Hyperledger fabric v1.0を動かす

これは、SIerで3年間客先へ常駐して古いWebシステムを保守開発してきたWindowsとExcelしか知らないド素人の僕が、ブロックチェーンをMac上で動かしてみました。

当然、Macもgoもまともに使ったことの無い僕が書くので、本当初歩的なことから書いています。そして、深掘りはしていないです。
目標は、**自分のマシンでブロックチェーンなるものを動かすこと** それだけです。


ブロックチェーンとは何か
===========================

いきなりHyperledger fabricの導入と始めてしまいましたが、そもそもブロックチェーンとは何かということについても、自分の整理のためにも簡単にまとめようと思います。

最近、ニュースなどを見ているとFinTechという言葉をよく耳にすると思いますが、ブロックチェーンはそれを構成する技術の一つとされています。

ブロックチェーンというととても新しいものに感じますが、すごく簡単にいうとデータベースなのです。
ただ、そのデータの格納方法や業務処理を載せられる点が従来のデータベースとは異なるため、注目されています。

ブロックチェーンについては、Mastering Bitcoinとう書籍があり、それが日本語訳され公開されているため、それを読むと理解が深まります。
[https://www.bitcoinbook.info/translations/ja/book.pdf](https://www.bitcoinbook.info/translations/ja/book.pdf)

### ブロックとチェーンとトランザクション

ブロックチェーンについて、見ていると、「トランザクション」「ブロック」「チェーン」という言葉がよく出てきます。
これらを一言でいうと、『ブロックには、トランザクションとして個々の取引が過去の取引記録とともに記録されチェーンのようにつながっているもの。』となると思います。


### ブロックチェーンの技術要素

ブロックチェーンを構成する技術は、大きく分けて4つあるとされています。

- 分散台帳
  - 参加者のみで共有される、追記のみ可能な台帳
- スマートコントラクト
  - ブロックチェーン上に契約条項などの業務ルールや業務処理を実施する機能
- プライバシー
  - 公開鍵基盤により、ユーザーのプライバシーを保護する
- 合意形成
  - トランザクションを検証し、合意を形成する

### 仮想通貨

ブロックチェーンといえば、Bitcoinを始めとする仮想通貨の技術として社会に認知されてしまっているが、実はそうでなく様々な分野にも応用できる技術なのです。

様々な分野とは、世の中にあるビジネスも含められ、それらが、Hyperledger fabricへとつながっていきます。

Hyperledger fabricとは
======================

これについては、以下の記事がとても詳しいです。

[オープンソースのブロックチェーン Hyperledger Fabric を試してみる](http://qiita.com/kyrieleison/items/ec5223bbe6140822df4a)

ブロックチェーンは、Bitcoinがから始まりましたが、他の領域にも応用できる技術であることはちょっと書きました。
ただ、Bitcoinそのままの状態では、ビジネスとしては利用しにくいものでした。

それらを、利用しやすいようにしたブロックチェーン基盤が Hyperledger fabric です。


Hyperledger fabric 導入のための事前準備
=====================================

Hyperledger fabircを導入するためには、以下の環境が必要なため、実際の導入の前に準備をします。
そのため、以下の環境が導入済みであれば、この項目は飛ばして頂きたいです。

- go言語
- Docker

僕は、現在Mac環境で作業をしているので、基本的にMac環境での導入方法になります。
しかし、色々調べている過程で得たWindows環境下のことについては、できるだけ記載できるようにします。

以下が、この環境を構築したときの環境です。
その他ソフトウェアのバージョン等の情報は、導入しながら記載していきます。

```
$ sw_vers
ProductName:	Mac OS X
ProductVersion:	10.12.4
BuildVersion:	16E195
```


Homebrewのインストール
--------------------

これは、必須ではありませんが、go言語をかんたんにインストールするために導入しました。
と言うよりも、以前Mysqlをインストールするときに利用したので、せっかくだから導入しようと思ったためです。


### Homebrew

MacOS用のパッケージマネージャ。RedHatでいうところのyumや、Debianでいうところのapt-getです。

実際のコマンドは、公式サイト（[Homebrew](https://brew.sh/index_ja.html)）を参照すれば詳しくわかると思います。
一応、インストールコマンドだけ載せておきます。

`/usr/bin/ruby -e "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/master/install)"`

これを書いている時点でのバージョンは、以下の通りでした。

```
$ brew --version
Homebrew 1.2.1
Homebrew/homebrew-core (git revision 9000; last commit 2017-05-21)
```

Windowsについては、こういったパッケージ管理というものは存在していないと思うので、Homebrewの設定は必要ありません。
その代わり、ひとつひとつインストーラを見つけて、インストール必要があると思います。

#### Homebrewをマルチアカウントで利用する時のことについて

bomebrewで導入したmysqlをマルチアカウントで使うときに、色々と面倒だったのでそれをメモにしておきます。

```
sudo chgrp -R staff /usr/local
sudo chmod -R g+w /usr/local
```

管理者アカウントだけであれば、グループは`admin`でい良いのかもしれません。

goの開発環境構築
--------------

### golang

僕もこのプログラミング言語は初めて利用するため、この言語について少し読んでみました。

このプログラミング言語は、googleが開発た言語です。
一般には、軽量スレッディングのための機能や、型付けについては、静的型付けであるが、プログラミング時には動的型付け言語のように楽にプログラミングできるとされています。
しかし、僕自身はこれが初めての利用のため、この言語自体には、まだ感想などは持っていません。


### goのインストール

```
$ brew install go
==> Downloading https://homebrew.bintray.com/bottles/go-1.8.1.sierra.bottle.tar.gz
######################################################################## 100.0%
==> Pouring go-1.8.1.sierra.bottle.tar.gz
==> Using the sandbox
==> Caveats
A valid GOPATH is required to use the `go get` command.
If $GOPATH is not specified, $HOME/go will be used by default:
  https://golang.org/doc/code.html#GOPATH

You may wish to add the GOROOT-based install location to your PATH:
  export PATH=$PATH:/usr/local/opt/go/libexec/bin
==> Summary
🍺  /usr/local/Cellar/go/1.8.1: 7,030 files, 281.8MB
```

Homebrewを使い始めてずっと思っていますが、このビール不思議です。。
※home brewは、自家醸造とかそんな意味があるみたいで、それでビールらしいです。

インストール後のメッセージに、A valid GOPATH is required to use the \`go get\` command.
といっているので、環境変数を設定してあげます。
`go get`は、pythonでいうところの、pipみたいなもので、パッケージ管理システムのようなので、これの使い方くらいは、後で調べておく必要がありそうです。

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

`GOPATH`は、特に場所について規定とかはないようですが、ネットを見ていると、`$HOME/.go`に作ってる人が多いようだったので、それに倣って設定することにしました。(デフォルトの場合は、`$HOME/go`に作られるようである。ただ、あまり見えると邪魔なので、.をくっつけました。)

`GOPATH`は、import文で指定するパッケージが格納される場所になります。詳細は、公式ドキュメントを参照して欲しいです。リンクは以下。
[https://golang.org/doc/code.html#GOPATH](https://golang.org/doc/code.html#GOPATH)


起動時に環境変数が設定されるようにしたいので、bash_profileにも環境変数の設定を書きます。

```shell:bash_profile
## Go
if [ -x "`which go`" ]; then
  export GOPATH=$HOME/.go
  export PATH=$PATH:$GOPATH/bin
fi
```

Windowsの場合は、[公式サイト](http://golang-jp.org/)で、zipとインストーラの２種類が配布されているので、そこからダウンロードして導入します。

zipの場合は、好きな場所(公式には、`C:\go`が推奨と記載あり)に解凍後、GoのルートのbinディレクトリへPATHとGOPATHを設定してください。

インストーラの場合には、自動的にPATHは通るはずです。インストール後、確認をしてください。
GOPATHについては、`C:\Users\ユーザー名\go`へ設定されると記載がありました。
詳細は、上記のGoのサイトで日本語訳したインストールガイドがあるので、それを参照。

### 確認

ここまでで、とりあえずgoの環境が整ったはずなので、公式サイトの、Hello Worldを試してみようと思います。
ここまで問題なく作業ができていれば、しっかりとコンソール上で挨拶してくれるはずです。

```go:hello.go
package main

import "fmt"

func main() {
  fmt.Printf("Hello World!\n")
}
```

と、書いて実行してみようと思います。

```
$ go run hello.go
Hello World!
```

なんとか、メッセージがコンソール上に表示されたので、正常に動いて環境は導入できたのかなと思います。

Docker環境の導入
--------------

ソフトウェア開発関連の記事を見ていると、よくDockerというのものを目にします。
fabricを利用するためには、必要なものなのですが、今まで、触ったこともろくに調べたことも無いので、ざっくりとどのようなものかくらいは見てみようと@ITの記事に目を通してみました。

[超入門Docker：第1回　Dockerとは](http://www.atmarkit.co.jp/ait/articles/1701/30/news037.html)

Dockerとは、**非常に軽量なコンテナ型のアプリケーション実行環境** らしいです。

Vmwareとか仮想化とどう違うのかとかも載っていましたが、今は実行環境ってことだけで進めてみようと思います。


### Dockerのインストール

ざっくりとググった結果、Dockerは、Linuxを前提にしているらしいです。Mac環境は、まずまず良さそうなのだけれど、
なんだかWindowsは面倒そうな感じでした。

時間に余裕と、すごく興味が出てきたらしっかりと調べてみようと思います。


### Homebrewでのインストール

せっかくHomebrewを導入したのですが、最初なので公式な方法で導入していみようと思います。
そのため、僕はHomebrewで導入を行っていませんが、以下のコマンドのみでインストールすることができるようです。

Homebrewでの導入方法は、Qiitaの記事などに沢山情報があったので、そちらの方から情報を得たほうがより詳細な情報を得ることができると思います。


[Docker環境をHomebrewで手軽に作成](http://qiita.com/digitalm/items/49b7099554bdbff5ed8e)

```
# Homebrew cask
$ brew cask --version
Cloning into '/usr/local/Homebrew/Library/Taps/caskroom/homebrew-cask'...
remote: Counting objects: 3721, done.
remote: Compressing objects: 100% (3703/3703), done.
remote: Total 3721 (delta 34), reused 626 (delta 14), pack-reused 0
Receiving objects: 100% (3721/3721), 1.26 MiB | 0 bytes/s, done.
Resolving deltas: 100% (34/34), done.
Tapped 0 formulae (3,730 files, 3.9MB)
Homebrew-Cask 1.2.1
caskroom/homebrew-cask (git revision 8819; last commit 2017-05-24)
$
$ brew install docker
$ brew cask install docker

```

### 手動インストール

公式の以下のページを参考にインストールします。
[docker docs - Install Docker for Mac](https://docs.docker.com/docker-for-mac/install/)

ページを開いてすぐに、stable版とEdge版のダウンロードボタンがありますが、僕は、一応 stableの方をインストールしました。

インストールしたのでバージョン等を確認してみます。

```
$ docker version
Client:
 Version:      17.03.1-ce
 API version:  1.27
 Go version:   go1.7.5
 Git commit:   c6d412e
 Built:        Tue Mar 28 00:40:02 2017
 OS/Arch:      darwin/amd64

Server:
 Version:      17.03.1-ce
 API version:  1.27 (minimum version 1.12)
 Go version:   go1.7.5
 Git commit:   c6d412e
 Built:        Fri Mar 24 00:00:50 2017
 OS/Arch:      linux/amd64
 Experimental: true
```

```
$ docker info
Containers: 0
 Running: 0
 Paused: 0
 Stopped: 0
Images: 0
Server Version: 17.03.1-ce
Storage Driver: overlay2
 Backing Filesystem: extfs
 Supports d_type: true
 Native Overlay Diff: true
Logging Driver: json-file
Cgroup Driver: cgroupfs
Plugins:
 Volume: local
 Network: bridge host ipvlan macvlan null overlay
Swarm: inactive
Runtimes: runc
Default Runtime: runc
Init Binary: docker-init
containerd version: 4ab9917febca54791c5f071a9d1f404867857fcc
runc version: 54296cf40ad8143b62dbcaa1d90e520a2136ddfe
init version: 949e6fa
Security Options:
 seccomp
  Profile: default
Kernel Version: 4.9.27-moby
Operating System: Alpine Linux v3.5
OSType: linux
Architecture: x86_64
CPUs: 2
Total Memory: 1.952 GiB
Name: moby
ID: 6YGR:55IW:5Y62:VRCZ:MWKF:TK7K:YPWD:QF4M:RMQ7:7GOD:3QAZ:VFNR
Docker Root Dir: /var/lib/docker
Debug Mode (client): false
Debug Mode (server): true
 File Descriptors: 16
 Goroutines: 26
 System Time: 2017-05-24T02:38:30.923133328Z
 EventsListeners: 1
No Proxy: *.local, 169.254/16, 127.0.0.1
Registry: https://index.docker.io/v1/
Experimental: true
Insecure Registries:
 127.0.0.0/8
Live Restore Enabled: false
```


ここまでで、事前準備は終了です。


Hyperledger fabricの導入
=======================

ここからは、いよいよHyperledger fabricの導入を行っていこうと思います。

Hyperledger fabricは、現在 v0.6 と v1.0 がありますが、今回はやはり始めるなら新しい方ということでv1.0を導入していきます。


dockerイメージの取得
------------------

fabricは、Dockerイメージとして配布されているため、それらのファイルを取得します。
なお、Windowsの場合には、Git BashやMinGWが必要となるため、導入をしてくおいてください。

なにはともあれ、今回の作業場所を作ってください。

```
$ mkdir fabric_sample
$ cd fabric_sample
```

fabricのDockerイメージをHyperledgerのリポジトリからpullするため、以下のコマンドを実行してください。

```
$ curl -sS https://raw.githubusercontent.com/hyperledger/fabric/master/examples/e2e_cli/bootstrap.sh | bash
```

作業ディレクトリに以下のディレクトリが作成されたかと思いますので、
設定ファイル等が格納されているディレクトリへ移動してください。

```
$ ls
release
$ cd release/darwin-amd64/
$ ls
base                             crypto-config                    docker-compose-e2e.yaml          network_setup.sh
bin                              crypto-config.yaml               download-dockerimages.sh         scripts
bootstrap.sh                     docker-compose-cli.yaml          end-to-end.rst
channel-artifacts                docker-compose-couch.yaml        generateArtifacts.sh
configtx.yaml                    docker-compose-e2e-template.yaml install
```

Hyperledger fabric の構成
-------------------------

google翻訳と、原文を行ったり来たり。英語が苦手な僕は少しずつわけが分からなくなってきました。

下準備は、終了したのでここからはシステムの構成をします。
しかし、まだまだ僕も勉強中のため、ここでは簡単な起動のみを行います。

システム構成のためには、いくつかの設定ファイル(yaml)を編集する必要がありますが、すでにサンプルの値が設定されているため、ここでは特に編集を加えずに準備をします。
構成のため、いくつかぼ作業が必要ですが、Hyperledger fabric では、作業を簡単にするためのスクリプトが用意されているため、それを利用し、構成します。
以下のコマンドを実行して下さい。

```
$ generateArtifacts.sh
```

これによって、以下のものが構成されます。

- Genesis block
- Peer org
- Orderer org

Peer org と Orderer orgについてですが、これはv0.6まではブロックチェーンサービスとしてあったのかと思いますが、v1.0からアーキテクチャが変更になっています。
ブロックチェーンノードの役割が分割されています。

- Peer org
  - トランザクションをシミュレート実行し、トランザクションを検証、元帳を管理する。
- Orderer org
  - トランザクションの順序を整理する


Hyperledger fabricの起動
------------------------

ここからは、Hyperledger fabricを動かして行きますが、公式のチュートリアルに沿って手順を進めます。

### 環境設定

まずの初期化のために、以下のコマンドを実行してください。

```
./generateArtifacts.sh mychannel
```

このコマンドの引数”mychannel”はチャンネル名です。任意で指定してください。指定しない場合は、デフォルトでmychannelに設定されます。

このシェルでは、ざっくりいうと、以下のことが実行されています。

- 暗号鍵の生成
- Dockerの定義ファイルへの鍵情報反映
- ジェネシスブロックの生成
- チャンネルの設定

特に、チャンネルについてはv1.0からなのかもしれません。ネットにあるv0.6の情報では、これについて、見つけられませんし……
ぐぐってみたところ、Hyperledger fabricでは、Multi-channelとSub-ledgerをサポートしているらしく、Channelはledgerの共有範囲を定義するために生成するそうです。

シェルを実行すると、鍵の生成部分で以下のようなエラーメッセージが表示されますが、これは無視して問題無いとマニュアルに記載がありました。

```
[bccsp] GetDefault -> WARN 001 Before using BCCSP, please call InitFactories(). Falling back to bootBCCSP.
```

初期化は、このシェル一発で終了します。非常に簡単に起動するための準備がされています。

これで、ネットワークの起動をすることができるわけですが、その前に1箇所ネットワーク起動のためのシェルを編集してほしいです。

```diff
@@ -49,7 +49,7 @@
       - CORE_PEER_TLS_ROOTCERT_FILE=/opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/peerOrganizations/org1.example.com/peers/peer0.org1.example.com/tls/ca.crt
       - CORE_PEER_MSPCONFIGPATH=/opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/peerOrganizations/org1.example.com/users/Admin@org1.example.com/msp
     working_dir: /opt/gopath/src/github.com/hyperledger/fabric/peer
-#    command: /bin/bash -c './scripts/script.sh ${CHANNEL_NAME}; sleep $TIMEOUT'
+    command: /bin/bash -c './scripts/script.sh ${CHANNEL_NAME}; sleep $TIMEOUT'
     volumes:
         - /var/run/:/host/var/run/
         - ../chaincode/go/:/opt/gopath/src/github.com/hyperledger/fabric/examples/chaincode/go
```

そのままでも問題無いのですが、コメントアウトしない場合、ネットワーク起動と同時にコードが走ってしまうので、それを防止したいです。
コメントアウトしない場合は、チェーンコードのインストール等とチェーンコードのインストールも実行も全て実行されます。楽をした方はコメントアウトしないでください。

### ネットワークの起動

ネットワークの起動は、Dockerを起動するだけです。

```
CHANNEL_NAME=mychannel TIMEOUT=360 docker-compose -f docker-compose-cli.yaml up -d
```

タイムアウト値は、cliコンテナの終了までの時間です。デフォルトであれば、60秒に設定されます。
これで一応ネットワークは上がります。

上でコメントアウトをして実行した場合は、これからチェーンコードのインストールなどが必要になりますが、これは、scriptファイルを読みながら実行するのがわかりやすいです。

まずは、クライアントにログインします。
コマンドは、`docker exec -it cli bash`でDocker上でbashを起動することができます。

スクリプトファイルは`/opt/gopath/src/github.com/hyperledger/fabric/peer/scripts`に入っているので、確認して見てください。

大まかな流れは、

1. peerにチャンネルを生成
1. peerとチャンネルを紐付け
1. チェーンコードのインストール
1. チェーンコードのインスタンス化
1. query/Invokeの実行

という流れです。

私は、面倒くさがりなので、スクリプトファイルのQuery/Invoke部分のみをコメントアウトして、スクリプトを実行しました。

一つひとつ実行するには、以下の環境変数の設定が必要です。

```
CORE_PEER_MSPCONFIGPATH=/opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/peerOrganizations/org1.example.com/users/Admin@org1.example.com/msp
CORE_PEER_ADDRESS=peer0.org1.example.com:7051
CORE_PEER_LOCALMSPID="Org1MSP"
CORE_PEER_TLS_ROOTCERT_FILE=/opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/peerOrganizations/org1.example.com/peers/peer0.org1.example.com/tls/ca.crt
```

### チャンネルの生成

チャンネル生成のコマンドは、以下の通りですがいくつかオプションがあります。

```
peer channel create -o orderer.example.com:7050 -c $CHANNEL_NAME -f ./channel-artifacts/channel.tx --tls $CORE_PEER_TLS_ENABLED --cafile /opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/ordererOrganizations/example.com/orderers/orderer.example.com/msp/cacerts/ca.example.com-cert.pem
```
-c オプションは、チャンネル名を指定するもので、今までデフォルトで作業をしている場合には、”mychannel"を環境変数に設定しておく必要があります。
--tlsオプションは、CAサーバーの有無だと思っているのですが…… そして--cafileは、鍵

### チャンネルの紐付け

```
peer channel join -b mychannel.block
```

これは、非常に簡単。
-b オプションに<チャンネル名> + ".block" を与えてください。

### チェーンコードのインストール

```
peer chaincode install -n mycc -v 1.0 -p github.com/hyperledger/fabric/examples/chaincode/go/chaincode_example02
```

今回は、fabricのサンプルを利用します。
[chaincode_example02](https://github.com/hyperledger/fabric/tree/master/examples/chaincode/go/chaincode_example02)


### インスタンス化

```
peer chaincode instantiate -o orderer.example.com:7050 --tls $CORE_PEER_TLS_ENABLED --cafile /opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/ordererOrganizations/example.com/orderers/orderer.example.com/msp/cacerts/ca.example.com-cert.pem -C $CHANNEL_NAME -n mycc -v 1.0 -p github.com/hyperledger/fabric/examples/chaincode/go/chaincode_example02 -c '{"Args":["init","a", "100", "b","200"]}' -P "OR ('Org1MSP.member','Org2MSP.member')"
```

少し長いですが、上記のコマンドでインスタンス化を行うことができます。
-P オプションは、注意して見ておく必要があって、チェーンコードに対するトランザクションの検証に必要な保証レベルを指定しているものです。
上記のコマンドであれば、ORが設定されているため、どちらかの署名が必要であり、ANDを指定した場合には、両方の署名が必要になります。


### 準備完了

これで、大体の準備は終了しました。
あとは、次項のクエリの実行を試してみてください。

クエリの実行
----------

ここはざっくりと行きます。大きく分けて参照系と更新系です。

### Query

```
# peer chaincode query -C $CHANNEL_NAME -n mycc -c '{"Args":["query","a"]}'
peer chaincode query -C $CHANNEL_NAME -n mycc -c '{"Args":["query","a"]}'
2017-06-06 04:01:05.322 UTC [msp] getMspConfig -> INFO 001 intermediate certs folder not found at [/opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/peerOrganizations/org1.example.com/users/Admin@org1.example.com/msp/intermediatecerts]. Skipping.: [stat /opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/peerOrganizations/org1.example.com/users/Admin@org1.example.com/msp/intermediatecerts: no such file or directory]
2017-06-06 04:01:05.323 UTC [msp] getMspConfig -> INFO 002 crls folder not found at [/opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/peerOrganizations/org1.example.com/users/Admin@org1.example.com/msp/intermediatecerts]. Skipping.: [stat /opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/peerOrganizations/org1.example.com/users/Admin@org1.example.com/msp/crls: no such file or directory]
2017-06-06 04:01:05.324 UTC [msp] getMspConfig -> INFO 003 MSP configuration file not found at [/opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/peerOrganizations/org1.example.com/users/Admin@org1.example.com/msp/config.yaml]: [stat /opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/peerOrganizations/org1.example.com/users/Admin@org1.example.com/msp/config.yaml: no such file or directory]
2017-06-06 04:01:05.379 UTC [msp] GetLocalMSP -> DEBU 004 Returning existing local MSP
2017-06-06 04:01:05.379 UTC [msp] GetDefaultSigningIdentity -> DEBU 005 Obtaining default signing identity
2017-06-06 04:01:05.381 UTC [msp/identity] Sign -> DEBU 006 Sign: plaintext: 0AB1070A6708031A0C0881D2D8C90510...6D7963631A0A0A0571756572790A0161 
2017-06-06 04:01:05.381 UTC [msp/identity] Sign -> DEBU 007 Sign: digest: B1AFF6EB89C822367267DF1966E4C212CB63816BF3E4575D94109F872B08264D 
Query Result: 90
2017-06-06 04:01:05.398 UTC [main] main -> INFO 008 Exiting.....
```

このように表示されれば成功でしょうか。

### Invoke

更新は、少しQueryよりも長いコメンドです。
鍵情報もオプションで指定しなければ行けません

```
peer chaincode invoke -o orderer.example.com:7050  --tls $CORE_PEER_TLS_ENABLED --cafile /opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/ordererOrganizations/example.com/orderers/orderer.example.com/msp/cacerts/ca.example.com-cert.pem  -C $CHANNEL_NAME -n mycc -c '{"Args":["invoke","a","b","10"]}'
2017-06-06 04:02:09.823 UTC [msp] getMspConfig -> INFO 001 intermediate certs folder not found at [/opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/peerOrganizations/org1.example.com/users/Admin@org1.example.com/msp/intermediatecerts]. Skipping.: [stat /opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/peerOrganizations/org1.example.com/users/Admin@org1.example.com/msp/intermediatecerts: no such file or directory]
2017-06-06 04:02:09.824 UTC [msp] getMspConfig -> INFO 002 crls folder not found at [/opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/peerOrganizations/org1.example.com/users/Admin@org1.example.com/msp/intermediatecerts]. Skipping.: [stat /opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/peerOrganizations/org1.example.com/users/Admin@org1.example.com/msp/crls: no such file or directory]
2017-06-06 04:02:09.825 UTC [msp] getMspConfig -> INFO 003 MSP configuration file not found at [/opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/peerOrganizations/org1.example.com/users/Admin@org1.example.com/msp/config.yaml]: [stat /opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/peerOrganizations/org1.example.com/users/Admin@org1.example.com/msp/config.yaml: no such file or directory]
2017-06-06 04:02:09.874 UTC [msp] GetLocalMSP -> DEBU 004 Returning existing local MSP
2017-06-06 04:02:09.874 UTC [msp] GetDefaultSigningIdentity -> DEBU 005 Obtaining default signing identity
2017-06-06 04:02:09.886 UTC [msp/identity] Sign -> DEBU 006 Sign: plaintext: 0AB1070A6708031A0C08C1D2D8C90510...696E766F6B650A01610A01620A023130 
2017-06-06 04:02:09.886 UTC [msp/identity] Sign -> DEBU 007 Sign: digest: BF0DE2B805CEA15D6DECEC0EA54B3F360C8EC70ED0A01A65F6F954CA9C7AEAA6 
2017-06-06 04:02:09.908 UTC [msp/identity] Sign -> DEBU 008 Sign: plaintext: 0AB1070A6708031A0C08C1D2D8C90510...5AF1ACA6EB7D788A6FE6C8A511E781D9 
2017-06-06 04:02:09.908 UTC [msp/identity] Sign -> DEBU 009 Sign: digest: D3019778F6AC956CD314C5AE506D872144FDF06A041BE03891251B2DB58DBFD2 
2017-06-06 04:02:09.913 UTC [chaincodeCmd] chaincodeInvokeOrQuery -> INFO 00a Invoke result: version:1 response:<status:200 message:"OK" > payload:"\n \362#\311\265\212sJ\300(\r\021h\022\\{\244\362\007\001\265\377]O\364,\360v\r,\273\216\222\022Y\nE\022\024\n\004lscc\022\014\n\n\n\004mycc\022\002\010\003\022-\n\004mycc\022%\n\007\n\001a\022\002\010\004\n\007\n\001b\022\002\010\004\032\007\n\001a\032\00280\032\010\n\001b\032\003220\032\003\010\310\001\"\013\022\004mycc\032\0031.0" endorsement:<endorser:"\n\007Org1MSP\022\325\006-----BEGIN -----\nMIICWjCCAgCgAwIBAgIQQxRc4MbvKUYWgo9QsucwmDAKBggqhkjOPQQDAjBzMQsw\nCQYDVQQGEwJVUzETMBEGA1UECBMKQ2FsaWZvcm5pYTEWMBQGA1UEBxMNU2FuIEZy\nYW5jaXNjbzEZMBcGA1UEChMQb3JnMS5leGFtcGxlLmNvbTEcMBoGA1UEAxMTY2Eu\nb3JnMS5leGFtcGxlLmNvbTAeFw0xNzA2MDUxNTA5MTVaFw0yNzA2MDMxNTA5MTVa\nMFsxCzAJBgNVBAYTAlVTMRMwEQYDVQQIEwpDYWxpZm9ybmlhMRYwFAYDVQQHEw1T\nYW4gRnJhbmNpc2NvMR8wHQYDVQQDExZwZWVyMC5vcmcxLmV4YW1wbGUuY29tMFkw\nEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEAL42JyEYleiKACAq5D/hQ1Qji0kvd7hA\nRfjX7iwnc9ucfjMpSrJog5Z+aBp4bk13D5hEcGs6+s0rBsXDpzS3AaOBjTCBijAO\nBgNVHQ8BAf8EBAMCBaAwEwYDVR0lBAwwCgYIKwYBBQUHAwEwDAYDVR0TAQH/BAIw\nADArBgNVHSMEJDAigCA8Vo0bChIqPhVY8w8TsU7y7l/gku423TtNSGHDv5ghzTAo\nBgNVHREEITAfghZwZWVyMC5vcmcxLmV4YW1wbGUuY29tggVwZWVyMDAKBggqhkjO\nPQQDAgNIADBFAiEAuxcn7ISNCvj5cU+NDIxft0W/ozYZp/RWTdl4+3U8ZXECIGGj\n3Kn1N8wWwkQLDHzneFP6bayV7AM/wAz+NAK/up5Z\n-----END -----\n" signature:"0D\002 f\355~\230n>~\223\270S\366Un7/j\316m\347\307\350g\265}\026\351\236\340\006\003C'\002 \021\\1z\341\307+Rc\265O\350\356K\214\227Z\361\254\246\353}x\212o\346\310\245\021\347\201\331" > 
2017-06-06 04:02:09.916 UTC [main] main -> INFO 00b Exiting.....
```

中程の`chaincodeInvokeOrQuery -> INFO 00a Invoke result: version:1 response:<status:200 message:"OK" > payload:"\n`が表示されれば成功しているものと思います。

```
peer chaincode invoke -o orderer.example.com:7050  --tls $CORE_PEER_TLS_ENABLED --cafile /opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/ordererOrganizations/example.com/orderers/orderer.example.com/msp/cacerts/ca.example.com-cert.pem  -C $CHANNEL_NAME -n mycc -c '{"Args":["invoke","a","b","10"]}'
2017-06-06 04:02:09.823 UTC [msp] getMspConfig -> INFO 001 intermediate certs folder not found at [/opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/peerOrganizations/org1.example.com/users/Admin@org1.example.com/msp/intermediatecerts]. Skipping.: [stat /opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/peerOrganizations/org1.example.com/users/Admin@org1.example.com/msp/intermediatecerts: no such file or directory]
2017-06-06 04:02:09.824 UTC [msp] getMspConfig -> INFO 002 crls folder not found at [/opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/peerOrganizations/org1.example.com/users/Admin@org1.example.com/msp/intermediatecerts]. Skipping.: [stat /opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/peerOrganizations/org1.example.com/users/Admin@org1.example.com/msp/crls: no such file or directory]
2017-06-06 04:02:09.825 UTC [msp] getMspConfig -> INFO 003 MSP configuration file not found at [/opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/peerOrganizations/org1.example.com/users/Admin@org1.example.com/msp/config.yaml]: [stat /opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/peerOrganizations/org1.example.com/users/Admin@org1.example.com/msp/config.yaml: no such file or directory]
2017-06-06 04:02:09.874 UTC [msp] GetLocalMSP -> DEBU 004 Returning existing local MSP
2017-06-06 04:02:09.874 UTC [msp] GetDefaultSigningIdentity -> DEBU 005 Obtaining default signing identity
2017-06-06 04:02:09.886 UTC [msp/identity] Sign -> DEBU 006 Sign: plaintext: 0AB1070A6708031A0C08C1D2D8C90510...696E766F6B650A01610A01620A023130 
2017-06-06 04:02:09.886 UTC [msp/identity] Sign -> DEBU 007 Sign: digest: BF0DE2B805CEA15D6DECEC0EA54B3F360C8EC70ED0A01A65F6F954CA9C7AEAA6 
2017-06-06 04:02:09.908 UTC [msp/identity] Sign -> DEBU 008 Sign: plaintext: 0AB1070A6708031A0C08C1D2D8C90510...5AF1ACA6EB7D788A6FE6C8A511E781D9 
2017-06-06 04:02:09.908 UTC [msp/identity] Sign -> DEBU 009 Sign: digest: D3019778F6AC956CD314C5AE506D872144FDF06A041BE03891251B2DB58DBFD2 
2017-06-06 04:02:09.913 UTC [chaincodeCmd] chaincodeInvokeOrQuery -> INFO 00a Invoke result: version:1 response:<status:200 message:"OK" > payload:"\n \362#\311\265\212sJ\300(\r\021h\022\\{\244\362\007\001\265\377]O\364,\360v\r,\273\216\222\022Y\nE\022\024\n\004lscc\022\014\n\n\n\004mycc\022\002\010\003\022-\n\004mycc\022%\n\007\n\001a\022\002\010\004\n\007\n\001b\022\002\010\004\032\007\n\001a\032\00280\032\010\n\001b\032\003220\032\003\010\310\001\"\013\022\004mycc\032\0031.0" endorsement:<endorser:"\n\007Org1MSP\022\325\006-----BEGIN -----\nMIICWjCCAgCgAwIBAgIQQxRc4MbvKUYWgo9QsucwmDAKBggqhkjOPQQDAjBzMQsw\nCQYDVQQGEwJVUzETMBEGA1UECBMKQ2FsaWZvcm5pYTEWMBQGA1UEBxMNU2FuIEZy\nYW5jaXNjbzEZMBcGA1UEChMQb3JnMS5leGFtcGxlLmNvbTEcMBoGA1UEAxMTY2Eu\nb3JnMS5leGFtcGxlLmNvbTAeFw0xNzA2MDUxNTA5MTVaFw0yNzA2MDMxNTA5MTVa\nMFsxCzAJBgNVBAYTAlVTMRMwEQYDVQQIEwpDYWxpZm9ybmlhMRYwFAYDVQQHEw1T\nYW4gRnJhbmNpc2NvMR8wHQYDVQQDExZwZWVyMC5vcmcxLmV4YW1wbGUuY29tMFkw\nEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEAL42JyEYleiKACAq5D/hQ1Qji0kvd7hA\nRfjX7iwnc9ucfjMpSrJog5Z+aBp4bk13D5hEcGs6+s0rBsXDpzS3AaOBjTCBijAO\nBgNVHQ8BAf8EBAMCBaAwEwYDVR0lBAwwCgYIKwYBBQUHAwEwDAYDVR0TAQH/BAIw\nADArBgNVHSMEJDAigCA8Vo0bChIqPhVY8w8TsU7y7l/gku423TtNSGHDv5ghzTAo\nBgNVHREEITAfghZwZWVyMC5vcmcxLmV4YW1wbGUuY29tggVwZWVyMDAKBggqhkjO\nPQQDAgNIADBFAiEAuxcn7ISNCvj5cU+NDIxft0W/ozYZp/RWTdl4+3U8ZXECIGGj\n3Kn1N8wWwkQLDHzneFP6bayV7AM/wAz+NAK/up5Z\n-----END -----\n" signature:"0D\002 f\355~\230n>~\223\270S\366Un7/j\316m\347\307\350g\265}\026\351\236\340\006\003C'\002 \021\\1z\341\307+Rc\265O\350\356K\214\227Z\361\254\246\353}x\212o\346\310\245\021\347\201\331" > 
2017-06-06 04:02:09.916 UTC [main] main -> INFO 00b Exiting.....
root@2476f4f9cafc:/opt/gopath/src/github.com/hyperledger/fabric/peer# peer chaincode query -C $CHANNEL_NAME -n mycc -c '{"Args":["query","a"]}'
2017-06-06 04:06:12.774 UTC [msp] getMspConfig -> INFO 001 intermediate certs folder not found at [/opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/peerOrganizations/org1.example.com/users/Admin@org1.example.com/msp/intermediatecerts]. Skipping.: [stat /opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/peerOrganizations/org1.example.com/users/Admin@org1.example.com/msp/intermediatecerts: no such file or directory]
2017-06-06 04:06:12.774 UTC [msp] getMspConfig -> INFO 002 crls folder not found at [/opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/peerOrganizations/org1.example.com/users/Admin@org1.example.com/msp/intermediatecerts]. Skipping.: [stat /opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/peerOrganizations/org1.example.com/users/Admin@org1.example.com/msp/crls: no such file or directory]
2017-06-06 04:06:12.775 UTC [msp] getMspConfig -> INFO 003 MSP configuration file not found at [/opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/peerOrganizations/org1.example.com/users/Admin@org1.example.com/msp/config.yaml]: [stat /opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/peerOrganizations/org1.example.com/users/Admin@org1.example.com/msp/config.yaml: no such file or directory]
2017-06-06 04:06:12.819 UTC [msp] GetLocalMSP -> DEBU 004 Returning existing local MSP
2017-06-06 04:06:12.819 UTC [msp] GetDefaultSigningIdentity -> DEBU 005 Obtaining default signing identity
2017-06-06 04:06:12.820 UTC [msp/identity] Sign -> DEBU 006 Sign: plaintext: 0AB1070A6708031A0C08B4D4D8C90510...6D7963631A0A0A0571756572790A0161 
2017-06-06 04:06:12.820 UTC [msp/identity] Sign -> DEBU 007 Sign: digest: DFC6902BF5AFF39F69F12DF9789FF41DD8F633FE6F44487E342968761DBC2E2F 
Query Result: 80
2017-06-06 04:06:12.850 UTC [main] main -> INFO 008 Exiting.....
root@2476f4f9cafc:/opt/gopath/src/github.com/hyperledger/fabric/peer# 
```


まとめ
-----

本当はDBを変更したりしたかったのですが、まだ少し時間がかかりそうです。
次回は、チェーンコードをいじって自分のロジックを走らせえみようと思います。