mirror of
https://github.com/hl-archive-node/nanoreth.git
synced 2025-12-06 02:49:55 +00:00
feat: alloy-evm and new revm integration (#14021)
Co-authored-by: Matthias Seitz <matthias.seitz@outlook.de> Co-authored-by: rakita <rakita@users.noreply.github.com>
This commit is contained in:
301
Cargo.lock
generated
301
Cargo.lock
generated
@ -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",
|
||||
|
||||
39
Cargo.toml
39
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" }
|
||||
|
||||
@ -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,
|
||||
|
||||
@ -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" }
|
||||
|
||||
@ -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",
|
||||
]
|
||||
|
||||
@ -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()
|
||||
}
|
||||
}
|
||||
|
||||
@ -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
|
||||
|
||||
@ -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,
|
||||
|
||||
@ -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;
|
||||
|
||||
@ -50,4 +50,5 @@ op = [
|
||||
"dep:op-alloy-rpc-types-engine",
|
||||
"dep:reth-optimism-chainspec",
|
||||
"reth-payload-primitives/op",
|
||||
"reth-evm/op",
|
||||
]
|
||||
|
||||
@ -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
|
||||
|
||||
@ -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
|
||||
|
||||
@ -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)]
|
||||
|
||||
@ -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() {
|
||||
|
||||
@ -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;
|
||||
|
||||
|
||||
@ -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",
|
||||
]
|
||||
|
||||
@ -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",
|
||||
]
|
||||
|
||||
@ -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
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@ -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};
|
||||
|
||||
|
||||
@ -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<EXT, DB: Database> Evm for EthEvm<'_, EXT, DB> {
|
||||
type DB = DB;
|
||||
type Tx = TxEnv;
|
||||
type Error = EVMError<DB::Error>;
|
||||
type HaltReason = HaltReason;
|
||||
|
||||
fn block(&self) -> &BlockEnv {
|
||||
self.0.block()
|
||||
}
|
||||
|
||||
fn transact(&mut self, tx: Self::Tx) -> Result<ResultAndState, Self::Error> {
|
||||
*self.tx_mut() = tx;
|
||||
self.0.transact()
|
||||
}
|
||||
|
||||
fn transact_system_call(
|
||||
&mut self,
|
||||
caller: Address,
|
||||
contract: Address,
|
||||
data: Bytes,
|
||||
) -> Result<ResultAndState, Self::Error> {
|
||||
#[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<ChainSpec>,
|
||||
evm_factory: EthEvmFactory,
|
||||
}
|
||||
|
||||
impl EthEvmConfig {
|
||||
/// Creates a new Ethereum EVM configuration with the given chain spec.
|
||||
pub const fn new(chain_spec: Arc<ChainSpec>) -> Self {
|
||||
Self { chain_spec }
|
||||
pub fn new(chain_spec: Arc<ChainSpec>) -> 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<EvmEnv, Self::Error> {
|
||||
// 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<DBError: core::error::Error + Send + Sync + 'static> = EVMError<DBError>;
|
||||
type HaltReason = HaltReason;
|
||||
type EvmFactory = EthEvmFactory;
|
||||
|
||||
fn evm_with_env<DB: Database>(&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<DB, I>(
|
||||
&self,
|
||||
db: DB,
|
||||
evm_env: EvmEnv,
|
||||
inspector: I,
|
||||
) -> Self::Evm<'_, DB, I>
|
||||
where
|
||||
DB: Database,
|
||||
I: revm::GetInspector<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_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::<EmptyDBTyped<ProviderError>>::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::<EmptyDBTyped<ProviderError>>::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::<EmptyDBTyped<ProviderError>>::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::<EmptyDBTyped<ProviderError>>::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());
|
||||
}
|
||||
}
|
||||
|
||||
@ -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.
|
||||
|
||||
@ -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 {
|
||||
|
||||
@ -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::<u64>();
|
||||
let base_fee = evm_env.block_env.basefee.to::<u64>();
|
||||
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::<u64>();
|
||||
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());
|
||||
|
||||
|
||||
@ -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",
|
||||
]
|
||||
|
||||
@ -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<TxEnv> 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,
|
||||
},
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -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",
|
||||
]
|
||||
|
||||
@ -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",
|
||||
]
|
||||
|
||||
@ -149,6 +149,8 @@ impl From<ProviderError> 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 {
|
||||
|
||||
@ -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",
|
||||
]
|
||||
|
||||
@ -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() {
|
||||
|
||||
@ -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)]
|
||||
|
||||
@ -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)]
|
||||
|
||||
@ -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<Header = N::BlockHeader, Transaction = N::SignedTx>,
|
||||
{
|
||||
}
|
||||
|
||||
/// Helper to access [`EvmFactory::Error`] for a given [`ConfigureEvm`].
|
||||
pub type EvmErrorFor<Evm, DB> = <<Evm as ConfigureEvm>::EvmFactory as EvmFactory<
|
||||
EvmEnv<<Evm as ConfigureEvmEnv>::Spec>,
|
||||
>>::Error<DB>;
|
||||
|
||||
/// Helper to access [`EvmFactory::HaltReason`] for a given [`ConfigureEvm`].
|
||||
pub type HaltReasonFor<Evm> = <<Evm as ConfigureEvm>::EvmFactory as EvmFactory<
|
||||
EvmEnv<<Evm as ConfigureEvmEnv>::Spec>,
|
||||
>>::HaltReason;
|
||||
|
||||
/// Helper to access [`ConfigureEvmEnv::Spec`] for a given [`ConfigureEvmEnv`].
|
||||
pub type SpecFor<Evm> = <Evm as ConfigureEvmEnv>::Spec;
|
||||
|
||||
@ -82,7 +82,7 @@ where
|
||||
state: F,
|
||||
) -> Result<BlockExecutionOutput<<Self::Primitives as NodePrimitives>::Receipt>, Self::Error>
|
||||
where
|
||||
F: FnMut(&revm::db::State<DB>),
|
||||
F: FnMut(&revm_database::State<DB>),
|
||||
{
|
||||
match self {
|
||||
Self::Left(a) => a.execute_with_state_closure(block, state),
|
||||
@ -90,7 +90,7 @@ where
|
||||
}
|
||||
}
|
||||
|
||||
fn into_state(self) -> revm::db::State<DB> {
|
||||
fn into_state(self) -> revm_database::State<DB> {
|
||||
match self {
|
||||
Self::Left(a) => a.into_state(),
|
||||
Self::Right(b) => b.into_state(),
|
||||
|
||||
@ -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<Spec = SpecId> {
|
||||
/// 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<Spec> EvmEnv<Spec> {
|
||||
/// 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 }
|
||||
}
|
||||
}
|
||||
@ -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<DBError> EvmError for EVMError<DBError>
|
||||
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,
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -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)]
|
||||
|
||||
@ -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<ResultAndState, Self::Error>;
|
||||
|
||||
/// Executes a system call.
|
||||
fn transact_system_call(
|
||||
&mut self,
|
||||
caller: Address,
|
||||
contract: Address,
|
||||
data: Bytes,
|
||||
) -> Result<ResultAndState, Self::Error>;
|
||||
|
||||
/// 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<ResultAndState, Self::Error>
|
||||
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<DB: Database, Evm: ConfigureEvm>:
|
||||
Inspector<<Evm::EvmFactory as EvmFactory<EvmEnv<Evm::Spec>>>::Context<DB>>
|
||||
{
|
||||
}
|
||||
impl<T, DB, Evm> InspectorFor<DB, Evm> for T
|
||||
where
|
||||
DB: Database,
|
||||
Evm: ConfigureEvm,
|
||||
T: Inspector<<Evm::EvmFactory as EvmFactory<EvmEnv<Evm::Spec>>>::Context<DB>>,
|
||||
{
|
||||
}
|
||||
/// Helper trait to bound [`revm::Database::Error`] with common requirements.
|
||||
pub trait Database: revm::Database<Error: core::error::Error + Send + Sync + 'static> {}
|
||||
impl<T> Database for T where T: revm::Database<Error: core::error::Error + Send + Sync + 'static> {}
|
||||
|
||||
/// 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<DB::Error>,
|
||||
HaltReason = Self::HaltReason,
|
||||
>;
|
||||
/// The EVM factory.
|
||||
type EvmFactory: EvmFactory<EvmEnv<Self::Spec>, Tx = Self::TxEnv>;
|
||||
|
||||
/// The error type returned by the EVM. See [`Evm::Error`].
|
||||
type EvmError<DBError: core::error::Error + Send + Sync + 'static>: 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::Spec>,
|
||||
) -> Self::Evm<'_, DB, ()>;
|
||||
) -> <Self::EvmFactory as EvmFactory<EvmEnv<Self::Spec>>>::Evm<DB, NoOpInspector> {
|
||||
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<DB: Database>(&self, db: DB, header: &Self::Header) -> Self::Evm<'_, DB, ()> {
|
||||
fn evm_for_block<DB: Database>(
|
||||
&self,
|
||||
db: DB,
|
||||
header: &Self::Header,
|
||||
) -> <Self::EvmFactory as EvmFactory<EvmEnv<Self::Spec>>>::Evm<DB, NoOpInspector> {
|
||||
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<Self::Spec>,
|
||||
inspector: I,
|
||||
) -> Self::Evm<'_, DB, I>
|
||||
) -> <Self::EvmFactory as EvmFactory<EvmEnv<Self::Spec>>>::Evm<DB, I>
|
||||
where
|
||||
DB: Database,
|
||||
I: GetInspector<DB>;
|
||||
I: InspectorFor<DB, Self>,
|
||||
{
|
||||
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<Header = T::Header, TxEnv = T::TxEnv, Spec = T::Spec>,
|
||||
{
|
||||
type Evm<'a, DB: Database + 'a, I: 'a> = T::Evm<'a, DB, I>;
|
||||
type EvmError<DBError: core::error::Error + Send + Sync + 'static> = T::EvmError<DBError>;
|
||||
type HaltReason = T::HaltReason;
|
||||
type EvmFactory = T::EvmFactory;
|
||||
|
||||
fn evm_for_block<DB: Database>(&self, db: DB, header: &Self::Header) -> Self::Evm<'_, DB, ()> {
|
||||
fn evm_factory(&self) -> &Self::EvmFactory {
|
||||
(*self).evm_factory()
|
||||
}
|
||||
|
||||
fn evm_for_block<DB: Database>(
|
||||
&self,
|
||||
db: DB,
|
||||
header: &Self::Header,
|
||||
) -> <Self::EvmFactory as EvmFactory<EvmEnv<Self::Spec>>>::Evm<DB, NoOpInspector> {
|
||||
(*self).evm_for_block(db, header)
|
||||
}
|
||||
|
||||
@ -167,7 +139,7 @@ where
|
||||
&self,
|
||||
db: DB,
|
||||
evm_env: EvmEnv<Self::Spec>,
|
||||
) -> Self::Evm<'_, DB, ()> {
|
||||
) -> <Self::EvmFactory as EvmFactory<EvmEnv<Self::Spec>>>::Evm<DB, NoOpInspector> {
|
||||
(*self).evm_with_env(db, evm_env)
|
||||
}
|
||||
|
||||
@ -176,10 +148,10 @@ where
|
||||
db: DB,
|
||||
evm_env: EvmEnv<Self::Spec>,
|
||||
inspector: I,
|
||||
) -> Self::Evm<'_, DB, I>
|
||||
) -> <Self::EvmFactory as EvmFactory<EvmEnv<Self::Spec>>>::Evm<DB, I>
|
||||
where
|
||||
DB: Database,
|
||||
I: GetInspector<DB>,
|
||||
I: InspectorFor<DB, Self>,
|
||||
{
|
||||
(*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<revm_primitives::SpecId> + 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<revm_primitives::TxEnv> + 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<u64>;
|
||||
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<u64> {
|
||||
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<T: TransactionEnv> TransactionEnv for revm_optimism::OpTransaction<T> {
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
||||
@ -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<DB> {
|
||||
fn into_state(self) -> revm_database::State<DB> {
|
||||
State::builder().with_database(Default::default()).build()
|
||||
}
|
||||
|
||||
|
||||
@ -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<DB: Database, P: NodePrimitives> Executor<DB> for NoopBlockExecutorProvider
|
||||
Err(BlockExecutionError::msg(UNAVAILABLE_FOR_NOOP))
|
||||
}
|
||||
|
||||
fn into_state(self) -> revm::db::State<DB> {
|
||||
fn into_state(self) -> revm_database::State<DB> {
|
||||
unreachable!()
|
||||
}
|
||||
|
||||
|
||||
@ -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<Halt>(
|
||||
chain_spec: impl EthereumHardforks,
|
||||
block_timestamp: u64,
|
||||
block_number: u64,
|
||||
parent_block_hash: B256,
|
||||
evm: &mut impl Evm<Error: Display>,
|
||||
) -> Result<Option<ResultAndState>, BlockExecutionError> {
|
||||
evm: &mut impl Evm<HaltReason = Halt>,
|
||||
) -> Result<Option<ResultAndState<Halt>>, 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))
|
||||
}
|
||||
|
||||
@ -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<Halt>(
|
||||
chain_spec: impl EthereumHardforks,
|
||||
block_timestamp: u64,
|
||||
block_number: u64,
|
||||
parent_beacon_block_root: Option<B256>,
|
||||
evm: &mut impl Evm<Error: Display>,
|
||||
) -> Result<Option<ResultAndState>, BlockExecutionError> {
|
||||
evm: &mut impl Evm<Error: Display, HaltReason = Halt>,
|
||||
) -> Result<Option<ResultAndState<Halt>>, 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))
|
||||
}
|
||||
|
||||
@ -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<Error: Display>,
|
||||
) -> Result<ResultAndState, BlockExecutionError> {
|
||||
pub(crate) fn transact_withdrawal_requests_contract_call<Halt>(
|
||||
evm: &mut impl Evm<Error: Display, HaltReason = Halt>,
|
||||
) -> Result<ResultAndState<Halt>, 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<Bytes, BlockExecutionError> {
|
||||
pub(crate) fn post_commit<Halt: Debug>(
|
||||
result: ExecutionResult<Halt>,
|
||||
) -> Result<Bytes, BlockExecutionError> {
|
||||
match result {
|
||||
ExecutionResult::Success { output, .. } => Ok(output.into_data()),
|
||||
ExecutionResult::Revert { output, .. } => {
|
||||
|
||||
@ -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<Error: Display>,
|
||||
) -> Result<ResultAndState, BlockExecutionError> {
|
||||
pub(crate) fn transact_consolidation_requests_contract_call<Halt>(
|
||||
evm: &mut impl Evm<Error: Display, HaltReason = Halt>,
|
||||
) -> Result<ResultAndState<Halt>, 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<Bytes, BlockExecutionError> {
|
||||
pub(crate) fn post_commit<Halt: Debug>(
|
||||
result: ExecutionResult<Halt>,
|
||||
) -> Result<Bytes, BlockExecutionError> {
|
||||
match result {
|
||||
ExecutionResult::Success { output, .. } => Ok(output.into_data()),
|
||||
ExecutionResult::Revert { output, .. } => {
|
||||
|
||||
@ -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<DB: DatabaseCommit, Error: Display>,
|
||||
evm: &mut impl Evm<DB: DatabaseCommit>,
|
||||
) -> Result<Bytes, BlockExecutionError> {
|
||||
let result_and_state = eip7002::transact_withdrawal_requests_contract_call(evm)?;
|
||||
|
||||
|
||||
@ -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<DB: Database> Executor<DB> for MockExecutorProvider {
|
||||
_f: F,
|
||||
) -> Result<BlockExecutionOutput<<Self::Primitives as NodePrimitives>::Receipt>, Self::Error>
|
||||
where
|
||||
F: FnMut(&revm::db::State<DB>),
|
||||
F: FnMut(&revm_database::State<DB>),
|
||||
{
|
||||
<Self as Executor<DB>>::execute(self, block)
|
||||
}
|
||||
@ -116,7 +116,7 @@ impl<DB: Database> Executor<DB> for MockExecutorProvider {
|
||||
<Self as Executor<DB>>::execute(self, block)
|
||||
}
|
||||
|
||||
fn into_state(self) -> revm::db::State<DB> {
|
||||
fn into_state(self) -> revm_database::State<DB> {
|
||||
unreachable!()
|
||||
}
|
||||
|
||||
|
||||
@ -75,6 +75,7 @@ tempfile.workspace = true
|
||||
optimism = [
|
||||
"reth-db?/optimism",
|
||||
"reth-db-api?/optimism",
|
||||
"reth-provider/optimism",
|
||||
]
|
||||
|
||||
test-utils = [
|
||||
|
||||
@ -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 = [
|
||||
|
||||
@ -81,7 +81,7 @@ std = [
|
||||
]
|
||||
optimism = [
|
||||
"reth-optimism-primitives/optimism",
|
||||
"revm/optimism",
|
||||
"reth-execution-types/optimism",
|
||||
"reth-optimism-node/optimism",
|
||||
"reth-provider/optimism",
|
||||
]
|
||||
|
||||
@ -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.
|
||||
|
||||
@ -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",
|
||||
]
|
||||
|
||||
@ -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
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@ -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<ChainSpec>,
|
||||
EvmConfig: ConfigureEvm = OpEvmConfig<ChainSpec>,
|
||||
> {
|
||||
/// The chainspec
|
||||
chain_spec: Arc<ChainSpec>,
|
||||
/// How to create an EVM.
|
||||
evm_config: EvmConfig,
|
||||
/// Receipt builder.
|
||||
receipt_builder: Arc<dyn OpReceiptBuilder<N::SignedTx, Receipt = N::Receipt>>,
|
||||
receipt_builder:
|
||||
Arc<dyn OpReceiptBuilder<N::SignedTx, HaltReasonFor<EvmConfig>, Receipt = N::Receipt>>,
|
||||
}
|
||||
|
||||
impl OpExecutionStrategyFactory<OpPrimitives> {
|
||||
@ -53,12 +54,18 @@ impl OpExecutionStrategyFactory<OpPrimitives> {
|
||||
}
|
||||
}
|
||||
|
||||
impl<N: NodePrimitives, ChainSpec, EvmConfig> OpExecutionStrategyFactory<N, ChainSpec, EvmConfig> {
|
||||
impl<N: NodePrimitives, ChainSpec, EvmConfig: ConfigureEvm>
|
||||
OpExecutionStrategyFactory<N, ChainSpec, EvmConfig>
|
||||
{
|
||||
/// Creates a new executor strategy factory.
|
||||
pub fn new(
|
||||
chain_spec: Arc<ChainSpec>,
|
||||
evm_config: EvmConfig,
|
||||
receipt_builder: impl OpReceiptBuilder<N::SignedTx, Receipt = N::Receipt>,
|
||||
receipt_builder: impl OpReceiptBuilder<
|
||||
N::SignedTx,
|
||||
HaltReasonFor<EvmConfig>,
|
||||
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<DB, N: NodePrimitives, ChainSpec, EvmConfig>
|
||||
where
|
||||
EvmConfig: Clone,
|
||||
EvmConfig: ConfigureEvm,
|
||||
{
|
||||
/// The chainspec
|
||||
chain_spec: Arc<ChainSpec>,
|
||||
@ -104,21 +111,24 @@ where
|
||||
/// Utility to call system smart contracts.
|
||||
system_caller: SystemCaller<EvmConfig, ChainSpec>,
|
||||
/// Receipt builder.
|
||||
receipt_builder: Arc<dyn OpReceiptBuilder<N::SignedTx, Receipt = N::Receipt>>,
|
||||
receipt_builder:
|
||||
Arc<dyn OpReceiptBuilder<N::SignedTx, HaltReasonFor<EvmConfig>, Receipt = N::Receipt>>,
|
||||
}
|
||||
|
||||
impl<DB, N, ChainSpec, EvmConfig> OpExecutionStrategy<DB, N, ChainSpec, EvmConfig>
|
||||
where
|
||||
N: NodePrimitives,
|
||||
ChainSpec: OpHardforks,
|
||||
EvmConfig: Clone,
|
||||
EvmConfig: ConfigureEvm,
|
||||
{
|
||||
/// Creates a new [`OpExecutionStrategy`]
|
||||
pub fn new(
|
||||
state: State<DB>,
|
||||
chain_spec: Arc<ChainSpec>,
|
||||
evm_config: EvmConfig,
|
||||
receipt_builder: Arc<dyn OpReceiptBuilder<N::SignedTx, Receipt = N::Receipt>>,
|
||||
receipt_builder: Arc<
|
||||
dyn OpReceiptBuilder<N::SignedTx, HaltReasonFor<EvmConfig>, 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<Self::DB> {
|
||||
fn into_state(self) -> revm_database::State<Self::DB> {
|
||||
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 {
|
||||
|
||||
@ -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<U256, BlockExecutionError> {
|
||||
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<DB>(
|
||||
chain_spec: impl OpHardforks,
|
||||
timestamp: u64,
|
||||
db: &mut revm::State<DB>,
|
||||
db: &mut revm_database::State<DB>,
|
||||
) -> 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.
|
||||
|
||||
@ -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<EXT, DB: Database> Evm for OpEvm<'_, EXT, DB> {
|
||||
type DB = DB;
|
||||
type Tx = TxEnv;
|
||||
type Error = EVMError<DB::Error>;
|
||||
type HaltReason = HaltReason;
|
||||
|
||||
fn block(&self) -> &BlockEnv {
|
||||
self.0.block()
|
||||
}
|
||||
|
||||
fn transact(&mut self, tx: Self::Tx) -> Result<ResultAndState, Self::Error> {
|
||||
*self.tx_mut() = tx;
|
||||
self.0.transact()
|
||||
}
|
||||
|
||||
fn transact_system_call(
|
||||
&mut self,
|
||||
caller: Address,
|
||||
contract: Address,
|
||||
data: Bytes,
|
||||
) -> Result<ResultAndState, Self::Error> {
|
||||
#[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<ChainSpec = OpChainSpec> {
|
||||
chain_spec: Arc<ChainSpec>,
|
||||
evm_factory: OpEvmFactory,
|
||||
}
|
||||
|
||||
impl<ChainSpec> Clone for OpEvmConfig<ChainSpec> {
|
||||
fn clone(&self) -> Self {
|
||||
Self { chain_spec: self.chain_spec.clone() }
|
||||
Self { chain_spec: self.chain_spec.clone(), evm_factory: OpEvmFactory::default() }
|
||||
}
|
||||
}
|
||||
|
||||
impl<ChainSpec> OpEvmConfig<ChainSpec> {
|
||||
/// Creates a new [`OpEvmConfig`] with the given chain spec.
|
||||
pub const fn new(chain_spec: Arc<ChainSpec>) -> Self {
|
||||
Self { chain_spec }
|
||||
pub fn new(chain_spec: Arc<ChainSpec>) -> Self {
|
||||
Self { chain_spec, evm_factory: OpEvmFactory::default() }
|
||||
}
|
||||
|
||||
/// Returns the chain spec associated with this configuration.
|
||||
@ -155,130 +73,87 @@ impl<ChainSpec: EthChainSpec + OpHardforks + 'static> ConfigureEvmEnv for OpEvmC
|
||||
type Header = Header;
|
||||
type Transaction = OpTransactionSigned;
|
||||
type Error = EIP1559ParamError;
|
||||
type TxEnv = TxEnv;
|
||||
type Spec = SpecId;
|
||||
type TxEnv = OpTransaction<TxEnv>;
|
||||
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<Self::Spec> {
|
||||
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<EvmEnv, Self::Error> {
|
||||
// configure evm env based on parent block
|
||||
let cfg = CfgEnv::default().with_chain_id(self.chain_spec.chain().id());
|
||||
|
||||
) -> Result<EvmEnv<Self::Spec>, 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<ChainSpec: EthChainSpec + OpHardforks + 'static> ConfigureEvm for OpEvmConfig<ChainSpec> {
|
||||
type Evm<'a, DB: Database + 'a, I: 'a> = OpEvm<'a, I, DB>;
|
||||
type EvmError<DBError: core::error::Error + Send + Sync + 'static> = EVMError<DBError>;
|
||||
type HaltReason = HaltReason;
|
||||
type EvmFactory = OpEvmFactory;
|
||||
|
||||
fn evm_with_env<DB: Database>(&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<DB, I>(
|
||||
&self,
|
||||
db: DB,
|
||||
evm_env: EvmEnv,
|
||||
inspector: I,
|
||||
) -> Self::Evm<'_, DB, I>
|
||||
where
|
||||
DB: Database,
|
||||
I: GetInspector<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_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::<EmptyDBTyped<ProviderError>>::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::<EmptyDBTyped<ProviderError>>::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::<EmptyDBTyped<ProviderError>>::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::<EmptyDBTyped<ProviderError>>::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::<EmptyDBTyped<ProviderError>>::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::<EmptyDBTyped<ProviderError>>::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]
|
||||
|
||||
@ -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<Halt>,
|
||||
/// Cumulative gas used.
|
||||
pub cumulative_gas_used: u64,
|
||||
}
|
||||
|
||||
/// Type that knows how to build a receipt based on execution result.
|
||||
pub trait OpReceiptBuilder<T>: fmt::Debug + Send + Sync + Unpin + 'static {
|
||||
pub trait OpReceiptBuilder<T, Halt>: fmt::Debug + Send + Sync + Unpin + 'static {
|
||||
/// Receipt type.
|
||||
type Receipt: Send + Sync + Clone + Unpin + 'static;
|
||||
|
||||
@ -26,8 +26,8 @@ pub trait OpReceiptBuilder<T>: 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<Self::Receipt, ReceiptBuilderCtx<'a, T>>;
|
||||
ctx: ReceiptBuilderCtx<'a, T, Halt>,
|
||||
) -> Result<Self::Receipt, ReceiptBuilderCtx<'a, T, Halt>>;
|
||||
|
||||
/// Builds receipt for a deposit transaction.
|
||||
fn build_deposit_receipt(&self, inner: OpDepositReceipt) -> Self::Receipt;
|
||||
@ -38,13 +38,13 @@ pub trait OpReceiptBuilder<T>: fmt::Debug + Send + Sync + Unpin + 'static {
|
||||
#[non_exhaustive]
|
||||
pub struct BasicOpReceiptBuilder;
|
||||
|
||||
impl OpReceiptBuilder<OpTransactionSigned> for BasicOpReceiptBuilder {
|
||||
impl<Halt> OpReceiptBuilder<OpTransactionSigned, Halt> for BasicOpReceiptBuilder {
|
||||
type Receipt = OpReceipt;
|
||||
|
||||
fn build_receipt<'a>(
|
||||
&self,
|
||||
ctx: ReceiptBuilderCtx<'a, OpTransactionSigned>,
|
||||
) -> Result<Self::Receipt, ReceiptBuilderCtx<'a, OpTransactionSigned>> {
|
||||
ctx: ReceiptBuilderCtx<'a, OpTransactionSigned, Halt>,
|
||||
) -> Result<Self::Receipt, ReceiptBuilderCtx<'a, OpTransactionSigned, Halt>> {
|
||||
match ctx.tx.tx_type() {
|
||||
OpTxType::Deposit => Err(ctx),
|
||||
ty => {
|
||||
|
||||
@ -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",
|
||||
|
||||
@ -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<TxEnv = TxEnv>,
|
||||
Evm: ConfigureEvmEnv<TxEnv = revm_optimism::OpTransaction<TxEnv>>,
|
||||
>,
|
||||
OpEthApiError: FromEvmError<N::Evm>,
|
||||
<<N as FullNodeComponents>::Pool as TransactionPool>::Transaction: MaybeConditionalTransaction,
|
||||
@ -318,7 +318,7 @@ where
|
||||
Storage = OpStorage,
|
||||
Engine = OpEngineTypes,
|
||||
>,
|
||||
Evm: ConfigureEvm<TxEnv = TxEnv>,
|
||||
Evm: ConfigureEvm<TxEnv = revm_optimism::OpTransaction<TxEnv>>,
|
||||
>,
|
||||
OpEthApiError: FromEvmError<N::Evm>,
|
||||
<<N as FullNodeComponents>::Pool as TransactionPool>::Transaction: MaybeConditionalTransaction,
|
||||
|
||||
@ -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",
|
||||
|
||||
@ -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<Pool, Client, EvmConfig, N: NodePrimitives, Txs = ()> {
|
||||
pub struct OpPayloadBuilder<Pool, Client, EvmConfig: ConfigureEvm, N: NodePrimitives, Txs = ()> {
|
||||
/// 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<Pool, Client, EvmConfig, N: NodePrimitives, Txs = ()
|
||||
/// transactions are allowed.
|
||||
pub best_transactions: Txs,
|
||||
/// Node primitive types.
|
||||
pub receipt_builder: Arc<dyn OpReceiptBuilder<N::SignedTx, Receipt = N::Receipt>>,
|
||||
pub receipt_builder:
|
||||
Arc<dyn OpReceiptBuilder<N::SignedTx, HaltReasonFor<EvmConfig>, Receipt = N::Receipt>>,
|
||||
}
|
||||
|
||||
impl<Pool, Client, EvmConfig, N: NodePrimitives> OpPayloadBuilder<Pool, Client, EvmConfig, N> {
|
||||
impl<Pool, Client, EvmConfig, N> OpPayloadBuilder<Pool, Client, EvmConfig, N>
|
||||
where
|
||||
EvmConfig: ConfigureEvm,
|
||||
N: NodePrimitives,
|
||||
{
|
||||
/// `OpPayloadBuilder` constructor.
|
||||
///
|
||||
/// Configures the builder with the default settings.
|
||||
@ -84,7 +94,11 @@ impl<Pool, Client, EvmConfig, N: NodePrimitives> OpPayloadBuilder<Pool, Client,
|
||||
pool: Pool,
|
||||
client: Client,
|
||||
evm_config: EvmConfig,
|
||||
receipt_builder: impl OpReceiptBuilder<N::SignedTx, Receipt = N::Receipt>,
|
||||
receipt_builder: impl OpReceiptBuilder<
|
||||
N::SignedTx,
|
||||
HaltReasonFor<EvmConfig>,
|
||||
Receipt = N::Receipt,
|
||||
>,
|
||||
) -> Self {
|
||||
Self::with_builder_config(pool, client, evm_config, receipt_builder, Default::default())
|
||||
}
|
||||
@ -94,7 +108,11 @@ impl<Pool, Client, EvmConfig, N: NodePrimitives> OpPayloadBuilder<Pool, Client,
|
||||
pool: Pool,
|
||||
client: Client,
|
||||
evm_config: EvmConfig,
|
||||
receipt_builder: impl OpReceiptBuilder<N::SignedTx, Receipt = N::Receipt>,
|
||||
receipt_builder: impl OpReceiptBuilder<
|
||||
N::SignedTx,
|
||||
HaltReasonFor<EvmConfig>,
|
||||
Receipt = N::Receipt,
|
||||
>,
|
||||
config: OpBuilderConfig,
|
||||
) -> Self {
|
||||
Self {
|
||||
@ -109,7 +127,7 @@ impl<Pool, Client, EvmConfig, N: NodePrimitives> OpPayloadBuilder<Pool, Client,
|
||||
}
|
||||
}
|
||||
|
||||
impl<Pool, Client, EvmConfig, N: NodePrimitives, Txs>
|
||||
impl<Pool, Client, EvmConfig: ConfigureEvm, N: NodePrimitives, Txs>
|
||||
OpPayloadBuilder<Pool, Client, EvmConfig, N, Txs>
|
||||
{
|
||||
/// Sets the rollup's compute pending block configuration option.
|
||||
@ -469,7 +487,7 @@ impl<Txs> 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<N: NodePrimitives> ExecutionInfo<N> {
|
||||
|
||||
/// Container type that holds all necessities to build a new payload.
|
||||
#[derive(Debug)]
|
||||
pub struct OpPayloadBuilderCtx<EvmConfig: ConfigureEvmEnv, ChainSpec, N: NodePrimitives> {
|
||||
pub struct OpPayloadBuilderCtx<EvmConfig: ConfigureEvm, ChainSpec, N: NodePrimitives> {
|
||||
/// 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<EvmConfig: ConfigureEvmEnv, ChainSpec, N: NodePri
|
||||
/// The currently best payload.
|
||||
pub best_payload: Option<OpBuiltPayload<N>>,
|
||||
/// Receipt builder.
|
||||
pub receipt_builder: Arc<dyn OpReceiptBuilder<N::SignedTx, Receipt = N::Receipt>>,
|
||||
pub receipt_builder:
|
||||
Arc<dyn OpReceiptBuilder<N::SignedTx, HaltReasonFor<EvmConfig>, Receipt = N::Receipt>>,
|
||||
}
|
||||
|
||||
impl<EvmConfig, ChainSpec, N> OpPayloadBuilderCtx<EvmConfig, ChainSpec, N>
|
||||
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<u64> {
|
||||
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<N>,
|
||||
result: ExecutionResult,
|
||||
result: ExecutionResult<HaltReasonFor<EvmConfig>>,
|
||||
deposit_nonce: Option<u64>,
|
||||
tx: &N::SignedTx,
|
||||
) -> N::Receipt {
|
||||
|
||||
@ -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 = []
|
||||
|
||||
@ -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<revm_optimism::OpTransaction<TxEnv>> for OpTransactionSigned {
|
||||
fn fill_tx_env(&self, tx_env: &mut revm_optimism::OpTransaction<TxEnv>, 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()
|
||||
},
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -89,4 +89,5 @@ optimism = [
|
||||
"reth-optimism-node?/optimism",
|
||||
"reth-optimism-primitives/optimism",
|
||||
"reth-optimism-rpc?/optimism",
|
||||
"reth-provider?/optimism",
|
||||
]
|
||||
|
||||
@ -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",
|
||||
|
||||
@ -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<OpInvalidTransactionError> for jsonrpsee_types::error::ErrorObject<'st
|
||||
}
|
||||
}
|
||||
|
||||
impl TryFrom<InvalidTransaction> for OpInvalidTransactionError {
|
||||
impl TryFrom<OpTransactionError> for OpInvalidTransactionError {
|
||||
type Error = InvalidTransaction;
|
||||
|
||||
fn try_from(err: InvalidTransaction) -> Result<Self, Self::Error> {
|
||||
fn try_from(err: OpTransactionError) -> Result<Self, Self::Error> {
|
||||
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<BlockError> for OpEthApiError {
|
||||
}
|
||||
}
|
||||
|
||||
impl<DB> From<EVMError<DB>> for OpEthApiError
|
||||
impl<T> From<EVMError<T, OpTransactionError>> for OpEthApiError
|
||||
where
|
||||
EthApiError: From<EVMError<DB>>,
|
||||
T: Into<EthApiError>,
|
||||
{
|
||||
fn from(error: EVMError<DB>) -> Self {
|
||||
Self::Eth(error.into())
|
||||
fn from(error: EVMError<T, OpTransactionError>) -> 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<OpHaltReason> 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(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -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,
|
||||
|
||||
@ -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<N> EthCall for OpEthApi<N>
|
||||
where
|
||||
@ -29,7 +30,10 @@ where
|
||||
impl<N> Call for OpEthApi<N>
|
||||
where
|
||||
Self: LoadState<
|
||||
Evm: ConfigureEvm<Header = ProviderHeader<Self::Provider>, TxEnv = TxEnv>,
|
||||
Evm: ConfigureEvm<
|
||||
Header = ProviderHeader<Self::Provider>,
|
||||
TxEnv = OpTransaction<TxEnv>,
|
||||
>,
|
||||
Error: FromEvmError<Self::Evm>,
|
||||
> + SpawnBlocking,
|
||||
Self::Error: From<OpEthApiError>,
|
||||
@ -47,14 +51,17 @@ where
|
||||
|
||||
fn create_txn_env(
|
||||
&self,
|
||||
block_env: &BlockEnv,
|
||||
evm_env: &EvmEnv<SpecFor<Self::Evm>>,
|
||||
request: TransactionRequest,
|
||||
) -> Result<TxEnv, Self::Error> {
|
||||
mut db: impl Database<Error: Into<EthApiError>>,
|
||||
) -> Result<OpTransaction<TxEnv>, 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:
|
||||
// <https://github.com/ledgerwatch/erigon/blob/eae2d9a79cb70dbe30b3a6b79c436872e4605458/cmd/rpcdaemon/commands/trace_adhoc.go#L956
|
||||
// https://github.com/ledgerwatch/erigon/blob/eae2d9a79cb70dbe30b3a6b79c436872e4605458/eth/ethconfig/config.go#L94>
|
||||
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() })
|
||||
}
|
||||
}
|
||||
|
||||
@ -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<N> LoadPendingBlock for OpEthApi<N>
|
||||
where
|
||||
@ -101,7 +104,7 @@ where
|
||||
receipts: &[ProviderReceipt<Self::Provider>],
|
||||
) -> reth_provider::ProviderBlock<Self::Provider> {
|
||||
let chain_spec = self.provider().chain_spec();
|
||||
let timestamp = block_env.timestamp.to::<u64>();
|
||||
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::<u64>()),
|
||||
number: block_env.number.to::<u64>(),
|
||||
gas_limit: block_env.gas_limit.to::<u64>(),
|
||||
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::<u64>()
|
||||
}),
|
||||
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<Self::Provider>,
|
||||
result: ExecutionResult,
|
||||
result: ExecutionResult<HaltReasonFor<N::Evm>>,
|
||||
cumulative_gas_used: u64,
|
||||
) -> reth_provider::ProviderReceipt<Self::Provider> {
|
||||
let receipt = alloy_consensus::Receipt {
|
||||
|
||||
@ -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<Self, OpEthApiError> {
|
||||
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<Self, OpEthApiError> {
|
||||
let timestamp = meta.timestamp;
|
||||
let block_number = meta.block_number;
|
||||
|
||||
@ -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<Pool, Provider: NodePrimitivesProvider, EvmConfig> {
|
||||
pub struct OpDebugWitnessApi<Pool, Provider: NodePrimitivesProvider, EvmConfig: ConfigureEvm> {
|
||||
inner: Arc<OpDebugWitnessApiInner<Pool, Provider, EvmConfig>>,
|
||||
}
|
||||
|
||||
impl<Pool, Provider: NodePrimitivesProvider, EvmConfig>
|
||||
impl<Pool, Provider: NodePrimitivesProvider, EvmConfig: ConfigureEvm>
|
||||
OpDebugWitnessApi<Pool, Provider, EvmConfig>
|
||||
{
|
||||
/// Creates a new instance of the `OpDebugWitnessApi`.
|
||||
@ -42,6 +42,7 @@ impl<Pool, Provider: NodePrimitivesProvider, EvmConfig>
|
||||
|
||||
impl<Pool, Provider, EvmConfig> OpDebugWitnessApi<Pool, Provider, EvmConfig>
|
||||
where
|
||||
EvmConfig: ConfigureEvm,
|
||||
Provider: NodePrimitivesProvider + BlockReaderIdExt<Header = reth_primitives::Header>,
|
||||
{
|
||||
/// Fetches the parent header by hash.
|
||||
@ -94,6 +95,7 @@ where
|
||||
|
||||
impl<Pool, Provider, EvmConfig> Clone for OpDebugWitnessApi<Pool, Provider, EvmConfig>
|
||||
where
|
||||
EvmConfig: ConfigureEvm,
|
||||
Provider: NodePrimitivesProvider,
|
||||
{
|
||||
fn clone(&self) -> Self {
|
||||
@ -102,6 +104,7 @@ where
|
||||
}
|
||||
impl<Pool, Provider, EvmConfig> Debug for OpDebugWitnessApi<Pool, Provider, EvmConfig>
|
||||
where
|
||||
EvmConfig: ConfigureEvm,
|
||||
Provider: NodePrimitivesProvider,
|
||||
{
|
||||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||
@ -109,7 +112,7 @@ where
|
||||
}
|
||||
}
|
||||
|
||||
struct OpDebugWitnessApiInner<Pool, Provider: NodePrimitivesProvider, EvmConfig> {
|
||||
struct OpDebugWitnessApiInner<Pool, Provider: NodePrimitivesProvider, EvmConfig: ConfigureEvm> {
|
||||
provider: Provider,
|
||||
builder: OpPayloadBuilder<Pool, Provider, EvmConfig, Provider::Primitives>,
|
||||
task_spawner: Box<dyn TaskSpawner>,
|
||||
|
||||
@ -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",
|
||||
]
|
||||
|
||||
@ -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,
|
||||
|
||||
@ -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,
|
||||
|
||||
@ -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",
|
||||
|
||||
@ -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::<byteorder::BigEndian>().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<Account> 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(
|
||||
|
||||
@ -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<TxEnv> {
|
||||
/// Fills `TxEnv` with an [`Address`] and transaction.
|
||||
fn fill_tx_env(&self, tx_env: &mut TxEnv, sender: Address);
|
||||
}
|
||||
|
||||
@ -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<T> FullSignedTx for T where
|
||||
T: SignedTransaction + FillTxEnv + MaybeCompact + MaybeSerdeBincodeCompat
|
||||
{
|
||||
}
|
||||
pub trait FullSignedTx: SignedTransaction + MaybeCompact + MaybeSerdeBincodeCompat {}
|
||||
impl<T> FullSignedTx for T where T: SignedTransaction + MaybeCompact + MaybeSerdeBincodeCompat {}
|
||||
|
||||
/// A signed transaction.
|
||||
#[auto_impl::auto_impl(&, Arc)]
|
||||
|
||||
@ -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",
|
||||
]
|
||||
|
||||
@ -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: DatabaseRef>(db: DB) {
|
||||
/// let mut cached_reads = CachedReads::default();
|
||||
|
||||
@ -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.
|
||||
///
|
||||
|
||||
@ -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.
|
||||
///
|
||||
|
||||
@ -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;
|
||||
|
||||
@ -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::<KeccakKeyHasher>(bundle_state.state())
|
||||
}
|
||||
}
|
||||
|
||||
@ -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)]
|
||||
|
||||
@ -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
|
||||
|
||||
@ -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::<u64>() - 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 <https://github.com/foundry-rs/foundry/issues/4388>
|
||||
@ -409,12 +413,10 @@ pub trait EthCall: EstimateCall + Call + LoadPendingBlock + LoadBlock + FullEthA
|
||||
// <https://github.com/ethereum/go-ethereum/blob/8990c92aea01ca07801597b00c0d83d4e2d9b811/internal/ethapi/api.go#L1476-L1476>
|
||||
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: <Self::Evm as ConfigureEvmEnv>::TxEnv,
|
||||
) -> Result<
|
||||
(
|
||||
ResultAndState,
|
||||
ResultAndState<HaltReasonFor<Self::Evm>>,
|
||||
(EvmEnv<<Self::Evm as ConfigureEvmEnv>::Spec>, <Self::Evm as ConfigureEvmEnv>::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<DB>(
|
||||
fn transact_with_inspector<DB, I>(
|
||||
&self,
|
||||
db: DB,
|
||||
evm_env: EvmEnv<<Self::Evm as ConfigureEvmEnv>::Spec>,
|
||||
tx_env: <Self::Evm as ConfigureEvmEnv>::TxEnv,
|
||||
inspector: impl GetInspector<DB>,
|
||||
inspector: I,
|
||||
) -> Result<
|
||||
(
|
||||
ResultAndState,
|
||||
ResultAndState<HaltReasonFor<Self::Evm>>,
|
||||
(EvmEnv<<Self::Evm as ConfigureEvmEnv>::Spec>, <Self::Evm as ConfigureEvmEnv>::TxEnv),
|
||||
),
|
||||
Self::Error,
|
||||
>
|
||||
where
|
||||
DB: Database<Error = ProviderError>,
|
||||
I: InspectorFor<DB, Self::Evm>,
|
||||
{
|
||||
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<HaltReasonFor<Self::Evm>>,
|
||||
(
|
||||
EvmEnv<<Self::Evm as ConfigureEvmEnv>::Spec>,
|
||||
<Self::Evm as ConfigureEvmEnv>::TxEnv,
|
||||
@ -643,7 +646,11 @@ pub trait Call:
|
||||
) -> impl Future<Output = Result<Option<R>, Self::Error>> + Send
|
||||
where
|
||||
Self: LoadBlock + LoadTransaction,
|
||||
F: FnOnce(TransactionInfo, ResultAndState, StateCacheDb<'_>) -> Result<R, Self::Error>
|
||||
F: FnOnce(
|
||||
TransactionInfo,
|
||||
ResultAndState<HaltReasonFor<Self::Evm>>,
|
||||
StateCacheDb<'_>,
|
||||
) -> Result<R, Self::Error>
|
||||
+ 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<SpecFor<Self::Evm>>,
|
||||
request: TransactionRequest,
|
||||
db: impl Database<Error: Into<EthApiError>>,
|
||||
) -> Result<<Self::Evm as ConfigureEvmEnv>::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 <https://github.com/paradigmxyz/reth/issues/1959>
|
||||
@ -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));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -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::<u64>();
|
||||
|
||||
// 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<DB>(
|
||||
&self,
|
||||
env_gas_limit: U256,
|
||||
env_gas_limit: u64,
|
||||
evm_env: EvmEnv<<Self::Evm as ConfigureEvmEnv>::Spec>,
|
||||
mut tx_env: <Self::Evm as ConfigureEvmEnv>::TxEnv,
|
||||
db: &mut DB,
|
||||
@ -298,7 +296,7 @@ pub trait EstimateCall: Call {
|
||||
EthApiError: From<DB::Error>,
|
||||
{
|
||||
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<Halt>(
|
||||
result: ExecutionResult<Halt>,
|
||||
tx_gas_limit: u64,
|
||||
highest_gas_limit: &mut u64,
|
||||
lowest_gas_limit: &mut u64,
|
||||
|
||||
@ -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::<u64>() == 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<Self::Provider>,
|
||||
result: ExecutionResult,
|
||||
result: ExecutionResult<HaltReasonFor<Self::Evm>>,
|
||||
cumulative_gas_used: u64,
|
||||
) -> ProviderReceipt<Self::Provider>;
|
||||
|
||||
@ -214,7 +221,7 @@ pub trait LoadPendingBlock:
|
||||
parent_hash: B256,
|
||||
state_root: B256,
|
||||
transactions: Vec<ProviderTx<Self::Provider>>,
|
||||
results: Vec<ExecutionResult>,
|
||||
results: Vec<ExecutionResult<HaltReasonFor<Self::Evm>>>,
|
||||
) -> (ProviderBlock<Self::Provider>, Vec<ProviderReceipt<Self::Provider>>) {
|
||||
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::<u64>();
|
||||
let base_fee = evm_env.block_env.basefee.to::<u64>();
|
||||
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,
|
||||
&[],
|
||||
);
|
||||
|
||||
|
||||
@ -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,
|
||||
|
||||
@ -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<HaltReasonFor<Self::Evm>>,
|
||||
(EvmEnv<<Self::Evm as ConfigureEvmEnv>::Spec>, <Self::Evm as ConfigureEvmEnv>::TxEnv),
|
||||
),
|
||||
Self::Error,
|
||||
>
|
||||
where
|
||||
DB: Database<Error = ProviderError>,
|
||||
I: GetInspector<DB>,
|
||||
I: InspectorFor<DB, Self::Evm>,
|
||||
{
|
||||
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<R, Self::Error>
|
||||
where
|
||||
Self: Call,
|
||||
F: FnOnce(TracingInspector, ResultAndState) -> Result<R, Self::Error>,
|
||||
F: FnOnce(
|
||||
TracingInspector,
|
||||
ResultAndState<HaltReasonFor<Self::Evm>>,
|
||||
) -> Result<R, Self::Error>,
|
||||
{
|
||||
self.with_state_at_block(at, |state| {
|
||||
let mut db = CacheDB::new(StateProviderDatabase::new(state));
|
||||
@ -104,7 +111,11 @@ pub trait Trace:
|
||||
) -> impl Future<Output = Result<R, Self::Error>> + Send
|
||||
where
|
||||
Self: LoadPendingBlock + Call,
|
||||
F: FnOnce(TracingInspector, ResultAndState, StateCacheDb<'_>) -> Result<R, Self::Error>
|
||||
F: FnOnce(
|
||||
TracingInspector,
|
||||
ResultAndState<HaltReasonFor<Self::Evm>>,
|
||||
StateCacheDb<'_>,
|
||||
) -> Result<R, Self::Error>
|
||||
+ Send
|
||||
+ 'static,
|
||||
R: Send + 'static,
|
||||
@ -138,7 +149,7 @@ pub trait Trace:
|
||||
F: FnOnce(
|
||||
TransactionInfo,
|
||||
TracingInspector,
|
||||
ResultAndState,
|
||||
ResultAndState<HaltReasonFor<Self::Evm>>,
|
||||
StateCacheDb<'_>,
|
||||
) -> Result<R, Self::Error>
|
||||
+ Send
|
||||
@ -168,12 +179,13 @@ pub trait Trace:
|
||||
F: FnOnce(
|
||||
TransactionInfo,
|
||||
Insp,
|
||||
ResultAndState,
|
||||
ResultAndState<HaltReasonFor<Self::Evm>>,
|
||||
StateCacheDb<'_>,
|
||||
) -> Result<R, Self::Error>
|
||||
+ Send
|
||||
+ 'static,
|
||||
Insp: for<'a, 'b> Inspector<StateCacheDbRefMutWrapper<'a, 'b>> + Send + 'static,
|
||||
Insp:
|
||||
for<'a, 'b> InspectorFor<StateCacheDbRefMutWrapper<'a, 'b>, Self::Evm> + Send + 'static,
|
||||
R: Send + 'static,
|
||||
{
|
||||
async move {
|
||||
@ -232,7 +244,7 @@ pub trait Trace:
|
||||
F: Fn(
|
||||
TransactionInfo,
|
||||
TracingInspector,
|
||||
ExecutionResult,
|
||||
ExecutionResult<HaltReasonFor<Self::Evm>>,
|
||||
&EvmState,
|
||||
&StateCacheDb<'_>,
|
||||
) -> Result<R, Self::Error>
|
||||
@ -272,14 +284,15 @@ pub trait Trace:
|
||||
F: Fn(
|
||||
TransactionInfo,
|
||||
Insp,
|
||||
ExecutionResult,
|
||||
ExecutionResult<HaltReasonFor<Self::Evm>>,
|
||||
&EvmState,
|
||||
&StateCacheDb<'_>,
|
||||
) -> Result<R, Self::Error>
|
||||
+ Send
|
||||
+ 'static,
|
||||
Setup: FnMut() -> Insp + Send + 'static,
|
||||
Insp: for<'a, 'b> Inspector<StateCacheDbRefMutWrapper<'a, 'b>> + Send + 'static,
|
||||
Insp:
|
||||
for<'a, 'b> InspectorFor<StateCacheDbRefMutWrapper<'a, 'b>, 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::<u64>();
|
||||
let base_fee = evm_env.block_env.basefee.saturating_to::<u64>();
|
||||
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<HaltReasonFor<Self::Evm>>,
|
||||
&EvmState,
|
||||
&StateCacheDb<'_>,
|
||||
) -> Result<R, Self::Error>
|
||||
@ -430,14 +443,15 @@ pub trait Trace:
|
||||
F: Fn(
|
||||
TransactionInfo,
|
||||
Insp,
|
||||
ExecutionResult,
|
||||
ExecutionResult<HaltReasonFor<Self::Evm>>,
|
||||
&EvmState,
|
||||
&StateCacheDb<'_>,
|
||||
) -> Result<R, Self::Error>
|
||||
+ Send
|
||||
+ 'static,
|
||||
Setup: FnMut() -> Insp + Send + 'static,
|
||||
Insp: for<'a, 'b> Inspector<StateCacheDbRefMutWrapper<'a, 'b>> + Send + 'static,
|
||||
Insp:
|
||||
for<'a, 'b> InspectorFor<StateCacheDbRefMutWrapper<'a, 'b>, 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<DB: Send + Database<Error: Display> + DatabaseCommit>(
|
||||
fn apply_pre_execution_changes<DB: Send + Database + DatabaseCommit>(
|
||||
&self,
|
||||
block: &RecoveredBlock<ProviderBlock<Self::Provider>>,
|
||||
db: &mut DB,
|
||||
|
||||
@ -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: <https://github.com/ethereum/go-ethereum/blob/bc0b87ca196f92e5af49bd33cc190ef0ec32b197/eth/tracers/api.go#L955-L955>
|
||||
|
||||
@ -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
|
||||
|
||||
18
crates/rpc/rpc-eth-types/src/cache/db.rs
vendored
18
crates/rpc/rpc-eth-types/src/cache/db.rs
vendored
@ -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<StateProviderDatabase<StateProviderTraitObjWrapper<'a>>>;
|
||||
@ -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<Option<revm_primitives::AccountInfo>, Self::Error> {
|
||||
) -> Result<Option<AccountInfo>, Self::Error> {
|
||||
self.0.basic(address)
|
||||
}
|
||||
|
||||
fn code_by_hash(&mut self, code_hash: B256) -> Result<revm_primitives::Bytecode, Self::Error> {
|
||||
fn code_by_hash(&mut self, code_hash: B256) -> Result<Bytecode, Self::Error> {
|
||||
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<Option<revm_primitives::AccountInfo>, Self::Error> {
|
||||
) -> Result<Option<AccountInfo>, Self::Error> {
|
||||
self.0.basic_ref(address)
|
||||
}
|
||||
|
||||
fn code_by_hash_ref(&self, code_hash: B256) -> Result<revm_primitives::Bytecode, Self::Error> {
|
||||
fn code_by_hash_ref(&self, code_hash: B256) -> Result<Bytecode, Self::Error> {
|
||||
self.0.code_by_hash_ref(code_hash)
|
||||
}
|
||||
|
||||
|
||||
@ -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<EthApiError> {
|
||||
@ -81,28 +83,28 @@ impl AsEthApiError for EthApiError {
|
||||
|
||||
/// Helper trait to convert from revm errors.
|
||||
pub trait FromEvmError<Evm: ConfigureEvm>:
|
||||
From<Evm::EvmError<ProviderError>> + FromEvmHalt
|
||||
From<EvmErrorFor<Evm, ProviderError>> + FromEvmHalt<HaltReasonFor<Evm>>
|
||||
{
|
||||
/// Converts from EVM error to this type.
|
||||
fn from_evm_err(err: Evm::EvmError<ProviderError>) -> Self {
|
||||
fn from_evm_err(err: EvmErrorFor<Evm, ProviderError>) -> Self {
|
||||
err.into()
|
||||
}
|
||||
}
|
||||
|
||||
impl<T, Evm> FromEvmError<Evm> for T
|
||||
where
|
||||
T: From<Evm::EvmError<ProviderError>> + FromEvmHalt,
|
||||
T: From<EvmErrorFor<Evm, ProviderError>> + FromEvmHalt<HaltReasonFor<Evm>>,
|
||||
Evm: ConfigureEvm,
|
||||
{
|
||||
}
|
||||
|
||||
/// Helper trait to convert from revm errors.
|
||||
pub trait FromEvmHalt<Halt = HaltReason> {
|
||||
pub trait FromEvmHalt<Halt> {
|
||||
/// Converts from EVM halt to this type.
|
||||
fn from_evm_halt(halt: Halt, gas_limit: u64) -> Self;
|
||||
}
|
||||
|
||||
impl FromEvmHalt for EthApiError {
|
||||
impl FromEvmHalt<HaltReason> for EthApiError {
|
||||
fn from_evm_halt(halt: HaltReason, gas_limit: u64) -> Self {
|
||||
RpcInvalidTransactionError::halt(halt, gas_limit).into()
|
||||
}
|
||||
|
||||
@ -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<reth_errors::ProviderError> for EthApiError {
|
||||
}
|
||||
}
|
||||
|
||||
impl<T> From<EVMError<T>> for EthApiError
|
||||
impl From<InvalidHeader> for EthApiError {
|
||||
fn from(value: InvalidHeader) -> Self {
|
||||
match value {
|
||||
InvalidHeader::ExcessBlobGasNotSet => Self::ExcessBlobGasNotSet,
|
||||
InvalidHeader::PrevrandaoNotSet => Self::PrevrandaoNotSet,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<T> From<EVMError<T, InvalidTransaction>> for EthApiError
|
||||
where
|
||||
T: Into<Self>,
|
||||
{
|
||||
fn from(err: EVMError<T>) -> Self {
|
||||
fn from(err: EVMError<T, InvalidTransaction>) -> 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<RpcInvalidTransactionError> for jsonrpsee_types::error::ErrorObject<'s
|
||||
}
|
||||
}
|
||||
|
||||
impl From<revm::primitives::InvalidTransaction> for RpcInvalidTransactionError {
|
||||
fn from(err: revm::primitives::InvalidTransaction) -> Self {
|
||||
use revm::primitives::InvalidTransaction;
|
||||
impl From<InvalidTransaction> for RpcInvalidTransactionError {
|
||||
fn from(err: InvalidTransaction) -> Self {
|
||||
match err {
|
||||
InvalidTransaction::InvalidChainId => Self::InvalidChainId,
|
||||
InvalidTransaction::PriorityFeeGreaterThanMaxFee => Self::TipAboveFeeCap,
|
||||
@ -546,7 +555,7 @@ impl From<revm::primitives::InvalidTransaction> 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<Bytes> {
|
||||
pub fn ensure_success<Halt, Error: FromEvmHalt<Halt> + FromEthApiError>(
|
||||
result: ExecutionResult<Halt>,
|
||||
) -> Result<Bytes, Error> {
|
||||
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)),
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -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<Item = Address> {
|
||||
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<Item = Address> {
|
||||
///
|
||||
/// 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>(db: &mut DB, env: &impl TransactionEnv) -> EthResult<U256>
|
||||
pub fn caller_gas_allowance<DB>(db: &mut DB, env: &impl TransactionEnv) -> EthResult<u64>
|
||||
where
|
||||
DB: Database,
|
||||
EthApiError: From<<DB as Database>::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<DB>(
|
||||
}
|
||||
|
||||
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();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -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<T, B>(
|
||||
pub fn build_simulated_block<T, B, Halt: Clone>(
|
||||
senders: Vec<Address>,
|
||||
results: Vec<ExecutionResult>,
|
||||
results: Vec<ExecutionResult<Halt>>,
|
||||
full_transactions: bool,
|
||||
tx_resp_builder: &T,
|
||||
block: B,
|
||||
) -> Result<SimulatedBlock<Block<T::Transaction, Header<B::Header>>>, T::Error>
|
||||
where
|
||||
T: TransactionCompat<BlockTx<B>, Error: FromEthApiError + FromEvmHalt>,
|
||||
T: TransactionCompat<BlockTx<B>, Error: FromEthApiError + FromEvmHalt<Halt>>,
|
||||
B: reth_primitives_traits::Block,
|
||||
{
|
||||
let mut calls: Vec<SimCallResult> = 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 {
|
||||
|
||||
@ -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<TransactionContext>,
|
||||
fused_inspector: &mut Option<TracingInspector>,
|
||||
) -> 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))
|
||||
}
|
||||
}
|
||||
|
||||
@ -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::<u64>());
|
||||
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,
|
||||
};
|
||||
|
||||
|
||||
@ -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<Provider, Pool, Network, EvmConfig> EthCall for EthApi<Provider, Pool, Network, EvmConfig>
|
||||
where
|
||||
@ -40,14 +41,17 @@ where
|
||||
|
||||
fn create_txn_env(
|
||||
&self,
|
||||
block_env: &BlockEnv,
|
||||
evm_env: &EvmEnv<SpecFor<Self::Evm>>,
|
||||
request: TransactionRequest,
|
||||
mut db: impl Database<Error: Into<EthApiError>>,
|
||||
) -> Result<TxEnv, 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,
|
||||
@ -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:
|
||||
// <https://github.com/ledgerwatch/erigon/blob/eae2d9a79cb70dbe30b3a6b79c436872e4605458/cmd/rpcdaemon/commands/trace_adhoc.go#L956
|
||||
// https://github.com/ledgerwatch/erigon/blob/eae2d9a79cb70dbe30b3a6b79c436872e4605458/eth/ethconfig/config.go#L94>
|
||||
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)
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user