协议演进 / BIP/比特币改进提案 / BIP-36
BIP-36
想给 version 消息加一份自定义服务清单,让实验性扩展不必抢占 64 位 services 位域;方案最终关闭,未被采用。本 BIP 目前处于已关闭状态。
一、档案卡
| 编号 | BIP-36 |
|---|---|
| 标题 | Custom Services |
| 作者 | Stefan Thomas <[email protected]> |
| 指定日期 | 2012-08-03 |
| 层级 | Peer Services(对等服务) |
| 类型 | Specification(规范类) |
| 状态 | Closed(已关闭) |
| 阅读版 | https://bips.dev/36 |
| 官方原文 | https://github.com/bitcoin/bips/blob/master/bip-0036.mediawiki |
二、放在哪一族
BIP-36 属于对等服务层的“节点能力宣告”这一族。节点在握手时用 version 消息里的 64 位 services 位域告诉对方自己能做什么,每一项标准服务占一位,如 NODE_NETWORK、NODE_BLOOM 等。
与它相关的文档包括 BIP-14(协议版本与用户代理)、BIP-33(分层节点,同样动过 services 位的主意)、BIP-37(其服务后来以 NODE_BLOOM 服务位宣告,见 BIP-111)与 BIP-159(NODE_NETWORK_LIMITED 服务位)。
BIP-36 问的是另一个问题:位域只有 64 位,实验性的、还没标准化的扩展服务,该到哪里去登记自己?
三、它要解决什么
原文希望鼓励开发者实验各种扩展比特币协议的自定义服务,并举了例子:分布式哈希表(DHT)、分布式矿池、轻客户端支持协议、定向消息路由、自定义传输支持等。
但没有通用框架时,这些实验很容易互相撞车:名字撞、命令撞、位域乱占。每个实验都往有限的 64 位 services 字段里塞自己的标志,字段会被污染、耗尽,彼此也无法共存。
BIP-36 要提供的正是这个框架:让客户端在 version 消息里以结构化的清单宣告自定义服务,既不占用标准位域,又给日后“转正”留好升级路径;同时附上一些不具约束力的实现建议。
四、规则本身
4.1 version 消息新增两个字段
在 version 消息的 extra_height 之后新增:
service_count:变长整数,表示额外服务的数量;service_list:服务定义清单,每项包含service_name(变长字符串,服务的唯一标识)、service_version(32 位无符号整数,服务自己的版本号,版本越高数字应越大)、service_data(变长字符串,服务特有的附加数据)。
一个节点不得宣告两个同名服务;若对方发来这样的 version 消息,客户端可以断开连接。
service_data 的建议用法是:一般应传空字符串,改用自定义握手去初始化协议、交换能力等信息;打算转正为标准服务的服务不得依赖 service_data,因为标准服务的 services 字段没有对应机制。不打算转正的服务则可用它传少量初始化数据,例如自定义传输(UDP、WebSocket)服务把端口号放进去。格式由服务自定,可以是二进制或 ASCII,原文建议用便于调试的人类可读格式。
4.2 服务标识符的命名规则
每个服务应选一个未被他人使用的新标识,并登记到原文指定的 Service identifiers 维基页面,附维护者姓名与联系方式;没有真在用的标识不要登记。已被接受的 BIP 保留或使用的标识,他人不得挪用。
标识长度必须在 5 到 11 个字符之间,只能用 ASCII 字符,且不得含 /、*、_、: 四个字符。原文给的合规例子包括 MySampleSvc、smartserv、P-Pool;太短、太长或含非法字符的则不合规。
4.3 自定义命令的推荐格式(可选)
比特币命令名最长 12 个字符,塞不下“服务标识 + 命令名”。因此原文建议:一个服务在比特币网络上只占一个命令名,即下划线加服务标识(如 _MySampleSvc),以同时避免与别的服务和与现行、未来的协议消息撞名。
真正的子命令放在载荷开头的额外头部里:12 字节的 subcommand(ASCII,空字节填充,填充非空则数据包被拒),其后是实际数据 subpayload。文档中引用这种消息的写法是“服务标识:子命令”,如 MySampleSvc:search。不理解的服务或子命令,客户端应当直接忽略。
4.4 从自定义到标准的转正路径
想进入比特币协议的自定义服务必须满足:不使用 service_data;使用与 services 字段相同的“每节点一位”的对等发现机制;子命令不得与现行或计划中的协议命令冲突。
转正流程大致是:先实现并测试;API 相对稳定后写成 BIP 正式提交;被接受后分配一个 NODE_* 常量,进入过渡期——过渡期内客户端必须同时认两种宣告方式、同时收两种形式的命令,但只发包装形式的消息,且 API 不得变更;过渡期结束后只用 services 字段宣告、只发未包装消息,此后 API 再变就需要新的 BIP 并提升协议版本。原文同时强调,这条转正通道只应留给有强理由的服务;也可以只把服务以自定义形式标准化,而不转成标准服务。
4.5 设计取舍
原文列的目标包括:最小化命名空间冲突风险、给自定义服务留平滑的转正路径、对服务作者施加最少限制、让创建与同时支持多个自定义服务的成本尽量低。
为什么不另发一条新消息、非要改 version?原文的理由是:让标准服务与自定义服务的宣告待在同一条消息里,两类服务的生命周期才能保持一致,也便于识别正处在“两种方式同时宣告”的转正过渡期服务。此外,原文还顺带固定了 subcommand、subpayload、service identifier 等一套讨论自定义服务时的通用名词。
五、谁必须动
普通持币人:无直接变化。本方案不涉及地址、交易与余额。
实验性服务的开发者:若采用本框架,要按规则命名与登记标识、在 version 中宣告服务,并按推荐格式组织命令;不认识的服务与子命令要学会忽略。
全节点实现者:要解析扩展后的 version 消息,处理重名服务等异常情形;是否真去实现某个自定义服务,仍由各自决定。
共识层:完全不动。改动只在握手消息与节点能力宣告层面。
六、现在算不算数,以及一个常见误读
状态为 Closed(已关闭)。BIP-36 的宣告框架没有被网络采用:今天的 version 消息里没有 service_list 字段,新服务进入协议的实际做法,仍是逐个 BIP 论证、逐个分配 NODE_* 服务位(如后来的 NODE_BLOOM、NODE_NETWORK_LIMITED、NODE_COMPACT_FILTERS 等各自的文档)。本页的价值在于留档:它记录了社区曾认真考虑过“给实验留一个通用登记处”,最后没有走这条路。
常见误读:
“services 位域里没给我的功能留位子,我就可以按 BIP-36 的格式自己宣告一个自定义服务,全网节点都得认。”
不对。BIP-36 本身已经关闭,从未成为生效标准;而且即便在它自己的设计里,自定义宣告也只是实验框架,别的客户端对不理解的服务应当忽略,而不是必须支持。想让一项能力成为全网通用的服务,至今仍要走单独 BIP 并分配标准服务位的老路。
七、延伸
- 阅读版:https://bips.dev/36
- 官方原文:https://github.com/bitcoin/bips/blob/master/bip-0036.mediawiki
- 相关:BIP-14 协议版本与用户代理、BIP-111 NODE_BLOOM 服务位、BIP-159 NODE_NETWORK_LIMITED 服务位
- 仓库总目录:https://github.com/bitcoin/bips
