Hyperledger Fabric と戯れる part.4
Writing Your First Application (つづき)
前回に続き、Writing Your First Application チュートリアルをすすめてく。
hyperledger-fabric.readthedocs.io
node query.js
前々回あたりからチラホラ query とか invoke とか普通に言ってたが、基本的に query は参照などの read only なアクセス、invoke は追加・更新などの write を伴うアクセスに使う。
(実際のところ invoke で read only な事とかも出来たりするので不正確だったりするけど、まあさておき。)
../../basic-network/connection.json
をccp
として読み込み- 前回と同じ
- 以下、
mychannel
へのアクセスをするために使用している
new FileSystemWallet()
として./wallet
を使用- 前回と同じ
- これまでの操作により、
./wallet
にはadmin
とuser1
の Identity が存在している
gateway.connect(ccp, {wallet, identity: 'user1' ...})
でuser1
としてゲートウェイに接続admin
でなくuser1
として接続する点以外は前回と同じ- これで、各ノードに対し
wallet
を使用して接続し、client
のuser1@org1.department1
として振舞える
network = await gateway.getNetwork('mychannel')
でmychannel
へのアクセスを獲得contract = network.getContract('fabcar')
で ChainCodefabcar
へのアクセスを獲得result = await contract.evaluateTransaction('queryAllCars')
で ChainCode のqueryAllCars()
をコール- Hyperledger Fabric SDK for node.js Class: Contract
- 引数を渡したいときは第二引数以降に渡す
- 結果は result に JSON として返る
- 現在保存されている全ての car 情報が返ってきている
で、肝心の ChainCode 側を見ていく。ChainCode 側のドキュメントはこちら。
lib/fabcar.js
が本体。 (index.js
もあるけど、module の export しかしてない)
class FabCar extends Contract
のように fabric-contract-api.Contract
を継承しているクラスのメソッドがそのまま SDK 側から呼べるようになっている。
メソッドは Context
クラスを第一引数に必ず取り、以降の引数(省略可能) を取れば、クライアントSDK側からデータを受けとることができる。
詳しくはこちらを参照。
なお、Context の class API にはクラス変数の説明がないが上記ドキュメントの「Structure of the Transaction Context」を読めばわかる通り、ctx.stub
で ChainCodeStub
オブジェクト、 ctx.identity
で ClientIdentity
オブジェクトをそれぞれ取得できる。
-
ClientIdentity
- Hyperledger Fabric Node.js Contract and Shim Class: ClientIdentity
- 名前の通りリクエスト元クライアントの Identity 情報。今回の場合
./wallet/user1/user1
に含まれていた証明書の内容 getAttributeValue()
は同証明書における1.2.3.4.5.6.7.8.1
の値のattrs
にあった Object に対する getter- たとえば、
getAttributevalue("hf.Affiliation")
の結果は"org1.department1"
になる
- たとえば、
-
ChainCodeStub
- Hyperledger Fabric Node.js Contract and Shim Class: ChaincodeStub
- 台帳への getter/setter や、リクエストに関する情報などが含まれる
やってることは単純にこれだけ。
FabCar.queryAllCars(ctx)
ctx.stub.getStateByRange(...)
で車データを全件取得する- データは
Buffer
なので、toString()
したりJSON.parse()
したりして JSON に変換 - 文字列に戻して
return
なお、取得したデータは startFabric.sh
で invoke
していた、initLedger()
で格納している。
せっかくなので内容を見てみるけど、queryAllCars
以上にやってる事は単純。
FabCar.initLedger(ctx)
- 初期データを定義
ctx.stub.putState(...)
で 1 つずつ保存していく
node invoke.js
query.js
と diff を取るとわかるが、違いは最後の contract.evaluateTransaction('queryAllCars')
が contract.submitTransaction('createCar', ...)
になっている事と、明示的に gateway.disconnect()
しているところのみ。
evaluateTransaction -> submitTransaction
- Hyperledger Fabric SDK for node.js Class: Contract
- 名前の通りで、
query
は「トランザクションの評価」をしていただけで、invoke
では「トランザクションの送信」をしている
FabCar.createCar()
- 引数で指定された内容で Car オブジェクトを作って、それを
ctx.stub.putState()
で保存してるだけ
- 引数で指定された内容で Car オブジェクトを作って、それを
gateway.disconnect()
の実行- コメントアウトして実行してみるとわかるけど、これをやらないと
invoke.js
は永久に終わらない。 - 不可解だが、
query
にこの行を足しても問題は起きないし、極めて一般的な感覚としてconnect
したら必ずdisconnect
するべきと思うので、そういうもんだと思っておく
- コメントアウトして実行してみるとわかるけど、これをやらないと
おしまい
話長くなるかと思ったけど、すげえ短かった。
次回は Commercial paper tutorial をやる予定。