diff --git a/Cargo.lock b/Cargo.lock index 63a6ddb756e..a7fcc8b9592 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -109,9 +109,9 @@ checksum = "5c6cb57a04249c6480766f7f7cef5467412af1490f8d1e243141daddada3264f" [[package]] name = "alloy-chains" -version = "0.1.21" +version = "0.1.22" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cd47e5f8545bdf53beb545d3c039b4afa16040bdf69c50100581579b08776afd" +checksum = "04e9a1892803b02f53e25bea3e414ddd0501f12d97456c9d5ade4edf88f9516f" dependencies = [ "alloy-rlp", "arbitrary", @@ -348,7 +348,7 @@ checksum = "8037e03c7f462a063f28daec9fda285a9a89da003c552f8637a80b9c8fd96241" dependencies = [ "proc-macro2", "quote", - "syn 2.0.66", + "syn 2.0.67", ] [[package]] @@ -548,7 +548,7 @@ dependencies = [ "proc-macro-error", "proc-macro2", "quote", - "syn 2.0.66", + "syn 2.0.67", ] [[package]] @@ -565,7 +565,7 @@ dependencies = [ "proc-macro-error", "proc-macro2", "quote", - "syn 2.0.66", + "syn 2.0.67", "syn-solidity", "tiny-keccak", ] @@ -583,7 +583,7 @@ dependencies = [ "proc-macro2", "quote", "serde_json", - "syn 2.0.66", + "syn 2.0.67", "syn-solidity", ] @@ -786,7 +786,7 @@ dependencies = [ "proc-macro-error", "proc-macro2", "quote", - "syn 2.0.66", + "syn 2.0.67", ] [[package]] @@ -1006,7 +1006,7 @@ checksum = "16e62a023e7c117e27523144c5d2459f4397fcc3cab0085af8e2224f643a0193" dependencies = [ "proc-macro2", "quote", - "syn 2.0.66", + "syn 2.0.67", ] [[package]] @@ -1017,7 +1017,7 @@ checksum = "c6fa2087f2753a7da8cc1c0dbfcf89579dd57458e36769de5ac750b4671737ca" dependencies = [ "proc-macro2", "quote", - "syn 2.0.66", + "syn 2.0.67", ] [[package]] @@ -1055,7 +1055,7 @@ checksum = "3c87f3f15e7794432337fc718554eaa4dc8f04c9677a950ffe366f20a162ae42" dependencies = [ "proc-macro2", "quote", - "syn 2.0.66", + "syn 2.0.67", ] [[package]] @@ -1176,7 +1176,7 @@ dependencies = [ "regex", "rustc-hash 1.1.0", "shlex", - "syn 2.0.66", + "syn 2.0.67", "which", ] @@ -1219,9 +1219,9 @@ dependencies = [ [[package]] name = "bitm" -version = "0.4.1" +version = "0.4.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "31b9ea263f0faf826a1c9de0e8bf8f32f5986c05f5e3abcf6bcde74616009586" +checksum = "b06e8e5bec3490b9f6f3adbb78aa4f53e8396fd9994e8a62a346b44ea7c15f35" dependencies = [ "dyn_size_of", ] @@ -1373,7 +1373,7 @@ checksum = "6be9c93793b60dac381af475b98634d4b451e28336e72218cad9a20176218dbc" dependencies = [ "proc-macro2", "quote", - "syn 2.0.66", + "syn 2.0.67", "synstructure", ] @@ -1482,7 +1482,7 @@ checksum = "1ee891b04274a59bd38b412188e24b849617b2e45a0fd8d057deb63e7403761b" dependencies = [ "proc-macro2", "quote", - "syn 2.0.66", + "syn 2.0.67", ] [[package]] @@ -1702,7 +1702,7 @@ dependencies = [ "heck 0.5.0", "proc-macro2", "quote", - "syn 2.0.66", + "syn 2.0.67", ] [[package]] @@ -2173,7 +2173,7 @@ checksum = "f46882e17999c6cc590af592290432be3bce0428cb0d5f8b6715e4dc7b383eb3" dependencies = [ "proc-macro2", "quote", - "syn 2.0.66", + "syn 2.0.67", ] [[package]] @@ -2197,7 +2197,7 @@ dependencies = [ "proc-macro2", "quote", "strsim", - "syn 2.0.66", + "syn 2.0.67", ] [[package]] @@ -2208,7 +2208,7 @@ checksum = "733cabb43482b1a1b53eee8583c2b9e8684d592215ea83efd305dd31bc2f0178" dependencies = [ "darling_core", "quote", - "syn 2.0.66", + "syn 2.0.67", ] [[package]] @@ -2314,7 +2314,7 @@ checksum = "67e77553c4162a157adbf834ebae5b415acbecbeafc7a74b0e886657506a7611" dependencies = [ "proc-macro2", "quote", - "syn 2.0.66", + "syn 2.0.67", ] [[package]] @@ -2327,7 +2327,7 @@ dependencies = [ "proc-macro2", "quote", "rustc_version 0.4.0", - "syn 2.0.66", + "syn 2.0.67", ] [[package]] @@ -2435,13 +2435,13 @@ dependencies = [ [[package]] name = "displaydoc" -version = "0.2.4" +version = "0.2.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "487585f4d0c6655fe74905e2504d8ad6908e4db67f744eb140876906c2f3175d" +checksum = "97369cbbc041bc366949bc74d34658d6cda5621039731c6310521892a3a20ae0" dependencies = [ "proc-macro2", "quote", - "syn 2.0.66", + "syn 2.0.67", ] [[package]] @@ -2598,7 +2598,7 @@ dependencies = [ "heck 0.4.1", "proc-macro2", "quote", - "syn 2.0.66", + "syn 2.0.67", ] [[package]] @@ -2609,7 +2609,7 @@ checksum = "6fd000fd6988e73bbe993ea3db9b1aa64906ab88766d654973924340c8cddb42" dependencies = [ "proc-macro2", "quote", - "syn 2.0.66", + "syn 2.0.67", ] [[package]] @@ -3145,6 +3145,21 @@ version = "1.0.7" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3f9eec918d3f24069decb9af1554cad7c880e2da24a9afd88aca000531ab82c1" +[[package]] +name = "foreign-types" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f6f339eb8adc052cd2ca78910fda869aefa38d22d5cb648e6485e4d3fc06f3b1" +dependencies = [ + "foreign-types-shared", +] + +[[package]] +name = "foreign-types-shared" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "00b0228411908ca8685dba7fc2cdd70ec9990a6e753e89b6ac91a84c40fbaf4b" + [[package]] name = "form_urlencoded" version = "1.2.1" @@ -3254,7 +3269,7 @@ checksum = "87750cf4b7a4c0625b1529e4c543c2182106e4dedc60a2a6455e00d212c489ac" dependencies = [ "proc-macro2", "quote", - "syn 2.0.66", + "syn 2.0.67", ] [[package]] @@ -3741,6 +3756,22 @@ dependencies = [ "webpki-roots", ] +[[package]] +name = "hyper-tls" +version = "0.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "70206fc6890eaca9fde8a0bf71caa2ddfc9fe045ac9e5c70df101a7dbde866e0" +dependencies = [ + "bytes", + "http-body-util", + "hyper", + "hyper-util", + "native-tls", + "tokio", + "tokio-native-tls", + "tower-service", +] + [[package]] name = "hyper-util" version = "0.1.5" @@ -3784,7 +3815,7 @@ dependencies = [ "proc-macro-error", "proc-macro2", "quote", - "syn 2.0.66", + "syn 2.0.67", ] [[package]] @@ -3934,7 +3965,7 @@ checksum = "d2abdd3a62551e8337af119c5899e600ca0c88ec8f23a46c60ba216c803dcf1a" dependencies = [ "proc-macro2", "quote", - "syn 2.0.66", + "syn 2.0.67", ] [[package]] @@ -4338,7 +4369,7 @@ dependencies = [ "proc-macro-crate", "proc-macro2", "quote", - "syn 2.0.66", + "syn 2.0.67", ] [[package]] @@ -4454,13 +4485,103 @@ dependencies = [ "sha3-asm", ] +[[package]] +name = "kona-derive" +version = "0.0.1" +source = "git+https://github.com/ethereum-optimism/kona?branch=main#0f5d9ab3f41fd6d1f29ae4ed5a4198fc4098b7bd" +dependencies = [ + "alloc-no-stdlib", + "alloy-consensus", + "alloy-eips", + "alloy-primitives", + "alloy-provider", + "alloy-rlp", + "alloy-rpc-client", + "alloy-rpc-types", + "alloy-sol-types", + "alloy-transport", + "alloy-transport-http", + "anyhow", + "async-trait", + "brotli", + "c-kzg", + "hashbrown 0.14.5", + "kona-primitives", + "lru", + "miniz_oxide", + "op-alloy-consensus", + "reqwest", + "revm 9.0.0", + "serde", + "serde_json", + "sha2 0.10.8", + "spin", + "tracing", + "unsigned-varint 0.8.0", +] + +[[package]] +name = "kona-exex" +version = "0.1.0" +dependencies = [ + "alloy-consensus", + "alloy-eips", + "alloy-provider", + "alloy-rlp", + "alloy-rpc-client", + "alloy-rpc-types", + "alloy-transport", + "alloy-transport-http", + "anyhow", + "async-trait", + "eyre", + "kona-derive", + "reqwest", + "reth", + "reth-basic-payload-builder", + "reth-evm", + "reth-execution-errors", + "reth-exex", + "reth-node-api", + "reth-node-ethereum", + "reth-payload-builder", + "reth-primitives", + "reth-provider", + "reth-revm", + "reth-rpc-types", + "reth-testing-utils", + "reth-tracing", + "reth-transaction-pool", + "secp256k1", + "serde_json", + "tokio", + "tracing", + "url", +] + +[[package]] +name = "kona-primitives" +version = "0.0.1" +source = "git+https://github.com/ethereum-optimism/kona?branch=main#0f5d9ab3f41fd6d1f29ae4ed5a4198fc4098b7bd" +dependencies = [ + "alloy-consensus", + "alloy-eips", + "alloy-primitives", + "alloy-rlp", + "alloy-sol-types", + "anyhow", + "op-alloy-consensus", + "serde", + "superchain-primitives", +] + [[package]] name = "lazy_static" -version = "1.4.0" +version = "1.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646" +checksum = "bbd2bcb4c963f2ddae06a2efc7e9f3591312473c50c6685e1f298068316e66fe" dependencies = [ - "spin 0.5.2", + "spin", ] [[package]] @@ -4948,7 +5069,7 @@ dependencies = [ "cfg-if", "proc-macro2", "quote", - "syn 2.0.66", + "syn 2.0.67", ] [[package]] @@ -5032,6 +5153,23 @@ dependencies = [ "unsigned-varint 0.7.2", ] +[[package]] +name = "native-tls" +version = "0.2.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a8614eb2c83d59d1c8cc974dd3f920198647674a0a035e1af1fa58707e317466" +dependencies = [ + "libc", + "log", + "openssl", + "openssl-probe", + "openssl-sys", + "schannel", + "security-framework", + "security-framework-sys", + "tempfile", +] + [[package]] name = "nibble_vec" version = "0.1.0" @@ -5200,7 +5338,7 @@ dependencies = [ "proc-macro-crate", "proc-macro2", "quote", - "syn 2.0.66", + "syn 2.0.67", ] [[package]] @@ -5247,18 +5385,69 @@ version = "11.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0ab1bc2a289d34bd04a330323ac98a1b4bc82c9d9fcb1e66b63caa84da26b575" +[[package]] +name = "op-alloy-consensus" +version = "0.1.0" +source = "git+https://github.com/alloy-rs/op-alloy#97cca5624dc3db8631ff7866e091876fd2fedd25" +dependencies = [ + "alloy-consensus", + "alloy-eips", + "alloy-primitives", + "alloy-rlp", + "alloy-serde", + "serde", +] + [[package]] name = "opaque-debug" version = "0.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c08d65885ee38876c4f86fa503fb49d7b507c2b62552df7c70b2fce627e06381" +[[package]] +name = "openssl" +version = "0.10.64" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "95a0481286a310808298130d22dd1fef0fa571e05a8f44ec801801e84b216b1f" +dependencies = [ + "bitflags 2.5.0", + "cfg-if", + "foreign-types", + "libc", + "once_cell", + "openssl-macros", + "openssl-sys", +] + +[[package]] +name = "openssl-macros" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a948666b637a0f465e8564c73e89d4dde00d72d4d473cc972f390fc3dcee7d9c" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.67", +] + [[package]] name = "openssl-probe" version = "0.1.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ff011a302c396a5197692431fc1948019154afc178baf7d8e37367442a4601cf" +[[package]] +name = "openssl-sys" +version = "0.9.102" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c597637d56fbc83893a35eb0dd04b2b8e7a50c91e64e9493e398b5df4fb45fa2" +dependencies = [ + "cc", + "libc", + "pkg-config", + "vcpkg", +] + [[package]] name = "option-ext" version = "0.2.0" @@ -5479,7 +5668,7 @@ dependencies = [ "phf_shared", "proc-macro2", "quote", - "syn 2.0.66", + "syn 2.0.67", ] [[package]] @@ -5508,7 +5697,7 @@ checksum = "2f38a4412a78282e09a2cf38d195ea5420d15ba0602cb375210efbc877243965" dependencies = [ "proc-macro2", "quote", - "syn 2.0.66", + "syn 2.0.67", ] [[package]] @@ -5667,7 +5856,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5f12335488a2f3b0a83b14edad48dca9879ce89b2edd10e80237e4e852dd645e" dependencies = [ "proc-macro2", - "syn 2.0.66", + "syn 2.0.67", ] [[package]] @@ -5727,9 +5916,9 @@ dependencies = [ [[package]] name = "proc-macro2" -version = "1.0.85" +version = "1.0.86" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "22244ce15aa966053a896d1accb3a6e68469b97c7f33f284b99f0d576879fc23" +checksum = "5e719e8df665df0d1c8fbfd238015744736151d4445ec0836b8e628aae103b77" dependencies = [ "unicode-ident", ] @@ -6145,11 +6334,13 @@ dependencies = [ "http-body-util", "hyper", "hyper-rustls", + "hyper-tls", "hyper-util", "ipnet", "js-sys", "log", "mime", + "native-tls", "once_cell", "percent-encoding", "pin-project-lite", @@ -6163,6 +6354,7 @@ dependencies = [ "serde_urlencoded", "sync_wrapper", "tokio", + "tokio-native-tls", "tokio-rustls", "tokio-util", "tower-service", @@ -6318,7 +6510,7 @@ dependencies = [ "reth-revm", "reth-tasks", "reth-transaction-pool", - "revm", + "revm 10.0.0", "tokio", "tracing", ] @@ -6519,7 +6711,7 @@ dependencies = [ "proc-macro2", "quote", "similar-asserts", - "syn 2.0.66", + "syn 2.0.67", ] [[package]] @@ -6945,7 +7137,7 @@ dependencies = [ "reth-primitives", "reth-rpc-types", "reth-rpc-types-compat", - "revm-primitives", + "revm-primitives 5.0.0", "serde", "serde_json", "sha2 0.10.8", @@ -6980,7 +7172,7 @@ dependencies = [ "reth-provider", "reth-revm", "reth-transaction-pool", - "revm", + "revm 10.0.0", "tracing", ] @@ -7007,8 +7199,8 @@ dependencies = [ "reth-primitives", "reth-prune-types", "reth-storage-errors", - "revm", - "revm-primitives", + "revm 10.0.0", + "revm-primitives 5.0.0", ] [[package]] @@ -7025,7 +7217,7 @@ dependencies = [ "reth-prune-types", "reth-revm", "reth-testing-utils", - "revm-primitives", + "revm-primitives 5.0.0", "secp256k1", "serde_json", ] @@ -7043,8 +7235,8 @@ dependencies = [ "reth-primitives", "reth-prune-types", "reth-revm", - "revm", - "revm-primitives", + "revm 10.0.0", + "revm-primitives 5.0.0", "thiserror", "tracing", ] @@ -7058,7 +7250,7 @@ dependencies = [ "reth-consensus", "reth-prune-types", "reth-storage-errors", - "revm-primitives", + "revm-primitives 5.0.0", "thiserror-no-std", ] @@ -7072,7 +7264,7 @@ dependencies = [ "reth-execution-errors", "reth-primitives", "reth-trie", - "revm", + "revm 10.0.0", "serde", ] @@ -7214,7 +7406,7 @@ dependencies = [ "quote", "regex", "serial_test", - "syn 2.0.66", + "syn 2.0.67", "trybuild", ] @@ -7582,7 +7774,7 @@ dependencies = [ "reth-rpc-types-compat", "reth-tracing", "reth-transaction-pool", - "revm-primitives", + "revm-primitives 5.0.0", "serde", "serde_json", "thiserror", @@ -7619,7 +7811,7 @@ dependencies = [ "reth-rpc-types", "reth-rpc-types-compat", "reth-transaction-pool", - "revm", + "revm 10.0.0", "sha2 0.10.8", "thiserror", "tracing", @@ -7643,7 +7835,7 @@ dependencies = [ "reth-provider", "reth-rpc-types", "reth-transaction-pool", - "revm", + "revm 10.0.0", "serde_json", "thiserror", "tokio", @@ -7706,7 +7898,7 @@ dependencies = [ "reth-primitives-traits", "reth-static-file-types", "reth-trie-common", - "revm-primitives", + "revm-primitives 5.0.0", "secp256k1", "serde", "serde_json", @@ -7739,7 +7931,7 @@ dependencies = [ "proptest-derive", "rand 0.8.5", "reth-codecs", - "revm-primitives", + "revm-primitives 5.0.0", "roaring", "serde", "serde_json", @@ -7781,7 +7973,7 @@ dependencies = [ "reth-storage-errors", "reth-testing-utils", "reth-trie", - "revm", + "revm 10.0.0", "strum", "tempfile", "tokio", @@ -7852,7 +8044,7 @@ dependencies = [ "reth-storage-api", "reth-storage-errors", "reth-trie", - "revm", + "revm 10.0.0", "tracing", ] @@ -7900,9 +8092,9 @@ dependencies = [ "reth-tasks", "reth-testing-utils", "reth-transaction-pool", - "revm", + "revm 10.0.0", "revm-inspectors", - "revm-primitives", + "revm-primitives 5.0.0", "schnellru", "secp256k1", "serde", @@ -8219,7 +8411,7 @@ dependencies = [ "reth-stages-types", "reth-storage-errors", "reth-trie", - "revm", + "revm 10.0.0", ] [[package]] @@ -8307,7 +8499,7 @@ dependencies = [ "reth-provider", "reth-tasks", "reth-tracing", - "revm", + "revm 10.0.0", "rustc-hash 2.0.0", "schnellru", "serde", @@ -8343,7 +8535,7 @@ dependencies = [ "reth-stages-types", "reth-storage-errors", "reth-trie-common", - "revm", + "revm 10.0.0", "serde", "serde_json", "similar-asserts", @@ -8375,7 +8567,7 @@ dependencies = [ "proptest-derive", "reth-codecs", "reth-primitives-traits", - "revm-primitives", + "revm-primitives 5.0.0", "serde", "serde_json", "test-fuzz", @@ -8408,6 +8600,19 @@ dependencies = [ "tracing", ] +[[package]] +name = "revm" +version = "9.0.0" +source = "git+https://github.com/bluealloy/revm?rev=a832a4e#a832a4e9f17ce6876d98d5f53b7efbb18d27fb23" +dependencies = [ + "auto_impl", + "cfg-if", + "dyn-clone", + "revm-interpreter 5.0.0", + "revm-precompile 7.0.0", + "serde", +] + [[package]] name = "revm" version = "10.0.0" @@ -8417,17 +8622,17 @@ dependencies = [ "auto_impl", "cfg-if", "dyn-clone", - "revm-interpreter", - "revm-precompile", + "revm-interpreter 6.0.0", + "revm-precompile 8.0.0", "serde", "serde_json", ] [[package]] name = "revm-inspectors" -version = "0.1.0" +version = "0.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "eba2e187811b160463663fd71881b4e5d653720ba00be0f1e85962d4db60341c" +checksum = "1b0971cad2f8f1ecb10e270d80646e63bf19daef0dc0a17a45680d24bb346b7c" dependencies = [ "alloy-primitives", "alloy-rpc-types", @@ -8436,21 +8641,45 @@ dependencies = [ "boa_engine", "boa_gc", "colorchoice", - "revm", + "revm 10.0.0", "serde_json", "thiserror", ] +[[package]] +name = "revm-interpreter" +version = "5.0.0" +source = "git+https://github.com/bluealloy/revm?rev=a832a4e#a832a4e9f17ce6876d98d5f53b7efbb18d27fb23" +dependencies = [ + "revm-primitives 4.0.0", + "serde", +] + [[package]] name = "revm-interpreter" version = "6.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "23dfd24faa3cbbd96e0976103d1e174d6559b8036730f70415488ee21870d578" dependencies = [ - "revm-primitives", + "revm-primitives 5.0.0", "serde", ] +[[package]] +name = "revm-precompile" +version = "7.0.0" +source = "git+https://github.com/bluealloy/revm?rev=a832a4e#a832a4e9f17ce6876d98d5f53b7efbb18d27fb23" +dependencies = [ + "aurora-engine-modexp", + "c-kzg", + "k256", + "once_cell", + "revm-primitives 4.0.0", + "ripemd", + "sha2 0.10.8", + "substrate-bn", +] + [[package]] name = "revm-precompile" version = "8.0.0" @@ -8463,13 +8692,33 @@ dependencies = [ "k256", "once_cell", "p256", - "revm-primitives", + "revm-primitives 5.0.0", "ripemd", "secp256k1", "sha2 0.10.8", "substrate-bn", ] +[[package]] +name = "revm-primitives" +version = "4.0.0" +source = "git+https://github.com/bluealloy/revm?rev=a832a4e#a832a4e9f17ce6876d98d5f53b7efbb18d27fb23" +dependencies = [ + "alloy-primitives", + "auto_impl", + "bitflags 2.5.0", + "bitvec", + "c-kzg", + "cfg-if", + "derive_more", + "dyn-clone", + "enumn", + "hashbrown 0.14.5", + "hex", + "once_cell", + "serde", +] + [[package]] name = "revm-primitives" version = "5.0.0" @@ -8520,7 +8769,7 @@ dependencies = [ "cfg-if", "getrandom 0.2.15", "libc", - "spin 0.9.8", + "spin", "untrusted", "windows-sys 0.52.0", ] @@ -8980,7 +9229,7 @@ checksum = "500cbc0ebeb6f46627f50f3f5811ccf6bf00643be300b4c3eabc0ef55dc5b5ba" dependencies = [ "proc-macro2", "quote", - "syn 2.0.66", + "syn 2.0.67", ] [[package]] @@ -9006,6 +9255,17 @@ dependencies = [ "thiserror", ] +[[package]] +name = "serde_repr" +version = "0.1.19" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6c64451ba24fc7a6a2d60fc75dd9c83c90903b19028d4eff35e88fc1e86564e9" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.67", +] + [[package]] name = "serde_spanned" version = "0.6.6" @@ -9054,7 +9314,7 @@ dependencies = [ "darling", "proc-macro2", "quote", - "syn 2.0.66", + "syn 2.0.67", ] [[package]] @@ -9079,7 +9339,7 @@ checksum = "82fe9db325bcef1fbcde82e078a5cc4efdf787e96b3b9cf45b50b529f2083d67" dependencies = [ "proc-macro2", "quote", - "syn 2.0.66", + "syn 2.0.67", ] [[package]] @@ -9306,17 +9566,14 @@ dependencies = [ "sha1", ] -[[package]] -name = "spin" -version = "0.5.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6e63cff320ae2c57904679ba7cb63280a3dc4613885beafb148ee7bf9aa9042d" - [[package]] name = "spin" version = "0.9.8" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6980e8d7511241f8acf4aebddbb1ff938df5eebe98691418c4468d0b72a96a67" +dependencies = [ + "lock_api", +] [[package]] name = "spki" @@ -9341,7 +9598,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2ff9eaf853dec4c8802325d8b6d3dffa86cc707fd7a1a4cdbf416e13b061787a" dependencies = [ "quote", - "syn 2.0.66", + "syn 2.0.67", ] [[package]] @@ -9387,7 +9644,7 @@ dependencies = [ "proc-macro2", "quote", "rustversion", - "syn 2.0.66", + "syn 2.0.67", ] [[package]] @@ -9419,6 +9676,23 @@ dependencies = [ "num-traits", ] +[[package]] +name = "superchain-primitives" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3ce53db1b0ae24593ac759782cceedb03c838a39bb1f2ccd5c0923778acd7871" +dependencies = [ + "alloy-consensus", + "alloy-eips", + "alloy-genesis", + "alloy-primitives", + "alloy-sol-types", + "anyhow", + "hashbrown 0.14.5", + "serde", + "serde_repr", +] + [[package]] name = "symbolic-common" version = "12.9.2" @@ -9455,9 +9729,9 @@ dependencies = [ [[package]] name = "syn" -version = "2.0.66" +version = "2.0.67" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c42f3f41a2de00b01c0aaad383c5a45241efc8b2d1eda5661812fda5f3cdcff5" +checksum = "ff8655ed1d86f3af4ee3fd3263786bc14245ad17c4c7e85ba7187fb3ae028c90" dependencies = [ "proc-macro2", "quote", @@ -9473,7 +9747,7 @@ dependencies = [ "paste", "proc-macro2", "quote", - "syn 2.0.66", + "syn 2.0.67", ] [[package]] @@ -9490,7 +9764,7 @@ checksum = "c8af7666ab7b6390ab78131fb5b0fce11d6b7a6951602017c35fa82800708971" dependencies = [ "proc-macro2", "quote", - "syn 2.0.66", + "syn 2.0.67", ] [[package]] @@ -9575,7 +9849,7 @@ dependencies = [ "prettyplease", "proc-macro2", "quote", - "syn 2.0.66", + "syn 2.0.67", ] [[package]] @@ -9614,7 +9888,7 @@ checksum = "46c3384250002a6d5af4d114f2845d37b57521033f30d5c3f46c4d70e1197533" dependencies = [ "proc-macro2", "quote", - "syn 2.0.66", + "syn 2.0.67", ] [[package]] @@ -9792,7 +10066,17 @@ checksum = "5f5ae998a069d4b5aba8ee9dad856af7d520c3699e6159b185c2acd48155d39a" dependencies = [ "proc-macro2", "quote", - "syn 2.0.66", + "syn 2.0.67", +] + +[[package]] +name = "tokio-native-tls" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bbae76ab933c85776efabc971569dd6119c580d8f5d448769dec1764bf796ef2" +dependencies = [ + "native-tls", + "tokio", ] [[package]] @@ -9990,7 +10274,7 @@ checksum = "34704c8d6ebcbc939824180af020566b01a7c01f80641264eba0999f6c2b6be7" dependencies = [ "proc-macro2", "quote", - "syn 2.0.66", + "syn 2.0.67", ] [[package]] @@ -10435,7 +10719,7 @@ dependencies = [ "once_cell", "proc-macro2", "quote", - "syn 2.0.66", + "syn 2.0.67", "wasm-bindgen-shared", ] @@ -10469,7 +10753,7 @@ checksum = "e94f17b526d0a461a191c78ea52bbce64071ed5c04c9ffe424dcb38f74171bb7" dependencies = [ "proc-macro2", "quote", - "syn 2.0.66", + "syn 2.0.67", "wasm-bindgen-backend", "wasm-bindgen-shared", ] @@ -10610,7 +10894,7 @@ checksum = "9107ddc059d5b6fbfbffdfa7a7fe3e22a226def0b2608f72e9d552763d3e1ad7" dependencies = [ "proc-macro2", "quote", - "syn 2.0.66", + "syn 2.0.67", ] [[package]] @@ -10621,7 +10905,7 @@ checksum = "29bee4b38ea3cde66011baa44dba677c432a78593e202392d1e9070cf2a7fca7" dependencies = [ "proc-macro2", "quote", - "syn 2.0.66", + "syn 2.0.67", ] [[package]] @@ -10879,7 +11163,7 @@ checksum = "28cc31741b18cb6f1d5ff12f5b7523e3d6eb0852bbbad19d73905511d9849b95" dependencies = [ "proc-macro2", "quote", - "syn 2.0.66", + "syn 2.0.67", "synstructure", ] @@ -10900,7 +11184,7 @@ checksum = "15e934569e47891f7d9411f1a451d947a60e000ab3bd24fbb970f000387d1b3b" dependencies = [ "proc-macro2", "quote", - "syn 2.0.66", + "syn 2.0.67", ] [[package]] @@ -10920,7 +11204,7 @@ checksum = "0ea7b4a3637ea8669cedf0f1fd5c286a17f3de97b8dd5a70a6c167a1730e63a5" dependencies = [ "proc-macro2", "quote", - "syn 2.0.66", + "syn 2.0.67", "synstructure", ] @@ -10941,7 +11225,7 @@ checksum = "ce36e65b0d2999d2aafac989fb249189a141aee1f53c612c1f37d72631959f69" dependencies = [ "proc-macro2", "quote", - "syn 2.0.66", + "syn 2.0.67", ] [[package]] @@ -10963,7 +11247,7 @@ checksum = "97cf56601ee5052b4417d90c8755c6683473c926039908196cf35d99f893ebe7" dependencies = [ "proc-macro2", "quote", - "syn 2.0.66", + "syn 2.0.67", ] [[package]] diff --git a/examples/exex/kona/Cargo.toml b/examples/exex/kona/Cargo.toml new file mode 100644 index 00000000000..48b44e37cbd --- /dev/null +++ b/examples/exex/kona/Cargo.toml @@ -0,0 +1,50 @@ +[package] +name = "kona-exex" +version = "0.1.0" +publish = false +edition.workspace = true +license.workspace = true + +[dependencies] +# reth +reth.workspace = true +reth-exex.workspace = true +reth-node-api.workspace = true +reth-primitives.workspace = true +reth-execution-errors.workspace = true +reth-provider.workspace = true +reth-revm.workspace = true +reth-tracing.workspace = true +reth-transaction-pool.workspace = true +reth-basic-payload-builder.workspace = true +reth-evm.workspace = true +reth-payload-builder.workspace = true +reth-rpc-types.workspace = true +reth-node-ethereum.workspace = true + +# alloy +alloy-rlp.workspace = true +alloy-eips.workspace = true +alloy-provider.workspace = true +alloy-rpc-client.workspace = true +alloy-rpc-types.workspace = true +alloy-transport-http.workspace = true +alloy-transport = { workspace = true, default-features = false } +alloy-consensus = { workspace = true, default-features = false, features = ["kzg"] } + +# other +tracing.workspace = true +async-trait.workspace = true +url.workspace = true +reqwest.workspace = true +eyre.workspace = true +tokio.workspace = true +serde_json.workspace = true + +# kona +anyhow = { version = "1.0.86", default-features = false } +kona-derive = { git = "https://github.com/ethereum-optimism/kona", branch = "main", features = ["online", "serde", "k256"] } + +[dev-dependencies] +reth-testing-utils.workspace = true +secp256k1.workspace = true diff --git a/examples/exex/kona/src/blobs.rs b/examples/exex/kona/src/blobs.rs new file mode 100644 index 00000000000..a3a7bd88a7e --- /dev/null +++ b/examples/exex/kona/src/blobs.rs @@ -0,0 +1,90 @@ +//! Blob Provider + +use anyhow::Result; +use async_trait::async_trait; +use kona_derive::{ + online::{OnlineBeaconClient, OnlineBlobProvider, SimpleSlotDerivation}, + traits::BlobProvider, + types::{alloy_primitives::B256, Blob, BlobProviderError, BlockInfo, IndexedBlobHash}, +}; +use std::{ + boxed::Box, + collections::HashMap, + sync::{Arc, Mutex}, +}; + +/// Fallback online blob provider. +pub type OnlineBlobFallback = OnlineBlobProvider; + +/// A blob provider that hold blobs in memory. +#[derive(Debug, Clone)] +pub struct InMemoryBlobProvider { + /// Maps block hashes to blobs. + blocks_to_blob: HashMap>, +} + +impl InMemoryBlobProvider { + /// Creates a new [InMemoryBlobProvider]. + pub fn new() -> Self { + Self { blocks_to_blob: HashMap::new() } + } + + /// Inserts multiple blobs into the provider. + pub fn insert_blobs(&mut self, block_hash: B256, blobs: Vec) { + self.blocks_to_blob.entry(block_hash).or_default().extend(blobs); + } +} + +/// [BlobProvider] for the [kona_derive::DerivationPipeline]. +#[derive(Debug, Clone)] +pub struct ExExBlobProvider( + Arc>, + /// Fallback online blob provider. + /// This is used primarily during sync when archived blobs + /// aren't provided by reth since they'll be too old. + OnlineBlobFallback, +); + +impl ExExBlobProvider { + /// Creates a new [ExExBlobProvider]. + pub fn new(inner: Arc>, fallback: OnlineBlobFallback) -> Self { + Self(inner, fallback) + } + + /// Attempts to fetch blobs using the inner blob store. + async fn inner_blob_load( + &mut self, + block_ref: &BlockInfo, + hashes: &[IndexedBlobHash], + ) -> anyhow::Result> { + let err = |block_ref: &BlockInfo| { + anyhow::anyhow!("Blob not found for block ref: {:?}", block_ref) + }; + let locked = self.0.lock().map_err(|_| anyhow::anyhow!("Failed to lock inner provider"))?; + let blobs_for_block = + locked.blocks_to_blob.get(&block_ref.hash).ok_or_else(|| err(block_ref))?; + let mut blobs = Vec::new(); + for _blob_hash in hashes { + for blob in blobs_for_block { + blobs.push(*blob); + } + } + Ok(blobs) + } +} + +#[async_trait] +impl BlobProvider for ExExBlobProvider { + /// Fetches blobs for a given block ref and the blob hashes. + async fn get_blobs( + &mut self, + block_ref: &BlockInfo, + blob_hashes: &[IndexedBlobHash], + ) -> Result, BlobProviderError> { + if let Ok(b) = self.inner_blob_load(block_ref, blob_hashes).await { + return Ok(b); + } + tracing::warn!(target: "blob-provider", "Blob provider falling back to online provider"); + self.1.get_blobs(block_ref, blob_hashes).await + } +} diff --git a/examples/exex/kona/src/main.rs b/examples/exex/kona/src/main.rs new file mode 100644 index 00000000000..3e4c23f62e9 --- /dev/null +++ b/examples/exex/kona/src/main.rs @@ -0,0 +1,244 @@ +//! Run with +//! +//! ```not_rust +//! cargo run -p kona-exex node \ +//! --datadir ./db/ \ +//! --chain sepolia \ +//! --metrics 0.0.0.0:9425 \ +//! --http \ +//! --http.port 8333 \ +//! --http.addr 0.0.0.0 \ +//! --http.api debug,eth,net,trace,txpool,rpc,web3,admin \ +//! --authrpc.jwtsecret \ +//! --authrpc.addr 0.0.0.0 \ +//! --authrpc.port 8554 \ +//! -vvv +//! ``` +//! +//! This launches a regular reth node instance for the specified `--chain`. +//! +//! The Execution Extension runs ontop of the node, receiving chain state updates from +//! the reth node. It derives L2 Payload Attributes and validates them against a trusted +//! L2 RPC endpoint. +//! +//! See the [kona-derive][kd] package for details into payload derivation. +//! +//! [kd]: https://github.com/ethereum-optimism/kona/tree/main/crates/derive + +use kona_derive::{ + online::*, + stages::{ + AttributesQueue, BatchQueue, ChannelBank, ChannelReader, FrameQueue, L1Retrieval, + L1Traversal, + }, + types::{BlockInfo, L2BlockInfo, OP_MAINNET_CONFIG}, +}; +use reth::transaction_pool::TransactionPool; +use reth_exex::{ExExContext, ExExEvent}; +use reth_node_api::FullNodeComponents; +use reth_tracing::tracing::{debug, error, info, warn}; +use std::{ + collections::HashMap, + sync::{Arc, Mutex}, +}; + +mod blobs; +mod providers; +mod validation; + +// L2 RPC is used to validate derived payloads. +const L2_RPC_URL: &str = "L2_RPC_URL"; +// Beacon URL is used as a fallback for fetching archived +// blobs that reth won't provide during sync. +const BEACON_URL: &str = "BEACON_URL"; + +fn main() -> eyre::Result<()> { + reth::cli::Cli::parse_args().run(|builder, _| async move { + let handle = builder + .node(reth_node_ethereum::EthereumNode::default()) + .install_exex("kona", move |ctx| async { Ok(follow_safe_head(ctx)) }) + .launch() + .await?; + handle.wait_for_node_exit().await + }) +} + +fn new_req_url(var: &str) -> reqwest::Url { + std::env::var(var).unwrap_or_else(|_| panic!("{var} must be set")).parse().unwrap() +} + +fn info_from_header(block: &reth::primitives::SealedBlock) -> BlockInfo { + BlockInfo { + hash: block.hash(), + number: block.number, + timestamp: block.timestamp, + parent_hash: block.parent_hash, + } +} + +type LocalPipeline = + DerivationPipeline, AlloyL2ChainProvider>; + +type LocalDataProvider = EthereumDataSource; + +type LocalAttributesBuilder = + StatefulAttributesBuilder; + +type LocalAttributesQueue = AttributesQueue< + BatchQueue< + ChannelReader< + ChannelBank>>>, + >, + AlloyL2ChainProvider, + >, + LocalAttributesBuilder, +>; + +pub async fn follow_safe_head(mut ctx: ExExContext) -> eyre::Result<()> { + let cfg = Arc::new(OP_MAINNET_CONFIG); + let mut chain_provider = providers::LocalChainProvider::new(); + chain_provider.insert_block_info(BlockInfo { + hash: cfg.genesis.l1.hash, + number: cfg.genesis.l1.number, + timestamp: Default::default(), + parent_hash: Default::default(), + }); + let mut l2_provider = AlloyL2ChainProvider::new_http(new_req_url(L2_RPC_URL), cfg.clone()); + let attributes = + StatefulAttributesBuilder::new(cfg.clone(), l2_provider.clone(), chain_provider.clone()); + let beacon_client = OnlineBeaconClient::new_http(BEACON_URL.to_string()); + let blob_provider = + OnlineBlobProvider::<_, SimpleSlotDerivation>::new(beacon_client, None, None); + let blob_store = Arc::new(Mutex::new(blobs::InMemoryBlobProvider::new())); + let blob_provider = blobs::ExExBlobProvider::new(Arc::clone(&blob_store), blob_provider); + let dap = EthereumDataSource::new(chain_provider.clone(), blob_provider, &cfg); + let mut cursor = l2_provider + .l2_block_info_by_number(cfg.genesis.l2.number) + .await + .expect("Failed to fetch genesis L2 block info for pipeline cursor"); + let tip = chain_provider + .block_info_by_number(cursor.l1_origin.number) + .await + .expect("Failed to fetch genesis L1 block info for pipeline tip"); + let validator = validation::OnlineValidator::new_http( + new_req_url(L2_RPC_URL), + cfg.canyon_time.unwrap_or_default(), + ); + let mut pipeline: LocalPipeline = PipelineBuilder::new() + .rollup_config(cfg.clone()) + .dap_source(dap) + .l2_chain_provider(l2_provider.clone()) + .chain_provider(chain_provider.clone()) + .builder(attributes) + .origin(tip) + .build(); + let mut derived_attributes_count = 0; + let mut cursor_map: HashMap = HashMap::new(); + + // Continuously step on the pipeline and validate payloads. + let mut synced_to_l2_genesis = false; + let mut curr_tip = 0; + let mut now = std::time::SystemTime::now(); + loop { + if synced_to_l2_genesis { + info!(target: "loop", "Validated payload attributes number {}", derived_attributes_count); + info!(target: "loop", "Pending l2 safe head num: {}", cursor.block_info.number); + match pipeline.step(cursor).await { + Ok(_) => info!(target: "loop", "Stepped derivation pipeline"), + Err(e) => warn!(target: "loop", "Error stepping derivation pipeline: {:?}", e), + } + + if let Some(attributes) = pipeline.next_attributes() { + if !validator.validate(&attributes).await { + error!(target: "loop", "Failed payload validation: {}", attributes.parent.block_info.hash); + return Ok(()); + } + derived_attributes_count += 1; + match l2_provider.l2_block_info_by_number(cursor.block_info.number + 1).await { + Ok(bi) => { + let tip = chain_provider + .block_info_by_number(bi.l1_origin.number) + .await + .expect("Failed to fetch genesis L1 block info for pipeline tip"); + cursor_map.insert(tip, bi); + cursor = bi; + } + Err(e) => { + error!(target: "loop", "Failed to fetch next pending l2 safe head: {}, err: {:?}", cursor.block_info.number + 1, e); + } + } + println!( + "Validated Payload Attributes {derived_attributes_count} [L2 Block Num: {}] [L2 Timestamp: {}] [L1 Origin Block Num: {}]", + attributes.parent.block_info.number + 1, + attributes.attributes.timestamp, + pipeline.origin().unwrap().number, + ); + info!(target: "loop", "attributes: {:#?}", attributes); + } else { + debug!(target: "loop", "No attributes to validate"); + } + } else if let Ok(s) = now.elapsed().map(|s| s.as_secs()) { + if s > 60 { + now = std::time::SystemTime::now(); + let dist = if curr_tip <= cfg.genesis.l1.number { + cfg.genesis.l1.number - curr_tip + } else { + 0 + }; + info!(target: "loop", "Not synced to l2 genesis. Distance to genesis: {}", dist); + } + } + + if let Ok(notification) = ctx.notifications.try_recv() { + if let Some(reverted_chain) = notification.reverted_chain() { + chain_provider.commit(reverted_chain.clone()); + let block_info = info_from_header(&reverted_chain.tip().block); + let blocks = reverted_chain + .blocks_iter() + .collect::>(); + for block in blocks { + let tx_hashes = block + .transactions() + .map(|tx| tx.hash) + .collect::>(); + let blobs = ctx.pool().get_all_blobs(tx_hashes)?; + let blobs = blobs + .into_iter() + .map(|b| b.1) + .collect::>(); + let mut locked_blob_provider = blob_store + .lock() + .map_err(|_| eyre::eyre!("Failed to lock blob provider"))?; + let blobs = blobs.into_iter().flat_map(|b| b.blobs).collect(); + locked_blob_provider.insert_blobs(block.hash(), blobs); + } + cursor = if let Some(c) = cursor_map.get(&block_info) { + *c + } else { + panic!("Failed to get previous cursor for old chain tip"); + }; + pipeline.reset(block_info).await.map_err(|e| eyre::eyre!(e))?; + } + if let Some(committed_chain) = notification.committed_chain() { + chain_provider.commit(committed_chain.clone()); + let tip_number = committed_chain + .blocks_iter() + .map(|b| b.block.header.header().number) + .max() + .unwrap_or_default(); + curr_tip = tip_number; + if tip_number >= cfg.genesis.l1.number { + tracing::debug!(target: "loop", "Chain synced to rollup genesis with L2 block number: {}", tip_number); + synced_to_l2_genesis = true; + } + ctx.events.send(ExExEvent::FinishedHeight(committed_chain.tip().number))?; + } + } + if ctx.notifications.is_closed() { + warn!(target: "loop", "ExEx notification channel closed, exiting"); + break; + } + } + + Err(eyre::eyre!("Main loop exited unexpectedly")) +} diff --git a/examples/exex/kona/src/providers.rs b/examples/exex/kona/src/providers.rs new file mode 100644 index 00000000000..507b5f2d510 --- /dev/null +++ b/examples/exex/kona/src/providers.rs @@ -0,0 +1,271 @@ +//! Local in-memory providers. + +use anyhow::Result; +use async_trait::async_trait; +use kona_derive::{ + traits::ChainProvider, + types::{ + alloy_primitives::B256, BlockInfo, Header, Receipt, Signed, TxEip1559, TxEip2930, + TxEip4844, TxEip4844Variant, TxEnvelope, TxLegacy, + }, +}; +use reth_primitives::Transaction; +use reth_provider::Chain; +use std::{collections::HashMap, sync::Arc}; + +/// An in-memory [ChainProvider] that stores chain data. +#[derive(Debug, Default, Clone)] +pub struct LocalChainProvider { + /// Maps [B256] hash to [Header]. + hash_to_header: HashMap, + + /// Maps [B256] hash to [BlockInfo]. + hash_to_block_info: HashMap, + + /// Maps [B256] hash to [Vec]<[Receipt]>. + hash_to_receipts: HashMap>, + + /// Maps a [B256] hash to a [Vec]<[TxEnvelope]>. + hash_to_txs: HashMap>, +} + +impl LocalChainProvider { + pub fn new() -> Self { + Self::default() + } + + /// Commits Chain state to the provider. + pub fn commit(&mut self, chain: Arc) { + self.commit_headers(&chain); + self.commit_block_infos(&chain); + self.commit_receipts(&chain); + self.commit_txs(&chain); + } + + /// Commits [Header]s to the provider. + fn commit_headers(&mut self, chain: &Arc) { + for header in chain.headers() { + // TODO: won't need to coerce once reth uses alloy types + self.hash_to_header.insert( + header.hash(), + Header { + parent_hash: header.parent_hash, + ommers_hash: header.ommers_hash, + beneficiary: header.beneficiary, + state_root: header.state_root, + requests_root: header.requests_root, + transactions_root: header.transactions_root, + receipts_root: header.receipts_root, + withdrawals_root: header.withdrawals_root, + logs_bloom: header.logs_bloom, + difficulty: header.difficulty, + number: header.number, + gas_limit: header.gas_limit as u128, + gas_used: header.gas_used as u128, + timestamp: header.timestamp, + mix_hash: header.mix_hash, + nonce: header.nonce.into(), + base_fee_per_gas: header.base_fee_per_gas.map(|b| b as u128), + blob_gas_used: header.blob_gas_used.map(|b| b as u128), + excess_blob_gas: header.excess_blob_gas.map(|b| b as u128), + parent_beacon_block_root: header.parent_beacon_block_root, + extra_data: header.extra_data.clone(), + }, + ); + } + } + + /// Commits [BlockInfo]s to the provider. + fn commit_block_infos(&mut self, chain: &Arc) { + for block in chain.blocks_iter() { + self.hash_to_block_info.insert( + block.hash(), + BlockInfo { + hash: block.hash(), + number: block.number, + timestamp: block.timestamp, + parent_hash: block.parent_hash, + }, + ); + } + } + + /// Inserts a [BlockInfo] into the provider. + pub fn insert_block_info(&mut self, block_info: BlockInfo) { + self.hash_to_block_info.insert(block_info.hash, block_info); + } + + /// Commits [Receipt]s to the provider. + fn commit_receipts(&mut self, chain: &Arc) { + for (b, receipt) in chain.blocks_and_receipts() { + self.hash_to_receipts.insert( + b.hash(), + receipt + .iter() + .flat_map(|r| { + r.as_ref().map(|r| Receipt { + cumulative_gas_used: r.cumulative_gas_used as u128, + logs: r.logs.clone(), + status: alloy_consensus::Eip658Value::Eip658(r.success), + }) + }) + .collect(), + ); + } + } + + /// Commits [TxEnvelope]s to the provider. + fn commit_txs(&mut self, chain: &Arc) { + for b in chain.blocks_iter() { + let txs = b + .transactions() + .flat_map(|tx| { + let mut buf = Vec::new(); + tx.signature.encode(&mut buf); + use alloy_rlp::Decodable; + let sig = match kona_derive::types::alloy_primitives::Signature::decode( + &mut buf.as_slice(), + ) { + Ok(s) => s, + Err(_) => return None, + }; + let new = match &tx.transaction { + Transaction::Legacy(l) => { + let legacy_tx = TxLegacy { + chain_id: l.chain_id, + nonce: l.nonce, + gas_price: l.gas_price, + gas_limit: l.gas_limit as u128, + to: l.to, + value: l.value, + input: l.input.clone(), + }; + TxEnvelope::Legacy(Signed::new_unchecked(legacy_tx, sig, tx.hash)) + } + Transaction::Eip2930(e) => { + let eip_tx = TxEip2930 { + chain_id: e.chain_id, + nonce: e.nonce, + gas_price: e.gas_price, + gas_limit: e.gas_limit as u128, + to: e.to, + value: e.value, + input: e.input.clone(), + access_list: alloy_eips::eip2930::AccessList( + e.access_list + .0 + .clone() + .into_iter() + .map(|item| alloy_eips::eip2930::AccessListItem { + address: item.address, + storage_keys: item.storage_keys.clone(), + }) + .collect(), + ), + }; + TxEnvelope::Eip2930(Signed::new_unchecked(eip_tx, sig, tx.hash)) + } + Transaction::Eip1559(e) => { + let eip_tx = TxEip1559 { + chain_id: e.chain_id, + nonce: e.nonce, + max_priority_fee_per_gas: e.max_priority_fee_per_gas, + max_fee_per_gas: e.max_fee_per_gas, + gas_limit: e.gas_limit as u128, + to: e.to, + value: e.value, + input: e.input.clone(), + access_list: alloy_eips::eip2930::AccessList( + e.access_list + .0 + .clone() + .into_iter() + .map(|item| alloy_eips::eip2930::AccessListItem { + address: item.address, + storage_keys: item.storage_keys.clone(), + }) + .collect(), + ), + }; + TxEnvelope::Eip1559(Signed::new_unchecked(eip_tx, sig, tx.hash)) + } + Transaction::Eip4844(e) => { + let eip_tx = TxEip4844 { + chain_id: e.chain_id, + nonce: e.nonce, + max_fee_per_gas: e.max_fee_per_gas, + max_priority_fee_per_gas: e.max_priority_fee_per_gas, + max_fee_per_blob_gas: e.max_fee_per_blob_gas, + blob_versioned_hashes: e.blob_versioned_hashes.clone(), + gas_limit: e.gas_limit as u128, + to: e.to, + value: e.value, + input: e.input.clone(), + access_list: alloy_eips::eip2930::AccessList( + e.access_list + .0 + .clone() + .into_iter() + .map(|item| alloy_eips::eip2930::AccessListItem { + address: item.address, + storage_keys: item.storage_keys.clone(), + }) + .collect(), + ), + }; + TxEnvelope::Eip4844(Signed::new_unchecked( + TxEip4844Variant::TxEip4844(eip_tx), + sig, + tx.hash, + )) + } + }; + Some(new) + }) + .collect(); + self.hash_to_txs.insert(b.hash(), txs); + } + } +} + +#[async_trait] +impl ChainProvider for LocalChainProvider { + /// Fetch the L1 [Header] for the given [B256] hash. + async fn header_by_hash(&mut self, hash: B256) -> Result
{ + self.hash_to_header.get(&hash).cloned().ok_or_else(|| anyhow::anyhow!("Header not found")) + } + + /// 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 { + self.hash_to_block_info + .values() + .find(|bi| bi.number == number) + .cloned() + .ok_or_else(|| anyhow::anyhow!("Block not found")) + } + + /// 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.hash_to_receipts + .get(&hash) + .cloned() + .ok_or_else(|| anyhow::anyhow!("Receipts not found")) + } + + /// Returns block info and transactions for the given block hash. + async fn block_info_and_transactions_by_hash( + &mut self, + hash: B256, + ) -> Result<(BlockInfo, Vec)> { + let block_info = self + .hash_to_block_info + .get(&hash) + .cloned() + .ok_or_else(|| anyhow::anyhow!("Block not found"))?; + let txs = + self.hash_to_txs.get(&hash).cloned().ok_or_else(|| anyhow::anyhow!("Tx not found"))?; + Ok((block_info, txs)) + } +} diff --git a/examples/exex/kona/src/validation.rs b/examples/exex/kona/src/validation.rs new file mode 100644 index 00000000000..7bdb2d093d0 --- /dev/null +++ b/examples/exex/kona/src/validation.rs @@ -0,0 +1,88 @@ +//! Contains logic to validate derivation pipeline outputs. + +use alloy_provider::{Provider, ReqwestProvider}; +use alloy_rpc_types::{BlockNumberOrTag, BlockTransactionsKind, Header}; +use alloy_transport::TransportResult; +use anyhow::Result; +use kona_derive::types::{L2AttributesWithParent, L2PayloadAttributes, RawTransaction}; +use std::vec::Vec; +use tracing::warn; + +/// OnlineValidator +/// +/// Validates the [`L2AttributesWithParent`] by fetching the associated L2 block from +/// a trusted L2 RPC and constructing the L2 Attributes from the block. +#[derive(Debug, Clone)] +pub struct OnlineValidator { + /// The L2 provider. + provider: ReqwestProvider, + /// The canyon activation timestamp. + canyon_activation: u64, +} + +impl OnlineValidator { + /// Creates a new `OnlineValidator`. + pub fn new(provider: ReqwestProvider, canyon: u64) -> Self { + Self { provider, canyon_activation: canyon } + } + + /// Creates a new [OnlineValidator] from the provided [reqwest::Url]. + pub fn new_http(url: reqwest::Url, canyon: u64) -> Self { + let inner = ReqwestProvider::new_http(url); + Self::new(inner, canyon) + } + + /// Fetches a block [Header] and a list of raw RLP encoded transactions from the L2 provider. + /// + /// This method needs to fetch the non-hydrated block and then + /// fetch the raw transactions using the `debug_*` namespace. + pub(crate) async fn get_block( + &self, + tag: BlockNumberOrTag, + ) -> Result<(Header, Vec)> { + // Don't hydrate the block so we only get a list of transaction hashes. + let block = self + .provider + .get_block(tag.into(), BlockTransactionsKind::Hashes) + .await + .map_err(|e| anyhow::anyhow!(e))? + .ok_or(anyhow::anyhow!("Block not found"))?; + // For each transaction hash, fetch the raw transaction RLP. + let mut txs = vec![]; + for tx in block.transactions.hashes() { + let tx: TransportResult = + self.provider.raw_request("debug_getRawTransaction".into(), [tx]).await; + if let Ok(tx) = tx { + txs.push(tx); + } else { + warn!("Failed to fetch transaction: {:?}", tx); + } + } + Ok((block.header, txs)) + } + + /// Gets the payload for the specified [BlockNumberOrTag]. + pub(crate) async fn get_payload(&self, tag: BlockNumberOrTag) -> Result { + let (header, transactions) = self.get_block(tag).await?; + Ok(L2PayloadAttributes { + timestamp: header.timestamp, + prev_randao: header.mix_hash.unwrap_or_default(), + fee_recipient: header.miner, + // Withdrawals on optimism are always empty, *after* canyon (Shanghai) activation + withdrawals: (header.timestamp >= self.canyon_activation).then_some(Vec::default()), + parent_beacon_block_root: header.parent_beacon_block_root, + transactions, + no_tx_pool: true, + gas_limit: Some(header.gas_limit as u64), + }) + } + + /// Validates the given [`L2AttributesWithParent`]. + pub async fn validate(&self, attributes: &L2AttributesWithParent) -> bool { + let expected = attributes.parent.block_info.number + 1; + let tag = BlockNumberOrTag::from(expected); + let payload = self.get_payload(tag).await.unwrap(); + tracing::debug!("Check payload against: {:?}", payload); + attributes.attributes == payload + } +}