软分叉的艺术 – 政策规则保护
软分叉是修正和引入新的比特币共识规则的主要方式。接下来的一系列文章将介绍软分叉是如何被实现的。
共识规则和软分叉
共识规则决定着每个交易或每个区块的有效性。比特币网络上的每个用户和矿工都遵守着同一套共识规则,代表着他们都愿意接受和同意一个账本。
当大多数用户和/或矿工决定采用更严格的共识规则时,软分叉就可能出现,这使一些以前有效的交易/区块将变为无效,而不是相反。如果大多数人执行新的规则的话,其他任何违规分叉(统计上)都不会在工作量证明方面赶上新的更严格的共识分叉。遵守旧规则的少数人将始终遵循更长,更严格的分叉,使得网络上的每个人都会最终接受和同意一个账本。
政策规则和共识规则
虽然共识规则是确定交易有效性的唯一标准,但是传播节点或挖矿节点可能偏好某种交易。例如:
作为垃圾邮件控制机制,费用非常低的或 “微产量”(输出值很低)的交易将被拒绝。
一些矿工拒绝将 “链上赌场” 交易包括在内,这些交易被认为是垃圾邮件。
未知版本的交易被拒绝(目前只有版本 1 和 2 是 “已知的” )。
非常规的脚本(即不是 P2PKH , P2SH , v0 segwit 或其他一些情况)和未知的 NOPx 代码(目前仅知道 OP_NOP2 和 OP_NOP3 )的交易将被拒绝。
更换费用( Replace-by-fee )和母费子付( child-pay-for-parent )也属于政策规定,因为他们确定了哪些是矿工首选的交易。
根据定义,政策规则必须至少与共识规则一样严格。很明显,矿工们不希望在一个区块中包含无效交易(这会导致采矿奖励的丧失),或者将其传播(这将被同行排斥)。
虽然政策规定可能比共识规定更严格,但要注意,政策规定并不决定交易的有效性。一旦交易被包含在有效的区块中,即使它违反了一些政策规则,所有的网络节点也将会接受并承认它。
同样要注意的是政策规则是区域性的,而共识性规则是普遍性的。这意味着不同的网络节点可能有不同的策略规则。只要运行相同的共识规则,他们仍然会一致同意区块链账本。
违反政策规则的交易有时被称为“非标准交易”,我们需要将其与 “无效交易” 区分开。
政策规则和软分叉
理想情况下,所有的矿工都应该在软分叉激活之前升级到新的更严格的规则版本。在经济利益上,他们有强烈的动力去做这件事,因为挖掘一个无效区块(就新规则而言)会形成重大的财务成本。但是,像比特币这样的去中心化系统,矿工的行为是不能保证的。
虽然矿工们理论上应该关注所有规则变化的提案并及时采取行动,但是一旦矿工挖掘无效区块便会导致市场中断和普通用户的经济损失。因此,任何计划良好的软分叉都应该考虑到这一点,并将风险降至最低。
诀窍是,软分叉的内容应该限制在现有并广泛采用的政策规定所涵盖的范围内。拥有政策规定,但不了解新的共识规则的矿工,将会自动拒绝这些交易,因此,他们绝不会将新交易规则中的交易包括在内。这在比特币历史上的一些案例中有详细阐述。
在上述图像中,工人在一条无法使用的道路上摆放 “道路封闭” 的标示牌,该障碍物在工人放置标示牌之前已经存在。新的交通标示牌只能防止一些 “非标准” 的行为,因此造成的影响很有限。
案例分析描述
BIP65:检查锁定时间验证OP_NOP1 到 OP_NOP10 在比特币脚本语言来说原本没有意义。虽然它们被算为一个操作(脚本中有 201 个操作数量限制),但实际上它们在交易验证时被忽略。然而,自 0.10 版本开始,比特币核心中就包含了一个策略规则,在默认情况下拒绝 OP_NOPx 。 BIP65 是比特币核心 0.12 中引入的软分叉,其将 OP_NOP2 重新定义为 OP_CHECKLOCKTIMEVERIFY( OP_CLTV ) 。 OP_CLTV 检查顶层堆栈值是否大于交易的 nLockTime 字段(以及其他的条件)。如果任何条件匹配,交易将被视为无效。否则, OP_CLTV 将像 OP_NOP2 一样被忽略。
新的节点在软分叉激活后将强制执行的新的共识规则。即使在激活激活之前,原来的 OP_NOP2 策略规则已被 OP_CLTV 规则取代。(这是没问题的,因为 OP_CLTV 规则比原来的 OP_NOP2 共识规则更严格)
旧的采矿节点不会执行 nLockTime 检查。但是,只要运行 0.10 或更高版本,默认的 OP_NOP2 策略规则将阻止它们包含任何具有 OP_CLTV 的交易,无论该交易是有效或无效的。因此,对于新的 OP_CLTV 共识规则, 0.10 或以上的旧采矿节点不会主动产出无效区块。
BIP68:使用序列号的相对锁定时间nSequence 是比特币交易中的一个领域,基本上没有被使用。 BIP68 的概念是使用 nSequence 字段来实现相对锁定时间,这是支付渠道和闪电网络等高级交易的一个非常重要的组成部分。然而,自比特币的第一个版本以来, nSequence 字段就一直被忽略,矿工对任何 nSequence 值的交易都采取接受态度。没有关于 nSequence 值的政策规则,因此不能像 OP_CLTV 那样简单地完成一个安全的软分叉。
诀窍是使用交易版本字段( nVersion )。从版本 0.7 开始,非版本 -1 交易将被政策规则拒绝。为了充分利用这一点, BIP68 要求仅在交易版本为 2 或更高(准确来说低于 0 )的情况下强制执行 nSequence 的新规则。因此,旧的采矿节点不会产出任何违反 BIP68 的区块,因为在默认情况下它们将不包括任何非版本 -1 交易。
攻击者不能通过简单地改变交易版本来“关闭” BIP68 ,因为版本有签名认证。这也是交易版本与共识规则相关联的唯一实例。
BIP141:隔离见证隔离见证( segwit )是通过重新定义特定的脚本模式来修复交易可规模化的一种软分叉。 BIP141 的模式是一个以单个 OP_x(x = 0到16)开始的输出脚本(或P2SH redeemscript ),接着是 2 到 40 个字节之间的规范数据推送。但是,这不是最初提出的方案。在第一稿中,见证程序模式是在 2 到 41 个字节之间进行单次推送。
自 v0.6 版本以来已经实施该政策,用来拒绝非常规的脚本(即不是 P2PKH , P2SH 和其他几种类型)的交易。在这方面,第一份见证计划模式草案确实是不规范的。
问题是用 P2SH 编程的见证程序。在 v0.10 之前,政策规则也会拒绝任非常规的 P2SH 脚本。而这个规则在 v0.10 中大大放松了,原来的见证程序设计没有被覆盖。
几个备选方案也在当时的考虑范围:
[*]新的交易 nVersion (如 BIP68 )不起作用。如果新的共识规则是“只有当 nVersion 大于 2 时才执行 segwit 规则”,则攻击者可以通过改变 nVersion 来窃取存储在 segwit 输出中的所有加密货币(因为 nVersion 仅由 segwit 签名认证,而当 nVersion 是 2 以下时是不被检查的)。
[*]OP_NOPx 可以被用来标识见证程序。但是,这会使所有见证程序多出 1 个字节,并占用有限的 OP_NOPx 空间。
最终版本使用了 BIP62 的所谓 “clean stack” 政策规则。虽然 BIP62 现在被撤回了,但其规则仍作为政策被执行。 “Clean stack” 要求脚本评估必须以唯一一个堆栈项目结束。然而,最后的见证程序设计留下了两个堆栈。这基本上是没问题的,但却违反了 “clean stack” 政策。
失败案例:BIP16和支付脚本散列
(P2SH)
BIP16 是第一个计划实行比特币软分叉的。当 55% 的哈希算力表示准备就绪时(当前使用率约 80% 到 95% ),它被激活了。在引入 P2SH 之前,没有政策规定来检查支出输出的形式。因此,相当数量的矿工在软分叉激活数月之后一直在产出无效区块,偶尔会产出长区块链。
失败案例:莱特币的隔离见证比特币隔离见证实施后不久,莱特币就开始整合 segwit 的代码。然而,尽管 segwit 在 Bitcoin Core 0.13.1 中发布,但当时的最后一个莱特币版本是 0.10.4 ,其中没有包含 “clean stack” 规则。 莱特币的开发员试图通过给 segwit 增加一个额外的共识规则来解决这个问题,要求区块版本必须至少为 0x20000000 ,希望能强迫矿工升级。事实证明,所有的矿工在激活之前都升级了(最后一个大型矿工在激活几个小时前升级),而并没有造成分叉因为上一个版本中没有 CLEANSTACK 。
如果大型采矿池在最后一分钟没有升级,那么额外的区块版本规则就只能提供很少的保护。这将在下一篇文章中进一步讨论。
政策保护不是万能的
读至此时,读者可能会发现,上述的政策保护手段只会阻止未升级的矿工在软分叉激活后主动产出第一个无效块。然而,如果这个无效块被创造出来,那么未经升级的矿工会接受它,同时如果得到更多工作证明的支持,那么这个区块链就会越来越长。所以这只是一种减少而不是完全消除在软分叉激活中发生意外区块链分叉的方法。如果在大量矿工正在通过不同的完整节点运行不同的政策规则的情况下,那么这个政策保护也是存在问题的。
页:
[1]