- 在之前的博客中,我们完成了以太坊私有链的搭建,并执行了一些基本的操作,现在将实现多节点私有链的搭建。
- 如果还没有搭建好自己的私有链,或者对私有链的基本操作不熟悉,请参考之前的博客:
Ubuntu18.04搭建自己的以太坊私有链(一)
Ubuntu18.04搭建自己的以太坊私有链(二)
1. 初始化节点02
为了区分两个节点,我们将之前创作的节点,称为节点01,即将创建的节点称为节点02。
- 创建私有链专门的data目录:
$ mkdir /home/hadoop/private_eth2
- 使用以下命令初始化节点02的创世区块,指定私有链数据的存放目录、创世区块文件genesis.json目录。两个节点使用相同的创世区块文件,但数据存放目录不同。
$ geth --datadir /home/hadoop/eth/private_eth2/ init /home/hadoop/eth/private_eth1/genesis.json
INFO [03-22|21:03:05.521] Maximum peer count ETH=25 LES=0 total=25
INFO [03-22|21:03:05.583] Allocated cache and file handles database=/home/hadoop/eth/private_eth2/geth/chaindata cache=16 handles=16
INFO [03-22|21:03:05.709] Writing custom genesis block
INFO [03-22|21:03:05.709] Persisted trie from memory database nodes=0 size=0.00B time=4.867µs gcnodes=0 gcsize=0.00B gctime=0s livenodes=1 livesize=0.00B
INFO [03-22|21:03:05.710] Successfully wrote genesis state database=chaindata hash=6c63bb…074e7d
INFO [03-22|21:03:05.710] Allocated cache and file handles database=/home/hadoop/eth/private_eth2/geth/lightchaindata cache=16 handles=16
INFO [03-22|21:03:05.811] Writing custom genesis block
INFO [03-22|21:03:05.811] Persisted trie from memory database nodes=0 size=0.00B time=7.695µs gcnodes=0 gcsize=0.00B gctime=0s livenodes=1 livesize=0.00B
INFO [03-22|21:03:05.812] Successfully wrote genesis state database=lightchaindata hash=6c63bb…074e7d
- 使用
tree
命令以树形结构显示datadir
的目录结构
2. 启动节点02并与节点01相关联
- 查询节点01的enoded url,这是节点01与其他节点互动的唯一id。
> admin.nodeInfo.enode
"enode://7e4b2928c42d406686b28f406913f30dae969ea34b2cf11f8211f286e0b245b2a368111791bde0cefdf4f6256e6ca38d5b17a1c5f806be17c4ed637f967428f1@127.0.0.1:30303?discport=0"
- 启动节点02,由于我们是单机多节点,节点02的port以及rpcport应与节点01不同,并通过enoded url与节点01相关联。
$ geth --networkid 230 --datadir /home/hadoop/eth/private_eth2/ --identity "john" --rpc --rpcport "8888" --port "31000" --rpcaddr "192.168.1.120" --nodiscover --bootnodes "enode://7e4b2928c42d406686b28f406913f30dae969ea34b2cf11f8211f286e0b245b2a368111791bde0cefdf4f6256e6ca38d5b17a1c5f806be17c4ed637f967428f1@127.0.0.1:30303?discport=0" --rpcapi "eth,net,web3,personal,admin,shh,txpool,debug,miner" console
...
Welcome to the Geth JavaScript console!
instance: Geth/john/v1.8.23-stable-c9427004/linux-amd64/go1.10.4
modules: admin:1.0 debug:1.0 eth:1.0 ethash:1.0 miner:1.0 net:1.0 personal:1.0 rpc:1.0 txpool:1.0 web3:1.0
注意:
bootndoes
的值来链接节点01,后面跟着在节点01的控制台通过admin.nodeInfo.enode
得到的值。也可以先不设置bootnodes
,直接启动节点,进入命令行后通过admin.addPeer(enodeUrl)
来添加节点01,使其和节点01相连。
- 奇怪的是,自己使用上面的命令并没有成功,在通过
net.peerCount
查询连接的其他节点数时,发现仍然为0。就算重启节点01和节点02,仍然是0。于是只是单纯的启动节点02,然后admin.addPeer(enodeUrl)
来添加第一个节点01,操作成功!
$ geth --networkid 230 --datadir /home/hadoop/eth/private_eth2/ --identity "john" --rpc --rpcport "8888" --port "31000" --rpcaddr "192.168.1.120" --nodiscover --rpcapi "eth,net,web3,personal,admin,shh,txpool,debug,miner" console
...
> admin.addPeer("enode://7e4b2928c42d406686b28f406913f30dae969ea34b2cf11f8211f286e0b245b2a368111791bde0cefdf4f6256e6ca38d5b17a1c5f806be17c4ed637f967428f1@127.0.0.1:30303?discport=0")
true
// 节点同步信息
INFO [03-22|21:34:28.716] Block synchronisation started
INFO [03-22|21:34:28.735] Imported new state entries count=3 elapsed=116.216µs processed=3 pending=0 retry=0 duplicate=0 unexpected=0
INFO [03-22|21:34:30.342] Imported new block headers count=60 elapsed=1.605s number=60 hash=7b5d28…55462f age=1h32m16s
INFO [03-22|21:34:30.369] Imported new chain segment blocks=41 txs=0 mgas=0.000 elapsed=21.987ms mgasps=0.000 number=41 hash=d03157…a0cb43 age=2h49m57s cache=8.73kB
INFO [03-22|21:34:30.383] Imported new chain segment blocks=19 txs=2 mgas=0.042 elapsed=12.815ms mgasps=3.277 number=60 hash=7b5d28…55462f age=1h32m16s cache=16.58kB
INFO [03-22|21:34:31.755] Imported new block headers count=2 elapsed=10.793ms number=62 hash=f2b68b…48e201 age=1h32m15s
INFO [03-22|21:34:31.757] Imported new chain segment blocks=2 txs=0 mgas=0.000 elapsed=1.383ms mgasps=0.000 number=62 hash=f2b68b…48e201 age=1h32m15s cache=17.36kB
INFO [03-22|21:34:31.757] Fast sync complete, auto disabling
- 查看节点02的信息
> admin.nodeInfo
{
enode: "enode://5929c76f9e0b4ff07e14fdf94bbf6055fd63a97c47804194a10468c6e8d431d5a587110196032a71bf4da4c0e09f719d9442edf85ebe9076760347254fd74c55@127.0.0.1:31000?discport=0",
enr: "0xf88fb8406bbe9fd696c289c20b598327096791bd158c6285b923f7d85ffe1a158401badf61862d2d8440b02d35e6fda06be30fa954f8608683aacd62ec9826d326b3824f0183636170c6c5836574683f826964827634826970847f00000189736563703235366b31a1035929c76f9e0b4ff07e14fdf94bbf6055fd63a97c47804194a10468c6e8d431d583746370827918",
id: "cf7657cd11dbc0a476d61e4715d63f2a8e1549bb02d61e1c54282467df80276e",
ip: "127.0.0.1",
listenAddr: "[::]:31000",
name: "Geth/john/v1.8.23-stable-c9427004/linux-amd64/go1.10.4",
ports: {
discovery: 0,
listener: 31000
},
protocols: {
eth: {
config: {
chainId: 230,
eip150Hash: "0x0000000000000000000000000000000000000000000000000000000000000000",
eip155Block: 0,
eip158Block: 0,
homesteadBlock: 0
},
difficulty: 8313104,
genesis: "0x6c63bbf647549be8c653071e7e8c881edb10c8ec2729f3faa972f50741074e7d",
head: "0xf2b68bb76975981601e63fb2a1619a27a1b2e5efcf20c5790a3879cad948e201",
network: 230
}
}
}
3. 多节点信息的查看
- 在节点01和节点02均可执行命令,查询连接的其他节点的个数
> net.peerCount
1
- 在节点01和节点02均可执行命令,查询连接的其他节点列表
> admin.peers //节点01上执行的该命令
[{
caps: ["eth/62", "eth/63"],
enode: "enode://7e4b2928c42d406686b28f406913f30dae969ea34b2cf11f8211f286e0b245b2a368111791bde0cefdf4f6256e6ca38d5b17a1c5f806be17c4ed637f967428f1@127.0.0.1:30303?discport=0",
id: "626cbf32dae996ff507a75d62b757b0a421579a6b9fd721ed2b9bf1deb482c66",
name: "Geth/lucy/v1.8.23-stable-c9427004/linux-amd64/go1.10.4",
network: {
inbound: false,
localAddress: "127.0.0.1:47662",
remoteAddress: "127.0.0.1:30303",
static: true,
trusted: false
},
protocols: {
eth: {
difficulty: 8313104,
head: "0xf2b68bb76975981601e63fb2a1619a27a1b2e5efcf20c5790a3879cad948e201",
version: 63
}
}
}]
- 查询节点02中的区块数,发现已经与节点01同步,变为62:
> eth.blockNumber
62
4. 添加节点03到私有链网络中
- 初始化节点03、开启节点03与节点02的操作相同
- 但是在使用
admin.addPeer()
命令时,需要分别将节点01和节点02都添加为他的peer。
5. 多节点挖矿
- 我们会发现节点02和节点03,此时的账户数为0,即没有默认的账户。下面分别在节点02和节点03上创建两个新的账户。
//节点03的创建过程
> personal.newAccount("123456")
"0x0875b1d4a6461cc91ff2ea5f0d5d7462b6a3fc88"
> personal.newAccount("123456")
"0xfd69975429d4ade5c2e3b34aa31d7235d1f47e2f"
- 将节点03的
eth.accounts[1]
设为矿工账户,节点02默认将eth.accounts[0]
作为矿工账户(eth.coinbase
)。 - 同时开启节点01,节点02,节点03进行挖矿,使用的是配置超低的迷你主机,简直卡死了!其中节点03的挖矿信息如下:
> miner.start(1)
INFO [03-22|22:05:27.827] Updated mining threads threads=1
INFO [03-22|22:05:27.828] Transaction pool price threshold updated price=1000000000
null
> INFO [03-22|22:05:27.829] Commit new mining work number=63 sealhash=1c7535…6ca198 uncles=0 txs=0 gas=0 fees=0 elapsed=646.606µs
> INFO [03-22|22:08:55.962] Successfully sealed new block number=63 sealhash=1c7535…6ca198 hash=32cb43…14ebe0 elapsed=3m28.133s
INFO [03-22|22:08:55.962] ? mined potential block number=63 hash=32cb43…14ebe0
INFO [03-22|22:08:55.962] Commit new mining work number=64 sealhash=f90210…cbbc29 uncles=0 txs=0 gas=0 fees=0 elapsed=259.586µs
INFO [03-22|22:08:56.289] Imported new chain segment blocks=1 txs=0 mgas=0.000 elapsed=11.371ms mgasps=0.000 number=63 hash=91fba5…fe0a86 age=3m33s cache=18.70kB
INFO [03-22|22:08:56.289] Commit new mining work number=64 sealhash=e57d68…08abc4 uncles=1 txs=0 gas=0 fees=0 elapsed=292.541µs
//中间有很长的一段时间节点03都没有挖到矿,等到他挖到矿时,区块数已经从63变到了68
INFO [03-22|22:09:21.140] Imported new chain segment blocks=1 txs=0 mgas=0.000 elapsed=20.876ms mgasps=0.000 number=67 hash=66d1fa…10e41f cache=22.09kB
INFO [03-22|22:09:21.140] Commit new mining work number=68 sealhash=3fa390…4fe9e0 uncles=0 txs=0 gas=0 fees=0 elapsed=344.814µs
INFO [03-22|22:09:24.064] Successfully sealed new block number=68 sealhash=3fa390…4fe9e0 hash=5d84ad…856e55 elapsed=2.923s
INFO [03-22|22:09:24.064] ? mined potential block number=68 hash=5d84ad…856e55
INFO [03-22|22:09:24.065] Commit new mining work number=69 sealhash=3c22fd…a691d0 uncles=0 txs=0 gas=0 fees=0 elapsed=399.419µs
- 分别查询节点01,02,03的账户余额:
//节点01的账户余额
> web3.fromWei(eth.getBalance(eth.accounts[0]),"ether")
668.875
> web3.fromWei(eth.getBalance(eth.accounts[1]),"ether")
8
//节点02的账户余额
> web3.fromWei(eth.getBalance(eth.accounts[0]),"ether")
208.4375
> web3.fromWei(eth.getBalance(eth.accounts[1]),"ether")
0
//节点03的账户余额
> web3.fromWei(eth.getBalance(eth.accounts[0]),"ether")
0
> web3.fromWei(eth.getBalance(eth.accounts[1]),"ether")
315
注意: 这里出现了节点01和节点02中的账户余额不是5的整数倍,是因为有叔块
存在原因。叔块的相关概念将在下一篇博客中进行讲解。
- 节点01的eth.accounts[0]向节点03的eth.accounts[0]账户转账16个ether,分两次转账:
切记:转账操作只有在启动挖矿后才能生效,切记!!!!
//节点01解锁账户eth.accounts[0]
> personal.unlockAccount(eth.accounts[0],"123456",2000)
true
//节点03获取eth.accounts[0]的账户地址
> eth.accounts[0]
"0x0875b1d4a6461cc91ff2ea5f0d5d7462b6a3fc88"
//节点01中执行转账,第一次转账12个ether
> eth.sendTransaction({from:eth.accounts[0],to:"0x0875b1d4a6461cc91ff2ea5f0d5d7462b6a3fc88",value:web3.toWei(12,'ether')})
INFO [03-23|10:45:56.336] Setting new local account address=0x99BCfb3127A4181Ee5b1Ac0a32FFa016cdc10829
INFO [03-23|10:45:56.337] Submitted transaction fullhash=0x1f53ff24c0ac08bab1a1f519e073ae7a763011170fa0991d69eea5a9f10061c7 recipient=0x0875b1D4A6461CC91Ff2eA5F0D5d7462b6A3fc88
"0x1f53ff24c0ac08bab1a1f519e073ae7a763011170fa0991d69eea5a9f10061c7"
//第二次转账4个ether
> eth.sendTransaction({from:eth.accounts[0],to:"0x0875b1d4a6461cc91ff2ea5f0d5d7462b6a3fc88",value:web3.toWei(4,'ether')})
INFO [03-23|10:49:40.550] Submitted transaction fullhash=0xfe68a4384b6a4a95658ca334487b3f4cd79bcbd7120c49aacdce866fdc8e2714 recipient=0x0875b1D4A6461CC91Ff2eA5F0D5d7462b6A3fc88
"0xfe68a4384b6a4a95658ca334487b3f4cd79bcbd7120c49aacdce866fdc8e2714"
//节点02中查询当前待确认交易的信息,说明待打包的区块229中有两个交易,省略部分信息
> eth.getBlock("pending", true).transactions
[{
blockHash: "0xabdad70ada2ade7028a21ddd1031192a46463a4da868ddbcbc10c90a0bf2b289",
blockNumber: 229,
//这是节点01的eth.accounts[0]账户地址
from: "0x99bcfb3127a4181ee5b1ac0a32ffa016cdc10829",
...
nonce: 2,
...
//这是节点03的eth.accounts[0]账户地址
to: "0x0875b1d4a6461cc91ff2ea5f0d5d7462b6a3fc88",
transactionIndex: 0,
v: "0x1f0",
value: 12000000000000000000
}, {
blockHash: "0xabdad70ada2ade7028a21ddd1031192a46463a4da868ddbcbc10c90a0bf2b289",
blockNumber: 229,
//这是节点01的eth.accounts[0]账户地址
from: "0x99bcfb3127a4181ee5b1ac0a32ffa016cdc10829",
...
nonce: 3,
...
//这是节点03的eth.accounts[0]账户地址
to: "0x0875b1d4a6461cc91ff2ea5f0d5d7462b6a3fc88",
transactionIndex: 1,
v: "0x1ef",
value: 4000000000000000000
}]
> txpool.inspect.pending
{
0x99BCfb3127A4181Ee5b1Ac0a32FFa016cdc10829: {
2: "0x0875b1D4A6461CC91Ff2eA5F0D5d7462b6A3fc88: 12000000000000000000 wei + 90000 gas × 1000000000 wei",
3: "0x0875b1D4A6461CC91Ff2eA5F0D5d7462b6A3fc88: 4000000000000000000 wei + 90000 gas × 1000000000 wei"
}
}
//节点02和03同时挖矿,将交易打包
> miner.start(1)
...
// 停止挖矿,节点01上查看是否存在待确认的交易
> txpool.inspect.pending
{}
//节点02上查看区块229的信息,有些信息被省略,显示区块号和区块中的交易
> eth.getBlock(229)
{
difficulty: 134877,
...
number: 229,
...
//可以发现区块229中,包含发起的两个转账交易的交易号
transactions: ["0x1f53ff24c0ac08bab1a1f519e073ae7a763011170fa0991d69eea5a9f10061c7", "0xfe68a4384b6a4a95658ca334487b3f4cd79bcbd7120c49aacdce866fdc8e2714"],
...
}
//查看节点03的eth.accounts[0]账户余额是否变为16个ether
> web3.fromWei(eth.getBalance(eth.accounts[0]),"ether")
16
//查看节点01的eth.accounts[0]账户余额是否减少16个ether
> web3.fromWei(eth.getBalance(eth.accounts[0]),"ether")
652.874958