安全可扩展性:互联网计算机的点对点层
互联网计算机区块链使开发人员能够使用容器智能合约完全在链上构建面向消费者的 dapp ,从而可以重新构想网络服务、DeFi 平台、社交媒体、NFT、游戏等等。
因此,互联网计算机被设计为安全、可靠和可扩展。
可扩展性是一个非常重要的因素,它主要依赖于网络中消息分发的效率,网络越大,必须分发的消息就越多。为此,互联网计算机网络被划分为子网。
每个子网都可以被视为较小的互联网计算机区块链,它们在选定的节点上运行容器,点对点(“P2P”)层是在同一子网的节点之间实现安全、可靠和可扩展的通信的一层。
互联网计算机协议有四个主要层:
执行管理用于确定性执行软件消息的安全环境。
消息路由在子网之间路由用户和系统生成的消息,管理应用程序的输入和输出队列,并调度消息以供执行。
共识选择和排序从用户和不同子网接收的消息,以创建可以在传递到消息路由层之前进行公证和最终确定的输入区块。
点对点从用户以及同一子网区块链中的其他节点收集和发布消息,点对点层接收到的消息被传播到子网中的其他节点,以确保平台的安全性、可靠性和弹性。
互联网计算机点对点层的三个主要挑战是安全性、性能和可扩展性。互联网计算机的设计即使是针对恶意节点也能确保安全,因此其点对点层和协议旨在即使在存在此类恶意节点(最多 1/3 的子网)的情况下也能保持运行。
这与其他传统的点对点设计不同,它增加了复杂性和性能的权衡,我将在下面讨论。点对点层以最小的性能开销实现了安全目标,同时仍然使子网能够扩展。
此外,互联网计算机的点对点层为消息提供了独特的优先级机制,这样可以更快地传送重要消息并通过不发送不需要的消息来节省带宽。
在这篇博文中,我将涉及互联网计算机的点对点层的以下几个方面:
要求
基本原则
与应用程序组件的交互
数据结构
八卦协议
带宽和内存注意事项
点对点层负责发送由上面的层(例如,共识)创建的工件,并负责接收、验证、处理和分发来自同一子网中其他节点以及来自用户的工件。点对点层保证,如果正确的节点向其对等节点发送工件,则该工件最终将被子网中需要它的所有正确节点接收。
这可以看作是可靠广播的一种特殊情况,是为我们的共识算法量身定制的,具有优先级。在某些网络假设下,它提供限时交付。
我们希望我们的点对点层在以下要求下提供这种保证:
尽管存在拜占庭故障,但限时/最终交付
为不同的应用程序组件/对等点保留资源
有界资源
不同工件的优先级
高效率
DOS/垃圾邮件弹性
加密、真实性和完整性
点对点使用八卦机制在子网中分发消息,八卦协议的原理是将您收到的消息或您创建的消息发送给子网中的对等方,其过程类似于谣言的传播。点对点中的对等点由覆盖网络拓扑确定,一切都保证在 O(diameter) 跳跃中传递,如果覆盖是无向连接的,则所有节点都遵循协议,并且不会丢弃任何消息。
点对点层被设计为即使在拜占庭节点存在的情况下也具有容错能力。如果一个节点表现出恶意(例如,不遵守协议,试图伤害其他节点或用户),或者如果它表现出一些错误行为(例如,不响应,不分发工件,遭受严重的网络延迟)。
因此,点对点层的设计考虑了在子网中拥有此类节点的可能性,并保证即使子网中多达三分之一的节点是拜占庭节点也能正确有效地运行。
在考虑拜占庭节点时,我们希望避免几个问题。第一种是所谓的日蚀攻击,其中某个节点的所有对等方碰巧是恶意的或有故障的,恶意节点可以串通并选择正确节点看到的工件,并将该节点与网络的其余部分断开。因为我们验证消息的真实性,恶意节点无法用欺骗消息欺骗诚实节点,但连接性问题仍然存在。
为了避免这种情况,我们必须使用覆盖来保证与足够多的对等点的连接,以便所有诚实的节点以非常高的概率形成连接。对于足够小的子网,一个节点可以连接到子网中的所有其他节点,形成一个完整的图,从而提供完美的日蚀攻击保护。对于较大的子网,例如网络神经系统 (NNS),我们将使用稀疏覆盖。
因为我们想保证在一定时间内所有依赖它们的节点都收到工件,所以八卦协议需要确保这些工件被交付,尽管可能存在故障链接和节点的问题。八卦协议通常基于传播模式,导致带宽的冗余和浪费。因此,以减少这些开销的方式设计此类协议非常重要。
工件可能很大,如果这些工件从多个对等点多次发送,则会导致严重的带宽浪费,这类似于不得不从多个朋友那里一遍又一遍地听到相同的谣言。在这个比喻中,你的朋友可以先问你是否听说过最新消息,而不是再告诉你谣言。在我们的上下文中,这对应于首先发送的广告。广告是小消息,仅包含工件的元数据和一些验证它们的方法,但不包含其内容,每个节点然后从至少一个对等方请求它需要的工件。
在我们的设计中,我们从询问一个对等点开始,但是如果遇到问题,我们可能会向另一个对等点询问相同的工件,这可能会重复,直到我们找到一个没有故障的诚实对等点。
广告包括由八卦协议及其应用程序组件用于完整性验证(例如,完整性哈希)和用于决策(例如,帮助组件确定工件优先级的属性)的字段。
一个节点可能会收到多个广告,因此可能必须选择首先请求哪些工件,每个广告都包含一些由创建它的客户端组件提供的属性。例如,共识工件包含一个 height 属性,它告诉相应工件的区块高度。共识还为八卦提供了优先功能,它接受一个广告(及其属性)并返回一个优先级值(最低的是“丢弃”,这意味着不需要这个工件,最高的是“立即获取”,这意味着最高优先级的工件)。
例如,如果共识现在处于高度 10,它可能更喜欢该高度的工件而不是高度 11 或 12 的工件,这取决于它们的类型以及可能的其他状态参数(作为一般规则,它更喜欢相同的高度而不是不同的高度),点对点使用这些优先级值来确定应该首先请求哪个工件。
点对点在工件池中存储接收的工件,它通知共识和其他客户端组件有关池中的更改,然后应用程序组件确定其关于池内容的下一步操作,工件池包含每个应用程序组件的所有可用工件。
我们将工件分类为“已验证”或“未验证”,后一类用于尚未验证的工件。验证意味着由客户端组件检查工件,例如,通过验证签名。如果需要,可以将客户端的工件池持久化到非易失性存储中,我们这样做是为了共识工件。
上面我们可以看到一个节点为八卦协议保存了哪些数据结构,左侧是工件池,它分为已验证和未验证部分,未验证的部分包含那些尚未验证的工件。每个未验证部分的大小是有界的,以防止坏节点填满工件池从而导致资源泄漏和拒绝服务攻击,但足够大以确保协议在正常情况下正确运行。
此外,对于每个对等点,我们维护其上下文,这有助于我们跟踪我们收到了哪些广告、我们向谁请求了哪些广告等等:
广告队列是从该对等方接收到的所有广告的优先队列,它们按优先级排序
请求的集合包含已经从该对等点请求相应工件的所有广告
接收检查缓存用于阻止对最近收到的工件的请求
这些是八卦协议处理的主要事件:
池中的新工件(由客户端组件在本地添加)
处理从对等方收到的新广告
处理从对等方收到的新工件
恢复和重新连接问题
池中的新工件(由客户端组件在本地添加)
当一个节点从客户端组件接收到一个新的工件时,它会为它创建一个广告,并将这个广告发送给它的所有对等点。
处理从对等方收到的新广告
当节点从对等节点收到广告时,它首先检查相应的工件是否已由节点本身下载或创建。如果不是,并且此广告的优先级高于“丢弃”,则将广告添加到发送它的对等方的广告队列中。如果工件池的未验证部分中有足够的空间供对等方使用,我们会专门为此对等方 i 调用一个名为 download_next(i) 的函数。
该函数获取最高优先级的广告(基于优先级函数分配的优先级),并从该对等方请求相应的工件。因此,我们没有必要请求我们刚刚收到广告的工件,我们将只请求具有最高优先级的工件。
请求工件后,相应的广告从广告队列移动到我们向其请求工件的对等方的请求集合。
我们可能在多个对等方的广告队列中拥有相同的广告,因为多个对等方可能向我们发送了相同的广告。广告将保留在其他对等方的广告队列中,直到我们收到实际的工件。在工件请求上设置超时,以防止无响应或缓慢的对等点,这有助于保证有限的时间交付。
我们将避免从我们已经提出请求的对等方请求工件,因为它可能行为不端。在这种情况下,我们会看到其他对等点是否已经发布了相同的工件,如果是,我们将在尝试无响应的对等点之前尝试从它们那里获取它。
处理从对等方收到的新工件
当我们从对等方收到工件时,我们首先通过检查相应的广告是否在对等方的请求集中来确保它是被请求的。然后我们使用相应的完整性哈希验证其完整性,如果这些检查中的任何一项失败,则意味着该对等方行为不端。
最终,我们从所有广告队列和请求的集合中删除广告,我们将工件添加到发送它的对等方的未验证池中,我们将把它留在那里让客户端组件检查和验证它。我们还将工件的散列添加到称为接收检查的小缓存中,每个对等点维护,以忽略同一工件的进一步广告。
这样做是为了为应用程序组件提供一些宽限期来更新它们的优先级函数,这样即使工件从池的未验证部分中删除,它们也不会再次请求相同的广告。如果我们在未经验证的工件池中仍有空间供此对等体使用,我们将根据优先级使用 download_next(i) 函数从中请求下一个工件。
传输和连接管理
在八卦组件下方,有一个传输组件,用于维护对等点之间的实际网络连接。传输组件负责尝试保持连接稳定,对于瞬态连接问题和拥塞情况,它有自己的缓冲区。它有一个内部机制来确保连接不会挂起并检测比平常更长的延迟,这对于提供限时交付很重要。
具有自己的 7 层标头的传输帧八卦消息,其中包含一些由传输组件用于维护流动和报告错误的元数据字段。目前,传输在对等点之间使用多个 TCP 流。
传输以适应这种分散式点对点网络的方式使用 TLS 1.3,没有证书颁发机构层次结构作为信任根。相反,信任的根是为节点提供自签名证书的注册表,以便节点可以对其对等方进行身份验证。
如果 TCP 连接中断,传输会定期尝试重新连接(只要相应的对等方仍在节点分配的覆盖层上)。当重新建立连接时,我们会清空相应的传输队列并开始接收新消息。
由于所有数据结构都有大小限制,这也适用于传输缓冲区。如果这样的缓冲区已满,或者如果我们一直在等待重新连接,传输最终会通知接收器八卦组件潜在的消息丢失。然后接收方可以发送重传请求。
重传请求是八卦协议的消息,它有一个过滤器来告诉接收者请求的发送者看到的最新工件。可能是在发送此请求时其他对等点已经成功发送了相同的广告,因此节点可能不需要在它错过的所有消息上赶上相应的对等点。
收到重传请求后,发送方节点根据请求中包含的过滤器发送所有相关广告,传输将这些广告发送给接收者。如果在此过程中队列再次变满,则将发送剩余广告的另一个重传请求。
总而言之,点对点层保证了子网中工件的限时交付。它使用广告-请求-工件模式和覆盖拓扑来减少带宽开销,并为客户端组件提供优先级 API,以确保首先交付最高优先级的工件。该协议具有容错性,并考虑了拒绝服务攻击和其他威胁。
开始在 smartcontracts.org 上构建并加入我们的开发者社区 forum.dfinity.org。
作者:Yotam Harchol(DFINITY 网络研究科学家)
翻译:Catherine
- 往 期 推 荐 -
DFINITY 开发者资助计划奖授予 102 项资助,价值 204 万美元
长按关注 DFINITY 微信公众号
随时答疑解惑
*添加小助手微信 comiocn 进交流社群