协议演进 / BIP/比特币改进提案 / BIP-130
BIP-130
节点发一条空的 sendheaders 消息表明:以后有新区块时,请直接用 headers 消息把区块头推给我,不必再走 inv 公告。本 BIP 目前处于已部署状态。
一、档案卡
| 编号 | BIP-130 |
|---|---|
| 标题 | sendheaders message |
| 作者 | Suhas Daftuar <[email protected]> |
| 指定日期 | 2015-05-08 |
| 层级 | Peer Services(对等服务) |
| 类型 | Specification(规范类) |
| 状态 | Deployed(已部署) |
| 阅读版 | https://bips.dev/130 |
| 官方原文 | https://github.com/bitcoin/bips/blob/master/bip-0130.mediawiki |
二、放在哪一族
P2P 网络与区块中继族。它只动节点之间“怎么宣布新区块”这一件小事,属于对等服务层,不碰共识、不碰交易格式。
它的上下文是 0.10 版引入的 headers-first(先头后体)区块下载:区块只有能接上一条有效的区块头链时才会被处理。理解本 BIP,要先看清它与既有消息的分工:inv 宣布“我有这个区块哈希”,getheaders 索取区块头,headers 送回区块头,getdata / block 则取整块。本 BIP 没有新增这些消息,只新增了一条表达偏好的信号消息,让对方可以省掉其中一来一回。
同族可对照阅读的有 BIP-152(紧凑区块中继)等同样着眼于降低区块传播开销的文档,但两者机制不同,不要混为一谈。
三、它要解决什么
3.1 先见流程:宣布一个新区块要多绕一圈
原文复述了当时区块中继的一般流程:
- 节点 N 用一条 inv 消息宣布新链尖,里面只有区块哈希;
- 对等节点 P 收到后,回一条 getheaders(索取直到新链尖的区块头,外加定位用的 block locator),再回一条 getdata 取新链尖整块;
- N 再回一条 headers(新区块的头,连同 P 还不知道的前置区块头),和一条 block(新区块整块)。
既然自 headers-first 以来,P 反正都要先拿到区块头才能处理区块,那么当新区块就建在当前链尖之上时,N 直接把新区块的区块头宣布出来更有效率:省下 P 生成与发送 getheaders 这一步,也省下构造 block locator 的功夫。
3.2 重组时:中间区块的头迟到,整块就只能等
发生重组、有一个或多个区块被断开时,当时节点只对新链尖发一条 inv。对等节点可以立刻请求新链尖整块,但要等中间区块的区块头送达后,才能请求那些中间区块。如果宣布时就把从最后分叉点到新链尖的一串区块头一并发出,对等节点便可立刻请求全部中间区块。
所以本 BIP 要的不是新功能,而是一次握手约定:让一个节点能事先告诉对方“以后直接用 headers 向我宣布新区块”。
四、规则本身
原文规范只有三条,出奇地短:
- 消息定义:sendheaders 消息是一条空消息,其 pchCommand == “sendheaders”,没有载荷;
- 收到后的许可:节点收到一条 sendheaders 消息后,被允许(permitted)但不被要求(not required),在宣布新区块时直接发送新区块的区块头——连同该节点认为对方为使区块接上链可能需要的其他区块头;
- 功能发现:通过检查协议版本是否 >= 70012 来判断对方是否支持这一特性。
附加约束:sendheaders 的支持是可选的;实现它的软件还可以自行附加额外约束,例如只接受连接刚建立后不久发来的 sendheaders 消息。
实现指向:原文给出 Bitcoin Core 的 PR #6494 作为实现。
向后兼容
原文一句话:改动之后,旧客户端仍完全兼容、可互操作。不发 sendheaders 的节点,继续走 inv 老流程;收到 sendheaders 也可以不理会——因为规范用的是“允许但不要求”。
五、谁必须动
普通持币人:无感,也无须操作。这是节点软件之间的中继优化,不改变地址、交易或确认规则。
钱包开发者:全节点钱包若自实现 P2P 中继,可按本规范发送 sendheaders 并处理直接推来的 headers;轻钱包一般依赖所连节点的既有行为,不必专门适配。
全节点开发者与运营者:想获得这项优化的一方,在连接后向对端发送 sendheaders(协议版本需 >= 70012);宣布新区块的一方,在对端发过 sendheaders 时可改用 headers 直接宣布。两项都是可选的。
矿工:不必专门动。更快、更省带宽的区块头宣布对全网传播有益,但本 BIP 不给矿工设定任何义务。
共识层:无改动。区块有效性、区块头本身的格式与验证规则都不变,变的只是宣布方式。
六、现在算不算数,以及一个常见误读
状态为 Deployed(已部署)。按仓库状态解释:这条消息已经进入实际运行的节点软件与网络实践,是一项现行有效的对等服务规范,而不是待议提案。也正因为它在原文里就被设计成可选且向后兼容,“已部署”不意味着全网每条连接都必须使用它——不用的连接照常以 inv 方式工作,网络不会因此分裂。
常见误读:“发了 sendheaders,对方就必须直接推区块头,不许再发 inv。”
不对。原文的措辞是 permitted, but not required:收到 sendheaders 只意味着对方获得了这样宣布的许可,没有服从义务;实现方甚至可以附加条件,例如只认连接刚建立时发来的那一条。把它读成强制命令,就读错了这份短规范里最关键的一个词。
