这并非围绕新规则的争议,而是验证对数据库实现存在隐藏依赖:较新的 LevelDB 能处理输入数量异常多的区块,旧版本却耗尽了 Berkeley DB 的默认锁数量;矿工随后协调回到兼容分支,之后的 0.8.1 版本为受控迁移做好准备。
2013 年三月 11 日,一个运行 Bitcoin 0.8 的节点挖出了区块 225 430。新版本接受该区块,部分 0.7.2 及更早版本节点却拒绝它;于是同一父区块之后同时生长出包含该区块的分支和不包含它的分支。差异不在 hash 或 proof of work 本身,而在本地软件是否首先认定该区块有效。 [2]
触发条件不只是区块的字节大小。该区块包含此前未见的交易输入数量,旧节点在写入时耗尽了 Berkeley DB 的默认锁数量。所需锁数还取决于具体节点数据库页面的排列,因此,一个较小但本应有效的区块可能失败,而此前达到最大尺寸的测试区块却能通过。 [1]
Bitcoin 0.8 将区块和交易索引从 Berkeley DB 迁移到没有相同锁上限的 LevelDB。最初约 60 % 的算力在 0.8 分支上继续构建,但旧节点因拒绝起始区块而不承认该分支的工作量。最重链规则只会在节点已经验证为有效的历史中选择,因此无法单独解决这种分歧。 [1]
Pieter Wuille 发布紧急警报,并建议商家暂停处理付款。开发者和运营者讨论后,由 Michael Marsee(网名 Eleuthria)管理的 BTCGuild 与 Marek Palatinus 的 Slush Pool 都退回 Bitcoin 0.7。目标不是永久宣布技术上较新的分支错误,而是迅速把工作量集中到两个广泛部署版本都能验证的历史上。 [3]
当兼容分支在累计工作量上领先后,0.8 节点重组到该分支,仅在原 0.8 分支挖出的区块变成 stale block。BIP 50 记录了分裂期间至少一次金额较大的 double spend;事后报告称这是实验,并非蓄意盗窃。该事件仍说明了为什么交易所和商家在链尖不确定时会暂停入金并等待更多确认。 [1]
Bitcoin Core 0.8.1 于 2013 年三月 18 日发布。它加入了从三月 21 日至五月 15 日执行的临时区块接受规则,防止接受旧节点无法处理的区块,并在区块 225 430 加入内置 checkpoint。事后报告还列出 10 000 个锁的估算上限、500 000 字节的挖矿上限,以及把 Berkeley DB 锁上限设为 537 000 的 backport。 [4]
临时兼容并非最终状态。旧节点运营者须在五月 15 日前升级到 0.8.1、更新的 backport,或明确提高锁上限;矿工不得在协调日期前提高该上限,以免再次制造被网络其余部分拒绝的区块。2013 年八月 16 日,网络接受区块 252 451,并永久把未修补节点留在另一边。 [5]
这次事件说明,共识不只是区块格式的文字描述,还包括验证代码、程序库、数据库事务、错误路径和边界测试的精确行为。后续措施因此包括在 testnet 上进行交易压力生成、改进服务警报、监视较长侧链,并更谨慎地协调变更;快速恢复也暴露了当时网络对少数可联系开发者和大型矿池的依赖。 [1]
要获得更完整的理解,请将本词条与以下词条结合阅读: Bitcoin Core, 共识规则, Hard Fork, Reorg, Full Node, Mining Pool. 反向关联还来自: Schelling Point.