diff --git a/Cargo.lock b/Cargo.lock index 1d5a8f1f2..cc494cfab 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -258,6 +258,16 @@ dependencies = [ "sha2 0.10.8", ] +[[package]] +name = "alloy-evm" +version = "0.1.0" +source = "git+https://github.com/alloy-rs/evm?rev=048248c#048248c74a2bd9adb262e8975ce22db6e76e2ee2" +dependencies = [ + "alloy-primitives", + "revm", + "revm-optimism", +] + [[package]] name = "alloy-genesis" version = "0.11.1" @@ -355,6 +365,17 @@ dependencies = [ "url", ] +[[package]] +name = "alloy-op-evm" +version = "0.1.0" +source = "git+https://github.com/alloy-rs/evm?rev=048248c#048248c74a2bd9adb262e8975ce22db6e76e2ee2" +dependencies = [ + "alloy-evm", + "alloy-primitives", + "revm", + "revm-optimism", +] + [[package]] name = "alloy-primitives" version = "0.8.21" @@ -1862,9 +1883,9 @@ dependencies = [ [[package]] name = "clap" -version = "4.5.29" +version = "4.5.30" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8acebd8ad879283633b343856142139f2da2317c96b05b4dd6181c61e2480184" +checksum = "92b7b18d71fad5313a1e320fa9897994228ce274b60faa4d694fe0ea89cd9e6d" dependencies = [ "clap_builder", "clap_derive", @@ -1872,9 +1893,9 @@ dependencies = [ [[package]] name = "clap_builder" -version = "4.5.29" +version = "4.5.30" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f6ba32cbda51c7e1dfd49acc1457ba1a7dec5b64fe360e828acb13ca8dc9c2f9" +checksum = "a35db2071778a7344791a4fb4f95308b5673d219dee3ae348b86642574ecc90c" dependencies = [ "anstream", "anstyle", @@ -2554,6 +2575,17 @@ dependencies = [ "syn 1.0.109", ] +[[package]] +name = "derive-where" +version = "1.2.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "62d671cc41a825ebabc75757b62d3d168c577f9149b2d49ece1dad1f72119d25" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.98", +] + [[package]] name = "derive_arbitrary" version = "1.4.1" @@ -3062,6 +3094,7 @@ name = "example-custom-evm" version = "0.0.0" dependencies = [ "alloy-consensus", + "alloy-evm", "alloy-genesis", "alloy-primitives", "eyre", @@ -3083,6 +3116,7 @@ name = "example-custom-inspector" version = "0.0.0" dependencies = [ "alloy-eips", + "alloy-evm", "alloy-primitives", "alloy-rpc-types-eth", "clap", @@ -3090,7 +3124,6 @@ dependencies = [ "reth", "reth-evm", "reth-node-ethereum", - "revm-primitives", ] [[package]] @@ -3260,6 +3293,7 @@ name = "example-stateful-precompile" version = "0.0.0" dependencies = [ "alloy-consensus", + "alloy-evm", "alloy-genesis", "alloy-primitives", "eyre", @@ -6287,7 +6321,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3779b94aeb87e8bd4e834cee3650289ee9e0d5677f976ecdb6d219e5f4f6cd94" dependencies = [ "rand_chacha 0.9.0", - "rand_core 0.9.0", + "rand_core 0.9.1", "zerocopy 0.8.18", ] @@ -6318,7 +6352,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d3022b5f1df60f26e1ffddd6c66e8aa15de382ae63b3a0c1bfc0e4d3e3f325cb" dependencies = [ "ppv-lite86", - "rand_core 0.9.0", + "rand_core 0.9.1", ] [[package]] @@ -6341,9 +6375,9 @@ dependencies = [ [[package]] name = "rand_core" -version = "0.9.0" +version = "0.9.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b08f3c9802962f7e1b25113931d94f43ed9725bebc59db9d0c3e9a23b67e15ff" +checksum = "a88e0da7a2c97baa202165137c158d0a2e824ac465d13d81046727b34cb247d3" dependencies = [ "getrandom 0.3.1", "zerocopy 0.8.18", @@ -6399,9 +6433,9 @@ dependencies = [ [[package]] name = "raw-cpuid" -version = "11.3.0" +version = "11.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c6928fa44c097620b706542d428957635951bade7143269085389d42c8a4927e" +checksum = "529468c1335c1c03919960dfefdb1b3648858c20d7ec2d0663e728e4a717efbc" dependencies = [ "bitflags 2.8.0", ] @@ -6730,7 +6764,8 @@ dependencies = [ "reth-storage-api", "reth-testing-utils", "reth-trie", - "revm", + "revm-database", + "revm-state", "tokio", "tokio-stream", "tracing", @@ -7406,6 +7441,7 @@ dependencies = [ "reth-trie-parallel", "reth-trie-sparse", "revm-primitives", + "revm-state", "schnellru", "thiserror 2.0.11", "tokio", @@ -7438,6 +7474,7 @@ dependencies = [ "reth-provider", "reth-revm", "reth-trie", + "revm-database", "revm-primitives", "serde", "serde_json", @@ -7654,7 +7691,7 @@ dependencies = [ "reth-primitives-traits", "reth-testing-utils", "reth-zstd-compressors", - "revm-primitives", + "revm-context", "secp256k1", "serde", "test-fuzz", @@ -7676,6 +7713,7 @@ version = "1.2.0" dependencies = [ "alloy-consensus", "alloy-eips", + "alloy-evm", "alloy-primitives", "auto_impl", "futures-util", @@ -7694,7 +7732,8 @@ dependencies = [ "reth-primitives-traits", "reth-storage-errors", "revm", - "revm-primitives", + "revm-database", + "revm-optimism", ] [[package]] @@ -7703,10 +7742,10 @@ version = "1.2.0" dependencies = [ "alloy-consensus", "alloy-eips", + "alloy-evm", "alloy-genesis", "alloy-primitives", "alloy-sol-types", - "derive_more", "reth-chainspec", "reth-consensus", "reth-ethereum-consensus", @@ -7717,8 +7756,6 @@ dependencies = [ "reth-primitives-traits", "reth-revm", "reth-testing-utils", - "revm", - "revm-primitives", "secp256k1", "serde_json", ] @@ -7732,6 +7769,7 @@ dependencies = [ "alloy-rlp", "nybbles", "reth-storage-errors", + "revm-database-interface", "thiserror 2.0.11", ] @@ -7751,6 +7789,7 @@ dependencies = [ "reth-primitives-traits", "reth-trie-common", "revm", + "revm-database", "serde", "serde_with", ] @@ -8515,7 +8554,9 @@ version = "1.2.0" dependencies = [ "alloy-consensus", "alloy-eips", + "alloy-evm", "alloy-genesis", + "alloy-op-evm", "alloy-primitives", "derive_more", "op-alloy-consensus", @@ -8533,6 +8574,8 @@ dependencies = [ "reth-primitives-traits", "reth-revm", "revm", + "revm-database", + "revm-optimism", "revm-primitives", "thiserror 2.0.11", "tracing", @@ -8599,6 +8642,7 @@ dependencies = [ "reth-transaction-pool", "reth-trie-db", "revm", + "revm-optimism", "serde", "serde_json", "tokio", @@ -8664,7 +8708,8 @@ dependencies = [ "reth-codecs", "reth-primitives-traits", "reth-zstd-compressors", - "revm-primitives", + "revm-context", + "revm-optimism", "rstest", "secp256k1", "serde", @@ -8716,6 +8761,7 @@ dependencies = [ "reth-tasks", "reth-transaction-pool", "revm", + "revm-optimism", "serde_json", "thiserror 2.0.11", "tokio", @@ -8759,7 +8805,7 @@ dependencies = [ "reth-provider", "reth-storage-api", "reth-transaction-pool", - "revm", + "revm-optimism", ] [[package]] @@ -8883,7 +8929,9 @@ dependencies = [ "rayon", "reth-chainspec", "reth-codecs", + "revm-bytecode", "revm-primitives", + "revm-state", "secp256k1", "serde", "serde_json", @@ -8934,7 +8982,9 @@ dependencies = [ "reth-testing-utils", "reth-trie", "reth-trie-db", - "revm", + "revm-database", + "revm-database-interface", + "revm-state", "strum", "tempfile", "tokio", @@ -9004,6 +9054,8 @@ dependencies = [ "reth-storage-errors", "reth-trie", "revm", + "revm-database", + "revm-inspector", ] [[package]] @@ -9285,6 +9337,7 @@ dependencies = [ "reth-transaction-pool", "reth-trie", "revm", + "revm-database", "revm-inspectors", "revm-primitives", "schnellru", @@ -9500,7 +9553,7 @@ dependencies = [ "reth-storage-errors", "reth-trie", "reth-trie-db", - "revm", + "revm-database", ] [[package]] @@ -9514,6 +9567,7 @@ dependencies = [ "reth-primitives-traits", "reth-prune-types", "reth-static-file-types", + "revm-database-interface", "thiserror 2.0.11", ] @@ -9605,7 +9659,7 @@ dependencies = [ "reth-tasks", "reth-tracing", "revm-interpreter", - "revm-primitives", + "revm-specification", "rustc-hash 2.1.1", "schnellru", "serde", @@ -9641,7 +9695,8 @@ dependencies = [ "reth-storage-errors", "reth-trie-common", "reth-trie-sparse", - "revm", + "revm-database", + "revm-state", "serde_json", "tracing", "triehash", @@ -9672,7 +9727,8 @@ dependencies = [ "rayon", "reth-codecs", "reth-primitives-traits", - "revm", + "revm-database", + "revm-state", "serde", "serde_json", "serde_with", @@ -9700,6 +9756,7 @@ dependencies = [ "reth-trie", "reth-trie-common", "revm", + "revm-database", "serde", "serde_json", "similar-asserts", @@ -9769,16 +9826,124 @@ dependencies = [ [[package]] name = "revm" -version = "19.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dfc5bef3c95fadf3b6a24a253600348380c169ef285f9780a793bb7090c8990d" +version = "20.0.0-alpha.1" +source = "git+https://github.com/bluealloy/revm?rev=a8b9b1e#a8b9b1e403d73be0af1fd107f217dd835eb79971" dependencies = [ - "auto_impl", - "cfg-if", - "dyn-clone", - "once_cell", + "revm-bytecode", + "revm-context", + "revm-context-interface", + "revm-database", + "revm-database-interface", + "revm-handler", + "revm-inspector", "revm-interpreter", "revm-precompile", + "revm-primitives", + "revm-specification", + "revm-state", +] + +[[package]] +name = "revm-bytecode" +version = "1.0.0-alpha.1" +source = "git+https://github.com/bluealloy/revm?rev=a8b9b1e#a8b9b1e403d73be0af1fd107f217dd835eb79971" +dependencies = [ + "bitvec", + "revm-primitives", + "revm-specification", + "serde", +] + +[[package]] +name = "revm-context" +version = "1.0.0-alpha.1" +source = "git+https://github.com/bluealloy/revm?rev=a8b9b1e#a8b9b1e403d73be0af1fd107f217dd835eb79971" +dependencies = [ + "alloy-eip2930", + "alloy-eip7702", + "auto_impl", + "cfg-if", + "derive-where", + "revm-bytecode", + "revm-context-interface", + "revm-database-interface", + "revm-interpreter", + "revm-primitives", + "revm-specification", + "revm-state", + "serde", +] + +[[package]] +name = "revm-context-interface" +version = "1.0.0-alpha.1" +source = "git+https://github.com/bluealloy/revm?rev=a8b9b1e#a8b9b1e403d73be0af1fd107f217dd835eb79971" +dependencies = [ + "alloy-eip2930", + "alloy-eip7702", + "auto_impl", + "revm-database-interface", + "revm-primitives", + "revm-specification", + "revm-state", + "serde", +] + +[[package]] +name = "revm-database" +version = "1.0.0-alpha.1" +source = "git+https://github.com/bluealloy/revm?rev=a8b9b1e#a8b9b1e403d73be0af1fd107f217dd835eb79971" +dependencies = [ + "auto_impl", + "revm-bytecode", + "revm-database-interface", + "revm-primitives", + "revm-state", + "serde", +] + +[[package]] +name = "revm-database-interface" +version = "1.0.0-alpha.1" +source = "git+https://github.com/bluealloy/revm?rev=a8b9b1e#a8b9b1e403d73be0af1fd107f217dd835eb79971" +dependencies = [ + "auto_impl", + "revm-primitives", + "revm-state", + "serde", +] + +[[package]] +name = "revm-handler" +version = "1.0.0-alpha.1" +source = "git+https://github.com/bluealloy/revm?rev=a8b9b1e#a8b9b1e403d73be0af1fd107f217dd835eb79971" +dependencies = [ + "auto_impl", + "revm-bytecode", + "revm-context", + "revm-context-interface", + "revm-database", + "revm-interpreter", + "revm-precompile", + "revm-primitives", + "revm-specification", + "revm-state", + "serde", +] + +[[package]] +name = "revm-inspector" +version = "1.0.0-alpha.1" +source = "git+https://github.com/bluealloy/revm?rev=a8b9b1e#a8b9b1e403d73be0af1fd107f217dd835eb79971" +dependencies = [ + "auto_impl", + "revm-context", + "revm-database-interface", + "revm-handler", + "revm-interpreter", + "revm-precompile", + "revm-primitives", + "revm-state", "serde", "serde_json", ] @@ -9786,8 +9951,7 @@ dependencies = [ [[package]] name = "revm-inspectors" version = "0.15.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6d87cdf1c0d878b48423f8a86232950657abaf72a2d0d14af609467542313b1a" +source = "git+https://github.com/paradigmxyz/revm-inspectors?rev=74b6aa4#74b6aa48107b93a9f661a30bd1d763bbf145e828" dependencies = [ "alloy-primitives", "alloy-rpc-types-eth", @@ -9805,28 +9969,45 @@ dependencies = [ [[package]] name = "revm-interpreter" -version = "15.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7dcab7ef2064057acfc84731205f4bc77f4ec1b35630800b26ff6a185731c5ab" +version = "16.0.0-alpha.1" +source = "git+https://github.com/bluealloy/revm?rev=a8b9b1e#a8b9b1e403d73be0af1fd107f217dd835eb79971" dependencies = [ + "revm-bytecode", + "revm-context-interface", "revm-primitives", + "revm-specification", + "serde", +] + +[[package]] +name = "revm-optimism" +version = "1.0.0-alpha.1" +source = "git+https://github.com/bluealloy/revm?rev=a8b9b1e#a8b9b1e403d73be0af1fd107f217dd835eb79971" +dependencies = [ + "auto_impl", + "once_cell", + "revm", + "revm-inspector", + "revm-precompile", "serde", ] [[package]] name = "revm-precompile" -version = "16.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6caa1a7ff2cc4a09a263fcf9de99151706f323d30f33d519ed329f017a02b046" +version = "17.0.0-alpha.1" +source = "git+https://github.com/bluealloy/revm?rev=a8b9b1e#a8b9b1e403d73be0af1fd107f217dd835eb79971" dependencies = [ "aurora-engine-modexp", "blst", "c-kzg", "cfg-if", "k256", + "libsecp256k1", "once_cell", "p256", + "revm-context-interface", "revm-primitives", + "revm-specification", "ripemd", "secp256k1", "sha2 0.10.8", @@ -9835,21 +10016,31 @@ dependencies = [ [[package]] name = "revm-primitives" -version = "15.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f0f987564210317706def498421dfba2ae1af64a8edce82c6102758b48133fcb" +version = "16.0.0-alpha.1" +source = "git+https://github.com/bluealloy/revm?rev=a8b9b1e#a8b9b1e403d73be0af1fd107f217dd835eb79971" dependencies = [ - "alloy-eip2930", - "alloy-eip7702", "alloy-primitives", - "auto_impl", - "bitflags 2.8.0", - "bitvec", - "c-kzg", - "cfg-if", - "dyn-clone", +] + +[[package]] +name = "revm-specification" +version = "1.0.0-alpha.1" +source = "git+https://github.com/bluealloy/revm?rev=a8b9b1e#a8b9b1e403d73be0af1fd107f217dd835eb79971" +dependencies = [ "enumn", - "hex", + "revm-primitives", + "serde", +] + +[[package]] +name = "revm-state" +version = "1.0.0-alpha.1" +source = "git+https://github.com/bluealloy/revm?rev=a8b9b1e#a8b9b1e403d73be0af1fd107f217dd835eb79971" +dependencies = [ + "bitflags 2.8.0", + "revm-bytecode", + "revm-primitives", + "revm-specification", "serde", ] @@ -10210,9 +10401,9 @@ checksum = "6ea1a2d0a644769cc99faa24c3ad26b379b786fe7c36fd3c546254801650e6dd" [[package]] name = "ryu-js" -version = "1.0.1" +version = "1.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ad97d4ce1560a5e27cec89519dc8300d1aa6035b099821261c651486a19e44d5" +checksum = "dd29631678d6fb0903b69223673e122c32e9ae559d0960a38d574695ebc0ea15" [[package]] name = "same-file" @@ -10949,9 +11140,9 @@ checksum = "55937e1799185b12863d447f42597ed69d9928686b8d88a1df17376a097d8369" [[package]] name = "tempfile" -version = "3.16.0" +version = "3.17.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "38c246215d7d24f48ae091a2902398798e05d978b24315d6efbc00ede9a8bb91" +checksum = "22e5a0acb1f3f55f65cc4a866c361b2fb2a0ff6366785ae6fbb5f85df07ba230" dependencies = [ "cfg-if", "fastrand 2.3.0", diff --git a/Cargo.toml b/Cargo.toml index bbd660421..c6176ca33 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -428,15 +428,25 @@ reth-trie-sparse = { path = "crates/trie/sparse" } reth-zstd-compressors = { path = "crates/storage/zstd-compressors", default-features = false } # revm -revm = { version = "19.5.0", default-features = false } -revm-primitives = { version = "15.2.0", default-features = false } -revm-interpreter = { version = "15.2.0", default-features = false } -revm-inspectors = "0.15.0" +revm = { version = "20.0.0-alpha.1", default-features = false } +revm-bytecode = { version = "1.0.0-alpha.1", default-features = false } +revm-database = { version = "1.0.0-alpha.1", default-features = false } +revm-state = { version = "1.0.0-alpha.1", default-features = false } +revm-primitives = { version = "16.0.0-alpha.1", default-features = false } +revm-interpreter = { version = "16.0.0-alpha.1", default-features = false } +revm-inspector = { version = "1.0.0-alpha.1", default-features = false } +revm-context = { version = "1.0.0-alpha.1", default-features = false } +revm-context-interface = { version = "1.0.0-alpha.1", default-features = false } +revm-database-interface = { version = "1.0.0-alpha.1", default-features = false } +revm-specification = { version = "1.0.0-alpha.1", default-features = false } +revm-optimism = { version = "1.0.0-alpha.1", default-features = false } +revm-inspectors = "0.15" # eth alloy-chains = { version = "0.1.32", default-features = false } alloy-dyn-abi = "0.8.20" alloy-eip2124 = { version = "0.1.0", default-features = false } +alloy-evm = { version = "0.1", default-features = false } alloy-primitives = { version = "0.8.20", default-features = false, features = ["map-foldhash"] } alloy-rlp = { version = "0.3.10", default-features = false, features = ["core-net"] } alloy-sol-types = "0.8.20" @@ -472,6 +482,7 @@ alloy-transport-ipc = { version = "0.11.1", default-features = false } alloy-transport-ws = { version = "0.11.1", default-features = false } # op +alloy-op-evm = { version = "0.1", default-features = false } op-alloy-rpc-types = { version = "0.10.3", default-features = false } op-alloy-rpc-types-engine = { version = "0.10.3", default-features = false } op-alloy-network = { version = "0.10.3", default-features = false } @@ -611,7 +622,25 @@ snmalloc-rs = { version = "0.3.7", features = ["build_cc"] } # See: https://github.com/eira-fransham/crunchy/issues/13 crunchy = "=0.2.2" -# [patch.crates-io] +[patch.crates-io] +alloy-evm = { git = "https://github.com/alloy-rs/evm", rev = "048248c" } +alloy-op-evm = { git = "https://github.com/alloy-rs/evm", rev = "048248c" } + +revm = { git = "https://github.com/bluealloy/revm", rev = "a8b9b1e" } +revm-bytecode = { git = "https://github.com/bluealloy/revm", rev = "a8b9b1e" } +revm-database = { git = "https://github.com/bluealloy/revm", rev = "a8b9b1e" } +revm-state = { git = "https://github.com/bluealloy/revm", rev = "a8b9b1e" } +revm-primitives = { git = "https://github.com/bluealloy/revm", rev = "a8b9b1e" } +revm-interpreter = { git = "https://github.com/bluealloy/revm", rev = "a8b9b1e" } +revm-inspector = { git = "https://github.com/bluealloy/revm", rev = "a8b9b1e" } +revm-context = { git = "https://github.com/bluealloy/revm", rev = "a8b9b1e" } +revm-context-interface = { git = "https://github.com/bluealloy/revm", rev = "a8b9b1e" } +revm-database-interface = { git = "https://github.com/bluealloy/revm", rev = "a8b9b1e" } +revm-specification = { git = "https://github.com/bluealloy/revm", rev = "a8b9b1e" } +revm-optimism = { git = "https://github.com/bluealloy/revm", rev = "a8b9b1e" } + +revm-inspectors = { git = "https://github.com/paradigmxyz/revm-inspectors", rev = "74b6aa4" } + # alloy-consensus = { git = "https://github.com/alloy-rs/alloy", rev = "cfb13aa" } # alloy-contract = { git = "https://github.com/alloy-rs/alloy", rev = "cfb13aa" } # alloy-eips = { git = "https://github.com/alloy-rs/alloy", rev = "cfb13aa" } diff --git a/bin/reth/src/commands/debug_cmd/build_block.rs b/bin/reth/src/commands/debug_cmd/build_block.rs index b1a5cf04a..71504481e 100644 --- a/bin/reth/src/commands/debug_cmd/build_block.rs +++ b/bin/reth/src/commands/debug_cmd/build_block.rs @@ -1,4 +1,5 @@ //! Command for debugging block building. +use crate::primitives::kzg::KzgSettings; use alloy_consensus::{BlockHeader, TxEip4844}; use alloy_eips::{ eip2718::Encodable2718, @@ -32,10 +33,7 @@ use reth_provider::{ BlockHashReader, BlockReader, BlockWriter, ChainSpecProvider, ProviderFactory, StageCheckpointReader, StateProviderFactory, }; -use reth_revm::{ - cached::CachedReads, cancelled::CancelOnDrop, database::StateProviderDatabase, - primitives::KzgSettings, -}; +use reth_revm::{cached::CachedReads, cancelled::CancelOnDrop, database::StateProviderDatabase}; use reth_stages::StageId; use reth_transaction_pool::{ blobstore::InMemoryBlobStore, BlobStore, EthPooledTransaction, PoolConfig, TransactionOrigin, diff --git a/book/sources/Cargo.toml b/book/sources/Cargo.toml index b374ad798..f1293df53 100644 --- a/book/sources/Cargo.toml +++ b/book/sources/Cargo.toml @@ -11,3 +11,22 @@ reth-exex = { path = "../../crates/exex/exex" } reth-node-ethereum = { path = "../../crates/ethereum/node" } reth-tracing = { path = "../../crates/tracing" } reth-node-api = { path = "../../crates/node/api" } + +[patch.crates-io] +alloy-evm = { git = "https://github.com/alloy-rs/evm", rev = "048248c" } +alloy-op-evm = { git = "https://github.com/alloy-rs/evm", rev = "048248c" } + +revm = { git = "https://github.com/bluealloy/revm", rev = "a8b9b1e" } +revm-bytecode = { git = "https://github.com/bluealloy/revm", rev = "a8b9b1e" } +revm-database = { git = "https://github.com/bluealloy/revm", rev = "a8b9b1e" } +revm-state = { git = "https://github.com/bluealloy/revm", rev = "a8b9b1e" } +revm-primitives = { git = "https://github.com/bluealloy/revm", rev = "a8b9b1e" } +revm-interpreter = { git = "https://github.com/bluealloy/revm", rev = "a8b9b1e" } +revm-inspector = { git = "https://github.com/bluealloy/revm", rev = "a8b9b1e" } +revm-context = { git = "https://github.com/bluealloy/revm", rev = "a8b9b1e" } +revm-context-interface = { git = "https://github.com/bluealloy/revm", rev = "a8b9b1e" } +revm-database-interface = { git = "https://github.com/bluealloy/revm", rev = "a8b9b1e" } +revm-specification = { git = "https://github.com/bluealloy/revm", rev = "a8b9b1e" } +revm-optimism = { git = "https://github.com/bluealloy/revm", rev = "a8b9b1e" } + +revm-inspectors = { git = "https://github.com/paradigmxyz/revm-inspectors", rev = "74b6aa4" } diff --git a/crates/chain-state/Cargo.toml b/crates/chain-state/Cargo.toml index 639b211d5..fb7b4f53d 100644 --- a/crates/chain-state/Cargo.toml +++ b/crates/chain-state/Cargo.toml @@ -26,7 +26,8 @@ reth-trie.workspace = true alloy-eips.workspace = true alloy-primitives.workspace = true alloy-consensus.workspace = true -revm.workspace = true +revm-database.workspace = true +revm-state = { workspace = true, optional = true } # async tokio = { workspace = true, default-features = false, features = ["sync", "macros"] } @@ -59,9 +60,9 @@ test-utils = [ "alloy-signer", "alloy-signer-local", "rand", + "revm-state", "reth-chainspec/test-utils", "reth-primitives/test-utils", "reth-primitives-traits/test-utils", "reth-trie/test-utils", - "revm/test-utils", ] diff --git a/crates/chain-state/src/in_memory.rs b/crates/chain-state/src/in_memory.rs index 90be2c065..2008b0839 100644 --- a/crates/chain-state/src/in_memory.rs +++ b/crates/chain-state/src/in_memory.rs @@ -1049,7 +1049,7 @@ mod tests { } impl HashedPostStateProvider for MockStateProvider { - fn hashed_post_state(&self, _bundle_state: &revm::db::BundleState) -> HashedPostState { + fn hashed_post_state(&self, _bundle_state: &revm_database::BundleState) -> HashedPostState { HashedPostState::default() } } diff --git a/crates/chain-state/src/memory_overlay.rs b/crates/chain-state/src/memory_overlay.rs index 01b4c0e23..8651e07da 100644 --- a/crates/chain-state/src/memory_overlay.rs +++ b/crates/chain-state/src/memory_overlay.rs @@ -13,7 +13,7 @@ use reth_trie::{ updates::TrieUpdates, AccountProof, HashedPostState, HashedStorage, MultiProof, MultiProofTargets, StorageMultiProof, TrieInput, }; -use revm::db::BundleState; +use revm_database::BundleState; use std::sync::OnceLock; /// A state provider that stores references to in-memory blocks along with their state as well as a diff --git a/crates/chain-state/src/test_utils.rs b/crates/chain-state/src/test_utils.rs index 4bbb88be7..53c63845f 100644 --- a/crates/chain-state/src/test_utils.rs +++ b/crates/chain-state/src/test_utils.rs @@ -27,7 +27,8 @@ use reth_primitives_traits::{ }; use reth_storage_api::NodePrimitivesProvider; use reth_trie::{root::state_root_unhashed, updates::TrieUpdates, HashedPostState}; -use revm::{db::BundleState, primitives::AccountInfo}; +use revm_database::BundleState; +use revm_state::AccountInfo; use std::{ collections::HashMap, ops::Range, diff --git a/crates/engine/invalid-block-hooks/src/witness.rs b/crates/engine/invalid-block-hooks/src/witness.rs index ad5ceb906..1f4cd1f19 100644 --- a/crates/engine/invalid-block-hooks/src/witness.rs +++ b/crates/engine/invalid-block-hooks/src/witness.rs @@ -11,7 +11,8 @@ use reth_primitives::{NodePrimitives, RecoveredBlock, SealedHeader}; use reth_primitives_traits::{BlockBody, SignedTransaction}; use reth_provider::{BlockExecutionOutput, ChainSpecProvider, StateProviderFactory}; use reth_revm::{ - database::StateProviderDatabase, db::states::bundle_state::BundleRetention, StateBuilder, + database::StateProviderDatabase, + db::{states::bundle_state::BundleRetention, StateBuilder}, }; use reth_rpc_api::DebugApiClient; use reth_tracing::tracing::warn; diff --git a/crates/engine/local/Cargo.toml b/crates/engine/local/Cargo.toml index d1503db5d..5d0eb22ba 100644 --- a/crates/engine/local/Cargo.toml +++ b/crates/engine/local/Cargo.toml @@ -50,4 +50,5 @@ op = [ "dep:op-alloy-rpc-types-engine", "dep:reth-optimism-chainspec", "reth-payload-primitives/op", + "reth-evm/op", ] diff --git a/crates/engine/tree/Cargo.toml b/crates/engine/tree/Cargo.toml index eb5ac3db1..a22626031 100644 --- a/crates/engine/tree/Cargo.toml +++ b/crates/engine/tree/Cargo.toml @@ -86,6 +86,7 @@ reth-trie-db.workspace = true # alloy alloy-rlp.workspace = true +revm-state.workspace = true assert_matches.workspace = true criterion.workspace = true diff --git a/crates/engine/tree/benches/channel_perf.rs b/crates/engine/tree/benches/channel_perf.rs index 5eb919da8..18de45964 100644 --- a/crates/engine/tree/benches/channel_perf.rs +++ b/crates/engine/tree/benches/channel_perf.rs @@ -2,13 +2,12 @@ #![allow(missing_docs)] +use alloy_primitives::{B256, U256}; use criterion::{criterion_group, criterion_main, BatchSize, BenchmarkId, Criterion}; use proptest::test_runner::TestRunner; use rand::Rng; -use revm_primitives::{ - Account, AccountInfo, AccountStatus, Address, EvmState, EvmStorage, EvmStorageSlot, HashMap, - B256, U256, -}; +use revm_primitives::{Address, HashMap}; +use revm_state::{Account, AccountInfo, AccountStatus, EvmState, EvmStorage, EvmStorageSlot}; use std::{hint::black_box, thread}; /// Creates a mock state with the specified number of accounts for benchmarking diff --git a/crates/engine/tree/benches/state_root_task.rs b/crates/engine/tree/benches/state_root_task.rs index d5b0f7980..45f1bb5da 100644 --- a/crates/engine/tree/benches/state_root_task.rs +++ b/crates/engine/tree/benches/state_root_task.rs @@ -3,6 +3,8 @@ #![allow(missing_docs)] +use alloy_consensus::constants::KECCAK_EMPTY; +use alloy_primitives::{Address, B256}; use criterion::{criterion_group, criterion_main, BenchmarkId, Criterion}; use proptest::test_runner::TestRunner; use rand::Rng; @@ -15,10 +17,8 @@ use reth_provider::{ AccountReader, HashingWriter, ProviderFactory, }; use reth_trie::TrieInput; -use revm_primitives::{ - Account as RevmAccount, AccountInfo, AccountStatus, Address, EvmState, EvmStorageSlot, HashMap, - B256, KECCAK_EMPTY, U256, -}; +use revm_primitives::{HashMap, U256}; +use revm_state::{Account as RevmAccount, AccountInfo, AccountStatus, EvmState, EvmStorageSlot}; use std::{hint::black_box, sync::Arc}; #[derive(Debug, Clone)] diff --git a/crates/engine/tree/src/tree/mod.rs b/crates/engine/tree/src/tree/mod.rs index d8bc46ce8..b4e99ce48 100644 --- a/crates/engine/tree/src/tree/mod.rs +++ b/crates/engine/tree/src/tree/mod.rs @@ -37,7 +37,7 @@ use reth_ethereum_primitives::EthPrimitives; use reth_evm::{ execute::BlockExecutorProvider, system_calls::{NoopHook, OnStateHook}, - ConfigureEvm, Evm, TransactionEnv, + ConfigureEvm, Evm, }; use reth_payload_builder::PayloadBuilderHandle; use reth_payload_primitives::{EngineApiMessageVersion, PayloadBuilderAttributes}; @@ -2764,12 +2764,15 @@ where let state_provider = StateProviderDatabase::new(&state_provider); + let mut evm_env = evm_config.evm_env(&block); + + evm_env.cfg_env.disable_nonce_check = true; + // create a new executor and disable nonce checks in the env - let mut evm = evm_config.evm_for_block(state_provider, &block); + let mut evm = evm_config.evm_with_env(state_provider, evm_env); // create the tx env and reset nonce - let mut tx_env = evm_config.tx_env(&tx, tx.signer()); - tx_env.unset_nonce(); + let tx_env = evm_config.tx_env(&tx, tx.signer()); // exit early if execution is done if cancel_execution.is_cancelled() { diff --git a/crates/engine/tree/src/tree/root.rs b/crates/engine/tree/src/tree/root.rs index 6aee07b96..863799e5d 100644 --- a/crates/engine/tree/src/tree/root.rs +++ b/crates/engine/tree/src/tree/root.rs @@ -11,6 +11,7 @@ use reth_provider::{ providers::ConsistentDbView, BlockReader, DBProvider, DatabaseProviderFactory, StateCommitmentProvider, }; +use reth_revm::state::EvmState; use reth_trie::{ hashed_cursor::HashedPostStateCursorFactory, prefix_set::TriePrefixSetsMut, @@ -27,7 +28,7 @@ use reth_trie_sparse::{ errors::{SparseStateTrieResult, SparseTrieErrorKind}, SparseStateTrie, }; -use revm_primitives::{keccak256, EvmState, B256}; +use revm_primitives::{keccak256, B256}; use std::{ collections::{BTreeMap, VecDeque}, sync::{ @@ -1190,9 +1191,9 @@ mod tests { }; use reth_testing_utils::generators::{self, Rng}; use reth_trie::{test_utils::state_root, TrieInput}; - use revm_primitives::{ - Account as RevmAccount, AccountInfo, AccountStatus, Address, EvmState, EvmStorageSlot, - HashMap, B256, KECCAK_EMPTY, U256, + use revm_primitives::{Address, HashMap, B256, KECCAK_EMPTY, U256}; + use revm_state::{ + Account as RevmAccount, AccountInfo, AccountStatus, EvmState, EvmStorageSlot, }; use std::sync::Arc; diff --git a/crates/engine/util/Cargo.toml b/crates/engine/util/Cargo.toml index 5e8a1fba1..5010f261c 100644 --- a/crates/engine/util/Cargo.toml +++ b/crates/engine/util/Cargo.toml @@ -25,6 +25,7 @@ reth-revm.workspace = true reth-provider.workspace = true reth-ethereum-forks.workspace = true revm-primitives.workspace = true +revm-database.workspace = true reth-trie.workspace = true reth-payload-primitives.workspace = true @@ -53,5 +54,5 @@ tracing.workspace = true [features] optimism = [ - "revm-primitives/optimism", + "reth-provider/optimism", ] diff --git a/crates/ethereum/evm/Cargo.toml b/crates/ethereum/evm/Cargo.toml index 06cba81dc..45618034b 100644 --- a/crates/ethereum/evm/Cargo.toml +++ b/crates/ethereum/evm/Cargo.toml @@ -14,25 +14,22 @@ workspace = true # Reth reth-chainspec.workspace = true reth-ethereum-forks.workspace = true +reth-revm.workspace = true reth-evm.workspace = true reth-primitives.workspace = true reth-ethereum-consensus.workspace = true reth-consensus.workspace = true -revm.workspace = true # Ethereum -revm-primitives.workspace = true reth-primitives-traits.workspace = true # Alloy alloy-primitives.workspace = true alloy-eips.workspace = true +alloy-evm.workspace = true alloy-sol-types.workspace = true alloy-consensus.workspace = true -# Misc -derive_more.workspace = true - [dev-dependencies] reth-testing-utils.workspace = true reth-evm = { workspace = true, features = ["test-utils"] } @@ -53,13 +50,11 @@ std = [ "alloy-eips/std", "alloy-genesis/std", "alloy-primitives/std", - "revm/std", - "revm-primitives/std", "secp256k1/std", "reth-ethereum-forks/std", "serde_json/std", "reth-primitives-traits/std", "reth-chainspec/std", - "derive_more/std", + "alloy-evm/std", "reth-execution-types/std", ] diff --git a/crates/ethereum/evm/src/config.rs b/crates/ethereum/evm/src/config.rs index de4340062..3d0e13faa 100644 --- a/crates/ethereum/evm/src/config.rs +++ b/crates/ethereum/evm/src/config.rs @@ -1,87 +1,86 @@ use alloy_consensus::Header; use reth_chainspec::{ChainSpec, EthereumHardforks}; use reth_ethereum_forks::EthereumHardfork; +use reth_revm::specification::hardfork::SpecId; -/// Map the latest active hardfork at the given header to a revm -/// [`SpecId`](revm_primitives::SpecId). -pub fn revm_spec(chain_spec: &ChainSpec, header: &Header) -> revm_primitives::SpecId { +/// Map the latest active hardfork at the given header to a revm [`SpecId`]. +pub fn revm_spec(chain_spec: &ChainSpec, header: &Header) -> SpecId { revm_spec_by_timestamp_and_block_number(chain_spec, header.timestamp, header.number) } -/// Map the latest active hardfork at the given timestamp or block number to a revm -/// [`SpecId`](revm_primitives::SpecId). +/// Map the latest active hardfork at the given timestamp or block number to a revm [`SpecId`]. pub fn revm_spec_by_timestamp_and_block_number( chain_spec: &ChainSpec, timestamp: u64, block_number: u64, -) -> revm_primitives::SpecId { +) -> SpecId { if chain_spec .fork(EthereumHardfork::Osaka) .active_at_timestamp_or_number(timestamp, block_number) { - revm_primitives::OSAKA + SpecId::OSAKA } else if chain_spec .fork(EthereumHardfork::Prague) .active_at_timestamp_or_number(timestamp, block_number) { - revm_primitives::PRAGUE + SpecId::PRAGUE } else if chain_spec .fork(EthereumHardfork::Cancun) .active_at_timestamp_or_number(timestamp, block_number) { - revm_primitives::CANCUN + SpecId::CANCUN } else if chain_spec .fork(EthereumHardfork::Shanghai) .active_at_timestamp_or_number(timestamp, block_number) { - revm_primitives::SHANGHAI + SpecId::SHANGHAI } else if chain_spec.is_paris_active_at_block(block_number).is_some_and(|active| active) { - revm_primitives::MERGE + SpecId::MERGE } else if chain_spec .fork(EthereumHardfork::London) .active_at_timestamp_or_number(timestamp, block_number) { - revm_primitives::LONDON + SpecId::LONDON } else if chain_spec .fork(EthereumHardfork::Berlin) .active_at_timestamp_or_number(timestamp, block_number) { - revm_primitives::BERLIN + SpecId::BERLIN } else if chain_spec .fork(EthereumHardfork::Istanbul) .active_at_timestamp_or_number(timestamp, block_number) { - revm_primitives::ISTANBUL + SpecId::ISTANBUL } else if chain_spec .fork(EthereumHardfork::Petersburg) .active_at_timestamp_or_number(timestamp, block_number) { - revm_primitives::PETERSBURG + SpecId::PETERSBURG } else if chain_spec .fork(EthereumHardfork::Byzantium) .active_at_timestamp_or_number(timestamp, block_number) { - revm_primitives::BYZANTIUM + SpecId::BYZANTIUM } else if chain_spec .fork(EthereumHardfork::SpuriousDragon) .active_at_timestamp_or_number(timestamp, block_number) { - revm_primitives::SPURIOUS_DRAGON + SpecId::SPURIOUS_DRAGON } else if chain_spec .fork(EthereumHardfork::Tangerine) .active_at_timestamp_or_number(timestamp, block_number) { - revm_primitives::TANGERINE + SpecId::TANGERINE } else if chain_spec .fork(EthereumHardfork::Homestead) .active_at_timestamp_or_number(timestamp, block_number) { - revm_primitives::HOMESTEAD + SpecId::HOMESTEAD } else if chain_spec .fork(EthereumHardfork::Frontier) .active_at_timestamp_or_number(timestamp, block_number) { - revm_primitives::FRONTIER + SpecId::FRONTIER } else { panic!( "invalid hardfork chainspec: expected at least one hardfork, got {:?}", @@ -104,7 +103,7 @@ mod tests { 0, 0 ), - revm_primitives::CANCUN + SpecId::CANCUN ); assert_eq!( revm_spec_by_timestamp_and_block_number( @@ -112,12 +111,12 @@ mod tests { 0, 0 ), - revm_primitives::SHANGHAI + SpecId::SHANGHAI ); let mainnet = ChainSpecBuilder::mainnet().build(); assert_eq!( revm_spec_by_timestamp_and_block_number(&mainnet, 0, mainnet.paris_block().unwrap()), - revm_primitives::MERGE + SpecId::MERGE ); } @@ -125,75 +124,75 @@ mod tests { fn test_to_revm_spec() { assert_eq!( revm_spec(&ChainSpecBuilder::mainnet().cancun_activated().build(), &Default::default()), - revm_primitives::CANCUN + SpecId::CANCUN ); assert_eq!( revm_spec( &ChainSpecBuilder::mainnet().shanghai_activated().build(), &Default::default() ), - revm_primitives::SHANGHAI + SpecId::SHANGHAI ); assert_eq!( revm_spec(&ChainSpecBuilder::mainnet().paris_activated().build(), &Default::default()), - revm_primitives::MERGE + SpecId::MERGE ); assert_eq!( revm_spec(&ChainSpecBuilder::mainnet().london_activated().build(), &Default::default()), - revm_primitives::LONDON + SpecId::LONDON ); assert_eq!( revm_spec(&ChainSpecBuilder::mainnet().berlin_activated().build(), &Default::default()), - revm_primitives::BERLIN + SpecId::BERLIN ); assert_eq!( revm_spec( &ChainSpecBuilder::mainnet().istanbul_activated().build(), &Default::default() ), - revm_primitives::ISTANBUL + SpecId::ISTANBUL ); assert_eq!( revm_spec( &ChainSpecBuilder::mainnet().petersburg_activated().build(), &Default::default() ), - revm_primitives::PETERSBURG + SpecId::PETERSBURG ); assert_eq!( revm_spec( &ChainSpecBuilder::mainnet().byzantium_activated().build(), &Default::default() ), - revm_primitives::BYZANTIUM + SpecId::BYZANTIUM ); assert_eq!( revm_spec( &ChainSpecBuilder::mainnet().spurious_dragon_activated().build(), &Default::default() ), - revm_primitives::SPURIOUS_DRAGON + SpecId::SPURIOUS_DRAGON ); assert_eq!( revm_spec( &ChainSpecBuilder::mainnet().tangerine_whistle_activated().build(), &Default::default() ), - revm_primitives::TANGERINE + SpecId::TANGERINE ); assert_eq!( revm_spec( &ChainSpecBuilder::mainnet().homestead_activated().build(), &Default::default() ), - revm_primitives::HOMESTEAD + SpecId::HOMESTEAD ); assert_eq!( revm_spec( &ChainSpecBuilder::mainnet().frontier_activated().build(), &Default::default() ), - revm_primitives::FRONTIER + SpecId::FRONTIER ); } @@ -201,11 +200,11 @@ mod tests { fn test_eth_spec() { assert_eq!( revm_spec(&MAINNET, &Header { timestamp: 1710338135, ..Default::default() }), - revm_primitives::CANCUN + SpecId::CANCUN ); assert_eq!( revm_spec(&MAINNET, &Header { timestamp: 1681338455, ..Default::default() }), - revm_primitives::SHANGHAI + SpecId::SHANGHAI ); assert_eq!( @@ -213,43 +212,43 @@ mod tests { &MAINNET, &Header { difficulty: U256::from(10_u128), number: 15537394, ..Default::default() } ), - revm_primitives::MERGE + SpecId::MERGE ); assert_eq!( revm_spec(&MAINNET, &Header { number: 15537394 - 10, ..Default::default() }), - revm_primitives::LONDON + SpecId::LONDON ); assert_eq!( revm_spec(&MAINNET, &Header { number: 12244000 + 10, ..Default::default() }), - revm_primitives::BERLIN + SpecId::BERLIN ); assert_eq!( revm_spec(&MAINNET, &Header { number: 12244000 - 10, ..Default::default() }), - revm_primitives::ISTANBUL + SpecId::ISTANBUL ); assert_eq!( revm_spec(&MAINNET, &Header { number: 7280000 + 10, ..Default::default() }), - revm_primitives::PETERSBURG + SpecId::PETERSBURG ); assert_eq!( revm_spec(&MAINNET, &Header { number: 7280000 - 10, ..Default::default() }), - revm_primitives::BYZANTIUM + SpecId::BYZANTIUM ); assert_eq!( revm_spec(&MAINNET, &Header { number: 2675000 + 10, ..Default::default() }), - revm_primitives::SPURIOUS_DRAGON + SpecId::SPURIOUS_DRAGON ); assert_eq!( revm_spec(&MAINNET, &Header { number: 2675000 - 10, ..Default::default() }), - revm_primitives::TANGERINE + SpecId::TANGERINE ); assert_eq!( revm_spec(&MAINNET, &Header { number: 1150000 + 10, ..Default::default() }), - revm_primitives::HOMESTEAD + SpecId::HOMESTEAD ); assert_eq!( revm_spec(&MAINNET, &Header { number: 1150000 - 10, ..Default::default() }), - revm_primitives::FRONTIER + SpecId::FRONTIER ); } } diff --git a/crates/ethereum/evm/src/execute.rs b/crates/ethereum/evm/src/execute.rs index 5313f55c5..fc570d01a 100644 --- a/crates/ethereum/evm/src/execute.rs +++ b/crates/ethereum/evm/src/execute.rs @@ -21,8 +21,7 @@ use reth_evm::{ }; use reth_primitives::{EthPrimitives, Receipt, RecoveredBlock}; use reth_primitives_traits::{BlockBody, SignedTransaction}; -use revm::db::State; -use revm_primitives::{db::DatabaseCommit, ResultAndState}; +use reth_revm::{context_interface::result::ResultAndState, db::State, DatabaseCommit}; /// Factory for [`EthExecutionStrategy`]. #[derive(Debug, Clone)] @@ -300,10 +299,14 @@ mod tests { use reth_primitives::{Account, Block, BlockBody, Transaction}; use reth_primitives_traits::{crypto::secp256k1::public_key_to_address, Block as _}; use reth_revm::{ - database::StateProviderDatabase, test_utils::StateProviderTest, Database, TransitionState, + database::StateProviderDatabase, + db::TransitionState, + primitives::{address, BLOCKHASH_SERVE_WINDOW}, + state::EvmState, + test_utils::StateProviderTest, + Database, }; use reth_testing_utils::generators::{self, sign_tx_with_key_pair}; - use revm_primitives::{address, EvmState, BLOCKHASH_SERVE_WINDOW}; use secp256k1::{Keypair, Secp256k1}; use std::{collections::HashMap, sync::mpsc}; diff --git a/crates/ethereum/evm/src/lib.rs b/crates/ethereum/evm/src/lib.rs index ce522eb09..316299031 100644 --- a/crates/ethereum/evm/src/lib.rs +++ b/crates/ethereum/evm/src/lib.rs @@ -17,18 +17,20 @@ extern crate alloc; -use alloc::{sync::Arc, vec::Vec}; +use alloc::sync::Arc; use alloy_consensus::{BlockHeader, Header}; +pub use alloy_evm::EthEvm; +use alloy_evm::EthEvmFactory; use alloy_primitives::{Address, U256}; use core::{convert::Infallible, fmt::Debug}; use reth_chainspec::{ChainSpec, EthChainSpec, MAINNET}; -use reth_evm::{env::EvmEnv, ConfigureEvm, ConfigureEvmEnv, Database, Evm, NextBlockEnvAttributes}; +use reth_evm::{ConfigureEvm, ConfigureEvmEnv, EvmEnv, NextBlockEnvAttributes}; use reth_primitives::TransactionSigned; use reth_primitives_traits::transaction::execute::FillTxEnv; -use revm::{inspector_handle_register, EvmBuilder}; -use revm_primitives::{ - AnalysisKind, BlobExcessGasAndPrice, BlockEnv, Bytes, CfgEnv, CfgEnvWithHandlerCfg, EVMError, - HaltReason, HandlerCfg, ResultAndState, SpecId, TxEnv, TxKind, +use reth_revm::{ + context::{BlockEnv, CfgEnv, TxEnv}, + context_interface::block::BlobExcessGasAndPrice, + specification::hardfork::SpecId, }; mod config; @@ -44,90 +46,17 @@ pub mod dao_fork; /// [EIP-6110](https://eips.ethereum.org/EIPS/eip-6110) handling. pub mod eip6110; -/// Ethereum EVM implementation. -#[derive(derive_more::Debug, derive_more::Deref, derive_more::DerefMut, derive_more::From)] -#[debug(bound(DB::Error: Debug))] -pub struct EthEvm<'a, EXT, DB: Database>(revm::Evm<'a, EXT, DB>); - -impl Evm for EthEvm<'_, EXT, DB> { - type DB = DB; - type Tx = TxEnv; - type Error = EVMError; - type HaltReason = HaltReason; - - fn block(&self) -> &BlockEnv { - self.0.block() - } - - fn transact(&mut self, tx: Self::Tx) -> Result { - *self.tx_mut() = tx; - self.0.transact() - } - - fn transact_system_call( - &mut self, - caller: Address, - contract: Address, - data: Bytes, - ) -> Result { - #[allow(clippy::needless_update)] // side-effect of optimism fields - let tx_env = TxEnv { - caller, - transact_to: TxKind::Call(contract), - // Explicitly set nonce to None so revm does not do any nonce checks - nonce: None, - gas_limit: 30_000_000, - value: U256::ZERO, - data, - // Setting the gas price to zero enforces that no value is transferred as part of the - // call, and that the call will not count against the block's gas limit - gas_price: U256::ZERO, - // The chain ID check is not relevant here and is disabled if set to None - chain_id: None, - // Setting the gas priority fee to None ensures the effective gas price is derived from - // the `gas_price` field, which we need to be zero - gas_priority_fee: None, - access_list: Vec::new(), - // blob fields can be None for this tx - blob_hashes: Vec::new(), - max_fee_per_blob_gas: None, - // TODO remove this once this crate is no longer built with optimism - ..Default::default() - }; - - *self.tx_mut() = tx_env; - - let prev_block_env = self.block().clone(); - - // ensure the block gas limit is >= the tx - self.block_mut().gas_limit = U256::from(self.tx().gas_limit); - - // disable the base fee check for this call by setting the base fee to zero - self.block_mut().basefee = U256::ZERO; - - let res = self.0.transact(); - - // re-set the block env - *self.block_mut() = prev_block_env; - - res - } - - fn db_mut(&mut self) -> &mut Self::DB { - &mut self.context.evm.db - } -} - /// Ethereum-related EVM configuration. #[derive(Debug, Clone)] pub struct EthEvmConfig { chain_spec: Arc, + evm_factory: EthEvmFactory, } impl EthEvmConfig { /// Creates a new Ethereum EVM configuration with the given chain spec. - pub const fn new(chain_spec: Arc) -> Self { - Self { chain_spec } + pub fn new(chain_spec: Arc) -> Self { + Self { chain_spec, evm_factory: Default::default() } } /// Creates a new Ethereum EVM configuration for the ethereum mainnet. @@ -146,7 +75,7 @@ impl ConfigureEvmEnv for EthEvmConfig { type Transaction = TransactionSigned; type Error = Infallible; type TxEnv = TxEnv; - type Spec = revm_primitives::SpecId; + type Spec = SpecId; fn tx_env(&self, transaction: &TransactionSigned, sender: Address) -> Self::TxEnv { let mut tx_env = TxEnv::default(); @@ -157,25 +86,24 @@ impl ConfigureEvmEnv for EthEvmConfig { fn evm_env(&self, header: &Self::Header) -> EvmEnv { let spec = config::revm_spec(self.chain_spec(), header); - let mut cfg_env = CfgEnv::default(); - cfg_env.chain_id = self.chain_spec.chain().id(); - cfg_env.perf_analyse_created_bytecodes = AnalysisKind::default(); + // configure evm env based on parent block + let cfg_env = CfgEnv::new().with_chain_id(self.chain_spec.chain().id()).with_spec(spec); let block_env = BlockEnv { - number: U256::from(header.number()), - coinbase: header.beneficiary(), - timestamp: U256::from(header.timestamp()), + number: header.number(), + beneficiary: header.beneficiary(), + timestamp: header.timestamp(), difficulty: if spec >= SpecId::MERGE { U256::ZERO } else { header.difficulty() }, prevrandao: if spec >= SpecId::MERGE { header.mix_hash() } else { None }, - gas_limit: U256::from(header.gas_limit()), - basefee: U256::from(header.base_fee_per_gas().unwrap_or_default()), + gas_limit: header.gas_limit(), + basefee: header.base_fee_per_gas().unwrap_or_default(), // EIP-4844 excess blob gas of this block, introduced in Cancun blob_excess_gas_and_price: header.excess_blob_gas.map(|excess_blob_gas| { BlobExcessGasAndPrice::new(excess_blob_gas, spec >= SpecId::PRAGUE) }), }; - EvmEnv { cfg_env, spec, block_env } + EvmEnv { cfg_env, block_env } } fn next_evm_env( @@ -183,9 +111,6 @@ impl ConfigureEvmEnv for EthEvmConfig { parent: &Self::Header, attributes: NextBlockEnvAttributes, ) -> Result { - // configure evm env based on parent block - let cfg = CfgEnv::default().with_chain_id(self.chain_spec.chain().id()); - // ensure we're not missing any timestamp based hardforks let spec_id = revm_spec_by_timestamp_and_block_number( &self.chain_spec, @@ -193,6 +118,9 @@ impl ConfigureEvmEnv for EthEvmConfig { parent.number() + 1, ); + // configure evm env based on parent block + let cfg = CfgEnv::new().with_chain_id(self.chain_spec.chain().id()).with_spec(spec_id); + // if the parent block did not have excess blob gas (i.e. it was pre-cancun), but it is // cancun now, we need to set the excess blob gas to the default value(0) let blob_excess_gas_and_price = parent @@ -206,7 +134,7 @@ impl ConfigureEvmEnv for EthEvmConfig { self.chain_spec.base_fee_params_at_timestamp(attributes.timestamp), ); - let mut gas_limit = U256::from(attributes.gas_limit); + let mut gas_limit = attributes.gas_limit; // If we are on the London fork boundary, we need to multiply the parent's gas limit by the // elasticity multiplier to get the new gas limit. @@ -217,71 +145,34 @@ impl ConfigureEvmEnv for EthEvmConfig { .elasticity_multiplier; // multiply the gas limit by the elasticity multiplier - gas_limit *= U256::from(elasticity_multiplier); + gas_limit *= elasticity_multiplier as u64; // set the base fee to the initial base fee from the EIP-1559 spec basefee = Some(INITIAL_BASE_FEE) } let block_env = BlockEnv { - number: U256::from(parent.number + 1), - coinbase: attributes.suggested_fee_recipient, - timestamp: U256::from(attributes.timestamp), + number: parent.number + 1, + beneficiary: attributes.suggested_fee_recipient, + timestamp: attributes.timestamp, difficulty: U256::ZERO, prevrandao: Some(attributes.prev_randao), gas_limit, // calculate basefee based on parent block's gas usage - basefee: basefee.map(U256::from).unwrap_or_default(), + basefee: basefee.unwrap_or_default(), // calculate excess gas based on parent block's blob gas usage blob_excess_gas_and_price, }; - Ok((CfgEnvWithHandlerCfg::new_with_spec_id(cfg, spec_id), block_env).into()) + Ok((cfg, block_env).into()) } } impl ConfigureEvm for EthEvmConfig { - type Evm<'a, DB: Database + 'a, I: 'a> = EthEvm<'a, I, DB>; - type EvmError = EVMError; - type HaltReason = HaltReason; + type EvmFactory = EthEvmFactory; - fn evm_with_env(&self, db: DB, evm_env: EvmEnv) -> Self::Evm<'_, DB, ()> { - let cfg_env_with_handler_cfg = CfgEnvWithHandlerCfg { - cfg_env: evm_env.cfg_env, - handler_cfg: HandlerCfg::new(evm_env.spec), - }; - EthEvm( - EvmBuilder::default() - .with_db(db) - .with_cfg_env_with_handler_cfg(cfg_env_with_handler_cfg) - .with_block_env(evm_env.block_env) - .build(), - ) - } - - fn evm_with_env_and_inspector( - &self, - db: DB, - evm_env: EvmEnv, - inspector: I, - ) -> Self::Evm<'_, DB, I> - where - DB: Database, - I: revm::GetInspector, - { - let cfg_env_with_handler_cfg = CfgEnvWithHandlerCfg { - cfg_env: evm_env.cfg_env, - handler_cfg: HandlerCfg::new(evm_env.spec), - }; - EthEvm( - EvmBuilder::default() - .with_db(db) - .with_external_context(inspector) - .with_cfg_env_with_handler_cfg(cfg_env_with_handler_cfg) - .with_block_env(evm_env.block_env) - .append_handler_register(inspector_handle_register) - .build(), - ) + fn evm_factory(&self) -> &Self::EvmFactory { + &self.evm_factory } } @@ -290,15 +181,14 @@ mod tests { use super::*; use alloy_consensus::Header; use alloy_genesis::Genesis; - use alloy_primitives::U256; use reth_chainspec::{Chain, ChainSpec, MAINNET}; - use reth_evm::{env::EvmEnv, execute::ProviderError}; - use revm::{ - db::{CacheDB, EmptyDBTyped}, - inspectors::NoOpInspector, - primitives::{BlockEnv, CfgEnv, SpecId}, + use reth_evm::{execute::ProviderError, EvmEnv}; + use reth_revm::{ + context::{BlockEnv, CfgEnv}, + database_interface::EmptyDBTyped, + db::CacheDB, + inspector::NoOpInspector, }; - use revm_primitives::HandlerCfg; #[test] fn test_fill_cfg_and_block_env() { @@ -337,14 +227,8 @@ mod tests { let evm = evm_config.evm_with_env(db, evm_env.clone()); // Check that the EVM environment - assert_eq!(evm.context.evm.env.block, evm_env.block_env); - assert_eq!(evm.context.evm.env.cfg, evm_env.cfg_env); - - // Default spec ID - assert_eq!(evm.handler.spec_id(), SpecId::LATEST); - - // No Optimism - assert_eq!(evm.handler.cfg, HandlerCfg { spec_id: SpecId::LATEST, ..Default::default() }); + assert_eq!(evm.block, evm_env.block_env); + assert_eq!(evm.cfg, evm_env.cfg_env); } #[test] @@ -362,13 +246,7 @@ mod tests { let evm = evm_config.evm_with_env(db, evm_env); // Check that the EVM environment is initialized with the custom environment - assert_eq!(evm.context.evm.inner.env.cfg, cfg); - - // Default spec ID - assert_eq!(evm.handler.spec_id(), SpecId::LATEST); - - // No Optimism - assert_eq!(evm.handler.cfg, HandlerCfg { spec_id: SpecId::LATEST, ..Default::default() }); + assert_eq!(evm.cfg, cfg); } #[test] @@ -379,25 +257,18 @@ mod tests { let db = CacheDB::>::default(); // Create customs block and tx env - let block = BlockEnv { - basefee: U256::from(1000), - gas_limit: U256::from(10_000_000), - number: U256::from(42), - ..Default::default() - }; + let block = + BlockEnv { basefee: 1000, gas_limit: 10_000_000, number: 42, ..Default::default() }; let evm_env = EvmEnv { block_env: block, ..Default::default() }; let evm = evm_config.evm_with_env(db, evm_env.clone()); // Verify that the block and transaction environments are set correctly - assert_eq!(evm.context.evm.env.block, evm_env.block_env); + assert_eq!(evm.block, evm_env.block_env); // Default spec ID - assert_eq!(evm.handler.spec_id(), SpecId::LATEST); - - // No Optimism - assert_eq!(evm.handler.cfg, HandlerCfg { spec_id: SpecId::LATEST, ..Default::default() }); + assert_eq!(evm.cfg.spec, SpecId::LATEST); } #[test] @@ -407,18 +278,15 @@ mod tests { let db = CacheDB::>::default(); - let evm_env = EvmEnv { spec: SpecId::CONSTANTINOPLE, ..Default::default() }; + let evm_env = EvmEnv { + cfg_env: CfgEnv::new().with_spec(SpecId::CONSTANTINOPLE), + ..Default::default() + }; let evm = evm_config.evm_with_env(db, evm_env); // Check that the spec ID is setup properly - assert_eq!(evm.handler.spec_id(), SpecId::PETERSBURG); - - // No Optimism - assert_eq!( - evm.handler.cfg, - HandlerCfg { spec_id: SpecId::PETERSBURG, ..Default::default() } - ); + assert_eq!(evm.cfg.spec, SpecId::CONSTANTINOPLE); } #[test] @@ -429,16 +297,11 @@ mod tests { let evm_env = EvmEnv::default(); - let evm = evm_config.evm_with_env_and_inspector(db, evm_env.clone(), NoOpInspector); + let evm = evm_config.evm_with_env_and_inspector(db, evm_env.clone(), NoOpInspector {}); // Check that the EVM environment is set to default values - assert_eq!(evm.context.evm.env.block, evm_env.block_env); - assert_eq!(evm.context.evm.env.cfg, evm_env.cfg_env); - assert_eq!(evm.context.external, NoOpInspector); - assert_eq!(evm.handler.spec_id(), SpecId::LATEST); - - // No Optimism - assert_eq!(evm.handler.cfg, HandlerCfg { spec_id: SpecId::LATEST, ..Default::default() }); + assert_eq!(evm.block, evm_env.block_env); + assert_eq!(evm.cfg, evm_env.cfg_env); } #[test] @@ -449,18 +312,13 @@ mod tests { let cfg_env = CfgEnv::default().with_chain_id(111); let block = BlockEnv::default(); - let evm_env = - EvmEnv { cfg_env: cfg_env.clone(), block_env: block, spec: Default::default() }; + let evm_env = EvmEnv { cfg_env: cfg_env.clone(), block_env: block }; - let evm = evm_config.evm_with_env_and_inspector(db, evm_env, NoOpInspector); + let evm = evm_config.evm_with_env_and_inspector(db, evm_env, NoOpInspector {}); // Check that the EVM environment is set with custom configuration - assert_eq!(evm.context.evm.env.cfg, cfg_env); - assert_eq!(evm.context.external, NoOpInspector); - assert_eq!(evm.handler.spec_id(), SpecId::LATEST); - - // No Optimism - assert_eq!(evm.handler.cfg, HandlerCfg { spec_id: SpecId::LATEST, ..Default::default() }); + assert_eq!(evm.cfg, cfg_env); + assert_eq!(evm.cfg.spec, SpecId::LATEST); } #[test] @@ -470,23 +328,15 @@ mod tests { let db = CacheDB::>::default(); // Create custom block and tx environment - let block = BlockEnv { - basefee: U256::from(1000), - gas_limit: U256::from(10_000_000), - number: U256::from(42), - ..Default::default() - }; + let block = + BlockEnv { basefee: 1000, gas_limit: 10_000_000, number: 42, ..Default::default() }; let evm_env = EvmEnv { block_env: block, ..Default::default() }; - let evm = evm_config.evm_with_env_and_inspector(db, evm_env.clone(), NoOpInspector); + let evm = evm_config.evm_with_env_and_inspector(db, evm_env.clone(), NoOpInspector {}); // Verify that the block and transaction environments are set correctly - assert_eq!(evm.context.evm.env.block, evm_env.block_env); - assert_eq!(evm.context.external, NoOpInspector); - assert_eq!(evm.handler.spec_id(), SpecId::LATEST); - - // No Optimism - assert_eq!(evm.handler.cfg, HandlerCfg { spec_id: SpecId::LATEST, ..Default::default() }); + assert_eq!(evm.block, evm_env.block_env); + assert_eq!(evm.cfg.spec, SpecId::LATEST); } #[test] @@ -495,21 +345,16 @@ mod tests { let evm_config = EthEvmConfig::new(MAINNET.clone()); let db = CacheDB::>::default(); - let evm_env = EvmEnv { spec: SpecId::CONSTANTINOPLE, ..Default::default() }; + let evm_env = EvmEnv { + cfg_env: CfgEnv::new().with_spec(SpecId::CONSTANTINOPLE), + ..Default::default() + }; - let evm = evm_config.evm_with_env_and_inspector(db, evm_env.clone(), NoOpInspector); + let evm = evm_config.evm_with_env_and_inspector(db, evm_env.clone(), NoOpInspector {}); // Check that the spec ID is set properly - assert_eq!(evm.handler.spec_id(), SpecId::PETERSBURG); - assert_eq!(evm.context.evm.env.block, evm_env.block_env); - assert_eq!(evm.context.evm.env.cfg, evm_env.cfg_env); - assert_eq!(evm.context.evm.env.tx, Default::default()); - assert_eq!(evm.context.external, NoOpInspector); - - // No Optimism - assert_eq!( - evm.handler.cfg, - HandlerCfg { spec_id: SpecId::PETERSBURG, ..Default::default() } - ); + assert_eq!(evm.block, evm_env.block_env); + assert_eq!(evm.cfg, evm_env.cfg_env); + assert_eq!(evm.tx, Default::default()); } } diff --git a/crates/ethereum/node/src/node.rs b/crates/ethereum/node/src/node.rs index 40ac74dee..6baa88f45 100644 --- a/crates/ethereum/node/src/node.rs +++ b/crates/ethereum/node/src/node.rs @@ -34,7 +34,7 @@ use reth_transaction_pool::{ TransactionValidationTaskExecutor, }; use reth_trie_db::MerklePatriciaTrie; -use revm::primitives::TxEnv; +use revm::context::TxEnv; use std::sync::Arc; /// Type configuration for a regular Ethereum node. diff --git a/crates/ethereum/node/tests/e2e/utils.rs b/crates/ethereum/node/tests/e2e/utils.rs index d33dc3650..a2928e212 100644 --- a/crates/ethereum/node/tests/e2e/utils.rs +++ b/crates/ethereum/node/tests/e2e/utils.rs @@ -1,4 +1,4 @@ -use alloy_eips::{BlockId, BlockNumberOrTag}; +use alloy_eips::{eip2930::AccessListItem, eip7702::Authorization, BlockId, BlockNumberOrTag}; use alloy_primitives::{bytes, Address, B256, U256}; use alloy_provider::{ network::{ @@ -16,7 +16,6 @@ use reth_ethereum_primitives::TxType; use reth_node_api::NodeTypesWithDBAdapter; use reth_node_ethereum::EthereumNode; use reth_provider::FullProvider; -use revm::primitives::{AccessListItem, Authorization}; /// Helper function to create a new eth payload attributes pub(crate) fn eth_payload_attributes(timestamp: u64) -> EthPayloadBuilderAttributes { diff --git a/crates/ethereum/payload/src/lib.rs b/crates/ethereum/payload/src/lib.rs index 568307c2a..5b7fba221 100644 --- a/crates/ethereum/payload/src/lib.rs +++ b/crates/ethereum/payload/src/lib.rs @@ -20,7 +20,7 @@ use reth_chainspec::{ChainSpec, ChainSpecProvider, EthChainSpec, EthereumHardfor use reth_errors::RethError; use reth_ethereum_primitives::{Block, BlockBody, Receipt, TransactionSigned}; use reth_evm::{ - env::EvmEnv, system_calls::SystemCaller, ConfigureEvm, Evm, EvmError, InvalidTxError, + system_calls::SystemCaller, ConfigureEvm, Evm, EvmEnv, EvmError, InvalidTxError, NextBlockEnvAttributes, }; use reth_evm_ethereum::{eip6110::parse_deposits_from_receipts, EthEvmConfig}; @@ -32,15 +32,17 @@ use reth_primitives_traits::{ proofs::{self}, Block as _, SignedTransaction, }; -use reth_revm::database::StateProviderDatabase; +use reth_revm::{ + database::StateProviderDatabase, + db::{states::bundle_state::BundleRetention, State}, +}; use reth_storage_api::StateProviderFactory; use reth_transaction_pool::{ error::InvalidPoolTransactionError, BestTransactions, BestTransactionsAttributes, PoolTransaction, TransactionPool, ValidPoolTransaction, }; use revm::{ - db::{states::bundle_state::BundleRetention, State}, - primitives::ResultAndState, + context_interface::{result::ResultAndState, Block as _}, DatabaseCommit, }; use std::sync::Arc; @@ -186,19 +188,19 @@ where debug!(target: "payload_builder", id=%attributes.id, parent_header = ?parent_header.hash(), parent_number = parent_header.number, "building new payload"); let mut cumulative_gas_used = 0; - let block_gas_limit: u64 = evm_env.block_env.gas_limit.to::(); - let base_fee = evm_env.block_env.basefee.to::(); + let block_gas_limit: u64 = evm_env.block_env.gas_limit; + let base_fee = evm_env.block_env.basefee; let mut executed_txs = Vec::new(); let mut best_txs = best_txs(BestTransactionsAttributes::new( base_fee, - evm_env.block_env.get_blob_gasprice().map(|gasprice| gasprice as u64), + evm_env.block_env.blob_gasprice().map(|gasprice| gasprice as u64), )); let mut total_fees = U256::ZERO; - let block_number = evm_env.block_env.number.to::(); - let beneficiary = evm_env.block_env.coinbase; + let block_number = evm_env.block_env.number; + let beneficiary = evm_env.block_env.beneficiary; let mut system_caller = SystemCaller::new(evm_config.clone(), chain_spec.clone()); diff --git a/crates/ethereum/primitives/Cargo.toml b/crates/ethereum/primitives/Cargo.toml index 9cf44822e..66d94679e 100644 --- a/crates/ethereum/primitives/Cargo.toml +++ b/crates/ethereum/primitives/Cargo.toml @@ -18,14 +18,14 @@ reth-primitives-traits.workspace = true reth-zstd-compressors = { workspace = true, optional = true } # ethereum -alloy-eips.workspace = true +alloy-eips = { workspace = true, features = ["k256"] } alloy-primitives.workspace = true alloy-network = { workspace = true, optional = true } alloy-consensus = { workspace = true, features = ["serde"] } alloy-serde = { workspace = true, optional = true } alloy-rlp.workspace = true alloy-rpc-types-eth = { workspace = true, optional = true } -revm-primitives.workspace = true +revm-context.workspace = true # misc arbitrary = { workspace = true, optional = true, features = ["derive"] } @@ -65,9 +65,9 @@ std = [ "alloy-eips/std", "derive_more/std", "secp256k1?/std", - "revm-primitives/std", "alloy-serde?/std", "alloy-rpc-types-eth?/std", + "revm-context/std", ] reth-codec = [ "std", @@ -84,7 +84,6 @@ arbitrary = [ "reth-codecs?/arbitrary", "reth-primitives-traits/arbitrary", "alloy-eips/arbitrary", - "revm-primitives/arbitrary", "alloy-serde?/arbitrary", "alloy-rpc-types-eth?/arbitrary", ] diff --git a/crates/ethereum/primitives/src/transaction.rs b/crates/ethereum/primitives/src/transaction.rs index 7a481d3b6..f21af0d14 100644 --- a/crates/ethereum/primitives/src/transaction.rs +++ b/crates/ethereum/primitives/src/transaction.rs @@ -21,7 +21,7 @@ use reth_primitives_traits::{ transaction::{error::TransactionConversionError, signed::RecoveryError}, FillTxEnv, InMemorySize, SignedTransaction, }; -use revm_primitives::{AuthorizationList, TxEnv}; +use revm_context::TxEnv; use serde::{Deserialize, Serialize}; macro_rules! delegate { @@ -750,81 +750,89 @@ impl reth_codecs::Compact for TransactionSigned { } } -impl FillTxEnv for TransactionSigned { +impl FillTxEnv for TransactionSigned { fn fill_tx_env(&self, tx_env: &mut TxEnv, sender: Address) { - tx_env.caller = sender; - match self.as_ref() { - Transaction::Legacy(tx) => { - tx_env.gas_limit = tx.gas_limit; - tx_env.gas_price = U256::from(tx.gas_price); - tx_env.gas_priority_fee = None; - tx_env.transact_to = tx.to; - tx_env.value = tx.value; - tx_env.data = tx.input.clone(); - tx_env.chain_id = tx.chain_id; - tx_env.nonce = Some(tx.nonce); - tx_env.access_list.clear(); - tx_env.blob_hashes.clear(); - tx_env.max_fee_per_blob_gas.take(); - tx_env.authorization_list = None; - } - Transaction::Eip2930(tx) => { - tx_env.gas_limit = tx.gas_limit; - tx_env.gas_price = U256::from(tx.gas_price); - tx_env.gas_priority_fee = None; - tx_env.transact_to = tx.to; - tx_env.value = tx.value; - tx_env.data = tx.input.clone(); - tx_env.chain_id = Some(tx.chain_id); - tx_env.nonce = Some(tx.nonce); - tx_env.access_list.clone_from(&tx.access_list.0); - tx_env.blob_hashes.clear(); - tx_env.max_fee_per_blob_gas.take(); - tx_env.authorization_list = None; - } - Transaction::Eip1559(tx) => { - tx_env.gas_limit = tx.gas_limit; - tx_env.gas_price = U256::from(tx.max_fee_per_gas); - tx_env.gas_priority_fee = Some(U256::from(tx.max_priority_fee_per_gas)); - tx_env.transact_to = tx.to; - tx_env.value = tx.value; - tx_env.data = tx.input.clone(); - tx_env.chain_id = Some(tx.chain_id); - tx_env.nonce = Some(tx.nonce); - tx_env.access_list.clone_from(&tx.access_list.0); - tx_env.blob_hashes.clear(); - tx_env.max_fee_per_blob_gas.take(); - tx_env.authorization_list = None; - } - Transaction::Eip4844(tx) => { - tx_env.gas_limit = tx.gas_limit; - tx_env.gas_price = U256::from(tx.max_fee_per_gas); - tx_env.gas_priority_fee = Some(U256::from(tx.max_priority_fee_per_gas)); - tx_env.transact_to = TxKind::Call(tx.to); - tx_env.value = tx.value; - tx_env.data = tx.input.clone(); - tx_env.chain_id = Some(tx.chain_id); - tx_env.nonce = Some(tx.nonce); - tx_env.access_list.clone_from(&tx.access_list.0); - tx_env.blob_hashes.clone_from(&tx.blob_versioned_hashes); - tx_env.max_fee_per_blob_gas = Some(U256::from(tx.max_fee_per_blob_gas)); - tx_env.authorization_list = None; - } - Transaction::Eip7702(tx) => { - tx_env.gas_limit = tx.gas_limit; - tx_env.gas_price = U256::from(tx.max_fee_per_gas); - tx_env.gas_priority_fee = Some(U256::from(tx.max_priority_fee_per_gas)); - tx_env.transact_to = tx.to.into(); - tx_env.value = tx.value; - tx_env.data = tx.input.clone(); - tx_env.chain_id = Some(tx.chain_id); - tx_env.nonce = Some(tx.nonce); - tx_env.access_list.clone_from(&tx.access_list.0); - tx_env.blob_hashes.clear(); - tx_env.max_fee_per_blob_gas.take(); - tx_env.authorization_list = - Some(AuthorizationList::Signed(tx.authorization_list.clone())); - } + *tx_env = match self.as_ref() { + Transaction::Legacy(tx) => TxEnv { + gas_limit: tx.gas_limit, + gas_price: tx.gas_price, + gas_priority_fee: None, + kind: tx.to, + value: tx.value, + data: tx.input.clone(), + chain_id: tx.chain_id, + nonce: tx.nonce, + access_list: Default::default(), + blob_hashes: Default::default(), + max_fee_per_blob_gas: Default::default(), + authorization_list: Default::default(), + tx_type: 0, + caller: sender, + }, + Transaction::Eip2930(tx) => TxEnv { + gas_limit: tx.gas_limit, + gas_price: tx.gas_price, + gas_priority_fee: None, + kind: tx.to, + value: tx.value, + data: tx.input.clone(), + chain_id: Some(tx.chain_id), + nonce: tx.nonce, + access_list: tx.access_list.clone(), + blob_hashes: Default::default(), + max_fee_per_blob_gas: Default::default(), + authorization_list: Default::default(), + tx_type: 1, + caller: sender, + }, + Transaction::Eip1559(tx) => TxEnv { + gas_limit: tx.gas_limit, + gas_price: tx.max_fee_per_gas, + gas_priority_fee: Some(tx.max_priority_fee_per_gas), + kind: tx.to, + value: tx.value, + data: tx.input.clone(), + chain_id: Some(tx.chain_id), + nonce: tx.nonce, + access_list: tx.access_list.clone(), + blob_hashes: Default::default(), + max_fee_per_blob_gas: Default::default(), + authorization_list: Default::default(), + tx_type: 2, + caller: sender, + }, + Transaction::Eip4844(tx) => TxEnv { + gas_limit: tx.gas_limit, + gas_price: tx.max_fee_per_gas, + gas_priority_fee: Some(tx.max_priority_fee_per_gas), + kind: TxKind::Call(tx.to), + value: tx.value, + data: tx.input.clone(), + chain_id: Some(tx.chain_id), + nonce: tx.nonce, + access_list: tx.access_list.clone(), + blob_hashes: tx.blob_versioned_hashes.clone(), + max_fee_per_blob_gas: tx.max_fee_per_blob_gas, + authorization_list: Default::default(), + tx_type: 3, + caller: sender, + }, + Transaction::Eip7702(tx) => TxEnv { + gas_limit: tx.gas_limit, + gas_price: tx.max_fee_per_gas, + gas_priority_fee: Some(tx.max_priority_fee_per_gas), + kind: TxKind::Call(tx.to), + value: tx.value, + data: tx.input.clone(), + chain_id: Some(tx.chain_id), + nonce: tx.nonce, + access_list: tx.access_list.clone(), + blob_hashes: Default::default(), + max_fee_per_blob_gas: Default::default(), + authorization_list: tx.authorization_list.clone(), + tx_type: 4, + caller: sender, + }, } } } diff --git a/crates/evm/Cargo.toml b/crates/evm/Cargo.toml index 909261353..e78281ea9 100644 --- a/crates/evm/Cargo.toml +++ b/crates/evm/Cargo.toml @@ -24,11 +24,13 @@ reth-primitives-traits.workspace = true reth-storage-errors.workspace = true revm.workspace = true -revm-primitives.workspace = true +revm-database.workspace = true +revm-optimism = { workspace = true, optional = true } # alloy alloy-primitives.workspace = true alloy-eips.workspace = true +alloy-evm.workspace = true alloy-consensus.workspace = true auto_impl.workspace = true @@ -53,15 +55,17 @@ std = [ "alloy-eips/std", "alloy-primitives/std", "alloy-consensus/std", - "revm-primitives/std", "revm/std", "reth-ethereum-forks/std", "reth-ethereum-primitives/std", "reth-chainspec/std", "reth-consensus-common/std", + "alloy-evm/std", + "revm-database/std", + "revm-optimism?/std", "reth-execution-errors/std", - "reth-storage-errors/std", "reth-execution-types/std", + "reth-storage-errors/std", ] test-utils = [ "dep:parking_lot", @@ -72,3 +76,8 @@ test-utils = [ "reth-primitives-traits/test-utils", "revm/test-utils", ] +op = [ + "revm-optimism", + "alloy-evm/op", + "reth-primitives-traits/op", +] diff --git a/crates/evm/execution-errors/Cargo.toml b/crates/evm/execution-errors/Cargo.toml index 1047fdbd2..f71e904f3 100644 --- a/crates/evm/execution-errors/Cargo.toml +++ b/crates/evm/execution-errors/Cargo.toml @@ -19,6 +19,8 @@ alloy-rlp.workspace = true alloy-eips.workspace = true nybbles.workspace = true +revm-database-interface.workspace = true + thiserror.workspace = true [features] @@ -29,5 +31,6 @@ std = [ "alloy-rlp/std", "thiserror/std", "nybbles/std", + "revm-database-interface/std", "reth-storage-errors/std", ] diff --git a/crates/evm/execution-errors/src/lib.rs b/crates/evm/execution-errors/src/lib.rs index 676161a21..b309c2599 100644 --- a/crates/evm/execution-errors/src/lib.rs +++ b/crates/evm/execution-errors/src/lib.rs @@ -149,6 +149,8 @@ impl From for BlockExecutionError { } } +impl revm_database_interface::DBErrorMarker for BlockExecutionError {} + /// Internal (i.e., not validation or consensus related) `BlockExecutor` Errors #[derive(Error, Debug)] pub enum InternalBlockExecutionError { diff --git a/crates/evm/execution-types/Cargo.toml b/crates/evm/execution-types/Cargo.toml index d504892b8..19a75c3ed 100644 --- a/crates/evm/execution-types/Cargo.toml +++ b/crates/evm/execution-types/Cargo.toml @@ -17,6 +17,7 @@ reth-execution-errors.workspace = true reth-trie-common.workspace = true revm.workspace = true +revm-database.workspace = true # alloy alloy-consensus.workspace = true @@ -36,7 +37,7 @@ reth-ethereum-primitives.workspace = true [features] default = ["std"] -optimism = ["revm/optimism"] +optimism = [] serde = [ "dep:serde", "rand/serde", @@ -45,6 +46,7 @@ serde = [ "alloy-primitives/serde", "reth-primitives-traits/serde", "alloy-consensus/serde", + "revm-database/serde", "reth-trie-common/serde", ] serde-bincode-compat = [ @@ -64,8 +66,9 @@ std = [ "reth-primitives-traits/std", "alloy-consensus/std", "serde_with?/std", - "reth-trie-common/std", + "derive_more/std", "reth-ethereum-primitives/std", "reth-execution-errors/std", - "derive_more/std", + "reth-trie-common/std", + "revm-database/std", ] diff --git a/crates/evm/execution-types/src/chain.rs b/crates/evm/execution-types/src/chain.rs index a5c000adc..064cd62a1 100644 --- a/crates/evm/execution-types/src/chain.rs +++ b/crates/evm/execution-types/src/chain.rs @@ -12,7 +12,7 @@ use reth_primitives_traits::{ RecoveredBlock, SealedHeader, SignedTransaction, }; use reth_trie_common::updates::TrieUpdates; -use revm::db::BundleState; +use revm_database::BundleState; /// A chain of blocks and their final state. /// @@ -706,7 +706,7 @@ mod tests { use alloy_consensus::TxType; use alloy_primitives::{Address, B256}; use reth_ethereum_primitives::Receipt; - use revm::primitives::{AccountInfo, HashMap}; + use revm::{primitives::HashMap, state::AccountInfo}; #[test] fn chain_append() { diff --git a/crates/evm/execution-types/src/execute.rs b/crates/evm/execution-types/src/execute.rs index 463c5f641..eadb68aa8 100644 --- a/crates/evm/execution-types/src/execute.rs +++ b/crates/evm/execution-types/src/execute.rs @@ -1,6 +1,6 @@ use alloc::vec::Vec; use alloy_eips::eip7685::Requests; -use revm::db::BundleState; +use revm_database::BundleState; /// The result of executing a block. #[derive(Debug, Clone, PartialEq, Eq)] diff --git a/crates/evm/execution-types/src/execution_outcome.rs b/crates/evm/execution-types/src/execution_outcome.rs index 3cf72526d..fff6d2019 100644 --- a/crates/evm/execution-types/src/execution_outcome.rs +++ b/crates/evm/execution-types/src/execution_outcome.rs @@ -4,10 +4,8 @@ use alloy_eips::eip7685::Requests; use alloy_primitives::{logs_bloom, map::HashMap, Address, BlockNumber, Bloom, Log, B256, U256}; use reth_primitives_traits::{Account, Bytecode, Receipt, StorageEntry}; use reth_trie_common::{HashedPostState, KeyHasher}; -use revm::{ - db::{states::BundleState, BundleAccount}, - primitives::AccountInfo, -}; +use revm::state::AccountInfo; +use revm_database::{states::BundleState, BundleAccount}; /// Represents a changed account #[derive(Clone, Copy, Debug, PartialEq, Eq)] diff --git a/crates/evm/src/aliases.rs b/crates/evm/src/aliases.rs index ef15aaf74..aae9faf4b 100644 --- a/crates/evm/src/aliases.rs +++ b/crates/evm/src/aliases.rs @@ -1,5 +1,6 @@ //! Helper aliases when working with [`NodePrimitives`] and the traits in this crate. use crate::{ConfigureEvm, ConfigureEvmEnv}; +use alloy_evm::{EvmEnv, EvmFactory}; use reth_primitives_traits::NodePrimitives; /// This is a type alias to make type bounds simpler when we have a [`NodePrimitives`] and need a @@ -29,3 +30,16 @@ where C: ConfigureEvm
, { } + +/// Helper to access [`EvmFactory::Error`] for a given [`ConfigureEvm`]. +pub type EvmErrorFor = <::EvmFactory as EvmFactory< + EvmEnv<::Spec>, +>>::Error; + +/// Helper to access [`EvmFactory::HaltReason`] for a given [`ConfigureEvm`]. +pub type HaltReasonFor = <::EvmFactory as EvmFactory< + EvmEnv<::Spec>, +>>::HaltReason; + +/// Helper to access [`ConfigureEvmEnv::Spec`] for a given [`ConfigureEvmEnv`]. +pub type SpecFor = ::Spec; diff --git a/crates/evm/src/either.rs b/crates/evm/src/either.rs index 132a35a44..7aaded54c 100644 --- a/crates/evm/src/either.rs +++ b/crates/evm/src/either.rs @@ -82,7 +82,7 @@ where state: F, ) -> Result::Receipt>, Self::Error> where - F: FnMut(&revm::db::State), + F: FnMut(&revm_database::State), { match self { Self::Left(a) => a.execute_with_state_closure(block, state), @@ -90,7 +90,7 @@ where } } - fn into_state(self) -> revm::db::State { + fn into_state(self) -> revm_database::State { match self { Self::Left(a) => a.into_state(), Self::Right(b) => b.into_state(), diff --git a/crates/evm/src/env.rs b/crates/evm/src/env.rs deleted file mode 100644 index 8b10c48f4..000000000 --- a/crates/evm/src/env.rs +++ /dev/null @@ -1,48 +0,0 @@ -use revm::primitives::{BlockEnv, CfgEnvWithHandlerCfg}; -use revm_primitives::{CfgEnv, SpecId}; - -/// Container type that holds both the configuration and block environment for EVM execution. -#[derive(Debug, Clone, Default)] -pub struct EvmEnv { - /// The configuration environment with handler settings - pub cfg_env: CfgEnv, - /// The block environment containing block-specific data - pub block_env: BlockEnv, - /// The spec id of the chain. Specifies which hardfork is currently active, `Spec` type will - /// most likely be an enum over hardforks. - pub spec: Spec, -} - -impl EvmEnv { - /// Create a new `EvmEnv` from its components. - /// - /// # Arguments - /// - /// * `cfg_env_with_handler_cfg` - The configuration environment with handler settings - /// * `block` - The block environment containing block-specific data - pub const fn new(cfg_env: CfgEnv, block_env: BlockEnv, spec: Spec) -> Self { - Self { cfg_env, spec, block_env } - } - - /// Returns a reference to the block environment. - pub const fn block_env(&self) -> &BlockEnv { - &self.block_env - } - - /// Returns a reference to the configuration environment. - pub const fn cfg_env(&self) -> &CfgEnv { - &self.cfg_env - } - - /// Returns the spec id of the chain - pub const fn spec_id(&self) -> &Spec { - &self.spec - } -} - -impl From<(CfgEnvWithHandlerCfg, BlockEnv)> for EvmEnv { - fn from((cfg_env_with_handler_cfg, block_env): (CfgEnvWithHandlerCfg, BlockEnv)) -> Self { - let CfgEnvWithHandlerCfg { cfg_env, handler_cfg } = cfg_env_with_handler_cfg; - Self { cfg_env, spec: handler_cfg.spec_id, block_env } - } -} diff --git a/crates/evm/src/error.rs b/crates/evm/src/error.rs deleted file mode 100644 index 55dac3b57..000000000 --- a/crates/evm/src/error.rs +++ /dev/null @@ -1,49 +0,0 @@ -use revm_primitives::{EVMError, InvalidTransaction}; - -/// Abstraction over transaction validation error. -pub trait InvalidTxError: core::error::Error + Send + Sync + 'static { - /// Returns whether the error cause by transaction having a nonce lower than expected. - fn is_nonce_too_low(&self) -> bool; -} - -impl InvalidTxError for InvalidTransaction { - fn is_nonce_too_low(&self) -> bool { - matches!(self, Self::NonceTooLow { .. }) - } -} - -/// Abstraction over errors that can occur during EVM execution. -/// -/// It's assumed that errors can occur either because of an invalid transaction, meaning that other -/// transaction might still result in successful execution, or because of a general EVM -/// misconfiguration. -/// -/// If caller occurs a error different from [`EvmError::InvalidTransaction`], it should most likely -/// be treated as fatal error flagging some EVM misconfiguration. -pub trait EvmError: core::error::Error + Send + Sync + 'static { - /// Errors which might occur as a result of an invalid transaction. i.e unrelated to general EVM - /// configuration. - type InvalidTransaction: InvalidTxError; - - /// Returns the [`EvmError::InvalidTransaction`] if the error is an invalid transaction error. - fn as_invalid_tx_err(&self) -> Option<&Self::InvalidTransaction>; - - /// Returns `true` if the error is an invalid transaction error. - fn is_invalid_tx_err(&self) -> bool { - self.as_invalid_tx_err().is_some() - } -} - -impl EvmError for EVMError -where - DBError: core::error::Error + Send + Sync + 'static, -{ - type InvalidTransaction = InvalidTransaction; - - fn as_invalid_tx_err(&self) -> Option<&Self::InvalidTransaction> { - match self { - Self::Transaction(err) => Some(err), - _ => None, - } - } -} diff --git a/crates/evm/src/execute.rs b/crates/evm/src/execute.rs index 7cb0e7378..1a75bad5a 100644 --- a/crates/evm/src/execute.rs +++ b/crates/evm/src/execute.rs @@ -18,8 +18,8 @@ use alloy_primitives::{ }; use reth_consensus::ConsensusError; use reth_primitives::{NodePrimitives, Receipt, RecoveredBlock}; -use revm::db::{states::bundle_state::BundleRetention, State}; -use revm_primitives::{Account, AccountStatus, EvmState}; +use revm::state::{Account, AccountStatus, EvmState}; +use revm_database::{states::bundle_state::BundleRetention, State}; /// A type that knows how to execute a block. It is assumed to operate on a /// [`crate::Evm`] internally and use [`State`] as database. @@ -378,8 +378,12 @@ mod tests { use core::marker::PhantomData; use reth_chainspec::{ChainSpec, MAINNET}; use reth_primitives::EthPrimitives; - use revm::db::{CacheDB, EmptyDBTyped}; - use revm_primitives::{address, bytes, AccountInfo, KECCAK_EMPTY}; + use revm::{ + database_interface::EmptyDBTyped, + primitives::{address, bytes, KECCAK_EMPTY}, + state::AccountInfo, + }; + use revm_database::CacheDB; use std::sync::Arc; #[derive(Clone, Default)] diff --git a/crates/evm/src/lib.rs b/crates/evm/src/lib.rs index 42f3012de..ce60e6586 100644 --- a/crates/evm/src/lib.rs +++ b/crates/evm/src/lib.rs @@ -19,21 +19,19 @@ extern crate alloc; use alloy_consensus::transaction::Recovered; use alloy_eips::eip2930::AccessList; -use alloy_primitives::{Address, Bytes, B256, U256}; +pub use alloy_evm::evm::EvmFactory; +use alloy_primitives::{Address, B256}; use core::fmt::Debug; use reth_primitives_traits::{BlockHeader, SignedTransaction}; -use revm::{DatabaseCommit, GetInspector}; -use revm_primitives::{BlockEnv, ResultAndState, TxEnv, TxKind}; +use revm::{ + context::TxEnv, + inspector::{Inspector, NoOpInspector}, +}; pub mod batch; pub mod either; /// EVM environment configuration. -pub mod env; -/// EVM error types. -mod error; -pub use error::*; pub mod execute; -pub use env::EvmEnv; mod aliases; pub use aliases::*; @@ -47,69 +45,28 @@ pub mod system_calls; /// test helpers for mocking executor pub mod test_utils; -/// An abstraction over EVM. -/// -/// At this point, assumed to be implemented on wrappers around [`revm::Evm`]. -pub trait Evm { - /// Database type held by the EVM. - type DB; - /// Transaction environment - type Tx; - /// Error type returned by EVM. Contains either errors related to invalid transactions or - /// internal irrecoverable execution errors. - type Error; - /// Halt reason. Enum over all possible reasons for halting the execution. When execution halts, - /// it means that transaction is valid, however, it's execution was interrupted (e.g because of - /// running out of gas or overflowing stack). - type HaltReason; +pub use alloy_evm::{Database, Evm, EvmEnv, EvmError, InvalidTxError}; - /// Reference to [`BlockEnv`]. - fn block(&self) -> &BlockEnv; - - /// Executes the given transaction. - fn transact(&mut self, tx: Self::Tx) -> Result; - - /// Executes a system call. - fn transact_system_call( - &mut self, - caller: Address, - contract: Address, - data: Bytes, - ) -> Result; - - /// Returns a mutable reference to the underlying database. - fn db_mut(&mut self) -> &mut Self::DB; - - /// Executes a transaction and commits the state changes to the underlying database. - fn transact_commit(&mut self, tx_env: Self::Tx) -> Result - where - Self::DB: DatabaseCommit, - { - let result = self.transact(tx_env)?; - self.db_mut().commit(result.state.clone()); - - Ok(result) - } +/// Helper trait to bound [`Inspector`] for a [`ConfigureEvm`]. +pub trait InspectorFor: + Inspector<>>::Context> +{ +} +impl InspectorFor for T +where + DB: Database, + Evm: ConfigureEvm, + T: Inspector<>>::Context>, +{ } -/// Helper trait to bound [`revm::Database::Error`] with common requirements. -pub trait Database: revm::Database {} -impl Database for T where T: revm::Database {} /// Trait for configuring the EVM for executing full blocks. pub trait ConfigureEvm: ConfigureEvmEnv { - /// The EVM implementation. - type Evm<'a, DB: Database + 'a, I: 'a>: Evm< - Tx = Self::TxEnv, - DB = DB, - Error = Self::EvmError, - HaltReason = Self::HaltReason, - >; + /// The EVM factory. + type EvmFactory: EvmFactory, Tx = Self::TxEnv>; - /// The error type returned by the EVM. See [`Evm::Error`]. - type EvmError: EvmError; - - /// Halt reason type returned by the EVM. See [`Evm::HaltReason`]. - type HaltReason; + /// Provides a reference to [`EvmFactory`] implementation. + fn evm_factory(&self) -> &Self::EvmFactory; /// Returns a new EVM with the given database configured with the given environment settings, /// including the spec id and transaction environment. @@ -119,7 +76,9 @@ pub trait ConfigureEvm: ConfigureEvmEnv { &self, db: DB, evm_env: EvmEnv, - ) -> Self::Evm<'_, DB, ()>; + ) -> >>::Evm { + self.evm_factory().create_evm(db, evm_env) + } /// Returns a new EVM with the given database configured with `cfg` and `block_env` /// configuration derived from the given header. Relies on @@ -128,7 +87,11 @@ pub trait ConfigureEvm: ConfigureEvmEnv { /// # Caution /// /// This does not initialize the tx environment. - fn evm_for_block(&self, db: DB, header: &Self::Header) -> Self::Evm<'_, DB, ()> { + fn evm_for_block( + &self, + db: DB, + header: &Self::Header, + ) -> >>::Evm { let evm_env = self.evm_env(header); self.evm_with_env(db, evm_env) } @@ -144,10 +107,13 @@ pub trait ConfigureEvm: ConfigureEvmEnv { db: DB, evm_env: EvmEnv, inspector: I, - ) -> Self::Evm<'_, DB, I> + ) -> >>::Evm where DB: Database, - I: GetInspector; + I: InspectorFor, + { + self.evm_factory().create_evm_with_inspector(db, evm_env, inspector) + } } impl<'b, T> ConfigureEvm for &'b T @@ -155,11 +121,17 @@ where T: ConfigureEvm, &'b T: ConfigureEvmEnv
, { - type Evm<'a, DB: Database + 'a, I: 'a> = T::Evm<'a, DB, I>; - type EvmError = T::EvmError; - type HaltReason = T::HaltReason; + type EvmFactory = T::EvmFactory; - fn evm_for_block(&self, db: DB, header: &Self::Header) -> Self::Evm<'_, DB, ()> { + fn evm_factory(&self) -> &Self::EvmFactory { + (*self).evm_factory() + } + + fn evm_for_block( + &self, + db: DB, + header: &Self::Header, + ) -> >>::Evm { (*self).evm_for_block(db, header) } @@ -167,7 +139,7 @@ where &self, db: DB, evm_env: EvmEnv, - ) -> Self::Evm<'_, DB, ()> { + ) -> >>::Evm { (*self).evm_with_env(db, evm_env) } @@ -176,10 +148,10 @@ where db: DB, evm_env: EvmEnv, inspector: I, - ) -> Self::Evm<'_, DB, I> + ) -> >>::Evm where DB: Database, - I: GetInspector, + I: InspectorFor, { (*self).evm_with_env_and_inspector(db, evm_env, inspector) } @@ -204,7 +176,7 @@ pub trait ConfigureEvmEnv: Send + Sync + Unpin + Clone + 'static { type Error: core::error::Error + Send + Sync; /// Identifier of the EVM specification. - type Spec: Into + Debug + Copy + Send + Sync; + type Spec: Debug + Copy + Send + Sync + 'static; /// Returns a [`TxEnv`] from a transaction and [`Address`]. fn tx_env(&self, transaction: &Self::Transaction, signer: Address) -> Self::TxEnv; @@ -248,11 +220,8 @@ pub struct NextBlockEnvAttributes { /// Abstraction over transaction environment. pub trait TransactionEnv: - Into + Debug + Default + Clone + Send + Sync + 'static + revm::context_interface::Transaction + Debug + Clone + Send + Sync + 'static { - /// Returns configured gas limit. - fn gas_limit(&self) -> u64; - /// Set the gas limit. fn set_gas_limit(&mut self, gas_limit: u64); @@ -263,11 +232,7 @@ pub trait TransactionEnv: } /// Returns the configured nonce. - /// - /// This may return `None`, if the nonce has been intentionally unset in the environment. This - /// is useful in optimizations like transaction prewarming, where nonce checks should be - /// ignored. - fn nonce(&self) -> Option; + fn nonce(&self) -> u64; /// Sets the nonce. fn set_nonce(&mut self, nonce: u64); @@ -278,29 +243,6 @@ pub trait TransactionEnv: self } - /// Unsets the nonce. This should be used when nonce checks for the transaction should be - /// ignored. - /// - /// See [`TransactionEnv::nonce`] for applications where this may be desired. - fn unset_nonce(&mut self); - - /// Constructs a version of this [`TransactionEnv`] that has the nonce unset. - /// - /// See [`TransactionEnv::nonce`] for applications where this may be desired. - fn without_nonce(mut self) -> Self { - self.unset_nonce(); - self - } - - /// Returns configured gas price. - fn gas_price(&self) -> U256; - - /// Returns configured value. - fn value(&self) -> U256; - - /// Caller of the transaction. - fn caller(&self) -> Address; - /// Set access list. fn set_access_list(&mut self, access_list: AccessList); @@ -309,56 +251,41 @@ pub trait TransactionEnv: self.set_access_list(access_list); self } - - /// Returns calldata for the transaction. - fn input(&self) -> &Bytes; - - /// Returns [`TxKind`] of the transaction. - fn kind(&self) -> TxKind; } impl TransactionEnv for TxEnv { - fn gas_limit(&self) -> u64 { - self.gas_limit - } - fn set_gas_limit(&mut self, gas_limit: u64) { self.gas_limit = gas_limit; } - fn gas_price(&self) -> U256 { - self.gas_price.to() - } - - fn nonce(&self) -> Option { + fn nonce(&self) -> u64 { self.nonce } fn set_nonce(&mut self, nonce: u64) { - self.nonce = Some(nonce); - } - - fn unset_nonce(&mut self) { - self.nonce = None; - } - - fn value(&self) -> U256 { - self.value - } - - fn caller(&self) -> Address { - self.caller + self.nonce = nonce; } fn set_access_list(&mut self, access_list: AccessList) { - self.access_list = access_list.to_vec(); - } - - fn input(&self) -> &Bytes { - &self.data - } - - fn kind(&self) -> TxKind { - self.transact_to + self.access_list = access_list; + } +} + +#[cfg(feature = "op")] +impl TransactionEnv for revm_optimism::OpTransaction { + fn set_gas_limit(&mut self, gas_limit: u64) { + self.base.set_gas_limit(gas_limit); + } + + fn nonce(&self) -> u64 { + TransactionEnv::nonce(&self.base) + } + + fn set_nonce(&mut self, nonce: u64) { + self.base.set_nonce(nonce); + } + + fn set_access_list(&mut self, access_list: AccessList) { + self.base.set_access_list(access_list); } } diff --git a/crates/evm/src/metrics.rs b/crates/evm/src/metrics.rs index e92a3e9eb..e5895b50c 100644 --- a/crates/evm/src/metrics.rs +++ b/crates/evm/src/metrics.rs @@ -11,8 +11,9 @@ use alloy_consensus::BlockHeader; use metrics::{Counter, Gauge, Histogram}; use reth_execution_types::BlockExecutionOutput; use reth_metrics::Metrics; -use reth_primitives::{NodePrimitives, RecoveredBlock}; -use revm_primitives::EvmState; +use reth_primitives::RecoveredBlock; +use reth_primitives_traits::NodePrimitives; +use revm::state::EvmState; use std::time::Instant; /// Wrapper struct that combines metrics and state hook @@ -143,13 +144,15 @@ impl ExecutorMetrics { mod tests { use super::*; use alloy_eips::eip7685::Requests; + use alloy_primitives::{B256, U256}; use metrics_util::debugging::{DebugValue, DebuggingRecorder, Snapshotter}; use reth_execution_types::BlockExecutionResult; use reth_primitives::EthPrimitives; - use revm::db::{EmptyDB, State}; - use revm_primitives::{ - Account, AccountInfo, AccountStatus, EvmState, EvmStorage, EvmStorageSlot, B256, U256, + use revm::{ + database_interface::EmptyDB, + state::{Account, AccountInfo, AccountStatus, EvmStorage, EvmStorageSlot}, }; + use revm_database::State; use std::sync::mpsc; /// A mock executor that simulates state changes @@ -191,7 +194,7 @@ mod tests { }) } - fn into_state(self) -> revm::db::State { + fn into_state(self) -> revm_database::State { State::builder().with_database(Default::default()).build() } diff --git a/crates/evm/src/noop.rs b/crates/evm/src/noop.rs index a6b155419..b76daead7 100644 --- a/crates/evm/src/noop.rs +++ b/crates/evm/src/noop.rs @@ -1,14 +1,13 @@ //! A no operation block executor implementation. -use reth_execution_errors::BlockExecutionError; -use reth_execution_types::BlockExecutionResult; -use reth_primitives::{NodePrimitives, RecoveredBlock}; - use crate::{ execute::{BlockExecutorProvider, Executor}, system_calls::OnStateHook, Database, }; +use reth_execution_errors::BlockExecutionError; +use reth_execution_types::BlockExecutionResult; +use reth_primitives::{NodePrimitives, RecoveredBlock}; const UNAVAILABLE_FOR_NOOP: &str = "execution unavailable for noop"; @@ -53,7 +52,7 @@ impl Executor for NoopBlockExecutorProvider Err(BlockExecutionError::msg(UNAVAILABLE_FOR_NOOP)) } - fn into_state(self) -> revm::db::State { + fn into_state(self) -> revm_database::State { unreachable!() } diff --git a/crates/evm/src/system_calls/eip2935.rs b/crates/evm/src/system_calls/eip2935.rs index 6b85866d3..b156e7e95 100644 --- a/crates/evm/src/system_calls/eip2935.rs +++ b/crates/evm/src/system_calls/eip2935.rs @@ -1,15 +1,12 @@ //! [EIP-2935](https://eips.ethereum.org/EIPS/eip-2935) system call implementation. -use core::fmt::Display; - +use crate::Evm; use alloc::string::ToString; use alloy_eips::eip2935::HISTORY_STORAGE_ADDRESS; - -use crate::Evm; use alloy_primitives::B256; use reth_chainspec::EthereumHardforks; use reth_execution_errors::{BlockExecutionError, BlockValidationError}; -use revm_primitives::ResultAndState; +use revm::context_interface::result::ResultAndState; /// Applies the pre-block call to the [EIP-2935] blockhashes contract, using the given block, /// chain specification, and EVM. @@ -24,13 +21,13 @@ use revm_primitives::ResultAndState; /// /// [EIP-2935]: https://eips.ethereum.org/EIPS/eip-2935 #[inline] -pub(crate) fn transact_blockhashes_contract_call( +pub(crate) fn transact_blockhashes_contract_call( chain_spec: impl EthereumHardforks, block_timestamp: u64, block_number: u64, parent_block_hash: B256, - evm: &mut impl Evm, -) -> Result, BlockExecutionError> { + evm: &mut impl Evm, +) -> Result>, BlockExecutionError> { if !chain_spec.is_prague_active_at_timestamp(block_timestamp) { return Ok(None) } @@ -58,7 +55,7 @@ pub(crate) fn transact_blockhashes_contract_call( // There should be no state changes to these addresses anyways as a result of this system call, // so we can just remove them from the state returned. res.state.remove(&alloy_eips::eip4788::SYSTEM_ADDRESS); - res.state.remove(&evm.block().coinbase); + res.state.remove(&evm.block().beneficiary); Ok(Some(res)) } diff --git a/crates/evm/src/system_calls/eip4788.rs b/crates/evm/src/system_calls/eip4788.rs index 549c1cdf6..457954d7c 100644 --- a/crates/evm/src/system_calls/eip4788.rs +++ b/crates/evm/src/system_calls/eip4788.rs @@ -6,7 +6,7 @@ use alloy_primitives::B256; use core::fmt::Display; use reth_chainspec::EthereumHardforks; use reth_execution_errors::{BlockExecutionError, BlockValidationError}; -use revm_primitives::ResultAndState; +use revm::context_interface::result::ResultAndState; /// Applies the pre-block call to the [EIP-4788] beacon block root contract, using the given block, /// chain spec, EVM. @@ -18,13 +18,13 @@ use revm_primitives::ResultAndState; /// /// [EIP-4788]: https://eips.ethereum.org/EIPS/eip-4788 #[inline] -pub(crate) fn transact_beacon_root_contract_call( +pub(crate) fn transact_beacon_root_contract_call( chain_spec: impl EthereumHardforks, block_timestamp: u64, block_number: u64, parent_beacon_block_root: Option, - evm: &mut impl Evm, -) -> Result, BlockExecutionError> { + evm: &mut impl Evm, +) -> Result>, BlockExecutionError> { if !chain_spec.is_cancun_active_at_timestamp(block_timestamp) { return Ok(None) } @@ -65,7 +65,7 @@ pub(crate) fn transact_beacon_root_contract_call( // There should be no state changes to these addresses anyways as a result of this system call, // so we can just remove them from the state returned. res.state.remove(&alloy_eips::eip4788::SYSTEM_ADDRESS); - res.state.remove(&evm.block().coinbase); + res.state.remove(&evm.block().beneficiary); Ok(Some(res)) } diff --git a/crates/evm/src/system_calls/eip7002.rs b/crates/evm/src/system_calls/eip7002.rs index 51db7c084..177fb51b2 100644 --- a/crates/evm/src/system_calls/eip7002.rs +++ b/crates/evm/src/system_calls/eip7002.rs @@ -3,9 +3,9 @@ use crate::Evm; use alloc::format; use alloy_eips::eip7002::WITHDRAWAL_REQUEST_PREDEPLOY_ADDRESS; use alloy_primitives::Bytes; -use core::fmt::Display; +use core::fmt::{Debug, Display}; use reth_execution_errors::{BlockExecutionError, BlockValidationError}; -use revm_primitives::{ExecutionResult, ResultAndState}; +use revm::context_interface::result::{ExecutionResult, ResultAndState}; /// Applies the post-block call to the EIP-7002 withdrawal requests contract. /// @@ -13,9 +13,9 @@ use revm_primitives::{ExecutionResult, ResultAndState}; /// /// Note: this does not commit the state changes to the database, it only transact the call. #[inline] -pub(crate) fn transact_withdrawal_requests_contract_call( - evm: &mut impl Evm, -) -> Result { +pub(crate) fn transact_withdrawal_requests_contract_call( + evm: &mut impl Evm, +) -> Result, BlockExecutionError> { // Execute EIP-7002 withdrawal requests contract message data. // // This requirement for the withdrawal requests contract call defined by @@ -44,7 +44,7 @@ pub(crate) fn transact_withdrawal_requests_contract_call( // There should be no state changes to these addresses anyways as a result of this system call, // so we can just remove them from the state returned. res.state.remove(&alloy_eips::eip7002::SYSTEM_ADDRESS); - res.state.remove(&evm.block().coinbase); + res.state.remove(&evm.block().beneficiary); Ok(res) } @@ -52,7 +52,9 @@ pub(crate) fn transact_withdrawal_requests_contract_call( /// Calls the withdrawals requests system contract, and returns the requests from the execution /// output. #[inline] -pub(crate) fn post_commit(result: ExecutionResult) -> Result { +pub(crate) fn post_commit( + result: ExecutionResult, +) -> Result { match result { ExecutionResult::Success { output, .. } => Ok(output.into_data()), ExecutionResult::Revert { output, .. } => { diff --git a/crates/evm/src/system_calls/eip7251.rs b/crates/evm/src/system_calls/eip7251.rs index 3f9431b81..700b826d1 100644 --- a/crates/evm/src/system_calls/eip7251.rs +++ b/crates/evm/src/system_calls/eip7251.rs @@ -3,9 +3,9 @@ use crate::Evm; use alloc::format; use alloy_eips::eip7251::CONSOLIDATION_REQUEST_PREDEPLOY_ADDRESS; use alloy_primitives::Bytes; -use core::fmt::Display; +use core::fmt::{Debug, Display}; use reth_execution_errors::{BlockExecutionError, BlockValidationError}; -use revm_primitives::{ExecutionResult, ResultAndState}; +use revm::context_interface::result::{ExecutionResult, ResultAndState}; /// Applies the post-block call to the EIP-7251 consolidation requests contract. /// @@ -14,9 +14,9 @@ use revm_primitives::{ExecutionResult, ResultAndState}; /// /// Note: this does not commit the state changes to the database, it only transact the call. #[inline] -pub(crate) fn transact_consolidation_requests_contract_call( - evm: &mut impl Evm, -) -> Result { +pub(crate) fn transact_consolidation_requests_contract_call( + evm: &mut impl Evm, +) -> Result, BlockExecutionError> { // Execute EIP-7251 consolidation requests contract message data. // // This requirement for the consolidation requests contract call defined by @@ -46,7 +46,7 @@ pub(crate) fn transact_consolidation_requests_contract_call( // There should be no state changes to these addresses anyways as a result of this system call, // so we can just remove them from the state returned. res.state.remove(&alloy_eips::eip7002::SYSTEM_ADDRESS); - res.state.remove(&evm.block().coinbase); + res.state.remove(&evm.block().beneficiary); Ok(res) } @@ -54,7 +54,9 @@ pub(crate) fn transact_consolidation_requests_contract_call( /// Calls the consolidation requests system contract, and returns the requests from the execution /// output. #[inline] -pub(crate) fn post_commit(result: ExecutionResult) -> Result { +pub(crate) fn post_commit( + result: ExecutionResult, +) -> Result { match result { ExecutionResult::Success { output, .. } => Ok(output.into_data()), ExecutionResult::Revert { output, .. } => { diff --git a/crates/evm/src/system_calls/mod.rs b/crates/evm/src/system_calls/mod.rs index 253104105..f99e1ca0a 100644 --- a/crates/evm/src/system_calls/mod.rs +++ b/crates/evm/src/system_calls/mod.rs @@ -6,12 +6,11 @@ use alloy_consensus::BlockHeader; use alloy_eips::{ eip7002::WITHDRAWAL_REQUEST_TYPE, eip7251::CONSOLIDATION_REQUEST_TYPE, eip7685::Requests, }; -use alloy_primitives::Bytes; +use alloy_primitives::{Bytes, B256}; use core::fmt::Display; use reth_chainspec::EthereumHardforks; use reth_execution_errors::BlockExecutionError; -use revm::DatabaseCommit; -use revm_primitives::{EvmState, B256}; +use revm::{state::EvmState, DatabaseCommit}; mod eip2935; mod eip4788; @@ -167,8 +166,8 @@ where let mut evm = evm_config.evm_with_env(db, evm_env.clone()); self.apply_blockhashes_contract_call( - evm_env.block_env.timestamp.to(), - evm_env.block_env.number.to(), + evm_env.block_env.timestamp, + evm_env.block_env.number, parent_block_hash, &mut evm, )?; @@ -220,8 +219,8 @@ where let mut evm = evm_config.evm_with_env(db, evm_env.clone()); self.apply_beacon_root_contract_call( - evm_env.block_env.timestamp.to(), - evm_env.block_env.number.to(), + evm_env.block_env.timestamp, + evm_env.block_env.number, parent_beacon_block_root, &mut evm, )?; @@ -279,7 +278,7 @@ where /// Applies the post-block call to the EIP-7002 withdrawal request contract. pub fn apply_withdrawal_requests_contract_call( &mut self, - evm: &mut impl Evm, + evm: &mut impl Evm, ) -> Result { let result_and_state = eip7002::transact_withdrawal_requests_contract_call(evm)?; diff --git a/crates/evm/src/test_utils.rs b/crates/evm/src/test_utils.rs index 12798fbf5..49b8cbb63 100644 --- a/crates/evm/src/test_utils.rs +++ b/crates/evm/src/test_utils.rs @@ -13,7 +13,7 @@ use parking_lot::Mutex; use reth_execution_errors::BlockExecutionError; use reth_execution_types::{BlockExecutionResult, ExecutionOutcome}; use reth_primitives::{EthPrimitives, NodePrimitives, RecoveredBlock}; -use revm::State; +use revm_database::State; use std::sync::Arc; /// A [`BlockExecutorProvider`] that returns mocked execution results. @@ -100,7 +100,7 @@ impl Executor for MockExecutorProvider { _f: F, ) -> Result::Receipt>, Self::Error> where - F: FnMut(&revm::db::State), + F: FnMut(&revm_database::State), { >::execute(self, block) } @@ -116,7 +116,7 @@ impl Executor for MockExecutorProvider { >::execute(self, block) } - fn into_state(self) -> revm::db::State { + fn into_state(self) -> revm_database::State { unreachable!() } diff --git a/crates/net/downloaders/Cargo.toml b/crates/net/downloaders/Cargo.toml index a74fcfe84..56ca9197d 100644 --- a/crates/net/downloaders/Cargo.toml +++ b/crates/net/downloaders/Cargo.toml @@ -75,6 +75,7 @@ tempfile.workspace = true optimism = [ "reth-db?/optimism", "reth-db-api?/optimism", + "reth-provider/optimism", ] test-utils = [ diff --git a/crates/optimism/cli/Cargo.toml b/crates/optimism/cli/Cargo.toml index 2d53e33f4..89912c8c0 100644 --- a/crates/optimism/cli/Cargo.toml +++ b/crates/optimism/cli/Cargo.toml @@ -85,6 +85,7 @@ optimism = [ "reth-db-api/optimism", "reth-optimism-primitives/optimism", "reth-downloaders/optimism", + "reth-provider/optimism", "reth-optimism-consensus/optimism", ] asm-keccak = [ diff --git a/crates/optimism/consensus/Cargo.toml b/crates/optimism/consensus/Cargo.toml index fde656273..393ea6be2 100644 --- a/crates/optimism/consensus/Cargo.toml +++ b/crates/optimism/consensus/Cargo.toml @@ -81,7 +81,7 @@ std = [ ] optimism = [ "reth-optimism-primitives/optimism", - "revm/optimism", "reth-execution-types/optimism", "reth-optimism-node/optimism", + "reth-provider/optimism", ] diff --git a/crates/optimism/consensus/src/validation/isthmus.rs b/crates/optimism/consensus/src/validation/isthmus.rs index 91d197b44..6d7ce9197 100644 --- a/crates/optimism/consensus/src/validation/isthmus.rs +++ b/crates/optimism/consensus/src/validation/isthmus.rs @@ -6,7 +6,7 @@ use core::fmt; use reth_optimism_primitives::predeploys::ADDRESS_L2_TO_L1_MESSAGE_PASSER; use reth_storage_api::StorageRootProvider; use reth_trie_common::HashedStorage; -use revm::db::BundleAccount; +use revm::database::BundleAccount; /// Verifies that `withdrawals_root` (i.e. `l2tol1-msg-passer` storage root since Isthmus) field is /// set in block header. diff --git a/crates/optimism/evm/Cargo.toml b/crates/optimism/evm/Cargo.toml index b1b2aaedc..a49826a1c 100644 --- a/crates/optimism/evm/Cargo.toml +++ b/crates/optimism/evm/Cargo.toml @@ -14,7 +14,7 @@ workspace = true # Reth reth-chainspec.workspace = true reth-ethereum-forks.workspace = true -reth-evm.workspace = true +reth-evm = { workspace = true, features = ["op"] } reth-primitives-traits.workspace = true reth-execution-errors.workspace = true reth-execution-types.workspace = true @@ -23,7 +23,9 @@ reth-consensus-common.workspace = true # ethereum alloy-eips.workspace = true +alloy-evm.workspace = true alloy-primitives.workspace = true +alloy-op-evm.workspace = true op-alloy-consensus.workspace = true alloy-consensus.workspace = true @@ -35,7 +37,9 @@ reth-optimism-primitives.workspace = true # revm revm.workspace = true +revm-database.workspace = true revm-primitives.workspace = true +revm-optimism.workspace = true # misc derive_more.workspace = true @@ -74,11 +78,13 @@ std = [ "reth-optimism-chainspec/std", "reth-execution-errors/std", "reth-execution-types/std", + "alloy-evm/std", + "alloy-op-evm/std", + "revm-database/std", + "revm-optimism/std", ] optimism = [ "reth-execution-types/optimism", "reth-optimism-consensus/optimism", - "revm/optimism", - "revm-primitives/optimism", "reth-optimism-primitives/optimism", ] diff --git a/crates/optimism/evm/src/config.rs b/crates/optimism/evm/src/config.rs index 770791dba..6375ceb3c 100644 --- a/crates/optimism/evm/src/config.rs +++ b/crates/optimism/evm/src/config.rs @@ -1,13 +1,13 @@ use alloy_consensus::Header; use reth_optimism_forks::OpHardforks; +use revm_optimism::OpSpecId; -/// Map the latest active hardfork at the given header to a revm -/// [`SpecId`](revm_primitives::SpecId). -pub fn revm_spec(chain_spec: impl OpHardforks, header: &Header) -> revm_primitives::SpecId { +/// Map the latest active hardfork at the given header to a revm [`OpSpecId`]. +pub fn revm_spec(chain_spec: impl OpHardforks, header: &Header) -> OpSpecId { revm_spec_by_timestamp_after_bedrock(chain_spec, header.timestamp) } -/// Returns the revm [`SpecId`](revm_primitives::SpecId) at the given timestamp. +/// Returns the revm [`OpSpecId`] at the given timestamp. /// /// # Note /// @@ -16,23 +16,23 @@ pub fn revm_spec(chain_spec: impl OpHardforks, header: &Header) -> revm_primitiv pub fn revm_spec_by_timestamp_after_bedrock( chain_spec: impl OpHardforks, timestamp: u64, -) -> revm_primitives::SpecId { +) -> OpSpecId { if chain_spec.is_isthmus_active_at_timestamp(timestamp) { - revm_primitives::ISTHMUS + OpSpecId::ISTHMUS } else if chain_spec.is_holocene_active_at_timestamp(timestamp) { - revm_primitives::HOLOCENE + OpSpecId::HOLOCENE } else if chain_spec.is_granite_active_at_timestamp(timestamp) { - revm_primitives::GRANITE + OpSpecId::GRANITE } else if chain_spec.is_fjord_active_at_timestamp(timestamp) { - revm_primitives::FJORD + OpSpecId::FJORD } else if chain_spec.is_ecotone_active_at_timestamp(timestamp) { - revm_primitives::ECOTONE + OpSpecId::ECOTONE } else if chain_spec.is_canyon_active_at_timestamp(timestamp) { - revm_primitives::CANYON + OpSpecId::CANYON } else if chain_spec.is_regolith_active_at_timestamp(timestamp) { - revm_primitives::REGOLITH + OpSpecId::REGOLITH } else { - revm_primitives::BEDROCK + OpSpecId::BEDROCK } } @@ -51,35 +51,35 @@ mod tests { } assert_eq!( revm_spec_by_timestamp_after_bedrock(op_cs(|cs| cs.isthmus_activated()), 0), - revm_primitives::ISTHMUS + OpSpecId::ISTHMUS ); assert_eq!( revm_spec_by_timestamp_after_bedrock(op_cs(|cs| cs.holocene_activated()), 0), - revm_primitives::HOLOCENE + OpSpecId::HOLOCENE ); assert_eq!( revm_spec_by_timestamp_after_bedrock(op_cs(|cs| cs.granite_activated()), 0), - revm_primitives::GRANITE + OpSpecId::GRANITE ); assert_eq!( revm_spec_by_timestamp_after_bedrock(op_cs(|cs| cs.fjord_activated()), 0), - revm_primitives::FJORD + OpSpecId::FJORD ); assert_eq!( revm_spec_by_timestamp_after_bedrock(op_cs(|cs| cs.ecotone_activated()), 0), - revm_primitives::ECOTONE + OpSpecId::ECOTONE ); assert_eq!( revm_spec_by_timestamp_after_bedrock(op_cs(|cs| cs.canyon_activated()), 0), - revm_primitives::CANYON + OpSpecId::CANYON ); assert_eq!( revm_spec_by_timestamp_after_bedrock(op_cs(|cs| cs.bedrock_activated()), 0), - revm_primitives::BEDROCK + OpSpecId::BEDROCK ); assert_eq!( revm_spec_by_timestamp_after_bedrock(op_cs(|cs| cs.regolith_activated()), 0), - revm_primitives::REGOLITH + OpSpecId::REGOLITH ); } @@ -92,35 +92,35 @@ mod tests { } assert_eq!( revm_spec(op_cs(|cs| cs.isthmus_activated()), &Default::default()), - revm_primitives::ISTHMUS + OpSpecId::ISTHMUS ); assert_eq!( revm_spec(op_cs(|cs| cs.holocene_activated()), &Default::default()), - revm_primitives::HOLOCENE + OpSpecId::HOLOCENE ); assert_eq!( revm_spec(op_cs(|cs| cs.granite_activated()), &Default::default()), - revm_primitives::GRANITE + OpSpecId::GRANITE ); assert_eq!( revm_spec(op_cs(|cs| cs.fjord_activated()), &Default::default()), - revm_primitives::FJORD + OpSpecId::FJORD ); assert_eq!( revm_spec(op_cs(|cs| cs.ecotone_activated()), &Default::default()), - revm_primitives::ECOTONE + OpSpecId::ECOTONE ); assert_eq!( revm_spec(op_cs(|cs| cs.canyon_activated()), &Default::default()), - revm_primitives::CANYON + OpSpecId::CANYON ); assert_eq!( revm_spec(op_cs(|cs| cs.bedrock_activated()), &Default::default()), - revm_primitives::BEDROCK + OpSpecId::BEDROCK ); assert_eq!( revm_spec(op_cs(|cs| cs.regolith_activated()), &Default::default()), - revm_primitives::REGOLITH + OpSpecId::REGOLITH ); } } diff --git a/crates/optimism/evm/src/execute.rs b/crates/optimism/evm/src/execute.rs index dd04f9d22..524d73bd3 100644 --- a/crates/optimism/evm/src/execute.rs +++ b/crates/optimism/evm/src/execute.rs @@ -16,15 +16,15 @@ use reth_evm::{ }, state_change::post_block_balance_increments, system_calls::{OnStateHook, StateChangePostBlockSource, StateChangeSource, SystemCaller}, - ConfigureEvmFor, Database, Evm, + ConfigureEvm, ConfigureEvmFor, Database, Evm, HaltReasonFor, }; use reth_optimism_chainspec::OpChainSpec; use reth_optimism_consensus::validate_block_post_execution; use reth_optimism_forks::OpHardforks; use reth_optimism_primitives::{transaction::signed::OpTransaction, DepositReceipt, OpPrimitives}; use reth_primitives_traits::{BlockBody, NodePrimitives, RecoveredBlock, SignedTransaction}; -use revm::State; -use revm_primitives::{db::DatabaseCommit, ResultAndState}; +use revm::{context_interface::result::ResultAndState, DatabaseCommit}; +use revm_database::State; use tracing::trace; /// Factory for [`OpExecutionStrategy`]. @@ -32,14 +32,15 @@ use tracing::trace; pub struct OpExecutionStrategyFactory< N: NodePrimitives = OpPrimitives, ChainSpec = OpChainSpec, - EvmConfig = OpEvmConfig, + EvmConfig: ConfigureEvm = OpEvmConfig, > { /// The chainspec chain_spec: Arc, /// How to create an EVM. evm_config: EvmConfig, /// Receipt builder. - receipt_builder: Arc>, + receipt_builder: + Arc, Receipt = N::Receipt>>, } impl OpExecutionStrategyFactory { @@ -53,12 +54,18 @@ impl OpExecutionStrategyFactory { } } -impl OpExecutionStrategyFactory { +impl + OpExecutionStrategyFactory +{ /// Creates a new executor strategy factory. pub fn new( chain_spec: Arc, evm_config: EvmConfig, - receipt_builder: impl OpReceiptBuilder, + receipt_builder: impl OpReceiptBuilder< + N::SignedTx, + HaltReasonFor, + Receipt = N::Receipt, + >, ) -> Self { Self { chain_spec, evm_config, receipt_builder: Arc::new(receipt_builder) } } @@ -93,7 +100,7 @@ where #[allow(missing_debug_implementations)] pub struct OpExecutionStrategy where - EvmConfig: Clone, + EvmConfig: ConfigureEvm, { /// The chainspec chain_spec: Arc, @@ -104,21 +111,24 @@ where /// Utility to call system smart contracts. system_caller: SystemCaller, /// Receipt builder. - receipt_builder: Arc>, + receipt_builder: + Arc, Receipt = N::Receipt>>, } impl OpExecutionStrategy where N: NodePrimitives, ChainSpec: OpHardforks, - EvmConfig: Clone, + EvmConfig: ConfigureEvm, { /// Creates a new [`OpExecutionStrategy`] pub fn new( state: State, chain_spec: Arc, evm_config: EvmConfig, - receipt_builder: Arc>, + receipt_builder: Arc< + dyn OpReceiptBuilder, Receipt = N::Receipt>, + >, ) -> Self { let system_caller = SystemCaller::new(evm_config.clone(), chain_spec.clone()); Self { state, chain_spec, evm_config, system_caller, receipt_builder } @@ -292,7 +302,7 @@ where &mut self.state } - fn into_state(self) -> revm::db::State { + fn into_state(self) -> revm_database::State { self.state } @@ -337,9 +347,8 @@ mod tests { use reth_optimism_chainspec::OpChainSpecBuilder; use reth_optimism_primitives::{OpReceipt, OpTransactionSigned}; use reth_primitives_traits::Account; - use reth_revm::{ - database::StateProviderDatabase, test_utils::StateProviderTest, L1_BLOCK_CONTRACT, - }; + use reth_revm::{database::StateProviderDatabase, test_utils::StateProviderTest}; + use revm_optimism::constants::L1_BLOCK_CONTRACT; use std::{collections::HashMap, str::FromStr}; fn create_op_state_provider() -> StateProviderTest { diff --git a/crates/optimism/evm/src/l1.rs b/crates/optimism/evm/src/l1.rs index fb789d06c..fecfb832b 100644 --- a/crates/optimism/evm/src/l1.rs +++ b/crates/optimism/evm/src/l1.rs @@ -6,10 +6,8 @@ use alloy_primitives::{address, b256, hex, Address, Bytes, B256, U256}; use reth_execution_errors::BlockExecutionError; use reth_optimism_forks::OpHardforks; use reth_primitives_traits::BlockBody; -use revm::{ - primitives::{Bytecode, HashMap, SpecId}, - DatabaseCommit, L1BlockInfo, -}; +use revm::{primitives::HashMap, state::Bytecode, DatabaseCommit}; +use revm_optimism::{L1BlockInfo, OpSpecId}; use tracing::trace; /// The address of the create2 deployer @@ -272,13 +270,13 @@ impl RethL1BlockInfo for L1BlockInfo { } let spec_id = if chain_spec.is_fjord_active_at_timestamp(timestamp) { - SpecId::FJORD + OpSpecId::FJORD } else if chain_spec.is_ecotone_active_at_timestamp(timestamp) { - SpecId::ECOTONE + OpSpecId::ECOTONE } else if chain_spec.is_regolith_active_at_timestamp(timestamp) { - SpecId::REGOLITH + OpSpecId::REGOLITH } else if chain_spec.is_bedrock_active_at_block(block_number) { - SpecId::BEDROCK + OpSpecId::BEDROCK } else { return Err( OpBlockExecutionError::L1BlockInfo(L1BlockInfoError::HardforksNotActive).into() @@ -295,11 +293,11 @@ impl RethL1BlockInfo for L1BlockInfo { input: &[u8], ) -> Result { let spec_id = if chain_spec.is_fjord_active_at_timestamp(timestamp) { - SpecId::FJORD + OpSpecId::FJORD } else if chain_spec.is_regolith_active_at_timestamp(timestamp) { - SpecId::REGOLITH + OpSpecId::REGOLITH } else if chain_spec.is_bedrock_active_at_block(block_number) { - SpecId::BEDROCK + OpSpecId::BEDROCK } else { return Err( OpBlockExecutionError::L1BlockInfo(L1BlockInfoError::HardforksNotActive).into() @@ -315,7 +313,7 @@ impl RethL1BlockInfo for L1BlockInfo { pub fn ensure_create2_deployer( chain_spec: impl OpHardforks, timestamp: u64, - db: &mut revm::State, + db: &mut revm_database::State, ) -> Result<(), DB::Error> where DB: revm::Database, @@ -337,7 +335,7 @@ where acc_info.code = Some(Bytecode::new_raw(Bytes::from_static(&CREATE_2_DEPLOYER_BYTECODE))); // Convert the cache account back into a revm account and mark it as touched. - let mut revm_acc: revm::primitives::Account = acc_info.into(); + let mut revm_acc: revm::state::Account = acc_info.into(); revm_acc.mark_touch(); // Commit the create2 deployer account to the database. diff --git a/crates/optimism/evm/src/lib.rs b/crates/optimism/evm/src/lib.rs index 6e49cf2b8..13374bbbe 100644 --- a/crates/optimism/evm/src/lib.rs +++ b/crates/optimism/evm/src/lib.rs @@ -12,23 +12,25 @@ extern crate alloc; -use alloc::{sync::Arc, vec::Vec}; +use alloc::sync::Arc; use alloy_consensus::{BlockHeader, Header}; +use alloy_op_evm::OpEvmFactory; use alloy_primitives::{Address, U256}; use core::fmt::Debug; use op_alloy_consensus::EIP1559ParamError; use reth_chainspec::EthChainSpec; -use reth_evm::{env::EvmEnv, ConfigureEvm, ConfigureEvmEnv, Database, Evm, NextBlockEnvAttributes}; +use reth_evm::{ConfigureEvm, ConfigureEvmEnv, EvmEnv, NextBlockEnvAttributes}; use reth_optimism_chainspec::OpChainSpec; use reth_optimism_consensus::next_block_base_fee; use reth_optimism_forks::OpHardforks; use reth_optimism_primitives::OpTransactionSigned; use reth_primitives_traits::FillTxEnv; use revm::{ - inspector_handle_register, - primitives::{AnalysisKind, CfgEnvWithHandlerCfg, TxEnv}, - EvmBuilder, GetInspector, + context::{BlockEnv, CfgEnv, TxEnv}, + context_interface::block::BlobExcessGasAndPrice, + specification::hardfork::SpecId, }; +use revm_optimism::{OpSpecId, OpTransaction}; mod config; pub use config::{revm_spec, revm_spec_by_timestamp_after_bedrock}; @@ -41,108 +43,24 @@ pub use receipts::*; mod error; pub use error::OpBlockExecutionError; -use revm_primitives::{ - BlobExcessGasAndPrice, BlockEnv, Bytes, CfgEnv, EVMError, HaltReason, HandlerCfg, - OptimismFields, ResultAndState, SpecId, TxKind, -}; - -/// OP EVM implementation. -#[derive(derive_more::Debug, derive_more::Deref, derive_more::DerefMut, derive_more::From)] -#[debug(bound(DB::Error: Debug))] -pub struct OpEvm<'a, EXT, DB: Database>(revm::Evm<'a, EXT, DB>); - -impl Evm for OpEvm<'_, EXT, DB> { - type DB = DB; - type Tx = TxEnv; - type Error = EVMError; - type HaltReason = HaltReason; - - fn block(&self) -> &BlockEnv { - self.0.block() - } - - fn transact(&mut self, tx: Self::Tx) -> Result { - *self.tx_mut() = tx; - self.0.transact() - } - - fn transact_system_call( - &mut self, - caller: Address, - contract: Address, - data: Bytes, - ) -> Result { - #[allow(clippy::needless_update)] // side-effect of optimism fields - let tx_env = TxEnv { - caller, - transact_to: TxKind::Call(contract), - // Explicitly set nonce to None so revm does not do any nonce checks - nonce: None, - gas_limit: 30_000_000, - value: U256::ZERO, - data, - // Setting the gas price to zero enforces that no value is transferred as part of the - // call, and that the call will not count against the block's gas limit - gas_price: U256::ZERO, - // The chain ID check is not relevant here and is disabled if set to None - chain_id: None, - // Setting the gas priority fee to None ensures the effective gas price is derived from - // the `gas_price` field, which we need to be zero - gas_priority_fee: None, - access_list: Vec::new(), - // blob fields can be None for this tx - blob_hashes: Vec::new(), - max_fee_per_blob_gas: None, - authorization_list: None, - optimism: OptimismFields { - source_hash: None, - mint: None, - is_system_transaction: Some(false), - // The L1 fee is not charged for the EIP-4788 transaction, submit zero bytes for the - // enveloped tx size. - enveloped_tx: Some(Bytes::default()), - }, - }; - - *self.tx_mut() = tx_env; - - let prev_block_env = self.block().clone(); - - // ensure the block gas limit is >= the tx - self.block_mut().gas_limit = U256::from(self.tx().gas_limit); - - // disable the base fee check for this call by setting the base fee to zero - self.block_mut().basefee = U256::ZERO; - - let res = self.0.transact(); - - // re-set the block env - *self.block_mut() = prev_block_env; - - res - } - - fn db_mut(&mut self) -> &mut Self::DB { - &mut self.context.evm.db - } -} /// Optimism-related EVM configuration. #[derive(Debug)] pub struct OpEvmConfig { chain_spec: Arc, + evm_factory: OpEvmFactory, } impl Clone for OpEvmConfig { fn clone(&self) -> Self { - Self { chain_spec: self.chain_spec.clone() } + Self { chain_spec: self.chain_spec.clone(), evm_factory: OpEvmFactory::default() } } } impl OpEvmConfig { /// Creates a new [`OpEvmConfig`] with the given chain spec. - pub const fn new(chain_spec: Arc) -> Self { - Self { chain_spec } + pub fn new(chain_spec: Arc) -> Self { + Self { chain_spec, evm_factory: OpEvmFactory::default() } } /// Returns the chain spec associated with this configuration. @@ -155,130 +73,87 @@ impl ConfigureEvmEnv for OpEvmC type Header = Header; type Transaction = OpTransactionSigned; type Error = EIP1559ParamError; - type TxEnv = TxEnv; - type Spec = SpecId; + type TxEnv = OpTransaction; + type Spec = OpSpecId; fn tx_env(&self, transaction: &Self::Transaction, signer: Address) -> Self::TxEnv { - let mut tx_env = TxEnv::default(); + let mut tx_env = Default::default(); transaction.fill_tx_env(&mut tx_env, signer); tx_env } - fn evm_env(&self, header: &Self::Header) -> EvmEnv { + fn evm_env(&self, header: &Self::Header) -> EvmEnv { let spec = config::revm_spec(self.chain_spec(), header); - let mut cfg_env = CfgEnv::default(); - cfg_env.chain_id = self.chain_spec.chain().id(); - cfg_env.perf_analyse_created_bytecodes = AnalysisKind::default(); + let cfg_env = CfgEnv::new().with_chain_id(self.chain_spec.chain().id()).with_spec(spec); let block_env = BlockEnv { - number: U256::from(header.number()), - coinbase: header.beneficiary(), - timestamp: U256::from(header.timestamp()), - difficulty: if spec >= SpecId::MERGE { U256::ZERO } else { header.difficulty() }, - prevrandao: if spec >= SpecId::MERGE { header.mix_hash() } else { None }, - gas_limit: U256::from(header.gas_limit()), - basefee: U256::from(header.base_fee_per_gas().unwrap_or_default()), + number: header.number(), + beneficiary: header.beneficiary(), + timestamp: header.timestamp(), + difficulty: if spec.into_eth_spec() >= SpecId::MERGE { + U256::ZERO + } else { + header.difficulty() + }, + prevrandao: if spec.into_eth_spec() >= SpecId::MERGE { + header.mix_hash() + } else { + None + }, + gas_limit: header.gas_limit(), + basefee: header.base_fee_per_gas().unwrap_or_default(), // EIP-4844 excess blob gas of this block, introduced in Cancun blob_excess_gas_and_price: header.excess_blob_gas().map(|excess_blob_gas| { - BlobExcessGasAndPrice::new(excess_blob_gas, spec >= SpecId::PRAGUE) + BlobExcessGasAndPrice::new(excess_blob_gas, spec.into_eth_spec() >= SpecId::PRAGUE) }), }; - EvmEnv { cfg_env, block_env, spec } + EvmEnv { cfg_env, block_env } } fn next_evm_env( &self, parent: &Self::Header, attributes: NextBlockEnvAttributes, - ) -> Result { - // configure evm env based on parent block - let cfg = CfgEnv::default().with_chain_id(self.chain_spec.chain().id()); - + ) -> Result, Self::Error> { // ensure we're not missing any timestamp based hardforks let spec_id = revm_spec_by_timestamp_after_bedrock(&self.chain_spec, attributes.timestamp); + // configure evm env based on parent block + let cfg_env = CfgEnv::new().with_chain_id(self.chain_spec.chain().id()).with_spec(spec_id); + // if the parent block did not have excess blob gas (i.e. it was pre-cancun), but it is // cancun now, we need to set the excess blob gas to the default value(0) let blob_excess_gas_and_price = parent .maybe_next_block_excess_blob_gas( self.chain_spec().blob_params_at_timestamp(attributes.timestamp), ) - .or_else(|| (spec_id.is_enabled_in(SpecId::CANCUN)).then_some(0)) + .or_else(|| (spec_id.into_eth_spec().is_enabled_in(SpecId::CANCUN)).then_some(0)) .map(|gas| BlobExcessGasAndPrice::new(gas, false)); let block_env = BlockEnv { - number: U256::from(parent.number + 1), - coinbase: attributes.suggested_fee_recipient, - timestamp: U256::from(attributes.timestamp), + number: parent.number + 1, + beneficiary: attributes.suggested_fee_recipient, + timestamp: attributes.timestamp, difficulty: U256::ZERO, prevrandao: Some(attributes.prev_randao), - gas_limit: U256::from(attributes.gas_limit), + gas_limit: attributes.gas_limit, // calculate basefee based on parent block's gas usage - basefee: U256::from(next_block_base_fee( - &self.chain_spec, - parent, - attributes.timestamp, - )?), + basefee: next_block_base_fee(&self.chain_spec, parent, attributes.timestamp)?, // calculate excess gas based on parent block's blob gas usage blob_excess_gas_and_price, }; - let cfg_env_with_handler_cfg; - { - cfg_env_with_handler_cfg = CfgEnvWithHandlerCfg { - cfg_env: cfg, - handler_cfg: HandlerCfg { spec_id, is_optimism: true }, - }; - } - - Ok((cfg_env_with_handler_cfg, block_env).into()) + Ok(EvmEnv { cfg_env, block_env }) } } impl ConfigureEvm for OpEvmConfig { - type Evm<'a, DB: Database + 'a, I: 'a> = OpEvm<'a, I, DB>; - type EvmError = EVMError; - type HaltReason = HaltReason; + type EvmFactory = OpEvmFactory; - fn evm_with_env(&self, db: DB, evm_env: EvmEnv) -> Self::Evm<'_, DB, ()> { - let cfg_env_with_handler_cfg = CfgEnvWithHandlerCfg { - cfg_env: evm_env.cfg_env, - handler_cfg: HandlerCfg { spec_id: evm_env.spec, is_optimism: true }, - }; - - EvmBuilder::default() - .with_db(db) - .with_cfg_env_with_handler_cfg(cfg_env_with_handler_cfg) - .with_block_env(evm_env.block_env) - .build() - .into() - } - - fn evm_with_env_and_inspector( - &self, - db: DB, - evm_env: EvmEnv, - inspector: I, - ) -> Self::Evm<'_, DB, I> - where - DB: Database, - I: GetInspector, - { - let cfg_env_with_handler_cfg = CfgEnvWithHandlerCfg { - cfg_env: evm_env.cfg_env, - handler_cfg: HandlerCfg { spec_id: evm_env.spec, is_optimism: true }, - }; - - EvmBuilder::default() - .with_db(db) - .with_external_context(inspector) - .with_cfg_env_with_handler_cfg(cfg_env_with_handler_cfg) - .with_block_env(evm_env.block_env) - .append_handler_register(inspector_handle_register) - .build() - .into() + fn evm_factory(&self) -> &Self::EvmFactory { + &self.evm_factory } } @@ -288,7 +163,7 @@ mod tests { use alloy_consensus::{Header, Receipt}; use alloy_eips::eip7685::Requests; use alloy_genesis::Genesis; - use alloy_primitives::{bytes, map::HashMap, Address, LogData, B256, U256}; + use alloy_primitives::{bytes, map::HashMap, Address, LogData, B256}; use reth_chainspec::ChainSpec; use reth_evm::execute::ProviderError; use reth_execution_types::{ @@ -296,13 +171,11 @@ mod tests { }; use reth_optimism_chainspec::BASE_MAINNET; use reth_optimism_primitives::{OpBlock, OpPrimitives, OpReceipt}; - use reth_primitives_traits::{Account, Log, RecoveredBlock}; - use revm::{ - db::{BundleState, CacheDB, EmptyDBTyped}, - inspectors::NoOpInspector, - primitives::{AccountInfo, BlockEnv, CfgEnv, SpecId}, - }; - use revm_primitives::HandlerCfg; + use reth_primitives_traits::{Account, RecoveredBlock}; + use revm::{database_interface::EmptyDBTyped, inspector::NoOpInspector, state::AccountInfo}; + use revm_database::{BundleState, CacheDB}; + use revm_optimism::OpSpecId; + use revm_primitives::Log; use std::sync::Arc; fn test_evm_config() -> OpEvmConfig { @@ -345,13 +218,7 @@ mod tests { let evm = evm_config.evm_with_env(db, evm_env.clone()); // Check that the EVM environment - assert_eq!(evm.context.evm.env.cfg, evm_env.cfg_env); - - // Default spec ID - assert_eq!(evm.handler.spec_id(), SpecId::LATEST); - - // Optimism in handler - assert_eq!(evm.handler.cfg, HandlerCfg { spec_id: SpecId::LATEST, is_optimism: true }); + assert_eq!(evm.cfg, evm_env.cfg_env); } #[test] @@ -361,20 +228,14 @@ mod tests { let db = CacheDB::>::default(); // Create a custom configuration environment with a chain ID of 111 - let cfg = CfgEnv::default().with_chain_id(111); + let cfg = CfgEnv::new().with_chain_id(111).with_spec(OpSpecId::default()); let evm_env = EvmEnv { cfg_env: cfg.clone(), ..Default::default() }; let evm = evm_config.evm_with_env(db, evm_env); // Check that the EVM environment is initialized with the custom environment - assert_eq!(evm.context.evm.inner.env.cfg, cfg); - - // Default spec ID - assert_eq!(evm.handler.spec_id(), SpecId::LATEST); - - // Optimism in handler - assert_eq!(evm.handler.cfg, HandlerCfg { spec_id: SpecId::LATEST, is_optimism: true }); + assert_eq!(evm.cfg, cfg); } #[test] @@ -384,25 +245,15 @@ mod tests { let db = CacheDB::>::default(); // Create customs block and tx env - let block = BlockEnv { - basefee: U256::from(1000), - gas_limit: U256::from(10_000_000), - number: U256::from(42), - ..Default::default() - }; + let block = + BlockEnv { basefee: 1000, gas_limit: 10_000_000, number: 42, ..Default::default() }; let evm_env = EvmEnv { block_env: block, ..Default::default() }; let evm = evm_config.evm_with_env(db, evm_env.clone()); // Verify that the block and transaction environments are set correctly - assert_eq!(evm.context.evm.env.block, evm_env.block_env); - - // Default spec ID - assert_eq!(evm.handler.spec_id(), SpecId::LATEST); - - // Optimism in handler - assert_eq!(evm.handler.cfg, HandlerCfg { spec_id: SpecId::LATEST, is_optimism: true }); + assert_eq!(evm.block, evm_env.block_env); } #[test] @@ -411,15 +262,12 @@ mod tests { let db = CacheDB::>::default(); - let evm_env = EvmEnv { spec: SpecId::ECOTONE, ..Default::default() }; + let evm_env = + EvmEnv { cfg_env: CfgEnv::new().with_spec(OpSpecId::ECOTONE), ..Default::default() }; - let evm = evm_config.evm_with_env(db, evm_env); + let evm = evm_config.evm_with_env(db, evm_env.clone()); - // Check that the spec ID is setup properly - assert_eq!(evm.handler.spec_id(), SpecId::ECOTONE); - - // Optimism in handler - assert_eq!(evm.handler.cfg, HandlerCfg { spec_id: SpecId::ECOTONE, is_optimism: true }); + assert_eq!(evm.cfg, evm_env.cfg_env); } #[test] @@ -429,17 +277,11 @@ mod tests { let evm_env = EvmEnv { cfg_env: Default::default(), ..Default::default() }; - let evm = evm_config.evm_with_env_and_inspector(db, evm_env.clone(), NoOpInspector); + let evm = evm_config.evm_with_env_and_inspector(db, evm_env.clone(), NoOpInspector {}); // Check that the EVM environment is set to default values - assert_eq!(evm.context.evm.env.block, evm_env.block_env); - assert_eq!(evm.context.evm.env.cfg, evm_env.cfg_env); - assert_eq!(evm.context.evm.env.tx, Default::default()); - assert_eq!(evm.context.external, NoOpInspector); - assert_eq!(evm.handler.spec_id(), SpecId::LATEST); - - // Optimism in handler - assert_eq!(evm.handler.cfg, HandlerCfg { spec_id: SpecId::LATEST, is_optimism: true }); + assert_eq!(evm.block, evm_env.block_env); + assert_eq!(evm.cfg, evm_env.cfg_env); } #[test] @@ -447,20 +289,15 @@ mod tests { let evm_config = test_evm_config(); let db = CacheDB::>::default(); - let cfg = CfgEnv::default().with_chain_id(111); + let cfg = CfgEnv::new().with_chain_id(111).with_spec(OpSpecId::default()); let block = BlockEnv::default(); - let evm_env = EvmEnv { block_env: block, cfg_env: cfg.clone(), ..Default::default() }; + let evm_env = EvmEnv { block_env: block, cfg_env: cfg.clone() }; - let evm = evm_config.evm_with_env_and_inspector(db, evm_env.clone(), NoOpInspector); + let evm = evm_config.evm_with_env_and_inspector(db, evm_env.clone(), NoOpInspector {}); // Check that the EVM environment is set with custom configuration - assert_eq!(evm.context.evm.env.cfg, cfg); - assert_eq!(evm.context.evm.env.block, evm_env.block_env); - assert_eq!(evm.context.external, NoOpInspector); - assert_eq!(evm.handler.spec_id(), SpecId::LATEST); - - // Optimism in handler - assert_eq!(evm.handler.cfg, HandlerCfg { spec_id: SpecId::LATEST, is_optimism: true }); + assert_eq!(evm.cfg, cfg); + assert_eq!(evm.block, evm_env.block_env); } #[test] @@ -469,23 +306,14 @@ mod tests { let db = CacheDB::>::default(); // Create custom block and tx environment - let block = BlockEnv { - basefee: U256::from(1000), - gas_limit: U256::from(10_000_000), - number: U256::from(42), - ..Default::default() - }; + let block = + BlockEnv { basefee: 1000, gas_limit: 10_000_000, number: 42, ..Default::default() }; let evm_env = EvmEnv { block_env: block, ..Default::default() }; - let evm = evm_config.evm_with_env_and_inspector(db, evm_env.clone(), NoOpInspector); + let evm = evm_config.evm_with_env_and_inspector(db, evm_env.clone(), NoOpInspector {}); // Verify that the block and transaction environments are set correctly - assert_eq!(evm.context.evm.env.block, evm_env.block_env); - assert_eq!(evm.context.external, NoOpInspector); - assert_eq!(evm.handler.spec_id(), SpecId::LATEST); - - // Optimism in handler - assert_eq!(evm.handler.cfg, HandlerCfg { spec_id: SpecId::LATEST, is_optimism: true }); + assert_eq!(evm.block, evm_env.block_env); } #[test] @@ -493,21 +321,14 @@ mod tests { let evm_config = test_evm_config(); let db = CacheDB::>::default(); - let evm_env = EvmEnv { spec: SpecId::ECOTONE, ..Default::default() }; + let evm_env = + EvmEnv { cfg_env: CfgEnv::new().with_spec(OpSpecId::ECOTONE), ..Default::default() }; - let evm = evm_config.evm_with_env_and_inspector(db, evm_env.clone(), NoOpInspector); + let evm = evm_config.evm_with_env_and_inspector(db, evm_env.clone(), NoOpInspector {}); // Check that the spec ID is set properly - assert_eq!(evm.handler.spec_id(), SpecId::ECOTONE); - assert_eq!(evm.context.evm.env.cfg, evm_env.cfg_env); - assert_eq!(evm.context.evm.env.block, evm_env.block_env); - assert_eq!(evm.context.external, NoOpInspector); - - // Check that the spec ID is setup properly - assert_eq!(evm.handler.spec_id(), SpecId::ECOTONE); - - // Optimism in handler - assert_eq!(evm.handler.cfg, HandlerCfg { spec_id: SpecId::ECOTONE, is_optimism: true }); + assert_eq!(evm.cfg, evm_env.cfg_env); + assert_eq!(evm.block, evm_env.block_env); } #[test] diff --git a/crates/optimism/evm/src/receipts.rs b/crates/optimism/evm/src/receipts.rs index 2ced9c7b7..64e7b3f9e 100644 --- a/crates/optimism/evm/src/receipts.rs +++ b/crates/optimism/evm/src/receipts.rs @@ -2,21 +2,21 @@ use alloy_consensus::{Eip658Value, Receipt}; use core::fmt; use op_alloy_consensus::{OpDepositReceipt, OpTxType}; use reth_optimism_primitives::{OpReceipt, OpTransactionSigned}; -use revm_primitives::ExecutionResult; +use revm::context_interface::result::ExecutionResult; /// Context for building a receipt. #[derive(Debug)] -pub struct ReceiptBuilderCtx<'a, T> { +pub struct ReceiptBuilderCtx<'a, T, Halt> { /// Transaction pub tx: &'a T, /// Result of transaction execution. - pub result: ExecutionResult, + pub result: ExecutionResult, /// Cumulative gas used. pub cumulative_gas_used: u64, } /// Type that knows how to build a receipt based on execution result. -pub trait OpReceiptBuilder: fmt::Debug + Send + Sync + Unpin + 'static { +pub trait OpReceiptBuilder: fmt::Debug + Send + Sync + Unpin + 'static { /// Receipt type. type Receipt: Send + Sync + Clone + Unpin + 'static; @@ -26,8 +26,8 @@ pub trait OpReceiptBuilder: fmt::Debug + Send + Sync + Unpin + 'static { /// case, the `build_deposit_receipt` method will be called. fn build_receipt<'a>( &self, - ctx: ReceiptBuilderCtx<'a, T>, - ) -> Result>; + ctx: ReceiptBuilderCtx<'a, T, Halt>, + ) -> Result>; /// Builds receipt for a deposit transaction. fn build_deposit_receipt(&self, inner: OpDepositReceipt) -> Self::Receipt; @@ -38,13 +38,13 @@ pub trait OpReceiptBuilder: fmt::Debug + Send + Sync + Unpin + 'static { #[non_exhaustive] pub struct BasicOpReceiptBuilder; -impl OpReceiptBuilder for BasicOpReceiptBuilder { +impl OpReceiptBuilder for BasicOpReceiptBuilder { type Receipt = OpReceipt; fn build_receipt<'a>( &self, - ctx: ReceiptBuilderCtx<'a, OpTransactionSigned>, - ) -> Result> { + ctx: ReceiptBuilderCtx<'a, OpTransactionSigned, Halt>, + ) -> Result> { match ctx.tx.tx_type() { OpTxType::Deposit => Err(ctx), ty => { diff --git a/crates/optimism/node/Cargo.toml b/crates/optimism/node/Cargo.toml index c2dbd5f13..245846a5f 100644 --- a/crates/optimism/node/Cargo.toml +++ b/crates/optimism/node/Cargo.toml @@ -47,6 +47,7 @@ reth-optimism-primitives = { workspace = true, features = ["serde", "serde-binco # revm with required optimism features revm = { workspace = true, features = ["secp256k1", "blst", "c-kzg"] } +revm-optimism.workspace = true # ethereum alloy-eips.workspace = true @@ -87,9 +88,9 @@ futures.workspace = true [features] default = ["reth-codec"] optimism = [ + "reth-provider/optimism", "reth-optimism-evm/optimism", "reth-optimism-payload-builder/optimism", - "revm/optimism", "reth-optimism-rpc/optimism", "reth-engine-local/op", "reth-optimism-consensus/optimism", diff --git a/crates/optimism/node/src/node.rs b/crates/optimism/node/src/node.rs index 23d020b44..94669e4eb 100644 --- a/crates/optimism/node/src/node.rs +++ b/crates/optimism/node/src/node.rs @@ -50,7 +50,7 @@ use reth_transaction_pool::{ TransactionPool, TransactionValidationTaskExecutor, }; use reth_trie_db::MerklePatriciaTrie; -use revm::primitives::TxEnv; +use revm::context::TxEnv; use std::sync::Arc; /// Storage implementation for Optimism. @@ -246,7 +246,7 @@ where Storage = OpStorage, Engine = OpEngineTypes, >, - Evm: ConfigureEvmEnv, + Evm: ConfigureEvmEnv>, >, OpEthApiError: FromEvmError, <::Pool as TransactionPool>::Transaction: MaybeConditionalTransaction, @@ -318,7 +318,7 @@ where Storage = OpStorage, Engine = OpEngineTypes, >, - Evm: ConfigureEvm, + Evm: ConfigureEvm>, >, OpEthApiError: FromEvmError, <::Pool as TransactionPool>::Transaction: MaybeConditionalTransaction, diff --git a/crates/optimism/payload/Cargo.toml b/crates/optimism/payload/Cargo.toml index de637b2c7..935bea058 100644 --- a/crates/optimism/payload/Cargo.toml +++ b/crates/optimism/payload/Cargo.toml @@ -54,8 +54,8 @@ sha2.workspace = true [features] optimism = [ + "reth-provider/optimism", "reth-optimism-evm/optimism", - "revm/optimism", "reth-execution-types/optimism", "reth-optimism-consensus/optimism", "reth-optimism-primitives/optimism", diff --git a/crates/optimism/payload/src/builder.rs b/crates/optimism/payload/src/builder.rs index a17879b6f..b7e0066b1 100644 --- a/crates/optimism/payload/src/builder.rs +++ b/crates/optimism/payload/src/builder.rs @@ -21,8 +21,8 @@ use reth_basic_payload_builder::*; use reth_chain_state::{ExecutedBlock, ExecutedBlockWithTrieUpdates}; use reth_chainspec::{ChainSpecProvider, EthChainSpec, EthereumHardforks}; use reth_evm::{ - env::EvmEnv, system_calls::SystemCaller, ConfigureEvmEnv, ConfigureEvmFor, Database, Evm, - EvmError, InvalidTxError, NextBlockEnvAttributes, + system_calls::SystemCaller, ConfigureEvm, ConfigureEvmFor, Database, Evm, EvmEnv, EvmError, + HaltReasonFor, InvalidTxError, NextBlockEnvAttributes, }; use reth_execution_types::ExecutionOutcome; use reth_optimism_consensus::calculate_receipt_root_no_memo_optimism; @@ -43,13 +43,18 @@ use reth_provider::{ StateRootProvider, StorageRootProvider, }; use reth_revm::{ - cancelled::CancelOnDrop, database::StateProviderDatabase, witness::ExecutionWitnessRecord, + cancelled::CancelOnDrop, + database::StateProviderDatabase, + db::{states::bundle_state::BundleRetention, State}, + witness::ExecutionWitnessRecord, }; use reth_transaction_pool::{BestTransactionsAttributes, PoolTransaction, TransactionPool}; use reth_trie::HashedStorage; use revm::{ - db::{states::bundle_state::BundleRetention, State}, - primitives::{ExecutionResult, ResultAndState}, + context_interface::{ + result::{ExecutionResult, ResultAndState}, + Block, + }, DatabaseCommit, }; use std::{fmt::Display, sync::Arc}; @@ -57,7 +62,7 @@ use tracing::{debug, trace, warn}; /// Optimism's payload builder #[derive(Debug, Clone)] -pub struct OpPayloadBuilder { +pub struct OpPayloadBuilder { /// The rollup's compute pending block configuration option. // TODO(clabby): Implement this feature. pub compute_pending_block: bool, @@ -73,10 +78,15 @@ pub struct OpPayloadBuilder>, + pub receipt_builder: + Arc, Receipt = N::Receipt>>, } -impl OpPayloadBuilder { +impl OpPayloadBuilder +where + EvmConfig: ConfigureEvm, + N: NodePrimitives, +{ /// `OpPayloadBuilder` constructor. /// /// Configures the builder with the default settings. @@ -84,7 +94,11 @@ impl OpPayloadBuilder, + receipt_builder: impl OpReceiptBuilder< + N::SignedTx, + HaltReasonFor, + Receipt = N::Receipt, + >, ) -> Self { Self::with_builder_config(pool, client, evm_config, receipt_builder, Default::default()) } @@ -94,7 +108,11 @@ impl OpPayloadBuilder, + receipt_builder: impl OpReceiptBuilder< + N::SignedTx, + HaltReasonFor, + Receipt = N::Receipt, + >, config: OpBuilderConfig, ) -> Self { Self { @@ -109,7 +127,7 @@ impl OpPayloadBuilder +impl OpPayloadBuilder { /// Sets the rollup's compute pending block configuration option. @@ -469,7 +487,7 @@ impl OpBuilder<'_, Txs> { let header = Header { parent_hash: ctx.parent().hash(), ommers_hash: EMPTY_OMMER_ROOT_HASH, - beneficiary: ctx.evm_env.block_env.coinbase, + beneficiary: ctx.evm_env.block_env.beneficiary, state_root, transactions_root, receipts_root, @@ -642,7 +660,7 @@ impl ExecutionInfo { /// Container type that holds all necessities to build a new payload. #[derive(Debug)] -pub struct OpPayloadBuilderCtx { +pub struct OpPayloadBuilderCtx { /// The type that knows how to perform system calls and configure the evm. pub evm_config: EvmConfig, /// The DA config for the payload builder @@ -658,12 +676,13 @@ pub struct OpPayloadBuilderCtx>, /// Receipt builder. - pub receipt_builder: Arc>, + pub receipt_builder: + Arc, Receipt = N::Receipt>>, } impl OpPayloadBuilderCtx where - EvmConfig: ConfigureEvmEnv, + EvmConfig: ConfigureEvm, ChainSpec: EthChainSpec + OpHardforks, N: NodePrimitives, { @@ -686,24 +705,22 @@ where /// Returns the block gas limit to target. pub fn block_gas_limit(&self) -> u64 { - self.attributes() - .gas_limit - .unwrap_or_else(|| self.evm_env.block_env.gas_limit.saturating_to()) + self.attributes().gas_limit.unwrap_or(self.evm_env.block_env.gas_limit) } /// Returns the block number for the block. pub fn block_number(&self) -> u64 { - self.evm_env.block_env.number.to() + self.evm_env.block_env.number } /// Returns the current base fee pub fn base_fee(&self) -> u64 { - self.evm_env.block_env.basefee.to() + self.evm_env.block_env.basefee } /// Returns the current blob gas price. pub fn get_blob_gasprice(&self) -> Option { - self.evm_env.block_env.get_blob_gasprice().map(|gasprice| gasprice as u64) + self.evm_env.block_env.blob_gasprice().map(|gasprice| gasprice as u64) } /// Returns the blob fields for the header. @@ -835,7 +852,7 @@ where fn build_receipt( &self, info: &ExecutionInfo, - result: ExecutionResult, + result: ExecutionResult>, deposit_nonce: Option, tx: &N::SignedTx, ) -> N::Receipt { diff --git a/crates/optimism/primitives/Cargo.toml b/crates/optimism/primitives/Cargo.toml index a33c54652..b531303d6 100644 --- a/crates/optimism/primitives/Cargo.toml +++ b/crates/optimism/primitives/Cargo.toml @@ -21,8 +21,9 @@ reth-zstd-compressors = { workspace = true, optional = true } alloy-primitives.workspace = true alloy-consensus.workspace = true alloy-rlp.workspace = true -alloy-eips.workspace = true -revm-primitives = { workspace = true, optional = true } +alloy-eips = { workspace = true, features = ["k256"] } +revm-context.workspace = true +revm-optimism.workspace = true secp256k1 = { workspace = true, optional = true } # op @@ -64,13 +65,14 @@ std = [ "serde?/std", "bytes?/std", "derive_more/std", - "revm-primitives?/std", "secp256k1?/std", "alloy-rlp/std", "reth-zstd-compressors?/std", "op-alloy-consensus/std", + "revm-optimism/std", "alloy-rpc-types-eth?/std", "alloy-serde?/std", + "revm-context/std", ] alloy-compat = ["dep:alloy-network", "dep:alloy-serde", "dep:alloy-rpc-types-eth"] reth-codec = [ @@ -93,9 +95,10 @@ serde = [ "reth-codecs?/serde", "op-alloy-consensus/serde", "rand?/serde", - "revm-primitives?/serde", "secp256k1?/serde", + "revm-optimism/serde", "alloy-rpc-types-eth?/serde", + "revm-context/serde", ] serde-bincode-compat = [ "alloy-consensus/serde-bincode-compat", @@ -114,12 +117,8 @@ arbitrary = [ "alloy-consensus/arbitrary", "alloy-eips/arbitrary", "alloy-primitives/arbitrary", - "revm-primitives?/arbitrary", "rand", "alloy-rpc-types-eth?/arbitrary", "alloy-serde?/arbitrary", ] -optimism = [ - "dep:revm-primitives", - "revm-primitives/optimism", -] +optimism = [] diff --git a/crates/optimism/primitives/src/transaction/signed.rs b/crates/optimism/primitives/src/transaction/signed.rs index 688eb9f66..e087c6cb5 100644 --- a/crates/optimism/primitives/src/transaction/signed.rs +++ b/crates/optimism/primitives/src/transaction/signed.rs @@ -28,8 +28,10 @@ use reth_primitives_traits::{ crypto::secp256k1::{recover_signer, recover_signer_unchecked}, sync::OnceLock, transaction::{error::TransactionConversionError, signed::RecoveryError}, - InMemorySize, SignedTransaction, + FillTxEnv, InMemorySize, SignedTransaction, }; +use revm_context::TxEnv; +use revm_optimism::transaction::deposit::DepositTransactionParts; /// Signed transaction. #[cfg_attr(any(test, feature = "reth-codec"), reth_codecs::add_arbitrary_tests(rlp))] @@ -210,100 +212,106 @@ impl OpTransaction for OpTransactionSigned { } } -#[cfg(feature = "optimism")] -impl reth_primitives_traits::FillTxEnv for OpTransactionSigned { - fn fill_tx_env(&self, tx_env: &mut revm_primitives::TxEnv, sender: Address) { +impl FillTxEnv> for OpTransactionSigned { + fn fill_tx_env(&self, tx_env: &mut revm_optimism::OpTransaction, sender: Address) { let envelope = self.encoded_2718(); - tx_env.caller = sender; - match &self.transaction { - OpTypedTransaction::Legacy(tx) => { - tx_env.gas_limit = tx.gas_limit; - tx_env.gas_price = alloy_primitives::U256::from(tx.gas_price); - tx_env.gas_priority_fee = None; - tx_env.transact_to = tx.to; - tx_env.value = tx.value; - tx_env.data = tx.input.clone(); - tx_env.chain_id = tx.chain_id; - tx_env.nonce = Some(tx.nonce); - tx_env.access_list.clear(); - tx_env.blob_hashes.clear(); - tx_env.max_fee_per_blob_gas.take(); - tx_env.authorization_list = None; - } - OpTypedTransaction::Eip2930(tx) => { - tx_env.gas_limit = tx.gas_limit; - tx_env.gas_price = alloy_primitives::U256::from(tx.gas_price); - tx_env.gas_priority_fee = None; - tx_env.transact_to = tx.to; - tx_env.value = tx.value; - tx_env.data = tx.input.clone(); - tx_env.chain_id = Some(tx.chain_id); - tx_env.nonce = Some(tx.nonce); - tx_env.access_list.clone_from(&tx.access_list.0); - tx_env.blob_hashes.clear(); - tx_env.max_fee_per_blob_gas.take(); - tx_env.authorization_list = None; - } - OpTypedTransaction::Eip1559(tx) => { - tx_env.gas_limit = tx.gas_limit; - tx_env.gas_price = alloy_primitives::U256::from(tx.max_fee_per_gas); - tx_env.gas_priority_fee = - Some(alloy_primitives::U256::from(tx.max_priority_fee_per_gas)); - tx_env.transact_to = tx.to; - tx_env.value = tx.value; - tx_env.data = tx.input.clone(); - tx_env.chain_id = Some(tx.chain_id); - tx_env.nonce = Some(tx.nonce); - tx_env.access_list.clone_from(&tx.access_list.0); - tx_env.blob_hashes.clear(); - tx_env.max_fee_per_blob_gas.take(); - tx_env.authorization_list = None; - } - OpTypedTransaction::Eip7702(tx) => { - tx_env.gas_limit = tx.gas_limit; - tx_env.gas_price = alloy_primitives::U256::from(tx.max_fee_per_gas); - tx_env.gas_priority_fee = - Some(alloy_primitives::U256::from(tx.max_priority_fee_per_gas)); - tx_env.transact_to = tx.to.into(); - tx_env.value = tx.value; - tx_env.data = tx.input.clone(); - tx_env.chain_id = Some(tx.chain_id); - tx_env.nonce = Some(tx.nonce); - tx_env.access_list.clone_from(&tx.access_list.0); - tx_env.blob_hashes.clear(); - tx_env.max_fee_per_blob_gas.take(); - tx_env.authorization_list = - Some(revm_primitives::AuthorizationList::Signed(tx.authorization_list.clone())); - } - OpTypedTransaction::Deposit(tx) => { - tx_env.access_list.clear(); - tx_env.gas_limit = tx.gas_limit; - tx_env.gas_price = alloy_primitives::U256::ZERO; - tx_env.gas_priority_fee = None; - tx_env.transact_to = tx.to; - tx_env.value = tx.value; - tx_env.data = tx.input.clone(); - tx_env.chain_id = None; - tx_env.nonce = None; - tx_env.authorization_list = None; + let base = match &self.transaction { + OpTypedTransaction::Legacy(tx) => TxEnv { + gas_limit: tx.gas_limit, + gas_price: tx.gas_price, + gas_priority_fee: None, + kind: tx.to, + value: tx.value, + data: tx.input.clone(), + chain_id: tx.chain_id, + nonce: tx.nonce, + access_list: Default::default(), + blob_hashes: Default::default(), + max_fee_per_blob_gas: Default::default(), + authorization_list: Default::default(), + tx_type: 0, + caller: sender, + }, + OpTypedTransaction::Eip2930(tx) => TxEnv { + gas_limit: tx.gas_limit, + gas_price: tx.gas_price, + gas_priority_fee: None, + kind: tx.to, + value: tx.value, + data: tx.input.clone(), + chain_id: Some(tx.chain_id), + nonce: tx.nonce, + access_list: tx.access_list.clone(), + blob_hashes: Default::default(), + max_fee_per_blob_gas: Default::default(), + authorization_list: Default::default(), + tx_type: 1, + caller: sender, + }, + OpTypedTransaction::Eip1559(tx) => TxEnv { + gas_limit: tx.gas_limit, + gas_price: tx.max_fee_per_gas, + gas_priority_fee: Some(tx.max_priority_fee_per_gas), + kind: tx.to, + value: tx.value, + data: tx.input.clone(), + chain_id: Some(tx.chain_id), + nonce: tx.nonce, + access_list: tx.access_list.clone(), + blob_hashes: Default::default(), + max_fee_per_blob_gas: Default::default(), + authorization_list: Default::default(), + tx_type: 2, + caller: sender, + }, + OpTypedTransaction::Eip7702(tx) => TxEnv { + gas_limit: tx.gas_limit, + gas_price: tx.max_fee_per_gas, + gas_priority_fee: Some(tx.max_priority_fee_per_gas), + kind: TxKind::Call(tx.to), + value: tx.value, + data: tx.input.clone(), + chain_id: Some(tx.chain_id), + nonce: tx.nonce, + access_list: tx.access_list.clone(), + blob_hashes: Default::default(), + max_fee_per_blob_gas: Default::default(), + authorization_list: tx.authorization_list.clone(), + tx_type: 4, + caller: sender, + }, + OpTypedTransaction::Deposit(tx) => TxEnv { + gas_limit: tx.gas_limit, + gas_price: 0, + kind: tx.to, + value: tx.value, + data: tx.input.clone(), + chain_id: None, + nonce: 0, + access_list: Default::default(), + blob_hashes: Default::default(), + max_fee_per_blob_gas: Default::default(), + authorization_list: Default::default(), + gas_priority_fee: Default::default(), + tx_type: 126, + caller: sender, + }, + }; - tx_env.optimism = revm_primitives::OptimismFields { - source_hash: Some(tx.source_hash), - mint: tx.mint, - is_system_transaction: Some(tx.is_system_transaction), - enveloped_tx: Some(envelope.into()), - }; - return - } - } - - tx_env.optimism = revm_primitives::OptimismFields { - source_hash: None, - mint: None, - is_system_transaction: Some(false), + *tx_env = revm_optimism::OpTransaction { + base, enveloped_tx: Some(envelope.into()), - } + deposit: if let OpTypedTransaction::Deposit(tx) = &self.transaction { + DepositTransactionParts { + is_system_transaction: tx.is_system_transaction, + source_hash: tx.source_hash, + mint: tx.mint, + } + } else { + Default::default() + }, + }; } } diff --git a/crates/optimism/reth/Cargo.toml b/crates/optimism/reth/Cargo.toml index ed54f42c9..485fd5f3d 100644 --- a/crates/optimism/reth/Cargo.toml +++ b/crates/optimism/reth/Cargo.toml @@ -89,4 +89,5 @@ optimism = [ "reth-optimism-node?/optimism", "reth-optimism-primitives/optimism", "reth-optimism-rpc?/optimism", + "reth-provider?/optimism", ] diff --git a/crates/optimism/rpc/Cargo.toml b/crates/optimism/rpc/Cargo.toml index 552d4101d..75fca7e33 100644 --- a/crates/optimism/rpc/Cargo.toml +++ b/crates/optimism/rpc/Cargo.toml @@ -53,6 +53,7 @@ op-alloy-rpc-types-engine.workspace = true op-alloy-rpc-jsonrpsee.workspace = true op-alloy-consensus.workspace = true revm.workspace = true +revm-optimism.workspace = true # async parking_lot.workspace = true @@ -77,7 +78,7 @@ reth-optimism-chainspec.workspace = true [features] optimism = [ "reth-optimism-evm/optimism", - "revm/optimism", + "reth-provider/optimism", "reth-optimism-consensus/optimism", "reth-optimism-payload-builder/optimism", "reth-optimism-primitives/optimism", diff --git a/crates/optimism/rpc/src/error.rs b/crates/optimism/rpc/src/error.rs index 01388cc8d..be0fcc02f 100644 --- a/crates/optimism/rpc/src/error.rs +++ b/crates/optimism/rpc/src/error.rs @@ -6,7 +6,8 @@ use reth_optimism_evm::OpBlockExecutionError; use reth_rpc_eth_api::AsEthApiError; use reth_rpc_eth_types::{error::api::FromEvmHalt, EthApiError}; use reth_rpc_server_types::result::{internal_rpc_err, rpc_err}; -use revm::primitives::{EVMError, HaltReason, InvalidTransaction, OptimismInvalidTransaction}; +use revm::context_interface::result::{EVMError, InvalidTransaction}; +use revm_optimism::{OpHaltReason, OpTransactionError}; /// Optimism specific errors, that extend [`EthApiError`]. #[derive(Debug, thiserror::Error)] @@ -79,20 +80,16 @@ impl From for jsonrpsee_types::error::ErrorObject<'st } } -impl TryFrom for OpInvalidTransactionError { +impl TryFrom for OpInvalidTransactionError { type Error = InvalidTransaction; - fn try_from(err: InvalidTransaction) -> Result { + fn try_from(err: OpTransactionError) -> Result { match err { - InvalidTransaction::OptimismError(err) => match err { - OptimismInvalidTransaction::DepositSystemTxPostRegolith => { - Ok(Self::DepositSystemTxPostRegolith) - } - OptimismInvalidTransaction::HaltedDepositPostRegolith => { - Ok(Self::HaltedDepositPostRegolith) - } - }, - _ => Err(err), + OpTransactionError::DepositSystemTxPostRegolith => { + Ok(Self::DepositSystemTxPostRegolith) + } + OpTransactionError::HaltedDepositPostRegolith => Ok(Self::HaltedDepositPostRegolith), + OpTransactionError::Base(err) => Err(err), } } } @@ -145,17 +142,31 @@ impl From for OpEthApiError { } } -impl From> for OpEthApiError +impl From> for OpEthApiError where - EthApiError: From>, + T: Into, { - fn from(error: EVMError) -> Self { - Self::Eth(error.into()) + fn from(error: EVMError) -> Self { + match error { + EVMError::Transaction(err) => match err.try_into() { + Ok(err) => Self::InvalidTransaction(err), + Err(err) => Self::Eth(EthApiError::InvalidTransaction(err.into())), + }, + EVMError::Database(err) => Self::Eth(err.into()), + EVMError::Header(err) => Self::Eth(err.into()), + EVMError::Precompile(err) => Self::Eth(EthApiError::EvmPrecompile(err)), + EVMError::Custom(err) => Self::Eth(EthApiError::EvmCustom(err)), + } } } -impl FromEvmHalt for OpEthApiError { - fn from_evm_halt(halt: HaltReason, gas_limit: u64) -> Self { - EthApiError::from_evm_halt(halt, gas_limit).into() +impl FromEvmHalt for OpEthApiError { + fn from_evm_halt(halt: OpHaltReason, gas_limit: u64) -> Self { + match halt { + OpHaltReason::FailedDeposit => { + OpInvalidTransactionError::HaltedDepositPostRegolith.into() + } + OpHaltReason::Base(halt) => EthApiError::from_evm_halt(halt, gas_limit).into(), + } } } diff --git a/crates/optimism/rpc/src/eth/block.rs b/crates/optimism/rpc/src/eth/block.rs index 72ddfa0df..83a9ce7f2 100644 --- a/crates/optimism/rpc/src/eth/block.rs +++ b/crates/optimism/rpc/src/eth/block.rs @@ -59,11 +59,6 @@ where timestamp, }; - // We must clear this cache as different L2 transactions can have different - // L1 costs. A potential improvement here is to only clear the cache if the - // new transaction input has changed, since otherwise the L1 cost wouldn't. - l1_block_info.clear_tx_l1_cost(); - Ok(OpReceiptBuilder::new( &self.inner.eth_api.provider().chain_spec(), tx, diff --git a/crates/optimism/rpc/src/eth/call.rs b/crates/optimism/rpc/src/eth/call.rs index 21f2792b1..4bd4d9d51 100644 --- a/crates/optimism/rpc/src/eth/call.rs +++ b/crates/optimism/rpc/src/eth/call.rs @@ -2,14 +2,15 @@ use super::OpNodeCore; use crate::{OpEthApi, OpEthApiError}; use alloy_primitives::{Bytes, TxKind, U256}; use alloy_rpc_types_eth::transaction::TransactionRequest; -use reth_evm::ConfigureEvm; +use reth_evm::{ConfigureEvm, EvmEnv, SpecFor}; use reth_provider::ProviderHeader; use reth_rpc_eth_api::{ helpers::{estimate::EstimateCall, Call, EthCall, LoadBlock, LoadState, SpawnBlocking}, FromEthApiError, FromEvmError, FullEthApiTypes, IntoEthApiError, }; -use reth_rpc_eth_types::{revm_utils::CallFees, RpcInvalidTransactionError}; -use revm::primitives::{BlockEnv, OptimismFields, TxEnv}; +use reth_rpc_eth_types::{revm_utils::CallFees, EthApiError, RpcInvalidTransactionError}; +use revm::{context::TxEnv, context_interface::Block, Database}; +use revm_optimism::OpTransaction; impl EthCall for OpEthApi where @@ -29,7 +30,10 @@ where impl Call for OpEthApi where Self: LoadState< - Evm: ConfigureEvm
, TxEnv = TxEnv>, + Evm: ConfigureEvm< + Header = ProviderHeader, + TxEnv = OpTransaction, + >, Error: FromEvmError, > + SpawnBlocking, Self::Error: From, @@ -47,14 +51,17 @@ where fn create_txn_env( &self, - block_env: &BlockEnv, + evm_env: &EvmEnv>, request: TransactionRequest, - ) -> Result { + mut db: impl Database>, + ) -> Result, Self::Error> { // Ensure that if versioned hashes are set, they're not empty if request.blob_versioned_hashes.as_ref().is_some_and(|hashes| hashes.is_empty()) { return Err(RpcInvalidTransactionError::BlobTransactionMissingBlobHashes.into_eth_err()) } + let tx_type = request.preferred_type() as u8; + let TransactionRequest { from, to, @@ -70,7 +77,8 @@ where blob_versioned_hashes, max_fee_per_blob_gas, authorization_list, - .. + transaction_type: _, + sidecar: _, } = request; let CallFees { max_priority_fee_per_gas, gas_price, max_fee_per_blob_gas } = @@ -78,36 +86,55 @@ where gas_price.map(U256::from), max_fee_per_gas.map(U256::from), max_priority_fee_per_gas.map(U256::from), - block_env.basefee, + U256::from(evm_env.block_env.basefee), blob_versioned_hashes.as_deref(), max_fee_per_blob_gas.map(U256::from), - block_env.get_blob_gasprice().map(U256::from), + evm_env.block_env.blob_gasprice().map(U256::from), )?; - let gas_limit = gas.unwrap_or_else(|| block_env.gas_limit.min(U256::from(u64::MAX)).to()); + let gas_limit = gas.unwrap_or( + // Use maximum allowed gas limit. The reason for this + // is that both Erigon and Geth use pre-configured gas cap even if + // it's possible to derive the gas limit from the block: + // + evm_env.block_env.gas_limit, + ); - #[allow(clippy::needless_update)] - let env = TxEnv { + let chain_id = chain_id.unwrap_or(evm_env.cfg_env.chain_id); + + let caller = from.unwrap_or_default(); + + let nonce = if let Some(nonce) = nonce { + nonce + } else { + db.basic(caller).map_err(Into::into)?.map(|acc| acc.nonce).unwrap_or_default() + }; + + let base = TxEnv { + tx_type, gas_limit, nonce, - caller: from.unwrap_or_default(), - gas_price, - gas_priority_fee: max_priority_fee_per_gas, - transact_to: to.unwrap_or(TxKind::Create), + caller, + gas_price: gas_price.saturating_to(), + gas_priority_fee: max_priority_fee_per_gas.map(|v| v.saturating_to()), + kind: to.unwrap_or(TxKind::Create), value: value.unwrap_or_default(), data: input .try_into_unique_input() .map_err(Self::Error::from_eth_err)? .unwrap_or_default(), - chain_id, - access_list: access_list.unwrap_or_default().into(), + chain_id: Some(chain_id), + access_list: access_list.unwrap_or_default(), // EIP-4844 fields blob_hashes: blob_versioned_hashes.unwrap_or_default(), - max_fee_per_blob_gas, - authorization_list: authorization_list.map(Into::into), - optimism: OptimismFields { enveloped_tx: Some(Bytes::new()), ..Default::default() }, + max_fee_per_blob_gas: max_fee_per_blob_gas + .map(|v| v.saturating_to()) + .unwrap_or_default(), + // EIP-7702 fields + authorization_list: authorization_list.unwrap_or_default(), }; - Ok(env) + Ok(OpTransaction { base, enveloped_tx: Some(Bytes::new()), deposit: Default::default() }) } } diff --git a/crates/optimism/rpc/src/eth/pending_block.rs b/crates/optimism/rpc/src/eth/pending_block.rs index a81938c02..92a318920 100644 --- a/crates/optimism/rpc/src/eth/pending_block.rs +++ b/crates/optimism/rpc/src/eth/pending_block.rs @@ -9,7 +9,7 @@ use alloy_eips::{eip7685::EMPTY_REQUESTS_HASH, merge::BEACON_NONCE, BlockNumberO use alloy_primitives::{B256, U256}; use op_alloy_consensus::{OpDepositReceipt, OpTxType}; use reth_chainspec::{EthChainSpec, EthereumHardforks}; -use reth_evm::ConfigureEvm; +use reth_evm::{ConfigureEvm, HaltReasonFor}; use reth_optimism_consensus::calculate_receipt_root_no_memo_optimism; use reth_optimism_forks::OpHardforks; use reth_optimism_primitives::{OpBlock, OpReceipt, OpTransactionSigned}; @@ -25,7 +25,10 @@ use reth_rpc_eth_api::{ }; use reth_rpc_eth_types::{EthApiError, PendingBlock}; use reth_transaction_pool::{PoolTransaction, TransactionPool}; -use revm::primitives::{BlockEnv, ExecutionResult}; +use revm::{ + context::BlockEnv, + context_interface::{result::ExecutionResult, Block}, +}; impl LoadPendingBlock for OpEthApi where @@ -101,7 +104,7 @@ where receipts: &[ProviderReceipt], ) -> reth_provider::ProviderBlock { let chain_spec = self.provider().chain_spec(); - let timestamp = block_env.timestamp.to::(); + let timestamp = block_env.timestamp; let transactions_root = calculate_transaction_root(&transactions); let receipts_root = @@ -115,7 +118,7 @@ where let header = Header { parent_hash, ommers_hash: EMPTY_OMMER_ROOT_HASH, - beneficiary: block_env.coinbase, + beneficiary: block_env.beneficiary, state_root, transactions_root, receipts_root, @@ -124,15 +127,15 @@ where timestamp, mix_hash: block_env.prevrandao.unwrap_or_default(), nonce: BEACON_NONCE.into(), - base_fee_per_gas: Some(block_env.basefee.to::()), - number: block_env.number.to::(), - gas_limit: block_env.gas_limit.to::(), + base_fee_per_gas: Some(block_env.basefee), + number: block_env.number, + gas_limit: block_env.gas_limit, difficulty: U256::ZERO, gas_used: receipts.last().map(|r| r.cumulative_gas_used()).unwrap_or_default(), blob_gas_used: is_cancun.then(|| { transactions.iter().map(|tx| tx.blob_gas_used().unwrap_or_default()).sum::() }), - excess_blob_gas: block_env.get_blob_excess_gas(), + excess_blob_gas: block_env.blob_excess_gas(), extra_data: Default::default(), parent_beacon_block_root: is_cancun.then_some(B256::ZERO), requests_hash: is_prague.then_some(EMPTY_REQUESTS_HASH), @@ -148,7 +151,7 @@ where fn assemble_receipt( &self, tx: &ProviderTx, - result: ExecutionResult, + result: ExecutionResult>, cumulative_gas_used: u64, ) -> reth_provider::ProviderReceipt { let receipt = alloy_consensus::Receipt { diff --git a/crates/optimism/rpc/src/eth/receipt.rs b/crates/optimism/rpc/src/eth/receipt.rs index 064fcf0ee..513a46537 100644 --- a/crates/optimism/rpc/src/eth/receipt.rs +++ b/crates/optimism/rpc/src/eth/receipt.rs @@ -111,12 +111,12 @@ impl OpReceiptFieldsBuilder { } } - /// Applies [`L1BlockInfo`](revm::L1BlockInfo). + /// Applies [`L1BlockInfo`](revm_optimism::L1BlockInfo). pub fn l1_block_info( mut self, chain_spec: &OpChainSpec, tx: &OpTransactionSigned, - l1_block_info: &mut revm::L1BlockInfo, + l1_block_info: &mut revm_optimism::L1BlockInfo, ) -> Result { let raw_tx = tx.encoded_2718(); let block_number = self.block_number; @@ -218,7 +218,7 @@ impl OpReceiptBuilder { meta: TransactionMeta, receipt: &OpReceipt, all_receipts: &[OpReceipt], - l1_block_info: &mut revm::L1BlockInfo, + l1_block_info: &mut revm_optimism::L1BlockInfo, ) -> Result { let timestamp = meta.timestamp; let block_number = meta.block_number; diff --git a/crates/optimism/rpc/src/witness.rs b/crates/optimism/rpc/src/witness.rs index 3bf9c30cc..7e2e221df 100644 --- a/crates/optimism/rpc/src/witness.rs +++ b/crates/optimism/rpc/src/witness.rs @@ -5,7 +5,7 @@ use alloy_rpc_types_debug::ExecutionWitness; use jsonrpsee_core::{async_trait, RpcResult}; use op_alloy_rpc_types_engine::OpPayloadAttributes; use reth_chainspec::ChainSpecProvider; -use reth_evm::ConfigureEvmFor; +use reth_evm::{ConfigureEvm, ConfigureEvmFor}; use reth_node_api::NodePrimitives; use reth_optimism_chainspec::OpChainSpec; use reth_optimism_payload_builder::{OpPayloadBuilder, OpPayloadPrimitives}; @@ -21,11 +21,11 @@ use std::{fmt::Debug, sync::Arc}; use tokio::sync::{oneshot, Semaphore}; /// An extension to the `debug_` namespace of the RPC API. -pub struct OpDebugWitnessApi { +pub struct OpDebugWitnessApi { inner: Arc>, } -impl +impl OpDebugWitnessApi { /// Creates a new instance of the `OpDebugWitnessApi`. @@ -42,6 +42,7 @@ impl impl OpDebugWitnessApi where + EvmConfig: ConfigureEvm, Provider: NodePrimitivesProvider + BlockReaderIdExt
, { /// Fetches the parent header by hash. @@ -94,6 +95,7 @@ where impl Clone for OpDebugWitnessApi where + EvmConfig: ConfigureEvm, Provider: NodePrimitivesProvider, { fn clone(&self) -> Self { @@ -102,6 +104,7 @@ where } impl Debug for OpDebugWitnessApi where + EvmConfig: ConfigureEvm, Provider: NodePrimitivesProvider, { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { @@ -109,7 +112,7 @@ where } } -struct OpDebugWitnessApiInner { +struct OpDebugWitnessApiInner { provider: Provider, builder: OpPayloadBuilder, task_spawner: Box, diff --git a/crates/optimism/txpool/Cargo.toml b/crates/optimism/txpool/Cargo.toml index 90cd92a61..4af571263 100644 --- a/crates/optimism/txpool/Cargo.toml +++ b/crates/optimism/txpool/Cargo.toml @@ -26,7 +26,7 @@ reth-storage-api.workspace = true reth-transaction-pool.workspace = true # revm -revm.workspace = true +revm-optimism.workspace = true # optimism op-alloy-consensus.workspace = true @@ -53,5 +53,5 @@ reth-provider = { workspace = true, features = ["test-utils"] } optimism = [ "reth-optimism-evm/optimism", "reth-optimism-primitives/optimism", - "revm/optimism", + "reth-provider/optimism", ] diff --git a/crates/optimism/txpool/src/validator.rs b/crates/optimism/txpool/src/validator.rs index cd41475dc..123142ae7 100644 --- a/crates/optimism/txpool/src/validator.rs +++ b/crates/optimism/txpool/src/validator.rs @@ -12,7 +12,7 @@ use reth_transaction_pool::{ EthPoolTransaction, EthTransactionValidator, TransactionOrigin, TransactionValidationOutcome, TransactionValidator, }; -use revm::L1BlockInfo; +use revm_optimism::L1BlockInfo; use std::sync::{ atomic::{AtomicU64, Ordering}, Arc, diff --git a/crates/payload/basic/src/lib.rs b/crates/payload/basic/src/lib.rs index 84995d3e7..8bae47f60 100644 --- a/crates/payload/basic/src/lib.rs +++ b/crates/payload/basic/src/lib.rs @@ -22,9 +22,9 @@ use reth_payload_primitives::{BuiltPayload, PayloadBuilderAttributes, PayloadKin use reth_primitives::{NodePrimitives, SealedHeader}; use reth_primitives_traits::{proofs, HeaderTy}; use reth_provider::{BlockReaderIdExt, CanonStateNotification, StateProviderFactory}; -use reth_revm::{cached::CachedReads, cancelled::CancelOnDrop}; +use reth_revm::{cached::CachedReads, cancelled::CancelOnDrop, db::State}; use reth_tasks::TaskSpawner; -use revm::{Database, State}; +use revm::Database; use std::{ fmt, future::Future, diff --git a/crates/primitives-traits/Cargo.toml b/crates/primitives-traits/Cargo.toml index 1882d1ae0..4b89d7cdb 100644 --- a/crates/primitives-traits/Cargo.toml +++ b/crates/primitives-traits/Cargo.toml @@ -19,10 +19,12 @@ reth-codecs = { workspace = true, optional = true } alloy-consensus.workspace = true alloy-eips.workspace = true alloy-genesis.workspace = true -alloy-primitives.workspace = true +alloy-primitives = { workspace = true, features = ["k256"] } alloy-rlp.workspace = true alloy-trie.workspace = true revm-primitives.workspace = true +revm-bytecode.workspace = true +revm-state.workspace = true # op op-alloy-consensus = { workspace = true, optional = true } @@ -90,6 +92,8 @@ std = [ "op-alloy-consensus?/std", "serde_json/std", "reth-chainspec/std", + "revm-bytecode/std", + "revm-state/std", ] secp256k1 = ["dep:secp256k1"] test-utils = [ @@ -134,6 +138,8 @@ serde = [ "k256/serde", "secp256k1?/serde", "alloy-trie/serde", + "revm-bytecode/serde", + "revm-state/serde", ] reth-codec = [ "dep:reth-codecs", diff --git a/crates/primitives-traits/src/account.rs b/crates/primitives-traits/src/account.rs index 64ce209e7..a6f301be8 100644 --- a/crates/primitives-traits/src/account.rs +++ b/crates/primitives-traits/src/account.rs @@ -3,24 +3,25 @@ use alloy_genesis::GenesisAccount; use alloy_primitives::{keccak256, Bytes, B256, U256}; use alloy_trie::TrieAccount; use derive_more::Deref; -use revm_primitives::{AccountInfo, Bytecode as RevmBytecode, BytecodeDecodeError}; +use revm_bytecode::{Bytecode as RevmBytecode, BytecodeDecodeError}; +use revm_state::AccountInfo; #[cfg(any(test, feature = "reth-codec"))] /// Identifiers used in [`Compact`](reth_codecs::Compact) encoding of [`Bytecode`]. pub mod compact_ids { - /// Identifier for [`LegacyRaw`](revm_primitives::Bytecode::LegacyRaw). + /// Identifier for legacy raw bytecode. pub const LEGACY_RAW_BYTECODE_ID: u8 = 0; /// Identifier for removed bytecode variant. pub const REMOVED_BYTECODE_ID: u8 = 1; - /// Identifier for [`LegacyAnalyzed`](revm_primitives::Bytecode::LegacyAnalyzed). + /// Identifier for [`LegacyAnalyzed`](revm_bytecode::Bytecode::LegacyAnalyzed). pub const LEGACY_ANALYZED_BYTECODE_ID: u8 = 2; - /// Identifier for [`Eof`](revm_primitives::Bytecode::Eof). + /// Identifier for [`Eof`](revm_bytecode::Bytecode::Eof). pub const EOF_BYTECODE_ID: u8 = 3; - /// Identifier for [`Eip7702`](revm_primitives::Bytecode::Eip7702). + /// Identifier for [`Eip7702`](revm_bytecode::Bytecode::Eip7702). pub const EIP7702_BYTECODE_ID: u8 = 4; } @@ -90,7 +91,7 @@ impl Bytecode { Self(RevmBytecode::new_raw(bytes)) } - /// Creates a new raw [`revm_primitives::Bytecode`]. + /// Creates a new raw [`revm_bytecode::Bytecode`]. /// /// Returns an error on incorrect Bytecode format. #[inline] @@ -105,13 +106,9 @@ impl reth_codecs::Compact for Bytecode { where B: bytes::BufMut + AsMut<[u8]>, { - use compact_ids::{ - EIP7702_BYTECODE_ID, EOF_BYTECODE_ID, LEGACY_ANALYZED_BYTECODE_ID, - LEGACY_RAW_BYTECODE_ID, - }; + use compact_ids::{EIP7702_BYTECODE_ID, EOF_BYTECODE_ID, LEGACY_ANALYZED_BYTECODE_ID}; let bytecode = match &self.0 { - RevmBytecode::LegacyRaw(bytes) => bytes, RevmBytecode::LegacyAnalyzed(analyzed) => analyzed.bytecode(), RevmBytecode::Eof(eof) => eof.raw(), RevmBytecode::Eip7702(eip7702) => eip7702.raw(), @@ -119,10 +116,6 @@ impl reth_codecs::Compact for Bytecode { buf.put_u32(bytecode.len() as u32); buf.put_slice(bytecode.as_ref()); let len = match &self.0 { - RevmBytecode::LegacyRaw(_) => { - buf.put_u8(LEGACY_RAW_BYTECODE_ID); - 1 - } // [`REMOVED_BYTECODE_ID`] has been removed. RevmBytecode::LegacyAnalyzed(analyzed) => { buf.put_u8(LEGACY_ANALYZED_BYTECODE_ID); @@ -165,7 +158,7 @@ impl reth_codecs::Compact for Bytecode { RevmBytecode::new_analyzed( bytes, buf.read_u64::().unwrap() as usize, - revm_primitives::JumpTable::from_slice(buf), + revm_bytecode::JumpTable::from_slice(buf), ) }), EOF_BYTECODE_ID | EIP7702_BYTECODE_ID => { @@ -221,11 +214,10 @@ impl From for AccountInfo { #[cfg(test)] mod tests { + use super::*; use alloy_primitives::{hex_literal::hex, B256, U256}; use reth_codecs::Compact; - use revm_primitives::{JumpTable, LegacyAnalyzedBytecode}; - - use super::*; + use revm_bytecode::{JumpTable, LegacyAnalyzedBytecode}; #[test] fn test_account() { @@ -273,12 +265,12 @@ mod tests { let mut buf = vec![]; let bytecode = Bytecode::new_raw(Bytes::default()); let len = bytecode.to_compact(&mut buf); - assert_eq!(len, 5); + assert_eq!(len, 46); let mut buf = vec![]; let bytecode = Bytecode::new_raw(Bytes::from(&hex!("ffff"))); let len = bytecode.to_compact(&mut buf); - assert_eq!(len, 7); + assert_eq!(len, 49); let mut buf = vec![]; let bytecode = Bytecode(RevmBytecode::LegacyAnalyzed(LegacyAnalyzedBytecode::new( diff --git a/crates/primitives-traits/src/transaction/execute.rs b/crates/primitives-traits/src/transaction/execute.rs index c7350f194..0d16e2fa4 100644 --- a/crates/primitives-traits/src/transaction/execute.rs +++ b/crates/primitives-traits/src/transaction/execute.rs @@ -1,10 +1,9 @@ //! Abstraction of an executable transaction. use alloy_primitives::Address; -use revm_primitives::TxEnv; /// Loads transaction into execution environment. -pub trait FillTxEnv { - /// Fills [`TxEnv`] with an [`Address`] and transaction. +pub trait FillTxEnv { + /// Fills `TxEnv` with an [`Address`] and transaction. fn fill_tx_env(&self, tx_env: &mut TxEnv, sender: Address); } diff --git a/crates/primitives-traits/src/transaction/signed.rs b/crates/primitives-traits/src/transaction/signed.rs index 48d059d8c..9979a3fcf 100644 --- a/crates/primitives-traits/src/transaction/signed.rs +++ b/crates/primitives-traits/src/transaction/signed.rs @@ -2,7 +2,7 @@ use crate::{ crypto::secp256k1::{recover_signer, recover_signer_unchecked}, - FillTxEnv, InMemorySize, MaybeCompact, MaybeSerde, MaybeSerdeBincodeCompat, + InMemorySize, MaybeCompact, MaybeSerde, MaybeSerdeBincodeCompat, }; use alloc::{fmt, vec::Vec}; use alloy_consensus::{ @@ -14,15 +14,8 @@ use alloy_primitives::{keccak256, Address, PrimitiveSignature as Signature, TxHa use core::hash::Hash; /// Helper trait that unifies all behaviour required by block to support full node operations. -pub trait FullSignedTx: - SignedTransaction + FillTxEnv + MaybeCompact + MaybeSerdeBincodeCompat -{ -} - -impl FullSignedTx for T where - T: SignedTransaction + FillTxEnv + MaybeCompact + MaybeSerdeBincodeCompat -{ -} +pub trait FullSignedTx: SignedTransaction + MaybeCompact + MaybeSerdeBincodeCompat {} +impl FullSignedTx for T where T: SignedTransaction + MaybeCompact + MaybeSerdeBincodeCompat {} /// A signed transaction. #[auto_impl::auto_impl(&, Arc)] diff --git a/crates/revm/Cargo.toml b/crates/revm/Cargo.toml index 9edaad908..d6c009d74 100644 --- a/crates/revm/Cargo.toml +++ b/crates/revm/Cargo.toml @@ -23,6 +23,8 @@ alloy-primitives.workspace = true # revm revm.workspace = true +revm-database.workspace = true +revm-inspector.workspace = true [dev-dependencies] reth-trie.workspace = true @@ -33,13 +35,15 @@ alloy-consensus.workspace = true [features] default = ["std"] std = [ - "alloy-consensus/std", - "alloy-primitives/std", - "reth-ethereum-forks/std", "reth-primitives-traits/std", - "reth-storage-errors/std", + "alloy-primitives/std", "revm/std", + "alloy-consensus/std", + "reth-ethereum-forks/std", + "revm-database/std", + "revm-inspector/std", "reth-storage-api/std", + "reth-storage-errors/std", ] witness = ["dep:reth-trie"] test-utils = [ @@ -54,5 +58,7 @@ serde = [ "alloy-consensus/serde", "reth-trie?/serde", "reth-ethereum-forks/serde", + "revm-database/serde", "reth-primitives-traits/serde", + "revm-inspector/serde", ] diff --git a/crates/revm/src/cached.rs b/crates/revm/src/cached.rs index 5d5262adc..83b10ba65 100644 --- a/crates/revm/src/cached.rs +++ b/crates/revm/src/cached.rs @@ -4,10 +4,7 @@ use alloy_primitives::{ Address, B256, U256, }; use core::cell::RefCell; -use revm::primitives::{ - db::{Database, DatabaseRef}, - AccountInfo, Bytecode, -}; +use revm::{bytecode::Bytecode, state::AccountInfo, Database, DatabaseRef}; /// A container type that caches reads from an underlying [`DatabaseRef`]. /// @@ -17,8 +14,7 @@ use revm::primitives::{ /// # Example /// /// ``` -/// use reth_revm::cached::CachedReads; -/// use revm::db::{DatabaseRef, State}; +/// use reth_revm::{cached::CachedReads, DatabaseRef, db::State}; /// /// fn build_payload(db: DB) { /// let mut cached_reads = CachedReads::default(); diff --git a/crates/revm/src/database.rs b/crates/revm/src/database.rs index e039ca9d6..fafe990c3 100644 --- a/crates/revm/src/database.rs +++ b/crates/revm/src/database.rs @@ -4,11 +4,7 @@ use core::ops::{Deref, DerefMut}; use reth_primitives_traits::Account; use reth_storage_api::{AccountReader, BlockHashReader, StateProvider}; use reth_storage_errors::provider::{ProviderError, ProviderResult}; -use revm::{ - db::DatabaseRef, - primitives::{AccountInfo, Bytecode}, - Database, -}; +use revm::{bytecode::Bytecode, state::AccountInfo, Database, DatabaseRef}; /// A helper trait responsible for providing state necessary for EVM execution. /// diff --git a/crates/revm/src/either.rs b/crates/revm/src/either.rs index e93ba3a8d..e26d2ccb7 100644 --- a/crates/revm/src/either.rs +++ b/crates/revm/src/either.rs @@ -1,8 +1,5 @@ use alloy_primitives::{Address, B256, U256}; -use revm::{ - primitives::{AccountInfo, Bytecode}, - Database, -}; +use revm::{bytecode::Bytecode, state::AccountInfo, Database}; /// An enum type that can hold either of two different [`Database`] implementations. /// diff --git a/crates/revm/src/lib.rs b/crates/revm/src/lib.rs index 0a95d7480..5d91c1ca5 100644 --- a/crates/revm/src/lib.rs +++ b/crates/revm/src/lib.rs @@ -21,6 +21,9 @@ pub mod cancelled; /// Contains glue code for integrating reth database into revm's [Database]. pub mod database; +pub use revm_database as db; +pub use revm_inspector as inspector; + /// Common test helpers #[cfg(any(test, feature = "test-utils"))] pub mod test_utils; diff --git a/crates/revm/src/test_utils.rs b/crates/revm/src/test_utils.rs index de4b35093..07f93c6c1 100644 --- a/crates/revm/src/test_utils.rs +++ b/crates/revm/src/test_utils.rs @@ -151,7 +151,7 @@ impl StateProofProvider for StateProviderTest { } impl HashedPostStateProvider for StateProviderTest { - fn hashed_post_state(&self, bundle_state: &revm::db::BundleState) -> HashedPostState { + fn hashed_post_state(&self, bundle_state: &revm_database::BundleState) -> HashedPostState { HashedPostState::from_bundle_state::(bundle_state.state()) } } diff --git a/crates/revm/src/witness.rs b/crates/revm/src/witness.rs index 0df5751ee..ce6494177 100644 --- a/crates/revm/src/witness.rs +++ b/crates/revm/src/witness.rs @@ -1,6 +1,6 @@ use alloy_primitives::{keccak256, map::B256Map, Bytes, B256}; use reth_trie::{HashedPostState, HashedStorage}; -use revm::State; +use revm_database::State; /// Tracks state changes during execution. #[derive(Debug, Clone, Default)] diff --git a/crates/rpc/rpc-eth-api/Cargo.toml b/crates/rpc/rpc-eth-api/Cargo.toml index 6f65b91d8..76d0b92f6 100644 --- a/crates/rpc/rpc-eth-api/Cargo.toml +++ b/crates/rpc/rpc-eth-api/Cargo.toml @@ -13,9 +13,9 @@ workspace = true [dependencies] # reth -revm.workspace = true +revm = { workspace = true, features = ["optional_block_gas_limit", "optional_eip3607", "optional_no_base_fee"] } revm-inspectors.workspace = true -revm-primitives = { workspace = true, features = ["dev"] } +revm-primitives = { workspace = true } reth-primitives-traits.workspace = true reth-errors.workspace = true reth-evm.workspace = true diff --git a/crates/rpc/rpc-eth-api/src/helpers/call.rs b/crates/rpc/rpc-eth-api/src/helpers/call.rs index a28ba704d..998d53b14 100644 --- a/crates/rpc/rpc-eth-api/src/helpers/call.rs +++ b/crates/rpc/rpc-eth-api/src/helpers/call.rs @@ -3,8 +3,7 @@ use super::{LoadBlock, LoadPendingBlock, LoadState, LoadTransaction, SpawnBlocking, Trace}; use crate::{ - helpers::estimate::EstimateCall, FromEthApiError, FromEvmError, FullEthApiTypes, RpcBlock, - RpcNodeCore, + helpers::estimate::EstimateCall, FromEvmError, FullEthApiTypes, RpcBlock, RpcNodeCore, }; use alloy_consensus::BlockHeader; use alloy_eips::{eip1559::calc_next_block_base_fee, eip2930::AccessListResult}; @@ -18,16 +17,14 @@ use alloy_rpc_types_eth::{ use futures::Future; use reth_chainspec::EthChainSpec; use reth_errors::ProviderError; -use reth_evm::{env::EvmEnv, ConfigureEvm, ConfigureEvmEnv, Database, Evm, TransactionEnv}; +use reth_evm::{ + ConfigureEvm, ConfigureEvmEnv, Evm, EvmEnv, HaltReasonFor, InspectorFor, SpecFor, + TransactionEnv, +}; use reth_node_api::BlockBody; use reth_primitives_traits::SignedTransaction; use reth_provider::{BlockIdReader, ChainSpecProvider, ProviderHeader}; -use reth_revm::{ - database::StateProviderDatabase, - db::CacheDB, - primitives::{BlockEnv, ExecutionResult, ResultAndState}, - DatabaseRef, -}; +use reth_revm::{database::StateProviderDatabase, db::CacheDB, DatabaseRef}; use reth_rpc_eth_types::{ cache::db::{StateCacheDbRefMutWrapper, StateProviderTraitObjWrapper}, error::{api::FromEvmHalt, ensure_success}, @@ -35,7 +32,13 @@ use reth_rpc_eth_types::{ simulate::{self, EthSimulateError}, EthApiError, RevertError, RpcInvalidTransactionError, StateCacheDb, }; -use revm::{DatabaseCommit, GetInspector}; +use revm::{ + context_interface::{ + result::{ExecutionResult, ResultAndState}, + Transaction, + }, + Database, DatabaseCommit, +}; use revm_inspectors::{access_list::AccessListInspector, transfer::TransferInspector}; use tracing::trace; @@ -106,12 +109,12 @@ pub trait EthCall: EstimateCall + Call + LoadPendingBlock + LoadBlock + FullEthA let chain_spec = RpcNodeCore::provider(&this).chain_spec(); while let Some(block) = block_state_calls.next() { // Increase number and timestamp for every new block - evm_env.block_env.number += U256::from(1); - evm_env.block_env.timestamp += U256::from(1); + evm_env.block_env.number += 1; + evm_env.block_env.timestamp += 1; if validation { - let base_fee_params = chain_spec - .base_fee_params_at_timestamp(evm_env.block_env.timestamp.to()); + let base_fee_params = + chain_spec.base_fee_params_at_timestamp(evm_env.block_env.timestamp); let base_fee = if let Some(latest) = blocks.last() { let header = &latest.inner.header; calc_next_block_base_fee( @@ -123,9 +126,9 @@ pub trait EthCall: EstimateCall + Call + LoadPendingBlock + LoadBlock + FullEthA } else { base_block.next_block_base_fee(base_fee_params).unwrap_or_default() }; - evm_env.block_env.basefee = U256::from(base_fee); + evm_env.block_env.basefee = base_fee; } else { - evm_env.block_env.basefee = U256::ZERO; + evm_env.block_env.basefee = 0; } let SimBlock { block_overrides, state_overrides, calls } = block; @@ -137,7 +140,7 @@ pub trait EthCall: EstimateCall + Call + LoadPendingBlock + LoadBlock + FullEthA apply_state_overrides(state_overrides, &mut db)?; } - if (total_gas_limit - gas_used) < evm_env.block_env.gas_limit.to() { + if (total_gas_limit - gas_used) < evm_env.block_env.gas_limit { return Err( EthApiError::Other(Box::new(EthSimulateError::GasLimitReached)).into() ) @@ -148,7 +151,7 @@ pub trait EthCall: EstimateCall + Call + LoadPendingBlock + LoadBlock + FullEthA let txs_without_gas_limit = calls.iter().filter(|tx| tx.gas.is_none()).count(); - if total_specified_gas > evm_env.block_env.gas_limit.to() { + if total_specified_gas > evm_env.block_env.gas_limit { return Err(EthApiError::Other(Box::new( EthSimulateError::BlockGasLimitExceeded, )) @@ -156,7 +159,7 @@ pub trait EthCall: EstimateCall + Call + LoadPendingBlock + LoadBlock + FullEthA } if txs_without_gas_limit > 0 { - (evm_env.block_env.gas_limit.to::() - total_specified_gas) / + (evm_env.block_env.gas_limit - total_specified_gas) / txs_without_gas_limit as u64 } else { 0 @@ -252,7 +255,7 @@ pub trait EthCall: EstimateCall + Call + LoadPendingBlock + LoadBlock + FullEthA let (res, _env) = self.transact_call_at(request, block_number.unwrap_or_default(), overrides).await?; - ensure_success(res.result).map_err(Self::Error::from_eth_err) + ensure_success(res.result) } } @@ -341,7 +344,7 @@ pub trait EthCall: EstimateCall + Call + LoadPendingBlock + LoadBlock + FullEthA this.prepare_call_env(evm_env.clone(), tx, &mut db, overrides)?; let (res, _) = this.transact(&mut db, evm_env, tx)?; - match ensure_success(res.result) { + match ensure_success::<_, Self::Error>(res.result) { Ok(output) => { results.push(EthCallResponse { value: Some(output), error: None }); } @@ -397,8 +400,9 @@ pub trait EthCall: EstimateCall + Call + LoadPendingBlock + LoadBlock + FullEthA Self: Trace, { let state = self.state_at_block_id(at)?; + let mut db = CacheDB::new(StateProviderDatabase::new(state)); - let mut tx_env = self.create_txn_env(&evm_env.block_env, request.clone())?; + let mut tx_env = self.create_txn_env(&evm_env, request.clone(), &mut db)?; // we want to disable this in eth_createAccessList, since this is common practice used by // other node impls and providers @@ -409,12 +413,10 @@ pub trait EthCall: EstimateCall + Call + LoadPendingBlock + LoadBlock + FullEthA // evm_env.cfg_env.disable_base_fee = true; - let mut db = CacheDB::new(StateProviderDatabase::new(state)); - - if request.gas.is_none() && tx_env.gas_price() > U256::ZERO { + if request.gas.is_none() && tx_env.gas_price() > 0 { let cap = caller_gas_allowance(&mut db, &tx_env)?; // no gas limit was provided in the request, so we need to cap the request's gas limit - tx_env.set_gas_limit(cap.min(evm_env.block_env.gas_limit).saturating_to()); + tx_env.set_gas_limit(cap.min(evm_env.block_env.gas_limit)); } // can consume the list since we're not using the request anymore @@ -494,7 +496,7 @@ pub trait Call: tx_env: ::TxEnv, ) -> Result< ( - ResultAndState, + ResultAndState>, (EvmEnv<::Spec>, ::TxEnv), ), Self::Error, @@ -511,21 +513,22 @@ pub trait Call: /// Executes the [`EvmEnv`] against the given [Database] without committing state /// changes. #[expect(clippy::type_complexity)] - fn transact_with_inspector( + fn transact_with_inspector( &self, db: DB, evm_env: EvmEnv<::Spec>, tx_env: ::TxEnv, - inspector: impl GetInspector, + inspector: I, ) -> Result< ( - ResultAndState, + ResultAndState>, (EvmEnv<::Spec>, ::TxEnv), ), Self::Error, > where DB: Database, + I: InspectorFor, { let mut evm = self.evm_config().evm_with_env_and_inspector(db, evm_env.clone(), inspector); let res = evm.transact(tx_env.clone()).map_err(Self::Error::from_evm_err)?; @@ -543,7 +546,7 @@ pub trait Call: ) -> impl Future< Output = Result< ( - ResultAndState, + ResultAndState>, ( EvmEnv<::Spec>, ::TxEnv, @@ -643,7 +646,11 @@ pub trait Call: ) -> impl Future, Self::Error>> + Send where Self: LoadBlock + LoadTransaction, - F: FnOnce(TransactionInfo, ResultAndState, StateCacheDb<'_>) -> Result + F: FnOnce( + TransactionInfo, + ResultAndState>, + StateCacheDb<'_>, + ) -> Result + Send + 'static, R: Send + 'static, @@ -716,11 +723,12 @@ pub trait Call: /// Configures a new `TxEnv` for the [`TransactionRequest`] /// /// All `TxEnv` fields are derived from the given [`TransactionRequest`], if fields are - /// `None`, they fall back to the [`BlockEnv`]'s settings. + /// `None`, they fall back to the [`EvmEnv`]'s settings. fn create_txn_env( &self, - block_env: &BlockEnv, + evm_env: &EvmEnv>, request: TransactionRequest, + db: impl Database>, ) -> Result<::TxEnv, Self::Error>; /// Prepares the [`EvmEnv`] for execution of calls. @@ -759,7 +767,7 @@ pub trait Call: } // apply configured gas cap - evm_env.block_env.gas_limit = U256::from(self.call_gas_limit()); + evm_env.block_env.gas_limit = self.call_gas_limit(); // Disabled because eth_call is sometimes used with eoa senders // See @@ -781,16 +789,16 @@ pub trait Call: } let request_gas = request.gas; - let mut tx_env = self.create_txn_env(&evm_env.block_env, request)?; + let mut tx_env = self.create_txn_env(&evm_env, request, &mut *db)?; if request_gas.is_none() { // No gas limit was provided in the request, so we need to cap the transaction gas limit - if tx_env.gas_price() > U256::ZERO { + if tx_env.gas_price() > 0 { // If gas price is specified, cap transaction gas limit with caller allowance trace!(target: "rpc::eth::call", ?tx_env, "Applying gas limit cap with caller allowance"); let cap = caller_gas_allowance(db, &tx_env)?; // ensure we cap gas_limit to the block's - tx_env.set_gas_limit(cap.min(evm_env.block_env.gas_limit).saturating_to()); + tx_env.set_gas_limit(cap.min(evm_env.block_env.gas_limit)); } } diff --git a/crates/rpc/rpc-eth-api/src/helpers/estimate.rs b/crates/rpc/rpc-eth-api/src/helpers/estimate.rs index 6b868a457..55a369c66 100644 --- a/crates/rpc/rpc-eth-api/src/helpers/estimate.rs +++ b/crates/rpc/rpc-eth-api/src/helpers/estimate.rs @@ -7,15 +7,16 @@ use alloy_rpc_types_eth::{state::StateOverride, transaction::TransactionRequest, use futures::Future; use reth_chainspec::MIN_TRANSACTION_GAS; use reth_errors::ProviderError; -use reth_evm::{env::EvmEnv, ConfigureEvmEnv, Database, TransactionEnv}; +use reth_evm::{ConfigureEvmEnv, Database, EvmEnv, TransactionEnv}; use reth_provider::StateProvider; -use reth_revm::{database::StateProviderDatabase, db::CacheDB, primitives::ExecutionResult}; +use reth_revm::{database::StateProviderDatabase, db::CacheDB}; use reth_rpc_eth_types::{ error::api::FromEvmHalt, revm_utils::{apply_state_overrides, caller_gas_allowance}, EthApiError, RevertError, RpcInvalidTransactionError, }; use reth_rpc_server_types::constants::gas_oracle::{CALL_STIPEND_GAS, ESTIMATE_GAS_ERROR_RATIO}; +use revm::context_interface::{result::ExecutionResult, Transaction}; use revm_primitives::TxKind; use tracing::trace; @@ -55,7 +56,7 @@ pub trait EstimateCall: Call { request.nonce = None; // Keep a copy of gas related request values - let tx_request_gas_limit = request.gas.map(U256::from); + let tx_request_gas_limit = request.gas; let tx_request_gas_price = request.gas_price; // the gas limit of the corresponding block let block_env_gas_limit = evm_env.block_env.gas_limit; @@ -73,8 +74,8 @@ pub trait EstimateCall: Call { .unwrap_or(block_env_gas_limit); // Configure the evm env - let mut tx_env = self.create_txn_env(&evm_env.block_env, request)?; let mut db = CacheDB::new(StateProviderDatabase::new(state)); + let mut tx_env = self.create_txn_env(&evm_env, request, &mut db)?; // Apply any state overrides if specified. if let Some(state_override) = state_override { @@ -107,15 +108,12 @@ pub trait EstimateCall: Call { // Check funds of the sender (only useful to check if transaction gas price is more than 0). // // The caller allowance is check by doing `(account.balance - tx.value) / tx.gas_price` - if tx_env.gas_price() > U256::ZERO { + if tx_env.gas_price() > 0 { // cap the highest gas limit by max gas caller can afford with given gas price highest_gas_limit = highest_gas_limit .min(caller_gas_allowance(&mut db, &tx_env).map_err(Self::Error::from_eth_err)?); } - // We can now normalize the highest gas limit to a u64 - let mut highest_gas_limit = highest_gas_limit.saturating_to::(); - // If the provided gas limit is less than computed cap, use that tx_env.set_gas_limit(tx_env.gas_limit().min(highest_gas_limit)); @@ -288,7 +286,7 @@ pub trait EstimateCall: Call { #[inline] fn map_out_of_gas_err( &self, - env_gas_limit: U256, + env_gas_limit: u64, evm_env: EvmEnv<::Spec>, mut tx_env: ::TxEnv, db: &mut DB, @@ -298,7 +296,7 @@ pub trait EstimateCall: Call { EthApiError: From, { let req_gas_limit = tx_env.gas_limit(); - tx_env.set_gas_limit(env_gas_limit.try_into().unwrap_or(u64::MAX)); + tx_env.set_gas_limit(env_gas_limit); let (res, _) = match self.transact(db, evm_env, tx_env) { Ok(res) => res, Err(err) => return err, @@ -314,7 +312,7 @@ pub trait EstimateCall: Call { RpcInvalidTransactionError::Revert(RevertError::new(output)).into_eth_err() } ExecutionResult::Halt { reason, .. } => { - RpcInvalidTransactionError::EvmHalt(reason).into_eth_err() + Self::Error::from_evm_halt(reason, req_gas_limit) } } } @@ -326,8 +324,8 @@ pub trait EstimateCall: Call { /// gas limit for a transaction. It adjusts the highest or lowest gas limits depending on /// whether the execution succeeded, reverted, or halted due to specific reasons. #[inline] -pub fn update_estimated_gas_range( - result: ExecutionResult, +pub fn update_estimated_gas_range( + result: ExecutionResult, tx_gas_limit: u64, highest_gas_limit: &mut u64, lowest_gas_limit: &mut u64, diff --git a/crates/rpc/rpc-eth-api/src/helpers/pending_block.rs b/crates/rpc/rpc-eth-api/src/helpers/pending_block.rs index 66db02e2e..d465810fd 100644 --- a/crates/rpc/rpc-eth-api/src/helpers/pending_block.rs +++ b/crates/rpc/rpc-eth-api/src/helpers/pending_block.rs @@ -11,8 +11,8 @@ use futures::Future; use reth_chainspec::{EthChainSpec, EthereumHardforks}; use reth_errors::RethError; use reth_evm::{ - env::EvmEnv, state_change::post_block_withdrawals_balance_increments, - system_calls::SystemCaller, ConfigureEvm, ConfigureEvmEnv, Evm, EvmError, InvalidTxError, + state_change::post_block_withdrawals_balance_increments, system_calls::SystemCaller, + ConfigureEvm, ConfigureEvmEnv, Evm, EvmEnv, EvmError, HaltReasonFor, InvalidTxError, NextBlockEnvAttributes, }; use reth_primitives::{InvalidTransactionError, RecoveredBlock}; @@ -23,14 +23,21 @@ use reth_provider::{ }; use reth_revm::{ database::StateProviderDatabase, - primitives::{BlockEnv, ExecutionResult, ResultAndState}, + db::{states::bundle_state::BundleRetention, State}, }; use reth_rpc_eth_types::{EthApiError, PendingBlock, PendingBlockEnv, PendingBlockEnvOrigin}; use reth_transaction_pool::{ error::InvalidPoolTransactionError, BestTransactionsAttributes, PoolTransaction, TransactionPool, }; -use revm::{db::states::bundle_state::BundleRetention, DatabaseCommit, State}; +use revm::{ + context::BlockEnv, + context_interface::{ + result::{ExecutionResult, ResultAndState}, + Block, + }, + DatabaseCommit, +}; use std::time::{Duration, Instant}; use tokio::sync::Mutex; use tracing::debug; @@ -155,7 +162,7 @@ pub trait LoadPendingBlock: // check if the block is still good if let Some(pending_block) = lock.as_ref() { // this is guaranteed to be the `latest` header - if pending.evm_env.block_env.number.to::() == pending_block.block.number() && + if pending.evm_env.block_env.number == pending_block.block.number() && parent_hash == pending_block.block.parent_hash() && now <= pending_block.expires_at { @@ -193,7 +200,7 @@ pub trait LoadPendingBlock: fn assemble_receipt( &self, tx: &ProviderTx, - result: ExecutionResult, + result: ExecutionResult>, cumulative_gas_used: u64, ) -> ProviderReceipt; @@ -214,7 +221,7 @@ pub trait LoadPendingBlock: parent_hash: B256, state_root: B256, transactions: Vec>, - results: Vec, + results: Vec>>, ) -> (ProviderBlock, Vec>) { let mut cumulative_gas_used = 0; let mut receipts = Vec::with_capacity(results.len()); @@ -257,15 +264,15 @@ pub trait LoadPendingBlock: let mut cumulative_gas_used = 0; let mut sum_blob_gas_used = 0; - let block_gas_limit: u64 = evm_env.block_env.gas_limit.to::(); - let base_fee = evm_env.block_env.basefee.to::(); + let block_gas_limit: u64 = evm_env.block_env.gas_limit; + let base_fee = evm_env.block_env.basefee; let mut executed_txs = Vec::new(); let mut senders = Vec::new(); let mut best_txs = self.pool().best_transactions_with_attributes(BestTransactionsAttributes::new( base_fee, - evm_env.block_env.get_blob_gasprice().map(|gasprice| gasprice as u64), + evm_env.block_env.blob_gasprice().map(|gasprice| gasprice as u64), )); let chain_spec = self.provider().chain_spec(); @@ -384,7 +391,7 @@ pub trait LoadPendingBlock: // executes the withdrawals and commits them to the Database and BundleState. let balance_increments = post_block_withdrawals_balance_increments( chain_spec.as_ref(), - evm_env.block_env.timestamp.try_into().unwrap_or(u64::MAX), + evm_env.block_env.timestamp, &[], ); diff --git a/crates/rpc/rpc-eth-api/src/helpers/state.rs b/crates/rpc/rpc-eth-api/src/helpers/state.rs index 4bb0f67f0..d3c07c1a3 100644 --- a/crates/rpc/rpc-eth-api/src/helpers/state.rs +++ b/crates/rpc/rpc-eth-api/src/helpers/state.rs @@ -10,7 +10,7 @@ use alloy_serde::JsonStorageKey; use futures::Future; use reth_chainspec::{EthChainSpec, EthereumHardforks}; use reth_errors::RethError; -use reth_evm::{env::EvmEnv, ConfigureEvmEnv}; +use reth_evm::{ConfigureEvmEnv, EvmEnv}; use reth_provider::{ BlockIdReader, BlockNumReader, ChainSpecProvider, StateProvider, StateProviderBox, StateProviderFactory, diff --git a/crates/rpc/rpc-eth-api/src/helpers/trace.rs b/crates/rpc/rpc-eth-api/src/helpers/trace.rs index b01a6482f..d517651be 100644 --- a/crates/rpc/rpc-eth-api/src/helpers/trace.rs +++ b/crates/rpc/rpc-eth-api/src/helpers/trace.rs @@ -9,20 +9,24 @@ use futures::Future; use reth_chainspec::ChainSpecProvider; use reth_errors::ProviderError; use reth_evm::{ - env::EvmEnv, system_calls::SystemCaller, ConfigureEvm, ConfigureEvmEnv, Database, Evm, + system_calls::SystemCaller, ConfigureEvm, ConfigureEvmEnv, Database, Evm, EvmEnv, + HaltReasonFor, InspectorFor, }; use reth_primitives::RecoveredBlock; use reth_primitives_traits::{BlockBody, SignedTransaction}; use reth_provider::{BlockReader, ProviderBlock, ProviderHeader, ProviderTx}; -use reth_revm::database::StateProviderDatabase; +use reth_revm::{database::StateProviderDatabase, db::CacheDB}; use reth_rpc_eth_types::{ cache::db::{StateCacheDb, StateCacheDbRefMutWrapper, StateProviderTraitObjWrapper}, EthApiError, }; -use revm::{db::CacheDB, DatabaseCommit, GetInspector, Inspector}; +use revm::{ + context_interface::result::{ExecutionResult, ResultAndState}, + state::EvmState, + DatabaseCommit, +}; use revm_inspectors::tracing::{TracingInspector, TracingInspectorConfig}; -use revm_primitives::{EvmState, ExecutionResult, ResultAndState}; -use std::{fmt::Display, sync::Arc}; +use std::sync::Arc; /// Executes CPU heavy tasks. pub trait Trace: @@ -46,14 +50,14 @@ pub trait Trace: inspector: I, ) -> Result< ( - ResultAndState, + ResultAndState>, (EvmEnv<::Spec>, ::TxEnv), ), Self::Error, > where DB: Database, - I: GetInspector, + I: InspectorFor, { let mut evm = self.evm_config().evm_with_env_and_inspector(db, evm_env.clone(), inspector); let res = evm.transact(tx_env.clone()).map_err(Self::Error::from_evm_err)?; @@ -77,7 +81,10 @@ pub trait Trace: ) -> Result where Self: Call, - F: FnOnce(TracingInspector, ResultAndState) -> Result, + F: FnOnce( + TracingInspector, + ResultAndState>, + ) -> Result, { self.with_state_at_block(at, |state| { let mut db = CacheDB::new(StateProviderDatabase::new(state)); @@ -104,7 +111,11 @@ pub trait Trace: ) -> impl Future> + Send where Self: LoadPendingBlock + Call, - F: FnOnce(TracingInspector, ResultAndState, StateCacheDb<'_>) -> Result + F: FnOnce( + TracingInspector, + ResultAndState>, + StateCacheDb<'_>, + ) -> Result + Send + 'static, R: Send + 'static, @@ -138,7 +149,7 @@ pub trait Trace: F: FnOnce( TransactionInfo, TracingInspector, - ResultAndState, + ResultAndState>, StateCacheDb<'_>, ) -> Result + Send @@ -168,12 +179,13 @@ pub trait Trace: F: FnOnce( TransactionInfo, Insp, - ResultAndState, + ResultAndState>, StateCacheDb<'_>, ) -> Result + Send + 'static, - Insp: for<'a, 'b> Inspector> + Send + 'static, + Insp: + for<'a, 'b> InspectorFor, Self::Evm> + Send + 'static, R: Send + 'static, { async move { @@ -232,7 +244,7 @@ pub trait Trace: F: Fn( TransactionInfo, TracingInspector, - ExecutionResult, + ExecutionResult>, &EvmState, &StateCacheDb<'_>, ) -> Result @@ -272,14 +284,15 @@ pub trait Trace: F: Fn( TransactionInfo, Insp, - ExecutionResult, + ExecutionResult>, &EvmState, &StateCacheDb<'_>, ) -> Result + Send + 'static, Setup: FnMut() -> Insp + Send + 'static, - Insp: for<'a, 'b> Inspector> + Send + 'static, + Insp: + for<'a, 'b> InspectorFor, Self::Evm> + Send + 'static, R: Send + 'static, { async move { @@ -306,8 +319,8 @@ pub trait Trace: let state_at = block.parent_hash(); let block_hash = block.hash(); - let block_number = evm_env.block_env.number.saturating_to::(); - let base_fee = evm_env.block_env.basefee.saturating_to::(); + let block_number = evm_env.block_env.number; + let base_fee = evm_env.block_env.basefee; // now get the state let state = this.state_at_block_id(state_at.into())?; @@ -391,7 +404,7 @@ pub trait Trace: F: Fn( TransactionInfo, TracingInspector, - ExecutionResult, + ExecutionResult>, &EvmState, &StateCacheDb<'_>, ) -> Result @@ -430,14 +443,15 @@ pub trait Trace: F: Fn( TransactionInfo, Insp, - ExecutionResult, + ExecutionResult>, &EvmState, &StateCacheDb<'_>, ) -> Result + Send + 'static, Setup: FnMut() -> Insp + Send + 'static, - Insp: for<'a, 'b> Inspector> + Send + 'static, + Insp: + for<'a, 'b> InspectorFor, Self::Evm> + Send + 'static, R: Send + 'static, { self.trace_block_until_with_inspector(block_id, block, None, insp_setup, f) @@ -448,7 +462,7 @@ pub trait Trace: /// Note: This should only be called when tracing an entire block vs individual transactions. /// When tracing transaction on top of an already committed block state, those transitions are /// already applied. - fn apply_pre_execution_changes + DatabaseCommit>( + fn apply_pre_execution_changes( &self, block: &RecoveredBlock>, db: &mut DB, diff --git a/crates/rpc/rpc-eth-api/src/helpers/transaction.rs b/crates/rpc/rpc-eth-api/src/helpers/transaction.rs index 1c2113729..012eb1ecb 100644 --- a/crates/rpc/rpc-eth-api/src/helpers/transaction.rs +++ b/crates/rpc/rpc-eth-api/src/helpers/transaction.rs @@ -38,8 +38,7 @@ use std::sync::Arc; /// There are subtle differences between when transacting [`TransactionRequest`]: /// /// The endpoints `eth_call` and `eth_estimateGas` and `eth_createAccessList` should always -/// __disable__ the base fee check in the -/// [`EnvWithHandlerCfg`](revm_primitives::CfgEnvWithHandlerCfg). +/// __disable__ the base fee check in the [`CfgEnv`](revm::context::CfgEnv). /// /// The behaviour for tracing endpoints is not consistent across clients. /// Geth also disables the basefee check for tracing: diff --git a/crates/rpc/rpc-eth-types/Cargo.toml b/crates/rpc/rpc-eth-types/Cargo.toml index f306eefbd..0aa10ec87 100644 --- a/crates/rpc/rpc-eth-types/Cargo.toml +++ b/crates/rpc/rpc-eth-types/Cargo.toml @@ -35,8 +35,9 @@ alloy-consensus.workspace = true alloy-sol-types.workspace = true alloy-rpc-types-eth.workspace = true revm.workspace = true +revm-database.workspace = true revm-inspectors.workspace = true -revm-primitives = { workspace = true, features = ["dev"] } +revm-primitives.workspace = true # rpc jsonrpsee-core.workspace = true diff --git a/crates/rpc/rpc-eth-types/src/cache/db.rs b/crates/rpc/rpc-eth-types/src/cache/db.rs index e61e69eac..ad20d4f89 100644 --- a/crates/rpc/rpc-eth-types/src/cache/db.rs +++ b/crates/rpc/rpc-eth-types/src/cache/db.rs @@ -4,10 +4,14 @@ use alloy_primitives::{Address, B256, U256}; use reth_errors::ProviderResult; -use reth_revm::{database::StateProviderDatabase, db::CacheDB, DatabaseRef}; +use reth_revm::{database::StateProviderDatabase, DatabaseRef}; use reth_storage_api::{HashedPostStateProvider, StateProvider}; use reth_trie::{HashedStorage, MultiProofTargets}; -use revm::Database; +use revm::{ + state::{AccountInfo, Bytecode}, + Database, +}; +use revm_database::CacheDB; /// Helper alias type for the state's [`CacheDB`] pub type StateCacheDb<'a> = CacheDB>>; @@ -138,7 +142,7 @@ impl reth_storage_api::BlockHashReader for StateProviderTraitObjWrapper<'_> { impl HashedPostStateProvider for StateProviderTraitObjWrapper<'_> { fn hashed_post_state( &self, - bundle_state: &revm::db::BundleState, + bundle_state: &revm_database::BundleState, ) -> reth_trie::HashedPostState { self.0.hashed_post_state(bundle_state) } @@ -192,11 +196,11 @@ impl<'a> Database for StateCacheDbRefMutWrapper<'a, '_> { fn basic( &mut self, address: revm_primitives::Address, - ) -> Result, Self::Error> { + ) -> Result, Self::Error> { self.0.basic(address) } - fn code_by_hash(&mut self, code_hash: B256) -> Result { + fn code_by_hash(&mut self, code_hash: B256) -> Result { self.0.code_by_hash(code_hash) } @@ -219,11 +223,11 @@ impl<'a> DatabaseRef for StateCacheDbRefMutWrapper<'a, '_> { fn basic_ref( &self, address: revm_primitives::Address, - ) -> Result, Self::Error> { + ) -> Result, Self::Error> { self.0.basic_ref(address) } - fn code_by_hash_ref(&self, code_hash: B256) -> Result { + fn code_by_hash_ref(&self, code_hash: B256) -> Result { self.0.code_by_hash_ref(code_hash) } diff --git a/crates/rpc/rpc-eth-types/src/error/api.rs b/crates/rpc/rpc-eth-types/src/error/api.rs index 81f38ed29..03641d067 100644 --- a/crates/rpc/rpc-eth-types/src/error/api.rs +++ b/crates/rpc/rpc-eth-types/src/error/api.rs @@ -1,10 +1,12 @@ //! Helper traits to wrap generic l1 errors, in network specific error type configured in //! `reth_rpc_eth_api::EthApiTypes`. -use crate::{EthApiError, RpcInvalidTransactionError}; +use crate::EthApiError; use reth_errors::ProviderError; -use reth_evm::ConfigureEvm; -use revm_primitives::HaltReason; +use reth_evm::{ConfigureEvm, EvmErrorFor, HaltReasonFor}; +use revm::context_interface::result::HaltReason; + +use super::RpcInvalidTransactionError; /// Helper trait to wrap core [`EthApiError`]. pub trait FromEthApiError: From { @@ -81,28 +83,28 @@ impl AsEthApiError for EthApiError { /// Helper trait to convert from revm errors. pub trait FromEvmError: - From> + FromEvmHalt + From> + FromEvmHalt> { /// Converts from EVM error to this type. - fn from_evm_err(err: Evm::EvmError) -> Self { + fn from_evm_err(err: EvmErrorFor) -> Self { err.into() } } impl FromEvmError for T where - T: From> + FromEvmHalt, + T: From> + FromEvmHalt>, Evm: ConfigureEvm, { } /// Helper trait to convert from revm errors. -pub trait FromEvmHalt { +pub trait FromEvmHalt { /// Converts from EVM halt to this type. fn from_evm_halt(halt: Halt, gas_limit: u64) -> Self; } -impl FromEvmHalt for EthApiError { +impl FromEvmHalt for EthApiError { fn from_evm_halt(halt: HaltReason, gas_limit: u64) -> Self { RpcInvalidTransactionError::halt(halt, gas_limit).into() } diff --git a/crates/rpc/rpc-eth-types/src/error/mod.rs b/crates/rpc/rpc-eth-types/src/error/mod.rs index 1d93a7ffe..1327625fd 100644 --- a/crates/rpc/rpc-eth-types/src/error/mod.rs +++ b/crates/rpc/rpc-eth-types/src/error/mod.rs @@ -1,14 +1,13 @@ //! Implementation specific Errors for the `eth_` namespace. pub mod api; -pub use api::{AsEthApiError, FromEthApiError, FromEvmError, IntoEthApiError}; - -use core::time::Duration; - +use crate::error::api::FromEvmHalt; use alloy_eips::BlockId; use alloy_primitives::{Address, Bytes, U256}; use alloy_rpc_types_eth::{error::EthRpcErrorCode, request::TransactionInputError, BlockError}; use alloy_sol_types::{ContractError, RevertReason}; +pub use api::{AsEthApiError, FromEthApiError, FromEvmError, IntoEthApiError}; +use core::time::Duration; use reth_errors::RethError; use reth_primitives_traits::transaction::signed::RecoveryError; use reth_rpc_server_types::result::{ @@ -18,9 +17,10 @@ use reth_transaction_pool::error::{ Eip4844PoolTransactionError, Eip7702PoolTransactionError, InvalidPoolTransactionError, PoolError, PoolErrorKind, PoolTransactionError, }; -use revm::primitives::{EVMError, ExecutionResult, HaltReason, InvalidTransaction, OutOfGasError}; +use revm::context_interface::result::{ + EVMError, ExecutionResult, HaltReason, InvalidHeader, InvalidTransaction, OutOfGasError, +}; use revm_inspectors::tracing::MuxError; -use revm_primitives::InvalidHeader; use tracing::error; /// A trait to convert an error to an RPC error. @@ -273,11 +273,20 @@ impl From for EthApiError { } } -impl From> for EthApiError +impl From for EthApiError { + fn from(value: InvalidHeader) -> Self { + match value { + InvalidHeader::ExcessBlobGasNotSet => Self::ExcessBlobGasNotSet, + InvalidHeader::PrevrandaoNotSet => Self::PrevrandaoNotSet, + } + } +} + +impl From> for EthApiError where T: Into, { - fn from(err: EVMError) -> Self { + fn from(err: EVMError) -> Self { match err { EVMError::Transaction(invalid_tx) => match invalid_tx { InvalidTransaction::NonceTooLow { tx, state } => { @@ -285,8 +294,7 @@ where } _ => RpcInvalidTransactionError::from(invalid_tx).into(), }, - EVMError::Header(InvalidHeader::PrevrandaoNotSet) => Self::PrevrandaoNotSet, - EVMError::Header(InvalidHeader::ExcessBlobGasNotSet) => Self::ExcessBlobGasNotSet, + EVMError::Header(err) => err.into(), EVMError::Database(err) => err.into(), EVMError::Custom(err) => Self::EvmCustom(err), EVMError::Precompile(err) => Self::EvmPrecompile(err), @@ -489,7 +497,9 @@ impl RpcInvalidTransactionError { /// Converts the out of gas error pub const fn out_of_gas(reason: OutOfGasError, gas_limit: u64) -> Self { match reason { - OutOfGasError::Basic => Self::BasicOutOfGas(gas_limit), + OutOfGasError::Basic | OutOfGasError::ReentrancySentry => { + Self::BasicOutOfGas(gas_limit) + } OutOfGasError::Memory | OutOfGasError::MemoryLimit => Self::MemoryOutOfGas(gas_limit), OutOfGasError::Precompile => Self::PrecompileOutOfGas(gas_limit), OutOfGasError::InvalidOperand => Self::InvalidOperandOutOfGas(gas_limit), @@ -514,9 +524,8 @@ impl From for jsonrpsee_types::error::ErrorObject<'s } } -impl From for RpcInvalidTransactionError { - fn from(err: revm::primitives::InvalidTransaction) -> Self { - use revm::primitives::InvalidTransaction; +impl From for RpcInvalidTransactionError { + fn from(err: InvalidTransaction) -> Self { match err { InvalidTransaction::InvalidChainId => Self::InvalidChainId, InvalidTransaction::PriorityFeeGreaterThanMaxFee => Self::TipAboveFeeCap, @@ -546,7 +555,7 @@ impl From for RpcInvalidTransactionError { InvalidTransaction::BlobGasPriceGreaterThanMax => Self::BlobFeeCapTooLow, InvalidTransaction::EmptyBlobs => Self::BlobTransactionMissingBlobHashes, InvalidTransaction::BlobVersionNotSupported => Self::BlobHashVersionMismatch, - InvalidTransaction::TooManyBlobs { have } => Self::TooManyBlobs { have }, + InvalidTransaction::TooManyBlobs { have, .. } => Self::TooManyBlobs { have }, InvalidTransaction::BlobCreateTransaction => Self::BlobTransactionIsCreate, InvalidTransaction::EofCrateShouldHaveToAddress => Self::EofCrateShouldHaveToAddress, InvalidTransaction::AuthorizationListNotSupported => { @@ -779,15 +788,15 @@ pub enum SignError { /// Converts the evm [`ExecutionResult`] into a result where `Ok` variant is the output bytes if it /// is [`ExecutionResult::Success`]. -pub fn ensure_success(result: ExecutionResult) -> EthResult { +pub fn ensure_success + FromEthApiError>( + result: ExecutionResult, +) -> Result { match result { ExecutionResult::Success { output, .. } => Ok(output.into_data()), ExecutionResult::Revert { output, .. } => { - Err(RpcInvalidTransactionError::Revert(RevertError::new(output)).into()) - } - ExecutionResult::Halt { reason, gas_used } => { - Err(RpcInvalidTransactionError::halt(reason, gas_used).into()) + Err(Error::from_eth_err(RpcInvalidTransactionError::Revert(RevertError::new(output)))) } + ExecutionResult::Halt { reason, gas_used } => Err(Error::from_evm_halt(reason, gas_used)), } } diff --git a/crates/rpc/rpc-eth-types/src/revm_utils.rs b/crates/rpc/rpc-eth-types/src/revm_utils.rs index 70685c931..c857aac83 100644 --- a/crates/rpc/rpc-eth-types/src/revm_utils.rs +++ b/crates/rpc/rpc-eth-types/src/revm_utils.rs @@ -6,24 +6,12 @@ use alloy_rpc_types_eth::{ BlockOverrides, }; use reth_evm::TransactionEnv; -use revm::{ - db::CacheDB, - precompile::{PrecompileSpecId, Precompiles}, - primitives::{db::DatabaseRef, Bytecode, SpecId}, - Database, -}; -use revm_primitives::BlockEnv; +use revm::{context::BlockEnv, state::Bytecode, Database, DatabaseRef}; +use revm_database::CacheDB; use std::cmp::min; use super::{EthApiError, EthResult, RpcInvalidTransactionError}; -/// Returns the addresses of the precompiles corresponding to the `SpecId`. -#[inline] -pub fn get_precompiles(spec_id: SpecId) -> impl IntoIterator { - let spec = PrecompileSpecId::from_spec_id(spec_id); - Precompiles::new(spec).addresses().copied() -} - /// Calculates the caller gas allowance. /// /// `allowance = (account.balance - tx.value) / tx.gas_price` @@ -33,7 +21,7 @@ pub fn get_precompiles(spec_id: SpecId) -> impl IntoIterator { /// /// Note: this takes the mut [Database] trait because the loaded sender can be reused for the /// following operation like `eth_call`. -pub fn caller_gas_allowance(db: &mut DB, env: &impl TransactionEnv) -> EthResult +pub fn caller_gas_allowance(db: &mut DB, env: &impl TransactionEnv) -> EthResult where DB: Database, EthApiError: From<::Error>, @@ -52,9 +40,10 @@ where Ok(balance // Calculate the amount of gas the caller can afford with the specified gas price. - .checked_div(env.gas_price()) + .checked_div(U256::from(env.gas_price())) // This will be 0 if gas price is 0. It is fine, because we check it before. - .unwrap_or_default()) + .unwrap_or_default() + .saturating_to()) } /// Helper type for representing the fees of a `TransactionRequest` @@ -220,25 +209,25 @@ pub fn apply_block_overrides( } if let Some(number) = number { - env.number = number; + env.number = number.saturating_to(); } if let Some(difficulty) = difficulty { env.difficulty = difficulty; } if let Some(time) = time { - env.timestamp = U256::from(time); + env.timestamp = time; } if let Some(gas_limit) = gas_limit { - env.gas_limit = U256::from(gas_limit); + env.gas_limit = gas_limit; } if let Some(coinbase) = coinbase { - env.coinbase = coinbase; + env.beneficiary = coinbase; } if let Some(random) = random { env.prevrandao = Some(random); } if let Some(base_fee) = base_fee { - env.basefee = base_fee; + env.basefee = base_fee.saturating_to(); } } diff --git a/crates/rpc/rpc-eth-types/src/simulate.rs b/crates/rpc/rpc-eth-types/src/simulate.rs index dec476e26..ad21f0b3e 100644 --- a/crates/rpc/rpc-eth-types/src/simulate.rs +++ b/crates/rpc/rpc-eth-types/src/simulate.rs @@ -11,8 +11,8 @@ use reth_primitives::RecoveredBlock; use reth_primitives_traits::{block::BlockTx, BlockBody as _, SignedTransaction}; use reth_rpc_server_types::result::rpc_err; use reth_rpc_types_compat::{block::from_block, TransactionCompat}; -use revm::Database; -use revm_primitives::{Address, Bytes, ExecutionResult, TxKind}; +use revm::{context_interface::result::ExecutionResult, Database}; +use revm_primitives::{Address, Bytes, TxKind}; use crate::{ error::{ @@ -113,15 +113,15 @@ where /// Handles outputs of the calls execution and builds a [`SimulatedBlock`]. #[expect(clippy::type_complexity)] -pub fn build_simulated_block( +pub fn build_simulated_block( senders: Vec
, - results: Vec, + results: Vec>, full_transactions: bool, tx_resp_builder: &T, block: B, ) -> Result>>, T::Error> where - T: TransactionCompat, Error: FromEthApiError + FromEvmHalt>, + T: TransactionCompat, Error: FromEthApiError + FromEvmHalt>, B: reth_primitives_traits::Block, { let mut calls: Vec = Vec::with_capacity(results.len()); @@ -130,7 +130,7 @@ where for (index, (result, tx)) in results.iter().zip(block.body().transactions()).enumerate() { let call = match result { ExecutionResult::Halt { reason, gas_used } => { - let error = T::Error::from_evm_halt(*reason, tx.gas_limit()); + let error = T::Error::from_evm_halt(reason.clone(), tx.gas_limit()); SimCallResult { return_data: Bytes::new(), error: Some(SimulateError { diff --git a/crates/rpc/rpc/src/debug.rs b/crates/rpc/rpc/src/debug.rs index b92166efd..d15d16033 100644 --- a/crates/rpc/rpc/src/debug.rs +++ b/crates/rpc/rpc/src/debug.rs @@ -1,7 +1,7 @@ use alloy_consensus::BlockHeader; use alloy_eips::{eip2718::Encodable2718, BlockId, BlockNumberOrTag}; use alloy_genesis::ChainConfig; -use alloy_primitives::{Address, Bytes, B256, U256}; +use alloy_primitives::{Address, Bytes, B256}; use alloy_rlp::{Decodable, Encodable}; use alloy_rpc_types_debug::ExecutionWitness; use alloy_rpc_types_eth::{ @@ -17,9 +17,8 @@ use async_trait::async_trait; use jsonrpsee::core::RpcResult; use reth_chainspec::{EthChainSpec, EthereumHardforks}; use reth_evm::{ - env::EvmEnv, execute::{BlockExecutorProvider, Executor}, - ConfigureEvmEnv, TransactionEnv, + ConfigureEvmEnv, EvmEnv, }; use reth_primitives::{NodePrimitives, ReceiptWithBloom, RecoveredBlock}; use reth_primitives_traits::{Block as _, BlockBody, SignedTransaction}; @@ -28,7 +27,11 @@ use reth_provider::{ ReceiptProviderIdExt, StateProofProvider, StateProvider, StateProviderFactory, TransactionVariant, }; -use reth_revm::{database::StateProviderDatabase, witness::ExecutionWitnessRecord}; +use reth_revm::{ + database::StateProviderDatabase, + db::{CacheDB, State}, + witness::ExecutionWitnessRecord, +}; use reth_rpc_api::DebugApiServer; use reth_rpc_eth_api::{ helpers::{EthTransactions, TraceExt}, @@ -37,10 +40,7 @@ use reth_rpc_eth_api::{ use reth_rpc_eth_types::{EthApiError, StateCacheDb}; use reth_rpc_server_types::{result::internal_rpc_err, ToRpcResult}; use reth_tasks::pool::BlockingTaskGuard; -use revm::{ - db::{CacheDB, State}, - primitives::db::DatabaseCommit, -}; +use revm::{context_interface::Transaction, state::EvmState, DatabaseCommit}; use revm_inspectors::tracing::{ FourByteInspector, MuxInspector, TracingInspector, TracingInspectorConfig, TransactionContext, }; @@ -369,12 +369,8 @@ where let db = db.0; let tx_info = TransactionInfo { - block_number: Some( - evm_env.block_env.number.try_into().unwrap_or_default(), - ), - base_fee: Some( - evm_env.block_env.basefee.try_into().unwrap_or_default(), - ), + block_number: Some(evm_env.block_env.number), + base_fee: Some(evm_env.block_env.basefee), hash: None, block_hash: None, index: None, @@ -447,12 +443,9 @@ where tx_env.clone(), &mut inspector, )?; - let env = revm_primitives::Env::boxed( - evm_env.cfg_env, - evm_env.block_env, - tx_env.into(), - ); - inspector.json_result(res, &env, db).map_err(Eth::Error::from_eth_err) + inspector + .json_result(res, &tx_env, &evm_env.block_env, db) + .map_err(Eth::Error::from_eth_err) }) .await?; @@ -588,8 +581,8 @@ where results.push(trace); } // Increment block_env number and timestamp for the next bundle - evm_env.block_env.number += U256::from(1); - evm_env.block_env.timestamp += U256::from(12); + evm_env.block_env.number += 1; + evm_env.block_env.timestamp += 12; all_bundles.push(results); } @@ -700,7 +693,7 @@ where db: &mut StateCacheDb<'_>, transaction_context: Option, fused_inspector: &mut Option, - ) -> Result<(GethTrace, revm_primitives::EvmState), Eth::Error> { + ) -> Result<(GethTrace, EvmState), Eth::Error> { let GethDebugTracingOptions { config, tracer, tracer_config, .. } = opts; let tx_info = TransactionInfo { @@ -710,8 +703,8 @@ where .map(|c| c.tx_index.map(|i| i as u64)) .unwrap_or_default(), block_hash: transaction_context.as_ref().map(|c| c.block_hash).unwrap_or_default(), - block_number: Some(evm_env.block_env.number.try_into().unwrap_or_default()), - base_fee: Some(evm_env.block_env.basefee.try_into().unwrap_or_default()), + block_number: Some(evm_env.block_env.number), + base_fee: Some(evm_env.block_env.basefee), }; if let Some(tracer) = tracer { @@ -825,13 +818,9 @@ where self.eth_api().inspect(&mut *db, evm_env, tx_env, &mut inspector)?; let state = res.state.clone(); - let env = revm_primitives::Env::boxed( - evm_env.cfg_env, - evm_env.block_env, - tx_env.into(), - ); - let result = - inspector.json_result(res, &env, db).map_err(Eth::Error::from_eth_err)?; + let result = inspector + .json_result(res, &tx_env, &evm_env.block_env, db) + .map_err(Eth::Error::from_eth_err)?; Ok((GethTrace::JS(result), state)) } } diff --git a/crates/rpc/rpc/src/eth/bundle.rs b/crates/rpc/rpc/src/eth/bundle.rs index 45df07d2c..df8de0582 100644 --- a/crates/rpc/rpc/src/eth/bundle.rs +++ b/crates/rpc/rpc/src/eth/bundle.rs @@ -7,7 +7,7 @@ use alloy_rpc_types_mev::{EthCallBundle, EthCallBundleResponse, EthCallBundleTra use jsonrpsee::core::RpcResult; use reth_evm::{ConfigureEvm, ConfigureEvmEnv, Evm}; use reth_primitives_traits::SignedTransaction; -use reth_revm::database::StateProviderDatabase; +use reth_revm::{database::StateProviderDatabase, db::CacheDB}; use reth_rpc_eth_api::{ helpers::{Call, EthTransactions, LoadPendingBlock}, EthCallBundleApiServer, FromEthApiError, FromEvmError, @@ -17,10 +17,7 @@ use reth_tasks::pool::BlockingTaskGuard; use reth_transaction_pool::{ EthBlobTransactionSidecar, EthPoolTransaction, PoolPooledTx, PoolTransaction, TransactionPool, }; -use revm::{ - db::{CacheDB, DatabaseCommit, DatabaseRef}, - primitives::ResultAndState, -}; +use revm::{context_interface::result::ResultAndState, DatabaseCommit, DatabaseRef}; use std::sync::Arc; /// `Eth` bundle implementation. @@ -101,14 +98,14 @@ where let (mut evm_env, at) = self.eth_api().evm_env_at(block_id).await?; if let Some(coinbase) = coinbase { - evm_env.block_env.coinbase = coinbase; + evm_env.block_env.beneficiary = coinbase; } // need to adjust the timestamp for the next block if let Some(timestamp) = timestamp { - evm_env.block_env.timestamp = U256::from(timestamp); + evm_env.block_env.timestamp = timestamp; } else { - evm_env.block_env.timestamp += U256::from(12); + evm_env.block_env.timestamp += 12; } if let Some(difficulty) = difficulty { @@ -116,9 +113,8 @@ where } // default to call gas limit unless user requests a smaller limit - evm_env.block_env.gas_limit = U256::from(self.inner.eth_api.call_gas_limit()); + evm_env.block_env.gas_limit = self.inner.eth_api.call_gas_limit(); if let Some(gas_limit) = gas_limit { - let gas_limit = U256::from(gas_limit); if gas_limit > evm_env.block_env.gas_limit { return Err( EthApiError::InvalidTransaction(RpcInvalidTransactionError::GasTooHigh).into() @@ -128,19 +124,19 @@ where } if let Some(base_fee) = base_fee { - evm_env.block_env.basefee = U256::from(base_fee); + evm_env.block_env.basefee = base_fee.try_into().unwrap_or(u64::MAX); } let state_block_number = evm_env.block_env.number; // use the block number of the request - evm_env.block_env.number = U256::from(block_number); + evm_env.block_env.number = block_number; let eth_api = self.eth_api().clone(); self.eth_api() .spawn_with_state_at_block(at, move |state| { - let coinbase = evm_env.block_env.coinbase; - let basefee = Some(evm_env.block_env.basefee.to::()); + let coinbase = evm_env.block_env.beneficiary; + let basefee = Some(evm_env.block_env.basefee); let db = CacheDB::new(StateProviderDatabase::new(state)); let initial_coinbase = db @@ -244,7 +240,7 @@ where eth_sent_to_coinbase, gas_fees: total_gas_fess, results, - state_block_number: state_block_number.to(), + state_block_number, total_gas_used, }; diff --git a/crates/rpc/rpc/src/eth/helpers/call.rs b/crates/rpc/rpc/src/eth/helpers/call.rs index 2e08e7775..fee3268f1 100644 --- a/crates/rpc/rpc/src/eth/helpers/call.rs +++ b/crates/rpc/rpc/src/eth/helpers/call.rs @@ -2,15 +2,16 @@ use crate::EthApi; use alloy_consensus::Header; +use alloy_primitives::{TxKind, U256}; use alloy_rpc_types::TransactionRequest; -use reth_evm::ConfigureEvm; +use reth_evm::{ConfigureEvm, EvmEnv, SpecFor}; use reth_provider::{BlockReader, ProviderHeader}; use reth_rpc_eth_api::{ helpers::{estimate::EstimateCall, Call, EthCall, LoadPendingBlock, LoadState, SpawnBlocking}, FromEthApiError, FromEvmError, FullEthApiTypes, IntoEthApiError, }; -use reth_rpc_eth_types::{revm_utils::CallFees, RpcInvalidTransactionError}; -use revm_primitives::{BlockEnv, TxEnv, TxKind, U256}; +use reth_rpc_eth_types::{revm_utils::CallFees, EthApiError, RpcInvalidTransactionError}; +use revm::{context::TxEnv, context_interface::Block, Database}; impl EthCall for EthApi where @@ -40,14 +41,17 @@ where fn create_txn_env( &self, - block_env: &BlockEnv, + evm_env: &EvmEnv>, request: TransactionRequest, + mut db: impl Database>, ) -> Result { // Ensure that if versioned hashes are set, they're not empty if request.blob_versioned_hashes.as_ref().is_some_and(|hashes| hashes.is_empty()) { return Err(RpcInvalidTransactionError::BlobTransactionMissingBlobHashes.into_eth_err()) } + let tx_type = request.preferred_type() as u8; + let TransactionRequest { from, to, @@ -72,42 +76,54 @@ where gas_price.map(U256::from), max_fee_per_gas.map(U256::from), max_priority_fee_per_gas.map(U256::from), - block_env.basefee, + U256::from(evm_env.block_env.basefee), blob_versioned_hashes.as_deref(), max_fee_per_blob_gas.map(U256::from), - block_env.get_blob_gasprice().map(U256::from), + evm_env.block_env.blob_gasprice().map(U256::from), )?; - let gas_limit = gas.unwrap_or_else(|| { + let gas_limit = gas.unwrap_or( // Use maximum allowed gas limit. The reason for this // is that both Erigon and Geth use pre-configured gas cap even if // it's possible to derive the gas limit from the block: // - block_env.gas_limit.saturating_to() - }); + evm_env.block_env.gas_limit, + ); + + let chain_id = chain_id.unwrap_or(evm_env.cfg_env.chain_id); + + let caller = from.unwrap_or_default(); + + let nonce = if let Some(nonce) = nonce { + nonce + } else { + db.basic(caller).map_err(Into::into)?.map(|acc| acc.nonce).unwrap_or_default() + }; #[allow(clippy::needless_update)] let env = TxEnv { + tx_type, gas_limit, nonce, - caller: from.unwrap_or_default(), - gas_price, - gas_priority_fee: max_priority_fee_per_gas, - transact_to: to.unwrap_or(TxKind::Create), + caller, + gas_price: gas_price.saturating_to(), + gas_priority_fee: max_priority_fee_per_gas.map(|v| v.saturating_to()), + kind: to.unwrap_or(TxKind::Create), value: value.unwrap_or_default(), data: input .try_into_unique_input() .map_err(Self::Error::from_eth_err)? .unwrap_or_default(), - chain_id, - access_list: access_list.unwrap_or_default().into(), + chain_id: Some(chain_id), + access_list: access_list.unwrap_or_default(), // EIP-4844 fields blob_hashes: blob_versioned_hashes.unwrap_or_default(), - max_fee_per_blob_gas, + max_fee_per_blob_gas: max_fee_per_blob_gas + .map(|v| v.saturating_to()) + .unwrap_or_default(), // EIP-7702 fields - authorization_list: authorization_list.map(Into::into), - ..Default::default() + authorization_list: authorization_list.unwrap_or_default(), }; Ok(env) diff --git a/crates/rpc/rpc/src/eth/helpers/pending_block.rs b/crates/rpc/rpc/src/eth/helpers/pending_block.rs index 36ec6352c..872d721bb 100644 --- a/crates/rpc/rpc/src/eth/helpers/pending_block.rs +++ b/crates/rpc/rpc/src/eth/helpers/pending_block.rs @@ -4,7 +4,7 @@ use alloy_consensus::{constants::EMPTY_WITHDRAWALS, Header, Transaction, EMPTY_O use alloy_eips::{eip7685::EMPTY_REQUESTS_HASH, merge::BEACON_NONCE}; use alloy_primitives::U256; use reth_chainspec::{EthChainSpec, EthereumHardforks}; -use reth_evm::ConfigureEvm; +use reth_evm::{ConfigureEvm, HaltReasonFor}; use reth_primitives::{logs_bloom, BlockBody, Receipt}; use reth_primitives_traits::proofs::calculate_transaction_root; use reth_provider::{ @@ -18,7 +18,11 @@ use reth_rpc_eth_api::{ }; use reth_rpc_eth_types::PendingBlock; use reth_transaction_pool::{PoolTransaction, TransactionPool}; -use revm_primitives::{BlockEnv, B256}; +use revm::{ + context::BlockEnv, + context_interface::{result::ExecutionResult, Block}, +}; +use revm_primitives::B256; use crate::EthApi; @@ -67,7 +71,7 @@ where let logs_bloom = logs_bloom(receipts.iter().flat_map(|r| &r.logs)); - let timestamp = block_env.timestamp.to::(); + let timestamp = block_env.timestamp; let is_shanghai = chain_spec.is_shanghai_active_at_timestamp(timestamp); let is_cancun = chain_spec.is_cancun_active_at_timestamp(timestamp); let is_prague = chain_spec.is_prague_active_at_timestamp(timestamp); @@ -75,24 +79,24 @@ where let header = Header { parent_hash, ommers_hash: EMPTY_OMMER_ROOT_HASH, - beneficiary: block_env.coinbase, + beneficiary: block_env.beneficiary, state_root, transactions_root, receipts_root, withdrawals_root: is_shanghai.then_some(EMPTY_WITHDRAWALS), logs_bloom, - timestamp: block_env.timestamp.to::(), + timestamp: block_env.timestamp, mix_hash: block_env.prevrandao.unwrap_or_default(), nonce: BEACON_NONCE.into(), - base_fee_per_gas: Some(block_env.basefee.to::()), - number: block_env.number.to::(), - gas_limit: block_env.gas_limit.to::(), + base_fee_per_gas: Some(block_env.basefee), + number: block_env.number, + gas_limit: block_env.gas_limit, difficulty: U256::ZERO, gas_used: receipts.last().map(|r| r.cumulative_gas_used).unwrap_or_default(), blob_gas_used: is_cancun.then(|| { transactions.iter().map(|tx| tx.blob_gas_used().unwrap_or_default()).sum::() }), - excess_blob_gas: block_env.get_blob_excess_gas(), + excess_blob_gas: block_env.blob_excess_gas(), extra_data: Default::default(), parent_beacon_block_root: is_cancun.then_some(B256::ZERO), requests_hash: is_prague.then_some(EMPTY_REQUESTS_HASH), @@ -108,7 +112,7 @@ where fn assemble_receipt( &self, tx: &ProviderTx, - result: revm_primitives::ExecutionResult, + result: ExecutionResult>, cumulative_gas_used: u64, ) -> reth_provider::ProviderReceipt { #[allow(clippy::needless_update)] diff --git a/crates/rpc/rpc/src/eth/sim_bundle.rs b/crates/rpc/rpc/src/eth/sim_bundle.rs index c21a12894..5914b2a97 100644 --- a/crates/rpc/rpc/src/eth/sim_bundle.rs +++ b/crates/rpc/rpc/src/eth/sim_bundle.rs @@ -3,7 +3,7 @@ use alloy_consensus::BlockHeader; use alloy_eips::BlockNumberOrTag; use alloy_primitives::U256; -use alloy_rpc_types_eth::{BlockId, BlockOverrides}; +use alloy_rpc_types_eth::BlockId; use alloy_rpc_types_mev::{ BundleItem, Inclusion, Privacy, RefundConfig, SendBundleRequest, SimBundleLogs, SimBundleOverrides, SimBundleResponse, Validity, @@ -11,20 +11,19 @@ use alloy_rpc_types_mev::{ use jsonrpsee::core::RpcResult; use reth_evm::{ConfigureEvm, ConfigureEvmEnv, Evm}; use reth_provider::ProviderTx; -use reth_revm::database::StateProviderDatabase; +use reth_revm::{database::StateProviderDatabase, db::CacheDB}; use reth_rpc_api::MevSimApiServer; use reth_rpc_eth_api::{ helpers::{block::LoadBlock, Call, EthTransactions}, FromEthApiError, FromEvmError, }; -use reth_rpc_eth_types::{utils::recover_raw_transaction, EthApiError}; +use reth_rpc_eth_types::{ + revm_utils::apply_block_overrides, utils::recover_raw_transaction, EthApiError, +}; use reth_tasks::pool::BlockingTaskGuard; use reth_transaction_pool::{PoolConsensusTx, PoolPooledTx, PoolTransaction, TransactionPool}; -use revm::{ - db::CacheDB, - primitives::{Address, ResultAndState}, - DatabaseCommit, DatabaseRef, -}; +use revm::{context_interface::result::ResultAndState, DatabaseCommit, DatabaseRef}; +use revm_primitives::Address; use std::{sync::Arc, time::Duration}; use tracing::info; @@ -229,7 +228,6 @@ where logs: bool, ) -> Result { let SimBundleOverrides { parent_block, block_overrides, .. } = overrides; - let BlockOverrides { number, coinbase, time, gas_limit, base_fee, .. } = block_overrides; // Parse and validate bundle // Also, flatten the bundle here so that its easier to process @@ -240,27 +238,6 @@ where let current_block = self.eth_api().block_with_senders(current_block_id).await?; let current_block = current_block.ok_or(EthApiError::HeaderNotFound(block_id))?; - // apply overrides - if let Some(block_number) = number { - evm_env.block_env.number = U256::from(block_number); - } - - if let Some(coinbase) = coinbase { - evm_env.block_env.coinbase = coinbase; - } - - if let Some(timestamp) = time { - evm_env.block_env.timestamp = U256::from(timestamp); - } - - if let Some(gas_limit) = gas_limit { - evm_env.block_env.gas_limit = U256::from(gas_limit); - } - - if let Some(base_fee) = base_fee { - evm_env.block_env.basefee = U256::from(base_fee); - } - let eth_api = self.inner.eth_api.clone(); let sim_response = self @@ -269,9 +246,12 @@ where .spawn_with_state_at_block(current_block_id, move |state| { // Setup environment let current_block_number = current_block.number(); - let coinbase = evm_env.block_env.coinbase; + let coinbase = evm_env.block_env.beneficiary; let basefee = evm_env.block_env.basefee; - let db = CacheDB::new(StateProviderDatabase::new(state)); + let mut db = CacheDB::new(StateProviderDatabase::new(state)); + + // apply overrides + apply_block_overrides(block_overrides, &mut db, &mut evm_env.block_env); let initial_coinbase_balance = DatabaseRef::basic_ref(&db, coinbase) .map_err(EthApiError::from_eth_err)? @@ -354,7 +334,7 @@ where }); // Calculate payout transaction fee - let payout_tx_fee = basefee * + let payout_tx_fee = U256::from(basefee) * U256::from(SBUNDLE_PAYOUT_MAX_COST) * U256::from(refund_configs.len() as u64); diff --git a/crates/rpc/rpc/src/otterscan.rs b/crates/rpc/rpc/src/otterscan.rs index b8e1f92a7..06e6483f8 100644 --- a/crates/rpc/rpc/src/otterscan.rs +++ b/crates/rpc/rpc/src/otterscan.rs @@ -19,11 +19,11 @@ use reth_rpc_eth_api::{ }; use reth_rpc_eth_types::{utils::binary_search, EthApiError}; use reth_rpc_server_types::result::internal_rpc_err; +use revm::context_interface::result::ExecutionResult; use revm_inspectors::{ tracing::{types::CallTraceNode, TracingInspectorConfig}, transfer::{TransferInspector, TransferKind}, }; -use revm_primitives::ExecutionResult; const API_LEVEL: u64 = 8; diff --git a/crates/rpc/rpc/src/trace.rs b/crates/rpc/rpc/src/trace.rs index b7bf38eb6..a2057fd60 100644 --- a/crates/rpc/rpc/src/trace.rs +++ b/crates/rpc/rpc/src/trace.rs @@ -19,13 +19,13 @@ use reth_consensus_common::calc::{base_block_reward_pre_merge, block_reward, omm use reth_evm::ConfigureEvmEnv; use reth_primitives_traits::{BlockBody, BlockHeader}; use reth_provider::{BlockNumReader, BlockReader, ChainSpecProvider}; -use reth_revm::database::StateProviderDatabase; +use reth_revm::{database::StateProviderDatabase, db::CacheDB}; use reth_rpc_api::TraceApiServer; use reth_rpc_eth_api::{helpers::TraceExt, FromEthApiError, RpcNodeCore}; use reth_rpc_eth_types::{error::EthApiError, utils::recover_raw_transaction}; use reth_tasks::pool::BlockingTaskGuard; use reth_transaction_pool::{PoolPooledTx, PoolTransaction, TransactionPool}; -use revm::db::{CacheDB, DatabaseCommit}; +use revm::DatabaseCommit; use revm_inspectors::{ opcode::OpcodeGasInspector, tracing::{parity::populate_state_diff, TracingInspector, TracingInspectorConfig}, diff --git a/crates/storage/errors/Cargo.toml b/crates/storage/errors/Cargo.toml index e9405a485..ac390343c 100644 --- a/crates/storage/errors/Cargo.toml +++ b/crates/storage/errors/Cargo.toml @@ -25,6 +25,8 @@ alloy-rlp.workspace = true derive_more.workspace = true thiserror.workspace = true +revm-database-interface.workspace = true + [features] default = ["std"] std = [ @@ -34,6 +36,7 @@ std = [ "derive_more/std", "reth-primitives-traits/std", "thiserror/std", + "revm-database-interface/std", "reth-prune-types/std", "reth-static-file-types/std", ] diff --git a/crates/storage/errors/src/provider.rs b/crates/storage/errors/src/provider.rs index c2fac985c..92bf068e6 100644 --- a/crates/storage/errors/src/provider.rs +++ b/crates/storage/errors/src/provider.rs @@ -8,6 +8,7 @@ use derive_more::Display; use reth_primitives_traits::{transaction::signed::RecoveryError, GotExpected}; use reth_prune_types::PruneSegmentError; use reth_static_file_types::StaticFileSegment; +use revm_database_interface::DBErrorMarker; /// Provider result type. pub type ProviderResult = Result; @@ -177,6 +178,8 @@ impl ProviderError { } } +impl DBErrorMarker for ProviderError {} + impl From for ProviderError { fn from(error: alloy_rlp::Error) -> Self { Self::Rlp(error) diff --git a/crates/storage/provider/Cargo.toml b/crates/storage/provider/Cargo.toml index e9a246265..9a084932a 100644 --- a/crates/storage/provider/Cargo.toml +++ b/crates/storage/provider/Cargo.toml @@ -39,7 +39,8 @@ alloy-eips.workspace = true alloy-primitives.workspace = true alloy-rpc-types-engine.workspace = true alloy-consensus.workspace = true -revm.workspace = true +revm-database.workspace = true +revm-state = { workspace = true, optional = true } # async tokio = { workspace = true, features = ["sync", "macros", "rt-multi-thread"] } @@ -75,6 +76,8 @@ reth-testing-utils.workspace = true reth-ethereum-engine-primitives.workspace = true reth-ethereum-primitives.workspace = true +revm-database-interface.workspace = true +revm-state.workspace = true parking_lot.workspace = true tempfile.workspace = true assert_matches.workspace = true @@ -84,6 +87,12 @@ eyre.workspace = true alloy-consensus.workspace = true [features] +optimism = [ + "reth-execution-types/optimism", + "reth-codecs/op", + "reth-db/optimism", + "reth-db-api/optimism", +] serde = [ "dashmap/serde", "notify/serde", @@ -93,7 +102,6 @@ serde = [ "alloy-consensus/serde", "alloy-eips/serde", "alloy-rpc-types-engine/serde", - "revm/serde", "reth-codecs/serde", "reth-primitives-traits/serde", "reth-execution-types/serde", @@ -101,6 +109,9 @@ serde = [ "reth-trie/serde", "reth-stages-types/serde", "reth-prune-types/serde", + "revm-database/serde", + "revm-database-interface/serde", + "revm-state?/serde", ] test-utils = [ "reth-db/test-utils", @@ -117,7 +128,7 @@ test-utils = [ "reth-codecs/test-utils", "reth-db-api/test-utils", "reth-trie-db/test-utils", - "revm/test-utils", "reth-prune-types/test-utils", "reth-stages-types/test-utils", + "revm-state", ] diff --git a/crates/storage/provider/src/bundle_state/state_reverts.rs b/crates/storage/provider/src/bundle_state/state_reverts.rs index 3e1ba2a4b..1e0304c19 100644 --- a/crates/storage/provider/src/bundle_state/state_reverts.rs +++ b/crates/storage/provider/src/bundle_state/state_reverts.rs @@ -1,5 +1,5 @@ use alloy_primitives::{B256, U256}; -use revm::db::states::RevertToSlot; +use revm_database::states::RevertToSlot; use std::iter::Peekable; /// Iterator over storage reverts. diff --git a/crates/storage/provider/src/lib.rs b/crates/storage/provider/src/lib.rs index deccdea28..c35a2a6d9 100644 --- a/crates/storage/provider/src/lib.rs +++ b/crates/storage/provider/src/lib.rs @@ -36,7 +36,7 @@ pub use reth_execution_types::*; pub mod bundle_state; /// Re-export `OriginalValuesKnown` -pub use revm::db::states::OriginalValuesKnown; +pub use revm_database::states::OriginalValuesKnown; /// Writer standalone type. pub mod writer; diff --git a/crates/storage/provider/src/providers/blockchain_provider.rs b/crates/storage/provider/src/providers/blockchain_provider.rs index 23cac3df8..14a130a67 100644 --- a/crates/storage/provider/src/providers/blockchain_provider.rs +++ b/crates/storage/provider/src/providers/blockchain_provider.rs @@ -23,7 +23,7 @@ use reth_chain_state::{ use reth_chainspec::{ChainInfo, EthereumHardforks}; use reth_db::{models::BlockNumberAddress, transaction::DbTx, Database}; use reth_db_api::models::{AccountBeforeTx, StoredBlockBodyIndices}; -use reth_evm::{env::EvmEnv, ConfigureEvmEnv}; +use reth_evm::{ConfigureEvmEnv, EvmEnv}; use reth_execution_types::ExecutionOutcome; use reth_node_types::{BlockTy, HeaderTy, NodeTypesWithDB, ReceiptTy, TxTy}; use reth_primitives::{ @@ -40,10 +40,7 @@ use reth_storage_api::{ use reth_storage_errors::provider::ProviderResult; use reth_trie::HashedPostState; use reth_trie_db::StateCommitment; -use revm::{ - db::BundleState, - primitives::{BlockEnv, CfgEnvWithHandlerCfg}, -}; +use revm_database::BundleState; use std::{ ops::{Add, RangeBounds, RangeInclusive, Sub}, sync::Arc, @@ -811,7 +808,7 @@ mod tests { self, random_block, random_block_range, random_changeset_range, random_eoa_accounts, random_receipt, BlockParams, BlockRangeParams, }; - use revm::db::BundleState; + use revm_database::BundleState; use std::{ ops::{Bound, Deref, Range, RangeBounds}, sync::Arc, diff --git a/crates/storage/provider/src/providers/bundle_state_provider.rs b/crates/storage/provider/src/providers/bundle_state_provider.rs index 36a1f2fbe..b1b74c3ca 100644 --- a/crates/storage/provider/src/providers/bundle_state_provider.rs +++ b/crates/storage/provider/src/providers/bundle_state_provider.rs @@ -187,7 +187,7 @@ impl StateProofProvider impl HashedPostStateProvider for BundleStateProvider { - fn hashed_post_state(&self, bundle_state: &revm::db::BundleState) -> HashedPostState { + fn hashed_post_state(&self, bundle_state: &revm_database::BundleState) -> HashedPostState { self.state_provider.hashed_post_state(bundle_state) } } diff --git a/crates/storage/provider/src/providers/consistent.rs b/crates/storage/provider/src/providers/consistent.rs index 1bd0fc03c..e26aee1dc 100644 --- a/crates/storage/provider/src/providers/consistent.rs +++ b/crates/storage/provider/src/providers/consistent.rs @@ -30,7 +30,7 @@ use reth_storage_api::{ StateProvider, StorageChangeSetReader, }; use reth_storage_errors::provider::ProviderResult; -use revm::db::states::PlainStorageRevert; +use revm_database::states::PlainStorageRevert; use std::{ ops::{Add, Bound, RangeBounds, RangeInclusive, Sub}, sync::Arc, @@ -1492,7 +1492,7 @@ mod tests { use reth_testing_utils::generators::{ self, random_block_range, random_changeset_range, random_eoa_accounts, BlockRangeParams, }; - use revm::db::BundleState; + use revm_database::BundleState; use std::{ ops::{Bound, Range, RangeBounds}, sync::Arc, diff --git a/crates/storage/provider/src/providers/database/mod.rs b/crates/storage/provider/src/providers/database/mod.rs index 9c2e5031f..54b21d023 100644 --- a/crates/storage/provider/src/providers/database/mod.rs +++ b/crates/storage/provider/src/providers/database/mod.rs @@ -28,7 +28,7 @@ use reth_storage_api::{ use reth_storage_errors::provider::ProviderResult; use reth_trie::HashedPostState; use reth_trie_db::StateCommitment; -use revm::db::BundleState; +use revm_database::BundleState; use std::{ ops::{RangeBounds, RangeInclusive}, path::Path, diff --git a/crates/storage/provider/src/providers/database/provider.rs b/crates/storage/provider/src/providers/database/provider.rs index ce2b29eba..52dffe2fe 100644 --- a/crates/storage/provider/src/providers/database/provider.rs +++ b/crates/storage/provider/src/providers/database/provider.rs @@ -66,7 +66,7 @@ use reth_trie::{ HashedPostStateSorted, Nibbles, StateRoot, StoredNibbles, }; use reth_trie_db::{DatabaseStateRoot, DatabaseStorageTrieCursor}; -use revm::db::states::{ +use revm_database::states::{ PlainStateReverts, PlainStorageChangeset, PlainStorageRevert, StateChangeset, }; use std::{ diff --git a/crates/storage/provider/src/providers/state/historical.rs b/crates/storage/provider/src/providers/state/historical.rs index 6a7a49288..447535a1b 100644 --- a/crates/storage/provider/src/providers/state/historical.rs +++ b/crates/storage/provider/src/providers/state/historical.rs @@ -395,7 +395,7 @@ impl StateProof impl HashedPostStateProvider for HistoricalStateProviderRef<'_, Provider> { - fn hashed_post_state(&self, bundle_state: &revm::db::BundleState) -> HashedPostState { + fn hashed_post_state(&self, bundle_state: &revm_database::BundleState) -> HashedPostState { HashedPostState::from_bundle_state::< ::KeyHasher, >(bundle_state.state()) diff --git a/crates/storage/provider/src/providers/state/latest.rs b/crates/storage/provider/src/providers/state/latest.rs index 6a2857e50..dc7632921 100644 --- a/crates/storage/provider/src/providers/state/latest.rs +++ b/crates/storage/provider/src/providers/state/latest.rs @@ -152,7 +152,7 @@ impl StateProofProvider impl HashedPostStateProvider for LatestStateProviderRef<'_, Provider> { - fn hashed_post_state(&self, bundle_state: &revm::db::BundleState) -> HashedPostState { + fn hashed_post_state(&self, bundle_state: &revm_database::BundleState) -> HashedPostState { HashedPostState::from_bundle_state::< ::KeyHasher, >(bundle_state.state()) diff --git a/crates/storage/provider/src/providers/state/macros.rs b/crates/storage/provider/src/providers/state/macros.rs index bc96f3ad0..18dfb42f9 100644 --- a/crates/storage/provider/src/providers/state/macros.rs +++ b/crates/storage/provider/src/providers/state/macros.rs @@ -58,7 +58,7 @@ macro_rules! delegate_provider_impls { fn witness(&self, input: reth_trie::TrieInput, target: reth_trie::HashedPostState) -> reth_storage_errors::provider::ProviderResult>; } HashedPostStateProvider $(where [$($generics)*])? { - fn hashed_post_state(&self, bundle_state: &revm::db::BundleState) -> reth_trie::HashedPostState; + fn hashed_post_state(&self, bundle_state: &revm_database::BundleState) -> reth_trie::HashedPostState; } ); } diff --git a/crates/storage/provider/src/test_utils/blocks.rs b/crates/storage/provider/src/test_utils/blocks.rs index 6f44b9fe1..e72ea7fdf 100644 --- a/crates/storage/provider/src/test_utils/blocks.rs +++ b/crates/storage/provider/src/test_utils/blocks.rs @@ -16,7 +16,8 @@ use reth_primitives::{ TransactionSigned, TxType, }; use reth_trie::root::{state_root_unhashed, storage_root_unhashed}; -use revm::{db::BundleState, primitives::AccountInfo}; +use revm_database::BundleState; +use revm_state::AccountInfo; use std::{str::FromStr, sync::LazyLock}; /// Assert genesis block diff --git a/crates/storage/provider/src/test_utils/mock.rs b/crates/storage/provider/src/test_utils/mock.rs index c7130706d..fd177cc58 100644 --- a/crates/storage/provider/src/test_utils/mock.rs +++ b/crates/storage/provider/src/test_utils/mock.rs @@ -729,10 +729,10 @@ impl StateProofProvider for MockEthProv } } -impl HashedPostStateProvider +impl HashedPostStateProvider for MockEthProvider { - fn hashed_post_state(&self, _state: &revm::db::BundleState) -> HashedPostState { + fn hashed_post_state(&self, _state: &revm_database::BundleState) -> HashedPostState { HashedPostState::default() } } diff --git a/crates/storage/provider/src/traits/state.rs b/crates/storage/provider/src/traits/state.rs index b49e05db2..671ea2e27 100644 --- a/crates/storage/provider/src/traits/state.rs +++ b/crates/storage/provider/src/traits/state.rs @@ -2,7 +2,7 @@ use alloy_primitives::BlockNumber; use reth_execution_types::ExecutionOutcome; use reth_storage_errors::provider::ProviderResult; use reth_trie::HashedPostStateSorted; -use revm::db::{ +use revm_database::{ states::{PlainStateReverts, StateChangeset}, OriginalValuesKnown, }; diff --git a/crates/storage/provider/src/writer/mod.rs b/crates/storage/provider/src/writer/mod.rs index 8867698c5..47e9242ac 100644 --- a/crates/storage/provider/src/writer/mod.rs +++ b/crates/storage/provider/src/writer/mod.rs @@ -11,7 +11,7 @@ use reth_primitives::{NodePrimitives, StaticFileSegment}; use reth_primitives_traits::SignedTransaction; use reth_storage_api::{DBProvider, StageCheckpointWriter, TransactionsProviderExt}; use reth_storage_errors::writer::UnifiedStorageWriterError; -use revm::db::OriginalValuesKnown; +use revm_database::OriginalValuesKnown; use std::sync::Arc; use tracing::debug; @@ -242,17 +242,15 @@ mod tests { HashedPostState, HashedStorage, StateRoot, StorageRoot, }; use reth_trie_db::{DatabaseStateRoot, DatabaseStorageRoot}; - use revm::{ - db::{ - states::{ - bundle_state::BundleRetention, changes::PlainStorageRevert, PlainStorageChangeset, - }, - BundleState, EmptyDB, + use revm_database::{ + states::{ + bundle_state::BundleRetention, changes::PlainStorageRevert, PlainStorageChangeset, }, - primitives::{ - Account as RevmAccount, AccountInfo as RevmAccountInfo, AccountStatus, EvmStorageSlot, - }, - DatabaseCommit, State, + BundleState, State, + }; + use revm_database_interface::{DatabaseCommit, EmptyDB}; + use revm_state::{ + Account as RevmAccount, AccountInfo as RevmAccountInfo, AccountStatus, EvmStorageSlot, }; use std::{collections::BTreeMap, str::FromStr}; diff --git a/crates/storage/storage-api/Cargo.toml b/crates/storage/storage-api/Cargo.toml index bcba142d4..fc46af864 100644 --- a/crates/storage/storage-api/Cargo.toml +++ b/crates/storage/storage-api/Cargo.toml @@ -23,7 +23,7 @@ reth-storage-errors.workspace = true reth-trie.workspace = true reth-trie-db.workspace = true reth-db.workspace = true -revm.workspace = true +revm-database.workspace = true reth-ethereum-primitives.workspace = true # ethereum @@ -42,11 +42,11 @@ std = [ "alloy-eips/std", "alloy-primitives/std", "alloy-rpc-types-engine/std", - "reth-ethereum-primitives/std", "reth-primitives-traits/std", - "revm/std", "reth-stages-types/std", + "revm-database/std", + "reth-ethereum-primitives/std", + "reth-execution-types/std", "reth-prune-types/std", "reth-storage-errors/std", - "reth-execution-types/std", ] diff --git a/crates/storage/storage-api/src/noop.rs b/crates/storage/storage-api/src/noop.rs index 5a2cad5e5..da67b7fdc 100644 --- a/crates/storage/storage-api/src/noop.rs +++ b/crates/storage/storage-api/src/noop.rs @@ -447,7 +447,7 @@ impl StateProofProvider for NoopProvider HashedPostStateProvider for NoopProvider { - fn hashed_post_state(&self, _bundle_state: &revm::db::BundleState) -> HashedPostState { + fn hashed_post_state(&self, _bundle_state: &revm_database::BundleState) -> HashedPostState { HashedPostState::default() } } diff --git a/crates/storage/storage-api/src/state.rs b/crates/storage/storage-api/src/state.rs index 21f75dc23..b2e1bf462 100644 --- a/crates/storage/storage-api/src/state.rs +++ b/crates/storage/storage-api/src/state.rs @@ -11,7 +11,7 @@ use reth_primitives_traits::Bytecode; use reth_storage_errors::provider::ProviderResult; use reth_trie::HashedPostState; use reth_trie_db::StateCommitment; -use revm::db::states::BundleState; +use revm_database::BundleState; /// Type alias of boxed [`StateProvider`]. pub type StateProviderBox = Box; diff --git a/crates/transaction-pool/Cargo.toml b/crates/transaction-pool/Cargo.toml index 08435c900..f22052eab 100644 --- a/crates/transaction-pool/Cargo.toml +++ b/crates/transaction-pool/Cargo.toml @@ -22,8 +22,8 @@ reth-execution-types.workspace = true reth-fs-util.workspace = true reth-storage-api.workspace = true reth-tasks.workspace = true -revm-primitives.workspace = true revm-interpreter.workspace = true +revm-specification.workspace = true # ethereum alloy-eips = { workspace = true, features = ["kzg"] } @@ -88,7 +88,7 @@ serde = [ "smallvec/serde", "reth-primitives-traits/serde", "revm-interpreter/serde", - "revm-primitives/serde", + "revm-specification/serde", ] test-utils = [ "rand", @@ -113,7 +113,6 @@ arbitrary = [ "reth-primitives-traits/arbitrary", "smallvec/arbitrary", "revm-interpreter/arbitrary", - "revm-primitives/arbitrary", ] [[bench]] diff --git a/crates/transaction-pool/src/traits.rs b/crates/transaction-pool/src/traits.rs index c3503ca67..676b23db6 100644 --- a/crates/transaction-pool/src/traits.rs +++ b/crates/transaction-pool/src/traits.rs @@ -12,7 +12,7 @@ use alloy_eips::{ eip4844::{BlobAndProofV1, BlobTransactionSidecar, BlobTransactionValidationError}, eip7702::SignedAuthorization, }; -use alloy_primitives::{Address, TxHash, TxKind, B256, U256}; +use alloy_primitives::{Address, Bytes, TxHash, TxKind, B256, U256}; use futures_util::{ready, Stream}; use reth_eth_wire_types::HandleMempoolData; use reth_execution_types::ChangedAccount; @@ -1284,7 +1284,7 @@ impl alloy_consensus::Transaction for EthPooled self.transaction.value() } - fn input(&self) -> &revm_primitives::Bytes { + fn input(&self) -> &Bytes { self.transaction.input() } diff --git a/crates/transaction-pool/src/validate/eth.rs b/crates/transaction-pool/src/validate/eth.rs index c8edbf52d..42e5dda79 100644 --- a/crates/transaction-pool/src/validate/eth.rs +++ b/crates/transaction-pool/src/validate/eth.rs @@ -885,7 +885,7 @@ pub fn ensure_intrinsic_gas( transaction: &T, fork_tracker: &ForkTracker, ) -> Result<(), InvalidPoolTransactionError> { - use revm_primitives::SpecId; + use revm_specification::hardfork::SpecId; let spec_id = if fork_tracker.is_prague_activated() { SpecId::PRAGUE } else if fork_tracker.is_shanghai_activated() { @@ -898,8 +898,12 @@ pub fn ensure_intrinsic_gas( spec_id, transaction.input(), transaction.is_create(), - transaction.access_list().map(|list| list.0.as_slice()).unwrap_or(&[]), - transaction.authorization_list().map(|l| l.len()).unwrap_or(0) as u64, + transaction.access_list().map(|l| l.len()).unwrap_or_default() as u64, + transaction + .access_list() + .map(|l| l.iter().map(|i| i.storage_keys.len()).sum::()) + .unwrap_or_default() as u64, + transaction.authorization_list().map(|l| l.len()).unwrap_or_default() as u64, ); let gas_limit = transaction.gas_limit(); diff --git a/crates/trie/common/Cargo.toml b/crates/trie/common/Cargo.toml index e98d574cd..a72b9f435 100644 --- a/crates/trie/common/Cargo.toml +++ b/crates/trie/common/Cargo.toml @@ -29,7 +29,7 @@ itertools = { workspace = true, features = ["use_alloc"] } nybbles = { workspace = true, features = ["rlp"] } # reth -revm.workspace = true +revm-database.workspace = true # `serde` feature serde = { workspace = true, optional = true } @@ -62,6 +62,7 @@ bincode.workspace = true serde.workspace = true serde_json.workspace = true serde_with.workspace = true +revm-state.workspace = true [features] default = ["std"] @@ -80,7 +81,8 @@ std = [ "serde?/std", "serde_with?/std", "serde_json/std", - "revm/std", + "revm-database/std", + "revm-state/std", ] eip1186 = [ "alloy-rpc-types-eth/serde", @@ -96,7 +98,8 @@ serde = [ "alloy-rpc-types-eth?/serde", "reth-primitives-traits/serde", "reth-codecs?/serde", - "revm/serde", + "revm-database/serde", + "revm-state/serde", ] reth-codec = [ "dep:reth-codecs", @@ -114,7 +117,6 @@ test-utils = [ "arbitrary", "reth-primitives-traits/test-utils", "reth-codecs/test-utils", - "revm/test-utils", ] arbitrary = [ "std", @@ -128,7 +130,6 @@ arbitrary = [ "nybbles/arbitrary", "reth-codecs/arbitrary", "alloy-rpc-types-eth?/arbitrary", - "revm/arbitrary", ] rayon = ["dep:rayon"] diff --git a/crates/trie/common/src/hashedstate.rs b/crates/trie/common/src/hashedstate.rs index 7da72cbe7..dd33af85d 100644 --- a/crates/trie/common/src/hashedstate.rs +++ b/crates/trie/common/src/hashedstate.rs @@ -9,15 +9,15 @@ use alloy_primitives::{ Address, B256, U256, }; use itertools::Itertools; -use reth_primitives_traits::Account; -use revm::db::{AccountStatus, BundleAccount}; - #[cfg(feature = "rayon")] pub use rayon::*; +use reth_primitives_traits::Account; #[cfg(feature = "rayon")] use rayon::prelude::{IntoParallelIterator, ParallelIterator}; +use revm_database::{AccountStatus, BundleAccount}; + /// Representation of in-memory hashed state. #[derive(PartialEq, Eq, Clone, Default, Debug)] pub struct HashedPostState { @@ -381,10 +381,8 @@ mod tests { use super::*; use crate::KeccakKeyHasher; use alloy_primitives::Bytes; - use revm::{ - db::{states::StorageSlot, StorageWithOriginalValues}, - primitives::{AccountInfo, Bytecode}, - }; + use revm_database::{states::StorageSlot, StorageWithOriginalValues}; + use revm_state::{AccountInfo, Bytecode}; #[test] fn hashed_state_wiped_extension() { @@ -470,7 +468,7 @@ mod tests { balance: U256::from(123), nonce: 42, code_hash: B256::random(), - code: Some(Bytecode::LegacyRaw(Bytes::from(vec![1, 2]))), + code: Some(Bytecode::new_raw(Bytes::from(vec![1, 2]))), }; let mut storage = StorageWithOriginalValues::default(); diff --git a/crates/trie/db/Cargo.toml b/crates/trie/db/Cargo.toml index af31ccab9..b7e51be9c 100644 --- a/crates/trie/db/Cargo.toml +++ b/crates/trie/db/Cargo.toml @@ -53,6 +53,7 @@ reth-trie-common = { workspace = true, features = ["test-utils", "arbitrary"] } reth-trie = { workspace = true, features = ["test-utils"] } alloy-consensus.workspace = true +revm-database.workspace = true # trie triehash = "0.8" @@ -75,6 +76,7 @@ serde = [ "reth-trie-common/serde", "reth-provider/serde", "reth-primitives-traits/serde", + "revm-database/serde", ] test-utils = [ "triehash", diff --git a/crates/trie/db/src/state.rs b/crates/trie/db/src/state.rs index 8d9bf029a..31ebc24ab 100644 --- a/crates/trie/db/src/state.rs +++ b/crates/trie/db/src/state.rs @@ -270,7 +270,8 @@ mod tests { use reth_db::test_utils::create_test_rw_db; use reth_db_api::database::Database; use reth_trie::KeccakKeyHasher; - use revm::{db::BundleState, primitives::AccountInfo}; + use revm::state::AccountInfo; + use revm_database::BundleState; #[test] fn from_bundle_state_with_rayon() { diff --git a/crates/trie/trie/Cargo.toml b/crates/trie/trie/Cargo.toml index 71b486152..33b0438e5 100644 --- a/crates/trie/trie/Cargo.toml +++ b/crates/trie/trie/Cargo.toml @@ -20,7 +20,7 @@ reth-storage-errors.workspace = true reth-trie-sparse.workspace = true reth-trie-common = { workspace = true, features = ["rayon"] } -revm.workspace = true +revm-database.workspace = true # alloy alloy-eips.workspace = true @@ -49,6 +49,9 @@ reth-primitives-traits = { workspace = true, features = ["test-utils"] } reth-ethereum-primitives = { workspace = true, features = ["arbitrary", "std"] } reth-trie-common = { workspace = true, features = ["test-utils", "arbitrary"] } +# revm +revm-state.workspace = true + # trie triehash = "0.8" @@ -65,14 +68,19 @@ serde = [ "alloy-consensus/serde", "alloy-trie/serde", "alloy-eips/serde", - "revm/serde", "reth-trie-common/serde", "reth-primitives-traits/serde", + "alloy-primitives/serde", + "alloy-consensus/serde", + "alloy-trie/serde", + "alloy-eips/serde", + "reth-trie-common/serde", + "revm-database/serde", "reth-stages-types/serde", + "revm-state/serde", ] test-utils = [ "triehash", - "revm/test-utils", "reth-primitives-traits/test-utils", "reth-trie-common/test-utils", "reth-ethereum-primitives/test-utils", diff --git a/crates/trie/trie/benches/hash_post_state.rs b/crates/trie/trie/benches/hash_post_state.rs index a50b3cd15..3cbd2ced8 100644 --- a/crates/trie/trie/benches/hash_post_state.rs +++ b/crates/trie/trie/benches/hash_post_state.rs @@ -3,7 +3,7 @@ use alloy_primitives::{keccak256, map::HashMap, Address, B256, U256}; use criterion::{criterion_group, criterion_main, BenchmarkId, Criterion}; use proptest::{prelude::*, strategy::ValueTree, test_runner::TestRunner}; use reth_trie::{HashedPostState, HashedStorage, KeccakKeyHasher}; -use revm::db::{states::BundleBuilder, BundleAccount}; +use revm_database::{states::BundleBuilder, BundleAccount}; pub fn hash_post_state(c: &mut Criterion) { let mut group = c.benchmark_group("Hash Post State"); diff --git a/deny.toml b/deny.toml index cc48b1667..f43544942 100644 --- a/deny.toml +++ b/deny.toml @@ -93,4 +93,5 @@ allow-git = [ "https://github.com/foundry-rs/block-explorers", "https://github.com/bluealloy/revm", "https://github.com/paradigmxyz/revm-inspectors", + "https://github.com/alloy-rs/evm", ] diff --git a/examples/custom-beacon-withdrawals/src/main.rs b/examples/custom-beacon-withdrawals/src/main.rs index e16cfe7e8..c19c34d40 100644 --- a/examples/custom-beacon-withdrawals/src/main.rs +++ b/examples/custom-beacon-withdrawals/src/main.rs @@ -12,8 +12,9 @@ use reth::{ builder::{components::ExecutorBuilder, BuilderContext, FullNodeTypes}, cli::Cli, revm::{ + db::State, primitives::{address, Address}, - DatabaseCommit, State, + DatabaseCommit, }, }; use reth_chainspec::{ChainSpec, EthereumHardforks}; @@ -204,7 +205,7 @@ pub fn apply_withdrawals_contract_call( // Clean-up post system tx context state.remove(&SYSTEM_ADDRESS); - state.remove(&evm.block().coinbase); + state.remove(&evm.block().beneficiary); evm.db_mut().commit(state); diff --git a/examples/custom-evm/Cargo.toml b/examples/custom-evm/Cargo.toml index b236647f1..103c4e3db 100644 --- a/examples/custom-evm/Cargo.toml +++ b/examples/custom-evm/Cargo.toml @@ -16,6 +16,7 @@ reth-ethereum-payload-builder.workspace = true reth-node-ethereum = { workspace = true, features = ["test-utils"] } reth-tracing.workspace = true reth-evm.workspace = true +alloy-evm.workspace = true alloy-genesis.workspace = true alloy-primitives.workspace = true alloy-consensus.workspace = true diff --git a/examples/custom-evm/src/main.rs b/examples/custom-evm/src/main.rs index 06c92960b..6aa7551e3 100644 --- a/examples/custom-evm/src/main.rs +++ b/examples/custom-evm/src/main.rs @@ -3,6 +3,7 @@ #![cfg_attr(not(test), warn(unused_crate_dependencies))] use alloy_consensus::Header; +use alloy_evm::{eth::EthEvmContext, EvmFactory}; use alloy_genesis::Genesis; use alloy_primitives::{address, Address, Bytes}; use reth::{ @@ -12,21 +13,24 @@ use reth::{ }, payload::{EthBuiltPayload, EthPayloadBuilderAttributes}, revm::{ - handler::register::EvmHandler, - inspector_handle_register, - precompile::{Precompile, PrecompileOutput, PrecompileSpecId}, - primitives::{ - CfgEnvWithHandlerCfg, EVMError, Env, HaltReason, HandlerCfg, PrecompileResult, SpecId, - TxEnv, + context::{Cfg, Context, TxEnv}, + context_interface::{ + result::{EVMError, HaltReason}, + ContextTr, }, - ContextPrecompiles, EvmBuilder, GetInspector, + handler::{EthPrecompiles, PrecompileProvider}, + inspector::{Inspector, NoOpInspector}, + interpreter::{interpreter::EthInterpreter, InterpreterResult}, + precompile::{PrecompileFn, PrecompileOutput, PrecompileResult, Precompiles}, + specification::hardfork::SpecId, + MainBuilder, MainContext, }, rpc::types::engine::PayloadAttributes, tasks::TaskManager, transaction_pool::{PoolTransaction, TransactionPool}, }; use reth_chainspec::{Chain, ChainSpec}; -use reth_evm::{env::EvmEnv, Database}; +use reth_evm::{Database, EvmEnv}; use reth_evm_ethereum::{EthEvm, EthEvmConfig}; use reth_node_api::{ ConfigureEvm, ConfigureEvmEnv, FullNodeTypes, NextBlockEnvAttributes, NodeTypes, @@ -39,7 +43,44 @@ use reth_node_ethereum::{ }; use reth_primitives::{EthPrimitives, TransactionSigned}; use reth_tracing::{RethTracer, Tracer}; -use std::{convert::Infallible, sync::Arc}; +use std::{ + convert::Infallible, + sync::{Arc, OnceLock}, +}; + +/// Custom EVM configuration. +#[derive(Debug, Clone, Default)] +#[non_exhaustive] +pub struct MyEvmFactory; + +impl EvmFactory for MyEvmFactory { + type Evm, EthInterpreter>> = + EthEvm>>; + type Tx = TxEnv; + type Error = EVMError; + type HaltReason = HaltReason; + type Context = EthEvmContext; + + fn create_evm(&self, db: DB, input: EvmEnv) -> Self::Evm { + let evm = Context::mainnet() + .with_db(db) + .with_cfg(input.cfg_env) + .with_block(input.block_env) + .build_mainnet_with_inspector(NoOpInspector {}) + .with_precompiles(CustomPrecompiles::new()); + + EthEvm::new(evm, false) + } + + fn create_evm_with_inspector, EthInterpreter>>( + &self, + db: DB, + input: EvmEnv, + inspector: I, + ) -> Self::Evm { + EthEvm::new(self.create_evm(db, input).into_inner().with_inspector(inspector), true) + } +} /// Custom EVM configuration #[derive(Debug, Clone)] @@ -47,42 +88,13 @@ use std::{convert::Infallible, sync::Arc}; pub struct MyEvmConfig { /// Wrapper around mainnet configuration inner: EthEvmConfig, + /// Custom EVM factory. + evm_factory: MyEvmFactory, } impl MyEvmConfig { - pub const fn new(chain_spec: Arc) -> Self { - Self { inner: EthEvmConfig::new(chain_spec) } - } -} - -impl MyEvmConfig { - /// Sets the precompiles to the EVM handler - /// - /// This will be invoked when the EVM is created via [ConfigureEvm::evm_with_env] or - /// [ConfigureEvm::evm_with_env_and_inspector] - /// - /// This will use the default mainnet precompiles and add additional precompiles. - pub fn set_precompiles(handler: &mut EvmHandler) - where - DB: Database, - { - // first we need the evm spec id, which determines the precompiles - let spec_id = handler.cfg.spec_id; - - // install the precompiles - handler.pre_execution.load_precompiles = Arc::new(move || { - let mut precompiles = ContextPrecompiles::new(PrecompileSpecId::from_spec_id(spec_id)); - precompiles.extend([( - address!("0000000000000000000000000000000000000999"), - Precompile::Env(Self::my_precompile).into(), - )]); - precompiles - }); - } - - /// A custom precompile that does nothing - fn my_precompile(_data: &Bytes, _gas: u64, _env: &Env) -> PrecompileResult { - Ok(PrecompileOutput::new(0, Bytes::new())) + pub fn new(chain_spec: Arc) -> Self { + Self { inner: EthEvmConfig::new(chain_spec), evm_factory: MyEvmFactory::default() } } } @@ -111,50 +123,10 @@ impl ConfigureEvmEnv for MyEvmConfig { } impl ConfigureEvm for MyEvmConfig { - type Evm<'a, DB: Database + 'a, I: 'a> = EthEvm<'a, I, DB>; - type EvmError = EVMError; - type HaltReason = HaltReason; + type EvmFactory = MyEvmFactory; - fn evm_with_env(&self, db: DB, evm_env: EvmEnv) -> Self::Evm<'_, DB, ()> { - let cfg_env_with_handler_cfg = CfgEnvWithHandlerCfg { - cfg_env: evm_env.cfg_env, - handler_cfg: HandlerCfg::new(evm_env.spec), - }; - EvmBuilder::default() - .with_db(db) - .with_cfg_env_with_handler_cfg(cfg_env_with_handler_cfg) - .with_block_env(evm_env.block_env) - // add additional precompiles - .append_handler_register(MyEvmConfig::set_precompiles) - .build() - .into() - } - - fn evm_with_env_and_inspector( - &self, - db: DB, - evm_env: EvmEnv, - inspector: I, - ) -> Self::Evm<'_, DB, I> - where - DB: Database, - I: GetInspector, - { - let cfg_env_with_handler_cfg = CfgEnvWithHandlerCfg { - cfg_env: evm_env.cfg_env, - handler_cfg: HandlerCfg::new(evm_env.spec), - }; - - EvmBuilder::default() - .with_db(db) - .with_external_context(inspector) - .with_cfg_env_with_handler_cfg(cfg_env_with_handler_cfg) - .with_block_env(evm_env.block_env) - // add additional precompiles - .append_handler_register(MyEvmConfig::set_precompiles) - .append_handler_register(inspector_handle_register) - .build() - .into() + fn evm_factory(&self) -> &Self::EvmFactory { + &self.evm_factory } } @@ -215,6 +187,70 @@ where self.inner.build(MyEvmConfig::new(ctx.chain_spec()), ctx, pool) } } + +/// A custom precompile that contains static precompiles. +#[derive(Clone)] +pub struct CustomPrecompiles { + pub precompiles: EthPrecompiles, +} + +impl CustomPrecompiles { + /// Given a [`PrecompileProvider`] and cache for a specific precompiles, create a + /// wrapper that can be used inside Evm. + fn new() -> Self { + Self { precompiles: EthPrecompiles::default() } + } +} + +/// Returns precompiles for Fjor spec. +pub fn prague_custom() -> &'static Precompiles { + static INSTANCE: OnceLock = OnceLock::new(); + INSTANCE.get_or_init(|| { + let mut precompiles = Precompiles::prague().clone(); + // Custom precompile. + precompiles.extend([( + address!("0000000000000000000000000000000000000999"), + |_, _| -> PrecompileResult { + PrecompileResult::Ok(PrecompileOutput::new(0, Bytes::new())) + } as PrecompileFn, + ) + .into()]); + precompiles + }) +} + +impl PrecompileProvider for CustomPrecompiles { + type Context = CTX; + type Output = InterpreterResult; + + fn set_spec(&mut self, spec: <::Cfg as Cfg>::Spec) { + let spec_id = spec.clone().into(); + if spec_id == SpecId::PRAGUE { + self.precompiles = EthPrecompiles { precompiles: prague_custom(), ..Default::default() } + } else { + self.precompiles.set_spec(spec); + } + } + + fn run( + &mut self, + context: &mut Self::Context, + address: &Address, + bytes: &Bytes, + gas_limit: u64, + ) -> Result, reth::revm::precompile::PrecompileErrors> { + self.precompiles.run(context, address, bytes, gas_limit) + } + + fn contains(&self, address: &Address) -> bool { + self.precompiles.contains(address) + } + + fn warm_addresses(&self) -> Box + '_> { + self.precompiles.warm_addresses() + } +} + #[tokio::main] async fn main() -> eyre::Result<()> { let _guard = RethTracer::new().init()?; diff --git a/examples/custom-inspector/Cargo.toml b/examples/custom-inspector/Cargo.toml index 5d9753da7..e8051e4f7 100644 --- a/examples/custom-inspector/Cargo.toml +++ b/examples/custom-inspector/Cargo.toml @@ -9,9 +9,9 @@ license.workspace = true reth.workspace = true reth-evm.workspace = true reth-node-ethereum.workspace = true -revm-primitives.workspace = true alloy-rpc-types-eth.workspace = true clap = { workspace = true, features = ["derive"] } futures-util.workspace = true +alloy-evm.workspace = true alloy-primitives.workspace = true alloy-eips.workspace = true diff --git a/examples/custom-inspector/src/main.rs b/examples/custom-inspector/src/main.rs index 9afaf17ea..134bce76b 100644 --- a/examples/custom-inspector/src/main.rs +++ b/examples/custom-inspector/src/main.rs @@ -11,6 +11,7 @@ #![cfg_attr(not(test), warn(unused_crate_dependencies))] use alloy_eips::BlockNumberOrTag; +use alloy_evm::Evm; use alloy_primitives::Address; use alloy_rpc_types_eth::{state::EvmOverrides, TransactionRequest}; use clap::Parser; @@ -20,17 +21,16 @@ use reth::{ chainspec::EthereumChainSpecParser, cli::Cli, revm::{ - inspector_handle_register, - interpreter::{Interpreter, OpCode}, - primitives::{Env, EnvWithHandlerCfg}, - Database, Evm, EvmContext, Inspector, + bytecode::opcode::OpCode, + context_interface::ContextTr, + inspector::Inspector, + interpreter::{interpreter::EthInterpreter, interpreter_types::Jumps, Interpreter}, }, rpc::api::eth::helpers::Call, transaction_pool::TransactionPool, }; -use reth_evm::EvmEnv; +use reth_evm::ConfigureEvm; use reth_node_ethereum::node::EthereumNode; -use revm_primitives::HandlerCfg; fn main() { Cli::::parse() @@ -60,31 +60,24 @@ fn main() { let call_request = TransactionRequest::from_recovered_transaction(tx.to_consensus()); + let evm_config = node.evm_config.clone(); + let result = eth_api .spawn_with_call_at( call_request, BlockNumberOrTag::Latest.into(), EvmOverrides::default(), move |db, evm_env, tx_env| { - let EvmEnv { cfg_env, block_env, spec } = evm_env; - let env = EnvWithHandlerCfg { - handler_cfg: HandlerCfg::new(spec), - env: Env::boxed(cfg_env, block_env, tx_env), - }; let mut dummy_inspector = DummyInspector::default(); - { - // configure the evm with the custom inspector - let mut evm = Evm::builder() - .with_db(db) - .with_external_context(&mut dummy_inspector) - .with_env_with_handler_cfg(env) - .append_handler_register(inspector_handle_register) - .build(); - // execute the transaction on a blocking task and await - // the - // inspector result - let _ = evm.transact()?; - } + let mut evm = evm_config.evm_with_env_and_inspector( + db, + evm_env, + &mut dummy_inspector, + ); + // execute the transaction on a blocking task and await + // the + // inspector result + let _ = evm.transact(tx_env)?; Ok(dummy_inspector) }, ) @@ -130,16 +123,16 @@ struct DummyInspector { ret_val: Vec, } -impl Inspector for DummyInspector +impl Inspector for DummyInspector where - DB: Database, + CTX: ContextTr, { /// This method is called at each step of the EVM execution. /// It checks if the current opcode is valid and if so, it stores the opcode and its /// corresponding program counter in the `ret_val` vector. - fn step(&mut self, interp: &mut Interpreter, _context: &mut EvmContext) { - if let Some(opcode) = OpCode::new(interp.current_opcode()) { - self.ret_val.push(format!("{}: {}", interp.program_counter(), opcode)); + fn step(&mut self, interp: &mut Interpreter, _context: &mut CTX) { + if let Some(opcode) = OpCode::new(interp.bytecode.opcode()) { + self.ret_val.push(format!("{}: {}", interp.bytecode.pc(), opcode)); } } } diff --git a/examples/custom-rlpx-subprotocol/src/subprotocol/protocol/proto.rs b/examples/custom-rlpx-subprotocol/src/subprotocol/protocol/proto.rs index 4657fe1f1..b0786e20f 100644 --- a/examples/custom-rlpx-subprotocol/src/subprotocol/protocol/proto.rs +++ b/examples/custom-rlpx-subprotocol/src/subprotocol/protocol/proto.rs @@ -86,7 +86,7 @@ impl CustomRlpxProtoMessage { /// Decodes a `CustomRlpxProtoMessage` from the given message buffer. pub fn decode_message(buf: &mut &[u8]) -> Option { if buf.is_empty() { - return None; + return None } let id = buf[0]; buf.advance(1); diff --git a/examples/stateful-precompile/Cargo.toml b/examples/stateful-precompile/Cargo.toml index bda2afac3..4da34d503 100644 --- a/examples/stateful-precompile/Cargo.toml +++ b/examples/stateful-precompile/Cargo.toml @@ -14,6 +14,7 @@ reth-primitives.workspace = true reth-node-ethereum = { workspace = true, features = ["test-utils"] } reth-tracing.workspace = true reth-evm.workspace = true +alloy-evm.workspace = true alloy-genesis.workspace = true alloy-primitives.workspace = true alloy-consensus.workspace = true diff --git a/examples/stateful-precompile/src/main.rs b/examples/stateful-precompile/src/main.rs index 50f369af4..6f38d9a3d 100644 --- a/examples/stateful-precompile/src/main.rs +++ b/examples/stateful-precompile/src/main.rs @@ -3,6 +3,7 @@ #![cfg_attr(not(test), warn(unused_crate_dependencies))] use alloy_consensus::Header; +use alloy_evm::{eth::EthEvmContext, EvmFactory}; use alloy_genesis::Genesis; use alloy_primitives::{Address, Bytes}; use parking_lot::RwLock; @@ -10,19 +11,22 @@ use reth::{ api::NextBlockEnvAttributes, builder::{components::ExecutorBuilder, BuilderContext, NodeBuilder}, revm::{ - handler::register::EvmHandler, - inspector_handle_register, - precompile::{Precompile, PrecompileSpecId}, - primitives::{ - CfgEnvWithHandlerCfg, EVMError, Env, HaltReason, HandlerCfg, PrecompileResult, SpecId, - StatefulPrecompileMut, TxEnv, + context::{Cfg, Context, TxEnv}, + context_interface::{ + result::{EVMError, HaltReason}, + ContextTr, }, - ContextPrecompile, ContextPrecompiles, EvmBuilder, GetInspector, + handler::{EthPrecompiles, PrecompileProvider}, + inspector::{Inspector, NoOpInspector}, + interpreter::{interpreter::EthInterpreter, InterpreterResult}, + precompile::PrecompileErrors, + specification::hardfork::SpecId, + MainBuilder, MainContext, }, tasks::TaskManager, }; use reth_chainspec::{Chain, ChainSpec}; -use reth_evm::{env::EvmEnv, Database}; +use reth_evm::{Database, EvmEnv}; use reth_node_api::{ConfigureEvm, ConfigureEvmEnv, FullNodeTypes, NodeTypes}; use reth_node_core::{args::RpcServerArgs, node_config::NodeConfig}; use reth_node_ethereum::{ @@ -35,10 +39,9 @@ use schnellru::{ByLength, LruMap}; use std::{collections::HashMap, convert::Infallible, sync::Arc}; /// Type alias for the LRU cache used within the [`PrecompileCache`]. -type PrecompileLRUCache = LruMap<(Bytes, u64), PrecompileResult>; +type PrecompileLRUCache = LruMap<(SpecId, Bytes, u64), Result>; -/// Type alias for the thread-safe `Arc>` wrapper around [`PrecompileCache`]. -type CachedPrecompileResult = Arc>; +type WrappedEthEvm = EthEvm>>>; /// A cache for precompile inputs / outputs. /// @@ -50,7 +53,44 @@ type CachedPrecompileResult = Arc>; #[derive(Debug, Default)] pub struct PrecompileCache { /// Caches for each precompile input / output. - cache: HashMap<(Address, SpecId), CachedPrecompileResult>, + cache: HashMap, +} + +/// Custom EVM factory. +#[derive(Debug, Clone, Default)] +#[non_exhaustive] +pub struct MyEvmFactory { + precompile_cache: Arc>, +} + +impl EvmFactory for MyEvmFactory { + type Evm, EthInterpreter>> = WrappedEthEvm; + type Tx = TxEnv; + type Error = EVMError; + type HaltReason = HaltReason; + type Context = EthEvmContext; + + fn create_evm(&self, db: DB, input: EvmEnv) -> Self::Evm { + let new_cache = self.precompile_cache.clone(); + + let evm = Context::mainnet() + .with_db(db) + .with_cfg(input.cfg_env) + .with_block(input.block_env) + .build_mainnet_with_inspector(NoOpInspector {}) + .with_precompiles(WrappedPrecompile::new(EthPrecompiles::default(), new_cache)); + + EthEvm::new(evm, false) + } + + fn create_evm_with_inspector, EthInterpreter>>( + &self, + db: DB, + input: EvmEnv, + inspector: I, + ) -> Self::Evm { + EthEvm::new(self.create_evm(db, input).into_inner().with_inspector(inspector), true) + } } /// Custom EVM configuration @@ -58,93 +98,85 @@ pub struct PrecompileCache { #[non_exhaustive] pub struct MyEvmConfig { inner: EthEvmConfig, - precompile_cache: Arc>, + evm_factory: MyEvmFactory, } impl MyEvmConfig { /// Creates a new instance. pub fn new(chain_spec: Arc) -> Self { - Self { inner: EthEvmConfig::new(chain_spec), precompile_cache: Default::default() } - } - - /// Sets the precompiles to the EVM handler - /// - /// This will be invoked when the EVM is created via [ConfigureEvm::evm_with_env] or - /// [ConfigureEvm::evm_with_env_and_inspector] - /// - /// This will use the default mainnet precompiles and wrap them with a cache. - pub fn set_precompiles( - handler: &mut EvmHandler, - cache: Arc>, - ) where - DB: Database, - { - // first we need the evm spec id, which determines the precompiles - let spec_id = handler.cfg.spec_id; - - let mut loaded_precompiles: ContextPrecompiles = - ContextPrecompiles::new(PrecompileSpecId::from_spec_id(spec_id)); - for (address, precompile) in loaded_precompiles.to_mut().iter_mut() { - // get or insert the cache for this address / spec - let mut cache = cache.write(); - let cache = cache - .cache - .entry((*address, spec_id)) - .or_insert(Arc::new(RwLock::new(LruMap::new(ByLength::new(1024))))); - - *precompile = Self::wrap_precompile(precompile.clone(), cache.clone()); - } - - // install the precompiles - handler.pre_execution.load_precompiles = Arc::new(move || loaded_precompiles.clone()); - } - - /// Given a [`ContextPrecompile`] and cache for a specific precompile, create a new precompile - /// that wraps the precompile with the cache. - fn wrap_precompile( - precompile: ContextPrecompile, - cache: Arc>>, - ) -> ContextPrecompile - where - DB: Database, - { - let ContextPrecompile::Ordinary(precompile) = precompile else { - // context stateful precompiles are not supported, due to lifetime issues or skill - // issues - panic!("precompile is not ordinary"); - }; - - let wrapped = WrappedPrecompile { precompile, cache: cache.clone() }; - - ContextPrecompile::Ordinary(Precompile::StatefulMut(Box::new(wrapped))) + Self { inner: EthEvmConfig::new(chain_spec), evm_factory: MyEvmFactory::default() } } } /// A custom precompile that contains the cache and precompile it wraps. #[derive(Clone)] -pub struct WrappedPrecompile { +pub struct WrappedPrecompile { /// The precompile to wrap. - precompile: Precompile, + precompile: P, /// The cache to use. - cache: Arc>>, + cache: Arc>, + /// The spec id to use. + spec: SpecId, } -impl StatefulPrecompileMut for WrappedPrecompile { - fn call_mut(&mut self, bytes: &Bytes, gas_price: u64, _env: &Env) -> PrecompileResult { +impl WrappedPrecompile

{ + /// Given a [`PrecompileProvider`] and cache for a specific precompiles, create a + /// wrapper that can be used inside Evm. + fn new(precompile: P, cache: Arc>) -> Self { + WrappedPrecompile { precompile, cache: cache.clone(), spec: SpecId::LATEST } + } +} + +impl> PrecompileProvider + for WrappedPrecompile

+{ + type Context = P::Context; + type Output = P::Output; + + fn set_spec(&mut self, spec: <::Cfg as Cfg>::Spec) { + self.precompile.set_spec(spec.clone()); + self.spec = spec.into(); + } + + fn run( + &mut self, + context: &mut Self::Context, + address: &Address, + bytes: &Bytes, + gas_limit: u64, + ) -> Result, reth::revm::precompile::PrecompileErrors> { let mut cache = self.cache.write(); - let key = (bytes.clone(), gas_price); + let key = (self.spec, bytes.clone(), gas_limit); // get the result if it exists - if let Some(result) = cache.get(&key) { - return result.clone() + if let Some(precompiles) = cache.cache.get_mut(address) { + if let Some(result) = precompiles.get(&key) { + return result.clone().map(Some) + } } // call the precompile if cache miss - let output = self.precompile.call(bytes, gas_price, _env); - cache.insert(key, output.clone()); + let output = self.precompile.run(context, address, bytes, gas_limit); + + if let Some(output) = output.clone().transpose() { + // insert the result into the cache + cache + .cache + .entry(*address) + .or_insert(PrecompileLRUCache::new(ByLength::new(1024))) + .insert(key, output); + } output } + + fn contains(&self, address: &Address) -> bool { + self.precompile.contains(address) + } + + fn warm_addresses(&self) -> Box + '_> { + self.precompile.warm_addresses() + } } impl ConfigureEvmEnv for MyEvmConfig { @@ -172,56 +204,10 @@ impl ConfigureEvmEnv for MyEvmConfig { } impl ConfigureEvm for MyEvmConfig { - type Evm<'a, DB: Database + 'a, I: 'a> = EthEvm<'a, I, DB>; - type EvmError = EVMError; - type HaltReason = HaltReason; + type EvmFactory = MyEvmFactory; - fn evm_with_env(&self, db: DB, evm_env: EvmEnv) -> Self::Evm<'_, DB, ()> { - let cfg_env_with_handler_cfg = CfgEnvWithHandlerCfg { - cfg_env: evm_env.cfg_env, - handler_cfg: HandlerCfg::new(evm_env.spec), - }; - - let new_cache = self.precompile_cache.clone(); - EvmBuilder::default() - .with_db(db) - .with_cfg_env_with_handler_cfg(cfg_env_with_handler_cfg) - .with_block_env(evm_env.block_env) - // add additional precompiles - .append_handler_register_box(Box::new(move |handler| { - MyEvmConfig::set_precompiles(handler, new_cache.clone()) - })) - .build() - .into() - } - - fn evm_with_env_and_inspector( - &self, - db: DB, - evm_env: EvmEnv, - inspector: I, - ) -> Self::Evm<'_, DB, I> - where - DB: Database, - I: GetInspector, - { - let cfg_env_with_handler_cfg = CfgEnvWithHandlerCfg { - cfg_env: evm_env.cfg_env, - handler_cfg: HandlerCfg::new(evm_env.spec), - }; - let new_cache = self.precompile_cache.clone(); - EvmBuilder::default() - .with_db(db) - .with_external_context(inspector) - .with_cfg_env_with_handler_cfg(cfg_env_with_handler_cfg) - .with_block_env(evm_env.block_env) - // add additional precompiles - .append_handler_register_box(Box::new(move |handler| { - MyEvmConfig::set_precompiles(handler, new_cache.clone()) - })) - .append_handler_register(inspector_handle_register) - .build() - .into() + fn evm_factory(&self) -> &Self::EvmFactory { + &self.evm_factory } } @@ -246,7 +232,7 @@ where ) -> eyre::Result<(Self::EVM, Self::Executor)> { let evm_config = MyEvmConfig { inner: EthEvmConfig::new(ctx.chain_spec()), - precompile_cache: self.precompile_cache.clone(), + evm_factory: MyEvmFactory { precompile_cache: self.precompile_cache.clone() }, }; Ok(( evm_config.clone(),