继续浏览精彩内容
慕课网APP
程序员的梦工厂
打开
继续
感谢您的支持,我会继续努力的
赞赏金额会直接到老师账户
将二维码发送给自己后长按识别
微信支付
支付宝支付

美图DPOS以太坊节点网络启动和测试(Docker版)

慕尼黑的夜晚无繁华
关注TA
已关注
手记 370
粉丝 60
获赞 318

节点网络启动

1、简单测试起见,修改maxValidator为最小数
consensus/dpos/dpos.go

maxValidatorSize = 3

2、构建美图以太坊docker镜像

cd $GOPATH/src/github.com/meitu/go-ethereum docker build . -t meitugeth

3、建立节点数据目录

mkdir meitu cd meitu mkdir node1 mkdir node2 mkdir node3

4、编写docker-compose.yml启动文件

version: '3.3' services:   node1:     image: meitugeth     command: --ipcpath "/root/.ethereum/geth.ipc" --port 30303     ports:       - "15450:8545"       - "15460:8546"       - "10303:30303"       - "10303:30303/udp"       - "10304:30304/udp"     volumes:       - /etc/localtime:/etc/localtime       - ./node1/:/root/.ethereum/     environment:       - TZ=Asia/Shanghai   node2:     image: meitugeth     command: --ipcpath "/root/.ethereum/geth.ipc" --port 30303     ports:       - "25450:8545"       - "25460:8546"       - "20303:30303"       - "20303:30303/udp"       - "20304:30304/udp"     volumes:       - /etc/localtime:/etc/localtime       - ./node2/:/root/.ethereum/     environment:       - TZ=Asia/Shanghai   node3:     image: meitugeth     command: --ipcpath "/root/.ethereum/geth.ipc" --port 30303     ports:       - "35450:8545"       - "35460:8546"       - "40303:30303"       - "40303:30303/udp"       - "40304:30304/udp"     volumes:       - /etc/localtime:/etc/localtime       - ./node3/:/root/.ethereum/     environment:       - TZ=Asia/Shanghai

5、在meitu目录下启动3个以太坊节点

docker-compose up -d

启动网络的思路1:
在创世块里配置好第一批验证节点,然后启动。
启动网络的思路2:
混合POW和DPOS,用POW进行投票,产生第一批验证节点,并自动切换到DPOS。

这里显然采用思路1.

6、进入node1容器

docker exec -it $container_node1_id /bin/sh

7、获取geth JavaScript控制台

geth attach ipc:/root/.ethereum/geth.ipc

8、在node1节点建立coinbase

personal.newAccount('xxxx') "0x8807fa0db2c60675a8f833dd010469e408428b83"

记录下上述地址。

9、退出node1容器或者打开新窗口进入node2、node3

loop:重复6-9步骤,在node2和node3上分别设立coinbase。

3个节点的地址分别为:

0x8807fa0db2c60675a8f833dd010469e408428b83 0xdf5f5a7abc5d0821c50deb4368528d8691f18737 0xe0d64bfb1a30d66ae0f06ce36d5f4edf6835cd7c

10、写创世块配置文件,把3个节点地址列入第一批验证人列表。
meitu_genesis.json

{     "config": {         "chainId": 8888,         "eip155Block": 0,         "eip158Block": 0,         "byzantiumBlock":0,         "dpos":{             "validators":[                 "0x8807fa0db2c60675a8f833dd010469e408428b83",                 "0xdf5f5a7abc5d0821c50deb4368528d8691f18737",                 "0xe0d64bfb1a30d66ae0f06ce36d5f4edf6835cd7c"             ]         }     },     "nonce": "0x0000000000000042",     "difficulty": "0x020000",     "mixHash": "0x0000000000000000000000000000000000000000000000000000000000000000",     "coinbase": "0x0000000000000000000000000000000000000000",     "timestamp": "0x00",     "parentHash": "0x0000000000000000000000000000000000000000000000000000000000000000",     "extraData": "0x11bbe8db4e347b4e8c937c1c8370e4b5ed33adb3db69cbdb7a38e1e50b1b82fa",     "gasLimit": "0x500000",     "alloc": {} }

11、删除每个节点下个geth目录,保留keystore目录,并用创始配置重新init datadir。

rm -rf node1/geth rm -rf node2/geth rm -rf node3/geth

将创始配置分别拷贝入数据目录下,以便在容器内能访问到。

cp meitu_genesis.json node1  cp meitu_genesis.json node2 cp meitu_genesis.json node3

像第6步一样,进入node1之后,执行init

geth init /root/.ethereum/meitu_genesis.json

loop:重复在node2和node3上分别执行init。

12、重启节点网络

docker-compose down docker-conpose up -d

13、随便进入某个节点,查看验证人是否设置成功。

dpos.getValidators() ["0x8807fa0db2c60675a8f833dd010469e408428b83", "0xdf5f5a7abc5d0821c50deb4368528d8691f18737", "0xe0d64bfb1a30d66ae0f06ce36d5f4edf6835cd7c"]

14、查看节点是否互联

admin.peers []

为空,说明节点之间没有互相发现。

15、让节点互联

查看每个节点信息

admin.nodeInfo

确认:enode都不一样,protocols都一样。

记下三个enode

"enode://97caa3fe607663197d8741be1f26a1e53fc936cdef7187cdec737495fa01ae501d95a659bdf48e7d8505a8fc1dacfb715b17775ba86f1575a46d8cffa1f6b509@[::]:30303" "enode://15bc1789ff8b5108a1e47cf257bae7928d5bfc1eb44c5d61c8dad86f7ac6b985c82dc32e3ffcdf06bd142f4a19183d89c51e4a5fdd1c5447e7172f2e5aadb428@[::]:30303" "enode://0031048c457163671377bd197d05a78b1c11d474705b29b1b2473b37356d0a4fdf96563fcbda1d6cdf21a6e30f3082935276c4538a82b14da1d660b04ef99213@[::]:30303"

查看docker容器网络信息

docker network inspect meitu_default "Containers": {             "0cd2b0fd97fd53650767302162038878d95b7f39dce48a3db7181d12d3ee673f": {                 "Name": "meitu_node2_1",                 "EndpointID": "2fc2b79fb840ba3a2deae61ef4cef8e944684e5259ff88f43283f3a206b3bb90",                 "MacAddress": "02:42:ac:15:00:03",                 "IPv4Address": "172.21.0.3/16",                 "IPv6Address": ""             },             "73c6bafac7173b737495df70d091ea7c1a966826edd79e08c20cd3f0f19ce479": {                 "Name": "meitu_node3_1",                 "EndpointID": "e16177540cb80ae1f731008e1975135119a12ddaf626f07a160d55e3c2d5b0ba",                 "MacAddress": "02:42:ac:15:00:04",                 "IPv4Address": "172.21.0.4/16",                 "IPv6Address": ""             },             "a67590ead292ed4d905eb868c6d8c6049b7796be8dd6464f20f96a019749560b": {                 "Name": "meitu_node1_1",                 "EndpointID": "a852916334db8149e43ffcc51176589bf4a379cff7efe48a44eb207e7883d448",                 "MacAddress": "02:42:ac:15:00:02",                 "IPv4Address": "172.21.0.2/16",                 "IPv6Address": ""             }         },

记录下每个节点的ip,也可以用127.0.0.1加节点映射到本机的不同网络端口。

在节点1容器内执行

admin.addPeer("enode://15bc1789ff8b5108a1e47cf257bae7928d5bfc1eb44c5d61c8dad86f7ac6b985c82dc32e3ffcdf06bd142f4a19183d89c51e4a5fdd1c5447e7172f2e5aadb428@[172.21.0.3]:30303") admin.addPeer("enode://0031048c457163671377bd197d05a78b1c11d474705b29b1b2473b37356d0a4fdf96563fcbda1d6cdf21a6e30f3082935276c4538a82b14da1d660b04ef99213@[172.21.0.4]:30303")

再看节点网络

admin.peers [{     caps: ["eth/62", "eth/63"],     id: "0031048c457163671377bd197d05a78b1c11d474705b29b1b2473b37356d0a4fdf96563fcbda1d6cdf21a6e30f3082935276c4538a82b14da1d660b04ef99213",     name: "Geth/v1.7.4-stable-6be4cd4b/linux-amd64/go1.9.7",     network: {       localAddress: "172.21.0.2:48258",       remoteAddress: "172.21.0.4:30303"     },     protocols: {       eth: {         difficulty: 131072,         head: "0x19d4e0c4422cfe81c35cb9420127a6dc590c3e6b09ca835c840d53a601ed1d32",         version: 63       }     } }, {     caps: ["eth/62", "eth/63"],     id: "15bc1789ff8b5108a1e47cf257bae7928d5bfc1eb44c5d61c8dad86f7ac6b985c82dc32e3ffcdf06bd142f4a19183d89c51e4a5fdd1c5447e7172f2e5aadb428",     name: "Geth/v1.7.4-stable-6be4cd4b/linux-amd64/go1.9.7",     network: {       localAddress: "172.21.0.2:49844",       remoteAddress: "172.21.0.3:30303"     },     protocols: {       eth: {         difficulty: 131072,         head: "0x19d4e0c4422cfe81c35cb9420127a6dc590c3e6b09ca835c840d53a601ed1d32",         version: 63       }     } }]

注意,第15步的互联方式是临时性的,每次重启docker之后admin.peers会重新为空。

为方便互联,可以将bootnodes配置到启动文件里。

version: '3.3' services:   node1:     image: meitugeth     command: --ipcpath "/root/.ethereum/geth.ipc" --port 30303     ports:       - "15450:8545"       - "15460:8546"       - "10303:30303"       - "10303:30303/udp"       - "10304:30304/udp"     volumes:       - /etc/localtime:/etc/localtime       - ./node1/:/root/.ethereum/     environment:       - TZ=Asia/Shanghai   node2:     image: meitugeth     command: --ipcpath "/root/.ethereum/geth.ipc" --port 30303 --bootnodes enode://97caa3fe607663197d8741be1f26a1e53fc936cdef7187cdec737495fa01ae501d95a659bdf48e7d8505a8fc1dacfb715b17775ba86f1575a46d8cffa1f6b509@[172.21.0.2]:30303     depends_on:       - node1     ports:       - "25450:8545"       - "25460:8546"       - "20303:30303"       - "20303:30303/udp"       - "20304:30304/udp"     volumes:       - /etc/localtime:/etc/localtime       - ./node2/:/root/.ethereum/     environment:       - TZ=Asia/Shanghai   node3:     image: meitugeth     command: --ipcpath "/root/.ethereum/geth.ipc" --port 30303 --bootnodes enode://97caa3fe607663197d8741be1f26a1e53fc936cdef7187cdec737495fa01ae501d95a659bdf48e7d8505a8fc1dacfb715b17775ba86f1575a46d8cffa1f6b509@[172.21.0.2]:30303     depends_on:           - node1     ports:       - "35450:8545"       - "35460:8546"       - "40303:30303"       - "40303:30303/udp"       - "40304:30304/udp"     volumes:       - /etc/localtime:/etc/localtime       - ./node3/:/root/.ethereum/     environment:       - TZ=Asia/Shanghai

再验证下节点是否互联

amdin.peers [{     caps: ["eth/62", "eth/63"],     id: "0031048c457163671377bd197d05a78b1c11d474705b29b1b2473b37356d0a4fdf96563fcbda1d6cdf21a6e30f3082935276c4538a82b14da1d660b04ef99213",     name: "Geth/v1.7.4-stable-6be4cd4b/linux-amd64/go1.9.7",     network: {       localAddress: "172.21.0.2:48356",       remoteAddress: "172.21.0.4:30303"     },     protocols: {       eth: {         difficulty: 131072,         head: "0x19d4e0c4422cfe81c35cb9420127a6dc590c3e6b09ca835c840d53a601ed1d32",         version: 63       }     } }, {     caps: ["eth/62", "eth/63"],     id: "15bc1789ff8b5108a1e47cf257bae7928d5bfc1eb44c5d61c8dad86f7ac6b985c82dc32e3ffcdf06bd142f4a19183d89c51e4a5fdd1c5447e7172f2e5aadb428",     name: "Geth/v1.7.4-stable-6be4cd4b/linux-amd64/go1.9.7",     network: {       localAddress: "172.21.0.2:30303",       remoteAddress: "172.21.0.3:47174"     },     protocols: {       eth: {         difficulty: 131072,         head: "0x19d4e0c4422cfe81c35cb9420127a6dc590c3e6b09ca835c840d53a601ed1d32",         version: 63       }     } }]

“主网”启动成功!

投票、出块验证

分别在3个节点上把validator无限期解锁,谁不解锁谁别出块、跳过你。这里源码默认10秒1块。

personal.unlockAccount(eth.validator,'xxxx', 0)

根据美图解释,这里validator和coinbase的区别:
coinbase收取挖矿奖励,validator可以设置为其他地址,但默认和coinbase一样。

3个节点分别启动挖矿

miner.start()

查看出块信息

> eth.getBlock(15) {   coinbase: "0x8807fa0db2c60675a8f833dd010469e408428b83",   difficulty: 1,   extraData: "0xd783010704846765746887676f312e392e37856c696e757800000000000000000c50642f0a32b6ad0ac5c94ee6a8e4ef2043aa0a763a6eb817223c9d585454a604e836f37b281fdf7962631aaf2963763783556fee7c6bcebf3df2113f93815001",   gasLimit: 5166620,   gasUsed: 0,   hash: "0x2d598f908d0535d58a82019ff0ec88e666065d3efcfc93293decbe1f26ea5d16",   logsBloom: "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",   mixHash: "0x0000000000000000000000000000000000000000000000000000000000000000",   nonce: "0x0000000000000000",   number: 15,   parentHash: "0x2ba52152d2ca5e60aca873c850b1bef7812bf940f04a8756944dfd0f85f8fde3",   receiptsRoot: "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",   sha3Uncles: "0x1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347",   size: 794,   stateRoot: "0x45e73d97158ba78c2afae887038b18d70d92e865dc3b0b175423061bf6bde29b",   timestamp: 1530254800,   totalDifficulty: 131087,   transactions: [],   transactionsRoot: "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",   uncles: [],   validator: "0x8807fa0db2c60675a8f833dd010469e408428b83" } > eth.getBlock(16) {   coinbase: "0xe0d64bfb1a30d66ae0f06ce36d5f4edf6835cd7c",   difficulty: 1,   extraData: "0xd783010704846765746887676f312e392e37856c696e757800000000000000000a6277cd4e5153f10abb221aa850ed64059b6fe93b1451417321cf17190a1f6b56707ca05550d4727f48874ce0899c3012990b361fe79e88d4ca51788eb6500e01",   gasLimit: 5161576,   gasUsed: 0,   hash: "0x4de33e49fb536a710737fb1e09c4f713a0ca7e5511682451e006898e71af365d",   logsBloom: "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",   mixHash: "0x0000000000000000000000000000000000000000000000000000000000000000",   nonce: "0x0000000000000000",   number: 16,   parentHash: "0x2d598f908d0535d58a82019ff0ec88e666065d3efcfc93293decbe1f26ea5d16",   receiptsRoot: "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",   sha3Uncles: "0x1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347",   size: 794,   stateRoot: "0xe50a0e2181198d8543dcaf26be57f2c004e92ee446195d75fe447fcf6c4f0992",   timestamp: 1530254810,   totalDifficulty: 131088,   transactions: [],   transactionsRoot: "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",   uncles: [],   validator: "0xe0d64bfb1a30d66ae0f06ce36d5f4edf6835cd7c" } > eth.getBlock(17) {   coinbase: "0xdf5f5a7abc5d0821c50deb4368528d8691f18737",   difficulty: 1,   extraData: "0xd783010704846765746887676f312e392e37856c696e757800000000000000004bbf4fbec4706ecae18a4cbb0d92a9c9546e13503ca818f7b22860c78f5bac0748196864c697dabf6891c372e6911c1664ced36fdebfaa9ac2b608a9cb1beba701",   gasLimit: 5156537,   gasUsed: 0,   hash: "0x743db2aa9732c26e80d21fa81fca75e8a952ea9f219b5720b5af7ebf7f832abd",   logsBloom: "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",   mixHash: "0x0000000000000000000000000000000000000000000000000000000000000000",   nonce: "0x0000000000000000",   number: 17,   parentHash: "0x4de33e49fb536a710737fb1e09c4f713a0ca7e5511682451e006898e71af365d",   receiptsRoot: "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",   sha3Uncles: "0x1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347",   size: 794,   stateRoot: "0x3dcb37771aceff66ff2af6f281e7306ead90824f0ecea18f60ffd87fd722731c",   timestamp: 1530254820,   totalDifficulty: 131089,   transactions: [],   transactionsRoot: "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",   uncles: [],   validator: "0xdf5f5a7abc5d0821c50deb4368528d8691f18737" }

可以看到3个节点轮流出块,10秒1块。

测试1:
假如2节点因某种原因不能出块了,那么下一轮当1节点出块后,3节点在时隔20秒后出块。

特别鸣谢美图架构组林大佬@Hulk

原文链接:https://segmentfault.com/a/1190000015408582

打开App,阅读手记
1人推荐
发表评论
随时随地看视频慕课网APP

热门评论

您好,我根据您的方案已经部署成功了,可是我有一个问题,就是您的文章是通过ipc连接的各个节点,就是只能通过本机进行访问,我想问一下如何在其他计算机上访问整个以太坊网络呢,就是例如普通部署以太坊的rpc一样的那种,谢谢

查看全部评论