在私有网络中建立多个节点组成的集群,并互相发现,产生交易.
创世区块
集群中所有的节点必须报有相同的genesis state, 否则节点无法关联上1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21{
"config": {
"chainId": 180,
"homesteadBlock": 0,
"eip155Block": 0,
"eip158Block": 0
},
"alloc": {
"fad9684b077d9046ff2e293a375d29e2ebc5445a": {
"balance": "30000000000000000"
}
},
"coinbase": "0x0000000000000000000000000000000000000000",
"difficulty": "0x20000",
"extraData": "",
"gasLimit": "0x2fefd8",
"nonce": "0x0000000000000042",
"mixhash": "0x0000000000000000000000000000000000000000000000000000000000000000",
"parentHash": "0x0000000000000000000000000000000000000000000000000000000000000000",
"timestamp": "0x00"
}
搭建私有链节点
参考<<搭建私有链(Private Chain)并进行挖矿和交易>>,
启动节点1作为
boot node,1
2
3
4# Node 1 - boot node 1
geth --datadir ./data/1 init genesis.json
cp -R ./keystore/ ./data/1/keystore/
geth --datadir ./data/1 --identity "boot-node-1" --networkid 1808923373394438348 --verbosity 6 --ipcdisable --port 30301 --rpcport 8101 console 2>> ./logs/1.log可以查看帐号信息和当前节点信息:
1
2
3
4
5
6> personal.listAccounts
["0xfad9684b077d9046ff2e293a375d29e2ebc5445a"]
> admin.peers
[]
> admin.nodeInfo.enode
"enode://19c2f5b1d4e3ea0d4b042eb3b631b0eb7648c442df687926d8b7063e2d50404e1566c8a052e5c57925b20df9a8b0fa2511679df20c37100b62e6f1446cf5bfe3@[::]:30301"启动节点3作为挖矿节点
以--mine启动节点3作为挖矿节点, 再通过--bootnodes配置关联节点11
2
3
4
5
6
7# Node 3 - miner node
geth --datadir ./data/3 init genesis.json
cp -R ./keystore/ ./data/3/keystore/
geth --datadir ./data/3 --identity "miner-node" --networkid 1808923373394438348 --verbosity 4 --ipcdisable --port 30303 --rpcport 8103 \
--minerthreads=1 --etherbase fad9684b077d9046ff2e293a375d29e2ebc5445a \
--bootnodes "enode://19c2f5b1d4e3ea0d4b042eb3b631b0eb7648c442df687926d8b7063e2d50404e1566c8a052e5c57925b20df9a8b0fa2511679df20c37100b62e6f1446cf5bfe3@127.0.0.1:30301" \
console 2>> ./logs/3.log节点3起来后,检查节点联系:
1
2
3
4
5
6> personal.listAccounts
["0xfad9684b077d9046ff2e293a375d29e2ebc5445a"]
> admin.peers
[{
...
}]注意: 通过IP
127.0.0.1替代, 外部主机也可以通过外部IP建立关联. (可以通过ifconfig|grep netmask|awk '{print $2}'可获取IP.)启动节点2也作为
boot node:1
2
3
4# Node 2 - boot node 2
geth --datadir ./data/2 init genesis.json
cp -R ./keystore/ ./data/2/keystore/
geth --datadir ./data/2 --identity "boot-node-2" --networkid 1808923373394438348 --verbosity 4 --ipcdisable --port 30302 --rpcport 8102 console 2>> ./logs/2.log节点2起来后,可以查看帐号信息和当前节点信息:
1
2
3
4
5
6> personal.listAccounts
["0xfad9684b077d9046ff2e293a375d29e2ebc5445a"]
> admin.peers
[]
> admin.nodeInfo.enode
"enode://dd4b2503ad79644d0591daa7b11bcb04ce62fe4798a1747b62a8289e3dbd0cdb770478dcc44e42a00ff2ddcfde1cfeb98fbf36769474bfcddb07704b75e0f026@[::]:30302"关联节点2 & 3:
在节点3控制台通过admin.addPeer()命令关联节点2 & 3, 再检查节点1, 2 & 3的peers:1
2
3
4
5
6> addmin.addPeer('enode://dd4b2503ad79644d0591daa7b11bcb04ce62fe4798a1747b62a8289e3dbd0cdb770478dcc44e42a00ff2ddcfde1cfeb98fbf36769474bfcddb07704b75e0f026@127.0.0.1:30302')
true
> admin.peers
[
...
]查看账余额
检查初始账户的余额为30000000000000000, 通过miner.start(1)让矿工开工:1
2
3
4> miner.start(1)
null
> eth.getBalance('0xfad9684b077d9046ff2e293a375d29e2ebc5445a')
30000000000000000金额在变化, 矿工已开工.
启动节点4为交易节点
通过--bootnodes将两个boot node都关联上:1
2
3
4
5
6# Node 4 - transaction node 1
geth --datadir ./data/4 init genesis.json
cp -R ./keystore/ ./data/4/keystore/
geth --datadir ./data/4 --identity "transaction-node-1" --networkid 1808923373394438348 --verbosity 4 --ipcdisable --port 30304 --rpcport 8104 \
--bootnodes "enode://19c2f5b1d4e3ea0d4b042eb3b631b0eb7648c442df687926d8b7063e2d50404e1566c8a052e5c57925b20df9a8b0fa2511679df20c37100b62e6f1446cf5bfe3@127.0.0.1:30301,enode://dd4b2503ad79644d0591daa7b11bcb04ce62fe4798a1747b62a8289e3dbd0cdb770478dcc44e42a00ff2ddcfde1cfeb98fbf36769474bfcddb07704b75e0f026@127.0.0.1:30302" \
console 2>> ./logs/4.log一个交易节点发生交易
通过miner.stop()关停矿区, 在交易节点上新加帐号, 并转账:1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38> personal.newAccount("acct1")
"0xfe14b8ed857f4482602d9438f651c94e8a53b31f"
> eth.getBalance('0xfe14b8ed857f4482602d9438f651c94e8a53b31f')
0
> eth.getBalance('0xfad9684b077d9046ff2e293a375d29e2ebc5445a')
890029999999999999995
> personal.unlockAccount('0xfad9684b077d9046ff2e293a375d29e2ebc5445a')
Unlock account 0xfad9684b077d9046ff2e293a375d29e2ebc5445a
Passphrase: [password]
true
> eth.sendTransaction({from:'0xfad9684b077d9046ff2e293a375d29e2ebc5445a',to:'0xfe14b8ed857f4482602d9438f651c94e8a53b31f',value:5})
"0x01afeaac31ad8226950d45c91e637021546071978eb0589ecc7ba03f9b7f7302"
> eth.getTransaction('0x01afeaac31ad8226950d45c91e637021546071978eb0589ecc7ba03f9b7f7302') // 产看交易细节
{
blockHash: "0x0000000000000000000000000000000000000000000000000000000000000000",
blockNumber: null,
from: "0xfad9684b077d9046ff2e293a375d29e2ebc5445a",
gas: 90000,
gasPrice: 18000000000,
hash: "0x01afeaac31ad8226950d45c91e637021546071978eb0589ecc7ba03f9b7f7302",
input: "0x",
nonce: 0,
r: "0x79b8930fa1efbf3352636b8f1723ff040fb4d477489d5e424b1da36ab799c59f",
s: "0x371bbebf6d5e1f568f2169d1c581c7e79f8c92ce28d9873ec6c23095e9d6092e",
to: "0xfe14b8ed857f4482602d9438f651c94e8a53b31f",
transactionIndex: 0,
v: "0x18b",
value: 5
}
> eth.getBalance('0xfe14b8ed857f4482602d9438f651c94e8a53b31f')
0
> eth.getBalance('0xfad9684b077d9046ff2e293a375d29e2ebc5445a')
890029999999999999995
> txpool.status // 查看交易池
{
pending: 1,
queued: 0
}矿工开工
miner.start(1), 再来查看交易:1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26> txpool.status // 查看交易池
{
pending: 0,
queued: 0
}
> eth.getBalance('0xfe14b8ed857f4482602d9438f651c94e8a53b31f')
5
> eth.getBalance('0xfad9684b077d9046ff2e293a375d29e2ebc5445a')
890029999999999999990
> eth.getTransaction('0x01afeaac31ad8226950d45c91e637021546071978eb0589ecc7ba03f9b7f7302')
{
blockHash: "0x2dfa70b0383b49f69ce8863ac453108f52921f0880c0fb4b4e14230cd82b5186",
blockNumber: 127,
from: "0xfad9684b077d9046ff2e293a375d29e2ebc5445a",
gas: 90000,
gasPrice: 18000000000,
hash: "0x01afeaac31ad8226950d45c91e637021546071978eb0589ecc7ba03f9b7f7302",
input: "0x",
nonce: 0,
r: "0x79b8930fa1efbf3352636b8f1723ff040fb4d477489d5e424b1da36ab799c59f",
s: "0x371bbebf6d5e1f568f2169d1c581c7e79f8c92ce28d9873ec6c23095e9d6092e",
to: "0xfe14b8ed857f4482602d9438f651c94e8a53b31f",
transactionIndex: 0,
v: "0x18b",
value: 5
}交易节点之间发生交易
以static node的方式关联节点, 配置 static-nodes.json1
2
3
4[
"enode://19c2f5b1d4e3ea0d4b042eb3b631b0eb7648c442df687926d8b7063e2d50404e1566c8a052e5c57925b20df9a8b0fa2511679df20c37100b62e6f1446cf5bfe3@127.0.0.1:30301",
"enode://dd4b2503ad79644d0591daa7b11bcb04ce62fe4798a1747b62a8289e3dbd0cdb770478dcc44e42a00ff2ddcfde1cfeb98fbf36769474bfcddb07704b75e0f026@127.0.0.1:30302"
]启动节点5为第二个交易节点:
1
2
3
4
5
6# Node 5 - transaction node 2
geth --datadir ./data/5 init genesis.json
cp -R ./keystore/ ./data/5/keystore/
cp -R ./static-nodes.json ./data/5/
geth --datadir ./data/5 --identity transaction-node-2 --networkid 1808923373394438348 --verbosity 4 --ipcdisable --port 30305 --rpcport 8105 \
console 2>> ./logs/5.log为节点5创建帐号:
1
2
3
4
5
6> personal.newAccount('acct2')
"0x210bb5dc90b655622ae4be01a37c26ec35b83ed2"
> eth.getBalance('0xfe14b8ed857f4482602d9438f651c94e8a53b31f')
1650000000010
> eth.getBalance('0x210bb5dc90b655622ae4be01a37c26ec35b83ed2')
0从节点4开始交易:
1
2
3
4
5
6> personal.unlockAccount('0xfe14b8ed857f4482602d9438f651c94e8a53b31f')
Unlock account 0xfe14b8ed857f4482602d9438f651c94e8a53b31f
Passphrase: [password]
true
> eth.sendTransaction({from:'0xfe14b8ed857f4482602d9438f651c94e8a53b31f',to:'0x210bb5dc90b655622ae4be01a37c26ec35b83ed2',value:5})
"0x01afeaac31ad8226950d45c91e637021546071978eb0589ecc7ba03f9b7f7302"注意:
- 当前节点必须包含转出账户, 否则无法交易
- 通过 static-nodes.json 的方式创建起来的节点, 是只能发现文件中配置的节点, 无法发现集群中中其他的节点, 这样可以用于做网络隔离.
关停
boot node
当关停boot node时, 会发现两个通过boot node简历关联的节点还是可以发现彼此的.boot node在集群中充当一个审批人的角色, 一个新的节点在需要给boot node发申请, 由boot node决定它是否可以加入这个圈子.boot node同意它的申请后, 它从boot node得到集群中其他节点的信息, 然后它并会与这些节点建立联系. 这时,boot node就已经完成了他的任务, 后续它的存在是可有可无的.
疑问:
- 节点集群中的单个节点上创建的帐号如何同步到其他的节点上
补充
节点发现协议
参考:
- http://blog.csdn.net/wo541075754/article/details/78926177
- http://www.cnblogs.com/zl03jsj/p/6876064.html
- http://blog.csdn.net/ddffr/article/details/78732256
- http://blog.csdn.net/ddffr/article/details/78912026
- https://github.com/ethereum/wiki/wiki/Node-discovery-protocol
- https://github.com/ethereum/devp2p/blob/master/rlpx.md#node-discovery