协议演进 / BIP/比特币改进提案 / BIP-159
BIP-159
新增 NODE_NETWORK_LIMITED 服务位,让已裁剪节点能如实宣告自己至少可提供最近 288 个区块,而不是冒充全量节点。本 BIP 目前处于已部署状态。
一、档案卡
| 编号 | BIP-159 |
|---|---|
| 标题 | NODE_NETWORK_LIMITED service bit |
| 作者 | Jonas Schnelli <[email protected]> |
| 指定日期 | 2017-05-11 |
| 层级 | Peer Services(对等服务) |
| 类型 | Specification(规范类) |
| 状态 | Deployed(已部署) |
| 阅读版 | https://bips.dev/159 |
| 官方原文 | https://github.com/bitcoin/bips/blob/master/bip-0159.mediawiki |
二、放在哪一族
服务位(service bit)与节点能力宣告一族。比特币节点在握手与地址传播时用一组服务位说明自己能提供什么服务,其他节点据此决定连谁、向谁要什么数据。既有的 NODE_NETWORK 服务位只表达一种能力:“我能提供全部历史区块”。
BIP-159 在这套宣告体系里补上缺失的一档:能力有限但并非无用。它的直接同类是更早的 BIP-111(NODE_BLOOM 服务位)——同样是用一个新服务位把一类节点的真实能力如实说出来,让需要服务的对端自行取舍,而不是靠试错去发现。
原文篇幅很短,文件头也没有 Requires、Replaces 等关系字段:它只定义一个新服务位及其使用纪律,不改动任何既有消息的格式。
三、它要解决什么
原文 Motivation 的起点是裁剪节点(pruned peer)的尴尬处境。裁剪节点为了节省磁盘,只保留最近一段时间的区块数据,但除此之外——中继新区块、区块头、交易与地址——它与传统全节点能提供的服务并无不同。
问题出在宣告环节:当时只有 NODE_NETWORK 一个服务位表示“能提供全部历史区块”。于是出现两难:
- 裁剪节点如实不置 NODE_NETWORK,它在对端眼里就近乎“什么都提供不了”,难以被选中连接,它的中继能力被白白浪费;
- 它若置上 NODE_NETWORK,则是虚假宣告,向它索取深层历史区块的节点必然扑空。
原文列出的两点诉求因此是:第一,裁剪节点应有办法宣告自己“能提供有限但明确的服务”;第二,已完成初始区块下载的节点,应当可以把一部分出站连接名额留给裁剪节点,让其他对端把宝贵的连接留给能提供全链数据的未裁剪节点去完成自举同步。把有限能力如实标签化,整个网络的连接资源才能分工。
四、规则本身
4.1 新服务位:bit 10,最低保证 288 个区块
本 BIP 新增的服务位是:
- NODE_NETWORK_LIMITED:bit 10(0x400)。置位即承诺:该节点必须有能力提供至少最近 288 个区块——原文括注约合 2 天的区块量。
与之配套的宣告纪律是:裁剪/受限节点不得置任何表示“能提供完整区块链”的服务位(例如 NODE_NETWORK);而反过来,能提供完整区块链的节点也可以同时置 NODE_NETWORK_LIMITED——原文特意用一条 Rationale 说明,这个方向的叠加是允许的。
4.2 使用纪律:缓冲、地址中继与防指纹
原文 Specification 的其余部分都是围绕这个服务位的使用纪律:
- 重组缓冲:连接到置 NODE_NETWORK_LIMITED 的对端时,应计入 144 个区块的安全缓冲,以应对链重组——即不要把对方的可用深度恰好用到 288 的极限上;
- 地址中继:遵循本 BIP 的全节点,应当中继自己愿意连接的对端的地址与服务信息(
addr消息),包括置 NODE_NETWORK_LIMITED 的对端。否则有限节点宣告了能力,却在地址传播中被过滤掉,宣告便没有意义; - 防指纹对策:不同裁剪节点的裁剪深度各不相同(取决于配置与磁盘空间),若如实按各自深度提供区块,对手可用
getdata请求逐段试探出一个节点的确切裁剪深度,形成指纹识别弱点。因此裁剪节点不应泄漏自己的裁剪深度,并且不应提供比 288 这个宣告阈值更深的区块。
4.3 风险:谁需要检查服务位
原文 Risks 一节把代价与注意事项说清:
- 遵循本 BIP 的裁剪节点可能消耗更多的出站带宽——它们会被更多对端选作连接与中继对象;
- 不检查
addr消息中服务位(nServiceFlags)的轻客户端,可能稀里糊涂连上一个裁剪节点,并向它索取低于其裁剪深度的(过滤后)区块,结果自然拿不到。原文给轻客户端两条路:只需要链尖附近(过滤后)区块的,就连置 NODE_NETWORK_LIMITED、且最好不同时宣告全链服务的对端;需要 288 个区块以前数据的,就连宣告能提供完整区块链的对端。经 DNS 种子获取对端地址的轻客户端,应使用 DNS 的按服务位过滤选项。
兼容性:原文明确本提案向后兼容——不懂这个新服务位的旧节点只是不理解这一位,不影响既有连接与数据交换。参考实现见原文列出的两个 Bitcoin Core 合并请求(分别关于宣告与连接/中继)。
五、谁必须动
普通持币人:无直接动作。是否以裁剪模式运行自己的节点,本来就是个人在磁盘与服务能力之间的取舍;本 BIP 只是让这种取舍能被如实宣告。
全节点(尤其是裁剪节点):本 BIP 的实现主体:裁剪节点按规定置 NODE_NETWORK_LIMITED、不虚置 NODE_NETWORK、不过深提供区块;所有遵循本 BIP 的节点在地址中继时不把有限节点过滤掉。
钱包与轻客户端开发者:连接对端前必须检查服务位,按自己要取的数据深度选对端(链尖附近找 LIMITED 节点,深层历史找全链节点),经 DNS 种子找对端时使用服务位过滤。
共识层:完全不动。服务位是 P2P 层的能力标签,不影响区块与交易的有效性。
六、现在算不算数,以及一个常见误读
状态为 Deployed(已部署)。按 BIP 体系的用法,这表示该服务位已被实际部署进运行中的实现:今天网络上的裁剪节点正是靠这一位向外说明“我至少有最近 288 个区块”。它是一个很小的规范——一个比特位加一组使用纪律——但解决的是资源分工问题:全网不必每个节点都存全链,前提是能力边界必须说清楚,找数据的节点才不会扑空。
常见误读:
“置了 NODE_NETWORK_LIMITED,就说明这个节点总共只存了 288 个区块,问它第 289 个区块以前的东西一概没有。”
不对。288 是宣告的最低保证(至少能提供最近 288 个),不是该节点实际存储深度的自报家门。原文甚至专门要求裁剪节点不要泄漏自己的确切裁剪深度、不要提供比阈值更深的区块,正是为了让外界无法反推出它到底存了多少。把这个下限数字读成精确库存,既误解了规范,也恰好落进了原文要防的指纹识别陷阱。
七、延伸
- 阅读版:https://bips.dev/159
- 官方原文:https://github.com/bitcoin/bips/blob/master/bip-0159.mediawiki
- 相关:BIP-111 NODE_BLOOM 服务位(同为以服务位如实宣告节点能力的一例)
- 仓库总目录:https://github.com/bitcoin/bips
