源码

https://github.com/meitu/go-ethereum

节点网络启动

1、简单测试起见,需要将节点最大验证器数修改为最小数
consensus/dpos/dpos.go

maxValidatorSize = 3

2、构建以太坊docker镜像

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

3、创建节点数据目录

mkdir meitu
cd meitu
mkdir node1
mkdir node2
mkdir node3

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

version: '3.3'
services:mgeth_node_1:image: mgethcontainer_name: mgeth_node_1build: context: ..command: --ipcpath "/root/.ethereum/geth.ipc" --port 30303ports:- "15450:8545"- "15460:8546"- "10303:30303"- "10303:30303/udp"- "10304:30304/udp"volumes:- /etc/localtime:/etc/localtime- ./node1/:/root/.ethereum/environment:- TZ=Asia/Shanghaimgeth_node_2:image: mgethcontainer_name: mgeth_node_2build: context: ..command: --ipcpath "/root/.ethereum/geth.ipc" --port 30303depends_on:- mgeth_node_1ports:- "25450:8545"- "25460:8546"- "20303:30303"- "20303:30303/udp"- "20304:30304/udp"volumes:- /etc/localtime:/etc/localtime- ./node2/:/root/.ethereum/environment:- TZ=Asia/Shanghaimgeth_node_3:image: mgethcontainer_name: mgeth_node_3build: context: ..command: --ipcpath "/root/.ethereum/geth.ipc" --port 30303depends_on:- mgeth_node_1ports:- "45450:8545"- "45460: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

启动思路:

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

6、进入以太坊节点容器

docker exec -it mgeth_node_1 /bin/sh
docker exec -it mgeth_node_2 /bin/sh
docker exec -it mgeth_node_3 /bin/sh

7、获取geth JavaScript控制台

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

或者可以

docker exec -it mgeth_node_1 geth attach ipc:/root/.ethereum/geth.ipc

8、在node1节点建立coinbase

personal.newAccount('xxxx')

"0x8807fa0db2c60675a8f833dd010469e408428b83"

记录下上述地址。

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

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

3个节点的地址分别为:

0x8807fa0db2c60675a8f833dd010469e408428b83
0xdf5f5a7abc5d0821c50deb4368528d8691f18737
0xe0d64bfb1a30d66ae0f06ce36d5f4edf6835cd7c

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

{"config": {"chainId": 8888,"eip155Block": 0,"eip158Block": 0,"byzantiumBlock":0,"dpos":{"validators":["0x8807fa0db2c60675a8f833dd010469e408428b83","0xdf5f5a7abc5d0821c50deb4368528d8691f18737","0xe0d64bfb1a30d66ae0f06ce36d5f4edf6835cd7c"]}},"nonce": "0x0000000000000042","difficulty": "0x99999","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 mt_genesis.json node1
cp mt_genesis.json node2
cp mt_genesis.json node3

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

geth init /root/.ethereum/mt_genesis.json 

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

12、重启节点网络

docker-compose down
docker-compose 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 mgeth_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:mgeth_node_1:image: mgethcontainer_name: mgeth_node_1build: context: ..command: --ipcpath "/root/.ethereum/geth.ipc" --port 30303ports:- "15450:8545"- "15460:8546"- "10303:30303"- "10303:30303/udp"- "10304:30304/udp"volumes:- /etc/localtime:/etc/localtime- ./node1/:/root/.ethereum/environment:- TZ=Asia/Shanghaimgeth_node_2:image: mgethcontainer_name: mgeth_node_2build: context: ..command: --ipcpath "/root/.ethereum/geth.ipc" --port 30303 --bootnodes enode://97caa3fe607663197d8741be1f26a1e53fc936cdef7187cdec737495fa01ae501d95a659bdf48e7d8505a8fc1dacfb715b17775ba86f1575a46d8cffa1f6b509@[172.21.0.2]:30303depends_on:- mgeth_node_1ports:- "25450:8545"- "25460:8546"- "20303:30303"- "20303:30303/udp"- "20304:30304/udp"volumes:- /etc/localtime:/etc/localtime- ./node2/:/root/.ethereum/environment:- TZ=Asia/Shanghaimgeth_node_3:image: mgethcontainer_name: mgeth_node_3build: context: ..command: --ipcpath "/root/.ethereum/geth.ipc" --port 30303 --bootnodes enode://97caa3fe607663197d8741be1f26a1e53fc936cdef7187cdec737495fa01ae501d95a659bdf48e7d8505a8fc1dacfb715b17775ba86f1575a46d8cffa1f6b509@[172.21.0.2]:30303depends_on:- mgeth_node_1ports:- "45450:8545"- "45460: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秒后出块。

Tips:

之前在一台服务器上部署后发现暴露出来的15450端口一直无法访问,把端口加入防火墙规则甚至是关闭防火墙依然无用,检查了云平台上的安全组规则一切正常,最后在服务器用ifconfig检查了一下,发现docker创建的网关和eth0的网卡都是在172.22下面的。


修改docker-compose.yml把bridge更换到另一个网段,重启,成功!

美图DPOS共识机制ETH节点网络启动和测试相关推荐

  1. 美图DPOS以太坊教程(Docker版)

    一.前言 最近,需要接触区块链项目的主链开发,在EOS.BTC.ethereum.超级账本这几种区块链技术当中,相互对比后,最终还是以go-ethereum为解决方案. 以ethereum为基准去找解 ...

  2. EOS入门(8)---浅谈EOS的DPOS共识机制

    EOS入门(8)---浅谈EOS的DPOS共识机制  光_武 关注 2018.03.17 14:13 字数 3873 阅读 1534评论 1喜欢 2 本文参考汤强公众号的一篇文章坐看邻国领袖打高尔夫球 ...

  3. POW,POS,DPOS共识机制简单介绍

    区块链技术的诞生基于共识机制,所谓的共识,简单来理解,即打成共识一致的观点,随着技术的发展与演变,我们听到了越来越多的共识,例如:POS,DPOS,POW,Pool验证池,POC,POR等共识算法机制 ...

  4. python爬虫今日头条街拍美图开发背景_【Python3网络爬虫开发实战】6.4-分析Ajax爬取今日头条街拍美图...

    [摘要] 本节中,我们以今日头条为例来尝试通过分析Ajax请求来抓取网页数据的方法.这次要抓取的目标是今日头条的街拍美图,抓取完成之后,将每组图片分文件夹下载到本地并保存下来. 1. 准备工作 在本节 ...

  5. Pow,Pos,Dpos共识机制比较

    1.工作量证明(pow) 简述: 理论上每个计算机都拥有可以参与计算获得挖矿的机会,正因为这样拥有更多算力的机器则拥有更大机会找到哈希值获得奖励.挖矿难度相同,算力决定出块的概率.拥有百分之51的算力 ...

  6. DPoS共识机制白皮书理解

    目录 1.用户组成及关系 2.共识流程 1.正常情况 2.恶意节点多重制造问题 3.网络碎片问题 4.不可篡改的区块 3.思考 DPoS (Delegated Proof of Stake) 股份授权 ...

  7. 3-12 董事会体制:DPOS共识机制(股份授权代表机制)

    体验指导 先进行投票: 再连续点击"记账"按钮: 同步练习

  8. 以太坊又一次大拥堵何去何从?深度对话美图以太坊DPoS算法实现团队

    最近,以太坊又一次出现大拥堵,美图基于以太坊框架实现了 DPoS 算法并且对代码进行了开源(链接见文末),希望借助此方案能让以太坊发展有更多的选择的可能. 图:最近一周以太坊交易又出现大范围拥堵 有些 ...

  9. EOS共识机制——DPoS代理权益证明

    链客,专为开发者而生,有问必答! 此文章来自区块链技术社区,未经允许拒绝转载. 区块链共识机制与它的演进,是由于区块链式去中心化而且分布式的系统,必须要有一套放诸四海皆准类似宪法的规则,来规范如何证明 ...

最新文章

  1. 征服围棋之后 谷歌DeepMind宣布利用AI对抗乳腺癌
  2. Springboot - -web应用开发-Servlets, Filters, listeners
  3. 在wdos系统下搭建Dns服务器
  4. 洛谷P4319 变化的道路
  5. linux开启防火墙ping,如何在防火墙中放开ping
  6. 使用maven插件构建docker镜像
  7. 47 - 算法 - 记住常用位运算-Leetcode-136-只出现一次的数字
  8. java中值滤波_Java实现图像中值滤波
  9. 关于collectionView的一些内容
  10. Java基础方面(二)
  11. PS学习总结一:入门版必备的基础功能
  12. 揭秘:嫦娥四号为何有月昼工作和月夜休眠两种模式?
  13. 居于canvas的原生js抽奖小程序
  14. 深度强化学习发展现状及展望:万字总结解读83篇文献
  15. 天地人“三界传说”官网基础效果(适合各分辨率页面)
  16. 大数据基础知识思维导图
  17. 计算机专业被check后拒签,签证被Check是怎么一回事?解读美签的几种情况
  18. 打印字母对称型的金字塔图案(C语言)
  19. 度量空间的完备化定理
  20. 由“人人网”解析移动互联网的未来发展战略

热门文章

  1. 什么是顶级域名?如何获得顶级域名解析方案
  2. KFC门店定点查询(输入城市名称即可查询)
  3. 2019腾讯产品策划/运营暑期实习生提前批凉凉面经
  4. widget是什么意思?
  5. Python爬虫爬取韩国电影售票评分网站电影排行榜Top250
  6. 革命性新疗法后 第三例艾滋病治愈病例可能出现了!
  7. 从高朋裁员说起——山寨,不是创新的“中国模式”
  8. 华为轮值董事长郭平:华为重申不造车
  9. delphi Android 创建缩略图,用Delphi实现缩略图查看
  10. 基于OpenCV实现海岸线变化检测