Hyperledger Fabricを学ぶ(15回目) サンプルネットワーク「Fabcar」の解説④「台帳情報更新のチェーンコード」
こんにちは。
このブログでは、ブロックチェーン関連を中心としたテック系の情報の紹介をしております。
この連載では、オープンソースのブロックチェーンプラットフォーム「Hyperledger Fabric」について、少しずつ勉強を進めてゆきます。
自分なりに公式のドキュメントを噛み砕きながら、分かり易くまとめて行きたいと思います。
前回に引き続き、サンプルネットワーク「Fabcar」で実行しているプログラムの内容について説明していきます。
今回は台帳情報の更新のためのプログラム「invoke.js」です。
台帳情報の更新用のチェーンコード
前回(こちら)でもお話致しましたが、Hyperledger Fabricのネットワーク上の台帳に、外部から直接アクセスすることはできません。
ネットワーク上の台帳にアクセスするためのチェーンコードを呼び出すことで、間接的に台帳の情報にアクセスすることになります。
前回(こちら)は台帳情報の取得用のプログラム「query.js」の中身を確認しましたが、今回は台帳の更新用のプログラム「invoke.js」を見ていきます。
「invoke.js」の実行
台帳の情報を更新するためのプログラムは、前回(こちら)の参照用のプログラムと比較して複雑になっています。
今回は台帳情報の更新を行うため、Ordererを使用します。
前回はPeerとチャネルだけのインスタンス生成でしたが、今回では20行目からチャネル、Peer、Ordererのインスタンスを生成しています。
// setup the fabric network
var channel = fabric_client.newChannel('mychannel');
var peer = fabric_client.newPeer('grpc://localhost:7051');
channel.addPeer(peer);
var order = fabric_client.newOrderer('grpc://localhost:7050')
channel.addOrderer(order);
キーバリューストアの作成や、ユーザー証明書の取得に関しては前回とほぼ同様です。
61行目で、今回実行したい台帳情報更新用のチェーンコードの指定と、チェーンコードが使用するパラメータの設定を行います。
// changeCarOwner chaincode function - requires 2 args , ex: args: ['CAR10', 'Barry'],
// must send the proposal to endorsing peers
var request = {
chaincodeId: 'fabcar',
fcn: 'createCar',
args: ['CAR10', 'Toyota', 'Purius', 'White', 'MasaAndTomo'],
chainId: 'mychannel',
txId: tx_id
//targets: let default to the peer assigned to the client
//chaincodeId: 'fabcar',
//fcn: '',
//args: [''],
//chainId: 'mychannel',
//txId: tx_id
"createCar"が今回実行したいチェーンコードです。
台帳へ新しい車の情報を追加するチェーンコードです。
"args"で設定しているのが"createCar"が新しい車を追加する際に使用する車の情報です。
実行したいチェーンコードの設定ができたので、あとは実行するだけかと思いますが、Hyperledger Fabricでは、台帳へ情報を書き込むためにもう一つ手順を踏む必要があります。
トランザクションの検証
台帳の書き込みを行う前に、書き込みの内容(ここではトランザクションと表現します)を事前に検証する必要があります。
検証はPeerが行います。
まず、トランザクションをPeerに対して送信を行い、Peerにトランザクションの内容を検証してもらいます。
76行目にて、チャネルへトランザクションを送信します。
// send the transaction proposal to the peers
return channel.sendTransactionProposal(request);
チャネルに登録されているPeerにトランザクションが送信され、内容の検証が行われます。
77行目から、Peerに送信したトランザクションの検証結果の確認を行っています。
}).then((results) => {
var proposalResponses = results[0];
var proposal = results[1];
let isProposalGood = false;
if (proposalResponses && proposalResponses[0].response && proposalResponses[0].response.status === 200) {
isProposalGood = true;
console.log('Transaction proposal was good');
検証結果”results”には検証結果が1番目に、リクエストそのものが2番目に格納されています。
検証結果が"200"で返却されていることをここで確認しています。
次に、実際に台帳情報の更新を行うために、Ordererへのトランザクション送信に移ります。
Ordererへの送信
台帳への情報の書き込みは、Peerにて検証済みのトランザクションをOrdererを経由することで実行されます。
Ordererの役割については、以前Ordererについて書いた記事(こちら)も参考にしてください。
88行目にて、Peerの検証結果の確認を行い、検証結果がGoodの場合、Ordererへの送信処理が開始されます。
if (isProposalGood) {
console.log(util.format(
'Successfully sent Proposal and received ProposalResponse: Status - %s, message - "%s"',
proposalResponses[0].response.status, proposalResponses[0].response.message));
// build up the request for the orderer to have the transaction committed
var request = {
proposalResponses: proposalResponses,
proposal: proposal
};
94行目で、Ordererに送信するトランザクションの中身を設定しています。
ここで設定しているのはPeerで検証した検証結果とリクエストそのものです。
105行目にて、Ordererにトランザクションの送信を行っています。
var sendPromise = channel.sendTransaction(request);
106行目以降で、Ordererに対して送信したトランザクションのコミットを待つ処理がありますが、ここでは説明を省かせてもらいます。
150行目から、Ordererへのトランザクションの送信結果の確認を行っています。
}).then((results) => {
console.log('Send transaction promise and event listener promise have completed');
// check the results in the order the promises were added to the promise all list
if (results && results[0] && results[0].status === 'SUCCESS') {
console.log('Successfully sent transaction to the orderer.');
} else {
console.error('Failed to order the transaction. Error code: ' + response.status);
}
if(results && results[1] && results[1].event_status === 'VALID') {
console.log('Successfully committed the change to the ledger by the peer');
} else {
console.log('Transaction failed to be committed to the ledger due to ::'+results[1].event_status);
}
送信結果"results"にはOrdererへトランザクションが送信されたかの結果と、トランザクションがコミットされたかの結果が含まれています。
Ordererへのトランザクションの送信結果が"Success"で、トランクションのコミット結果が"Valid"であれば台帳情報の更新は完了しています。
まとめ
今回の台帳情報更新用のプログラム"invoke.js"の処理の流れを図にするとこんな感じでしょうか。
前回の台帳情報の取得プログラムと違って、更新用のプログラムはその内容を一度Peerで検証し、Ordererを経由することで初めて台帳情報を更新することができるのがポイントです。
今回までで、サンプルネットワーク「Fabcar」の解説についてはいったん終了としようと思います。
次回以降もしばらく、Hyperledger Fabricの紹介・解説について連載していこうと思います。
おわり。