Diem 区块链上的 XUS 币种模块:Move 源码、Genesis 注册流程与形式化规范深度解析
【免费下载链接】diem Diem’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
本文以 XUS.md 文档为主体,结合仓库内 XUS.move 源码及其上下游依赖(Diem、AccountLimits、Roles、DiemTimestamp、Genesis),系统讲解 Diem(原 Libra)网络中 XUS 币种模块的设计意图、初始化函数、链上资源布局与 Move Prover 形式化规范。读完本文,你将理解一个稳定币(SCS)在 Diem 框架中如何被定义、注册与约束,并能在阅读同类 Move 模块文档时快速定位关键实现。
XUS 模块在 Diem 框架中的角色定位
Diem 框架(DiemFramework)采用"多币种 + 统一账本"设计:链上可以同时存在多种货币,每一种货币都由一个独立的 Move 模块承载其类型标签与初始化逻辑。XUS 正是其中一个币种模块,它定义链上 XUS 币种,并在系统 genesis(创世)阶段完成注册。
从 Diem.move 的注释可以确认,register_SCS_currency 注册的是 SCS(stable currency,稳定币),即非合成币(non-synthetic currency);与之相对,XDX 属于合成币(synthetic),用于链上计价与汇率锚定。模块文档开篇即说明:
This module defines the coin type XUS and its initialization function.
整个模块职责非常收敛——只做两件事:
模块骨架与依赖关系
XUS.move 的全部源码约 70 行,结构如下:
module DiemFramework::XUS {
use DiemFramework::AccountLimits;
use DiemFramework::Diem;
use DiemFramework::DiemTimestamp;
use DiemFramework::Roles;
use Std::FixedPoint32;
struct XUS { }
public fun initialize(dr_account: &signer, tc_account: &signer) { … }
spec module { … }
}
模块依赖了五个标准框架模块,每个依赖都对应初始化函数中的一类职责:
| DiemTimestamp | 通过 assert_genesis() 校验当前处于 genesis 阶段 |
| Roles | 通过 assert_diem_root / assert_treasury_compliance 校验调用者角色 |
| Diem | 通过 register_SCS_currency<XUS> 完成核心币种注册 |
| AccountLimits | 通过 publish_unrestricted_limits<XUS> 发布无限制转账限额 |
| FixedPoint32 | 构造 XUS 到 XDX 的初始汇率(定点数 1.0) |
值得注意的是,与许多框架模块不同,XUS 模块本身不含任何业务函数——所有转账、铸币、销毁逻辑都收敛在 Diem 模块中,XUS 只是"币种身份"的载体。
struct XUS:链上币种的身份标签
/// The type tag representing the `XUS` currency on-chain.
struct XUS { }
XUS 是一个空结构体,且 XUS 的 CurrencyInfo<XUS> 存储位于 @CurrencyInfo 地址(见下文)。它本身不携带任何字段(docgen 输出中的 dummy_field: bool 是空结构体的文档占位符),其价值完全体现在类型系统层面:
- 作为泛型参数实例化 Diem::CurrencyInfo<XUS>、Diem::Coin<XUS> 等资源;
- 作为 Diem::is_currency<XUS>() 等查询的"类型键"。
在 Move 中,空结构体作为"类型标签"是一种常见模式:类型本身即数据,编译期就能保证 XUS 与 XDX、XDX 与 LBR 之间不会混用。这也是 Move 资源安全模型在币种隔离上的直接体现。
initialize:genesis 时刻的币种注册函数
initialize 是 XUS 模块唯一的公开函数,签名如下:
public fun initialize(dr_account: &signer, tc_account: &signer)
其中 dr_account 是 DiemRoot(Diem 根)账户签名者,tc_account 是 TreasuryCompliance(财库合规)账户签名者。函数体分四步:
第一步:断言处于 genesis 阶段
DiemTimestamp::assert_genesis();
initialize 只允许在创世阶段调用(文档明确:"This can only be called from genesis")。assert_genesis 会校验链上时间戳尚未初始化,从根源上杜绝运行期任何人重复注册或篡改币种。
第二步:角色权限校验
Roles::assert_treasury_compliance(tc_account);
Roles::assert_diem_root(dr_account);
- DiemRoot 是系统管理员的最高权限账户(Genesis.move 中由它初始化全局配置);
- TreasuryCompliance 负责铸币、销毁与合规相关操作。
这一步对应 DIP-2 权限模型中的关键条目(详见形式化规范小节):币种注册只能由 DiemRoot 发起,而 MintCapability/BurnCapability 只能归属 TreasuryCompliance 账户。
第三步:调用 Diem::register_SCS_currency 注册币种
Diem::register_SCS_currency<XUS>(
dr_account,
tc_account,
FixedPoint32::create_from_rational(1, 1), // exchange rate to XDX
1000000, // scaling_factor = 10^6
100, // fractional_part = 10^2
b"XUS"
);
六个参数的含义与取值如下:
| dr_account | — | DiemRoot 签名者,CoinInfo 将发布在其账户地址 |
| tc_account | — | TreasuryCompliance 签名者,铸币/销毁能力将发布在其账户地址 |
| to_xdx_exchange_rate | create_from_rational(1, 1) = 1.0 | XUS 兑 XDX 的初始汇率(定点数) |
| scaling_factor | 1000000 = 10⁶ | 币种最小单位与人类可读单位之比,即 1 XUS = 1,000,000 个链上最小单位 |
| fractional_part | 100 = 10² | 人类可读表示的小数位精度(相当于"分"级别的两位小数) |
| currency_code | b"XUS" | 币种符号,ASCII 编码,写入 CurrencyInfo.currency_code |
代码注释与 Diem.move 的 CurrencyInfo 文档 给出了 scaling_factor 与 fractional_part 的权威解释:scaling_factor 是"除以它得到人类可读金额"的数(如 XUS 的 10⁶),fractional_part 是"人类可读表示中使用的最小分数位"(如 XUS 的 10² 分)。这意味着 XUS 在链上以微单位计量、对外展示保留两位小数。
第四步:发布无限制限额
AccountLimits::publish_unrestricted_limits<XUS>(dr_account);
在 DiemRoot 账户下发布 LimitsDefinition<XUS> 资源。从 AccountLimits.move 源码看,无限制限额的实质是将四个字段全部置为极值:
LimitsDefinition<CoinType> {
max_inflow: MAX_U64,
max_outflow: MAX_U64,
max_holding: MAX_U64,
time_period: ONE_DAY,
}
即流入/流出/持仓均无上限,时间窗口为一个自然日。这意味着 XUS 在账户间的转账不受限额约束(只有 TC 账户或持有 &AccountLimitMutationCapability 的调用者才能把窗口指向其他限额定义,从而覆盖此设置)。
底层原理:register_SCS_currency 的资源布局
Diem::register_SCS_currency(Diem.move#L1311-L1336)是 XUS 注册的真正执行者,其设计要点是资源分属两个账户:
let (mint_cap, burn_cap) =
register_currency<CoinType>(
dr_account, to_xdx_exchange_rate,
false, // is_synthetic = false,XUS 是稳定币
scaling_factor, fractional_part, currency_code,
);
// 校验 tc_account 下尚未存在 MintCapability,防止重复
move_to(tc_account, mint_cap);
publish_burn_capability<CoinType>(tc_account, burn_cap);
- register_currency(Diem.move#L1242 起)负责在 @CurrencyInfo 地址发布 CurrencyInfo<XUS> 资源,并执行参数合法性校验:assert(0 < scaling_factor && scaling_factor <= MAX_SCALING_FACTOR, …),其中 MAX_SCALING_FACTOR = 10000000000(10¹⁰,Diem.move#L154)。XUS 的 10⁶ 满足约束;
- MintCapability<XUS> 与 BurnCapability<XUS> 被 move_to 到 TreasuryCompliance 账户,且函数开头同样执行了 Roles::assert_treasury_compliance(tc_account) 与 Roles::assert_diem_root(dr_account)——与 XUS 模块内的校验互为呼应(双保险);
- is_synthetic 参数传 false,再次印证 XUS 是锚定实资产的稳定币,而非像 XDX 那样的合成币。
注册完成后,CurrencyInfo<XUS>(Diem.move#L111-L151)中会记录 total_value、preburn_value、to_xdx_exchange_rate、is_synthetic、scaling_factor、fractional_part、currency_code、can_mint,以及铸币、销毁、预销毁、取消销毁、汇率变更五类事件流。
调用链:Genesis 如何触发 XUS 初始化
XUS::initialize 的唯一调用点是框架初始化函数 Genesis::initialize_internal(Genesis.move#L56-L109):
// Currency setup
Diem::initialize(dr_account);
// Currency setup
XUS::initialize(dr_account, tc_account);
XDX::initialize(dr_account, tc_account);
初始化顺序是严格编排的:先 DiemAccount::initialize、ChainId::initialize、DiemConfig::initialize 打好账本与配置基础,再 Diem::initialize 建立币种基础设施,随后才依次注册 XUS 与 XDX。因为 DiemTimestamp::assert_genesis() 的存在,这套流程只在创世块执行一次,运行期任何重放都会因时间戳已初始化而中止。这也解释了为何 initialize 直接接收签名者引用而非"能力"对象——它本质上是创世脚本的一部分。
形式化规范:中止条件与资源持久性不变量
XUS 模块携带了完整的 Move Prover 规范(即关联文档中的 "Specification" 与 "Module Specification" 部分),用于机器可验证的正确性证明。
initialize 的中止条件
spec initialize {
include Diem::RegisterSCSCurrencyAbortsIf<XUS>{currency_code: b"XUS", scaling_factor: 1000000};
include AccountLimits::PublishUnrestrictedLimitsAbortsIf<XUS>{publish_account: dr_account};
include Diem::RegisterSCSCurrencyEnsures<XUS>;
include AccountLimits::PublishUnrestrictedLimitsEnsures<XUS>{publish_account: dr_account};
include DiemTimestamp::AbortsIfNotGenesis;
include Roles::AbortsIfNotDiemRoot{account: dr_account};
include Roles::AbortsIfNotTreasuryCompliance{account: tc_account};
}
规范逐条对应权限模型(引用自 DIP-2):
- 非 genesis 阶段调用必然中止(AbortsIfNotGenesis);
- 只有 DiemRoot 账户能注册新币种(AbortsIfNotDiemRoot,权限 [[H8]]);
- 只有 TreasuryCompliance 账户能持有 MintCapability([[H1]])与 BurnCapability([[H3]])(AbortsIfNotTreasuryCompliance);
- scaling_factor 为 0 或超过 MAX_SCALING_FACTOR 时中止(INVALID_ARGUMENT);
- CurrencyInfo<XUS> 已存在时中止(ALREADY_PUBLISHED)。
确保条件则声明:注册成功后 Diem::is_currency<XUS>() 成立、总供应量 total_value == 0、TC 账户持有铸币能力(Diem.move#L1357-L1360)。
资源持久性不变量
模块级规范(Persistence of Resources)用三条不变量锁定"genesis 之后 XUS 资源状态不可变":
// 1. 运行期 XUS 必为已注册币种
invariant [suspendable] DiemTimestamp::is_operating() ==> Diem::is_currency<XUS>();
// 2. 运行期 DiemRoot 下必存在 LimitsDefinition<XUS>
invariant [suspendable] DiemTimestamp::is_operating()
==> exists<AccountLimits::LimitsDefinition<XUS>>(@DiemRoot);
// 3. LimitsDefinition<XUS> 只允许存在于 @DiemRoot,不允许出现在其他地址
invariant forall addr: address where exists<AccountLimits::LimitsDefinition<XUS>>(addr):
addr == @DiemRoot;
第一、二条是"存在性"保证:只要链处于运行期,XUS 一定已注册、限额定义一定在 DiemRoot 下;第三条是"唯一性"保证:LimitsDefinition<XUS> 不可能被发布到其他任何地址。源码注释还解释了第二条不变量为何放在 XUS 模块而非 AccountLimits::publish_unrestricted_limits 内:该函数对泛型 CoinType 并非对所有类型都成立,而"对 XUS 成立"这一事实只能在此处针对具体类型断言。
这些规范的价值在于:证明 initialize 不可被滥用、注册结果不可被篡改,这正是金融网络中币种引入流程需要的形式化保障。
小结与延伸阅读
XUS 模块是理解 Diem 多币种架构的最小完整范例:一个空结构体定义身份、一个 initialize 完成注册、一组不变量锁定状态。它的实现高度依赖 Diem 与 AccountLimits 两个框架模块,任何新币种(例如同目录的 XDX)都遵循同样的"类型标签 + genesis 注册 + 规范证明"模式。
继续深入可参考以下仓库文件:
- 模块源码:XUS.move
- 注册实现与 CurrencyInfo 定义:Diem.move
- 限额发布实现:AccountLimits.move
- 创世调用链:Genesis.move
- 角色权限断言:Roles.move
- 框架模块总览:overview.md
- 关联文档原文:XUS.md
【免费下载链接】diem Diem’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
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考



-171主机测评](https://www.171host.com/wp-content/uploads/2026/10/20261028040945-6ae175894b981-220x150.jpg)

