Skip to content

Commit

Permalink
Merge pull request #1242 from bysomeone/feat-parachain-rollup
Browse files Browse the repository at this point in the history
Feat parachain rollup
  • Loading branch information
vipwzw authored Feb 21, 2023
2 parents 6995b7e + dc33199 commit 8dabc1c
Show file tree
Hide file tree
Showing 71 changed files with 5,579 additions and 428 deletions.
14 changes: 11 additions & 3 deletions chain33.para.toml
Original file line number Diff line number Diff line change
Expand Up @@ -83,6 +83,13 @@ httpApi=["eth","web3","personal","admin","net"]
wsAddr="localhost:8546"
wsApi=["eth","web3","personal","admin","net"]

[rpc.sub.parachain]
#主链节点的grpc服务器ip,当前可以支持多ip负载均衡,如“118.31.177.1:8802,39.97.2.127:8802”
#mainChainGrpcAddr="jiedian2.bityuan.com,cloud.bityuan.com"
mainChainGrpcAddr="localhost:8802"
#配置grpc负载均衡为sync模式
useGrpcLBSync=false

[mempool]
name="para"
poolCacheSize=10240
Expand Down Expand Up @@ -120,9 +127,7 @@ halvePeriod=1000


[consensus.sub.para]
#主链节点的grpc服务器ip,当前可以支持多ip负载均衡,如“118.31.177.1:8802,39.97.2.127:8802”
#ParaRemoteGrpcClient="jiedian2.bityuan.com,cloud.bityuan.com"
ParaRemoteGrpcClient="localhost:8802"
#ParaRemoteGrpcClient配置已变更为mainChainGrpcAddr
#主链指定高度的区块开始同步
startHeight=345850
#主链指定高度后等待块数,防止主链回滚,联盟链最小为1,小于1则采用缺省高度100
Expand Down Expand Up @@ -397,6 +402,9 @@ Enable=0
[fork.sub.vote]
Enable=0

[fork.sub.rollup]
Enable=-1

[fork.sub.accountmanager]
Enable=0

Expand Down
10 changes: 7 additions & 3 deletions chain33.para.toml.readme
Original file line number Diff line number Diff line change
Expand Up @@ -72,6 +72,13 @@ whitelist=["127.0.0.1"]
jrpcFuncWhitelist=["*"]
grpcFuncWhitelist=["*"]

[rpc.sub.parachain]
#主链节点的grpc服务器ip,当前可以支持多ip负载均衡,如“118.31.177.1:8802,39.97.2.127:8802”
#mainChainGrpcAddr="jiedian2.bityuan.com,cloud.bityuan.com"
mainChainGrpcAddr="localhost:8802"
#配置grpc负载均衡为sync模式
useGrpcLBSync=false

#兼容支持ETH 部分RPC接口
[rpc.sub.eth]
enable=false
Expand Down Expand Up @@ -120,9 +127,6 @@ halvePeriod=1000


[consensus.sub.para]
#主链节点的grpc服务器ip,当前可以支持多ip负载均衡,如“118.31.177.1:8802,39.97.2.127:8802”
#ParaRemoteGrpcClient="cloud.bityuan.com,jiedian2.bityuan.com"
ParaRemoteGrpcClient="localhost:8802"
#主链指定高度的区块开始同步
startHeight=345850
#主链指定高度后等待块数,防止主链回滚,联盟链最小为1,小于1则采用缺省高度100
Expand Down
2 changes: 1 addition & 1 deletion go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ module github.com/33cn/plugin
go 1.16

require (
github.com/33cn/chain33 v1.67.6-0.20230202063800-bec7bd8482fe
github.com/33cn/chain33 v1.68.0
github.com/BurntSushi/toml v0.3.1
github.com/NebulousLabs/Sia v1.3.7
github.com/NebulousLabs/errors v0.0.0-20181203160057-9f787ce8f69e // indirect
Expand Down
4 changes: 2 additions & 2 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -47,8 +47,8 @@ dmitri.shuralyov.com/html/belt v0.0.0-20180602232347-f7d459c86be0/go.mod h1:JLBr
dmitri.shuralyov.com/service/change v0.0.0-20181023043359-a85b471d5412/go.mod h1:a1inKt/atXimZ4Mv927x+r7UpyzRUf4emIoiiSC2TN4=
dmitri.shuralyov.com/state v0.0.0-20180228185332-28bcc343414c/go.mod h1:0PRwlb0D6DFvNNtx+9ybjezNCa8XF0xaYcETyp6rHWU=
git.apache.org/thrift.git v0.0.0-20180902110319-2566ecd5d999/go.mod h1:fPE2ZNJGynbRyZ4dJvy6G277gSllfV2HJqblrnkyeyg=
github.com/33cn/chain33 v1.67.6-0.20230202063800-bec7bd8482fe h1:ZuymWAASnCPpODNC/LCHsYRMmC7tsrkenSuG9eTz8/4=
github.com/33cn/chain33 v1.67.6-0.20230202063800-bec7bd8482fe/go.mod h1:rOabIpP0KWiehXmX6ShOrAveTUvdoQvjUkUePdwk/oQ=
github.com/33cn/chain33 v1.68.0 h1:+KNYtePKHf/k9xqU791CNsap18WEFcY8a+Aa807KKrY=
github.com/33cn/chain33 v1.68.0/go.mod h1:rOabIpP0KWiehXmX6ShOrAveTUvdoQvjUkUePdwk/oQ=
github.com/AndreasBriese/bbloom v0.0.0-20180913140656-343706a395b7/go.mod h1:bOvUY6CB00SOBii9/FifXqc0awNKxLFCL/+pkDPuyl8=
github.com/AndreasBriese/bbloom v0.0.0-20190306092124-e2d15f34fcf9/go.mod h1:bOvUY6CB00SOBii9/FifXqc0awNKxLFCL/+pkDPuyl8=
github.com/AndreasBriese/bbloom v0.0.0-20190825152654-46b345b51c96 h1:cTp8I5+VIoKjsnZuH8vjyaysT/ses3EvZeaV/1UkF2M=
Expand Down
11 changes: 6 additions & 5 deletions plugin/consensus/init/init.go
Original file line number Diff line number Diff line change
@@ -1,11 +1,12 @@
package init

import (
_ "github.com/33cn/plugin/plugin/consensus/dpos" //auto gen
_ "github.com/33cn/plugin/plugin/consensus/para" //auto gen
_ "github.com/33cn/plugin/plugin/consensus/pbft" //auto gen
_ "github.com/33cn/plugin/plugin/consensus/qbft" //auto gen
_ "github.com/33cn/plugin/plugin/consensus/raft" //auto gen
_ "github.com/33cn/plugin/plugin/consensus/dpos" //auto gen
_ "github.com/33cn/plugin/plugin/consensus/para" //auto gen
_ "github.com/33cn/plugin/plugin/consensus/pbft" //auto gen
_ "github.com/33cn/plugin/plugin/consensus/qbft" //auto gen
_ "github.com/33cn/plugin/plugin/consensus/raft" //auto gen
_ "github.com/33cn/plugin/plugin/consensus/rollup"
_ "github.com/33cn/plugin/plugin/consensus/tendermint" //auto gen
_ "github.com/33cn/plugin/plugin/consensus/ticket" //auto gen
)
1 change: 0 additions & 1 deletion plugin/consensus/para/para.go
Original file line number Diff line number Diff line change
Expand Up @@ -70,7 +70,6 @@ type client struct {

type subConfig struct {
WriteBlockMsec int64 `json:"writeBlockMsec,omitempty"`
ParaRemoteGrpcClient string `json:"paraRemoteGrpcClient,omitempty"`
StartHeight int64 `json:"startHeight,omitempty"`
WaitMainBlockNum int64 `json:"waitMainBlockNum,omitempty"`
GenesisStartHeightSame bool `json:"genesisStartHeightSame,omitempty"`
Expand Down
1 change: 1 addition & 0 deletions plugin/consensus/para/para_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -195,6 +195,7 @@ func getMockLastBlock(para *client, returnBlock *types.Block) {
para.BaseClient = baseCli

qClient := &qmocks.Client{}
qClient.On("GetConfig").Return(&types.Chain33Config{})
para.InitClient(qClient, initBlock)

msg := queue.NewMessage(0, "", 1, returnBlock)
Expand Down
2 changes: 1 addition & 1 deletion plugin/consensus/para/paramultidownload.go
Original file line number Diff line number Diff line change
Expand Up @@ -142,7 +142,7 @@ func (m *multiDldClient) testConn(conn *connectCli, inv *inventory) {

func (m *multiDldClient) getConns(inv *inventory) error {
cfg := m.paraClient.GetAPI().GetConfig()
paraRemoteGrpcIps := types.Conf(cfg, "config.consensus.sub.para").GStr("ParaRemoteGrpcClient")
paraRemoteGrpcIps := cfg.GetModuleConfig().RPC.ParaChain.MainChainGrpcAddr
ips := strings.Split(paraRemoteGrpcIps, ",")
var conns []*connectCli
for _, ip := range ips {
Expand Down
150 changes: 150 additions & 0 deletions plugin/consensus/rollup/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,150 @@
# 平行链扩容

即平行链自主打包出块, 并通过rollup只将状态数据提交至主链存证


## 功能
rollup 涉及功能介绍

### 交易打包
- 平行链需要配置挖矿共识, 并自主打包交易, 产生区块
- 交易需要直接发送至平行链端, 否则无法被打包

### 状态提交
状态提交包括全量提交和精简提交模式, 同时包含超时提交及分段提交策略

#### 精简提交
- 验证者节点对本地的区块头数据共识, 并提交至主链rollup合约存证
- 默认每32个区块触发一次提交


#### 全量提交
- 验证者节点对本地的区块及交易数据共识, 并提交至主链rollup合约存证
- 默认至少收集128笔交易触发一次提交, 该种模式下交易必须采用bls算法签名
- 建议crypto配置中限制签名算法, 避免误发送非bls签名的交易

#### 超时提交
- 本地一直不生成新区块, 且存在未提交区块数据时, 触发超时提交
- 配置项maxCommitInterval指定

#### 分段提交
- 仅在全量提交中会触发
- 单个区块交易过多, 单次提交数据超过最大交易容量, 触发分段

### 资产跨链
- rollup模式兼容已有的资产跨链转账, 但跨链结算需要等到状态提交后
- 跨链交易会被转发到主链优先执行, 主链执行后由平行链自动拉取到本地执行
- 如果交易组中包含有跨链交易, 则交易组判定为跨链交易


### 区块同步
- 支持节点间基于p2p区块同步
- 配置项isParaChain需要置为false


## 配置

### 配置文件

基于已有平行链配置文件做调整
- 自主挖矿打包出块, 为已有配置改动, 参照联盟链节点, 包括mempool, 共识, 以及p2p等
- 状态提交, 为新增配置, 即rollup关联配置

```toml
[blockchain]
# 配置为false或删除, 该配置用于经典平行链模式, 会限制节点间相互同步
isParaChain = false


[mempool]
# 配置para以外的mempool插件
name="timeline"
poolCacheSize=10240
# 最低交易费率, 根据需要配置
minTxFeeRate=0


# p2p功能需开启, 建议使用dht插件
[p2p]
types=["dht"]
enable=true

[p2p.sub.dht]
port=13803
DHTDataPath="paradatadir/p2pstore"


# 平行链相关的rpc配置
[rpc.parachain]
#主链节点的grpc服务器ip,当前可以支持多ip负载均衡,如“118.31.177.1:8802,39.97.2.127:8802”
mainChainGrpcAddr="localhost:8802"
# 平行链跨链交易需要转发到主链
forwardExecs=["paracross"]
forwardActionNames=["crossAssetTransfer"]


[consensus]
# 挖矿共识, 平行链需要自主打包, 需配置联盟链类型共识, 如tendermint, pbft等, 测试可用solo/raft
name="solo"
# 提交共识, 验证节点需要配置, 删除该配置即可关闭rollup功能
committer="rollup"

[consensus.sub.rollup]

# 配置节点账户私钥, 隐秘性不好, 用于测试
authKey=""
# 当authKey未配置时, 支持配置节点账户地址
# 即从钱包中获取对应的私钥, 节点需要创建钱包并解锁导入对应的私钥
authAccount=""

# 全量数据即提交所有交易源数据, 此时交易签名必须为bls类型
# 默认关闭, 即仅提交区块header数据
fullDataCommit=false
# 最大状态提交间隔时长
# 最低60s, 默认5min
maxCommitInterval=60 #seconds
# 设置平行链启动时对应的主链高度
startHeight=0
# 同步主链区块头, 预留高度, 减少回滚概率
# 默认12, 最低设为1
reservedMainHeight=12
```


### 部署配置
- 主链开启rollup合约
- 验证节点主链质押, 对应平行链的NodeGroup配置
- 节点共识提交采用bls签名, 在配置NodeGroup时需要指定节点的bls公钥信息

```
# 命令行基于验证节点私钥生成对应的bls公钥信息
./cli para bls pub -p <nodeAuthKey>
# 主链 apply node group构建交易
./cli para nodegroup apply --paraName=<paraTitle> -a <nodeAuthAddr> -p <nodeBlsPub> -c <frozenAmount>
# 主链 approve node group构建交易, applyID即apply交易的哈希
./cli para nodegroup approve --paraName=<paraTitle> -c <frozenAmount> -i <applyID>
```

[NodeGroup相关文档](https://chain.33.cn/document/134)


## 命令行


```
# 查看平行链rollup状态
./cli rollup status -t <paraTitle>
# 查看单轮提交的汇总信息
./cli rollup round -t <paraTitle> -r <roundNum>
# 查看验证者bls公钥信息
./cli rollup validator -t <paraTitle>
```

99 changes: 99 additions & 0 deletions plugin/consensus/rollup/cache.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,99 @@
package rollup

import (
"bytes"
"sync"

rtypes "github.com/33cn/plugin/plugin/dapp/rollup/types"
)

const (
// 缓存已提交的历史checkpoint数量(主要应对主链可能的分叉回滚情况)
historyCacheCount = 10
)

type commitCache struct {
lock sync.RWMutex
minCacheRound int64
commitList map[int64]*commitInfo
signList map[int64]*validatorSignMsgSet
}

func newCommitCache(currRound int64) *commitCache {

c := &commitCache{minCacheRound: currRound}
c.commitList = make(map[int64]*commitInfo, 32)
c.signList = make(map[int64]*validatorSignMsgSet, 32)
return c
}

func (c *commitCache) addCommitInfo(info *commitInfo) {
c.lock.Lock()
defer c.lock.Unlock()

c.commitList[info.cp.CommitRound] = info
}

func (c *commitCache) getCheckPoint(round int64) *rtypes.CheckPoint {

c.lock.RLock()
defer c.lock.RUnlock()
return c.commitList[round].cp
}

func (c *commitCache) addValidatorSign(isSelf bool, sign *rtypes.ValidatorSignMsg) {
c.lock.Lock()
defer c.lock.Unlock()
set, ok := c.signList[sign.CommitRound]
if !ok {
set = &validatorSignMsgSet{others: make([]*rtypes.ValidatorSignMsg, 0, 8)}
c.signList[sign.CommitRound] = set
}
if isSelf {
set.self = sign
return
}

// 检测是否有重复
for _, other := range set.others {
if bytes.Equal(sign.PubKey, other.PubKey) {
return
}
}
set.others = append(set.others, sign)
}

// clean already commit batch and sign
func (c *commitCache) cleanHistory(currRound int64) {
c.lock.Lock()
defer c.lock.Unlock()

maxDelRound := currRound - historyCacheCount
for i := c.minCacheRound; i <= maxDelRound; i++ {
delete(c.signList, i)
delete(c.commitList, i)
}

if maxDelRound >= c.minCacheRound {
c.minCacheRound = maxDelRound + 1
}
}

//

func (c *commitCache) getPreparedCommit(round int64, aggreSign aggreSignFunc) *commitInfo {

c.lock.RLock()
defer c.lock.RUnlock()

signSet := c.signList[round]
pubs, aSign := aggreSign(signSet)
if pubs == nil {
return nil
}
info := c.commitList[round]

info.cp.ValidatorPubs = pubs
info.cp.AggregateValidatorSign = aSign
return info
}
Loading

0 comments on commit 8dabc1c

Please sign in to comment.