ARTICLE DETAIL

资讯详情

深耕郑州网站建设与运营推广的一线实战洞察。

Foundry Anvil 在 eth_simulateV1 中输出区块访问列表哈希:Amsterdam 硬分叉后的实现与验证

Foundry Anvil 在 eth_simulateV1 中输出区块访问列表哈希:Amsterdam 硬分叉后的实现与验证 Foundry Anvil 在 eth_simulateV1 中输出区块访问列表哈希Amsterdam 硬分叉后的实现与验证【免费下载链接】foundryFoundry is a blazing fast, portable and modular toolkit for Ethereum application development written in Rust.项目地址: https://gitcode.com/GitHub_Trending/fo/foundry本篇围绕 Foundry 仓库中一条 Anvil 的 patch 级变更展开在eth_simulateV1返回的模拟区块头中将计算得到的区块访问列表哈希Block Access List HashBAL Hash随头部字段一并输出且仅在 Amsterdam 硬分叉生效之后才填充该字段。读完本文你将掌握eth_simulateV1模拟区块头的字段构成、区块访问列表哈希的计算与放置逻辑、Amsterdam 分叉开关对它的门控方式以及仓库中用于验证这一行为的集成测试细节可直接在自己的链上开发与测试工具链中复现与使用。变更背景一条 changelog 背后的功能.changelog/anvil-simulate-block-access-list-hash.md是仓库采用 changelog 片段fragment机制维护的变更记录原文只有一句话anvil: patch— Include the computed block access list hash ineth_simulateV1block headers after Amsterdam.它声明了一个 patch 级向后兼容的缺陷修复/小增强行为变更在 Amsterdam 硬分叉激活之后Anvil 的eth_simulateV1返回的每个模拟区块头中会包含计算得到的区块访问列表哈希字段。这里的区块访问列表哈希对应的是围绕区块级访问列表Block Access ListBAL的规范——在仓库依赖的alloy_eips中由eip7928模块承载。从 crates/anvil/tests/it/simulate.rs 的导入可以看到该模块暴露的核心类型AccountChanges某个账户在区块生命周期内发生的全部变更nonce 变更、存储槽读写/变更SlotChanges、StorageChange、NonceChange、BlockAccessIndex描述具体存储槽与 nonce 变化并携带其在访问序列中的索引compute_block_access_list_hash将排序后的AccountChanges列表计算为最终的 32 字节哈希EMPTY_BLOCK_ACCESS_LIST_HASH空访问列表对应的常量哈希。简言之区块访问列表试图把区块执行过程中读写了哪些账户与存储槽以确定性的方式压缩成一个可验证的哈希Anvil 在模拟eth_simulateV1与出块路径上都需要正确携带它以保证返回的区块头与主网共识规则一致。行为细节什么条件下会出现 blockAccessListHash该变更的核心行为可以用分叉门控 字段填充两句话概括Amsterdam 之后才填充只有当前模拟区块时间戳已经激活 Amsterdam 硬分叉时区块头中才会带上blockAccessListHash字段在此之前例如 Osaka 或更早硬分叉下该字段不会出现。每个模拟区块独立计算eth_simulateV1可以一次请求多个blockStateCalls产生一串连续模拟区块每个区块头都携带自己的访问列表哈希且后一个区块的parentHash链到前一个区块的hash因此访问列表哈希会实质影响链式区块哈希的最终结果。这一行为在 crates/anvil/tests/it/simulate.rs 的test_simulate_block_access_list_hash_rpc中被逐条断言测试分别在Osaka与Amsterdam两种硬分叉下、以及traceTransfers为false/true两种参数组合下发起eth_simulateV1请求并断言Amsterdam 下返回的区块对象带有blockAccessListHash且值等于本地用compute_block_access_list_hash预计算的expected_hash非 AmsterdamOsaka下区块对象不包含blockAccessListHash键区块头的hash与header.hash_slow()一致即该字段确实参与头部哈希计算对一个空调用的模拟区块blockAccessListHash仍是字符串但值不同于有访问行为的区块说明空区块使用空列表的哈希而一旦有状态访问哈希即随之变化。源码实现解析哈希从哪来、放到哪里去1. 模拟路径从 BAL 状态构建器到区块头字段eth_simulateV1的核心实现在 crates/anvil/src/eth/backend/mem/mod.rs 的simulate_at内部。模拟开始时L8061cache_db.bal_state被初始化为带 BAL 构建器的状态跟踪器cache_db.bal_state BalState::new().with_bal_builder();执行完一个区块内的全部调用后模拟循环从 BAL 状态构建器中取出已收集的访问列表数据并计算区块访问列表哈希L8456-L8459let block_access_list_hash cache_db .bal_state .take_built_alloy_bal() .map(|bal| compute_block_access_list_hash(bal.as_slice()));随后该值被写入Header的block_access_list_hash字段L8460-L8461与logs_bloom、transactions_root、receipts_root、parent_hash、base_fee_per_gas等字段一起构造出完整的模拟区块头最后通过header.hash_slow()计算区块哈希L8493并作为parentHash传递给下一个模拟区块。Header结构体中对应字段的定义可以在 crates/anvil/core/src/eth/block.rs 一带看到block_access_list_hash是一个可空的B256字段其余各处如该文件 的默认构造路径在非 Amsterdam 语境下保持None。2. 分叉开关is_amsterdam 如何决定字段是否出现在 crates/anvil/src/eth/backend/mem/mod.rs 处Anvil 用创世配置中的amsterdam_time判定当前区块时间戳是否已进入 Amsterdamlet is_amsterdam genesis.config.amsterdam_time.is_some_and(|fork| fork timestamp);若amsterdam_time未配置链未声明 Amsterdam 激活时间或当前区块时间戳早于激活时间则is_amsterdam为false模拟区块头中的block_access_list_hash保持NoneRPC 输出中不会出现blockAccessListHash键反之则按上文流程填充计算哈希。同一个开关也作用于常规出块路径在 L9581 处Anvil 出块时为 Amsterdam 之后的区块写入EMPTY_BLOCK_ACCESS_LIST_HASH空列表哈希保证即使区块没有任何访问行为头部字段也是确定性的常量而非缺失。3. 从调用链到 RPC 输出模拟产生的SimulatedBlock最终以 RPC 对象返回区块头被包装进AnyRpcHeader并序列化为 JSONblockAccessListHash因此作为区块对象的顶层字段暴露给调用方见 crates/anvil/src/eth/backend/mem/mod.rs 附近对alloy_rpc_types::Block的组装逻辑。也就是说这次 changelog 变更不是另起炉灶而是在既有eth_simulateV1区块构造流程中补上了 Amsterdam 规范要求缺失的头部字段使模拟结果与真实出块行为对齐。测试验证如何确认该字段行为正确仓库用 crates/anvil/tests/it/simulate.rs 中的test_simulate_block_access_list_hash_rpc全面覆盖了这一变更其验证手法值得借鉴构造确定性的访问模式。测试通过stateOverrides将系统合约HISTORY_STORAGE_ADDRESS、BEACON_ROOTS_ADDRESS、提款/存款请求预部署地址等的代码覆盖为0x再对HISTORY_STORAGE_ADDRESS与WITHDRAWAL_REQUEST_PREDEPLOY_ADDRESS注入固定的写槽字节码0x602a5f5500即向 slot 0 写入 42对测试合约注入0x5f5450602a60015500读 slot 0、写 slot 1从而让谁读了哪个槽、谁写了哪个槽完全确定便于在测试侧用同一套AccountChanges数据结构复算期望哈希。本地复算期望值。测试手工构造expected系统合约的存储变更、from账户的 nonce 变更、contract的存储读与存储变更、beneficiary的空变更按地址排序后调用compute_block_access_list_hash得到expected_hashL105-L129再与 RPC 返回值逐字节比对。分叉与参数矩阵。测试对Osaka/Amsterdam两种硬分叉 ×traceTransfers两种取值分别断言Amsterdam 下有字段且等于期望哈希Osaka 下无字段第三个空模拟区块的哈希存在但不同于有访问的区块且所有区块的hash与header.hash_slow()一致、相邻区块parentHash正确串联。如需在本地复现可在仓库根目录用cargo test -p anvil并指定该测试名test_simulate_block_access_list_hash_rpc运行 anvil 集成测试套件测试会自动拉起内存节点、通过 HTTP RPC 发起eth_simulateV1请求并完成上述断言。对使用者的影响与注意事项面向链上工具与测试框架如果你依赖eth_simulateV1做交易批处理预演、MEV 策略回放或状态差异分析在配置了 Amsterdam 激活时间的链上现在可以直接从返回区块对象中读取blockAccessListHash无需自行复算访问列表。分叉配置决定字段有无Anvil 默认测试链如果未配置amsterdam_time该字段不会出现只有在genesis.config.amsterdam_time配置且区块时间戳达到激活时间后才会填充判断时应以链配置而非 Anvil 版本为准。字段参与区块哈希block_access_list_hash是头部字段之一直接影响header.hash_slow()的结果进而影响模拟区块的parentHash链。任何依赖模拟区块哈希做后续计算的场景都应意识到该字段已纳入哈希输入。空区块也有确定性哈希Amsterdam 下的空访问区块使用EMPTY_BLOCK_ACCESS_LIST_HASH常量出块路径或对空列表计算得到的哈希模拟路径而不是缺失字段消费方可以据此区分未激活分叉与激活但无访问两种状态。总结这条 changelog 片段背后是一次小而完整的共识对齐改动Anvil 在eth_simulateV1的模拟区块头构造流程中接入区块访问列表哈希计算并通过amsterdam_time时间戳判断实现分叉门控配套集成测试用确定性状态覆盖与本地复算的方式对字段有无、哈希值正确性、区块哈希一致性做了全矩阵验证。理解这条变更等于同时掌握了 Anvil 模拟区块头的构造链路、BAL 哈希的计算入口以及 Foundry 仓库changelog 片段 集成测试驱动的功能开发模式。【免费下载链接】foundryFoundry is a blazing fast, portable and modular toolkit for Ethereum application development written in Rust.项目地址: https://gitcode.com/GitHub_Trending/fo/foundry创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
返回列表