比特币节点协议升级过去有一条笨重的隐形流水线:想加一条新消息,先升协议版本号,再祈祷各家客户端按同一节奏把数字抬上去。BIP-434 想把这条流水线拆掉。它由 Anthony Towns 起草,最早的想法在 2020 年 8 月的 bitcoin-dev 邮件列表就已提出,2026 年 1 月 14 日正式立项,2025 年 12 月的新一轮讨论后定稿,状态已是 Complete——它是「规范完成」类别里最新一批的样板之一。
先讲它替代的现状。历史上 P2P 功能的启用方式有三种:抬版本号后直接发新消息(BIP-130 的 sendheaders 要求 70012、BIP-133 的 feefilter 要求 70013、BIP-152 的紧凑区块要求 70014);在握手期 version 与 verack 之间插一条一次性探测消息(BIP-155 的 sendaddrv2、BIP-339 的 wtxidrelay);或者挂服务位。三种套路各有前例,但每来一个新提案就要重新发明一次「邻居到底支不支持」的问答,而且都要回答同一个尴尬问题:不认识这条消息的节点会不会直接掰断连接?比特币从 0.1 版起就把「忽略未知消息」当作协议可扩展性的显式理由,可历史上 Core 曾在相当长的窗口期里不欢迎 verack 前的未知消息,btcd 早期也直接禁止——如果客户端坚持掰断,新消息一上线就可能导致网络分裂。
BIP-434 的解法是一条通用的 feature 消息。载荷只有两个字段:featureid,一个 4 到 80 字节、建议只含可打印 ASCII 的字符串,已分配 BIP 编号的功能应当直接拿编号当身份(例如 BIP434,多版本可写 BIP434v2,分部可写 BIP434.3);featuredata,最多 512 字节的按功能自定义配置,没有内容就传空数组。规则全部压在时序上:实现节点必须宣告不低于 70017 的协议版本;只向同样宣告 70017 以上的邻居发送 feature;消息必须出现在 version 之后、verack 之前;verack 发出后不得再发。基于该 BIP 定义新功能时有条铁律:未经对方 feature 消息确认支持之前,该功能引入的新消息不得在 verack 后发出——把「先亮牌再打牌」写成了硬性纪律。
这套机制真正解放的是什么?是版本号的协调成本。以前每次功能上线,各家实现要在「抬到哪个数字」上互相等待,数字本身还不携带语义;现在功能身份直接绑 BIP 编号,握手期各发一条自报家门,实现与否互不阻塞。对试验性功能,规范也留了口子:没有 BIP 编号的必须自选一个全局唯一标识,避免两个实验撞名。它同时给了老代码一条明确指令——对 version 与 verack 之间收到的未知消息应当忽略而不是掰断,等于把「可扩展性靠宽容」这件事从默契升级成条文。
拿一个具体场景收个尾:假设某实验提案想引入新的地址族,需要邻居在收地址前先确认对方解析器认账。旧流程是先谈「所有实现都把版本号抬到 700xx」,协调记录里全是各家发版节奏的拉扯;BIP-434 之下,它只需定义 featureid 为「BIP新编号」的 feature 消息,握手期各发一条,收到即启用、没收到当不支持,抬不抬版本号与各家的发版排期解耦。规范连边带纪律都想到了:feature 消息只在握手期出现、之后不得重发,意味着协商结果是一次性的连接级决定,节点不需要维护跨连接的状态表,实现面很小。反过来说,它的功能天花板也在这里——握手期一次性广播、无重协商,适合「支持与否」这类布尔事实,复杂的能力矩阵仍要靠服务位或消息层自己设计。
快速问答
问:feature 消息会取代服务位吗?
答:不会。服务位是长期能力的粗粒度公告(比如能不能提供历史区块),feature 面向连接级、握手期的功能协商,两者粒度不同、可并存。
问:Complete 状态意味着已经在主网运行了吗? 答:不。Complete 只说明规范定稿,主网行为取决于各客户端的实际实现与默认开关,判断启用状态请查当期客户端文档。
风险提示:P2P 层消息规则随客户端版本演进,本文规则以 BIP-434 定稿文本为准,不构成对任何软件当前行为的承诺。

发表评论
还没有评论,来说两句吧。
评论区为展示样式,提交不会被处理。