akiyoko blog

akiyoko の IT技術系ブログです

まだ Moodle で消耗してるの? オープンソースの Python製 LMS「RELATE」が圧倒的にカスタマイズしやくてヤバイぞ!

この投稿は 「Django Advent Calendar 2017 - Qiita」 の 19日目の記事です。


こんにちは、akiyoko です。

「Django Advent Calendar」は 2年連続 4度目の参加になります。昨年は最後まで枠が空いていたので、調子に乗って3日分も担当してしまいました。 *1, *2, *3


あと、2年前に Python製 CMS「Mezzanine」を紹介したときの流れで、煽りタイトルを付けてしまいました。重ね重ね申し訳ございません。

《過去記事》
akiyoko.hatenablog.jp



 

はじめに

オープンソースの LMS(学習管理システム)と言えば、

などがまず真っ先に挙げられますが、今回紹介するのは、Python 製で Webフレームワークの代表格「Django」をベースに開発されたオープンソースの LMS、その名も「RELATE」です。 *4


例えば、Pythonista なあなたが LMS を開発することになったとしましょう。
良さげな候補が Moodle しか見つからず、「仕方ない、Moodle をカスタマイズするか。はぁ、PHP か・・」というのは精神衛生上よろしくないですよね?(すいません、個人の意見です。)

そんなとき、Moodle じゃない Python製の LMS があればワクワクしてきませんか? ・・しませんか、そうですか。


あとよく聞くのは、Moodle は要らない機能が多すぎるという問題。ちょっとしたテキストと動画、小テスト(クイズ)が受講できる講座をオンラインで実施したいだけなら、もっとシンプルなものが求められるケースもありますよね。


しかも、Moodle は GPLライセンス のため、Moodle をカスタマイズしてオンライン学習サービスをリリースした場合にはソースコードの公開が求められることになります。

Moodleはコピー・利用・修正してかまいませんが,条件として,ソースコードを公開し,元のライセンスや著作権表示を修正したり削除したりせず,同じライセンスをMoodleから派生したソフトにも与えなければなりません。


Moodleとは - MoodleDocs


そのため、BtoB 向けに Moodle をカスタマイズして提供するというのはライセンス上どうしても困難な面があるかと思います。その点、RELATE は MITライセンス なのでソースコードの公開義務はありません。機能追加し放題、思う存分カスタマイズすることができます。



 

RELATE の特徴

まず、RELATE には、

  • Python 製、Django ベース
  • コースコンテンツを Markdown 形式で記述(プログラマ向け!)
  • コースコンテンツは1講座ごとに Git 管理(管理画面でバージョンの切り替えも可能)
  • VideoJS による動画埋め込みを標準サポート
  • 日本語にも翻訳可能 *5

といった特徴があります。中でも、コースコンテンツを Markdown で書くという特徴はオンリーワンじゃないでしょうか(私の知る限りで)。


画面はトップ画面、テキスト(動画)画面、クイズ画面、成績画面、管理側画面などで構成され、LMS としてひと通りの機能が揃っています。機能はさほど多くないですが、実用的でしっかりと作り込まれており、Moodle や Canvas の2000オーバーには及びませんが、GitHub スターは現時点で120ほど付いています。また、Python 3、Django 1.11 にも対応しています。


ところで Django 1.11 なら、この「Two Scoops of Django」シリーズの最新版が絶対オススメです。英語ですが(と言っても難しい感じの本ではないです)、現場で役立つこと間違いなしのナンバーワン Django本です。


GitHub の履歴を覗いてみると、2014年5月から inducer がコツコツとプロトタイプを作り始め、dzhuang が途中で加わり、現在は主に二人で開発を続けていますが、最近も頻繁にコミットがされています(今日も何件かコミットされていました)。

inducler(Andreas Klöckner)はプロフィールを公開していて、ドイツ出身で現在はイリノイ州立大学のコンピュータサイエンスの助教授をしているとのこと。自身(?)の オンラインクラス にこの RELATE を使っているようです。なので、ちゃんと Python や Django のバージョンアップに追随しているのですね。

全部を一個人が作ったのではなく(一応)複数人が開発していて、Issue や PR をオープンに受け入れているのでサポートもある程度期待できそうです。何よりも、ベースが Django なのでコードが理解しやすくカスタマイズしやすいのが嬉しいところです。


これで SPA だったら最高なのになぁ、と思ったあなた。・・そんなあなたのために、「Web Expedition」(webexp)という「Django + Angular」なイケてる LMS を見つけておきました(*6)。一応オープンソースなのですが開発者が最新版のソースコードを push してないのか、昔触ったときにうまく動かなかった記憶がありますのでご注意を。





 

Ubuntu 16.04 on Docker for Mac で構築してみる

Ubuntu 16.04 on Docker for Mac 上に RELATE のサイトを構築してみます。
もちろん、以下の構築手順は本番向けではありませんのでくれぐれもご注意を。

環境

$ sw_vers
ProductName:	Mac OS X
ProductVersion:	10.12.6
BuildVersion:	16G1114

$ docker --version
Docker version 17.09.1-ce, build 19e2cf6


 

Docker コンテナを起動

$ docker run -it -p 80:8000 --name relate ubuntu:16.04

# cat /etc/issue
Ubuntu 16.04.3 LTS \n \l

# apt-get update
# apt-get install -y python3-dev python3-pip
# pip3 install -U pip
# apt-get install -y vim git curl

# python3 -V
Python 3.5.2
# pip3 -V
pip 9.0.1 from /usr/local/lib/python3.5/dist-packages (python 3.5)

### Bower をインストール
# apt-get install -y nodejs npm
# nodejs -v
v4.2.6
# npm -v
3.5.2
# npm install -g bower



以降は、Installation — RELATE 2015.1 documentation を参考にして RELATE のインストールを進めていきます。

なお、検証時の RELATE のバージョンは、66d3d38 です(2017/12/19 時点の最新版)。

# cd /opt/
# git clone https://github.com/inducer/relate.git

### 事前にコースコンテンツも配置しておく
# git clone https://github.com/inducer/relate-sample.git
# cd relate
# pip3 install -r requirements.txt

ここで、

Command "python setup.py egg_info" failed with error code 1 in /tmp/pip-build-uh2f9ekj/django-select2/

というエラーが出る場合がありますが、「django-select2」6.0.0 のバグの可能性があります。

diff --git a/requirements.txt b/requirements.txt
index 3a5dbd3..e39372f 100644
--- a/requirements.txt
+++ b/requirements.txt
@@ -94,7 +94,7 @@ git+https://github.com/celery/django-celery.git@6232c79557517afa74967fcb980c0db2
 # }}}

 # For searchable select widgets
-django_select2>=5.5.0
+django_select2<6

 # To sanitize HTML generated by user code
 bleach>=2.0,<3

と修正して

# pip3 install -r requirements.txt

をやり直せば、うまくインストールできました。

# cp local_settings.example.py local_settings.py
# vi local_settings.py

で、

ALLOWED_HOSTS = ["*"]

に変更。

# python3 manage.py migrate
# python3 manage.py createsuperuser
### (admin/admin@example.com/pass)

# python3 manage.py bower_install --allow-root

ここで、Ubuntu 16 は "node" ではなくて "nodejs" として認識するため、ここで以下のようなエラーが出てしまう場合があります。

/usr/bin/env: 'node': No such file or directory

この場合は、以下のコマンドを実行すれば OK です。

# ln -s /usr/bin/nodejs /usr/bin/node

改めて、

# python3 manage.py bower_install --allow-root

を実行。

最後に、runserver を起動します。

# python3 manage.py runserver 0.0.0.0:8000

ブラウザで、
http://localhost/login/
にアクセスします。

f:id:akiyoko:20171219230405p:plain


 

コースコンテンツの登録

「Sign in」のリンクを辿り、superuser でログインします。

f:id:akiyoko:20171219230421p:plain

ログインできたら、「Set up new course」ボタンをクリックします。

f:id:akiyoko:20171219230508p:plain


以下のようにサンプル講座の設定をおこない、「Validate and create」ボタンを押下。

Course identifier: t-001
Course name: Test Course
Number: T001
Time period: March 2018
Start date:
End date:
Only visible to course staff: チェック
Listed on main page: チェック
Accepts enrollment: チェック
Git source: /opt/relate-sample
SSH private key: 
Course root in repository: 
Course file: course.yml(デフォルト)
Events file: events.yml(デフォルト)
Enrollment approval required: 
Enrollment required email suffix: 
From emai: admin@example.com
Notify email: admin@example.com

f:id:akiyoko:20171219230813p:plain:w300


サンプル講座のトップ画面が表示されます。

f:id:akiyoko:20171219233802p:plain


講座を受講してみる

本来は受講者を作成してログインし直すべきですが(成りすましモードもあります)、このまま進めていきます。

トップ画面から以下のリンクをクリックするか、「http://localhost/course/t-001/flow/001-linalg-recap/start/」にアクセスすると、テキストページのフローに進むことができます。

f:id:akiyoko:20171219233606p:plain

ここに動画やテキストを配置します。ページ移動は上部のナビゲーションから可能です。

f:id:akiyoko:20171219233129p:plain



次に、クイズ(小テスト)です。


トップ画面から、「sample quiz」というリンクをクリックするか、「http://localhost/course/t-001/flow/quiz-test/start/」にアクセスします。

f:id:akiyoko:20171219233629p:plain

クイズが横に並んでいます。

f:id:akiyoko:20171219231934p:plain

いろんな形式のクイズを出すことができます。

f:id:akiyoko:20171219232041p:plain

クイズの形式はこの他にも多数用意されています。

f:id:akiyoko:20171219232011p:plain

クイズを提出する場合は、右側のボタンをクリック。

f:id:akiyoko:20171219232146p:plain

確認画面が表示されます。

f:id:akiyoko:20171219232604p:plain

結果画面も用意されています。

f:id:akiyoko:20171219232639p:plain

完了したクイズは、後で振り返りをすることもできます。

f:id:akiyoko:20171219232748p:plain


管理者側の画面で成績の一覧をチェックすることも可能です。

f:id:akiyoko:20171219232906p:plain



 

まとめ

2年前に Python製で Django ベースの CMS「Mezzanine」を紹介しましたが、今回は同じく Python 製で Django ベースの LMS「RELATE」を紹介してみました。


Django ベースで開発されているため、Django に慣れている Pythonista であれば容易にカスタマイズができますし、既存の様々なライブラリを利用することができるため、思うがままの LMS を創り上げることができます。

これを機にオリジナルのオンライン学習サービスをリリースしてみてはいかがでしょうか。



明日は、kzkamago0721 さんの「Django Advent Calendar 2017 - Qiita」 20日目の記事です。よろしくお願いします。

*1:昨年は最後まで枠が空いていたので、調子に乗って3日分も担当してしまいました。《過去記事》akiyoko.hatenablog.jp

*2:《過去記事》akiyoko.hatenablog.jp

*3:《過去記事》akiyoko.hatenablog.jp

*4:検索に引っかかりにくい名前つけやがって、こんちくしょう!!

*5:ただし、コースコンテンツの翻訳は難しいかも。

*6:Quiz Web App with Django + Angular and deployment on pythonanywhere | Bhargav Patel

ビットコイン・仮想通貨・ブロックチェーンの本を合計10冊読んだのでオススメ本を紹介

この投稿は 「暗号通貨 Advent Calendar 2017 - Qiita」 の 18日目の記事です。

こんにちは、akiyoko です。

 

はじめに

ビットコインが 100万円を突破した 11月後半あたりから「ビットコイン」「仮想通貨」「ブロックチェーン」などのキーワードがものすごい勢いで急激にトレンドを上げています。


f:id:akiyoko:20171218015754p:plain
(2017/12/18時点。今現在のトレンドはまとめの下に掲載)


それに合わせて関連本の出版も急増していて、Amazon でも「ビットコイン」「仮想通貨」「ブロックチェーン」等で検索すると、合わせて 400冊以上も本が見つかる状況となっていて、こちらもちょっとしたお祭り状態になっています。

ビットコインをはじめとする仮想通貨やブロックチェーンの情報ならインターネットにいろいろと転がっているとは思いますが、ある程度整理された知識をまとめて押さえるのには本が一番と考えている人も多く、私も(もちろんインターネットの情報もチェックしますが)体系的な知識を入れるために本から入ることも少なくありません。


今年は仮想通貨やブロックチェーン関連の本を合計10冊ほど読んだのですが、今回はその中から(特に技術者目線で)有用だと感じた度合いを「オススメ度」という形で示しながら紹介していきたいと思います。また、技術者ではない人にも読めるかどうか判断できるように「難易度」の目安(★ が多いほど難しい)も付けてみました。ぜひ参考にしてください。



先に結論を書くと、技術者であれば、①〜③のいずれか一冊かインターネットの情報でざっと概要を頭に入れた後、「⑥ いちばんやさしいブロックチェーンの教本」で周辺の情報も含めて技術的なところを押さえておけばまずは大丈夫です。

技術者でなければ、「③ いまさら聞けない ビットコインとブロックチェーン」が分かりやすくてイチ推しです。

プラスアルファとして何か読むのであれば、読み物としての「④ デジタル・ゴールド」が非常に面白いです。将来の金融業界にブロックチェーンがどんな衝撃を与えるか興味がある方は「⑧ アフター・ビットコイン」は必読です。


さあ、行ってみましょう!


 

ビットコイン関連

ビットコインに特化した本。まずはここから入る人も多いと思います。私もそうでした。

① ビットコイン解説本

オススメ度:★☆☆☆☆
難易度:★☆☆☆☆


「ビットコインって何?」という状態から最初に読んだ本。

ビットコインは「お金」なのか?という疑問に、ポイントサービス(Tポイント・楽天ポイント 等)や電子マネー(楽天Edy・Suica 等)、クレジットカードとの比較をしながらその特徴を説明していきます。お金の歴史やビットコイン誕生の歴史についても少し触れられており、ビットコインの概要を知るための本と言えます。気軽に読めるページ量(75ページ程度)なので、てっとり早く概要を知りたいという人や最初に読む本としてはいい と思います。逆に、技術的に詳しく知りたいという人には全然物足りないでしょう。

2014年発刊ということで少し古臭さは否めませんが、概要を知るというだけなら特に問題ないと思います。


 

② ビットコインはどのようにして動いているのか? ビザンチン将軍問題、ハッシュ関数、ブロックチェーン、PoWプロトコル

オススメ度:★☆☆☆☆
難易度:★★☆☆☆

11月の SegWit2x ハードフォーク回避 を見事予言的中したフルタイムビットコイナー、大石 哲之さんの本。

私の予想では、マイナーが経済的に合理的あれば、決してSegwit2xのフォークを行わないと考えている。マイナーは、価値の低い2xコインを採掘せず、1xコインを採掘し続けるだろう。その結果、11/16日には、実際は何もおこらないだろう。


http://doublehash.me/segwit2x-fork/」より


ビットコインの核心(そして革新)部分である「ビザンチン将軍問題」にフォーカスを当てた仕組み解説本 ですが、何か事情があって急いで出したのでしょうか、内容に物足りなさを感じます(実際 66ページと薄い)。技術的な内容は少しだけしか触れられていません。というか、ほぼビザンチン将軍問題の説明だけに終始しています。しかしながら、説明や比喩が多少回りくどく感じられ、余計にモヤモヤするかもしれません(あくまで私の感想ですが)。

全般的に図が一切無いからでしょうか、内容がスッキリと頭に入ってこない印象です。出版された2014年当時としては数少ない日本語の情報だったかもしれませんが、今となってはインターネットに転がっているレベルと言えば言い過ぎでしょうか。


 

③ いまさら聞けない ビットコインとブロックチェーン

オススメ度:★★★★☆
難易度:★★☆☆☆


国内大手の仮想通貨取引所 coincheck の COO 大塚 雄介 氏の著書。 *1

現金やクレジットカードとの違いやビットコインのメリットなどの初歩の初歩から始まり、ビットコインの簡単な仕組みやセキュリティに至るまで、なるべく誰でも理解できるように技術的な説明が必要な部分をうまく掻い潜りながら工夫して説明されているのがよく分かります。仮想通貨ビギナーでも何の問題もなく読み進められると思います。その割に、SegWit(セグウィット)やクラウドマイニングなどについても説明があり、周辺知識もしっかり押さえられています。

また、国内最多のアルトコインを販売している coincheck に所属しているということもあってか、ビットコインだけでなく、Ethereum(イーサリアム)や Augur(オーガー) などのいくつかのアルトコインについての説明もされています。ということで、技術的なことは苦手だけどビットコイン周辺のいろいろな情報を押さえたいという人にはピッタリ の内容でしょう。


文春オンラインの記事「ビットコインの仕組みを文系の人にわかりやすく伝えるには? | 文春オンライン」で

「類書は多いですが、文系の人でも簡単に、大づかみにこの分野を理解できるのはこの本だけと思います」(担当編集者の千葉正幸さん)

と書かれている通り、技術的な話は一切出てこないので、「文系なのでちょっと・・」という方にもバッチリ理解できるような本になっていると思います。



ビットコイン取引高日本一の仮想通貨取引所 coincheck bitcoin
ビットコイン取引高日本一の仮想通貨取引所 coincheck bitcoin



 

④ デジタル・ゴールド ── ビットコイン、その知られざる物語

オススメ度:★★★★★
難易度:★★☆☆☆


2009年のビットコイン誕生から2014年までの黎明期の歴史を、ビットコインに熱狂した人たちの物語を中心に、実際にあった出来事をベースに仔細に描いた人間ドラマ。 仮想通貨の「王様」とまで呼ばれるまでになった今とは全く違う、ビットコインの若かりし頃の裏の顔を垣間見ることができます。これが事実だとすると(著者はニューヨーク・タイムズ紙の記者で緻密な取材をおこなったとのことなので事実無根なことは書いていないと思いますが)、ビットコインが現在このように多くの人を魅了するほどに大きくなっているのはまさに奇跡だと感じてしまいます(それこそがビットコインの持つ「力」が本物だと証明していると考えることもできますね)。いずれにせよ読み物として最高の面白さです。

サトシ・ナカモトの人物像(私の想像と全く違いました)、違法サイト「シルクロード」で人気を維持していたダークサイドな時期、2014年2月の「Mt.GOX」事件の詳細など、私のような新参者が知らない歴史がこの一冊に詰まっています。「Mt.GOX」がアレの頭文字だったとか知ったときはショックで唖然としました(笑)。

技術的な要素は「補足」として巻末に書かれていますが、何も知らなくても全く問題なく読み進められます。しかしながら技術的な内容が少しでも分かっていれば、この物語をより一層楽しめるでしょう。

若干気になったのは、最後のあっけない終わり方。紆余曲折ありながらも物語はまだまだ続いているのになと思ったのですが、数年後に続編が出るのを期待しましょう。


 

⑤ ビットコインとブロックチェーン : 暗号通貨を支える技術

オススメ度:★★★★★
難易度:★★★★★


原題は「Mastering Bitcoin」。世界的にも有名な一冊で、もはやビットコイン技術者のバイブルとも言われている本です。あるいは、卒業証書と言っていいかもしれません。これが読めたら、ビットコインの仕組みはひと通りは理解できているという証になるでしょう。完全に技術者向け。 読む前にある程度の知識は入れておいたほうが良いと思います。何の知識もなくこの本を最初に読むと、十中八九挫折します。他の本で曖昧に説明されていたことが事細かに書かれていて、(細かい部分までは理解できなくても)「なるほどこういう仕組みで作られているのか」とスッキリできるようになります。

後半に、初期の頃のアルトコインの情報もあり、こちらもなかなか有益な内容になっています。


 

ブロックチェーン関連

こちらは、取り扱うテーマをビットコインだけに絞らず、幅広くブロックチェーンまでを解説した本です。

⑥ いちばんやさしいブロックチェーンの教本 ― 人気講師が教えるビットコインを支える仕組み

オススメ度:★★★★★
難易度:★★★☆☆


タイトルに「いちばんやさしい」とありますが、詳しめな技術要素の説明もあって、対象読者は明らかに「技術者」です。ビットコインやブロックチェーンの概要をある程度知っていて、もう少し深掘りして勉強したい技術者にはピッタリです。 全体的によくまとまっていて、個人的には一番のオススメ本です。

技術的な部分をなるべく詳しく説明しながら、且つ分かりやすく説明されています。他の本では解説していない細かな部分もちゃんと説明をしているなという印象で、これ一冊でほとんどの基礎的な要素をしっかりと網羅することができると思います。ブロックチェーン以外にも、ウォレットやスマートコントラクト、などの周辺情報も幅広く説明しており、まさにこれ一冊で OK というイメージです。

先に述べた通り難易度が少し高いのですが(そういうものなんだと読み流すことはできますが)、ITパスポートレベルの基礎知識があれば何とか理解はできるのではないかと思います。


 

⑦ ブロックチェーン・レボリューション ―― ビットコインを支える技術はどのようにビジネスと経済、そして世界を変えるのか

オススメ度:★★★☆☆
難易度:★☆☆☆☆


ブロックチェーンという技術がビジネス、経済、世界をどのように変えるのかといった「ブロックチェーン革命」について書かれた本です。従来の「情報のインターネット」に対して、ブロックチェーンは「価値とお金のインターネット」と言われる所以について、ブロックチェーン革命の要となる7つのポイントについて、「信頼」「非中央集権」「インセンティブの設計」「不正ができない」「個人情報のブラックボックス化」「スマートコントラクト」「格差を解消するデザイン」という点が挙げられると言います。ハッとしたのは、「これからは、いいことをすると得をして、悪いことをすると損になるようなインターネットが実現する」という点。私がブロックチェーンを画期的だと思うのは、利用者が利己的な行動をしてもそれがシステム全体としての利益に繋がるという設計の妙なのですが、そのあたりの話が技術的な説明一切無しに書かれているのは面白いところです。インターネットは世の中を良くしたと言われますが、格差を広げただけという指摘もあります。そんな中、インターネットがスポットライトを当てなかった人たちにもブロックチェーンが光を照らす。そんな新しい未来がブロックチェーンによって来るかもしれない。夢と希望と可能性を感じられる、面白い本ではないでしょうか。

ただし、少し分厚いのが唯一の難点でしょうか。


中村 伊知哉氏のブログでも書評がありますね。
ブロックチェーンは革命なのか? ~ Ichiya Nakamura / 中村伊知哉


 

⑧ アフター・ビットコイン : 仮想通貨とブロックチェーンの次なる覇者

オススメ度:★★★★☆
難易度:★★☆☆☆


ビットコイン(いわゆる「ブロックチェーン 1.0」)はバブル、オワコン。これからは、金融の世界を根本的に変革するポテンシャルを秘めている「ブロックチェーン 2.0」(決済・送金、証券決済など)、「ブロックチェーン 3.0」(登記、資産管理、投票など)に利用されるであろう「分散型台帳技術」の時代だよ、という内容の本です。
話の流れ上、どうしてもビットコインはバブルにしてしまいたい駆け足気味の前半部分には少し違和感を覚えましたが、後半の金融分野への深い造詣はさすが日本銀行で「電子現金プロジェクト」に携わり、決済機構局でデジタル通貨を研究、国際決済銀行(BIS)でグローバルな活躍をしてきた経歴を持つ著者の得意分野、まさに独壇場という感じの内容でした。

パブリックなチェーンであるビットコインと比較して、金融界で導入されるであろうプライベートチェーンの利点、ネックとなる承認速度やファイナリティの問題、個人的に一番の謎だった「プライベートチェーンをマイニングするインセンティブって?」という(ビットコインの仕組みをベースに考えると理解しにくい)モヤモヤや疑問が解消します。また、Linux Foundation が推進する「HyperLedger Fabric(ハイパーレッジャー・ファブリック)」、R3 コンソーシアムの「Corda(コルダ)」、Ripple の「ILP(インターレッジャー・プロトコル)」などのプライベートチェーンについての解説や、中央銀行が狙う当座預金のデジタル化(決済コイン型デジタル通貨)、証券決済などの話題が盛り沢山で、ビットコインブームを脇においてこれだけしっかりとブロックチェーンの金融分野への展開を論じている本は少ないのではないかと思います。

⑦がぼやっとしたブロックチェーンがもたらす夢の未来を書いているとすれば、こちらは具体的な近未来像を描いています。プライベートチェーンについての多彩な情報は他の本には無いオンリーワンな内容かと思います。金融業界に今後何が起こるかを知りたい人、ビットコインじゃないブロックチェーンの可能性について詳しく知りたいという人にはピッタリ な内容です。


著者の中島氏はこんな人です。
「ビットコイン」の終わりから「ブロックチェーン」の時代へ:中島真志 | 記事 | 新潮社 Foresight(フォーサイト) | 会員制国際情報サイト

ビットコイン界隈で有名な DEG さんの書評も見つけました。
【迫るラストデイ】アフター・ビットコインを読みました | ARUTOKO(あるとこ)


 

Ethereum ・スマートコントラクト関連


Ethereum の本は何冊か出ていますが、まずは一冊だけ読んでみました。

⑨ スマートコントラクト本格入門 ― FinTechとブロックチェーンが作り出す近未来がわかる

オススメ度:★★★★☆
難易度:★★★★☆


数少ないスマートコントラクトの実践入門書。

序盤は FinTech やブロックチェーンの超概要、中盤はスマートコントラクトについて書かれています。中でも、ブロックチェーンやスマートコントラクトに関わる法律・規制の話は他の本にはなかなか無いので貴重です。後半はガラッと変わって開発者向けの話になり、SolidityTruffleGeth を使った Ethererum ベースのスマートコントラクト開発の具体的な手順について述べられており、実際に手を動かしてみようといった感じになっています。ということで、Ethererum を使ったスマートコントラクトの開発をしてみたい人には入門書として非常に有益 な内容になっていると思います。


Ethereumはどのように動いているのか - The Coffee Times」と合わせて読むとよいかと思います。なお、ERC20トークン については書かれていませんので悪しからず。


 

アルトコイン関連

意外にと言うか、アルトコイン(ビットコイン以外の仮想通貨)についての本はあまり見当たりません。成長のスピードが早過ぎて情報がすぐに陳腐化してしまうからでしょうか。今のところ次の一冊くらいしかないのですが、読んでみました。

 

⑩ 一冊でまるわかり 暗号通貨 2016〜2017

オススメ度:★★☆☆☆
難易度:★☆☆☆☆


タイトルから適当に書いたかと思いきや(笑)、意外としっかり調べている印象です。しかしながら、取り上げているアルトコインの種類が少なくて中途半端な印象も。実際、役に立ったかと言えば微妙でコスパは多少悪いかなと感じました。続編(あるのかな?)に期待です。

ある程度まとまったコインの情報が日本語で書かれたものが他に無いため、今改めて見返すと有用な部分も多いです。Twitter やブログでの特定のアルトコイン推しのポジトークに辟易していて、第三者視点からの情報が欲しいという人にはマッチする かもしれません。

ちなみにこの本に取り上げられているアルトコインは以下の24種類です。

 

まとめ

今年、「ビットコイン」「仮想通貨」「ブロックチェーン」関連の本を合計10冊読んだので、「難易度」と「オススメ度」を付けてそれらを一冊ずつ紹介してみました。

ただし、★ の数はあくまで個人の感想ですのでご注意ください。書籍をご購入の際は、ご自身の目的に合ったものを用法用量を守って正しくお選びください。




明日は、ohac さんの「暗号通貨 Advent Calendar 2017 - Qiita」 19日目の記事です。よろしくお願いします。



 

おまけ

本はもう何冊か読んでいたのですが、10冊の枠から外れたものをおまけで紹介。

⑪ 1時間でわかるビットコイン投資入門

オススメ度:★☆☆☆☆
難易度:★☆☆☆☆


薄くて(144ページ程度)対話形式でテンポよく読めるなので、数時間で読み切ることができます。内容はだいぶ薄め。

ポートフォリオ、指値注文と成行注文、時間分散(ドルコスト平均法)、アービトラージ、証拠金取引など、仮想通貨「投資」についてのまさに基本が書かれている本。知っておいて損はないとは思いますが、まあ皆さん大体知ってますよね、といった内容。

この本は 5月に出版(寄稿は4月)された比較的新しめの本なのですが、

私は2018年末までに1BTC=30万円近辺もあり得るとみているため

などと書かれているあたり(実際には 2017年5月25日に 30万円達成 *25)、ビットコイン・仮想通貨の流れは早いな(早過ぎて怖いな)と感じてしまいます。


 

参考

現在の「ビットコイン」「仮想通貨」「暗号通貨」「ブロックチェーン」のトレンドです。


たった5分でデモが動かせる! Hyperledger Sawtooth(ハイパーレッジャー・ソウトゥース)でブロックチェーンを手軽に体験してみよう

この投稿は 「ブロックチェーン Advent Calendar 2017 - Qiita」 の 17日目の記事です。

こんにちは akiyoko です。

はじめに

仮想通貨やブロックチェーンの昨今の盛り上がりにより、ブロックチェーンの情報が本やインターネットで簡単に手に入るようになってきました。


そろそろ、
「ブロックチェーンの理論は大体分かった。次のステップとして、

面倒な設定なしに、5分ほどで簡単にデモが動かせる、そんなお手軽なブロックチェーンがあればいいのになぁ。。

と考えている技術者の方が増えてきているのではないでしょうか。

f:id:akiyoko:20171217035811p:plain:w300


ハイ、あるんです!

今回は、たった5分で簡単にデモが動かせる分散型台帳フレームワーク、その名も「Hyperledger Sawtooth」を紹介したいと思います。


ちなみに「Sawtooth」は「ノコギリ」ですが、何故このネーミングになったのかについては調べてもよく分かりませんでした。 *1

f:id:akiyoko:20171217202359p:plain:w200


 

Hyperledger Sawtooth とは

Hyperledger(ハイパーレッジャー)とは

Hyperledger は Linux Foundation が 2015年12月に発足したプロジェクトで、様々なビジネス領域で実際に使えるエンタープライズ向けのブロックチェーン技術の標準化を目指しており、現在 180を超える企業(*2)が協力して分散型台帳フレームワークのオープンソース開発や実証実験、コミュニティの構築や教育によるエコシステムの拡大に取り組んでいます。

Hyperledger is an open source collaborative effort created to advance cross-industry blockchain technologies. It is a global collaboration, hosted by The Linux Foundation, including leaders in finance, banking, Internet of Things, supply chains, manufacturing and Technology.


About – Hyperledger

Hyperledger incubates and promotes a range of business blockchain technologies, including distributed ledger frameworks, smart contract engines, client libraries, graphical interfaces, utility libraries and sample applications.


Blockchain Technology Projects – Hyperledger


Hyperledger のフレームワークと言えば何よりもまず、IBM が初期の開発をリードし現在では大手IT企業が多数参加している「Hyperledger Fabric」がその代名詞として挙げられることが多いですが(*3)、他にも

といったプロダクトがオープンソースとしてプロジェクトにホストされており(*5)、特徴や採用している技術、ユースケースがそれぞれ異なります。


Hyperledger のフレームワーク全体に共通したゴールとしては、スループットやファイナリティなどの問題を解決し、エンタープライズ用途に耐えうるレベルのプロダクトを提供しようとしていることが挙げられます。またビジネスで利用するためには、クローズドで開発されたプロダクトよりもオープンソースで開発されているプロダクトの方が評価しやすく、情報の透明性もあり、コミュニティが充実しているプロダクトだと採用されやすいというケースもあります。この Hyperledger プロジェクトにより、分散型台帳やブロックチェーン技術が実ビジネス領域に広く浸透していくことが期待されています。



 

Hyperledger Sawtooth(ソウトゥース)とは

Hyperledger Sawtooth は、オープンソースの分散型台帳(DLT)であり、スマートコントラクトエンジン(Smart Contract Engine)です。米 Intel 社が開発していたものが、2016年5月に Hyperledger プロジェクトにオープンソースとして提供されました。


Hyperledger Fabric と同様に、モジュラー型アーキテクチャ(Modular Architecture)を念頭に設計されており、コンポーネントがそれぞれ部品化されていてプラガブル(置き換え可能)になっているのが特徴です。

面白いのがコンセンサスアルゴリズムさえもプラガブルになっている点で、今のところ、Sawtooth 独自の「PoET(Proof of Elapsed Time)」と開発・検証用の「Dev Mode」が用意されています。

PoET は、Enclave(trusted function *6)によって決められた待ち時間が一番短いノードがリーダーになる、という抽選アルゴリズムです。PoW のようにハッシュキャッシュに対する計算コストを掛ける必要がなく、Intel社が言うには数千台のノードが参加してもスケールするとのことです。ただし PoET は、Intel製 SGXチップ搭載ノードによる 「Trusted Execution Environment(TEE)」をベースにすることで安全にランダムなリーダーを選出する仕組みを取っているため、

独自のコンセンサスアルゴリズムPoETを持つが、これは本来intelが提供するハードウェアを利用して行われるため完全版ではなく、オープンソース版ではシミュレータが用意されている。


さまざまなブロックチェーン技術

といった制限もあるようです。


なお、公式ドキュメント によると、パブリックな Validator(ノード)ネットワークを構成することもできるが、チェーン内通貨などのインセンティブの設計が必要でそれは Sawtooth のスコープ範囲外とのこと。なので実質、コンソーシアム型かプライベート型のどちらかで利用されることが多いと思われます。



GitHub を見ると、現時点でソースコード全体の7割ほどが Python で書かれています(*7)。モデルに相当する「Transaction Family」やスマートコントラクトに相当する「Transaction Processor」を開発者が任意に実装することができ、SDK も用意されています。SDK は Python の他、C++, Go, Java, Javascript など複数の言語で開発ができるようにパッケージが個別に提供されています。




 

全体像

だらだらと解説をしてきましたが、文章だけでは全体像がよく分からないと思いますので、私の理解した範囲で Hyperledger Sawtooth の利用イメージの全体図を描いてみました。今回動かす「intkey」と呼ばれる “out of the box” なサンプルデモを Docker 上で動かす場合の構成図を示しています。公式ドキュメント の図をもう少し詳しくした感じのイメージです。


f:id:akiyoko:20171216193555p:plain



Hyperledger's Sawtooth Lake Bets on Modular Blockchains and Elapsed-Time Consensus | Altoros」の図はかなり細かい部分まで書かれていてすごく良いのですが、説明が少なくてここから正確に理解するはなかなか難しいと思います。


登場人物

用語の定義は ここ に書かれています。

 

Transaction Family

モデルに相当する構造体です。State を変更するためのフィールドや Transaction Processor を呼び出す際のアクションなどを任意に定義できます。上の図には描いていませんが、Client で Transaction を作成する際に利用しています。

A transaction family is a set containing: a transaction payload format, a model for storing information in global state, and a procedure for validating a transaction and updating state based on the transaction payload.


参考:IntkeyMessageFactory クラス

 

Transaction

State を更新するための情報、ヘッダ、署名を含んだデータで、「intkey」デモでは、「キーに対応する数値を登録する」「登録済みのキーに対応する数値を増やす」「登録済みのキーに対応する数値を減らす」といった一つ一つの処理に対応するトランザクションを表します。

A transaction is a protobuf object containing a payload, header, and signature. The signature is generated by the transaction signer by signing the transaction header with the transaction signer’s private key.

 

Batch

Transaction を複数含んでおり、ある程度まとまった処理を表現できます。Transaction に依存関係がある場合などにうまく活用できそうです。Batch はシステムが扱う最小単位で、最終的に全ての変更が反映されるか全く反映されないかのいずれかになります。

a batch is the atomic unit of change in the system. If a batch has been applied, all transactions will have been applied in the order contained within the batch. If a batch has not been applied (maybe because one of the transactions is invalid), then none of the transactions will be applied.


https://sawtooth.hyperledger.org/docs/core/releases/latest/architecture/transactions_and_batches.html#why-batches

 
ということで、ブロックチェーン上のブロックとバッチ(Batch)とトランザクション(Transaction)の関係は以下の図のようになります。つまり、ブロックの中に複数のバッチが含まれ、バッチの中に複数のトランザクションが含まれることになります。

f:id:akiyoko:20171217234733p:plain:w400

 

State

ブロックチェーンとは別に管理されるグローバルな状態を表します。Ethereum で言うところの「world state」に相当します。

Radix Merkle Tree 形式で管理されており、Transaction 実行後のそれぞれの状態がネームスペース付きの70桁のアドレスを割り当てられて保管されています。なお、Radix アドレスの先頭6桁は Transaction Family 固有のネームスペースを表す領域になっています。 *8

 

Validator

Hyperledger Sawtooth の中心的な役割を担います。トランザクションのバッチを処理して、ブロックを作成するまでのサイクルを実行します。ビットコインのブロックチェーンで言うところの「フルノード」が近いかもしれません。

非常に紛らわしいのですが、下にも書かれている通り「Validator」がデータのチェックをおこなっているわけではなく、実際にはトランザクションやバッチのデータ検証は「Transaction Processor」などに移譲していることが多いようです(「intkey」でもそのような作りになっています)。

A validator is the component ultimately responsible for validating batches of transactions, combining them into blocks, maintaining consensus with the network, and coordinating communication between clients, other validators, and transaction processors. Much of the actual validation is delegated to other components, such as transaction processors and the active consensus module.

 

Transaction Executor

しかるべきタイミングで Transaction Processor と呼ばれるプログラム(Ethereum で言うところのスマートコントラクトか)にトランザクションのデータを渡す役割を担っています。

The Executor is responsible for the execution of transactions by sending them to transaction processors. The overall flow for each transaction is:

  • The Executor obtains the next transaction and initial context from the scheduler
  • The Executor obtains a new context for the transaction from the Context Manager by providing the initial context (contexts are chained together)
  • The Executor sends the transaction and a context reference to the transaction processor
  • The transaction processor updates the context’s state via context manager calls
  • The transaction processor notifies the Executor that the transaction is complete
  • The Executor updates the scheduler with the transaction’s result with the updated context


https://sawtooth.hyperledger.org/docs/core/releases/latest/architecture/scheduling.html

 

Transaction Processor

トランザクションを検証し、処理をおこなってグローバルな State を書き換えることができます。開発者が事前に任意のプログラムを書くことができます。

A transaction processor validates transactions and updates state based on the rules defined by a given transaction family.

いわゆるスマートコントラクトです。

An intkey transaction processor implemented as a smart contract

TransactionHandler は Transaction Processor の一つで、よりビジネスロジック(アプリケーション)寄りとのこと。

参考:IntkeyTransactionHandler


 

デモを動かしてみよう

さて、いよいよデモを動かすときが来ました。(ここまで長かった。。)

今回動かすのは、Sawtooth のサンプルで一番簡単な「intkey」というデモになります。クライアントから REST API を通して数字を登録したり増減させたりすることができるシステムで、ある程度まとまった処理がブロックとしてチェーンに次々に繋がっていくのが体験できます。Docker イメージの中にすでに組み込まれているので、Docker コンテナを起動するだけでデモを実行できる環境が整います。


 
以降、macOS の Docker 上で Hyperledger Sawtooth の「intkey」デモを動かしていきます。


ちなみに私のローカル環境は以下の通りです。

$ sw_vers
ProductName:	Mac OS X
ProductVersion:	10.12.6
BuildVersion:	16G1114

$ docker --version
Docker version 17.09.1-ce, build 19e2cf6


 

0.Docker for Mac をインストール

こちらは事前に済ませておいてください。

ここは「5分」に加えちゃだめですよ。


 

1.Hyperledger の最新版 sawtooth-core をダウンロード

まず、Hyperledger の sawtooth-core の GitHub から、以下の手順で「sawtooth-core-1.0.0rc5.zip」をダウンロードします。なお現時点での最新版は「v1.0.0rc5」となっていました。

f:id:akiyoko:20171216234020p:plain
f:id:akiyoko:20171216234035p:plain


まだ 1分しか経っていませんよね?



 

2.コンテナを起動

zipファイルを解凍し、以下のコマンドを実行してコンテナを起動します。

$ docker-compose -f ~/Downloads/sawtooth-core-1.0.0rc5/docker/compose/sawtooth-default.yaml up

しばらくすると、各種コンテナが起動します。遅くても 2〜3分くらいで全て起動し終わるでしょうか。


「docker ps」コマンドを叩いて、コンテナのステータスを確認しましょう。

$ docker ps
CONTAINER ID        IMAGE                                       COMMAND                  CREATED              STATUS              PORTS                              NAMES
fbb42c0ae927        hyperledger/sawtooth-all:1.0                "bash -c 'sawtooth..."   About a minute ago   Up About a minute   4004/tcp, 8008/tcp                 sawtooth-shell-default
94c6768b9c5f        hyperledger/sawtooth-xo-tp-python:1.0       "xo-tp-python -vv ..."   About a minute ago   Up About a minute   4004/tcp                           sawtooth-xo-tp-python-default
e008347a256d        hyperledger/sawtooth-intkey-tp-python:1.0   "intkey-tp-python ..."   About a minute ago   Up About a minute   4004/tcp                           sawtooth-intkey-tp-python-default
7e194e70fda1        hyperledger/sawtooth-settings-tp:1.0        "settings-tp -vv -..."   About a minute ago   Up About a minute   4004/tcp                           sawtooth-settings-tp-default
f51e20d2ce48        hyperledger/sawtooth-rest-api:1.0           "sawtooth-rest-api..."   About a minute ago   Up About a minute   4004/tcp, 0.0.0.0:8008->8008/tcp   sawtooth-rest-api-default
b8e2627fe1cd        hyperledger/sawtooth-validator:1.0          "bash -c 'sawadm k..."   About a minute ago   Up About a minute   0.0.0.0:4004->4004/tcp             sawtooth-validator-default


起動に3分掛かったとして、今のところ計4分ですね。


 

3.クライアント上でコマンドを実行

次に、ターミナル上で

$ docker exec -it sawtooth-shell-default bash

と実行し、起動したクライアント(図の「Client」)のコンテナにログインします。



ハイ、準備は終了です。
4分30秒くらいでセッティングが完了したと思います。



以降は、sawtooth コマンドを利用して intkey の処理を実行していきます。なおその際、「Using Sawtooth with Docker — Sawtooth v1.0.5 documentation」を見ながら進めてもいいのですが、現時点でドキュメントが少し古くて(ドキュメントの対象バージョンが「v0.8.13」になっているため)、ポート番号が間違っている箇所があります。REST API の「8080」ポートは最新版では「8008」が正しいので、適宜「8008」に読み替えて進めてください。



 

genesis ブロックを確認
# sawtooth block list --url http://rest-api:8008
NUM  BLOCK_ID                                                                                                                          BATS  TXNS  SIGNER
0    d16b15f03ff35031f094f5dadf4211ee7bb41c4bb707f0e7d0e015b70b85b8164a326dec294ff02e2aefcf1aa6cdbe3be8eb70d5d63cf322a269feda12b78534  1     1     02850b3d81f14c7c1b9f2aee1274e2...

コンテナ起動直後にブロックを確認すると、genesis ブロックが 1つ作成されているのが確認できます。

ちなみに、以下のように実行すると、REST API が返す JSON を見ることができます。

# curl http://rest-api:8008/blocks


 

State を確認
# sawtooth state list --url http://rest-api:8008
ADDRESS                                                                 SIZE  DATA
000000a87cb5eafdcca6a8cde0fb0dec1400c5ab274474a6aa82c12840f169a04216b7  110   b'\nl\n&sawtooth.settings.vote.authorized_keys\x12B039f7586349ccf1490127db60acd6ac6c00cdebf5ea67ccc...
HEAD BLOCK: "d16b15f03ff35031f094f5dadf4211ee7bb41c4bb707f0e7d0e015b70b85b8164a326dec294ff02e2aefcf1aa6cdbe3be8eb70d5d63cf322a269feda12b78534"

初期状態のステータスを確認することができます。Radix Merkle Tree 形式で格納されています。

なお、「DATA」には dict オブジェクトを cbor でシリアライズした文字列が格納されていて、誰でも簡単に復元可能です。また「HEAD BLOCK」には、ブロックチェーンに書き込まれた最後のブロックの「BLOCK_ID」が表示されています。つまり、State にはブロックチェーンの最後のブロックが何であるかが保持されているということが分かります。


ちなみに、ターミナルの横幅の関係で「...」と切れてしまっているのを表示する場合は、「sawtooth state show」コマンドで詳細を見ることができます。

# sawtooth state show 000000a87cb5eafdcca6a8cde0fb0dec1400c5ab274474a6aa82c12840f169a04216b7 --url http://rest-api:8008
DATA: "b'\nl\n&sawtooth.settings.vote.authorized_keys\x12B039f7586349ccf1490127db60acd6ac6c00cdebf5ea67cccc6453a9f5b295c1777'"
HEAD: "d16b15f03ff35031f094f5dadf4211ee7bb41c4bb707f0e7d0e015b70b85b8164a326dec294ff02e2aefcf1aa6cdbe3be8eb70d5d63cf322a269feda12b78534"


 

バッチを作成
# intkey create_batch --key-count 3 --count 2
Writing to batches.intkey...

このコマンドは、複数のトランザクションを含むバッチをいくつか作成し、ローカルに「batches.intkey」というファイルとして書き出してくれます。この時点では、トランザクションやバッチはブロックチェーンには書き込まれません。ローカルファイルにデータを書き込むだけです。


このコマンドが具体的に何をやっているかと言うと、6桁のランダムな文字列を key_count 個分作成してそれぞれに対応するランダムなデフォルト値(9000〜100000)を設定し、作成したキーの値を 1〜10 のうちのランダムな値で足したり引いたりするトランザクションを作成しています。

前半部分では、ランダムな文字列とそのデフォルト値を新規作成する処理を 1トランザクションとし、key_count 個分のトランザクションをまとめて 1バッチとしています。後半部分では、値を増減させるトランザクションをランダム回数分繰り返したものを含んだバッチを、count 個数分作成しています。


例えば、key_count = 3, count = 2 の場合だと、

"transactions": [
    {"Verb": "set", "Name": "vJKChA", "Value": 9223},
    {"Verb": "set", "Name": "NcEktd", "Value": 9459},
    {"Verb": "set", "Name": "wVgqYd", "Value": 9011},
]

といったトランザクションを含むバッチを1個だけ新規作成し、次に、

"transactions": [
    {"Verb": "inc", "Name": "wVgqYd", "Value": 3},
    {"Verb": "dec", "Name": "vJKChA", "Value": 9},
    {"Verb": "inc", "Name": "NcEktd", "Value": 4},
]
"transactions": [
    {"Verb": "inc", "Name": "NcEktd", "Value": 2},
    {"Verb": "dec", "Name": "wVgqYd", "Value": 1},
    {"Verb": "inc", "Name": "NcEktd", "Value": 3},
    {"Verb": "dec", "Name": "vJKChA", "Value": 1},
    {"Verb": "inc", "Name": "wVgqYd", "Value": 6},
    {"Verb": "inc", "Name": "NcEktd", "Value": 4},
    {"Verb": "dec", "Name": "vJKChA", "Value": 1},
    {"Verb": "dec", "Name": "NcEktd", "Value": 9},
]

という値を更新するためのトランザクションをそれぞれランダム個含むバッチを2個作成することになります(分かりやすく模式化して書いたので実際のものとは多少異なります)。


 

バッチを Validator ネットワークに送信
# sawtooth batch submit -f batches.intkey --url http://rest-api:8008
batches: 3,  batch/sec: 44.84783422259765

先ほど作成したファイルを読み込んで、バッチを一斉にネットワークに送信します。

「batches: 3」とログが出ているので、バッチを3つ(新規作成1つ+更新2つ)送信したことが分かります。Validator ネットワーク側では 1〜3台のノードが個別にトランザクションを受け取って処理を実行することが予想されます。もちろん順序が逆にならないようにスケジューリングされて実行されるはずなので、ご安心を。


 

ブロックを確認
# sawtooth block list --url http://rest-api:8008
NUM  BLOCK_ID                                                                                                                          BATS  TXNS  SIGNER
2    2ba9acebbe53f32909c1b341ace92d7d6d467dfd8a7de4deeed7d719f4794eff01a4c258ce3798fa8742f4deba214e11c6a73255acdf4f48205c15c17d3bcbf6  2     8     02850b3d81f14c7c1b9f2aee1274e2...
1    a275a1f80ec4e89f38e5f06f598891e24997bd1d29c2e471682f4d82b6a36ecc070beb7b3b483598a23552fbe0dae7588a7efb031bcbde6b62acbf73946655d4  1     3     02850b3d81f14c7c1b9f2aee1274e2...
0    d16b15f03ff35031f094f5dadf4211ee7bb41c4bb707f0e7d0e015b70b85b8164a326dec294ff02e2aefcf1aa6cdbe3be8eb70d5d63cf322a269feda12b78534  1     1     02850b3d81f14c7c1b9f2aee1274e2...

「NUM」が「1」「2」のブロックが合計2つ増えています。クライアントからバッチを3個一斉に送信したのに、最終的には別々のブロックとしてチェーンに固定化されているのがミソと言えばミソでしょう。Sawtooth ではチェーン内部にタイマーがあり、一定時間ごとにブロックが承認されるようになっているようなのでこのようなことが起こり得るのです。

また、NUMが「1」のブロックの「BATS」が「1」、「TXNS」が「3」となっているのは、ブロックの中にバッチが1個、トランザクションが3個入っていることを示しています。同じように、NUMが「2」のブロックの「BATS」が「2」、「TXNS」が「8」となっているので、ブロックの中にバッチが2個、トランザクションが8個入っていることが推測されます。

実際に最後のブロックの中身を以下のコマンドで確認すると、「batches」直下に「(バッチの)header」が2つあるのでバッチが2個、1つ目のバッチの「transactions」直下に「(トランザクションの)header」が1つ、2つ目のバッチの「transactions」直下に「header」が7つあるので合計8個のトランザクションが含まれていることが確認できます。

# sawtooth block show 2ba9acebbe53f32909c1b341ace92d7d6d467dfd8a7de4deeed7d719f4794eff01a4c258ce3798fa8742f4deba214e11c6a73255acdf4f48205c15c17d3bcbf6 --url http://rest-api:8008
batches:
- header:
    signer_public_key: 02991e34411f9282a0a057d4adf0b00f44605d0da25bf8141e1e7b2875486083ac
    transaction_ids:
    - d9069e5d4d254faf9d42dcf66ca468edfef1a0bc7370465e90c48a9b46061bf63bdf92a76fbaa846e6ca802e0f5003ed02e4561e3e516f783177b2be1c82a450
  header_signature: 69e787f67dbdfac18799e799d344c4fe3f70f99de58993241a249f63789ad2c549560fc874b3bb1c78d52d33f7882b24290240bc1f9142b5e9db1b49c52002f7
  trace: false
  transactions:
  - header:
      batcher_public_key: 02991e34411f9282a0a057d4adf0b00f44605d0da25bf8141e1e7b2875486083ac
      dependencies:
      - 18b1b2e26d6bcf605c601d118fe27a84108c8abf1110c15a8fb9e84b283681176758235e622d963f930f26876ffaff72637492fb296da23f4ff559d226c372ab
      family_name: intkey
      family_version: '1.0'
      inputs:
      - 1cf1265008cef7e8135dc4a2f0a8d94f75fa526a1f7d383cc82fd5e3c384744de2c1c9
      nonce: 0x1.68d516ec2ccfdp+30
      outputs:
      - 1cf1265008cef7e8135dc4a2f0a8d94f75fa526a1f7d383cc82fd5e3c384744de2c1c9
      payload_sha512: f1c7d99b8c5fea748e2ed97e3c61dcfb1edd8a32415945a0a1c80e39b71c9a7e1128f852b315c0478d62a6b9026e1c5247f9d60d63c062b9d1a102df4381d4bc
      signer_public_key: 02991e34411f9282a0a057d4adf0b00f44605d0da25bf8141e1e7b2875486083ac
    header_signature: d9069e5d4d254faf9d42dcf66ca468edfef1a0bc7370465e90c48a9b46061bf63bdf92a76fbaa846e6ca802e0f5003ed02e4561e3e516f783177b2be1c82a450
    payload: o2ROYW1lZnp3bVNCSWVWYWx1ZQJkVmVyYmNpbmM=
- header:
    signer_public_key: 02991e34411f9282a0a057d4adf0b00f44605d0da25bf8141e1e7b2875486083ac
    transaction_ids:
    - ae4c9d201f108f2e1f7f89e00032c6176d518415dcfc0fb4584f32a3ddaae8e8644c3028357ae34d08eebf95a9a0d65e31402a2c0e6cf4f67d35d3b3ec5c28d4
    - 87f681c683075bbd9e85c0c754ea797f8d407bfb6d9e3b0d669bec068ea3e1d7752b2b5136718c87dfb95ec3cfe4e810ba591d6b93dd2e69f202f0fd0a58c210
    - 582073cb877d06086500303ad8e5736d7aad7d7575e41f42b1ba4324e52bfd7e457effbc151842d04208a56a90a4b86a0d48167d365a1e46e3845823488460ed
    - b119f313f8cd778d06b311dcc613d6e4e12db8822f7e76bdbe8adfb234072cdc3d449e04d0711cf22bd34179d5677b9d83ee7604b62c5d43646118d2153be4b3
    - 47442f8dd34c17cc1ac1dc38f043fcd45e87d1a7a584a15c614b290abdaaea2771f968c156776107582dc39bc9a2f0c5f242348bf790a00c14e1c207a3bd4992
    - f54356ec854c54fb2abe0f6fd767d1207b461ba82f563c296f611c3b4fc1962b615e124d1649460e5ddca64d28f2f7477302a145189c44a664b8fd61d0e605c8
    - 07b1eb851b952778c928d380d1ea6121949f64cbedb16f41e1d9334000815b69207e4d51373c2a77b0dcd609c295577c10b17a00c765bfad565fda2fc9bebc68
  header_signature: 9a6e057f190e10d7a5d52a0892fc724f58106cc78d9db32cf7da1aedd93f0c9e170c5db853899bbb6b4f1cd1838ab5145d5e568ccde6b777119b5c29305b3083
  trace: false
  transactions:
  - header:
      batcher_public_key: 02991e34411f9282a0a057d4adf0b00f44605d0da25bf8141e1e7b2875486083ac
      dependencies:
      - 67a02d58c36134362b63a2043fb95e0f4f1830293227fc1a859d4fd979d9679e3c2d450a3279b582a02248d66514334af70d9198cc05049740d1bdac9daac32d
      family_name: intkey
      family_version: '1.0'
      inputs:
      - 1cf126c0efc8717958cef02cc3131b80479462b9c90dc6aa0fe7e09229504bf4a62d27
      nonce: 0x1.68d516ec2d0c1p+30
      outputs:
      - 1cf126c0efc8717958cef02cc3131b80479462b9c90dc6aa0fe7e09229504bf4a62d27
      payload_sha512: b339df5cfa78060d82790be2b9f7d0db8064fb89a3c42ab8f3c1246bc3247bd9d86c4860324584fd8ef58bd948997bb417f0a093fb6355ccc776b346d51e9bc3
      signer_public_key: 02991e34411f9282a0a057d4adf0b00f44605d0da25bf8141e1e7b2875486083ac
    header_signature: ae4c9d201f108f2e1f7f89e00032c6176d518415dcfc0fb4584f32a3ddaae8e8644c3028357ae34d08eebf95a9a0d65e31402a2c0e6cf4f67d35d3b3ec5c28d4
    payload: o2ROYW1lZm54QmtodWVWYWx1ZQZkVmVyYmNkZWM=
  - header:
      batcher_public_key: 02991e34411f9282a0a057d4adf0b00f44605d0da25bf8141e1e7b2875486083ac
      dependencies:
      - 67a02d58c36134362b63a2043fb95e0f4f1830293227fc1a859d4fd979d9679e3c2d450a3279b582a02248d66514334af70d9198cc05049740d1bdac9daac32d
      family_name: intkey
      family_version: '1.0'
      inputs:
      - 1cf126c0efc8717958cef02cc3131b80479462b9c90dc6aa0fe7e09229504bf4a62d27
      nonce: 0x1.68d516ec2d2d3p+30
      outputs:
      - 1cf126c0efc8717958cef02cc3131b80479462b9c90dc6aa0fe7e09229504bf4a62d27
      payload_sha512: 16bb60a1f4f07335a1aa2417e758d41945ea64cc6743dce71871a291ecbd5b25964272207c05ca03be8eb6c4a9b914d15bebf0e8e41769dfeb3564926f37f142
      signer_public_key: 02991e34411f9282a0a057d4adf0b00f44605d0da25bf8141e1e7b2875486083ac
    header_signature: 87f681c683075bbd9e85c0c754ea797f8d407bfb6d9e3b0d669bec068ea3e1d7752b2b5136718c87dfb95ec3cfe4e810ba591d6b93dd2e69f202f0fd0a58c210
    payload: o2ROYW1lZm54QmtodWVWYWx1ZQlkVmVyYmNpbmM=
  - header:
      batcher_public_key: 02991e34411f9282a0a057d4adf0b00f44605d0da25bf8141e1e7b2875486083ac
      dependencies:
      - 67a02d58c36134362b63a2043fb95e0f4f1830293227fc1a859d4fd979d9679e3c2d450a3279b582a02248d66514334af70d9198cc05049740d1bdac9daac32d
      family_name: intkey
      family_version: '1.0'
      inputs:
      - 1cf126c0efc8717958cef02cc3131b80479462b9c90dc6aa0fe7e09229504bf4a62d27
      nonce: 0x1.68d516ec2d4ddp+30
      outputs:
      - 1cf126c0efc8717958cef02cc3131b80479462b9c90dc6aa0fe7e09229504bf4a62d27
      payload_sha512: c8056631e8a3096891b7b6c2ab1e4f7275f697ce806762dcad037bcf25502a617b2d6fcd6b3d5dca71fb9427f2ab46d99261b0eee939d88c07483fdcb99673bc
      signer_public_key: 02991e34411f9282a0a057d4adf0b00f44605d0da25bf8141e1e7b2875486083ac
    header_signature: 582073cb877d06086500303ad8e5736d7aad7d7575e41f42b1ba4324e52bfd7e457effbc151842d04208a56a90a4b86a0d48167d365a1e46e3845823488460ed
    payload: o2ROYW1lZm54QmtodWVWYWx1ZQJkVmVyYmNkZWM=
  - header:
      batcher_public_key: 02991e34411f9282a0a057d4adf0b00f44605d0da25bf8141e1e7b2875486083ac
      dependencies:
      - 67a02d58c36134362b63a2043fb95e0f4f1830293227fc1a859d4fd979d9679e3c2d450a3279b582a02248d66514334af70d9198cc05049740d1bdac9daac32d
      family_name: intkey
      family_version: '1.0'
      inputs:
      - 1cf126c0efc8717958cef02cc3131b80479462b9c90dc6aa0fe7e09229504bf4a62d27
      nonce: 0x1.68d516ec2d6f2p+30
      outputs:
      - 1cf126c0efc8717958cef02cc3131b80479462b9c90dc6aa0fe7e09229504bf4a62d27
      payload_sha512: 6c07331ddb97af0db05aa9fb64afe7ac52a7e0229992ca487a812e296ff9adedebaba2fcd4e0c7cec71d5505df942e84b6031baeb025e2841545092c1a154985
      signer_public_key: 02991e34411f9282a0a057d4adf0b00f44605d0da25bf8141e1e7b2875486083ac
    header_signature: b119f313f8cd778d06b311dcc613d6e4e12db8822f7e76bdbe8adfb234072cdc3d449e04d0711cf22bd34179d5677b9d83ee7604b62c5d43646118d2153be4b3
    payload: o2ROYW1lZm54QmtodWVWYWx1ZQNkVmVyYmNkZWM=
  - header:
      batcher_public_key: 02991e34411f9282a0a057d4adf0b00f44605d0da25bf8141e1e7b2875486083ac
      dependencies:
      - 9c6e0588503d407a662a416d2d551d1e65998ddfefd5d377f3175a2a24a0cee47ee0692a033a0f52d9155ba036ff57b73a26faf4ad3f6a60e4a27068ddfe4323
      family_name: intkey
      family_version: '1.0'
      inputs:
      - 1cf12656d2b508c206f56463d26e9045aad7d42527de7899f4acfc93d1e9f7b9c8c2c8
      nonce: 0x1.68d516ec2d8f3p+30
      outputs:
      - 1cf12656d2b508c206f56463d26e9045aad7d42527de7899f4acfc93d1e9f7b9c8c2c8
      payload_sha512: d27adf0758adac89fde1bd1ec866a86ea63073ff811323b3ddec639a625c87af4edf45ed94d6fbef2e4a65bb98055b0a2e2eb1894e1f169ff10059b7dc1bd9de
      signer_public_key: 02991e34411f9282a0a057d4adf0b00f44605d0da25bf8141e1e7b2875486083ac
    header_signature: 47442f8dd34c17cc1ac1dc38f043fcd45e87d1a7a584a15c614b290abdaaea2771f968c156776107582dc39bc9a2f0c5f242348bf790a00c14e1c207a3bd4992
    payload: o2ROYW1lZndWZ3FZZGVWYWx1ZQlkVmVyYmNkZWM=
  - header:
      batcher_public_key: 02991e34411f9282a0a057d4adf0b00f44605d0da25bf8141e1e7b2875486083ac
      dependencies:
      - 67a02d58c36134362b63a2043fb95e0f4f1830293227fc1a859d4fd979d9679e3c2d450a3279b582a02248d66514334af70d9198cc05049740d1bdac9daac32d
      family_name: intkey
      family_version: '1.0'
      inputs:
      - 1cf126c0efc8717958cef02cc3131b80479462b9c90dc6aa0fe7e09229504bf4a62d27
      nonce: 0x1.68d516ec2db21p+30
      outputs:
      - 1cf126c0efc8717958cef02cc3131b80479462b9c90dc6aa0fe7e09229504bf4a62d27
      payload_sha512: bd4e037e91ebd277a2e03821aa01fc821be97d27aeb69edd008d6453fde1f846a6fe564dccafec9061bd07f903f50ddc95bdfbebbb74e13251fb9539c13f673f
      signer_public_key: 02991e34411f9282a0a057d4adf0b00f44605d0da25bf8141e1e7b2875486083ac
    header_signature: f54356ec854c54fb2abe0f6fd767d1207b461ba82f563c296f611c3b4fc1962b615e124d1649460e5ddca64d28f2f7477302a145189c44a664b8fd61d0e605c8
    payload: o2ROYW1lZm54QmtodWVWYWx1ZQVkVmVyYmNpbmM=
  - header:
      batcher_public_key: 02991e34411f9282a0a057d4adf0b00f44605d0da25bf8141e1e7b2875486083ac
      dependencies:
      - 9c6e0588503d407a662a416d2d551d1e65998ddfefd5d377f3175a2a24a0cee47ee0692a033a0f52d9155ba036ff57b73a26faf4ad3f6a60e4a27068ddfe4323
      family_name: intkey
      family_version: '1.0'
      inputs:
      - 1cf12656d2b508c206f56463d26e9045aad7d42527de7899f4acfc93d1e9f7b9c8c2c8
      nonce: 0x1.68d516ec2de3ap+30
      outputs:
      - 1cf12656d2b508c206f56463d26e9045aad7d42527de7899f4acfc93d1e9f7b9c8c2c8
      payload_sha512: 08e0a3f2ff71ed2a5ba635cd528e7a7606135cd116d16bc471f86889a1ad51bc378ac9381c77a965c15935e505680a05007badaf561ab8773fc533df791673ec
      signer_public_key: 02991e34411f9282a0a057d4adf0b00f44605d0da25bf8141e1e7b2875486083ac
    header_signature: 07b1eb851b952778c928d380d1ea6121949f64cbedb16f41e1d9334000815b69207e4d51373c2a77b0dcd609c295577c10b17a00c765bfad565fda2fc9bebc68
    payload: o2ROYW1lZndWZ3FZZGVWYWx1ZQRkVmVyYmNpbmM=
header:
  batch_ids:
  - 69e787f67dbdfac18799e799d344c4fe3f70f99de58993241a249f63789ad2c549560fc874b3bb1c78d52d33f7882b24290240bc1f9142b5e9db1b49c52002f7
  - 9a6e057f190e10d7a5d52a0892fc724f58106cc78d9db32cf7da1aedd93f0c9e170c5db853899bbb6b4f1cd1838ab5145d5e568ccde6b777119b5c29305b3083
  block_num: '2'
  consensus: RGV2bW9kZQ==
  previous_block_id: a275a1f80ec4e89f38e5f06f598891e24997bd1d29c2e471682f4d82b6a36ecc070beb7b3b483598a23552fbe0dae7588a7efb031bcbde6b62acbf73946655d4
  signer_public_key: 02850b3d81f14c7c1b9f2aee1274e2862d0e707dbe57136602ec5437dab774b431
  state_root_hash: 3370c09db54b81f7ddf5fcd4b2d38f18c8f0cd8dbebf90a8eb30b23eb9c92325
header_signature: 2ba9acebbe53f32909c1b341ace92d7d6d467dfd8a7de4deeed7d719f4794eff01a4c258ce3798fa8742f4deba214e11c6a73255acdf4f48205c15c17d3bcbf6

なお、「inputs」や「outputs」は State のアドレスを表しており、それぞれのトランザクションの処理結果の格納先を指し示しています。



 

最終的な State を確認

最後に State の値がどうなったかを確認してみます。

# sawtooth state list --url http://rest-api:8008
ADDRESS                                                                 SIZE  DATA
000000a87cb5eafdcca6a8cde0fb0dec1400c5ab274474a6aa82c12840f169a04216b7  110   b'\nl\n&sawtooth.settings.vote.authorized_keys\x12B039f7586349ccf1490127db60acd6ac6c00cdebf5ea67ccc...
1cf1265008cef7e8135dc4a2f0a8d94f75fa526a1f7d383cc82fd5e3c384744de2c1c9  11    b'\xa1fzwmSBI\x19\xe9\xe6'                                                                         ...
1cf12656d2b508c206f56463d26e9045aad7d42527de7899f4acfc93d1e9f7b9c8c2c8  11    b"\xa1fwVgqYd\x191'"                                                                               ...
1cf126c0efc8717958cef02cc3131b80479462b9c90dc6aa0fe7e09229504bf4a62d27  13    b'\xa1fnxBkhu\x1a\x00\x01I\xd9'                                                                    ...
HEAD BLOCK: "2ba9acebbe53f32909c1b341ace92d7d6d467dfd8a7de4deeed7d719f4794eff01a4c258ce3798fa8742f4deba214e11c6a73255acdf4f48205c15c17d3bcbf6"

アドレスが「1cf1265008ce...」「1cf12656d2b5...」「1cf126c0efc8...」のレコードが増えています(先頭6桁が同じになっている理由はお分かりですよね)。最後に処理されたトランザクションの「outputs」の値が「1cf12656d2b508c206f56463d26e9045aad7d42527de7899f4acfc93d1e9f7b9c8c2c8」で、それに合致するアドレスの「DATA」が、最新の Status の値になっているはずです。


cbor でシリアライズされた値をデコードしてみます。

>>> import cbor
>>> cbor.loads(b"\xa1fwVgqYd\x191'")
{'wVgqYd': 12583}

確認することができました。
結構増えてますね。



 

まとめ

5分ほどでデモを動かせるところまで簡単にセットアップができてしまう、お手軽なブロックチェーン「Hyperledger Sawtooth」を紹介しました。


11月末に参加した勉強会「「bitFlyer Drink Meetup! #9」に参加してきました - akiyoko blog」でこのプロダクトを知り、プロダクト自体が Python で書かれていて、Python でスマートコントラクトを自由に書けるというところにグッと来たのが、この記事を書こうと思ったきっかけです。

軽い気持ちで「ブロックチェーン」の Advent Calendar に登録してしまった今日までの二週間ほどで急ごしらえで勉強した内容を書き殴ったので、間違っているところがいろいろあるかと思います。もし間違いがありましたら、温かい目で見ると同時に優しく教えていただけるとありがたいです。



明日は、m0t0k1ch1 さんの「ブロックチェーン Advent Calendar 2017 - Qiita」 18日目の記事です。
よろしくお願いします。


 

おまけ

最近読んだ本ですが、金融分野において、今回紹介した Hyperledger Sawtooth の兄貴分である「Hyperledger Fabric」や R3コンソーシアムが開発した「Corda」、Ripple 社が推進する「ILP」などのコンソーシアム型あるいはプライベート型の分散型台帳フレームワークを利用した大規模な実証実験が進められており、そう遠くない将来にブロックチェーン技術が金融業界に革命を起こす、という衝撃の内容です。

ビットコインじゃないブロックチェーンについて知りたい方は是非。金融業界の方で「これから何が起こるのか知りたい!」という方はマストだと思います。

*1:Intel のチップだから「ノコギリ波」なのかな。。

*2:https://hyperledger.org/members

*3:有名すぎるため、単に「Hyperledger」と書かれているものが実際には「Hyperledger Fabric」を差していることが多いので注意が必要です。Hyperledger あるある

*4:https://www.boj.or.jp/announcements/release_2017/data/rel170227a7.pdf

*5:Blockchain Technology Projects – Hyperledger

*6:このあたりが何を意味しているかがよく分かってません。。

*7:ちなみに、Fabric は Go、Iroha は C++ で書かれているそうです。 https://www.boj.or.jp/announcements/release_2017/data/rel170227a7.pdf

*8:https://sawtooth.hyperledger.org/docs/core/releases/latest/architecture/global_state.html?highlight=merkle#radix-addresses

「ビットコインとか勉強会#13」に参加してきました

会場

株式会社 LIFULL
〒102-0083 東京都千代田区麹町 1-4-4 8F

Twitter

twitter.com




ビットコイン取引高日本一の仮想通貨取引所 coincheck bitcoin
ビットコイン取引高日本一の仮想通貨取引所 coincheck bitcoin


 

全体の感想など

「ビットコインとか勉強会」の参加はこれで 5回目です。 *1, *2, *3, *4


最近はブロックチェーンの本を読んだりインターネットや Twitter で情報と集めたりしていろいろ勉強をしていて、仮想通貨やブロックチェーンの勉強会に行っても昔と比べて理解度が上がっていると思っていたのですが、「insight」や「electrumx」などのサーバサイドプロダクトの存在は初めて知りました。まだまだアンテナの張り方が足りないようですね。

もう少し話を聞きたかったので急遽、懇親会にも参加してみました。久々でしたが、すごくいい話が聞けました。

今回はどちらかと言うと開発者寄りの話でしたが、実際に手を動かしてコマンドを叩いてみるようなもくもく会的なイベントにも今後参加していきたいと思います。





 

ビットコインを支えるインフラについて

Yuki Akiyama 氏 (@you21979)(ビットバンク株式会社 ビットコインエンジニア)


暗号通貨 Advent Calendar 2017 - Qiita」を立てた方だとか。最近では、

などの記事も。

  • なぜインフラが必要なのか?
    • ウォレットを作るときに困るから
    • (自分以外の)ビットコインアドレスを指定して未使用のトランザクション(UTXO)の一覧を取得する、などの一見簡単なことができない
  • 解決するプロダクト
    • insight, electrumx
    • 端末側でウォレットを動かすためのバックエンドサーバ
  • insight
    • Node.js で作られている
    • REST-API で簡単に情報を取得できる(これがスゴイところ)
    • 5つの部品から構成されている
      • 魔改造版 bitcoind
      • bitcore-lib
      • bitcore-node(UTXOのデータベース)
      • insight-ui(ブロックエクスプローラの画面)
      • insight-api(REST-API)
    • マルチプラットフォームのウォレットをホスティングできる
    • まだ SegWit に対応していない(v5 から対応予定?)
      • Confirmされるまで見れない?
    • 最新版に追従しにくい。自分で魔改造版 bitcoind にパッチを当てる必要がある。かなり大変
    • データベースが巨大。来年には500BG超えそう。。
    • 開発が滞ってた?最近活発に?
    • オルトコインの対応は? ⇒ しにくい
      • 開発チームが insight の対応をしているところもあるが(Litecoin, ZCash, Dash, Zcoin)、結構不安定?
  • electrumx
    • ウォレットソフト electrum のサーバサイド実装
    • Python3で作られている。作者は kyuupichan
    • electrum を使ったクライアント? 例えば、Coinomi など
    • 最初からオルトコインに対応できるように設計されているのがスゴイ
      • 現在30種類くらい対応
      • coins.py に記述されているコインであれば、設定ファイルに記載するだけで対応可能。
      • 積極的にプルリクを取り込んでくれる
    • REST-API じゃないが、プッシュ通知とかがあって便利
    • APIの設計が細切れ?になってて、必要なデータを一度で取得できないため、いくつか組み合わせる必要あり
    • トランザクションをデコードしてくれない。自分で解析が必要
    • システム的に、定期的にメンテが必要。ダウンタイムが必要。オルトコインだと1ヶ月ちょっと??(ビットコインだと1年くらい)
    • ウォレット作るなら十分。他のことをやろうとすると大変??


 

しっかり学ぶ ICOのベストプラクティス

千賀 優作 氏 (@syrohei)(一般社団法人 分散技術総合研究所 代表理事)



千賀さんは最強のイーサリアマーだそうです。
RICO をオープンソースで開発中とのことで、それについての説明です。

  • スマートコントラクトが必要
  • (EIP20Token以外の)ICOの規格が統一されていない
    • 今年のICO の 90〜95%くらいは EIP20トークン?
    • Golem, Gnosis は受け取ったEtherを認識できないとか?で ICO が失敗したとか??
  • 学習コスト、開発コスト、ハードルが高い
  • セキュリティ的な要件、法的リスクもある
  • ICOのベストプラクティスとは?
    • スムーズなICOを実現するための準備
      • なりすましやフィッシング詐欺に適切な対処が可能
    • スマートコントラクトのメリットを強力に活用
      • Trusted なアプリケーションを低コストで稼働
    • コードの信頼性を維持
      • 絶対にバグをうまないコードを
  • RICOTruffle フレームワークによるベストでナイスな ICO開発
  • Ethereum のウィークポイント
    • Ethereum の tx は一つの tx で一つの method しか実行できない
      • 設計を考え直すこともしばしば
    • スマートコントラクトの無限ループが発生しやすい
      • 再帰的呼び出しに弱い(The DAO の攻撃)
    • 設計が複雑になりやすい。挙動を正確に把握しないとガスが無駄になりがち
    • 構造体が使いにくい(代わりにコントラクトを新規に生成したほうがいい?)
    • function() は多用しない(無限ループの脆弱性)
    • できる限りグローバル変数(外部変数)は使わない。設計を見直す
    • 条件分岐(if else)を多用し過ぎるとテストしづらくなるので、適度に列挙型 enum で状態遷移を明確に
    • 常にガスの利用を意識した処理を心がける(ストレージをなるべく使わない)
  • Truffle は Solidity ベースのスマートコントラクトを作成するのに最適
    • 最低限のコントラクト管理機能があり、テストも簡単に書ける
    • もはやデファクトスタンダードに
  • RICO における Proof of Donation による寄付証明とイベントハンドリング
  • RICO は、ICOに最適化されたオープンソースフレームワーク
    • Truffle のテンプレートエンジン
    • 誰かが誰かに寄付をした、ということを証明する
    • (機能拡張すれば)ホワイトリストにも対応できる

イーサリアムのスマートコントラクトについて知りたい、あるいは開発をしてみたいという方にはこちらの本が有益だと思います。私も最近読み終えました。

*1:<過去記事> akiyoko.hatenablog.jp

*2:<過去記事> akiyoko.hatenablog.jp

*3:<過去記事> akiyoko.hatenablog.jp

*4:<過去記事> akiyoko.hatenablog.jp

まだ CSV の文字化けで消耗してるの?(Excel で直接開いても文字化けしない CSVファイルを Python3 で作成するスマートな方法)

この投稿は 「python Advent Calendar 2017 - Qiita」 の 9日目の記事です。

こんにちは、akiyoko です。
「Python Advent Calendar」は 4年連続 4度目の参加になります。 *1, *2, *3



はじめに

皆さん、CSV は好きですよね? Excel も大好きですね?
じゃあ当然、CSVファイルは Excel で開きますよね。

文字化けは? ・・もちろん嫌いですよね。
でも CSVファイルを Excel で開こうとしたときに、こんな文字化け地獄を経験したことはありませんでしたか? *4


f:id:akiyoko:20171205230423p:plain:w400


ということで今回は、Excel で直接開いたときに文字化けしない CSV ファイルを Python3 で作成する方法 を紹介したいと思います。(おまけで Python2 でのやり方も書いておきますが、今時 Python2 で消耗している人なんていないですよね? *5



 

結論

結論を先に書くと、

  • Unicode の文字符号化方式は 「UTF-16(正確には、BOMありの UTF-16 LE)」
  • タブ区切り

で CSVファイルを作成すれば、Excel で直接開いても文字化けせず、それぞれの値がセルごとに分かれて表示されます。


(参考)Which encoding opens CSV files correctly with Excel on both Mac and Windows? - Stack Overflow



Windowsでは、リトルエンディアンのUTF-16符号化スキームが使われている。内部表現では16ビット符号なし整数を符号単位とするUTF-16符号化形式(CEFなのでBOMはなし)として扱い、ファイルなどではBOMありのUTF-16符号化スキーム(リトルエンディアン)が主である。


UTF-16 - Wikipedia

Note Microsoft uses UTF-16, little endian byte order.


Using Byte Order Marks | Microsoft Docs

とあるように、Microsoft Excel が 「BOMありの UTF-16 LE」を扱っているため、この方法がベストと言えそうです。


なお、「CSV(Comma-Separated Values)」と言いながらも区切り文字がタブなので、厳密には「TSV(Tab-Separated Values)」と呼ぶべきでしょうか。議論の余地はあるものの(*6)、拡張子を「.csv」としておくことでダブルクリック時に自動的に Excel が起動してくれるので(アプリケーションが関連付けられているので)、拡張子は「.csv」とした方がよいでしょう。



 

検証(Python 3)

ファイルオープン時に「encoding='utf-16'」と指定することで、符号化方式が「UTF-16 LE with BOM」となります。
「encoding='utf-8-sig'」(UTF-8 with BOM)だと、環境によっては(Mac + Excel 2011 とか?)文字化けすることがあるので推奨しません。

import csv


def main():
    rows = [['髙﨑 將'], ['あああ', 'いいい', 'ううう'], ['Ⅰ・Ⅱ・Ⅲ', '①②③']]

    # OK
    with open('utf_16_excel_tab.csv', 'w', newline='', encoding='utf-16') as f:
        w = csv.writer(f, dialect='excel-tab', quoting=csv.QUOTE_ALL)
        w.writerows(rows)

    # これでもOK
    with open('utf_16_excel_tab_2.csv', 'w', newline='', encoding='utf-16') as f:
        w = csv.writer(f, dialect='excel', delimiter='\t', quoting=csv.QUOTE_ALL)
        w.writerows(rows)

    # 文字化けしないが、セルごとに分かれないのでNG
    with open('utf_16.csv', 'w', newline='', encoding='utf-16') as f:
        w = csv.writer(f, quoting=csv.QUOTE_ALL)
        w.writerows(rows)

    # 文字化け (しない場合もある)
    with open('utf_8_sig.csv', 'w', newline='', encoding='utf-8-sig') as f:
        w = csv.writer(f, quoting=csv.QUOTE_ALL)
        w.writerows(rows)

    # 文字化け (しない場合もあるが、セルごとに分かれないのでNG)
    with open('utf_8_sig_excel_tab.csv', 'w', newline='', encoding='utf-8-sig') as f:
        w = csv.writer(f, dialect='excel-tab', quoting=csv.QUOTE_ALL)
        w.writerows(rows)

    # 文字化け
    with open('utf_8.csv', 'w', newline='', encoding='utf-8') as f:
        w = csv.writer(f, quoting=csv.QUOTE_ALL)
        w.writerows(rows)

    # 文字化け
    with open('utf_8_excel_tab.csv', 'w', newline='', encoding='utf-8') as f:
        w = csv.writer(f, dialect='excel-tab', quoting=csv.QUOTE_ALL)
        w.writerows(rows)


if __name__ == '__main__':
    main()


OK

f:id:akiyoko:20171205231119p:plain:w500

セルごとに分かれない

f:id:akiyoko:20171205231145p:plain:w500

文字化け

f:id:akiyoko:20171205231136p:plain:w500


なお、確認した環境は、

  • macOS 10.12.16 + Microsoft Office 365 & Excel for Mac 2011
  • Windows 10 + Microsoft Office 2010

です。



ちなみに、open 時に「newline=''」を指定している理由は、Windows 対策のためです。


(参考)

 

おまけ(Python 2)

# -*- coding: utf-8 -*-
import cStringIO

import codecs
import unicodecsv as csv


class UnicodeWriter:
    """
    A CSV writer which will write rows to CSV file "f",
    which is encoded in the given encoding.
    """

    def __init__(self, f, dialect=csv.excel, encoding="utf-8", **kwds):
        # Redirect output to a queue
        self.queue = cStringIO.StringIO()
        self.writer = csv.writer(self.queue, dialect=dialect, **kwds)
        self.stream = f
        self.encoder = codecs.getincrementalencoder(encoding)()

    def writerow(self, row):
        self.writer.writerow([s.encode("utf-8") for s in row])
        # Fetch UTF-8 output from the queue ...
        data = self.queue.getvalue()
        data = data.decode("utf-8")
        # ... and reencode it into the target encoding
        data = self.encoder.encode(data)
        # write to the target stream
        self.stream.write(data)
        # empty queue
        self.queue.truncate(0)

    def writerows(self, rows):
        for row in rows:
            self.writerow(row)


def main():
    rows = [[u'髙﨑 將'], [u'あああ', u'いいい', u'ううう'], [u'Ⅰ・Ⅱ・Ⅲ', u'①②③']]

    with open('test_unicode_writer.csv', 'w') as f:
        w = UnicodeWriter(f, dialect=csv.excel_tab, encoding='utf-16')
        w.writerows(rows)


if __name__ == '__main__':
    main()

https://docs.python.org/2/library/csv.html#examples の UnicodeWriter をそのまま使えばいいよという話ですが、それにしても面倒臭いですよね。いっそ滅んでしまえばいいのに、Python2。



 

まとめ

Excel で直接開いても文字化けしない CSVファイルを Python3 で作成するには、

  • ファイルオープン時に「encoding='utf-16'」と指定
  • csv.writer の引数に「dialect='excel-tab'」と指定

とするのがスマートで確実です。

今回はちょっとレガシーな話題でした。



明日は、driller さんの「python Advent Calendar 2017 - Qiita」 10日目の記事です。
よろしくお願いします。




 

おまけ

文字コードに詳しくなりたい人は、こちらをどうぞ。

*1:《過去記事》akiyoko.hatenablog.jp

*2:《過去記事》akiyoko.hatenablog.jp

*3:《過去記事》akiyoko.hatenablog.jp

*4:ネタが古いですね。図は、「悪循環画像ジェネレータ」を利用させていただきました。

*5:・・はい、私です。

*6:「タブ区切りは CSV じゃなくて TSV だろ」問題がついに解決した - 頭ん中

「あなたの趣味は?」のアンケート結果を R で因子分析してみた

この投稿は 「R Advent Calendar 2017 - Qiita」 の 4日目の記事です。

こんにちは、akiyoko です。
「R Advent Calendar 2017」は 3年ぶり 2回目の参加になります。 *1

何をしたのか?

「あなたの趣味は?」というアンケート結果に対して「因子分析」を実施 することで回答の奥に潜む共通要因を探り、どんな趣味趣向を持った人たちがアンケートに回答してくれていたのか? を分析してみました。


具体的にはこんなシチュエーションです。

現在、アンケートの回収に Google Forms を使っていて、回答項目の一つに「あなたの趣味は何ですか?」(*2)という項目が含まれています。例えばこんな感じです(実際には他にも項目があります)。


f:id:akiyoko:20171202235107p:plain:w300

趣味アンケート

Q1.あなたの趣味は何ですか? 当てはまるものを次の中から全てお答えください


【選択肢】特に無い/将棋/囲碁/チェス/ポーカー/麻雀/その他のボードゲーム・テーブルゲーム/TVゲーム・PCゲーム(携帯用を含む)/映画鑑賞/音楽鑑賞/楽器演奏/演芸・演劇鑑賞/美術鑑賞/スポーツ観覧/ダンス/料理・お菓子作り/ガーデニング/読書/ネットサーフィン/パチンコ・パチスロ/競馬・競輪・競艇/カラオケ/その他(自由回答)


回答結果をグラフにすると、以下のようになりました。

f:id:akiyoko:20171203003721p:plain:w500

しかしながら、このままでは面白くない。何か新しい視点で分析できないものか? *3

ということで、このアンケート回答者の趣味の傾向から、どんなクラスタの人たちがアンケートに回答してくれているのか?ということを趣味の背後に潜んでいる共通因子から推測してみよう、と思い立ったわけです。


 

そもそも因子分析とは?

こちらの説明が非常に分かりやすいです。

  • 因子分析は,複数の変数間の関係性を探る際によく用いられる手法である(ただし正確には潜在的な変数を仮定するのだが,以下に説明する)。
  • 因子分析をする目的は,「因子」を見つけることである。
  • 因子とは,実際に測定されるものではなく,測定された変数間の相関関係をもとに導き出される「潜在的な変数」(観測されない,仮定された変数)である。
  • 言い換えると,因子分析とは「ある観測された変数(たとえば質問項目)が,どのような潜在的な因子から影響を受けているか」を探る手法といえる。


心理データ解析第8回(1)」より


よく「主成分分析」と混同しやすい「因子分析」ですが、

  • 因子分析をする目的は「共通因子を見つけること」である
  • その一方で,主成分分析の目的は「情報を縮約すること」である。

心理データ解析補足01」より

といった違いがあります。上記サイトの図が特に分かりやすいです。

私の感覚では、主成分分析は、主成分を1つに縮約して観測された変数に重み付けをして各データ行の「合計得点」を求めたいときや、主成分を2つに次元圧縮して特徴量を一つの散布図にまとめて表示するときに使うもの、と考えています。



 

なぜ R?

普段は Excel や Python でデータ分析をしていて R は使わないのですが、私の知る限りでは、因子分析に関しては Excel 単体ではできず、Python でも簡単にできるようなものがありません(scikit-learn には sklearn.decomposition.FactorAnalysis というクラスがあるのですがそれを使ったサンプルが何故かあまりありません。主成分分析をするサンプルならいつくもあるのですが・・)。
その点、R なら超簡単に出来てしまうことが分かってからは、因子分析には R を利用するようにしています。

実践

ここからが本番です。

Google Forms のアンケート結果をクレンジングしてファイルを CSV形式で保存し、R に読み込ませて分析します。

データクレンジング

Google Forms からアンケート結果を xlsx形式でエクスポートすると、こんな感じになっています。

f:id:akiyoko:20171202163927p:plain


Excel関数を使ってチェックボックス形式のデータを整形します。
具体的には、別の Excelファイルを新規作成し、(選択肢として不要なので)「特に無い」「その他」の列を削除した後、以下のようにして「0」「1」のデータに変換します。

f:id:akiyoko:20171203003640p:plain


[ファイル]>[名前を付けて保存]から、ファイルを CSV 形式で保存します。
ファイル名は、例えば「factor_analysis.csv」など、日本語を使わない方が無難です(RStudio から読み込めない可能性があります)。

将棋,囲碁,チェス,ポーカー,麻雀,その他のボードゲーム・テーブルゲーム,TVゲーム・PCゲーム(携帯用を含む),映画鑑賞,音楽鑑賞,楽器演奏,演芸・演劇鑑賞,美術鑑賞,スポーツ観覧,ダンス,料理・お菓子作り,ガーデニング,読書,ネットサーフィン,パチンコ・パチスロ,競馬・競輪・競艇,カラオケ
0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0
0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0
1,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,1,1,0,0,0
(以下略)

 

RStudio にデータ投入

インストールしていない場合は、公式ダウンロードページ から RStudio をダウンロードしてインストールします。
私が使ったバージョンは、RStudio for Mac(Version 1.0.153)です。


作成した CSVファイルを読み込みます。

> data <- read.csv(file="~/Downloads/factor_analysis.csv", header=T, fileEncoding="Shift-JIS")
> head(data)
  将棋 囲碁 チェス ポーカー 麻雀 その他のボードゲーム.テーブルゲーム TVゲーム.PCゲーム.携帯用を含む. 映画鑑賞 音楽鑑賞 楽器演奏 演芸.演劇鑑賞 美術鑑賞 スポーツ観覧 ダンス 料理.お菓子作り
1    0    0      0        0    0                                   1                               0        0        0        0             0        0            0      0               0
2    0    1      0        0    0                                   0                               0        0        0        0             0        0            0      0               0
3    1    0      0        0    0                                   0                               0        0        0        0             0        0            1      0               0
4    1    1      0        0    1                                   1                               0        0        0        0             0        0            0      0               0
5    0    0      0        1    0                                   0                               0        0        0        1             0        0            0      0               0
6    0    0      0        0    0                                   0                               0        1        1        0             0        1            0      0               0
  ガーデニング 読書 ネットサーフィン パチンコ.パチスロ 競馬.競輪.競艇 カラオケ
1            0    0                1                 0              0        0
2            0    0                0                 0              1        0
3            0    1                1                 0              0        0
4            0    0                1                 0              0        0
5            0    0                0                 0              0        0
6            0    1                0                 0              0        0

上記は CSV ファイルのエンコード形式が「Shift-JIS」の場合の記述ですが、もし「UTF-8」にした場合は「fileEncoding="UTF-8"」とすれば OK です。


 

RStudio で因子分析

以降は、ほぼ「Rで因子分析やってみた」のままです。

まずは、因子数を決定します。

> c <- cor(data)
> e <- eigen(c)$values
> e
 [1] 2.7796088 2.6282309 1.7220938 1.6669475 1.4724370 1.3176913 1.2386144 1.0709480 0.9855064 0.8927945 0.7569210 0.6899642 0.6341069 0.6018854 0.5724795 0.4168670 0.3761065 0.3551432 0.3143882
[20] 0.2790165 0.2282491

固有値のグラフをスクリープロットとして出力します。

> plot(e, type="b", main="Scree Plot", xlab="Number", ylab="Eigenvalue")

f:id:akiyoko:20171203004038p:plain:w500


固有値の減少がなだらかになる直前までの固有値の数を因子数とする(スクリー基準)、および、因子数の基準となる固有値の最小値を「1」とする(カイザーガットマン基準)を考慮して、因子数を「6」としました。 *4, *5


最後に、因子数を 6 として因子分析をおこないます。

> factanal(x=data, factors=6, rotation="promax")

「rotation」の引数は、"none", "varimax", "promax" などがありますが、今回は、因子間の相関を仮定しないする(2017.12.26 訂正)プロマックス回転「 promax」を選択しました。 *6


f:id:akiyoko:20171203004437p:plain
f:id:akiyoko:20171203004450p:plain


この結果を因子負荷量の大小で色付けすると、以下の表のようになります。

f:id:akiyoko:20171203004907p:plain:w500


上記の表から、以下のように共通因子(趣味趣向クラスタ)を分類してみました。あくまでも仮説ですが。

  • 因子1:「麻雀」「囲碁」「将棋」の因子負荷量が大きい ・・・ 囲碁将棋系
  • 因子2:「美術鑑賞」「演芸・演劇鑑賞」の因子負荷量が大きい ・・・ アート系?
  • 因子3:「楽器演奏」「料理・お菓子作り」「ダンス」の因子負荷量が大きい ・・・ 音楽系?
  • 因子4:「競馬・競輪・競艇」「パチンコ・パチスロ」の因子負荷量が大きい ・・・ ギャンブル系
  • 因子5:「その他のボードゲーム・テーブルゲーム」「チェス」の因子負荷量が大きい ・・・ その他のボードゲーム系
  • 因子6:「映画鑑賞」「音楽鑑賞」の因子負荷量が大きい ・・・ オーソドックスな趣味系?


一部強引なところもあるかもしれませんが、アンケートに回答した人が「ああ、私はこの趣味趣向クラスタだな」と分かりやすいような分類になっているのではないかと思います。




 

まとめ

  • 因子分析は R でやれば超簡単
  • 数行で書けるよ

これを言うためだけに 8000字オーバーの記事を書いてしまいました。。



明日は、yamano357 さんの「R Advent Calendar 2017 - Qiita」 5日目の記事です。
よろしくお願いします。


 

おまけ

因子分析の結果表示でそれぞれの出力行がガタついて項目がズレてしまう場合は、
[Preferences]>[Appearance]から、Editor font に「Osaka-Mono」を選択すれば解決します(Mac の場合)。


f:id:akiyoko:20171203182418p:plain:w350



今回の場合はグラフ描画時に日本語を出力していませんが、RStudio でグラフを描画する際に文字化けしてしまう場合は、

par(family="HiraKakuProN-W3")

と事前に実行しておけばよいです。 *7

*1:《過去記事》akiyoko.hatenablog.jp

*2:今回はインドア系の趣味についてのみアンケートしました。

*3:選択肢に挙げた15種類の趣味は、総務省統計局が5年ごとに実施している「社会生活基本調査」(出典:平成28年 社会生活基本調査結果(総務省統計局))の「趣味・娯楽」の34種類の区分のうちの15種類と一致させているので、やろうと思えば、その種類別行動者数(≒趣味にしている人の割合)と照らし合わせることで世間一般の平均的な趣味趣向と比較することもできます。

*4:http://cogpsy.educ.kyoto-u.ac.jp/personal/Kusumi/datasem06/minemoto.pdf

*5:実際には「5」から「7」を順次選んで計算したところ、「6」が結論を導きやすかったという理由もあります。

*6:因子分析における因子軸の回転法について | Sunny side up!

*7:Rとウェブ解析:MACでグラフの日本語文字化けを防ぐ簡単な方法

「bitFlyer Drink Meetup! #9」に参加してきました

主催

bitFlyer

会場

株式会社bitFlyer 本社
東京都港区赤坂 9‐7‐1 ミッドタウン・タワー 8F



 

全体の感想など

11/28 から 11/30 までの直近3日間だけで

  • POSレジでの決済サービス開始 *1
  • 米国進出(bitFlyer USA Inc.) *2
  • FX 初のサーキットブレイク発動 *3

と(良くも悪くも)話題に事欠かない日本最大の仮想通貨取引所を運営する bitFlyer の勉強会に参加してきました。


bitFlyer ビットコインを始めるなら安心・安全な取引所で


国内シェアが8割、テレビCM を大量投入するなど、ビットコイン・仮想通貨の取引所としてはノリにノッている bitFlyer ですが、全銀協が推薦する実証実験プラットフォームベンダーに選出されたとの発表もあったことから、取引所以外にブロックチェーン自体にも注力していこうという方向性が窺えます。 *4


現在は「miyabi」という自社製ブロックチェーンをゼロから作っているとのことです。開発言語は C# で、チームがまだ小さいということもあってかお披露目はまだ当分先のようです。 *5



あと、会場はこんな感じで(私の写真ではありません)、六本木ミッドタウンの新オフィスに引っ越して 1ヶ月とのことでフロアも雰囲気もピカピカなオフィスでした。社員も90名に急増したとのことで、さすがノリノリですね(よく見ると床に刻み海苔らしきものが散らばってましたが、前日のイベントでピザでも食べたのでしょうか。まさにノリノリ)。




bitFlyer ビットコインを始めるなら安心・安全な取引所で



さて、LT の内容ですが、Hyperledger Sawtooth は今回初めて聞きました。PoET(Proof of Elapsed Time)も初耳です。

公式ドキュメント によると、Intel SGX のチップを使った Intel サーバ群を TEE(Trusted Execution Environments:信頼済み実行環境?)としたブロックチェーン上で、待ち時間をランダムに割り当てられたノードペアがブロックの承認をおこなうという仕様になっているようです(間違っていたらすいません)。

ただし PoET が動作するのは、Intel の分散台帳プラットフォーム「Sawtooth Lake」など限定的なブロックチェーン上のみのようで、実質 PoET はパブリックチェーンとしては利用できないということでしょうかね。
しかも、

実験用途にしか利用を推奨していない。
独自のコンセンサスアルゴリズムPoETを持つが、これは本来intelが提供するハードウェアを利用して行われるため完全版ではなく、オープンソース版ではシミュレータが用意されている。


開発は続けられているが、正式なプロダクトへの採用を勧めていない為、選択肢にはならない。


さまざまなブロックチェーン技術」より

とあるように、メインは実験用途とか。登壇者も「実務では使っていない」と言っていましたので、miyabi 開発のために他製品を調査してみたということなのかもしれません(実際、他の方も「社内勉強会の資料を外に出せるように手を入れた」と言っていました)。なお今回のデモは Docker のシミュレータ上で動作させるため、Intel SGX の TEE は利用しておらず、Mac でも問題なく動かせるというカラクリのようです。

また、(サンプルの ○✕ゲームの実装がそうなっているだけかもしれませんが、)Ether の Gas のようなトランザクション手数料の仕組みがないため、ノードのマイニングの報酬がなく、ノードを立てる経済インセンティブをどう設計するかについてはシステム上の懸念が残ります。というかそもそも、 Hyperledger 系プロダクトは分散台帳と暗号技術で守られた P2Pネットワーク、コンセンサスアルゴリズムを使いやすいように提供しているだけで、ブロックチェーン経済圏は範疇外ということなのかもしれません。

ブロックチェーンプラットフォームとしてメジャーなのはBitcoinとEthereumですが、それらとHyperledgerとの大きな違いは、bitcoinにとっての「bitcoin」、ethereumにとっての「ether」のような仮想通貨の単位がHyperledger には存在しないことです。Hyperledgerでは、純粋にブロックチェーンの持つ分散型台帳という特性を仮想通貨に限らず社会の様々なソリューションの技術基盤として汎用的に活用できるように開発されています。


Hyperledger入門 : Hyperledger(ハイパーレッジャー)って何? | BlockChain Online ブロックチェーンオンライン」より


Hyperledger プロジェクトの立ち位置については、http://doublehash.me/tag/hyper-ledger/ の図が分かりやすかったです。しかしながら Hyperledger Sawtooth はどちらかと言えば、Transaction and data は「Public」、Mining/Consensus は「Trusted(consensus)」(つまり図の左下のエリア)なんじゃないかな?と思いました。




まあそれはさておいて、(私が長年 Python を使ってきたということもあって)Python で任意のスクリプトを書けるのは面白いな、と思いました。
Python 製のブロックチェーンとしては他にも、

  • HydraChain
    • Ethereum の拡張版で、コンソーシアム型またはプライベート型のブロックチェーンを構築可能。Python でコントラクトを書けるのが特徴。
  • BigchainDB
  • DragonChain

などがありますが、Python で自由にコントラクトを記述できる有名どころとしては HydraChain が挙げられるでしょうか。ただし、HydraChain はノードが最低限 6台必要ということで検証用途としては Hyperledger Sawtooth に軍配が上がるということなのかもしれません(実際試してみましたが、Docker 上でデモを動かすのは非常に簡単でした)。



 

WindowsのDocker環境でブロックチェーンを動かしてみる

越智 佳景 氏(ブロックチェーンエンジニア 株式会社 bitFlyer)

  • Hyperledger
    • ビジネスのためのブロックチェーン技術 *6
    • Linux Foundationで開発
    • オープンソース
    • Sawtooth (ソウトゥース)は Hyperledger プロジェクトの一つで Intel が開発を主導 *7
  • PoW は参加者が限定されていない場合に有効
  • Sawtooth トランザクション
    • アプリ開発者が任意に設計できる
    • Validator が Transaction Processor(ビットコインのスクリプトに相当)に問い合わせ
    • ステートを変更する
  • Sawtooth ブロック
    • 代表ノードがブロックを作る
      • Intel SGX のチップ、Intel のサーバを信用する??
    • PoET(Proof of Elapsed Time:時間に応じてブロックを作れる可能性が高まる)
  • Docker
    • 3月あたりにEE(Enterprise)とCE(Community)に分かれた
    • 実行方法は二つ
      • Dockerfile(docker build . で Imageを作って docker run)
      • 複数コンテナをまとめて起動する場合は docker-compose.yaml(docker compose up でコンテナを起動)

なおブロックについては、チェーン内部にタイマーがあり、一定時間ごとに自動的にブロックが作られるようになっているとのこと。また State は、トランザクション外(メモリ上?)で管理されるそうです。




 

macOS の Docker環境で Hyperledger Sawtooth を動かす

ここから、私の macOS の Docker 上で Hyperledger Sawtooth のデモを動かしてみます。

環境は以下の通りです。

$ sw_vers
ProductName:    Mac OS X
ProductVersion: 10.12.6
BuildVersion:   16G1036

$ docker --version
Docker version 17.09.1-ce, build 19e2cf6


Sawtooth Enterprise Blockchain に事例が紹介されていますが、その他に ○✕ゲームがデモ用に実装されているので、それを Docker 上で動作させてみます。と言っても、発表の内容をなぞるだけですが。


まず、Hyperledger の sawtooth-core の GitHub から、以下の手順で sawtooth-core-1.0.0rc3.zip をダウンロードします。なお現時点での最新版は「v1.0.0rc3」。

f:id:akiyoko:20171201024521p:plain

f:id:akiyoko:20171201024759p:plain


docker/compose/sawtooth-default.yaml を開いて、以下のように shell をコピペして shell1, shell2 に書き換えます。

  ...

  shell1:
    image: hyperledger/sawtooth-all:1.0
    container_name: sawtooth-shell-default1
    expose:
      - 8008
      - 4004
    depends_on:
      - rest-api
    entrypoint: "bash -c \"\
        sawtooth keygen && \
        tail -f /dev/null \
        \""

  shell2:
    image: hyperledger/sawtooth-all:1.0
    container_name: sawtooth-shell-default2
    expose:
      - 8008
      - 4004
    depends_on:
      - rest-api
    entrypoint: "bash -c \"\
        sawtooth keygen && \
        tail -f /dev/null \
        \""

 
以下のコマンドを実行して、コンテナを起動します。

$ docker-compose -f ~/Downloads/sawtooth-core-1.0.0rc3/docker/compose/sawtooth-default.yaml up

しばらくすると、各種コンテナが起動します。

$ docker ps
CONTAINER ID        IMAGE                                       COMMAND                  CREATED             STATUS              PORTS                              NAMES
2efe61c116df        hyperledger/sawtooth-all:1.0                "bash -c 'sawtooth..."   16 minutes ago      Up 15 minutes       4004/tcp, 8008/tcp                 sawtooth-shell-default1
9d14523518bb        hyperledger/sawtooth-all:1.0                "bash -c 'sawtooth..."   16 minutes ago      Up 15 minutes       4004/tcp, 8008/tcp                 sawtooth-shell-default2
59f216a70497        hyperledger/sawtooth-settings-tp:1.0        "settings-tp -vv -..."   16 minutes ago      Up 15 minutes       4004/tcp                           sawtooth-settings-tp-default
0f0d651f61b3        hyperledger/sawtooth-rest-api:1.0           "sawtooth-rest-api..."   16 minutes ago      Up 16 minutes       4004/tcp, 0.0.0.0:8008->8008/tcp   sawtooth-rest-api-default
f17d965f771b        hyperledger/sawtooth-xo-tp-python:1.0       "xo-tp-python -vv ..."   16 minutes ago      Up 16 minutes       4004/tcp                           sawtooth-xo-tp-python-default
2ae2e16405f2        hyperledger/sawtooth-intkey-tp-python:1.0   "intkey-tp-python ..."   16 minutes ago      Up 15 minutes       4004/tcp                           sawtooth-intkey-tp-python-default
25803f8bec59        hyperledger/sawtooth-validator:1.0          "bash -c 'sawadm k..."   16 minutes ago      Up 16 minutes       0.0.0.0:4004->4004/tcp             sawtooth-validator-default


次に、別々のターミナル上で

《ターミナル 1》

$ docker exec -it sawtooth-shell-default1 bash

《ターミナル 2》

$ docker exec -it sawtooth-shell-default2 bash

を実行し、起動した 2つの shell クライアントのコンテナにそれぞれログインします。


xo の遊び方、コマンドなどの仕様については、以下を参照。


《ターミナル 1》

### user1 用の鍵を作成
# sawtooth keygen user1
writing file: /root/.sawtooth/keys/user1.priv
writing file: /root/.sawtooth/keys/user1.pub

### ゲームを新規作成
# xo create --url http://rest-api:8008 --username user1 game1
Response: {
  "link": "http://rest-api:8008/batch_statuses?id=5ebd578b0c6800460bcf2e53cd8275f2e8266fee9e9fd421f94f7b92d0b785fe28debe5c0a986fb44c784df7a1e35cf678d8f3fe3e3255fcc1fe0b710420cbd8"
}

### ゲームが作成されたか確認
# xo list --url http://rest-api:8008
GAME            PLAYER 1        PLAYER 2        BOARD     STATE
game1                                           --------- P1-NEXT

### user1 が一手目を打つ
# xo take --url http://rest-api:8008 --username user1 game1 1
Response: {
  "link": "http://rest-api:8008/batch_statuses?id=19189296519d8ced6d94902203004607532bb59b5dd8b75fcc5ff99022dc02fb54e26c6618dec172d27e09cb7808d3f2b14aac7cdece01960a321b532673afe7"
}

### ゲームの状況を確認
# xo show --url http://rest-api:8008 game1
GAME:     : game1
PLAYER 1  : 03a8de
PLAYER 2  :
STATE     : P2-NEXT

  X |   |
 ---|---|---
    |   |
 ---|---|---
    |   |


《ターミナル 2》

### user2 用の鍵を作成
# sawtooth keygen user2
writing file: /root/.sawtooth/keys/user2.priv
writing file: /root/.sawtooth/keys/user2.pub

### ゲームの一覧を確認
# xo list --url http://rest-api:8008
GAME            PLAYER 1        PLAYER 2        BOARD     STATE
game1           03a8de                          X-------- P2-NEXT

### user2 が 2手目を打つ
# xo take --url http://rest-api:8008 --username user2 game1 3
Response: {
  "link": "http://rest-api:8008/batch_statuses?id=1d33ab7613cb9cffc5813502b1a47b1f9ea78d291fe2ce69187bd6128034593f0889eba850cf7e92e32db0f702cbc55e61508d1e743dd3fad19c2a47cd574792"
}

### 試合のステータスを確認
# xo show --url http://rest-api:8008 game1
GAME:     : game1
PLAYER 1  : 03a8de
PLAYER 2  : 039346
STATE     : P1-NEXT

  X |   | O
 ---|---|---
    |   |
 ---|---|---
    |   |

という感じで、xo-tp-python がトランザクションを処理しています。
もちろん鍵が合わないユーザーは、間違った順番で take できないように検証がおこなわれます。

なおブロックは、チェーン内部にタイマーがあり、一定時間ごとに自動的にブロックが作られるようになっているとのこと。ちなみに、State はトランザクション外(メモリ上?)で管理されるということです。