P2P层简述

P2P 层主要负责在子网里的副本之间传送协议消息。这些消息有达成共识所需的消息,比如区块提案和公证等,还有来自消息路由层的入口消息。当边缘节点发送消息时,副本的 P2P 层就会接收和广播这些消息。


这些消息主要有两类:一类是用于达成共识的签名消息,另一类是用户客户端发送的输入消息。对于用户发出的输入消息,P2P 层会把它们排好顺序,这样共识层就可以按照顺序把数据打包成荷载,并生成区块了。

工件

比如我们有一家中子星快递公司(IC),而 P2P 层就是快递公司的配送网络,负责在地区(子网)内的配送点(副本)之间传输包裹(信息)。

P2P 层就是个广播通道。P2P 层的设计能确保如果一个诚实的配送点(副本)广播了一条消息,那么这条消息最终将会被子网中的所有诚实副本所接收。即使有人试图恶意干扰,部分网络偶尔中断的情况下,包裹仍然能够高效地送到收件人手中。即使有副本出现故障也不能影响到诚实副本之间的相互通信。

image-20230622184950322

每个配送点(副本)里面有一些包裹,这些包裹就是 “ 工件 ”(Artifacts)。所以每个配送点(副本)都有一个 “ 工件池 ” ,存放自己的信息。工件是配送点之间用来创建、验证和达成共识的信息。这些信息可以是共识区块提案、用户的入口信息或用于 https 外调功能的响应签名。配送点会把这些包裹分发给其他配送点,让它们都知道子网的状态。

image-20230622183845786

当需要把包裹(工件)发送给其他配送点时,P2P 层会被调用。这就像是快递公司经理(比如共识层的组件)通知配送员,他们需要把一个新包裹送出去。比如现在某个配送点(副本)创建了新的区块提案,需要发送给子网里的其他配送点。再比如配送点(副本)收到了另一个配送点发来的包裹,然后要把它转发给其他地方。

公告-请求-传递

P2P 层要负责保障高吞吐量,高吞吐量比低延迟更重要。

但是在共识协议中,一些消息,尤其是区块提案非常大。而且根据共识协议,为了安全,这些消息会被所有副本反复广播。

他们希望尽可能快地传递大量的包裹(高吞吐量),但同时也要考虑运输成本(带宽)。

快递公司采用公告-请求-传递机制来提高效率。当一个配送点(副本)有一个重要的包裹(大消息)要发送时,他们不会直接发送包裹。相反,他们会发送一个包裹清单(公告 / Adverts),告知其他配送点有一个重要的包裹。当其他配送点收到这个清单时,确认了这就是他们需要的包裹,他们会主动联系发件配送点(请求)并要求传递这个包裹(传递)。这个过程可能会牺牲一些时间(延迟),但它能够节省运输成本(降低带宽使用)。对于小包裹(消息)而言,不值得牺牲延迟追求带宽。可以省去公告,直接发送消息。

为了节省带宽,P2P 层会创建一种叫做公告的简短消息,它非常小巧,只包含工件的哈希值和一些元数据,然后将这些消息广播给其他副本。当其他副本收到公告时,它们会判断是否想要下载相关的工件。如果答案是肯定的,它们就会向发布公告的副本发送一个明确的请求消息。

image-20230622182359087

如果这个快递公司经营有方,发展到非常庞大时,包含了很多配送点。这时,公告-请求-传递机制可以在一个 覆盖网络(Overlay network) 上运行。在这个覆盖网络中,每个配送点只和它们的合作伙伴(对等节点 / Peers)互相发送包裹。当某个配送点想要广播一个包裹时,他会先把包裹的清单告诉自己的合作伙伴。那些合作伙伴在收到清单后,可能会请求包裹的传递,并在满足特定条件的情况下,把这个包裹的清单告诉自己的合作伙伴。这就像一个八卦网络(gossip network),一传十,十传百。如果子网的副本数量比较少,会将公告发送给子网中的所有副本。

快递公司(P2P 网络)可以在牺牲一定的延迟的情况下,有效地降低运输成本(带宽使用),实现高吞吐量的目标。这对于一个高效的快递公司(分布式网络系统)来说非常重要。

image-20230622191625809

但是可不要大意了,为了确保每个包裹完整、安全、高效送达,每个公告都包含了一个完整性哈希值,就像包裹的条形码。在完成包裹下载后,配送点会检查下载的内容,确保它和公告中的哈希值匹配,这样才能确保包裹的完整性。

当然只靠哈希还不够安全。恶意配送点可能会发送一个公告,然后发一个伪造的包裹,这个包裹的哈希值与公告中的哈希值匹配。这时候,配送点需要检查包裹是否符合要求(比如看包裹有没有正确的签名),在进一步处理或转发给其他配送点之前,要确保包裹是安全的。

当发现收到的公告有问题或者加入新子网时,配送点会向其他配送点发送重新传输请求。这个请求可以发送给一个特定的配送点,也可以发送给所有的配送点。请求中包含了关于当前状态的信息,其他配送点可以通过发送公告来帮助这个配送点更新自己的状态。在这里了解更多。

分块

有时候,某些包裹(比如状态同步工件)太大了,没法整体发送。我们可以把它们切成若干个小数据块(Chunks),然后用一个公告代表这些数据块。

image-20230622190057801

下载这些数据块的时候,配送点会尝试从多个曾经发过公告的配送点那里下载相应的数据块。这样可以加快下载速度,更好的利用带宽。分块的包裹会进行单个块和整体的验证,由相应的配送点负责单个块的验证。

重传请求

快递公司需要确保包裹能准时送达。有时候,因为某些原因,包裹清单(公告)可能会在途中出现问题,比如快递员忘记扫描包裹的条形码、运送超时了或者包裹清单丢了。或者有新的配送点加入子网时。

这时配送点就得发送一个 “ 重传请求 ” 了,类似于询问:“ 嘿,我有没有遗漏什么包裹?我有没有错过什么信息?请重新给我发一遍。”

其他配送点就可以将他错过的信息发送给他。虽然重传请求主要是为了帮助配送点同步错过的包裹,但为了确保包裹准确投递,配送点之间会定期发送这样的请求。

传输

快递公司的核心业务是在各个地点之间传递包裹。P2P 层底层的传输组件,就是快递公司的运输工具(卡车、飞机等),负责把包裹从一个地方送到另一个地方。这些传输工具在配送点之间创建基于 TLS 的 TCP 连接,双方都用自己的私钥验证身份。传输层协议会根据网络状况、包裹大小等因素来选择合适的方式。为了确保包裹可以顺利传输(Transport),协议具备一定的容错能力和对网络故障的处理能力。

为了让配送点之间知道他们应该与哪个配送点建立联系,快递公司需要维护一个包含所有配送点信息的 “ 名册 ”(网络神经系统(NNS)注册 Canister )。这个名册会包含配送点的地址以及用于身份验证的特殊标识。

每个副本都有自己的公钥,存储在一个叫做 “ 网络神经系统 ”(NNS)的地方。为了防止 DOS 攻击,副本只和同一子网中的其他副本联系。副本之间的连接会根据 NNS 的记录进行调整。

NNS 注册表还包含最新的子网成员信息(哪些副本属于哪个子网)以及历史信息。副本通过查询 NNS 的注册表来了解其自身的成员资格、副本、IP 地址和公钥。副本在建立 TLS 连接时,就可以确保只连接到同一子网内的其他副本,实现双向身份验证。

随着时间的推移,快递公司可能会开设新的配送点或关闭一些旧的配送点。因此,传输组件需要不断跟踪这些变化并相应地调整与配送点之间的联系。

此外,传输组件还需要确保通信线路畅通无阻,并在出现问题时自动重新建立联系。传输组件提供了一种保持连接稳定的机制,能够迅速检测到连接问题(通过心跳机制),并在连接断开时自动重新建立连接。当一个 TCP 连接空闲超过 200 毫秒时,系统会发送一个心跳消息。在接收端,如果 5 秒内没有收到任何数据(包括心跳消息),连接将会中断并尝试重新连接。这种做法避免了等待 TCP 协议可能非常漫长的超时时间,这种情况有时会在互联网路由发生变更时出现。在成功重新建立连接之后,将会发送重传请求至相应的副本。

有时候,传输组件也会与被注册表刚刚删除的配送点(副本)连接,直到共识层不需要这样的连接。

总结

P2P 层通过公告-请求-传递机制高效传输包裹,同时使用完整性哈希值和其他检查手段来确保包裹的正确性。传输组件负责在快递员和分拣中心之间传递包裹信息。它使用一种名为重传请求的方法来确保没有错过任何关键信息,并在需要时进行身份验证和重连。通过多种机制为信息传输提供高效、安全、稳定的通信基础。

这就是关于 P2P 层的介绍啦,接下来看看 IC 的共识层是怎样运行的!