10.13改变共识规则

共识规则确定交易和块的有效性。 这些规则是所有比特币节点之间协作的基础,并且负责将所有不同角色的本地视角融合到整个网络中的单一一致的区块链中。虽然共识规则在短期内是不变的,并且在所有节点之间必须一致,但长期来看它们并不总是不变的。 为了演进和开发比特币系统,规则必须随时改变以适应新功能,改进或修复错误。 然而,与传统软件开发不同,升级到共识系统要困难得多,需要所有参与者之间的协调。

10.13.1硬分叉

在前面章节比特币分叉中,我们研究了比特币网络如何短暂地分叉,网络中的两个部分在短时间内处于区块链的两个不同分支。我们看到这个过程是如何自然发生的,作为网络的正常运行的一部分,以及如何在一个或多个块被挖掘之后,网络在一个统一的区块链上重新收敛。

另一种情况是,网络也可能会分叉到两条链条,这是由于共识规则的变化。这种分叉称为硬分叉,因为这种分叉后,网络不会重新收敛到单个链路上。相反,这两条链子独立发展。当比特币网络的一部分节点按照与网络的其余部分节点不同的一致性规则运行时,硬分叉就会发生。

这可能是由于错误或者由于故意改变了协商一致规则的实施而发生的。硬分叉可用于改变共识的规则,但需要在系统中所有参与者之间进行协调。没有升级到新的共识规则的任何节点都不能参与共识机制,并且在硬分叉时刻被强制到单独的链上。

因此,硬分叉引入的变化可以被认为不是“向前兼容”,因为未升级的系统不能再处理新的共识规则。让我们来看一下硬分叉的技巧和具体的例子。下图10-9显示区块链出现两个分叉。在块高度4处,发生单一个区块分叉。这是我们在前面章节比特币分叉中看到的自发分叉的类型。经过块5的挖掘,网络在一条链上重新收敛,分叉被解决。

10.13 改变共识规则 - 图1然而,后来在块高度6处发生了硬分叉。我们假设原因是由于新共识规则的变化出现新的客户端版本。从块高度7开始,矿工运行新的版本,需要接受新类型的数字签名,我们称之为“Smores”签名,它不是基于ECDSA的签名。紧接着,运行新版本的节点创建了一笔包含Smores签名的交易,一个更新了软件的矿工挖矿出了包含此交易的区块7b。

任何尚未升级软件以验证Smores签名的节点或矿工现在都无法处区块7b。从他们的角度来看,包含Smores签名的交易和包含该交易的块7b的交易都是无效的,因为它们是根据旧的共识规则进行评估的。

这些节点将拒绝该笔交易和区块,并且不会传播它们。正在使用旧规则的任何矿工都不接受块7b,并且将继续挖掘其父级为块6的候选块。实际上,使用如果它们连接的所有节点都是也遵守旧的规则,遵守旧规则的矿工甚至可能接收不到块7b,因此不会传播这个区块。最终,他们将能够开采区块7a,这个旧的规则是有效的,其中不包含与Smores签名的任何交易。

这两个链条从这一点继续分歧。 “b”链的矿工将继续接受并开采含有Smores签名的交易,而“a”链上的矿工将继续忽视这些交易。即使块8b不包含任何Smores签名的交易,“a”链上的矿工也无法处理。对他们来说,它似乎是一个孤立的块,因为它的父“7b”不被识别为一个有效的块。

10.13.2硬分叉:软件,网络,采矿和链

对于软件开发人员来说,术语“分叉”具有另一个含义,对“硬分叉”一词增加了混淆。在开源软件中,当一组开发人员选择遵循不同的软件路线图并启动开源项目的竞争实施时,会发生叉。我们已经讨论了两种情况,这将导致硬分叉:共识规则中的错误,以及对共识规则的故意修改。在故意改变共识规则的情况下,软件叉在硬分叉之前。但是,对于这种类型的硬分叉,新的共识规则必须通过开发,采用和启动新的软件实现。

试图改变共识规则的软分叉的例子包括Bitcoin XT,Bitcoin Classic和最近的Bitcoin Unlimited。但是,这些软分叉都没有产生硬分叉。虽然软件叉是一个必要的前提条件,但它本身不足以发生硬分叉。对于硬分叉发生,必须是由于采取相互竞争的实施方案,并且规则需要由矿工,钱包和中间节点激活。相反,有许多比特币核心的替代实现方案,甚至还有软分叉,这些没有改变共识规则,阻止发生错误,可以在网络上共存并互操作,最终并未导致硬分叉。

不同的共识规则在交易或块的验证中会以明确的和清晰的方式有所不同。这种差别可能以微妙的方式表现,比如共识规则适用于比特币脚本或加密原语(如数字签名)时。最后,共识规则的差别还可能会由于意料之外的方式,比如由于系统限制或实现细节所产生的隐含共识约束。在将Bitcoin Core 0.7升级到0.8之前的意料之中的硬分叉中看到了后者的一个例子,这是由于用于存储块的Berkley DB实现的限制引起的。

从概念上讲,我们可以将硬分叉子看成四个阶段:软分叉,网络分叉,挖矿分叉和区块链分叉。该过程开始于开发人员创建的客户端,这个客户端对共识规则进行了修改。当这种新版本的客户端部署在网络中时,一定百分比的矿工,钱包用户和中间节点可以采用并运行该版本客户端。得到的分叉将取决于新的共识规则是否适用于区块,交易或系统其他方面。如果新的共识规则与交易有关,那么当交易被挖掘成一个块时,根据新规则创建交易的钱包可能会产生出一个网络分叉,这就是一个硬分叉。如果新规则与区块有关,那么当一个块根据新规则被挖掘时,硬分叉进程将开始。

首先,是网络分叉。基于旧的共识规则的节点将拒绝根据新规则创建的任何交易和块。此外,遵循旧的共识规则的节点将暂时禁止和断开发送这些无效交易和块的任何节点。因此,网络将分为两部分:旧节点将只保留连接到旧节点,新节点只能连接到新节点。基于新规则的单个交易或块将通过网络波动,实现分区,导致出现两个网络。

一旦使用新规则的矿工开采了一个块,挖矿和区块链也将分叉。新的矿工将在新区块之上挖掘,而老矿工将根据旧的规则挖掘一个单独的链条。处于分区的网络将使得按照各自共识规则运行的矿工将不会接收彼此的块,因为它们连接到两个单独的网络。

10.13.3分离矿工和难度

随着矿工们被分裂开始开采两条不同的链条,链上的哈希算力也被分裂。两个链之间的挖矿能力可以分成任意比例。新的规则可能只有少数人跟随,或者也可能是绝大多数矿工。

我们假设,例如,80%-20%的分割,大多数挖矿能力使用新的共识规则。我们还假设分叉在改变目标(retarget)后立即出现。这两条链将从改变目标之后各自接受自己的难度。新的共识规则拥有80%的以前可用的挖矿权的承诺。从这个链的角度来看,与上一周期相比,挖矿能力突然下降了20%。区块将会平均每12分钟发现一次,这意味着可以扩大这条链的挖矿能力下降了20%。这个块发行速度将持续下去(除非有任何改变哈希功率的因素出现),直到2016块开采,这将需要大约24,192分钟(每个块需要12分钟)或16.8天。 16.8天后,基于此链中哈希算力的减少,改变目标将再次发生,并将难度调整(减少20%)每10分钟产生一个区块。

少数人认可的那条链,根据旧规则继续挖矿,现在只有20%的哈希算力,将面临更加艰巨的任务。在这条链上,平均每隔50分钟开采一次。这个难度将不会在2016个块之前进行调整,这将需要100,800分钟,或大约10周的时间。假设每个块具有固定容量,这也将导致交易容量减少5倍,因为每小时可用于记录交易的块大幅减少了。

10.13.4有争议的硬叉

这是共识软件开发的黎明。正如开源开发改变了软件的方法和产品,创造了新的方法论,新工具和新社区,共识软件开发也代表了计算机科学的新前沿。在比特币发展路线图的辩论,实验和纠结之中,我们将看到新的开发工具,实践,方法和社区的出现。硬分叉被视为有风险,因为它们迫使少数人被迫选择升级或是必须保留在少数派链条上。将整个系统分为两个竞争系统的风险被许多人认为是不可接受的风险。结果,许多开发人员不愿使用硬分叉机制来实现对共识规则的升级,除非整个网络都能达成一致。

任何没有被所有人支持的硬分叉建议也被认为是“有争议”的,不愿冒险分裂系统。硬分叉的问题在比特币开发社区也是非常有争议的,尤其是与控制区块大小限制的共识规则的任何提议相关。一些开发商反对任何形式的硬叉,认为它太冒险了。另一些人认为硬分叉机制是提升共识规则的重要工具,避免了“技术债务”,并与过去提供了一个干净的了断。

最后,有些开发商看到硬分叉作为一种应该很少使用的机制,应该经过认真的计划,并且只有在近乎一致的共识下才建议使用。我们已经看到出现了新的方法来解决硬分叉的危险。在下一节中,我们将看一下软分叉,以及BIP-34和BIP-9信号和激活共识修改的方法。

10.13.5软分叉

并非所有共识规则的变化都会导致硬分叉。只有前向不兼容的共识规则的变化才会导致分叉。如果共识规则的改变也能够让未修改的客户端仍然按照先前的规则对待交易或者区块,那么就可以在不进行分叉的情况下实现共识修改。这就是软分叉,来区分之前的硬分叉。实际上软分叉不是分叉。软分叉是与共识规则的前向兼容并作些变化,允许未升级的客户端程序继续与新规则同时工作。

软分叉的一个不是很明显的方面就是,软分叉级只能用于增加共识规则约束,而不是扩展它们。为了向前兼容,根据新规则创建的交易和块也必须在旧规则下有效,但是反之亦然。新规则只能增加限制,否则,根据旧规则创建的交易和区块被拒绝时,还是会将触发硬分叉。

软叉可以通过多种方式实现,该术语不定义单一方法,而是一组方法,它们都有一个共同点:它们不要求所有节点升级或强制非升级节点必须脱离共识。

10.13.5.1软分叉重新定义NOP操作码

基于NOP操作码的重新解释,在比特币中实现了一些软分叉。 Bitcoin脚本有10个操作码保留供将来使用,NOP1到NOP10。 根据共识规则,这些操作码在脚本中的存在被解释为无效的运算符,这意味着它们没有任何效果。 在NOP操作码之后继续执行,就好像它不存在一样。因此,软叉可以修改NOP代码的语义给它新的含义。

例如,BIP-65(CHECKLOCKTIMEVERIFY)重新解释了NOP2操作码。 实施BIP-65的客户将NOP2解释为OP_CHECKLOCKTIMEVERIFY,并在其锁定脚本中包含该操作码的UTXO上,强制了绝对锁定的共识规则。 这种变化是一个软分叉,因为在BIP-65下有效的交易在任何没有实现(不了解)BIP-65的客户端上也是有效的。 对于旧的客户端,该脚本包含一个NOP代码,这被忽略。

10.13.5.2其他方式软分叉升级

NOP操作码的重新解释既是计划的,也是共识升级的明显机制。然而,最近,引入了另一种软分叉机制,其不依赖于NOP操作码,用于非常特定类型的共识改变。这在隔离见证掌机[segwit]中有更详细的检查。 Segwit是一个交易结构的体系结构变化,它将解锁脚本(见证)从交易内部移动到外部数据结构(将其隔离)。

Segwit最初被设想为硬分叉升级,因为它修改了一个基本的结构(交易)。在2015年11月,一位从事比特币核心工作的开发人员提出了一种机制,通过这种机制,可以将软件包引入segwit。用于此的机制是在segwit规则下创建的UTXO的锁定脚本的修改,使得未修改的客户端将任何解锁脚本视为可锁定脚本。

因此,可以引入segwit就是软分叉,而不需要每个节点必须从链上升级或拆分网络。有可能还有其他尚未被发现的机制,通过这种机制可以以向前兼容的方式进行升级,都作为软分叉。

10.13.6对软分叉的批评

基于NOP操作码的软分叉是相对无争议的。 NOP操作码被放置在比特币脚本中,明确的目标是允许无中断升级。然而,许多开发人员担心软分叉升级的其他方法会产生不可接受的折衷。

对软分叉更改的常见批评包括:

  • 技术性债务

由于软叉在技术上比硬叉升级更复杂,所以引入了技术性债务,这是指由于过去的设计权衡而增加代码维护的未来成本。代码复杂性又增加了错误和安全漏洞的可能性。

  • 验证放松

未经修改的客户端将交易视为有效,而不评估修改的共识规则。实际上,未经修改的客户端不会使用全面的协商一致的规则来验证,因为它们对新规则无视。这适用于基于NOP的升级,以及其他软分叉升级。

  • 不可逆转升级

因为软分叉产生额外的共识约束的交易,所以它们在实践中成为不可逆转的升级。如果软分叉升级在被激活后被回退,根据新规则创建的任何交易都可能导致旧规则下的资金损失。例如,如果根据旧规则对CLTV交易进行评估,则不存在任何时间锁定约束,并且可以花费在任何时间。因此,评论家认为,由于错误而不得不被回退的失败的软分叉几乎肯定会导致资金的流失。