# Sophon Messager 设计说明书

sophon-messager是一个用于管理本地消息的组件,用于保存地址消息、管理消息状态和控制推送消息的频率。

  • 支持多个miner:提供了较为实用的API给miner推送消息
  • 持久化存储:支持MySQL和SQLite两种存储方案
  • nonce管理:合理的分配nonce,降低nonce冲突
  • 动态的控制推送频率和消息量
  • 集成权限验证、trace及API限流
  • 提供较为完善的命令行工具

# 详细设计

# 整体架构

# 功能模块

# 权限验证

该验证分两部分,一是对访问sophon-messager 使用token是否合法的验证,二是验证是否具有访问API的权限,下图是权限验证流程图。

# token 合法性验证

token 分为两种,一种是由sophon-auth服务生成,另外一种是sophon-messager本身生成,该token只用于本机的命令行命令。 token 会被sophon-messager和sophon-auth依次验证合法性,只要其中一个验证通过就算合法token。 sophon-auth 验证token合法后会返回该token的权限信息。

# API权限验证

API权限分为4种:read, write, sign, admin,权限依次由低到高,token的权限必须等于或者大于API设定的权限才算验证通过。

# 消息选择

  • 获取所有需推送消息的地址,然后并发的按地址选择消息
  • 判断该地址能否推送消息
  • 获取该地的actor,主要是为了获得链上nonce
  • 比较链上nonce和该地址的nonce,若链上nonce大,则更新该地址nonce
  • 获取该地的fill消息并放到待推送列表
  • 与该地址的最大选择消息数比较并计算可推送消息数
  • 获取改地址的unfill消息,并排查已过期消息,最后获得候选消息
  • 通过节点预估候选消息的gas,预估完成后筛除预估失败消息
  • 逐个消息进行签名,直到达到可推送消息,该地址该次选择消息完成
  • 等待各个地址选择消息完成
  • 更新消息信息和地址nonce
  • 推送消息到节点

下图是消息选择流程图

# 数据库模块

该模块设计为能够支持MySQL和SQLite两种数据库,并能够通过配置文件来配置具体使用那个数据库,因此需要将该模块对外交互部分抽象成接口,减少外部对使用不同数据库的感知。 使用单元测试对该模块各个具体实现进行测试。

# 统一对外接口
type Repo interface {
    AddressRepo() AddressRepo
    MessageRepo() MessageRepo
}

# 地址表接口
type AddressRepo interface {}
# 消息表接口
type MessageRepo interface {}

# 消息状态管理

消息总共分以下几种状态:

UnKnown:    unkonwn
UnFillMsg:  未签名
FillMsg:    已签名
OnChainMsg: 已上链
FailedMsg:  失败
NonceConflictMsg:被替换
NoWalletMsg:未找到钱包

下图是消息状态转换图

# head 处理

通过调用节点ChainNotify接口可以不断的获得新的head,head 里面包含current、apply和revert三种tipset,需要分别对其处理。 首先对current类型的tipset进行处理,与sophon-messager已处理的tipset做对比,防止漏处理某些tipset。 然后处理revert tipsets,再处理apply tipsets,根据apply tipset拿到已经上链的消息,然后再逐一更新sophon-messager中对应的消息信息。

# 命令行命令

  • 全局参数
    • 查询全局参数
    • 设置全局参数
  • 地址
    • 查询地址信息
    • 禁止和激活地址
    • 设置选择消息数
  • 消息
    • 查询消息信息
    • 列出失败、阻塞消息
    • 更新消息状态
    • 调整消息状态
  • 节点
    • 查询节点信息
    • 增加节点

# 数据表设计

sophon-messager 用到了4张数据表,分别是全局参数表,地址表,消息表,节点信息表,以下是各个表的详细结构。

  1. 全局参数表,用于保存全局参数信息
name type desc
id smallint(2) primary key
gas_over_estimation double gas limit的系数
max_fee varchar(256)
gas_fee_cap varchar(256)
sel_msg_num bigint(20) 单次选择的最大消息数
gas_over_premium DOUBLE gas premium的系数
  1. 地址表,用于保存地址相关信息
name type desc
id varchar(256) primary key
addr varchar(256) uniqueIndex, 地址
nonce bigint 地址的nonce
weight bigint
sel_msg_num bigint(20) 改地址单次选择的最大消息数
state int 地址状态
gas_over_estimation decimal(10,2) gas limit的系数
gas_over_estimation decimal(10,2) gas premium的系数
max_fee varchar(256)
gas_fee_cap varchar(256)
is_deleted int 是否删除,-1:否,1:是
created_at datetime 创建时间
updated_at datetime 更新时间
  1. 消息表,用于保存消息初始信息,执行结果等信息
name type desc
id varchar(256) primary key
version bigint 消息版本
nonce bigint 消息使用的nonce
from_addr varchar(256) 消息发送地址
to varchar(256) 消息接收地址
value varchar(256) 转账消息表示转账金额
gas_limit bigint
gas_fee_cap varchar(256)
gas_premium varchar(256)
method int 执行消息的函数代号
params blob
signed_data blob 消息签名结果
unsigned_cid varchar(256) unsigned消息的CID
signed_cid varchar(256) signed消息的CID
height bigint 消息打包高度
receipt_exit_code bigint 消息执行完的退出码
receipt_return_value blob 消息执行返回值
receipt_gas_used bigint 消息执行消耗的gas
tipset_key varchar(1024) 消息打包高度的tipset的key
meta_expire_epoch bigint 过期高度
meta_gas_over_estimation gas 预估超出的系数
meta_max_fee varchar(256) gas 费用上限
meta_gas_fee_cap varchar(256) gas feecap数值
meta_gas_over_premium decimal(10,2) gas premium的系数
state int 消息状态
is_deleted int 是否删除,-1:否,1:是
created_at datetime 创建时间
updated_at datetime 更新时间
  1. 节点信息表,用于保存节点相关信息
name type desc
id varchar(256) primary key
name varchar(256) 节点名
url varchar(256) 节点 URL
token varchar(256) 节点 token
node_type int 节点类型
is_deleted int 是否删除,-1:否,1:是
created_at datetime 创建时间
updated_at datetime 更新时间
  1. actor费用配置表
name type desc
id varchar(256) primary key
actor_v uint actor版本
code varchar(256) 代码
method unsigned bigint 方法号
gas_over_estimation decimal(10,2) gas limit的系数
gas_over_estimation decimal(10,2) gas premium的系数
max_fee varchar(256) 最大费用
base_fee varchar(256) 基础费用阈值
gas_fee_cap varchar(256)
created_at datetime 创建时间
updated_at datetime 更新时间