本文操作系统:windows 10 家庭中文版。
1、下载Geth
在官网下载:https://geth.ethereum.org/downloads/
或者从国内镜像下载:https://ethfans.org/wikis/Ethereum-Geth-Mirror
本文从国内镜像下载,版本号:geth-windows-amd64-1.8.3
主要参考文档:https://ethfans.org/posts/how-to-build-private-chain-with-Geth
2、安装Geth
双击下载的文件geth-windows-amd64-1.8.3-329ac18e.exe进行安装:
安装完毕后目录如下:
3、加载创世区块
首先,需要定义区块链的创世状态;通过geth来配置以太坊私有链,是学习以太坊的入门步骤。而其中,如何配置创世文件,又是最关键的一步。
如果在其中产生错误,有些会导致无法初始化私有链,有些还会导致在以后的过程中发生各种莫名其妙的错误。
新建一个创世文件,该文件的后缀为.json(大部分命名为genesis.json),注意:不同的genesis.json适用于不同的geth版本;将该文件放到geth的安装目录下,文件的内容类似:
{
"config": {
"chainId": <arbitrary positive integer>,
"homesteadBlock": 0,
"eip150Block": 0,
"eip155Block": 0,
"eip158Block": 0,
"byzantiumBlock": 0,
"constantinopleBlock": 0,
"petersburgBlock": 0,
"clique": {
"period": 5,
"epoch": 30000
},
"ethash": {}
},
"alloc": {
"dbdbdb2cbd23b783741e8d7fcf51e459b497e4a6": { "balance": "1000000000"},
"e6716f9544a56c530d868e4bfbacb172315bdead": { "balance": "2000000000"},
...
},
"nonce": "0x000000000000002a",
"difficulty": "0x020000",
"mixhash": "0x0000000000000000000000000000000000000000000000000000000000000000",
"coinbase": "0x0000000000000000000000000000000000000000",
"timestamp": "0x00",
"parentHash": "0x0000000000000000000000000000000000000000000000000000000000000000",
"extraData": "0x",
"gasLimit": "0x2fefd8"
}
我们对配置项的内容进行一下简单的介绍。
1.config:定义链配置,会影响共识协议,虽然链配置对创世影响不大,但新区块的出块规则均依赖链配置。
(1)chainId: 是 EIP-155 引入的一个用来区分不同 EVM 链的一个标识,主要作用就是避免一个交易在签名之后被重复在不同的链上提交。私有链的 chainId 最好不要和现有任何已经在公开运行的 EVM 链的 chainId 相同。已经被占用的 chainId 可以通过这个列表查看。注意:networkid 参数通常需要与 chainId 的值一致,可用来防止replay attack重发攻击:恶意重复或拖延正确数据传输的一种网络攻击手段。
(2)homesteadBlock:Homestead 硬分叉区块高度,以太坊发展蓝图中的一个阶段。第一阶段是以太坊区块链面世,代号为frontier,第二个阶段即为当前阶段,代号为Homestead(家园),第三阶段为Metropolis(大都会),大都会又细分为两个小阶段,第一个是Byzantium(拜占庭)硬分叉(引入新型零知识证明算法以及pos权益证明共识算法),第二个是Constantinople(君士坦丁堡)硬分叉(以太坊正式应用pow和pos混合链,解决拜占庭引发的问题)。最后一个阶段代号Petersburg(彼得堡),最终版本的以太坊稳定运行。
(3)eip150Block: EIP 150 硬分叉区块高度。
(4)eip155Block: EIP 155 硬分叉区块高度。
(5)eip158Block: EIP 158 硬分叉区块高度。
(6)byzantiumBlock: Byzantium 硬分叉区块高度。
(7)constantinopleBlock: Constantinople 硬分叉区块高度。
(8)petersburgBlock: Petersburg 硬分叉区块高度。
(9)clique: 实现的是PoA(权威证明,Proof of Authority)共识。
(10)ethash: 实现的是PoW(工作量证明,Proof of Work)共识。
注意:在以太坊的官方源码中,有两个共识算法:clique和ethash,它们都位于以太坊项目的consensus目录下。在以太坊中clique仅在测试网络里使用,真实的以太坊主网还是使用PoW算法(ethash模块实现)。但在自己组成私有网络时,你可以自由选择使用clique还是ethash。本配置文件中clique与ethash只能二选一。
2.alloc: 用来预置账号以及账号的以太币数量,因为私有链挖矿比较容易,所以不需要预置有币的账号,需要的时候自己创建即可以。
3.nonce:一个64位随机数,用于挖矿,和mixhash的设置需要满足以太坊的Yellow paper, 4.3.4.Block Header Validity (44)章节所描述的条件。以证明在该块上进行了足够的计算。
4.difficulty: 设置计算区块的难度,如果数值过大,挖矿时间较长,在测试环境为节省算力和等待时间可设置较小值。它可以根据前一个块的难度级别和时间戳来计算。难度越高,Miner必须执行的统计更多计算才能发现有效块。此值用于控制区块链的块生成时间,将块生成频率保持在目标范围内。
5.mixhash:与nonce配合用于挖矿,由上一个区块的一部分生成的hash。和nonce的设置需要满足以太坊的Yellow paper, 4.3.4. Block Header Validity, (44)章节所描述的条件。以证明在该块上进行了足够的计算。
6.coinbase: 矿工账号,随便填写。
7.timestamp: 设置创世块的时间戳,"0x00"表示北京时间“1970-01-01 08:00:00”。时间戳还允许验证链内的块顺序。
8.parentHash: 上一个区块的hash值,因为是创世块,所以这个值是“0”。
9.extraData: 附加信息,随便填,可以填你的个性信息,必须为十六进制的字符串。
10.gasLimit: 该值设置对gas的消耗总量限制,用来限制区块能包含的交易信息总和。私有链可以填很大,最大“0xffffffff”。
4、创世区块初始化
本文实际配置的genesis.json如下:
{
"config": {
"chainId": 202005,
"homesteadBlock": 0,
"eip155Block": 0,
"eip158Block": 0
},
"alloc": {
"7610fd66c272332edd59a43460ad24eee1973bfe": {"balance": "1000000000"}
},
"nonce": "0x000000000000002a",
"difficulty": "0x020000",
"mixhash": "0x0000000000000000000000000000000000000000000000000000000000000000",
"coinbase": "0x0000000000000000000000000000000000000000",
"timestamp": "0x00",
"parentHash": "0x0000000000000000000000000000000000000000000000000000000000000000",
"extraData": "0x68656c6c6f20776f726c642021",
"gasLimit": "0x2fefd8"
}
1.执行以下命令来启动初始化创世块的命令:
C:\Program Files\Geth>geth --datadir "d:/data_init1/" init genesis.json
本文将初始化json文件放在geth同级目录下,如果放在其他目录下,指定具体的路径即可。该命令同时创建了一个data_init1目录专门存储节点数据,执行完成会发现在该目录下多出两个目录,一个为geth一个为keystore。其中geth里面放数据相关信息,keystore里面放加密过的私钥文件。
执行时打印日志如下:
C:\Program Files\Geth>geth --datadir "d:/data_init1/" init genesis.json
INFO [05-14|11:40:36] Maximum peer count ETH=25 LES=0 total=25
INFO [05-14|11:40:36] Allocated cache and file handles database=d:\\data_init1\\geth\\chaindata cache=16 handles=16
INFO [05-14|11:40:36] Writing custom genesis block
INFO [05-14|11:40:36] Persisted trie from memory database nodes=1 size=196.00B time=0s gcnodes=0 gcsize=0.00B gctime=0s livenodes=1 livesize=0.00B
INFO [05-14|11:40:36] Successfully wrote genesis state database=chaindata hash=abff60…e74751
INFO [05-14|11:40:36] Allocated cache and file handles database=d:\\data_init1\\geth\\lightchaindata cache=16 handles=16
INFO [05-14|11:40:36] Writing custom genesis block
INFO [05-14|11:40:36] Persisted trie from memory database nodes=1 size=196.00B time=0s gcnodes=0 gcsize=0.00B gctime=0s livenodes=1 livesize=0.00B
INFO [05-14|11:40:36] Successfully wrote genesis state database=lightchaindata hash=abff60…e74751
C:\Program Files\Geth>
经过以上命令,已经完成了私有连的初始化工作。因为本文要建立联盟链,因此需要再创建执行一遍同样的命令,json文件必须相同,datadir目录必须不同。本文使用data_init2和data_init3目录来存储第二个节点和第三个节点的数据。
C:\Program Files\Geth>geth --datadir "d:/data_init2/" init genesis.json
INFO [05-14|11:48:14] Maximum peer count ETH=25 LES=0 total=25
INFO [05-14|11:48:14] Allocated cache and file handles database=d:\\data_init2\\geth\\chaindata cache=16 handles=16
INFO [05-14|11:48:14] Writing custom genesis block
INFO [05-14|11:48:14] Persisted trie from memory database nodes=1 size=196.00B time=0s gcnodes=0 gcsize=0.00B gctime=0s livenodes=1 livesize=0.00B
INFO [05-14|11:48:14] Successfully wrote genesis state database=chaindata hash=abff60…e74751
INFO [05-14|11:48:14] Allocated cache and file handles database=d:\\data_init2\\geth\\lightchaindata cache=16 handles=16
INFO [05-14|11:48:14] Writing custom genesis block
INFO [05-14|11:48:14] Persisted trie from memory database nodes=1 size=196.00B time=1.0045ms gcnodes=0 gcsize=0.00B gctime=0s livenodes=1 livesize=0.00B
INFO [05-14|11:48:14] Successfully wrote genesis state database=lightchaindata hash=abff60…e74751
C:\Program Files\Geth>geth --datadir "d:/data_init3/" init genesis.json
INFO [05-14|11:48:21] Maximum peer count ETH=25 LES=0 total=25
INFO [05-14|11:48:21] Allocated cache and file handles database=d:\\data_init3\\geth\\chaindata cache=16 handles=16
INFO [05-14|11:48:21] Writing custom genesis block
INFO [05-14|11:48:21] Persisted trie from memory database nodes=1 size=196.00B time=0s gcnodes=0 gcsize=0.00B gctime=0s livenodes=1 livesize=0.00B
INFO [05-14|11:48:21] Successfully wrote genesis state database=chaindata hash=abff60…e74751
INFO [05-14|11:48:21] Allocated cache and file handles database=d:\\data_init3\\geth\\lightchaindata cache=16 handles=16
INFO [05-14|11:48:21] Writing custom genesis block
INFO [05-14|11:48:21] Persisted trie from memory database nodes=1 size=196.00B time=997.2µs gcnodes=0 gcsize=0.00B gctime=0s livenodes=1 livesize=0.00B
INFO [05-14|11:48:21] Successfully wrote genesis state database=lightchaindata hash=abff60…e74751
C:\Program Files\Geth>
2.初始化创世块可能的错误:
(1)Fatal: invalid genesis file: missing 0x prefix for hex data:这个错误信息意思很明白,就是你的json文件中,对于16进制数据,需要加上“0x”前缀。
(2)Fatal: invalid genesis file: hex string has odd length: 从v1.6开始,设置的十六进制数值,不能是奇数位, 比如不能是“0x0”,而应该是“0x00”。
(3)Fatal: failed to write genesis block: genesis has no chain configuration :这个错误信息,就是说,你的json文件中,缺少config部分。看到这个信息,我们不需要把geth退回到v1.5版本,而是需要加上config部分。
(4)Error: invalid sender undefined: 这个错误不会导致初始化失败,但是会在以后的转账(eth.sendTransaction),或者部署智能合约的时候产生。解决方法就是chainId 不能设置为0。
5、启动联盟链
本文在同一台机器启动联盟链,开三个窗口来启动三个节点。需要注意的是,虽然是三个节点,但他们的启动程序都是geth,只不过datadir目录不同而已。
在cmd窗口执行以下命令启动节点,注意启动之后不要关闭窗口。
geth --datadir "datadir" --networkid 666 --identity "node" --port 30303 --rpc --rpcport 8545 --rpcapi "db,eth,eth,net,web3,admin" --rpcaddr "0.0.0.0" --rpccorsdomain "*" --nodiscover --verbosity 4 console
参数简介:
- --networkid : 指定网路ID,与genesis.json中的chainId一致;
- --identity : 设置节点ID;
- --port : 节点端口,默认是30303;
- --rpc : 启用 rpc 服务;
- --rpcport : rpc 服务端口,默认是8545;
- --rpcaddr : http-rpc服务器接口地址:默认“127.0.0.1”
- --rpccorsdomain : 相当于域名白名单,“*”是允许通过任意域名访问;
- --nodiscover : 此参数确保geth不去寻找peers,主要是为了严格控制联盟链连入的节点;
- --verbosity : 日志等级:0=silent, 1=error, 2=warn, 3=info, 4=debug, 5=detail ;默认是3;
- console : 进入控制台。
本文启动第一个节点命令:
geth --datadir "d:/data_init1/" --networkid 202005 --port 30303 --rpc --rpcport 8545 --rpcapi "eth,net,web3,admin" --rpccorsdomain "*" --nodiscover console
注意:在windows中,同一台主机启动第二个节点如果报错:“Fatal: Error starting protocol stack: Access is denied.”;需要添加参数:--ipcdisable;停止ipc。
本文启动第二个节点命令:
geth --datadir "d:/data_init2/" --networkid 202005 --port 30305 --rpc --rpcport 8547 --rpcapi "eth,net,web3,admin" --rpccorsdomain "*" --nodiscover --ipcdisable console
本文启动第三个节点命令:
geth --datadir "d:/data_init3/" --networkid 202005 --port 30307 --rpc --rpcport 8549 --rpcapi "eth,net,web3,admin" --rpccorsdomain "*" --nodiscover --ipcdisable console
其中,第一个节点执行时日志如下:
C:\Program Files\Geth>geth --datadir "d:/data_init1/" --networkid 202005 --port 30303 --rpc --rpcapi "eth,net,web3,admin" --rpccorsdomain "*" --nodiscover console
INFO [05-14|12:25:50] Maximum peer count ETH=25 LES=0 total=25
INFO [05-14|12:25:50] Starting peer-to-peer node instance=Geth/v1.8.3-stable-329ac18e/windows-amd64/go1.10
INFO [05-14|12:25:50] Allocated cache and file handles database=d:\\data_init1\\geth\\chaindata cache=768 handles=1024
WARN [05-14|12:25:50] Upgrading database to use lookup entries
INFO [05-14|12:25:50] Initialised chain configuration config="{ChainID: 202005 Homestead: 0 DAO: <nil> DAOSupport: false EIP150: <nil> EIP155: 0 EIP158: 0 Byzantium: <nil> Constantinople: <nil> Engine: unknown}"
INFO [05-14|12:25:50] Database deduplication successful deduped=0
INFO [05-14|12:25:50] Disk storage enabled for ethash caches dir=d:\\data_init1\\geth\\ethash count=3
INFO [05-14|12:25:50] Disk storage enabled for ethash DAGs dir=C:\\Users\\liyuq\\AppData\\Ethash count=2
INFO [05-14|12:25:50] Initialising Ethereum protocol versions="[63 62]" network=202005
INFO [05-14|12:25:50] Loaded most recent local header number=0 hash=abff60…e74751 td=131072
INFO [05-14|12:25:50] Loaded most recent local full block number=0 hash=abff60…e74751 td=131072
INFO [05-14|12:25:50] Loaded most recent local fast block number=0 hash=abff60…e74751 td=131072
INFO [05-14|12:25:50] Regenerated local transaction journal transactions=0 accounts=0
INFO [05-14|12:25:50] Starting P2P networking
INFO [05-14|12:25:50] RLPx listener up self="enode://11ccf92aef003418bbbc278a1fb2d9162a61532bc43061c253ba68e6fd42509afd412a5ef55c065073a7caccaa5b109b2077caf38af0b724b68f9a4d372ce200@[::]:30303?discport=0"
INFO [05-14|12:25:50] IPC endpoint opened url=\\\\.\\pipe\\geth.ipc
INFO [05-14|12:25:50] HTTP endpoint opened url=http://127.0.0.1:8545 cors=* vhosts=localhost
Welcome to the Geth JavaScript console!
instance: Geth/v1.8.3-stable-329ac18e/windows-amd64/go1.10
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
>
第二个节点和第三个节点输出日志类似。
这样,我们就顺利的启动了三个节点,进入了控制台,接下来的操作都在控制台中进行。