空谷に吼える

ブロックチェーン/DLTまわりのなにかしらを書いていく所存

Hyperledger Fabricのコンセンサスを親切に説明 ~ Endorsementフェーズ編

前のエントリでHLFのコンセンサスのちょう概要がわかりましたね?
しかし残念ながら、あなたはちょう概要だけわかっていてもHLFを使ったクールなシステムを適切に設計できるようにはなっていません。ということで今度はもうちょっと詳細をお勉強していきましょう

なんの話

  • Hyperledger Fabricがどのようにコンセンサスを形成しているかを解説
  • まずはEndorsementフェーズのプロセスを説明

内容

概要のふりかえり

ざっくり言うとHLFにおけるコンセンサスは各Peerノードが保持する台帳(分散台帳の1コピー)のすべてで同一の値が追記される、あるいは、すべてで追記が失敗するという状況を維持するための仕組みです。そしてそのコンセンサスを形成するプロセスは、Endorsement⇒Ordering⇒Validationの3フェーズで構成されています。ただしOrderingのフェーズもいろいろやっているんですがちょっとレイヤーが異なっているので、ここではいったん割愛します。

  • EndorsementフェーズでChaincodeを仮実行し、台帳から読み取った値と書き込む予定の値(RWSet)とEndorseを行うPeer(Endorser)の署名(Endorsement)を取得
  • Validationフェーズでは台帳を保持するすべてのPeerがそれぞれ、必要なEndorsementが集まっているかの検証および書き込む値のバージョンが仮実行時とずれていないかの検証を行ったうえで台帳にコミット

以下が詳細です。長すぎてあなたがウッてなるかもしれないので、Endorsementフェーズ編とValidationフェーズ編でエントリ分けています、スゴイ親切

1. Endorsementフェーズ

1-1. Proposal

Chaincodeでの台帳への更新(新規Key-ValueセットのCreate、既存Key-ValueセットのUpdateおよびDelete)を行うトランザクションを実行したい場合、クライアントアプリケーションはそのChaincodeのEndorsement Policyにあらかじめ定められている条件を満たすだけのEndorsementをPeerから取得してこなければなりません。したがってまずクライアントアプリケーションは、1~nのEndorserにTxのProposalを送信します。

  • Endorsement Policy: あるChaincodeで台帳の更新を行う場合、どのようなEndosementを集めてこなければならないかを定める条件です。Chaincode×チャネル単位で設定できます。ここでEndorsementはPeer単位ではなく、組織を表すOrganization(Org)単位でカウントされることに注意してください。Org A,B,Cで構成されるコンソーシアムネットワークでそれぞれがふたつのPeerを持っている場合、Endorsement Policyは例えば「3つのOrgのうち、任意の2つのOrg配下のPeerからEndorsmentの取得」といったような条件になります。
    このEndorsement Policyがすなわち「どうしたらコンセンサスが取れたことにして台帳に追記できるか」の条件になります。上記のような単純なOrg数(1~n)による条件から、スコアリングでの重みづけ評決など、かなり柔軟に条件を設定することができます。詳細は公式ドキュメントを参照しましょう。

  • Endorser(Endorsing Peer): どのPeerでもEndorsementを行うことができるわけではなく、Endorserという役割を付与されたPeerのみがEndorsementを行うことができます。これはEndorsementを行う=Chaincodeを実行することになるので、それぞれのOrg配下のPeerの間での負荷分散や軽減のために、Endorsementを行うPeerを絞っておけるようにするという仕組みです。

1-2. Proposal Response

Proposalを受け取ったPeerはリクエストされたChaincodeを実行します。ただしこの際に台帳への書き込みのコミットは行いません。このため、ここでのChaincodeの実行を「仮実行」と呼ぶことがあります。Chaincodeを正常に(つまりエラーにならずに)実行できた場合、PeerはクライアントにRWSetと自身のEndorsementを含んだProposal Responseを返信します。

  • RWSet: Chaincodeの実行の中で、台帳のState DBから読み取った値があればそのKeyおよびそのバージョンのセット(Read-Set)、また、台帳に書き込む(予定の)値があればそのKey-Valueのセット(Write-Set)が含まれます。つまりRead-Write-Setです。Read-Setはない場合もあること(単純に新規Key-Valueセットを追加する場合など)、また、値ではなくバージョン(そのKeyの更新回数)が含まれていることに注意しましょう。また、台帳の参照だけ行うトランザクションの場合、もちろんWrite-Setはありません。

  • Endorsement: Endorser PeerのIDを表す値と、電子署名から構成されます。電子署名はPeerの持つ秘密鍵を使い、RWSetなどのResponseの他の部分の値に対して行われます。これによりEndorsementを偽造することや、後でクライアントやOrdererが値を改ざんすることができないようになっています。

1-3. Transaction Submit

クライアントには各EndorserからProposal Responseが返されてきます。ここで必ずしも全Endorserからの応答を待つ必要はなく、Endorsement Policyに十分なResponseが集まった時点でクライアントはOrdering ServiceにTxを送信し、次のOrderingフェーズへと進めることができます。

ただし注意点は、単にEndorsementの数がそろえばいいということではなく、各PeerからのResponseに含まれるRWSetが一致している必要がある(のちのValidationフェーズで一致しているかチェックされる)という点です。通常、各PeerのState DBは同一のKey-Valueセット(バージョンも同一)を保持しているはずであり、また、各Peerで実行されるChaincodeが同一かつdeterministic(決定ー的)であれば、各Peerから返答されたRWSetは一致するはずです。が、State DBが直接更新されるなどしてforkしている、各Peerで実行しているChaincodeの中身が異なっている、あるいはnon-determinsiticであるなどの場合、RWSetが一致しない可能性があります。

ここまでがEndorsementフェーズ編でした、続いてValidationフェーズ編を別のエントリでお勉強しましょう