一 环境准备
1 Go-Ethereum
Go-Ethereum是由以太坊基金会提供的官方客户端软件。它是用Go编程语言编写的,简称Geth。可以按照以下wiki说明安装go-ethereum,地址为:https://github.com/ethereum/go-ethereum/wiki/Building-Ethereum。
这里简单介绍一下在mac上通过源码安装的步骤:
1) 下载geth源码:
git clone https://github.com/ethereum/go-ethereum
2) 安装go环境
brew install go
3) compile、build、install geth
cd go-ethereum
make geth
4) xcode支持
If you see some errors related to header files of Mac OS system library, install XCode Command Line Tools, and try again.
xcode-select --install
5) 测试安装是否成功
执行命令:geth version,如果出现以下信息说明安装成功
> geth version
Geth
Version: 1.8.14-stable
Architecture: amd64
Protocol Versions: [63 62]
Network Id: 1
Go Version: go1.10.3
Operating System: darwin
GOPATH=/Users/wuzhengfei/Documents/workspace/go/workspace
GOROOT=/usr/local/go
二 搭建私有链
在go-ethereum中详细介绍了搭建私有链的过程,有兴趣的话,可以详细看一下。
1 常见创世区块
1) 常见创世区块
首先需要为区块链创建一个创世区块,所有的区块都会挂在这个创世区块的后面。创建一个json文件(这里命名为genesis.json
),其内容如下:
{
"config": {
"chainId": 0,
"homesteadBlock": 0,
"eip155Block": 0,
"eip158Block": 0
},
"alloc" : {},
"coinbase" : "0x0000000000000000000000000000000000000000",
"difficulty": "0x20000",
"extraData" : "",
"gasLimit" : "0x2fefd8",
"nonce" : "0x0000000000055555",
"mixhash" : "0x0000000000000000000000000000000000000000000000000000000000000000",
"parentHash": "0x0000000000000000000000000000000000000000000000000000000000000000",
"timestamp" : "0x00"
}
以上json来自go-ethereum官网,他可以满足大部分场景的需要。建议修改nonce的值,这样可以防止未知的远程节点连接到此私有的测试网络中。
2) 指定数据保存目录
如下图目录结构所示,genesis.json为创世区块地址,data0为区块链数据地址。
2 初始化
创建好创世区块以后,通过以下命令初始化Geth节点,确保所有参数都能设置正确,如下所示:
$ geth -datadir /Users/wuzhengfei/Documents/ethereum/testchain/data0 init /Users/wuzhengfei/Documents/ethereum/testchain/genesis.json
geth init命令用来初始化区块链,其中-datadir指定数据存放目录,genesis.json是init命令的参数。运行此命令,会读取genesis.json文件,根据其中的内容,将创世区块写入到区块链中。结果如下所示:
$ geth -datadir /Users/wuzhengfei/Documents/ethereum/testchain/data0 init /Users/wuzhengfei/Documents/ethereum/testchain/genesis.json
INFO [12-16|15:00:35.410] Maximum peer count ETH=25 LES=0 total=25
INFO [12-16|15:00:35.423] Allocated cache and file handles database=/Users/wuzhengfei/Documents/ethereum/testchain/data0/geth/chaindata cache=16 handles=16
INFO [12-16|15:00:35.427] Writing custom genesis block
INFO [12-16|15:00:35.428]Persisted trie from memory database nodes=4 size=573.00B time=93.543µs gcnodes=0 gcsize=0.00B gctime=0s livenodes=1 livesize=0.00B
INFO [12-16|15:00:35.428] Successfully wrote genesis state database=chaindata hash=d62439…28110e
INFO [12-16|15:00:35.428] Allocated cache and file handles database=/Users/wuzhengfei/Documents/ethereum/testchain/data0/geth/lightchaindata cache=16 handles=16
INFO [12-16|15:00:35.430] Writing custom genesis block
INFO [12-16|15:00:35.431] Persisted trie from memory database nodes=4 size=573.00B time=73.437µs gcnodes=0 gcsize=0.00B gctime=0s livenodes=1 livesize=0.00B
INFO [12-16|15:00:35.431] Successfully wrote genesis state database=lightchaindata hash=d62439…28110e
初始化后的目录结构如下所示:
3 交互模式
1) 进入交互模式
执行geth console命令
$ geth --datadir data0/ --nodiscover console 2>>../etherum.log
输出信息如下所示,说明进入交互模式成功,当然也可以进入ethereum.log文件中查看日志
wuzhengfeideMacBook-Pro:testchain wuzhengfei$ geth --datadir data0/ --nodiscover console 2>>../etherum.log
Welcome to the Geth JavaScript console!
instance: Geth/v1.8.14-stable/darwin-amd64/go1.10.3
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
2) 创建账户
a) 查看已创建账户
执行eth.accounts方法
eth.accounts
因为还未创建账户,所以输出信息如下所示:
> eth.accounts
[]
b) 创建账户
执行newAccount()方法,如下所示;
personal.newAccount()
输出信息如下所示:
> personal.newAccount("wuzhengfei")
"0x555b8a7fb1e3f95745fd31be168f8e1d77dced5a"
再次执行eth.accounts命令即可看到当前的账户。
> eth.accounts
["0x555b8a7fb1e3f95745fd31be168f8e1d77dced5a"]
3) 挖矿
a) 查看账户余额
eth.getBalance("0x555b8a7fb1e3f95745fd31be168f8e1d77dced5a")
因为还没有以太币,所以输出结果如下:
> eth.getBalance("0x555b8a7fb1e3f95745fd31be168f8e1d77dced5a")
0
b) 挖矿
执行miner.start(),开始挖矿
miner.start()
输出结果如下
> miner.start()
null
此时进入ethereum.log文件中,可以看到挖矿有一个初始化过程,达到100以后即开始挖矿。
INFO [12-16|15:44:25.879] Generating DAG in progress epoch=0 percentage=96 elapsed=2m32.178s
INFO [12-16|15:44:27.878] Generating DAG in progress epoch=0 percentage=97 elapsed=2m34.177s
INFO [12-16|15:44:29.756] Generating DAG in progress epoch=0 percentage=98 elapsed=2m36.055s
INFO [12-16|15:44:31.931] Generating DAG in progress epoch=0 percentage=99 elapsed=2m38.230s
INFO [12-16|15:44:31.934] Generated ethash verification cache epoch=0 elapsed=2m38.232s
INFO [12-16|15:44:33.799] Successfully sealed new block number=1 hash=c40a19…a0977d elapsed=2m40.760s
INFO [12-16|15:44:33.812] mined potential block number=1 hash=c40a19…a0977d
INFO [12-16|15:44:33.813] Commit new mining work number=2 uncles=0 txs=0 gas=0 fees=0 elapsed=177.937µs
INFO [12-16|15:44:35.770] Successfully sealed new block number=2 hash=b0f39a…03fef1 elapsed=1.956s
INFO [12-16|15:44:35.770] mined potential block number=2 hash=b0f39a…03fef1
c) 查看账户余额
挖矿一段时间后,再次查看账户余额
> eth.getBalance("0x555b8a7fb1e3f95745fd31be168f8e1d77dced5a")
200000000000000000000
d) 停止挖矿
停止挖矿,只需执行miner.stop()
miner.stop()
输出结果如下
> miner.stop()
true
三 常见问题
1 创世区块中的alloc问题
网上的博客中,都说通过在创世区块的alloc中指定账户以及账户余额,如下所示:
{
"config": {
"chainId": 10,
"homesteadBlock": 0,
"eip155Block": 0,
"eip158Block": 0
},
"coinbase" : "0x0000000000000000000000000000000000000000",
"difficulty" : "0x20000",
"extraData" : "",
"gasLimit" : "0x2fefd8",
"nonce" : "0x00000000000666666666",
"mixhash" : "0x0000000000000000000000000000000000000000000000000000000000000000",
"parentHash" : "0x0000000000000000000000000000000000000000000000000000000000000000",
"timestamp" : "0x00",
"alloc": {
"0x1d82a7d2c4fd6aad2054a368098318ab998f4786": {
"balance": "100000000000000000000"
}
}
}
然后执行geth init命令,如下所示
geth --datadir data0/ init genesis.json
就能在初始化后的网络中看到这些账户,并且账户有一定余额。亲测,这是有问题的。因为在init前区块链中不存在此账户(0x1d82a7d2c4fd6aad2054a368098318ab998f4786),所以init后是查不到这个账户,当然也就没有余额了。如果想给指定的一批账号初始化余额,需要先创建账户,然后在执行init。具体步骤如下:
第一步:先在交互模式下创建账户:
persion.newAccount(“密码”)
第二步:移除之前的db
geth removedb --datadir data0/
第三步:将账户信息放入genesis.json中,即将上面alloc中的账户改成第一步中创建的账户。
重新init
geth --datadir data0/ init genesis.json