空消息换一张清单
比特币的 P2P 协议里大多数消息都带着数据,唯独 BIP-35 定义的 mempool 消息是一个空壳:命令字段写着 mempool,正文什么都没有。对端收到后,把自家内存池里所有交易的哈希打包成一条 inv 消息回给你——就是节点平时转发交易时用的同一种清单格式。拿到清单后,你想要哪几笔,再用常规的 getdata 逐笔取即可。协议同时给这条能力加了发现条件:对端协议版本不低于 60002 且服务字段带网络全节点位,才值得发这条消息。整个提案 2012 年 8 月分配编号,状态 Deployed,改动小到大包实现只是一个拉取请求。
2012 年的三个动机
提案把用途列得很老实。第一条是 SPV 轻客户端:手机钱包不跑全节点,想即时确认”这笔转账广播了没有”,最直接的办法是问邻居的内存池。第二条是矿工:节点重启后内存池清空,错过了一池子的费用,发一句 mempool 就能把漏掉的交易捞回来。第三条是远程诊断:运维者隔着一台机器看另一台机器的池子状态。
三条动机里,第一条藏着那个年代的信任结构——零确认交易被当作可接受的到账信号,商户脚本等着 inv 清单里出现目标哈希就算数。
为什么今天几乎听不到它
零确认的退场不是因为 BIP-35 失效,而是它承载的假设破产了。2010 年代中期之后,双花零确认的手法不断被演示:芬尼攻击把预挖的币在广播前花掉、费率赌博让交易在池子里滞留、再到 replace-by-fee 让”已广播”三个字有了新的法律含义——一笔在内存池里的交易随时可能被替换掉。任何依赖”此刻在池子里”的收款逻辑,都建立在可被邻居单方改写的状态上。
更耐人寻味的是实现的走向:处理这条消息的代码至今还在比特币核心的网络层里,但加了闸门——只有当节点自己广播布隆过滤器服务位、或者对方持有专门的内存池权限时,请求才会被应答;否则一条越界的 mempool 请求甚至可能让请求方被断开。从”任何邻居都可查询”到”默认关闭、白名单应答”,这条 2012 年的消息用了十年时间被改写成特权接口。
对矿工和运维,这条消息也显得笨重:一池子哈希动辄几万条,而现代中继网络本来就靠 inv 逐步公告交易,重启后的补课更多由持久化队列(节点重启时把内存池存盘再加载)解决,BIP-35 的用途被更细的机制分走了。
一条设计教训
BIP-35 最值得记住的是它暴露的信息面:让任何邻居一句话看全你的内存池,等于把”哪些交易已经网络可见”变成公共品。后来的协议演化明显收敛了这类默认公开——交易选择先公告后索要、只中继费率达到门槛的交易、用 feefilter 之类的消息提前商量门槛。池子从”可查询的公共服务”变成了”带闸门的工作队列”。读老提案时你会发现不少想法没有错,只是它们假设的对手变了。
动手看一眼
跑着比特币核心的机器上,这条能力其实没有直接暴露成一条 RPC——它是节点对节点的。普通用户能观察到的对应物是 getrawmempool 之类的本机接口,以及公共内存池浏览器:它们背后是服务器替你持续监听网络,而不是每个用户直接向邻居广播 mempool 消息。这个区别提醒你:协议层的能力、节点软件的暴露面、公共服务的形态,是三层不同的东西,很多”比特币能做 X”的说法混淆的正是这三层。本文只讨论协议机制,不构成任何投资建议。
发表评论
还没有评论,来说两句吧。
评论区为展示样式,提交不会被处理。