# 协议升级模块设计文档
# 一、总体描述
# 1.1 模块概述
# 1.1.1 为什么要有《协议升级》模块
不同的协议版本支持的交易类型、消息类型不同,为了管理区块链网络的版本,需要提供完善的版本管理功能。
# 1.1.2 《协议升级》要做什么
- 解析区块头中的版本信息,进行动态统计、升级、回退
- 为其他模块提供版本支持的交易类型、消息类型、版本信息查询服务
# 1.1.3 《协议升级》在系统中的定位
协议升级是底层模块之一,以下分功能讨论模块依赖情况
依赖
- 区块管理模块-初始化本地协议版本信息
被依赖
- 所有关心消息处理、交易处理的模块
# 1.2 架构图
补充图片
# 二、功能设计
# 2.1 功能架构图
补充图片
# 2.2 模块服务
# 2.2.1 获取当前主网版本信息
接口说明
根据链ID查询DB得到主网版本信息
请求示例
{ "cmd": "currentMainnetVersion", "minVersion":"1.1", "params": ["888"] }
请求参数说明
index | parameter | required | type | description |
---|---|---|---|---|
0 | chainId | true | Long | 链ID |
返回示例
Failed
{ "version": 1.2, "code": 1, "msg": "error message", "result": {} }
Success
{ "version": 1.2, "code": 0, "result": { "chainId": "888", "versionInfo": { "major": "1", "minor": "1", "percent": "80",//固定值 "slice": "100",//固定值 "waitCount": "240"//固定值 } } }
返回字段说明
parameter | type | description |
---|---|---|
chainId | Integer | 链ID |
major | Integer | 主版本号 |
minor | Integer | 次版本号 |
percent | Integer | 有效比例 |
slice | Integer | 最小统计片断长度 |
waitCount | Integer | 连续确认次数 |
# 2.2.2 获取当前本地版本信息
接口说明
根据链ID查询DB得到本地版本信息
请求示例
{ "cmd": "currentLocalVersion", "minVersion":"1.1", "params": ["888"] }
请求参数说明
index | parameter | required | type | description |
---|---|---|---|---|
0 | chainId | true | Long | 链ID |
返回示例
Failed
``` { "version": 1.2, "code":1, "msg" :"xxxxxxxxxxxxxxxxxx", "result":{} } ```
Success
{ "version": 1.2, "code": 0, "result": { "chainId": "888", "versionInfo": { "major": "1", "minor": "1", "percent": "80", "slice": "100", "waitCount": "240" } } }
返回字段说明
参考2.2.1
# 2.2.3 根据区块高度获取版本统计信息
接口说明
根据链ID查询DB得到本地版本信息
请求示例
{ "cmd": "statisticsInfo", "minVersion":"1.1", "params": ["888", "888"] }
请求参数说明
index parameter required type description 0 chainId true Long 链ID 1 height true Long 区块高度 返回示例
Failed
{ "version": 1.2, "code":1, "msg" :"xxxxxxxxxxxxxxxxxx", "result":{} }
Success
{ "version": 1.2, "code": 0, "result": { "chainId": "888", "statisticsInfo": { "major": "1", "minor": "1", "percent": "80", "slice": "100", "count": "240" } } }
返回字段说明
参考2.2.1
# 2.3 模块内部功能
# 2.3.1 模块启动
功能说明:
启动协议升级模块
流程描述
补充图片
1.RPC服务初始化
2.初始化通用数据库
3.加载配置信息
4.初始化各链数据库
5.等待依赖模块就绪
依赖服务
工具模块、内核模块
# 2.3.2 版本升级
功能说明:
每保存一个区块或者回滚一个区块时,都会读取区块头中的版本号,动态统计版本比例信息,决定是否进行协议升级。主版本号不允许跨版本升级,次版本号允许跨版本升级
流程描述
每100个区块为一个统计区间,统计区块头中版本号的分布比例,并且保存到数据库(key=height, value=版本信息,连续确认次数等等)
版本占比大于某个阈值(必须大于50%)时,就能确定该统计区间内的版本号,当连续260个统计区间内的占比最大版本号保持连续时,主网执行协议升级。
如果没有版本号占比大于阈值,沿用当前生效版本号作为当前区间的版本号
如果中途有统计区间版本号波动,则重新开始统计
模拟几种场景:
waitCount(连续确认次数)
# 正常升级(中途统计没有波动)
起始区块高度1000,协议版本号=1.0
1001-1100高度区间内的区块统计,占比80%的区块协议版本号=1.1,waitCount=1
1101-1200高度区间内的区块统计,占比80%的区块协议版本号=1.1,waitCount=2
。
。
。
27001-27100高度区间内的区块统计,占比80%的区块协议版本号=1.1,waitCount=260
从27101区块开始新协议生效
# 正常升级(中途统计有波动)
起始区块高度1000,协议版本号=1.0
1001-1100高度区间内的区块统计,占比80%的区块协议版本号=1.1,waitCount=1
1101-1200高度区间内的区块统计,占比80%的区块协议版本号=1.1,waitCount=2
1201-1300高度区间内的区块统计,占比80%的区块协议版本号=1.0,waitCount=0
1301-1400高度区间内的区块统计,占比80%的区块协议版本号=1.1,waitCount=1
。
。
。
27301-27400高度区间内的区块统计,占比80%的区块协议版本号=1.1,waitCount=260
从27401区块开始新协议生效
# 异常升级(先回滚,中途统计没有波动)
主链
起始区块高度1000,协议版本号=1.0
1001-1100高度区间内的区块统计,占比80%的区块协议版本号=1.1,waitCount=1
1101-1200高度区间内的区块统计,占比80%的区块协议版本号=1.1,waitCount=2
。
。
。
27001-27100高度区间内的区块统计,占比80%的区块协议版本号=1.1,waitCount=260
从27101区块开始新协议生效
分叉链
起始区块高度1000,协议版本号=1.0,分叉高度1211
1001-1100高度区间内的区块统计,占比80%的区块协议版本号=1.1,waitCount=1
1101-1200高度区间内的区块统计,占比80%的区块协议版本号=1.1,waitCount=2
1201-1300高度区间内的区块统计,占比80%的区块协议版本号=1.0,waitCount=0
1301-1400高度区间内的区块统计,占比80%的区块协议版本号=1.0,waitCount=0
分叉链切换第一步
回滚到分叉点
1001-1100高度区间内的区块统计,占比80%的区块协议版本号=1.1,waitCount=1
1101-1200高度区间内的区块统计,占比80%的区块协议版本号=1.1,waitCount=2
1201-1211高度区间内的区块统计,区块数量不足100,不统计
添加新的区块
1001-1100高度区间内的区块统计,占比80%的区块协议版本号=1.1,waitCount=1
1101-1200高度区间内的区块统计,占比80%的区块协议版本号=1.1,waitCount=2
1201-1300高度区间内的区块统计,占比80%的区块协议版本号=1.1,waitCount=3
。
。
。
27001-27100高度区间内的区块统计,占比80%的区块协议版本号=1.1,waitCount=260
从27101区块开始新协议生效
# 异常升级(先回滚,中途统计有波动)
与第三种情况类似
依赖服务
工具模块的数据库工具
# 2.3.3 延迟升级
功能说明:
为了处理升级过程中发现新协议有BUG的情况
流程描述
假定当前版本号为1.0,待升级版本号1.1,但是1.1版本升级过程中发现了BUG
通过降低新协议1.1比例来重置协议升级过程,使得主网版本持续定留在旧版本1.0,修复新协议1.1BUG后,再重启升级过程。
依赖服务
工具模块的数据库工具
# 2.3.4 版本信息推送
功能说明:
每个统计区间的最后一个区块接收完毕时,主动通知各模块当前生效的协议版本信息,主要是通知交易管理模块有效的交易类型及有效的交易验证器,通知网络模块有效的消息类型及消息处理器。
流程描述
依赖服务
工具模块的数据库工具
# 三、事件说明
# 3.1 发布的事件
# 3.1.1 协议升级
说明:协议版本升级,发布该事件
event_topic : "versionUpadte",
data:{
chainId
major
minor
height
}
# 3.2 订阅的事件
略
# 四、协议
# 4.1 网络通讯协议
略
# 4.2 消息协议
略
# 五、模块配置
[
{
"name": "supportTxTypes",
"remark": "支持的交易类型",
"readOnly": "true",
"value": "1,2,3,4,5"
},
{
"name": "supportMessageTypes",
"remark": "支持的消息类型",
"readOnly": "true",
"value": "1,2,3,4,5"
}
]
# 六、Java特有的设计
- BlockHeader对象新增字段
字段名称
字段类型
说明
blockMajor byte 区块主版本号 blockMinor byte 区块次版本号 mainnetMajor byte 主网主版本号 mainnetMinor byte 主网次版本号
- BlockChainVersion对象设计
字段名称
字段类型
说明
major byte 主版本号 minor byte 次版本号
# 七、补充内容
- 不同协议版本的消息是否处理由网络模块判断?还是由各个消息的注册模块判断
- 不同协议版本的交易是否处理由交易模块判断?还是由各个交易的注册模块判断
- 协议支持的消息类型、交易类型、交易处理器由配置文件初始化?还是由各模块来注册?
- 是否允许版本回退?由1.1版本回退到1.0-------------------不予许
- 不支持POW