# 协议升级模块设计文档

# 一、总体描述

# 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(连续确认次数)

    1. # 正常升级(中途统计没有波动)

      起始区块高度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区块开始新协议生效

    2. # 正常升级(中途统计有波动)

      起始区块高度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区块开始新协议生效

    3. # 异常升级(先回滚,中途统计没有波动)

      主链

      起始区块高度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区块开始新协议生效

    4. # 异常升级(先回滚,中途统计有波动)

      与第三种情况类似

  • 依赖服务

    工具模块的数据库工具

# 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. 不同协议版本的消息是否处理由网络模块判断?还是由各个消息的注册模块判断
  2. 不同协议版本的交易是否处理由交易模块判断?还是由各个交易的注册模块判断
  3. 协议支持的消息类型、交易类型、交易处理器由配置文件初始化?还是由各模块来注册?
  4. 是否允许版本回退?由1.1版本回退到1.0-------------------不予许
  5. 不支持POW
Last Updated: 2019/9/3 下午4:38:35