搭建以太坊私有链

网页版现成的 Demo,https://andersbrownworth.com/

一、安装geth

使用 Homebrew 安装基于 Go 开发的以太坊客户端 geth

1
2
brew tap ethereum/ethereum
brew install ethereum

官方参考:https://github.com/ethereum/go-ethereum/wiki/Installation-Instructions-for-Mac

二、创世配置文件

创建区块存放路径

$ mkdir ~/Desktop/ethdev

创建创世配置文件

touch genesis.json

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
{
"config": {
"chainId": 1057,
"homesteadBlock": 0,
"eip150Block": 0,
"eip155Block": 0,
"eip158Block": 0
},
"alloc" : {},
"coinbase" : "0x0000000000000000000000000000000000000000",
"difficulty" : "0x02000",
"extraData" : "",
"gasLimit" : "0x2fefd8",
"nonce" : "0x00",
"mixhash" : "0x0000000000000000000000000000000000000000000000000000000000000000",
"parentHash" : "0x0000000000000000000000000000000000000000000000000000000000000000",
"timestamp" : "0x00"
}
  • config项是定义链配置,会影响共识协议,但新区块的出块规则均依赖链配置。
参数名称参数描述
chainId链ID,在全球须唯一,各个链之间ID不同
homesteadBlock以太坊 homested 版本硬分叉高度。 意味着从此高度开始,新区块受 homested 版本共识规则约束。 因涉及共识变更,如果希望继续接受新区块则必须升级以太坊程序,属于区块链硬分叉。 如果不接受共识变更,则可以独立使用新的 ChainID 继续原共识,且必须独立维护版本。
eip150BlockEIP 150 硬分叉的高度,解决拒绝服务攻击
eip150HashEIP 150 的hash值
eip155BlockEIP 155 硬分叉的高度
eip158BlockEIP 158 硬分叉的高度
mixhash与nonce配合用于挖矿,由上一个区块的一部分生成的hash。
noncenonce就是一个64位随机数,用于挖矿
difficulty设置当前区块的难度
alloc用来预置账号以及账号的以太币数量
coinbase一个地址,对应创世区块的Coinbase字段
timestamp设置创世块的UTC时间戳
parentHash上一个区块的hash值
extraData附加信息
gasLimit该值设置对GAS的消耗总量限制

三、创世块生成

geth --datadir "./chain" init genesis.json

目录作用
geth保存区块链相关数据,如:数据库
keystore保存账户信息

四、创建私有链

geth --datadir "./chain" --nodiscover console 2>>eth_output.log

参数名称参数描述
datadir设置当前区块链网络数据存放的位置
console启动命令行模式,可以在Geth中执行命令
nodiscover私有链地址,不会被网上看到
2>>eth_output.log输入到日志 eth_output.log

五、账户创建-挖矿-交易

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
ashin@MacBook ethdev % geth --datadir "./chain" init genesis.json
INFO [01-01|20:57:38.559] Maximum peer count ETH=50 LES=0 total=50
INFO [01-01|20:57:38.578] Allocated cache and file handles database=/Users/ashin/Desktop/ethdev/chain/geth/chaindata cache=16.00MiB handles=16
INFO [01-01|20:57:38.616] Writing custom genesis block
INFO [01-01|20:57:38.619] Persisted trie from memory database nodes=0 size=0.00B time=22.08µs gcnodes=0 gcsize=0.00B gctime=0s livenodes=1 livesize=0.00B
INFO [01-01|20:57:38.620] Successfully wrote genesis state database=chaindata hash=003508…74a1dc
INFO [01-01|20:57:38.620] Allocated cache and file handles database=/Users/ashin/Desktop/ethdev/chain/geth/lightchaindata cache=16.00MiB handles=16
INFO [01-01|20:57:38.662] Writing custom genesis block
INFO [01-01|20:57:38.662] Persisted trie from memory database nodes=0 size=0.00B time=6.172µs gcnodes=0 gcsize=0.00B gctime=0s livenodes=1 livesize=0.00B
INFO [01-01|20:57:38.668] Successfully wrote genesis state database=lightchaindata hash=003508…74a1dc

ashin@MacBook ethdev % geth --datadir "./chain" --nodiscover console 2>>eth_output.log
Welcome to the Geth JavaScript console!

instance: Geth/v1.9.9-stable/darwin-amd64/go1.13.4
at block: 0 (Thu, 01 Jan 1970 08:00:00 CST)
datadir: /Users/ashin/Desktop/ethdev/chain
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

> eth.accounts
[]
> personal.newAccount("Jay")
"0xef3a556a7274dba30aed0cd08c7c3580a7920be4"

> personal.newAccount("Tim")
"0x6dd925ea5094915bfdb6d875e2038308ac4423cd"

> eth.accounts
["0xef3a556a7274dba30aed0cd08c7c3580a7920be4", "0x6dd925ea5094915bfdb6d875e2038308ac4423cd"]

> user0 = eth.accounts[0]
"0xef3a556a7274dba30aed0cd08c7c3580a7920be4"

> user1 = eth.accounts[1]
"0x6dd925ea5094915bfdb6d875e2038308ac4423cd"

> miner.start()
null

> miner.stop()
null

> eth.getBalance(user0)
75000000000000000000

> eth.getBalance(user1)
0

> eth.blockNumber
15

> eth.sendTransaction({from:user0, to:user1, value:web3.toWei(10, "ether")})
Error: authentication needed: password or unlock
at web3.js:3143:20
at web3.js:6347:15
at web3.js:5081:36
at <anonymous>:1:1

> personal.unlockAccount(user0)
Unlock account 0xef3a556a7274dba30aed0cd08c7c3580a7920be4
Password:
true

> eth.sendTransaction({from:user0, to:user1, value:web3.toWei(10, "ether")})
"0xdc7757409bd0876f6ccefc967ba71a1c5d3c0119acf3d26799dba2593ec8f302"

> eth.getBalance(user0)
75000000000000000000

> eth.getBalance(user1)
0

> miner.start()
null

> miner.stop()
null

> eth.blockNumber
21

> eth.getBalance(user0)
95000000000000000000

> eth.getBalance(user1)
10000000000000000000

相关命令

  • eth.accounts 查看所有账户

  • personal.newAccount("Jay") 创建账户,password 为Jay

  • eth.getBalance(user0) 获取账户余额

  • miner.start() 开始挖矿

  • miner.stop() 结束挖矿

  • eth.blockNumber 区块个数

  • eth.sendTransaction({from:user0, to:user1, value:web3.toWei(10, "ether")}) 交易

  • personal.unlockAccount(user0, "Jay") 解锁账户

  • th.getBlock(n) 查看区块n

  • tail -f eth_output.log 动态显示log

六、以太坊相关概念

DAO

Decentralized Autonomous Organization 去中心化自治组织

EVM

以太坊虚拟机(EVM)是以太坊中智能合约的运行环境。沙箱封装隔离,运行在EVM内部的代码不能接触到网络、文件系统或者其它进程。

Accounts

以太坊中有两类账户,它们共用同一个地址空间。外部账户,该类账户被公钥-私钥对控制。合约账户,该类账户被存储在账户中的代码控制。 外部账户的地址是由公钥决定的,合约账户的地址是在创建合约时确定的。

Gas

每一笔交易需要支付一定的gasgas price是由创建者设置的,调用合约的发送账户需要交易费用 = gas price * gas amount。

以太坊单位

UnitWei ValueWei
wei11 wei
Kwei1e3 wei1,000
Mwei1e6 wei1,000,000
Gwei1e9 wei1,000,000,000
microether1e12 wei1,000,000,000,000
milliether1e15 wei1,000,000,000,000,000
ether1e18 wei1,000,000,000,000,000,000

coinbase

coinbase 就是系统生成的币,如挖矿奖励。

硬分叉

硬分叉是指当区块链代码发生改变后,旧节点拒绝接受由新节点创建的区块,不符合原规则的区块将会被忽略,矿工会按照原规则在他们最后验证的区块之后创建新的区块,区块链领域最有名的硬分叉案例,便是“以太坊”分叉,一句话说就是:旧区块不兼容新区块就是硬分叉。

软分叉

软分叉是指区块链代码发生改变后,旧的节点并不会感知到区块链代码发生改变,并继续接受由新节点创建的区块,矿工们可能会在他们完全没有理解或验证过的区块上进行工作,软分叉新旧节点双方始终都工作在同一条链上。一句话说就是:旧区块兼容新区块就是软分叉。

参考