Hyperledger Fabricのチェーンコードを実装していて気になったのでメモ。
Hyperledger Fabricってなんぞ?という方はこちらをご参考ください。
Amazon Managed BlockchainがリリースされたのでHyperledger Fabricも合わせて情報をまとめてみた – Qiita
https://cloudpack.media/46950
Amazon Managed BlockchainでHyperledger Fabricのブロックチェーンネットワークを構築してみた – Qiita
https://cloudpack.media/46963
getStateByRange
メソッドの範囲指定でendKey
は取得範囲に入らない
ひとまず再現コード抜粋。TypeScriptで実装しています。
TypeScriptを利用した実装方法については下記をご参考ください。
Hyperledger Fabricのチェーンコード(Node.js)をTypeScriptで実装できるようにしてみた – Qiita
https://cloudpack.media/47504
チェーンコード実装(抜粋)
(略) async Invoke(stub: ChaincodeStub): Promise<ChaincodeResponse> { let ret = stub.getFunctionAndParameters(); const {fcn, params} = stub.getFunctionAndParameters(); console.info(ret); const method = (this as any)[fcn]; if (!method) { throw new Error('Received unknown function ' + ret.fcn + ' invocation'); } try { let payload = await method(stub, params); return Shim.success(payload); } catch (err) { return Shim.error(err); } } async queryByRange(stub: ChaincodeStub, args: string[]): Promise<Buffer> { if (args.length != 2) { throw new Error('Incorrect number of arguments.'); } let startKey = args[0]; let endKey = args[1]; let results = []; let iterator = await stub.getStateByRange(startKey, endKey); while(true) { const res = await iterator.next(); if (res.value && res.value.value.toString()) { let item = JSON.parse(res.value.value.toString('utf8')); results.push(item); } if (res.done) { await iterator.close(); return Buffer.from(JSON.stringify(results)); } } } (略)
value.value
とか気持ち悪いなぁ.toString('utf8')
って'utf8'
を指定しないと’JSON.parse’ できなくてハマります。
ステートDBには以下のようなデータが保存されている前提です。
ステートDBの中身
[ {"id":"hoge01","hoge":"hoge"}, {"id":"hoge02","hoge":"hoge"}, {"id":"hoge03","hoge":"hoge"} ]
で、チェーンコードのqueryByRange
を実行して情報を取得してみます。
※Fablic CLIで実行、パラメータはいろいろ省略しています。
> docker exec cli peer chaincode query \ -o $ORDERER -C mychannel -n $cc_name \ -c '{"function":"queryByRange","Args":["hoge01", "hoge01"]}' []
あれ取れない。
> docker exec cli peer chaincode query \ -o $ORDERER -C mychannel -n $cc_name \ -c '{"function":"queryByRange","Args":["hoge01", "hoge02"]}' [{"id":"hoge01","hoge":"hoge"}]
お、まさか。。。
> docker exec cli peer chaincode query \ -o $ORDERER -C mychannel -n $cc_name \ -c '{"function":"queryByRange","Args":["hoge01", "hoge03"]}' [{"id":"hoge01","hoge":"hoge"},{"id":"hoge02","hoge":"hoge"}]
なるほど。endKey
は取得対象外なのね。。。
気になって仕様を確認してみたら確かにそういう仕様でした。
Hyperledger Fabric Node.js Contract and Shim Class: ChaincodeStub
https://fabric-shim.github.io/master/fabric-shim.ChaincodeStub.html
Returns a range iterator over a set of keys in the ledger. The iterator can be used to iterate over all keys between the startKey (inclusive) and endKey (exclusive).
Google翻訳
元帳の一連のキーに対する範囲反復子を返します。 反復子はstartKey(これを含む)とendKey(これを含まない)の間のすべてのキーを反復処理するために使用できます。
endKey(これを含まない)
oh…
そうですか。
キーに数値を含めてインクリメントする場合ならまあ対応は楽ですが、キーにULIDを利用しようとしてたのでこれはちっと面倒な感じです。むむむぅ。
参考
Hyperledger Fabric Node.js Contract and Shim Class: ChaincodeStub
https://fabric-shim.github.io/master/fabric-shim.ChaincodeStub.html
Amazon Managed BlockchainがリリースされたのでHyperledger Fabricも合わせて情報をまとめてみた – Qiita
https://cloudpack.media/46950
Amazon Managed BlockchainでHyperledger Fabricのブロックチェーンネットワークを構築してみた – Qiita
https://cloudpack.media/46963
Hyperledger Fabricのチェーンコード(Node.js)をTypeScriptで実装できるようにしてみた – Qiita
https://cloudpack.media/47504
元記事はこちら
「Hyperledger Fabricのチェーンコードで'getStateByRange'の仕様が微妙っぽかったので調べてみたら微妙だった」