以太坊 p2p网络——kademlia协议

    Kademlia协议(以下简称Kad),是一种分布式哈希表(DHT,Distributed Hash Table)技术,不过和其他DHT实现技术比较,如Chord、CAN、Pastry等,Kad通过独特的以异或算法(XOR)为距离度量基础,建立了一种全新的DHT拓扑结构,相比于其他算法,大大提高了路由查询速度。

    在Kademlia网络中,所有信息均以的哈希表条目形式加 以存储,这些条目被分散地存储在各个节点上,从而以全网方式构成一张巨大的分布式哈希表。我们可以形象地把这张哈希大表看成是一本字典:只要知道了信息索 引的key,我们便可以通过Kademlia协议来查询其所对应的value信息,而不管这个value信息究竟是存储在哪一个节点之上。在eMule、 BitTorrent等P2P文件交换系统中,Kademlia主要充当了文件信息检索协议这一关键角色,但Kad网络的应用并不仅限于文件交换

节点

    每个用户都有一个ID号, ID长度根据不同网络而定,例如以太坊中是512bit,eMule是128bit。 它是在你第一次使用Kad时随机生成的. 出现两个相同ID的概率实在太小了, 这几乎不可能发生. 我们可以认为, 在Kad网络里, 没有两个用户具有相同的ID号, 除非你故意那样做.每个用户都是Kad网络里的一个结点, 因此用户的ID就是结点的ID.

距离

    在Kad网络中,两个节点之间距离并不是依靠物理距离、路由器跳数来衡量的,事实上,Kad网络将任意两个节点之间的距离d定义为其二者ID值的逐比特二进制和数,即异或。假定两个节点的ID分别为a与b,则有:d=a XOR b。在Kad中,每一个节点都可以根据这一距离概念来判断其他节点距离自己的“远近”,当d值大时,节点间距离较远,而当d值小时,则两个节点相距很近。 这里的“远近”和“距离”都只是一种逻辑上的度量描述而已;在Kad中,距离这一度量是无方向性的,也就是说a到b的距离恒等于b到a的距离,因为a XOR b==b XOR a。

    因为Kademlia是根据bit位XOR计算得到"相对距离"的,对于越低bit位,XOR可能得到的结果越小,对于越高位的bit位,XOR可能得到的值就越大,并且是呈现2的指数方式增长的,所以,从数学上来说,一个DHT网络中的所有节点,通过这种方式(XOR距离)进行寻址,每次前进一个bit,最大只需要log2N次即可到达目标节点(log2逼近的思路,即bit 2可以表示世界上任何数字)

节点和它本身之间的异或距离是0异或距离是对称的:即从A到B的异或距离与从B到A的异或距离是等同的异或距离符合三角形不等式:给定三个顶点A B C,假如AC之间的异或距离最大,那么AC之间的异或距离必小于或等于AB异或距离和BC异或距离之和.由于以上的这些属性,在实际的节点距离的度量过程中计算量将大大降低。Kademlia搜索的每一次迭代将距目标至少更近1 bit。一个基本的具有2的n次方个节点的Kademlia网络在最坏的情况下只需花n步就可找到被搜索的节点或值。

协议消息

Kademlia协议包括四种远程RPC操作:PING、STORE、FIND_NODE、FIND_VALUE。

1、PING操作的作用是探测一个节点,用以判断其是否仍然在线。

2、STORE操作的作用是通知一个节点存储一个<key,value>对,以便以后查询需要。

3、FIND_NODE操作使用一个160bit的ID作为参数。本操作的接受者返回它所知道的更接近目标ID的K个节点的(IP address,UDP port,Node ID)信息。这些节点的信息可以是从一个单独的K桶获得,也可以从多个K桶获得(如果最接近目标ID的K桶未满)。不管是哪种情况,接受者都将返回K个节点的信息给操作发起者。但如果接受者所有K桶的节点信息加起来也没有K个,则它会返回全部节点的信息给发起者。

4、FIND_VALUE操作和FIND_NODE操作类似,不同的是它只需要返回一个节点的(IP address,UDP port,Node ID)信息。如果本操作的接受者收到同一个key的STORE操作,则会直接返回存储的value值。注:在Kad网络中,系统存储的数据以<key,value>对形式存放。根据笔者的分析,在BitSpirit的DHT实现中,其key值为torrent文件的info_hash串,其value值则和torrent文件有密切关系。

为了防止伪造地址,在所有RPC操作中,接受者都需要响应一个随机的160bit的ID值。另外,为了确信发送者的网络地址,PING操作还可以附带在接受者的RPC回复信息中。

路由表

Kad的路由表是通过一些称之为K桶的表格构造起来的。Kademlia路由表由多个列表组成,每个列表对应节点ID的一位(例如: 假如节点ID共有6位,则节点的路由表将包含6个列表),一个列表中包含多个条目,条目中包含定位其他节点所必要的一些数据。列表条目中的这些数据通常是由其他节点的IP地址,端口和节点ID组成。

K桶的更新机制非常高效的实现了一种把最近看到的节点更新的策略,除非在线节点一直未从K桶中移出过。也就是说在线时间长的节点具有较高的可能性继续保留在K桶列表中。采用这种机制是基于对Gnutella网络上大量用户行为习惯的研究结果,既节点的失效概率和在线时长成反比关系,如图3(横坐标为分钟,纵坐标为概率):可以明显看出,用户在线时间越长,他在下一时段继续在线的可能性就越高。

所以,通过把在线时间长的节点留在K桶里,Kad就明显增加K桶中的节点在下一时间段仍然在线的概率,这对应Kad网络的稳定性和减少网络维护成本(不需要频繁构建节点的路由表)带来很大好处。

这种机制的另一个好处是能在一定程度上防御DOS攻击,因为只有当老节点失效后,Kad才会更新K桶的信息,这就避免了通过新节点的加入来泛洪路由信息。

为了防止K桶老化,所有在一定时间之内无更新操作的K桶,都会分别从自己的K桶中随机选择一些节点执行RPC_PING操作。上述这些K桶机制使Kad缓和了流量瓶颈(所有节点不会同时进行大量的更新操作),同时也能对节点的失效进行迅速响应。

猜你喜欢

转载自blog.csdn.net/xq723310/article/details/82426113