
区块链金融科技【免费下载链接】diemDiem’s mission is to build a trusted and innovative financial network that empowers people and businesses around the world.项目地址https://gitcode.com/gh_mirrors/di/diem点击查看免费下载本篇文章深入剖析 Diem 区块链框架中的0x1::ChainId模块源码位于 language/diem-framework/modules/ChainId.move关联文档见 release-1.2.0-rc0 生成的模块文档。链 ID 是区分 testnet、devnet 与 Diem 主网等不同链的唯一标识其最核心的职责是防止「为某条链构造的交易被另一条链执行」。读完本文你将掌握ChainId资源的数据结构、初始化与读取两条关键调用链、它在交易执行前置校验中的强制检查逻辑以及 Rust 侧配置与命名链的对应关系。模块定位为什么需要 Chain ID在 Diem 生态中会同时运行多条彼此独立的链正式的主网Mainnet、测试网Testnet、开发网Devnet等。这些链运行的是同一套 Move 框架代码如果一笔签名交易可以在任意一条链上被执行那么攻击者就可以把在主网上构造的交易重放到测试网或反之造成资金与账本状态错乱。ChainId模块正是为化解这一风险而设计的The chain id distinguishes between different chains (e.g., testnet and the main Diem network). One important role is to prevent transactions intended for one chain from being executed on another.其职责被拆分为三部分存储链 ID一个可发布的resource容器、初始化链 ID仅在 genesis 阶段由 DiemRoot 账户执行一次、读取链 ID供交易执行框架在 prologue 阶段做一致性校验。核心数据结构ChainId 资源与错误常量模块只定义了一个资源字段极其精简resource struct ChainId { id: u8 }id: u8以 8 位无符号整数表示的链 ID。在 Rust 侧实现中 types/src/chain_id.rs 有注释说明u7 in a u8 is uleb-compatible即当前按 u8 存储的取值空间在 uleb 编码下是兼容的未来有升级为 uleb64 的可能。该资源通过has key能力文档中的resource发布到账户地址下属于 Move 的全局存储资源。模块同时定义了一个错误常量const ECHAIN_ID: u64 0;文档注释给出其语义「TheChainIdresource was not in the required state」即ChainId资源未处于预期状态时抛出。实际代码中它配合Errors::already_published(ECHAIN_ID)使用用于表达「该资源已被重复发布」的冲突场景。initialize在 genesis 阶段发布链 IDinitialize是模块中唯一的写操作public fun initialize(dr_account: signer, id: u8) { DiemTimestamp::assert_genesis(); CoreAddresses::assert_diem_root(dr_account); assert(!existsChainId(Signer::address_of(dr_account)), Errors::already_published(ECHAIN_ID)); move_to(dr_account, ChainId { id }) }其执行流程包含三道强前置校验体现了 Diem 框架对「只允许在正确的时间、由正确的账户、且只初始化一次」的严格控制必须在 genesis 阶段DiemTimestamp::assert_genesis()确保链尚未进入运行状态链 ID 只能在创世初始化时被写入调用者必须是 DiemRootCoreAddresses::assert_diem_root(dr_account)校验签名者是 DiemRoot 账户0x1核心地址防止任意账户伪造链 ID不可重复发布先检查目标地址是否已存在ChainId资源已存在则抛出Errors::already_published(ECHAIN_ID)保证幂等与唯一性。满足条件后通过move_to(dr_account, ChainId { id })将资源发布到 DiemRoot 账户地址下成为链上全局状态的一部分。实际调用链Genesis 初始化initialize并非孤立存在它被创世流程统一编排。在 language/diem-framework/modules/Genesis.move 的initialize_internal中chain_id: u8作为入参传入并在 DiemAccount 初始化之后立即执行DiemAccount::initialize(dr_account, x00000000000000000000000000000000); ChainId::initialize(dr_account, chain_id);从源码结构可以看出链 ID 的发布紧跟在账户体系初始化之后、DiemConfig等其他链上配置初始化之前说明它是链身份的最基础配置之一。这也与模块文档中的形式化不变量相呼应见下文「Module Specification」。get运行时读取链 IDget是模块中唯一的读操作public fun get(): u8 acquires ChainId { DiemTimestamp::assert_operating(); borrow_globalChainId(CoreAddresses::DIEM_ROOT_ADDRESS()).id }前置条件DiemTimestamp::assert_operating()只有链处于正常运行非 genesis、非 shutdown状态时才允许读取与initialize的assert_genesis形成时间轴上的对称约束——创世时写入运行时读取读取路径固定为从CoreAddresses::DIEM_ROOT_ADDRESS()即0x1借用全局ChainId资源并取其id字段与initialize的发布地址保持一致。关键校验场景交易 prologue 的跨链防护get最核心的调用方是交易执行的公共前置校验prologue。在 language/diem-framework/modules/DiemAccount.move 的prologue_common中注释为[PCA1]的第一条检查即是// [PCA1]: Check that the chain ID stored on-chain matches the chain ID specified by the transaction assert(ChainId::get() chain_id, Errors::invalid_argument(PROLOGUE_EBAD_CHAIN_ID));也就是说每一笔交易在执行前其携带的 chain_id 都必须与链上存储的 ChainId 完全一致否则交易以PROLOGUE_EBAD_CHAIN_ID错误被拒绝。这正是文档所述「prevent transactions intended for one chain from being executed on another」的落地实现——交易签名的目标链与当前执行链不匹配时在 prologue 阶段即被拦截根本不会进入后续的 gas 计费与脚本执行。与之配套的形式化规范DiemAccount.move也明确约束aborts_if chain_id ! ChainId::spec_get_chain_id()。Rust 侧实现ChainId 类型与命名链链 ID 不仅在 Move 层存在在 Rust 侧同样有对应类型与配置支撑。查看 types/src/chain_id.rs 可知pub struct ChainId(u8);这是一个基于u8的新类型包装newtype实现了Serialize/Deserialize等 trait。更为实用的是其中的NamedChain枚举它为保留的链 ID 提供了人类可读的名字枚举值数值 ID用途说明MAINNET1Diem 主网生产链保留给 1TESTNET2测试网官方提醒修改这些 ID 会破坏各类组织的测试环境应避免变更DEVNET3开发网TESTING4测试环境PREMAINNET5主网上线前的预发布网源码注释还特别说明链 ID 0 被保留用于「意外初始化」的兜底——用户可能不小心把 ChainId 字段初始化为 0因此 0 不作为任何命名链使用。NamedChain同时提供了双向转换能力str_to_chain_id把MAINNET、TESTNET等字符串解析为ChainIdfrom_chain_id把数值反向映射为枚举。官方强调在配置文件和 CLI 中为了可读性可以使用命名链但签名交易时仍应使用数值链 ID如主网为 1、测试网为 2。配置中的 chain_id 字段在节点/工具配置中chain_id 作为配置项出现。以 config/src/config/key_manager_config.rs 为例#[serde(deserialize_with chain_id::deserialize_config_chain_id)] pub chain_id: ChainId,该字段通过deserialize_config_chain_id自定义反序列化器解析支持字符串如TESTNET或 u8 数字如2两种写法两种形式最终都会收敛为ChainId(u8)其默认值来自ChainId::test()测试用链 ID。这套设计让运维人员在 genesis 配置、密钥管理工具等场景下既可以写chain_id: 2也可以写chain_id: TESTNET同时保证底层数值一致。形式化规范Module Specification模块文档还给出了面向 Move Prover 的形式化规范用于机器验证关键性质Initialization 不变量ChainId.moveinvariant [suspendable] DiemTimestamp::is_operating() existsChainId(DiemRoot);含义当 Diem 处于运行状态时链 ID 资源必然已存在于 DiemRoot 地址下。这一全局不变量把「先 genesis 初始化、后进入运行态」的时间约束固化为可被证明的链上性质杜绝了「链已在运行但 ChainId 缺失」的非法状态。initialize的行为规范ChainId.movespec initialize { pragma opaque; let dr_addr Signer::address_of(dr_account); modifies globalChainId(dr_addr); include DiemTimestamp::AbortsIfNotGenesis; include CoreAddresses::AbortsIfNotDiemRoot{account: dr_account}; aborts_if existsChainId(dr_addr) with Errors::ALREADY_PUBLISHED; ensures existsChainId(dr_addr); }规范精确声明了该函数只修改dr_addr处的ChainId全局状态非 genesis 或非 DiemRoot 调用会中止重复发布以ALREADY_PUBLISHED中止调用成功后该地址必然存在ChainId资源。Helper Functionspec fun spec_get_chain_id(): u8 { globalChainId(DiemRoot).id }spec_get_chain_id是get()的规范辅助函数供其他模块如DiemAccount的 prologue 规范在证明中引用链 ID 的取值而无需依赖具体实现。小结0x1::ChainId是一个小而关键的框架模块它通过「一条链一个 ID」的基本设计支撑起 Diem 多链并行而不串扰的安全模型存储层ChainId { id: u8 }资源发布在 DiemRoot 账户下作为链上全局状态生命周期initialize仅允许在 genesis 由 DiemRoot 调用一次通过DiemTimestamp::assert_genesis与CoreAddresses::assert_diem_root双重约束get仅允许在运行态读取DiemTimestamp::assert_operating防护效果每一笔交易都在prologue_common的[PCA1]检查中比对链上 ID 与交易携带 ID不匹配即以PROLOGUE_EBAD_CHAIN_ID拒绝从执行入口杜绝跨链重放工程配套Rust 侧 types/src/chain_id.rs 提供数值/命名链MAINNET1、TESTNET2、DEVNET3、TESTING4、PREMAINNET5的双向解析配置系统支持字符串或数字两种写法可验证性模块级不变量与函数规范经 Move Prover 形式化定义确保「运行时必有 ChainId」等关键性质可被机器证明。对于需要自定义链如私有测试网的开发者只需在 genesis 初始化时传入一个新的 u8 链 ID并确保交易签名时携带相同数值即可其余防护机制由框架自动生效。赞分享区块链金融科技【免费下载链接】diemDiem’s mission is to build a trusted and innovative financial network that empowers people and businesses around the world.项目地址https://gitcode.com/gh_mirrors/di/diem点击查看免费下载相关推荐Diem 框架 ChainId 模块深度解析链 ID 的存储、初始化与链间防重放机制Diem 框架 ChainId 模块深度解析链 ID 的存储、初始化与链间防重放机制 导读 0x1::ChainId 是 Diem 区块链框架Diem Fr区块链金融科技Diem Move 模块 ChainId 深度解析链标识的存储、初始化与交易防串链校验Diem Move 模块 ChainId 深度解析链标识的存储、初始化与交易防串链校验 本文围绕 Diem 区块链 Move 框架中的 0x1::ChainI区块链金融科技深入解析 Diem 链上 ChainId 模块从 Move 源码到交易防重放校验深入解析 Diem 链上 ChainId 模块从 Move 源码到交易防重放校验 本篇文章以 Diem 区块链框架中负责链标识的链上模块 0x1::Chain区块链金融科技创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考