Hyperledger Fabricのチェーンコードを実装していて気になったのでメモ。
Hyperledger Fabricってなんぞ?という方はこちらをご参考ください。
Amazon Managed BlockchainがリリースされたのでHyperledger Fabricも合わせて情報をまとめてみた - Qiita
https://qiita.com/kai_kou/items/5a968f42c5f96296f6fe
Amazon Managed BlockchainでHyperledger Fabricのブロックチェーンネットワークを構築してみた - Qiita
https://qiita.com/kai_kou/items/e02e34dd9abb26219a7e
getStateByRange
メソッドの範囲指定でendKey
は取得範囲に入らない
ひとまず再現コード抜粋。TypeScriptで実装しています。
TypeScriptを利用した実装方法については下記をご参考ください。
Hyperledger Fabricのチェーンコード(Node.js)をTypeScriptで実装できるようにしてみた - Qiita
https://qiita.com/kai_kou/items/0726c9a462bdcaf3856c
(略)
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には以下のようなデータが保存されている前提です。
[
{"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://qiita.com/kai_kou/items/5a968f42c5f96296f6fe
Amazon Managed BlockchainでHyperledger Fabricのブロックチェーンネットワークを構築してみた - Qiita
https://qiita.com/kai_kou/items/e02e34dd9abb26219a7e
Hyperledger Fabricのチェーンコード(Node.js)をTypeScriptで実装できるようにしてみた - Qiita
https://qiita.com/kai_kou/items/0726c9a462bdcaf3856c