7
3

More than 5 years have passed since last update.

gethでPoAでノード2つで環境構築

Last updated at Posted at 2019-01-20

概要

ノード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 を確認してみる。

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状態になる
も試したい。

参考

感謝。

7
3
2

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
7
3