Kademlia 怎么路由?以太坊节点发现的异或距离与桶表 图 1
Kademlia 怎么路由?以太坊节点发现的异或距离与桶表 · 图 1

冷启动的第一个问题:我认识谁

一台全新节点启动时,它对网络一无所知。比特币的做法里 DNS 种子节点负责递出第一批地址;以太坊的做法更进一步,在种子之外跑一套持续“查号”的发现协议。客户端内置若干引导节点(bootnodes),新节点先和它们打招呼,然后开始像滚雪球一样扩充自己的邻居池。滚雪球的规则来自一个 2002 年的老发明——Kademlia,一套最初为文件共享网络设计的分布式路由表。

把每个节点变成一个数字

以太坊节点各有一对 secp256k1 密钥作为长期节点身份,公开出来的节点 ID 在旧版发现协议里就是 512 位的非压缩公钥,在 discv5 里则取公钥的哈希;配套的 ENR 记录还签着公网 IP、端口和能力声明。距离不是经纬度或网段,而是两个节点 ID 的异或值:按位异或,越小的异或值意味着“越靠近”。这个定义让全网空间变成一颗以 ID 位为分叉的假想树——每个节点眼里的“离我最近的集合”都完全不同。

路由表:离我不同距离的桶

每个节点把距离空间切成一系列桶:第 k 号桶装“与我距离落在 2 的 k 次方量级”的节点。和某个桶里的邻居ping成功后,它被移到桶的头部(最近使用优先);桶满了,最久没回应的候选被踢出重选。想找“离目标 ID 最近”的节点时,本地节点向已知邻居询问它们的最近者,邻居返回若干 ENR,问的人再问下一跳——每问一次,返回的 ID 距离目标更近,几轮之后就像二分查找一样逼近。这正是 Kademlia 的精髓:不需要中心目录,每个人只维护一小撮邻居就能把整个网络当查询库用。

它解决什么,又不保证什么

发现协议只负责“给你一堆看起来活跃的节点和它们的公开记录”,不担保诚实。ENR 由节点自己签,签名能验真伪,验不了“它说的是真话”。所以新节点仍然要配合自己的拨号策略:主动出连、限制入连、按分叉哈希拒绝串网。以太坊的 discv4 长期服务于主网发现,discv5 作为更新的加密传输层随后落地并逐步扩大使用,具体到某个客户端默认开哪一套,以当期客户端文档为准。

和比特币 DNS 种子的对照

比特币的种子节点是“黄页”:拨出几十条地址后靠 addr 消息互相转介绍。以太坊把黄页+查号台合体:种子只是入口,异或距离路由让节点自己组织出覆盖全网的查询结构。两种设计都能把新节点喂饱,差别在于以太坊的邻居池天然按“ID 距离均匀”分布——这既防止所有人挤在同一拓扑角落,也让某个地理区域的节点更容易凑出跨区路由路径。

一笔直觉算术

512 位 ID 做异或距离,意味着“离我最近的一半节点”大致落在首位为 0 的半个空间里,再切一半是 256 号桶以内。路由表通常给每个桶留十几个位置,于是活跃路由集只有几百条记录,却能覆盖整个 ID 空间的不同距离层级。查询期望跳数是桶位数的对数量级——实践中四五跳就能凑齐一整页邻居。这解释了为什么一个只连了几十条记录的节点,每次冷启动都能抽出与上次几乎不重样的邻居名单:候选在同桶里按最近活跃轮换,而每个桶都替你存着全网的一个横截面。

快速问答

桶数固定吗? 由 ID 位宽决定(512 位即 512 个理论桶,低位桶常空)。发现协议传区块吗? 不传,它只在 UDP 层换名片,区块走 RLPx 等其他连接。关掉发现会怎样? 节点只能靠静态 peer 维持,几乎必然掉队。

常见误区

一是把“距离”读成网络延迟——异或距离与物理距离无关,只影响路由表分布。二是以为发现协议是安全机制,它只是通讯录,真验证发生在同步与共识层。三是把 discv4 与 discv5 说成两代“共识协议”,它们是同一套 P2P 的传输与握手演进,链规则与之无关。

风险提示:本文是网络机制科普,不构成任何投资建议;自行跑节点请注意防火墙与端口暴露的基本防护。