From 172d7b244253ebda91de1581efe2bcba5f75d27d Mon Sep 17 00:00:00 2001 From: refcell Date: Wed, 2 Oct 2024 10:16:51 -0400 Subject: [PATCH] feat: kona-providers (#596) * feat: kona-providers * fix: remove to_l2_block_ref utility * fix: no_std * fix: nits --- Cargo.lock | 121 +++++++------ Cargo.toml | 31 ++-- bin/client/Cargo.toml | 1 + bin/client/src/l1/chain_provider.rs | 2 +- bin/client/src/l1/driver.rs | 3 +- bin/client/src/l2/chain_provider.rs | 32 ++-- bin/host/src/fetcher/mod.rs | 2 +- crates/derive/Cargo.toml | 1 + crates/derive/src/attributes/mod.rs | 9 +- crates/derive/src/batch/mod.rs | 3 +- crates/derive/src/batch/span_batch/batch.rs | 66 ++++--- .../src/batch/span_batch/transactions.rs | 4 +- .../src/batch/span_batch/tx_data/eip1559.rs | 2 +- .../src/batch/span_batch/tx_data/eip2930.rs | 2 +- .../src/batch/span_batch/tx_data/legacy.rs | 2 +- crates/derive/src/block.rs | 166 ------------------ crates/derive/src/lib.rs | 5 +- crates/derive/src/pipeline/builder.rs | 5 +- crates/derive/src/pipeline/core.rs | 5 +- crates/derive/src/pipeline/mod.rs | 7 +- crates/derive/src/sources/blobs.rs | 3 +- crates/derive/src/sources/calldata.rs | 3 +- crates/derive/src/sources/ethereum.rs | 3 +- crates/derive/src/sources/variant.rs | 3 +- crates/derive/src/stages/batch_queue.rs | 30 ++-- crates/derive/src/stages/l1_traversal.rs | 7 +- .../stages/test_utils/sys_config_fetcher.rs | 3 +- crates/derive/src/traits/mod.rs | 3 - crates/derive/src/traits/providers.rs | 54 ------ crates/derive/src/traits/test_utils.rs | 7 +- crates/executor/benches/execution.rs | 6 +- crates/executor/src/lib.rs | 46 ++--- crates/executor/src/util.rs | 10 +- crates/mpt/src/list_walker.rs | 8 +- crates/mpt/src/node.rs | 8 +- crates/mpt/src/test_util.rs | 16 +- crates/providers-alloy/Cargo.toml | 2 + crates/providers-alloy/src/alloy_providers.rs | 39 ++-- crates/providers-alloy/src/lib.rs | 10 +- crates/providers/Cargo.toml | 26 +++ crates/providers/README.md | 3 + crates/providers/src/l1_chain_provider.rs | 32 ++++ crates/providers/src/l2_chain_provider.rs | 30 ++++ crates/providers/src/lib.rs | 20 +++ crates/providers/src/utils.rs | 91 ++++++++++ examples/trusted-sync/src/validation.rs | 2 +- 46 files changed, 500 insertions(+), 434 deletions(-) delete mode 100644 crates/derive/src/block.rs create mode 100644 crates/providers/Cargo.toml create mode 100644 crates/providers/README.md create mode 100644 crates/providers/src/l1_chain_provider.rs create mode 100644 crates/providers/src/l2_chain_provider.rs create mode 100644 crates/providers/src/lib.rs create mode 100644 crates/providers/src/utils.rs diff --git a/Cargo.lock b/Cargo.lock index 84303359..a00e861a 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -255,15 +255,17 @@ dependencies = [ [[package]] name = "alloy-consensus" -version = "0.3.6" +version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "629b62e38d471cc15fea534eb7283d2f8a4e8bdb1811bcc5d66dda6cfce6fae1" +checksum = "fa2d9df04dce5c4a8d46783fa18d687b946a9f7d61166cdc35b0631dfc50b810" dependencies = [ "alloy-eips", "alloy-primitives", "alloy-rlp", "alloy-serde", + "auto_impl", "c-kzg", + "derive_more 1.0.0", "serde", ] @@ -292,9 +294,9 @@ dependencies = [ [[package]] name = "alloy-eips" -version = "0.3.6" +version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f923dd5fca5f67a43d81ed3ebad0880bd41f6dd0ada930030353ac356c54cd0f" +checksum = "2717a756c33fe935751d8963b5898d406c8846199660c9d6c6eeb41a18a15697" dependencies = [ "alloy-eip2930", "alloy-eip7702", @@ -310,9 +312,9 @@ dependencies = [ [[package]] name = "alloy-genesis" -version = "0.3.6" +version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3a7a18afb0b318616b6b2b0e2e7ac5529d32a966c673b48091c9919e284e6aca" +checksum = "fe9162561c17566bf289a5d0aad07831b7c07d5412108ce533689d379940ba70" dependencies = [ "alloy-primitives", "alloy-serde", @@ -321,9 +323,9 @@ dependencies = [ [[package]] name = "alloy-json-rpc" -version = "0.3.6" +version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d3c717b5298fad078cd3a418335b266eba91b511383ca9bd497f742d5975d5ab" +checksum = "0c4f3797fbb22b3312d6cb63fcce9a1f921e567074f9dc2c012de5200342ebe8" dependencies = [ "alloy-primitives", "alloy-sol-types", @@ -335,9 +337,9 @@ dependencies = [ [[package]] name = "alloy-network" -version = "0.3.6" +version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fb3705ce7d8602132bcf5ac7a1dd293a42adc2f183abf5907c30ac535ceca049" +checksum = "ad95873a12c4e0a45575c66fcabe7ccc31fcf4c946a7d30c7cc38a115c59004e" dependencies = [ "alloy-consensus", "alloy-eips", @@ -356,10 +358,11 @@ dependencies = [ [[package]] name = "alloy-network-primitives" -version = "0.3.6" +version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "94ad40869867ed2d9cd3842b1e800889e5b49e6b92da346e93862b4a741bedf3" +checksum = "8416e4e9ceee8014d2f89fc3dde331da392b26d14226a0d5cbc207ae7799fb2f" dependencies = [ + "alloy-consensus", "alloy-eips", "alloy-primitives", "alloy-serde", @@ -368,9 +371,9 @@ dependencies = [ [[package]] name = "alloy-node-bindings" -version = "0.3.6" +version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5988a227293f949525f0a1b3e1ef728d2ef24afa96bad2b7788c6c9617fa3eec" +checksum = "60d32daf9f95aa04cd7cad47f9de58ab91a3a039fa51979637787f14f13a8292" dependencies = [ "alloy-genesis", "alloy-primitives", @@ -412,9 +415,9 @@ dependencies = [ [[package]] name = "alloy-provider" -version = "0.3.6" +version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "927f708dd457ed63420400ee5f06945df9632d5d101851952056840426a10dc5" +checksum = "e82c0e8ebddbcce9450431680dc1576b380e1a781c2f8033321bef805272644b" dependencies = [ "alloy-chains", "alloy-consensus", @@ -468,11 +471,12 @@ dependencies = [ [[package]] name = "alloy-rpc-client" -version = "0.3.6" +version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7d82952dca71173813d4e5733e2c986d8b04aea9e0f3b0a576664c232ad050a5" +checksum = "424516469135db9d385a1f9a51bc0d198e226bf3ff29843fde799a39b5507e12" dependencies = [ "alloy-json-rpc", + "alloy-primitives", "alloy-transport", "alloy-transport-http", "futures", @@ -489,10 +493,11 @@ dependencies = [ [[package]] name = "alloy-rpc-types" -version = "0.3.6" +version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "64333d639f2a0cf73491813c629a405744e16343a4bc5640931be707c345ecc5" +checksum = "da0d2d760a666acdcaed038164bef0d179ee10790ba68e39b18361faac7eb6e7" dependencies = [ + "alloy-primitives", "alloy-rpc-types-eth", "alloy-serde", "serde", @@ -500,9 +505,9 @@ dependencies = [ [[package]] name = "alloy-rpc-types-engine" -version = "0.3.6" +version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1464c4dd646e1bdfde86ae65ce5ba168dbb29180b478011fe87117ae46b1629b" +checksum = "c032e9b725a990be03cc0ddd9fa73c21f61d1449b328083aa22fbfafb03eda1b" dependencies = [ "alloy-consensus", "alloy-eips", @@ -511,13 +516,14 @@ dependencies = [ "alloy-serde", "derive_more 1.0.0", "serde", + "strum", ] [[package]] name = "alloy-rpc-types-eth" -version = "0.3.6" +version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "83aa984386deda02482660aa31cb8ca1e63d533f1c31a52d7d181ac5ec68e9b8" +checksum = "3e1f655dcd5e9ccf215cbffb69272698ef6b3ec76907e8937345f2a82ae04ed4" dependencies = [ "alloy-consensus", "alloy-eips", @@ -526,9 +532,7 @@ dependencies = [ "alloy-rlp", "alloy-serde", "alloy-sol-types", - "cfg-if", "derive_more 1.0.0", - "hashbrown", "itertools 0.13.0", "serde", "serde_json", @@ -536,9 +540,9 @@ dependencies = [ [[package]] name = "alloy-serde" -version = "0.3.6" +version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "731f75ec5d383107fd745d781619bd9cedf145836c51ecb991623d41278e71fa" +checksum = "5c1b34ed2d54f2db4ec4f38bcd78d9913f9b2deb065254d3541cc350ba660c0d" dependencies = [ "alloy-primitives", "serde", @@ -547,9 +551,9 @@ dependencies = [ [[package]] name = "alloy-signer" -version = "0.3.6" +version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "307324cca94354cd654d6713629f0383ec037e1ff9e3e3d547212471209860c0" +checksum = "672b6462295502a7eb24e76e16dc8664ece33d168a2cade3bf4dac6a858e054e" dependencies = [ "alloy-primitives", "async-trait", @@ -619,9 +623,9 @@ dependencies = [ [[package]] name = "alloy-transport" -version = "0.3.6" +version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "33616b2edf7454302a1d48084db185e52c309f73f6c10be99b0fe39354b3f1e9" +checksum = "5c99b41f0ea73dbbb1f0c970dd7c5150db9040d6201c07daf1ee0bfd74f5fb60" dependencies = [ "alloy-json-rpc", "base64", @@ -638,9 +642,9 @@ dependencies = [ [[package]] name = "alloy-transport-http" -version = "0.3.6" +version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a944f5310c690b62bbb3e7e5ce34527cbd36b2d18532a797af123271ce595a49" +checksum = "e8915d70b52abcefa0d9e463a3d85de82f3dd7d14a0caa94f6ec3802cb462be9" dependencies = [ "alloy-json-rpc", "alloy-transport", @@ -653,14 +657,13 @@ dependencies = [ [[package]] name = "alloy-trie" -version = "0.5.3" +version = "0.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0a46c9c4fdccda7982e7928904bd85fe235a0404ee3d7e197fff13d61eac8b4f" +checksum = "e9703ce68b97f8faae6f7739d1e003fc97621b856953cbcdbb2b515743f23288" dependencies = [ "alloy-primitives", "alloy-rlp", "derive_more 1.0.0", - "hashbrown", "nybbles", "smallvec", "tracing", @@ -2023,9 +2026,9 @@ dependencies = [ [[package]] name = "httparse" -version = "1.9.4" +version = "1.9.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0fcc0b4a115bf80b728eb8ea024ad5bd707b615bfed49e0665b6e0f86fd082d9" +checksum = "7d71d3574edd2771538b901e6549113b4006ece66150fb69c0fb6d9a2adae946" [[package]] name = "httpdate" @@ -2295,6 +2298,7 @@ dependencies = [ "kona-mpt", "kona-preimage", "kona-primitives", + "kona-providers", "lru", "op-alloy-consensus", "op-alloy-genesis", @@ -2346,6 +2350,7 @@ dependencies = [ "async-trait", "brotli", "kona-primitives", + "kona-providers", "lazy_static", "miniz_oxide", "op-alloy-consensus", @@ -2481,6 +2486,19 @@ dependencies = [ "tracing", ] +[[package]] +name = "kona-providers" +version = "0.0.1" +dependencies = [ + "alloy-consensus", + "alloy-primitives", + "async-trait", + "op-alloy-consensus", + "op-alloy-genesis", + "op-alloy-protocol", + "thiserror 1.0.64 (git+https://github.com/quartiq/thiserror?branch=no-std)", +] + [[package]] name = "kona-providers-alloy" version = "0.0.1" @@ -2497,8 +2515,10 @@ dependencies = [ "async-trait", "kona-derive", "kona-primitives", + "kona-providers", "lazy_static", "lru", + "op-alloy-consensus", "op-alloy-genesis", "op-alloy-protocol", "prometheus", @@ -2928,9 +2948,9 @@ checksum = "b410bbe7e14ab526a0e86877eb47c6996a2bd7746f027ba551028c925390e4e9" [[package]] name = "op-alloy-consensus" -version = "0.2.12" +version = "0.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "21aad1fbf80d2bcd7406880efc7ba109365f44bbb72896758ddcbfa46bf1592c" +checksum = "c662868734bd5a274c4474dc0642b5211f008367e591573277e5895333cb78f5" dependencies = [ "alloy-consensus", "alloy-eips", @@ -2944,9 +2964,9 @@ dependencies = [ [[package]] name = "op-alloy-genesis" -version = "0.2.12" +version = "0.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6e1b8a9b70da0e027242ec1762f0f3a386278b6291d00d12ff5a64929dc19f68" +checksum = "67b4faf4f93b34c263e66cb163a085d9da72ced1f3adb34b7bd70c6e9fc7e5d6" dependencies = [ "alloy-consensus", "alloy-eips", @@ -2958,16 +2978,16 @@ dependencies = [ [[package]] name = "op-alloy-protocol" -version = "0.2.12" +version = "0.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bf300a82ae2d30e2255bfea87a2259da49f63a25a44db561ae64cc9e3084139f" +checksum = "20bec4f5aff4fe44e1e5beecd988096e6b757bd4bdfe6b10bb3f08c410287348" dependencies = [ "alloy-consensus", "alloy-eips", "alloy-primitives", "alloy-rlp", "alloy-serde", - "hashbrown", + "derive_more 1.0.0", "op-alloy-consensus", "op-alloy-genesis", "serde", @@ -2975,9 +2995,9 @@ dependencies = [ [[package]] name = "op-alloy-rpc-types-engine" -version = "0.2.12" +version = "0.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2947272a81ebf988f4804b6f0f6a7c0b2f6f89a908cb410e36f8f3828f81c778" +checksum = "eb2b515967262eae36ccecf868ab123dd8a098476f08f28f8ab4c3db5e1ee306" dependencies = [ "alloy-eips", "alloy-primitives", @@ -4300,12 +4320,11 @@ checksum = "13c2bddecc57b384dee18652358fb23172facb8a2c51ccc10d74c157bdea3292" [[package]] name = "superchain" -version = "0.5.1" +version = "0.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c2e6a2cf2036fe8d041cc4efa8b1a91660b77497077b1656ab769e8665d8ad0c" +checksum = "4a854c55867599645eb2f518a68af34094f3a76140d02280e2bf5e913a796ebb" dependencies = [ "alloy-primitives", - "hashbrown", "lazy_static", "op-alloy-genesis", "serde", diff --git a/Cargo.toml b/Cargo.toml index f75285bf..16d0ea08 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -64,6 +64,7 @@ kona-executor = { path = "crates/executor", version = "0.0.2" } kona-common-proc = { path = "crates/common-proc", version = "0.0.3" } kona-derive = { path = "crates/derive", version = "0.0.3", default-features = false } kona-primitives = { path = "crates/primitives", version = "0.0.2", default-features = false } +kona-providers = { path = "crates/providers", version = "0.0.1" } kona-providers-alloy = { path = "crates/providers-alloy", version = "0.0.1", default-features = false } # General @@ -112,27 +113,27 @@ unsigned-varint = "0.8.0" revm = { version = "14.0.2", default-features = false } # Optimism -superchain = { version = "0.5", default-features = false } +superchain = { version = "0.7", default-features = false } # K/V database rocksdb = { version = "0.22", default-features = false, features = ["snappy"] } # Alloy alloy-rlp = { version = "0.3.8", default-features = false } -alloy-trie = { version = "0.5.3", default-features = false } -alloy-eips = { version = "0.3.6", default-features = false } -alloy-provider = { version = "0.3.6", default-features = false } +alloy-trie = { version = "0.6.0", default-features = false } +alloy-eips = { version = "0.4.0", default-features = false } +alloy-provider = { version = "0.4.0", default-features = false } alloy-primitives = { version = "0.8", default-features = false } -alloy-consensus = { version = "0.3.6", default-features = false } -alloy-transport = { version = "0.3.6", default-features = false } -alloy-rpc-types = { version = "0.3.6", default-features = false } -alloy-rpc-client = { version = "0.3.6", default-features = false } -alloy-rpc-types-engine = { version = "0.3.6", default-features = false } -alloy-node-bindings = { version = "0.3.6", default-features = false } -alloy-transport-http = { version = "0.3.6", default-features = false } +alloy-consensus = { version = "0.4.0", default-features = false } +alloy-transport = { version = "0.4.0", default-features = false } +alloy-rpc-types = { version = "0.4.0", default-features = false } +alloy-rpc-client = { version = "0.4.0", default-features = false } +alloy-rpc-types-engine = { version = "0.4.0", default-features = false } +alloy-node-bindings = { version = "0.4.0", default-features = false } +alloy-transport-http = { version = "0.4.0", default-features = false } # OP Alloy -op-alloy-consensus = { version = "0.2.12", default-features = false } -op-alloy-protocol = { version = "0.2.12", default-features = false } -op-alloy-genesis = { version = "0.2.12", default-features = false } -op-alloy-rpc-types-engine = { version = "0.2.12", default-features = false } +op-alloy-consensus = { version = "0.3.2", default-features = false } +op-alloy-protocol = { version = "0.3.2", default-features = false } +op-alloy-genesis = { version = "0.3.2", default-features = false } +op-alloy-rpc-types-engine = { version = "0.3.2", default-features = false } diff --git a/bin/client/Cargo.toml b/bin/client/Cargo.toml index 771f73ac..4a2fcaa3 100644 --- a/bin/client/Cargo.toml +++ b/bin/client/Cargo.toml @@ -16,6 +16,7 @@ kona-preimage.workspace = true kona-mpt.workspace = true kona-derive.workspace = true kona-executor.workspace = true +kona-providers.workspace = true kona-primitives = { workspace = true, features = ["serde"] } op-alloy-genesis = { workspace = true, features = ["serde"] } op-alloy-protocol.workspace = true diff --git a/bin/client/src/l1/chain_provider.rs b/bin/client/src/l1/chain_provider.rs index b98c741b..7c38d800 100644 --- a/bin/client/src/l1/chain_provider.rs +++ b/bin/client/src/l1/chain_provider.rs @@ -8,9 +8,9 @@ use alloy_primitives::{Bytes, B256}; use alloy_rlp::Decodable; use anyhow::{anyhow, Result}; use async_trait::async_trait; -use kona_derive::traits::ChainProvider; use kona_mpt::{OrderedListWalker, TrieProvider}; use kona_preimage::{CommsClient, PreimageKey, PreimageKeyType}; +use kona_providers::ChainProvider; use op_alloy_protocol::BlockInfo; /// The oracle-backed L1 chain provider for the client program. diff --git a/bin/client/src/l1/driver.rs b/bin/client/src/l1/driver.rs index 2495371d..fdda5b9f 100644 --- a/bin/client/src/l1/driver.rs +++ b/bin/client/src/l1/driver.rs @@ -19,11 +19,12 @@ use kona_derive::{ AttributesQueue, BatchQueue, BatchStream, ChannelBank, ChannelReader, FrameQueue, L1Retrieval, L1Traversal, }, - traits::{BlobProvider, ChainProvider, L2ChainProvider, OriginProvider}, + traits::{BlobProvider, OriginProvider}, }; use kona_executor::{KonaHandleRegister, StatelessL2BlockExecutor}; use kona_mpt::{TrieHinter, TrieProvider}; use kona_preimage::{CommsClient, PreimageKey, PreimageKeyType}; +use kona_providers::{ChainProvider, L2ChainProvider}; use op_alloy_genesis::RollupConfig; use op_alloy_protocol::{BlockInfo, L2BlockInfo}; use op_alloy_rpc_types_engine::OptimismAttributesWithParent; diff --git a/bin/client/src/l2/chain_provider.rs b/bin/client/src/l2/chain_provider.rs index e4991bba..077fa5ed 100644 --- a/bin/client/src/l2/chain_provider.rs +++ b/bin/client/src/l2/chain_provider.rs @@ -2,16 +2,16 @@ use crate::{BootInfo, HintType}; use alloc::{boxed::Box, sync::Arc, vec::Vec}; -use alloy_consensus::Header; +use alloy_consensus::{BlockBody, Header}; use alloy_eips::eip2718::Decodable2718; use alloy_primitives::{Address, Bytes, B256}; use alloy_rlp::Decodable; use anyhow::{anyhow, Result}; use async_trait::async_trait; -use kona_derive::{block::OpBlock, traits::L2ChainProvider}; use kona_mpt::{OrderedListWalker, TrieHinter, TrieProvider}; use kona_preimage::{CommsClient, PreimageKey, PreimageKeyType}; -use op_alloy_consensus::OpTxEnvelope; +use kona_providers::{to_system_config, L2ChainProvider}; +use op_alloy_consensus::{OpBlock, OpTxEnvelope}; use op_alloy_genesis::{RollupConfig, SystemConfig}; use op_alloy_protocol::L2BlockInfo; @@ -71,11 +71,12 @@ impl L2ChainProvider for OracleL2ChainProvider type Error = anyhow::Error; async fn l2_block_info_by_number(&mut self, number: u64) -> Result { - // Get the payload at the given block number. - let payload = self.block_by_number(number).await?; + // Get the block at the given number. + let block = self.block_by_number(number).await?; // Construct the system config from the payload. - payload.to_l2_block_ref(&self.boot_info.rollup_config).map_err(Into::into) + L2BlockInfo::from_block_and_genesis(&block, &self.boot_info.rollup_config.genesis) + .map_err(Into::into) } async fn block_by_number(&mut self, number: u64) -> Result { @@ -99,9 +100,16 @@ impl L2ChainProvider for OracleL2ChainProvider let optimism_block = OpBlock { header, - body: transactions, - withdrawals: self.boot_info.rollup_config.is_canyon_active(timestamp).then(Vec::new), - ..Default::default() + body: BlockBody { + transactions, + ommers: Vec::new(), + withdrawals: self + .boot_info + .rollup_config + .is_canyon_active(timestamp) + .then(Vec::new), + requests: None, + }, }; Ok(optimism_block) } @@ -111,11 +119,11 @@ impl L2ChainProvider for OracleL2ChainProvider number: u64, rollup_config: Arc, ) -> Result { - // Get the payload at the given block number. - let payload = self.block_by_number(number).await?; + // Get the block at the given number. + let block = self.block_by_number(number).await?; // Construct the system config from the payload. - payload.to_system_config(rollup_config.as_ref()).map_err(Into::into) + to_system_config(&block, rollup_config.as_ref()).map_err(Into::into) } } diff --git a/bin/host/src/fetcher/mod.rs b/bin/host/src/fetcher/mod.rs index 4ebaed38..5b2d0771 100644 --- a/bin/host/src/fetcher/mod.rs +++ b/bin/host/src/fetcher/mod.rs @@ -555,7 +555,7 @@ where buf.put_slice(node.as_ref()); }); hb.root(); - let intermediates = hb.take_proofs(); + let intermediates = hb.take_proof_nodes().into_inner(); for (_, value) in intermediates.into_iter() { let value_hash = keccak256(value.as_ref()); diff --git a/crates/derive/Cargo.toml b/crates/derive/Cargo.toml index 58bf02d7..f7b552f3 100644 --- a/crates/derive/Cargo.toml +++ b/crates/derive/Cargo.toml @@ -33,6 +33,7 @@ tracing.workspace = true async-trait.workspace = true # Workspace +kona-providers.workspace = true kona-primitives.workspace = true # `serde` feature dependencies diff --git a/crates/derive/src/attributes/mod.rs b/crates/derive/src/attributes/mod.rs index e8d901b1..54878ce6 100644 --- a/crates/derive/src/attributes/mod.rs +++ b/crates/derive/src/attributes/mod.rs @@ -4,7 +4,7 @@ use crate::{ errors::{ BuilderError, PipelineEncodingError, PipelineError, PipelineErrorKind, PipelineResult, }, - traits::{AttributesBuilder, ChainProvider, L2ChainProvider}, + traits::AttributesBuilder, }; use alloc::{boxed::Box, fmt::Debug, string::ToString, sync::Arc, vec, vec::Vec}; use alloy_consensus::{Eip658Value, Receipt}; @@ -13,6 +13,7 @@ use alloy_primitives::{address, Address, Bytes, B256}; use alloy_rlp::Encodable; use alloy_rpc_types_engine::PayloadAttributes; use async_trait::async_trait; +use kona_providers::{ChainProvider, L2ChainProvider}; use op_alloy_consensus::Hardforks; use op_alloy_genesis::RollupConfig; use op_alloy_protocol::{decode_deposit, L1BlockInfoTx, L2BlockInfo, DEPOSIT_EVENT_ABI_HASH}; @@ -97,7 +98,11 @@ where .await .map_err(|e| PipelineError::BadEncoding(e).crit())?; sys_config - .update_with_receipts(&receipts, &self.rollup_cfg, header.timestamp) + .update_with_receipts( + &receipts, + self.rollup_cfg.l1_system_config_address, + self.rollup_cfg.is_ecotone_active(header.timestamp), + ) .map_err(|e| PipelineError::SystemConfigUpdate(e).crit())?; l1_header = header; deposit_transactions = deposits; diff --git a/crates/derive/src/batch/mod.rs b/crates/derive/src/batch/mod.rs index 8dad6153..8e617466 100644 --- a/crates/derive/src/batch/mod.rs +++ b/crates/derive/src/batch/mod.rs @@ -2,10 +2,11 @@ //! [SingleBatch]. use alloy_rlp::{Buf, Decodable}; +use kona_providers::L2ChainProvider; use op_alloy_genesis::RollupConfig; use op_alloy_protocol::{BlockInfo, L2BlockInfo}; -use crate::{errors::PipelineEncodingError, traits::L2ChainProvider}; +use crate::errors::PipelineEncodingError; mod batch_type; pub use batch_type::BatchType; diff --git a/crates/derive/src/batch/span_batch/batch.rs b/crates/derive/src/batch/span_batch/batch.rs index 04dde566..a4054ad2 100644 --- a/crates/derive/src/batch/span_batch/batch.rs +++ b/crates/derive/src/batch/span_batch/batch.rs @@ -3,6 +3,7 @@ use alloc::vec::Vec; use alloy_eips::eip2718::Encodable2718; use alloy_primitives::FixedBytes; +use kona_providers::L2ChainProvider; use op_alloy_consensus::OpTxType; use op_alloy_genesis::RollupConfig; use op_alloy_protocol::{BlockInfo, L2BlockInfo}; @@ -10,10 +11,7 @@ use tracing::{info, warn}; use super::{SpanBatchBits, SpanBatchElement, SpanBatchError, SpanBatchTransactions}; -use crate::{ - batch::{BatchValidity, SingleBatch}, - traits::L2ChainProvider, -}; +use crate::batch::{BatchValidity, SingleBatch}; /// The span batch contains the input to build a span of L2 blocks in derived form. #[derive(Debug, Default, Clone, PartialEq, Eq)] @@ -300,28 +298,36 @@ impl SpanBatch { return BatchValidity::Undecided; } }; - let safe_block_txs = &safe_block_payload.body; + let safe_block = &safe_block_payload.body; let batch_txs = &self.batches[i as usize].transactions; // Execution payload has deposit txs but batch does not. - let deposit_count: usize = - safe_block_txs.iter().map(|tx| if tx.is_deposit() { 1 } else { 0 }).sum(); - if safe_block_txs.len() - deposit_count != batch_txs.len() { + let deposit_count: usize = safe_block + .transactions + .iter() + .map(|tx| if tx.is_deposit() { 1 } else { 0 }) + .sum(); + if safe_block.transactions.len() - deposit_count != batch_txs.len() { warn!( "overlapped block's tx count does not match, safe_block_txs: {}, batch_txs: {}", - safe_block_txs.len(), + safe_block.transactions.len(), batch_txs.len() ); return BatchValidity::Drop; } - for j in 0..batch_txs.len() { + let batch_txs_len = batch_txs.len(); + #[allow(clippy::needless_range_loop)] + for j in 0..batch_txs_len { let mut buf = Vec::new(); - safe_block_txs[j + deposit_count].encode_2718(&mut buf); + safe_block.transactions[j + deposit_count].encode_2718(&mut buf); if buf != batch_txs[j].0 { warn!("overlapped block's transaction does not match"); return BatchValidity::Drop; } } - let safe_block_ref = match safe_block_payload.to_l2_block_ref(cfg) { + let safe_block_ref = match L2BlockInfo::from_block_and_genesis( + &safe_block_payload, + &cfg.genesis, + ) { Ok(r) => r, Err(e) => { warn!("failed to extract L2BlockInfo from execution payload, hash: {}, err: {e}", safe_block_payload.header.hash_slow()); @@ -534,7 +540,6 @@ impl SpanBatch { mod tests { use super::*; use crate::{ - block::OpBlock, stages::test_utils::{CollectingLayer, TraceStorage}, traits::test_utils::TestL2ChainProvider, }; @@ -542,7 +547,7 @@ mod tests { use alloy_consensus::Header; use alloy_eips::BlockNumHash; use alloy_primitives::{b256, Bytes}; - use op_alloy_consensus::OpTxType; + use op_alloy_consensus::{OpBlock, OpTxType}; use op_alloy_genesis::ChainGenesis; use tracing::Level; use tracing_subscriber::{layer::SubscriberExt, util::SubscriberInitExt}; @@ -1525,8 +1530,15 @@ mod tests { l1_origin: BlockNumHash { number: 9, ..Default::default() }, ..Default::default() }; - let block = - OpBlock { header: Header { number: 41, ..Default::default() }, ..Default::default() }; + let block = OpBlock { + header: Header { number: 41, ..Default::default() }, + body: alloy_consensus::BlockBody { + transactions: Vec::new(), + ommers: Vec::new(), + withdrawals: None, + requests: None, + }, + }; let mut fetcher = TestL2ChainProvider { blocks: vec![l2_block], op_blocks: vec![block], @@ -1593,8 +1605,15 @@ mod tests { l1_origin: BlockNumHash { number: 9, ..Default::default() }, ..Default::default() }; - let block = - OpBlock { header: Header { number: 41, ..Default::default() }, ..Default::default() }; + let block = OpBlock { + header: Header { number: 41, ..Default::default() }, + body: alloy_consensus::BlockBody { + transactions: Vec::new(), + ommers: Vec::new(), + withdrawals: None, + requests: None, + }, + }; let mut fetcher = TestL2ChainProvider { blocks: vec![l2_block], op_blocks: vec![block], @@ -1663,8 +1682,15 @@ mod tests { l1_origin: BlockNumHash { number: 9, ..Default::default() }, ..Default::default() }; - let block = - OpBlock { header: Header { number: 41, ..Default::default() }, ..Default::default() }; + let block = OpBlock { + header: Header { number: 41, ..Default::default() }, + body: alloy_consensus::BlockBody { + transactions: Vec::new(), + ommers: Vec::new(), + withdrawals: None, + requests: None, + }, + }; let mut fetcher = TestL2ChainProvider { blocks: vec![l2_block], op_blocks: vec![block], diff --git a/crates/derive/src/batch/span_batch/transactions.rs b/crates/derive/src/batch/span_batch/transactions.rs index 86e08f49..17e9e50b 100644 --- a/crates/derive/src/batch/span_batch/transactions.rs +++ b/crates/derive/src/batch/span_batch/transactions.rs @@ -396,9 +396,7 @@ impl SpanBatchTransactions { self.y_parity_bits.set_bit((i + offset) as usize, y_parity_bit); self.tx_nonces.push(nonce); self.tx_datas.push(tx_data_buf); - self.tx_gases.push(gas.try_into().map_err(|_| { - SpanBatchError::Decoding(SpanDecodingError::InvalidTransactionData) - })?); + self.tx_gases.push(gas); self.tx_types.push(tx_type); } self.total_block_tx_count += total_block_tx_count; diff --git a/crates/derive/src/batch/span_batch/tx_data/eip1559.rs b/crates/derive/src/batch/span_batch/tx_data/eip1559.rs index 0e487a7a..279b8125 100644 --- a/crates/derive/src/batch/span_batch/tx_data/eip1559.rs +++ b/crates/derive/src/batch/span_batch/tx_data/eip1559.rs @@ -44,7 +44,7 @@ impl SpanBatchEip1559TransactionData { |_| SpanBatchError::Decoding(SpanDecodingError::InvalidTransactionData), )?, ), - gas_limit: gas as u128, + gas_limit: gas, to: to.map_or(TxKind::Create, TxKind::Call), value: self.value, input: self.data.clone().into(), diff --git a/crates/derive/src/batch/span_batch/tx_data/eip2930.rs b/crates/derive/src/batch/span_batch/tx_data/eip2930.rs index 56357217..0062abc6 100644 --- a/crates/derive/src/batch/span_batch/tx_data/eip2930.rs +++ b/crates/derive/src/batch/span_batch/tx_data/eip2930.rs @@ -37,7 +37,7 @@ impl SpanBatchEip2930TransactionData { SpanBatchError::Decoding(SpanDecodingError::InvalidTransactionData) })?, ), - gas_limit: gas as u128, + gas_limit: gas, to: to.map_or(TxKind::Create, TxKind::Call), value: self.value, input: self.data.clone().into(), diff --git a/crates/derive/src/batch/span_batch/tx_data/legacy.rs b/crates/derive/src/batch/span_batch/tx_data/legacy.rs index 625627a3..0f8649f6 100644 --- a/crates/derive/src/batch/span_batch/tx_data/legacy.rs +++ b/crates/derive/src/batch/span_batch/tx_data/legacy.rs @@ -34,7 +34,7 @@ impl SpanBatchLegacyTransactionData { SpanBatchError::Decoding(SpanDecodingError::InvalidTransactionData) })?, ), - gas_limit: gas as u128, + gas_limit: gas, to: to.map_or(TxKind::Create, TxKind::Call), value: self.value, input: self.data.clone().into(), diff --git a/crates/derive/src/block.rs b/crates/derive/src/block.rs deleted file mode 100644 index eb847f69..00000000 --- a/crates/derive/src/block.rs +++ /dev/null @@ -1,166 +0,0 @@ -//! This module contains the various Block types. - -use alloc::vec::Vec; -use alloy_consensus::{Header, TxEnvelope}; -use alloy_eips::eip4895::Withdrawal; -use alloy_primitives::B256; -use alloy_rlp::{RlpDecodable, RlpEncodable}; -use op_alloy_consensus::OpTxEnvelope; -use op_alloy_genesis::{RollupConfig, SystemConfig}; -use op_alloy_protocol::{ - block_info::DecodeError, BlockInfo, L1BlockInfoBedrock, L1BlockInfoEcotone, L1BlockInfoTx, - L2BlockInfo, -}; -use thiserror::Error; - -/// Ethereum full block. -/// -/// Withdrawals can be optionally included at the end of the RLP encoded message. -/// -/// Taken from [reth-primitives](https://github.com/paradigmxyz/reth) -#[derive(Debug, Clone, PartialEq, Eq, Default, RlpEncodable, RlpDecodable)] -#[rlp(trailing)] -pub struct Block { - /// Block header. - pub header: Header, - /// Transactions in this block. - pub body: Vec, - /// Ommers/uncles header. - pub ommers: Vec
, - /// Block withdrawals. - pub withdrawals: Option>, -} - -/// An error encountered during [OpBlock] conversion. -#[derive(Error, Debug)] -pub enum OpBlockConversionError { - /// Invalid genesis hash. - #[error("Invalid genesis hash. Expected {0}, got {1}")] - InvalidGenesisHash(B256, B256), - /// Invalid transaction type. - #[error("First payload transaction has unexpected type: {0}")] - InvalidTxType(u8), - /// L1 Info error - #[error(transparent)] - L1InfoError(#[from] DecodeError), - /// Missing system config in genesis block. - #[error("Missing system config in genesis block")] - MissingSystemConfigGenesis, - /// Empty transactions. - #[error("Empty transactions in payload. Block hash: {0}")] - EmptyTransactions(B256), -} - -/// OP Stack full block. -/// -/// Withdrawals can be optionally included at the end of the RLP encoded message. -/// -/// Taken from [reth-primitives](https://github.com/paradigmxyz/reth) -#[derive(Debug, Clone, PartialEq, Eq, Default, RlpEncodable, RlpDecodable)] -#[rlp(trailing)] -pub struct OpBlock { - /// Block header. - pub header: Header, - /// Transactions in this block. - pub body: Vec, - /// Ommers/uncles header. - pub ommers: Vec
, - /// Block withdrawals. - pub withdrawals: Option>, -} - -impl OpBlock { - /// Converts the [OpBlock] to an [L2BlockInfo], by checking against the L1 - /// information transaction or the genesis block. - pub fn to_l2_block_ref( - &self, - rollup_config: &RollupConfig, - ) -> Result { - let (l1_origin, sequence_number) = if self.header.number == rollup_config.genesis.l2.number - { - if self.header.hash_slow() != rollup_config.genesis.l2.hash { - return Err(OpBlockConversionError::InvalidGenesisHash( - rollup_config.genesis.l2.hash, - self.header.hash_slow(), - )); - } - (rollup_config.genesis.l1, 0) - } else { - if self.body.is_empty() { - return Err(OpBlockConversionError::EmptyTransactions(self.header.hash_slow())); - } - - let OpTxEnvelope::Deposit(ref tx) = self.body[0] else { - return Err(OpBlockConversionError::InvalidTxType(self.body[0].tx_type() as u8)); - }; - - let l1_info = L1BlockInfoTx::decode_calldata(tx.input.as_ref())?; - (l1_info.id(), l1_info.sequence_number()) - }; - - Ok(L2BlockInfo { - block_info: BlockInfo { - hash: self.header.hash_slow(), - number: self.header.number, - parent_hash: self.header.parent_hash, - timestamp: self.header.timestamp, - }, - l1_origin, - seq_num: sequence_number, - }) - } - - /// Converts the [OpBlock] to a partial [SystemConfig]. - pub fn to_system_config( - &self, - rollup_config: &RollupConfig, - ) -> Result { - if self.header.number == rollup_config.genesis.l2.number { - if self.header.hash_slow() != rollup_config.genesis.l2.hash { - return Err(OpBlockConversionError::InvalidGenesisHash( - rollup_config.genesis.l2.hash, - self.header.hash_slow(), - )); - } - return rollup_config - .genesis - .system_config - .ok_or(OpBlockConversionError::MissingSystemConfigGenesis); - } - - if self.body.is_empty() { - return Err(OpBlockConversionError::EmptyTransactions(self.header.hash_slow())); - } - let OpTxEnvelope::Deposit(ref tx) = self.body[0] else { - return Err(OpBlockConversionError::InvalidTxType(self.body[0].tx_type() as u8)); - }; - - let l1_info = L1BlockInfoTx::decode_calldata(tx.input.as_ref())?; - let l1_fee_scalar = match l1_info { - L1BlockInfoTx::Bedrock(L1BlockInfoBedrock { l1_fee_scalar, .. }) => l1_fee_scalar, - L1BlockInfoTx::Ecotone(L1BlockInfoEcotone { - base_fee_scalar, - blob_base_fee_scalar, - .. - }) => { - // Translate Ecotone values back into encoded scalar if needed. - // We do not know if it was derived from a v0 or v1 scalar, - // but v1 is fine, a 0 blob base fee has the same effect. - let mut buf = B256::ZERO; - buf[0] = 0x01; - buf[24..28].copy_from_slice(blob_base_fee_scalar.to_be_bytes().as_ref()); - buf[28..32].copy_from_slice(base_fee_scalar.to_be_bytes().as_ref()); - buf.into() - } - }; - - Ok(SystemConfig { - batcher_address: l1_info.batcher_address(), - overhead: l1_info.l1_fee_overhead(), - scalar: l1_fee_scalar, - gas_limit: self.header.gas_limit as u64, - base_fee_scalar: None, - blob_base_fee_scalar: None, - }) - } -} diff --git a/crates/derive/src/lib.rs b/crates/derive/src/lib.rs index 341b890e..c08a298b 100644 --- a/crates/derive/src/lib.rs +++ b/crates/derive/src/lib.rs @@ -12,13 +12,14 @@ pub mod prelude { errors::{PipelineError, PipelineErrorKind}, pipeline::{DerivationPipeline, PipelineBuilder}, sources::EthereumDataSource, - traits::{ChainProvider, L2ChainProvider, OriginProvider, Pipeline, StepResult}, + traits::{OriginProvider, Pipeline, StepResult}, }; + + pub use kona_providers::prelude::*; } pub mod attributes; pub mod batch; -pub mod block; pub mod errors; pub mod pipeline; pub mod sources; diff --git a/crates/derive/src/pipeline/builder.rs b/crates/derive/src/pipeline/builder.rs index 6c853ba5..ed8e541d 100644 --- a/crates/derive/src/pipeline/builder.rs +++ b/crates/derive/src/pipeline/builder.rs @@ -1,14 +1,13 @@ //! Contains the `PipelineBuilder` object that is used to build a `DerivationPipeline`. -use super::{ - AttributesBuilder, ChainProvider, DataAvailabilityProvider, DerivationPipeline, L2ChainProvider, -}; +use super::{AttributesBuilder, DataAvailabilityProvider, DerivationPipeline}; use crate::stages::{ AttributesQueue, BatchQueue, BatchStream, ChannelBank, ChannelReader, FrameQueue, L1Retrieval, L1Traversal, }; use alloc::sync::Arc; use core::fmt::Debug; +use kona_providers::{ChainProvider, L2ChainProvider}; use op_alloy_genesis::RollupConfig; use op_alloy_protocol::BlockInfo; diff --git a/crates/derive/src/pipeline/core.rs b/crates/derive/src/pipeline/core.rs index b05aeab5..1586aff3 100644 --- a/crates/derive/src/pipeline/core.rs +++ b/crates/derive/src/pipeline/core.rs @@ -1,13 +1,14 @@ //! Contains the core derivation pipeline. use super::{ - L2ChainProvider, NextAttributes, OriginAdvancer, OriginProvider, Pipeline, PipelineError, - PipelineResult, ResettableStage, StepResult, + NextAttributes, OriginAdvancer, OriginProvider, Pipeline, PipelineError, PipelineResult, + ResettableStage, StepResult, }; use crate::errors::PipelineErrorKind; use alloc::{boxed::Box, collections::VecDeque, string::ToString, sync::Arc}; use async_trait::async_trait; use core::fmt::Debug; +use kona_providers::L2ChainProvider; use op_alloy_genesis::RollupConfig; use op_alloy_protocol::{BlockInfo, L2BlockInfo}; use op_alloy_rpc_types_engine::OptimismAttributesWithParent; diff --git a/crates/derive/src/pipeline/mod.rs b/crates/derive/src/pipeline/mod.rs index ec1e53d5..67232aa7 100644 --- a/crates/derive/src/pipeline/mod.rs +++ b/crates/derive/src/pipeline/mod.rs @@ -2,10 +2,13 @@ /// Re-export trait arguments. pub use crate::traits::{ - AttributesBuilder, ChainProvider, DataAvailabilityProvider, L2ChainProvider, NextAttributes, - OriginAdvancer, OriginProvider, Pipeline, ResetProvider, ResettableStage, StepResult, + AttributesBuilder, DataAvailabilityProvider, NextAttributes, OriginAdvancer, OriginProvider, + Pipeline, ResetProvider, ResettableStage, StepResult, }; +/// Re-export kona provider traits. +pub use kona_providers::{ChainProvider, L2ChainProvider}; + /// Re-export error types. pub use crate::errors::{PipelineError, PipelineResult}; diff --git a/crates/derive/src/sources/blobs.rs b/crates/derive/src/sources/blobs.rs index 93b93e03..28e27a10 100644 --- a/crates/derive/src/sources/blobs.rs +++ b/crates/derive/src/sources/blobs.rs @@ -2,13 +2,14 @@ use crate::{ errors::{BlobProviderError, PipelineError, PipelineResult}, - traits::{AsyncIterator, BlobProvider, ChainProvider}, + traits::{AsyncIterator, BlobProvider}, }; use alloc::{boxed::Box, format, string::ToString, vec::Vec}; use alloy_consensus::{Transaction, TxEip4844Variant, TxEnvelope, TxType}; use alloy_primitives::{Address, Bytes, TxKind}; use async_trait::async_trait; use kona_primitives::{BlobData, IndexedBlobHash}; +use kona_providers::ChainProvider; use op_alloy_protocol::BlockInfo; use tracing::warn; diff --git a/crates/derive/src/sources/calldata.rs b/crates/derive/src/sources/calldata.rs index f24c763e..c866f345 100644 --- a/crates/derive/src/sources/calldata.rs +++ b/crates/derive/src/sources/calldata.rs @@ -2,12 +2,13 @@ use crate::{ errors::{PipelineError, PipelineResult}, - traits::{AsyncIterator, ChainProvider}, + traits::AsyncIterator, }; use alloc::{boxed::Box, collections::VecDeque, format}; use alloy_consensus::{Transaction, TxEnvelope}; use alloy_primitives::{Address, Bytes, TxKind}; use async_trait::async_trait; +use kona_providers::ChainProvider; use op_alloy_protocol::BlockInfo; /// A data iterator that reads from calldata. diff --git a/crates/derive/src/sources/ethereum.rs b/crates/derive/src/sources/ethereum.rs index 7ca5dd55..b679a6e3 100644 --- a/crates/derive/src/sources/ethereum.rs +++ b/crates/derive/src/sources/ethereum.rs @@ -4,11 +4,12 @@ use crate::{ errors::PipelineResult, sources::{BlobSource, CalldataSource, EthereumDataSourceVariant}, - traits::{BlobProvider, ChainProvider, DataAvailabilityProvider}, + traits::{BlobProvider, DataAvailabilityProvider}, }; use alloc::{boxed::Box, fmt::Debug}; use alloy_primitives::{Address, Bytes}; use async_trait::async_trait; +use kona_providers::ChainProvider; use op_alloy_genesis::RollupConfig; use op_alloy_protocol::BlockInfo; diff --git a/crates/derive/src/sources/variant.rs b/crates/derive/src/sources/variant.rs index d29f4196..3ef18328 100644 --- a/crates/derive/src/sources/variant.rs +++ b/crates/derive/src/sources/variant.rs @@ -3,11 +3,12 @@ use alloc::boxed::Box; use alloy_primitives::Bytes; use async_trait::async_trait; +use kona_providers::ChainProvider; use crate::{ errors::PipelineResult, sources::{BlobSource, CalldataSource}, - traits::{AsyncIterator, BlobProvider, ChainProvider}, + traits::{AsyncIterator, BlobProvider}, }; /// An enum over the various data sources. diff --git a/crates/derive/src/stages/batch_queue.rs b/crates/derive/src/stages/batch_queue.rs index 910574de..e8843b99 100644 --- a/crates/derive/src/stages/batch_queue.rs +++ b/crates/derive/src/stages/batch_queue.rs @@ -4,11 +4,12 @@ use crate::{ batch::{Batch, BatchValidity, BatchWithInclusionBlock, SingleBatch}, errors::{PipelineEncodingError, PipelineError, PipelineErrorKind, PipelineResult, ResetError}, stages::attributes_queue::AttributesProvider, - traits::{L2ChainProvider, OriginAdvancer, OriginProvider, ResettableStage}, + traits::{OriginAdvancer, OriginProvider, ResettableStage}, }; use alloc::{boxed::Box, sync::Arc, vec::Vec}; use async_trait::async_trait; use core::fmt::Debug; +use kona_providers::L2ChainProvider; use op_alloy_genesis::{RollupConfig, SystemConfig}; use op_alloy_protocol::{BlockInfo, L2BlockInfo}; use tracing::{error, info, warn}; @@ -456,7 +457,6 @@ where mod tests { use super::*; use crate::{ - block::OpBlock, stages::{ channel_reader::BatchReader, test_utils::{CollectingLayer, MockBatchQueueProvider, TraceStorage}, @@ -468,7 +468,7 @@ mod tests { use alloy_eips::{eip2718::Decodable2718, BlockNumHash}; use alloy_primitives::{address, b256, Address, Bytes, TxKind, B256, U256}; use alloy_rlp::{BytesMut, Encodable}; - use op_alloy_consensus::{OpTxEnvelope, OpTxType, TxDeposit}; + use op_alloy_consensus::{OpBlock, OpTxEnvelope, OpTxType, TxDeposit}; use op_alloy_genesis::ChainGenesis; use op_alloy_protocol::{L1BlockInfoBedrock, L1BlockInfoTx}; use tracing::Level; @@ -626,22 +626,22 @@ mod tests { .map(|tx| OpTxEnvelope::decode_2718(&mut &tx[..]).unwrap()) .collect(); let block = OpBlock { - header: Header { - number: 8, - // TODO: fix hash - ..Default::default() + header: Header { number: 8, ..Default::default() }, + body: alloy_consensus::BlockBody { + transactions: batch_txs, + ommers: Vec::new(), + withdrawals: None, + requests: None, }, - body: batch_txs, - ..Default::default() }; let second = OpBlock { - header: Header { - number: 9, - // TODO: fix hash - ..Default::default() + header: Header { number: 9, ..Default::default() }, + body: alloy_consensus::BlockBody { + transactions: second_batch_txs, + ommers: Vec::new(), + withdrawals: None, + requests: None, }, - body: second_batch_txs, - ..Default::default() }; let fetcher = TestL2ChainProvider { blocks: vec![block_nine, block_seven], diff --git a/crates/derive/src/stages/l1_traversal.rs b/crates/derive/src/stages/l1_traversal.rs index 225be637..538247f8 100644 --- a/crates/derive/src/stages/l1_traversal.rs +++ b/crates/derive/src/stages/l1_traversal.rs @@ -3,11 +3,12 @@ use crate::{ errors::{PipelineError, PipelineResult, ResetError}, stages::L1RetrievalProvider, - traits::{ChainProvider, OriginAdvancer, OriginProvider, ResettableStage}, + traits::{OriginAdvancer, OriginProvider, ResettableStage}, }; use alloc::{boxed::Box, string::ToString, sync::Arc}; use alloy_primitives::Address; use async_trait::async_trait; +use kona_providers::ChainProvider; use op_alloy_genesis::{RollupConfig, SystemConfig}; use op_alloy_protocol::BlockInfo; use tracing::warn; @@ -101,8 +102,8 @@ impl OriginAdvancer for L1Traversal { if let Err(e) = self.system_config.update_with_receipts( receipts.as_slice(), - &self.rollup_config, - next_l1_origin.timestamp, + self.rollup_config.l1_system_config_address, + self.rollup_config.is_ecotone_active(next_l1_origin.timestamp), ) { return Err(PipelineError::SystemConfigUpdate(e).crit()); } diff --git a/crates/derive/src/stages/test_utils/sys_config_fetcher.rs b/crates/derive/src/stages/test_utils/sys_config_fetcher.rs index 6e01b5d9..8810bf79 100644 --- a/crates/derive/src/stages/test_utils/sys_config_fetcher.rs +++ b/crates/derive/src/stages/test_utils/sys_config_fetcher.rs @@ -1,10 +1,11 @@ //! Implements a mock [L2SystemConfigFetcher] for testing. -use crate::{block::OpBlock, traits::L2ChainProvider}; use alloc::{boxed::Box, sync::Arc}; use alloy_primitives::map::HashMap; use anyhow::Result; use async_trait::async_trait; +use kona_providers::L2ChainProvider; +use op_alloy_consensus::OpBlock; use op_alloy_genesis::{RollupConfig, SystemConfig}; use op_alloy_protocol::L2BlockInfo; diff --git a/crates/derive/src/traits/mod.rs b/crates/derive/src/traits/mod.rs index 8c59f0ae..d4b01ff0 100644 --- a/crates/derive/src/traits/mod.rs +++ b/crates/derive/src/traits/mod.rs @@ -13,9 +13,6 @@ pub use data_sources::{AsyncIterator, BlobProvider, DataAvailabilityProvider}; mod reset; pub use reset::ResetProvider; -mod providers; -pub use providers::{ChainProvider, L2ChainProvider}; - mod stages; pub use stages::{OriginAdvancer, OriginProvider, ResettableStage}; diff --git a/crates/derive/src/traits/providers.rs b/crates/derive/src/traits/providers.rs index cc7f16cc..8b137891 100644 --- a/crates/derive/src/traits/providers.rs +++ b/crates/derive/src/traits/providers.rs @@ -1,55 +1 @@ -use core::fmt::Display; -use crate::block::OpBlock; -use alloc::{boxed::Box, string::ToString, sync::Arc, vec::Vec}; -use alloy_consensus::{Header, Receipt, TxEnvelope}; -use alloy_primitives::B256; -use async_trait::async_trait; -use op_alloy_genesis::{RollupConfig, SystemConfig}; -use op_alloy_protocol::{BlockInfo, L2BlockInfo}; - -/// Describes the functionality of a data source that can provide information from the blockchain. -#[async_trait] -pub trait ChainProvider { - /// The error type for the [ChainProvider]. - type Error: Display + ToString; - - /// Fetch the L1 [Header] for the given [B256] hash. - async fn header_by_hash(&mut self, hash: B256) -> Result; - - /// Returns the block at the given number, or an error if the block does not exist in the data - /// source. - async fn block_info_by_number(&mut self, number: u64) -> Result; - - /// Returns all receipts in the block with the given hash, or an error if the block does not - /// exist in the data source. - async fn receipts_by_hash(&mut self, hash: B256) -> Result, Self::Error>; - - /// Returns the [BlockInfo] and list of [TxEnvelope]s from the given block hash. - async fn block_info_and_transactions_by_hash( - &mut self, - hash: B256, - ) -> Result<(BlockInfo, Vec), Self::Error>; -} - -/// Describes the functionality of a data source that fetches safe blocks. -#[async_trait] -pub trait L2ChainProvider { - /// The error type for the [L2ChainProvider]. - type Error: Display + ToString; - - /// Returns the L2 block info given a block number. - /// Errors if the block does not exist. - async fn l2_block_info_by_number(&mut self, number: u64) -> Result; - - /// Returns the block for a given number. - /// Errors if no block is available for the given block number. - async fn block_by_number(&mut self, number: u64) -> Result; - - /// Returns the [SystemConfig] by L2 number. - async fn system_config_by_number( - &mut self, - number: u64, - rollup_config: Arc, - ) -> Result; -} diff --git a/crates/derive/src/traits/test_utils.rs b/crates/derive/src/traits/test_utils.rs index 925a1a86..54b61298 100644 --- a/crates/derive/src/traits/test_utils.rs +++ b/crates/derive/src/traits/test_utils.rs @@ -1,11 +1,8 @@ //! Test Utilities for derive traits use crate::{ - block::OpBlock, errors::{BlobProviderError, PipelineError, PipelineResult}, - traits::{ - AsyncIterator, BlobProvider, ChainProvider, DataAvailabilityProvider, L2ChainProvider, - }, + traits::{AsyncIterator, BlobProvider, DataAvailabilityProvider}, }; use alloc::{boxed::Box, sync::Arc, vec, vec::Vec}; use alloy_consensus::{Header, Receipt, TxEnvelope}; @@ -15,6 +12,8 @@ use anyhow::Result; use async_trait::async_trait; use core::fmt::Debug; use kona_primitives::IndexedBlobHash; +use kona_providers::{ChainProvider, L2ChainProvider}; +use op_alloy_consensus::OpBlock; use op_alloy_genesis::{RollupConfig, SystemConfig}; use op_alloy_protocol::{BlockInfo, L2BlockInfo}; diff --git a/crates/executor/benches/execution.rs b/crates/executor/benches/execution.rs index 0963133e..6b0576a9 100644 --- a/crates/executor/benches/execution.rs +++ b/crates/executor/benches/execution.rs @@ -9,7 +9,7 @@ use anyhow::{anyhow, Result}; use criterion::{criterion_group, criterion_main, Bencher, Criterion}; use kona_executor::StatelessL2BlockExecutor; use kona_mpt::{NoopTrieHinter, TrieProvider}; -use op_alloy_genesis::{RollupConfig, OP_BASE_FEE_PARAMS, OP_CANYON_BASE_FEE_PARAMS}; +use op_alloy_genesis::{RollupConfig, OP_MAINNET_BASE_FEE_PARAMS}; use op_alloy_rpc_types_engine::OptimismPayloadAttributes; use pprof::criterion::{Output, PProfProfiler}; use serde::Deserialize; @@ -73,8 +73,8 @@ fn op_mainnet_exec_bench( canyon_time: Some(0), delta_time: Some(0), ecotone_time: Some(0), - base_fee_params: OP_BASE_FEE_PARAMS, - canyon_base_fee_params: OP_CANYON_BASE_FEE_PARAMS, + base_fee_params: OP_MAINNET_BASE_FEE_PARAMS.as_base_fee_params(), + canyon_base_fee_params: OP_MAINNET_BASE_FEE_PARAMS.as_canyon_base_fee_params(), ..Default::default() }; diff --git a/crates/executor/src/lib.rs b/crates/executor/src/lib.rs index b93dbee9..bc4729cc 100644 --- a/crates/executor/src/lib.rs +++ b/crates/executor/src/lib.rs @@ -288,7 +288,7 @@ where let excess_blob_gas = if self.config.is_ecotone_active(parent_header.timestamp) { let parent_excess_blob_gas = parent_header.excess_blob_gas.unwrap_or_default(); let parent_blob_gas_used = parent_header.blob_gas_used.unwrap_or_default(); - calc_excess_blob_gas(parent_excess_blob_gas as u64, parent_blob_gas_used as u64) + calc_excess_blob_gas(parent_excess_blob_gas, parent_blob_gas_used) } else { // For the first post-fork block, both blob gas fields are evaluated to 0. calc_excess_blob_gas(0, 0) @@ -311,14 +311,14 @@ where logs_bloom, difficulty: U256::ZERO, number: block_number, - gas_limit: gas_limit.into(), - gas_used: cumulative_gas_used as u128, + gas_limit, + gas_used: cumulative_gas_used, timestamp: payload.payload_attributes.timestamp, mix_hash: payload.payload_attributes.prev_randao, nonce: Default::default(), - base_fee_per_gas: Some(base_fee), + base_fee_per_gas: base_fee.try_into().ok(), blob_gas_used, - excess_blob_gas, + excess_blob_gas: excess_blob_gas.and_then(|x| x.try_into().ok()), parent_beacon_block_root: payload.payload_attributes.parent_beacon_block_root, // Provide no extra data on OP Stack chains extra_data: Bytes::default(), @@ -501,7 +501,7 @@ where let blob_excess_gas_and_price = parent_header .next_block_excess_blob_gas() .or_else(|| spec_id.is_enabled_in(SpecId::ECOTONE).then_some(0)) - .map(|x| BlobExcessGasAndPrice::new(x as u64)); + .map(BlobExcessGasAndPrice::new); // If the payload attribute timestamp is past canyon activation, // use the canyon base fee params from the rollup config. let base_fee_params = if config.is_canyon_active(payload_attrs.payload_attributes.timestamp) @@ -543,7 +543,7 @@ where OpTxEnvelope::Legacy(signed_tx) => { let tx = signed_tx.tx(); env.caller = signed_tx.recover_signer().map_err(ExecutorError::SignatureError)?; - env.gas_limit = tx.gas_limit as u64; + env.gas_limit = tx.gas_limit; env.gas_price = U256::from(tx.gas_price); env.gas_priority_fee = None; env.transact_to = match tx.to { @@ -568,7 +568,7 @@ where OpTxEnvelope::Eip2930(signed_tx) => { let tx = signed_tx.tx(); env.caller = signed_tx.recover_signer().map_err(ExecutorError::SignatureError)?; - env.gas_limit = tx.gas_limit as u64; + env.gas_limit = tx.gas_limit; env.gas_price = U256::from(tx.gas_price); env.gas_priority_fee = None; env.transact_to = match tx.to { @@ -593,7 +593,7 @@ where OpTxEnvelope::Eip1559(signed_tx) => { let tx = signed_tx.tx(); env.caller = signed_tx.recover_signer().map_err(ExecutorError::SignatureError)?; - env.gas_limit = tx.gas_limit as u64; + env.gas_limit = tx.gas_limit; env.gas_price = U256::from(tx.max_fee_per_gas); env.gas_priority_fee = Some(U256::from(tx.max_priority_fee_per_gas)); env.transact_to = match tx.to { @@ -618,7 +618,7 @@ where OpTxEnvelope::Deposit(tx) => { env.caller = tx.from; env.access_list.clear(); - env.gas_limit = tx.gas_limit as u64; + env.gas_limit = tx.gas_limit; env.gas_price = U256::ZERO; env.gas_priority_fee = None; match tx.to { @@ -650,7 +650,7 @@ mod test { use alloy_rpc_types_engine::PayloadAttributes; use anyhow::{anyhow, Result}; use kona_mpt::NoopTrieHinter; - use op_alloy_genesis::{OP_BASE_FEE_PARAMS, OP_CANYON_BASE_FEE_PARAMS}; + use op_alloy_genesis::OP_MAINNET_BASE_FEE_PARAMS; use serde::Deserialize; use std::collections::HashMap; @@ -711,8 +711,8 @@ mod test { canyon_time: Some(0), delta_time: Some(0), ecotone_time: Some(0), - base_fee_params: OP_BASE_FEE_PARAMS, - canyon_base_fee_params: OP_CANYON_BASE_FEE_PARAMS, + base_fee_params: OP_MAINNET_BASE_FEE_PARAMS.as_base_fee_params(), + canyon_base_fee_params: OP_MAINNET_BASE_FEE_PARAMS.as_canyon_base_fee_params(), ..Default::default() }; @@ -769,8 +769,8 @@ mod test { canyon_time: Some(0), delta_time: Some(0), ecotone_time: Some(0), - base_fee_params: OP_BASE_FEE_PARAMS, - canyon_base_fee_params: OP_CANYON_BASE_FEE_PARAMS, + base_fee_params: OP_MAINNET_BASE_FEE_PARAMS.as_base_fee_params(), + canyon_base_fee_params: OP_MAINNET_BASE_FEE_PARAMS.as_canyon_base_fee_params(), ..Default::default() }; @@ -831,8 +831,8 @@ mod test { canyon_time: Some(0), delta_time: Some(0), ecotone_time: Some(0), - base_fee_params: OP_BASE_FEE_PARAMS, - canyon_base_fee_params: OP_CANYON_BASE_FEE_PARAMS, + base_fee_params: OP_MAINNET_BASE_FEE_PARAMS.as_base_fee_params(), + canyon_base_fee_params: OP_MAINNET_BASE_FEE_PARAMS.as_canyon_base_fee_params(), ..Default::default() }; @@ -900,8 +900,8 @@ mod test { canyon_time: Some(0), delta_time: Some(0), ecotone_time: Some(0), - base_fee_params: OP_BASE_FEE_PARAMS, - canyon_base_fee_params: OP_CANYON_BASE_FEE_PARAMS, + base_fee_params: OP_MAINNET_BASE_FEE_PARAMS.as_base_fee_params(), + canyon_base_fee_params: OP_MAINNET_BASE_FEE_PARAMS.as_canyon_base_fee_params(), ..Default::default() }; @@ -963,8 +963,8 @@ mod test { canyon_time: Some(0), delta_time: Some(0), ecotone_time: Some(0), - base_fee_params: OP_BASE_FEE_PARAMS, - canyon_base_fee_params: OP_CANYON_BASE_FEE_PARAMS, + base_fee_params: OP_MAINNET_BASE_FEE_PARAMS.as_base_fee_params(), + canyon_base_fee_params: OP_MAINNET_BASE_FEE_PARAMS.as_canyon_base_fee_params(), ..Default::default() }; @@ -1035,8 +1035,8 @@ mod test { canyon_time: Some(0), delta_time: Some(0), ecotone_time: Some(0), - base_fee_params: OP_BASE_FEE_PARAMS, - canyon_base_fee_params: OP_CANYON_BASE_FEE_PARAMS, + base_fee_params: OP_MAINNET_BASE_FEE_PARAMS.as_base_fee_params(), + canyon_base_fee_params: OP_MAINNET_BASE_FEE_PARAMS.as_canyon_base_fee_params(), ..Default::default() }; diff --git a/crates/executor/src/util.rs b/crates/executor/src/util.rs index fd0a785d..d6710824 100644 --- a/crates/executor/src/util.rs +++ b/crates/executor/src/util.rs @@ -61,11 +61,11 @@ pub(crate) fn logs_bloom<'a>(logs: impl IntoIterator) -> Bloom { /// Extract the gas limit from an [OpTxEnvelope]. pub(crate) fn extract_tx_gas_limit(tx: &OpTxEnvelope) -> u128 { match tx { - OpTxEnvelope::Legacy(tx) => tx.tx().gas_limit, - OpTxEnvelope::Eip2930(tx) => tx.tx().gas_limit, - OpTxEnvelope::Eip1559(tx) => tx.tx().gas_limit, - OpTxEnvelope::Eip4844(tx) => tx.tx().gas_limit(), - OpTxEnvelope::Deposit(tx) => tx.gas_limit, + OpTxEnvelope::Legacy(tx) => tx.tx().gas_limit.into(), + OpTxEnvelope::Eip2930(tx) => tx.tx().gas_limit.into(), + OpTxEnvelope::Eip1559(tx) => tx.tx().gas_limit.into(), + OpTxEnvelope::Eip4844(tx) => tx.tx().gas_limit().into(), + OpTxEnvelope::Deposit(tx) => tx.gas_limit.into(), _ => unreachable!(), } } diff --git a/crates/mpt/src/list_walker.rs b/crates/mpt/src/list_walker.rs index 3c6ede61..3ec35965 100644 --- a/crates/mpt/src/list_walker.rs +++ b/crates/mpt/src/list_walker.rs @@ -213,11 +213,13 @@ mod test { let mut trie = ordered_trie_with_encoder(&VALUES, |v, buf| v.encode(buf)); let root = trie.root(); - let preimages = - trie.take_proofs().into_iter().fold(BTreeMap::default(), |mut acc, (_, value)| { + let preimages = trie.take_proof_nodes().into_inner().into_iter().fold( + BTreeMap::default(), + |mut acc, (_, value)| { acc.insert(keccak256(value.as_ref()), value); acc - }); + }, + ); let fetcher = TrieNodeProvider::new(preimages, BTreeMap::default(), BTreeMap::default()); let list = OrderedListWalker::try_new_hydrated(root, &fetcher).unwrap(); diff --git a/crates/mpt/src/node.rs b/crates/mpt/src/node.rs index 26622959..d7976896 100644 --- a/crates/mpt/src/node.rs +++ b/crates/mpt/src/node.rs @@ -790,11 +790,13 @@ mod test { }); let root = trie.root(); - let preimages = - trie.take_proofs().into_iter().fold(BTreeMap::default(), |mut acc, (_, value)| { + let preimages = trie.take_proof_nodes().into_inner().into_iter().fold( + BTreeMap::default(), + |mut acc, (_, value)| { acc.insert(keccak256(value.as_ref()), value); acc - }); + }, + ); let fetcher = TrieNodeProvider::new(preimages, Default::default(), Default::default()); let mut root_node = diff --git a/crates/mpt/src/test_util.rs b/crates/mpt/src/test_util.rs index 55d59d0a..d4bba38d 100644 --- a/crates/mpt/src/test_util.rs +++ b/crates/mpt/src/test_util.rs @@ -66,11 +66,13 @@ pub(crate) async fn get_live_derivable_receipts_list( assert_eq!(block.header.receipts_root, root); // Construct the mapping of hashed intermediates -> raw intermediates - let preimages = - list.take_proofs().into_iter().fold(BTreeMap::default(), |mut acc, (_, value)| { + let preimages = list.take_proof_nodes().into_inner().into_iter().fold( + BTreeMap::default(), + |mut acc, (_, value)| { acc.insert(keccak256(value.as_ref()), value); acc - }); + }, + ); Ok((root, preimages, consensus_receipts)) } @@ -105,11 +107,13 @@ pub(crate) async fn get_live_derivable_transactions_list( assert_eq!(block.header.transactions_root, root); // Construct the mapping of hashed intermediates -> raw intermediates - let preimages = - list.take_proofs().into_iter().fold(BTreeMap::default(), |mut acc, (_, value)| { + let preimages = list.take_proof_nodes().into_inner().into_iter().fold( + BTreeMap::default(), + |mut acc, (_, value)| { acc.insert(keccak256(value.as_ref()), value); acc - }); + }, + ); Ok((root, preimages, consensus_txs)) } diff --git a/crates/providers-alloy/Cargo.toml b/crates/providers-alloy/Cargo.toml index b4a15a27..eb228f5c 100644 --- a/crates/providers-alloy/Cargo.toml +++ b/crates/providers-alloy/Cargo.toml @@ -21,6 +21,7 @@ alloy-consensus = { workspace = true, features = ["k256", "serde", "std"] } alloy-primitives = { workspace = true, features = ["rlp", "k256", "serde"] } # OP Alloy +op-alloy-consensus = { workspace = true, features = ["k256"] } op-alloy-protocol = { workspace = true, features = ["serde", "std"] } op-alloy-genesis = { workspace = true, features = ["serde", "std"] } @@ -31,6 +32,7 @@ tracing.workspace = true async-trait.workspace = true # Workspace +kona-providers.workspace = true kona-derive = { workspace = true, features = ["serde"] } kona-primitives = { workspace = true, features = ["serde", "online"] } diff --git a/crates/providers-alloy/src/alloy_providers.rs b/crates/providers-alloy/src/alloy_providers.rs index 87728a19..5ef9fd80 100644 --- a/crates/providers-alloy/src/alloy_providers.rs +++ b/crates/providers-alloy/src/alloy_providers.rs @@ -1,21 +1,18 @@ //! Providers that use alloy provider types on the backend. -use alloy_consensus::{Header, Receipt, ReceiptWithBloom, TxEnvelope, TxType}; +use alloy_consensus::{Block, Header, Receipt, ReceiptWithBloom, TxEnvelope, TxType}; use alloy_primitives::{Bytes, B256, U64}; use alloy_provider::{Provider, ReqwestProvider}; use alloy_rlp::{Buf, Decodable}; use alloy_transport::{RpcError, TransportErrorKind, TransportResult}; use async_trait::async_trait; +use kona_providers::{to_system_config, ChainProvider, L2ChainProvider}; use lru::LruCache; +use op_alloy_consensus::OpBlock; use op_alloy_genesis::{RollupConfig, SystemConfig}; use op_alloy_protocol::{BlockInfo, L2BlockInfo}; use std::{boxed::Box, num::NonZeroUsize, sync::Arc, vec::Vec}; -use kona_derive::{ - block::{Block, OpBlock}, - traits::{ChainProvider, L2ChainProvider}, -}; - const CACHE_SIZE: usize = 16; /// The [AlloyChainProvider] is a concrete implementation of the [ChainProvider] trait, providing @@ -250,8 +247,9 @@ impl ChainProvider for AlloyChainProvider { parent_hash: block.header.parent_hash, timestamp: block.header.timestamp, }; - self.block_info_and_transactions_by_hash_cache.put(hash, (block_info, block.body.clone())); - Ok((block_info, block.body)) + self.block_info_and_transactions_by_hash_cache + .put(hash, (block_info, block.body.transactions.clone())); + Ok((block_info, block.body.transactions)) } } @@ -331,17 +329,18 @@ impl L2ChainProvider for AlloyL2ChainProvider { return Err(e); } }; - let l2_block_info = match block.to_l2_block_ref(self.rollup_config.as_ref()) { - Ok(b) => b, - Err(e) => { - crate::timer!(DISCARD, timer); - crate::inc!( - PROVIDER_ERRORS, - &["l2_chain_provider", "l2_block_info_by_number", "to_l2_block_ref"] - ); - return Err(RpcError::LocalUsageError(Box::new(e))); - } - }; + let l2_block_info = + match L2BlockInfo::from_block_and_genesis(&block, &self.rollup_config.genesis) { + Ok(b) => b, + Err(e) => { + crate::timer!(DISCARD, timer); + crate::inc!( + PROVIDER_ERRORS, + &["l2_chain_provider", "l2_block_info_by_number", "from_block_and_genesis"] + ); + return Err(RpcError::LocalUsageError(Box::new(e))); + } + }; self.l2_block_info_by_number_cache.put(number, l2_block_info); Ok(l2_block_info) } @@ -410,7 +409,7 @@ impl L2ChainProvider for AlloyL2ChainProvider { return Err(e); } }; - let sys_config = match block.to_system_config(&rollup_config) { + let sys_config = match to_system_config(&block, &rollup_config) { Ok(s) => s, Err(e) => { crate::timer!(DISCARD, timer); diff --git a/crates/providers-alloy/src/lib.rs b/crates/providers-alloy/src/lib.rs index 1a6a835c..1287161f 100644 --- a/crates/providers-alloy/src/lib.rs +++ b/crates/providers-alloy/src/lib.rs @@ -16,7 +16,15 @@ pub use test_utils::*; /// Re-export commonly used types and traits. pub mod prelude { - pub use super::*; + pub use super::{ + alloy_providers::{AlloyChainProvider, AlloyL2ChainProvider}, + beacon_client::{BeaconClient, OnlineBeaconClient}, + blob_provider::{ + BlobSidecarProvider, OnlineBlobProvider, OnlineBlobProviderBuilder, + OnlineBlobProviderWithFallback, SimpleSlotDerivation, SlotDerivation, + }, + pipeline::{new_online_pipeline, OnlinePipeline}, + }; pub use kona_derive::prelude::*; } diff --git a/crates/providers/Cargo.toml b/crates/providers/Cargo.toml new file mode 100644 index 00000000..14fb8db5 --- /dev/null +++ b/crates/providers/Cargo.toml @@ -0,0 +1,26 @@ +[package] +name = "kona-providers" +description = "Provider traits for Kona" +version = "0.0.1" +edition.workspace = true +authors.workspace = true +license.workspace = true +repository.workspace = true +homepage.workspace = true + +[lints] +workspace = true + +[dependencies] +# Alloy +alloy-consensus.workspace = true +alloy-primitives.workspace = true + +# OP Alloy +op-alloy-protocol.workspace = true +op-alloy-genesis.workspace = true +op-alloy-consensus = { workspace = true, features = ["k256"] } + +# Misc +thiserror.workspace = true +async-trait.workspace = true diff --git a/crates/providers/README.md b/crates/providers/README.md new file mode 100644 index 00000000..9a13e57f --- /dev/null +++ b/crates/providers/README.md @@ -0,0 +1,3 @@ +## `kona-providers` + +Provider trait definitions for `kona-derive`. diff --git a/crates/providers/src/l1_chain_provider.rs b/crates/providers/src/l1_chain_provider.rs new file mode 100644 index 00000000..caae2238 --- /dev/null +++ b/crates/providers/src/l1_chain_provider.rs @@ -0,0 +1,32 @@ +//! L1 Chain Provider. + +use alloc::{boxed::Box, string::ToString, vec::Vec}; +use alloy_consensus::{Header, Receipt, TxEnvelope}; +use alloy_primitives::B256; +use async_trait::async_trait; +use core::fmt::Display; +use op_alloy_protocol::BlockInfo; + +/// Describes the functionality of a data source that can provide information from the blockchain. +#[async_trait] +pub trait ChainProvider { + /// The error type for the [ChainProvider]. + type Error: Display + ToString; + + /// Fetch the L1 [Header] for the given [B256] hash. + async fn header_by_hash(&mut self, hash: B256) -> Result; + + /// Returns the block at the given number, or an error if the block does not exist in the data + /// source. + async fn block_info_by_number(&mut self, number: u64) -> Result; + + /// Returns all receipts in the block with the given hash, or an error if the block does not + /// exist in the data source. + async fn receipts_by_hash(&mut self, hash: B256) -> Result, Self::Error>; + + /// Returns the [BlockInfo] and list of [TxEnvelope]s from the given block hash. + async fn block_info_and_transactions_by_hash( + &mut self, + hash: B256, + ) -> Result<(BlockInfo, Vec), Self::Error>; +} diff --git a/crates/providers/src/l2_chain_provider.rs b/crates/providers/src/l2_chain_provider.rs new file mode 100644 index 00000000..148c0c27 --- /dev/null +++ b/crates/providers/src/l2_chain_provider.rs @@ -0,0 +1,30 @@ +//! L2 Chain Provider + +use alloc::{boxed::Box, string::ToString, sync::Arc}; +use async_trait::async_trait; +use core::fmt::Display; +use op_alloy_consensus::OpBlock; +use op_alloy_genesis::{RollupConfig, SystemConfig}; +use op_alloy_protocol::L2BlockInfo; + +/// Describes the functionality of a data source that fetches safe blocks. +#[async_trait] +pub trait L2ChainProvider { + /// The error type for the [L2ChainProvider]. + type Error: Display + ToString; + + /// Returns the L2 block info given a block number. + /// Errors if the block does not exist. + async fn l2_block_info_by_number(&mut self, number: u64) -> Result; + + /// Returns the block for a given number. + /// Errors if no block is available for the given block number. + async fn block_by_number(&mut self, number: u64) -> Result; + + /// Returns the [SystemConfig] by L2 number. + async fn system_config_by_number( + &mut self, + number: u64, + rollup_config: Arc, + ) -> Result; +} diff --git a/crates/providers/src/lib.rs b/crates/providers/src/lib.rs new file mode 100644 index 00000000..b0dec93e --- /dev/null +++ b/crates/providers/src/lib.rs @@ -0,0 +1,20 @@ +#![doc = include_str!("../README.md")] +#![cfg_attr(docsrs, feature(doc_cfg, doc_auto_cfg))] +#![cfg_attr(not(test), warn(unused_crate_dependencies))] +#![no_std] + +extern crate alloc; + +/// Re-export commonly used types and traits. +pub mod prelude { + pub use super::*; +} + +mod utils; +pub use utils::{to_system_config, OpBlockConversionError}; + +mod l1_chain_provider; +pub use l1_chain_provider::ChainProvider; + +mod l2_chain_provider; +pub use l2_chain_provider::L2ChainProvider; diff --git a/crates/providers/src/utils.rs b/crates/providers/src/utils.rs new file mode 100644 index 00000000..a310b19f --- /dev/null +++ b/crates/providers/src/utils.rs @@ -0,0 +1,91 @@ +//! Conversion utilities. + +use alloy_primitives::B256; +use op_alloy_consensus::{OpBlock, OpTxEnvelope}; +use op_alloy_genesis::{RollupConfig, SystemConfig}; +use op_alloy_protocol::{ + block_info::DecodeError, L1BlockInfoBedrock, L1BlockInfoEcotone, L1BlockInfoHolocene, + L1BlockInfoTx, +}; +use thiserror::Error; + +/// An error encountered during [OpBlock] conversion. +#[derive(Error, Debug)] +pub enum OpBlockConversionError { + /// Invalid genesis hash. + #[error("Invalid genesis hash. Expected {0}, got {1}")] + InvalidGenesisHash(B256, B256), + /// Invalid transaction type. + #[error("First payload transaction has unexpected type: {0}")] + InvalidTxType(u8), + /// L1 Info error + #[error(transparent)] + L1InfoError(#[from] DecodeError), + /// Missing system config in genesis block. + #[error("Missing system config in genesis block")] + MissingSystemConfigGenesis, + /// Empty transactions. + #[error("Empty transactions in payload. Block hash: {0}")] + EmptyTransactions(B256), +} + +/// Converts the [OpBlock] to a partial [SystemConfig]. +pub fn to_system_config( + block: &OpBlock, + rollup_config: &RollupConfig, +) -> Result { + if block.header.number == rollup_config.genesis.l2.number { + if block.header.hash_slow() != rollup_config.genesis.l2.hash { + return Err(OpBlockConversionError::InvalidGenesisHash( + rollup_config.genesis.l2.hash, + block.header.hash_slow(), + )); + } + return rollup_config + .genesis + .system_config + .ok_or(OpBlockConversionError::MissingSystemConfigGenesis); + } + + if block.body.transactions.is_empty() { + return Err(OpBlockConversionError::EmptyTransactions(block.header.hash_slow())); + } + let OpTxEnvelope::Deposit(ref tx) = block.body.transactions[0] else { + return Err(OpBlockConversionError::InvalidTxType( + block.body.transactions[0].tx_type() as u8 + )); + }; + + let l1_info = L1BlockInfoTx::decode_calldata(tx.input.as_ref())?; + let l1_fee_scalar = match l1_info { + L1BlockInfoTx::Bedrock(L1BlockInfoBedrock { l1_fee_scalar, .. }) => l1_fee_scalar, + L1BlockInfoTx::Ecotone(L1BlockInfoEcotone { + base_fee_scalar, + blob_base_fee_scalar, + .. + }) | + L1BlockInfoTx::Holocene(L1BlockInfoHolocene { + base_fee_scalar, + blob_base_fee_scalar, + .. + }) => { + // Translate Ecotone values back into encoded scalar if needed. + // We do not know if it was derived from a v0 or v1 scalar, + // but v1 is fine, a 0 blob base fee has the same effect. + let mut buf = B256::ZERO; + buf[0] = 0x01; + buf[24..28].copy_from_slice(blob_base_fee_scalar.to_be_bytes().as_ref()); + buf[28..32].copy_from_slice(base_fee_scalar.to_be_bytes().as_ref()); + buf.into() + } + }; + + Ok(SystemConfig { + batcher_address: l1_info.batcher_address(), + overhead: l1_info.l1_fee_overhead(), + scalar: l1_fee_scalar, + gas_limit: block.header.gas_limit, + base_fee_scalar: None, + blob_base_fee_scalar: None, + }) +} diff --git a/examples/trusted-sync/src/validation.rs b/examples/trusted-sync/src/validation.rs index f26d52f1..dd4d7f34 100644 --- a/examples/trusted-sync/src/validation.rs +++ b/examples/trusted-sync/src/validation.rs @@ -79,7 +79,7 @@ impl OnlineValidator { }, transactions: Some(transactions), no_tx_pool: Some(true), - gas_limit: Some(header.gas_limit as u64), + gas_limit: Some(header.gas_limit), }) }