Hyperledger Fabricのアーキテクチャとchaincodeのデプロイ
はじめに
前回はHyperledger fabric-samplesを利用して、自動車の所有者を管理するchaincodeを動かしました。いくつかのトランザクションを発行して、ブロックチェーンのブロックが積まれていく様子を確認できたかと思います。
しかし、エンドースメントポリシーを満たさないトランザクションはブロックが積まれましたが、値は反映されませんでした。今回は、なぜそのようになったのか、Hyperledger Fabricのアーキテクチャと共に解説します。また、前回コマンドを実行したchaincodeのデプロイについても触れていきます。
Hyperledger Fabricアーキテクチャ
Hyperledger Fabricには「CA」「orderer」「peer」という3つのノードがあります。CAは許可型ブロックチェーンを実現するための重要な役割をもつ認証局で、組織のメンバーに証明書の発行や失効ができます。
Ordererはトランザクションの順序を決め、ブロックに変換して検証とコミットのためpeerにブロックを配布します。コンセンサス(合意形成)にはKafkaやRaftを使用しますが、Kafkaは非推奨になっているため、現在ではRaftが標準で利用されます。今後はPBFT(Practical Byzantine Fault Tolerance)を実装する予定です。
Peerは台帳(後述)を維持し、台帳の読み書き操作を行うchaincodeを実行します。Peerは各組織に1つ以上あり、異なる組織のpeer間で相互に状況を確認するため、ゴシッププロトコルを用いて通信を行います。組織の中で外部と通信を行う代表的なpeerを「anchor peer」と呼びます。Anchor peer同士が通信し合い、anchor peerが知っているすべてのpeerについて情報交換をします。
台帳とブロックとワールドステート
Hyperledger Fabricにおける台帳(ledger)は、複数のトランザクションを含むブロックとワールドステート(world stateまたはstate database)から構成されています。銀行口座に例えると、利用可能な残高がワールドステートで、今までの取引履歴がブロックです。ワールドステートは今までの取引履歴を計算することで算出でき、最新の残高で取引を実行します。
検証(Validation)
Hyperledger fabricでは、全てのトランザクションの値を反映するわけではありません。Hyperledger fabricは分散システムであり、タイミングによっては参照したワールドステートが最新ではない可能性があります(ファントムリード)。また、エンドースメント直後にOrdererからブロックを受け取りワールドステートに反映してしまい、エンドースメントした結果と最新のワールドステートの値が異なることもあります。
これらを防ぐために、Execute-Order-ValidateアーキテクチャのValidationフェーズでトランザクションの値を確認しています。Validateフェーズは各トランザクションがエンドースメントポリシーを満たしているか、またはタイミングによってはエンドースメントを受け取った後で新しいブロックが積まれてトランザクションの結果が変わり、結果の不一致が起きてないかを検証しています。
Validationフェーズの検証により、トランザクションが無効になっても、すでにOrderフェーズでそのトランザクションを含んだブロックでハッシュ値を計算しているため、そのトランザクションは削除できません。したがって、それら無効なトランザクションの値はワールドステートに反映されません。
反映されない理由
前回でも解説したように、エンドースメントポリシーを満たさないトランザクションは検証の仕組みにより、ブロックとしては積まれてもワールドステートには反映されません。そのため、ワールドステートの値を取得するためにqueryを実行するとValidationフェーズで有効となった最新のトランザクションの値が取得されます。
スマートコントラクト「chaincode」
ビジネスで取引をするには、ルールなどを決めた契約を取り交わす必要があります。この契約が当事者同士の相互作用を決めるビジネスモデルになります。このモデルをコードで表現したものがスマートコントラクトで、Hyperledger Fabricではスマートコントラクトのことを「chainocde」と呼びます。
chaincodeはGoやNode.js、Javaで記述できます。dockerコンテナ内で動作し、アプリケーションから送信されたトランザクションを介して台帳の状態を操作します。Channel上に1つ以上のchaincodeをインストールでき、chaincodeからほかのchaincodeを呼び出すこともできます。
chaincodeのデプロイ方法
前回のfabric-samplesを利用して、どのようにchaincodeをデプロイしているのか詳しく見てみましょう。test-networkのnetwork.shでは、環境構築後にchannelを構築し、chaincodeをデプロイしました。Chaincodeのデプロイは次のような手順で行っています。
Cat fabric-samples/test-network/scripts/deployCC.sh (中略) packageChaincode 1 (中略) installChaincode 1 (中略) installChaincode 2 (中略) queryInstalled 1 (中略) approveForMyOrg 1 (中略) checkCommitReadiness 1 "\"Org1MSP\": true" "\"Org2MSP\": false" checkCommitReadiness 2 "\"Org1MSP\": true" "\"Org2MSP\": false" (中略) approveForMyOrg 2 (中略) checkCommitReadiness 1 "\"Org1MSP\": true" "\"Org2MSP\": true" checkCommitReadiness 2 "\"Org1MSP\": true" "\"Org2MSP\": true" (中略) commitChaincodeDefinition 1 2 (中略) chaincodeInvokeInit 1 2 (中略)
1. パッケージング
3行目のpackageChaincodeでは、Org1がchaincodeのソースコードと必要なモジュールをtarファイルにパッケージングしています。Fabric sdkやchaincode内で定義したパッケージを取得(Nodejsであればnpm、Goであればvendering)してtarファイルにパッケージ化します。前回と同様に、./network.sh deployCCを実行した際に同じディレクトリにfabcar.tar.gzのファイルが生成されます。これは1つの組織が代表して行っても良いですし、各組織がそれぞれ行っても大丈夫です。
2. インストール
5、7行目で、パッケージングしたchaincodeを組織Org1とOrg2それぞれのpeerにインストールしています。エンドースメントを行う必要があるpeer全てにインストールしますが、エンドースメントしないpeerというものもあり、それはブロックを保存するだけのpeerです。
3. 承認
11、16行目で、インストールしたchaincodeを各組織(Org1とOrg2)で承認します。承認を行うコマンドのパラメータにはchaincodeの名前やバージョン、エンドースメントポリシーなどがあります。承認はこれらの各組織のパラメータの投票として機能します。組織間でこれらのパラメータの提案に対して一貫性を持つ必要があります。
4. コミット
十分な数の組織がchaincodeのパラメータを承認すると、21行目でchannelにコミットしています。13、14、18、19行目で各組織(Org1とOrg2)が提案したパラメータを確認しています。承認が必要な数の組織数はConfigtx/configtx.yaml(下記)で確認できます。19行目のLifecycleEndorsementのRuleには“MAJORITY Endorsement”と記載されているので、過半数以上の承認があればコミットが可能です。
Cat configtx/configtx.yaml (中略) Application: &ApplicationDefaults (中略) # Policies defines the set of policies at this level of the config tree # For Application policies, their canonical path is # /Channel/Application/Policies: Readers: Type: ImplicitMeta Rule: "ANY Readers" Writers: Type: ImplicitMeta Rule: "ANY Writers" Admins: Type: ImplicitMeta Rule: "MAJORITY Admins" LifecycleEndorsement: Type: ImplicitMeta Rule: "MAJORITY Endorsement" Endorsement: Type: ImplicitMeta Rule: "MAJORITY Endorsement" (中略)
5. 初期化
chaincodeがコミットされるとchaincodeを使用できるようになりますが、chaincodeは初期化が必要なため、chaincod内に定義されたInit関数を呼び出します(deployCC.shの23行目)。
このように、chiancodeのデプロイは複数組織で行います。ブロックチェーンは複数組織での業務で利用されるため、それぞれの組織の合意を得たプロセスで行われる必要があります。
おわりに
今回は、Hyperledger Fabricのアーキテクチャとchaincodeのデプロイについて解説しました。ブロックチェーンは普通のシステムと違って異なる組織が登場するため、それぞれ協調してchaincodeを開始する必要があります。その方法は、fabric-samplesのスクリプトを見れば理解できるでしょう。
次回は、実際にchaincodeを開発してみたいと思います。
連載バックナンバー
Think ITメルマガ会員登録受付中
全文検索エンジンによるおすすめ記事
- Hyperledger FabricのPermissionedとExecute-Orderer-Validateアーキテクチャ
- Hyperledger Fabricに関連する2つのプロジェクトとHyperledger Fabricに関するリソース
- Fabric SDK(Software Development Kit)を用いてNode.jsからchaincodeを呼び出す
- fabric-samplesのfabcarを用いてchaincodeの中身を記述する
- エンタープライズグレードのブロックチェーンを発展させる「Hyperledger」とは
- 再注目されているHyperledgerをテーマに、Linux Foundationが「Hyperledger Tokyo Meetup」をオンライン開催【後編】
- 「Open Source Forum 2019」開催 ― キーマンが語る企業や社会の要素となるOSS技術とは
- LFが分散型テクノロジーエコシステムのための統括組織「LF Decentralized Trust」の立ち上げを発表、ほか
- 「Linux Foundation認定ITアソシエイト」が日本語で受験可能に、日立が「Hyperledger Fabric」を用いたデジタル化の課題解決事例を公開、ほか
- Open Source Summit Japan 2018開幕 Jim Zemlinの講演に続きAGLやHyperledgerの事例を発表