作者:Peter Todd
来源:https://petertodd.org/2024/covenant-dependent-layer-2-review
链上钱包实现了从交易到交易的(大致上)一一映射:对于用户要执行的一笔 经济 的交易,大致上需要一笔 区块链 交易。交易的聚合、coinjoin、cut-through,等等技术,都稍稍偏离了一点点,但大体上,我们这个说法还是对的。
闪电通道则实现了一种 多对一 映射:闪电通道的魔法就在于,实质上不限量的经济交易可以在一条通道内发生,而通道自身绑定在一个未花费的交易输出(UTXO)中。本质上,我们抓住了 “时间” 维度 —— 交易 —— 并通过让这个维度塌缩实现了显著的扩容。
但是,让每个用户创建一个 UTXO 是不够好的(至少可以争议)。所以,出现了许多提议,尝试让多个用户可以自主保管地共享一个 UTXO 来实现更大的扩容效果。这一次,塌缩的是 “空间” 维度 —— 用户 —— 化为一个 UTXO。
我在这里的目标是审核所有这些提议,找出它们共有的技术模式,找出它们所需的新的操作码类型或软分叉升级,然后建立一个综合性的表格,将所有方案都放入表格中。在这个过程中,我们也会定义什么是 “Layer 2 协议”、闪电网络已经能够实现何种扩容,并理解要实现这些提议,我们需要对交易池(mempool)作那些升级。
感谢 Fulgur Ventures 资助这项研究。他们对本文的内容没有编辑权限,在正式出版之前也没有审核过。
感谢 Daniela Brozzoni、Sarah Cox 等人在出版前的审核。
1 定义
1.1 什么是 “Layer 2”?
通常人们会给 “Layer 2” 采用宽泛的定义,以至于连银行一样的实体(例如 Liquid)也可以被定义成 Layer 2。出于本文的目的,我们会采用一种更狭窄的定义:Layer 2 是一种以比特币为主导(Bitcoin-denominated)系统,其存在目的是允许 BTC 以高于链上交易的频率在相关人之间转移,并且:
- 考虑了 系统内 的惩罚和代价之后,没人能从系统中偷盗资金而获利。系统外的成本和惩罚,比如声誉损失、法律后果,等等,在我们的定义中是 不考虑的。
- (优先)资金的真正所有者可以单方面取出自己的资金(减去交易手续费),而无需任何第三方的合作。
第一项是有必要的,因为我们希望我们的 L2 系统可以表示价值很小、小到无法在链上表示的数额和交易。举个例子,在闪电通道中,HTLC 可以有小到无法在链上表示的面额。在这种情况下,HTLC 的价值会被加到承诺交易的交易手续费中。虽然闪电节点可以有针对地关闭通道来 “盗取” 一个粉尘 HTLC,但这样做是非常昂贵的 [1],代价超过 HTLC 本身的价值,所以盗窃是无利可图的。
第二项则是说,单方面取款总是我们的首要设计目标 [2]。
在这个定义下,闪电通道会被认为是一种 L2 系统。但是,像 Liquid、Cashu、和 Fedemint 这样的系统,则 不是 L2,因为是另一方(或几方)控制着你的资金。“客户端验证(client-side validation)” 方案(比如 RGB)也不是 这个定义下的 L2,因为它们是无法免信任地转移 BTC 本身的。最后,“Statechains”也不符合这个定义(中文译本),因为如果 Statechain 实体(服务商)有意不遵守协议,就可以偷盗资金。
1.2 什么是 “限制条款”?
……那么,为什么 L2 系统需要限制条款来实现更强的可扩展性呢?
在比特币的脚本编程中,“限制条款” 指的是一种机制,可以提前限制一个交易输出(txout)被花费的方式,从而花费这个 txout 的交易的形式是预先定义好的,或者,以一种不完全取决于电子签名的方式来限制它的花费。在多个参与者之间共享 UTXO 的 L2 系统需要限制条款,因为它们需要限制 UTXO 的花费方式,以实现 L2 协议的规则和激励因素。
1.2.1 递归型限制条款
递归型限制条款是具有这样的属性的限制条款:限制一个 UTXO 花费方式的规则可以递归地应用,无限地延伸到花费交易的子 UTXO 中。递归型限制条款长期被一些人认为是不可取的,因为它们可能导致资金被永远拘限。或者,至少,在没有第三方(比如政府)的许可时就会永远受困。
2 目标
闪电通道是目前 Layer 2 系统中的 “翘楚”。但它也有局限性,即:
- 可扩展性 —— 闪电通道目前要求每个终端用户至少要有一个 UTXO [3]。
- 流动性 —— 闪电通道要资金被绑定在通道中。
- 交互式 —— 闪电通道要求支付的接收者在线,以免信任地收取支付。
在评估 Layer 2 系统时,我们的目标是能够在这些关键的局限性上有所提升,最好是不会引入新的局限性。
2.1 闪电通道的可扩展性限制
在真实场景中,“每个终端用户需要一个 UTXO” 意味着什么?因为闪电通道可以无限期运行,分析它的一种办法是搞清楚每年可以创建多少条新的通道 [4]?创建一个 taproot 输出的边际成本是 43vB43vB;如果通道的创建可以平摊,也就是许多通道可以在一笔交易中开启,那么其它的交易开销就会变得微不足道,并且每年都可以新开相当多的通道来容纳新的用户。 举个例子,假设 90% 的区块空间都被用来开启新的 taproot 闪电通道:
52,560blocksyear×1,000,000vBblock×9052,560blocksyear×1,000,000vBblock×90
(结果是每年可以开启 11 亿条新通道)
预估全世界有一半人口拥有智能手机,也就是 43 亿人。所以事实上,每年我们都可以引导有可能用得上闪电网络的人群中的一大比例进入闪电网络。
然而,通道不会永远不关闭。有些时候,用户想要切换钱包、增加或减少通道的容量,等等。改变通道容量最高效的办法就是 “通道拼接”,尤其是 Phoenix Wallet 的实现。
就像通道的开启,通道拼接也可以平摊,以提高效率:多个拼接操作可以共享一笔交易,以减少为添加和移除资金而需要的输入和输出的数量 [5]。因此,每个用户的拼接操作所需的增量区块空间,假设用户使用 musig,是 43vB43vB 的 taproot 输出加上 57.5vB57.5vB taproot 密钥路径花费的见证数据,总计是 100.5vB100.5vB。如果我们再一次假设 90% 的区块空间都被用于这个用途,那么是:
52,560blocksyear×1,000,000vBblock×9052,560blocksyear×1,000,000vBblock×90
(结果是每年可执行 4.7 亿次通道拼接)
最后,注意,在钱包之间切换闪电通道是可以在一笔交易中完成的,要么是信任新钱包,在资金已经被发到承诺地址后再签名一笔承诺交易;要么是在新旧两个钱包实现中支持合作式 “关闭又开启新通道”。
当然,在闪电通道之外,会有别的比特币应用场景来争夺区块空间,而且很难知道这会怎样转化为手续费率。但这些数字给了我们一个粗糙的估计,说明以当前的技术,至少在技术上,是可能做到支持数亿自主保管的闪电网络用户的。
3 L2 综述
在我们的 L2 定义下,比特币开发者社区一直在讨论的设计模式有两个:
- 通道
- 虚拟 UTXO
在通道模式中,闪电通道是一个主要的例子,状态的推进是通过参与者交换预先签名的、可以 被挖出(但不代表 “皆大欢喜” 结局)的交易来实现的。这些预先签名的交易会在参与者之间分割一个 UTXO 的价值;经济往来是通过反复使用新的预签名交易改变分割的结果来实现的。因为会有许多有效交易在花费同一个 UTXO,就需要一些激励机制来保证只有正确的交易会真正得到区块确认。
而在 “虚拟 UTXO(V-UTXO)” 设计模式中,Ark 是最显著的例子,V-UTXO 是通过限制条款或多方的约定创造出来的;表示价值的交易 可以 被挖出,从而将各方的 V-UTXO 在链上变成真正的 UTXO,但这样的交易也不代表 “皆大欢喜” 结局。从这个角度看,V-UTXO 也类似于通道。但与通道不同的是,V-UTXO 方案是通过花费 V-UTXO 自身来实现交易的,(概念上)是使用单笔 [6] 预先签名的交易。
而 “皆大欢喜” 设计模式是使用 “所有参与者都同意” 的脚本路径,例如一个 N-of-N 的多签名装置;taproot 是专门为这个概念而设计的,允许密钥路径(通过 musig)成为一个 N-of-N 的多签名装置。假设所有参与者都同意,这一路径会允许资金被高效(且私密)地花费。
有趣的是,因为虚拟 UTXO 在许多方面是 “真实的”,在虚拟 UTXO 上建立通道是非常容易的,只需让虚拟 UTXO 在被挖出时会导致通道所需的 UTXO 被创建即可。在这个意义上,虚拟 UTXO 比通道稍微低层一些。
3.1 闪电网络
截至目前为止,在生成环境中实现的闪电网络,主要基于 BOLT 标准。闪电网络是一系列技术的组合,包括闪电通道和 HTLC、P2P 路由网络、洋葱路由、发票标准,等等。重要的是,闪电网络 不是 一个公示系统,所以 “闪电系统” 的不同模块不需要被所有用户以完全相同的方式采用。出于本文的目的,在我们说 “闪电网络” 的时候,我们采取广义,包括对现有的(典型的)、已被广泛使用的闪电网络协议(们)的易于预见的升级。
如前所述,闪电网络的关键特征是终端用户的可扩展性限制,来自于每个用户都需要至少一个 UTXO 的要求。也就是说,对于闪电网络的 “核心” 路由模块来说 —— 公开的、转发大量交易的闪电节点 —— 这些可扩展性限制并不是很大的困扰,因为只要终端用户的数量比路由节点多得多,闪电网络就能良好运作,每一条公开的、用户支付转发的通道都可以瞬时地轻松处理大量交易。这也是为什么许多新提出的 L2 系统都被期望能够参与闪电网络。我们也可以观察到,现有的、并不那么符合 L2 标准的系统,比如 Cashu,要重度依赖于闪电网络,才能真正变得有用:Cashu 的主要用法可能就是发送和收取闪电支付。
3.1.1 非交互式通道
这种构造通过使用 OP_CTV
来减少交互需求、优化闪电通道。不过,它并不能优化 “每个用户一个 UTXO” 的可扩展性限制,所以我们不会进一步讨论它。
3.2 通道工厂
在这种构造中,我们可以让多方协调进入一个 n-of-n 的多签名地址,与之匹配的一笔预签名交易会花费这个多签名地址、创造出 n个不同的 UTXO 来分割资金。而这 n 个 UTXO 分别都会用作一个支付通道。这些通道的安全性跟直接在链上开启是相同的,因为在需要将通道状态发布到链上的时候,分割资金的交易可以被挖出。这可能可以节约链上的空间,因为当通道关闭的时候,因为 —— 理论上 —— nn 个参与者可以合作一次性关闭所有 nn 条通道。
因为通道工厂是协调型 UTXO,是 可以 被挖出的,但在愉快结局中并不被期望要实际挖出,所以它是 V-UTXO 的一个 非常 原始的例子。
通道工厂的实现并不要求任何软分叉。但是,上面所述的简单的通道工厂可能在参与者稍微多一些之后就会变得不实用,因为需要用户的协作才能真正实现扩容的好处。因此,OP_Evict 或者 CTV(通过 txout 树)这样的限制条款提议可能会带来帮助,它们允许发布更细粒度的结果 —— 单方可被弹出到链上,而无需强迫所有人都同时出现在链上。
3.3 Eltoo/LN-Symmetry
因为 Eltto 是一个糟糕的容易引起混淆的名字,我们在下文中只使用更新后的名称 “LN-Symmetry”。
Poon-Dryja 通道惩罚发布不正确的状态的行为来激励发布正确的状态,LN-Symmetry 则反其道而行之,允许不正确的状态用额外一笔交易来更新。它的好处是通过移除惩罚的复杂性简化了闪电通道。不过,在不可信任的环境中,它可能也会有不利之处,因为可以说为了遏制其中,惩罚是有必要的。
LN-Symmetry 需要一个软分叉来启用 SIGHASH_ANYPREVOUT,以允许新的状态交易可以重复花费旧的状态交易。
就其自身而言,LN-Symmetry 并不能为传统的闪电通道带来扩展性能提升。但其支持者们主张它会让通道工厂更容易实现。
3.4 Ark
Ark 采用了新的方法来实现交易扩容:完全可转移的虚拟 UTXO(V-UTXO),这些虚拟 UTXO 可以在原子化的 [7] 链下交易中合并及分割。在 Ark 中,一个中心协调者 “Ark 服务商(ASP)” 给用户提供定义好时限(比如 4 周)的 V-UTXO。这些周期叫做 “轮次”。这些 V-UTXO 是通过资金池交易输出创造出来的,每一轮会创造一次,通过某种机制(比如 CTV)来让单个链上交易输出能够承诺一棵 V-UTXO 的树。轮次的过期机制是 Ark 实现可扩展性好处的关键:在一轮的末期,资金池交易的输出会解锁,允许 ASP 单方面在一笔小体积的交易中用一个签名来花费它。因为轮次有过期时间,被资金池交易输出创建出来的 V-UTXO 也就有了过期时间:持有 V-UTXO 的用户必须要么在相应池交易输出过期之前花掉这个 V-UTXO,要么将它发布到链上(单方面取款)。
为了转移 V-UTXO,Ark 协调者要一同签名花费一个或多个 V-UTXO 的交易,并让交易仅在 另一个 轮次中创造出一个或更多其它 V-UTXO 时才会生效。结合一些精心设计的超时机制 —— 完整的细节要看 Ark 的文档 —— 这一依赖就是让 V-UTXO 的花费变得免信任的地方:除非新的 V-UTXO 在另一个池交易中创造出来,旧的 V-UTXO 就无法在链上(随着池交易输出被花费而一并)取走。有一些办法可以实现这种依赖。但确切的细节跟本文的目的不相关。
注意,这意味着一个 ASP 将同时操作多个活跃中的轮次。新的轮次会被频繁创建,以允许现有轮次中的资金被转移。但现有的轮次会跟新的轮次重叠,因为它们一般会在新的轮次(新的池交易)创建之后过期。
3.4.1 Ark 的经济模型
在一个 V-UTXO 被花费掉的时候,ASP 必须在一个表示新轮次的池交易输出中提供匹配的 BTC。但是,在当前的轮次结束之前,他们是无法动用被花费 V-UTXO 的价值的。因此,V-UTXO 的花费有一个成本:货币的时间价值,这是因为 ASP 必须垫付资金。
确切地说,这个代价是在 V-UTXO 被 花费 的时候才产生的。在 V-UTXO 没有被花费的时候,它代表着一个非常真实的、可以被发布到链上以单方面取出资金的潜在 UTXO;用户自己控制着自己的资金。然而,为了花费这个 V-UTXO,ASP 必须创造一个 新的 池交易输出,用的是 ASP 从别处获得的资金,而被花费的 V-UTXO 中的资金,在其轮次到期之前,是不能为这个 ASP 所用的。
因此,花费一个 V-UTXO 需要一个短期的贷款,以覆盖从现在到轮次过期的这段时间。意思是,随着 V-UTXO 的老化(逐渐逼近轮次的到期时刻),花费一个 V-UTXO 的流动性成本会逐渐下降 —— 理论上 —— 最终趋于零(也即在轮次最终过期的时候)。
最后,还要记住的是,花费一个 V-UTXO 的成本是跟被花费的 V-UTXO 的 总 大小有关的,而 不是 由交给接收者的数额决定的。这意味着,有意直接转移多个 V-UTXO 的钱包(与之相对的是为了(例如)基于 V-UTXO 的闪电通道而管理一个 V-UTXO 的钱包)需要作出取舍:决定将一笔资金分割成多少个 V-UTXO。只留一个 V-UTXO 可以尽可能降低单方面取款的代价,但会让基于流动性的交易手续费变得最大;分割成许多 V-UTXO 则正好相反。这跟链上比特币以及闪电交易的经济模型都完全不同。
什么是流动性成本?截至本文撰写之时,闪电网络钱包 Phoenix 为持续 1 年的通道流动性收取 1% 的手续费;在最差情况下,Phoenix 将不得不将资金绑定 1 年时间。然而,这里面的假设是这些流动性没有被使用。很有可能,对 Phoenix 来说,资金成本在事实上高于一年 1%,但他们假设普通客户用尽这些入账流动性的时间会短于一年。Phoenix 也从交易手续费中赚取收入,因此也能补贴通道流动性。最后,Phoenix 还有可能不赚钱!
美国的国债(US Treasury Bill)收益率可以给我们另一个估计。在本文撰写之时,3 月期的国债收益率大概是年化 5% 。因为美元的通胀会使这个收益率有水分,出于分析的目的,我们就假设以 BTC 为本位的资金的流动性成本是年化 3%。
如果一轮长 4 周,那么交易的流动性成本会从 33 开始,逐步降低到 0 。假设用户在当前轮过期的两周之前移动资金,为实现资金的自主保管而需支付的流动性成本大约是年化 1.5% 。另一方面,如果用户一直等待到最后一刻 [8],这个流动性成本将接近于零,风险是错过到期时间。
用户可能不会认为这代价很便宜。而且,这个代价假设了每一轮的成本都是固定的,并且已经通过大量参与者来摊销交易手续费和其它代价,使它们都已经变得微不足道。
但如果这个固定成本并不小呢?假设一个 ASP 有1000 个用户,平均一个小时创建一笔池交易。在 4 周时间里,就会有 672 笔链上交易。这意味着,只是为了保管自己的资金,这个 ASP 的用户整体上就必须为几乎跟用户数量一样多的交易支付手续费!对他们来说,如果都跑去开启自己的闪电通道,可能还会更便宜,而且 ASP 还会让他们等待一个小时来确认交易。
3.4.2 冷启动 Ark
一个只有少数用户的新 ASP 会面临一个困局:要么 ASP 的轮次不那么频繁地发生,从而用户需要等待很长时间才能等到相应的轮次收集到足够多的 V-UTXO 来实现有用的可扩展性和交易手续费减免;要么,ASP 的池交易发生得很频繁,然后每个用户都要支付较高的交易手续费。如我们在上一节讨论的,它可能需要大量的用户来摊销频繁发生的轮次以及相应的池交易。
由于存在过期时间,这个问题会变得更加严重,甚至比闪电通道要面临的更严重:至少一条闪电通道可以无限期有用,在一条通道开启之后,它可以在接下来几个月里逐步摊销。其次,因为轮次会过期,在创建支持这些轮次的交易输出的 时机 选择上,不够灵活:如果高手续费的情形持续一周或两周,即将过期的池交易输出的用户就别无选择,只有(集体)支付高手续费率来维持资金的保管。而在闪电通道中,开启通道的时机选择会灵活得多。
虽然 Ark 的作者一开始想得非常乐观,认为只需几秒就可以创建新的一轮,但是,如果交易费无法得到补贴,Ark 的初次启动也许只能发生在可以等待几个小时来确认交易的应用场景中。
3.4.3 交互性
非托管的 Akr 是一种高交互需求的协议:因为你的 V-UTXO 会过期,你需要在过期之前跟 ASP 交互,不然,ASP 可以取走你的资金。这种交互需求也是无法外包的:相比之下,闪电通道有 “瞭望塔”,可以遏制你的对手尝试欺诈你 —— 即使你的节点离线了,而 Ark V-UTXO 的持有者为了免信任,必须使用自己的私钥来刷新资金。在 Ark 中,与瞭望塔最接近的东西是签名交易以允许瞭望塔在到期之前代你单方面取回资金,而这会有高昂的交易费成本。
考虑一下,要是资金所有者离线,它的 V-UTXO 会发生什么事:在轮次过期之后,ASP 需要回收资金,以应对未来轮次的流动性需要。如果一个 V-UTXO 的持有者离线,将 V-UTXO 发布到链上将面临高昂的交易代价,因为 ASP 需要取出多层的 V-UTXO 树上的资金。ASP 可以在一个新的轮次中重新创建出未花费的 V-UTXO,但是,从 V-UTXO 持有者的角度看,这不是免信任的,因为他们将无法在缺乏来自 ASP 的数据 [9] 的前提下花费这些 V-UTXO。ASP 也可以直接将未花费的 V-UTXO 记录成托管的余额。甚至可以有没收资金的条款!
我个人的看法是,考虑到 Ark 中自主保管的代价并不便宜,许多用户会转而选择可以自动滚动资金到新轮次中的 ASP、直接接受每一轮的末尾都可能出现欺诈的风险。这比预防性转移资金以保证资金安全(例如,不会因为没有及时打开手机、控制钱包转移资金)要更便宜。
3.4.4 更高级的 Ark
使用更高级的限制条款来减少 Ark 的流动性需求,也许是可信的,如果典型的情形是流动性会在一轮中全部用完的话。举个例子,我们假设一个交易池输出中所有 V-UTXO 总价值的 50% 会被花掉。如果 ASP 可以仅回收交易池输出的一部分的话,他们就可以更快地回收资金、降低整体的流动性成本。虽然现在还没有公开出现这样的具体提议,似乎只要有 充分高级TM 限制条款,是可以做到的。最有可能的是通过某种 “脚本复活(Script Revival)”软分叉,一次性添加多个有用的操作码。
类似地,通过这样的 充分高级TM 限制条款,完整的交易输出树结构可以被替换成具有某种滚动取款方案,从而节约空间。我们会在下一个章节中讨论这个话题,因为这种技术可能对其它方案也有用。
轮次结束时候的保管问题是 充分高级TM 限制条款 可以解决的另一个问题:一种限制条款,尤其是一种可以验证零知识证据(ZK-proof)限制条款,可以强制 ASP 在下一轮中重新创建所有未花费的限制条款,消除在一轮结束时监护权被交给 ASP 的问题。虽然可能这也不足以让它成为 免信任的,因为用户可能依然需要来自 ASP 的一些数据来花费自己在新轮次中的 V-UTXO,这可以防止 ASP 从对离线用户的欺诈中获得好处。
3.4.5 单方面取款时候的链上手续费支付
类似于闪电通道,链上手续费率支付的经济原理和一个 V-UTXO 在支付完手续费后的实际价值,决定了 Ark 的用法是否符合我们的 L2 定义(可以单方面退出,不会让 ASP 从欺诈中获利)。我们会在下文讨论交易输出树设计模式时进一步讨论。
3.5 Validity Rollups
一个类似于侧链构造的大类,普遍被提议使用某种形式的零知识证明技术来强制执行规则。这样的零知识证明技术是 “有效性 rollup(validity rollup)” 跟其它形式的侧链的关键区别:如果相关的零知识证明方案能够工作,交易的有效性将由数学来保证,而不需要信任一个第三方。在这个用法中,零知识证明的 “零知识” 特性并不是必要的:即使证据 “泄露”了它要证明的东西的信息,也是完全没问题的。只是碰巧这类数学方案中的绝大部分都恰好是零知识证明方案。
从比特币的角度,有效性 rollup 方案需要一种限制条款,因为我们希望能够为这样的方案创建出一种 UTXO,仅在方案的规则得到遵守时才能被花费。这也并不 必然 是一种去中心化的系统。许多有效性 rollup 方案实际上完全是中心化的;rollup 证据仅用来证明一个中心化的交易排序者为一组排序好的交易应用了规则。
至于要用什么限制条款 …… 零知识证明技术依然是一个非常新的领域,经常有进展出现。所以,我们极不可能看到任何直接验证某一种零知识证据的操作码被添加到比特币中。相反,普遍接受的事情是具体的方案会用更通用的操作码(尤其是 OP_CAT
)以在脚本中验证零知识证据。举个例子,StarkWare 正在争取让 OP_CAT
能被采用。
有效性 rollup 是一个非常大的领域,有许多的 低质量/高炒作 的项目。除了指出可能需要什么操作码来让这一类设计变得可行之外,我们不会进一步讨论。
3.6 BitVM
非常粗糙地说,BitVM 是一种在两个参与者之间构造一条闪电通道、让闪电通道的规则能够用一种零知识证据来强制执行的方法。因为它不需要限制条款就能在当今的比特币上实现,而且它无法直接用来创建可扩展性强于 “每个用户要有 1 个 UTXO” 的 L2 系统,我们不会进一步讨论。
3.7 层级式通道
层级式通道 [10] 致力于让通道的容量调整(resizing)更快更便宜:“层级式通道之于通道容量,如果闪电通道之于比特币。”然而,在根本上,它依然不能超越 “每个用户要有 1 个 UTXO” 的限制。它也不要求对比特币协议的任何变更。所以我们我们也不会进一步讨论。层级式通道的支持者们应该直接实现它!这不需要我们的许可。
3.8 CoinPool
Coinpool 让多个用户可以共享一个 UTXO、在用户之间转移资金,并且用户都可以单方面取款。CoinPool 的书面提议需要三种新的软分叉特性:SIGHASH_ANYPREVOUT
、SIGHASH_GROUP
以允许一个签名仅能应用到某一个 UTXO 上,以及 OP_MerkleSub
以验证某一个分支从一棵默克尔树上移除了;后者也可以用 OP_CAT
来实现。
目前,CoinPool 的开发似乎有些停滞,表述其规范的网页的最后一次更新是两年前的了。
3.9 Enigma Network
虽然我被请求讨论 Enigma Network,似乎没有文档能说明这个提议真正的样貌。Bitfinex 的博客文章提出了一系列口号;而 MIT 的页面是空白的。因为这篇博客文章并没有真的说清楚它的实际构造,我们不再进一步讨论。
4 交易池的考虑
Bitcoin Core 当前的交易池策略对 L2 系统来说是不理想的。在这里,我们会介绍它所面临的一些重大挑战,以及可能的优化。
4.1 交易钉死
最终来说是一种经济上的爆破。“交易钉死攻击”,指的是多种情形,一些人可以有意(或无意)让一笔目标交易变得难以挖出,因为另一笔与之冲突的交易被抢先广播并且也 没有 挖出。这是一种经济上的爆破,是因为在一个真正的交易钉死场景中,目标交易是矿工一旦挖出就能得到好处的;而相冲突的交易在很长时间(可能是永久)里 没有 被挖出。
钉死攻击的最简单例子来自一个事实:没有 “full-RBF”(即节点默认所有交易都是可被替换的),交易替换特性可以被关闭。然后,我们可以发起一笔低手续费率、关闭了替换特性的交易,那么它既不会被挖出,也无法被替换。基本上,所有的出块者都开启了 full-RBF,从而解决了这个问题;并且,截至本文撰写之时,在下一版本的 Bitcoin Core 中,full-RBF 应该会默认开启了(在努力了 11 年之后!)。
这让 BIP-125 规则 #3 相关的钉死攻击,变成了剩余唯一跟多方 L2 协议有关(且在 Bitcoin Core 还没有得到解决)的钉死攻击。此处引用 BIP-125 规则 #3:
替代交易需要支付更高的手续费绝对值(而不仅仅是手续费率);要高出所有被替换的交易所支付的手续费总和。
这一规则是可以被利用的:可以广播一笔(或者一组)大体积但低手续费率的钉死交易、花费跟多方协议相关的输出。因为交易的手续费率很低,它就不会很快被挖出(可能永远不会)。然而,因为它的手续费总和较高,用另一笔交易来替换它是不经济的。
BIP-125 规则 #3 相关的钉死攻击在 “手续费率替换(RBFR)” 中是很容易解决的,而且在所有情形中都可以解决。遗憾的是,尚不清楚 RBFR 会不会很快被 Bitcoin Core 采用,因为他们在一种较差的不完整解决方案 “TRUC/V3 交易” 中花了大量时间(中文译本)。
4.2 手续费支付方法
RBF、CPFP、SIGHASH_ANYONECANPAY
、锚点输出和手续费资助
因为手续费率是无法预测的,可靠而又经济的手续费,在交易被预签名的情形中,是非常难做到的。手续费支付的黄金标准是使用 RBF(手续费替换),从一个 “低估” 数值开始,逐步替代以更高手续费的版本,直到交易被挖出。举个例子,OpenTimestamps 日历软件已经用这种办法很多年了,而且 LND 也在 v0.18 中支持了 “考虑终止期限的 RBF”。
RBF 之所以是黄金标准,因为它在几乎所有 [11] 场景中,都是最节约区块空间的:相对于一开始就猜对了正确的手续费的交易而言,替代交易并不需要额外的输入或输出。
效率是重要的,因为手续费中支付中的低效率会让暗箱的手续费支付变成大矿工的利润来源;而体量小的、分散的矿工,则无法从中获益,因为给小矿工支付以期望交易确认是不切实际的、没有用的。协议外的支付也可能会招来 AML/KYC 问题:目前,大部分的协议外手续费支付支付系统都要求某种形式的 AML/KYC 流程;一个显著的例外是 mempool.space 加速器,在本文撰写之时(2024 年 8 月),可以用闪电支付,无需账户。
为了在预签名交易的情形中直接使用 RBF,你需要预签名同一交易携带不同手续费的变体,以覆盖手续费的完整可能区间。虽然这在许多情形中是相当可行的,因为必要的变体数量通常很少 [12],但目前,生产环境中的闪电网络协议 —— 以及提议中的其它协议 —— 都转而选择了 “子为父偿(CPFP)”,通常会通过 “锚点输出”。
锚点输出背后的想法是,向一笔交易添加一个或更多小额(或是零价值)的输出,让子交易在追加手续费(即 CPFP)时可以花费这些输出。在应用到闪电通道这样使用小体积链上交易的协议上时,这自然是非常低效的,会让使用临时锚点输出的承诺交易的总体积膨胀到原来的几乎两倍。在应用到使用较大体积交易的协议 —— 比如使用 OP_CAT
来实现限制条款 —— 上时,就不会那么令人困扰了。
锚点输出的一个不那么显著的问题是,需要保留额外的 UTXO(用在子交易中)来支付手续费。在一个标准的 “客户端” 应用中,这可能是一个重大的开销负担,因为不使用锚点输出的时候,通常完全不需要保管超过一个 UTXO。实际上,在现有的一些面向消费者的闪电钱包中,无法在高手续费环境中支付手续费可能会让他们容易被通道对手攻击(偷盗资金)。
SIGHASH_ANYONECANPAY
可以在某些场合下用来支付手续费,它允许给签好名的交易增加额外的输入;SIGHASH_SINGLE
则允许也加入输出。闪电网络协议将它们用在 HTLC 交易中。在目前,如果没有谨慎处理 [13],这种用法是容易遭到钉死攻击的,因为攻击者可以加入许多输入 以及/或者 输出来制作 高手续费/低费率 的钉死交易。RBFR 可以解决这个问题;而用在 TRUC/V3 交易中的方法则不能解决这个问题。这种手续费支付方法不如 RBF 那么高效,但可以比锚点输出更高效。
最后,也有许多软分叉提议,要给比特币协议加入一种手续费资助系统。这让交易可以声明对其它交易的依赖关系,使得,资助交易只能在被资助交易被挖出的时候挖出(极可能在同一个区块)。这可以比传统的 CPFP 效率高得多,因为资助交易可以使用比交易输入少得多的字节来声明这种依赖关系。
4.3 替代交易循环攻击
“替代交易循环攻击”[14] 尝试用替代交易阻挡一笔目标 L2 交易足够长时间,并让一笔不那么好的交易被挖出。本质上,对攻击者来说,替代交易循环攻击是交易钉死攻击的一种替代,因为攻击者的意图是阻止一笔好的、诚实的交易足够长事件(不让它被挖出),从而让一笔不那么有价值的的、不诚实的交易被挖出。不同的是,替代交易循环攻击不可能是无意中触发的。
典型的例子是针对闪电通道中的 HTLC 交易的。虽然人们可能会认为 HTLC 是一种合约,要么 一笔交易通过揭晓原像来花费它,要么它就会超时。但事实上,因为比特币脚本的限制,通过揭晓原像来花费它的机会是 永远 存在的,在超时之后,只是会 额外 开启一种超时花费机制。
替代交易循环攻击就利用了这一点,在超时 之后 继续尝试使用原像花费交易,来替换尝试通过超时机制赎回价值的交易,同时,不让受害者知道这个原像。成功的替换交易循环攻击要持续足够长时间,直到另一条通道中的 HTLC 超时。
要从替换交易循环中获利,一大挑战在于攻击的每一轮都需要消耗资金。一个能够觉察最终期限的闪电网络实现会使用越来越高的手续费,以尝试在下一个 HTLC 输出过期之前花费(赎回)当前的 HTLC。其次,一旦替代循环结束,任何人都可以通过重新广播被替代的交易 [15] 来挫败这种攻击。
跟钉死攻击一样,替代交易循环也是对矿工的经济爆破。在每次循环结束的时候,都又一笔交易会从交易池中移除,虽然它是完全有效的,也是可以挖出的,只要矿工的交易池中保留了它的话。
5 特性模式与软分叉
我们已经为多种依赖于限制条款的 L2 系统以及交易池所面临的挑战作了概述,接下来我们要提炼一系列著名的软分叉特性(主要是新的操作码)和这些 L2 系统共有的设计模式。对软分叉提议,我们也会讨论跟这些提议相关的技术风险,以及部署它们所面临的挑战。
5.1 OP_Expire
我们先把这个搞清楚。OP_Expire
是作为一种直接消除替代交易循环攻击的办法而被提出的 [16],它直击根本:HTLC 是可以同时被两种不同方式花费的。在 L2 系统的语境下,这跟所有使用 HTLC 及类似机制的系统有关,可能也会跟其它用法有关。OP_Expire
将让一个交易输出在某个时间点 之后 不能再被花费,从而 HTLC 的花费条件变成真正排他性的 OR,而不是 “程序员的 OR”。
真正的 OP_Expire
软分叉可能会由两个特性组成,类似于分两步到来的 OP_CheckLockTimeVerify
和 OP_CheckSequenceVerify
(译者注:分别是脚本层面的绝对时间锁和相对时间锁):
- 交易的过期高度字段,最有可能通过 taproot annex 来实现。
- 一个
OP_Expire
操作码,可以检查交易的过期高度不低于目标高度。
虽然 OP_Expire
自身很难算是限制条款,却似乎对许多依赖于限制条款的 L2 系统都是有用的。不过,给定替代交易循环也可以通过互助重广播 [15] 来缓解,它又可能不够有用。
部署和使用 OP_Expire
的一个非常明显的挑战在于区块链重组:在比特币的技术社区中,从中本聪 [17] 开始,就在尝试保证比特币的共识协议具有这样一种特性:即使发生了深度的重组,以前被挖出的交易也可以进入新区块。这一设计原则尝试避免得到了大量确认的 UTXO 一夕之间变成永久无效的恶魔场景 —— 依赖这些 UTXO 的人就会丢失资金 —— 如果一次共识错误导致了大规模的重组。
在大规模重组事件中,使用上述过期机制的交易可能会变成无法再挖出,因为抵达了它们的过期高度。OP_Expire
提议认为可以将使用上述过期机制的交易当作 coinbase 交易,让它的输出也在 100 个区块内无法花费,从而缓解这个问题。
部署交易过期机制的一种重大负担是达成共识:这种取舍是可接受的吗?甚至,我们需要它吗?在 OP_Expire
能够起作用的交易中,已经包含了冻结用户资金的长时间锁定。加入更长的超时时间是不合适的。此外,在区块重组之后,重复花费总是能够作废某一些 UTXO:随着 RBF 的普及和 “无密钥锚点输出” 的是由,交易超时机制还会有很大作用吗?
5.3 SIGHASH_ANYPREVOUT
BIP-118 提出了两种新的签名哈希模式,两种都 不会 承诺被花费的具体 UTXO。SIGHASH_ANYPREVOUT
,(本质上)转而承诺了 scriptPubKey
(脚本公钥);SIGHASH_ANYPREVOUTANYSCRIPT
则允许任何脚本。如前面所讨论的,这最初是为了支持 LN-Symmetry 而提出的,用于避免每一个被签名过的通道状态都可能要求专门的响应。
SIGHASH_ANYPREVOUT
在我们想要使用带有 RBF 手续费变体的预签名交易时,可能也是有用的,因为签名不再依赖于一个具体的交易 id,也就避免了手续费变体的组合爆炸。然而,当前的 BIP-118 没有指出这一应用场景;也可能是不兼容的,因为 SIGHASH_ANYPREVOUT
被提议也承诺 UTXO 的价值。
对 SIGHASH_ANYPREVOUT
的一种初步反对意见是:钱包可能会因为不合适的使用方式而让自身陷入困境。问题在于,一旦 一个 SIGHASH_ANYPREVOUT
签名被发布,它就可以被用来花费 任何 使用相同脚本的交易输出。因此,只要第二个使用相同脚本的输出被偶然创建出来了,SIGHASH_ANYPREVOUT
就允许一种简单的重放攻击(replay attack),会导致资金被盗。然而,因为钱包和 L2 实现还有许多可能搬起石头砸自己的脚的地方,这一顾虑似乎也消亡了。
在此时,广大的技术社区对于实现 BIP-118 似乎是合理乐观的。然而,就像我们在讨论 LN-Symmetry 时候说的,人们也在辩论他的主要应用场景 —— LN-Symmetry —— 是不是一个好的想法。
5.3 OP_CheckTemplateVerify
我们要讨论的第一个专为限制条款设计的提议是 OP_CheckTemplateVerify
,常常也被称为 “CTV”,它致力于创建一种非常具体的、受限的限制条款操作码,只做一件事:以特定方式哈希不包含具体输入 UTXO 的花费交易,然后检查检查得到的哈希摘要是否与脚本堆栈栈顶的元素相等。这使得我们可以提前约束花费一个输出的花费交易,而不会 让真正的递归型限制条款成为可能。
为什么 CTV 不能实现递归型限制条款?因为哈希函数:CTV 用一个模板哈希值来检查花费交易,那么就没有办法 [18] 创建一种可以包含 CTV 和自身哈希值的模板。
话说回来,这不尽然是一种真正的限制:在最新的计算机上,你可以在几秒内轻松哈希出一条深度达到几千万笔交易的 CTV 模板链条。而 nSeuqunce 相对时间锁和有限的区块空间,会让这个链条轻轻松松将一笔资金锁定几千年。
当前 BIP-119 中的 CTV 提议只有一种哈希模式,叫做 DefaultCheckTemplateVerifyHash
,本质上就是在模板哈希值中承诺花费交易的每一方面。从实用的角度看,这意味着,在许多情况下,CPFP 会成为唯一可用的手续费支付手段。如前所述,这可能是一个问题,因为它让暗箱的支付变成可以节约大量成本的手段,在使用 CTV 的交易体积较小的时候。
公允地说,CTV 也在围绕限制条款操作码提议的技术社区中得到了广泛的支持,因为它相对简洁,用途广泛。
5.3.1 LNHANCE
一种实现 CTV 的提议是将它与额外两种操作码 OP_CheckSigFromStack(Verify)
和 OP_InternalKey
相结合。问题在于,截至本文撰写之时,相关 PR 和 BIP 中的文档不足以支持或否决这一提议。对于这些操作码被期待在哪一些真实案例中发挥作用,相关的 BIP 完全没有任何分析,更不用说深度的案例脚本了。
虽然这个提议的作者们可能有很好的理由,他们有责任解释这些理由并给予恰当的证明。因此,我们不会再进一步讨论。
5.4 OP_TXHASH
类似于 CTV,这一提议通过哈希来自花费交易的数据,从而实现一种非递归的限制条款功能。与 CTV 不同的是,TXHASH 提议提供了一个 “字段选择器” 机制,允许灵活地限制花费花费。这种灵活性实现了两个主要目标:
- 允许为交易添加手续费,而不会打破多交易串联的协议。
- 多用户的协议可以允许用户只限制自己的输入和输出。
OP_TXHASH
的主要问题在于,字段选择器机制也带来了非常多的复杂性,让审核以及测试变得更难(相比于简单得多的 CTV 提议)。截至本文撰写时,甚至还没有出现关于字段选择器机制到底能带来什么好处、具体如何使用的设计分析。因此我们不再讨论。
5.5 OP_CAT
这是个拼接操作码,可以拼接堆栈栈顶的两个元素,然后将结果推回栈中。比特币最初发布的时候,是启用了 OP_CAT
的。但中本聪在 2010 年就悄悄移除了它,因为最初的实现缺乏对结果元素的体积限制,从而容易受到 DoS 攻击。看看这样一个脚本:
DUP CAT DUP CAT...
如果堆栈元素的体积没有限制,每迭代一轮 DUP CAT
都会让栈顶元素的体积倍增,最终用尽所有内存。
拼接足以实现许多类型的限制条款,也包括递归型限制条款,通过:
- 在堆栈中,使用一个或更多
OP_CAT
装置(以及所需的无论什么限制条款专用型逻辑),组装出 没有见证数据 的 残缺 交易。 - 在堆栈中验证组装出来的交易跟花费交易相匹配。
事实证明,通过滥用 Schnorr 签名的数学,就可以用精心构造的签名,在 OP_CheckSig
中执行上述第二个步骤。不过,更可能的是,OP_CAT
软分叉会跟 OP_CheckSigFromStack
相结合,后者允许用验证堆栈中的一个签名是对某一目标交易的有效签名 [19],来执行上述第二个步骤;然后再对同一个签名使用 OP_CheckSig
,来验证花费交易跟目标交易一致 [20]。
事实上,我们只需要组装交易 而不需要 见证数据,是一个关键点:限制条款只需要验证交易 做了什么 —— 其输入和输出 —— 而不需要验证见证数据(如果有的话)能否让这个操作有效。
模数脚本体积限制,结合 OP_CAT
和 OP_CheckSigFromStack
,足以开发只是许多类型的限制条款,包括递归型限制条款。相比更高效的解决方案(比如 CTV),这会更贵一些。但代价上的差别会比你想的要小!
大致上,使用 OP_CAT
,会需要将花费交易的所有非见证数据部分,都通过见证数据放置再堆栈中。对于标准的 CTV 应用场景,例如交易输出树,来说,花费交易完全没有见证数据。但因为见证数据可以打 75% 的折扣,因此子交易的实质交易手续费仅仅高出了 25% 。还不错!
5.5.1 OP_CAT
是否太过强力?
这可能是部署 OP_CAT
要面临的最大的政治和技术阻力:很难预测 OP_CAT
会让哪些用法成为可能。猫咪一旦出了笼子,想抓回来就不是那么容易的了。
一个很好的例子是,有人主张只需要 OP_CAT
就可以在比特币脚本中实现相当高效且安全的 STARK(可扩展的透明知识陈述)验证。因为 STARK 可以证明相当广泛的语句,所以,可以高效实现 STARK 就有极大的影响,不会只影响 L2 系统,因为它会使得许多不同的系统都可以建立在比特币上。一种强烈的反对一件事:这些用法可能不是对所有比特币用户都好。
产生有害的、会诱发中心化的 “矿工可抽取价值(MEV)”,被 Matt Corallo 命名为 “邪恶 MEV(MEVil)”,是一个关键的潜在问题(中文译本)。简而言之,MEVil 是指 大矿工/大矿池 可以通过使用复杂的交易挖矿策略赚取额外收益 —— 而不仅仅是尽可能多的手续费 —— 而小矿工难以采用这些策略的情形。OP_CAT
可以创造出来的金融工具非常复杂,这会让 MEVil 很难消除。在比特币上,显著的 MEVil 在代币拍卖协议出现的时候,就已经出现;幸运的是,这个问题已经因为 full-RBF 的采用而被解决掉了。
除了潜在的 MEVil,OP_CAT
还有其它几种用法可能是有害的。举个例子,我们之前已经评审过的 Drivechain 提议,就被广泛认为是对比特币有害的。有人认为使用 OP_CAT
就可以实现 Drivechain。另一个例子是 Taproot Assets 这样的代币协议。虽然基本上无法阻止使用 “客户端验证” 概念来实现它们,但也有人提出使用 OP_CAT
来实现它们,这对终端用户可能更有吸引力,但这可能会使用多得多的区块空间,可能会挤出 “正统的” 比特币交易。这些用法可能会带来司法问题,取决于这些代币协议多么经常用在金融欺诈中。
5.6 递进哈希
在限制条款的实现中,OP_CAT
的主要用法是拼接数据,然后哈希它们。另一种实现相同目标的方法是使用某种递进哈希的操作码(incremental hashing opcode),取一个 SHA256
运算的某个中间状态,然后哈希更多数据;SHA256 自身是在 64 字节的数据块上操作的。递进哈希操作码有许多种可能的设计。
一个重要的设计抉择是,在将实际的中间状态字节暴露在堆栈中的时候,要使用某种规范的形式,还是用某种不透明的类型来表示它们(使得实际的字节数值无法被直接操作)。SHA256 被指定了一个具体的、固定的初始化向量,如果可以使用任意的 中间状态/初始化向量,不确定 SHA256 的密码学属性是否还能得到保留。
当然,因为递进哈希可以做到 OP_CAT
能做的许多事,只是效率更高,它也要面临一样的顾虑:太过强大。
5.7 Script Revival
OP_CAT
是中本聪禁用的 15 个操作码之一。除了恢复 OP_CAT
,Rusty Russell 正在提议 [21] 通过重启启用其中的大部分操作码、加入 DoS 限制(可能还要在同一个软分叉中加入少量新操作码),将比特币的脚本编程能耐复原成 “中本聪初版”。具体来说,可能会加入一个 OP_CheckSigFromStack
。
虽然 OP_CAT
自身已经让(递归的)限制条款成为可能,完整的 “script revival(脚本复兴)” 会让更加复杂的限制条款成为可能 —— 实现起来也容易得多 —— 因为可以直接操作花费交易的某些部分。举个例子,你可以事项一种限制条款脚本,使用算数操作码来保证交易的输出的总价值会保持一些有趣的属性。
此外,脚本复兴也面临跟 OP_CAT
相同的顾虑,甚至更多,因为它比 OP_CAT
还要强力。
5.7.1 Simplicity
类似于脚本复兴,Simplicity 跟 L2 和限制条款相关是因为它可以做所有事情。而与脚本复兴不同的是,Simplicity 软分叉可能会给比特币的脚本系统加入一种全新的编程语言,基于 9 种叫做 “结合码(combinator)” 的操作码原语。
实际上,Simplicity 既过于简单,又一点也不简单。结合码过于底层,以至于连加法这样基本的操作都要辛辛苦苦从头实现;裸的 Simplicity 代码在实践中会过于繁琐。因此,Simplicity 的任何真实用法可要利用一种代码替换系统,类似于库函数调用,叫做 “jet”。这就成了一个 实用/政治 问题:如何决定要实现哪个 jet?很可能 jets 会用 C++ 语言来实现,就跟别的操作码一样,从而每加入一个新的 jet 都需要一次软分叉。
5.8 OP_FancyTreeManipulationStuff
人们还提出了许多相对专用的操作码,以更节约空间的方式操作树结构,以供依赖于限制条款的 L2 系统使用。举个例子,Coinpool 提议就提出了 TAPLEAF_UPDATE_VERIFY 和 OP_MERKLESUB,两种操作码都是对 taproot 脚本树的操作,对 Coinpool 提议来说都是必要的,而 MATT 也提出了一种 OP_CheckContractVerify
操作码,基本上,就是验证关于默克尔树的陈述。
从本文的目的出发,我们不需要细究这许多提议中每一种的细节。相反,我们可以把它们都当成一类:它们全部是相对专用的协议,旨在让一类 L2 成为可能,并希望没有意料之外的副作用。它们都有高效的优点:比起使用更通用的操作码(例如 OP_CAT
操作),它们都使用更少的区块空间,就能实现相同的目标。但它们的缺点就在于给脚本系统增加了复杂性,就为了一个可能小众的应用场景。
同样的顾虑在比特币是否要接受 Simplicity 的讨论中也存在。在 Simplicity 中,要为常用的模式添加一种 jet(等价于操作码)。一样的,为专门的场景实现 jet(比如树操作)也会有类似的优点和缺点,跟为场景专用的操作实现复杂的操作码一样。
6 资金池
所有尝试让多个用户共享一个 UTXO 的 L2 系统都可以被认为是某种多用户的资金池,其中的用户持有某种形式的取款权。潜在地,也会有一种可以向资金池添加资金的机制(除了用预签名的资金创建资金池之外)。
一种资金池要有用,就必须有某种方式, “分享与之相关的数据状态”:如何分割输出的价值?如果这个资产池会随时间变化,它的状态也必须随着资金的进入和退出而改变。因为我们是建立在比特币上的,添加和从池中移出资金不可避免要花费该资金池所控制的 UTXO。
请记住,比特币共识系统自身就建立在 对状态变更的验证 之上:交易通过它的见证来证明对 UTXO 集状态的改变是有效的;工作量证明让我们可以对发生了哪一组达成共识。这意味着,资金池自身也要建立在对状态变更的验证之上:我们要向每一个比特币节点证明,资金池的规则,在每一次状态变更中,都得到了遵守。
但 免信任的 L2 资金池还有另一个关键侧面:当资产池的状态改变的时候,资金池的系统必须为参与这个资金池的用户提供足够多的数据,让用户能够复原自己的资金。如果没有做到这一点,那我们的系统就无法提供单方面取款、无需第三方协助的特性。许多基于 rollup 的系统都是做不到的:它们受困于 数据可得性 故障,只要第三方协调员下线,用户就无法复原自己的资金,因为缺乏必要的数据来构造有效的资金复原交易。(译者注:从概念上来说,这一批评是无效的,因为 rollup 的定义中包括会将这样的必要数据直接发布在区块链上的要求;不这样发布的技术范式应该有别的名称。但不排除可能有一些以 rollup 为卖点的项目并没有保证这一点。)
知道了有这样的限制,那么资金池要建立在怎样的数据结构上?无法避免,它们都是某种形式的树结构。具体来说,是某种形式的默克尔树。必须是树结构,因为这是计算机科学中唯一可伸缩的数据结构;必须默克尔化,因为这基本上是用密码学承诺树结构状态的唯一合理方式。最后,更新树的操作不可避免要发布到比特币区块链上,因为这是一种所有 L2 用户都共享的公开媒介,也是唯一一个我们可以强迫用户发布的地方。而且,因为任何限制条款实现,都将需要部分树结构,来验证限制条款的规则得到了遵守。
那么,这些抽象的理论,如何翻译成比特币交易和脚本?
6.1 单笔预签名交易
树的退化形式,就是整棵树只有一个叶子。这里,粗糙地说,我们的资金池的状态只能变更一次。举个例子,标准的闪电通道就属于这一类,打开之后,就只能关闭一次。在通道关闭的时候,被发布出来的数据是预签名交易自身,这对通道的对手来说是足够的信息,可以从区块链数据中知晓 txid,然后通过花费它来复原资金。
这里需要的唯一一种 “限制条款” 就是最基本的限制条款:预签名的交易。
6.2 交易输出树
下一种,更复杂的设计模式,是交易输出树。Ark 是显著的例子。在这里,通过花费一棵预签名交易树的根 UTXO ,就可以分割资金池;这可以通过简单的限制条款,例如预签名交易或者 CTV,来强制执行;UTXO 的价值可以不断分割成更小的数额,直到出现叶子节点,可被它真正的所有者花费。
重点是,交易输出树的用意是给予用户复原资金的 选择权,而这些选择权也是有代价的:比起在一笔交易中分割 UTXO,交易输出树总是更贵的分割方法。树结构每深一层,都会增加一些成本,因为创建一层所必要的交易输出和输入都要占用一些字节。
那么,交易输出树提供了何种选择权?这方面,Arck 又是一个很好的例子:我们不希望在链上赎回一个 V-UTXO 会导致每一个 V-UTXO 都出现在链上。通过使用树结构,赎回操作会将树结构不断分割成更小的部分,直到目标 V-UTXO 被发布到链上。
类似于单笔预签名交易的情形,被发布的信息就是交易自身,可以通知别的用户的钱包如何花费资金(如果有必要的话)。
交易输出树的可扩展性带来了有趣的规模经济。在一个有 nn 个 v-UTXO 的资金池中,第一个要发布到链上的 V-UTXO 所需付出的代价,大概是一笔交易的 log2(n)log2(n) 倍,因为必须在链上发布 log2(n)log2(n) 笔分割交易。然而,一旦第一个 V-UTXO 被弹出到链上,后续的 V-UTXO 要在链上赎回就会变得更便宜,因为其他人已经支付了让中间交易得以挖出的代价。
回想一下,在一棵有 nn 个叶子的二叉树中,元素的总数量是 2n2n 个。这就意味着,要将 所有 的 V-UTXO 发布到链上,通过交易输出树来实现的总成本将是用一笔交易来实现的小几倍。惊人地高效!
又或者不是这样的 …… 如果资金池赎回的总体积足够高,它们将构成对总的区块空间的不小的需求。区块空间是一个供需系统,所以,高需求之下,某个时间开始手续费就会上升。推到极端,很有可能创建出来的交易输出树是那么深,以至于实际上赎回树上的每一个 V-UTXO 变得不可能。
跟交易输出树有关的一个开放问题是,谁支付手续费?怎么支付?一个显然的解决方案是在叶子交易中使用无密钥的描点输出,让想要叶子交易被挖出的人来支付手续费,通过 CPFP。在某些场景中,V-UTXO 自身可以在创建后立即花费,没有 CSV 延迟,所以 V-UTXO 自身也可以被用来支付手续费,也是通过 CPFP。
因为许可问题,RBF 实现起来更加复杂:RBF 手续费的明显来源是 V-UTXO 的价值。但是,我们怎么保证只有所有者才能签名一笔更高手续费的交易?在许多情形下,怎么做到比无密钥锚点输出更高效都是不清楚的。不过,不能做到这一点,就会给终端用户钱包所使用的方案带来严峻的挑战,因为如果 V-UTXO 无法被立即花费的话,钱包内可能没有 UTXO 来执行 CPFP。
最后,我们需要缜密地思考交易输出树系统需要什么样的激励机制,要把手续费也纳入考量。举个例子,在 Ark 这样的系统中,如果一组 V-UTXO 各自 都要花很多钱才能发布到链上,以至于退回到链上是不经济的,那么,一个不合作的协调员就可能会拒绝让这些 V-UTXO 在链下赎回,也就是可以在超时之后,用一笔花费交易盗取这些 V-UTXO 中的价值。
如果这问题无解,那么,可以说,这样的系统,在面对低价值的 V-UTXO 的时候,已经不符合 L2 的标准了。
6.3 基于余额的方案
交易输出树的状态机依然是相对简单的:要么资金池继续存在,要么它被花费,从而产生两个或更多更小的资金池。使用更高级的限制条款,我们可以转而将资金池处理成一种可变化的余额表,并且能够向现金表增加资金、从其中减去资金。
为此,我们需要实现一种不简单的状态机。但根本上我们还要实现一种共享的数据库。为什么呢?因为目标是要在许多不同的所有者之间分享一个 UTXO。最终来说,如果我们真的要获得一种可扩展性提升,我们就必须让发布在链上的所有权数据尽可能少。
这些要求自然将我们引向某种树形的默克尔化数据结构,例如一种默克尔总和树。操作这种数据结构内在地需要像 OP_CAT
这样的东西,某种零知识证据验证操作码,或者是一种专用的树操作码。
有趣的是,就像在交易输出树情形中一样,你不可能可扩展性做得比 log(n)log(n) 级别更好、还维持相似的安全特性。为什么呢?假设我们有一种假想的 OP_ZKP
,通过一些高级的数学,只需要 32 字节就可以证明任何陈述。虽然这种零知识证据可以 证明 对这个默克尔化的数据结构的操作符合这个 L2 系统的规则,但也无法为下一个想运行状态变更的用户提供必要的 数据。这就不能满足单方面取款的优先标准:在最好的情况下,只有第一个用户能够无条件取款。而后续的用户就做不到了。
相反,如果默克尔化数据结构的变更部分是通过限制条款脚本签名来发布的 —— 例如,一棵默克尔树上的一个分支摘要 —— 那么下一个用户将有足够多的数据来更新他们对系统状态的理解,然后也将可以发起单方面取款。
一个可能绕过这个问题的办法是,让限制条款要求将证据发布在比特币区块链之外的公开媒体上。不过,安全性保证将弱于使用比特币区块链的情形。
最后,注意,交易输出树和基于余额的方法可以结合。如果被操作的数据结构 就是 一棵交易输出树,那么,就可以给输出树增加资金:花费根输出并添加新的资金,然后用一个限制条款脚本来验证资金被添加到了输出树种。等价的,资金也可以使用交易输出树可用的机制来移除。高级 Ark 就是这类方案的一个例子。
7 故障数据比例
L2 通过在敌意场景中加入互动要求来实现可扩展性。在几乎所有情形中,这都意味着,协议中的诚实参与者要在终止时间到来之前让交易被挖出;要是没有赶上,资金就可能被盗。
在所有去中心化的区块链上,最大的区块容量都受制于技术限制(中心化的区块链也如此)。在比特币上,区块空间的上限让比特币的区块空间几乎全时间满载。因为比特币挖矿是个拍卖系统,向出价最高者拍卖区块空间,在实际上,这意味让交易得到区块确认的手续费率门槛值会随着需求的起落而起落。
手续费率总是会影响 L2 的经济模式和故障模式。举个例子,在闪电通道中 “粉尘大小” 的 HTLC 因为价值太低、在链上赎回不经济,就使用了跟大额 HTLC 不同的安全模式。虽然闪电网络协议还没有恰当地实现,但理论上,这个门槛值应该是动态的,基于起起落落的手续费率,理想情况下,是能取到一个点,让参与者可以选择基于手续费率,决定一个 HTLC 要不要存在于一笔承诺交易中。
人们已经提出了在闪电网络上主动制造事件来发动的多种攻击,例如 “洪水攻击” [22] 和大规模退出攻击 [23]。因为比特币的区块空间是在所有应用场景之间共享的,攻击波及别的 L2 系统也是有可能的:例如,在 Ark 上触发大规模退出,然后从闪电通道中获利。
L在多个用户间共享 UTXO 的 L2,先天让这些问题变得更加难搞,因为在最坏情形下,区块空间需求会在故障期间异常高涨。截至本文撰写之时,我们还从未实际观察到闪电网络上出现许多通道不得不同时关闭的大规模故障。这是一个很好的理由:我们应该在使用 UTXO 共享方案拓宽可拓展性边界之前,从闪电网络和它的 “每个用户1 个 UTXO” 限制中获得额外的操作经验。
其次,在新的 UTXO 共享方案被广泛采用之前,应有对区块空间需求高涨时期潜在攻击可能性的细致研究。举个例子,在一个 Ark 这样的系统中,ASP 可以使用比其他参与者更少的区块空间来赎回资金,所以有意制造高手续费率环境、然后没收单方面取款不经济的资金,可能会成为一种有利可图的欺诈,这就完全违背了我们给真正 L2 系统提出的两条标准。
8 共识清理
在初始的比特币协议中,中本聪还在一些事情上犯了错误,尤其是,脚本内的 DoS 攻击、虫洞攻击,还有默克尔树问题。以前,许多其它共识问题已经用软分叉修复了,例如切换成使用 “过往中值时间” 来运算基于时间的 nLockTime,(尝试)修复交易 id 重合问题,等等。
最近的一次软分叉 Taproot,因为部署流程相对争议较大,花了很长时间才真正部署。先部署 “共识清理” 软分叉,再(为新型 L2)启用新的操作码或其它特性的一个理由是,我们已经知道了,广大的社区是多么希望实现争议应该相对较小、可以说对每一个人都有好处的软分叉。
9 测试依赖于软分叉的 L2
开发者们不需要等待软分叉实际激活才能测试自己的想法。Ark 开发者们在 “无限制条款 Ark” 中使用的一个非常复杂的方法就是用预签名交易来模拟限制条款。这让他们可以用真正的 BTC,或者说在主网上,实现相同的信任特征,然后测试他们的 Ark 想法(因为 Ark 被预期用限制条款来实现)。取舍在于,这种无限制条款的 Ark 需要所有参与者都在线,才能签名预签名交易。由于它使用真正的 BTC,也许可以证明,对特定用户的生产环境,它是非常有用的,使人可以忍受它的交互要求。
一种更简单的方法是直接假装某些参与者无法作出限制条款可以阻止的行为。举个例子,如果被提议的协议希望使用 CTV 来强制在一棵交易树种花费一棵输出树,那么每一个 CTV 都可以替换成一个 NOP
或者 CheckSig
。虽然事实上输出树没有真的被强制执行,跟这棵树和每一方交互的代码都可以被当成有 CTV 那样测试,并且,因为 NOP
和 CheckSig
是标准脚本,协议可以在主网上用真实资金来测试。
10 可能的软分叉
未来路怎么走?在这里,我们将汇总我们分析过的所有主要的 L2 方案,以及让这些 L2 成功,需要(R)哪些软分叉、以及哪些分叉是有用的(U)。如前所述,OP_CAT
(以及它的延伸:包含了它的脚本复兴软分叉),可以模仿这个列表中所有其它软分叉 —— 除了 OP_Expire
和手续费资助 —— 所以,当一个项目的需要可以被其它一些软分叉更高效地直接满足的时候,我们就不会包括 OP_CAT
。
我们也将省略所有提议中的默克尔树操作码。它们都太狭窄、太专用了,从现在来看,没什么机会得到采用。以至于,在这些操作码有用的地方,通过 OP_CAT
以及/或者 脚本复兴来实现它们的效果,是更有可能获得采用的道路。
OP_Expire | SIGHASH_ANYPREVOUT | CTV | OP_CAT | 脚本复兴 | |
---|---|---|---|---|---|
闪电通道 | U | U | U | ||
通道工厂 | U | U | |||
LN-Symmetry | U | R | |||
Ark | U | R | |||
高级 Ark | U | U | R | ||
有效性 Rollup | R | U |
在这里,CTV 是显然的胜出者,然后是 SIGHASH_ANYPREVOUT
(OP_Expire
虽然对许多东西有用,它可以修复替代交易循环攻击,但不是根本的)。CTV 胜出,是因为许多东西都适合 “确保花费交易匹配这个模板” 的设计模式;甚至 OP_CAT
构造也可以高效使用 CTV。
与 OP_CAT
不同的是,CTV 似乎不会引来意外的后果,只有在特定场景中鼓励暗箱手续费支付的风险。这并不理想,但还没有人提出得到广泛支持的替代方案。
我个人的建议是:先激活共识清理软分叉,然后是 CTV 软分叉。
11 脚注
1. 至少,应该是这样的!好像现在的闪电客户端实现并不会很好地限制转发中的粉尘 HTLC 的总价值。 ↩
2. 十年以前,我就提出了一种 L2 系统 —— 忠诚保险银行 —— 符合这个第三方偷盗无利可图的要求。但不满足单方面取款的优先标准。我是第一个说闪电通道比忠诚保险银行 好得多 的人! ↩
3. 你可能会问,为什么说闪电通道要求每个终端用户至少要有 1 个 UTXO?一条通道不是有两个用户吗?理由在于,闪电网络是一个 网络:如果每两个用户只有 1 个 UTXO,那么最多你只能形成许多相互孤立的 成对 用户,而无法形成一个广大的网络。每个节点 1 个 UTXO, 也只能形成一串节点(用户),虽然在技术上来说,这些节点是完全相连的。当然,在现实中,每个用户需要 不止 一个 UTXO,因为一个节点链条仅对少量节点有用,因为通过几百跳来路由一笔交易在技术上是不可行的。 ↩
4. Alex Bosworth 独立公开了一份分析,得出的数字跟我在 2022 年得出的本质上相同!在我写自己的文章时,我要么从来没看过他的分析 —— 又或者早已忘记了。所以我很开心我们得出了相同的数字。 ↩
5. 事实是,通道拼接的拼入和拼出可以合并在同一笔交易中,也会减少必要的额外输出的数量,因为拼出也可以给拼入提供资金。还要指出的是,对外部观察者来说,这样的交易跟 coinjoin 是无法区分的。 ↩
6. 为了使用 RBF,一个 V-UTXO 方案可能要拥有许多预签名交易。但这许多笔交易的目的是为了执行一笔经济的交易。—— 就像在闪电通道中一样,不是为了让多笔经济交易都能发生。当然,这个定义有点模糊;也许有人能提出一种结合 V-UTXO 和通道余额的方案! ↩
7. 也就是说,一笔 Ark 交易要么发生,要么不发生;它可能需要几小时甚至几天来启动。但是,要么预定的所有资金都转移了,要么完全没有转移。 ↩
8. 请记住,如果 ASP 拒绝让一个 V-UTXO 进入一个新轮次,用户的唯一应对手段是单方面在链上取出资金。这办法不仅昂贵,而且要花时间:也许用户的交易还没得到确认,ASP 就已经可以把池交易输出花掉了。如果一轮足够长,甚至可能变成同一轮的用户争夺区块空间。 ↩
9. 出版证明问题的一个例子,我们会在后面讨论。 ↩
10. [[Lightning-dev] 使用层级式通道,在链下调整闪电通道的大小](https://lists.linuxfoundation.org/pipermail/lightning-dev/2023-March/003886.html),jlspc,2023 年 3 月 18 日(中文译本)。亦见 GitHub。 ↩
11. 在交易的输入和输出都因为某些约束而被固定的罕见场合中,RBF 可能比暗箱手续费支付、手续费资助等等方案更低效,它们可以让交易的体积更小。 ↩
12. 1.0575=12721.0575=1272,所以,75 个彼此差距为 5% 的手续费变体,就可以覆盖比特币主网上曾经出现过的单区块内费率差异最大的区间。 ↩
13. 在应对交易钉死风险时,可以仅对部分签名应用 SIGHASH_ANYONECANPAY
,这样可以防止发动攻击的参与者添加输入。闪电网络也对 HTLC 交易应用了这种技术,仅一方会使用 SIGHASH_ANYONECANPAY
来签名。 ↩
14. 虽然权威来源是 Antoine Riard 的论文,我强烈建议阅读 monoautical 的介绍替代交易循环攻击的推特,那是一个容易理解的解释。 ↩
15. [[bitcoin-dev] Altruistic Rebroadcasting – A Partial Replacement Cycling Mitigation](https://lists.linuxfoundation.org/pipermail/bitcoin-dev/2023-December/022188.html),Peter Todd,2023 年 12 月 9 日。 ↩
16. [[bitcoin-dev] OP_Expire and Coinbase-Like Behavior: Making HTLCs Safer by Letting Transactions Expire Safely](https://lists.linuxfoundation.org/pipermail/bitcoin-dev/2023-November/022108.html),Peter Todd,2023 年 11 月 2 日。 ↩
17. Coinbase 交易是跟它所在的区块绑定的。中本聪让这些输出不可花费,直到它们累计获得 100 个区块确认。中本聪也在 bitcointalk 中讨论过完全相同的问题,并解释了为什么一种 OP_BLOCKNUMBER
操作码可能是危险的。 ↩
18. 如果你找出了一条包含了其自身哈希值的消息,我强烈建议你卖掉你所有的比特币,换成热兵器、食物和弹药,然后找一个不错的洞穴藏身。 ↩
19. 技术上来说,我们实际上要构造 CheckSig
为我们选择的 SIGHASH
模式使用的序列化方式,这不同于生产交易 id 时候的序列化方式。 ↩
20. 如果 CTV 可用,你也可以直接组装出 CTV 模板,哈希它,然后用 CTV 来检查它。这是有用的,如果限制条款专用的逻辑比 CTV 独自可以做的复杂得多的话。 ↩
21. Rusty 首次提出这个想法是在 bitccoin++ Austin 2024 会议的一场演讲中。在本文撰写之时,他也在撰写相关的 BIP 草案和实现。 ↩
22. “Flood & Loot: A Systemic Attack On The Lightning Network”,Jona Harris and Aviv Zohar,2020 年 6 月 15 日。 ↩
23. “Mass Exit Attacks on the Lightning Network”,Cosimo Sguanci and Anastasios Sidiropoulos,2024 年 2 月 7 日 ↩
Peter Todd 2024-09-11
https://www.btcstudy.org/2024/09/11/soft-for-covenant-dependent-layer-2-review/