EIP-8142:区块内嵌Blob(BiB)——原型报告

peter-scroll 发布于 2026-06-30 阅读 16

本文详细介绍了EIP-8142(Block-in-Blobs,简称BiB)的原型实现。

作者:Péter Garamvölgyi ( @thegaram33)

最后更新:2026-06-26

简介

我在 ethrex 和 Lighthouse 上为 EIP-8142: Block-in-Blobs(简称 BiB)构建了一个原型。本文档概述了这项工作。其目标是帮助讨论此 EIP,并引导核心开发者将其纳入。具体来说,我们需要梳理开放的规范和实现挑战。

摘要 · BiB · 原型 · 发现 · 代码 · 背景 · 资源

摘要

在 ethrex、Lighthouse 和 Kurtosis 开发网络的基础上,使用 Claude 实现了一个端到端原型。

范围内的代码变更

不在本原型范围内的变更

  • 将 EIP 移植到 execution-specs、consensus-specs、EELS/EEST
  • 完整的 EIP-8025 zkAttester 集成
    • 集成到 ere-guest、zkboost、Proof Engine 等
    • 不下载负载即可证明
  • 使用真实证明器的端到端开发网络
  • CL 负载 blob 托管和负载重建
  • 外部区块构建器
  • Dora 浏览器变更

重点见解(详情请跳转至 发现):

  • 概念变更很小,主要是 EL 侧,CL 变更极少。
  • BiB 与现有的 DA 逻辑以及 EIP-8025 都很好地组合。
  • BiB 将 KZG 置于区块生产过程的 热路径 上。
  • 后 BiB 的 blob 费用市场仍然是一个开放的研究问题。
  • 估算 BAL 大小和负载 blob 数量是实现的最大障碍。

建议的下一步:

  • 对 BiB 对 Engine API 延迟的影响进行更详细的基准测试。
  • 重新设计 BiB 编码,或考虑将 BAL 排除在 BiB 之外。(如果没有 BAL,负载 blob 的大小更可预测,并且可以增量构建。)
  • 实现 verify_blob_kzg_proofverify_blob_kzg_proof_batch 的 Rust 原型。
  • 端到端证明测试,集成 ere-guestzkboost
  • 与提议的 pq-DA 方案进行初步 BiB 集成。
  • 最终确定 BiB blob 费用市场设计。
  • 与 CL 客户端开发者 讨论 CL 负载 blob 托管问题。
  • 收集反馈(ethrex 团队、zkEVM 团队、EL/CL 客户端开发者等)。

BiB 概述

动机

BiB 提议使用以太坊现有的 blob 机制(如 EIP-4844EIP-7594 所定义)来分发执行负载。这一变更的动机是向 zkEVM(EIP-8025: 可选执行证明)的过渡。动机有两个方面:

  1. 执行负载可用性。zkAttesters 通过验证针对区块头的有效性证明来验证执行负载,而不是重新执行它。这意味着他们可以在不下载完整负载的情况下进行证明,因此今天负载可用性的隐含保证不再成立。将负载发布在 blobs 中保证了任何人都可以下载并重新执行它。请参阅 ethresear.ch/t/blocks-are-dead-long-live-blobs

  2. 带宽扩展。过渡到 zkEVM 可以扩展执行,因为 zkAttesters 可以在亚线性时间内验证区块。但带宽仍然会随区块大小线性扩展。通过使用 blobs,验证者将采样数据而不是下载完整负载。请参阅 ethresear.ch/t/a-native-zkevm-scales-bandwidth-not-just-execution

在 BiB 下,区块提议者(EL 客户端)必须将执行负载编码到一个或多个 blobs 中,然后将这些 blobs 传递给 CL 客户端。CL 客户端随后像处理任何其他 blobs 一样进行数据分发和数据可用性采样。证明者通过重新编码负载并比较 blob 版本化哈希来验证此编码。zkAttesters 将其作为有效性证明的一部分进行验证。

术语

Payload blob。我们引入术语 payload blob 来指代包含执行负载数据的 blobs。相比之下,user blobs(又名 type-3 blobs)由用户通过 mempool 提交。Payload blobs 不附加到任何交易,并且无法从 EVM 内部访问。Payload blobs 在 blob 包中始终位于 user blobs 之前。

这种 blob 类型的区分是概念性的:对于 DA 逻辑,所有 blobs 看起来相同。

分叉激活和依赖项

BiB 依赖于 BALs(EIP-7928: 区块级访问列表)。为简单起见,原型构建在 ePBS(EIP-7732: 内建提议者-构建者分离)之前的版本上。根据 strawmap,BiB 可能会与后量子 DA 一起推出,但此原型仍使用 KZG。

规范亮点

如需完整上下文,请先阅读 EIP-8142

数据类型变更:在负载头部添加了一个新字段 payload_blob_count。没有这个新字段,就无法区分 payload 和 user blobs。

Payload blob 编码:Payload blobs 包含交易和 BAL,以 RLP 编码。交易是唯一无法从执行负载头部推导出的数据。BAL 可以通过重新执行区块来推导,因此将它们包含在 payload blob 中使此构造更有利于证明器。

fig-payload-blob-encoding

重用现有 blob 逻辑:BiB 在 CL 侧需要最小的更改,它旨在重用现有的 blob 分发和数据可用性采样逻辑。对于大多数目的,CL 客户端将 payload 和 user blobs 同等对待。EL 客户端或 guest 程序验证 payload blobs 是否正确构造,但数据可用性是通过 CL 中现有的 PeerDAS 机制实现的。

无需更改 EVM、mempool:EL 的更改主要封装在 Engine API 中。由于 payload blobs 不暴露给 EVM,因此状态转换函数没有更改。需要澄清的是:当 blob 交易(type-3)触发 EVM 执行时,其 blob 版本化哈希可以从 EVM 内部访问。相比之下,payload blobs 永远不会注入到 EVM 上下文中。

限制和费用:协议定义的 blob 计数限制(MAX_BLOBS_PER_BLOCK)适用于 payload 和 user blobs 的总和,不能超过。然而,payload blobs 可能会覆盖节点操作员在其自身验证节点上配置的用户定义 blob 上限。Payload blobs 也参与费用市场计算。

fig-blob-layout

不变量:在 BiB 之前,有一个不变量:“每个 blob 承诺都有一个对应的 blob 交易”。这不再成立。另一方面,MAX_BLOBS_PER_BLOCK 不变量仍然有效。

BiB 原型讨论

我们概述了原型实现,涵盖原生和 zk 流程(见下图)。我们首先介绍主要收获,然后详细说明代码变更。

原生与 zk 的等价性似乎是明显的(假设 KZG 是安全的且错误概率可忽略),但应该更正式地论证。

fig-native-vs-zk-flow

发现

1. KZG 操作进入 Engine-API 热路径

在 BiB 之前,blob 承诺和 cell 证明始终由用户在发送交易之前计算,而不是由节点计算。有了 BiB,payload blob 承诺和 cell 证明现在由 EL 客户端计算。这是一个计算量大的操作(大约每个 blob 100 毫秒),处于 engine_getPayload 的关键路径上。

下面的开发网络截图显示 BiB 激活后延迟增加:

grafana-engine-latency-2

无法流水线化:BiB 编码为 header ‖ BAL ‖ RLP(txs)headerBAL 在区块最终确定之前是未知的,因此 engine_getPayload 中的计算(KZG 承诺和 cell 证明)无法流水线化。然而,它可以对所有 payload blobs 并行化。下面有更多关于此的内容

对负载验证的影响:在 engine_newPayload 中,BiB 步骤是非阻塞的:我们可以并行进行 blob 验证和区块重新执行。主要风险是资源争用,例如,8 个内核并行进行 payload blob 验证可能会占用并行交易执行和状态根计算所需的资源。

fig-kzg-latency2

尖峰导致停滞:在本地开发网络中,我们观察到 Engine API 延迟偶尔出现尖峰,导致区块生产停滞——这需要进一步调查。

每个 payload blob 的操作 getPayload(生产者) newPayload(验证者)
承诺 MSM(blob_to_kzg_commitment
cell 证明compute_cells_and_kzg_proofs ✓ — 主要成本(每个 blob 约几百毫秒)
打开证明(compute_blob_kzg_proof ✓(仅 zk 流程)
相对 KZG 成本 高昂 仅承诺 → 约轻 10 倍

2. 负载构建期间难以执行 blob 数量限制

在构建负载时,我们必须强制执行不变量:payload_blob_count + user_blob_count <= MAX_BLOBS_PER_BLOCKpayload_blob_count 取决于 RLP 编码的交易和 BAL。后者 难以估计

在原型中,当我们添加新交易时,我们计算添加的 BAL 大小的快速但不准确的上限。这可能导致负载构建器过早密封区块。类似的问题在原始 EIP PR 中 被指出

fig-block-building-loop

这种启发式方法可能非常不准确,具体取决于区块的状态访问模式(开发网络使用了具有重叠状态访问的交易):

grafana-bal-over-estimate

3. KZG blob 和批量验证在某些证明后端上不可用

以前,运行 ethrex 节点不需要 c-kzg(功能标志)。现在它需要,因为它在验证(engine_newPayload)和区块生产(engine_getPayload)中都被使用。

Deneb 规范 定义了各种 KZG 函数。verify_kzg_proof 在任何地方都能工作(它用于点评估预编译),但 verify_blob_kzg_proof 在 OpenVM/Zisk 上缺失,并且没有后端提供纯 Rust 批量验证(verify_blob_kzg_proof_batch)。在证明器 guest 程序中,拥有 verify_blob_kzg_proof_batch 对于高效验证 payload blob 承诺至关重要。

由于点评估在任何地方都已可用,每个后端都已经拥有 BLS12-381 配对和 G1 操作,只是它们没有被组装成缺失的规范函数。

fig-backend-kzg-matrix

4. Blob 费用市场的影响尚不清楚

Payload blobs 与 user blobs 共享 blob 预算和费用市场。它们如何重新定价数据可用性尚未解决。

5. CL blob 托管无法针对 payload blobs

EIP 设想 CL 客户端从其 blobs 重建负载。但托管要么是所有 cell(超级节点),要么是 PeerDAS 列子集。没有像“仅 payload blobs”(或特定 rollup 的 blobs)这样的配置。换句话说,托管是按列的,而针对 blobs 将需要按行的托管。这可以作为单独的 ERC 添加到 CL 客户端。

这对于任何希望在不运行超级节点的情况下从 blobs 下载负载的人来说都很重要。

fig-custody-matrix

一个相关的问题是历史数据的可用性。目前这是一个隐含的保证,节点愿意为同步对等方提供服务(出于利他主义,或者说默认配置)。CL 客户端仅保留 blob 数据几周,之后默认删除。

6. 当前的 EIP 文本有些不准确和不完整

一些修复在 EIPs#11763 中。

编码。最初 EIP 使用了错误的(小端)blob 域元素编码;已更新为将大端 MSB 设置为 0x00

空负载。BAL 永远不会为空,即使区块是空的(考虑到系统合约调用)。因此,payload blob 数量始终严格非零。

创世配置和激活。尚未指定。原型混合使用了 Amsterdam 和 Gloas:EL 在 Amsterdam 后激活,CL 在 Fulu 和 Gloas 之间激活。

费用市场变更尚待评估。

7. 没有激励高 payload blob 利用率

负载不太可能恰好填满 N 个 blobs。最后一个 blob 可能已满或几乎为空。没有激励来填满它。

另外,域元素编码(将 MSB 保留为 0x00)可能不是最有效的编码。从技术上讲,我们可以额外利用 MSB 的 6 位,同时仍然适合 BLS 域,以编码简单性换取效率。

以前有一些关于对 BiB 数据应用某种压缩的讨论。

fig-blob-underutilization

另见来自本地开发网络的数据:

grafana-last-blob-fill

8. 潜在的证明开销

证明器为 payload blobs 执行 KZG 批量评估和 RLP 编码。开销尚未在真实证明环境中评估。

9. 原生 rollups 重用 BiB 更改的 L1 STF

BiB 将 payload-blob 构建和验证添加到高级状态转换函数中。原生 rollups 旨在按原样重用 L1 的 STF,可能不应继承这一点。

Ethrex 变更

完整差异:Thegaram:ethrex:eip-8142-block-in-blobs(基于 v18.0.0-rc.1

EL 变更广泛,涉及 Engine API、负载构建、KZG 库以及 EIP-8025 guest 程序。

分叉激活types/genesis.rs

在 Amsterdam 之后激活 EIP-8142,因为它依赖于 BALs。

Payload blob 编码types/eip8142.rs

在 payload blobs 和字节之间进行转换,遵循规范。

头部和 blobs 包变更types/block.rsnetworking/rpc/types/payload.rstypes/blobs_bundle.rs

  • 区块头部 和负载添加新字段 payload_blob_count,在 EIP-8142 激活之前省略。
  • Blob 包 继续使用 payload blobs 和 user blobs 的 cell 证明,并将这些传递给 CL 客户端(create_from_blobs)。
  • 可选地,我们还为 payload blobs 计算 KZG 打开证明,以便在 guest 程序中验证(compute_payload_kzg_proofs)。
  • 我们 强制执行不变量,即 payload blobs 必须位于 user blobs 之前(from_sections)。
  • 并行化 payload blob 包的承诺和证明计算,因为这位于 engine_getPayload 的热路径上(create_from_blobs)。

KZG/加密crypto/provider.rscrypto/kzg.rs

  • 添加先前未实现的 verify_blob_kzg_proof_batch 方法。
  • c-kzg 可用时(原生/主机、RISC0),我们直接使用其批量验证。
  • 否则(例如 SP1/kzg-rs),我们目前循环进行单 blob 验证作为临时解决方法。

新的 Engine APInetworking/rpc/engine/mod.rsnetworking/rpc/engine/payload.rs

  • 定义新的 API engine_newPayloadV6(以及 engine_newPayloadWithWitnessV6)。在 verify_eip8142_payload 中实现 payload-blob 验证。
  • 定义新的 API engine_getPayloadV7
  • 定义新的 API engine_getPayloadWithKzgProofsV7,未暴露的面向证明器的 API。对应 EIP get_payload_zk。附加 KZG payload blob 证明。
  • 注意:BiB 中新添加的大部分验证都是在 Engine API 中完成的。ethrex 的区块指标(显示在日志中)不会包含这些,因为这些指标是在不同的 crate 中实现的。

负载构建blockchain/payload.rscommon/validation.rs

证明器 guest 程序types/eip8025_ssz.rsguest-program/src/l1/input.rsguest-program/src/l1/program.rs

fig-prover-input

测试tests/eip8142_native.rstests/eip8142_guest.rs

  • 原生引擎往返(getPayloadV7 -> newPayloadV6)测试。
  • Guest 程序证明器/拒绝测试。

Lighthouse 变更

完整差异:Thegaram:lighthouse:eip-8142-block-in-blobs(基于 v8.1.3

CL 变更最小且主要是机械性的。差异的主体是分叉激活样板代码,添加了一个新的 BiB 分叉变体。概念性的 CL 变更很小:一个新字段 payload_blob_count 和对 blob 版本化哈希验证的调整。

分叉激活fork_name.rschain_spec.rsupgrade/bib.rs

Payload 头部数据结构变更execution_payload_header.rsexecution_payload.rsbeacon_block_body.rs

  • 执行负载和头部的新 Bib superstruct 变体,添加了 payload_blob_count 字段;头部升级 默认为 0
  • 新的 BeaconBlockBodyBib / BeaconBlock / BeaconState 变体贯穿 BiB payload 类型(例如状态的 latest_execution_payload_header)。
  • 这些是机械性的 superstruct 添加;payload_blob_count 是唯一新的 BiB 语义字段。

连接新的 Engine API:engine_newPayloadV6 / engine_getPayloadV7engine_api/http.rsjson_structures.rsnew_payload_request.rs

Blob 验证versioned_hashes.rs

  • verify_versioned_hashes 现在剥离前导的 payload_blob_count 哈希(payload blobs),并仅针对负载的交易版本化哈希验证 type-3 user-blob 后缀。
  • User blobs 可以在没有 EL 状态的情况下检查;payload blobs 无法廉价验证,因此此 CL 侧检查(在乐观同步期间使用)将它们推迟到 EL(engine_newPayloadV6),类似于状态根。

测试bib.rs

  • beacon_node/beacon_chain/tests/bib.rs 中的端到端 BiB 区块生产/验证测试。

本地开发网络

完整差异:Thegaram:ethereum-package:eip-8142-block-in-blobs

适用于本地测试的原型开发网络,使用本地构建的 ethrex/lighthouse 镜像。这个 2×2 Lighthouse-ethrex Kurtosis 开发网络运行 原生 BiB 路径:创世为 Fulu/Osaka,BiB 在 epoch 1 激活,之后开发网络在 spamoor 负载下生产和导入带有 payload blobs 和 type-3 blobs 的 BiB 区块。

grafana-activation

运行开发网络:

docker build -t ethrex:bib .
docker build -t lighthouse:bib .

kurtosis run --enclave bib . \
  --args-file ./bib_network_params.yaml \
  --image-download missing

更多开发网络截图

以下是一些来自 Grafana 的示例截图,这些数据来自本地开发网络运行。我们有一个 spamoor 实例首先运行 EOA、ERC20 和 blob 交易,然后运行“大区块”交易(eoatxdata: "random:25000")。

在 EIP-8142 激活时,我们开始看到 payload blobs,并且我们可以看到数据分解(交易 vs BAL)。

grafana-activation

我们可以看到最后一个 blob 的利用率随机波动。

grafana-last-blob-fill

Engine API 的 getPayload 方法显示出显著升高的延迟。

grafana-engine-latency

当前的负载构建器 BAL 估计可能非常不准确,具体取决于交易负载。

grafana-bal-over-estimate

在启用大型交易垃圾邮件发送器后,我们现在看到每个区块最多有 8 个 payload blobs。

grafana-large-blocks

创世和解析器连接el_cl_genesis_generator.starinput_parser.starsanity_check.star

  • 通过输入解析器和健全性检查传递 bib_fork_epoch,并教导 EL/CL 创世生成器发出 BiB 分叉计划(创世保持 Fulu;BiB 是一次 upgrade_to_bib 转换)。
  • 避免 BiB 在创世时构建:两层都从生成器处理的 Fulu/Osaka 开始,并在 epoch 1 转换,这也测试了分叉边界的版本化哈希处理。

开发网络配置bib_network_params.yaml

  • 2×2 ethrex/lighthouse 验证者;spamoor 配置为高 blob/交易可变性,以驱动 payload blobs 和 type-3 user blobs 的混合。

Grafana 仪表板eip8142-dashboard.json

  • BiB 可观察性:payload-blob 数量、payload BAL/txs 字节大小和 BiB 区块计数器(由新的 EL 仪表 eip8142_payload_bal_bytes / eip8142_payload_txs_bytes 和 CL EXECUTION_LAYER_BIB_BLOCKS 计数器支持)。

安全考虑

依赖 KZG。BiB 使用现有的 DA 机制,包括 KZG 承诺和 blob 证明。这不能抵御量子攻击,并且将来必须迁移到不同的 DA 方案。为了高效证明,我们依赖批量承诺验证,新方案也应支持。

数据扣留。构建者可以设置 payload_blob_count 并发布承诺,同时扣留底层 payload-blob 数据。类似于扣留 user blobs,这样的区块将被验证者拒绝。

格式错误/无效的 payload blobs。构建者可以发布无法解码为有效负载的 blobs,或者与 blobs 不匹配的承诺。两个验证路径都会拒绝:原生 newPayloadV6 重新计算承诺(MSM)并比较版本化哈希,然后解码;zk guest 验证打开(verify_blob_kzg_proof_batch)并解码。编码是严格的——每个域元素 MSB 为零、零填充以及 [BAL-len][txs-len] 头部都经过检查——因此格式错误的 payload blob 会失败验证,区块被拒绝。

Blob 预算争用。Payload blobs 和 user blobs 共享一个 MAX_BLOBS_PER_BLOCK 限制和一个费用市场。大区块需要更多 payload blobs,这可能会挤出 user blobs 并改变 blob 费用。组合限制限制了总 DA 负载,并在每个路径上强制执行,但 经济 交互(payload blobs 如何重新定价 blob 市场)是主要的开放研究问题,而不是已确定的属性。

验证延迟/资源成本。Cell 证明生成(~每个 blob 几百毫秒)现在位于 engine_getPayload 热路径上(engine_newPayload 仅重新计算承诺,轻得多)。生产者承担构建成本;验证者承担验证成本,通过批量验证和并行化减轻。这提高了节点资源需求(并使 c-kzg 成为必需),但受现有区块大小/blob 限制的约束,而不是无界 DoS 向量。

证明可靠性。zk 路径的可靠性依赖于 KZG 绑定加上 Fiat–Shamir 批量组合器;有缺陷的组合器会让证明者将不同的负载当作已承诺的负载传递。新添加的 KZG 实现应仔细验证和审计。

乐观同步。在乐观同步期间,CL 跳过 payload-blob 验证,仅检查 user-blob 版本化哈希,将 payload blobs 推迟到 EL(newPayloadV6),类似于状态根。Payload blobs 在没有 EL 状态的情况下无法廉价验证,并且这仅是对尚未完全验证的区块的健全性检查,因此推迟是安全的。

附录:背景

Engine API

Engine API 是以太坊节点的共识层(CL)和执行层(EL)客户端之间的认证 JSON-RPC 接口。CL 驱动共识、分叉选择以及区块/blob 的 gossip。EL 处理交易执行和状态。它们专门通过此接口进行通信。

  • engine_getPayload:CL 要求 EL 为其提议的区块构建一个执行负载。EL 返回负载以及其中包含的任何 blobs 的 blobs 包(blobs 及其 KZG 承诺和 cell 证明)。
  • engine_newPayload:CL 将从网络接收到的负载交给 EL 执行和验证,EL 回复有效/无效。

由于 BiB payload blobs 由 EL 生成和验证,且从不暴露给 EVM,因此更改几乎完全位于此 Engine API 边界内,作为这些方法的新版本实现:engine_getPayloadV7engine_newPayloadV6

区块访问列表(BALs)

区块访问列表(EIP-7928)是一种附加到区块的结构,记录区块接触的每个状态位置:账户、存储槽及其执行后的值。BAL 的主要目的是 性能优化:它允许节点并行化磁盘读取、交易验证和状态根计算,并在同步期间重建状态而无需重新执行交易(“无执行状态更新”)。

BAL 不是 无状态或证明机制;它不携带 Merkle 证明,也不允许节点在没有状态的情况下验证区块。该角色属于 执行见证(状态值 + 证明),它与 BAL 正交,不会被其取代。

BAL 格式(简化):

AccountChanges = [\
    address,                 # bytes20\
    [ SlotChanges,    ... ], # storage_changes  (写入,包括将槽清零)\
    [ uint256,        ... ], # storage_reads    (读取但从未写入的槽)\
    [ BalanceChange,  ... ], # post-tx 余额 (仅当余额实际改变时)\
    [ NonceChange,    ... ], # post-tx nonce\
    [ CodeChange,     ... ], # post-tx 运行时字节码 / 7702 委托\
]

## 每个接触的地址一个条目
BlockAccessList = [ AccountChanges, ... ]

规范 RLP 编码:由于头部绑定了 keccak256(rlp(bal)),字节必须是规范/确定性的。EIP 指定了 RLP 编码、最小大端整数、强制键排序等。

为什么 BAL 不是增量可构建的rlp([tx_1, …, tx_n]) 可以增量构建,因为每个交易是自包含的,可以简单地追加到字节流中(为简单起见忽略 RLP 长度前缀)。BAL 不同:它不是一个扁平列表,而是一棵树,由一个全局值(地址)键控,并在整个区块中聚合。任何交易都可以更新任意条目中的值;我们直到整个区块执行完毕才知道最终的数据结构(和编码字节)。

这对 BiB 有一个重要的影响:在负载构建期间,payload blobs 只能在区块准备好时才能知道。这使得负载构建更加复杂(更难遵守 MAX_BLOBS_PER_BLOCK 限制)且成本更高(增加了 KZG cell 证明生成延迟)。

KZG

BiB 严重依赖 KZG 承诺,因此值得回顾主要的 KZG 原语(另请参阅 Deneb 规范):

  • 承诺。一个 blob 是 BLS12-381 标量域中的 4096 个域元素,解释为次数 <4096 的多项式 p 在固定点(4096 次单位根)上的求值。KZG 承诺是一个单一的曲线点,它绑定该多项式。blob 的版本化哈希只是此承诺的哈希。
  • 点评估证明。一个简短的证明,证明 p(z) = y 在单点 z 处,通过单个配对(verify_kzg_proof)检查。这是所有其他内容构建的基础原语。这在 EVM 内直接作为点评估预编译公开,其中所有输入由调用者提供。
  • Blob 证明verify_blob_kzg_proof(blob, commitment, proof) 证明一个完整的 128 KiB blob 与承诺匹配。它简化为点评估证明:推导一个挑战 z = compute_challenge(blob, commitment)(Fiat–Shamir),评估 y = p(z)(重心坐标),然后运行 verify_kzg_proof。非正式地,Schwartz–Zippel 引理表明,当且仅当此随机检查通过时,承诺与 blob 匹配的概率非常高。
  • Cell 证明。EIP-7594/PeerDAS blob 包携带 cell 证明,用于数据可用性采样而不是整个 blob 验证。
  • 批量验证。批量形式 verify_blob_kzg_proof_batch 通过规范定义的 Fiat–Shamir 组合器,使用大约一个多配对同时验证许多 blobs。

fig-kzg-proof-types

在当今的以太坊中,完整的 blob 验证(blob-承诺绑定检查)在 mempool 和 CL 客户端中完成,但从未在 EL STF 中完成。在 BiB 下,节点(和 guest 程序)必须验证实际的 payload blob 内容。

证明后端问题。KZG 支持在各后端之间不均匀,只有 blob 级操作是问题所在:

  • 点评估在每个后端上都有效(主机/RISC0 上的 c-kzg,SP1 上的 kzg-rs,openvm-kzg,以及 Zisk 上的硬件加速)。
  • verify_blob_kzg_proof 在 OpenVM 和 Zisk 上缺失(未实现),并且没有后端提供纯 Rust 批量验证。
  • 计划中的修复(在原型中推迟以保持差异最小)是通用归约:在 ethrex 自己的代码中执行 compute_challenge + 重心评估,并仅调用普遍可用的 verify_kzg_proof,绕过每个后端的 blob 级差距,批量验证稍后作为优化添加。

fig-backend-kzg-matrix

Blob 验证

  • BiB 之前:用户计算 blob 交易 sidecar(承诺和 cell 证明)。EL 在 mempool 中验证它(verify_blob_kzg_proof),然后构建一个区块并将其作为 blobs 包的一部分传递给 CL。CL 验证这些,分发和采样 blobs。EL STF 永远不需要 blob 内容,只需要点评估预编译的 blob 版本化哈希(0x0a)。
  • BiB 之后:EL 客户端(和 guest 程序)必须验证 payload blobs 与负载匹配。

EIP-8025

EIP-8025: 可选执行证明是以太坊向 zkEVM 过渡的第一步。zkAttesters 不是重新执行每个区块,而是验证针对区块头的有效性证明。

  • Guest 程序。EL 状态转换函数被编译为在 zkVM 内运行。证明区块意味着在区块的输入(无状态执行)上执行此 guest 程序,并产生一个正确执行的简洁证明。
  • 公共与私有输入。公共输入是验证者看到并绑定的:规范 SSZ NewPayloadRequest。私有输入是证明者使用但验证者永远看不到的见证(状态、交易等)。
  • 加密后端。相同的 guest 逻辑在几个证明后端上运行,每个后端都有自己的加密实现(例如主机和 RISC0 上的 c-kzg,SP1 上的 kzg-rs),由 guest 入口点选择。

附录:规范符合性检查清单

由 Claude 生成。

领域 状态
Blob 编码/解码(31 字节块,MSB=0,[BAL-len][txs-len] 头部,填充和长度检查,往返)
payload_blob_count 头部字段(存在当且仅当 EIP-8142 激活,RLP 尾部可选,serde)
engine_getPayloadV7 — 从 {BAL, transactions} 生成 payload blobs,payload-first 包,cell 证明
engine_newPayloadV6 — 重新计算承诺(MSM),版本化哈希相等性(payload + type-3)
zk guest(new_payload_zk)— 推导 blobs,verify_blob_kzg_proof_batch,通过 HTR'd 版本化哈希固定承诺
所有路径上的组合限制 payload + type-3 ≤ MAX_BLOBS_PER_BLOCK(溢出安全)
get_payload_zkengine_getPayloadWithKzgProofsV7)— 随机点打开证明,仅证明器
批量验证后端覆盖 ⚠️ 仅 c-kzg + SP1;OpenVM/Zisk 差距

附录:资源

规范:EIP-8142 及后续修复 EIPs#11272。另请参见这些 PR 下的评论中的历史背景:EIPs#11212EIPs#11530

研究讨论:https://ethresear.ch/t/blocks-are-dead-long-live-blobs/24611https://ethresear.ch/t/a-native-zkevm-scales-bandwidth-not-just-execution/25254

  • 原文链接: hackmd.io/@peter-scroll/...
  • 登链社区 AI 助手,为大家转译优秀英文文章,如有翻译不通的地方,还请包涵~

相关文章

0 条评论