October 15, 2018 · 区块链 本文字数: 1.4k 阅读时长:7 min 全站字数:344.2k

以太坊私有链实战

  1. 环境准备
  2. 指定私有网络的ID
  3. 手动生成创世块Genesis Block
  4. 创建coinbase账号和测试账号
  5. 启动网络
  6. 新增加节点
  7. 转账测试
  8. 参考资料

环境准备

安装geth(https://github.com/ethereum/go-ethereum)

1
2
3
git clone https://github.com/ethereum/go-ethereum
cd go-ethereum
make geth

指定私有网络的ID

私有的以太坊网络是独立的网络,需要和主网隔离。由于在以太坊网络中,一个网络的是由节点的版本和网络ID确定。所以,私有以太坊网络需要指定不同于主网的网络ID(--networkid)。以太坊主网的网络ID是1,在本文中我们指定网络ID为510

手动生成创世块Genesis Block

每一个区块链网络需要创世块,创世块只能手动生成。在创世块中有默认的网络的配置参数。这里自定义创世块的参数如下:

1
2
3
4
5
6
7
8
9
10
11
{
"config": {
"chainId": 510,
"homesteadBlock": 0,
"eip155Block": 0,
"eip158Block": 0
},
"difficulty": "10000",
"gasLimit": "2100000",
"alloc": { }
}

其中:

  1. config中
    • chainId是网络ID。
    • homesteadBlock, eip155Block, eip158Block, byzantiumBlock 和链的分叉相关,由于是新创建链,所以都是0.
  2. difficulty控制挖矿的速度。以太坊主网的difficulty17179869184。私有链中可以使用10–10000,更快的挖矿获取足够余额进行测试。
  3. gasLimit:每个区块中使用的gas上限。
  4. alloc预分配的账号和余额。

创建coinbase账号和测试账号

创建两个账号一个用于挖矿,一个用于测试转账。两个账号密码均为123456

1
2
3
4
5
6
7
8
9
10
11
12
13
geth --datadir ./data account new
INFO [10-15|15:19:40.880] Maximum peer count ETH=25 LES=0 total=25
Your new account is locked with a password. Please give a password. Do not forget this password.
Passphrase:
Repeat passphrase:
Address: {63205ca105c33e0d9c6c63b3bfa8b3072b25561e}

geth --datadir ./data account new
INFO [10-15|15:20:23.814] Maximum peer count ETH=25 LES=0 total=25
Your new account is locked with a password. Please give a password. Do not forget this password.
Passphrase:
Repeat passphrase:
Address: {8cfebfa90284d5261352fea5e2ce04ba85fab032}

启动网络

首先导入自定义创世块:

1
2
3
4
5
6
7
8
9
10
geth --datadir ./data init genesis.json
INFO [10-15|15:17:17.415] Maximum peer count ETH=25 LES=0 total=25
INFO [10-15|15:17:17.426] Allocated cache and file handles database=/Users/zhangmin/GitRepo/10xBlockchain/ethereum/data/geth/chaindata cache=16 handles=16
INFO [10-15|15:17:17.440] Writing custom genesis block
INFO [10-15|15:17:17.441] Persisted trie from memory database nodes=3 size=399.00B time=136.636µs gcnodes=0 gcsize=0.00B gctime=0s livenodes=1 livesize=0.00B
INFO [10-15|15:17:17.442] Successfully wrote genesis state database=chaindata hash=614a31…9df7ba
INFO [10-15|15:17:17.442] Allocated cache and file handles database=/Users/zhangmin/GitRepo/10xBlockchain/ethereum/data/geth/lightchaindata cache=16 handles=16
INFO [10-15|15:17:17.446] Writing custom genesis block
INFO [10-15|15:17:17.447] Persisted trie from memory database nodes=3 size=399.00B time=109.067µs gcnodes=0 gcsize=0.00B gctime=0s livenodes=1 livesize=0.00B
INFO [10-15|15:17:17.447] Successfully wrote genesis state database=lightchaindata hash=614a31…9df7ba

启动网络

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
geth --datadir ./data --networkid 510 console 2>> eth.log
Welcome to the Geth JavaScript console!

instance: Geth/v1.8.17-stable-8bbe7207/darwin-amd64/go1.10.3
coinbase: 0x63205ca105c33e0d9c6c63b3bfa8b3072b25561e
at block: 0 (Thu, 01 Jan 1970 08:00:00 CST)
datadir: /Users/zhangmin/GitRepo/10xBlockchain/ethereum/data
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
>personal
{
listAccounts: ["0x63205ca105c33e0d9c6c63b3bfa8b3072b25561e", "0x8cfebfa90284d5261352fea5e2ce04ba85fab032"],
listWallets: [{
accounts: [{...}],
status: "Locked",
url: "keystore:///Users/zhangmin/GitRepo/10xBlockchain/ethereum/data/keystore/UTC--2018-10-15T07-19-46.008985807Z--63205ca105c33e0d9c6c63b3bfa8b3072b25561e"
}, {
accounts: [{...}],
status: "Locked",
url: "keystore:///Users/zhangmin/GitRepo/10xBlockchain/ethereum/data/keystore/UTC--2018-10-15T07-20-28.677729373Z--8cfebfa90284d5261352fea5e2ce04ba85fab032"
}],
deriveAccount: function(),
ecRecover: function(),
getListAccounts: function(callback),
getListWallets: function(callback),
importRawKey: function(),
lockAccount: function(),
newAccount: function github.com/ethereum/go-ethereum/console.(*bridge).NewAccount-fm(),
openWallet: function github.com/ethereum/go-ethereum/console.(*bridge).OpenWallet-fm(),
sendTransaction: function(),
sign: function github.com/ethereum/go-ethereum/console.(*bridge).Sign-fm(),
signTransaction: function(),
unlockAccount: function github.com/ethereum/go-ethereum/console.(*bridge).UnlockAccount-fm()
}
> eth.coinbase
"0x63205ca105c33e0d9c6c63b3bfa8b3072b25561e"
> eth.getBalance(eth.coinbase)
117000000000000000000
> miner.start()

查看日志:

1
2
3
4
5
6
7
8
9
10
11
tail -f eth.log
INFO [10-15|15:21:25.240] Initialising Ethereum protocol versions="[63 62]" network=510
INFO [10-15|15:21:25.242] Loaded most recent local header number=0 hash=614a31…9df7ba td=200000000 age=49y5mo4w
INFO [10-15|15:21:25.242] Loaded most recent local full block number=0 hash=614a31…9df7ba td=200000000 age=49y5mo4w
INFO [10-15|15:21:25.242] Loaded most recent local fast block number=0 hash=614a31…9df7ba td=200000000 age=49y5mo4w
INFO [10-15|15:21:25.244] Regenerated local transaction journal transactions=0 accounts=0
INFO [10-15|15:21:25.246] Starting P2P networking
INFO [10-15|15:21:27.364] UDP listener up self=enode://df36af55f6e743df802a6d0c62ec3cb822ffa51962f6062cfb9f24f4dff175d9d5582b4c32b2cd3861059531cba05e34627bb669c58e45cba2401e2f0611f39c@[::]:30303
INFO [10-15|15:21:27.364] RLPx listener up self=enode://df36af55f6e743df802a6d0c62ec3cb822ffa51962f6062cfb9f24f4dff175d9d5582b4c32b2cd3861059531cba05e34627bb669c58e45cba2401e2f0611f39c@[::]:30303
INFO [10-15|15:21:27.372] IPC endpoint opened url=/Users/zhangmin/GitRepo/10xBlockchain/ethereum/data/geth.ipc
INFO [10-15|15:21:27.482] Etherbase automatically configured address=0x63205Ca105C33e0d9c6C63B3BFA8b3072b25561e

新增加节点

新增加的节点必须使用相同的创世区块配置。

1
geth --datadir ./data_new init genesis.json

另外的端口启动节点,不同的数据目录。

1
geth --datadir ./data_new --networkid 510 --port 30304 console 2>> eth_new.log

首先获取第一个节点的信息:

1
2
3
4
5
6
admin.nodeInfo
{
enode: "enode://3bf3e20156786fbd1491ce6278f56b4e2c8dd967c7d09dddb0eee65ced8a50fed1ed29e8ef41f1c401cc9780c437b724369335366c222115a83f7396d78a44d9@[::]:30303",
id: "f61b6331bf038abd9f89c0ae5552916a265ae05bc4940bccd635bf2dfce7e9bc",
ip: "::",
listenAddr: "[::]:30303",

然后将第二个节点加入到第一个节点中:

1
2
3
admin.addPeer("enode://3bf3e20156786fbd1491ce6278f56b4e2c8dd967c7d09dddb0eee65ced8a50fed1ed29e8ef41f1c401cc9780c437b724369335366c222115a83f7396d78a44d9@[::]:30303")
true
> admin.peers

转账测试

发送交易,转账1 Ether。转账时必须运行挖矿,同时转账时需要解锁发送方的钱包才能进行操作。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
eth.sendTransaction({from: "0x63205ca105c33e0d9c6c63b3bfa8b3072b25561e", to: "0x8cfebfa90284d5261352fea5e2ce04ba85fab032", value: web3.toWei(1, "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

> eth.getBalance(eth.accounts[1])
0
> eth.getBalance(eth.accounts[0]);
117000000000000000000
> personal.unlockAccount(eth.accounts[0], "123456")
true
> eth.sendTransaction({from: "0x63205ca105c33e0d9c6c63b3bfa8b3072b25561e", to: "0x8cfebfa90284d5261352fea5e2ce04ba85fab032", value: web3.toWei(1, "ether")})
"0x423ced0b798d1907428a9339f9d7e525c5226edff325279442c9f2aec315d876"

查询转账交易信息和区块信息:

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
eth.getTransaction("0x423ced0b798d1907428a9339f9d7e525c5226edff325279442c9f2aec315d876")
{
blockHash: "0x37db0977e37d44701c7fdd2c7f18118b7c53f3edbb3904dc5b76d75b33741fd9",
blockNumber: 40,
from: "0x63205ca105c33e0d9c6c63b3bfa8b3072b25561e",
gas: 90000,
gasPrice: 1000000000,
hash: "0x423ced0b798d1907428a9339f9d7e525c5226edff325279442c9f2aec315d876",
input: "0x",
nonce: 0,
r: "0x601302c307574ec0da812c3ca6824a3902da58ba1b76776f0bb78f5b92b071b",
s: "0x263b2af2cc6d638a7ca4bd556d7cdb3eb94cf428bb61de6a91f5451b9be2ccdf",
to: "0x8cfebfa90284d5261352fea5e2ce04ba85fab032",
transactionIndex: 0,
v: "0x41f",
value: 1000000000000000000
}

eth.getBlock("0x37db0977e37d44701c7fdd2c7f18118b7c53f3edbb3904dc5b76d75b33741fd9");
{
difficulty: 131072,
extraData: "0xd983010811846765746888676f312e31302e338664617277696e",
gasLimit: 2183549,
gasUsed: 21000,
hash: "0x37db0977e37d44701c7fdd2c7f18118b7c53f3edbb3904dc5b76d75b33741fd9",
logsBloom: "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
miner: "0x63205ca105c33e0d9c6c63b3bfa8b3072b25561e",
mixHash: "0xeb1f010e868d2550f2f9feb11663e4271157dc1ba7dfb3e149732a65248389b7",
nonce: "0x61d30e747129e775",
number: 40,
parentHash: "0x289b5434db8989318ff9228dac106595f5486eed1c0ad2606236f789def839ae",
receiptsRoot: "0x056b23fbba480696b65fe5a59b8f2148a1299103c4f57df839233af2cf4ca2d2",
sha3Uncles: "0x1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347",
size: 652,
stateRoot: "0x4b8b3c533a4170c04c4f1f36c31a4ed91d0f64995be516e4f054d3987eca8bd9",
timestamp: 1539589783,
totalDifficulty: 5300325,
transactions: ["0x423ced0b798d1907428a9339f9d7e525c5226edff325279442c9f2aec315d876"],
transactionsRoot: "0xbc2c2cfd59445bad7a8cef2d3797b6d870b0f18020d1493eff23a20e672cf394",
uncles: []
}

参考资料

  1. Private Network: https://github.com/ethereum/go-ethereum/wiki/Private-network
    1.How To: Create Your Own Private Ethereum Blockchain https://medium.com/mercuryprotocol/how-to-create-your-own-private-ethereum-blockchain-dad6af82fc9f
  2. Ethereum: Setting Up A Private Blockchain https://medium.com/coinmonks/ethereum-setting-up-a-private-blockchain-67bbb96cf4f1