前置条件
安装好 docker-compose docker.io jq pwgen
pwgen 64 1 来生成后面所需密钥
创建所需文件
#创建目录,存储文件
mkdir privateChain
cd privateChain
#创建存储节点数据和创世文件的目录(根据需要来创建节点数目)
mkdir node_1 node_2 genesis
#创建节点的子目录来存储节点的配置文件
mkdir node_1/configs node_2/configs
下载创世文件
#根据需要修改goerli.json中的networkID
wget https://raw.githubusercontent.com/NethermindEth/nethermind/09389fc28b37605acc5eaed764d3e973969fe319/src/Nethermind/Chains/goerli.json
cp goerli.json genesis/goerli.json
生成静态文件
在当前目录创建static-nodes.json
cat <<EOF > static-nodes.json
[
]
EOF
创建 config.cfg 文件
创建 config.cfg 文件并将其放置在 node_1/configs 子文件夹中(对 node_2 也执行此操作,但LocalIp, ExternalIp and Host需改变)
pwgen 64 1来生成不同TestNodeKey
cat <<EOF > node_1/configs/config.cfg
{
"Init": {
"WebSocketsEnabled": false,
"StoreReceipts" : true,
"EnableUnsecuredDevWallet": true,
"IsMining": true,
"ChainSpecPath": "/config/genesis/goerli.json",
"BaseDbPath": "nethermind_db/clique",
"LogFileName": "clique.logs.txt",
"StaticNodesPath": "Data/static-nodes.json"
},
"Network": {
"DiscoveryPort": 30300,
"P2PPort": 30300,
"LocalIp": "10.5.0.2",
"ExternalIp": "10.5.0.2"
},
"JsonRpc": {
"Enabled": true,
"Host": "10.5.0.2",
"Port": 8545
},
"KeyStoreConfig": {
"TestNodeKey": "8687A55019CCA647F6C063F530D47E9A90725D62D853F4B973E589DB24CA9305"
}
}
EOF
创建docker-compose 文件
单节点
cat <<EOF > docker-compose.yml
version: "3.5"
services:
node_1:
image: nethermind/nethermind:1.10.17
command: --config config
container_name: node_1
volumes:
- ./genesis:/config/genesis
- ./node_1/configs/config.cfg:/nethermind/configs/config.cfg
- ./static-nodes.json:/nethermind/Data/static-nodes.json
- ./node_1/db/clique:/nethermind/nethermind_db/clique
- ./node_1/keystore:/nethermind/keystore
ports:
- 0.0.0.0:8547:8545
networks:
vpcbr:
ipv4_address: 10.5.0.2
networks:
vpcbr:
driver: bridge
ipam:
config:
- subnet: 192.168.0.0/24
EOF
双节点(多节点类似)
cat <<EOF > docker-compose.yml
version: "3.5"
services:
node_1:
image: nethermind/nethermind:1.10.17
command: --config config
container_name: node_1
volumes:
- ./genesis:/config/genesis
- ./node_1/configs/config.cfg:/nethermind/configs/config.cfg
- ./static-nodes.json:/nethermind/Data/static-nodes.json
- ./node_1/db/clique:/nethermind/nethermind_db/clique
- ./node_1/keystore:/nethermind/keystore
ports:
- 0.0.0.0:8547:8545
networks:
vpcbr:
ipv4_address: 10.5.0.2
node_2:
image: nethermind/nethermind:1.10.17
command: --config config
container_name: node_2
volumes:
- ./genesis:/config/genesis
- ./node_2/configs/config.cfg:/nethermind/configs/config.cfg
- ./static-nodes.json:/nethermind/Data/static-nodes.json
- ./node_2/db/clique:/nethermind/nethermind_db/clique
- ./node_2/keystore:/nethermind/keystore
ports:
- 0.0.0.0:8548:8545
networks:
vpcbr:
ipv4_address: 10.5.0.3
networks:
vpcbr:
driver: bridge
ipam:
config:
- subnet: 10.5.0.0/16
EOF
启动节点
分别运行每个节点,以便我们可以复制并保存每个节点的Enode和Node地址
docker-compose run node_1
或者
docker-compose up
记录的Enode和Node地址格式,将下面命令复制到终端中
SIGNER_1="74b21f51f4822f76ecff4070e7871e2b40406514"
STATIC_NODE_1="enode://1dc1b054dc77261a6ecff3d3e012dc96e2f2bd14c80d38092f39acd7f5d6c1597b75fbdc2a1442d519494b2ac9957dbc3a4df10602735a553d64b4170924169f@192.168.0.2:30303"
SIGNER_2="18306a376470013050d5eabfa8550abaa18ab9fa"
STATIC_NODE_2="enode://0036fbf892353e6161467cc27ca9592183260dac8b1d3a31da5473f5cdf3670d25114fef0b305723b9fda7ac1ae10855ae92eb7c175d0d36b7d35bdfcf7359ba@192.168.0.4:30303"
并且在终端中并创建 EXTRA_VANITY 和 EXTRA_SEAL 变量
EXTRA_VANITY="0x22466c6578692069732061207468696e6722202d204166726900000000000000"
EXTRA_SEAL="0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000"
创建 EXTRA_DATA 变量
EXTRA_DATA=${EXTRA_VANITY}${SIGNER_1}${SIGNER_2}${EXTRA_SEAL}
在 goerli.json 文件中,修改 genesis 字段中的 extraData 属性
cat goerli.json | jq '.genesis.extraData = '\"$EXTRA_DATA\"'' > genesis/goerli.json
向static-nodes.json添加各节点的Enodes
cat <<EOF > static-nodes.json
[
"$STATIC_NODE_1",
"$STATIC_NODE_2"
]
EOF
清除节点的数据,以便准备重新启动节点时使用
sudo rm -rf node_1/db/clique node_2/db/clique
重新启动节点
docker-compose up