前言
当前区块链大都使用的是投票决定这种方法,但是如何使现实中的投票转换到区块链中,如何让举手表决变得更加智能,如何让投票透明、安全、权威,这是区块链的一大设计思路,有很多人觉得联盟链是个梦,是个虚无缥缈的东西,确实联盟链介于公链的开放和私链的自主中,一不小心就会更加偏向于另外一边,那么如何将这个1/2做的更加像1/2是一个挑战。
本篇文章我们使用FISCO BCOS的委员会设计思想来介绍联盟链投票这件事情,话不多说,直接开始。文中多引用FISCO BCOS官网中的原话,再加上自己的实操与理解,以保证全篇文章的科学性。
环境:
Ubuntu20
FISCO BCOS
FISCO BCOS Console
正文
角色定义
分为治理方、运维方、监管方和业务方。考虑到权责分离,治理方、运维方和开发方权责分离,角色互斥。
治理方: | 拥有投票权,可以参与治理投票,可以增删节点、修改链配置、添加撤销运维、冻结解冻合约、对用户表的写权限控制。链级别的可变配置的权限。 |
运维方: | 由治理方添加运维账号,运维账号可以部署合约、创建表、管理合约版本、冻结解冻本账号部署的合约。 |
业务方: | 业务方账号由运维添加到某个合约,可以调用该合约的写接口。 |
监管方: | 监管方监管链的运行,能够获取链运行中权限变更的记录、能够获取需要审计的数据 |
权限
以下简称治理账号为委员。
增删委员、修改委员权重、修改生效阈值三个操作,需要有效投票权重/总权重>生效阈值生效。其中总权重=SUM(委员权重)
治理账号可以添加运维账号,但治理账号不拥有运维的权限
运维账号可以为某个合约添加业务账号,但运维账号没有业务账号权限
(图片来源于FISCO BCOS官方文档)
权限项
权限操作 | 控制方式 | 命名 | 默认阈值 | 修改方式 |
---|---|---|---|---|
增删委员 | 控制写权限表 | AUTH_ASSIGN_AUTH | 0.5 | 委员投票 |
修改委员权重 | 控制写权限表 | AUTH_ASSIGN_AUTH | 0.5 | 委员投票 |
修改生效投票阈值(投票委员权重和大于该值) | 控制写权限表 | AUTH_ASSIGN_AUTH | 0.5 | 委员投票 |
增删节点(观察/共识) | 控制写共识表 | AUTH_CTRL_NODE | 委员可操作 | |
修改链配置项 | 控制写配置表 | AUTH_MODIFY_CONFIG | 委员可操作 | |
冻结解冻合约 | 合约生命周期 | AUTH_CTRL_CONTRACT_LIFE | 委员可操作 | |
添加撤销运维 | AUTH_CTRL_OPERATOR | 委员可操作 | ||
用户表写权限 | AUTH_CTRL_USER_TABLE | 委员可操作 | ||
部署合约 | _sys_tables_的写权限 | AUTH_CREATE_TABLE | 运维操作 | |
创建表 | _sys_tables_的写权限 | AUTH_CREATE_TABLE | 运维操作 | |
合约版本管理 | CNS | AUTH_CTRL_CNS | 运维操作 | |
冻结解冻本账号部署的合约 | 修改合约状态 | 运维操作 | ||
调用合约 | 合约表写权限 | 业务操作 |
计票与生效
-
所有治理操作需要有效投票数/委员数>生效阈值才能生效
-
每次投票操作,如果是委员投票,则记录操作内容和投票委员,不重复计票
-
每次投票操作,计票结束后,计算有效投票数/委员数,如果大于此操作的生效阈值,则对应操作生效,写入
-
投票设置过期时间,根据块高,blockLimit的10倍,固定不可改
功能列表
-
增删委员计票与生效
-
修改委员权重计票与生效
-
修改生效阈值计票与生效
-
委员增删运维
-
委员解冻冻结合约
-
委员增删节点
-
委员修改系统配置
-
权限项默认阈值存储
-
运维部署合约的权限
-
运维管理合约版本的权限
实操
这里对上文进行一些总结,那么首先先说权限控制这个概念:权限控制通过控制台(console)进行实现,首先登陆使用的是控制台的启动脚本进行登陆,使用-pem参数指定用户文件。
使用get_account.sh脚本进行文件生成,这里我们还是一样生成三个文件,去体验不同的权限控制
新建三个用户
bash get_accounts.sh
之后创建文件
bash get_accounts 私钥
进入控制台
./start.sh 1 -pem ./accounts/私钥
使用我们刚才所创建的私钥文件进入控制台 ,这样就可以指定用户体验权限控制
重复这个操作,开三个窗口,登陆上一步我们所操作的三个用户
将用户1变成委员
grantCommitteeMember 私钥
// 附上私钥将用户加入委员会
listCommitteeMembers
//验证委员会列表中是否有当前用户
使用用户1将用户2任命为委员
grantCommitteeMember 私钥
// 附上私钥将用户加入委员会
listCommitteeMembers
//验证委员会列表中是否有当前用户
验证是否有权限对区块链进行操作
-
tx_count_limit:区块最大打包交易数
-
tx_gas_limit:交易执行允许消耗的最大gas数
-
rpbft_epoch_sealer_num: rPBFT系统配置,一个共识周期内选取的共识节点数目
-
rpbft_epoch_block_num: rPBFT系统配置,一个共识周期出块数目
-
consensus_timeout:PBFT共识过程中,每个区块执行的超时时间,默认为3s,单位为秒
用户1
用户2
用户3
最终我们发现权限控制是真实存在的,那么只需要在登陆区块链以及用户上链之前限定好权限即可
撤销某用户的权限
用户1撤销用户2的权限
用户2撤销用户2的权限
因为我们这里只有三个用户,其中两个用户有权限,所以我们的两个用户各持有50%的决定权,需要两个用户都同意才可以撤销
计算公式:有效票/总票数=2/2=1>0.5
验证是否撤销成功
修改用户权重
首先先查看一下当前用户的权重,因为我们上一步撤销了用户2的权限,所以加入用户3进行对比
queryCommitteeMemberWeight 私钥
grantCommitteeMember 私钥
listCommitteeMembers
updateCommitteeMemberWeight 私钥 权重数
queryCommitteeMemberWeight 私钥
这个时候我们查询后发现,投票的权重并没有更新,这是因为我们设置了用户3为委员,所以现在的投票机制还是五五开,因此我们还是需要去用户3哪里投票
updateCommitteeMemberWeight 私钥 权重数
queryCommitteeMemberWeight 私钥
在用户3这里更新一下我们的权重,在查询一下发现weight变成了2
修改阈值操作
我们发现不管是几个用户一直都是,五五开,或者是超过半数才可以,这个时候我们就会有疑问了,那么怎么样才可以不用五五开或者是46?73?这样的阈值呢
因为我们刚才将用户1的权重设置为了2,所以我们将用户2重新赋予权限
grantCommitteeMember 私钥
listCommiteeMembers
使用用户1将我们的阈值更新为75,之后查询一下
updateThreshold 75
queryThreshold
这个时候我们还是发现,所有的并没有改变,那是因为我们只是有一个用户进行了投票,那么我们切换到其他用户去进行投票
这个时候,就有疑问了,不是75了吗,为什么两个用户投了票就更新了呀,这里呢是因为,在这之前的阈值是50,只需要两个用户投票即可,我们现在设置75也是因为用户1有了两票,当用户多起来了以后,我们就需要根据实际情况去设置权重以及阈值
运维委员设立
我们的委员职责是分开且独立的,不会存在一个人就可以管理整个区块链的情况发生
这里我们使用上面的方法再新建一个账户
bash get_account.sh
bash get_account.sh 私钥文件
在开始之前,我们先部署一下HelloWorld合约,没有任何问题
使用用户1控制台将用户4任命为运维委员
这里我们部署HelloWorld合约
deploy HelloWorld
发现部署失败了,这里的原因就是我们所说的,各司其职,只要有了运维人员,就不在具有运维的职责