本文提出了FullDAS,一种用于数据可用性抽样(DAS)的网络堆栈,旨在支持32MB及以上的大区块。FullDAS通过优化数据分散和抽样过程,包括liteDAS抽样协议、主题路由、改进的连接机制以及2D编码等技术,旨在实现快速、高效和稳健的数据可用性,从而解决当前网络堆栈在处理大数据块时遇到的瓶颈问题。
作者:Csaba Kiraly,与 Leonardo Bautista-Gomez 和 Dmitriy Ryajov 合作,来自 Codex.storage 研究团队。
注意:本文档描述了我们目前的想法,是与其他团队合作努力和多次讨论的结果。如果没有 @dankrad , @djrtwo , @fradamt , @AgeManning , @Nashatyrev , @matt , @pop , 和 @Echo 的贡献和想法,这是不可能实现的。
最初的 Danksharding 提案 目标是 32 MB 的区块,并且这个大小主要是由于 DAS 数据结构 中使用的 KZG 承诺的计算约束而选择的。自那时以来,网络设计经历了各种迭代,旨在有效地使区块数据在 P2P 结构中可用,并允许节点从此结构中进行抽样。然而,这些构造都没有令人信服地支持 32MB 的区块,这使得网络解决方案的性能成为真正的瓶颈。在这篇文章中,我们研究了这些网络问题并提出了解决方案,目的是使 32 MB(甚至更多)成为可能。
DAS(数据可用性抽样)的目标是以高概率确定给定的数据区块已提供给任何感兴趣的人,并且在不要求系统中任何单个节点持有(甚至临时接收)整个数据区块的情况下做到这一点。
也就是说,我们希望将各个节点的带宽需求保持在当前(EIP-4844 之后)以太坊网络的水平,同时处理大几个数量级的区块。从网络的角度来看,这是对以太坊 DAS 设计的一个重要约束。
对于我们关于网络方面的讨论,重要的是要强调 DAS 有两个不同的部分:“使数据可用”部分和“抽样”部分。
首先,必须使数据可用。可用性意味着系统中的节点获得“足够”的数据,以便能够共同重建原始区块。因此,可用性是 系统级别的属性:数据要么可用于整个系统,要么不可用。至少,这是我们想要实现的目标。
与一般的 P2P 系统一样,数据的量最好不要“刚刚好”,而应该是 非常足够,这意味着即使存在流失、网络分区或大部分恶意节点,也可以重建数据。只有在这一点上,我们才能说数据已被提供。
换句话说,我们应该设计一个协议,以确保没有临界情况:数据要么不可用(未被来源释放),要么非常可用。正如我们稍后将看到的,正是纠删码和稳健且高度冗余的 P2P 网络结构之间的相互作用使这成为可能。
其次,是抽样。抽样是单个节点对提供给系统的内容的看法。它是一个节点说服自己数据已被提供,并且它为此使用的技术是检索区块的几个部分。sample(样本) 是要检索的片段的(通常是随机的)选择,而 sampling(抽样) 是检索这些片段。如果此抽样成功,并且在一些 独立性假设 下,节点可以说服自己数据确实已被提供。
重要的是,在后台,在概率计算 背后,存在那些令人讨厌的独立性假设。基本上,假设数据是(过去是,或者将来是)独立于选择的样本而发布的。不幸的是,这可能会被利用,并且区块生产者及其“同伙”对节点的样本选择了解得越多,引入相关性从而愚弄某人就越容易。因此,sample selection(样本选择) 和 limited disclosure of the selection(对选择的有限披露) 是安全保证的重要组成部分。
注意:在这篇文章中,我们将区块的片段称为 segments(片段),但当使用 1D 编码时,它们也称为“column(列)”,当使用 2D 编码时,称为“cell(单元格)”,或者有时,令人困惑的术语“sample(样本)”既用于片段,也用于所选片段的列表。
另请注意,抽样并不是我们可以用来“说服自己”数据可用的唯一技术。在不尝试列出所有可能性的情况下,我们可以使用简洁的证明、受信任的朋友等。然而,抽样是无需信任的,并将数据片段传播到系统中的所有节点,最终实现额外的冗余层,从而实现恢复。
无论是在提供数据时,还是在节点进行抽样时,区块的片段都会传递到节点。但是,哪些片段传递到哪个节点是由这两个阶段中的不同目标驱动的。
我们称应该传递到节点的片段为它的 interest(兴趣)。系统中存在两种类型的兴趣。它们相似,但用途不同,并且存在一些根本差异:
Interest(兴趣)可以 change over time(随时间变化),例如从 epoch 到 epoch 的样本选择,或者对于托管,还可能会有其他的时间粒度。改变它或保持它的固定性都对安全性和网络效率产生影响。
数据可用性和抽样的需求之间的根本差异,以及托管和样本的属性之间的差异,也反映在网络设计中。我们可以区分片段分布的两个阶段:
这两个阶段可以使用不同的 P2P 网络结构。在下文中,我们重点介绍这些网络结构,为分散和抽样设计快速、稳健和带宽高效的协议。
FullDAS - LossyDAS - liteDAS - 数据可用性抽样组件960×720 80 KB
在最初的设计中,计划使用 GossipSub 进行分散,包含许多主题(512 个用于列,512 个用于行),将列和行分发到所有 stake 节点(带有验证器的信标节点)进行托管。相反,对于抽样,计划从所有完整节点(stake 和非 stake)设置一个单独的 DHT,为所有抽样查询提供服务。正如我们在相关的帖子和论文中强调的那样,这带来了一些挑战。
因此,在 PeerDAS 和 SubnetDAS 中,我们调整了设计以提供中间解决方案,在功能和可扩展性方面都做出了妥协。
在 PeerDAS 中,我们修改了托管分配和分散,使其基于 NodeID,使所有完整节点(stake 和非 stake)都成为托管系统的一部分。然后,使用节点现有对等节点的 Request/Response (Req/Resp) 协议从该 P2P 结构进行抽样,从而增加了对等节点发现 (Discv5) 以及节点必须维持的对等节点数量的压力。
相反,SubnetDAS 修改了设计,以始终使用 GossipSub 分发机制,用于分散和抽样。同样,这限制了我们的可能性,也牺牲了抽样查询的不可链接性。
即使对于几个 MB 的区块来说,这些的快速且带宽高效的实现也证明具有挑战性,这就是我们得出主要主题的地方:如何使 DAS 适用于 32 MB 及以上的区块?
在下文中,我们将介绍堆栈的重要部分:
从抽象层面来说,抽样听起来很简单:
然而,实际上,事情变得复杂得多。在我们关于 LossyDAS、IncrementalDAS 和 DiDAS 的文章中,我们处理了一些与样本选择相关的复杂性,但我们在该文章中遗漏了所有网络方面的内容。
为了设计抽样协议,除了上面的草案大纲之外,我们还应该回答以下问题:
此外,我们应该设计一种快速、稳健且带宽高效的协议。
对于抽样,我们提出 liteDAS,这是一种新的 Req/Resp 协议,旨在以接近最低的带宽使用量提供接近最低的抽样延迟,从而避免在正常路径和出现问题时过度利用资源。liteDAS 背后的关键观察结果是:
我们提出的 messaging primitive(消息传递原语) 是 带有显式超时时间的请求。这个简单的原语允许我们尽早开始抽样(在 slot 开始时),并且可以构建一个很好的动态行为,初始阶段用于处理正常路径,第二个阶段用于处理潜在问题,如下所述:
在 T_0(slot 开始时,或者当公共参数已知时)
直观地说,这很快(将抽样延迟降低到接近最小值)、带宽高效(在正常路径上每个片段仅发送一个 Req/Resp)且稳健(一旦完成托管分配,便会探索抽样选项)。
在 slot 开始时发送抽样查询使我们能够将抽样延迟最小化到分散延迟之上的单个 1 跳延迟(我们查询的节点接收到片段或列的延迟)。
更详细地说,为了理解为什么这很快,让我们看看最快的情况是什么。如果节点在知道它需要什么样本时,立即询问所有可能拥有该样本的对等节点,即计划托管该片段的所有对等节点,那么就可以实现最小的抽样延迟。然而,这意味着我们的节点会收到大量响应,从而增加了相当大的额外负载。在 liteDAS 中,我们一次只询问 P 个对等节点,这是带宽效率和延迟之间的折衷方案。 我们关于 GossipSub 延迟分布的数据 和我们最初的模拟表明,在正常路径上,延迟折衷方案非常有限。
该协议在正常路径上准确地接收每个样本(或列)一次。在非正常路径上,我们可以通过更改稍后阶段的 P 来在遵循具有较短超时时间的顺序逻辑或允许一些并行性(从而产生重复项)之间进行折衷。重要的是,如果数据实际上不可用,它仍会将资源利用率保持在限制范围内。
在第一阶段,上述抽样的稳健性依赖于分散的稳健性。分散已经采用了许多可靠性技术,因此,在正常路径上,对于每个 ID,我们选择的单个节点很可能收到样本。
相反,如果分散存在问题,我们的抽样对延迟的敏感性也会降低:无论如何,在通过托管广泛提供可用性之前,抽样都不应成功。因此,我们有时间“寻找”片段。在初始阶段之后,我们的协议将循环遍历可能托管同一片段的其他潜在对等节点。届时,我们还可以并行发送更多查询,最终允许一些重复项。
除了基本思想之外,还有一些其他的调整可以改善动态行为:
liteDAS 仍然假设我们拥有要向其发送请求的对等节点。如果我们没有这些对等节点,并且我们必须搜索托管给定 ID 的对等节点该怎么办?如果我们在请求片段之前还必须完成复杂的连接过程该怎么办?
正如之前强调的那样,我们可以预计到对托管对等节点的搜索。尽管如此,有时我们确实需要搜索托管特定 ID 的对等节点,并且这应该相对较快。这是目前围绕 DAS 讨论中争论的关键点。作为抽样过程的一部分,我们需要在几秒钟内找到并连接到对等节点,这似乎是主要的限制因素之一。当构建用于高效的基于列(/行)的分发的网格时,分散也存在类似的问题,尽管在这种情况下,时间没有那么关键。
AgeManning 在 PeerDAS 规范讨论的一部分 中很好地总结了当前协议堆栈的问题。使用当前的堆栈从新对等节点获取单个片段的效率非常低。显然,这个问题有两个主要的潜在方面:
首先,让我们看看我们可以做些什么来快速找到给定片段的托管节点。关键在于明智地分配托管。
由于我们需要系统范围的可用性,因此必须正确分配托管,以提供良好的覆盖率。随机的本地选择可以提供这一点,但幸运的是,我们可以做得更好。托管的一个优点是我们 不需要隐藏谁托管什么。我们可以使用此属性,通过以确定性的方式 从 NodeID 导出托管兴趣(最终使用一些轮换方案并使用公共随机性),从而使我们的系统更加高效。似乎公开节点的托管兴趣不会影响安全性。似乎我们也可以提前公开披露兴趣(使托管在时间上保持稳定,类似于我们今天对证明所做的那样),并且这仍然不会产生安全问题。
请注意,这里有一个问题:通过使用 NodeID,我们没有像最初的提案那样将托管绑定到验证器,而是绑定到完整节点(包括未 stake 的节点)。因此,我们无法真正强制执行托管。我们目前无论如何都不想强制执行它,但稍后我们可能会引入 Proof Of Custody(托管证明),届时我们必须重新审视这一点。创建大量新 NodeID 也很容易,这可能会使托管面临有针对性的女巫攻击。
通过从 NodeID 导出托管,我们可以通过两种方式加快搜索速度。首先,我们可以从 nodeID 的最左边位导出托管。这使我们能够使用 Discv5 Kademlia 搜索而不是随机游走,因为 Kademlia 是基于前缀的。其次,如果使用托管轮换方案(节点会定期更改他们托管的列/行),我们可以从 NodeID 计算出这一点,而无需联系对等节点或从 Discv5 获取更新的 ENR 记录。
我们已经在 PeerDAS 中使用了这个基于 NodeID 的确定性托管分配技巧:它使我们能够使分散更有效,并且还允许抽样对等节点更轻松地找到托管节点,只需基于 NodeID 和与 ENR 中的 NodeID 一起发布的一小部分元数据即可。
请注意,样本的情况并非如此,我们确实关心使确定给定节点将对什么进行抽样变得相对困难,否则我们将很容易攻击单个节点。因此,我们无法从 NodeID 导出样本(片段 ID 列表),并且我们也最好避免将整个样本(再次,是 ID 列表,而不是数据)发送到单个节点。因此,我们更喜欢节点即时请求样本,最好有选择地向不同的对等节点公开兴趣,从而限制单个节点的暴露。
我们掌握的另一个选择是直接将托管节点搜索引入我们的协议中,从而规避 Discv5 的困难。
在当前的提案中,列是使用 GossipSub 分发的,不同的列 ID 映射到不同的 GossipSub 主题。列 ID 空间被视为一个平面列表,而不考虑主题之间的任何关系。
然而,我们不必将行和列 ID 空间视为平面 ID 空间。我们可以使用几乎任何距离度量,并要求节点保持一些与其列/行 ID 接近的邻居,从而实现更快的搜索。以下是一些解释这可能如何工作的示例:
[C-D, C+D] mod NUM_COLS
范围内的邻居,其中D
和N
是选定的C+2^j mod NUM_COLS
的至少 N 个邻居,其中 j in [0..log2(NUM_COLS}-1]
第一个(循环)的可扩展性不是很好,最后两个具有良好的可扩展性。然而,如果我们将列数(和行数)保持得足够低,那么这些中的任何一个都足以找到任何 C 的潜在邻居。如果我们想扩展得更高,我们可能想选择最适合我们使用的那一个。
请注意,主题 ID 空间是密集的,每个 ID 代表一个主题,并且我们期望拥有的节点数量大于主题数量。相反,在典型的 DHT 中,密钥和节点 ID 在 ID 空间中是稀疏的。拥有密集的 ID 空间使我们能够简化搜索。
相对容易扩展上述任何一种技术来处理行和列,可以通过将列和行 ID 空间视为两个单独的 ID 空间,或者通过定义一个联合距离函数来实现。
另请注意,当我们在 2D 中进行抽样时,我们要么查找列 C 中的节点,要么查找行 R 中的节点。任何一个都足够了,这使我们的搜索更快。
连接问题主要是由于协议限制造成的,因为我们在 libP2P 之上运行,而 libP2P 最初并非设计用于快速连接。我们通过严格限制连接的对等节点数量,并使许多节点的连接数量已满来使我们的生活更加艰难(众所周知,某些对等节点不接受连接,因此其他对等节点会过载,其对等节点计数已满,因此也不接受新连接)。
我们在下面列出了此问题的一些可能的解决方案:
我们认为这些可以解决连接问题,使我们能够实现 FullDAS。但是,还需要进行更多测试。
最初,我们打算使用 GossipSub 进行分散,原因有几个。它是一种发布-订阅协议,可以很好地映射到纠删码结构,为每列(如果使用 1D 纠删码)或列和行(如果使用 2D 纠删码)创建单独的主题。它也经过了实战检验,已经在以太坊中用于区块扩散和证明聚合,显示出快速可靠的操作,如 我们相关的帖子测量区块扩散和证明的延迟分布 中所讨论的那样.
在 PeerDAS 中,我们实际上是将分散问题映射到相对少量的 GossipSub 主题。虽然这是一个合理的第一个方法,但有些方面是分散问题所特有的,并且允许进行性能优化。
我们已经使用 我们自定义的 DAS 模拟器 研究了区块可以使用多快的速度分散到托管中,无论是在 1D 还是在 2D 纠删码编码的情况下。正如我们在 EthereumZurich'23 的演讲 和后来的演讲 (EDCON'23, EthPrague'23, EthCC'23) 中所展示的,如果正确填充了列和行主题,GossipSub 可以在几秒钟内将区块数据分散到数千个节点。然而,在这些演讲中,我们提到 GossipSub-like 发布-订阅协议是有原因的。就目前而言,GossipSub 并不是我们拥有的最佳选择。我们认为我们可以进行一些更改,使其更好地适用于我们的情况。最终,我们也可能会导出一个专门针对分散用例的自定义协议。
在下文中,我们列出了 GossipSub 主题和分散的一般用途之间的一些可能差异,展示了一些可以进行的优化。我们将专门用一篇文章来详细扩展这些内容。
在 DAS 描述中,纠删码主要被用作一种使抽样更稳健的工具。然而,我们应该强调的是,我们可以在设计中使用纠删码来实现两个目的:
放大抽样 很容易理解:使用比率 R=K/N(例如 1/2)的代码,并假设数据不可用,则每个抽样的片段都将无法发现数据不可用的机会降低了 2 倍。我们喜欢这种指数属性,它使我们仅通过抽样几个片段就可以达到非常低的误报 (FP) 率。在 2D 情况下,比率不如 1D 好,但我们仍然具有很好的指数属性。
放大可用性 是一件不同的事情。这意味着,如果数据可用,我们会使其非常可用。我们通过在分散期间使用 in-network repair(网络内修复) 来实现此目的。这是我们的纠删码结构和分散网络结构交汇的地方。通过根据代码(在列和行中)来组织节点,并通过使节点同时参与行和列,我们可以在分散期间启用 EC 结构中的本地修复。
正如我们在 EthereumZuri.ch'23 讨论 中的模拟中已经展示的那样,这种网络内修复正在放大可用性。基本上,如果没有发布足够的样本,则网段计数将保持在 75% 以下,而验证器和许多构造中的完整节点使用的基于行/列的抽样 (SubnetSampling) 仍然非常低。网段抽样也仍然非常低。
相反,如果发布了一个以上的网段,其结果将通过分散结构放大到几乎 100%。
然而,为了使这种放大机制起作用,我们需要 2D 代码。我们无法在 1D 情况下真正做到这一点,因为在 1D 情况下,只能在拥有 K 个片段的节点中进行修复,基本上是整个区块。相反,在 2D 情况下,我们可以在任何单个行或列中进行修复,因此各个节点可以修复然后发送。换句话说,我们需要具有本地修复能力的代码。我们可以使用 2D RS 制作这样的代码(如果我们愿意,还有其他具有本地修复能力的代码构造)。
因此,虽然我们可以通过多种方式将网段 ID 映射到托管,但我们通过列和行来执行,以在分散期间启用网络内修复和可用性放大。
我们撰写本文的目的是概述 FullDAS 的主要构建块,这是我们为具有 32MB 或更大的区块的 DAS 提出的网络堆栈。我们讨论了将区块数据分散到托管 P2P 结构中的新方法,同时还放大了数据的可用性。我们还展示了使用 liteDAS、主题路由和改进的连接机制,从此结构实现快速、带宽高效和稳健的抽样所需的工具。
在这一点上,很多人可能很明显,我们正在构建类似于 DHT 的东西,过去曾多次提出这一点:分散到托管和抽样之间的区别,以及 DHT 的通用概念并没有那么大。使用 FullDAS,我们实际上正在构建一个专用分布式存储结构,具有自定义播种、修复和检索,每个都针对 DAS 编码和 DAS 目的进行了优化。
以上一些技术已经在模拟中进行了评估,而另一些技术正在进行中。我们为此目的编写了两个模拟器:
这两个都在进行中,我们计划在 FullDAS 协议的改进和评估继续进行时发布更多帖子。
我们之前关于采样技术的文章:LossyDAS, IncrementalDAS, 和 DiDAS
使用 Kademlia DHT 进行 DAS 的可扩展性限制
我们关于测量 GossipSub 延迟分布的文章,包括用于区块和用于证明时
我们之前关于 DAS 的演示文稿:
我们的 DAS 模拟器:
具有高级抽象的 DAS 模拟器,用 Python 编写,用于大规模实验
具有较低级别抽象的 DAS 模拟器,使用 nim-libP2P 堆栈直接通过 Shadow
- 原文链接: ethresear.ch/t/fulldas-t...
- 登链社区 AI 助手,为大家转译优秀英文文章,如有翻译不通的地方,还请包涵~
如果觉得我的文章对您有用,请随意打赏。你的支持将鼓励我继续创作!