(转)在以太坊私有网络中建立节点集群,并发生交易

第二节中了解了使用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",正式进入区块链的开发.

另外说一下,
本人也是区块链新手,一边学习,一边把学习的过程记录下来向大家分享,中间走了非常多的弯路,
耗费了大量时间, 文章主要是把自己的学习经验分享出来,一个是自己可以巩固,另外可以帮助大家,避免大家和我一样走很多弯路.
如果文章中有写得不对的,或者有更好的方法,还请各位大神批评指正.

转自:http://www.cnblogs.com/zl03jsj/p/6876064.html

posted @ 2018-02-01 10:26  人艰不拆_zmc  阅读(580)  评论(0编辑  收藏  举报