diff --git a/Cargo.lock b/Cargo.lock index 55fd621db..9f377bba1 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -26,7 +26,7 @@ checksum = "b169f7a6d4742236a0a00c541b845991d0ac43e546831af1249753ab4c3aa3a0" dependencies = [ "cfg-if", "cipher", - "cpufeatures", + "cpufeatures 0.2.17", ] [[package]] @@ -97,11 +97,11 @@ checksum = "683d7910e743518b0e34f1186f92494becacb047c7b6bf616c96772180fef923" [[package]] name = "alloy-chains" -version = "0.2.21" +version = "0.2.33" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1b9ebac8ff9c2f07667e1803dc777304337e160ce5153335beb45e8ec0751808" +checksum = "f4e9e31d834fe25fe991b8884e4b9f0e59db4a97d86e05d1464d6899c013cd62" dependencies = [ - "alloy-primitives 1.4.1", + "alloy-primitives 1.5.7", "alloy-rlp", "num_enum", "serde", @@ -110,16 +110,43 @@ dependencies = [ [[package]] name = "alloy-consensus" -version = "1.1.2" +version = "1.8.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7f16daaf7e1f95f62c6c3bf8a3fc3d78b08ae9777810c0bb5e94966c7cd57ef0" +dependencies = [ + "alloy-eips 1.8.3", + "alloy-primitives 1.5.7", + "alloy-rlp", + "alloy-serde 1.8.3", + "alloy-trie", + "alloy-tx-macros 1.8.3", + "auto_impl", + "borsh", + "c-kzg", + "derive_more 2.1.0", + "either", + "k256 0.13.4", + "once_cell", + "rand 0.8.5", + "secp256k1 0.30.0", + "serde", + "serde_json", + "serde_with", + "thiserror 2.0.17", +] + +[[package]] +name = "alloy-consensus" +version = "2.0.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8b6440213a22df93a87ed512d2f668e7dc1d62a05642d107f82d61edc9e12370" +checksum = "e3d64da86c616b5092ea64eea648f311bbd58630a0b384c42d699175d6f9122b" dependencies = [ - "alloy-eips", - "alloy-primitives 1.4.1", + "alloy-eips 2.0.4", + "alloy-primitives 1.5.7", "alloy-rlp", - "alloy-serde", - "alloy-trie 0.9.1", - "alloy-tx-macros", + "alloy-serde 2.0.4", + "alloy-trie", + "alloy-tx-macros 2.0.4", "arbitrary", "auto_impl", "borsh", @@ -138,27 +165,41 @@ dependencies = [ [[package]] name = "alloy-consensus-any" -version = "1.1.2" +version = "1.8.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "118998d9015332ab1b4720ae1f1e3009491966a0349938a1f43ff45a8a4c6299" +dependencies = [ + "alloy-consensus 1.8.3", + "alloy-eips 1.8.3", + "alloy-primitives 1.5.7", + "alloy-rlp", + "alloy-serde 1.8.3", + "serde", +] + +[[package]] +name = "alloy-consensus-any" +version = "2.0.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "15d0bea09287942405c4f9d2a4f22d1e07611c2dbd9d5bf94b75366340f9e6e0" +checksum = "8fd98696ca3617d3a9ba1a6f2011880cbfd5618228dab6400c9f8bca457859a8" dependencies = [ - "alloy-consensus", - "alloy-eips", - "alloy-primitives 1.4.1", + "alloy-consensus 2.0.4", + "alloy-eips 2.0.4", + "alloy-primitives 1.5.7", "alloy-rlp", - "alloy-serde", + "alloy-serde 2.0.4", "arbitrary", "serde", ] [[package]] name = "alloy-dyn-abi" -version = "1.4.1" +version = "1.5.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3fdff496dd4e98a81f4861e66f7eaf5f2488971848bb42d9c892f871730245c8" +checksum = "cc2db5c583aaef0255aa63a4fe827f826090142528bba48d1bf4119b62780cad" dependencies = [ "alloy-json-abi", - "alloy-primitives 1.4.1", + "alloy-primitives 1.5.7", "alloy-sol-type-parser", "alloy-sol-types", "derive_more 2.1.0", @@ -174,7 +215,7 @@ version = "0.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "741bdd7499908b3aa0b159bba11e71c8cddd009a2c2eb7a06e825f1ec87900a5" dependencies = [ - "alloy-primitives 1.4.1", + "alloy-primitives 1.5.7", "alloy-rlp", "arbitrary", "crc", @@ -189,7 +230,7 @@ version = "0.2.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9441120fa82df73e8959ae0e4ab8ade03de2aaae61be313fbf5746277847ce25" dependencies = [ - "alloy-primitives 1.4.1", + "alloy-primitives 1.5.7", "alloy-rlp", "arbitrary", "borsh", @@ -203,7 +244,7 @@ version = "0.6.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2919c5a56a1007492da313e7a3b6d45ef5edc5d33416fdec63c0d7a2702a0d20" dependencies = [ - "alloy-primitives 1.4.1", + "alloy-primitives 1.5.7", "alloy-rlp", "arbitrary", "borsh", @@ -214,64 +255,99 @@ dependencies = [ "thiserror 2.0.17", ] +[[package]] +name = "alloy-eip7928" +version = "0.3.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "72bc95fd73591644f0022065bef3c027d1a5ed875a53cb19a898d71a00818c1d" +dependencies = [ + "alloy-primitives 1.5.7", + "alloy-rlp", + "arbitrary", + "borsh", + "once_cell", + "serde", + "thiserror 2.0.17", +] + [[package]] name = "alloy-eips" -version = "1.1.2" +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 1.5.7", + "alloy-rlp", + "alloy-serde 1.8.3", + "auto_impl", + "borsh", + "c-kzg", + "derive_more 2.1.0", + "either", + "serde", + "serde_with", + "sha2 0.10.9", +] + +[[package]] +name = "alloy-eips" +version = "2.0.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4bd2c7ae05abcab4483ce821f12f285e01c0b33804e6883dd9ca1569a87ee2be" +checksum = "64c0456f5f7a4497e9342d20f528e30f5288ddfa0d6a012bd5044afee46cd8a0" dependencies = [ "alloy-eip2124", "alloy-eip2930", "alloy-eip7702", - "alloy-primitives 1.4.1", + "alloy-eip7928", + "alloy-primitives 1.5.7", "alloy-rlp", - "alloy-serde", + "alloy-serde 2.0.4", "arbitrary", "auto_impl", "borsh", "c-kzg", "derive_more 2.1.0", "either", - "ethereum_ssz 0.9.1", - "ethereum_ssz_derive", + "ethereum_ssz 0.10.1", + "ethereum_ssz_derive 0.10.1", "serde", "serde_with", "sha2 0.10.9", - "thiserror 2.0.17", ] [[package]] name = "alloy-evm" -version = "0.23.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "527b47dc39850c6168002ddc1f7a2063e15d26137c1bb5330f6065a7524c1aa9" +version = "0.34.0" +source = "git+https://github.com/alloy-rs/evm?rev=13c9068fe8d0b112f2836783f9702eb3d3b7871f#13c9068fe8d0b112f2836783f9702eb3d3b7871f" dependencies = [ - "alloy-consensus", - "alloy-eips", - "alloy-hardforks 0.4.4", - "alloy-primitives 1.4.1", + "alloy-consensus 2.0.4", + "alloy-eips 2.0.4", + "alloy-hardforks 0.4.7", + "alloy-primitives 1.5.7", "alloy-rpc-types-engine", - "alloy-rpc-types-eth", + "alloy-rpc-types-eth 2.0.4", "alloy-sol-types", "auto_impl", "derive_more 2.1.0", - "op-alloy-consensus", - "op-alloy-rpc-types-engine", - "op-revm", "revm", "thiserror 2.0.17", + "tracing", ] [[package]] name = "alloy-genesis" -version = "1.1.2" +version = "2.0.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fc47eaae86488b07ea8e20236184944072a78784a1f4993f8ec17b3aa5d08c21" +checksum = "a71ff8b55d2b8aa05259f474cae7dea0e4991724dc18936b81cb23ec492a0c2a" dependencies = [ - "alloy-eips", - "alloy-primitives 1.4.1", - "alloy-serde", - "alloy-trie 0.9.1", + "alloy-eips 2.0.4", + "alloy-primitives 1.5.7", + "alloy-serde 2.0.4", + "alloy-trie", "borsh", "serde", "serde_with", @@ -285,20 +361,20 @@ checksum = "3165210652f71dfc094b051602bafd691f506c54050a174b1cba18fb5ef706a3" dependencies = [ "alloy-chains", "alloy-eip2124", - "alloy-primitives 1.4.1", + "alloy-primitives 1.5.7", "auto_impl", "dyn-clone", ] [[package]] name = "alloy-hardforks" -version = "0.4.4" +version = "0.4.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1e29d7eacf42f89c21d7f089916d0bdb4f36139a31698790e8837d2dbbd4b2c3" +checksum = "83ba208044232d14d4adbfa77e57d6329f51bc1acc21f5667bb7db72d88a0831" dependencies = [ "alloy-chains", "alloy-eip2124", - "alloy-primitives 1.4.1", + "alloy-primitives 1.5.7", "auto_impl", "dyn-clone", "serde", @@ -306,11 +382,11 @@ dependencies = [ [[package]] name = "alloy-json-abi" -version = "1.4.1" +version = "1.5.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5513d5e6bd1cba6bdcf5373470f559f320c05c8c59493b6e98912fbe6733943f" +checksum = "e9dbe713da0c737d9e5e387b0ba790eb98b14dd207fe53eef50e19a5a8ec3dac" dependencies = [ - "alloy-primitives 1.4.1", + "alloy-primitives 1.5.7", "alloy-sol-type-parser", "serde", "serde_json", @@ -318,11 +394,26 @@ dependencies = [ [[package]] name = "alloy-json-rpc" -version = "1.1.2" +version = "1.8.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "422d110f1c40f1f8d0e5562b0b649c35f345fccb7093d9f02729943dcd1eef71" +dependencies = [ + "alloy-primitives 1.5.7", + "alloy-sol-types", + "http 1.4.0", + "serde", + "serde_json", + "thiserror 2.0.17", + "tracing", +] + +[[package]] +name = "alloy-json-rpc" +version = "2.0.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "003f46c54f22854a32b9cc7972660a476968008ad505427eabab49225309ec40" +checksum = "19e352478b756bad5d7203148e4b461861282ea2ded3da406ba24868b52cd098" dependencies = [ - "alloy-primitives 1.4.1", + "alloy-primitives 1.5.7", "alloy-sol-types", "http 1.4.0", "serde", @@ -333,19 +424,19 @@ dependencies = [ [[package]] name = "alloy-network" -version = "1.1.2" +version = "2.0.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4f4029954d9406a40979f3a3b46950928a0fdcfe3ea8a9b0c17490d57e8aa0e3" +checksum = "ed08ae169869e08370ed121612e0d3dadac33d1a256e9f2465926b23f0bd7d95" dependencies = [ - "alloy-consensus", - "alloy-consensus-any", - "alloy-eips", - "alloy-json-rpc", - "alloy-network-primitives", - "alloy-primitives 1.4.1", + "alloy-consensus 2.0.4", + "alloy-consensus-any 2.0.4", + "alloy-eips 2.0.4", + "alloy-json-rpc 2.0.4", + "alloy-network-primitives 2.0.4", + "alloy-primitives 1.5.7", "alloy-rpc-types-any", - "alloy-rpc-types-eth", - "alloy-serde", + "alloy-rpc-types-eth 2.0.4", + "alloy-serde 2.0.4", "alloy-signer", "alloy-sol-types", "async-trait", @@ -359,30 +450,44 @@ dependencies = [ [[package]] name = "alloy-network-primitives" -version = "1.1.2" +version = "1.8.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "eb82711d59a43fdfd79727c99f270b974c784ec4eb5728a0d0d22f26716c87ef" +dependencies = [ + "alloy-consensus 1.8.3", + "alloy-eips 1.8.3", + "alloy-primitives 1.5.7", + "alloy-serde 1.8.3", + "serde", +] + +[[package]] +name = "alloy-network-primitives" +version = "2.0.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7805124ad69e57bbae7731c9c344571700b2a18d351bda9e0eba521c991d1bcb" +checksum = "02e6c7ad28afe348a9a9c5624b67ee5b3607b8de98d5816b3056ecdfa6fa2697" dependencies = [ - "alloy-consensus", - "alloy-eips", - "alloy-primitives 1.4.1", - "alloy-serde", + "alloy-consensus 2.0.4", + "alloy-eips 2.0.4", + "alloy-primitives 1.5.7", + "alloy-serde 2.0.4", "serde", ] [[package]] name = "alloy-node-bindings" -version = "1.1.2" +version = "2.0.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b03d35475a02d2a8b76209cb4a1336cb7d85331d10a0f6ec329ee42151695c19" +checksum = "5a29998ddc1f3a7658b82de0784566c65e2f116917a349de7fdd0b765e539d0c" dependencies = [ "alloy-genesis", "alloy-hardforks 0.2.13", "alloy-network", - "alloy-primitives 1.4.1", + "alloy-primitives 1.5.7", "alloy-signer", "alloy-signer-local", "k256 0.13.4", + "libc", "rand 0.8.5", "serde_json", "tempfile", @@ -442,9 +547,9 @@ dependencies = [ [[package]] name = "alloy-primitives" -version = "1.4.1" +version = "1.5.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "355bf68a433e0fd7f7d33d5a9fc2583fde70bf5c530f63b80845f8da5505cf28" +checksum = "de3b431b4e72cd8bd0ec7a50b4be18e73dab74de0dba180eef171055e5d5926e" dependencies = [ "alloy-rlp", "arbitrary", @@ -452,8 +557,9 @@ dependencies = [ "cfg-if", "const-hex", "derive_more 2.1.0", + "fixed-cache", "foldhash 0.2.0", - "getrandom 0.3.4", + "getrandom 0.4.2", "hashbrown 0.16.1", "indexmap 2.12.1", "itoa", @@ -461,31 +567,33 @@ dependencies = [ "keccak-asm", "paste", "proptest", - "proptest-derive 0.6.0", + "proptest-derive", "rand 0.9.2", + "rapidhash", "ruint", "rustc-hash 2.1.1", "serde", "sha3", - "tiny-keccak", ] [[package]] name = "alloy-provider" -version = "1.1.2" +version = "2.0.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d369e12c92870d069e0c9dc5350377067af8a056e29e3badf8446099d7e00889" +checksum = "93a7c17472b55482d4734154c2f5ed13f72e03f6752cebb927f6a2d8b52e646c" dependencies = [ "alloy-chains", - "alloy-consensus", - "alloy-eips", - "alloy-json-rpc", + "alloy-consensus 2.0.4", + "alloy-eips 2.0.4", + "alloy-json-rpc 2.0.4", "alloy-network", - "alloy-network-primitives", - "alloy-primitives 1.4.1", + "alloy-network-primitives 2.0.4", + "alloy-primitives 1.5.7", "alloy-pubsub", "alloy-rpc-client", - "alloy-rpc-types-eth", + "alloy-rpc-types-debug", + "alloy-rpc-types-eth 2.0.4", + "alloy-rpc-types-trace", "alloy-signer", "alloy-sol-types", "alloy-transport", @@ -499,10 +607,10 @@ dependencies = [ "either", "futures", "futures-utils-wasm", - "lru 0.13.0", + "lru 0.16.3", "parking_lot", "pin-project", - "reqwest 0.12.24", + "reqwest 0.13.2", "serde", "serde_json", "thiserror 2.0.17", @@ -514,12 +622,12 @@ dependencies = [ [[package]] name = "alloy-pubsub" -version = "1.1.2" +version = "2.0.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f77d20cdbb68a614c7a86b3ffef607b37d087bb47a03c58f4c3f8f99bc3ace3b" +checksum = "a8d86958b02bca85103d64fa60d7b364a8b017c6e40f2b02c3f50ca22964a738" dependencies = [ - "alloy-json-rpc", - "alloy-primitives 1.4.1", + "alloy-json-rpc 2.0.4", + "alloy-primitives 1.5.7", "alloy-transport", "auto_impl", "bimap", @@ -536,9 +644,9 @@ dependencies = [ [[package]] name = "alloy-rlp" -version = "0.3.12" +version = "0.3.15" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5f70d83b765fdc080dbcd4f4db70d8d23fe4761f2f02ebfa9146b833900634b4" +checksum = "dc90b1e703d3c03f4ff7f48e82dd0bc1c8211ab7d079cd836a06fcfeb06651cb" dependencies = [ "alloy-rlp-derive", "arrayvec", @@ -547,9 +655,9 @@ dependencies = [ [[package]] name = "alloy-rlp-derive" -version = "0.3.12" +version = "0.3.15" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "64b728d511962dda67c1bc7ea7c03736ec275ed2cf4c35d9585298ac9ccf3b73" +checksum = "f36834a5c0a2fa56e171bf256c34d70fca07d0c0031583edea1c4946b7889c9e" dependencies = [ "proc-macro2 1.0.103", "quote 1.0.42", @@ -558,12 +666,12 @@ dependencies = [ [[package]] name = "alloy-rpc-client" -version = "1.1.2" +version = "2.0.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "31c89883fe6b7381744cbe80fef638ac488ead4f1956a4278956a1362c71cd2e" +checksum = "5beb5c2fe6b960c8e8b038e69fd502a90a2e930afa4770efb748b163b0767729" dependencies = [ - "alloy-json-rpc", - "alloy-primitives 1.4.1", + "alloy-json-rpc 2.0.4", + "alloy-primitives 1.5.7", "alloy-pubsub", "alloy-transport", "alloy-transport-http", @@ -571,7 +679,7 @@ dependencies = [ "alloy-transport-ws", "futures", "pin-project", - "reqwest 0.12.24", + "reqwest 0.13.2", "serde", "serde_json", "tokio", @@ -584,79 +692,84 @@ dependencies = [ [[package]] name = "alloy-rpc-types" -version = "1.1.2" +version = "2.0.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "64e279e6d40ee40fe8f76753b678d8d5d260cb276dc6c8a8026099b16d2b43f4" +checksum = "4ee1257a278f6d293e05c5162c5940a1561b1aa85ded0028b464c81de37ebfa5" dependencies = [ - "alloy-primitives 1.4.1", + "alloy-primitives 1.5.7", "alloy-rpc-types-engine", - "alloy-rpc-types-eth", - "alloy-serde", + "alloy-rpc-types-eth 2.0.4", + "alloy-serde 2.0.4", "serde", ] [[package]] name = "alloy-rpc-types-admin" -version = "1.1.2" +version = "2.0.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2bcf50ccb65d29b8599f8f5e23dcac685f1d79459654c830cba381345760e901" +checksum = "e2144d5b2866e651796eac0a997d3b5a056449c12e0d91be3184129e0c722885" dependencies = [ "alloy-genesis", - "alloy-primitives 1.4.1", + "alloy-primitives 1.5.7", "serde", "serde_json", ] [[package]] name = "alloy-rpc-types-anvil" -version = "1.1.2" +version = "2.0.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5e176c26fdd87893b6afeb5d92099d8f7e7a1fe11d6f4fe0883d6e33ac5f31ba" +checksum = "df32156f085e74eac942b6103744be49b817c302341aaa8cb0c1c88dc29228d9" dependencies = [ - "alloy-primitives 1.4.1", - "alloy-rpc-types-eth", - "alloy-serde", + "alloy-primitives 1.5.7", + "alloy-rpc-types-eth 2.0.4", + "alloy-serde 2.0.4", "serde", ] [[package]] name = "alloy-rpc-types-any" -version = "1.1.2" +version = "2.0.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b43c1622aac2508d528743fd4cfdac1dea92d5a8fa894038488ff7edd0af0b32" +checksum = "6a234bfbdf7a76c3d13808f729af5321852de3dedcaa6fc6d5f54787aaf54c6a" dependencies = [ - "alloy-consensus-any", - "alloy-rpc-types-eth", - "alloy-serde", + "alloy-consensus-any 2.0.4", + "alloy-network-primitives 2.0.4", + "alloy-primitives 1.5.7", + "alloy-rpc-types-eth 2.0.4", + "alloy-serde 2.0.4", + "serde", + "serde_json", ] [[package]] name = "alloy-rpc-types-beacon" -version = "1.1.2" +version = "2.0.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1786681640d4c60f22b6b8376b0f3fa200360bf1c3c2cb913e6c97f51928eb1b" +checksum = "296450f5e76bece0116c939b9437b0421a5da9c5d40031bf4cf9b38d3d94e475" dependencies = [ - "alloy-eips", - "alloy-primitives 1.4.1", + "alloy-eips 2.0.4", + "alloy-primitives 1.5.7", "alloy-rpc-types-engine", "derive_more 2.1.0", - "ethereum_ssz 0.9.1", - "ethereum_ssz_derive", + "ethereum_ssz 0.10.1", + "ethereum_ssz_derive 0.10.1", "serde", "serde_json", "serde_with", "thiserror 2.0.17", - "tree_hash 0.10.0", - "tree_hash_derive 0.10.0", + "tree_hash 0.12.1", + "tree_hash_derive 0.12.1", ] [[package]] name = "alloy-rpc-types-debug" -version = "1.1.2" +version = "2.0.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1b2ca3a434a6d49910a7e8e51797eb25db42ef8a5578c52d877fcb26d0afe7bc" +checksum = "0ab075ac1c25bcf697f133b7cd92e2fb26afe213e872ef79fdf77f0d7bcb3793" dependencies = [ - "alloy-primitives 1.4.1", + "alloy-primitives 1.5.7", + "alloy-rlp", "derive_more 2.1.0", "serde", "serde_with", @@ -664,18 +777,18 @@ dependencies = [ [[package]] name = "alloy-rpc-types-engine" -version = "1.1.2" +version = "2.0.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d9c4c53a8b0905d931e7921774a1830609713bd3e8222347963172b03a3ecc68" +checksum = "73b12366c96f4013e1aeebc96c6b56e5f33f07853c42ea2f485045c0c157a4a1" dependencies = [ - "alloy-consensus", - "alloy-eips", - "alloy-primitives 1.4.1", + "alloy-consensus 2.0.4", + "alloy-eips 2.0.4", + "alloy-primitives 1.5.7", "alloy-rlp", - "alloy-serde", + "alloy-serde 2.0.4", "derive_more 2.1.0", - "ethereum_ssz 0.9.1", - "ethereum_ssz_derive", + "ethereum_ssz 0.10.1", + "ethereum_ssz_derive 0.10.1", "jsonwebtoken", "rand 0.8.5", "serde", @@ -684,17 +797,38 @@ dependencies = [ [[package]] name = "alloy-rpc-types-eth" -version = "1.1.2" +version = "1.8.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "59c095f92c4e1ff4981d89e9aa02d5f98c762a1980ab66bec49c44be11349da2" +dependencies = [ + "alloy-consensus 1.8.3", + "alloy-consensus-any 1.8.3", + "alloy-eips 1.8.3", + "alloy-network-primitives 1.8.3", + "alloy-primitives 1.5.7", + "alloy-rlp", + "alloy-serde 1.8.3", + "alloy-sol-types", + "itertools 0.14.0", + "serde", + "serde_json", + "serde_with", + "thiserror 2.0.17", +] + +[[package]] +name = "alloy-rpc-types-eth" +version = "2.0.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ed5fafb741c19b3cca4cdd04fa215c89413491f9695a3e928dee2ae5657f607e" +checksum = "56a282daf869eeb7383d3d5c2deb35b0b3fb45ecb329513af4090fc61245ee18" dependencies = [ - "alloy-consensus", - "alloy-consensus-any", - "alloy-eips", - "alloy-network-primitives", - "alloy-primitives 1.4.1", + "alloy-consensus 2.0.4", + "alloy-consensus-any 2.0.4", + "alloy-eips 2.0.4", + "alloy-network-primitives 2.0.4", + "alloy-primitives 1.5.7", "alloy-rlp", - "alloy-serde", + "alloy-serde 2.0.4", "alloy-sol-types", "arbitrary", "itertools 0.14.0", @@ -706,28 +840,28 @@ dependencies = [ [[package]] name = "alloy-rpc-types-mev" -version = "1.1.2" +version = "2.0.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "49a97bfc6d9b411c85bb08e1174ddd3e5d61b10d3bd13f529d6609f733cb2f6f" +checksum = "7adc1243d55744a66b3a6cbbbba96436e8df5d248f2ee8186bef4238ef704ec7" dependencies = [ - "alloy-consensus", - "alloy-eips", - "alloy-primitives 1.4.1", - "alloy-rpc-types-eth", - "alloy-serde", + "alloy-consensus 2.0.4", + "alloy-eips 2.0.4", + "alloy-primitives 1.5.7", + "alloy-rpc-types-eth 2.0.4", + "alloy-serde 2.0.4", "serde", "serde_json", ] [[package]] name = "alloy-rpc-types-trace" -version = "1.1.2" +version = "2.0.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c55324323aa634b01bdecb2d47462a8dce05f5505b14a6e5db361eef16eda476" +checksum = "6184b5d14152b68b0bb8beb621339d94f0b761a37958bb365fbf7c00922125c2" dependencies = [ - "alloy-primitives 1.4.1", - "alloy-rpc-types-eth", - "alloy-serde", + "alloy-primitives 1.5.7", + "alloy-rpc-types-eth 2.0.4", + "alloy-serde 2.0.4", "serde", "serde_json", "thiserror 2.0.17", @@ -735,23 +869,34 @@ dependencies = [ [[package]] name = "alloy-rpc-types-txpool" -version = "1.1.2" +version = "2.0.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "96b1aa28effb6854be356ce92ed64cea3b323acd04c3f8bfb5126e2839698043" +checksum = "f00b631c361e7c7baaf4f1f5a9877730f3507fed2acb9d4b34841b8184b2ec28" dependencies = [ - "alloy-primitives 1.4.1", - "alloy-rpc-types-eth", - "alloy-serde", + "alloy-primitives 1.5.7", + "alloy-rpc-types-eth 2.0.4", + "alloy-serde 2.0.4", "serde", ] [[package]] name = "alloy-serde" -version = "1.1.2" +version = "1.8.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "11ece63b89294b8614ab3f483560c08d016930f842bf36da56bf0b764a15c11e" +dependencies = [ + "alloy-primitives 1.5.7", + "serde", + "serde_json", +] + +[[package]] +name = "alloy-serde" +version = "2.0.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a6f180c399ca7c1e2fe17ea58343910cad0090878a696ff5a50241aee12fc529" +checksum = "a0eada2558e921b39dfcead33c487364df9b31374f5733c1c9d2c891c4529933" dependencies = [ - "alloy-primitives 1.4.1", + "alloy-primitives 1.5.7", "arbitrary", "serde", "serde_json", @@ -759,11 +904,11 @@ dependencies = [ [[package]] name = "alloy-signer" -version = "1.1.2" +version = "2.0.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ecc39ad2c0a3d2da8891f4081565780703a593f090f768f884049aa3aa929cbc" +checksum = "41eb29f7a8adcd8941fbb8e134022a133e6f8dfd345f2e3b7109599f8a7dca08" dependencies = [ - "alloy-primitives 1.4.1", + "alloy-primitives 1.5.7", "async-trait", "auto_impl", "either", @@ -774,13 +919,13 @@ dependencies = [ [[package]] name = "alloy-signer-local" -version = "1.1.2" +version = "2.0.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "930e17cb1e46446a193a593a3bfff8d0ecee4e510b802575ebe300ae2e43ef75" +checksum = "bef839e7ce9b59aa60fa9a175e97986c6145c888d643b0f1fb0a3e7b8e56a2e2" dependencies = [ - "alloy-consensus", + "alloy-consensus 2.0.4", "alloy-network", - "alloy-primitives 1.4.1", + "alloy-primitives 1.5.7", "alloy-signer", "async-trait", "coins-bip32", @@ -793,9 +938,9 @@ dependencies = [ [[package]] name = "alloy-sol-macro" -version = "1.4.1" +version = "1.5.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f3ce480400051b5217f19d6e9a82d9010cdde20f1ae9c00d53591e4a1afbb312" +checksum = "ab81bab693da9bb79f7a95b64b394718259fdd7e41dceeced4cad57cb71c4f6a" dependencies = [ "alloy-sol-macro-expander", "alloy-sol-macro-input", @@ -807,9 +952,9 @@ dependencies = [ [[package]] name = "alloy-sol-macro-expander" -version = "1.4.1" +version = "1.5.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6d792e205ed3b72f795a8044c52877d2e6b6e9b1d13f431478121d8d4eaa9028" +checksum = "489f1620bb7e2483fb5819ed01ab6edc1d2f93939dce35a5695085a1afd1d699" dependencies = [ "alloy-sol-macro-input", "const-hex", @@ -818,16 +963,16 @@ dependencies = [ "proc-macro-error2", "proc-macro2 1.0.103", "quote 1.0.42", + "sha3", "syn 2.0.111", "syn-solidity", - "tiny-keccak", ] [[package]] name = "alloy-sol-macro-input" -version = "1.4.1" +version = "1.5.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0bd1247a8f90b465ef3f1207627547ec16940c35597875cdc09c49d58b19693c" +checksum = "56cef806ad22d4392c5fc83cf8f2089f988eb99c7067b4e0c6f1971fc1cca318" dependencies = [ "const-hex", "dunce", @@ -841,9 +986,9 @@ dependencies = [ [[package]] name = "alloy-sol-type-parser" -version = "1.4.1" +version = "1.5.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "954d1b2533b9b2c7959652df3076954ecb1122a28cc740aa84e7b0a49f6ac0a9" +checksum = "a6df77fea9d6a2a75c0ef8d2acbdfd92286cc599983d3175ccdc170d3433d249" dependencies = [ "serde", "winnow", @@ -851,23 +996,23 @@ dependencies = [ [[package]] name = "alloy-sol-types" -version = "1.4.1" +version = "1.5.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "70319350969a3af119da6fb3e9bddb1bce66c9ea933600cb297c8b1850ad2a3c" +checksum = "64612d29379782a5dde6f4b6570d9c756d734d760c0c94c254d361e678a6591f" dependencies = [ "alloy-json-abi", - "alloy-primitives 1.4.1", + "alloy-primitives 1.5.7", "alloy-sol-macro", "serde", ] [[package]] name = "alloy-transport" -version = "1.1.2" +version = "2.0.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cae82426d98f8bc18f53c5223862907cac30ab8fc5e4cd2bb50808e6d3ab43d8" +checksum = "3ac7a80c0bac3e44559d53d002e34c461dc2f23262b42cafec019bc70551abbe" dependencies = [ - "alloy-json-rpc", + "alloy-json-rpc 2.0.4", "auto_impl", "base64 0.22.1", "derive_more 2.1.0", @@ -886,13 +1031,14 @@ dependencies = [ [[package]] name = "alloy-transport-http" -version = "1.1.2" +version = "2.0.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "90aa6825760905898c106aba9c804b131816a15041523e80b6d4fe7af6380ada" +checksum = "eed3ed3300a998f88639ed619fdbbd88bd82865e00c6a8ecb796c99eb12358f6" dependencies = [ - "alloy-json-rpc", + "alloy-json-rpc 2.0.4", "alloy-transport", - "reqwest 0.12.24", + "itertools 0.14.0", + "reqwest 0.13.2", "serde_json", "tower 0.5.2", "tracing", @@ -901,11 +1047,11 @@ dependencies = [ [[package]] name = "alloy-transport-ipc" -version = "1.1.2" +version = "2.0.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6ace83a4a6bb896e5894c3479042e6ba78aa5271dde599aa8c36a021d49cc8cc" +checksum = "1075d9d30fd4d71e50000fd4afb19ed2664ceab20c2a29f3889a6e988329e02d" dependencies = [ - "alloy-json-rpc", + "alloy-json-rpc 2.0.4", "alloy-pubsub", "alloy-transport", "bytes", @@ -921,9 +1067,9 @@ dependencies = [ [[package]] name = "alloy-transport-ws" -version = "1.1.2" +version = "2.0.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "86c9ab4c199e3a8f3520b60ba81aa67bb21fed9ed0d8304e0569094d0758a56f" +checksum = "0e3bff84b2b2a46eb34cc522dc3f889a2867c70be90a377421429b662b3ec4ce" dependencies = [ "alloy-pubsub", "alloy-transport", @@ -932,53 +1078,51 @@ dependencies = [ "rustls 0.23.35", "serde_json", "tokio", - "tokio-tungstenite 0.26.2", + "tokio-tungstenite 0.28.0", "tracing", + "url", "ws_stream_wasm", ] [[package]] name = "alloy-trie" -version = "0.8.1" +version = "0.9.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "983d99aa81f586cef9dae38443245e585840fcf0fc58b09aee0b1f27aed1d500" +checksum = "3f14b5d9b2c2173980202c6ff470d96e7c5e202c65a9f67884ad565226df7fbb" dependencies = [ - "alloy-primitives 1.4.1", + "alloy-primitives 1.5.7", "alloy-rlp", - "arrayvec", + "arbitrary", + "derive_arbitrary", "derive_more 2.1.0", - "nybbles 0.3.4", + "nybbles", + "proptest", + "proptest-derive", + "serde", "smallvec", + "thiserror 2.0.17", "tracing", ] [[package]] -name = "alloy-trie" -version = "0.9.1" +name = "alloy-tx-macros" +version = "1.8.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e3412d52bb97c6c6cc27ccc28d4e6e8cf605469101193b50b0bd5813b1f990b5" +checksum = "d69722eddcdf1ce096c3ab66cf8116999363f734eb36fe94a148f4f71c85da84" dependencies = [ - "alloy-primitives 1.4.1", - "alloy-rlp", - "arbitrary", - "arrayvec", - "derive_arbitrary", - "derive_more 2.1.0", - "nybbles 0.4.6", - "proptest", - "proptest-derive 0.5.1", - "serde", - "smallvec", - "tracing", + "darling 0.23.0", + "proc-macro2 1.0.103", + "quote 1.0.42", + "syn 2.0.111", ] [[package]] name = "alloy-tx-macros" -version = "1.1.2" +version = "2.0.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ae109e33814b49fc0a62f2528993aa8a2dd346c26959b151f05441dc0b9da292" +checksum = "99fce0350197dcd4ba4e9a7dd43915d908c0eb0e7352755791709a705e1c76b6" dependencies = [ - "darling 0.21.3", + "darling 0.23.0", "proc-macro2 1.0.103", "quote 1.0.42", "syn 2.0.111", @@ -1078,6 +1222,21 @@ dependencies = [ "derive_arbitrary", ] +[[package]] +name = "archery" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0a8da9bc4c4053ee067669762bcaeea6e241841295a2b6c948312dad6ef4cc02" +dependencies = [ + "static_assertions", +] + +[[package]] +name = "archery" +version = "1.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "70e0a5f99dfebb87bb342d0f53bb92c81842e100bbb915223e38349580e5441d" + [[package]] name = "argminmax" version = "0.6.3" @@ -1595,54 +1754,126 @@ version = "1.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c08606f8c3cbf4ce6ec8e28fb0014a2c086708fe954eaa885384a6165172e7e8" +[[package]] +name = "aws-lc-rs" +version = "1.16.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a054912289d18629dc78375ba2c3726a3afe3ff71b4edba9dedfca0e3446d1fc" +dependencies = [ + "aws-lc-sys", + "untrusted 0.7.1", + "zeroize", +] + +[[package]] +name = "aws-lc-sys" +version = "0.39.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "83a25cf98105baa966497416dbd42565ce3a8cf8dbfd59803ec9ad46f3126399" +dependencies = [ + "cc", + "cmake", + "dunce", + "fs_extra", +] + [[package]] name = "axum" -version = "0.8.7" +version = "0.7.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5b098575ebe77cb6d14fc7f32749631a6e44edbef6b796f89b020e99ba20d425" +checksum = "edca88bc138befd0323b20752846e6587272d3b03b0343c8ea28a6f819e6e71f" dependencies = [ - "axum-core", + "async-trait", + "axum-core 0.4.5", "bytes", "futures-util", "http 1.4.0", "http-body 1.0.1", "http-body-util", + "hyper 1.8.1", + "hyper-util", "itoa", - "matchit", + "matchit 0.7.3", "memchr", "mime", "percent-encoding", "pin-project-lite", - "serde_core", + "rustversion", + "serde", + "serde_json", + "serde_path_to_error", + "serde_urlencoded", "sync_wrapper 1.0.2", + "tokio", "tower 0.5.2", "tower-layer", "tower-service", + "tracing", ] [[package]] -name = "axum-core" -version = "0.5.5" +name = "axum" +version = "0.8.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "59446ce19cd142f8833f856eb31f3eb097812d1479ab224f54d72428ca21ea22" +checksum = "5b098575ebe77cb6d14fc7f32749631a6e44edbef6b796f89b020e99ba20d425" dependencies = [ + "axum-core 0.5.5", "bytes", - "futures-core", + "futures-util", "http 1.4.0", "http-body 1.0.1", "http-body-util", + "itoa", + "matchit 0.8.4", + "memchr", "mime", + "percent-encoding", "pin-project-lite", + "serde_core", "sync_wrapper 1.0.2", + "tower 0.5.2", "tower-layer", "tower-service", ] [[package]] -name = "az" -version = "1.2.1" +name = "axum-core" +version = "0.4.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "09f2bd6146b97ae3359fa0cc6d6b376d9539582c7b4220f041a33ec24c226199" +dependencies = [ + "async-trait", + "bytes", + "futures-util", + "http 1.4.0", + "http-body 1.0.1", + "http-body-util", + "mime", + "pin-project-lite", + "rustversion", + "sync_wrapper 1.0.2", + "tower-layer", + "tower-service", + "tracing", +] + +[[package]] +name = "axum-core" +version = "0.5.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7b7e4c2464d97fe331d41de9d5db0def0a96f4d823b8b32a2efd503578988973" +checksum = "59446ce19cd142f8833f856eb31f3eb097812d1479ab224f54d72428ca21ea22" +dependencies = [ + "bytes", + "futures-core", + "http 1.4.0", + "http-body 1.0.1", + "http-body-util", + "mime", + "pin-project-lite", + "sync_wrapper 1.0.2", + "tower-layer", + "tower-service", +] [[package]] name = "backon" @@ -1744,13 +1975,13 @@ dependencies = [ name = "bid-scraper" version = "0.1.0" dependencies = [ - "alloy-primitives 1.4.1", + "alloy-primitives 1.5.7", "alloy-provider", "alloy-rpc-types-beacon", "async-trait", "derivative", "ethereum_ssz 0.9.1", - "ethereum_ssz_derive", + "ethereum_ssz_derive 0.9.1", "exponential-backoff", "eyre", "futures", @@ -1813,24 +2044,6 @@ dependencies = [ "serde", ] -[[package]] -name = "bindgen" -version = "0.71.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5f58bf3d7db68cfbac37cfc485a8d711e87e064c3d0fe0435b92f7a407f9d6b3" -dependencies = [ - "bitflags 2.10.0", - "cexpr", - "clang-sys", - "itertools 0.13.0", - "proc-macro2 1.0.103", - "quote 1.0.42", - "regex", - "rustc-hash 2.1.1", - "shlex", - "syn 2.0.111", -] - [[package]] name = "bindgen" version = "0.72.1" @@ -1840,7 +2053,7 @@ dependencies = [ "bitflags 2.10.0", "cexpr", "clang-sys", - "itertools 0.13.0", + "itertools 0.11.0", "log", "prettyplease", "proc-macro2 1.0.103", @@ -1897,6 +2110,12 @@ dependencies = [ "serde_core", ] +[[package]] +name = "bitmaps" +version = "3.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a1d084b0137aaa901caf9f1e8b21daa6aa24d41cd806e111335541eff9683bd6" + [[package]] name = "bitvec" version = "1.0.1" @@ -1910,6 +2129,20 @@ dependencies = [ "wyz", ] +[[package]] +name = "blake3" +version = "1.8.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4d2d5991425dfd0785aed03aedcf0b321d61975c9b5b3689c774a2610ae0b51e" +dependencies = [ + "arrayref", + "arrayvec", + "cc", + "cfg-if", + "constant_time_eq 0.4.2", + "cpufeatures 0.3.0", +] + [[package]] name = "block-buffer" version = "0.9.0" @@ -1937,6 +2170,25 @@ dependencies = [ "generic-array", ] +[[package]] +name = "bls" +version = "0.2.0" +source = "git+https://github.com/sigp/lighthouse?rev=27cfa18c17e148fb75827d0ea3c9a2c69db0aae0#27cfa18c17e148fb75827d0ea3c9a2c69db0aae0" +dependencies = [ + "alloy-primitives 1.5.7", + "blst", + "ethereum_hashing 0.8.0", + "ethereum_serde_utils 0.8.0", + "ethereum_ssz 0.10.1", + "fixed_bytes", + "hex", + "rand 0.9.2", + "safe_arith", + "serde", + "tree_hash 0.12.1", + "zeroize", +] + [[package]] name = "blst" version = "0.3.16" @@ -1949,6 +2201,22 @@ dependencies = [ "zeroize", ] +[[package]] +name = "blstrs" +version = "0.7.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7a8a8ed6fefbeef4a8c7b460e4110e12c5e22a5b7cf32621aae6ad650c4dcf29" +dependencies = [ + "blst", + "byte-slice-cast", + "ff 0.13.1", + "group 0.13.0", + "pairing", + "rand_core 0.6.4", + "serde", + "subtle", +] + [[package]] name = "bnum" version = "0.13.0" @@ -2217,12 +2485,6 @@ version = "1.2.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7575182f7272186991736b70173b0ea045398f984bf5ebbb3804736ce1330c9d" -[[package]] -name = "bytecount" -version = "0.6.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "175812e0be2bccb6abe50bb8d566126198344f707e304f45c648fd8f2cc0365e" - [[package]] name = "bytemuck" version = "1.24.0" @@ -2251,9 +2513,9 @@ checksum = "1fd0f2584146f6f2ef48085050886acf353beff7305ebd1ae69500e27c67f64b" [[package]] name = "bytes" -version = "1.11.0" +version = "1.11.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b35204fbdc0b3f4446b89fc1ac2cf84a8a68971995d0bf2e925ec7cd960f9cb3" +checksum = "1e748733b7cbc798e1434b6ac524f0c1ff2ab456fe201501e6497c8417a4fc33" dependencies = [ "serde", ] @@ -2280,9 +2542,9 @@ dependencies = [ [[package]] name = "c-kzg" -version = "2.1.5" +version = "2.1.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e00bf4b112b07b505472dbefd19e37e53307e2bfed5a79e0cc161d58ccd0e687" +checksum = "6648ed1e4ea8e8a1a4a2c78e1cda29a3fd500bc622899c340d8525ea9a76b24a" dependencies = [ "arbitrary", "blst", @@ -2305,31 +2567,19 @@ dependencies = [ [[package]] name = "cargo-platform" -version = "0.1.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e35af189006b9c0f00a064685c727031e3ed2d8020f7ba284d78cc2671bd36ea" -dependencies = [ - "serde", -] - -[[package]] -name = "cargo_metadata" -version = "0.14.2" +version = "0.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4acbb09d9ee8e23699b9634375c72795d095bf268439da88562cf9b501f181fa" +checksum = "87a0c0e6148f11f01f32650a2ea02d532b2ad4e81d8bd41e6e565b5adc5e6082" dependencies = [ - "camino", - "cargo-platform", - "semver 1.0.27", "serde", - "serde_json", + "serde_core", ] [[package]] name = "cargo_metadata" -version = "0.19.2" +version = "0.23.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dd5eb614ed4c27c5d706420e4320fbe3216ab31fa1c33cd8246ac36dae4479ba" +checksum = "ef987d17b0a113becdd19d3d0022d04d7ef41f9efe4f3fb63ac44ba61df3ade9" dependencies = [ "camino", "cargo-platform", @@ -2339,12 +2589,6 @@ dependencies = [ "thiserror 2.0.17", ] -[[package]] -name = "cassowary" -version = "0.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "df8670b8c7b9dae1793364eafadf7239c40d669904660c5960d74cfd80b46a53" - [[package]] name = "cast" version = "0.3.0" @@ -2362,10 +2606,11 @@ dependencies = [ [[package]] name = "cc" -version = "1.2.15" +version = "1.2.60" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c736e259eea577f443d5c86c304f9f4ae0295c43f3ba05c21f1d66b5f06001af" +checksum = "43c5703da9466b66a946814e1adf53ea2c90f10063b86290cc9eb67ce3478a20" dependencies = [ + "find-msvc-tools", "jobserver", "libc", "shlex", @@ -2534,7 +2779,7 @@ dependencies = [ "hyper 1.8.1", "hyper-tls 0.6.0", "hyper-util", - "lz4_flex", + "lz4_flex 0.11.5", "polonius-the-crab", "quanta", "serde", @@ -2667,16 +2912,16 @@ version = "7.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b03b7db8e0b4b2fdad6c551e634134e99ec000e5c8c3b6856c65e8bbaded7a3b" dependencies = [ - "crossterm 0.29.0", + "crossterm", "unicode-segmentation", - "unicode-width 0.2.0", + "unicode-width", ] [[package]] name = "compact_str" -version = "0.8.1" +version = "0.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3b79c4069c6cad78e2e0cdfcbd26275770669fb39fd308a752dc110e83b9af32" +checksum = "3fdb1325a1cece981e8a296ab8f0f9b63ae357bd0784a9faaf548cc7b480707a" dependencies = [ "castaway", "cfg-if", @@ -2686,6 +2931,26 @@ dependencies = [ "static_assertions", ] +[[package]] +name = "compare_fields" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f6f45d0b4d61b582303179fb7a1a142bc9d647b7583db3b0d5f25a21d286fab9" +dependencies = [ + "compare_fields_derive", + "itertools 0.14.0", +] + +[[package]] +name = "compare_fields_derive" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "92ff1dbbda10d495b2c92749c002b2025e0be98f42d1741ecc9ff820d2f04dce" +dependencies = [ + "quote 1.0.42", + "syn 2.0.111", +] + [[package]] name = "compression-codecs" version = "0.4.33" @@ -2733,7 +2998,7 @@ dependencies = [ "encode_unicode", "libc", "once_cell", - "unicode-width 0.2.0", + "unicode-width", "windows-sys 0.59.0", ] @@ -2744,7 +3009,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3bb320cac8a0750d7f25280aa97b09c26edfe161164238ecbbb31092b079e735" dependencies = [ "cfg-if", - "cpufeatures", + "cpufeatures 0.2.17", "proptest", "serde_core", ] @@ -2787,6 +3052,32 @@ version = "0.1.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "245097e9a4535ee1e3e3931fcfcd55a796a44c643e8596ff6566d68f09b87bbc" +[[package]] +name = "constant_time_eq" +version = "0.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3d52eff69cd5e647efe296129160853a42795992097e8af39800e1060caeea9b" + +[[package]] +name = "context_deserialize" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4c523eea4af094b5970c321f4604abc42c5549d3cbae332e98325403fbbdbf70" +dependencies = [ + "context_deserialize_derive", + "serde", +] + +[[package]] +name = "context_deserialize_derive" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3b7bf98c48ffa511b14bb3c76202c24a8742cea1efa9570391c5d41373419a09" +dependencies = [ + "quote 1.0.42", + "syn 2.0.111", +] + [[package]] name = "convert_case" version = "0.4.0" @@ -2862,6 +3153,15 @@ dependencies = [ "libc", ] +[[package]] +name = "cpufeatures" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8b2a41393f66f16b0823bb79094d54ac5fbd34ab292ddafb9a0456ac9f87d201" +dependencies = [ + "libc", +] + [[package]] name = "crc" version = "3.4.0" @@ -2986,22 +3286,6 @@ version = "0.8.21" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d0a5c400df2834b80a4c3327b3aad3a4c4cd4de0629063962b03235697506a28" -[[package]] -name = "crossterm" -version = "0.28.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "829d955a0bb380ef178a640b91779e3987da38c9aea133b20614cfed8cdea9c6" -dependencies = [ - "bitflags 2.10.0", - "crossterm_winapi", - "mio", - "parking_lot", - "rustix 0.38.44", - "signal-hook", - "signal-hook-mio", - "winapi", -] - [[package]] name = "crossterm" version = "0.29.0" @@ -3010,9 +3294,13 @@ checksum = "d8b9f2e4c67f833b660cdb0a3523065869fb35570177239812ed4c905aeff87b" dependencies = [ "bitflags 2.10.0", "crossterm_winapi", + "derive_more 2.1.0", "document-features", + "mio", "parking_lot", - "rustix 1.1.2", + "rustix", + "signal-hook", + "signal-hook-mio", "winapi", ] @@ -3136,7 +3424,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "97fb8b7c4503de7d6ae7b42ab72a5a59857b4c937ec27a3d4539dba95b5ab2be" dependencies = [ "cfg-if", - "cpufeatures", + "cpufeatures 0.2.17", "curve25519-dalek-derive", "digest 0.10.7", "fiat-crypto", @@ -3176,6 +3464,16 @@ dependencies = [ "darling_macro 0.21.3", ] +[[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" @@ -3197,6 +3495,19 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1247195ecd7e3c85f83c8d2a366e4210d588e802133e1e355180a9870b517ea4" dependencies = [ "fnv", + "ident_case", + "proc-macro2 1.0.103", + "quote 1.0.42", + "strsim", + "syn 2.0.111", +] + +[[package]] +name = "darling_core" +version = "0.23.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9865a50f7c335f53564bb694ef660825eb8610e0a53d3e11bf1b0d3df31e03b0" +dependencies = [ "ident_case", "proc-macro2 1.0.103", "quote 1.0.42", @@ -3227,6 +3538,17 @@ dependencies = [ "syn 2.0.111", ] +[[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", + "quote 1.0.42", + "syn 2.0.111", +] + [[package]] name = "dashmap" version = "5.5.3" @@ -3246,6 +3568,7 @@ version = "6.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5041cc499144891f3790297212f32a74fb938e5136a14943f338ef9e0ae276cf" dependencies = [ + "arbitrary", "cfg-if", "crossbeam-utils", "hashbrown 0.14.5", @@ -3253,6 +3576,7 @@ dependencies = [ "once_cell", "parking_lot_core", "rayon", + "serde", ] [[package]] @@ -3526,9 +3850,8 @@ dependencies = [ [[package]] name = "discv5" -version = "0.10.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f170f4f6ed0e1df52bf43b403899f0081917ecf1500bfe312505cc3b515a8899" +version = "0.10.4" +source = "git+https://github.com/sigp/discv5?rev=7663c00#7663c00ee0837ea98547caaedede95d9d6736f4d" dependencies = [ "aes", "aes-gcm", @@ -3539,18 +3862,17 @@ dependencies = [ "enr 0.13.0", "fnv", "futures", - "hashlink 0.9.1", + "hashlink 0.11.0", "hex", "hkdf", "lazy_static", "libp2p-identity", - "lru 0.12.5", "more-asserts", "multiaddr 0.18.2", "parking_lot", "rand 0.8.5", "smallvec", - "socket2 0.5.10", + "socket2 0.6.3", "tokio", "tracing", "uint 0.10.0", @@ -3712,6 +4034,25 @@ version = "0.6.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "12a0bb14ac04a9fcf170d0bbbef949b44cc492f4452bd20c095636956f653642" +[[package]] +name = "eip4844" +version = "0.9.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "82ab45fc63db6bbe5c3eb7c79303b2aff7ee529c991b2111c46879d1ea38407e" +dependencies = [ + "ekzg-bls12-381", + "ekzg-maybe-rayon", + "ekzg-polynomial", + "ekzg-serialization", + "ekzg-single-open", + "ekzg-trusted-setup", + "hex", + "itertools 0.14.0", + "serde", + "serde_json", + "sha2 0.10.9", +] + [[package]] name = "either" version = "1.15.0" @@ -3722,34 +4063,120 @@ dependencies = [ ] [[package]] -name = "elliptic-curve" -version = "0.12.3" +name = "ekzg-bls12-381" +version = "0.9.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e7bb888ab5300a19b8e5bceef25ac745ad065f3c9f7efc6de1b91958110891d3" +checksum = "05c599a59deba6188afd9f783507e4d89efc997f0fa340a758f0d0992b322416" dependencies = [ - "base16ct 0.1.1", - "crypto-bigint 0.4.9", - "der 0.6.1", - "digest 0.10.7", - "ff 0.12.1", - "generic-array", - "group 0.12.1", - "pkcs8 0.9.0", - "rand_core 0.6.4", - "sec1 0.3.0", + "blst", + "blstrs", + "ff 0.13.1", + "group 0.13.0", + "pairing", "subtle", - "zeroize", ] [[package]] -name = "elliptic-curve" -version = "0.13.8" +name = "ekzg-erasure-codes" +version = "0.9.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b5e6043086bf7973472e0c7dff2142ea0b680d30e18d9cc40f267efbf222bd47" +checksum = "8474a41a30ddd2b651798b1aa9ce92011207c3667186fe9044184683250109e7" dependencies = [ - "base16ct 0.2.0", - "crypto-bigint 0.5.5", - "digest 0.10.7", + "ekzg-bls12-381", + "ekzg-polynomial", +] + +[[package]] +name = "ekzg-maybe-rayon" +version = "0.9.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9cf94d1385185c1f7caef4973be49702c7d9ffdeaf832d126dbb9ed6efe09d40" + +[[package]] +name = "ekzg-multi-open" +version = "0.9.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e6d37456a32cf79bdbddd6685a2adec73210e2d60332370bc0e9a502b6d93beb" +dependencies = [ + "ekzg-bls12-381", + "ekzg-maybe-rayon", + "ekzg-polynomial", + "sha2 0.10.9", +] + +[[package]] +name = "ekzg-polynomial" +version = "0.9.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "704751bac85af4754bb8a14457ef24d820738062d0b6f3763534d0980b1a1e81" +dependencies = [ + "ekzg-bls12-381", + "ekzg-maybe-rayon", +] + +[[package]] +name = "ekzg-serialization" +version = "0.9.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3cb983d9f75b2804c00246def8d52c01cf05f70c22593b8d314fbcf0cf89042b" +dependencies = [ + "ekzg-bls12-381", + "hex", +] + +[[package]] +name = "ekzg-single-open" +version = "0.9.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "799d5806d51e1453fa0f528d6acf4127e2a89e98312c826151ebc24ee3448ec3" +dependencies = [ + "ekzg-bls12-381", + "ekzg-polynomial", + "itertools 0.14.0", +] + +[[package]] +name = "ekzg-trusted-setup" +version = "0.9.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "85314d56718dc2c6dd77c3b3630f1839defcb6f47d9c20195608a0f7976095ab" +dependencies = [ + "ekzg-bls12-381", + "ekzg-serialization", + "hex", + "serde", + "serde_json", +] + +[[package]] +name = "elliptic-curve" +version = "0.12.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e7bb888ab5300a19b8e5bceef25ac745ad065f3c9f7efc6de1b91958110891d3" +dependencies = [ + "base16ct 0.1.1", + "crypto-bigint 0.4.9", + "der 0.6.1", + "digest 0.10.7", + "ff 0.12.1", + "generic-array", + "group 0.12.1", + "pkcs8 0.9.0", + "rand_core 0.6.4", + "sec1 0.3.0", + "subtle", + "zeroize", +] + +[[package]] +name = "elliptic-curve" +version = "0.13.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b5e6043086bf7973472e0c7dff2142ea0b680d30e18d9cc40f267efbf222bd47" +dependencies = [ + "base16ct 0.2.0", + "crypto-bigint 0.5.5", + "digest 0.10.7", "ff 0.13.1", "generic-array", "group 0.13.0", @@ -3927,15 +4354,6 @@ dependencies = [ "windows-sys 0.61.2", ] -[[package]] -name = "error-chain" -version = "0.12.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2d2f06b9cac1506ece98fe3231e3cc9c4410ec3d5b1f24ae1c8946f0742cdefc" -dependencies = [ - "version_check 0.9.5", -] - [[package]] name = "etcetera" version = "0.8.0" @@ -3951,9 +4369,9 @@ dependencies = [ name = "eth-sparse-mpt" version = "0.1.0" dependencies = [ - "alloy-primitives 1.4.1", + "alloy-primitives 1.5.7", "alloy-rlp", - "alloy-trie 0.8.1", + "alloy-trie", "arrayvec", "criterion", "dashmap 6.1.0", @@ -3961,7 +4379,7 @@ dependencies = [ "eyre", "flate2", "hash-db", - "nybbles 0.3.4", + "nybbles", "parking_lot", "proptest", "rand 0.8.5", @@ -3982,6 +4400,19 @@ dependencies = [ "triehash", ] +[[package]] +name = "eth2_interop_keypairs" +version = "0.2.0" +source = "git+https://github.com/sigp/lighthouse?rev=27cfa18c17e148fb75827d0ea3c9a2c69db0aae0#27cfa18c17e148fb75827d0ea3c9a2c69db0aae0" +dependencies = [ + "bls", + "ethereum_hashing 0.8.0", + "hex", + "num-bigint", + "serde", + "yaml_serde", +] + [[package]] name = "ethabi" version = "18.0.0" @@ -4060,7 +4491,18 @@ version = "0.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c853bd72c9e5787f8aafc3df2907c2ed03cff3150c3acd94e2e53a98ab70a8ab" dependencies = [ - "cpufeatures", + "cpufeatures 0.2.17", + "ring", + "sha2 0.10.9", +] + +[[package]] +name = "ethereum_hashing" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5aa93f58bb1eb3d1e556e4f408ef1dac130bad01ac37db4e7ade45de40d1c86a" +dependencies = [ + "cpufeatures 0.2.17", "ring", "sha2 0.10.9", ] @@ -4084,7 +4526,7 @@ version = "0.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3dc1355dbb41fbbd34ec28d4fb2a57d9a70c67ac3c19f6a5ca4d4a176b9e997a" dependencies = [ - "alloy-primitives 1.4.1", + "alloy-primitives 1.5.7", "hex", "serde", "serde_derive", @@ -4108,7 +4550,7 @@ version = "0.9.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0dcddb2554d19cde19b099fadddde576929d7a4d0c1cd3512d1fd95cf174375c" dependencies = [ - "alloy-primitives 1.4.1", + "alloy-primitives 1.5.7", "ethereum_serde_utils 0.8.0", "itertools 0.13.0", "serde", @@ -4117,6 +4559,22 @@ dependencies = [ "typenum", ] +[[package]] +name = "ethereum_ssz" +version = "0.10.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2128a84f7a3850d54ee343334e3392cca61f9f6aa9441eec481b9394b43c238b" +dependencies = [ + "alloy-primitives 1.5.7", + "context_deserialize", + "ethereum_serde_utils 0.8.0", + "itertools 0.14.0", + "serde", + "serde_derive", + "smallvec", + "typenum", +] + [[package]] name = "ethereum_ssz_derive" version = "0.9.1" @@ -4129,6 +4587,18 @@ dependencies = [ "syn 2.0.111", ] +[[package]] +name = "ethereum_ssz_derive" +version = "0.10.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cd596f91cff004fc8d02be44c21c0f9b93140a04b66027ae052f5f8e05b48eba" +dependencies = [ + "darling 0.23.0", + "proc-macro2 1.0.103", + "quote 1.0.42", + "syn 2.0.111", +] + [[package]] name = "ethers-core" version = "2.0.14" @@ -4268,6 +4738,7 @@ version = "0.13.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c0b50bfb653653f9ca9095b427bed08ab8d75a137839d9ad64eb11810d5b6393" dependencies = [ + "bitvec", "rand_core 0.6.4", "subtle", ] @@ -4290,6 +4761,23 @@ dependencies = [ "windows-sys 0.60.2", ] +[[package]] +name = "find-msvc-tools" +version = "0.1.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5baebc0774151f905a1a2cc41989300b1e6fbb29aff0ceffa1064fdd3088d582" + +[[package]] +name = "fixed-cache" +version = "0.1.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c41c7aa69c00ebccf06c3fa7ffe2a6cf26a58b5fe4deabfe646285ff48136a8f" +dependencies = [ + "equivalent", + "rapidhash", + "typeid", +] + [[package]] name = "fixed-hash" version = "0.8.0" @@ -4302,6 +4790,36 @@ dependencies = [ "static_assertions", ] +[[package]] +name = "fixed-map" +version = "0.9.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "86ed19add84e8cb9e8cc5f7074de0324247149ffef0b851e215fb0edc50c229b" +dependencies = [ + "fixed-map-derive", + "serde", +] + +[[package]] +name = "fixed-map-derive" +version = "0.9.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6dc7a9cb3326bafb80642c5ce99b39a2c0702d4bfa8ee8a3e773791a6cbe2407" +dependencies = [ + "proc-macro2 1.0.103", + "quote 1.0.42", + "syn 2.0.111", +] + +[[package]] +name = "fixed_bytes" +version = "0.1.0" +source = "git+https://github.com/sigp/lighthouse?rev=27cfa18c17e148fb75827d0ea3c9a2c69db0aae0#27cfa18c17e148fb75827d0ea3c9a2c69db0aae0" +dependencies = [ + "alloy-primitives 1.5.7", + "safe_arith", +] + [[package]] name = "fixedbitset" version = "0.5.7" @@ -4394,6 +4912,12 @@ version = "2.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "28dd6caf6059519a65843af8fe2a3ae298b14b80179855aeb4adc2c1934ee619" +[[package]] +name = "fs_extra" +version = "1.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "42703706b716c37f96a77aea830392ad231f44c9e9a67872fa5548707e11b11c" + [[package]] name = "fsevent-sys" version = "4.1.0" @@ -4716,7 +5240,7 @@ version = "0.2.24" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "cfe4fbac503b8d1f88e6676011885f34b7174f46e59956bba534ba83abded4df" dependencies = [ - "unicode-width 0.2.0", + "unicode-width", ] [[package]] @@ -4752,11 +5276,24 @@ dependencies = [ "cfg-if", "js-sys", "libc", - "r-efi", + "r-efi 5.3.0", "wasip2", "wasm-bindgen", ] +[[package]] +name = "getrandom" +version = "0.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0de51e6874e94e7bf76d726fc5d13ba782deca734ff60d5bb2fb2607c7406555" +dependencies = [ + "cfg-if", + "libc", + "r-efi 6.0.0", + "wasip2", + "wasip3", +] + [[package]] name = "ghash" version = "0.5.1" @@ -4853,16 +5390,6 @@ dependencies = [ "web-sys", ] -[[package]] -name = "gmp-mpfr-sys" -version = "1.6.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "60f8970a75c006bb2f8ae79c6768a116dd215fa8346a87aed99bf9d82ca43394" -dependencies = [ - "libc", - "windows-sys 0.60.2", -] - [[package]] name = "governor" version = "0.6.3" @@ -4901,7 +5428,9 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f0f9ef7462f7c099f518d754361858f86d8a07af53ba9af0fe635bbccb151a63" dependencies = [ "ff 0.13.1", + "rand 0.8.5", "rand_core 0.6.4", + "rand_xorshift 0.3.0", "subtle", ] @@ -5028,11 +5557,11 @@ dependencies = [ [[package]] name = "hashlink" -version = "0.9.1" +version = "0.11.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6ba4ff7128dee98c7dc9794b6a411377e1404dba1c97deb8d1a55297bd25d8af" +checksum = "ea0b22561a9c04a7cb1a302c013e0259cd3b4bb619f145b32f72b8b4bcbed230" dependencies = [ - "hashbrown 0.14.5", + "hashbrown 0.16.1", ] [[package]] @@ -5405,7 +5934,6 @@ dependencies = [ "tokio", "tokio-rustls 0.26.4", "tower-service", - "webpki-roots 1.0.4", ] [[package]] @@ -5468,8 +5996,8 @@ dependencies = [ "libc", "percent-encoding", "pin-project-lite", - "socket2 0.6.1", - "system-configuration 0.6.1", + "socket2 0.6.3", + "system-configuration", "tokio", "tower-service", "tracing", @@ -5488,7 +6016,7 @@ dependencies = [ "js-sys", "log", "wasm-bindgen", - "windows-core 0.62.2", + "windows-core 0.57.0", ] [[package]] @@ -5684,7 +6212,7 @@ version = "0.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "fd2ff4c48a8b992baabb09a573db9446bff89e39a193500dd5c8f8196c241c63" dependencies = [ - "bindgen 0.72.1", + "bindgen", "cc", "iceoryx2-pal-concurrency-sync", "iceoryx2-pal-configuration", @@ -5782,6 +6310,12 @@ dependencies = [ "zerovec", ] +[[package]] +name = "id-arena" +version = "2.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3d3067d79b975e8844ca9eb072e16b31c3c1c36928edf9c6789548c524d0d954" + [[package]] name = "ident_case" version = "1.0.1" @@ -5819,6 +6353,31 @@ dependencies = [ "windows-sys 0.59.0", ] +[[package]] +name = "imbl" +version = "7.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e525189e5f603908d0c6e0d402cb5de9c4b2c8866151fabc4ebd771ed2630a2e" +dependencies = [ + "archery 1.2.2", + "bitmaps", + "imbl-sized-chunks", + "rand_core 0.9.3", + "rand_xoshiro", + "serde_core", + "version_check 0.9.5", + "wide", +] + +[[package]] +name = "imbl-sized-chunks" +version = "0.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8f4241005618a62f8d57b2febd02510fb96e0137304728543dfc5fd6f052c22d" +dependencies = [ + "bitmaps", +] + [[package]] name = "impl-codec" version = "0.6.0" @@ -5915,7 +6474,7 @@ dependencies = [ "console", "number_prefix", "portable-atomic", - "unicode-width 0.2.0", + "unicode-width", "web-time", ] @@ -5986,6 +6545,14 @@ dependencies = [ "cfg-if", ] +[[package]] +name = "int_to_bytes" +version = "0.2.0" +source = "git+https://github.com/sigp/lighthouse?rev=27cfa18c17e148fb75827d0ea3c9a2c69db0aae0#27cfa18c17e148fb75827d0ea3c9a2c69db0aae0" +dependencies = [ + "bytes", +] + [[package]] name = "integer-encoding" version = "4.1.0" @@ -6146,10 +6713,12 @@ dependencies = [ [[package]] name = "js-sys" -version = "0.3.83" +version = "0.3.95" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "464a3709c7f55f1f721e5389aa6ea4e3bc6aba669353300af094b29ffbdde1d8" +checksum = "2964e92d1d9dc3364cae4d718d93f227e3abb088e747d92e0395bfdedf1c12ca" dependencies = [ + "cfg-if", + "futures-util", "once_cell", "wasm-bindgen", ] @@ -6228,7 +6797,7 @@ dependencies = [ "pin-project", "rustls 0.23.35", "rustls-pki-types", - "rustls-platform-verifier", + "rustls-platform-verifier 0.5.3", "soketto 0.8.1", "thiserror 2.0.17", "tokio", @@ -6326,7 +6895,7 @@ dependencies = [ "jsonrpsee-core 0.26.0", "jsonrpsee-types 0.26.0", "rustls 0.23.35", - "rustls-platform-verifier", + "rustls-platform-verifier 0.5.3", "serde", "serde_json", "thiserror 2.0.17", @@ -6489,16 +7058,18 @@ dependencies = [ [[package]] name = "jsonwebtoken" -version = "9.3.1" +version = "10.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5a87cc7a48537badeae96744432de36f4be2b4a34a05a5ef32e9dd8a1c169dde" +checksum = "0529410abe238729a60b108898784df8984c87f6054c9c4fcacc47e4803c1ce1" dependencies = [ + "aws-lc-rs", "base64 0.22.1", + "getrandom 0.2.16", "js-sys", "pem", - "ring", "serde", "serde_json", + "signature 2.2.0", "simple_asn1", ] @@ -6529,20 +7100,31 @@ dependencies = [ "signature 2.2.0", ] +[[package]] +name = "kasuari" +version = "0.4.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8fe90c1150662e858c7d5f945089b7517b0a80d8bf7ba4b1b5ffc984e7230a5b" +dependencies = [ + "hashbrown 0.16.1", + "portable-atomic", + "thiserror 2.0.17", +] + [[package]] name = "keccak" version = "0.1.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ecc2af9a1119c51f12a14607e783cb977bde58bc069ff0c3da1095e635d70654" dependencies = [ - "cpufeatures", + "cpufeatures 0.2.17", ] [[package]] name = "keccak-asm" -version = "0.1.4" +version = "0.1.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "505d1856a39b200489082f90d897c3f07c455563880bc5952e38eabf731c83b6" +checksum = "fa468878266ad91431012b3e5ef1bf9b170eab22883503a318d46857afa4579a" dependencies = [ "digest 0.10.7", "sha3-asm", @@ -6568,6 +7150,25 @@ dependencies = [ "libc", ] +[[package]] +name = "kzg" +version = "0.1.0" +source = "git+https://github.com/sigp/lighthouse?rev=27cfa18c17e148fb75827d0ea3c9a2c69db0aae0#27cfa18c17e148fb75827d0ea3c9a2c69db0aae0" +dependencies = [ + "educe", + "ethereum_hashing 0.8.0", + "ethereum_serde_utils 0.8.0", + "ethereum_ssz 0.10.1", + "ethereum_ssz_derive 0.10.1", + "hex", + "rayon", + "rust_eth_kzg", + "serde", + "serde_json", + "tracing", + "tree_hash 0.12.1", +] + [[package]] name = "lazy_static" version = "1.5.0" @@ -6577,6 +7178,12 @@ dependencies = [ "spin 0.9.8", ] +[[package]] +name = "leb128fmt" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "09edd9e8b54e49e587e4f6295a7d29c3ea94d469cb40ab8ca70b288248a81db2" + [[package]] name = "lexical" version = "6.1.1" @@ -6652,9 +7259,9 @@ dependencies = [ [[package]] name = "libc" -version = "0.2.178" +version = "0.2.186" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "37c93d8daa9d8a012fd8ab92f088405fb202ea0b6ab73ee2482ae66af4f42091" +checksum = "68ab91017fe16c622486840e4c83c9a37afeff978bd239b5293d61ece587de66" [[package]] name = "libgit2-sys" @@ -6709,7 +7316,7 @@ version = "0.14.11" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a54ad7278b8bc5301d5ffd2a94251c004feb971feba96c971ea4063645990757" dependencies = [ - "bindgen 0.72.1", + "bindgen", "errno", "libc", ] @@ -6725,6 +7332,22 @@ dependencies = [ "redox_syscall", ] +[[package]] +name = "librocksdb-sys" +version = "0.17.3+10.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cef2a00ee60fe526157c9023edab23943fae1ce2ab6f4abb2a807c1746835de9" +dependencies = [ + "bindgen", + "bzip2-sys", + "cc", + "libc", + "libz-sys", + "lz4-sys", + "tikv-jemalloc-sys", + "zstd-sys", +] + [[package]] name = "libsqlite3-sys" version = "0.27.0" @@ -6736,6 +7359,12 @@ dependencies = [ "vcpkg", ] +[[package]] +name = "libyaml-rs" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2e126dda6f34391ab7b444f9922055facc83c07a910da3eb16f1e4d9c45dc777" + [[package]] name = "libz-sys" version = "1.1.23" @@ -6749,8 +7378,17 @@ dependencies = [ ] [[package]] -name = "linked-hash-map" -version = "0.5.6" +name = "line-clipping" +version = "0.3.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5f4de44e98ddbf09375cbf4d17714d18f39195f4f4894e8524501726fd9a8a4a" +dependencies = [ + "bitflags 2.10.0", +] + +[[package]] +name = "linked-hash-map" +version = "0.5.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0717cef1bc8b636c6e1c1bbdefc09e6322da8a9321966e8928ef80d20f7f770f" @@ -6764,12 +7402,6 @@ dependencies = [ "serde_core", ] -[[package]] -name = "linux-raw-sys" -version = "0.4.15" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d26c52dbd32dccf2d10cac7725f8eae5296885fb5703b261f7d0a0739ec807ab" - [[package]] name = "linux-raw-sys" version = "0.11.0" @@ -6837,11 +7469,11 @@ dependencies = [ [[package]] name = "lru" -version = "0.13.0" +version = "0.16.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "227748d55f2f0ab4735d87fd623798cb6b664512fe979705f829c9f81c934465" +checksum = "a1dc47f592c06f33f8e3aea9591776ec7c9f9e4124778ff8a3c3b87159f7e593" dependencies = [ - "hashbrown 0.15.5", + "hashbrown 0.16.1", ] [[package]] @@ -6878,6 +7510,12 @@ dependencies = [ "twox-hash", ] +[[package]] +name = "lz4_flex" +version = "0.12.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "98c23545df7ecf1b16c303910a69b079e8e251d60f7dd2cc9b4177f2afaf1746" + [[package]] name = "mac" version = "0.1.1" @@ -6920,6 +7558,12 @@ version = "0.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "670fdfda89751bc4a84ac13eaa63e205cf0fd22b4c9a5fbfa085b63c1f1d3a30" +[[package]] +name = "maplit" +version = "1.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3e2e65a1a2e43cfcb47a895c4c8b10d1f4a61097f9f254f183aee60cad9c651d" + [[package]] name = "markup5ever" version = "0.11.0" @@ -6954,6 +7598,12 @@ dependencies = [ "regex-automata", ] +[[package]] +name = "matchit" +version = "0.7.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0e7465ac9959cc2b1404e8e2367b43684a6d13790fe23056cc8c6c5a6b7bcb94" + [[package]] name = "matchit" version = "0.8.4" @@ -7024,6 +7674,40 @@ dependencies = [ "zip", ] +[[package]] +name = "merkle_proof" +version = "0.2.0" +source = "git+https://github.com/sigp/lighthouse?rev=27cfa18c17e148fb75827d0ea3c9a2c69db0aae0#27cfa18c17e148fb75827d0ea3c9a2c69db0aae0" +dependencies = [ + "alloy-primitives 1.5.7", + "ethereum_hashing 0.8.0", + "fixed_bytes", + "safe_arith", +] + +[[package]] +name = "metastruct" +version = "0.1.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "969a1be9bd80794bdf93b23ab552c2ec6f3e83b33164824553fd996cdad513b8" +dependencies = [ + "metastruct_macro", +] + +[[package]] +name = "metastruct_macro" +version = "0.1.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "de9164f767d73a507c19205868c84da411dc7795f4bdabf497d3dd93cfef9930" +dependencies = [ + "darling 0.23.0", + "itertools 0.14.0", + "proc-macro2 1.0.103", + "quote 1.0.42", + "smallvec", + "syn 2.0.111", +] + [[package]] name = "metrics" version = "0.24.3" @@ -7036,28 +7720,27 @@ dependencies = [ [[package]] name = "metrics-derive" -version = "0.1.0" +version = "0.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f3dbdd96ed57d565ec744cba02862d707acf373c5772d152abae6ec5c4e24f6c" +checksum = "161ab904c2c62e7bda0f7562bf22f96440ca35ff79e66c800cbac298f2f4f5ec" dependencies = [ "proc-macro2 1.0.103", "quote 1.0.42", - "regex", "syn 2.0.111", ] [[package]] name = "metrics-exporter-prometheus" -version = "0.16.2" +version = "0.18.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dd7399781913e5393588a8d8c6a2867bf85fb38eaf2502fdce465aad2dc6f034" +checksum = "3589659543c04c7dc5526ec858591015b87cd8746583b51b48ef4353f99dbcda" dependencies = [ "base64 0.22.1", "indexmap 2.12.1", "metrics", "metrics-util", "quanta", - "thiserror 1.0.69", + "thiserror 2.0.17", ] [[package]] @@ -7071,20 +7754,20 @@ dependencies = [ "mach2", "metrics", "once_cell", - "procfs 0.18.0", + "procfs", "rlimit", "windows 0.62.2", ] [[package]] name = "metrics-util" -version = "0.19.1" +version = "0.20.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b8496cc523d1f94c1385dd8f0f0c2c480b2b8aeccb5b7e4485ad6365523ae376" +checksum = "cdfb1365fea27e6dd9dc1dbc19f570198bc86914533ad639dae939635f096be4" dependencies = [ "crossbeam-epoch", "crossbeam-utils", - "hashbrown 0.15.5", + "hashbrown 0.16.1", "metrics", "quanta", "rand 0.9.2", @@ -7119,6 +7802,29 @@ dependencies = [ "tracing", ] +[[package]] +name = "milhouse" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "259dd9da2ae5e0278b95da0b7ecef9c18c309d0a2d9e6db57ed33b9e8910c5e7" +dependencies = [ + "alloy-primitives 1.5.7", + "context_deserialize", + "educe", + "ethereum_hashing 0.8.0", + "ethereum_ssz 0.10.1", + "ethereum_ssz_derive 0.10.1", + "itertools 0.13.0", + "parking_lot", + "rayon", + "serde", + "smallvec", + "tree_hash 0.12.1", + "triomphe", + "typenum", + "vec_map", +] + [[package]] name = "mime" version = "0.3.17" @@ -7135,21 +7841,6 @@ dependencies = [ "unicase", ] -[[package]] -name = "mini-moka" -version = "0.10.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c325dfab65f261f386debee8b0969da215b3fa0037e74c8a1234db7ba986d803" -dependencies = [ - "crossbeam-channel", - "crossbeam-utils", - "dashmap 5.5.3", - "skeptic", - "smallvec", - "tagptr", - "triomphe", -] - [[package]] name = "minimal-lexical" version = "0.2.1" @@ -7168,9 +7859,9 @@ dependencies = [ [[package]] name = "mio" -version = "1.1.0" +version = "1.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "69d83b0086dc8ecf3ce9ae2874b2d1290252e2a30720bea58a5c6639b0092873" +checksum = "50b7e5b27aa02a74bac8c3f23f448f8d87ff11f92d3aac1a6ed369ee08cc56c1" dependencies = [ "libc", "log", @@ -7207,9 +7898,9 @@ dependencies = [ [[package]] name = "modular-bitfield" -version = "0.11.2" +version = "0.13.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a53d79ba8304ac1c4f9eb3b9d281f21f7be9d4626f72ce7df4ad8fbde4f38a74" +checksum = "2956e537fc68236d2aa048f55704f231cc93f1c4de42fe1ecb5bd7938061fc4a" dependencies = [ "modular-bitfield-impl", "static_assertions", @@ -7217,13 +7908,13 @@ dependencies = [ [[package]] name = "modular-bitfield-impl" -version = "0.11.2" +version = "0.13.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5a7d5f7076603ebc68de2dc6a650ec331a062a13abaa346975be747bbfa4b789" +checksum = "59b43b4fd69e3437618106f7754f34021b831a514f9e1a98ae863cabcd8d8dad" dependencies = [ "proc-macro2 1.0.103", "quote 1.0.42", - "syn 1.0.109", + "syn 2.0.111", ] [[package]] @@ -7545,9 +8236,9 @@ dependencies = [ [[package]] name = "num-conv" -version = "0.1.0" +version = "0.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "51d515d32fb182ee37cda2ccdcb92950d6a3c2893aa280e540671c2cd0f3b1d9" +checksum = "c6673768db2d862beb9b39a78fdcb1a69439615d5794a1be50caa9bc92c81967" [[package]] name = "num-integer" @@ -7616,7 +8307,7 @@ version = "0.7.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ff32365de1b6743cb203b710788263c44a03de03802daf96092f2da4fe6ba4d7" dependencies = [ - "proc-macro-crate 3.4.0", + "proc-macro-crate 1.1.3", "proc-macro2 1.0.103", "quote 1.0.42", "syn 2.0.111", @@ -7639,30 +8330,36 @@ checksum = "830b246a0e5f20af87141b25c173cd1b609bd7779a4617d6ec582abaf90870f3" [[package]] name = "nybbles" -version = "0.3.4" +version = "0.4.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8983bb634df7248924ee0c4c3a749609b5abcb082c28fffe3254b3eb3602b307" +checksum = "0d49ff0c0d00d4a502b39df9af3a525e1efeb14b9dabb5bb83335284c1309210" dependencies = [ "alloy-rlp", - "const-hex", + "arbitrary", + "cfg-if", "proptest", + "ruint", "serde", "smallvec", ] [[package]] -name = "nybbles" -version = "0.4.6" +name = "objc2-core-foundation" +version = "0.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2c4b5ecbd0beec843101bffe848217f770e8b8da81d8355b7d6e226f2199b3dc" +checksum = "2a180dd8642fa45cdb7dd721cd4c11b1cadd4929ce112ebd8b9f5803cc79d536" dependencies = [ - "alloy-rlp", - "arbitrary", - "cfg-if", - "proptest", - "ruint", - "serde", - "smallvec", + "bitflags 2.10.0", +] + +[[package]] +name = "objc2-io-kit" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "33fafba39597d6dc1fb709123dfa8289d39406734be322956a69f0931c73bb15" +dependencies = [ + "libc", + "objc2-core-foundation", ] [[package]] @@ -7687,56 +8384,6 @@ version = "11.1.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d6790f58c7ff633d8771f42965289203411a5e5c68388703c06e14f24770b41e" -[[package]] -name = "op-alloy-consensus" -version = "0.22.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "726da827358a547be9f1e37c2a756b9e3729cb0350f43408164794b370cad8ae" -dependencies = [ - "alloy-consensus", - "alloy-eips", - "alloy-primitives 1.4.1", - "alloy-rlp", - "alloy-serde", - "arbitrary", - "derive_more 2.1.0", - "serde", - "serde_with", - "thiserror 2.0.17", -] - -[[package]] -name = "op-alloy-rpc-types-engine" -version = "0.22.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d8f24b8cb66e4b33e6c9e508bf46b8ecafc92eadd0b93fedd306c0accb477657" -dependencies = [ - "alloy-consensus", - "alloy-eips", - "alloy-primitives 1.4.1", - "alloy-rlp", - "alloy-rpc-types-engine", - "alloy-serde", - "derive_more 2.1.0", - "ethereum_ssz 0.9.1", - "ethereum_ssz_derive", - "op-alloy-consensus", - "serde", - "snap", - "thiserror 2.0.17", -] - -[[package]] -name = "op-revm" -version = "12.0.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e31622d03b29c826e48800f4c8f389c8a9c440eb796a3e35203561a288f12985" -dependencies = [ - "auto_impl", - "revm", - "serde", -] - [[package]] name = "opaque-debug" version = "0.3.1" @@ -7826,6 +8473,18 @@ dependencies = [ "tracing", ] +[[package]] +name = "opentelemetry-appender-tracing" +version = "0.31.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ef6a1ac5ca3accf562b8c306fa8483c85f4390f768185ab775f242f7fe8fdcc2" +dependencies = [ + "opentelemetry", + "tracing", + "tracing-core", + "tracing-subscriber 0.3.22", +] + [[package]] name = "opentelemetry-http" version = "0.31.0" @@ -7920,13 +8579,21 @@ dependencies = [ "winapi", ] +[[package]] +name = "pairing" +version = "0.23.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "81fec4625e73cf41ef4bb6846cafa6d44736525f442ba45e407c4a000a13996f" +dependencies = [ + "group 0.13.0", +] + [[package]] name = "parity-scale-codec" version = "3.7.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "799781ae679d79a948e13d4824a40970bfa500058d245760dd857301059810fa" dependencies = [ - "arbitrary", "arrayvec", "bitvec", "byte-slice-cast", @@ -8605,7 +9272,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9d1fe60d06143b2430aa532c94cfe9e29783047f06c0d7fd359a9a51b729fa25" dependencies = [ "cfg-if", - "cpufeatures", + "cpufeatures 0.2.17", "opaque-debug", "universal-hash", ] @@ -8821,40 +9488,17 @@ dependencies = [ "unicode-ident", ] -[[package]] -name = "procfs" -version = "0.17.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cc5b72d8145275d844d4b5f6d4e1eef00c8cd889edb6035c21675d1bb1f45c9f" -dependencies = [ - "bitflags 2.10.0", - "chrono", - "flate2", - "hex", - "procfs-core 0.17.0", - "rustix 0.38.44", -] - [[package]] name = "procfs" version = "0.18.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "25485360a54d6861439d60facef26de713b1e126bf015ec8f98239467a2b82f7" -dependencies = [ - "bitflags 2.10.0", - "procfs-core 0.18.0", - "rustix 1.1.2", -] - -[[package]] -name = "procfs-core" -version = "0.17.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "239df02d8349b06fc07398a3a1697b06418223b1c7725085e801e7c0fc6a12ec" dependencies = [ "bitflags 2.10.0", "chrono", - "hex", + "flate2", + "procfs-core", + "rustix", ] [[package]] @@ -8864,6 +9508,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e6401bf7b6af22f78b563665d15a22e9aef27775b79b149a66ca022468a4e405" dependencies = [ "bitflags 2.10.0", + "chrono", "hex", ] @@ -8913,20 +9558,9 @@ dependencies = [ [[package]] name = "proptest-derive" -version = "0.5.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4ee1c9ac207483d5e7db4940700de86a9aae46ef90c48b57f99fe7edb8345e49" -dependencies = [ - "proc-macro2 1.0.103", - "quote 1.0.42", - "syn 2.0.111", -] - -[[package]] -name = "proptest-derive" -version = "0.6.0" +version = "0.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "095a99f75c69734802359b682be8daaf8980296731f6470434ea2c652af1dd30" +checksum = "fb6dc647500e84a25a85b100e76c85b8ace114c209432dc174f20aac11d4ed6c" dependencies = [ "proc-macro2 1.0.103", "quote 1.0.42", @@ -8959,8 +9593,8 @@ version = "0.13.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "be769465445e8c1474e9c5dac2018218498557af32d9ed057325ec9a41ae81bf" dependencies = [ - "heck 0.5.0", - "itertools 0.14.0", + "heck 0.4.1", + "itertools 0.11.0", "log", "multimap", "once_cell", @@ -8980,7 +9614,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8a56d757972c98b346a9b766e3f02746cde6dd1cd1d1d563472929fdd74bec4d" dependencies = [ "anyhow", - "itertools 0.14.0", + "itertools 0.11.0", "proc-macro2 1.0.103", "quote 1.0.42", "syn 2.0.111", @@ -8993,7 +9627,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9120690fafc389a67ba3803df527d0ec9cbbc9cc45e4cc20b332996dfb672425" dependencies = [ "anyhow", - "itertools 0.14.0", + "itertools 0.11.0", "proc-macro2 1.0.103", "quote 1.0.42", "syn 2.0.111", @@ -9014,17 +9648,6 @@ version = "2.28.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "106dd99e98437432fed6519dedecfade6a06a73bb7b2a1e019fdd2bee5778d94" -[[package]] -name = "pulldown-cmark" -version = "0.9.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "57206b407293d2bcd3af849ce869d52068623f19e1b5ff8e8778e3309439682b" -dependencies = [ - "bitflags 2.10.0", - "memchr", - "unicase", -] - [[package]] name = "quanta" version = "0.12.6" @@ -9080,7 +9703,7 @@ dependencies = [ "quinn-udp", "rustc-hash 2.1.1", "rustls 0.23.35", - "socket2 0.6.1", + "socket2 0.6.3", "thiserror 2.0.17", "tokio", "tracing", @@ -9093,6 +9716,7 @@ version = "0.11.13" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f1906b49b0c3bc04b5fe5d86a77925ae6524a19b816ae38ce1e426255f1d8a31" dependencies = [ + "aws-lc-rs", "bytes", "getrandom 0.3.4", "lru-slab", @@ -9117,7 +9741,7 @@ dependencies = [ "cfg_aliases", "libc", "once_cell", - "socket2 0.6.1", + "socket2 0.6.3", "tracing", "windows-sys 0.60.2", ] @@ -9146,6 +9770,12 @@ version = "5.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "69cdb34c158ceb288df11e18b4bd39de994f6657d83847bdffdbd7f346754b0f" +[[package]] +name = "r-efi" +version = "6.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f8dcc9c7d52a811697d2151c701e0d08956f92b0e24136cf4cf27b57a6a0d9bf" + [[package]] name = "radium" version = "0.7.0" @@ -9371,6 +10001,15 @@ dependencies = [ "rand_core 0.3.1", ] +[[package]] +name = "rand_xorshift" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d25bf25ec5ae4a3f1b92f929810509a2f53d7dca2f50b794ff57e3face536c8f" +dependencies = [ + "rand_core 0.6.4", +] + [[package]] name = "rand_xorshift" version = "0.4.0" @@ -9390,42 +10029,94 @@ dependencies = [ ] [[package]] -name = "ratatui" -version = "0.29.0" +name = "rapidhash" +version = "4.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "eabd94c2f37801c20583fc49dd5cd6b0ba68c716787c2dd6ed18571e1e63117b" +checksum = "b5e48930979c155e2f33aa36ab3119b5ee81332beb6482199a8ecd6029b80b59" dependencies = [ - "bitflags 2.10.0", - "cassowary", - "compact_str", - "crossterm 0.28.1", - "indoc", - "instability", - "itertools 0.13.0", - "lru 0.12.5", - "paste", - "strum 0.26.3", - "unicode-segmentation", - "unicode-truncate", - "unicode-width 0.2.0", + "rand 0.9.2", + "rustversion", ] [[package]] -name = "raw-cpuid" -version = "11.6.0" +name = "ratatui" +version = "0.30.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "498cd0dc59d73224351ee52a95fee0f1a617a2eae0e7d9d720cc622c73a54186" +checksum = "d1ce67fb8ba4446454d1c8dbaeda0557ff5e94d39d5e5ed7f10a65eb4c8266bc" dependencies = [ - "bitflags 2.10.0", + "instability", + "ratatui-core", + "ratatui-crossterm", + "ratatui-widgets", ] [[package]] -name = "rayon" -version = "1.11.0" +name = "ratatui-core" +version = "0.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "368f01d005bf8fd9b1206fb6fa653e6c4a81ceb1466406b81792d87c5677a58f" +checksum = "5ef8dea09a92caaf73bff7adb70b76162e5937524058a7e5bff37869cbbec293" dependencies = [ - "either", + "bitflags 2.10.0", + "compact_str", + "hashbrown 0.16.1", + "indoc", + "itertools 0.14.0", + "kasuari", + "lru 0.16.3", + "strum 0.27.2", + "thiserror 2.0.17", + "unicode-segmentation", + "unicode-truncate", + "unicode-width", +] + +[[package]] +name = "ratatui-crossterm" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "577c9b9f652b4c121fb25c6a391dd06406d3b092ba68827e6d2f09550edc54b3" +dependencies = [ + "cfg-if", + "crossterm", + "instability", + "ratatui-core", +] + +[[package]] +name = "ratatui-widgets" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d7dbfa023cd4e604c2553483820c5fe8aa9d71a42eea5aa77c6e7f35756612db" +dependencies = [ + "bitflags 2.10.0", + "hashbrown 0.16.1", + "indoc", + "instability", + "itertools 0.14.0", + "line-clipping", + "ratatui-core", + "strum 0.27.2", + "time", + "unicode-segmentation", + "unicode-width", +] + +[[package]] +name = "raw-cpuid" +version = "11.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "498cd0dc59d73224351ee52a95fee0f1a617a2eae0e7d9d720cc622c73a54186" +dependencies = [ + "bitflags 2.10.0", +] + +[[package]] +name = "rayon" +version = "1.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "368f01d005bf8fd9b1206fb6fa653e6c4a81ceb1466406b81792d87c5677a58f" +dependencies = [ + "either", "rayon-core", ] @@ -9445,28 +10136,30 @@ version = "0.1.0" dependencies = [ "ahash", "alloy-chains", - "alloy-consensus", - "alloy-eips", + "alloy-consensus 2.0.4", + "alloy-eips 2.0.4", "alloy-evm", - "alloy-json-rpc", + "alloy-json-rpc 2.0.4", "alloy-network", - "alloy-network-primitives", + "alloy-network-primitives 2.0.4", "alloy-node-bindings", - "alloy-primitives 1.4.1", + "alloy-primitives 1.5.7", "alloy-provider", "alloy-rlp", "alloy-rpc-types", "alloy-rpc-types-beacon", "alloy-rpc-types-engine", - "alloy-rpc-types-eth", + "alloy-rpc-types-eth 2.0.4", "alloy-signer-local", - "alloy-trie 0.8.1", + "alloy-trie", "assert_matches", "async-trait", + "axum 0.7.9", "beacon-api-client", "bid-scraper", "bigdecimal 0.4.9", "bincode", + "bls", "built", "clap", "criterion", @@ -9478,7 +10171,7 @@ dependencies = [ "derive_more 2.1.0", "eth-sparse-mpt", "ethereum-consensus", - "ethereum_ssz 0.9.1", + "ethereum_ssz 0.10.1", "exponential-backoff", "eyre", "flate2", @@ -9486,11 +10179,12 @@ dependencies = [ "foldhash 0.1.5", "futures", "governor", + "hex", "itertools 0.11.0", "jsonrpsee 0.20.4", "lazy_static", "lru 0.12.5", - "lz4_flex", + "lz4_flex 0.11.5", "mempool-dumpster", "metrics_macros", "mev-share-sse", @@ -9513,16 +10207,18 @@ dependencies = [ "reth-db", "reth-db-common", "reth-errors", + "reth-ethereum-primitives", "reth-evm", "reth-evm-ethereum", "reth-node-api", "reth-node-core", "reth-node-ethereum", "reth-payload-builder", - "reth-primitives", "reth-primitives-traits", "reth-provider", + "reth-tasks 2.1.0", "reth-trie", + "reth-trie-db", "reth-trie-parallel", "revm", "schnellru", @@ -9533,6 +10229,7 @@ dependencies = [ "sha2 0.10.9", "shellexpand", "sqlx", + "ssz_types 0.14.1", "sysperf", "tempfile", "test_utils", @@ -9545,8 +10242,11 @@ dependencies = [ "toml 0.8.23", "tonic 0.13.1", "tonic-build", + "tower 0.4.13", "tracing", "tracing-subscriber 0.3.22", + "tree_hash 0.12.1", + "types", "url", "uuid", "warp", @@ -9568,7 +10268,7 @@ name = "rbuilder-operator" version = "0.1.0" dependencies = [ "ahash", - "alloy-primitives 1.4.1", + "alloy-primitives 1.5.7", "alloy-rpc-types-beacon", "alloy-signer", "alloy-signer-local", @@ -9617,9 +10317,9 @@ name = "rbuilder-primitives" version = "0.1.0" dependencies = [ "ahash", - "alloy-consensus", - "alloy-eips", - "alloy-primitives 1.4.1", + "alloy-consensus 2.0.4", + "alloy-eips 2.0.4", + "alloy-primitives 1.5.7", "alloy-rlp", "alloy-rpc-types", "alloy-rpc-types-beacon", @@ -9628,8 +10328,8 @@ dependencies = [ "derivative", "derive_more 2.1.0", "ethereum-consensus", - "ethereum_ssz 0.9.1", - "ethereum_ssz_derive", + "ethereum_ssz 0.10.1", + "ethereum_ssz_derive 0.10.1", "eyre", "integer-encoding", "proptest", @@ -9637,7 +10337,6 @@ dependencies = [ "reqwest 0.12.24", "reth-chainspec", "reth-ethereum-primitives", - "reth-primitives", "reth-primitives-traits", "reth-transaction-pool", "revm", @@ -9647,7 +10346,7 @@ dependencies = [ "serde_json", "serde_with", "sha2 0.10.9", - "ssz_types", + "ssz_types 0.8.0", "thiserror 1.0.69", "time", "tracing", @@ -9661,11 +10360,11 @@ dependencies = [ name = "rbuilder-rebalancer" version = "0.1.0" dependencies = [ - "alloy-consensus", - "alloy-eips", - "alloy-primitives 1.4.1", + "alloy-consensus 2.0.4", + "alloy-eips 2.0.4", + "alloy-primitives 1.5.7", "alloy-provider", - "alloy-rpc-types-eth", + "alloy-rpc-types-eth 2.0.4", "alloy-signer", "alloy-signer-local", "clap", @@ -9684,7 +10383,7 @@ dependencies = [ name = "rbuilder-utils" version = "0.1.0" dependencies = [ - "alloy-primitives 1.4.1", + "alloy-primitives 1.5.7", "clickhouse", "derive_more 2.1.0", "rand 0.9.2", @@ -9839,9 +10538,9 @@ name = "reipc" version = "0.1.0" source = "git+https://github.com/nethermindeth/reipc.git?rev=b0b70735cda6273652212d1591188642e3449ed7#b0b70735cda6273652212d1591188642e3449ed7" dependencies = [ - "alloy-json-rpc", - "alloy-primitives 1.4.1", - "alloy-rpc-types-eth", + "alloy-json-rpc 1.8.3", + "alloy-primitives 1.5.7", + "alloy-rpc-types-eth 1.8.3", "bytes", "crossbeam", "dashmap 6.1.0", @@ -9882,7 +10581,7 @@ dependencies = [ "serde_json", "serde_urlencoded", "sync_wrapper 0.1.2", - "system-configuration 0.5.1", + "system-configuration", "tokio", "tokio-native-tls", "tokio-rustls 0.24.1", @@ -9891,7 +10590,7 @@ dependencies = [ "url", "wasm-bindgen", "wasm-bindgen-futures", - "wasm-streams", + "wasm-streams 0.4.2", "web-sys", "webpki-roots 0.25.4", "winreg", @@ -9934,6 +10633,46 @@ dependencies = [ "tokio", "tokio-native-tls", "tokio-rustls 0.26.4", + "tower 0.5.2", + "tower-http", + "tower-service", + "url", + "wasm-bindgen", + "wasm-bindgen-futures", + "web-sys", +] + +[[package]] +name = "reqwest" +version = "0.13.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ab3f43e3283ab1488b624b44b0e988d0acea0b3214e694730a055cb6b2efa801" +dependencies = [ + "base64 0.22.1", + "bytes", + "futures-channel", + "futures-core", + "futures-util", + "http 1.4.0", + "http-body 1.0.1", + "http-body-util", + "hyper 1.8.1", + "hyper-rustls 0.27.7", + "hyper-util", + "js-sys", + "log", + "percent-encoding", + "pin-project-lite", + "quinn", + "rustls 0.23.35", + "rustls-pki-types", + "rustls-platform-verifier 0.6.2", + "serde", + "serde_json", + "serde_urlencoded", + "sync_wrapper 1.0.2", + "tokio", + "tokio-rustls 0.26.4", "tokio-util", "tower 0.5.2", "tower-http", @@ -9941,9 +10680,8 @@ dependencies = [ "url", "wasm-bindgen", "wasm-bindgen-futures", - "wasm-streams", + "wasm-streams 0.5.0", "web-sys", - "webpki-roots 1.0.4", ] [[package]] @@ -9954,13 +10692,13 @@ checksum = "1e061d1b48cb8d38042de4ae0a7a6401009d6143dc80d2e2d6f31f0bdd6470c7" [[package]] name = "reth" -version = "1.9.3" -source = "git+https://github.com/paradigmxyz/reth?rev=27a8c0f5a6dfb27dea84c5751776ecabdd069646#27a8c0f5a6dfb27dea84c5751776ecabdd069646" +version = "2.1.0" +source = "git+https://github.com/paradigmxyz/reth?rev=8ebfaff134a973ea7b89f619a0562882e97b93c7#8ebfaff134a973ea7b89f619a0562882e97b93c7" dependencies = [ + "alloy-primitives 1.5.7", "alloy-rpc-types", "aquamarine", "clap", - "eyre", "reth-chainspec", "reth-cli-runner", "reth-cli-util", @@ -9970,7 +10708,6 @@ dependencies = [ "reth-ethereum-cli", "reth-ethereum-payload-builder", "reth-ethereum-primitives", - "reth-evm", "reth-network", "reth-network-api", "reth-node-api", @@ -9980,10 +10717,8 @@ dependencies = [ "reth-node-metrics", "reth-payload-builder", "reth-payload-primitives", - "reth-primitives", + "reth-primitives-traits", "reth-provider", - "reth-ress-protocol", - "reth-ress-provider", "reth-revm", "reth-rpc", "reth-rpc-api", @@ -9991,45 +10726,46 @@ dependencies = [ "reth-rpc-convert", "reth-rpc-eth-types", "reth-rpc-server-types", - "reth-tasks 1.9.3", - "reth-tokio-util", + "reth-tasks 2.1.0", "reth-transaction-pool", - "tokio", "tracing", ] [[package]] name = "reth-basic-payload-builder" -version = "1.9.3" -source = "git+https://github.com/paradigmxyz/reth?rev=27a8c0f5a6dfb27dea84c5751776ecabdd069646#27a8c0f5a6dfb27dea84c5751776ecabdd069646" +version = "2.1.0" +source = "git+https://github.com/paradigmxyz/reth?rev=8ebfaff134a973ea7b89f619a0562882e97b93c7#8ebfaff134a973ea7b89f619a0562882e97b93c7" dependencies = [ - "alloy-consensus", - "alloy-eips", - "alloy-primitives 1.4.1", + "alloy-consensus 2.0.4", + "alloy-eips 2.0.4", + "alloy-primitives 1.5.7", "futures-core", "futures-util", "metrics", "reth-chain-state", - "reth-metrics 1.9.3", + "reth-execution-cache", + "reth-metrics 2.1.0", "reth-payload-builder", "reth-payload-builder-primitives", "reth-payload-primitives", "reth-primitives-traits", "reth-revm", "reth-storage-api", - "reth-tasks 1.9.3", + "reth-tasks 2.1.0", + "reth-trie-parallel", + "serde", "tokio", "tracing", ] [[package]] name = "reth-chain-state" -version = "1.9.3" -source = "git+https://github.com/paradigmxyz/reth?rev=27a8c0f5a6dfb27dea84c5751776ecabdd069646#27a8c0f5a6dfb27dea84c5751776ecabdd069646" +version = "2.1.0" +source = "git+https://github.com/paradigmxyz/reth?rev=8ebfaff134a973ea7b89f619a0562882e97b93c7#8ebfaff134a973ea7b89f619a0562882e97b93c7" dependencies = [ - "alloy-consensus", - "alloy-eips", - "alloy-primitives 1.4.1", + "alloy-consensus 2.0.4", + "alloy-eips 2.0.4", + "alloy-primitives 1.5.7", "alloy-signer", "alloy-signer-local", "derive_more 2.1.0", @@ -10037,11 +10773,12 @@ dependencies = [ "parking_lot", "pin-project", "rand 0.9.2", + "rayon", "reth-chainspec", "reth-errors", "reth-ethereum-primitives", "reth-execution-types", - "reth-metrics 1.9.3", + "reth-metrics 2.1.0", "reth-primitives-traits", "reth-storage-api", "reth-trie", @@ -10055,16 +10792,16 @@ dependencies = [ [[package]] name = "reth-chainspec" -version = "1.9.3" -source = "git+https://github.com/paradigmxyz/reth?rev=27a8c0f5a6dfb27dea84c5751776ecabdd069646#27a8c0f5a6dfb27dea84c5751776ecabdd069646" +version = "2.1.0" +source = "git+https://github.com/paradigmxyz/reth?rev=8ebfaff134a973ea7b89f619a0562882e97b93c7#8ebfaff134a973ea7b89f619a0562882e97b93c7" dependencies = [ "alloy-chains", - "alloy-consensus", - "alloy-eips", + "alloy-consensus 2.0.4", + "alloy-eips 2.0.4", "alloy-evm", "alloy-genesis", - "alloy-primitives 1.4.1", - "alloy-trie 0.9.1", + "alloy-primitives 1.5.7", + "alloy-trie", "auto_impl", "derive_more 2.1.0", "reth-ethereum-forks", @@ -10075,8 +10812,8 @@ dependencies = [ [[package]] name = "reth-cli" -version = "1.9.3" -source = "git+https://github.com/paradigmxyz/reth?rev=27a8c0f5a6dfb27dea84c5751776ecabdd069646#27a8c0f5a6dfb27dea84c5751776ecabdd069646" +version = "2.1.0" +source = "git+https://github.com/paradigmxyz/reth?rev=8ebfaff134a973ea7b89f619a0562882e97b93c7#8ebfaff134a973ea7b89f619a0562882e97b93c7" dependencies = [ "alloy-genesis", "clap", @@ -10084,23 +10821,23 @@ dependencies = [ "reth-cli-runner", "reth-db", "serde_json", - "shellexpand", ] [[package]] name = "reth-cli-commands" -version = "1.9.3" -source = "git+https://github.com/paradigmxyz/reth?rev=27a8c0f5a6dfb27dea84c5751776ecabdd069646#27a8c0f5a6dfb27dea84c5751776ecabdd069646" +version = "2.1.0" +source = "git+https://github.com/paradigmxyz/reth?rev=8ebfaff134a973ea7b89f619a0562882e97b93c7#8ebfaff134a973ea7b89f619a0562882e97b93c7" dependencies = [ "alloy-chains", - "alloy-consensus", - "alloy-eips", - "alloy-primitives 1.4.1", + "alloy-consensus 2.0.4", + "alloy-eips 2.0.4", + "alloy-primitives 1.5.7", "alloy-rlp", "backon", + "blake3", "clap", "comfy-table", - "crossterm 0.28.1", + "crossterm", "eyre", "fdlimit", "futures", @@ -10108,8 +10845,11 @@ dependencies = [ "humantime", "itertools 0.14.0", "lz4", + "metrics", + "parking_lot", "ratatui", - "reqwest 0.12.24", + "rayon", + "reqwest 0.13.2", "reth-chainspec", "reth-cli", "reth-cli-runner", @@ -10144,12 +10884,15 @@ dependencies = [ "reth-primitives-traits", "reth-provider", "reth-prune", + "reth-prune-types", "reth-revm", "reth-stages", + "reth-stages-types", "reth-static-file", "reth-static-file-types", + "reth-storage-api", + "reth-tasks 2.1.0", "reth-trie", - "reth-trie-common", "reth-trie-db", "secp256k1 0.30.0", "serde", @@ -10157,28 +10900,29 @@ dependencies = [ "tar", "tokio", "tokio-stream", - "toml 0.8.23", + "toml 0.9.8", "tracing", + "url", "zstd 0.13.3", ] [[package]] name = "reth-cli-runner" -version = "1.9.3" -source = "git+https://github.com/paradigmxyz/reth?rev=27a8c0f5a6dfb27dea84c5751776ecabdd069646#27a8c0f5a6dfb27dea84c5751776ecabdd069646" +version = "2.1.0" +source = "git+https://github.com/paradigmxyz/reth?rev=8ebfaff134a973ea7b89f619a0562882e97b93c7#8ebfaff134a973ea7b89f619a0562882e97b93c7" dependencies = [ - "reth-tasks 1.9.3", + "reth-tasks 2.1.0", "tokio", "tracing", ] [[package]] name = "reth-cli-util" -version = "1.9.3" -source = "git+https://github.com/paradigmxyz/reth?rev=27a8c0f5a6dfb27dea84c5751776ecabdd069646#27a8c0f5a6dfb27dea84c5751776ecabdd069646" +version = "2.1.0" +source = "git+https://github.com/paradigmxyz/reth?rev=8ebfaff134a973ea7b89f619a0562882e97b93c7#8ebfaff134a973ea7b89f619a0562882e97b93c7" dependencies = [ - "alloy-eips", - "alloy-primitives 1.4.1", + "alloy-eips 2.0.4", + "alloy-primitives 1.5.7", "cfg-if", "eyre", "libc", @@ -10187,23 +10931,24 @@ dependencies = [ "secp256k1 0.30.0", "serde", "thiserror 2.0.17", + "tikv-jemalloc-sys", "tikv-jemallocator", ] [[package]] name = "reth-codecs" -version = "1.9.3" -source = "git+https://github.com/paradigmxyz/reth?rev=27a8c0f5a6dfb27dea84c5751776ecabdd069646#27a8c0f5a6dfb27dea84c5751776ecabdd069646" +version = "0.3.1" +source = "git+https://github.com/paradigmxyz/reth-core?rev=afa5162668db00749b14bf30d06d3bed5c71aa4c#afa5162668db00749b14bf30d06d3bed5c71aa4c" dependencies = [ - "alloy-consensus", - "alloy-eips", + "alloy-consensus 2.0.4", + "alloy-eips 2.0.4", "alloy-genesis", - "alloy-primitives 1.4.1", - "alloy-trie 0.9.1", + "alloy-primitives 1.5.7", + "alloy-trie", "arbitrary", "bytes", "modular-bitfield", - "op-alloy-consensus", + "parity-scale-codec", "reth-codecs-derive", "reth-zstd-compressors", "serde", @@ -10212,8 +10957,8 @@ dependencies = [ [[package]] name = "reth-codecs-derive" -version = "1.9.3" -source = "git+https://github.com/paradigmxyz/reth?rev=27a8c0f5a6dfb27dea84c5751776ecabdd069646#27a8c0f5a6dfb27dea84c5751776ecabdd069646" +version = "0.3.1" +source = "git+https://github.com/paradigmxyz/reth-core?rev=afa5162668db00749b14bf30d06d3bed5c71aa4c#afa5162668db00749b14bf30d06d3bed5c71aa4c" dependencies = [ "proc-macro2 1.0.103", "quote 1.0.42", @@ -10222,26 +10967,28 @@ dependencies = [ [[package]] name = "reth-config" -version = "1.9.3" -source = "git+https://github.com/paradigmxyz/reth?rev=27a8c0f5a6dfb27dea84c5751776ecabdd069646#27a8c0f5a6dfb27dea84c5751776ecabdd069646" +version = "2.1.0" +source = "git+https://github.com/paradigmxyz/reth?rev=8ebfaff134a973ea7b89f619a0562882e97b93c7#8ebfaff134a973ea7b89f619a0562882e97b93c7" dependencies = [ "eyre", "humantime-serde", "reth-network-types", "reth-prune-types", "reth-stages-types", + "reth-static-file-types", "serde", - "toml 0.8.23", + "toml 0.9.8", "url", ] [[package]] name = "reth-consensus" -version = "1.9.3" -source = "git+https://github.com/paradigmxyz/reth?rev=27a8c0f5a6dfb27dea84c5751776ecabdd069646#27a8c0f5a6dfb27dea84c5751776ecabdd069646" +version = "2.1.0" +source = "git+https://github.com/paradigmxyz/reth?rev=8ebfaff134a973ea7b89f619a0562882e97b93c7#8ebfaff134a973ea7b89f619a0562882e97b93c7" dependencies = [ - "alloy-consensus", - "alloy-primitives 1.4.1", + "alloy-consensus 2.0.4", + "alloy-eip7928", + "alloy-primitives 1.5.7", "auto_impl", "reth-execution-types", "reth-primitives-traits", @@ -10250,11 +10997,12 @@ dependencies = [ [[package]] name = "reth-consensus-common" -version = "1.9.3" -source = "git+https://github.com/paradigmxyz/reth?rev=27a8c0f5a6dfb27dea84c5751776ecabdd069646#27a8c0f5a6dfb27dea84c5751776ecabdd069646" +version = "2.1.0" +source = "git+https://github.com/paradigmxyz/reth?rev=8ebfaff134a973ea7b89f619a0562882e97b93c7#8ebfaff134a973ea7b89f619a0562882e97b93c7" dependencies = [ - "alloy-consensus", - "alloy-eips", + "alloy-consensus 2.0.4", + "alloy-eips 2.0.4", + "alloy-primitives 1.5.7", "reth-chainspec", "reth-consensus", "reth-primitives-traits", @@ -10262,13 +11010,13 @@ dependencies = [ [[package]] name = "reth-consensus-debug-client" -version = "1.9.3" -source = "git+https://github.com/paradigmxyz/reth?rev=27a8c0f5a6dfb27dea84c5751776ecabdd069646#27a8c0f5a6dfb27dea84c5751776ecabdd069646" +version = "2.1.0" +source = "git+https://github.com/paradigmxyz/reth?rev=8ebfaff134a973ea7b89f619a0562882e97b93c7#8ebfaff134a973ea7b89f619a0562882e97b93c7" dependencies = [ - "alloy-consensus", - "alloy-eips", - "alloy-json-rpc", - "alloy-primitives 1.4.1", + "alloy-consensus 2.0.4", + "alloy-eips 2.0.4", + "alloy-json-rpc 2.0.4", + "alloy-primitives 1.5.7", "alloy-provider", "alloy-rpc-types-engine", "alloy-transport", @@ -10276,7 +11024,7 @@ dependencies = [ "derive_more 2.1.0", "eyre", "futures", - "reqwest 0.12.24", + "reqwest 0.13.2", "reth-node-api", "reth-primitives-traits", "reth-tracing", @@ -10288,49 +11036,50 @@ dependencies = [ [[package]] name = "reth-db" -version = "1.9.3" -source = "git+https://github.com/paradigmxyz/reth?rev=27a8c0f5a6dfb27dea84c5751776ecabdd069646#27a8c0f5a6dfb27dea84c5751776ecabdd069646" +version = "2.1.0" +source = "git+https://github.com/paradigmxyz/reth?rev=8ebfaff134a973ea7b89f619a0562882e97b93c7#8ebfaff134a973ea7b89f619a0562882e97b93c7" dependencies = [ - "alloy-primitives 1.4.1", + "alloy-primitives 1.5.7", "derive_more 2.1.0", "eyre", + "libc", "metrics", "page_size", "parking_lot", + "quanta", "reth-db-api", "reth-fs-util", "reth-libmdbx", - "reth-metrics 1.9.3", + "reth-metrics 2.1.0", "reth-nippy-jar", "reth-static-file-types", "reth-storage-errors", "reth-tracing", "rustc-hash 2.1.1", "strum 0.27.2", - "sysinfo 0.33.1", + "sysinfo 0.38.4", "tempfile", "thiserror 2.0.17", + "tracing", ] [[package]] name = "reth-db-api" -version = "1.9.3" -source = "git+https://github.com/paradigmxyz/reth?rev=27a8c0f5a6dfb27dea84c5751776ecabdd069646#27a8c0f5a6dfb27dea84c5751776ecabdd069646" +version = "2.1.0" +source = "git+https://github.com/paradigmxyz/reth?rev=8ebfaff134a973ea7b89f619a0562882e97b93c7#8ebfaff134a973ea7b89f619a0562882e97b93c7" dependencies = [ - "alloy-consensus", - "alloy-genesis", - "alloy-primitives 1.4.1", + "alloy-consensus 2.0.4", + "alloy-primitives 1.5.7", "arbitrary", + "arrayvec", "bytes", "derive_more 2.1.0", "metrics", "modular-bitfield", - "parity-scale-codec", "proptest", "reth-codecs", "reth-db-models", "reth-ethereum-primitives", - "reth-optimism-primitives", "reth-primitives-traits", "reth-prune-types", "reth-stages-types", @@ -10342,12 +11091,12 @@ dependencies = [ [[package]] name = "reth-db-common" -version = "1.9.3" -source = "git+https://github.com/paradigmxyz/reth?rev=27a8c0f5a6dfb27dea84c5751776ecabdd069646#27a8c0f5a6dfb27dea84c5751776ecabdd069646" +version = "2.1.0" +source = "git+https://github.com/paradigmxyz/reth?rev=8ebfaff134a973ea7b89f619a0562882e97b93c7#8ebfaff134a973ea7b89f619a0562882e97b93c7" dependencies = [ - "alloy-consensus", + "alloy-consensus 2.0.4", "alloy-genesis", - "alloy-primitives 1.4.1", + "alloy-primitives 1.5.7", "boyer-moore-magiclen", "eyre", "reth-chainspec", @@ -10372,11 +11121,11 @@ dependencies = [ [[package]] name = "reth-db-models" -version = "1.9.3" -source = "git+https://github.com/paradigmxyz/reth?rev=27a8c0f5a6dfb27dea84c5751776ecabdd069646#27a8c0f5a6dfb27dea84c5751776ecabdd069646" +version = "2.1.0" +source = "git+https://github.com/paradigmxyz/reth?rev=8ebfaff134a973ea7b89f619a0562882e97b93c7#8ebfaff134a973ea7b89f619a0562882e97b93c7" dependencies = [ - "alloy-eips", - "alloy-primitives 1.4.1", + "alloy-eips 2.0.4", + "alloy-primitives 1.5.7", "arbitrary", "bytes", "modular-bitfield", @@ -10387,10 +11136,10 @@ dependencies = [ [[package]] name = "reth-discv4" -version = "1.9.3" -source = "git+https://github.com/paradigmxyz/reth?rev=27a8c0f5a6dfb27dea84c5751776ecabdd069646#27a8c0f5a6dfb27dea84c5751776ecabdd069646" +version = "2.1.0" +source = "git+https://github.com/paradigmxyz/reth?rev=8ebfaff134a973ea7b89f619a0562882e97b93c7#8ebfaff134a973ea7b89f619a0562882e97b93c7" dependencies = [ - "alloy-primitives 1.4.1", + "alloy-primitives 1.5.7", "alloy-rlp", "discv5", "enr 0.13.0", @@ -10412,10 +11161,10 @@ dependencies = [ [[package]] name = "reth-discv5" -version = "1.9.3" -source = "git+https://github.com/paradigmxyz/reth?rev=27a8c0f5a6dfb27dea84c5751776ecabdd069646#27a8c0f5a6dfb27dea84c5751776ecabdd069646" +version = "2.1.0" +source = "git+https://github.com/paradigmxyz/reth?rev=8ebfaff134a973ea7b89f619a0562882e97b93c7#8ebfaff134a973ea7b89f619a0562882e97b93c7" dependencies = [ - "alloy-primitives 1.4.1", + "alloy-primitives 1.5.7", "alloy-rlp", "derive_more 2.1.0", "discv5", @@ -10426,7 +11175,7 @@ dependencies = [ "rand 0.9.2", "reth-chainspec", "reth-ethereum-forks", - "reth-metrics 1.9.3", + "reth-metrics 2.1.0", "reth-network-peers", "secp256k1 0.30.0", "thiserror 2.0.17", @@ -10436,15 +11185,15 @@ dependencies = [ [[package]] name = "reth-dns-discovery" -version = "1.9.3" -source = "git+https://github.com/paradigmxyz/reth?rev=27a8c0f5a6dfb27dea84c5751776ecabdd069646#27a8c0f5a6dfb27dea84c5751776ecabdd069646" +version = "2.1.0" +source = "git+https://github.com/paradigmxyz/reth?rev=8ebfaff134a973ea7b89f619a0562882e97b93c7#8ebfaff134a973ea7b89f619a0562882e97b93c7" dependencies = [ - "alloy-primitives 1.4.1", + "alloy-primitives 1.5.7", + "dashmap 6.1.0", "data-encoding", "enr 0.13.0", "hickory-resolver", "linked_hash_set", - "parking_lot", "reth-ethereum-forks", "reth-network-peers", "reth-tokio-util", @@ -10460,12 +11209,12 @@ dependencies = [ [[package]] name = "reth-downloaders" -version = "1.9.3" -source = "git+https://github.com/paradigmxyz/reth?rev=27a8c0f5a6dfb27dea84c5751776ecabdd069646#27a8c0f5a6dfb27dea84c5751776ecabdd069646" +version = "2.1.0" +source = "git+https://github.com/paradigmxyz/reth?rev=8ebfaff134a973ea7b89f619a0562882e97b93c7#8ebfaff134a973ea7b89f619a0562882e97b93c7" dependencies = [ - "alloy-consensus", - "alloy-eips", - "alloy-primitives 1.4.1", + "alloy-consensus 2.0.4", + "alloy-eips 2.0.4", + "alloy-primitives 1.5.7", "alloy-rlp", "async-compression", "futures", @@ -10476,12 +11225,12 @@ dependencies = [ "rayon", "reth-config", "reth-consensus", - "reth-metrics 1.9.3", + "reth-metrics 2.1.0", "reth-network-p2p", "reth-network-peers", "reth-primitives-traits", "reth-storage-api", - "reth-tasks 1.9.3", + "reth-tasks 2.1.0", "thiserror 2.0.17", "tokio", "tokio-stream", @@ -10491,11 +11240,11 @@ dependencies = [ [[package]] name = "reth-ecies" -version = "1.9.3" -source = "git+https://github.com/paradigmxyz/reth?rev=27a8c0f5a6dfb27dea84c5751776ecabdd069646#27a8c0f5a6dfb27dea84c5751776ecabdd069646" +version = "2.1.0" +source = "git+https://github.com/paradigmxyz/reth?rev=8ebfaff134a973ea7b89f619a0562882e97b93c7#8ebfaff134a973ea7b89f619a0562882e97b93c7" dependencies = [ "aes", - "alloy-primitives 1.4.1", + "alloy-primitives 1.5.7", "alloy-rlp", "block-padding", "byteorder", @@ -10504,29 +11253,26 @@ dependencies = [ "ctr", "digest 0.10.7", "futures", - "generic-array", "hmac", "pin-project", "rand 0.8.5", "reth-network-peers", "secp256k1 0.30.0", "sha2 0.10.9", - "sha3", "thiserror 2.0.17", "tokio", "tokio-stream", "tokio-util", "tracing", - "typenum", ] [[package]] name = "reth-engine-local" -version = "1.9.3" -source = "git+https://github.com/paradigmxyz/reth?rev=27a8c0f5a6dfb27dea84c5751776ecabdd069646#27a8c0f5a6dfb27dea84c5751776ecabdd069646" +version = "2.1.0" +source = "git+https://github.com/paradigmxyz/reth?rev=8ebfaff134a973ea7b89f619a0562882e97b93c7#8ebfaff134a973ea7b89f619a0562882e97b93c7" dependencies = [ - "alloy-consensus", - "alloy-primitives 1.4.1", + "alloy-consensus 2.0.4", + "alloy-primitives 1.5.7", "alloy-rpc-types-engine", "eyre", "futures-util", @@ -10535,6 +11281,7 @@ dependencies = [ "reth-ethereum-engine-primitives", "reth-payload-builder", "reth-payload-primitives", + "reth-primitives-traits", "reth-storage-api", "reth-transaction-pool", "tokio", @@ -10544,12 +11291,12 @@ dependencies = [ [[package]] name = "reth-engine-primitives" -version = "1.9.3" -source = "git+https://github.com/paradigmxyz/reth?rev=27a8c0f5a6dfb27dea84c5751776ecabdd069646#27a8c0f5a6dfb27dea84c5751776ecabdd069646" +version = "2.1.0" +source = "git+https://github.com/paradigmxyz/reth?rev=8ebfaff134a973ea7b89f619a0562882e97b93c7#8ebfaff134a973ea7b89f619a0562882e97b93c7" dependencies = [ - "alloy-consensus", - "alloy-eips", - "alloy-primitives 1.4.1", + "alloy-consensus 2.0.4", + "alloy-eips 2.0.4", + "alloy-primitives 1.5.7", "alloy-rpc-types-engine", "auto_impl", "futures", @@ -10567,45 +11314,24 @@ dependencies = [ "tokio", ] -[[package]] -name = "reth-engine-service" -version = "1.9.3" -source = "git+https://github.com/paradigmxyz/reth?rev=27a8c0f5a6dfb27dea84c5751776ecabdd069646#27a8c0f5a6dfb27dea84c5751776ecabdd069646" -dependencies = [ - "futures", - "pin-project", - "reth-chainspec", - "reth-consensus", - "reth-engine-primitives", - "reth-engine-tree", - "reth-ethereum-primitives", - "reth-evm", - "reth-network-p2p", - "reth-node-types", - "reth-payload-builder", - "reth-provider", - "reth-prune", - "reth-stages-api", - "reth-tasks 1.9.3", -] - [[package]] name = "reth-engine-tree" -version = "1.9.3" -source = "git+https://github.com/paradigmxyz/reth?rev=27a8c0f5a6dfb27dea84c5751776ecabdd069646#27a8c0f5a6dfb27dea84c5751776ecabdd069646" +version = "2.1.0" +source = "git+https://github.com/paradigmxyz/reth?rev=8ebfaff134a973ea7b89f619a0562882e97b93c7#8ebfaff134a973ea7b89f619a0562882e97b93c7" dependencies = [ - "alloy-consensus", - "alloy-eips", + "alloy-consensus 2.0.4", + "alloy-eip7928", + "alloy-eips 2.0.4", "alloy-evm", - "alloy-primitives 1.4.1", + "alloy-primitives 1.5.7", "alloy-rlp", "alloy-rpc-types-engine", "crossbeam-channel", - "dashmap 6.1.0", "derive_more 2.1.0", "futures", + "indexmap 2.12.1", "metrics", - "mini-moka", + "moka", "parking_lot", "rayon", "reth-chain-state", @@ -10615,8 +11341,9 @@ dependencies = [ "reth-errors", "reth-ethereum-primitives", "reth-evm", + "reth-execution-cache", "reth-execution-types", - "reth-metrics 1.9.3", + "reth-metrics 2.1.0", "reth-network-p2p", "reth-payload-builder", "reth-payload-primitives", @@ -10625,15 +11352,15 @@ dependencies = [ "reth-prune", "reth-revm", "reth-stages-api", - "reth-tasks 1.9.3", + "reth-tasks 2.1.0", "reth-trie", + "reth-trie-common", + "reth-trie-db", "reth-trie-parallel", "reth-trie-sparse", - "reth-trie-sparse-parallel", "revm", "revm-primitives", "schnellru", - "smallvec", "thiserror 2.0.17", "tokio", "tracing", @@ -10641,10 +11368,10 @@ dependencies = [ [[package]] name = "reth-engine-util" -version = "1.9.3" -source = "git+https://github.com/paradigmxyz/reth?rev=27a8c0f5a6dfb27dea84c5751776ecabdd069646#27a8c0f5a6dfb27dea84c5751776ecabdd069646" +version = "2.1.0" +source = "git+https://github.com/paradigmxyz/reth?rev=8ebfaff134a973ea7b89f619a0562882e97b93c7#8ebfaff134a973ea7b89f619a0562882e97b93c7" dependencies = [ - "alloy-consensus", + "alloy-consensus 2.0.4", "alloy-rpc-types-engine", "eyre", "futures", @@ -10669,30 +11396,31 @@ dependencies = [ [[package]] name = "reth-era" -version = "1.9.3" -source = "git+https://github.com/paradigmxyz/reth?rev=27a8c0f5a6dfb27dea84c5751776ecabdd069646#27a8c0f5a6dfb27dea84c5751776ecabdd069646" +version = "2.1.0" +source = "git+https://github.com/paradigmxyz/reth?rev=8ebfaff134a973ea7b89f619a0562882e97b93c7#8ebfaff134a973ea7b89f619a0562882e97b93c7" dependencies = [ - "alloy-consensus", - "alloy-eips", - "alloy-primitives 1.4.1", + "alloy-consensus 2.0.4", + "alloy-eips 2.0.4", + "alloy-primitives 1.5.7", "alloy-rlp", - "ethereum_ssz 0.9.1", - "ethereum_ssz_derive", - "reth-ethereum-primitives", + "ethereum_ssz 0.10.1", + "ethereum_ssz_derive 0.10.1", + "sha2 0.10.9", "snap", "thiserror 2.0.17", ] [[package]] name = "reth-era-downloader" -version = "1.9.3" -source = "git+https://github.com/paradigmxyz/reth?rev=27a8c0f5a6dfb27dea84c5751776ecabdd069646#27a8c0f5a6dfb27dea84c5751776ecabdd069646" +version = "2.1.0" +source = "git+https://github.com/paradigmxyz/reth?rev=8ebfaff134a973ea7b89f619a0562882e97b93c7#8ebfaff134a973ea7b89f619a0562882e97b93c7" dependencies = [ - "alloy-primitives 1.4.1", + "alloy-primitives 1.5.7", "bytes", "eyre", "futures-util", - "reqwest 0.12.24", + "reqwest 0.13.2", + "reth-era", "reth-fs-util", "sha2 0.10.9", "tokio", @@ -10700,11 +11428,11 @@ dependencies = [ [[package]] name = "reth-era-utils" -version = "1.9.3" -source = "git+https://github.com/paradigmxyz/reth?rev=27a8c0f5a6dfb27dea84c5751776ecabdd069646#27a8c0f5a6dfb27dea84c5751776ecabdd069646" +version = "2.1.0" +source = "git+https://github.com/paradigmxyz/reth?rev=8ebfaff134a973ea7b89f619a0562882e97b93c7#8ebfaff134a973ea7b89f619a0562882e97b93c7" dependencies = [ - "alloy-consensus", - "alloy-primitives 1.4.1", + "alloy-consensus 2.0.4", + "alloy-primitives 1.5.7", "eyre", "futures-util", "reth-db-api", @@ -10722,8 +11450,8 @@ dependencies = [ [[package]] name = "reth-errors" -version = "1.9.3" -source = "git+https://github.com/paradigmxyz/reth?rev=27a8c0f5a6dfb27dea84c5751776ecabdd069646#27a8c0f5a6dfb27dea84c5751776ecabdd069646" +version = "2.1.0" +source = "git+https://github.com/paradigmxyz/reth?rev=8ebfaff134a973ea7b89f619a0562882e97b93c7#8ebfaff134a973ea7b89f619a0562882e97b93c7" dependencies = [ "reth-consensus", "reth-execution-errors", @@ -10733,11 +11461,11 @@ dependencies = [ [[package]] name = "reth-eth-wire" -version = "1.9.3" -source = "git+https://github.com/paradigmxyz/reth?rev=27a8c0f5a6dfb27dea84c5751776ecabdd069646#27a8c0f5a6dfb27dea84c5751776ecabdd069646" +version = "2.1.0" +source = "git+https://github.com/paradigmxyz/reth?rev=8ebfaff134a973ea7b89f619a0562882e97b93c7#8ebfaff134a973ea7b89f619a0562882e97b93c7" dependencies = [ "alloy-chains", - "alloy-primitives 1.4.1", + "alloy-primitives 1.5.7", "alloy-rlp", "bytes", "derive_more 2.1.0", @@ -10747,7 +11475,7 @@ dependencies = [ "reth-ecies", "reth-eth-wire-types", "reth-ethereum-forks", - "reth-metrics 1.9.3", + "reth-metrics 2.1.0", "reth-network-peers", "reth-primitives-traits", "serde", @@ -10761,14 +11489,15 @@ dependencies = [ [[package]] name = "reth-eth-wire-types" -version = "1.9.3" -source = "git+https://github.com/paradigmxyz/reth?rev=27a8c0f5a6dfb27dea84c5751776ecabdd069646#27a8c0f5a6dfb27dea84c5751776ecabdd069646" +version = "2.1.0" +source = "git+https://github.com/paradigmxyz/reth?rev=8ebfaff134a973ea7b89f619a0562882e97b93c7#8ebfaff134a973ea7b89f619a0562882e97b93c7" dependencies = [ "alloy-chains", - "alloy-consensus", - "alloy-eips", - "alloy-hardforks 0.4.4", - "alloy-primitives 1.4.1", + "alloy-consensus 2.0.4", + "alloy-eip7928", + "alloy-eips 2.0.4", + "alloy-hardforks 0.4.7", + "alloy-primitives 1.5.7", "alloy-rlp", "bytes", "derive_more 2.1.0", @@ -10782,8 +11511,8 @@ dependencies = [ [[package]] name = "reth-ethereum-cli" -version = "1.9.3" -source = "git+https://github.com/paradigmxyz/reth?rev=27a8c0f5a6dfb27dea84c5751776ecabdd069646#27a8c0f5a6dfb27dea84c5751776ecabdd069646" +version = "2.1.0" +source = "git+https://github.com/paradigmxyz/reth?rev=8ebfaff134a973ea7b89f619a0562882e97b93c7#8ebfaff134a973ea7b89f619a0562882e97b93c7" dependencies = [ "clap", "eyre", @@ -10798,20 +11527,19 @@ dependencies = [ "reth-node-ethereum", "reth-node-metrics", "reth-rpc-server-types", + "reth-tasks 2.1.0", "reth-tracing", - "reth-tracing-otlp", "tracing", - "url", ] [[package]] name = "reth-ethereum-consensus" -version = "1.9.3" -source = "git+https://github.com/paradigmxyz/reth?rev=27a8c0f5a6dfb27dea84c5751776ecabdd069646#27a8c0f5a6dfb27dea84c5751776ecabdd069646" +version = "2.1.0" +source = "git+https://github.com/paradigmxyz/reth?rev=8ebfaff134a973ea7b89f619a0562882e97b93c7#8ebfaff134a973ea7b89f619a0562882e97b93c7" dependencies = [ - "alloy-consensus", - "alloy-eips", - "alloy-primitives 1.4.1", + "alloy-consensus 2.0.4", + "alloy-eips 2.0.4", + "alloy-primitives 1.5.7", "reth-chainspec", "reth-consensus", "reth-consensus-common", @@ -10822,30 +11550,28 @@ dependencies = [ [[package]] name = "reth-ethereum-engine-primitives" -version = "1.9.3" -source = "git+https://github.com/paradigmxyz/reth?rev=27a8c0f5a6dfb27dea84c5751776ecabdd069646#27a8c0f5a6dfb27dea84c5751776ecabdd069646" +version = "2.1.0" +source = "git+https://github.com/paradigmxyz/reth?rev=8ebfaff134a973ea7b89f619a0562882e97b93c7#8ebfaff134a973ea7b89f619a0562882e97b93c7" dependencies = [ - "alloy-eips", - "alloy-primitives 1.4.1", - "alloy-rlp", + "alloy-eips 2.0.4", + "alloy-primitives 1.5.7", "alloy-rpc-types-engine", "reth-engine-primitives", "reth-ethereum-primitives", "reth-payload-primitives", "reth-primitives-traits", "serde", - "sha2 0.10.9", "thiserror 2.0.17", ] [[package]] name = "reth-ethereum-forks" -version = "1.9.3" -source = "git+https://github.com/paradigmxyz/reth?rev=27a8c0f5a6dfb27dea84c5751776ecabdd069646#27a8c0f5a6dfb27dea84c5751776ecabdd069646" +version = "2.1.0" +source = "git+https://github.com/paradigmxyz/reth?rev=8ebfaff134a973ea7b89f619a0562882e97b93c7#8ebfaff134a973ea7b89f619a0562882e97b93c7" dependencies = [ "alloy-eip2124", - "alloy-hardforks 0.4.4", - "alloy-primitives 1.4.1", + "alloy-hardforks 0.4.7", + "alloy-primitives 1.5.7", "auto_impl", "once_cell", "rustc-hash 2.1.1", @@ -10853,12 +11579,12 @@ dependencies = [ [[package]] name = "reth-ethereum-payload-builder" -version = "1.9.3" -source = "git+https://github.com/paradigmxyz/reth?rev=27a8c0f5a6dfb27dea84c5751776ecabdd069646#27a8c0f5a6dfb27dea84c5751776ecabdd069646" +version = "2.1.0" +source = "git+https://github.com/paradigmxyz/reth?rev=8ebfaff134a973ea7b89f619a0562882e97b93c7#8ebfaff134a973ea7b89f619a0562882e97b93c7" dependencies = [ - "alloy-consensus", - "alloy-eips", - "alloy-primitives 1.4.1", + "alloy-consensus 2.0.4", + "alloy-eips 2.0.4", + "alloy-primitives 1.5.7", "alloy-rlp", "alloy-rpc-types-engine", "reth-basic-payload-builder", @@ -10868,6 +11594,7 @@ dependencies = [ "reth-ethereum-primitives", "reth-evm", "reth-evm-ethereum", + "reth-execution-cache", "reth-payload-builder", "reth-payload-builder-primitives", "reth-payload-primitives", @@ -10882,28 +11609,22 @@ dependencies = [ [[package]] name = "reth-ethereum-primitives" -version = "1.9.3" -source = "git+https://github.com/paradigmxyz/reth?rev=27a8c0f5a6dfb27dea84c5751776ecabdd069646#27a8c0f5a6dfb27dea84c5751776ecabdd069646" +version = "2.1.0" +source = "git+https://github.com/paradigmxyz/reth?rev=8ebfaff134a973ea7b89f619a0562882e97b93c7#8ebfaff134a973ea7b89f619a0562882e97b93c7" dependencies = [ - "alloy-consensus", - "alloy-eips", - "alloy-primitives 1.4.1", - "alloy-rlp", - "alloy-rpc-types-eth", - "alloy-serde", - "arbitrary", - "modular-bitfield", + "alloy-consensus 2.0.4", + "alloy-eips 2.0.4", + "alloy-primitives 1.5.7", + "alloy-rpc-types-eth 2.0.4", "reth-codecs", "reth-primitives-traits", - "reth-zstd-compressors", "serde", - "serde_with", ] [[package]] name = "reth-etl" -version = "1.9.3" -source = "git+https://github.com/paradigmxyz/reth?rev=27a8c0f5a6dfb27dea84c5751776ecabdd069646#27a8c0f5a6dfb27dea84c5751776ecabdd069646" +version = "2.1.0" +source = "git+https://github.com/paradigmxyz/reth?rev=8ebfaff134a973ea7b89f619a0562882e97b93c7#8ebfaff134a973ea7b89f619a0562882e97b93c7" dependencies = [ "rayon", "reth-db-api", @@ -10912,20 +11633,21 @@ dependencies = [ [[package]] name = "reth-evm" -version = "1.9.3" -source = "git+https://github.com/paradigmxyz/reth?rev=27a8c0f5a6dfb27dea84c5751776ecabdd069646#27a8c0f5a6dfb27dea84c5751776ecabdd069646" +version = "2.1.0" +source = "git+https://github.com/paradigmxyz/reth?rev=8ebfaff134a973ea7b89f619a0562882e97b93c7#8ebfaff134a973ea7b89f619a0562882e97b93c7" dependencies = [ - "alloy-consensus", - "alloy-eips", + "alloy-consensus 2.0.4", + "alloy-eips 2.0.4", "alloy-evm", - "alloy-primitives 1.4.1", + "alloy-primitives 1.5.7", "auto_impl", "derive_more 2.1.0", "futures-util", "metrics", + "rayon", "reth-execution-errors", "reth-execution-types", - "reth-metrics 1.9.3", + "reth-metrics 2.1.0", "reth-primitives-traits", "reth-storage-api", "reth-storage-errors", @@ -10935,15 +11657,14 @@ dependencies = [ [[package]] name = "reth-evm-ethereum" -version = "1.9.3" -source = "git+https://github.com/paradigmxyz/reth?rev=27a8c0f5a6dfb27dea84c5751776ecabdd069646#27a8c0f5a6dfb27dea84c5751776ecabdd069646" +version = "2.1.0" +source = "git+https://github.com/paradigmxyz/reth?rev=8ebfaff134a973ea7b89f619a0562882e97b93c7#8ebfaff134a973ea7b89f619a0562882e97b93c7" dependencies = [ - "alloy-consensus", - "alloy-eips", + "alloy-consensus 2.0.4", + "alloy-eips 2.0.4", "alloy-evm", - "alloy-primitives 1.4.1", + "alloy-primitives 1.5.7", "alloy-rpc-types-engine", - "derive_more 2.1.0", "reth-chainspec", "reth-ethereum-forks", "reth-ethereum-primitives", @@ -10954,28 +11675,47 @@ dependencies = [ "revm", ] +[[package]] +name = "reth-execution-cache" +version = "2.1.0" +source = "git+https://github.com/paradigmxyz/reth?rev=8ebfaff134a973ea7b89f619a0562882e97b93c7#8ebfaff134a973ea7b89f619a0562882e97b93c7" +dependencies = [ + "alloy-primitives 1.5.7", + "fixed-cache", + "metrics", + "parking_lot", + "reth-errors", + "reth-metrics 2.1.0", + "reth-primitives-traits", + "reth-provider", + "reth-revm", + "reth-trie", + "tracing", +] + [[package]] name = "reth-execution-errors" -version = "1.9.3" -source = "git+https://github.com/paradigmxyz/reth?rev=27a8c0f5a6dfb27dea84c5751776ecabdd069646#27a8c0f5a6dfb27dea84c5751776ecabdd069646" +version = "2.1.0" +source = "git+https://github.com/paradigmxyz/reth?rev=8ebfaff134a973ea7b89f619a0562882e97b93c7#8ebfaff134a973ea7b89f619a0562882e97b93c7" dependencies = [ "alloy-evm", - "alloy-primitives 1.4.1", + "alloy-primitives 1.5.7", "alloy-rlp", - "nybbles 0.4.6", + "nybbles", "reth-storage-errors", "thiserror 2.0.17", ] [[package]] name = "reth-execution-types" -version = "1.9.3" -source = "git+https://github.com/paradigmxyz/reth?rev=27a8c0f5a6dfb27dea84c5751776ecabdd069646#27a8c0f5a6dfb27dea84c5751776ecabdd069646" +version = "2.1.0" +source = "git+https://github.com/paradigmxyz/reth?rev=8ebfaff134a973ea7b89f619a0562882e97b93c7#8ebfaff134a973ea7b89f619a0562882e97b93c7" dependencies = [ - "alloy-consensus", - "alloy-eips", + "alloy-consensus 2.0.4", + "alloy-eips 2.0.4", "alloy-evm", - "alloy-primitives 1.4.1", + "alloy-primitives 1.5.7", + "alloy-rlp", "derive_more 2.1.0", "reth-ethereum-primitives", "reth-primitives-traits", @@ -10987,12 +11727,12 @@ dependencies = [ [[package]] name = "reth-exex" -version = "1.9.3" -source = "git+https://github.com/paradigmxyz/reth?rev=27a8c0f5a6dfb27dea84c5751776ecabdd069646#27a8c0f5a6dfb27dea84c5751776ecabdd069646" +version = "2.1.0" +source = "git+https://github.com/paradigmxyz/reth?rev=8ebfaff134a973ea7b89f619a0562882e97b93c7#8ebfaff134a973ea7b89f619a0562882e97b93c7" dependencies = [ - "alloy-consensus", - "alloy-eips", - "alloy-primitives 1.4.1", + "alloy-consensus 2.0.4", + "alloy-eips 2.0.4", + "alloy-primitives 1.5.7", "eyre", "futures", "itertools 0.14.0", @@ -11005,7 +11745,7 @@ dependencies = [ "reth-evm", "reth-exex-types", "reth-fs-util", - "reth-metrics 1.9.3", + "reth-metrics 2.1.0", "reth-node-api", "reth-node-core", "reth-payload-builder", @@ -11014,7 +11754,7 @@ dependencies = [ "reth-prune-types", "reth-revm", "reth-stages-api", - "reth-tasks 1.9.3", + "reth-tasks 2.1.0", "reth-tracing", "rmp-serde", "thiserror 2.0.17", @@ -11025,11 +11765,11 @@ dependencies = [ [[package]] name = "reth-exex-types" -version = "1.9.3" -source = "git+https://github.com/paradigmxyz/reth?rev=27a8c0f5a6dfb27dea84c5751776ecabdd069646#27a8c0f5a6dfb27dea84c5751776ecabdd069646" +version = "2.1.0" +source = "git+https://github.com/paradigmxyz/reth?rev=8ebfaff134a973ea7b89f619a0562882e97b93c7#8ebfaff134a973ea7b89f619a0562882e97b93c7" dependencies = [ - "alloy-eips", - "alloy-primitives 1.4.1", + "alloy-eips 2.0.4", + "alloy-primitives 1.5.7", "reth-chain-state", "reth-execution-types", "reth-primitives-traits", @@ -11039,8 +11779,8 @@ dependencies = [ [[package]] name = "reth-fs-util" -version = "1.9.3" -source = "git+https://github.com/paradigmxyz/reth?rev=27a8c0f5a6dfb27dea84c5751776ecabdd069646#27a8c0f5a6dfb27dea84c5751776ecabdd069646" +version = "2.1.0" +source = "git+https://github.com/paradigmxyz/reth?rev=8ebfaff134a973ea7b89f619a0562882e97b93c7#8ebfaff134a973ea7b89f619a0562882e97b93c7" dependencies = [ "serde", "serde_json", @@ -11049,11 +11789,11 @@ dependencies = [ [[package]] name = "reth-invalid-block-hooks" -version = "1.9.3" -source = "git+https://github.com/paradigmxyz/reth?rev=27a8c0f5a6dfb27dea84c5751776ecabdd069646#27a8c0f5a6dfb27dea84c5751776ecabdd069646" +version = "2.1.0" +source = "git+https://github.com/paradigmxyz/reth?rev=8ebfaff134a973ea7b89f619a0562882e97b93c7#8ebfaff134a973ea7b89f619a0562882e97b93c7" dependencies = [ - "alloy-consensus", - "alloy-primitives 1.4.1", + "alloy-consensus 2.0.4", + "alloy-primitives 1.5.7", "alloy-rlp", "alloy-rpc-types-debug", "eyre", @@ -11077,8 +11817,8 @@ dependencies = [ [[package]] name = "reth-ipc" -version = "1.9.3" -source = "git+https://github.com/paradigmxyz/reth?rev=27a8c0f5a6dfb27dea84c5751776ecabdd069646#27a8c0f5a6dfb27dea84c5751776ecabdd069646" +version = "2.1.0" +source = "git+https://github.com/paradigmxyz/reth?rev=8ebfaff134a973ea7b89f619a0562882e97b93c7#8ebfaff134a973ea7b89f619a0562882e97b93c7" dependencies = [ "bytes", "futures", @@ -11097,11 +11837,12 @@ dependencies = [ [[package]] name = "reth-libmdbx" -version = "1.9.3" -source = "git+https://github.com/paradigmxyz/reth?rev=27a8c0f5a6dfb27dea84c5751776ecabdd069646#27a8c0f5a6dfb27dea84c5751776ecabdd069646" +version = "2.1.0" +source = "git+https://github.com/paradigmxyz/reth?rev=8ebfaff134a973ea7b89f619a0562882e97b93c7#8ebfaff134a973ea7b89f619a0562882e97b93c7" dependencies = [ "bitflags 2.10.0", "byteorder", + "crossbeam-queue", "dashmap 6.1.0", "derive_more 2.1.0", "parking_lot", @@ -11113,10 +11854,10 @@ dependencies = [ [[package]] name = "reth-mdbx-sys" -version = "1.9.3" -source = "git+https://github.com/paradigmxyz/reth?rev=27a8c0f5a6dfb27dea84c5751776ecabdd069646#27a8c0f5a6dfb27dea84c5751776ecabdd069646" +version = "2.1.0" +source = "git+https://github.com/paradigmxyz/reth?rev=8ebfaff134a973ea7b89f619a0562882e97b93c7#8ebfaff134a973ea7b89f619a0562882e97b93c7" dependencies = [ - "bindgen 0.71.1", + "bindgen", "cc", ] @@ -11131,32 +11872,34 @@ dependencies = [ [[package]] name = "reth-metrics" -version = "1.9.3" -source = "git+https://github.com/paradigmxyz/reth?rev=27a8c0f5a6dfb27dea84c5751776ecabdd069646#27a8c0f5a6dfb27dea84c5751776ecabdd069646" +version = "2.1.0" +source = "git+https://github.com/paradigmxyz/reth?rev=8ebfaff134a973ea7b89f619a0562882e97b93c7#8ebfaff134a973ea7b89f619a0562882e97b93c7" dependencies = [ "futures", "metrics", "metrics-derive", + "reth-primitives-traits", "tokio", "tokio-util", ] [[package]] name = "reth-net-banlist" -version = "1.9.3" -source = "git+https://github.com/paradigmxyz/reth?rev=27a8c0f5a6dfb27dea84c5751776ecabdd069646#27a8c0f5a6dfb27dea84c5751776ecabdd069646" +version = "2.1.0" +source = "git+https://github.com/paradigmxyz/reth?rev=8ebfaff134a973ea7b89f619a0562882e97b93c7#8ebfaff134a973ea7b89f619a0562882e97b93c7" dependencies = [ - "alloy-primitives 1.4.1", + "alloy-primitives 1.5.7", + "ipnet", ] [[package]] name = "reth-net-nat" -version = "1.9.3" -source = "git+https://github.com/paradigmxyz/reth?rev=27a8c0f5a6dfb27dea84c5751776ecabdd069646#27a8c0f5a6dfb27dea84c5751776ecabdd069646" +version = "2.1.0" +source = "git+https://github.com/paradigmxyz/reth?rev=8ebfaff134a973ea7b89f619a0562882e97b93c7#8ebfaff134a973ea7b89f619a0562882e97b93c7" dependencies = [ "futures-util", "if-addrs", - "reqwest 0.12.24", + "reqwest 0.13.2", "serde_with", "thiserror 2.0.17", "tokio", @@ -11165,12 +11908,12 @@ dependencies = [ [[package]] name = "reth-network" -version = "1.9.3" -source = "git+https://github.com/paradigmxyz/reth?rev=27a8c0f5a6dfb27dea84c5751776ecabdd069646#27a8c0f5a6dfb27dea84c5751776ecabdd069646" +version = "2.1.0" +source = "git+https://github.com/paradigmxyz/reth?rev=8ebfaff134a973ea7b89f619a0562882e97b93c7#8ebfaff134a973ea7b89f619a0562882e97b93c7" dependencies = [ - "alloy-consensus", - "alloy-eips", - "alloy-primitives 1.4.1", + "alloy-consensus 2.0.4", + "alloy-eips 2.0.4", + "alloy-primitives 1.5.7", "alloy-rlp", "aquamarine", "auto_impl", @@ -11184,6 +11927,7 @@ dependencies = [ "pin-project", "rand 0.8.5", "rand 0.9.2", + "rayon", "reth-chainspec", "reth-consensus", "reth-discv4", @@ -11195,7 +11939,7 @@ dependencies = [ "reth-ethereum-forks", "reth-ethereum-primitives", "reth-fs-util", - "reth-metrics 1.9.3", + "reth-metrics 2.1.0", "reth-net-banlist", "reth-network-api", "reth-network-p2p", @@ -11203,7 +11947,7 @@ dependencies = [ "reth-network-types", "reth-primitives-traits", "reth-storage-api", - "reth-tasks 1.9.3", + "reth-tasks 2.1.0", "reth-tokio-util", "reth-transaction-pool", "rustc-hash 2.1.1", @@ -11211,6 +11955,7 @@ dependencies = [ "secp256k1 0.30.0", "serde", "smallvec", + "socket2 0.6.3", "thiserror 2.0.17", "tokio", "tokio-stream", @@ -11220,13 +11965,13 @@ dependencies = [ [[package]] name = "reth-network-api" -version = "1.9.3" -source = "git+https://github.com/paradigmxyz/reth?rev=27a8c0f5a6dfb27dea84c5751776ecabdd069646#27a8c0f5a6dfb27dea84c5751776ecabdd069646" +version = "2.1.0" +source = "git+https://github.com/paradigmxyz/reth?rev=8ebfaff134a973ea7b89f619a0562882e97b93c7#8ebfaff134a973ea7b89f619a0562882e97b93c7" dependencies = [ - "alloy-consensus", - "alloy-primitives 1.4.1", + "alloy-consensus 2.0.4", + "alloy-primitives 1.5.7", "alloy-rpc-types-admin", - "alloy-rpc-types-eth", + "alloy-rpc-types-eth 2.0.4", "auto_impl", "derive_more 2.1.0", "enr 0.13.0", @@ -11245,12 +11990,12 @@ dependencies = [ [[package]] name = "reth-network-p2p" -version = "1.9.3" -source = "git+https://github.com/paradigmxyz/reth?rev=27a8c0f5a6dfb27dea84c5751776ecabdd069646#27a8c0f5a6dfb27dea84c5751776ecabdd069646" +version = "2.1.0" +source = "git+https://github.com/paradigmxyz/reth?rev=8ebfaff134a973ea7b89f619a0562882e97b93c7#8ebfaff134a973ea7b89f619a0562882e97b93c7" dependencies = [ - "alloy-consensus", - "alloy-eips", - "alloy-primitives 1.4.1", + "alloy-consensus 2.0.4", + "alloy-eips 2.0.4", + "alloy-primitives 1.5.7", "auto_impl", "derive_more 2.1.0", "futures", @@ -11267,10 +12012,10 @@ dependencies = [ [[package]] name = "reth-network-peers" -version = "1.9.3" -source = "git+https://github.com/paradigmxyz/reth?rev=27a8c0f5a6dfb27dea84c5751776ecabdd069646#27a8c0f5a6dfb27dea84c5751776ecabdd069646" +version = "2.1.0" +source = "git+https://github.com/paradigmxyz/reth?rev=8ebfaff134a973ea7b89f619a0562882e97b93c7#8ebfaff134a973ea7b89f619a0562882e97b93c7" dependencies = [ - "alloy-primitives 1.4.1", + "alloy-primitives 1.5.7", "alloy-rlp", "enr 0.13.0", "secp256k1 0.30.0", @@ -11282,8 +12027,8 @@ dependencies = [ [[package]] name = "reth-network-types" -version = "1.9.3" -source = "git+https://github.com/paradigmxyz/reth?rev=27a8c0f5a6dfb27dea84c5751776ecabdd069646#27a8c0f5a6dfb27dea84c5751776ecabdd069646" +version = "2.1.0" +source = "git+https://github.com/paradigmxyz/reth?rev=8ebfaff134a973ea7b89f619a0562882e97b93c7#8ebfaff134a973ea7b89f619a0562882e97b93c7" dependencies = [ "alloy-eip2124", "humantime-serde", @@ -11296,13 +12041,13 @@ dependencies = [ [[package]] name = "reth-nippy-jar" -version = "1.9.3" -source = "git+https://github.com/paradigmxyz/reth?rev=27a8c0f5a6dfb27dea84c5751776ecabdd069646#27a8c0f5a6dfb27dea84c5751776ecabdd069646" +version = "2.1.0" +source = "git+https://github.com/paradigmxyz/reth?rev=8ebfaff134a973ea7b89f619a0562882e97b93c7#8ebfaff134a973ea7b89f619a0562882e97b93c7" dependencies = [ "anyhow", "bincode", "derive_more 2.1.0", - "lz4_flex", + "lz4_flex 0.12.1", "memmap2 0.9.9", "reth-fs-util", "serde", @@ -11313,8 +12058,8 @@ dependencies = [ [[package]] name = "reth-node-api" -version = "1.9.3" -source = "git+https://github.com/paradigmxyz/reth?rev=27a8c0f5a6dfb27dea84c5751776ecabdd069646#27a8c0f5a6dfb27dea84c5751776ecabdd069646" +version = "2.1.0" +source = "git+https://github.com/paradigmxyz/reth?rev=8ebfaff134a973ea7b89f619a0562882e97b93c7#8ebfaff134a973ea7b89f619a0562882e97b93c7" dependencies = [ "alloy-rpc-types-engine", "eyre", @@ -11330,19 +12075,19 @@ dependencies = [ "reth-payload-builder-primitives", "reth-payload-primitives", "reth-provider", - "reth-tasks 1.9.3", + "reth-tasks 2.1.0", "reth-tokio-util", "reth-transaction-pool", ] [[package]] name = "reth-node-builder" -version = "1.9.3" -source = "git+https://github.com/paradigmxyz/reth?rev=27a8c0f5a6dfb27dea84c5751776ecabdd069646#27a8c0f5a6dfb27dea84c5751776ecabdd069646" +version = "2.1.0" +source = "git+https://github.com/paradigmxyz/reth?rev=8ebfaff134a973ea7b89f619a0562882e97b93c7#8ebfaff134a973ea7b89f619a0562882e97b93c7" dependencies = [ - "alloy-consensus", - "alloy-eips", - "alloy-primitives 1.4.1", + "alloy-consensus 2.0.4", + "alloy-eips 2.0.4", + "alloy-primitives 1.5.7", "alloy-provider", "alloy-rpc-types", "alloy-rpc-types-engine", @@ -11351,11 +12096,11 @@ dependencies = [ "fdlimit", "futures", "jsonrpsee 0.26.0", + "parking_lot", "rayon", "reth-basic-payload-builder", "reth-chain-state", "reth-chainspec", - "reth-cli-util", "reth-config", "reth-consensus", "reth-consensus-debug-client", @@ -11365,7 +12110,6 @@ dependencies = [ "reth-downloaders", "reth-engine-local", "reth-engine-primitives", - "reth-engine-service", "reth-engine-tree", "reth-engine-util", "reth-evm", @@ -11392,10 +12136,11 @@ dependencies = [ "reth-rpc-layer", "reth-stages", "reth-static-file", - "reth-tasks 1.9.3", + "reth-tasks 2.1.0", "reth-tokio-util", "reth-tracing", "reth-transaction-pool", + "reth-trie-db", "secp256k1 0.30.0", "serde_json", "tokio", @@ -11405,12 +12150,12 @@ dependencies = [ [[package]] name = "reth-node-core" -version = "1.9.3" -source = "git+https://github.com/paradigmxyz/reth?rev=27a8c0f5a6dfb27dea84c5751776ecabdd069646#27a8c0f5a6dfb27dea84c5751776ecabdd069646" +version = "2.1.0" +source = "git+https://github.com/paradigmxyz/reth?rev=8ebfaff134a973ea7b89f619a0562882e97b93c7#8ebfaff134a973ea7b89f619a0562882e97b93c7" dependencies = [ - "alloy-consensus", - "alloy-eips", - "alloy-primitives 1.4.1", + "alloy-consensus 2.0.4", + "alloy-eips 2.0.4", + "alloy-primitives 1.5.7", "alloy-rpc-types-engine", "clap", "derive_more 2.1.0", @@ -11418,6 +12163,7 @@ dependencies = [ "eyre", "futures", "humantime", + "ipnet", "rand 0.9.2", "reth-chainspec", "reth-cli-util", @@ -11429,6 +12175,7 @@ dependencies = [ "reth-engine-local", "reth-engine-primitives", "reth-ethereum-forks", + "reth-net-banlist", "reth-net-nat", "reth-network", "reth-network-p2p", @@ -11441,15 +12188,15 @@ dependencies = [ "reth-stages-types", "reth-storage-api", "reth-storage-errors", + "reth-tasks 2.1.0", "reth-tracing", "reth-tracing-otlp", "reth-transaction-pool", "secp256k1 0.30.0", "serde", - "shellexpand", "strum 0.27.2", "thiserror 2.0.17", - "toml 0.8.23", + "toml 0.9.8", "tracing", "url", "vergen", @@ -11458,13 +12205,13 @@ dependencies = [ [[package]] name = "reth-node-ethereum" -version = "1.9.3" -source = "git+https://github.com/paradigmxyz/reth?rev=27a8c0f5a6dfb27dea84c5751776ecabdd069646#27a8c0f5a6dfb27dea84c5751776ecabdd069646" +version = "2.1.0" +source = "git+https://github.com/paradigmxyz/reth?rev=8ebfaff134a973ea7b89f619a0562882e97b93c7#8ebfaff134a973ea7b89f619a0562882e97b93c7" dependencies = [ - "alloy-eips", + "alloy-eips 2.0.4", "alloy-network", "alloy-rpc-types-engine", - "alloy-rpc-types-eth", + "alloy-rpc-types-eth 2.0.4", "eyre", "reth-chainspec", "reth-engine-local", @@ -11496,11 +12243,11 @@ dependencies = [ [[package]] name = "reth-node-ethstats" -version = "1.9.3" -source = "git+https://github.com/paradigmxyz/reth?rev=27a8c0f5a6dfb27dea84c5751776ecabdd069646#27a8c0f5a6dfb27dea84c5751776ecabdd069646" +version = "2.1.0" +source = "git+https://github.com/paradigmxyz/reth?rev=8ebfaff134a973ea7b89f619a0562882e97b93c7#8ebfaff134a973ea7b89f619a0562882e97b93c7" dependencies = [ - "alloy-consensus", - "alloy-primitives 1.4.1", + "alloy-consensus 2.0.4", + "alloy-primitives 1.5.7", "chrono", "futures-util", "reth-chain-state", @@ -11513,19 +12260,19 @@ dependencies = [ "thiserror 2.0.17", "tokio", "tokio-stream", - "tokio-tungstenite 0.26.2", + "tokio-tungstenite 0.28.0", "tracing", "url", ] [[package]] name = "reth-node-events" -version = "1.9.3" -source = "git+https://github.com/paradigmxyz/reth?rev=27a8c0f5a6dfb27dea84c5751776ecabdd069646#27a8c0f5a6dfb27dea84c5751776ecabdd069646" +version = "2.1.0" +source = "git+https://github.com/paradigmxyz/reth?rev=8ebfaff134a973ea7b89f619a0562882e97b93c7#8ebfaff134a973ea7b89f619a0562882e97b93c7" dependencies = [ - "alloy-consensus", - "alloy-eips", - "alloy-primitives 1.4.1", + "alloy-consensus 2.0.4", + "alloy-eips 2.0.4", + "alloy-primitives 1.5.7", "alloy-rpc-types-engine", "derive_more 2.1.0", "futures", @@ -11544,20 +12291,22 @@ dependencies = [ [[package]] name = "reth-node-metrics" -version = "1.9.3" -source = "git+https://github.com/paradigmxyz/reth?rev=27a8c0f5a6dfb27dea84c5751776ecabdd069646#27a8c0f5a6dfb27dea84c5751776ecabdd069646" +version = "2.1.0" +source = "git+https://github.com/paradigmxyz/reth?rev=8ebfaff134a973ea7b89f619a0562882e97b93c7#8ebfaff134a973ea7b89f619a0562882e97b93c7" dependencies = [ + "bytes", "eyre", "http 1.4.0", + "http-body-util", "jsonrpsee-server 0.26.0", "metrics", "metrics-exporter-prometheus", "metrics-process", "metrics-util", - "procfs 0.17.0", - "reqwest 0.12.24", - "reth-metrics 1.9.3", - "reth-tasks 1.9.3", + "procfs", + "reqwest 0.13.2", + "reth-metrics 2.1.0", + "reth-tasks 2.1.0", "tikv-jemalloc-ctl", "tokio", "tower 0.5.2", @@ -11566,8 +12315,8 @@ dependencies = [ [[package]] name = "reth-node-types" -version = "1.9.3" -source = "git+https://github.com/paradigmxyz/reth?rev=27a8c0f5a6dfb27dea84c5751776ecabdd069646#27a8c0f5a6dfb27dea84c5751776ecabdd069646" +version = "2.1.0" +source = "git+https://github.com/paradigmxyz/reth?rev=8ebfaff134a973ea7b89f619a0562882e97b93c7#8ebfaff134a973ea7b89f619a0562882e97b93c7" dependencies = [ "reth-chainspec", "reth-db-api", @@ -11576,42 +12325,25 @@ dependencies = [ "reth-primitives-traits", ] -[[package]] -name = "reth-optimism-primitives" -version = "1.9.3" -source = "git+https://github.com/paradigmxyz/reth?rev=27a8c0f5a6dfb27dea84c5751776ecabdd069646#27a8c0f5a6dfb27dea84c5751776ecabdd069646" -dependencies = [ - "alloy-consensus", - "alloy-eips", - "alloy-primitives 1.4.1", - "alloy-rlp", - "arbitrary", - "bytes", - "modular-bitfield", - "op-alloy-consensus", - "reth-codecs", - "reth-primitives-traits", - "reth-zstd-compressors", - "serde", - "serde_with", -] - [[package]] name = "reth-payload-builder" -version = "1.9.3" -source = "git+https://github.com/paradigmxyz/reth?rev=27a8c0f5a6dfb27dea84c5751776ecabdd069646#27a8c0f5a6dfb27dea84c5751776ecabdd069646" +version = "2.1.0" +source = "git+https://github.com/paradigmxyz/reth?rev=8ebfaff134a973ea7b89f619a0562882e97b93c7#8ebfaff134a973ea7b89f619a0562882e97b93c7" dependencies = [ - "alloy-consensus", - "alloy-primitives 1.4.1", + "alloy-consensus 2.0.4", + "alloy-primitives 1.5.7", "alloy-rpc-types", + "derive_more 2.1.0", "futures-util", "metrics", "reth-chain-state", "reth-ethereum-engine-primitives", - "reth-metrics 1.9.3", + "reth-execution-cache", + "reth-metrics 2.1.0", "reth-payload-builder-primitives", "reth-payload-primitives", "reth-primitives-traits", + "reth-trie-parallel", "tokio", "tokio-stream", "tracing", @@ -11619,8 +12351,8 @@ dependencies = [ [[package]] name = "reth-payload-builder-primitives" -version = "1.9.3" -source = "git+https://github.com/paradigmxyz/reth?rev=27a8c0f5a6dfb27dea84c5751776ecabdd069646#27a8c0f5a6dfb27dea84c5751776ecabdd069646" +version = "2.1.0" +source = "git+https://github.com/paradigmxyz/reth?rev=8ebfaff134a973ea7b89f619a0562882e97b93c7#8ebfaff134a973ea7b89f619a0562882e97b93c7" dependencies = [ "pin-project", "reth-payload-primitives", @@ -11631,70 +12363,60 @@ dependencies = [ [[package]] name = "reth-payload-primitives" -version = "1.9.3" -source = "git+https://github.com/paradigmxyz/reth?rev=27a8c0f5a6dfb27dea84c5751776ecabdd069646#27a8c0f5a6dfb27dea84c5751776ecabdd069646" +version = "2.1.0" +source = "git+https://github.com/paradigmxyz/reth?rev=8ebfaff134a973ea7b89f619a0562882e97b93c7#8ebfaff134a973ea7b89f619a0562882e97b93c7" dependencies = [ - "alloy-eips", - "alloy-primitives 1.4.1", + "alloy-consensus 2.0.4", + "alloy-eips 2.0.4", + "alloy-primitives 1.5.7", + "alloy-rlp", "alloy-rpc-types-engine", "auto_impl", "either", - "op-alloy-rpc-types-engine", "reth-chain-state", "reth-chainspec", "reth-errors", + "reth-execution-types", "reth-primitives-traits", + "reth-trie-common", "serde", + "sha2 0.10.9", "thiserror 2.0.17", "tokio", ] [[package]] name = "reth-payload-validator" -version = "1.9.3" -source = "git+https://github.com/paradigmxyz/reth?rev=27a8c0f5a6dfb27dea84c5751776ecabdd069646#27a8c0f5a6dfb27dea84c5751776ecabdd069646" +version = "2.1.0" +source = "git+https://github.com/paradigmxyz/reth?rev=8ebfaff134a973ea7b89f619a0562882e97b93c7#8ebfaff134a973ea7b89f619a0562882e97b93c7" dependencies = [ - "alloy-consensus", + "alloy-consensus 2.0.4", "alloy-rpc-types-engine", "reth-primitives-traits", ] -[[package]] -name = "reth-primitives" -version = "1.9.3" -source = "git+https://github.com/paradigmxyz/reth?rev=27a8c0f5a6dfb27dea84c5751776ecabdd069646#27a8c0f5a6dfb27dea84c5751776ecabdd069646" -dependencies = [ - "alloy-consensus", - "c-kzg", - "once_cell", - "reth-ethereum-forks", - "reth-ethereum-primitives", - "reth-primitives-traits", - "reth-static-file-types", -] - [[package]] name = "reth-primitives-traits" -version = "1.9.3" -source = "git+https://github.com/paradigmxyz/reth?rev=27a8c0f5a6dfb27dea84c5751776ecabdd069646#27a8c0f5a6dfb27dea84c5751776ecabdd069646" +version = "0.3.1" +source = "git+https://github.com/paradigmxyz/reth-core?rev=afa5162668db00749b14bf30d06d3bed5c71aa4c#afa5162668db00749b14bf30d06d3bed5c71aa4c" dependencies = [ - "alloy-consensus", - "alloy-eips", + "alloy-consensus 2.0.4", + "alloy-eips 2.0.4", "alloy-genesis", - "alloy-primitives 1.4.1", + "alloy-primitives 1.5.7", "alloy-rlp", - "alloy-rpc-types-eth", - "alloy-trie 0.9.1", + "alloy-rpc-types-eth 2.0.4", + "alloy-trie", "arbitrary", - "auto_impl", "byteorder", "bytes", + "dashmap 6.1.0", "derive_more 2.1.0", "modular-bitfield", "once_cell", - "op-alloy-consensus", "proptest", "proptest-arbitrary-interop", + "quanta", "rayon", "reth-codecs", "revm-bytecode", @@ -11702,20 +12424,19 @@ dependencies = [ "revm-state", "secp256k1 0.30.0", "serde", - "serde_with", "thiserror 2.0.17", ] [[package]] name = "reth-provider" -version = "1.9.3" -source = "git+https://github.com/paradigmxyz/reth?rev=27a8c0f5a6dfb27dea84c5751776ecabdd069646#27a8c0f5a6dfb27dea84c5751776ecabdd069646" +version = "2.1.0" +source = "git+https://github.com/paradigmxyz/reth?rev=8ebfaff134a973ea7b89f619a0562882e97b93c7#8ebfaff134a973ea7b89f619a0562882e97b93c7" dependencies = [ - "alloy-consensus", - "alloy-eips", - "alloy-primitives 1.4.1", + "alloy-consensus 2.0.4", + "alloy-eips 2.0.4", + "alloy-genesis", + "alloy-primitives 1.5.7", "alloy-rpc-types-engine", - "dashmap 6.1.0", "eyre", "itertools 0.14.0", "metrics", @@ -11732,7 +12453,7 @@ dependencies = [ "reth-ethereum-primitives", "reth-execution-types", "reth-fs-util", - "reth-metrics 1.9.3", + "reth-metrics 2.1.0", "reth-nippy-jar", "reth-node-types", "reth-primitives-traits", @@ -11741,10 +12462,12 @@ dependencies = [ "reth-static-file-types", "reth-storage-api", "reth-storage-errors", + "reth-tasks 2.1.0", "reth-trie", "reth-trie-db", "revm-database", "revm-state", + "rocksdb", "strum 0.27.2", "tokio", "tracing", @@ -11752,12 +12475,12 @@ dependencies = [ [[package]] name = "reth-prune" -version = "1.9.3" -source = "git+https://github.com/paradigmxyz/reth?rev=27a8c0f5a6dfb27dea84c5751776ecabdd069646#27a8c0f5a6dfb27dea84c5751776ecabdd069646" +version = "2.1.0" +source = "git+https://github.com/paradigmxyz/reth?rev=8ebfaff134a973ea7b89f619a0562882e97b93c7#8ebfaff134a973ea7b89f619a0562882e97b93c7" dependencies = [ - "alloy-consensus", - "alloy-eips", - "alloy-primitives 1.4.1", + "alloy-consensus 2.0.4", + "alloy-eips 2.0.4", + "alloy-primitives 1.5.7", "itertools 0.14.0", "metrics", "rayon", @@ -11765,11 +12488,13 @@ dependencies = [ "reth-db-api", "reth-errors", "reth-exex-types", - "reth-metrics 1.9.3", + "reth-metrics 2.1.0", "reth-primitives-traits", "reth-provider", "reth-prune-types", + "reth-stages-types", "reth-static-file-types", + "reth-storage-api", "reth-tokio-util", "rustc-hash 2.1.1", "thiserror 2.0.17", @@ -11779,10 +12504,10 @@ dependencies = [ [[package]] name = "reth-prune-types" -version = "1.9.3" -source = "git+https://github.com/paradigmxyz/reth?rev=27a8c0f5a6dfb27dea84c5751776ecabdd069646#27a8c0f5a6dfb27dea84c5751776ecabdd069646" +version = "2.1.0" +source = "git+https://github.com/paradigmxyz/reth?rev=8ebfaff134a973ea7b89f619a0562882e97b93c7#8ebfaff134a973ea7b89f619a0562882e97b93c7" dependencies = [ - "alloy-primitives 1.4.1", + "alloy-primitives 1.5.7", "arbitrary", "derive_more 2.1.0", "modular-bitfield", @@ -11790,6 +12515,7 @@ dependencies = [ "serde", "strum 0.27.2", "thiserror 2.0.17", + "tracing", ] [[package]] @@ -11811,58 +12537,14 @@ dependencies = [ "tracing", ] -[[package]] -name = "reth-ress-protocol" -version = "1.9.3" -source = "git+https://github.com/paradigmxyz/reth?rev=27a8c0f5a6dfb27dea84c5751776ecabdd069646#27a8c0f5a6dfb27dea84c5751776ecabdd069646" -dependencies = [ - "alloy-consensus", - "alloy-primitives 1.4.1", - "alloy-rlp", - "futures", - "reth-eth-wire", - "reth-ethereum-primitives", - "reth-network", - "reth-network-api", - "reth-storage-errors", - "tokio", - "tokio-stream", - "tracing", -] - -[[package]] -name = "reth-ress-provider" -version = "1.9.3" -source = "git+https://github.com/paradigmxyz/reth?rev=27a8c0f5a6dfb27dea84c5751776ecabdd069646#27a8c0f5a6dfb27dea84c5751776ecabdd069646" -dependencies = [ - "alloy-consensus", - "alloy-primitives 1.4.1", - "eyre", - "futures", - "parking_lot", - "reth-chain-state", - "reth-errors", - "reth-ethereum-primitives", - "reth-evm", - "reth-node-api", - "reth-primitives-traits", - "reth-ress-protocol", - "reth-revm", - "reth-storage-api", - "reth-tasks 1.9.3", - "reth-tokio-util", - "reth-trie", - "schnellru", - "tokio", - "tracing", -] - [[package]] name = "reth-revm" -version = "1.9.3" -source = "git+https://github.com/paradigmxyz/reth?rev=27a8c0f5a6dfb27dea84c5751776ecabdd069646#27a8c0f5a6dfb27dea84c5751776ecabdd069646" +version = "2.1.0" +source = "git+https://github.com/paradigmxyz/reth?rev=8ebfaff134a973ea7b89f619a0562882e97b93c7#8ebfaff134a973ea7b89f619a0562882e97b93c7" dependencies = [ - "alloy-primitives 1.4.1", + "alloy-primitives 1.5.7", + "alloy-rlp", + "alloy-rpc-types-debug", "reth-primitives-traits", "reth-storage-api", "reth-storage-errors", @@ -11872,16 +12554,16 @@ dependencies = [ [[package]] name = "reth-rpc" -version = "1.9.3" -source = "git+https://github.com/paradigmxyz/reth?rev=27a8c0f5a6dfb27dea84c5751776ecabdd069646#27a8c0f5a6dfb27dea84c5751776ecabdd069646" +version = "2.1.0" +source = "git+https://github.com/paradigmxyz/reth?rev=8ebfaff134a973ea7b89f619a0562882e97b93c7#8ebfaff134a973ea7b89f619a0562882e97b93c7" dependencies = [ - "alloy-consensus", + "alloy-consensus 2.0.4", "alloy-dyn-abi", - "alloy-eips", + "alloy-eips 2.0.4", "alloy-evm", "alloy-genesis", "alloy-network", - "alloy-primitives 1.4.1", + "alloy-primitives 1.5.7", "alloy-rlp", "alloy-rpc-client", "alloy-rpc-types", @@ -11889,24 +12571,20 @@ dependencies = [ "alloy-rpc-types-beacon", "alloy-rpc-types-debug", "alloy-rpc-types-engine", - "alloy-rpc-types-eth", + "alloy-rpc-types-eth 2.0.4", "alloy-rpc-types-mev", "alloy-rpc-types-trace", "alloy-rpc-types-txpool", - "alloy-serde", + "alloy-serde 2.0.4", "alloy-signer", "alloy-signer-local", "async-trait", "derive_more 2.1.0", "dyn-clone", "futures", - "http 1.4.0", - "http-body 1.0.1", - "hyper 1.8.1", "itertools 0.14.0", "jsonrpsee 0.26.0", "jsonrpsee-types 0.26.0", - "jsonwebtoken", "parking_lot", "pin-project", "reth-chain-state", @@ -11915,10 +12593,12 @@ dependencies = [ "reth-consensus-common", "reth-engine-primitives", "reth-errors", + "reth-ethereum-engine-primitives", + "reth-ethereum-primitives", "reth-evm", "reth-evm-ethereum", "reth-execution-types", - "reth-metrics 1.9.3", + "reth-metrics 2.1.0", "reth-network-api", "reth-network-peers", "reth-network-types", @@ -11932,7 +12612,8 @@ dependencies = [ "reth-rpc-eth-types", "reth-rpc-server-types", "reth-storage-api", - "reth-tasks 1.9.3", + "reth-tasks 2.1.0", + "reth-tracing", "reth-transaction-pool", "reth-trie-common", "revm", @@ -11944,43 +12625,44 @@ dependencies = [ "thiserror 2.0.17", "tokio", "tokio-stream", - "tower 0.5.2", "tracing", "tracing-futures", ] [[package]] name = "reth-rpc-api" -version = "1.9.3" -source = "git+https://github.com/paradigmxyz/reth?rev=27a8c0f5a6dfb27dea84c5751776ecabdd069646#27a8c0f5a6dfb27dea84c5751776ecabdd069646" +version = "2.1.0" +source = "git+https://github.com/paradigmxyz/reth?rev=8ebfaff134a973ea7b89f619a0562882e97b93c7#8ebfaff134a973ea7b89f619a0562882e97b93c7" dependencies = [ - "alloy-eips", + "alloy-eips 2.0.4", "alloy-genesis", - "alloy-json-rpc", - "alloy-primitives 1.4.1", + "alloy-json-rpc 2.0.4", + "alloy-primitives 1.5.7", "alloy-rpc-types", "alloy-rpc-types-admin", "alloy-rpc-types-anvil", "alloy-rpc-types-beacon", "alloy-rpc-types-debug", "alloy-rpc-types-engine", - "alloy-rpc-types-eth", + "alloy-rpc-types-eth 2.0.4", "alloy-rpc-types-mev", "alloy-rpc-types-trace", "alloy-rpc-types-txpool", - "alloy-serde", + "alloy-serde 2.0.4", "jsonrpsee 0.26.0", "reth-chain-state", "reth-engine-primitives", "reth-network-peers", "reth-rpc-eth-api", "reth-trie-common", + "serde", + "serde_json", ] [[package]] name = "reth-rpc-builder" -version = "1.9.3" -source = "git+https://github.com/paradigmxyz/reth?rev=27a8c0f5a6dfb27dea84c5751776ecabdd069646#27a8c0f5a6dfb27dea84c5751776ecabdd069646" +version = "2.1.0" +source = "git+https://github.com/paradigmxyz/reth?rev=8ebfaff134a973ea7b89f619a0562882e97b93c7#8ebfaff134a973ea7b89f619a0562882e97b93c7" dependencies = [ "alloy-network", "alloy-provider", @@ -11992,20 +12674,24 @@ dependencies = [ "reth-chain-state", "reth-chainspec", "reth-consensus", + "reth-engine-primitives", "reth-evm", "reth-ipc", - "reth-metrics 1.9.3", + "reth-metrics 2.1.0", "reth-network-api", "reth-node-core", + "reth-payload-primitives", "reth-primitives-traits", "reth-rpc", "reth-rpc-api", + "reth-rpc-engine-api", "reth-rpc-eth-api", "reth-rpc-eth-types", "reth-rpc-layer", "reth-rpc-server-types", "reth-storage-api", - "reth-tasks 1.9.3", + "reth-tasks 2.1.0", + "reth-tokio-util", "reth-transaction-pool", "serde", "thiserror 2.0.17", @@ -12018,48 +12704,48 @@ dependencies = [ [[package]] name = "reth-rpc-convert" -version = "1.9.3" -source = "git+https://github.com/paradigmxyz/reth?rev=27a8c0f5a6dfb27dea84c5751776ecabdd069646#27a8c0f5a6dfb27dea84c5751776ecabdd069646" +version = "2.1.0" +source = "git+https://github.com/paradigmxyz/reth?rev=8ebfaff134a973ea7b89f619a0562882e97b93c7#8ebfaff134a973ea7b89f619a0562882e97b93c7" dependencies = [ - "alloy-consensus", - "alloy-json-rpc", + "alloy-consensus 2.0.4", + "alloy-evm", + "alloy-json-rpc 2.0.4", "alloy-network", - "alloy-primitives 1.4.1", - "alloy-rpc-types-eth", - "alloy-signer", + "alloy-primitives 1.5.7", + "alloy-rpc-types-eth 2.0.4", "auto_impl", "dyn-clone", "jsonrpsee-types 0.26.0", - "reth-ethereum-primitives", "reth-evm", "reth-primitives-traits", - "revm-context", + "reth-rpc-traits", "thiserror 2.0.17", ] [[package]] name = "reth-rpc-engine-api" -version = "1.9.3" -source = "git+https://github.com/paradigmxyz/reth?rev=27a8c0f5a6dfb27dea84c5751776ecabdd069646#27a8c0f5a6dfb27dea84c5751776ecabdd069646" +version = "2.1.0" +source = "git+https://github.com/paradigmxyz/reth?rev=8ebfaff134a973ea7b89f619a0562882e97b93c7#8ebfaff134a973ea7b89f619a0562882e97b93c7" dependencies = [ - "alloy-eips", - "alloy-primitives 1.4.1", + "alloy-eips 2.0.4", + "alloy-primitives 1.5.7", + "alloy-rlp", "alloy-rpc-types-engine", "async-trait", "jsonrpsee-core 0.26.0", "jsonrpsee-types 0.26.0", "metrics", - "parking_lot", "reth-chainspec", "reth-engine-primitives", - "reth-metrics 1.9.3", + "reth-metrics 2.1.0", + "reth-network-api", "reth-payload-builder", "reth-payload-builder-primitives", "reth-payload-primitives", "reth-primitives-traits", "reth-rpc-api", "reth-storage-api", - "reth-tasks 1.9.3", + "reth-tasks 2.1.0", "reth-transaction-pool", "serde", "thiserror 2.0.17", @@ -12069,20 +12755,21 @@ dependencies = [ [[package]] name = "reth-rpc-eth-api" -version = "1.9.3" -source = "git+https://github.com/paradigmxyz/reth?rev=27a8c0f5a6dfb27dea84c5751776ecabdd069646#27a8c0f5a6dfb27dea84c5751776ecabdd069646" +version = "2.1.0" +source = "git+https://github.com/paradigmxyz/reth?rev=8ebfaff134a973ea7b89f619a0562882e97b93c7#8ebfaff134a973ea7b89f619a0562882e97b93c7" dependencies = [ - "alloy-consensus", + "alloy-consensus 2.0.4", "alloy-dyn-abi", - "alloy-eips", + "alloy-eip7928", + "alloy-eips 2.0.4", "alloy-evm", - "alloy-json-rpc", + "alloy-json-rpc 2.0.4", "alloy-network", - "alloy-primitives 1.4.1", + "alloy-primitives 1.5.7", "alloy-rlp", - "alloy-rpc-types-eth", + "alloy-rpc-types-eth 2.0.4", "alloy-rpc-types-mev", - "alloy-serde", + "alloy-serde 2.0.4", "async-trait", "auto_impl", "dyn-clone", @@ -12102,27 +12789,28 @@ dependencies = [ "reth-rpc-eth-types", "reth-rpc-server-types", "reth-storage-api", - "reth-tasks 1.9.3", + "reth-tasks 2.1.0", "reth-transaction-pool", "reth-trie-common", "revm", "revm-inspectors", + "serde_json", "tokio", "tracing", ] [[package]] name = "reth-rpc-eth-types" -version = "1.9.3" -source = "git+https://github.com/paradigmxyz/reth?rev=27a8c0f5a6dfb27dea84c5751776ecabdd069646#27a8c0f5a6dfb27dea84c5751776ecabdd069646" +version = "2.1.0" +source = "git+https://github.com/paradigmxyz/reth?rev=8ebfaff134a973ea7b89f619a0562882e97b93c7#8ebfaff134a973ea7b89f619a0562882e97b93c7" dependencies = [ - "alloy-consensus", - "alloy-eips", + "alloy-consensus 2.0.4", + "alloy-eips 2.0.4", "alloy-evm", "alloy-network", - "alloy-primitives 1.4.1", + "alloy-primitives 1.5.7", "alloy-rpc-client", - "alloy-rpc-types-eth", + "alloy-rpc-types-eth 2.0.4", "alloy-sol-types", "alloy-transport", "derive_more 2.1.0", @@ -12132,20 +12820,20 @@ dependencies = [ "jsonrpsee-types 0.26.0", "metrics", "rand 0.9.2", - "reqwest 0.12.24", + "reqwest 0.13.2", "reth-chain-state", "reth-chainspec", "reth-errors", "reth-ethereum-primitives", "reth-evm", "reth-execution-types", - "reth-metrics 1.9.3", + "reth-metrics 2.1.0", "reth-primitives-traits", "reth-revm", "reth-rpc-convert", "reth-rpc-server-types", "reth-storage-api", - "reth-tasks 1.9.3", + "reth-tasks 2.1.0", "reth-transaction-pool", "reth-trie", "revm", @@ -12156,12 +12844,13 @@ dependencies = [ "tokio", "tokio-stream", "tracing", + "url", ] [[package]] name = "reth-rpc-layer" -version = "1.9.3" -source = "git+https://github.com/paradigmxyz/reth?rev=27a8c0f5a6dfb27dea84c5751776ecabdd069646#27a8c0f5a6dfb27dea84c5751776ecabdd069646" +version = "2.1.0" +source = "git+https://github.com/paradigmxyz/reth?rev=8ebfaff134a973ea7b89f619a0562882e97b93c7#8ebfaff134a973ea7b89f619a0562882e97b93c7" dependencies = [ "alloy-rpc-types-engine", "http 1.4.0", @@ -12174,11 +12863,11 @@ dependencies = [ [[package]] name = "reth-rpc-server-types" -version = "1.9.3" -source = "git+https://github.com/paradigmxyz/reth?rev=27a8c0f5a6dfb27dea84c5751776ecabdd069646#27a8c0f5a6dfb27dea84c5751776ecabdd069646" +version = "2.1.0" +source = "git+https://github.com/paradigmxyz/reth?rev=8ebfaff134a973ea7b89f619a0562882e97b93c7#8ebfaff134a973ea7b89f619a0562882e97b93c7" dependencies = [ - "alloy-eips", - "alloy-primitives 1.4.1", + "alloy-eips 2.0.4", + "alloy-primitives 1.5.7", "alloy-rpc-types-engine", "jsonrpsee-core 0.26.0", "jsonrpsee-types 0.26.0", @@ -12188,21 +12877,37 @@ dependencies = [ "strum 0.27.2", ] +[[package]] +name = "reth-rpc-traits" +version = "0.3.1" +source = "git+https://github.com/paradigmxyz/reth-core?rev=afa5162668db00749b14bf30d06d3bed5c71aa4c#afa5162668db00749b14bf30d06d3bed5c71aa4c" +dependencies = [ + "alloy-consensus 2.0.4", + "alloy-network", + "alloy-primitives 1.5.7", + "alloy-rpc-types-eth 2.0.4", + "alloy-signer", + "reth-primitives-traits", + "thiserror 2.0.17", +] + [[package]] name = "reth-stages" -version = "1.9.3" -source = "git+https://github.com/paradigmxyz/reth?rev=27a8c0f5a6dfb27dea84c5751776ecabdd069646#27a8c0f5a6dfb27dea84c5751776ecabdd069646" +version = "2.1.0" +source = "git+https://github.com/paradigmxyz/reth?rev=8ebfaff134a973ea7b89f619a0562882e97b93c7#8ebfaff134a973ea7b89f619a0562882e97b93c7" dependencies = [ - "alloy-consensus", - "alloy-eips", - "alloy-primitives 1.4.1", - "bincode", + "alloy-consensus 2.0.4", + "alloy-eips 2.0.4", + "alloy-primitives 1.5.7", + "alloy-rlp", "eyre", "futures-util", "itertools 0.14.0", "num-traits", + "page_size", "rayon", - "reqwest 0.12.24", + "reqwest 0.13.2", + "reth-chainspec", "reth-codecs", "reth-config", "reth-consensus", @@ -12216,6 +12921,7 @@ dependencies = [ "reth-execution-types", "reth-exex", "reth-fs-util", + "reth-libmdbx", "reth-network-p2p", "reth-primitives-traits", "reth-provider", @@ -12224,7 +12930,9 @@ dependencies = [ "reth-revm", "reth-stages-api", "reth-static-file-types", + "reth-storage-api", "reth-storage-errors", + "reth-tasks 2.1.0", "reth-trie", "reth-trie-db", "thiserror 2.0.17", @@ -12234,18 +12942,19 @@ dependencies = [ [[package]] name = "reth-stages-api" -version = "1.9.3" -source = "git+https://github.com/paradigmxyz/reth?rev=27a8c0f5a6dfb27dea84c5751776ecabdd069646#27a8c0f5a6dfb27dea84c5751776ecabdd069646" +version = "2.1.0" +source = "git+https://github.com/paradigmxyz/reth?rev=8ebfaff134a973ea7b89f619a0562882e97b93c7#8ebfaff134a973ea7b89f619a0562882e97b93c7" dependencies = [ - "alloy-eips", - "alloy-primitives 1.4.1", + "alloy-eips 2.0.4", + "alloy-primitives 1.5.7", "aquamarine", "auto_impl", "futures-util", "metrics", + "reth-codecs", "reth-consensus", "reth-errors", - "reth-metrics 1.9.3", + "reth-metrics 2.1.0", "reth-network-p2p", "reth-primitives-traits", "reth-provider", @@ -12261,10 +12970,10 @@ dependencies = [ [[package]] name = "reth-stages-types" -version = "1.9.3" -source = "git+https://github.com/paradigmxyz/reth?rev=27a8c0f5a6dfb27dea84c5751776ecabdd069646#27a8c0f5a6dfb27dea84c5751776ecabdd069646" +version = "2.1.0" +source = "git+https://github.com/paradigmxyz/reth?rev=8ebfaff134a973ea7b89f619a0562882e97b93c7#8ebfaff134a973ea7b89f619a0562882e97b93c7" dependencies = [ - "alloy-primitives 1.4.1", + "alloy-primitives 1.5.7", "arbitrary", "bytes", "modular-bitfield", @@ -12275,10 +12984,10 @@ dependencies = [ [[package]] name = "reth-static-file" -version = "1.9.3" -source = "git+https://github.com/paradigmxyz/reth?rev=27a8c0f5a6dfb27dea84c5751776ecabdd069646#27a8c0f5a6dfb27dea84c5751776ecabdd069646" +version = "2.1.0" +source = "git+https://github.com/paradigmxyz/reth?rev=8ebfaff134a973ea7b89f619a0562882e97b93c7#8ebfaff134a973ea7b89f619a0562882e97b93c7" dependencies = [ - "alloy-primitives 1.4.1", + "alloy-primitives 1.5.7", "parking_lot", "rayon", "reth-codecs", @@ -12295,24 +13004,27 @@ dependencies = [ [[package]] name = "reth-static-file-types" -version = "1.9.3" -source = "git+https://github.com/paradigmxyz/reth?rev=27a8c0f5a6dfb27dea84c5751776ecabdd069646#27a8c0f5a6dfb27dea84c5751776ecabdd069646" +version = "2.1.0" +source = "git+https://github.com/paradigmxyz/reth?rev=8ebfaff134a973ea7b89f619a0562882e97b93c7#8ebfaff134a973ea7b89f619a0562882e97b93c7" dependencies = [ - "alloy-primitives 1.4.1", + "alloy-primitives 1.5.7", "clap", "derive_more 2.1.0", + "fixed-map", + "reth-stages-types", "serde", "strum 0.27.2", + "tracing", ] [[package]] name = "reth-storage-api" -version = "1.9.3" -source = "git+https://github.com/paradigmxyz/reth?rev=27a8c0f5a6dfb27dea84c5751776ecabdd069646#27a8c0f5a6dfb27dea84c5751776ecabdd069646" +version = "2.1.0" +source = "git+https://github.com/paradigmxyz/reth?rev=8ebfaff134a973ea7b89f619a0562882e97b93c7#8ebfaff134a973ea7b89f619a0562882e97b93c7" dependencies = [ - "alloy-consensus", - "alloy-eips", - "alloy-primitives 1.4.1", + "alloy-consensus 2.0.4", + "alloy-eips 2.0.4", + "alloy-primitives 1.5.7", "alloy-rpc-types-engine", "auto_impl", "reth-chainspec", @@ -12326,21 +13038,24 @@ dependencies = [ "reth-storage-errors", "reth-trie-common", "revm-database", + "serde_json", ] [[package]] name = "reth-storage-errors" -version = "1.9.3" -source = "git+https://github.com/paradigmxyz/reth?rev=27a8c0f5a6dfb27dea84c5751776ecabdd069646#27a8c0f5a6dfb27dea84c5751776ecabdd069646" +version = "2.1.0" +source = "git+https://github.com/paradigmxyz/reth?rev=8ebfaff134a973ea7b89f619a0562882e97b93c7#8ebfaff134a973ea7b89f619a0562882e97b93c7" dependencies = [ - "alloy-eips", - "alloy-primitives 1.4.1", + "alloy-eips 2.0.4", + "alloy-primitives 1.5.7", "alloy-rlp", "derive_more 2.1.0", + "reth-codecs", "reth-primitives-traits", "reth-prune-types", "reth-static-file-types", "revm-database-interface", + "revm-state", "thiserror 2.0.17", ] @@ -12362,17 +13077,20 @@ dependencies = [ [[package]] name = "reth-tasks" -version = "1.9.3" -source = "git+https://github.com/paradigmxyz/reth?rev=27a8c0f5a6dfb27dea84c5751776ecabdd069646#27a8c0f5a6dfb27dea84c5751776ecabdd069646" +version = "2.1.0" +source = "git+https://github.com/paradigmxyz/reth?rev=8ebfaff134a973ea7b89f619a0562882e97b93c7#8ebfaff134a973ea7b89f619a0562882e97b93c7" dependencies = [ - "auto_impl", - "dyn-clone", + "crossbeam-utils", + "dashmap 6.1.0", "futures-util", + "libc", "metrics", + "parking_lot", "pin-project", "rayon", - "reth-metrics 1.9.3", + "reth-metrics 2.1.0", "thiserror 2.0.17", + "thread-priority", "tokio", "tracing", "tracing-futures", @@ -12380,8 +13098,8 @@ dependencies = [ [[package]] name = "reth-tokio-util" -version = "1.9.3" -source = "git+https://github.com/paradigmxyz/reth?rev=27a8c0f5a6dfb27dea84c5751776ecabdd069646#27a8c0f5a6dfb27dea84c5751776ecabdd069646" +version = "2.1.0" +source = "git+https://github.com/paradigmxyz/reth?rev=8ebfaff134a973ea7b89f619a0562882e97b93c7#8ebfaff134a973ea7b89f619a0562882e97b93c7" dependencies = [ "tokio", "tokio-stream", @@ -12390,8 +13108,8 @@ dependencies = [ [[package]] name = "reth-tracing" -version = "1.9.3" -source = "git+https://github.com/paradigmxyz/reth?rev=27a8c0f5a6dfb27dea84c5751776ecabdd069646#27a8c0f5a6dfb27dea84c5751776ecabdd069646" +version = "2.1.0" +source = "git+https://github.com/paradigmxyz/reth?rev=8ebfaff134a973ea7b89f619a0562882e97b93c7#8ebfaff134a973ea7b89f619a0562882e97b93c7" dependencies = [ "clap", "eyre", @@ -12401,18 +13119,19 @@ dependencies = [ "tracing-appender", "tracing-journald", "tracing-logfmt", + "tracing-samply", "tracing-subscriber 0.3.22", - "url", ] [[package]] name = "reth-tracing-otlp" -version = "1.9.3" -source = "git+https://github.com/paradigmxyz/reth?rev=27a8c0f5a6dfb27dea84c5751776ecabdd069646#27a8c0f5a6dfb27dea84c5751776ecabdd069646" +version = "2.1.0" +source = "git+https://github.com/paradigmxyz/reth?rev=8ebfaff134a973ea7b89f619a0562882e97b93c7#8ebfaff134a973ea7b89f619a0562882e97b93c7" dependencies = [ "clap", "eyre", "opentelemetry", + "opentelemetry-appender-tracing", "opentelemetry-otlp", "opentelemetry-semantic-conventions", "opentelemetry_sdk", @@ -12424,17 +13143,18 @@ dependencies = [ [[package]] name = "reth-transaction-pool" -version = "1.9.3" -source = "git+https://github.com/paradigmxyz/reth?rev=27a8c0f5a6dfb27dea84c5751776ecabdd069646#27a8c0f5a6dfb27dea84c5751776ecabdd069646" +version = "2.1.0" +source = "git+https://github.com/paradigmxyz/reth?rev=8ebfaff134a973ea7b89f619a0562882e97b93c7#8ebfaff134a973ea7b89f619a0562882e97b93c7" dependencies = [ - "alloy-consensus", - "alloy-eips", - "alloy-primitives 1.4.1", + "alloy-consensus 2.0.4", + "alloy-eips 2.0.4", + "alloy-primitives 1.5.7", "alloy-rlp", "aquamarine", "auto_impl", "bitflags 2.10.0", "futures-util", + "imbl", "metrics", "parking_lot", "pin-project", @@ -12443,12 +13163,15 @@ dependencies = [ "reth-chainspec", "reth-eth-wire-types", "reth-ethereum-primitives", + "reth-evm", + "reth-evm-ethereum", "reth-execution-types", "reth-fs-util", - "reth-metrics 1.9.3", + "reth-metrics 2.1.0", "reth-primitives-traits", "reth-storage-api", - "reth-tasks 1.9.3", + "reth-tasks 2.1.0", + "revm", "revm-interpreter", "revm-primitives", "rustc-hash 2.1.1", @@ -12464,19 +13187,20 @@ dependencies = [ [[package]] name = "reth-trie" -version = "1.9.3" -source = "git+https://github.com/paradigmxyz/reth?rev=27a8c0f5a6dfb27dea84c5751776ecabdd069646#27a8c0f5a6dfb27dea84c5751776ecabdd069646" +version = "2.1.0" +source = "git+https://github.com/paradigmxyz/reth?rev=8ebfaff134a973ea7b89f619a0562882e97b93c7#8ebfaff134a973ea7b89f619a0562882e97b93c7" dependencies = [ - "alloy-consensus", - "alloy-eips", - "alloy-primitives 1.4.1", + "alloy-consensus 2.0.4", + "alloy-eips 2.0.4", + "alloy-primitives 1.5.7", "alloy-rlp", - "alloy-trie 0.9.1", + "alloy-trie", "auto_impl", "itertools 0.14.0", "metrics", + "parking_lot", "reth-execution-errors", - "reth-metrics 1.9.3", + "reth-metrics 2.1.0", "reth-primitives-traits", "reth-stages-types", "reth-storage-errors", @@ -12489,22 +13213,22 @@ dependencies = [ [[package]] name = "reth-trie-common" -version = "1.9.3" -source = "git+https://github.com/paradigmxyz/reth?rev=27a8c0f5a6dfb27dea84c5751776ecabdd069646#27a8c0f5a6dfb27dea84c5751776ecabdd069646" +version = "2.1.0" +source = "git+https://github.com/paradigmxyz/reth?rev=8ebfaff134a973ea7b89f619a0562882e97b93c7#8ebfaff134a973ea7b89f619a0562882e97b93c7" dependencies = [ - "alloy-consensus", - "alloy-primitives 1.4.1", + "alloy-consensus 2.0.4", + "alloy-primitives 1.5.7", "alloy-rlp", - "alloy-rpc-types-eth", - "alloy-serde", - "alloy-trie 0.9.1", + "alloy-rpc-types-eth 2.0.4", + "alloy-serde 2.0.4", + "alloy-trie", "arbitrary", "arrayvec", "bytes", "derive_more 2.1.0", "hash-db", "itertools 0.14.0", - "nybbles 0.4.6", + "nybbles", "plain_hasher", "rayon", "reth-codecs", @@ -12516,92 +13240,84 @@ dependencies = [ [[package]] name = "reth-trie-db" -version = "1.9.3" -source = "git+https://github.com/paradigmxyz/reth?rev=27a8c0f5a6dfb27dea84c5751776ecabdd069646#27a8c0f5a6dfb27dea84c5751776ecabdd069646" +version = "2.1.0" +source = "git+https://github.com/paradigmxyz/reth?rev=8ebfaff134a973ea7b89f619a0562882e97b93c7#8ebfaff134a973ea7b89f619a0562882e97b93c7" dependencies = [ - "alloy-primitives 1.4.1", + "alloy-primitives 1.5.7", + "metrics", + "parking_lot", "reth-db-api", "reth-execution-errors", + "reth-metrics 2.1.0", "reth-primitives-traits", + "reth-stages-types", + "reth-storage-api", + "reth-storage-errors", "reth-trie", + "reth-trie-common", "tracing", ] [[package]] name = "reth-trie-parallel" -version = "1.9.3" -source = "git+https://github.com/paradigmxyz/reth?rev=27a8c0f5a6dfb27dea84c5751776ecabdd069646#27a8c0f5a6dfb27dea84c5751776ecabdd069646" +version = "2.1.0" +source = "git+https://github.com/paradigmxyz/reth?rev=8ebfaff134a973ea7b89f619a0562882e97b93c7#8ebfaff134a973ea7b89f619a0562882e97b93c7" dependencies = [ - "alloy-primitives 1.4.1", + "alloy-eip7928", + "alloy-evm", + "alloy-primitives 1.5.7", "alloy-rlp", "crossbeam-channel", - "dashmap 6.1.0", + "crossbeam-utils", "derive_more 2.1.0", "itertools 0.14.0", "metrics", "rayon", "reth-execution-errors", - "reth-metrics 1.9.3", + "reth-metrics 2.1.0", + "reth-primitives-traits", "reth-provider", "reth-storage-errors", + "reth-tasks 2.1.0", "reth-trie", - "reth-trie-common", - "reth-trie-sparse", + "revm-state", "thiserror 2.0.17", - "tokio", "tracing", ] [[package]] name = "reth-trie-sparse" -version = "1.9.3" -source = "git+https://github.com/paradigmxyz/reth?rev=27a8c0f5a6dfb27dea84c5751776ecabdd069646#27a8c0f5a6dfb27dea84c5751776ecabdd069646" +version = "2.1.0" +source = "git+https://github.com/paradigmxyz/reth?rev=8ebfaff134a973ea7b89f619a0562882e97b93c7#8ebfaff134a973ea7b89f619a0562882e97b93c7" dependencies = [ - "alloy-primitives 1.4.1", + "alloy-primitives 1.5.7", "alloy-rlp", - "alloy-trie 0.9.1", - "auto_impl", + "alloy-trie", "metrics", "rayon", "reth-execution-errors", - "reth-metrics 1.9.3", + "reth-metrics 2.1.0", "reth-primitives-traits", "reth-trie-common", - "smallvec", - "tracing", -] - -[[package]] -name = "reth-trie-sparse-parallel" -version = "1.9.3" -source = "git+https://github.com/paradigmxyz/reth?rev=27a8c0f5a6dfb27dea84c5751776ecabdd069646#27a8c0f5a6dfb27dea84c5751776ecabdd069646" -dependencies = [ - "alloy-primitives 1.4.1", - "alloy-rlp", - "alloy-trie 0.9.1", - "metrics", - "rayon", - "reth-execution-errors", - "reth-metrics 1.9.3", - "reth-trie-common", - "reth-trie-sparse", + "serde", + "serde_json", + "slotmap", "smallvec", "tracing", ] [[package]] name = "reth-zstd-compressors" -version = "1.9.3" -source = "git+https://github.com/paradigmxyz/reth?rev=27a8c0f5a6dfb27dea84c5751776ecabdd069646#27a8c0f5a6dfb27dea84c5751776ecabdd069646" +version = "0.3.1" +source = "git+https://github.com/paradigmxyz/reth-core?rev=afa5162668db00749b14bf30d06d3bed5c71aa4c#afa5162668db00749b14bf30d06d3bed5c71aa4c" dependencies = [ "zstd 0.13.3", ] [[package]] name = "revm" -version = "31.0.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bb67a5223602113cae59a305acde2d9936bc18f2478dda879a6124b267cebfb6" +version = "38.0.0" +source = "git+https://github.com/bluealloy/revm?rev=7ac2a4a922d70e73f7b45baa16ed996f479d6a41#7ac2a4a922d70e73f7b45baa16ed996f479d6a41" dependencies = [ "revm-bytecode", "revm-context", @@ -12618,9 +13334,8 @@ dependencies = [ [[package]] name = "revm-bytecode" -version = "7.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e2c6b5e6e8dd1e28a4a60e5f46615d4ef0809111c9e63208e55b5c7058200fb0" +version = "10.0.0" +source = "git+https://github.com/bluealloy/revm?rev=7ac2a4a922d70e73f7b45baa16ed996f479d6a41#7ac2a4a922d70e73f7b45baa16ed996f479d6a41" dependencies = [ "bitvec", "phf 0.13.1", @@ -12630,9 +13345,8 @@ dependencies = [ [[package]] name = "revm-context" -version = "11.0.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "92850e150f4f99d46c05a20ad0cd09286a7ad4ee21866fffb87101de6e602231" +version = "16.0.1" +source = "git+https://github.com/bluealloy/revm?rev=7ac2a4a922d70e73f7b45baa16ed996f479d6a41#7ac2a4a922d70e73f7b45baa16ed996f479d6a41" dependencies = [ "bitvec", "cfg-if", @@ -12647,9 +13361,8 @@ dependencies = [ [[package]] name = "revm-context-interface" -version = "12.0.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f6d701e2c2347d65216b066489ab22a0a8e1f7b2568256110d73a7d5eff3385c" +version = "17.0.1" +source = "git+https://github.com/bluealloy/revm?rev=7ac2a4a922d70e73f7b45baa16ed996f479d6a41#7ac2a4a922d70e73f7b45baa16ed996f479d6a41" dependencies = [ "alloy-eip2930", "alloy-eip7702", @@ -12663,11 +13376,10 @@ dependencies = [ [[package]] name = "revm-database" -version = "9.0.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "980d8d6bba78c5dd35b83abbb6585b0b902eb25ea4448ed7bfba6283b0337191" +version = "13.0.1" +source = "git+https://github.com/bluealloy/revm?rev=7ac2a4a922d70e73f7b45baa16ed996f479d6a41#7ac2a4a922d70e73f7b45baa16ed996f479d6a41" dependencies = [ - "alloy-eips", + "alloy-eips 2.0.4", "revm-bytecode", "revm-database-interface", "revm-primitives", @@ -12677,22 +13389,21 @@ dependencies = [ [[package]] name = "revm-database-interface" -version = "8.0.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8cce03e3780287b07abe58faf4a7f5d8be7e81321f93ccf3343c8f7755602bae" +version = "11.0.1" +source = "git+https://github.com/bluealloy/revm?rev=7ac2a4a922d70e73f7b45baa16ed996f479d6a41#7ac2a4a922d70e73f7b45baa16ed996f479d6a41" dependencies = [ "auto_impl", "either", "revm-primitives", "revm-state", "serde", + "thiserror 2.0.17", ] [[package]] name = "revm-handler" -version = "12.0.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b45418ed95cfdf0cb19effdbb7633cf2144cab7fb0e6ffd6b0eb9117a50adff6" +version = "18.1.0" +source = "git+https://github.com/bluealloy/revm?rev=7ac2a4a922d70e73f7b45baa16ed996f479d6a41#7ac2a4a922d70e73f7b45baa16ed996f479d6a41" dependencies = [ "auto_impl", "derive-where", @@ -12709,9 +13420,8 @@ dependencies = [ [[package]] name = "revm-inspector" -version = "12.0.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c99801eac7da06cc112df2244bd5a64024f4ef21240e923b26e73c4b4a0e5da6" +version = "19.0.0" +source = "git+https://github.com/bluealloy/revm?rev=7ac2a4a922d70e73f7b45baa16ed996f479d6a41#7ac2a4a922d70e73f7b45baa16ed996f479d6a41" dependencies = [ "auto_impl", "either", @@ -12727,12 +13437,11 @@ dependencies = [ [[package]] name = "revm-inspectors" -version = "0.32.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "21caa99f22184a6818946362778cccd3ff02f743c1e085bee87700671570ecb7" +version = "0.39.0" +source = "git+https://github.com/paradigmxyz/revm-inspectors?rev=1c2e997a33baa698decdaaba5f14326fc40dfee6#1c2e997a33baa698decdaaba5f14326fc40dfee6" dependencies = [ - "alloy-primitives 1.4.1", - "alloy-rpc-types-eth", + "alloy-primitives 1.5.7", + "alloy-rpc-types-eth 2.0.4", "alloy-rpc-types-trace", "alloy-sol-types", "anstyle", @@ -12747,9 +13456,8 @@ dependencies = [ [[package]] name = "revm-interpreter" -version = "29.0.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "22789ce92c5808c70185e3bc49732f987dc6fd907f77828c8d3470b2299c9c65" +version = "35.0.1" +source = "git+https://github.com/bluealloy/revm?rev=7ac2a4a922d70e73f7b45baa16ed996f479d6a41#7ac2a4a922d70e73f7b45baa16ed996f479d6a41" dependencies = [ "revm-bytecode", "revm-context-interface", @@ -12760,9 +13468,8 @@ dependencies = [ [[package]] name = "revm-precompile" -version = "29.0.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "968b124028960201abf6d6bf8e223f15fadebb4307df6b7dc9244a0aab5d2d05" +version = "34.0.0" +source = "git+https://github.com/bluealloy/revm?rev=7ac2a4a922d70e73f7b45baa16ed996f479d6a41#7ac2a4a922d70e73f7b45baa16ed996f479d6a41" dependencies = [ "ark-bls12-381", "ark-bn254", @@ -12771,36 +13478,35 @@ dependencies = [ "ark-serialize 0.5.0", "arrayref", "aurora-engine-modexp", + "aws-lc-rs", "blst", "c-kzg", "cfg-if", "k256 0.13.4", "p256", + "revm-context-interface", "revm-primitives", "ripemd", - "rug", "secp256k1 0.31.1", "sha2 0.10.9", ] [[package]] name = "revm-primitives" -version = "21.0.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "29e161db429d465c09ba9cbff0df49e31049fe6b549e28eb0b7bd642fcbd4412" +version = "23.0.0" +source = "git+https://github.com/bluealloy/revm?rev=7ac2a4a922d70e73f7b45baa16ed996f479d6a41#7ac2a4a922d70e73f7b45baa16ed996f479d6a41" dependencies = [ - "alloy-primitives 1.4.1", - "num_enum", + "alloy-primitives 1.5.7", "once_cell", "serde", ] [[package]] name = "revm-state" -version = "8.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7d8be953b7e374dbdea0773cf360debed8df394ea8d82a8b240a6b5da37592fc" +version = "11.0.1" +source = "git+https://github.com/bluealloy/revm?rev=7ac2a4a922d70e73f7b45baa16ed996f479d6a41#7ac2a4a922d70e73f7b45baa16ed996f479d6a41" dependencies = [ + "alloy-eip7928", "bitflags 2.10.0", "revm-bytecode", "revm-primitives", @@ -12838,15 +13544,15 @@ dependencies = [ "cfg-if", "getrandom 0.2.16", "libc", - "untrusted", + "untrusted 0.9.0", "windows-sys 0.52.0", ] [[package]] name = "ringbuffer" -version = "0.15.0" +version = "0.16.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3df6368f71f205ff9c33c076d170dd56ebf68e8161c733c0caa07a7a5509ed53" +checksum = "57b0b88a509053cbfd535726dcaaceee631313cef981266119527a1d110f6d2b" [[package]] name = "ripemd" @@ -12912,14 +13618,24 @@ dependencies = [ [[package]] name = "roaring" -version = "0.10.12" +version = "0.11.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "19e8d2cfa184d94d0726d650a9f4a1be7f9b76ac9fdb954219878dc00c1c1e7b" +checksum = "1dedc5658c6ecb3bdb5ef5f3295bb9253f42dcf3fd1402c03f6b1f7659c3c4a9" dependencies = [ "bytemuck", "byteorder", ] +[[package]] +name = "rocksdb" +version = "0.24.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ddb7af00d2b17dbd07d82c0063e25411959748ff03e8d4f96134c2ff41fce34f" +dependencies = [ + "libc", + "librocksdb-sys", +] + [[package]] name = "rolling-file" version = "0.2.0" @@ -12935,6 +13651,15 @@ version = "0.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "afab94fb28594581f62d981211a9a4d53cc8130bbcbbb89a0440d9b8e81a7746" +[[package]] +name = "rpds" +version = "0.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b4ef5140bcb576bfd6d56cd2de709a7d17851ac1f3805e67fe9d99e42a11821f" +dependencies = [ + "archery 0.4.0", +] + [[package]] name = "rsa" version = "0.9.9" @@ -12955,18 +13680,6 @@ dependencies = [ "zeroize", ] -[[package]] -name = "rug" -version = "1.28.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "58ad2e973fe3c3214251a840a621812a4f40468da814b1a3d6947d433c2af11f" -dependencies = [ - "az", - "gmp-mpfr-sys", - "libc", - "libm", -] - [[package]] name = "ruint" version = "1.17.0" @@ -13037,6 +13750,23 @@ dependencies = [ "syn 0.15.44", ] +[[package]] +name = "rust_eth_kzg" +version = "0.9.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1522b7a740cd7f5bc52ea49863618511c8de138dcdf3f8a80b15b3f764942a5b" +dependencies = [ + "eip4844", + "ekzg-bls12-381", + "ekzg-erasure-codes", + "ekzg-multi-open", + "ekzg-serialization", + "ekzg-trusted-setup", + "hex", + "serde", + "serde_json", +] + [[package]] name = "rustc-hash" version = "1.1.0" @@ -13085,19 +13815,6 @@ dependencies = [ "semver 1.0.27", ] -[[package]] -name = "rustix" -version = "0.38.44" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fdb5bc1ae2baa591800df16c9ca78619bf65c0488b41b96ccec5d11220d8c154" -dependencies = [ - "bitflags 2.10.0", - "errno", - "libc", - "linux-raw-sys 0.4.15", - "windows-sys 0.59.0", -] - [[package]] name = "rustix" version = "1.1.2" @@ -13107,7 +13824,7 @@ dependencies = [ "bitflags 2.10.0", "errno", "libc", - "linux-raw-sys 0.11.0", + "linux-raw-sys", "windows-sys 0.61.2", ] @@ -13129,6 +13846,7 @@ version = "0.23.35" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "533f54bc6a7d4f647e46ad909549eda97bf5afc1585190ef692b4286b198bd8f" dependencies = [ + "aws-lc-rs", "log", "once_cell", "ring", @@ -13202,6 +13920,27 @@ dependencies = [ "windows-sys 0.59.0", ] +[[package]] +name = "rustls-platform-verifier" +version = "0.6.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1d99feebc72bae7ab76ba994bb5e121b8d83d910ca40b36e0921f53becc41784" +dependencies = [ + "core-foundation 0.10.1", + "core-foundation-sys", + "jni", + "log", + "once_cell", + "rustls 0.23.35", + "rustls-native-certs 0.8.2", + "rustls-platform-verifier-android", + "rustls-webpki 0.103.8", + "security-framework 3.5.1", + "security-framework-sys", + "webpki-root-certs 1.0.4", + "windows-sys 0.61.2", +] + [[package]] name = "rustls-platform-verifier-android" version = "0.1.1" @@ -13215,7 +13954,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8b6275d1ee7a1cd780b64aca7726599a1dbc893b1e64144529e55c3c2f745765" dependencies = [ "ring", - "untrusted", + "untrusted 0.9.0", ] [[package]] @@ -13224,9 +13963,10 @@ version = "0.103.8" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2ffdfa2f5286e2247234e03f680868ac2815974dc39e00ea15adc445d0aafe52" dependencies = [ + "aws-lc-rs", "ring", "rustls-pki-types", - "untrusted", + "untrusted 0.9.0", ] [[package]] @@ -13259,6 +13999,21 @@ version = "1.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "dd29631678d6fb0903b69223673e122c32e9ae559d0960a38d574695ebc0ea15" +[[package]] +name = "safe_arch" +version = "0.7.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "96b02de82ddbe1b636e6170c21be622223aea188ef2e139be0a5b219ec215323" +dependencies = [ + "bytemuck", +] + +[[package]] +name = "safe_arith" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b147bb6111014916d3ef9d4c85173124a8e12193a67f6176d67244afd558d6c1" + [[package]] name = "same-file" version = "1.0.6" @@ -13372,7 +14127,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "da046153aa2352493d6cb7da4b6e5c0c057d8a1d0a9aa8560baffdd945acd414" dependencies = [ "ring", - "untrusted", + "untrusted 0.9.0", ] [[package]] @@ -13616,6 +14371,17 @@ dependencies = [ "serde_core", ] +[[package]] +name = "serde_path_to_error" +version = "0.1.20" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "10a9ff822e371bb5403e391ecd83e182e0e77ba7f6fe0160b795797109d1b457" +dependencies = [ + "itoa", + "serde", + "serde_core", +] + [[package]] name = "serde_qs" version = "0.8.5" @@ -13636,6 +14402,15 @@ dependencies = [ "serde", ] +[[package]] +name = "serde_spanned" +version = "1.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6662b5879511e06e8999a8a235d848113e942c9124f211511b16466ee2995f26" +dependencies = [ + "serde_core", +] + [[package]] name = "serde_urlencoded" version = "0.7.1" @@ -13718,7 +14493,7 @@ checksum = "99cd6713db3cf16b6c84e06321e049a9b9f699826e16096d23bbcc44d15d51a6" dependencies = [ "block-buffer 0.9.0", "cfg-if", - "cpufeatures", + "cpufeatures 0.2.17", "digest 0.9.0", "opaque-debug", ] @@ -13730,7 +14505,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e3bf829a2d51ab4a5ddf1352d8470c140cadc8301b2ae1789db023f01cedd6ba" dependencies = [ "cfg-if", - "cpufeatures", + "cpufeatures 0.2.17", "digest 0.10.7", ] @@ -13748,7 +14523,7 @@ checksum = "4d58a1e1bf39749807d89cf2d98ac2dfa0ff1cb3faa38fbb64dd88ac8013d800" dependencies = [ "block-buffer 0.9.0", "cfg-if", - "cpufeatures", + "cpufeatures 0.2.17", "digest 0.9.0", "opaque-debug", ] @@ -13760,7 +14535,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a7507d819769d01a365ab707794a4084392c824f54a7a6a7862f8c3d0892b283" dependencies = [ "cfg-if", - "cpufeatures", + "cpufeatures 0.2.17", "digest 0.10.7", "sha2-asm", ] @@ -13786,9 +14561,9 @@ dependencies = [ [[package]] name = "sha3-asm" -version = "0.1.4" +version = "0.1.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c28efc5e327c837aa837c59eae585fc250715ef939ac32881bcc11677cd02d46" +checksum = "59cbb88c189d6352cc8ae96a39d19c7ecad8f7330b29461187f2587fdc2988d5" dependencies = [ "cc", "cfg-if", @@ -13904,21 +14679,6 @@ version = "1.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "56199f7ddabf13fe5074ce809e7d3f42b42ae711800501b5b16ea82ad029c39d" -[[package]] -name = "skeptic" -version = "0.13.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "16d23b015676c90a0f01c197bfdc786c20342c73a0afdda9025adb0bc42940a8" -dependencies = [ - "bytecount", - "cargo_metadata 0.14.2", - "error-chain", - "glob", - "pulldown-cmark", - "tempfile", - "walkdir", -] - [[package]] name = "sketches-ddsketch" version = "0.3.0" @@ -13931,6 +14691,15 @@ version = "0.4.11" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7a2ae44ef20feb57a68b23d846850f861394c2e02dc425a50098ae8c90267589" +[[package]] +name = "slotmap" +version = "1.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bdd58c3c93c3d278ca835519292445cb4b0d4dc59ccfdf7ceadaab3f8aeb4038" +dependencies = [ + "version_check 0.9.5", +] + [[package]] name = "small_btree" version = "0.1.0" @@ -13979,12 +14748,12 @@ dependencies = [ [[package]] name = "socket2" -version = "0.6.1" +version = "0.6.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "17129e116933cf371d018bb80ae557e889637989d8638274fb25622827b03881" +checksum = "3a766e1110788c36f4fa1c2b71b387a7815aa65f88ce0229841826633d93723e" dependencies = [ "libc", - "windows-sys 0.60.2", + "windows-sys 0.61.2", ] [[package]] @@ -14332,6 +15101,24 @@ dependencies = [ "typenum", ] +[[package]] +name = "ssz_types" +version = "0.14.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d625e4de8e0057eefe7e0b1510ba1dd7adf10cd375fad6cc7fcceac7c39623c9" +dependencies = [ + "context_deserialize", + "educe", + "ethereum_serde_utils 0.8.0", + "ethereum_ssz 0.10.1", + "itertools 0.14.0", + "serde", + "serde_derive", + "smallvec", + "tree_hash 0.12.1", + "typenum", +] + [[package]] name = "stable_deref_trait" version = "1.2.1" @@ -14478,6 +15265,30 @@ version = "2.6.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "13c2bddecc57b384dee18652358fb23172facb8a2c51ccc10d74c157bdea3292" +[[package]] +name = "superstruct" +version = "0.10.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bae4a9ccd7882533c1f210e400763ec6ee64c390fc12248c238276281863719e" +dependencies = [ + "darling 0.23.0", + "itertools 0.14.0", + "proc-macro2 1.0.103", + "quote 1.0.42", + "smallvec", + "syn 2.0.111", +] + +[[package]] +name = "swap_or_not_shuffle" +version = "0.2.0" +source = "git+https://github.com/sigp/lighthouse?rev=27cfa18c17e148fb75827d0ea3c9a2c69db0aae0#27cfa18c17e148fb75827d0ea3c9a2c69db0aae0" +dependencies = [ + "alloy-primitives 1.5.7", + "ethereum_hashing 0.8.0", + "fixed_bytes", +] + [[package]] name = "syn" version = "0.15.44" @@ -14513,9 +15324,9 @@ dependencies = [ [[package]] name = "syn-solidity" -version = "1.4.1" +version = "1.5.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ff790eb176cc81bb8936aed0f7b9f14fc4670069a2d371b3e3b0ecce908b2cb3" +checksum = "53f425ae0b12e2f5ae65542e00898d500d4d318b4baf09f40fd0d410454e9947" dependencies = [ "paste", "proc-macro2 1.0.103", @@ -14589,11 +15400,25 @@ dependencies = [ "windows 0.57.0", ] +[[package]] +name = "sysinfo" +version = "0.38.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "92ab6a2f8bfe508deb3c6406578252e491d299cbbf3bc0529ecc3313aee4a52f" +dependencies = [ + "libc", + "memchr", + "ntapi", + "objc2-core-foundation", + "objc2-io-kit", + "windows 0.62.2", +] + [[package]] name = "sysperf" version = "0.1.0" dependencies = [ - "alloy-primitives 1.4.1", + "alloy-primitives 1.5.7", "rand 0.8.5", "rayon", "sysinfo 0.33.1", @@ -14607,18 +15432,7 @@ checksum = "ba3a3adc5c275d719af8cb4272ea1c4a6d668a777f37e115f6d11ddbc1c8e0e7" dependencies = [ "bitflags 1.3.2", "core-foundation 0.9.4", - "system-configuration-sys 0.5.0", -] - -[[package]] -name = "system-configuration" -version = "0.6.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3c879d448e9d986b661742763247d3693ed13609438cf3d006f51f5368a5ba6b" -dependencies = [ - "bitflags 2.10.0", - "core-foundation 0.9.4", - "system-configuration-sys 0.6.0", + "system-configuration-sys", ] [[package]] @@ -14631,16 +15445,6 @@ dependencies = [ "libc", ] -[[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 = "tag_ptr" version = "0.1.0" @@ -14685,7 +15489,7 @@ dependencies = [ "fastrand 2.3.0", "getrandom 0.3.4", "once_cell", - "rustix 1.1.2", + "rustix", "windows-sys 0.61.2", ] @@ -14711,14 +15515,14 @@ name = "test-relay" version = "0.1.0" dependencies = [ "ahash", - "alloy-consensus", - "alloy-json-rpc", - "alloy-primitives 1.4.1", + "alloy-consensus 2.0.4", + "alloy-json-rpc 2.0.4", + "alloy-primitives 1.5.7", "alloy-provider", "alloy-rpc-types-beacon", "clap", "ctor", - "ethereum_ssz 0.9.1", + "ethereum_ssz 0.10.1", "eyre", "flate2", "lazy_static", @@ -14740,6 +15544,15 @@ dependencies = [ "warp", ] +[[package]] +name = "test_random_derive" +version = "0.2.0" +source = "git+https://github.com/sigp/lighthouse?rev=27cfa18c17e148fb75827d0ea3c9a2c69db0aae0#27cfa18c17e148fb75827d0ea3c9a2c69db0aae0" +dependencies = [ + "quote 1.0.42", + "syn 2.0.111", +] + [[package]] name = "test_utils" version = "0.1.0" @@ -14795,6 +15608,20 @@ dependencies = [ "syn 2.0.111", ] +[[package]] +name = "thread-priority" +version = "3.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2210811179577da3d54eb69ab0b50490ee40491a25d95b8c6011ba40771cb721" +dependencies = [ + "bitflags 2.10.0", + "cfg-if", + "libc", + "log", + "rustversion", + "windows 0.61.3", +] + [[package]] name = "thread_local" version = "1.1.9" @@ -14846,9 +15673,9 @@ dependencies = [ [[package]] name = "time" -version = "0.3.44" +version = "0.3.47" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "91e7d9e3bb61134e77bde20dd4825b97c010155709965fedf0f49bb138e52a9d" +checksum = "743bd48c283afc0388f9b8827b976905fb217ad9e647fae3a379a9283c4def2c" dependencies = [ "deranged", "itoa", @@ -14857,22 +15684,22 @@ dependencies = [ "num-conv", "num_threads", "powerfmt", - "serde", + "serde_core", "time-core", "time-macros", ] [[package]] name = "time-core" -version = "0.1.6" +version = "0.1.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "40868e7c1d2f0b8d73e4a8c7f0ff63af4f6d19be117e90bd73eb1d62cf831c6b" +checksum = "7694e1cfe791f8d31026952abf09c69ca6f6fa4e1a1229e18988f06a04a12dca" [[package]] name = "time-macros" -version = "0.2.24" +version = "0.2.27" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "30cfb0125f12d9c277f35663a0a33f8c30190f4e4574868a330595412d34ebf3" +checksum = "2e70e4c5a0e0a8a4823ad65dfe1a6930e4f4d756dcd9dd7939022b5e8c501215" dependencies = [ "num-conv", "time-core", @@ -14931,9 +15758,9 @@ checksum = "1f3ccbac311fea05f86f61904b462b55fb3df8837a366dfc601a0161d0532f20" [[package]] name = "tokio" -version = "1.48.0" +version = "1.52.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ff360e02eab121e0bc37a2d3b4d4dc622e6eda3a8e5253d5435ecf5bd4c68408" +checksum = "8fc7f01b389ac15039e4dc9531aa973a135d7a4135281b12d7c1bc79fd57fffe" dependencies = [ "bytes", "libc", @@ -14941,16 +15768,16 @@ dependencies = [ "parking_lot", "pin-project-lite", "signal-hook-registry", - "socket2 0.6.1", + "socket2 0.6.3", "tokio-macros", "windows-sys 0.61.2", ] [[package]] name = "tokio-macros" -version = "2.6.0" +version = "2.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "af407857209536a95c8e56f8231ef2c2e2aff839b22e07a1ffcbc617e9db9fa5" +checksum = "385a6cb71ab9ab790c5fe8d67f1645e6c450a7ce006a33de03daa956cf70a496" dependencies = [ "proc-macro2 1.0.103", "quote 1.0.42", @@ -15025,6 +15852,22 @@ dependencies = [ "tokio", "tokio-rustls 0.26.4", "tungstenite 0.26.2", +] + +[[package]] +name = "tokio-tungstenite" +version = "0.28.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d25a406cddcc431a75d3d9afc6a7c0f7428d4891dd973e4d54c56b46127bf857" +dependencies = [ + "futures-util", + "log", + "rustls 0.23.35", + "rustls-native-certs 0.8.2", + "rustls-pki-types", + "tokio", + "tokio-rustls 0.26.4", + "tungstenite 0.28.0", "webpki-roots 0.26.11", ] @@ -15059,11 +15902,26 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "dc1beb996b9d83529a9e75c17a1686767d148d70663143c7854d8b4a09ced362" dependencies = [ "serde", - "serde_spanned", + "serde_spanned 0.6.9", "toml_datetime 0.6.11", "toml_edit 0.22.27", ] +[[package]] +name = "toml" +version = "0.9.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f0dc8b1fb61449e27716ec0e1bdf0f6b8f3e8f6b05391e8497b8b6d7804ea6d8" +dependencies = [ + "indexmap 2.12.1", + "serde_core", + "serde_spanned 1.1.1", + "toml_datetime 0.7.3", + "toml_parser", + "toml_writer", + "winnow", +] + [[package]] name = "toml_datetime" version = "0.6.11" @@ -15090,7 +15948,7 @@ checksum = "41fe8c660ae4257887cf66394862d21dbca4a6ddd26f04a3560410406a2f819a" dependencies = [ "indexmap 2.12.1", "serde", - "serde_spanned", + "serde_spanned 0.6.9", "toml_datetime 0.6.11", "toml_write", "winnow", @@ -15123,6 +15981,12 @@ version = "0.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5d99f8c9a7727884afe522e9bd5edbfc91a3312b36a77b5fb8926e4c31a41801" +[[package]] +name = "toml_writer" +version = "1.1.1+spec-1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "756daf9b1013ebe47a8776667b466417e2d4c5679d441c26230efd9ef78692db" + [[package]] name = "tonic" version = "0.13.1" @@ -15130,7 +15994,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7e581ba15a835f4d9ea06c55ab1bd4dce26fc53752c69a04aac00703bfb49ba9" dependencies = [ "async-trait", - "axum", + "axum 0.8.7", "base64 0.22.1", "bytes", "h2 0.4.12", @@ -15240,9 +16104,9 @@ dependencies = [ [[package]] name = "tower-http" -version = "0.6.7" +version = "0.6.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9cf146f99d442e8e68e585f5d798ccd3cad9a7835b917e09728880a862706456" +checksum = "d4e6559d53cc268e5031cd8429d05415bc4cb4aefc4aa5d6cc35fbf5b924a1f8" dependencies = [ "async-compression", "base64 0.22.1", @@ -15360,9 +16224,9 @@ dependencies = [ [[package]] name = "tracing-logfmt" -version = "0.3.5" +version = "0.3.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6b1f47d22deb79c3f59fcf2a1f00f60cbdc05462bf17d1cd356c1fefa3f444bd" +checksum = "a250055a3518b5efba928a18ffac8d32d42ea607a9affff4532144cd5b2e378e" dependencies = [ "time", "tracing", @@ -15389,6 +16253,22 @@ dependencies = [ "web-time", ] +[[package]] +name = "tracing-samply" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c175f7ecc002b6ef04776a39f440503e4e788790ddbdbfac8259b7a069526334" +dependencies = [ + "cfg-if", + "itoa", + "libc", + "mach2", + "memmap2 0.9.9", + "smallvec", + "tracing-core", + "tracing-subscriber 0.3.22", +] + [[package]] name = "tracing-serde" version = "0.2.0" @@ -15436,19 +16316,19 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "373495c23db675a5192de8b610395e1bec324d596f9e6111192ce903dc11403a" dependencies = [ "alloy-primitives 0.8.26", - "ethereum_hashing", + "ethereum_hashing 0.7.0", "smallvec", ] [[package]] name = "tree_hash" -version = "0.10.0" +version = "0.12.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ee44f4cef85f88b4dea21c0b1f58320bdf35715cf56d840969487cff00613321" +checksum = "f7fd51aa83d2eb83b04570808430808b5d24fdbf479a4d5ac5dee4a2e2dd2be4" dependencies = [ - "alloy-primitives 1.4.1", - "ethereum_hashing", - "ethereum_ssz 0.9.1", + "alloy-primitives 1.5.7", + "ethereum_hashing 0.8.0", + "ethereum_ssz 0.10.1", "smallvec", "typenum", ] @@ -15467,11 +16347,11 @@ dependencies = [ [[package]] name = "tree_hash_derive" -version = "0.10.0" +version = "0.12.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0bee2ea1551f90040ab0e34b6fb7f2fa3bad8acc925837ac654f2c78a13e3089" +checksum = "8840ad4d852e325d3afa7fde8a50b2412f89dce47d7eb291c0cc7f87cd040f38" dependencies = [ - "darling 0.20.11", + "darling 0.23.0", "proc-macro2 1.0.103", "quote 1.0.42", "syn 2.0.111", @@ -15492,6 +16372,10 @@ name = "triomphe" version = "0.1.15" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "dd69c5aa8f924c7519d6372789a74eac5b94fb0f8fcf0d4a97eb0bfc3e785f39" +dependencies = [ + "serde", + "stable_deref_trait", +] [[package]] name = "try-lock" @@ -15537,18 +16421,90 @@ dependencies = [ "utf-8", ] +[[package]] +name = "tungstenite" +version = "0.28.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8628dcc84e5a09eb3d8423d6cb682965dea9133204e8fb3efee74c2a0c259442" +dependencies = [ + "bytes", + "data-encoding", + "http 1.4.0", + "httparse", + "log", + "rand 0.9.2", + "rustls 0.23.35", + "rustls-pki-types", + "sha1", + "thiserror 2.0.17", + "utf-8", +] + [[package]] name = "twox-hash" version = "2.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9ea3136b675547379c4bd395ca6b938e5ad3c3d20fad76e7fe85f9e0d011419c" +[[package]] +name = "typeid" +version = "1.0.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bc7d623258602320d5c55d1bc22793b57daff0ec7efc270ea7d55ce1d5f5471c" + [[package]] name = "typenum" version = "1.19.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "562d481066bde0658276a35467c4af00bdc6ee726305698a55b86e61d7ad82bb" +[[package]] +name = "types" +version = "0.2.1" +source = "git+https://github.com/sigp/lighthouse?rev=27cfa18c17e148fb75827d0ea3c9a2c69db0aae0#27cfa18c17e148fb75827d0ea3c9a2c69db0aae0" +dependencies = [ + "alloy-primitives 1.5.7", + "alloy-rlp", + "bls", + "compare_fields", + "context_deserialize", + "educe", + "eth2_interop_keypairs", + "ethereum_hashing 0.8.0", + "ethereum_serde_utils 0.8.0", + "ethereum_ssz 0.10.1", + "ethereum_ssz_derive 0.10.1", + "fixed_bytes", + "hex", + "int_to_bytes", + "itertools 0.14.0", + "kzg", + "maplit", + "merkle_proof", + "metastruct", + "milhouse", + "parking_lot", + "rand 0.9.2", + "rand_xorshift 0.4.0", + "rayon", + "regex", + "rpds", + "safe_arith", + "serde", + "serde_json", + "smallvec", + "ssz_types 0.14.1", + "superstruct", + "swap_or_not_shuffle", + "tempfile", + "test_random_derive", + "tracing", + "tree_hash 0.12.1", + "tree_hash_derive 0.12.1", + "typenum", + "yaml_serde", +] + [[package]] name = "ucd-trie" version = "0.1.7" @@ -15626,21 +16582,15 @@ checksum = "f6ccf251212114b54433ec949fd6a7841275f9ada20dddd2f29e9ceea4501493" [[package]] name = "unicode-truncate" -version = "1.1.0" +version = "2.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b3644627a5af5fa321c95b9b235a72fd24cd29c648c2c379431e6628655627bf" +checksum = "16b380a1238663e5f8a691f9039c73e1cdae598a30e9855f541d29b08b53e9a5" dependencies = [ - "itertools 0.13.0", + "itertools 0.14.0", "unicode-segmentation", - "unicode-width 0.1.14", + "unicode-width", ] -[[package]] -name = "unicode-width" -version = "0.1.14" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7dd6e30e90baa6f72411720665d41d89b9a3d039dc45b8faea1ddd07f617f6af" - [[package]] name = "unicode-width" version = "0.2.0" @@ -15687,6 +16637,12 @@ version = "0.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "eb066959b24b5196ae73cb057f45598450d2c5f71460e98c49b738086eff9c06" +[[package]] +name = "untrusted" +version = "0.7.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a156c684c91ea7d62626509bce3cb4e1d9ed5c4d978f7b4352658f96a4c26b4a" + [[package]] name = "untrusted" version = "0.9.0" @@ -15776,14 +16732,20 @@ version = "0.2.15" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "accd4ea62f7bb7a82fe23066fb0957d48ef677f6eeb8215f372f52e48bb32426" +[[package]] +name = "vec_map" +version = "0.8.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f1bddf1187be692e79c5ffeab891132dfb0f236ed36a43c7ed39f1165ee20191" + [[package]] name = "vergen" -version = "9.0.6" +version = "9.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6b2bf58be11fc9414104c6d3a2e464163db5ef74b12296bda593cac37b6e4777" +checksum = "b849a1f6d8639e8de261e81ee0fc881e3e3620db1af9f2e0da015d4382ceaf75" dependencies = [ "anyhow", - "cargo_metadata 0.19.2", + "cargo_metadata", "derive_builder", "regex", "rustversion", @@ -15793,9 +16755,9 @@ dependencies = [ [[package]] name = "vergen-git2" -version = "1.0.7" +version = "9.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4f6ee511ec45098eabade8a0750e76eec671e7fb2d9360c563911336bea9cac1" +checksum = "d51ab55ddf1188c8d679f349775362b0fa9e90bd7a4ac69838b2a087623f0d57" dependencies = [ "anyhow", "derive_builder", @@ -15808,9 +16770,9 @@ dependencies = [ [[package]] name = "vergen-lib" -version = "0.1.6" +version = "9.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9b07e6010c0f3e59fcb164e0163834597da68d1f864e2b8ca49f74de01e9c166" +checksum = "b34a29ba7e9c59e62f229ae1932fb1b8fb8a6fdcc99215a641913f5f5a59a569" dependencies = [ "anyhow", "derive_builder", @@ -15921,7 +16883,16 @@ version = "1.0.1+wasi-0.2.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0562428422c63773dad2c345a1882263bbf4d65cf3f42e90921f787ef5ad58e7" dependencies = [ - "wit-bindgen", + "wit-bindgen 0.46.0", +] + +[[package]] +name = "wasip3" +version = "0.4.0+wasi-0.3.0-rc-2026-01-06" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5428f8bf88ea5ddc08faddef2ac4a67e390b88186c703ce6dbd955e1c145aca5" +dependencies = [ + "wit-bindgen 0.51.0", ] [[package]] @@ -15932,9 +16903,9 @@ checksum = "b8dad83b4f25e74f184f64c43b150b91efe7647395b42289f38e50566d82855b" [[package]] name = "wasm-bindgen" -version = "0.2.106" +version = "0.2.118" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0d759f433fa64a2d763d1340820e46e111a7a5ab75f993d1852d70b03dbb80fd" +checksum = "0bf938a0bacb0469e83c1e148908bd7d5a6010354cf4fb73279b7447422e3a89" dependencies = [ "cfg-if", "once_cell", @@ -15945,22 +16916,19 @@ dependencies = [ [[package]] name = "wasm-bindgen-futures" -version = "0.4.56" +version = "0.4.68" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "836d9622d604feee9e5de25ac10e3ea5f2d65b41eac0d9ce72eb5deae707ce7c" +checksum = "f371d383f2fb139252e0bfac3b81b265689bf45b6874af544ffa4c975ac1ebf8" dependencies = [ - "cfg-if", "js-sys", - "once_cell", "wasm-bindgen", - "web-sys", ] [[package]] name = "wasm-bindgen-macro" -version = "0.2.106" +version = "0.2.118" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "48cb0d2638f8baedbc542ed444afc0644a29166f1595371af4fecf8ce1e7eeb3" +checksum = "eeff24f84126c0ec2db7a449f0c2ec963c6a49efe0698c4242929da037ca28ed" dependencies = [ "quote 1.0.42", "wasm-bindgen-macro-support", @@ -15968,9 +16936,9 @@ dependencies = [ [[package]] name = "wasm-bindgen-macro-support" -version = "0.2.106" +version = "0.2.118" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cefb59d5cd5f92d9dcf80e4683949f15ca4b511f4ac0a6e14d4e1ac60c6ecd40" +checksum = "9d08065faf983b2b80a79fd87d8254c409281cf7de75fc4b773019824196c904" dependencies = [ "bumpalo", "proc-macro2 1.0.103", @@ -15981,13 +16949,35 @@ dependencies = [ [[package]] name = "wasm-bindgen-shared" -version = "0.2.106" +version = "0.2.118" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cbc538057e648b67f72a982e708d485b2efa771e1ac05fec311f9f63e5800db4" +checksum = "5fd04d9e306f1907bd13c6361b5c6bfc7b3b3c095ed3f8a9246390f8dbdee129" dependencies = [ "unicode-ident", ] +[[package]] +name = "wasm-encoder" +version = "0.244.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "990065f2fe63003fe337b932cfb5e3b80e0b4d0f5ff650e6985b1048f62c8319" +dependencies = [ + "leb128fmt", + "wasmparser", +] + +[[package]] +name = "wasm-metadata" +version = "0.244.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bb0e353e6a2fbdc176932bbaab493762eb1255a7900fe0fea1a2f96c296cc909" +dependencies = [ + "anyhow", + "indexmap 2.12.1", + "wasm-encoder", + "wasmparser", +] + [[package]] name = "wasm-streams" version = "0.4.2" @@ -16001,6 +16991,31 @@ dependencies = [ "web-sys", ] +[[package]] +name = "wasm-streams" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9d1ec4f6517c9e11ae630e200b2b65d193279042e28edd4a2cda233e46670bbb" +dependencies = [ + "futures-util", + "js-sys", + "wasm-bindgen", + "wasm-bindgen-futures", + "web-sys", +] + +[[package]] +name = "wasmparser" +version = "0.244.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "47b807c72e1bac69382b3a6fb3dbe8ea4c0ed87ff5629b8685ae6b9a611028fe" +dependencies = [ + "bitflags 2.10.0", + "hashbrown 0.15.5", + "indexmap 2.12.1", + "semver 1.0.27", +] + [[package]] name = "wasmtimer" version = "0.4.3" @@ -16017,9 +17032,9 @@ dependencies = [ [[package]] name = "web-sys" -version = "0.3.83" +version = "0.3.95" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9b32828d774c412041098d182a8b38b16ea816958e07cf40eec2bc080ae137ac" +checksum = "4f2dfbb17949fa2088e5d39408c48368947b86f7834484e87b73de55bc14d97d" dependencies = [ "js-sys", "wasm-bindgen", @@ -16087,6 +17102,16 @@ dependencies = [ "wasite", ] +[[package]] +name = "wide" +version = "0.7.33" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0ce5da8ecb62bcd8ec8b7ea19f69a51275e91299be594ea5cc6ef7819e16cd03" +dependencies = [ + "bytemuck", + "safe_arch", +] + [[package]] name = "widestring" version = "1.2.1" @@ -16709,6 +17734,94 @@ version = "0.46.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f17a85883d4e6d00e8a97c586de764dabcc06133f7f1d55dce5cdc070ad7fe59" +[[package]] +name = "wit-bindgen" +version = "0.51.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d7249219f66ced02969388cf2bb044a09756a083d0fab1e566056b04d9fbcaa5" +dependencies = [ + "wit-bindgen-rust-macro", +] + +[[package]] +name = "wit-bindgen-core" +version = "0.51.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ea61de684c3ea68cb082b7a88508a8b27fcc8b797d738bfc99a82facf1d752dc" +dependencies = [ + "anyhow", + "heck 0.5.0", + "wit-parser", +] + +[[package]] +name = "wit-bindgen-rust" +version = "0.51.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b7c566e0f4b284dd6561c786d9cb0142da491f46a9fbed79ea69cdad5db17f21" +dependencies = [ + "anyhow", + "heck 0.5.0", + "indexmap 2.12.1", + "prettyplease", + "syn 2.0.111", + "wasm-metadata", + "wit-bindgen-core", + "wit-component", +] + +[[package]] +name = "wit-bindgen-rust-macro" +version = "0.51.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0c0f9bfd77e6a48eccf51359e3ae77140a7f50b1e2ebfe62422d8afdaffab17a" +dependencies = [ + "anyhow", + "prettyplease", + "proc-macro2 1.0.103", + "quote 1.0.42", + "syn 2.0.111", + "wit-bindgen-core", + "wit-bindgen-rust", +] + +[[package]] +name = "wit-component" +version = "0.244.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9d66ea20e9553b30172b5e831994e35fbde2d165325bec84fc43dbf6f4eb9cb2" +dependencies = [ + "anyhow", + "bitflags 2.10.0", + "indexmap 2.12.1", + "log", + "serde", + "serde_derive", + "serde_json", + "wasm-encoder", + "wasm-metadata", + "wasmparser", + "wit-parser", +] + +[[package]] +name = "wit-parser" +version = "0.244.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ecc8ac4bc1dc3381b7f59c34f00b67e18f910c2c0f50015669dde7def656a736" +dependencies = [ + "anyhow", + "id-arena", + "indexmap 2.12.1", + "log", + "semver 1.0.27", + "serde", + "serde_derive", + "serde_json", + "unicode-xid 0.2.6", + "wasmparser", +] + [[package]] name = "write16" version = "1.0.0" @@ -16756,7 +17869,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "32e45ad4206f6d2479085147f02bc2ef834ac85886624a23575ae137c8aa8156" dependencies = [ "libc", - "rustix 1.1.2", + "rustix", ] [[package]] @@ -16780,6 +17893,19 @@ dependencies = [ "linked-hash-map", ] +[[package]] +name = "yaml_serde" +version = "0.10.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "08c7c1b1a6a7c8a6b2741a6c21a4f8918e51899b111cfa08d1288202656e3975" +dependencies = [ + "indexmap 2.12.1", + "itoa", + "libyaml-rs", + "ryu", + "serde", +] + [[package]] name = "yansi" version = "1.0.1" @@ -16856,6 +17982,7 @@ version = "1.8.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b97154e67e32c85465826e8bcc1c59429aaaf107c1e4a9e53c8d8ccd5eff88d0" dependencies = [ + "serde", "zeroize_derive", ] @@ -16913,7 +18040,7 @@ dependencies = [ "aes", "byteorder", "bzip2", - "constant_time_eq", + "constant_time_eq 0.1.5", "crc32fast", "crossbeam-utils", "flate2", diff --git a/Cargo.toml b/Cargo.toml index 92ef5359d..8fd882ee8 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,7 +1,7 @@ [workspace.package] version = "0.1.0" edition = "2021" -rust-version = "1.85" +rust-version = "1.93" license = "MIT OR Apache-2.0" homepage = "https://github.com/flashbots/rbuilder" repository = "https://github.com/flashbots/rbuilder" @@ -70,61 +70,71 @@ codegen-units = 1 incremental = false [workspace.dependencies] -reth = { git = "https://github.com/paradigmxyz/reth", rev = "27a8c0f5a6dfb27dea84c5751776ecabdd069646" } -reth-cli-util = { git = "https://github.com/paradigmxyz/reth", rev = "27a8c0f5a6dfb27dea84c5751776ecabdd069646" } -reth-db = { git = "https://github.com/paradigmxyz/reth", rev = "27a8c0f5a6dfb27dea84c5751776ecabdd069646" } -reth-db-common = { git = "https://github.com/paradigmxyz/reth", rev = "27a8c0f5a6dfb27dea84c5751776ecabdd069646" } -reth-errors = { git = "https://github.com/paradigmxyz/reth", rev = "27a8c0f5a6dfb27dea84c5751776ecabdd069646" } -reth-payload-builder = { git = "https://github.com/paradigmxyz/reth", rev = "27a8c0f5a6dfb27dea84c5751776ecabdd069646" } -reth-node-api = { git = "https://github.com/paradigmxyz/reth", rev = "27a8c0f5a6dfb27dea84c5751776ecabdd069646" } -reth-node-ethereum = { git = "https://github.com/paradigmxyz/reth", rev = "27a8c0f5a6dfb27dea84c5751776ecabdd069646" } -reth-trie = { git = "https://github.com/paradigmxyz/reth", rev = "27a8c0f5a6dfb27dea84c5751776ecabdd069646" } -reth-trie-parallel = { git = "https://github.com/paradigmxyz/reth", rev = "27a8c0f5a6dfb27dea84c5751776ecabdd069646" } -reth-node-core = { git = "https://github.com/paradigmxyz/reth", rev = "27a8c0f5a6dfb27dea84c5751776ecabdd069646" } -reth-primitives = { git = "https://github.com/paradigmxyz/reth", rev = "27a8c0f5a6dfb27dea84c5751776ecabdd069646" } -reth-ethereum-primitives = { git = "https://github.com/paradigmxyz/reth", rev = "27a8c0f5a6dfb27dea84c5751776ecabdd069646" } -reth-primitives-traits = { git = "https://github.com/paradigmxyz/reth", rev = "27a8c0f5a6dfb27dea84c5751776ecabdd069646" } -reth-provider = { git = "https://github.com/paradigmxyz/reth", rev = "27a8c0f5a6dfb27dea84c5751776ecabdd069646", features = [ +# reth crates — paradigmxyz/reth bal-devnet-6 (glamsterdam-devnet-3): adds +# engine_getPayloadV6, BlockAccessList (EIP-7928), and ExecutionPayloadGloas. +reth = { git = "https://github.com/paradigmxyz/reth", rev = "8ebfaff134a973ea7b89f619a0562882e97b93c7" } +reth-cli-util = { git = "https://github.com/paradigmxyz/reth", rev = "8ebfaff134a973ea7b89f619a0562882e97b93c7" } +reth-db = { git = "https://github.com/paradigmxyz/reth", rev = "8ebfaff134a973ea7b89f619a0562882e97b93c7" } +reth-db-common = { git = "https://github.com/paradigmxyz/reth", rev = "8ebfaff134a973ea7b89f619a0562882e97b93c7" } +reth-errors = { git = "https://github.com/paradigmxyz/reth", rev = "8ebfaff134a973ea7b89f619a0562882e97b93c7" } +reth-payload-builder = { git = "https://github.com/paradigmxyz/reth", rev = "8ebfaff134a973ea7b89f619a0562882e97b93c7" } +reth-node-api = { git = "https://github.com/paradigmxyz/reth", rev = "8ebfaff134a973ea7b89f619a0562882e97b93c7" } +reth-node-ethereum = { git = "https://github.com/paradigmxyz/reth", rev = "8ebfaff134a973ea7b89f619a0562882e97b93c7" } +reth-trie = { git = "https://github.com/paradigmxyz/reth", rev = "8ebfaff134a973ea7b89f619a0562882e97b93c7" } +reth-trie-parallel = { git = "https://github.com/paradigmxyz/reth", rev = "8ebfaff134a973ea7b89f619a0562882e97b93c7" } +reth-node-core = { git = "https://github.com/paradigmxyz/reth", rev = "8ebfaff134a973ea7b89f619a0562882e97b93c7" } +reth-ethereum-primitives = { git = "https://github.com/paradigmxyz/reth", rev = "8ebfaff134a973ea7b89f619a0562882e97b93c7" } +reth-primitives-traits = { version = "0.3.0" } +reth-provider = { git = "https://github.com/paradigmxyz/reth", rev = "8ebfaff134a973ea7b89f619a0562882e97b93c7", features = [ "test-utils", ] } -reth-chainspec = { git = "https://github.com/paradigmxyz/reth", rev = "27a8c0f5a6dfb27dea84c5751776ecabdd069646" } -reth-evm = { git = "https://github.com/paradigmxyz/reth", rev = "27a8c0f5a6dfb27dea84c5751776ecabdd069646" } -reth-evm-ethereum = { git = "https://github.com/paradigmxyz/reth", rev = "27a8c0f5a6dfb27dea84c5751776ecabdd069646" } -reth-execution-errors = { git = "https://github.com/paradigmxyz/reth", rev = "27a8c0f5a6dfb27dea84c5751776ecabdd069646" } -reth-trie-db = { git = "https://github.com/paradigmxyz/reth", rev = "27a8c0f5a6dfb27dea84c5751776ecabdd069646" } -reth-transaction-pool = { git = "https://github.com/paradigmxyz/reth", rev = "27a8c0f5a6dfb27dea84c5751776ecabdd069646" } - -# compatible with reth 27a8c0f5a6dfb27dea84c5751776ecabdd069646 dependencies -revm = { version = "31.0.2", features = [ +reth-chainspec = { git = "https://github.com/paradigmxyz/reth", rev = "8ebfaff134a973ea7b89f619a0562882e97b93c7" } +reth-evm = { git = "https://github.com/paradigmxyz/reth", rev = "8ebfaff134a973ea7b89f619a0562882e97b93c7" } +reth-evm-ethereum = { git = "https://github.com/paradigmxyz/reth", rev = "8ebfaff134a973ea7b89f619a0562882e97b93c7" } +reth-execution-errors = { git = "https://github.com/paradigmxyz/reth", rev = "8ebfaff134a973ea7b89f619a0562882e97b93c7" } +reth-trie-db = { git = "https://github.com/paradigmxyz/reth", rev = "8ebfaff134a973ea7b89f619a0562882e97b93c7" } +reth-transaction-pool = { git = "https://github.com/paradigmxyz/reth", rev = "8ebfaff134a973ea7b89f619a0562882e97b93c7" } +reth-tasks = { git = "https://github.com/paradigmxyz/reth", rev = "8ebfaff134a973ea7b89f619a0562882e97b93c7" } + +# compatible with local reth dependencies (bumped for bal-devnet-6) +revm = { version = "=38.0.0", features = [ "std", "secp256k1", "optional_balance_check", ], default-features = false } -revm-inspectors = { version = "0.32.0", default-features = false } +revm-inspectors = { version = "=0.39.0", default-features = false } -ethereum_ssz_derive = "0.9.0" -ethereum_ssz = "0.9.0" +ethereum_ssz_derive = "0.10.0" +ethereum_ssz = "0.10.0" +tree_hash = "0.12.0" -alloy-primitives = { version = "1.4.1", default-features = false, features = [ +# Lighthouse consensus types for Gloas/EPBS SSZ types — glamsterdam-devnet-3 +# branch (has `execution_requests_root` on ExecutionPayloadBid and the new +# Gloas envelope schema with `parent_beacon_block_root`, no `slot`/`state_root`). +lighthouse_types = { git = "https://github.com/sigp/lighthouse", rev = "27cfa18c17e148fb75827d0ea3c9a2c69db0aae0", package = "types", default-features = false, features = ["saturating-arith"] } +lighthouse_bls = { git = "https://github.com/sigp/lighthouse", rev = "27cfa18c17e148fb75827d0ea3c9a2c69db0aae0", package = "bls" } +lighthouse_ssz_types = { version = "0.14.1", package = "ssz_types", features = ["context_deserialize", "runtime_types"] } + +alloy-primitives = { version = "1.5.6", default-features = false, features = [ "getrandom", ] } -alloy-rlp = "0.3.10" -alloy-chains = "0.2.5" -alloy-trie = { version = "0.8.1", default-features = false } -alloy-evm = { version = "0.23.3", default-features = false } -alloy-provider = { version = "1.0.41", features = ["ipc", "pubsub", "ws"] } -alloy-eips = { version = "1.0.41" } -alloy-rpc-types = { version = "1.0.41" } -alloy-json-rpc = { version = "1.0.41" } -alloy-network = { version = "1.0.41" } -alloy-network-primitives = { version = "1.0.41" } -alloy-node-bindings = { version = "1.0.41" } -alloy-consensus = { version = "1.0.41", features = ["kzg"] } -alloy-rpc-types-beacon = { version = "1.0.41", features = ["ssz"] } -alloy-rpc-types-engine = { version = "1.0.41", features = ["ssz"] } -alloy-rpc-types-eth = { version = "1.0.41" } -alloy-signer = { version = "1.0.41" } -alloy-signer-local = { version = "1.0.41" } +alloy-rlp = "0.3.13" +alloy-chains = "0.2.33" +alloy-trie = { version = "0.9.4", default-features = false } +alloy-evm = { version = "0.34.0", default-features = false } +alloy-provider = { version = "2.0.1", features = ["ipc", "pubsub", "ws"] } +alloy-eips = { version = "2.0.1" } +alloy-rpc-types = { version = "2.0.1" } +alloy-json-rpc = { version = "2.0.1" } +alloy-network = { version = "2.0.1" } +alloy-network-primitives = { version = "2.0.1" } +alloy-node-bindings = { version = "2.0.1" } +alloy-consensus = { version = "2.0.1", features = ["kzg"] } +alloy-rpc-types-beacon = { version = "2.0.1", features = ["ssz"] } +alloy-rpc-types-engine = { version = "2.0.1", features = ["ssz"] } +alloy-rpc-types-eth = { version = "2.0.1" } +alloy-signer = { version = "2.0.1" } +alloy-signer-local = { version = "2.0.1" } # Version required by ethereum-consensus beacon-api-client mev-share-sse = { git = "https://github.com/paradigmxyz/mev-share-rs", rev = "9eb2b0138ab3202b9eb3af4b19c7b3bf40b0faa8", default-features = false } @@ -185,3 +195,28 @@ metrics_macros = { path = "crates/rbuilder/src/telemetry/metrics_macros" } [workspace.metadata.cargo-shear] # cargo-shear invalidly marks these as unused. ignored = ["prost", "prost-types"] + +# Mirror upstream reth's patch section so revm/alloy-evm/reth-codecs resolve to +# the same revs reth itself is built against. If this gets out of sync with +# reth's Cargo.toml, the build fails with conflicting type definitions for the +# `revm` types reth's API surface uses. +[patch.crates-io] +revm = { git = "https://github.com/bluealloy/revm", rev = "7ac2a4a922d70e73f7b45baa16ed996f479d6a41" } +revm-bytecode = { git = "https://github.com/bluealloy/revm", rev = "7ac2a4a922d70e73f7b45baa16ed996f479d6a41" } +revm-context = { git = "https://github.com/bluealloy/revm", rev = "7ac2a4a922d70e73f7b45baa16ed996f479d6a41" } +revm-context-interface = { git = "https://github.com/bluealloy/revm", rev = "7ac2a4a922d70e73f7b45baa16ed996f479d6a41" } +revm-database = { git = "https://github.com/bluealloy/revm", rev = "7ac2a4a922d70e73f7b45baa16ed996f479d6a41" } +revm-database-interface = { git = "https://github.com/bluealloy/revm", rev = "7ac2a4a922d70e73f7b45baa16ed996f479d6a41" } +revm-handler = { git = "https://github.com/bluealloy/revm", rev = "7ac2a4a922d70e73f7b45baa16ed996f479d6a41" } +revm-inspector = { git = "https://github.com/bluealloy/revm", rev = "7ac2a4a922d70e73f7b45baa16ed996f479d6a41" } +revm-interpreter = { git = "https://github.com/bluealloy/revm", rev = "7ac2a4a922d70e73f7b45baa16ed996f479d6a41" } +revm-precompile = { git = "https://github.com/bluealloy/revm", rev = "7ac2a4a922d70e73f7b45baa16ed996f479d6a41" } +revm-primitives = { git = "https://github.com/bluealloy/revm", rev = "7ac2a4a922d70e73f7b45baa16ed996f479d6a41" } +revm-state = { git = "https://github.com/bluealloy/revm", rev = "7ac2a4a922d70e73f7b45baa16ed996f479d6a41" } +revm-inspectors = { git = "https://github.com/paradigmxyz/revm-inspectors", rev = "1c2e997a33baa698decdaaba5f14326fc40dfee6" } +alloy-evm = { git = "https://github.com/alloy-rs/evm", rev = "13c9068fe8d0b112f2836783f9702eb3d3b7871f" } +reth-codecs = { git = "https://github.com/paradigmxyz/reth-core", rev = "afa5162668db00749b14bf30d06d3bed5c71aa4c" } +reth-codecs-derive = { git = "https://github.com/paradigmxyz/reth-core", rev = "afa5162668db00749b14bf30d06d3bed5c71aa4c" } +reth-primitives-traits = { git = "https://github.com/paradigmxyz/reth-core", rev = "afa5162668db00749b14bf30d06d3bed5c71aa4c" } +reth-rpc-traits = { git = "https://github.com/paradigmxyz/reth-core", rev = "afa5162668db00749b14bf30d06d3bed5c71aa4c" } +reth-zstd-compressors = { git = "https://github.com/paradigmxyz/reth-core", rev = "afa5162668db00749b14bf30d06d3bed5c71aa4c" } diff --git a/crates/eth-sparse-mpt/Cargo.toml b/crates/eth-sparse-mpt/Cargo.toml index 2111bd4ca..cb6b544f1 100644 --- a/crates/eth-sparse-mpt/Cargo.toml +++ b/crates/eth-sparse-mpt/Cargo.toml @@ -17,7 +17,7 @@ rustc-hash = "2.0.0" rayon = "1.10.0" smallvec = "1.13.2" alloy-trie.workspace = true -nybbles = { version = "0.3.3", features = ["serde"] } +nybbles = { version = "0.4", features = ["serde"] } tracing.workspace = true diff --git a/crates/eth-sparse-mpt/src/utils.rs b/crates/eth-sparse-mpt/src/utils.rs index 288ff1c96..4e831584a 100644 --- a/crates/eth-sparse-mpt/src/utils.rs +++ b/crates/eth-sparse-mpt/src/utils.rs @@ -29,25 +29,28 @@ pub fn rlp_pointer(rlp_encode: Bytes) -> Bytes { } pub fn concat_path(p1: &Nibbles, p2: &[u8]) -> Nibbles { - let mut result = Nibbles::with_capacity(p1.len() + p2.len()); - result.extend_from_slice_unchecked(p1); - result.extend_from_slice_unchecked(p2); + let mut result = *p1; + let p2_nibbles = Nibbles::from_nibbles_unchecked(p2); + result.extend(&p2_nibbles); result } pub fn strip_first_nibble_mut(p: &mut Nibbles) -> u8 { - let nibble = p[0]; - let vec = p.as_mut_vec_unchecked(); + let nibble = p.get_unchecked(0); + let mut vec = p.to_vec(); vec.remove(0); + *p = Nibbles::from_nibbles_unchecked(vec); nibble } #[inline] pub fn extract_prefix_and_suffix(p1: &Nibbles, p2: &Nibbles) -> (Nibbles, Nibbles, Nibbles) { let prefix_len = p1.common_prefix_length(p2); - let prefix = Nibbles::from_nibbles_unchecked(&p1[..prefix_len]); - let suffix1 = Nibbles::from_nibbles_unchecked(&p1[prefix_len..]); - let suffix2 = Nibbles::from_nibbles_unchecked(&p2[prefix_len..]); + let p1_vec = p1.to_vec(); + let p2_vec = p2.to_vec(); + let prefix = Nibbles::from_nibbles_unchecked(&p1_vec[..prefix_len]); + let suffix1 = Nibbles::from_nibbles_unchecked(&p1_vec[prefix_len..]); + let suffix2 = Nibbles::from_nibbles_unchecked(&p2_vec[prefix_len..]); (prefix, suffix1, suffix2) } @@ -137,15 +140,14 @@ fn mismatch_chunks(xs: &[u8], ys: &[u8]) -> usize { .count() } -// rbuilder uses nybbles v3.3.0 and reth_trie uses nybbles v4.3.0. This is a temporary fix to convert between the two. -// We can remove the below methods once rbuilder has been upgraded to nybbles v4.3.0. -// nybbles v4.3.0 has a breaking change (byte array with 1 byte per nybble vs U256 packed data + length) in the API which breaks a lot of parts of the eth sparse trie code. +// rbuilder and reth_trie now both use nybbles v0.4.x, so these are identity conversions. +// Kept for backward compatibility with call sites. #[inline] pub fn convert_reth_nybbles_to_nibbles(n: reth_trie::Nibbles) -> Nibbles { - Nibbles::from_nibbles(n.to_vec()) + n } #[inline] pub fn convert_nibbles_to_reth_nybbles(n: Nibbles) -> reth_trie::Nibbles { - reth_trie::Nibbles::from_nibbles(n.as_slice()) + n } diff --git a/crates/eth-sparse-mpt/src/v1/reth_sparse_trie/shared_cache.rs b/crates/eth-sparse-mpt/src/v1/reth_sparse_trie/shared_cache.rs index 47447807b..e3815302f 100644 --- a/crates/eth-sparse-mpt/src/v1/reth_sparse_trie/shared_cache.rs +++ b/crates/eth-sparse-mpt/src/v1/reth_sparse_trie/shared_cache.rs @@ -146,11 +146,11 @@ impl RethSparseTrieShareCacheInternal { multiproof: MultiProof, ) -> Result<(), AddNodeError> { let mut nodes: Vec<_> = multiproof.account_subtree.into_iter().collect(); - nodes.sort_by_key(|(p, _)| p.clone()); + nodes.sort_by_key(|(p, _)| *p); self.account_trie.add_nodes(&nodes)?; for (account, storge_proofs) in multiproof.storages { let mut nodes: Vec<_> = storge_proofs.subtree.into_iter().collect(); - nodes.sort_by_key(|(p, _)| p.clone()); + nodes.sort_by_key(|(p, _)| *p); let account = Bytes::copy_from_slice(account.as_slice()); let storage_trie = self.storage_tries.entry(account).or_default(); storage_trie.add_nodes(&nodes)?; diff --git a/crates/eth-sparse-mpt/src/v1/reth_sparse_trie/trie_fetcher/mod.rs b/crates/eth-sparse-mpt/src/v1/reth_sparse_trie/trie_fetcher/mod.rs index 9fd0f6669..bee9a7017 100644 --- a/crates/eth-sparse-mpt/src/v1/reth_sparse_trie/trie_fetcher/mod.rs +++ b/crates/eth-sparse-mpt/src/v1/reth_sparse_trie/trie_fetcher/mod.rs @@ -13,7 +13,7 @@ use reth_provider::{ providers::ConsistentDbView, BlockReader, DBProvider, DatabaseProviderFactory, }; use reth_trie::{proof::Proof, MultiProof as RethMultiProof, MultiProofTargets, EMPTY_ROOT_HASH}; -use reth_trie_db::{DatabaseHashedCursorFactory, DatabaseTrieCursorFactory}; +use reth_trie_db::{DatabaseHashedCursorFactory, DatabaseTrieCursorFactory, LegacyKeyAdapter}; use serde::{Deserialize, Serialize}; use serde_with::{serde_as, Seq}; @@ -78,7 +78,7 @@ where let start = Instant::now(); let provider = self.consistent_db_view.provider_ro()?; let proof = Proof::new( - DatabaseTrieCursorFactory::new(provider.tx_ref()), + DatabaseTrieCursorFactory::<_, LegacyKeyAdapter>::new(provider.tx_ref()), DatabaseHashedCursorFactory::new(provider.tx_ref()), ); let targets_accounts = targets.len(); @@ -105,10 +105,12 @@ where } } -fn pad_path(mut path: Nibbles) -> B256 { - path.as_mut_vec_unchecked().resize(64, 0); +fn pad_path(path: Nibbles) -> B256 { + let mut v = path.to_vec(); + v.resize(64, 0); + let padded = Nibbles::from_nibbles_unchecked(v); let mut res = B256::default(); - path.pack_to(res.as_mut_slice()); + padded.pack_to(res.as_mut_slice()); res } @@ -164,16 +166,16 @@ fn merge_results( let mut result = MultiProof::default(); for mut proof in multiproofs { result.account_subtree.append(&mut proof.account_subtree); - result.account_subtree.sort_by_key(|s| s.0.clone()); - result.account_subtree.dedup_by_key(|s| s.0.clone()); + result.account_subtree.sort_by_key(|s| s.0); + result.account_subtree.dedup_by_key(|s| s.0); for (account, mut storage_proof) in proof.storages { let result_storage_proof = result.storages.entry(account).or_default(); result_storage_proof .subtree .append(&mut storage_proof.subtree); - result_storage_proof.subtree.sort_by_key(|s| s.0.clone()); - result_storage_proof.subtree.dedup_by_key(|s| s.0.clone()); + result_storage_proof.subtree.sort_by_key(|s| s.0); + result_storage_proof.subtree.dedup_by_key(|s| s.0); } } @@ -194,7 +196,7 @@ fn convert_reth_multiproof( for (k, v) in reth_proof.account_subtree.into_inner() { account_subtree.push((convert_reth_nybbles_to_nibbles(k), v)); } - account_subtree.sort_by_key(|a| a.0.clone()); + account_subtree.sort_by_key(|a| a.0); let mut storages = hash_map_with_capacity(reth_proof.storages.len()); for (k, reth_storage_proof) in reth_proof.storages { if !all_requested_accounts.contains(&k) { @@ -208,7 +210,7 @@ fn convert_reth_multiproof( for (k, v) in reth_storage_proof.subtree.into_inner() { subtree.push((convert_reth_nybbles_to_nibbles(k), v)); } - subtree.sort_by_key(|a| a.0.clone()); + subtree.sort_by_key(|a| a.0); let v = StorageMultiProof { subtree }; storages.insert(k, v); } diff --git a/crates/eth-sparse-mpt/src/v1/sparse_mpt/diff_trie/mod.rs b/crates/eth-sparse-mpt/src/v1/sparse_mpt/diff_trie/mod.rs index 81210807a..22cbcb4bc 100644 --- a/crates/eth-sparse-mpt/src/v1/sparse_mpt/diff_trie/mod.rs +++ b/crates/eth-sparse-mpt/src/v1/sparse_mpt/diff_trie/mod.rs @@ -65,7 +65,7 @@ pub struct NodeCursor { impl NodeCursor { pub fn new(key: Nibbles, head: u64) -> Self { - let current_path = Nibbles::with_capacity(key.len()); + let current_path = Nibbles::default(); Self { current_node: head, current_path, @@ -75,9 +75,9 @@ impl NodeCursor { pub fn step_into_extension(&mut self, ext: &DiffExtensionNode) { let len = ext.key().len(); - self.current_path - .extend_from_slice_unchecked(&self.path_left[..len]); - self.path_left.as_mut_vec_unchecked().drain(..len); + let prefix = self.path_left.slice(..len); + self.current_path.extend(&prefix); + self.path_left = self.path_left.slice(len..); self.current_node = ext.child.ptr(); } @@ -101,10 +101,9 @@ fn try_get_node_mut<'a>( ptr: u64, path: &Nibbles, ) -> Result<&'a mut DiffTrieNode, ErrSparseNodeNotFound> { - nodes.get_mut(&ptr).ok_or_else(|| ErrSparseNodeNotFound { - path: path.clone(), - ptr, - }) + nodes + .get_mut(&ptr) + .ok_or(ErrSparseNodeNotFound { path: *path, ptr }) } pub fn get_new_ptr(ptrs: &mut u64) -> u64 { @@ -238,13 +237,10 @@ impl DiffTrie { let n = c.step_into_branch(branch); if branch.has_child(n) { - let child = - branch - .get_diff_child_mut(n) - .ok_or_else(|| ErrSparseNodeNotFound { - path: c.current_path.clone(), - ptr: u64::MAX, - })?; + let child = branch.get_diff_child_mut(n).ok_or(ErrSparseNodeNotFound { + path: c.current_path, + ptr: u64::MAX, + })?; child.mark_dirty(); continue; } else { @@ -313,9 +309,9 @@ impl DiffTrie { return Err(DeletionError::KeyNotFound); } - let child = branch.get_diff_child_mut(n).ok_or_else(|| { + let child = branch.get_diff_child_mut(n).ok_or({ DeletionError::NodeNotFound(ErrSparseNodeNotFound { - path: c.current_path.clone(), + path: c.current_path, ptr: u64::MAX, }) })?; @@ -332,9 +328,10 @@ impl DiffTrie { .other_child_nibble(n) .expect("other child must exist"); if branch.get_diff_child(other_child_nibble).is_none() { - let mut other_child_path = c.current_path.clone(); - if let Some(l) = other_child_path.as_mut_vec_unchecked().last_mut() { - *l = other_child_nibble; + let mut other_child_path = c.current_path; + if !other_child_path.is_empty() { + other_child_path + .set_at(other_child_path.len() - 1, other_child_nibble); } return Err(DeletionError::NodeNotFound(ErrSparseNodeNotFound { path: other_child_path, @@ -428,9 +425,9 @@ impl DiffTrie { DiffTrieNodeKind::Leaf(leaf_below), ) => { // we just replace extension node by merging its path into leaf with child_nibble - let mut new_leaf_key = ext_above.key().clone(); + let mut new_leaf_key = *ext_above.key(); new_leaf_key.push(*child_nibble); - new_leaf_key.extend_from_slice_unchecked(leaf_below.key()); + new_leaf_key.extend(leaf_below.key()); let mut new_leaf = leaf_below; new_leaf.changed_key = Some(new_leaf_key); @@ -443,7 +440,7 @@ impl DiffTrie { // we merge two extension nodes into current node with child_nibble let ext_key = ext_above.key_mut(); ext_key.push(*child_nibble); - ext_key.extend_from_slice_unchecked(ext_below.key()); + ext_key.extend(ext_below.key()); ext_above.child = ext_below.child.clone(); } @@ -469,10 +466,12 @@ impl DiffTrie { DiffTrieNodeKind::Leaf(mut leaf_below), ) => { // merge missing nibble into the leaf - leaf_below - .key_mut() - .as_mut_vec_unchecked() - .insert(0, *child_nibble); + { + let key = leaf_below.key_mut(); + let old_key = *key; + *key = Nibbles::from_nibbles_unchecked([*child_nibble]); + key.extend(&old_key); + } let new_leaf_ptr = get_new_ptr(&mut self.ptrs); let new_child = DiffTrieNode { @@ -491,10 +490,12 @@ impl DiffTrie { DiffTrieNodeKind::Extension(mut ext_below), ) => { // merge missing nibble into the extension - ext_below - .key_mut() - .as_mut_vec_unchecked() - .insert(0, *child_nibble); + { + let key = ext_below.key_mut(); + let old_key = *key; + *key = Nibbles::from_nibbles_unchecked([*child_nibble]); + key.extend(&old_key); + } let new_child_ptr = get_new_ptr(&mut self.ptrs); let new_child = DiffTrieNode { kind: DiffTrieNodeKind::Extension(ext_below), @@ -563,13 +564,21 @@ impl DiffTrie { .expect("orphaned child existence verif"); match &mut child_below.kind { DiffTrieNodeKind::Leaf(leaf) => { - leaf.key_mut() - .as_mut_vec_unchecked() - .insert(0, child_nibble); + { + let key = leaf.key_mut(); + let old_key = *key; + *key = Nibbles::from_nibbles_unchecked([child_nibble]); + key.extend(&old_key); + } child_below.rlp_pointer = None; } DiffTrieNodeKind::Extension(ext) => { - ext.key_mut().as_mut_vec_unchecked().insert(0, child_nibble); + { + let key = ext.key_mut(); + let old_key = *key; + *key = Nibbles::from_nibbles_unchecked([child_nibble]); + key.extend(&old_key); + } child_below.rlp_pointer = None; } DiffTrieNodeKind::Branch(_) => { diff --git a/crates/eth-sparse-mpt/src/v1/sparse_mpt/diff_trie/nodes.rs b/crates/eth-sparse-mpt/src/v1/sparse_mpt/diff_trie/nodes.rs index 164aaebb5..620ffcd58 100644 --- a/crates/eth-sparse-mpt/src/v1/sparse_mpt/diff_trie/nodes.rs +++ b/crates/eth-sparse-mpt/src/v1/sparse_mpt/diff_trie/nodes.rs @@ -174,7 +174,7 @@ impl DiffLeafNode { let fixed_key = self .fixed .as_ref() - .map(|k| k.key.clone()) + .map(|k| k.key) .expect("leaf incorrect form"); self.changed_key = Some(fixed_key); } @@ -331,7 +331,7 @@ impl DiffExtensionNode { let fixed_key = self .fixed .as_ref() - .map(|k| k.key.clone()) + .map(|k| k.key) .expect("ext incorrect form"); self.changed_key = Some(fixed_key); } diff --git a/crates/eth-sparse-mpt/src/v1/sparse_mpt/fixed_trie.rs b/crates/eth-sparse-mpt/src/v1/sparse_mpt/fixed_trie.rs index 2934337f0..51a69a737 100644 --- a/crates/eth-sparse-mpt/src/v1/sparse_mpt/fixed_trie.rs +++ b/crates/eth-sparse-mpt/src/v1/sparse_mpt/fixed_trie.rs @@ -167,12 +167,12 @@ impl FixedTrie { for (ptr, node) in &diff_trie.nodes { let fixed_node = match &node.kind { DiffTrieNodeKind::Leaf(leaf) => FixedTrieNode::Leaf(Arc::new(FixedLeafNode { - key: leaf.key().clone(), + key: *leaf.key(), value: leaf.value().clone(), })), DiffTrieNodeKind::Extension(ext) => FixedTrieNode::Extension { node: Arc::new(FixedExtensionNode { - key: ext.key().clone(), + key: *ext.key(), child: ext .child .rlp_pointer @@ -261,7 +261,7 @@ impl FixedTrie { // here we find parent to link with this new node let mut current_path = Nibbles::new(); - let mut path_left = path.clone(); + let mut path_left = *path; let mut current_node = self.head; let mut parent: Option = None; @@ -286,8 +286,9 @@ impl FixedTrie { parent_child_idx = None; let len = node.key.len(); - current_path.extend_from_slice_unchecked(&path_left[..len]); - path_left.as_mut_vec_unchecked().drain(..len); + let prefix = path_left.slice(..len); + current_path.extend(&prefix); + path_left = path_left.slice(len..); if path_left.is_empty() { break; @@ -455,11 +456,10 @@ impl FixedTrie { // orphan node is missing // we stepped into child above so the path is the path of current child and orphan child differs // only in last nibble - let mut path = c.current_path.clone(); - path.as_mut_vec_unchecked() - .last_mut() - .map(|n| *n = orphan_nibble) - .unwrap(); + let mut path = c.current_path; + if !path.is_empty() { + path.set_at(path.len() - 1, orphan_nibble); + } missing_nodes.push(path); } } diff --git a/crates/eth-sparse-mpt/src/v2/fetch.rs b/crates/eth-sparse-mpt/src/v2/fetch.rs index 43f27fcaf..34b1daf1d 100644 --- a/crates/eth-sparse-mpt/src/v2/fetch.rs +++ b/crates/eth-sparse-mpt/src/v2/fetch.rs @@ -18,7 +18,7 @@ use reth_trie::{ proof::{Proof, StorageProof}, MultiProofTargets, }; -use reth_trie_db::{DatabaseHashedCursorFactory, DatabaseTrieCursorFactory}; +use reth_trie_db::{DatabaseHashedCursorFactory, DatabaseTrieCursorFactory, LegacyKeyAdapter}; use super::SharedCacheV2; @@ -39,12 +39,12 @@ impl MissingNodesFetcher { .storage_proof_targets .entry(*hashed_address) .or_default(); - entry.0.insert(pad_path(node.clone())); + entry.0.insert(pad_path(node)); entry.1.push(node); } pub fn add_missing_account_node(&mut self, node: Nibbles) { - self.account_proof_targets.push(pad_path(node.clone())); + self.account_proof_targets.push(pad_path(node)); self.account_proof_requested_nodes.push(node); } @@ -80,7 +80,7 @@ impl MissingNodesFetcher { } let proof = StorageProof::new_hashed( - DatabaseTrieCursorFactory::new(provider.tx_ref()), + DatabaseTrieCursorFactory::<_, LegacyKeyAdapter>::new(provider.tx_ref()), DatabaseHashedCursorFactory::new(provider.tx_ref()), hashed_address, ); @@ -90,7 +90,7 @@ impl MissingNodesFetcher { *fetched_nodes.lock() += requested_proofs.len(); for requested_proof in requested_proofs { let proof_for_node = storge_multiproof.subtree.matching_nodes_sorted( - &convert_nibbles_to_reth_nybbles(requested_proof.clone()), + &convert_nibbles_to_reth_nybbles(requested_proof), ); let reth_proof_for_node = proof_for_node .into_iter() @@ -123,7 +123,7 @@ impl MissingNodesFetcher { } let proof = Proof::new( - DatabaseTrieCursorFactory::new(provider.tx_ref()), + DatabaseTrieCursorFactory::<_, LegacyKeyAdapter>::new(provider.tx_ref()), DatabaseHashedCursorFactory::new(provider.tx_ref()), ); let targets = MultiProofTargets::accounts(std::mem::take(&mut self.account_proof_targets)); @@ -133,7 +133,7 @@ impl MissingNodesFetcher { for requested_node in self.account_proof_requested_nodes.drain(..) { let proof_for_node = multiproof .account_subtree - .matching_nodes_sorted(&convert_nibbles_to_reth_nybbles(requested_node.clone())); + .matching_nodes_sorted(&convert_nibbles_to_reth_nybbles(requested_node)); let reth_proof_for_node = proof_for_node .into_iter() @@ -149,9 +149,11 @@ impl MissingNodesFetcher { } } -fn pad_path(mut path: Nibbles) -> B256 { - path.as_mut_vec_unchecked().resize(64, 0); +fn pad_path(path: Nibbles) -> B256 { + let mut v = path.to_vec(); + v.resize(64, 0); + let padded = Nibbles::from_nibbles_unchecked(v); let mut res = B256::default(); - path.pack_to(res.as_mut_slice()); + padded.pack_to(res.as_mut_slice()); res } diff --git a/crates/eth-sparse-mpt/src/v2/mod.rs b/crates/eth-sparse-mpt/src/v2/mod.rs index 4986e84f7..809bd50f3 100644 --- a/crates/eth-sparse-mpt/src/v2/mod.rs +++ b/crates/eth-sparse-mpt/src/v2/mod.rs @@ -446,7 +446,7 @@ impl RootHashCalculator { { fetcher .lock() - .add_missing_account_node(storage_calc.unpacked_hashed_address.clone()); + .add_missing_account_node(storage_calc.unpacked_hashed_address); } if storage_calc.insert_keys.is_empty() && storage_calc.delete_keys.is_empty() { @@ -466,7 +466,7 @@ impl RootHashCalculator { if !storage_calc.proof_store.has_proof(node) { fetcher .lock() - .add_missing_storage_node(&storage_calc.hashed_address, node.clone()); + .add_missing_storage_node(&storage_calc.hashed_address, *node); } } }); @@ -549,7 +549,7 @@ impl RootHashCalculator { storage_calc.insert_storage_key[i], AppliedStorageOp { inserted_value: storage_calc.insert_storage_value[i], - revert_key: storage_calc.insert_keys[i].clone(), + revert_key: storage_calc.insert_keys[i], revert_value, }, ); @@ -574,7 +574,7 @@ impl RootHashCalculator { storage_calc.delete_storage_key[i], AppliedStorageOp { inserted_value: U256::ZERO, - revert_key: storage_calc.delete_keys[i].clone(), + revert_key: storage_calc.delete_keys[i], revert_value: Some(revert_value), }, ); @@ -639,7 +639,7 @@ impl RootHashCalculator { let ok = storage_calc.trie.try_add_proof_from_proof_store(&missing_node, &storage_calc.proof_store).expect("should be able to insert proofs from proof store when they are found (storage trie)"); assert!(ok, "proof is not added (storage trie)"); } else { - storage_calc.missing_nodes_requested.push(missing_node.clone()); + storage_calc.missing_nodes_requested.push(missing_node); fetcher.lock().add_missing_storage_node(&storage_calc.hashed_address, missing_node); } } @@ -733,7 +733,7 @@ impl RootHashCalculator { } } - let key = storage_calc.unpacked_hashed_address.clone(); + let key = storage_calc.unpacked_hashed_address; if let Some(trie_account) = trie_account { let value = alloy_rlp::encode(trie_account); self.account_trie.insert_keys.push(key); @@ -768,7 +768,7 @@ impl RootHashCalculator { for address in proof_targets { let storage_calc = self.get_account_storage(address); let storage_calc = storage_calc.lock(); - let key = storage_calc.unpacked_hashed_address.clone(); + let key = storage_calc.unpacked_hashed_address; self.account_trie.proof_keys.push(key); self.account_trie.proof_account_keys.push(*address); self.account_trie.proof_ok.push(false); @@ -834,7 +834,7 @@ impl RootHashCalculator { account_trie.insert_account_keys[i], AppliedAccountOp { inserted_value: Some(account_trie.insert_account_values[i]), - revert_key: account_trie.insert_keys[i].clone(), + revert_key: account_trie.insert_keys[i], revert_value, }, ); @@ -859,7 +859,7 @@ impl RootHashCalculator { account_trie.delete_account_keys[i], AppliedAccountOp { inserted_value: None, - revert_key: account_trie.delete_keys[i].clone(), + revert_key: account_trie.delete_keys[i], revert_value: Some(revert_value), }, ); @@ -921,9 +921,7 @@ impl RootHashCalculator { let ok = account_trie.trie.try_add_proof_from_proof_store(&missing_node, proof_store).expect("should be able to insert proofs from proof store when they are found (storage trie)"); assert!(ok, "proof is not added (storage trie)"); } else { - account_trie - .missing_nodes_requested - .push(missing_node.clone()); + account_trie.missing_nodes_requested.push(missing_node); fetcher.add_missing_account_node(missing_node); } } diff --git a/crates/eth-sparse-mpt/src/v2/trie/mod.rs b/crates/eth-sparse-mpt/src/v2/trie/mod.rs index 459da833a..9c337a849 100644 --- a/crates/eth-sparse-mpt/src/v2/trie/mod.rs +++ b/crates/eth-sparse-mpt/src/v2/trie/mod.rs @@ -93,8 +93,8 @@ pub enum ProofError { pub struct NodeNotFound(pub Nibbles); impl NodeNotFound { - fn new(path: &[u8]) -> Self { - Self(Nibbles::from_nibbles_unchecked(path)) + fn new(path: &Nibbles) -> Self { + Self(*path) } } @@ -199,7 +199,7 @@ impl Trie { nibbles_key: &Nibbles, insert_value: InsertValue<'_>, ) -> Result>, NodeNotFound> { - let ins_key = nibbles_key.as_slice(); + let ins_key = nibbles_key.to_vec(); let mut current_node = 0; let mut path_walked = 0; @@ -210,7 +210,7 @@ impl Trie { let node = self .nodes .get(current_node) - .ok_or_else(|| NodeNotFound(nibbles_key.clone()))?; + .ok_or(NodeNotFound(*nibbles_key))?; self.hashed_nodes[current_node] = false; match node { DiffTrieNode::Branch { children } => { @@ -219,9 +219,7 @@ impl Trie { let n = ins_key[path_walked] as usize; path_walked += 1; if let Some(child_ptr) = self.branch_node_children[children][n] { - current_node = child_ptr - .as_local() - .ok_or_else(|| NodeNotFound(nibbles_key.clone()))?; + current_node = child_ptr.as_local().ok_or(NodeNotFound(*nibbles_key))?; continue; } else { let new_leaf_key = self.insert_key(&ins_key[path_walked..]); @@ -239,9 +237,7 @@ impl Trie { if ins_key[path_walked..].starts_with(&self.keys[key.clone()]) { path_walked += key.len(); - current_node = next_node - .as_local() - .ok_or_else(|| NodeNotFound(nibbles_key.clone()))?; + current_node = next_node.as_local().ok_or(NodeNotFound(*nibbles_key))?; continue; } @@ -377,7 +373,7 @@ impl Trie { &mut self, nibbles_key: &Nibbles, ) -> Result, DeletionError> { - let del_key = nibbles_key.as_slice(); + let del_key = nibbles_key.to_vec(); let mut current_node = 0; let mut path_walked = 0; @@ -390,7 +386,7 @@ impl Trie { let node = self .nodes .get(current_node) - .ok_or_else(|| NodeNotFound(nibbles_key.clone()))?; + .ok_or(NodeNotFound(*nibbles_key))?; self.hashed_nodes[current_node] = false; match node { DiffTrieNode::Branch { children } => { @@ -406,9 +402,7 @@ impl Trie { path_walked += 1; if let Some(child_ptr) = self.branch_node_children[children][n as usize] { - current_node = child_ptr - .as_local() - .ok_or_else(|| NodeNotFound(nibbles_key.clone()))?; + current_node = child_ptr.as_local().ok_or(NodeNotFound(*nibbles_key))?; if self.branch_node_children[children] .iter() .filter(|c| c.is_some()) @@ -423,9 +417,8 @@ impl Trie { .unwrap(); let orphan_ptr = orphan_ptr.unwrap(); if orphan_ptr.is_remote() { - let mut orphan_path = Nibbles::with_capacity(path_walked); - orphan_path - .extend_from_slice_unchecked(&del_key[..(path_walked - 1)]); + let mut orphan_path = + Nibbles::from_nibbles_unchecked(&del_key[..(path_walked - 1)]); orphan_path.push_unchecked(orphan_nibble as u8); return Err(NodeNotFound(orphan_path).into()); } @@ -442,9 +435,7 @@ impl Trie { if del_key[path_walked..].starts_with(&self.keys[key.clone()]) { self.walk_path.push((current_node, 0)); path_walked += key.len(); - current_node = next_node - .as_local() - .ok_or_else(|| NodeNotFound(nibbles_key.clone()))?; + current_node = next_node.as_local().ok_or(NodeNotFound(*nibbles_key))?; continue; } @@ -873,6 +864,8 @@ impl Trie { value: None, }; + let target_key_vec = target_key.to_vec(); + let mut current_node = 0; let mut path_walked = 0; @@ -880,15 +873,14 @@ impl Trie { let node = self .nodes .get(current_node) - .ok_or_else(|| NodeNotFound(target_key.clone()))?; + .ok_or(NodeNotFound(*target_key))?; if !self.hashed_nodes[current_node] { return Err(ProofError::TrieIsDirty); } self.rlp_encode_node(current_node, &mut buf, proof_store); - let current_node_path = - Nibbles::from_nibbles_unchecked(&target_key.as_slice()[..path_walked]); + let current_node_path = Nibbles::from_nibbles_unchecked(&target_key_vec[..path_walked]); result.proof.push((current_node_path, buf.clone())); match node { @@ -899,13 +891,11 @@ impl Trie { let children = *children; - let n = target_key[path_walked]; + let n = target_key_vec[path_walked]; path_walked += 1; if let Some(child_ptr) = self.branch_node_children[children][n as usize] { - current_node = child_ptr - .as_local() - .ok_or_else(|| NodeNotFound(target_key.clone()))?; + current_node = child_ptr.as_local().ok_or(NodeNotFound(*target_key))?; continue; } @@ -915,18 +905,16 @@ impl Trie { let key = key.clone(); let next_node = *next_node; - if target_key[path_walked..].starts_with(&self.keys[key.clone()]) { + if target_key_vec[path_walked..].starts_with(&self.keys[key.clone()]) { path_walked += key.len(); - current_node = next_node - .as_local() - .ok_or_else(|| NodeNotFound(target_key.clone()))?; + current_node = next_node.as_local().ok_or(NodeNotFound(*target_key))?; continue; } break; } DiffTrieNode::Leaf { key, value } => { - if self.keys[key.clone()] == target_key[path_walked..] { + if self.keys[key.clone()] == target_key_vec[path_walked..] { result.value = Some(self.values[value.clone()].to_vec()); } break; @@ -1038,14 +1026,14 @@ impl Trie { }); } ProofNode::Extension { key, child } => { - let key = &proof_store.keys_guard()[*key]; - let key = self.insert_key(key); + let key_nibbles = proof_store.keys_guard()[*key].to_vec(); + let key = self.insert_key(&key_nibbles); let next_node = NodePtr::Remote(*child); self.push_node(DiffTrieNode::Extension { key, next_node }); } ProofNode::Leaf { key, value } => { - let key = &proof_store.keys_guard()[*key]; - let key = self.insert_key(key); + let key_nibbles = proof_store.keys_guard()[*key].to_vec(); + let key = self.insert_key(&key_nibbles); let value = &proof_store.values_guard()[*value]; let value = self.copy_value(value); self.push_node(DiffTrieNode::Leaf { key, value }); @@ -1057,6 +1045,8 @@ impl Trie { return Ok(()); } + let path_vec = path.to_vec(); + let mut current_node = 0; let mut path_walked = 0; @@ -1064,45 +1054,48 @@ impl Trie { let mut parent_nibble = 0; loop { + let walked_nibbles = Nibbles::from_nibbles_unchecked(&path_vec[..path_walked]); let node = self .nodes .get(current_node) - .ok_or_else(|| NodeNotFound::new(&path[..path_walked]))?; + .ok_or_else(|| NodeNotFound::new(&walked_nibbles))?; self.hashed_nodes[current_node] = false; match node { DiffTrieNode::Branch { children } => { let children = *children; - let n = path[path_walked] as usize; + let n = path_vec[path_walked] as usize; path_walked += 1; - if path[path_walked..].is_empty() { + if path_vec[path_walked..].is_empty() { parent_ptr = self.branch_node_children[children][n]; parent_nibble = n; break; } if let Some(child_ptr) = self.branch_node_children[children][n] { - current_node = child_ptr - .as_local() - .ok_or_else(|| NodeNotFound::new(&path[..path_walked]))?; + current_node = child_ptr.as_local().ok_or_else(|| { + let walked = Nibbles::from_nibbles_unchecked(&path_vec[..path_walked]); + NodeNotFound::new(&walked) + })?; continue; } else { - return Err(NodeNotFound::new(&path[..path_walked])); + let walked = Nibbles::from_nibbles_unchecked(&path_vec[..path_walked]); + return Err(NodeNotFound::new(&walked)); } } DiffTrieNode::Extension { key, next_node } => { let key = key.clone(); let next_node = *next_node; - if path[path_walked..].starts_with(&self.keys[key.clone()]) { + if path_vec[path_walked..].starts_with(&self.keys[key.clone()]) { path_walked += key.len(); - if path[path_walked..].is_empty() { + if path_vec[path_walked..].is_empty() { parent_ptr = Some(next_node); parent_nibble = 0; break; } current_node = next_node.as_local().ok_or_else(|| { - NodeNotFound(Nibbles::from_nibbles_unchecked(&path[..path_walked])) + NodeNotFound(Nibbles::from_nibbles_unchecked(&path_vec[..path_walked])) })?; continue; } @@ -1125,15 +1118,15 @@ impl Trie { let new_node = match node { ProofNode::Leaf { key, value } => { - let key = &proof_store.keys_guard()[*key]; - let key = self.insert_key(key); + let key_nibbles = proof_store.keys_guard()[*key].to_vec(); + let key = self.insert_key(&key_nibbles); let value = &proof_store.values_guard()[*value]; let value = self.copy_value(value); self.push_node(DiffTrieNode::Leaf { key, value }) } ProofNode::Extension { key, child } => { - let key = &proof_store.keys_guard()[*key]; - let key = self.insert_key(key); + let key_nibbles = proof_store.keys_guard()[*key].to_vec(); + let key = self.insert_key(&key_nibbles); let next_node = NodePtr::Remote(*child); self.push_node(DiffTrieNode::Extension { key, next_node }) } diff --git a/crates/eth-sparse-mpt/test_data/failure_case_0.json.gz b/crates/eth-sparse-mpt/test_data/failure_case_0.json.gz index b4b6ed500..bc2339d91 100644 Binary files a/crates/eth-sparse-mpt/test_data/failure_case_0.json.gz and b/crates/eth-sparse-mpt/test_data/failure_case_0.json.gz differ diff --git a/crates/eth-sparse-mpt/test_data/multiproof_0.json.gz b/crates/eth-sparse-mpt/test_data/multiproof_0.json.gz index c344528eb..6c131e880 100644 Binary files a/crates/eth-sparse-mpt/test_data/multiproof_0.json.gz and b/crates/eth-sparse-mpt/test_data/multiproof_0.json.gz differ diff --git a/crates/eth-sparse-mpt/test_data/multiproof_1.json.gz b/crates/eth-sparse-mpt/test_data/multiproof_1.json.gz index edb9d658f..fa6601186 100644 Binary files a/crates/eth-sparse-mpt/test_data/multiproof_1.json.gz and b/crates/eth-sparse-mpt/test_data/multiproof_1.json.gz differ diff --git a/crates/rbuilder-operator/src/bidding_service_wrapper/fast_streams/subscriber_poller.rs b/crates/rbuilder-operator/src/bidding_service_wrapper/fast_streams/subscriber_poller.rs index 8ffc9dd8d..a6a1c84c9 100644 --- a/crates/rbuilder-operator/src/bidding_service_wrapper/fast_streams/subscriber_poller.rs +++ b/crates/rbuilder-operator/src/bidding_service_wrapper/fast_streams/subscriber_poller.rs @@ -93,7 +93,10 @@ impl SubscriberPoll } let delta = offset_datetime_to_timestamp_us(OffsetDateTime::now_utc()) - start; self.poll_duration_stats.add_duration(delta); - if self.total_samples % Self::METRICS_TRACE_INTERVAL == 0 { + if self + .total_samples + .is_multiple_of(Self::METRICS_TRACE_INTERVAL) + { info!( name = self.name, avg_flight_time_us = self.flight_stats.average_duration(), diff --git a/crates/rbuilder-operator/src/flashbots_config.rs b/crates/rbuilder-operator/src/flashbots_config.rs index 1d91e0520..cc07ca45e 100644 --- a/crates/rbuilder-operator/src/flashbots_config.rs +++ b/crates/rbuilder-operator/src/flashbots_config.rs @@ -174,6 +174,7 @@ impl LiveBuilderConfig for FlashbotsConfig { bid_observer, bidding_service.clone(), cancellation_token.clone(), + None, // No EPBS block observer in flashbots config ) .await?; diff --git a/crates/rbuilder-primitives/Cargo.toml b/crates/rbuilder-primitives/Cargo.toml index 10e3b4ee4..cc47288fe 100644 --- a/crates/rbuilder-primitives/Cargo.toml +++ b/crates/rbuilder-primitives/Cargo.toml @@ -24,7 +24,6 @@ revm-inspectors.workspace = true # reth reth-chainspec.workspace = true reth-primitives-traits.workspace = true -reth-primitives.workspace = true reth-ethereum-primitives.workspace = true reth-transaction-pool.workspace = true diff --git a/crates/rbuilder-primitives/src/built_block.rs b/crates/rbuilder-primitives/src/built_block.rs index 5bcf8390f..258bd7fc0 100644 --- a/crates/rbuilder-primitives/src/built_block.rs +++ b/crates/rbuilder-primitives/src/built_block.rs @@ -21,7 +21,9 @@ use alloy_rpc_types_engine::{ ExecutionPayloadV3, }; use reth_chainspec::{ChainSpec, EthereumHardforks}; -use reth_primitives::SealedBlock; +use reth_primitives_traits::SealedBlock; + +type EthSealedBlock = SealedBlock; use std::sync::Arc; #[derive(Clone, Debug)] @@ -83,6 +85,9 @@ impl SignedBuiltBlock { signature: self.signature, })) } + ExecutionPayload::V4(_v4) => { + eyre::bail!("v4 payloads are not supported"); + } } } } @@ -155,7 +160,7 @@ fn marshall_txs_blobs_sidecars_v2( pub fn block_to_execution_payload( chain_spec: &ChainSpec, attrs: &PayloadAttributesData, - sealed_block: &SealedBlock, + sealed_block: &EthSealedBlock, ) -> ExecutionPayload { let transactions = sealed_block .body() @@ -163,19 +168,20 @@ pub fn block_to_execution_payload( .iter() .map(|tx| tx.encoded_2718().into()) .collect(); + let header = sealed_block.header(); let payload_v1 = ExecutionPayloadV1 { - parent_hash: sealed_block.parent_hash, - fee_recipient: sealed_block.beneficiary, - state_root: sealed_block.state_root, - receipts_root: sealed_block.receipts_root, - logs_bloom: sealed_block.logs_bloom, + parent_hash: header.parent_hash, + fee_recipient: header.beneficiary, + state_root: header.state_root, + receipts_root: header.receipts_root, + logs_bloom: header.logs_bloom, prev_randao: attrs.payload_attributes.prev_randao, - block_number: sealed_block.number, - gas_limit: sealed_block.gas_limit, - gas_used: sealed_block.gas_used, - timestamp: sealed_block.timestamp, - extra_data: sealed_block.extra_data.clone(), - base_fee_per_gas: U256::from(sealed_block.base_fee_per_gas.unwrap_or_default()), + block_number: header.number, + gas_limit: header.gas_limit, + gas_used: header.gas_used, + timestamp: header.timestamp, + extra_data: header.extra_data.clone(), + base_fee_per_gas: U256::from(header.base_fee_per_gas.unwrap_or_default()), block_hash: sealed_block.hash(), transactions, }; diff --git a/crates/rbuilder-primitives/src/epbs/bid.rs b/crates/rbuilder-primitives/src/epbs/bid.rs new file mode 100644 index 000000000..2c0cb1a37 --- /dev/null +++ b/crates/rbuilder-primitives/src/epbs/bid.rs @@ -0,0 +1,109 @@ +//! ExecutionPayloadBid types for EPBS. +//! +//! These types represent the builder's commitment to produce an execution payload. +//! See: https://github.com/ethereum/consensus-specs/blob/master/specs/gloas/builder.md + +use alloy_primitives::{Address, BlockHash, Bytes, B256}; +use alloy_rpc_types_beacon::BlsSignature; +use serde::{Deserialize, Serialize}; +use serde_with::{serde_as, DisplayFromStr}; + +/// Signing domain for EPBS builder bids. +/// From consensus-specs/specs/gloas/beacon-chain.md: +/// | DOMAIN_BEACON_BUILDER | DomainType('0x0B000000') | +pub const DOMAIN_BEACON_BUILDER: [u8; 4] = [0x0B, 0x00, 0x00, 0x00]; + +/// from consensus-specs/specs/gloas/beacon-chain.md: +#[serde_as] +#[derive(Debug, Clone, PartialEq, Eq, Hash, Serialize, Deserialize)] +pub struct ExecutionPayloadBid { + /// hash of the current head of execution chain + pub parent_block_hash: BlockHash, + /// hash tree root of the beacon block the proposer will build on + pub parent_block_root: B256, + /// this is the blockhash which the builder constructed the payload + pub block_hash: BlockHash, + /// previous RANDAO of the constructed payload + pub prev_randao: B256, + /// execution address to receive the payment + pub fee_recipient: Address, + /// gas limit of the constructed payload + #[serde_as(as = "DisplayFromStr")] + pub gas_limit: u64, + /// validator index of the builder performing these actions. + #[serde_as(as = "DisplayFromStr")] + pub builder_index: u64, + /// to be the slot for which this bid is aimed. + #[serde_as(as = "DisplayFromStr")] + pub slot: u64, + /// to be the value (in gwei) that the builder will pay the proposer if the bid is accepted + #[serde_as(as = "DisplayFromStr")] + pub value: u64, + /// must be zero for in protocol payments. non-zero only if proposer accepts trusted payments + #[serde_as(as = "DisplayFromStr")] + pub execution_payment: u64, + /// blob commitments for the payload. + /// per spec: List[KZGCommitment, MAX_BLOB_COMMITMENTS_PER_BLOCK] + pub blob_kzg_commitments: Vec, + /// Hash-tree-root of the typed `ExecutionRequests` (deposits, withdrawals, + /// consolidations) committed by this bid. + pub execution_requests_root: B256, +} + +impl ExecutionPayloadBid { + /// Returns the total payment to the proposer (value + execution_payment). + pub fn total_value(&self) -> u64 { + self.value.saturating_add(self.execution_payment) + } + + /// Returns true if this bid uses only in-protocol (beacon chain) payment. + pub fn is_in_protocol_payment(&self) -> bool { + self.execution_payment == 0 + } +} + +/// SignedExecutionPayloadBid is a signed commitment from a builder. +/// +/// signature is created using the builder's validator key and the +/// DOMAIN_BEACON_BUILDER domain. +/// +/// from consensus-specs/specs/gloas/beacon-chain.md: + +#[derive(Debug, Clone, PartialEq, Eq, Hash, Serialize, Deserialize)] +pub struct SignedExecutionPayloadBid { + /// execution payload + pub message: ExecutionPayloadBid, + /// bls signature over the bid using the builder's validator key. + pub signature: BlsSignature, +} + +/// resp for get_bid endpoint. +/// +/// This follows the Builder API spec for EPBS: +/// GET /eth/v1/builder/execution_payload_bid/{slot}/{parent_hash}/{parent_root}/{proposer_index} +#[derive(Debug, Clone, Serialize, Deserialize)] +pub struct GetExecutionPayloadBidResponse { + /// The fork version, e.g., "gloas". + pub version: String, + /// signed bid using validator signature + pub data: SignedExecutionPayloadBid, +} + +/// the params are for the get_bid endpoint following the builder-sepc +#[derive(Debug, Clone)] +pub struct GetBidParams { + /// slot for which the bid is being considered for + pub slot: u64, + /// hash of the parent block the proposer will upon + pub parent_hash: BlockHash, + /// root of the parent block the proposer will build upon + pub parent_root: B256, + /// to be reitrved from the path params + pub proposer_index: u64, + /// address from the X-Fee-Recipient header + pub fee_recipient: Address, + /// timeout ms for request via X-Timeout-Ms header + pub timeout_ms: Option, + /// timestamp from Date-Milliseconds header for latency measurement + pub date_milliseconds: Option, +} diff --git a/crates/rbuilder-primitives/src/epbs/envelope.rs b/crates/rbuilder-primitives/src/epbs/envelope.rs new file mode 100644 index 000000000..e771c047a --- /dev/null +++ b/crates/rbuilder-primitives/src/epbs/envelope.rs @@ -0,0 +1,196 @@ +//! ExecutionPayloadEnvelope types for EPBS. +//! +//! These types represent the full execution payload that the builder reveals +//! after their bid is included in a beacon block. +//! See: https://github.com/ethereum/consensus-specs/blob/master/specs/gloas/builder.md + +use alloy_eips::eip7594::BlobTransactionSidecarVariant; +use alloy_primitives::{Address, Bloom, Bytes, B256, U256}; +use alloy_rpc_types_beacon::BlsSignature; +use serde::{Deserialize, Serialize}; +use serde_with::{serde_as, DisplayFromStr}; +use std::sync::Arc; + +// TODO: check if it can imported from some crate +#[serde_as] +#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)] +pub struct ExecutionPayloadGloas { + pub parent_hash: B256, + pub fee_recipient: Address, + pub state_root: B256, + pub receipts_root: B256, + pub logs_bloom: Bloom, + pub prev_randao: B256, + #[serde_as(as = "DisplayFromStr")] + pub block_number: u64, + #[serde_as(as = "DisplayFromStr")] + pub gas_limit: u64, + #[serde_as(as = "DisplayFromStr")] + pub gas_used: u64, + #[serde_as(as = "DisplayFromStr")] + pub timestamp: u64, + pub extra_data: Bytes, + #[serde_as(as = "DisplayFromStr")] + pub base_fee_per_gas: U256, + pub block_hash: B256, + pub transactions: Vec, + pub withdrawals: Vec, + #[serde_as(as = "DisplayFromStr")] + pub blob_gas_used: u64, + #[serde_as(as = "DisplayFromStr")] + pub excess_blob_gas: u64, + pub block_access_list: Bytes, + #[serde_as(as = "DisplayFromStr")] + pub slot_number: u64, +} + +#[serde_as] +#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)] +pub struct BeaconWithdrawal { + #[serde_as(as = "DisplayFromStr")] + pub index: u64, + #[serde_as(as = "DisplayFromStr")] + pub validator_index: u64, + pub address: Address, + #[serde_as(as = "DisplayFromStr")] + pub amount: u64, +} + +/// ExecutionPayloadEnvelope contains the full execution payload and associated data. +/// +/// This is revealed by the builder after their SignedExecutionPayloadBid is included +/// in a beacon block. The envelope is broadcast on the `execution_payload` P2P topic. +/// + +#[serde_as] +#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)] +pub struct ExecutionPayloadEnvelope { + /// The full Gloas execution payload (V3 fields + block_access_list + slot_number). + pub payload: ExecutionPayloadGloas, + /// Execution requests (deposits, withdrawals, consolidations). + /// TODO: Use proper ExecutionRequests type from Alloy when available. + pub execution_requests: ExecutionRequests, + /// Validator index of the builder. + #[serde_as(as = "DisplayFromStr")] + pub builder_index: u64, + /// Hash tree root of the beacon block that included this builder's bid. + pub beacon_block_root: B256, + /// Hash tree root of the parent of the beacon block that includes this + /// envelope's bid. + pub parent_beacon_block_root: B256, +} + +/// Placeholder for ExecutionRequests until available in Alloy. +/// TODO: Replace with alloy_rpc_types_beacon::requests::ExecutionRequestsV4 or equivalent. +#[derive(Debug, Clone, Default, PartialEq, Eq, Serialize, Deserialize)] +pub struct ExecutionRequests { + /// Deposit requests from the execution layer. + #[serde(default)] + pub deposits: Vec, + /// Withdrawal requests from the execution layer. + #[serde(default)] + pub withdrawals: Vec, + /// Consolidation requests from the execution layer. + #[serde(default)] + pub consolidations: Vec, +} + +/// SignedExecutionPayloadEnvelope is the envelope signed by the builder. +/// +/// From consensus-specs/specs/gloas/beacon-chain.md: +/// ```python +/// class SignedExecutionPayloadEnvelope(Container): +/// message: ExecutionPayloadEnvelope +/// signature: BLSSignature +/// ``` +#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)] +pub struct SignedExecutionPayloadEnvelope { + /// The execution payload envelope message. + pub message: ExecutionPayloadEnvelope, + /// BLS signature over the envelope using the builder's validator key. + pub signature: BlsSignature, +} + +/// Cached payload data stored by the builder after creating a bid. +/// +/// When a builder creates an ExecutionPayloadBid, they must store the full +/// payload data so they can reveal it when/if their bid is accepted. +#[derive(Debug, Clone)] +pub struct CachedPayloadData { + /// The signed bid that was broadcast/returned. + pub bid: super::SignedExecutionPayloadBid, + /// The full execution payload (to be revealed later). + pub payload: ExecutionPayloadGloas, + /// Execution requests associated with the payload. + pub execution_requests: ExecutionRequests, + /// Blob KZG commitments. + pub blob_kzg_commitments: Vec, + /// Reference to the original blob sidecars from the built block. Held by + /// `Arc` so cache inserts are pointer bumps, not 128KB-per-blob copies. + /// Use `blobs()` and `cell_proofs()` to materialize the wire-format + /// `Vec` for the envelope-publish API. + pub sidecars: Vec>, + /// Timestamp when this cache entry was created. + pub created_at: std::time::Instant, +} + +impl CachedPayloadData { + /// Creates a new cached payload entry. + pub fn new( + bid: super::SignedExecutionPayloadBid, + payload: ExecutionPayloadGloas, + execution_requests: ExecutionRequests, + blob_kzg_commitments: Vec, + sidecars: Vec>, + ) -> Self { + Self { + bid, + payload, + execution_requests, + blob_kzg_commitments, + sidecars, + created_at: std::time::Instant::now(), + } + } + + /// Build the envelope from cached data and the beacon block roots. + pub fn build_envelope( + &self, + beacon_block_root: B256, + parent_beacon_block_root: B256, + ) -> ExecutionPayloadEnvelope { + ExecutionPayloadEnvelope { + payload: self.payload.clone(), + execution_requests: self.execution_requests.clone(), + builder_index: self.bid.message.builder_index, + beacon_block_root, + parent_beacon_block_root, + } + } + + /// Materialize raw blob bytes from the sidecars in publish api order + pub fn blobs(&self) -> Vec { + let mut out = Vec::new(); + for sidecar in &self.sidecars { + if let BlobTransactionSidecarVariant::Eip7594(s) = sidecar.as_ref() { + for blob in &s.blobs { + out.push(Bytes::copy_from_slice(blob.as_ref())); + } + } + } + out + } + + /// Materialize the flat list of EIP-7594 cell proofs in publish api order + pub fn cell_proofs(&self) -> Vec { + let mut out = Vec::new(); + for sidecar in &self.sidecars { + if let BlobTransactionSidecarVariant::Eip7594(s) = sidecar.as_ref() { + for proof in &s.cell_proofs { + out.push(Bytes::copy_from_slice(proof.as_slice())); + } + } + } + out + } +} diff --git a/crates/rbuilder-primitives/src/epbs/mod.rs b/crates/rbuilder-primitives/src/epbs/mod.rs new file mode 100644 index 000000000..ac21317d1 --- /dev/null +++ b/crates/rbuilder-primitives/src/epbs/mod.rs @@ -0,0 +1,7 @@ +mod bid; +mod envelope; +mod proposer_preferences; + +pub use bid::*; +pub use envelope::*; +pub use proposer_preferences::*; diff --git a/crates/rbuilder-primitives/src/epbs/proposer_preferences.rs b/crates/rbuilder-primitives/src/epbs/proposer_preferences.rs new file mode 100644 index 000000000..8773f573b --- /dev/null +++ b/crates/rbuilder-primitives/src/epbs/proposer_preferences.rs @@ -0,0 +1,29 @@ +use alloy_primitives::{Address, B256}; +use alloy_rpc_types_beacon::BlsSignature; +use serde::{Deserialize, Serialize}; +use serde_with::{serde_as, DisplayFromStr}; + +/// Proposer preferences broadcast via the `proposer_preferences` gossip topic. +/// from consensus-specs/specs/gloas/p2p-interface.md: +#[serde_as] +#[derive(Debug, Clone, PartialEq, Eq, Hash, Serialize, Deserialize)] +pub struct ProposerPreferences { + pub dependent_root: B256, + /// slot at which the validator will propose. + #[serde_as(as = "DisplayFromStr")] + pub proposal_slot: u64, + ///validator index of the proposer. + #[serde_as(as = "DisplayFromStr")] + pub validator_index: u64, + /// proposers preferred fee recipient + pub fee_recipient: Address, + /// proposer's preferred gas limit + #[serde_as(as = "DisplayFromStr")] + pub gas_limit: u64, +} + +#[derive(Debug, Clone, PartialEq, Eq, Hash, Serialize, Deserialize)] +pub struct SignedProposerPreferences { + pub message: ProposerPreferences, + pub signature: BlsSignature, +} diff --git a/crates/rbuilder-primitives/src/evm_inspector.rs b/crates/rbuilder-primitives/src/evm_inspector.rs index 82dff8287..f12cd7907 100644 --- a/crates/rbuilder-primitives/src/evm_inspector.rs +++ b/crates/rbuilder-primitives/src/evm_inspector.rs @@ -2,7 +2,8 @@ use ahash::HashMap; use alloy_consensus::Transaction; use alloy_primitives::{Address, B256, U256}; use alloy_rpc_types::AccessList; -use reth_primitives::{Recovered, TransactionSigned}; +use reth_ethereum_primitives::TransactionSigned; +use reth_primitives_traits::Recovered; use revm::{ bytecode::opcode, context::ContextTr, diff --git a/crates/rbuilder-primitives/src/lib.rs b/crates/rbuilder-primitives/src/lib.rs index 4a860e50e..5b4a7e82d 100644 --- a/crates/rbuilder-primitives/src/lib.rs +++ b/crates/rbuilder-primitives/src/lib.rs @@ -1,6 +1,7 @@ //! Order types used as elements for block building. pub mod built_block; +pub mod epbs; pub mod evm_inspector; pub mod fmt; pub mod mev_boost; @@ -10,6 +11,7 @@ pub mod serialize; mod test_data_generator; use alloy_consensus::Transaction as _; +use alloy_eips::eip4844::{BYTES_PER_BLOB, BYTES_PER_COMMITMENT, BYTES_PER_PROOF}; use alloy_eips::{ eip2718::{Decodable2718, Eip2718Error, Encodable2718}, eip4844::{Blob, BlobTransactionSidecar, Bytes48, DATA_GAS_PER_BLOB}, @@ -22,10 +24,8 @@ use derivative::Derivative; use evm_inspector::UsedStateTrace; use integer_encoding::VarInt; use reth_ethereum_primitives::PooledTransactionVariant; -use reth_primitives::{ - kzg::{BYTES_PER_BLOB, BYTES_PER_COMMITMENT, BYTES_PER_PROOF}, - Recovered, Transaction, TransactionSigned, -}; +use reth_ethereum_primitives::{Transaction, TransactionSigned}; +use reth_primitives_traits::Recovered; use reth_primitives_traits::{InMemorySize, SignedTransaction as _, SignerRecoverable}; use reth_transaction_pool::{ BlobStore, BlobStoreError, EthPooledTransaction, Pool, TransactionOrdering, TransactionPool, @@ -1138,9 +1138,23 @@ fn can_execute_with_block_base_fee>( } /// Models consumed/reserved space on a block to be able to insert payout tx when finished filling the block. +/// +/// EIP-8037 in glamsterdam the block has two independent gas budgets +/// regular execution gas and state-diff gas. The block-level total written +/// into `header.gas_used` is `max(regular, state)` — see +/// alloy-evm/crates/evm/src/eth/block.rs::EthBlockExecutor::finish. We track +/// both here so the header can be sealed correctly while receipts continue +/// to use cumulative `tx_gas_used = regular + state - refunds` (carried in +/// `gas` for backwards compatibility with everything that already reads it). #[derive(Debug, Clone, Copy, Default, PartialEq, Eq, Hash)] pub struct BlockSpace { pub gas: u64, + /// EIP-8037 regular execution gas used. Sum per-tx of + /// `block_regular_gas_used()`. Bounded by the block gas limit. + pub regular_gas: u64, + /// EIP-8037 state-diff gas used. Sum per-tx of `block_state_gas_used()`. + /// Bounded independently by the block gas limit. + pub state_gas: u64, /// EIP-7934 limits the size of the final rlp block. /// Estimation of the sum of the rlp txs sizes. pub rlp_length: usize, @@ -1151,6 +1165,26 @@ impl BlockSpace { pub fn new(gas: u64, rlp_length: usize, blob_gas: u64) -> Self { Self { gas, + regular_gas: 0, + state_gas: 0, + rlp_length, + blob_gas, + } + } + + /// Construct with explicit EIP-8037 regular/state gas split. `gas` should + /// be `tx_gas_used` (the receipt-cumulative value). + pub fn new_split( + gas: u64, + regular_gas: u64, + state_gas: u64, + rlp_length: usize, + blob_gas: u64, + ) -> Self { + Self { + gas, + regular_gas, + state_gas, rlp_length, blob_gas, } @@ -1158,6 +1192,8 @@ impl BlockSpace { pub const ZERO: Self = Self { gas: 0, + regular_gas: 0, + state_gas: 0, rlp_length: 0, blob_gas: 0, }; @@ -1166,6 +1202,8 @@ impl BlockSpace { impl std::ops::AddAssign for BlockSpace { fn add_assign(&mut self, other: Self) { self.gas += other.gas; + self.regular_gas += other.regular_gas; + self.state_gas += other.state_gas; self.rlp_length += other.rlp_length; self.blob_gas += other.blob_gas; } @@ -1177,6 +1215,8 @@ impl std::ops::Add for BlockSpace { fn add(self, other: Self) -> Self { Self { gas: self.gas + other.gas, + regular_gas: self.regular_gas + other.regular_gas, + state_gas: self.state_gas + other.state_gas, rlp_length: self.rlp_length + other.rlp_length, blob_gas: self.blob_gas + other.blob_gas, } @@ -1186,6 +1226,8 @@ impl std::ops::Add for BlockSpace { impl std::ops::SubAssign for BlockSpace { fn sub_assign(&mut self, other: Self) { self.gas = self.gas.checked_sub(other.gas).unwrap(); + self.regular_gas = self.regular_gas.checked_sub(other.regular_gas).unwrap(); + self.state_gas = self.state_gas.checked_sub(other.state_gas).unwrap(); self.rlp_length = self.rlp_length.checked_sub(other.rlp_length).unwrap(); self.blob_gas = self.blob_gas.checked_sub(other.blob_gas).unwrap(); } @@ -1196,7 +1238,7 @@ mod tests { use super::*; use alloy_consensus::TxLegacy; use alloy_primitives::{fixed_bytes, Signature}; - use reth_primitives::{Transaction, TransactionSigned}; + use reth_ethereum_primitives::{Transaction, TransactionSigned}; use uuid::uuid; #[test] diff --git a/crates/rbuilder-primitives/src/mev_boost/ssz_roots.rs b/crates/rbuilder-primitives/src/mev_boost/ssz_roots.rs index eb5d3029f..91f42b92a 100644 --- a/crates/rbuilder-primitives/src/mev_boost/ssz_roots.rs +++ b/crates/rbuilder-primitives/src/mev_boost/ssz_roots.rs @@ -145,3 +145,37 @@ pub fn sha_pair(a: &B256, b: &B256) -> B256 { h.update(b); B256::from_slice(&h.finalize()) } + +/// KZG commitment is 48 bytes. +#[derive(tree_hash_derive::TreeHash)] +struct KzgCommitment { + inner: FixedVector, +} + +impl From<&[u8]> for KzgCommitment { + fn from(bytes: &[u8]) -> Self { + let mut inner = vec![0u8; 48]; + let len = bytes.len().min(48); + inner[..len].copy_from_slice(&bytes[..len]); + Self { + inner: FixedVector::from(inner), + } + } +} + +/// MAX_BLOB_COMMITMENTS_PER_BLOCK for Gloas. +type MaxBlobCommitmentsPerBlock = typenum::U4096; + +/// Calculate SSZ hash_tree_root for blob KZG commitments. +/// +/// This computes the Merkle root of the list of KZG commitments as required +/// by the consensus specs for ExecutionPayloadBid.blob_kzg_commitments_root. +pub fn calculate_blob_kzg_commitments_root_ssz(commitments: &[impl AsRef<[u8]>]) -> B256 { + let commitments: VariableList = VariableList::from( + commitments + .iter() + .map(|c| KzgCommitment::from(c.as_ref())) + .collect::>(), + ); + B256::from_slice(&commitments.tree_hash_root()[..]) +} diff --git a/crates/rbuilder-primitives/src/test_data_generator.rs b/crates/rbuilder-primitives/src/test_data_generator.rs index c8b3017f7..9dff02313 100644 --- a/crates/rbuilder-primitives/src/test_data_generator.rs +++ b/crates/rbuilder-primitives/src/test_data_generator.rs @@ -4,7 +4,8 @@ use super::{ }; use alloy_consensus::TxLegacy; use alloy_primitives::{Address, BlockHash, Signature, TxHash, B256, U256}; -use reth_primitives::{Recovered, Transaction, TransactionSigned}; +use reth_ethereum_primitives::{Transaction, TransactionSigned}; +use reth_primitives_traits::Recovered; use uuid::Uuid; /// TestDataGenerator allows you to create unique test objects with unique content, it tries to use different numbers for every field it sets since it may help debugging. diff --git a/crates/rbuilder-rebalancer/Cargo.toml b/crates/rbuilder-rebalancer/Cargo.toml index f1d151920..a82624283 100644 --- a/crates/rbuilder-rebalancer/Cargo.toml +++ b/crates/rbuilder-rebalancer/Cargo.toml @@ -43,4 +43,4 @@ clap.workspace = true eyre.workspace = true toml.workspace = true tracing.workspace = true -reqwest.workspace = true +reqwest = { workspace = true, features = ["json"] } diff --git a/crates/rbuilder/Cargo.toml b/crates/rbuilder/Cargo.toml index 268a7b711..ff65324c6 100644 --- a/crates/rbuilder/Cargo.toml +++ b/crates/rbuilder/Cargo.toml @@ -28,10 +28,11 @@ reth-db.workspace = true reth-errors.workspace = true reth-payload-builder.workspace = true reth-trie.workspace = true +reth-trie-db.workspace = true reth-trie-parallel.workspace = true reth-node-api.workspace = true reth-node-core.workspace = true -reth-primitives.workspace = true +reth-ethereum-primitives.workspace = true reth-primitives-traits.workspace = true reth-provider.workspace = true reth-chainspec.workspace = true @@ -39,6 +40,7 @@ reth-evm.workspace = true reth-evm-ethereum.workspace = true revm.workspace = true reth-node-ethereum.workspace = true +reth-tasks.workspace = true alloy-primitives.workspace = true alloy-rlp.workspace = true @@ -58,11 +60,15 @@ alloy-eips.workspace = true alloy-trie.workspace = true ethereum_ssz.workspace = true +lighthouse_types.workspace = true +lighthouse_bls.workspace = true +lighthouse_ssz_types.workspace = true +tree_hash.workspace = true test_utils = { path = "src/test_utils" } metrics_macros = { path = "src/telemetry/metrics_macros" } -reqwest = { workspace = true, features = ["blocking"] } +reqwest = { workspace = true, features = ["blocking", "json"] } serde_with = { workspace = true, features = ["time_0_3"] } url.workspace = true sqlx = { version = "0.7.1", features = [ @@ -114,6 +120,9 @@ derivative.workspace = true mockall = "0.12.1" shellexpand = "3.1.0" async-trait = "0.1.80" +axum = "0.7" +hex = "0.4" +tower = "0.4" eth-sparse-mpt.workspace = true bid-scraper.workspace = true sysperf.workspace = true diff --git a/crates/rbuilder/benches/benchmarks/mev_boost.rs b/crates/rbuilder/benches/benchmarks/mev_boost.rs index 9a0f93848..1c6309349 100644 --- a/crates/rbuilder/benches/benchmarks/mev_boost.rs +++ b/crates/rbuilder/benches/benchmarks/mev_boost.rs @@ -5,8 +5,10 @@ use alloy_rpc_types_beacon::relay::SubmitBlockRequest as AlloySubmitBlockRequest use alloy_rpc_types_beacon::BlsPublicKey; use criterion::{criterion_group, Criterion}; use rbuilder::mev_boost::{rpc::TestDataGenerator, sign_block_for_relay, BLSBlockSigner}; -use reth::primitives::SealedBlock; -use reth_primitives::kzg::Blob; +use reth_primitives_traits::SealedBlock; + +type EthSealedBlock = SealedBlock>; +use alloy_eips::eip4844::Blob; use ssz::Encode; use std::{fs, path::PathBuf, sync::Arc}; @@ -54,19 +56,17 @@ fn bench_mevboost_sign(c: &mut Criterion) { serde_json::from_str(&json_content).expect("Failed to deserialize JSON"); // Extract blob data from JSON and convert it to Blob - let blobs: Vec = vec![Blob::from_hex( - json_value - .get("data") - .unwrap() - .as_str() - .expect("Data is not a valid string"), - ) - .unwrap()]; + let blob_hex = json_value + .get("data") + .unwrap() + .as_str() + .expect("Data is not a valid string"); + let blobs: Vec = vec![blob_hex.parse().unwrap()]; // Generate a BlobTransactionSidecar from the blobs let blob = BlobTransactionSidecar::try_from_blobs(blobs).unwrap(); - let sealed_block = SealedBlock::default(); + let sealed_block = EthSealedBlock::default(); let signer = BLSBlockSigner::test_signer(); let mut blobs = vec![]; for _ in 0..3 { @@ -95,7 +95,7 @@ fn bench_mevboost_sign(c: &mut Criterion) { // Create a sealed block that is after the Cancun hard fork in Sepolia // this is, a timestamp higher than 1706655072 - let sealed_block_deneb = SealedBlock::new_unhashed(Block::new( + let sealed_block_deneb = EthSealedBlock::new_unhashed(Block::new( Header { timestamp: 2706655072, blob_gas_used: Some(64), diff --git a/crates/rbuilder/src/backtest/build_block/full_partial_block_execution_tracer.rs b/crates/rbuilder/src/backtest/build_block/full_partial_block_execution_tracer.rs index 4b8020c22..72b08466b 100644 --- a/crates/rbuilder/src/backtest/build_block/full_partial_block_execution_tracer.rs +++ b/crates/rbuilder/src/backtest/build_block/full_partial_block_execution_tracer.rs @@ -274,29 +274,17 @@ impl PartialBlockForkExecutionTracer for FullPartialBlockExecutionTracer { }; let (result, coinbase_delta, gas_used) = match &res { Ok(Ok(tx_ok)) => match tx_ok.exec_result { - revm::context::result::ExecutionResult::Success { - reason: _, - gas_used: _, - gas_refunded: _, - logs: _, - output: _, - } => ( + revm::context::result::ExecutionResult::Success { .. } => ( SimpleTxExecutionResult::OkSuccess, tx_ok.tx_info.coinbase_profit, tx_ok.tx_info.space_used.gas, ), - revm::context::result::ExecutionResult::Revert { - gas_used: _, - output: _, - } => ( + revm::context::result::ExecutionResult::Revert { .. } => ( SimpleTxExecutionResult::OkRevert, tx_ok.tx_info.coinbase_profit, tx_ok.tx_info.space_used.gas, ), - revm::context::result::ExecutionResult::Halt { - reason: _, - gas_used: _, - } => ( + revm::context::result::ExecutionResult::Halt { .. } => ( SimpleTxExecutionResult::OkHalt, tx_ok.tx_info.coinbase_profit, tx_ok.tx_info.space_used.gas, diff --git a/crates/rbuilder/src/backtest/restore_landed_orders/resim_landed_block.rs b/crates/rbuilder/src/backtest/restore_landed_orders/resim_landed_block.rs index a4141a7fb..fa9e8ecd6 100644 --- a/crates/rbuilder/src/backtest/restore_landed_orders/resim_landed_block.rs +++ b/crates/rbuilder/src/backtest/restore_landed_orders/resim_landed_block.rs @@ -14,7 +14,8 @@ use alloy_primitives::{TxHash, B256, I256}; use eyre::Context; use rbuilder_primitives::evm_inspector::SlotKey; use reth_chainspec::ChainSpec; -use reth_primitives::{Receipt, Recovered, TransactionSigned}; +use reth_ethereum_primitives::{Receipt, TransactionSigned}; +use reth_primitives_traits::Recovered; use std::sync::Arc; #[derive(Debug)] diff --git a/crates/rbuilder/src/backtest/store.rs b/crates/rbuilder/src/backtest/store.rs index eaec978f9..a6a052eb3 100644 --- a/crates/rbuilder/src/backtest/store.rs +++ b/crates/rbuilder/src/backtest/store.rs @@ -696,7 +696,7 @@ mod test { serialize::{RawBundle, RawBundleMetadata, RawTx}, BundleReplacementKey, LAST_BUNDLE_VERSION, }; - use reth_primitives::Recovered; + use reth_primitives_traits::Recovered; use time::OffsetDateTime; use uuid::uuid; @@ -850,6 +850,7 @@ mod test { ), block_hash: Some(B256::with_last_byte(3)), block_number: Some(4), + block_timestamp: None, transaction_index: Some(5), effective_gas_price: Some(7), } diff --git a/crates/rbuilder/src/beacon_api_client/mod.rs b/crates/rbuilder/src/beacon_api_client/mod.rs index 6fb05c7e7..be3c7cfbd 100644 --- a/crates/rbuilder/src/beacon_api_client/mod.rs +++ b/crates/rbuilder/src/beacon_api_client/mod.rs @@ -1,16 +1,110 @@ +use alloy_primitives::B256; use alloy_rpc_types_beacon::events::PayloadAttributesEvent; use beacon_api_client::{mainnet::Client as bClient, Error, Topic}; use mev_share_sse::client::EventStream; -use serde::Deserialize; +use rbuilder_primitives::epbs::{ + ExecutionPayloadEnvelope, SignedExecutionPayloadBid, SignedExecutionPayloadEnvelope, + SignedProposerPreferences, +}; +use serde::{Deserialize, Serialize}; +use serde_with::{serde_as, DisplayFromStr}; use std::{collections::HashMap, fmt::Debug}; use url::Url; +#[derive(Debug, Clone, Deserialize)] +pub struct GenesisData { + #[serde(with = "serde_utils::quoted_u64")] + pub genesis_time: u64, + pub genesis_validators_root: B256, + #[serde(with = "serde_utils::bytes_4_hex")] + pub genesis_fork_version: [u8; 4], +} + +#[derive(Debug, Clone, Deserialize)] +struct GenesisResponse { + data: GenesisData, +} + +/// Validator data from the beacon chain. +#[derive(Debug, Clone, Deserialize)] +pub struct ValidatorData { + /// validator index + #[serde(with = "serde_utils::quoted_u64")] + pub index: u64, + /// validators balance in gwei + #[serde(with = "serde_utils::quoted_u64")] + pub balance: u64, + /// validators status + pub status: String, + /// validator details + pub validator: ValidatorDetails, +} + +/// Detailed validator information. +#[derive(Debug, Clone, Deserialize)] +pub struct ValidatorDetails { + pub pubkey: String, + pub withdrawal_credentials: String, + #[serde(with = "serde_utils::quoted_u64")] + pub effective_balance: u64, + pub slashed: bool, + #[serde(with = "serde_utils::quoted_u64")] + pub activation_eligibility_epoch: u64, + #[serde(with = "serde_utils::quoted_u64")] + pub activation_epoch: u64, + #[serde(with = "serde_utils::quoted_u64")] + pub exit_epoch: u64, + #[serde(with = "serde_utils::quoted_u64")] + pub withdrawable_epoch: u64, +} + +#[derive(Debug, Clone, Deserialize)] +struct ValidatorResponse { + data: ValidatorData, +} + +mod serde_utils { + use serde::{Deserialize, Deserializer}; + + pub mod quoted_u64 { + use super::*; + + pub fn deserialize<'de, D>(deserializer: D) -> Result + where + D: Deserializer<'de>, + { + let s = String::deserialize(deserializer)?; + s.parse().map_err(serde::de::Error::custom) + } + } + + pub mod bytes_4_hex { + use super::*; + + pub fn deserialize<'de, D>(deserializer: D) -> Result<[u8; 4], D::Error> + where + D: Deserializer<'de>, + { + let s = String::deserialize(deserializer)?; + let s = s.strip_prefix("0x").unwrap_or(&s); + let bytes = hex::decode(s).map_err(serde::de::Error::custom)?; + if bytes.len() != 4 { + return Err(serde::de::Error::custom("expected 4 bytes")); + } + let mut arr = [0u8; 4]; + arr.copy_from_slice(&bytes); + Ok(arr) + } + } +} + pub const DEFAULT_CL_NODE_URL: &str = "http://localhost:8000"; #[derive(Deserialize, Clone)] #[serde(try_from = "String")] pub struct Client { inner: bClient, + endpoint_url: Url, } impl Debug for Client { @@ -21,8 +115,10 @@ impl Debug for Client { impl Default for Client { fn default() -> Self { + let url = Url::parse(DEFAULT_CL_NODE_URL).unwrap(); Self { - inner: bClient::new(Url::parse(DEFAULT_CL_NODE_URL).unwrap()), + inner: bClient::new(url.clone()), + endpoint_url: url, } } } @@ -30,17 +126,406 @@ impl Default for Client { impl Client { pub fn new(endpoint: Url) -> Self { Self { - inner: bClient::new(endpoint), + inner: bClient::new(endpoint.clone()), + endpoint_url: endpoint, } } + pub fn endpoint(&self) -> &Url { + &self.endpoint_url + } + pub async fn get_spec(&self) -> Result, Error> { self.inner.get_spec().await } + pub async fn get_seconds_per_slot(&self) -> eyre::Result { + let url = self + .endpoint_url + .join("eth/v1/config/spec") + .map_err(|e| eyre::eyre!("Invalid URL: {}", e))?; + + let response = reqwest::Client::new() + .get(url) + .header("Accept", "application/json") + .send() + .await?; + + if !response.status().is_success() { + let status = response.status(); + let body = response.text().await.unwrap_or_default(); + return Err(eyre::eyre!( + "Failed to fetch chain spec: {} - {}", + status, + body + )); + } + + let body: serde_json::Value = response.json().await?; + let raw = body + .get("data") + .and_then(|d| d.get("SECONDS_PER_SLOT")) + .and_then(|v| v.as_str()) + .ok_or_else(|| eyre::eyre!("Chain spec response missing data.SECONDS_PER_SLOT"))?; + raw.parse::() + .map_err(|e| eyre::eyre!("Failed to parse SECONDS_PER_SLOT='{}': {}", raw, e)) + } + pub async fn get_events(&self) -> Result, Error> { self.inner.get_events::().await } + + /// Fetch genesis data from the beacon chain. + /// Returns the genesis time, genesis validators root, and genesis fork version. + pub async fn get_genesis(&self) -> eyre::Result { + let url = self + .endpoint_url + .join("eth/v1/beacon/genesis") + .map_err(|e| eyre::eyre!("Invalid URL: {}", e))?; + + let response = reqwest::get(url).await?; + + if !response.status().is_success() { + return Err(eyre::eyre!("Failed to get genesis: {}", response.status())); + } + + let genesis_response: GenesisResponse = response.json().await?; + + Ok(genesis_response.data) + } + + /// Fetch the active fork version at head + pub async fn get_head_fork_version(&self) -> eyre::Result<[u8; 4]> { + let url = self + .endpoint_url + .join("eth/v1/beacon/states/head/fork") + .map_err(|e| eyre::eyre!("Invalid URL: {}", e))?; + + let response = reqwest::get(url).await?; + if !response.status().is_success() { + return Err(eyre::eyre!("Failed to get fork: {}", response.status())); + } + + let val: serde_json::Value = response.json().await?; + let current_version = val + .get("data") + .and_then(|d| d.get("current_version")) + .and_then(|v| v.as_str()) + .ok_or_else(|| eyre::eyre!("No current_version in fork response"))?; + + let s = current_version + .strip_prefix("0x") + .unwrap_or(current_version); + let bytes = hex::decode(s).map_err(|e| eyre::eyre!("Invalid fork hex: {}", e))?; + if bytes.len() != 4 { + return Err(eyre::eyre!( + "Expected 4-byte fork version, got {}", + bytes.len() + )); + } + let mut arr = [0u8; 4]; + arr.copy_from_slice(&bytes); + Ok(arr) + } + + /// Fetch validator data from the beacon chain by pubkey or index. + /// + /// The `validator_id` can be either: + /// - A hex encoded BLS public key + /// - A validator index as a string + pub async fn get_validator(&self, validator_id: &str) -> eyre::Result { + let path = format!("eth/v1/beacon/states/head/validators/{}", validator_id); + let url = self + .endpoint_url + .join(&path) + .map_err(|e| eyre::eyre!("Invalid URL: {}", e))?; + + let response = reqwest::get(url).await?; + + if response.status() == reqwest::StatusCode::NOT_FOUND { + return Err(eyre::eyre!( + "Validator not found: {}. Make sure the builder validator is registered and active on the beacon chain.", + validator_id + )); + } + + if !response.status().is_success() { + let status = response.status(); + let body = response.text().await.unwrap_or_default(); + return Err(eyre::eyre!( + "Failed to get validator {}: {} - {}", + validator_id, + status, + body + )); + } + + let validator_response: ValidatorResponse = response.json().await?; + + Ok(validator_response.data) + } + + /// Fetch validator data from the beacon chain by BLS public key. + /// jut a helper method that formats the public key correctly. + pub async fn get_validator_by_pubkey(&self, pubkey: &[u8]) -> eyre::Result { + let pubkey_hex = format!("0x{}", hex::encode(pubkey)); + self.get_validator(&pubkey_hex).await + } + + /// Fetch a builder's index and `deposit_epoch` from the beacon state by BLS + /// public key. + pub async fn get_builder_entry_by_pubkey(&self, pubkey: &[u8]) -> eyre::Result<(u64, u64)> { + let pubkey_hex = format!("0x{}", hex::encode(pubkey)); + + let url = self + .endpoint_url + .join("eth/v2/debug/beacon/states/head") + .map_err(|e| eyre::eyre!("Invalid URL: {}", e))?; + + let response = reqwest::Client::new() + .get(url) + .header("Accept", "application/json") + .send() + .await?; + + if !response.status().is_success() { + let status = response.status(); + let body = response.text().await.unwrap_or_default(); + return Err(eyre::eyre!( + "Failed to fetch beacon state: {} - {}", + status, + body + )); + } + + // parse only the builders field from the state to avoid deserializing everything + let state_response: serde_json::Value = response.json().await?; + let builders = state_response + .get("data") + .and_then(|d| d.get("builders")) + .and_then(|b| b.as_array()) + .ok_or_else(|| { + eyre::eyre!( + "Beacon state does not contain builders field. \ + Is the chain at Gloas fork yet?" + ) + })?; + + for (index, builder) in builders.iter().enumerate() { + let pk = match builder.get("pubkey").and_then(|p| p.as_str()) { + Some(pk) => pk, + None => continue, + }; + if pk != pubkey_hex { + continue; + } + let deposit_epoch_str = builder + .get("deposit_epoch") + .and_then(|d| d.as_str()) + .ok_or_else(|| { + eyre::eyre!("Builder entry at index {} is missing deposit_epoch", index) + })?; + let deposit_epoch: u64 = deposit_epoch_str.parse().map_err(|e| { + eyre::eyre!( + "Failed to parse deposit_epoch '{}': {}", + deposit_epoch_str, + e + ) + })?; + return Ok((index as u64, deposit_epoch)); + } + + Err(eyre::eyre!( + "Builder with pubkey {} not found in beacon state builders registry. \ + Make sure the builder has been deposited with BUILDER_WITHDRAWAL_PREFIX (0x03).", + pubkey_hex + )) + } + + /// Fetch the current finalized epoch + pub async fn get_finalized_epoch(&self) -> eyre::Result { + let url = self + .endpoint_url + .join("eth/v1/beacon/states/head/finality_checkpoints") + .map_err(|e| eyre::eyre!("Invalid URL: {}", e))?; + + let response = reqwest::Client::new() + .get(url) + .header("Accept", "application/json") + .send() + .await?; + + if !response.status().is_success() { + let status = response.status(); + let body = response.text().await.unwrap_or_default(); + return Err(eyre::eyre!( + "Failed to fetch finality checkpoints: {} - {}", + status, + body + )); + } + + let body: serde_json::Value = response.json().await?; + let epoch_str = body + .get("data") + .and_then(|d| d.get("finalized")) + .and_then(|f| f.get("epoch")) + .and_then(|e| e.as_str()) + .ok_or_else(|| { + eyre::eyre!("finality_checkpoints response missing data.finalized.epoch") + })?; + epoch_str + .parse::() + .map_err(|e| eyre::eyre!("Failed to parse finalized epoch '{}': {}", epoch_str, e)) + } + + /// Submit a signed execution payload bid to p2p via the beacon node. + pub async fn submit_execution_payload_bid( + &self, + bid: &SignedExecutionPayloadBid, + ) -> eyre::Result<()> { + let url = self + .endpoint_url + .join("eth/v1/beacon/execution_payload_bid") + .map_err(|e| eyre::eyre!("Invalid URL: {}", e))?; + + let response = reqwest::Client::new() + .post(url) + .header("Eth-Consensus-Version", "gloas") + .json(bid) + .send() + .await?; + + if !response.status().is_success() { + let status = response.status(); + let body = response.text().await.unwrap_or_default(); + return Err(eyre::eyre!( + "Failed to submit execution payload bid: {} - {}", + status, + body + )); + } + + Ok(()) + } + + /// Submit a signed execution payload envelope to p2p via the beacon node. + pub async fn submit_execution_payload_envelope( + &self, + envelope: &SignedExecutionPayloadEnvelope, + blobs: &[alloy_primitives::Bytes], + cell_proofs: &[alloy_primitives::Bytes], + ) -> eyre::Result<()> { + let url = self + .endpoint_url + .join("eth/v1/beacon/execution_payload_envelope") + .map_err(|e| eyre::eyre!("Invalid URL: {}", e))?; + + let body = PublishEnvelopeRequest { + message: &envelope.message, + signature: &envelope.signature, + blobs: blobs.iter().map(hex_encode).collect(), + cell_proofs: cell_proofs.iter().map(hex_encode).collect(), + }; + + // Bound the envelope reveal POST so a stuck cl cannot leak our spawned + // reveal task indefinitely. + // TODO: revisit the timeout value + const ENVELOPE_REVEAL_TIMEOUT: std::time::Duration = std::time::Duration::from_millis(5500); + let response = reqwest::Client::new() + .post(url) + .header("Eth-Consensus-Version", "gloas") + .json(&body) + .timeout(ENVELOPE_REVEAL_TIMEOUT) + .send() + .await + .map_err(|e| { + if e.is_timeout() { + eyre::eyre!( + "Envelope reveal post timed out after {:?}", + ENVELOPE_REVEAL_TIMEOUT + ) + } else { + eyre::eyre!("Envelope reveal POST failed: {}", e) + } + })?; + + if !response.status().is_success() { + let status = response.status(); + let body = response.text().await.unwrap_or_default(); + return Err(eyre::eyre!( + "Failed to submit execution payload envelope: {} - {}", + status, + body + )); + } + + Ok(()) + } + + /// Fetch a beacon blocks `signed_execution_payload_bid` and `parent_root`. + /// + /// used at reveal time: + /// * the bid tells us which block_hash the proposer committed to (so we + /// can look up the matching cached payload) and + /// * `parent_root` is what the envelope's `parent_beacon_block_root` + /// field must be set to + pub async fn get_beacon_block_bid( + &self, + block_id: &str, + ) -> eyre::Result> { + let path = format!("eth/v2/beacon/blocks/{}", block_id); + let url = self + .endpoint_url + .join(&path) + .map_err(|e| eyre::eyre!("Invalid URL: {}", e))?; + + let response = reqwest::get(url).await?; + + if response.status() == reqwest::StatusCode::NOT_FOUND { + return Ok(None); + } + + if !response.status().is_success() { + let status = response.status(); + let body = response.text().await.unwrap_or_default(); + return Err(eyre::eyre!( + "Failed to get beacon block {}: {} - {}", + block_id, + status, + body + )); + } + + let block_response: serde_json::Value = response.json().await?; + let message = block_response + .get("data") + .and_then(|d| d.get("message")) + .ok_or_else(|| eyre::eyre!("Missing data.message in beacon block response"))?; + + let parent_root = message + .get("parent_root") + .and_then(|v| v.as_str()) + .ok_or_else(|| eyre::eyre!("Missing parent_root in beacon block message"))?; + let parent_root: B256 = parent_root + .parse() + .map_err(|e| eyre::eyre!("Invalid parent_root hex: {}", e))?; + + let bid = message + .get("body") + .and_then(|b| b.get("signed_execution_payload_bid")) + .map(|bid_value| serde_json::from_value::(bid_value.clone())) + .transpose() + .map_err(|e| eyre::eyre!("Failed to parse bid from block: {}", e))?; + + Ok(bid.map(|bid| BeaconBlockBidInfo { bid, parent_root })) + } +} + +#[derive(Debug, Clone)] +pub struct BeaconBlockBidInfo { + pub bid: SignedExecutionPayloadBid, + pub parent_root: B256, } impl TryFrom for Client { @@ -48,7 +533,10 @@ impl TryFrom for Client { fn try_from(s: String) -> Result { let url = Url::parse(&s)?; - Ok(Client::new(url)) + Ok(Self { + inner: bClient::new(url.clone()), + endpoint_url: url, + }) } } @@ -60,6 +548,69 @@ impl Topic for PayloadAttributesTopic { type Data = PayloadAttributesEvent; } +/// SSE topic for head events from the beacon node. +pub struct HeadTopic; + +impl Topic for HeadTopic { + const NAME: &'static str = "head"; + + type Data = HeadEvent; +} + +/// SSE topic for execution payload bid events. +pub struct ExecutionPayloadBidTopic; + +impl Topic for ExecutionPayloadBidTopic { + const NAME: &'static str = "execution_payload_bid"; + + type Data = SignedExecutionPayloadBid; +} + +/// SSE topic for proposer preferences events. +pub struct ProposerPreferencesTopic; + +#[derive(Debug, Clone, serde::Deserialize)] +pub struct ProposerPreferencesEvent { + #[allow(dead_code)] + pub version: String, + pub data: SignedProposerPreferences, +} + +impl Topic for ProposerPreferencesTopic { + const NAME: &'static str = "proposer_preferences"; + + type Data = ProposerPreferencesEvent; +} + +/// Head event from the beacon node SSE stream. +#[serde_as] +#[derive(Debug, Clone, Deserialize)] +pub struct HeadEvent { + #[serde_as(as = "DisplayFromStr")] + pub slot: u64, + pub block: B256, + /// state root of the new head state. + pub state: B256, + #[serde(default)] + pub execution_optimistic: bool, +} + +/// Request body for POST /eth/v1/beacon/execution_payload_envelope. +/// TODO: verify the struct +#[derive(Debug, Clone, Serialize)] +struct PublishEnvelopeRequest<'a> { + message: &'a ExecutionPayloadEnvelope, + signature: &'a alloy_rpc_types_beacon::BlsSignature, + #[serde(skip_serializing_if = "Vec::is_empty")] + blobs: Vec, + #[serde(skip_serializing_if = "Vec::is_empty")] + cell_proofs: Vec, +} + +fn hex_encode(b: &alloy_primitives::Bytes) -> String { + format!("0x{}", hex::encode(b.as_ref())) +} + #[cfg(test)] mod tests { // TODO: Enable these tests. diff --git a/crates/rbuilder/src/bin/debug-bench-machine.rs b/crates/rbuilder/src/bin/debug-bench-machine.rs index 2268fa3d0..8a9c30e33 100644 --- a/crates/rbuilder/src/bin/debug-bench-machine.rs +++ b/crates/rbuilder/src/bin/debug-bench-machine.rs @@ -24,7 +24,6 @@ use rbuilder::{ use rbuilder_config::load_toml_config; use rbuilder_primitives::mev_boost::SubmitBlockRequest; use reth_primitives_traits::SignerRecoverable; -use reth_provider::StateProvider; use std::{path::PathBuf, sync::Arc, time::Instant}; use tracing::{debug, info}; @@ -104,11 +103,11 @@ async fn main() -> eyre::Result<()> { mev_blocker_price, ); - let state_provider = Arc::::from( + let state_provider = Arc::new(rbuilder::building::SyncStateProvider::new( provider_factory .provider_factory_unchecked() .history_by_block_number(last_block)?, - ); + )); let mut build_times_ms = Vec::new(); let mut finalize_time_ms = Vec::new(); diff --git a/crates/rbuilder/src/bin/run-bundle-on-prefix.rs b/crates/rbuilder/src/bin/run-bundle-on-prefix.rs index 57d783b24..9eefb85c1 100644 --- a/crates/rbuilder/src/bin/run-bundle-on-prefix.rs +++ b/crates/rbuilder/src/bin/run-bundle-on-prefix.rs @@ -156,9 +156,9 @@ impl LandedBlockInfo { .config .base_config() .create_reth_provider_factory(true)?; - let block_state = provider - .history_by_block_hash(ctx.attributes.parent)? - .into(); + let block_state = std::sync::Arc::new(rbuilder::building::SyncStateProvider::new( + provider.history_by_block_hash(ctx.attributes.parent)?, + )); let order_statistics = OrderStatistics::new(); Ok(BlockBuildingHelperFromProvider::new( BuiltBlockId::ZERO, diff --git a/crates/rbuilder/src/building/bid_adjustments.rs b/crates/rbuilder/src/building/bid_adjustments.rs index f5639f902..99b005aa9 100644 --- a/crates/rbuilder/src/building/bid_adjustments.rs +++ b/crates/rbuilder/src/building/bid_adjustments.rs @@ -4,7 +4,7 @@ use rbuilder_primitives::mev_boost::{ ssz_roots::{tx_ssz_leaf_root, CompactSszTransactionTree}, BidAdjustmentStateProofs, }; -use reth_primitives::TransactionSigned; +use reth_ethereum_primitives::TransactionSigned; use std::collections::{HashMap, HashSet}; use tracing::*; diff --git a/crates/rbuilder/src/building/builders/block_building_helper.rs b/crates/rbuilder/src/building/builders/block_building_helper.rs index 5bbd70d34..408486c01 100644 --- a/crates/rbuilder/src/building/builders/block_building_helper.rs +++ b/crates/rbuilder/src/building/builders/block_building_helper.rs @@ -1,5 +1,6 @@ +use crate::building::SyncStateProvider; use alloy_primitives::{utils::format_ether, Address, TxHash, I256, U256}; -use reth_provider::StateProvider; +use reth_chainspec::EthereumHardforks; use std::{ cmp::max, sync::Arc, @@ -36,7 +37,7 @@ use super::Block; /// 2 - Call lots of commit_order. /// 3 - Call set_trace_fill_time when you are done calling commit_order (we still have to review this step). /// 4 - Call finalize_block. -pub trait BlockBuildingHelper: Send + Sync { +pub trait BlockBuildingHelper: Send { fn box_clone(&self) -> Box; /// Tries to add an order to the end of the block. @@ -213,7 +214,7 @@ impl BlockBuildingHelperFromProvider { #[allow(clippy::too_many_arguments)] pub fn new( built_block_id: BuiltBlockId, - state_provider: Arc, + state_provider: Arc, building_ctx: BlockBuildingContext, local_ctx: &mut ThreadBlockBuildingContext, builder_name: String, @@ -249,7 +250,7 @@ impl< #[allow(clippy::too_many_arguments)] pub fn new_with_execution_tracer( built_block_id: BuiltBlockId, - state_provider: Arc, + state_provider: Arc, building_ctx: BlockBuildingContext, local_ctx: &mut ThreadBlockBuildingContext, builder_name: String, @@ -269,9 +270,27 @@ impl< PartialBlock::new_with_execution_tracer(discard_txs, partial_block_execution_tracer) .with_tracer(GasUsedSimulationTracer::default()); let mut block_state = BlockState::new_arc(state_provider); + // enable BAL accumulation for Amsterdam-active blocks. Per-tx + // commits will populate the BAL builder state on `BlockState`, and + // `take_built_bal()` at finalize emits the RLP-encoded list. Pre-Amsterdam + // we leave it disabled so revm doesn't pay the BAL bookkeeping cost. + let is_amsterdam = building_ctx + .chain_spec + .is_amsterdam_active_at_timestamp(building_ctx.attributes.timestamp()); + if is_amsterdam { + block_state.enable_bal_builder(); + } partial_block .pre_block_call(&building_ctx, local_ctx, &mut block_state) .map_err(|_| BlockBuildingHelperError::PreBlockCallFailed)?; + // EIP-7928: pre-execution system calls (blockhashes + beacon root) + // share `tx_index = 0`; the next access — the first regular tx — + // belongs to `tx_index = 1`. Bump now so commits of real txs go in + // at the right index. Reth's validator does the same after its + // `apply_pre_execution_changes` (payload_validator.rs:1064). + if is_amsterdam { + block_state.bump_bal_index(); + } let payout_tx_space = estimate_payout_gas_limit( building_ctx.attributes.suggested_fee_recipient, &building_ctx, @@ -483,6 +502,7 @@ impl< txs_blobs_sidecars: finalized_block.txs_blob_sidecars, execution_requests: finalized_block.execution_requests, bid_adjustments: finalized_block.bid_adjustments, + block_access_list: finalized_block.block_access_list, }; Ok(FinalizeBlockResult { block }) } diff --git a/crates/rbuilder/src/building/builders/mock_block_building_helper.rs b/crates/rbuilder/src/building/builders/mock_block_building_helper.rs index 3cdee9459..0a414c34a 100644 --- a/crates/rbuilder/src/building/builders/mock_block_building_helper.rs +++ b/crates/rbuilder/src/building/builders/mock_block_building_helper.rs @@ -13,7 +13,9 @@ use crate::{ use alloy_primitives::{Address, Bytes, B256, I256, U256}; use eth_sparse_mpt::utils::{HashMap, HashSet}; use rbuilder_primitives::{order_statistics::OrderStatistics, SimValue, SimulatedOrder}; -use reth_primitives::SealedBlock; +use reth_primitives_traits::SealedBlock; + +type EthSealedBlock = SealedBlock; use revm::database::BundleState; use time::OffsetDateTime; use tokio::sync::broadcast; @@ -98,10 +100,11 @@ impl BlockBuildingHelper for MockBlockBuildingHelper { let block = Block { builder_name: "BlockBuildingHelper".to_string(), trace: self.built_block_trace.clone(), - sealed_block: SealedBlock::default(), + sealed_block: EthSealedBlock::default(), txs_blobs_sidecars: Vec::new(), execution_requests: Default::default(), bid_adjustments: Default::default(), + block_access_list: None, }; Ok(FinalizeBlockResult { block }) diff --git a/crates/rbuilder/src/building/builders/mod.rs b/crates/rbuilder/src/building/builders/mod.rs index fe65d7651..c15523d16 100644 --- a/crates/rbuilder/src/building/builders/mod.rs +++ b/crates/rbuilder/src/building/builders/mod.rs @@ -19,7 +19,9 @@ use ahash::HashSet; use alloy_eips::eip7594::BlobTransactionSidecarVariant; use alloy_primitives::{Address, Bytes}; use rbuilder_primitives::{mev_boost::BidAdjustmentData, AccountNonce, OrderId, SimulatedOrder}; -use reth::primitives::SealedBlock; +use reth_primitives_traits::SealedBlock; + +type EthSealedBlock = SealedBlock; use std::{ collections::HashMap, fmt::Debug, @@ -43,13 +45,18 @@ use super::{simulated_order_command_to_sink, OrderPriority, PrioritizedOrderStor pub struct Block { pub builder_name: String, pub trace: BuiltBlockTrace, - pub sealed_block: SealedBlock, + pub sealed_block: EthSealedBlock, /// Sidecars for the txs included in SealedBlock pub txs_blobs_sidecars: Vec>, /// The Pectra execution requests for this bid. pub execution_requests: Vec, /// Bid adjustment data by fee payer address. pub bid_adjustments: HashMap, + /// EIP-7928 rlp encoded BAL, populated post amsterdam from + /// the EVM executor (`BlockBuilderOutcome.block_access_list`). `None` + /// pre amsterdam. Required to populate `ExecutionPayloadGloas.block_access_list` + /// in the EPBS envelope. + pub block_access_list: Option, } /// Id to uniquely identify every block built (unique even among different algorithms). diff --git a/crates/rbuilder/src/building/builders/ordering_builder.rs b/crates/rbuilder/src/building/builders/ordering_builder.rs index ffa69eadd..da928ba4d 100644 --- a/crates/rbuilder/src/building/builders/ordering_builder.rs +++ b/crates/rbuilder/src/building/builders/ordering_builder.rs @@ -14,7 +14,8 @@ use crate::{ }, order_is_worth_executing, BlockBuildingContext, ExecutionError, NullPartialBlockExecutionTracer, OrderPriority, PartialBlockExecutionTracer, - PrioritizedOrderStore, SimulatedOrderSink, Sorting, ThreadBlockBuildingContext, + PrioritizedOrderStore, SimulatedOrderSink, Sorting, SyncStateProvider, + ThreadBlockBuildingContext, }, live_builder::{ block_output::bidding_service_interface::CompetitionBidContext, @@ -31,7 +32,6 @@ use ahash::{HashMap, HashSet}; use alloy_primitives::I256; use derivative::Derivative; use rbuilder_primitives::{AccountNonce, OrderId, SimValue, SimulatedOrder}; -use reth_provider::StateProvider; use serde::Deserialize; use std::{ marker::PhantomData, @@ -94,11 +94,11 @@ pub fn run_ordering_builder( { let payload_id = input.ctx.payload_id; - let block_state: Arc = match input + let block_state: Arc = match input .provider .history_by_block_hash(input.ctx.attributes.parent) { - Ok(state) => Arc::from(state), + Ok(state) => Arc::new(SyncStateProvider::new(state)), Err(err) => { error!( ?err, @@ -186,7 +186,7 @@ where block_orders_from_sim_orders::(input.sim_orders, &state_provider)?; let mut local_ctx = ThreadBlockBuildingContext::default(); let mut builder = OrderingBuilderContext::new( - Arc::from(state_provider), + Arc::new(SyncStateProvider::new(state_provider)), input.builder_name, input.ctx.clone(), ordering_config, @@ -214,7 +214,7 @@ where #[derivative(Debug)] pub struct OrderingBuilderContext { #[derivative(Debug = "ignore")] - state: Arc, + state: Arc, builder_name: String, ctx: BlockBuildingContext, config: OrderingBuilderConfig, @@ -232,7 +232,7 @@ pub struct OrderingBuilderContext { impl OrderingBuilderContext { pub fn new( - state: Arc, + state: Arc, builder_name: String, ctx: BlockBuildingContext, config: OrderingBuilderConfig, diff --git a/crates/rbuilder/src/building/builders/parallel_builder/block_building_result_assembler.rs b/crates/rbuilder/src/building/builders/parallel_builder/block_building_result_assembler.rs index 78c5e2f78..c550ed609 100644 --- a/crates/rbuilder/src/building/builders/parallel_builder/block_building_result_assembler.rs +++ b/crates/rbuilder/src/building/builders/parallel_builder/block_building_result_assembler.rs @@ -2,9 +2,9 @@ use super::{ results_aggregator::BestResults, ConflictGroup, GroupId, ParallelBuilderConfig, ResolutionResult, }; +use crate::building::SyncStateProvider; use ahash::HashMap; use alloy_primitives::utils::format_ether; -use reth_provider::StateProvider; use std::{ sync::Arc, time::{Duration, Instant}, @@ -31,7 +31,7 @@ use rbuilder_primitives::order_statistics::OrderStatistics; /// Assembles block building results from the best orderings of order groups. pub struct BlockBuildingResultAssembler { - state: Arc, + state: Arc, ctx: BlockBuildingContext, pub local_ctx: ThreadBlockBuildingContext, cancellation_token: CancellationToken, @@ -58,7 +58,7 @@ impl BlockBuildingResultAssembler { pub fn new( config: &ParallelBuilderConfig, best_results: Arc, - state: Arc, + state: Arc, ctx: BlockBuildingContext, cancellation_token: CancellationToken, builder_name: String, diff --git a/crates/rbuilder/src/building/builders/parallel_builder/conflict_resolvers.rs b/crates/rbuilder/src/building/builders/parallel_builder/conflict_resolvers.rs index 8e06e596b..5a09a22c3 100644 --- a/crates/rbuilder/src/building/builders/parallel_builder/conflict_resolvers.rs +++ b/crates/rbuilder/src/building/builders/parallel_builder/conflict_resolvers.rs @@ -1,10 +1,10 @@ +use crate::building::SyncStateProvider; use ahash::HashMap; use alloy_primitives::{Address, U256}; use derivative::Derivative; use eyre::Result; use itertools::Itertools; use rand::{seq::SliceRandom, SeedableRng}; -use reth::providers::StateProvider; use std::sync::Arc; use tokio_util::sync::CancellationToken; use tracing::trace; @@ -26,7 +26,7 @@ use rbuilder_primitives::{OrderId, SimulatedOrder}; #[derivative(Debug)] pub struct ResolverContext { #[derivative(Debug = "ignore")] - pub state: Arc, + pub state: Arc, pub ctx: BlockBuildingContext, pub cancellation_token: CancellationToken, pub simulation_cache: Arc, @@ -43,7 +43,7 @@ impl ResolverContext { /// * `cache` - Optional cached reads for optimization. /// * `simulation_cache` - Shared cache for simulation results. pub fn new( - state: Arc, + state: Arc, ctx: BlockBuildingContext, cancellation_token: CancellationToken, simulation_cache: Arc, @@ -126,7 +126,7 @@ impl ResolverContext { &mut self, sequence_of_orders: Vec, task: &ConflictTask, - state_provider: Arc, + state_provider: Arc, ) -> Result<(ResolutionResult, BlockState)> { // @todo actually reuse it for the duration of the block let mut local_ctx = ThreadBlockBuildingContext::default(); @@ -283,7 +283,7 @@ impl ResolverContext { } /// Initializes the block state, using a cached state if available. - fn initialize_block_state(&mut self, state_provider: Arc) -> BlockState { + fn initialize_block_state(&mut self, state_provider: Arc) -> BlockState { BlockState::new_arc(state_provider) } @@ -450,7 +450,8 @@ mod tests { use alloy_consensus::TxLegacy; use alloy_primitives::{Address, TxHash, B256, U256}; use reth::primitives::TransactionSigned; - use reth_primitives::{Recovered, Transaction}; + use reth_ethereum_primitives::Transaction; + use reth_primitives_traits::Recovered; use uuid::Uuid; use super::*; diff --git a/crates/rbuilder/src/building/builders/parallel_builder/conflict_resolving_pool.rs b/crates/rbuilder/src/building/builders/parallel_builder/conflict_resolving_pool.rs index 396ab75ea..8cbc627b4 100644 --- a/crates/rbuilder/src/building/builders/parallel_builder/conflict_resolving_pool.rs +++ b/crates/rbuilder/src/building/builders/parallel_builder/conflict_resolving_pool.rs @@ -1,7 +1,7 @@ +use crate::building::SyncStateProvider; use alloy_primitives::utils::format_ether; use crossbeam_queue::SegQueue; use eyre::Result; -use reth_provider::StateProvider; use std::{ sync::{mpsc as std_mpsc, Arc}, thread, @@ -65,10 +65,10 @@ where let simulation_cache = self.simulation_cache.clone(); let ctx = self.ctx.clone(); - let block_state: Arc = self - .provider - .history_by_block_hash(self.ctx.attributes.parent)? - .into(); + let block_state: Arc = Arc::new(SyncStateProvider::new( + self.provider + .history_by_block_hash(self.ctx.attributes.parent)?, + )); thread::spawn(move || { while !cancellation_token.is_cancelled() { if let Some(task) = task_queue.pop() { @@ -112,7 +112,7 @@ where fn process_task( task: ConflictTask, ctx: &BlockBuildingContext, - state: Arc, + state: Arc, cancellation_token: CancellationToken, simulation_cache: Arc, ) -> Result<(GroupId, (ResolutionResult, ConflictGroup))> { @@ -156,7 +156,7 @@ where &mut self, new_groups: Vec, ctx: &BlockBuildingContext, - state: Arc, + state: Arc, simulation_cache: Arc, ) -> Vec<(GroupId, (ResolutionResult, ConflictGroup))> { let mut results = Vec::new(); diff --git a/crates/rbuilder/src/building/builders/parallel_builder/conflict_task_generator.rs b/crates/rbuilder/src/building/builders/parallel_builder/conflict_task_generator.rs index dfc6f62ed..c8e5ba605 100644 --- a/crates/rbuilder/src/building/builders/parallel_builder/conflict_task_generator.rs +++ b/crates/rbuilder/src/building/builders/parallel_builder/conflict_task_generator.rs @@ -425,8 +425,8 @@ mod tests { evm_inspector::{SlotKey, UsedStateTrace}, MempoolTx, Order, SimValue, SimulatedOrder, TransactionSignedEcRecoveredWithBlobs, }; - use reth::primitives::{Transaction, TransactionSigned}; - use reth_primitives::Recovered; + use reth_ethereum_primitives::{Transaction, TransactionSigned}; + use reth_primitives_traits::Recovered; use std::sync::Arc; use std::sync::mpsc; diff --git a/crates/rbuilder/src/building/builders/parallel_builder/groups.rs b/crates/rbuilder/src/building/builders/parallel_builder/groups.rs index a0b6d8800..0164c82ef 100644 --- a/crates/rbuilder/src/building/builders/parallel_builder/groups.rs +++ b/crates/rbuilder/src/building/builders/parallel_builder/groups.rs @@ -379,8 +379,8 @@ mod tests { use alloy_consensus::TxLegacy; use alloy_primitives::{Address, TxHash, B256, U256}; - use reth::primitives::{Transaction, TransactionSigned}; - use reth_primitives::Recovered; + use reth_ethereum_primitives::{Transaction, TransactionSigned}; + use reth_primitives_traits::Recovered; use rbuilder_primitives::{ evm_inspector::{SlotKey, UsedStateTrace}, diff --git a/crates/rbuilder/src/building/builders/parallel_builder/mod.rs b/crates/rbuilder/src/building/builders/parallel_builder/mod.rs index ab11a91ac..0793a05f8 100644 --- a/crates/rbuilder/src/building/builders/parallel_builder/mod.rs +++ b/crates/rbuilder/src/building/builders/parallel_builder/mod.rs @@ -10,6 +10,7 @@ pub mod task; use alloy_primitives::I256; pub use groups::*; +use crate::building::SyncStateProvider; use ahash::HashMap; use conflict_resolving_pool::{ConflictResolvingPool, TaskQueue}; use conflict_task_generator::ConflictTaskGenerator; @@ -17,7 +18,6 @@ use crossbeam::queue::SegQueue; use eyre::Result; use itertools::Itertools; use results_aggregator::BestResults; -use reth_provider::StateProvider; use serde::Deserialize; use simulation_cache::SharedSimulationCache; use std::{ @@ -123,10 +123,11 @@ where let results_aggregator = ResultsAggregator::new(group_result_receiver, Arc::clone(&best_results)); - let block_state = input - .provider - .history_by_block_hash(input.ctx.attributes.parent)? - .into(); + let block_state = Arc::new(SyncStateProvider::new( + input + .provider + .history_by_block_hash(input.ctx.attributes.parent)?, + )); let block_building_result_assembler = BlockBuildingResultAssembler::new( config, @@ -329,10 +330,11 @@ where let setup_duration = setup_start.elapsed(); - let block_state: Arc = input - .provider - .history_by_block_hash(input.ctx.attributes.parent)? - .into(); + let block_state: Arc = Arc::new(SyncStateProvider::new( + input + .provider + .history_by_block_hash(input.ctx.attributes.parent)?, + )); // Group processing let processing_start = Instant::now(); diff --git a/crates/rbuilder/src/building/conflict.rs b/crates/rbuilder/src/building/conflict.rs index 19067aad2..98935f4f1 100644 --- a/crates/rbuilder/src/building/conflict.rs +++ b/crates/rbuilder/src/building/conflict.rs @@ -1,4 +1,7 @@ -use super::{BlockBuildingContext, BlockState, PartialBlockFork, ThreadBlockBuildingContext}; +use super::{ + BlockBuildingContext, BlockState, PartialBlockFork, SyncStateProvider, + ThreadBlockBuildingContext, +}; use crate::building::BlockBuildingSpaceState; use alloy_primitives::{Address, U256}; use itertools::Itertools; @@ -30,7 +33,7 @@ pub fn find_conflict_slow( ctx: &BlockBuildingContext, orders: &[Order], ) -> eyre::Result> { - let mut state_provider = Arc::::from(state_provider); + let mut state_provider = Arc::new(SyncStateProvider::new(state_provider)); let mut local_ctx = ThreadBlockBuildingContext::default(); // We use empty combined refunds because the value of the bundle will // not change from batching. diff --git a/crates/rbuilder/src/building/evm.rs b/crates/rbuilder/src/building/evm.rs index 464905c62..f05069a8c 100644 --- a/crates/rbuilder/src/building/evm.rs +++ b/crates/rbuilder/src/building/evm.rs @@ -84,12 +84,13 @@ impl EvmFactory for EthCachedEvmFactory { where DB: Database, { + let spec = *env.cfg_env.spec(); let evm = self .evm_factory .create_evm(db, env) .into_inner() .with_precompiles(WrappedPrecompile::new( - EthPrecompiles::default(), + EthPrecompiles::new(spec), self.cache.clone(), )); diff --git a/crates/rbuilder/src/building/mod.rs b/crates/rbuilder/src/building/mod.rs index acc3b44cb..efa8f8599 100644 --- a/crates/rbuilder/src/building/mod.rs +++ b/crates/rbuilder/src/building/mod.rs @@ -42,21 +42,19 @@ use rbuilder_primitives::{ mev_boost::BidAdjustmentData, BlockSpace, Order, SimValue, SimulatedOrder, TransactionSignedEcRecoveredWithBlobs, }; -use reth::{ - payload::PayloadId, - primitives::{Block, SealedBlock}, -}; +use reth::payload::PayloadId; use reth_chainspec::{ChainSpec, EthChainSpec, EthereumHardforks}; use reth_errors::{BlockExecutionError, BlockValidationError, ProviderError}; +use reth_ethereum_primitives::Block; +use reth_ethereum_primitives::BlockBody; use reth_evm::{ConfigureEvm, NextBlockEnvAttributes}; use reth_evm_ethereum::{revm_spec_by_timestamp_and_block_number, EthEvmConfig}; -use reth_node_api::{EngineApiMessageVersion, PayloadBuilderAttributes}; -use reth_payload_builder::EthPayloadBuilderAttributes; -use reth_primitives::BlockBody; +use reth_node_api::payload_id; +use reth_primitives_traits::SealedBlock; use reth_primitives_traits::{proofs, Block as _}; use revm::{ context_interface::result::InvalidTransaction, database::states::bundle_state::BundleRetention, - primitives::hardfork::SpecId, + database_interface::DatabaseCommitExt, primitives::hardfork::SpecId, }; use serde::Deserialize; use std::{ @@ -69,7 +67,7 @@ use std::{ }; use thiserror::Error; use time::OffsetDateTime; -use tracing::{error, trace}; +use tracing::{debug, error, trace}; use tx_sim_cache::TxExecutionCache; pub mod bid_adjustments; @@ -97,6 +95,66 @@ pub use self::{ #[cfg(test)] pub use conflict::*; +/// Local replacement for the removed `reth_ethereum_engine_primitives::EthPayloadBuilderAttributes`. +/// Contains all the fields needed for block building from payload attributes. +#[derive(Debug, Clone, PartialEq, Eq, Default)] +pub struct EthPayloadBuilderAttributes { + /// Id of the payload + pub id: PayloadId, + /// Parent block to build the payload on top + pub parent: B256, + /// Unix timestamp for the generated payload + pub timestamp: u64, + /// Address of the recipient for collecting transaction fee + pub suggested_fee_recipient: Address, + /// Randomness value for the generated payload + pub prev_randao: B256, + /// Withdrawals for the generated payload + pub withdrawals: Withdrawals, + /// Root of the parent beacon block + pub parent_beacon_block_root: Option, + /// Beacon slot for the payload. `Some` post glamsterdam (EIP-8037), + /// `None` for pre-fork blocks. + pub slot_number: Option, +} + +impl EthPayloadBuilderAttributes { + /// Creates a new payload builder attributes from the parent hash and payload attributes. + pub fn new(parent: B256, attributes: alloy_rpc_types_engine::PayloadAttributes) -> Self { + let id = payload_id(&parent, &attributes); + Self { + id, + parent, + timestamp: attributes.timestamp, + suggested_fee_recipient: attributes.suggested_fee_recipient, + prev_randao: attributes.prev_randao, + withdrawals: attributes.withdrawals.unwrap_or_default().into(), + parent_beacon_block_root: attributes.parent_beacon_block_root, + slot_number: attributes.slot_number, + } + } + + /// Returns the timestamp. + pub fn timestamp(&self) -> u64 { + self.timestamp + } + + /// Returns the suggested fee recipient. + pub fn suggested_fee_recipient(&self) -> Address { + self.suggested_fee_recipient + } + + /// Returns the prev randao. + pub fn prev_randao(&self) -> B256 { + self.prev_randao + } + + /// Returns the parent beacon block root. + pub fn parent_beacon_block_root(&self) -> Option { + self.parent_beacon_block_root + } +} + /// Estimated overhead for the whole block header rlp length const BLOCK_HEADER_RLP_OVERHEAD: usize = 1024; @@ -148,12 +206,15 @@ impl BlockBuildingContext { mev_blocker_price: U256, adjustment_fee_payers: ahash::HashSet
, ) -> Option { - let attributes = EthPayloadBuilderAttributes::try_new( + let proposal_slot = attributes.data.proposal_slot; + let mut attributes = EthPayloadBuilderAttributes::new( attributes.data.parent_block_hash, attributes.data.payload_attributes.clone(), - EngineApiMessageVersion::default() as u8, - ) - .expect("PayloadBuilderAttributes::try_new"); + ); + + if chain_spec.is_amsterdam_active_at_timestamp(attributes.timestamp) { + attributes.slot_number = Some(proposal_slot); + } let eth_evm_config = EthEvmConfig::new(chain_spec.clone()); let gas_limit = calculate_block_gas_limit( parent.gas_limit, @@ -171,6 +232,8 @@ impl BlockBuildingContext { gas_limit, withdrawals: Some(attributes.withdrawals.clone()), parent_beacon_block_root: attributes.parent_beacon_block_root, + extra_data: Default::default(), + slot_number: attributes.slot_number, }, ) .ok()?; @@ -273,6 +336,7 @@ impl BlockBuildingContext { prev_randao: onchain_block.header.mix_hash, withdrawals, parent_beacon_block_root: onchain_block.header.parent_beacon_block_root, + slot_number: onchain_block.header.slot_number, }; let spec_id = spec_id.unwrap_or_else(|| { // we use current block data instead of the parent block data to determine fork @@ -493,6 +557,14 @@ impl BlockBuildingSpaceState { self.space_used.gas } + pub fn regular_gas_used(&self) -> u64 { + self.space_used.regular_gas + } + + pub fn state_gas_used(&self) -> u64 { + self.space_used.state_gas + } + pub fn blob_gas_used(&self) -> u64 { self.space_used.blob_gas } @@ -607,7 +679,7 @@ impl ExecutionError { pub struct FinalizeResult { /// Sealed block. - pub sealed_block: SealedBlock, + pub sealed_block: SealedBlock, // sidecars for all txs in SealedBlock pub txs_blob_sidecars: Vec>, /// The Pectra execution requests for this bid. @@ -616,6 +688,9 @@ pub struct FinalizeResult { pub bid_adjustments: HashMap, /// Duration of root hash calculation. pub root_hash_time: Duration, + /// EIP-7928 rlp encoded BAL. `Some` post glamsterdam,`None` + /// pre-Amsterdam. + pub block_access_list: Option, } #[derive(Debug, thiserror::Error)] @@ -946,6 +1021,8 @@ impl(); } } + // filter zero value entries so we don't churn the BAL with no-ops. + balance_increments.retain(|_, balance| *balance > 0); db.db() .increment_balances(balance_increments) .map_err(|_| { @@ -1081,6 +1158,57 @@ impl`) accumulated by revm during execution. We hash + // and rlp encoded it via the same helper reths validator uses + // (`compute_block_access_list_hash`, see consensus/src/validation.rs:93) + // so the header hash and the wire bytes are derived identically on + // both sides. + let built_bal = state.take_built_bal(); + let is_amsterdam = ctx + .chain_spec + .is_amsterdam_active_at_timestamp(ctx.attributes.timestamp); + let block_access_list_hash = is_amsterdam.then(|| { + alloy_eips::eip7928::compute_block_access_list_hash(built_bal.as_deref().unwrap_or(&[])) + }); + // rlp encode the BAL into the payload bytes we ship in the envelope. + // Encode via `encode_list` so the onthewire bytes match exactly what + // reth-validator decodes back into `BlockAccessList` before hashing. + let block_access_list = built_bal.as_ref().map(|bal| { + let mut buf = Vec::new(); + alloy_rlp::encode_list(bal.as_slice(), &mut buf); + alloy_primitives::Bytes::from(buf) + }); + + // EIP-8037 (Amsterdam) splits block gas into regular and state gas, + // each bounded by `gas_limit` independently. The header `gas_used` + // is `max(regular, state)` — matches alloy-evm's + // EthBlockExecutor::finish, which is what the consensus validator + // re-derives in validate_block_post_execution. Pre-Amsterdam we keep + // the old behavior (cumulative tx_gas_used). + let tx_gas_used = self.space_state.gas_used(); + let regular_gas_used = self.space_state.regular_gas_used(); + let state_gas_used = self.space_state.state_gas_used(); + let header_gas_used = if is_amsterdam { + regular_gas_used.max(state_gas_used) + } else { + tx_gas_used + }; + + debug!( + block_number, + is_amsterdam, + tx_count = self.executed_tx_infos.len(), + tx_gas_used, + regular_gas_used, + state_gas_used, + header_gas_used, + "Sealing block header gas accounting" + ); + let header = Header { parent_hash: ctx.attributes.parent, ommers_hash: EMPTY_OMMER_ROOT_HASH, @@ -1097,12 +1225,14 @@ impl Self { + Self(provider) + } + + /// Access the inner provider (for methods not on StateProvider). + pub fn inner(&self) -> &(dyn StateProvider + Send) { + &*self.0 + } +} + +impl std::fmt::Debug for SyncStateProvider { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + f.debug_struct("SyncStateProvider").finish() + } +} + +impl std::ops::Deref for SyncStateProvider { + type Target = StateProviderBox; + fn deref(&self) -> &StateProviderBox { + &self.0 + } +} + +// Implement all StateProvider supertraits and StateProvider itself by forwarding to the inner Box. + +impl reth_provider::BlockHashReader for SyncStateProvider { + fn block_hash(&self, number: u64) -> reth_errors::ProviderResult> { + self.0.block_hash(number) + } + fn canonical_hashes_range( + &self, + start: u64, + end: u64, + ) -> reth_errors::ProviderResult> { + self.0.canonical_hashes_range(start, end) + } +} + +impl reth_provider::AccountReader for SyncStateProvider { + fn basic_account( + &self, + address: &Address, + ) -> reth_errors::ProviderResult> { + self.0.basic_account(address) + } +} + +impl reth_provider::BytecodeReader for SyncStateProvider { + fn bytecode_by_hash( + &self, + code_hash: &B256, + ) -> reth_errors::ProviderResult> { + self.0.bytecode_by_hash(code_hash) + } +} + +impl reth_provider::StateRootProvider for SyncStateProvider { + fn state_root(&self, state: reth_trie::HashedPostState) -> reth_errors::ProviderResult { + self.0.state_root(state) + } + fn state_root_from_nodes( + &self, + input: reth_trie::TrieInput, + ) -> reth_errors::ProviderResult { + self.0.state_root_from_nodes(input) + } + fn state_root_with_updates( + &self, + state: reth_trie::HashedPostState, + ) -> reth_errors::ProviderResult<(B256, reth_trie::updates::TrieUpdates)> { + self.0.state_root_with_updates(state) + } + fn state_root_from_nodes_with_updates( + &self, + input: reth_trie::TrieInput, + ) -> reth_errors::ProviderResult<(B256, reth_trie::updates::TrieUpdates)> { + self.0.state_root_from_nodes_with_updates(input) + } +} + +impl reth_provider::StorageRootProvider for SyncStateProvider { + fn storage_root( + &self, + address: Address, + hashed_storage: reth_trie::HashedStorage, + ) -> reth_errors::ProviderResult { + self.0.storage_root(address, hashed_storage) + } + fn storage_proof( + &self, + address: Address, + slot: B256, + hashed_storage: reth_trie::HashedStorage, + ) -> reth_errors::ProviderResult { + self.0.storage_proof(address, slot, hashed_storage) + } + fn storage_multiproof( + &self, + address: Address, + slots: &[B256], + hashed_storage: reth_trie::HashedStorage, + ) -> reth_errors::ProviderResult { + self.0.storage_multiproof(address, slots, hashed_storage) + } +} + +impl reth_provider::StateProofProvider for SyncStateProvider { + fn proof( + &self, + input: reth_trie::TrieInput, + address: Address, + slots: &[B256], + ) -> reth_errors::ProviderResult { + self.0.proof(input, address, slots) + } + fn multiproof( + &self, + input: reth_trie::TrieInput, + targets: reth_trie::MultiProofTargets, + ) -> reth_errors::ProviderResult { + self.0.multiproof(input, targets) + } + fn witness( + &self, + input: reth_trie::TrieInput, + target: reth_trie::HashedPostState, + mode: reth_trie::ExecutionWitnessMode, + ) -> reth_errors::ProviderResult> { + self.0.witness(input, target, mode) + } +} + +impl reth_provider::HashedPostStateProvider for SyncStateProvider { + fn hashed_post_state(&self, bundle_state: &BundleState) -> reth_trie::HashedPostState { + self.0.hashed_post_state(bundle_state) + } +} + +impl StateProvider for SyncStateProvider { + fn storage( + &self, + account: Address, + storage_key: alloy_primitives::StorageKey, + ) -> reth_errors::ProviderResult> { + self.0.storage(account, storage_key) + } +} + +/// Helper to convert `EvmDatabaseError` to `ProviderError`. +fn map_evm_db_error( + e: revm::database_interface::bal::EvmDatabaseError, +) -> ProviderError { + match e { + revm::database_interface::bal::EvmDatabaseError::Database(e) => e, + revm::database_interface::bal::EvmDatabaseError::Bal(e) => ProviderError::other(e), + } +} #[derive(Clone)] pub struct BlockState { - provider: Arc, + provider: Arc, bundle_state: Option, + bal_state: Option, } impl BlockState { pub fn new(provider: StateProviderBox) -> Self { - Self::new_arc(Arc::from(provider)) + Self::new_arc(Arc::new(SyncStateProvider::new(provider))) } - pub fn new_arc(provider: Arc) -> Self { + pub fn new_arc(provider: Arc) -> Self { Self { provider, bundle_state: Some(BundleState::default()), + bal_state: Some(BalState::default()), } } - pub fn into_provider(self) -> Arc { + pub fn into_provider(self) -> Arc { self.provider } @@ -61,7 +241,7 @@ impl BlockState { self } - pub fn into_parts(self) -> (BundleState, Arc) { + pub fn into_parts(self) -> (BundleState, Arc) { (self.bundle_state.unwrap(), self.provider) } @@ -73,7 +253,7 @@ impl BlockState { self.bundle_state.as_mut().unwrap() } - pub fn state_provider(&self) -> Arc { + pub fn state_provider(&self) -> Arc { self.provider.clone() } @@ -81,6 +261,62 @@ impl BlockState { self.bundle_state.clone().unwrap() } + /// enable per tx BAL accumulation. Call this once at block build start + /// when the chainspecs amsterdam fork is active for the building slots + /// timestamp. Without this, `take_built_bal()` always returns `None`. + pub fn enable_bal_builder(&mut self) { + if let Some(state) = self.bal_state.as_mut() { + *state = std::mem::take(state).with_bal_builder(); + } + } + + /// Advance the EIP-7928 BAL `tx_index` counter. EIP-7928 tags every BAL + /// entry with the transaction index at which the access occurred — pre- + /// execution system calls share index 0, then the index bumps to 1 for tx + /// 0, to 2 for tx 1, and so on. Reth's validator bumps the index after + /// `apply_pre_execution_changes` and after each `execute_transaction` + /// (see crates/engine/tree/src/tree/payload_validator.rs:1064,1113), so + /// we must do the same on the builder side or the BAL bytes our + /// `take_built_bal()` emits will hash differently from the validator's + /// re-derived BAL → `block_access_list_hash mismatch`. + pub fn bump_bal_index(&mut self) { + if let Some(state) = self.bal_state.as_mut() { + state.bump_bal_index(); + } + } + + /// Extract the accumulated EIP-7928 Block Access List. Returns `None` + /// if `enable_bal_builder()` was never called for this block. + /// + /// Returns the canonical `alloy_eip7928::Bal` (wrapper around + /// `Vec`) so the caller can both: + /// * compute `header.block_access_list_hash` via + /// `alloy_eips::eip7928::compute_block_access_list_hash` — the + /// same free function reth's `validate_block_post_execution` + /// uses (consensus/src/validation.rs:93), and + /// * RLP-encode the bytes for the envelope payload field. + pub fn take_built_bal(&mut self) -> Option { + let bal = self.bal_state.as_mut()?.take_built_alloy_bal()?; + // Gated so we don't pay the encode_list + keccak256 cost every + // finalize iteration (~50/slot) when debug logging is off. Keep + // hash + hex preview so that a future `block_access_list_hash + // mismatch` can be diffed byte-for-byte against reth's BAL. + if tracing::enabled!(tracing::Level::DEBUG) { + let mut bytes_buf = Vec::new(); + alloy_rlp::encode_list(bal.as_slice(), &mut bytes_buf); + let hash = alloy_eips::eip7928::compute_block_access_list_hash(bal.as_slice()); + let preview_len = bytes_buf.len().min(128); + debug!( + bal_len = bytes_buf.len(), + bal_account_count = bal.len(), + bal_hash = %hash, + bal_hex_head = %alloy_primitives::hex::encode(&bytes_buf[..preview_len]), + "Built block access list" + ); + } + Some(bal) + } + pub fn new_db_ref<'a, 'b, 'c>( &'a mut self, shared_cache_reads: &'b SharedCachedReads, @@ -89,12 +325,16 @@ impl BlockState { let state_provider = StateProviderDatabase::new(&self.provider); let cachedb = CachedDB::new(state_provider, local_cache_reads, shared_cache_reads); let bundle_state = self.bundle_state.take().unwrap(); - let db = State::builder() + // Carry the persistent BAL builder state (if any) into the freshly built + // revm State so EIP-7928 BAL accumulation continues across per-tx calls. + let bal_state = self.bal_state.take().unwrap_or_default(); + let mut db = State::builder() .with_database(cachedb) .with_bundle_prestate(bundle_state) .with_bundle_update() .build(); - BlockStateDBRef::new(db, &mut self.bundle_state) + db.bal_state = bal_state; + BlockStateDBRef::new(db, &mut self.bundle_state, &mut self.bal_state) } pub fn balance( @@ -106,7 +346,8 @@ impl BlockState { let mut db = self.new_db_ref(shared_cache_reads, local_cache_reads); Ok(db .as_mut() - .basic(address)? + .basic(address) + .map_err(map_evm_db_error)? .map(|acc| acc.balance) .unwrap_or_default()) } @@ -120,7 +361,8 @@ impl BlockState { let mut db = self.new_db_ref(shared_cache_reads, local_cache_reads); Ok(db .as_mut() - .basic(address)? + .basic(address) + .map_err(map_evm_db_error)? .map(|acc| acc.nonce) .unwrap_or_default()) } @@ -134,7 +376,8 @@ impl BlockState { let mut db = self.new_db_ref(shared_cache_reads, local_cache_reads); Ok(db .as_mut() - .basic(address)? + .basic(address) + .map_err(map_evm_db_error)? .map(|acc| acc.code_hash) .unwrap_or_else(|| KECCAK_EMPTY)) } @@ -156,23 +399,31 @@ impl BlockState { } } -/// A wrapper around a [`State`] that will return the [`BundleState`] back to [`BlockState`] when dropped. +/// A wrapper around a [`State`] that returns the [`BundleState`] and the +/// [`BalState`] back to [`BlockState`] when dropped, so both accumulate across +/// per-tx calls to `new_db_ref`. pub struct BlockStateDBRef<'a, DB> where DB: Database, { db: State, parent_bundle_state_ref: &'a mut Option, + parent_bal_state_ref: &'a mut Option, } impl<'a, DB> BlockStateDBRef<'a, DB> where DB: Database, { - pub fn new(db: State, parent_bundle_state_ref: &'a mut Option) -> Self { + pub fn new( + db: State, + parent_bundle_state_ref: &'a mut Option, + parent_bal_state_ref: &'a mut Option, + ) -> Self { Self { db, parent_bundle_state_ref, + parent_bal_state_ref, } } @@ -186,7 +437,11 @@ where DB: Database, { fn drop(&mut self) { - *self.parent_bundle_state_ref = Some(self.db.take_bundle()) + *self.parent_bundle_state_ref = Some(self.db.take_bundle()); + // Move the BAL state back to the parent so the next `new_db_ref` call + // continues accumulating into the same BAL. `mem::take` is fine + // because revm's `BalState::default()` is a valid empty state. + *self.parent_bal_state_ref = Some(std::mem::take(&mut self.db.bal_state)); } } @@ -433,6 +688,17 @@ pub struct PartialBlockFork< pub struct PartialBlockRollobackPoint { rollobacks: usize, + /// Snapshot of the EIP-7928 BAL accumulator at rollback creation. + /// `Some` only when BAL building is enabled (Amsterdam+). The BalState + /// itself has no revert API: `bal_state.commit()` mutates the builder + /// (appends per-account entries) and `bump_bal_index` advances a counter. + /// If a bundle/order partially commits and then fails, those mutations + /// leak into the final BAL — every leaked entry tags with a `tx_index` + /// that doesn't match the validator's re-execution (which never sees + /// the rolled-back txs), producing `block_access_list_hash mismatch`. + /// Restoring this snapshot on `rollback()` keeps our BAL in lockstep + /// with what the block's transaction list will commit. + bal_snapshot: Option, } #[derive(Debug, Clone)] @@ -456,7 +722,9 @@ pub enum CriticalCommitOrderError { #[error("Reth error: {0}")] Reth(#[from] ProviderError), #[error("EVM error: {0}")] - EVM(#[from] EVMError), + EVM(#[from] EVMError>), + #[error("EVM database error: {0}")] + EvmDB(#[from] revm::database_interface::bal::EvmDatabaseError), /// This could happen if we can't fit a balance in a I256 (unlikely/impossible since the ETH total supply is several orders of magnitude bellow I256::max) #[error("BigIntConversionError error: {0}")] BigIntConversionError(#[from] alloy_primitives::BigIntConversionError), @@ -491,8 +759,19 @@ impl< } pub fn rollback_point(&self) -> PartialBlockRollobackPoint { + // Only snapshot when the BAL builder is active — pre-Amsterdam this + // is `None` and the clone is essentially free. Post-Amsterdam the + // BalState carries the accumulated `Vec` plus the + // running `bal_index`, both of which must be restored on rollback. + let bal_snapshot = self + .state + .bal_state + .as_ref() + .filter(|s| s.bal_builder.is_some()) + .cloned(); PartialBlockRollobackPoint { rollobacks: self.rollbacks, + bal_snapshot, } } @@ -503,6 +782,14 @@ impl< .expect("incorrect rollback"); let bundle_state = self.state.bundle_state.as_mut().expect("no bundle state"); bundle_state.revert(rollbacks); + // Restore the BAL accumulator alongside the bundle state. The BAL + // has no revert API of its own, so we replay the snapshot we took + // before this order ran. Without this every rolled-back bundle + // leaves stale entries + advanced bal_index in the accumulator + // and the validator's re-derived BAL hashes differently. + if let Some(snapshot) = rollback_point.bal_snapshot { + self.state.bal_state = Some(snapshot); + } self.rollbacks = rollback_point.rollobacks; } @@ -670,8 +957,12 @@ impl< Err(err) => return Ok(Err(err)), }; + let tx_gas_used = res.result.tx_gas_used(); + let regular_gas_used = res.result.gas().block_regular_gas_used(); + let state_gas_used = res.result.gas().block_state_gas_used(); + if let Some(tracer) = &mut self.tracer { - tracer.add_gas_used(res.result.gas_used()); + tracer.add_gas_used(tx_gas_used); if let (true, Some(t)) = (is_recording_used_state, used_state_trace) { tracer.add_used_state_trace(t) } @@ -682,10 +973,22 @@ impl< // This allows calling saturating_coinbase_delta. @Pending: this should be a scope/child function. drop(db); self.rollbacks += 1; - - // add gas used by the transaction to cumulative gas used, before creating the receipt - let space_used = BlockSpace::new( - res.result.gas_used(), + // EIP-7928: advance the BAL `tx_index` after each successfully + // committed transaction. Matches reth-validator's per-tx bump + // (crates/engine/tree/src/tree/payload_validator.rs:1113). Without + // this every tx's accesses are tagged with the same index, the + // re-derived BAL on the validator side does not, and the resulting + // RLP bytes hash differently → `block_access_list_hash mismatch` + // on reveal. + self.state.bump_bal_index(); + + // Track regular and state gas separately for EIP-8037 header semantics + // while keeping `gas = tx_gas_used` so receipt cumulative_gas_used stays + // correct. + let space_used = BlockSpace::new_split( + tx_gas_used, + regular_gas_used, + state_gas_used, tx_with_blobs.internal_tx_unsecure().length(), blob_gas_used, ); @@ -1155,7 +1458,7 @@ fn execute_evm( evm_env: EvmEnv, tx_with_blobs: &TransactionSignedEcRecoveredWithBlobs, used_state_tracer: Option<&mut UsedStateTrace>, - db: impl Database, + db: impl Database>, blocklist: &HashSet
, ) -> Result, CriticalCommitOrderError> where @@ -1171,9 +1474,10 @@ where EVMError::Transaction(tx_err) => { return Ok(Err(TransactionErr::InvalidTransaction(tx_err))) } - EVMError::Database(_) | EVMError::Header(_) | EVMError::Custom(_) => { - return Err(err.into()) - } + EVMError::Database(_) + | EVMError::Header(_) + | EVMError::Custom(_) + | EVMError::CustomAny(_) => return Err(err.into()), }, }; drop(evm); diff --git a/crates/rbuilder/src/building/payout_tx.rs b/crates/rbuilder/src/building/payout_tx.rs index 1550177cf..e71a67a0a 100644 --- a/crates/rbuilder/src/building/payout_tx.rs +++ b/crates/rbuilder/src/building/payout_tx.rs @@ -8,8 +8,9 @@ use alloy_primitives::{Address, TxKind as TransactionKind, U256}; use alloy_rlp::Encodable as _; use reth_chainspec::ChainSpec; use reth_errors::ProviderError; +use reth_ethereum_primitives::{Transaction, TransactionSigned}; use reth_evm::Evm; -use reth_primitives::{Recovered, Transaction, TransactionSigned}; +use reth_primitives_traits::Recovered; use revm::context::result::{EVMError, ExecutionResult}; pub fn create_payout_tx( @@ -42,7 +43,7 @@ pub enum PayoutTxErr { #[error("Signature error: {0}")] SignError(#[from] secp256k1::Error), #[error("EVM error: {0}")] - EvmError(#[from] EVMError), + EvmError(#[from] EVMError>), } impl PartialEq for PayoutTxErr { @@ -86,17 +87,16 @@ pub fn insert_test_payout_tx( let mut db = state.new_db_ref(&ctx.shared_cached_reads, &mut local_ctx.cached_reads); let mut evm = ctx.evm_factory.create_evm(db.as_mut(), ctx.evm_env.clone()); - let cache_account = evm.db_mut().load_cache_account(builder_signer.address)?; + let cache_account = evm + .db_mut() + .load_cache_account(builder_signer.address) + .map_err(PayoutTxErr::Reth)?; let gas_fee = ctx.evm_env.block_env.basefee as u128 * gas_limit as u128; cache_account.increment_balance((tx_value + gas_fee) * 2); // double for luck let res = evm.transact(&tx)?; match res.result { - ExecutionResult::Success { - gas_used, - gas_refunded, - .. - } => Ok(Some(gas_used + gas_refunded)), + ExecutionResult::Success { gas, .. } => Ok(Some(gas.total_gas_spent())), _ => Ok(None), } } @@ -169,9 +169,7 @@ pub fn estimate_payout_gas_limit( .cfg_env .tx_gas_limit_cap .unwrap_or(ctx.evm_env.block_env.gas_limit); - let gas_left = max_tx_gas_limit - .checked_sub(space_used.gas) - .unwrap_or_default(); + let gas_left = max_tx_gas_limit.saturating_sub(space_used.gas); let estimation = insert_test_payout_tx(to, ctx, local_ctx, state, gas_left)? .ok_or(EstimatePayoutGasErr::FailedToEstimate)?; @@ -214,7 +212,7 @@ mod tests { use assert_matches::assert_matches; use reth_chainspec::{EthereumHardfork, MAINNET}; use reth_db::{tables, transaction::DbTxMut}; - use reth_primitives::Account; + use reth_primitives_traits::Account; use reth_provider::test_utils::create_test_provider_factory_with_chain_spec; use revm::primitives::hardfork::SpecId; use std::sync::Arc; diff --git a/crates/rbuilder/src/building/precompile_cache.rs b/crates/rbuilder/src/building/precompile_cache.rs index 672f7f25c..b54f14f6a 100644 --- a/crates/rbuilder/src/building/precompile_cache.rs +++ b/crates/rbuilder/src/building/precompile_cache.rs @@ -8,7 +8,7 @@ use revm::{ context::{Cfg, ContextTr}, handler::PrecompileProvider, interpreter::{CallInputs, InterpreterResult}, - primitives::hardfork::SpecId, + primitives::{hardfork::SpecId, AddressSet}, }; use std::{num::NonZeroUsize, sync::Arc}; @@ -85,7 +85,7 @@ impl> Pre output } - fn warm_addresses(&self) -> Box> { + fn warm_addresses(&self) -> &AddressSet { self.precompile.warm_addresses() } diff --git a/crates/rbuilder/src/building/sim.rs b/crates/rbuilder/src/building/sim.rs index b0eccaf7f..ae0aff2bd 100644 --- a/crates/rbuilder/src/building/sim.rs +++ b/crates/rbuilder/src/building/sim.rs @@ -6,7 +6,7 @@ use super::{ use crate::{ building::{ order_is_worth_executing, BlockBuildingContext, BlockBuildingSpaceState, BlockState, - CriticalCommitOrderError, NullPartialBlockForkExecutionTracer, + CriticalCommitOrderError, NullPartialBlockForkExecutionTracer, SyncStateProvider, }, live_builder::order_input::mempool_txs_detector::MempoolTxsDetector, provider::StateProviderFactory, @@ -18,7 +18,6 @@ use alloy_primitives::Address; use rand::seq::SliceRandom; use rbuilder_primitives::{Order, OrderId, SimulatedOrder}; use reth_errors::ProviderError; -use reth_provider::StateProvider; use std::{ cmp::{max, min, Ordering}, collections::hash_map::Entry, @@ -324,7 +323,7 @@ where { let nonces = { let state = provider.history_by_block_hash(ctx.attributes.parent)?; - NonceCache::new(state.into()) + NonceCache::new(Arc::new(SyncStateProvider::new(state))) }; let mut sim_tree = SimTree::new(nonces); @@ -339,8 +338,9 @@ where } let mut sim_errors = Vec::new(); - let mut state_for_sim = - Arc::::from(provider.history_by_block_hash(ctx.attributes.parent)?); + let mut state_for_sim = Arc::new(SyncStateProvider::new( + provider.history_by_block_hash(ctx.attributes.parent)?, + )); let mut local_ctx = ThreadBlockBuildingContext::default(); loop { // mix new orders into the sim_tree diff --git a/crates/rbuilder/src/building/testing/bundle_tests/mod.rs b/crates/rbuilder/src/building/testing/bundle_tests/mod.rs index 33816e546..fab0898ce 100644 --- a/crates/rbuilder/src/building/testing/bundle_tests/mod.rs +++ b/crates/rbuilder/src/building/testing/bundle_tests/mod.rs @@ -1,7 +1,7 @@ pub mod setup; use alloy_primitives::{Address, Bytes, U256}; -use reth_primitives::Bytecode; +use reth_primitives_traits::Bytecode; use std::collections::{HashMap, HashSet}; use crate::{ diff --git a/crates/rbuilder/src/building/testing/bundle_tests/setup.rs b/crates/rbuilder/src/building/testing/bundle_tests/setup.rs index 69046ac08..ab650c5c8 100644 --- a/crates/rbuilder/src/building/testing/bundle_tests/setup.rs +++ b/crates/rbuilder/src/building/testing/bundle_tests/setup.rs @@ -6,7 +6,7 @@ use crate::building::{ cached_reads::{LocalCachedReads, SharedCachedReads}, testing::test_chain_state::{BlockArgs, NamedAddr, TestChainState, TxArgs}, BlockState, ExecutionError, ExecutionResult, NullPartialBlockExecutionTracer, OrderErr, - PartialBlock, ThreadBlockBuildingContext, + PartialBlock, SyncStateProvider, ThreadBlockBuildingContext, }; use alloy_primitives::{Address, TxHash}; use parking_lot::Mutex; @@ -195,8 +195,9 @@ impl TestSetup { ) } fn try_commit_order(&mut self) -> eyre::Result> { - let state_provider: Arc = - Arc::from(self.test_chain.provider_factory().latest()?); + let state_provider: Arc = Arc::new(SyncStateProvider::new( + self.test_chain.provider_factory().latest()?, + )); let mut local_ctx = ThreadBlockBuildingContext::default(); let sim_order = SimulatedOrder { diff --git a/crates/rbuilder/src/building/testing/evm_inspector_tests/mod.rs b/crates/rbuilder/src/building/testing/evm_inspector_tests/mod.rs index fe3f384c8..c2ce90144 100644 --- a/crates/rbuilder/src/building/testing/evm_inspector_tests/mod.rs +++ b/crates/rbuilder/src/building/testing/evm_inspector_tests/mod.rs @@ -1,5 +1,5 @@ use alloy_primitives::{B256, U256}; -use reth_primitives::TransactionSigned; +use reth_ethereum_primitives::TransactionSigned; use crate::building::testing::{ evm_inspector_tests::setup::TestSetup, test_chain_state::NamedAddr, @@ -104,7 +104,7 @@ fn test_read_balance() -> eyre::Result<()> { let mev_test_contract_addr = test_setup.named_address(NamedAddr::MevTest)?; let dummy_addr = test_setup.named_address(NamedAddr::Dummy)?; - let tx: reth_primitives::Recovered = + let tx: reth_primitives_traits::Recovered = test_setup.make_test_read_balance_tx(dummy_addr, 100)?; let used_state_trace = test_setup.inspect_tx_without_commit(tx)?; @@ -126,7 +126,7 @@ fn test_ephemeral_contract_destruct() -> eyre::Result<()> { let test_setup = TestSetup::new()?; let refund_addr = test_setup.named_address(NamedAddr::Dummy)?; - let tx: reth_primitives::Recovered = + let tx: reth_primitives_traits::Recovered = test_setup.make_test_ephemeral_contract_destruct_tx(refund_addr, 100)?; let used_state_trace = test_setup.inspect_tx_without_commit(tx)?; diff --git a/crates/rbuilder/src/building/testing/evm_inspector_tests/setup.rs b/crates/rbuilder/src/building/testing/evm_inspector_tests/setup.rs index 07f536879..ba59b7cdc 100644 --- a/crates/rbuilder/src/building/testing/evm_inspector_tests/setup.rs +++ b/crates/rbuilder/src/building/testing/evm_inspector_tests/setup.rs @@ -6,8 +6,9 @@ use crate::building::{ }; use alloy_primitives::Address; use rbuilder_primitives::evm_inspector::{RBuilderEVMInspector, UsedStateTrace}; +use reth_ethereum_primitives::TransactionSigned; use reth_evm::Evm; -use reth_primitives::{Recovered, TransactionSigned}; +use reth_primitives_traits::Recovered; #[derive(Debug)] pub struct TestSetup { diff --git a/crates/rbuilder/src/building/testing/test_chain_state.rs b/crates/rbuilder/src/building/testing/test_chain_state.rs index 582348579..c51b6083c 100644 --- a/crates/rbuilder/src/building/testing/test_chain_state.rs +++ b/crates/rbuilder/src/building/testing/test_chain_state.rs @@ -14,15 +14,17 @@ use alloy_rpc_types_beacon::events::{PayloadAttributesData, PayloadAttributesEve use eth_sparse_mpt::ETHSpareMPTVersion::V2; use lazy_static::lazy_static; use reth::{ - primitives::{Account, BlockBody, Bytecode}, + primitives::{Account, Bytecode}, providers::ProviderFactory, rpc::types::{engine::PayloadAttributes, Withdrawal}, }; use reth_chainspec::{ChainSpec, EthereumHardfork, MAINNET}; use reth_db::{cursor::DbCursorRW, tables, transaction::DbTxMut}; use reth_errors::ProviderResult; -use reth_primitives::{Recovered, TransactionSigned}; +use reth_ethereum_primitives::BlockBody; +use reth_ethereum_primitives::TransactionSigned; use reth_primitives_traits::Block as _; +use reth_primitives_traits::Recovered; use reth_provider::{ test_utils::{create_test_provider_factory, MockNodeTypesWithDB}, BlockWriter, @@ -137,7 +139,7 @@ impl TestChainState { { let provider = provider_factory.provider_rw()?; provider.insert_block( - Block::new(genesis_header.header().clone(), BlockBody::default()) + &Block::new(genesis_header.header().clone(), BlockBody::default()) .try_into_recovered() .unwrap(), )?; @@ -346,7 +348,7 @@ impl TestBlockContextBuilder { ) -> Self { TestBlockContextBuilder { parent_gas_limit: 30_000_000, - parent_timestamp: block_args.timestamp.checked_sub(12).unwrap_or_default(), + parent_timestamp: block_args.timestamp.saturating_sub(12), block_number: block_args.number, parent_base_fee_per_gas: 1, builder_signer, @@ -380,6 +382,7 @@ impl TestBlockContextBuilder { suggested_fee_recipient: self.suggested_fee_recipient, withdrawals: self.withdrawals, parent_beacon_block_root: None, + slot_number: None, }, }, }, @@ -393,7 +396,7 @@ impl TestBlockContextBuilder { withdrawals_root: None, logs_bloom: Default::default(), difficulty: Default::default(), - number: self.block_number.checked_sub(1).unwrap_or_default(), + number: self.block_number.saturating_sub(1), gas_limit: self.parent_gas_limit, gas_used: self.parent_gas_used, timestamp: self.parent_timestamp, @@ -405,6 +408,8 @@ impl TestBlockContextBuilder { parent_beacon_block_root: None, extra_data: Default::default(), requests_hash: Default::default(), + block_access_list_hash: None, + slot_number: None, }, self.builder_signer, self.chain_spec, diff --git a/crates/rbuilder/src/building/tx_sim_cache/mod.rs b/crates/rbuilder/src/building/tx_sim_cache/mod.rs index c3840b168..cc451b3f3 100644 --- a/crates/rbuilder/src/building/tx_sim_cache/mod.rs +++ b/crates/rbuilder/src/building/tx_sim_cache/mod.rs @@ -222,7 +222,7 @@ impl TxExecutionCache { pub fn get_cached_result( &self, - mut db: impl Database, + mut db: impl Database>, tx_hash: &B256, coinbase: &Address, ) -> Result { diff --git a/crates/rbuilder/src/building/tx_sim_cache/result_store.rs b/crates/rbuilder/src/building/tx_sim_cache/result_store.rs index a8f244e61..ec689b310 100644 --- a/crates/rbuilder/src/building/tx_sim_cache/result_store.rs +++ b/crates/rbuilder/src/building/tx_sim_cache/result_store.rs @@ -144,6 +144,7 @@ mod tests { nonce: 0, code_hash: Default::default(), code: None, + account_id: None, }), } } diff --git a/crates/rbuilder/src/live_builder/base_config.rs b/crates/rbuilder/src/live_builder/base_config.rs index 34e57ea87..aafbffdfc 100644 --- a/crates/rbuilder/src/live_builder/base_config.rs +++ b/crates/rbuilder/src/live_builder/base_config.rs @@ -30,8 +30,8 @@ use reth_chainspec::ChainSpec; use reth_db::DatabaseEnv; use reth_node_api::NodeTypesWithDBAdapter; use reth_node_ethereum::EthereumNode; -use reth_primitives::StaticFileSegment; use reth_provider::StaticFileProviderFactory; +use reth_provider::StaticFileSegment; use serde::{Deserialize, Deserializer}; use serde_with::serde_as; use std::{ @@ -264,6 +264,8 @@ impl BaseConfig { simulation_use_random_coinbase: self.simulation_use_random_coinbase, faster_finalize: self.faster_finalize, order_flow_tracer_manager, + epbs_server: None, + epbs_p2p_service: None, }) } @@ -313,9 +315,29 @@ impl BaseConfig { "root_hash_compare_sparse_trie can't be set without root_hash_use_sparse_trie" ); } - // temporary guard until reth is fixed - if !self.root_hash_use_sparse_trie || self.root_hash_compare_sparse_trie { - eyre::bail!("root_hash_use_sparse_trie=true and root_hash_compare_sparse_trie=false must be set, otherwise node will produce incorrect blocks or confusing error messages. These settings are enforced temporarily because upstream parallel root hash implementation is not correct.") + // TODO(EPBS-DEVNET): The original guard required `root_hash_use_sparse_trie=true`. + // It was relaxed because the sparse trie implementation panics with + // `alloy-trie 0.9.5` (`add_branch key ... self.key ...` ordering assertion) + // when running against the reth 2.0 fork used for the EPBS devnet. + // + // This relaxation is ONLY safe for devnet testing of EPBS bid signing/p2p flow. + // Bids built without sparse-trie-validated state roots may produce blocks + // that the beacon chain ultimately rejects. Restore the strict guard + // (or fix the sparse trie panic in eth-sparse-mpt) before any production use. + // + // It's also possible state-root recomputation isn't strictly needed for the + // bid path at all — the EL already produces a state_root via engine_getPayload. + // Investigate whether rbuilder can skip its own recomputation when the EL value + // is trusted (similar to buildoor's approach). + if self.root_hash_compare_sparse_trie { + eyre::bail!("root_hash_compare_sparse_trie=false must be set, otherwise node will produce incorrect blocks or confusing error messages.") + } + if !self.root_hash_use_sparse_trie { + tracing::warn!( + "root_hash_use_sparse_trie=false — using non-sparse trie path. \ + This bypasses a temporary guard relaxed for EPBS devnet testing. \ + NOT for production use. See TODO(EPBS-DEVNET) in base_config.rs." + ); } let thread_pool = self.root_hash_thread_pool()?; let version = match self.root_hash_sparse_trie_version.as_str() { @@ -574,8 +596,18 @@ pub fn create_provider_factory( } }; - let provider_factory_reopener = - ProviderFactoryReopener::new(db, chain_spec, reth_static_files_path, root_hash_config)?; + let rocksdb_provider = reth_provider::providers::RocksDBProvider::builder(&reth_db_path) + .with_default_tables() + .build()?; + let runtime = reth_tasks::Runtime::test(); + let provider_factory_reopener = ProviderFactoryReopener::new( + db, + chain_spec, + reth_static_files_path, + root_hash_config, + rocksdb_provider, + runtime, + )?; if provider_factory_reopener .provider_factory_unchecked() @@ -648,13 +680,23 @@ mod test { let data_dir = MaybePlatformPath::::from(tempdir.keep()); let data_dir = data_dir.unwrap_or_chain_default(Chain::mainnet(), DatadirArgs::default()); - let db = Arc::new(init_db(data_dir.data_dir(), Default::default()).unwrap()); + let db = Arc::new(init_db(data_dir.db(), Default::default()).unwrap()); + let rocksdb_provider = + reth_provider::providers::RocksDBProvider::builder(data_dir.db().as_path()) + .with_default_tables() + .build() + .unwrap(); + let runtime = reth_tasks::Runtime::test(); let provider_factory = ProviderFactory::>::new( db, SEPOLIA.clone(), StaticFileProvider::read_write(data_dir.static_files().as_path()).unwrap(), - ); + rocksdb_provider, + runtime, + ) + .unwrap(); init_genesis(&provider_factory).unwrap(); + drop(provider_factory); // Create longer-lived PathBuf values let data_dir_path = data_dir.data_dir(); diff --git a/crates/rbuilder/src/live_builder/block_output/bid_observer.rs b/crates/rbuilder/src/live_builder/block_output/bid_observer.rs index a982cc58d..cca1bcbfe 100644 --- a/crates/rbuilder/src/live_builder/block_output/bid_observer.rs +++ b/crates/rbuilder/src/live_builder/block_output/bid_observer.rs @@ -1,5 +1,4 @@ use alloy_primitives::U256; -use reth_primitives::SealedBlock; use crate::{building::BuiltBlockTrace, live_builder::payload_events::MevBoostSlotData}; diff --git a/crates/rbuilder/src/live_builder/block_output/bid_observer_multiplexer.rs b/crates/rbuilder/src/live_builder/block_output/bid_observer_multiplexer.rs index a608ee8ea..de40952ce 100644 --- a/crates/rbuilder/src/live_builder/block_output/bid_observer_multiplexer.rs +++ b/crates/rbuilder/src/live_builder/block_output/bid_observer_multiplexer.rs @@ -1,5 +1,3 @@ -use reth_primitives::SealedBlock; - use crate::{building::BuiltBlockTrace, live_builder::payload_events::MevBoostSlotData}; use super::bid_observer::BidObserver; diff --git a/crates/rbuilder/src/live_builder/block_output/block_observer.rs b/crates/rbuilder/src/live_builder/block_output/block_observer.rs new file mode 100644 index 000000000..56de527a6 --- /dev/null +++ b/crates/rbuilder/src/live_builder/block_output/block_observer.rs @@ -0,0 +1,75 @@ +//! Block observer interface for notifying external systems of built blocks. +//! +//! This module provides the `BlockObserver` trait that allows components to be +//! notified when new blocks are built. The primary use case is notifying the +//! EPBS Builder API server of new blocks so it can generate bids. + +use crate::building::builders::Block; +use alloy_primitives::{BlockHash, B256}; +use std::sync::Arc; + +/// Observer that receives notifications when blocks are built. +/// +/// Implementations can use these notifications to: +/// - Generate EPBS bids +pub trait BlockObserver: Send + Sync + std::fmt::Debug { + /// Called when a new block has been finalized and is ready for submission. + /// + /// # Arguments + /// * `slot` - The slot number this block is for + /// * `parent_hash` - The execution layer parent block hash + /// * `parent_block_root` - The beacon chain parent block root (from + /// `payload_attributes_event.data.parent_block_root`). Used as + /// `bid.parent_block_root` per the gloas spec. + /// * `block` - The finalized block + fn on_block_built( + &self, + slot: u64, + parent_hash: BlockHash, + parent_block_root: B256, + block: &Block, + ); +} + +/// A no-op observer that does nothing. +/// Used as a default when no observer is configured. +#[derive(Debug, Clone, Default)] +pub struct NoOpBlockObserver; + +impl BlockObserver for NoOpBlockObserver { + fn on_block_built( + &self, + _slot: u64, + _parent_hash: BlockHash, + _parent_block_root: B256, + _block: &Block, + ) { + // No-op + } +} + +/// A multi observer that forwards notifications to multiple observers. +#[derive(Debug)] +pub struct MultiBlockObserver { + observers: Vec>, +} + +impl MultiBlockObserver { + pub fn new(observers: Vec>) -> Self { + Self { observers } + } +} + +impl BlockObserver for MultiBlockObserver { + fn on_block_built( + &self, + slot: u64, + parent_hash: BlockHash, + parent_block_root: B256, + block: &Block, + ) { + for observer in &self.observers { + observer.on_block_built(slot, parent_hash, parent_block_root, block); + } + } +} diff --git a/crates/rbuilder/src/live_builder/block_output/mod.rs b/crates/rbuilder/src/live_builder/block_output/mod.rs index 39d312ae5..756e43144 100644 --- a/crates/rbuilder/src/live_builder/block_output/mod.rs +++ b/crates/rbuilder/src/live_builder/block_output/mod.rs @@ -1,5 +1,6 @@ pub mod best_block_from_algorithms; pub mod bidding_service_interface; +pub mod block_observer; pub mod relay_submit; pub mod true_value_bidding_service; pub mod unfinished_block_processing; diff --git a/crates/rbuilder/src/live_builder/block_output/relay_submit.rs b/crates/rbuilder/src/live_builder/block_output/relay_submit.rs index eeece4fc9..6f161ec41 100644 --- a/crates/rbuilder/src/live_builder/block_output/relay_submit.rs +++ b/crates/rbuilder/src/live_builder/block_output/relay_submit.rs @@ -686,7 +686,7 @@ impl MultiRelayBlockBuildingSink for RelaySetDispatcher { fn new_block(&self, relay_set: RelaySet, block: Block) { if let Some(sink) = self.sinks.get(&relay_set) { sink.new_block(block); - } else { + } else if !relay_set.relays().is_empty() { error!(relay_set = ?relay_set, "Relay set not found"); } } diff --git a/crates/rbuilder/src/live_builder/block_output/true_value_bidding_service.rs b/crates/rbuilder/src/live_builder/block_output/true_value_bidding_service.rs index 0c3e45a73..968831a4b 100644 --- a/crates/rbuilder/src/live_builder/block_output/true_value_bidding_service.rs +++ b/crates/rbuilder/src/live_builder/block_output/true_value_bidding_service.rs @@ -37,12 +37,15 @@ impl NewTrueBlockValueBiddingService { default_relay_set.remove(&relay); relay_sets_subsidies.insert(RelaySet::new(vec![relay]), subsidy); } - if !default_relay_set.is_empty() { - relay_sets_subsidies.insert( - RelaySet::new(default_relay_set.into_iter().collect()), - config.subsidy, - ); - } + // TODO: this setup was done mainly for testing the implementation + // and should be subsituted with a better approach, maybe make passing relays as optional + // always insert a relay set — even if empty (EPBS-only mode with no relays). + // This ensures the bidding service produces seal commands so blocks flow + // through the finalization pipeline and reach the block observer. + relay_sets_subsidies.insert( + RelaySet::new(default_relay_set.into_iter().collect()), + config.subsidy, + ); Ok(Self { slot_delta_to_start_bidding: config.slot_delta_to_start_bidding, diff --git a/crates/rbuilder/src/live_builder/block_output/unfinished_block_processing.rs b/crates/rbuilder/src/live_builder/block_output/unfinished_block_processing.rs index 7fe3ba2fc..b65d543dd 100644 --- a/crates/rbuilder/src/live_builder/block_output/unfinished_block_processing.rs +++ b/crates/rbuilder/src/live_builder/block_output/unfinished_block_processing.rs @@ -9,6 +9,7 @@ use ahash::HashMap; /// 6. Bidding service asks to finalize that block with concrete proposer value /// 7. Finalized block is adjusted to pay chosen amount to the proposer (`finalize_worker` thread) /// 8. Resulting block is submitted to `BlockBuildingSink` (in running builder its used by a thread that submits block to relays). +/// 9. Block observers (like EPBS bid provider) are notified of the new block. /// /// Alternatively if configured (adjust_finalized_blocks = true) to run using old flow `prefinalize_worker` would not do anything with the block /// and `finalize_worker` would do full finalization instead of adjustment of the finalize block. @@ -56,6 +57,7 @@ use super::{ BiddingService, BlockSealInterfaceForSlotBidder, BuiltBlockDescriptorForSlotBidder, SlotBidder, SlotBidderSealBidCommand, }, + block_observer::BlockObserver, relay_submit::RelaySubmitSinkFactory, }; @@ -67,6 +69,7 @@ use crate::live_builder::building::built_block_cache::BuiltBlockCache; /// 1. UnfinishedBuiltBlocksInput and starts `prefinalize_worker` and `finalize_worker` threads. /// 2. SlotBidder from BiddingService to manage bidding values for the sealed blocks /// 3. BlockBuildingSink to send finished blocks for relay submission +/// 4. Notifies block observers (like EPBS bid provider) of finalized blocks. #[derive(Derivative)] #[derivative(Debug)] pub struct UnfinishedBuiltBlocksInputFactory

{ @@ -81,6 +84,9 @@ pub struct UnfinishedBuiltBlocksInputFactory

{ adjust_finalized_blocks: bool, /// relay sets well get on bids. relay_sets: Vec, + /// Optional block observer for EPBS and other integrations. + #[derivative(Debug = "ignore")] + block_observer: Option>, } impl UnfinishedBuiltBlocksInputFactory

{ @@ -97,9 +103,16 @@ impl UnfinishedBuiltBlocksInputFactory

{ wallet_balance_watcher, adjust_finalized_blocks, relay_sets, + block_observer: None, } } + /// Set the block observer for EPBS integration. + pub fn with_block_observer(mut self, observer: Arc) -> Self { + self.block_observer = Some(observer); + self + } + pub fn create_sink( &mut self, slot_data: MevBoostSlotData, @@ -146,6 +159,18 @@ impl UnfinishedBuiltBlocksInputFactory

{ .create_builder_sink(slot_data.clone(), cancel.clone()) .into(); + // extract slot info for block observer + let slot = slot_data.slot(); + let parent_hash = slot_data.payload_attributes_event.data.parent_block_hash; + // Beacon parent block root from payload_attributes — used as + // bid.parent_block_root in EPBS bids per gloas/builder.md. + let parent_block_root = slot_data.parent_block_root(); + + info!( + relay_set_count = input.last_finalize_commands.len(), + has_observer = self.block_observer.is_some(), + "Spawning finalize threads for slot" + ); for (relay_set, last_finalize_command) in input.last_finalize_commands.iter() { let finalized_blocks = input.pre_finalized_multi_blocks.clone(); let cancellation_token = cancel.clone(); @@ -153,6 +178,7 @@ impl UnfinishedBuiltBlocksInputFactory

{ let relay_set = relay_set.clone(); let last_finalize_command = last_finalize_command.clone(); let block_sink = block_sink.clone(); + let block_observer = self.block_observer.clone(); std::thread::Builder::new() .name("finalize_worker".into()) .spawn(move || { @@ -163,6 +189,10 @@ impl UnfinishedBuiltBlocksInputFactory

{ last_finalize_command, adjust_finalized_blocks, cancellation_token, + block_observer, + slot, + parent_hash, + parent_block_root, ) }) .unwrap(); @@ -436,7 +466,10 @@ impl UnfinishedBuiltBlocksInput { let id_span = tracing::info_span!("block_id", block_id = bid.block_id.0); let _guard_id_span = id_span.enter(); - trace!(?bid, "Received seal command"); + info!( + payout_info_count = bid.payout_info.len(), + "Received seal command" + ); let mut unused_multi_blocks = Vec::new(); let mut found_multi_block: Option = None; @@ -582,14 +615,20 @@ impl UnfinishedBuiltBlocksInput { block_building_helper, local_ctx, ); + let relay_set_count = multi_prefinalized_block + .prefinalized_blocks_by_relay_set + .len(); self.pre_finalized_multi_blocks .lock() .push(multi_prefinalized_block); // Must update creation time here because since constructor we did some stuff and we want to measure only bidding core timings. block_descriptor.creation_time = OffsetDateTime::now_utc(); + info!( + block_id = block_id.0, + relay_set_count, "Prefinalized block, notifying bidding service" + ); slot_bidder.notify_new_built_block(block_descriptor); - trace!("Notified bidding service"); } trace!("Finished prefinalize_worker"); } @@ -597,6 +636,7 @@ impl UnfinishedBuiltBlocksInput { // finalize_worker impl UnfinishedBuiltBlocksInput { + #[allow(clippy::too_many_arguments)] fn run_finalize_thread( relay_set: RelaySet, block_building_sink: Arc, @@ -604,6 +644,10 @@ impl UnfinishedBuiltBlocksInput { last_finalize_command: Arc>, adjust_finalized_blocks: bool, cancellation_token: CancellationToken, + block_observer: Option>, + slot: u64, + parent_hash: alloy_primitives::BlockHash, + parent_block_root: alloy_primitives::B256, ) { loop { if cancellation_token.is_cancelled() { @@ -668,6 +712,20 @@ impl UnfinishedBuiltBlocksInput { result.block.trace.chosen_as_best_at = finalize_command.prefinalized_block.chosen_as_best_at; result.block.trace.sent_to_bidder = finalize_command.prefinalized_block.sent_to_bidder; + + // Notify block observer (EPBS bid provider) of the new block + if let Some(observer) = &block_observer { + info!( + slot, + ?parent_hash, + ?parent_block_root, + "Finalize thread notifying block observer" + ); + observer.on_block_built(slot, parent_hash, parent_block_root, &result.block); + } else { + tracing::debug!(slot, "Finalize thread: no block observer configured"); + } + block_building_sink.new_block(relay_set.clone(), result.block); } } diff --git a/crates/rbuilder/src/live_builder/builder_api/bid_provider.rs b/crates/rbuilder/src/live_builder/builder_api/bid_provider.rs new file mode 100644 index 000000000..b1d5a952c --- /dev/null +++ b/crates/rbuilder/src/live_builder/builder_api/bid_provider.rs @@ -0,0 +1,640 @@ +//! EPBS Bid Provider - Integrates with the block building pipeline to generate bids. +//! +//! This module provides the `LiveEpbsBidProvider` which implements `EpbsBidProvider` +//! by connecting to the existing block building infrastructure. + +use alloy_primitives::{BlockHash, B256, U256}; +use parking_lot::RwLock; +use rbuilder_primitives::epbs::{ + BeaconWithdrawal, CachedPayloadData, ExecutionPayloadBid, ExecutionRequests, GetBidParams, + SignedExecutionPayloadBid, +}; +use std::{collections::HashMap, sync::Arc, time::Instant}; +use tokio::sync::mpsc; +use tracing::{debug, info, trace}; + +use crate::{ + building::builders::Block, live_builder::block_output::block_observer::BlockObserver, + mev_boost::EpbsBidSigner, +}; +use alloy_primitives::Bytes; + +use super::EpbsBidProvider; + +/// Key for tracking best blocks by slot and parent. +#[derive(Debug, Clone, PartialEq, Eq, Hash)] +pub struct SlotParentKey { + pub slot: u64, + pub parent_hash: BlockHash, +} + +impl SlotParentKey { + pub fn from_params(params: &GetBidParams) -> Self { + Self { + slot: params.slot, + parent_hash: params.parent_hash, + } + } +} + +/// Cached block data for generating EPBS bids. +#[derive(Debug, Clone)] +pub struct CachedBlockData { + /// The built block from the building pipeline. + pub block: Block, + /// When this block was cached. + pub cached_at: Instant, + /// Slot this block is for. + pub slot: u64, + /// Beacon parent_block_root from payload_attributes. MUST be paired with + /// `parent_block_hash` (below) — Prysm verifies that the beacon block at + /// `parent_block_root` commits to `parent_block_hash` as its EL payload. + pub parent_block_root: B256, + /// EL parent block hash from payload_attributes (NOT from the built block's + /// own parent_hash — those can diverge from the CL's view). + pub parent_block_hash: BlockHash, +} + +/// Config for the LiveEpbsBidProvider. +#[derive(Debug, Clone)] +pub struct LiveEpbsBidProviderConfig { + /// max number of blocks to cache. + pub max_cached_blocks: usize, + /// max age of a cached block before it's considered stale. + pub max_block_age_ms: u64, + /// only meant to be used for devnet testing + /// TODO dont use for prod + pub bid_value_subsidy_gwei: u64, +} + +impl Default for LiveEpbsBidProviderConfig { + fn default() -> Self { + Self { + max_cached_blocks: 100, + max_block_age_ms: 12_000, // one slot, but maybe we can also update it? + // Default 0: production-safe. Set explicitly via L1Config + bid_value_subsidy_gwei: 0, + } + } +} + +/// Live EPBS Bid Provider that integrates with the block building pipeline. +/// +/// This provider: +/// 1. Receives built blocks from the block building pipeline +/// 2. Tracks the best block for each slot/parent combination +/// 3. Generates SignedExecutionPayloadBid on request +/// 4. Caches full payloads for later revelation +pub struct LiveEpbsBidProvider { + /// Configuration. + config: LiveEpbsBidProviderConfig, + /// The signer for creating signed bids. Optional to support lazy initialization. + /// Contains the builder_index (looked up from beacon chain by public key). + signer: Arc>>, + /// Best blocks by slot/parent key. + best_blocks: RwLock>, + /// Cache of full payloads for revelation, keyed by **block_hash**. + /// growth is capped and is achieved via slot-aware cleanup + /// `cleanup_older_than(oldest_slot)` drops entries whose + /// `bid.message.slot < oldest_slot`. The P2P main loop calls this on + /// every detected slot transition with `current_slot - 64`, mirroring + /// buildoor's pattern. + payload_cache: Arc>>, + fresh_block_tx: RwLock>>, +} + +impl LiveEpbsBidProvider { + /// Create a new LiveEpbsBidProvider with a signer. + pub fn new(signer: EpbsBidSigner, config: LiveEpbsBidProviderConfig) -> Self { + Self { + config, + signer: Arc::new(RwLock::new(Some(signer))), + best_blocks: RwLock::new(HashMap::new()), + payload_cache: Arc::new(RwLock::new(HashMap::new())), + fresh_block_tx: RwLock::new(None), + } + } + + /// Create a new uninitialized LiveEpbsBidProvider. + /// + /// The signer must be set later using `set_signer()` before bids can be generated. + /// The builder_index will be obtained from the signer once it's set. + pub fn new_uninitialized(config: LiveEpbsBidProviderConfig) -> Self { + Self { + config, + signer: Arc::new(RwLock::new(None)), + best_blocks: RwLock::new(HashMap::new()), + payload_cache: Arc::new(RwLock::new(HashMap::new())), + fresh_block_tx: RwLock::new(None), + } + } + + /// Subscribe to "fresh block cached" notifications. Returns a receiver that + /// emits a slot number whenever `on_new_block` caches a block (including + /// when an existing slot's best block is updated). + pub fn subscribe_fresh_blocks(&self) -> mpsc::UnboundedReceiver { + let (tx, rx) = mpsc::unbounded_channel(); + *self.fresh_block_tx.write() = Some(tx); + rx + } + + /// Set the signer for this provider. + /// + /// This is used for lazy initialization when the builder_index and signing domain + /// need to be fetched from the beacon chain after startup. + pub fn set_signer(&self, signer: EpbsBidSigner) { + *self.signer.write() = Some(signer); + } + + /// Check if the signer is ready. + pub fn is_ready(&self) -> bool { + self.signer.read().is_some() + } + + /// Get the builder index (if signer is initialized). + pub fn builder_index(&self) -> Option { + self.signer.read().as_ref().map(|s| s.builder_index()) + } + + /// Get a shared reference to the signer for use by the P2P service. + pub fn shared_signer(&self) -> Arc>> { + self.signer.clone() + } + + /// Get a shared reference to the payload cache for use by the P2P reveal handler. + pub fn shared_payload_cache(&self) -> Arc>> { + self.payload_cache.clone() + } + + /// Notify the provider of a new built block. + /// + /// This should be called by the block building pipeline whenever a new + /// block is produced. The provider will track the best block for each + /// slot/parent combination. + pub fn on_new_block( + &self, + slot: u64, + parent_hash: BlockHash, + parent_block_root: B256, + block: Block, + ) { + let key = SlotParentKey { slot, parent_hash }; + + let cached = CachedBlockData { + block: block.clone(), + cached_at: Instant::now(), + slot, + parent_block_root, + // Use the parent_block_hash from payload_attributes (passed via + // BlockObserver). It must match the EL block referenced by + // `parent_block_root` from the CL's perspective. Using the built + // block's own parent_hash can diverge from the CL view and breaks + // Prysm's `VerifyParentBlockHash` check. + parent_block_hash: parent_hash, + }; + + let mut best_blocks = self.best_blocks.write(); + + // Check if this block is better than the current best + let should_update = match best_blocks.get(&key) { + Some(existing) => block.trace.bid_value > existing.block.trace.bid_value, + None => true, + }; + + if should_update { + info!( + slot, + ?parent_hash, + block_hash = ?block.sealed_block.hash(), + bid_value = %block.trace.bid_value, + cached_blocks = best_blocks.len() + 1, + "EPBS: Cached new best block for slot" + ); + best_blocks.insert(key, cached); + } + + // Cleanup old entries if we are over the limit + if best_blocks.len() > self.config.max_cached_blocks { + let now = Instant::now(); + best_blocks.retain(|_, v| { + now.duration_since(v.cached_at).as_millis() < self.config.max_block_age_ms as u128 + }); + } + + // Release the best_blocks lock before notifying subscribers. Notifications + // only fire when we actually updated the cache. + drop(best_blocks); + if should_update { + if let Some(tx) = self.fresh_block_tx.read().as_ref() { + // Channel is unbounded; failure means receiver dropped, which + // is benign (the P2P service may not be running). + let _ = tx.send(slot); + } + } + } + + /// Get the best block for a given slot/parent combination. + pub fn get_best_block(&self, params: &GetBidParams) -> Option { + let best_blocks = self.best_blocks.read(); + // If the caller specifies a concrete parent_hash, look up the exact key. + // If parent_hash is ZERO (P2P bidder doesn't track parent_hash before + // bidding), find the highest-value cached block for the requested slot. + if !params.parent_hash.is_zero() { + let key = SlotParentKey::from_params(params); + return best_blocks.get(&key).cloned(); + } + best_blocks + .iter() + .filter(|(k, _)| k.slot == params.slot) + .max_by_key(|(_, v)| v.block.trace.bid_value) + .map(|(_, v)| v.clone()) + } + + /// Convert a Block to an ExecutionPayloadBid. + /// + /// Method form (not associated fn) so it can read `self.config` for the + /// devnet bid-value subsidy. See `LiveEpbsBidProviderConfig::bid_value_subsidy_gwei` + /// for the rationale and removal criteria. + fn block_to_bid( + &self, + cached: &CachedBlockData, + params: &GetBidParams, + builder_index: u64, + blob_kzg_commitments: Vec, + ) -> ExecutionPayloadBid { + let block = &cached.block; + // bid_value is in wei, we need gwei + let true_value_gwei: u64 = (block.trace.bid_value / U256::from(1_000_000_000u64)) + .try_into() + .unwrap_or(u64::MAX); + + // Apply the devnet subsidy on top of the block's true value. Saturating + // add so a misconfigured huge subsidy doesn't wrap. When the subsidy is + // 0 (production default), this is a no-op. + let value_gwei = true_value_gwei.saturating_add(self.config.bid_value_subsidy_gwei); + if self.config.bid_value_subsidy_gwei > 0 { + debug!( + slot = params.slot, + true_value_gwei, + subsidy_gwei = self.config.bid_value_subsidy_gwei, + bid_value_gwei = value_gwei, + "Applied devnet bid-value subsidy" + ); + } + + // Use fee_recipient from caller (proposer preferences if cached, otherwise + // the hardcoded devnet fallback set in p2p::service). If still zero (e.g. + // builder server callers that don't set it), fall back to the block's own + // beneficiary — this won't pass the gossip [REJECT] rule but is a sane + // last resort. + let fee_recipient = if !params.fee_recipient.is_zero() { + params.fee_recipient + } else { + block.sealed_block.beneficiary + }; + + // If the caller didn't supply a concrete parent_hash (e.g. P2P bidder), + // use the cached parent_block_hash from payload_attributes (NOT the built + // block's own parent_hash). This must match the EL block that the beacon + // block at `parent_block_root` commits to — Prysm verifies this pairing. + let parent_block_hash = if params.parent_hash.is_zero() { + cached.parent_block_hash + } else { + params.parent_hash + }; + + // Use the cached parent_block_root from when the block was prefinalized + // (from payload_attributes_event for that slot). If caller supplied a + // non-zero parent_root, that takes priority. + let parent_block_root = if !params.parent_root.is_zero() { + params.parent_root + } else { + cached.parent_block_root + }; + + // Compute the typed execution_requests root the bid commits to. + // cl verifies at envelope reveal that the revealed requests hash + // to this same root (gloas/p2p-interface.md) + let exec_reqs = Self::convert_execution_requests(&block.execution_requests); + let execution_requests_root = crate::mev_boost::sign_epbs::execution_requests_root( + &exec_reqs, + ) + .unwrap_or_else(|err| { + tracing::warn!( + slot = params.slot, + ?err, + "Failed to compute execution_requests_root; bidding with zero root \ + (envelope reveal will fail cls request-root check)" + ); + B256::ZERO + }); + + ExecutionPayloadBid { + parent_block_hash, + parent_block_root, + block_hash: block.sealed_block.hash(), + prev_randao: block.sealed_block.mix_hash, + fee_recipient, + gas_limit: block.sealed_block.gas_limit, + builder_index, + slot: params.slot, + value: value_gwei, + execution_payment: 0, // In protocol payment + blob_kzg_commitments, + execution_requests_root, + } + } + + // TODO: review implementation + /// Convert execution requests from EIP-7685 typed format to separated lists. + /// + /// EIP-7685 execution requests are prefixed with a type byte: + /// - 0x00: Deposit requests + /// - 0x01: Withdrawal requests + /// - 0x02: Consolidation requests + fn convert_execution_requests(requests: &[Bytes]) -> ExecutionRequests { + let mut deposits = Vec::new(); + let mut withdrawals = Vec::new(); + let mut consolidations = Vec::new(); + + for request in requests { + if request.is_empty() { + continue; + } + + let request_type = request[0]; + let request_data = Bytes::copy_from_slice(&request[1..]); + + match request_type { + 0x00 => deposits.push(request_data), + 0x01 => withdrawals.push(request_data), + 0x02 => consolidations.push(request_data), + _ => { + // Unknown request type - skip it + debug!(request_type, "Unknown execution request type, skipping"); + } + } + } + + ExecutionRequests { + deposits, + withdrawals, + consolidations, + } + } + + /// Cache the payload for later revelation. + /// + /// Keyed by block_hash so multiple bids per slot (different algos / different + /// orderings → different block_hashes) all stay reachable; the proposer may + /// pick any of them. Blob bytes are NOT copied here — `cached.sidecars` + /// holds `Arc` refs to the original sidecars from the built block (cheap + /// clone), and the wire-format `Vec` is built only at reveal time + /// via `cached.blobs()` / `cached.cell_proofs()`. + /// + /// Bounded growth comes from slot-aware cleanup, not from the cache key. + fn cache_payload(&self, signed_bid: &SignedExecutionPayloadBid, block: &Block) { + let slot = signed_bid.message.slot; + let block_hash = signed_bid.message.block_hash; + + // Convert block to ExecutionPayloadGloas + let payload = self.block_to_execution_payload(block, slot); + + // Extract blob commitments + let blob_kzg_commitments = self.extract_blob_commitments(block); + + // Hold the sidecars by Arc reference. No fresh blob byte copy at + // cache-insert time — the original buffers in the Block stay shared. + let sidecars: Vec<_> = block.txs_blobs_sidecars.to_vec(); + + let execution_requests = Self::convert_execution_requests(&block.execution_requests); + + let cached = CachedPayloadData::new( + signed_bid.clone(), + payload, + execution_requests, + blob_kzg_commitments, + sidecars, + ); + + debug!( + slot, + ?block_hash, + sidecar_count = cached.sidecars.len(), + "Cached payload for revelation" + ); + + self.payload_cache.write().insert(block_hash, cached); + } + + /// Convert a Block to ExecutionPayloadGloas (flat snake_case wire shape). + fn block_to_execution_payload( + &self, + block: &Block, + slot: u64, + ) -> rbuilder_primitives::epbs::ExecutionPayloadGloas { + let sealed = &block.sealed_block; + + let transactions: Vec = sealed + .body() + .transactions + .iter() + .map(|tx| { + let mut buf = Vec::new(); + alloy_eips::eip2718::Encodable2718::encode_2718(tx, &mut buf); + Bytes::from(buf) + }) + .collect(); + + let withdrawals: Vec = sealed + .body() + .withdrawals + .as_ref() + .map(|w| { + w.iter() + .map(|wd| BeaconWithdrawal { + index: wd.index, + validator_index: wd.validator_index, + address: wd.address, + amount: wd.amount, + }) + .collect() + }) + .unwrap_or_default(); + + rbuilder_primitives::epbs::ExecutionPayloadGloas { + parent_hash: sealed.parent_hash, + fee_recipient: sealed.beneficiary, + state_root: sealed.state_root, + receipts_root: sealed.receipts_root, + logs_bloom: sealed.logs_bloom, + prev_randao: sealed.mix_hash, + block_number: sealed.number, + gas_limit: sealed.gas_limit, + gas_used: sealed.gas_used, + timestamp: sealed.timestamp, + extra_data: sealed.extra_data.clone(), + base_fee_per_gas: U256::from(sealed.base_fee_per_gas.unwrap_or_default()), + block_hash: sealed.hash(), + transactions, + withdrawals, + blob_gas_used: sealed.blob_gas_used.unwrap_or_default(), + excess_blob_gas: sealed.excess_blob_gas.unwrap_or_default(), + block_access_list: block.block_access_list.clone().unwrap_or_default(), + slot_number: slot, + } + } + + /// Extract blob KZG commitments from a block. + fn extract_blob_commitments(&self, block: &Block) -> Vec { + let mut commitments = Vec::new(); + + for sidecar in &block.txs_blobs_sidecars { + match sidecar.as_ref() { + alloy_eips::eip7594::BlobTransactionSidecarVariant::Eip4844(s) => { + for commitment in &s.commitments { + commitments.push(alloy_primitives::Bytes::copy_from_slice( + commitment.as_slice(), + )); + } + } + alloy_eips::eip7594::BlobTransactionSidecarVariant::Eip7594(s) => { + for commitment in &s.commitments { + commitments.push(alloy_primitives::Bytes::copy_from_slice( + commitment.as_slice(), + )); + } + } + } + } + + commitments + } + + /// Get a cached payload by block_hash. + pub fn get_cached_payload(&self, block_hash: &BlockHash) -> Option { + self.payload_cache.read().get(block_hash).cloned() + } + + /// drop payload cache and best-blocks entries whose slot is strictly older + /// than `oldest_slot_to_keep`. Called from the P2P main loop on slot + /// transitions to bound memory growth payload_cache is keyed by block_hash + /// but each entry knows its slot via `entry.bid.message.slot` so we filter on that. + pub fn cleanup_older_than(&self, oldest_slot_to_keep: u64) { + let mut payload = self.payload_cache.write(); + let before = payload.len(); + payload.retain(|_, v| v.bid.message.slot >= oldest_slot_to_keep); + let after_payload = payload.len(); + drop(payload); + + let mut best = self.best_blocks.write(); + let best_before = best.len(); + best.retain(|key, _| key.slot >= oldest_slot_to_keep); + let best_after = best.len(); + drop(best); + + if before != after_payload || best_before != best_after { + debug!( + oldest_slot_to_keep, + payload_pruned = before - after_payload, + best_pruned = best_before - best_after, + "Pruned old cache entries" + ); + } + } +} + +impl std::fmt::Debug for LiveEpbsBidProvider { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + f.debug_struct("LiveEpbsBidProvider") + .field("config", &self.config) + .field("builder_index", &self.builder_index()) + .field("signer_ready", &self.is_ready()) + .field("cached_blocks", &self.best_blocks.read().len()) + .field("cached_payloads", &self.payload_cache.read().len()) + .finish() + } +} + +/// Implement BlockObserver so that the block building pipeline can notify us of new blocks. +impl BlockObserver for LiveEpbsBidProvider { + fn on_block_built( + &self, + slot: u64, + parent_hash: BlockHash, + parent_block_root: B256, + block: &Block, + ) { + self.on_new_block(slot, parent_hash, parent_block_root, block.clone()); + } +} + +#[async_trait::async_trait] +impl EpbsBidProvider for LiveEpbsBidProvider { + async fn generate_bid( + &self, + params: &GetBidParams, + ) -> eyre::Result> { + // Check if signer is ready + let signer = self.signer.read(); + let signer = match signer.as_ref() { + Some(s) => s, + None => { + debug!( + slot = params.slot, + "EPBS signer not yet initialized, cannot generate bid" + ); + return Ok(None); + } + }; + + // Get the best block for this slot/parent + let cached_block = match self.get_best_block(params) { + Some(cached) => cached, + None => { + trace!( + slot = params.slot, + ?params.parent_hash, + "No block available for bid request" + ); + return Ok(None); + } + }; + + // Check if the block is too old + let age_ms = cached_block.cached_at.elapsed().as_millis(); + if age_ms > self.config.max_block_age_ms as u128 { + debug!( + slot = params.slot, + age_ms, "Best block is stale, not returning bid" + ); + return Ok(None); + } + + // extract blob commitments + let blob_kzg_commitments = self.extract_blob_commitments(&cached_block.block); + + // Create the bid + let bid = self.block_to_bid( + &cached_block, + params, + signer.builder_index(), + blob_kzg_commitments, + ); + + // Sign the bid + let signed_bid = signer.sign_bid(&bid)?; + + info!( + slot = params.slot, + block_hash = ?signed_bid.message.block_hash, + value = signed_bid.message.value, + "Generated EPBS bid" + ); + + // Cache the payload for later revelation + self.cache_payload(&signed_bid, &cached_block.block); + + Ok(Some(signed_bid)) + } +} diff --git a/crates/rbuilder/src/live_builder/builder_api/handlers.rs b/crates/rbuilder/src/live_builder/builder_api/handlers.rs new file mode 100644 index 000000000..255b5e720 --- /dev/null +++ b/crates/rbuilder/src/live_builder/builder_api/handlers.rs @@ -0,0 +1,179 @@ +use alloy_primitives::{Address, B256}; +use axum::{ + extract::{Path, State}, + http::{HeaderMap, StatusCode}, + response::IntoResponse, + Json, +}; +use rbuilder_primitives::epbs::{GetBidParams, GetExecutionPayloadBidResponse}; +use std::sync::Arc; +use tracing::{error, info, trace}; + +use super::EpbsBuilderState; + +/// GET /eth/v1/builder/execution_payload_bid/{slot}/{parent_hash}/{parent_root}/{proposer_index} +/// +/// returns a SignedExecutionPayloadBid for the given slot. +pub async fn get_execution_payload_bid_handler( + State(state): State>, + Path((slot, parent_hash, parent_root, proposer_index)): Path<(u64, String, String, u64)>, + headers: HeaderMap, +) -> Result { + // Parse path parameters + let parent_hash = + parse_hash(&parent_hash).map_err(|_| GetExecutionPayloadBidError::InvalidParentHash)?; + let parent_root = + parse_hash(&parent_root).map_err(|_| GetExecutionPayloadBidError::InvalidParentRoot)?; + + // Parse headers + let fee_recipient = parse_fee_recipient(&headers)?; + let timeout_ms = parse_timeout_ms(&headers); + let date_milliseconds = parse_date_milliseconds(&headers); + + let params = GetBidParams { + slot, + parent_hash, + parent_root, + proposer_index, + fee_recipient, + timeout_ms, + date_milliseconds, + }; + + trace!( + slot = params.slot, + proposer_index = params.proposer_index, + ?params.parent_hash, + ?params.fee_recipient, + "Received get_execution_payload_bid request" + ); + + // Get the best bid from the builder + match state.get_execution_payload_bid(¶ms).await { + Ok(Some(signed_bid)) => { + info!( + slot = params.slot, + block_hash = ?signed_bid.message.block_hash, + value = signed_bid.message.value, + "Returning execution payload bid" + ); + + let response = GetExecutionPayloadBidResponse { + version: "gloas".to_string(), + data: signed_bid, + }; + + Ok(( + StatusCode::OK, + [("Eth-Consensus-Version", "gloas")], + Json(response), + )) + } + Ok(None) => { + trace!(slot = params.slot, "No execution payload bid available"); + Err(GetExecutionPayloadBidError::NoBidAvailable) + } + Err(e) => { + error!(slot = params.slot, error = ?e, "Error generating execution payload bid"); + Err(GetExecutionPayloadBidError::InternalError(e.to_string())) + } + } +} + +/// Error type for get_execution_payload_bid handler. +#[derive(Debug)] +pub enum GetExecutionPayloadBidError { + InvalidParentHash, + InvalidParentRoot, + InvalidFeeRecipient, + MissingFeeRecipient, + NoBidAvailable, + InternalError(String), +} + +impl IntoResponse for GetExecutionPayloadBidError { + fn into_response(self) -> axum::response::Response { + let (status, message) = match self { + GetExecutionPayloadBidError::InvalidParentHash => { + (StatusCode::BAD_REQUEST, "Invalid parent_hash".to_string()) + } + GetExecutionPayloadBidError::InvalidParentRoot => { + (StatusCode::BAD_REQUEST, "Invalid parent_root".to_string()) + } + GetExecutionPayloadBidError::InvalidFeeRecipient => ( + StatusCode::BAD_REQUEST, + "Invalid X-Fee-Recipient header".to_string(), + ), + GetExecutionPayloadBidError::MissingFeeRecipient => ( + StatusCode::BAD_REQUEST, + "Missing required X-Fee-Recipient header".to_string(), + ), + GetExecutionPayloadBidError::NoBidAvailable => { + // Per spec, return 204 No Content when no bid is available + return StatusCode::NO_CONTENT.into_response(); + } + GetExecutionPayloadBidError::InternalError(msg) => { + (StatusCode::INTERNAL_SERVER_ERROR, msg) + } + }; + + let body = serde_json::json!({ + "code": status.as_u16(), + "message": message + }); + + (status, Json(body)).into_response() + } +} + +// Helper functions for parsing request parameters + +fn parse_hash(s: &str) -> Result { + // Strip 0x prefix if present + let s = s.strip_prefix("0x").unwrap_or(s); + let bytes = hex::decode(s).map_err(|_| ())?; + if bytes.len() != 32 { + return Err(()); + } + let mut arr = [0u8; 32]; + arr.copy_from_slice(&bytes); + Ok(B256::from(arr)) +} + +fn parse_fee_recipient(headers: &HeaderMap) -> Result { + let header_value = headers + .get("X-Fee-Recipient") + .ok_or(GetExecutionPayloadBidError::MissingFeeRecipient)? + .to_str() + .map_err(|_| GetExecutionPayloadBidError::InvalidFeeRecipient)?; + + let s = header_value.strip_prefix("0x").unwrap_or(header_value); + let bytes = hex::decode(s).map_err(|_| GetExecutionPayloadBidError::InvalidFeeRecipient)?; + if bytes.len() != 20 { + return Err(GetExecutionPayloadBidError::InvalidFeeRecipient); + } + let mut arr = [0u8; 20]; + arr.copy_from_slice(&bytes); + Ok(Address::from(arr)) +} + +fn parse_timeout_ms(headers: &HeaderMap) -> Option { + headers + .get("X-Timeout-Ms") + .and_then(|v| v.to_str().ok()) + .and_then(|s| s.parse().ok()) +} + +fn parse_date_milliseconds(headers: &HeaderMap) -> Option { + headers + .get("Date-Milliseconds") + .and_then(|v| v.to_str().ok()) + .and_then(|s| s.parse().ok()) +} + +/// GET /eth/v1/builder/status +/// +/// Returns 200 OK if the builder is healthy. +pub async fn status_handler() -> StatusCode { + StatusCode::OK +} diff --git a/crates/rbuilder/src/live_builder/builder_api/mod.rs b/crates/rbuilder/src/live_builder/builder_api/mod.rs new file mode 100644 index 000000000..0c6edc1b0 --- /dev/null +++ b/crates/rbuilder/src/live_builder/builder_api/mod.rs @@ -0,0 +1,11 @@ +mod bid_provider; +mod handlers; +pub mod p2p; +mod server; + +pub use bid_provider::{ + CachedBlockData, LiveEpbsBidProvider, LiveEpbsBidProviderConfig, SlotParentKey, +}; +pub use handlers::{get_execution_payload_bid_handler, GetExecutionPayloadBidError}; +pub use p2p::{EpbsP2PConfig, EpbsP2PService}; +pub use server::{EpbsBidProvider, EpbsBuilderServer, EpbsBuilderServerConfig, EpbsBuilderState}; diff --git a/crates/rbuilder/src/live_builder/builder_api/p2p/bid_tracker.rs b/crates/rbuilder/src/live_builder/builder_api/p2p/bid_tracker.rs new file mode 100644 index 000000000..6c21aae89 --- /dev/null +++ b/crates/rbuilder/src/live_builder/builder_api/p2p/bid_tracker.rs @@ -0,0 +1,198 @@ +use alloy_primitives::{BlockHash, B256}; +use parking_lot::RwLock; +use rbuilder_primitives::epbs::SignedExecutionPayloadBid; +use std::collections::HashMap; +use tracing::debug; + +// TODO: revisit key construction +/// Key for tracking bids +#[derive(Debug, Clone, PartialEq, Eq, Hash)] +struct BidKey { + slot: u64, + parent_block_hash: BlockHash, + parent_block_root: B256, +} + +impl BidKey { + fn from_bid(bid: &rbuilder_primitives::epbs::ExecutionPayloadBid) -> Self { + Self { + slot: bid.slot, + parent_block_hash: bid.parent_block_hash, + parent_block_root: bid.parent_block_root, + } + } +} + +/// Tracks competing bids and our own bids per slot from execution_payload_bid SSE to[ic] +#[derive(Debug)] +pub struct BidTracker { + /// Highest bid seen per (slot, parent_hash, parent_root). + highest_bids: RwLock>, + /// Our own submitted bids: slot -> latest bid. + our_bids: RwLock>, + // TODO: maybe we can remove this but keep for now + /// Our builder index for identifying our own bids. + our_builder_index: u64, +} + +impl BidTracker { + pub fn new(our_builder_index: u64) -> Self { + Self { + highest_bids: RwLock::new(HashMap::new()), + our_bids: RwLock::new(HashMap::new()), + our_builder_index, + } + } + + /// Process an incoming bid from the SSE stream. + /// Returns true if this bid is the new highest for its key. + pub fn on_bid_received(&self, bid: &SignedExecutionPayloadBid) -> bool { + let key = BidKey::from_bid(&bid.message); + let mut highest = self.highest_bids.write(); + + let is_new_highest = match highest.get(&key) { + Some(existing) => bid.message.value > existing.message.value, + None => true, + }; + + if is_new_highest { + debug!( + slot = bid.message.slot, + builder_index = bid.message.builder_index, + value = bid.message.value, + "New highest bid received" + ); + highest.insert(key, bid.clone()); + } + + is_new_highest + } + + /// Record a bid we submitted. + pub fn on_bid_submitted(&self, bid: &SignedExecutionPayloadBid) { + let slot = bid.message.slot; + self.our_bids.write().insert(slot, bid.clone()); + // Also track it as potentially the highest + self.on_bid_received(bid); + } + + /// Get the highest competing bid for a given slot/parent combination. + pub fn highest_bid( + &self, + slot: u64, + parent_hash: &BlockHash, + parent_root: &B256, + ) -> Option { + let key = BidKey { + slot, + parent_block_hash: *parent_hash, + parent_block_root: *parent_root, + }; + self.highest_bids.read().get(&key).cloned() + } + + /// Get our latest submitted bid for a slot. + pub fn our_bid(&self, slot: u64) -> Option { + self.our_bids.read().get(&slot).cloned() + } + + /// Check if we are currently the highest bidder for a slot/parent. + pub fn are_we_winning(&self, slot: u64, parent_hash: &BlockHash, parent_root: &B256) -> bool { + let key = BidKey { + slot, + parent_block_hash: *parent_hash, + parent_block_root: *parent_root, + }; + self.highest_bids + .read() + .get(&key) + .map(|bid| bid.message.builder_index == self.our_builder_index) + .unwrap_or(false) + } + + /// Clean up entries older than current_slot. + pub fn cleanup(&self, current_slot: u64) { + self.highest_bids + .write() + .retain(|key, _| key.slot >= current_slot.saturating_sub(2)); + self.our_bids + .write() + .retain(|&slot, _| slot >= current_slot.saturating_sub(2)); + } +} + +#[cfg(test)] +mod tests { + use super::*; + use alloy_primitives::Address; + use alloy_rpc_types_beacon::BlsSignature; + + fn make_bid(slot: u64, builder_index: u64, value: u64) -> SignedExecutionPayloadBid { + SignedExecutionPayloadBid { + message: rbuilder_primitives::epbs::ExecutionPayloadBid { + parent_block_hash: BlockHash::ZERO, + parent_block_root: B256::ZERO, + block_hash: BlockHash::ZERO, + prev_randao: B256::ZERO, + fee_recipient: Address::ZERO, + gas_limit: 30_000_000, + builder_index, + slot, + value, + execution_payment: 0, + blob_kzg_commitments: vec![], + execution_requests_root: B256::ZERO, + }, + signature: BlsSignature::default(), + } + } + + #[test] + fn test_bid_tracking() { + let tracker = BidTracker::new(1); + + // 1st bid from builder 2 + let bid1 = make_bid(100, 2, 1000); + assert!(tracker.on_bid_received(&bid1)); + + // higher bid from builder 3 + let bid2 = make_bid(100, 3, 2000); + assert!(tracker.on_bid_received(&bid2)); + + // lower bid should not replace + let bid3 = make_bid(100, 4, 500); + assert!(!tracker.on_bid_received(&bid3)); + + let highest = tracker + .highest_bid(100, &BlockHash::ZERO, &B256::ZERO) + .unwrap(); + assert_eq!(highest.message.value, 2000); + } + + #[test] + fn test_our_bid_tracking() { + let tracker = BidTracker::new(1); + + let our_bid = make_bid(100, 1, 1500); + tracker.on_bid_submitted(&our_bid); + + assert!(tracker.our_bid(100).is_some()); + assert!(tracker.are_we_winning(100, &BlockHash::ZERO, &B256::ZERO)); + + // someone outbided us + let higher_bid = make_bid(100, 2, 2000); + tracker.on_bid_received(&higher_bid); + assert!(!tracker.are_we_winning(100, &BlockHash::ZERO, &B256::ZERO)); + } + + #[test] + fn test_cleanup() { + let tracker = BidTracker::new(1); + tracker.on_bid_submitted(&make_bid(10, 1, 100)); + tracker.on_bid_submitted(&make_bid(20, 1, 200)); + + tracker.cleanup(20); + assert!(tracker.our_bid(10).is_none()); + assert!(tracker.our_bid(20).is_some()); + } +} diff --git a/crates/rbuilder/src/live_builder/builder_api/p2p/mod.rs b/crates/rbuilder/src/live_builder/builder_api/p2p/mod.rs new file mode 100644 index 000000000..892205380 --- /dev/null +++ b/crates/rbuilder/src/live_builder/builder_api/p2p/mod.rs @@ -0,0 +1,9 @@ +pub mod bid_tracker; +pub mod proposer_prefs; +pub mod reveal_handler; +pub mod scheduler; +pub mod service; +pub mod types; + +pub use service::EpbsP2PService; +pub use types::EpbsP2PConfig; diff --git a/crates/rbuilder/src/live_builder/builder_api/p2p/proposer_prefs.rs b/crates/rbuilder/src/live_builder/builder_api/p2p/proposer_prefs.rs new file mode 100644 index 000000000..681243551 --- /dev/null +++ b/crates/rbuilder/src/live_builder/builder_api/p2p/proposer_prefs.rs @@ -0,0 +1,92 @@ +use parking_lot::RwLock; +use rbuilder_primitives::epbs::ProposerPreferences; +use std::collections::HashMap; +use tracing::debug; + +/// Cache of proposer preferences keyed by proposal slot. +#[derive(Debug)] +pub struct ProposerPreferencesCache { + /// slot -> ProposerPreferences mapping. + prefs: RwLock>, +} + +impl Default for ProposerPreferencesCache { + fn default() -> Self { + Self::new() + } +} + +impl ProposerPreferencesCache { + pub fn new() -> Self { + Self { + prefs: RwLock::new(HashMap::new()), + } + } + + /// Insert or update preferences for a slot. + pub fn insert(&self, prefs: ProposerPreferences) { + let slot = prefs.proposal_slot; + debug!( + slot, + validator_index = prefs.validator_index, + fee_recipient = %prefs.fee_recipient, + gas_limit = prefs.gas_limit, + "Cached proposer preferences" + ); + self.prefs.write().insert(slot, prefs); + } + + pub fn get(&self, slot: u64) -> Option { + self.prefs.read().get(&slot).cloned() + } + + /// cleanup up preferences older than current_slot - max_age_slots. + pub fn cleanup(&self, current_slot: u64, max_age_slots: u64) { + let cutoff = current_slot.saturating_sub(max_age_slots); + self.prefs.write().retain(|&slot, _| slot >= cutoff); + } + + pub fn len(&self) -> usize { + self.prefs.read().len() + } + + pub fn is_empty(&self) -> bool { + self.prefs.read().is_empty() + } +} + +#[cfg(test)] +mod tests { + use super::*; + use alloy_primitives::Address; + + fn make_prefs(slot: u64) -> ProposerPreferences { + ProposerPreferences { + proposal_slot: slot, + validator_index: 42, + fee_recipient: Address::ZERO, + gas_limit: 30_000_000, + } + } + + #[test] + fn test_insert_and_get() { + let cache = ProposerPreferencesCache::new(); + cache.insert(make_prefs(100)); + assert!(cache.get(100).is_some()); + assert!(cache.get(101).is_none()); + } + + #[test] + fn test_cleanup() { + let cache = ProposerPreferencesCache::new(); + cache.insert(make_prefs(10)); + cache.insert(make_prefs(20)); + cache.insert(make_prefs(30)); + cache.cleanup(30, 15); + // slot 10 is < 30 - 15 = 15, should be removed + assert!(cache.get(10).is_none()); + assert!(cache.get(20).is_some()); + assert!(cache.get(30).is_some()); + } +} diff --git a/crates/rbuilder/src/live_builder/builder_api/p2p/reveal_handler.rs b/crates/rbuilder/src/live_builder/builder_api/p2p/reveal_handler.rs new file mode 100644 index 000000000..adcf64064 --- /dev/null +++ b/crates/rbuilder/src/live_builder/builder_api/p2p/reveal_handler.rs @@ -0,0 +1,125 @@ +use alloy_primitives::{BlockHash, B256}; +use parking_lot::RwLock; +use rbuilder_primitives::epbs::{CachedPayloadData, SignedExecutionPayloadBid}; +use std::{collections::HashMap, sync::Arc}; +use tracing::info; + +use crate::{beacon_api_client::Client, mev_boost::EpbsBidSigner}; + +/// Handles payload revelation after bid inclusion in a beacon block. +#[derive(Clone)] +pub struct RevealHandler { + /// Beacon api client for constructing and submitting envelopes. + beacon_client: Client, + /// Shared signer for envelope signing. + signer: Arc>>, + /// Shared payload cache from the bid provider, keyed by block_hash. + /// We key by block_hash (not slot) because we may submit multiple bids + /// per slot — the proposer can include any of them, and we need to + /// reveal the payload that backs the specific block_hash they picked. + payload_cache: Arc>>, +} + +impl RevealHandler { + pub fn new( + beacon_client: Client, + signer: Arc>>, + payload_cache: Arc>>, + ) -> Self { + Self { + beacon_client, + signer, + payload_cache, + } + } + + /// Called when a head event indicates our bid was included in a beacon block. + pub async fn on_bid_included( + &self, + slot: u64, + beacon_block_root: B256, + parent_beacon_block_root: B256, + included_bid: &SignedExecutionPayloadBid, + ) -> eyre::Result<()> { + let block_hash = included_bid.message.block_hash; + + info!( + slot, + ?block_hash, + ?beacon_block_root, + ?parent_beacon_block_root, + builder_index = included_bid.message.builder_index, + "Our bid was included, starting payload reveal" + ); + + // 1. look up the cached payload by the included bid's block_hash. + // The cache holds an entry for every block_hash we ever bid for, + // so even if the proposer included an earlier bid (not our latest), + // we still find the right payload here. Bounded growth is enforced + // by slot aware cleanup in the P2P main loop, not by overwriting on + // the same key. + let cached = self + .payload_cache + .read() + .get(&block_hash) + .cloned() + .ok_or_else(|| { + eyre::eyre!( + "No cached payload found for block_hash {:?} at slot {} \ + (likely the matching bid was generated before cleanup retention)", + block_hash, + slot + ) + })?; + + // 2. build envelope locally + let envelope = cached.build_envelope(beacon_block_root, parent_beacon_block_root); + + // 3. sign the envelope + let signed_envelope = { + let signer_guard = self.signer.read(); + let signer = signer_guard + .as_ref() + .ok_or_else(|| eyre::eyre!("Signer not initialized"))?; + signer.sign_envelope(&envelope)? + }; + + // Materialize raw blob bytes + cell proofs from the cached sidecars. + // This is the only place we actually pay the per-blob heap copy cost + let blobs = cached.blobs(); + let cell_proofs = cached.cell_proofs(); + + info!( + slot, + ?block_hash, + ?beacon_block_root, + blob_count = blobs.len(), + cell_proof_count = cell_proofs.len(), + "Submitting signed execution payload envelope" + ); + + // 4. submit to p2p via beacon api, including raw blobs and + // cell proofs so the beacon node can compute and broadcast + // DataColumnSidecars. Without these, peers fail data availability + // checks even though the envelope itself passes gossip validation. + self.beacon_client + .submit_execution_payload_envelope(&signed_envelope, &blobs, &cell_proofs) + .await?; + + info!( + slot, + ?block_hash, + "Successfully submitted execution payload envelope" + ); + + Ok(()) + } +} + +impl std::fmt::Debug for RevealHandler { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + f.debug_struct("RevealHandler") + .field("beacon_client", &self.beacon_client) + .finish() + } +} diff --git a/crates/rbuilder/src/live_builder/builder_api/p2p/scheduler.rs b/crates/rbuilder/src/live_builder/builder_api/p2p/scheduler.rs new file mode 100644 index 000000000..f6dbfe59a --- /dev/null +++ b/crates/rbuilder/src/live_builder/builder_api/p2p/scheduler.rs @@ -0,0 +1,190 @@ +use super::types::EpbsP2PConfig; +use std::time::{Duration, SystemTime, UNIX_EPOCH}; + +/// Manages bid timing within slots. +/// Manages time-based bid submission within slot boundaries. +/// Supports two modes: +/// interval mode: resubmit bids at regular intervals within the bidding window +/// single bid mode: submit once when payload is ready +#[derive(Debug, Clone)] +pub struct BidScheduler { + /// Genesis time in seconds since Unix epoch. + genesis_time: u64, + /// Slot duration in seconds. + seconds_per_slot: u64, + /// Ms relative to slot start when bidding opens (negative = before slot start). + bid_start_ms: i64, + /// Ms relative to slot start when bidding closes (typically positive). + bid_end_ms: i64, + /// Interval between bid resubmissions, 0 = single bid mode. + bid_interval_ms: u64, +} + +impl BidScheduler { + pub fn new(config: &EpbsP2PConfig) -> Self { + Self { + genesis_time: config.genesis_time, + seconds_per_slot: config.seconds_per_slot, + bid_start_ms: config.bid_start_ms, + bid_end_ms: config.bid_end_ms, + bid_interval_ms: config.bid_interval_ms, + } + } + + /// Returns the slot start time as seconds since unix epoch. + pub fn slot_start_time(&self, slot: u64) -> u64 { + self.genesis_time + slot * self.seconds_per_slot + } + + /// Returns ms relative to the start of the given slot. + /// Negative when wall-clock is before the slot starts; positive once the + /// slot has begun. Computed in i128 to avoid overflow on the subtraction + /// before truncating to i64 at the end. + pub fn ms_relative_to_slot(&self, slot: u64) -> i64 { + let now_ms = SystemTime::now() + .duration_since(UNIX_EPOCH) + .unwrap_or_default() + .as_millis() as i128; + let slot_start_ms = (self.slot_start_time(slot) as i128) * 1000; + (now_ms - slot_start_ms) as i64 + } + + /// Returns true if we are currently within the bidding window for the given slot. + /// Window: [bid_start_ms, bid_end_ms) relative to slot start. + pub fn is_in_bidding_window(&self, slot: u64) -> bool { + let rel = self.ms_relative_to_slot(slot); + rel >= self.bid_start_ms && rel < self.bid_end_ms + } + + /// Returns the duration until the bidding window opens for the given slot. + /// Returns Duration::ZERO if the window is already open. + /// Returns None if the bidding window has already closed. + pub fn time_until_bid_start(&self, slot: u64) -> Option { + let rel = self.ms_relative_to_slot(slot); + if rel >= self.bid_end_ms { + return None; + } + if rel >= self.bid_start_ms { + return Some(Duration::ZERO); + } + Some(Duration::from_millis((self.bid_start_ms - rel) as u64)) + } + + /// Returns the duration until the bidding window closes for the given slot. + /// Returns None if the window has already closed. + pub fn time_until_bid_end(&self, slot: u64) -> Option { + let rel = self.ms_relative_to_slot(slot); + if rel >= self.bid_end_ms { + return None; + } + let remaining = self.bid_end_ms - rel; + Some(Duration::from_millis(remaining.max(0) as u64)) + } + + /// Whether this scheduler is in single bid mode i.e no resubmission in the slot. + pub fn is_single_bid_mode(&self) -> bool { + self.bid_interval_ms == 0 + } + + /// Returns the bid resubmission interval or none in single bid mode. + pub fn bid_interval(&self) -> Option { + if self.bid_interval_ms == 0 { + None + } else { + Some(Duration::from_millis(self.bid_interval_ms)) + } + } + + /// Compute the current slot from wall clock time. + pub fn current_slot(&self) -> u64 { + let now = SystemTime::now() + .duration_since(UNIX_EPOCH) + .unwrap_or_default() + .as_secs(); + if now < self.genesis_time { + return 0; + } + (now - self.genesis_time) / self.seconds_per_slot + } +} + +#[cfg(test)] +mod tests { + use super::*; + + fn make_scheduler(genesis_time: u64) -> BidScheduler { + BidScheduler { + genesis_time, + seconds_per_slot: 12, + bid_start_ms: -1000, + bid_end_ms: 1000, + bid_interval_ms: 250, + } + } + + #[test] + fn test_slot_start_time() { + let s = make_scheduler(1_000_000); + assert_eq!(s.slot_start_time(0), 1_000_000); + assert_eq!(s.slot_start_time(1), 1_000_012); + assert_eq!(s.slot_start_time(100), 1_001_200); + } + + #[test] + fn test_single_bid_mode() { + let mut s = make_scheduler(0); + assert!(!s.is_single_bid_mode()); + s.bid_interval_ms = 0; + assert!(s.is_single_bid_mode()); + } + + #[test] + fn test_bid_interval() { + let s = make_scheduler(0); + assert_eq!(s.bid_interval(), Some(Duration::from_millis(250))); + } + + #[test] + fn test_ms_relative_to_slot_negative_pre_slot() { + // build a scheduler whose slot 1 starts ~1 hour in the future. The + // relative time for slot 1 should be a large negative number. + let now_secs = SystemTime::now() + .duration_since(UNIX_EPOCH) + .unwrap_or_default() + .as_secs(); + let s = make_scheduler(now_secs + 3600); + let rel = s.ms_relative_to_slot(0); + assert!(rel < 0, "expected negative rel, got {}", rel); + assert!(!s.is_in_bidding_window(0)); + } + + #[test] + fn test_ms_relative_to_slot_in_window() { + // set genesis to current second so slot 0 starts at the rounded down + // second of now. ms_relative_to_slot(0) then equals now_ms % 1000, + // which is in [0, 999] — always inside the [-1000, +1000) window. + let now_secs = SystemTime::now() + .duration_since(UNIX_EPOCH) + .unwrap_or_default() + .as_secs(); + let s = make_scheduler(now_secs); + let rel = s.ms_relative_to_slot(0); + assert!( + (0..1000).contains(&rel), + "expected rel in [0, 1000), got {}", + rel + ); + assert!(s.is_in_bidding_window(0)); + } + + #[test] + fn test_ms_relative_to_slot_post_window() { + // slot 0 started 5s ago rel is ~+5000, outside [-1000, +1000). + let now_secs = SystemTime::now() + .duration_since(UNIX_EPOCH) + .unwrap_or_default() + .as_secs(); + let s = make_scheduler(now_secs.saturating_sub(5)); + assert!(!s.is_in_bidding_window(0)); + } +} diff --git a/crates/rbuilder/src/live_builder/builder_api/p2p/service.rs b/crates/rbuilder/src/live_builder/builder_api/p2p/service.rs new file mode 100644 index 000000000..c6a1143d7 --- /dev/null +++ b/crates/rbuilder/src/live_builder/builder_api/p2p/service.rs @@ -0,0 +1,616 @@ +//! Main P2P ePBS builder service orchestrator. +//! +//! This service coordinates the full P2P builder flow: +//! 1. Subscribes to SSE events from the beacon node (head, bids, proposer preferences) +//! 2. Submits bids to the beacon node for P2P gossip on a schedule +//! 3. Monitors for bid inclusion in beacon blocks +//! 4. Triggers payload envelope revelation after bid inclusion + +use super::{ + bid_tracker::BidTracker, proposer_prefs::ProposerPreferencesCache, + reveal_handler::RevealHandler, scheduler::BidScheduler, types::EpbsP2PConfig, +}; +use crate::{ + beacon_api_client::{ + Client, ExecutionPayloadBidTopic, HeadEvent, HeadTopic, ProposerPreferencesTopic, + }, + live_builder::builder_api::{EpbsBidProvider, LiveEpbsBidProvider}, + mev_boost::EpbsBidSigner, +}; +use alloy_primitives::{BlockHash, B256}; +use futures::StreamExt; +use parking_lot::RwLock; +use rbuilder_primitives::epbs::{GetBidParams, SignedExecutionPayloadBid}; +use std::{collections::HashMap, sync::Arc}; +use tokio::sync::mpsc; +use tokio_util::sync::CancellationToken; +use tracing::{debug, error, info, warn}; + +/// Main p2p epbs builder service. +/// This service coordinates the full P2P builder flow: +/// Noting all the duties it currently takes care of +/// 1. Subscribes to SSE events from the beacon node (head, bids, proposer preferences) +/// 2. Submits bids to the beacon node for P2P gossip on a schedule +/// 3. Monitors for bid inclusion in beacon blocks +/// 4. Triggers payload envelope revelation after bid inclusion +pub struct EpbsP2PService { + config: EpbsP2PConfig, + beacon_client: Client, + bid_provider: Arc, + signer: Arc>>, + payload_cache: Arc>>, + /// Receiver for fresh block cached notifications from the bid provider. + /// Consumed by the main loop to fire bids the moment a block is ready, + /// bypassing the polling interval. + fresh_block_rx: tokio::sync::Mutex>>, +} + +impl EpbsP2PService { + pub fn new( + config: EpbsP2PConfig, + beacon_client: Client, + bid_provider: Arc, + signer: Arc>>, + payload_cache: Arc< + RwLock>, + >, + ) -> Self { + let fresh_block_rx = bid_provider.subscribe_fresh_blocks(); + Self { + config, + beacon_client, + bid_provider, + signer, + payload_cache, + fresh_block_rx: tokio::sync::Mutex::new(Some(fresh_block_rx)), + } + } + + /// Run the P2P builder service. + /// + /// This spawns SSE listener tasks and runs the main event loop until cancelled. + pub async fn run(self, cancel: CancellationToken) -> eyre::Result<()> { + info!("Starting EPBS P2P builder service"); + + loop { + if cancel.is_cancelled() { + return Ok(()); + } + if self.signer.read().is_some() { + break; + } + debug!("Waiting for EPBS signer initialization..."); + tokio::time::sleep(std::time::Duration::from_secs(2)).await; + } + + let builder_index = self + .signer + .read() + .as_ref() + .map(|s| s.builder_index()) + .unwrap_or(0); + + info!(builder_index, "EPBS P2P service signer ready"); + + let scheduler = BidScheduler::new(&self.config); + let bid_tracker = Arc::new(BidTracker::new(builder_index)); + let prefs_cache = Arc::new(ProposerPreferencesCache::new()); + let reveal_handler = RevealHandler::new( + self.beacon_client.clone(), + self.signer.clone(), + self.payload_cache.clone(), + ); + + // channel for head events from sse listener + // TODO: spinning unbounded channel for now. revist again. + let (head_tx, mut head_rx) = mpsc::unbounded_channel::(); + // channel for bid events from sse listener + // TODO: spinning unbounded channel for now. revist again. + let (bid_tx, mut bid_rx) = mpsc::unbounded_channel::(); + + // spawning the sse listeners for head and bids + let head_handle = { + let client = self.beacon_client.clone(); + let cancel = cancel.clone(); + let tx = head_tx; + tokio::spawn(async move { + Self::run_head_listener(client, tx, cancel).await; + }) + }; + + let bid_handle = { + let client = self.beacon_client.clone(); + let cancel = cancel.clone(); + let tx = bid_tx; + tokio::spawn(async move { + Self::run_bid_listener(client, tx, cancel).await; + }) + }; + + let prefs_handle = { + let client = self.beacon_client.clone(); + let cancel = cancel.clone(); + let cache = prefs_cache.clone(); + tokio::spawn(async move { + Self::run_prefs_listener(client, cache, cancel).await; + }) + }; + + // main event loop + let mut current_slot = scheduler.current_slot(); + let mut bid_interval = self.create_bid_interval(); + + let mut fresh_block_rx = self + .fresh_block_rx + .lock() + .await + .take() + .expect("fresh_block_rx initialized in EpbsP2PService::new"); + + info!(current_slot, "EPBS P2P service entering main loop"); + + loop { + tokio::select! { + _ = cancel.cancelled() => { + info!("EPBS P2P service shutting down"); + break; + } + + // head event recevied, check if our bid was included + Some(head_event) = head_rx.recv() => { + let new_slot = head_event.slot; + if new_slot > current_slot { + debug!(old_slot = current_slot, new_slot, "New slot detected"); + current_slot = new_slot; + bid_tracker.cleanup(current_slot); + //TODO keeping for 2 epochs think again about it. + prefs_cache.cleanup(current_slot, 64); + // we keep the most recent PAYLOAD_CACHE_RETENTION_SLOTS + // worth of entries, long enough to still reveal a + // bid that won a few slots ago, short enough to cap + // memory at PAYLOAD_CACHE_RETENTION_SLOTS × per-slot payload size. + const PAYLOAD_CACHE_RETENTION_SLOTS: u64 = 8; + let oldest_to_keep = current_slot + .saturating_sub(PAYLOAD_CACHE_RETENTION_SLOTS); + self.bid_provider.cleanup_older_than(oldest_to_keep); + } + + // check if our bid was included in this block + self.handle_head_event( + &head_event, + &bid_tracker, + &reveal_handler, + builder_index, + ).await; + } + + // competing bid received + Some(bid) = bid_rx.recv() => { + let is_new_highest = bid_tracker.on_bid_received(&bid); + if is_new_highest && bid.message.builder_index != builder_index { + debug!( + slot = bid.message.slot, + competing_value = bid.message.value, + competing_builder = bid.message.builder_index, + "Outbid by competing builder" + ); + } + } + + // submit/resubmit bid + _ = bid_interval.tick() => { + let next_slot = current_slot + 1; + let bid_slot = if scheduler.is_in_bidding_window(next_slot) { + Some(next_slot) + } else if scheduler.is_in_bidding_window(current_slot) { + Some(current_slot) + } else { + None + }; + + if let Some(slot) = bid_slot { + if let Err(e) = self.submit_bid( + slot, + &prefs_cache, + &bid_tracker, + ).await { + debug!(slot, error = %e, "Failed to submit bid"); + } + } + } + + Some(slot) = fresh_block_rx.recv() => { + if scheduler.is_in_bidding_window(slot) { + debug!(slot, "Fresh block ready and in window, submitting bid immediately"); + if let Err(e) = self.submit_bid( + slot, + &prefs_cache, + &bid_tracker, + ).await { + debug!(slot, error = %e, "Failed to submit fresh-block bid"); + } + } else { + let rel = scheduler.ms_relative_to_slot(slot); + debug!( + slot, + ms_relative_to_slot = rel, + "Fresh block ready but outside bid window; will be picked up by next interval tick" + ); + } + } + } + } + + // cleanup all + head_handle.abort(); + bid_handle.abort(); + prefs_handle.abort(); + + info!("EPBS P2P service stopped"); + Ok(()) + } + + /// Handle a head event by checking if our bid was included. + async fn handle_head_event( + &self, + head_event: &HeadEvent, + bid_tracker: &BidTracker, + reveal_handler: &RevealHandler, + builder_index: u64, + ) { + let slot = head_event.slot; + let block_root = head_event.block; + + let our_bid = bid_tracker.our_bid(slot); + + // query the beacon node to see which bid was included + let block_root_hex = format!("0x{}", hex::encode(block_root)); + match self + .beacon_client + .get_beacon_block_bid(&block_root_hex) + .await + { + Ok(Some(info)) => { + let included_bid = &info.bid; + let parent_beacon_block_root = info.parent_root; + // trigger the reveal whenever the included bid is ours. We may + // have submitted several bids per slot with different block hashes + // the payload cache is keyed by block hash, so the RevealHandler + // will look up he included bids block hash directly. + if included_bid.message.builder_index == builder_index { + if let Some(ref tracked) = our_bid { + if tracked.message.block_hash != included_bid.message.block_hash { + debug!( + slot, + included_block_hash = ?included_bid.message.block_hash, + latest_tracked_block_hash = ?tracked.message.block_hash, + "Proposer included one of our earlier bids (not our latest); revealing the included payload" + ); + } + } + info!( + slot, + ?block_root, + included_block_hash = ?included_bid.message.block_hash, + ?parent_beacon_block_root, + "Our bid was included in the beacon block, triggering reveal" + ); + + let reveal_handler = reveal_handler.clone(); + let included_bid = included_bid.clone(); + tokio::spawn(async move { + if let Err(e) = reveal_handler + .on_bid_included( + slot, + block_root, + parent_beacon_block_root, + &included_bid, + ) + .await + { + error!(slot, error = %e, "Failed to reveal payload"); + } + }); + } else { + debug!( + slot, + included_builder = included_bid.message.builder_index, + "Different builder's bid was included" + ); + } + } + Ok(None) => { + debug!(slot, "No bid found in beacon block body"); + } + Err(e) => { + warn!(slot, error = %e, "Failed to query beacon block for bid"); + } + } + } + + /// Generate and submit a bid for the given slot. + /// + /// if proposer preferences are available, uses them for fee_recipient and validates + /// the bid against them. If not available, falls back to using the payload's own + /// values, which come from the suggested_fee_recipient in payload attributes. + async fn submit_bid( + &self, + slot: u64, + prefs_cache: &ProposerPreferencesCache, + bid_tracker: &BidTracker, + ) -> eyre::Result<()> { + let prefs = prefs_cache.get(slot); + let has_prefs = prefs.is_some(); + + if !has_prefs { + debug!( + slot, + "No proposer preferences for slot, falling back to payload values" + ); + } + + // TODO: per consensus specs gloas/p2p-interface.md, `bid.fee_recipient` + // MUST equal `ProposerPreferences.fee_recipient` for the slot. The proposer + // signs and broadcasts these on the `proposer_preferences` + // Once we receive prefs reliably via the SSE stream this hardcoded + // fallback should be removed and bids should always use cached prefs. + const DEVNET_FALLBACK_FEE_RECIPIENT: alloy_primitives::Address = + alloy_primitives::address!("8943545177806ED17B9F23F0a21ee5948eCaa776"); + + let fee_recipient = prefs + .as_ref() + .map(|p| p.fee_recipient) + .unwrap_or(DEVNET_FALLBACK_FEE_RECIPIENT); + + let params = GetBidParams { + slot, + // bid provider uses the best cached blocks parent_hash + parent_hash: BlockHash::ZERO, // this will be overridden by providers cached data + // bid provider uses the cached parent_block_root captured from the + // payload_attributes event when the block was built + parent_root: B256::ZERO, + proposer_index: prefs.as_ref().map(|p| p.validator_index).unwrap_or(0), + fee_recipient, + timeout_ms: None, + date_milliseconds: None, + }; + + // generate bid via the bid provider + let signed_bid = self + .bid_provider + .generate_bid(¶ms) + .await? + .ok_or_else(|| eyre::eyre!("No bid available for slot {}", slot))?; + + // validate P2P gossip rules per consensus-specs p2p rules + // [REJECT] execution_payment must be 0 for P2P gossip + if signed_bid.message.execution_payment != 0 { + return Err(eyre::eyre!( + "Bid has non-zero execution_payment ({}), cannot broadcast via P2P", + signed_bid.message.execution_payment + )); + } + + // validate against proposer preferences only if available + if let Some(ref prefs) = prefs { + // [REJECT] fee_recipient must match proposer preferences + if signed_bid.message.fee_recipient != prefs.fee_recipient { + return Err(eyre::eyre!( + "Bid fee_recipient {:?} does not match proposer preferences {:?}", + signed_bid.message.fee_recipient, + prefs.fee_recipient + )); + } + + // [REJECT] gas_limit must match proposer preferences + if signed_bid.message.gas_limit != prefs.gas_limit { + return Err(eyre::eyre!( + "Bid gas_limit {} does not match proposer preferences {}", + signed_bid.message.gas_limit, + prefs.gas_limit + )); + } + } + + // [REJECT] blob_kzg_commitments length must not exceed MAX_BLOB_COMMITMENTS_PER_BLOCK + const MAX_BLOB_COMMITMENTS_PER_BLOCK: usize = 4096; + if signed_bid.message.blob_kzg_commitments.len() > MAX_BLOB_COMMITMENTS_PER_BLOCK { + return Err(eyre::eyre!( + "Bid has {} blob_kzg_commitments, exceeds max {}", + signed_bid.message.blob_kzg_commitments.len(), + MAX_BLOB_COMMITMENTS_PER_BLOCK + )); + } + + info!( + slot, + value = signed_bid.message.value, + block_hash = ?signed_bid.message.block_hash, + builder_index = signed_bid.message.builder_index, + "Submitting bid to beacon node for P2P gossip" + ); + + // submit to beacon node + self.beacon_client + .submit_execution_payload_bid(&signed_bid) + .await?; + + // keep track of our bid + bid_tracker.on_bid_submitted(&signed_bid); + + info!( + slot, + value = signed_bid.message.value, + "Bid submitted successfully" + ); + + Ok(()) + } + + /// Create the bid resubmission interval timer. + fn create_bid_interval(&self) -> tokio::time::Interval { + let interval_ms = if self.config.bid_interval_ms > 0 { + self.config.bid_interval_ms + } else { + // single bid mode: use a long interval, bids will be gated by the scheduler + 1000 + }; + let mut interval = tokio::time::interval(std::time::Duration::from_millis(interval_ms)); + interval.set_missed_tick_behavior(tokio::time::MissedTickBehavior::Skip); + interval + } + + /// SSE listener for head events. + async fn run_head_listener( + client: Client, + tx: mpsc::UnboundedSender, + cancel: CancellationToken, + ) { + loop { + if cancel.is_cancelled() { + return; + } + + match client.get_events::().await { + Ok(mut stream) => { + info!("Connected to beacon node head SSE stream"); + loop { + tokio::select! { + _ = cancel.cancelled() => return, + event = stream.next() => { + match event { + Some(Ok(head_event)) => { + if tx.send(head_event).is_err() { + return; // Receiver dropped + } + } + Some(Err(e)) => { + warn!(error = %e, "Error in head SSE stream"); + break; // Reconnect + } + None => { + warn!("Head SSE stream ended"); + break; // Reconnect + } + } + } + } + } + } + Err(e) => { + warn!(error = %e, "Failed to connect to head SSE stream"); + } + } + + // backoff before reconnecting + tokio::select! { + _ = cancel.cancelled() => return, + _ = tokio::time::sleep(std::time::Duration::from_secs(5)) => {} + } + } + } + + /// SSE listener for execution payload bid events. + async fn run_bid_listener( + client: Client, + tx: mpsc::UnboundedSender, + cancel: CancellationToken, + ) { + loop { + if cancel.is_cancelled() { + return; + } + + match client.get_events::().await { + Ok(mut stream) => { + info!("Connected to beacon node bid SSE stream"); + loop { + tokio::select! { + _ = cancel.cancelled() => return, + event = stream.next() => { + match event { + Some(Ok(bid)) => { + if tx.send(bid).is_err() { + return; + } + } + Some(Err(e)) => { + warn!(error = %e, "Error in bid SSE stream"); + break; + } + None => { + warn!("Bid SSE stream ended"); + break; + } + } + } + } + } + } + Err(e) => { + warn!(error = %e, "Failed to connect to bid SSE stream"); + } + } + + tokio::select! { + _ = cancel.cancelled() => return, + _ = tokio::time::sleep(std::time::Duration::from_secs(5)) => {} + } + } + } + + /// SSE listener for proposer preferences events. + async fn run_prefs_listener( + client: Client, + cache: Arc, + cancel: CancellationToken, + ) { + loop { + if cancel.is_cancelled() { + return; + } + + match client.get_events::().await { + Ok(mut stream) => { + info!("Connected to beacon node proposer preferences SSE stream"); + loop { + tokio::select! { + _ = cancel.cancelled() => return, + event = stream.next() => { + match event { + Some(Ok(prefs_event)) => { + cache.insert(prefs_event.data.message); + } + Some(Err(e)) => { + warn!(error = %e, "Error in proposer preferences SSE stream"); + break; + } + None => { + warn!("Proposer preferences SSE stream ended"); + break; + } + } + } + } + } + } + Err(e) => { + warn!(error = %e, "Failed to connect to proposer preferences SSE stream"); + } + } + + tokio::select! { + _ = cancel.cancelled() => return, + _ = tokio::time::sleep(std::time::Duration::from_secs(5)) => {} + } + } + } +} + +impl std::fmt::Debug for EpbsP2PService { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + f.debug_struct("EpbsP2PService") + .field("config", &self.config) + .finish() + } +} diff --git a/crates/rbuilder/src/live_builder/builder_api/p2p/types.rs b/crates/rbuilder/src/live_builder/builder_api/p2p/types.rs new file mode 100644 index 000000000..3a91efd30 --- /dev/null +++ b/crates/rbuilder/src/live_builder/builder_api/p2p/types.rs @@ -0,0 +1,61 @@ +use serde::Deserialize; + +/// config for the p2p epbs builder service. +#[derive(Debug, Clone)] +pub struct EpbsP2PConfig { + /// Whether P2P bid broadcasting is enabled. + pub enabled: bool, + /// Milliseconds relative to slot start when bidding opens. Negative = before + /// slot start. Bids gossiped before slot start land in proposer caches in + /// time for the slot start getBlock query. + pub bid_start_ms: i64, + /// Milliseconds relative to slot start when bidding closes. Typically positive + /// (some grace after slot start in case the proposer queries late). + pub bid_end_ms: i64, + /// Interval between bid resubmissions in ms. 0 = single bid mode. + pub bid_interval_ms: u64, + /// Value increment per resubmission in gwei. + pub bid_value_increment_gwei: u64, + /// subsidy added to `bid.value` to win the proposer's + /// "P2P bid > local EL value" comparison + /// TODO: Added for testing and will probably need to be removed + pub bid_value_subsidy_gwei: u64, + /// Genesis time from the beacon chain (seconds since unix epoch). + pub genesis_time: u64, + /// Slot duration in seconds (from beacon spec). + pub seconds_per_slot: u64, +} + +impl Default for EpbsP2PConfig { + fn default() -> Self { + Self { + enabled: false, + bid_start_ms: -1000, + bid_end_ms: 1000, + bid_interval_ms: 250, + bid_value_increment_gwei: 0, + bid_value_subsidy_gwei: 0, + genesis_time: 0, + seconds_per_slot: 12, + } + } +} + +/// event types used by the P2P service event loop. +#[derive(Debug, Clone)] +pub enum P2PEvent { + /// A new head was seen on the beacon chain. + NewHead(HeadEventData), + /// A competing bid was seen on the P2P network. + BidReceived(rbuilder_primitives::epbs::SignedExecutionPayloadBid), + /// Proposer preferences received from P2P gossip. + ProposerPreferences(rbuilder_primitives::epbs::SignedProposerPreferences), +} + +/// Extracted head event data relevant to the p2p builder. +#[derive(Debug, Clone, Deserialize)] +pub struct HeadEventData { + pub slot: u64, + pub block_root: alloy_primitives::B256, + pub state_root: alloy_primitives::B256, +} diff --git a/crates/rbuilder/src/live_builder/builder_api/server.rs b/crates/rbuilder/src/live_builder/builder_api/server.rs new file mode 100644 index 000000000..01ab718b1 --- /dev/null +++ b/crates/rbuilder/src/live_builder/builder_api/server.rs @@ -0,0 +1,166 @@ +//! EPBS Builder API HTTP Server. + +use alloy_primitives::BlockHash; +use axum::{routing::get, Router}; +use parking_lot::RwLock; +use rbuilder_primitives::epbs::{CachedPayloadData, GetBidParams, SignedExecutionPayloadBid}; +use std::{collections::HashMap, net::SocketAddr, sync::Arc, time::Duration}; +use tokio::net::TcpListener; +use tokio_util::sync::CancellationToken; +use tracing::info; + +use super::handlers::{get_execution_payload_bid_handler, status_handler}; + +#[derive(Debug, Clone)] +pub struct EpbsBuilderServerConfig { + /// server address + pub listen_addr: SocketAddr, + /// max age for cached payloads before they are evicted. + pub cache_ttl: Duration, +} + +impl Default for EpbsBuilderServerConfig { + fn default() -> Self { + Self { + listen_addr: "0.0.0.0:18551".parse().unwrap(), + cache_ttl: Duration::from_secs(32 * 12), // setting upto 2 epochs + } + } +} + +/// Trait for generating EPBS bids. +/// +/// This trait is implemented by the block builder to provide bids +/// to the EPBS Builder API server. +#[async_trait::async_trait] +pub trait EpbsBidProvider: Send + Sync { + /// generates the signed execution payload and returns it if no error encountered + /// returns none if no bid can be generated (e.g., unknown slot, no payload ready). + async fn generate_bid( + &self, + params: &GetBidParams, + ) -> eyre::Result>; +} + +/// State shared between the HTTP server and handlers. +pub struct EpbsBuilderState { + /// builder server config + pub config: EpbsBuilderServerConfig, + /// bid provider (block builder integration). + bid_provider: Arc, + /// cache the generated payloads, keyed by block_hash. + /// when a bid is returned, the full payload is cached here + /// so it can be revealed when the beacon block is seen. + payload_cache: RwLock>, +} + +impl std::fmt::Debug for EpbsBuilderState { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + f.debug_struct("EpbsBuilderState") + .field("config", &self.config) + .field("payload_cache_len", &self.payload_cache.read().len()) + .finish() + } +} + +impl EpbsBuilderState { + pub fn new(config: EpbsBuilderServerConfig, bid_provider: Arc) -> Self { + Self { + config, + bid_provider, + payload_cache: RwLock::new(HashMap::new()), + } + } + + /// Returns a signed execution payload bid given the bid params. + pub async fn get_execution_payload_bid( + &self, + params: &GetBidParams, + ) -> eyre::Result> { + self.bid_provider.generate_bid(params).await + } + + /// cache a payload for later revelation. + pub fn cache_payload(&self, data: CachedPayloadData) { + let block_hash = data.bid.message.block_hash; + self.payload_cache.write().insert(block_hash, data); + } + + pub fn get_cached_payload(&self, block_hash: &BlockHash) -> Option { + self.payload_cache.read().get(block_hash).cloned() + } + + pub fn cleanup_cache(&self) { + let ttl = self.config.cache_ttl; + self.payload_cache + .write() + .retain(|_, v| v.created_at.elapsed() < ttl); + } +} + +/// EPBS Builder API HTTP Server. +#[derive(Debug)] +pub struct EpbsBuilderServer { + state: Arc, +} + +impl EpbsBuilderServer { + pub fn new(config: EpbsBuilderServerConfig, bid_provider: Arc) -> Self { + Self { + state: Arc::new(EpbsBuilderState::new(config, bid_provider)), + } + } + + pub fn state(&self) -> Arc { + self.state.clone() + } + + /// Returns the listen address for this server. + pub fn listen_addr(&self) -> std::net::SocketAddr { + self.state.config.listen_addr + } + + fn build_router(&self) -> Router { + Router::new() + .route( + "/eth/v1/builder/execution_payload_bid/:slot/:parent_hash/:parent_root/:proposer_index", + get(get_execution_payload_bid_handler), + ) + .route("/eth/v1/builder/status", get(status_handler)) + .with_state(self.state.clone()) + } + + pub async fn run(self, cancel: CancellationToken) -> eyre::Result<()> { + let addr = self.state.config.listen_addr; + let router = self.build_router(); + + info!("starting builder server for epbs bids {}", addr); + + let listener = TcpListener::bind(addr).await?; + + // spawn cache cleanup task + let state_clone = self.state.clone(); + let cancel_clone = cancel.clone(); + tokio::spawn(async move { + let mut interval = tokio::time::interval(Duration::from_secs(60)); + loop { + tokio::select! { + _ = cancel_clone.cancelled() => break, + _ = interval.tick() => { + state_clone.cleanup_cache(); + } + } + } + }); + + // run the server + axum::serve(listener, router) + .with_graceful_shutdown(async move { + cancel.cancelled().await; + info!("shutting down builder server"); + }) + .await?; + + Ok(()) + } +} diff --git a/crates/rbuilder/src/live_builder/config.rs b/crates/rbuilder/src/live_builder/config.rs index b35be25d6..a3d83a107 100644 --- a/crates/rbuilder/src/live_builder/config.rs +++ b/crates/rbuilder/src/live_builder/config.rs @@ -7,10 +7,15 @@ use super::{ bidding_service_interface::{ BidObserver, BiddingService, LandedBlockInfo, NullBidObserver, }, + block_observer, relay_submit::{RelaySubmitSinkFactory, SubmissionConfig}, true_value_bidding_service::NewTrueBlockValueBiddingService, unfinished_block_processing::UnfinishedBuiltBlocksInputFactory, }, + builder_api::{ + EpbsBuilderServer, EpbsBuilderServerConfig, EpbsP2PService, LiveEpbsBidProvider, + LiveEpbsBidProviderConfig, + }, wallet_balance_watcher::WalletBalanceWatcher, }; use crate::{ @@ -37,11 +42,12 @@ use crate::{ relay_submit::OptimisticV3Config, }, cli::LiveBuilderConfig, - payload_events::MevBoostSlotDataGenerator, + payload_events::{MevBoostSlotDataGenerator, ParentNumberResolver}, }, mev_boost::{ bloxroute_grpc, optimistic_v3::{self, OptimisticV3BlockCache}, + sign_epbs::EpbsBidSigner, BLSBlockSigner, MevBoostRelayBidSubmitter, MevBoostRelaySlotInfoProvider, RelayClient, RelayConfig, RelaySubmitConfig, }, @@ -65,8 +71,8 @@ use reth_chainspec::{Chain, ChainSpec, NamedChain}; use reth_db::DatabaseEnv; use reth_node_api::NodeTypesWithDBAdapter; use reth_node_ethereum::EthereumNode; -use reth_primitives::StaticFileSegment; use reth_provider::StaticFileProviderFactory; +use reth_provider::StaticFileSegment; use serde::Deserialize; use serde_with::{serde_as, OneOrMany}; use std::{ @@ -94,6 +100,19 @@ pub const BID_SOURCE_TIMEOUT_SECS: u64 = 28; /// Don't want to waste too much time in case i failed to non-boost block. pub const BID_SOURCE_WAIT_TIME_SECS: u64 = 2; +pub const DEFAULT_EPBS_SERVER_PORT: u16 = 18551; + +/// Default for epbs_enabled - enabled by default. +/// Signing domain will be fetched from beacon chain in background if not configured +fn default_epbs_enabled() -> bool { + true +} + +/// Default EPBS server port +fn default_epbs_server_port() -> u16 { + DEFAULT_EPBS_SERVER_PORT +} + #[derive(Debug, Clone, Deserialize, PartialEq, Eq)] #[serde(tag = "algo", rename_all = "kebab-case", deny_unknown_fields)] pub enum SpecificBuilderConfig { @@ -216,6 +235,57 @@ pub struct L1Config { pub optimistic_v3_public_url: String, /// The relay pubkey. pub optimistic_v3_relay_pubkeys: HashSet, + + /// Enable EPBS Builder API server. + #[serde(default = "default_epbs_enabled")] + pub epbs_enabled: bool, + /// EPBS Builder API server IP. + #[serde(default = "default_ip")] + pub epbs_server_ip: Ipv4Addr, + /// EPBS Builder API server port. + #[serde(default = "default_epbs_server_port")] + pub epbs_server_port: u16, + /// Secret key for the builder's validator (for signing EPBS bids). + /// If not provided, relay_secret_key will be used. + epbs_builder_secret_key: Option>, + /// Signing domain for EPBS bids (32 bytes hex). + /// Computed from: DOMAIN_BEACON_BUILDER + fork_data_root + /// Can be set via env var: "$EPBS_SIGNING_DOMAIN" + epbs_signing_domain: Option>, + + /// Enable P2P ePBS builder (bid gossip via beacon node). + #[serde(default)] + pub epbs_p2p_enabled: bool, + /// Milliseconds relative to slot start when bidding opens (P2P mode). + /// Negative values mean before slot start, which is the recommended setting + /// so bids land in proposer caches before the slot start `getBlock` query. + #[serde(default = "default_epbs_p2p_bid_start_ms")] + pub epbs_p2p_bid_start_ms: i64, + /// Milliseconds relative to slot start when bidding closes (P2P mode). + #[serde(default = "default_epbs_p2p_bid_end_ms")] + pub epbs_p2p_bid_end_ms: i64, + /// Interval between bid resubmissions in ms (0 = single bid, P2P mode). + #[serde(default = "default_epbs_p2p_bid_interval_ms")] + pub epbs_p2p_bid_interval_ms: u64, + /// Value increment per resubmission in gwei (P2P mode). + #[serde(default)] + pub epbs_p2p_bid_value_increment_gwei: u64, + /// added for testing only for now, in prod probably dont need this + /// TODO: think how to remove it. + #[serde(default)] + pub epbs_p2p_bid_value_subsidy_gwei: u64, +} + +fn default_epbs_p2p_bid_start_ms() -> i64 { + -1000 +} + +fn default_epbs_p2p_bid_end_ms() -> i64 { + 1000 +} + +fn default_epbs_p2p_bid_interval_ms() -> u64 { + 250 } impl Default for L1Config { @@ -232,6 +302,19 @@ impl Default for L1Config { optimistic_v3_server_port: 6071, optimistic_v3_public_url: String::new(), optimistic_v3_relay_pubkeys: HashSet::default(), + // EPBS defaults - enabled by default for testing + epbs_enabled: true, + epbs_server_ip: default_ip(), + epbs_server_port: DEFAULT_EPBS_SERVER_PORT, + epbs_builder_secret_key: None, + epbs_signing_domain: None, + // EPBS P2P defaults - disabled by default + epbs_p2p_enabled: false, + epbs_p2p_bid_start_ms: default_epbs_p2p_bid_start_ms(), + epbs_p2p_bid_end_ms: default_epbs_p2p_bid_end_ms(), + epbs_p2p_bid_interval_ms: default_epbs_p2p_bid_interval_ms(), + epbs_p2p_bid_value_increment_gwei: 0, + epbs_p2p_bid_value_subsidy_gwei: 0, } } } @@ -251,6 +334,410 @@ impl L1Config { .collect() } + pub fn epbs_server_addr(&self) -> SocketAddr { + SocketAddr::V4(SocketAddrV4::new( + self.epbs_server_ip, + self.epbs_server_port, + )) + } + + /// Returns the EPBS builder secret key, falling back to relay_secret_key if not set. + pub fn epbs_secret_key(&self) -> eyre::Result> { + let key_str = if let Some(key) = &self.epbs_builder_secret_key { + Some(key.value()?) + } else if let Some(key) = &self.relay_secret_key { + Some(key.value()?) + } else { + None + }; + + match key_str { + Some(s) => { + let key = SecretKey::try_from(s) + .map_err(|e| eyre::eyre!("Failed to parse EPBS secret key: {:?}", e))?; + Ok(Some(key)) + } + None => Ok(None), + } + } + + /// Returns the EPBS signing domain from config/env if set. + /// + /// The signing domain should be computed as: + /// `DOMAIN_BEACON_BUILDER (4 bytes) + fork_data_root[0:28]` + /// + /// Can be configured via: + /// - Config file: `epbs_signing_domain = "0x..."` + /// - Environment variable: `epbs_signing_domain = "$EPBS_SIGNING_DOMAIN"` + /// + /// Returns None if not configured (will be fetched from beacon chain). + pub fn epbs_signing_domain(&self) -> eyre::Result> { + match &self.epbs_signing_domain { + Some(domain) => { + let domain_str = domain.value()?; + let domain_str = domain_str.strip_prefix("0x").unwrap_or(&domain_str); + let bytes = hex::decode(domain_str) + .map_err(|e| eyre::eyre!("Failed to decode EPBS signing domain: {}", e))?; + if bytes.len() != 32 { + return Err(eyre::eyre!( + "EPBS signing domain must be 32 bytes, got {}", + bytes.len() + )); + } + let mut arr = [0u8; 32]; + arr.copy_from_slice(&bytes); + Ok(Some(B256::from(arr))) + } + None => Ok(None), + } + } + + /// Create EPBS components if enabled. + /// + /// The builder_index and signing_domain are fetched from the beacon chain + /// in a background task, allowing the server to start immediately without blocking. + /// + /// Returns: + /// - The EPBS bid provider (also implements BlockObserver) + /// - The EPBS server (to be spawned) + /// - Optionally, the P2P service (if epbs_p2p_enabled) + /// + /// Returns None if EPBS is not enabled. + pub async fn create_epbs_components( + &self, + ) -> eyre::Result< + Option<( + Arc, + EpbsBuilderServer, + Option, + )>, + > { + use crate::mev_boost::sign_epbs::compute_epbs_domain; + + if !self.epbs_enabled { + info!("EPBS Builder API server is disabled"); + return Ok(None); + } + + info!( + listen_addr = %self.epbs_server_addr(), + "EPBS Builder API server is enabled" + ); + + let secret_key = self + .epbs_secret_key()? + .ok_or_else(|| eyre::eyre!("EPBS secret key is required when epbs_enabled is true"))?; + + // get pubkey for retreiving builder_index + let pubkey = secret_key.public_key(); + let pubkey_bytes = pubkey.as_ref().to_vec(); + + // Get signing domain from config (optional - will be fetched if not provided) + let signing_domain = self.epbs_signing_domain()?; + + let clients = self.beacon_clients()?; + if clients.is_empty() { + return Err(eyre::eyre!( + "No beacon chain clients configured. Set cl_node_url for EPBS." + )); + } + + // Create provider without signer - will be initialized in background + // after fetching builder_index and signing domain from beacon chain + info!("Will fetch builder_index and signing domain from beacon chain in background"); + let provider_config = LiveEpbsBidProviderConfig { + bid_value_subsidy_gwei: self.epbs_p2p_bid_value_subsidy_gwei, + ..LiveEpbsBidProviderConfig::default() + }; + if provider_config.bid_value_subsidy_gwei > 0 { + warn!( + subsidy_gwei = provider_config.bid_value_subsidy_gwei, + "EPBS bid-value subsidy is non-zero. This is a devnet/testing knob — \ + every bid will pay the proposer this much above the block's true value. \ + Set epbs_p2p_bid_value_subsidy_gwei=0 for production." + ); + } + let provider = Arc::new(LiveEpbsBidProvider::new_uninitialized(provider_config)); + + let p2p_beacon_client = clients.first().cloned(); + + // Spawn background task to fetch builder_index and signing domain, then initialize signer + let provider_clone = provider.clone(); + tokio::spawn(async move { + // retry indefinitely. Builder activation can take 25-30 min + // on mainnet, and if the beacon node goes down the signer should still + // come up when it's back. Better to log warnings than to give up. + const INITIAL_BACKOFF_MS: u64 = 1000; + const MAX_BACKOFF_MS: u64 = 10000; + + let mut last_error: Option = None; + let mut attempt: u32 = 0; + + loop { + attempt += 1; + + for client in &clients { + let (builder_index, deposit_epoch) = + match client.get_builder_entry_by_pubkey(&pubkey_bytes).await { + Ok(entry) => { + info!( + builder_index = entry.0, + deposit_epoch = entry.1, + "Found builder in beacon state builders registry" + ); + entry + } + Err(e) => { + tracing::warn!( + attempt, + beacon_endpoint = %client.endpoint(), + pubkey = hex::encode(&pubkey_bytes), + error = ?e, + "Failed to fetch builder index from beacon state" + ); + last_error = Some(e); + continue; + } + }; + + // a builder is `is_active_builder` only once its `deposit_epoch` + // has been finalized. Publishing bids before that fails + match client.get_finalized_epoch().await { + Ok(finalized_epoch) if finalized_epoch >= deposit_epoch => { + info!( + builder_index, + deposit_epoch, finalized_epoch, "Builder is finalized-active" + ); + } + Ok(finalized_epoch) => { + // builder is in the registry but its deposit_epoch + // hasnt finalized yet. Keep waiting.s. + if attempt % 10 == 1 { + info!( + attempt, + builder_index, + deposit_epoch, + finalized_epoch, + "Builder is registered but not yet active (waiting for deposit_epoch to finalize)" + ); + } else { + tracing::debug!( + attempt, + builder_index, + deposit_epoch, + finalized_epoch, + "Builder pending finalization" + ); + } + last_error = Some(eyre::eyre!( + "Builder not yet active: deposit_epoch={} > finalized_epoch={}", + deposit_epoch, + finalized_epoch + )); + continue; + } + Err(e) => { + tracing::warn!( + attempt, + beacon_endpoint = %client.endpoint(), + error = ?e, + "Failed to fetch finalized epoch" + ); + last_error = Some(e); + continue; + } + } + + // Get signing domain (from config or beacon chain) + let domain = if let Some(domain) = signing_domain { + info!("Using configured EPBS signing domain"); + domain + } else { + match client.get_genesis().await { + Ok(genesis) => { + let fork_version = match client.get_head_fork_version().await { + Ok(v) => { + info!(?v, "Using current head fork_version for EPBS signing domain"); + v + } + Err(e) => { + tracing::warn!( + error = ?e, + "Failed to fetch head fork version, falling back to genesis fork version" + ); + genesis.genesis_fork_version + } + }; + let domain = compute_epbs_domain( + fork_version, + genesis.genesis_validators_root, + ); + info!( + ?domain, + ?fork_version, + genesis_validators_root = ?genesis.genesis_validators_root, + "Computed EPBS signing domain from beacon chain" + ); + domain + } + Err(e) => { + last_error = Some(e); + continue; + } + } + }; + + // Create and set the signer + let signer = EpbsBidSigner::new(secret_key, builder_index, domain); + provider_clone.set_signer(signer); + info!( + builder_index, + "EPBS signer initialized, bid generation is now enabled" + ); + return; + } + + let backoff_exp = std::cmp::min(attempt.saturating_sub(1), 10); + let backoff_ms: u64 = + std::cmp::min(INITIAL_BACKOFF_MS * 2u64.pow(backoff_exp), MAX_BACKOFF_MS); + + // log at info level every 10 attempts to avoid log spam on long waits + // (e.g. waiting for builder deposit to activate on mainnet). + if attempt % 10 == 1 { + info!( + attempt, + backoff_ms, + error = ?last_error, + "Beacon client not ready, retrying in background..." + ); + } else { + tracing::debug!( + attempt, + backoff_ms, + "Beacon client not ready, retrying in background..." + ); + } + tokio::time::sleep(std::time::Duration::from_millis(backoff_ms)).await; + } + }); + + let server_config = EpbsBuilderServerConfig { + listen_addr: self.epbs_server_addr(), + ..Default::default() + }; + + // Create the server + let server = EpbsBuilderServer::new(server_config, provider.clone()); + + info!( + listen_addr = %self.epbs_server_addr(), + "EPBS Builder API server configured (waiting for beacon chain for builder_index)" + ); + + // Create P2P service if enabled + let p2p_service = if self.epbs_p2p_enabled { + use super::builder_api::p2p::EpbsP2PConfig; + + info!("EPBS P2P builder service is enabled"); + + let (genesis_time, seconds_per_slot) = if let Some(client) = p2p_beacon_client.as_ref() + { + let mut gt: Option = None; + let mut sps: Option = None; + let mut attempt: u32 = 0; + while gt.is_none() || sps.is_none() { + attempt += 1; + if gt.is_none() { + match client.get_genesis().await { + Ok(g) => gt = Some(g.genesis_time), + Err(e) => { + if attempt % 5 == 1 { + tracing::warn!( + attempt, + error = ?e, + "Failed to fetch genesis_time, retrying..." + ); + } else { + tracing::debug!( + attempt, + error = ?e, + "Failed to fetch genesis_time" + ); + } + } + } + } + if sps.is_none() { + match client.get_seconds_per_slot().await { + Ok(s) => sps = Some(s), + Err(e) => { + if attempt % 5 == 1 { + tracing::warn!( + attempt, + error = ?e, + "Failed to fetch SECONDS_PER_SLOT, retrying..." + ); + } else { + tracing::debug!( + attempt, + error = ?e, + "Failed to fetch SECONDS_PER_SLOT" + ); + } + } + } + } + if gt.is_some() && sps.is_some() { + break; + } + let backoff_secs = std::cmp::min(10, 1u64 << attempt.saturating_sub(1).min(4)); + tokio::time::sleep(std::time::Duration::from_secs(backoff_secs)).await; + } + // TODO clean/fix the defaults + let gt = gt.unwrap_or(0); + let sps = sps.unwrap_or(12); + info!( + genesis_time = gt, + seconds_per_slot = sps, + attempts = attempt, + "Fetched chain timing for EPBS P2P scheduler" + ); + (gt, sps) + } else { + // TODO clean/fix the defaults + (0, 12) + }; + + let p2p_config = EpbsP2PConfig { + enabled: true, + bid_start_ms: self.epbs_p2p_bid_start_ms, + bid_end_ms: self.epbs_p2p_bid_end_ms, + bid_interval_ms: self.epbs_p2p_bid_interval_ms, + bid_value_increment_gwei: self.epbs_p2p_bid_value_increment_gwei, + bid_value_subsidy_gwei: self.epbs_p2p_bid_value_subsidy_gwei, + genesis_time, + seconds_per_slot, + }; + + let beacon_client = p2p_beacon_client + .ok_or_else(|| eyre::eyre!("No beacon client available for P2P service"))?; + + let p2p_service = EpbsP2PService::new( + p2p_config, + beacon_client, + provider.clone(), + provider.shared_signer(), + provider.shared_payload_cache(), + ); + + Some(p2p_service) + } else { + None + }; + + Ok(Some((provider, server, p2p_service))) + } + /// Analyzes relay_config and creates MevBoostRelayBidSubmitter/MevBoostRelaySlotInfoProvider as needed. fn create_relay_sub_objects( relay_config: &RelayConfig, @@ -363,7 +850,7 @@ impl L1Config { } } } - if slot_info_providers.is_empty() { + if slot_info_providers.is_empty() && !self.epbs_p2p_enabled { return Err(eyre::eyre!("No relays enabled for getting slot info")); } Ok((submitters, slot_info_providers)) @@ -458,7 +945,7 @@ impl L1Config { ); let (submitters, slot_info_providers) = self.create_relays()?; - if slot_info_providers.is_empty() { + if slot_info_providers.is_empty() && !self.epbs_p2p_enabled { eyre::bail!("No slot info providers provided"); } @@ -510,6 +997,19 @@ impl LiveBuilderConfig for Config { let (wallet_balance_watcher, _) = create_wallet_balance_watcher(provider.clone(), &self.base_config).await?; + // Create EPBS components if enabled + let epbs_components = self.l1_config.create_epbs_components().await?; + let (block_observer, epbs_server, epbs_p2p_service): ( + Option>, + Option, + Option, + ) = match epbs_components { + Some((bid_provider, server, p2p_service)) => { + (Some(bid_provider), Some(server), p2p_service) + } + None => (None, None, None), + }; + let (sink_factory, slot_info_provider, adjustment_fee_payers) = create_sink_factory_and_relays( &self.base_config, @@ -519,10 +1019,11 @@ impl LiveBuilderConfig for Config { Box::new(NullBidObserver {}), bidding_service, cancellation_token.clone(), + block_observer, ) .await?; - let live_builder = create_builder_from_sink( + let mut live_builder = create_builder_from_sink( &self.base_config, &self.l1_config, provider, @@ -532,6 +1033,16 @@ impl LiveBuilderConfig for Config { cancellation_token, ) .await?; + + // Set EPBS server if enabled + if let Some(server) = epbs_server { + live_builder = live_builder.with_epbs_server(server); + } + // Set EPBS P2P service if enabled + if let Some(p2p_service) = epbs_p2p_service { + live_builder = live_builder.with_epbs_p2p_service(p2p_service); + } + let builders = create_builders( self.live_builders()?, self.base_config.max_order_execution_duration_warning(), @@ -753,8 +1264,16 @@ pub fn create_provider_factory( } }; - let provider_factory_reopener = - ProviderFactoryReopener::new(db, chain_spec, reth_static_files_path, root_hash_config)?; + let rocksdb_provider = reth_provider::providers::RocksDBProvider::new(&reth_db_path)?; + let runtime = reth_tasks::Runtime::test(); + let provider_factory_reopener = ProviderFactoryReopener::new( + db, + chain_spec, + reth_static_files_path, + root_hash_config, + rocksdb_provider, + runtime, + )?; if provider_factory_reopener .provider_factory_unchecked() @@ -1074,6 +1593,7 @@ where .await??) } +#[allow(clippy::too_many_arguments)] pub async fn create_sink_factory_and_relays

( base_config: &BaseConfig, l1_config: &L1Config, @@ -1082,6 +1602,7 @@ pub async fn create_sink_factory_and_relays

( bid_observer: Box, bidding_service: Arc, cancellation_token: CancellationToken, + block_observer: Option>, ) -> eyre::Result<( UnfinishedBuiltBlocksInputFactory

, Vec, @@ -1107,7 +1628,7 @@ where ); } - let sink_factory = UnfinishedBuiltBlocksInputFactory::new( + let mut sink_factory = UnfinishedBuiltBlocksInputFactory::new( bidding_service, sink_sealed_factory, wallet_balance_watcher, @@ -1115,6 +1636,11 @@ where relay_sets, ); + // Wire block observer for EPBS integration + if let Some(observer) = block_observer { + sink_factory = sink_factory.with_block_observer(observer); + } + Ok((sink_factory, slot_info_provider, adjustment_fee_payers)) } @@ -1129,12 +1655,23 @@ pub async fn create_builder_from_sink

( cancellation_token: CancellationToken, ) -> eyre::Result> where - P: StateProviderFactory, + P: StateProviderFactory + Clone + 'static, { let blocklist_provider = base_config .blocklist_provider(cancellation_token.clone()) .await?; + // TODO(prysm-buildoor-apis): resolver for the parent_block_number=0 + // workaround in MevBoostSlotDataGenerator. See ParentNumberResolver doc. + let provider_for_resolver = provider.clone(); + let parent_number_resolver: ParentNumberResolver = std::sync::Arc::new(move |hash| { + provider_for_resolver + .header(&hash) + .ok() + .flatten() + .map(|h| h.number) + }); + let payload_event = MevBoostSlotDataGenerator::new( l1_config.beacon_clients()?, slot_info_provider, @@ -1142,6 +1679,7 @@ where adjustment_fee_payers, blocklist_provider.clone(), cancellation_token.clone(), + Some(parent_number_resolver), ); base_config .create_builder_with_provider_factory( diff --git a/crates/rbuilder/src/live_builder/mod.rs b/crates/rbuilder/src/live_builder/mod.rs index bdcdd38f5..2f9b6b431 100644 --- a/crates/rbuilder/src/live_builder/mod.rs +++ b/crates/rbuilder/src/live_builder/mod.rs @@ -1,6 +1,7 @@ pub mod base_config; pub mod block_list_provider; pub mod block_output; +pub mod builder_api; pub mod building; pub mod cli; pub mod config; @@ -15,6 +16,7 @@ pub mod watchdog; use crate::{ building::{builders::BlockBuildingAlgorithm, BlockBuildingContext}, live_builder::{ + builder_api::EpbsBuilderServer, order_flow_tracing::order_flow_tracer_manager::OrderFlowTracerManager, order_input::{start_orderpool_jobs, OrderInputConfig}, process_killer::ProcessKiller, @@ -42,7 +44,8 @@ use reth::transaction_pool::{ TransactionPool, TransactionValidator, }; use reth_chainspec::ChainSpec; -use reth_primitives::{Recovered, TransactionSigned}; +use reth_ethereum_primitives::TransactionSigned; +use reth_primitives_traits::Recovered; use std::{ cmp::min, fmt::Debug, @@ -134,6 +137,15 @@ where pub simulation_use_random_coinbase: bool, pub order_flow_tracer_manager: Box, + + /// Optional EPBS Builder API server (EIP-7732). + /// When set, the server will be spawned alongside the builder. + pub epbs_server: Option, + + /// Optional EPBS P2P builder service. + /// When set, bids will be broadcast via p2p and payload envelopes + /// will be revealed after bid inclusion in beacon blocks. + pub epbs_p2p_service: Option, } impl

LiveBuilder

@@ -148,6 +160,28 @@ where Self { builders, ..self } } + /// Set the EPBS Builder API server. + /// + /// When set, the server will be spawned when `run()` is called and will + /// serve bids to proposers via the Builder API (EIP-7732). + pub fn with_epbs_server(self, server: EpbsBuilderServer) -> Self { + Self { + epbs_server: Some(server), + ..self + } + } + + /// Set the EPBS P2P builder service. + /// + /// When set, the service will be spawned when `run()` is called and will + /// broadcast bids via p2p gossip and reveal payloads after bid inclusion. + pub fn with_epbs_p2p_service(self, service: builder_api::EpbsP2PService) -> Self { + Self { + epbs_p2p_service: Some(service), + ..self + } + } + pub async fn run( self, ready_to_build: Arc, // If Some, we should send a message for every slot we start building. @@ -233,8 +267,75 @@ where self.order_flow_tracer_manager, ); + // Spawn EPBS Builder API server if configured + if let Some(epbs_server) = self.epbs_server { + let cancel = self.global_cancellation.clone(); + info!( + listen_addr = %epbs_server.listen_addr(), + "Starting EPBS Builder API server" + ); + inner_jobs_handles.push(tokio::spawn(async move { + if let Err(e) = epbs_server.run(cancel).await { + error!(?e, "EPBS Builder API server error"); + } + })); + } + + // Spawn epbs p2p builder service if configured + if let Some(p2p_service) = self.epbs_p2p_service { + let cancel = self.global_cancellation.clone(); + info!("Starting EPBS P2P builder service"); + inner_jobs_handles.push(tokio::spawn(async move { + if let Err(e) = p2p_service.run(cancel).await { + error!(?e, "EPBS P2P builder service error"); + } + })); + } + ready_to_build.store(true, Ordering::Relaxed); - while let Some(payload) = payload_events_channel.recv().await { + while let Some(mut payload) = payload_events_channel.recv().await { + // Fix A: Prysm's payload_attributes SSE wrapper adds + // `parent_block_number` as a convenience field. Pre-Gloas it carries the + // EL parent block number; post-Gloas it is often 0 because the previous + // slot's payload may be a pending builder bid that hasn't been revealed. + // The consensus-spec PayloadAttributes never had this field. + // + // Resolve the actual block number from the EL using `parent_block_hash` + // (which IS reliably populated). This matches buildoor's approach of + // letting the EL be the source of truth for block numbers. + // TODO: add proper fix for next local devnet testing + let parent_hash = payload.parent_block_hash(); + match self.provider.header(&parent_hash) { + Ok(Some(header)) => { + let resolved_number = header.number; + let attr_number = payload.payload_attributes_event.data.parent_block_number; + if attr_number != resolved_number { + debug!( + ?parent_hash, + attr_number, + resolved_number, + "Resolved parent_block_number from EL (Gloas/EPBS quirk)" + ); + payload.payload_attributes_event.data.parent_block_number = resolved_number; + } + } + Ok(None) => { + // parent not yet in our DB — keep whatever the sse event had. + // fail with a clearer error if needed. + debug!( + ?parent_hash, + "Parent header not found in EL while resolving parent_block_number" + ); + } + Err(e) => { + warn!( + ?parent_hash, + error = ?e, + "Failed to look up parent header for parent_block_number resolution" + ); + } + } + let blocklist = self.blocklist_provider.get_blocklist()?; if blocklist.contains(&payload.fee_recipient()) { warn!( diff --git a/crates/rbuilder/src/live_builder/order_input/txpool_fetcher.rs b/crates/rbuilder/src/live_builder/order_input/txpool_fetcher.rs index e62032df4..9e5dd45a9 100644 --- a/crates/rbuilder/src/live_builder/order_input/txpool_fetcher.rs +++ b/crates/rbuilder/src/live_builder/order_input/txpool_fetcher.rs @@ -156,14 +156,16 @@ mod test { let sidecar: SidecarBuilder = SidecarBuilder::from_slice("Blobs are fun!".as_bytes()); - let sidecar = sidecar.build().unwrap(); + let sidecar: alloy_eips::eip4844::BlobTransactionSidecar = sidecar.build().unwrap(); let gas_price = provider.get_gas_price().await.unwrap(); let eip1559_est = provider.estimate_eip1559_fees().await.unwrap(); let tx = TransactionRequest { max_fee_per_blob_gas: Some(gas_price), - sidecar: Some(sidecar), + sidecar: Some(alloy_eips::eip7594::BlobTransactionSidecarVariant::Eip4844( + sidecar, + )), ..TransactionRequest::default() .with_to(alice) .with_nonce(0) diff --git a/crates/rbuilder/src/live_builder/payload_events/mod.rs b/crates/rbuilder/src/live_builder/payload_events/mod.rs index e87ba47e1..085d46e64 100644 --- a/crates/rbuilder/src/live_builder/payload_events/mod.rs +++ b/crates/rbuilder/src/live_builder/payload_events/mod.rs @@ -33,6 +33,13 @@ use super::block_list_provider::BlockListProvider; const RECENTLY_SENT_EVENTS_BUFF: usize = 10; const NEW_PAYLOAD_RECV_TIMEOUT: Duration = SLOT_DURATION.saturating_mul(2); +// TODO(prysm-buildoor-apis): Remove this workaround once Prysm's +// `bharath-123-buildoor-apis` branch is patched to populate the SSE +// `payload_attributes` event's `parent_block_number` field correctly. Today +// it always reports "0" post-Gloas, which breaks rbuilder's state-root +// computation +pub type ParentNumberResolver = Arc Option + Send + Sync>; + /// If connection to the consensus client if broken we wait this time. /// One slot (12secs) is enough so we don't saturate any resource and we don't miss to many slots. const CONSENSUS_CLIENT_RECONNECT_WAIT: Duration = SLOT_DURATION; @@ -60,6 +67,10 @@ impl MevBoostSlotData { self.payload_attributes_event.data.parent_block_hash } + pub fn parent_block_root(&self) -> B256 { + self.payload_attributes_event.data.parent_block_root + } + pub fn parent_block_num_hash(&self) -> BlockNumHash { BlockNumHash::new( self.payload_attributes_event.data.parent_block_number, @@ -100,7 +111,8 @@ impl MevBoostSlotData { /// - Call MevBoostSlotDataGenerator::spawn. /// - Poll new slots via the returned UnboundedReceiver on spawn. /// - If join with spawned task is needed await on the JoinHandle returned by spawn. -#[derive(Debug)] +#[derive(derivative::Derivative)] +#[derivative(Debug)] pub struct MevBoostSlotDataGenerator { cls: Vec, relays: Vec, @@ -108,6 +120,9 @@ pub struct MevBoostSlotDataGenerator { adjustment_fee_payers: HashMap, blocklist_provider: Arc, global_cancellation: CancellationToken, + /// See [`ParentNumberResolver`]; `None` disables the workaround + #[derivative(Debug = "ignore")] + parent_number_resolver: Option, } impl MevBoostSlotDataGenerator { @@ -118,6 +133,7 @@ impl MevBoostSlotDataGenerator { adjustment_fee_payers: HashMap, blocklist_provider: Arc, global_cancellation: CancellationToken, + parent_number_resolver: Option, ) -> Self { Self { cls, @@ -126,6 +142,7 @@ impl MevBoostSlotDataGenerator { adjustment_fee_payers, blocklist_provider, global_cancellation, + parent_number_resolver, } } @@ -162,7 +179,7 @@ impl MevBoostSlotDataGenerator { let mut relays = relays; let mut recently_sent_data = VecDeque::with_capacity(RECENTLY_SENT_EVENTS_BUFF); - while let Some(event) = source.recv().await { + while let Some(mut event) = source.recv().await { if self.global_cancellation.is_cancelled() { return; } @@ -170,6 +187,27 @@ impl MevBoostSlotDataGenerator { let payload_id: InternalPayloadId = payload_counter; payload_counter += 1; + // TODO(prysm-buildoor-apis): see ParentNumberResolver. prysms + // `bharath-123-buildoor-apis` branch sends `parent_block_number=0` + // in post gloas ss events while keeping `parent_block_hash` + // valid. Recover the real number from the el to keep the + // (number, hash) pair internally consistent for state-root + // computation. + if event.data.parent_block_number == 0 && event.data.parent_block_hash != B256::ZERO + { + if let Some(resolver) = self.parent_number_resolver.as_ref() { + if let Some(real_number) = resolver(event.data.parent_block_hash) { + event.data.parent_block_number = real_number; + } else { + warn!( + payload_id, + parent_hash = ?event.data.parent_block_hash, + "SSE parent_block_number=0 but EL provider could not resolve it" + ); + } + } + } + let slot = event.data.proposal_slot; let block = event.data.parent_block_number + 1; let parent_hash = event.data.parent_block_hash; @@ -184,8 +222,37 @@ impl MevBoostSlotDataGenerator { "Payload attributes received from CL client" ); - let (slot_data, relay_registrations) = if let Some(res) = relays.slot_data(slot) { - res + let (slot_data, relay_registrations, correct_event) = if let Some((sd, rr)) = + relays.slot_data(slot) + { + let mut ev = event; + ev.data.payload_attributes.suggested_fee_recipient = sd.fee_recipient; + info!(payload_id, address = ?sd.fee_recipient, "Payload attributes correct fee recipient set from relay"); + (sd, rr, ev) + } else if self.relays.is_empty() { + // EPBS mode: no relays configured, use CL-provided payload attributes as is. + // The fee_recipient comes from the CL's suggested_fee_recipient (payload attributes), + // and gas_limit from the default block gas limit. + let fee_recipient = event.data.payload_attributes.suggested_fee_recipient; + info!( + payload_id, + ?fee_recipient, + "No relays configured, using CL payload attributes directly (EPBS mode)" + ); + // TODO: per consensus-specs gloas/p2p-interface.md + // `bid.gas_limit` MUST equal `ProposerPreferences.gas_limit` + // for the slot. Until we receive prefs reliably via SSE, + // hardcode the gas_limit Prysm validators actually sign + // for testing purpose i am currently setting 150_000_000, + // but it should be derived from the proposer preferences + // to pass the p2p validation. + let sd = SlotData { + fee_recipient, + gas_limit: 150_000_000, + pubkey: alloy_rpc_types_beacon::BlsPublicKey::ZERO, + }; + let rr = Arc::new(HashMap::default()); + (sd, rr, event) } else { info!( payload_id, @@ -195,20 +262,6 @@ impl MevBoostSlotDataGenerator { continue; }; - info!( - payload_id, - ?slot_data, - ?relay_registrations, - "Slot data from relays received" - ); - - let mut correct_event = event; - correct_event - .data - .payload_attributes - .suggested_fee_recipient = slot_data.fee_recipient; - info!(payload_id, address = ?slot_data.fee_recipient, "Payload attributes correct fee recipient set"); - let mev_boost_slot_data = MevBoostSlotData { payload_attributes_event: correct_event, suggested_gas_limit: slot_data.gas_limit, diff --git a/crates/rbuilder/src/live_builder/simulation/mod.rs b/crates/rbuilder/src/live_builder/simulation/mod.rs index 1dfa36514..45ed660e1 100644 --- a/crates/rbuilder/src/live_builder/simulation/mod.rs +++ b/crates/rbuilder/src/live_builder/simulation/mod.rs @@ -150,7 +150,7 @@ where return; } }; - NonceCache::new(state.into()) + NonceCache::new(Arc::new(crate::building::SyncStateProvider::new(state))) }; let sim_tree = SimTree::new(nonces); diff --git a/crates/rbuilder/src/live_builder/simulation/sim_worker.rs b/crates/rbuilder/src/live_builder/simulation/sim_worker.rs index 838ad3c6c..48e20a4c7 100644 --- a/crates/rbuilder/src/live_builder/simulation/sim_worker.rs +++ b/crates/rbuilder/src/live_builder/simulation/sim_worker.rs @@ -49,14 +49,15 @@ pub fn run_sim_worker

( let mut last_sim_finished = Instant::now(); - let state_provider = - match provider.history_by_block_hash(current_sim_context.block_ctx.attributes.parent) { - Ok(state_provider) => Arc::new(state_provider), - Err(err) => { - error!(?err, "Error while getting state for block"); - continue 'main; - } - }; + let state_provider = match provider + .history_by_block_hash(current_sim_context.block_ctx.attributes.parent) + { + Ok(state_provider) => Arc::new(crate::building::SyncStateProvider::new(state_provider)), + Err(err) => { + error!(?err, "Error while getting state for block"); + continue 'main; + } + }; while let Ok(task) = current_sim_context.requests.recv() { let sim_thread_wait_time = last_sim_finished.elapsed(); let sim_start = Instant::now(); diff --git a/crates/rbuilder/src/mev_boost/mod.rs b/crates/rbuilder/src/mev_boost/mod.rs index 1168f5f12..179a32cb7 100644 --- a/crates/rbuilder/src/mev_boost/mod.rs +++ b/crates/rbuilder/src/mev_boost/mod.rs @@ -28,8 +28,10 @@ mod error; pub mod fake_mev_boost_relay; pub mod optimistic_v3; pub mod rpc; +pub mod sign_epbs; pub mod sign_payload; pub use error::*; +pub use sign_epbs::*; pub use sign_payload::*; const TOTAL_PAYMENT_HEADER: &str = "Total-Payment"; diff --git a/crates/rbuilder/src/mev_boost/rpc.rs b/crates/rbuilder/src/mev_boost/rpc.rs index c4cbcde84..5665048de 100644 --- a/crates/rbuilder/src/mev_boost/rpc.rs +++ b/crates/rbuilder/src/mev_boost/rpc.rs @@ -102,6 +102,7 @@ impl TestDataGenerator { suggested_fee_recipient: self.create_address(), withdrawals: None, parent_beacon_block_root: Some(self.create_hash()), + slot_number: None, }, } } diff --git a/crates/rbuilder/src/mev_boost/sign_epbs.rs b/crates/rbuilder/src/mev_boost/sign_epbs.rs new file mode 100644 index 000000000..c70197e0a --- /dev/null +++ b/crates/rbuilder/src/mev_boost/sign_epbs.rs @@ -0,0 +1,320 @@ +//! EPBS bid and envelope signing for EIP-7732/Gloas. +//! +//! This module implements signing for ExecutionPayloadBid and ExecutionPayloadEnvelope +//! using the DOMAIN_BEACON_BUILDER domain as specified in the consensus specs. +//! +//! uses lh consensus types for ssz hash_tree_root computation + +use alloy_primitives::B256; +use alloy_rpc_types_beacon::BlsSignature; +use ethereum_consensus::crypto::SecretKey; +use lighthouse_bls::{PublicKeyBytes, SignatureBytes}; +use lighthouse_ssz_types::VariableList; +use lighthouse_types::{ + ConsolidationRequest, DepositRequest, ExecutionBlockHash, + ExecutionPayloadBid as LhExecutionPayloadBid, + ExecutionPayloadEnvelope as LhExecutionPayloadEnvelope, ExecutionPayloadGloas, + ExecutionRequests as LhExecutionRequests, Hash256, KzgCommitments, MainnetEthSpec, SignedRoot, + Slot, Withdrawal as LhWithdrawal, WithdrawalRequest, +}; +use rbuilder_primitives::epbs::{ + ExecutionPayloadBid, ExecutionPayloadEnvelope, SignedExecutionPayloadBid, + SignedExecutionPayloadEnvelope, +}; + +/// DOMAIN_BEACON_BUILDER from consensus-specs/specs/gloas/beacon-chain.md +/// Value: DomainType('0x0B000000') +pub const DOMAIN_BEACON_BUILDER: [u8; 4] = [0x0B, 0x00, 0x00, 0x00]; + +/// Signer for EPBS bids using the builder's validator key. +/// +/// uses DOMAIN_BEACON_BUILDER since the builder is now a staked +/// validator in the beacon chain. +#[derive(Debug, Clone)] +pub struct EpbsBidSigner { + /// Builder validator secret key. + sec: SecretKey, + /// The builders validator index in the beacon chain. + builder_index: u64, + /// Pre comp domain for signing (DOMAIN_BEACON_BUILDER + fork version + genesis validators root). + domain: B256, +} + +impl EpbsBidSigner { + /// Create a new EPBS bid signer. + pub fn new(sec: SecretKey, builder_index: u64, domain: B256) -> Self { + Self { + sec, + builder_index, + domain, + } + } + + /// Create from a hex-encoded secret key string. + pub fn from_string(secret_key: String, builder_index: u64, domain: B256) -> eyre::Result { + let secret_key = SecretKey::try_from(secret_key) + .map_err(|e| eyre::eyre!("Failed to parse key: {:?}", e.to_string()))?; + Ok(Self::new(secret_key, builder_index, domain)) + } + + /// Get the builder's validator index. + pub fn builder_index(&self) -> u64 { + self.builder_index + } + + /// Get the builder's public key. + pub fn pub_key(&self) -> alloy_rpc_types_beacon::BlsPublicKey { + alloy_rpc_types_beacon::BlsPublicKey::from_slice(&self.sec.public_key()) + } + + /// Sign an ExecutionPayloadBid using lh ssz types. + pub fn sign_bid(&self, bid: &ExecutionPayloadBid) -> eyre::Result { + let lh_bid = to_lh_bid(bid)?; + let signing_root = lh_bid.signing_root(self.domain); + let signature = self.sec.sign(signing_root.as_ref()); + let signature = BlsSignature::from_slice(&signature); + + Ok(SignedExecutionPayloadBid { + message: bid.clone(), + signature, + }) + } + + /// Sign an ExecutionPayloadEnvelope using Lighthouse's SSZ types. + pub fn sign_envelope( + &self, + envelope: &ExecutionPayloadEnvelope, + ) -> eyre::Result { + let lh_envelope = to_lh_envelope(envelope)?; + let signing_root = lh_envelope.signing_root(self.domain); + let signature = self.sec.sign(signing_root.as_ref()); + let signature = BlsSignature::from_slice(&signature); + + Ok(SignedExecutionPayloadEnvelope { + message: envelope.clone(), + signature, + }) + } +} + +// --------------------------------------------------------------------------- +// bid conversion: alloy types -> lh types +// --------------------------------------------------------------------------- + +fn to_lh_bid(bid: &ExecutionPayloadBid) -> eyre::Result> { + let commitments: Vec = bid + .blob_kzg_commitments + .iter() + .map(|c| { + let mut bytes = [0u8; 48]; + let len = c.len().min(48); + bytes[..len].copy_from_slice(&c[..len]); + lighthouse_types::KzgCommitment(bytes) + }) + .collect(); + let blob_kzg_commitments = KzgCommitments::::new(commitments) + .map_err(|e| eyre::eyre!("Too many blob KZG commitments: {:?}", e))?; + + Ok(LhExecutionPayloadBid { + parent_block_hash: ExecutionBlockHash::from_root(Hash256::from(bid.parent_block_hash)), + parent_block_root: Hash256::from(bid.parent_block_root), + block_hash: ExecutionBlockHash::from_root(Hash256::from(bid.block_hash)), + prev_randao: Hash256::from(bid.prev_randao), + fee_recipient: bid.fee_recipient, + gas_limit: bid.gas_limit, + builder_index: bid.builder_index, + slot: Slot::new(bid.slot), + value: bid.value, + execution_payment: bid.execution_payment, + blob_kzg_commitments, + execution_requests_root: Hash256::from(bid.execution_requests_root), + }) +} + +// --------------------------------------------------------------------------- +// envelope conversion: alloy types -> lh types +// --------------------------------------------------------------------------- + +fn to_lh_envelope( + envelope: &ExecutionPayloadEnvelope, +) -> eyre::Result> { + let payload = to_lh_execution_payload(envelope)?; + let execution_requests = to_lh_execution_requests(&envelope.execution_requests)?; + + Ok(LhExecutionPayloadEnvelope { + payload, + execution_requests, + builder_index: envelope.builder_index, + beacon_block_root: Hash256::from(envelope.beacon_block_root), + parent_beacon_block_root: Hash256::from(envelope.parent_beacon_block_root), + }) +} + +fn to_lh_execution_payload( + envelope: &ExecutionPayloadEnvelope, +) -> eyre::Result> { + let p = &envelope.payload; + + let transactions: Vec<_> = p + .transactions + .iter() + .map(|tx| { + VariableList::new(tx.to_vec()) + .map_err(|e| eyre::eyre!("Transaction too large: {:?}", e)) + }) + .collect::>>()?; + let transactions = VariableList::new(transactions) + .map_err(|e| eyre::eyre!("Too many transactions: {:?}", e))?; + + let withdrawals: Vec = p + .withdrawals + .iter() + .map(|w| LhWithdrawal { + index: w.index, + validator_index: w.validator_index, + address: w.address, + amount: w.amount, + }) + .collect(); + let withdrawals = + VariableList::new(withdrawals).map_err(|e| eyre::eyre!("Too many withdrawals: {:?}", e))?; + + let extra_data = VariableList::new(p.extra_data.to_vec()) + .map_err(|e| eyre::eyre!("Extra data too long: {:?}", e))?; + + let logs_bloom = lighthouse_ssz_types::FixedVector::new(p.logs_bloom.to_vec()) + .map_err(|e| eyre::eyre!("Invalid logs_bloom: {:?}", e))?; + + // glam-devnet-3 additions: block access list and the slot the payload is for. + let block_access_list = VariableList::new(p.block_access_list.to_vec()) + .map_err(|e| eyre::eyre!("Block access list too large: {:?}", e))?; + + Ok(ExecutionPayloadGloas { + parent_hash: ExecutionBlockHash::from_root(Hash256::from(p.parent_hash)), + fee_recipient: p.fee_recipient, + state_root: Hash256::from(p.state_root), + receipts_root: Hash256::from(p.receipts_root), + logs_bloom, + prev_randao: Hash256::from(p.prev_randao), + block_number: p.block_number, + gas_limit: p.gas_limit, + gas_used: p.gas_used, + timestamp: p.timestamp, + extra_data, + base_fee_per_gas: p.base_fee_per_gas, + block_hash: ExecutionBlockHash::from_root(Hash256::from(p.block_hash)), + transactions, + withdrawals, + blob_gas_used: p.blob_gas_used, + excess_blob_gas: p.excess_blob_gas, + block_access_list, + slot_number: Slot::new(p.slot_number), + }) +} + +fn to_lh_execution_requests( + requests: &rbuilder_primitives::epbs::ExecutionRequests, +) -> eyre::Result> { + let deposits: Vec = requests + .deposits + .iter() + .filter(|raw| raw.len() >= 192) + .map(|raw| { + Ok(DepositRequest { + pubkey: PublicKeyBytes::deserialize(&raw[0..48]) + .map_err(|e| eyre::eyre!("deposit pubkey: {:?}", e))?, + withdrawal_credentials: Hash256::from_slice(&raw[48..80]), + amount: u64::from_le_bytes(raw[80..88].try_into().unwrap()), + signature: SignatureBytes::deserialize(&raw[88..184]) + .map_err(|e| eyre::eyre!("deposit signature: {:?}", e))?, + index: u64::from_le_bytes(raw[184..192].try_into().unwrap()), + }) + }) + .collect::>>()?; + let deposits = VariableList::new(deposits) + .map_err(|e| eyre::eyre!("Too many deposit requests: {:?}", e))?; + + let withdrawals: Vec = requests + .withdrawals + .iter() + .filter(|raw| raw.len() >= 76) + .map(|raw| { + Ok(WithdrawalRequest { + source_address: alloy_primitives::Address::from_slice(&raw[0..20]), + validator_pubkey: PublicKeyBytes::deserialize(&raw[20..68]) + .map_err(|e| eyre::eyre!("withdrawal validator_pubkey: {:?}", e))?, + amount: u64::from_le_bytes(raw[68..76].try_into().unwrap()), + }) + }) + .collect::>>()?; + let withdrawals = VariableList::new(withdrawals) + .map_err(|e| eyre::eyre!("Too many withdrawal requests: {:?}", e))?; + + let consolidations: Vec = requests + .consolidations + .iter() + .filter(|raw| raw.len() >= 116) + .map(|raw| { + Ok(ConsolidationRequest { + source_address: alloy_primitives::Address::from_slice(&raw[0..20]), + source_pubkey: PublicKeyBytes::deserialize(&raw[20..68]) + .map_err(|e| eyre::eyre!("consolidation source_pubkey: {:?}", e))?, + target_pubkey: PublicKeyBytes::deserialize(&raw[68..116]) + .map_err(|e| eyre::eyre!("consolidation target_pubkey: {:?}", e))?, + }) + }) + .collect::>>()?; + let consolidations = VariableList::new(consolidations) + .map_err(|e| eyre::eyre!("Too many consolidation requests: {:?}", e))?; + + Ok(LhExecutionRequests { + deposits, + withdrawals, + consolidations, + }) +} + +pub fn execution_requests_root( + requests: &rbuilder_primitives::epbs::ExecutionRequests, +) -> eyre::Result { + use tree_hash::TreeHash; + let lh = to_lh_execution_requests(requests)?; + Ok(B256::from(lh.tree_hash_root())) +} + +// --------------------------------------------------------------------------- +// domain computation +// --------------------------------------------------------------------------- + +/// Compute the EPBS signing domain from beacon chain genesis data. +/// +/// The domain is computed following the consensus-specs: +/// ```python +/// domain = compute_domain(DOMAIN_BEACON_BUILDER, fork_version, genesis_validators_root) +/// ``` +pub fn compute_epbs_domain(fork_version: [u8; 4], genesis_validators_root: B256) -> B256 { + use ethereum_consensus::{ + phase0::beacon_state::ForkData, + primitives::{Root, Version}, + ssz::prelude::*, + }; + + let version = Version::try_from(fork_version.as_slice()).expect("fork_version is 4 bytes"); + let root = Root::try_from(genesis_validators_root.as_slice()).expect("root is 32 bytes"); + + let fork_data = ForkData { + current_version: version, + genesis_validators_root: root, + }; + + let fork_data_root = fork_data + .hash_tree_root() + .expect("ForkData hash_tree_root should not fail"); + + // construcrt domain: DOMAIN_BEACON_BUILDER || fork_data_root[:28] + let mut domain = [0u8; 32]; + domain[0..4].copy_from_slice(&DOMAIN_BEACON_BUILDER); + domain[4..32].copy_from_slice(&fork_data_root[..28]); + + B256::from(domain) +} diff --git a/crates/rbuilder/src/mev_boost/sign_payload.rs b/crates/rbuilder/src/mev_boost/sign_payload.rs index fcdff6346..725fa32a1 100644 --- a/crates/rbuilder/src/mev_boost/sign_payload.rs +++ b/crates/rbuilder/src/mev_boost/sign_payload.rs @@ -9,7 +9,9 @@ use ethereum_consensus::{ signing::sign_with_domain, ssz::prelude::*, }; -use reth_primitives::SealedBlock; +use reth_primitives_traits::SealedBlock; + +type EthSealedBlock = SealedBlock; use serde_with::{serde_as, DisplayFromStr}; /// Object to sign blocks to be sent to relays. @@ -101,7 +103,7 @@ fn a2e_address(a: &Address) -> ExecutionAddress { pub fn sign_block_for_relay( signer: &BLSBlockSigner, - sealed_block: &SealedBlock, + sealed_block: &EthSealedBlock, attrs: &PayloadAttributesData, proposer_pubkey: BlsPublicKey, value: U256, diff --git a/crates/rbuilder/src/provider/ipc_state_provider.rs b/crates/rbuilder/src/provider/ipc_state_provider.rs index 8215ffa83..c22d276f9 100644 --- a/crates/rbuilder/src/provider/ipc_state_provider.rs +++ b/crates/rbuilder/src/provider/ipc_state_provider.rs @@ -16,14 +16,14 @@ use dashmap::DashMap; use quick_cache::sync::Cache; use reipc::rpc_provider::RpcProvider; use reth_errors::{ProviderError, ProviderResult}; -use reth_primitives::{Account, Bytecode}; +use reth_primitives_traits::{Account, Bytecode}; use reth_provider::{ errors::any::AnyError, AccountReader, BlockHashReader, BytecodeReader, HashedPostStateProvider, StateProofProvider, StateProvider, StateProviderBox, StateRootProvider, StorageRootProvider, }; use reth_trie::{ - updates::TrieUpdates, AccountProof, HashedPostState, HashedStorage, MultiProof, - MultiProofTargets, StorageMultiProof, StorageProof, TrieInput, + updates::TrieUpdates, AccountProof, ExecutionWitnessMode, HashedPostState, HashedStorage, + MultiProof, MultiProofTargets, StorageMultiProof, StorageProof, TrieInput, }; use revm::{ database::{BundleAccount, BundleState}, @@ -419,7 +419,12 @@ impl StateProofProvider for IpcStateProvider { unimplemented!() } - fn witness(&self, _input: TrieInput, _target: HashedPostState) -> ProviderResult> { + fn witness( + &self, + _input: TrieInput, + _target: HashedPostState, + _mode: ExecutionWitnessMode, + ) -> ProviderResult> { unimplemented!() } } diff --git a/crates/rbuilder/src/provider/reth_prov.rs b/crates/rbuilder/src/provider/reth_prov.rs index c3ed1c270..a75c49e43 100644 --- a/crates/rbuilder/src/provider/reth_prov.rs +++ b/crates/rbuilder/src/provider/reth_prov.rs @@ -5,7 +5,7 @@ use alloy_primitives::{BlockHash, BlockNumber, B256}; use reth_errors::ProviderResult; use reth_provider::{ BlockReader, DatabaseProviderFactory, HeaderProvider, PruneCheckpointReader, - StageCheckpointReader, StateProviderBox, TrieReader, + StageCheckpointReader, StateProviderBox, }; use tracing::error; @@ -30,7 +30,13 @@ impl

StateProviderFactoryFromRethProvider

{ impl

StateProviderFactory for StateProviderFactoryFromRethProvider

where P: DatabaseProviderFactory< - Provider: BlockReader + TrieReader + StageCheckpointReader + PruneCheckpointReader, + Provider: BlockReader + + StageCheckpointReader + + PruneCheckpointReader + + reth_provider::BlockNumReader + + reth_provider::ChangeSetReader + + reth_provider::StorageChangeSetReader + + reth_provider::StorageSettingsCache, > + reth_provider::StateProviderFactory + HeaderProvider

+ Clone @@ -69,7 +75,9 @@ where } fn root_hasher(&self, parent_num_hash: BlockNumHash) -> ProviderResult> { - let hasher = self.history_by_block_hash(parent_num_hash.hash)?; + let hasher = crate::building::SyncStateProvider::new( + self.history_by_block_hash(parent_num_hash.hash)?, + ); let parent_state_root = self .provider .header_by_hash_or_number(parent_num_hash.hash.into())? diff --git a/crates/rbuilder/src/roothash/mod.rs b/crates/rbuilder/src/roothash/mod.rs index e4db93915..5254914a7 100644 --- a/crates/rbuilder/src/roothash/mod.rs +++ b/crates/rbuilder/src/roothash/mod.rs @@ -5,7 +5,7 @@ use eth_sparse_mpt::*; use reth::providers::providers::ConsistentDbView; use reth_provider::{ providers::OverlayStateProviderFactory, BlockReader, DatabaseProviderFactory, - HashedPostStateProvider, PruneCheckpointReader, StageCheckpointReader, TrieReader, + HashedPostStateProvider, PruneCheckpointReader, StageCheckpointReader, }; use reth_trie::TrieInput; use reth_trie_parallel::root::{ParallelStateRoot, ParallelStateRootError}; @@ -81,7 +81,13 @@ pub fn calculate_account_proofs

( ) -> Result>, RootHashError> where P: DatabaseProviderFactory< - Provider: BlockReader + TrieReader + StageCheckpointReader + PruneCheckpointReader, + Provider: BlockReader + + StageCheckpointReader + + PruneCheckpointReader + + reth_provider::BlockNumReader + + reth_provider::ChangeSetReader + + reth_provider::StorageChangeSetReader + + reth_provider::StorageSettingsCache, > + Send + Sync + Clone @@ -119,21 +125,31 @@ fn calculate_parallel_root_hash( provider: P, ) -> Result where - HasherType: HashedPostStateProvider, + HasherType: HashedPostStateProvider + Send + Sync, P: DatabaseProviderFactory< - Provider: BlockReader + TrieReader + StageCheckpointReader + PruneCheckpointReader, + Provider: BlockReader + + StageCheckpointReader + + PruneCheckpointReader + + reth_provider::BlockNumReader + + reth_provider::ChangeSetReader + + reth_provider::StorageChangeSetReader + + reth_provider::StorageSettingsCache, > + Send + Sync + Clone + 'static, { - let overlay = OverlayStateProviderFactory::new(provider); + let overlay_builder = reth_provider::providers::OverlayBuilder::< + reth_ethereum_primitives::EthPrimitives, + >::new(B256::ZERO, reth_trie_db::ChangesetCache::new()); + let overlay = OverlayStateProviderFactory::new(provider, overlay_builder); let hashed_post_state = hasher.hashed_post_state(outcome); let parallel_root_calculator = ParallelStateRoot::new( overlay, TrieInput::from_state(hashed_post_state) .prefix_sets .freeze(), + reth_tasks::Runtime::test(), ); parallel_root_calculator.incremental_root() } @@ -150,9 +166,15 @@ pub fn calculate_state_root( config: &RootHashContext, ) -> Result where - HasherType: HashedPostStateProvider, + HasherType: HashedPostStateProvider + Send + Sync, P: DatabaseProviderFactory< - Provider: BlockReader + TrieReader + StageCheckpointReader + PruneCheckpointReader, + Provider: BlockReader + + StageCheckpointReader + + PruneCheckpointReader + + reth_provider::BlockNumReader + + reth_provider::ChangeSetReader + + reth_provider::StorageChangeSetReader + + reth_provider::StorageSettingsCache, > + Send + Sync + Clone diff --git a/crates/rbuilder/src/utils/mod.rs b/crates/rbuilder/src/utils/mod.rs index c9239b201..800988f82 100644 --- a/crates/rbuilder/src/utils/mod.rs +++ b/crates/rbuilder/src/utils/mod.rs @@ -142,9 +142,13 @@ pub fn gen_uid() -> u64 { pub fn default_cfg_env(chain_spec: &ChainSpec, block_timestamp: u64, block_number: u64) -> CfgEnv { let spec = revm_spec_by_timestamp_and_block_number(chain_spec, block_timestamp, block_number); - CfgEnv::new() + + // TODO: remove and handle this properly. Remove depreciated + #[allow(deprecated)] + let cfg = CfgEnv::new() .with_chain_id(chain_spec.chain().id()) - .with_spec(spec) + .with_spec(spec); + cfg } pub fn unix_timestamp_now() -> u64 { diff --git a/crates/rbuilder/src/utils/noncer.rs b/crates/rbuilder/src/utils/noncer.rs index 4234ff172..0d5629113 100644 --- a/crates/rbuilder/src/utils/noncer.rs +++ b/crates/rbuilder/src/utils/noncer.rs @@ -10,12 +10,12 @@ use std::sync::Arc; #[derivative(Debug)] pub struct NonceCache { #[derivative(Debug = "ignore")] - state: Arc, + state: Arc, cache: Arc>, } impl NonceCache { - pub fn new(state: Arc) -> Self { + pub fn new(state: Arc) -> Self { Self { state, cache: Arc::new(DashMap::default()), diff --git a/crates/rbuilder/src/utils/provider_factory_reopen.rs b/crates/rbuilder/src/utils/provider_factory_reopen.rs index dd756120c..3fb169243 100644 --- a/crates/rbuilder/src/utils/provider_factory_reopen.rs +++ b/crates/rbuilder/src/utils/provider_factory_reopen.rs @@ -18,10 +18,10 @@ use reth_db::DatabaseError; use reth_errors::{ProviderError, ProviderResult, RethResult}; use reth_node_api::{NodePrimitives, NodeTypesWithDB}; use reth_provider::{ - providers::{ProviderNodeTypes, StaticFileProvider}, + providers::{ProviderNodeTypes, RocksDBProvider, StaticFileProvider}, BlockNumReader, BlockReader, DatabaseProviderFactory, HashedPostStateProvider, HeaderProvider, - PruneCheckpointReader, StageCheckpointReader, StateProviderBox, StaticFileProviderFactory, - TrieReader, + PruneCheckpointReader, RocksDBProviderFactory, StageCheckpointReader, StateProviderBox, + StaticFileProviderFactory, }; use revm::database::BundleState; use std::{ops::DerefMut, path::PathBuf, sync::Arc}; @@ -42,6 +42,8 @@ pub struct ProviderFactoryReopener { testing_mode: bool, /// None ->No root hash (MockRootHasher) root_hash_config: Option, + rocksdb_provider: Option, + runtime: Option, } /// root_hash_config None -> MockRootHasher used @@ -51,12 +53,17 @@ impl ProviderFactoryReopener chain_spec: Arc, static_files_path: PathBuf, root_hash_config: Option, + rocksdb_provider: RocksDBProvider, + runtime: reth_tasks::Runtime, ) -> RethResult { let provider_factory = ProviderFactory::new( db, chain_spec.clone(), - StaticFileProvider::read_only(static_files_path.as_path(), true).unwrap(), - ); + StaticFileProvider::read_only(static_files_path.as_path()).unwrap(), + rocksdb_provider.clone(), + runtime.clone(), + ) + .map_err(|e| reth_errors::RethError::msg(e.to_string()))?; Ok(Self { provider_factory: Arc::new(Mutex::new(provider_factory)), @@ -64,6 +71,8 @@ impl ProviderFactoryReopener static_files_path, root_hash_config, testing_mode: false, + rocksdb_provider: Some(rocksdb_provider), + runtime: Some(runtime), }) } @@ -73,12 +82,15 @@ impl ProviderFactoryReopener ) -> RethResult { let chain_spec = provider_factory.chain_spec(); let static_files_path = provider_factory.static_file_provider().path().to_path_buf(); + let rocksdb_provider = provider_factory.rocksdb_provider(); Ok(Self { provider_factory: Arc::new(Mutex::new(provider_factory)), chain_spec, static_files_path, root_hash_config, testing_mode: true, + rocksdb_provider: Some(rocksdb_provider), + runtime: None, }) } @@ -108,12 +120,20 @@ impl ProviderFactoryReopener debug!(?err, "Provider factory is inconsistent, reopening"); inc_provider_reopen_counter(); - *provider_factory = ProviderFactory::new( - provider_factory.db_ref().clone(), - self.chain_spec.clone(), - StaticFileProvider::read_only(self.static_files_path.as_path(), true) - .unwrap(), - ); + if let (Some(rocksdb), Some(runtime)) = (&self.rocksdb_provider, &self.runtime) + { + *provider_factory = ProviderFactory::new( + provider_factory.db_ref().clone(), + self.chain_spec.clone(), + StaticFileProvider::read_only(self.static_files_path.as_path()) + .unwrap(), + rocksdb.clone(), + runtime.clone(), + ) + .unwrap(); + } else { + let _ = provider_factory.sync_providers_if_needed(); + } } } @@ -292,9 +312,15 @@ impl RootHasherImpl { impl RootHasher for RootHasherImpl where - HasherType: HashedPostStateProvider, + HasherType: HashedPostStateProvider + Send + Sync, T: DatabaseProviderFactory< - Provider: BlockReader + TrieReader + StageCheckpointReader + PruneCheckpointReader, + Provider: BlockReader + + StageCheckpointReader + + PruneCheckpointReader + + reth_provider::BlockNumReader + + reth_provider::ChangeSetReader + + reth_provider::StorageChangeSetReader + + reth_provider::StorageSettingsCache, > + Send + Sync + Clone diff --git a/crates/rbuilder/src/utils/receipts.rs b/crates/rbuilder/src/utils/receipts.rs index 13f151a1a..57579ae07 100644 --- a/crates/rbuilder/src/utils/receipts.rs +++ b/crates/rbuilder/src/utils/receipts.rs @@ -1,12 +1,12 @@ use ahash::HashMap; use alloy_consensus::ReceiptWithBloom; use alloy_eips::Encodable2718; +use alloy_primitives::Log; use alloy_primitives::{Bloom, Bytes, B256}; use alloy_trie::{proof::ProofRetainer, root::adjust_index_for_rlp, HashBuilder, Nibbles}; use eth_sparse_mpt::v2::trie::{proof_store::ProofStore, Trie}; use itertools::Itertools; -use reth::primitives::Receipt; -use reth_primitives::Log; +use reth_ethereum_primitives::Receipt; use crate::building::TransactionExecutionInfo; @@ -285,8 +285,8 @@ pub fn ordered_trie_root_and_proof(items: &[Bytes], proof_index: usize) -> (B256 mod tests { use alloy_consensus::{TxReceipt, TxType}; use alloy_primitives::{address, fixed_bytes}; + use alloy_primitives::{logs_bloom, Log, LogData}; use rbuilder_primitives::BlockSpace; - use reth_primitives::{logs_bloom, Log, LogData}; use crate::utils::test_utils::tx; diff --git a/crates/rbuilder/src/utils/test_utils.rs b/crates/rbuilder/src/utils/test_utils.rs index 80fb9cf2a..20fd6da6c 100644 --- a/crates/rbuilder/src/utils/test_utils.rs +++ b/crates/rbuilder/src/utils/test_utils.rs @@ -1,6 +1,7 @@ use alloy_primitives::{Address, Signature, B256, I256, U256}; use rbuilder_primitives::{OrderId, TransactionSignedEcRecoveredWithBlobs}; -use reth_primitives::{Recovered, Transaction, TransactionSigned}; +use reth_ethereum_primitives::{Transaction, TransactionSigned}; +use reth_primitives_traits::Recovered; pub fn order_id(id: u64) -> OrderId { OrderId::Tx(hash(id)) diff --git a/crates/rbuilder/src/utils/tx_signer.rs b/crates/rbuilder/src/utils/tx_signer.rs index 891ca5544..b453d39b8 100644 --- a/crates/rbuilder/src/utils/tx_signer.rs +++ b/crates/rbuilder/src/utils/tx_signer.rs @@ -1,7 +1,13 @@ use alloy_consensus::SignableTransaction; -use alloy_primitives::{Address, Signature, B256, U256}; -use reth_primitives::{public_key_to_address, Recovered, Transaction, TransactionSigned}; -use secp256k1::{Message, SecretKey, SECP256K1}; +use alloy_primitives::{keccak256, Address, Signature, B256, U256}; +use reth_ethereum_primitives::{Transaction, TransactionSigned}; +use reth_primitives_traits::Recovered; +use secp256k1::{Message, PublicKey, SecretKey, SECP256K1}; + +fn public_key_to_address(pubkey: PublicKey) -> Address { + let hash = keccak256(&pubkey.serialize_uncompressed()[1..]); + Address::from_slice(&hash[12..]) +} /// Simple struct to sign txs/messages. /// Mainly used to sign payout txs from the builder and to create test data. diff --git a/crates/reth-rbuilder/src/main.rs b/crates/reth-rbuilder/src/main.rs index 999a1ba78..aa3725f46 100644 --- a/crates/reth-rbuilder/src/main.rs +++ b/crates/reth-rbuilder/src/main.rs @@ -23,7 +23,7 @@ use reth::{ use reth_node_ethereum::{node::EthereumAddOns, EthereumNode}; use reth_provider::{ providers::BlockchainProvider, BlockReader, ChainSpecProvider, DatabaseProviderFactory, - HeaderProvider, PruneCheckpointReader, StageCheckpointReader, TrieReader, + HeaderProvider, PruneCheckpointReader, StageCheckpointReader, }; use reth_transaction_pool::{blobstore::DiskFileBlobStore, EthTransactionPool}; use std::{ @@ -88,7 +88,13 @@ fn spawn_rbuilder

( config_path: PathBuf, ) where P: DatabaseProviderFactory< - Provider: BlockReader + TrieReader + StageCheckpointReader + PruneCheckpointReader, + Provider: BlockReader + + StageCheckpointReader + + PruneCheckpointReader + + reth_provider::ChangeSetReader + + reth_provider::StorageChangeSetReader + + reth_provider::StorageSettingsCache + + reth_provider::BlockNumReader, > + reth_provider::StateProviderFactory + HeaderProvider

+ reth_provider::ChainSpecProvider diff --git a/crates/test-relay/src/relay.rs b/crates/test-relay/src/relay.rs index 62c48a041..703865e0b 100644 --- a/crates/test-relay/src/relay.rs +++ b/crates/test-relay/src/relay.rs @@ -336,6 +336,7 @@ fn spawn_mev_boost_slot_data_generator( Default::default(), Arc::new(NullBlockListProvider::default()), cancellation_token.clone(), + None, ); let (_, slot_data_generator) = slot_data_generator.spawn(); diff --git a/docker/Dockerfile.rbuilder b/docker/Dockerfile.rbuilder index 20a8b9996..eddee1b73 100644 --- a/docker/Dockerfile.rbuilder +++ b/docker/Dockerfile.rbuilder @@ -9,7 +9,7 @@ ARG FEATURES ARG RBUILDER_BIN="rbuilder" -FROM rust:1.89-bookworm AS base +FROM rust:1.93-bookworm AS base ARG TARGETPLATFORM RUN apt-get update \