协议演进 / BIP/比特币改进提案 / BIP-60
BIP-60
提议把 version 消息中的 relay 字段定为固定必备字段、协议版本升至 70002,解决 BIP-37 引入的可选字段给反序列化带来的麻烦。提案最终关闭,未成为现行规则。本 BIP 目前处于已关闭状态。
一、档案卡
| 编号 | BIP-60 |
|---|---|
| 标题 | Fixed Length "version" Message (Relay-Transactions Field) |
| 作者 | Amir Taaki <[email protected]> |
| 指定日期 | 2013-06-16 |
| 层级 | Peer Services(对等服务) |
| 类型 | Specification(规范类) |
| 状态 | Closed(已关闭) |
| 阅读版 | https://bips.dev/60 |
| 官方原文 | https://github.com/bitcoin/bips/blob/master/bip-0060.mediawiki |
二、放在哪一族
P2P 网络协议的消息格式族,直接因 BIP-37 而起:BIP-37 给 version 消息加了一个标志,表明是否要向该节点中继新交易消息,协议版本随之升到 70001。
BIP-60 处理的是这个改动的“后遗症”:relay 标志成了 version 消息流中的一个可选部分。它还引用了 BIP-14(User Agent),version 消息中的 user_agent 字段即出自该规范。
三、它要解决什么
原文的批评集中在“可选字段”破坏了比特币消息的两条性质:
- 字段个数固定:比特币消息的一个性质是字段数量固定,格式简单易懂。往消息里加可选字段,会在可选字段之后还有其他字段时造成反序列化问题。
- 长度可校验:以 version 消息为例,本可以检查其长度来确认字节流是否一致;有了可选字段,这种检查不再可能。而检查一致性——无论是内部反序列化代码,还是核查其他节点发来的 version 消息格式是否正确——都是有益的。原文还设想:将来网络实现更加多样化时,会需要按每个协议版本严格执行这种字段长度合规检查。
- 流式解析:定长字段消息可以把流操作符传来传去做反序列化;有了可选字段,这一性质也丢了——解析器必须额外知道流还剩多少字节,解析不再是“傻读”即可。
一句话:问题不在 relay 标志本身,而在它以“有就读、没有就算”的可选形式存在。
四、规则本身
4.1 version 消息的完整字段表
原文给出的 version 负载字段依次为:
version(4 字节,int32_t):节点使用的协议版本;services(8 字节,uint64_t):为这条连接启用的功能位域;timestamp(8 字节,int64_t):标准 UNIX 时间戳(秒);addr_recv(26 字节,net_addr):接收此消息的节点的网络地址;- 以下为 version ≥ 106 才有:
addr_from(26 字节,net_addr):发送此消息的节点的网络地址; nonce(8 字节,uint64_t):每次发送 version 包时随机生成的节点随机数,用于检测连到了自己;user_agent(变长,var_str):见 BIP-14,字符串为 0 字节时填 0x00;start_height(4 字节,int32_t):发送方节点收到的最新区块高度;relay(1 字节,bool):远程对等方是否应公布中继交易,见 BIP-37,自版本 ≥ 70001 起。
原文同时重申握手流程:节点建立出站连接后立即公布自己的 version,远程节点以自己的 version 回应;双方交换完 version 之前不能有进一步通信。version 包被接受后,应回送一个 “verack” 包。当时已分配的 services 值只有 1(NODE_NETWORK,表示可向该节点索取完整区块而非仅区块头)。
4.2 具体的代码层面改动
- 在 PushVersion()(net.cpp)的 PushMessage() 调用中加入 fRelayTx,即发送 version 时把 relay 字段作为固定组成部分发出(原文给出的示例代码中该参数为 true);
- 协议版本从 70001 提高到 70002。
要义是:把 relay 从“可选尾巴”变成该协议版本下每个 version 消息都必备的定长收尾字段,恢复第二节所述的长度可校验与流式解析性质。
五、谁必须动
普通持币人:无直接变化,不涉及交易与地址。
钱包开发者:完整节点钱包无感;直接实现 P2P 握手的轻客户端实现者,才需要按版本处理 version 消息的字段构成。
全节点与矿工:若当年实施,节点需按 70002 的格式发送 version 并能正确解析。它最终关闭,因此没有成为必须执行的现行要求。
共识层:本 BIP 不修改共识规则,只涉及对等节点之间握手消息的格式。
六、现在算不算数,以及一个常见误读
状态为 Closed(已关闭)——不算数。它提出的“70002 + relay 必备字段”没有成为现行规则;本页保留它,是因为它把“为什么消息格式要定长”这条协议设计原则讲得最清楚。
常见误读:
“BIP-60 被关闭,说明 relay 字段本身是个错误设计、后来被移除了。”
不对。原文从头到尾没有反对 relay 标志的功能——它由 BIP-37 引入,表明节点是否接收中继交易。作者反对的是它的存在形式:作为可选字段破坏定长与可校验性。关闭的是这份“改成必备字段”的提案,不是 relay 字段本身。
七、延伸
- 阅读版:https://bips.dev/60
- 官方原文:https://github.com/bitcoin/bips/blob/master/bip-0060.mediawiki
- 相关:BIP-37 连接 Bloom 过滤、BIP-14 User Agent
- 仓库总目录:https://github.com/bitcoin/bips
