如何将Solidity的SortitionSumTree数据结构迁移至Substrate实现
现有实现问题及修正方案
你当前的实现存在多处不符合原始业务逻辑和Substrate开发规范的问题,具体如下:
- 核心字段类型错误:Solidity原始定义中
stack、nodes均为uint[]动态数组,你把这两个字段写成了单个u128,完全无法实现原树结构的存储逻辑,必须改为Vec<u128>类型。 - 键类型选择低效:原Solidity中mapping的键为定长
bytes32类型,你使用变长Vec<u8>作为对应键虽然能运行,但定长数组[u8; 32]的存储成本、计算性能都更优,更符合Substrate开发规范。 - 派生冗余:
SortitionSumTree作为存储值类型,不需要派生PartialOrd、Ordtrait,这两个 trait 仅用于BTreeMap的键类型要求,多余派生会增加不必要的计算开销。 - 整数类型对齐问题:Solidity默认
uint为256位无符号整数,如果你需要和原有Solidity逻辑完全对齐、避免数值溢出风险,可以将u128替换为Substrate原生支持的U256类型,若业务数值范围确定不超过u128上限则可保留现有设置。
修正后的规范实现代码
use sp_std::collections::btree_map::BTreeMap; // 若不需要256位整数对齐Solidity,可删除下面这行导入,把所有U256替换为u128即可 use sp_runtime::U256; #[derive(PartialEq, Eq, Default, Clone, Encode, Decode, TypeInfo)] #[cfg_attr(feature = "std", derive(Debug))] pub struct SortitionSumTree { pub k: U256, pub stack: Vec<U256>, pub nodes: Vec<U256>, pub ids_to_tree_indexes: BTreeMap<[u8; 32], U256>, pub node_indexes_to_ids: BTreeMap<U256, [u8; 32]>, } #[pallet::storage] #[pallet::getter(fn sortition_sum_trees)] pub type SortitionSumTrees<T> = StorageMap<_, Blake2_128Concat, [u8; 32], SortitionSumTree>;
额外优化建议
如果你的SortitionSumTree结构体体积较大,且单次业务操作只会修改其中少数字段,不建议将整个结构体作为单个StorageMap的值存储,否则每次读写都需要完整序列化/反序列化整个结构体,开销较高。可以将不同字段拆分为独立的Storage项存储,进一步提升链上运行性能。
内容的提问来源于stack exchange,提问作者Amiya Behera
相关产品推荐
相关产品推荐

