39
38

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

Hyperledger Fabric のチェーンコードを実装する

Last updated at Posted at 2016-10-24

オープンソースのブロックチェーン Hyperledger Fabric を試してみる の続き

Hyperledger Fabric のチェーンコードを書いてみたときのメモです。
Bluemix 上の IBM Blockchain を使っています。

途中までのメモ書きなので、また随時書き足していく予定です。

チェーンコードとは

チェーンコードは Fabric ネットワーク上にデプロイされ、トランザクションを処理するプログラムコードです。
Fabric では、スマートコントラクトをチェーンコードとして実現しています。

今現在、Fabric がサポートしているチェーンコードの開発言語は Go と Java で、JavaScript も近い将来に追加されるとのことです。
今回は Go を使ってチェーンコードを書いていきます。

開発言語については Q&A で取り上げられています:
http://hyperledger-fabric.readthedocs.io/en/latest/FAQ/chaincode_FAQ/

チェーンコードを書いてみる

今回は、IBM Blockchain の learn-chaincode にチェーンコード実装のチュートリアルがあるため、それに沿って進めてみます。
https://github.com/IBM-Blockchain/learn-chaincode

サンプルのチェーンコードをクローンする

まず https://github.com/IBM-Blockchain/learn-chaincode をフォークし、ローカル環境の $GOPATH/src/github.om/<GITHUB_ID>/ にクローンします。

% cd $GOPATH
% mkdir -p src/github.com/<YOUR_GITHUB_ID_HERE>/
% cd src/github.com/<YOUR_GITHUB_ID_HERE>/
% git clone https://github.com/<YOUR_GITHUB_ID_HERE>/learn-chaincode.git

GOPATH は Go のワークスペースの場所を指します。未設定の場合は、以下のように設定してください。
(GOPATH について: http://golang-jp.org/doc/code.html#GOPATH)

export GOPATH=$HOME/.go
export PATH=$PATH:$GOPATH/bin

その他、Go の環境セットアップについては以降割愛します。Go についての基礎はこちら。

クローンしたリポジトリには、startfinished の二つのバージョンのチェーンコードがあります。

start にあるチェーンコードを変更しつつ、迷ったら finished を都度参照するという形で進めます。

ローカル環境でビルドを確認する

次に start のチェーンコードをローカル環境でビルドしてみて、正常に実行可能かの確認をします。

% cd $GOPATH/src/github.com/<YOUR_GITHUB_ID_HERE>/learn-chaincode/start
% go build ./
chaincode_start.go:23:2: cannot find package "github.com/hyperledger/fabric/core/chaincode/shim" in any of:
        /Users/<USER_NAME>/.anyenv/envs/goenv/versions/1.4/src/github.com/hyperledger/fabric/core/chaincode/shim (from $GOROOT)
        /Users/<USER_NAME>/.go/src/github.com/hyperledger/fabric/core/chaincode/shim (from $GOPATH)

ビルドするとエラーが出ました。環境設定が上手くいっていないようなので、以下を確認します。
https://github.com/IBM-Blockchain/learn-chaincode/blob/6827af167c8e46c289c1cb23d96b36fe97846875/docs/setup.md

Hyperledger Fabric が必要なようなので、クローンします。
Bluemix 上の IBM Blokchain では v0.5-developer-preview が使用されているので、それをローカルにクローンします。

% mkdir -p $GOPATH/github.com/hyperledger
% cd $GOPATH/github.com/hyperledger
% git clone -b v0.5-developer-preview https://github.com/hyperledger-archives/fabric.git

また、v0.5-developer-preview に対応しているのは v1.0 ブランチなので、そちらに切り替えます。

% cd $GOPATH/src/github.com/<YOUR_GITHUB_ID_HERE>/learn-chaincode
% git checkout v1.0

これで再度ビルドします。

% cd $GOPATH/src/github.com/<YOUR_GITHUB_ID_HERE>/learn-chaincode/start
% go build ./
% ls
chaincode_start.go start

今度は上手くいきました。ビルド結果の start が作成されています。

チェーンコードを書き換える

作成したコードはこちらにあります。
https://github.com/kyrieleison/learn-chaincode/blob/v1.0/start/chaincode_start.go

チェインコードを書くときには、3つの関数(init, invoke, query)と main 関数が必要です。

  • init
    • チェーンコードをデプロイしたときに呼び出される関数で、チェーンコードに必要な初期化処理を行います
    • 今回は初期化処理として、与えられた引数を hello_world キーに対するバリューとしてステートに追加しています
  • invoke
    • 何か実作業を行うための関数を呼び出したいときに呼び出す関数で、チェーン上のブロックにグループ分けされたトランザクションとして記録されます。function パラメータを受取って、その関数を実行するようにします
    • 今回は function パラメータとして write を受け取ったとき、二つの引数のうち一つをキー、もう一つをそのキーのバリューとしてステートに書き込みます
  • query
    • チェーンコードのステートを照会するときに呼び出す関数で、キーバリュー型のステートを取得します
    • 今回は function パラメータとして read を受け取ったとき、その引数をキーとしてステートを取得し、バリューを返します

REST API で確認する

チェーンコードがデプロイ・実行・参照できるかを、IBM Blockchain の REST API で確認してみます。

チェーンコードの操作にはユーザログインが必要なので、Registrar API で任意のユーザにログインします。

POST https://b43adcdd35ba429d9a5045427432ee82-vp2.us.blockchain.ibm.com:444/registrar
{
  "enrollId": "<ENROLL_ID>",
  "enrollSecret": "<ENROLL_SECRET>"
}

{
  "OK": "Login successful for user '<ENROLL_ID>'."
}

無事にログインできたら、Chaincode API でチェインコードをデプロイします。chaincodeID.path には、自分のフォークしたリポジトリのパスを指定します。

POST https://b43adcdd35ba429d9a5045427432ee82-vp2.us.blockchain.ibm.com:444/chaincode
{
  "jsonrpc": "2.0",
  "method": "deploy",
  "params": {
    "type": 1,
    "chaincodeID": {
      "path": "https://github.com/kyrieleison/learn-chaincode/start"
    },
    "ctorMsg": {
      "function": "init",
      "args": [
        "hi there"
      ]
    },
    "secureContext": "<ENROLL_ID>"
  },
  "id": 1
}

{
  "jsonrpc": "2.0",
  "error": {
    "code": -32001,
    "message": "Deployment failure",
    "data": "Error when deploying chaincode: Error getting chaincode package bytes: Error getting code 'go get' failed with error: 'exit status 2'\n# github.com/kyrieleison/learn-chaincode/start\n/go/_usercode_/440950172/src/github.com/kyrieleison/learn-chaincode/start/chaincode_start.go:41: undefined: shim.ChaincodeStubInterface\n/go/_usercode_/440950172/src/github.com/kyrieleison/learn-chaincode/start/chaincode_start.go:50: undefined: shim.ChaincodeStubInterface\n/go/_usercode_/440950172/src/github.com/kyrieleison/learn-chaincode/start/chaincode_start.go:63: undefined: shim.ChaincodeStubInterface\n"
  },
  "id": 1
}

デプロイが失敗しました。
undefined: shim.ChaincodeStubInterface... というエラーが出ていますが、これは v2.0 のAPIです。
v1.0 のブランチに対してコードをプッシュしていて、しかし パスに指定していた https://github.com/kyrieleison/learn-chaincode/start はデフォルトブランチである master ブランチのコードを go get するため、v2.0 のコードが読み込まれてエラーになったようです。

そこで、リポジトリにある v1.0 ブランチを、デフォルトブランチに変更して再度実行してみました。

POST https://b43adcdd35ba429d9a5045427432ee82-vp2.us.blockchain.ibm.com:444/chaincode
{
  "jsonrpc": "2.0",
  "method": "deploy",
  "params": {
    "type": 1,
    "chaincodeID": {
      "path": "https://github.com/kyrieleison/learn-chaincode/start"
    },
    "ctorMsg": {
      "function": "init",
      "args": [
        "hi there"
      ]
    },
    "secureContext": "<ENROLL_ID>"
  },
  "id": 1
}

{
  "jsonrpc": "2.0",
  "result": {
    "status": "OK",
    "message": "25b17bfcb3236793de06648ca4a094e2922af5f21ff68431486205b1c59e3fbede189133b4a71ba04af63ee061a11ef7a705f6a4ed01409377bf705865b0c51c"
  },
  "id": 1
}

無事にデプロイに成功し、チェーンコードIDが返ってきました。

続けて、チェーンコードを実行してみます。chaincodeID に返ってきたハッシュを指定し、function に実行したい関数名(ここでは write)、args に関数へ渡したい引数(ここでは hi therego away)を指定します。

POST https://b43adcdd35ba429d9a5045427432ee82-vp2.us.blockchain.ibm.com:444/chaincode
{
  "jsonrpc": "2.0",
  "method": "invoke",
  "params": {
    "type": 1,
    "chaincodeID": {
      "name": "25b17bfcb3236793de06648ca4a094e2922af5f21ff68431486205b1c59e3fbede189133b4a71ba04af63ee061a11ef7a705f6a4ed01409377bf705865b0c51c"
    },
    "ctorMsg": {
      "function": "write",
      "args": [
        "hi there", "go away"
      ]
    },
    "secureContext": "<ENROLL_ID>"
  },
  "id": 1
}

{
  "jsonrpc": "2.0",
  "result": {
    "status": "OK",
    "message": "a9e2faeb-feb2-4753-a0a4-ab3f9738f165"
  },
  "id": 1
}

チェーンコードが実行され、トランザクションの UUID が返ってきました。

最後はステートが更新されたのかを確認するため、ステートを参照します。
実行時と同様に chaincodeID に返ってきたハッシュを指定し、function に実行したい関数名(ここでは read)、args に関数へ渡したい引数(ここでは hi there というキー)を指定します。

POST https://b43adcdd35ba429d9a5045427432ee82-vp2.us.blockchain.ibm.com:444/chaincode
{
  "jsonrpc": "2.0",
  "method": "query",
  "params": {
    "type": 1,
    "chaincodeID": {
      "name": "25b17bfcb3236793de06648ca4a094e2922af5f21ff68431486205b1c59e3fbede189133b4a71ba04af63ee061a11ef7a705f6a4ed01409377bf705865b0c51c"
    },
    "ctorMsg": {
      "function": "read",
      "args": [
        "hi there"
      ]
    },
    "secureContext": "<ENROLL_ID>"
  },
  "id": 1
}

{
  "jsonrpc": "2.0",
  "result": {
    "status": "OK",
    "message": "go away"
  },
  "id": 1
}

hi there というキーに対して、go away というバリューが返ってきました。
これでチェーンコードが実行されたことできちんとステートが更新されていることが分かりました。

チェーンコードを書くのに役立つコードやドキュメント

Hyperledger Fabric の examples/chaincode に Go と Java のサンプルコードがあるので、どういったことができるのか参考になると思います。
公式ドキュメントでは chaincode_example02.go がよく使われています。
https://github.com/hyperledger/fabric/tree/master/examples/chaincode

また、ソースコードは fablic/core/chaincode にあります。
https://github.com/hyperledger/fabric/tree/master/core/chaincode

チェーンコードAPIのドキュメントはこちらにあるので、本格的に始める場合は参照すると良さそうです。
https://godoc.org/github.com/hyperledger/fabric/core/chaincode/shim

39
38
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
39
38

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?