使用 Parity 建立Proof-of-Authority (PoA) Ethereum Chain

从无到有建立Ethereum联盟链

开发Ethereum Dapp的过程中,需要一个测试用的chain,之前是使用testrpc或直接连到Ethereum testnet (Ropsten),不过testrpc有各种坑需要处理,而Ropsten testnet则是需要同步与等待区块,相当的烦人。前几天看到Parity 1.5版以后支持建立Proof of Authority Chains,可以直接解决上述的问题,果然一试成主顾。

若你有下列困扰,可以建立自己测试用的PoA chain

  • 公司内网或无对外网路,无法同步区块
  • 降低测试时等待区块的时间
  • 不想碰到testrpc各种坑

PoA Chain特点有

  • 有别于PoW (Proof-of-Work)需要解数学难题来产生block,PoA是依靠预设好的Authority nodes,负责产生block。
  • 可依照需求设定Authority node数量。
  • 可指定产生block的时间,例如收到交易的5秒后产生block。
  • 一般的Ethereum node也可以连接到PoA Chain,正常发起transactions, contracts等。
  • 这篇教学文基本上是照著Parity Demo PoA 教程来撰写。

Parity是一个注重效能的Ethereum Client端软体

1. 安装Parity (1.5.0以上版本)

请自行到Parity官网安装,支持Ubutnu, OSX, Docker, Windows

2. 设定chain spec

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 } } } }
    }
}

  • stepDuration 设定成5秒产生一个区块
  • validators 设定Authority的地方,目前先空著,后续产生account之后再回来填入

将上述资料存成 demo-spec.json

3. 设定两个node

此教学会在同一台机器上跑两个node,因此有些Parity原生的设定参数会有衝突,两个node需要分别设定不同值。

  • -d 指定储存资料与帐号的目录
  • --dport 指定Parity的network port,可用来让其他node连接
  • --jsonrpc-port 这是JSON RPC port,使用web3.js时会需要
  • ui-port Parity提供的Web-based UI port
  • dapps-port Parity Dapps使用的port

可以用下列指令启动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

4. 设定帐号(Account)

我们总共要开3个帐号:2个Authority跟1个user帐号。

步骤1、 首先启动 node0 : parity --config node0.toml

接著开启网页 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 的帐号设定

  • Authority account: 0x00Bd138aBD70e2F00903268F3Db08f2D25677C9e
  • User account: 0x004ec07d2329997267Ec62b4166639513386F32E

步骤2、 再来设定 node1 的帐号,启动 parity --config node1.toml ,步骤相同,连接到 http://localhost:8181 ,pass phrase使用 node1

启动Parity node1

输入node1

完成Authority account

这样就完成 node1 的帐号设定

  • Authority account: 0x00Aa39d30F0D20FF03a22cCfc30B7EfbFca597C2

步骤3、 将Authority account写入 demo-spec.json 档案

"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" }
    }
}

5. 启动Authority node

为了启动Authority node来产生区块,我们必须设定负责产生block的signer,分别是 node0 与 node1 account

步骤1、开启一个 node.pwds 档案,写入 node0 与 node1 的password,内容如下

node0
node1

步骤2、在设定档 node0.toml 加入 [account] 及 [mining] 设定,如下

[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"

步骤3、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
[account]
password = ["node.pwds"]
[mining]
engine_signer = "0x00Aa39d30F0D20FF03a22cCfc30B7EfbFca597C2"
reseal_on_txs = "none"

步骤4、分别启动两个node

parity --config node0.toml

parity --config node1.toml

6、连接两个node

使用Postman透过JSON RPC来测试

步骤1、Post下列JSON资料至 http://localhost:8540 以取得 node0 的enode资料

{
 "jsonrpc":"2.0",
 "method":"parity_enode",
 "params":[],
 "id":0
}

取得enode连接资讯

步骤2、将 node0 的enode加入 node1 ,Post下列JSON资料至node1 (http://localhost:8541 )

{
 "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,就表示已经连接上。

7. 发送transaction

通过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"

你可能感兴趣的:(使用 Parity 建立Proof-of-Authority (PoA) Ethereum Chain)