ARTICLE DETAIL

资讯详情

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

go-ethereum evm t8n 缺失 currentBaseFee 错误测试解析:EIP-1559 环境下 env 配置的强制约束

go-ethereum evm t8n 缺失 currentBaseFee 错误测试解析:EIP-1559 环境下 env 配置的强制约束 go-ethereum evm t8n 缺失 currentBaseFee 错误测试解析EIP-1559 环境下 env 配置的强制约束【免费下载链接】go-ethereumGo implementation of the Ethereum protocol项目地址: https://gitcode.com/gh_mirrors/go/go-ethereum导读本文围绕 go-ethereum 仓库中 cmd/evm/testdata/11/readme.md 这份测试用例说明文档深入讲解evm t8n无状态状态转换工具在 London/EIP-1559 分叉下对env中 basefee 字段的强制校验机制。读者将掌握为什么链上天然携带的 basefee 在 t8n 中必须手动写入env、缺失时工具如何以退出码 3 报错、currentBaseFee与parentBaseFee两条配置路径的取舍逻辑以及如何在--state.forkLondon下正确构造可运行的测试输入。测试场景总览一个刻意构造的错误用例cmd/evm/testdata/11/readme.md 描述的是一次预期失败的状态转换测试在--state.forkLondon下运行evm t8n但输入的env中没有提供currentBaseFee工具应输出错误并返回非零退出码。该用例与仓库中其他正向用例如 testdata/1、testdata/25 验证 basefee 计算形成互补专门覆盖 EIP-1559 配置校验的异常分支。核心结论是在 EIP-1559 激活的链上basefee 存在于区块头中并作为区块头校验的一部分被验证而evm t8n没有区块概念basefee 必须由调用者在env中显式提供否则工具拒绝执行。这正是该文档要传达的最关键设计意图。为什么 t8n 要求手动提供 basefee链上世界与无状态世界的差异文档明确指出On a live blockchain, the basefee is present in the header, and verified as part of header validation.真实链上basefeeEIP-1559 的基础费用随每个区块头一起产生和广播执行交易时客户端直接从 header 读取该值并配合出块流程完成一致性校验。而在evm t8n的模型里输入只有三份 JSONalloc、txs、env没有区块头对象因此EIP-1559 生效后的 basefee 必须由用户在env中补齐。源码中的校验入口在 cmd/evm/internal/t8ntool/transition.go 中applyLondonChecks函数完整实现了这一逻辑func applyLondonChecks(env *stEnv, chainConfig *params.ChainConfig) error { if !chainConfig.IsLondon(big.NewInt(int64(env.Number))) { return nil } // Sanity check, to not panic in state_transition if env.BaseFee ! nil { // Already set, base fee has precedent over parent base fee. return nil } if env.ParentBaseFee nil || env.Number 0 { return NewError(ErrorConfig, errors.New(EIP-1559 config but missing parentBaseFee in env section)) } env.BaseFee eip1559.CalcBaseFee(chainConfig, types.Header{ Number: new(big.Int).SetUint64(env.Number - 1), BaseFee: env.ParentBaseFee, GasUsed: env.ParentGasUsed, GasLimit: env.ParentGasLimit, }) return nil }校验逻辑可以拆解为三步分叉门控先通过chainConfig.IsLondon(blockNumber)判断当前区块高度是否已激活 LondonEIP-1559。未激活时直接返回 nil不施加任何 basefee 约束直供优先若env.currentBaseFee对应env.BaseFee已显式给出直接通过——显式 basefee 优先于从 parent 推导推导兜底否则要求parentBaseFee存在且区块号不为 0利用eip1559.CalcBaseFee依据父区块的 basefee、gasUsed、gasLimit 计算当前 basefee。该函数在 Transition 主流程 中于交易执行前被调用与applyShanghaiChecks、applyMergeChecks、applyCancunChecks等构成一条链式的环境预检流水线。一个值得注意的细节文档输出与实际源码的措辞差异testdata/11的 readme 中记录的错误信息为EIP-1559 config but missing currentBaseFee in env section而当前仓库源码 transition.go 中同样分支产生的文案是parentBaseFee而非currentBaseFee。这反映了代码演进早期版本要求用户直接提供currentBaseFee后来 t8n 支持了parentBaseFeeparentGasUsedparentGasLimit推导机制对应 testdata/25 的 basefee 计算用例错误提示随之更新。从源码结构看testdata/11 的 readme 与预期输出保留了历史措辞测试断言关注的是退出码 3 而非精确的 stderr 文本见下文测试机制分析因此不影响该用例的有效性。复现与验证亲手跑出错误文档给出了完整的复现命令在cmd/evm目录下执行dir./testdata/11 ./evm t8n --state.forkLondon --input.alloc$dir/alloc.json --input.txs$dir/txs.json --input.env$dir/env.json --output.allocstdout --output.resultstdout 21/dev/null预期输出为退出码 3 及错误信息EIP-1559 config but missing currentBaseFee in env section。命令要点--state.forkLondon显式指定启用 EIP-1559 的分叉这是触发校验的前提--input.alloc/--input.txs/--input.env三份标准输入--output.allocstdout/--output.resultstdout声明输出位置21/dev/null把 stderr 保留到终端、丢弃 stdout从而只看到错误信息。测试输入逐字段解读env.jsontestdata/11/env.json中故意省略了currentBaseFee与parentBaseFee{ currentCoinbase : 0x2adc25665018aa1fe0e6bc666dac8fc2697ff9ba, currentDifficulty : 0x020000, currentNumber : 0x01, currentTimestamp : 0x03e8, previousHash : 0xfda4419b3660e99f37e536dae1ab081c180136bb38c837a93e93d9aab58553b2, currentGasLimit : 0x0f4240, blockHashes : { 0 : 0xfda4419b3660e99f37e536dae1ab081c180136bb38c837a93e93d9aab58553b2 } }对照 cmd/evm/internal/t8ntool/execution.go 中stEnv的定义字段JSON 键本用例取值说明CoinbasecurrentCoinbase0x2adc...ff9ba区块收益接收地址必填DifficultycurrentDifficulty0x020000当前难度必填NumbercurrentNumber0x01区块高度 1必填TimestampcurrentTimestamp0x03e8时间戳必填GasLimitcurrentGasLimit0x0f4240区块 gas 上限必填BlockHashesblockHashes{0: ...}供 BLOCKHASH 操作码查询BaseFeecurrentBaseFee缺失触发错误的根因ParentBaseFeeparentBaseFee缺失推导路径也被切断注意第 4 行使用了previousHash键而stEnv结构中并无该字段实际键名为parentUncleHash/blockHashesJSON 反序列化时未知字段会被忽略不影响测试目的——本用例只需满足London 分叉 无 basefee这一触发条件。alloc.jsontestdata/11/alloc.json预置了三个账户包含持币账户、带合约代码的账户如0x0f57...5ec6的 code0x61ffff5060046000f3以及 precompile 风格的存储账户结构与 testdata/1/alloc.json 等标准用例一致。txs.jsontestdata/11/txs.json包含一笔已签名的 Legacy 交易v/r/s与secretKey齐备其 sender 为0xa94f5374fce5edbc8e2a8697c15331677e6ebf0balloc 中余额为0x0de0b6b3a7640000即 1 ETH。由于 basefee 校验发生在 Transition 函数 的交易执行之前这笔交易实际上根本没有机会被执行——工具在预检阶段即失败退出这再次印证了 env 配置校验的高优先级。退出码 3 的语义文档中的ERROR(3)并非普通日志前缀而是 t8n 规范化的错误码。在 cmd/evm/internal/t8ntool/transition.go 中定义const ( ErrorEVM 2 ErrorConfig 3 ErrorMissingBlockhash 4 ErrorJson 10 ErrorIO 11 ErrorRlp 12 )ErrorEVM (2)EVM 执行层面错误ErrorConfig (3)配置/输入环境错误——basefee 缺失正属于此类ErrorMissingBlockhash (4)缺失区块哈希见 testdata/4 用例ErrorJson (10) / ErrorIO (11) / ErrorRlp (12)输入输出编解码类错误。错误码不仅对人工排查有意义更重要的价值在于可被测试程序与自动化流水线断言脚本无需解析 stderr 文本只需检查退出码即可区分配置错误与执行错误。测试如何断言这个错误用例cmd/evm/t8n_test.go 的TestT8n通过cmdtest.NewTestCmd以子进程方式驱动evm t8n表格驱动地覆盖了从 Frontier 到 Osaka 的全部 testdata 目录。testdata/11 虽然没有被列入当前表格表格中编号为 1、3、4、5、13、14、19、23、24、25、26、28、29、30、33、34 等但同目录的设计与 4 号用例expExitCode: 4缺失 blockhash如出一辙通过expExitCode断言失败场景通过expOut对比成功场景的期望输出cmpJson做语义级 JSON 比较见 t8n_test.go。这种预期失败用例的价值在于守护校验逻辑防止未来重构时误删applyLondonChecks或放宽约束导致缺失 basefee 的输入静默通过固化错误码契约确保配置类错误稳定地以 3 退出供上层工具如状态测试夹具生成器可靠依赖文档化行为readme 即测试注释向后续维护者解释为什么这个目录的输入跑不通。正确的 EIP-1559 env 配置姿势方案一直接提供 currentBaseFee在 London 分叉下最直接的做法是在env中给出当前块的 basefee{ currentCoinbase : 0x2adc25665018aa1fe0e6bc666dac8fc2697ff9ba, currentNumber : 0x01, currentGasLimit : 0x0f4240, currentTimestamp : 0x03e8, currentBaseFee : 0x3b9aca00, currentDifficulty : 0x020000 }0x3b9aca00即 1 Gwei10^9是 EIP-1559 的初始 basefee 值。对照stEnv结构currentBaseFee对应BaseFee *big.Int在 execution.go 中会直接注入 EVM 上下文// If currentBaseFee is defined, add it to the vmContext. if pre.Env.BaseFee ! nil { vmContext.BaseFee new(big.Int).Set(pre.Env.BaseFee) }方案二提供 parentBaseFee 让 t8n 自行推导不直接给currentBaseFee而是给出父区块信息由applyLondonChecks调用eip1559.CalcBaseFee计算{ currentNumber : 0x01, parentBaseFee : 0x3b9aca00, parentGasUsed : 0x0, parentGasLimit : 0x0f4240 }此时生成的vmContext.BaseFee会通过 execution.go 的 result 输出 以currentBaseFee键回写。注意区块号必须大于 0env.Number 0时父区块不存在直接报错。常用环境参数速查表基于 stEnv 定义 与 cmd/evm/README.md 的 env 章节参数JSON 键必填说明币基地址currentCoinbase是区块奖励接收方区块号currentNumber是决定分叉判定时间戳currentTimestamp是决定时间相关分叉gas 上限currentGasLimit是区块 gas 上限难度currentDifficulty是前合并/否后合并后合并必须为 0 或省略basefeecurrentBaseFeeLondon 后二选一直接指定父 basefeeparentBaseFeeLondon 后二选一配合parentGasUsed/parentGasLimit推导随机数currentRandom后合并必填Paris 起需要提款列表withdrawalsShanghai 起必填缺失报Shanghai config but missing withdrawals区块哈希blockHashes按需BLOCKHASH 操作码查询叔块ommers按需奖励与难度计算若 London 之后未提供 basefee 且区块号非 0t8n 的完整错误路径是applyLondonChecks返回NewError(ErrorConfig, ...)→ Transition 主流程向上返回 → CLI 以退出码 3 终止stderr 打印错误文案。与相邻校验用例的横向对照testdata/11 并非孤例cmd/evm/internal/t8ntool/transition.go 中还有一组同构的分叉环境预检构成完整的错误矩阵分叉缺失字段错误信息退出码LondonbasefeeEIP-1559 config but missing parentBaseFee in env section3ShanghaiwithdrawalsShanghai config but missing withdrawals in env section3Paris合并后currentRandompost-merge requires currentRandom to be defined in env3Paris合并后难度非零post-merge difficulty must be zero (or omitted) in env3CancunparentBeaconBlockRootpost-cancun env requires parentBeaconBlockRoot to be set3对应的仓库用例testdata/11本主题basefee 缺失、testdata/24Paris 下env-missingrandom.jsonexpExitCode: 3见 t8n_test.go、testdata/4Berlin 下缺失 blockhash退出码 4。这些用例共同守护着t8n 的 env 必须自包含这一核心契约无状态工具不继承链上上下文凡是链上由区块头提供的字段都必须由调用者在 env 中显式补齐。总结testdata/11通过一个刻意残缺的env.json完整演示了evm t8n在 EIP-1559 环境下的 basefee 强制约束链上区块头天然携带的 basefee在无状态的 t8n 中必须由用户通过currentBaseFee直接提供或通过parentBaseFee 父区块 gas 数据推导两者皆缺时工具在交易执行前即以退出码 3ErrorConfig拒绝运行。理解这一机制是正确使用evm t8n进行无状态状态转换测试、编写可复现的 EVM 测试夹具、以及排查配置错误 vs 执行错误的第一道门槛。【免费下载链接】go-ethereumGo implementation of the Ethereum protocol项目地址: https://gitcode.com/gh_mirrors/go/go-ethereum创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
返回列表