diff --git a/bolt-sidecar/Cargo.lock b/bolt-sidecar/Cargo.lock index d50b0bb60..5a14a06ab 100644 --- a/bolt-sidecar/Cargo.lock +++ b/bolt-sidecar/Cargo.lock @@ -50,19 +50,35 @@ version = "0.1.22" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "04e9a1892803b02f53e25bea3e414ddd0501f12d97456c9d5ade4edf88f9516f" dependencies = [ + "alloy-rlp", "num_enum", + "serde", "strum", ] +[[package]] +name = "alloy-consensus" +version = "0.1.0" +source = "git+https://github.com/alloy-rs/alloy?rev=17633df#17633df04920e07cd7afbd6ee825fcde677fa1d1" +dependencies = [ + "alloy-eips 0.1.0 (git+https://github.com/alloy-rs/alloy?rev=17633df)", + "alloy-primitives", + "alloy-rlp", + "alloy-serde 0.1.0 (git+https://github.com/alloy-rs/alloy?rev=17633df)", + "c-kzg", + "serde", + "sha2 0.10.8", +] + [[package]] name = "alloy-consensus" version = "0.1.0" source = "git+https://github.com/alloy-rs/alloy?rev=64feb9bc51c8021ea08535694c44de84222f474e#64feb9bc51c8021ea08535694c44de84222f474e" dependencies = [ - "alloy-eips 0.1.0", + "alloy-eips 0.1.0 (git+https://github.com/alloy-rs/alloy?rev=64feb9bc51c8021ea08535694c44de84222f474e)", "alloy-primitives", "alloy-rlp", - "alloy-serde 0.1.0", + "alloy-serde 0.1.0 (git+https://github.com/alloy-rs/alloy?rev=64feb9bc51c8021ea08535694c44de84222f474e)", "c-kzg", "serde", ] @@ -70,7 +86,7 @@ dependencies = [ [[package]] name = "alloy-consensus" version = "0.1.2" -source = "git+https://github.com/alloy-rs/alloy#8aa54828c025a99bbe7e2d4fc9768605d172cc6d" +source = "git+https://github.com/alloy-rs/alloy#61921bccf676843823164bc7acc31cc9df5d3079" dependencies = [ "alloy-eips 0.1.2", "alloy-primitives", @@ -80,6 +96,19 @@ dependencies = [ "serde", ] +[[package]] +name = "alloy-eips" +version = "0.1.0" +source = "git+https://github.com/alloy-rs/alloy?rev=17633df#17633df04920e07cd7afbd6ee825fcde677fa1d1" +dependencies = [ + "alloy-primitives", + "alloy-rlp", + "alloy-serde 0.1.0 (git+https://github.com/alloy-rs/alloy?rev=17633df)", + "c-kzg", + "once_cell", + "serde", +] + [[package]] name = "alloy-eips" version = "0.1.0" @@ -87,7 +116,7 @@ source = "git+https://github.com/alloy-rs/alloy?rev=64feb9bc51c8021ea08535694c44 dependencies = [ "alloy-primitives", "alloy-rlp", - "alloy-serde 0.1.0", + "alloy-serde 0.1.0 (git+https://github.com/alloy-rs/alloy?rev=64feb9bc51c8021ea08535694c44de84222f474e)", "c-kzg", "once_cell", "serde", @@ -97,7 +126,7 @@ dependencies = [ [[package]] name = "alloy-eips" version = "0.1.2" -source = "git+https://github.com/alloy-rs/alloy#8aa54828c025a99bbe7e2d4fc9768605d172cc6d" +source = "git+https://github.com/alloy-rs/alloy#61921bccf676843823164bc7acc31cc9df5d3079" dependencies = [ "alloy-primitives", "alloy-rlp", @@ -108,13 +137,23 @@ dependencies = [ "sha2 0.10.8", ] +[[package]] +name = "alloy-genesis" +version = "0.1.0" +source = "git+https://github.com/alloy-rs/alloy?rev=17633df#17633df04920e07cd7afbd6ee825fcde677fa1d1" +dependencies = [ + "alloy-primitives", + "alloy-serde 0.1.0 (git+https://github.com/alloy-rs/alloy?rev=17633df)", + "serde", +] + [[package]] name = "alloy-genesis" version = "0.1.0" source = "git+https://github.com/alloy-rs/alloy?rev=64feb9bc51c8021ea08535694c44de84222f474e#64feb9bc51c8021ea08535694c44de84222f474e" dependencies = [ "alloy-primitives", - "alloy-serde 0.1.0", + "alloy-serde 0.1.0 (git+https://github.com/alloy-rs/alloy?rev=64feb9bc51c8021ea08535694c44de84222f474e)", "serde", "serde_json", ] @@ -122,7 +161,7 @@ dependencies = [ [[package]] name = "alloy-genesis" version = "0.1.2" -source = "git+https://github.com/alloy-rs/alloy#8aa54828c025a99bbe7e2d4fc9768605d172cc6d" +source = "git+https://github.com/alloy-rs/alloy#61921bccf676843823164bc7acc31cc9df5d3079" dependencies = [ "alloy-primitives", "alloy-serde 0.1.2", @@ -132,7 +171,7 @@ dependencies = [ [[package]] name = "alloy-json-rpc" version = "0.1.2" -source = "git+https://github.com/alloy-rs/alloy#8aa54828c025a99bbe7e2d4fc9768605d172cc6d" +source = "git+https://github.com/alloy-rs/alloy#61921bccf676843823164bc7acc31cc9df5d3079" dependencies = [ "alloy-primitives", "serde", @@ -144,7 +183,7 @@ dependencies = [ [[package]] name = "alloy-network" version = "0.1.2" -source = "git+https://github.com/alloy-rs/alloy#8aa54828c025a99bbe7e2d4fc9768605d172cc6d" +source = "git+https://github.com/alloy-rs/alloy#61921bccf676843823164bc7acc31cc9df5d3079" dependencies = [ "alloy-consensus 0.1.2", "alloy-eips 0.1.2", @@ -163,7 +202,7 @@ dependencies = [ [[package]] name = "alloy-node-bindings" version = "0.1.2" -source = "git+https://github.com/alloy-rs/alloy#8aa54828c025a99bbe7e2d4fc9768605d172cc6d" +source = "git+https://github.com/alloy-rs/alloy#61921bccf676843823164bc7acc31cc9df5d3079" dependencies = [ "alloy-genesis 0.1.2", "alloy-primitives", @@ -202,7 +241,7 @@ dependencies = [ [[package]] name = "alloy-provider" version = "0.1.2" -source = "git+https://github.com/alloy-rs/alloy#8aa54828c025a99bbe7e2d4fc9768605d172cc6d" +source = "git+https://github.com/alloy-rs/alloy#61921bccf676843823164bc7acc31cc9df5d3079" dependencies = [ "alloy-chains", "alloy-consensus 0.1.2", @@ -235,7 +274,7 @@ dependencies = [ [[package]] name = "alloy-pubsub" version = "0.1.2" -source = "git+https://github.com/alloy-rs/alloy#8aa54828c025a99bbe7e2d4fc9768605d172cc6d" +source = "git+https://github.com/alloy-rs/alloy#61921bccf676843823164bc7acc31cc9df5d3079" dependencies = [ "alloy-json-rpc", "alloy-primitives", @@ -275,7 +314,7 @@ dependencies = [ [[package]] name = "alloy-rpc-client" version = "0.1.2" -source = "git+https://github.com/alloy-rs/alloy#8aa54828c025a99bbe7e2d4fc9768605d172cc6d" +source = "git+https://github.com/alloy-rs/alloy#61921bccf676843823164bc7acc31cc9df5d3079" dependencies = [ "alloy-json-rpc", "alloy-primitives", @@ -295,17 +334,36 @@ dependencies = [ "url", ] +[[package]] +name = "alloy-rpc-types" +version = "0.1.0" +source = "git+https://github.com/alloy-rs/alloy?rev=17633df#17633df04920e07cd7afbd6ee825fcde677fa1d1" +dependencies = [ + "alloy-consensus 0.1.0 (git+https://github.com/alloy-rs/alloy?rev=17633df)", + "alloy-eips 0.1.0 (git+https://github.com/alloy-rs/alloy?rev=17633df)", + "alloy-genesis 0.1.0 (git+https://github.com/alloy-rs/alloy?rev=17633df)", + "alloy-primitives", + "alloy-rlp", + "alloy-serde 0.1.0 (git+https://github.com/alloy-rs/alloy?rev=17633df)", + "alloy-sol-types", + "itertools 0.12.1", + "jsonrpsee-types", + "serde", + "serde_json", + "thiserror", +] + [[package]] name = "alloy-rpc-types" version = "0.1.0" source = "git+https://github.com/alloy-rs/alloy?rev=64feb9bc51c8021ea08535694c44de84222f474e#64feb9bc51c8021ea08535694c44de84222f474e" dependencies = [ - "alloy-consensus 0.1.0", - "alloy-eips 0.1.0", - "alloy-genesis 0.1.0", + "alloy-consensus 0.1.0 (git+https://github.com/alloy-rs/alloy?rev=64feb9bc51c8021ea08535694c44de84222f474e)", + "alloy-eips 0.1.0 (git+https://github.com/alloy-rs/alloy?rev=64feb9bc51c8021ea08535694c44de84222f474e)", + "alloy-genesis 0.1.0 (git+https://github.com/alloy-rs/alloy?rev=64feb9bc51c8021ea08535694c44de84222f474e)", "alloy-primitives", "alloy-rlp", - "alloy-serde 0.1.0", + "alloy-serde 0.1.0 (git+https://github.com/alloy-rs/alloy?rev=64feb9bc51c8021ea08535694c44de84222f474e)", "alloy-sol-types", "itertools 0.12.1", "serde", @@ -316,7 +374,7 @@ dependencies = [ [[package]] name = "alloy-rpc-types" version = "0.1.2" -source = "git+https://github.com/alloy-rs/alloy#8aa54828c025a99bbe7e2d4fc9768605d172cc6d" +source = "git+https://github.com/alloy-rs/alloy#61921bccf676843823164bc7acc31cc9df5d3079" dependencies = [ "alloy-rpc-types-eth", "alloy-serde 0.1.2", @@ -327,9 +385,9 @@ name = "alloy-rpc-types-beacon" version = "0.1.0" source = "git+https://github.com/alloy-rs/alloy?rev=64feb9bc51c8021ea08535694c44de84222f474e#64feb9bc51c8021ea08535694c44de84222f474e" dependencies = [ - "alloy-eips 0.1.0", + "alloy-eips 0.1.0 (git+https://github.com/alloy-rs/alloy?rev=64feb9bc51c8021ea08535694c44de84222f474e)", "alloy-primitives", - "alloy-rpc-types-engine 0.1.0", + "alloy-rpc-types-engine 0.1.0 (git+https://github.com/alloy-rs/alloy?rev=64feb9bc51c8021ea08535694c44de84222f474e)", "serde", "serde_with", "thiserror", @@ -338,7 +396,7 @@ dependencies = [ [[package]] name = "alloy-rpc-types-beacon" version = "0.1.2" -source = "git+https://github.com/alloy-rs/alloy#8aa54828c025a99bbe7e2d4fc9768605d172cc6d" +source = "git+https://github.com/alloy-rs/alloy#61921bccf676843823164bc7acc31cc9df5d3079" dependencies = [ "alloy-eips 0.1.2", "alloy-primitives", @@ -348,17 +406,32 @@ dependencies = [ "thiserror", ] +[[package]] +name = "alloy-rpc-types-engine" +version = "0.1.0" +source = "git+https://github.com/alloy-rs/alloy?rev=17633df#17633df04920e07cd7afbd6ee825fcde677fa1d1" +dependencies = [ + "alloy-consensus 0.1.0 (git+https://github.com/alloy-rs/alloy?rev=17633df)", + "alloy-primitives", + "alloy-rlp", + "alloy-rpc-types 0.1.0 (git+https://github.com/alloy-rs/alloy?rev=17633df)", + "alloy-serde 0.1.0 (git+https://github.com/alloy-rs/alloy?rev=17633df)", + "jsonrpsee-types", + "serde", + "thiserror", +] + [[package]] name = "alloy-rpc-types-engine" version = "0.1.0" source = "git+https://github.com/alloy-rs/alloy?rev=64feb9bc51c8021ea08535694c44de84222f474e#64feb9bc51c8021ea08535694c44de84222f474e" dependencies = [ - "alloy-consensus 0.1.0", - "alloy-eips 0.1.0", + "alloy-consensus 0.1.0 (git+https://github.com/alloy-rs/alloy?rev=64feb9bc51c8021ea08535694c44de84222f474e)", + "alloy-eips 0.1.0 (git+https://github.com/alloy-rs/alloy?rev=64feb9bc51c8021ea08535694c44de84222f474e)", "alloy-primitives", "alloy-rlp", - "alloy-rpc-types 0.1.0", - "alloy-serde 0.1.0", + "alloy-rpc-types 0.1.0 (git+https://github.com/alloy-rs/alloy?rev=64feb9bc51c8021ea08535694c44de84222f474e)", + "alloy-serde 0.1.0 (git+https://github.com/alloy-rs/alloy?rev=64feb9bc51c8021ea08535694c44de84222f474e)", "jsonwebtoken", "rand 0.8.5", "serde", @@ -368,7 +441,7 @@ dependencies = [ [[package]] name = "alloy-rpc-types-engine" version = "0.1.2" -source = "git+https://github.com/alloy-rs/alloy#8aa54828c025a99bbe7e2d4fc9768605d172cc6d" +source = "git+https://github.com/alloy-rs/alloy#61921bccf676843823164bc7acc31cc9df5d3079" dependencies = [ "alloy-consensus 0.1.2", "alloy-eips 0.1.2", @@ -385,7 +458,7 @@ dependencies = [ [[package]] name = "alloy-rpc-types-eth" version = "0.1.2" -source = "git+https://github.com/alloy-rs/alloy#8aa54828c025a99bbe7e2d4fc9768605d172cc6d" +source = "git+https://github.com/alloy-rs/alloy#61921bccf676843823164bc7acc31cc9df5d3079" dependencies = [ "alloy-consensus 0.1.2", "alloy-eips 0.1.2", @@ -399,6 +472,28 @@ dependencies = [ "thiserror", ] +[[package]] +name = "alloy-rpc-types-trace" +version = "0.1.0" +source = "git+https://github.com/alloy-rs/alloy?rev=17633df#17633df04920e07cd7afbd6ee825fcde677fa1d1" +dependencies = [ + "alloy-primitives", + "alloy-rpc-types 0.1.0 (git+https://github.com/alloy-rs/alloy?rev=17633df)", + "alloy-serde 0.1.0 (git+https://github.com/alloy-rs/alloy?rev=17633df)", + "serde", + "serde_json", +] + +[[package]] +name = "alloy-serde" +version = "0.1.0" +source = "git+https://github.com/alloy-rs/alloy?rev=17633df#17633df04920e07cd7afbd6ee825fcde677fa1d1" +dependencies = [ + "alloy-primitives", + "serde", + "serde_json", +] + [[package]] name = "alloy-serde" version = "0.1.0" @@ -412,7 +507,7 @@ dependencies = [ [[package]] name = "alloy-serde" version = "0.1.2" -source = "git+https://github.com/alloy-rs/alloy#8aa54828c025a99bbe7e2d4fc9768605d172cc6d" +source = "git+https://github.com/alloy-rs/alloy#61921bccf676843823164bc7acc31cc9df5d3079" dependencies = [ "alloy-primitives", "serde", @@ -422,7 +517,7 @@ dependencies = [ [[package]] name = "alloy-signer" version = "0.1.2" -source = "git+https://github.com/alloy-rs/alloy#8aa54828c025a99bbe7e2d4fc9768605d172cc6d" +source = "git+https://github.com/alloy-rs/alloy#61921bccf676843823164bc7acc31cc9df5d3079" dependencies = [ "alloy-primitives", "async-trait", @@ -435,7 +530,7 @@ dependencies = [ [[package]] name = "alloy-signer-local" version = "0.1.2" -source = "git+https://github.com/alloy-rs/alloy#8aa54828c025a99bbe7e2d4fc9768605d172cc6d" +source = "git+https://github.com/alloy-rs/alloy#61921bccf676843823164bc7acc31cc9df5d3079" dependencies = [ "alloy-consensus 0.1.2", "alloy-network", @@ -508,7 +603,7 @@ dependencies = [ [[package]] name = "alloy-transport" version = "0.1.2" -source = "git+https://github.com/alloy-rs/alloy#8aa54828c025a99bbe7e2d4fc9768605d172cc6d" +source = "git+https://github.com/alloy-rs/alloy#61921bccf676843823164bc7acc31cc9df5d3079" dependencies = [ "alloy-json-rpc", "base64 0.22.1", @@ -525,7 +620,7 @@ dependencies = [ [[package]] name = "alloy-transport-http" version = "0.1.2" -source = "git+https://github.com/alloy-rs/alloy#8aa54828c025a99bbe7e2d4fc9768605d172cc6d" +source = "git+https://github.com/alloy-rs/alloy#61921bccf676843823164bc7acc31cc9df5d3079" dependencies = [ "alloy-json-rpc", "alloy-transport", @@ -539,7 +634,7 @@ dependencies = [ [[package]] name = "alloy-transport-ws" version = "0.1.2" -source = "git+https://github.com/alloy-rs/alloy#8aa54828c025a99bbe7e2d4fc9768605d172cc6d" +source = "git+https://github.com/alloy-rs/alloy#61921bccf676843823164bc7acc31cc9df5d3079" dependencies = [ "alloy-pubsub", "alloy-transport", @@ -553,6 +648,22 @@ dependencies = [ "ws_stream_wasm", ] +[[package]] +name = "alloy-trie" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "beb28aa4ecd32fdfa1b1bdd111ff7357dd562c6b2372694cf9e613434fcba659" +dependencies = [ + "alloy-primitives", + "alloy-rlp", + "derive_more", + "hashbrown 0.14.5", + "nybbles", + "serde", + "smallvec", + "tracing", +] + [[package]] name = "android-tzdata" version = "0.1.1" @@ -834,6 +945,16 @@ version = "1.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1505bd5d3d116872e7271a6d4e16d81d0c8570876c8de68093a09ac269d8aac0" +[[package]] +name = "aurora-engine-modexp" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0aef7712851e524f35fbbb74fa6599c5cd8692056a1c36f9ca0d2001b670e7e5" +dependencies = [ + "hex", + "num", +] + [[package]] name = "auto_impl" version = "1.2.0" @@ -989,6 +1110,15 @@ dependencies = [ "url", ] +[[package]] +name = "beef" +version = "0.5.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3a8241f3ebb85c056b509d4327ad0358fbbba6ffb340bf388f26350aeda225b1" +dependencies = [ + "serde", +] + [[package]] name = "bimap" version = "0.6.3" @@ -1021,6 +1151,9 @@ name = "bitflags" version = "2.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "cf4b9d6a944f767f8e5e0db018570623c85f3d925ac718db4e06d0187adb21c1" +dependencies = [ + "serde", +] [[package]] name = "bitvec" @@ -1030,6 +1163,7 @@ checksum = "1bc2832c24239b0141d5674bb9174f9d68a8b5b3f2753311927c172ca46f7e9c" dependencies = [ "funty", "radium", + "serde", "tap", "wyz", ] @@ -1101,7 +1235,8 @@ dependencies = [ "parking_lot", "rand 0.8.5", "reqwest 0.12.5", - "secp256k1", + "reth-primitives", + "secp256k1 0.29.0", "serde", "serde_json", "thiserror", @@ -1129,6 +1264,12 @@ version = "1.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c3ac9f8b63eca6fd385229b3675f6cc0dc5c8a5c8a54a59d4f52ffd670d87b0c" +[[package]] +name = "bytemuck" +version = "1.16.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b236fc92302c97ed75b38da1f4917b5cdda4984745740f153a5d3059e48d725e" + [[package]] name = "byteorder" version = "1.5.0" @@ -1207,6 +1348,11 @@ name = "cc" version = "1.0.99" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "96c51067fd44124faa7f870b4b1c969379ad32b2ba805aa959430ceaa384f695" +dependencies = [ + "jobserver", + "libc", + "once_cell", +] [[package]] name = "cfg-if" @@ -1307,6 +1453,15 @@ version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6245d59a3e82a7fc217c5828a6692dbc6dfb63a0c8c90495621f7b9d79704a0e" +[[package]] +name = "convert_case" +version = "0.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ec182b0ca2f35d8fc196cf3404988fd8b8c739a4d270ff118a398feb0cbec1ca" +dependencies = [ + "unicode-segmentation", +] + [[package]] name = "core-foundation" version = "0.9.4" @@ -1341,6 +1496,40 @@ dependencies = [ "libc", ] +[[package]] +name = "crc" +version = "3.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "69e6e4d7b33a94f0991c26729976b10ebde1d34c3ee82408fb536164fa10d636" +dependencies = [ + "crc-catalog", +] + +[[package]] +name = "crc-catalog" +version = "2.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "19d374276b40fb8bbdee95aef7c7fa6b5316ec764510eb64b8dd0e2ed0d7e7f5" + +[[package]] +name = "crossbeam-deque" +version = "0.8.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "613f8cc01fe9cf1a3eb3d7f488fd2fa8388403e97039e2f73692932e291a770d" +dependencies = [ + "crossbeam-epoch", + "crossbeam-utils", +] + +[[package]] +name = "crossbeam-epoch" +version = "0.9.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5b82ac4a3c2ca9c3460964f020e1402edd5753411d7737aa39c3714ad1b5420e" +dependencies = [ + "crossbeam-utils", +] + [[package]] name = "crossbeam-utils" version = "0.8.20" @@ -1523,7 +1712,7 @@ version = "0.99.18" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5f33878137e4dafd7fa914ad4e259e18a4e8e532b9617a2d0150262bf53abfce" dependencies = [ - "convert_case", + "convert_case 0.4.0", "proc-macro2", "quote", "rustc_version 0.4.0", @@ -1557,6 +1746,12 @@ version = "1.0.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "56ce8c6da7551ec6c462cbaf3bfbc75131ebbfa1c944aeaa9dab51ca1c5f0c3b" +[[package]] +name = "dyn-clone" +version = "1.0.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0d6ef0072f8a535281e4876be788938b528e9a1d43900b82c2569af7da799125" + [[package]] name = "ecdsa" version = "0.14.8" @@ -1656,6 +1851,36 @@ dependencies = [ "zeroize", ] +[[package]] +name = "enr" +version = "0.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2a3d8dc56e02f954cac8eb489772c552c473346fc34f67412bb6244fd647f7e4" +dependencies = [ + "base64 0.21.7", + "bytes", + "hex", + "k256 0.13.3", + "log", + "rand 0.8.5", + "rlp", + "secp256k1 0.27.0", + "serde", + "sha3", + "zeroize", +] + +[[package]] +name = "enumn" +version = "0.1.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6fd000fd6988e73bbe993ea3db9b1aa64906ab88766d654973924340c8cddb42" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.67", +] + [[package]] name = "equivalent" version = "1.0.1" @@ -1712,7 +1937,7 @@ dependencies = [ "blst", "bs58", "c-kzg", - "enr", + "enr 0.6.2", "hex", "integer-sqrt", "multiaddr", @@ -2147,6 +2372,7 @@ checksum = "e5274423e17b7c9fc20b6e7e208532f9b19825d82dfd615708b70edd83df41f1" dependencies = [ "ahash", "allocator-api2", + "serde", ] [[package]] @@ -2588,6 +2814,15 @@ version = "1.0.11" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "49f1f14873335454500d59611f1cf4a4b0f786f9ac11f4312a78e4cf2566695b" +[[package]] +name = "jobserver" +version = "0.1.31" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d2b099aaa34a9751c5bf0878add70444e1ed2dd73f347be99003d4577277de6e" +dependencies = [ + "libc", +] + [[package]] name = "js-sys" version = "0.3.69" @@ -2597,6 +2832,19 @@ dependencies = [ "wasm-bindgen", ] +[[package]] +name = "jsonrpsee-types" +version = "0.22.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "150d6168405890a7a3231a3c74843f58b8959471f6df76078db2619ddee1d07d" +dependencies = [ + "anyhow", + "beef", + "serde", + "serde_json", + "thiserror", +] + [[package]] name = "jsonwebtoken" version = "9.3.0" @@ -2635,6 +2883,7 @@ dependencies = [ "elliptic-curve 0.13.8", "once_cell", "sha2 0.10.8", + "signature 2.2.0", ] [[package]] @@ -2658,9 +2907,12 @@ dependencies = [ [[package]] name = "lazy_static" -version = "1.4.0" +version = "1.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646" +checksum = "bbd2bcb4c963f2ddae06a2efc7e9f3591312473c50c6685e1f298068316e66fe" +dependencies = [ + "spin 0.9.8", +] [[package]] name = "libc" @@ -2778,6 +3030,27 @@ dependencies = [ "windows-sys 0.48.0", ] +[[package]] +name = "modular-bitfield" +version = "0.11.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a53d79ba8304ac1c4f9eb3b9d281f21f7be9d4626f72ce7df4ad8fbde4f38a74" +dependencies = [ + "modular-bitfield-impl", + "static_assertions", +] + +[[package]] +name = "modular-bitfield-impl" +version = "0.11.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5a7d5f7076603ebc68de2dc6a650ec331a062a13abaa346975be747bbfa4b789" +dependencies = [ + "proc-macro2", + "quote", + "syn 1.0.109", +] + [[package]] name = "multer" version = "2.1.0" @@ -2868,6 +3141,20 @@ dependencies = [ "winapi", ] +[[package]] +name = "num" +version = "0.4.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "35bd024e8b2ff75562e5f34e7f4905839deb4b22955ef5e73d2fea1b9813cb23" +dependencies = [ + "num-bigint", + "num-complex", + "num-integer", + "num-iter", + "num-rational", + "num-traits", +] + [[package]] name = "num-bigint" version = "0.4.5" @@ -2878,6 +3165,15 @@ dependencies = [ "num-traits", ] +[[package]] +name = "num-complex" +version = "0.4.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "73f88a1307638156682bada9d7604135552957b7818057dcef22705b4d509495" +dependencies = [ + "num-traits", +] + [[package]] name = "num-conv" version = "0.1.0" @@ -2893,6 +3189,28 @@ dependencies = [ "num-traits", ] +[[package]] +name = "num-iter" +version = "0.1.45" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1429034a0490724d0075ebb2bc9e875d6503c3cf69e235a8941aa757d83ef5bf" +dependencies = [ + "autocfg", + "num-integer", + "num-traits", +] + +[[package]] +name = "num-rational" +version = "0.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f83d14da390562dca69fc84082e73e548e1ad308d24accdedd2720017cb37824" +dependencies = [ + "num-bigint", + "num-integer", + "num-traits", +] + [[package]] name = "num-traits" version = "0.2.19" @@ -2934,6 +3252,19 @@ dependencies = [ "syn 2.0.67", ] +[[package]] +name = "nybbles" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "95f06be0417d97f81fe4e5c86d7d01b392655a9cac9c19a848aa033e18937b23" +dependencies = [ + "alloy-rlp", + "const-hex", + "proptest", + "serde", + "smallvec", +] + [[package]] name = "object" version = "0.36.0" @@ -3385,6 +3716,26 @@ dependencies = [ "rand_core 0.6.4", ] +[[package]] +name = "rayon" +version = "1.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b418a60154510ca1a002a752ca9714984e21e4241e804d32555251faf8b78ffa" +dependencies = [ + "either", + "rayon-core", +] + +[[package]] +name = "rayon-core" +version = "1.12.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1465873a3dfdaa8ae7cb14b4383657caab0b3e8a0aa9ae8e04b044854c8dfce2" +dependencies = [ + "crossbeam-deque", + "crossbeam-utils", +] + [[package]] name = "redox_syscall" version = "0.5.2" @@ -3508,6 +3859,163 @@ dependencies = [ "winreg 0.52.0", ] +[[package]] +name = "reth-codecs" +version = "0.2.0-beta.5" +source = "git+https://github.com/paradigmxyz/reth?rev=71c404d#71c404d9cb7a678d4c0f6442a9c2b8449529fe2a" +dependencies = [ + "alloy-primitives", + "bytes", + "reth-codecs-derive", +] + +[[package]] +name = "reth-codecs-derive" +version = "0.2.0-beta.5" +source = "git+https://github.com/paradigmxyz/reth?rev=71c404d#71c404d9cb7a678d4c0f6442a9c2b8449529fe2a" +dependencies = [ + "convert_case 0.6.0", + "proc-macro2", + "quote", + "syn 2.0.67", +] + +[[package]] +name = "reth-ethereum-forks" +version = "0.2.0-beta.5" +source = "git+https://github.com/paradigmxyz/reth?rev=71c404d#71c404d9cb7a678d4c0f6442a9c2b8449529fe2a" +dependencies = [ + "alloy-chains", + "alloy-primitives", + "alloy-rlp", + "crc", + "serde", + "thiserror", +] + +[[package]] +name = "reth-primitives" +version = "0.2.0-beta.5" +source = "git+https://github.com/paradigmxyz/reth?rev=71c404d#71c404d9cb7a678d4c0f6442a9c2b8449529fe2a" +dependencies = [ + "alloy-chains", + "alloy-eips 0.1.0 (git+https://github.com/alloy-rs/alloy?rev=17633df)", + "alloy-genesis 0.1.0 (git+https://github.com/alloy-rs/alloy?rev=17633df)", + "alloy-primitives", + "alloy-rlp", + "alloy-trie", + "byteorder", + "bytes", + "c-kzg", + "cfg-if", + "derive_more", + "enr 0.10.0", + "itertools 0.12.1", + "modular-bitfield", + "nybbles", + "once_cell", + "rayon", + "reth-codecs", + "reth-ethereum-forks", + "reth-rpc-types", + "revm", + "revm-primitives", + "roaring", + "secp256k1 0.27.0", + "serde", + "serde_json", + "serde_with", + "sha2 0.10.8", + "strum", + "tempfile", + "thiserror", + "zstd", +] + +[[package]] +name = "reth-rpc-types" +version = "0.2.0-beta.5" +source = "git+https://github.com/paradigmxyz/reth?rev=71c404d#71c404d9cb7a678d4c0f6442a9c2b8449529fe2a" +dependencies = [ + "alloy-genesis 0.1.0 (git+https://github.com/alloy-rs/alloy?rev=17633df)", + "alloy-primitives", + "alloy-rlp", + "alloy-rpc-types 0.1.0 (git+https://github.com/alloy-rs/alloy?rev=17633df)", + "alloy-rpc-types-engine 0.1.0 (git+https://github.com/alloy-rs/alloy?rev=17633df)", + "alloy-rpc-types-trace", + "enr 0.10.0", + "jsonrpsee-types", + "secp256k1 0.27.0", + "serde", + "serde_json", + "serde_with", + "thiserror", + "url", +] + +[[package]] +name = "revm" +version = "8.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "72a454c1c650b2b2e23f0c461af09e6c31e1d15e1cbebe905a701c46b8a50afc" +dependencies = [ + "auto_impl", + "cfg-if", + "dyn-clone", + "revm-interpreter", + "revm-precompile", + "serde", + "serde_json", +] + +[[package]] +name = "revm-interpreter" +version = "4.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d322f2730cd300e99d271a1704a2dfb8973d832428f5aa282aaa40e2473b5eec" +dependencies = [ + "revm-primitives", + "serde", +] + +[[package]] +name = "revm-precompile" +version = "6.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "931f692f3f4fc72ec39d5d270f8e9d208c4a6008de7590ee96cf948e3b6d3f8d" +dependencies = [ + "aurora-engine-modexp", + "c-kzg", + "k256 0.13.3", + "once_cell", + "revm-primitives", + "ripemd", + "secp256k1 0.28.2", + "sha2 0.10.8", + "substrate-bn", +] + +[[package]] +name = "revm-primitives" +version = "3.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cbbc9640790cebcb731289afb7a7d96d16ad94afeb64b5d0b66443bd151e79d6" +dependencies = [ + "alloy-primitives", + "auto_impl", + "bitflags 2.5.0", + "bitvec", + "c-kzg", + "cfg-if", + "derive_more", + "dyn-clone", + "enumn", + "hashbrown 0.14.5", + "hex", + "once_cell", + "serde", +] + [[package]] name = "rfc6979" version = "0.3.1" @@ -3559,6 +4067,15 @@ dependencies = [ "windows-sys 0.52.0", ] +[[package]] +name = "ripemd" +version = "0.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bd124222d17ad93a644ed9d011a40f4fb64aa54275c08cc216524a9ea82fb09f" +dependencies = [ + "digest 0.10.7", +] + [[package]] name = "rlp" version = "0.5.2" @@ -3581,6 +4098,16 @@ dependencies = [ "syn 1.0.109", ] +[[package]] +name = "roaring" +version = "0.10.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7699249cc2c7d71939f30868f47e9d7add0bdc030d90ee10bfd16887ff8bb1c8" +dependencies = [ + "bytemuck", + "byteorder", +] + [[package]] name = "ruint" version = "1.12.3" @@ -3802,6 +4329,25 @@ dependencies = [ "zeroize", ] +[[package]] +name = "secp256k1" +version = "0.27.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "25996b82292a7a57ed3508f052cfff8640d38d32018784acd714758b43da9c8f" +dependencies = [ + "secp256k1-sys 0.8.1", +] + +[[package]] +name = "secp256k1" +version = "0.28.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d24b59d129cdadea20aea4fb2352fa053712e5d713eee47d700cd4b2bc002f10" +dependencies = [ + "rand 0.8.5", + "secp256k1-sys 0.9.2", +] + [[package]] name = "secp256k1" version = "0.29.0" @@ -3809,7 +4355,25 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0e0cc0f1cf93f4969faf3ea1c7d8a9faed25918d96affa959720823dfe86d4f3" dependencies = [ "rand 0.8.5", - "secp256k1-sys", + "secp256k1-sys 0.10.0", +] + +[[package]] +name = "secp256k1-sys" +version = "0.8.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "70a129b9e9efbfb223753b9163c4ab3b13cff7fd9c7f010fbac25ab4099fa07e" +dependencies = [ + "cc", +] + +[[package]] +name = "secp256k1-sys" +version = "0.9.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e5d1746aae42c19d583c3c1a8c646bfad910498e2051c551a7f2e3c0c9fbb7eb" +dependencies = [ + "cc", ] [[package]] @@ -3900,6 +4464,7 @@ version = "1.0.117" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "455182ea6142b14f93f4bc5320a2b31c1f266b66a4a5c858b013302a5d8cbfc3" dependencies = [ + "indexmap 2.2.6", "itoa", "ryu", "serde", @@ -4108,6 +4673,9 @@ name = "smallvec" version = "1.13.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3c5e1a9a646d36c3599cd173a41282daf47c44583ad367b8e6837255952e5c67" +dependencies = [ + "serde", +] [[package]] name = "socket2" @@ -4213,6 +4781,19 @@ dependencies = [ "syn 2.0.67", ] +[[package]] +name = "substrate-bn" +version = "0.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "72b5bbfa79abbae15dd642ea8176a21a635ff3c00059961d1ea27ad04e5b441c" +dependencies = [ + "byteorder", + "crunchy", + "lazy_static", + "rand 0.8.5", + "rustc-hex", +] + [[package]] name = "subtle" version = "2.6.0" @@ -4781,6 +5362,12 @@ dependencies = [ "tinyvec", ] +[[package]] +name = "unicode-segmentation" +version = "1.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d4c87d22b6e3f4a18d4d40ef354e97c90fcb14dd91d7dc0aa9d8a1172ebf7202" + [[package]] name = "unicode-xid" version = "0.2.4" @@ -5305,3 +5892,31 @@ dependencies = [ "quote", "syn 2.0.67", ] + +[[package]] +name = "zstd" +version = "0.13.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2d789b1514203a1120ad2429eae43a7bd32b90976a7bb8a05f7ec02fa88cc23a" +dependencies = [ + "zstd-safe", +] + +[[package]] +name = "zstd-safe" +version = "7.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1cd99b45c6bc03a018c8b8a86025678c87e55526064e38f9df301989dce7ec0a" +dependencies = [ + "zstd-sys", +] + +[[package]] +name = "zstd-sys" +version = "2.0.11+zstd.1.5.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "75652c55c0b6f3e6f12eb786fe1bc960396bf05a1eb3bf1f3691c3610ac2e6d4" +dependencies = [ + "cc", + "pkg-config", +] diff --git a/bolt-sidecar/Cargo.toml b/bolt-sidecar/Cargo.toml index ae0cbcf05..379191d7b 100644 --- a/bolt-sidecar/Cargo.toml +++ b/bolt-sidecar/Cargo.toml @@ -8,23 +8,17 @@ default-run = "bolt-sidecar" # core clap = { version = "4.5.4", features = ["derive"] } tokio = { version = "1", features = ["full"] } +axum = { version = "0.7", features = ["macros"] } warp = "0.3.7" futures = "0.3" -axum = { version = "0.7", features = ["macros"] } # crypto blst = "0.3.12" secp256k1 = { version = "0.29.0", features = ["rand"] } # alloy -alloy-rpc-client = { git = "https://github.com/alloy-rs/alloy", features = [ - "reqwest", - "ws", - "pubsub", -] } -alloy-provider = { git = "https://github.com/alloy-rs/alloy", features = [ - "ws", -] } +alloy-rpc-client = { git = "https://github.com/alloy-rs/alloy", features = ["reqwest", "ws", "pubsub"] } +alloy-provider = { git = "https://github.com/alloy-rs/alloy", features = ["ws"] } alloy-signer = { git = "https://github.com/alloy-rs/alloy" } alloy-signer-local = { git = "https://github.com/alloy-rs/alloy" } alloy-transport = { git = "https://github.com/alloy-rs/alloy" } @@ -34,14 +28,16 @@ alloy-transport-ws = { git = "https://github.com/alloy-rs/alloy" } alloy-pubsub = { git = "https://github.com/alloy-rs/alloy" } alloy-rpc-types = { git = "https://github.com/alloy-rs/alloy" } alloy-rpc-types-beacon = { git = "https://github.com/alloy-rs/alloy" } -alloy-consensus = { git = "https://github.com/alloy-rs/alloy", features = [ - "k256", -] } +alloy-consensus = { git = "https://github.com/alloy-rs/alloy", features = ["k256"] } alloy-json-rpc = { git = "https://github.com/alloy-rs/alloy" } alloy-primitives = { version = "0.7.1", features = ["rand"] } alloy-network = { git = "https://github.com/alloy-rs/alloy" } alloy-rlp = "0.3" +# reth +reth-primitives = { git = "https://github.com/paradigmxyz/reth", rev = "71c404d" } +# reth-provider = { git = "https://github.com/paradigmxyz/reth", rev = "71c404d" } + reqwest = "0.12" ethereum-consensus = { git = "https://github.com/ralexstokes/ethereum-consensus", rev = "cf3c404" } beacon-api-client = { git = "https://github.com/ralexstokes/ethereum-consensus", rev = "cf3c404" } diff --git a/bolt-sidecar/bin/sidecar.rs b/bolt-sidecar/bin/sidecar.rs index 66cf49646..2ed342d5d 100644 --- a/bolt-sidecar/bin/sidecar.rs +++ b/bolt-sidecar/bin/sidecar.rs @@ -1,3 +1,5 @@ +use std::time::Duration; + use bolt_sidecar::{ crypto::{ bls::{from_bls_signature_to_consensus_signature, Signer, SignerBLS}, @@ -6,7 +8,7 @@ use bolt_sidecar::{ json_rpc::{api::ApiError, start_server}, primitives::{ BatchedSignedConstraints, ChainHead, CommitmentRequest, ConstraintsMessage, - LocalPayloadFetcher, NoopPayloadFetcher, SignedConstraints, + LocalPayloadFetcher, SignedConstraints, }, spec::ConstraintsApi, start_builder_proxy, @@ -14,10 +16,9 @@ use bolt_sidecar::{ fetcher::{StateClient, StateFetcher}, ExecutionState, }, - BuilderProxyConfig, Config, MevBoostClient, Opts, + BuilderProxyConfig, Config, MevBoostClient, }; -use clap::Parser; use tokio::sync::mpsc; use tracing::info; @@ -27,31 +28,34 @@ async fn main() -> eyre::Result<()> { info!("Starting sidecar"); - let opts = Opts::parse(); - let config = Config::try_from(opts)?; + let config = Config::parse_from_cli()?; let (api_events, mut api_events_rx) = mpsc::channel(1024); + // TODO: support external signers let signer = Signer::new(config.private_key.clone().unwrap()); let state_client = StateClient::new(&config.execution_api, 8); + let mevboost_client = MevBoostClient::new(&config.mevboost_url); let head = state_client.get_head().await?; - let mut execution_state = ExecutionState::new(state_client, ChainHead::new(0, head)).await?; - let mevboost_client = MevBoostClient::new(config.mevboost_url.clone()); - let shutdown_tx = start_server(config, api_events).await?; let builder_proxy_config = BuilderProxyConfig::default(); let (payload_tx, mut payload_rx) = mpsc::channel(1); - let _payload_fetcher = LocalPayloadFetcher::new(payload_tx); - - let _builder_proxy = tokio::spawn(async move { - if let Err(e) = start_builder_proxy(NoopPayloadFetcher, builder_proxy_config).await { - tracing::error!("Builder proxy failed: {:?}", e); + let payload_fetcher = LocalPayloadFetcher::new(payload_tx); + + tokio::spawn(async move { + loop { + if let Err(e) = + start_builder_proxy(payload_fetcher.clone(), builder_proxy_config.clone()).await + { + tracing::error!("Builder API proxy failed: {:?}", e); + tokio::time::sleep(Duration::from_secs(5)).await; + } } }); @@ -94,8 +98,18 @@ async fn main() -> eyre::Result<()> { } Some(request) = payload_rx.recv() => { tracing::info!("Received payload request: {:?}", request); - let _response = execution_state.get_block_template(request.slot); - // TODO: extract payload & bid + let Some(response) = execution_state.get_block_template(request.slot) else { + tracing::warn!("No block template found for slot {} when requested", request.slot); + let _ = request.response.send(None); + continue; + }; + + // For fallback block building, we need to turn a block template into an actual SignedBuilderBid. + // This will also require building the full ExecutionPayload that we want the proposer to commit to. + // Once we have that, we need to send it as response to the validator via the pending get_header RPC call. + // The validator will then call get_payload with the corresponding SignedBlindedBeaconBlock. We then need to + // respond with the full ExecutionPayload inside the BeaconBlock (+ blobs if any). + let _ = request.response.send(None); } diff --git a/bolt-sidecar/src/api/builder.rs b/bolt-sidecar/src/api/builder.rs index c6d93b452..18e27be19 100644 --- a/bolt-sidecar/src/api/builder.rs +++ b/bolt-sidecar/src/api/builder.rs @@ -113,6 +113,8 @@ impl<T: ConstraintsApi, P: PayloadFetcher + Send + Sync> BuilderProxyServer<T, P { Ok(Ok(header)) => { tracing::debug!(elapsed = ?start.elapsed(), "Returning signed builder bid: {:?}", header); + // TODO: verify proofs here. If they are invalid, we should fall back to locally built block + Ok(Json(header.bid)) } Ok(Err(_)) | Err(_) => { @@ -210,14 +212,14 @@ impl Default for BuilderProxyConfig { pub async fn start_builder_proxy<P: PayloadFetcher + Send + Sync + 'static>( payload_fetcher: P, config: BuilderProxyConfig, -) -> Result<(), Box<dyn std::error::Error>> { +) -> Result<(), eyre::Error> { tracing::info!( port = config.port, target = config.mev_boost_url, "Starting builder proxy..." ); - let mev_boost = MevBoostClient::new(config.mev_boost_url); + let mev_boost = MevBoostClient::new(&config.mev_boost_url); let server = Arc::new(BuilderProxyServer::new(mev_boost, payload_fetcher)); let router = Router::new() .route("/", get(index)) diff --git a/bolt-sidecar/src/builder/mod.rs b/bolt-sidecar/src/builder/mod.rs new file mode 100644 index 000000000..891fda2df --- /dev/null +++ b/bolt-sidecar/src/builder/mod.rs @@ -0,0 +1,4 @@ +pub mod template; +pub use template::BlockTemplate; + +pub mod payload_builder; diff --git a/bolt-sidecar/src/builder/payload_builder.rs b/bolt-sidecar/src/builder/payload_builder.rs new file mode 100644 index 000000000..f7206c78e --- /dev/null +++ b/bolt-sidecar/src/builder/payload_builder.rs @@ -0,0 +1,200 @@ +#![allow(missing_docs)] +#![allow(unused)] + +use alloy_consensus::TxEnvelope; +use alloy_primitives::{Address, Bytes, B256, U256}; +use ethereum_consensus::{ + capella::spec, + crypto::bls::{PublicKey as BlsPublicKey, SecretKey as BlsSecretKey}, + deneb::mainnet::ExecutionPayloadHeader, + ssz::prelude::{ssz_rs, ByteList, ByteVector, List}, + types::mainnet::ExecutionPayload, +}; +use reth_primitives::{ + constants::BEACON_NONCE, proofs, BlockBody, Bloom, Header, SealedBlock, SealedHeader, + TransactionSigned, EMPTY_OMMER_ROOT_HASH, +}; + +use crate::primitives::{BuilderBid, Slot}; + +#[derive(Debug, thiserror::Error)] +pub enum PayloadBuilderError { + #[error("Failed to build payload: {0}")] + Custom(String), +} + +#[derive(Debug)] +pub struct FallbackPayloadBuilder<SRP> +where + SRP: StateRootProvider, +{ + state_root_provider: SRP, + + fee_recipient: Address, + + // keypair used for signing the payload + private_key: BlsSecretKey, + public_key: BlsPublicKey, +} + +/// Minimal execution context required to build a valid payload on the target slot. +#[derive(Debug)] +pub struct ExecutionContext { + head_slot_number: Slot, + parent_hash: B256, + transactions: Vec<TransactionSigned>, + block: NextBlockInfo, +} + +#[derive(Debug)] +pub struct NextBlockInfo { + number: u64, + timestamp: u64, + prev_randao: B256, + base_fee: u64, + extra_data: Bytes, + gas_limit: u64, +} + +/// Provider that is able to compute the state root over a set of state diffs. +/// TODO: how do we avoid full access to the state DB here? +pub trait StateRootProvider { + fn get_state_root(&self) -> Result<B256, PayloadBuilderError>; +} + +impl<SRP> FallbackPayloadBuilder<SRP> +where + SRP: StateRootProvider, +{ + /// Build a minimal payload to be used as a fallback + pub async fn build_fallback_payload( + &self, + context: ExecutionContext, + ) -> Result<BuilderBid, PayloadBuilderError> { + // TODO: actually get the state root (needs to count post-state diffs) + let state_root = self.state_root_provider.get_state_root()?; + let transactions_root = proofs::calculate_transaction_root(&context.transactions); + + // TODO: fill all of these with correct values + let withdrawals_root = Some(B256::default()); + let receipts_root = B256::default(); + let logs_bloom = Bloom::default(); + let gas_used = 0; + let parent_beacon_root = B256::default(); + let value = U256::ZERO; + + let header = Header { + parent_hash: context.parent_hash, + ommers_hash: EMPTY_OMMER_ROOT_HASH, + beneficiary: self.fee_recipient, + state_root, + transactions_root, + receipts_root, + withdrawals_root, + logs_bloom, + difficulty: U256::ZERO, + number: context.block.number, + gas_limit: context.block.gas_limit, + gas_used, + timestamp: context.block.timestamp, + mix_hash: context.block.prev_randao, + nonce: BEACON_NONCE, + base_fee_per_gas: Some(context.block.base_fee), + blob_gas_used: None, + excess_blob_gas: None, + parent_beacon_block_root: Some(parent_beacon_root), + extra_data: context.block.extra_data, + }; + + let body = BlockBody { + transactions: context.transactions, + ommers: Vec::new(), + withdrawals: None, + }; + + let sealed_block = SealedBlock::new(header.seal_slow(), body); + let submission = BuilderBid { + header: to_execution_payload_header(&sealed_block.header), + blob_kzg_commitments: List::default(), + public_key: self.public_key.clone(), + value, + }; + + Ok(submission) + } +} + +pub(crate) fn to_execution_payload_header(value: &SealedHeader) -> ExecutionPayloadHeader { + ExecutionPayloadHeader { + parent_hash: to_bytes32(value.parent_hash), + fee_recipient: to_bytes20(value.beneficiary), + state_root: to_bytes32(value.state_root), + receipts_root: to_bytes32(value.receipts_root), + logs_bloom: to_byte_vector(value.logs_bloom), + prev_randao: to_bytes32(value.mix_hash), + block_number: value.number, + gas_limit: value.gas_limit, + gas_used: value.gas_used, + timestamp: value.timestamp, + extra_data: ByteList::try_from(value.extra_data.as_ref()).unwrap(), + base_fee_per_gas: ssz_rs::U256::from(value.base_fee_per_gas.unwrap_or_default()), + block_hash: to_bytes32(value.hash()), + transactions_root: value.transactions_root, + withdrawals_root: value.withdrawals_root.unwrap_or_default(), + blob_gas_used: value.blob_gas_used.unwrap_or_default(), + excess_blob_gas: value.excess_blob_gas.unwrap_or_default(), + } +} + +pub(crate) fn to_execution_payload(value: &SealedBlock) -> ExecutionPayload { + let hash = value.hash(); + let header = &value.header; + let transactions = &value.body; + let withdrawals = &value.withdrawals; + let transactions = transactions + .iter() + .map(|t| spec::Transaction::try_from(t.envelope_encoded().as_ref()).unwrap()) + .collect::<Vec<_>>(); + let withdrawals = withdrawals + .as_ref() + .unwrap() + .iter() + .map(|w| spec::Withdrawal { + index: w.index as usize, + validator_index: w.validator_index as usize, + address: to_bytes20(w.address), + amount: w.amount, + }) + .collect::<Vec<_>>(); + + let payload = spec::ExecutionPayload { + parent_hash: to_bytes32(header.parent_hash), + fee_recipient: to_bytes20(header.beneficiary), + state_root: to_bytes32(header.state_root), + receipts_root: to_bytes32(header.receipts_root), + logs_bloom: to_byte_vector(header.logs_bloom), + prev_randao: to_bytes32(header.mix_hash), + block_number: header.number, + gas_limit: header.gas_limit, + gas_used: header.gas_used, + timestamp: header.timestamp, + extra_data: ByteList::try_from(header.extra_data.as_ref()).unwrap(), + base_fee_per_gas: ssz_rs::U256::from(header.base_fee_per_gas.unwrap_or_default()), + block_hash: to_bytes32(hash), + transactions: TryFrom::try_from(transactions).unwrap(), + withdrawals: TryFrom::try_from(withdrawals).unwrap(), + }; + ExecutionPayload::Capella(payload) +} + +fn to_bytes32(value: B256) -> spec::Bytes32 { + spec::Bytes32::try_from(value.as_ref()).unwrap() +} + +fn to_bytes20(value: Address) -> spec::ExecutionAddress { + spec::ExecutionAddress::try_from(value.as_ref()).unwrap() +} + +fn to_byte_vector(value: Bloom) -> ByteVector<256> { + ByteVector::<256>::try_from(value.as_ref()).unwrap() +} diff --git a/bolt-sidecar/src/template/mod.rs b/bolt-sidecar/src/builder/template.rs similarity index 95% rename from bolt-sidecar/src/template/mod.rs rename to bolt-sidecar/src/builder/template.rs index 84a0c1f68..10c23225e 100644 --- a/bolt-sidecar/src/template/mod.rs +++ b/bolt-sidecar/src/builder/template.rs @@ -116,21 +116,6 @@ impl BlockTemplate { } } -/// StateDiff tracks the intermediate changes to the state according to the block template. -#[derive(Debug, Default)] -pub struct StateDiff { - diffs: HashMap<Address, (u64, U256)>, -} - -impl StateDiff { - /// Returns a tuple of the nonce and balance diff for the given address. - /// The nonce diff should be added to the current nonce, the balance diff should be subtracted from - /// the current balance. - pub fn get_diff(&self, address: &Address) -> Option<(u64, U256)> { - self.diffs.get(address).copied() - } -} - impl TryFrom<BlockTemplate> for PayloadAndBid { type Error = Box<dyn std::error::Error>; @@ -144,6 +129,28 @@ impl TryFrom<BlockTemplate> for PayloadAndBid { }, signature: todo!(), }; + + Ok(PayloadAndBid { + payload: todo!(), + bid, + }) + } +} + +/// StateDiff tracks the intermediate changes to the state according to the block template. +#[derive(Debug, Default)] +pub struct StateDiff { + /// Map of diffs per address. Each diff is a tuple of the nonce and balance diff + /// that should be applied to the current state. + diffs: HashMap<Address, (u64, U256)>, +} + +impl StateDiff { + /// Returns a tuple of the nonce and balance diff for the given address. + /// The nonce diff should be added to the current nonce, the balance diff should be subtracted from + /// the current balance. + pub fn get_diff(&self, address: &Address) -> Option<(u64, U256)> { + self.diffs.get(address).copied() } } diff --git a/bolt-sidecar/src/client/mevboost.rs b/bolt-sidecar/src/client/mevboost.rs index 744019b58..61589864e 100644 --- a/bolt-sidecar/src/client/mevboost.rs +++ b/bolt-sidecar/src/client/mevboost.rs @@ -29,7 +29,7 @@ pub struct MevBoostClient { impl MevBoostClient { /// Creates a new MEV-Boost client with the given URL. - pub fn new(url: String) -> Self { + pub fn new(url: &str) -> Self { Self { url: url.trim_end_matches('/').to_string(), client: reqwest::ClientBuilder::new() diff --git a/bolt-sidecar/src/client/rpc.rs b/bolt-sidecar/src/client/rpc.rs index 8d628e834..ed084a0d2 100644 --- a/bolt-sidecar/src/client/rpc.rs +++ b/bolt-sidecar/src/client/rpc.rs @@ -16,8 +16,8 @@ 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 client that supports batching. +/// Implements all methods that are relevant to Bolt state. #[derive(Clone, Debug)] pub struct RpcClient(alloy::RpcClient<Http<Client>>); diff --git a/bolt-sidecar/src/config.rs b/bolt-sidecar/src/config.rs index ca2652384..ed8a5ef81 100644 --- a/bolt-sidecar/src/config.rs +++ b/bolt-sidecar/src/config.rs @@ -73,6 +73,14 @@ impl Default for Config { } } +impl Config { + /// Parse the command-line options and return a new `Config` instance + pub fn parse_from_cli() -> eyre::Result<Self> { + let opts = Opts::parse(); + Self::try_from(opts) + } +} + impl TryFrom<Opts> for Config { type Error = eyre::Report; diff --git a/bolt-sidecar/src/lib.rs b/bolt-sidecar/src/lib.rs index 38c1ce246..ff9b8d0ee 100644 --- a/bolt-sidecar/src/lib.rs +++ b/bolt-sidecar/src/lib.rs @@ -20,7 +20,7 @@ mod common; /// Functionality for building local block templates that can /// be used as a fallback for proposers. It's also used to keep /// any intermediary state that is needed to simulate EVM execution -mod template; +pub mod builder; /// Configuration and command-line argument parsing mod config; diff --git a/bolt-sidecar/src/primitives/mod.rs b/bolt-sidecar/src/primitives/mod.rs index ee6ff68c0..6a5c5369d 100644 --- a/bolt-sidecar/src/primitives/mod.rs +++ b/bolt-sidecar/src/primitives/mod.rs @@ -1,6 +1,9 @@ +// TODO: add docs +#![allow(missing_docs)] + use std::sync::{atomic::AtomicU64, Arc}; -use alloy_primitives::{Bytes, TxHash, U256}; +use alloy_primitives::U256; use ethereum_consensus::{ capella, crypto::{KzgCommitment, PublicKey as BlsPublicKey, Signature as BlsSignature}, @@ -32,23 +35,6 @@ pub use transaction::TxInfo; /// An alias for a Beacon Chain slot number pub type Slot = u64; -/// An enum representing all possible (signed) commitments. -#[derive(Debug)] -pub enum Commitment { - /// Inclusion commitment, accepted and signed by the proposer - /// through this sidecar's signer. - Inclusion(InclusionCommitment), -} - -#[derive(Debug)] -pub struct InclusionCommitment { - pub slot: Slot, - pub tx_hash: TxHash, - pub raw_tx: Bytes, - // TODO: - pub signature: Bytes, -} - /// Minimal account state needed for commitment validation. #[derive(Debug, Clone, Copy)] pub struct AccountState { @@ -79,14 +65,6 @@ pub struct SignedBuilderBidWithProofs { pub proofs: List<ConstraintProof, 300>, } -#[derive(Debug, Default, Clone, SimpleSerialize, serde::Serialize, serde::Deserialize)] -pub struct MerkleMultiProof { - // We use List here for SSZ, TODO: choose max - transaction_hashes: List<Hash32, 300>, - generalized_indexes: List<u64, 300>, - merkle_hashes: List<Hash32, 1000>, -} - #[derive(Debug, Default, Clone, SimpleSerialize, serde::Serialize, serde::Deserialize)] pub struct ConstraintProof { #[serde(rename = "txHash")] @@ -102,6 +80,14 @@ pub struct MerkleProof { hashes: List<Hash32, 1000>, } +#[derive(Debug, Default, Clone, SimpleSerialize, serde::Serialize, serde::Deserialize)] +pub struct MerkleMultiProof { + // We use List here for SSZ, TODO: choose max + transaction_hashes: List<Hash32, 300>, + generalized_indexes: List<u64, 300>, + merkle_hashes: List<Hash32, 1000>, +} + #[derive(Debug)] pub struct FetchPayloadRequest { pub slot: u64, @@ -114,6 +100,7 @@ pub struct PayloadAndBid { pub payload: GetPayloadResponse, } +#[derive(Debug, Clone)] pub struct LocalPayloadFetcher { tx: mpsc::Sender<FetchPayloadRequest>, } @@ -142,6 +129,7 @@ pub trait PayloadFetcher { async fn fetch_payload(&self, slot: u64) -> Option<PayloadAndBid>; } +#[derive(Debug)] pub struct NoopPayloadFetcher; #[async_trait::async_trait] diff --git a/bolt-sidecar/src/state/execution.rs b/bolt-sidecar/src/state/execution.rs index a9486031c..1f9645959 100644 --- a/bolt-sidecar/src/state/execution.rs +++ b/bolt-sidecar/src/state/execution.rs @@ -5,9 +5,9 @@ use std::collections::HashMap; use thiserror::Error; use crate::{ + builder::BlockTemplate, common::{calculate_max_basefee, validate_transaction}, primitives::{AccountState, ChainHead, CommitmentRequest, Slot}, - template::BlockTemplate, }; use super::{fetcher::StateFetcher, StateError}; diff --git a/bolt-sidecar/src/state/fetcher.rs b/bolt-sidecar/src/state/fetcher.rs index ecd9501f3..7f1b9f1da 100644 --- a/bolt-sidecar/src/state/fetcher.rs +++ b/bolt-sidecar/src/state/fetcher.rs @@ -15,6 +15,7 @@ const MAX_RETRIES: u32 = 8; /// The retry backoff in milliseconds. const RETRY_BACKOFF_MS: u64 = 200; +/// A trait for fetching state updates. pub trait StateFetcher { async fn get_state_update( &self, @@ -23,7 +24,9 @@ pub trait StateFetcher { ) -> Result<StateUpdate, TransportError>; async fn get_head(&self) -> Result<u64, TransportError>; + async fn get_basefee(&self, block_number: Option<u64>) -> Result<u128, TransportError>; + async fn get_account_state( &self, address: &Address, @@ -31,13 +34,15 @@ pub trait StateFetcher { ) -> Result<AccountState, TransportError>; } -#[derive(Clone)] +/// A basic state fetcher that uses an RPC client to fetch state updates. +#[derive(Clone, Debug)] pub struct StateClient { client: RpcClient, retry_backoff: Duration, } impl StateClient { + /// Create a new `StateClient` with the given URL and maximum retries. pub fn new(url: &str, max_retries: u32) -> Self { let client = RpcClient::new(url); Self { diff --git a/bolt-sidecar/src/types/mod.rs b/bolt-sidecar/src/types/mod.rs deleted file mode 100644 index a65058857..000000000 --- a/bolt-sidecar/src/types/mod.rs +++ /dev/null @@ -1,178 +0,0 @@ -use alloy_primitives::U256; -use ethereum_consensus::{ - capella, - crypto::KzgCommitment, - deneb::mainnet::{BlobsBundle, ExecutionPayloadHeader, MAX_BLOB_COMMITMENTS_PER_BLOCK}, - primitives::{BlsPublicKey, BlsSignature, Hash32}, - serde::as_str, - ssz::prelude::*, - types::mainnet::ExecutionPayload, - Fork, -}; -use tokio::sync::{mpsc, oneshot}; - -pub mod commitment; -pub mod constraint; -pub mod transaction; - -/// An alias for a Beacon Chain slot number -pub type Slot = u64; - -/// Minimal account state needed for commitment validation. -#[derive(Debug, Clone, Copy)] -pub struct AccountState { - /// The nonce of the account. This is the number of transactions sent from this account - /// and should be the - pub transaction_count: u64, - pub balance: U256, -} - -#[derive(Debug, Default, Clone, SimpleSerialize, serde::Serialize, serde::Deserialize)] -pub struct BuilderBid { - pub header: ExecutionPayloadHeader, - pub blob_kzg_commitments: List<KzgCommitment, MAX_BLOB_COMMITMENTS_PER_BLOCK>, - #[serde(with = "as_str")] - pub value: U256, - #[serde(rename = "pubkey")] - pub public_key: BlsPublicKey, -} - -#[derive(Debug, Default, Clone, SimpleSerialize, serde::Serialize, serde::Deserialize)] -pub struct SignedBuilderBid { - pub message: BuilderBid, - pub signature: BlsSignature, -} - -#[derive(Debug, Default, Clone, SimpleSerialize, serde::Serialize, serde::Deserialize)] -pub struct SignedBuilderBidWithProofs { - pub bid: SignedBuilderBid, - pub proofs: List<ConstraintProof, 300>, -} - -#[derive(Debug, Default, Clone, SimpleSerialize, serde::Serialize, serde::Deserialize)] -pub struct MerkleMultiProof { - // We use List here for SSZ, TODO: choose max - transaction_hashes: List<Hash32, 300>, - generalized_indexes: List<u64, 300>, - merkle_hashes: List<Hash32, 1000>, -} - -#[derive(Debug, Default, Clone, SimpleSerialize, serde::Serialize, serde::Deserialize)] -pub struct ConstraintProof { - #[serde(rename = "txHash")] - tx_hash: Hash32, - #[serde(rename = "merkleProof")] - merkle_proof: MerkleProof, -} - -#[derive(Debug, Default, Clone, SimpleSerialize, serde::Serialize, serde::Deserialize)] -pub struct MerkleProof { - index: u64, - // TODO: for now, max 1000 - hashes: List<Hash32, 1000>, -} - -pub struct FetchPayloadRequest { - pub slot: u64, - pub response: oneshot::Sender<Option<PayloadAndBid>>, -} - -pub struct PayloadAndBid { - pub bid: SignedBuilderBid, - pub payload: GetPayloadResponse, -} - -pub struct LocalPayloadFetcher { - tx: mpsc::Sender<FetchPayloadRequest>, -} - -#[async_trait::async_trait] -impl PayloadFetcher for LocalPayloadFetcher { - async fn fetch_payload(&self, slot: u64) -> Option<PayloadAndBid> { - let (tx, rx) = oneshot::channel(); - - let fetch_params = FetchPayloadRequest { slot, response: tx }; - - self.tx.send(fetch_params).await.ok()?; - - rx.await.ok().flatten() - } -} - -#[async_trait::async_trait] -pub trait PayloadFetcher { - async fn fetch_payload(&self, slot: u64) -> Option<PayloadAndBid>; -} - -pub struct NoopPayloadFetcher; - -#[async_trait::async_trait] -impl PayloadFetcher for NoopPayloadFetcher { - async fn fetch_payload(&self, slot: u64) -> Option<PayloadAndBid> { - tracing::info!(slot, "Fetch payload called"); - None - } -} - -/// TODO: implement SSZ -#[derive(Debug, Clone, serde::Serialize, serde::Deserialize)] -pub struct PayloadAndBlobs { - pub execution_payload: ExecutionPayload, - pub blobs_bundle: Option<BlobsBundle>, -} - -impl Default for PayloadAndBlobs { - fn default() -> Self { - Self { - execution_payload: ExecutionPayload::Capella(capella::ExecutionPayload::default()), - blobs_bundle: None, - } - } -} - -#[derive(Debug, serde::Serialize)] -#[serde(tag = "version", content = "data")] -pub enum GetPayloadResponse { - #[serde(rename = "bellatrix")] - Bellatrix(ExecutionPayload), - #[serde(rename = "capella")] - Capella(ExecutionPayload), - #[serde(rename = "deneb")] - Deneb(PayloadAndBlobs), -} - -impl GetPayloadResponse { - pub fn try_from_execution_payload(exec_payload: &PayloadAndBlobs) -> Option<Self> { - match exec_payload.execution_payload.version() { - Fork::Capella => Some(GetPayloadResponse::Capella( - exec_payload.execution_payload.clone(), - )), - Fork::Bellatrix => Some(GetPayloadResponse::Bellatrix( - exec_payload.execution_payload.clone(), - )), - Fork::Deneb => Some(GetPayloadResponse::Deneb(exec_payload.clone())), - _ => None, - } - } -} - -impl<'de> serde::Deserialize<'de> for GetPayloadResponse { - fn deserialize<D>(deserializer: D) -> Result<Self, D::Error> - where - D: serde::Deserializer<'de>, - { - let value = serde_json::Value::deserialize(deserializer)?; - if let Ok(inner) = <_ as serde::Deserialize>::deserialize(&value) { - return Ok(Self::Capella(inner)); - } - if let Ok(inner) = <_ as serde::Deserialize>::deserialize(&value) { - return Ok(Self::Deneb(inner)); - } - if let Ok(inner) = <_ as serde::Deserialize>::deserialize(&value) { - return Ok(Self::Bellatrix(inner)); - } - Err(serde::de::Error::custom( - "no variant could be deserialized from input for GetPayloadResponse", - )) - } -}