チェーンコードの実装やアプリケーションの開発にあたって、開発環境が必要になります。
今回は開発環境の立ち上げを行ってみました。
開発環境を構築する3つの方法
Vagrant を利用
Hyperledger Fabric リポジトリの devenv
ディレクトリ下に、Vagrantfile とプロビジョニング用のスクリプトが用意されているため、それを使用して構築します。
- Vagrant, VirtualBox をインストール
- Hyperleder Fabric リポジトリをクローンし、
devenv
ディレクトリ下に移動 -
vagrant up
を実行して仮想マシンを起動・プロビジョニング- 必要なパッケージがインストールされた専用の Vagrant Box (Ubuntu) が利用される
- Vagrant Box のダウンロードに20分、起動・プロビジョニングに20分ほどかかった
-
vagrant ssh
でサーバに入る -
make membersrvc && membersrvc
でメンバーシップサービスを起動 -
make peer && peer node start --peer-chaincodedev
でピアを起動
しかし、この方法では構築する中でいくつか問題が発生し、かなりしんどかったです。
- Docker のインストールに必要な GPG キーが取得できない(こちらと同じ方法で解決: http://qiita.com/togana/items/cf3bf9bb7cf28923b221)
- JavaSDK のバージョン選択が上手くいかない(プロビジョニングは進行)
- Node のバージョンが古いため(v0.12.7)、NodeSDK のユニットテストが通らない
既知の問題もあるようですし、次の Docker を使用した環境構築の方が非常に簡単なのでおすすめです。
Docker for Mac/Windows を利用
Hyperledger Fabric はそれぞれのサービスが Docker コンテナになっており、Mac/Windows 上に直接コンテナを起動することができます。
- Docker をインストール
- 公式サイト https://docker.github.io/engine/installation/
- Homebrew Cask があれば
brew cask install docker
- 必要な Docker イメージを Pull する
docker pull hyperledger/fabric-peer:latest
docker pull hyperledger/fabric-membersrvc:latest
- 10分から15分程度で完了した
- Docker Compose でメンバーシップサービスとピアのコンテナを構築
- Docker Compose 用の設定ファイルが公式で提供されているので、任意の場所に
docker-compose.yml
として設置する -
docker-compose up
でメンバーシップサービスとピアのコンテナが起動する
- Docker Compose 用の設定ファイルが公式で提供されているので、任意の場所に
コンテナ起動時の docker-compose.yml
は以下です。
membersrvc:
image: hyperledger/fabric-membersrvc
command: membersrvc
vp0:
image: hyperledger/fabric-peer
environment:
- CORE_PEER_ADDRESSAUTODETECT=true
- CORE_VM_ENDPOINT=http://172.17.0.1:2375
- CORE_LOGGING_LEVEL=DEBUG
- CORE_PEER_ID=vp0
- CORE_PEER_PKI_ECA_PADDR=membersrvc:7054
- CORE_PEER_PKI_TCA_PADDR=membersrvc:7054
- CORE_PEER_PKI_TLSCA_PADDR=membersrvc:7054
- CORE_SECURITY_ENABLED=true
- CORE_SECURITY_ENROLLID=test_vp0
- CORE_SECURITY_ENROLLSECRET=MwYpmSRjupbT
links:
- membersrvc
command: sh -c "sleep 5; peer node start --peer-chaincodedev"
それぞれ、コンテナ構築時に使用する Docker イメージ、構築後の実行コマンド、環境変数などが指定されます。
Docker Toolbox を利用
:note: http://hyperledger-fabric.readthedocs.io/en/latest/Setup/Chaincode-setup/#option-3-docker-toolbox
Docker for Mac/Windows と同様の手順で構築可能です。
Docker for Mac/Windows との違いは、Docker が稼働する仮想環境がネイティブか VirtualBox かの違いだけです。
Docker for Mac/Windows はネイティブ上に稼働し、Docker Toolbox は VirtualBox 上に稼働します。
Docker for Mac の使い方メモ
今回は Docker for Mac を使って構築しました。
コンテナの構築・起動
% docker-compose up
Creating docker_membersrvc_1
Creating docker_vp0_1
Attaching to docker_membersrvc_1, docker_vp0_1
コンテナの停止
% docker-compose stop
Stopping docker_membersrvc_1 ... done
Stopping docker_vp0_1 ... done
コンテナの削除
% docker-compose rm
Going to remove docker_vp0_1, docker_membersrvc_1
Are you sure? [yN] y
Removing docker_vp0_1 ... done
Removing docker_membersrvc_1 ... done
コンテナプロセスの確認
% docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
11bdfd641d57 hyperledger/fabric-peer "sh -c 'sleep 5; peer" 20 hours ago Up 28 seconds 0.0.0.0:7050-7051->7050-7051/tcp, 0.0.0.0:7053->7053/tcp docker_vp0_1
b2e60ea30a40 hyperledger/fabric-membersrvc "membersrvc" 20 hours ago Up 29 seconds 0.0.0.0:7054->7054/tcp docker_membersrvc_1
コンテナ内部に入る
% docker exec -it 11bdfd641d57 /bin/bash
root@11bdfd641d57:/opt/gopath/src/github.com/hyperledger/fabric# pstree -Aalunp
sh,1 -c sleep 5; peer node start --peer-chaincodedev
`-peer,8 node start --peer-chaincodedev
|-{peer},9
|-{peer},10
|-{peer},11
|-{peer},12
|-{peer},13
|-{peer},14
|-{peer},15
`-{peer},16
動作テスト
起動したコンテナでの動作テストを、REST API を使って行います。
REST API は 7050 ポートを使用します。
Registrar API でのログイン
membersrvc/membersrvc.yml
に初期のログイン情報があるので、その情報を使って任意のユーザにログインします。
% curl -X POST -H 'Content-Type: application/json' -d '{"enrollId":"jim","enrollSecret":"6avZQLwcUe9b"}' http://localhost:7050/registrar
{"OK":"Login successful for user 'jim'."}
Chaincode API でのチェーンコード設置・実行・参照
Docker for Mac で構築した場合、ローカル環境上にチェーンコードをビルドし、実行することでチェーンコードを起動・ピアに登録することができます。
まずは $GOPATH
下に chaincode_example02.go
というサンプルをダウンロードします。
% mkdir -p $GOPATH/src/github.com/chaincode_example02/
% cd $GOPATH/src/github.com/chaincode_example02
% curl GET https://raw.githubusercontent.com/hyperledger/fabric/master/examples/chaincode/go/chaincode_example02/chaincode_example02.go > chaincode_example02.go
サンプルコードには Hyperledger Fabric リポジトリのコードが必要なので、こちらも $GOPATH
下にクローンします。
% mkdir -p $GOPATH/src/github.com/hyperledger
% cd $GOPATH/src/github.com/hyperledger
% git clone https://github.com/hyperledger/fabric.git
再びサンプルコードのあるディレクトリまで戻って、go build
します。
% cd $GOPATH/src/github.com/chaincode_example02
% go build
chaincode_example02
が作成されるので、実行します。
実行する際に任意のチェーンコードID名と、起動しているピアコンテナのアドレスを指定します。
% CORE_CHAINCODE_ID_NAME=mycc CORE_PEER_ADDRESS=0.0.0.0:7051 ./chaincode_example02
19:00:56.500 [shim] INFO : error with chaincode log level: logger: invalid log level level=
19:00:56.500 [shim] DEBU : Peer address: 0.0.0.0:7051
19:00:56.503 [shim] DEBU : os.Args returns: [./chaincode_example02]
19:00:56.505 [shim] DEBU : Registering.. sending REGISTER
19:00:56.510 [shim] DEBU : []Received message REGISTERED from shim
19:00:56.510 [shim] DEBU : []Handling ChaincodeMessage of type: REGISTERED(state:created)
19:00:56.510 [shim] DEBU : Received REGISTERED, ready for invocations
これでピアにチェーンコードが登録され、任意のチェーンコードID名を使用してデプロイ・実行できるようになります。
下記を実行して登録したチェーンコードをデプロイします。
初期値として a
に 1000
、b
に 2000
をセットするようになっています。
% echo '{
"jsonrpc": "2.0",
"method": "deploy",
"params": {
"type": 1,
"chaincodeID": {
"name": "mycc"
},
"ctorMsg": {
"function": "init",
"args": ["a", "1000", "b", "2000"]
},
"secureContext": "jim"
},
"id": 1
}' |
curl -X POST -H 'Content-Type: application/json' -d @- http://localhost:7050/chaincode
{"jsonrpc":"2.0","result":{"status":"OK","message":"mycc"},"id":1}
デプロイしたチェーンコードを指定して、invoke してみます。
a
から b
に 100
を渡すような処理です。
% echo '{
"jsonrpc": "2.0",
"method": "invoke",
"params": {
"type": 1,
"chaincodeID": {
"name": "mycc"
},
"ctorMsg": {
"function": "invoke",
"args": ["a", "b", "100"]
},
"secureContext": "jim"
},
"id": 1
}' |
curl -X POST -H 'Content-Type: application/json' -d @- http://localhost:7050/chaincode
{"jsonrpc":"2.0","result":{"status":"OK","message":"d0e86638-778c-4a50-9d72-a160b8b6d74f"},"id":1}
query で処理が正常に完了したかを確認します。
a
を指定すると結果は 900
に、b
を指定すると結果は 2100
になりました。
% echo '{
"jsonrpc": "2.0",
"method": "query",
"params": {
"type": 1,
"chaincodeID": {
"name": "mycc"
},
"ctorMsg": {
"function": "query",
"args": ["a"]
},
"secureContext": "jim"
},
"id": 1
}' |
curl -X POST -H 'Content-Type: application/json' -d @- http://localhost:7050/chaincode
{"jsonrpc":"2.0","result":{"status":"OK","message":"900"},"id":1}
% echo '{
"jsonrpc": "2.0",
"method": "query",
"params": {
"type": 1,
"chaincodeID": {
"name": "mycc"
},
"ctorMsg": {
"function": "query",
"args": ["b"]
},
"secureContext": "jim"
},
"id": 1
}' |
curl -X POST -H 'Content-Type: application/json' -d @- http://localhost:7050/chaincode
{"jsonrpc":"2.0","result":{"status":"OK","message":"2100"},"id":1}