(转)在以太坊私有网络中建立节点集群,并发生交易
第二节中了解了使用geth搭建以太坊私有网络,这一次则要在私有网络中建立多个node组成的集群,并互相发现,产生交易.
为了在本地网络运行多个以太坊节点的实例,必须确保一下几点:
1. 每个实例都有独立的数据目录(--datadir)
2. 每个实例运行都有独立的端口.(eth和rpc两者都是)(--port 和 --rpcprot)
3. 在集群的情况下, 实例之间都必须要知道彼此.
4. 唯一的ipc通信端点,或者禁用ipc.
启动第一个节点(指定端口,并禁用ipc),运行命令和结果如下:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
|
~ /Documents/private-geth geth --datadir . /data/00 --networkid 314590 --ipcdisable --port 61910 --rpcport 8200 console INFO [05-29|16:18:59] Starting peer-to-peer node instance=Geth /v1 .6.1-stable-021c3c28 /linux-amd64/go1 .8.1 INFO [05-29|16:18:59] Allocated cache and file handles database= /home/zl/Documents/private-geth/data/00/geth/chaindata cache=128 handles=1024 INFO [05-29|16:18:59] Initialised chain configuration config= "{ChainID: 15 Homestead: 0 DAO: <nil> DAOSupport: false EIP150: <nil> EIP155: 0 EIP158: 0 Engine: unknown}" INFO [05-29|16:18:59] Disk storage enabled for ethash caches dir = /home/zl/Documents/private-geth/data/00/geth/ethash count=3 INFO [05-29|16:18:59] Disk storage enabled for ethash DAGs dir = /home/zl/ .ethash count=2 INFO [05-29|16:18:59] Initialising Ethereum protocol versions= "[63 62]" network=314590 INFO [05-29|16:18:59] Loaded most recent local header number=29 hash =8ff3ff…dac4a2 td=7372364 INFO [05-29|16:18:59] Loaded most recent local full block number=29 hash =8ff3ff…dac4a2 td=7372364 INFO [05-29|16:18:59] Loaded most recent local fast block number=29 hash =8ff3ff…dac4a2 td=7372364 WARN [05-29|16:18:59] Blockchain not empty, fast sync disabled INFO [05-29|16:18:59] Starting P2P networking INFO [05-29|16:19:01] Mapped network port proto=udp extport=61910 intport=61910 interface= "UPNP IGDv1-IP1" INFO [05-29|16:19:02] RLPx listener up self=enode: //ad307e052d0e04af519b8999fa870800df8a7a0cc2a91e6aea30e879b75c344dfa12c773a63a71677c2a3ea1254cf982815817f7ff58bd79e5837ea44d791a2d @192.168.1.2:61910 INFO [05-29|16:19:02] Mapped network port proto=tcp extport=61910 intport=61910 interface= "UPNP IGDv1-IP1" Welcome to the Geth JavaScript console! instance: Geth /v1 .6.1-stable-021c3c28 /linux-amd64/go1 .8.1 coinbase: 0x5fba50fce50baf0b8a7314200ba46336958ac97e at block: 29 (Mon, 29 May 2017 13:13:46 CST) datadir: /home/zl/Documents/private-geth/data/00 modules: admin:1.0 debug:1.0 eth:1.0 miner:1.0 net:1.0 personal:1.0 rpc:1.0 txpool:1.0 web3:1.0 |
上面的命令以命令行的(console)的方式启动了节点, 所以我们可以通过继续输入下面的命令获取节点实例的enode url:
1
2
3
|
>admin.nodeInfo.enode "enode://ad307e052d0e04af519b8999fa870800df8a7a0cc2a91e6aea30e879b75c344dfa12c773a63a71677c2a3ea1254cf982815817f7ff58bd79e5837ea44d791a2d@192.168.1.2:61910" > |
###########################获取本机IP地址###########################
1
2
3
|
$ ifconfig | grep netmask| awk '{print $2}' 127.0.0.1 192.168.1.102 |
###########################
再打开一个终端,初始化第二个节点:
1
|
geth --datadir . /data/01 init . /genesis .json |
启动第二个节点:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
|
~ /Documents/private-geth geth --datadir . /data/01 --networkid 314590 --ipcdisable --port 61911 --rpcport 8101 --bootnodes "enode://ad307e052d0e04af519b8999fa870800df8a7a0cc2a91e6aea30e879b75c344dfa12c773a63a71677c2a3ea1254cf982815817f7ff58bd79e5837ea44d791a2d@192.168.1.2:61910" console INFO [05-29|18:42:15] Starting peer-to-peer node instance=Geth /v1 .6.1-stable-021c3c28 /linux-amd64/go1 .8.1 INFO [05-29|18:42:15] Allocated cache and file handles database= /home/zl/Documents/private-geth/data/01/geth/chaindata cache=128 handles=1024 INFO [05-29|18:42:15] Initialised chain configuration config= "{ChainID: 15 Homestead: 0 DAO: DAOSupport: false EIP150: EIP155: 0 EIP158: 0 Engine: unknown}" INFO [05-29|18:42:15] Disk storage enabled for ethash caches dir = /home/zl/Documents/private-geth/data/01/geth/ethash count=3 INFO [05-29|18:42:15] Disk storage enabled for ethash DAGs dir = /home/zl/ .ethash count=2 INFO [05-29|18:42:15] Initialising Ethereum protocol versions= "[63 62]" network=314590 INFO [05-29|18:42:15] Loaded most recent local header number=36 hash =e1541c…418ce3 td=8938686 INFO [05-29|18:42:15] Loaded most recent local full block number=36 hash =e1541c…418ce3 td=8938686 INFO [05-29|18:42:15] Loaded most recent local fast block number=36 hash =e1541c…418ce3 td=8938686 WARN [05-29|18:42:15] Blockchain not empty, fast sync disabled INFO [05-29|18:42:15] Starting P2P networking INFO [05-29|18:42:17] Mapped network port proto=udp extport=61911 intport=61911 interface= "UPNP IGDv1-IP1" INFO [05-29|18:42:17] RLPx listener up self=enode: //2261c433ed5d12924f727b61bf4084f22f4199b430115827c8eae3bb210c0dd5b3dd7df8dc13d8ca80c80f4a36e25c7bc7737737001d0b09324ee43ca6b9d7f8 @192.168.1.2:61911 INFO [05-29|18:42:17] Mapped network port proto=tcp extport=61911 intport=61911 interface= "UPNP IGDv1-IP1" Welcome to the Geth JavaScript console! instance: Geth /v1 .6.1-stable-021c3c28 /linux-amd64/go1 .8.1 coinbase: 0x0a8c35653d8b229c16f0c9ce6f63cffb877cfdcf at block: 36 (Mon, 29 May 2017 18:30:22 CST) datadir: /home/zl/Documents/private-geth/data/01 modules: admin:1.0 debug:1.0 eth:1.0 miner:1.0 net:1.0 personal:1.0 rpc:1.0 txpool:1.0 web3:1.0 |
上面的命令中,--bootndoes 是设置当前节点启动后,直接通过设置--bootndoes 的值来链接第一个节点, --bootnoedes 的值可以通过在第一个节的命令行中,输入:admin.nodeInfo.enode命令打印出来.
也可以不设置 --bootnodes, 直接启动,启动后进入命令行, 通过命令admin.addPeer(enodeUrlOfFirst Instance)把它作为一个peer添加进来.
为了确认链接成功,第二个节点输入:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
|
> admin.nodeInfo { enode: "enode://2261c433ed5d12924f727b61bf4084f22f4199b430115827c8eae3bb210c0dd5b3dd7df8dc13d8ca80c80f4a36e25c7bc7737737001d0b09324ee43ca6b9d7f8@192.168.1.2:61911" , id : "2261c433ed5d12924f727b61bf4084f22f4199b430115827c8eae3bb210c0dd5b3dd7df8dc13d8ca80c80f4a36e25c7bc7737737001d0b09324ee43ca6b9d7f8" , ip: "192.168.1.2" , listenAddr: "[::]:61911" , name: "Geth/v1.6.1-stable-021c3c28/linux-amd64/go1.8.1" , ports: { discovery: 61911, listener: 61911 }, protocols: { eth: { difficulty: 8938686, genesis: "0xa0e580c6769ac3dd80894b2a256164a76b796839d2eb7f799ef6b9850ea5e82e" , head : "0xe1541cc54dbcade54fb61053ffa71391c44bb6655cf9619635263960bc418ce3" , network: 314590 } } } > |
第一个节点输入:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
|
> net.peerCount 1 > admin.peers [{ caps: [ "eth/62" , "eth/63" ], id : "2261c433ed5d12924f727b61bf4084f22f4199b430115827c8eae3bb210c0dd5b3dd7df8dc13d8ca80c80f4a36e25c7bc7737737001d0b09324ee43ca6b9d7f8" , name: "Geth/v1.6.1-stable-021c3c28/linux-amd64/go1.8.1" , network: { localAddress: "192.168.0.103:61910" , remoteAddress: "192.168.1.2:41912" }, protocols: { eth: { difficulty: 8938686, head : "0xe1541cc54dbcade54fb61053ffa71391c44bb6655cf9619635263960bc418ce3" , version: 63 } } }] > |
从得到的结果可以看出,第一个节点有1个peer链接, 链接的node id为:
"2261c433ed5d12924f727b61bf4084f22f4199b430115827c8eae3bb210c0dd5b3dd7df8dc13d8ca80c80f4a36e25c7bc7737737001d0b09324ee43ca6b9d7f8"
这个id,正好就是第二个节点的id.
按照这样的方式继续扩展,可以非常容易就可以建立本地节点集群.这些工作都可以写成脚本代码来完成, 里面还可以包含创建账户,挖矿等..
请参考:https://github.com/ethersphere/eth-utils下的gethcluster.sh脚本,以及README中的使用方法和示例.
链接成功后,使用我们在上一篇文章中挖矿的账户,向第二个节点发送 "ether"(以太币的货币单位,还有一种叫"Wei",基本上这些货币单位都是用一些牛逼的人的名字来命名的).
首先查看第二个节点的Wei数量和整个网络的区块号,还有接收货币的账号id:
1
2
3
4
5
6
7
|
> eth.getBalance(eth.accounts[0]) 0000000000000000000 > eth.blockNumber 30 > eth.accounts[0] "0x0a8c35653d8b229c16f0c9ce6f63cffb877cfdcf" > |
在第一个节点命令行中,执行下面的操作:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
|
> personal.unlockAccount(eth.accounts[0], "ko2005" ) true > eth.sendTransaction({from: "0x5fba50fce50baf0b8a7314200ba46336958ac97e" , to: "0x0a8c35653d8b229c16f0c9ce6f63cffb877cfdcf" , value: web3.toWei(1, "ether" )}) INFO [05-29|17:33:42] Submitted transaction fullhash=0x51a75422f79fa96e70a0c1481851bc9f827868c44203b68d74f9815ffb367d5f recipient=0x0a8c35653d8b229c16f0c9ce6f63cffb877cfdcf "0x51a75422f79fa96e70a0c1481851bc9f827868c44203b68d74f9815ffb367d5f" > eth.pendingTransactions [{ blockHash: null, blockNumber: null, from: "0x5fba50fce50baf0b8a7314200ba46336958ac97e" , gas: 90000, gasPrice: 20000000000, hash : "0x51a75422f79fa96e70a0c1481851bc9f827868c44203b68d74f9815ffb367d5f" , input: "0x" , nonce: 0, r: "0x5632a8ade4a767dbd949ba1042cb33f98dd0722ab999ba18e1454d19d8bd1f6d" , s: "0x515dcfa3de297f0c956ad9a061a5561f47cc9ccbb0a547cda59193c77fcbe3f7" , to: "0x0a8c35653d8b229c16f0c9ce6f63cffb877cfdcf" , transactionIndex: 0, v : "0x42" , value: 1000000000000000000 }] |
eth.sendTransaction就是执行发送以太币的操作, 参数from, to分别是发送账户和接收账户, web3.toWei(1, "ether")是将1单位"ether"转换为相应的"Wei"数量.
然后执行挖矿(这里我也不理解,为什么发送货币以后,要通过挖矿才能让交易生效)
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
|
> miner.start() INFO [05-29|18:26:47] Updated mining threads threads=0 INFO [05-29|18:26:47] Starting mining operation null > INFO [05-29|18:26:47] Commit new mining work number=31 txs=1 uncles=0 elapsed=1.094ms > INFO [05-29|18:30:14] Successfully sealed new block number=31 hash =19e3d7…a6ecd5 INFO [05-29|18:30:14] 🔨 mined potential block number=31 hash =19e3d7…a6ecd5 INFO [05-29|18:30:14] Commit new mining work number=32 txs=0 uncles=0 elapsed=2.314ms INFO [05-29|18:30:17] Successfully sealed new block number=32 hash =94748a…cdbc17 INFO [05-29|18:30:17] 🔨 mined potential block number=32 hash =94748a…cdbc17 INFO [05-29|18:30:17] Commit new mining work number=33 txs=0 uncles=0 elapsed=156.295µs INFO [05-29|18:30:19] Successfully sealed new block number=33 hash =b8e037…cd50ff INFO [05-29|18:30:19] 🔨 mined potential block number=33 hash =b8e037…cd50ff INFO [05-29|18:30:19] Commit new mining work number=34 txs=0 uncles=0 elapsed=131.676µs > mINFO [05-29|18:30:20] Successfully sealed new block number=34 hash =7ad61a…f63067 INFO [05-29|18:30:20] 🔨 mined potential block number=34 hash =7ad61a…f63067 INFO [05-29|18:30:20] Commit new mining work number=35 txs=0 uncles=0 elapsed=138.957µs > miner.stINFO [05-29|18:30:22] Successfully sealed new block number=35 hash =eb9652…a1a9e3 INFO [05-29|18:30:22] 🔨 mined potential block number=35 hash =eb9652…a1a9e3 INFO [05-29|18:30:22] Commit new mining work number=36 txs=0 uncles=0 elapsed=334.318µs > miner.stopINFO [05-29|18:30:22] Successfully sealed new block number=36 hash =e1541c…418ce3 INFO [05-29|18:30:22] 🔗 block reached canonical chain number=31 hash =19e3d7…a6ecd5 INFO [05-29|18:30:22] 🔨 mined potential block number=36 hash =e1541c…418ce3 INFO [05-29|18:30:22] Commit new mining work number=37 txs=0 uncles=0 elapsed=117.185µs > miner.stop() true > |
从上面的日志可以看到,执行挖矿之后,一共有6个区块产生.
再在第二个节点的命令行输入:
1
2
3
4
|
> eth.blockNumber 36 > eth.getBalance(eth.accounts[0]) 1000000000000000000 |
可以看到第二个节点中的账户,已经得有了1个"ether", 并且可以看出,以太坊中,1"ether"=1000000000000000000"Wei.
之前输入eth.blockNumber,得到的值为30,其实只要挖出第一个区块的时候,就可以停止,发送到第二个node账户中的一个"ether",就已经生效.
总结一下:
这次以我们完成了以下内容:
1)创建区块链私有网络,并在网络中,建立自己的节点集群.
2)在接点集群中,通过一个节点的账户向网络中的另外一个节点的账户转了1个以太坊币,交易成功.
下一次,我们将开始使用truffle,写一个以太坊的"Hello World",正式进入区块链的开发.
另外说一下,
本人也是区块链新手,一边学习,一边把学习的过程记录下来向大家分享,中间走了非常多的弯路,
耗费了大量时间, 文章主要是把自己的学习经验分享出来,一个是自己可以巩固,另外可以帮助大家,避免大家和我一样走很多弯路.
如果文章中有写得不对的,或者有更好的方法,还请各位大神批评指正.