概要
ノード2つのプライベートネットワークを構築してみる。コンセンサスアルゴリズムは PoA にしてみる。一般に、ネットワークへ参加するノード数が可変な場合はbootnodeをセットアップするようだが、今回はbootnodeを使わず、ノードを2つに限定し、static-nodes.json で設定とした。
通常はサーバを2台準備してそれぞれにノードをセットアップすると思われるが、今回の目的はセットアップ手順の把握であるため、1つのサーバにノードを2つセットアップしている。
bootnode を使っておらず、--syncmode "full" としており、ノードが1つでも落ちると全マイニングが止まってしまうかも? ノード2つのうち、片方のマイニングを止めると、もう片方のマイニングは止まってしまう。ノード3つの場合は、そのうちの1ノードのマイニングを止めても、他が止まることは無い。2ノード止めると、残りの1ノードもマイニングが止まる。当記事では2ノードで構成しているが、最低3ノードは欲しい。
また、理解不足なところもあるので、追って調べなおしたい。ご指摘等は歓迎します。
環境
- Ubuntu 14.04
- geth 1.8.21-stable
環境構築手順
↓1つ目のノードのdataディレクトリを poa_data1 、2つ目のノードのdataディレクトリを poa_data2 とし、各ノードでアカウントを1つずつ作成する。
$ mkdir ~/poa_data1/
$ mkdir ~/poa_data2/
$ geth account new --datadir poa_data1/
INFO [01-20|06:08:38.163] Maximum peer count ETH=25 LES=0 total=25
Your new account is locked with a password. Please give a password. Do not forget this password.
Passphrase:
Repeat passphrase:
Address: {25440d10657f6e321a0d9e10399b4e83235f7cb0}
$ geth account new --datadir poa_data2/
INFO [01-20|06:08:56.390] Maximum peer count ETH=25 LES=0 total=25
Your new account is locked with a password. Please give a password. Do not forget this password.
Passphrase:
Repeat passphrase:
Address: {bf00b7fbe82cbc89682ed9e01cd487d7dfdd21b4}
$
↑作成したアカウント2つのアドレスが表示される。このアドレスは後で使う。
↓puppeth を使うことで、Genesisファイルを簡単に作れるらしいので、試してみる。
$ puppeth
+-----------------------------------------------------------+
| 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. |
+-----------------------------------------------------------+
Please specify a network name to administer (no spaces, hyphens or capital letters please)
> networkx
↑適当な名前を付ける。スペース、ハイフン、大文字はダメ。
Sweet, you can set this via --network=networkx next time!
INFO [01-20|06:18:01.966] Administering Ethereum network name=networkx
WARN [01-20|06:18:01.966] No previous configurations found path=/home/vagrant/.puppeth/networkx
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
↑新しいgenesis を設定したいので 2 を選ぶ。
What would you like to do? (default = create)
1. Create new genesis from scratch
2. Import already existing genesis
> 1
↑新しく作りたいので 1 を選ぶ。
Which consensus engine to use? (default = clique)
1. Ethash - proof-of-work
2. Clique - proof-of-authority
> 2
↑コンセンサスアルゴリズムは、PoAにしたいので 2 を選ぶ。
How many seconds should blocks take? (default = 15)
> 2
↑ブロックの生成間隔。ここでは 2 秒に設定してみる。2 ではなく 0 とすればトランザクションが存在する時に限り、ブロックが生成されるようになる(空のブロックが生成されなくなる)。
Which accounts are allowed to seal? (mandatory at least one)
> 0x25440d10657f6e321a0d9e10399b4e83235f7cb0
> 0xbf00b7fbe82cbc89682ed9e01cd487d7dfdd21b4
> 0x(Enter)
↑先ほど作成したアドレスを入力する。アドレスは片方ではなく両方を入力しても支障は無いようである。アドレスを入力せずにEnterのみを入力すると次のステップへ進む。
Which accounts should be pre-funded? (advisable at least one)
> 0x25440d10657f6e321a0d9e10399b4e83235f7cb0
> 0xbf00b7fbe82cbc89682ed9e01cd487d7dfdd21b4
> 0x
↑同様に入力。
Should the precompile-addresses (0x1 .. 0xff) be pre-funded with 1 wei? (advisable yes)
> no
↑お勧めは yes らしいが、今回は no とする。yes とすると 0x1から0xffまでのff個のaddress に 1 wei 配られるようである。
Specify your chain/network ID if you want an explicit one (default = random)
> 15
↑network ID を入力する。適当に 15 にしておく。
INFO [01-20|06:21:57.311] Configured new 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
> 2
1. Modify existing fork rules
2. Export genesis configurations
3. Remove genesis configuration
> 2
Which folder to save the genesis specs into? (default = current)
Will create networkx.json, networkx-aleth.json, networkx-harmony.json, networkx-parity.json
> (Enter)
INFO [01-20|06:22:31.791] Saved native genesis chain spec path=networkx.json
ERROR[01-20|06:22:31.791] Failed to create Aleth chain spec err="unsupported consensus engine"
ERROR[01-20|06:22:31.791] Failed to create Parity chain spec err="unsupported consensus engine"
INFO [01-20|06:22:31.791] Saved genesis chain spec client=harmony path=networkx-harmony.json
↑これで、目的の genesisファイルの生成 ができた。Aleth chain spec と Parity chain spec がエラーとなっているが、今回は使わないので問題無い。networkx-harmony.json も今回は使わない。
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
> Ctrl + C
↑また同じものが表示される。Ctrl + C で抜ける。
puppeth で入力した情報は 隠しディレクトリ .puppeth に保存されているようだ。
↓生成された networkx.json を確認してみる。
{
"config": {
"chainId": 15,
"homesteadBlock": 1,
"eip150Block": 2,
"eip150Hash": "0x0000000000000000000000000000000000000000000000000000000000000000",
"eip155Block": 3,
"eip158Block": 3,
"byzantiumBlock": 4,
"constantinopleBlock": 5,
"clique": {
"period": 2,
"epoch": 30000
}
},
"nonce": "0x0",
"timestamp": "0x5c4412ca",
"extraData": "0x000000000000000000000000000000000000000000000000000000000000000025440d10657f6e321a0d9e10399b4e83235f7cb0bf00b7fbe82cbc89682ed9e01cd487d7dfdd21b40000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
"gasLimit": "0x47b760",
"difficulty": "0x1",
"mixHash": "0x0000000000000000000000000000000000000000000000000000000000000000",
"coinbase": "0x0000000000000000000000000000000000000000",
"alloc": {
"25440d10657f6e321a0d9e10399b4e83235f7cb0": {
"balance": "0x200000000000000000000000000000000000000000000000000000000000000"
},
"bf00b7fbe82cbc89682ed9e01cd487d7dfdd21b4": {
"balance": "0x200000000000000000000000000000000000000000000000000000000000000"
}
},
"number": "0x0",
"gasUsed": "0x0",
"parentHash": "0x0000000000000000000000000000000000000000000000000000000000000000"
}
↑片方のノードには alloc に指定されている片方のアドレスしか存在しないが、存在しない方のアドレスは無視されるようで、この後、特にエラーが発生するようなことも無い。
↓生成した networkx.json を使って初期化する。
$ geth --datadir poa_data1/ init networkx.json
$ geth --datadir poa_data2/ init networkx.json
↓ノードを1つ起動する。
$ geth --datadir poa_data1 --nodiscover --port 30001 --networkid 15
↓もう1つのノードを起動する。サーバ1台に2ノード動かしているので、poa_data1 とは異なるポートとしている。
(Windowsから操作している場合、もう1つTeraTermを起動)
$ geth --datadir poa_data2 --nodiscover --port 30002 --networkid 15
↓gethにIPCで接続し(gethコンソール)、enodeを確認する。確認した値を後で使う。
(Windowsから操作している場合、もう1つTeraTermを起動)
$ geth attach ipc:poa_data1/geth.ipc
> eth.getBalance(eth.accounts[0])
9.04625697166532776746648320380374280103671755200316906558262375061821325312e+74
> admin.nodeInfo.enode
"enode://cd7b3f3525d036d8c088176a695a355bb65136e1142290255f7d8b43a0366c899dc9765c3d83bb89e911d992be0db1440f5cc32ad62d6f8c006b094aeb04c115@127.0.0.1:30001?discport=0"
>
↓もう1つのノードも同様に enode を確認する。
(Windowsから操作している場合、もう1つTeraTermを起動)
$ geth attach ipc:poa_data2/geth.ipc
> eth.getBalance(eth.accounts[0])
9.04625697166532776746648320380374280103671755200316906558262375061821325312e+74
> admin.nodeInfo.enode
"enode://1ec0c192374a22d8ebaab70b2f21e8b75c2af667c4f9d9c57e553deaf45bfa5e7387e1da4f1cbff96d955dafa2957c5f0865d4dee1cdfd291a01e0ac8ab14cf8@127.0.0.1:30002?discport=0"
>
↓ノードから別ノードへの接続の設定を行う。poa_data1 には poa_data2 の enodeを入力する。
自身のenodeも入力してしまうと、WARN「Removing static dial candidate id=0x9b2c70 addr=127.0.0.1:30001 err="is self"」が出力されてしまうので今回は含めていない(含めても支障はないのかも?)。
(Windowsから操作している場合、もう1つTeraTermを起動)
$ vi poa_data1/static-nodes.json
[
"enode://1ec0c192374a22d8ebaab70b2f21e8b75c2af667c4f9d9c57e553deaf45bfa5e7387e1da4f1cbff96d955dafa2957c5f0865d4dee1cdfd291a01e0ac8ab14cf8@127.0.0.1:30002?discport=0"
]
↓同様に、poa_data2 には poa_data1 の enodeを入力する。
(Windowsから操作している場合、もう1つTeraTermを起動)
$ vi poa_data2/static-nodes.json
[
"enode://cd7b3f3525d036d8c088176a695a355bb65136e1142290255f7d8b43a0366c899dc9765c3d83bb89e911d992be0db1440f5cc32ad62d6f8c006b094aeb04c115@127.0.0.1:30001?discport=0"
]
↓各gethをCtrl+C で停止して、起動しなおす。--syncmode "full" を付けること。--syncmode を付けないと、マイニングした時に1ブロック作成した後、警告が表示され、マイニングが進まなくなる様子だった。
Clique : Discarded bad propagated block#1 when syncing #14945
geth --datadir poa_data1 --nodiscover --port 30001 --syncmode "full" --networkid 15
↓もう1つのノードも同様に再起動。
geth --datadir poa_data2 --nodiscover --port 30002 --syncmode "full" --networkid 15
↓各gethコンソールも Ctrl + D で抜けて、入りなおす。設定が反映されているか確認する。
$ geth attach ipc:poa_data1/geth.ipc
> admin.peers
[{
caps: ["eth/63"],
enode: "enode://1ec0c192374a22d8ebaab70b2f21e8b75c2af667c4f9d9c57e553deaf45bfa5e7387e1da4f1cbff96d955dafa2957c5f0865d4dee1cdfd291a01e0ac8ab14cf8@127.0.0.1:45533",
id: "211d55cc935b3e14c40e3073c4fcf3f12e48103b17bdc1e2533a71a049fade52",
name: "Geth/v1.8.21-stable-9dc5d1a9/linux-amd64/go1.10.4",
network: {
inbound: true,
localAddress: "127.0.0.1:30001",
remoteAddress: "127.0.0.1:45533",
static: false,
trusted: false
},
protocols: {
eth: {
difficulty: 1,
head: "0x046367f44f2636b856c2e2d1137ac471c854bef2ed89690ce31e476dc329618d",
version: 63
}
}
}]
>
↓同様にもう1つのノードも確認。
$ geth attach ipc:poa_data2/geth.ipc
> admin.peers
[{
caps: ["eth/63"],
enode: "enode://cd7b3f3525d036d8c088176a695a355bb65136e1142290255f7d8b43a0366c899dc9765c3d83bb89e911d992be0db1440f5cc32ad62d6f8c006b094aeb04c115@127.0.0.1:30001?discport=0",
id: "644b181ec5e93656f601d4478a5d8d1ca538832ab411d7659df4e069519b6e6a",
name: "Geth/v1.8.21-stable-9dc5d1a9/linux-amd64/go1.10.4",
network: {
inbound: false,
localAddress: "127.0.0.1:45533",
remoteAddress: "127.0.0.1:30001",
static: true,
trusted: false
},
protocols: {
eth: {
difficulty: 1,
head: "0x046367f44f2636b856c2e2d1137ac471c854bef2ed89690ce31e476dc329618d",
version: 63
}
}
}]
>
↓両方のノードで下記を行い、マイニングを開始する。personal.unlockAccount(eth.accounts[0], "パスワード", 60) だと、60秒後にマイニングが停止してしまうので注意。
> personal.unlockAccount(eth.accounts[0], "上記でアカウント作成時に入力したパスワード", 0)
true
> miner.start()
null
>
2つのノードでマイニングのログが出力され続ける。
動作確認
↓poa_data1のgethコンソールで、送金先のアカウントを作って、送金してみる。
> personal.newAccount()
Passphrase:
Repeat passphrase:
"0xb4d5e9684ba006b84e8459d07b9c76a4c3bcf5fc"
> eth.getBalance(eth.accounts[1])
0
> eth.sendTransaction({from: eth.accounts[0], to: eth.accounts[1], value: 10})
"0x919dc9ac565ec607bf163e5917612b82d092feda4e988818d7b4ecf1bdda839d"
> eth.getBalance(eth.accounts[1])
10
↓同期されているかを確認したい。poa_data2のgethコンソールで確認。
> eth.getBalance("0xb4d5e9684ba006b84e8459d07b9c76a4c3bcf5fc")
10
> eth.getTransaction("0x919dc9ac565ec607bf163e5917612b82d092feda4e988818d7b4ecf1bdda839d")
{
blockHash: "0x9a1acc0d3b53d6105adbd2333a9b44a73e276facfd53070e7e291e0c95e7b8f3",
blockNumber: 1,
from: "0xea2d56c51d100a87d7942516a80bf0cadb6b9fc8",
gas: 90000,
gasPrice: 1000000000,
hash: "0x919dc9ac565ec607bf163e5917612b82d092feda4e988818d7b4ecf1bdda839d",
input: "0x",
nonce: 0,
r: "0x9c577bceb82a5455accddc5b84c1bccaf00e40d1a699ce92b9da9a49e82c6cd6",
s: "0x3e6d80a778bfa6c47af878f707d889c41f493fced2fe9b54ddc9418a72efe26b",
to: "0xb4d5e9684ba006b84e8459d07b9c76a4c3bcf5fc",
transactionIndex: 0,
v: "0x1c",
value: 10
}
>
問題無く、同期されている様子ですね。
今回試していないこと
@fukumame55 氏の
Ethereumのプライベートチェーンでトランザクションが発生した時のみ、マイニングを実施する方法
も試したい。
@yuksekig 氏の
PoAのプライベートチェーンネットワークに後からsignerノードを追加する方法(geth) と
gethでPoAでプライベートチェーンを構築している場合、ブロック生成間隔を0にすれば自ずとAUTOMINING状態になる
も試したい。
参考
感謝。
- Clique : Discarded bad propagated block#1 when syncing #14945
- @shiki_tak - EthereumのプライベートネットをPoAで構築する
- @fukumame55 - EthereumのPoA(Proof of Authority)ネットワークを複数のノードで構築
- ブロックチェーンEthereum入門 2
- Geth(Go Ethereum)でプライベートネットワーク用のbootnodeをセットアップする
- Using puppeth To Manually Create An Ethereum Proof Of Authority (Clique) Network On AWS
- How to use static-nodes.json / trusted-nodes.json to prevent connection loss on private network?
- Not able to start miner on Ethereum POA - Block sealing failed
- Block sealing failed, when consensus engine is configed to clique. #15282