原文标题:《THE GREAT SCRIPT RESTORATION: A PATH FORWARD FOR BITCOIN》
撰文:Shinobi
编译:Chris,Techub News
比特币最初被设计时,带有一个完全成熟的脚本语言,旨在涵盖和支持用户可能想到的任何潜在的安全用例。正如中本聪在消失前所说:
「比特币的本质是,一旦 0.1 版本发布,其核心设计就注定在其生命周期内无法改变。正因如此,我想设计它来支持我能想到的每种交易类型。问题在于,每件事都需要特殊的支持代码和数据字段,无论是否使用,而且每次只能覆盖一个特殊案例。这会导致特殊情况下网络的拥堵。解决方案是脚本,它将问题概括化,以便交易双方可以将其交易描述为网络节点评估的一个谓词。」—— 中本聪,2010 年 6 月 17 日。
其全部意图是给用户一个足够通用的语言,使他们可以按照自己的意愿组合自己的交易类型。即,给用户设计和试验如何编程自己的资产的空间。
在他消失之前,中本聪移除了 15 个操作码,完全禁用了它们,并为脚本引擎堆栈上可以操作的数据大小设定了一个硬限制(520 字节)。这是因为他确实搞砸了,留下了大量方式让复杂脚本可以用来对整个网络进行拒绝服务攻击,创建巨大且昂贵的交易,使节点崩溃。
这些操作码并不是因为中本聪认为功能危险或人们不应该使用它们而被移除的,而是仅仅(至少表面上)因为它们在没有资源限制的情况下使用,会对网络施加的最坏情况验证成本构成风险。
自那以后,每次比特币的升级,最终都是简化剩余的功能,纠正中本聪留给我们的其他不太严重的缺陷,并扩展我们留下的脚本子集的功能。
恢复脚本的逻辑
在五月初的 Bitcoin++ 会议上,Core Lightning 开发者 Rusty Russell 在会议的第一次演讲中提出了一个相当激进的建议。他基本上提出了重新启用中本聪在 2010 年消失前禁用的大部分操作码的想法。
自 2021 年 Taproot 激活以来的这几年,开发方向坦白地说有点迷茫。我们都知道,比特币并不足够可扩展,无法真正以自我主权的方式服务世界上大部分人口,甚至可能无法以信任最小化或托管方式扩展到超大规模的托管人和服务提供者,从而无法真正摆脱政府监管的限制。
任何从技术层面理解比特币的人都明白这一点,这没有争论的余地。争论的是,如何解决这个短板。自 Taproot 以来,每个人都在提出建议,但这些建议都只能解决非常特定的用例。
ANYPREVOUT(APO),一个允许签名在不同交易上可重用的提案,它专门为优化 Lightning 和多方版本而设计。
CHECKTEMPLATEVERIFY(CTV),一个强制规定加密货币只能通过与预定义交易完全匹配的交易花费的提案,专门设计用来扩展预签交易链的功能。
OP_VAULT 专门设计用来为冷存储方案启用一个 「超时期」,以便用户如果他们的密钥被泄露,可以通过将其发送到一个更冷的多签设置来 「取消」 冷存储的取款。
还有许多其他提案,但我想你明白我的意思了。与其尝试解决狭窄功能,不如全面解决比特币在根本上扩展所需的表达性和可编程性,这些年来的每个提案都设计用来提供小幅度的可扩展性或改进某个被认为是理想的狭窄功能。我认为这就是为什么这些对话没有进展的原因。没有人对其他提案感到满意,因为它不符合他们希望看到的用例。
没有任何一个提案是全面的,能让提案之外的任何人认为它是合理的下一步。
这就是恢复脚本的逻辑。通过推动和分析中本聪最初设计的脚本的全面恢复,我们实际上可以尝试探索我们需要的全部功能,而不是在狭小的功能扩展上争论不休。
操作代码
- OP_CAT:取堆栈上的两个数据块并将它们合并成一个。
- OP_SUBSTR:取一个长度参数(以字节为单位),从堆栈上取出一个数据块,移除指定长度的字节并将其放回。
- OP_LEFT & OP_RIGHT:取一个长度参数,从数据块的一侧或另一侧移除指定长度的字节。
- OP_INVERT & OP_AND & OP_OR & OP_XOR & OP_UPSHIFT & OP_DOWNSHIFT:从堆栈上取出一个数据元素并对其进行相应的位操作。
- OP_2MUL & OP_2DIV & OP_MUL & OP_DIV & OP_MOD:用于乘法、除法和模运算的数学操作符(返回除法的余数)。
以上是拟恢复的操作码。此外,Rusty 提议了三个操作码,以简化不同操作码的组合。
- OP_CTV(或 TXHASH / 等效项):允许强制要求交易的某些部分提前定义。
- CSFS:允许针对任意数据验证签名,而不仅仅是整个交易。这允许你要求脚本或数据的某些部分必须签名才能执行。
- OP_TWEAKVERIFY:验证涉及公钥的 Schnorr 操作,如从聚合公钥中添加或减去单个公钥。这可确保在一个方离开共享 UTXO 时,其他所有人的资金被发送到一个不需要离开方签名的聚合公钥,以便合作花费。
我们为何要这么做
Layer 2 本质上是比特币基础层的扩展,它们在功能上受到基础层功能的限制。Lightning 需要三次软分叉,CHECKLOCKTIMEVERIFY(CLTV)、CHECKSEQUENCEVERIFY(CSV)和隔离见证,才能实现。
没有更灵活的基础层,就无法构建更灵活的 Layer 2。唯一的捷径是依赖信任的第三方,这一点我们都希望在比特币大规模应用中尽可能消除。
为了安全地将超过两个人打包到单个 UTXO 中并在基础层上无信任地强制执行,我们需要做一些我们现在无法做到的事情。比特币脚本不够灵活。最基本的层面上,我们需要约束,脚本需要能够实际强制执行更多关于执行交易的细节,以确保用户安全退出 UTXO 而不危及其他用户的资金。
从宏观角度看,这是我们需要的功能:
- 内省:我们需要能够实际检查堆栈上花费交易本身的具体细节,例如 「这笔钱的一部分去某个公钥」。这让我可以用我自己的特定 Taproot 分支自行取款,同时确保我不能拿走其他人的钱。脚本执行将通过共识强制执行,确保其他所有人拥有的正确金额被发送回其他用户公钥组成的地址。
- 前向数据携带:假设我们走得更远,比 Lightning 通道还要多的人,我们构建了一个有大量人的单个 UTXO,任何人都可以随意进出。几乎总是需要一个默克尔树及其根,我们需要某种方式来追踪谁有多少钱。这意味着当有人离开时,我们必须确保 「记录」 谁有权得到什么成为所有其他人资金的更改 UTXO 的一部分。这本质上是内省的一个特定用途。
- 公钥修改:我们需要确保可以在堆栈上验证聚合公钥的修改。在 UTXO 共享方案中,我们的目标是有一个包含所有参与者的聚合密钥,允许合作且更高效地移动资金。每当有人单方面离开共享 UTXO 时,我们需要从聚合密钥中移除他们的个人密钥。如果不预先计算所有可能的组合,唯一的选择是能够验证从聚合密钥中减去一个密钥创建了一个有效的由其他个人密钥组成的密钥。
如何确保安全:VAROPS
正如我上面所说,禁用所有这些操作码是为了消除可能导致网络崩溃的拒绝服务攻击风险。有一种方法可以解决这个问题,即限制这些操作码可以使用的资源量。
我们已经有这样一个解决方案用于签名验证,这是验证比特币脚本最昂贵的部分。它叫做 sigops 预算。每次使用签名检查操作码都会消耗每个区块允许的签名操作预算。这对交易验证单个区块的成本设定了一个硬限制。
Taproot 改变了这种工作的方式,使用每个交易相对于其大小的 sigops 限制,而不是使用单个全局区块限制。这实质上与相同的全局限制相同,但使得更容易推理单个交易可用的 sigops 数量。
Taproot 处理 sigops 限制相对于每个交易的方式的变化提供了一种方法来概括这一点,这就是 Rusty 提议的 varops 限制。其想法是为每个重新启用的操作码分配一个成本,以考虑最坏情况,即验证它们可能创建的最昂贵的计算成本。每个操作码都会有自己的 「sigops」 限制,以约束它在验证过程中可以消耗的资源量。这也会基于使用它们的任何交易的大小,从而保持推理的简便性,同时仍然累计到每个区块的隐含全局限制。
这将解决导致中本聪最初禁用所有这些操作码的拒绝服务风险。
向前推进
我敢肯定你们中的许多人在想 「这是太大的变化」。我可以理解这一点,但我认为作为一个提案理解这个项目的重要方面是,我们不必全做。这个提案的价值不一定是将所有这些都恢复,而是我们实际全面地审视这一大套原语,并问自己我们真正需要什么功能。
这将与过去三年争论和争吵的小范围改变完全不同,这些改变只对某些功能有所帮助。这是一个大帐篷,可以把每个人都聚集在一起,真正全面地评估从这里走向何方。也许我们最终会恢复所有这些,或者我们只激活一些,因为共识是我们需要的功能。
无论最终结果是什么,这都可以是一个关于我们从这里走向何方的对话的有益改变。我们可以实际绘制并全面了解情况,而不是在争论接下来要走的模糊和半明路径。
这不是我们必须采取的前进道路,但我认为这是我们决定哪条路的最好机会。是时候开始以一种有成效的方式再次共同努力了。


