【2019年3月末版】Hyperledger Burrow ちゃんと入門

# Hyperledger Burrow ちゃんと試してみます。

[前回の記事](https://qiita.com/koinori/items/a76bc513459f6d69fa34)では fabric の EVM でチェーンコードが動いただけで Burrow の雰囲気を満喫してしまいましたが、今回はちゃんと Burrow を使用したいと思います。

Github のリポジトリは以下です。

- https://github.com/hyperledger/burrow

# 環境構築

今回は Ubuntu 18.04 ベースで大丈夫です。例によって lxc でコンテナ立ち上げるところからスタートいたします。

## Ubuntu 18.04 に Go言語のインストール

```console
$ lxc launch -p docker ubuntu burrow-go
$ lxc exec burrow-go bash
# sed -i.bak -e "s%http://[^ ]\+%http://ftp.riken.go.jp/Linux/ubuntu/%g" /etc/apt/sources.list
# apt update && apt upgrade -y
# apt install -y make
# cd /tmp && wget https://dl.google.com/go/go1.11.linux-amd64.tar.gz
# tar -xvf go1.11.linux-amd64.tar.gz
# mv go /usr/local
# rm go1.11.linux-amd64.tar.gz
# cd ~/
# mkdir go
# vi ~/.bashrc
```
以下の環境変数を bash に追加します。

```bash
export GOROOT=/usr/local/go
export GOPATH=$HOME/go
export PATH=$GOPATH/bin:$GOROOT/bin:$PATH
```
source して go のバージョンを確認してみましょう。

```console
# . ~/.bashrc
# go version
go version go1.11 linux/amd64
```

以上で GO のインストールは完了です。

## Burrow のダウンロード、ビルド
以下の手順を参考にします。
- https://github.com/hyperledger/burrow/blob/develop/docs/INSTALL.md
ですが`go get`ではうまくいかなかったので、`$GOPATH` 以下で `git clone`して同じ階層になるようにいたします。

```console
# mkdir -p $GOPATH/src/github.com/hyperledger
# cd $GOPATH/src/github.com/hyperledger
# git clone https://github.com/hyperledger/burrow.git
# cd burrow
# make build
```
で、`bin/burrow`がビルドされます。

```console
# ./bin/burrow -v
0.24.6+commit.v0.24.3-31-gfd132ac3+2019-03-25
```
チュートリアルにある手順ではこれを使うのですが、パスを通すのが面倒なので以下のコマンドで`burrow`コマンドを直接、インストールしてみます。

```console
# go install ./cmd/burrow
# burrow -v
0.24.6
```
こっちで問題なさそうです。

# Burrow ノードの起動

以下のチュートリアルに従ってシングルノードのオールインワン構成で立ち上げてみます。
- [Set up a single full account node](https://github.com/hyperledger/burrow/blob/develop/docs/quickstart/single-full-node.md)

```console
# burrow spec -p1 -f1 | burrow configure -s- > burrow.toml
# cat burrow.toml
...
  [[GenesisDoc.Validators]]
    Address = "F2E3188BA926EA8E43B74501C2F554D703C31D32"
    PublicKey = "{\"CurveType\":\"ed25519\",\"PublicKey\":\"F3E4AB248A3149B18C532AA86BAC7924AEDFD945968DED81E50A0686E7CDC11A\"}"
    Amount = 9999999999
...
```
上記で表示される`Validators.Address`を以下のコマンドで引き渡します。またこのアドレスは重要なので控えておきます。

```console
# burrow start --validator-address=F2E3188BA926EA8E43B74501C2F554D703C31D32
```
起動するとすごい勢いでログが流れていきます。tendermint のブロック生成がスタートしたようです。ブロック長が続々と伸びていきますね・・・

`bg` で後ろに送ってもログの送信が止まらないので諦めて別ターミナルを開きます。(Tendermintの再起動はちょっとめんどくさそうなのでこのまま続行します。)

# トランザクションの送信

`Burrow`コマンドでトランザクションを送る場合は`yaml`でトランザクションの命令？定義？を記述する必要があるようです。
以下の内容に従って最初のトランザクションを送ってみましょう。

- [Send transactions to a burrow network](https://github.com/hyperledger/burrow/blob/develop/docs/quickstart/send-transactions.md)

まず、先ほどの`burrow.toml`を`cat`して送信先のアドレスを確認します。上記で使用した Validatorと同じアドレスのアカウントもあるので、validatorではない方のアドレスをメモっておきます。

```console
# cat burrow.toml
...
  [[GenesisDoc.Accounts]]
    Address = "4F6CC8D6DF45ECABAC25634977EC33616FA3F9F6"
    PublicKey = "{\"CurveType\":\"ed25519\",\"PublicKey\":\"B765F3D2F33B3F34F213DDC3D956AFDAE0C23408CDB63A33386817DD1EE999F8\"}"
    Amount = 9999999999
    Name = "Participant_0"
...
```
上記の宛先アドレスを指定した以下のようなトランザクションyamlファイルを作成します。

```yaml:test.yaml
jobs:
  - name: sendTxTest1
    send:
      destination: 4F6CC8D6DF45ECABAC25634977EC33616FA3F9F6
      amount: 42
```
さっそく、Validatorのアドレス宛に送ってみましょう。

```console
# SIGNING_ADDRESS=F2E3188BA926EA8E43B74501C2F554D703C31D32
# burrow deploy --address $SIGNING_ADDRESS -f test.yaml
*****Executing Job*****

Job Name                                    => defaultAddr


*****Executing Job*****

Job Name                                    => sendTxTest1


Transaction Hash                            => 2E946B8EAE56A7B7B8377D7FDA11FE87753F8D4B96915B611D32B41FD7E98025
Writing [test.output.json] to current directory
# cat test.output.json
{
  "defaultAddr": "F2E3188BA926EA8E43B74501C2F554D703C31D32",
  "sendTxTest1": "2E946B8EAE56A7B7B8377D7FDA11FE87753F8D4B96915B611D32B41FD7E98025"
}
```
無事に実行されました！

# スマートコントラクトのデプロイ
続いて、以下のページに従ってスマートコントラクトのデプロイと実行を行ってみます。

- [Deploy Contracts](https://github.com/hyperledger/burrow/blob/develop/docs/quickstart/deploy-contracts.md)

## Solidity コンパイラ Solc のインストール

以下のページに solidity 単体のインストール方法についても記載があります。
[https://solidity.readthedocs.io/en/v0.4.24/installing-solidity.html](https://solidity.readthedocs.io/en/v0.4.24/installing-solidity.html)

こちらに従って、Ubuntuパッケージから大人しくインストールいたします。

```console
# add-apt-repository ppa:ethereum/ethereum
# apt update
# apt install -y solc
```

## サンプルスマートコントラクトのデプロイ

チュートリアルにある SimpleStorage をデプロイしてみます。

```console
# cd tests/jobs_fixtures/app06-deploy_basi_contract_and_different_solc_types_packed_unpacked/
# burrow deploy --address F2E3188BA926EA8E43B74501C2F554D703C31D32
*****Executing Job*****

Job Name                                    => defaultAddr


*****Executing Job*****

Job Name                                    => deployStorageK


Saving Binary                               => SimpleStorage
Deploying Contract                          name => SimpleStorage
                                            addr => 3E4893FF3A5F9672E2B7DFD77A2D641EA6BCC3BF
*****Executing Job*****

Job Name                                    => setStorageBaseBool


*****Executing Job*****

Job Name                                    => setStorageBool


*****Executing Job*****

Job Name                                    => queryStorageBool


Return Value                                => true
*****Executing Job*****

Job Name                                    => assertStorageBool


Assertion Succeeded                         => true == true
*****Executing Job*****

Job Name                                    => setStorageBool2


*****Executing Job*****

Job Name                                    => queryStorageBool2


Return Value                                => true
*****Executing Job*****

Job Name                                    => assertStorageBool2


Assertion Succeeded                         => true == true
*****Executing Job*****

Job Name                                    => setStorageBaseInt


*****Executing Job*****

Job Name                                    => setStorageInt


*****Executing Job*****

Job Name                                    => queryStorageInt


Return Value                                => 50000
*****Executing Job*****

Job Name                                    => assertStorageInt


Assertion Succeeded                         => 50000 == 50000
*****Executing Job*****

Job Name                                    => setStorageBaseUint


*****Executing Job*****

Job Name                                    => setStorageUint


*****Executing Job*****

Job Name                                    => queryStorageUint


Return Value                                => 9999999
*****Executing Job*****

Job Name                                    => assertStorageUint


Assertion Succeeded                         => 9999999 == 9999999
*****Executing Job*****

Job Name                                    => setStorageBaseAddress


*****Executing Job*****

Job Name                                    => setStorageAddress


*****Executing Job*****

Job Name                                    => queryStorageAddress


Return Value                                => 1040E6521541DAB4E7EE57F21226DD17CE9F0FB7
*****Executing Job*****

Job Name                                    => assertStorageAddress


Assertion Succeeded                         => 1040E6521541DAB4E7EE57F21226DD17CE9F0FB7 == 1040E6521541DAB4E7EE57F21226DD17CE9F0FB7
*****Executing Job*****

Job Name                                    => setStorageBaseBytes


*****Executing Job*****

Job Name                                    => setStorageBytes


*****Executing Job*****

Job Name                                    => queryStorageBytes


Return Value                                => marmatoshi
*****Executing Job*****

Job Name                                    => assertStorageBytes


Assertion Succeeded                         => marmatoshi == marmatoshi
*****Executing Job*****

Job Name                                    => setStorageBaseString


*****Executing Job*****

Job Name                                    => setStorageString


*****Executing Job*****

Job Name                                    => queryStorageString


Return Value                                => nakaburrow
*****Executing Job*****

Job Name                                    => assertStorageString


Assertion Succeeded                         => nakaburrow == nakaburrow
Writing [deploy.output.json] to current directory
```
バッチリ、動きますね。。。

```console
# cd ../app40-simple-storage/
# burrow deploy --address F2E3188BA926EA8E43B74501C2F554D703C31D32
*****Executing Job*****

Job Name                                    => defaultAddr


*****Executing Job*****

Job Name                                    => deploySimpleStorage


Saving Binary                               => SimpleStorage
Deploying Contract                          name => SimpleStorage
                                            addr => 464CA7D3283BFF960CBF17B1F3B8FC7CC84E04D9
*****Executing Job*****

Job Name                                    => setStorage


*****Executing Job*****

Job Name                                    => getStorage


Function call to constant function, query-contract type job will be faster than call
Return Value                                => 3
*****Executing Job*****

Job Name                                    => assertStorage


Assertion Succeeded                         => 3 == 3
Writing [deploy.output.json] to current directory
# cat deploy.output.json
{
  "assertStorage": "passed",
  "defaultAddr": "F2E3188BA926EA8E43B74501C2F554D703C31D32",
  "deploySimpleStorage": "464CA7D3283BFF960CBF17B1F3B8FC7CC84E04D9",
  "getStorage": "3",
  "setStorage": ""
}
```
ちょっと想像以上に処理が速いので試しに solc をアンインストールしてみます。

```console
# apt remove solc
# cd ../app05-deploy_query_contracts_and_testing_rendering_solc_int_type/
# burrow deploy --address F2E3188BA926EA8E43B74501C2F554D703C31D32
*****Executing Job*****

Job Name                                    => defaultAddr


*****Executing Job*****

Job Name                                    => setStorageBase


*****Executing Job*****

Job Name                                    => deployStorageK


exec: "solc": executable file not found in $PATH
```
`solc`がないと怒られました。
また`apt`で`install`されるのは現在、`0.5.6`ですが`solc`の`0.5`系の対応ができているんですね！
`Burrow`も`Ethereum`で動かすより手っ取り早いな・・・

改めて実行してみます。

```
# apt install -y solc
# burrow deploy --address F2E3188BA926EA8E43B74501C2F554D703C31D32
*****Executing Job*****

Job Name                                    => defaultAddr


*****Executing Job*****

Job Name                                    => setStorageBase


*****Executing Job*****

Job Name                                    => deployStorageK


Saving Binary                               => Storage
Deploying Contract                          name => Storage
                                            addr => F28514804B7B17934297A3EF6360A5227EF589E5
*****Executing Job*****

Job Name                                    => setStorage


*****Executing Job*****

Job Name                                    => queryStorage


Return Value                                => 5
*****Executing Job*****

Job Name                                    => assertStorage


Assertion Succeeded                         => 5 == 5
Writing [deploy.output.json] to current directory
# cat deploy.output.json
{
  "assertStorage": "passed",
  "defaultAddr": "F2E3188BA926EA8E43B74501C2F554D703C31D32",
  "deployStorageK": "F28514804B7B17934297A3EF6360A5227EF589E5",
  "queryStorage": "5",
  "setStorage": "",
  "setStorageBase": "5"
}
```
ばっちりですね！！

# まとめ

Hyperledger Burrow を Ubuntu 18.04 ベースで動かしてみましたが Solc の 0.5 系の対応もできていてビックリいたしました。0.4系から0.5系では破壊的更新があったので 0.4系のスマートコントラクトを0.5系のコンパイラでビルドさせるの大変なんだけど・・・`Ethereum`本体より簡単なんじゃないだろうか？
また単独ノードでは Tendermint がかなり高速です。ベンチマークとか全然取ってませんが、個人的なスマートコントラクト開発では十分なレスポンスが返せていると思います。
Tendermint 自身も試してみたいと思います。

本日は以上です。