协议演进 / BIP/比特币改进提案 / BIP-339

BIP-339 基于 WTXID 的交易中继

交易公告与索取改用包含见证数据的 wtxid 而非 txid,堵住见证可锻性带来的中继干扰与重复下载。本 BIP 目前处于已部署状态。

一、档案卡

档案卡
编号BIP-339
标题WTXID-based transaction relay
作者Suhas Daftuar <[email protected]>
指定日期2020-02-03
层级Peer Services(对等服务)
类型Specification(规范类)
状态Deployed(已部署)
阅读版https://bips.dev/339
官方原文https://github.com/bitcoin/bips/blob/master/bip-0339.mediawiki

二、放在哪一族

对等网络(P2P)协议族,处在交易中继(transaction relay)这条链路上:节点先用 inv 公告“我有这笔交易”,对方再用 getdata 索取。

它建立在隔离见证(SegWit)之上:wtxid 这个概念由 BIP-141 定义——对包含见证数据的完整交易再做一次哈希;带见证的序列化方式见 BIP-144。BIP-339 做的事,是把中继环节引用交易的标识从 txid 换成 wtxid。

同族邻居:BIP-338(同作者,disabletx 消息,管哪些连接不走交易中继);更早的中继优化还有 BIP-152 紧凑区块中继。

三、它要解决什么

历史上,inv 公告交易时用的都是 txid——不包含见证数据的哈希。SegWit 被网络采用之后(BIP-141、BIP-143、BIP-144),这一惯例仍未改变,而问题恰恰出在见证上:

一笔交易的见证可以被改动(malleated)而不改变其 txid。于是节点收到一份见证被改过、因而拒绝接受的交易后,当其他对等节点再公告同一个 txid 时,它通常还是会再下载一遍——因为它没法仅凭 txid 区分“这次是完好版本还是又一份被改过的版本”。

反过来处理也不行:如果节点拒绝一次后就拉黑该 txid、再不下载,第三方就能抢先把一份见证被改坏的无效版本公告给各节点,让大家误以为这个 txid 已经“见过且无效”,从而把正版交易的中继堵死。

症结在于公告标识没有承诺见证内容。改用 wtxid——它把见证也算进哈希——两种版本天然是两个不同的标识,上述两难随之消除。这正是原文 Motivation 的完整逻辑。

四、规则本身

4.1 协商消息 wtxidrelay

只有双方都发过这条消息的连接,才启用基于 wtxid 的中继。

4.2 新的 inv 类型 MSG_WTX

4.3 启用后的行为

4.4 向后兼容与实现

基于 wtxid 的中继只在双方都支持的对等节点之间启用,旧客户端在本改动后仍完全兼容、可互操作。原文给出的实现是 Bitcoin Core 的 PR #18044。

五、谁必须动

普通持币人:无感。交易本身、地址、签名方式都不变。

钱包开发者:无需改动。钱包构造与广播的交易与从前完全一样,变的只是节点之间公告时用的标识。

全节点开发者与节点运营者:实现 wtxidrelay 协商与 MSG_WTX 的公告/索取逻辑,升级后与同样升级的对等节点自动启用;对旧对等节点自动回退 txid 方式。

共识层:不涉及。txid 与 wtxid 的定义早在 BIP-141 就已定下,本 BIP 一个字也没改共识规则,只改中继层引用交易的方式。

六、现在算不算数,以及一个常见误读

状态为 Deployed(已部署)。它是一个已经落地的对等协议约定:支持的节点两两协商启用,不支持的老节点继续按 txid 中继,两套方式在同一网络上长期共存——这正是原文向后兼容一节的设计。

常见误读:

“BIP-339 之后,交易的 ID 换成 wtxid 了。”

不对。交易仍然同时有 txid 与 wtxid 两个哈希,txid 的定义和用途没有变——例如一个输出被哪笔交易花费,靠的仍是 txid 定位。本 BIP 只规定了一件事:在支持它的两个节点之间,公告与索取交易时改报 wtxid。把“中继时怎么称呼这笔交易”和“交易本身的标识体系”混为一谈,就会误以为全网改了 ID。

七、延伸

本页内容整理自 bitcoin/bips 仓库与 bips.dev,事实已与仓库核对;解读仅供学习参考。