[Blockchain]Hyperledger Fabricを試す(balans-transfer編)


目的

今回使用する予定なのは「fabcar」なのですが、「byfn」を試してみましたが、残りの「balance-transfer」も試してみます。

参考サイト

hyperledger/fabric-samplesのbalance-transferをUbuntu16.04で動かしてみた

起動

balance-transferはdockerコンテナで起動されるようです。
デーモンモードではないようなので、起動用と動作検証用の2つのセッションが必要になります。

まずは1つ目のセッションで起動を行います。

$ cd fabric-samples/balance-transfer
$ ./runApp.sh

    :

[xxxx-xx-xx 07:28:18.543] [INFO] SampleWebApp - ****************** SERVER STARTED ************************
[xxxx-xx-xx 07:28:18.545] [INFO] SampleWebApp - ***************  http://localhost:4000  ******************

動作検証

起動が完了したら、2つめのセッションで動作確認を行います。

$ cd fabric-samples/balance-transfer
$ ./testApis.sh

実行すると、Blockchain内の情報を取得できていることが分かります。
(実行結果はとても長いのでこちらへの記載は控えます)

解析

Blockchainの情報にはBlockHashとPreHashがありました。
BlockHashは自ブロックのハッシュ値、PreHashは直前のブロックのハッシュ値のようです。
この辺はHyperledger Explorerで確認するととてもわかり易いです。

先程実行したtestApis.shを見ると、いくつかのAPIを実行していることが分かります。
その中に、ブロック番号を指定したブロック情報の取得用APIがありました。

echo "GET query Block by blockNumber"
echo
BLOCK_INFO=$(curl -s -X GET \
  "http://localhost:4000/channels/mychannel/blocks/1?peer=peer0.org1.example.com" \
  -H "authorization: Bearer $ORG1_TOKEN" \
  -H "content-type: application/json")
echo $BLOCK_INFO
# Assign previous block hash to HASH
HASH=$(echo $BLOCK_INFO | jq -r ".header.previous_hash")
echo

ブロック番号を指定せず、チャンネル名の指定だけで実行すると、BlockChainの情報を取得することができました。

echo "GET Block Chain info"
echo
BLOCK_INFO=$(curl -s -X GET \
  "http://localhost:4000/channels/mychannel" \
  -H "authorization: Bearer $ORG1_TOKEN" \
  -H "content-type: application/json")
echo $BLOCK_INFO
# Assign previous block hash to HASH
HASH=$(echo $BLOCK_INFO | jq -r ".header.previous_hash")
echo

実行結果には以下のような情報が出力されており、最新ブロック番号が取得できていることが分かります。
今回の出力結果からは最新ブロック番号は「11」だと分かります。

GET Block Chain info

{"height":{"low":11,"high":0,"unsigned":true},"currentBlockHash":...

この「11」というブロック番号を先程のブロック番号を指定した情報取得のAPIで実行すれば、最新のブロック情報を取得できるということが分かりました。

そして、そのブロック情報にはトランザクション情報「tx_id」がありました。
このトランザクション情報を使用して、どのような結果だったのかを逆引きすることができます。

TRX_ID="fa16c35e58d7249eaadf786ab0b750ad4e26c3597882e014095ebb5af721a3d0"
echo "GET query Transaction by TransactionID"
echo
curl -s -X GET http://localhost:4000/channels/mychannel/transactions/$TRX_ID?peer=peer0.org1.example.com \
  -H "authorization: Bearer $ORG1_TOKEN" \
  -H "content-type: application/json"
echo
echo

実行結果は以下のようになります。

"writes":[{"key":"a","is_delete":false,"value":"30"},{"key":"b","is_delete":false,"value":"270"}]

このように、
(1)最新ブロック情報の取得
(2)ブロック情報を指定して特定ブロックの情報を取得
(3)ブロックにあるトランザクション情報を使用し実行結果を取得
と、(2)と(3)を繰り返し遡れば、過去の実行履歴を追跡することができそうです。

要員管理に応用できるか?

balance-transferのチェインコード(fabric-samples/balance-transfer/artifacts/src/github.com/example_cc/node/example_cc.go)を見ると、構造体の宣言がありました。

    let A = args[0];
    let B = args[2];
    let Aval = args[1];
    let Bval = args[3];

~/fabric-samples/balance-transfer/testAPIs.sh

ここに、初期値の登録と更新(invoke)時の処理の記載がありました。

chaincodeのインストール後、初期データとして、a=100、b=200の価値を登録しているようです。

curl -s -X POST \
  http://localhost:4000/channels/mychannel/chaincodes \
  -H "authorization: Bearer $ORG1_TOKEN" \
  -H "content-type: application/json" \
  -d "{
        \"chaincodeName\":\"mycc\",
        \"chaincodeVersion\":\"v0\",
        \"chaincodeType\": \"$LANGUAGE\",
        \"args\":[\"a\",\"100\",\"b\",\"200\"]
}"

更新時の処理として、aからbへ価値を10移動する処理もあります。

VALUES=$(curl -s -X POST \
  http://localhost:4000/channels/mychannel/chaincodes/mycc \
  -H "authorization: Bearer $ORG1_TOKEN" \
  -H "content-type: application/json" \
  -d "{
  \"peers\": [\"peer0.org1.example.com\",\"peer0.org2.example.com\"],
  \"fcn\":\"move\",
  \"args\":[\"a\",\"b\",\"10\"]
}")

chaincode「example_cc.go」の94、95行には計算式もありました。

 94     Aval = Aval - amount;
 95     Bval = Bval + amount;
 96     console.info(util.format('Aval = %d, Bval = %d\n', Aval, Bval));

ここまでの解析しかできていませんが、構造体の宣言については要員管理に即したエンティティに変更すれば、より複雑な構造を定義できそうです。
ただ、特定のデータの検索やデータの修正など、APIを使用してどのように行えばよいのかまでは到達できませんでした。

おわりに

今回の検証はとても有意義な内容でした。
Hyperledger Explorerもひょっとしたら内部でAPIを実行して情報を得ているのかもしれません。
独自のGUIを作成する際にはこれらのAPIを実行すればよいのではという発想燃えることができました。
ただし、特定のデータの検索はデータの修正など、APIでどのように行えばよいのかまでは理解することができませんでした。
課題はまだ多く残っていますが、このbalans-transferで検証できたAPIがかなり重要だということが分かりました。