尧图网站设计 尧图网站设计YAOTU DESIGN
ARTICLE DETAIL

资讯详情

深耕网站设计与一线实操的经验洞察。

kona-executor:OP Stack 无状态区块执行器源码深度解析

kona-executor:OP Stack 无状态区块执行器源码深度解析 kona-executorOP Stack 无状态区块执行器源码深度解析【免费下载链接】optimismOptimism is Ethereum, scaled.项目地址: https://gitcode.com/GitHub_Trending/op/optimism本篇技术指南以 Optimism 仓库中 rust/kona/crates/proof/executor/README.md 为纲深入剖析kona-executor这一no_std无状态区块执行器它以 kona-mpt 的TrieDB为状态后端在完全不维护完整 L2 状态的前提下执行 OP Stack 区块并产出可验证的区块头与输出根output root是 Kona 故障证明fault proof体系中链下可复现执行的关键一环。读完本文你将掌握其架构分层、StatelessL2Builder的建块流程、基于 Merkle 证明的TrieDB设计、EIP-1559 与硬分叉参数处理、区块封印逻辑以及它在kona-driver中的实际接线方式。一、模块定位一句话背后的大设计原文档用一句话定义了整个 crate 的本质Ano_stdimplementation of a stateless block executor for the OP stack, backed bykona-mptsTrieDB.这句话包含三个关键限定词分别对应三类核心技术决策no_std在 src/lib.rs 中通过#![cfg_attr(not(any(test, feature test-utils)), no_std)]强制开启仅在测试或启用test-utilsfeature 时才引入标准库。这意味着该执行器可以被编译进无法依赖操作系统资源的故障证明虚拟机如 Cannon/MIPS 或 zkVM中运行。stateless无状态传统执行引擎如 op-geth维护完整的状态数据库kona-executor只持有受信任的父区块 state root 按需获取的 Merkle 证明 witness 预映像边执行边重建所需状态。backed bykona-mptsTrieDB状态访问全部落到 kona-mpt 提供的递归内存版十六进制 MPT支持检索、插入、删除与根哈希计算执行器本身不关心 trie 节点如何存储只通过TrieProvider按哈希取节点预映像。该 crate 的依赖也在 Cargo.toml 中给出了佐证工作区依赖kona-mpt、kona-genesis提供RollupConfig、kona-protocol配合revm/op-revmEVM 执行、alloy-op-evmOP 交易类型与收据、op-alloy-rpc-types-engineOpPayloadAttributes。crate 版本为0.4.0。二、核心类型StatelessL2Builder与四个泛型模块入口 src/lib.rs 对外只导出少量高内聚类型StatelessL2Builder、BlockBuildingOutcome、compute_receipts_root来自builder模块TrieDB、TrieDBProvider、NoopTrieDBProvider来自db模块完整错误体系ExecutorError、ExecutorResult、TrieDBError、TrieDBResult、Eip1559ValidationError。2.1 结构体定义StatelessL2Builder定义在 src/builder/core.rs携带四个泛型参数每个都对应一条可插拔的扩展点泛型Trait 约束职责PTrieDBProvider按哈希获取 trie 节点、合约字节码、区块头预映像HTrieHinter向 host 发送 hint预取执行所需的 witness 数据EvmEvmFactorySpec OpSpecId, BlockEnv BlockEnv创建 EVM 执行环境的工厂ROpReceiptBuilderTransaction OpTxEnvelope决定收据信封形态OP Stack 默认OpAlloyReceiptBuilder如 Celo 的 CIP-64 收据可自行注入结构体内部持有三个字段config: a RollupConfig—— 链参数与各硬分叉激活高度trie_db: TrieDBP, H—— 无状态状态访问的唯一入口factory: OpBlockExecutorFactoryR, RollupConfig, Evm—— OP 专属的区块执行器工厂理解 OP 交易类型、系统调用与状态管理。2.2 构造与生命周期let builder StatelessL2Builder::new( rollup_config, // 链参数与分叉激活高度 evm_factory, // EVM 工厂如 OpEvmFactory::OpTx::default() receipt_builder, // 收据构建器如 OpAlloyReceiptBuilder::default() trie_provider, // trie 数据提供者P trie_hinter, // witness 提示器H parent_header, // 父区块的 SealedHeader );new会基于父区块头的state_root构造一个盲化blinded根节点见 src/builder/core.rs。由于执行器无状态安全头safe head推进就意味着用新父头重建一个新 builder——这一生命周期设计在第五节与 kona-driver 的集成中体现得最明显。三、TrieDB把 Merkle 证明当作数据库TrieDB位于 src/db/mod.rs是 crate 的地基。它实现 revm 的Databasetrait让 EVM 在无状态环境下执行时每次状态访问都落到按需、可验证的 trie 查询上。3.1 三个内部结构root_node: TrieNode—— 当前 state root 对应的根节点创建时通过TrieNode::new_blinded(parent_block_header.state_root)盲化storage_roots: HashMapAddress, TrieNode—— 各账户存储 trie 的内存缓存parent_block_header: SealedHeaderfetcher: FTrieDBProviderhinter: HTrieHinter。3.2 关键行为对应Database实现basic(address)先通过get_trie_account查询账户。查询前会调用hinter.hint_account_proof(address, parent_hash)向 host 发出账户证明 hintsrc/db/mod.rs随后用keccak256(address)的 nibbles 在根节点上open路径取回 RLP 编码的TrieAccount并解码。账户的 storage root 会被插入storage_roots缓存。code_by_hash(code_hash)委托fetcher.bytecode_by_hash取合约字节码。storage(address, index)先 hint 存储证明再从账户缓存中的 storage trie 打开keccak256(slot)路径读取值槽位不存在返回U256::ZERO。block_hash(number)利用BLOCK_HASH_HISTORY限制256 个区块从父头沿parent_hash链式回溯通过fetcher.header_by_hash取历史头直至目标区块号src/db/mod.rs。state_root(bundle)区块执行完成后把 revm 的BundleState变更集应用到 trie再对根节点blind()重新计算 state rootsrc/db/mod.rs。3.3 确定性保证与存储修剪update_accounts在应用变更集前会先对哈希后的地址与存储槽位排序保证多次运行结果完全一致这是故障证明可复现性的硬性要求。对存储槽位若present_value归零则在 trie 中删除该节点change_storage否则插入新值src/db/mod.rs。db/mod.rs末尾的单元测试覆盖了账户销毁Destroyed/DestroyedChanged/DestroyedAgain在 state root 中的去留语义例如被销毁账户不应出现在 trie 中与销毁后重建的账户必须重新插入。3.4 构造示例源码 doctest 摘录TrieDB的文档示例src/db/mod.rs展示了最小接线方式use kona_executor::{NoopTrieDBProvider, TrieDB}; use kona_mpt::NoopTrieHinter; let mock_parent_block_header Header::default(); let trie_db TrieDB::new(mock_parent_block_header.seal_slow(), NoopTrieDBProvider, NoopTrieHinter); let executor_factory OpBlockExecutorFactory::new( OpAlloyReceiptBuilder::default(), OpChainHardforks::op_mainnet(), OpEvmFactory::alloy_op_evm::OpTx::default(), ); let mut state State::builder().with_database(trie_db).with_bundle_update().build(); let evm executor_factory.evm_factory().create_evm(mut state, EvmEnv::default()); let executor executor_factory.create_executor(evm, OpBlockExecutionCtx::default()); // 执行区块交易... state.merge_transitions(BundleRetention::Reverts); let bundle state.take_bundle(); let state_root state.database.state_root(bundle).expect(Failed to compute state root);3.5 Provider 与 Hinter 抽象TrieDBProvidersrc/db/traits.rs在kona-mpt的TrieProvider::trie_node_by_hash之上追加bytecode_by_hash与header_by_hash两个方法NoopTrieDBProvider是测试用的空实现。TrieHinterkona-mpt 的 traits定义了hint_trie_node、hint_account_proof、hint_storage_proof、hint_execution_witness四个 hint 接口——在故障证明场景下host 侧预取数据、客户端guest侧通过 hint 驱动是 Cannon 预映像预言机模式的核心。四、build_block无状态建块的完整流水线StatelessL2Builder::build_block(attrs: OpPayloadAttributes) - ExecutorResultBlockBuildingOutcomeR::Receipt是建块主入口src/builder/core.rs源码注释将流程拆为四步环境准备调用active_base_fee_params依据父头时间戳选择当前生效的 EIP-1559 参数再由evm_env组装EvmEnvOpSpecIdgas limit、base fee、suggested fee recipient、prev_randao、时间戳等。Witness 预取hint调用hinter.hint_execution_witness(parent_hash, attrs)让 host 把执行该 payload 所需的全部预映像灌入 preimage store。该功能是实验性的——hint 失败不会中止建块而是回退到按需获取预映像。执行用State::builder().with_database(mut trie_db).with_bundle_update()构建 revm 状态层OpBlockExecutorFactory创建执行器对 payload 内交易做签名恢复recovered_transactions_with_encoded调用parse_post_exec_payload_from_transactions解析 SDMSequencer Deposit Messagepost-exec 交易并按PostExecMode::Verify校验随后executor.execute_block(transactions.iter())完成区块执行。封印sealstate.merge_transitions(BundleRetention::Reverts)合并状态变更take_bundle取出BundleState调用seal_block计算各类 root 并组装新区块头最后trie_db.set_parent_block_header(header.clone())推进父头为下一个区块做准备。整个流程中大量使用info!日志target: block_builder输出区块号、时间戳、gas、交易数与最终 state root 等可观测指标便于故障排查与复现对照。五、EVM 环境与 EIP-1559 参数推导src/builder/env.rs 集中了环境相关的分叉逻辑是理解 OP 硬分叉Canyon/Holocene/Jovian如何影响建块的窗口。5.1active_base_fee_params的选择逻辑按父头时间戳从新到旧匹配Jovian 已激活从父头extra_data解码 Jovian 版 EIP-1559 参数同时返回min_base_feeJovian 起 base fee 存在下限Holocene 已激活Jovian 未激活从父头extra_data解码 Holocene 版参数min_base_fee恒为 0Canyon 已激活使用config.chain_op_config.post_canyon_params()其余使用pre_canyon_params()。5.2 下一个区块 base fee 的计算next_block_base_fee在 Jovian 激活后引入特殊处理取max(blob_gas_used, gas_used)作为分母输入计算下一个 base fee且结果不得低于min_base_feeJovian 之前 min-base-fee 为 0该钳制是空操作。5.3 Holocene/Jovian extraData 编解码src/util.rs 中的decode_holocene_eip_1559_params_block_header、decode_jovian_eip_1559_params_block_header以及对应的 encode 函数负责与op-alloy-consensus的decode_holocene_extra_data/decode_jovian_extra_data对接。其单元测试验证了Holocene 版本号字节为0x00Jovian 为0x01分母denominator或弹性elasticity为零时解码必须失败避免除零长度非法、版本号错误的 extraData 必须报错payload 中eip_1559_params缺失时报MissingEIP1559Params为全零时回退编码 Canyon 默认参数。六、区块封印seal_block与 output rootsrc/builder/assemble.rs 负责把执行结果固化为区块头并计算 L2 输出根。6.1 区块头字段计算seal_block依据硬分叉激活状态逐项计算src/builder/assemble.rsstate_roottrie_db.state_root(bundle)基于变更集重算transactions_rootordered_trie_with_encoder按交易原始字节构造对空交易列表直接 panic——源码注释明确指出这是严重的协议违规receipts_rootcompute_receipts_root按收据构建器生成withdrawals_rootIsthmus 激活时取 L2 到 L1 消息传递者L2_TO_L1_MESSAGE_PASSER账户的 storage rootCanyon 激活时取EMPTY_ROOT_HASH否则为Noneblob 字段Jovian 激活写入真实blob_gas_used且excess_blob_gas 0Ecotone 激活但 Jovian 未激活时两者都置 0extra_dataHolocene/Jovian 激活时编码 EIP-1559 参数写入requests_hashIsthmus 激活时为EMPTY_REQUESTS_HASHEIP-7685 空请求哈希。6.2compute_receipts_root的 Regolith 特殊编码compute_receipts_root复刻了 op-geth/op-erigon 在Regolith 激活后、Canyon 激活前的收据 trie 编码该阶段 deposit 收据的编码省略 deposit nonce。实现通过OpReceiptBuilder::strip_deposit_nonce委托给各链的收据构建器——OP Stack 实现覆写该行为其他链如 Celo继承为空操作src/builder/assemble.rs。6.3compute_output_root与 L2 输出根output_root keccak256(version_byte .. payload) payload state_root .. withdrawal_storage_root .. latest_block_hashcompute_output_root通过OutputRoot::from_parts(parent_header.state_root, storage_root, parent_header.seal())构造并哈希其中storage_root来自消息传递者账户优先读TrieDB缓存否则回源 trie 查询。这正是 L1 上 L2OutputOracle / 输出根提案所引用的承诺值。七、错误处理模型src/errors.rs 提供了三级错误体系覆盖整个执行生命周期ExecutorError建块/执行错误按类别分输入校验MissingGasLimit、MissingTransactions、MissingEIP1559ParamsHolocene 后、MissingParentBeaconBlockRootDencun 后执行BlockGasLimitExceeded、UnsupportedTransactionType、ExecutionError包装 EVM 级BlockExecutionError数据完整性Recovery签名恢复失败、RLPError、TrieDBError、InvalidPostExecPayloadSDM post-exec 校验失败、InvalidExtraDataEIP-1559 参数解码失败。TrieDBErrortrie 操作错误包括RootNotBlinded、MissingAccountInfo、TrieNode包装TrieNodeError、Provider并实现了 revm 的DBErrorMarker可直接作为数据库错误传播。Eip1559ValidationError仅包装EIP1559ParamError的透明错误。八、测试策略真实区块 Fixture 驱动的回归测试kona-executor的测试思路极具工程参考价值用真实 OP 主网区块作为 fixture验证无状态执行与有状态执行结果完全一致。8.1 Fixture 结构testdata/ 下存放 8 个block-*.tar.gz归档区块号从 26207960 到 26211680每个归档内包含kv/RocksDB 键值库以 Snappy 压缩存放 trie 节点/字节码/区块头预映像fixture.json反序列化后的ExecutorTestFixture含rollup_config、parent_header、executing_payload及期望的区块哈希。8.2 测试工具链src/test_utils.rs由test-utilsfeature 或 dev-dependencies 启用提供load_test_fixture解包归档、打开 RocksDB、解析 fixtureexecute_loaded_fixture用真实配置构造StatelessL2Builder并执行 payload可选 SDM 激活覆盖run_test_fixture执行 fixture 并断言产出的区块哈希与期望值一致。8.3 关键测试用例src/builder/core/tests.rs 中的test_statelessly_execute_block通过rstest遍历全部testdata/*.tar.gz完成端到端无状态执行校验此外还针对 SDM post-exec 交易做了详尽的负向测试SDM 未激活时拒绝 post-exec 交易、区块号不匹配、重复 post-exec 交易、合法空 payload 不改变状态与 gas 等。九、在故障证明体系中的真实用途KonaExecutorkona-executor不是孤立组件。在 rust/kona/crates/proof/proof/src/executor.rs 中KonaExecutor包装了StatelessL2Builder并实现kona_driver::Executortrait从而接入故障证明的派生驱动循环update_safe_head(header)由于执行器无状态每次 safe head 推进就重建一个StatelessL2Builderexecutor.rsexecute_payload(attributes)委托给内部 builder 的build_block未初始化时报ExecutorError::MissingExecutorexecutor.rswait_until_ready为空操作——因为无状态执行器无需等待任何状态同步。这种每次执行都从父 state root 出发、依赖 witness 重建状态的模型正是故障证明双方proposer 与 challenger能在互不共享状态的情况下对同一区块头达成一致执行结果的根本保证。proof-interop的 consolidation 流程proof-interop/src/consolidation.rs同样复用了该执行器。十、总结kona-executor用盲化 MPT 根节点 按需证明拉取 revm 状态层包装三件套把传统有状态执行器压缩成了可放进no_std证明环境中的确定性函数输入(RollupConfig, 父头, OpPayloadAttributes, witness)输出(SealedHeader, BlockExecutionResult)。它既支撑了 Kona 客户端对 safe head 的链上推进也为 fault proof 提供了可复现、可验证的区块执行语义。若要进一步深入建议按以下顺序阅读源码src/db/mod.rs —— 理解证明即数据库src/builder/core.rs —— 掌握四步建块流水线src/builder/assemble.rs —— 学习分叉感知的区块头组装src/builder/core/tests.rs 与 testdata/ —— 借鉴真实区块回归测试的构造方法。【免费下载链接】optimismOptimism is Ethereum, scaled.项目地址: https://gitcode.com/GitHub_Trending/op/optimism创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
返回列表