搭建私有链并进行挖矿和交易
创世区块的配置
搭建私有链首先需要指定创世区块的配置,此文件就是一个内容格式为json的文本文件。 我们可以将创世区块 genesis.json
的配置如下:1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17{
"alloc": {},
"config": {
"chainID": 72,
"homesteadBlock": 0,
"eip155Block": 0,
"eip158Block": 0
},
"nonce": "0x0000000000000000",
"difficulty": "0x4000",
"mixhash": "0x0000000000000000000000000000000000000000000000000000000000000000",
"coinbase": "0x0000000000000000000000000000000000000000",
"timestamp": "0x00",
"parentHash": "0x0000000000000000000000000000000000000000000000000000000000000000",
"extraData": "0x11bbe8db4e347b4e8c937c1c8370e4b5ed33adb3db69cbdb7a38e1e50b1b82fa",
"gasLimit": "0xffffffff"
}
配置项简介:
alloc
: 用来预置账号以及账号的以太币数量,因为私有链挖矿比较容易,所以不需要预置有币的账号,需要的时候自己创建即可以。nonce
: 一个64位随机数,用于挖矿,和mixhash的设置需要满足以太坊的Yellow paper, 4.3.4.Block Header Validity (44)章节所描述的条件。difficulty
: 设置计算区块的难度,如果数值过大,挖矿时间较长,在测试环境为节省算力和等带时间可设置较小值。mixhash
: 与nonce配合用于挖矿,由上一个区块的一部分生成的hash。和nonce的设置需要满足以太坊的Yellow paper, 4.3.4. Block Header Validity, (44)章节所描述的条件。coinbase
: 矿工账号,随便填写。timestamp
: 设置创世块的时间戳。parentHash
: 上一个区块的hash值,因为是创世块,所以这个值是0。extraData
: 附加信息,随便填,可以填你的个性信息,必须为十六进制的字符串。gasLimit
: 该值设置对GAS的消耗总量限制,用来限制区块能包含的交易信息总和,因为是私有链,所以填最大。
初始化创世块
通过以下命名初始化创世区块:
1 | geth --datadir ./private_chain_data_1/ init genesis.json |
得到日志如下:1
2
3
4
5
6
7
8
9INFO [03-07|21:02:11] Maximum peer count ETH=25 LES=0 total=25
INFO [03-07|21:02:11] Allocated cache and file handles database=/home/wangy/ethereum/private_chain/private_chain_data_1/geth/chaindata cache=16 handles=16
INFO [03-07|21:02:11] Writing custom genesis block
INFO [03-07|21:02:11] Persisted trie from memory database nodes=0 size=0.00B time=52.906µs gcnodes=0 gcsize=0.00B gctime=0s livenodes=1 livesize=0.00B
INFO [03-07|21:02:11] Successfully wrote genesis state database=chaindata hash=942f59…a2588a
INFO [03-07|21:02:11] Allocated cache and file handles database=/home/wangy/ethereum/private_chain/private_chain_data_1/geth/lightchaindata cache=16 handles=16
INFO [03-07|21:02:11] Writing custom genesis block
INFO [03-07|21:02:11] Persisted trie from memory database nodes=0 size=0.00B time=1.416µs gcnodes=0 gcsize=0.00B gctime=0s livenodes=1 livesize=0.00B
INFO [03-07|21:02:11] Successfully wrote genesis state database=lightchaindata hash=942f59…a2588a
私有链初始化完成.
启动并进入控制台
通过指定datadir
来启动节点:1
geth --datadir ./private_chain_data_1/ --networkid 88 --nodiscover console
geth
参数说明:
networkid
指定网路ID,确保不适用1-4。nodiscover
此参数确保geth不去寻找peers,主要是为了严格控制联盟链连入的节点。identity
: 区块链的标示,随便填写,用于标示目前网络的名字init
: 指定创世块文件的位置,并创建初始块datadir
: 设置当前区块链网络数据存放的位置port
: 网络监听端口rpc
: 启动rpc通信,可以进行智能合约的部署和调试rpcapi
: 设置允许连接的rpc的客户端,一般为db,eth,net,web3console
: 启动命令行模式,可以在Geth中执行命令
节点启动后, 得到日志如下:1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20INFO [03-07|21:08:40] Maximum peer count ETH=25 LES=0 total=25
INFO [03-07|21:08:40] Starting peer-to-peer node instance=Geth/v1.8.2-stable/linux-amd64/go1.8.3
INFO [03-07|21:08:40] Allocated cache and file handles database=/home/wangy/ethereum/private_chain/private_chain_data_1/geth/chaindata cache=768 handles=512
WARN [03-07|21:08:40] Upgrading database to use lookup entries
INFO [03-07|21:08:40] Initialised chain configuration config="{ChainID: 72 Homestead: 0 DAO: <nil> DAOSupport: false EIP150: <nil> EIP155: 0 EIP158: 0 Byzantium: <nil> Constantinople: <nil> Engine: unknown}"
INFO [03-07|21:08:40] Disk storage enabled for ethash caches dir=/home/wangy/ethereum/private_chain/private_chain_data_1/geth/ethash count=3
INFO [03-07|21:08:40] Disk storage enabled for ethash DAGs dir=/home/wangy/.ethash count=2
INFO [03-07|21:08:40] Initialising Ethereum protocol versions="[63 62]" network=88
INFO [03-07|21:08:40] Loaded most recent local header number=0 hash=942f59…a2588a td=16384
INFO [03-07|21:08:40] Loaded most recent local full block number=0 hash=942f59…a2588a td=16384
INFO [03-07|21:08:40] Loaded most recent local fast block number=0 hash=942f59…a2588a td=16384
INFO [03-07|21:08:40] Regenerated local transaction journal transactions=0 accounts=0
INFO [03-07|21:08:40] Starting P2P networking
INFO [03-07|21:08:40] Database deduplication successful deduped=0
INFO [03-07|21:08:40] RLPx listener up self="enode://b41177a956e39a36f77bb73b857688d3c27989a259a8820559d1efa81e8952b70280bfa91419acd7e93f2ccff5bcdb298f400bc384b6e3ce3fbf2a0952bb060b@[::]:30303?discport=0"
INFO [03-07|21:08:40] IPC endpoint opened url=/home/wangy/ethereum/private_chain/private_chain_data_1/geth.ipc
Welcome to the Geth JavaScript console!
instance: Geth/v1.8.2-stable/linux-amd64/go1.8.3
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
通过日志可以发现这个节点启用的是默认端口为 30303
.
这是一个交互式的Javascript执行环境,在这里面可以执行Javascript方法. 对象主要包括:
eth
: 包含一些跟操作区块链相关的方法net
: 包含以下查看p2p网络状态的方法admin
: 包含一些与管理节点相关的方法miner
: 包含启动&停止挖矿的一些方法personal
: 主要包含一些管理账户的方法txpool
: 包含一些查看交易内存池的方法web3
: 包含了以上对象,还包含一些单位换算的方法
配置帐号
上一步的日志说 No etherbase set and no accounts found as default
, 那么我们接着创建一个密码为password的帐号:1
2
3
4
5
6
7
8
9> personal.listAccounts
[]
>
> personal.newAccount("password")
"0x1a36a03932e3b73292df56b6493058425e518857"
>
> personal.listAccounts
["0x1a36a03932e3b73292df56b6493058425e518857"]
>
查看账户余额:1
2> web3.fromWei(eth.getBalance(eth.coinbase), "ether")
0
查看钱包信息:1
2
3
4
5
6
7
8
9> personal.listWallets
[{
accounts: [{
address: "0x1a36a03932e3b73292df56b6493058425e518857",
url: "keystore:///home/wangy/ethereum/private_chain/private_chain_data_1/keystore/UTC--2018-03-08T05-16-25.359680161Z--1a36a03932e3b73292df56b6493058425e518857"
}],
status: "Locked",
url: "keystore:///home/wangy/ethereum/private_chain/private_chain_data_1/keystore/UTC--2018-03-08T05-16-25.359680161Z--1a36a03932e3b73292df56b6493058425e518857"
}]
挖矿
帐号创建成功以后, 我们就可以通过 miner.start()
来开始挖矿了. 命令启动后, 得到日志如下:1
2
3
4
5
6
7
8
9
10
11
12
13
14> miner.start()
INFO [03-07|21:58:20] Updated mining threads threads=0
INFO [03-07|21:58:20] Transaction pool price threshold updated price=18000000000
null
INFO [03-07|21:58:20] Starting mining operation
INFO [03-07|21:58:20] Commit new mining work number=1 txs=0 uncles=0 elapsed=231.751µs
INFO [03-07|21:58:28] Generating DAG in progress epoch=1 percentage=0 elapsed=4.904s
INFO [03-07|21:58:33] Generating DAG in progress epoch=1 percentage=1 elapsed=10.359s
INFO [03-07|21:58:39] Generating DAG in progress epoch=1 percentage=2 elapsed=15.923s
INFO [03-07|21:58:44] Generating DAG in progress epoch=1 percentage=3 elapsed=21.394s
INFO [03-07|21:58:50] Generating DAG in progress epoch=1 percentage=4 elapsed=26.783s
INFO [03-07|21:58:56] Generating DAG in progress epoch=1 percentage=5 elapsed=33.166s
INFO [03-07|21:59:01] Generating DAG in progress epoch=1 percentage=6 elapsed=38.682s
...
注意看 percentage
, 这个时候你还没有开始挖矿哦, 在做挖矿准备工作. 只有在percentage
变成了100%之后, 才可以挖到矿的. 如下, 只有到了 Generated ethash verification cache
才算整整开始挖矿. Successfully sealed new block
才是挖到矿了哦1
2
3
4
5
6
7
8
9
10
11
12
13INFO [03-07|22:07:26] Generating DAG in progress epoch=1 percentage=97 elapsed=9m2.944s
INFO [03-07|22:07:31] Generating DAG in progress epoch=1 percentage=98 elapsed=9m8.134s
INFO [03-07|22:07:37] Generating DAG in progress epoch=1 percentage=99 elapsed=9m13.969s
INFO [03-07|22:07:37] Generated ethash verification cache epoch=1 elapsed=9m13.972s
INFO [03-07|22:14:22] Successfully sealed new block number=1 hash=d26e3e…f6662f
INFO [03-07|22:14:22] 🔨 mined potential block number=1 hash=d26e3e…f6662f
INFO [03-07|22:14:22] Commit new mining work number=2 txs=0 uncles=0 elapsed=174.575µs
INFO [03-07|22:15:00] Successfully sealed new block number=2 hash=1e4192…1f9e6e
INFO [03-07|22:15:00] 🔨 mined potential block number=2 hash=1e4192…1f9e6e
INFO [03-07|22:15:00] Commit new mining work number=3 txs=0 uncles=0 elapsed=119.383µs
INFO [03-07|22:15:05] Successfully sealed new block number=3 hash=2f8d08…47177a
INFO [03-07|22:15:05] 🔨 mined potential block number=3 hash=2f8d08…47177a
INFO [03-07|22:15:05] Commit new mining work number=4 txs=0 uncles=0 elapsed=103.057µs
中途可以通过 miner.stop()
命令可以停止挖矿. 注意: 输入的字符会被挖矿刷屏信息冲掉,没有关系,只要输入完整的 miner.stop()
之后回车,即可停止挖矿。
检查账户余额:
1
2> eth.getBalance(eth.coinbase)
15000000000000000000
挖矿成功.
交易
新建一个帐号用于交易:
1 | > personal.newAccount("password1") |
尝试产生交易
1 | eth.sendTransaction({from:'0x1a36a03932e3b73292df56b6493058425e518857',to:'0x2ed11e9f064572d2f2f651e4d7c3824f0b949022',value:5}) |
Error: authentication needed: password or unlock
at web3.js:3143:20
at web3.js:6347:15
at web3.js:5081:36
at:1:1
通过 personal.listWallets
命令可以发现掌勺是Locked
状态1
2
3
4
5
6
7
8
9
10
11
12
13
14
15[{
accounts: [{
address: "0x1a36a03932e3b73292df56b6493058425e518857",
url: "keystore:///home/wangy/ethereum/private_chain/private_chain_data_1/keystore/UTC--2018-03-08T05-16-25.359680161Z--1a36a03932e3b73292df56b6493058425e518857"
}],
status: "Locked",
url: "keystore:///home/wangy/ethereum/private_chain/private_chain_data_1/keystore/UTC--2018-03-08T05-16-25.359680161Z--1a36a03932e3b73292df56b6493058425e518857"
}, {
accounts: [{
address: "0x2ed11e9f064572d2f2f651e4d7c3824f0b949022",
url: "keystore:///home/wangy/ethereum/private_chain/private_chain_data_1/keystore/UTC--2018-03-08T07-23-58.161695617Z--2ed11e9f064572d2f2f651e4d7c3824f0b949022"
}],
status: "Locked",
url: "keystore:///home/wangy/ethereum/private_chain/private_chain_data_1/keystore/UTC--2018-03-08T07-23-58.161695617Z--2ed11e9f064572d2f2f651e4d7c3824f0b949022"
}]
以太坊的保护机制,每隔一段时间帐户就会自动锁定,这个时候任何以太币在账户之间的转换都会被拒绝,除非把该账户解锁
解锁帐号:
1 | > personal.unlockAccount('0x1a36a03932e3b73292df56b6493058425e518857') |
输入密码password
, 确认解锁帐号.
重新开始交易
1 | eth.sendTransaction({from:'0x1a36a03932e3b73292df56b6493058425e518857',to:'0x2ed11e9f064572d2f2f651e4d7c3824f0b949022',value:5}) |
交易成功. 查看账户余额:1
2
3
4> eth.getBalance('0x1a36a03932e3b73292df56b6493058425e518857')
15000000000000000000
> eth.getBalance('0x2ed11e9f064572d2f2f651e4d7c3824f0b949022')
0
交易已完成, 怎么两个账户的余额没有发生变化呢?
查看交易池状态 txpool.status
:1
2
3
4
5> txpool.status
{
pending: 1,
queued: 0
}
这笔交易还处于pending状态. 原来以太链上的交易是由矿工来完成的, 没有矿工, 以太链上的所有操作都是无法完成的.
矿工完成交易操作
让矿工开工 miner.start()
.1
2
3
4
5
6
7INFO [03-07|23:58:14] Transaction pool price threshold updated price=18000000000
null
> INFO [03-07|23:58:14] Starting mining operation
INFO [03-07|23:58:14] Commit new mining work number=4 txs=1 uncles=0 elapsed=352.367µs
INFO [03-07|23:58:57] Successfully sealed new block number=4 hash=62e46c…53ce76
INFO [03-07|23:58:57] 🔨 mined potential block number=4 hash=62e46c…53ce76
INFO [03-07|23:58:57] Commit new mining work number=5 txs=0 uncles=0 elapsed=1.954ms
查验交易状态
1 | # 1. 检查交易池 |
转账成功.
gas
问题
给帐号2充值
1
2
3> eth.sendTransaction({from:'0x1a36a03932e3b73292df56b6493058425e518857',to:'0x2935155a6980bad50a87a29b31c69adb9065cdba',value: 29999999999999999995})
INFO [03-08|00:20:51] Submitted transaction fullhash=0x70bbeee1f047ae71d02888b75e64d02a1f5dbba2153ffd13489844b94dca99db recipient=0x2935155a6980BAd50A87a29b31C69adb9065cdbA
"0x70bbeee1f047ae71d02888b75e64d02a1f5dbba2153ffd13489844b94dca99db"矿工完成交易后, 查看余额:
1
2
3
4
5> eth.getBalance('0x2ed11e9f064572d2f2f651e4d7c3824f0b949022')
5
> eth.getBalance('0x2935155a6980bad50a87a29b31c69adb9065cdba')
40000000000
>帐号2给帐号1转账:
1
2
3
4
5
6
7> personal.unlockAccount('0x2935155a6980bad50a87a29b31c69adb9065cdba')
> eth.sendTransaction({from:'0x2935155a6980bad50a87a29b31c69adb9065cdba',to:'0x2ed11e9f064572d2f2f651e4d7c3824f0b949022',value: 5})
Error: insufficient funds for gas * price + value
at web3.js:3143:20
at web3.js:6347:15
at web3.js:5081:36
at <anonymous>:1:1WHAT!
40000000000
还不够手续费的啊. 看上面的交易’0x6d4fb888d21b09f39f71b6e06911b090dcd1160c068605ea5ff399aef1702380’ 可以看出gas
是90000, 而gasPrice
是18000000000.
补充
以太币的单位
以太币不是无限可分的, 相对于比特币只一个计量单位, 比特币的计量单位较多. 以太币的最小单位是Wei, 一个以太币等于1018 Wei.
以太币有以下计量单位, 每一个单位都对应了以为大牛 ( 了解大牛 ):
单位 | Wei | 大牛 |
---|---|---|
wei | 1 | Wei Dai |
Kwei | 103 | Babbage |
Mwei | 106 | Lovelace |
Gwei | 109 | Shannon |
Microether | 1012 | Szabo |
Milliether | 1015 | Finney |
Ether | 1018 | - |