协议演进 / BIP/比特币改进提案 / BIP-155

BIP-155 addrv2 消息

新增 addrv2 消息,用网络 ID 加变长地址在 P2P 网络中 gossip 节点地址,使 Tor v3、I2P 等长地址也能被传播。本 BIP 目前处于已部署状态。

一、档案卡

档案卡
编号BIP-155
标题addrv2 message
作者Wladimir J. van der Laan <[email protected]>
指定日期2019-02-27
层级Peer Services(对等服务)
类型Specification(规范类)
状态Deployed(已部署)
阅读版https://bips.dev/155
官方原文https://github.com/bitcoin/bips/blob/master/bip-0155.mediawiki

二、放在哪一族

节点地址发现与 gossip(地址传播)一族。它接续的是既有的 addr 消息:节点靠互相转告“我知道这些节点在这些网络端点上”,新节点才能逐步找到可连接的对等节点,无需永远依赖少数种子。

BIP-155 不是推翻 addr,而是给它配一个 v2 继任者。旧 addr 把一切端点塞进固定的 16 字节地址字段(洋葱地址靠 OnionCat 方式嵌进 IPv6 形式),装不下新一代网络的长地址;addrv2 用“网络 ID + 变长地址”的结构把这个上限打开,同时保留与旧对等节点的兼容路径。

原文文件头没有 Requires、Replaces 等关系字段——它与旧 addr 的关系是并行兼容、按对端能力选用,而不是在文件头层面声明取代。

三、它要解决什么

原文 Motivation 聚焦一个具体的装不下问题:

Tor v3 隐藏服务自 Tor 0.3.2.9 起进入稳定版,相比旧版隐藏服务有更好的加密与隐私特性,但它的地址是 256 位的,塞不进现有 addr 消息——旧消息把洋葱地址封装在 OnionCat IPv6 地址里,地址字段只有 128 位。

不止 Tor:I2P 等其他传输层协议历来就使用更长的地址。地址 gossip 不过去,意味着这些网络上的节点无法经 P2P 网络被其他对等节点发现和连接,哪怕节点软件本身支持走这些网络出站。

因此需要一条新消息:能装下更长的端点地址、能区分地址属于哪个网络、还能继续与只懂旧 addr 的节点共存。

四、规则本身

4.1 消息格式:把定长字段换成网络 ID 加变长地址

addrv2 消息(pchCommand == "addrv2")沿用 P2P 消息的标准序列化,整体结构与 addr 相近,差别有两处:固定的 16 字节 IP 地址被换成一个网络 ID 加一段变长地址;服务位(services)字段改用 CompactSize 编码(通常更省字节,这是原文致谢中点明的改动来源之一)。

每条地址记录包含:

上限纪律:一条消息最多装 1,000 个地址,客户端应拒绝超出的消息;单个 addr 字段最长 512 字节(4096 位),更长的应拒绝,不论网络 ID 为何。收到与表中规定长度不符的地址,客户端应拒绝该消息中的相应地址,因为它们没有意义。

4.2 网络 ID 登记表

原文保留的网络 ID 如下(新的网络 ID 必须另以一份 BIP 文档登记,不得私自占用):

两条防混淆规则:其一,某些 IPv6 地址段本身是用来嵌入其他网络的(例如 IPv4-in-IPv6 的 ::ffff:0:0/96),这类地址已有其所属网络 ID 下的规范编码,不得再以 IPV6 的名义发送,收到时应忽略,以免同一端点被当作两个不同的对等节点。其二,客户端不应 gossip 自己不认识的网络的地址——无法验证真伪,就可能被 trick 去传播无效地址;反之,建议客户端 gossip 所有已知网络的地址,哪怕自己当前并未连在其中某些网络上,这对多宿主(multi-homed)节点有帮助,也让观察者更难判断一个节点到底连了哪些网络。

各网络的具体编码细节放在原文附录 A 至 E 中,包括 Tor v2 的旧编码(已停用)、Tor v3、I2P、Cjdns 与 Yggdrasil 的编码方式。

4.3 如何宣告支持:sendaddrv2

新增一条 sendaddrv2 消息表示“我能懂 addrv2,请优先发 addrv2 给我”——它只表达对接收 addrv2(而非 addr)的偏好,不涉及是否愿意接收未经请求的地址消息。

时序是硬性的:sendaddrv2 只能在收到对方 version 消息之后、自己发出 verack 之前发送。对没有发过 sendaddrv2 的旧对等节点,继续发旧的 addr 消息,并忽略其中新引入的地址类型,保证新旧节点混在同一网络里都能工作。

原文 Reference implementation 一节列出了 Bitcoin Core 中的原始参考实现条目链接。

五、谁必须动

普通持币人:无直接动作。这里的“地址”是节点在各网络上的端点,不是收款地址;钱包里的地址格式完全不受影响。

全节点:本 BIP 的实现主体:按对端是否发过 sendaddrv2 决定发 addrv2 还是旧 addr,遵守条数、长度与网络 ID 的校验纪律,并按规定 gossip 已知网络的地址。

钱包开发者:一般不必实现;只有自带 P2P 地址发现逻辑的实现才需要处理 addrv2 与 sendaddrv2。

共识层:完全不动。节点地址如何传播,不影响区块与交易的有效性。

六、现在算不算数,以及一个常见误读

状态为 Deployed(已部署)。按 BIP 体系的用法,这表示规范已进入实际运行的部署:支持它的节点之间用 addrv2 交换包括 Tor v3、I2P 在内的各类端点地址,不支持的旧节点继续走旧 addr 路径,两者并存。它解决的是一类很实际的连通性问题:没有可 gossip 的长地址格式,运行在新一代洋葱服务或 I2P 上的节点就很难被网络发现。

常见误读:

“BIP-155 改了比特币的地址格式,以后收款地址要变长了。”

不对。这里的 address 从头到尾指的都是 P2P 网络中节点的网络端点(IP、.onion、.i2p 等),是“节点在哪里能被连上”的问题;用户之间付款用的比特币地址(其格式由地址与脚本类 BIP 定义)与本 BIP 毫无关系。把两者混为一谈,就会误以为每次 P2P 消息升级都要换钱包地址。

七、延伸

本页内容整理自 bitcoin/bips 仓库与 bips.dev,事实已与仓库核对;解读仅供学习参考。