本文提出了一种新颖的数据可用性抽样(DAS)和分片blob内存池的设计,旨在增强可扩展性并保持去中心化。该设计通过引入分片blob内存池和部分列广播,实现了分布式区块构建,从而降低了网络带宽需求,并消除了执行层(EL)和共识层(CL)之间的网络冗余。
本文提出了一种用于数据可用性抽样(DAS)和分片 Blob 内存池的新颖设计,旨在增强可扩展性,同时保持去中心化。传统的 Danksharding 策略假设一个区块构建者/提议者创建一个区块,对其进行纠删码编码,然后将完整的数据分发到整个点对点(P2P)网络。这在网络带宽方面要求很高,特别是对于小型家庭质押者,区块构建者和提议者是同一个节点。本文中的提议通过借助两个新思路来实现分布式区块构建(DBB)来克服这个问题:i) 分片 Blob 内存池,以及 ii) 部分列传播。
本文的其余部分组织如下。首先,阐明作为这个新设计基础的底层假设。然后,介绍当前的 DAS 和 Blob 内存池设计。最后,阐明所提出的设计及其随之而来的好处。
以下是我们在本文中使用的主要假设。
网络规模:以太坊当前的网络规模估计约为 10,000 个节点。对于本文,我们假设网络规模将保持在 5,000 到 50,000 个节点之间,但需要理解的是,这可能会在未来几年发生变化。
区块结构:我们假设所有数据 Blob 都是由 512 字节的元素组成的,这些元素被称为“单元”,然后使用纠删码(Reed Solomon)将它们分组和扩展,以创建一个二维矩阵。
Slot 吞吐量:我们的目标吞吐量是每个 slot 256 个 128KB 的 Blob,在使用纠删码扩展之前,总计每个 slot 32 MB。因此,在经过 2D 纠删码扩展后,大小为 128MB。
数据传播:Gossipsub 用于在 P2P 网络内的多个通道中,在共识层(CL)传播数据。我们假设 Gossipsub 可以扩展到一千个主题甚至更多。
一个区块及其 Blob 的整个 slot 周期可以用以下四个步骤来描述。
在以太坊网络中,Blob 通过类型 3(0x03
)交易提交。自从 Pectra 以来,该交易可以包含一个或多个 Blob,最多九个。类型 3 交易通过 devP2P 网络进行 gossip 传播。这意味着,首先将交易的哈希值推送给所有 peer 节点,然后节点可以决定拉取交易和相关的 Blob 数据,这些数据在 BlobTxSidecar
中传输。如果节点不需要,则 不需要 下载类型 3 交易或 Blob 数据。想要构建和提议区块的验证者节点应该监控网络中的交易,包括类型 3,并且应该将所有 Blob 下载到它们的内存池中。Blob 数据进入执行层(EL)Blob 内存池,在那里等待包含到区块中。当节点被选择提议区块时,它将包含其内存池中的一些 Blob,前提是它们的可用性已经得到验证。任何节点都可以选择下载所有 Blob 数据用于其他目的(例如,监控、研究)。
一个区块由两个主要部分组成:执行负载和 Blob 数据。执行负载不包含 Blob 数据,它仅通过类型 3 交易引用 Blob。区块构建者/提议者选择将哪些 Blob 包含在区块中,以及以什么顺序包含。在完全规模下,它选择每个 slot 最多 256 个 Blob(每个 128KB),从而在纠删码之前产生总共约 32MB 的 Blob 数据。区块构建者通过 Reed-Solomon 编码在水平和垂直方向上扩展这些数据,从而产生一个 128MB 的区块。
区块构建者/提议者将执行负载广播到网络以进行验证,并通过 Gossipsub 通道传播整个行和列。CL 节点仅保管(即存储)区块中所有行和列的一小部分。保管的行数和列数由每个节点决定,但每个节点必须保管最少数量的行和列。一些节点可以决定保管所有行和列,使它们成为超级节点。CL 节点接收执行负载,以及它们通过 Gossipsub 保管的整个行和列。CL 节点在其以太坊名称记录(ENS)中告知其他节点它们的保管大小。行和列是从节点 ID 确定性地派生的,因此任何节点都可以知道其 peer 节点保管哪些行和列。
CL 节点共同确保所有 Blob 都可以检索,而无需每个节点都存储完整的区块(128MB)。由于 Blob 使用纠删码进行扩展,即使是部分 Blob 数据也允许完全重建(如果可以获得足够的数据)。CL 节点执行随机抽样以验证数据可用性。每个节点选择一些随机单元来从其 peer 节点抽样。它知道哪些 peer 节点保管哪些列/单元,因此它可以向它们请求。或者,它可以将请求发送给多个 peer 节点 并让任何节点响应。
这个新设计的主要目标有三个:
在本节中,我们介绍这个新设计中引入的新概念。
每隔几秒钟下载数千万字节的 Blob 数据可能会给 Internet 带宽有限的家庭质押者带来压力。因此,我们提出了一种水平分片内存池设计,以便 EL 节点只需要下载部分 Blob。主要思想是基于节点的节点 ID 和它们将存储的 Blob 的类型 3 交易的哈希值来分片节点:如果且仅当类型 3 交易的哈希值的最后 4 位与其节点 ID 的最后 4 位匹配时,节点才应该下载类型 3 交易及其相关的 Blob。这创建了 16 个不同的分片,其中所有类型 3 交易和 Blob 都是不相交的。EL 节点下载到其内存池中的相同 Blob 与 CL 节点必须保管的相同行相同,因此无需通过 CL 网络下载行;它们可以通过从 EL 到 CL 的 getBlobs
获取。这意味着对于每个 slot,节点将根据类型 3 交易的哈希值来保管不同的行。不过,基于 peer 节点的节点 ID 和 slot 的执行负载,计算出 peer 节点为给定 slot 保管哪些行 ID 应该相当简单。对于这个例子,我们使用了 4 位(16 个分片),但不需要是 4;它可以是任何数量的位 B
,用于分片我们想要每个区块拥有的 256 个 Blob。这减少了网络带宽,同时在区块创建后加速了 CL 层的数据传播。
需要强调几个要点。由于行保管基于类型 3 交易哈希,因此节点必须存储的 Blob/行数从一个 slot 到下一个 slot 并不相同,因为它取决于哈希和每个交易的 Blob 数量。但是,平均而言,所有节点在统计上存储相同数量的数据。相反,对于给定的 slot,并非所有节点都存储相同数量的行。尽管如此,所有 Blob 在节点之间平均分配并稳健地复制。这种策略通过消除 CL 中 Blob/行的传播来避免 EL 和 CL 冗余。另一种可以使用的策略是验证者保管:要存储的 Blob/行数可以直接与节点中验证者的数量成正比。例如,节点的要求可能是匹配节点 ID 的最后 B
位,而对于具有验证者的节点,它可能是匹配最后 B-1
位。拥有更多验证者的节点可能更经常提议区块;因此,在它们的 Blob 内存池中拥有更多 Blob 有助于它们更快地构建区块。此外,从经济角度来看,拥有多个验证者的节点可能拥有硬件和网络资源来保管更多 Blob/行。
列与 Blob 不同,因为它们只有在构建区块后才知道。因此,只有在区块构建者/提议者决定包含哪些 Blob 以及以什么顺序包含后,才能传播列,甚至部分传播。在这个提议中,CL 节点有一定数量的列要保管,并且列的精确索引是从节点 ID 确定性地决定的,与之前的设计方式相同。这些列索引在节点的整个生命周期内保持不变。这意味着,与行相反,节点总是在每个 slot 存储相同数量的列,并且始终是相同的列。行和列之间的这种不一致对于优化网络带宽利用率至关重要。同时,它实现了稳健的数据保管和快速抽样。
与整个列传输相反,部分列传输是这个新设计的关键部分,因为通过水平分片内存池,大多数节点在接收到执行负载时将无法传播整个列。因此,部分列传输对于传播部分数据和加速区块扩散是必要的。例如,如果 Blob 内存池被划分为 16 个分片,那么要获得一个完整的列,节点将需要在该列的 gossipsub 主题上接收 16 条部分列消息。通过在每个节点收到执行负载后立即传播部分列,网络不需要依赖区块构建者/提议者的上传速度来获得它们各自的列。当区块提议者是上传带宽有限的家庭质押者时,这一点尤其重要。此外,即使所有 EL 节点都在它们的内存池中拥有所有 Blob 并共享完整的列以避免区块提议者瓶颈,它们仍然会上传整个列。相比之下,这种设计允许每个节点仅发送 1/16 的列,从而减少带宽消耗。
这个设计与现有设计的主要区别在于引入了分片内存池。在这个设计中,节点仅下载一定数量的类型 3 交易和相关的 Blob sidecar(即 Blob 数据)。每个节点必须保管的 Blob 是从节点 ID 以确定性的方式计算出来的,这样每个节点都可以知道要为自己下载哪些 Blob,也可以知道它的 peer 节点保管哪些 Blob。每个节点应该下载并存储在其 Blob 内存池中的类型 3 交易数量有一个最小值。拥有验证者的节点可以在它们的 Blob 内存池中保管更多的 Blob,类似于验证者保管。节点可以选择将每个 Blob 都下载到它们的 Blob 内存池中,要么是因为它们有很多验证者,要么是因为它们需要它来完成它们的任务(例如,区块构建者、rollup、浏览器)。
目标是引入每个 slot 256 个 128 KB 的 Blob,在纠删码之前总计 32 MB 的 Blob 数据。通过这种新设计,区块构建者/提议者有一个有限的(即分片的)类型 3 交易列表可以附加到它的区块中。它可以决定只附加来自其受限列表的 Blob。但是,还有另一种策略。由于区块提议者是提前知道的,因此必须在下一个 epoch 中提议区块的节点可以暂时改变其 Blob 内存池的行为,开始下载所有类型 3 交易和 Blob,直到区块被提议的那一刻,届时它们可以恢复到标准的 Blob 内存池行为。
区块构建者/提议者应该传播的第一件事是执行负载,其中包括附加到区块的类型 3 交易和 Blob 的列表。
CL 节点需要保管(即存储)来自 EC 扩展区块的一些行和列。在这个设计中,我们建议 CL 必须保管的行,应该是 EL 应该下载到它们的内存池中的相同 Blob。通过这样做,我们确信,无论区块中包含哪些 Blob,每个遵循该协议的 CL 节点都不需要通过网络接收任何水平行,因为它们已经将它放在它们的 Blob 内存池中。相反,它们可以通过纠删码在水平方向上扩展它,并将其从 EL Blob 内存池传输到 CL 保管存储。在这种情况下,没有节点,甚至区块构建者,应该通过 CL 网络推送水平行,因为不需要这样做,因为水平传播发生在 EL。如果由于某种原因(例如,网络或硬件故障),一个节点没有它应该在它的 Blob 内存池中拥有的 Blob,它可以从它的 peer 节点通过拉取来请求它们。
关于列传播,当 CL 节点接收到区块的执行负载时,它知道哪些 Blob 要包含在区块中。由于节点拥有区块的一些行,因此它也拥有该节点负责的列的一些单元格,但不是全部。因此,节点不是发送整个列(除非它是超级节点),而是通过 Gossipsub 主题传播部分列。这应该能够从列主题中的所有 peer 节点快速检索列。一旦一个节点收到了来自非扩展列的所有单元格,它就使用纠删码在垂直方向上扩展该列。此时,网络中的所有节点都应该拥有分配给保管的相应行和列。
在这个新设计中,抽样没有重大变化。一切都以与之前设计相同的方式发生。
假设在任何给定时间,大约有一千个类型 3 交易,区块构建者可以从中选择将其引入到它们的下一个区块中。这为想要在它们的 Blob 内存池中拥有所有 Blob 的区块构建者创建了一个大约 128MB 的 Blob 内存池。如果我们假设没有验证者的节点保管以与其节点 ID 相同的最后 4 位结尾的 Blob,那么它们持有 1/16 的 Blob。平均而言,在 1024 个 Blob 中,有 64 个 Blob(约 8MB)。假设一个拥有 8,000 个节点并且节点 ID 同质分布的网络,每个 Blob 将存储在大约 500 个节点上,从而提供足够的冗余和健壮性。感谢我们的爬虫,我们获取了今天网络中 EL 节点的当前列表,并按照这种设计对它们进行了分片。上图显示了每个分片中存在的节点数。
我们还分析了从 Pectra(5 月 22 日)到 6 月 3 日(6107 个 epoch)的所有类型 3 交易,并根据它们各自的分片绘制了它们,以检查它们的分布是否同质。总共有 254,097 个类型 3 交易分布在 16 个分片中,如下所示。
类似地,我们验证了 707,923 个 Blob 也同质分布在各个分片中。
这不包括多验证者节点和超级节点。
为了实施本文中提出的水平分片 Blob 内存池设计,EL 节点只需要做一项额外的检查,验证匹配的哈希值,然后再拉取类型 3 交易。
对于列传播,我们需要实施“部分列传输”,以允许传播部分列。这可以像发送一个较短的(1/16)列以及列中单元格位置的列表一样简单。
其他几种策略可以补充这个提议:
我们可以添加一个 Blob 内存池票证,用于将 Blob 引入到 Blob 内存池中。该票证可以通过拍卖获得。Blob 内存池票证的目的是限制注入到内存池中的 Blob 数量,从而防止 DoS 攻击。但是,在这种设计中,Blob 内存池是水平分片的,因此不需要太多 Blob 内存池票证。
区块构建者/提议者可以“尽最大努力”地传播所有数据(行和列)。虽然大多数数据列将通过部分传播从其他peer 节点到达,但来自区块构建者的列可以用作备份策略。
节点应该使用 IDONTWANT 消息来减少接收单元格时的带宽。请注意,由于分片是不相交且确定性的,因此部分传播将始终传播完全相同的部分消息。因此,IDONTWANT 消息仍然可以在部分传播的上下文中工作。
由于列传播从所有节点同时开始,因此我们可以在最大限度地减少匿名性问题的情况下实施推拉阶段转换策略。
这项研究由 Codex 团队 完成。我们要感谢 @dankrad 和其他 DAS 研究人员的反馈和贡献。
- 原文链接: ethresear.ch/t/a-new-des...
- 登链社区 AI 助手,为大家转译优秀英文文章,如有翻译不通的地方,还请包涵~
如果觉得我的文章对您有用,请随意打赏。你的支持将鼓励我继续创作!