不动 64 位服务位图也能报名新功能:BIP-36 自定义服务的命名与版本字段 图 1
不动 64 位服务位图也能报名新功能:BIP-36 自定义服务的命名与版本字段 · 图 1

比特币 P2P 握手里的 services 字段只有 64 位,每一位都是一个 NODE_* 常数——NODE_NETWORK、NODE_BLOOM、NODE_NETWORK_LIMITED 等都占着一个。想给协议加实验性功能的人越来越多,坑位却很有限,BIP-36《自定义服务》就是为解决这个拥挤而写的:与其每试一个新东西就要申请一个位,不如让节点在握手时附上一张”名片列表”,用字符串名字自报家门。这份提案由 Stefan Thomas 起草、2012 年 8 月立项,最终状态 Closed,没有被主流客户端实现,但它提出的问题——协议扩展位是稀缺资源——在今天仍以别的形式存在。

它的设计动机部分列出了想被孵化的实验方向:分布式哈希表、分布式矿池、轻量客户端支持协议、定向消息路由、自定义传输层(比如 UDP 或 WebSocket)。这些实验如果都直接改写主协议,要么互相冲突,要么逼着所有人升级。BIP-36 给的框架是:在 version 命令的 extra_height 字段之后追加两个字段——一个 var_int 型 service_count 说明后面有几项服务,再跟一个 service_list 列表。每项服务由三段构成:service_name 是唯一的服务标识字符串,service_version 是 4 字节无符号整数表示该服务的版本号,service_data 再放一段该服务自己的初始化数据。

规则里有三处细节值得逐条看。第一,同一台节点不得用同一个 service_name 公告两项服务,收到这种消息的对端可以直接断开——重名意味着语义冲突,宁可断线也不猜。第二,service_version 的取值由该服务的社区自己定,只要求”新版本号取更大的整数”这种弱序;一旦某项服务被标准化,它就领到一个 NODE_* 常数,以后靠标准位图和协议版本号说话,过渡期允许常数位和自定义条目同时挂出。第三,也是最反直觉的一条:提案建议服务尽量把 service_data 留空(0x00),改用服务自己的握手流程去交换能力信息;想转正的标准服务必须不依赖 service_data,因为标准服务位那一侧根本没有对应的携带初始化数据的机制。换句话说,service_data 只是给”不打算转正、又需要塞一小撮初始化参数”的实验留的口子。

撞名之外还有撞消息名的坑,提案连这个都预见了。比特币协议的消息命令名上限 12 字符,既容不下服务名又容不下服务自己的子命令,于是建议所有自定义服务的消息统一挂在一个 command 名下——名字用下划线开头加精确的服务标识(形如 _MySampleSvc),下划线避开与现有及未来标准消息的冲突,子命令再作为负载内字段区分;文档里引用这类消息的推荐写法是”服务标识冒号子命令”。整个框架的冲突消解靠的全是命名纪律而不是中央分配,这是 2012 年前后 P2P 研究圈的惯用思路,优点是零协调成本,弱点也将在下文显形。

这份提案为什么停在 Closed?从结果看,它要解决的问题被两种更省力的办法消化了。一种是继续慢慢分配标准位,64 位至今远未用完,竞争没有想象中激烈;另一种是把实验整个搬出主协议——比如服务发现的事后来由 DNS 种子、独立网络层(如 discv5 那类思路在以太坊侧的实践)等外部机制承担。主协议的 version 消息则走上另一条路:BIP-60 强调固定字段数、后来 BIP-151 与 BIP-324 各自处理加密需求,都倾向于让 version 保持紧凑,而不是不断加尾巴。

常见误区有三。其一,以为 BIP-36 的自定义服务与某个具体实验(比如某年流行的 DHT 客户端)是一回事:提案本身只是框架,从未绑定特定实现。其二,以为挂了自定义服务名就等于全网可见性:主流节点的转发逻辑不认识这些名字,能不能找到”同好”取决于实现方自己怎么记录与匹配。其三,把 service_version 与协议 version 字段混淆:前者是某个实验服务自己的内部版本号,后者是整条 P2P 协议的版本协商值。

快速问答。问:今天还有节点实现它吗?答:主流客户端的 version 消息里没有 service_count/service_list 字段,它没有进入常规部署。问:那实验性功能现在怎么协商?答:常见的落点是独立功能位加专门握手消息,或者干脆在协议外发现彼此;BIP-36 当年设想的”握手内名片”路线没有被社区接手。问:它和 BIP-13 之类的位分配文档什么关系?答:那类文档负责给标准位编制名单,BIP-36 恰恰是想让实验避开这份名单。

一条边界值得单独记:自定义服务把冲突风险从”位图撞车”转移成了”命名撞车”和”沉默忽略”——没有恶意,也没有协调,两个同名异义的实现各自运行,除非实现方自己约定去重。这正是它比分配标准位更弱、也更便宜的地方。

风险提示:本文是协议机制科普,不构成投资建议,也不构成对任何实验协议的采用性背书。

不动 64 位服务位图也能报名新功能:BIP-36 自定义服务的命名与版本字段 图 2
不动 64 位服务位图也能报名新功能:BIP-36 自定义服务的命名与版本字段 · 图 2