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

BIP-35 mempool 消息

新增一个空的 mempool 消息:对方收到后,用 inv 把自己内存池里全部交易的哈希报回来,让节点能直接索取别人的未确认交易集合。本 BIP 目前处于已部署状态。

一、档案卡

档案卡
编号BIP-35
标题mempool message
作者Jeff Garzik <[email protected]>
指定日期2012-08-16
层级Peer Services(对等服务)
类型Specification(规范类)
状态Deployed(已部署)
阅读版https://bips.dev/35
官方原文https://github.com/bitcoin/bips/blob/master/bip-0035.mediawiki

二、放在哪一族

BIP-35 属于对等服务层的交易中继族。它打交道的对象是节点的交易内存池(mempool):每个节点暂存已收到、已验证但尚未进区块的交易。

同族的近邻包括 BIP-31(pong 消息)、BIP-37(连接布隆过滤)、BIP-61(Reject 消息)与 BIP-133(feefilter 消息)。它们的共同点是只改节点之间的通信方式,不改共识规则。

在 BIP-35 之前,一个节点只能被动等别人把新交易广播给自己,没有办法主动问一句:“你池子里现在都有哪些交易?”

三、它要解决什么

原文列了三个希望直接访问对方内存池的场景:

障碍在于协议里没有这样的查询入口:inv 平时只通告对方新收到的交易,getdata 也只被实现为索取“最近中继过”的交易哈希,问不到对方池子的全量存量。

四、规则本身

4.1 mempool 消息本身是空的

mempool 消息定义为一条空消息,命令名(pchCommand)就是 mempool,不带任何载荷。

4.2 收到后的回应

节点收到 mempool 消息后,应回一个 inv 消息,其中包含本节点交易内存池里全部交易的 MSG_TX 哈希(如果池子非空)。

请求方按通常流程处理 inv:看中哪些哈希,再用 getdata 去取交易本体。

4.3 配套扩展 getdata

参考实现原本会忽略“不在最近中继集合里”的交易哈希请求。为了让上面的流程真正走通,支持 BIP-35 的实现必须扩展 getdata 的行为:允许按哈希到内存池里查询交易,而不只是查最近广播过的那些。

4.4 如何判断对方支持

功能发现靠 version 消息的两个条件同时成立:

原文还提醒:已有实现会丢弃向量长度超过 50000 的 inv 消息,因此内存池很大时,一次全量通告存在这个上限约束。

4.5 向后兼容

旧客户端在此改动之后仍然 100% 兼容、可以互通:不支持的节点不发也不会处理 mempool 消息即可。

五、谁必须动

普通持币人:无直接变化。不改变交易格式与确认规则。

钱包与 SPV 客户端:可以向全节点主动索取内存池清单,补上刚发生、还没确认的相关交易,不必只靠被动广播。

全节点:若要提供此功能,需要实现 mempool 消息的回应,并扩展 getdata 到可查内存池;同时要意识到这等于把自家内存池内容对外公开,节点软件可以按自身策略决定是否响应。

矿工:重启后可借此快速补回未确认交易,减少漏掉手续费收入的机会。

共识层:完全不动。内存池是各节点的本地策略,池子里有什么从来不是共识规则。

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

状态为 Deployed。mempool 消息已是对等协议的一部分,节点软件沿用至今。它提供的是“查询对方此刻池子内容”的能力,具体是否响应、以什么频率响应,仍由各节点实现自行决定。

常见误读:

“出现在某个节点的 mempool 里,就等于交易已经确认、不会变了。”

不对。内存池只是未确认交易的暂存区:交易可以因手续费竞争、冲突或节点重启而被替换或逐出。只有交易被写进区块并累积足够确认,才算落定。BIP-35 让这份暂存清单可查询,并没有给清单里的交易加上任何保证。

七、延伸

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