EthereumのプライベートネットをPoAで構築する

最近、Ethereumのデベロッパー向けコミュニティである[Hi-Ether（ハイイーサと読みます）のmeetup](https://qiita.com/tsukukobaan/items/78a2a47c61c4f5040c6a)に行ってきました。
その中でALISのCTOである石井さんから「Ethereumで「今」サービスを作る」という講演があり、スケーラビリティの問題から「今」サービスを作るのは非常にしんどい、そのため、PoAでプライベートネットを作ってサービスを運営するというお話がありました。

このとき、

「そういえば、PoAでプライベートネット作ったことないな〜」

と思い、どうやって作ればいいのかなと調べてみることにしました。
しかし、意外と日本語の情報が出てこない...

ということで今回は備忘も兼ねて、PoAでEthereumのプライベートネットを構築する手順をまとめてみました。

##0. 前提
- go-ethereumがインストールしてある
- make allでビルド済み
- gethコマンドの操作に慣れている

##1. 新しいアカウントを作成する
今回はprivateconsortiumというディレクトリを用意し、その中にアカウントを作成します。

```
$ geth account new --datadir ./privateconsortium/node1/keystore
```

##2. ジェネシス・ブロックを作成する
go-ethereumに付属しているpuppethツールを使用して、PoAネットワークのジェネシス・ブロックを作成します。
network名をprivateconsortiumとして、puppethを実行します。

今回はジェネシス・ブロック作成なので、2を選ぶ。

```
$ puppeth --network privateconsortium/
+-----------------------------------------------------------+
| Welcome to puppeth, your Ethereum private network manager |
|                                                           |
| This tool lets you create a new Ethereum network down to  |
| the genesis block, bootnodes, miners and ethstats servers |
| without the hassle that it would normally entail.         |
|                                                           |
| Puppeth uses SSH to dial in to remote servers, and builds |
| its network components out of Docker containers using the |
| docker-compose toolset.                                   |
+-----------------------------------------------------------+

INFO [02-04|10:30:17] Administering Ethereum network           name=privateconsortium/
WARN [02-04|10:30:17] No previous configurations found         path=/Users/shikitakahashi/.puppeth/privateconsortium

What would you like to do? (default = stats)
 1. Show network stats
 2. Configure new genesis
 3. Track new remote server
 4. Deploy network components
> 2
```

PoAなので、ここでも2を選ぶ。

```
Which consensus engine to use? (default = clique)
 1. Ethash - proof-of-work
 2. Clique - proof-of-authority
> 2
```

ブロック生成の感覚を設定します。

```
How many seconds should blocks take? (default = 15)
>5
```

geth account newコマンドで作成したアカウントのアドレスを入力する。

```
Which accounts are allowed to seal? (mandatory at least one)
> 0xf18aecbf8b0fabd8c56b41471ba923457df8bca7
> 0x
```

ここも上記と同様です。

```
Which accounts should be pre-funded? (advisable at least one)
> 0xf18aecbf8b0fabd8c56b41471ba923457df8bca7
> 0x
```

network IDを設定します。今回はdefaultのランダムにしました。

```
Specify your chain/network ID if you want an explicit one (default = random)
>
```

こちらもデフォルトです。

```
Anything fun to embed into the genesis block? (max 32 bytes)
> 
```


```
What would you like to do? (default = stats)
 1. Show network stats
 2. Manage existing genesis
 3. Track new remote server
 4. Deploy network components
> 2
```

```
 1. Modify existing fork rules
 2. Export genesis configuration
> 2

Which file to save the genesis into? (default = privateconsortium/.json)
> private.json
INFO [02-04|10:47:06] Exported existing genesis block 

What would you like to do? (default = stats)
 1. Show network stats
 2. Manage existing genesis
 3. Track new remote server
 4. Deploy network components
> ^C
```

##3. ネットワークを開始する
ノードを起動します。 

```
$ geth --datadir node1 init private.json
$ geth --datadir node1 --port 3000
```

さらに別のタブを開いて、gethコンソールにそれぞれ入ります。

```
$ geth attach ipc:node1/geth.ipc
Welcome to the Geth JavaScript console!

instance: Geth/v1.7.3-stable/darwin-amd64/go1.9.2
 modules: admin:1.0 clique:1.0 debug:1.0 eth:1.0 miner:1.0 net:1.0 personal:1.0 rpc:1.0 txpool:1.0 web3:1.0

>
```

##4. マイニングを開始する
アカウントのロックを解除してマイニングを開始する。

```
> personal.unlockAccount(eth.coinbase, 'pass1', 0)
> eth.defaultAccount = eth.coinbase
> miner.start()
```

マイニングが開始されました。

```
INFO [02-05|09:43:10] IPC endpoint opened: /Users/user1/privateconsortium/node1/geth.ipc 
INFO [02-05|09:43:11] Mapped network port                      proto=udp extport=3000 intport=3000 interface="UPNP IGDv1-PPP1"
INFO [02-05|09:43:11] Mapped network port                      proto=tcp extport=3000 intport=3000 interface="UPNP IGDv1-PPP1"
INFO [02-05|09:43:39] Transaction pool price threshold updated price=18000000000
INFO [02-05|09:43:39] Starting mining operation 
INFO [02-05|09:43:39] Commit new mining work                   number=1 txs=0 uncles=0 elapsed=843.646µs
INFO [02-05|09:43:39] Successfully sealed new block            number=1 hash=a12e9a…da4078
INFO [02-05|09:43:39] 🔨 mined potential block                  number=1 hash=a12e9a…da4078
```

gethコンソールでも確認してみます。

```
> eth.blockNumber
24
```

##5. トランザクションを発生させる

試しに、もう一つアカウントを作って、送金してみます。

```
> personal.newAccount('pass2')
"0x4306ce8dee048055fd16114e407f3a63fda17e05"
> eth.sendTransaction({from:eth.coinbase, to:"0x4306ce8dee048055fd16114e407f3a63fda17e05", value: web3.toWei(5, "ether")})
"0xd9dd3ad56bdbc5a3674f33e8ce99d3710052b6ac080ea07f288a8042db08de47"
> eth.getTransaction("0xd9dd3ad56bdbc5a3674f33e8ce99d3710052b6ac080ea07f288a8042db08de47")
{
  blockHash: "0x642af37393ab9e8394c651b3e5abfc6809b8e46fb8cc9ab91c5fc3409a66968e",
  blockNumber: 59,
  from: "0x0e0933629f2aeba6175b523776c2db1a4a6513bf",
  gas: 90000,
  gasPrice: 18000000000,
  hash: "0xd9dd3ad56bdbc5a3674f33e8ce99d3710052b6ac080ea07f288a8042db08de47",
  input: "0x",
  nonce: 0,
  r: "0xebba3681a9e594930447bff7e950e721b541a62915bf8bf7c317790f8c029e07",
  s: "0x31a35525c1e6d481e8808ee494d169b692858314bbc126c5a797a481daed2c42",
  to: "0x4306ce8dee048055fd16114e407f3a63fda17e05",
  transactionIndex: 0,
  v: "0x287a",
  value: 5000000000000000000
}
> eth.getBalance(eth.accounts[1])
5000000000000000000
```

送金まで確認できました。

##6. まとめ
PoAでEthereumのプライベートネットを構築することができましたが、
[ノードを2つ立てて、2つの署名を必要とする設定をする](https://modalduality.org/posts/puppeth/)と、以下のログで止まってマイニングが進まなかったので、引き続き調査が必要と思われます。

```
INFO [02-05|09:13:59] 🔨 mined potential block                  number=1 hash=6ff65a…59887f
INFO [02-05|09:13:59] Commit new mining work                   number=2 txs=0 uncles=0 elapsed=836.622µs
INFO [02-05|09:13:59] Signed recently, must wait for others 
INFO [02-05|09:27:17] Transaction pool price threshold updated price=18000000000
INFO [02-05|09:27:17] Starting mining operation 
INFO [02-05|09:27:17] Commit new mining work                   number=2 txs=0 uncles=0 elapsed=1.635ms
INFO [02-05|09:27:17] Signed recently, must wait for others 
```

Ethereumで「今」サービスを作ろうとすると、スケーラビリティの問題があるのでPoAでプライベートネット構築も視野に入れた方がよさそうです。
しかし、こういった事象も含めて、ブロックチェーンの黎明期感が半端ないなということを実感して、ワクワクもしてきますよね。
今後の技術的発展に期待して今できることをしましょう！