Tendermint Essentials Vol.1 ~Tendermint Core & ABCI~
Cosmos SDKや同SDKを使用したブロックチェーンの基盤となっているコンポーネントが『Tendermint』です。Tendermintはビザンチン耐性を持ち、分散型システムにおいてコンセンサス(合意形成)を提供するソフトウェアです。この記事ではTendermintの基本的なコンポーネントであるTendermint CoreとABCI(Application Blockchain Interface)を取り上げたいと思います。
この記事は以下の順序に沿って進んでいきます。必要に応じて読み飛ばしてください。
- Tendermintとは
- ABCI(Application Blockchain Interface)
- コンセンサス形成
- ハードスプーン
- Tendermintインストール(Go言語)
Tendermintとは
TendermintはBFT(Byzamtine Fault Tolerant)、ビザンチン耐性のあるSMR(State Machine Replication)を実行するソフトウェアです。
ビザンチン将軍問題に対応できることをビザンチン耐性があると言いますが、この問題は古くから多くの研究があり詳細な説明があるため、ここでは説明を割愛させて頂きます。分散型のネットワーク上で暗号学とハッシュを活用した台帳、つまりブロックチェーン技術に応用できるものとしてビザンチン将軍問題は近年活発に議論されてきました。[1]
Tendermintはブロックチェーン等の分散型アプリケーションに、簡単に適用でき、またスケーラブルなソリューションを展開できるように開発されています。
Tendermintには2つのコンポーネントがあります。
- Tendermint Core
ステートを各ノードに決定した順序で記録するコンセンサスエンジン - ABCI(Application Blockchain Interface)
ブロックチェーンとやり取りするためのインターフェース(上位はどのようなプログラミング言語でも選択可能です)
Tendermintは既存の技術とどう異なるのか説明していきます。公式サイトの説明です。[2]
・分散型の『Key-Value』ストアとは異なる
Zookeeper/etcd/consulはすべてBFTではないアルゴリズムの上に実装されている分散型のKey-Valueストアです。典型的なケースで、3つから5つのノードでクラスタを作成し、半数までのノードの障害に耐えられます。しかしBFTではないために悪意のあるノードに対する耐性がありません。BFTの必要ないシステムや他の機構によってBFTの耐性を持たせる場合には、これらのシステムを採用することも可能です。TendermintはBFT(Byzamtine Fault Tolerant)です。
・ビットコインやEthereumとは異なる
TendermintはコンセンサスにおいてPoS(Proof-of-Stake)を実装できますが、必ずしも必要ではありません。ノードがネットワークに参加してブロック生成を行う過程では、その権限をトークンによる持ち分比率で行うことも、他の方法を選択することも可能です。
Validators are expected to be online, and the set of validators is permissioned/curated by some external process. Proof-of-stake is not required, but can be implemented on top of Tendermint consensus. That is, validators may be required to post collateral on-chain, off-chain, or may not be required to post any collateral at all.
Tendermintのコンセンサスエンジンはプラグ&プレイです。他のアプリケーションのステート状態を保持するGeneral Purpose Blockchain(GPB)として使用でき、他のブロックチェーンのコンセンサス部分をTendermintで置き換えることもできるようになっています。Tendermintはブロックチェーンエンジンです。ビットコインやEthereumのようにモノリシック(一枚岩)ではありません。
ABCI(Application Blockchain Interface)
Tendermint Coreがコンセンサスエンジンとしてトランザクションの処理やブロック生成を行ってくれる一方、開発者はABCI(Application Blockchain Interface)を橋渡しとして利用することでアプリケーションロジックの記述に専念できます。ABCIを介してAPIを使用するようにして、アプリケーション側からTendermint Coreとメッセージをやり取りできます。
以下の図は公式のものですが、アプリケーションとTendermint Core間の3つの接続を表しています。
- アプリケーションからMempoolへのトランザクション処理のための接続(上部)
- ブロック生成のためコンセンサスエンジンへの接続(下部上)
- アプリケーションロジックの呼び出し(下部下)
ABCIの主要メッセージです。
- InitChain —genesis ファイルを用いてブロックチェーンを最初に生成する際に呼ばれます。genesis ファイルの情報から生成される最初のアプリケーションの状態を返す必要があり、このアプリケーションの状態が初期状態として1番目のブロックのトランザクションに取り込まれます。
- CheckTx — トランザクションはブロックに取り込まれる前にTendermintのmempool(トランザクションを処理するところ)に入りますが、その前に各トランザクションは検証されます。ここではトランザクションがデコードできるかやトランザクションが含むメッセージがアプリケーション側にあるかなど基本的な検証のみ実施されます。
- DeliverTx — ブロックチェーンのトランザクションは全てこのメッセージを通して呼び出されます。アプリケーション側で受け取ったトランザクションを解釈してロジックを実行します。アプリケーションはステータスコードを返す必要があります。
- Commit — ブロック内のトランザクションが処理されると、アプリケーションロジックはハッシュ(マークルルートハッシュ)を返します。このメッセージによってステートハッシュはバリデータによって署名され、次のブロックに取り込まれます。この時点のアプリケーションの状態をコミットするために必要なメッセージです。
- BeginBlock — バリデータ(提案者)から合意が得られた(2/3以上)場合に新しいブロックを生成しますが、その際にコールされるメッセージです。アプリケーションロジックによって規定することも、Tendermintのブロックタイムに合わせて呼び出すことも可能です。
- EndBlock — 各ブロックの終わりに呼び出されるメッセージです。アプリケーション側から呼び出すように規定することも、Tendermintのブロックタイムに合わせることも可能です。EndBlockはバリデータ(提案者)の更新を含むこともできます。従ってネットワークから取り除かれたバリデータや新しい参加者はここで反映されることになります。
- Query — ユーザによって呼ばれるメッセージです。データ部を伴い、渡されたデータはアプリケーション側で処理や返り値を決定します。
より詳細な情報は公式のGithubで公開されています。[4]
コンセンサス形成
BFT(Byzamtine Fault Tolerant)、ビザンチン耐性のあるコンセンサスアルゴリズムがどう働くかを示した図です。上中央の『Propose』から処理が始まります。青色の線だけを追うと以下のように進みます。
- 新しいブロックがプロポーズされる
- ブロックに問題がなければPrevoteする
- 2/3以上がPrevoteしたらブロックをPrecommitする
- 2/3以上がPrecommitしたらブロックをコミットする
- 新しいブロック高が得られる
ここでブロックの生成やコミットなどに係るノードをバリデータ(提案者)と呼びます。PoS(Proof-of-Stake)のブロックチェーンではお馴染みですが、Tendermintの場合においても、2/3はノードの数ではなく投票できる力の比率です。
従ってCosmos Hubで行われているようにトークンを発行してバリデータの内のそのトークン保有比率で計算することができて、多くのトークン保有者に大きな権利を与えられるようになっています。また二重署名などを違反行為として定義し、違反した場合には、トークンを毀損するペナルティを設けることも可能です(ここは自身でコーディングする必要がありますが、Cosmos Hubのスラッシングの機能です)。
ハードスプーン
EthermintというTendermintを用いたEthereumの実装をご紹介しました。この実装はただEthereumのアーキテクチャをTendermintの上に複製しただけでなく、ETHの保有者のアカウントや値を保持し、Ethermint VM Zoneにペッグできるようになっています。EthereumのETHを持っているユーザはEVM側でトークンをPhotonとして再現できます。
EthermintのPhotonがCosmos Hubではフィートークンとして使用されるように設計されていて、OmiseGo、0x、FOAMなども同様のハードスプーンを計画しています。[5]
“Hard spoon: a new chain that takes into account state from an existing chain; not to compete, but to provide broad access.” — Jae Kwon
Tendermintインストール(Go言語)
Tendermint CoreはGo言語で書かれたパッケージとして提供されています。概略を紹介してきましたが、簡単なサンプルアプリを動かしてイメージを掴みたいと思います。
まずはGoでTendermintをインストールしてください。ここではUbuntu 16.04でGo バージョン1.12.5を使用しました。[6]
gvmを利用しています。 abci-cli
はコマンドラインでABCIメッセージを送ることができるツールです。このツールも導入します。
$ gvm install go1.12.5 -B
$ mkdir -p $GOPATH/src/github.com/tendermint
$ cd $GOPATH/src/github.com/tendermint
$ git clone https://github.com/tendermint/tendermint.git
$ cd tendermint
$ make get_tools
$ make install_abci
$ make build
abci-cli
を使用して kvstore
のアプリケーションを立ち上げます。このアプリはトランザクションをキーバリューの形でマークルツリーに保存するサンプルです。ABCIのメッセージを受け取って動作し、挙動の確認が簡単にできます。
$ abci-cli kvstore
I[2019-07-24|21:05:35.071] Starting ABCIServer module=abci-server impl=ABCIServer
I[2019-07-24|21:05:35.083] Waiting for new connection... module=abci-server
アプリケーションが接続を待ち受けますので、別のターミナルを立ち上げてTendermintを起動してください。
$ tendermint version
0.32.1-3a1f8768
$ tendermint init
I[2019-00-00|21:46:00.632] Generated private validator module=main keyFile=/home/.tendermint/config/priv_validator_key.json stateFile=/home/.tendermint/data/priv_validator_state.json
I[2019-07-25|21:46:00.633] Generated node key module=main path=/home/.tendermint/config/node_key.json
I[2019-07-25|21:46:00.633] Generated genesis file module=main path=/home/.tendermint/config/genesis.json
$ tendermint node
Tendermintが起動してブロックの生成が始まれば成功です。
さらに別のターミナルで abci-cli
のコンソールを立ち上げます。このコンソールから kvstore
のアプリケーションのソケットへメッセージを送信します。アプリケーション側ではハンドラが実装されていてABCIメッセージを処理できるようになっています。
$ abci-cli console
I[2019-00-00|22:22:33.567] Starting socketClient module=abci-client impl=socketClient
>
echo hello
と info
と送ってみます。 abci
サーバ側で接続許可のログが出力されることを確認してください。
> echo hello
-> code: OK
-> data: hello
-> data.hex: 0x68656C6C6F
> info
-> code: OK
-> data: {"size":0}
-> data.hex: 0x7B2273697A65223A307D
>
...at ABCI server
I[2019-00-00|22:22:33.567] Accepted a new connection module=abci-server
I[2019-00-00|22:22:33.567] Waiting for new connection... module=abci-server
abci-cli
のコンソールからトランザクションを送って kvstore
へキーバリューの変数保存をしてみます。 deliver_tx
に続けて保存したい内容を指示します。 deliver_tx "def=xyz"
のコマンドで (def, xyz)
をトランザクションとして送出し、ブロックに取り込まれると、 query
で結果が確認できるようになります。[7]
> deliver_tx "abc"
-> code: OK
> info
-> code: OK
-> data: {"size":1}
-> data.hex: 0x7B2273697A65223A317D
> commit
-> code: OK
-> data.hex: 0x0200000000000000
> info
-> code: OK
-> data: {"size":1}
-> data.hex: 0x7B2273697A65223A317D
> query "abc"
-> code: OK
-> log: exists
-> height: 0
-> key: abc
-> key.hex: 616263
-> value: abc
-> value.hex: 616263
> deliver_tx "def=xyz"
-> code: OK
> commit
-> code: OK
-> data.hex: 0x0400000000000000
> query "def"
-> code: OK
-> log: exists
-> height: 0
-> key: def
-> key.hex: 646566
-> value: xyz
-> value.hex: 78797A
>
以上、 kvstore
を使用した簡単なサンプルでした。
まとめ
- Tendermintはビザンチン耐性のあるコンセンサスアルゴリズムを提供するソフトウェアでGeneral Purpose Blockchain(GPB)として利用できる
- ビットコインやEthereumのようにモノリシック(一枚岩)ではない
- アプリケーションロジックとTendermint Coreのブロックチェーン側はABCI(Application Blockchain Interface)という仕組みでメッセージを介してやり取りする
- コンセンサスエンジンは比率で2/3以上の投票権を持つノードの合意を得ることで進む
- 投票権はPoS(Proof-of-Stake)と同様にトークンを発行し、その保有比率(ステーキングしている比率)で測ることができる
- ハードスプーンという仕組みで既存のブロックチェーンからスプーンすることができる
abci-cli
を使用することでコマンドラインからABCIメッセージを送信できる
お知らせ
■ステーキング事業の提供を始めました!
7月からHashHubでは、Cosmos,Tezos,IOSTの3つのトークンをステーキング出来るサービス「Sanka Network」を提供し始めました。本サービスのご利用をご検討の方は、下記のWEBサイトからお問い合わせください。
Sanke Network:https://www.sanka.network/
■HashHubでは下記のポジションを積極採用中です!
・コミュニティマネージャー
・ブロックチェーン技術者・開発者
・ビジネスディベロップメント
詳細は下記Wantedlyのページをご覧ください。
Wantedly:https://www.wantedly.com/companies/hashhub/projects
■HashHubでは入居者募集中です!
HashHubは、ブロックチェーン業界で働いている人のためのコワーキングスペースを運営しています。ご利用をご検討の方は、下記のWEBサイトからお問い合わせください。また、最新情報はTwitterで発信中です。
HashHub:https://hashhub.tokyo/
Twitter:https://twitter.com/HashHub_Tokyo