跳转到内容

机密资产(CA)

机密资产(Confidential Asset,CA) 标准是 Aptos 上面向同质化资产(FA)的隐私协议。它允许用户隐藏链上的转账金额和持有余额,同时保持发送方与接收方地址公开可见。

任何非 dispatchable FA 均可封装为机密余额。协议支持最大 2⁶⁴ − 1 的转账金额和最大 2¹²⁸ − 1 的余额。

每个 (用户, 代币) 对会生成一套独立的密钥对:

  • 解密密钥(DK):用户持有的私钥标量,永远不离开客户端。
  • 加密密钥(EK):由 DK 派生并存储在链上,供他人为该用户加密金额。

关系为 EK = DK⁻¹ · H,其中 H 为 Ristretto255 哈希基点。

这套密钥与用户的 Aptos 账户签名密钥完全独立。

每个机密存储包含两个加密余额:

  • pending_balance(待处理余额):接收所有入账存款和转账。
  • available_balance(可用余额):可花费余额,用于出账转账和提款。

资金首先进入 pending_balance,用户必须调用 rollover_pending_balance 将其移入 available_balance 后才能使用。

每个余额被拆分为 16 位块,每个块用 Twisted ElGamal 在 Ristretto255 上加密:

P_i = v_i · G + r_i · H (承诺)
R_i = r_i · EK (密钥密文)
  • G 为 Ristretto255 基点,H 为哈希基点。
  • 持有者通过计算 v_i · G = P_i − DK · R_i 并求解离散对数完成解密。
  • 由于加密具有加法同态性,新存款可直接加到密文上,无需解密。
余额类型块数总位数最大值
pending_balance4 × 16 位642⁶⁴ − 1
available_balance8 × 16 位1282¹²⁸ − 1

同态加法可能导致块的值超过 16 位。归一化会将 available_balance 的每个块重新压缩到 [0, 2¹⁶) 区间。归一化在 rollover 之前是必需的,且需要提交链上可验证的 ZKP。

enum ConfidentialStore has key {
V1 {
pending_balance: CompressedBalance<Pending>,
available_balance: CompressedBalance<Available>,
ek: CompressedRistretto, // 加密密钥(公开)
pending_balance_count: u32, // 达到 MAX_TRANSFERS_BEFORE_ROLLOVER 时必须 rollover
pause_incoming: bool, // 暂停接收转账(密钥轮换前需启用)
}
}

MAX_TRANSFERS_BEFORE_ROLLOVER = 65536:若 pending_balance_count 达到上限,下一笔入账转账前用户必须先调用 rollover_pending_balance

deposit 外,所有修改状态的操作都需要 ZKP,分两类:

四种 NP 关系,各用 Schnorr 风格的 Σ-协议证明:

操作NP 关系证明内容
register_balanceR_regEK = DK⁻¹ · H(用户知道 DK)
withdraw_toR_withdraw提款金额与密文匹配;余额保持非负
confidential_transferR_transfer发送金额与接收方密文匹配;余额守恒
rotate_encryption_keyR_keyrot新 EK = δ · 旧 EK;R 分量已用新密钥重新加密

每次花费/归一化操作都包含一个 Bulletproof 范围证明,证明每个余额块 ∈ [0, 2¹⁶)

  • DST:b"AptosConfidentialAsset/BulletproofRangeProof"
  • 在链上通过 ristretto255_bulletproofs 原生模块批量验证。

审计员系统允许指定方读取机密金额。每笔转账都包含为相应审计员加密的金额密文,链上验证其正确性。

优先级类型说明
最高资产审计员由资产创建者按代币设置,覆盖全局审计员
默认全局审计员由 Aptos 治理设置,适用于所有未配置资产审计员的代币
可选自愿审计员由发送方按笔添加,数量不限

当配置了有效审计员(全局或资产级)时,其参与是强制性的。链上证明验证器会确保对应审计员的密文正确构造。

available_balance 存储了在上次 rollover 时用当时审计员 EK 加密的 R_aud 分量。当审计员密钥变更(epoch 递增)时,用户必须 rollover 以刷新该分量;链上验证器会强制 epoch 一致性。

设置控制方效果
白名单治理仅白名单内的 FA 类型可使用 CA;白名单为空时不限制
紧急暂停治理暂停除存款和提款外的所有操作
全局审计员治理设置/更换强制全局审计员 EK
资产审计员FA 创建者设置/更换强制按代币审计员 EK

所有入口函数均在 aptos_framework::confidential_asset 中。_raw 后缀表示接受原始字节向量(用于证明数据)而非类型化结构体,这是当前稳定 API。

(signer, token) 创建 ConfidentialStore 并将 EK 存储到链上。

public entry fun register_balance_raw(
sender: &signer,
token: Object<Metadata>,
ek: vector<u8>, // 32 字节压缩 Ristretto255 点
proof_bytes: vector<u8>, // R_reg 的序列化 sigma 证明
)

将代币从 signer 的公开 FA 存储移入 pending_balance。不需要 ZKP。

public entry fun deposit(
sender: &signer,
token: Object<Metadata>,
to: address,
amount: u64,
)

同态地将 pending_balance 加入 available_balance,并将 pending_balance 重置为零。可用余额必须先完成归一化。

public entry fun rollover_pending_balance(
sender: &signer,
token: Object<Metadata>,
new_balance: ConfidentialAvailableBalance,
proof: SigmaProofWithdraw,
zkrp: RangeProof,
pause_incoming: bool,
)

available_balance 解密一笔金额并发送到公开 FA 存储。

public entry fun withdraw_to_raw(
sender: &signer,
token: Object<Metadata>,
to: address,
amount: u64,
new_balance: vector<vector<u8>>, // 剩余可用余额字节
proof_bytes: vector<u8>, // R_withdraw sigma 证明
zkrp_bytes: vector<u8>, // Bulletproof 范围证明
)

通过 ZKP 将 available_balance 的各块重新压缩到 16 位范围。

public entry fun normalize_raw(
sender: &signer,
token: Object<Metadata>,
new_balance: vector<vector<u8>>,
proof_bytes: vector<u8>,
zkrp_bytes: vector<u8>,
)

将隐私金额从发送方的 available_balance 转移到接收方的 pending_balance。金额永远不会在链上公开。

public entry fun confidential_transfer_raw(
sender: &signer,
token: Object<Metadata>,
recipient: address,
new_balance: vector<vector<u8>>,
transfer_amount: vector<vector<u8>>, // 用接收方 EK 加密的金额密文
proof_bytes: vector<u8>, // R_transfer sigma 证明
zkrp_bytes: vector<u8>, // Bulletproof 范围证明
memo: vector<u8>, // 可选;最大 256 字节;未加密
)

用新 EK 替换链上存储的 EK,并用新密钥重新加密 available_balance 的 R 分量。需要 pause_incoming = truepending_balance 为零。

public entry fun rotate_encryption_key_raw(
sender: &signer,
token: Object<Metadata>,
new_ek: vector<u8>,
new_balance: vector<vector<u8>>,
proof_bytes: vector<u8>,
zkrp_bytes: vector<u8>,
)
函数返回值说明
get_encryption_keyOption<vector<u8>>用户当前的代币 EK
has_user_registeredbool(user, token) 的机密存储是否存在
get_pending_balance原始字节加密的待处理余额
get_available_balance原始字节加密的可用余额
get_pending_balance_countu32上次 rollover 后的待处理入账次数
is_balance_normalizedbool可用余额是否处于 16 位正常形式
is_incoming_pausedbool是否已暂停接收转账
get_global_auditorOption<vector<u8>>全局审计员 EK(治理设置后有值)
get_asset_auditorOption<vector<u8>>资产级审计员 EK(创建者设置后有值)
is_emergency_pausedbool治理是否已触发紧急暂停
get_total_confidential_supplyu128当前所有机密存储中锁定的代币总量
  • 不支持 dispatchable FA。 只有非 dispatchable 的同质化资产才能使用 CA。带有自定义转账分发函数的 dispatchable FA 在注册时会被 is_safe_for_confidentiality 拒绝。
  • 地址公开。 每笔交易的发送方和接收方地址以明文形式出现在链上。
  • 总供应量公开。 get_total_confidential_supply 会揭示当前处于机密模式的代币数量。