美圖DPOS以太坊節點網絡啓動和測試(Docker版)

節點網絡啓動

一、簡單測試起見,修改maxValidator爲最小數
consensus/dpos/dpos.gonode

maxValidatorSize = 3

二、構建美圖以太坊docker鏡像linux

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

三、創建節點數據目錄git

mkdir meitu
cd meitu
mkdir node1
mkdir node2
mkdir node3

四、編寫docker-compose.yml啓動文件github

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

五、在meitu目錄下啓動3個以太坊節點docker

docker-compose up -d

啓動網絡的思路1:
在創世塊裏配置好第一批驗證節點,而後啓動。
啓動網絡的思路2:
混合POW和DPOS,用POW進行投票,產生第一批驗證節點,並自動切換到DPOS。json

這裏顯然採用思路1.網絡

六、進入node1容器架構

docker exec -it $container_node1_id /bin/sh

七、獲取geth JavaScript控制檯oop

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

八、在node1節點創建coinbase測試

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

記錄下上述地址。

九、退出node1容器或者打開新窗口進入node二、node3

loop:重複6-9步驟,在node2和node3上分別設立coinbase。

3個節點的地址分別爲:

0x8807fa0db2c60675a8f833dd010469e408428b83
0xdf5f5a7abc5d0821c50deb4368528d8691f18737
0xe0d64bfb1a30d66ae0f06ce36d5f4edf6835cd7c

十、寫創世塊配置文件,把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": {}
}

十一、刪除每一個節點下個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。

十二、重啓節點網絡

docker-compose down
docker-conpose up -d

1三、隨便進入某個節點,查看驗證人是否設置成功。

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

1四、查看節點是否互聯

admin.peers
[]

爲空,說明節點之間沒有互相發現。

1五、讓節點互聯

查看每一個節點信息

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

相關文章
相關標籤/搜索