
reth 新硬分叉集成实战指南从 HARDFORK-CHECKLIST 读懂 alloy 类型、Engine API 与校验器的三层改造路径【免费下载链接】rethModular, contributor-friendly and blazing-fast implementation of the Ethereum protocol, in Rust项目地址: https://gitcode.com/GitHub_Trending/re/reth在以太坊客户端的开发中接入一个新硬分叉或 devnet往往意味着从最底层的数据类型到最上层的 Engine API 端点都要动刀。reth 仓库根目录下的 HARDFORK-CHECKLIST.md 正是为此准备的非穷尽式集成清单它把一次硬分叉改造拆成三个层次alloy 基础类型层、Engine API 类型层、reth 实现层。读完本文你将掌握这份清单中每一条目的落点新 EIP 数据结构和交易类型应该写进哪个 crate、ExecutionPayloadSidecar容器承载了什么、以及EngineApitrait 与EngineValidatortrait 各自要更新哪些方法并能沿着文中给出的源码路径在仓库中逐一定位实现。一、清单的整体脉络一次硬分叉改造的三层分工HARDFORK-CHECKLIST.md 虽然篇幅不长但它勾勒出的改造路径非常清晰且与 reth 当前的依赖结构严格对应引入新的 EIP 类型或修改基础数据类型Introducing new EIP types or changes to primitive types——这一层落在外部的 alloy 生态 cratealloy-eips、alloy-consensusEngine API 类型变更Engine API——新的engine_newPayloadVx/engine_getPayloadVx端点类型与ExecutionPayloadSidecar扩展落在alloy-rpc-types-enginereth 自身的改动Reth changes——EngineApitrait 的新端点、ExecutionPayload ExecutionPayloadSidecar到Block的转换、EngineValidatortrait 的版本化校验。这种分层的前提是 reth 把协议原语外包给了 alloy。从工作区根目录 Cargo.toml 可以看到当前的版本锁定alloy-eips与alloy-consensus均为2.4.2alloy-primitives为1.6.1另有alloy-hardforks 0.4.8。也就是说清单中先改 alloy这一步在 reth 仓库侧对应的操作是升级这些依赖版本并适配新字段——这也是清单标题自称Non-exhaustive非穷尽的原因它给出的是关键落点而非完整 PR 流程。二、清单第一层新 EIP 类型与基础数据结构的改动2.1 新 EIP 的数据结构先落到alloy-eips清单第一条写道所有新的 EIP 数据结构、常量、辅助函数等All new EIP data structures/constants/helpers etc.一律先进alloy-eipscrate。这一约定的意义在于把与具体 EIP 编号绑定的数据如eip4844的 blob 相关结构、eip7685的执行请求类型与协议执行解耦reth 中所有 crate 通过依赖引入即可复用。在 reth 仓库内可以直接看到这种从alloy_eips消费的模式。例如 Engine API 的服务端 trait 定义 crates/rpc/rpc-api/src/engine.rs 开头就导入use alloy_eips::{ eip4844::{BlobAndProofV1, BlobAndProofV2, BlobCellsAndProofsV1}, eip7685::RequestsOrHash, BlockId, BlockNumberOrTag, };其中RequestsOrHash是 EIP-7685执行层请求的抽象被new_payload_v4/new_payload_v5/new_payload_v6等多个端点作为参数使用见 engine.rs L69-L101。从源码结构看凡是清单中说的新 EIP 数据结构最终都会像RequestsOrHash一样出现在这些端点的签名里——这为判断一个新类型放对了位置提供了一个可验证的检验点。2.2 新交易类型进入alloy-consensus清单明确区分了两类原语EIP 数据结构放alloy-eips新交易类型放alloy-consensus。交易类型属于共识层定义RLP 编码、字段校验而 EIP 数据结构往往还包含与 RPC、状态读取相关的辅助形态因此二者的归属 crate 不同。对 reth 开发者而言这意味着新增交易类型时除了升级 alloy 依赖还要检查交易解析与池侧的适配仓库中对alloy-consensus的引用遍布各 crate工作区Cargo.toml中alloy-consensus { version 2.4.2, default-features false }Cargo.toml L454。2.3 修改既有结构Header/Block时改alloy-consensus以 Prague 的request_hashes为例清单第三点指出若变更触及既有数据结构如Header或Block要直接改alloy-consensus中的类型并给出实例——Prague 分叉在Header上新增的request_hashes字段。这条经验值得展开硬分叉对头部字段的改动会同时波及 RLP/JSON 序列化、Merkle 计算与 P2P 消息校验所以必须从类型源头alloy-consensus改起而不是在 reth 内做补丁式扩展。三、清单第二层Engine API 类型的扩展3.1 新engine_newPayloadVx/engine_getPayloadVx端点 →alloy-rpc-types-engine清单的 Engine API 部分规定如果硬分叉带来新的engine_newPayloadVx与engine_getPayloadVx端点对就把新类型加到alloy-rpc-types-enginecrate。reth 的 Engine API trait 对这一依赖的消费同样直接可见——crates/rpc/rpc-api/src/engine.rs 从alloy_rpc_types_engine导入ExecutionPayloadV1、ExecutionPayloadV3、ExecutionPayloadV4、ForkchoiceState、ForkchoiceUpdated、PayloadId、PayloadStatus等全部端点参数/返回值类型。从 engine.rs 的实际方法清单可以读到版本与分叉的对应关系这也是理解为什么要加 Vx的最好参照端点版本对应分叉语境关键差异源自代码注释newPayloadV1/getPayloadV1Paris不应接受withdrawals字段L46-L49newPayloadV2/getPayloadV2Shanghaipayload attributes 中新增withdrawalsL113-L127newPayloadV3/getPayloadV3Cancun增加versioned_hashes、parent_beacon_block_rootL55-L64newPayloadV4/getPayloadV4Prague再增加execution_requests: RequestsOrHashL66-L76newPayloadV5/getPayloadV5Amsterdam / OsakaV5 使用ExecutionPayloadV4getPayloadV5注释标注为 Post OsakaL78-L88、L230-L241newPayloadV6/forkchoiceUpdatedV5Bogota代码注释明确为 stub即 devnet 进行中的占位实现L90-L101特别注意forkchoiceUpdatedV4Amsterdam 起 payload attributes 增加slotNumber字段同时引入了第三个位置参数custody_columns: OptionB128——这是 EIP-8070 稀疏 blobpool 的 custody-column 位图设置时必须为 16 字节且只传 custody columns 不传 payload attributes 时第二参数仍须为nullengine.rs L143-L165。这类参数个数与空值约定的细节正是新端点最容易出错的协议点也是清单要求把新参数写对的原因。此外从 Prague 开始还出现了getInclusionListV1FOCIL 包含列表L256-L260与带block_access_list的getPayloadBodiesByHashV2/getPayloadBodiesByRangeV2EIP-7928L269-L317说明 Engine API 的版本化不止停留在newPayload/getPayload一对端点上。3.2ExecutionPayloadSidecar把payload 转 block 所需的全部附加参数装进一个容器清单给出了ExecutionPayloadSidecar的职责定义如果engine_newPayloadVx端点有新参数就加进ExecutionPayloadSidecar容器类型。这个类型包含把ExecutionPayload转换成 EL block 所需的全部附加参数。This types contains all additional parameters that are required to convert anExecutionPayloadto an EL block.在 reth 中可以直接看到这套容器化设计在用的样子。Engine API 的实现 crates/rpc/rpc-engine-api/src/engine_api.rs 中端点收到的执行数据被组织成ExecutionData { payload, sidecar }并且 sidecar 按版本构造V1/V2 场景ExecutionPayloadSidecar::none()如 engine_api.rs L1350、L1360CancunExecutionPayloadSidecar::v3(CancunPayloadFields { ... })L1377PragueExecutionPayloadSidecar::v4(...)L1404、L1433更新的版本ExecutionPayloadSidecar::v6(...)L1460。也就是说每个newPayloadVx端点多出来的参数在 reth 内部统一收敛为 sidecar 的一个版本构造子。这解释了清单为何把 sidecar 列为 Engine API 层的一等公民新增端点参数时先加 sidecar 变体下游的payload → block转换与校验才能拿到完整字段。对应的测试文件 crates/rpc/rpc-engine-api/tests/it/payload.rs 同样引用了ExecutionPayloadSidecar是验证各版本转换行为的现成参照。四、清单第三层reth 仓库内的三处必改点清单 Reth changes 一节列出三个子项逐一在仓库中都有明确落点。4.1 在EngineApitrait 中添加新端点并实现Engine API 的服务端契约定义在 crates/rpc/rpc-api/src/engine.rs L45 的pub trait EngineApiEngine: EngineTypes。注意该 trait 上方的注释L36-L41由于 jsonrpsee 的rpc宏无法理解关联类型这里刻意用泛型Engine: EngineTypes替代关联类型且DeserializeOwned边界必须手工添加——新增端点方法时要保持与现有#[cfg_attr(..., rpc(server, namespace engine))]相同的模式。EngineTypes抽象来自 crates/engine/primitives/src/lib.rs 一带的引擎类型体系同文件还定义了EngineApiValidatortrait。实现侧则经由 node builder 装配crates/node/builder/src/rpc.rs 定义了EngineValidatorAddOn、EngineValidatorBuilder与EngineApiBuilder三个构建器 traitL1402节点可以通过它们扩展/校验器插件化。从源码结构看新增一个newPayloadVx端点的完整链路是EngineApitrait 加方法 → 服务端实现调用对应版本的ExecutionData构造含 sidecar→ 交给 tree 侧校验。4.2 更新ExecutionPayload ExecutionPayloadSidecar→Block的转换清单原文如果有额外参数更新ExecutionPayloadExecutionPayloadSidecar到Block的转换。这一步的承接者就是上一节提到的EngineValidator契约中的convert_payload_to_blockThis function must convert the payload into the executable block and pre-validate its fields. Implementers should ensure that the checks are done in the order that conforms with the engine-API specification.见 crates/engine/tree/src/tree/payload_validator.rs L1750-L1753。其签名fn convert_payload_to_block(self, payload: Types::ExecutionData) - ResultSealedBlockN::Block, NewPayloadError说明sidecar 携带的新字段如 Prague 的execution_requests、Amsterdam 的 custody columns 相关参数会在这里被消费最终装配为可执行的密封块。端点多一个参数而转换少取一个字段是最典型的payload 通过但语义错误的 bug清单把它单列一条正是这个原因。4.3 更新EngineValidatortrait 的版本化校验第三个必改点更新EngineValidatortrait 中的版本特定校验检查。该 trait 定义在 crates/engine/tree/src/tree/payload_validator.rs L1722-L1793核心方法与硬分叉工作的关系如下validate_payload_attributes_against_header校验 payload attributes 与头部的关系默认强制 payloadAttributes.timestamp 必须大于 forkchoiceState.headBlockHash 所指块的 timestampL1727-L1740。新分叉若改变属性集合如slotNumber、custodyColumns校验规则必须同步convert_payload_to_block如上所述payload 到可执行块的转换与预校验L1742-L1753validate_payload/validate_block分别校验来自 Engine API 的 payload 与来自 P2P 网络的块L1755-L1767on_inserted_executed_block、on_canonical_head_changed、payload_builder_resources块插入后的状态更新、规范头切换通知、以及向 payload builder 作业发放资源L1769-L1792。trait 的默认实现BasicEngineValidator从 L1795 开始对DatabaseProviderFactoryStateProviderFactory等约束做泛型化——新分叉引入的状态规则例如对执行请求的校验通常就是在这条实现链上按块号/时间戳落在哪个分叉分支处理。五、配套机制分叉激活条件的存放位置清单聚焦于类型与 API 层但硬分叉落地还离不开激活条件reth 中这部分有独立的一层。crates/ethereum/hardforks/src/hardforks/mod.rs 定义了Hardforkstrait 与ChainHardforks结构ChainHardforks::new要求分叉列表按激活顺序排列并注释说明等价的以太坊分叉必须包含L53-L61激活条件类型ForkCondition覆盖Block/TTD/Timestamp/Never四种形态L84-L92fork_block会按形态提取对应值——从源码结构看时间戳激活Cancun 及之后的主流方式与块号/TTD 激活在此统一抽象fork_id按 EIP-6122 计算latest_fork_id返回最新实现的分叉标识并特别注释在很多情况下这会是给定网络上的未来ForkIdL30-L37同目录 dev.rs 提供DEV_HARDFORKS与仓库名hard fork/devnet的清单定位相呼应devnet 阶段的分叉激活同样走这套结构。而具体链的分叉参数则与链规格chainspec绑定genesis 文件位于 crates/chainspec/res/genesis含 mainnet、sepolia、holesky、hoodi 等 JSON新增/调整分叉时需要在对应链规格中登记激活条件。六、小结按清单执行的最小改动路径把 HARDFORK-CHECKLIST.md 的三个小节与仓库证据合并一个新硬分叉或 devnet在 reth 中的标准改造顺序是alloy 层新 EIP 数据结构/常量/辅助函数进alloy-eips新交易类型与Header/Block等既有结构变更如 Prague 的request_hashes进alloy-consensus随后在 reth 工作区 Cargo.toml 中升级对应 alloy 版本Engine API 类型层新的engine_newPayloadVx/engine_getPayloadVx参数类型进alloy-rpc-types-engine端点新增参数一律加进ExecutionPayloadSidecar容器参照 engine_api.rs 中v3/v4/v6的既有构造子模式reth 实现层在 EngineApi trait 增加并实现新端点更新ExecutionPayload Sidecar → Block转换经由 EngineValidator::convert_payload_to_block更新 EngineValidator 中版本特定的属性/块校验激活条件与测试在 ChainHardforks 体系与链规格 genesis 中登记分叉激活条件并沿用 crates/rpc/rpc-engine-api/tests/it/payload.rs 等既有用例验证各版本 payload 的转换行为。需要说明的是该清单自我标注为Non-exhaustive非穷尽文中给出的端点版本表与行号均以当前仓库实际内容为准例如newPayloadV6/forkchoiceUpdatedV5目前仍是 Bogota devnet 的 stub 实现如果你的目标是接入一个尚未合入的最新分叉应以 alloy 与执行层 API 规范的最新演进为准再回看本文中的路径定位改动点。【免费下载链接】rethModular, contributor-friendly and blazing-fast implementation of the Ethereum protocol, in Rust项目地址: https://gitcode.com/GitHub_Trending/re/reth创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考