在以太坊上实现联盟链小结

搞了三四个月联盟链,基本上算是告一段落,大概梳理下所做的东西,希望能对要做联盟链的人有所帮助。

在写这篇文章前,简单介绍下联盟链的功能。 * __国密和国际算法切换__ * __参数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指定加密类型,PermisionWlSendTxPermisionWlCreateTx是权限里面是白名单还说黑名单有效,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评估 gaslimitgas的方法需要返回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很难查询合约 执行失败原因。

本文参与登链社区写作激励计划 ,好文好收益,欢迎正在阅读的你也加入。

  • 发表于 2020-08-03 18:55
  • 阅读 ( 552 )
  • 学分 ( 92 )
  • 分类:Geth

该内容来自于互联网公开内容,非区块链原创内容,如若转载,请注明出处:https://htzkw.com/archives/27836

联系我们

aliyinhang@gmail.com