客户端验证EIP

  • shemnon
  • 发布于 2025-03-18 16:42
  • 阅读 10

本文档描述了一个RPC方法,该方法为当前和下一个分叉提供节点相关的配置数据。通过提供一个RPC方法,允许客户端在下一个硬分叉之前报告关键配置变量,运维团队可以更有信心地确认客户端已正确配置并为即将到来的分叉做好准备。该方法旨在供节点运营商、验证器团队和网络监控工具使用,以验证客户端是否为即将到来的分叉做好了准备。

摘要

本文档描述了一种 RPC 方法,该方法为当前和下一个分叉提供节点相关的配置数据。

动机

在以太坊的历史中,曾多次出现客户端未针对即将到来的硬分叉正确配置,导致在跨越分叉边界时失去共识的情况。大多数事件都是小问题,例如单个客户端在工作量证明中分叉链,或者其区块在权益证明中变为孤块。

最重要的一次事件发生在 Holesky 测试网上的 Pectra 激活期间。网络上的六个客户端中有四个客户端的存款合约配置不正确。不正确的链不是被孤立,而是被证明是合理的,并且副作用在 Holesky 上持续存在,即使在达到最终确定性之后。

通过提供一种 RPC 方法,允许客户端在下一个硬分叉之前报告关键配置变量,运维团队可以更加确信客户端已正确配置并为即将到来的分叉做好准备。

目标受众和用例

此方法旨在供节点运营商、验证者团队和网络监控工具使用,以验证客户端是否为即将到来的分叉做好准备。用例包括:

  • 自动化的分叉前验证脚本,用于比较节点之间的 eth_config 输出。
  • 验证者运营商的手动检查,以确保与分叉规范保持一致。
  • 客户端开发人员的调试,以识别配置不匹配。
  • 共识层对应方的自动检查

规范

本文档中的关键字“必须(MUST)”,“禁止(MUST NOT)”,“需要(REQUIRED)”,“将要(SHALL)”,“将不(SHALL NOT)”,“应该(SHOULD)”,“不应该(SHOULD NOT)”,“推荐(RECOMMENDED)”,“不推荐(NOT RECOMMENDED)”,“可以(MAY)”和“可选(OPTIONAL)”应按照 RFC 2119 和 RFC 8174 中的描述进行解释。

客户端必须公开一个新的 RPC 方法,以通过标准 JSON-RPC 端口报告当前功能配置和预期的下一个配置。

客户端可以通过 Engine API 公开此方法。

客户端可以使用这些配置对象来管理其每个分叉的配置,但它们不应该简单地返回未经处理的配置数据。

在报告当前和下一个配置时,客户端必须包含此 EIP 中指定的每个配置参数。

客户端必须返回最新的配置值,以反映它们提供的最新区块头。如果客户端缓存配置,则必须确保在跨越分叉边界时清除此类缓存。

配置 RPC

引入了一个新的 JSON-RPC API,eth_config。它不带参数,并返回下一节中指定的结果对象。

结果对象结构

RPC 响应包含两种类型的四个成员:

"current" 和 "next" 成员分别包含当前生效的配置对象和下一个配置,如果客户端未配置为支持未来的分叉,则为空。

"currentHash" 和 "nextHash" 成员分别包含当前配置和下一个配置的哈希值,如果下一个配置也为空,则为空。

将分叉配置转换为哈希值

要生成分叉哈希,表示分叉配置的 JSON 对象按照 RFC-8785 转换为规范形式(简而言之,没有空格,排序的键,以及最简单的数字值)。然后使用 CRC-32 对结果进行哈希处理。

配置对象必须精确包含分叉的 meta-EIP 中指定的参数及其配置的值 —— 不多也不少。解释性注释或客户端特定的扩展不得包含在结果对象中。

配置对象中的字段

每个配置对象必须包含以下字段,按规范顺序呈现。此 RPC 假定网络是合并后的,并且未指定与工作量证明相关的问题。

未来的分叉可以添加、调整、删除或更新字段。相应的更改必须在其各自的 meta-EIP 中定义。

activationTime

分叉激活时间戳,表示为 Unix 纪元秒数(UTC)的 JSON 数字。对于“current”配置,这反映了实际激活时间;对于“next”,如果已知,则为计划时间,如果未计划,则为空。

blobsSchedule

特定分叉的 blob 配置参数,如 genesis 文件中定义的那样。这是一个 JSON 对象,包含三个成员 —— basefeeUpdateFractionmaxtarget —— 所有这些都表示为 JSON 数字。

chainId

当前网络的链 ID,表示为带有无符号 0x 前缀的十六进制数字的字符串,并删除所有前导零。此规范不支持没有链 ID 或链 ID 为零的链。

precompiles

分叉的活动预编译合约的表示。如果预编译被链上合约替换,则不包括在内。

这是一个 JSON 对象,其中的成员是预编译的 20 字节 0x 前缀十六进制地址(保留零),值是每个合约的约定名称,通常在定义该合约的 EIP 中指定。

对于 Cancun,合约名称是(按顺序):ECRECSHA256RIPEMD160IDMODEXPBN256_ADDBN256_MULBN256_PAIRINGBLAKE2FKZG_POINT_EVALUATION

对于 Prague,添加的合约是(按顺序):BLS12_G1ADDBLS12_G1MULTIEXPBLS12_G2ADDBLS12_G2MULTIEXPBLS12_PAIRINGBLS12_MAP_FIELD_TO_CURVEBLS12_MAP_FIELD_TO_CURVE

systemContracts

一个 JSON 对象,表示与分叉相关的系统级合约,如其定义 EIP 中引入的那样。键是合约名称(例如,BEACON_ROOTS_ADDRESS),来自它们首次出现的 EIP,按字母顺序排序。值是 0x 前缀十六进制形式的 20 字节地址,保留前导零。在 Cancun 之前的分叉中省略。

对于 Cancun,唯一的系统合约是 BEACON_ROOTS_ADDRESS

对于 Prague,系统合约是(按顺序):BEACON_ROOTS_ADDRESSCONSOLIDATION_REQUEST_PREDEPLOY_ADDRESSDEPOSIT_CONTRACT_ADDRESSHISTORY_STORAGE_ADDRESSWITHDRAWAL_REQUEST_PREDEPLOY_ADDRESS

未来的分叉必须在其 meta-EIP 中定义系统合约的列表。

理由

为什么要枚举预编译合约?(一般来说,为什么要跟踪特定的配置项?)

本规范的目的是使节点能够在分叉之前声明它们已加载并准备好正确的配置。过去的测试网和主网分叉已经揭示了客户端存在不正确的预编译集、链 ID、存款合约地址和其他配置错误。

特别是对于预编译合约,已经讨论过在未来的分叉中删除或替换预编译合约,因此完整枚举预编译合约将反映删除。

通常,如果可配置的变量或常量导致客户端在分叉时发生分歧 —— 无论是在主网、测试网、开发网还是公共 rollup 上 —— 该变量或常量都是可报告配置的候选对象。

完整的配置而不是增量

最初的设计考虑为“next”分叉使用部分配置,而不是完整的配置。但是,对过去事件的分析表明,导致分歧的一些参数(例如,存款合约)是在较早的分叉中引入的,由于依赖于这些配置的无关 EIP,因此在随后的分叉中发生了共识失败。部分“next”配置哈希将无法检测到此类错误。

另一种方法是将先前分叉的哈希嵌入到下一个分叉中 —— 将需要定义用于提取差异和合并配置的规则,以及指定所有先前的分叉配置哈希。这也会使追溯添加参数(例如,gas 计划常量和变量)变得复杂。

嵌套变量与扁平变量

嵌套结构更易于阅读,而扁平结构更易于合并。由于本规范对当前和下一个分叉使用完整配置,因此无需合并,从而使可读性成为首要任务。

提供 genesis.json 中未指定的数据

一些报告的值是规范级别的常量,许多客户端未将其包含在其配置文件中。但是,某些 EIP 常量(例如,存款合约)已成为测试网中的变量,因此有必要将其包括在内。

JSON 作为配置格式

选择 JSON 是因为它的普遍性、机器和人类的可读性,以及通过 RFC-8785 存在的标准规范形式。YAML 缺少标准规范形式。没有以太坊软件使用 XML 进行配置,采用它会增加每个客户端的库大小。可以发明一种格式,但需要在本规范中进行定义和标准化。

CRC-32 作为哈希格式

使用 CRC-32 而不是加密哈希的原因与 EIP-2124 中的原因相同,并通过引用合并。简而言之,节点可能会说谎,减少 4 字节是为了方便而不是安全,并且 CRC-32 已被广泛实现。

向后兼容性

此 EIP 不会更改先前的行为。Cancun 之前的配置是非标准的,共享 Cancun 之前配置的客户端将产生非标准结果。

支持 Cancun 之前的分叉的客户端可以返回部分或非标准配置,但应该努力遵循为 Cancun 配置指定的字段的精神。仅 Cancun 及以后的分叉需要完全合规。

测试用例

示例配置

Holesky Prague 配置

{
  "activationTime": 1740434112,
  "blobSchedule": {
    "baseFeeUpdateFraction": 5007716,
    "max": 9,
    "target": 6
  },
  "chainId": "0x4268",
  "precompiles": {
    "0x0000000000000000000000000000000000000001": "ECREC",
    "0x0000000000000000000000000000000000000002": "SHA256",
    "0x0000000000000000000000000000000000000003": "RIPEMD160",
    "0x0000000000000000000000000000000000000004": "ID",
    "0x0000000000000000000000000000000000000005": "MODEXP",
    "0x0000000000000000000000000000000000000006": "BN256_ADD",
    "0x0000000000000000000000000000000000000007": "BN256_MUL",
    "0x0000000000000000000000000000000000000008": "BN256_PAIRING",
    "0x0000000000000000000000000000000000000009": "BLAKE2F",
    "0x000000000000000000000000000000000000000a": "KZG_POINT_EVALUATION",
    "0x000000000000000000000000000000000000000b": "BLS12_G1ADD",
    "0x000000000000000000000000000000000000000c": "BLS12_G1MULTIEXP",
    "0x000000000000000000000000000000000000000d": "BLS12_G2ADD",
    "0x000000000000000000000000000000000000000e": "BLS12_G2MULTIEXP",
    "0x000000000000000000000000000000000000000f": "BLS12_PAIRING",
    "0x0000000000000000000000000000000000000010": "BLS12_MAP_FIELD_TO_CURVE",
    "0x0000000000000000000000000000000000000011": "BLS12_MAP_FIELD_TO_CURVE"
  },
  "systemContracts": {
    "BEACON_ROOTS_ADDRESS": "0x000f3df6d732807ef1319fb7b8bb8522d0beac02",
    "CONSOLIDATION_REQUEST_PREDEPLOY_ADDRESS": "0x0000bbddc7ce488642fb579f8b00f3a590007251",
    "DEPOSIT_CONTRACT_ADDRESS": "0x4242424242424242424242424242424242424242",
    "HISTORY_STORAGE_ADDRESS": "0x0000f90827f1c53a10cb7a02335b175320002935",
    "WITHDRAWAL_REQUEST_PREDEPLOY_ADDRESS": "0x00000961ef480eb55e80d19ad83579a64c007002"
  }
}

Holesky Cancun 配置

{
  "activationTime": 1707305664,
  "blobSchedule": {
    "baseFeeUpdateFraction": 3338477,
    "max": 6,
    "target": 3
  },
  "chainId": "0x4268",
  "precompiles": {
    "0x0000000000000000000000000000000000000001": "ECREC",
    "0x0000000000000000000000000000000000000002": "SHA256",
    "0x0000000000000000000000000000000000000003": "RIPEMD160",
    "0x0000000000000000000000000000000000000004": "ID",
    "0x0000000000000000000000000000000000000005": "MODEXP",
    "0x0000000000000000000000000000000000000006": "BN256_ADD",
    "0x0000000000000000000000000000000000000007": "BN256_MUL",
    "0x0000000000000000000000000000000000000008": "BN256_PAIRING",
    "0x0000000000000000000000000000000000000009": "BLAKE2F",
    "0x000000000000000000000000000000000000000a": "KZG_POINT_EVALUATION"
  },
  "systemContracts": {
    "BEACON_ROOTS_ADDRESS": "0x000f3df6d732807ef1319fb7b8bb8522d0beac02"
  }
}

示例 JSON-RPC

以下 RPC 命令在 Holesky 上在 Prague 被安排但未激活时发出:

curl -X POST -H "Content-Type: application/json" --data '{"jsonrpc":"2.0","method":"eth_config","id":1}' http://localhost:8545

将返回(格式化后):

{
  "jsonrpc": "2.0",
  "id": 1,
  "result": {
    "current": {
      "activationTime": 1707305664,
      "blobSchedule": {
        "baseFeeUpdateFraction": 3338477,
        "max": 6,
        "target": 3
      },
      "chainId": "0x4268",
      "precompiles": {
        "0x0000000000000000000000000000000000000001": "ECREC",
        "0x0000000000000000000000000000000000000002": "SHA256",
        "0x0000000000000000000000000000000000000003": "RIPEMD160",
        "0x0000000000000000000000000000000000000004": "ID",
        "0x0000000000000000000000000000000000000005": "MODEXP",
        "0x0000000000000000000000000000000000000006": "BN256_ADD",
        "0x0000000000000000000000000000000000000007": "BN256_MUL",
        "0x0000000000000000000000000000000000000008": "BN256_PAIRING",
        "0x0000000000000000000000000000000000000009": "BLAKE2F",
        "0x000000000000000000000000000000000000000a": "KZG_POINT_EVALUATION"
      },
      "systemContracts": {
        "BEACON_ROOTS_ADDRESS": "0x000f3df6d732807ef1319fb7b8bb8522d0beac02"
      }
    },
    "currentHash": "9c186ad4",
    "next": {
      "activationTime": 1740434112,
      "blobSchedule": {
        "baseFeeUpdateFraction": 5007716,
        "max": 9,
        "target": 6
      },
      "chainId": "0x4268",
      "precompiles": {
        "0x0000000000000000000000000000000000000001": "ECREC",
        "0x0000000000000000000000000000000000000002": "SHA256",
        "0x0000000000000000000000000000000000000003": "RIPEMD160",
        "0x0000000000000000000000000000000000000004": "ID",
        "0x0000000000000000000000000000000000000005": "MODEXP",
        "0x0000000000000000000000000000000000000006": "BN256_ADD",
        "0x0000000000000000000000000000000000000007": "BN256_MUL",
        "0x0000000000000000000000000000000000000008": "BN256_PAIRING",
        "0x0000000000000000000000000000000000000009": "BLAKE2F",
        "0x000000000000000000000000000000000000000a": "KZG_POINT_EVALUATION",
        "0x000000000000000000000000000000000000000b": "BLS12_G1ADD",
        "0x000000000000000000000000000000000000000c": "BLS12_G1MULTIEXP",
        "0x000000000000000000000000000000000000000d": "BLS12_G2ADD",
        "0x000000000000000000000000000000000000000e": "BLS12_G2MULTIEXP",
        "0x000000000000000000000000000000000000000f": "BLS12_PAIRING",
        "0x0000000000000000000000000000000000000010": "BLS12_MAP_FIELD_TO_CURVE",
        "0x0000000000000000000000000000000000000011": "BLS12_MAP_FIELD_TO_CURVE"
      },
      "systemContracts": {
        "BEACON_ROOTS_ADDRESS": "0x000f3df6d732807ef1319fb7b8bb8522d0beac02",
        "CONSOLIDATION_REQUEST_PREDEPLOY_ADDRESS": "0x0000bbddc7ce488642fb579f8b00f3a590007251",
        "DEPOSIT_CONTRACT_ADDRESS": "0x4242424242424242424242424242424242424242",
        "HISTORY_STORAGE_ADDRESS": "0x0000f90827f1c53a10cb7a02335b175320002935",
        "WITHDRAWAL_REQUEST_PREDEPLOY_ADDRESS": "0x00000961ef480eb55e80d19ad83579a64c007002"
      }
    },
    "nextHash": "1c6a3b9f"
  }
}

参考实现

Besu 中的示例实现

安全考虑事项

  • 暴露风险:不正确的配置可能会泄露操作细节。运营商应该eth_config 限制为受信任的接口(例如,本地访问或经过身份验证的端点)。
  • 不诚实的节点:客户端可能会报告虚假配置。对等方或监控工具可以交叉检查 eth_config 输出与已知的分叉规范或其他节点的响应,以检测异常。
  • DDoS 缓解:客户端应该在内部缓存配置对象并限制 eth_config 请求的速率,以防止资源耗尽。实现可以施加最小响应间隔(例如,1 秒)。

版权

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

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

0 条评论

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