Slide 1

Slide 1 text

Tendermintをさわってみる 2018.09.03 坪井有花 @__kyrieleison__ ビットコインとか勉強会 #21

Slide 2

Slide 2 text

- Webエンジニア / 株式会社TRUSTDOCK - 本人確認をAPIで提供している会社です - 過去にブロックチェーン x 本人確認の実証実験を
 していました - 趣味で Dapps 開発をして遊んでいます 坪井有花 @__kyrieleison__

Slide 3

Slide 3 text

目的 - Tendermintの概要を知る - Tendermintのノードを起動したり、アプリケーションコードを読んだり、実行したりすること を通じて、Tendermintで何ができるのかを理解する - EthermintやCosmosのような、Tendermintをベースとしたブロックチェーンについて知り、 スケーラビリティ問題を解決するための手札を増やす (…ための足がかりにする) 本発表を通じて、こんな目的が達成できたらよいなと考えております よろしくお願いいたします

Slide 4

Slide 4 text

スケーラビリティ問題について

Slide 5

Slide 5 text

スケーラビリティ問題を解決するアプローチ - On-chain / 1st layer - コンセンサスアルゴリズムの改善 - Casper (Proof of Stake): 通貨の保有量に応じてマイナーを選出することで、計算を必要とする Proof of Work よりも高速にコンセンサスを得られる - 処理の並列化 - Sharding: トランザクションを分割し、ノードグループ毎に割り当てることで並列処理を可能にする - Off-chain / 2nd layer - ステートチャネルで処理 - Raiden Network: ペイメントチャネルで取引を行い、チェーンには最新の状態だけを記録することで、 取引を早く安く行える - サイドチェーンで処理 - Plasma: 子チェーンでトランザクションを処理し、親チェーンにはブロックのハッシュだけを記録することで、 トランザクションの処理を早く安く行える

Slide 6

Slide 6 text

- On-chain / 1st layer - コンセンサスアルゴリズムの改善 - Casper (Proof of Stake): 通貨の保有量に応じてマイナーを選出することで、計算を必要とする Proof of Work よりも高速にコンセンサスを得られる - 処理の並列化 - Sharding: トランザクションを分割し、ノードグループ毎に割り当てることで並列処理を可能にする - Off-chain / 2nd layer - ステートチャネルで処理 - Raiden Network: ペイメントチャネルで取引を行い、チェーンには最新の状態だけを記録することで、 取引を早く安く行える - サイドチェーンで処理 - Plasma: 子チェーンでトランザクションを処理し、親チェーンにはブロックのハッシュだけを記録することで、 トランザクションの処理を早く安く行える スケーラビリティ問題を解決するアプローチ Tendermint

Slide 7

Slide 7 text

- On-chain / 1st layer - コンセンサスアルゴリズムの改善 - Casper (Proof of Stake): 通貨の保有量に応じてマイナーを選出することで、計算を必要とする Proof of Work よりも高速にコンセンサスを得られる - 処理の並列化 - Sharding: トランザクションを分割し、ノードグループ毎に割り当てることで並列処理を可能にする - Off-chain / 2nd layer - ステートチャネルで処理 - Raiden Network: ペイメントチャネルで取引を行い、チェーンには最新の状態だけを記録することで、 取引を早く安く行える - サイドチェーンで処理 - Plasma: 子チェーンでトランザクションを処理し、親チェーンにはブロックのハッシュだけを記録することで、 トランザクションの処理を早く安く行える スケーラビリティ問題を解決するアプローチ Tendermintをベースとしたブロックチェーン Cosmos, Ethermint Tendermint

Slide 8

Slide 8 text

Tendermint

Slide 9

Slide 9 text

Tendermint セキュアかつスケーラブルなブロックチェーンを誰でも容易に構築するための コンセンサスエンジンとアプリケーションインターフェースをパッケージングしたソフトウェア Tendermint コンセンサスエンジン Tendermint Core アプリケーションインターフェース Application BlockChain Interface (ABCI)

Slide 10

Slide 10 text

セキュアかつスケーラブルなブロックチェーンを誰でも容易に構築するための コンセンサスエンジンとアプリケーションインターフェースをパッケージングしたソフトウェア 特徴 - 1秒あたり数千トランザクションを処理できる - ブロック生成後すぐにファイナリティを得られる - 3分の1のノードが停止、または悪意を持った振る舞いをしても安全 - 任意のプログラミング言語でブロックチェーンプロトコルの実装ができる ブロックチェーンプロトコルの開発者は、Tendermintを用いることで コンセンサスアルゴリズムやP2Pネットワークのセキュリティやスケーラビリティを意識せず また特定のプログラミング言語にも縛られずに 独自のブロックチェーンプロトコルを開発することができる

Slide 11

Slide 11 text

Tendermintで実装されているブロックチェーン Tendermintで実装されたこれらのブロックチェーンが実用段階になれば Dapps開発者にとっても、これまで開発したDappsをそのままに よりスケーラブルなブロックチェーンに乗り換えることができるかもしれない Ethermint EVMを実装しており web3やsolidityとの互換性がある EthereumのDappsを処理できる Cosmos Tendermintで実装されたチェーン同士は 相互にメッセージをやりとりできる 異なるチェーン間でのトークン移転を容易にする

Slide 12

Slide 12 text

Application BlockChain Interface (ABCI)

Slide 13

Slide 13 text

Application BlockChain Interface (ABCI) 1台のマシン上でのステートマシン(= アプリケーションロジック)と 複数のマシンへステートマシンを複製する仕組み(= コンセンサスエンジン)との間に シンプルなインターフェースを提供することで、それぞれの関心事を分離する コンセンサスエンジン ステートに対するトランザクションが すべてのマシンに同じ順序で複製されることを保証する アプリケーションロジック トランザクションを検証し、OKなら トランザクションを実行してステートを更新する ABCI

Slide 14

Slide 14 text

メッセージプロトコル アプリケーションロジックとコンセンサスエンジンとの間のインターフェースは、 リクエストとレスポンスのペアで構成される”メッセージ”として定義される コンセンサスエンジンがリクエストを行い、アプリケーションロジックがレスポンスを行う レスポンス リクエスト ABCI ABCI サーバ ABCI クライアント アプリケーションロジック コンセンサスエンジン

Slide 15

Slide 15 text

メッセージプロトコル メッセージはGoogleが開発しているデータフォーマット”Protocol Buffer”で定義する 主要なメッセージタイプとしてCheckTx, DeliverTx, Commit等がある - CheckTx - リクエストされたトランザクションの検証を行う - DeliverTx - リクエストされたトランザクションの検証と実行を行い、アプリケーションステートを更新する - Commit - 現在のアプリケーションステートのルートハッシュを計算する - レスポンスとして返却されたルートハッシュを次のブロックのヘッダにセットする

Slide 16

Slide 16 text

Go JavaScript Python C++ Java 任意のプログラミング言語でABCIを使う場合、その言語でのABCIサーバ実装が必要となる クライアントとの通信には、GRPCかソケット通信のいずれかを選択する ABCIサーバ ABCI レスポンス リクエスト ABCI サーバ ABCI クライアント アプリケーションロジック コンセンサスエンジン

Slide 17

Slide 17 text

ABCIクライアントはコンセンサスエンジンであるTendermint Coreが担うため、 通常の場合は実装する必要はない “abci-cli”というテストツールを用いて、コマンドラインからリクエストすることも可能 ABCIクライアント ABCI レスポンス リクエスト ABCI サーバ ABCI クライアント アプリケーションロジック コンセンサスエンジン abci-cli or

Slide 18

Slide 18 text

ブロックチェーンプロトコル ABCIはコネクション指向で、メッセージのやりとりにはコネクションを確立する タイミングと用途に応じて、3つのコネクションを明示的に使い分ける - Mempool Connection - ユーザからトランザクションを受け取ったときに確立するコネクション - Consensus Connection - コンセンサスの得られた新しいブロックがコミットされたときに確立するコネクション - Query Connection - アプリケーションステートの状態を問い合わせるときに確立するコネクション

Slide 19

Slide 19 text

Mempool Connection ユーザからトランザクションを受け取ったときに確立するコネクション CheckTXメッセージを送ってトランザクションを検証し、 受け取ったトランザクションを他のノードにブロードキャストするかどうかを判断する ABCI ABCI サーバ ABCI クライアント アプリケーションロジック コンセンサスエンジン 2. CheckTXメッセージを送信 4. OK or NG を返却 3. トランザクションを検証 5. OKならメモリプールに溜 めておき、受け取ったの と同じ順序で他のノード にブロードキャストする。 NGなら破棄する 1. トランザクションを 受け取る

Slide 20

Slide 20 text

Consensus Connection コンセンサスの得られた新しいブロックがコミットされたときに確立するコネクション BeginBlock, [DeliverTX, ...], EndBlock, Commit の一連のメッセージを送って ブロックのすべてのトランザクションを実行し、次のブロック生成の準備をする ABCI ABCI サーバ ABCI クライアント アプリケーションロジック コンセンサスエンジン 4. ステートのルートハッシュを返却 3. DeliverTXで送られた トランザクションを検証・ 実行してステートを更新 する 5. ステートのルートハッシュを 次のブロックのヘッダにセッ トする 1. コンセンサスを得ら れた新しいブロック がチェーンにコミット される 2. BeginBlock, [DeliverTX,…], EndBlock, Commitメッセージ を送信

Slide 21

Slide 21 text

Query Connection アプリケーションステートの状態を問い合わせるときに確立するコネクション 最後にコミットしたBlockHeightやルートハッシュを問い合わせるInfoメッセージや アプリケーションステートのデータを問い合わせるQueryメッセージ等を処理する ABCI ABCI サーバ ABCI クライアント アプリケーションロジック コンセンサスエンジン 1. Queryメッセージ等を送信 2. 結果を返却

Slide 22

Slide 22 text

Tendermint Core

Slide 23

Slide 23 text

Tendermint Core 同じトランザクションが同じ順序で、すべてのマシンに複製されることを保証する 低レイヤなプロトコル コンセンサスアルゴリズムとP2Pネットワークプロトコルで構成される Tendermint Core アプリケーションロジック ABCI コンセンサスアルゴリズム P2Pネットワーク

Slide 24

Slide 24 text

コンセンサスアルゴリズム 部分的に非同期で、決定論的な BFT-based PoS - 部分的に非同期 - トランザクションを収集/検証/拡散するのに特定の時間を設定する(Bitcoinは10分、 Ethereumは15秒) = 同期的 - タイムアウトするまで非同期で続く = 部分的非同期, 弱い同期 - 決定論的 - ランダム性がなく、完全に決定論的にプロポーザーを選出する - 通貨の保有量に応じた加重ラウンドロビン方式でローテーションする Chain-based PoS (Casper) と BFT-based PoS との違いについては Consensus Compare: Casper vs. Tendermint を参照してください

Slide 25

Slide 25 text

コンセンサスを得るまでのステップ

Slide 26

Slide 26 text

コンセンサスを得るまでのステップ 2. Pre-Vote 1. Propose 4. Commit 3. Pre-Commit

Slide 27

Slide 27 text

コンセンサスを得るまでのステップ 1. Transaction Submittion - ユーザからトランザクションが送られるとローカルのMempoolキャッシュに保持される - ABCIのMempool Connectionでトランザクションがアプリケーションで検証され、ローカ ルのMempoolに保持された後、他ノードのMempoolにブロードキャストされる 2. Propose - P2Pネットワークに参加するノード(バリデータ)の中から、通貨保有量に応じた加重ラウン ドロビン方式で”プロポーザー”が選ばれる - メモリプールに溜まっているトランザクションを近隣のバリデータにブロードキャストする

Slide 28

Slide 28 text

コンセンサスを得るまでのステップ 3. Pre-Vote - 提案されたブロックに1回目の投票(署名)を行う - 2/3以上のバリデータが投票し終わるか、タイムアウトに達するまで待つ - 投票が集まればすぐに次のステップに進むことができる = 部分的非同期 4. Pre-Commit - Pre-Voteで2/3以上のバリデータが投票したブロックに、2回目の投票(署名)を行う - 2/3以上のバリデータが投票し終わるか、タイムアウトに達するまで待つ - 1ラウンドでPre-Commitできるのは1度だけ。そのため、同時に別のブロックがPre- Commitされることはなく、フォークが発生しない = すぐにファイナリティが得られる

Slide 29

Slide 29 text

コンセンサスを得るまでのステップ 5. Commit - 2/3以上のバリデータからの投票が集まったブロックが、ブロックチェーンにコミットされる - ABCIのConsensus Connectionでアプリケーションステートが更新される - 投票が集まらなかったブロックは、次のラウンドに回される

Slide 30

Slide 30 text

Tendermintをさわってみる

Slide 31

Slide 31 text

https://tendermint.com/docs/ introduction/install.html Tendermintのインストール GCPでUbuntu 18.04のVMインスタンスを作成し、セットアップしました

Slide 32

Slide 32 text

ルートディレクトリの初期化: $HOME/.tendermint 下に秘密鍵やチェーンの初期定義ファイルが生成される $ tendermint init I[09-04|14:50:24.402] Generated private validator module=main path=/root/.tendermint/config/ priv_validator.json I[09-04|14:50:24.403] Generated node key module=main path=/root/.tendermint/config/ node_key.json I[09-04|14:50:24.403] Generated genesis file module=main path=/root/.tendermint/config/ genesis.json $ tendermint node --proxy_app=kvstore I[09-04|14:50:33.146] Starting multiAppConn module=proxy impl=multiAppConn I[09-04|14:50:33.146] Starting localClient module=abci-client connection=query impl=localClient I[09-04|14:50:33.146] Starting localClient module=abci-client connection=mempool impl=localClient I[09-04|14:50:33.146] Starting localClient module=abci-client connection=consensus impl=localClient I[09-04|14:50:33.146] ABCI Handshake module=consensus appHeight=0 appHash= I[09-04|14:50:33.146] ABCI Replay Blocks module=consensus appHeight=0 storeHeight=0 stateHeight=0 I[09-04|14:50:33.148] Completed ABCI Handshake - Tendermint and App are synced module=consensus appHeight=0 appHash= ノードの起動(1): kvstoreというサンプルアプリケーションをインプロセスで起動し、ABCIハンドシェイクをして接続する

Slide 33

Slide 33 text

ノードの起動(2): ノードがバリデータとして起動し、周辺のピアと接続しにいこうとする (が、見つからないため1ノードで続行する) ノードの起動(3): コンセンサスが開始され、プロポーザーとして選出される。プロポーザルブロックを生成する I[09-04|14:50:33.148] This node is a validator module=consensus addr=11C18BAB5694F38F8A2AC7A8FEDC90C62D320700 pubKey=PubKeyEd25519{9E12F91773DCCE385FC02778AB7BB94D9C0D2249C70F44AEA7179758FBF03F86} I[09-04|14:50:33.361] Starting Node module=main impl=Nodeactor … 中略 … I[09-04|14:50:33.368] Started node module=main nodeInfo="NodeInfo{id: d662eb55503a3934ec72a6636db84a539f9ce5fe, moniker: instance-2, network: test-chain-HVlSTN [listen 10.142.0.2:26656], version: 0.23.0-013b9cef ([amino_version=0.10.1 p2p_version=0.5.0 consensus_version=v1/0.2.2 rpc_version=0.7.0/3 tx_index=on rpc_addr=tcp://0.0.0.0:26657])}" I[09-04|14:50:33.368] Ensure peers module=p2p numOutPeers=0 numInPeers=0 numDialing=0 numToDial=10 I[09-04|14:50:33.368] No addresses to dial nor connected peers. Falling back to seeds module=p2p E[09-04|14:50:33.368] Couldn't connect to any seeds module=p2p I[09-04|14:50:34.357] enterNewRound(1/0). Current: 1/0/RoundStepNewHeight module=consensus height=1 round=0 I[09-04|14:50:34.357] enterPropose(1/0). Current: 1/0/RoundStepNewRound module=consensus height=1 round=0 I[09-04|14:50:34.357] enterPropose: Our turn to propose module=consensus height=1 round=0 proposer=11C18BAB5694F38F8A2AC7A8FEDC90C62D320700 privValidator="PrivValidator{11C18BAB5694F38F8A2AC7A8FEDC90C62D320700 LH:0, LR:0, LS:0}" I[09-04|14:50:34.360] Signed proposal module=consensus height=1 round=0 proposal="Proposal{1/0 1:08E44C262B06 (-1,:0:000000000000) 05A0C21B1A54 @ 2018-09-04T14:50:34.358047426Z}" I[09-04|14:50:34.363] Received proposal module=consensus proposal="Proposal{1/0 1:08E44C262B06 (-1,:0:000000000000) 05A0C21B1A54 @ 2018-09-04T14:50:34.358047426Z}" I[09-04|14:50:34.369] Received complete proposal block module=consensus height=1 hash=048C7EC62CF3BB8C145F96517AAB93262F762B7962B79

Slide 34

Slide 34 text

ノードの起動(4): Pre-Vote ノードの起動(5): Pre-Commit I[09-04|14:50:34.369] enterPrevote(1/0). Current: 1/0/RoundStepPropose module=consensus I[09-04|14:50:34.369] enterPrevote: ProposalBlock is valid module=consensus height=1 round=0 I[09-04|14:50:34.372] Signed and pushed vote module=consensus height=1 round=0 vote="Vote{0:11C18BAB5694 1/00/1(Prevote) 048C7EC62CF3 FB3D599C0A0D @ 2018-09-04T14:50:34.369900185Z}" err=null I[09-04|14:50:34.374] Added to prevote module=consensus vote="Vote{0:11C18BAB5694 1/00/1(Prevote) 048C7EC62CF3 FB3D599C0A0D @ 2018-09-04T14:50:34.369900185Z}" prevotes="VoteSet{H:1 R:0 T:1 +2/3:048C7EC62CF3BB8C145F96517AAB93262F762B79:1:08E44C262B06(1) BA{1:x} map[]}” I[09-04|14:50:34.375] enterPrecommit(1/0). Current: 1/0/RoundStepPrevote module=consensus height=1 round=0 I[09-04|14:50:34.375] enterPrecommit: +2/3 prevoted proposal block. Locking module=consensus height=1 round=0 hash=048C7EC62CF3BB8C145F96517AAB93262F762B79 I[09-04|14:50:34.377] Signed and pushed vote module=consensus height=1 round=0 vote="Vote{0:11C18BAB5694 1/00/2(Precommit) 048C7EC62CF3 E6A1CD8E697A @ 2018-09-04T14:50:34.375424414Z}" err=null I[09-04|14:50:34.380] Added to precommit module=consensus vote="Vote{0:11C18BAB5694 1/00/2(Precommit) 048C7EC62CF3 E6A1CD8E697A @ 2018-09-04T14:50:34.375424414Z}" precommits="VoteSet{H:1 R:0 T:2 +2/3:048C7EC62CF3BB8C145F96517AAB93262F762B79:1:08E44C262B06(1) BA{1:x} map[]}” ノードの起動(6): Commit I[09-04|14:50:34.380] enterCommit(1/0). Current: 1/0/RoundStepPrecommit module=consensus height=1 commitRound=0 I[09-04|14:50:34.380] Commit is for locked block. Set ProposalBlock=LockedBlock module=consensus height=1 commitRound=0 blockHash=048C7EC62CF3BB8C145F96517AAB93262F762B79 I[09-04|14:50:34.381] Finalizing commit of block with 0 txs module=consensus height=1 hash=048C7EC62CF3BB8C145F96517AAB93262F762B79 root=

Slide 35

Slide 35 text

I[09-04|14:50:34.381] Block{ Header{ ChainID: test-chain-HVlSTN Height: 1 Time: 2018-09-04 14:50:34.357894057 +0000 UTC NumTxs: 0 TotalTxs: 0 LastBlockID: :0:000000000000 LastCommit: Data: Validators: A84F985E84234524C58721C7BF452D4E73A48B88 App: Consensus: D6B74BB35BDFFD8392340F2A379173548AE188FE Results: Evidence: }#048C7EC62CF3BB8C145F96517AAB93262F762B79 Data{ }# EvidenceData{ }# Commit{ BlockID: :0:000000000000 Precommits: }# }#048C7EC62CF3BB8C145F96517AAB93262F762B79 module=consensus I[09-04|14:50:34.388] Executed block module=state height=1 validTxs=0 invalidTxs=0 I[09-04|14:50:34.391] Committed state module=state height=1 txs=0 appHash=0000000000000000 module=txindex height=1 ノードの起動(7): 新しいブロックが生成され、アプリケーションステートもコミットされる

Slide 36

Slide 36 text

https://tendermint.com/docs/ tendermint-core/using- tendermint.html より詳しくはこちら Tendermintノードの実行、トランザクションの発行、バリデータの追加 etc…

Slide 37

Slide 37 text

https://github.com/ tendermint/js-abci ABCIサーバのJS実装 js-abci とサンプルコード

Slide 38

Slide 38 text

let createABCIServer = require(‘abci') let state = { count: 0 } let handlers = { // …中略… deliverTx (request) { let tx = padTx(request.tx) // padTxはトランザクションデータが4bytesかチェックする関数 let number = tx.readUInt32BE(0) if (number !== state.count) { return { code: 1, log: 'tx does not match count' } } state.count += 1 // 検証がOKならステートを更新 return { code: 0, log: 'tx succeeded' } } } let port = 26658 createABCIServer(handlers).listen(port, () => { console.log(`listening on port ${port}`) }) js-abciを用いたアプリケーションロジックのサンプル: トランザクション毎にカウントアップしてステートに保持する

Slide 39

Slide 39 text

Tendermintは、ステートの複製に関することを気にせず、プログラミング言語に縛られず セキュアでスケーラブルなブロックチェーンを容易に構築可能 今よりパワフルなブロックチェーンが続々と登場する可能性 ブロックチェーンプロコトル開発の敷居が下がり、Dapps開発の選択肢も広がる 今ある基盤がひっくり返るかもしれない まとめ Tendermint Core セキュアでスケーラブルなコンセンサスアルゴリズムと P2Pネットワークを提供 ABCI コンセンサスエンジンとアプリケーションロジックを 分離するインターフェースを提供