Upgrade to Pro — share decks privately, control downloads, hide ads and more …

Hyperledger FabricアプリケーションとChaincodeの開発

gakumura
October 25, 2022

Hyperledger FabricアプリケーションとChaincodeの開発

2021/12/8 Blockchain GIG#11でしゃべった内容
→2022/10/25 Blockchain GIG特別編 HLF集中講義#3 Hyperledger FabricのアプリとChaincodeの開発 でリバイズ
Hyperledger Fabricのクライアントアプリケーション、Chaincodeを開発する際に知っておきたいこと

gakumura

October 25, 2022
Tweet

More Decks by gakumura

Other Decks in Technology

Transcript

  1. Copyright © 2022 Oracle and/or its affiliates 2 中村 岳

    Twitter @gakumura はてなブログ @gakumura …主にHyperledger Fabric関連 • 現職:ソリューションエンジニア@日本オラクル • 担当:Oracle Blockchain Platform、 Blockchain Table • 前職:金融決済系SIerでパッケージ開発 • SWIFT、CLS、日銀ネット関連の銀行間決済システム
  2. Hyperledger Fabricをベースにエンタープライズ利用向けPaaSとオンプレミスで提供 • 数ステップで構築完了、GUIコンソールで管理・運用も容易 • エンタープライズグレードの耐障害制、堅牢性 • マルチクラウド、ハイブリッドクラウド、 オープンなネットワーク構成が可能 •

    Oracle独自の付加価値: • State DBとしてBerkeley DBを利用:パフォーマンスとクエリ利便性向上 • 多機能なREST API:スマートコントラクトの利用を容易に • 台帳のデータをRDBに複製:大量照会、分析、データ統合 • スマートコントラクトを容易に開発:付属の開発ツールでアセット仕様からコードを自動生成 • 複数ChannelのアトミックトランザクションとXA対応:複数Channelでの更新のアトミックな実行 や、ローカルのDB、MQなどとのグローバルトランザクションをサポート Oracle Blockchain Platform Copyright © 2022 Oracle and/or its affiliates 東京DCからも サービス提供中 3
  3. • 10/11(火): Hyperledger Fabric(再)入門 • コンポーネントやトランザクションフローなど基本を解説 • 10/18(火):Hyperledger Fabricのネットワーク設計 •

    ブロックチェーンネットワークの設計の考え方、進め方を解説 • 10/25(火):Hyperledger FabricアプリとChaincodeの開発 • クライアントアプリケーションとChaincodeの開発方法を解説 • 11/1(火):Oracle Blockchain Platformを用いたHLFアプリ開発 • Oracle Blockchain Platformならではのメリット、開発方法を解説 集中講義シリーズ Copyright © 2022 Oracle and/or its affiliates 4
  4. • 所謂「スマートコントラクト」をHLFではChaincodeと呼んでいる • 別にコントラクト=契約を表現していなくてもよい(契約を表現していてもよい) • 単に「台帳の読み書きのロジック」と考えるとわかりやすい • 「RDBにおけるストアドプロシージャのようなもの」という説明もある • 台帳(のデータ)の更新の唯一の手段である

    • Chaincodeの関数がトランザクションの実行単位である • Chaincodeを経由せずに台帳を更新する(適切な)手段はない • 台帳の参照についてはいくつかバイパス手段がある • ブロックを直接見る、State DBを直接見る、外部DBに複製したデータを見る • ユーザーが開発する通常のChaincode(→User Chaincode)の他に、Chaincodeライフサイ クルやChannel設定などに関連したロジックを担うプリセットのSystem Chaincodeが存在する • System Chaincodeについては通常特に意識しないでOKなので本資料では触れず、以降で はUser Chaincodeのみの話をします Chaincodeとは何か? Copyright © 2022 Oracle and/or its affiliates 7 Client App Fabric SDK Peerノード Ledger Chaincode
  5. 運用上重要なものを含むが、Chaincodeの開発自体にはあまり関係ないかも 項目 内容 有効化とアップグレードの分 権化 v1.4系ではChaincodeの有効化およびアップグレードを単一のOrgのオペレーションで行っていた。そのため、Chaincode のパラメータ(Endorsement PolicyやPrivate Data Collection、Init関数の引数など)に他のOrgが関われなかった。

    v2.x系の新ライフサイクルでは、パラメータ内容を含む有効化&アップグレードオペレーションについて、予め複数のOrgから の承認が必要になった。 パラメータ設定更新方法の 改善 Chaincodeをインストールし直さなくてもEndorsement PolicyとPrivate Data Collectionのを更新することが可能に なった。 パッケージ概念の追加 v1.x系でのChaincode IDとバージョンの概念に加え、インストールモジュールの実体を指すパッケージ概念が追加された (パッケージを単位としてインストールするようになった)。 また、インストールされた同一のパッケージを元に複数のChaincodeインスタンスを別のChaincode ID/バージョンを付与 し、別のパラメータで同一Channelで稼働させることが可能になった。 ローカルカスタマイズが可能に v2.x系では、各OrgでインストールするChaincodeのロジック内容(→パッケージの内容)が必ずしも一致していなくても よくなった。これにより、自Orgのみが使う参照用の関数の追加など、ローカルなカスタマイズを行うことができるようになった。 Chaincode稼働環境の 柔軟化 v1.x系ではChaincodeインスタンスはPeerごと×Chaincode(&バージョン)ごとに作成されるDockerコンテナ上で稼 働していた。v2.x系ではDockerコンテナ以外の稼働環境も選ぶことができるようになり、また、必ずしもPeerごとの単位で はなく、外部サービスのかたちで稼働させて複数Peerから共用することができるようになった。 参考:v2.x系でのChaincode関連の主要な変更 Copyright © 2022 Oracle and/or its affiliates 9
  6. • Chaincode開発言語の選択肢:Node.js、Go、Java • これらの言語で用意されたFabric Chaincode SDKを利用してChaincodeを実装 する • できることは基本的には変わらないので、お好みで選択 •

    いずれかのAPIを選択して実装する • fabric-contract-api(後から追加された高レベルAPI、現在の推奨) • fabric-shim(初期から存在する低レベルAPI) • 多くの場合、Chaincodeはそれほど複雑にも大規模にもならない • Ethereumにおけるスマコン(ERC、Open Zeppelin、etc.の学習が必須&デー タの持ち方と扱い方のお作法がだいぶ特殊)とは事情はかなり異なるので、イメージ に引きずられない • まずはHLFのGitHubのサンプルコーナー (https://github.com/hyperledger/fabric-samples)にあるChaincodeをい ろいろ眺めてみることを推奨 Chaincodeの実装 Copyright © 2022 Oracle and/or its affiliates 10 Peerノード Ledger Chaincode fabric-contract-api Client App Fabric SDK
  7. • Chaincode内に実処理を記述した関数を複数実装し、クライアントがトランザクションでどの関数を利用するかを指定 して呼び出すことになる • 関数の分岐はどちらのAPIを利用しているかによって書き方が異なる • fabric-shimを利用している場合、invoke()関数が単一のエントリーポイントになっており、invokeの処理の中 で実処理を担う関数の呼び出しに分岐させる invoke(実処理関数名, [引数の配列])

    { if (実処理関数名 == hoge) {hoge([引数の配列])} if (実処理関数名 == fuga) {fuga([引数の配列])} ... } • fabric-contract-apiを利用している場合invoke()関数は不要で、実処理を担う関数の呼び出し分岐まで API側でやってくれる • Init()という名前で初期化関数を実装しておく必要がある • Chaincodeの有効化とアップグレードのトランザクションの中で呼び出される • Init()内ではChannelの台帳のセットアップ的なことをやってもよいし、何もやらなくてもよい Chaincodeの実装お作法 Copyright © 2022 Oracle and/or its affiliates 11
  8. Peer Peerノードが保持する分散台帳の1コピー 復習:Hyperledger Fabricにおける「台帳」 12 • 台帳は以下ふたつの要素から構成される + Blockchain:履歴 •

    トランザクションの履歴が格納される ハッシュチェーンで連結されたブロックのファイル • 追記オンリーで蓄積していく World State:状態 • 各Keyに対する現在(最新)バージョンの値を保持 • レコードは更新、削除が可能 (履歴はBlockchainに残っている) • State DBと呼ばれるDBに格納される Ledger Peer Ledger Peer Ledger Peer Ledger Copyright © 2022 Oracle and/or its affiliates
  9. 台帳に保存される「現在の値(ステート)」とそれを保持するデータベース World StateはKey-Valueストアで、Valueには任意の文字列やバイナリを格納可能 • ChaincodeはWorld StateからKeyのValueを読み出し、書き込むことで 台帳上のデータに対してのビジネスロジックを表現する • State DBと呼ばれるデータベースに保持される

    通常のHLFではState DBにはLevelDBかCouchDBを選択可能 • LevelDB:シンプルなデータ構造を扱う場合向き(例:口座番号がKey/残高がValue) • Keyを指定するステート検索しかできない(単一指定or範囲指定) • CouchDB:複数の属性を持つValueを扱いやすい • JSON形式でValueを格納すると、Attributeを条件に指定して検索できる(リッチクエリ) • LevelDBに比べると低速な点、Phantom Read問題に係る制約には留意 復習:World StateとState DB 13 Copyright © 2022 Oracle and/or its affiliates
  10. ある程度柔軟なデータ構造を扱え、State DBによる検索の表現能力もそこそこ 復習:World Stateで扱うデータ構造の例 Copyright © 2022 Oracle and/or its

    affiliates 14 Key:口座番号 Value:残高 1020345 10,000,000 1020346 56,400 Key:アセット種別とID Value:アセット情報 car^aaa111 {“color”:”red”, “price”:10000, “owner”:”Bob”, “drive”:”front”} car^bbb222 {“color”:”blue”, “price”:30000, owner”:”Alice”, “drive”:”AWD’} bike^xyz345 {“color”:”green”, “price”:30000, owner”:”Alice”, “CC”:”1800’} シンプルなKey-Value構造:口座 複合キーとJSONを用いたKey-Value構造:アセット台帳 Keyの値を指定してValueを読み取る/書き込む 複合キーの利用や Key値の範囲指定のクエリも可 State DBにCouchDBを使いValueをJSONにしておくと リッチクエリが使える (例:ownerがAliceのアセットを全件取得)
  11. • Chaincodeを実装する際に利用する主な機能はSDKのChaincodeStubクラスにまとまっている • このクラスの内容(関数)を抑えておけば基礎の学習はだいたいOK • Go/Java/Node.jsのSDKで細かい関数の有無、関数名に差異(ここではNode.js基準で記載)があるが、実質的にで きることは同等。Node.jsのドキュメントは説明が多くてわかりやすい。 • 以下によく使う主要なものを抜粋して記載 Chaincode

    SDKの主要な機能① Copyright © 2022 Oracle and/or its affiliates 15 カテゴリ 関数 説明 引数 getArgs クライアントから渡された引数を取得する getTransient TransientMap(Transactionに載らない=Blockchain上に値が記録されない特殊 な引数)として渡された引数を取得する トランザクション情報 getTxTimeStamp クライアントから渡されたTransactionのタイムスタンプを取得する getTxID クライアントから渡されたTransactionのID(ランダムなGUID)を取得する getMspId トランザクション発行者(クライアント)の所属Organizationを取得する getCreator トランザクション発行者のアイデンティティを取得する
  12. • 台帳操作系の機能のうち主要なものは以下(World Stateへの操作についてはPrivate Data用に同等の機能が存在するが、こ こでは一律割愛) • いずれも特に難しいところはないが、参照系はRead-Set Validationとの絡みで更新トランザクション内での利用に制約がつくもの、 注意が必要なものがある点は留意(後述) Chaincode

    SDKの主要な機能② Copyright © 2022 Oracle and/or its affiliates 16 カテゴリ 関数 説明 World Stateの 更新 putState 指定したKey、ValueのレコードをWorld Stateに書き込む(Keyが既にあればValueを上書きす る) deleteState 指定したKeyのレコードをWorld Stateから削除する 台帳の参照 getState 指定したKeyのValueをWorld Stateから取得する getStateByRange StartKey~EndKeyで指定した範囲のKeyのレコードをWorld Stateから検索し取得する getStateByPartial CompositeKey 複合Keyを持たせたレコードについて、複合Keyの前部分を指定し、前方一致でWorld Stateから 検索し取得する getQueryResult State DBのデータベース実装が対応している構文でクエリを渡し、World Stateの検索結果のレコー ドを取得する(例:CouchDBを利用→JSONリッチクエリ) getHistoryForKey 指定したKeyについての履歴(過去から現在のバージョンのValue、TxIDとTimeStamp)を Blockchainから取得する
  13. • ChaincodeはEndorsement Phaseの中で呼び出されてPeerノー ドにより実行される • クライアントアプリケーションからPeerにChaincode実行依頼 (Transaction Proposal)を送付 • Chaincode関数の引数はここで渡す

    • PeerノードがChaincodeを実行し署名を付けて結果 (Endorsement)を返却 • 関数のレスポンスとRWSetが含まれる • クライアントはEndorsement Policyで定められた必要な分の Endorsementを収集する →Chaincodeは通常、複数のOrganizationの複数のPeerで冗長に 実行される • Peerの処理リソースはネットワークの共有資産 • Chaincodeの処理コストには敏感になったほうが良い 復習:トランザクションの中でのChaincodeの使われ方 Copyright © 2022 Oracle and/or its affiliates 17
  14. • 台帳上のデータを参照したいが台帳を更新する意図がない場合、クライアントアプリはEndorsement(に含まれるレ スポンス)だけ受け取れば良いのでEndorsement Phaseまででトランザクションを終わらせる(Ordererに Transactionメッセージを送信しない) • Fabric SDKにクエリ用APIとして用意されている • この場合冗長に実行させる必要はなく、ひとつのPeerにTransaction

    Proposalを送れば良い • v2.x系で可能になったローカルカスタマイズと組み合わせるといろいろ便利なこともできる • なお、参照した事実だけ記録するためにそのままOrdering Phaseまで進めることもできる • 参照はした(→Read-Setアリ)が更新しなかった(→Write-Setナシ)トランザクションとしてBlockchainに 残る • 参照の記録はクライアントアプリ次第なので、 強制できない点には留意 Tips: Chaincodeで台帳の参照だけを行う(更新を行わない) Copyright © 2022 Oracle and/or its affiliates 18
  15. 指針として、Chaincodeに何もかもやらせようとせず、できるだけシンプルなものに留めておいたほうがよい→Chaincodeに必須でないも の、向いていないものはクライアントアプリケーションロジックや、台帳データ複製先のデータベースで引き取る やるべき • Chaincodeに必須なのはWorld StateとPrivate Dataの更新に関連する機能 • 更新の中で必要な参照機能(条件評価など)を含む •

    基本的な(それほど複雑でない、規模の大きくない)クエリの機能もあって良い やらないべき • Chaincodeは複雑でコストの重い処理、広い範囲のデータを一括で読み書きする処理にはあまり向いていない • Endorsementでは複数Peerでロジックが冗長に実行される • State DBはRDBと同じようには使えない…大規模集計、分析は得意ではない • トランザクションフローの仕組み上、1トランザクションに大量のRWSetが含まれると他のトランザクションと衝突しやすく、結果的に 処理性能に問題が発生しやすい • 必要な場合はバッチとして切り出し時間を区切るなどして他のトランザクションに影響を与えないように工夫する 何をChaincodeのロジックとして持っておくべきか? Copyright © 2022 Oracle and/or its affiliates 19
  16. • 前述の「複雑でコストの重い処理、広い範囲のデータを一括で読み書きする処理」以外にもChaincodeロジックの設 計あるいは実装にあたって注意が必要な以下の点を説明していく Chaincodeロジックの注意点 Copyright © 2022 Oracle and/or its

    affiliates 20 項目 要点 非-決定性ロジック 実行したPeer間で結果がバラバラになり得るロジックは作り込んではいけない 外部情報の参照(オラクル) Chaincodeから台帳の外部にある情報を見に行くのは難しい Read My Writes 今書いたValueはまだコミットされてないので読めない 更新トランザクション内での 一部クエリ機能の利用制約 一部のクエリ(World State、Private Data、Blockchainの検索)機能はValidationで検 出されない不整合を起こし得るので更新トランザクションの中での利用には注意が必要 Chaincode内Chaincode呼び出し Chaincode内から別のChaincodeを呼び出せるが、同一Channelでない場合は安全でな い、呼び出し先のChannelの更新もできない 同一レコードについての 更新スループット追及上の限界 トランザクションフローにおけるRead-Set Validationの関係で、同一のレコードを高密度で 更新するユースケースが苦手
  17. スマートコントラクトとステートの一致 分散/独立したステートを一致させるにはどうすればよいか? 前提として、ステートを更新する方法、条件を予め合意し共有しておく • 予め合意していることをもってシステム化された「契約」とみなせるため スマートコントラクトと呼ばれる • ステートは契約の履行の結果を記した台帳ということになる そのうえで、全ノードで一致したステートを保持する方法はふたつ •

    全てのノードがそれぞれスマートコントラクトを実行してステートを遷移させる • 一部(単一または複数)のノードでスマートコントラクトをシミュレーション実行し、 事後状態となるステートを伝播する • Hyperledger Fabricのコンセンサスモデルはこちら 非-決定性 Copyright © 2022 Oracle and/or its affiliates 23
  18. あるTransactionがWorld Stateから読んだレコード、書き込む(予定の)値 <TxReadWriteSet> <NsReadWriteSet name="chaincode1"> <read-set> <read key="K1", version="1"> <read

    key="K2", version="1"> </read-set> <write-set> <write key="K1", value="V1”> <write key="K3", value="V2”> <write key="K4", isDelete="true" > </write-set> </NsReadWriteSet> <TxReadWriteSet> 復習:RWSetの例 ※バージョンの形式は単純化しており正確なものではない Copyright © 2022 Oracle and/or its affiliates 25 • K1とK2のレコードを読んでいる • それぞれバージョンは”1” • K1に”V1”という値を、K3に”V2”という値をそれぞれ 書き込もうとしている • K4のレコードを削除しようとしている
  19. Chaincodeの決定性がなぜ必要か • Chaincodeにはそのインプットとして常に台帳の現在ステートとクライアントからの入力値(引数)が存在する • 複数ノードでそれぞれChaincodeが実行された結果に含まれる事後ステート=Write-Setが同一になっていないと ならない • 異なるWrite-Setを集めてきてもEndorsement Policyを満たさない •

    すなわち、同一インプットからは同一の事後ステートが導かれるようにしておく必要がある • この条件を満たすChaincodeをdeterministic(決定性の、決定的な)であると呼び、 そうでないものをindeterministic(非-決定性の、非-決定的な)と呼ぶ • Chaincode内に非-決定性のロジックを作り込んではならない 非-決定性 Copyright © 2022 Oracle and/or its affiliates 26
  20. 非-決定性ロジックの例:ノードのローカル日時の利用 • Chaincode内でノードのローカル日時を取得して利用するのは、 他のノードと必ずしも一致しなくなるのでNG • 時刻同期が不完全なことによるズレ • Chaincodeの実行タイミングのズレ • 「現在」の日時はクライアント側で決定してから渡すしかない

    • ⇨クライアント側で任意の値を渡すことができる(不正の余地がある) • これはつまり、特別な手段を講じない限り「現在」日時はコンセンサスの外部ということ 非-決定性 P L CC P L CC ≠ 12:00:00 12:01:23 Copyright © 2022 Oracle and/or its affiliates 28
  21. 日時に関する補足 非-決定性 Copyright © 2022 Oracle and/or its affiliates •

    ブロック内のトランザクションデータ(トランザクション 履歴)として保存されているタイムスタンプもクライ アントアプリケーションで決定しているもの • 必ずしもクライアントが正しいタイムスタンプを渡すと も限らない • トランザクション履歴を利用する際には、順序付け などにこのタイムスタンプを使用してはならない 29
  22. • 例えばスポーツ賭博や予測市場などのサービスをブロックチェーン/分散台帳で実現しようとしたときに、現実世界の情 報(試合結果や値動き)が必要 • クライアントアプリケーションから渡すことにすると、都合良く偽れてしまう • 不正があったことを後から追求可能ではあるので、それで問題ないユースケースならそれでよい • スマートコントラクトからネットワーク外部の情報にアクセスしてコンセンサス内で取得してこないとならない •

    何も考えないで実装すると、外部サービスへのアクセスにインタラプトするMockを建ててそこから都合の良い情報を 返す、などわりとかんたんに不正ができる • このような要求に対して、中立かつ信頼できるかたちでネットワーク外部の情報を提供するサービスをオラクル (Oracle、託宣)と呼ぶ • オラクルが情報を自身の署名付きで提供することで、偽装や改ざんが不能でコンセンサスに取り入れられる外部情報 が利用できる • しかし署名の検証をどう行うかまで考慮が必要となるなど、オラクル利用はけっこう難しい 安全な外部情報の利用(オラクル) Copyright © 2022 Oracle and/or its affiliates 31
  23. • Chaincodeの中でWorld StateまたはPrivate Data Collectionにデータを書き込み(PutState/ PutPrivateData)したあとに、同一Tx内で先程書き込んだデータを読み出そう(GetState/GetPrivateData、 あるいは各種クエリ)としても読み出せない(反映されていない) • 例:{Key, Value}=K1,

    V1のレコードにK1, V2を上書き(PutState)してからすぐGetStateすると取得し たデータはK1, V1のまま • 理由:台帳とPrivate Dataに更新が反映されるのはValidation/Commitフェーズなので • それまでは更新が反映されないので、さっき書いたものが読めない…”Can’t Read My Writes” • 対処法は一時格納用の変数を用意するだけなので簡単だが、知らないとたまにハマるので注意 できない:Read My Writes Copyright © 2022 Oracle and/or its affiliates 32
  24. • HLFではValidationフェーズでのRead-Set ValidationによりMVCC(MultiVersion Concurrency Control)でのデータ整 合性、一貫性保護を行っている • また、一部のレンジクエリ機能はValidation時にChaincode実行時と同じ検索条件で再実行され、結果セット(のサマリ値)が 変わっていないことを確認している→Phantom Readが検知される

    • 対象:getState(PrivateData)ByRange,getState(PrivateData)ByPartialCompositekey • Chaincode内で使えるクエリ機能のうち以下はValidationの検知スコープ外の挙動が発生する可能性があるため、更新トランザ クション内での利用には注意が必要(基本的には使用するべきではない) 更新トランザクション内での一部クエリ機能の利用制約 Copyright © 2022 Oracle and/or its affiliates 33 クエリ機能 問題点の説明 getHistoryForKey 履歴は読んでもRead-Setに載らないので、Validationフェーズまでにその Keyに更新があっても検知できない ※ただしgetStateと併用していれば問題ないので回避は容易 getStateByRangeWithPagenation, getStateByPartialCompositeKeyWithPagenation, getQueryResult, getPrivateDataByRangeWithPagenation, getPrivateDataByPartialCompositeKeyWithPagenation, getPrivateDataQueryResult これらのレンジクエリ(検索結果としてゼロ~複数の結果セットを返すクエ リ)は共通してValidationフェーズに再実行されないため、Phantom Readの発生を検知できない →Phantom Read問題
  25. Tx2 • Read-Setに含まれるKeyのバージョンが自身の現在のWorld Stateの それと一致しているか • 言い換えると、Chaincode実行時点(Endorsementフェーズ)で 読み取ったレコードのValueが、Validation時点までに更新されてい ないことをチェックしている Read-Set

    Validationの必要性: • HLFはあるトランザクションでStateをReadする時点とWrite/Commit する時点が離れており、その間のロックもしていない • Read時点からWrite時点までにトランザクションの前提としたStateの状 態が変わってしまうケースがある • i.e. 他のトランザクションによって更新 • 前提が変わっている場合には検出してトランザクションを無効にする必要が ある 復習:Read-Set Validation Copyright © 2022 Oracle and/or its affiliates 34 World State <read key=“A", version=“3"> <write key=“A", value=“800”> Key Value Version A 0 4 不一致
  26. CouchDBでのリッチクエリでの例 リッチクエリとは • HLFではState DBとして利用しているデータベース側の機能を利用し、そのデータベースネイティブのクエリ文によりWorld Stateお よびPrivate Dataの検索を行うリッチクエリを利用することができる • getQueryResult、getPrivateDataQueryResultでクエリ文を渡す

    • KeyではなくValueの内容を検索条件に使えるのが非常に強力な点…ビジネスロジックの表現力の大幅な拡張 • どのようなリッチクエリを使えるかはState DBとして利用するデータベースに依存する • State DBにCouchDBを利用している場合、ValueをJSONにして格納しておくと、JSONの属性とその値を条件に指定したクエリ (⇨JSONリッチクエリ)が利用可能 • 例:{“owner” : “Bob”, “color” : “Red”, “size” : “100” }というような項目を持ったmarbleアイテムに対して、owner がBobである、colorがRedでない、sizeが50より大きいといった条件で検索 Phantom Read問題にかかる制約 • リッチクエリを含む一部のレンジクエリはValidation時に再実行されない • 本来結果セットのレンジに入るべきレコードがEndorsement~Validationフェーズの間で追加、更新により増えていても検知 できない(Phantom Readの発生を検知できない) • ロジックの意図とデータの更新結果の不整合を起こす可能性があるため、(運用上の特別な考慮をしてPhantom Readの発生 可能性を排除できない限り)更新トランザクションで使用してはならない Phantom Read問題 Copyright © 2022 Oracle and/or its affiliates 35
  27. 物の所有権をHLFの台帳上で管理しており、初期状態は以下とする CouchDBのPhantom Read問題:事象の例① Key: Item ID Value: JSON形式 Item1 {“owner”

    : “Alice”, “color” : “Blue”, “size” : “50” } Item2 {“owner” : “Bob”, “color” : “Red”, “size” : “100” } Item3 {“owner” : “Carol”, “color” : “Yellow”, “size” : “80” } • この状態からふたつの更新トランザクションを間を置かずに発行する – Tx1 :Carolの持ち物をすべてAliceに譲渡する…ownerがCarolのものをAliceに更新する – Tx2 :Aliceの持ち物をすべてBobに譲渡する…ownerがAliceのものをBobに更新する • State DBとしてCouchDBを使用しており、Owner値による更新すべきレコードの抽出にはリッチクエリを使用する前提とす る Copyright © 2022 Oracle and/or its affiliates 36
  28. まずCarolの持ち物をすべてAliceに譲渡したのちにAliceの持ち物をすべてBobに譲渡したいので、Tx 1 とTx 2 の実行後の 期待される結果は以下 CouchDBのPhantom Read問題:事象の例② しかしCouchDBではPhantom Read問題により以下の結果になる場合がある

    Item ID Owner初期状態 中間状態(Tx1後) 結果(Tx2後) Item1 Alice Alice Bob Item2 Bob Bob Bob Item3 Carol Alice Bob Item ID Owner初期状態 中間状態(Tx1後) 結果 Item1 Alice Alice Bob Item2 Bob Bob Bob Item3 Carol Alice Alice 取りこぼし Copyright © 2022 Oracle and/or its affiliates 37
  29. トランザクションが以下の時系列で処理されると意図しない結果が発生する • Tx 1 のEndorsementをE 1 、ValidationをV 1、 Tx 2

    も同様にE 2 とV 2 とし、OrderingをOと表記 CouchDBのPhantom Read問題:事象の例③ E1 E2 O V2 V1 Item ID 初期状態~V1前まで V1後 V2後 Item1 Alice Alice Bob Item2 Bob Bob Bob Item3 Carol Alice Alice Copyright © 2022 Oracle and/or its affiliates 38
  30. • V 2 でAliceの持ち物であるにもかかわらず、Item3の取りこぼしが生じている • Tx 2 でのリッチクエリ結果にはItem3が含まれておらず、したがってRead-Set ValidationにItem3は含まれず取りこ ぼしは検知できない

    • このようなパターンの不整合を検知するにはValidationフェーズでのレンジクエリの再実行が必要 CouchDBのPhantom Read問題:事象の例③ E1 E2 O V2 V1 Item ID 初期状態~V1前まで V1後 V2後 Item1 Alice Alice Bob Item2 Bob Bob Bob Item3 Carol Alice Alice Copyright © 2022 Oracle and/or its affiliates 39 V2 Validation
  31. 単一ChannelでのChaincode呼び出し • 単一Channel上で複数Chaincodeを稼働させることが(ふつうに)可能 • ただし、あるChaincodeが台帳/Private Data Collectionに書き込んだレコードは、そのChaincodeからしか直接アクセスで きない • Chaincode

    A on Channel Xが書き込んだレコードは、Chaincode B on Channel Xからは直接にはアクセスできない • World State/Private Dataだけでなく、Blockchainから取得できるキー履歴、トランザクション履歴の参照にもこの制約が ある • Chaincodeから同一Channel内で稼働する別のChaincodeを呼び出すことが可能 • Chaincode A on Channel X⇒Chaincode B on Channel Xは可能 • Chaincode A on Channel XがChaincode B on Channel Xが書き込んだレコードを参照/更新したいときは、 Chaincode Bを経由すれば参照/更新できる • ただし、実行するPeerには呼び出し元と呼び出し先両方のChaincodeがInstallされていることが必要 • 管理が煩雑になるので再利用性の理由のみなどでのChaincode分割は推奨しない • 単一Channel上であれば複数のChaincodeが絡んでも単一トランザクションとなり、RWSetも共有している Chaincode内Chaincode呼び出し Copyright © 2022 Oracle and/or its affiliates 40
  32. DogCC 例:複数種類のトークンを扱う場合 • 複数種類のトークンをひとつのChaincodeでまとめて管理することもできる • 例①:ひとつのChaincode内で複数種類のNFTを扱い、互いに交換可能にする • 例②:ひとつのChaincode内でNFTとFTを扱い、DVP(Delivery Versus Payment)をやる

    • トークンごとに分けても良い • この場合、異種トークンの交換は専用のChaincodeを作り、そこから各トークンのChaincodeを呼ぶ 41 Copyright © 2022 Oracle and/or its affiliates SuperTokenChaincode DogNFT CatNFT PericaFT 交換ロジック Dog ロジック Cat ロジック Perica ロジック ExchangeChaincode 交換ロジック DogNFT Dog ロジック CatCC CatNFT Cat ロジック PericaCC PericaFT Perica ロジック
  33. 別ChannelのChaincode呼び出しに関わる制約 • ChaincodeはChannelごとにインスタンス化(Instantiate)され稼働しており、呼び出し(Invoke)する際もChannelを指定 して呼び出し実行させる • あるChannelでInvokeされたChaincodeから他のChannel上のChaincodeを呼び出し、台帳(およびPrivate Data)を参 照することは可能だが、呼び出し先のChannelの台帳の更新を実行することはできない • Chaincode

    A on Channel XからChaincode B on Channel Yを呼び出してChannel Yの台帳をクエリした結果を Chaincode Aから利用することは可能だが、Channel Yの更新は不可ということ • Channelごとに台帳が存在する、つまりChannelが異なれば別の台帳であり、ステートおよびトランザクションは共有していないという ことに留意が必要 • 整合性、一貫性を担保する仕組みはChannelごとにしか用意されていない/機能しない • Chaincodeから他のChannelのChaincodeを呼び出してクエリした際にタイミングマターが生じ、複数Peer間でのクエリ結果が 異なる可能性がある Chaincode内Chaincode呼び出し Copyright © 2022 Oracle and/or its affiliates 42
  34. • Chaincodeは台帳(のデータ)の更新の唯一の手段である • Chaincodeは台帳のデータを通じた複数組織間のコミュニケーションのメッセージングインターフェース であり、同時に台帳のデータ構造定義とデータに対してのロジックを担う • Chaincode SDKを通じて実装する • 開発言語はNode.js、Go、Javaが選べる

    • ChaincodeのSDKはそれほど難しくない • 多くの場合、Chaincodeはそれほど複雑にも大規模にもならない • 向いていない、できない、知らないとハマるなど、Chaincodeロジックの設計あるいは実装にあたって 注意が必要な点は抑えておく Chaincodeまとめ Copyright © 2022 Oracle and/or its affiliates 43 Client App Fabric SDK Peerノード Ledger Chaincode
  35. • HLFの種々の機能を利用するアプリケーションのこと…… だが、主にはHLFのトランザクションを使うアプリケーションをクライアントアプリケーションと 呼んでいる(→トランザクションの主体である) • トランザクションにおいて以下の役割を担う • Peerノードに対してChaincode実行を依頼する • Peerノードから返ってきたEndorsementを集める

    • Ordering ServiceにTransaction(メッセージ)を送付する • クライアントアプリケーションは一般にHLFとのインタラクション以外にも色々と役割を持たさ れるが、そのあたりは一般のアプリケーション開発の範疇なのでここではあまり触れない クライアントアプリケーションとは? Copyright © 2022 Oracle and/or its affiliates 45 Client App Fabric SDK Peerノード Ledger Chaincode 証明書
  36. 凡例 D社 C社 B社 A社 ノード コンソーシアム型ブロックチェーンの一般的な概観 Copyright © 2022

    Oracle and/or its affiliates SC L ノード SC L ノード SC L ノード SC L アプリ ブロックチェーン プラットフォーム アプリ オペレーター 他システム SC スマート コントラクト L 台帳 A社の所管するシステムの範囲 アプリ アプリ 46 ブロックチェーンノードは コンソーシアム内で分散して 所有/管理/運用
  37. ノード ノード ブロックチェーンノード エンタープライズでのブロックチェーンを利用したシステムのイメージ Copyright © 2022 Oracle and/or its

    affiliates 47 台帳 スマート コントラクト アプリ ケーション データベース 既存 データベース ユーザー アプリ連携 データ統合 ブロックチェーンと同内容 のデータをDBに複製 BIツール ERP、SCM等 基幹システム ERP、SCM等 基幹システム ERP、SCM等の 基幹システムや 他アプリケーション 既存 データベース 既存 データベース トランザクション発行 47
  38. • クライアントアプリケーションは通常、Fabric SDKを用いて実装する • Fabric SDKはNode.js版とJava版が正式リリース • Node.js版:fabric-network パッケージを用いる…高レベルなAPI、現在の推奨 •

    低レベルなAPIはfabric-common パッケージ • Java版:Hyperledger Fabric Gateway SDK for Javaを用いる…高レベルなAPI、現在の推奨 • 低レベルなAPIはHyperledger Fabric SDK for Java • Node.js版とJava版のSDKでは細かい機能の有無や粒度、実装お作法などはだいぶ異なっているが、実質的にでき ることはおおよそ同じ(※のはず…) • アプリケーション設計、実装にあたっての抽象的な概念(設計要素)は共通しているので、ここではその要素の話を していく クライアントアプリケーションの実装 Copyright © 2022 Oracle and/or its affiliates 48
  39. Fabric SDKの主要要素:Wallet Copyright © 2022 Oracle and/or its affiliates 50

    from: https://hyperledger-fabric.readthedocs.io/ja/latest/developapps/wallet.html • クライアントアプリケーションが用いるHLFネットワーク上のユーザーアイデンティティの(抽象的な)ストア • 秘密鍵/証明書ペアにIDラベルを付けてWalletに追加し、以降そのIDラベルによってWalletからアイデンティティを用いる • ファイルシステムWallet、インメモリWallet、CouchDB Walletの形態から選べる • 秘密鍵をHSMに格納することも可 • 秘密鍵/証明書ペアの作成/発行は Fabric CA Clientなどで予めやっておく (Walletのスコープ外)
  40. • クライアントからHLFのネットワークコンポーネント(Peer、Ordererなど)に対してメッセージを送る際に、「どこにいるどのコンポーネ ントにメッセージを送信するか」を抽象化して管理してくれる要素 • あるChannelのあるChaincodeのトランザクションを実行したい場合、Channel参加有無、Chaincodeインストール有無や Endorsement PolicyなどによってTransaction Proposal送信先のPeerの使い分けが必要で、Gatewayがそのあたりを やってくれる •

    ネットワークコンポーネントからクライアントアプリケーションへのメッセージ受け取り(Eventなど)も管理してくれる • Connection Profileの設定(YAMLまたはJSONで記述)に基づいて動作する • 動的なConnection Profile:最小限の設定を記述しておき、PeerのService Discovery機能により動的にネットワーク 構成情報(トポロジーやノードの死活、Channel参加有無、Endorsement Policy、Private Data Collection参加有 無など)を取得する • 静的なConnection Profile:上記の全てのネットワーク構成情報を予め記載しておく • クライアントアプリケーションはTransaction Proposal(Chaincode実行依頼)送信先をGatewayの動的な制御に任せ ることもでき、ネットワークの構成情報を取得したうえで自身で細かく指定することもできる • 現状ではトランザクションの中で触るPrivate Data CollectionやCollection-Level/State-Levelの細かい Endorsement Policyまでは動的には考慮してくれない模様なので、そのあたりを使う場合自身で指定してやる必要アリ Fabric SDKの主要要素: Gateway Copyright © 2022 Oracle and/or its affiliates 51
  41. • トランザクションの一連のプロセスを抽象化し実行してくれる • EndorsementフェーズでのPeerへのTransaction Proposalメッセージの送信~Endorsementの収集 • OrderingフェーズでのOrdering ServiceへのTransactionメッセージの送信 • Validationフェーズでのトランザクション結果のEventメッセージ受け取り

    • 前提としてWallet(および用いるユーザーアイデンティティ)、Gatewayの構成をしたうえでContractを用いてトランザクションを実 行する • 台帳の更新を行うトランザクション用の関数と、クエリ用の関数が用意されている • 【Node.js】submitTransaction/【Java】createTransaction …台帳の更新とValidation結果の取得まで行う • 【共通】evaluateTransaction …Chaincodeの実行結果レスポンスの取得まで(台帳は更新されない) Fabric SDKの主要要素: Contract Copyright © 2022 Oracle and/or its affiliates 52
  42. public static void main(String[] args) throws IOException { // Load

    an existing wallet holding identities used to access the network. Path walletDirectory = Paths.get("wallet"); Wallet wallet = Wallets.newFileSystemWallet(walletDirectory); // Path to a common connection profile describing the network. Path networkConfigFile = Paths.get("connection.json"); // Configure the gateway connection used to access the network. Gateway.Builder builder = Gateway.createBuilder() .identity(wallet, "user1") .networkConfig(networkConfigFile); // Create a gateway connection try (Gateway gateway = builder.connect()) { // Obtain a smart contract deployed on the network. Network network = gateway.getNetwork("mychannel"); Contract contract = network.getContract("fabcar"); // Submit transactions that store state to the ledger. byte[] createCarResult = contract.createTransaction("createCar") .submit("CAR10", "VW", "Polo", "Grey", "Mary"); System.out.println(new String(createCarResult, StandardCharsets.UTF_8)); // Evaluate transactions that query state from the ledger. byte[] queryAllCarsResult = contract.evaluateTransaction("queryAllCars"); System.out.println(new String(queryAllCarsResult, StandardCharsets.UTF_8)); } catch (ContractException | TimeoutException | InterruptedException e) { e.printStackTrace(); } } Java Gateway SDKを用いた実装サンプル: Copyright © 2022 Oracle and/or its affiliates 53 from: https://hyperledger.github.io/fabric-gateway-java/release-2.2/
  43. // Connect to a gateway peer const connectionProfileJson = (await

    fs.promises.readFile(connectionProfileFileName)).toString(); const connectionProfile = JSON.parse(connectionProfileJson); const wallet = await Wallets.newFileSystemWallet(walletDirectoryPath); const gatewayOptions: GatewayOptions = { identity: '[email protected]', // Previously imported identity wallet, }; const gateway = new Gateway(); await gateway.connect(connectionProfile, gatewayOptions); try { // Obtain the smart contract with which our application wants to interact const network = await gateway.getNetwork(channelName); const contract = network.getContract(chaincodeId); // Submit transactions for the smart contract const args = [arg1, arg2]; const submitResult = await contract.submitTransaction('transactionName', ...args); // Evaluate queries for the smart contract const evalResult = await contract.evaluateTransaction('transactionName', ...args); // Create and submit transactions for the smart contract with transient data const transientResult = await contract.createTransaction(transactionName) .setTransient(privateData) .submit(arg1, arg2); } finally { // Disconnect from the gateway peer when all work for this client identity is complete gateway.disconnect(); } Node.js fabric-network-apiを用いた実装サンプル: Copyright © 2022 Oracle and/or its affiliates 54 from: https://hyperledger.github.io/fabric-sdk-node/release-2.2/module-fabric-network.html
  44. • クライアントアプリケーションは通常、Fabric SDKを用いて実装する • Fabric SDKはNode.js版とJava版が正式リリース • 凝ったことをやろうとしなければSDKがよしなにやってくれる部分が多く、HLFでのトランザクション実行部分の実装は さほど難しくない •

    Connection Profile設定の用意、ユーザーアイデンティティ(CAを利用した秘密鍵/証明書の作成)の用意 は必要 • 前提としてHLFの構造、要素(アイデンティティ、Channel、Private Dataなど)とトランザクションフローの しっかりとした理解は必要 クライアントアプリケーションのFabric SDKを利用した実装まとめ Copyright © 2022 Oracle and/or its affiliates 55
  45. ノード ノード エンタープライズ領域でのユースケースの クライアントアプリケーションのイメージ Copyright © 2022 Oracle and/or its

    affiliates 台帳 Chaincode アプリ ケーション データベース 既存 データベース API ユーザー アプリ連携 データ統合 データ複製 集計・分析 ERP、SCM等 基幹システム ERP、SCM等 基幹システム ERP、SCM等 基幹システム 既存 データベース 既存 データベース HLF トランザクション 57
  46. • クライアントアプリケーション自体のビジネスロジック、UIなどの実装がもちろん必要 • 多くの場合、自身のローカルなデータストアを持つことになる • アプリケーションユーザーの認証…HLFのネットワークアイデンティティとは別の層(HLFでは一般的にエンドユーザーごとにネット ワークアイデンティティを割り当てることはしない) • 必要に応じて台帳からデータベースへのデータの複製を行う •

    集計、分析をデータベース上で行えるようになり、データの活用可能性が向上 • データ統合も容易になる • 別アプリケーション/システムとの連携 • エンタープライズのユースケースでは多くの場合、ERPやSCM、基幹システムとの連携が必要 • APIやインテグレーションツールを通じたアプリケーション連携 • 既存データとのデータ統合 • 関係先が増えると、HLF上のデータ(トランザクション)との整合性の考慮も必要に… • ChaincodeロジックおよびHLFトランザクション部分よりも、それ以外の側面のほうが開発ボリュームの割合は恐らくだいぶ大きくな る • ので、一般的な(エンタープライズ領域の)アプリケーション/システム開発のスキルも重要 クライアントアプリケーションのHLFトランザクション以外の役割 Copyright © 2022 Oracle and/or its affiliates 58
  47. • 基本的には分散システムでのデータストア間の整合性を保護する方法に準じる • 2PC/3PCは使えないのでSagaパターン、補償トランザクションなどで対応 • 最も難しいのはタイムアウト障害のハンドリング:複数データストアで共通に持つKeyを用意して冪等&リトライ可 能になるように設計しておくとベター • ブロックチェーンならではの注意すべきところは他参加者がいるところ •

    他参加者が台帳の更新を受けて直ちにアクションを取っても問題ないようにする必要 • 他参加者も同時にトランザクションを仕掛けていても整合性が崩れないようにしておく 複数データストア利用時の整合性保護の方式 Copyright © 2022 Oracle and/or its affiliates 61
  48. • 基本的には個別データストア→台帳の順序がおすすめ • オフチェーンの個別データストアは取り消しなどの手当がしやすく、他参加者にも伝わらない • 個別データストアでの更新が成功してから(成功する確証が取れてから)台帳の更新トランザクションを発行する • 個別データストア側の更新をロールバックできるならベター • 先にRDB側でトランザクション発行しホールド

    • HLFのトランザクションが確定(valid/committed)したらコミット • Proposalでエラーになるか、Validationフェーズでinvalidになったらロールバック • ロック長時間化による性能劣化の可能性には留意 ケース①:台帳&個別データストアを同時に更新したい Transaction Scope Copyright © 2022 Oracle and/or its affiliates 62
  49. 【PR】Oracle Blockchain Platformの REST APIでの複数Channel間アトミックトランザクションのサポート • 2フェーズコミットを用いたアトミックトランザクションをサポート • セットに含めた全てのトランザクションが揃ってコミット(反映)、 またはロールバック(撤回)される

    • Hyperledger Fabricを用いるうえで課題となりがちな 複数Channel間での更新の整合性担保を容易に • 例:Channel1でNFTの所有者を更新しつつ、 Channel2で代金としてコインの残高を移転 • REST ProxyのatomicTransactionsエンドポイントを使用 • Fabric SDK/gRPCでアトミックトランザクションを行いたい 場合は、後述のXAライブラリを利用 69 Copyright © 2022 Oracle and/or its affiliates クライアント アプリケーション REST Proxy Channel 1 REST API: atomicTransactions [ {Ch1でのTx1}, {Ch2でのTx2} ] {Ch1でのTx1} Channel 2 {Ch2でのTx2} アトミック Blockchain
  50. 【PR】Oracle Blockchain Platformの XA対応によるグローバル分散トランザクションのサポート • 分散トランザクションの標準であるX/Open XAに対応し、 Oracle Blockchain PlatformをXAリソースとして扱えるように

    • 分散トランザクションの一部としてブロックチェーンのトランザクションを 実行することが可能 • 2フェーズコミットにより、セットでのコミットまたはロールバック • エンタープライズで求められるデータ整合性の担保が容易に実装可能 • 複数Channel間でのアトミックトランザクション • データベース、メッセージキューなど他のXA対応リソースとのアト ミックなトランザクション • クライアントアプリケーションをJavaで実装し、OBPXAResource、 OBPXADataSource、OBPXAConnectionなどのライブラリを用いる ことで利用可能 70 Copyright © 2022 Oracle and/or its affiliates Ch1 Ch2 MQ DB Blockchain 他のXAリソース クライアントアプリケーション Tx Managerライブラリ OBP XA ライブラリ 他XAリソース ライブラリ トランザクションマネージャ Tx Tx Tx Tx アトミック
  51. • 10/11(火): Hyperledger Fabric(再)入門 • コンポーネントやトランザクションフローなど基本を解説 • 10/18(火):Hyperledger Fabricのネットワーク設計 •

    ブロックチェーンネットワークの設計の考え方、進め方を解説 • 10/25(火):Hyperledger FabricアプリとChaincodeの開発 • クライアントアプリケーションとChaincodeの開発方法を解説 • 11/1(火):Oracle Blockchain Platformを用いたHLFアプリ開発 • Oracle Blockchain Platformならではのメリット、開発方法を解説 集中講義シリーズ Copyright © 2022 Oracle and/or its affiliates 72
  52. Orderer Organization配下にPeer、Orderer、CAのコンポーネントとクライアントアプリケーション Hyperledger Fabricネットワークの概観図 Peer Client App CA Chain Code

    Ledger Orderer A社 Orderer Peer CA Chain Code Ledger Orderer Orderer Orderer Peer Chain Code Ledger CA Orderer CA Orderer Peer Chain Code Ledger B社 D社 C社 Client App Client App Client App Copyright © 2022 Oracle and/or its affiliates Hyperledger Fabric完全に理解した!! 73