メインコンテンツへスキップ

1024プログラマーズデー記念: simple chain

陈天(ArcBlock 研发副总裁)
Tendermint

著者: 陳天(ArcBlock 研究開発副社長)

先々週、Cybermiles向けに提供したsupernodeをリリースしました。CybermilesのメインネットワークがTendermintを使用しているため、先週はTendermintを調べ、学びながらTendermintを紹介するslidesを書きました。

TendermintはPBFTから派生したconsensus engineであり、その上にApplication BlockChain Interface(ABCI)を構築しています。これにより、ブロックチェーンの開発者はサービスの提供方法やサービスの状態管理に集中でき、コンセンサスの達成方法、mempoolの管理方法、安全なp2p通信の方法といった細かな処理はTendermintに任せることができます。Tendermint自体はgolangで書かれており、ABCIインターフェイスはprotobufで実装され、raw TCPまたはhttp2(gRPC)を使ってapplication layerと通信します。

日曜日、暇な時間に、tendermintを使って何か作ってみようと思いました。しかしtendermintにはelixir向けのABCI実装が提供されておらず、コミュニティのerlang実装もいくつかの機能が欠けていました。また、erlangでRecordを使ってprotobufを記述する方式があまり好きではなかったため、Tonyのprotobufライブラリを使ってelixir向けのABCI実装を書き、github.com/arcblock/ex_abciに公開しました。その後、Tendermint自身が提供するcounter example app——ブロックチェーンの改ざん不可能性を利用してネットワーク全体で唯一のカウンターを維持するもの——を実装しました。

ex_abciを使えば、counter appのコアコードは数十行程度で、info、check_tx、deliver_txいくつかのインターフェイスを実装するだけです:

このようなappはhello worldとしては使えますが、Tendermintが信頼できるかどうかを検証するためのものであり、それ自体は本質的ではありません。Tendermintはkv storeのexampleも提供していますが、ブロックチェーンの核心要素を捉えられていないと感じたため、十分にシンプルで、できれば数百行以内でブロックチェーン技術を示せるSimple Chainを作ろうという考えが生まれました。では、ブロックチェーンの核心要素とは何か——私はこの図、Merkle Patricia Tree(MPT)だと思います:

これはイーサリアムがWorld Stateを保存するためのコアです。読者の皆さんはpatricia tree(prefix tree、radix tree、またはtrieとも呼ばれる)をご存知だと思います。ブロックチェーンの知識がある方はmerkle treeもご存知でしょう。MPTは両者を組み合わせ、自己検証機能を持つpersistent data structure(関数型プログラミング言語でlist / mapを保存する方式)を構成しています。MPTおよび上図については、弊社エンジニアのDing Peilingが前回の北京Hackathonで素晴らしい講演を行っています。興味のある方はYouTubeのArcBlockチャンネルで「ArcBlock's Introduction to Blockchain」をご覧ください。37分頃からMPTの解説が始まり、約10分間、非常にわかりやすく解説しています。紙幅の都合上、ここでは詳しく展開しません。

Simple Chainについて、プロダクトとして以下のように考えました:

  1. アカウントシステムはイーサリアムと互換性を持つ
  2. Tendermintの全インターフェイスを完全に使用し、それぞれの意義を探る
  3. chainの状態はMPTで保存し、各blockのcommit後のstate rootをTendermintに提出する
  4. chainは基本的なフォールトトレランスを持つ——例えばtxの実行途中でクラッシュしても、前のblockのstateに回復して実行を継続できる
  5. TransactionはEthereum txの簡略版を使用し、1つのTXにはfrom、to、nonce、total、pub keyのみを含む
  6. MPTにはEthereumに類似したaccountを保存し、各accountは自身のbalance、nonce、num_txsを持つ
  7. client RPCはWalletモジュールに直接統合し、デモを容易にする

2日間かけて、粗削りな、マルチノードテストを経ていないバージョンがようやく実装できました。ソースコードはex_abci/examples/simple_chainをご覧ください。主な外部インターフェイスについてお話しします:

  1. Wallet.new: オフラインアカウントを生成する
  2. Wallet.declare: 各Walletが初回に限りシステムから10000トークンを受け取れる。主にテスト用
  3. Wallet.transfer:あるアカウントから別のアカウントへ送金する。双方のaddressに対応するaccountがchainのMPT内で更新され、各blockのcommit後にMPT root、つまりapp stateがblock headerに書き込まれる
  4. Wallet.info / Wallet.chain_info:accountの情報 / chainの情報にアクセスする

以下は実行時の全体的な流れです。

初期化:

Walletの状態:

送金:

Tendermint block:

送金後の状態:

このSimple Chainで主に使用した技術:

  1. TendermintとEx_abci、これは当然のこと
  2. ElixirにおけるMPT実装:merkle_patricia_tree
  3. Tonyのprotobuf実装。MPT内にaccountを保存する際、そのvalueもprotobufで定義している
  4. keccakf1600:ethereumのsha3の実装。account addressの生成や各種hashが必要な場面で使用(なお、ここではdouble hashは使用していない)
  5. libsecp256k1:ECDSAの実装。主にwalletの生成、およびtransactionのsignとverifyに使用

現在のコード量は400行以内で、ひと目で把握でき、TendermintとブロックチェーンのBasicロジックを理解するのに最適です。興味のある読者はtendermintをインストールし、github.com/arcblock/ex_abciをダウンロードして試してみてください。

本来この記事は1024節前に公開するつもりでした——昨夜(24日)にcrash recoveryの処理がうまくいかず、今朝90号ハイウェイの霧の中を車で走っているときにふと解決策が思い浮かびました。そのため記事の公開が遅れてしまいました。これらの技術に興味のある方は、https://www.arcblock.io/en/learning/(「続きを読む」をクリック)で今後のTech Talkに参加登録していただくか、ArcBlockのYouTubeチャンネルをフォローして過去の知識共有コンテンツをご覧ください。

皆さん、1024節おめでとうございます!