diff --git a/Cargo.lock b/Cargo.lock index 5e07217..f285481 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -14,7 +14,7 @@ version = "0.5.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d122413f284cf2d62fb1b7db97e02edb8cda96d769b16e443a4f6195e35662b0" dependencies = [ - "crypto-common", + "crypto-common 0.1.7", "generic-array", ] @@ -101,14 +101,14 @@ dependencies = [ [[package]] name = "alloy-consensus" -version = "2.0.4" +version = "2.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e3d64da86c616b5092ea64eea648f311bbd58630a0b384c42d699175d6f9122b" +checksum = "a6ff0c4adba2abdcd9fb5829ae5f4394c06f8585ed283a9ba79aa33763c802e1" dependencies = [ - "alloy-eips 2.0.4", + "alloy-eips", "alloy-primitives", "alloy-rlp", - "alloy-serde 2.0.4", + "alloy-serde", "alloy-trie", "alloy-tx-macros", "arbitrary", @@ -129,24 +129,24 @@ dependencies = [ [[package]] name = "alloy-consensus-any" -version = "2.0.4" +version = "2.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8fd98696ca3617d3a9ba1a6f2011880cbfd5618228dab6400c9f8bca457859a8" +checksum = "7cdf48932b1db3216175e19a2b476d89d53076e004850ee7983c6807ba0fde74" dependencies = [ "alloy-consensus", - "alloy-eips 2.0.4", + "alloy-eips", "alloy-primitives", "alloy-rlp", - "alloy-serde 2.0.4", + "alloy-serde", "arbitrary", "serde", ] [[package]] name = "alloy-dyn-abi" -version = "1.5.7" +version = "1.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cc2db5c583aaef0255aa63a4fe827f826090142528bba48d1bf4119b62780cad" +checksum = "a475bb02d9cef2dbb99065c1664ab3fe1f9352e21d6d5ed3f02cdbfc06ed1abc" dependencies = [ "alloy-json-abi", "alloy-primitives", @@ -156,7 +156,7 @@ dependencies = [ "itoa", "serde", "serde_json", - "winnow 0.7.15", + "winnow 1.0.2", ] [[package]] @@ -207,9 +207,9 @@ dependencies = [ [[package]] name = "alloy-eip7928" -version = "0.3.6" +version = "0.4.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "72bc95fd73591644f0022065bef3c027d1a5ed875a53cb19a898d71a00818c1d" +checksum = "b3b12337f74cbfa451cb04dac173974814a6ff463079e1793aa09600ba8813ab" dependencies = [ "alloy-primitives", "alloy-rlp", @@ -222,32 +222,9 @@ dependencies = [ [[package]] name = "alloy-eips" -version = "1.8.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e6ef28c9fdad22d4eec52d894f5f2673a0895f1e5ef196734568e68c0f6caca8" -dependencies = [ - "alloy-eip2124", - "alloy-eip2930", - "alloy-eip7702", - "alloy-eip7928", - "alloy-primitives", - "alloy-rlp", - "alloy-serde 1.8.3", - "auto_impl", - "borsh", - "c-kzg", - "derive_more", - "either", - "serde", - "serde_with", - "sha2", -] - -[[package]] -name = "alloy-eips" -version = "2.0.4" +version = "2.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "64c0456f5f7a4497e9342d20f528e30f5288ddfa0d6a012bd5044afee46cd8a0" +checksum = "ea4c0453065b9206acc0f869a258dc8dcbbd595e144b4446f2c493a24a814d1f" dependencies = [ "alloy-eip2124", "alloy-eip2930", @@ -255,7 +232,7 @@ dependencies = [ "alloy-eip7928", "alloy-primitives", "alloy-rlp", - "alloy-serde 2.0.4", + "alloy-serde", "arbitrary", "auto_impl", "borsh", @@ -271,12 +248,12 @@ dependencies = [ [[package]] name = "alloy-evm" -version = "0.34.0" +version = "0.37.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c1ceeea6dcbbcd4e546b27700763a6f6c3b3fee30054209884f521078b6fda4f" +checksum = "acde665074b478c97047dc2a461b4916cac77922d690e5b7415d1941ae7ff7bf" dependencies = [ "alloy-consensus", - "alloy-eips 2.0.4", + "alloy-eips", "alloy-hardforks", "alloy-primitives", "alloy-rpc-types-engine", @@ -291,13 +268,13 @@ dependencies = [ [[package]] name = "alloy-genesis" -version = "2.0.4" +version = "2.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a71ff8b55d2b8aa05259f474cae7dea0e4991724dc18936b81cb23ec492a0c2a" +checksum = "027ba57264c5d05e4ff52e6090b3592e7526f5d5f5a844add6bbdd17c071c911" dependencies = [ - "alloy-eips 2.0.4", + "alloy-eips", "alloy-primitives", - "alloy-serde 2.0.4", + "alloy-serde", "alloy-trie", "borsh", "serde", @@ -320,9 +297,9 @@ dependencies = [ [[package]] name = "alloy-json-abi" -version = "1.5.7" +version = "1.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e9dbe713da0c737d9e5e387b0ba790eb98b14dd207fe53eef50e19a5a8ec3dac" +checksum = "7c36c9d7f9021601b04bfef14a4b64849f6d73116a4e91e071d7fbfe10247901" dependencies = [ "alloy-primitives", "alloy-sol-type-parser", @@ -332,9 +309,9 @@ dependencies = [ [[package]] name = "alloy-json-rpc" -version = "2.0.4" +version = "2.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "19e352478b756bad5d7203148e4b461861282ea2ded3da406ba24868b52cd098" +checksum = "c4691c60de5d628533752cd07e102d17c47874c06c04c91af33960fd94c484f4" dependencies = [ "alloy-primitives", "alloy-sol-types", @@ -347,19 +324,19 @@ dependencies = [ [[package]] name = "alloy-network" -version = "2.0.4" +version = "2.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ed08ae169869e08370ed121612e0d3dadac33d1a256e9f2465926b23f0bd7d95" +checksum = "9d912bb639bf4ac31e83095afe9e907c8b9774ce0c405966228368309fcfc45f" dependencies = [ "alloy-consensus", "alloy-consensus-any", - "alloy-eips 2.0.4", + "alloy-eips", "alloy-json-rpc", "alloy-network-primitives", "alloy-primitives", "alloy-rpc-types-any", "alloy-rpc-types-eth", - "alloy-serde 2.0.4", + "alloy-serde", "alloy-signer", "alloy-sol-types", "async-trait", @@ -373,22 +350,22 @@ dependencies = [ [[package]] name = "alloy-network-primitives" -version = "2.0.4" +version = "2.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "02e6c7ad28afe348a9a9c5624b67ee5b3607b8de98d5816b3056ecdfa6fa2697" +checksum = "d875a11bd98595f57f73890f2e36f4a1cca0fa670623e59c9fb08b2389979c36" dependencies = [ "alloy-consensus", - "alloy-eips 2.0.4", + "alloy-eips", "alloy-primitives", - "alloy-serde 2.0.4", + "alloy-serde", "serde", ] [[package]] name = "alloy-primitives" -version = "1.5.7" +version = "1.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "de3b431b4e72cd8bd0ec7a50b4be18e73dab74de0dba180eef171055e5d5926e" +checksum = "4885c1409b6936c4898e646ef58baf6ec54edaf6d8179f79df805a7b85b7cf3e" dependencies = [ "alloy-rlp", "arbitrary", @@ -398,31 +375,32 @@ dependencies = [ "derive_more", "foldhash 0.2.0", "getrandom 0.4.2", - "hashbrown 0.16.1", + "hashbrown 0.17.0", "indexmap 2.14.0", "itoa", "k256", "keccak-asm", "paste", "proptest", - "proptest-derive", + "proptest-derive 0.8.0", "rand 0.9.4", "rapidhash", "ruint", "rustc-hash", + "secp256k1 0.31.1", "serde", - "sha3", + "sha3 0.11.0", ] [[package]] name = "alloy-provider" -version = "2.0.4" +version = "2.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "93a7c17472b55482d4734154c2f5ed13f72e03f6752cebb927f6a2d8b52e646c" +checksum = "0e7d526d184d392a8fbcf4293e457789b307bb70646e4f8b902989a246529450" dependencies = [ "alloy-chains", "alloy-consensus", - "alloy-eips 2.0.4", + "alloy-eips", "alloy-json-rpc", "alloy-network", "alloy-network-primitives", @@ -448,7 +426,7 @@ dependencies = [ "lru", "parking_lot", "pin-project", - "reqwest 0.13.3", + "reqwest", "serde", "serde_json", "thiserror 2.0.18", @@ -460,9 +438,9 @@ dependencies = [ [[package]] name = "alloy-pubsub" -version = "2.0.4" +version = "2.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a8d86958b02bca85103d64fa60d7b364a8b017c6e40f2b02c3f50ca22964a738" +checksum = "6fa5976a77e32a63152e937fa90d0dae1f8142b41a9a99a6386d6ea58934cfa6" dependencies = [ "alloy-json-rpc", "alloy-primitives", @@ -482,9 +460,9 @@ dependencies = [ [[package]] name = "alloy-rlp" -version = "0.3.15" +version = "0.3.16" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dc90b1e703d3c03f4ff7f48e82dd0bc1c8211ab7d079cd836a06fcfeb06651cb" +checksum = "24671b1f62edcf0f9b62994c7bf72cd621a04a4b99f5020ece1a647b40e2f103" dependencies = [ "alloy-rlp-derive", "arrayvec", @@ -493,9 +471,9 @@ dependencies = [ [[package]] name = "alloy-rlp-derive" -version = "0.3.15" +version = "0.3.16" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f36834a5c0a2fa56e171bf256c34d70fca07d0c0031583edea1c4946b7889c9e" +checksum = "9d4311c03125e8a18296504560b9de3d75ecbd0dcda7f71e6cf2a196d57e6fba" dependencies = [ "proc-macro2", "quote", @@ -504,9 +482,9 @@ dependencies = [ [[package]] name = "alloy-rpc-client" -version = "2.0.4" +version = "2.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5beb5c2fe6b960c8e8b038e69fd502a90a2e930afa4770efb748b163b0767729" +checksum = "755447dc13a04c6fa6db8dedb5d32ab5edfa4dd7aa34487ff192a3d873e0e8cf" dependencies = [ "alloy-json-rpc", "alloy-primitives", @@ -517,7 +495,7 @@ dependencies = [ "alloy-transport-ws", "futures", "pin-project", - "reqwest 0.13.3", + "reqwest", "serde", "serde_json", "tokio", @@ -530,22 +508,22 @@ dependencies = [ [[package]] name = "alloy-rpc-types" -version = "2.0.4" +version = "2.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4ee1257a278f6d293e05c5162c5940a1561b1aa85ded0028b464c81de37ebfa5" +checksum = "96deb317fe224e98a8ae17a7ed7ea63478867385bf50b7abd53642b24cfd811a" dependencies = [ "alloy-primitives", "alloy-rpc-types-engine", "alloy-rpc-types-eth", - "alloy-serde 2.0.4", + "alloy-serde", "serde", ] [[package]] name = "alloy-rpc-types-admin" -version = "2.0.4" +version = "2.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e2144d5b2866e651796eac0a997d3b5a056449c12e0d91be3184129e0c722885" +checksum = "3279cb55f7069c2fb1dbcd9ab2c6e79a02d63c92fd0b850addea0a3715d6b05f" dependencies = [ "alloy-genesis", "alloy-primitives", @@ -555,38 +533,38 @@ dependencies = [ [[package]] name = "alloy-rpc-types-anvil" -version = "2.0.4" +version = "2.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "df32156f085e74eac942b6103744be49b817c302341aaa8cb0c1c88dc29228d9" +checksum = "9f89d27756bf3effdac25d07692724e840ce90ca1ff956a6b47dd2ae1612f597" dependencies = [ "alloy-primitives", "alloy-rpc-types-eth", - "alloy-serde 2.0.4", + "alloy-serde", "serde", ] [[package]] name = "alloy-rpc-types-any" -version = "2.0.4" +version = "2.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6a234bfbdf7a76c3d13808f729af5321852de3dedcaa6fc6d5f54787aaf54c6a" +checksum = "911a513723ef0b90c3b072f65eebf54d6ebc8b651d06734e252d024bd89b88ac" dependencies = [ "alloy-consensus-any", "alloy-network-primitives", "alloy-primitives", "alloy-rpc-types-eth", - "alloy-serde 2.0.4", + "alloy-serde", "serde", "serde_json", ] [[package]] name = "alloy-rpc-types-beacon" -version = "2.0.4" +version = "2.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "296450f5e76bece0116c939b9437b0421a5da9c5d40031bf4cf9b38d3d94e475" +checksum = "81133671b8da58169589aac996f3c4da23bbdee85b13ecee7098065f3eae718a" dependencies = [ - "alloy-eips 2.0.4", + "alloy-eips", "alloy-primitives", "alloy-rpc-types-engine", "derive_more", @@ -602,9 +580,9 @@ dependencies = [ [[package]] name = "alloy-rpc-types-debug" -version = "2.0.4" +version = "2.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0ab075ac1c25bcf697f133b7cd92e2fb26afe213e872ef79fdf77f0d7bcb3793" +checksum = "b9e9c1f9ac81c56b2d96901201db7eb95c4e9fc3c21237a4690f8c652aa62089" dependencies = [ "alloy-primitives", "alloy-rlp", @@ -615,15 +593,15 @@ dependencies = [ [[package]] name = "alloy-rpc-types-engine" -version = "2.0.4" +version = "2.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "73b12366c96f4013e1aeebc96c6b56e5f33f07853c42ea2f485045c0c157a4a1" +checksum = "5b1f682c4881aa7000ac7cc86d7aeeb3b09836a77a90b329820140233651aeea" dependencies = [ "alloy-consensus", - "alloy-eips 2.0.4", + "alloy-eips", "alloy-primitives", "alloy-rlp", - "alloy-serde 2.0.4", + "alloy-serde", "derive_more", "ethereum_ssz", "ethereum_ssz_derive", @@ -635,17 +613,17 @@ dependencies = [ [[package]] name = "alloy-rpc-types-eth" -version = "2.0.4" +version = "2.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "56a282daf869eeb7383d3d5c2deb35b0b3fb45ecb329513af4090fc61245ee18" +checksum = "4e1bd19904581ee2075b61faabab1a4cefa8b96d8f2c85343adeae8ecf615e2b" dependencies = [ "alloy-consensus", "alloy-consensus-any", - "alloy-eips 2.0.4", + "alloy-eips", "alloy-network-primitives", "alloy-primitives", "alloy-rlp", - "alloy-serde 2.0.4", + "alloy-serde", "alloy-sol-types", "arbitrary", "itertools 0.14.0", @@ -657,28 +635,28 @@ dependencies = [ [[package]] name = "alloy-rpc-types-mev" -version = "2.0.4" +version = "2.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7adc1243d55744a66b3a6cbbbba96436e8df5d248f2ee8186bef4238ef704ec7" +checksum = "54c635f0c45a871b55c276653e3838d1687d86282eeaf3d83a1914e02563b3f2" dependencies = [ "alloy-consensus", - "alloy-eips 2.0.4", + "alloy-eips", "alloy-primitives", "alloy-rpc-types-eth", - "alloy-serde 2.0.4", + "alloy-serde", "serde", "serde_json", ] [[package]] name = "alloy-rpc-types-trace" -version = "2.0.4" +version = "2.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6184b5d14152b68b0bb8beb621339d94f0b761a37958bb365fbf7c00922125c2" +checksum = "796729a4e1783904c6040f11a503c4d55ddb16f69dc199ad15e50c4ad039f371" dependencies = [ "alloy-primitives", "alloy-rpc-types-eth", - "alloy-serde 2.0.4", + "alloy-serde", "serde", "serde_json", "thiserror 2.0.18", @@ -686,32 +664,21 @@ dependencies = [ [[package]] name = "alloy-rpc-types-txpool" -version = "2.0.4" +version = "2.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f00b631c361e7c7baaf4f1f5a9877730f3507fed2acb9d4b34841b8184b2ec28" +checksum = "8533c450895de79eb581875bfc317d1a239ae71aba79e20ee158fa153268f163" dependencies = [ "alloy-primitives", "alloy-rpc-types-eth", - "alloy-serde 2.0.4", - "serde", -] - -[[package]] -name = "alloy-serde" -version = "1.8.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "11ece63b89294b8614ab3f483560c08d016930f842bf36da56bf0b764a15c11e" -dependencies = [ - "alloy-primitives", + "alloy-serde", "serde", - "serde_json", ] [[package]] name = "alloy-serde" -version = "2.0.4" +version = "2.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a0eada2558e921b39dfcead33c487364df9b31374f5733c1c9d2c891c4529933" +checksum = "c1e97b3e0b9f816b25083045dcfa69431bd059a078e828e4d82d296d1949b96c" dependencies = [ "alloy-primitives", "arbitrary", @@ -721,9 +688,9 @@ dependencies = [ [[package]] name = "alloy-signer" -version = "2.0.4" +version = "2.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "41eb29f7a8adcd8941fbb8e134022a133e6f8dfd345f2e3b7109599f8a7dca08" +checksum = "6913d06ccc0d9c6ab67e2f82e2fbe292706da1f91442f30cded2d04b56bf0d58" dependencies = [ "alloy-primitives", "async-trait", @@ -736,9 +703,9 @@ dependencies = [ [[package]] name = "alloy-signer-local" -version = "2.0.4" +version = "2.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bef839e7ce9b59aa60fa9a175e97986c6145c888d643b0f1fb0a3e7b8e56a2e2" +checksum = "c880813cd26bd1ddf8c2236e31295896efd1fcc5cc761d8894ae894503aeea53" dependencies = [ "alloy-consensus", "alloy-network", @@ -755,9 +722,9 @@ dependencies = [ [[package]] name = "alloy-sol-macro" -version = "1.5.7" +version = "1.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ab81bab693da9bb79f7a95b64b394718259fdd7e41dceeced4cad57cb71c4f6a" +checksum = "840128ed2b2971d6d4668a553fe403a82683d3acc646c73e75887e7157408033" dependencies = [ "alloy-sol-macro-expander", "alloy-sol-macro-input", @@ -769,9 +736,9 @@ dependencies = [ [[package]] name = "alloy-sol-macro-expander" -version = "1.5.7" +version = "1.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "489f1620bb7e2483fb5819ed01ab6edc1d2f93939dce35a5695085a1afd1d699" +checksum = "63ec265e5d65d725175f6ca7711c970824c90ef9c0d1f1973711d4150ee612dd" dependencies = [ "alloy-sol-macro-input", "const-hex", @@ -780,16 +747,16 @@ dependencies = [ "proc-macro-error2", "proc-macro2", "quote", - "sha3", + "sha3 0.11.0", "syn 2.0.117", "syn-solidity", ] [[package]] name = "alloy-sol-macro-input" -version = "1.5.7" +version = "1.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "56cef806ad22d4392c5fc83cf8f2089f988eb99c7067b4e0c6f1971fc1cca318" +checksum = "89bf01077f18650876cfa682eb1f949967b5cde03f1a51c955c469d2c9b4aa67" dependencies = [ "const-hex", "dunce", @@ -803,19 +770,19 @@ dependencies = [ [[package]] name = "alloy-sol-type-parser" -version = "1.5.7" +version = "1.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a6df77fea9d6a2a75c0ef8d2acbdfd92286cc599983d3175ccdc170d3433d249" +checksum = "857b470ecdd2ed38beaf82ad1a38c516a8ff75266750f38b9eeed001d575241b" dependencies = [ "serde", - "winnow 0.7.15", + "winnow 1.0.2", ] [[package]] name = "alloy-sol-types" -version = "1.5.7" +version = "1.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "64612d29379782a5dde6f4b6570d9c756d734d760c0c94c254d361e678a6591f" +checksum = "384cf252de0db2dec52821eac037a7f57e2aa33fe5b900ce6fe39973402341f1" dependencies = [ "alloy-json-abi", "alloy-primitives", @@ -825,9 +792,9 @@ dependencies = [ [[package]] name = "alloy-transport" -version = "2.0.4" +version = "2.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3ac7a80c0bac3e44559d53d002e34c461dc2f23262b42cafec019bc70551abbe" +checksum = "999adfe5c91035c6bf4c4210e0eb8d0caed79d76fbf5e1b70d78721f6097ac04" dependencies = [ "alloy-json-rpc", "auto_impl", @@ -848,14 +815,14 @@ dependencies = [ [[package]] name = "alloy-transport-http" -version = "2.0.4" +version = "2.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "eed3ed3300a998f88639ed619fdbbd88bd82865e00c6a8ecb796c99eb12358f6" +checksum = "0e79a2c1793afc61eed9ca0963da370a988b27d2bbfa67c78013e262d47424c4" dependencies = [ "alloy-json-rpc", "alloy-transport", "itertools 0.14.0", - "reqwest 0.13.3", + "reqwest", "serde_json", "tower", "tracing", @@ -864,9 +831,9 @@ dependencies = [ [[package]] name = "alloy-transport-ipc" -version = "2.0.4" +version = "2.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1075d9d30fd4d71e50000fd4afb19ed2664ceab20c2a29f3889a6e988329e02d" +checksum = "c24422d5159996688b0c094babf1969cb0197d453902da483711c92c1624fea2" dependencies = [ "alloy-json-rpc", "alloy-pubsub", @@ -884,9 +851,9 @@ dependencies = [ [[package]] name = "alloy-transport-ws" -version = "2.0.4" +version = "2.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0e3bff84b2b2a46eb34cc522dc3f889a2867c70be90a377421429b662b3ec4ce" +checksum = "1bea36621cd4e4f06c1243e556b32fdc9c4db7b9b09b72a95a87383c0ffcc625" dependencies = [ "alloy-pubsub", "alloy-transport", @@ -914,7 +881,7 @@ dependencies = [ "derive_more", "nybbles", "proptest", - "proptest-derive", + "proptest-derive 0.7.0", "serde", "smallvec", "thiserror 2.0.18", @@ -923,11 +890,11 @@ dependencies = [ [[package]] name = "alloy-tx-macros" -version = "2.0.4" +version = "2.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "99fce0350197dcd4ba4e9a7dd43915d908c0eb0e7352755791709a705e1c76b6" +checksum = "406bc1183f6843e0aba09f7b3365e828b597213d60793ba5cb41befc863e3a78" dependencies = [ - "darling 0.23.0", + "darling", "proc-macro2", "quote", "syn 2.0.117", @@ -978,7 +945,7 @@ version = "1.1.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "40c48f72fd53cd289104fc64099abca73db4166ad86ea0b4341abe65af83dadc" dependencies = [ - "windows-sys 0.60.2", + "windows-sys 0.61.2", ] [[package]] @@ -989,7 +956,7 @@ checksum = "291e6a250ff86cd4a820112fb8898808a366d8f9f58ce16d1f538353ad55747d" dependencies = [ "anstyle", "once_cell_polyfill", - "windows-sys 0.60.2", + "windows-sys 0.61.2", ] [[package]] @@ -1622,12 +1589,12 @@ dependencies = [ ] [[package]] -name = "block-padding" -version = "0.3.3" +name = "block-buffer" +version = "0.12.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a8894febbff9f758034a5b8e12d87918f56dfc64a8e1fe757d65e29041538d93" +checksum = "d2f6c7dbe95a6ed67ad9f18e57daf93a2f034c524b99fd2b76d18fdfeb6660aa" dependencies = [ - "generic-array", + "hybrid-array", ] [[package]] @@ -1642,6 +1609,31 @@ dependencies = [ "zeroize", ] +[[package]] +name = "bon" +version = "3.9.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a602c73c7b0148ec6d12af6fd5cc7a46e2eacc8878271a999abac56eed12f561" +dependencies = [ + "bon-macros", + "rustversion", +] + +[[package]] +name = "bon-macros" +version = "3.9.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6dee98b0db6a962de883bf5d20362dee4d7ca0d12fe39a7c6c73c844e1cd7c1f" +dependencies = [ + "darling", + "ident_case", + "prettyplease", + "proc-macro2", + "quote", + "rustversion", + "syn 2.0.117", +] + [[package]] name = "borsh" version = "1.6.1" @@ -1765,39 +1757,6 @@ dependencies = [ "serde", ] -[[package]] -name = "camino" -version = "1.2.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e629a66d692cb9ff1a1c664e41771b3dcaf961985a9774c0eb0bd1b51cf60a48" -dependencies = [ - "serde_core", -] - -[[package]] -name = "cargo-platform" -version = "0.3.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dd0061da739915fae12ea00e16397555ed4371a6bb285431aab930f61b0aa4ba" -dependencies = [ - "serde", - "serde_core", -] - -[[package]] -name = "cargo_metadata" -version = "0.23.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ef987d17b0a113becdd19d3d0022d04d7ef41f9efe4f3fb63ac44ba61df3ade9" -dependencies = [ - "camino", - "cargo-platform", - "semver 1.0.28", - "serde", - "serde_json", - "thiserror 2.0.18", -] - [[package]] name = "castaway" version = "0.2.4" @@ -1846,6 +1805,17 @@ version = "0.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "613afe47fcd5fac7ccf1db93babcb082c5994d996f20b8b159f2ad1658eb5724" +[[package]] +name = "chacha20" +version = "0.10.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d524456ba66e72eb8b115ff89e01e497f8e6d11d78b70b1aa13c0fbd97540a81" +dependencies = [ + "cfg-if", + "cpufeatures 0.3.0", + "rand_core 0.10.1", +] + [[package]] name = "chrono" version = "0.4.44" @@ -1866,7 +1836,7 @@ version = "0.4.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "773f3b9af64447d2ce9850330c473515014aa235e6a783b02db81ff39e4a3dad" dependencies = [ - "crypto-common", + "crypto-common 0.1.7", "inout", ] @@ -1977,7 +1947,7 @@ dependencies = [ "ripemd", "serde", "sha2", - "sha3", + "sha3 0.10.9", "thiserror 1.0.69", ] @@ -2111,6 +2081,16 @@ dependencies = [ "unicode-segmentation", ] +[[package]] +name = "core-foundation" +version = "0.9.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "91e195e091a93c46f7102ec7818a2aa394e1e1771c3ab4825963fa03e45afb8f" +dependencies = [ + "core-foundation-sys", + "libc", +] + [[package]] name = "core-foundation" version = "0.10.1" @@ -2196,9 +2176,9 @@ dependencies = [ [[package]] name = "crossbeam-epoch" -version = "0.9.18" +version = "0.9.20" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5b82ac4a3c2ca9c3460964f020e1402edd5753411d7737aa39c3714ad1b5420e" +checksum = "2d6914041f254d6e9176c01941b21115dcfb7089e55135a35411081bd106ef3f" dependencies = [ "crossbeam-utils", ] @@ -2274,6 +2254,15 @@ dependencies = [ "typenum", ] +[[package]] +name = "crypto-common" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ce6e4c961d6cd6c9a86db418387425e8bdeaf05b3c8bc1411e6dca4c252f1453" +dependencies = [ + "hybrid-array", +] + [[package]] name = "ctr" version = "0.9.2" @@ -2310,38 +2299,14 @@ dependencies = [ "syn 2.0.117", ] -[[package]] -name = "darling" -version = "0.20.11" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fc7f46116c46ff9ab3eb1597a45688b6715c6e628b5c133e288e709a29bcb4ee" -dependencies = [ - "darling_core 0.20.11", - "darling_macro 0.20.11", -] - [[package]] name = "darling" version = "0.23.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "25ae13da2f202d56bd7f91c25fba009e7717a1e4a1cc98a76d844b65ae912e9d" dependencies = [ - "darling_core 0.23.0", - "darling_macro 0.23.0", -] - -[[package]] -name = "darling_core" -version = "0.20.11" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0d00b9596d185e565c2207a0b01f8bd1a135483d02d9b7b0a54b11da8d53412e" -dependencies = [ - "fnv", - "ident_case", - "proc-macro2", - "quote", - "strsim", - "syn 2.0.117", + "darling_core", + "darling_macro", ] [[package]] @@ -2358,33 +2323,22 @@ dependencies = [ "syn 2.0.117", ] -[[package]] -name = "darling_macro" -version = "0.20.11" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fc34b93ccb385b40dc71c6fceac4b2ad23662c7eeb248cf10d529b7e055b6ead" -dependencies = [ - "darling_core 0.20.11", - "quote", - "syn 2.0.117", -] - [[package]] name = "darling_macro" version = "0.23.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ac3984ec7bd6cfa798e62b4a642426a5be0e68f9401cfc2a01e3fa9ea2fcdb8d" dependencies = [ - "darling_core 0.23.0", + "darling_core", "quote", "syn 2.0.117", ] [[package]] name = "dashmap" -version = "6.1.0" +version = "6.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5041cc499144891f3790297212f32a74fb938e5136a14943f338ef9e0ae276cf" +checksum = "e6361d5c062261c78a176addb82d4c821ae42bed6089de0e12603cd25de2059c" dependencies = [ "arbitrary", "cfg-if", @@ -2419,7 +2373,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ccc2776f0c61eca1ca32528f85548abd1a4be8fb53d1b21c013e4f18da1e7090" dependencies = [ "data-encoding", - "syn 1.0.109", + "syn 2.0.117", ] [[package]] @@ -2455,7 +2409,6 @@ version = "0.5.8" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7cd812cc2bc1d69d4764bd80df88b4317eaef9e773c75226407d9bc0876b211c" dependencies = [ - "powerfmt", "serde_core", ] @@ -2492,37 +2445,6 @@ dependencies = [ "syn 2.0.117", ] -[[package]] -name = "derive_builder" -version = "0.20.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "507dfb09ea8b7fa618fcf76e953f4f5e192547945816d5358edffe39f6f94947" -dependencies = [ - "derive_builder_macro", -] - -[[package]] -name = "derive_builder_core" -version = "0.20.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2d5bcf7b024d6835cfb3d473887cd966994907effbe9227e8c8219824d06c4e8" -dependencies = [ - "darling 0.20.11", - "proc-macro2", - "quote", - "syn 2.0.117", -] - -[[package]] -name = "derive_builder_macro" -version = "0.20.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ab63b0e2bf4d5928aff72e83a7dace85d7bba5fe12dcc3c5a572d78caffd3f3c" -dependencies = [ - "derive_builder_core", - "syn 2.0.117", -] - [[package]] name = "derive_more" version = "2.1.1" @@ -2567,12 +2489,22 @@ version = "0.10.7" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9ed9a281f7bc9b7576e61468ba615a66a5c8cfdff42420a70aa82701a3b1e292" dependencies = [ - "block-buffer", + "block-buffer 0.10.4", "const-oid", - "crypto-common", + "crypto-common 0.1.7", "subtle", ] +[[package]] +name = "digest" +version = "0.11.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f1dd6dbb5841937940781866fa1281a1ff7bd3bf827091440879f9994983d5c2" +dependencies = [ + "block-buffer 0.12.1", + "crypto-common 0.2.2", +] + [[package]] name = "dirs-next" version = "2.0.0" @@ -2717,9 +2649,9 @@ dependencies = [ [[package]] name = "either" -version = "1.15.0" +version = "1.16.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "48c757948c5ede0e46177b7add2e67155f70e33c07fea8284df6576da70b3719" +checksum = "91622ff5e7162018101f2fea40d6ebf4a78bbe5a49736a2020649edf9693679e" dependencies = [ "serde", ] @@ -2760,22 +2692,10 @@ dependencies = [ "rand 0.8.6", "secp256k1 0.30.0", "serde", - "sha3", + "sha3 0.10.9", "zeroize", ] -[[package]] -name = "enum-as-inner" -version = "0.6.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a1e6a265c649f3f5979b601d26f1d05ada116434c87741c9493cb56218f76cbc" -dependencies = [ - "heck", - "proc-macro2", - "quote", - "syn 2.0.117", -] - [[package]] name = "enum-ordinalize" version = "4.3.2" @@ -2809,7 +2729,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "39cab71617ae0d63f51a36d69f866391735b51691dbda63cf6f96d042b63efeb" dependencies = [ "libc", - "windows-sys 0.59.0", + "windows-sys 0.61.2", ] [[package]] @@ -2838,9 +2758,9 @@ dependencies = [ [[package]] name = "ethereum_ssz" -version = "0.10.3" +version = "0.10.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "368a4a4e4273b0135111fe9464e35465067766a8f664615b5a86338b73864407" +checksum = "e462875ad8693755ea8913d6e905715c76ea4836e2254e18c9cf0f7a8f8c2a13" dependencies = [ "alloy-primitives", "ethereum_serde_utils", @@ -2853,11 +2773,11 @@ dependencies = [ [[package]] name = "ethereum_ssz_derive" -version = "0.10.3" +version = "0.10.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f2cd82c68120c89361e1a457245cf212f7d9f541bffaffed530c8f2d54a160b2" +checksum = "daf022360bdbe9456eda5f35718a50476d5b2a0d51a97ed4eae27420737a6fba" dependencies = [ - "darling 0.23.0", + "darling", "proc-macro2", "quote", "syn 2.0.117", @@ -2957,9 +2877,9 @@ checksum = "5baebc0774151f905a1a2cc41989300b1e6fbb29aff0ceffa1064fdd3088d582" [[package]] name = "fixed-cache" -version = "0.1.8" +version = "0.1.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c41c7aa69c00ebccf06c3fa7ffe2a6cf26a58b5fe4deabfe646285ff48136a8f" +checksum = "2fe63500644ef0269fe6b744e7e5dc5c20b5eebf3d881bc2be53f194636f6583" dependencies = [ "equivalent", "rapidhash", @@ -3172,8 +3092,8 @@ dependencies = [ "libc", "log", "rustversion", - "windows-link 0.1.3", - "windows-result 0.3.4", + "windows-link 0.2.1", + "windows-result 0.4.1", ] [[package]] @@ -3223,6 +3143,7 @@ dependencies = [ "cfg-if", "libc", "r-efi 6.0.0", + "rand_core 0.10.1", "wasip2", "wasip3", ] @@ -3239,15 +3160,14 @@ dependencies = [ [[package]] name = "git2" -version = "0.20.4" +version = "0.21.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7b88256088d75a56f8ecfa070513a775dd9107f6530ef14919dac831af9cfe2b" +checksum = "ddddbf932745a6be37109b6112d3ee09696106f848449069d3a57bba937ab82e" dependencies = [ "bitflags", "libc", "libgit2-sys", "log", - "url", ] [[package]] @@ -3381,8 +3301,6 @@ dependencies = [ "allocator-api2", "equivalent", "foldhash 0.2.0", - "serde", - "serde_core", ] [[package]] @@ -3390,6 +3308,11 @@ name = "hashbrown" version = "0.17.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4f467dd6dccf739c208452f8014c75c18bb8301b050ad1cfb27153803edb0f51" +dependencies = [ + "foldhash 0.2.0", + "serde", + "serde_core", +] [[package]] name = "hashlink" @@ -3438,48 +3361,72 @@ dependencies = [ ] [[package]] -name = "hickory-proto" -version = "0.25.2" +name = "hickory-net" +version = "0.26.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f8a6fe56c0038198998a6f217ca4e7ef3a5e51f46163bd6dd60b5c71ca6c6502" +checksum = "e2295ed2f9c31e471e1428a8f88a3f0e1f4b27c15049592138d1eebe9c35b183" dependencies = [ "async-trait", "cfg-if", "data-encoding", - "enum-as-inner", "futures-channel", "futures-io", "futures-util", + "hickory-proto", "idna", "ipnet", + "jni 0.22.4", + "rand 0.10.2", + "thiserror 2.0.18", + "tinyvec", + "tokio", + "tracing", + "url", +] + +[[package]] +name = "hickory-proto" +version = "0.26.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0bab31817bfb44672a252e97fe81cd0c18d1b2cf892108922f6818820df8c643" +dependencies = [ + "data-encoding", + "idna", + "ipnet", + "jni 0.22.4", "once_cell", - "rand 0.9.4", + "prefix-trie", + "rand 0.10.2", "ring", "serde", "thiserror 2.0.18", "tinyvec", - "tokio", "tracing", "url", ] [[package]] name = "hickory-resolver" -version = "0.25.2" +version = "0.26.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dc62a9a99b0bfb44d2ab95a7208ac952d31060efc16241c87eaf36406fecf87a" +checksum = "f0d58d28879ceecde6607729660c2667a081ccdc082e082675042793960f178c" dependencies = [ "cfg-if", "futures-util", + "hickory-net", "hickory-proto", "ipconfig", + "ipnet", + "jni 0.22.4", "moka", + "ndk-context", "once_cell", "parking_lot", - "rand 0.9.4", + "rand 0.10.2", "resolv-conf", "serde", "smallvec", + "system-configuration", "thiserror 2.0.18", "tokio", "tracing", @@ -3576,6 +3523,15 @@ dependencies = [ "serde", ] +[[package]] +name = "hybrid-array" +version = "0.4.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "818356c5132c1fede50f837ca96afbe78ff42413047f4abb886217845e1b6c8c" +dependencies = [ + "typenum", +] + [[package]] name = "hyper" version = "1.9.0" @@ -3609,7 +3565,6 @@ dependencies = [ "hyper-util", "log", "rustls", - "rustls-native-certs", "tokio", "tokio-rustls", "tower-service", @@ -3663,7 +3618,7 @@ dependencies = [ "js-sys", "log", "wasm-bindgen", - "windows-core 0.61.2", + "windows-core 0.62.2", ] [[package]] @@ -3929,7 +3884,6 @@ version = "0.1.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "879f10e63c20629ecabbb64a8010319738c66a5cd0c29b02d63d272b03751d01" dependencies = [ - "block-padding", "generic-array", ] @@ -3939,7 +3893,7 @@ version = "0.3.12" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5eb2d60ef19920a3a9193c3e371f726ec1dafc045dac788d0fb3704272458971" dependencies = [ - "darling 0.23.0", + "darling", "indoc", "proc-macro2", "quote", @@ -3979,6 +3933,9 @@ name = "ipnet" version = "2.12.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d98f6fed1fde3f8c21bc40a1abb88dd75e67924f9cffc3ef95607bad8017f8e2" +dependencies = [ + "serde", +] [[package]] name = "is_terminal_polyfill" @@ -4356,6 +4313,16 @@ dependencies = [ "cpufeatures 0.2.17", ] +[[package]] +name = "keccak" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9e24a010dd405bd7ed803e5253182815b41bf2e6a80cc3bfc066658e03a198aa" +dependencies = [ + "cfg-if", + "cpufeatures 0.3.0", +] + [[package]] name = "keccak-asm" version = "0.1.6" @@ -4656,9 +4623,9 @@ checksum = "dae608c151f68243f2b000364e1f7b186d9c29845f7d2d85bd31b9ad77ad552b" [[package]] name = "macro-string" -version = "0.1.4" +version = "0.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1b27834086c65ec3f9387b096d66e99f221cf081c2b738042aa252bcd41204e3" +checksum = "59a9dbbfc75d2688ed057456ce8a3ee3f48d12eec09229f560f3643b9f275653" dependencies = [ "proc-macro2", "quote", @@ -4706,9 +4673,9 @@ checksum = "f8ca58f447f06ed17d5fc4043ce1b10dd205e060fb3ce5b979b8ed8e59ff3f79" [[package]] name = "memmap2" -version = "0.9.10" +version = "0.9.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "714098028fe011992e1c3962653c96b2d578c4b4bce9036e15ff220319b1e0e3" +checksum = "d1219ed1b7f229ee7104d281dd01d6802fe28bb6e95d292942c4daacdeb798c0" dependencies = [ "libc", ] @@ -4876,12 +4843,12 @@ version = "1.0.0" dependencies = [ "alloy-chains", "alloy-consensus", - "alloy-eips 2.0.4", + "alloy-eips", "alloy-evm", "alloy-genesis", "alloy-hardforks", "alloy-primitives", - "alloy-serde 2.0.4", + "alloy-serde", "auto_impl", "eyre", "morph-primitives", @@ -4916,7 +4883,7 @@ name = "morph-engine-api" version = "1.0.0" dependencies = [ "alloy-consensus", - "alloy-eips 2.0.4", + "alloy-eips", "alloy-genesis", "alloy-primitives", "alloy-rpc-types-engine", @@ -4939,52 +4906,6 @@ dependencies = [ "tracing", ] -[[package]] -name = "morph-engine-tree-ext" -version = "1.0.0" -dependencies = [ - "alloy-consensus", - "alloy-eip7928", - "alloy-eips 2.0.4", - "alloy-evm", - "alloy-genesis", - "alloy-primitives", - "alloy-rlp", - "alloy-rpc-types-engine", - "alloy-rpc-types-eth", - "crossbeam-channel", - "derive_more", - "eyre", - "morph-chainspec", - "morph-node", - "morph-payload-types", - "morph-primitives", - "reth-chain-state", - "reth-consensus", - "reth-db", - "reth-engine-primitives", - "reth-engine-tree", - "reth-errors", - "reth-evm", - "reth-execution-cache", - "reth-node-api", - "reth-payload-builder", - "reth-payload-primitives", - "reth-primitives-traits", - "reth-provider", - "reth-revm", - "reth-tasks", - "reth-tracing", - "reth-trie", - "reth-trie-db", - "reth-trie-parallel", - "reth-trie-sparse", - "revm-primitives", - "serde_json", - "tokio", - "tracing", -] - [[package]] name = "morph-evm" version = "1.0.0" @@ -4993,6 +4914,7 @@ dependencies = [ "alloy-evm", "alloy-genesis", "alloy-primitives", + "alloy-rpc-types-eth", "derive_more", "morph-chainspec", "morph-payload-types", @@ -5016,7 +4938,7 @@ name = "morph-node" version = "1.0.0" dependencies = [ "alloy-consensus", - "alloy-eips 2.0.4", + "alloy-eips", "alloy-genesis", "alloy-hardforks", "alloy-primitives", @@ -5033,7 +4955,6 @@ dependencies = [ "morph-chainspec", "morph-consensus", "morph-engine-api", - "morph-engine-tree-ext", "morph-evm", "morph-payload-builder", "morph-payload-types", @@ -5042,6 +4963,7 @@ dependencies = [ "morph-rpc", "morph-txpool", "parking_lot", + "reth-chain-state", "reth-chainspec", "reth-db", "reth-db-api", @@ -5049,6 +4971,8 @@ dependencies = [ "reth-engine-local", "reth-engine-tree", "reth-errors", + "reth-evm", + "reth-execution-cache", "reth-exex", "reth-node-api", "reth-node-builder", @@ -5081,7 +5005,7 @@ name = "morph-payload-builder" version = "1.0.0" dependencies = [ "alloy-consensus", - "alloy-eips 2.0.4", + "alloy-eips", "alloy-primitives", "alloy-rlp", "metrics", @@ -5113,11 +5037,11 @@ name = "morph-payload-types" version = "1.0.0" dependencies = [ "alloy-consensus", - "alloy-eips 2.0.4", + "alloy-eips", "alloy-primitives", "alloy-rlp", "alloy-rpc-types-engine", - "alloy-serde 2.0.4", + "alloy-serde", "morph-primitives", "rand 0.8.6", "reth-ethereum-primitives", @@ -5133,10 +5057,10 @@ name = "morph-primitives" version = "1.0.0" dependencies = [ "alloy-consensus", - "alloy-eips 2.0.4", + "alloy-eips", "alloy-primitives", "alloy-rlp", - "alloy-serde 2.0.4", + "alloy-serde", "bytes", "modular-bitfield", "reth-codecs", @@ -5199,7 +5123,7 @@ name = "morph-revm" version = "1.0.0" dependencies = [ "alloy-consensus", - "alloy-eips 2.0.4", + "alloy-eips", "alloy-evm", "alloy-primitives", "alloy-sol-types", @@ -5222,12 +5146,12 @@ name = "morph-rpc" version = "1.0.0" dependencies = [ "alloy-consensus", - "alloy-eips 2.0.4", + "alloy-eips", "alloy-evm", "alloy-network", "alloy-primitives", "alloy-rpc-types-eth", - "alloy-serde 2.0.4", + "alloy-serde", "derive_more", "eyre", "jsonrpsee", @@ -5284,7 +5208,7 @@ name = "morph-txpool" version = "1.0.0" dependencies = [ "alloy-consensus", - "alloy-eips 2.0.4", + "alloy-eips", "alloy-evm", "alloy-primitives", "c-kzg", @@ -5346,6 +5270,12 @@ dependencies = [ "unsigned-varint", ] +[[package]] +name = "ndk-context" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "27b02d87554356db9e9a873add8782d4ea6e3e58ea071a9adb9a2e8ddb884a8b" + [[package]] name = "nom" version = "7.1.3" @@ -5356,6 +5286,15 @@ dependencies = [ "minimal-lexical", ] +[[package]] +name = "nonmax" +version = "0.5.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "610a5acd306ec67f907abe5567859a3c693fb9886eb1f012ab8f2a47bef3db51" +dependencies = [ + "serde", +] + [[package]] name = "notify" version = "8.2.0" @@ -5398,7 +5337,7 @@ version = "0.50.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7957b9740744892f114936ab4a57b3f487491bbeafaf8083688b16841a4240e5" dependencies = [ - "windows-sys 0.59.0", + "windows-sys 0.61.2", ] [[package]] @@ -5436,9 +5375,9 @@ dependencies = [ [[package]] name = "num-conv" -version = "0.2.1" +version = "0.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c6673768db2d862beb9b39a78fdcb1a69439615d5794a1be50caa9bc92c81967" +checksum = "521739c6d2bac4aa25192232afe6841231376b2b26d4d9fae5ecf8ca5772e441" [[package]] name = "num-integer" @@ -5507,7 +5446,6 @@ version = "0.7.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "680998035259dcfcafe653688bf2aa6d3e2dc05e98be6ab46afb089dc84f1df8" dependencies = [ - "proc-macro-crate", "proc-macro2", "quote", "syn 2.0.117", @@ -5586,9 +5524,9 @@ checksum = "7c87def4c32ab89d880effc9e097653c8da5d6ef28e6b539d313baaacfbafcbe" [[package]] name = "opentelemetry" -version = "0.31.0" +version = "0.32.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b84bcd6ae87133e903af7ef497404dda70c60d0ea14895fc8a5e6722754fc2a0" +checksum = "b0142c63252a9e054e68a4c61a5778f7b14f576274d593f8ce883d191a099682" dependencies = [ "futures-core", "futures-sink", @@ -5600,22 +5538,22 @@ dependencies = [ [[package]] name = "opentelemetry-http" -version = "0.31.0" +version = "0.32.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d7a6d09a73194e6b66df7c8f1b680f156d916a1a942abf2de06823dd02b7855d" +checksum = "5683015d09e2df236ef005b17f6f196f0d5f6313c4fa43a7b6a53b52776e4331" dependencies = [ "async-trait", "bytes", "http", "opentelemetry", - "reqwest 0.12.28", + "reqwest", ] [[package]] name = "opentelemetry-otlp" -version = "0.31.1" +version = "0.32.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1f69cd6acbb9af919df949cd1ec9e5e7fdc2ef15d234b6b795aaa525cc02f71f" +checksum = "9966929966d17620d7c316c643ba62631826e10021409357772d5eea84f62c35" dependencies = [ "http", "opentelemetry", @@ -5623,18 +5561,18 @@ dependencies = [ "opentelemetry-proto", "opentelemetry_sdk", "prost", - "reqwest 0.12.28", + "reqwest", "thiserror 2.0.18", "tokio", "tonic", - "tracing", + "tonic-types", ] [[package]] name = "opentelemetry-proto" -version = "0.31.0" +version = "0.32.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a7175df06de5eaee9909d4805a3d07e28bb752c34cab57fa9cff549da596b30f" +checksum = "56d658ba1faf63f7b9c492cfbe6e0ec365440a16132d3270c1065f7b33f1b638" dependencies = [ "opentelemetry", "opentelemetry_sdk", @@ -5645,21 +5583,22 @@ dependencies = [ [[package]] name = "opentelemetry-semantic-conventions" -version = "0.31.0" +version = "0.32.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e62e29dfe041afb8ed2a6c9737ab57db4907285d999ef8ad3a59092a36bdc846" +checksum = "c913ac17a6c451661ee255f4625d143e51647ae78ebd969b75e41c4442f4fe47" [[package]] name = "opentelemetry_sdk" -version = "0.31.0" +version = "0.32.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e14ae4f5991976fd48df6d843de219ca6d31b01daaab2dad5af2badeded372bd" +checksum = "9b59f80e1ac4d5ff7a2db8fb6c80badb7f0f3f858211fba08dd9aaec750894f9" dependencies = [ "futures-channel", "futures-executor", "futures-util", "opentelemetry", "percent-encoding", + "portable-atomic", "rand 0.9.4", "thiserror 2.0.18", ] @@ -5951,6 +5890,17 @@ dependencies = [ "zerocopy", ] +[[package]] +name = "prefix-trie" +version = "0.8.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4cf6e3177f0684016a5c209b00882e15f8bdd3f3bb48f0491df10cd102d0c6e7" +dependencies = [ + "either", + "ipnet", + "num-traits", +] + [[package]] name = "pretty_assertions" version = "1.4.1" @@ -6095,6 +6045,17 @@ dependencies = [ "syn 2.0.117", ] +[[package]] +name = "proptest-derive" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c57924a81864dddafba92e1bf92f9bf82f97096c44489548a60e888e1547549b" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.117", +] + [[package]] name = "prost" version = "0.14.3" @@ -6118,6 +6079,15 @@ dependencies = [ "syn 2.0.117", ] +[[package]] +name = "prost-types" +version = "0.14.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8991c4cbdb8bc5b11f0b074ffe286c30e523de90fee5ba8132f1399f23cb3dd7" +dependencies = [ + "prost", +] + [[package]] name = "quanta" version = "0.12.6" @@ -6254,6 +6224,17 @@ dependencies = [ "serde", ] +[[package]] +name = "rand" +version = "0.10.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c7f5fa3a058cd35567ef9bfa5e75732bee0f9e4c55fa90477bef2dfcdbc4be80" +dependencies = [ + "chacha20", + "getrandom 0.4.2", + "rand_core 0.10.1", +] + [[package]] name = "rand_chacha" version = "0.3.1" @@ -6293,6 +6274,12 @@ dependencies = [ "serde", ] +[[package]] +name = "rand_core" +version = "0.10.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "63b8176103e19a2643978565ca18b50549f6101881c443590420e4dc998a3c69" + [[package]] name = "rand_xorshift" version = "0.4.0" @@ -6486,57 +6473,17 @@ version = "0.4.14" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6e1dd4122fc1595e8162618945476892eefca7b88c52820e74af6262213cae8f" dependencies = [ - "aho-corasick", - "memchr", - "regex-syntax", -] - -[[package]] -name = "regex-syntax" -version = "0.8.10" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dc897dd8d9e8bd1ed8cdad82b5966c3e0ecae09fb1907d58efaa013543185d0a" - -[[package]] -name = "reqwest" -version = "0.12.28" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "eddd3ca559203180a307f12d114c268abf583f59b03cb906fd0b3ff8646c1147" -dependencies = [ - "base64 0.22.1", - "bytes", - "futures-channel", - "futures-core", - "futures-util", - "http", - "http-body", - "http-body-util", - "hyper", - "hyper-rustls", - "hyper-util", - "js-sys", - "log", - "percent-encoding", - "pin-project-lite", - "quinn", - "rustls", - "rustls-native-certs", - "rustls-pki-types", - "serde", - "serde_json", - "serde_urlencoded", - "sync_wrapper", - "tokio", - "tokio-rustls", - "tower", - "tower-http", - "tower-service", - "url", - "wasm-bindgen", - "wasm-bindgen-futures", - "web-sys", + "aho-corasick", + "memchr", + "regex-syntax", ] +[[package]] +name = "regex-syntax" +version = "0.8.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dc897dd8d9e8bd1ed8cdad82b5966c3e0ecae09fb1907d58efaa013543185d0a" + [[package]] name = "reqwest" version = "0.13.3" @@ -6587,11 +6534,11 @@ checksum = "1e061d1b48cb8d38042de4ae0a7a6401009d6143dc80d2e2d6f31f0bdd6470c7" [[package]] name = "reth-basic-payload-builder" -version = "2.2.0" -source = "git+https://github.com/paradigmxyz/reth?tag=v2.2.0#88505c7fcbfdebfd3b56d88c86b62e950043c6c4" +version = "2.4.0" +source = "git+https://github.com/paradigmxyz/reth?tag=v2.4.0#943af245c4d69c6c1df241df016c278ffb5d15df" dependencies = [ "alloy-consensus", - "alloy-eips 2.0.4", + "alloy-eips", "alloy-primitives", "futures-core", "futures-util", @@ -6614,11 +6561,11 @@ dependencies = [ [[package]] name = "reth-chain-state" -version = "2.2.0" -source = "git+https://github.com/paradigmxyz/reth?tag=v2.2.0#88505c7fcbfdebfd3b56d88c86b62e950043c6c4" +version = "2.4.0" +source = "git+https://github.com/paradigmxyz/reth?tag=v2.4.0#943af245c4d69c6c1df241df016c278ffb5d15df" dependencies = [ "alloy-consensus", - "alloy-eips 2.0.4", + "alloy-eips", "alloy-primitives", "alloy-signer", "alloy-signer-local", @@ -6635,9 +6582,10 @@ dependencies = [ "reth-metrics", "reth-primitives-traits", "reth-storage-api", + "reth-tasks", "reth-trie", - "revm-database", - "revm-state", + "reth-trie-sparse", + "revm", "serde", "tokio", "tokio-stream", @@ -6646,12 +6594,12 @@ dependencies = [ [[package]] name = "reth-chainspec" -version = "2.2.0" -source = "git+https://github.com/paradigmxyz/reth?tag=v2.2.0#88505c7fcbfdebfd3b56d88c86b62e950043c6c4" +version = "2.4.0" +source = "git+https://github.com/paradigmxyz/reth?tag=v2.4.0#943af245c4d69c6c1df241df016c278ffb5d15df" dependencies = [ "alloy-chains", "alloy-consensus", - "alloy-eips 2.0.4", + "alloy-eips", "alloy-evm", "alloy-genesis", "alloy-primitives", @@ -6666,8 +6614,8 @@ dependencies = [ [[package]] name = "reth-cli" -version = "2.2.0" -source = "git+https://github.com/paradigmxyz/reth?tag=v2.2.0#88505c7fcbfdebfd3b56d88c86b62e950043c6c4" +version = "2.4.0" +source = "git+https://github.com/paradigmxyz/reth?tag=v2.4.0#943af245c4d69c6c1df241df016c278ffb5d15df" dependencies = [ "alloy-genesis", "clap", @@ -6679,12 +6627,12 @@ dependencies = [ [[package]] name = "reth-cli-commands" -version = "2.2.0" -source = "git+https://github.com/paradigmxyz/reth?tag=v2.2.0#88505c7fcbfdebfd3b56d88c86b62e950043c6c4" +version = "2.4.0" +source = "git+https://github.com/paradigmxyz/reth?tag=v2.4.0#943af245c4d69c6c1df241df016c278ffb5d15df" dependencies = [ "alloy-chains", "alloy-consensus", - "alloy-eips 2.0.4", + "alloy-eips", "alloy-primitives", "alloy-rlp", "backon", @@ -6703,7 +6651,7 @@ dependencies = [ "parking_lot", "ratatui", "rayon", - "reqwest 0.13.3", + "reqwest", "reth-chainspec", "reth-cli", "reth-cli-runner", @@ -6751,6 +6699,7 @@ dependencies = [ "secp256k1 0.30.0", "serde", "serde_json", + "socket2", "tar", "tokio", "tokio-stream", @@ -6762,8 +6711,8 @@ dependencies = [ [[package]] name = "reth-cli-runner" -version = "2.2.0" -source = "git+https://github.com/paradigmxyz/reth?tag=v2.2.0#88505c7fcbfdebfd3b56d88c86b62e950043c6c4" +version = "2.4.0" +source = "git+https://github.com/paradigmxyz/reth?tag=v2.4.0#943af245c4d69c6c1df241df016c278ffb5d15df" dependencies = [ "reth-tasks", "tokio", @@ -6772,10 +6721,10 @@ dependencies = [ [[package]] name = "reth-cli-util" -version = "2.2.0" -source = "git+https://github.com/paradigmxyz/reth?tag=v2.2.0#88505c7fcbfdebfd3b56d88c86b62e950043c6c4" +version = "2.4.0" +source = "git+https://github.com/paradigmxyz/reth?tag=v2.4.0#943af245c4d69c6c1df241df016c278ffb5d15df" dependencies = [ - "alloy-eips 2.0.4", + "alloy-eips", "alloy-primitives", "cfg-if", "eyre", @@ -6791,12 +6740,12 @@ dependencies = [ [[package]] name = "reth-codecs" -version = "0.3.1" +version = "0.5.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fce542a96bf888f31854803e80b3340bc233927743aa580838014e8a88fe0d66" +checksum = "eb43f4858fef4e3b42b80954d2edf1ff67c8ad7498347083cdc7d0f6eff2f081" dependencies = [ "alloy-consensus", - "alloy-eips 2.0.4", + "alloy-eips", "alloy-genesis", "alloy-primitives", "alloy-trie", @@ -6812,9 +6761,9 @@ dependencies = [ [[package]] name = "reth-codecs-derive" -version = "0.3.1" +version = "0.5.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "634c90f1cc0f9887680ca785b0b21aa961070b9465917bf65afaec56a6d005bb" +checksum = "5798ae4d6b264764bc0d742468bd32c7fb515e774645d4930f95ff6311f3ae14" dependencies = [ "proc-macro2", "quote", @@ -6823,8 +6772,8 @@ dependencies = [ [[package]] name = "reth-config" -version = "2.2.0" -source = "git+https://github.com/paradigmxyz/reth?tag=v2.2.0#88505c7fcbfdebfd3b56d88c86b62e950043c6c4" +version = "2.4.0" +source = "git+https://github.com/paradigmxyz/reth?tag=v2.4.0#943af245c4d69c6c1df241df016c278ffb5d15df" dependencies = [ "eyre", "humantime-serde", @@ -6839,10 +6788,11 @@ dependencies = [ [[package]] name = "reth-consensus" -version = "2.2.0" -source = "git+https://github.com/paradigmxyz/reth?tag=v2.2.0#88505c7fcbfdebfd3b56d88c86b62e950043c6c4" +version = "2.4.0" +source = "git+https://github.com/paradigmxyz/reth?tag=v2.4.0#943af245c4d69c6c1df241df016c278ffb5d15df" dependencies = [ "alloy-consensus", + "alloy-eip7928", "alloy-primitives", "auto_impl", "reth-execution-types", @@ -6852,11 +6802,11 @@ dependencies = [ [[package]] name = "reth-consensus-common" -version = "2.2.0" -source = "git+https://github.com/paradigmxyz/reth?tag=v2.2.0#88505c7fcbfdebfd3b56d88c86b62e950043c6c4" +version = "2.4.0" +source = "git+https://github.com/paradigmxyz/reth?tag=v2.4.0#943af245c4d69c6c1df241df016c278ffb5d15df" dependencies = [ "alloy-consensus", - "alloy-eips 2.0.4", + "alloy-eips", "alloy-primitives", "reth-chainspec", "reth-consensus", @@ -6865,11 +6815,11 @@ dependencies = [ [[package]] name = "reth-consensus-debug-client" -version = "2.2.0" -source = "git+https://github.com/paradigmxyz/reth?tag=v2.2.0#88505c7fcbfdebfd3b56d88c86b62e950043c6c4" +version = "2.4.0" +source = "git+https://github.com/paradigmxyz/reth?tag=v2.4.0#943af245c4d69c6c1df241df016c278ffb5d15df" dependencies = [ "alloy-consensus", - "alloy-eips 2.0.4", + "alloy-eips", "alloy-json-rpc", "alloy-primitives", "alloy-provider", @@ -6879,9 +6829,8 @@ dependencies = [ "derive_more", "eyre", "futures", - "reqwest 0.13.3", + "reqwest", "reth-node-api", - "reth-primitives-traits", "reth-tracing", "ringbuffer", "serde", @@ -6891,8 +6840,8 @@ dependencies = [ [[package]] name = "reth-db" -version = "2.2.0" -source = "git+https://github.com/paradigmxyz/reth?tag=v2.2.0#88505c7fcbfdebfd3b56d88c86b62e950043c6c4" +version = "2.4.0" +source = "git+https://github.com/paradigmxyz/reth?tag=v2.4.0#943af245c4d69c6c1df241df016c278ffb5d15df" dependencies = [ "alloy-primitives", "derive_more", @@ -6920,8 +6869,8 @@ dependencies = [ [[package]] name = "reth-db-api" -version = "2.2.0" -source = "git+https://github.com/paradigmxyz/reth?tag=v2.2.0#88505c7fcbfdebfd3b56d88c86b62e950043c6c4" +version = "2.4.0" +source = "git+https://github.com/paradigmxyz/reth?tag=v2.4.0#943af245c4d69c6c1df241df016c278ffb5d15df" dependencies = [ "alloy-consensus", "alloy-primitives", @@ -6946,8 +6895,8 @@ dependencies = [ [[package]] name = "reth-db-common" -version = "2.2.0" -source = "git+https://github.com/paradigmxyz/reth?tag=v2.2.0#88505c7fcbfdebfd3b56d88c86b62e950043c6c4" +version = "2.4.0" +source = "git+https://github.com/paradigmxyz/reth?tag=v2.4.0#943af245c4d69c6c1df241df016c278ffb5d15df" dependencies = [ "alloy-consensus", "alloy-genesis", @@ -6976,10 +6925,10 @@ dependencies = [ [[package]] name = "reth-db-models" -version = "2.2.0" -source = "git+https://github.com/paradigmxyz/reth?tag=v2.2.0#88505c7fcbfdebfd3b56d88c86b62e950043c6c4" +version = "2.4.0" +source = "git+https://github.com/paradigmxyz/reth?tag=v2.4.0#943af245c4d69c6c1df241df016c278ffb5d15df" dependencies = [ - "alloy-eips 2.0.4", + "alloy-eips", "alloy-primitives", "arbitrary", "bytes", @@ -6991,8 +6940,8 @@ dependencies = [ [[package]] name = "reth-discv4" -version = "2.2.0" -source = "git+https://github.com/paradigmxyz/reth?tag=v2.2.0#88505c7fcbfdebfd3b56d88c86b62e950043c6c4" +version = "2.4.0" +source = "git+https://github.com/paradigmxyz/reth?tag=v2.4.0#943af245c4d69c6c1df241df016c278ffb5d15df" dependencies = [ "alloy-primitives", "alloy-rlp", @@ -7016,8 +6965,8 @@ dependencies = [ [[package]] name = "reth-discv5" -version = "2.2.0" -source = "git+https://github.com/paradigmxyz/reth?tag=v2.2.0#88505c7fcbfdebfd3b56d88c86b62e950043c6c4" +version = "2.4.0" +source = "git+https://github.com/paradigmxyz/reth?tag=v2.4.0#943af245c4d69c6c1df241df016c278ffb5d15df" dependencies = [ "alloy-primitives", "alloy-rlp", @@ -7040,8 +6989,8 @@ dependencies = [ [[package]] name = "reth-dns-discovery" -version = "2.2.0" -source = "git+https://github.com/paradigmxyz/reth?tag=v2.2.0#88505c7fcbfdebfd3b56d88c86b62e950043c6c4" +version = "2.4.0" +source = "git+https://github.com/paradigmxyz/reth?tag=v2.4.0#943af245c4d69c6c1df241df016c278ffb5d15df" dependencies = [ "alloy-primitives", "dashmap", @@ -7064,11 +7013,11 @@ dependencies = [ [[package]] name = "reth-downloaders" -version = "2.2.0" -source = "git+https://github.com/paradigmxyz/reth?tag=v2.2.0#88505c7fcbfdebfd3b56d88c86b62e950043c6c4" +version = "2.4.0" +source = "git+https://github.com/paradigmxyz/reth?tag=v2.4.0#943af245c4d69c6c1df241df016c278ffb5d15df" dependencies = [ "alloy-consensus", - "alloy-eips 2.0.4", + "alloy-eips", "alloy-primitives", "alloy-rlp", "async-compression", @@ -7099,11 +7048,11 @@ dependencies = [ [[package]] name = "reth-e2e-test-utils" -version = "2.2.0" -source = "git+https://github.com/paradigmxyz/reth?tag=v2.2.0#88505c7fcbfdebfd3b56d88c86b62e950043c6c4" +version = "2.4.0" +source = "git+https://github.com/paradigmxyz/reth?tag=v2.4.0#943af245c4d69c6c1df241df016c278ffb5d15df" dependencies = [ "alloy-consensus", - "alloy-eips 2.0.4", + "alloy-eips", "alloy-network", "alloy-primitives", "alloy-provider", @@ -7156,13 +7105,12 @@ dependencies = [ [[package]] name = "reth-ecies" -version = "2.2.0" -source = "git+https://github.com/paradigmxyz/reth?tag=v2.2.0#88505c7fcbfdebfd3b56d88c86b62e950043c6c4" +version = "2.4.0" +source = "git+https://github.com/paradigmxyz/reth?tag=v2.4.0#943af245c4d69c6c1df241df016c278ffb5d15df" dependencies = [ "aes", "alloy-primitives", "alloy-rlp", - "block-padding", "byteorder", "cipher", "concat-kdf", @@ -7184,8 +7132,8 @@ dependencies = [ [[package]] name = "reth-engine-local" -version = "2.2.0" -source = "git+https://github.com/paradigmxyz/reth?tag=v2.2.0#88505c7fcbfdebfd3b56d88c86b62e950043c6c4" +version = "2.4.0" +source = "git+https://github.com/paradigmxyz/reth?tag=v2.4.0#943af245c4d69c6c1df241df016c278ffb5d15df" dependencies = [ "alloy-consensus", "alloy-primitives", @@ -7207,11 +7155,11 @@ dependencies = [ [[package]] name = "reth-engine-primitives" -version = "2.2.0" -source = "git+https://github.com/paradigmxyz/reth?tag=v2.2.0#88505c7fcbfdebfd3b56d88c86b62e950043c6c4" +version = "2.4.0" +source = "git+https://github.com/paradigmxyz/reth?tag=v2.4.0#943af245c4d69c6c1df241df016c278ffb5d15df" dependencies = [ "alloy-consensus", - "alloy-eips 2.0.4", + "alloy-eips", "alloy-primitives", "alloy-rpc-types-engine", "auto_impl", @@ -7220,10 +7168,12 @@ dependencies = [ "reth-errors", "reth-ethereum-primitives", "reth-evm", + "reth-execution-errors", "reth-execution-types", "reth-payload-builder-primitives", "reth-payload-primitives", "reth-primitives-traits", + "reth-storage-api", "reth-trie-common", "serde", "thiserror 2.0.18", @@ -7232,12 +7182,12 @@ dependencies = [ [[package]] name = "reth-engine-tree" -version = "2.2.0" -source = "git+https://github.com/paradigmxyz/reth?tag=v2.2.0#88505c7fcbfdebfd3b56d88c86b62e950043c6c4" +version = "2.4.0" +source = "git+https://github.com/paradigmxyz/reth?tag=v2.4.0#943af245c4d69c6c1df241df016c278ffb5d15df" dependencies = [ "alloy-consensus", "alloy-eip7928", - "alloy-eips 2.0.4", + "alloy-eips", "alloy-evm", "alloy-primitives", "alloy-rlp", @@ -7248,7 +7198,6 @@ dependencies = [ "indexmap 2.14.0", "metrics", "moka", - "parking_lot", "rayon", "reth-chain-state", "reth-chainspec", @@ -7280,7 +7229,6 @@ dependencies = [ "reth-trie-parallel", "reth-trie-sparse", "revm", - "revm-primitives", "schnellru", "thiserror 2.0.18", "tokio", @@ -7289,10 +7237,12 @@ dependencies = [ [[package]] name = "reth-engine-util" -version = "2.2.0" -source = "git+https://github.com/paradigmxyz/reth?tag=v2.2.0#88505c7fcbfdebfd3b56d88c86b62e950043c6c4" +version = "2.4.0" +source = "git+https://github.com/paradigmxyz/reth?tag=v2.4.0#943af245c4d69c6c1df241df016c278ffb5d15df" dependencies = [ "alloy-consensus", + "alloy-primitives", + "alloy-rlp", "alloy-rpc-types-engine", "eyre", "futures", @@ -7317,13 +7267,15 @@ dependencies = [ [[package]] name = "reth-era" -version = "2.2.0" -source = "git+https://github.com/paradigmxyz/reth?tag=v2.2.0#88505c7fcbfdebfd3b56d88c86b62e950043c6c4" +version = "2.4.0" +source = "git+https://github.com/paradigmxyz/reth?tag=v2.4.0#943af245c4d69c6c1df241df016c278ffb5d15df" dependencies = [ "alloy-consensus", - "alloy-eips 2.0.4", + "alloy-eips", "alloy-primitives", "alloy-rlp", + "alloy-rpc-types-beacon", + "alloy-rpc-types-engine", "ethereum_ssz", "ethereum_ssz_derive", "sha2", @@ -7333,14 +7285,14 @@ dependencies = [ [[package]] name = "reth-era-downloader" -version = "2.2.0" -source = "git+https://github.com/paradigmxyz/reth?tag=v2.2.0#88505c7fcbfdebfd3b56d88c86b62e950043c6c4" +version = "2.4.0" +source = "git+https://github.com/paradigmxyz/reth?tag=v2.4.0#943af245c4d69c6c1df241df016c278ffb5d15df" dependencies = [ "alloy-primitives", "bytes", "eyre", "futures-util", - "reqwest 0.13.3", + "reqwest", "reth-era", "reth-fs-util", "sha2", @@ -7349,11 +7301,12 @@ dependencies = [ [[package]] name = "reth-era-utils" -version = "2.2.0" -source = "git+https://github.com/paradigmxyz/reth?tag=v2.2.0#88505c7fcbfdebfd3b56d88c86b62e950043c6c4" +version = "2.4.0" +source = "git+https://github.com/paradigmxyz/reth?tag=v2.4.0#943af245c4d69c6c1df241df016c278ffb5d15df" dependencies = [ "alloy-consensus", "alloy-primitives", + "alloy-rlp", "eyre", "futures-util", "reth-db-api", @@ -7371,8 +7324,8 @@ dependencies = [ [[package]] name = "reth-errors" -version = "2.2.0" -source = "git+https://github.com/paradigmxyz/reth?tag=v2.2.0#88505c7fcbfdebfd3b56d88c86b62e950043c6c4" +version = "2.4.0" +source = "git+https://github.com/paradigmxyz/reth?tag=v2.4.0#943af245c4d69c6c1df241df016c278ffb5d15df" dependencies = [ "reth-consensus", "reth-execution-errors", @@ -7382,8 +7335,8 @@ dependencies = [ [[package]] name = "reth-eth-wire" -version = "2.2.0" -source = "git+https://github.com/paradigmxyz/reth?tag=v2.2.0#88505c7fcbfdebfd3b56d88c86b62e950043c6c4" +version = "2.4.0" +source = "git+https://github.com/paradigmxyz/reth?tag=v2.4.0#943af245c4d69c6c1df241df016c278ffb5d15df" dependencies = [ "alloy-chains", "alloy-primitives", @@ -7410,13 +7363,13 @@ dependencies = [ [[package]] name = "reth-eth-wire-types" -version = "2.2.0" -source = "git+https://github.com/paradigmxyz/reth?tag=v2.2.0#88505c7fcbfdebfd3b56d88c86b62e950043c6c4" +version = "2.4.0" +source = "git+https://github.com/paradigmxyz/reth?tag=v2.4.0#943af245c4d69c6c1df241df016c278ffb5d15df" dependencies = [ "alloy-chains", "alloy-consensus", "alloy-eip7928", - "alloy-eips 2.0.4", + "alloy-eips", "alloy-hardforks", "alloy-primitives", "alloy-rlp", @@ -7432,8 +7385,8 @@ dependencies = [ [[package]] name = "reth-ethereum-cli" -version = "2.2.0" -source = "git+https://github.com/paradigmxyz/reth?tag=v2.2.0#88505c7fcbfdebfd3b56d88c86b62e950043c6c4" +version = "2.4.0" +source = "git+https://github.com/paradigmxyz/reth?tag=v2.4.0#943af245c4d69c6c1df241df016c278ffb5d15df" dependencies = [ "clap", "eyre", @@ -7455,11 +7408,11 @@ dependencies = [ [[package]] name = "reth-ethereum-consensus" -version = "2.2.0" -source = "git+https://github.com/paradigmxyz/reth?tag=v2.2.0#88505c7fcbfdebfd3b56d88c86b62e950043c6c4" +version = "2.4.0" +source = "git+https://github.com/paradigmxyz/reth?tag=v2.4.0#943af245c4d69c6c1df241df016c278ffb5d15df" dependencies = [ "alloy-consensus", - "alloy-eips 2.0.4", + "alloy-eips", "alloy-primitives", "reth-chainspec", "reth-consensus", @@ -7471,10 +7424,10 @@ dependencies = [ [[package]] name = "reth-ethereum-engine-primitives" -version = "2.2.0" -source = "git+https://github.com/paradigmxyz/reth?tag=v2.2.0#88505c7fcbfdebfd3b56d88c86b62e950043c6c4" +version = "2.4.0" +source = "git+https://github.com/paradigmxyz/reth?tag=v2.4.0#943af245c4d69c6c1df241df016c278ffb5d15df" dependencies = [ - "alloy-eips 2.0.4", + "alloy-eips", "alloy-primitives", "alloy-rpc-types-engine", "reth-engine-primitives", @@ -7487,8 +7440,8 @@ dependencies = [ [[package]] name = "reth-ethereum-forks" -version = "2.2.0" -source = "git+https://github.com/paradigmxyz/reth?tag=v2.2.0#88505c7fcbfdebfd3b56d88c86b62e950043c6c4" +version = "2.4.0" +source = "git+https://github.com/paradigmxyz/reth?tag=v2.4.0#943af245c4d69c6c1df241df016c278ffb5d15df" dependencies = [ "alloy-eip2124", "alloy-hardforks", @@ -7500,11 +7453,11 @@ dependencies = [ [[package]] name = "reth-ethereum-payload-builder" -version = "2.2.0" -source = "git+https://github.com/paradigmxyz/reth?tag=v2.2.0#88505c7fcbfdebfd3b56d88c86b62e950043c6c4" +version = "2.4.0" +source = "git+https://github.com/paradigmxyz/reth?tag=v2.4.0#943af245c4d69c6c1df241df016c278ffb5d15df" dependencies = [ "alloy-consensus", - "alloy-eips 2.0.4", + "alloy-eips", "alloy-primitives", "alloy-rlp", "alloy-rpc-types-engine", @@ -7530,11 +7483,11 @@ dependencies = [ [[package]] name = "reth-ethereum-primitives" -version = "2.2.0" -source = "git+https://github.com/paradigmxyz/reth?tag=v2.2.0#88505c7fcbfdebfd3b56d88c86b62e950043c6c4" +version = "2.4.0" +source = "git+https://github.com/paradigmxyz/reth?tag=v2.4.0#943af245c4d69c6c1df241df016c278ffb5d15df" dependencies = [ "alloy-consensus", - "alloy-eips 2.0.4", + "alloy-eips", "alloy-primitives", "alloy-rpc-types-eth", "reth-codecs", @@ -7544,8 +7497,8 @@ dependencies = [ [[package]] name = "reth-etl" -version = "2.2.0" -source = "git+https://github.com/paradigmxyz/reth?tag=v2.2.0#88505c7fcbfdebfd3b56d88c86b62e950043c6c4" +version = "2.4.0" +source = "git+https://github.com/paradigmxyz/reth?tag=v2.4.0#943af245c4d69c6c1df241df016c278ffb5d15df" dependencies = [ "rayon", "reth-db-api", @@ -7554,11 +7507,12 @@ dependencies = [ [[package]] name = "reth-evm" -version = "2.2.0" -source = "git+https://github.com/paradigmxyz/reth?tag=v2.2.0#88505c7fcbfdebfd3b56d88c86b62e950043c6c4" +version = "2.4.0" +source = "git+https://github.com/paradigmxyz/reth?tag=v2.4.0#943af245c4d69c6c1df241df016c278ffb5d15df" dependencies = [ "alloy-consensus", - "alloy-eips 2.0.4", + "alloy-eip7928", + "alloy-eips", "alloy-evm", "alloy-primitives", "auto_impl", @@ -7578,11 +7532,11 @@ dependencies = [ [[package]] name = "reth-evm-ethereum" -version = "2.2.0" -source = "git+https://github.com/paradigmxyz/reth?tag=v2.2.0#88505c7fcbfdebfd3b56d88c86b62e950043c6c4" +version = "2.4.0" +source = "git+https://github.com/paradigmxyz/reth?tag=v2.4.0#943af245c4d69c6c1df241df016c278ffb5d15df" dependencies = [ "alloy-consensus", - "alloy-eips 2.0.4", + "alloy-eips", "alloy-evm", "alloy-primitives", "alloy-rpc-types-engine", @@ -7598,8 +7552,8 @@ dependencies = [ [[package]] name = "reth-execution-cache" -version = "2.2.0" -source = "git+https://github.com/paradigmxyz/reth?tag=v2.2.0#88505c7fcbfdebfd3b56d88c86b62e950043c6c4" +version = "2.4.0" +source = "git+https://github.com/paradigmxyz/reth?tag=v2.4.0#943af245c4d69c6c1df241df016c278ffb5d15df" dependencies = [ "alloy-primitives", "fixed-cache", @@ -7616,8 +7570,8 @@ dependencies = [ [[package]] name = "reth-execution-errors" -version = "2.2.0" -source = "git+https://github.com/paradigmxyz/reth?tag=v2.2.0#88505c7fcbfdebfd3b56d88c86b62e950043c6c4" +version = "2.4.0" +source = "git+https://github.com/paradigmxyz/reth?tag=v2.4.0#943af245c4d69c6c1df241df016c278ffb5d15df" dependencies = [ "alloy-evm", "alloy-primitives", @@ -7629,11 +7583,11 @@ dependencies = [ [[package]] name = "reth-execution-types" -version = "2.2.0" -source = "git+https://github.com/paradigmxyz/reth?tag=v2.2.0#88505c7fcbfdebfd3b56d88c86b62e950043c6c4" +version = "2.4.0" +source = "git+https://github.com/paradigmxyz/reth?tag=v2.4.0#943af245c4d69c6c1df241df016c278ffb5d15df" dependencies = [ "alloy-consensus", - "alloy-eips 2.0.4", + "alloy-eips", "alloy-evm", "alloy-primitives", "alloy-rlp", @@ -7648,11 +7602,11 @@ dependencies = [ [[package]] name = "reth-exex" -version = "2.2.0" -source = "git+https://github.com/paradigmxyz/reth?tag=v2.2.0#88505c7fcbfdebfd3b56d88c86b62e950043c6c4" +version = "2.4.0" +source = "git+https://github.com/paradigmxyz/reth?tag=v2.4.0#943af245c4d69c6c1df241df016c278ffb5d15df" dependencies = [ "alloy-consensus", - "alloy-eips 2.0.4", + "alloy-eips", "alloy-primitives", "eyre", "futures", @@ -7686,10 +7640,10 @@ dependencies = [ [[package]] name = "reth-exex-types" -version = "2.2.0" -source = "git+https://github.com/paradigmxyz/reth?tag=v2.2.0#88505c7fcbfdebfd3b56d88c86b62e950043c6c4" +version = "2.4.0" +source = "git+https://github.com/paradigmxyz/reth?tag=v2.4.0#943af245c4d69c6c1df241df016c278ffb5d15df" dependencies = [ - "alloy-eips 2.0.4", + "alloy-eips", "alloy-primitives", "reth-chain-state", "reth-execution-types", @@ -7700,8 +7654,8 @@ dependencies = [ [[package]] name = "reth-fs-util" -version = "2.2.0" -source = "git+https://github.com/paradigmxyz/reth?tag=v2.2.0#88505c7fcbfdebfd3b56d88c86b62e950043c6c4" +version = "2.4.0" +source = "git+https://github.com/paradigmxyz/reth?tag=v2.4.0#943af245c4d69c6c1df241df016c278ffb5d15df" dependencies = [ "serde", "serde_json", @@ -7710,8 +7664,8 @@ dependencies = [ [[package]] name = "reth-invalid-block-hooks" -version = "2.2.0" -source = "git+https://github.com/paradigmxyz/reth?tag=v2.2.0#88505c7fcbfdebfd3b56d88c86b62e950043c6c4" +version = "2.4.0" +source = "git+https://github.com/paradigmxyz/reth?tag=v2.4.0#943af245c4d69c6c1df241df016c278ffb5d15df" dependencies = [ "alloy-consensus", "alloy-primitives", @@ -7730,16 +7684,14 @@ dependencies = [ "reth-tracing", "reth-trie", "revm", - "revm-bytecode", - "revm-database", "serde", "serde_json", ] [[package]] name = "reth-ipc" -version = "2.2.0" -source = "git+https://github.com/paradigmxyz/reth?tag=v2.2.0#88505c7fcbfdebfd3b56d88c86b62e950043c6c4" +version = "2.4.0" +source = "git+https://github.com/paradigmxyz/reth?tag=v2.4.0#943af245c4d69c6c1df241df016c278ffb5d15df" dependencies = [ "bytes", "futures", @@ -7758,8 +7710,8 @@ dependencies = [ [[package]] name = "reth-libmdbx" -version = "2.2.0" -source = "git+https://github.com/paradigmxyz/reth?tag=v2.2.0#88505c7fcbfdebfd3b56d88c86b62e950043c6c4" +version = "2.4.0" +source = "git+https://github.com/paradigmxyz/reth?tag=v2.4.0#943af245c4d69c6c1df241df016c278ffb5d15df" dependencies = [ "bitflags", "byteorder", @@ -7775,8 +7727,8 @@ dependencies = [ [[package]] name = "reth-mdbx-sys" -version = "2.2.0" -source = "git+https://github.com/paradigmxyz/reth?tag=v2.2.0#88505c7fcbfdebfd3b56d88c86b62e950043c6c4" +version = "2.4.0" +source = "git+https://github.com/paradigmxyz/reth?tag=v2.4.0#943af245c4d69c6c1df241df016c278ffb5d15df" dependencies = [ "bindgen", "cc", @@ -7784,8 +7736,8 @@ dependencies = [ [[package]] name = "reth-metrics" -version = "2.2.0" -source = "git+https://github.com/paradigmxyz/reth?tag=v2.2.0#88505c7fcbfdebfd3b56d88c86b62e950043c6c4" +version = "2.4.0" +source = "git+https://github.com/paradigmxyz/reth?tag=v2.4.0#943af245c4d69c6c1df241df016c278ffb5d15df" dependencies = [ "futures", "metrics", @@ -7797,8 +7749,8 @@ dependencies = [ [[package]] name = "reth-net-banlist" -version = "2.2.0" -source = "git+https://github.com/paradigmxyz/reth?tag=v2.2.0#88505c7fcbfdebfd3b56d88c86b62e950043c6c4" +version = "2.4.0" +source = "git+https://github.com/paradigmxyz/reth?tag=v2.4.0#943af245c4d69c6c1df241df016c278ffb5d15df" dependencies = [ "alloy-primitives", "ipnet", @@ -7806,12 +7758,12 @@ dependencies = [ [[package]] name = "reth-net-nat" -version = "2.2.0" -source = "git+https://github.com/paradigmxyz/reth?tag=v2.2.0#88505c7fcbfdebfd3b56d88c86b62e950043c6c4" +version = "2.4.0" +source = "git+https://github.com/paradigmxyz/reth?tag=v2.4.0#943af245c4d69c6c1df241df016c278ffb5d15df" dependencies = [ "futures-util", "if-addrs", - "reqwest 0.13.3", + "reqwest", "serde_with", "thiserror 2.0.18", "tokio", @@ -7820,11 +7772,11 @@ dependencies = [ [[package]] name = "reth-network" -version = "2.2.0" -source = "git+https://github.com/paradigmxyz/reth?tag=v2.2.0#88505c7fcbfdebfd3b56d88c86b62e950043c6c4" +version = "2.4.0" +source = "git+https://github.com/paradigmxyz/reth?tag=v2.4.0#943af245c4d69c6c1df241df016c278ffb5d15df" dependencies = [ "alloy-consensus", - "alloy-eips 2.0.4", + "alloy-eips", "alloy-primitives", "alloy-rlp", "aquamarine", @@ -7878,8 +7830,8 @@ dependencies = [ [[package]] name = "reth-network-api" -version = "2.2.0" -source = "git+https://github.com/paradigmxyz/reth?tag=v2.2.0#88505c7fcbfdebfd3b56d88c86b62e950043c6c4" +version = "2.4.0" +source = "git+https://github.com/paradigmxyz/reth?tag=v2.4.0#943af245c4d69c6c1df241df016c278ffb5d15df" dependencies = [ "alloy-consensus", "alloy-primitives", @@ -7903,11 +7855,12 @@ dependencies = [ [[package]] name = "reth-network-p2p" -version = "2.2.0" -source = "git+https://github.com/paradigmxyz/reth?tag=v2.2.0#88505c7fcbfdebfd3b56d88c86b62e950043c6c4" +version = "2.4.0" +source = "git+https://github.com/paradigmxyz/reth?tag=v2.4.0#943af245c4d69c6c1df241df016c278ffb5d15df" dependencies = [ "alloy-consensus", - "alloy-eips 2.0.4", + "alloy-eip7928", + "alloy-eips", "alloy-primitives", "auto_impl", "derive_more", @@ -7926,8 +7879,8 @@ dependencies = [ [[package]] name = "reth-network-peers" -version = "2.2.0" -source = "git+https://github.com/paradigmxyz/reth?tag=v2.2.0#88505c7fcbfdebfd3b56d88c86b62e950043c6c4" +version = "2.4.0" +source = "git+https://github.com/paradigmxyz/reth?tag=v2.4.0#943af245c4d69c6c1df241df016c278ffb5d15df" dependencies = [ "alloy-primitives", "alloy-rlp", @@ -7941,8 +7894,8 @@ dependencies = [ [[package]] name = "reth-network-types" -version = "2.2.0" -source = "git+https://github.com/paradigmxyz/reth?tag=v2.2.0#88505c7fcbfdebfd3b56d88c86b62e950043c6c4" +version = "2.4.0" +source = "git+https://github.com/paradigmxyz/reth?tag=v2.4.0#943af245c4d69c6c1df241df016c278ffb5d15df" dependencies = [ "alloy-eip2124", "humantime-serde", @@ -7955,8 +7908,8 @@ dependencies = [ [[package]] name = "reth-nippy-jar" -version = "2.2.0" -source = "git+https://github.com/paradigmxyz/reth?tag=v2.2.0#88505c7fcbfdebfd3b56d88c86b62e950043c6c4" +version = "2.4.0" +source = "git+https://github.com/paradigmxyz/reth?tag=v2.4.0#943af245c4d69c6c1df241df016c278ffb5d15df" dependencies = [ "anyhow", "bincode", @@ -7972,8 +7925,8 @@ dependencies = [ [[package]] name = "reth-node-api" -version = "2.2.0" -source = "git+https://github.com/paradigmxyz/reth?tag=v2.2.0#88505c7fcbfdebfd3b56d88c86b62e950043c6c4" +version = "2.4.0" +source = "git+https://github.com/paradigmxyz/reth?tag=v2.4.0#943af245c4d69c6c1df241df016c278ffb5d15df" dependencies = [ "alloy-rpc-types-engine", "eyre", @@ -7996,11 +7949,11 @@ dependencies = [ [[package]] name = "reth-node-builder" -version = "2.2.0" -source = "git+https://github.com/paradigmxyz/reth?tag=v2.2.0#88505c7fcbfdebfd3b56d88c86b62e950043c6c4" +version = "2.4.0" +source = "git+https://github.com/paradigmxyz/reth?tag=v2.4.0#943af245c4d69c6c1df241df016c278ffb5d15df" dependencies = [ "alloy-consensus", - "alloy-eips 2.0.4", + "alloy-eips", "alloy-primitives", "alloy-provider", "alloy-rpc-types", @@ -8064,11 +8017,11 @@ dependencies = [ [[package]] name = "reth-node-core" -version = "2.2.0" -source = "git+https://github.com/paradigmxyz/reth?tag=v2.2.0#88505c7fcbfdebfd3b56d88c86b62e950043c6c4" +version = "2.4.0" +source = "git+https://github.com/paradigmxyz/reth?tag=v2.4.0#943af245c4d69c6c1df241df016c278ffb5d15df" dependencies = [ "alloy-consensus", - "alloy-eips 2.0.4", + "alloy-eips", "alloy-primitives", "alloy-rpc-types-engine", "clap", @@ -8119,14 +8072,20 @@ dependencies = [ [[package]] name = "reth-node-ethereum" -version = "2.2.0" -source = "git+https://github.com/paradigmxyz/reth?tag=v2.2.0#88505c7fcbfdebfd3b56d88c86b62e950043c6c4" +version = "2.4.0" +source = "git+https://github.com/paradigmxyz/reth?tag=v2.4.0#943af245c4d69c6c1df241df016c278ffb5d15df" dependencies = [ - "alloy-eips 2.0.4", + "alloy-consensus", + "alloy-eips", "alloy-network", + "alloy-primitives", "alloy-rpc-types-engine", "alloy-rpc-types-eth", + "ethereum_ssz", + "ethereum_ssz_derive", "eyre", + "http-body-util", + "jsonrpsee", "reth-chainspec", "reth-engine-local", "reth-engine-primitives", @@ -8139,6 +8098,7 @@ dependencies = [ "reth-network", "reth-node-api", "reth-node-builder", + "reth-node-core", "reth-payload-primitives", "reth-primitives-traits", "reth-provider", @@ -8152,13 +8112,16 @@ dependencies = [ "reth-tracing", "reth-transaction-pool", "revm", + "serde", + "serde_json", "tokio", + "tower", ] [[package]] name = "reth-node-ethstats" -version = "2.2.0" -source = "git+https://github.com/paradigmxyz/reth?tag=v2.2.0#88505c7fcbfdebfd3b56d88c86b62e950043c6c4" +version = "2.4.0" +source = "git+https://github.com/paradigmxyz/reth?tag=v2.4.0#943af245c4d69c6c1df241df016c278ffb5d15df" dependencies = [ "alloy-consensus", "alloy-primitives", @@ -8181,11 +8144,11 @@ dependencies = [ [[package]] name = "reth-node-events" -version = "2.2.0" -source = "git+https://github.com/paradigmxyz/reth?tag=v2.2.0#88505c7fcbfdebfd3b56d88c86b62e950043c6c4" +version = "2.4.0" +source = "git+https://github.com/paradigmxyz/reth?tag=v2.4.0#943af245c4d69c6c1df241df016c278ffb5d15df" dependencies = [ "alloy-consensus", - "alloy-eips 2.0.4", + "alloy-eips", "alloy-primitives", "alloy-rpc-types-engine", "derive_more", @@ -8205,8 +8168,8 @@ dependencies = [ [[package]] name = "reth-node-metrics" -version = "2.2.0" -source = "git+https://github.com/paradigmxyz/reth?tag=v2.2.0#88505c7fcbfdebfd3b56d88c86b62e950043c6c4" +version = "2.4.0" +source = "git+https://github.com/paradigmxyz/reth?tag=v2.4.0#943af245c4d69c6c1df241df016c278ffb5d15df" dependencies = [ "bytes", "eyre", @@ -8221,7 +8184,7 @@ dependencies = [ "metrics-util", "pprof_util", "procfs", - "reqwest 0.13.3", + "reqwest", "reth-fs-util", "reth-metrics", "reth-tasks", @@ -8234,8 +8197,8 @@ dependencies = [ [[package]] name = "reth-node-types" -version = "2.2.0" -source = "git+https://github.com/paradigmxyz/reth?tag=v2.2.0#88505c7fcbfdebfd3b56d88c86b62e950043c6c4" +version = "2.4.0" +source = "git+https://github.com/paradigmxyz/reth?tag=v2.4.0#943af245c4d69c6c1df241df016c278ffb5d15df" dependencies = [ "reth-chainspec", "reth-db-api", @@ -8246,8 +8209,8 @@ dependencies = [ [[package]] name = "reth-payload-builder" -version = "2.2.0" -source = "git+https://github.com/paradigmxyz/reth?tag=v2.2.0#88505c7fcbfdebfd3b56d88c86b62e950043c6c4" +version = "2.4.0" +source = "git+https://github.com/paradigmxyz/reth?tag=v2.4.0#943af245c4d69c6c1df241df016c278ffb5d15df" dependencies = [ "alloy-consensus", "alloy-primitives", @@ -8270,8 +8233,8 @@ dependencies = [ [[package]] name = "reth-payload-builder-primitives" -version = "2.2.0" -source = "git+https://github.com/paradigmxyz/reth?tag=v2.2.0#88505c7fcbfdebfd3b56d88c86b62e950043c6c4" +version = "2.4.0" +source = "git+https://github.com/paradigmxyz/reth?tag=v2.4.0#943af245c4d69c6c1df241df016c278ffb5d15df" dependencies = [ "pin-project", "reth-payload-primitives", @@ -8282,17 +8245,16 @@ dependencies = [ [[package]] name = "reth-payload-primitives" -version = "2.2.0" -source = "git+https://github.com/paradigmxyz/reth?tag=v2.2.0#88505c7fcbfdebfd3b56d88c86b62e950043c6c4" +version = "2.4.0" +source = "git+https://github.com/paradigmxyz/reth?tag=v2.4.0#943af245c4d69c6c1df241df016c278ffb5d15df" dependencies = [ "alloy-consensus", - "alloy-eips 2.0.4", + "alloy-eips", "alloy-primitives", "alloy-rlp", "alloy-rpc-types-engine", "auto_impl", "either", - "reth-chain-state", "reth-chainspec", "reth-errors", "reth-execution-types", @@ -8306,8 +8268,8 @@ dependencies = [ [[package]] name = "reth-payload-util" -version = "2.2.0" -source = "git+https://github.com/paradigmxyz/reth?tag=v2.2.0#88505c7fcbfdebfd3b56d88c86b62e950043c6c4" +version = "2.4.0" +source = "git+https://github.com/paradigmxyz/reth?tag=v2.4.0#943af245c4d69c6c1df241df016c278ffb5d15df" dependencies = [ "alloy-consensus", "alloy-primitives", @@ -8316,8 +8278,8 @@ dependencies = [ [[package]] name = "reth-payload-validator" -version = "2.2.0" -source = "git+https://github.com/paradigmxyz/reth?tag=v2.2.0#88505c7fcbfdebfd3b56d88c86b62e950043c6c4" +version = "2.4.0" +source = "git+https://github.com/paradigmxyz/reth?tag=v2.4.0#943af245c4d69c6c1df241df016c278ffb5d15df" dependencies = [ "alloy-consensus", "alloy-rpc-types-engine", @@ -8326,12 +8288,12 @@ dependencies = [ [[package]] name = "reth-primitives-traits" -version = "0.3.1" +version = "0.5.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8ee12e304adbacbb32248c9806ebafbe1e2811fbfefe53c5e5b710a8438b7ec0" +checksum = "f59c928b2865af5bcdbce94800270b7f7798f27a22ca0aabdd2b7d3e6587c9ce" dependencies = [ "alloy-consensus", - "alloy-eips 2.0.4", + "alloy-eips", "alloy-genesis", "alloy-primitives", "alloy-rlp", @@ -8359,11 +8321,12 @@ dependencies = [ [[package]] name = "reth-provider" -version = "2.2.0" -source = "git+https://github.com/paradigmxyz/reth?tag=v2.2.0#88505c7fcbfdebfd3b56d88c86b62e950043c6c4" +version = "2.4.0" +source = "git+https://github.com/paradigmxyz/reth?tag=v2.4.0#943af245c4d69c6c1df241df016c278ffb5d15df" dependencies = [ "alloy-consensus", - "alloy-eips 2.0.4", + "alloy-eip7928", + "alloy-eips", "alloy-genesis", "alloy-primitives", "alloy-rpc-types-engine", @@ -8393,11 +8356,12 @@ dependencies = [ "reth-storage-api", "reth-storage-errors", "reth-tasks", + "reth-tokio-util", "reth-trie", "reth-trie-db", - "revm-database", - "revm-state", + "revm", "rocksdb", + "smallvec", "strum", "tokio", "tracing", @@ -8405,15 +8369,13 @@ dependencies = [ [[package]] name = "reth-prune" -version = "2.2.0" -source = "git+https://github.com/paradigmxyz/reth?tag=v2.2.0#88505c7fcbfdebfd3b56d88c86b62e950043c6c4" +version = "2.4.0" +source = "git+https://github.com/paradigmxyz/reth?tag=v2.4.0#943af245c4d69c6c1df241df016c278ffb5d15df" dependencies = [ "alloy-consensus", - "alloy-eips 2.0.4", "alloy-primitives", "itertools 0.14.0", "metrics", - "rayon", "reth-config", "reth-db-api", "reth-errors", @@ -8434,8 +8396,8 @@ dependencies = [ [[package]] name = "reth-prune-types" -version = "2.2.0" -source = "git+https://github.com/paradigmxyz/reth?tag=v2.2.0#88505c7fcbfdebfd3b56d88c86b62e950043c6c4" +version = "2.4.0" +source = "git+https://github.com/paradigmxyz/reth?tag=v2.4.0#943af245c4d69c6c1df241df016c278ffb5d15df" dependencies = [ "alloy-primitives", "arbitrary", @@ -8450,8 +8412,8 @@ dependencies = [ [[package]] name = "reth-revm" -version = "2.2.0" -source = "git+https://github.com/paradigmxyz/reth?tag=v2.2.0#88505c7fcbfdebfd3b56d88c86b62e950043c6c4" +version = "2.4.0" +source = "git+https://github.com/paradigmxyz/reth?tag=v2.4.0#943af245c4d69c6c1df241df016c278ffb5d15df" dependencies = [ "alloy-primitives", "alloy-rlp", @@ -8465,12 +8427,13 @@ dependencies = [ [[package]] name = "reth-rpc" -version = "2.2.0" -source = "git+https://github.com/paradigmxyz/reth?tag=v2.2.0#88505c7fcbfdebfd3b56d88c86b62e950043c6c4" +version = "2.4.0" +source = "git+https://github.com/paradigmxyz/reth?tag=v2.4.0#943af245c4d69c6c1df241df016c278ffb5d15df" dependencies = [ "alloy-consensus", "alloy-dyn-abi", - "alloy-eips 2.0.4", + "alloy-eip7928", + "alloy-eips", "alloy-evm", "alloy-genesis", "alloy-network", @@ -8486,7 +8449,7 @@ dependencies = [ "alloy-rpc-types-mev", "alloy-rpc-types-trace", "alloy-rpc-types-txpool", - "alloy-serde 2.0.4", + "alloy-serde", "alloy-signer", "alloy-signer-local", "async-trait", @@ -8514,6 +8477,7 @@ dependencies = [ "reth-network-peers", "reth-network-types", "reth-node-api", + "reth-payload-primitives", "reth-primitives-traits", "reth-revm", "reth-rpc-api", @@ -8524,12 +8488,10 @@ dependencies = [ "reth-rpc-server-types", "reth-storage-api", "reth-tasks", - "reth-tracing", "reth-transaction-pool", "reth-trie-common", "revm", "revm-inspectors", - "revm-primitives", "serde", "serde_json", "sha2", @@ -8542,10 +8504,10 @@ dependencies = [ [[package]] name = "reth-rpc-api" -version = "2.2.0" -source = "git+https://github.com/paradigmxyz/reth?tag=v2.2.0#88505c7fcbfdebfd3b56d88c86b62e950043c6c4" +version = "2.4.0" +source = "git+https://github.com/paradigmxyz/reth?tag=v2.4.0#943af245c4d69c6c1df241df016c278ffb5d15df" dependencies = [ - "alloy-eips 2.0.4", + "alloy-eips", "alloy-genesis", "alloy-json-rpc", "alloy-primitives", @@ -8559,7 +8521,7 @@ dependencies = [ "alloy-rpc-types-mev", "alloy-rpc-types-trace", "alloy-rpc-types-txpool", - "alloy-serde 2.0.4", + "alloy-serde", "jsonrpsee", "reth-chain-state", "reth-engine-primitives", @@ -8572,8 +8534,8 @@ dependencies = [ [[package]] name = "reth-rpc-builder" -version = "2.2.0" -source = "git+https://github.com/paradigmxyz/reth?tag=v2.2.0#88505c7fcbfdebfd3b56d88c86b62e950043c6c4" +version = "2.4.0" +source = "git+https://github.com/paradigmxyz/reth?tag=v2.4.0#943af245c4d69c6c1df241df016c278ffb5d15df" dependencies = [ "alloy-network", "alloy-provider", @@ -8615,8 +8577,8 @@ dependencies = [ [[package]] name = "reth-rpc-convert" -version = "2.2.0" -source = "git+https://github.com/paradigmxyz/reth?tag=v2.2.0#88505c7fcbfdebfd3b56d88c86b62e950043c6c4" +version = "2.4.0" +source = "git+https://github.com/paradigmxyz/reth?tag=v2.4.0#943af245c4d69c6c1df241df016c278ffb5d15df" dependencies = [ "alloy-consensus", "alloy-evm", @@ -8635,10 +8597,10 @@ dependencies = [ [[package]] name = "reth-rpc-engine-api" -version = "2.2.0" -source = "git+https://github.com/paradigmxyz/reth?tag=v2.2.0#88505c7fcbfdebfd3b56d88c86b62e950043c6c4" +version = "2.4.0" +source = "git+https://github.com/paradigmxyz/reth?tag=v2.4.0#943af245c4d69c6c1df241df016c278ffb5d15df" dependencies = [ - "alloy-eips 2.0.4", + "alloy-eips", "alloy-primitives", "alloy-rlp", "alloy-rpc-types-engine", @@ -8666,13 +8628,13 @@ dependencies = [ [[package]] name = "reth-rpc-eth-api" -version = "2.2.0" -source = "git+https://github.com/paradigmxyz/reth?tag=v2.2.0#88505c7fcbfdebfd3b56d88c86b62e950043c6c4" +version = "2.4.0" +source = "git+https://github.com/paradigmxyz/reth?tag=v2.4.0#943af245c4d69c6c1df241df016c278ffb5d15df" dependencies = [ "alloy-consensus", "alloy-dyn-abi", "alloy-eip7928", - "alloy-eips 2.0.4", + "alloy-eips", "alloy-evm", "alloy-json-rpc", "alloy-network", @@ -8680,7 +8642,7 @@ dependencies = [ "alloy-rlp", "alloy-rpc-types-eth", "alloy-rpc-types-mev", - "alloy-serde 2.0.4", + "alloy-serde", "async-trait", "auto_impl", "dyn-clone", @@ -8695,6 +8657,7 @@ dependencies = [ "reth-network-api", "reth-node-api", "reth-primitives-traits", + "reth-prune-types", "reth-revm", "reth-rpc-convert", "reth-rpc-eth-types", @@ -8712,16 +8675,19 @@ dependencies = [ [[package]] name = "reth-rpc-eth-types" -version = "2.2.0" -source = "git+https://github.com/paradigmxyz/reth?tag=v2.2.0#88505c7fcbfdebfd3b56d88c86b62e950043c6c4" +version = "2.4.0" +source = "git+https://github.com/paradigmxyz/reth?tag=v2.4.0#943af245c4d69c6c1df241df016c278ffb5d15df" dependencies = [ + "alloy-chains", "alloy-consensus", - "alloy-eips 2.0.4", + "alloy-eip7928", + "alloy-eips", "alloy-evm", "alloy-network", "alloy-primitives", "alloy-rpc-client", "alloy-rpc-types-eth", + "alloy-serde", "alloy-sol-types", "alloy-transport", "derive_more", @@ -8731,7 +8697,7 @@ dependencies = [ "jsonrpsee-types", "metrics", "rand 0.9.4", - "reqwest 0.13.3", + "reqwest", "reth-chain-state", "reth-chainspec", "reth-errors", @@ -8760,8 +8726,8 @@ dependencies = [ [[package]] name = "reth-rpc-layer" -version = "2.2.0" -source = "git+https://github.com/paradigmxyz/reth?tag=v2.2.0#88505c7fcbfdebfd3b56d88c86b62e950043c6c4" +version = "2.4.0" +source = "git+https://github.com/paradigmxyz/reth?tag=v2.4.0#943af245c4d69c6c1df241df016c278ffb5d15df" dependencies = [ "alloy-rpc-types-engine", "http", @@ -8774,10 +8740,10 @@ dependencies = [ [[package]] name = "reth-rpc-server-types" -version = "2.2.0" -source = "git+https://github.com/paradigmxyz/reth?tag=v2.2.0#88505c7fcbfdebfd3b56d88c86b62e950043c6c4" +version = "2.4.0" +source = "git+https://github.com/paradigmxyz/reth?tag=v2.4.0#943af245c4d69c6c1df241df016c278ffb5d15df" dependencies = [ - "alloy-eips 2.0.4", + "alloy-eips", "alloy-primitives", "alloy-rpc-types-engine", "jsonrpsee-core", @@ -8790,9 +8756,9 @@ dependencies = [ [[package]] name = "reth-rpc-traits" -version = "0.3.1" +version = "0.5.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "860fe223501a76ff14aa3bf164f739f31008c2a2905ac85708bfd88f042e6151" +checksum = "ace77dbcdd59c014fda4565ebfec76cd1fe6f5d98584b4655e8d22a947b9eee3" dependencies = [ "alloy-consensus", "alloy-network", @@ -8805,11 +8771,10 @@ dependencies = [ [[package]] name = "reth-stages" -version = "2.2.0" -source = "git+https://github.com/paradigmxyz/reth?tag=v2.2.0#88505c7fcbfdebfd3b56d88c86b62e950043c6c4" +version = "2.4.0" +source = "git+https://github.com/paradigmxyz/reth?tag=v2.4.0#943af245c4d69c6c1df241df016c278ffb5d15df" dependencies = [ "alloy-consensus", - "alloy-eips 2.0.4", "alloy-primitives", "alloy-rlp", "eyre", @@ -8818,7 +8783,7 @@ dependencies = [ "num-traits", "page_size", "rayon", - "reqwest 0.13.3", + "reqwest", "reth-chainspec", "reth-codecs", "reth-config", @@ -8857,10 +8822,10 @@ dependencies = [ [[package]] name = "reth-stages-api" -version = "2.2.0" -source = "git+https://github.com/paradigmxyz/reth?tag=v2.2.0#88505c7fcbfdebfd3b56d88c86b62e950043c6c4" +version = "2.4.0" +source = "git+https://github.com/paradigmxyz/reth?tag=v2.4.0#943af245c4d69c6c1df241df016c278ffb5d15df" dependencies = [ - "alloy-eips 2.0.4", + "alloy-eips", "alloy-primitives", "aquamarine", "auto_impl", @@ -8885,8 +8850,8 @@ dependencies = [ [[package]] name = "reth-stages-types" -version = "2.2.0" -source = "git+https://github.com/paradigmxyz/reth?tag=v2.2.0#88505c7fcbfdebfd3b56d88c86b62e950043c6c4" +version = "2.4.0" +source = "git+https://github.com/paradigmxyz/reth?tag=v2.4.0#943af245c4d69c6c1df241df016c278ffb5d15df" dependencies = [ "alloy-primitives", "arbitrary", @@ -8899,8 +8864,8 @@ dependencies = [ [[package]] name = "reth-static-file" -version = "2.2.0" -source = "git+https://github.com/paradigmxyz/reth?tag=v2.2.0#88505c7fcbfdebfd3b56d88c86b62e950043c6c4" +version = "2.4.0" +source = "git+https://github.com/paradigmxyz/reth?tag=v2.4.0#943af245c4d69c6c1df241df016c278ffb5d15df" dependencies = [ "alloy-primitives", "parking_lot", @@ -8919,8 +8884,8 @@ dependencies = [ [[package]] name = "reth-static-file-types" -version = "2.2.0" -source = "git+https://github.com/paradigmxyz/reth?tag=v2.2.0#88505c7fcbfdebfd3b56d88c86b62e950043c6c4" +version = "2.4.0" +source = "git+https://github.com/paradigmxyz/reth?tag=v2.4.0#943af245c4d69c6c1df241df016c278ffb5d15df" dependencies = [ "alloy-primitives", "clap", @@ -8934,11 +8899,12 @@ dependencies = [ [[package]] name = "reth-storage-api" -version = "2.2.0" -source = "git+https://github.com/paradigmxyz/reth?tag=v2.2.0#88505c7fcbfdebfd3b56d88c86b62e950043c6c4" +version = "2.4.0" +source = "git+https://github.com/paradigmxyz/reth?tag=v2.4.0#943af245c4d69c6c1df241df016c278ffb5d15df" dependencies = [ "alloy-consensus", - "alloy-eips 2.0.4", + "alloy-eip7928", + "alloy-eips", "alloy-primitives", "alloy-rpc-types-engine", "auto_impl", @@ -8951,17 +8917,18 @@ dependencies = [ "reth-prune-types", "reth-stages-types", "reth-storage-errors", + "reth-tokio-util", "reth-trie-common", - "revm-database", + "revm", "serde_json", ] [[package]] name = "reth-storage-errors" -version = "2.2.0" -source = "git+https://github.com/paradigmxyz/reth?tag=v2.2.0#88505c7fcbfdebfd3b56d88c86b62e950043c6c4" +version = "2.4.0" +source = "git+https://github.com/paradigmxyz/reth?tag=v2.4.0#943af245c4d69c6c1df241df016c278ffb5d15df" dependencies = [ - "alloy-eips 2.0.4", + "alloy-eips", "alloy-primitives", "alloy-rlp", "derive_more", @@ -8969,15 +8936,14 @@ dependencies = [ "reth-primitives-traits", "reth-prune-types", "reth-static-file-types", - "revm-database-interface", - "revm-state", + "revm", "thiserror 2.0.18", ] [[package]] name = "reth-tasks" -version = "2.2.0" -source = "git+https://github.com/paradigmxyz/reth?tag=v2.2.0#88505c7fcbfdebfd3b56d88c86b62e950043c6c4" +version = "2.4.0" +source = "git+https://github.com/paradigmxyz/reth?tag=v2.4.0#943af245c4d69c6c1df241df016c278ffb5d15df" dependencies = [ "crossbeam-utils", "dashmap", @@ -8997,11 +8963,11 @@ dependencies = [ [[package]] name = "reth-testing-utils" -version = "2.2.0" -source = "git+https://github.com/paradigmxyz/reth?tag=v2.2.0#88505c7fcbfdebfd3b56d88c86b62e950043c6c4" +version = "2.4.0" +source = "git+https://github.com/paradigmxyz/reth?tag=v2.4.0#943af245c4d69c6c1df241df016c278ffb5d15df" dependencies = [ "alloy-consensus", - "alloy-eips 2.0.4", + "alloy-eips", "alloy-genesis", "alloy-primitives", "rand 0.8.6", @@ -9013,8 +8979,8 @@ dependencies = [ [[package]] name = "reth-tokio-util" -version = "2.2.0" -source = "git+https://github.com/paradigmxyz/reth?tag=v2.2.0#88505c7fcbfdebfd3b56d88c86b62e950043c6c4" +version = "2.4.0" +source = "git+https://github.com/paradigmxyz/reth?tag=v2.4.0#943af245c4d69c6c1df241df016c278ffb5d15df" dependencies = [ "tokio", "tokio-stream", @@ -9023,8 +8989,8 @@ dependencies = [ [[package]] name = "reth-tracing" -version = "2.2.0" -source = "git+https://github.com/paradigmxyz/reth?tag=v2.2.0#88505c7fcbfdebfd3b56d88c86b62e950043c6c4" +version = "2.4.0" +source = "git+https://github.com/paradigmxyz/reth?tag=v2.4.0#943af245c4d69c6c1df241df016c278ffb5d15df" dependencies = [ "clap", "eyre", @@ -9032,6 +8998,7 @@ dependencies = [ "rolling-file", "tracing", "tracing-appender", + "tracing-chrome", "tracing-journald", "tracing-logfmt", "tracing-samply", @@ -9040,9 +9007,10 @@ dependencies = [ [[package]] name = "reth-tracing-otlp" -version = "2.2.0" -source = "git+https://github.com/paradigmxyz/reth?tag=v2.2.0#88505c7fcbfdebfd3b56d88c86b62e950043c6c4" +version = "2.4.0" +source = "git+https://github.com/paradigmxyz/reth?tag=v2.4.0#943af245c4d69c6c1df241df016c278ffb5d15df" dependencies = [ + "base64 0.22.1", "clap", "eyre", "opentelemetry", @@ -9057,11 +9025,11 @@ dependencies = [ [[package]] name = "reth-transaction-pool" -version = "2.2.0" -source = "git+https://github.com/paradigmxyz/reth?tag=v2.2.0#88505c7fcbfdebfd3b56d88c86b62e950043c6c4" +version = "2.4.0" +source = "git+https://github.com/paradigmxyz/reth?tag=v2.4.0#943af245c4d69c6c1df241df016c278ffb5d15df" dependencies = [ "alloy-consensus", - "alloy-eips 2.0.4", + "alloy-eips", "alloy-primitives", "alloy-rlp", "aquamarine", @@ -9087,8 +9055,6 @@ dependencies = [ "reth-storage-api", "reth-tasks", "revm", - "revm-interpreter", - "revm-primitives", "rustc-hash", "schnellru", "serde", @@ -9102,11 +9068,11 @@ dependencies = [ [[package]] name = "reth-trie" -version = "2.2.0" -source = "git+https://github.com/paradigmxyz/reth?tag=v2.2.0#88505c7fcbfdebfd3b56d88c86b62e950043c6c4" +version = "2.4.0" +source = "git+https://github.com/paradigmxyz/reth?tag=v2.4.0#943af245c4d69c6c1df241df016c278ffb5d15df" dependencies = [ "alloy-consensus", - "alloy-eips 2.0.4", + "alloy-eips", "alloy-primitives", "alloy-rlp", "alloy-trie", @@ -9121,21 +9087,20 @@ dependencies = [ "reth-storage-errors", "reth-trie-common", "reth-trie-sparse", - "revm-database", "tracing", "triehash", ] [[package]] name = "reth-trie-common" -version = "2.2.0" -source = "git+https://github.com/paradigmxyz/reth?tag=v2.2.0#88505c7fcbfdebfd3b56d88c86b62e950043c6c4" +version = "2.4.0" +source = "git+https://github.com/paradigmxyz/reth?tag=v2.4.0#943af245c4d69c6c1df241df016c278ffb5d15df" dependencies = [ "alloy-consensus", "alloy-primitives", "alloy-rlp", "alloy-rpc-types-eth", - "alloy-serde 2.0.4", + "alloy-serde", "alloy-trie", "arbitrary", "arrayvec", @@ -9148,15 +9113,15 @@ dependencies = [ "rayon", "reth-codecs", "reth-primitives-traits", - "revm-database", + "revm", "serde", "serde_with", ] [[package]] name = "reth-trie-db" -version = "2.2.0" -source = "git+https://github.com/paradigmxyz/reth?tag=v2.2.0#88505c7fcbfdebfd3b56d88c86b62e950043c6c4" +version = "2.4.0" +source = "git+https://github.com/paradigmxyz/reth?tag=v2.4.0#943af245c4d69c6c1df241df016c278ffb5d15df" dependencies = [ "alloy-primitives", "metrics", @@ -9165,7 +9130,6 @@ dependencies = [ "reth-execution-errors", "reth-metrics", "reth-primitives-traits", - "reth-stages-types", "reth-storage-api", "reth-storage-errors", "reth-trie", @@ -9175,19 +9139,15 @@ dependencies = [ [[package]] name = "reth-trie-parallel" -version = "2.2.0" -source = "git+https://github.com/paradigmxyz/reth?tag=v2.2.0#88505c7fcbfdebfd3b56d88c86b62e950043c6c4" +version = "2.4.0" +source = "git+https://github.com/paradigmxyz/reth?tag=v2.4.0#943af245c4d69c6c1df241df016c278ffb5d15df" dependencies = [ - "alloy-eip7928", "alloy-evm", "alloy-primitives", "alloy-rlp", "crossbeam-channel", "crossbeam-utils", - "derive_more", - "itertools 0.14.0", "metrics", - "rayon", "reth-execution-errors", "reth-metrics", "reth-primitives-traits", @@ -9196,19 +9156,19 @@ dependencies = [ "reth-tasks", "reth-trie", "reth-trie-sparse", - "revm-state", + "revm", "thiserror 2.0.18", "tracing", ] [[package]] name = "reth-trie-sparse" -version = "2.2.0" -source = "git+https://github.com/paradigmxyz/reth?tag=v2.2.0#88505c7fcbfdebfd3b56d88c86b62e950043c6c4" +version = "2.4.0" +source = "git+https://github.com/paradigmxyz/reth?tag=v2.4.0#943af245c4d69c6c1df241df016c278ffb5d15df" dependencies = [ "alloy-primitives", - "alloy-rlp", "alloy-trie", + "either", "metrics", "rayon", "reth-execution-errors", @@ -9219,23 +9179,24 @@ dependencies = [ "serde_json", "slotmap", "smallvec", + "strum", "tracing", ] [[package]] name = "reth-zstd-compressors" -version = "0.3.1" +version = "0.5.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c12fafa33d2f420a9d39249a3e0357b1928d09429f30758b85280409092873b2" +checksum = "e1bd4ae4f54a2ba813eef082910bc646bd31cab8ed134308fa71f1068331fb84" dependencies = [ "zstd", ] [[package]] name = "revm" -version = "38.0.0" +version = "41.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "91202d39dbe8e8d10e9e8f2b76c30da68ecd1d25be69ba6d853ad0d03a3a398a" +checksum = "9d51c254839fb36357d0b02d02e46ba57e683d7b017e2da33b47ae74685a9e59" dependencies = [ "revm-bytecode", "revm-context", @@ -9252,9 +9213,9 @@ dependencies = [ [[package]] name = "revm-bytecode" -version = "10.0.0" +version = "41.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bdbb3a3d735efa94c91f2ef6bf20a35f99a77bc78f3e25bd758336901bdf9661" +checksum = "e33493cf6d996e9242db4f2002caef48ec9aa8c4f3fff3b18aed10ef3942eec7" dependencies = [ "bitvec", "phf", @@ -9264,9 +9225,9 @@ dependencies = [ [[package]] name = "revm-context" -version = "16.0.1" +version = "41.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c5f68d928d8b228e0faeb1c6ed75c4fde7d124f1ddf9119b67e7a0ad4041237d" +checksum = "86e48fc736d9542c082ea5305be44b6a14b53a615f0147ad57f62189fd813068" dependencies = [ "bitvec", "cfg-if", @@ -9281,9 +9242,9 @@ dependencies = [ [[package]] name = "revm-context-interface" -version = "17.0.1" +version = "41.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1f3758e6167c4ba7a59a689c519a047edaefcd4c37d74f279b93ed87bc8aece4" +checksum = "ac68282a454318246817486835a446519291dd0a8167d09de14c7e96f2147696" dependencies = [ "alloy-eip2930", "alloy-eip7702", @@ -9297,11 +9258,13 @@ dependencies = [ [[package]] name = "revm-database" -version = "13.0.1" +version = "41.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c281a1f11d3bcb8c0bba1199ed6bcb001d1aeb3d4fb366819e14f88723989a4e" +checksum = "d761681a43e48408ea23f7f66ff56ff7b6128cadb8f9135d1b94787d0c0fc6b4" dependencies = [ - "alloy-eips 1.8.3", + "alloy-eips", + "derive_more", + "either", "revm-bytecode", "revm-database-interface", "revm-primitives", @@ -9311,9 +9274,9 @@ dependencies = [ [[package]] name = "revm-database-interface" -version = "11.0.1" +version = "41.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d89efb9832a4e3742bb4ded5f7fe5bf905e8860e69427d4dfec153484fc6d304" +checksum = "b96e37d62fa60b45987b408486c84ebef4af4e7ddf1b3b96b4955a7263fd4e92" dependencies = [ "auto_impl", "either", @@ -9325,9 +9288,9 @@ dependencies = [ [[package]] name = "revm-handler" -version = "18.1.0" +version = "41.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "783e903d6922b7f5f9a940d1bb229530502d2924b1aed9d5ca5a94ebf065d460" +checksum = "f5e043ebfc0899c435e44475796285898e4f822e637bd67856da79cc170bd9df" dependencies = [ "auto_impl", "derive-where", @@ -9344,9 +9307,9 @@ dependencies = [ [[package]] name = "revm-inspector" -version = "19.0.0" +version = "41.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8216ad58422090d0daa9eb430e0a081f7ad07e7fd30681dee71f8420c99624e0" +checksum = "2e470b2a5e177918944d8cd26174455b61b8fbfbbe7fe411d28b4097e410d11e" dependencies = [ "auto_impl", "either", @@ -9362,9 +9325,9 @@ dependencies = [ [[package]] name = "revm-inspectors" -version = "0.39.0" +version = "0.41.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "731b682530a732ef9c189ef831589128e2ce34d4a306c956322ae2dffe009715" +checksum = "54e22e1aa328f78e8c3dea6a3a860a3a3c3a77c4a7e775e3fdd3dcbb24a152ac" dependencies = [ "alloy-primitives", "alloy-rpc-types-eth", @@ -9380,9 +9343,9 @@ dependencies = [ [[package]] name = "revm-interpreter" -version = "35.0.1" +version = "41.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1ece9f41b69658c15d748288a4dbdfc06a63f3ce93d983af440de3f1631dce6a" +checksum = "fa5547f653f9e4c47b4f9a9075a0b7c0faea5fa29b7873f392733a943837825d" dependencies = [ "revm-bytecode", "revm-context-interface", @@ -9393,9 +9356,9 @@ dependencies = [ [[package]] name = "revm-precompile" -version = "34.0.0" +version = "41.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a346a8cc6c8c39bd65306641c692191299c0a7b63d38810e39e8fe9b92378660" +checksum = "6d785931e4b8750cf9d79c808c22f05979c8d191baafc8badd4651db82584c1c" dependencies = [ "ark-bls12-381", "ark-bn254", @@ -9419,24 +9382,24 @@ dependencies = [ [[package]] name = "revm-primitives" -version = "23.0.0" +version = "41.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0c99bda77d9661521ba0b4bc04558c6692074f01e65dd420fa3b893033d9b8a2" +checksum = "66f39151a31afe93d97f7ac894dd9dcc989368d5ccba19ce079bfc1d73b77452" dependencies = [ "alloy-primitives", - "num_enum", "once_cell", "serde", ] [[package]] name = "revm-state" -version = "11.0.1" +version = "41.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c32490ed687dba31c3c882beb8c20408bdd30ef96690d8f145b0ee9a87040bfe" +checksum = "73ef2fffc28acc41e8ef7525f2b1d16288a10f80579a1b33e7e62abc9892314a" dependencies = [ "alloy-eip7928", "bitflags", + "nonmax", "revm-bytecode", "revm-primitives", "serde", @@ -9444,9 +9407,9 @@ dependencies = [ [[package]] name = "revm-statetest-types" -version = "17.0.1" +version = "41.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "94743de1e54a812077b79dd3a87b4059175a804650b21582fb6feae96ef2be9c" +checksum = "d9ced634104a9857185f02a7a3a5dd4a503590fababafbb295ad213df6dbf302" dependencies = [ "alloy-eip7928", "k256", @@ -9650,7 +9613,7 @@ dependencies = [ "errno", "libc", "linux-raw-sys", - "windows-sys 0.59.0", + "windows-sys 0.61.2", ] [[package]] @@ -9697,7 +9660,7 @@ version = "0.5.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "19787cda76408ec5404443dc8b31795c87cd8fec49762dc75fa727740d34acc1" dependencies = [ - "core-foundation", + "core-foundation 0.10.1", "core-foundation-sys", "jni 0.21.1", "log", @@ -9718,7 +9681,7 @@ version = "0.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "26d1e2536ce4f35f4846aa13bff16bd0ff40157cdb14cc056c7b14ba41233ba0" dependencies = [ - "core-foundation", + "core-foundation 0.10.1", "core-foundation-sys", "jni 0.22.4", "log", @@ -9730,7 +9693,7 @@ dependencies = [ "security-framework", "security-framework-sys", "webpki-root-certs 1.0.7", - "windows-sys 0.59.0", + "windows-sys 0.61.2", ] [[package]] @@ -9912,7 +9875,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b7f4bc775c73d9a02cde8bf7b2ec4c9d12743edf609006c7facc23998404cd1d" dependencies = [ "bitflags", - "core-foundation", + "core-foundation 0.10.1", "core-foundation-sys", "libc", "security-framework-sys", @@ -9942,10 +9905,6 @@ name = "semver" version = "1.0.28" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8a7852d02fc848982e0c167ef163aaff9cd91dc640ba85e263cb1ce46fae51cd" -dependencies = [ - "serde", - "serde_core", -] [[package]] name = "semver-parser" @@ -10058,7 +10017,7 @@ version = "3.19.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "cf2ebbe86054f9b45bc3881e865683ccfaccce97b9b4cb53f3039d67f355a334" dependencies = [ - "darling 0.23.0", + "darling", "proc-macro2", "quote", "syn 2.0.117", @@ -10103,7 +10062,17 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "77fd7028345d415a4034cf8777cd4f8ab1851274233b45f84e3d955502d93874" dependencies = [ "digest 0.10.7", - "keccak", + "keccak 0.1.6", +] + +[[package]] +name = "sha3" +version = "0.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "be176f1a57ce4e3d31c1a166222d9768de5954f811601fb7ca06fc8203905ce1" +dependencies = [ + "digest 0.11.3", + "keccak 0.2.0", ] [[package]] @@ -10256,7 +10225,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3a766e1110788c36f4fa1c2b71b387a7815aa65f88ce0229841826633d93723e" dependencies = [ "libc", - "windows-sys 0.60.2", + "windows-sys 0.61.2", ] [[package]] @@ -10360,9 +10329,9 @@ dependencies = [ [[package]] name = "syn-solidity" -version = "1.5.7" +version = "1.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "53f425ae0b12e2f5ae65542e00898d500d4d318b4baf09f40fd0d410454e9947" +checksum = "ec005042c7d952febc1a3ef5b0f6674e9054aa836877a31c90b20e25b3d31744" dependencies = [ "paste", "proc-macro2", @@ -10404,6 +10373,27 @@ dependencies = [ "windows 0.62.2", ] +[[package]] +name = "system-configuration" +version = "0.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a13f3d0daba03132c0aa9767f98351b3488edc2c100cda2d2ec2b04f3d8d3c8b" +dependencies = [ + "bitflags", + "core-foundation 0.9.4", + "system-configuration-sys", +] + +[[package]] +name = "system-configuration-sys" +version = "0.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8e1d1b10ced5ca923a1fcb8d03e96b8d3268065d724548c0211415ff6ac6bac4" +dependencies = [ + "core-foundation-sys", + "libc", +] + [[package]] name = "tagptr" version = "0.2.0" @@ -10437,7 +10427,7 @@ dependencies = [ "getrandom 0.4.2", "once_cell", "rustix", - "windows-sys 0.59.0", + "windows-sys 0.61.2", ] [[package]] @@ -10545,12 +10535,11 @@ dependencies = [ [[package]] name = "time" -version = "0.3.47" +version = "0.3.53" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "743bd48c283afc0388f9b8827b976905fb217ad9e647fae3a379a9283c4def2c" +checksum = "18dfaaeddcb932337b5e7866ee7d0ce9b76d2fd092997146f187ec09b4558a50" dependencies = [ "deranged", - "itoa", "libc", "num-conv", "num_threads", @@ -10562,15 +10551,15 @@ dependencies = [ [[package]] name = "time-core" -version = "0.1.8" +version = "0.1.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7694e1cfe791f8d31026952abf09c69ca6f6fa4e1a1229e18988f06a04a12dca" +checksum = "9e1c906769ad99c88eaa54e728060edef082f8e358ff32030cb7c7d315e81109" [[package]] name = "time-macros" -version = "0.2.27" +version = "0.2.31" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2e70e4c5a0e0a8a4823ad65dfe1a6930e4f4d756dcd9dd7939022b5e8c501215" +checksum = "c431b87111666e491a90baa837f914fb45cd5dc3c268591b0220ff5057f2085f" dependencies = [ "num-conv", "time-core", @@ -10603,9 +10592,9 @@ checksum = "1f3ccbac311fea05f86f61904b462b55fb3df8837a366dfc601a0161d0532f20" [[package]] name = "tokio" -version = "1.52.2" +version = "1.52.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "110a78583f19d5cdb2c5ccf321d1290344e71313c6c37d43520d386027d18386" +checksum = "8fc7f01b389ac15039e4dc9531aa973a135d7a4135281b12d7c1bc79fd57fffe" dependencies = [ "bytes", "libc", @@ -10780,6 +10769,17 @@ dependencies = [ "tonic", ] +[[package]] +name = "tonic-types" +version = "0.14.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "73ab1b02061f83d519bba3caa167f88f261ef05720ab8ebc954ade70de3348e8" +dependencies = [ + "prost", + "prost-types", + "tonic", +] + [[package]] name = "tower" version = "0.5.3" @@ -10879,6 +10879,17 @@ dependencies = [ "syn 2.0.117", ] +[[package]] +name = "tracing-chrome" +version = "0.7.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bf0a738ed5d6450a9fb96e86a23ad808de2b727fd1394585da5cdd6788ffe724" +dependencies = [ + "serde_json", + "tracing-core", + "tracing-subscriber 0.3.23", +] + [[package]] name = "tracing-core" version = "0.1.36" @@ -10935,9 +10946,9 @@ dependencies = [ [[package]] name = "tracing-opentelemetry" -version = "0.32.1" +version = "0.33.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1ac28f2d093c6c477eaa76b23525478f38de514fa9aeb1285738d4b97a9552fc" +checksum = "adbc64cba7137545b8044cb1fe9814f7aacf3c6b5f9b45be8bb5db538befdb26" dependencies = [ "js-sys", "opentelemetry", @@ -11024,7 +11035,7 @@ version = "0.12.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8840ad4d852e325d3afa7fde8a50b2412f89dce47d7eb291c0cc7f87cd040f38" dependencies = [ - "darling 0.23.0", + "darling", "proc-macro2", "quote", "syn 2.0.117", @@ -11160,7 +11171,7 @@ version = "0.5.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "fc1de2c688dc15305988b563c3854064043356019f97a4b46276fe734c4f07ea" dependencies = [ - "crypto-common", + "crypto-common 0.1.7", "subtle", ] @@ -11238,14 +11249,12 @@ checksum = "accd4ea62f7bb7a82fe23066fb0957d48ef677f6eeb8215f372f52e48bb32426" [[package]] name = "vergen" -version = "9.1.0" +version = "10.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b849a1f6d8639e8de261e81ee0fc881e3e3620db1af9f2e0da015d4382ceaf75" +checksum = "b5574dd2f922b1a46a06a4b1dc11193a4012108fd54cf725e1816cb8183d8778" dependencies = [ "anyhow", - "cargo_metadata", - "derive_builder", - "regex", + "bon", "rustversion", "time", "vergen-lib", @@ -11253,12 +11262,12 @@ dependencies = [ [[package]] name = "vergen-git2" -version = "9.1.0" +version = "10.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d51ab55ddf1188c8d679f349775362b0fa9e90bd7a4ac69838b2a087623f0d57" +checksum = "410e2f72acce10471037150cd9c585ee7b54560f348bf70cd5fc8e87d3433e45" dependencies = [ "anyhow", - "derive_builder", + "bon", "git2", "rustversion", "time", @@ -11268,12 +11277,12 @@ dependencies = [ [[package]] name = "vergen-lib" -version = "9.1.0" +version = "10.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b34a29ba7e9c59e62f229ae1932fb1b8fb8a6fdcc99215a641913f5f5a59a569" +checksum = "8cd42fd155c2c2971f6d00face12ec245fbb604fce011ccaf2306d014c2e97ca" dependencies = [ "anyhow", - "derive_builder", + "bon", "rustversion", ] @@ -11556,7 +11565,7 @@ version = "0.1.11" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c2a7b1c03c876122aa43f3020e6c3c3ee5c05081c9a00739faf7503aeba10d22" dependencies = [ - "windows-sys 0.59.0", + "windows-sys 0.61.2", ] [[package]] @@ -12011,9 +12020,6 @@ name = "winnow" version = "0.7.15" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "df79d97927682d2fd8adb29682d1140b343be4ac0f08fd68b7765d9c059d3945" -dependencies = [ - "memchr", -] [[package]] name = "winnow" diff --git a/Cargo.toml b/Cargo.toml index a9b4e0f..eae76ed 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,7 +1,7 @@ [workspace.package] version = "1.0.0" edition = "2024" -rust-version = "1.93" +rust-version = "1.95" license = "MIT OR Apache-2.0" publish = false @@ -13,7 +13,6 @@ members = [ "crates/chainspec", "crates/consensus", "crates/engine-api", - "crates/engine-tree-ext", "crates/evm", "crates/node", "crates/rpc", @@ -90,7 +89,6 @@ codegen-units = 1 morph-chainspec = { path = "crates/chainspec", default-features = false } morph-consensus = { path = "crates/consensus", default-features = false } morph-engine-api = { path = "crates/engine-api", default-features = false } -morph-engine-tree-ext = { path = "crates/engine-tree-ext", default-features = false } morph-evm = { path = "crates/evm", default-features = false } morph-node = { path = "crates/node"} morph-payload-builder = { path = "crates/payload/builder", default-features = false } @@ -101,98 +99,98 @@ morph-rpc = { path = "crates/rpc" } morph-revm = { path = "crates/revm", default-features = false } morph-txpool = { path = "crates/txpool", default-features = false } -reth-basic-payload-builder = { git = "https://github.com/paradigmxyz/reth", tag = "v2.2.0" } -reth-chain-state = { git = "https://github.com/paradigmxyz/reth", tag = "v2.2.0" } -reth-chainspec = { git = "https://github.com/paradigmxyz/reth", tag = "v2.2.0" } -reth-cli = { git = "https://github.com/paradigmxyz/reth", tag = "v2.2.0" } -reth-cli-commands = { git = "https://github.com/paradigmxyz/reth", tag = "v2.2.0" } -reth-cli-util = { git = "https://github.com/paradigmxyz/reth", tag = "v2.2.0" } -reth-codecs = { version = "0.3.1", default-features = false } -reth-codecs-derive = "0.3.1" -reth-consensus = { git = "https://github.com/paradigmxyz/reth", tag = "v2.2.0" } -reth-consensus-common = { git = "https://github.com/paradigmxyz/reth", tag = "v2.2.0" } -reth-db = { git = "https://github.com/paradigmxyz/reth", tag = "v2.2.0" } -reth-db-api = { git = "https://github.com/paradigmxyz/reth", tag = "v2.2.0" } -reth-e2e-test-utils = { git = "https://github.com/paradigmxyz/reth", tag = "v2.2.0" } -reth-engine-local = { git = "https://github.com/paradigmxyz/reth", tag = "v2.2.0" } -reth-engine-primitives = { git = "https://github.com/paradigmxyz/reth", tag = "v2.2.0" } -reth-engine-tree = { git = "https://github.com/paradigmxyz/reth", tag = "v2.2.0" } -reth-errors = { git = "https://github.com/paradigmxyz/reth", tag = "v2.2.0" } -reth-eth-wire-types = { git = "https://github.com/paradigmxyz/reth", tag = "v2.2.0" } -reth-exex = { git = "https://github.com/paradigmxyz/reth", tag = "v2.2.0" } -reth-exex-test-utils = { git = "https://github.com/paradigmxyz/reth", tag = "v2.2.0" } -reth-exex-types = { git = "https://github.com/paradigmxyz/reth", tag = "v2.2.0" } -reth-ethereum = { git = "https://github.com/paradigmxyz/reth", tag = "v2.2.0" } -reth-ethereum-cli = { git = "https://github.com/paradigmxyz/reth", tag = "v2.2.0" } -reth-ethereum-consensus = { git = "https://github.com/paradigmxyz/reth", tag = "v2.2.0" } -reth-ethereum-engine-primitives = { git = "https://github.com/paradigmxyz/reth", tag = "v2.2.0" } -reth-ethereum-primitives = { git = "https://github.com/paradigmxyz/reth", tag = "v2.2.0", default-features = false } -reth-evm = { git = "https://github.com/paradigmxyz/reth", tag = "v2.2.0" } -reth-evm-ethereum = { git = "https://github.com/paradigmxyz/reth", tag = "v2.2.0" } -reth-execution-types = { git = "https://github.com/paradigmxyz/reth", tag = "v2.2.0" } -reth-metrics = { git = "https://github.com/paradigmxyz/reth", tag = "v2.2.0" } -reth-network-peers = { git = "https://github.com/paradigmxyz/reth", tag = "v2.2.0" } -reth-node-api = { git = "https://github.com/paradigmxyz/reth", tag = "v2.2.0" } -reth-node-builder = { git = "https://github.com/paradigmxyz/reth", tag = "v2.2.0" } -reth-node-core = { git = "https://github.com/paradigmxyz/reth", tag = "v2.2.0" } -reth-node-ethereum = { git = "https://github.com/paradigmxyz/reth", tag = "v2.2.0" } -reth-node-metrics = { git = "https://github.com/paradigmxyz/reth", tag = "v2.2.0" } -reth-payload-builder = { git = "https://github.com/paradigmxyz/reth", tag = "v2.2.0" } -reth-payload-primitives = { git = "https://github.com/paradigmxyz/reth", tag = "v2.2.0" } -reth-payload-util = { git = "https://github.com/paradigmxyz/reth", tag = "v2.2.0" } -reth-primitives-traits = { version = "0.3.1", default-features = false } -reth-provider = { git = "https://github.com/paradigmxyz/reth", tag = "v2.2.0" } -reth-rpc = { git = "https://github.com/paradigmxyz/reth", tag = "v2.2.0" } -reth-rpc-api = { git = "https://github.com/paradigmxyz/reth", tag = "v2.2.0" } -reth-rpc-builder = { git = "https://github.com/paradigmxyz/reth", tag = "v2.2.0" } -reth-rpc-convert = { git = "https://github.com/paradigmxyz/reth", tag = "v2.2.0" } -reth-rpc-eth-api = { git = "https://github.com/paradigmxyz/reth", tag = "v2.2.0" } -reth-rpc-eth-types = { git = "https://github.com/paradigmxyz/reth", tag = "v2.2.0" } -reth-rpc-server-types = { git = "https://github.com/paradigmxyz/reth", tag = "v2.2.0" } -reth-storage-api = { git = "https://github.com/paradigmxyz/reth", tag = "v2.2.0" } -reth-tasks = { git = "https://github.com/paradigmxyz/reth", tag = "v2.2.0" } -reth-tracing = { git = "https://github.com/paradigmxyz/reth", tag = "v2.2.0" } -reth-trie = { git = "https://github.com/paradigmxyz/reth", tag = "v2.2.0" } -reth-transaction-pool = { git = "https://github.com/paradigmxyz/reth", tag = "v2.2.0" } -reth-zstd-compressors = { version = "0.3.1", default-features = false } -reth-execution-cache = { git = "https://github.com/paradigmxyz/reth", tag = "v2.2.0" } -reth-trie-db = { git = "https://github.com/paradigmxyz/reth", tag = "v2.2.0" } -reth-trie-parallel = { git = "https://github.com/paradigmxyz/reth", tag = "v2.2.0" } -reth-trie-sparse = { git = "https://github.com/paradigmxyz/reth", tag = "v2.2.0", default-features = false } +reth-basic-payload-builder = { git = "https://github.com/paradigmxyz/reth", tag = "v2.4.0" } +reth-chain-state = { git = "https://github.com/paradigmxyz/reth", tag = "v2.4.0" } +reth-chainspec = { git = "https://github.com/paradigmxyz/reth", tag = "v2.4.0" } +reth-cli = { git = "https://github.com/paradigmxyz/reth", tag = "v2.4.0" } +reth-cli-commands = { git = "https://github.com/paradigmxyz/reth", tag = "v2.4.0" } +reth-cli-util = { git = "https://github.com/paradigmxyz/reth", tag = "v2.4.0" } +reth-codecs = { version = "0.5.0", default-features = false } +reth-codecs-derive = "0.5.0" +reth-consensus = { git = "https://github.com/paradigmxyz/reth", tag = "v2.4.0" } +reth-consensus-common = { git = "https://github.com/paradigmxyz/reth", tag = "v2.4.0" } +reth-db = { git = "https://github.com/paradigmxyz/reth", tag = "v2.4.0" } +reth-db-api = { git = "https://github.com/paradigmxyz/reth", tag = "v2.4.0" } +reth-e2e-test-utils = { git = "https://github.com/paradigmxyz/reth", tag = "v2.4.0" } +reth-engine-local = { git = "https://github.com/paradigmxyz/reth", tag = "v2.4.0" } +reth-engine-primitives = { git = "https://github.com/paradigmxyz/reth", tag = "v2.4.0" } +reth-engine-tree = { git = "https://github.com/paradigmxyz/reth", tag = "v2.4.0" } +reth-errors = { git = "https://github.com/paradigmxyz/reth", tag = "v2.4.0" } +reth-eth-wire-types = { git = "https://github.com/paradigmxyz/reth", tag = "v2.4.0" } +reth-exex = { git = "https://github.com/paradigmxyz/reth", tag = "v2.4.0" } +reth-exex-test-utils = { git = "https://github.com/paradigmxyz/reth", tag = "v2.4.0" } +reth-exex-types = { git = "https://github.com/paradigmxyz/reth", tag = "v2.4.0" } +reth-ethereum = { git = "https://github.com/paradigmxyz/reth", tag = "v2.4.0" } +reth-ethereum-cli = { git = "https://github.com/paradigmxyz/reth", tag = "v2.4.0" } +reth-ethereum-consensus = { git = "https://github.com/paradigmxyz/reth", tag = "v2.4.0" } +reth-ethereum-engine-primitives = { git = "https://github.com/paradigmxyz/reth", tag = "v2.4.0" } +reth-ethereum-primitives = { git = "https://github.com/paradigmxyz/reth", tag = "v2.4.0", default-features = false } +reth-evm = { git = "https://github.com/paradigmxyz/reth", tag = "v2.4.0" } +reth-evm-ethereum = { git = "https://github.com/paradigmxyz/reth", tag = "v2.4.0" } +reth-execution-types = { git = "https://github.com/paradigmxyz/reth", tag = "v2.4.0" } +reth-metrics = { git = "https://github.com/paradigmxyz/reth", tag = "v2.4.0" } +reth-network-peers = { git = "https://github.com/paradigmxyz/reth", tag = "v2.4.0" } +reth-node-api = { git = "https://github.com/paradigmxyz/reth", tag = "v2.4.0" } +reth-node-builder = { git = "https://github.com/paradigmxyz/reth", tag = "v2.4.0" } +reth-node-core = { git = "https://github.com/paradigmxyz/reth", tag = "v2.4.0" } +reth-node-ethereum = { git = "https://github.com/paradigmxyz/reth", tag = "v2.4.0" } +reth-node-metrics = { git = "https://github.com/paradigmxyz/reth", tag = "v2.4.0" } +reth-payload-builder = { git = "https://github.com/paradigmxyz/reth", tag = "v2.4.0" } +reth-payload-primitives = { git = "https://github.com/paradigmxyz/reth", tag = "v2.4.0" } +reth-payload-util = { git = "https://github.com/paradigmxyz/reth", tag = "v2.4.0" } +reth-primitives-traits = { version = "0.5.0", default-features = false } +reth-provider = { git = "https://github.com/paradigmxyz/reth", tag = "v2.4.0" } +reth-rpc = { git = "https://github.com/paradigmxyz/reth", tag = "v2.4.0" } +reth-rpc-api = { git = "https://github.com/paradigmxyz/reth", tag = "v2.4.0" } +reth-rpc-builder = { git = "https://github.com/paradigmxyz/reth", tag = "v2.4.0" } +reth-rpc-convert = { git = "https://github.com/paradigmxyz/reth", tag = "v2.4.0" } +reth-rpc-eth-api = { git = "https://github.com/paradigmxyz/reth", tag = "v2.4.0" } +reth-rpc-eth-types = { git = "https://github.com/paradigmxyz/reth", tag = "v2.4.0" } +reth-rpc-server-types = { git = "https://github.com/paradigmxyz/reth", tag = "v2.4.0" } +reth-storage-api = { git = "https://github.com/paradigmxyz/reth", tag = "v2.4.0" } +reth-tasks = { git = "https://github.com/paradigmxyz/reth", tag = "v2.4.0" } +reth-tracing = { git = "https://github.com/paradigmxyz/reth", tag = "v2.4.0" } +reth-trie = { git = "https://github.com/paradigmxyz/reth", tag = "v2.4.0" } +reth-transaction-pool = { git = "https://github.com/paradigmxyz/reth", tag = "v2.4.0" } +reth-zstd-compressors = { version = "0.5.0", default-features = false } +reth-execution-cache = { git = "https://github.com/paradigmxyz/reth", tag = "v2.4.0" } +reth-trie-db = { git = "https://github.com/paradigmxyz/reth", tag = "v2.4.0" } +reth-trie-parallel = { git = "https://github.com/paradigmxyz/reth", tag = "v2.4.0" } +reth-trie-sparse = { git = "https://github.com/paradigmxyz/reth", tag = "v2.4.0", default-features = false } -reth-revm = { git = "https://github.com/paradigmxyz/reth", tag = "v2.2.0", features = [ +reth-revm = { git = "https://github.com/paradigmxyz/reth", tag = "v2.4.0", features = [ "std", "optional-checks", ] } -revm = { version = "38.0.0", features = [ +revm = { version = "41.0.0", features = [ "optional_fee_charge", "optional_eip7623", ], default-features = false } -alloy = { version = "2.0.4", default-features = false } -alloy-consensus = { version = "2.0.4", default-features = false } -alloy-contract = { version = "2.0.4", default-features = false } -alloy-eip7928 = { version = "0.3.4", default-features = false } -alloy-eips = { version = "2.0.4", default-features = false } -alloy-evm = { version = "0.34.0", default-features = false } -alloy-genesis = "2.0.4" +alloy = { version = "2.1.1", default-features = false } +alloy-consensus = { version = "2.1.1", default-features = false } +alloy-contract = { version = "2.1.1", default-features = false } +alloy-eip7928 = { version = "0.4.5", default-features = false } +alloy-eips = { version = "2.1.1", default-features = false } +alloy-evm = { version = "0.37.0", default-features = false } +alloy-genesis = "2.1.1" alloy-hardforks = "0.4.7" -alloy-network = { version = "2.0.4", default-features = false } -alloy-primitives = { version = "1.5.6", default-features = false } -alloy-provider = { version = "2.0.4", default-features = false } -alloy-rlp = "0.3.13" -alloy-trie = "0.9.5" -alloy-rpc-types-engine = "2.0.4" -alloy-rpc-types-eth = { version = "2.0.4" } -alloy-serde = "2.0.4" -alloy-signer = "2.0.4" -alloy-signer-local = "2.0.4" -alloy-sol-types = { version = "1.5.6", default-features = false } -alloy-transport = "2.0.4" +alloy-network = { version = "2.1.1", default-features = false } +alloy-primitives = { version = "1.6.0", default-features = false } +alloy-provider = { version = "2.1.1", default-features = false } +alloy-rlp = "0.3.16" +alloy-trie = "0.9.4" +alloy-rpc-types-engine = "2.1.1" +alloy-rpc-types-eth = { version = "2.1.1" } +alloy-serde = "2.1.1" +alloy-signer = "2.1.1" +alloy-signer-local = "2.1.1" +alloy-sol-types = { version = "1.6.0", default-features = false } +alloy-transport = "2.1.1" alloy-chains = { version = "0.2.33", default-features = false } crossbeam-channel = "0.5.13" -revm-primitives = { version = "23.0.0", default-features = false } -revm-statetest-types = { version = "17.0.1", default-features = false } +revm-primitives = { version = "41.0.0", default-features = false } +revm-statetest-types = { version = "41.0.0", default-features = false } arbitrary = { version = "1.3", features = ["derive"] } async-lock = "3.4.1" async-trait = "0.1" @@ -234,8 +232,8 @@ tokio-stream = "0.1.17" tokio-util = "0.7.16" tracing = "0.1.41" tracing-subscriber = "0.3.22" -vergen = "9.1.0" -vergen-git2 = "9.1.0" +vergen = "10.0.1" +vergen-git2 = "10.0.1" criterion = "0.7.0" test-case = "3" pyroscope = "0.5.8" diff --git a/crates/chainspec/src/hardfork.rs b/crates/chainspec/src/hardfork.rs index 42d7518..63b005b 100644 --- a/crates/chainspec/src/hardfork.rs +++ b/crates/chainspec/src/hardfork.rs @@ -234,7 +234,7 @@ mod tests { let params = GasParams::new_spec(spec); assert_eq!( - params.tx_eip7702_per_auth_state_gas(), + params.tx_eip7702_state_gas(), 0, "MorphHardfork {fork:?} must not enable EIP-8037 state gas" ); @@ -245,15 +245,14 @@ mod tests { fn test_eip7702_refund_stays_regular_for_morph_specs() { for spec in [SpecId::CANCUN, SpecId::PRAGUE, SpecId::OSAKA] { let params = GasParams::new_spec(spec); - let total_refund = 25_000; - let (state_refund, regular_refund) = params.split_eip7702_refund(total_refund); - assert_eq!( - state_refund, 0, + params.tx_eip7702_state_refund(2, 2), + 0, "spec={spec:?}: Morph must not route EIP-7702 refunds to state gas" ); assert_eq!( - regular_refund, total_refund, + params.tx_eip7702_auth_refund_regular(), + params.tx_eip7702_auth_refund(), "spec={spec:?}: Morph EIP-7702 refunds must remain subject to the regular refund cap" ); } diff --git a/crates/consensus/src/validation.rs b/crates/consensus/src/validation.rs index 3b32297..cd12183 100644 --- a/crates/consensus/src/validation.rs +++ b/crates/consensus/src/validation.rs @@ -89,7 +89,7 @@ const GAS_LIMIT_BOUND_DIVISOR: u64 = 1024; /// start, have sequential queue indices, and are consistent with `header.next_l1_msg_index`. /// 2. **Cross-block monotonicity** (`validate_header_against_parent`): `header.next_l1_msg_index` /// is monotonically non-decreasing relative to the parent. -/// 3. **Parent-aware exactness** (`MorphBasicEngineValidator`): once the engine tree has +/// 3. **Parent-aware exactness** (`MorphTreeEngineValidator`): once the engine tree has /// both parent header and block body, Jade blocks must exactly match the value derived /// from `parent.next_l1_msg_index` and the block's leading L1 messages. /// @@ -356,6 +356,7 @@ impl FullConsensus for MorphConsensus { block: &RecoveredBlock, result: &BlockExecutionResult, receipt_root_bloom: Option, + _block_access_list_hash: Option, ) -> Result<(), ConsensusError> { // Verify the block gas used let cumulative_gas_used = result @@ -2070,7 +2071,7 @@ mod tests { let recovered = reth_primitives_traits::RecoveredBlock::new_unhashed(block, vec![Address::ZERO]); - let post_result = consensus.validate_block_post_execution(&recovered, &result, None); + let post_result = consensus.validate_block_post_execution(&recovered, &result, None, None); assert!(matches!( post_result, Err(ConsensusError::BlockGasUsed { .. }) diff --git a/crates/engine-api/src/builder.rs b/crates/engine-api/src/builder.rs index 390e5a1..26aa0e3 100644 --- a/crates/engine-api/src/builder.rs +++ b/crates/engine-api/src/builder.rs @@ -725,6 +725,7 @@ impl RealMorphL2EngineApi { parent_beacon_block_root: None, // Morph L2 has no PoS slot semantics; introduced in alloy 2.0. slot_number: None, + target_gas_limit: None, }, transactions: Some(params.transactions), gas_limit: gas_limit_override, @@ -737,7 +738,7 @@ impl RealMorphL2EngineApi { attributes: rpc_attributes, parent_hash, cache: None, - trie_handle: None, + state_root_handle: None, }; let _ = self .payload_builder diff --git a/crates/engine-tree-ext/Cargo.toml b/crates/engine-tree-ext/Cargo.toml deleted file mode 100644 index 255e6c8..0000000 --- a/crates/engine-tree-ext/Cargo.toml +++ /dev/null @@ -1,80 +0,0 @@ -[package] -name = "morph-engine-tree-ext" -version.workspace = true -edition.workspace = true -rust-version.workspace = true -license.workspace = true -publish.workspace = true - -[lints] -workspace = true - -[dependencies] -# morph local crates -morph-chainspec = { workspace = true } -# morph-primitives brought in transitively via morph-chainspec; direct dep here -# enables the reth-codec feature so cargo test -p morph-engine-tree-ext satisfies -# NodePrimitives::Receipt: FullReceipt (requires Compact impl). -morph-primitives = { workspace = true, features = ["reth-codec"] } - -# reth (workspace = true after Task 4 flips root Cargo.toml to paradigmxyz/reth v2.0.0) -reth-chain-state = { workspace = true } -reth-consensus = { workspace = true } -reth-db = { workspace = true } -reth-engine-primitives = { workspace = true } -reth-engine-tree = { workspace = true } -reth-errors = { workspace = true } -reth-evm = { workspace = true } -reth-execution-cache = { workspace = true } -reth-payload-primitives = { workspace = true } -reth-primitives-traits = { workspace = true } -reth-provider = { workspace = true } -reth-revm = { workspace = true } -reth-tasks = { workspace = true } -reth-trie = { workspace = true } -reth-trie-db = { workspace = true } -reth-trie-parallel = { workspace = true } - -# alloy / revm — workspace versions from reth v2.0.0 -alloy-consensus = { workspace = true } -alloy-eip7928 = { workspace = true } -alloy-eips = { workspace = true } -alloy-evm = { workspace = true } -alloy-primitives = { workspace = true } -alloy-rlp = { workspace = true } -revm-primitives = { workspace = true } - -# utilities -crossbeam-channel = { workspace = true } -derive_more = { workspace = true } -tokio = { workspace = true } -tracing = { workspace = true } - -[features] -default = ["std"] -std = [] -trie-debug = ["dep:reth-trie-sparse"] -# Forwards `morph-node`'s `test-utils` feature, which provides `MorphTestNode`, -# `TestNodeBuilder`, `HardforkSchedule`, etc. used by the Jade-boundary -# integration test. -test-utils = ["morph-node/test-utils"] - -[dependencies.reth-trie-sparse] -workspace = true -default-features = false -optional = true - -[dev-dependencies] -alloy-genesis = { workspace = true } -serde_json = { workspace = true } -# Jade boundary integration test — exercises MorphBasicEngineValidator through -# the real MorphNode stack via morph-node's test-utils feature. -morph-node = { workspace = true, features = ["test-utils"] } -morph-payload-types = { workspace = true } -reth-node-api = { workspace = true } -reth-payload-builder = { workspace = true } -reth-tracing = { workspace = true } -alloy-rpc-types-engine = { workspace = true } -alloy-rpc-types-eth = { workspace = true } -eyre = { workspace = true } -tokio = { workspace = true, features = ["macros", "rt-multi-thread"] } diff --git a/crates/engine-tree-ext/src/gate.rs b/crates/engine-tree-ext/src/gate.rs deleted file mode 100644 index e3dbd9d..0000000 --- a/crates/engine-tree-ext/src/gate.rs +++ /dev/null @@ -1,67 +0,0 @@ -//! Decides whether strict state-root equality must be enforced for a block. -//! -//! Pre-Jade Morph blocks store ZK-trie roots in `header.state_root`, while reth -//! computes MPT roots. Skipping the strict check pre-Jade is safe because the -//! first post-Jade block's successful strict check retroactively anchors the -//! MPT state accumulated across the pre-Jade range (transitivity of EVM -//! execution; see the design spec). - -use morph_chainspec::{MorphChainSpec, MorphHardforks}; - -/// Returns `true` iff reth must enforce the strict -/// `computed_state_root == header.state_root()` check at the given block -/// timestamp. Post-Jade: true. Pre-Jade: false. -pub fn state_root_enforced_at(chain_spec: &MorphChainSpec, timestamp: u64) -> bool { - chain_spec.is_jade_active_at_timestamp(timestamp) -} - -#[cfg(test)] -mod tests { - use super::*; - use alloy_genesis::Genesis; - use serde_json::json; - use std::sync::Arc; - - fn chain_spec_with_jade_at(jade_time: u64) -> Arc { - let genesis: Genesis = serde_json::from_value(json!({ - "config": { - "chainId": 1337, - "bernoulliBlock": 0, - "curieBlock": 0, - "morph": {}, - "jadeForkTime": jade_time - }, - "alloc": {} - })) - .expect("valid test genesis"); - Arc::new(MorphChainSpec::from(genesis)) - } - - #[test] - fn skipped_before_jade() { - let cs = chain_spec_with_jade_at(1_000); - assert!(!state_root_enforced_at(&cs, 0)); - assert!(!state_root_enforced_at(&cs, 500)); - assert!(!state_root_enforced_at(&cs, 999)); - } - - #[test] - fn strict_at_and_after_jade() { - let cs = chain_spec_with_jade_at(1_000); - assert!(state_root_enforced_at(&cs, 1_000)); - assert!(state_root_enforced_at(&cs, 1_001)); - assert!(state_root_enforced_at(&cs, u64::MAX)); - } - - #[test] - fn skipped_when_jade_unset() { - let genesis: Genesis = serde_json::from_value(json!({ - "config": { "chainId": 1337, "bernoulliBlock": 0, "curieBlock": 0, "morph": {} }, - "alloc": {} - })) - .unwrap(); - let cs = Arc::new(MorphChainSpec::from(genesis)); - assert!(!state_root_enforced_at(&cs, 0)); - assert!(!state_root_enforced_at(&cs, 1_000_000)); - } -} diff --git a/crates/engine-tree-ext/src/lib.rs b/crates/engine-tree-ext/src/lib.rs deleted file mode 100644 index fc27722..0000000 --- a/crates/engine-tree-ext/src/lib.rs +++ /dev/null @@ -1,13 +0,0 @@ -//! Morph extension of reth's engine tree. -//! -//! Verbatim copy of `reth_engine_tree::tree::payload_validator` from reth v2.0.0, -//! used as the foundation for a Jade-gated state-root skip. -//! -//! `trie_updates` is a verbatim copy of the private sibling module from the same -//! source tree, required by `payload_validator::compare_trie_updates_with_serial`. - -pub mod gate; -pub mod payload_validator; -pub(crate) mod trie_updates; - -pub use payload_validator::MorphBasicEngineValidator; diff --git a/crates/engine-tree-ext/src/payload_validator.rs b/crates/engine-tree-ext/src/payload_validator.rs deleted file mode 100644 index 5d52e08..0000000 --- a/crates/engine-tree-ext/src/payload_validator.rs +++ /dev/null @@ -1,2193 +0,0 @@ -//! Types and traits for validating blocks and payloads. -//! -//! # Validation pipeline -//! -//! When the engine processes a new payload (`engine_newPayload`), validation happens in phases: -//! -//! ## Phase 1 – Payload conversion -//! [`PayloadValidator::convert_payload_to_block`] decodes the execution payload (RLP, hashing) -//! into a [`SealedBlock`]. This runs on a background thread concurrently with state setup. -//! -//! ## Phase 2 – Pre-execution consensus -//! - [`HeaderValidator::validate_header`] — standalone header checks (hash, gas, base fee, -//! fork-specific fields) -//! - [`Consensus::validate_block_pre_execution`] — body vs header (tx root, ommer hash, withdrawals -//! root) -//! - [`HeaderValidator::validate_header_against_parent`] — sequential checks (block number, -//! timestamp, gas limit, base fee vs parent) -//! -//! ## Phase 3 – Execution -//! Block transactions are executed via the EVM. Receipt roots are computed incrementally. -//! -//! ## Phase 4 – Post-execution consensus -//! - [`FullConsensus::validate_block_post_execution`] — gas used, receipt root, logs bloom, -//! requests hash -//! - [`PayloadValidator::validate_block_post_execution_with_hashed_state`] — network-specific -//! (no-op on L1, used by OP Stack) -//! -//! ## Payload attributes validation (`engine_forkchoiceUpdated`) -//! When the CL provides payload attributes to start building a block: -//! - [`PayloadValidator::validate_payload_attributes_against_header`] — ensures timestamp ordering -//! -//! If validation passes, a payload build job is started. If it fails, -//! `INVALID_PAYLOAD_ATTRIBUTES` is returned without rolling back the forkchoice update. -//! -//! [`HeaderValidator::validate_header`]: reth_consensus::HeaderValidator::validate_header -//! [`Consensus::validate_block_pre_execution`]: reth_consensus::Consensus::validate_block_pre_execution -//! [`HeaderValidator::validate_header_against_parent`]: reth_consensus::HeaderValidator::validate_header_against_parent -//! [`FullConsensus::validate_block_post_execution`]: reth_consensus::FullConsensus::validate_block_post_execution -//! [`SealedBlock`]: reth_primitives_traits::SealedBlock - -use alloy_consensus::transaction::{Either, TxHashRef}; -use alloy_eip7928::BlockAccessList; -use alloy_eips::{NumHash, eip1898::BlockWithParent, eip4895::Withdrawal}; -use alloy_evm::Evm; -use alloy_primitives::{B256, map::B256Set}; -use reth_engine_tree::tree::{ - CacheWaitDurations, CachedStateProvider, EngineApiMetrics, EngineApiTreeState, EngineValidator, - ExecutionEnv, PayloadHandle, StateProviderBuilder, TreeConfig, WaitForCaches, - error::{InsertBlockError, InsertBlockErrorKind, InsertPayloadError}, - instrumented_state::{InstrumentedStateProvider, StateProviderStats}, - payload_processor::{ - PayloadProcessor, - multiproof::{StateRootComputeOutcome, StateRootHandle}, - }, - payload_validator::TreeCtx, - precompile_cache::{CachedPrecompile, CachedPrecompileMetrics, PrecompileCacheMap}, -}; -use reth_revm::database::StateProviderDatabase; -#[cfg(feature = "trie-debug")] -use reth_trie_sparse::debug_recorder::TrieDebugRecorder; - -use crate::gate::state_root_enforced_at; -use morph_chainspec::{MorphChainSpec, MorphHardforks}; -use morph_primitives::{MorphHeader, MorphTxEnvelope}; -use reth_chain_state::{DeferredTrieData, ExecutedBlock, ExecutionTimingStats, LazyOverlay}; -use reth_consensus::{ConsensusError, FullConsensus, ReceiptRootBloom}; -use reth_engine_primitives::{ - ConfigureEngineEvm, ExecutableTxIterator, ExecutionPayload, InvalidBlockHook, PayloadValidator, -}; -use reth_engine_tree::tree::payload_processor::receipt_root_task::{ - IndexedReceipt, ReceiptRootTaskHandle, -}; -use reth_errors::{BlockExecutionError, ProviderResult}; -use reth_evm::{ - ConfigureEvm, EvmEnvFor, ExecutionCtxFor, OnStateHook, SpecFor, block::BlockExecutor, - execute::ExecutableTxFor, -}; -use reth_execution_cache::{CacheStats, SavedCache}; -use reth_payload_primitives::{ - BuiltPayload, InvalidPayloadAttributesError, NewPayloadError, PayloadTypes, -}; -use reth_primitives_traits::{ - AlloyBlockHeader, BlockBody, BlockTy, FastInstant as Instant, GotExpected, NodePrimitives, - RecoveredBlock, SealedBlock, SealedHeader, SignerRecoverable, -}; -use reth_provider::{ - BlockExecutionOutput, BlockNumReader, BlockReader, ChangeSetReader, DatabaseProviderFactory, - DatabaseProviderROFactory, HashedPostStateProvider, ProviderError, PruneCheckpointReader, - StageCheckpointReader, StateProvider, StateProviderFactory, StateReader, - StorageChangeSetReader, StorageSettingsCache, - providers::{OverlayBuilder, OverlayStateProviderFactory}, -}; -use reth_revm::db::{BundleAccount, State, states::bundle_state::BundleRetention}; -use reth_trie::{HashedPostState, StateRoot, trie_cursor::TrieCursorFactory, updates::TrieUpdates}; -use reth_trie_db::ChangesetCache; -use reth_trie_parallel::root::{ParallelStateRoot, ParallelStateRootError}; -use revm_primitives::{Address, KECCAK_EMPTY}; -use std::{ - collections::HashMap, - panic::{self, AssertUnwindSafe}, - sync::{ - Arc, - atomic::{AtomicUsize, Ordering}, - mpsc::RecvTimeoutError, - }, - time::Duration, -}; -use tracing::{Span, debug, debug_span, error, info, instrument, trace, warn}; - -/// Output of block or payload validation. -pub type ValidationOutcome>> = - Result<(ExecutedBlock, Option>), E>; - -/// Handle to a [`HashedPostState`] computed on a background thread. -type LazyHashedPostState = reth_tasks::LazyHandle; - -/// Result type for block validation with optional timing stats. -type InsertPayloadResult = Result< - (ExecutedBlock, Option>), - InsertPayloadError<::Block>, ->; - -/// Context providing access to tree state during validation. -/// -/// A helper type that provides reusable payload validation logic for network-specific validators. -/// -/// This type satisfies [`EngineValidator`] and is responsible for executing blocks/payloads. -/// -/// This type contains common validation, execution, and state root computation logic that can be -/// used by network-specific payload validators (e.g., Ethereum, Optimism). It is not meant to be -/// used as a standalone component, but rather as a building block for concrete implementations. -#[derive(derive_more::Debug)] -pub struct MorphBasicEngineValidator -where - Evm: ConfigureEvm, -{ - /// Provider for database access. - provider: P, - /// Consensus implementation for validation. - consensus: Arc>, - /// EVM configuration. - evm_config: Evm, - /// Configuration for the tree. - config: TreeConfig, - /// Payload processor for state root computation. - payload_processor: PayloadProcessor, - /// Precompile cache map. - precompile_cache_map: PrecompileCacheMap>, - /// Precompile cache metrics. - precompile_cache_metrics: HashMap, - /// Hook to call when invalid blocks are encountered. - #[debug(skip)] - invalid_block_hook: Box>, - /// Metrics for the engine api. - metrics: EngineApiMetrics, - /// Validator for the payload. - validator: V, - /// Changeset cache for in-memory trie changesets - changeset_cache: ChangesetCache, - /// Task runtime for spawning parallel work. - runtime: reth_tasks::Runtime, - /// Chain spec, used to gate pre-Jade state-root skipping. - chain_spec: Arc, -} - -impl MorphBasicEngineValidator -where - N: NodePrimitives< - Block = morph_primitives::Block, - BlockHeader = MorphHeader, - SignedTx = MorphTxEnvelope, - >, - P: DatabaseProviderFactory< - Provider: BlockReader - + StageCheckpointReader - + PruneCheckpointReader - + ChangeSetReader - + StorageChangeSetReader - + BlockNumReader - + StorageSettingsCache, - > + BlockReader
- + ChangeSetReader - + BlockNumReader - + StateProviderFactory - + StateReader - + HashedPostStateProvider - + Clone - + 'static, - Evm: ConfigureEvm + 'static, -{ - /// Creates a new `TreePayloadValidator`. - #[expect(clippy::too_many_arguments)] - pub fn new( - provider: P, - consensus: Arc>, - evm_config: Evm, - validator: V, - config: TreeConfig, - invalid_block_hook: Box>, - changeset_cache: ChangesetCache, - runtime: reth_tasks::Runtime, - chain_spec: Arc, - ) -> Self { - let precompile_cache_map = PrecompileCacheMap::default(); - let payload_processor = PayloadProcessor::new( - runtime.clone(), - evm_config.clone(), - &config, - precompile_cache_map.clone(), - ); - Self { - provider, - consensus, - evm_config, - payload_processor, - precompile_cache_map, - precompile_cache_metrics: HashMap::new(), - config, - invalid_block_hook, - metrics: EngineApiMetrics::default(), - validator, - changeset_cache, - runtime, - chain_spec, - } - } - - /// Converts a [`BlockOrPayload`] to a recovered block. - #[instrument(level = "debug", target = "engine::tree::payload_validator", skip_all)] - pub fn convert_to_block>>( - &self, - input: BlockOrPayload, - ) -> Result, NewPayloadError> - where - V: PayloadValidator, - { - match input { - BlockOrPayload::Payload(payload) => self.validator.convert_payload_to_block(payload), - BlockOrPayload::Block(block) => Ok(block), - } - } - - /// Returns EVM environment for the given payload or block. - pub fn evm_env_for>>( - &self, - input: &BlockOrPayload, - ) -> Result, Evm::Error> - where - V: PayloadValidator, - Evm: ConfigureEngineEvm, - { - match input { - BlockOrPayload::Payload(payload) => Ok(self.evm_config.evm_env_for_payload(payload)?), - BlockOrPayload::Block(block) => Ok(self.evm_config.evm_env(block.header())?), - } - } - - /// Returns [`ExecutableTxIterator`] for the given payload or block. - pub fn tx_iterator_for<'a, T: PayloadTypes>>( - &'a self, - input: &'a BlockOrPayload, - ) -> Result, NewPayloadError> - where - V: PayloadValidator, - Evm: ConfigureEngineEvm, - { - Ok(match input { - BlockOrPayload::Payload(payload) => { - let iter = self - .evm_config - .tx_iterator_for_payload(payload) - .map_err(NewPayloadError::other)?; - Either::Left(iter) - } - BlockOrPayload::Block(block) => { - let txs = block.body().clone_transactions(); - let convert = |tx: N::SignedTx| tx.try_into_recovered(); - Either::Right((txs, convert)) - } - }) - } - - /// Returns a [`ExecutionCtxFor`] for the given payload or block. - pub fn execution_ctx_for<'a, T: PayloadTypes>>( - &self, - input: &'a BlockOrPayload, - ) -> Result, Evm::Error> - where - V: PayloadValidator, - Evm: ConfigureEngineEvm, - { - match input { - BlockOrPayload::Payload(payload) => Ok(self.evm_config.context_for_payload(payload)?), - BlockOrPayload::Block(block) => Ok(self.evm_config.context_for_block(block)?), - } - } - - /// Handles execution errors by checking if header validation errors should take precedence. - /// - /// When an execution error occurs, this function checks if there are any header validation - /// errors that should be reported instead, as header validation errors have higher priority. - fn handle_execution_error>>( - &self, - input: BlockOrPayload, - execution_err: InsertBlockErrorKind, - parent_block: &SealedHeader, - ) -> InsertPayloadResult - where - V: PayloadValidator, - { - debug!( - target: "engine::tree::payload_validator", - ?execution_err, - block = ?input.num_hash(), - "Block execution failed, checking for header validation errors" - ); - - // If execution failed, we should first check if there are any header validation - // errors that take precedence over the execution error - let block = self.convert_to_block(input)?; - - // Validate block consensus rules which includes header validation - if let Err(consensus_err) = self.validate_block_inner(&block, None) { - // Header validation error takes precedence over execution error - return Err(InsertBlockError::new(block, consensus_err.into()).into()); - } - - // Also validate against the parent - if let Err(consensus_err) = self - .consensus - .validate_header_against_parent(block.sealed_header(), parent_block) - { - // Parent validation error takes precedence over execution error - return Err(InsertBlockError::new(block, consensus_err.into()).into()); - } - - // No header validation errors, return the original execution error - Err(InsertBlockError::new(block, execution_err).into()) - } - - /// Validates a block that has already been converted from a payload. - /// - /// This method performs: - /// - Consensus validation - /// - Block execution - /// - State root computation - /// - Fork detection - #[instrument( - level = "debug", - target = "engine::tree::payload_validator", - skip_all, - fields( - parent = ?input.parent_hash(), - type_name = ?input.type_name(), - ) - )] - pub fn validate_block_with_state>>( - &mut self, - input: BlockOrPayload, - mut ctx: TreeCtx<'_, N>, - ) -> InsertPayloadResult - where - V: PayloadValidator + Clone, - Evm: ConfigureEngineEvm, - { - // Spawn payload conversion on a background thread so it runs concurrently with the - // rest of the function (setup + execution). For payloads this overlaps the cost of - // RLP decoding + header hashing. - let is_payload = matches!(&input, BlockOrPayload::Payload(_)); - let convert_to_block = match &input { - BlockOrPayload::Payload(_) => { - let payload_clone = input.clone(); - let validator = self.validator.clone(); - let handle = self.payload_processor.executor().spawn_blocking_named( - "payload-convert", - move || { - let BlockOrPayload::Payload(payload) = payload_clone else { - unreachable!() - }; - validator.convert_payload_to_block(payload) - }, - ); - Either::Left(handle) - } - BlockOrPayload::Block(_) => Either::Right(()), - }; - - // Returns the sealed block, either by awaiting the background conversion task (for - // payloads) or by extracting the already-converted block directly. - let convert_to_block = - move |input: BlockOrPayload| -> Result, NewPayloadError> { - match convert_to_block { - Either::Left(handle) => handle.try_into_inner().expect("sole handle"), - Either::Right(()) => { - let BlockOrPayload::Block(block) = input else { - unreachable!() - }; - Ok(block) - } - } - }; - - /// A helper macro that returns the block in case there was an error - /// This macro is used for early returns before block conversion - macro_rules! ensure_ok { - ($expr:expr) => { - match $expr { - Ok(val) => val, - Err(e) => { - let block = convert_to_block(input)?; - return Err(InsertBlockError::new(block, e.into()).into()); - } - } - }; - } - - /// A helper macro for handling errors after the input has been converted to a block - macro_rules! ensure_ok_post_block { - ($expr:expr, $block:expr) => { - match $expr { - Ok(val) => val, - Err(e) => { - return Err( - InsertBlockError::new($block.into_sealed_block(), e.into()).into() - ) - } - } - }; - } - - let parent_hash = input.parent_hash(); - - trace!(target: "engine::tree::payload_validator", "Fetching block state provider"); - let _enter = - debug_span!(target: "engine::tree::payload_validator", "state_provider").entered(); - let Some(provider_builder) = - ensure_ok!(self.state_provider_builder(parent_hash, ctx.state())) - else { - // this is pre-validated in the tree - return Err(InsertBlockError::new( - convert_to_block(input)?, - ProviderError::HeaderNotFound(parent_hash.into()).into(), - ) - .into()); - }; - let mut state_provider = ensure_ok!(provider_builder.build()); - drop(_enter); - - // Fetch parent block. This goes to memory most of the time unless the parent block is - // beyond the in-memory buffer. - let Some(parent_block) = ensure_ok!(self.sealed_header_by_hash(parent_hash, ctx.state())) - else { - return Err(InsertBlockError::new( - convert_to_block(input)?, - ProviderError::HeaderNotFound(parent_hash.into()).into(), - ) - .into()); - }; - - let evm_env = debug_span!(target: "engine::tree::payload_validator", "evm_env") - .in_scope(|| self.evm_env_for(&input)) - .map_err(NewPayloadError::other)?; - - let env = ExecutionEnv { - evm_env, - hash: input.hash(), - parent_hash: input.parent_hash(), - parent_state_root: parent_block.state_root(), - transaction_count: input.transaction_count(), - gas_used: input.gas_used(), - withdrawals: input.withdrawals().map(|w| w.to_vec()), - // Morph blocks (pre-Amsterdam) carry no BAL. Skip BAL-driven prewarming - // and let the payload processor install its own state hook for prewarm - // updates instead. - decoded_bal: None, - }; - - // Plan the strategy used for state root computation. - let strategy = self.plan_state_root_computation(); - - debug!( - target: "engine::tree::payload_validator", - ?strategy, - "Decided which state root algorithm to run" - ); - - // Get an iterator over the transactions in the payload - let txs = self.tx_iterator_for(&input)?; - - // Morph blocks (pre-Amsterdam) carry no BAL, so we deliberately drop the - // upstream BAL extraction. The header validator returns `None` for - // `block_access_list_hash()`, so any BAL bytes carried on the wire are - // ignored. - - // Create lazy overlay from ancestors - this doesn't block, allowing execution to start - // before the trie data is ready. The overlay will be computed on first access. - let (lazy_overlay, anchor_hash) = Self::get_parent_lazy_overlay(parent_hash, ctx.state()); - - // Create overlay factory for payload processor (StateRootTask path needs it for - // multiproofs). v2.2.0 moved `with_block_hash` / `with_lazy_overlay` onto - // `OverlayBuilder`, so we configure the builder first and pass it to the factory. - let overlay_builder = OverlayBuilder::::new(anchor_hash, self.changeset_cache.clone()) - .with_lazy_overlay(lazy_overlay); - let overlay_factory = - OverlayStateProviderFactory::new(self.provider.clone(), overlay_builder); - - // Spawn the appropriate processor based on strategy - let mut handle = ensure_ok!(self.spawn_payload_processor( - env.clone(), - txs, - provider_builder, - overlay_factory.clone(), - strategy, - )); - - // Create optional cache stats for detailed block logging - let slow_block_enabled = self.config.slow_block_threshold().is_some(); - let cache_stats = slow_block_enabled.then(|| Arc::new(CacheStats::default())); - - // Use cached state provider before executing, used in execution after prewarming threads - // complete - if let Some((caches, cache_metrics)) = handle.caches().zip(handle.cache_metrics()) { - state_provider = Box::new( - CachedStateProvider::new(state_provider, caches, cache_metrics) - .with_cache_stats(cache_stats.clone()), - ); - }; - - let state_provider_stats = if slow_block_enabled || self.config.state_provider_metrics() { - let instrumented_state_provider = - InstrumentedStateProvider::new(state_provider, "engine"); - let stats = slow_block_enabled.then(|| instrumented_state_provider.stats()); - state_provider = Box::new(instrumented_state_provider); - stats - } else { - None - }; - - // Execute the block and handle any execution errors. - // The receipt root task is spawned before execution and receives receipts incrementally - // as transactions complete, allowing parallel computation during execution. - let execute_block_start = Instant::now(); - let (output, senders, receipt_root_rx) = - match self.execute_block(state_provider, env, &input, &mut handle) { - Ok(output) => output, - Err(err) => return self.handle_execution_error(input, err, &parent_block), - }; - let execution_duration = execute_block_start.elapsed(); - - // After executing the block we can stop prewarming transactions - handle.stop_prewarming_execution(); - - // Create ExecutionOutcome early so we can terminate caching before validation and state - // root computation. Using Arc allows sharing with both the caching task and the deferred - // trie task without cloning the expensive BundleState. - let output = Arc::new(output); - - // Terminate caching task early since execution is complete and caching is no longer - // needed. This frees up resources while state root computation continues. - let valid_block_tx = handle.terminate_caching(Some(output.clone())); - - // Spawn hashed post state computation in background so it runs concurrently with - // block conversion and receipt root computation. This is a pure CPU-bound task - // (keccak256 hashing of all changed addresses and storage slots). - let hashed_state_output = output.clone(); - let hashed_state_provider = self.provider.clone(); - let hashed_state: LazyHashedPostState = self - .payload_processor - .executor() - .spawn_blocking_named("hash-post-state", move || { - let _span = debug_span!( - target: "engine::tree::payload_validator", - "hashed_post_state", - ) - .entered(); - hashed_state_provider.hashed_post_state(&hashed_state_output.state) - }); - - let block = convert_to_block(input)?; - let transaction_root = is_payload.then(|| { - let body = block.body().clone(); - let parent_span = Span::current(); - let num_hash = block.num_hash(); - self.payload_processor.executor().spawn_blocking_named("payload-tx-root", move || { - let _span = - debug_span!(target: "engine::tree::payload_validator", parent: parent_span, "payload_tx_root", block = ?num_hash) - .entered(); - body.calculate_tx_root() - }) - }); - let block = block.with_senders(senders); - - // Wait for the receipt root computation to complete. - let receipt_root_bloom = { - let _enter = debug_span!( - target: "engine::tree::payload_validator", - "wait_receipt_root", - ) - .entered(); - - receipt_root_rx - .blocking_recv() - .inspect_err(|_| { - tracing::error!( - target: "engine::tree::payload_validator", - "Receipt root task dropped sender without result, receipt root calculation likely aborted" - ); - }) - .ok() - }; - let transaction_root = transaction_root.map(|handle| { - let _span = - debug_span!(target: "engine::tree::payload_validator", "wait_payload_tx_root") - .entered(); - handle.try_into_inner().expect("sole handle") - }); - - let hashed_state = ensure_ok_post_block!( - self.validate_post_execution( - &block, - &parent_block, - &output, - &mut ctx, - transaction_root, - receipt_root_bloom, - hashed_state, - ), - block - ); - - let root_time = Instant::now(); - let mut maybe_state_root = None; - let mut state_root_task_failed = false; - #[cfg(feature = "trie-debug")] - let mut trie_debug_recorders = Vec::new(); - - match strategy { - StateRootStrategy::StateRootTask => { - debug!(target: "engine::tree::payload_validator", "Using sparse trie state root algorithm"); - - let task_result = ensure_ok_post_block!( - self.await_state_root_with_timeout( - &mut handle, - overlay_factory.clone(), - &hashed_state, - ), - block - ); - - match task_result { - Ok(StateRootComputeOutcome { - state_root, - trie_updates, - #[cfg(feature = "trie-debug")] - debug_recorders, - }) => { - let elapsed = root_time.elapsed(); - info!(target: "engine::tree::payload_validator", ?state_root, ?elapsed, "State root task finished"); - - #[cfg(feature = "trie-debug")] - { - trie_debug_recorders = debug_recorders; - } - - // Compare trie updates with serial computation if configured - if self.config.always_compare_trie_updates() { - let _has_diff = self.compare_trie_updates_with_serial( - overlay_factory.clone(), - &hashed_state, - trie_updates.as_ref().clone(), - ); - #[cfg(feature = "trie-debug")] - if _has_diff { - Self::write_trie_debug_recorders( - block.header().number(), - &trie_debug_recorders, - ); - } - } - - // Pre-Jade Morph blocks store a ZK-trie root in header.state_root; - // reth computes an MPT root which will never match. The strict check - // is only enforced post-Jade. See gate::state_root_enforced_at and - // the design spec for transitivity of EVM execution. - let strict_enforced = - state_root_enforced_at(&self.chain_spec, block.header().timestamp()); - - // we double check the state root here for good measure - if !strict_enforced || state_root == block.header().state_root() { - maybe_state_root = Some((state_root, trie_updates, elapsed)) - } else { - warn!( - target: "engine::tree::payload_validator", - ?state_root, - block_state_root = ?block.header().state_root(), - "State root task returned incorrect state root" - ); - #[cfg(feature = "trie-debug")] - Self::write_trie_debug_recorders( - block.header().number(), - &trie_debug_recorders, - ); - state_root_task_failed = true; - } - } - Err(error) => { - debug!(target: "engine::tree::payload_validator", %error, "State root task failed"); - state_root_task_failed = true; - } - } - } - StateRootStrategy::Parallel => { - debug!(target: "engine::tree::payload_validator", "Using parallel state root algorithm"); - match self.compute_state_root_parallel(overlay_factory.clone(), &hashed_state) { - Ok(result) => { - let elapsed = root_time.elapsed(); - info!( - target: "engine::tree::payload_validator", - regular_state_root = ?result.0, - ?elapsed, - "Regular root task finished" - ); - maybe_state_root = Some((result.0, Arc::new(result.1), elapsed)); - } - Err(error) => { - debug!(target: "engine::tree::payload_validator", %error, "Parallel state root computation failed"); - } - } - } - StateRootStrategy::Synchronous => {} - } - - // Determine the state root. - // If the state root was computed in parallel, we use it. - // Otherwise, we fall back to computing it synchronously. - let (state_root, trie_output, root_elapsed) = if let Some(maybe_state_root) = - maybe_state_root - { - maybe_state_root - } else { - // fallback is to compute the state root regularly in sync - if self.config.state_root_fallback() { - debug!(target: "engine::tree::payload_validator", "Using state root fallback for testing"); - } else { - warn!(target: "engine::tree::payload_validator", "Failed to compute state root in parallel"); - self.metrics - .block_validation - .state_root_parallel_fallback_total - .increment(1); - } - - let (root, updates) = ensure_ok_post_block!( - Self::compute_state_root_serial(overlay_factory.clone(), &hashed_state), - block - ); - - if state_root_task_failed { - self.metrics - .block_validation - .state_root_task_fallback_success_total - .increment(1); - } - - (root, Arc::new(updates), root_time.elapsed()) - }; - - self.metrics - .block_validation - .record_state_root(&trie_output, root_elapsed.as_secs_f64()); - self.metrics - .record_state_root_gas_bucket(block.header().gas_used(), root_elapsed.as_secs_f64()); - debug!(target: "engine::tree::payload_validator", ?root_elapsed, "Calculated state root"); - - // ensure state root matches — post-Jade only. Pre-Jade blocks carry a - // ZK-trie root in the header which will never equal reth's MPT root. - // Correctness is proven transitively by the first post-Jade block's - // successful strict check (see design spec). - let strict_enforced = state_root_enforced_at(&self.chain_spec, block.header().timestamp()); - - if strict_enforced && state_root != block.header().state_root() { - #[cfg(feature = "trie-debug")] - Self::write_trie_debug_recorders(block.header().number(), &trie_debug_recorders); - - // call post-block hook - self.on_invalid_block( - &parent_block, - &block, - &output, - Some((&trie_output, state_root)), - ctx.state_mut(), - ); - let block_state_root = block.header().state_root(); - return Err(InsertBlockError::new( - block.into_sealed_block(), - ConsensusError::BodyStateRootDiff( - GotExpected { - got: state_root, - expected: block_state_root, - } - .into(), - ) - .into(), - ) - .into()); - } - - let timing_stats = state_provider_stats.map(|stats| { - self.calculate_timing_stats( - &block, - stats, - cache_stats, - &output, - execution_duration, - root_elapsed, - ) - }); - - if let Some(valid_block_tx) = valid_block_tx { - let _ = valid_block_tx.send(()); - } - - // Create the overlay provider NOW, while we're on the engine loop thread and trie changeset - // eviction cannot race with us. If we deferred this to the background task, persistence - // could advance and evict changeset cache entries between factory creation and the task - // actually running, causing expensive DB fallback computations when building the overlay. - let changeset_provider = - ensure_ok_post_block!(overlay_factory.database_provider_ro(), block); - - let executed_block = self.spawn_deferred_trie_task( - block, - output, - &ctx, - hashed_state, - trie_output, - changeset_provider, - ); - Ok((executed_block, timing_stats)) - } - - /// Return sealed block header from database or in-memory state by hash. - fn sealed_header_by_hash( - &self, - hash: B256, - state: &EngineApiTreeState, - ) -> ProviderResult>> { - // check memory first - let header = state.tree_state().sealed_header_by_hash(&hash); - - if header.is_some() { - Ok(header) - } else { - self.provider.sealed_header_by_hash(hash) - } - } - - /// Validate if block is correct and satisfies all the consensus rules that concern the header - /// and block body itself. - #[instrument(level = "debug", target = "engine::tree::payload_validator", skip_all)] - fn validate_block_inner( - &self, - block: &SealedBlock, - transaction_root: Option, - ) -> Result<(), ConsensusError> { - if let Err(e) = self.consensus.validate_header(block.sealed_header()) { - error!(target: "engine::tree::payload_validator", ?block, "Failed to validate header {}: {e}", block.hash()); - return Err(e); - } - - if let Err(e) = self - .consensus - .validate_block_pre_execution_with_tx_root(block, transaction_root) - { - error!(target: "engine::tree::payload_validator", ?block, "Failed to validate block {}: {e}", block.hash()); - return Err(e); - } - - Ok(()) - } - - /// Validates Morph's parent-aware L1 message index invariant. - /// - /// go-ethereum derives `NextL1MsgIndex` from the parent queue index plus the - /// L1 messages processed by this block. Since `next_l1_msg_index` is not part - /// of the block hash, Jade and later must reject any mismatch before accepting - /// the payload. - fn validate_next_l1_msg_index_against_parent( - &self, - block: &RecoveredBlock, - parent_block: &SealedHeader, - ) -> Result<(), ConsensusError> { - if !self - .chain_spec - .is_jade_active_at_timestamp(block.header().timestamp()) - { - return Ok(()); - } - - let mut expected = parent_block.next_l1_msg_index; - for tx in block.body().transactions() { - if !tx.is_l1_msg() { - break; - } - - let queue_index = tx.queue_index().ok_or_else(|| { - ConsensusError::msg("L1 message transaction is missing queue index") - })?; - // Match geth's `NumL1MessagesProcessed(parent_queue_index)`: forward skips - // are counted as processed, so the derived next index is last_queue + 1. - expected = queue_index.checked_add(1).ok_or_else(|| { - ConsensusError::msg(format!( - "invalid block.NextL1MsgIndex: expected {}, got {}", - u64::MAX, - block.header().next_l1_msg_index - )) - })?; - } - - let actual = block.header().next_l1_msg_index; - if actual != expected { - return Err(ConsensusError::msg(format!( - "invalid block.NextL1MsgIndex: expected {expected}, got {actual}" - ))); - } - - Ok(()) - } - - /// Executes a block with the given state provider. - /// - /// This method orchestrates block execution: - /// 1. Sets up the EVM with state database and precompile caching - /// 2. Spawns a background task for incremental receipt root computation - /// 3. Executes transactions with metrics collection via state hooks - /// 4. Merges state transitions and records execution metrics - #[instrument(level = "debug", target = "engine::tree::payload_validator", skip_all)] - #[expect(clippy::type_complexity)] - fn execute_block( - &mut self, - state_provider: S, - env: ExecutionEnv, - input: &BlockOrPayload, - handle: &mut PayloadHandle, Err, N::Receipt>, - ) -> Result< - ( - BlockExecutionOutput, - Vec
, - tokio::sync::oneshot::Receiver<(B256, alloy_primitives::Bloom)>, - ), - InsertBlockErrorKind, - > - where - S: StateProvider + Send, - Err: core::error::Error + Send + Sync + 'static, - V: PayloadValidator, - T: PayloadTypes>, - Evm: ConfigureEngineEvm, - { - debug!(target: "engine::tree::payload_validator", "Executing block"); - - let mut db = debug_span!(target: "engine::tree", "build_state_db").in_scope(|| { - State::builder() - .with_database(StateProviderDatabase::new(state_provider)) - .with_bundle_update() - .build() - }); - - let (spec_id, mut executor) = { - let _span = debug_span!(target: "engine::tree", "create_evm").entered(); - let spec_id = *env.evm_env.spec_id(); - let evm = self.evm_config.evm_with_env(&mut db, env.evm_env); - let ctx = self - .execution_ctx_for(input) - .map_err(|e| InsertBlockErrorKind::Other(Box::new(e)))?; - let executor = self.evm_config.create_executor(evm, ctx); - (spec_id, executor) - }; - - if !self.config.precompile_cache_disabled() { - let _span = debug_span!(target: "engine::tree", "setup_precompile_cache").entered(); - executor - .evm_mut() - .precompiles_mut() - .map_cacheable_precompiles(|address, precompile| { - let metrics = self - .precompile_cache_metrics - .entry(*address) - .or_insert_with(|| CachedPrecompileMetrics::new_with_address(*address)) - .clone(); - CachedPrecompile::wrap( - precompile, - self.precompile_cache_map.cache_for_address(*address), - spec_id, - Some(metrics), - ) - }); - } - - // Spawn background task to compute receipt root and logs bloom incrementally. - // Unbounded channel is used since tx count bounds capacity anyway (max ~30k txs per block). - let receipts_len = input.transaction_count(); - let (receipt_tx, receipt_rx) = crossbeam_channel::unbounded(); - let (result_tx, result_rx) = tokio::sync::oneshot::channel(); - let task_handle = ReceiptRootTaskHandle::new(receipt_rx, result_tx); - self.payload_processor - .executor() - .spawn_blocking_named("receipt-root", move || task_handle.run(receipts_len)); - - let transaction_count = input.transaction_count(); - let executed_tx_index = Arc::clone(handle.executed_tx_index()); - let executor = executor.with_state_hook( - handle - .state_hook() - .map(|hook| Box::new(hook) as Box), - ); - - let execution_start = Instant::now(); - - // Execute all transactions and finalize - let (executor, senders) = self.execute_transactions( - executor, - transaction_count, - handle.iter_transactions(), - &receipt_tx, - &executed_tx_index, - )?; - drop(receipt_tx); - - // Finish execution and get the result - let post_exec_start = Instant::now(); - let (_evm, result) = debug_span!(target: "engine::tree", "BlockExecutor::finish") - .in_scope(|| executor.finish()) - .map(|(evm, result)| (evm.into_db(), result))?; - self.metrics - .record_post_execution(post_exec_start.elapsed()); - - // Merge transitions into bundle state - debug_span!(target: "engine::tree", "merge_transitions") - .in_scope(|| db.merge_transitions(BundleRetention::Reverts)); - - let output = BlockExecutionOutput { - result, - state: db.take_bundle(), - }; - - let execution_duration = execution_start.elapsed(); - self.metrics - .record_block_execution(&output, execution_duration); - self.metrics - .record_block_execution_gas_bucket(output.result.gas_used, execution_duration); - debug!(target: "engine::tree::payload_validator", elapsed = ?execution_duration, "Executed block"); - - Ok((output, senders, result_rx)) - } - - /// Executes transactions and collects senders, streaming receipts to a background task. - /// - /// This method handles: - /// - Applying pre-execution changes (e.g., beacon root updates) - /// - Executing each transaction with timing metrics - /// - Streaming receipts to the receipt root computation task - /// - Collecting transaction senders for later use - /// - /// Returns the executor (for finalization) and the collected senders. - fn execute_transactions( - &self, - mut executor: E, - transaction_count: usize, - transactions: impl Iterator>, - receipt_tx: &crossbeam_channel::Sender>, - executed_tx_index: &AtomicUsize, - ) -> Result<(E, Vec
), BlockExecutionError> - where - E: BlockExecutor, - Tx: alloy_evm::block::ExecutableTx + alloy_evm::RecoveredTx, - InnerTx: TxHashRef, - Err: core::error::Error + Send + Sync + 'static, - { - let mut senders = Vec::with_capacity(transaction_count); - - // Apply pre-execution changes (e.g., beacon root update) - let pre_exec_start = Instant::now(); - debug_span!(target: "engine::tree", "pre_execution") - .in_scope(|| executor.apply_pre_execution_changes())?; - self.metrics.record_pre_execution(pre_exec_start.elapsed()); - - // Execute transactions - let exec_span = debug_span!(target: "engine::tree", "execution").entered(); - let mut transactions = transactions.into_iter(); - // Some executors may execute transactions that do not append receipts during the - // main loop (e.g., system transactions whose receipts are added during finalization). - // In that case, invoking the callback on every transaction would resend the previous - // receipt with the same index and can panic the ordered root builder. - let mut last_sent_len = 0usize; - loop { - // Measure time spent waiting for next transaction from iterator - // (e.g., parallel signature recovery) - let wait_start = Instant::now(); - let Some(tx_result) = transactions.next() else { - break; - }; - self.metrics.record_transaction_wait(wait_start.elapsed()); - - let tx = tx_result.map_err(BlockExecutionError::other)?; - let tx_signer = *>::signer(&tx); - - senders.push(tx_signer); - - let _enter = debug_span!( - target: "engine::tree", - "execute tx", - tx_index = senders.len() - 1, - ) - .entered(); - trace!(target: "engine::tree", "Executing transaction"); - - let tx_start = Instant::now(); - executor.execute_transaction(tx)?; - self.metrics - .record_transaction_execution(tx_start.elapsed()); - - // advance the shared counter so prewarm workers skip already-executed txs - executed_tx_index.store(senders.len(), Ordering::Relaxed); - - let current_len = executor.receipts().len(); - if current_len > last_sent_len { - last_sent_len = current_len; - // Send the latest receipt to the background task for incremental root computation. - if let Some(receipt) = executor.receipts().last() { - let tx_index = current_len - 1; - let _ = receipt_tx.send(IndexedReceipt::new(tx_index, receipt.clone())); - } - } - } - drop(exec_span); - - Ok((executor, senders)) - } - - /// Compute state root for the given hashed post state in parallel. - /// - /// Uses an overlay factory which provides the state of the parent block, along with the - /// [`HashedPostState`] containing the changes of this block, to compute the state root and - /// trie updates for this block. - /// - /// # Returns - /// - /// Returns `Ok(_)` if computed successfully. - /// Returns `Err(_)` if error was encountered during computation. - #[instrument(level = "debug", target = "engine::tree::payload_validator", skip_all)] - fn compute_state_root_parallel( - &self, - overlay_factory: OverlayStateProviderFactory, - hashed_state: &LazyHashedPostState, - ) -> Result<(B256, TrieUpdates), ParallelStateRootError> { - let hashed_state = hashed_state.get(); - // The `hashed_state` argument will be taken into account as part of the overlay, but we - // need to use the prefix sets which were generated from it to indicate to the - // ParallelStateRoot which parts of the trie need to be recomputed. - let prefix_sets = hashed_state.construct_prefix_sets().freeze(); - let overlay_factory = - overlay_factory.with_extended_hashed_state_overlay(hashed_state.clone_into_sorted()); - ParallelStateRoot::new(overlay_factory, prefix_sets, self.runtime.clone()) - .incremental_root_with_updates() - } - - /// Compute state root for the given hashed post state in serial. - /// - /// Uses an overlay factory which provides the state of the parent block, along with the - /// [`HashedPostState`] containing the changes of this block, to compute the state root and - /// trie updates for this block. - fn compute_state_root_serial( - overlay_factory: OverlayStateProviderFactory, - hashed_state: &LazyHashedPostState, - ) -> ProviderResult<(B256, TrieUpdates)> { - let hashed_state = hashed_state.get(); - // The `hashed_state` argument will be taken into account as part of the overlay, but we - // need to use the prefix sets which were generated from it to indicate to the - // StateRoot which parts of the trie need to be recomputed. - let prefix_sets = hashed_state.construct_prefix_sets().freeze(); - let overlay_factory = - overlay_factory.with_extended_hashed_state_overlay(hashed_state.clone_into_sorted()); - - let provider = overlay_factory.database_provider_ro()?; - - Ok(StateRoot::new(&provider, &provider) - .with_prefix_sets(prefix_sets) - .root_with_updates()?) - } - - /// Awaits the state root from the background task, with an optional timeout fallback. - /// - /// If a timeout is configured (`state_root_task_timeout`), this method first waits for the - /// state root task up to the timeout duration. If the task doesn't complete in time, a - /// sequential state root computation is spawned via `spawn_blocking`. Both computations - /// then race: the main thread polls the task receiver and the sequential result channel - /// in a loop, returning whichever finishes first. - /// - /// If no timeout is configured, this simply awaits the state root task without any fallback. - /// - /// Returns `ProviderResult>` where the outer `ProviderResult` captures - /// unrecoverable errors from the sequential fallback (e.g. DB errors), while the inner - /// `Result` captures parallel state root task errors that can still fall back to serial. - #[instrument( - level = "debug", - target = "engine::tree::payload_validator", - name = "await_state_root", - skip_all - )] - fn await_state_root_with_timeout( - &self, - handle: &mut PayloadHandle, - overlay_factory: OverlayStateProviderFactory, - hashed_state: &LazyHashedPostState, - ) -> ProviderResult> { - let Some(timeout) = self.config.state_root_task_timeout() else { - return Ok(handle.state_root()); - }; - - let task_rx = handle.take_state_root_rx(); - - match task_rx.recv_timeout(timeout) { - Ok(result) => Ok(result), - Err(RecvTimeoutError::Disconnected) => Ok(Err(ParallelStateRootError::Other( - "sparse trie task dropped".to_string(), - ))), - Err(RecvTimeoutError::Timeout) => { - warn!( - target: "engine::tree::payload_validator", - ?timeout, - "State root task timed out, spawning sequential fallback" - ); - self.metrics - .block_validation - .state_root_task_timeout_total - .increment(1); - - let (seq_tx, seq_rx) = - std::sync::mpsc::channel::>(); - - let seq_overlay = overlay_factory; - let seq_hashed_state = hashed_state.clone(); - self.payload_processor - .executor() - .spawn_blocking_named("serial-root", move || { - let result = - Self::compute_state_root_serial(seq_overlay, &seq_hashed_state); - let _ = seq_tx.send(result); - }); - - const POLL_INTERVAL: std::time::Duration = std::time::Duration::from_millis(10); - - loop { - match task_rx.recv_timeout(POLL_INTERVAL) { - Ok(result) => { - debug!( - target: "engine::tree::payload_validator", - source = "task", - "State root timeout race won" - ); - return Ok(result); - } - Err(RecvTimeoutError::Disconnected) => { - debug!( - target: "engine::tree::payload_validator", - "State root task dropped, waiting for sequential fallback" - ); - let result = seq_rx.recv().map_err(|_| { - ProviderError::other(std::io::Error::other( - "both state root computations failed", - )) - })?; - let (state_root, trie_updates) = result?; - return Ok(Ok(StateRootComputeOutcome { - state_root, - trie_updates: Arc::new(trie_updates), - #[cfg(feature = "trie-debug")] - debug_recorders: Vec::new(), - })); - } - Err(RecvTimeoutError::Timeout) => {} - } - - if let Ok(result) = seq_rx.try_recv() { - debug!( - target: "engine::tree::payload_validator", - source = "sequential", - "State root timeout race won" - ); - let (state_root, trie_updates) = result?; - return Ok(Ok(StateRootComputeOutcome { - state_root, - trie_updates: Arc::new(trie_updates), - #[cfg(feature = "trie-debug")] - debug_recorders: Vec::new(), - })); - } - } - } - } - } - - /// Compares trie updates from the state root task with serial state root computation. - /// - /// This is used for debugging and validating the correctness of the parallel state root - /// task implementation. When enabled via `--engine.state-root-task-compare-updates`, this - /// method runs a separate serial state root computation and compares the resulting trie - /// updates. - fn compare_trie_updates_with_serial( - &self, - overlay_factory: OverlayStateProviderFactory, - hashed_state: &LazyHashedPostState, - task_trie_updates: TrieUpdates, - ) -> bool { - debug!(target: "engine::tree::payload_validator", "Comparing trie updates with serial computation"); - - match Self::compute_state_root_serial(overlay_factory.clone(), hashed_state) { - Ok((serial_root, serial_trie_updates)) => { - debug!( - target: "engine::tree::payload_validator", - ?serial_root, - "Serial state root computation finished for comparison" - ); - - // Get a database provider to use as trie cursor factory - match overlay_factory.database_provider_ro() { - Ok(provider) => { - match crate::trie_updates::compare_trie_updates( - &provider, - task_trie_updates, - serial_trie_updates, - ) { - Ok(has_diff) => return has_diff, - Err(err) => { - warn!( - target: "engine::tree::payload_validator", - %err, - "Error comparing trie updates" - ); - return true; - } - } - } - Err(err) => { - warn!( - target: "engine::tree::payload_validator", - %err, - "Failed to get database provider for trie update comparison" - ); - } - } - } - Err(err) => { - warn!( - target: "engine::tree::payload_validator", - %err, - "Failed to compute serial state root for comparison" - ); - } - } - false - } - - /// Writes trie debug recorders to a JSON file for the given block number. - /// - /// The file is written to the current working directory as - /// `trie_debug_block_{block_number}.json`. - #[cfg(feature = "trie-debug")] - fn write_trie_debug_recorders( - block_number: u64, - recorders: &[(Option, TrieDebugRecorder)], - ) { - let path = format!("trie_debug_block_{block_number}.json"); - match serde_json::to_string_pretty(recorders) { - Ok(json) => match std::fs::write(&path, json) { - Ok(()) => { - warn!( - target: "engine::tree::payload_validator", - %path, - "Wrote trie debug recorders to file" - ); - } - Err(err) => { - warn!( - target: "engine::tree::payload_validator", - %err, - %path, - "Failed to write trie debug recorders" - ); - } - }, - Err(err) => { - warn!( - target: "engine::tree::payload_validator", - %err, - "Failed to serialize trie debug recorders" - ); - } - } - } - - /// Validates the block after execution. - /// - /// This performs: - /// - parent header validation - /// - post-execution consensus validation - /// - state-root based post-execution validation - /// - /// If `receipt_root_bloom` is provided, it will be used instead of computing the receipt root - /// and logs bloom from the receipts. - /// - /// The `hashed_state` handle wraps the background hashed post state computation. - #[instrument(level = "debug", target = "engine::tree::payload_validator", skip_all)] - #[expect(clippy::too_many_arguments)] - fn validate_post_execution>>( - &self, - block: &RecoveredBlock, - parent_block: &SealedHeader, - output: &BlockExecutionOutput, - ctx: &mut TreeCtx<'_, N>, - transaction_root: Option, - receipt_root_bloom: Option, - hashed_state: LazyHashedPostState, - ) -> Result - where - V: PayloadValidator, - { - let start = Instant::now(); - - trace!(target: "engine::tree::payload_validator", block=?block.num_hash(), "Validating block consensus"); - // validate block consensus rules - if let Err(e) = self.validate_block_inner(block, transaction_root) { - return Err(e.into()); - } - - // now validate against the parent - let _enter = debug_span!(target: "engine::tree::payload_validator", "validate_header_against_parent").entered(); - if let Err(e) = self - .consensus - .validate_header_against_parent(block.sealed_header(), parent_block) - { - warn!(target: "engine::tree::payload_validator", ?block, "Failed to validate header {} against parent: {e}", block.hash()); - return Err(e.into()); - } - drop(_enter); - - if let Err(e) = self.validate_next_l1_msg_index_against_parent(block, parent_block) { - warn!( - target: "engine::tree::payload_validator", - ?block, - "Failed to validate NextL1MsgIndex against parent for block {}: {e}", - block.hash() - ); - return Err(e.into()); - } - - // Validate block post-execution rules - let _enter = - debug_span!(target: "engine::tree::payload_validator", "validate_block_post_execution") - .entered(); - if let Err(err) = - self.consensus - .validate_block_post_execution(block, output, receipt_root_bloom) - { - // call post-block hook - self.on_invalid_block(parent_block, block, output, None, ctx.state_mut()); - return Err(err.into()); - } - drop(_enter); - - // Wait for the background keccak256 hashing task to complete. This blocks until - // all changed addresses and storage slots have been hashed. - let hashed_state_ref = - debug_span!(target: "engine::tree::payload_validator", "wait_hashed_post_state") - .in_scope(|| hashed_state.get()); - - let _enter = debug_span!(target: "engine::tree::payload_validator", "validate_block_post_execution_with_hashed_state").entered(); - if let Err(err) = self - .validator - .validate_block_post_execution_with_hashed_state(hashed_state_ref, block) - { - // call post-block hook - self.on_invalid_block(parent_block, block, output, None, ctx.state_mut()); - return Err(err.into()); - } - - // record post-execution validation duration - self.metrics - .block_validation - .post_execution_validation_duration - .record(start.elapsed().as_secs_f64()); - - Ok(hashed_state) - } - - /// Spawns a payload processor task based on the state root strategy. - /// - /// This method determines how to execute the block and compute its state root based on - /// the selected strategy: - /// - `StateRootTask`: Uses a dedicated task for state root computation with proof generation - /// - `Parallel`: Computes state root in parallel with block execution - /// - `Synchronous`: Falls back to sequential execution and state root computation - /// - /// The method handles strategy fallbacks if the preferred approach fails, ensuring - /// block execution always completes with a valid state root. - /// - /// # Arguments - /// - /// * `overlay_factory` - Pre-computed overlay factory for multiproof generation - /// (`StateRootTask`) - #[instrument( - level = "debug", - target = "engine::tree::payload_validator", - skip_all, - fields(?strategy) - )] - fn spawn_payload_processor>( - &mut self, - env: ExecutionEnv, - txs: T, - provider_builder: StateProviderBuilder, - overlay_factory: OverlayStateProviderFactory, - strategy: StateRootStrategy, - ) -> Result< - PayloadHandle< - impl ExecutableTxFor + use, - impl core::error::Error + Send + Sync + 'static + use, - N::Receipt, - >, - InsertBlockErrorKind, - > { - match strategy { - StateRootStrategy::StateRootTask => { - let spawn_start = Instant::now(); - - let handle = self.payload_processor.spawn( - env, - txs, - provider_builder, - overlay_factory, - &self.config, - ); - - // record prewarming initialization duration - self.metrics - .block_validation - .spawn_payload_processor - .record(spawn_start.elapsed().as_secs_f64()); - - Ok(handle) - } - StateRootStrategy::Parallel | StateRootStrategy::Synchronous => { - let start = Instant::now(); - let handle = - self.payload_processor - .spawn_cache_exclusive(env, txs, provider_builder); - - // Record prewarming initialization duration - self.metrics - .block_validation - .spawn_payload_processor - .record(start.elapsed().as_secs_f64()); - - Ok(handle) - } - } - } - - /// Creates a `StateProviderBuilder` for the given parent hash. - /// - /// This method checks if the parent is in the tree state (in-memory) or persisted to disk, - /// and creates the appropriate provider builder. - fn state_provider_builder( - &self, - hash: B256, - state: &EngineApiTreeState, - ) -> ProviderResult>> { - if let Some((historical, blocks)) = state.tree_state().blocks_by_hash(hash) { - debug!(target: "engine::tree::payload_validator", %hash, %historical, "found canonical state for block in memory, creating provider builder"); - // the block leads back to the canonical chain - return Ok(Some(StateProviderBuilder::new( - self.provider.clone(), - historical, - Some(blocks), - ))); - } - - // Check if the block is persisted - if let Some(header) = self.provider.header(hash)? { - debug!(target: "engine::tree::payload_validator", %hash, number = %header.number(), "found canonical state for block in database, creating provider builder"); - // For persisted blocks, we create a builder that will fetch state directly from the - // database - return Ok(Some(StateProviderBuilder::new( - self.provider.clone(), - hash, - None, - ))); - } - - debug!(target: "engine::tree::payload_validator", %hash, "no canonical state found for block"); - Ok(None) - } - - /// Determines the state root computation strategy based on configuration. - /// - /// Note: Use state root task only if prefix sets are empty, otherwise proof generation is - /// too expensive because it requires walking all paths in every proof. - const fn plan_state_root_computation(&self) -> StateRootStrategy { - if self.config.state_root_fallback() { - StateRootStrategy::Synchronous - } else if self.config.use_state_root_task() { - StateRootStrategy::StateRootTask - } else { - StateRootStrategy::Parallel - } - } - - /// Called when an invalid block is encountered during validation. - fn on_invalid_block( - &self, - parent_header: &SealedHeader, - block: &RecoveredBlock, - output: &BlockExecutionOutput, - trie_updates: Option<(&TrieUpdates, B256)>, - state: &mut EngineApiTreeState, - ) { - if state.has_invalid_header(&block.hash()) { - // we already marked this block as invalid - return; - } - self.invalid_block_hook - .on_invalid_block(parent_header, block, output, trie_updates); - } - - /// Creates a [`LazyOverlay`] for the parent block without blocking. - /// - /// Returns a lazy overlay that will compute the trie input on first access, and the anchor - /// block hash (the highest persisted ancestor). This allows execution to start immediately - /// while the trie input computation is deferred until the overlay is actually needed. - /// - /// If parent is on disk (no in-memory blocks), returns `None` for the lazy overlay. - /// - /// Uses a cached overlay if available for the canonical head (the common case). - fn get_parent_lazy_overlay( - parent_hash: B256, - state: &EngineApiTreeState, - ) -> (Option>, B256) { - // Get blocks leading to the parent to determine the anchor - let (anchor_hash, blocks) = state - .tree_state() - .blocks_by_hash(parent_hash) - .unwrap_or_else(|| (parent_hash, vec![])); - - if blocks.is_empty() { - debug!(target: "engine::tree::payload_validator", "Parent found on disk, no lazy overlay needed"); - return (None, anchor_hash); - } - - // Try to use the cached overlay if it matches both parent hash and anchor - if let Some(cached) = state - .tree_state() - .get_cached_overlay(parent_hash, anchor_hash) - { - debug!( - target: "engine::tree::payload_validator", - %parent_hash, - %anchor_hash, - "Using cached canonical overlay" - ); - return (Some(cached.overlay.clone()), cached.anchor_hash); - } - - debug!( - target: "engine::tree::payload_validator", - %anchor_hash, - num_blocks = blocks.len(), - "Creating lazy overlay for in-memory blocks" - ); - - // v2.2.0 ingests the executed blocks themselves; per-block - // `DeferredTrieData` extraction is no longer required. - (Some(LazyOverlay::new(blocks)), anchor_hash) - } - - /// Spawns a background task to compute and sort trie data for the executed block. - /// - /// This function creates a [`DeferredTrieData`] handle with fallback inputs and spawns a - /// blocking task that calls `wait_cloned()` to: - /// 1. Sort the block's hashed state and trie updates - /// 2. Merge ancestor overlays and extend with the sorted data - /// 3. Create an [`AnchoredTrieInput`](reth_chain_state::AnchoredTrieInput) for efficient future - /// trie computations - /// 4. Cache the result so subsequent calls return immediately - /// - /// If the background task hasn't completed when `trie_data()` is called, `wait_cloned()` - /// computes from the stored inputs, eliminating deadlock risk and duplicate computation. - /// - /// The validation hot path can return immediately after state root verification, - /// while consumers (DB writes, overlay providers, proofs) get trie data either - /// from the completed task or via fallback computation. - fn spawn_deferred_trie_task( - &self, - block: RecoveredBlock, - execution_outcome: Arc>, - ctx: &TreeCtx<'_, N>, - hashed_state: LazyHashedPostState, - trie_output: Arc, - changeset_provider: impl TrieCursorFactory + Send + 'static, - ) -> ExecutedBlock { - // Capture parent hash and ancestor overlays for deferred trie input construction. - let (anchor_hash, overlay_blocks) = ctx - .state() - .tree_state() - .blocks_by_hash(block.parent_hash()) - .unwrap_or_else(|| (block.parent_hash(), Vec::new())); - - // Collect lightweight ancestor trie data handles. We don't call trie_data() here; - // the merge and any fallback sorting happens in the compute_trie_input_task. - let ancestors: Vec = overlay_blocks - .iter() - .rev() - .map(|b| b.trie_data_handle()) - .collect(); - - // Create deferred handle with fallback inputs in case the background task hasn't completed. - // Resolve the lazy handle into Arc. By this point the hashed state has - // already been computed and used for state root verification, so .get() returns instantly. - let hashed_state = match hashed_state.try_into_inner() { - Ok(state) => Arc::new(state), - Err(handle) => Arc::new(handle.get().clone()), - }; - let deferred_trie_data = - DeferredTrieData::pending(hashed_state, trie_output, anchor_hash, ancestors); - let deferred_handle_task = deferred_trie_data.clone(); - let block_validation_metrics = self.metrics.block_validation.clone(); - - // Capture block info and cache handle for changeset computation - let block_hash = block.hash(); - let block_number = block.number(); - - // Register a pending changeset entry so that concurrent readers will wait for - // this computation to finish rather than falling back to the expensive DB path. - // The guard ensures the pending entry is cancelled if the task panics. - let pending_changeset_guard = self.changeset_cache.register_pending(block_hash); - - // Spawn background task to compute trie data. Calling `wait_cloned` will compute from - // the stored inputs and cache the result, so subsequent calls return immediately. - let compute_trie_input_task = move || { - let _span = debug_span!( - target: "engine::tree::payload_validator", - "compute_trie_input_task", - block_number - ) - .entered(); - - let result = panic::catch_unwind(AssertUnwindSafe(|| { - let compute_start = Instant::now(); - let computed = deferred_handle_task.wait_cloned(); - block_validation_metrics - .deferred_trie_compute_duration - .record(compute_start.elapsed().as_secs_f64()); - - // Record sizes of the computed trie data - block_validation_metrics - .hashed_post_state_size - .record(computed.hashed_state.total_len() as f64); - block_validation_metrics - .trie_updates_sorted_size - .record(computed.trie_updates.total_len() as f64); - if let Some(anchored) = &computed.anchored_trie_input { - block_validation_metrics - .anchored_overlay_trie_updates_size - .record(anchored.trie_input.nodes.total_len() as f64); - block_validation_metrics - .anchored_overlay_hashed_state_size - .record(anchored.trie_input.state.total_len() as f64); - } - - // Compute and cache changesets using the computed trie_updates. - // Use the pre-created provider to avoid races with changeset cache - // eviction that can happen between task spawn and execution. - let changeset_start = Instant::now(); - - match reth_trie::changesets::compute_trie_changesets( - &changeset_provider, - &computed.trie_updates, - ) { - Ok(changesets) => { - debug!( - target: "engine::tree::changeset", - ?block_number, - elapsed = ?changeset_start.elapsed(), - "Computed and caching changesets" - ); - - pending_changeset_guard.resolve(block_number, Arc::new(changesets)); - } - Err(e) => { - warn!( - target: "engine::tree::changeset", - ?block_number, - ?e, - "Failed to compute changesets in deferred trie task" - ); - } - } - })); - - if result.is_err() { - error!( - target: "engine::tree::payload_validator", - "Deferred trie task panicked; fallback computation will be used when trie data is accessed" - ); - } - }; - - // Spawn task that computes trie data asynchronously. - self.payload_processor - .executor() - .spawn_blocking_named("trie-input", compute_trie_input_task); - - ExecutedBlock::with_deferred_trie_data( - Arc::new(block), - execution_outcome, - deferred_trie_data, - ) - } - - fn calculate_timing_stats( - &self, - block: &RecoveredBlock, - provider_stats: Arc, - cache_stats: Option>, - output: &BlockExecutionOutput, - execution_duration: Duration, - state_hash_duration: Duration, - ) -> Box { - let accounts_read = provider_stats.total_account_fetches(); - let storage_read = provider_stats.total_storage_fetches(); - let code_read = provider_stats.total_code_fetches(); - let code_bytes_read = provider_stats.total_code_fetched_bytes(); - - // Write stats from BundleState (final state changes) - let accounts_changed = output.state.state.len(); - let accounts_deleted = output - .state - .state - .values() - .filter(|acc| acc.was_destroyed()) - .count(); - let storage_slots_changed = output - .state - .state - .values() - .map(|account| account.storage.len()) - .sum::(); - let storage_slots_deleted = output - .state - .state - .values() - .flat_map(|account| account.storage.values()) - .filter(|slot| { - slot.present_value.is_zero() && !slot.previous_or_original_value.is_zero() - }) - .count(); - - // Helper: check if account represents a new contract deployment - let is_new_deployment = |acc: &BundleAccount| -> bool { - let has_code_now = acc - .info - .as_ref() - .is_some_and(|info| info.code_hash != KECCAK_EMPTY); - let had_no_code_before = acc - .original_info - .as_ref() - .map(|info| info.code_hash == KECCAK_EMPTY) - .unwrap_or(true); - has_code_now && had_no_code_before - }; - - let bytecodes_changed = output - .state - .state - .values() - .filter(|acc| is_new_deployment(acc)) - .count(); - - // Unique new code hashes to count actual bytes persisted (deduplicated) - let unique_new_code_hashes: B256Set = output - .state - .state - .values() - .filter(|acc| is_new_deployment(acc)) - .filter_map(|acc| acc.info.as_ref().map(|info| info.code_hash)) - .collect(); - let code_bytes_written: usize = unique_new_code_hashes - .iter() - .filter_map(|hash| { - output - .state - .contracts - .get(hash) - .map(|bytecode| bytecode.original_bytes().len()) - }) - .sum(); - - // Total time spent fetching state during execution - let state_read_duration = provider_stats.total_account_fetch_latency() - + provider_stats.total_storage_fetch_latency() - + provider_stats.total_code_fetch_latency(); - - // EIP-7702 delegation tracking from bytecode changes - // Count new EIP-7702 bytecodes as delegations set - let eip7702_delegations_set = output - .state - .contracts - .values() - .filter(|bytecode| bytecode.is_eip7702()) - .count(); - // Delegations cleared: accounts where bytecode changed FROM EIP-7702 TO empty - // This detects when an EIP-7702 delegation is removed by setting code to empty - // Note: Clearing a delegation does NOT destroy the account - it just empties the - // bytecode - let eip7702_delegations_cleared = output - .state - .state - .values() - .filter(|acc| { - // Check if original bytecode was EIP-7702 - let original_was_eip7702 = acc - .original_info - .as_ref() - .and_then(|info| info.code.as_ref()) - .map(|bytecode| bytecode.is_eip7702()) - .unwrap_or(false); - - // Check if current code is empty (delegation cleared) - let code_now_empty = acc - .info - .as_ref() - .map(|info| info.code_hash == KECCAK_EMPTY) - .unwrap_or(false); - - original_was_eip7702 && code_now_empty - }) - .count(); - - // Get cache statistics for detailed block logging - let (account_cache_hits, account_cache_misses) = cache_stats - .as_ref() - .map(|s| (s.account_hits(), s.account_misses())) - .unwrap_or_default(); - let (storage_cache_hits, storage_cache_misses) = cache_stats - .as_ref() - .map(|s| (s.storage_hits(), s.storage_misses())) - .unwrap_or_default(); - let (code_cache_hits, code_cache_misses) = cache_stats - .as_ref() - .map(|s| (s.code_hits(), s.code_misses())) - .unwrap_or_default(); - - // Build execution timing stats for detailed block logging - Box::new(ExecutionTimingStats { - block_number: block.number(), - block_hash: block.hash(), - gas_used: output.result.gas_used, - tx_count: block.transaction_count(), - execution_duration, - state_read_duration, - state_hash_duration, - accounts_read, - storage_read, - code_read, - code_bytes_read, - accounts_changed, - accounts_deleted, - storage_slots_changed, - storage_slots_deleted, - bytecodes_changed, - code_bytes_written, - eip7702_delegations_set, - eip7702_delegations_cleared, - account_cache_hits, - account_cache_misses, - storage_cache_hits, - storage_cache_misses, - code_cache_hits, - code_cache_misses, - }) - } -} - -/// Strategy describing how to compute the state root. -#[derive(Debug, Clone, Copy, PartialEq, Eq)] -enum StateRootStrategy { - /// Use the state root task (background sparse trie computation). - StateRootTask, - /// Run the parallel state root computation on the calling thread. - Parallel, - /// Fall back to synchronous computation via the state provider. - Synchronous, -} - -impl EngineValidator for MorphBasicEngineValidator -where - P: DatabaseProviderFactory< - Provider: BlockReader - + StageCheckpointReader - + PruneCheckpointReader - + ChangeSetReader - + StorageChangeSetReader - + BlockNumReader - + StorageSettingsCache, - > + BlockReader
- + StateProviderFactory - + StateReader - + ChangeSetReader - + BlockNumReader - + HashedPostStateProvider - + Clone - + 'static, - N: NodePrimitives< - Block = morph_primitives::Block, - BlockHeader = MorphHeader, - SignedTx = MorphTxEnvelope, - >, - V: PayloadValidator + Clone, - Evm: ConfigureEngineEvm + 'static, - Types: PayloadTypes>, -{ - fn validate_payload_attributes_against_header( - &self, - attr: &Types::PayloadAttributes, - header: &N::BlockHeader, - ) -> Result<(), InvalidPayloadAttributesError> { - self.validator - .validate_payload_attributes_against_header(attr, header) - } - - fn convert_payload_to_block( - &self, - payload: Types::ExecutionData, - ) -> Result, NewPayloadError> { - let block = self.validator.convert_payload_to_block(payload)?; - Ok(block) - } - - fn validate_payload( - &mut self, - payload: Types::ExecutionData, - ctx: TreeCtx<'_, N>, - ) -> ValidationOutcome { - self.validate_block_with_state(BlockOrPayload::Payload(payload), ctx) - } - - fn validate_block( - &mut self, - block: SealedBlock, - ctx: TreeCtx<'_, N>, - ) -> ValidationOutcome { - self.validate_block_with_state(BlockOrPayload::Block(block), ctx) - } - - fn on_inserted_executed_block(&self, block: ExecutedBlock) { - self.payload_processor.on_inserted_executed_block( - block.recovered_block.block_with_parent(), - &block.execution_output.state, - ); - } - - fn cache_for(&self, block_hash: B256) -> Option { - Some(self.payload_processor.cache_for(block_hash)) - } - - fn sparse_trie_handle_for( - &self, - parent_hash: B256, - parent_state_root: B256, - state: &EngineApiTreeState, - ) -> Option { - let (lazy_overlay, anchor_hash) = Self::get_parent_lazy_overlay(parent_hash, state); - let overlay_builder = OverlayBuilder::::new(anchor_hash, self.changeset_cache.clone()) - .with_lazy_overlay(lazy_overlay); - let overlay_factory = - OverlayStateProviderFactory::new(self.provider.clone(), overlay_builder); - - Some(self.payload_processor.spawn_state_root( - overlay_factory, - parent_state_root, - // Full proof workers — tx count unknown at FCU time (block built incrementally) - false, - &self.config, - )) - } -} - -impl WaitForCaches for MorphBasicEngineValidator -where - Evm: ConfigureEvm, -{ - fn wait_for_caches(&self) -> CacheWaitDurations { - self.payload_processor.wait_for_caches() - } -} - -/// Enum representing either block or payload being validated. -#[derive(Debug, Clone)] -pub enum BlockOrPayload { - /// Payload. - Payload(T::ExecutionData), - /// Block. - Block(SealedBlock::Primitives>>), -} - -impl BlockOrPayload { - /// Returns the hash of the block. - pub fn hash(&self) -> B256 { - match self { - Self::Payload(payload) => payload.block_hash(), - Self::Block(block) => block.hash(), - } - } - - /// Returns the number and hash of the block. - pub fn num_hash(&self) -> NumHash { - match self { - Self::Payload(payload) => payload.num_hash(), - Self::Block(block) => block.num_hash(), - } - } - - /// Returns the parent hash of the block. - pub fn parent_hash(&self) -> B256 { - match self { - Self::Payload(payload) => payload.parent_hash(), - Self::Block(block) => block.parent_hash(), - } - } - - /// Returns [`BlockWithParent`] for the block. - pub fn block_with_parent(&self) -> BlockWithParent { - match self { - Self::Payload(payload) => payload.block_with_parent(), - Self::Block(block) => block.block_with_parent(), - } - } - - /// Returns a string showing whether or not this is a block or payload. - pub const fn type_name(&self) -> &'static str { - match self { - Self::Payload(_) => "payload", - Self::Block(_) => "block", - } - } - - /// Returns the block access list if available. - pub const fn block_access_list(&self) -> Option> { - // TODO decode and return `BlockAccessList` - None - } - - /// Returns the number of transactions in the payload or block. - pub fn transaction_count(&self) -> usize - where - T::ExecutionData: ExecutionPayload, - { - match self { - Self::Payload(payload) => payload.transaction_count(), - Self::Block(block) => block.transaction_count(), - } - } - - /// Returns the withdrawals from the payload or block. - pub fn withdrawals(&self) -> Option<&[Withdrawal]> - where - T::ExecutionData: ExecutionPayload, - { - match self { - Self::Payload(payload) => payload.withdrawals().map(|w| w.as_slice()), - Self::Block(block) => block.body().withdrawals().map(|w| w.as_slice()), - } - } - - /// Returns the total gas used by the block. - pub fn gas_used(&self) -> u64 - where - T::ExecutionData: ExecutionPayload, - { - match self { - Self::Payload(payload) => payload.gas_used(), - Self::Block(block) => block.gas_used(), - } - } -} diff --git a/crates/engine-tree-ext/src/trie_updates.rs b/crates/engine-tree-ext/src/trie_updates.rs deleted file mode 100644 index 3ac7b52..0000000 --- a/crates/engine-tree-ext/src/trie_updates.rs +++ /dev/null @@ -1,357 +0,0 @@ -use alloy_primitives::{ - B256, - map::{B256Map, HashMap}, -}; -use reth_db::DatabaseError; -use reth_trie::{ - BranchNodeCompact, Nibbles, - trie_cursor::{TrieCursor, TrieCursorFactory}, - updates::{StorageTrieUpdates, TrieUpdates}, -}; -use std::collections::BTreeSet; -use tracing::warn; - -#[derive(Debug)] -struct EntryDiff { - task: T, - regular: T, - database: T, -} - -#[derive(Debug, Default)] -struct TrieUpdatesDiff { - account_nodes: HashMap>>, - removed_nodes: HashMap>, - storage_tries: B256Map, -} - -impl TrieUpdatesDiff { - fn has_differences(&self) -> bool { - !self.account_nodes.is_empty() - || !self.removed_nodes.is_empty() - || !self.storage_tries.is_empty() - } - - pub(super) fn log_differences(mut self) { - if self.has_differences() { - for ( - path, - EntryDiff { - task, - regular, - database, - }, - ) in &mut self.account_nodes - { - warn!(target: "engine::tree", ?path, ?task, ?regular, ?database, "Difference in account trie updates"); - } - - for ( - path, - EntryDiff { - task: task_removed, - regular: regular_removed, - database: database_not_exists, - }, - ) in &self.removed_nodes - { - warn!(target: "engine::tree", ?path, ?task_removed, ?regular_removed, ?database_not_exists, "Difference in removed account trie nodes"); - } - - for (address, storage_diff) in self.storage_tries { - storage_diff.log_differences(address); - } - } - } -} - -#[derive(Debug, Default)] -struct StorageTrieUpdatesDiff { - is_deleted: Option>, - storage_nodes: HashMap>>, - removed_nodes: HashMap>, -} - -impl StorageTrieUpdatesDiff { - fn has_differences(&self) -> bool { - self.is_deleted.is_some() - || !self.storage_nodes.is_empty() - || !self.removed_nodes.is_empty() - } - - fn log_differences(&self, address: B256) { - if let Some(EntryDiff { - task: task_deleted, - regular: regular_deleted, - database: database_not_exists, - }) = self.is_deleted - { - warn!(target: "engine::tree", ?address, ?task_deleted, ?regular_deleted, ?database_not_exists, "Difference in storage trie deletion"); - } - - for ( - path, - EntryDiff { - task, - regular, - database, - }, - ) in &self.storage_nodes - { - warn!(target: "engine::tree", ?address, ?path, ?task, ?regular, ?database, "Difference in storage trie updates"); - } - - for ( - path, - EntryDiff { - task: task_removed, - regular: regular_removed, - database: database_not_exists, - }, - ) in &self.removed_nodes - { - warn!(target: "engine::tree", ?address, ?path, ?task_removed, ?regular_removed, ?database_not_exists, "Difference in removed storage trie nodes"); - } - } -} - -/// Compares the trie updates from state root task, regular state root calculation and database, -/// and logs the differences if there's any. -/// -/// Returns `true` if there are differences. -pub(crate) fn compare_trie_updates( - trie_cursor_factory: impl TrieCursorFactory, - task: TrieUpdates, - regular: TrieUpdates, -) -> Result { - let mut task = adjust_trie_updates(task); - let mut regular = adjust_trie_updates(regular); - - let mut diff = TrieUpdatesDiff::default(); - - // compare account nodes - let mut account_trie_cursor = trie_cursor_factory.account_trie_cursor()?; - for key in task - .account_nodes - .keys() - .chain(regular.account_nodes.keys()) - .copied() - .collect::>() - { - let (task, regular) = ( - task.account_nodes.remove(&key), - regular.account_nodes.remove(&key), - ); - let database = account_trie_cursor.seek_exact(key)?.map(|x| x.1); - - if !branch_nodes_equal(task.as_ref(), regular.as_ref(), database.as_ref())? { - diff.account_nodes.insert( - key, - EntryDiff { - task, - regular, - database, - }, - ); - } - } - - // compare removed nodes - let mut account_trie_cursor = trie_cursor_factory.account_trie_cursor()?; - for key in task - .removed_nodes - .iter() - .chain(regular.removed_nodes.iter()) - .copied() - .collect::>() - { - let (task_removed, regular_removed) = ( - task.removed_nodes.contains(&key), - regular.removed_nodes.contains(&key), - ); - let database_not_exists = account_trie_cursor.seek_exact(key)?.is_none(); - // If the deletion is a no-op, meaning that the entry is not in the - // database, do not add it to the diff. - if task_removed != regular_removed && !database_not_exists { - diff.removed_nodes.insert( - key, - EntryDiff { - task: task_removed, - regular: regular_removed, - database: database_not_exists, - }, - ); - } - } - - // compare storage tries - for key in task - .storage_tries - .keys() - .chain(regular.storage_tries.keys()) - .copied() - .collect::>() - { - let (mut task, mut regular) = ( - task.storage_tries.remove(&key), - regular.storage_tries.remove(&key), - ); - if task != regular { - #[expect(clippy::or_fun_call)] - let storage_diff = compare_storage_trie_updates( - || trie_cursor_factory.storage_trie_cursor(key), - // Compare non-existent storage tries as empty. - task.as_mut().unwrap_or(&mut Default::default()), - regular.as_mut().unwrap_or(&mut Default::default()), - )?; - if storage_diff.has_differences() { - diff.storage_tries.insert(key, storage_diff); - } - } - } - - // log differences - let has_differences = diff.has_differences(); - diff.log_differences(); - - Ok(has_differences) -} - -fn compare_storage_trie_updates( - trie_cursor: impl Fn() -> Result, - task: &mut StorageTrieUpdates, - regular: &mut StorageTrieUpdates, -) -> Result { - // Check if the storage trie exists by seeking to the first entry - let database_not_exists = trie_cursor()?.seek(Nibbles::default())?.is_none(); - let mut diff = StorageTrieUpdatesDiff { - // If the deletion is a no-op, meaning that the entry is not in the - // database, do not add it to the diff. - is_deleted: (task.is_deleted != regular.is_deleted && !database_not_exists).then_some( - EntryDiff { - task: task.is_deleted, - regular: regular.is_deleted, - database: database_not_exists, - }, - ), - ..Default::default() - }; - - // compare storage nodes - let mut storage_trie_cursor = trie_cursor()?; - for key in task - .storage_nodes - .keys() - .chain(regular.storage_nodes.keys()) - .copied() - .collect::>() - { - let (task, regular) = ( - task.storage_nodes.remove(&key), - regular.storage_nodes.remove(&key), - ); - let database = storage_trie_cursor.seek_exact(key)?.map(|x| x.1); - if !branch_nodes_equal(task.as_ref(), regular.as_ref(), database.as_ref())? { - diff.storage_nodes.insert( - key, - EntryDiff { - task, - regular, - database, - }, - ); - } - } - - // compare removed nodes - let mut storage_trie_cursor = trie_cursor()?; - for key in task - .removed_nodes - .iter() - .chain(regular.removed_nodes.iter()) - .collect::>() - { - let (task_removed, regular_removed) = ( - task.removed_nodes.contains(key), - regular.removed_nodes.contains(key), - ); - if task_removed == regular_removed { - continue; - } - let database_not_exists = storage_trie_cursor.seek_exact(*key)?.map(|x| x.1).is_none(); - // If the deletion is a no-op, meaning that the entry is not in the - // database, do not add it to the diff. - if !database_not_exists { - diff.removed_nodes.insert( - *key, - EntryDiff { - task: task_removed, - regular: regular_removed, - database: database_not_exists, - }, - ); - } - } - - Ok(diff) -} - -/// Filters the removed nodes of both account trie updates and storage trie updates, so that they -/// don't include those nodes that were also updated. -fn adjust_trie_updates(trie_updates: TrieUpdates) -> TrieUpdates { - TrieUpdates { - removed_nodes: trie_updates - .removed_nodes - .into_iter() - .filter(|key| !trie_updates.account_nodes.contains_key(key)) - .collect(), - storage_tries: trie_updates - .storage_tries - .into_iter() - .map(|(address, updates)| { - ( - address, - StorageTrieUpdates { - removed_nodes: updates - .removed_nodes - .into_iter() - .filter(|key| !updates.storage_nodes.contains_key(key)) - .collect(), - ..updates - }, - ) - }) - .collect(), - ..trie_updates - } -} - -/// Compares the branch nodes from state root task and regular state root calculation. -/// -/// If one of the branch nodes is [`None`], it means it's not updated and the other is compared to -/// the branch node from the database. -/// -/// Returns `true` if they are equal. -fn branch_nodes_equal( - task: Option<&BranchNodeCompact>, - regular: Option<&BranchNodeCompact>, - database: Option<&BranchNodeCompact>, -) -> Result { - Ok(match (task, regular) { - (Some(task), Some(regular)) => { - task.state_mask == regular.state_mask - && task.tree_mask == regular.tree_mask - && task.hash_mask == regular.hash_mask - && task.hashes == regular.hashes - && task.root_hash == regular.root_hash - } - (None, None) => true, - _ => { - if task.is_some() { - task == database - } else { - regular == database - } - } - }) -} diff --git a/crates/engine-tree-ext/tests/jade_boundary.rs b/crates/engine-tree-ext/tests/jade_boundary.rs deleted file mode 100644 index 7f5d846..0000000 --- a/crates/engine-tree-ext/tests/jade_boundary.rs +++ /dev/null @@ -1,212 +0,0 @@ -//! End-to-end verification of retroactive trust across the Jade hardfork -//! boundary. -//! -//! These tests exercise the `MorphBasicEngineValidator` through the real -//! `MorphNode` stack: they spin up an ephemeral node, build a valid block, -//! tamper with the header's `state_root`, and re-import via the Engine API. -//! -//! Retroactive-trust invariants: -//! * Pre-Jade: header state root is NOT compared against the MPT root the -//! validator computes — a mismatched `state_root` must still import. -//! * Post-Jade: the validator enforces strict MPT equality — the same -//! tampered `state_root` must be rejected as INVALID. -//! -//! Two existing sibling tests verify these invariants at the crate-of-use -//! level (`crates/node/tests/it/engine.rs::state_root_validation_skipped_pre_jade` -//! and `crates/node/tests/it/consensus.rs::post_jade_state_root_mismatch_is_rejected`). -//! The tests in this file pin the contract to the engine-tree-ext crate: if -//! someone tweaks `MorphBasicEngineValidator` in a way that breaks the -//! boundary, `cargo test -p morph-engine-tree-ext` is expected to catch it. - -#![cfg(feature = "test-utils")] - -use alloy_consensus::{BlockHeader, proofs}; -use alloy_primitives::{Address, B256}; -use alloy_rpc_types_engine::PayloadAttributes; -use morph_node::test_utils::{HardforkSchedule, MorphTestNode, TestNodeBuilder}; -use morph_payload_types::{MorphBuiltPayload, MorphPayloadAttributes, MorphPayloadTypes}; -use reth_node_api::PayloadTypes; -use reth_payload_builder::BuildNewPayload; -use reth_payload_primitives::BuiltPayload; -use reth_primitives_traits::SealedBlock; -use reth_provider::BlockReaderIdExt; - -/// Build an empty block through the payload builder without submitting it. -/// -/// `node.advance_block()` would time out waiting for a non-empty payload since -/// the pool is empty — instead, drive the builder directly with empty L1 -/// messages and resolve the payload synchronously via -/// `PayloadKind::WaitForPending`. This avoids fixed sleeps + polling, which -/// were flake-prone on loaded CI runners. -async fn build_candidate_block(node: &mut MorphTestNode) -> eyre::Result { - const BUILD_TIMEOUT: std::time::Duration = std::time::Duration::from_secs(30); - - let head = node - .inner - .provider - .sealed_header_by_number_or_tag(alloy_rpc_types_eth::BlockNumberOrTag::Latest)?; - let (head_hash, head_ts) = head - .map(|h| (h.hash(), h.timestamp())) - .unwrap_or((B256::ZERO, 0)); - - let rpc_attrs = MorphPayloadAttributes { - inner: PayloadAttributes { - timestamp: head_ts + 1, - prev_randao: B256::ZERO, - suggested_fee_recipient: Address::ZERO, - withdrawals: Some(vec![]), - parent_beacon_block_root: Some(B256::ZERO), - }, - transactions: Some(vec![]), - gas_limit: None, - base_fee_per_gas: None, - }; - - let payload_id = node - .inner - .payload_builder_handle - .send_new_payload(BuildNewPayload { - attributes: rpc_attrs, - parent_hash: head_hash, - cache: None, - trie_handle: None, - }) - .await? - .map_err(|e| eyre::eyre!("payload build failed: {e}"))?; - - tokio::time::timeout( - BUILD_TIMEOUT, - node.inner - .payload_builder_handle - .resolve_kind(payload_id, reth_node_api::PayloadKind::WaitForPending), - ) - .await - .map_err(|_| eyre::eyre!("payload build timed out after {:?}", BUILD_TIMEOUT))? - .ok_or_else(|| eyre::eyre!("no payload response for id {payload_id:?}"))? - .map_err(|e| eyre::eyre!("payload build error: {e}")) -} - -/// Tamper with a payload's header and ask the engine to import the result. -/// -/// Returns `true` if the engine accepted the block (VALID), `false` otherwise. -async fn try_import_with_tampered_state_root( - node: &mut MorphTestNode, - base: &MorphBuiltPayload, - bogus_state_root: B256, -) -> eyre::Result { - let sealed = base.block(); - let morph_header: morph_primitives::MorphHeader = sealed.header().inner.clone().into(); - let body = sealed.body().clone(); - let mut block = morph_primitives::Block::new(morph_header, body); - - block.header.inner.state_root = bogus_state_root; - block.header.inner.transactions_root = - proofs::calculate_transaction_root(&block.body.transactions); - - let modified_sealed = SealedBlock::seal_slow(block); - let execution_data = MorphPayloadTypes::block_to_payload(modified_sealed); - let status = node - .inner - .add_ons_handle - .beacon_engine_handle - .new_payload(execution_data) - .await?; - - Ok(status.is_valid()) -} - -#[tokio::test(flavor = "multi_thread")] -async fn pre_jade_block_with_tampered_state_root_imports() -> eyre::Result<()> { - reth_tracing::init_test_tracing(); - - let (mut nodes, _wallet) = TestNodeBuilder::new() - .with_schedule(HardforkSchedule::PreJade) - .build() - .await?; - let mut node = nodes.pop().unwrap(); - - let base_payload = build_candidate_block(&mut node).await?; - let accepted = - try_import_with_tampered_state_root(&mut node, &base_payload, B256::from([0xFF; 32])) - .await?; - - assert!( - accepted, - "pre-Jade block with tampered state_root must be accepted — retroactive trust skips \ - state-root validation before Jade" - ); - Ok(()) -} - -#[tokio::test(flavor = "multi_thread")] -async fn post_jade_block_with_tampered_state_root_is_rejected() -> eyre::Result<()> { - reth_tracing::init_test_tracing(); - - let (mut nodes, _wallet) = TestNodeBuilder::new() - .with_schedule(HardforkSchedule::AllActive) - .build() - .await?; - let mut node = nodes.pop().unwrap(); - - let base_payload = build_candidate_block(&mut node).await?; - let accepted = - try_import_with_tampered_state_root(&mut node, &base_payload, B256::from([0xFF; 32])) - .await?; - - assert!( - !accepted, - "post-Jade block with tampered state_root must be rejected — MorphBasicEngineValidator \ - enforces strict MPT root equality after Jade" - ); - Ok(()) -} - -/// Regression test: P2P-downloaded blocks enter the engine tree via the -/// Block-input path (`insert_block`), which never invokes -/// `convert_payload_to_block` and therefore registers no withdraw-trie-root -/// expectation. The validator must treat the missing entry as -/// `SkipValidation` so the downloaded block is accepted; otherwise sync -/// stalls indefinitely with `"missing withdraw trie root expectation -/// cache entry"`. -/// -/// The test runs two interconnected nodes: node[0] builds and imports a -/// block via the Engine API (Payload path → expectation registered on -/// node[0] only), then node[1] points its forkchoice at the new head so -/// reth's downloader fetches the block from node[0] over P2P. The download -/// lands in node[1]'s engine tree as a `Block` input. -#[tokio::test(flavor = "multi_thread")] -async fn p2p_downloaded_block_imports_without_registered_expectation() -> eyre::Result<()> { - reth_tracing::init_test_tracing(); - - let (mut nodes, _wallet) = TestNodeBuilder::new() - .with_schedule(HardforkSchedule::AllActive) - .with_num_nodes(2) - .build() - .await?; - let node1 = nodes.pop().expect("two nodes requested"); - let mut node0 = nodes.pop().expect("two nodes requested"); - - let payload = build_candidate_block(&mut node0).await?; - let head_hash = payload.block().hash(); - - let exec_data = MorphPayloadTypes::block_to_payload(payload.block().clone()); - let status = node0 - .inner - .add_ons_handle - .beacon_engine_handle - .new_payload(exec_data) - .await?; - assert!( - status.is_valid(), - "node[0] must accept its own freshly-built block, got {status:?}" - ); - node0.update_forkchoice(head_hash, head_hash).await?; - - // sync_to keeps issuing FCU until node[1]'s head matches `head_hash`. - // Since node[1] does not have the block, reth's engine tree will trigger - // its block downloader against the connected peer (node[0]) — downloaded - // blocks enter via the Block input path, exercising the bug. - node1.sync_to(head_hash).await?; - - Ok(()) -} diff --git a/crates/evm/Cargo.toml b/crates/evm/Cargo.toml index a9f9cf1..282f098 100644 --- a/crates/evm/Cargo.toml +++ b/crates/evm/Cargo.toml @@ -27,6 +27,7 @@ reth-rpc-eth-api = { workspace = true, optional = true } alloy-evm.workspace = true alloy-consensus.workspace = true alloy-primitives.workspace = true +alloy-rpc-types-eth.workspace = true derive_more.workspace = true thiserror.workspace = true diff --git a/crates/evm/src/block/mod.rs b/crates/evm/src/block/mod.rs index 6292f88..42ce326 100644 --- a/crates/evm/src/block/mod.rs +++ b/crates/evm/src/block/mod.rs @@ -19,8 +19,7 @@ use alloy_consensus::transaction::TxHashRef; use alloy_evm::{ Database, Evm, RecoveredTx, block::{ - BlockExecutionError, BlockExecutionResult, BlockExecutor, ExecutableTx, GasOutput, - OnStateHook, StateChangeSource, TxResult, + BlockExecutionError, BlockExecutionResult, BlockExecutor, ExecutableTx, GasOutput, TxResult, }, }; use alloy_primitives::{Address, Log, U256}; @@ -96,9 +95,6 @@ pub struct MorphBlockExecutor { /// Cached hardfork for this block (constant across all transactions). /// Set in `apply_pre_execution_changes`, reused in `commit_transaction`. hardfork: MorphHardfork, - /// Hook for notifying the engine about per-transaction state changes. - /// Used by `StateRootTask` for incremental sparse trie computation. - state_hook: Option>, } impl MorphBlockExecutor @@ -124,7 +120,6 @@ where receipts: Vec::new(), gas_used: 0, hardfork: MorphHardfork::default(), - state_hook: None, } } @@ -275,11 +270,6 @@ where post_fee_logs, } = output; - // Notify the state hook (e.g. StateRootTask) BEFORE committing. - if let Some(hook) = &mut self.state_hook { - hook.on_state(StateChangeSource::Transaction(self.receipts.len()), &state); - } - // EIP-8037 separates regular and state gas; pre-Amsterdam morph treats // them as a single number, so use the unified `tx_gas_used` getter. let gas_used = result.gas().tx_gas_used(); @@ -334,10 +324,6 @@ where )) } - fn set_state_hook(&mut self, hook: Option>) { - self.state_hook = hook; - } - fn evm_mut(&mut self) -> &mut Self::Evm { &mut self.evm } diff --git a/crates/evm/src/context.rs b/crates/evm/src/context.rs index 083a030..de01f68 100644 --- a/crates/evm/src/context.rs +++ b/crates/evm/src/context.rs @@ -17,9 +17,10 @@ impl reth_rpc_eth_api::helpers::pending_block::BuildPendingEnv, + block_overrides: Option<&alloy_rpc_types_eth::BlockOverrides>, ) -> Self { Self { - inner: NextBlockEnvAttributes::build_pending_env(parent), + inner: NextBlockEnvAttributes::build_pending_env(parent, block_overrides), base_fee_per_gas: None, } } diff --git a/crates/evm/src/evm.rs b/crates/evm/src/evm.rs index 9600501..e2454e4 100644 --- a/crates/evm/src/evm.rs +++ b/crates/evm/src/evm.rs @@ -4,7 +4,7 @@ use alloy_evm::{ revm::{ Context, ExecuteEvm, InspectEvm, Inspector, SystemCallEvm, context::{ - CfgEnv, + CfgEnv, DBErrorMarker, result::{EVMError, ResultAndState}, }, inspector::NoOpInspector, @@ -26,8 +26,7 @@ impl EvmFactory for MorphEvmFactory { type Evm>> = MorphEvm; type Context = MorphContext; type Tx = MorphTxEnv; - type Error = - EVMError; + type Error = EVMError; type HaltReason = MorphHaltReason; type Spec = MorphHardfork; type BlockEnv = MorphBlockEnv; diff --git a/crates/node/Cargo.toml b/crates/node/Cargo.toml index 3c6eca3..53257bb 100644 --- a/crates/node/Cargo.toml +++ b/crates/node/Cargo.toml @@ -14,7 +14,6 @@ workspace = true morph-chainspec.workspace = true morph-consensus.workspace = true morph-engine-api.workspace = true -morph-engine-tree-ext.workspace = true morph-evm.workspace = true morph-payload-builder.workspace = true morph-payload-types.workspace = true @@ -26,11 +25,14 @@ morph-txpool.workspace = true # Reth dependencies reth-db.workspace = true reth-db-api.workspace = true +reth-chain-state.workspace = true reth-node-core.workspace = true reth-chainspec.workspace = true reth-engine-local.workspace = true reth-engine-tree.workspace = true reth-errors.workspace = true +reth-evm.workspace = true +reth-execution-cache.workspace = true reth-exex.workspace = true reth-node-api.workspace = true reth-node-builder.workspace = true @@ -77,7 +79,7 @@ alloy-signer = { workspace = true, optional = true } alloy-signer-local = { workspace = true, optional = true } [build-dependencies] -vergen.workspace = true +vergen = { workspace = true, features = ["build", "cargo", "emit_and_set"] } vergen-git2.workspace = true [dev-dependencies] diff --git a/crates/node/build.rs b/crates/node/build.rs index d068046..6a83410 100644 --- a/crates/node/build.rs +++ b/crates/node/build.rs @@ -1,26 +1,23 @@ #![allow(missing_docs)] use std::{env, error::Error}; -use vergen::{BuildBuilder, CargoBuilder, Emitter}; -use vergen_git2::Git2Builder; +use vergen::{Build, Cargo, Emitter}; +use vergen_git2::Git2; fn main() -> Result<(), Box> { let mut emitter = Emitter::default(); - let build_builder = BuildBuilder::default().build_timestamp(true).build()?; + let build_builder = Build::builder().build_timestamp(true).build(); emitter.add_instructions(&build_builder)?; - let cargo_builder = CargoBuilder::default() - .features(true) - .target_triple(true) - .build()?; + let cargo_builder = Cargo::builder().features(true).target_triple(true).build(); emitter.add_instructions(&cargo_builder)?; - let git_builder = Git2Builder::default() + let git_builder = Git2::builder() .describe(false, true, None) .dirty(true) .sha(false) - .build()?; + .build(); emitter.add_instructions(&git_builder)?; emitter.emit_and_set()?; diff --git a/crates/node/src/node.rs b/crates/node/src/node.rs index 5256862..347cef9 100644 --- a/crates/node/src/node.rs +++ b/crates/node/src/node.rs @@ -213,6 +213,7 @@ impl PayloadAttributesBuilder .then(B256::random), // Morph L2 has no PoS slot semantics; field added in alloy 2.0. slot_number: None, + target_gas_limit: None, }, // No L1 transactions in local mining mode transactions: None, diff --git a/crates/node/src/test_utils.rs b/crates/node/src/test_utils.rs index d8f50d0..d58cfe5 100644 --- a/crates/node/src/test_utils.rs +++ b/crates/node/src/test_utils.rs @@ -354,6 +354,7 @@ pub async fn advance_empty_block(node: &mut MorphTestNode) -> eyre::Result eyre::Result morph_payload_types::MorphPay withdrawals: Some(vec![]), parent_beacon_block_root: Some(B256::ZERO), slot_number: None, + target_gas_limit: None, }, transactions: None, gas_limit: None, diff --git a/crates/node/src/validator.rs b/crates/node/src/validator.rs index b43e9c3..ab88e2a 100644 --- a/crates/node/src/validator.rs +++ b/crates/node/src/validator.rs @@ -6,12 +6,26 @@ use alloy_primitives::{B256, keccak256}; use dashmap::DashMap; use morph_chainspec::{ L2_MESSAGE_QUEUE_ADDRESS, L2_MESSAGE_QUEUE_WITHDRAW_TRIE_ROOT_SLOT, MorphChainSpec, + MorphHardforks, }; use morph_payload_types::{MorphExecutionData, MorphPayloadTypes}; -use morph_primitives::MorphHeader; +use morph_primitives::{MorphHeader, MorphPrimitives}; use parking_lot::Mutex; +use reth_chain_state::{ExecutedBlock, StateTrieOverlayManager}; use reth_chainspec::EthChainSpec; -use reth_errors::ConsensusError; +use reth_engine_tree::tree::payload_validator::TreeCtx; +use reth_engine_tree::tree::{ + BasicEngineValidator, CacheWaitDurations, EngineApiTreeState, EngineValidator, WaitForCaches, + error::{InsertBlockError, InsertBlockErrorKind}, + state_root_strategy::{ + DefaultStateRootStrategy, LazyHashedPostState, PayloadStateRootHandle, + PayloadStateRootJobContext, PreparedStateRootJob, StateRootJob, StateRootJobContext, + StateRootJobOutcome, StateRootStrategy, + }, +}; +use reth_errors::{ConsensusError, ProviderResult}; +use reth_evm::{ConfigureEvm, revm::context::Block as _}; +use reth_execution_cache::SavedCache; use reth_node_api::{ AddOnsContext, FullNodeComponents, InvalidPayloadAttributesError, NewPayloadError, NodeTypes, PayloadAttributes, PayloadTypes, PayloadValidator, @@ -20,8 +34,12 @@ use reth_node_builder::{ invalid_block_hook::InvalidBlockHookExt, rpc::{EngineValidatorBuilder, PayloadValidatorBuilder}, }; +use reth_payload_primitives::BuiltPayloadExecutedBlock; use reth_primitives_traits::{RecoveredBlock, SealedBlock}; -use reth_provider::ChainSpecProvider; +use reth_provider::{ + BlockExecutionOutput, BlockReader, ChainSpecProvider, StateProviderFactory, StateReader, + StateRootProvider, +}; use reth_tracing::tracing; use std::{collections::VecDeque, sync::Arc}; @@ -80,20 +98,16 @@ where >, >, Node::Provider: ChainSpecProvider, - PVB: PayloadValidatorBuilder, - PVB::Validator: reth_node_api::PayloadValidator< - ::Payload, - Block = reth_node_api::BlockTy, - > + Clone, + PVB: PayloadValidatorBuilder, { - type EngineValidator = - morph_engine_tree_ext::MorphBasicEngineValidator; + type EngineValidator = MorphTreeEngineValidator; async fn build_tree_validator( self, ctx: &AddOnsContext<'_, Node>, tree_config: reth_node_api::TreeConfig, changeset_cache: reth_trie_db::ChangesetCache, + state_trie_overlays: StateTrieOverlayManager, ) -> eyre::Result { let validator = self.payload_validator_builder.build(ctx).await?; let data_dir = ctx @@ -103,17 +117,346 @@ where .resolve_datadir(ctx.config.chain.chain()); let invalid_block_hook = ctx.create_invalid_block_hook(&data_dir).await?; let chain_spec = ctx.node.provider().chain_spec(); - - Ok(morph_engine_tree_ext::MorphBasicEngineValidator::new( - ctx.node.provider().clone(), + let post_execution_validator = validator.clone(); + + let provider = ctx.node.provider().clone(); + let state_root_strategy: Arc< + dyn StateRootStrategy, + > = Arc::new(MorphStateRootStrategy::new(chain_spec.clone())); + let tree_config = strict_morph_tree_config(tree_config); + let validator = BasicEngineValidator::new( + provider.clone(), Arc::new(ctx.node.consensus().clone()), ctx.node.evm_config().clone(), validator, tree_config, invalid_block_hook, changeset_cache, + state_trie_overlays, ctx.node.task_executor().clone(), + ) + .with_state_root_strategy(state_root_strategy); + + Ok(MorphTreeEngineValidator::new( + validator, + provider, + chain_spec, + post_execution_validator, + )) + } +} + +/// Morph only relaxes the header-root equality check before Jade, through +/// [`MorphStateRootStrategy`]. The upstream debug skip also suppresses trie +/// updates, so allowing it here would make both pre-Jade persistence and +/// post-Jade validation unsafe. +fn strict_morph_tree_config(tree_config: reth_node_api::TreeConfig) -> reth_node_api::TreeConfig { + if tree_config.skip_state_root() { + tracing::warn!( + target: "reth::cli", + "ignoring --debug.skip-state-root: Morph requires trie updates before Jade and strict state-root validation from Jade onward" + ); + } + tree_config.with_skip_state_root(false) +} + +/// Upstream engine validator plus Morph-specific validation hooks. +/// +/// State execution, caching and trie maintenance remain entirely upstream. This +/// wrapper preserves the parent-aware L1 queue invariant and the optional +/// consensus-layer withdraw-trie-root cross-check. +pub struct MorphTreeEngineValidator +where + Evm: ConfigureEvm, +{ + inner: BasicEngineValidator, + provider: P, + chain_spec: Arc, + post_execution_validator: MorphEngineValidator, +} + +impl MorphTreeEngineValidator +where + Evm: ConfigureEvm, +{ + const fn new( + inner: BasicEngineValidator, + provider: P, + chain_spec: Arc, + post_execution_validator: MorphEngineValidator, + ) -> Self { + Self { + inner, + provider, + chain_spec, + post_execution_validator, + } + } +} + +impl MorphTreeEngineValidator +where + Evm: ConfigureEvm, + P: BlockReader
, +{ + fn validate_next_l1_msg_index( + &self, + block: &SealedBlock, + ctx: &TreeCtx<'_, MorphPrimitives>, + ) -> Result<(), InsertBlockErrorKind> { + if !self + .chain_spec + .is_jade_active_at_timestamp(block.header().timestamp()) + { + return Ok(()); + } + + let parent_hash = block.parent_hash(); + let parent = match ctx.state().tree_state().sealed_header_by_hash(&parent_hash) { + Some(parent) => Some(parent), + None => self.provider.sealed_header_by_hash(parent_hash)?, + }; + let Some(parent) = parent else { + // The upstream validator reports the missing parent with the + // canonical provider error before executing the block. + return Ok(()); + }; + + let mut expected = parent.next_l1_msg_index; + for tx in block.body().transactions() { + if !tx.is_l1_msg() { + break; + } + let queue_index = tx.queue_index().ok_or_else(|| { + ConsensusError::msg("L1 message transaction is missing queue index") + })?; + expected = queue_index.checked_add(1).ok_or_else(|| { + ConsensusError::msg(format!( + "invalid block.NextL1MsgIndex: expected {}, got {}", + u64::MAX, + block.header().next_l1_msg_index + )) + })?; + } + + let actual = block.header().next_l1_msg_index; + if actual != expected { + return Err(ConsensusError::msg(format!( + "invalid block.NextL1MsgIndex: expected {expected}, got {actual}" + )) + .into()); + } + Ok(()) + } + + fn validate_next_l1_msg_index_for_block( + &self, + block: &SealedBlock, + ctx: &TreeCtx<'_, MorphPrimitives>, + ) -> Result<(), reth_engine_tree::tree::error::InsertPayloadError> + { + self.validate_next_l1_msg_index(block, ctx) + .map_err(|kind| InsertBlockError::new(block.clone(), kind).into()) + } + + fn validate_withdraw_trie_root( + &self, + output: reth_engine_tree::tree::ValidationOutput, + ) -> reth_engine_tree::tree::ValidationOutcome { + let block = output.executed_block.recovered_block(); + if let Err(err) = self + .post_execution_validator + .validate_withdraw_trie_root_update(block.hash(), || { + output.executed_block.hashed_state() + }) + { + return Err(InsertBlockError::consensus_error( + err, + output.executed_block.sealed_block().clone(), + ) + .into()); + } + + Ok(output) + } +} + +impl EngineValidator + for MorphTreeEngineValidator +where + P: BlockReader
+ Send + Sync + 'static, + Evm: ConfigureEvm + 'static, + BasicEngineValidator: + EngineValidator, +{ + fn validate_payload_attributes_against_header( + &self, + attr: &::PayloadAttributes, + header: &MorphHeader, + ) -> Result<(), InvalidPayloadAttributesError> { + self.inner + .validate_payload_attributes_against_header(attr, header) + } + + fn convert_payload_to_block( + &self, + payload: MorphExecutionData, + ) -> Result, NewPayloadError> { + self.inner.convert_payload_to_block(payload) + } + + fn validate_payload( + &mut self, + payload: MorphExecutionData, + ctx: TreeCtx<'_, MorphPrimitives>, + ) -> reth_engine_tree::tree::ValidationOutcome { + let block_hash = payload.block.hash(); + // `convert_payload_to_block` may already have registered a withdraw-root + // expectation for this hash. Clear it on every early reject path so a + // later re-import of the same hash does not observe a stale entry. + let l1_validation = self.validate_next_l1_msg_index_for_block(payload.block.as_ref(), &ctx); + self.post_execution_validator + .clear_withdraw_trie_root_expectation_on_error(block_hash, l1_validation)?; + + let validation = self.inner.validate_payload(payload, ctx); + let output = self + .post_execution_validator + .clear_withdraw_trie_root_expectation_on_error(block_hash, validation)?; + self.validate_withdraw_trie_root(output) + } + + fn validate_block( + &mut self, + block: SealedBlock, + ctx: TreeCtx<'_, MorphPrimitives>, + ) -> reth_engine_tree::tree::ValidationOutcome { + let block_hash = block.hash(); + let l1_validation = self.validate_next_l1_msg_index_for_block(&block, &ctx); + self.post_execution_validator + .clear_withdraw_trie_root_expectation_on_error(block_hash, l1_validation)?; + + let validation = self.inner.validate_block(block, ctx); + let output = self + .post_execution_validator + .clear_withdraw_trie_root_expectation_on_error(block_hash, validation)?; + self.validate_withdraw_trie_root(output) + } + + fn on_inserted_executed_block( + &self, + block: BuiltPayloadExecutedBlock, + ) -> ProviderResult> { + self.inner.on_inserted_executed_block(block) + } + + fn cache_for(&self, block_hash: B256) -> Option { + self.inner.cache_for(block_hash) + } + + fn payload_state_root_handle_for( + &self, + parent_hash: B256, + parent_header: &MorphHeader, + timestamp: u64, + state: &mut EngineApiTreeState, + ) -> Option { + self.inner + .payload_state_root_handle_for(parent_hash, parent_header, timestamp, state) + } +} + +impl WaitForCaches for MorphTreeEngineValidator +where + Evm: ConfigureEvm, + BasicEngineValidator: WaitForCaches, +{ + fn wait_for_caches(&self) -> CacheWaitDurations { + self.inner.wait_for_caches() + } +} + +/// Uses upstream's optimized state-root path from Jade onward. Before Jade it +/// computes and persists the real MPT updates but trusts the historical header +/// root, which is a ZK-trie commitment and cannot be compared to the MPT root. +#[derive(Debug)] +struct MorphStateRootStrategy { + chain_spec: Arc, + default: DefaultStateRootStrategy, +} + +impl MorphStateRootStrategy { + fn new(chain_spec: Arc) -> Self { + Self { chain_spec, + default: DefaultStateRootStrategy::default(), + } + } +} + +impl StateRootStrategy for MorphStateRootStrategy +where + P: BlockReader
+ + StateProviderFactory + + StateReader + + Clone + + Send + + Sync + + 'static, + Evm: ConfigureEvm + 'static, + DefaultStateRootStrategy: StateRootStrategy, +{ + fn prepare( + &self, + ctx: StateRootJobContext<'_, MorphPrimitives, P, Evm>, + ) -> ProviderResult> { + let timestamp: u64 = ctx.env().evm_env.block_env.timestamp().saturating_to(); + if self.chain_spec.is_jade_active_at_timestamp(timestamp) { + return self.default.prepare(ctx); + } + + Ok(PreparedStateRootJob::new( + Box::new(PreJadeStateRootJob { + provider_builder: ctx.provider_builder(), + }), + None, + )) + } + + fn prepare_payload_builder( + &self, + ctx: PayloadStateRootJobContext<'_, MorphPrimitives, P>, + ) -> ProviderResult> { + if self.chain_spec.is_jade_active_at_timestamp(ctx.timestamp()) { + return self.default.prepare_payload_builder(ctx); + } + Ok(None) + } +} + +struct PreJadeStateRootJob

{ + provider_builder: reth_engine_tree::tree::StateProviderBuilder, +} + +impl

StateRootJob for PreJadeStateRootJob

+where + P: BlockReader + StateProviderFactory + StateReader + Clone + Send + Sync + 'static, +{ + fn name(&self) -> &'static str { + "morph-pre-jade-trusted-header" + } + + fn finish( + &mut self, + block: &RecoveredBlock, + _output: Arc>, + hashed_state: &LazyHashedPostState, + ) -> ProviderResult { + let provider = self.provider_builder.build()?; + let (_mpt_root, trie_updates) = + provider.state_root_with_updates(hashed_state.get().as_ref().clone())?; + Ok(StateRootJobOutcome::new( + block.header().state_root(), + Arc::new(trie_updates), )) } } @@ -184,8 +527,19 @@ impl MorphEngineValidator { removed } - fn updated_withdraw_trie_root_from_hashed_state( - state_updates: &reth_trie::HashedPostState, + fn clear_withdraw_trie_root_expectation_on_error( + &self, + block_hash: B256, + result: Result, + ) -> Result { + if result.is_err() { + self.take_withdraw_trie_root_expectation(block_hash); + } + result + } + + fn updated_withdraw_trie_root_from_sorted_hashed_state( + state_updates: &reth_trie::HashedPostStateSorted, ) -> Option { let hashed_address = keccak256(L2_MESSAGE_QUEUE_ADDRESS); let hashed_slot = keccak256(B256::from(L2_MESSAGE_QUEUE_WITHDRAW_TRIE_ROOT_SLOT)); @@ -193,8 +547,44 @@ impl MorphEngineValidator { state_updates .storages .get(&hashed_address) - .and_then(|storage| storage.storage.get(&hashed_slot).copied()) - .map(B256::from) + .and_then(|storage| { + storage + .storage_slots + .binary_search_by_key(&hashed_slot, |(slot, _)| *slot) + .ok() + .map(|index| B256::from(storage.storage_slots[index].1)) + }) + } + + fn validate_withdraw_trie_root_update( + &self, + block_hash: B256, + state_updates: impl FnOnce() -> Arc, + ) -> Result<(), ConsensusError> { + let Some(expectation) = self.take_withdraw_trie_root_expectation(block_hash) else { + tracing::debug!( + target: "morph::engine_validator", + %block_hash, + "no withdraw trie root expectation registered; skipping CL cross-check" + ); + return Ok(()); + }; + let WithdrawTrieRootExpectation::Verify(expected) = expectation else { + return Ok(()); + }; + + let Some(actual) = + Self::updated_withdraw_trie_root_from_sorted_hashed_state(state_updates().as_ref()) + else { + // The slot was not touched, so its value is unchanged from the parent. + return Ok(()); + }; + if actual != expected { + return Err(ConsensusError::msg(format!( + "withdraw trie root mismatch: expected {expected}, got {actual}" + ))); + } + Ok(()) } } @@ -219,51 +609,6 @@ impl PayloadValidator for MorphEngineValidator { Ok(sealed_block) } - fn validate_block_post_execution_with_hashed_state( - &self, - state_updates: &reth_trie::HashedPostState, - block: &RecoveredBlock, - ) -> Result<(), ConsensusError> { - let Some(expectation) = self.take_withdraw_trie_root_expectation(block.hash()) else { - // No CL-supplied expectation. Reachable on the Block-input path - // (P2P-downloaded blocks, pipeline backfill, and buffered blocks - // whose expectation was evicted from the bounded LRU before - // reattach) — `convert_payload_to_block` was never invoked to - // register one. Treat as SkipValidation so sync isn't stalled; - // the strict post-Jade state-root check upstream still covers - // withdraw-trie consistency through state-root equality. - tracing::debug!( - target: "morph::engine_validator", - block_hash = %block.hash(), - "no withdraw trie root expectation registered; skipping CL cross-check" - ); - return Ok(()); - }; - let WithdrawTrieRootExpectation::Verify(expected_withdraw_trie_root) = expectation else { - return Ok(()); - }; - - // Only validate if the withdraw trie root slot was actually updated in this block. - // If the slot is absent from hashed_state, the root is unchanged from the parent — - // the consensus layer guarantees the expected value is correct in that case. - // Doing a DB read for the parent state here would be expensive (history_by_block_hash - // + storage lookup) and would occur while holding the execution cache write lock, - // causing lock contention with the next block's cache lookup. - let Some(actual_withdraw_trie_root) = - Self::updated_withdraw_trie_root_from_hashed_state(state_updates) - else { - return Ok(()); - }; - - if actual_withdraw_trie_root != expected_withdraw_trie_root { - return Err(ConsensusError::msg(format!( - "withdraw trie root mismatch: expected {expected_withdraw_trie_root}, got {actual_withdraw_trie_root}" - ))); - } - - Ok(()) - } - fn validate_payload_attributes_against_header( &self, attr: &::PayloadAttributes, @@ -283,6 +628,13 @@ mod tests { use alloy_primitives::U256; use reth_trie::{HashedPostState, HashedStorage}; + #[test] + fn morph_tree_config_never_uses_upstream_empty_update_state_root_skip() { + let config = reth_node_api::TreeConfig::default().with_skip_state_root(true); + + assert!(!strict_morph_tree_config(config).skip_state_root()); + } + #[test] fn test_extract_updated_withdraw_trie_root_from_hashed_state() { let expected = B256::from([0x11; 32]); @@ -295,7 +647,9 @@ mod tests { ); assert_eq!( - MorphEngineValidator::updated_withdraw_trie_root_from_hashed_state(&state), + MorphEngineValidator::updated_withdraw_trie_root_from_sorted_hashed_state( + &state.into_sorted(), + ), Some(expected) ); } @@ -304,7 +658,9 @@ mod tests { fn test_extract_updated_withdraw_trie_root_from_hashed_state_missing_slot() { let state = HashedPostState::default(); assert_eq!( - MorphEngineValidator::updated_withdraw_trie_root_from_hashed_state(&state), + MorphEngineValidator::updated_withdraw_trie_root_from_sorted_hashed_state( + &state.into_sorted(), + ), None ); } @@ -381,6 +737,43 @@ mod tests { ); } + #[test] + fn validation_error_clears_withdraw_trie_root_expectation() { + let validator = MorphEngineValidator::new(); + let hash = B256::from([0x43; 32]); + validator.record_withdraw_trie_root_expectation( + hash, + WithdrawTrieRootExpectation::Verify(B256::from([0xee; 32])), + ); + + let result = validator + .clear_withdraw_trie_root_expectation_on_error(hash, Err::<(), _>("validation failed")); + + assert_eq!(result, Err("validation failed")); + assert!( + validator + .take_withdraw_trie_root_expectation(hash) + .is_none() + ); + } + + #[test] + fn validation_success_preserves_withdraw_trie_root_expectation() { + let validator = MorphEngineValidator::new(); + let hash = B256::from([0x44; 32]); + let expectation = WithdrawTrieRootExpectation::Verify(B256::from([0xee; 32])); + validator.record_withdraw_trie_root_expectation(hash, expectation); + + let result = validator + .clear_withdraw_trie_root_expectation_on_error(hash, Ok::<_, &str>("validated")); + + assert_eq!(result, Ok("validated")); + assert_eq!( + validator.take_withdraw_trie_root_expectation(hash), + Some(expectation) + ); + } + #[test] fn test_record_skip_validation_expectation() { let validator = MorphEngineValidator::new(); @@ -436,7 +829,10 @@ mod tests { HashedStorage::from_iter(false, [(hashed_slot, U256::from_be_bytes([0x11; 32]))]), ); assert!( - MorphEngineValidator::updated_withdraw_trie_root_from_hashed_state(&state).is_none() + MorphEngineValidator::updated_withdraw_trie_root_from_sorted_hashed_state( + &state.into_sorted(), + ) + .is_none() ); } @@ -450,7 +846,10 @@ mod tests { HashedStorage::from_iter(false, [(wrong_slot, U256::from_be_bytes([0x22; 32]))]), ); assert!( - MorphEngineValidator::updated_withdraw_trie_root_from_hashed_state(&state).is_none() + MorphEngineValidator::updated_withdraw_trie_root_from_sorted_hashed_state( + &state.into_sorted(), + ) + .is_none() ); } @@ -475,8 +874,10 @@ mod tests { let validator = MorphEngineValidator::new(); let block = empty_recovered_block_with_hash(B256::from([0xab; 32])); - let result = validator - .validate_block_post_execution_with_hashed_state(&HashedPostState::default(), &block); + let state = HashedPostState::default(); + let result = validator.validate_withdraw_trie_root_update(block.hash(), || { + Arc::new(state.clone().into_sorted()) + }); assert!( result.is_ok(), @@ -496,8 +897,10 @@ mod tests { ); let block = empty_recovered_block_with_hash(hash); - let result = validator - .validate_block_post_execution_with_hashed_state(&HashedPostState::default(), &block); + let state = HashedPostState::default(); + let result = validator.validate_withdraw_trie_root_update(block.hash(), || { + Arc::new(state.clone().into_sorted()) + }); assert!(result.is_ok()); // expectation must be consumed. @@ -522,8 +925,10 @@ mod tests { // empty hashed state → no withdraw-slot diff → skip per the doc-comment // explanation in the validator. - let result = validator - .validate_block_post_execution_with_hashed_state(&HashedPostState::default(), &block); + let state = HashedPostState::default(); + let result = validator.validate_withdraw_trie_root_update(block.hash(), || { + Arc::new(state.clone().into_sorted()) + }); assert!(result.is_ok()); } @@ -552,7 +957,9 @@ mod tests { HashedStorage::from_iter(false, [(hashed_slot, U256::from_be_bytes(actual.0))]), ); - let result = validator.validate_block_post_execution_with_hashed_state(&state, &block); + let result = validator.validate_withdraw_trie_root_update(block.hash(), || { + Arc::new(state.clone().into_sorted()) + }); assert!( result.is_ok(), @@ -582,7 +989,9 @@ mod tests { let block = empty_recovered_block_with_hash(hash); let err = validator - .validate_block_post_execution_with_hashed_state(&state, &block) + .validate_withdraw_trie_root_update(block.hash(), || { + Arc::new(state.clone().into_sorted()) + }) .expect_err("mismatched root must fail"); assert!( err.to_string().contains("withdraw trie root mismatch"), @@ -617,6 +1026,7 @@ mod tests { withdrawals: None, parent_beacon_block_root: None, slot_number: None, + target_gas_limit: None, }, transactions: None, gas_limit: None, @@ -637,6 +1047,7 @@ mod tests { withdrawals: None, parent_beacon_block_root: None, slot_number: None, + target_gas_limit: None, }, transactions: None, gas_limit: None, @@ -657,6 +1068,7 @@ mod tests { withdrawals: None, parent_beacon_block_root: None, slot_number: None, + target_gas_limit: None, }, transactions: None, gas_limit: None, diff --git a/crates/node/tests/it/engine.rs b/crates/node/tests/it/engine.rs index 7404758..90be9bb 100644 --- a/crates/node/tests/it/engine.rs +++ b/crates/node/tests/it/engine.rs @@ -10,9 +10,11 @@ use alloy_rpc_types_engine::PayloadAttributes; use jsonrpsee::core::client::ClientT; use morph_node::test_utils::{HardforkSchedule, TestNodeBuilder}; use morph_payload_types::{ - AssembleL2BlockParams, ExecutableL2Data, GenericResponse, MorphPayloadAttributes, SafeL2Data, + AssembleL2BlockParams, ExecutableL2Data, GenericResponse, MorphPayloadAttributes, + MorphPayloadTypes, SafeL2Data, }; use morph_primitives::MorphHeader; +use reth_node_api::PayloadTypes; use reth_payload_builder::BuildNewPayload; use reth_payload_primitives::BuiltPayload; use reth_provider::{BlockIdReader, BlockReaderIdExt}; @@ -55,6 +57,39 @@ async fn state_root_validation_skipped_pre_jade() -> eyre::Result<()> { Ok(()) } +/// P2P-downloaded blocks enter through the block-input path, where no +/// Engine-API withdraw-root expectation has been registered locally. +#[tokio::test(flavor = "multi_thread")] +async fn p2p_downloaded_block_imports_without_registered_expectation() -> eyre::Result<()> { + reth_tracing::init_test_tracing(); + + let (mut nodes, _wallet) = TestNodeBuilder::new() + .with_schedule(HardforkSchedule::AllActive) + .with_num_nodes(2) + .build() + .await?; + let node1 = nodes.pop().expect("two nodes requested"); + let mut node0 = nodes.pop().expect("two nodes requested"); + + let payload = build_block_no_submit(&mut node0, vec![]).await?; + let head_hash = payload.block().hash(); + let execution_data = MorphPayloadTypes::block_to_payload(payload.block().clone(), None); + let status = node0 + .inner + .add_ons_handle + .beacon_engine_handle + .new_payload(execution_data) + .await?; + assert!( + status.is_valid(), + "source node rejected its block: {status:?}" + ); + node0.update_forkchoice(head_hash, head_hash).await?; + + node1.sync_to(head_hash).await?; + Ok(()) +} + /// `engine_newL2Block` can import consecutive blocks assembled over the authenticated RPC. #[tokio::test(flavor = "multi_thread")] async fn new_l2_block_imports_consecutive_assembled_blocks_over_rpc() -> eyre::Result<()> { @@ -580,6 +615,7 @@ async fn payload_builder_hash_matches_block_hash_with_nonzero_prev_randao() -> e withdrawals: Some(vec![]), parent_beacon_block_root: Some(B256::ZERO), slot_number: None, + target_gas_limit: None, }, transactions: Some(vec![]), gas_limit: None, @@ -593,7 +629,7 @@ async fn payload_builder_hash_matches_block_hash_with_nonzero_prev_randao() -> e attributes: rpc_attrs, parent_hash: head_hash, cache: None, - trie_handle: None, + state_root_handle: None, }) .await? .map_err(|e| eyre::eyre!("payload build failed: {e}"))?; diff --git a/crates/node/tests/it/helpers.rs b/crates/node/tests/it/helpers.rs index 808e9ed..b08a17b 100644 --- a/crates/node/tests/it/helpers.rs +++ b/crates/node/tests/it/helpers.rs @@ -48,6 +48,7 @@ pub(crate) async fn advance_block_with_l1_messages( withdrawals: Some(vec![]), parent_beacon_block_root: Some(B256::ZERO), slot_number: None, + target_gas_limit: None, }, transactions: Some(l1_messages), gas_limit: None, @@ -61,7 +62,7 @@ pub(crate) async fn advance_block_with_l1_messages( attributes: rpc_attrs, parent_hash: head_hash, cache: None, - trie_handle: None, + state_root_handle: None, }) .await? .map_err(|e| eyre::eyre!("payload build failed: {e}"))?; @@ -122,6 +123,7 @@ pub(crate) async fn build_block_no_submit( withdrawals: Some(vec![]), parent_beacon_block_root: Some(B256::ZERO), slot_number: None, + target_gas_limit: None, }, transactions: Some(l1_messages), gas_limit: None, @@ -135,7 +137,7 @@ pub(crate) async fn build_block_no_submit( attributes: rpc_attrs, parent_hash: head_hash, cache: None, - trie_handle: None, + state_root_handle: None, }) .await? .map_err(|e| eyre::eyre!("payload build failed: {e}"))?; @@ -192,7 +194,7 @@ pub(crate) async fn craft_and_try_import_block( let modified_sealed = SealedBlock::seal_slow(block); // Convert to execution payload and try to import - let execution_data = MorphPayloadTypes::block_to_payload(modified_sealed); + let execution_data = MorphPayloadTypes::block_to_payload(modified_sealed, None); let status = node .inner .add_ons_handle @@ -230,6 +232,7 @@ pub(crate) async fn expect_payload_build_failure( withdrawals: Some(vec![]), parent_beacon_block_root: Some(B256::ZERO), slot_number: None, + target_gas_limit: None, }, transactions: Some(l1_messages), gas_limit: None, @@ -243,7 +246,7 @@ pub(crate) async fn expect_payload_build_failure( attributes: rpc_attrs, parent_hash: head_hash, cache: None, - trie_handle: None, + state_root_handle: None, }) .await? { diff --git a/crates/payload/builder/src/builder.rs b/crates/payload/builder/src/builder.rs index 2f35359..e2dc38b 100644 --- a/crates/payload/builder/src/builder.rs +++ b/crates/payload/builder/src/builder.rs @@ -21,7 +21,7 @@ use reth_chainspec::ChainSpecProvider; use reth_evm::{ ConfigureEvm, Database, Evm, NextBlockEnvAttributes, block::{BlockExecutionError, BlockValidationError}, - execute::{BlockBuilder, BlockBuilderOutcome, BlockExecutor}, + execute::{BlockBuilder, BlockBuilderOutcome}, }; use reth_execution_cache::{CachedStateMetrics, CachedStateMetricsSource, CachedStateProvider}; use reth_execution_types::BlockExecutionOutput; @@ -169,7 +169,7 @@ where let BuildArguments { mut cached_reads, execution_cache, - trie_handle, + state_root_handle, config, cancel, best_payload, @@ -179,6 +179,7 @@ where let parent_hash = config.parent_header.hash(); let payload_id = config.payload_id; let parent_header = config.parent_header.clone(); + let parent_block_info = config.parent_block_info; let builder_attrs = MorphPayloadBuilderAttributes::try_new( parent_hash, config.attributes, @@ -187,6 +188,7 @@ where .map_err(|e| PayloadBuilderError::Other(e.into()))?; let builder_config = PayloadConfig { parent_header, + parent_block_info, attributes: builder_attrs, payload_id, }; @@ -215,7 +217,9 @@ where state_provider = Box::new(CachedStateProvider::new( state_provider, execution_cache.cache().clone(), - CachedStateMetrics::zeroed(CachedStateMetricsSource::Builder), + Some(CachedStateMetrics::zeroed( + CachedStateMetricsSource::Builder, + )), )); } let state = StateProviderDatabase::new(state_provider.as_ref()); @@ -226,7 +230,7 @@ where state_provider.as_ref(), ctx, best, - trie_handle, + state_root_handle, ) .map(|out| out.with_cached_reads(cached_reads)) } @@ -268,7 +272,7 @@ where config, cached_reads: Default::default(), execution_cache: None, - trie_handle: None, + state_root_handle: None, cancel: Default::default(), best_payload: None, }; @@ -686,7 +690,7 @@ fn build_payload_inner<'a, DB, BestTxs>( state_provider: &(impl StateProvider + ?Sized), ctx: MorphPayloadBuilderCtx, best: impl FnOnce(BestTransactionsAttributes) -> BestTxs + Send + Sync + 'a, - trie_handle: Option, + mut state_root_handle: Option, ) -> Result, PayloadBuilderError> where DB: Database, @@ -734,10 +738,11 @@ where // state hook so per-tx state diffs stream to the background trie task // during execution. The final `state_root()` recv() at finish time will // return quickly since most work is done concurrently. - if let Some(ref handle) = trie_handle { + if let Some(handle) = state_root_handle.as_mut() { builder - .executor_mut() - .set_state_hook(Some(Box::new(handle.state_hook()))); + .evm_mut() + .db_mut() + .set_state_hook(Some(Box::new(handle.take_state_hook()))); } // 1. Apply pre-execution changes (system contracts, etc.) @@ -815,8 +820,9 @@ where hashed_state, trie_updates, mut block, - } = if let Some(mut handle) = trie_handle { - builder.executor_mut().set_state_hook(None); + block_access_list: _, + } = if let Some(mut handle) = state_root_handle { + builder.evm_mut().db_mut().set_state_hook(None); match handle.state_root() { Ok(outcome) => builder.finish( state_provider, @@ -890,8 +896,9 @@ where recovered_block: Arc::new(block), execution_output: Arc::new(execution_output), // Keep unsorted; conversion to sorted is deferred until required. - hashed_state: Err(Arc::new(hashed_state)).into(), - trie_updates: Err(Arc::new(trie_updates)).into(), + hashed_state: Arc::new(hashed_state), + trie_updates: Arc::new(trie_updates), + changed_paths: None, }; let payload = MorphBuiltPayload::new( diff --git a/crates/payload/types/src/attributes.rs b/crates/payload/types/src/attributes.rs index 3aaea3a..86d7213 100644 --- a/crates/payload/types/src/attributes.rs +++ b/crates/payload/types/src/attributes.rs @@ -334,6 +334,7 @@ mod tests { parent_beacon_block_root: None, // Morph L2 has no PoS slot semantics; field added in alloy 2.0. slot_number: None, + target_gas_limit: None, }, transactions: None, gas_limit: None, diff --git a/crates/payload/types/src/lib.rs b/crates/payload/types/src/lib.rs index 9ded5aa..f940589 100644 --- a/crates/payload/types/src/lib.rs +++ b/crates/payload/types/src/lib.rs @@ -83,6 +83,12 @@ impl MorphExecutionData { } } +impl From for MorphExecutionData { + fn from(value: MorphBuiltPayload) -> Self { + Self::new(value.block) + } +} + impl ExecutionPayload for MorphExecutionData { fn parent_hash(&self) -> B256 { self.block.parent_hash() @@ -140,6 +146,7 @@ impl PayloadTypes for MorphPayloadTypes { block: SealedBlock< <::Primitives as NodePrimitives>::Block, >, + _bal: Option, ) -> Self::ExecutionData { MorphExecutionData::new(Arc::new(block)) } @@ -237,7 +244,7 @@ mod tests { fn test_block_to_payload() { let block = create_test_block(); let hash = block.hash(); - let data = MorphPayloadTypes::block_to_payload(block); + let data = MorphPayloadTypes::block_to_payload(block, None); assert_eq!(data.block_hash(), hash); assert!(data.expected_withdraw_trie_root.is_none()); } diff --git a/crates/revm/src/evm.rs b/crates/revm/src/evm.rs index d8ba55b..10d7fe5 100644 --- a/crates/revm/src/evm.rs +++ b/crates/revm/src/evm.rs @@ -14,7 +14,7 @@ use revm::{ }, inspector::InspectorEvmTr, interpreter::{ - Host, Instruction, InstructionContext, InstructionResult, + Host, Instruction, InstructionContext, InstructionExecResult, InstructionResult, gas::{BLOCKHASH, WARM_STORAGE_READ_COST}, interpreter::EthInterpreter, interpreter_types::{RuntimeFlag, StackTr}, @@ -70,10 +70,9 @@ fn morph_blockhash_result(chain_id: u64, current_number: u64, requested_number: /// for numbers within the 256-block lookup window. fn blockhash_morph( context: InstructionContext<'_, MorphContext, EthInterpreter>, -) { +) -> InstructionExecResult { let Some(([], number)) = StackTr::popn_top::<0>(&mut context.interpreter.stack) else { - context.interpreter.halt_underflow(); - return; + return Err(InstructionResult::StackUnderflow); }; let requested_number_u64 = as_u64_saturated(*number); @@ -81,6 +80,7 @@ fn blockhash_morph( let chain_id_u64 = as_u64_saturated(context.host.chain_id()); *number = morph_blockhash_result(chain_id_u64, current_number_u64, requested_number_u64); + Ok(()) } /// Morph custom SLOAD opcode. @@ -93,10 +93,11 @@ fn blockhash_morph( /// instead of "dirty" (100 gas), causing a 2800 gas mismatch vs go-eth. /// /// The DB read hits the State cache (O(1)) and only triggers on cold SLOADs. -fn sload_morph(context: InstructionContext<'_, MorphContext, EthInterpreter>) { +fn sload_morph( + context: InstructionContext<'_, MorphContext, EthInterpreter>, +) -> InstructionExecResult { let Some(([], index)) = StackTr::popn_top::<0>(&mut context.interpreter.stack) else { - context.interpreter.halt_underflow(); - return; + return Err(InstructionResult::StackUnderflow); }; let target = context.interpreter.input.target_address; @@ -125,16 +126,16 @@ fn sload_morph(context: InstructionContext<'_, MorphContext, E .gas .record_regular_cost(additional_cold_cost) { - context.interpreter.halt_oog(); - return; + return Err(InstructionResult::OutOfGas); } } *index = storage.data; } - Err(LoadError::ColdLoadSkipped) => context.interpreter.halt_oog(), - Err(LoadError::DBError) => context.interpreter.halt_fatal(), + Err(LoadError::ColdLoadSkipped) => return Err(InstructionResult::OutOfGas), + Err(LoadError::DBError) => return Err(InstructionResult::FatalExternalError), } + Ok(()) } /// Morph custom SSTORE opcode. @@ -150,17 +151,15 @@ fn sload_morph(context: InstructionContext<'_, MorphContext, E /// same 2800-gas-per-write divergence vs go-eth that `sload_morph` fixes. /// /// Uses DB-direct lookup (no per-tx runtime map needed). -fn sstore_morph(context: InstructionContext<'_, MorphContext, EthInterpreter>) { +fn sstore_morph( + context: InstructionContext<'_, MorphContext, EthInterpreter>, +) -> InstructionExecResult { if context.interpreter.runtime_flag.is_static() { - context - .interpreter - .halt(InstructionResult::StateChangeDuringStaticCall); - return; + return Err(InstructionResult::StateChangeDuringStaticCall); } let Some([index, value]) = StackTr::popn::<2>(&mut context.interpreter.stack) else { - context.interpreter.halt_underflow(); - return; + return Err(InstructionResult::StackUnderflow); }; let target = context.interpreter.input.target_address; @@ -169,10 +168,7 @@ fn sstore_morph(context: InstructionContext<'_, MorphContext, if spec_id.is_enabled_in(ISTANBUL) && context.interpreter.gas.remaining() <= context.host.gas_params().call_stipend() { - context - .interpreter - .halt(InstructionResult::ReentrancySentryOOG); - return; + return Err(InstructionResult::ReentrancySentryOOG); } if !context @@ -180,8 +176,7 @@ fn sstore_morph(context: InstructionContext<'_, MorphContext, .gas .record_regular_cost(context.host.gas_params().sstore_static_gas()) { - context.interpreter.halt_oog(); - return; + return Err(InstructionResult::OutOfGas); } let mut state_load = if spec_id.is_enabled_in(BERLIN) { @@ -193,18 +188,15 @@ fn sstore_morph(context: InstructionContext<'_, MorphContext, { Ok(load) => load, Err(LoadError::ColdLoadSkipped) => { - context.interpreter.halt_oog(); - return; + return Err(InstructionResult::OutOfGas); } Err(LoadError::DBError) => { - context.interpreter.halt_fatal(); - return; + return Err(InstructionResult::FatalExternalError); } } } else { let Some(load) = context.host.sstore(target, index, value) else { - context.interpreter.halt_fatal(); - return; + return Err(InstructionResult::FatalExternalError); }; load }; @@ -232,8 +224,7 @@ fn sstore_morph(context: InstructionContext<'_, MorphContext, state_load.is_cold, ); if !context.interpreter.gas.record_regular_cost(dynamic_gas) { - context.interpreter.halt_oog(); - return; + return Err(InstructionResult::OutOfGas); } context.interpreter.gas.record_refund( @@ -242,6 +233,7 @@ fn sstore_morph(context: InstructionContext<'_, MorphContext, .gas_params() .sstore_refund(is_istanbul, &state_load.data), ); + Ok(()) } /// MorphEvm extends the Evm with Morph specific types and logic. @@ -291,22 +283,27 @@ impl MorphEvm { let mut instructions = EthInstructions::new_mainnet_with_spec(spec.into()); // Morph custom BLOCKHASH implementation (matches Morph geth). - instructions.insert_instruction(0x40, Instruction::new(blockhash_morph::, BLOCKHASH)); + instructions.insert_instruction( + 0x40, + Instruction::new(blockhash_morph::), + BLOCKHASH as u16, + ); // Morph custom SLOAD: fixes original_value corruption from token fee deduction. instructions.insert_instruction( 0x54, - Instruction::new(sload_morph::, WARM_STORAGE_READ_COST), + Instruction::new(sload_morph::), + WARM_STORAGE_READ_COST as u16, ); // Morph custom SSTORE: same original_value fix on the SSTORE cold path. // Static gas = 0 because sstore_morph manages all gas accounting itself // (static + dynamic + refund). - instructions.insert_instruction(0x55, Instruction::new(sstore_morph::, 0)); + instructions.insert_instruction(0x55, Instruction::new(sstore_morph::), 0); // SELFDESTRUCT is disabled in Morph - instructions.insert_instruction(0xff, Instruction::unknown()); + instructions.insert_instruction(0xff, Instruction::unknown(), 0); // BLOBHASH is disabled in Morph - instructions.insert_instruction(0x49, Instruction::unknown()); + instructions.insert_instruction(0x49, Instruction::unknown(), 0); // BLOBBASEFEE is disabled in Morph - instructions.insert_instruction(0x4a, Instruction::unknown()); + instructions.insert_instruction(0x4a, Instruction::unknown(), 0); Self::new_inner(Evm { ctx, inspector, diff --git a/crates/revm/src/precompiles.rs b/crates/revm/src/precompiles.rs index 02d0cf3..cce783f 100644 --- a/crates/revm/src/precompiles.rs +++ b/crates/revm/src/precompiles.rs @@ -43,9 +43,8 @@ use revm::{ precompile::{ Precompile, PrecompileHalt, PrecompileId, PrecompileOutput, PrecompileResult, Precompiles, }, - primitives::{OnceLock, hardfork::SpecId}, + primitives::{AddressSet, OnceLock, hardfork::SpecId}, }; -use std::boxed::Box; use std::string::String; /// Standard precompile addresses @@ -395,7 +394,7 @@ where } #[inline] - fn warm_addresses(&self) -> Box> { + fn warm_addresses(&self) -> &AddressSet { self.inner.warm_addresses() } diff --git a/crates/rpc/src/eth/call.rs b/crates/rpc/src/eth/call.rs index f4a5e7f..a1718bb 100644 --- a/crates/rpc/src/eth/call.rs +++ b/crates/rpc/src/eth/call.rs @@ -57,6 +57,10 @@ where self.eth_api().max_simulate_blocks() } + fn compute_state_root_for_eth_simulate(&self) -> bool { + self.eth_api().compute_state_root_for_eth_simulate() + } + fn evm_memory_limit(&self) -> u64 { self.eth_api().evm_memory_limit() } diff --git a/crates/rpc/src/eth/mod.rs b/crates/rpc/src/eth/mod.rs index 96a08d7..cb7331a 100644 --- a/crates/rpc/src/eth/mod.rs +++ b/crates/rpc/src/eth/mod.rs @@ -17,8 +17,8 @@ use reth_rpc_convert::{RpcConvert, RpcConverter, RpcTypes}; use reth_rpc_eth_api::{ EthApiTypes, RpcNodeCore, RpcNodeCoreExt, helpers::{ - EthApiSpec, EthBlocks, EthFees, EthState, EthTransactions, LoadBlock, LoadFee, - LoadPendingBlock, LoadState, LoadTransaction, SpawnBlocking, Trace, + EthApiSpec, EthBlocks, EthFees, EthState, EthSubscriptions, EthTransactions, LoadBlock, + LoadFee, LoadPendingBlock, LoadState, LoadTransaction, SpawnBlocking, Trace, bal::GetBlockAccessList, pending_block::PendingEnvBuilder, }, }; @@ -320,6 +320,20 @@ where self.inner.eth_api.send_raw_transaction_sync_timeout() } + async fn send_pool_transaction( + &self, + origin: reth_transaction_pool::TransactionOrigin, + tx: reth_primitives_traits::WithEncoded>, + ) -> Result { + reth_rpc_eth_api::helpers::EthTransactions::send_pool_transaction( + &self.inner.eth_api, + origin, + tx, + ) + .await + .map_err(Into::into) + } + async fn send_transaction( &self, origin: reth_transaction_pool::TransactionOrigin, @@ -337,6 +351,13 @@ where } } +impl EthSubscriptions for MorphEthApi +where + N: MorphNodeCore, + Rpc: RpcConvert, +{ +} + impl EthFees for MorphEthApi where N: MorphNodeCore, diff --git a/deny.toml b/deny.toml index 26053b0..0b19c29 100644 --- a/deny.toml +++ b/deny.toml @@ -8,20 +8,6 @@ ignore = [ "RUSTSEC-2024-0436", # https://rustsec.org/advisories/RUSTSEC-2025-0141 bincode is unmaintained "RUSTSEC-2025-0141", - # https://rustsec.org/advisories/RUSTSEC-2026-0097 rand unsound with custom logger - # pinned transitively via reth; we don't install a custom logger so this is - # a false positive in our usage, but cargo-deny can't see usage - "RUSTSEC-2026-0097", - # https://rustsec.org/advisories/RUSTSEC-2026-0098 rustls-webpki URI name constraints - "RUSTSEC-2026-0098", - # https://rustsec.org/advisories/RUSTSEC-2026-0099 rustls-webpki wildcard name constraints - "RUSTSEC-2026-0099", - # https://rustsec.org/advisories/RUSTSEC-2026-0118 hickory-proto NSEC3 validation loop - # pinned transitively via reth-dns-discovery -> hickory-resolver ^0.25; no 0.25 fix is available - "RUSTSEC-2026-0118", - # https://rustsec.org/advisories/RUSTSEC-2026-0119 hickory-proto O(n^2) name compression - # fixed in hickory-proto 0.26.1, but hickory-resolver ^0.25 cannot select it - "RUSTSEC-2026-0119", # https://rustsec.org/advisories/RUSTSEC-2026-0173 proc-macro-error2 is unmaintained # build-time proc-macro pulled transitively via alloy-sol-macro; no fix available "RUSTSEC-2026-0173",