Ethereumの環境構築をDockerで行う(geth,parity)

この記事ではMac OS Sierra 10.12.4を使っています。

Ethereumの環境構築について、最近聞かれるのでまとめました。
現在、Ethereumの環境構築ではメジャーな方法が以下の２つあると考えています。

<b>

1. gethを利用する

1. parityを利用する

</b>


今回は２つの方法ともまとめてみようと思います。
gethをそのままインストールしても良いのですが、既存のDockerイメージを使う方が便利で、早く構築できるので、Dockerイメージを利用する方法でまとめます。



# 1.gethのDockerを利用して環境構築を行う

gethは公式のEthereumクライアントです。goで書かれているので、go-ethereum、頭文字をとってgethとしています。
gethのDockerを取得します。公式らしきDockerがありましたので、こちらを利用させていただきます。

[https://hub.docker.com/r/ethereum/client-go/]


## Dockerイメージのダウンロード

早速、docker pull で上記のイメージをダウンロードします。

```sh
docker pull ethereum/client-go #tagを指定しなければdefaultでlatestを取ってくる

Using default tag: latest
latest: Pulling from ethereum/client-go
88286f41530e: Pull complete 
528f0dd33bed: Pull complete 
8b00e08f6a7a: Pull complete 
Status: Downloaded newer image for ethereum/client-go:latest

docker images  # docker imageが落とせていることを確認
REPOSITORY           TAG                 IMAGE ID            CREATED             SIZE
ethereum/client-go   latest              34fe6352736b        7 hours ago         35.9MB

```

## Dockerコンテナの作成

```sh
docker runでイメージからコンテナを作ります。
docker run -d --name ethereum-node -v $HOME/ethereum-data:/root \
            -p 8545:8545 -p 30303:30303 \
            ethereum/client-go --fast --cache=512

CONTAINER ID        IMAGE                  COMMAND                  CREATED             STATUS              PORTS                                                                   NAMES
8dd333c2fb47        ethereum/client-go     "geth --fast --cac..."   3 seconds ago         Up 2 seconds        0.0.0.0:8545->8545/tcp, 0.0.0.0:30303->30303/tcp, 8546/tcp, 30303/udp   ethereum-node
```

各オプションを説明します。

<b>docker のオプション</b>

* -d デーモンとして裏で動かす
* --name コンテナ名をつけます（例だとethereum-node）
* -v ボリュームのマウント先を指定します。第一引数にマウント先、第二引数にdocker内のマウント元を指定します。例ではホストの「$HOME/ethereum-data」フォルダに、コンテナ内の「/root」内データをマウントさせます。ブロックチェーンデータはノードを立てる旅に同期ダウンロードしますが、コンテナをブロックチェーンデータごと消してしまうとまた初めからダウンロードがやり直しになってしまいます。ホスト側にマウントする事は必須と考えられます。
* -p ポート番号を指定します 

<b>ethereumのオプション</b>

* --fast 高速ダウンロードを行います
* --cache=512 キャッシュサイズを指定します。

## ブロックチェーン同期ログを確認する                                 

dockerのログを確認します。ブロックが同期されていきログがどんどん増えていきます。
ノードが無事に立った証拠ですね。

```sh
nao docker logs -f ethereum-node #fオプションはログを流しっぱなしにする。Ctrl+Cでログストリームから抜ける
WARN [09-13|15:17:54] No etherbase set and no accounts found as default 
INFO [09-13|15:17:54] Starting peer-to-peer node               instance=Geth/v1.7.0-unstable/linux-amd64/go1.9
INFO [09-13|15:17:54] Allocated cache and file handles         database=/root/.ethereum/geth/chaindata cache=512 handles=1024
INFO [09-13|15:17:54] Writing default main-net genesis block 
INFO [09-13|15:18:01] Initialised chain configuration          config="{ChainID: 1 Homestead: 1150000 DAO: 1920000 DAOSupport: true EIP150: 2463000 EIP155: 2675000 EIP158: 2675000 M
…
INFO [09-13|15:36:30] Imported new block receipts              count=4    elapsed=1.033ms   bytes=16      number=173656 hash=96bf2a…f1d7f6 ignored=0
INFO [09-13|15:36:30] Imported new state entries               count=1160 elapsed=7.944ms   processed=246145 pending=7605  retry=0   duplicate=0 unexpected=0
```

## dockerでgethコマンドを実行する

dockerコンテナ内に以下コマンドで入り、shを起動します。

```sh
docker exec -it ethereum-node sh
```

geth attachでノードにアクセスします。

```sh
/ #
/ # geth attach
Welcome to the Geth JavaScript console!
```

ethのコマンドを使えます。
eth.~でコマンドを色々と使えます。

試しにgetBlockでダウンロードしたブロックの中身を見て見ましょう。      

```sh
> eth.getBlock(100)
>{
  difficulty: 17916437174,
  extraData: "0x476574682f4c5649562f76312e302e302f6c696e75782f676f312e342e32",
  gasLimit: 5000,
  gasUsed: 0,
  hash: "0xdfe2e70d6c116a541101cecbb256d7402d62125f6ddc9b607d49edc989825c64",
  logsBloom: "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
  miner: "0xbb7b8287f3f0a933474a79eae42cbca977791171",
  mixHash: "0x5bb43c0772e58084b221c8e0c859a45950c103c712c5b8f11d9566ee078a4501",
  nonce: "0x37129c7f29a9364b",
  number: 100,
  parentHash: "0xdb10afd3efa45327eb284c83cc925bd9bd7966aea53067c1eebe0724d124ec1e",
  receiptsRoot: "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
  sha3Uncles: "0x1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347",
  size: 542,
  stateRoot: "0x90c25f6d7fddeb31a6cc5668a6bba77adbadec705eb7aa5a51265c2d1e3bb7ac",
  timestamp: 1438270443,
  totalDifficulty: 1766758139014,
  transactions: [],
  transactionsRoot: "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
  uncles: []
}
```

これでgethでノードを立てる方法はわかりましたね。 


# 2.parityのDockerを利用して環境構築を行う

parityは[Parity Technologies](https://parity.io/)の提供する軽量かつ高速なEthereumクライアントツールです。
gethと比べて高速にブロックチェーンのダウンロードができる、オプションが豊富で、いくらでも過去のブロックを遡って残高を参照できるなどの設定ができるなどの特徴があります。


ただし、過去にはバグが見つかり盗難被害が起きたこともあったようです。
[イーサリアムPARITYの脆弱性で34億円が盗まれる](https://ethereum-japan.net/ethereum/parity-maltisig-vulnerability-hacked-150keth/)

<b>こちらの盗難被害はParityクライアントのことではなく、Parityのマルチシグウォレットのスマートコントラクトのバグであると指摘をいただきました。</b>

## parityのDockerイメージをダウンロードする

Dockerイメージをダウンロードします。
[公式イメージ](https://hub.docker.com/r/parity/parity/)があったので利用します。Tagにlatestはないので、stableを指定します。


```sh
docker pull parity/parity:stable

stable: Pulling from parity/parity
7ee37f181318: Pull complete 
df5ffabe5e97: Pull complete 
ae2040ed51a1: Pull complete 
3ce7010d244b: Pull complete 
2538b201d2a6: Pull complete 
23f0aa8d9740: Pull complete 
a28c96feeaa9: Pull complete 
c800aa764e74: Pull complete 
Status: Downloaded newer image for parity/parity:stable

docker images #docker imageを落とせていることを確認
REPOSITORY           TAG                 IMAGE ID            CREATED             SIZE
parity/parity        stable              bf83ba750885        7 weeks ago         373MB

```

## Dockerコンテナを作成する

落としてきたDockerイメージからコンテナを作成します。

```sh
#コンテナ作成
docker run -d -v $HOME/eth_parity_data:/root/.local/share/io.parity.ethereum --name eth_parity_node parity/parity:stable --pruning fast --warp

#コンテナ確認
docker ps
CONTAINER ID        IMAGE                  COMMAND                  CREATED             STATUS              PORTS                          NAMES
d3ff1efd5d46        parity/parity:stable   "/parity/parity --..."   3 seconds ago       Up 2 seconds        8080/tcp, 8180/tcp, 8545/tcp   eth_parity_node

```

各オプションを説明します。

<b>docker のオプション</b>

* -d デーモンとして裏で動かす

* --name コンテナ名をつけます（例だとethereum-node）

* -v ボリュームのマウント先を指定します。第一引数にマウント先、第二引数にdocker内のマウント元を指定します。例ではホストの「$HOME/eth_parity_data」フォルダに、コンテナ内の「/root/.local/share/io.parity.ethereum」内データをマウントさせます。

<b>parity のオプション</b>

* --pruning fast 高速ダウンロードオプションです。archiveを指定すると、ダウンロードは時間がかかるものの、過去のどの時点を指定しても残高を確認できるようになります。

* --warp 高速ダウンロードオプションです。おそらく、公式を見る限り圧縮されたデータをダウンロードしてくるオプションと思われます。デフォルトではtrueなので明示指定は実は不要です


## parityノードのログを確認する

geth同様にログを確認します。
こちらも他ノードと繋がり、シンクロしていっています。
無事に立ちました。

```sh
docker logs -f eth_parity_node
2017-09-13 17:07:54 UTC Starting Parity/v1.6.10-stable-1a5b176-20170721/x86_64-linux-gnu/rustc1.18.0
2017-09-13 17:07:54 UTC State DB configuration: fast
2017-09-13 17:07:54 UTC Operating mode: active
2017-09-13 17:07:54 UTC Configured for Foundation using Ethash engine
2017-09-13 17:08:00 UTC Public node URL: 

2017-09-13 17:12:25 UTC Syncing snapshot 16/332        #0   10/25 peers     3 MiB db    7 KiB chain  0 bytes queue   10 KiB sync  RPC:  0 conn,  0 req/s,   0 µs
2017-09-13 17:12:30 UTC Syncing snapshot 16/332        #0   10/25 peers     3 MiB db    7 KiB chain  0 bytes queue   10 KiB sync  RPC:  0 conn,  0 req/s,   0 µs
2017-09-13 17:12:35 UTC Syncing snapshot 16/332        #0   10/25 peers     3 MiB db    7 KiB chain  0 bytes queue   10 KiB sync  RPC:  0 conn,  0 req/s,   0 µs
2017-09-13 17:12:40 UTC Syncing snapshot 16/332        #0   10/25 peers     3 MiB db    7 KiB chain  0 bytes queue   10 KiB sync  RPC:  0 conn,  0 req/s,   0 µs
2017-09-13 17:12:45 UTC Syncing snapshot 16/332        #0   10/25 peers     3 MiB db    7 KiB chain  0 bytes queue   10 KiB sync  RPC:  0 conn,  0 req/s,   0 µs
2017-09-13 17:12:50 UTC Syncing snapshot 18/332        #0   11/25 peers     3 MiB db    7 KiB chain  0 bytes queue   10 KiB sync  RPC:  0 conn,  0 req/s,   0 µs

```

今回は以上になります。
今後、色々な通貨のノードを立てたりしてみようと思います。