背景

Starcoin main网络这里简称为Starcoin 1.0, 需要向Starcoin 2.0做资产隐射,资产隐射当中会有些问题需要处理(StarcoinFramework 2.0 资产映射工作清单) ,能否将Starcoin 1.0和2.0都做到一个链当中,执行不同的VM处理不同类型的交易。 Bob hui jiao 讨论有如下想法

设计想法

1.交易类型添加

支持不同的交易类型,交易类型里面添加扩展字段,以前交易叫做Legacy交易,和新交易类型两种类型

Legacy交易基于以前逻辑来处理也就是master分支

新交易类型基于新的dag-master分支处理

2.状态树的实现

状态树的处理需要涉及到Block miner的逻辑,miner会将Legacy txn和txn一起打包,

执行的时候会产生Legacy txn执行,这里就说是VM1.0, txn执行这里简称为VM2.0

VM1.0产生state_root1, VM2.0产生state_root2,将state_root1, state_root2,新生成

state_root (需要设计下生成state_root的逻辑, 这里再设计一层smt tree3, 设置特殊key, value为(state_root1, state_root2) ),将key,value插入到stm tree3, 由二层存储结构变成3层)

3.模块相关

  1. OpenBlock以及miner相关模块

    1. BlockHeader保持结构体不变,兼容1.0区块,BlockBody中填充新旧两种交易

    2. BlockInfo中添加一个字段保存2.0 vm的state_root2,用于创建StateDB2时使用。

      1. 现有流程从BlockHeader中获取state_root1,为了保持兼容和减少工作量,保持不变。

      2. BlockInfoStore trait在多个流程中使用,比较容易通过block_id获取到blockInfo,进而获取到state_root2。如TxPoolService/WriteBlockChainService

      3. BlockInfo的更新不影响state_root1,比较容易处理

    3. 新的交易在执行后,会被添加到BlockHeader中的txn_accumulator,需要对两种HashValue进行转换

    4. gas_used通过TransactionOutput进行统计,并与block_gas_limit进行比较

  2. 交易execution模块的处理,

  3. StarcoinVM 1.0和2.0相关抽象和重写

  4. movevm 需要引用不同版本的move, 新的move repo引用都需要重命名

  5. 由于有些逻辑有相似之处,可能的对接口进行抽象,方便两个vm实现有太多重复冗余代码

  6. Storage存储相关,由于状态里面有state_root1和state_root2, 对应物理存储是放到一个文件夹还是不同文件夹

  7. Storage存储里面column family对应的schema也不一样,也需要对实现进行抽象

    1. storage instance可以复用现有的代码,包括cache和cf,复用transaction output处理流程

    2. ChainStateDB是用于更新stateroot的结构体,为了支持resource/resource_group tree,需要新的结构体和流程,包括Reader/Writer。

    3. 需要新的Super Trait - StarcoinMoveResolver,有许多基于StateView auto-implement trait

    4. 更新链上resource path,move vm解析时需要新的路径

    5. 不同vm之间使用StorageAdapter layer作为访问资源的统一入口

  8. StarcoinFramework相关处理

    1. 物理隔离:将1.0 与 2.0 放置在不同文件夹

    2. 加载方式:在加载处增加封装,根据参数采用不同加载方式

    3. gas计费:参考aptos,GasSchedule 抽象出来,采用不同的计费对象处理不同的场景

    4. 链上对象和模型:目前包含 Balance、Account 这些模型,将其转移到对应的版本framework文件夹中

    5. 目前StarcoinFramework是放到0x1账号下面的,如果放到同一文件夹,2.0的starcoinFramework需要放到另一个文件夹上(从vm加载流程来看,framework编译为mv/blob文件,vm执行genesis或者部署contract时根据版本目录选择加载)

  9. 同样需要处理的的基金会和一些链上资源 (Legacy vm和new vm合约部署,需要更新rpc接口, 合约部署到不同的状态, Legacy需要后面设置为freezing状态?)

  10. rpc相关和starmask处理,由于有1.0和2.0两个状态,需要获取两个余额,这里需要加上新的rpc api获取新状态的余额

  11. rpc service相关需要新老都添加一份

  12. p2p相关处理,这里p2p同步不仅涉及到Legacy同步处理,还涉及新的

  13. ABI相关,ABI也需要支持新老

  14. sync相关处理,由于Legacy txn和new txn打包到一个Block中,Legacy和new需要使用相同consenus, 不能consensus 1使用POW, consensus使用FlexiDag (consensus用同一个)

  15. 剩下的问题 (这些不用考虑)

    1. 老token和新token需要交互吗,如何交互

    2. 如果有交互是否需要类似bridge功能

  16. BlockMetaData交易生成作用在Legacy状态还是new状态?

设计思路2 -Multi Framework方案

用单一 compiler-v2 来支持不同的framework,参考以下的图示

Starcoin MultiFramework-20250319-071726.jpg

之前的Multi-VM方案如下图

starcoin双VM方案 (1)-20250319-072040.jpg

两类方案均需要满足的目标:

  1. 旧区块可以查询

  2. 基于旧数据的数据可以执行交易并修改

  3. Framework 1.0 的数据与Framework 2.0 的数据需要进行隔离

Framework 2.0 作以下修改:

  1. Framework 搬回工程,包含native、gas_schedule、 on_chain_config、stdlib、starcoin-framework

  2. DB部分,与现有的区块做物理隔离,根据选择的DB方案做不同的处理

存储方案

出块

调用和查询

执行流程

统一存储

保持原状,但是需要区分开framework的模块名称,另外可增加framework版本号

调用时,需要根据传入的framework版本号来区分,如果是版本号<=v12的调用,去调用新模块,则拒绝调用

根据调用版本号来处理

分开存储(假设分别为state tree v1 和v2)

增加一个总的statetree,合并v1和v2作为总的statetree的最新区块

根据版本号区分,选择对应的statetree,并选择对应的调用流程

根据调用版本号来处理

  1. rpc处理,旧的保持不变,新的在head里面增加framework版本号,若检测不到版本号按照默认处理

  2. 所有流程和共识按照2.0交易处理,sync的时也按照Framework2.0处理

  3. 升级2.0是基于1.0的代码做升级,可以在0x1下开辟新路径以解决模块名称冲突的问题,如 0x1/v13/coin/CoinStore,原有的数据保持不变(选择统一存储的情况下)

0x12345

0x1/Account/Balance

0x1/v13/Account/Balance