交易延展性是什么:签名没坏,交易编号为何变了 图 1
交易延展性是什么:签名没坏,交易编号为何变了 · 图 1

一个反直觉的事实:交易可以被改头换面

比特币交易一旦签名完成,任何人都不可能伪造签名或篡改被签名承诺的金额与收款地址——这是共识规则保证的。但协议的早期形态里存在一个别扭的角落:在不破坏任何签名的有效性的前提下,第三方可以改动交易的字节内容,而改动后的交易会哈希出一个全新的编号。签名是真的,钱也没多没少,只是交易身份证变了。这就是交易延展性。

可改的空间藏在哪里

交易签名并不对交易的每一个字节做承诺,而是对指定范围的字段做承诺。旧式签名脚本里存在两处天然的改造空间。其一是 ECDSA 签名编码的宽松性:同一组签名数学值可以写成两种不同的字节序列,节点验证时都承认,但两种编码哈希出不同的交易。其二是脚本结构本身:解锁脚本里塞进额外的、不影响执行结果的操作数,验证照样通过。攻击者不需要任何私钥,只要在交易广播途中做一次字节层面的化妆,原交易和改过的双胞胎就同时在全网扩散,最终只有一条能被打包,另一条的编号从此查无此人。

2014 年的那场停提风波

交易延展性从纸面问题变成公共事件是在 2014 年 2 月。交易所 Mt. Gox 于 2 月 7 日宣布暂停全部比特币提币,随后在 2 月 10 日的公告中把原因归为交易延展性:用户可以在提现交易上链前篡改其编号,再向平台主张转账未成功,诱导平台重复打款。这份公告的原文至今仍可在比特币论坛的存档帖里读到。需要划清界限的是:公告陈述的是 Mt. Gox 自己给出的解释,社区开发者当时对这一解释是否充分就存在公开分歧,且该机构后来的破产清算显示其财务状况远比公告描述的复杂。把延展性说成该平台全部问题的根源,与把延展性说成纯粹借口,都是过度断言。可以确认的技术事实是:延展性本身真实存在,且当时的钱包与交易所普遍用原始编号追踪提现,恰好踩在这个坑上。

协议如何把它关进笼子

对抗延展性走了两步棋。第一步是行为规范的收紧:限制签名必须采用唯一编码形式、非标准脚本形态不予中继,把已知的可改造空间逐个焊死;这类收紧属于节点政策,随各版本逐步部署。第二步是结构性的解法——隔离见证。它把见证数据从交易主体中分离出去,交易编号只对有主体部分计算,而可延展的字节恰好集中在见证部分,于是对同一笔逻辑交易,无论见证如何变化,主体编号恒定不变。这个性质不是附带福利,而是 2017 年 8 月在区块高度 481824 激活的这次升级的设计目标之一,因为闪电网络等协议必须在链下引用交易编号来构建依赖链,任何编号漂移都会让整条状态链崩断。此后又有一版不含见证数据的交易哈希被引入协议文档,作为更彻底的追踪编号,让服务方即使面对未隔离见证的旧式交易也能识别双胞胎。

收款方的现实防御清单

对普通用户,延展性带来的实际风险集中在”看零确认就放款”的场景。防御方式按稳妥程度递进:最基础的一条是不依赖 0 确认做不可逆决定,等交易进入区块后再确认,进块的交易不再可改造;其次是不以广播时的交易编号作为唯一追踪键,而是按”消费的输入”来认交易——无论编号怎么漂,被花的钱是同一笔;再次是使用支持隔离见证地址与 WTXID 追踪的钱包与服务。反过来,任何”帮你加速""提交重发”却要求你在旧编号未确认时提前放货的外部请求,都应提高警觉,因为那正是延展性滥用最常见的剧本。

风险提示:本文内容仅为技术说明,不构成任何投资建议;涉及资产操作请自行核验当前版本行为与官方文档。