本文使用二级制版本Geth
在同一台机器上搭建两个节点的以太坊私有链。操作系统环境 :
Windows 10
这里参考官方文档 Installation instructions for Windows
Geth
版本 : Geth – Elasa (v1.9.6)geth-windows-amd64-1.9.6-bd059680.exe
,按照提示一步一步完成安装;geth version
,看到类似如下输出表明安装成功;:Geth
Version: 1.9.6-stable
Git Commit: bd05968077f27f7eb083404dd8448157996a8788
Git Commit Date: 20191003
Architecture: amd64
Protocol Versions: [63]
Network Id: 1
Go Version: go1.13
Operating System: windows
GOPATH=
GOROOT=C:\go
这一节我们会在同一台机器上一步一步搭建一个以太坊私有链,包含两个节点 :
在一个磁盘空间宽裕的位置创建一个目录用于保存我们的私有链数据,这里我使用的目录是 D:\ethereum\privatechain
(你可以根据自己的实际情况自己命名目录)。
注意 : 下文中我们简称该目录为
privatechain
。
进入目录privatechain
,创建json
文件genesis.json
内容如下 :
{
"config": {
"chainId": 20191101,
"homesteadBlock": 0,
"eip155Block": 0,
"eip158Block": 0
},
"alloc" : {},
"coinbase" : "0x0000000000000000000000000000000000000000",
"difficulty" : "0x20000",
"extraData" : "",
"gasLimit" : "0x2fefd8",
"nonce" : "0x0000000000000042",
"mixhash" : "0x0000000000000000000000000000000000000000000000000000000000000000",
"parentHash" : "0x0000000000000000000000000000000000000000000000000000000000000000",
"timestamp" : "0x00"
}
注意这里的
chainId
我指定为20191101
。
privatechain
下创建目录data0
用于保存第一个私有链节点的数据。cd privatechain
geth --datadir data0 init genesis.json
控制台输出如下 :
D:\ethereum\privatechain>geth --datadir data0 init genesis.json
INFO [11-01|10:19:21.875] Maximum peer count ETH=50 LES=0 total=50
INFO [11-01|10:19:21.938] Allocated cache and file handles database=D:\\ethereum\\privatechain\\data0\\geth\\chaindata cache=16.00MiB handles=16
INFO [11-01|10:19:22.009] Writing custom genesis block
INFO [11-01|10:19:22.012] Persisted trie from memory database nodes=0 size=0.00B time=0s gcnodes=0 gcsize=0.00B gctime=0s livenodes=1 livesize=0.00B
INFO [11-01|10:19:22.019] Successfully wrote genesis state database=chaindata hash=5e1fc7…d790e0
INFO [11-01|10:19:22.024] Allocated cache and file handles database=D:\\ethereum\\privatechain\\data0\\geth\\lightchaindata cache=16.00MiB handles=16
INFO [11-01|10:19:22.101] Writing custom genesis block
INFO [11-01|10:19:22.106] Persisted trie from memory database nodes=0 size=0.00B time=0s gcnodes=0 gcsize=0.00B gctime=0s livenodes=1 livesize=0.00B
INFO [11-01|10:19:22.118] Successfully wrote genesis state database=lightchaindata hash=5e1fc7…d790e0
看到控制台输出中的Successfully wrote genesis state
表明节点0初始化成功。
现在观察data0
目录结构,会发现它已经不再是空目录了,现在它的结构看起来如下所示 :
D:.
│ genesis.json
│
├─data0
│ ├─geth
│ │ ├─chaindata
│ │ │ 000001.log
│ │ │ CURRENT
│ │ │ LOCK
│ │ │ LOG
│ │ │ MANIFEST-000000
│ │ │
│ │ └─lightchaindata
│ │ 000001.log
│ │ CURRENT
│ │ LOCK
│ │ LOG
│ │ MANIFEST-000000
│ │
│ └─keystore
privatechain
下创建目录data1
用于保存第一个私有链节点的数据。cd privatechain
geth --datadir data1 init genesis.json
这里需要注意的是节点1和节点0数据的初始化使用了同一个创世区块,其目的是这样它们才能组成同一个私有链。
控制台输出如下 :
INFO [11-01|10:24:38.928] Maximum peer count ETH=50 LES=0 total=50
INFO [11-01|10:24:38.993] Allocated cache and file handles database=D:\\ethereum\\privatechain\\data1\\geth\\chaindata cache=16.00MiB handles=16
INFO [11-01|10:24:39.084] Writing custom genesis block
INFO [11-01|10:24:39.088] Persisted trie from memory database nodes=0 size=0.00B time=0s gcnodes=0 gcsize=0.00B gctime=0s livenodes=1 livesize=0.00B
INFO [11-01|10:24:39.101] Successfully wrote genesis state database=chaindata hash=5e1fc7…d790e0
INFO [11-01|10:24:39.111] Allocated cache and file handles database=D:\\ethereum\\privatechain\\data1\\geth\\lightchaindata cache=16.00MiB handles=16
INFO [11-01|10:24:39.194] Writing custom genesis block
INFO [11-01|10:24:39.204] Persisted trie from memory database nodes=0 size=0.00B time=0s gcnodes=0 gcsize=0.00B gctime=0s livenodes=1 livesize=0.00B
INFO [11-01|10:24:39.242] Successfully wrote genesis state database=lightchaindata hash=5e1fc7…d790e0
同样,看到控制台输出中的Successfully wrote genesis state
表明节点1初始化成功。
现在data0
目录和data1
目录都不再是空目录了,现在其结构如下 :
├─data0
│ ├─geth
│ │ ├─chaindata
│ │ │ 000001.log
│ │ │ CURRENT
│ │ │ LOCK
│ │ │ LOG
│ │ │ MANIFEST-000000
│ │ │
│ │ └─lightchaindata
│ │ 000001.log
│ │ CURRENT
│ │ LOCK
│ │ LOG
│ │ MANIFEST-000000
│ │
│ └─keystore
└─data1
├─geth
│ ├─chaindata
│ │ 000001.log
│ │ CURRENT
│ │ LOCK
│ │ LOG
│ │ MANIFEST-000000
│ │
│ └─lightchaindata
│ 000001.log
│ CURRENT
│ LOCK
│ LOG
│ MANIFEST-000000
│
└─keystore
现在同一台机器上的两个私有链节点的目录和数据我们已经初始化完成了,现在可以启动私有链了。不过接下来我们要做一些观察和验证,所以两个节点一个一个启动并顺带完成我们的任务 :
本节我们将仅仅启动包含一个节点的私有链,创建两个账户,并在它们之间做转账。
cd privatechain
geth --datadir data0 --networkid 20191101 console
注意以上参数中:
console
表明要进入交互式控制台;--datadir data0
表明要启动是节点0;--networkid 20191101
表明这个私有网络的网络id是20191101;
(网络 id 在连接其他节点时会用到,以太坊公网网络 id 为 1,为了避免与公有链网络冲突,私有链节点启动时要指定自己的网络 id)
控制台输出如下:
INFO [11-01|10:35:37.351] Maximum peer count ETH=50 LES=0 total=50
INFO [11-01|10:35:37.417] Starting peer-to-peer node instance=Geth/v1.9.6-stable-bd059680/windows-amd64/go1.13
INFO [11-01|10:35:37.421] Allocated trie memory caches clean=256.00MiB dirty=256.00MiB
INFO [11-01|10:35:37.425] Allocated cache and file handles database=D:\\ethereum\\privatechain\\data0\\geth\\chaindata cache=512.00MiB handles=8192
INFO [11-01|10:35:37.743] Opened ancient database database=D:\\ethereum\\privatechain\\data0\\geth\\chaindata\\ancient
INFO [11-01|10:35:37.768] Initialised chain configuration config="{ChainID: 20191101 Homestead: 0 DAO: DAOSupport: false EIP150: EIP155: 0 EIP158: 0 Byzantium: Constantinople: Petersburg: Istanbul: Engine: unknown}"
INFO [11-01|10:35:37.814] Disk storage enabled for ethash caches dir=D:\\ethereum\\privatechain\\data0\\geth\\ethash count=3
INFO [11-01|10:35:37.839] Disk storage enabled for ethash DAGs dir=C:\\Users\\andy_\\AppData\\Local\\Ethash count=2
INFO [11-01|10:35:37.862] Initialising Ethereum protocol versions=[63] network=20191101 dbversion=<nil>
WARN [11-01|10:35:37.873] Upgrade blockchain database version from=<nil> to=7
INFO [11-01|10:35:37.955] Loaded most recent local header number=0 hash=5e1fc7…d790e0 td=131072 age=50y6mo3w
INFO [11-01|10:35:37.961] Loaded most recent local full block number=0 hash=5e1fc7…d790e0 td=131072 age=50y6mo3w
INFO [11-01|10:35:37.967] Loaded most recent local fast block number=0 hash=5e1fc7…d790e0 td=131072 age=50y6mo3w
INFO [11-01|10:35:37.973] Regenerated local transaction journal transactions=0 accounts=0
INFO [11-01|10:35:38.016] Allocated fast sync bloom size=512.00MiB
INFO [11-01|10:35:38.021] Initialized fast sync bloom items=0 errorrate=0.000 elapsed=0s
INFO [11-01|10:35:38.078] New local node record seq=1 id=5f41aa2d19202b7a ip=127.0.0.1 udp=30303 tcp=30303
INFO [11-01|10:35:38.085] Started P2P networking self=enode://c05ffa7d768dce4c2b4e3c19ca297b3e567b1f52df2e70e84ba1ffe7dd9673345a88027f266a1277bcc7f30286436dd4f02476246b07cf166040e67b64f8a2ac@127.0.0.1:30303
INFO [11-01|10:35:38.087] IPC endpoint opened url=\\\\.\\pipe\\geth.ipc
WARN [11-01|10:35:38.178] Served eth_coinbase reqid=3 t=0s err="etherbase must be explicitly specified"
Welcome to the Geth JavaScript console!
instance: Geth/v1.9.6-stable-bd059680/windows-amd64/go1.13
at block: 0 (Thu, 01 Jan 1970 08:00:00 CST)
datadir: D:\ethereum\privatechain\data0
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
>
这里我们看到了字样Welcome to the Geth JavaScript console!
,这说明节点0启动成功了。此时你可以认为一个以太坊私有链网络也已经启动了,只不过它只包含了一个节点,也就是我们所准备的节点0。
现在我们通过控制台在节点0上做一些观察和验证操作。
Geth JavaScript console
控制台提供了如下几种管理对象 :
eth
:区块链相关操作
net
:查看 P2P 网络状态
admin
:管理节点
miner
:启动 & 停止挖矿
personal
:管理账户
txpool
:查看交易内存池
web3
:单位换算等
首先,我们新建的私有链上应该是没有账户的;
通过如下命令可以验证 :
> eth.accounts
[]
接下来,我们创建第一个账户;
> personal.newAccount()
控制台交互输出如下 :
Password:
Repeat password:
INFO [11-01|10:50:25.858] Your new key was generated address=0x0C5Ae7c2520b1208d579bCF8b2bF624EdD7a025c
WARN [11-01|10:50:25.862] Please backup your key file! path=D:\\ethereum\\privatechain\\data0\\keystore\\UTC--2019-11-01T02-50-24.454154200Z--0c5ae7c2520b1208d579bcf8b2bf624edd7a025c
WARN [11-01|10:50:25.870] Please remember your password!
"0x0c5ae7c2520b1208d579bcf8b2bf624edd7a025c"
从上面的输出可见,我们创建的账号是 : 0x0c5ae7c2520b1208d579bcf8b2bf624edd7a025c
,密钥文件保存在文件D:\\ethereum\\privatechain\\data0\\keystore\\UTC--2019-11-01T02-50-24.454154200Z--0c5ae7c2520b1208d579bcf8b2bf624edd7a025c
。
为了方便起见,本文中所创建的以太坊私有链账户的密码统一使用
password
。
此时再通过eth.accounts
查看账户列表,结果输出如下 :
> eth.accounts
["0x0c5ae7c2520b1208d579bcf8b2bf624edd7a025c"]
接下来,我们创建第二个账户;
这里创建第二个账户,使用的方法跟创建第一个账户是相同的,使用personal.newAccount()
,这里不再重复。第二个账号创建完成之后,我们再看账户列表,输出如下 :
> eth.accounts
["0x0c5ae7c2520b1208d579bcf8b2bf624edd7a025c", "0xfb66cc211031fe8ae48acfed7a199d8d9038d978"]
这里所创建的第二个账号是0xfb66cc211031fe8ae48acfed7a199d8d9038d978
。
接下来,我们查看两个账户的余额;
> eth.getBalance(eth.accounts[0])
0
> eth.getBalance(eth.accounts[1])
0
>
查询账户余额使用的方法是
eth.getBalance()
。
很显然,因为是新账户,所以其余额都是 0。要使账户有余额,可以从其他账户转账过来,或者通过挖矿来获取奖励。我们目前是只有一个节点的新建私有链,所有账户都没有余额,所以要想账户中有余额,只能通过挖矿获取奖励。
通过 miner.start ()
来启动挖矿:
js miner.start()
第一次启动挖矿会先生成挖矿所需的 DAG
文件,这个过程有点慢,等进度达到 100%
后,就会开始挖矿,此时控制台会不断输出挖矿信息。该命令控制台输出大致如下 :
> miner.start()
INFO [11-01|11:07:01.068] Updated mining threads threads=8
INFO [11-01|11:07:01.071] Transaction pool price threshold updated price=1000000000
INFO [11-01|11:07:01.074] Etherbase automatically configured address=0x0C5Ae7c2520b1208d579bCF8b2bF624EdD7a025c
null
> INFO [11-01|11:07:01.093] Commit new mining work number=1 sealhash=a65bf2…04103e uncles=0 txs=0 gas=0 fees=0 elapsed=13.151ms
INFO [11-01|11:07:02.301] Generating DAG in progress epoch=0 percentage=0 elapsed=656.222ms
INFO [11-01|11:07:03.041] Generating DAG in progress epoch=0 percentage=1 elapsed=1.396s
// 这里为了便于阅读,删除了部分 DAG 生成过程的输出 ...
INFO [11-01|11:08:11.552] Generating DAG in progress epoch=0 percentage=99 elapsed=1m9.906s
INFO [11-01|11:08:11.559] Generated ethash verification cache epoch=0 elapsed=1m9.913s
INFO [11-01|11:08:27.440] Successfully sealed new block number=1 sealhash=a65bf2…04103e hash=d2cf12…d3024c elapsed=1m26.359s
INFO [11-01|11:08:27.463] mined potential block number=1 hash=d2cf12…d3024c
INFO [11-01|11:08:27.473] Commit new mining work number=2 sealhash=4f491d…d28143 uncles=0 txs=0 gas=0 fees=0 elapsed=9.973ms
INFO [11-01|11:08:27.605] Successfully sealed new block number=2 sealhash=4f491d…d28143 hash=3e79ae…7edb93 elapsed=142.618ms
INFO [11-01|11:08:27.610] mined potential block number=2 hash=3e79ae…7edb93
INFO [11-01|11:08:27.624] Commit new mining work number=3 sealhash=3c1731…64c50f uncles=0 txs=0 gas=0 fees=0 elapsed=13.962ms
INFO [11-01|11:08:27.848] Successfully sealed new block number=3 sealhash=3c1731…64c50f hash=22caae…fca7f8 elapsed=237.366ms
INFO [11-01|11:08:27.853] mined potential block number=3 hash=22caae…fca7f8
INFO [11-01|11:08:27.853] Mining too far in the future wait=2s
INFO [11-01|11:08:29.862] Commit new mining work number=4 sealhash=a5a106…024c01 uncles=0 txs=0 gas=0 fees=0 elapsed=2.009s
INFO [11-01|11:08:29.871] Successfully sealed new block number=4 sealhash=a5a106…024c01 hash=0cc77b…4a363b elapsed=8.956ms
一旦开始挖矿,可以通过在控制台输入miner.stop()
停止挖矿。这里需要注意的是,因为该命令输入时,挖矿正在进行,所以该命令的显示会不断被挖矿输出打扰。不过不用担心,只要确保正确输入该命令并回车即可停止挖矿。
挖矿运行一段时间之后,我们停止挖矿,来看看挖矿的效果。
挖到一个区块会奖励5个以太币,挖矿奖励会进入矿工的账户,该账户叫做 coinbase
,默认情况下 coinbase
是本节点账户中的第一个账户:
> eth.coinbase
"0x0c5ae7c2520b1208d579bcf8b2bf624edd7a025c" // 这里显示是我们上面所创建的第一个账户
矿工账户默认是本节点账户的第一个,但是也可以设置为其他的某个账户,相应命令
miner.setEtherbase
。
现在我们看看矿工账户,也就是第一个账户的余额情况 :
> eth.getBalance(eth.accounts[0])
580000000000000000000
>
由此可见,经过一段时间的挖矿,矿工账号的余额已经不再是0了,相应的挖矿奖励已经进入到了该账户中。不过eth.getBalance()
方法返回的单位是wei
,而不是以太币(ether)
,我们通过单位换算方法看看矿工到底获得了多少奖励:
> web3.fromWei(eth.getBalance(eth.accounts[0]),'ether')
580
>
注意 :
wei
/ether
之间的换算关系 :1 ether = 10的18次方 个 wei
现在第一个账户作为矿工账户得到了以太币奖励,而第二个账户余额还是为0。现在我们观察一个从账户0到账户1的转账动作。
转账之前,我们需要解锁转出账户,在我们这里例子里面,就是解锁第一个账户(索引为0),否则转账会失败 :
> personal.unlockAccount(eth.accounts[0]) // 解锁账户命令行
Unlock account 0x0c5ae7c2520b1208d579bcf8b2bf624edd7a025c
Password: // 这里输入该账户的密码
true // true 表示解锁成功
>
现在执行转账 : 账户0 转账到 账户1 10 个 ether
:
> amount = web3.toWei(10,'ether') // 定义一个变量 amount表示将要转账的金额:10 ether
"10000000000000000000"
> eth.sendTransaction({from:eth.accounts[0],to:eth.accounts[1],value:amount}) // 发起转账
INFO [11-01|11:32:35.037] Setting new local account address=0x0C5Ae7c2520b1208d579bCF8b2bF624EdD7a025c
INFO [11-01|11:32:35.041] Submitted transaction fullhash=0x7a9c536af0c8cc28219d378396a66f4e420b690dac8d28c70513bb3168714f7d recipient=0xFb66cc211031fE8AE48AcfED7a199D8d9038D978
"0x7a9c536af0c8cc28219d378396a66f4e420b690dac8d28c70513bb3168714f7d"
>
现在我们看账户1里面的余额:
> eth.getBalance(eth.accounts[1])
0
居然还是0。看起来上面的转账并未成功。确实是这样,因为此交易已经被提交到了区块链,但是因为没有矿工在工作,所以此交易并未被处理,所以转账尚未完成。现在,我们通过txpool
验证一下这个情况:
> txpool.status
{
pending: 1, // 一个交易处于悬挂状态
queued: 0
}
接下来我们启动矿工挖矿,让这个交易被处理:
> miner.start(1);admin.sleepBlocks(1);miner.stop(); // 使用一个线程启动挖矿,在一个区块被挖到后停止挖矿
INFO [11-01|11:47:32.582] Updated mining threads threads=1
INFO [11-01|11:47:32.601] Transaction pool price threshold updated price=1000000000
INFO [11-01|11:47:32.616] Commit new mining work number=117 sealhash=b14634…97d03c uncles=0 txs=0 gas=0 fees=0 elapsed=0s
INFO [11-01|11:47:32.633] Commit new mining work number=117 sealhash=d3be56…a329d7 uncles=0 txs=1 gas=21000 fees=2.1e-05 elapsed=16.955ms
INFO [11-01|11:47:33.310] Successfully sealed new block number=117 sealhash=d3be56…a329d7 hash=5f2525…c3ecc7 elapsed=677.208ms
INFO [11-01|11:47:33.317] block reached canonical chain number=110 hash=1ca8a9…58784c
INFO [11-01|11:47:33.323] mined potential block number=117 hash=5f2525…c3ecc7
INFO [11-01|11:47:33.328] Commit new mining work number=118 sealhash=701c7e…d51321 uncles=0 txs=0 gas=0 fees=0 elapsed=10.953ms
null
现在我们再来看当前的各种状态 :
> txpool.status
{
pending: 0, // 这里表明上面提交的交易已经完成
queued: 0
}
> web3.fromWei(eth.getBalance(eth.accounts[1]),'ether')
10 // 这里表明提交的转账交易已经完成,收款方已经收到10个ether
> web3.fromWei(eth.getBalance(eth.accounts[0]),'ether')
575 // 转出方10个ether已经扣除,不过作为矿工,又被刚才的挖矿动作奖励了5个ether
> eth.blockNumber
117 // 每个区块奖励5ether,117对应585个either,账户0中575个,账户1中10个
到此为止,我们在同一个私有链节点内转账有关的观察任务就算是完成了。接下来,我们看两个节点的私有链的情况。
目前我们已经有了一个私有链,包含一个启动的节点,也就是上面使用的节点:节点0。
现在我们打开一个新的命令行来启动我们最开始所准备的第二个节点:节点1。
因为节点0已经使用了默认端口30303
,所以第二个节点我们使用了一个不一样的端口30305
:
geth --datadir data1 --networkid 20191101 console --port 30305 --ipcdisable
类似地,我们在节点1上创建两个账号,如下 :
> eth.accounts
["0x717f9c974a3fe520cd6c258fa87b14eccb07a74c", "0xf91a6b107291a4271a2196562dd31dcb33c30119"]
到目前为止,我们有了一个如下的一个私有链 :
0x0c5ae7c2520b1208d579bcf8b2bf624edd7a025c
(矿工账号)
ether
0xfb66cc211031fe8ae48acfed7a199d8d9038d978
ether
0x717f9c974a3fe520cd6c258fa87b14eccb07a74c
(矿工账号)
ether
0xf91a6b107291a4271a2196562dd31dcb33c30119
ether
在第一个节点中查看自己的节点信息 :
> admin.nodeInfo.enode
"enode://c05ffa7d768dce4c2b4e3c19ca297b3e567b1f52df2e70e84ba1ffe7dd9673345a88027f266a1277bcc7f30286436dd4f02476246b07cf166040e67b64f8a2ac@127.0.0.1:30303"
在第二个节点上将第一个节点添加为自己的对等节点:
> admin.addPeer("enode://c05ffa7d768dce4c2b4e3c19ca297b3e567b1f52df2e70e84ba1ffe7dd9673345a88027f266a1277bcc7f30286436dd4f02476246b07cf166040e67b64f8a2ac@127.0.0.1:30303")
true
> admin.peers
[{
caps: ["eth/63"],
enode: "enode://c05ffa7d768dce4c2b4e3c19ca297b3e567b1f52df2e70e84ba1ffe7dd9673345a88027f266a1277bcc7f30286436dd4f02476246b07cf166040e67b64f8a2ac@127.0.0.1:30303",
id: "5f41aa2d19202b7a296edcaa2e20df52c9713bbabf58149461d44817e635e32a",
name: "Geth/v1.9.6-stable-bd059680/windows-amd64/go1.13",
network: {
inbound: false,
localAddress: "127.0.0.1:61622",
remoteAddress: "127.0.0.1:30303",
static: true,
trusted: false
},
protocols: {
eth: {
difficulty: 15891698,
head: "0x5f2525d836d9a5a7f37c9815cbae8906f1604b573d25742d81e41067c4c3ecc7",
version: 63
}
}
}]
>
通过上面输出我们可以看到,两个节点已经同一个私有链上互通了。
现在我们尝试从节点0上的账号1向节点1上的账号1转账8 ether
,并且该任务让节点1上的矿工完成 。
首先,从节点0上发起转账 :
> amount8 = web3.toWei(8,'ether')
"8000000000000000000"
> eth.getBalance("0xfb66cc211031fe8ae48acfed7a199d8d9038d978") // 节点0账号1转帐前余额
10000000000000000000
> eth.getBalance("0xf91a6b107291a4271a2196562dd31dcb33c30119") // 节点1账号1转帐前余额
0
> eth.sendTransaction({from:"0xfb66cc211031fe8ae48acfed7a199d8d9038d978",to:"0xf91a6b107291a4271a2196562dd31dcb33c30119",value:amount8}) // 发起转账
INFO [11-01|15:04:50.782] Setting new local account address=0xFb66cc211031fE8AE48AcfED7a199D8d9038D978
INFO [11-01|15:04:50.786] Submitted transaction fullhash=0x140784348c1baeb00d4c7b622d17884e21a56c2b4337d2bc1a93140e2e13fe44 recipient=0xF91A6B107291a4271a2196562DD31Dcb33C30119
"0x140784348c1baeb00d4c7b622d17884e21a56c2b4337d2bc1a93140e2e13fe44"
> txpool.status
{
pending: 1,
queued: 0
}
接下来,我们从节点1上开启挖矿 :
> miner.start(1);admin.sleepBlocks(1);miner.stop(); // 使用一个线程启动挖矿,在一个区块被挖到后停止挖矿
INFO [11-01|15:06:17.236] Updated mining threads threads=1
INFO [11-01|15:06:17.239] Transaction pool price threshold updated price=1000000000
INFO [11-01|15:06:17.242] block lost number=1 hash=988aff…3518ae
INFO [11-01|15:06:17.247] Commit new mining work number=118 sealhash=147484…a20630 uncles=0 txs=0 gas=0 fees=0 elapsed=4.985ms
INFO [11-01|15:06:17.254] Commit new mining work number=118 sealhash=46f768…ef2f47 uncles=0 txs=1 gas=21000 fees=2.1e-05 elapsed=11.967ms
INFO [11-01|15:06:25.744] Successfully sealed new block number=118 sealhash=46f768…ef2f47 hash=1176cd…765bd8 elapsed=8.490s
INFO [11-01|15:06:25.751] mined potential block number=118 hash=1176cd…765bd8
INFO [11-01|15:06:25.756] Commit new mining work number=119 sealhash=b50c09…2e3e35 uncles=0 txs=0 gas=0 fees=0 elapsed=4.987ms
null
>
然后,我们再从节点1控制台上观察相关账号的余额:
> web3.fromWei(eth.getBalance("0xfb66cc211031fe8ae48acfed7a199d8d9038d978"),'ether') // 节点0账号1转帐后余额
1.999979
> web3.fromWei(eth.getBalance("0xf91a6b107291a4271a2196562dd31dcb33c30119"),'ether') // 节点1账号1转帐后余额
8
>web3.fromWei(eth.getBalance("0x717f9c974a3fe520cd6c258fa87b14eccb07a74c"),'ether') // 节点1账号0挖矿后余额
5.000021
这里,我们梳理一下转账过程中的要点信息 :
然后基于此,转账成功后,最终结果是 :
从上面节点0上的账号1向节点1上的账号1之间的转账命令来看,和同一节点上两个账户直接的转账并无不同。以上内容将同节点账户转账和跨节点账户之间转账分开的目的只是为了逐步深入熟悉以太坊私有链的工作模式。