稀疏默克尔树

用户和开发者不直接与 SMT 交互;排除证明由 operator-private-channel 服务自动计算并提交。本页面是供运营者及任何构建运营者工具的人员参考的技术资料。

托管程序正在从此稀疏默克尔树设计迁移至链上 nonce 位图(在上游跟踪)。本页面内容与当前托管程序保持一致,待该变更落地后将进行修订。

用途

私有通道使用稀疏默克尔树(SMT)来保证每个提款 nonce 只能被结算一次。当运营者调用 ReleaseFunds 时,必须提供两个证明:一个排除证明,证明该 nonce 在当前根中尚不存在;以及一个包含证明,证明该 nonce 确实存在于调用者提供的新根中。只有在两项检查均通过后,程序才会存储新根,使任何未来重复使用该 nonce 的尝试均可被证明为无效。

树参数

  • 树高度:16
  • 最大叶节点数:65,536(2^16)
  • 哈希函数:SHA-256
  • 空叶节点值:[0u8; 32](32 个零字节)
  • 非空叶节点值:SHA256([1u8; 32]),以常量 NON_EMPTY_LEAF_HASH 存储
Root Hash (32 bytes)
/ \
Hash(L, R) Hash(L, R)
/ \ / \
Hash(L, R) Hash(L, R) Hash(L, R) Hash(L, R)
/ \ / \ / \ / \
... ... ... ... ... ... ... ...
/ \ / \ / \ / \ / \ / \ / \ / \
Leaf0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 ...
(nonces recorded as leaf positions using their value modulo 65536)

叶节点结构

每次提款恰好占用一个叶节点。叶节点位置由以下方式确定:

leaf_position = transaction_nonce % 65536

当叶节点的值等于 NON_EMPTY_LEAF_HASH(即 SHA256([1u8; 32]))时,该叶节点被视为非空。空叶节点的值全为零。

Nonce 与叶节点位置

ReleaseFunds 中的 transaction_nonce 为 u64 类型。其在树中的位置为 nonce % 65536,其预期 epoch 为 nonce / 65536。链上程序会验证此计算所得的 epoch 是否等于 Instance.current_tree_index;若不匹配,则抛出 InvalidTransactionNonceForCurrentTreeIndex。

树轮换

Tree Index 0 (nonces 0-65,535) Tree Index 1 (nonces 65,536-131,071)
┌────────────────────────────┐ ┌────────────────────────────┐
│ Root: 0x8fe6... │ │ Root: 0x8fe6... (reset) │
│ Nonces Used: 65,536/65,536 │ Rotate │ Nonces Used: 0/65,536 │
│ Status: FULL │ ──────> │ Status: ACTIVE │
└────────────────────────────┘ └────────────────────────────┘
(Tree exhausted) (Fresh tree)

SMT 的固定容量为 65,536 个叶节点。运营者服务通过检查 nonce % 65536 == 0(且 nonce > 0)来判断是否需要轮换;该边界标志着新 epoch 的开始。此时,operator-private-channel 会在提交下一个 ReleaseFunds 之前调用 ResetSmtRoot:

  • Instance.current_tree_index 递增
  • 提款根重置为空树
  • 前一树 epoch 的 nonce 被作废

运营者服务还会在每次 ReleaseFunds 调用前,验证本地 SMT 根是否与链上的 Instance.withdrawal_transactions_root 一致;若不匹配,则触发安全停机,而非提交可能无效的证明。

树轮换由存储在链上的 Instance.current_tree_index: u64 进行追踪。

在 ReleaseFunds 中的验证

ReleaseFunds 中的 sibling_proofs 参数恰好为 [u8; 512]:16 个兄弟哈希 × 每个 32 字节,与树高度 16 相匹配。

链上验证流程按顺序执行两项独立检查:

  1. verify_smt_exclusion_proof 证明 nonce 叶节点当前相对于 Instance.withdrawal_transactions_root 为空
  2. verify_smt_inclusion_proof 证明 nonce 叶节点存在于调用者提供的 new_withdrawal_root 参数中
  3. 仅当两项检查均通过时,程序才将 new_withdrawal_root 存储为新的 Instance.withdrawal_transactions_root 并释放代币

任一检查失败均会抛出 InvalidSmtProof。第 3 步中的根更新与每次 ReleaseFunds 调用原子性地执行。

Is this page helpful?

Table of Contents

Edit Page
©️ 2026 Solana 基金会版权所有