从零开始的PeerDAS

本文介绍了PeerDAS,一种允许节点分片blob保管责任的系统,旨在增加每个区块的blob数量,而无需线性增加所需的带宽和存储容量。PeerDAS通过纠删码、数据列分片和节点的数据列托管来实现这一目标,并引入了新的Req/Resp消息用于数据列的检索和验证。同时,文章还探讨了数据列的存储方式、重构机制以及PeerDAS相较于Proto-Danksharding的优势。

PeerDAS

Blobs -----

Polynomials -----------

*Chuck Norris 不需要采样数据可用性;当他觉得时机成熟时,数据就会变得可用。*

# 新颖的 PeerDAS 方法 (Fulu)

简介

我们提出了一种系统,该系统允许节点分摊 blob 保管的责任,而不是要求所有信标节点在 `4096` 个 epoch 内从所有区块中获取和存储每个 blob。 这种方法旨在增加每个区块的 blob 数量,而不会线性增加所需的带宽和存储容量。

然而,至关重要的是要确保所有 blob 在整个 `4096` 个 epoch 中始终有效可用。 一种简单但资源密集型的方法是下载每个 blob 来验证 blob 的可用性,这是 EIP-4844 (Proto-Danksharding) 中使用的当前方法。 不幸的是,即使下载 blob 而不存储它们也会消耗网络带宽。

PeerDAS 概念通过确保 blob 可用性来解决这一挑战,**而无需下载所有 blob**。

协议

第一步是将纠删码应用于每个 blob。 如果你不熟悉纠删码,请参阅本书末尾关于[多项式](https://hackmd.io/XyUFRKB1RGSiMEWlypw9hw#Polynomials)的部分。 就我们的目的而言,我们将使用 `2` 的纠删码比率。 这意味着经过纠删码的 blob 将需要非纠删码 blob 两倍的存储空间。

在应用纠删码之前,blob 可以表示为: ![image](https://hackmd.io/\_uploads/S1arLcZgA.png)

使用纠删码,blob 可以表示为: ![image](https://hackmd.io/\_uploads/r1ed89beA.png)

现在,让我们将所有行(blob)分成 128 列,称为 数据列。 ![image](https://hackmd.io/\_uploads/ryUrfqzeC.png)

  • 对于 `128` 个数据列,每个单元格代表 `256 kB / 128 = 2 kB`。
  • 对于 `6` 个 blob,每列代表 `2 kB * 6 = 12 kB`。

Peer custody

Peer 不再需要下载和存储完整的 blob(即整行)。 相反,他们只需要处理数据列的一个子集。

![image](https://hackmd.io/\_uploads/r1xQB2YGyx.png)

在此示例中:

  • 有 128 列`NUM_COLUMNS = 128`。
  • Peer 保管 `4` 个数据列

修改后的主题结构

随着 peerDAS 的引入,之前的 `blob_sidecar_<n> topics`(其中 `n=0..5`)已被 `data_column_sidecar_<n>` topics(其中 `n=0..127`)取代。

Prysm 日志示例: ``` ... INFO sync: Subscribed to topic=/eth2/153249ea/data_column_sidecar_36/ssz_snappy INFO sync: Subscribed to topic=/eth2/153249ea/data_column_sidecar_105/ssz_snappy INFO sync: Subscribed to topic=/eth2/153249ea/data_column_sidecar_124/ssz_snappy INFO sync: Subscribed to topic=/eth2/153249ea/data_column_sidecar_23/ssz_snappy ... ```

:::info 注意

在规范的早期版本中,单个主题可能包含多个数据列。 但是,在当前版本中,每个主题仅限于一个数据列,总共有 `128` 个主题。 :::

保管要求

没有附加的验证器

没有附加的验证器,一个完整节点需要下载、存储 并服务 至少 `4` 个数据列,但可以选择下载、存储 并服务 更多的数据列(如果需要)。

[来源](https://github.com/ethereum/consensus-specs/blob/dev/specs/fulu/das-core.md#custody-requirement)。

默认情况下,Prysm 信标节点将下载、存储 并服务 `4` 个数据列。 但是,使用 `--subscribe-all-subnets` 选项运行 Prysm 信标节点使其能够下载、存储 并服务 所有 `128` 个数据列。 在此配置中,该节点被认为是 超级节点

具有托管验证器(验证器保管)

具有至少一个附加的 validators,一个完整节点需要下载、存储 并服务 至少 `8` 个数据列。 对于每个新的 `32 ETH` 附加,完整节点需要下载、存储 并服务 额外的一个数据列。

  • 如果附加了 `3872 ETH` 或更多(`121` 个 validators,每个 `32 ETH`),则该节点需要下载、存储 并服务 最小的所有 `128` 个数据列。
  • 如果附加了 `1824 ETH` 或更多(`57` 个 validators,每个 `32 ETH`),则该节点需要下载、存储 并服务 最小的所有 `64` 个数据列,并且现在能够重建 `64` 个缺失的数据列

![image](https://hackmd.io/\_uploads/r13i\_o79Jg.png)

[来源](https://github.com/ethereum/consensus-specs/pull/3871/files)。

确定保管数据列

信标节点使用私钥运行,数据列的保管通过以下步骤确定:

  1. 从私钥确定性地派生出唯一的公钥。
  2. 从公钥确定性地派生出唯一的节点 ID。
  3. 从节点 ID 确定性地派生出 `128` 个数据列索引的唯一序列。
  4. 如果节点需要保管 `n` 个数据列,则这些数据列必须对应于步骤 3 中计算的序列的前 `n` 个索引。

示例: 如果在步骤 `3` 中,从节点 ID 派生出以下 128 个索引的唯一序列:`[14, 86, 45, 54, 66, 78, 127, 103, 2, ...]`,并且该节点被分配保管 `4` 列,则相应的索引必须是 `[14, 86, 45, 54]`。

如果在稍后的时间,同一个节点(使用同一个私钥)被分配保管 `6` 列,则相应的索引必须是 `[14, 86, 45, 54, 66, 78]`。

[来源](https://github.com/ethereum/consensus-specs/blob/dev/specs/_features/eip7594/das-core.md#get_data_column_sidecars)。

广告保管列

保管组的数量(对应于当前规范中保管数据列的数量)通过节点的 ENR 记录和 Metadata P2P 消息进行广播。

在 ENR 记录中,引入了一个新字段 `cgc`(保管组计数的缩写)来指示此信息。

示例: ``` enr:-Me4QGw9qjlhPjQ9Q-yoi_ju4-6aXLtvjeS2V2U0BveqIkeVGNObDR8pTRZCUVQW48yd81ch6SndZTzd6w6Ha1tqtDaGAZNDJl6sh2F0dG5ldHOIAAAAAAAAGACDY3NjBIRldGgykBUySepgAAA4AOH1BQAAAACCaWSCdjSCaXCErBAAFYlzZWNwMjU2azGhAnhJ7EpX-jrAq3cBimdLfhcXmUwMiZyxylTUjCrr00Y1iHN5bmNuZXRzAIN0Y3CCMsiDdWRwgjLI ```

![image](https://hackmd.io/\_uploads/Sy\_ZfRYMkx.png)

新的元数据结构: ```yaml seq_number: uint64 attnets: Bitvector[ATTESTATION_SUBNET_COUNT] syncnets: Bitvector[SYNC_COMMITTEE_SUBNET_COUNT] custody_subnet_count: uint64 # csc ```

节点 ID 和保管子网计数都是公开可访问的,允许任何人确定网络上任何节点的保管数据列。

新引入的 Req/Resp

PeerDAS 带有两个新的 Req/Resp 消息:`DataColumnSidecarsByRoot` 和 `DataColumnSidecarsByRange`。

([出典])

`DataColumnSidecarsByRoot` 允许通过指定以下内容从 peer 检索数据列 sidecar的列表:

  • 一个区块根,以及
  • 一个数据列索引。

在 Prysm 中,使用 `DataColumnSidecarsByRoot`:

  • 在 peer 采样期间,以及
  • 在重组后检索数据列时(如果重组足够小,不会切换回初始同步)。

`DataColumnSidecarsByRange` 允许通过指定以下内容从 peer 检索一系列数据列 sidecar:

  • 一个起始 slot,
  • 一个计数,以及
  • 一个数据列索引列表。

在 Prysm 中,`DataColumnSidecarsByRange` 用于初始同步期间。

数据列采样

两种类型的采样

除了管理保管列之外,节点还必须执行数据列采样,以统计方式验证所有数据列的可用性。 可以使用两种主要方法:保管采样peer 采样

Prysm 实现了这两种方法,但目前只有保管采样可用。 虽然保管采样更容易实现,但它需要更多的带宽。

客户端可以在子网采样和 peer 采样之间切换(或反之亦然),而无需协调的硬分叉。

保管采样

[来源](https://github.com/ethereum/consensus-specs/blob/dev/specs/fulu/das-core.md#custody-sampling)。

通过保管采样,节点需要通过 gossip 下载并验证每个区块至少 `8` 个数据列的有效性。

如果节点已经保管了至少 `8` 个数据列,则子网采样不做任何事情(无操作)。

示例 1: 如果一个节点保管 `5` 个数据列,那么对于每个包含 blob 的区块,它必须通过gossip获取并验证额外的 `3` 个数据列,总共 `5 + 3 = 8` 个数据列。

  • 注释 1: 该节点继续仅广播保管 `5` 个数据列(其 ENR 中的 `csc` 值保持为 `5`)。
  • 注释 2: 该节点不需要存储或服务为子网采样获取的 `3` 个额外数据列。

在这种情况下,该节点总共订阅 `8` 个 `data_column_sidecar_<n>` 主题:对应于其保管数据列的 `5` 个主题和子网采样所需的 `3` 个额外主题。

要将一个区块标记为可用,必须成功检索并验证所有保管和子网采样列。

![image](https://hackmd.io/\_uploads/B1avLy5GJg.png)

示例 2: 如果一个节点保管 `12` 个数据列,那么对于每个包含 blob 的区块,它不需要获取或验证任何额外的数据列。 总数仍然是 `12 + 0 = 12` 个数据列,并且子网采样是无操作的。

![image](https://hackmd.io/\_uploads/Bk-UvkqMkg.png)

下图显示了保管采样仅对未管理任何验证器的完整节点有效。

![image](https://hackmd.io/\_uploads/B13fKsm5yl.png)

Peer 采样

[来源](https://github.com/ethereum/consensus-specs/blob/dev/specs/fulu/peer-sampling.md)

子网采样 中,一个节点会订阅 `8` 个数据列主题,同时保管并通过其 ENR 和元数据广播,例如,只有 `4` 个数据列。

peer 采样 中,节点订阅的主题数量与它广播的数据列主题数量完全相同。

当节点收到一个包含 blob 的区块时,它会随机选择 `8` 个数据列,并使用 `DataColumnSidecarsByRoot` Req/Resp 消息从其直接 peer 中采样这些数据列。

因此,该节点实现了以下目标:

  • 保管某些列,这些列通过gossip获取和存储。
  • 通过 Req/Resp 协议检索一些数据列(尽管该节点不需要broadcast这些列)。

![image](https://hackmd.io/\_uploads/H1cWmM9fkg.png)

要将一个区块标记为可用,必须成功检索并验证所有保管和 peer 采样列。

如何存储数据列?

在 Prysm 中,数据列直接存储在文件系统中,模式为 `blobs/<blockRoot>/<columnIndex>.ssz`。

以下是一个保管列 `3`、`5`、`13` 和 `120` 的节点的示例: ``` blobs ├── 0x00022463ed9299403b70d78cd0ab5049fc03eefdd0bf87108ee387587eadd06b │ ├── 3.ssz │ ├── 5.ssz │ ├── 13.ssz │ └── 120.ssz ├── 0x00026f77d57e29089085edf99bc79a37f67cdb844f01aa5f85435e77de3c5d2b │ ├── 3.ssz │ ├── 5.ssz │ ├── 13.ssz │ └── 120.ssz ├── 0x0002fd2893c692ac508b502ba31fbfe351738280af8e92acc397e456af888c7a │ ├── 3.ssz │ ├── 5.ssz │ ├── 13.ssz │ └── 120.ssz ├── 0x0003be159d8a3d04ccbc288dfb19b39eba35dfb9eba1788a966cd90d23426c21 │ ├── 3.ssz │ ├── 5.ssz │ ├── 13.ssz │ └── 120.ssz ├── 0x0004d2a59f6ae7996a87a5b6e928b2fad0b864171dcf3bf609f74b8584f44722 │ ├── 3.ssz │ ├── 5.ssz │ ├── 13.ssz │ └── 120.ssz ├── 0x000537721bdc9fb0de40e0f14220155eb9cb94dd46e9b73f0a0e6fd852fa5539 │ ├── 3.ssz │ ├── 5.ssz │ ├── 13.ssz │ └── 120.ssz ... ```

重建

如果 Prysm 信标节点收到 `50%` 或更多的数据列(即 `64` 个或更多的数据列),它会立即开始重建缺失的 `50%`。

在 slot 的 `3 秒` 后,该节点会将它应该理论上收到的数据列(基于它订阅的相应主题)与它实际收到的数据列进行比较。 然后,信标节点会发送其差值。

我们真的需要所有这些复杂性吗?

保留带有行子网的 EIP-4844 并要求每个节点仅保管 blob 的一个子集是否就足够了?

考虑以下情况:每个区块最多有 6 个 blob。 与当前 EIP-4844 设计(所有节点都保管所有 blob)不同,在这个提议的(且有缺陷的)系统中,每个 peer 只需要保管 2 个子网。

现在,想象一下攻击者发起 DDoS 攻击,针对所有负责保管给定 blob 子集的节点。 在这种情况下,这些节点将完全无法服务相应的 blob。

因此,一些 blob——尽管已提交到区块——将不再可用。

![image](https://hackmd.io/\_uploads/HJCIw2fgR.png)

:::warning

这正是我们想要避免的情况。 :::

现在有了列子网 纠删码:

示例:

![image](https://hackmd.io/\_uploads/HyudqmN\_Jg.png)

提取一个(扩展的)blob: ![image](https://hackmd.io/\_uploads/ByAYq7Ndkg.png)

由于扩展的 blob 已[纠删码](https://learnblockchain.cn/article/17626),只要缺失不超过 50% 的扩展 blob,仍然可以重建扩展的 `256 kB` blob。

![image](https://hackmd.io/\_uploads/HJQGoXVuyl.png)

最后,检索原始的、非扩展的 `128 kB` blob。

![image](https://hackmd.io/\_uploads/BkPqUnGg0.png)

原始比较:没有 PeerDAS 与有 PeerDAS

没有 PeerDAS(仅 Proto-Danksharding)

当仅考虑 blob 数据 payload(不包括[Blob Sidecar](https://github.com/ethereum/consensus-specs/blob/dev/specs/deneb/p2p-interface.md#blobsidecar)中的其他数据,例如 `kzg_commitment` 或 `kzg_proof`)时:

  • 每个 blob 由 64 个单元格 组成。
  • 每个区块最多可以包含 6 个 blob
  • 每个单元格包含 2 kB 的数据。

这意味着一个节点负责存储最多: 每个区块 64 × 6 × 2 kB = 768 kB 的 blob 数据。

![image](https://hackmd.io/\_uploads/ry8za7VdJe.png)

有 PeerDAS

使用 PeerDAS,具有 4 个保管数据列和 4 个通过子网采样获取的额外数据列,并且仅考虑 blob 数据 payload(不包括[Data Column Sidecar](https://github.com/ethereum/consensus-specs/blob/dev/specs/fulu/das-core.md#datacolumnsidecar)中的其他数据,例如 `kzg_commitments` 或 `kzg_proofs`),同时保持总共 768 kB 的 blob 数据,我们可以定义以下内容:

  • 每个节点为每个区块保管和采样 8 个数据列
  • 每个区块最多可以包含 48 个 blob
  • 每个单元格包含 2 kB 的数据。

这导致每个节点保管和采样最多: 每个区块 8 × 48 × 2 kB = 768 kB 的 blob 数据。

![image](https://hackmd.io/\_uploads/B1mo144u1g.png)

仅关注 blob 数据,忽略所有其他约束和潜在挑战,PeerDAS 使以太坊网络能够实现 blob 数量 增加 8 倍

然而: > ...通过 PeerDAS 将 blob 吞吐量提高 8 倍可能“比我们想象的要难一些”,并且在开发人员确定如何最好地推出与采样相关的代码更改之前,需要进行更多的研究和测试。 [来源:Galaxy.com (Terence Tsao)](https://learnblockchain.cn/article/17625/)

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

0 条评论

请先 登录 后评论
manunalepa
manunalepa
江湖只有他的大名,没有他的介绍。