MCCV协议笔记(草稿)

LE 发布于 2026-05-24 阅读 70

MCCV是比特币上的金库协议,利用OP_CHECKTEMPLATEVERIFY预计算交易图,实现资金的安全存储。即使热钱包密钥被攻破,攻击者也无法立即窃取全部资金,因为取款有延迟和速率限制,用户或瞭望塔可在挑战期内检测并恢复资金。协议通过有向无环图枚举所有状态和转换,支持存款、取款和恢复操作,恢复操作可将资金扫到冷密钥。未来改进包括委托恢复密钥、独立瞭望塔、STARK证明等。

[!NOTE] 本文档仍在不断完善中。 它涵盖了大部分关键设计组件,且目前已是最新版本,但仍需进一步修订。

目标

此保险库协议旨在即使密钥泄露,也能防止资金被灾难性地盗取。

威胁模型

预期安全属性

MCCV 旨在减轻因热钱包泄露导致的资金被盗风险。

获得热钱包密钥访问权限的攻击者应无法立即窃取全部保险库余额。 相反,提现操作被延迟并设置速率限制。 速率限制为用户或委托的守望塔提供了检测未授权提现并将保险库资产转入恢复密钥的时间。

协议通过共识强制实施的速率限制也缓解了用户或委托的守望塔未能及时检测到未授权提现的情况。 如果用户或守望塔未能及时确认恢复交易,此速率限制还能减少损失。

安全假设

此系统的安全性依赖于以下几个关键假设:

  • 恢复密钥必须保持未泄露状态。
  • 用户或委托的守望塔必须在挑战期内监控区块链并对未授权提现做出响应。
  • 恢复交易必须在提现时间锁到期前在链上确认,才能完全阻止所有未授权提现。
    • 这包括用户或委托的守望塔能够独立为恢复交易提供手续费。
  • 预计算的保险库图必须正确生成并由用户验证。
  • 比特币共识规则,包括 OP_CHECKTEMPLATEVERIFY,必须按预期运行。

比特币生态系统假设

  • 共识层面强制执行 BIP-119 OP_CHECKTEMPLATEVERIFY
  • 策略支持临时锚点(Ephemeral Anchors)——用于传播零手续费的存款形状、提现和恢复交易
  • 策略支持包中继(Package Relay)——用于子交易为上述交易支付手续费

范围外

MCCV 不旨在防范:

  • 恢复密钥泄露
  • 恶意或有缺陷的保险库生成软件
  • 长时间丧失区块链监控能力
  • 阻止恢复交易确认的拒绝服务攻击
  • 物理胁迫攻击
  • 比特币共识故障

保险库结构

保险库由少量参数确定性地派生:

  • 热 xpub - 用于派生所有热密钥的 xpub。 这些密钥授权存款、提现以及将资产转入恢复地址。
  • 冷 xpub - 用于派生所有冷密钥的 xpub。 冷密钥是恢复密钥。 用户必须对冷 xpub 的私钥材料保密以维护保险库安全。
  • scale - 基础存款和提现增量。保险库上的每次操作都是此聪数的整数倍。
  • delay - 每次增量提现所需的延迟区块数
  • max-withdrawal - 单次最大提现金额
  • max-deposit - 单次最大存款金额
  • max-depth - 保险库可支持的操作次数(DAG 的深度)

保险库本身是一个预计算的有向无环图(DAG)交易输出,通过共识由 OP_CHECKTEMPLATEVERIFY 强制执行。 每个可能的状态和状态转换都被枚举,并通过 OP_CHECKTEMPLATEVERIFY 哈希提交。 每笔交易要么有一个保险库输出、一个提现输出,或两者都有。

交易按“代”排序,同一代内的每笔交易被认为具有相同的“深度”。 深度是指在此保险库的历史(当前保险库 UTXO)中,此交易之前执行过的保险库操作次数。 深度不反映在另一个 UTXO 上对保险库执行的操作。 保险库旨在拥有单一的连续历史。 如果用户希望创建另一个参数完全相同的保险库,则应增加账户索引。 用多个 UTXO 重复使用完全相同的保险库参数会直接关联独立的保险库,并存在密钥重用风险。 此外,当前版本的软件实现无法妥善处理这种有意为之的场景。

保险库输出代表处于特定状态的保险库,包含余额以及前两次保险库操作(存款或提现),并隐含了深度(此保险库上已执行的操作次数)。 需要前两次操作的原因在于:前一次操作定义了当前交易的形状,而再前一次操作定义了 nSequence 相对时间锁。 当前余额不以聪数表示,而是需要乘以 scale 才能得到保险库输出实际值的整数。 保险库输出的价值始终为 scale * balance

保险库输出为每个潜在后续保险库操作设有 taproot 脚本路径,但最后一个保险库输出除外,它只能由恢复密钥花费。 潜在的保险库操作包括:存入一定金额、提取一定金额、带提现输出转入恢复、仅自身转入恢复。 提现输出通过脚本路径提供三种操作:带保险库输出转入恢复、仅自身转入恢复,以及成熟后花费。 保险库和提现输出始终可以通过 taproot 密钥路径由冷密钥花费。

[!NOTE] 对于存款交易而言,log_2( max-withdrawal + max-deposit + 2 ) 必须小于 101,以确保交易保持在 TRUC 交易的大小限制内。 此处仅作完整性说明,因为实际保险库规模通常远小于 8。

概览图

性能

如概览图所示,此方案计算密集度相当高。 必须计算每个交易及状态间的转换,并计算交易的 OP_CHECKTEMPLATEVERIFY 哈希。 在最新基准测试出炉之前,保险库在通用硬件上的大致性能特征如下:计算包含数百个可用操作的保险库可能需要数十分钟,具体取决于其他参数。

存款操作

存款图

存款始终为保险库 scale 的整数倍,因此 scale 为 10,000 聪的保险库可接受 10,000 聪、20,000 聪、30,000 聪甚至更大额的存款。 单笔存款交易的最大金额由 max-deposit 参数控制。

存款通过两步完成。 首先,热钱包创建一笔存款形状交易,这是一笔零手续费的交易,其输出价值为存款金额 + 期望手续费。 由于保险库仅允许来自有限预计算集合的交易,实际的保险库交易需要一个适当大小的输入,这正是存款形状交易提供的。

在上图中,手续费贡献通过存款形状交易贡献 10,123 聪(而非 10,000 聪)来表示,其中 123 作为整个交易包的手续费。 然后,创建存款交易,花费前一个保险库输出(如果存在),加入新的存款金额,并创建新的保险库输出。 期望的手续费由子存款交易支付,因为存款交易的输入是 vault_current + deposit_amount + desired_fee,而输出是 vault_current + deposit_amount

保险库交易有两个版本:带相对时间锁和不带相对时间锁。 存款交易之后的保险库输出没有相对时间锁。 提现交易上的保险库输出始终承诺带有相对时间锁的保险库交易,该时间锁等于提现输出上的相对时间锁。 这确保了攻击者无法通过多次提现来绕过整体速率限制。

提现操作

提现图

存款类似,提现始终为保险库 scale 的整数倍,上限由 max-withdrawal 参数定义。

提现也通过两步完成。 第一步是创建提现交易。 由于保险库仅允许来自有限预计算集合的交易,提现必须先将提取的资金转到一个具有固定值和固定热密钥的输出中。

提现交易包含一个时间锁,该时间锁由提取的增量数乘以延迟参数得出。 提现交易上的提现输出通过 CSV 强制执行延迟,而保险库输出(如果存在)则通过 CTV 间接强制执行延迟,确保下一个保险库交易具有正确的 nSequence。 此提现交易将有一个提现输出、一个锚点输出,如果还有剩余保险库余额,则还有一个保险库输出。

在提现成熟之前,用户或守望塔可以将其转入恢复密钥。 提现输出和保险库输出(如果存在)都具有通过脚本路径将其转入恢复密钥的能力,既可以单独转,也可以一起转(如果适用)。 成熟后,它可以通过热密钥花费到目标地址。 这意味着提现输出有三种脚本路径花费方式:成熟后热密钥花费、仅将提现输出转入恢复,以及如果存在剩余保险库余额,则将提现和保险库余额一起转入恢复。

恢复操作

恢复交易允许用户或守望塔将保险库及任何待处理的提现转入恢复密钥。

恢复交易有四种变体:

  • 仅花费存款交易的保险库输出
  • 仅花费提现交易的保险库输出(忽略提现输出)
  • 同时花费提现交易的保险库输出和提现输出
  • 仅花费提现交易的提现输出(忽略保险库输出,或当提现清空保险库时保险库输出不存在)

用恢复交易花费保险库输出会终止保险库。

恢复交易始终有两个输出:一个可由恢复密钥花费的输出,以及一个锚点输出。 恢复密钥从冷 xpub 派生,每个深度级别都有一个唯一的恢复密钥。

锚点输出用于让子交易支付恢复交易的手续费。

未来改进

委托恢复密钥

当前设计中可能最大的遗漏是,没有一种方式能让委托代理将资金转入恢复密钥,同时又不赋予其发起提现的能力。 在专用的 tapleaf 中使用 OP_CHECKSIGFROMSTACK 从热密钥到委托密钥进行简单授权委托即可实现这一点。 这将允许用户仅将发起恢复的权限委托给守望塔服务。 这是一个相当简单的改动,我希望尽快完成。

独立守望塔

这可能是当前实现中最大的遗漏,我计划在短期内完成。 你可以手动执行守望塔功能,足以演示协议的功能,但有一个自动化的系统会更好。 这相当容易实现,我现在只是需要尽快转向其他工作。

转入委托

我心中没有一个精确的设计,但想法是在密钥丢失时提供一种合理的备份方案。 特别是在协作托管设置中的公司,可以选择将保险库转入其托管账户。 这将受一个非常长的时间锁(数月级别)限制,在此期间用户可以将资金转入其恢复地址(与未授权提现被发起时相同)。

缓存

大型保险库可能需要数分钟计算,而目前 MCCV 会反复重新计算整个保险库。 最简单的做法是将每 N 代缓存到磁盘上,这样计算时间就回到合理范围内,代价是磁盘空间。

优化

还有许多微观和宏观的优化空间。 宏观方面,保险库代码没有普遍使用 Context 对象进行内存缓存计算,这是一个容易优化的地方。 微观方面,将 CTV 计算代码从构建 rust-bitcoinTransaction 改为流式哈希计算,在我做过的相关基准测试中会有显著提升。

STARK 证明

我想特别提一下这个想法。 在我看来,此协议最大的问题是计算强度过高,无法在硬件钱包上运行,但初始保险库设置必须在可信设备上执行。 解决这一矛盾将极具价值。 我承认不知道这有多可行,但如果硬件钱包能够验证保险库是否生成正确,那将提供一个令人满意的解决方案。 这样,繁重的计算可以在强大的消费级硬件上执行,而信任保留在硬件钱包中。 我认为这能提供一个非常有说服力的用户故事,否则会弱很多。 当然,这种方法是否可行仍有待观察。 验证器代码必须足够紧凑,能够与现有钱包功能一起装入硬件钱包,并且性能足够快,使保险库验证可接受。 同样,在计算大型保险库后,生成证明的速度也必须足够快。

泛化

MCCV 展示了一种可以使用 OP_CHECKTEMPLATEVERIFY 构建的合约风格,但大部分代码可以复用于其他合约。 我已开始进行一些泛化工作,但还有很多工作要做。 此外,探索是否将时间投入到优化 sapio 上更值得。 MCCV 的大部分速度优势源于利用保险库结构实现并行化,如果我试图让软件过于通用,这些优势可能会丧失。

GPU 加速

通过一些工作,GPU 加速可以显著改善生成保险库上下文的时间。 这对于使更大保险库的计算变得实用来说肯定有价值,但在我看来,更高的优先级是弄清楚如何使保险库生成在硬件钱包上可行地生成或验证。

OP_TEMPLATEHASH

对于 MCCV 而言,Templatehash 是 OP_CHECKTEMPLATEVERIFY 的直接替代品。 我希望将契约操作码设为一个特性标记,以便两者都可以使用,但我希望先解决优化问题。 流式哈希对 MCCV 与 OP_CHECKTEMPLATEVERIFYOP_TEMPLATEHASH 的交互方式有深远影响,因此我想首先解决这个问题。 另一方面,按照目前使用 OP_CHECKTEMPLATEVERIFY 的方式,换成 OP_TEMPLATEHASH 几乎只需一个下午,所以我也许会早点去做。

  • 原文链接: github.com/LNHANCE-Exped...
  • 登链社区 AI 助手,为大家转译优秀英文文章,如有翻译不通的地方,还请包涵~

相关文章

0 条评论