Alert Source Discuss
⚠️ Draft Informational

EIP-7892: 仅 Blob 参数的硬分叉

定义了一种通过专门的硬分叉来扩展以太坊 blob 容量的机制,这些硬分叉仅修改与 blob 相关的参数。

Authors Mark Mackey (@ethDreamer), Raúl Kripalani (@raulk)
Created 2025-02-28
Discussion Link https://ethereum-magicians.org/t/eip-7892-blob-parameter-only-hardforks/23018
Requires EIP-7840

摘要

本 EIP 介绍了仅 Blob 参数 (BPO) 硬分叉,这是一种轻量级机制,通过有针对性的硬分叉来修改仅与 blob 相关的参数,从而逐步扩展以太坊的 blob 容量:targetmaxbaseFeeUpdateFractionmaxBlobsPerTx。 与传统的硬分叉不同,传统的硬分叉需要大量的协调并引入更广泛的协议更改,而 BPO 分叉能够快速、低开销地扩展 blob 容量,以响应实际需求和网络状况

动机

以太坊的扩展策略依赖于第 2 层 (L2) 解决方案来执行交易,同时将以太坊用作数据可用性 (DA) 层。 然而,对 DA 的需求迅速增加,并且目前仅在大型、不频繁的硬分叉中修改 blob 参数的方法不够灵活,无法跟上 L2 的增长。

BPO 分叉的主要动机如下:

  1. 持续扩展
    • L2 DA 的需求正在快速增长,导致 blob 容量持续饱和。
    • 大型、不频繁的 blob 参数更改会产生高成本和低效率。
    • BPO 分叉可以更频繁、更安全地增加容量。
  2. 降低运营开销
    • 性能改进和进一步的测试将继续释放更多容量。
    • 期望减少核心开发人员就参数增加达成一致意见到其有效部署之间的时间。
    • 完整的以太坊硬分叉需要在客户端进行大量的协调、测试和升级工作。
    • 通过隔离 blob 参数更改,BPO 分叉降低了升级的复杂性。
  3. 通过新的扩展技术增强稳定性
    • 主要的扩展升级(例如 EIP-7594)在最佳 blob 限制方面引入了不确定性。
    • BPO 分叉允许开发人员在观察主网性能和稳定性后安全地增加参数,而不是迫使核心开发人员接受稳定性和容量之间的次优权衡。
  4. 为构建者提供可预测的升级
    • 构建者和 L2 需要确信以太坊将不断扩展以支持他们的需求。
    • 一个结构化的 BPO 框架提供了可预测性,允许 rollup 通过以太坊提交到替代 DA 解决方案。

规范

定义

BPO 硬分叉被定义为协议升级,它仅通过配置修改与 blob 相关的参数,而无需任何客户端代码更改。 新参数在指定的激活时间立即生效。

Blob 计划配置

以下协议参数现在由 blob 计划配置管理:

  • Blob 目标 (target): 每个区块的预期 blob 数量。
  • Blob 限制 (max): 每个区块的最大 blob 数量。
  • 每个交易的 Blob 限制 (maxBlobsPerTx): 每个交易的最大 blob 数量。
  • Blob 基本费用更新分数 (baseFeeUpdateFraction): 确定 blob gas 价格如何按区块调整。

为了确保持一致性,当常规硬分叉更改这些参数中的任何一个时,它必须通过向 blob 计划配置添加条目来实现。

执行层配置

为了促进执行层上的这些更改,EIP-7840 中定义的 blobSchedule 对象中的每个分叉都通过顶层 <fork_name>Time 字段链接到激活时间戳,该字段保存激活插槽的 Unix 时间戳作为 JSON 数字。 BPO 分叉使用 bpo<index> 约定命名,其中 <index>1 开始。 左侧填充是不必要的,因为这些标签不受词典排序的影响。 激活时间戳仅对于在 Prague 之后发生的分叉是必需的。

"blobSchedule": {
  "cancun": {
    "target": 3,
    "max": 6,
    "baseFeeUpdateFraction": 3338477
  },
  "prague": {
    "target": 6,
    "max": 9,
    "baseFeeUpdateFraction": 5007716
  },
  "osaka": {
    "target": 6,
    "max": 9,
    "maxBlobsPerTx": 6,
    "baseFeeUpdateFraction": 5007716
  },
  "bpo1": {
    "target": 12,
    "max": 16,
    "maxBlobsPerTx": 12,
    "baseFeeUpdateFraction": 5007716
  },
  "bpo2": {
    "target": 16,
    "max": 24,
    "maxBlobsPerTx": 12,
    "baseFeeUpdateFraction": 5007716
  },
},
"cancunTime": 0,    // 没有向后移植
"pragueTime": 0,    // 没有向后移植
"osakaTime": 1747387400,
"bpo1Time": 1757387400,
"bpo2Time": 1767387784,

共识层配置

一个新的 BLOB_SCHEDULE 字段被添加到共识层配置中,其中包含一系列表示 ELECTRA_FORK_EPOCH 之后 blob 参数更改的条目。 每个更改 blob 参数的分叉都有一个条目,无论它是常规分叉还是仅 Blob 参数的分叉。

BLOB_SCHEDULE:
  - EPOCH: 380000     # FULU_FORK_EPOCH (示例)
    MAX_BLOBS_PER_BLOCK: 12
  - EPOCH: 400000     # 未来的匿名 BPO 分叉
    MAX_BLOBS_PER_BLOCK: 24
  - EPOCH: 420000     # 未来的匿名 BPO 分叉
    MAX_BLOBS_PER_BLOCK: 56
  - EPOCH: 440000     # GLOAS_FORK_EPOCH;未来引入 blob 参数更改的命名分叉
    MAX_BLOBS_PER_BLOCK: 72

上面的参数和计划纯粹是说明性的。 实际值和计划超出本规范的范围。

要求:

  • 执行和共识客户端必须共享一致的 BPO 分叉计划。
  • EL 的 blobSchedule 中的插槽号必须与共识层配置中指定的 epoch 的开始对齐。
  • EL 的 blobSchedule 中的 max 字段必须等于共识层配置中的 MAX_BLOBS_PER_BLOCK 值。
  • maxBlobsPerTx 字段是可选的,如果省略,则默认为 max 的值。 共识层不使用它。

修改后的 compute_fork_digest

更新 compute_fork_digest 助手以考虑 BPO 分叉:

@dataclass
class BlobScheduleEntry:
   epoch: Epoch
   max_blobs_per_block: uint64       # Aligning with the type of MAX_BLOBS_PER_BLOCK

def compute_fork_digest(
  current_version: Version,       # Unchanged; refers to the baseline hardfork atop which the blob schedule is applied
  genesis_validators_root: Root,  # Unchanged
  current_epoch: Epoch,           # New
  blob_schedule: Sequence[BlobScheduleEntry]  # New
) -> ForkDigest:
    """
    Return the 4-byte fork digest for the ``current_version`` and ``genesis_validators_root``,
    bitmasking blob parameters after ``ELECTRA_FORK_VERSION``.

    This is a digest primarily used for domain separation on the p2p layer.
    4-bytes suffices for practical separation of forks/chains.
    """
    base_digest = compute_fork_data_root(current_version, genesis_validators_root)[:4]

    # Find the blob parameters applicable to this epoch.
    # 查找适用于此 epoch 的 blob 参数
    sorted_schedule = sorted(blob_schedule, key=lambda e: e.epoch, reverse=True)
    blob_params = None
    for entry in sorted_schedule:
      if current_epoch >= entry.epoch:
        blob_params = entry
        break

    # This check enables us to roll out the BPO mechanism without a concurrent parameter change.
    # 此检查使我们能够在不同时的参数更改的情况下推出 BPO 机制。
    if blob_params is None:
      return ForkDigest(base_digest)

    # Safely bitmask blob parameters into the digest.
    # 安全地将 blob 参数位掩码到摘要中。
    assert 0 <= blob_params.max_blobs_per_block <= 0xFFFFFFFF
    mask = blob_params.max_blobs_per_block.to_bytes(4, 'big')
    masked_digest = bytes(a ^ b for a, b in zip(base_digest, mask))
    return ForkDigest(masked_digest)

P2P 网络

ENR

在共识层中,ENR 通过附加条目 nfd 扩展,nfd 是“下一个分叉摘要”的缩写。 该字段传达了下一个计划分叉的摘要,无论它是常规分叉还是 BPO 分叉。 这种方法优于编码特定于 BPO 的参数,因为它与特定用例无关,并提供更大的长期灵活性。

nfd SSZ Bytes4 ForkDigest

在发现和与对等方交互时,节点必须评估 nfd 以及它们在 eth2 密钥下对 ENRForkID::next_* 字段的现有考虑,以形成对对等方预期下一个分叉的更准确的视图。

Status req/resp

此交互不需要更改,但需要注意的是,响应有效负载必须正确包含更新后的 fork_digest

Gossip topics

主题结构或配置不需要更改。 但是,由于其 ForkDigestValue 组件的更改,所有主题将在 BPO 分叉时自动轮换。

交易池注意事项

BPO 分叉可能会减少每个块或交易允许的 blob 数量。 这意味着池中具有高 blob 计数的交易可能变得不符合包含条件。 不得传播此类交易,并应考虑将其从交易池中逐出。

理由

为什么不只使用常规硬分叉?

完整的硬分叉需要大量的协调、测试和实施更改,而不仅仅是参数调整。 例如,在 Lighthouse 中,典型的硬分叉实现需要数千行样板代码,然后才会发生任何协议更改。 BPO 分叉通过避免对这种样板代码的需求来简化此过程。

为什么在节点配置中指定参数而不是在代码中指定?

允许外部配置 blob 参数可以实现快速实验、测试和调整,而无需跨客户端实现进行代码更改。 测试团队可以用最少的客户端实施人员参与来调查不同的参数。

为什么不为 blob 参数创建一个链上投票机制?

  • 以太坊最近的 gas 限制增加到 36M 花了近一年的时间来协调
  • blob 容量是一个快速发展的、不断变化的目标,更广泛的 staking 社区目前没有足够的装备来跟踪
  • 链上机制需要更广泛的代码更改、测试周期以及关于治理结构的辩论。
  • BPO 分叉提供了一种更简单、更可预测的方法,同时为 blob 容量稳定后未来的链上投票机制留有空间

向后兼容性

BPO 分叉不会引入向后兼容性问题。

安全考虑

尚未发现安全风险。

版权

通过 CC0 放弃版权和相关权利。

Citation

Please cite this document as:

Mark Mackey (@ethDreamer), Raúl Kripalani (@raulk), "EIP-7892: 仅 Blob 参数的硬分叉 [DRAFT]," Ethereum Improvement Proposals, no. 7892, February 2025. [Online serial]. Available: https://eips.ethereum.org/EIPS/eip-7892.