720 / 736OVFL

Value Overflow Incident

区块 74 638 的数值溢出事件

Value Overflow Incident 是 2010年8月15日发生的严重共识事故:区块 74 638 中的一笔交易利用 64 位求和溢出,使两个巨额输出通过验证,并向当时正在挖掘的分支额外加入 2^64 satoshi。

错误出在验证规则的实现中,而不是密码学或发行计划。每个输出都是正数,但相加后溢出成了负数。输入金额与这个负数总额之间的差,随后被当成了手续费。版本 0.3.10 为每个输出和累计总额增加了上限;节点重组到修复后的分支后,错误区块便被排除在活跃历史之外。

2010年8月15日,开发者 Jeff Garzik 报告了异常区块 74 638。交易 1d5e512a9723cbef373b970eb52f1e9598ad67e7408077a82fdac194b65333c9 花费了一个价值 0.50 BTC 的输入,却产生了两个巨额输出。当时的 printblock 记录显示,每个输出为 92 233 720 368.54275808 BTC。这笔漏洞利用交易的作者一直未被可靠确认:公开记录能够证明交易数据,却不能证明创建者的身份或动机。 [1]

当时,Bitcoin 以聪为单位,用64位有符号整数表示金额。每个输出的整数值都是正数,略低于 int64 上限;记录中的十六进制数 0x7ffffffffff85ee0 也证实了这一数值。但两者之和 18 446 744 073 708 551 616 聪超出了取值范围,溢出后变成了 −1 000 000 聪。旧版验证程序将这个负数与输入金额比较,竟然接受了它。这是算术错误,而非数字签名被破解。讨论中最初的 JSON 记录在小数末位上有所不同;这里的精确计算采用 printblock 与十六进制记录共同确认的整数值。 [1]

输出总额变成 −0.01 BTC,而输入为 0.50 BTC,两者相减便产生了 0.51 BTC 的虚假手续费。因此,矿工在 coinbase 中领取了 50.51 BTC,而不是50 BTC的基础奖励。扣除已花费的输入,并计入 coinbase 超额领取的部分后,这两个巨额输出使错误分支的供应量恰好增加了 18 446 744 073 709 551 616 聪,即 2^64 聪,也就是 184 467 440 737.09551616 BTC。因此,这个数字并不只是两个输出金额的简单相加。 [2]

社区在时间压力下公开响应。Lfm 称漏洞严重,Gavin Andresen 提议快速检查每个输出是否超过 2100万 BTC,Satoshi Nakamoto 则发布更完整方案:拒绝负数或过高输出,并在每次相加后拒绝过高累计总额。Satoshi 还请矿工暂时停止,以便新的有效分支更快地追上并替换错误分支。 [2]

Satoshi 于 2010年8月15日论坛时间 23:48 宣布版本 0.3.10,距 Garzik 报告约五小时四十分钟。更新节点把漏洞交易与区块 74 638 视为无效,并从最后一个共同有效区块继续构建。同期公告后来称正确分支已超过错误分支,升级客户端可自动重组,无须手动删除 blockchain 文件。 [3]

并没有人在中央数据库中修改旧区块。当时存在两条竞争历史:旧节点按原规则接受该区块,修复节点拒绝它,只接受有效祖先之上的工作。修复分支累积更多 Proof of Work 后,网络跟随该分支,通胀区块退出活跃历史;起决定作用的是用户与矿工安装新规则及后续工作,而非某个管理员的命令。 [3]

当年加入的保护今天仍可在 Bitcoin Core 中看到。CheckTransaction 拒绝负输出、超过 MAX_MONEY 的输出,以及超出 MoneyRange 的累计总额;每次相加后检查,可防止危险总和先回绕再比较。源码注释明确引用 CVE-2010-5139,另一个重复输入检查则对应不同的 CVE-2018-17144 事件。 [4]

该事件说明,2100万枚的上限不是仅靠哈希保护的魔法常数:它由精确验证规则及其正确实现强制执行。审计必须覆盖单值范围、安全加法、coinbase 与手续费、检查顺序、边界测试向量,以及独立实现之间的一致性。历史也同时展示了早期社区快速修复的能力,以及当时对少数开发者、矿工和人工协调的高度依赖。 [5]

要获得更完整的理解,请将本词条与以下词条结合阅读: Bitcoin Core, 共识规则, 交易, UTXO, Reorg, Soft Fork.

01有效的 Bitcoin 中曾存在 1840亿 BTC 吗?

它们曾因漏洞区块而短暂存在于当时挖掘的错误分支。修复节点拒绝该分支,有效分支通过重组取代它,因此巨额输出不属于今天的活跃 blockchain 或 UTXO 集。不过历史事件本身无法否认:区块和同期响应都有记录。

02该事件是否永久破坏 2100万枚的上限?

没有。今天接受的历史中,修复后的共识规则拒绝错误区块,其输出在重组中消失。事件确实说明,上限依赖正确验证和参与者实际运行的软件;文档中的一句声明本身无法执行供应规则。

DOC · 001BitcoinTalk — Strange block 74638一手来源 DOC · 002BitcoinTalk — overflow bug SERIOUS一手来源 DOC · 003BitcoinTalk — Version 0.3.10, block 74638 overflow patch一手来源 DOC · 004Bitcoin Core — current CheckTransaction overflow checks文档 DOC · 005CVE — CVE-2010-5139文档
修订日期: 来源优先 · 非投资建议