Skip to content

以太坊中的Kademlia协议

在阅读此文前,请先了解Kademlia协议的内容。

以太坊的P2P网络使用了Kademlia协议,以太坊在使用Kademlia时,对协议中某些参数是一定要确定下来的,经过源码的阅读分析,大致搞懂了以太坊中的Kademlia协议是怎么运作的,现记录下来。

Ethereum中的节点距离

注意,这里我们讲的“距离”并非地理空间上的距离。

在之前的文章《以太坊的NodeID》中,我们指出以太坊使用了NodeID作为一个节点的标识,计算这个NodeID的SHA-256哈希,可以得到一个长度为32字节(256位)的哈希值,本文将其称为GUID(Globally unique identifier),两个节点的距离就是通过对两个节点的GUID进行异或(XOR)得出的。

两个节点的GUID进行异或计算后,会得到一个256位的二进制字符串,本文称其为距离字符串。距离字符串最左侧会有n个连续的0,那么两个节点的距离就是256-n。

例如

  • a XOR b = 000000111110111011.....,最左侧有6个连续的0,所以a和b距离为250;
  • a XOR b = 100011111110111011.....,最左侧有0个连续的0,所以a和b距离为256;
  • a XOR b = 110000111110111011.....,最左侧有0个连续的0,所以a和b距离为256;
  • a XOR b = 001000111110111011.....,最左侧有2个连续的0,所以a和b距离为254;

Ethereum中K桶相关的参数设置

下图是以太坊对Kademlia协议的参数配置,重点关注图上圈出的参数:

image-20221208230816303

geth一共使用了17个K桶,每个桶可以容纳16个对等节点。

因为两个节点的GUID都是其NodeID的哈希值,而距离字符串最左侧有n个连续的0意味着两节点的GUID的前n位相同,哈希值前n位相同的概率随着n的增大而变小。以太坊认为,前17位或者更多位相同的哈希值很稀少(甚至没有),并且为了防止日蚀攻击,以太坊设置了17个桶(从1.8.0版本开始)[1,2],第1个桶存放距离<=239的节点和距离为240的节点,第2个桶存放距离为241的节点,第3个桶存放距离为242的节点,.......,第17个桶存放了距离为256的节点。

每个桶可以放16个对等节点的信息。

Ethereum中K桶节点的限制

image-20221208234810299

可以看到,以太坊限制了K桶所存储的节点的IP地址。

一个K桶中,至多有2个节点来自同一个/24网段。

比如网段192.168.0.*就是一个/24网段,当192.168.0.2和192.168.0.3都在第i个桶时,192.168.0.4便不能再加入第i个桶。

一个table中,至多有10个节点来自同一个/24网段。这里的table就是节点表格,里面有所有的17个桶。当192.168.0.2-192.168.0.11都已经和我们的节点连接后,192.168.0.12便不能再与我们的节点连接。

Ethereum中K桶节点的刷新与存储

image-20221208235851404

以太坊P2P网络启动后,会启动协程loop循环:

  • 每隔30分钟自动刷新一次K桶
  • 每隔最大10秒钟验证每个K桶中的距离上次验证时间间隔最长的节点是否可以ping通
  • 每30秒将K桶中存在超过5分钟的节点存储本地数据库,视作稳定节点
  • 本地数据库中最多存储30个稳定节点
  • 数据库中的稳定节点如果已经5天未被验证,则会被丢弃

参考

  1. Henningsen S, Teunis D, Florian M, et al. Eclipsing ethereum peers with false friends[J]. arXiv preprint arXiv:1908.10141, 2019.
  2. Marcus Y, Heilman E, Goldberg S. Low-resource eclipse attacks on ethereum's peer-to-peer network[J]. Cryptology ePrint Archive, 2018.