10. 搭建XPoA共识的超级链网络

XPoA是为许可链设计的共识算法,XPoA共识算法的原理可以参考超级链的设计文档 XPoA技术文档 。许可链指的是所有参与链系统的节点,都需经过许可,未经过许可的节点不可接入系统。下面介绍下如何搭建一个XPoA共识的超级链网络。

10.1. 搭建XPoA共识网络

10.1.1. p2p网络配置

以搭建3节点网络为例,拷贝xuperchain编译产出的output到node1~node3。每个节点需修改配置文件 conf/xchain.yaml 中p2p一节,使用p2pv1,p2pv1是为许可链设计的p2p网络插件。

  1. p2p:
  2. module: p2pv1
  3. # port是节点p2p网络监听的默认端口,如果在一台机器上部署注意端口配置不要冲突,
  4. # node1配置的是47101,node2、node3可以分别设置为47102、47103
  5. port: 47101
  6. # 不使用证书
  7. isUseCert: false
  8. # 配置网络中所有节点的neturl, 格式ip:port, 也加上本节点的neturl
  9. staticNodes:
  10. xuper:
  11. - "127.0.0.1:47101"
  12. - "127.0.0.1:47102"
  13. - "127.0.0.1:47103"

注意,如果节点分布在不同的机器之上,需要把网络地址中的本地ip改为机器的实际ip。

10.1.2. 更新各节点的keys

由于节点目录下的keys都是默认的,node1保持不变,更新node2、node3的keys。更新前需手动删掉data/keys目录。更新keys命令如下:

  1. ./xchain-cli account newkeys

10.1.3. 配置创世块

XuperChain系统支持可插拔共识,通过修改创世块的参数,可以创建一个以XPoA为共识的链。创世块配置位于 data/config/xuper.json ,修改genesis_consensus一节。各个配置参数详解配置说明如下所示:

  1. {
  2. "version" : "1",
  3. "predistribution":[
  4. {
  5. "address" : "dpzuVdosQrF2kmzumhVeFQZa1aYcdgFpN",
  6. "quota" : "100000000000000000000"
  7. }
  8. ],
  9. "maxblocksize" : "128",
  10. "award" : "1000000",
  11. "decimals" : "8",
  12. "award_decay": {
  13. "height_gap": 31536000,
  14. "ratio": 1
  15. },
  16. "gas_price": {
  17. "cpu_rate": 1000,
  18. "mem_rate": 1000000,
  19. "disk_rate": 1,
  20. "xfee_rate": 1
  21. },
  22. "new_account_resource_amount": 1000,
  23. "genesis_consensus":{
  24. "name": "xpoa",
  25. "config": {
  26. // 声明共识的起始时间戳,建议设置为一个刚过去不久的时间戳,更新前10位
  27. "timestamp": "1590636296000000000",
  28. // 每个矿工连续出块的出块间隔
  29. "period":"3000",
  30. // 每一轮内每个矿工轮值任期内连续出块的个数
  31. "block_num":"10",
  32. // xpoa共识依赖的合约名称,无需修改
  33. "contract_name":"xpoa_validates",
  34. // xpoa共识查询候选人的合约方法,无需修改
  35. "method_name":"get_validates",
  36. // 指定第一轮初始矿工,所指定的初始矿工需要在网络中存在,不然系统轮到该节点出块时会没有节点出块
  37. "init_proposer": [
  38. {
  39. "address" : "dpzuVdosQrF2kmzumhVeFQZa1aYcdgFpN"
  40. , "neturl" : "10.26.29.40:47101"
  41. },
  42. {
  43. "address" : "VSML7NenZnGZgCEwtbQDKDSrPHhT5wsu6"
  44. , "neturl" : "10.26.29.40:47102"
  45. },
  46. {
  47. "address" : "bg3KLC3YCmvLWBCNAVHGHLfk3qeWEdoD3"
  48. , "neturl" : "10.26.29.40:47103"
  49. }
  50. ],
  51. // 使用chained-bft
  52. "bft_config": {}
  53. }
  54. }
  55. }

将修改好的1份xuper.json拷贝到另外2个节点的data/config目录下。

注意,拷贝配置内容到xuper.json时需去掉注释。

10.1.4. 创建链并启动xchain

检查data/blockchain 目录下内容为空之后,创建链并启动所有节点。命令如下:

  1. # 创建xuper链
  2. ./xchain-cli createChain
  3. # 启动服务节点
  4. nohup ./xchain &
  5. # check服务运行状况,修改-H后参数,可以查询每个节点状态
  6. for((i=1;i<=3;i++));do
  7. ./xchain-cli status -H 127.0.0.1:3710$i |grep -i height
  8. done

通过变更-H 参数,查看每个节点的状态,若所有节点高度都是一致变化的,则证明环境状态正常。

10.2. 验证集合合约部署和调用

XPoA共识算法中,候选人的变更依赖”验证集合”合约,所以需要部署”验证集合”合约。通过调用合约中的add_validate方法新增候选人、del_validate方法删除候选人、update_validate方法更新候选人neturl、get_validates方法查询候选人列表。通过设置合约方法的ACL,可以限制哪些用户具有变更候选人的权限,设置方法参考 设置合约方法的ACL

10.2.1. 创建合约账号

合约账号用来做合约的管理,创建合约账号,并给合约账号转账。

  1. # 创建合约账号
  2. [work@]$ node1 -> ./xchain-cli account new --account 1111111111111111 --fee 1000 -H 127.0.0.1:37101
  3. # 执行结果
  4. # contract response:
  5. # {
  6. # "pm": {
  7. # "rule": 1,
  8. # "acceptValue": 1.0
  9. # },
  10. # "aksWeight": {
  11. # "dpzuVdosQrF2kmzumhVeFQZa1aYcdgFpN": 1.0
  12. # }
  13. # }
  14. # The gas you cousume is: 1000
  15. # The fee you pay is: 1000
  16. # Tx id: eb9924c85a16d72f5daf6e6feabb130ef9c8a3ce8f507db08dcb726111aef74f
  17. # account name: XC1111111111111111@xuper
  18. # 给合约账号转账
  19. [work@]$ node1 -> ./xchain-cli transfer --to XC1111111111111111@xuper --amount 100000000 -H 127.0.0.1:37101
  20. # 执行结果
  21. # ec6fa53446a8c6ab0d8d45f2bba80c7e5122341ce9b0c85779f80ce1a55f37b6

10.2.2. 编译合约

“验证集合”合约源码位于core/contractsdk/cpp/example/xpoa_validates,执行如下命令编译合约,编译结果为xpoa_validates.wasm。

  1. # prj是xuperchain源码所在目录,设定环境变量
  2. export PATH=$prj/xuperchain/output:$PATH
  3. export XDEV_ROOT=$prj/xuperchain/core/contractsdk/cpp
  4. # 编译合约
  5. cd $prj/xuperchain/core/contractsdk/cpp/example/xpoa_validates
  6. xdev build

10.2.3. 部署合约

部署合约,并设置node1、node2为初始候选人。

  1. [work@]$ node1 -> ./xchain-cli wasm deploy --account XC1111111111111111@xuper --cname xpoa_validates --arg '{"addresss":"dpzuVdosQrF2kmzumhVeFQZa1aYcdgFpN;VSML7NenZnGZgCEwtbQDKDSrPHhT5wsu6","neturls":"127.0.0.1:47101;127.0.0.1:47102"}' ./xpoa_validates.wasm --fee 222065 -H 127.0.0.1:37101
  2. # 执行结果
  3. # contract response: initialize succeed
  4. # The gas you cousume is: 221920
  5. # The fee you pay is: 222065
  6. # Tx id: 4f9f11afcf080199b93d5f308b6dc0e07ce5b9099c36cbf9b4edb2ee398bcfa3

参数说明:

  • wasm deploy:部署wasm合约
  • –account XC1111111111111111@xuper:此为部署wasm合约的账号
  • –cname xpoa_validates :合约名称,需与xuper.json中配置的contract_name参数一致
  • –arg :此为传入合约的参数,这里设置初始矿工,所指定的初始矿工需要在网络中存在,多个矿工用分号间隔,且address与netrul要 一一对应。
  • ./xpoa_validates.wasm :是编译合约产出的文件

10.2.4. 增加候选人

以添加node3为候选人为例,添加后等待1分钟,调查看候选人命令,查看是否添加成功。

  1. [work@]$ node1 -> ./xchain-cli wasm invoke xpoa_validates --method add_validate --args '{"address":"bg3KLC3YCmvLWBCNAVHGHLfk3qeWEdoD3","neturl":"127.0.0.1:47103"}' --fee 300 -H 127.0.0.1:37101
  2. # 执行结果
  3. # contract response: {"address":"bg3KLC3YCmvLWBCNAVHGHLfk3qeWEdoD3","neturl":"127.0.0.1:47103"}
  4. # The gas you cousume is: 252
  5. # The fee you pay is: 300
  6. # Tx id: 5a3993d0e001aa0b140b204c013c6ea0b9741f8e1dfe81db71887579d63ce785

参数说明:

  • wasm invoke:调用合约
  • –method add_validate:调用add_validate方法
  • –args:传入的参数,填写待添加候选人的address和neturl

10.2.5. 查看候选人

查询结果中,候选人按字典序排列。

  1. [work@]$ node1 -> ./xchain-cli wasm invoke xpoa_validates --method get_validates -H 127.0.0.1:37101
  2. # 执行结果
  3. # contract response: {"proposers":[{"address":"VSML7NenZnGZgCEwtbQDKDSrPHhT5wsu6","neturl":"127.0.0.1:47102"},{"address":"bg3KLC3YCmvLWBCNAVHGHLfk3qeWEdoD3","neturl":"127.0.0.1:47103"},{"address":"dpzuVdosQrF2kmzumhVeFQZa1aYcdgFpN","neturl":"127.0.0.1:47101"}]}
  4. # The gas you cousume is: 439
  5. # You need add fee
  • wasm invoke:调用合约
  • –method get_validates:调用get_validates方法

10.2.6. 更新候选人

候选人的netrul发生变化后,需要更新。以更新node3的neturl为例,比如更新为localhost:47103。修改后等待1分钟,调查看候选人命令,查看是否修改成功。

  1. [work@]$ node1 -> ./xchain-cli wasm invoke xpoa_validates --method update_validate -a '{"address":"bg3KLC3YCmvLWBCNAVHGHLfk3qeWEdoD3","neturl":"localhost:47103"}' --fee 300 -H 127.0.0.1:37101
  2. # 执行结果
  3. # contract response: {"address":"bg3KLC3YCmvLWBCNAVHGHLfk3qeWEdoD3","neturl":"localhost:47103"}
  4. # The gas you cousume is: 263
  5. # The fee you pay is: 300
  6. # Tx id: 6e6289c513169cd32c44fa05bb06c0eba0f37f05acd5eb6ae4573ae266363b76

参数说明:

  • wasm invoke:调用合约
  • –method update_validate:调用update_validate方法
  • –args:传入的参数,填写待更新候选人的address和neturl

10.2.7. 删除候选人

将node3从候选人集合删除。删除后等待1分钟,调查看候选人命令,查看是否删除成功。

  1. [work@]$ node1 -> ./xchain-cli wasm invoke xpoa_validates --method del_validate -a '{"address":"bg3KLC3YCmvLWBCNAVHGHLfk3qeWEdoD3"}' --fee 300 -H 127.0.0.1:37101
  2. # 执行结果
  3. # contract response: ok
  4. # The gas you cousume is: 128
  5. # The fee you pay is: 300
  6. # Tx id: a033b1c4b548c3515a29b5d643fdad20cc778c71a75a95869ddaae067177d7c4
  • wasm invoke:调用合约
  • –method del_validate:调用del_validate方法
  • –args:传入的参数,填写待删除候选人的address和neturl

10.2.8. 查看当前正在出块的候选人

通过日志,可查看当前正在出块的候选人。示例如下,其中proposer是正在出块候选人。并且,多个候选人按字典序轮值出块。

  1. [work@]$ node1 -> tailf logs/xchain.log|grep "bft NewView"
  2. t=2020-06-28T17:04:24+0800 lvl=info msg="bft NewView" module=xchain viewNum=550 dpm.currentView=550 proposer=bg3KLC3YCmvLWBCNAVHGHLfk3qeWEdoD3 preProposer=VSML7NenZnGZgCEwtbQDKDSrPHhT5wsu6 err=nil
  3. t=2020-06-28T17:04:27+0800 lvl=info msg="bft NewView" module=xchain viewNum=551 dpm.currentView=551 proposer=bg3KLC3YCmvLWBCNAVHGHLfk3qeWEdoD3 preProposer=VSML7NenZnGZgCEwtbQDKDSrPHhT5wsu6 err=nil

10.3. 常见问题

  • 端口冲突:注意如果在一台机器上部署多个节点,各个节点的RPC监听端口以及p2p监听端口都需要设置地不相同,避免冲突;
  • 节点公私钥冲突:注意网络中不同节点./data/keys下的文件内容都应该不一样,这个文件夹是节点在网络中的唯一标识,每个节点需要独自生成,否则网络启动异常;
  • 遇到The gas you cousume is: XXXX, You need add fee 通过加–fee XXXX 参数附加资源;
  • Chained-Bft算法要求3个矿工的集群,不可以有矿工故障,所以如果使用更新候选人接口将节点neturl更新错误,将无法出块,需删除data/blockchain 目录下内容后,从10.1.4节开始重新部署环境。