5分钟快速从无到有建立Ethereum联盟链
开发Ethereum Dapp的过程中,需要一个测试用的chain,之前是使用testrpc或直接连到Ethereum testnet (Ropsten),不过testrpc有各种坑需要处理,而Ropsten testnet则是需要同步与等待区块,相当的烦人。前几天看到Parity 1.5版以后支持建立Proof of Authority Chains,可以直接解决上述的问题,果然一试成主顾。
若你有下列困扰,可以建立自己测试用的PoA chain
PoA Chain特点有
Parity是一个注重效能的Ethereum Client端软体
请自行到Parity官网安装,支持Ubutnu, OSX, Docker, Windows
PoA chain需要设定一个创世区块
{
"name": "DemoPoA",
"engine": {
"authorityRound": {
"params": {
"gasLimitBoundDivisor": "0x400",
"stepDuration": "5",
"validators" : {
"list": []
}
}
}
},
"params": {
"maximumExtraDataSize": "0x20",
"minGasLimit": "0x1388",
"networkID" : "0x2323"
},
"genesis": {
"seal": {
"authorityRound": {
"step": "0x0",
"signature": "0x0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000"
}
},
"difficulty": "0x20000",
"gasLimit": "0x5B8D80"
},
"accounts": {
"0x0000000000000000000000000000000000000001": { "balance": "1", "builtin": { "name": "ecrecover", "pricing": { "linear": { "base": 3000, "word": 0 } } } },
"0x0000000000000000000000000000000000000002": { "balance": "1", "builtin": { "name": "sha256", "pricing": { "linear": { "base": 60, "word": 12 } } } },
"0x0000000000000000000000000000000000000003": { "balance": "1", "builtin": { "name": "ripemd160", "pricing": { "linear": { "base": 600, "word": 120 } } } },
"0x0000000000000000000000000000000000000004": { "balance": "1", "builtin": { "name": "identity", "pricing": { "linear": { "base": 15, "word": 3 } } } }
}
}
将上述资料存成 demo-spec.json
此教学会在同一台机器上跑两个node,因此有些Parity原生的设定参数会有衝突,两个node需要分别设定不同值。
可以用下列指令启动Parity node
parity --chain demo-spec.json -d /tmp/parity0 --port 30300 --jsonrpc-port 8540 --ui-port 8180 --dapps-port 8080 --jsonrpc-apis web3,eth,net,personal,parity,parity_set,traces,rpc,parity_accounts
除了打一长串的指令外,Parity也提供更为简洁的config档案设定方式,使用 –config 即可引用设定档。
node0 使用如下设定档 node0.toml
[parity]
chain = "demo-spec.json"
base_path = "/tmp/parity0"
[network]
port = 30300
[rpc]
port = 8540
apis = ["web3", "eth", "net", "personal", "parity", "parity_set", "traces", "rpc", "parity_accounts"]
[ui]
port = 8180
[dapps]
port = 8080
node1 使用如下设定档 node1.toml
[parity]
chain = "demo-spec.json"
base_path = "/tmp/parity1"
[network]
port = 30301
[rpc]
port = 8541
apis = ["web3", "eth", "net", "personal", "parity", "parity_set", "traces", "rpc", "parity_accounts"]
[ui]
port = 8181
[dapps]
port = 8081
我们总共要开3个帐号:2个Authority跟1个user帐号。
接著开启网页 http://localhost:8180
我不知道怎么略过WELCOME操作,所以先跟著指示随便建立一个account,然后再删除XD
接著新增一个user account,使用Recover account from recovery phrase功能,为了示范的一致性,使用 user 当作pass phrase
选择第二项
输入user
完成User account
新增Authority account,一样使用Recover account from recovery phrase功能,为了示范的一致性,使用 node0 当作pass phrase
选择第二项
输入node0
最后要看到User与Node0 (Authority) account
这样就完成 node0 的帐号设定
启动Parity node1
输入node1
完成Authority account
这样就完成 node1 的帐号设定
"validators" : {
"list": [
"0x00Bd138aBD70e2F00903268F3Db08f2D25677C9e",
"0x00Aa39d30F0D20FF03a22cCfc30B7EfbFca597C2"
]
}
再将user account加入accounts,并给一些balance,后续可以使用
"0x004ec07d2329997267Ec62b4166639513386F32E": { "balance": "10000000000000000000000" }
完成后的demo-spec.json如下
{
"name": "DemoPoA",
"engine": {
"authorityRound": {
"params": {
"gasLimitBoundDivisor": "0x400",
"stepDuration": "5",
"validators" : {
"list": [
"0x00Bd138aBD70e2F00903268F3Db08f2D25677C9e",
"0x00Aa39d30F0D20FF03a22cCfc30B7EfbFca597C2"
]
}
}
}
},
"params": {
"maximumExtraDataSize": "0x20",
"minGasLimit": "0x1388",
"networkID" : "0x2323"
},
"genesis": {
"seal": {
"authorityRound": {
"step": "0x0",
"signature": "0x0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000"
}
},
"difficulty": "0x20000",
"gasLimit": "0x5B8D80"
},
"accounts": {
"0x0000000000000000000000000000000000000001": { "balance": "1", "builtin": { "name": "ecrecover", "pricing": { "linear": { "base": 3000, "word": 0 } } } },
"0x0000000000000000000000000000000000000002": { "balance": "1", "builtin": { "name": "sha256", "pricing": { "linear": { "base": 60, "word": 12 } } } },
"0x0000000000000000000000000000000000000003": { "balance": "1", "builtin": { "name": "ripemd160", "pricing": { "linear": { "base": 600, "word": 120 } } } },
"0x0000000000000000000000000000000000000004": { "balance": "1", "builtin": { "name": "identity", "pricing": { "linear": { "base": 15, "word": 3 } } } },
"0x004ec07d2329997267Ec62b4166639513386F32E": { "balance": "10000000000000000000000" }
}
}
为了启动Authority node来产生区块,我们必须设定负责产生block的signer,分别是 node0 与 node1 account
node0
node1
[parity]
chain = "demo-spec.json"
base_path = "/tmp/parity0"
[network]
port = 30300
[rpc]
port = 8540
apis = ["web3", "eth", "net", "personal", "parity", "parity_set", "traces", "rpc", "parity_accounts"]
[ui]
port = 8180
[dapps]
port = 8080
[account]
password = ["node.pwds"]
[mining]
engine_signer = "0x00Bd138aBD70e2F00903268F3Db08f2D25677C9e"
reseal_on_txs = "none"
[parity]
chain = "demo-spec.json"
base_path = "/tmp/parity1"
[network]
port = 30301
[rpc]
port = 8541
apis = ["web3", "eth", "net", "personal", "parity", "parity_set", "traces", "rpc", "parity_accounts"]
[ui]
port = 8181
[dapps]
port = 8081
[account]
password = ["node.pwds"]
[mining]
engine_signer = "0x00Aa39d30F0D20FF03a22cCfc30B7EfbFca597C2"
reseal_on_txs = "none"
parity --config node0.toml
parity --config node1.toml
使用Postman透过JSON RPC来测试
{
"jsonrpc":"2.0",
"method":"parity_enode",
"params":[],
"id":0
}
取得enode连接资讯
{
"jsonrpc":"2.0",
"method":"parity_addReservedPeer",
"params":["enode://6c4f53fc8536553c8f151516b7ee17f4b0719d21abe8fdd273588419cf467e3deafb414cd8efa331e4ad55fd7c2820a303a160895129e142a4306e7c3367d67c@172.20.160.80:30300"],
"id":0
}
你的IP地址会不一样,172.20.160.80
成功加入
最后到 node1 的console画面,会看到 0/1/25 peers,就表示已经连接上。
通过Parity提供的web-based UI可以很容易发送transaction,这边就不赘述了。
在开发时通常会将node跑在server上,让其他人可以透过JSON RPC port连接上去使用,此时只要在config里面加入 [interface] 设定即可。
假设server ip为192.168.1.1,将 node0.toml 修改如下:
[parity]
chain = "demo-spec.json"
base_path = "/tmp/parity0"
[network]
port = 30300
[rpc]
port = 8540
apis = ["web3", "eth", "net", "personal", "parity", "parity_set", "traces", "rpc", "parity_accounts"]
interface = "192.168.1.1"
[ui]
port = 8180
[dapps]
port = 8080
[account]
password = ["node.pwds"]
[mining]
engine_signer = "0x00Bd138aBD70e2F00903268F3Db08f2D25677C9e"
reseal_on_txs = "none"
同样 node1.toml 修改如下:
[parity]
chain = "demo-spec.json"
base_path = "/tmp/parity1"
[network]
port = 30301
[rpc]
port = 8541
apis = ["web3", "eth", "net", "personal", "parity", "parity_set", "traces", "rpc", "parity_accounts"]
interface = "192.168.1.1"
[ui]
port = 8181
[dapps]
port = 8081
[account]
password = ["node.pwds"]
[mining]
engine_signer = "0x00Aa39d30F0D20FF03a22cCfc30B7EfbFca597C2"
reseal_on_txs = "none"