Hyperledger Fabric v1.4/v1.3/v1.2.1で環境設定の動作確認: Build Your First Network (BYFN) を試してみる

# Changelog

Fabric v1.4 に対応済

# 概要

Hyperledger Fabric (以下Fabric) の環境設定を行った後にはサンプルで動作確認をするとよい。
ここではサンプルの1つである "Build Your First Network"、通称 **BYFN**、を動かす方法を説明する。
以下で説明するステップはmacOS High Sierraで動作確認をした。

ここではFabric v1.4を使って説明するが、v1.3/v1.2.1でも、Dockerイメージなどのバージョンの違いを除いて、まったく同じ方法が使える。

# BYFNとは

BYFNはシンプルな構成のFabricネットワーク上で、チャネルの作成と参加、チェーンコードのインストールとインスタンス化、その呼び出しなどを一通り試すサンプルコードである。もともとはFabricの動作確認 (シナリオテスト) 用のコードである。

> はじめはシンプルなスクリプトだったのだが最近多機能化してわかりにくくなっており不満である。サンプルスクリプトはシンプルであるべきだと思う。 

# 準備

環境設定は [Hyperledger Fabricを動かしてみよう (v1.4/v1.3/v1.2.1対応版)](https://qiita.com/miki110/items/7f4ef59b43c63aa7b754) を参照のこと。
鍵の作成などにはplatform-specific binaries (上記記事参照) が必要で、そこにパスが通っている必要がある。
あとは全てDockerコンテナの中で動くのでDockerがあればよく、Go/Node.js/Pythonなどは必要ない。

以下、作業ディレクトリ名を `~/fabric-140` とする。 

# 試す

(`generate`を省けば) 3コマンドで試せる。ただしく動いたかは【動作確認】の部分を参照のこと。

```bash
~/fabric-140$ cd fabric-samples/first-network

# この時点ですでに動いているDockerコンテナがある場合は停止、削除しておく
# 動いているのがBYFNの場合は `./byfn.sh down` とする

# ヘルプを表示する
~/fabric-140/fabric-samples/first-network$ ./byfn.sh
(ヘルプが出る)

# 暗号鍵ファイルやconfigファイルを生成する
# これをスキップしてもOK。upした時に必要なファイルがなければ自動で生成されるため
~/fabric-140/fabric-samples/first-network$ ./byfn.sh generate
(ログが出る)

# スタート。ログが一通り落ち着くまで眺め、期待した出力になっているか動作確認する
~/fabric-140/fabric-samples/first-network$ ./byfn.sh up
(ログが出る)

# コンテナのストップと削除など
~/fabric-140/fabric-samples/first-network$ ./byfn.sh down
(ログが出る)
```

**【動作確認】** `./byfn.sh up` して最後に以下のメッセージが出たら成功である。失敗の場合は途中でエラーメッセージが出る。
動作を確認したら `byfn.sh down` でコンテナを終了しておく。そうでないと次に試すときにエラーになる

```
(略)
===================== Query on peer1.org2 on channel 'mychannel' is successful ===================== 

========= All GOOD, BYFN execution completed =========== 


 _____   _   _   ____   
| ____| | \ | | |  _ \  
|  _|   |  \| | | | | | 
| |___  | |\  | | |_| | 
|_____| |_| \_| |____/  

```

# `byfn.sh` 解説

## ヘルプ表示 (`-h`)

`byfn.sh` を引数無しかオプション `-h` つきで起動するとヘルプが表示される:

```
Usage:
  byfn.sh <mode> [-c <channel name>] [-t <timeout>] [-d <delay>] [-f <docker-compose-file>] [-s <dbtype>] [-l <language>] [-o <consensus-type>] [-i <imagetag>] [-v]
    <mode> - one of 'up', 'down', 'restart', 'generate' or 'upgrade'
      - 'up' - bring up the network with docker-compose up
      - 'down' - clear the network with docker-compose down
      - 'restart' - restart the network
      - 'generate' - generate required certificates and genesis block
      - 'upgrade'  - upgrade the network from version 1.3.x to 1.4.0
    -c <channel name> - channel name to use (defaults to "mychannel")
    -t <timeout> - CLI timeout duration in seconds (defaults to 10)
    -d <delay> - delay duration in seconds (defaults to 3)
    -f <docker-compose-file> - specify which docker-compose file use (defaults to docker-compose-cli.yaml)
    -s <dbtype> - the database backend to use: goleveldb (default) or couchdb
    -l <language> - the chaincode language: golang (default) or node
    -o <consensus-type> - the consensus-type of the ordering service: solo (default) or kafka
    -i <imagetag> - the tag to be used to launch the network (defaults to "latest")
    -v - verbose mode
  byfn.sh -h (print this message)

Typically, one would first generate the required certificates and
genesis block, then bring up the network. e.g.:

        byfn.sh generate -c mychannel
        byfn.sh up -c mychannel -s couchdb
        byfn.sh up -c mychannel -s couchdb -i 1.4.0
        byfn.sh up -l node
        byfn.sh down -c mychannel
        byfn.sh upgrade -c mychannel

Taking all defaults:
        byfn.sh generate
        byfn.sh up
        byfn.sh down
```

## 鍵などの生成 (`generate`)

`./byfn.sh generate` で必要な鍵 (証明書)、ジェネシスブロック、チャネル作成のためのトランザクションデータなどが生成される。
`Continue?` と聞かれたら `y` で答える。
鍵などは `crypto-config/` に、のこりは `channel-artifacts/` に格納される。

> なお、`cryptogen` などが相対パスで呼ばれているので、そこにバイナリがあるようにしておく。

```
Generating certs and genesis block for channel 'mychannel' with CLI timeout of '10' seconds and CLI delay of '3' seconds
Continue? [Y/n] y
proceeding ...
.../fabric-140/fabric-samples/first-network/../bin/cryptogen

##########################################################
##### Generate certificates using cryptogen tool #########
##########################################################
+ cryptogen generate --config=./crypto-config.yaml
org1.example.com
org2.example.com
+ res=0
+ set +x

.../fabric-140/fabric-samples/first-network/../bin/configtxgen
##########################################################
#########  Generating Orderer Genesis block ##############
##########################################################
CONSENSUS_TYPE=solo
+ '[' solo == solo ']'
+ configtxgen -profile TwoOrgsOrdererGenesis -channelID byfn-sys-channel -outputBlock ./channel-artifacts/genesis.block
2019-02-16 14:06:12.822 JST [common.tools.configtxgen] main -> INFO 001 Loading configuration
2019-02-16 14:06:12.853 JST [common.tools.configtxgen.localconfig] completeInitialization -> INFO 002 orderer type: solo
2019-02-16 14:06:12.853 JST [common.tools.configtxgen.localconfig] Load -> INFO 003 Loaded configuration: .../fabric-140/fabric-samples/first-network/configtx.yaml
2019-02-16 14:06:12.877 JST [common.tools.configtxgen.localconfig] completeInitialization -> INFO 004 orderer type: solo
2019-02-16 14:06:12.877 JST [common.tools.configtxgen.localconfig] LoadTopLevel -> INFO 005 Loaded configuration: .../fabric-140/fabric-samples/first-network/configtx.yaml
2019-02-16 14:06:12.879 JST [common.tools.configtxgen] doOutputBlock -> INFO 006 Generating genesis block
2019-02-16 14:06:12.880 JST [common.tools.configtxgen] doOutputBlock -> INFO 007 Writing genesis block
+ res=0
+ set +x

#################################################################
### Generating channel configuration transaction 'channel.tx' ###
#################################################################
+ configtxgen -profile TwoOrgsChannel -outputCreateChannelTx ./channel-artifacts/channel.tx -channelID mychannel
2019-02-16 14:06:12.919 JST [common.tools.configtxgen] main -> INFO 001 Loading configuration
2019-02-16 14:06:12.945 JST [common.tools.configtxgen.localconfig] Load -> INFO 002 Loaded configuration: .../fabric-140/fabric-samples/first-network/configtx.yaml
2019-02-16 14:06:12.970 JST [common.tools.configtxgen.localconfig] completeInitialization -> INFO 003 orderer type: solo
2019-02-16 14:06:12.970 JST [common.tools.configtxgen.localconfig] LoadTopLevel -> INFO 004 Loaded configuration: .../fabric-140/fabric-samples/first-network/configtx.yaml
2019-02-16 14:06:12.970 JST [common.tools.configtxgen] doOutputChannelCreateTx -> INFO 005 Generating new channel configtx
2019-02-16 14:06:12.972 JST [common.tools.configtxgen] doOutputChannelCreateTx -> INFO 006 Writing new channel tx
+ res=0
+ set +x

#################################################################
#######    Generating anchor peer update for Org1MSP   ##########
#################################################################
+ configtxgen -profile TwoOrgsChannel -outputAnchorPeersUpdate ./channel-artifacts/Org1MSPanchors.tx -channelID mychannel -asOrg Org1MSP
2019-02-16 14:06:13.024 JST [common.tools.configtxgen] main -> INFO 001 Loading configuration
2019-02-16 14:06:13.053 JST [common.tools.configtxgen.localconfig] Load -> INFO 002 Loaded configuration: .../fabric-140/fabric-samples/first-network/configtx.yaml
2019-02-16 14:06:13.085 JST [common.tools.configtxgen.localconfig] completeInitialization -> INFO 003 orderer type: solo
2019-02-16 14:06:13.085 JST [common.tools.configtxgen.localconfig] LoadTopLevel -> INFO 004 Loaded configuration: .../fabric-140/fabric-samples/first-network/configtx.yaml
2019-02-16 14:06:13.085 JST [common.tools.configtxgen] doOutputAnchorPeersUpdate -> INFO 005 Generating anchor peer update
2019-02-16 14:06:13.088 JST [common.tools.configtxgen] doOutputAnchorPeersUpdate -> INFO 006 Writing anchor peer update
+ res=0
+ set +x

#################################################################
#######    Generating anchor peer update for Org2MSP   ##########
#################################################################
+ configtxgen -profile TwoOrgsChannel -outputAnchorPeersUpdate ./channel-artifacts/Org2MSPanchors.tx -channelID mychannel -asOrg Org2MSP
2019-02-16 14:06:13.134 JST [common.tools.configtxgen] main -> INFO 001 Loading configuration
2019-02-16 14:06:13.168 JST [common.tools.configtxgen.localconfig] Load -> INFO 002 Loaded configuration: .../fabric-140/fabric-samples/first-network/configtx.yaml
2019-02-16 14:06:13.193 JST [common.tools.configtxgen.localconfig] completeInitialization -> INFO 003 orderer type: solo
2019-02-16 14:06:13.193 JST [common.tools.configtxgen.localconfig] LoadTopLevel -> INFO 004 Loaded configuration: .../fabric-140/fabric-samples/first-network/configtx.yaml
2019-02-16 14:06:13.193 JST [common.tools.configtxgen] doOutputAnchorPeersUpdate -> INFO 005 Generating anchor peer update
2019-02-16 14:06:13.194 JST [common.tools.configtxgen] doOutputAnchorPeersUpdate -> INFO 006 Writing anchor peer update
+ res=0
+ set +x
```

## コンテナ群の立ち上げ (`up`)

`byfn.sh up` と実行すると、docker-composeでFabricのコンテナ群が立ち上がる。
いろいろオプションがあるがデフォルトでよい。`Continue?` には `y` で答える。
数分かかってチャネルの作成、ネットワークの作成、チェーンコードのデプロイとその実行 (更新系および参照系)などが行われる。

前述したようなメッセージが最後に表示されれば正常終了である。

この状態で、動作中のコンテナは以下のようになる:

```
~/fabric-140/fabric-samples/first-network$ docker container ls // 旧 docker ps
CONTAINER ID        IMAGE                                                                                                  COMMAND                  CREATED              STATUS              PORTS                                              NAMES
a63d2af1e4ef        dev-peer1.org2.example.com-mycc-1.0-26c2ef32838554aac4f7ad6f100aca865e87959c9a126e86d764c8d01f8346ab   "chaincode -peer.add…"   About a minute ago   Up About a minute                                                      dev-peer1.org2.example.com-mycc-1.0
418b30633c6b        dev-peer0.org1.example.com-mycc-1.0-384f11f484b9302df90b453200cfb25174305fce8f53f4e94d45ee3b6cab0ce9   "chaincode -peer.add…"   About a minute ago   Up About a minute                                                      dev-peer0.org1.example.com-mycc-1.0
f6fb8ef81c61        dev-peer0.org2.example.com-mycc-1.0-15b571b3ce849066b7ec74497da3b27e54e0df1345daff3951b94245ce09c42b   "chaincode -peer.add…"   2 minutes ago        Up 2 minutes                                                           dev-peer0.org2.example.com-mycc-1.0
96a66c29b669        hyperledger/fabric-tools:latest                                                                        "/bin/bash"              2 minutes ago        Up 2 minutes                                                           cli
b39892a30d17        hyperledger/fabric-peer:latest                                                                         "peer node start"        3 minutes ago        Up 2 minutes        0.0.0.0:10051->7051/tcp, 0.0.0.0:10053->7053/tcp   peer1.org2.example.com
1755a28957a9        hyperledger/fabric-orderer:latest                                                                      "orderer"                3 minutes ago        Up 2 minutes        0.0.0.0:7050->7050/tcp                             orderer.example.com
61e535c84ba1        hyperledger/fabric-peer:latest                                                                         "peer node start"        3 minutes ago        Up 2 minutes        0.0.0.0:8051->7051/tcp, 0.0.0.0:8053->7053/tcp     peer1.org1.example.com
184b763feb0f        hyperledger/fabric-peer:latest                                                                         "peer node start"        3 minutes ago        Up 2 minutes        0.0.0.0:9051->7051/tcp, 0.0.0.0:9053->7053/tcp     peer0.org2.example.com
72cbb467eff2        hyperledger/fabric-peer:latest                                                                         "peer node start"        3 minutes ago        Up 2 minutes        0.0.0.0:7051->7051/tcp, 0.0.0.0:7053->7053/tcp     peer0.org1.example.com
```

イメージ名およびコンテナ名が `dev-` で始まるのがチェーンコード (= スマートコントラクト) のコンテナである。
残りがpeerなどFabricのネットワークを構成するノードのコンテナたちである。

> チェーンコードのコンテナの命名規則は `<ネットワーク名>-<ピア名>-<チェーンコード名>-<バージョン>` となっている。ハッシュ値を除くと、これがチェーンコードを一意に特定する情報になっているはずである。チャネル名が含まれないことに注意する。

一方、イメージの一覧を表示するとこのようになる:

```
~/fabric-140/fabric-samples/first-network$ docker image ls // 旧 docker images
REPOSITORY                                                                                             TAG                 IMAGE ID            CREATED             SIZE
dev-peer1.org2.example.com-mycc-1.0-26c2ef32838554aac4f7ad6f100aca865e87959c9a126e86d764c8d01f8346ab   latest              a0975f7fd0d4        6 minutes ago       141MB
dev-peer0.org1.example.com-mycc-1.0-384f11f484b9302df90b453200cfb25174305fce8f53f4e94d45ee3b6cab0ce9   latest              2f4c4c00fb8d        6 minutes ago       141MB
dev-peer0.org2.example.com-mycc-1.0-15b571b3ce849066b7ec74497da3b27e54e0df1345daff3951b94245ce09c42b   latest              b3a638583c77        7 minutes ago       141MB
hyperledger/fabric-javaenv                                                                             1.4.0               3d91b3bf7118        4 weeks ago         1.75GB
hyperledger/fabric-javaenv                                                                             latest              3d91b3bf7118        4 weeks ago         1.75GB
hyperledger/fabric-tools                                                                               1.4.0               0a44f4261a55        5 weeks ago         1.56GB
hyperledger/fabric-tools                                                                               latest              0a44f4261a55        5 weeks ago         1.56GB
hyperledger/fabric-ccenv                                                                               1.4.0               5b31d55f5f3a        5 weeks ago         1.43GB
hyperledger/fabric-ccenv                                                                               latest              5b31d55f5f3a        5 weeks ago         1.43GB
hyperledger/fabric-orderer                                                                             1.4.0               54f372205580        5 weeks ago         150MB
hyperledger/fabric-orderer                                                                             latest              54f372205580        5 weeks ago         150MB
hyperledger/fabric-peer                                                                                1.4.0               304fac59b501        5 weeks ago         157MB
hyperledger/fabric-peer                                                                                latest              304fac59b501        5 weeks ago         157MB
hyperledger/fabric-ca                                                                                  1.4.0               1a804ab74f58        5 weeks ago         244MB
hyperledger/fabric-ca                                                                                  latest              1a804ab74f58        5 weeks ago         244MB
hyperledger/fabric-zookeeper                                                                           0.4.14              d36da0db87a4        4 months ago        1.43GB
hyperledger/fabric-zookeeper                                                                           latest              d36da0db87a4        4 months ago        1.43GB
hyperledger/fabric-kafka                                                                               0.4.14              a3b095201c66        4 months ago        1.44GB
hyperledger/fabric-kafka                                                                               latest              a3b095201c66        4 months ago        1.44GB
hyperledger/fabric-couchdb                                                                             0.4.14              f14f97292b4c        4 months ago        1.5GB
hyperledger/fabric-couchdb                                                                             latest              f14f97292b4c        4 months ago        1.5GB
hyperledger/fabric-baseos                                                                              amd64-0.4.14        75f5fb1a0e0c        4 months ago        124MB
```

環境設定時より新たに2種類のイメージが増えていることがわかる。
まず、`dev-` で始まるのはチェーンコードイメージである。ハッシュ値らしきものが何を意味しているかはわからない。
次に、fabric-baseosというイメージが増えている。これはチェーンコードをビルドするためのものか、チェーンコードを動かすためのものなのかは失念したが、そのどちらかである。他のイメージと異なり、uname値である `amd64` が付加されていることから、これのみアーキテクチャ依存のイメージである。
このイメージはあらかじめpullしておいてもよいかもしれない。それによりチェーンコードのデプロイ時間が大幅に短縮するはずである。

## コンテナなどの終了、削除 (`down`)

`./byfn.sh down` で動作中のコンテナを停止、削除する。これも `Continue?` には `y` で答える。

```
~/fabric-140/fabric-samples/first-network$ ./byfn.sh down
Stopping for channel 'mychannel' with CLI timeout of '10' seconds and CLI delay of '3' seconds
Continue? [Y/n] y
proceeding ...
Stopping cli                    ... done
Stopping peer1.org2.example.com ... done
Stopping orderer.example.com    ... done
Stopping peer1.org1.example.com ... done
Stopping peer0.org2.example.com ... done
Stopping peer0.org1.example.com ... done
Removing cli                    ... done
Removing peer1.org2.example.com ... done
Removing orderer.example.com    ... done
Removing peer1.org1.example.com ... done
Removing peer0.org2.example.com ... done
Removing peer0.org1.example.com ... done
Removing network net_byfn
Removing volume net_orderer.example.com
Removing volume net_peer0.org1.example.com
Removing volume net_peer1.org1.example.com
Removing volume net_peer0.org2.example.com
Removing volume net_peer1.org2.example.com
Removing volume net_peer0.org3.example.com
WARNING: Volume net_peer0.org3.example.com not found.
Removing volume net_peer1.org3.example.com
WARNING: Volume net_peer1.org3.example.com not found.
a63d2af1e4ef
418b30633c6b
f6fb8ef81c61
Untagged: dev-peer1.org2.example.com-mycc-1.0-26c2ef32838554aac4f7ad6f100aca865e87959c9a126e86d764c8d01f8346ab:latest
Deleted: sha256:a0975f7fd0d445766653e8a592a43c804ddab6ad46cc211ef28e30079796715d
Deleted: sha256:4ed616de4f9d4f9033133cee10ca9df9a59a1e8d9791d4c62b352b35935662bf
Deleted: sha256:293a5921a4423e066044b225edc11d0b8db33e2ee72fe44a436a9b15efe2ff4d
Deleted: sha256:076b31dc71797b2b3c645946c33897e8014ab9232adbbd6e8f5f7ea7989ead8c
Untagged: dev-peer0.org1.example.com-mycc-1.0-384f11f484b9302df90b453200cfb25174305fce8f53f4e94d45ee3b6cab0ce9:latest
Deleted: sha256:2f4c4c00fb8de081670d2cab210eee1d34443967d05928c18d20072973a7bece
Deleted: sha256:add908201943f2e122ab9525b5e113fd5486b71d642b8b60e3b216aa8b3d1fc5
Deleted: sha256:b201de718196c80d406ff665f1aedff5a36f6bfcbc65b3dc88ea385f75521268
Deleted: sha256:820130415cc03e95f775fd9b468c177c1da0cdfd1b36ff84178ecbdd26dc94aa
Untagged: dev-peer0.org2.example.com-mycc-1.0-15b571b3ce849066b7ec74497da3b27e54e0df1345daff3951b94245ce09c42b:latest
Deleted: sha256:b3a638583c7799a011f0c896a879a6b268e7d6d223b3bc462c5fcfdc866349e3
Deleted: sha256:0739e62e6d9ba11b94570b32b9a8182d9befb0cf6a35dd2dd6e8c8bb07325b46
Deleted: sha256:7a1b90a0a7d18547d5f5aebea1a933a873305389ca52eed6549b579bedfe9f76
Deleted: sha256:af7af72dce6183763955923dcf8d0c28734f13175297a1fc4aa8e52fb9421e03
```

`docker container ls -a` (旧 `docker ps -a`) で停止されたコンテナがすべて削除されていることを確認できる。
ログを見るとDockerネットワークとボリュームも削除されている。
また、`docker image ls` により、チェーンコードイメージが削除されていることもわかる。
これで次回 `byfn.sh` や他の `docker-compose` ファイルを起動したときに上手くいくはずである。

<!--
## Fabric networkの構成

> Docker composeファイルの説明

## どのようなトランザクションを送っているか

> script.sh の中身の説明
-->