diff --git a/bolt-sidecar/Cargo.lock b/bolt-sidecar/Cargo.lock index ebedf941..b1649a0c 100644 --- a/bolt-sidecar/Cargo.lock +++ b/bolt-sidecar/Cargo.lock @@ -120,9 +120,9 @@ dependencies = [ [[package]] name = "allocator-api2" -version = "0.2.20" +version = "0.2.21" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "45862d1c77f2228b9e10bc609d5bc203d86ebc9b87ad8d5d5167a6c9abf739d9" +checksum = "683d7910e743518b0e34f1186f92494becacb047c7b6bf616c96772180fef923" [[package]] name = "alloy" @@ -147,32 +147,32 @@ version = "0.7.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "02b0561294ccedc6181e5528b850b4579e3fbde696507baa00109bfd9054c5bb" dependencies = [ - "alloy-consensus 0.7.2", + "alloy-consensus 0.7.3", "alloy-contract", - "alloy-core 0.8.12", - "alloy-eips 0.7.2", - "alloy-genesis 0.7.2", - "alloy-network 0.7.2", - "alloy-provider 0.7.2", + "alloy-core 0.8.14", + "alloy-eips 0.7.3", + "alloy-genesis 0.7.3", + "alloy-network 0.7.3", + "alloy-provider 0.7.3", "alloy-pubsub", - "alloy-rpc-client 0.7.2", - "alloy-rpc-types 0.7.2", - "alloy-serde 0.7.2", - "alloy-signer 0.7.2", + "alloy-rpc-client 0.7.3", + "alloy-rpc-types 0.7.3", + "alloy-serde 0.7.3", + "alloy-signer 0.7.3", "alloy-signer-local", - "alloy-transport 0.7.2", - "alloy-transport-http 0.7.2", + "alloy-transport 0.7.3", + "alloy-transport-http 0.7.3", "alloy-transport-ipc", "alloy-transport-ws", ] [[package]] name = "alloy-chains" -version = "0.1.47" +version = "0.1.48" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "18c5c520273946ecf715c0010b4e3503d7eba9893cd9ce6b7fff5654c4a3c470" +checksum = "a0161082e0edd9013d23083465cc04b20e44b7a15646d36ba7b0cdb7cd6fe18f" dependencies = [ - "alloy-primitives 0.8.12", + "alloy-primitives 0.8.14", "num_enum", "serde", "strum", @@ -194,14 +194,14 @@ dependencies = [ [[package]] name = "alloy-consensus" -version = "0.7.2" +version = "0.7.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "73dd0ab7003dfa3efd252e423873cd3bc241d1456147e752f995cc8aabd1d1f6" +checksum = "a101d4d016f47f13890a74290fdd17b05dd175191d9337bc600791fb96e4dea8" dependencies = [ - "alloy-eips 0.7.2", - "alloy-primitives 0.8.12", + "alloy-eips 0.7.3", + "alloy-primitives 0.8.14", "alloy-rlp", - "alloy-serde 0.7.2", + "alloy-serde 0.7.3", "alloy-trie", "auto_impl", "c-kzg", @@ -212,37 +212,37 @@ dependencies = [ [[package]] name = "alloy-consensus-any" -version = "0.7.2" +version = "0.7.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d08234c0eece0e08602db5095a16dc942cad91967cccfcfc2c6a42c25563964f" +checksum = "fa60357dda9a3d0f738f18844bd6d0f4a5924cc5cf00bfad2ff1369897966123" dependencies = [ - "alloy-consensus 0.7.2", - "alloy-eips 0.7.2", - "alloy-primitives 0.8.12", + "alloy-consensus 0.7.3", + "alloy-eips 0.7.3", + "alloy-primitives 0.8.14", "alloy-rlp", - "alloy-serde 0.7.2", + "alloy-serde 0.7.3", "serde", ] [[package]] name = "alloy-contract" -version = "0.7.2" +version = "0.7.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6a01f5593f6878452c6dde102ece391b60cba79801c5f606f8fe898ff57cd5d7" +checksum = "2869e4fb31331d3b8c58c7db567d1e4e4e94ef64640beda3b6dd9b7045690941" dependencies = [ - "alloy-dyn-abi 0.8.12", - "alloy-json-abi 0.8.12", - "alloy-network 0.7.2", - "alloy-network-primitives 0.7.2", - "alloy-primitives 0.8.12", - "alloy-provider 0.7.2", + "alloy-dyn-abi 0.8.14", + "alloy-json-abi 0.8.14", + "alloy-network 0.7.3", + "alloy-network-primitives 0.7.3", + "alloy-primitives 0.8.14", + "alloy-provider 0.7.3", "alloy-pubsub", - "alloy-rpc-types-eth 0.7.2", - "alloy-sol-types 0.8.12", - "alloy-transport 0.7.2", + "alloy-rpc-types-eth 0.7.3", + "alloy-sol-types 0.8.14", + "alloy-transport 0.7.3", "futures", "futures-util", - "thiserror 2.0.3", + "thiserror 2.0.6", ] [[package]] @@ -259,15 +259,15 @@ dependencies = [ [[package]] name = "alloy-core" -version = "0.8.12" +version = "0.8.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9c8316d83e590f4163b221b8180008f302bda5cf5451202855cdd323e588849c" +checksum = "c3d14d531c99995de71558e8e2206c27d709559ee8e5a0452b965ea82405a013" dependencies = [ - "alloy-dyn-abi 0.8.12", - "alloy-json-abi 0.8.12", - "alloy-primitives 0.8.12", + "alloy-dyn-abi 0.8.14", + "alloy-json-abi 0.8.14", + "alloy-primitives 0.8.14", "alloy-rlp", - "alloy-sol-types 0.8.12", + "alloy-sol-types 0.8.14", ] [[package]] @@ -289,14 +289,14 @@ dependencies = [ [[package]] name = "alloy-dyn-abi" -version = "0.8.12" +version = "0.8.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ef2364c782a245cf8725ea6dbfca5f530162702b5d685992ea03ce64529136cc" +checksum = "80759b3f57b3b20fa7cd8fef6479930fc95461b58ff8adea6e87e618449c8a1d" dependencies = [ - "alloy-json-abi 0.8.12", - "alloy-primitives 0.8.12", - "alloy-sol-type-parser 0.8.12", - "alloy-sol-types 0.8.12", + "alloy-json-abi 0.8.14", + "alloy-primitives 0.8.14", + "alloy-sol-type-parser 0.8.14", + "alloy-sol-types 0.8.14", "const-hex", "itoa", "serde", @@ -310,18 +310,18 @@ version = "0.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0069cf0642457f87a01a014f6dc29d5d893cd4fd8fddf0c3cdfad1bb3ebafc41" dependencies = [ - "alloy-primitives 0.8.12", + "alloy-primitives 0.8.14", "alloy-rlp", "serde", ] [[package]] name = "alloy-eip7702" -version = "0.4.1" +version = "0.4.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5f6cee6a35793f3db8a5ffe60e86c695f321d081a567211245f503e8c498fce8" +checksum = "4c986539255fb839d1533c128e190e557e52ff652c9ef62939e233a81dd93f7e" dependencies = [ - "alloy-primitives 0.8.12", + "alloy-primitives 0.8.14", "alloy-rlp", "derive_more 1.0.0", "k256 0.13.4", @@ -347,15 +347,15 @@ dependencies = [ [[package]] name = "alloy-eips" -version = "0.7.2" +version = "0.7.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "50c242de43a1869bcb2fbce3b377130959d10dfd562b87ac7aa2f04d98baac51" +checksum = "8b6755b093afef5925f25079dd5a7c8d096398b804ba60cb5275397b06b31689" dependencies = [ "alloy-eip2930", "alloy-eip7702", - "alloy-primitives 0.8.12", + "alloy-primitives 0.8.14", "alloy-rlp", - "alloy-serde 0.7.2", + "alloy-serde 0.7.3", "c-kzg", "derive_more 1.0.0", "once_cell", @@ -376,12 +376,13 @@ dependencies = [ [[package]] name = "alloy-genesis" -version = "0.7.2" +version = "0.7.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9dd39b72f860cb0c542fac925f91d1939c2b14a0970b39d0ae304b5b7574a0ac" +checksum = "aeec8e6eab6e52b7c9f918748c9b811e87dbef7312a2e3a2ca1729a92966a6af" dependencies = [ - "alloy-primitives 0.8.12", - "alloy-serde 0.7.2", + "alloy-primitives 0.8.14", + "alloy-serde 0.7.3", + "alloy-trie", "serde", ] @@ -399,12 +400,12 @@ dependencies = [ [[package]] name = "alloy-json-abi" -version = "0.8.12" +version = "0.8.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b84c506bf264110fa7e90d9924f742f40ef53c6572ea56a0b0bd714a567ed389" +checksum = "ac4b22b3e51cac09fd2adfcc73b55f447b4df669f983c13f7894ec82b607c63f" dependencies = [ - "alloy-primitives 0.8.12", - "alloy-sol-type-parser 0.8.12", + "alloy-primitives 0.8.14", + "alloy-sol-type-parser 0.8.14", "serde", "serde_json", ] @@ -425,15 +426,15 @@ dependencies = [ [[package]] name = "alloy-json-rpc" -version = "0.7.2" +version = "0.7.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6c15c11661571a19a06896663c93e804ccf013159275a89a98e892014df514d8" +checksum = "4fa077efe0b834bcd89ff4ba547f48fb081e4fdc3673dd7da1b295a2cf2bb7b7" dependencies = [ - "alloy-primitives 0.8.12", - "alloy-sol-types 0.8.12", + "alloy-primitives 0.8.14", + "alloy-sol-types 0.8.14", "serde", "serde_json", - "thiserror 2.0.3", + "thiserror 2.0.6", "tracing", ] @@ -460,27 +461,27 @@ dependencies = [ [[package]] name = "alloy-network" -version = "0.7.2" +version = "0.7.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "60dd0b99eaa5e715dd90d42021f7f08a0a70976ea84f41a0ad233770e0c1962b" +checksum = "209a1882a08e21aca4aac6e2a674dc6fcf614058ef8cb02947d63782b1899552" dependencies = [ - "alloy-consensus 0.7.2", + "alloy-consensus 0.7.3", "alloy-consensus-any", - "alloy-eips 0.7.2", - "alloy-json-rpc 0.7.2", - "alloy-network-primitives 0.7.2", - "alloy-primitives 0.8.12", + "alloy-eips 0.7.3", + "alloy-json-rpc 0.7.3", + "alloy-network-primitives 0.7.3", + "alloy-primitives 0.8.14", "alloy-rpc-types-any", - "alloy-rpc-types-eth 0.7.2", - "alloy-serde 0.7.2", - "alloy-signer 0.7.2", - "alloy-sol-types 0.8.12", + "alloy-rpc-types-eth 0.7.3", + "alloy-serde 0.7.3", + "alloy-signer 0.7.3", + "alloy-sol-types 0.8.14", "async-trait", "auto_impl", "futures-utils-wasm", "serde", "serde_json", - "thiserror 2.0.3", + "thiserror 2.0.6", ] [[package]] @@ -496,30 +497,30 @@ dependencies = [ [[package]] name = "alloy-network-primitives" -version = "0.7.2" +version = "0.7.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "18abfc73ce48f074c8bc6e05c1f08ef0b1ddc9b04f191a821d0beb9470a42a29" +checksum = "c20219d1ad261da7a6331c16367214ee7ded41d001fabbbd656fbf71898b2773" dependencies = [ - "alloy-consensus 0.7.2", - "alloy-eips 0.7.2", - "alloy-primitives 0.8.12", - "alloy-serde 0.7.2", + "alloy-consensus 0.7.3", + "alloy-eips 0.7.3", + "alloy-primitives 0.8.14", + "alloy-serde 0.7.3", "serde", ] [[package]] name = "alloy-node-bindings" -version = "0.7.2" +version = "0.7.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f9a04cf8f3a19b024b2bc71b5774d423cd2edda7f67df6029daa1368c5c02da5" +checksum = "bffcf33dd319f21cd6f066d81cbdef0326d4bdaaf7cfe91110bc090707858e9f" dependencies = [ - "alloy-genesis 0.7.2", - "alloy-primitives 0.8.12", + "alloy-genesis 0.7.3", + "alloy-primitives 0.8.14", "k256 0.13.4", "rand 0.8.5", "serde_json", "tempfile", - "thiserror 2.0.3", + "thiserror 2.0.6", "tracing", "url", ] @@ -549,9 +550,9 @@ dependencies = [ [[package]] name = "alloy-primitives" -version = "0.8.12" +version = "0.8.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9fce5dbd6a4f118eecc4719eaa9c7ffc31c315e6c5ccde3642db927802312425" +checksum = "9db948902dfbae96a73c2fbf1f7abec62af034ab883e4c777c3fd29702bd6e2c" dependencies = [ "alloy-rlp", "bytes", @@ -560,9 +561,9 @@ dependencies = [ "derive_more 1.0.0", "foldhash", "getrandom 0.2.15", - "hashbrown 0.15.1", + "hashbrown 0.15.2", "hex-literal", - "indexmap 2.6.0", + "indexmap 2.7.0", "itoa", "k256 0.13.4", "keccak-asm", @@ -570,7 +571,7 @@ dependencies = [ "proptest", "rand 0.8.5", "ruint", - "rustc-hash 2.0.0", + "rustc-hash 2.1.0", "serde", "sha3 0.10.8", "tiny-keccak", @@ -611,24 +612,24 @@ dependencies = [ [[package]] name = "alloy-provider" -version = "0.7.2" +version = "0.7.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4933c761f10e44d5e901804b56efb2ce6e0945e6c57d2fa1e5ace303fae6f74a" +checksum = "9eefa6f4c798ad01f9b4202d02cea75f5ec11fa180502f4701e2b47965a8c0bb" dependencies = [ "alloy-chains", - "alloy-consensus 0.7.2", - "alloy-eips 0.7.2", - "alloy-json-rpc 0.7.2", - "alloy-network 0.7.2", - "alloy-network-primitives 0.7.2", - "alloy-primitives 0.8.12", + "alloy-consensus 0.7.3", + "alloy-eips 0.7.3", + "alloy-json-rpc 0.7.3", + "alloy-network 0.7.3", + "alloy-network-primitives 0.7.3", + "alloy-primitives 0.8.14", "alloy-pubsub", - "alloy-rpc-client 0.7.2", - "alloy-rpc-types-engine 0.7.2", - "alloy-rpc-types-eth 0.7.2", + "alloy-rpc-client 0.7.3", + "alloy-rpc-types-engine 0.7.3", + "alloy-rpc-types-eth 0.7.3", "alloy-rpc-types-trace", - "alloy-transport 0.7.2", - "alloy-transport-http 0.7.2", + "alloy-transport 0.7.3", + "alloy-transport-http 0.7.3", "alloy-transport-ipc", "alloy-transport-ws", "async-stream", @@ -644,7 +645,7 @@ dependencies = [ "schnellru", "serde", "serde_json", - "thiserror 2.0.3", + "thiserror 2.0.6", "tokio", "tracing", "url", @@ -653,13 +654,13 @@ dependencies = [ [[package]] name = "alloy-pubsub" -version = "0.7.2" +version = "0.7.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "808719714bfb2aa24b0eb2a38411ce8e654ba11c0ebf2a6648fcbe9fabfe696d" +checksum = "aac9a7210e0812b1d814118f426f57eb7fc260a419224dd1c76d169879c06907" dependencies = [ - "alloy-json-rpc 0.7.2", - "alloy-primitives 0.8.12", - "alloy-transport 0.7.2", + "alloy-json-rpc 0.7.3", + "alloy-primitives 0.8.14", + "alloy-transport 0.7.3", "bimap", "futures", "serde", @@ -672,9 +673,9 @@ dependencies = [ [[package]] name = "alloy-rlp" -version = "0.3.9" +version = "0.3.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "da0822426598f95e45dd1ea32a738dac057529a709ee645fcc516ffa4cbde08f" +checksum = "f542548a609dca89fcd72b3b9f355928cf844d4363c5eed9c5273a3dd225e097" dependencies = [ "alloy-rlp-derive", "arrayvec", @@ -683,13 +684,13 @@ dependencies = [ [[package]] name = "alloy-rlp-derive" -version = "0.3.9" +version = "0.3.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2b09cae092c27b6f1bde952653a22708691802e57bfef4a2973b80bea21efd3f" +checksum = "5a833d97bf8a5f0f878daf2c8451fff7de7f9de38baa5a45d936ec718d81255a" dependencies = [ "proc-macro2", "quote", - "syn 2.0.87", + "syn 2.0.90", ] [[package]] @@ -715,15 +716,15 @@ dependencies = [ [[package]] name = "alloy-rpc-client" -version = "0.7.2" +version = "0.7.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6ce26c25efb8290b6ba559ae6c40bf6630d337e107ae242e5790501420dba7b7" +checksum = "ed30bf1041e84cabc5900f52978ca345dd9969f2194a945e6fdec25b0620705c" dependencies = [ - "alloy-json-rpc 0.7.2", - "alloy-primitives 0.8.12", + "alloy-json-rpc 0.7.3", + "alloy-primitives 0.8.14", "alloy-pubsub", - "alloy-transport 0.7.2", - "alloy-transport-http 0.7.2", + "alloy-transport 0.7.3", + "alloy-transport-http 0.7.3", "alloy-transport-ipc", "alloy-transport-ws", "futures", @@ -754,28 +755,28 @@ dependencies = [ [[package]] name = "alloy-rpc-types" -version = "0.7.2" +version = "0.7.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "41080ce2640928f0df45c41d2af629b88db3cb31af3abbe614964ae10001ddac" +checksum = "5ab686b0fa475d2a4f5916c5f07797734a691ec58e44f0f55d4746ea39cbcefb" dependencies = [ - "alloy-primitives 0.8.12", - "alloy-rpc-types-beacon 0.7.2", - "alloy-rpc-types-engine 0.7.2", - "alloy-rpc-types-eth 0.7.2", + "alloy-primitives 0.8.14", + "alloy-rpc-types-beacon 0.7.3", + "alloy-rpc-types-engine 0.7.3", + "alloy-rpc-types-eth 0.7.3", "alloy-rpc-types-trace", - "alloy-serde 0.7.2", + "alloy-serde 0.7.3", "serde", ] [[package]] name = "alloy-rpc-types-any" -version = "0.7.2" +version = "0.7.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "abca110e59f760259e26d0c84912121468008aba48dd227af0f306cfd7bce9ae" +checksum = "200661999b6e235d9840be5d60a6e8ae2f0af9eb2a256dd378786744660e36ec" dependencies = [ "alloy-consensus-any", - "alloy-rpc-types-eth 0.7.2", - "alloy-serde 0.7.2", + "alloy-rpc-types-eth 0.7.3", + "alloy-serde 0.7.3", ] [[package]] @@ -796,17 +797,17 @@ dependencies = [ [[package]] name = "alloy-rpc-types-beacon" -version = "0.7.2" +version = "0.7.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "45c8db5fb70d2fece7bc1cd5adf42e72fc8a23547adeff8f558d9063f1e7788c" +checksum = "cc37861dc8cbf5da35d346139fbe6e03ee7823cc21138a2c4a590d3b0b4b24be" dependencies = [ - "alloy-eips 0.7.2", - "alloy-primitives 0.8.12", - "alloy-rpc-types-engine 0.7.2", - "alloy-serde 0.7.2", + "alloy-eips 0.7.3", + "alloy-primitives 0.8.14", + "alloy-rpc-types-engine 0.7.3", + "alloy-serde 0.7.3", "serde", "serde_with", - "thiserror 2.0.3", + "thiserror 2.0.6", ] [[package]] @@ -831,15 +832,15 @@ dependencies = [ [[package]] name = "alloy-rpc-types-engine" -version = "0.7.2" +version = "0.7.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d3b000c7f3469e7faa575ba70207294cf07e91dfd6ce4d04d5d5d8069f974a66" +checksum = "5d297268357e3eae834ddd6888b15f764cbc0f4b3be9265f5f6ec239013f3d68" dependencies = [ - "alloy-consensus 0.7.2", - "alloy-eips 0.7.2", - "alloy-primitives 0.8.12", + "alloy-consensus 0.7.3", + "alloy-eips 0.7.3", + "alloy-primitives 0.8.14", "alloy-rlp", - "alloy-serde 0.7.2", + "alloy-serde 0.7.3", "derive_more 1.0.0", "jsonwebtoken", "rand 0.8.5", @@ -868,18 +869,18 @@ dependencies = [ [[package]] name = "alloy-rpc-types-eth" -version = "0.7.2" +version = "0.7.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3468e7385fbb86b0fde5497d685c02f765ea09d36f7e07c5d1c9a52b077d38e2" +checksum = "a0600b8b5e2dc0cab12cbf91b5a885c35871789fb7b3a57b434bd4fced5b7a8b" dependencies = [ - "alloy-consensus 0.7.2", + "alloy-consensus 0.7.3", "alloy-consensus-any", - "alloy-eips 0.7.2", - "alloy-network-primitives 0.7.2", - "alloy-primitives 0.8.12", + "alloy-eips 0.7.3", + "alloy-network-primitives 0.7.3", + "alloy-primitives 0.8.14", "alloy-rlp", - "alloy-serde 0.7.2", - "alloy-sol-types 0.8.12", + "alloy-serde 0.7.3", + "alloy-sol-types 0.8.14", "derive_more 1.0.0", "itertools 0.13.0", "serde", @@ -888,16 +889,16 @@ dependencies = [ [[package]] name = "alloy-rpc-types-trace" -version = "0.7.2" +version = "0.7.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7a90be1bc8e3659db1c9512191873a268a917efbc62b8bd39a92c12bf613b193" +checksum = "4e073ab0e67429c60be281e181731132fd07d82e091c10c29ace6935101034bb" dependencies = [ - "alloy-primitives 0.8.12", - "alloy-rpc-types-eth 0.7.2", - "alloy-serde 0.7.2", + "alloy-primitives 0.8.14", + "alloy-rpc-types-eth 0.7.3", + "alloy-serde 0.7.3", "serde", "serde_json", - "thiserror 2.0.3", + "thiserror 2.0.6", ] [[package]] @@ -913,11 +914,11 @@ dependencies = [ [[package]] name = "alloy-serde" -version = "0.7.2" +version = "0.7.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "42de6002e2154b50b3568aea27e26bd9caf7b754658f43065f2e9b6ee0a8c839" +checksum = "9afa753a97002a33b2ccb707d9f15f31c81b8c1b786c95b73cc62bb1d1fd0c3f" dependencies = [ - "alloy-primitives 0.8.12", + "alloy-primitives 0.8.14", "serde", "serde_json", ] @@ -938,32 +939,32 @@ dependencies = [ [[package]] name = "alloy-signer" -version = "0.7.2" +version = "0.7.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f288a9a25e2578dab17845fd8d2be1d32de33565783ed185ded161a65f92381b" +checksum = "9b2cbff01a673936c2efd7e00d4c0e9a4dbbd6d600e2ce298078d33efbb19cd7" dependencies = [ - "alloy-primitives 0.8.12", + "alloy-primitives 0.8.14", "async-trait", "auto_impl", "elliptic-curve 0.13.8", "k256 0.13.4", - "thiserror 2.0.3", + "thiserror 2.0.6", ] [[package]] name = "alloy-signer-local" -version = "0.7.2" +version = "0.7.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0d8081f589ddc11a959605e30c723d51cad2562d9072305f8e3ef311f077e5eb" +checksum = "bd6d988cb6cd7d2f428a74476515b1a6e901e08c796767f9f93311ab74005c8b" dependencies = [ - "alloy-consensus 0.7.2", - "alloy-network 0.7.2", - "alloy-primitives 0.8.12", - "alloy-signer 0.7.2", + "alloy-consensus 0.7.3", + "alloy-network 0.7.3", + "alloy-primitives 0.8.14", + "alloy-signer 0.7.3", "async-trait", "k256 0.13.4", "rand 0.8.5", - "thiserror 2.0.3", + "thiserror 2.0.6", ] [[package]] @@ -977,21 +978,21 @@ dependencies = [ "proc-macro-error", "proc-macro2", "quote", - "syn 2.0.87", + "syn 2.0.90", ] [[package]] name = "alloy-sol-macro" -version = "0.8.12" +version = "0.8.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9343289b4a7461ed8bab8618504c995c049c082b70c7332efd7b32125633dc05" +checksum = "3bfd7853b65a2b4f49629ec975fee274faf6dff15ab8894c620943398ef283c0" dependencies = [ - "alloy-sol-macro-expander 0.8.12", - "alloy-sol-macro-input 0.8.12", + "alloy-sol-macro-expander 0.8.14", + "alloy-sol-macro-input 0.8.14", "proc-macro-error2", "proc-macro2", "quote", - "syn 2.0.87", + "syn 2.0.90", ] [[package]] @@ -1003,31 +1004,31 @@ dependencies = [ "alloy-sol-macro-input 0.7.7", "const-hex", "heck", - "indexmap 2.6.0", + "indexmap 2.7.0", "proc-macro-error", "proc-macro2", "quote", - "syn 2.0.87", + "syn 2.0.90", "syn-solidity 0.7.7", "tiny-keccak", ] [[package]] name = "alloy-sol-macro-expander" -version = "0.8.12" +version = "0.8.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4222d70bec485ceccc5d8fd4f2909edd65b5d5e43d4aca0b5dcee65d519ae98f" +checksum = "82ec42f342d9a9261699f8078e57a7a4fda8aaa73c1a212ed3987080e6a9cd13" dependencies = [ - "alloy-json-abi 0.8.12", - "alloy-sol-macro-input 0.8.12", + "alloy-json-abi 0.8.14", + "alloy-sol-macro-input 0.8.14", "const-hex", "heck", - "indexmap 2.6.0", + "indexmap 2.7.0", "proc-macro-error2", "proc-macro2", "quote", - "syn 2.0.87", - "syn-solidity 0.8.12", + "syn 2.0.90", + "syn-solidity 0.8.14", "tiny-keccak", ] @@ -1042,25 +1043,25 @@ dependencies = [ "heck", "proc-macro2", "quote", - "syn 2.0.87", + "syn 2.0.90", "syn-solidity 0.7.7", ] [[package]] name = "alloy-sol-macro-input" -version = "0.8.12" +version = "0.8.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2e17f2677369571b976e51ea1430eb41c3690d344fef567b840bfc0b01b6f83a" +checksum = "ed2c50e6a62ee2b4f7ab3c6d0366e5770a21cad426e109c2f40335a1b3aff3df" dependencies = [ - "alloy-json-abi 0.8.12", + "alloy-json-abi 0.8.14", "const-hex", "dunce", "heck", "proc-macro2", "quote", "serde_json", - "syn 2.0.87", - "syn-solidity 0.8.12", + "syn 2.0.90", + "syn-solidity 0.8.14", ] [[package]] @@ -1075,9 +1076,9 @@ dependencies = [ [[package]] name = "alloy-sol-type-parser" -version = "0.8.12" +version = "0.8.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "aa64d80ae58ffaafdff9d5d84f58d03775f66c84433916dc9a64ed16af5755da" +checksum = "ac17c6e89a50fb4a758012e4b409d9a0ba575228e69b539fe37d7a1bd507ca4a" dependencies = [ "serde", "winnow", @@ -1097,13 +1098,13 @@ dependencies = [ [[package]] name = "alloy-sol-types" -version = "0.8.12" +version = "0.8.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6520d427d4a8eb7aa803d852d7a52ceb0c519e784c292f64bb339e636918cf27" +checksum = "c9dc0fffe397aa17628160e16b89f704098bf3c9d74d5d369ebc239575936de5" dependencies = [ - "alloy-json-abi 0.8.12", - "alloy-primitives 0.8.12", - "alloy-sol-macro 0.8.12", + "alloy-json-abi 0.8.14", + "alloy-primitives 0.8.14", + "alloy-sol-macro 0.8.14", "const-hex", "serde", ] @@ -1129,17 +1130,17 @@ dependencies = [ [[package]] name = "alloy-transport" -version = "0.7.2" +version = "0.7.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "90352f4cf78017905c3244f48b38fadc345970bbc9095087c0f985a580550488" +checksum = "d69d36982b9e46075ae6b792b0f84208c6c2c15ad49f6c500304616ef67b70e0" dependencies = [ - "alloy-json-rpc 0.7.2", + "alloy-json-rpc 0.7.3", "base64 0.22.1", "futures-util", "futures-utils-wasm", "serde", "serde_json", - "thiserror 2.0.3", + "thiserror 2.0.6", "tokio", "tower 0.5.1", "tracing", @@ -1164,12 +1165,17 @@ dependencies = [ [[package]] name = "alloy-transport-http" -version = "0.7.2" +version = "0.7.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7d26c94d51fa8b1aee3d15db113dd0773776c02bb36dbaa2590b900dadd7e7d0" +checksum = "2e02ffd5d93ffc51d72786e607c97de3b60736ca3e636ead0ec1f7dce68ea3fd" dependencies = [ - "alloy-json-rpc 0.7.2", - "alloy-transport 0.7.2", + "alloy-json-rpc 0.7.3", + "alloy-rpc-types-engine 0.7.3", + "alloy-transport 0.7.3", + "http-body-util", + "hyper 1.5.1", + "hyper-util", + "jsonwebtoken", "reqwest 0.12.9", "serde_json", "tower 0.5.1", @@ -1179,13 +1185,13 @@ dependencies = [ [[package]] name = "alloy-transport-ipc" -version = "0.7.2" +version = "0.7.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "14c498fcdec50650be6b6a22ce7928a1b2738086b4f94f31b132e83498d45bbb" +checksum = "1b6f8b87cb84bae6d81ae6604b37741c8116f84f9784a0ecc6038c302e679d23" dependencies = [ - "alloy-json-rpc 0.7.2", + "alloy-json-rpc 0.7.3", "alloy-pubsub", - "alloy-transport 0.7.2", + "alloy-transport 0.7.3", "bytes", "futures", "interprocess", @@ -1198,15 +1204,15 @@ dependencies = [ [[package]] name = "alloy-transport-ws" -version = "0.7.2" +version = "0.7.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cd7b21335b55c9f715e2acca0228dc1d6880d961756916c13a9ce70f9f413e70" +checksum = "9c085c4e1e7680b723ffc558f61a22c061ed3f70eb3436f93f3936779c59cec1" dependencies = [ "alloy-pubsub", - "alloy-transport 0.7.2", + "alloy-transport 0.7.3", "futures", - "http 1.1.0", - "rustls 0.23.16", + "http 1.2.0", + "rustls 0.23.19", "serde_json", "tokio", "tokio-tungstenite", @@ -1216,11 +1222,11 @@ dependencies = [ [[package]] name = "alloy-trie" -version = "0.7.4" +version = "0.7.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b6b2e366c0debf0af77766c23694a3f863b02633050e71e096e257ffbd395e50" +checksum = "3a5fd8fea044cc9a8c8a50bb6f28e31f0385d820f116c5b98f6f4e55d6e5590b" dependencies = [ - "alloy-primitives 0.8.12", + "alloy-primitives 0.8.14", "alloy-rlp", "arrayvec", "derive_more 1.0.0", @@ -1302,9 +1308,9 @@ dependencies = [ [[package]] name = "anyhow" -version = "1.0.93" +version = "1.0.94" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4c95c10ba0b00a02636238b814946408b1322d5ac4760326e6fb8ec956d85775" +checksum = "c1fd03a028ef38ba2276dce7e33fcd6369c158a1bca17946c4b1b701891c1ff7" [[package]] name = "arbitrary" @@ -1519,7 +1525,7 @@ checksum = "c7c24de15d275a1ecfd47a380fb4d5ec9bfe0933f309ed5e705b775596a3574d" dependencies = [ "proc-macro2", "quote", - "syn 2.0.87", + "syn 2.0.90", ] [[package]] @@ -1530,7 +1536,7 @@ checksum = "721cae7de5c34fbb2acd27e21e6d2cf7b886dce0c27388d46c4e6c47ea4318dd" dependencies = [ "proc-macro2", "quote", - "syn 2.0.87", + "syn 2.0.90", ] [[package]] @@ -1558,7 +1564,7 @@ checksum = "3c87f3f15e7794432337fc718554eaa4dc8f04c9677a950ffe366f20a162ae42" dependencies = [ "proc-macro2", "quote", - "syn 2.0.87", + "syn 2.0.90", ] [[package]] @@ -1569,21 +1575,20 @@ checksum = "ace50bade8e6234aa140d9a2f552bbee1db4d353f69b8217bc503490fc1a9f26" [[package]] name = "aws-lc-rs" -version = "1.10.0" +version = "1.11.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cdd82dba44d209fddb11c190e0a94b78651f95299598e472215667417a03ff1d" +checksum = "f47bb8cc16b669d267eeccf585aea077d0882f4777b1c1f740217885d6e6e5a3" dependencies = [ "aws-lc-sys", - "mirai-annotations", "paste", "zeroize", ] [[package]] name = "aws-lc-sys" -version = "0.22.0" +version = "0.23.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "df7a4168111d7eb622a31b214057b8509c0a7e1794f44c546d742330dc793972" +checksum = "a2101df3813227bbaaaa0b04cd61c534c7954b22bd68d399b440be937dc63ff7" dependencies = [ "bindgen", "cc", @@ -1605,10 +1610,10 @@ dependencies = [ "axum-macros", "bytes", "futures-util", - "http 1.1.0", + "http 1.2.0", "http-body 1.0.1", "http-body-util", - "hyper 1.5.0", + "hyper 1.5.1", "hyper-util", "itoa", "matchit", @@ -1621,7 +1626,7 @@ dependencies = [ "serde_json", "serde_path_to_error", "serde_urlencoded", - "sync_wrapper 1.0.1", + "sync_wrapper 1.0.2", "tokio", "tower 0.5.1", "tower-layer", @@ -1638,13 +1643,13 @@ dependencies = [ "async-trait", "bytes", "futures-util", - "http 1.1.0", + "http 1.2.0", "http-body 1.0.1", "http-body-util", "mime", "pin-project-lite", "rustversion", - "sync_wrapper 1.0.1", + "sync_wrapper 1.0.2", "tower-layer", "tower-service", "tracing", @@ -1659,10 +1664,10 @@ dependencies = [ "axum", "axum-core", "bytes", - "fastrand 2.2.0", + "fastrand 2.3.0", "futures-util", "headers", - "http 1.1.0", + "http 1.2.0", "http-body 1.0.1", "http-body-util", "mime", @@ -1682,7 +1687,7 @@ checksum = "57d123550fa8d071b7255cb0cc04dc302baa6c8c4a79f55701552684d8399bce" dependencies = [ "proc-macro2", "quote", - "syn 2.0.87", + "syn 2.0.90", ] [[package]] @@ -1789,7 +1794,7 @@ dependencies = [ "regex", "rustc-hash 1.1.0", "shlex", - "syn 2.0.87", + "syn 2.0.90", "which", ] @@ -1928,7 +1933,9 @@ dependencies = [ "account_utils", "alloy 0.7.3", "alloy-node-bindings", - "alloy-rpc-types-engine 0.7.2", + "alloy-provider 0.7.3", + "alloy-rpc-types-engine 0.7.3", + "alloy-transport-http 0.7.3", "async-trait", "axum", "axum-extra", @@ -1947,6 +1954,7 @@ dependencies = [ "eyre", "futures", "hex", + "http-body-util", "metrics", "metrics-exporter-prometheus", "parking_lot 0.12.3", @@ -1958,9 +1966,10 @@ dependencies = [ "serde", "serde_json", "ssz_rs 0.9.0 (git+https://github.com/ralexstokes/ssz-rs?rev=ec3073e)", - "thiserror 2.0.3", + "thiserror 2.0.6", "tokio", "tokio-retry", + "tower 0.5.1", "tower-http", "tracing", "tracing-subscriber", @@ -2003,9 +2012,9 @@ checksum = "1fd0f2584146f6f2ef48085050886acf353beff7305ebd1ae69500e27c67f64b" [[package]] name = "bytes" -version = "1.8.0" +version = "1.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9ac0150caa2ae65ca5bd83f25c7de183dea78d4d366469f148435e2acfbad0da" +checksum = "325918d6fe32f23b19878fe4b34794ae41fc19ddbe53b10571a4874d44ffd39b" dependencies = [ "serde", ] @@ -2076,7 +2085,7 @@ dependencies = [ "docker-compose-types", "dotenvy", "eyre", - "indexmap 2.6.0", + "indexmap 2.7.0", "serde", "serde_json", "serde_yaml 0.9.33", @@ -2180,9 +2189,9 @@ dependencies = [ [[package]] name = "cc" -version = "1.2.0" +version = "1.2.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1aeb932158bd710538c73702db6945cb68a8fb08c519e6e12706b94263b36db8" +checksum = "27f657647bcff5394bf56c7317665bbf790a137a50eaaa5c6bfbb9e27a518f2d" dependencies = [ "jobserver", "libc", @@ -2206,9 +2215,9 @@ checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" [[package]] name = "chrono" -version = "0.4.38" +version = "0.4.39" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a21f936df1771bf62b77f047b726c4625ff2e8aa607c01ec06e5a05bd8463401" +checksum = "7e36cc9d416881d2e24f9a963be5fb1cd90966419ac844274161d10488b3e825" dependencies = [ "android-tzdata", "iana-time-zone", @@ -2276,9 +2285,9 @@ dependencies = [ [[package]] name = "clap" -version = "4.5.20" +version = "4.5.23" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b97f376d85a664d5837dbae44bf546e6477a679ff6610010f17276f686d867e8" +checksum = "3135e7ec2ef7b10c6ed8950f0f792ed96ee093fa088608f1c76e569722700c84" dependencies = [ "clap_builder", "clap_derive", @@ -2286,9 +2295,9 @@ dependencies = [ [[package]] name = "clap_builder" -version = "4.5.20" +version = "4.5.23" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "19bc80abd44e4bed93ca373a0704ccbd1b710dc5749406201bb018272808dc54" +checksum = "30582fc632330df2bd26877bde0c1f4470d57c582bbc070376afcd04d8cb4838" dependencies = [ "anstream", "anstyle", @@ -2306,14 +2315,14 @@ dependencies = [ "heck", "proc-macro2", "quote", - "syn 2.0.87", + "syn 2.0.90", ] [[package]] name = "clap_lex" -version = "0.7.2" +version = "0.7.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1462739cb27611015575c0c11df5df7601141071f07518d56fcc1be504cbec97" +checksum = "f46ad14479a25103f283c0f10005961cf086d8dc42205bb44c46ac563475dca6" [[package]] name = "clap_utils" @@ -2334,9 +2343,9 @@ dependencies = [ [[package]] name = "cmake" -version = "0.1.51" +version = "0.1.52" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fb1e43aa7fd152b1f968787f7dbcdeb306d1867ff373c69955211876c053f91a" +checksum = "c682c223677e0e5b6b7f63a64b9351844c3f1b1678a68b7ee617e30fb082620e" dependencies = [ "cc", ] @@ -2420,9 +2429,9 @@ dependencies = [ [[package]] name = "const-hex" -version = "1.13.1" +version = "1.14.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0121754e84117e65f9d90648ee6aa4882a6e63110307ab73967a4c5e7e69e586" +checksum = "4b0485bab839b018a8f1723fc5391819fea5f8f0f32288ef8a735fd096b6160c" dependencies = [ "cfg-if", "cpufeatures", @@ -2468,6 +2477,16 @@ dependencies = [ "libc", ] +[[package]] +name = "core-foundation" +version = "0.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b55271e5c8c478ad3f38ad24ef34923091e0548492a266d19b3c0b4d82574c63" +dependencies = [ + "core-foundation-sys", + "libc", +] + [[package]] name = "core-foundation-sys" version = "0.8.7" @@ -2485,9 +2504,9 @@ dependencies = [ [[package]] name = "cpufeatures" -version = "0.2.15" +version = "0.2.16" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0ca741a962e1b0bff6d724a1a0958b686406e853bb14061f218562e1896f95e6" +checksum = "16b80225097f2e5ae4e7179dd2266824648f3e2f49d9134d584b76389d31c4c3" dependencies = [ "libc", ] @@ -2694,7 +2713,7 @@ checksum = "f46882e17999c6cc590af592290432be3bce0428cb0d5f8b6715e4dc7b383eb3" dependencies = [ "proc-macro2", "quote", - "syn 2.0.87", + "syn 2.0.90", ] [[package]] @@ -2742,7 +2761,7 @@ dependencies = [ "proc-macro2", "quote", "strsim 0.11.1", - "syn 2.0.87", + "syn 2.0.90", ] [[package]] @@ -2764,7 +2783,7 @@ checksum = "d336a2a514f6ccccaa3e09b02d41d35330c07ddf03a62165fcec10bb561c7806" dependencies = [ "darling_core 0.20.10", "quote", - "syn 2.0.87", + "syn 2.0.90", ] [[package]] @@ -2900,7 +2919,7 @@ checksum = "30542c1ad912e0e3d22a1935c290e12e8a29d704a420177a31faad4a601a0800" dependencies = [ "proc-macro2", "quote", - "syn 2.0.87", + "syn 2.0.90", ] [[package]] @@ -2921,7 +2940,7 @@ dependencies = [ "darling 0.20.10", "proc-macro2", "quote", - "syn 2.0.87", + "syn 2.0.90", ] [[package]] @@ -2931,7 +2950,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ab63b0e2bf4d5928aff72e83a7dace85d7bba5fe12dcc3c5a572d78caffd3f3c" dependencies = [ "derive_builder_core", - "syn 2.0.87", + "syn 2.0.90", ] [[package]] @@ -2944,7 +2963,7 @@ dependencies = [ "proc-macro2", "quote", "rustc_version 0.4.1", - "syn 2.0.87", + "syn 2.0.90", ] [[package]] @@ -2965,7 +2984,7 @@ dependencies = [ "convert_case 0.6.0", "proc-macro2", "quote", - "syn 2.0.87", + "syn 2.0.90", "unicode-xid", ] @@ -3080,7 +3099,7 @@ checksum = "97369cbbc041bc366949bc74d34658d6cda5621039731c6310521892a3a20ae0" dependencies = [ "proc-macro2", "quote", - "syn 2.0.87", + "syn 2.0.90", ] [[package]] @@ -3090,7 +3109,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9213a368b9c0767c81ef9ced0f712cfd99d27d7de2a22a60e7ac9b1342c8a395" dependencies = [ "derive_builder", - "indexmap 2.6.0", + "indexmap 2.7.0", "serde", "serde_yaml 0.9.33", ] @@ -3270,7 +3289,7 @@ checksum = "2f9ed6b3789237c8a0c1c505af1c7eb2c560df6186f01b098c3a1064ea532f38" dependencies = [ "proc-macro2", "quote", - "syn 2.0.87", + "syn 2.0.90", ] [[package]] @@ -3290,12 +3309,12 @@ dependencies = [ [[package]] name = "errno" -version = "0.3.9" +version = "0.3.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "534c5cf6194dfab3db3242765c03bbe257cf92f22b38f6bc0c58d59108a820ba" +checksum = "33d852cb9b869c2a9b3df2f71a3074817f01e1844f839a144f5fcef059a4eb5d" dependencies = [ "libc", - "windows-sys 0.52.0", + "windows-sys 0.59.0", ] [[package]] @@ -3664,9 +3683,9 @@ dependencies = [ [[package]] name = "fastrand" -version = "2.2.0" +version = "2.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "486f806e73c5707928240ddc295403b1b93c96a02038563881c4a2fd84b81ac4" +checksum = "37909eebbb50d72f9059c3b6d82c0463f2ff062c9e95845c43a6c9c0355411be" [[package]] name = "fastrlp" @@ -3751,9 +3770,9 @@ dependencies = [ [[package]] name = "flate2" -version = "1.0.34" +version = "1.0.35" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a1b589b4dc103969ad3cf85c950899926ec64300a1a46d76c03a6072957036f0" +checksum = "c936bfdafb507ebbf50b8074c54fa31c5be9a1e7e5f467dd659697041407d07c" dependencies = [ "crc32fast", "miniz_oxide 0.8.0", @@ -3895,7 +3914,7 @@ checksum = "162ee34ebcb7c64a8abebc059ce0fee27c2262618d7b60ed8faf72fef13c3650" dependencies = [ "proc-macro2", "quote", - "syn 2.0.87", + "syn 2.0.90", ] [[package]] @@ -4031,7 +4050,7 @@ dependencies = [ "futures-sink", "futures-util", "http 0.2.12", - "indexmap 2.6.0", + "indexmap 2.7.0", "slab", "tokio", "tokio-util", @@ -4040,17 +4059,17 @@ dependencies = [ [[package]] name = "h2" -version = "0.4.6" +version = "0.4.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "524e8ac6999421f49a846c2d4411f337e53497d8ec55d67753beffa43c5d9205" +checksum = "ccae279728d634d083c00f6099cb58f01cc99c145b84b8be2f6c74618d79922e" dependencies = [ "atomic-waker", "bytes", "fnv", "futures-core", "futures-sink", - "http 1.1.0", - "indexmap 2.6.0", + "http 1.2.0", + "indexmap 2.7.0", "slab", "tokio", "tokio-util", @@ -4091,9 +4110,9 @@ dependencies = [ [[package]] name = "hashbrown" -version = "0.15.1" +version = "0.15.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3a9bfc1af68b1726ea47d3d5109de126281def866b33970e10fbab11b5dafab3" +checksum = "bf151400ff0baff5465007dd2f3e717f3fe502074ca563069ce3a6629d07b289" dependencies = [ "allocator-api2", "equivalent", @@ -4119,7 +4138,7 @@ dependencies = [ "base64 0.21.7", "bytes", "headers-core", - "http 1.1.0", + "http 1.2.0", "httpdate", "mime", "sha1", @@ -4131,7 +4150,7 @@ version = "0.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "54b4a22553d4242c49fddb9ba998a99962b5cc6f22cb5a3482bec22522403ce4" dependencies = [ - "http 1.1.0", + "http 1.2.0", ] [[package]] @@ -4238,9 +4257,9 @@ dependencies = [ [[package]] name = "http" -version = "1.1.0" +version = "1.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "21b9ddb458710bc376481b842f5da65cdf31522de232c1ca8146abce2a358258" +checksum = "f16ca2af56261c99fba8bac40a10251ce8188205a4c448fbb745a2e4daa76fea" dependencies = [ "bytes", "fnv", @@ -4265,7 +4284,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1efedce1fb8e6913f23e0c92de8e62cd5b772a67e7b3946df930a62566c93184" dependencies = [ "bytes", - "http 1.1.0", + "http 1.2.0", ] [[package]] @@ -4276,7 +4295,7 @@ checksum = "793429d76616a256bcb62c2a2ec2bed781c8307e797e2598c50010f2bee2544f" dependencies = [ "bytes", "futures-util", - "http 1.1.0", + "http 1.2.0", "http-body 1.0.1", "pin-project-lite", ] @@ -4330,7 +4349,7 @@ dependencies = [ "httpdate", "itoa", "pin-project-lite", - "socket2 0.5.7", + "socket2 0.5.8", "tokio", "tower-service", "tracing", @@ -4339,15 +4358,15 @@ dependencies = [ [[package]] name = "hyper" -version = "1.5.0" +version = "1.5.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bbbff0a806a4728c99295b254c8838933b5b082d75e3cb70c8dab21fdfbcfa9a" +checksum = "97818827ef4f364230e16705d4706e2897df2bb60617d6ca15d598025a3c481f" dependencies = [ "bytes", "futures-channel", "futures-util", - "h2 0.4.6", - "http 1.1.0", + "h2 0.4.7", + "http 1.2.0", "http-body 1.0.1", "httparse", "httpdate", @@ -4379,15 +4398,15 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "08afdbb5c31130e3034af566421053ab03787c640246a446327f550d11bcb333" dependencies = [ "futures-util", - "http 1.1.0", - "hyper 1.5.0", + "http 1.2.0", + "hyper 1.5.1", "hyper-util", "log", - "rustls 0.23.16", + "rustls 0.23.19", "rustls-native-certs", "rustls-pki-types", "tokio", - "tokio-rustls 0.26.0", + "tokio-rustls 0.26.1", "tower-service", ] @@ -4412,7 +4431,7 @@ checksum = "70206fc6890eaca9fde8a0bf71caa2ddfc9fe045ac9e5c70df101a7dbde866e0" dependencies = [ "bytes", "http-body-util", - "hyper 1.5.0", + "hyper 1.5.1", "hyper-util", "native-tls", "tokio", @@ -4429,11 +4448,11 @@ dependencies = [ "bytes", "futures-channel", "futures-util", - "http 1.1.0", + "http 1.2.0", "http-body 1.0.1", - "hyper 1.5.0", + "hyper 1.5.1", "pin-project-lite", - "socket2 0.5.7", + "socket2 0.5.8", "tokio", "tower-service", "tracing", @@ -4577,7 +4596,7 @@ checksum = "1ec89e9337638ecdc08744df490b221a7399bf8d164eb52a665454e60e075ad6" dependencies = [ "proc-macro2", "quote", - "syn 2.0.87", + "syn 2.0.90", ] [[package]] @@ -4654,13 +4673,13 @@ dependencies = [ [[package]] name = "impl-trait-for-tuples" -version = "0.2.2" +version = "0.2.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "11d7a9f6330b71fea57921c9b61c47ee6e84f72d394754eff6163ae67e7395eb" +checksum = "a0eb5a3343abf848c0984fe4604b2b105da9539376e24fc0a3b0007411ae4fd9" dependencies = [ "proc-macro2", "quote", - "syn 1.0.109", + "syn 2.0.90", ] [[package]] @@ -4682,12 +4701,12 @@ dependencies = [ [[package]] name = "indexmap" -version = "2.6.0" +version = "2.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "707907fe3c25f5424cce2cb7e1cbcafee6bdbe735ca90ef77c29e84591e5b9da" +checksum = "62f822373a4fe84d4bb149bf54e584a7f4abec90e072ed49cda0edea5b95471f" dependencies = [ "equivalent", - "hashbrown 0.15.1", + "hashbrown 0.15.2", "serde", ] @@ -4734,9 +4753,9 @@ dependencies = [ [[package]] name = "interprocess" -version = "2.2.1" +version = "2.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d2f4e4a06d42fab3e85ab1b419ad32b09eab58b901d40c57935ff92db3287a13" +checksum = "894148491d817cb36b6f778017b8ac46b17408d522dd90f539d677ea938362eb" dependencies = [ "doctest-file", "futures-core", @@ -4799,9 +4818,9 @@ dependencies = [ [[package]] name = "itoa" -version = "1.0.11" +version = "1.0.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "49f1f14873335454500d59611f1cf4a4b0f786f9ac11f4312a78e4cf2566695b" +checksum = "d75a2a4b1b190afb6f5425f10f6a8f959d2ea0b9c2b1d79553551850539e4674" [[package]] name = "jobserver" @@ -4814,10 +4833,11 @@ dependencies = [ [[package]] name = "js-sys" -version = "0.3.72" +version = "0.3.76" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6a88f1bda2bd75b0452a14784937d796722fdebfe50df998aeb3f0b7603019a9" +checksum = "6717b6b5b077764fb5966237269cb3c64edddde4b14ce42647430a78ced9e7b7" dependencies = [ + "once_cell", "wasm-bindgen", ] @@ -4915,9 +4935,9 @@ checksum = "830d08ce1d1d941e6b30645f1a0eb5643013d835ce3779a5fc208261dbe10f55" [[package]] name = "libc" -version = "0.2.162" +version = "0.2.168" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "18d287de67fe55fd7e1581fe933d965a5a9477b38e949cfa9f8574ef01506398" +checksum = "5aaeb2981e0606ca11d79718f8bb01164f1d6ed75080182d3abf017e6d244b6d" [[package]] name = "libflate" @@ -4945,9 +4965,9 @@ dependencies = [ [[package]] name = "libloading" -version = "0.8.5" +version = "0.8.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4979f22fdb869068da03c9f7528f8297c6fd2606bc3a4affe42e6a823fdb8da4" +checksum = "fc2f4eb4bc735547cfed7c0a4922cbd04a4655978c09b54f1f7b228750664c34" dependencies = [ "cfg-if", "windows-targets 0.52.6", @@ -5018,7 +5038,7 @@ dependencies = [ "futures-timer", "libp2p-identity", "multiaddr 0.18.2", - "multihash 0.19.2", + "multihash 0.19.3", "multistream-select", "once_cell", "parking_lot 0.12.3", @@ -5036,16 +5056,16 @@ dependencies = [ [[package]] name = "libp2p-identity" -version = "0.2.9" +version = "0.2.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "55cca1eb2bc1fd29f099f3daaab7effd01e1a54b7c577d0ed082521034d912e8" +checksum = "257b5621d159b32282eac446bed6670c39c7dc68a200a992d8f056afa0066f6d" dependencies = [ "asn1_der", "bs58 0.5.1", "ed25519-dalek", "hkdf", "libsecp256k1", - "multihash 0.19.2", + "multihash 0.19.3", "quick-protobuf", "rand 0.8.5", "sha2 0.10.8", @@ -5167,9 +5187,9 @@ checksum = "78b3ae25bc7c8c38cec158d1f2757ee79e9b3740fbc7ccf0e59e4b08d793fa89" [[package]] name = "litemap" -version = "0.7.3" +version = "0.7.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "643cb0b8d4fcc284004d5fd0d67ccf61dfffadb7f75e1e71bc420f4688a3a704" +checksum = "4ee93343901ab17bd981295f2cf0026d4ad018c7c31ba84549a4ddbb47a45104" [[package]] name = "lock_api" @@ -5224,7 +5244,7 @@ version = "0.12.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "234cf4f4a04dc1f57e24b96cc0cd600cf2af460d4161ac5ecdd0af8e1f3b2a38" dependencies = [ - "hashbrown 0.15.1", + "hashbrown 0.15.2", ] [[package]] @@ -5276,18 +5296,18 @@ dependencies = [ [[package]] name = "metastruct" -version = "0.1.2" +version = "0.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f00a5ba4a0f3453c31c397b214e1675d95b697c33763aa58add57ea833424384" +checksum = "d74f54f231f9a18d77393ecc5cc7ab96709b2a61ee326c2b2b291009b0cc5a07" dependencies = [ "metastruct_macro", ] [[package]] name = "metastruct_macro" -version = "0.1.2" +version = "0.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7c3a991d4536c933306e52f0e8ab303757185ec13a09d1f3e1cbde5a0d8410bf" +checksum = "985e7225f3a4dfbec47a0c6a730a874185fda840d365d7bbd6ba199dd81796d5" dependencies = [ "darling 0.13.4", "itertools 0.10.5", @@ -5315,10 +5335,10 @@ checksum = "b4f0c8427b39666bf970460908b213ec09b3b350f20c0c2eabcbba51704a08e6" dependencies = [ "base64 0.22.1", "http-body-util", - "hyper 1.5.0", + "hyper 1.5.1", "hyper-rustls 0.27.3", "hyper-util", - "indexmap 2.6.0", + "indexmap 2.7.0", "ipnet", "metrics", "metrics-util", @@ -5417,22 +5437,15 @@ dependencies = [ [[package]] name = "mio" -version = "1.0.2" +version = "1.0.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "80e04d1dcff3aae0704555fe5fee3bcfaf3d1fdf8a7e521d5b9d2b42acb52cec" +checksum = "2886843bf800fba2e3377cff24abf6379b4c4d5c6681eaf9ea5b0d15090450bd" dependencies = [ - "hermit-abi 0.3.9", "libc", "wasi 0.11.0+wasi-snapshot-preview1", "windows-sys 0.52.0", ] -[[package]] -name = "mirai-annotations" -version = "1.12.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c9be0862c1b3f26a88803c4a49de6889c10e608b3ee9344e6ef5b45fb37ad3d1" - [[package]] name = "modular-bitfield" version = "0.11.2" @@ -5469,7 +5482,7 @@ dependencies = [ "bytes", "encoding_rs", "futures-util", - "http 1.1.0", + "http 1.2.0", "httparse", "memchr", "mime", @@ -5506,7 +5519,7 @@ dependencies = [ "data-encoding", "libp2p-identity", "multibase", - "multihash 0.19.2", + "multihash 0.19.3", "percent-encoding", "serde", "static_assertions", @@ -5540,9 +5553,9 @@ dependencies = [ [[package]] name = "multihash" -version = "0.19.2" +version = "0.19.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cc41f430805af9d1cf4adae4ed2149c759b877b01d909a1f40256188d09345d2" +checksum = "6b430e7953c29dd6a09afc29ff0bb69c6e306329ee6794700aee27b76a1aea8d" dependencies = [ "core2", "unsigned-varint 0.8.0", @@ -5588,7 +5601,7 @@ dependencies = [ "openssl-probe", "openssl-sys", "schannel", - "security-framework", + "security-framework 2.11.1", "security-framework-sys", "tempfile", ] @@ -5705,7 +5718,7 @@ dependencies = [ "proc-macro-crate 3.2.0", "proc-macro2", "quote", - "syn 2.0.87", + "syn 2.0.90", ] [[package]] @@ -5748,32 +5761,32 @@ checksum = "b410bbe7e14ab526a0e86877eb47c6996a2bd7746f027ba551028c925390e4e9" [[package]] name = "op-alloy-consensus" -version = "0.7.2" +version = "0.7.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "77284451ec70602f148f4f3bc6d1106fdfefd57c11ff459c4b2985e400ed1a18" +checksum = "78f0daa0d0936d436a21b57571b1e27c5663aa2ab62f6edae5ba5be999f9f93e" dependencies = [ - "alloy-consensus 0.7.2", - "alloy-eips 0.7.2", - "alloy-primitives 0.8.12", + "alloy-consensus 0.7.3", + "alloy-eips 0.7.3", + "alloy-primitives 0.8.14", "alloy-rlp", - "alloy-serde 0.7.2", + "alloy-serde 0.7.3", "derive_more 1.0.0", "serde", - "thiserror 2.0.3", + "thiserror 2.0.6", ] [[package]] name = "op-alloy-rpc-types" -version = "0.7.2" +version = "0.7.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2bdc32eba4d43bbd23f1f16dece7afd991d41ab4ffc2494a72b048e9f38db622" +checksum = "73741855ffaa2041b33cb616d7db7180c1149b648c68c23bee9e15501073fb32" dependencies = [ - "alloy-consensus 0.7.2", - "alloy-eips 0.7.2", - "alloy-network-primitives 0.7.2", - "alloy-primitives 0.8.12", - "alloy-rpc-types-eth 0.7.2", - "alloy-serde 0.7.2", + "alloy-consensus 0.7.3", + "alloy-eips 0.7.3", + "alloy-network-primitives 0.7.3", + "alloy-primitives 0.8.14", + "alloy-rpc-types-eth 0.7.3", + "alloy-serde 0.7.3", "derive_more 1.0.0", "op-alloy-consensus", "serde", @@ -5834,7 +5847,7 @@ checksum = "a948666b637a0f465e8564c73e89d4dde00d72d4d473cc972f390fc3dcee7d9c" dependencies = [ "proc-macro2", "quote", - "syn 2.0.87", + "syn 2.0.90", ] [[package]] @@ -5845,9 +5858,9 @@ checksum = "ff011a302c396a5197692431fc1948019154afc178baf7d8e37367442a4601cf" [[package]] name = "openssl-src" -version = "300.4.0+3.4.0" +version = "300.4.1+3.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a709e02f2b4aca747929cca5ed248880847c650233cf8b8cdc48f40aaf4898a6" +checksum = "faa4eac4138c62414b5622d1b31c5c304f34b406b013c079c2bbc652fdd6678c" dependencies = [ "cc", ] @@ -6039,12 +6052,12 @@ checksum = "e3148f5046208a5d56bcfc03053e3ca6334e51da8dfb19b6cdc8b306fae3283e" [[package]] name = "pest" -version = "2.7.14" +version = "2.7.15" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "879952a81a83930934cbf1786752d6dedc3b1f29e8f8fb2ad1d0a36f377cf442" +checksum = "8b7cafe60d6cf8e62e1b9b2ea516a089c008945bb5a275416789e7db0bc199dc" dependencies = [ "memchr", - "thiserror 1.0.69", + "thiserror 2.0.6", "ucd-trie", ] @@ -6075,7 +6088,7 @@ checksum = "3c0f5fad0874fc7abcd4d750e76917eaebbecaa2c20bde22e1dbeeba8beb758c" dependencies = [ "proc-macro2", "quote", - "syn 2.0.87", + "syn 2.0.90", ] [[package]] @@ -6158,9 +6171,9 @@ dependencies = [ [[package]] name = "portable-atomic" -version = "1.9.0" +version = "1.10.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cc9c68a3f6da06753e9335d63e27f6b9754dd1920d941135b7ea8224f141adb2" +checksum = "280dc24453071f1b63954171985a0b0d30058d287960968b9b2aca264c8d4ee6" [[package]] name = "powerfmt" @@ -6193,7 +6206,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "64d1ec885c64d0457d564db4ec299b2dae3f9c02808b8ad9c3a089c591b18033" dependencies = [ "proc-macro2", - "syn 2.0.87", + "syn 2.0.90", ] [[package]] @@ -6285,14 +6298,14 @@ dependencies = [ "proc-macro-error-attr2", "proc-macro2", "quote", - "syn 2.0.87", + "syn 2.0.90", ] [[package]] name = "proc-macro2" -version = "1.0.89" +version = "1.0.92" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f139b0662de085916d1fb67d2b4169d1addddda1919e696f3252b740b629986e" +checksum = "37d3544b3f2748c54e147655edb5025752e2303145b5aefb3c3ea2c78b973bb0" dependencies = [ "unicode-ident", ] @@ -6635,11 +6648,11 @@ dependencies = [ "encoding_rs", "futures-core", "futures-util", - "h2 0.4.6", - "http 1.1.0", + "h2 0.4.7", + "http 1.2.0", "http-body 1.0.1", "http-body-util", - "hyper 1.5.0", + "hyper 1.5.1", "hyper-rustls 0.27.3", "hyper-tls 0.6.0", "hyper-util", @@ -6655,7 +6668,7 @@ dependencies = [ "serde", "serde_json", "serde_urlencoded", - "sync_wrapper 1.0.1", + "sync_wrapper 1.0.2", "system-configuration 0.6.1", "tokio", "tokio-native-tls", @@ -6670,12 +6683,12 @@ dependencies = [ [[package]] name = "reth-codecs" version = "1.1.2" -source = "git+https://github.com/paradigmxyz/reth#bedc68e8f4bd26927c1285e64e1cc652a0d839ff" +source = "git+https://github.com/paradigmxyz/reth#465692b5aff5718f10725077a9caf0a7b7c55297" dependencies = [ - "alloy-consensus 0.7.2", - "alloy-eips 0.7.2", - "alloy-genesis 0.7.2", - "alloy-primitives 0.8.12", + "alloy-consensus 0.7.3", + "alloy-eips 0.7.3", + "alloy-genesis 0.7.3", + "alloy-primitives 0.8.14", "alloy-trie", "bytes", "modular-bitfield", @@ -6687,43 +6700,43 @@ dependencies = [ [[package]] name = "reth-codecs-derive" version = "1.1.2" -source = "git+https://github.com/paradigmxyz/reth#bedc68e8f4bd26927c1285e64e1cc652a0d839ff" +source = "git+https://github.com/paradigmxyz/reth#465692b5aff5718f10725077a9caf0a7b7c55297" dependencies = [ "convert_case 0.6.0", "proc-macro2", "quote", - "syn 2.0.87", + "syn 2.0.90", ] [[package]] name = "reth-ethereum-forks" version = "1.1.2" -source = "git+https://github.com/paradigmxyz/reth#bedc68e8f4bd26927c1285e64e1cc652a0d839ff" +source = "git+https://github.com/paradigmxyz/reth#465692b5aff5718f10725077a9caf0a7b7c55297" dependencies = [ "alloy-chains", - "alloy-primitives 0.8.12", + "alloy-primitives 0.8.14", "alloy-rlp", "auto_impl", "crc", "dyn-clone", "once_cell", - "rustc-hash 2.0.0", + "rustc-hash 2.1.0", "serde", - "thiserror 2.0.3", + "thiserror 2.0.6", ] [[package]] name = "reth-primitives" version = "1.1.2" -source = "git+https://github.com/paradigmxyz/reth#bedc68e8f4bd26927c1285e64e1cc652a0d839ff" +source = "git+https://github.com/paradigmxyz/reth#465692b5aff5718f10725077a9caf0a7b7c55297" dependencies = [ - "alloy-consensus 0.7.2", - "alloy-eips 0.7.2", - "alloy-network 0.7.2", - "alloy-primitives 0.8.12", + "alloy-consensus 0.7.3", + "alloy-eips 0.7.3", + "alloy-network 0.7.3", + "alloy-primitives 0.8.14", "alloy-rlp", - "alloy-rpc-types 0.7.2", - "alloy-serde 0.7.2", + "alloy-rpc-types 0.7.3", + "alloy-serde 0.7.3", "alloy-trie", "bytes", "c-kzg", @@ -6747,12 +6760,12 @@ dependencies = [ [[package]] name = "reth-primitives-traits" version = "1.1.2" -source = "git+https://github.com/paradigmxyz/reth#bedc68e8f4bd26927c1285e64e1cc652a0d839ff" +source = "git+https://github.com/paradigmxyz/reth#465692b5aff5718f10725077a9caf0a7b7c55297" dependencies = [ - "alloy-consensus 0.7.2", - "alloy-eips 0.7.2", - "alloy-genesis 0.7.2", - "alloy-primitives 0.8.12", + "alloy-consensus 0.7.3", + "alloy-eips 0.7.3", + "alloy-genesis 0.7.3", + "alloy-primitives 0.8.14", "alloy-rlp", "auto_impl", "byteorder", @@ -6769,9 +6782,9 @@ dependencies = [ [[package]] name = "reth-static-file-types" version = "1.1.2" -source = "git+https://github.com/paradigmxyz/reth#bedc68e8f4bd26927c1285e64e1cc652a0d839ff" +source = "git+https://github.com/paradigmxyz/reth#465692b5aff5718f10725077a9caf0a7b7c55297" dependencies = [ - "alloy-primitives 0.8.12", + "alloy-primitives 0.8.14", "derive_more 1.0.0", "serde", "strum", @@ -6785,7 +6798,7 @@ checksum = "3702f132bb484f4f0d0ca4f6fbde3c82cfd745041abbedd6eda67730e1868ef0" dependencies = [ "alloy-eip2930", "alloy-eip7702", - "alloy-primitives 0.8.12", + "alloy-primitives 0.8.14", "auto_impl", "bitflags 2.6.0", "bitvec 1.0.1", @@ -6954,9 +6967,9 @@ checksum = "08d43f7aa6b08d49f382cde6a7982047c3426db949b1424bc4b7ec9ae12c6ce2" [[package]] name = "rustc-hash" -version = "2.0.0" +version = "2.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "583034fd73374156e66797ed8e5b0d5690409c9226b22d87cb7f19821c05d152" +checksum = "c7fb8039b3032c191086b10f11f319a6e99e1e82889c5cc6046f515c9db1d497" dependencies = [ "rand 0.8.5", ] @@ -6987,15 +7000,15 @@ dependencies = [ [[package]] name = "rustix" -version = "0.38.40" +version = "0.38.42" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "99e4ea3e1cdc4b559b8e5650f9c8e5998e3e5c1343b4eaf034565f32318d63c0" +checksum = "f93dc38ecbab2eb790ff964bb77fa94faf256fd3e73285fd7ba0903b76bedb85" dependencies = [ "bitflags 2.6.0", "errno", "libc", "linux-raw-sys", - "windows-sys 0.52.0", + "windows-sys 0.59.0", ] [[package]] @@ -7012,9 +7025,9 @@ dependencies = [ [[package]] name = "rustls" -version = "0.23.16" +version = "0.23.19" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "eee87ff5d9b36712a58574e12e9f0ea80f915a5b0ac518d322b24a465617925e" +checksum = "934b404430bb06b3fae2cba809eb45a1ab1aecd64491213d7c3301b88393f8d1" dependencies = [ "aws-lc-rs", "log", @@ -7028,15 +7041,14 @@ dependencies = [ [[package]] name = "rustls-native-certs" -version = "0.8.0" +version = "0.8.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fcaf18a4f2be7326cd874a5fa579fae794320a0f388d365dca7e480e55f83f8a" +checksum = "7fcff2dd52b58a8d98a70243663a0d234c4e2b79235637849d15913394a247d3" dependencies = [ "openssl-probe", - "rustls-pemfile 2.2.0", "rustls-pki-types", "schannel", - "security-framework", + "security-framework 3.0.1", ] [[package]] @@ -7145,9 +7157,9 @@ dependencies = [ [[package]] name = "scale-info" -version = "2.11.5" +version = "2.11.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1aa7ffc1c0ef49b0452c6e2986abf2b07743320641ffd5fc63d552458e3b779b" +checksum = "346a3b32eba2640d17a9cb5927056b08f3de90f65b72fe09402c2ad07d684d0b" dependencies = [ "cfg-if", "derive_more 1.0.0", @@ -7157,21 +7169,21 @@ dependencies = [ [[package]] name = "scale-info-derive" -version = "2.11.5" +version = "2.11.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "46385cc24172cf615450267463f937c10072516359b3ff1cb24228a4a08bf951" +checksum = "c6630024bf739e2179b91fb424b28898baf819414262c5d376677dbff1fe7ebf" dependencies = [ "proc-macro-crate 3.2.0", "proc-macro2", "quote", - "syn 2.0.87", + "syn 2.0.90", ] [[package]] name = "schannel" -version = "0.1.26" +version = "0.1.27" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "01227be5826fa0690321a2ba6c5cd57a19cf3f6a09e76973b58e61de6ab9d1c1" +checksum = "1f29ebaa345f945cec9fbbc532eb307f0fdad8161f281b6369539c8d84876b3d" dependencies = [ "windows-sys 0.59.0", ] @@ -7269,7 +7281,20 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "897b2245f0b511c87893af39b033e5ca9cce68824c4d7e7630b5a1d339658d02" dependencies = [ "bitflags 2.6.0", - "core-foundation", + "core-foundation 0.9.4", + "core-foundation-sys", + "libc", + "security-framework-sys", +] + +[[package]] +name = "security-framework" +version = "3.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e1415a607e92bec364ea2cf9264646dcce0f91e6d65281bd6f2819cca3bf39c8" +dependencies = [ + "bitflags 2.6.0", + "core-foundation 0.10.0", "core-foundation-sys", "libc", "security-framework-sys", @@ -7302,9 +7327,9 @@ checksum = "61697e0a1c7e512e84a621326239844a24d8207b4669b41bc18b32ea5cbf988b" [[package]] name = "semver-parser" -version = "0.10.2" +version = "0.10.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "00b0bef5b7f9e0df16536d3961cfb6e84331c065b4066afb39768d0e319411f7" +checksum = "9900206b54a3527fdc7b8a938bffd94a568bac4f4aa8113b209df75a09c0dec2" dependencies = [ "pest", ] @@ -7341,7 +7366,7 @@ checksum = "ad1e866f866923f252f05c889987993144fb74e722403468a4ebd70c3cd756c0" dependencies = [ "proc-macro2", "quote", - "syn 2.0.87", + "syn 2.0.90", ] [[package]] @@ -7385,7 +7410,7 @@ checksum = "6c64451ba24fc7a6a2d60fc75dd9c83c90903b19028d4eff35e88fc1e86564e9" dependencies = [ "proc-macro2", "quote", - "syn 2.0.87", + "syn 2.0.90", ] [[package]] @@ -7419,7 +7444,7 @@ dependencies = [ "chrono", "hex", "indexmap 1.9.3", - "indexmap 2.6.0", + "indexmap 2.7.0", "serde", "serde_derive", "serde_json", @@ -7436,7 +7461,7 @@ dependencies = [ "darling 0.20.10", "proc-macro2", "quote", - "syn 2.0.87", + "syn 2.0.90", ] [[package]] @@ -7457,7 +7482,7 @@ version = "0.9.33" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a0623d197252096520c6f2a5e1171ee436e5af99a5d7caa2891e55e61950e6d9" dependencies = [ - "indexmap 2.6.0", + "indexmap 2.7.0", "itoa", "ryu", "serde", @@ -7725,9 +7750,9 @@ dependencies = [ [[package]] name = "socket2" -version = "0.5.7" +version = "0.5.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ce305eb0b4296696835b71df73eb912e0f1ffd2556a501fcede6e0c50349191c" +checksum = "c970269d99b64e60ec3bd6ad27270092a5394c4e309314b18ae3fe575695fbe8" dependencies = [ "libc", "windows-sys 0.52.0", @@ -7782,7 +7807,7 @@ name = "ssz_rs" version = "0.9.0" source = "git+https://github.com/ralexstokes/ssz-rs?rev=ec3073e#ec3073e2273b4d0873fcb6df68ff4eff79588e92" dependencies = [ - "alloy-primitives 0.8.12", + "alloy-primitives 0.8.14", "bitvec 1.0.1", "serde", "sha2 0.9.9", @@ -7887,7 +7912,7 @@ dependencies = [ "proc-macro2", "quote", "rustversion", - "syn 2.0.87", + "syn 2.0.90", ] [[package]] @@ -7932,9 +7957,9 @@ dependencies = [ [[package]] name = "syn" -version = "2.0.87" +version = "2.0.90" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "25aa4ce346d03a6dcd68dd8b4010bcb74e54e62c90c573f394c46eae99aba32d" +checksum = "919d3b74a5dd0ccd15aeb8f93e7006bd9e14c295087c9896a110f490752bcf31" dependencies = [ "proc-macro2", "quote", @@ -7950,19 +7975,19 @@ dependencies = [ "paste", "proc-macro2", "quote", - "syn 2.0.87", + "syn 2.0.90", ] [[package]] name = "syn-solidity" -version = "0.8.12" +version = "0.8.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f76fe0a3e1476bdaa0775b9aec5b869ed9520c2b2fedfe9c6df3618f8ea6290b" +checksum = "da0523f59468a2696391f2a772edc089342aacd53c3caa2ac3264e598edf119b" dependencies = [ "paste", "proc-macro2", "quote", - "syn 2.0.87", + "syn 2.0.90", ] [[package]] @@ -7973,9 +7998,9 @@ checksum = "2047c6ded9c721764247e62cd3b03c09ffc529b2ba5b10ec482ae507a4a70160" [[package]] name = "sync_wrapper" -version = "1.0.1" +version = "1.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a7065abeca94b6a8a577f9bd45aa0867a2238b74e8eb67cf10d492bc39351394" +checksum = "0bf256ce5efdfa370213c1dabab5935a12e49f2c58d15e9eac2870d3b4f27263" dependencies = [ "futures-core", ] @@ -8000,7 +8025,7 @@ checksum = "c8af7666ab7b6390ab78131fb5b0fce11d6b7a6951602017c35fa82800708971" dependencies = [ "proc-macro2", "quote", - "syn 2.0.87", + "syn 2.0.90", ] [[package]] @@ -8010,7 +8035,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ba3a3adc5c275d719af8cb4272ea1c4a6d668a777f37e115f6d11ddbc1c8e0e7" dependencies = [ "bitflags 1.3.2", - "core-foundation", + "core-foundation 0.9.4", "system-configuration-sys 0.5.0", ] @@ -8021,7 +8046,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3c879d448e9d986b661742763247d3693ed13609438cf3d006f51f5368a5ba6b" dependencies = [ "bitflags 2.6.0", - "core-foundation", + "core-foundation 0.9.4", "system-configuration-sys 0.6.0", ] @@ -8064,7 +8089,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "28cce251fcbc87fac86a866eeb0d6c2d536fc16d06f184bb61aeae11aa4cee0c" dependencies = [ "cfg-if", - "fastrand 2.2.0", + "fastrand 2.3.0", "once_cell", "rustix", "windows-sys 0.59.0", @@ -8083,9 +8108,9 @@ dependencies = [ [[package]] name = "terminal_size" -version = "0.4.0" +version = "0.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4f599bd7ca042cfdf8f4512b277c02ba102247820f9d9d4a9f521f496751a6ef" +checksum = "5352447f921fda68cf61b4101566c0bdb5104eff6804d0678e5227580ab6a4e9" dependencies = [ "rustix", "windows-sys 0.59.0", @@ -8111,11 +8136,11 @@ dependencies = [ [[package]] name = "thiserror" -version = "2.0.3" +version = "2.0.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c006c85c7651b3cf2ada4584faa36773bd07bac24acfb39f3c431b36d7e667aa" +checksum = "8fec2a1820ebd077e2b90c4df007bebf344cd394098a13c563957d0afc83ea47" dependencies = [ - "thiserror-impl 2.0.3", + "thiserror-impl 2.0.6", ] [[package]] @@ -8126,18 +8151,18 @@ checksum = "4fee6c4efc90059e10f81e6d42c60a18f76588c3d74cb83a0b242a2b6c7504c1" dependencies = [ "proc-macro2", "quote", - "syn 2.0.87", + "syn 2.0.90", ] [[package]] name = "thiserror-impl" -version = "2.0.3" +version = "2.0.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f077553d607adc1caf65430528a576c757a71ed73944b66ebb58ef2bbd243568" +checksum = "d65750cab40f4ff1929fb1ba509e9914eb756131cef4210da8d5d700d26f6312" dependencies = [ "proc-macro2", "quote", - "syn 2.0.87", + "syn 2.0.90", ] [[package]] @@ -8161,9 +8186,9 @@ dependencies = [ [[package]] name = "time" -version = "0.3.36" +version = "0.3.37" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5dfd88e563464686c916c7e46e623e520ddc6d79fa6641390f2e3fa86e83e885" +checksum = "35e7868883861bd0e56d9ac6efcaaca0d6d5d82a2a7ec8209ff492c07cf37b21" dependencies = [ "deranged", "itoa", @@ -8182,9 +8207,9 @@ checksum = "ef927ca75afb808a4d64dd374f00a2adf8d0fcff8e7b184af886c3c87ec4a3f3" [[package]] name = "time-macros" -version = "0.2.18" +version = "0.2.19" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3f252a68540fde3a3877aeea552b832b40ab9a69e318efd078774a01ddee1ccf" +checksum = "2834e6017e3e5e4b9834939793b282bc03b37a3336245fa820e35e233e2a85de" dependencies = [ "num-conv", "time-core", @@ -8255,9 +8280,9 @@ checksum = "1f3ccbac311fea05f86f61904b462b55fb3df8837a366dfc601a0161d0532f20" [[package]] name = "tokio" -version = "1.41.1" +version = "1.42.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "22cfb5bee7a6a52939ca9224d6ac897bb669134078daa8735560897f69de4d33" +checksum = "5cec9b21b0450273377fc97bd4c33a8acffc8c996c987a7c5b319a0083707551" dependencies = [ "backtrace", "bytes", @@ -8266,7 +8291,7 @@ dependencies = [ "parking_lot 0.12.3", "pin-project-lite", "signal-hook-registry", - "socket2 0.5.7", + "socket2 0.5.8", "tokio-macros", "windows-sys 0.52.0", ] @@ -8279,7 +8304,7 @@ checksum = "693d596312e88961bc67d7f1f97af8a70227d9f90c31bba5806eec004978d752" dependencies = [ "proc-macro2", "quote", - "syn 2.0.87", + "syn 2.0.90", ] [[package]] @@ -8315,20 +8340,19 @@ dependencies = [ [[package]] name = "tokio-rustls" -version = "0.26.0" +version = "0.26.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0c7bc40d0e5a97695bb96e27995cd3a08538541b0a846f65bba7a359f36700d4" +checksum = "5f6d0975eaace0cf0fcadee4e4aaa5da15b5c079146f2cffb67c113be122bf37" dependencies = [ - "rustls 0.23.16", - "rustls-pki-types", + "rustls 0.23.19", "tokio", ] [[package]] name = "tokio-stream" -version = "0.1.16" +version = "0.1.17" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4f4e6ce100d0eb49a2734f8c0812bcd324cf357d21810932c5df6b96ef2b86f1" +checksum = "eca58d7bba4a75707817a2c44174253f9236b2d5fbd055602e9d5c07c139a047" dependencies = [ "futures-core", "pin-project-lite", @@ -8344,19 +8368,19 @@ checksum = "edc5f74e248dc973e0dbb7b74c7e0d6fcc301c694ff50049504004ef4d0cdcd9" dependencies = [ "futures-util", "log", - "rustls 0.23.16", + "rustls 0.23.19", "rustls-pki-types", "tokio", - "tokio-rustls 0.26.0", + "tokio-rustls 0.26.1", "tungstenite", - "webpki-roots 0.26.6", + "webpki-roots 0.26.7", ] [[package]] name = "tokio-util" -version = "0.7.12" +version = "0.7.13" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "61e7c3654c13bcd040d4a03abee2c75b1d14a37b423cf5a813ceae1cc903ec6a" +checksum = "d7fcaa8d55a2bdd6b83ace262b016eca0d79ee02818c5c1bcdf0305114081078" dependencies = [ "bytes", "futures-core", @@ -8402,7 +8426,7 @@ version = "0.22.22" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4ae48d6208a266e853d946088ed816055e556cc6028c5e8e2b84d9fa5dd7c7f5" dependencies = [ - "indexmap 2.6.0", + "indexmap 2.7.0", "serde", "serde_spanned", "toml_datetime", @@ -8448,7 +8472,7 @@ checksum = "1e9cd434a998747dd2c4276bc96ee2e0c7a2eadf3cae88e52be55a05fa9053f5" dependencies = [ "bitflags 2.6.0", "bytes", - "http 1.1.0", + "http 1.2.0", "http-body 1.0.1", "http-body-util", "pin-project-lite", @@ -8471,9 +8495,9 @@ checksum = "8df9b6e13f2d32c91b9bd719c00d1958837bc7dec474d94952798cc8e69eeec3" [[package]] name = "tracing" -version = "0.1.40" +version = "0.1.41" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c3523ab5a71916ccf420eebdf5521fcef02141234bbc0b8a49f2fdc4544364ef" +checksum = "784e0ac535deb450455cbfa28a6f0df145ea1bb7ae51b821cf5e7927fdcfbdd0" dependencies = [ "log", "pin-project-lite", @@ -8495,20 +8519,20 @@ dependencies = [ [[package]] name = "tracing-attributes" -version = "0.1.27" +version = "0.1.28" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "34704c8d6ebcbc939824180af020566b01a7c01f80641264eba0999f6c2b6be7" +checksum = "395ae124c09f9e6918a2310af6038fba074bcf474ac352496d5910dd59a2226d" dependencies = [ "proc-macro2", "quote", - "syn 2.0.87", + "syn 2.0.90", ] [[package]] name = "tracing-core" -version = "0.1.32" +version = "0.1.33" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c06d3da6113f116aaee68e4d601191614c9053067f9ab7f6edbcb161237daa54" +checksum = "e672c95779cf947c5311f83787af4fa8fffd12fb27e4993211a84bdfd9610f9c" dependencies = [ "once_cell", "valuable", @@ -8516,9 +8540,9 @@ dependencies = [ [[package]] name = "tracing-error" -version = "0.2.0" +version = "0.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d686ec1c0f384b1277f097b2f279a2ecc11afe8c133c1aabf036a27cb4cd206e" +checksum = "8b1581020d7a273442f5b45074a6a57d5757ad0a47dac0e9f0bd57b81936f3db" dependencies = [ "tracing", "tracing-subscriber", @@ -8537,9 +8561,9 @@ dependencies = [ [[package]] name = "tracing-serde" -version = "0.1.3" +version = "0.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bc6b213177105856957181934e4920de57730fc69bf42c37ee5bb664d406d9e1" +checksum = "704b1aeb7be0d0a84fc9828cae51dab5970fee5088f83d1dd7ee6f6246fc6ff1" dependencies = [ "serde", "tracing-core", @@ -8547,9 +8571,9 @@ dependencies = [ [[package]] name = "tracing-subscriber" -version = "0.3.18" +version = "0.3.19" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ad0f048c97dbd9faa9b7df56362b8ebcaa52adb06b498c050d2f4e32f90a7a8b" +checksum = "e8189decb5ac0fa7bc8b96b7cb9b2701d60d48805aca84a238004d665fcc4008" dependencies = [ "matchers", "nu-ansi-term", @@ -8654,11 +8678,11 @@ dependencies = [ "byteorder", "bytes", "data-encoding", - "http 1.1.0", + "http 1.2.0", "httparse", "log", "rand 0.8.5", - "rustls 0.23.16", + "rustls 0.23.19", "rustls-pki-types", "sha1", "thiserror 1.0.69", @@ -8747,9 +8771,9 @@ checksum = "eaea85b334db583fe3274d12b4cd1880032beab409c0d774be044d4480ab9a94" [[package]] name = "unicode-ident" -version = "1.0.13" +version = "1.0.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e91b56cd4cadaeb79bbf1a5645f6b4f8dc5bde8834ad5894a8db35fda9efa1fe" +checksum = "adb9e6ca4f869e1180728b7950e35922a7fc6397f7b641499e8f3ef06e50dc83" [[package]] name = "unicode-normalization" @@ -8814,9 +8838,9 @@ checksum = "8ecb6da28b8a351d773b68d5825ac39017e680750f980f3a1a85cd8dd28a47c1" [[package]] name = "url" -version = "2.5.3" +version = "2.5.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8d157f1b96d14500ffdc1f10ba712e780825526c03d9a49b4d0324b0d9113ada" +checksum = "32f8b686cadd1473f4bd0117a5d28d36b1ade384ea9b5069a1c40aefed7fda60" dependencies = [ "form_urlencoded", "idna", @@ -8965,9 +8989,9 @@ checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423" [[package]] name = "wasm-bindgen" -version = "0.2.95" +version = "0.2.99" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "128d1e363af62632b8eb57219c8fd7877144af57558fb2ef0368d0087bddeb2e" +checksum = "a474f6281d1d70c17ae7aa6a613c87fce69a127e2624002df63dcb39d6cf6396" dependencies = [ "cfg-if", "once_cell", @@ -8976,36 +9000,36 @@ dependencies = [ [[package]] name = "wasm-bindgen-backend" -version = "0.2.95" +version = "0.2.99" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cb6dd4d3ca0ddffd1dd1c9c04f94b868c37ff5fac97c30b97cff2d74fce3a358" +checksum = "5f89bb38646b4f81674e8f5c3fb81b562be1fd936d84320f3264486418519c79" dependencies = [ "bumpalo", "log", - "once_cell", "proc-macro2", "quote", - "syn 2.0.87", + "syn 2.0.90", "wasm-bindgen-shared", ] [[package]] name = "wasm-bindgen-futures" -version = "0.4.45" +version = "0.4.49" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cc7ec4f8827a71586374db3e87abdb5a2bb3a15afed140221307c3ec06b1f63b" +checksum = "38176d9b44ea84e9184eff0bc34cc167ed044f816accfe5922e54d84cf48eca2" dependencies = [ "cfg-if", "js-sys", + "once_cell", "wasm-bindgen", "web-sys", ] [[package]] name = "wasm-bindgen-macro" -version = "0.2.95" +version = "0.2.99" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e79384be7f8f5a9dd5d7167216f022090cf1f9ec128e6e6a482a2cb5c5422c56" +checksum = "2cc6181fd9a7492eef6fef1f33961e3695e4579b9872a6f7c83aee556666d4fe" dependencies = [ "quote", "wasm-bindgen-macro-support", @@ -9013,22 +9037,22 @@ dependencies = [ [[package]] name = "wasm-bindgen-macro-support" -version = "0.2.95" +version = "0.2.99" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "26c6ab57572f7a24a4985830b120de1594465e5d500f24afe89e16b4e833ef68" +checksum = "30d7a95b763d3c45903ed6c81f156801839e5ee968bb07e534c44df0fcd330c2" dependencies = [ "proc-macro2", "quote", - "syn 2.0.87", + "syn 2.0.90", "wasm-bindgen-backend", "wasm-bindgen-shared", ] [[package]] name = "wasm-bindgen-shared" -version = "0.2.95" +version = "0.2.99" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "65fc09f10666a9f147042251e0dda9c18f166ff7de300607007e96bdebc1068d" +checksum = "943aab3fdaaa029a6e0271b35ea10b72b943135afe9bffca82384098ad0e06a6" [[package]] name = "wasm-streams" @@ -9045,9 +9069,9 @@ dependencies = [ [[package]] name = "wasmtimer" -version = "0.4.0" +version = "0.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bb4f099acbc1043cc752b91615b24b02d7f6fcd975bd781fed9f50b3c3e15bf7" +checksum = "0048ad49a55b9deb3953841fa1fc5858f0efbcb7a18868c899a360269fac1b23" dependencies = [ "futures", "js-sys", @@ -9059,9 +9083,9 @@ dependencies = [ [[package]] name = "web-sys" -version = "0.3.72" +version = "0.3.76" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f6488b90108c040df0fe62fa815cbdee25124641df01814dd7282749234c6112" +checksum = "04dd7223427d52553d3702c004d3b2fe07c148165faa56313cb00211e31c12bc" dependencies = [ "js-sys", "wasm-bindgen", @@ -9085,9 +9109,9 @@ checksum = "5f20c57d8d7db6d3b86154206ae5d8fba62dd39573114de97c2cb0578251f8e1" [[package]] name = "webpki-roots" -version = "0.26.6" +version = "0.26.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "841c67bff177718f1d4dfefde8d8f0e78f9b6589319ba88312f567fc5841a958" +checksum = "5d642ff16b7e79272ae451b7322067cdc17cadf68c23264be9d94a32319efe7e" dependencies = [ "rustls-pki-types", ] @@ -9422,9 +9446,9 @@ dependencies = [ [[package]] name = "yoke" -version = "0.7.4" +version = "0.7.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6c5b1314b079b0930c31e3af543d8ee1757b1951ae1e1565ec704403a7240ca5" +checksum = "120e6aef9aa629e3d4f52dc8cc43a015c7724194c97dfaf45180d2daf2b77f40" dependencies = [ "serde", "stable_deref_trait", @@ -9434,13 +9458,13 @@ dependencies = [ [[package]] name = "yoke-derive" -version = "0.7.4" +version = "0.7.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "28cc31741b18cb6f1d5ff12f5b7523e3d6eb0852bbbad19d73905511d9849b95" +checksum = "2380878cad4ac9aac1e2435f3eb4020e8374b5f13c296cb75b4620ff8e229154" dependencies = [ "proc-macro2", "quote", - "syn 2.0.87", + "syn 2.0.90", "synstructure 0.13.1", ] @@ -9462,27 +9486,27 @@ checksum = "fa4f8080344d4671fb4e831a13ad1e68092748387dfc4f55e356242fae12ce3e" dependencies = [ "proc-macro2", "quote", - "syn 2.0.87", + "syn 2.0.90", ] [[package]] name = "zerofrom" -version = "0.1.4" +version = "0.1.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "91ec111ce797d0e0784a1116d0ddcdbea84322cd79e5d5ad173daeba4f93ab55" +checksum = "cff3ee08c995dee1859d998dea82f7374f2826091dd9cd47def953cae446cd2e" dependencies = [ "zerofrom-derive", ] [[package]] name = "zerofrom-derive" -version = "0.1.4" +version = "0.1.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0ea7b4a3637ea8669cedf0f1fd5c286a17f3de97b8dd5a70a6c167a1730e63a5" +checksum = "595eed982f7d355beb85837f651fa22e90b3c044842dc7f2c2842c086f295808" dependencies = [ "proc-macro2", "quote", - "syn 2.0.87", + "syn 2.0.90", "synstructure 0.13.1", ] @@ -9503,7 +9527,7 @@ checksum = "ce36e65b0d2999d2aafac989fb249189a141aee1f53c612c1f37d72631959f69" dependencies = [ "proc-macro2", "quote", - "syn 2.0.87", + "syn 2.0.90", ] [[package]] @@ -9525,7 +9549,7 @@ checksum = "6eafa6dfb17584ea3e2bd6e76e0cc15ad7af12b09abdd1ca55961bed9b1063c6" dependencies = [ "proc-macro2", "quote", - "syn 2.0.87", + "syn 2.0.90", ] [[package]] diff --git a/bolt-sidecar/Cargo.toml b/bolt-sidecar/Cargo.toml index b922e589..05da8f74 100644 --- a/bolt-sidecar/Cargo.toml +++ b/bolt-sidecar/Cargo.toml @@ -15,6 +15,8 @@ tokio = { version = "1", features = ["full"] } axum = { version = "0.7", features = ["macros"] } tower-http = { version = "0.5.2", features = ["timeout"] } axum-extra = "0.9.6" +tower = "0.5.1" +http-body-util = "0.1.2" futures = "0.3" tokio-retry = "0.3.0" @@ -31,11 +33,10 @@ alloy = { version = "0.7.3", features = [ "full", "provider-trace-api", "rpc-types-beacon", - "rpc-types-engine", -] } -alloy-rpc-types-engine = { version = "0.7.2", default-features = false, features = [ - "jwt", ] } +alloy-rpc-types-engine = { version = "0.7.2", default-features = false, features = ["jwt"] } +alloy-transport-http = { version = "0.7.2", default-features = false, features = ["jwt-auth"] } +alloy-provider = { version = "0.7.2", default-features = false, features = ["engine-api"] } # reth reth-primitives = { git = "https://github.com/paradigmxyz/reth", version = "1.1.2" } diff --git a/bolt-sidecar/src/builder/compat.rs b/bolt-sidecar/src/builder/compat.rs index d07ed00f..5b581dd7 100644 --- a/bolt-sidecar/src/builder/compat.rs +++ b/bolt-sidecar/src/builder/compat.rs @@ -2,14 +2,9 @@ use alloy::{ consensus::BlockHeader, eips::{eip2718::Encodable2718, eip4895::Withdrawal}, primitives::{Address, Bloom, B256, U256}, - rpc::types::{ - engine::{ - ExecutionPayload as AlloyExecutionPayload, ExecutionPayloadV1, ExecutionPayloadV2, - ExecutionPayloadV3, - }, - Withdrawals, - }, + rpc::types::Withdrawals, }; +use alloy_rpc_types_engine::{ExecutionPayloadV1, ExecutionPayloadV2, ExecutionPayloadV3}; use ethereum_consensus::{ bellatrix::mainnet::Transaction, capella::spec, @@ -81,7 +76,7 @@ pub(crate) fn to_execution_payload_header( pub(crate) fn to_alloy_execution_payload( block: &SealedBlock, block_hash: B256, -) -> AlloyExecutionPayload { +) -> ExecutionPayloadV3 { let alloy_withdrawals = block .body .withdrawals @@ -99,7 +94,7 @@ pub(crate) fn to_alloy_execution_payload( }) .unwrap_or_default(); - AlloyExecutionPayload::V3(ExecutionPayloadV3 { + ExecutionPayloadV3 { blob_gas_used: block.blob_gas_used().unwrap_or_default(), excess_blob_gas: block.excess_blob_gas.unwrap_or_default(), payload_inner: ExecutionPayloadV2 { @@ -121,7 +116,7 @@ pub(crate) fn to_alloy_execution_payload( }, withdrawals: alloy_withdrawals, }, - }) + } } /// Compatibility: convert a sealed block into an ethereum-consensus execution payload @@ -168,16 +163,6 @@ pub(crate) fn to_consensus_execution_payload(value: &SealedBlock) -> ConsensusEx ConsensusExecutionPayload::Deneb(payload) } -/// Compatibility: convert a Withdrawal from ethereum-consensus to alloy::primitives -pub(crate) fn to_alloy_withdrawal(value: ethereum_consensus::capella::Withdrawal) -> Withdrawal { - Withdrawal { - index: value.index as u64, - validator_index: value.validator_index as u64, - address: Address::from_slice(value.address.as_ref()), - amount: value.amount, - } -} - /// Compatibility: convert a withdrawal from alloy::primitives to ethereum-consensus pub(crate) fn to_consensus_withdrawal( value: &Withdrawal, diff --git a/bolt-sidecar/src/builder/fallback/engine_hinter.rs b/bolt-sidecar/src/builder/fallback/engine_hinter.rs new file mode 100644 index 00000000..362a2987 --- /dev/null +++ b/bolt-sidecar/src/builder/fallback/engine_hinter.rs @@ -0,0 +1,259 @@ +use std::ops::Deref; + +use alloy::{ + consensus::EMPTY_OMMER_ROOT_HASH, + primitives::{Address, Bloom, Bytes, B256, B64, U256}, + rpc::types::{Block, Withdrawal, Withdrawals}, +}; +use alloy_provider::ext::EngineApi; +use alloy_rpc_types_engine::{ClientCode, ExecutionPayloadV3, JwtSecret, PayloadStatusEnum}; +use reqwest::Url; +use reth_primitives::{ + BlockBody, Header as RethHeader, SealedBlock, SealedHeader, TransactionSigned, +}; +use tracing::{debug, error}; + +use crate::{ + builder::{compat::to_alloy_execution_payload, BuilderError}, + client::EngineClient, +}; + +use super::engine_hints::parse_hint_from_engine_response; + +/// The [EngineHinter] is responsible for gathering "hints" from the +/// engine API error responses to complete the sealed block. +/// +/// Since error messages are not overly standardized across execution clients, +/// we need to know which execution client is being used to properly parse the hints. +/// +/// This can be done by querying the EL `engine_getClientVersionV1` method. +#[derive(Debug)] +pub struct EngineHinter { + engine_client: EngineClient, +} + +impl Deref for EngineHinter { + type Target = EngineClient; + + fn deref(&self) -> &Self::Target { + &self.engine_client + } +} + +impl EngineHinter { + /// Create a new [EngineHinter] instance with the given JWT and engine RPC URL. + pub fn new(jwt_secret: JwtSecret, engine_rpc_url: Url) -> Self { + Self { engine_client: EngineClient::new_http(engine_rpc_url, jwt_secret) } + } + + /// Collect hints from the engine API to complete the sealed block. + /// This method will keep fetching hints until the payload is valid. + pub async fn fetch_payload_from_hints( + &self, + mut ctx: EngineHinterContext, + ) -> Result { + // The block body can be the same for all iterations, since it only contains + // the transactions and withdrawals from the context. + let body = ctx.build_block_body(); + + // Loop until we get a valid payload from the engine API. On each iteration, + // we build a new block header with the hints from the context and fetch the next hint. + let max_iterations = 20; + let mut iteration = 0; + loop { + debug!(%iteration, "Fetching hint from engine API"); + + // Build a new block header using the hints from the context + let header = ctx.build_block_header_with_hints(); + + let sealed_hash = header.hash_slow(); + let sealed_header = SealedHeader::new(header, sealed_hash); + let sealed_block = SealedBlock::new(sealed_header, body.clone()); + let block_hash = ctx.hints.block_hash.unwrap_or(sealed_block.hash()); + + // build the new execution payload from the block header + let exec_payload = to_alloy_execution_payload(&sealed_block, block_hash); + + // attempt to fetch the next hint from the engine API payload response + let hint = self.next_hint(exec_payload, &ctx).await?; + + if matches!(hint, EngineApiHint::ValidPayload) { + return Ok(sealed_block); + } + + // Populate the new hint in the context and continue the loop + ctx.hints.populate_new(hint); + + iteration += 1; + if iteration >= max_iterations { + return Err(BuilderError::ExceededMaxHintIterations(max_iterations)); + } + } + } + + /// Yield the next hint from the engine API by calling `engine_newPayloadV3` + /// and parsing the response to extract the hint. + /// + /// Returns Ok([EngineApiHint::ValidPayload]) if the payload is valid. + async fn next_hint( + &self, + exec_payload: ExecutionPayloadV3, + ctx: &EngineHinterContext, + ) -> Result { + let payload_status = self + .engine_client + .new_payload_v3( + exec_payload, + ctx.blob_versioned_hashes.clone(), + ctx.parent_beacon_block_root, + ) + .await?; + + let validation_error = match payload_status.status { + PayloadStatusEnum::Valid => return Ok(EngineApiHint::ValidPayload), + PayloadStatusEnum::Invalid { validation_error } => validation_error, + PayloadStatusEnum::Syncing | PayloadStatusEnum::Accepted => { + error!(status = ?payload_status.status, "Unexpected payload status from engine API"); + return Err(BuilderError::UnexpectedPayloadStatus(payload_status.status)) + } + }; + + // Parse the hint from the engine API response, based on the EL client code + let Some(hint) = parse_hint_from_engine_response(ctx.el_client_code, &validation_error)? + else { + return Err(BuilderError::FailedToParseHintsFromEngine); + }; + + Ok(hint) + } +} + +/// Engine API hint values that can be fetched from the engine API +/// to complete the sealed block. These hints are used to fill in +/// missing values in the block header. +#[derive(Debug, Copy, Clone)] +#[allow(clippy::large_enum_variant)] +pub enum EngineApiHint { + BlockHash(B256), + GasUsed(u64), + StateRoot(B256), + ReceiptsRoot(B256), + LogsBloom(Bloom), + ValidPayload, +} + +/// The collection of hints that can be fetched from the engine API +/// via the [EngineHinter] to complete the sealed block. +/// +/// When a field is `None`, we set it to its default value in the [ExecutionPayload] +/// and try to get the hint from the engine API response to fill its value. +#[derive(Debug, Default)] +pub struct Hints { + pub gas_used: Option, + pub receipts_root: Option, + pub logs_bloom: Option, + pub state_root: Option, + pub block_hash: Option, +} + +impl Hints { + /// Populate the new hint value in the context. + pub fn populate_new(&mut self, hint: EngineApiHint) { + match hint { + EngineApiHint::ValidPayload => { /* No-op */ } + + // If we receive a block hash hint, set it and keep it for the next one. + // This should not happen, but in case it does, it doesn't break the flow. + EngineApiHint::BlockHash(hash) => self.block_hash = Some(hash), + + // For regular hint types, set the value and reset the block hash + EngineApiHint::GasUsed(gas) => { + self.gas_used = Some(gas); + self.block_hash = None; + } + EngineApiHint::StateRoot(hash) => { + self.state_root = Some(hash); + self.block_hash = None; + } + EngineApiHint::ReceiptsRoot(hash) => { + self.receipts_root = Some(hash); + self.block_hash = None; + } + EngineApiHint::LogsBloom(bloom) => { + self.logs_bloom = Some(bloom); + self.block_hash = None; + } + } + } +} + +/// Context holding the necessary values for +/// building a sealed block. Some of this data is fetched from the +/// beacon chain, while others are calculated locally or from the +/// transactions themselves. +#[derive(Debug)] +pub struct EngineHinterContext { + pub extra_data: Bytes, + pub base_fee: u64, + pub blob_gas_used: u64, + pub excess_blob_gas: u64, + pub prev_randao: B256, + pub fee_recipient: Address, + pub transactions_root: B256, + pub withdrawals_root: B256, + pub parent_beacon_block_root: B256, + pub blob_versioned_hashes: Vec, + pub block_timestamp: u64, + pub transactions: Vec, + pub withdrawals: Vec, + pub head_block: Block, + pub hints: Hints, + pub el_client_code: ClientCode, +} + +impl EngineHinterContext { + /// Build a block body using the transactions and withdrawals from the context. + pub fn build_block_body(&self) -> BlockBody { + BlockBody { + ommers: Vec::new(), + transactions: self.transactions.clone(), + withdrawals: Some(Withdrawals::new(self.withdrawals.clone())), + } + } + + /// Build a header using the info from the context. + /// Use any hints available, and default to an empty value if not present. + pub fn build_block_header_with_hints(&self) -> RethHeader { + // Use the available hints, or default to an empty value if not present. + let gas_used = self.hints.gas_used.unwrap_or_default(); + let receipts_root = self.hints.receipts_root.unwrap_or_default(); + let logs_bloom = self.hints.logs_bloom.unwrap_or_default(); + let state_root = self.hints.state_root.unwrap_or_default(); + + RethHeader { + parent_hash: self.head_block.header.hash, + ommers_hash: EMPTY_OMMER_ROOT_HASH, + beneficiary: self.fee_recipient, + state_root, + transactions_root: self.transactions_root, + receipts_root, + withdrawals_root: Some(self.withdrawals_root), + logs_bloom, + difficulty: U256::ZERO, + number: self.head_block.header.number + 1, + gas_limit: self.head_block.header.gas_limit, + gas_used, + timestamp: self.block_timestamp, + mix_hash: self.prev_randao, + nonce: B64::ZERO, + base_fee_per_gas: Some(self.base_fee), + blob_gas_used: Some(self.blob_gas_used), + excess_blob_gas: Some(self.excess_blob_gas), + parent_beacon_block_root: Some(self.parent_beacon_block_root), + extra_data: self.extra_data.clone(), + // TODO: handle the Pectra-related fields + requests_hash: None, + target_blobs_per_block: None, + } + } +} diff --git a/bolt-sidecar/src/builder/fallback/engine_hints/geth.rs b/bolt-sidecar/src/builder/fallback/engine_hints/geth.rs new file mode 100644 index 00000000..37bbde57 --- /dev/null +++ b/bolt-sidecar/src/builder/fallback/engine_hints/geth.rs @@ -0,0 +1,52 @@ +use alloy::primitives::{Bloom, B256}; +use hex::FromHex; +use regex::Regex; + +use crate::builder::{fallback::engine_hinter::EngineApiHint, BuilderError}; + +/// Parse a hinted value from the engine response. +/// An example error message from the engine API looks like this: +/// +/// ```json +/// { +/// "jsonrpc": "2.0", +/// "id": 1, +/// "error": { +/// "code":-32000, +/// "message": "local: blockhash mismatch: got 0x... expected 0x..." +/// } +/// } +/// ``` +/// +/// Geth Reference: +/// - [ValidateState]() +/// - [Blockhash Mismatch]() +pub fn parse_geth_engine_error_hint(error: &str) -> Result, BuilderError> { + // Capture either the "local" or "got" value from the error message + let re = Regex::new(r"(?:local:|got) ([0-9a-zA-Z]+)").expect("valid regex"); + + let raw_hint_value = match re.captures(error).and_then(|cap| cap.get(1)) { + Some(matched) => matched.as_str().to_string(), + None => return Ok(None), + }; + + // Match the hint value to the corresponding hint type based on other parts of the error message + if error.contains("blockhash mismatch") { + return Ok(Some(EngineApiHint::BlockHash(B256::from_hex(raw_hint_value)?))); + } else if error.contains("invalid gas used") { + return Ok(Some(EngineApiHint::GasUsed(raw_hint_value.parse()?))); + } else if error.contains("invalid merkle root") { + return Ok(Some(EngineApiHint::StateRoot(B256::from_hex(raw_hint_value)?))); + } else if error.contains("invalid receipt root hash") { + return Ok(Some(EngineApiHint::ReceiptsRoot(B256::from_hex(raw_hint_value)?))); + } else if error.contains("invalid bloom") { + return Ok(Some(EngineApiHint::LogsBloom(Bloom::from_hex(&raw_hint_value)?))); + }; + + // Match some error message that we don't know how to handle + if error.contains("could not apply tx") { + return Err(BuilderError::InvalidTransactions(error.to_string())); + } + + Err(BuilderError::UnsupportedEngineHint(error.to_string())) +} diff --git a/bolt-sidecar/src/builder/fallback/engine_hints/mod.rs b/bolt-sidecar/src/builder/fallback/engine_hints/mod.rs new file mode 100644 index 00000000..52f3ed2d --- /dev/null +++ b/bolt-sidecar/src/builder/fallback/engine_hints/mod.rs @@ -0,0 +1,31 @@ +use alloy_rpc_types_engine::ClientCode; +use tracing::error; + +use crate::builder::BuilderError; + +use super::engine_hinter::EngineApiHint; + +/// Parse engine hints from Geth execution clients. +mod geth; + +/// Parse engine hints from Nethermind execution clients. +mod nethermind; + +/// Tries to parse engine hints from the given execution client and error response. +/// +/// * Returns Ok(None) if no hint could be parsed. +/// * Returns an error if the execution client is not supported. +pub fn parse_hint_from_engine_response( + client: ClientCode, + error: &str, +) -> Result, BuilderError> { + match client { + ClientCode::GE => geth::parse_geth_engine_error_hint(error), + // TODO: Add Nethermind engine hints parsing + // ClientCode::NM => nethermind::parse_nethermind_engine_error_hint(error), + _ => { + error!("Unsupported fallback execution client: {}", client.client_name()); + Err(BuilderError::UnsupportedEngineClient(client)) + } + } +} diff --git a/bolt-sidecar/src/builder/fallback/engine_hints/nethermind.rs b/bolt-sidecar/src/builder/fallback/engine_hints/nethermind.rs new file mode 100644 index 00000000..a83da548 --- /dev/null +++ b/bolt-sidecar/src/builder/fallback/engine_hints/nethermind.rs @@ -0,0 +1,27 @@ +use tracing::warn; + +use crate::builder::{fallback::engine_hinter::EngineApiHint, BuilderError}; + +/// Parse a hinted value from the engine response. +/// An example error message from the engine API looks like this: +/// +/// ```json +/// { +/// "jsonrpc": "2.0", +/// "id": 1, +/// "error": { +/// "code":-32000, +/// "message": "local: blockhash mismatch: got 0x... expected 0x..." +/// } +/// } +/// ``` +// TODO: implement hints parsing +// TODO: remove dead_code attribute +#[allow(dead_code)] +pub fn parse_nethermind_engine_error_hint( + error: &str, +) -> Result, BuilderError> { + warn!(%error, "Nethermind engine error hint parsing is not implemented"); + + Ok(None) +} diff --git a/bolt-sidecar/src/builder/fallback/mod.rs b/bolt-sidecar/src/builder/fallback/mod.rs new file mode 100644 index 00000000..912484fc --- /dev/null +++ b/bolt-sidecar/src/builder/fallback/mod.rs @@ -0,0 +1,18 @@ +/// Fallback block builder for when the PBS stack doesn't yield a valid block. +pub mod payload_builder; +pub use payload_builder::FallbackPayloadBuilder; + +/// Engine hinter for parsing hints from execution clients engine API responses. +mod engine_hinter; +pub use engine_hinter::EngineHinter; + +/// Utilities for parsing engine hints from different execution clients types. +mod engine_hints; + +/// Extra-data payload field used for locally built blocks, decoded in UTF-8. +/// +/// Corresponds to the string "Self-built with Bolt". It can be max 32 bytes +pub const DEFAULT_EXTRA_DATA: [u8; 20] = [ + 0x53, 0x65, 0x6c, 0x66, 0x2d, 0x62, 0x75, 0x69, 0x6c, 0x74, 0x20, 0x77, 0x69, 0x74, 0x68, 0x20, + 0x42, 0x6f, 0x6c, 0x74, +]; diff --git a/bolt-sidecar/src/builder/fallback/payload_builder.rs b/bolt-sidecar/src/builder/fallback/payload_builder.rs new file mode 100644 index 00000000..a5995154 --- /dev/null +++ b/bolt-sidecar/src/builder/fallback/payload_builder.rs @@ -0,0 +1,215 @@ +use alloy::{ + consensus::Transaction, + eips::{calc_excess_blob_gas, calc_next_block_base_fee, eip1559::BaseFeeParams}, + primitives::{Address, Bytes}, +}; +use reth_primitives::{proofs, SealedBlock, TransactionSigned}; +use tracing::debug; + +use super::{ + engine_hinter::{EngineHinter, EngineHinterContext}, + DEFAULT_EXTRA_DATA, +}; +use crate::{ + builder::BuilderError, + client::{BeaconClient, ExecutionClient}, + config::Opts, +}; + +/// The fallback payload builder is responsible for assembling a valid +/// sealed block from a set of transactions. It (ab)uses the engine API +/// to fetch "hints" for missing header values, such as the block hash, +/// gas used, state root, etc. +/// +/// The builder will keep querying the engine API until it has all the +/// necessary values to seal the block. This is a temporary solution +/// until the engine API is able to provide a full sealed block. +/// +/// Find more information about this process & its reasoning here: +/// +#[derive(Debug)] +pub struct FallbackPayloadBuilder { + extra_data: Bytes, + fee_recipient: Address, + beacon_api: BeaconClient, + execution_api: ExecutionClient, + engine_hinter: EngineHinter, + slot_time: u64, + genesis_time: u64, +} + +impl FallbackPayloadBuilder { + /// Create a new fallback payload builder + pub fn new(opts: &Opts, genesis_time: u64) -> Self { + let engine_hinter = EngineHinter::new(opts.engine_jwt_hex.0, opts.engine_api_url.clone()); + + let beacon_api = BeaconClient::new(opts.beacon_api_url.clone()); + let execution_api = ExecutionClient::new(opts.execution_api_url.clone()); + + Self { + extra_data: DEFAULT_EXTRA_DATA.into(), + fee_recipient: opts.fee_recipient, + slot_time: opts.chain.slot_time(), + engine_hinter, + execution_api, + genesis_time, + beacon_api, + } + } + + /// Build a minimal payload to be used as a fallback in case PBS relays fail + /// to provide a valid payload that fulfills the commitments made by Bolt. + pub async fn build_fallback_payload( + &self, + target_slot: u64, + transactions: &[TransactionSigned], + ) -> Result { + // Fetch the latest block to get the necessary parent values for the new block. + // For the timestamp, we must use the one expected by the beacon chain instead, to + // prevent edge cases where the proposer before us has missed their slot and therefore + // the timestamp of the previous block is too far in the past. + let head_block_fut = self.execution_api.get_block(None, true); + + // Fetch the execution client info from the engine API in order to know what hint + // types the engine hinter can parse from the engine API responses. + let el_client_info_fut = self.engine_hinter.engine_client_version(); + + let (head_block, el_client_info) = tokio::try_join!(head_block_fut, el_client_info_fut)?; + + let el_client_code = el_client_info[0].code; + debug!(client = %el_client_code.client_name(), "Fetched execution client info"); + + // Fetch required head info from the beacon client + let parent_beacon_block_root_fut = self.beacon_api.get_parent_beacon_block_root(); + let withdrawals_fut = self.beacon_api.get_expected_withdrawals_at_head(); + let prev_randao_fut = self.beacon_api.get_prev_randao(); + + let (parent_beacon_block_root, withdrawals, prev_randao) = + tokio::try_join!(parent_beacon_block_root_fut, withdrawals_fut, prev_randao_fut)?; + + // The next block timestamp must be calculated manually rather than relying on the + // previous execution block, to cover the edge case where any previous slots have + // been missed by the proposers immediately before us. + let block_timestamp = self.genesis_time + (target_slot * self.slot_time); + + let blob_versioned_hashes = transactions + .iter() + .flat_map(|tx| tx.blob_versioned_hashes()) + .flatten() + .copied() + .collect::>(); + + let base_fee = calc_next_block_base_fee( + head_block.header.gas_used, + head_block.header.gas_limit, + head_block.header.base_fee_per_gas.unwrap_or_default(), + BaseFeeParams::ethereum(), + ); + + let excess_blob_gas = calc_excess_blob_gas( + head_block.header.excess_blob_gas.unwrap_or_default(), + head_block.header.blob_gas_used.unwrap_or_default(), + ); + + let blob_gas_used = + transactions.iter().fold(0, |acc, tx| acc + tx.blob_gas_used().unwrap_or_default()); + + let ctx = EngineHinterContext { + base_fee, + blob_gas_used, + excess_blob_gas, + parent_beacon_block_root, + prev_randao, + extra_data: self.extra_data.clone(), + fee_recipient: self.fee_recipient, + transactions_root: proofs::calculate_transaction_root(transactions), + withdrawals_root: proofs::calculate_withdrawals_root(&withdrawals), + transactions: transactions.to_vec(), + blob_versioned_hashes, + block_timestamp, + withdrawals, + head_block, + el_client_code, + // start the context with empty hints + hints: Default::default(), + }; + + // Use the engine API to fetch the missing value for the payload, until we have + // all the necessary data to consider it valid and seal the block. + self.engine_hinter.fetch_payload_from_hints(ctx).await + } +} + +#[cfg(test)] +mod tests { + use std::time::{SystemTime, UNIX_EPOCH}; + + use alloy::{ + eips::eip2718::{Decodable2718, Encodable2718}, + network::{EthereumWallet, TransactionBuilder}, + primitives::{hex, Address}, + providers::{Provider, ProviderBuilder}, + signers::{k256::ecdsa::SigningKey, local::PrivateKeySigner}, + }; + use beacon_api_client::mainnet::Client as BeaconClient; + use reth_primitives::TransactionSigned; + use tracing::warn; + + use crate::{ + builder::FallbackPayloadBuilder, + test_util::{default_test_transaction, get_test_config}, + }; + + #[tokio::test] + async fn test_build_fallback_payload() -> eyre::Result<()> { + if tracing_subscriber::fmt::try_init().is_err() { + eprintln!("Failed to initialize logger"); + }; + + let Some(mut cfg) = get_test_config().await else { + warn!("Skipping test: missing test config"); + return Ok(()); + }; + + // Set the engine to either geth or nethermind + // ge: remotesmol:48551, nm: remotesmol:58551 + cfg.engine_api_url = "http://remotesmol:58551".parse()?; + + let raw_sk = std::env::var("PRIVATE_KEY")?; + + let provider = ProviderBuilder::new().on_http(cfg.execution_api_url.clone()); + let beacon_client = BeaconClient::new(cfg.beacon_api_url.clone()); + let genesis_time = beacon_client.get_genesis_details().await?.genesis_time; + let builder = FallbackPayloadBuilder::new(&cfg, genesis_time); + + let sk = SigningKey::from_slice(hex::decode(raw_sk)?.as_slice())?; + let signer = PrivateKeySigner::from_signing_key(sk.clone()); + let wallet = EthereumWallet::from(signer); + + let addy = Address::from_private_key(&sk); + let nonce = provider.get_transaction_count(addy).await?; + let tx = default_test_transaction(addy, Some(nonce)).with_chain_id(17000); + let tx_signed = tx.build(&wallet).await?; + let raw_encoded = tx_signed.encoded_2718(); + let tx_signed_reth = TransactionSigned::decode_2718(&mut raw_encoded.as_slice())?; + + let slot = genesis_time + + (SystemTime::now().duration_since(UNIX_EPOCH)?.as_secs() / cfg.chain.slot_time()) + + 1; + + let block = builder.build_fallback_payload(slot, &[tx_signed_reth]).await?; + + assert_eq!(block.body.transactions.len(), 1); + + Ok(()) + } + + #[test] + fn test_empty_el_withdrawals_root() { + // Withdrawal root in the execution layer header is MPT. + assert_eq!( + reth_primitives::proofs::calculate_withdrawals_root(&Vec::new()), + alloy::consensus::constants::EMPTY_WITHDRAWALS + ); + } +} diff --git a/bolt-sidecar/src/builder/mod.rs b/bolt-sidecar/src/builder/mod.rs index 410e1ba3..c0c433b4 100644 --- a/bolt-sidecar/src/builder/mod.rs +++ b/bolt-sidecar/src/builder/mod.rs @@ -1,5 +1,5 @@ use alloy::primitives::U256; -use beacon_api_client::mainnet::Client as BeaconClient; +use alloy_rpc_types_engine::{ClientCode, PayloadStatusEnum}; use ethereum_consensus::{ crypto::{KzgCommitment, PublicKey}, deneb::mainnet::ExecutionPayloadHeader, @@ -14,6 +14,11 @@ use crate::{ }, }; +/// Fallback payload building logic that (ab)uses the engine API's +/// `engine_newPayloadV3` response error to produce a valid payload. +pub mod fallback; +pub use fallback::FallbackPayloadBuilder; + /// Basic block template handler that can keep track of /// the local commitments according to protocol validity rules. /// @@ -26,11 +31,6 @@ pub use template::BlockTemplate; pub mod signature; use signature::sign_builder_message; -/// Fallback Payload builder agent that leverages the engine API's -/// `engine_newPayloadV3` response error to produce a valid payload. -pub mod payload_builder; -use payload_builder::FallbackPayloadBuilder; - /// Interface for fetching payloads from the beacon node. pub mod payload_fetcher; pub use payload_fetcher::{LocalPayloadFetcher, PayloadFetcher}; @@ -58,12 +58,22 @@ pub enum BuilderError { Transport(#[from] alloy::transports::TransportError), #[error("Failed in SSZ merkleization: {0}")] Merkleization(#[from] MerkleizationError), - #[error("Failed while interacting with beacon client: {0}")] - BeaconApi(#[from] beacon_api_client::Error), #[error("Failed to parse hint from engine response: {0}")] InvalidEngineHint(String), - #[error("Failed to build payload: {0}")] - Custom(String), + #[error("Beacon API error: {0}")] + BeaconApi(#[from] crate::client::beacon::BeaconClientError), + #[error("Failed to build payload due to invalid transactions: {0}")] + InvalidTransactions(String), + #[error("Got an unexpected response from engine_newPayload query: {0}")] + UnexpectedPayloadStatus(PayloadStatusEnum), + #[error("Failed to parse any hints from engine API validation error")] + FailedToParseHintsFromEngine, + #[error("Unsupported engine hint: {0}")] + UnsupportedEngineHint(String), + #[error("Unsupported engine client: {0}")] + UnsupportedEngineClient(ClientCode), + #[error("Failed to gather hints after {0} iterations")] + ExceededMaxHintIterations(u64), } /// Local builder instance that can ingest a sealed header and @@ -85,10 +95,10 @@ pub struct LocalBuilder { impl LocalBuilder { /// Create a new local builder with the given secret key. - pub fn new(opts: &Opts, beacon_api_client: BeaconClient, genesis_time: u64) -> Self { + pub fn new(opts: &Opts, genesis_time: u64) -> Self { Self { payload_and_bid: None, - fallback_builder: FallbackPayloadBuilder::new(opts, beacon_api_client, genesis_time), + fallback_builder: FallbackPayloadBuilder::new(opts, genesis_time), secret_key: opts.builder_private_key.clone(), chain: opts.chain, } @@ -150,12 +160,11 @@ impl LocalBuilder { blob_kzg_commitments: Vec, ) -> Result { // compat: convert from blst to ethereum consensus types - let pubkey = self.secret_key.sk_to_pk().to_bytes(); - let consensus_pubkey = PublicKey::try_from(pubkey.as_slice()).expect("valid pubkey bytes"); + let public_key = self.secret_key.sk_to_pk().to_bytes(); + let public_key = PublicKey::try_from(public_key.as_ref()).expect("valid public key"); let blob_kzg_commitments = List::try_from(blob_kzg_commitments).expect("valid list"); - let message = - BuilderBid { header, blob_kzg_commitments, public_key: consensus_pubkey, value }; + let message = BuilderBid { header, blob_kzg_commitments, public_key, value }; let signature = sign_builder_message(&self.chain, &self.secret_key, &message)?; diff --git a/bolt-sidecar/src/builder/payload_builder.rs b/bolt-sidecar/src/builder/payload_builder.rs deleted file mode 100644 index 0b4aeb85..00000000 --- a/bolt-sidecar/src/builder/payload_builder.rs +++ /dev/null @@ -1,498 +0,0 @@ -use std::{ - fmt, - time::{Duration, SystemTime, UNIX_EPOCH}, -}; - -use alloy::{ - consensus::{Header, Transaction, EMPTY_OMMER_ROOT_HASH}, - eips::{calc_excess_blob_gas, calc_next_block_base_fee, eip1559::BaseFeeParams}, - primitives::{Address, Bloom, Bytes, B256, B64, U256}, - rpc::types::{Block, Withdrawal, Withdrawals}, -}; -use alloy_rpc_types_engine::{Claims, ExecutionPayload, JwtSecret}; -use axum::http::HeaderValue; -use beacon_api_client::{BlockId, StateId}; -use hex::FromHex; -use regex::Regex; -use reqwest::Url; -use reth_primitives::{proofs, BlockBody, SealedBlock, SealedHeader, TransactionSigned}; -use serde_json::Value; -use tracing::trace; - -use super::{ - compat::{to_alloy_execution_payload, to_alloy_withdrawal}, - BuilderError, -}; - -use crate::{ - client::{BeaconClient, RpcClient}, - config::Opts, -}; - -/// Extra-data payload field used for locally built blocks, decoded in UTF-8. -/// -/// Corresponds to the string "Self-built with Bolt". It can be max 32 bytes -const DEFAULT_EXTRA_DATA: [u8; 20] = [ - 0x53, 0x65, 0x6c, 0x66, 0x2d, 0x62, 0x75, 0x69, 0x6c, 0x74, 0x20, 0x77, 0x69, 0x74, 0x68, 0x20, - 0x42, 0x6f, 0x6c, 0x74, -]; - -/// The fallback payload builder is responsible for assembling a valid -/// sealed block from a set of transactions. It (ab)uses the engine API -/// to fetch "hints" for missing header values, such as the block hash, -/// gas used, state root, etc. -/// -/// The builder will keep querying the engine API until it has all the -/// necessary values to seal the block. This is a temporary solution -/// until the engine API is able to provide a full sealed block. -/// -/// Find more information about this process & its reasoning here: -/// -pub struct FallbackPayloadBuilder { - extra_data: Bytes, - fee_recipient: Address, - beacon_api_client: BeaconClient, - execution_rpc_client: RpcClient, - engine_hinter: EngineHinter, - slot_time: u64, - genesis_time: u64, -} - -impl FallbackPayloadBuilder { - /// Create a new fallback payload builder - pub fn new(config: &Opts, beacon_api_client: BeaconClient, genesis_time: u64) -> Self { - let engine_hinter = EngineHinter { - client: reqwest::Client::new(), - jwt_hex: config.engine_jwt_hex.to_string(), - engine_rpc_url: config.engine_api_url.clone(), - }; - - Self { - engine_hinter, - extra_data: DEFAULT_EXTRA_DATA.into(), - fee_recipient: config.fee_recipient, - execution_rpc_client: RpcClient::new(config.execution_api_url.clone()), - slot_time: config.chain.slot_time(), - genesis_time, - beacon_api_client, - } - } -} - -/// Lightweight context struct to hold the necessary values for -/// building a sealed block. Some of this data is fetched from the -/// beacon chain, while others are calculated locally or from the -/// transactions themselves. -#[derive(Debug, Default)] -struct Context { - extra_data: Bytes, - base_fee: u64, - blob_gas_used: u64, - excess_blob_gas: u64, - prev_randao: B256, - fee_recipient: Address, - transactions_root: B256, - withdrawals_root: B256, - parent_beacon_block_root: B256, - block_timestamp: u64, -} - -#[derive(Debug, Default)] -struct Hints { - pub gas_used: Option, - pub receipts_root: Option, - pub logs_bloom: Option, - pub state_root: Option, - pub block_hash: Option, -} - -impl FallbackPayloadBuilder { - /// Build a minimal payload to be used as a fallback in case PBS relays fail - /// to provide a valid payload that fulfills the commitments made by Bolt. - pub async fn build_fallback_payload( - &self, - target_slot: u64, - transactions: &[TransactionSigned], - ) -> Result { - // We fetch the latest block to get the necessary parent values for the new block. - // For the timestamp, we must use the one expected by the beacon chain instead, to - // prevent edge cases where the proposer before us has missed their slot. - let latest_block = self.execution_rpc_client.get_block(None, true).await?; - - let withdrawals = self.get_expected_withdrawals_at_head().await?; - - let prev_randao = self.get_prev_randao().await?; - - let parent_beacon_block_root = B256::from_slice( - // TODO: compat: as_slice() from_slice() is necessary until we bump ethereum-consensus - // version to match alloy's. - self.beacon_api_client.get_beacon_block_root(BlockId::Head).await?.as_slice(), - ); - - let versioned_hashes = transactions - .iter() - .flat_map(|tx| tx.blob_versioned_hashes()) - .flatten() - .copied() - .collect::>(); - - let base_fee = calc_next_block_base_fee( - latest_block.header.gas_used, - latest_block.header.gas_limit, - latest_block.header.base_fee_per_gas.unwrap_or_default(), - BaseFeeParams::ethereum(), - ); - - let excess_blob_gas = calc_excess_blob_gas( - latest_block.header.excess_blob_gas.unwrap_or_default(), - latest_block.header.blob_gas_used.unwrap_or_default(), - ); - - let blob_gas_used = - transactions.iter().fold(0, |acc, tx| acc + tx.blob_gas_used().unwrap_or_default()); - - // We must calculate the next block timestamp manually rather than rely on the - // previous execution block, to cover the edge case where any previous slots have - // been missed by the proposers immediately before us. - let block_timestamp = self.genesis_time + (target_slot * self.slot_time); - - let ctx = Context { - base_fee, - blob_gas_used, - excess_blob_gas, - parent_beacon_block_root, - prev_randao, - extra_data: self.extra_data.clone(), - fee_recipient: self.fee_recipient, - transactions_root: proofs::calculate_transaction_root(transactions), - withdrawals_root: proofs::calculate_withdrawals_root(&withdrawals), - block_timestamp, - }; - - let body = BlockBody { - ommers: Vec::new(), - transactions: transactions.to_vec(), - withdrawals: Some(Withdrawals::new(withdrawals)), - }; - - let mut hints = Hints::default(); - let max_iterations = 20; - let mut i = 0; - loop { - let header = build_header_with_hints_and_context(&latest_block, &hints, &ctx); - - let sealed_hash = header.hash_slow(); - let sealed_header = SealedHeader::new(header, sealed_hash); - let sealed_block = SealedBlock::new(sealed_header, body.clone()); - - let block_hash = hints.block_hash.unwrap_or(sealed_block.hash()); - - let exec_payload = to_alloy_execution_payload(&sealed_block, block_hash); - - let engine_hint = self - .engine_hinter - .fetch_next_payload_hint(&exec_payload, &versioned_hashes, parent_beacon_block_root) - .await?; - - match engine_hint { - EngineApiHint::BlockHash(hash) => { - trace!("Should not receive block hash hint {:?}", hash); - hints.block_hash = Some(hash) - } - - EngineApiHint::GasUsed(gas) => { - hints.gas_used = Some(gas); - hints.block_hash = None; - } - EngineApiHint::StateRoot(hash) => { - hints.state_root = Some(hash); - hints.block_hash = None - } - EngineApiHint::ReceiptsRoot(hash) => { - hints.receipts_root = Some(hash); - hints.block_hash = None - } - EngineApiHint::LogsBloom(bloom) => { - hints.logs_bloom = Some(bloom); - hints.block_hash = None - } - - EngineApiHint::ValidPayload => return Ok(sealed_block), - } - - if i > max_iterations { - return Err(BuilderError::Custom( - "Too many iterations: Failed to fetch all missing header values from geth error messages" - .to_string(), - )); - } - - i += 1; - } - } - - /// Fetch the previous RANDAO value from the beacon chain. - /// - /// NOTE: for some reason, using the ApiResult from `beacon_api_client` doesn't work, so - /// we are making a direct request to the beacon client endpoint. - async fn get_prev_randao(&self) -> Result { - let url = self - .beacon_api_client - .endpoint - .join("/eth/v1/beacon/states/head/randao") - .map_err(|e| BuilderError::Custom(format!("Failed to join URL: {e:?}")))?; - - reqwest::Client::new() - .get(url) - .send() - .await? - .json::() - .await? - .pointer("/data/randao") - .and_then(|value| value.as_str()) - .map(|value| B256::from_hex(value).map_err(BuilderError::Hex)) - .ok_or_else(|| BuilderError::Custom("Failed to fetch prev_randao".to_string()))? - } - - /// Fetch the expected withdrawals for the given slot from the beacon chain. - async fn get_expected_withdrawals_at_head(&self) -> Result, BuilderError> { - Ok(self - .beacon_api_client - .get_expected_withdrawals(StateId::Head, None) - .await? - .into_iter() - .map(to_alloy_withdrawal) - .collect::>()) - } -} - -/// Engine API hint values that can be fetched from the engine API -/// to complete the sealed block. These hints are used to fill in -/// missing values in the block header. -#[derive(Debug)] -#[allow(clippy::large_enum_variant)] -pub(crate) enum EngineApiHint { - BlockHash(B256), - GasUsed(u64), - StateRoot(B256), - ReceiptsRoot(B256), - LogsBloom(Bloom), - ValidPayload, -} - -/// Engine hinter struct that is responsible for fetching hints from the -/// engine API to complete the sealed block. This struct is used by the -/// fallback payload builder to fetch missing header values. -#[derive(Debug)] -pub(crate) struct EngineHinter { - client: reqwest::Client, - jwt_hex: String, - engine_rpc_url: Url, -} - -impl EngineHinter { - /// Fetch the next payload hint from the engine API to complete the sealed block. - pub async fn fetch_next_payload_hint( - &self, - exec_payload: &ExecutionPayload, - versioned_hashes: &[B256], - parent_beacon_root: B256, - ) -> Result { - let auth_jwt = secret_to_bearer_header(&JwtSecret::from_hex(&self.jwt_hex)?); - - let body = format!( - r#"{{"id":1,"jsonrpc":"2.0","method":"engine_newPayloadV3","params":[{}, {}, "{:?}"]}}"#, - serde_json::to_string(&exec_payload)?, - serde_json::to_string(&versioned_hashes)?, - parent_beacon_root - ); - - let raw_hint = self - .client - .post(self.engine_rpc_url.as_str()) - .header("Content-Type", "application/json") - .header("Authorization", auth_jwt.clone()) - .body(body) - .send() - .await? - .text() - .await?; - - let Some(hint_value) = parse_geth_response(&raw_hint) else { - // If the hint is not found, it means that we likely got a VALID - // payload response or an error message that we can't parse. - if raw_hint.contains("\"status\":\"VALID\"") { - return Ok(EngineApiHint::ValidPayload); - } - return Err(BuilderError::InvalidEngineHint(raw_hint)); - }; - - trace!("engine hint: {:?}", raw_hint); - - // Match the hint value to the corresponding header field and return it - if raw_hint.contains("blockhash mismatch") { - return Ok(EngineApiHint::BlockHash(B256::from_hex(hint_value)?)); - } else if raw_hint.contains("invalid gas used") { - return Ok(EngineApiHint::GasUsed(hint_value.parse()?)); - } else if raw_hint.contains("invalid merkle root") { - return Ok(EngineApiHint::StateRoot(B256::from_hex(hint_value)?)); - } else if raw_hint.contains("invalid receipt root hash") { - return Ok(EngineApiHint::ReceiptsRoot(B256::from_hex(hint_value)?)); - } else if raw_hint.contains("invalid bloom") { - return Ok(EngineApiHint::LogsBloom(Bloom::from_hex(&hint_value)?)); - }; - - Err(BuilderError::Custom( - "Unexpected: failed to parse any hint from engine response".to_string(), - )) - } -} - -/// Parse the hint value from the engine response. -/// An example error message from the engine API looks like this: -/// ```text -/// {"jsonrpc":"2.0","id":1,"error":{"code":-32000,"message":"local: blockhash mismatch: got 0x... expected 0x..."}} -/// ``` -/// -/// Geth Reference: -/// - [ValidateState]() -/// - [Blockhash Mismatch]() -pub(crate) fn parse_geth_response(error: &str) -> Option { - // Capture either the "local" or "got" value from the error message - let re = Regex::new(r"(?:local:|got) ([0-9a-zA-Z]+)").expect("valid regex"); - - re.captures(error) - .and_then(|capture| capture.get(1).map(|matched| matched.as_str().to_string())) -} - -/// Build a header with the given hints and context values. -fn build_header_with_hints_and_context( - latest_block: &Block, - hints: &Hints, - context: &Context, -) -> Header { - // Use the available hints, or default to an empty value if not present. - let gas_used = hints.gas_used.unwrap_or_default(); - let receipts_root = hints.receipts_root.unwrap_or_default(); - let logs_bloom = hints.logs_bloom.unwrap_or_default(); - let state_root = hints.state_root.unwrap_or_default(); - - Header { - parent_hash: latest_block.header.hash, - ommers_hash: EMPTY_OMMER_ROOT_HASH, - beneficiary: context.fee_recipient, - state_root, - transactions_root: context.transactions_root, - receipts_root, - withdrawals_root: Some(context.withdrawals_root), - logs_bloom, - difficulty: U256::ZERO, - number: latest_block.header.number + 1, - gas_limit: latest_block.header.gas_limit, - gas_used, - timestamp: context.block_timestamp, - mix_hash: context.prev_randao, - nonce: B64::ZERO, - base_fee_per_gas: Some(context.base_fee), - blob_gas_used: Some(context.blob_gas_used), - excess_blob_gas: Some(context.excess_blob_gas), - parent_beacon_block_root: Some(context.parent_beacon_block_root), - extra_data: context.extra_data.clone(), - // TODO: handle the Pectra-related fields - requests_hash: None, - target_blobs_per_block: None, - } -} - -/// Helper function to convert a secret into a Bearer auth header value with claims according to -/// . -/// The token is valid for 60 seconds. -pub fn secret_to_bearer_header(secret: &JwtSecret) -> HeaderValue { - format!( - "Bearer {}", - secret - .encode(&Claims { - iat: (SystemTime::now().duration_since(UNIX_EPOCH).unwrap() + - Duration::from_secs(60)) - .as_secs(), - exp: None, - }) - .unwrap() - ) - .parse() - .unwrap() -} - -impl fmt::Debug for FallbackPayloadBuilder { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - f.debug_struct("FallbackPayloadBuilder") - .field("extra_data", &self.extra_data) - .field("fee_recipient", &self.fee_recipient) - .field("engine_hinter", &self.engine_hinter) - .finish() - } -} - -#[cfg(test)] -mod tests { - use std::time::{SystemTime, UNIX_EPOCH}; - - use alloy::{ - eips::eip2718::{Decodable2718, Encodable2718}, - network::{EthereumWallet, TransactionBuilder}, - primitives::{hex, Address}, - signers::{k256::ecdsa::SigningKey, local::PrivateKeySigner}, - }; - use beacon_api_client::mainnet::Client as BeaconClient; - use reth_primitives::TransactionSigned; - use tracing::warn; - - use crate::{ - builder::payload_builder::FallbackPayloadBuilder, - test_util::{default_test_transaction, get_test_config}, - }; - - #[tokio::test] - async fn test_build_fallback_payload() -> eyre::Result<()> { - let _ = tracing_subscriber::fmt::try_init(); - - let Some(cfg) = get_test_config().await else { - warn!("Skipping test: missing test config"); - return Ok(()); - }; - - let raw_sk = std::env::var("PRIVATE_KEY")?; - - let beacon_client = BeaconClient::new(cfg.beacon_api_url.clone()); - let genesis_time = beacon_client.get_genesis_details().await?.genesis_time; - let builder = FallbackPayloadBuilder::new(&cfg, beacon_client, genesis_time); - - let sk = SigningKey::from_slice(hex::decode(raw_sk)?.as_slice())?; - let signer = PrivateKeySigner::from_signing_key(sk.clone()); - let wallet = EthereumWallet::from(signer); - - let addy = Address::from_private_key(&sk); - let tx = default_test_transaction(addy, Some(3)).with_chain_id(1); - let tx_signed = tx.build(&wallet).await?; - let raw_encoded = tx_signed.encoded_2718(); - let tx_signed_reth = TransactionSigned::decode_2718(&mut raw_encoded.as_slice())?; - - let slot = genesis_time + - (SystemTime::now().duration_since(UNIX_EPOCH)?.as_secs() / cfg.chain.slot_time()) + - 1; - - let block = builder.build_fallback_payload(slot, &[tx_signed_reth]).await?; - assert_eq!(block.body.transactions.len(), 1); - - Ok(()) - } - - #[test] - fn test_empty_el_withdrawals_root() { - // Withdrawal root in the execution layer header is MPT. - assert_eq!( - reth_primitives::proofs::calculate_withdrawals_root(&Vec::new()), - alloy::consensus::constants::EMPTY_WITHDRAWALS - ); - } -} diff --git a/bolt-sidecar/src/client/beacon.rs b/bolt-sidecar/src/client/beacon.rs new file mode 100644 index 00000000..e37f5cc8 --- /dev/null +++ b/bolt-sidecar/src/client/beacon.rs @@ -0,0 +1,169 @@ +use std::{fmt::Debug, ops::Deref}; + +use alloy::{ + primitives::{Address, B256}, + rpc::types::Withdrawal, +}; +use beacon_api_client::{BlockId, StateId}; +use reqwest::Url; +use serde::{Deserialize, Serialize}; + +/// Errors that can occur while interacting with the beacon API. +#[derive(Debug, thiserror::Error)] +#[allow(missing_docs)] +pub enum BeaconClientError { + #[error("Failed to fetch: {0}")] + Reqwest(#[from] reqwest::Error), + #[error("Failed to decode: {0}")] + Serde(#[from] serde_json::Error), + #[error("Failed to parse hex: {0}")] + Hex(#[from] hex::FromHexError), + #[error("Failed to parse int: {0}")] + ParseInt(#[from] std::num::ParseIntError), + #[error("Data not found: {0}")] + DataNotFound(String), + #[error("Beacon API inner error: {0}")] + Inner(#[from] beacon_api_client::Error), + #[error("Failed to parse or build URL")] + Url, +} + +pub type BeaconClientResult = Result; + +/// The [BeaconApi] is responsible for fetching information from the beacon node. +/// +/// Unfortunately, we cannot rely solely on [beacon_api_client::Client] because its types +/// sometimes fail to deserialize and they don't allow for custom error handling +/// which is crucial for this service. +/// +/// For this reason, this struct is essentially a wrapper around [beacon_api_client::Client] +/// with added custom error handling and methods. +#[derive(Clone)] +pub struct BeaconClient { + client: reqwest::Client, + beacon_rpc_url: Url, + + // Inner client re-exported from the beacon_api_client crate. + // By wrapping this, we can automatically use its existing methods + // by dereferencing it. This allows us to extend its API. + inner: beacon_api_client::mainnet::Client, +} + +impl Deref for BeaconClient { + type Target = beacon_api_client::mainnet::Client; + + fn deref(&self) -> &Self::Target { + &self.inner + } +} + +impl BeaconClient { + /// Create a new [BeaconClient] instance with the given beacon RPC URL. + pub fn new(beacon_rpc_url: Url) -> Self { + let inner = beacon_api_client::mainnet::Client::new(beacon_rpc_url.clone()); + Self { client: reqwest::Client::new(), beacon_rpc_url, inner } + } + + /// Fetch the previous RANDAO value from the beacon node. + pub async fn get_prev_randao(&self) -> BeaconClientResult { + // NOTE: The beacon_api_client crate method for this doesn't always work, + // so we implement it manually here. + + let url = self + .beacon_rpc_url + .join("/eth/v1/beacon/states/head/randao") + .map_err(|_| BeaconClientError::Url)?; + + #[derive(Deserialize)] + struct Inner { + randao: B256, + } + + // parse from /data/randao + Ok(self.client.get(url).send().await?.json::>().await?.data.randao) + } + + /// Fetch the expected withdrawals for the given slot from the beacon chain. + /// + /// This function also maps the return type into [alloy::rpc::types::Withdrawal]s. + pub async fn get_expected_withdrawals_at_head(&self) -> BeaconClientResult> { + let res = self.inner.get_expected_withdrawals(StateId::Head, None).await?; + + let mut withdrawals = Vec::with_capacity(res.len()); + for w in res { + withdrawals.push(Withdrawal { + index: w.index as u64, + validator_index: w.validator_index as u64, + amount: w.amount, + address: Address::from_slice(w.address.as_slice()), + }); + } + + Ok(withdrawals) + } + + /// Fetch the parent beacon block root from the beacon chain. + pub async fn get_parent_beacon_block_root(&self) -> BeaconClientResult { + let res = self.inner.get_beacon_block_root(BlockId::Head).await?; + Ok(B256::from_slice(res.as_slice())) + } +} + +#[derive(Debug, Serialize, Deserialize)] +struct ResponseData { + pub data: T, +} + +impl Debug for BeaconClient { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + f.debug_struct("BeaconClient").field("beacon_rpc_url", &self.beacon_rpc_url).finish() + } +} + +#[cfg(test)] +mod tests { + use super::*; + use std::str::FromStr; + + #[tokio::test] + async fn test_get_prev_randao() { + let url = Url::from_str("http://remotebeast:44400").unwrap(); + + if reqwest::get(url.clone()).await.is_err_and(|err| err.is_timeout() || err.is_connect()) { + eprintln!("Skipping test because remotebeast is not reachable"); + return; + } + + let beacon_api = BeaconClient::new(url); + + assert!(beacon_api.get_prev_randao().await.is_ok()); + } + + #[tokio::test] + async fn test_get_expected_withdrawals_at_head() { + let url = Url::from_str("http://remotebeast:44400").unwrap(); + + if reqwest::get(url.clone()).await.is_err_and(|err| err.is_timeout() || err.is_connect()) { + eprintln!("Skipping test because remotebeast is not reachable"); + return; + } + + let beacon_api = BeaconClient::new(url); + + assert!(beacon_api.get_expected_withdrawals_at_head().await.is_ok()); + } + + #[tokio::test] + async fn test_get_parent_beacon_block_root() { + let url = Url::from_str("http://remotebeast:44400").unwrap(); + + if reqwest::get(url.clone()).await.is_err_and(|err| err.is_timeout() || err.is_connect()) { + eprintln!("Skipping test because remotebeast is not reachable"); + return; + } + + let beacon_api = BeaconClient::new(url); + + assert!(beacon_api.get_parent_beacon_block_root().await.is_ok()); + } +} diff --git a/bolt-sidecar/src/client/constraints_client.rs b/bolt-sidecar/src/client/constraints.rs similarity index 100% rename from bolt-sidecar/src/client/constraints_client.rs rename to bolt-sidecar/src/client/constraints.rs diff --git a/bolt-sidecar/src/client/engine.rs b/bolt-sidecar/src/client/engine.rs new file mode 100644 index 00000000..fcb339f7 --- /dev/null +++ b/bolt-sidecar/src/client/engine.rs @@ -0,0 +1,69 @@ +use std::ops::Deref; + +use alloy::{ + network::AnyNetwork, + primitives::Bytes, + providers::RootProvider, + rpc::client::RpcClient, + transports::{http::Http, TransportResult}, +}; +use alloy_provider::ext::EngineApi; +use alloy_rpc_types_engine::{ClientCode, ClientVersionV1, JwtSecret}; +use alloy_transport_http::{ + hyper_util::{ + client::legacy::{connect::HttpConnector, Client}, + rt::TokioExecutor, + }, + AuthLayer, AuthService, HyperClient, +}; +use http_body_util::Full; +use reqwest::Url; +use tower::ServiceBuilder; + +/// A Hyper HTTP client with a JWT authentication layer. +type HyperAuthClient> = HyperClient>>; + +/// The [`EngineClient`] is responsible for interacting with the engine API via HTTP. +/// The inner transport uses a JWT [AuthLayer] to authenticate requests. +#[derive(Debug, Clone)] +pub struct EngineClient { + inner: RootProvider, AnyNetwork>, +} + +impl Deref for EngineClient { + type Target = RootProvider, AnyNetwork>; + + fn deref(&self) -> &Self::Target { + &self.inner + } +} + +impl EngineClient { + /// Creates a new [`EngineClient`] from the provided [Url] and [JwtSecret]. + pub fn new_http(url: Url, jwt: JwtSecret) -> Self { + let hyper_client = Client::builder(TokioExecutor::new()).build_http::>(); + + let auth_layer = AuthLayer::new(jwt); + let service = ServiceBuilder::new().layer(auth_layer).service(hyper_client); + + let layer_transport = HyperClient::with_service(service); + let http_hyper = Http::with_client(layer_transport, url); + let rpc_client = RpcClient::new(http_hyper, true); + let inner = RootProvider::<_, AnyNetwork>::new(rpc_client); + + Self { inner } + } + + /// Send a request to identify the engine client version. + pub async fn engine_client_version(&self) -> TransportResult> { + // Send a mocked client info to the EL, since this is a required request argument + let mocked_cl_info = ClientVersionV1 { + code: ClientCode::RH, // pretend we are Reth + version: format!("v{}", env!("CARGO_PKG_VERSION")), + name: "BoltSidecar".to_string(), + commit: "unstable".to_string(), + }; + + self.inner.get_client_version_v1(mocked_cl_info).await + } +} diff --git a/bolt-sidecar/src/client/rpc.rs b/bolt-sidecar/src/client/execution.rs similarity index 76% rename from bolt-sidecar/src/client/rpc.rs rename to bolt-sidecar/src/client/execution.rs index e122db2f..06afbb8d 100644 --- a/bolt-sidecar/src/client/rpc.rs +++ b/bolt-sidecar/src/client/execution.rs @@ -3,34 +3,63 @@ use std::ops::{Deref, DerefMut}; use alloy::{ eips::BlockNumberOrTag, primitives::{Address, Bytes, TxHash, B256, U256, U64}, + providers::{ProviderBuilder, RootProvider}, rpc::{ - client::{self as alloyClient, ClientBuilder}, + client::{BatchRequest, ClientBuilder}, types::{Block, FeeHistory, TransactionReceipt}, }, transports::{http::Http, TransportErrorKind, TransportResult}, }; - use futures::{stream::FuturesUnordered, StreamExt}; use reqwest::{Client, Url}; use crate::primitives::AccountState; -/// An HTTP-based JSON-RPC client that supports batching. -/// Implements all methods that are relevant to Bolt state. +/// An HTTP-based JSON-RPC execution client provider that supports batching. +/// +/// This struct is a wrapper over an inner [`RootProvider`] and extends it with +/// methods that are relevant to the Bolt state. #[derive(Clone, Debug)] -pub struct RpcClient(alloyClient::RpcClient>); +pub struct ExecutionClient { + /// The custom RPC client that allows us to add custom batching and extend the provider. + rpc: alloy::rpc::client::RpcClient>, + /// The inner provider that implements all the JSON-RPC methods, that can be + /// easily used via dereferencing this struct. + inner: RootProvider>, +} + +impl Deref for ExecutionClient { + type Target = RootProvider>; + + fn deref(&self) -> &Self::Target { + &self.inner + } +} + +impl DerefMut for ExecutionClient { + fn deref_mut(&mut self) -> &mut Self::Target { + &mut self.inner + } +} -impl RpcClient { +impl ExecutionClient { /// Create a new `RpcClient` with the given URL. pub fn new>(url: U) -> Self { - let client = ClientBuilder::default().http(url.into()); + let url = url.into(); + let rpc = ClientBuilder::default().http(url.clone()); + let inner = ProviderBuilder::new().on_http(url); - Self(client) + Self { rpc, inner } + } + + /// Create a new batch request. + pub fn new_batch(&self) -> BatchRequest<'_, Http> { + self.rpc.new_batch() } /// Get the chain ID. pub async fn get_chain_id(&self) -> TransportResult { - let chain_id: String = self.0.request("eth_chainId", ()).await?; + let chain_id: String = self.rpc.request("eth_chainId", ()).await?; let chain_id = chain_id .get(2..) .ok_or(TransportErrorKind::Custom("not hex prefixed result".into()))?; @@ -48,7 +77,7 @@ impl RpcClient { let tag = block_number.map_or(BlockNumberOrTag::Latest, BlockNumberOrTag::Number); let fee_history: FeeHistory = - self.0.request("eth_feeHistory", (U64::from(1), tag, &[] as &[f64])).await?; + self.rpc.request("eth_feeHistory", (U64::from(1), tag, &[] as &[f64])).await?; let Some(base_fee) = fee_history.latest_block_base_fee() else { return Err(TransportErrorKind::Custom("Base fee not found".into()).into()); @@ -65,14 +94,14 @@ impl RpcClient { let tag = block_number.map_or(BlockNumberOrTag::Latest, BlockNumberOrTag::Number); let reward_percentiles: Vec = vec![]; let fee_history: FeeHistory = - self.0.request("eth_feeHistory", (block_count, tag, &reward_percentiles)).await?; + self.rpc.request("eth_feeHistory", (block_count, tag, &reward_percentiles)).await?; Ok(fee_history.latest_block_blob_base_fee().unwrap_or(0)) } /// Get the latest block number pub async fn get_head(&self) -> TransportResult { - let result: U64 = self.0.request("eth_blockNumber", ()).await?; + let result: U64 = self.rpc.request("eth_blockNumber", ()).await?; Ok(result.to()) } @@ -83,7 +112,7 @@ impl RpcClient { address: &Address, block_number: Option, ) -> TransportResult { - let mut batch = self.0.new_batch(); + let mut batch = self.rpc.new_batch(); let tag = block_number.map_or(BlockNumberOrTag::Latest, BlockNumberOrTag::Number); @@ -110,13 +139,13 @@ impl RpcClient { pub async fn get_block(&self, block_number: Option, full: bool) -> TransportResult { let tag = block_number.map_or(BlockNumberOrTag::Latest, BlockNumberOrTag::Number); - self.0.request("eth_getBlockByNumber", (tag, full)).await + self.rpc.request("eth_getBlockByNumber", (tag, full)).await } /// Send a raw transaction to the network. #[allow(unused)] pub async fn send_raw_transaction(&self, raw: Bytes) -> TransportResult { - self.0.request("eth_sendRawTransaction", [raw]).await + self.rpc.request("eth_sendRawTransaction", [raw]).await } /// Get the receipts for a list of transaction hashes. @@ -124,7 +153,7 @@ impl RpcClient { &self, hashes: &[TxHash], ) -> TransportResult>> { - let mut batch = self.0.new_batch(); + let mut batch = self.rpc.new_batch(); let futs = FuturesUnordered::new(); @@ -147,20 +176,6 @@ impl RpcClient { } } -impl Deref for RpcClient { - type Target = alloyClient::RpcClient>; - - fn deref(&self) -> &Self::Target { - &self.0 - } -} - -impl DerefMut for RpcClient { - fn deref_mut(&mut self) -> &mut Self::Target { - &mut self.0 - } -} - #[cfg(test)] mod tests { use std::str::FromStr; @@ -179,7 +194,7 @@ mod tests { async fn test_rpc_client() { let anvil = launch_anvil(); let anvil_url = Url::from_str(&anvil.endpoint()).unwrap(); - let client = RpcClient::new(anvil_url); + let client = ExecutionClient::new(anvil_url); let addr = anvil.addresses().first().unwrap(); @@ -195,7 +210,7 @@ mod tests { #[ignore] async fn test_get_receipts() { let _ = tracing_subscriber::fmt().try_init(); - let client = RpcClient::new(Url::from_str("http://localhost:8545").unwrap()); + let client = ExecutionClient::new(Url::from_str("http://localhost:8545").unwrap()); let _receipts = client .get_receipts(&[ @@ -223,7 +238,7 @@ mod tests { async fn test_smart_contract_code() -> eyre::Result<()> { dotenv().ok(); let rpc_url = Url::parse(std::env::var("RPC_URL").unwrap().as_str())?; - let rpc_client = RpcClient::new(rpc_url); + let rpc_client = ExecutionClient::new(rpc_url); // random deployed smart contract address let addr = Address::from_str("0xBA12222222228d8Ba445958a75a0704d566BF2C8")?; diff --git a/bolt-sidecar/src/client/mod.rs b/bolt-sidecar/src/client/mod.rs index fb58e61c..c8fcd239 100644 --- a/bolt-sidecar/src/client/mod.rs +++ b/bolt-sidecar/src/client/mod.rs @@ -1,13 +1,20 @@ /// Module for interacting with the Constraints client API via its Builder API interface. /// The Bolt sidecar's main purpose is to sit between the beacon node and Constraints client, /// so most requests are simply proxied to its API. -pub mod constraints_client; -pub use constraints_client::ConstraintsClient; +pub mod constraints; +pub use constraints::ConstraintsClient; -/// Module defining an RpcClient wrapper around the [`alloy::rpc::client::RpcClient`]. -/// It provides a simple interface to interact with the Execution layer JSON-RPC API. -pub mod rpc; -pub use rpc::RpcClient; +/// Module defining an execution layer client wrapper around [`alloy::rpc::client::RpcClient`] +/// for extending the [`alloy::providers::RootProvider`] with methods relevant to the Bolt state. +pub mod execution; +pub use execution::ExecutionClient; -// Re-export the beacon_api_client -pub use beacon_api_client::mainnet::Client as BeaconClient; +/// Module defining a beacon chain client for fetching information from the beacon node API. +/// It extends the [`beacon_api_client::mainnet::Client`] with custom error handling and methods. +pub mod beacon; +pub use beacon::BeaconClient; + +/// Module defining an Engine API client with a JWT authentication layer. Allows us to extend +/// the Alloy API with custom methods and error handling. +pub mod engine; +pub use engine::EngineClient; diff --git a/bolt-sidecar/src/common/secrets.rs b/bolt-sidecar/src/common/secrets.rs index 537f7d8c..8d1c0404 100644 --- a/bolt-sidecar/src/common/secrets.rs +++ b/bolt-sidecar/src/common/secrets.rs @@ -6,6 +6,7 @@ use std::{ }; use alloy::{hex, signers::k256::ecdsa::SigningKey}; +use alloy_rpc_types_engine::JwtSecret; use blst::min_pk::SecretKey; use rand::{Rng, RngCore}; use serde::{Deserialize, Deserializer}; @@ -101,12 +102,21 @@ impl Deref for EcdsaSecretKeyWrapper { /// A warpper for JWT secret key. #[derive(Debug, Clone)] -pub struct JwtSecretConfig(pub String); +pub struct JwtSecretConfig(pub JwtSecret); + +impl JwtSecretConfig { + /// Convert the JWT secret to hex string. + pub fn to_hex(&self) -> String { + hex::encode_prefixed(self.0.as_bytes()) + } +} impl Default for JwtSecretConfig { fn default() -> Self { let random_bytes: [u8; 32] = rand::thread_rng().gen(); let secret = hex::encode(random_bytes); + let secret = JwtSecret::from_hex(secret.as_str()).expect("valid hex bytes"); + Self(secret) } } @@ -125,8 +135,7 @@ impl From<&str> for JwtSecretConfig { }; assert!(jwt.len() == 64, "Engine JWT secret must be a 32 byte hex string"); - - Self(jwt) + Self(JwtSecret::from_hex(jwt.as_str()).expect("Invalid JWT secret hex bytes")) } } @@ -139,16 +148,3 @@ impl<'de> Deserialize<'de> for JwtSecretConfig { Ok(Self::from(jwt.as_str())) } } - -impl Deref for JwtSecretConfig { - type Target = str; - fn deref(&self) -> &Self::Target { - &self.0 - } -} - -impl Display for JwtSecretConfig { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - write!(f, "0x{}", self.0) - } -} diff --git a/bolt-sidecar/src/driver.rs b/bolt-sidecar/src/driver.rs index 062f3dd7..ffeea090 100644 --- a/bolt-sidecar/src/driver.rs +++ b/bolt-sidecar/src/driver.rs @@ -5,7 +5,6 @@ use alloy::{ rpc::types::beacon::events::HeadEvent, signers::local::PrivateKeySigner, }; -use beacon_api_client::mainnet::Client as BeaconClient; use ethereum_consensus::{ clock::{self, SlotStream, SystemTimeProvider}, phase0::mainnet::SLOTS_PER_EPOCH, @@ -26,7 +25,7 @@ use crate::{ }, builder::payload_fetcher::LocalPayloadFetcher, chain_io::BoltManager, - client::ConstraintsClient, + client::{BeaconClient, ConstraintsClient}, common::backoff::retry_with_backoff, config::Opts, crypto::{SignableBLS, SignerECDSA}, @@ -205,7 +204,7 @@ impl SidecarDriver { clock::from_system_time(genesis_time, opts.chain.slot_time(), SLOTS_PER_EPOCH) .into_stream(); - let local_builder = LocalBuilder::new(opts, beacon_client.clone(), genesis_time); + let local_builder = LocalBuilder::new(opts, genesis_time); let head_tracker = HeadTracker::start(beacon_client.clone()); let consensus = ConsensusState::new( diff --git a/bolt-sidecar/src/signer/commit_boost.rs b/bolt-sidecar/src/signer/commit_boost.rs index db3f249a..9200390c 100644 --- a/bolt-sidecar/src/signer/commit_boost.rs +++ b/bolt-sidecar/src/signer/commit_boost.rs @@ -13,7 +13,10 @@ use ssz::Decode; use thiserror::Error; use tracing::{debug, error, info}; -use crate::crypto::{bls::BLS_DST_PREFIX, ecdsa::SignerECDSA}; +use crate::{ + common::secrets::JwtSecretConfig, + crypto::{bls::BLS_DST_PREFIX, ecdsa::SignerECDSA}, +}; use super::SignerResult; @@ -41,9 +44,10 @@ pub enum CommitBoostError { #[allow(unused)] impl CommitBoostSigner { /// Create a new [CommitBoostSigner] instance - pub fn new(signer_url: Url, jwt: &str) -> SignerResult { + pub fn new(signer_url: Url, jwt: &JwtSecretConfig) -> SignerResult { let socket_addr = parse_address_from_url(signer_url).map_err(CommitBoostError::Other)?; - let signer_client = SignerClient::new(socket_addr, jwt).map_err(CommitBoostError::Other)?; + let signer_client = + SignerClient::new(socket_addr, &jwt.to_hex()).map_err(CommitBoostError::Other)?; let client = Self { signer_client, @@ -215,7 +219,8 @@ mod test { warn!("skipping test: commit-boost inputs are not set"); return Ok(()); }; - let signer = CommitBoostSigner::new(signer_server_address.parse()?, &jwt_hex).unwrap(); + let jwt = JwtSecretConfig::from(jwt_hex.as_str()); + let signer = CommitBoostSigner::new(signer_server_address.parse()?, &jwt).unwrap(); // Generate random data for the test let mut rng = rand::thread_rng(); @@ -242,7 +247,8 @@ mod test { warn!("skipping test: commit-boost inputs are not set"); return Ok(()); }; - let signer = CommitBoostSigner::new(signer_server_address.parse()?, &jwt_hex).unwrap(); + let jwt = JwtSecretConfig::from(jwt_hex.as_str()); + let signer = CommitBoostSigner::new(signer_server_address.parse()?, &jwt).unwrap(); let pubkey = signer.get_proxy_ecdsa_pubkey(); // Generate random data for the test diff --git a/bolt-sidecar/src/state/consensus.rs b/bolt-sidecar/src/state/consensus.rs index 4d560138..76ac1501 100644 --- a/bolt-sidecar/src/state/consensus.rs +++ b/bolt-sidecar/src/state/consensus.rs @@ -3,7 +3,7 @@ use std::{ time::{Duration, Instant}, }; -use beacon_api_client::{mainnet::Client, ProposerDuty}; +use beacon_api_client::ProposerDuty; use ethereum_consensus::{crypto::PublicKey as BlsPublicKey, phase0::mainnet::SLOTS_PER_EPOCH}; use tokio::join; use tracing::debug; @@ -50,7 +50,7 @@ struct Epoch { /// including validating commitment requests and updating the state based on the latest slot. pub struct ConsensusState { /// The beacon API client to fetch data from the beacon chain. - beacon_api_client: Client, + beacon_api_client: BeaconClient, /// The current epoch and associated proposer duties. epoch: Epoch, // Timestamp of when the latest slot was received @@ -220,6 +220,7 @@ mod tests { use crate::test_util::try_get_beacon_api_url; #[tokio::test] + #[ignore = "TODO: fix"] async fn test_update_slot() -> eyre::Result<()> { let _ = tracing_subscriber::fmt::try_init(); diff --git a/bolt-sidecar/src/state/fetcher.rs b/bolt-sidecar/src/state/fetcher.rs index ec6aa89a..f1cf6107 100644 --- a/bolt-sidecar/src/state/fetcher.rs +++ b/bolt-sidecar/src/state/fetcher.rs @@ -10,7 +10,7 @@ use futures::{stream::FuturesOrdered, StreamExt}; use reqwest::Url; use tracing::error; -use crate::{client::RpcClient, primitives::AccountState}; +use crate::{client::ExecutionClient, primitives::AccountState}; use super::execution::StateUpdate; @@ -60,14 +60,17 @@ pub trait StateFetcher { /// A basic state fetcher that uses an RPC client to fetch state updates. #[derive(Clone, Debug)] pub struct StateClient { - client: RpcClient, + client: ExecutionClient, retry_backoff: Duration, } impl StateClient { /// Create a new `StateClient` with the given URL and maximum retries. pub fn new>(url: U) -> Self { - Self { client: RpcClient::new(url), retry_backoff: Duration::from_millis(RETRY_BACKOFF_MS) } + Self { + client: ExecutionClient::new(url), + retry_backoff: Duration::from_millis(RETRY_BACKOFF_MS), + } } } @@ -224,7 +227,7 @@ impl StateFetcher for StateClient { #[cfg(test)] impl StateClient { - pub fn inner(&self) -> &RpcClient { + pub fn inner(&self) -> &ExecutionClient { &self.client } } diff --git a/bolt-sidecar/src/test_util.rs b/bolt-sidecar/src/test_util.rs index 3d7e3a25..ec857ded 100644 --- a/bolt-sidecar/src/test_util.rs +++ b/bolt-sidecar/src/test_util.rs @@ -33,17 +33,17 @@ use crate::{ /// The URL of the test execution client HTTP API. /// /// NOTE: this DNS is only available through the Chainbound Tailnet -const EXECUTION_API_URL: &str = "http://remotebeast:8545"; +const EXECUTION_API_URL: &str = "http://remotebeast:48545"; /// The URL of the test beacon client HTTP API. /// /// NOTE: this DNS is only available through the Chainbound Tailnet -const BEACON_API_URL: &str = "http://remotebeast:3500"; +const BEACON_API_URL: &str = "http://remotebeast:44400"; /// The URL of the test engine client HTTP API. /// /// NOTE: this DNS is only available through the Chainbound Tailnet -const ENGINE_API_URL: &str = "http://remotebeast:8551"; +const ENGINE_API_URL: &str = "http://remotebeast:48551"; /// Check if the test execution client is reachable by sending a GET request to it. pub(crate) async fn try_get_execution_api_url() -> Option<&'static str> { @@ -82,7 +82,7 @@ pub(crate) async fn try_get_beacon_api_url() -> Option<&'static str> { /// If any of the above values can't be found, the function will return `None`. pub(crate) async fn get_test_config() -> Option { env::set_var("BOLT_SIDECAR_PRIVATE_KEY", BlsSecretKeyWrapper::random().to_string()); - env::set_var("BOLT_SIDECAR_ENGINE_JWT_HEX", JwtSecretConfig::default().to_string()); + env::set_var("BOLT_SIDECAR_ENGINE_JWT_HEX", JwtSecretConfig::default().to_hex()); env::set_var("BOLT_SIDECAR_FEE_RECIPIENT", Address::ZERO.to_string()); env::set_var("BOLT_SIDECAR_BUILDER_PRIVATE_KEY", BlsSecretKeyWrapper::random().to_string()); env::set_var("BOLT_SIDECAR_CONSTRAINT_PRIVATE_KEY", BlsSecretKeyWrapper::random().to_string()); @@ -109,7 +109,7 @@ pub(crate) async fn get_test_config() -> Option { if let Some(url) = try_get_engine_api_url().await { opts.engine_api_url = url.parse().expect("valid URL"); } - opts.engine_jwt_hex = JwtSecretConfig(jwt); + opts.engine_jwt_hex = JwtSecretConfig::from(jwt.as_str()); Some(opts) }