(動かない)構成
- 各自のPCでSwarmクラスターを構成
- attachableなOverlayネットワークを1つ作成
- Ethereumクライアントは公式イメージ(ethereum/client-go)を使用
- 各自のPCでEthereumコンテナ起動(上記Overlayネットワーク指定)
- P2P接続する(手動)
プライベートチェーン用ネットワークの作成
※以下のSwarm設定動きません
Swarmの初期化
- Swarmの初期化をしたホストが最初の
manager
ノードになる - この時点で指定した2377ポートlistenしてない
docker swarm init --advertise-addr '192.168.x.x'
-
--listen-addr
指定したときエラーが出てる時点でもうなんかダメっぽい
docker swarm init --listen-addr '192.168.x.x'
Error response from daemon: manager stopped: failed to listen on remote API address: listen tcp 192.168.x.x:2377: bind: cannot assign requested address
- ファイヤーウォールはオフ
- 8545ポートのJSON-RPC呼ぶだけなら通る
Swarmのクラスターに参加
-
worker
ノードとして参加する - トークンは
manager
にもらう - ここまででSwarmクラスターは完成(しない)
-
connection refused
で繋がらない
docker swarm join --token SW...5j 192.168.x.x:2377
Overlayネットワークの作成
- 全コンテナがこのネットワークに参加する
- コンテナ起動時にこの
private-chain
ネットワークを指定する
docker network create -d overlay --attachable private-chain
Ethereumノードを建てる
データディレクトリの作成
- 各人の環境に合わせて好きな場所に作成
- ブロックチェーンのDB(data/ethereum/)とマイニング用のDAG(data/ethash/)を保存する
- コンテナ起動時にフルパスでボリューム指定する
mkdir -p /Users/$USER/data
genesis.jsonの作成
- ジェネシスブロック(最初のブロック)作成用のファイル
- Ethereumの初期化時に使用する
- 上記工程で作った
data
ディレクトリ直下にgenesis.json
というファイル名で配置
{
"config": {
"chainId": 10101,
"homesteadBlock": 0,
"eip155Block": 0,
"eip158Block": 0
},
"alloc" : {},
"coinbase" : "0x0000000000000000000000000000000000000000",
"difficulty" : "0x20000",
"extraData" : "",
"gasLimit" : "0x2fefd8",
"nonce" : "0x00000000000000de",
"mixhash" : "0x0000000000000000000000000000000000000000000000000000000000000000",
"parentHash" : "0x0000000000000000000000000000000000000000000000000000000000000000",
"timestamp" : "0x00"
}
イメージ取得
- 公式イメージを取得
- 何も指定せず起動すると、Ethereumメインネット(本番環境)と同期が始まってしまうので、まだ起動しない
docker pull ethereum/client-go
コンテナの起動
-
ENTRYPOINT
を/bin/sh
に書き換えて起動 -
-v
には上記工程で作成したdata
ディレクトリを指定 - ローカルの
bridge
ネットワーク内で起動する場合--network
指定なし
docker run -dit --name eth1 --entrypoint /bin/sh -v /Users/$USER/data:/root/data -p 8545:8545 -p 30303:30303 ethereum/client-go
- 上記工程で作成したOverlayネットワーク内で起動する場合
docker run -dit --name eth1 --entrypoint /bin/sh --network private-chain -p 8545:8545 -v /Users/$USER/data:/root/data ethereum/client-go
ジェネシスブロックの作成
-
attach
でコンテナ名を指定してに接続 - detachするには
Ctrl+p
→Ctrl+q
-
Ctrl-d
やexit
するとコンテナが終了してしまうので注意
docker attach eth1
-
genesis.json
を指定してジェネシス・ブロックを生成
geth --datadir /root/data/ethereum init /root/data/genesis.json
アカウントの作成
- ウォレットに最初のアカウントを追加
- このアカウントにマイニング報酬が送金される
geth --datadir /root/data/ethereum account new
Passphrase:
Repeat passphrase:
Address: {1a...d5}
Ethereumノードの起動
-
geth
を起動してREPL環境を表示 -
--miner.etherbase
には上記工程で作成したアカウントアドレスを指定 -
--allow-insecure-unlock
を付けないとpersonal.unlockAccount
出来なくなってたので付ける
geth --networkid 10101 --datadir /root/data/ethereum --ethash.dagdir /root/data/ethash --miner.etherbase 1a...d5 --nodiscover --allow-insecure-unlock --rpc --rpcaddr '0.0.0.0' console
- docker起動時にgethを起動する場合は全てのオプションを1行にまとめてコンテナ起動してもいい
docker run -dit --name eth -v /Users/$USER/data:/root/data -p 8545:8545 -p 30303:30303 ethereum/client-go --networkid 10101 --datadir /root/data/ethereum --ethash.dagdir /root/data/ethash --miner.etherbase 1a...d5 --nodiscover --allow-insecure-unlock --rpc --rpcaddr '0.0.0.0' console
↓上記コマンドを見やすく整形したもの
docker run -dit \
--name eth \
-v /Users/$USER/data:/root/data \
-p 8545:8545 \
-p 30303:30303 \
ethereum/client-go --networkid 10101 \
--datadir /root/data/ethereum \
--ethash.dagdir /root/data/ethash \
--miner.etherbase 1a...d5 \
--nodiscover \
--allow-insecure-unlock \
--rpc --rpcaddr '0.0.0.0' \
console
- Ethereumで使われているポート
- 8545: JSON-RPC
- 8546: WebSocket
- 8547: GraphQL
- 30303/tcp: P2P用
- 30303/udp: P2Pオートディスカバリ用
EthereumのJSコンソール
web3.js
- web3.js v0.x系のAPIが使える
> eth.blockNumber
0
P2Pネットワークの形成
他ノードへの接続
-
--nodiscover
フラグを指定してるので手動で接続する必要がある - 接続していないことを確認
> admin.peers
[]
> net.peerCount
0
- consoleに入ったら
enode
情報を取得
> admin.nodeInfo.enode
"enode://15...1e@127.0.0.1:30303?discport=0"
-
enode
内のIPアドレスをコンテナのIPアドレスに変更して接続
> admin.addPeer('enode://15...1e@10.x.x.x:30303?discport=0')
true
- やっぱり接続していないことを確認
- ピア情報がでてくる予定だった
> admin.peers
[]
> net.peerCount
0
操作
マイニング
- 初回はDAGの生成に5分ほどかかる
> eth.mining
false
> miner.start(1)
INFO [04-03|15:41:46.204] Updated mining threads threads=1
INFO [04-03|15:41:46.204] Transaction pool price threshold updated price=1000000000
INFO [04-03|15:41:46.205] Commit new mining work number=1 sealhash=caeddc…34d5e1 uncles=0 txs=0 gas=0 fees=0 elapsed=322.5µs
INFO [04-03|15:41:50.540] Generating DAG in progress epoch=0 percentage=0 elapsed=3.556s
INFO [04-03|15:41:54.010] Generating DAG in progress epoch=0 percentage=1 elapsed=7.025s
INFO [04-03|15:41:57.472] Generating DAG in progress epoch=0 percentage=2 elapsed=10.488s
:
INFO [04-03|15:47:38.808] Generating DAG in progress epoch=0 percentage=98 elapsed=5m52.229s
INFO [04-03|15:47:42.314] Generating DAG in progress epoch=0 percentage=99 elapsed=5m55.735s
INFO [04-03|15:47:42.326] Generated ethash verification cache epoch=0 elapsed=5m55.747s
INFO [04-03|15:47:47.763] Successfully sealed new block number=1 sealhash=caeddc…34d5e1 hash=49ceef…74d8f4 elapsed=6m1.963s
INFO [04-03|15:47:47.765] 🔨 mined potential block number=1 hash=49ceef…74d8f4
> eth.mining
true
- マイナーを止めてマイニング停止
- DAGの生成が止まらないが、いずれそれも止まるので動揺しない
> miner.stop()
アカウントの確認
> eth.accounts
["0x12af8fce5685c5e6f25da9dd8ef4da100cc9c0b8"]
> eth.accounts[0]
"0x12af8fce5685c5e6f25da9dd8ef4da100cc9c0b8"
残高の確認
- 100京wei = 1ether
> eth.getBalance(eth.accounts[0])
15
> web3.fromWei(eth.getBalance(eth.accounts[0]),'ether')
15
アカウントのアンロック
- 第3引数を
0
にするとプロセス起動中ずっとアンロック -
--allow-insecure-unlock
を付けないとエラーになるので注意
> personal.unlockAccount(eth.accounts[0],null,0)
Unlock account 0x12af8fce5685c5e6f25da9dd8ef4da100cc9c0b8
Passphrase:
true
トランザクションの送信
- いったんマイナーを止めとく
- トランザクションの送信には手数料(ETH)が必要
> bn = eth.blockNumber
13
> eth.sendTransaction({from:eth.accounts[0],to:eth.accounts[0],value:web3.toWei('1','ether')})
"0x0a...87"
トランザクションプール
> txpool.status
{
pending: 1,
queued: 0
}
> txpool.content
{
pending: {
0x12AF8FCE5685C5e6F25DA9dd8eF4Da100CC9c0B8: {
2: {
blockHash: "0x0000000000000000000000000000000000000000000000000000000000000000",
blockNumber: null,
from: "0x12af8fce5685c5e6f25da9dd8ef4da100cc9c0b8",
gas: "0x15f90",
gasPrice: "0x3b9aca00",
hash: "0x52bea06df31909b95fd201c098d4d4cc727de5bda9595370edfa9966a76d3d70",
input: "0x",
nonce: "0x2",
r: "0xc0dc7663149fba52e9a4ab357c8b37cfb051794187dfc9cd1f021b318077fa5a",
s: "0x441004d231de0e425bdfdbe961a07fdcedce38b347f3b79809394299f2988b6",
to: "0x12af8fce5685c5e6f25da9dd8ef4da100cc9c0b8",
transactionIndex: "0x0",
v: "0x4f0e",
value: "0xde0b6b3a7640000"
}
}
},
queued: {}
}
> txpool.inspect
{
pending: {
0x12AF8FCE5685C5e6F25DA9dd8eF4Da100CC9c0B8: {
2: "0x12AF8FCE5685C5e6F25DA9dd8eF4Da100CC9c0B8: 1000000000000000000 wei + 90000 gas × 1000000000 wei"
}
},
queued: {}
}
ブロックの確認
- マイニングを開始すると上記保留されてたトランザクションがブロックに取り込まれる
-
txpool
を確認すると空になってるはず
> eth.getBlock(bn+1)
{
difficulty: 131072,
extraData: "0xd8...78",
gasLimit: 3181688,
gasUsed: 21000,
hash: "0x5e...c3",
logsBloom: "0x00...00",
miner: "0x12...b8",
mixHash: "0x8a7c653952bf27288666a31263923d037dda944f4ce41260a4474e0df0d54e6b",
nonce: "0x3bdf8017b06618ae",
number: 13,
parentHash: "0x0e31202579fa2c97bb9546e261bf037821bd9c75a935e1a64c0b648b959e08ab",
receiptsRoot: "0x4287c2ed8bce2ced130f5c319d2cde9bc0fceefc273de7406b7112c68175d049",
sha3Uncles: "0x1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347",
size: 651,
stateRoot: "0x2eb370e6cc431ede290354bcb0b0abec74f16bacb2903703459c0f3e02d9a675",
timestamp: 1554883148,
totalDifficulty: 1838016,
transactions: ["0x170250400e5f087b90a235023f2460e9031bac12ad2683663fea2111711fb5a2"],
transactionsRoot: "0x2df21628faf3e362cd5bec2c90ad6a5d0bca59c3b75bc2e2f51a832806b4d09b",
uncles: []
}
トランザクションの確認
> eth.getTransaction(eth.getBlock(bn+1).transactions[0])
{
blockHash: "0x5ec8f2c51e7e2460a7def8cca57dbbf833d39f651f4b40168c9a4b92a149c5c3",
blockNumber: 13,
from: "0x12af8fce5685c5e6f25da9dd8ef4da100cc9c0b8",
gas: 90000,
gasPrice: 1000000000,
hash: "0x170250400e5f087b90a235023f2460e9031bac12ad2683663fea2111711fb5a2",
input: "0x",
nonce: 1,
r: "0xffd2eb20323e2fa0576fcad9c9fd3a5650f8e388e40d9b56a2e0765c1fc31f41",
s: "0x792e01ad9da9663f020c679db8c8e8afbd04d6e4260687b64d1f9e7519cd3d4c",
to: "0x12af8fce5685c5e6f25da9dd8ef4da100cc9c0b8",
transactionIndex: 0,
v: "0x4f0d",
value: 1000000000000000000
}