在以太坊上实现联盟链的小结
搞了三四个月联盟链,基本上算是告一段落,大概梳理下所做的东西,希望能对要做联盟链的人有所帮助。
在写这篇文章前,简单介绍下联盟链的功能。
- 国密和国际算法切换
- 参数toml配置
- 有币无币
- 支持gmssl
- p2p的证书准入
- 委员会成员更新
- solc编译器
- tendermint共识
- 权限准入
- 交易校验
- rpc api
- 状态存储
- 系统合约
加密算法
-
国密和S256,P256
支持国密sm2,sm3,sm4,国际的支持p256,比特币和以太坊都使用的s256.刚开始做的时候计算支持p256和国密,因为go sdk里面证书使用了p256。后在做的过程中发现国外证书很多还需要支持RSA,遂引入了gmssl,委员会中的PK公钥和证书做了分离。
recover公钥
Toml文件配置
toml文件的优点在于不需要在启动的时候指定一系列参数
-
节点信息
- 网络ID 同步模式
- 委员会私钥
- IP和端口
-
txpool
- gas门槛
- txpool账户数
-
节点rpc端口api
- 存储目录
- ipc websocket
- 开放api
- rpc 端口
-
p2p节点配置
- 证书
- 节点私钥
- 节点连接数
- 监听地址
创世区块
创世里面指定了 UseGas
指定有无币, KindOfCrypto
指定加密类型, PermisionWlSendTx
, PermisionWlCreateTx
是权限里面是白名单还说黑名单有效, Committee
指定了委员会的成员信息, CertList
指定证书列表。
return &Genesis{ Config: params.TestnetChainConfig, UseGas: 1, IsCoin: 1, KindOfCrypto: 2, PermisionWlSendTx: 1, PermisionWlCreateTx: 1, Timestamp: 1537891200, Coinbase: common.HexToAddress("0x0000000000000000000000000000000000000000"), ParentHash: common.HexToHash("0x0000000000000000000000000000000000000000000000000000000000000000"), Alloc: map[common.Address]types.GenesisAccount{ common.HexToAddress("0x68231C69431Cd7592356aBaC59E7A9D325406653"): {Balance: amount1}, }, Committee: []*types.CommitteeMember{ {Coinbase: getAddressFromPub(seedkey1), Publickey: seedkey1}, }, CertList: certList, }
有无币
当无币时 EstimateGas
, SuggestPrice
评估 gaslimit
和 gas
的方法需要返回0, tx_pool
中关于 gas
的判断和 evm
扣除 gas
的操作都要去掉。
GMSSL
这个模块主要做证书的生成,自认证,颁发证书,支持国密和RSA。
P2P证书的准入
节点启动的时候,委员会成员具有根证书,新接入的节点需要跟证书授权。
- 节点发现中加入证书校验,校验通过发送邻居节点。
- 在秘钥交换中也会校验证书,校验通过会建立连接。
- 支持tls,在开发中。
委员会成员更新
委员会成员的更新需要当届成员发起提案,当三分之二成员对同一个成员发起了 提案
,则此成员在 下一届
会成为新的委员会成员。提案是通过 交易
达成的,在链上部署了一个证书 系统合约
,所有的委员会只需发一笔交易,即可对一个成员的 删除
和 添加
.
solc编译器
由于abi中 函数的签名
用通过 sha3函数名+参数
得到的,所以如果你用以太坊提供的solc程序编译的合约,在链上是部署不成功的,这时需要用国密的solc编译器编译。
tendermint共识
众所周知,POW的共识TPS很低,想提高TPS,BFT算法是很好的选择,tendermint共识做的非常棒,能在5s内出块。
权限准入
这个恐怕是联盟链里面最复杂的场景了,花费了很长时间测试。主要有两个 基本功能
- 发交易权限
- 创建合约权限
这两大基本权限衍生出 管理员
和 普通成员
。管理员可以授予新成员普通成员权限和管理员权限。
-
组权限
:如果想对一批人进行管理,这里引入了组权限
,即创建一个群组,将一成员加到组里面,如果想移除组里所有人的权限,可删除组。组里面也有成员
和管理员
权限。 -
合约访问权限
:自己的创建的合约,可设置谁可以访问,只有添加到访问列表里的成员才可访问合约,这里面也有成员
和管理员
权限。
权限是 系统合约
实现的,任何的权限控制都需要通过 交易
来完成,权限是 立即生效
的,这个和证书合约有所不同。
里面用到了 大量的map
,导致存储的时候需要实现rlp方法,对 map
进行 排序
。
交易校验
由于国密recover公钥没有现成的实现,在交易字段里面加入了PK,这个和SDK联调的时候还是有一些问题,首先hash算法要匹配,计算出的TxHash要一样, RLP数据
的顺序也需一致。校验签名通过之后,用 PK
计算 账户地址
。
RPC API
rpc
中加入了证书和权限的一些查询方法,通过修改web3ext.go完成的, inputDefaultBlockNumberFormatter
这个字段在console里面可以不需要输入,通过json rpc的时候则需要填写,例如 latest
。
状态存储
合约和权限都是系统合约,存储的方式与合约存储一致,在状态里面加了种类型,方便状态回退。
系统合约
系统合约类似预编译合约,功能比以太坊里面的预编译合约强大一些,可操作状态,系统合约里面 不可存时间
,会造成状态不一致,系统合约debug比较烦, Receipt
里面 无Error
字段, Dapp
很难查询合约 执行失败
原因。
在写这篇文章前,简单介绍下联盟链的功能。
- 国密和国际算法切换
- 参数toml配置
- 有币无币
- 支持gmssl
- p2p的证书准入
- 委员会成员更新
- solc编译器
- tendermint共识
- 权限准入
- 交易校验
- rpc api
- 状态存储
- 系统合约
加密算法
-
国密和S256,P256
支持国密sm2,sm3,sm4,国际的支持p256,比特币和以太坊都使用的s256.刚开始做的时候计算支持p256和国密,因为go sdk里面证书使用了p256。后在做的过程中发现国外证书很多还需要支持RSA,遂引入了gmssl,委员会中的PK公钥和证书做了分离。
recover公钥
Toml文件配置
toml文件的优点在于不需要在启动的时候指定一系列参数
-
节点信息
- 网络ID 同步模式
- 委员会私钥
- IP和端口
-
txpool
- gas门槛
- txpool账户数
-
节点rpc端口api
- 存储目录
- ipc websocket
- 开放api
- rpc 端口
-
p2p节点配置
- 证书
- 节点私钥
- 节点连接数
- 监听地址
创世区块
创世里面指定了 UseGas
指定有无币, KindOfCrypto
指定加密类型, PermisionWlSendTx
, PermisionWlCreateTx
是权限里面是白名单还说黑名单有效, Committee
指定了委员会的成员信息, CertList
指定证书列表。
return &Genesis{ Config: params.TestnetChainConfig, UseGas: 1, IsCoin: 1, KindOfCrypto: 2, PermisionWlSendTx: 1, PermisionWlCreateTx: 1, Timestamp: 1537891200, Coinbase: common.HexToAddress("0x0000000000000000000000000000000000000000"), ParentHash: common.HexToHash("0x0000000000000000000000000000000000000000000000000000000000000000"), Alloc: map[common.Address]types.GenesisAccount{ common.HexToAddress("0x68231C69431Cd7592356aBaC59E7A9D325406653"): {Balance: amount1}, }, Committee: []*types.CommitteeMember{ {Coinbase: getAddressFromPub(seedkey1), Publickey: seedkey1}, }, CertList: certList, }
有无币
当无币时 EstimateGas
, SuggestPrice
评估 gaslimit
和 gas
的方法需要返回0, tx_pool
中关于 gas
的判断和 evm
扣除 gas
的操作都要去掉。
GMSSL
这个模块主要做证书的生成,自认证,颁发证书,支持国密和RSA。
P2P证书的准入
节点启动的时候,委员会成员具有根证书,新接入的节点需要跟证书授权。
- 节点发现中加入证书校验,校验通过发送邻居节点。
- 在秘钥交换中也会校验证书,校验通过会建立连接。
- 支持tls,在开发中。
委员会成员更新
委员会成员的更新需要当届成员发起提案,当三分之二成员对同一个成员发起了 提案
,则此成员在 下一届
会成为新的委员会成员。提案是通过 交易
达成的,在链上部署了一个证书 系统合约
,所有的委员会只需发一笔交易,即可对一个成员的 删除
和 添加
.
solc编译器
由于abi中 函数的签名
用通过 sha3函数名+参数
得到的,所以如果你用以太坊提供的solc程序编译的合约,在链上是部署不成功的,这时需要用国密的solc编译器编译。
tendermint共识
众所周知,POW的共识TPS很低,想提高TPS,BFT算法是很好的选择,tendermint共识做的非常棒,能在5s内出块。
权限准入
这个恐怕是联盟链里面最复杂的场景了,花费了很长时间测试。主要有两个 基本功能
- 发交易权限
- 创建合约权限
这两大基本权限衍生出 管理员
和 普通成员
。管理员可以授予新成员普通成员权限和管理员权限。
-
组权限
:如果想对一批人进行管理,这里引入了组权限
,即创建一个群组,将一成员加到组里面,如果想移除组里所有人的权限,可删除组。组里面也有成员
和管理员
权限。 -
合约访问权限
:自己的创建的合约,可设置谁可以访问,只有添加到访问列表里的成员才可访问合约,这里面也有成员
和管理员
权限。
权限是 系统合约
实现的,任何的权限控制都需要通过 交易
来完成,权限是 立即生效
的,这个和证书合约有所不同。
里面用到了 大量的map
,导致存储的时候需要实现rlp方法,对 map
进行 排序
。
交易校验
由于国密recover公钥没有现成的实现,在交易字段里面加入了PK,这个和SDK联调的时候还是有一些问题,首先hash算法要匹配,计算出的TxHash要一样, RLP数据
的顺序也需一致。校验签名通过之后,用 PK
计算 账户地址
。
RPC API
rpc
中加入了证书和权限的一些查询方法,通过修改web3ext.go完成的, inputDefaultBlockNumberFormatter
这个字段在console里面可以不需要输入,通过json rpc的时候则需要填写,例如 latest
。
状态存储
合约和权限都是系统合约,存储的方式与合约存储一致,在状态里面加了种类型,方便状态回退。
系统合约
系统合约类似预编译合约,功能比以太坊里面的预编译合约强大一些,可操作状态,系统合约里面 不可存时间
,会造成状态不一致,系统合约debug比较烦, Receipt
里面 无Error
字段, Dapp
很难查询合约 执行失败
原因。
本文参与登链社区写作激励计划 ,好文好收益,欢迎正在阅读的你也加入。
- 发表于 7分钟前
- 阅读 ( 6 )
- 学分 ( 0 )
- 分类:Geth