**介绍了dfinity的随机灯塔原理和三层网络扩展结构,并结合GitHub源代码分析了门限中继验证过程。本文将重点对区块链网络底层的点对点网络模进行简要介绍和代码分析。
作者:季周东、丛红雷
核心关键词:P2P、kademlia、DHT
本章源代码地址:
https://github.com/dfinity/go-dfinity-p2p
1、 dfinity网络简介
在dfinity网络中,所有客户端形成一个去中心化的P2P网络(完全对等网络,没有主节点)。上层应用程序通过客户端的发送接口向P2P网络发送消息,并通过接收接口接收其他客户端向网络发送的消息。
Dfinity的P2P网络基于协议实验室的libp2p,即s/kademlia网络。S/kademlia网络增强了kademlia网络的安全性,其网络结构和应用接口与kademlia网络相同。与kademlia类似,在整个P2P网络架构中,所有的数据实体客户端都被视为一棵二叉树的叶子节点,它们在整个二叉树中的位置由客户端ID的最短唯一前缀表示,节点ID直接对应于数据的哈希值,数据的元信息保存在相应的节点中。当我们在网络中搜索数据时(即通常搜索存储文件哈希值或关键字的节点),kademlia算法需要知道这些数据的哈希值,然后在分布式网络中开始搜索。每一步都会找到离目标更近的节点。当一个节点直接返回搜索值,或者再也找不到靠近键的节点ID时,停止搜索。Kademlia网络搜索类似于其他分布式哈希表。在具有n个节点的网络中,一次搜索的复杂度为O(log(n))。
去中心化的s/kademlia网络的**优点是它显著地增强了抵抗拒绝服务攻击的能力。即使网络中的一整组节点受到攻击,也不会对网络的可用性产生很大影响。通过网络的自组织能力,可以快速绕过这些被攻击的节点,完成网络重构,恢复网络的可用性。
2、 P2P客户端简介
下面详细分析了dfinity的P2P客户端。dfinity P2P客户端系统架构如下图所示:
本文首先介绍了P2P客户端的启动和入网过程,然后介绍了各种服务。
首先,让我们看看P2P客户端的配置。主要配置参数如下:
列表:节点的服务iplistenport:;服务端口kbucket节点大小:kademlia的k桶样本大小:在kademlia网络中,每次的样本数为:kademlia网络的种子节点列表:streamstorecapacity:;每个节点与其他客户端保持的链接数artifactcachesize:;每个节点的数据缓存大小
1) 客户端初始化和启动
要启动客户机节点,需要在本地加载配置。具体流程如下:
1根据配置建立本地数据缓存;
2生成自己的私钥和公钥,并根据公钥生成自己的节点ID;
3初始化网络节点信息缓存和连接池。网络节点信息缓存负责缓存网络中所有其他节点的信息,连接池负责管理客户端与所有其他节点之间的连接。
4初始化kademlia路由表,即kbucket(k bucket)
5将当前节点的ID添加到路由表中
6初始化见证缓存,该缓存负责记录网络中哪些节点也可以将数据缓存在本地数据缓存中
完成上述初始化后,客户端可以启动并加入P2P网络。
2) 加入P2P网络
在客户端完成本地初始化之后,它首先链接到配置的种子节点。它从种子节点开始,在网络中逐步构建自己的链路关系。具体流程如下:
1构建swarm网络并开始监听IP侦听器
2启动pair服务,该服务负责处理来自网络中其他节点的pair请求
3启动Ping服务,该服务负责处理节点之间的心跳消息
4启动sample服务,该服务负责处理sample请求
5向初始化期间配置的所有种子节点发送hello请求。如果seed节点得到hello回复,seed节点将被添加到kbucket路由表中
6启动节点发现服务,该服务将定期发送示例请求以更新自己的网络节点缓存
7启动节点数据同步的流服务。流服务通过连接池维护本地节点和邻居节点之间的链路。当节点发现服务更新并找到更新的邻居节点时,流服务将自动与新邻居节点建立连接
8**,启动广播服务,客户端成功加入P2P网络,开始处理其他应用的发送呼叫。
在与种子节点建立连接后,种子节点将其知道的最近邻节点列表发送给该节点,然后该节点根据其节点发现服务不断更新其最近邻节点列表,直到在网络中找到最近邻节点为止。
3) Ping服务
Ping服务主要负责P2P网络中心跳消息的处理。在P2P网络中,心跳消息有两个目的
1当一个节点与另一个节点建立连接关系时,Ping服务用于验证网络并记录链路TTL等信息
2每个节点还周期性地从节点信息缓存中随机选取多个节点,通过Ping服务验证节点的连通性,从而尽快检测到网络节点的变化
Ping服务处理来自其他节点的Ping请求。处理流程如下:
1读取对方发送的Ping数据
2将对方的Ping数据返回给发送方
3更新kbucket路由表中请求节点的位置
4) 节点发现服务
由于P2P网络中随时可能有新的节点加入或退出,为了保持整个网络的可用性,P2P网络节点需要定期检测网络,与其他节点进行通信,并更新网络中相邻节点的活动状态。客户端后台的节点发现服务负责此任务。
客户端后台节点发现服务的工作流程如下:
1收集当前kbucket路由表中记录的所有节点
2随机排列组合,随机选择m个节点(m为初始化配置参数)
3分别向m个随机节点发送样本请求
4在M个随机节点的样本回复中,会包含网络中其他节点的信息
5客户端将解析这些示例回复中其他节点的信息,将它们添加到自己的节点信息缓存中,并首先将其TTL设置为tempaddrttl
6然后客户端将向新发现的节点发送ping请求。如果Ping成功,请将TTL更改为provideraddrtl,并将节点添加到kbucket路由表中
7如果示例请求失败,请从节点缓存和kbucket路由表中删除该节点
从上面的过程可以看出,节点发现服务基于示例请求构造每个节点的网络状态。
5) 样品服务
sample服务(也称为sampling服务)负责处理来自其他节点的sample请求。业务请求节点采集网络节点的信息并发送请求;服务应答节点还根据网络节点的信息对请求节点的最近邻节点进行采样,构造样本应答,并将其发送回服务请求节点。Kademlia网络通过该服务加速了节点的查询。
当接收到来自其他节点的样本请求时,客户端需要进行以下处理:
1收集当前kbucket路由表中记录的所有节点
2所有节点都根据来自请求节点的kademlia距离(公共前缀距离)进行排序
3按指数分布随机抽取排序结果,选择m个节点
4从M个节点构造一个示例回复
5将示例回复发送到请求节点
6更新kbucket路由表中请求节点的位置
6) 流式服务
客户端的流服务负责管理和维护该节点的连接池,维护与该节点最近的N个节点的连接关系(N是初始化时配置的连接池容量)。当客户端发现与邻居节点的连接错误时,连接池中的连接将自动清除,客户端将自动更新与邻居节点的连接并更新连接池。具体处理工艺如下:
1首先,检查连接池是否已满。如果已经满了,就不需要处理了。否则,您需要向连接池添加新连接
2收集当前kbucket路由表中记录的所有节点
3以当前节点为网络中心节点,将所有节点分为两部分
4节点的两部分根据与当前节点的kademlia距离进行排序。排序后,选择距离当前节点最近的N/2个节点
5检查这些节点。如果连接池中没有与此节点的连接,请向此节点发送配对请求以建立连接
6建立对连接后,将为该链路启动对服务,完成节点间的数据交换。
7) 配对服务
客户端的配对服务负责处理网络中其他节点的配对请求,并与其他节点建立配对关系。建立了配对关系的节点将自动广播它们接收到的数据请求。具体处理工艺如下:
1收集当前kbucket中的所有节点
2计算k近邻
3检查发出配对请求的节点是否在k个最近邻居中
4否则,拒绝配对请求
5否则,请将此链接添加到您自己的链接池,并启动此链接的服务路由
8) 连接池业务路由
此路由负责接收其他节点从连接池发送的数据,将数据添加到自己节点的数据缓存中,并维护每个数据的见证。在广播数据时,该见证用于确定相应节点是否有数据的备份。如果有,则不需要将数据广播到相应的节点。路由过程如下:
1读取流以读取数据的校验和、数据大小和其他数据元素信息
2如果当前节点已缓存此数据,请直接答复发件人
3继续接收完整的数据并验证数据的完整性
4将数据的发送者添加到数据的见证列表中
5检查当前数据缓存是否缓存了此数据,如果没有,则将其添加到数据缓存中
6如果当前节点第一次接收到该数据,它会将该数据通知上层应用程序
9) 广播服务
客户端的广播服务负责接收来自上层应用的数据发送请求并将其发送到P2P网络。具体处理工艺如下:
1计算数据的校验和其他数据元素信息
2对于当前节点链接池中的所有链接
a) 以校验和为索引,检查见证列表,并检查相应节点是否仍缓存此数据
b) 如果未缓存数据,则将数据元素信息发送到相应的节点
3将数据分成块,然后依次将每个块发送给所有相邻节点
4如果在数据传输过程中发现网络错误,请关闭与相应节点的链路,并将其从链路池中删除。
10) 去中心化全网数据转发应用实例
由此可见,广播业务只向本地节点的最近邻节点广播数据,通过上层应用可以实现数据的全网广播。具体实施如下:
1创建一个路由以连续接收来自P2P客户端的数据
2对于每个接收到的数据,通过P2P客户端发送到网络。这样,整个网络的数据广播就通过相邻节点间的中继传输来完成。
文章链接:https://www.btchangqing.cn/255213.html
更新时间:2021年05月11日
本站大部分内容均收集于网络,若内容若侵犯到您的权益,请联系我们,我们将第一时间处理。