节点发现
节点连接主要负责发现P2P网络中的其它节点。Bytom实现了类Kademlia的DHT存储有关网络中Bytom节点的信息。协议维护了节点路由表,节点路由表依据距离把网络中节点信息存储到表中不同的bucket中。
节点发现协议
discovery |
---|
udp |
节点ID及距离
网络中每个节点都有一个唯一ID,节点每次启动时都会产生ED25519公私钥对,其中公钥作为节点的ID,长度32byte。
两个节点之间的距离是以下公式计算而来,所以节点之间的距离代表逻辑距离,而不是节点间的真实物理距离。
1 | distance(n₁, n₂) = keccak256(n₁) XOR keccak256(n₂) |
节点路由表
bucket index | node |
---|---|
k-bucket 0 | 距离[1,2) |
k-bucket 1 | 距离[2,4) |
k-bucket 2 | 距离[4,8) |
… | … |
k-bucket i | 距离 [2^i,2^(i+1) |
… | … |
k-bucket 255 | 距离[2^255, 2^(255+1)) |
根据Kademilia协议节点需要保留其邻居节点的信息。邻居节点存储在由“k-buckets”组成的路由表中。对于每个bucket[i] 0≤i<256
,存储距离自己“2^i”和“2^(i + 1)”之间的距离节点。
协议使用“k = 16”,即每个k-bucket最多存储16个节点。bucket中节点按上次查看的时间排序 - 最近看到的节点位于bucket头部,最先看到的在bucket尾部。
每当遇到新节点N1时,它就可以插入相应的桶中。如果桶中包含少于“k”的节点,则可以简单地将N1添加到桶头部。如果该桶已经包含k
个节点,则取桶中最先看到的节点N2,需要通过发送ping数据包重新验证节点是否在线。如果没有从N2收到答复,那就是被认为是无效的,N2被移除bucket并且N1被添加到桶的前面。
否则将N2加入cache中,如果cache也满了,则把最先放入cache中的节点N3删除。当有节点掉线时则会把cache中的最新节点放入bucket中。
路由表刷新
节点通过定期迭代查找距离targetID距离近的节点来更新路由表。工作过程如下:
a. 随机生成目标节点Id,记为TargetId,从1开始记录发现次数和刷新时间。
b. 在当前节点的K桶里查找与目标节点最近的16个节点
c. 向b中得到的每个节点发送findnode命令,接收到每个节点传回的neighbours节点
d. 对c返回的每个节点进行ping-pong测试然后更新到本地k桶
如果一轮FindNode查询无法返回比已知最近的节点更近的节点,启动器将FindNode重新发送到k个最近节点中未查找过得节点。
协议消息及编码
协议实现了Kademlia协议的两组命令:
ping<------------->pong------------->
findnode <---------->neighbors---------->
节点发现消息作为UDP数据报发送。数据包的最大大小为1280字节。
1 | packet = packet-header || packet-data |
每个数据包都以header开头:
1 | packet-header = hash ||nodeID ||signature||packet-type |
hash 字段使在同一个UDP端口上运行多个协议时可识别。
packet-type 是定义消息类型。
Ping Packet(0x01)
1 | packet-data = [version,from,to,expiration] |
expiration 字段是绝对的UNIX时间戳。包含过去时间戳的数据包会因为过期而无法处理。
收到ping数据包后,收件人应使用pong数据包进行回复。
Pong Packet(0x02)
1 | packet-data = [to,ping-hash,expiration] |
Pong是对ping的回复。
ping-hash 应该等于相应ping包的hash。应该忽略没有包含最新ping-hash的pong数据包,因为不是对最新ping消息做出的响应。
FindNode Packet(0x03)
1 | packet-data = [target,expiration] |
FindNode 数据包请求接近target的节点的信息。收到FindNode后,收件人应回复Neighbors数据包,在其本地表中找到最接近target的16个节点并返回。
Neighbors Packet(0x04)
1 | packet-data = [node,expiration] |
Neighbors是对FindNode的回复。