在私有网络中建立多个节点组成的集群,并互相发现,产生交易.
创世区块
集群中所有的节点必须报有相同的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