以太坊中更快的区块/blob传播 - 网络传输

文章提出了一种基于随机线性网络编码(RLNC)的以太坊区块和blob传播方案,旨在优化P2P网络中的广播和传输效率。通过将区块分割成小块并进行编码,该方案理论上可以在降低带宽消耗和减少网络跳数的同时,实现更快的区块分发。初步的实验数据表明,该方法能够显著提升传播速度,尤其是在处理较大的区块或blob时。

以太坊中更快的区块/blob 传播

感谢 @n1shantd、@ppopth 和 Ben Berger 对本文的讨论和反馈,以及 @dankrad (https://ethresear.ch/u/dankrad) 的许多有用的讨论。

摘要

我们提出了一种通过使用随机线性网络编码来广播和传输 P2P 网络中的区块和 blob 的方式的变更。我们证明了从理论上讲,我们可以以当前 gossipsub 实现所需时间的 5% 的带宽和 57% 的网络跳数(因此每个消息的延迟减半)来分发区块。我们提供了计算开销的具体基准。

介绍

当前用于分发区块的 gossipsub 机制大致如下。提议者在其所有 peer 中选取一个随机子集(称为其 Mesh),大小为 D=8,并将区块广播给它们。每个收到区块的 peer 都会执行一些非常快的初步验证:主要是签名验证,但最重要的是不包括状态转换或事务执行。经过这种快速验证后,该 peer 将其区块重新广播给另外 D 个 peer。这种设计有两个直接的后果:

  • 每次跳转至少增加以下延迟:从一个 peer 到下一个 peer 的一个完整区块传输(包括网络 ping 延迟,基本上与带宽无关,以及完整区块的传输,受带宽限制)。
  • Peer 不必要地向已经收到完整区块的其他 peer 广播完整区块。

我们建议在广播级别使用 随机线性网络编码 (RLNC)。通过这种编码,提议者会将区块拆分成 N 个块(例如,对于下面的所有模拟,N=10),而不是将完整区块发送给大约 8 个 peer,而是将单个块发送给大约 40 个 peer(不是原始块之一,而是它们的随机线性组合,有关隐私注意事项,请参见下文)。Peer 仍然需要下载一个完整区块,或者更确切地说 N 个块,但它们可以从不同的 peer 并行获取它们。在收到这 N 个块后,每个块都是组成原始区块的原始块的随机线性组合,peer 需要求解一个线性方程组以恢复完整区块。

一个概念验证 实现 突出了以下数字

  • 提议一个区块需要额外的 26 毫秒,这是受 CPU 限制的,并且可以在现代笔记本电脑(Apple M4 Pro)上完全并行化到小于 2 毫秒
  • 验证每个块需要 2.6 毫秒。
  • 解码完整区块需要 1.4 毫秒。
  • 使用 10 个块和 D=40,每个节点发送的数据是当前 gossipsub 的一半,并且网络以一半的时间广播一个 100KB 的区块,并且好处随着区块大小的增加而增加。

协议

有关网络编码的深入介绍,我们请读者参考 op. cit.这本教科书。我们在此处提及上述概念验证基准的最低实现细节。在区块传播(约 110KB)的情况下,延迟或网络跳数决定了传播时间,而在完整 DAS 中像 blob 这样的大消息的情况下,带宽决定了传播时间。

我们考虑一个具有素数特征的有限域 \mathbb{F}_p。在上面的示例中,我们选择 Ristretto 标量基础域,如 curve25519-dalek rust crate 所实现的那样。提议者获取一个区块,它是一个不透明的字节切片,并将其解释为 \mathbb{F}_p 中的元素向量。在撰写本文时,一个典型的以太坊区块约为 B = 110KB,鉴于每个 Ristretto 标量需要略小于 32 字节来编码,一个区块大约需要 B/32 = 3520 个 \mathbb{F}_p 元素。分成 N=10 个块,每个块可以看作是 \mathbb{F}_p^{M} 中的一个向量,其中 M \sim 352。因此,该区块被视为 N 个向量 v_i \in \mathbb{F}^M_p, i=1,...,N。提议者随机选择 D\sim 40 个 peer 的子集。对于每个这样的 peer,它将发送一个 \mathbb{F}_p^M 向量,以及一些额外的信息来验证消息并防止网络上的 DOS。我们解释一下提议者

提议者

我们将使用 Pedersen 对 Ristretto 椭圆曲线 E 的承诺,如上面提到的 rust crate 所实现的那样。我们假设我们已经随机选择了一个足够元素的受信任设置 G_j \in E, j = 1, ..., K,其中 K \gg M。我们为 \mathbb{F}_p^M 选择一个标准基 \{e_j\}_{j=1}^M。因此,每个向量 v_i 都可以唯一地写成

v_i = \sum_{j=1}^M a_{ij} e_j,

对于一些标量 a_{ij} \in \mathbb{F}_p。对于每个向量 v_i,我们都有一个 Pedersen 承诺

C_i = \sum_{j=1}^M a_{ij}G_j \in E.

最后,对于大小为 D \sim 40 的子集中的每个 peer,提议者均匀随机地选择一组标量 b_i, i=1, ...,N 并将以下信息发送给该 peer

  1. 向量 v = \sum_{i=1}^N b_i v_i \in \mathbb{F}_p^M。大小为 32M 字节,它是消息的内容。
  2. N 个承诺 C_i, i=1,...,N。这是 32N 字节。
  3. N 个系数 b_i, i=1, ...,N。这是 32N 字节。
  4. 对 N 个承诺 C_1 || C_2 || ... || C_N 的哈希的 BLS 签名,这是 96 字节。

一个 已签名消息 是以上 1-4 的元素的集合。我们看到每个消息作为 sidecar 发送了 64N \sim 640 个额外的字节。

接收 Peer

当一个 peer 收到上一节中的消息时,验证过程如下

  • 它验证签名对于提议者和接收承诺的哈希是否有效。
  • 它写入接收向量 v = \sum_{j=1}^M a_j e_j,然后计算 Pedersen 承诺 C = \sum_{j=1}^M a_j G_j。
  • 接收到的系数 b_i 声称 v = \sum_{i=1}^N b_i v_i。该 peer 计算 C'= \sum_{i=1}^N b_i C_i,然后验证 C = C'。

Peer 跟踪他们收到的消息,假设它们是向量 w_i, i = 1,...,L,其中 L < N。它们生成一个子空间 W \subset \mathbb{F}_p^M。当他们收到 v 时,他们首先检查该向量是否在 W 中。如果它在 W 中,那么他们会丢弃它,因为该向量已经是之前向量的线性组合。该协议的关键是这种情况发生的可能性非常小(对于上面的数字,这种情况发生的概率远小于 2^{-256})。作为其结果,当节点收到 N 个消息时,它知道它可以从消息 w_i, i=1,...,N 中恢复原始的 v_i,从而恢复区块。

另请注意,只需要一个签名验证,所有传入的消息都具有相同的承诺 C_i 并且对同一组承诺具有相同的签名,因此该 peer 可能会缓存第一次有效验证的结果。

发送 Peer

Peer 可以在收到一个块后立即将块发送给其他 peer。假设一个节点持有 w_i, i=1,...,L,其中 L \leq N,如上一节所述。一个节点还会跟踪他们收到的标量系数,因此他们知道他们持有的块满足

w_i = \sum_{j=1}^N b_{ij} v_j \quad \forall i,

对于他们在内部状态中保存的一些标量 b_{ij} \in \mathbb{F}_p。最后,节点还会保留完整的承诺 C_i 和提议者的签名,他们在验证他们收到的第一个块时已经验证了该签名。

节点发送消息的过程如下。

  • 他们随机选择 L 个标量 \alpha_i \in \mathbb{F}_p, i=1,...,L。
  • 他们形成块 w = \sum_{i=1}^L \alpha_i w_i。
  • 他们通过以下方式形成 N 个标量 a_j, i=1,...,N

a_j = \sum_{i=1}^L \alpha_i b_{ij}, \quad \forall j=1,...,N.

他们发送的消息包含块 w、系数 a_j 和承诺 C_i 以及提议者的签名。

基准

该协议有一些与 gossipsub 相同的组件,例如,提议者需要创建一个 BLS 签名,而验证者必须检查一个 BLS 签名。我们在此记录执行通常的 gossipsub 操作之外还需要执行的操作的基准。这些是协议在节点上具有的 CPU 开销。基准是在 Macbook M4 Pro 笔记本电脑和 Intel i7-8550U CPU @ 1.80GHz 上进行的。

这些基准的参数为 N=10,表示块的数量,总块大小被认为是 118.75KB。所有基准都是单线程的,并且都可以并行化

提议者

提议者需要执行 N 个 Pedersen 承诺。该基准测试结果为

时间 型号
[25.588 ms 25.646 ms 25.715 ms] Apple
[46.7ms 47.640 ms 48.667 ms] Intel

节点

接收节点需要为每个块计算 1 个 Pedersen 承诺,并执行由提议者提供的承诺的相应线性组合。这些时间如下

时间 型号
[2.6817 ms 2.6983 ms 2.7193 ms] Apple
[4.9479 ms 5.1023 ms 5.2832 ms] Intel

发送新块时,节点需要执行它可用的块的线性组合。这些时间如下

时间 型号
[246.67 µs 247.85 µs 249.46 µs] Apple
[616.97 µs 627.94 µs 640.59 µs] Intel

在收到 N 个块后解码完整块时,节点需要求解一个线性方程组。时间如下

时间 型号
[2.5280 ms 2.5328 ms 2.5382 ms] Apple
[5.1208 ms 5.1421 ms 5.1705 ms] Intel

总体 CPU 开销。

Apple M4 上提议者的总体开销是 26 毫秒单线程,而对于接收节点是 29.6 毫秒单线程。这两个过程都是完全可并行化的。在提议者的情况下,它可以并行计算每个承诺,而在接收节点的情况下,这些是自然并行事件,因为节点正在从不同的 peer 并行接收块。在 Apple M4 上并行运行这些过程会导致提议者端为 2.6 毫秒,接收 peer 为 2.7 毫秒。对于实际应用,与涉及的网络延迟相比,可以合理地将这些开销视为零。

优化

一些尚未实现的过早优化包括在块到达时反转线性系统,尽管上面引用的概念验证确实将传入的系数矩阵保持为 Echelon 形式。最重要的是,消息的随机系数不需要像 Ristretto 字段那样大的字段。像 \mathbb{F}_{257} 这样的小素数域就足够了。但是,由于 Pedersen 承诺发生在 Ristretto 曲线中,因此我们被迫在更大的字段中执行标量运算。这些基准的实现为线性组合选择了小系数,并且这些系数在每次跳转时都会增长。通过正确控制和选择随机系数,我们也许可以将线性系统的系数(以及因此在发送块中的带宽开销)限制为以 4 字节而不是 32 字节进行编码。

执行这种优化的最简单方法是在 \mathbb{F}_q 上定义的椭圆曲线上工作,其中 q = p^r 对于某个小素数 p。这样,系数可以在子域 \mathbb{F}_p \subset \mathbb{F}_q 上选择。

隐私注意事项 上面链接的 PoC 中的实现认为每个节点,包括提议者,都选择小系数来复合其线性变换。这允许接收具有小系数的块的 peer 识别该块的提议者。要么采用上述优化来通过执行像 Bareiss' 扩展这样的算法来保持所有系数都小,要么我们应该允许提议者从字段 \mathbb{F}_p 中选择随机系数。

模拟

我们在一些简化假设下进行了块传播的模拟,如下所示。

  • 我们选择一个随机网络,该网络建模为一个有向图,具有 10000 个节点,每个节点都有 D 个 peer 来发送消息。D 在本文中称为 Mesh 大小,并且选择了在 3 到 80 的大范围内变化。
  • Peer 在完整节点集中随机且均匀地选择。
  • 每个连接都选择具有相同的 X MBps 带宽(通常在以太坊中假定为 X=20,但我们可以将此数字保留为参数)
  • 每次网络跳转都会产生额外的 L 毫秒的恒定延迟(通常测量为 L=70,但我们可以将此数字保留为参数)
  • 消息大小假定为 B KB 的总大小。
  • 对于使用 RLNC 的模拟,我们使用 N=10 个块来分隔该块。
  • 每次节点会将消息发送给一个 peer,由于它是冗余的(例如,该 peer 已经拥有完整块),因此会丢弃该消息,我们会将消息的大小记录为 浪费的带宽

Gossipsub

我们使用发送消息的 peer 数 D=6。我们获得网络平均需要 7 跳才能将完整块传播到 99% 的网络,从而导致总传播时间为

T_{\mathrm{gossipsub, D=6}} = 7 \cdot (L + B/X),

以毫秒为单位。

gossipsub-total-theorical\ gossipsub-total-theorical1712×982 70.6 KB

使用 D=8 的结果类似

T_{\mathrm{gossipsub, D=8}} = 6 \cdot (L + B/X),

浪费的带宽对于 D=6 为 94,060 \cdot B,对于 D=8 为 100,297 \cdot B。

对于 B 的低值,如当前的以太坊区块,延迟决定了传播,而对于较大的值,例如在 peer-DAS 之后传播 blob,带宽成为主要因素。

RLNC

每个 peer 发送单个块

使用随机线性网络编码,我们可以使用不同的策略。我们模拟了一个系统,其中每个节点只会将一个块发送到其大小为 D 的 mesh 中的所有 peer,这样我们保证了产生的延迟与 gossipsub 中的延迟相同:每次跳转的单个延迟成本 L 毫秒。这要求 mesh 大小要明显大于 N,即块的数量。请注意,对于 gossipsub mesh 大小为 D_{gossipsub}(例如,当前以太坊中为 8),我们需要设置 D_{RLNC} = D_{gossipsub} \cdot N 才能消耗每个节点相同的带宽,对于当前值,这将是 80。

使用带宽的一半的更保守的值,即 D=40,我们获得

T_{RLNC, D=40} = 4 \cdot \left(L + \frac{B}{10 X} \right),

浪费的带宽为 29,917\cdot B。假设与今天相同的带宽,我们使用 D=80 得到令人印象深刻的

T_{RLNC, D=80} = 3 \cdot \left(L + \frac{B}{10 X} \right),

浪费的带宽为 28,124\cdot B,这是 gossipsub 中相应浪费带宽的 28%。

差异

对于每个节点发送的相同带宽,我们看到传播时间的不同之处在于将延迟除以 2(有 3 跳与 6 跳),以及通过消耗每单位时间十分之一的带宽更快地传播块。此外,通过多余消息浪费的带宽被削减到 gossipsub 浪费消息的 28%。对于传播时间和浪费的带宽,也获得了类似的结果,但每个节点发送的带宽减少了一半。

在较低的块大小端,延迟占主导地位,而 3 跳与 gossipsub 上的 6 跳起到了最大的作用,在较高的块大小端,带宽性能占主导地位。对于更大的块大小,RLNC 中的 CPU 开销会变得更糟,但是考虑到传输时间的数量级,这些可以忽略不计。

rlnc-gossipsub\ rlnc-gossipsub1712×982 87.7 KB

每个 peer 多个块

在生产中,每个 peer 发送单个块的方法中,具有更高带宽的节点可以选择广播到更多 peer。在节点级别,这可以通过简单地广播到所有当前 peer 来实现,并且节点运营商只需通过配置标志来选择 peer 的数量。另一种方法是允许节点依次将多个块发送给单个 peer。这些模拟的结果与上述完全相同,但 D 明显更低,正如预期的那样。例如,对于 D=6,在每个 peer 发送单个块的情况下,永远不会广播完整块。模拟需要 10 跳才能广播完整块。使用 D=10,跳数减少到 9。

结论、遗漏和进一步的工作

我们的结果表明,如果我们使用 RLNC 而不是当前的路由协议,那么预计在块传播时间和每个节点的带宽使用方面都会有相当大的改进。这些好处在块/blob 大小越大或每次跳转的延迟成本越短时越明显。实施此协议需要对当前架构进行重大更改,并且可能需要一种全新的 pubsub 机制。为了证明这一点是合理的,我们可能需要实施完整的网络堆栈以在 Shadow 下进行模拟。另一种方法是实施 Reed-Solomon 纠删码和路由,类似于我们对 Peer-DAS 所做的那样。将上述模拟扩展到这种情况应该很简单,但是 op. cit 已经包含许多这样的比较。

  • 原文链接: ethresear.ch/t/faster-bl...
  • 登链社区 AI 助手,为大家转译优秀英文文章,如有翻译不通的地方,还请包涵~
点赞 0
收藏 0
分享
本文参与登链社区写作激励计划 ,好文好收益,欢迎正在阅读的你也加入。

0 条评论

请先 登录 后评论
以太坊中文
以太坊中文
以太坊中文, 用中文传播以太坊的最新进展