From efef826b6000df8b60c054651837a8ff457142e7 Mon Sep 17 00:00:00 2001 From: eltitanb Date: Tue, 30 Sep 2025 20:24:29 +0100 Subject: [PATCH 1/9] fulu support first part --- Cargo.lock | 913 ++++++++++++++++-- Cargo.toml | 5 +- crates/common/Cargo.toml | 1 + crates/common/src/pbs/error.rs | 7 +- crates/common/src/pbs/types/beacon_block.rs | 186 ---- .../src/pbs/types/blinded_block_body.rs | 156 --- crates/common/src/pbs/types/blobs_bundle.rs | 19 - .../common/src/pbs/types/execution_payload.rs | 140 --- .../src/pbs/types/execution_requests.rs | 41 - crates/common/src/pbs/types/get_header.rs | 196 ---- crates/common/src/pbs/types/kzg.rs | 160 --- crates/common/src/pbs/types/mod.rs | 125 ++- crates/common/src/pbs/types/spec.rs | 61 -- crates/common/src/pbs/types/utils.rs | 51 - crates/common/src/types.rs | 1 + crates/pbs/src/mev_boost/get_header.rs | 107 +- crates/pbs/src/mev_boost/submit_block.rs | 112 ++- crates/pbs/src/routes/get_header.rs | 4 +- crates/pbs/src/routes/submit_block.rs | 6 +- tests/src/mock_relay.rs | 8 +- 20 files changed, 1103 insertions(+), 1196 deletions(-) delete mode 100644 crates/common/src/pbs/types/beacon_block.rs delete mode 100644 crates/common/src/pbs/types/blinded_block_body.rs delete mode 100644 crates/common/src/pbs/types/blobs_bundle.rs delete mode 100644 crates/common/src/pbs/types/execution_payload.rs delete mode 100644 crates/common/src/pbs/types/execution_requests.rs delete mode 100644 crates/common/src/pbs/types/get_header.rs delete mode 100644 crates/common/src/pbs/types/kzg.rs delete mode 100644 crates/common/src/pbs/types/spec.rs delete mode 100644 crates/common/src/pbs/types/utils.rs diff --git a/Cargo.lock b/Cargo.lock index 3994d591..18aa0ba6 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -292,7 +292,7 @@ checksum = "17248e392e79658b1faca7946bfe59825b891c3f6e382044499d99c57ba36a89" dependencies = [ "alloy-primitives 1.3.1", "alloy-sol-types", - "http", + "http 1.3.1", "serde", "serde_json", "thiserror 2.0.16", @@ -429,7 +429,7 @@ dependencies = [ "lru", "parking_lot", "pin-project", - "reqwest", + "reqwest 0.12.23", "serde", "serde_json", "thiserror 2.0.16", @@ -498,7 +498,7 @@ dependencies = [ "alloy-transport-ws", "futures", "pin-project", - "reqwest", + "reqwest 0.12.23", "serde", "serde_json", "tokio", @@ -771,7 +771,7 @@ dependencies = [ "alloy-json-rpc", "alloy-primitives 1.3.1", "auto_impl", - "base64", + "base64 0.22.1", "derive_more", "futures", "futures-utils-wasm", @@ -794,7 +794,7 @@ checksum = "c6332f6d470e465bf00f9306743ff172f54b83e7e31edfe28f1444c085ccb0e4" dependencies = [ "alloy-json-rpc", "alloy-transport", - "reqwest", + "reqwest 0.12.23", "serde_json", "tower 0.5.2", "tracing", @@ -830,8 +830,8 @@ dependencies = [ "alloy-pubsub", "alloy-transport", "futures", - "http", - "rustls", + "http 1.3.1", + "rustls 0.23.32", "serde_json", "tokio", "tokio-tungstenite", @@ -1167,8 +1167,8 @@ dependencies = [ "axum-core 0.4.5", "bytes", "futures-util", - "http", - "http-body", + "http 1.3.1", + "http-body 1.0.1", "http-body-util", "itoa", "matchit 0.7.3", @@ -1178,7 +1178,7 @@ dependencies = [ "pin-project-lite", "rustversion", "serde", - "sync_wrapper", + "sync_wrapper 1.0.2", "tower 0.5.2", "tower-layer", "tower-service", @@ -1195,10 +1195,10 @@ dependencies = [ "bytes", "form_urlencoded", "futures-util", - "http", - "http-body", + "http 1.3.1", + "http-body 1.0.1", "http-body-util", - "hyper", + "hyper 1.7.0", "hyper-util", "itoa", "matchit 0.8.4", @@ -1211,7 +1211,7 @@ dependencies = [ "serde_json", "serde_path_to_error", "serde_urlencoded", - "sync_wrapper", + "sync_wrapper 1.0.2", "tokio", "tower 0.5.2", "tower-layer", @@ -1228,13 +1228,13 @@ dependencies = [ "async-trait", "bytes", "futures-util", - "http", - "http-body", + "http 1.3.1", + "http-body 1.0.1", "http-body-util", "mime", "pin-project-lite", "rustversion", - "sync_wrapper", + "sync_wrapper 1.0.2", "tower-layer", "tower-service", ] @@ -1247,13 +1247,13 @@ checksum = "68464cd0412f486726fb3373129ef5d2993f90c34bc2bc1c1e9943b2f4fc7ca6" dependencies = [ "bytes", "futures-core", - "http", - "http-body", + "http 1.3.1", + "http-body 1.0.1", "http-body-util", "mime", "pin-project-lite", "rustversion", - "sync_wrapper", + "sync_wrapper 1.0.2", "tower-layer", "tower-service", "tracing", @@ -1270,8 +1270,8 @@ dependencies = [ "bytes", "futures-util", "headers", - "http", - "http-body", + "http 1.3.1", + "http-body 1.0.1", "http-body-util", "mime", "pin-project-lite", @@ -1308,12 +1308,34 @@ dependencies = [ "windows-targets 0.52.6", ] +[[package]] +name = "base-x" +version = "0.2.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4cbbc9d0964165b47557570cce6c952866c2678457aca742aafc9fb771d30270" + [[package]] name = "base16ct" version = "0.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4c7f02d4ea65f2c1853089ffd8d2787bdbc63de2f0d29dedbcf8ccdfa0ccd4cf" +[[package]] +name = "base256emoji" +version = "1.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b5e9430d9a245a77c92176e649af6e275f20839a48389859d1661e9a128d077c" +dependencies = [ + "const-str", + "match-lookup", +] + +[[package]] +name = "base64" +version = "0.21.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9d297deb1925b89f2ccc13d7635fa0714f12c87adce1c75356b39ca9b7178567" + [[package]] name = "base64" version = "0.22.1" @@ -1500,6 +1522,15 @@ dependencies = [ "zeroize", ] +[[package]] +name = "bs58" +version = "0.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bf88ba1141d185c399bee5288d850d63b8369520c1eafc32a0430b5b6c287bf4" +dependencies = [ + "tinyvec", +] + [[package]] name = "bumpalo" version = "3.19.0" @@ -1552,7 +1583,7 @@ dependencies = [ "comfy-table", "histogram", "rand 0.9.2", - "reqwest", + "reqwest 0.12.23", "serde", "serde_json", "tokio", @@ -1579,13 +1610,14 @@ dependencies = [ "alloy", "async-trait", "axum 0.8.4", - "base64", + "base64 0.22.1", "bimap", "bytes", "cipher 0.4.4", "ctr 0.9.2", "derive_more", "docker-image", + "eth2", "eth2_keystore", "ethereum_serde_utils 0.7.0", "ethereum_ssz", @@ -1596,7 +1628,7 @@ dependencies = [ "pbkdf2 0.12.2", "rand 0.9.2", "rayon", - "reqwest", + "reqwest 0.12.23", "serde", "serde_json", "serde_yaml", @@ -1644,7 +1676,7 @@ dependencies = [ "lazy_static", "parking_lot", "prometheus", - "reqwest", + "reqwest 0.12.23", "serde", "serde_json", "tokio", @@ -1694,7 +1726,7 @@ dependencies = [ "cb-pbs", "cb-signer", "eyre", - "reqwest", + "reqwest 0.12.23", "serde_json", "tempfile", "tokio", @@ -1894,6 +1926,12 @@ version = "0.9.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c2459377285ad874054d797f3ccebf984978aa39129f6eafde5cdc8315b612f8" +[[package]] +name = "const-str" +version = "0.4.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2f421161cb492475f1661ddc9815a745a1c894592070661180fdec3d4872e9c3" + [[package]] name = "const_format" version = "0.2.34" @@ -2096,6 +2134,33 @@ dependencies = [ "cipher 0.4.4", ] +[[package]] +name = "curve25519-dalek" +version = "4.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "97fb8b7c4503de7d6ae7b42ab72a5a59857b4c937ec27a3d4539dba95b5ab2be" +dependencies = [ + "cfg-if", + "cpufeatures", + "curve25519-dalek-derive", + "digest 0.10.7", + "fiat-crypto", + "rustc_version 0.4.1", + "subtle", + "zeroize", +] + +[[package]] +name = "curve25519-dalek-derive" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f46882e17999c6cc590af592290432be3bce0428cb0d5f8b6715e4dc7b383eb3" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.106", +] + [[package]] name = "da_commit" version = "0.8.1-rc.2" @@ -2238,6 +2303,26 @@ version = "2.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2a2330da5de22e8a3cb63252ce2abb30116bf5265e89c0e01bc17015ce30a476" +[[package]] +name = "data-encoding-macro" +version = "0.1.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "47ce6c96ea0102f01122a185683611bd5ac8d99e62bc59dd12e6bda344ee673d" +dependencies = [ + "data-encoding", + "data-encoding-macro-internal", +] + +[[package]] +name = "data-encoding-macro-internal" +version = "0.1.16" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8d162beedaa69905488a8da94f5ac3edb4dd4788b732fadb7bd120b2625c1976" +dependencies = [ + "data-encoding", + "syn 2.0.106", +] + [[package]] name = "der" version = "0.7.10" @@ -2428,6 +2513,31 @@ dependencies = [ "spki", ] +[[package]] +name = "ed25519" +version = "2.2.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "115531babc129696a58c64a4fef0a8bf9e9698629fb97e9e40767d235cfbcd53" +dependencies = [ + "pkcs8", + "signature", +] + +[[package]] +name = "ed25519-dalek" +version = "2.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "70e796c081cee67dc755e1a36a0a172b897fab85fc3f6bc48307991f64e4eca9" +dependencies = [ + "curve25519-dalek", + "ed25519", + "rand_core 0.6.4", + "serde", + "sha2 0.10.9", + "subtle", + "zeroize", +] + [[package]] name = "educe" version = "0.6.0" @@ -2584,6 +2694,25 @@ dependencies = [ "cfg-if", ] +[[package]] +name = "enr" +version = "0.13.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "851bd664a3d3a3c175cff92b2f0df02df3c541b4895d0ae307611827aae46152" +dependencies = [ + "alloy-rlp", + "base64 0.22.1", + "bytes", + "ed25519-dalek", + "hex", + "k256", + "log", + "rand 0.8.5", + "serde", + "sha3", + "zeroize", +] + [[package]] name = "enum-ordinalize" version = "4.3.0" @@ -2617,7 +2746,39 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "39cab71617ae0d63f51a36d69f866391735b51691dbda63cf6f96d042b63efeb" dependencies = [ "libc", - "windows-sys 0.61.0", + "windows-sys 0.59.0", +] + +[[package]] +name = "eth2" +version = "0.1.0" +source = "git+https://github.com/sigp/lighthouse?tag=v8.0.0-rc.0#e5b4983d6baf85770fe4539a565d8a2dd462bc53" +dependencies = [ + "derivative", + "either", + "enr", + "eth2_keystore", + "ethereum_serde_utils 0.8.0", + "ethereum_ssz", + "ethereum_ssz_derive", + "futures", + "futures-util", + "libp2p-identity", + "mediatype", + "multiaddr", + "pretty_reqwest_error", + "proto_array", + "rand 0.9.2", + "reqwest 0.11.27", + "reqwest-eventsource", + "sensitive_url", + "serde", + "serde_json", + "slashing_protection", + "ssz_types", + "test_random_derive", + "types", + "zeroize", ] [[package]] @@ -2731,6 +2892,17 @@ dependencies = [ "syn 2.0.106", ] +[[package]] +name = "eventsource-stream" +version = "0.2.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "74fef4569247a5f429d9156b9d0a2599914385dd189c539334c625d8099d90ab" +dependencies = [ + "futures-core", + "nom", + "pin-project-lite", +] + [[package]] name = "eyre" version = "0.6.12" @@ -2792,6 +2964,31 @@ dependencies = [ "subtle", ] +[[package]] +name = "fiat-crypto" +version = "0.2.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "28dea519a9695b9977216879a3ebfddf92f1c08c05d984f8996aecd6ecdc811d" + +[[package]] +name = "field-offset" +version = "0.3.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "38e2275cc4e4fc009b0669731a1e5ab7ebf11f469eaede2bab9309a5b4d6057f" +dependencies = [ + "memoffset", + "rustc_version 0.4.1", +] + +[[package]] +name = "filesystem" +version = "0.1.0" +source = "git+https://github.com/sigp/lighthouse?tag=v8.0.0-rc.0#e5b4983d6baf85770fe4539a565d8a2dd462bc53" +dependencies = [ + "winapi", + "windows-acl", +] + [[package]] name = "find-msvc-tools" version = "0.1.2" @@ -2938,6 +3135,12 @@ version = "0.3.31" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f90f7dce0722e95104fcb095585910c0977252f286e354b5e3bd38902cd99988" +[[package]] +name = "futures-timer" +version = "3.0.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f288b0a4f20f9a56b5d1da57e2227c661b7b16168e2f72365f57b63326e29b24" + [[package]] name = "futures-util" version = "0.3.31" @@ -3034,6 +3237,25 @@ dependencies = [ "subtle", ] +[[package]] +name = "h2" +version = "0.3.27" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0beca50380b1fc32983fc1cb4587bfa4bb9e78fc259aad4a0032d2080309222d" +dependencies = [ + "bytes", + "fnv", + "futures-core", + "futures-sink", + "futures-util", + "http 0.2.12", + "indexmap 2.11.4", + "slab", + "tokio", + "tokio-util", + "tracing", +] + [[package]] name = "h2" version = "0.4.12" @@ -3045,7 +3267,7 @@ dependencies = [ "fnv", "futures-core", "futures-sink", - "http", + "http 1.3.1", "indexmap 2.11.4", "slab", "tokio", @@ -3102,10 +3324,10 @@ version = "0.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b3314d5adb5d94bcdf56771f2e50dbbc80bb4bdf88967526706205ac9eff24eb" dependencies = [ - "base64", + "base64 0.22.1", "bytes", "headers-core", - "http", + "http 1.3.1", "httpdate", "mime", "sha1", @@ -3117,7 +3339,7 @@ version = "0.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "54b4a22553d4242c49fddb9ba998a99962b5cc6f22cb5a3482bec22522403ce4" dependencies = [ - "http", + "http 1.3.1", ] [[package]] @@ -3184,6 +3406,17 @@ dependencies = [ "digest 0.10.7", ] +[[package]] +name = "http" +version = "0.2.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "601cbb57e577e2f5ef5be8e7b83f0f63994f25aa94d673e54a92d5c516d101f1" +dependencies = [ + "bytes", + "fnv", + "itoa", +] + [[package]] name = "http" version = "1.3.1" @@ -3195,6 +3428,17 @@ dependencies = [ "itoa", ] +[[package]] +name = "http-body" +version = "0.4.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7ceab25649e9960c0311ea418d17bee82c0dcec1bd053b5f9a66e265a693bed2" +dependencies = [ + "bytes", + "http 0.2.12", + "pin-project-lite", +] + [[package]] name = "http-body" version = "1.0.1" @@ -3202,7 +3446,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1efedce1fb8e6913f23e0c92de8e62cd5b772a67e7b3946df930a62566c93184" dependencies = [ "bytes", - "http", + "http 1.3.1", ] [[package]] @@ -3213,8 +3457,8 @@ checksum = "b021d93e26becf5dc7e1b75b1bed1fd93124b374ceb73f43d4d4eafec896a64a" dependencies = [ "bytes", "futures-core", - "http", - "http-body", + "http 1.3.1", + "http-body 1.0.1", "pin-project-lite", ] @@ -3230,6 +3474,30 @@ version = "1.0.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "df3b46402a9d5adb4c86a0cf463f42e19994e3ee891101b1841f30a545cb49a9" +[[package]] +name = "hyper" +version = "0.14.32" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "41dfc780fdec9373c01bae43289ea34c972e40ee3c9f6b3c8801a35f35586ce7" +dependencies = [ + "bytes", + "futures-channel", + "futures-core", + "futures-util", + "h2 0.3.27", + "http 0.2.12", + "http-body 0.4.6", + "httparse", + "httpdate", + "itoa", + "pin-project-lite", + "socket2 0.5.10", + "tokio", + "tower-service", + "tracing", + "want", +] + [[package]] name = "hyper" version = "1.7.0" @@ -3240,9 +3508,9 @@ dependencies = [ "bytes", "futures-channel", "futures-core", - "h2", - "http", - "http-body", + "h2 0.4.12", + "http 1.3.1", + "http-body 1.0.1", "httparse", "httpdate", "itoa", @@ -3253,19 +3521,33 @@ dependencies = [ "want", ] +[[package]] +name = "hyper-rustls" +version = "0.24.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ec3efd23720e2049821a693cbc7e65ea87c72f1c58ff2f9522ff332b1491e590" +dependencies = [ + "futures-util", + "http 0.2.12", + "hyper 0.14.32", + "rustls 0.21.12", + "tokio", + "tokio-rustls 0.24.1", +] + [[package]] name = "hyper-rustls" version = "0.27.7" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e3c93eb611681b207e1fe55d5a71ecf91572ec8a6705cdb6857f7d8d5242cf58" dependencies = [ - "http", - "hyper", + "http 1.3.1", + "hyper 1.7.0", "hyper-util", - "rustls", + "rustls 0.23.32", "rustls-pki-types", "tokio", - "tokio-rustls", + "tokio-rustls 0.26.3", "tower-service", "webpki-roots 1.0.2", ] @@ -3276,13 +3558,26 @@ version = "0.5.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2b90d566bffbce6a75bd8b09a05aa8c2cb1fabb6cb348f8840c9e4c90a0d83b0" dependencies = [ - "hyper", + "hyper 1.7.0", "hyper-util", "pin-project-lite", "tokio", "tower-service", ] +[[package]] +name = "hyper-tls" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d6183ddfa99b85da61a140bea0efc93fdf56ceaa041b37d553518030827f9905" +dependencies = [ + "bytes", + "hyper 0.14.32", + "native-tls", + "tokio", + "tokio-native-tls", +] + [[package]] name = "hyper-tls" version = "0.6.0" @@ -3291,7 +3586,7 @@ checksum = "70206fc6890eaca9fde8a0bf71caa2ddfc9fe045ac9e5c70df101a7dbde866e0" dependencies = [ "bytes", "http-body-util", - "hyper", + "hyper 1.7.0", "hyper-util", "native-tls", "tokio", @@ -3305,20 +3600,20 @@ version = "0.1.17" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3c6995591a8f1380fcb4ba966a252a4b29188d51d2b89e3a252f5305be65aea8" dependencies = [ - "base64", + "base64 0.22.1", "bytes", "futures-channel", "futures-core", "futures-util", - "http", - "http-body", - "hyper", + "http 1.3.1", + "http-body 1.0.1", + "hyper 1.7.0", "ipnet", "libc", "percent-encoding", "pin-project-lite", "socket2 0.6.0", - "system-configuration", + "system-configuration 0.6.1", "tokio", "tower-service", "tracing", @@ -3539,7 +3834,7 @@ dependencies = [ "libc", "recvmsg", "tokio", - "widestring", + "widestring 1.2.0", "windows-sys 0.52.0", ] @@ -3625,7 +3920,7 @@ version = "9.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5a87cc7a48537badeae96744432de36f4be2b4a34a05a5ef32e9dd8a1c169dde" dependencies = [ - "base64", + "base64 0.22.1", "js-sys", "ring", "serde", @@ -3644,6 +3939,7 @@ dependencies = [ "once_cell", "serdect", "sha2 0.10.9", + "signature", ] [[package]] @@ -3707,6 +4003,21 @@ version = "0.2.15" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f9fbbcab51052fe104eb5e5d351cf728d30a5be1fe14d9be8a3b097481fb97de" +[[package]] +name = "libp2p-identity" +version = "0.2.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3104e13b51e4711ff5738caa1fb54467c8604c2e94d607e27745bcf709068774" +dependencies = [ + "bs58", + "hkdf", + "multihash", + "quick-protobuf", + "sha2 0.10.9", + "thiserror 2.0.16", + "tracing", +] + [[package]] name = "libsqlite3-sys" version = "0.25.2" @@ -3784,6 +4095,17 @@ version = "1.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3e2e65a1a2e43cfcb47a895c4c8b10d1f4a61097f9f254f183aee60cad9c651d" +[[package]] +name = "match-lookup" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1265724d8cb29dbbc2b0f06fffb8bf1a8c0cf73a78eede9ba73a4a66c52a981e" +dependencies = [ + "proc-macro2", + "quote", + "syn 1.0.109", +] + [[package]] name = "matchers" version = "0.2.0" @@ -3805,12 +4127,27 @@ version = "0.8.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "47e1ffaa40ddd1f3ed91f717a33c8c0ee23fff369e3aa8772b9605cc1d22f4c3" +[[package]] +name = "mediatype" +version = "0.19.20" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "33746aadcb41349ec291e7f2f0a3aa6834d1d7c58066fb4b01f68efc4c4b7631" + [[package]] name = "memchr" version = "2.7.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "32a282da65faaf38286cf3be983213fcf1d2e2a58700e808f83f4ea9a4804bc0" +[[package]] +name = "memoffset" +version = "0.9.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "488016bfae457b036d996092f6cb448677611ce4449e970ceaf42695203f218a" +dependencies = [ + "autocfg", +] + [[package]] name = "merkle_proof" version = "0.2.0" @@ -3885,6 +4222,12 @@ version = "0.3.17" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6877bb514081ee2a7ff5ef9de3281f14a4dd4bceac4c09388074a6b5df8a139a" +[[package]] +name = "minimal-lexical" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "68354c5c6bd36d73ff3feceb05efa59b6acb7626617f4962be322a825e61f79a" + [[package]] name = "miniz_oxide" version = "0.8.9" @@ -3900,9 +4243,50 @@ version = "1.0.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "78bed444cc8a2160f01cbcf811ef18cac863ad68ae8ca62092e8db51d51c761c" dependencies = [ - "libc", - "wasi 0.11.1+wasi-snapshot-preview1", - "windows-sys 0.59.0", + "libc", + "wasi 0.11.1+wasi-snapshot-preview1", + "windows-sys 0.59.0", +] + +[[package]] +name = "multiaddr" +version = "0.18.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fe6351f60b488e04c1d21bc69e56b89cb3f5e8f5d22557d6e8031bdfd79b6961" +dependencies = [ + "arrayref", + "byteorder", + "data-encoding", + "libp2p-identity", + "multibase", + "multihash", + "percent-encoding", + "serde", + "static_assertions", + "unsigned-varint", + "url", +] + +[[package]] +name = "multibase" +version = "0.9.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8694bb4835f452b0e3bb06dbebb1d6fc5385b6ca1caf2e55fd165c042390ec77" +dependencies = [ + "base-x", + "base256emoji", + "data-encoding", + "data-encoding-macro", +] + +[[package]] +name = "multihash" +version = "0.19.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6b430e7953c29dd6a09afc29ff0bb69c6e306329ee6794700aee27b76a1aea8d" +dependencies = [ + "core2", + "unsigned-varint", ] [[package]] @@ -3928,6 +4312,16 @@ dependencies = [ "tempfile", ] +[[package]] +name = "nom" +version = "7.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d273983c5a657a70a3e8f2a01329822f3b8c8172b73826411a55751e404a0a4a" +dependencies = [ + "memchr", + "minimal-lexical", +] + [[package]] name = "nu-ansi-term" version = "0.50.1" @@ -4105,6 +4499,15 @@ version = "0.1.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d05e27ee213611ffe7d6348b942e8f942b37114c00cc03cec254295a4a17852e" +[[package]] +name = "openssl-src" +version = "300.5.3+3.5.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dc6bad8cd0233b63971e232cc9c5e83039375b8586d2312f31fda85db8f888c2" +dependencies = [ + "cc", +] + [[package]] name = "openssl-sys" version = "0.9.109" @@ -4113,6 +4516,7 @@ checksum = "90096e2e47630d78b7d1c20952dc621f957103f8bc2c8359ec81290d75238571" dependencies = [ "cc", "libc", + "openssl-src", "pkg-config", "vcpkg", ] @@ -4317,6 +4721,15 @@ dependencies = [ "zerocopy", ] +[[package]] +name = "pretty_reqwest_error" +version = "0.1.0" +source = "git+https://github.com/sigp/lighthouse?tag=v8.0.0-rc.0#e5b4983d6baf85770fe4539a565d8a2dd462bc53" +dependencies = [ + "reqwest 0.11.27", + "sensitive_url", +] + [[package]] name = "prettyplease" version = "0.2.37" @@ -4465,6 +4878,20 @@ dependencies = [ "prost", ] +[[package]] +name = "proto_array" +version = "0.2.0" +source = "git+https://github.com/sigp/lighthouse?tag=v8.0.0-rc.0#e5b4983d6baf85770fe4539a565d8a2dd462bc53" +dependencies = [ + "ethereum_ssz", + "ethereum_ssz_derive", + "safe_arith", + "serde", + "serde_yaml", + "superstruct", + "types", +] + [[package]] name = "protobuf" version = "3.7.2" @@ -4491,6 +4918,15 @@ version = "1.2.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a1d01941d82fa2ab50be1e79e6714289dd7cde78eba4c074bc5a4374f650dfe0" +[[package]] +name = "quick-protobuf" +version = "0.8.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9d6da84cc204722a989e01ba2f6e1e276e190f22263d0cb6ce8526fcdb0d2e1f" +dependencies = [ + "byteorder", +] + [[package]] name = "quinn" version = "0.11.9" @@ -4503,7 +4939,7 @@ dependencies = [ "quinn-proto", "quinn-udp", "rustc-hash", - "rustls", + "rustls 0.23.32", "socket2 0.6.0", "thiserror 2.0.16", "tokio", @@ -4523,7 +4959,7 @@ dependencies = [ "rand 0.9.2", "ring", "rustc-hash", - "rustls", + "rustls 0.23.32", "rustls-pki-types", "slab", "thiserror 2.0.16", @@ -4561,6 +4997,27 @@ version = "5.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "69cdb34c158ceb288df11e18b4bd39de994f6657d83847bdffdbd7f346754b0f" +[[package]] +name = "r2d2" +version = "0.8.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "51de85fb3fb6524929c8a2eb85e6b6d363de4e8c48f9e2c2eac4944abc181c93" +dependencies = [ + "log", + "parking_lot", + "scheduled-thread-pool", +] + +[[package]] +name = "r2d2_sqlite" +version = "0.21.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b4f5d0337e99cd5cacd91ffc326c6cc9d8078def459df560c4f9bf9ba4a51034" +dependencies = [ + "r2d2", + "rusqlite", +] + [[package]] name = "radium" version = "0.7.0" @@ -4731,24 +5188,70 @@ version = "0.8.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "caf4aa5b0f434c91fe5c7f1ecb6a5ece2130b02ad2a590589dda5146df959001" +[[package]] +name = "reqwest" +version = "0.11.27" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dd67538700a17451e7cba03ac727fb961abb7607553461627b97de0b89cf4a62" +dependencies = [ + "base64 0.21.7", + "bytes", + "encoding_rs", + "futures-core", + "futures-util", + "h2 0.3.27", + "http 0.2.12", + "http-body 0.4.6", + "hyper 0.14.32", + "hyper-rustls 0.24.2", + "hyper-tls 0.5.0", + "ipnet", + "js-sys", + "log", + "mime", + "native-tls", + "once_cell", + "percent-encoding", + "pin-project-lite", + "rustls 0.21.12", + "rustls-pemfile 1.0.4", + "serde", + "serde_json", + "serde_urlencoded", + "sync_wrapper 0.1.2", + "system-configuration 0.5.1", + "tokio", + "tokio-native-tls", + "tokio-rustls 0.24.1", + "tokio-util", + "tower-service", + "url", + "wasm-bindgen", + "wasm-bindgen-futures", + "wasm-streams", + "web-sys", + "webpki-roots 0.25.4", + "winreg", +] + [[package]] name = "reqwest" version = "0.12.23" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d429f34c8092b2d42c7c93cec323bb4adeb7c67698f70839adec842ec10c7ceb" dependencies = [ - "base64", + "base64 0.22.1", "bytes", "encoding_rs", "futures-core", "futures-util", - "h2", - "http", - "http-body", + "h2 0.4.12", + "http 1.3.1", + "http-body 1.0.1", "http-body-util", - "hyper", - "hyper-rustls", - "hyper-tls", + "hyper 1.7.0", + "hyper-rustls 0.27.7", + "hyper-tls 0.6.0", "hyper-util", "js-sys", "log", @@ -4757,15 +5260,15 @@ dependencies = [ "percent-encoding", "pin-project-lite", "quinn", - "rustls", + "rustls 0.23.32", "rustls-pki-types", "serde", "serde_json", "serde_urlencoded", - "sync_wrapper", + "sync_wrapper 1.0.2", "tokio", "tokio-native-tls", - "tokio-rustls", + "tokio-rustls 0.26.3", "tokio-util", "tower 0.5.2", "tower-http", @@ -4778,6 +5281,22 @@ dependencies = [ "webpki-roots 1.0.2", ] +[[package]] +name = "reqwest-eventsource" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f529a5ff327743addc322af460761dff5b50e0c826b9e6ac44c3195c50bb2026" +dependencies = [ + "eventsource-stream", + "futures-core", + "futures-timer", + "mime", + "nom", + "pin-project-lite", + "reqwest 0.11.27", + "thiserror 1.0.69", +] + [[package]] name = "rfc6979" version = "0.4.0" @@ -4931,7 +5450,19 @@ dependencies = [ "errno", "libc", "linux-raw-sys", - "windows-sys 0.61.0", + "windows-sys 0.59.0", +] + +[[package]] +name = "rustls" +version = "0.21.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3f56a14d1f48b391359b22f731fd4bd7e43c97f3c50eee276f3aa09c94784d3e" +dependencies = [ + "log", + "ring", + "rustls-webpki 0.101.7", + "sct", ] [[package]] @@ -4944,11 +5475,20 @@ dependencies = [ "once_cell", "ring", "rustls-pki-types", - "rustls-webpki", + "rustls-webpki 0.103.6", "subtle", "zeroize", ] +[[package]] +name = "rustls-pemfile" +version = "1.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1c74cae0a4cf6ccbbf5f359f08efdf8ee7e1dc532573bf0db71968cb56b1448c" +dependencies = [ + "base64 0.21.7", +] + [[package]] name = "rustls-pemfile" version = "2.2.0" @@ -4968,6 +5508,16 @@ dependencies = [ "zeroize", ] +[[package]] +name = "rustls-webpki" +version = "0.101.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8b6275d1ee7a1cd780b64aca7726599a1dbc893b1e64144529e55c3c2f745765" +dependencies = [ + "ring", + "untrusted", +] + [[package]] name = "rustls-webpki" version = "0.103.6" @@ -5026,6 +5576,15 @@ dependencies = [ "windows-sys 0.61.0", ] +[[package]] +name = "scheduled-thread-pool" +version = "0.2.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3cbc66816425a074528352f5789333ecff06ca41b36b0b0efdfbb29edc391a19" +dependencies = [ + "parking_lot", +] + [[package]] name = "schemars" version = "0.9.0" @@ -5068,6 +5627,16 @@ dependencies = [ "sha2 0.9.9", ] +[[package]] +name = "sct" +version = "0.7.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "da046153aa2352493d6cb7da4b6e5c0c057d8a1d0a9aa8560baffdd945acd414" +dependencies = [ + "ring", + "untrusted", +] + [[package]] name = "sec1" version = "0.7.3" @@ -5157,6 +5726,15 @@ version = "0.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "cd0b0ec5f1c1ca621c432a25813d8d60c88abe6d3e08a3eb9cf37d97a0fe3d73" +[[package]] +name = "sensitive_url" +version = "0.1.0" +source = "git+https://github.com/sigp/lighthouse?tag=v8.0.0-rc.0#e5b4983d6baf85770fe4539a565d8a2dd462bc53" +dependencies = [ + "serde", + "url", +] + [[package]] name = "serde" version = "1.0.226" @@ -5258,7 +5836,7 @@ version = "3.14.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c522100790450cf78eeac1507263d0a350d4d5b30df0c8e1fe051a10c22b376e" dependencies = [ - "base64", + "base64 0.22.1", "chrono", "hex", "indexmap 1.9.3", @@ -5402,6 +5980,24 @@ version = "0.4.11" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7a2ae44ef20feb57a68b23d846850f861394c2e02dc425a50098ae8c90267589" +[[package]] +name = "slashing_protection" +version = "0.1.0" +source = "git+https://github.com/sigp/lighthouse?tag=v8.0.0-rc.0#e5b4983d6baf85770fe4539a565d8a2dd462bc53" +dependencies = [ + "arbitrary", + "ethereum_serde_utils 0.8.0", + "filesystem", + "r2d2", + "r2d2_sqlite", + "rusqlite", + "serde", + "serde_json", + "tempfile", + "tracing", + "types", +] + [[package]] name = "smallvec" version = "1.15.1" @@ -5487,7 +6083,7 @@ dependencies = [ "eyre", "lazy_static", "prometheus", - "reqwest", + "reqwest 0.12.23", "serde", "tokio", "tracing", @@ -5590,6 +6186,12 @@ dependencies = [ "syn 2.0.106", ] +[[package]] +name = "sync_wrapper" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2047c6ded9c721764247e62cd3b03c09ffc529b2ba5b10ec482ae507a4a70160" + [[package]] name = "sync_wrapper" version = "1.0.2" @@ -5610,6 +6212,17 @@ dependencies = [ "syn 2.0.106", ] +[[package]] +name = "system-configuration" +version = "0.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ba3a3adc5c275d719af8cb4272ea1c4a6d668a777f37e115f6d11ddbc1c8e0e7" +dependencies = [ + "bitflags 1.3.2", + "core-foundation", + "system-configuration-sys 0.5.0", +] + [[package]] name = "system-configuration" version = "0.6.1" @@ -5618,7 +6231,17 @@ checksum = "3c879d448e9d986b661742763247d3693ed13609438cf3d006f51f5368a5ba6b" dependencies = [ "bitflags 2.9.4", "core-foundation", - "system-configuration-sys", + "system-configuration-sys 0.6.0", +] + +[[package]] +name = "system-configuration-sys" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a75fb188eb626b924683e3b95e3a48e63551fcfb51949de2f06a9d91dbee93c9" +dependencies = [ + "core-foundation-sys", + "libc", ] [[package]] @@ -5647,7 +6270,7 @@ dependencies = [ "getrandom 0.3.3", "once_cell", "rustix", - "windows-sys 0.61.0", + "windows-sys 0.59.0", ] [[package]] @@ -5843,13 +6466,23 @@ dependencies = [ "tokio", ] +[[package]] +name = "tokio-rustls" +version = "0.24.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c28327cf380ac148141087fbfb9de9d7bd4e84ab5d2c28fbc911d753de8a7081" +dependencies = [ + "rustls 0.21.12", + "tokio", +] + [[package]] name = "tokio-rustls" version = "0.26.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "05f63835928ca123f1bef57abbcd23bb2ba0ac9ae1235f1e65bda0d06e7786bd" dependencies = [ - "rustls", + "rustls 0.23.32", "tokio", ] @@ -5873,10 +6506,10 @@ checksum = "7a9daff607c6d2bf6c16fd681ccb7eecc83e4e2cdc1ca067ffaadfca5de7f084" dependencies = [ "futures-util", "log", - "rustls", + "rustls 0.23.32", "rustls-pki-types", "tokio", - "tokio-rustls", + "tokio-rustls 0.26.3", "tungstenite", "webpki-roots 0.26.11", ] @@ -5974,22 +6607,22 @@ dependencies = [ "async-stream", "async-trait", "axum 0.7.9", - "base64", + "base64 0.22.1", "bytes", - "h2", - "http", - "http-body", + "h2 0.4.12", + "http 1.3.1", + "http-body 1.0.1", "http-body-util", - "hyper", + "hyper 1.7.0", "hyper-timeout", "hyper-util", "percent-encoding", "pin-project", "prost", - "rustls-pemfile", + "rustls-pemfile 2.2.0", "socket2 0.5.10", "tokio", - "tokio-rustls", + "tokio-rustls 0.26.3", "tokio-stream", "tower 0.4.13", "tower-layer", @@ -6040,7 +6673,7 @@ dependencies = [ "futures-core", "futures-util", "pin-project-lite", - "sync_wrapper", + "sync_wrapper 1.0.2", "tokio", "tower-layer", "tower-service", @@ -6056,8 +6689,8 @@ dependencies = [ "bitflags 2.9.4", "bytes", "futures-util", - "http", - "http-body", + "http 1.3.1", + "http-body 1.0.1", "iri-string", "pin-project-lite", "tower 0.5.2", @@ -6236,11 +6869,11 @@ checksum = "4793cb5e56680ecbb1d843515b23b6de9a75eb04b66643e256a396d43be33c13" dependencies = [ "bytes", "data-encoding", - "http", + "http 1.3.1", "httparse", "log", "rand 0.9.2", - "rustls", + "rustls 0.23.32", "rustls-pki-types", "sha1", "thiserror 2.0.16", @@ -6373,6 +7006,12 @@ version = "0.2.11" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "673aac59facbab8a9007c7f6108d11f63b603f7cabff99fabf650fea5c32b861" +[[package]] +name = "unsigned-varint" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "eb066959b24b5196ae73cb057f45598450d2c5f71460e98c49b738086eff9c06" + [[package]] name = "untrusted" version = "0.9.0" @@ -6633,6 +7272,12 @@ dependencies = [ "wasm-bindgen", ] +[[package]] +name = "webpki-roots" +version = "0.25.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5f20c57d8d7db6d3b86154206ae5d8fba62dd39573114de97c2cb0578251f8e1" + [[package]] name = "webpki-roots" version = "0.26.11" @@ -6651,6 +7296,12 @@ dependencies = [ "rustls-pki-types", ] +[[package]] +name = "widestring" +version = "0.4.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c168940144dd21fd8046987c16a46a33d5fc84eec29ef9dcddc2ac9e31526b7c" + [[package]] name = "widestring" version = "1.2.0" @@ -6679,6 +7330,18 @@ version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" +[[package]] +name = "windows-acl" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "177b1723986bcb4c606058e77f6e8614b51c7f9ad2face6f6fd63dd5c8b3cec3" +dependencies = [ + "field-offset", + "libc", + "widestring 0.4.3", + "winapi", +] + [[package]] name = "windows-core" version = "0.62.0" @@ -6773,6 +7436,15 @@ dependencies = [ "windows-link 0.2.0", ] +[[package]] +name = "windows-sys" +version = "0.48.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "677d2418bec65e3338edb076e806bc1ec15693c5d0104683f2efe857f61056a9" +dependencies = [ + "windows-targets 0.48.5", +] + [[package]] name = "windows-sys" version = "0.52.0" @@ -6809,6 +7481,21 @@ dependencies = [ "windows-link 0.2.0", ] +[[package]] +name = "windows-targets" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9a2fa6e2155d7247be68c096456083145c183cbbbc2764150dda45a87197940c" +dependencies = [ + "windows_aarch64_gnullvm 0.48.5", + "windows_aarch64_msvc 0.48.5", + "windows_i686_gnu 0.48.5", + "windows_i686_msvc 0.48.5", + "windows_x86_64_gnu 0.48.5", + "windows_x86_64_gnullvm 0.48.5", + "windows_x86_64_msvc 0.48.5", +] + [[package]] name = "windows-targets" version = "0.52.6" @@ -6842,6 +7529,12 @@ dependencies = [ "windows_x86_64_msvc 0.53.0", ] +[[package]] +name = "windows_aarch64_gnullvm" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2b38e32f0abccf9987a4e3079dfb67dcd799fb61361e53e2882c3cbaf0d905d8" + [[package]] name = "windows_aarch64_gnullvm" version = "0.52.6" @@ -6854,6 +7547,12 @@ version = "0.53.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "86b8d5f90ddd19cb4a147a5fa63ca848db3df085e25fee3cc10b39b6eebae764" +[[package]] +name = "windows_aarch64_msvc" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dc35310971f3b2dbbf3f0690a219f40e2d9afcf64f9ab7cc1be722937c26b4bc" + [[package]] name = "windows_aarch64_msvc" version = "0.52.6" @@ -6866,6 +7565,12 @@ version = "0.53.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c7651a1f62a11b8cbd5e0d42526e55f2c99886c77e007179efff86c2b137e66c" +[[package]] +name = "windows_i686_gnu" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a75915e7def60c94dcef72200b9a8e58e5091744960da64ec734a6c6e9b3743e" + [[package]] name = "windows_i686_gnu" version = "0.52.6" @@ -6890,6 +7595,12 @@ version = "0.53.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9ce6ccbdedbf6d6354471319e781c0dfef054c81fbc7cf83f338a4296c0cae11" +[[package]] +name = "windows_i686_msvc" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8f55c233f70c4b27f66c523580f78f1004e8b5a8b659e05a4eb49d4166cca406" + [[package]] name = "windows_i686_msvc" version = "0.52.6" @@ -6902,6 +7613,12 @@ version = "0.53.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "581fee95406bb13382d2f65cd4a908ca7b1e4c2f1917f143ba16efe98a589b5d" +[[package]] +name = "windows_x86_64_gnu" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "53d40abd2583d23e4718fddf1ebec84dbff8381c07cae67ff7768bbf19c6718e" + [[package]] name = "windows_x86_64_gnu" version = "0.52.6" @@ -6914,6 +7631,12 @@ version = "0.53.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2e55b5ac9ea33f2fc1716d1742db15574fd6fc8dadc51caab1c16a3d3b4190ba" +[[package]] +name = "windows_x86_64_gnullvm" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0b7b52767868a23d5bab768e390dc5f5c55825b6d30b86c844ff2dc7414044cc" + [[package]] name = "windows_x86_64_gnullvm" version = "0.52.6" @@ -6926,6 +7649,12 @@ version = "0.53.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0a6e035dd0599267ce1ee132e51c27dd29437f63325753051e71dd9e42406c57" +[[package]] +name = "windows_x86_64_msvc" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ed94fce61571a4006852b7389a063ab983c02eb1bb37b47f8272ce92d06d9538" + [[package]] name = "windows_x86_64_msvc" version = "0.52.6" @@ -6947,6 +7676,16 @@ dependencies = [ "memchr", ] +[[package]] +name = "winreg" +version = "0.50.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "524e57b2c537c0f9b1e69f1965311ec12182b4122e45035b1508cd24d2adadb1" +dependencies = [ + "cfg-if", + "windows-sys 0.48.0", +] + [[package]] name = "wit-bindgen" version = "0.46.0" diff --git a/Cargo.toml b/Cargo.toml index 278b5f59..1ef5e3c2 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -24,8 +24,8 @@ axum = { version = "0.8.1", features = ["macros"] } axum-extra = { version = "0.10.0", features = ["typed-header"] } base64 = "0.22.1" bimap = { version = "0.6.3", features = ["serde"] } -blst = "^0.3.15" blsful = "^2.5" +blst = "^0.3.15" bytes = "1.10.1" cb-cli = { path = "crates/cli" } cb-common = { path = "crates/common" } @@ -48,6 +48,7 @@ headers = "0.4.0" indexmap = "2.2.6" jsonwebtoken = { version = "9.3.1", default-features = false } lazy_static = "1.5.0" +lh_eth2 = { package = "eth2", git = "https://github.com/sigp/lighthouse", tag = "v8.0.0-rc.0" } lh_eth2_keystore = { package = "eth2_keystore", git = "https://github.com/sigp/lighthouse", tag = "v8.0.0-rc.0" } lh_types = { package = "types", git = "https://github.com/sigp/lighthouse", tag = "v8.0.0-rc.0" } parking_lot = "0.12.3" @@ -82,4 +83,4 @@ url = { version = "2.5.0", features = ["serde"] } uuid = { version = "1.8.0", features = ["fast-rng", "serde", "v4"] } [patch.crates-io] -blstrs_plus = { git = "https://github.com/Commit-Boost/blstrs" } \ No newline at end of file +blstrs_plus = { git = "https://github.com/Commit-Boost/blstrs" } diff --git a/crates/common/Cargo.toml b/crates/common/Cargo.toml index e46e1982..ea5c0199 100644 --- a/crates/common/Cargo.toml +++ b/crates/common/Cargo.toml @@ -23,6 +23,7 @@ ethereum_ssz_derive.workspace = true eyre.workspace = true futures.workspace = true jsonwebtoken.workspace = true +lh_eth2.workspace = true lh_eth2_keystore.workspace = true lh_types.workspace = true pbkdf2.workspace = true diff --git a/crates/common/src/pbs/error.rs b/crates/common/src/pbs/error.rs index 8f350735..b15a00ba 100644 --- a/crates/common/src/pbs/error.rs +++ b/crates/common/src/pbs/error.rs @@ -1,7 +1,7 @@ use alloy::primitives::{B256, U256}; use thiserror::Error; -use crate::{types::BlsPublicKey, utils::ResponseReadError}; +use crate::{types::BlsPublicKeyBytes, utils::ResponseReadError}; #[derive(Debug, Error)] pub enum PbsError { @@ -55,7 +55,7 @@ pub enum ValidationError { EmptyBlockhash, #[error("pubkey mismatch: expected {expected} got {got}")] - PubkeyMismatch { expected: Box, got: Box }, + PubkeyMismatch { expected: BlsPublicKeyBytes, got: BlsPublicKeyBytes }, #[error("parent hash mismatch: expected {expected} got {got}")] ParentHashMismatch { expected: B256, got: B256 }, @@ -96,4 +96,7 @@ pub enum ValidationError { #[error("payload mismatch: request: {request} response: {response}")] PayloadVersionMismatch { request: &'static str, response: &'static str }, + + #[error("unsupported fork")] + UnsupportedFork, } diff --git a/crates/common/src/pbs/types/beacon_block.rs b/crates/common/src/pbs/types/beacon_block.rs deleted file mode 100644 index 5d3b139c..00000000 --- a/crates/common/src/pbs/types/beacon_block.rs +++ /dev/null @@ -1,186 +0,0 @@ -use alloy::primitives::B256; -use serde::{Deserialize, Serialize}; -use ssz_derive::{Decode, Encode}; - -use super::{ - blinded_block_body::BlindedBeaconBlockBodyElectra, blobs_bundle::BlobsBundle, - execution_payload::ExecutionPayload, spec::ElectraSpec, utils::VersionedResponse, -}; -use crate::types::BlsSignature; - -#[derive(Debug, Clone, Serialize, Deserialize, Encode, Decode)] -/// Sent to relays in submit_block -pub struct SignedBlindedBeaconBlock { - pub message: BlindedBeaconBlock, - pub signature: BlsSignature, -} - -impl SignedBlindedBeaconBlock { - pub fn block_hash(&self) -> B256 { - match &self.message { - BlindedBeaconBlock::Electra(b) => b.body.execution_payload_header.block_hash, - } - } - - pub fn block_number(&self) -> u64 { - match &self.message { - BlindedBeaconBlock::Electra(b) => b.body.execution_payload_header.block_number, - } - } - - pub fn parent_hash(&self) -> B256 { - match &self.message { - BlindedBeaconBlock::Electra(b) => b.body.execution_payload_header.parent_hash, - } - } - - pub fn slot(&self) -> u64 { - match &self.message { - BlindedBeaconBlock::Electra(b) => b.slot, - } - } -} - -#[derive(Debug, Clone, Serialize, Deserialize, Encode, Decode)] -#[serde(untagged)] -#[ssz(enum_behaviour = "transparent")] -pub enum BlindedBeaconBlock { - Electra(BlindedBeaconBlockElectra), -} - -#[derive(Debug, Clone, Serialize, Deserialize, Encode, Decode)] -pub struct BlindedBeaconBlockElectra { - #[serde(with = "serde_utils::quoted_u64")] - pub slot: u64, - #[serde(with = "serde_utils::quoted_u64")] - pub proposer_index: u64, - pub parent_root: B256, - pub state_root: B256, - pub body: BlindedBeaconBlockBodyElectra, -} - -/// Returned by relay in submit_block -pub type SubmitBlindedBlockResponse = VersionedResponse; - -impl SubmitBlindedBlockResponse { - pub fn block_hash(&self) -> B256 { - match self { - VersionedResponse::Electra(d) => d.block_hash(), - } - } -} - -#[derive(Debug, Default, Clone, Serialize, Deserialize, Encode, Decode)] -pub struct PayloadAndBlobsElectra { - pub execution_payload: ExecutionPayload, - pub blobs_bundle: BlobsBundle, -} - -impl PayloadAndBlobsElectra { - pub fn block_hash(&self) -> B256 { - self.execution_payload.block_hash - } -} - -#[cfg(test)] -mod tests { - use serde_json::json; - use ssz::Encode; - - use super::*; - use crate::utils::{test_encode_decode, test_encode_decode_ssz}; - - #[test] - // this is from mev-boost test data - fn test_signed_blinded_block_fb_electra() { - let data = include_str!("testdata/signed-blinded-beacon-block-electra.json"); - let block = test_encode_decode::(data); - assert!(matches!(block.message, BlindedBeaconBlock::Electra(_))); - } - - #[test] - // this is from the builder api spec, but with blobs fixed to deserialize - // correctly - fn test_submit_blinded_block_response_electra() { - let blob = alloy::primitives::hex::encode_prefixed([1; 131072]); - - let data = json!({ - "version": "electra", - "data": { - "execution_payload": { - "parent_hash": - "0xcf8e0d4e9587369b2301d0790347320302cc0943d5a1884560367e8208d920f2", - "fee_recipient": "0xabcf8e0d4e9587369b2301d0790347320302cc09", - "state_root": "0xcf8e0d4e9587369b2301d0790347320302cc0943d5a1884560367e8208d920f2", - "receipts_root": - "0xcf8e0d4e9587369b2301d0790347320302cc0943d5a1884560367e8208d920f2", - "logs_bloom": - "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000" - , "prev_randao": - "0xcf8e0d4e9587369b2301d0790347320302cc0943d5a1884560367e8208d920f2", - "block_number": "1", - "gas_limit": "1", - "gas_used": "1", - "timestamp": "1", - "extra_data": "0xcf8e0d4e9587369b2301d0790347320302cc0943d5a1884560367e8208d920f2", - "base_fee_per_gas": "1", - "blob_gas_used": "1", - "excess_blob_gas": "1", - "block_hash": "0xcf8e0d4e9587369b2301d0790347320302cc0943d5a1884560367e8208d920f2", - "transactions": [ - "0x02f878831469668303f51d843b9ac9f9843b9aca0082520894c93269b73096998db66be0441e836d873535cb9c8894a19041886f000080c001a031cc29234036afbf9a1fb9476b463367cb1f957ac0b919b69bbc798436e604aaa018c4e9c3914eb27aadd0b91e10b18655739fcf8c1fc398763a9f1beecb8ddc86" - ], - "withdrawals": [ - { - "index": "1", - "validator_index": "1", - "address": "0xabcf8e0d4e9587369b2301d0790347320302cc09", - "amount": "32000000000" - } - ] - }, - "blobs_bundle": { - "commitments": [ - "0x8dab030c51e16e84be9caab84ee3d0b8bbec1db4a0e4de76439da8424d9b957370a10a78851f97e4b54d2ce1ab0d686f" - ], - "proofs": [ - "0xb4021b0de10f743893d4f71e1bf830c019e832958efd6795baf2f83b8699a9eccc5dc99015d8d4d8ec370d0cc333c06a" - ], - "blobs": [ - blob - ] - } - } - }).to_string(); - - let block = test_encode_decode::(&data); - assert!(matches!(block, SubmitBlindedBlockResponse::Electra(_))); - } - - #[test] - // this is dummy data generated with https://github.com/attestantio/go-eth2-client - fn test_signed_blinded_block_ssz() { - let data_json = include_str!("testdata/signed-blinded-beacon-block-electra-2.json"); - let block_json = test_encode_decode::(data_json); - assert!(matches!(block_json.message, BlindedBeaconBlock::Electra(_))); - - let data_ssz = include_bytes!("testdata/signed-blinded-beacon-block-electra-2.ssz"); - let block_ssz = test_encode_decode_ssz::(data_ssz); - assert!(matches!(block_ssz.message, BlindedBeaconBlock::Electra(_))); - - assert_eq!(block_json.as_ssz_bytes(), data_ssz); - } - - #[test] - // this is dummy data generated with https://github.com/attestantio/go-builder-client - fn test_execution_payload_block_ssz() { - let data_json = include_str!("testdata/execution-payload-electra.json"); - let block_json = test_encode_decode::(data_json); - - let data_ssz = include_bytes!("testdata/execution-payload-electra.ssz"); - let data_ssz = alloy::primitives::hex::decode(data_ssz).unwrap(); - test_encode_decode_ssz::(&data_ssz); - - assert_eq!(block_json.as_ssz_bytes(), data_ssz); - } -} diff --git a/crates/common/src/pbs/types/blinded_block_body.rs b/crates/common/src/pbs/types/blinded_block_body.rs deleted file mode 100644 index 754a8775..00000000 --- a/crates/common/src/pbs/types/blinded_block_body.rs +++ /dev/null @@ -1,156 +0,0 @@ -use alloy::primitives::{Address, B256}; -use serde::{Deserialize, Serialize}; -use ssz_derive::{Decode, Encode}; -use ssz_types::{BitList, BitVector, FixedVector, VariableList, typenum}; - -use super::{ - execution_payload::ExecutionPayloadHeader, execution_requests::ExecutionRequests, - kzg::KzgCommitments, spec::EthSpec, utils::*, -}; -use crate::types::{BlsPublicKey, BlsSignature}; - -#[derive(Debug, Clone, Serialize, Deserialize, Encode, Decode)] -#[serde(deny_unknown_fields)] -pub struct BlindedBeaconBlockBodyElectra { - pub randao_reveal: BlsSignature, - pub eth1_data: Eth1Data, - pub graffiti: B256, - pub proposer_slashings: VariableList, - pub attester_slashings: VariableList, T::MaxAttesterSlashings>, - pub attestations: VariableList, T::MaxAttestations>, - pub deposits: VariableList, - pub voluntary_exits: VariableList, - pub sync_aggregate: SyncAggregate, - pub execution_payload_header: ExecutionPayloadHeader, - pub bls_to_execution_changes: - VariableList, - pub blob_kzg_commitments: KzgCommitments, - pub execution_requests: ExecutionRequests, -} - -#[derive(Debug, Default, Clone, Serialize, Deserialize, Encode, Decode)] -pub struct Eth1Data { - pub deposit_root: B256, - #[serde(with = "serde_utils::quoted_u64")] - pub deposit_count: u64, - pub block_hash: B256, -} - -#[derive(Debug, Default, Clone, Serialize, Deserialize, Encode, Decode)] -pub struct BeaconBlockHeader { - #[serde(with = "serde_utils::quoted_u64")] - pub slot: u64, - #[serde(with = "serde_utils::quoted_u64")] - pub proposer_index: u64, - pub parent_root: B256, - pub state_root: B256, - pub body_root: B256, -} - -#[derive(Debug, Clone, Serialize, Deserialize, Encode, Decode)] -pub struct SignedBeaconBlockHeader { - pub message: BeaconBlockHeader, - pub signature: BlsSignature, -} - -#[derive(Debug, Clone, Serialize, Deserialize, Encode, Decode)] -pub struct BlsToExecutionChange { - #[serde(with = "serde_utils::quoted_u64")] - pub validator_index: u64, - pub from_bls_pubkey: BlsPublicKey, - pub to_execution_address: Address, -} - -#[derive(Debug, Clone, Serialize, Deserialize, Encode, Decode)] -pub struct SignedBlsToExecutionChange { - pub message: BlsToExecutionChange, - pub signature: BlsSignature, -} - -#[derive(Debug, Clone, Serialize, Deserialize, Encode, Decode)] -pub struct ProposerSlashing { - pub signed_header_1: SignedBeaconBlockHeader, - pub signed_header_2: SignedBeaconBlockHeader, -} - -#[derive(Debug, Clone, Serialize, Deserialize, Encode, Decode)] -pub struct AttesterSlashingElectra { - pub attestation_1: IndexedAttestationElectra, - pub attestation_2: IndexedAttestationElectra, -} - -#[derive(Debug, Clone, Serialize, Deserialize, Encode, Decode)] -#[serde(bound = "T: EthSpec")] -pub struct IndexedAttestationElectra { - /// Lists validator registry indices, not committee indices. - #[serde(with = "quoted_variable_list_u64")] - pub attesting_indices: VariableList, - pub data: AttestationData, - pub signature: BlsSignature, -} - -#[derive(Debug, Default, Clone, Serialize, Deserialize, Encode, Decode)] -pub struct AttestationData { - #[serde(with = "serde_utils::quoted_u64")] - pub slot: u64, - #[serde(with = "serde_utils::quoted_u64")] - pub index: u64, - // LMD GHOST vote - pub beacon_block_root: B256, - // FFG Vote - pub source: Checkpoint, - pub target: Checkpoint, -} - -#[derive(Debug, Default, Clone, Serialize, Deserialize, Encode, Decode)] -pub struct Checkpoint { - #[serde(with = "serde_utils::quoted_u64")] - pub epoch: u64, - pub root: B256, -} - -#[derive(Debug, Clone, Serialize, Deserialize, Encode, Decode)] -#[serde(bound = "T: EthSpec")] -pub struct AttestationElectra { - pub aggregation_bits: BitList, - pub data: AttestationData, - pub signature: BlsSignature, - pub committee_bits: BitVector, -} - -#[derive(Debug, Clone, Serialize, Deserialize, Encode, Decode)] -pub struct Deposit { - pub proof: FixedVector, // put this in EthSpec? - pub data: DepositData, -} - -#[derive(Debug, Clone, Serialize, Deserialize, Encode, Decode)] -pub struct DepositData { - pub pubkey: BlsPublicKey, - pub withdrawal_credentials: B256, - #[serde(with = "serde_utils::quoted_u64")] - pub amount: u64, - pub signature: BlsSignature, -} - -#[derive(Debug, Clone, Serialize, Deserialize, Encode, Decode)] -pub struct SignedVoluntaryExit { - pub message: VoluntaryExit, - pub signature: BlsSignature, -} - -#[derive(Debug, Default, Clone, Serialize, Deserialize, Encode, Decode)] -pub struct VoluntaryExit { - /// Earliest epoch when voluntary exit can be processed. - #[serde(with = "serde_utils::quoted_u64")] - pub epoch: u64, - #[serde(with = "serde_utils::quoted_u64")] - pub validator_index: u64, -} - -#[derive(Debug, Clone, Serialize, Deserialize, Encode, Decode)] -#[serde(bound = "T: EthSpec")] -pub struct SyncAggregate { - pub sync_committee_bits: BitVector, - pub sync_committee_signature: BlsSignature, -} diff --git a/crates/common/src/pbs/types/blobs_bundle.rs b/crates/common/src/pbs/types/blobs_bundle.rs deleted file mode 100644 index c861a930..00000000 --- a/crates/common/src/pbs/types/blobs_bundle.rs +++ /dev/null @@ -1,19 +0,0 @@ -use serde::{Deserialize, Serialize}; -use ssz_derive::{Decode, Encode}; -use ssz_types::{FixedVector, VariableList}; - -use super::{ - kzg::{KzgCommitments, KzgProofs}, - spec::EthSpec, -}; - -#[derive(Debug, Default, Clone, Serialize, Deserialize, Encode, Decode)] -#[serde(bound = "T: EthSpec")] -pub struct BlobsBundle { - pub commitments: KzgCommitments, - pub proofs: KzgProofs, - #[serde(with = "ssz_types::serde_utils::list_of_hex_fixed_vec")] - pub blobs: VariableList, ::MaxBlobCommitmentsPerBlock>, -} - -pub type Blob = FixedVector::BytesPerBlob>; diff --git a/crates/common/src/pbs/types/execution_payload.rs b/crates/common/src/pbs/types/execution_payload.rs deleted file mode 100644 index f4aff2c4..00000000 --- a/crates/common/src/pbs/types/execution_payload.rs +++ /dev/null @@ -1,140 +0,0 @@ -use alloy::primitives::{Address, B256, U256, b256}; -use serde::{Deserialize, Serialize}; -use ssz_derive::{Decode, Encode}; -use ssz_types::{FixedVector, VariableList}; -use tree_hash_derive::TreeHash; - -use super::spec::EthSpec; - -pub const EMPTY_TX_ROOT_HASH: B256 = - b256!("7ffe241ea60187fdb0187bfa22de35d1f9bed7ab061d9401fd47e34a54fbede1"); - -#[derive(Debug, Default, Clone, Serialize, Deserialize, Encode, Decode)] -pub struct ExecutionPayload { - pub parent_hash: B256, - pub fee_recipient: Address, - pub state_root: B256, - pub receipts_root: B256, - #[serde(with = "ssz_types::serde_utils::hex_fixed_vec")] - pub logs_bloom: FixedVector, - pub prev_randao: B256, - #[serde(with = "serde_utils::quoted_u64")] - pub block_number: u64, - #[serde(with = "serde_utils::quoted_u64")] - pub gas_limit: u64, - #[serde(with = "serde_utils::quoted_u64")] - pub gas_used: u64, - #[serde(with = "serde_utils::quoted_u64")] - pub timestamp: u64, - #[serde(with = "ssz_types::serde_utils::hex_var_list")] - pub extra_data: VariableList, - #[serde(with = "serde_utils::quoted_u256")] - pub base_fee_per_gas: U256, - pub block_hash: B256, - #[serde(with = "ssz_types::serde_utils::list_of_hex_var_list")] - pub transactions: Transactions, - pub withdrawals: VariableList, - #[serde(with = "serde_utils::quoted_u64")] - pub blob_gas_used: u64, - #[serde(with = "serde_utils::quoted_u64")] - pub excess_blob_gas: u64, -} - -pub type Transactions = VariableList< - Transaction<::MaxBytesPerTransaction>, - ::MaxTransactionsPerPayload, ->; -pub type Transaction = VariableList; - -#[derive(Debug, Default, Clone, Serialize, Deserialize, Encode, Decode)] -pub struct Withdrawal { - #[serde(with = "serde_utils::quoted_u64")] - pub index: u64, - #[serde(with = "serde_utils::quoted_u64")] - pub validator_index: u64, - pub address: Address, - #[serde(with = "serde_utils::quoted_u64")] - pub amount: u64, -} - -#[derive(Debug, Default, Clone, Serialize, Deserialize, Encode, Decode, TreeHash)] -pub struct ExecutionPayloadHeader { - pub parent_hash: B256, - pub fee_recipient: Address, - pub state_root: B256, - pub receipts_root: B256, - #[serde(with = "ssz_types::serde_utils::hex_fixed_vec")] - pub logs_bloom: FixedVector, - pub prev_randao: B256, - #[serde(with = "serde_utils::quoted_u64")] - pub block_number: u64, - #[serde(with = "serde_utils::quoted_u64")] - pub gas_limit: u64, - #[serde(with = "serde_utils::quoted_u64")] - pub gas_used: u64, - #[serde(with = "serde_utils::quoted_u64")] - pub timestamp: u64, - #[serde(with = "ssz_types::serde_utils::hex_var_list")] - pub extra_data: VariableList, - #[serde(with = "serde_utils::quoted_u256")] - pub base_fee_per_gas: U256, - pub block_hash: B256, - pub transactions_root: B256, - pub withdrawals_root: B256, - #[serde(with = "serde_utils::quoted_u64")] - pub blob_gas_used: u64, - #[serde(with = "serde_utils::quoted_u64")] - pub excess_blob_gas: u64, -} - -#[cfg(test)] -mod tests { - use alloy::primitives::b256; - use ssz_types::VariableList; - use tree_hash::TreeHash; - - use super::*; - use crate::{ - pbs::{ElectraSpec, types::execution_payload::Transactions}, - utils::test_encode_decode, - }; - - #[test] - fn test_empty_tx_root_hash() { - let txs: Transactions = VariableList::empty(); - let txs_root = txs.tree_hash_root(); - - assert_eq!(txs_root, EMPTY_TX_ROOT_HASH); - } - - #[test] - fn test_execution_payload_header() { - let data = r#"{ - "parent_hash": "0xcf8e0d4e9587369b2301d0790347320302cc0943d5a1884560367e8208d920f2", - "fee_recipient": "0xabcf8e0d4e9587369b2301d0790347320302cc09", - "state_root": "0xcf8e0d4e9587369b2301d0790347320302cc0943d5a1884560367e8208d920f2", - "receipts_root": "0xcf8e0d4e9587369b2301d0790347320302cc0943d5a1884560367e8208d920f2", - "logs_bloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", - "prev_randao": "0xcf8e0d4e9587369b2301d0790347320302cc0943d5a1884560367e8208d920f2", - "block_number": "1", - "gas_limit": "1", - "gas_used": "1", - "timestamp": "1", - "extra_data": "0xcf8e0d4e9587369b2301d0790347320302cc0943d5a1884560367e8208d920f2", - "base_fee_per_gas": "150", - "block_hash": "0xcf8e0d4e9587369b2301d0790347320302cc0943d5a1884560367e8208d920f2", - "transactions_root": "0xcf8e0d4e9587369b2301d0790347320302cc0943d5a1884560367e8208d920f2", - "withdrawals_root": "0x2daccf0e476ca3e2644afbd13b2621d55b4d515b813a3b867cdacea24bb352d1", - "blob_gas_used": "786432", - "excess_blob_gas": "95158272" - }"#; - - let parsed = test_encode_decode::>(data); - - assert_eq!( - parsed.parent_hash, - b256!("cf8e0d4e9587369b2301d0790347320302cc0943d5a1884560367e8208d920f2") - ); - assert_eq!(parsed.base_fee_per_gas, U256::from(150)); - } -} diff --git a/crates/common/src/pbs/types/execution_requests.rs b/crates/common/src/pbs/types/execution_requests.rs deleted file mode 100644 index 2c48f24a..00000000 --- a/crates/common/src/pbs/types/execution_requests.rs +++ /dev/null @@ -1,41 +0,0 @@ -use alloy::primitives::{Address, B256}; -use serde::{Deserialize, Serialize}; -use ssz_derive::{Decode, Encode}; -use ssz_types::VariableList; -use tree_hash_derive::TreeHash; - -use super::spec::EthSpec; -use crate::types::{BlsPublicKey, BlsSignature}; - -#[derive(Debug, Default, Clone, Serialize, Deserialize, Encode, Decode, TreeHash)] -pub struct ExecutionRequests { - pub deposits: VariableList, - pub withdrawals: VariableList, - pub consolidations: VariableList, -} - -#[derive(Debug, Clone, Serialize, Deserialize, Encode, Decode, TreeHash)] -pub struct DepositRequest { - pub pubkey: BlsPublicKey, - pub withdrawal_credentials: B256, - #[serde(with = "serde_utils::quoted_u64")] - pub amount: u64, - pub signature: BlsSignature, - #[serde(with = "serde_utils::quoted_u64")] - pub index: u64, -} - -#[derive(Debug, Clone, Serialize, Deserialize, Encode, Decode, TreeHash)] -pub struct WithdrawalRequest { - pub source_address: Address, - pub validator_pubkey: BlsPublicKey, - #[serde(with = "serde_utils::quoted_u64")] - pub amount: u64, -} - -#[derive(Debug, Clone, Serialize, Deserialize, Encode, Decode, TreeHash)] -pub struct ConsolidationRequest { - pub source_address: Address, - pub source_pubkey: BlsPublicKey, - pub target_pubkey: BlsPublicKey, -} diff --git a/crates/common/src/pbs/types/get_header.rs b/crates/common/src/pbs/types/get_header.rs deleted file mode 100644 index c243f21d..00000000 --- a/crates/common/src/pbs/types/get_header.rs +++ /dev/null @@ -1,196 +0,0 @@ -use alloy::primitives::{B256, U256}; -use serde::{Deserialize, Serialize}; -use ssz::{Decode, Encode}; -use ssz_derive::{Decode, Encode}; -use tree_hash_derive::TreeHash; - -use super::{ - execution_payload::ExecutionPayloadHeader, execution_requests::ExecutionRequests, - kzg::KzgCommitments, spec::ElectraSpec, utils::VersionedResponse, -}; -use crate::types::{BlsPublicKey, BlsSignature}; - -#[derive(Debug, Serialize, Deserialize, Clone)] -pub struct GetHeaderParams { - /// The slot to request the header for - pub slot: u64, - /// The parent hash of the block to request the header for - pub parent_hash: B256, - /// The pubkey of the validator that is requesting the header - pub pubkey: BlsPublicKey, -} - -/// Returned by relay in get_header -pub type GetHeaderResponse = - VersionedResponse>; - -impl GetHeaderResponse { - pub fn block_number(&self) -> u64 { - match self { - VersionedResponse::Electra(data) => data.message.header.block_number, - } - } - - pub fn block_hash(&self) -> B256 { - match self { - VersionedResponse::Electra(data) => data.message.header.block_hash, - } - } - - pub fn gas_limit(&self) -> u64 { - match self { - VersionedResponse::Electra(data) => data.message.header.gas_limit, - } - } - - pub fn pubkey(&self) -> &BlsPublicKey { - match self { - VersionedResponse::Electra(data) => &data.message.pubkey, - } - } - - pub fn value(&self) -> U256 { - match self { - VersionedResponse::Electra(data) => data.message.value, - } - } - - pub fn transactions_root(&self) -> B256 { - match self { - GetHeaderResponse::Electra(data) => data.message.header.transactions_root, - } - } - - pub fn parent_hash(&self) -> B256 { - match self { - GetHeaderResponse::Electra(data) => data.message.header.parent_hash, - } - } - - pub fn signautre(&self) -> &BlsSignature { - match self { - GetHeaderResponse::Electra(data) => &data.signature, - } - } -} - -#[derive(Debug, Clone, Serialize, Deserialize, Encode, Decode)] -pub struct SignedExecutionPayloadHeader { - pub message: T, - pub signature: BlsSignature, -} - -#[derive(Debug, Clone, Serialize, Deserialize, Encode, Decode, TreeHash)] -pub struct ExecutionPayloadHeaderMessageElectra { - pub header: ExecutionPayloadHeader, - pub blob_kzg_commitments: KzgCommitments, - pub execution_requests: ExecutionRequests, - #[serde(with = "serde_utils::quoted_u256")] - pub value: U256, - pub pubkey: BlsPublicKey, -} - -#[cfg(test)] -mod tests { - use alloy::primitives::U256; - - use super::*; - use crate::{ - constants::APPLICATION_BUILDER_DOMAIN, - pbs::VersionedResponse, - signature::verify_signed_message, - types::Chain, - utils::{test_encode_decode, test_encode_decode_ssz}, - }; - - #[test] - // from the builder api spec, with signature fixed to the correct pubkey - fn test_get_header_electra() { - let data = r#"{ - "version": "electra", - "data": { - "message": { - "header": { - "parent_hash": "0xcf8e0d4e9587369b2301d0790347320302cc0943d5a1884560367e8208d920f2", - "fee_recipient": "0xabcf8e0d4e9587369b2301d0790347320302cc09", - "state_root": "0xcf8e0d4e9587369b2301d0790347320302cc0943d5a1884560367e8208d920f2", - "receipts_root": "0xcf8e0d4e9587369b2301d0790347320302cc0943d5a1884560367e8208d920f2", - "logs_bloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", - "prev_randao": "0xcf8e0d4e9587369b2301d0790347320302cc0943d5a1884560367e8208d920f2", - "block_number": "1", - "gas_limit": "1", - "gas_used": "1", - "timestamp": "1", - "extra_data": "0xcf8e0d4e9587369b2301d0790347320302cc0943d5a1884560367e8208d920f2", - "base_fee_per_gas": "1", - "blob_gas_used": "1", - "excess_blob_gas": "1", - "block_hash": "0xcf8e0d4e9587369b2301d0790347320302cc0943d5a1884560367e8208d920f2", - "transactions_root": "0xcf8e0d4e9587369b2301d0790347320302cc0943d5a1884560367e8208d920f2", - "withdrawals_root": "0xcf8e0d4e9587369b2301d0790347320302cc0943d5a1884560367e8208d920f2" - }, - "blob_kzg_commitments": [ - "0xa94170080872584e54a1cf092d845703b13907f2e6b3b1c0ad573b910530499e3bcd48c6378846b80d2bfa58c81cf3d5" - ], - "execution_requests": { - "deposits": [ - { - "pubkey": "0x911f24ad11078aad2b28ff9dcb4651a0b686e3972b2b4190273f35d416bf057dbd95553d7a0edb107b1a5e1b211da8c4", - "withdrawal_credentials": "0xcf8e0d4e9587369b2301d0790347320302cc0943d5a1884560367e8208d920f2", - "amount": "1", - "signature": "0xb4f92cd90de8e4b67debeb0379f08d0e6d3046e67e824e6ed63cd841abc9999c8b123a780e34a480d4ef13466b6241e30000b047d27de43fcf475fc4e69da2d26929cec97742892346f53e78f973bbe8095285f05a8ea60b118cdd1e6a704c94", - "index": "1" - } - ], - "withdrawals": [ - { - "source_address": "0xabcf8e0d4e9587369b2301d0790347320302cc09", - "validator_pubkey": "0x911f24ad11078aad2b28ff9dcb4651a0b686e3972b2b4190273f35d416bf057dbd95553d7a0edb107b1a5e1b211da8c4", - "amount": "1" - } - ], - "consolidations": [ - { - "source_address": "0xabcf8e0d4e9587369b2301d0790347320302cc09", - "source_pubkey": "0x911f24ad11078aad2b28ff9dcb4651a0b686e3972b2b4190273f35d416bf057dbd95553d7a0edb107b1a5e1b211da8c4", - "target_pubkey": "0x911f24ad11078aad2b28ff9dcb4651a0b686e3972b2b4190273f35d416bf057dbd95553d7a0edb107b1a5e1b211da8c4" - } - ] - }, - "value": "1", - "pubkey": "0xac0a230bd98a766b8e4156f0626ee679dd280dee5b0eedc2b9455ca3dacc4c7618da5010b9db609450a712f095c9f7a5" - }, - "signature": "0x8aeb4642fb2982039a43fd6a6d9cc0ebf7598dbf02343c4617d9a68d799393c162492add63f31099a25eacc2782ba27a190e977a8c58760b6636dccb503d528b3be9e885c93d5b79699e68fcca870b0c790cdb00d67604d8b4a3025ae75efa2f" - } - }"#; - - let parsed = test_encode_decode::(data); - let VersionedResponse::Electra(parsed) = parsed; - - assert_eq!(parsed.message.value, U256::from(1)); - - assert!(verify_signed_message( - Chain::Holesky, - &parsed.message.pubkey, - &parsed.message, - &parsed.signature, - APPLICATION_BUILDER_DOMAIN - )) - } - - #[test] - // this is dummy data generated with https://github.com/attestantio/go-builder-client - fn test_signed_execution_payload_header_ssz() { - let data_json = include_str!("testdata/get-header-response.json"); - let block_json = test_encode_decode::< - SignedExecutionPayloadHeader, - >(data_json); - - let data_ssz = include_bytes!("testdata/get-header-response.ssz"); - test_encode_decode_ssz::>( - data_ssz, - ); - - assert_eq!(block_json.as_ssz_bytes(), data_ssz); - } -} diff --git a/crates/common/src/pbs/types/kzg.rs b/crates/common/src/pbs/types/kzg.rs deleted file mode 100644 index 82fc806d..00000000 --- a/crates/common/src/pbs/types/kzg.rs +++ /dev/null @@ -1,160 +0,0 @@ -use std::{ - fmt::{self, Debug, Display, Formatter}, - str::FromStr, -}; - -use serde::{Deserialize, Deserializer, Serialize, Serializer}; -use ssz_derive::{Decode, Encode}; -use ssz_types::VariableList; -use tree_hash::{PackedEncoding, TreeHash}; - -use super::spec::EthSpec; - -pub const BYTES_PER_COMMITMENT: usize = 48; -#[derive(Clone, Eq, PartialEq, Encode, Decode)] -#[ssz(struct_behaviour = "transparent")] -pub struct KzgCommitment(pub [u8; BYTES_PER_COMMITMENT]); -pub type KzgCommitments = - VariableList::MaxBlobCommitmentsPerBlock>; - -impl From for [u8; 48] { - fn from(value: KzgCommitment) -> Self { - value.0 - } -} - -impl TreeHash for KzgCommitment { - fn tree_hash_type() -> tree_hash::TreeHashType { - <[u8; BYTES_PER_COMMITMENT] as TreeHash>::tree_hash_type() - } - - fn tree_hash_packed_encoding(&self) -> PackedEncoding { - self.0.tree_hash_packed_encoding() - } - - fn tree_hash_packing_factor() -> usize { - <[u8; BYTES_PER_COMMITMENT] as TreeHash>::tree_hash_packing_factor() - } - - fn tree_hash_root(&self) -> tree_hash::Hash256 { - self.0.tree_hash_root() - } -} - -impl Display for KzgCommitment { - fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result { - write!(f, "{}", serde_utils::hex::encode(self.0)) - } -} - -impl Debug for KzgCommitment { - fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result { - write!(f, "{}", serde_utils::hex::encode(self.0)) - } -} - -impl Serialize for KzgCommitment { - fn serialize(&self, serializer: S) -> Result - where - S: Serializer, - { - serializer.serialize_str(&self.to_string()) - } -} - -impl<'de> Deserialize<'de> for KzgCommitment { - fn deserialize(deserializer: D) -> Result - where - D: Deserializer<'de>, - { - let string = String::deserialize(deserializer)?; - Self::from_str(&string).map_err(serde::de::Error::custom) - } -} - -impl FromStr for KzgCommitment { - type Err = String; - - fn from_str(s: &str) -> Result { - if let Some(stripped) = s.strip_prefix("0x") { - let bytes = alloy::primitives::hex::decode(stripped).map_err(|e| e.to_string())?; - if bytes.len() == BYTES_PER_COMMITMENT { - let mut kzg_commitment_bytes = [0; BYTES_PER_COMMITMENT]; - kzg_commitment_bytes[..].copy_from_slice(&bytes); - Ok(Self(kzg_commitment_bytes)) - } else { - Err(format!( - "InvalidByteLength: got {}, expected {}", - bytes.len(), - BYTES_PER_COMMITMENT - )) - } - } else { - Err("must start with 0x".to_string()) - } - } -} - -// PROOF -pub const BYTES_PER_PROOF: usize = 48; - -#[derive(Debug, Clone, Encode, Decode)] -#[ssz(struct_behaviour = "transparent")] -pub struct KzgProof(pub [u8; BYTES_PER_PROOF]); -pub type KzgProofs = VariableList::MaxBlobCommitmentsPerBlock>; - -impl From for [u8; 48] { - fn from(value: KzgProof) -> Self { - value.0 - } -} - -impl fmt::Display for KzgProof { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - write!(f, "{}", serde_utils::hex::encode(self.0)) - } -} - -impl From<[u8; BYTES_PER_PROOF]> for KzgProof { - fn from(bytes: [u8; BYTES_PER_PROOF]) -> Self { - Self(bytes) - } -} - -impl Serialize for KzgProof { - fn serialize(&self, serializer: S) -> Result - where - S: Serializer, - { - serializer.serialize_str(&self.to_string()) - } -} - -impl<'de> Deserialize<'de> for KzgProof { - fn deserialize(deserializer: D) -> Result - where - D: Deserializer<'de>, - { - let string = String::deserialize(deserializer)?; - Self::from_str(&string).map_err(serde::de::Error::custom) - } -} - -impl FromStr for KzgProof { - type Err = String; - - fn from_str(s: &str) -> Result { - if let Some(stripped) = s.strip_prefix("0x") { - let bytes = alloy::primitives::hex::decode(stripped).map_err(|e| e.to_string())?; - if bytes.len() == BYTES_PER_PROOF { - let mut kzg_proof_bytes = [0; BYTES_PER_PROOF]; - kzg_proof_bytes[..].copy_from_slice(&bytes); - Ok(Self(kzg_proof_bytes)) - } else { - Err(format!("InvalidByteLength: got {}, expected {}", bytes.len(), BYTES_PER_PROOF)) - } - } else { - Err("must start with 0x".to_string()) - } - } -} diff --git a/crates/common/src/pbs/types/mod.rs b/crates/common/src/pbs/types/mod.rs index c5eaeed6..db7a17c4 100644 --- a/crates/common/src/pbs/types/mod.rs +++ b/crates/common/src/pbs/types/mod.rs @@ -1,31 +1,94 @@ -mod beacon_block; -mod blinded_block_body; -mod blobs_bundle; -mod execution_payload; -mod execution_requests; -mod get_header; -mod kzg; -mod spec; -mod utils; - -pub use beacon_block::{ - BlindedBeaconBlock, BlindedBeaconBlockElectra, PayloadAndBlobsElectra, - SignedBlindedBeaconBlock, SubmitBlindedBlockResponse, -}; -pub use blobs_bundle::{Blob, BlobsBundle}; -pub use execution_payload::{ - EMPTY_TX_ROOT_HASH, ExecutionPayload, ExecutionPayloadHeader, Transaction, Transactions, - Withdrawal, -}; -pub use execution_requests::{ - ConsolidationRequest, DepositRequest, ExecutionRequests, WithdrawalRequest, -}; -pub use get_header::{ - ExecutionPayloadHeaderMessageElectra, GetHeaderParams, GetHeaderResponse, - SignedExecutionPayloadHeader, -}; -pub use kzg::{ - BYTES_PER_COMMITMENT, BYTES_PER_PROOF, KzgCommitment, KzgCommitments, KzgProof, KzgProofs, -}; -pub use spec::{ElectraSpec, EthSpec}; -pub use utils::VersionedResponse; +use alloy::primitives::{B256, U256, b256}; +use lh_types::{BlindedPayload, ExecPayload, MainnetEthSpec}; +use serde::{Deserialize, Serialize}; + +use crate::types::BlsPublicKey; + +pub const EMPTY_TX_ROOT_HASH: B256 = + b256!("7ffe241ea60187fdb0187bfa22de35d1f9bed7ab061d9401fd47e34a54fbede1"); + +/// Request object of POST `/eth/v1/builder/blinded_blocks` +pub type SignedBlindedBeaconBlock = + lh_types::signed_beacon_block::SignedBlindedBeaconBlock; +pub type BlindedBeaconBlock<'a> = + lh_types::beacon_block::BeaconBlockRef<'a, MainnetEthSpec, BlindedPayload>; +pub type BlindedBeaconBlockElectra = + lh_types::beacon_block::BeaconBlockElectra>; +pub type BlindedBeaconBlockFulu = + lh_types::beacon_block::BeaconBlockFulu>; + +pub type BlobsBundle = lh_eth2::types::BlobsBundle; +pub type PayloadAndBlobs = lh_eth2::types::ExecutionPayloadAndBlobs; +/// Response object of POST `/eth/v1/builder/blinded_blocks` +pub type SubmitBlindedBlockResponse = lh_types::ForkVersionedResponse; + +pub type ExecutionPayloadHeader = lh_types::ExecutionPayloadHeader; +pub type ExecutionPayloadHeaderRef<'a> = lh_types::ExecutionPayloadHeaderRef<'a, MainnetEthSpec>; +pub type ExecutionPayload = lh_types::ExecutionPayload; +pub type ExecutionPayloadElectra = lh_types::ExecutionPayloadElectra; +pub type ExecutionPayloadFulu = lh_types::ExecutionPayloadFulu; +pub type SignedBuilderBid = lh_types::builder_bid::SignedBuilderBid; + +/// Response object of GET +/// `/eth/v1/builder/header/{slot}/{parent_hash}/{pubkey}` +pub type GetHeaderResponse = lh_types::ForkVersionedResponse; + +pub use lh_types::ForkVersionedResponse; + +/// Response params of GET +/// `/eth/v1/builder/header/{slot}/{parent_hash}/{pubkey}` +#[derive(Debug, Serialize, Deserialize, Clone)] +pub struct GetHeaderParams { + /// The slot to request the header for + pub slot: u64, + /// The parent hash of the block to request the header for + pub parent_hash: B256, + /// The pubkey of the validator that is requesting the header + pub pubkey: BlsPublicKey, +} + +pub trait GetHeaderInfo { + fn block_hash(&self) -> B256; + fn value(&self) -> &U256; + fn block_number(&self) -> u64; + fn gas_limit(&self) -> u64; +} + +impl GetHeaderInfo for GetHeaderResponse { + fn block_hash(&self) -> B256 { + self.data.message.header().block_hash().0 + } + + fn value(&self) -> &U256 { + self.data.message.value() + } + + fn block_number(&self) -> u64 { + self.data.message.header().block_number() + } + + fn gas_limit(&self) -> u64 { + self.data.message.header().gas_limit() + } +} + +pub trait GetPyloadInfo { + fn block_hash(&self) -> B256; + fn block_number(&self) -> u64; + fn parent_hash(&self) -> B256; +} + +impl GetPyloadInfo for SignedBlindedBeaconBlock { + fn block_hash(&self) -> B256 { + // Block hash is only missing for Base and Altair forks + self.message().body().execution_payload().map(|r| r.block_hash().0).unwrap_or_default() + } + + fn block_number(&self) -> u64 { + self.message().body().execution_payload().map(|r| r.block_number()).unwrap_or_default() + } + + fn parent_hash(&self) -> B256 { + self.message().body().execution_payload().map(|r| r.parent_hash().0).unwrap_or_default() + } +} diff --git a/crates/common/src/pbs/types/spec.rs b/crates/common/src/pbs/types/spec.rs deleted file mode 100644 index 61bd90a4..00000000 --- a/crates/common/src/pbs/types/spec.rs +++ /dev/null @@ -1,61 +0,0 @@ -use serde::{Deserialize, Serialize}; -use ssz_types::typenum; - -pub trait EthSpec { - type MaxProposerSlashings: typenum::Unsigned + std::fmt::Debug; - type MaxValidatorsPerCommittee: typenum::Unsigned + std::fmt::Debug; - type MaxDeposits: typenum::Unsigned + std::fmt::Debug; - type MaxVoluntaryExits: typenum::Unsigned + std::fmt::Debug; - type SyncCommitteeSize: typenum::Unsigned + std::fmt::Debug; - type BytesPerLogsBloom: typenum::Unsigned + std::fmt::Debug; - type MaxExtraDataBytes: typenum::Unsigned + std::fmt::Debug; - type MaxBlsToExecutionChanges: typenum::Unsigned + std::fmt::Debug; - type MaxBlobCommitmentsPerBlock: typenum::Unsigned + std::fmt::Debug; - type MaxWithdrawalsPerPayload: typenum::Unsigned + std::fmt::Debug; - type MaxBytesPerTransaction: typenum::Unsigned + std::fmt::Debug; - type MaxTransactionsPerPayload: typenum::Unsigned + std::fmt::Debug; - type BytesPerBlob: typenum::Unsigned + std::fmt::Debug; - type MaxCommitteesPerSlot: typenum::Unsigned + std::fmt::Debug; - - // Updated in Electra - type MaxAttesterSlashings: typenum::Unsigned + std::fmt::Debug; - type MaxAttestations: typenum::Unsigned + std::fmt::Debug; - - // New in Electra - type MaxValidatorsPerSlot: typenum::Unsigned + std::fmt::Debug; - - type MaxConsolidationRequestsPerPayload: typenum::Unsigned + std::fmt::Debug; - type MaxDepositRequestsPerPayload: typenum::Unsigned + std::fmt::Debug; - type MaxWithdrawalRequestsPerPayload: typenum::Unsigned + std::fmt::Debug; -} - -#[derive(Debug, Default, Clone, Serialize, Deserialize)] -pub struct ElectraSpec; - -impl EthSpec for ElectraSpec { - type MaxValidatorsPerCommittee = typenum::U2048; - type MaxProposerSlashings = typenum::U16; - type MaxDeposits = typenum::U16; - type MaxVoluntaryExits = typenum::U16; - type SyncCommitteeSize = typenum::U512; - type MaxExtraDataBytes = typenum::U32; - type MaxBlobCommitmentsPerBlock = typenum::U4096; - type BytesPerLogsBloom = typenum::U256; - type MaxBlsToExecutionChanges = typenum::U16; - type MaxWithdrawalsPerPayload = typenum::U16; - type MaxBytesPerTransaction = typenum::U1073741824; - type MaxTransactionsPerPayload = typenum::U1048576; - type BytesPerBlob = typenum::U131072; - type MaxCommitteesPerSlot = typenum::U64; - - // Updated in Electra - type MaxAttesterSlashings = typenum::U1; - type MaxAttestations = typenum::U8; - - // Electra - type MaxValidatorsPerSlot = typenum::U131072; - - type MaxConsolidationRequestsPerPayload = typenum::U2; - type MaxDepositRequestsPerPayload = typenum::U8192; - type MaxWithdrawalRequestsPerPayload = typenum::U16; -} diff --git a/crates/common/src/pbs/types/utils.rs b/crates/common/src/pbs/types/utils.rs deleted file mode 100644 index 0a8de5c0..00000000 --- a/crates/common/src/pbs/types/utils.rs +++ /dev/null @@ -1,51 +0,0 @@ -use serde::{Deserialize, Serialize}; - -pub mod quoted_variable_list_u64 { - use serde::{Deserializer, Serializer, ser::SerializeSeq}; - use serde_utils::quoted_u64_vec::{QuotedIntVecVisitor, QuotedIntWrapper}; - use ssz_types::{VariableList, typenum::Unsigned}; - - pub fn serialize(value: &VariableList, serializer: S) -> Result - where - S: Serializer, - T: Unsigned, - { - let mut seq = serializer.serialize_seq(Some(value.len()))?; - for &int in value.iter() { - seq.serialize_element(&QuotedIntWrapper { int })?; - } - seq.end() - } - - pub fn deserialize<'de, D, T>(deserializer: D) -> Result, D::Error> - where - D: Deserializer<'de>, - T: Unsigned, - { - deserializer.deserialize_any(QuotedIntVecVisitor).and_then(|vec| { - VariableList::new(vec) - .map_err(|e| serde::de::Error::custom(format!("invalid length: {e:?}"))) - }) - } -} - -#[derive(Debug, Clone, Serialize, Deserialize)] -#[serde(tag = "version", content = "data")] -pub enum VersionedResponse { - #[serde(rename = "electra")] - Electra(E), -} - -impl Default for VersionedResponse { - fn default() -> Self { - Self::Electra(E::default()) - } -} - -impl VersionedResponse { - pub fn version(&self) -> &str { - match self { - VersionedResponse::Electra(_) => "electra", - } - } -} diff --git a/crates/common/src/types.rs b/crates/common/src/types.rs index 17775ba0..ffa32765 100644 --- a/crates/common/src/types.rs +++ b/crates/common/src/types.rs @@ -7,6 +7,7 @@ use serde::{Deserialize, Serialize}; use crate::{constants::APPLICATION_BUILDER_DOMAIN, signature::compute_domain}; +pub type BlsPublicKeyBytes = lh_types::PublicKeyBytes; pub type BlsPublicKey = lh_types::PublicKey; pub type BlsSignature = lh_types::Signature; pub type BlsSecretKey = lh_types::SecretKey; diff --git a/crates/pbs/src/mev_boost/get_header.rs b/crates/pbs/src/mev_boost/get_header.rs index c07893f8..44fe8a4b 100644 --- a/crates/pbs/src/mev_boost/get_header.rs +++ b/crates/pbs/src/mev_boost/get_header.rs @@ -12,12 +12,12 @@ use axum::http::{HeaderMap, HeaderValue}; use cb_common::{ constants::APPLICATION_BUILDER_DOMAIN, pbs::{ - EMPTY_TX_ROOT_HASH, GetHeaderParams, GetHeaderResponse, HEADER_START_TIME_UNIX_MS, - HEADER_TIMEOUT_MS, RelayClient, VersionedResponse, + EMPTY_TX_ROOT_HASH, ExecutionPayloadHeaderRef, GetHeaderInfo, GetHeaderParams, + GetHeaderResponse, HEADER_START_TIME_UNIX_MS, HEADER_TIMEOUT_MS, RelayClient, error::{PbsError, ValidationError}, }, signature::verify_signed_message, - types::{BlsPublicKey, BlsSignature, Chain}, + types::{BlsPublicKey, BlsPublicKeyBytes, BlsSignature, Chain}, utils::{ get_user_agent_with_version, ms_into_slot, read_chunked_body_with_max, timestamp_of_slot_start_sec, utcnow_ms, @@ -126,8 +126,9 @@ pub async fn get_header( match res { Ok(Some(res)) => { RELAY_LAST_SLOT.with_label_values(&[relay_id]).set(params.slot as i64); - let value_gwei = - (res.value() / U256::from(1_000_000_000)).try_into().unwrap_or_default(); + let value_gwei = (res.data.message.value() / U256::from(1_000_000_000)) + .try_into() + .unwrap_or_default(); RELAY_HEADER_VALUE.with_label_values(&[relay_id]).set(value_gwei); relay_bids.push(res) @@ -138,7 +139,7 @@ pub async fn get_header( } } - let max_bid = relay_bids.into_iter().max_by_key(|bid| bid.value()); + let max_bid = relay_bids.into_iter().max_by_key(|bid| *bid.value()); Ok(max_bid) } @@ -376,20 +377,26 @@ async fn send_one_get_header( relay_id = relay.id.as_ref(), header_size_bytes, latency = ?request_latency, - version = get_header_response.version(), - value_eth = format_ether(get_header_response.value()), + version =? get_header_response.version, + value_eth = format_ether(*get_header_response.value()), block_hash = %get_header_response.block_hash(), "received new header" ); - match &get_header_response { - VersionedResponse::Electra(res) => { + match &get_header_response.data.message.header() { + ExecutionPayloadHeaderRef::Bellatrix(_) | + ExecutionPayloadHeaderRef::Capella(_) | + ExecutionPayloadHeaderRef::Deneb(_) | + ExecutionPayloadHeaderRef::Gloas(_) => { + return Err(PbsError::Validation(ValidationError::UnsupportedFork)) + } + ExecutionPayloadHeaderRef::Electra(res) => { let header_data = HeaderData { - block_hash: res.message.header.block_hash, - parent_hash: res.message.header.parent_hash, - tx_root: res.message.header.transactions_root, - value: res.message.value, - timestamp: res.message.header.timestamp, + block_hash: res.block_hash.0, + parent_hash: res.parent_hash.0, + tx_root: res.transactions_root, + value: *get_header_response.value(), + timestamp: res.timestamp, }; validate_header_data( @@ -404,9 +411,36 @@ async fn send_one_get_header( validate_signature( chain, relay.pubkey(), - &res.message.pubkey, - &res.message, - &res.signature, + get_header_response.data.message.pubkey(), + &get_header_response.data.message, + &get_header_response.data.signature, + )?; + } + } + ExecutionPayloadHeaderRef::Fulu(res) => { + let header_data = HeaderData { + block_hash: res.block_hash.0, + parent_hash: res.parent_hash.0, + tx_root: res.transactions_root, + value: *get_header_response.value(), + timestamp: res.timestamp, + }; + + validate_header_data( + &header_data, + chain, + params.parent_hash, + validation.min_bid_wei, + params.slot, + )?; + + if !validation.skip_sigverify { + validate_signature( + chain, + relay.pubkey(), + get_header_response.data.message.pubkey(), + &get_header_response.data.message, + &get_header_response.data.signature, )?; } } @@ -475,20 +509,20 @@ fn validate_header_data( fn validate_signature( chain: Chain, expected_relay_pubkey: &BlsPublicKey, - received_relay_pubkey: &BlsPublicKey, + received_relay_pubkey: &BlsPublicKeyBytes, message: &T, signature: &BlsSignature, ) -> Result<(), ValidationError> { - if expected_relay_pubkey != received_relay_pubkey { + if expected_relay_pubkey.serialize() != received_relay_pubkey.as_serialized() { return Err(ValidationError::PubkeyMismatch { - expected: Box::new(expected_relay_pubkey.clone()), - got: Box::new(received_relay_pubkey.clone()), + expected: BlsPublicKeyBytes::from(expected_relay_pubkey), + got: received_relay_pubkey.clone(), }); } if !verify_signed_message( chain, - received_relay_pubkey, + expected_relay_pubkey, &message, signature, APPLICATION_BUILDER_DOMAIN, @@ -593,7 +627,7 @@ mod tests { fn test_validate_signature() { let secret_key = BlsSecretKey::test_random(); let pubkey = secret_key.public_key(); - let wrong_pubkey = BlsPublicKey::test_random(); + let wrong_pubkey = BlsPublicKeyBytes::test_random(); let wrong_signature = BlsSignature::test_random(); let message = B256::random(); @@ -601,18 +635,33 @@ mod tests { let signature = sign_builder_message(Chain::Holesky, &secret_key, &message); assert_eq!( - validate_signature(Chain::Holesky, &wrong_pubkey, &pubkey, &message, &wrong_signature), + validate_signature(Chain::Holesky, &pubkey, &wrong_pubkey, &message, &wrong_signature), Err(ValidationError::PubkeyMismatch { - expected: Box::new(wrong_pubkey), - got: Box::new(pubkey.clone()) + expected: BlsPublicKeyBytes::from(&pubkey), + got: wrong_pubkey }) ); assert!(matches!( - validate_signature(Chain::Holesky, &pubkey, &pubkey, &message, &wrong_signature), + validate_signature( + Chain::Holesky, + &pubkey, + &BlsPublicKeyBytes::from(&pubkey), + &message, + &wrong_signature + ), Err(ValidationError::Sigverify) )); - assert!(validate_signature(Chain::Holesky, &pubkey, &pubkey, &message, &signature).is_ok()); + assert!( + validate_signature( + Chain::Holesky, + &pubkey, + &BlsPublicKeyBytes::from(&pubkey), + &message, + &signature + ) + .is_ok() + ); } } diff --git a/crates/pbs/src/mev_boost/submit_block.rs b/crates/pbs/src/mev_boost/submit_block.rs index 0336bde8..7eed9f6a 100644 --- a/crates/pbs/src/mev_boost/submit_block.rs +++ b/crates/pbs/src/mev_boost/submit_block.rs @@ -1,11 +1,13 @@ use std::time::{Duration, Instant}; +use alloy::eips::eip7594::CELLS_PER_EXT_BLOB; use axum::http::{HeaderMap, HeaderValue}; use cb_common::{ pbs::{ - BlindedBeaconBlock, BlindedBeaconBlockElectra, BuilderApiVersion, - HEADER_START_TIME_UNIX_MS, PayloadAndBlobsElectra, RelayClient, SignedBlindedBeaconBlock, - SubmitBlindedBlockResponse, VersionedResponse, + BlindedBeaconBlock, BlindedBeaconBlockElectra, BlindedBeaconBlockFulu, BlobsBundle, + BuilderApiVersion, ExecutionPayload, ExecutionPayloadElectra, ExecutionPayloadFulu, + HEADER_START_TIME_UNIX_MS, RelayClient, SignedBlindedBeaconBlock, + SubmitBlindedBlockResponse, error::{PbsError, ValidationError}, }, utils::{get_user_agent_with_version, read_chunked_body_with_max, utcnow_ms}, @@ -178,24 +180,31 @@ async fn send_submit_block( relay_id = relay.id.as_ref(), retry, latency = ?request_latency, - version = block_response.version(), + version =% block_response.version, "received unblinded block" ); - if signed_blinded_block.block_hash() != block_response.block_hash() { - return Err(PbsError::Validation(ValidationError::BlockHashMismatch { - expected: signed_blinded_block.block_hash(), - got: block_response.block_hash(), - })); - } - // request has different type so cant be deserialized in the wrong version, // response has a "version" field - match (&signed_blinded_block.message, &block_response) { + match (&signed_blinded_block.message(), &block_response.data.execution_payload) { ( - BlindedBeaconBlock::Electra(signed_blinded_block), - VersionedResponse::Electra(block_response), - ) => validate_unblinded_block_electra(signed_blinded_block, block_response), + BlindedBeaconBlock::Electra(blinded_block), + ExecutionPayload::Electra(execution_payload), + ) => validate_unblinded_block_electra( + blinded_block, + execution_payload, + &block_response.data.blobs_bundle, + ), + + (BlindedBeaconBlock::Fulu(blinded_block), ExecutionPayload::Fulu(execution_payload)) => { + validate_unblinded_block_fulu( + blinded_block, + execution_payload, + &block_response.data.blobs_bundle, + ) + } + + _ => return Err(PbsError::Validation(ValidationError::UnsupportedFork)), }?; Ok(Some(block_response)) @@ -203,29 +212,82 @@ async fn send_submit_block( fn validate_unblinded_block_electra( signed_blinded_block: &BlindedBeaconBlockElectra, - block_response: &PayloadAndBlobsElectra, + execution_payload: &ExecutionPayloadElectra, + blobs_bundle: &BlobsBundle, +) -> Result<(), PbsError> { + let expected_block_hash = + signed_blinded_block.body.execution_payload.execution_payload_header.block_hash.0; + let got_block_hash = execution_payload.block_hash.0; + + if expected_block_hash != got_block_hash { + return Err(PbsError::Validation(ValidationError::BlockHashMismatch { + expected: expected_block_hash, + got: got_block_hash, + })); + } + + let expected_commitments = &signed_blinded_block.body.blob_kzg_commitments; + if expected_commitments.len() != blobs_bundle.blobs.len() || + expected_commitments.len() != blobs_bundle.commitments.len() || + expected_commitments.len() != blobs_bundle.proofs.len() + { + return Err(PbsError::Validation(ValidationError::KzgCommitments { + expected_blobs: expected_commitments.len(), + got_blobs: blobs_bundle.blobs.len(), + got_commitments: blobs_bundle.commitments.len(), + got_proofs: blobs_bundle.proofs.len(), + })); + } + + for (i, comm) in expected_commitments.iter().enumerate() { + // this is safe since we already know they are the same length + if *comm != blobs_bundle.commitments[i] { + return Err(PbsError::Validation(ValidationError::KzgMismatch { + expected: format!("{comm}"), + got: format!("{}", blobs_bundle.commitments[i]), + index: i, + })); + } + } + + Ok(()) +} + +fn validate_unblinded_block_fulu( + signed_blinded_block: &BlindedBeaconBlockFulu, + execution_payload: &ExecutionPayloadFulu, + blobs_bundle: &BlobsBundle, ) -> Result<(), PbsError> { - let blobs = &block_response.blobs_bundle; + let expected_block_hash = + signed_blinded_block.body.execution_payload.execution_payload_header.block_hash.0; + let got_block_hash = execution_payload.block_hash.0; + + if expected_block_hash != got_block_hash { + return Err(PbsError::Validation(ValidationError::BlockHashMismatch { + expected: expected_block_hash, + got: got_block_hash, + })); + } let expected_commitments = &signed_blinded_block.body.blob_kzg_commitments; - if expected_commitments.len() != blobs.blobs.len() || - expected_commitments.len() != blobs.commitments.len() || - expected_commitments.len() != blobs.proofs.len() + if expected_commitments.len() != blobs_bundle.blobs.len() || + expected_commitments.len() != blobs_bundle.commitments.len() || + expected_commitments.len() * CELLS_PER_EXT_BLOB != blobs_bundle.proofs.len() { return Err(PbsError::Validation(ValidationError::KzgCommitments { expected_blobs: expected_commitments.len(), - got_blobs: blobs.blobs.len(), - got_commitments: blobs.commitments.len(), - got_proofs: blobs.proofs.len(), + got_blobs: blobs_bundle.blobs.len(), + got_commitments: blobs_bundle.commitments.len(), + got_proofs: blobs_bundle.proofs.len(), })); } for (i, comm) in expected_commitments.iter().enumerate() { // this is safe since we already know they are the same length - if *comm != blobs.commitments[i] { + if *comm != blobs_bundle.commitments[i] { return Err(PbsError::Validation(ValidationError::KzgMismatch { expected: format!("{comm}"), - got: format!("{}", blobs.commitments[i]), + got: format!("{}", blobs_bundle.commitments[i]), index: i, })); } diff --git a/crates/pbs/src/routes/get_header.rs b/crates/pbs/src/routes/get_header.rs index 77607c28..98a411f7 100644 --- a/crates/pbs/src/routes/get_header.rs +++ b/crates/pbs/src/routes/get_header.rs @@ -5,7 +5,7 @@ use axum::{ response::IntoResponse, }; use cb_common::{ - pbs::GetHeaderParams, + pbs::{GetHeaderInfo, GetHeaderParams}, utils::{get_user_agent, ms_into_slot}, }; use reqwest::StatusCode; @@ -38,7 +38,7 @@ pub async fn handle_get_header>( match A::get_header(params, req_headers, state.clone()).await { Ok(res) => { if let Some(max_bid) = res { - info!(value_eth = format_ether(max_bid.value()), block_hash =% max_bid.block_hash(), "received header"); + info!(value_eth = format_ether(*max_bid.data.message.value()), block_hash =% max_bid.block_hash(), "received header"); BEACON_NODE_STATUS.with_label_values(&["200", GET_HEADER_ENDPOINT_TAG]).inc(); Ok((StatusCode::OK, axum::Json(max_bid)).into_response()) diff --git a/crates/pbs/src/routes/submit_block.rs b/crates/pbs/src/routes/submit_block.rs index 27d2c798..577fc887 100644 --- a/crates/pbs/src/routes/submit_block.rs +++ b/crates/pbs/src/routes/submit_block.rs @@ -1,6 +1,6 @@ use axum::{Json, extract::State, http::HeaderMap, response::IntoResponse}; use cb_common::{ - pbs::{BuilderApiVersion, SignedBlindedBeaconBlock}, + pbs::{BuilderApiVersion, GetPyloadInfo, SignedBlindedBeaconBlock}, utils::{get_user_agent, timestamp_of_slot_start_millis, utcnow_ms}, }; use reqwest::StatusCode; @@ -48,7 +48,7 @@ async fn handle_submit_block_impl>( Json(signed_blinded_block): Json, api_version: BuilderApiVersion, ) -> Result { - tracing::Span::current().record("slot", signed_blinded_block.slot()); + tracing::Span::current().record("slot", signed_blinded_block.slot().as_u64() as i64); tracing::Span::current() .record("block_hash", tracing::field::debug(signed_blinded_block.block_hash())); tracing::Span::current().record("block_number", signed_blinded_block.block_number()); @@ -60,7 +60,7 @@ async fn handle_submit_block_impl>( let now = utcnow_ms(); let slot = signed_blinded_block.slot(); let block_hash = signed_blinded_block.block_hash(); - let slot_start_ms = timestamp_of_slot_start_millis(slot, state.config.chain); + let slot_start_ms = timestamp_of_slot_start_millis(slot.into(), state.config.chain); let ua = get_user_agent(&req_headers); info!(ua, ms_into_slot = now.saturating_sub(slot_start_ms), "new request"); diff --git a/tests/src/mock_relay.rs b/tests/src/mock_relay.rs index 61c3e84d..b821915d 100644 --- a/tests/src/mock_relay.rs +++ b/tests/src/mock_relay.rs @@ -16,11 +16,9 @@ use axum::{ }; use cb_common::{ pbs::{ - BUILDER_V1_API_PATH, BUILDER_V2_API_PATH, BlindedBeaconBlock, - ExecutionPayloadHeaderMessageElectra, ExecutionRequests, GET_HEADER_PATH, GET_STATUS_PATH, - GetHeaderParams, GetHeaderResponse, KzgProof, REGISTER_VALIDATOR_PATH, SUBMIT_BLOCK_PATH, - SignedBlindedBeaconBlock, SignedExecutionPayloadHeader, SubmitBlindedBlockResponse, - VersionedResponse, + BUILDER_V1_API_PATH, BUILDER_V2_API_PATH, BlindedBeaconBlock, GET_HEADER_PATH, + GET_STATUS_PATH, GetHeaderParams, GetHeaderResponse, REGISTER_VALIDATOR_PATH, + SUBMIT_BLOCK_PATH, SignedBlindedBeaconBlock, SubmitBlindedBlockResponse, }, signature::sign_builder_root, types::{BlsSecretKey, Chain}, From 54016ef9f8c97f4bfb5177ea51ccfee64a9f3d2c Mon Sep 17 00:00:00 2001 From: eltitanb Date: Tue, 30 Sep 2025 20:53:38 +0100 Subject: [PATCH 2/9] fix test --- Cargo.lock | 1 + crates/common/src/pbs/types/mod.rs | 8 +++- tests/Cargo.toml | 1 + tests/src/mock_relay.rs | 66 ++++++++++++++++---------- tests/tests/pbs_get_header.rs | 22 +++++---- tests/tests/pbs_post_blinded_blocks.rs | 7 ++- 6 files changed, 69 insertions(+), 36 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 18aa0ba6..8ec4ae31 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1733,6 +1733,7 @@ dependencies = [ "tracing", "tracing-subscriber", "tree_hash", + "types", "url", ] diff --git a/crates/common/src/pbs/types/mod.rs b/crates/common/src/pbs/types/mod.rs index db7a17c4..19edf8d2 100644 --- a/crates/common/src/pbs/types/mod.rs +++ b/crates/common/src/pbs/types/mod.rs @@ -23,17 +23,23 @@ pub type PayloadAndBlobs = lh_eth2::types::ExecutionPayloadAndBlobs; pub type ExecutionPayloadHeader = lh_types::ExecutionPayloadHeader; +pub type ExecutionPayloadHeaderElectra = lh_types::ExecutionPayloadHeaderElectra; +pub type ExecutionPayloadHeaderFulu = lh_types::ExecutionPayloadHeaderFulu; pub type ExecutionPayloadHeaderRef<'a> = lh_types::ExecutionPayloadHeaderRef<'a, MainnetEthSpec>; pub type ExecutionPayload = lh_types::ExecutionPayload; pub type ExecutionPayloadElectra = lh_types::ExecutionPayloadElectra; pub type ExecutionPayloadFulu = lh_types::ExecutionPayloadFulu; pub type SignedBuilderBid = lh_types::builder_bid::SignedBuilderBid; +pub type BuilderBid = lh_types::builder_bid::BuilderBid; +pub type BuilderBidElectra = lh_types::builder_bid::BuilderBidElectra; /// Response object of GET /// `/eth/v1/builder/header/{slot}/{parent_hash}/{pubkey}` pub type GetHeaderResponse = lh_types::ForkVersionedResponse; -pub use lh_types::ForkVersionedResponse; +pub use lh_types::{ForkName, ForkVersionedResponse}; + +pub type ExecutionRequests = lh_types::execution_requests::ExecutionRequests; /// Response params of GET /// `/eth/v1/builder/header/{slot}/{parent_hash}/{pubkey}` diff --git a/tests/Cargo.toml b/tests/Cargo.toml index f1b5c9d9..3195cc11 100644 --- a/tests/Cargo.toml +++ b/tests/Cargo.toml @@ -11,6 +11,7 @@ cb-common.workspace = true cb-pbs.workspace = true cb-signer.workspace = true eyre.workspace = true +lh_types.workspace = true reqwest.workspace = true serde_json.workspace = true tempfile.workspace = true diff --git a/tests/src/mock_relay.rs b/tests/src/mock_relay.rs index b821915d..91001c46 100644 --- a/tests/src/mock_relay.rs +++ b/tests/src/mock_relay.rs @@ -16,15 +16,18 @@ use axum::{ }; use cb_common::{ pbs::{ - BUILDER_V1_API_PATH, BUILDER_V2_API_PATH, BlindedBeaconBlock, GET_HEADER_PATH, - GET_STATUS_PATH, GetHeaderParams, GetHeaderResponse, REGISTER_VALIDATOR_PATH, - SUBMIT_BLOCK_PATH, SignedBlindedBeaconBlock, SubmitBlindedBlockResponse, + BUILDER_V1_API_PATH, BUILDER_V2_API_PATH, BlobsBundle, BuilderBid, BuilderBidElectra, + ExecutionPayloadElectra, ExecutionPayloadHeaderElectra, ExecutionRequests, ForkName, + GET_HEADER_PATH, GET_STATUS_PATH, GetHeaderParams, GetHeaderResponse, GetPyloadInfo, + PayloadAndBlobs, REGISTER_VALIDATOR_PATH, SUBMIT_BLOCK_PATH, SignedBlindedBeaconBlock, + SignedBuilderBid, SubmitBlindedBlockResponse, }, signature::sign_builder_root, types::{BlsSecretKey, Chain}, - utils::timestamp_of_slot_start_sec, + utils::{TestRandomSeed, timestamp_of_slot_start_sec}, }; use cb_pbs::MAX_SIZE_SUBMIT_BLOCK_RESPONSE; +use lh_types::KzgProof; use tokio::net::TcpListener; use tracing::debug; use tree_hash::TreeHash; @@ -110,25 +113,32 @@ async fn handle_get_header( ) -> Response { state.received_get_header.fetch_add(1, Ordering::Relaxed); - let mut message = ExecutionPayloadHeaderMessageElectra { - header: Default::default(), - blob_kzg_commitments: Default::default(), - execution_requests: ExecutionRequests::default(), - value: Default::default(), - pubkey: state.signer.public_key(), + let mut header = ExecutionPayloadHeaderElectra { + parent_hash: parent_hash.into(), + block_hash: Default::default(), + timestamp: timestamp_of_slot_start_sec(0, state.chain), + ..ExecutionPayloadHeaderElectra::test_random() }; - message.header.parent_hash = parent_hash; - message.header.block_hash.0[0] = 1; - message.value = U256::from(10); - message.pubkey = state.signer.public_key(); - message.header.timestamp = timestamp_of_slot_start_sec(0, state.chain); + header.block_hash.0[0] = 1; + + let message = BuilderBid::Electra(BuilderBidElectra { + header, + blob_kzg_commitments: Default::default(), + execution_requests: ExecutionRequests::default(), + value: U256::from(10), + pubkey: state.signer.public_key().into(), + }); let object_root = message.tree_hash_root(); let signature = sign_builder_root(state.chain, &state.signer, object_root); - let response = SignedExecutionPayloadHeader { message, signature }; + let response = SignedBuilderBid { message, signature }; - let response = GetHeaderResponse::Electra(response); + let response = GetHeaderResponse { + version: ForkName::Electra, + data: response, + metadata: Default::default(), + }; (StatusCode::OK, Json(response)).into_response() } @@ -159,16 +169,24 @@ async fn handle_submit_block_v1( if state.large_body() { (StatusCode::OK, Json(vec![1u8; 1 + MAX_SIZE_SUBMIT_BLOCK_RESPONSE])).into_response() } else { - let VersionedResponse::Electra(mut response) = SubmitBlindedBlockResponse::default(); - response.execution_payload.block_hash = submit_block.block_hash(); + let mut execution_payload = ExecutionPayloadElectra::test_random(); + execution_payload.block_hash = submit_block.block_hash().into(); + + let mut blobs_bundle = BlobsBundle::default(); - let BlindedBeaconBlock::Electra(body) = submit_block.message; + blobs_bundle.blobs.push(Default::default()).unwrap(); + blobs_bundle.commitments = + submit_block.as_electra().unwrap().message.body.blob_kzg_commitments.clone(); + blobs_bundle.proofs.push(KzgProof([0; 48])).unwrap(); - response.blobs_bundle.blobs.push(Default::default()).unwrap(); - response.blobs_bundle.commitments = body.body.blob_kzg_commitments; - response.blobs_bundle.proofs.push(KzgProof([0; 48])).unwrap(); + let response = + PayloadAndBlobs { execution_payload: execution_payload.into(), blobs_bundle }; - let response = VersionedResponse::Electra(response); + let response = SubmitBlindedBlockResponse { + version: ForkName::Electra, + metadata: Default::default(), + data: response, + }; (StatusCode::OK, Json(response)).into_response() } diff --git a/tests/tests/pbs_get_header.rs b/tests/tests/pbs_get_header.rs index 66c83752..d44d70ce 100644 --- a/tests/tests/pbs_get_header.rs +++ b/tests/tests/pbs_get_header.rs @@ -2,7 +2,10 @@ use std::{sync::Arc, time::Duration}; use alloy::primitives::{B256, U256}; use cb_common::{ - pbs::GetHeaderResponse, signature::sign_builder_root, signer::random_secret, types::Chain, + pbs::GetHeaderResponse, + signature::sign_builder_root, + signer::random_secret, + types::{BlsPublicKeyBytes, Chain}, utils::timestamp_of_slot_start_sec, }; use cb_pbs::{DefaultBuilderApi, PbsService, PbsState}; @@ -12,6 +15,7 @@ use cb_tests::{ utils::{generate_mock_relay, get_pbs_static_config, setup_test_env, to_pbs_config}, }; use eyre::Result; +use lh_types::ForkName; use reqwest::StatusCode; use tracing::info; use tree_hash::TreeHash; @@ -45,17 +49,17 @@ async fn test_get_header() -> Result<()> { assert_eq!(res.status(), StatusCode::OK); let res = serde_json::from_slice::(&res.bytes().await?)?; - let GetHeaderResponse::Electra(res) = res; assert_eq!(mock_state.received_get_header(), 1); - assert_eq!(res.message.header.block_hash.0[0], 1); - assert_eq!(res.message.header.parent_hash, B256::ZERO); - assert_eq!(res.message.value, U256::from(10)); - assert_eq!(res.message.pubkey, mock_state.signer.public_key()); - assert_eq!(res.message.header.timestamp, timestamp_of_slot_start_sec(0, chain)); + assert_eq!(res.version, ForkName::Electra); + assert_eq!(res.data.message.header().block_hash().0[0], 1); + assert_eq!(res.data.message.header().parent_hash().0, B256::ZERO); + assert_eq!(*res.data.message.value(), U256::from(10)); + assert_eq!(*res.data.message.pubkey(), BlsPublicKeyBytes::from(mock_state.signer.public_key())); + assert_eq!(res.data.message.header().timestamp(), timestamp_of_slot_start_sec(0, chain)); assert_eq!( - res.signature, - sign_builder_root(chain, &mock_state.signer, res.message.tree_hash_root()) + res.data.signature, + sign_builder_root(chain, &mock_state.signer, res.data.message.tree_hash_root()) ); Ok(()) } diff --git a/tests/tests/pbs_post_blinded_blocks.rs b/tests/tests/pbs_post_blinded_blocks.rs index f0c47471..fc2a8fa6 100644 --- a/tests/tests/pbs_post_blinded_blocks.rs +++ b/tests/tests/pbs_post_blinded_blocks.rs @@ -1,7 +1,7 @@ use std::{sync::Arc, time::Duration}; use cb_common::{ - pbs::{BuilderApiVersion, SubmitBlindedBlockResponse}, + pbs::{BuilderApiVersion, GetPyloadInfo, SubmitBlindedBlockResponse}, signer::random_secret, types::Chain, }; @@ -23,7 +23,10 @@ async fn test_submit_block_v1() -> Result<()> { let signed_blinded_block = load_test_signed_blinded_block(); let response_body = serde_json::from_slice::(&res.bytes().await?)?; - assert_eq!(response_body.block_hash(), signed_blinded_block.block_hash()); + assert_eq!( + response_body.data.execution_payload.block_hash(), + signed_blinded_block.block_hash().into() + ); Ok(()) } From f08db4a1ecc972f6c1bc565470473a4e47b0963b Mon Sep 17 00:00:00 2001 From: eltitanb Date: Tue, 30 Sep 2025 20:54:38 +0100 Subject: [PATCH 3/9] reorded imports --- crates/common/src/pbs/types/mod.rs | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/crates/common/src/pbs/types/mod.rs b/crates/common/src/pbs/types/mod.rs index 19edf8d2..c18f1119 100644 --- a/crates/common/src/pbs/types/mod.rs +++ b/crates/common/src/pbs/types/mod.rs @@ -1,5 +1,6 @@ use alloy::primitives::{B256, U256, b256}; use lh_types::{BlindedPayload, ExecPayload, MainnetEthSpec}; +pub use lh_types::{ForkName, ForkVersionedResponse}; use serde::{Deserialize, Serialize}; use crate::types::BlsPublicKey; @@ -7,6 +8,8 @@ use crate::types::BlsPublicKey; pub const EMPTY_TX_ROOT_HASH: B256 = b256!("7ffe241ea60187fdb0187bfa22de35d1f9bed7ab061d9401fd47e34a54fbede1"); +pub type ExecutionRequests = lh_types::execution_requests::ExecutionRequests; + /// Request object of POST `/eth/v1/builder/blinded_blocks` pub type SignedBlindedBeaconBlock = lh_types::signed_beacon_block::SignedBlindedBeaconBlock; @@ -37,10 +40,6 @@ pub type BuilderBidElectra = lh_types::builder_bid::BuilderBidElectra; -pub use lh_types::{ForkName, ForkVersionedResponse}; - -pub type ExecutionRequests = lh_types::execution_requests::ExecutionRequests; - /// Response params of GET /// `/eth/v1/builder/header/{slot}/{parent_hash}/{pubkey}` #[derive(Debug, Serialize, Deserialize, Clone)] From 12b10c8d78bf4540c56146a3ec4fd0b9e0bab514 Mon Sep 17 00:00:00 2001 From: eltitanb Date: Tue, 30 Sep 2025 21:10:30 +0100 Subject: [PATCH 4/9] clippy --- crates/pbs/src/mev_boost/get_header.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/crates/pbs/src/mev_boost/get_header.rs b/crates/pbs/src/mev_boost/get_header.rs index 44fe8a4b..86743703 100644 --- a/crates/pbs/src/mev_boost/get_header.rs +++ b/crates/pbs/src/mev_boost/get_header.rs @@ -516,7 +516,7 @@ fn validate_signature( if expected_relay_pubkey.serialize() != received_relay_pubkey.as_serialized() { return Err(ValidationError::PubkeyMismatch { expected: BlsPublicKeyBytes::from(expected_relay_pubkey), - got: received_relay_pubkey.clone(), + got: *received_relay_pubkey, }); } From 996a0b4a079f9e98cf5fc6a0718d8635774e05e7 Mon Sep 17 00:00:00 2001 From: Joe Clapis Date: Tue, 30 Sep 2025 17:21:40 -0400 Subject: [PATCH 5/9] Added make to the build file --- provisioning/build.Dockerfile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/provisioning/build.Dockerfile b/provisioning/build.Dockerfile index 361150e7..b28b62ff 100644 --- a/provisioning/build.Dockerfile +++ b/provisioning/build.Dockerfile @@ -59,7 +59,7 @@ RUN if [ -f ${BUILD_VAR_SCRIPT} ]; then \ echo "No cross-compilation needed"; \ fi && \ apt update && \ - apt install -y git libssl-dev:${TARGETARCH} zlib1g-dev:${TARGETARCH} pkg-config && \ + apt install -y git make libssl-dev:${TARGETARCH} zlib1g-dev:${TARGETARCH} pkg-config && \ cargo chef cook ${TARGET_FLAG} --release --recipe-path recipe.json # Get the latest Protoc since the one in the Debian repo is incredibly old From 59acf6582288adc006d7c9413bdd344ed6824eaa Mon Sep 17 00:00:00 2001 From: eltitanb Date: Wed, 1 Oct 2025 00:02:42 +0100 Subject: [PATCH 6/9] add consensus header --- crates/common/src/config/mod.rs | 23 +- crates/common/src/pbs/constants.rs | 1 + crates/common/src/types.rs | 118 +++++++-- crates/pbs/src/mev_boost/submit_block.rs | 12 +- tests/data/helder_spec.yml | 2 + tests/data/holesky_spec.json | 301 ++++++++++++----------- tests/data/hoodi_spec.json | 58 +++-- tests/data/mainnet_spec_data.json | 257 ++++++++++--------- tests/data/sepolia_spec_data.json | 28 ++- 9 files changed, 482 insertions(+), 318 deletions(-) diff --git a/crates/common/src/config/mod.rs b/crates/common/src/config/mod.rs index f2fd2ff7..67a13cb0 100644 --- a/crates/common/src/config/mod.rs +++ b/crates/common/src/config/mod.rs @@ -68,18 +68,33 @@ impl CommitBoostConfig { let chain = match helper_config.chain { ChainLoader::Path { path, genesis_time_secs } => { // check if the file path is overridden by env var - let (slot_time_secs, genesis_fork_version) = + let (slot_time_secs, genesis_fork_version, fulu_fork_slot) = if let Some(path) = load_optional_env_var(CHAIN_SPEC_ENV) { load_chain_from_file(path.parse()?)? } else { load_chain_from_file(path)? }; - Chain::Custom { genesis_time_secs, slot_time_secs, genesis_fork_version } + Chain::Custom { + genesis_time_secs, + slot_time_secs, + genesis_fork_version, + fulu_fork_slot, + } } ChainLoader::Known(known) => Chain::from(known), - ChainLoader::Custom { genesis_time_secs, slot_time_secs, genesis_fork_version } => { + ChainLoader::Custom { + genesis_time_secs, + slot_time_secs, + genesis_fork_version, + fulu_fork_slot, + } => { let genesis_fork_version: ForkVersion = genesis_fork_version.as_ref().try_into()?; - Chain::Custom { genesis_time_secs, slot_time_secs, genesis_fork_version } + Chain::Custom { + genesis_time_secs, + slot_time_secs, + genesis_fork_version, + fulu_fork_slot, + } } }; diff --git a/crates/common/src/pbs/constants.rs b/crates/common/src/pbs/constants.rs index 0b43da1a..533da137 100644 --- a/crates/common/src/pbs/constants.rs +++ b/crates/common/src/pbs/constants.rs @@ -17,6 +17,7 @@ pub const HEADER_VERSION_KEY: &str = "X-CommitBoost-Version"; pub const HEADER_VERSION_VALUE: &str = COMMIT_BOOST_VERSION; pub const HEADER_START_TIME_UNIX_MS: &str = "Date-Milliseconds"; pub const HEADER_TIMEOUT_MS: &str = "X-Timeout-Ms"; +pub const HEADER_CONSENSUS_VERSION: &str = "Eth-Consensus-Version"; pub const DEFAULT_PBS_JWT_KEY: &str = "DEFAULT_PBS"; diff --git a/crates/common/src/types.rs b/crates/common/src/types.rs index ffa32765..077b4ccd 100644 --- a/crates/common/src/types.rs +++ b/crates/common/src/types.rs @@ -3,6 +3,7 @@ use std::path::PathBuf; use alloy::primitives::{B256, Bytes, b256, hex}; use derive_more::{Deref, Display, From, Into}; use eyre::{Context, bail}; +use lh_types::ForkName; use serde::{Deserialize, Serialize}; use crate::{constants::APPLICATION_BUILDER_DOMAIN, signature::compute_domain}; @@ -35,7 +36,12 @@ pub enum Chain { Sepolia, Helder, Hoodi, - Custom { genesis_time_secs: u64, slot_time_secs: u64, genesis_fork_version: ForkVersion }, + Custom { + genesis_time_secs: u64, + slot_time_secs: u64, + genesis_fork_version: ForkVersion, + fulu_fork_slot: u64, + }, } pub type ForkVersion = [u8; 4]; @@ -59,11 +65,17 @@ impl std::fmt::Debug for Chain { Self::Sepolia => write!(f, "Sepolia"), Self::Helder => write!(f, "Helder"), Self::Hoodi => write!(f, "Hoodi"), - Self::Custom { genesis_time_secs, slot_time_secs, genesis_fork_version } => f + Self::Custom { + genesis_time_secs, + slot_time_secs, + genesis_fork_version, + fulu_fork_slot, + } => f .debug_struct("Custom") .field("genesis_time_secs", genesis_time_secs) .field("slot_time_secs", slot_time_secs) .field("genesis_fork_version", &hex::encode_prefixed(genesis_fork_version)) + .field("fulu_fork_slot", fulu_fork_slot) .finish(), } } @@ -126,6 +138,21 @@ impl Chain { Chain::Custom { slot_time_secs, .. } => *slot_time_secs, } } + + pub fn fulu_fork_slot(&self) -> u64 { + match self { + Chain::Mainnet => KnownChain::Mainnet.fulu_fork_slot(), + Chain::Holesky => KnownChain::Holesky.fulu_fork_slot(), + Chain::Sepolia => KnownChain::Sepolia.fulu_fork_slot(), + Chain::Helder => KnownChain::Helder.fulu_fork_slot(), + Chain::Hoodi => KnownChain::Hoodi.fulu_fork_slot(), + Chain::Custom { slot_time_secs, .. } => *slot_time_secs, + } + } + + pub fn fork_by_slot(&self, slot: u64) -> ForkName { + if slot >= self.fulu_fork_slot() { ForkName::Fulu } else { ForkName::Electra } + } } #[derive(Debug, Clone, Copy, Serialize, Deserialize)] @@ -203,6 +230,15 @@ impl KnownChain { KnownChain::Hoodi => 12, } } + + pub fn fulu_fork_slot(&self) -> u64 { + match self { + KnownChain::Mainnet | KnownChain::Helder => u64::MAX, + KnownChain::Holesky => 5283840, + KnownChain::Sepolia => 8724480, + KnownChain::Hoodi => 1622016, + } + } } impl From for Chain { @@ -233,6 +269,7 @@ pub enum ChainLoader { genesis_time_secs: u64, slot_time_secs: u64, genesis_fork_version: Bytes, + fulu_fork_slot: u64, }, } @@ -247,13 +284,17 @@ impl Serialize for Chain { Chain::Sepolia => ChainLoader::Known(KnownChain::Sepolia), Chain::Helder => ChainLoader::Known(KnownChain::Helder), Chain::Hoodi => ChainLoader::Known(KnownChain::Hoodi), - Chain::Custom { genesis_time_secs, slot_time_secs, genesis_fork_version } => { - ChainLoader::Custom { - genesis_time_secs: *genesis_time_secs, - slot_time_secs: *slot_time_secs, - genesis_fork_version: Bytes::from(*genesis_fork_version), - } - } + Chain::Custom { + genesis_time_secs, + slot_time_secs, + genesis_fork_version, + fulu_fork_slot, + } => ChainLoader::Custom { + genesis_time_secs: *genesis_time_secs, + slot_time_secs: *slot_time_secs, + genesis_fork_version: Bytes::from(*genesis_fork_version), + fulu_fork_slot: *fulu_fork_slot, + }, }; loader.serialize(serializer) @@ -270,14 +311,29 @@ impl<'de> Deserialize<'de> for Chain { match loader { ChainLoader::Known(known) => Ok(Chain::from(known)), ChainLoader::Path { genesis_time_secs, path } => { - let (slot_time_secs, genesis_fork_version) = + let (slot_time_secs, genesis_fork_version, fulu_fork_slot) = load_chain_from_file(path).map_err(serde::de::Error::custom)?; - Ok(Chain::Custom { genesis_time_secs, slot_time_secs, genesis_fork_version }) + Ok(Chain::Custom { + genesis_time_secs, + slot_time_secs, + genesis_fork_version, + fulu_fork_slot, + }) } - ChainLoader::Custom { genesis_time_secs, slot_time_secs, genesis_fork_version } => { + ChainLoader::Custom { + genesis_time_secs, + slot_time_secs, + genesis_fork_version, + fulu_fork_slot, + } => { let genesis_fork_version: ForkVersion = genesis_fork_version.as_ref().try_into().map_err(serde::de::Error::custom)?; - Ok(Chain::Custom { genesis_time_secs, slot_time_secs, genesis_fork_version }) + Ok(Chain::Custom { + genesis_time_secs, + slot_time_secs, + genesis_fork_version, + fulu_fork_slot, + }) } } } @@ -289,20 +345,25 @@ impl<'de> Deserialize<'de> for Chain { /// - JSON as return the getSpec endpoint, either with or without the `data` /// field /// - YAML as used e.g. in Kurtosis/Ethereum Package -pub fn load_chain_from_file(path: PathBuf) -> eyre::Result<(u64, ForkVersion)> { +pub fn load_chain_from_file(path: PathBuf) -> eyre::Result<(u64, ForkVersion, u64)> { #[derive(Deserialize)] #[serde(rename_all = "UPPERCASE")] struct QuotedSpecFile { #[serde(with = "serde_utils::quoted_u64")] seconds_per_slot: u64, genesis_fork_version: Bytes, + #[serde(with = "serde_utils::quoted_u64")] + slots_per_epoch: u64, + #[serde(with = "serde_utils::quoted_u64")] + fulu_fork_epoch: u64, } impl QuotedSpecFile { - fn to_chain(&self) -> eyre::Result<(u64, ForkVersion)> { + fn to_chain(&self) -> eyre::Result<(u64, ForkVersion, u64)> { let genesis_fork_version: ForkVersion = self.genesis_fork_version.as_ref().try_into()?; - Ok((self.seconds_per_slot, genesis_fork_version)) + let fulu_fork_slot = self.fulu_fork_epoch.saturating_mul(self.slots_per_epoch); + Ok((self.seconds_per_slot, genesis_fork_version, fulu_fork_slot)) } } @@ -316,12 +377,16 @@ pub fn load_chain_from_file(path: PathBuf) -> eyre::Result<(u64, ForkVersion)> { struct SpecFile { seconds_per_slot: u64, genesis_fork_version: u32, + slots_per_epoch: Option, + fulu_fork_epoch: u64, } impl SpecFile { - fn to_chain(&self) -> (u64, ForkVersion) { + fn to_chain(&self) -> (u64, ForkVersion, u64) { let genesis_fork_version: ForkVersion = self.genesis_fork_version.to_be_bytes(); - (self.seconds_per_slot, genesis_fork_version) + let fulu_fork_slot = + self.fulu_fork_epoch.saturating_mul(self.slots_per_epoch.unwrap_or(32)); + (self.seconds_per_slot, genesis_fork_version, fulu_fork_slot) } } @@ -357,12 +422,13 @@ mod tests { #[test] fn test_load_custom() { - let s = r#"chain = { genesis_time_secs = 1, slot_time_secs = 2, genesis_fork_version = "0x01000000" }"#; + let s = r#"chain = { genesis_time_secs = 1, slot_time_secs = 2, genesis_fork_version = "0x01000000", fulu_fork_slot = 1 }"#; let decoded: MockConfig = toml::from_str(s).unwrap(); assert_eq!(decoded.chain, Chain::Custom { genesis_time_secs: 1, slot_time_secs: 2, - genesis_fork_version: [1, 0, 0, 0] + genesis_fork_version: [1, 0, 0, 0], + fulu_fork_slot: 1 }) } @@ -403,7 +469,8 @@ mod tests { assert_eq!(decoded.chain, Chain::Custom { genesis_time_secs: 1, slot_time_secs: KnownChain::Holesky.slot_time_sec(), - genesis_fork_version: KnownChain::Holesky.genesis_fork_version() + genesis_fork_version: KnownChain::Holesky.genesis_fork_version(), + fulu_fork_slot: KnownChain::Holesky.fulu_fork_slot(), }) } @@ -423,7 +490,8 @@ mod tests { assert_eq!(decoded.chain, Chain::Custom { genesis_time_secs: 1, slot_time_secs: KnownChain::Sepolia.slot_time_sec(), - genesis_fork_version: KnownChain::Sepolia.genesis_fork_version() + genesis_fork_version: KnownChain::Sepolia.genesis_fork_version(), + fulu_fork_slot: KnownChain::Sepolia.fulu_fork_slot(), }) } @@ -443,7 +511,8 @@ mod tests { assert_eq!(decoded.chain, Chain::Custom { genesis_time_secs: 1, slot_time_secs: KnownChain::Hoodi.slot_time_sec(), - genesis_fork_version: KnownChain::Hoodi.genesis_fork_version() + genesis_fork_version: KnownChain::Hoodi.genesis_fork_version(), + fulu_fork_slot: KnownChain::Hoodi.fulu_fork_slot(), }) } @@ -463,7 +532,8 @@ mod tests { assert_eq!(decoded.chain, Chain::Custom { genesis_time_secs: 1, slot_time_secs: KnownChain::Helder.slot_time_sec(), - genesis_fork_version: KnownChain::Helder.genesis_fork_version() + genesis_fork_version: KnownChain::Helder.genesis_fork_version(), + fulu_fork_slot: KnownChain::Helder.fulu_fork_slot(), }) } } diff --git a/crates/pbs/src/mev_boost/submit_block.rs b/crates/pbs/src/mev_boost/submit_block.rs index 7eed9f6a..ee124a94 100644 --- a/crates/pbs/src/mev_boost/submit_block.rs +++ b/crates/pbs/src/mev_boost/submit_block.rs @@ -6,7 +6,7 @@ use cb_common::{ pbs::{ BlindedBeaconBlock, BlindedBeaconBlockElectra, BlindedBeaconBlockFulu, BlobsBundle, BuilderApiVersion, ExecutionPayload, ExecutionPayloadElectra, ExecutionPayloadFulu, - HEADER_START_TIME_UNIX_MS, RelayClient, SignedBlindedBeaconBlock, + HEADER_CONSENSUS_VERSION, HEADER_START_TIME_UNIX_MS, RelayClient, SignedBlindedBeaconBlock, SubmitBlindedBlockResponse, error::{PbsError, ValidationError}, }, @@ -34,10 +34,20 @@ pub async fn submit_block( state: PbsState, api_version: &BuilderApiVersion, ) -> eyre::Result> { + debug!(?req_headers, "received headers"); + let consensus_version = + req_headers.get(HEADER_CONSENSUS_VERSION).cloned().unwrap_or_else(|| { + let slot = signed_blinded_block.slot().as_u64(); + let fork = state.config.chain.fork_by_slot(slot); + // safe because ForkName is visible ASCII chars + HeaderValue::from_str(&fork.to_string()).unwrap() + }); + // prepare headers let mut send_headers = HeaderMap::new(); send_headers.insert(HEADER_START_TIME_UNIX_MS, HeaderValue::from(utcnow_ms())); send_headers.insert(USER_AGENT, get_user_agent_with_version(&req_headers)?); + send_headers.insert(HEADER_CONSENSUS_VERSION, consensus_version); let relays = state.all_relays(); let mut handles = Vec::with_capacity(relays.len()); diff --git a/tests/data/helder_spec.yml b/tests/data/helder_spec.yml index 1c1a9549..7d3f9b04 100644 --- a/tests/data/helder_spec.yml +++ b/tests/data/helder_spec.yml @@ -40,6 +40,8 @@ DENEB_FORK_EPOCH: 0 ELECTRA_FORK_VERSION: 0x60132736 ELECTRA_FORK_EPOCH: 999999 +FULU_FORK_EPOCH: 18446744073709551615 + # EIP7594 - Peerdas EIP7594_FORK_VERSION: 0x70132736 EIP7594_FORK_EPOCH: 999999 diff --git a/tests/data/holesky_spec.json b/tests/data/holesky_spec.json index 5e19d62a..b9093ff0 100644 --- a/tests/data/holesky_spec.json +++ b/tests/data/holesky_spec.json @@ -1,141 +1,164 @@ { - "SLOTS_PER_EPOCH": "32", - "PRESET_BASE": "mainnet", - "TERMINAL_TOTAL_DIFFICULTY": "0", - "INACTIVITY_SCORE_BIAS": "4", - "PENDING_BALANCE_DEPOSITS_LIMIT": "134217728", - "MAX_ATTESTER_SLASHINGS": "2", - "MAX_WITHDRAWALS_PER_PAYLOAD": "16", - "INACTIVITY_PENALTY_QUOTIENT_BELLATRIX": "16777216", - "PENDING_PARTIAL_WITHDRAWALS_LIMIT": "134217728", - "INACTIVITY_PENALTY_QUOTIENT": "67108864", - "SAFE_SLOTS_TO_UPDATE_JUSTIFIED": "8", - "SECONDS_PER_ETH1_BLOCK": "14", - "MIN_SEED_LOOKAHEAD": "1", - "VALIDATOR_REGISTRY_LIMIT": "1099511627776", - "REORG_MAX_EPOCHS_SINCE_FINALIZATION": "2", - "SLOTS_PER_HISTORICAL_ROOT": "8192", - "RESP_TIMEOUT": "10", - "DOMAIN_VOLUNTARY_EXIT": "0x04000000", - "MAX_VALIDATORS_PER_COMMITTEE": "2048", - "MIN_GENESIS_TIME": "1695902100", - "ALTAIR_FORK_EPOCH": "0", - "HYSTERESIS_QUOTIENT": "4", - "ALTAIR_FORK_VERSION": "0x02017000", - "MAX_BYTES_PER_TRANSACTION": "1073741824", - "MAX_CHUNK_SIZE": "10485760", - "TTFB_TIMEOUT": "5", - "WHISTLEBLOWER_REWARD_QUOTIENT": "512", - "PROPOSER_REWARD_QUOTIENT": "8", - "MAX_VALIDATORS_PER_WITHDRAWALS_SWEEP": "16384", - "EPOCHS_PER_HISTORICAL_VECTOR": "65536", - "MIN_PER_EPOCH_CHURN_LIMIT": "4", - "MAX_ATTESTER_SLASHINGS_ELECTRA": "1", - "TARGET_AGGREGATORS_PER_SYNC_SUBCOMMITTEE": "16", - "MAX_DEPOSITS": "16", - "BELLATRIX_FORK_EPOCH": "0", - "MAX_REQUEST_BLOB_SIDECARS": "768", - "REORG_HEAD_WEIGHT_THRESHOLD": "20", - "TARGET_AGGREGATORS_PER_COMMITTEE": "16", - "DOMAIN_SYNC_COMMITTEE_SELECTION_PROOF": "0x08000000", - "MESSAGE_DOMAIN_INVALID_SNAPPY": "0x00000000", - "EPOCHS_PER_SLASHINGS_VECTOR": "8192", - "MIN_SLASHING_PENALTY_QUOTIENT": "128", - "MAX_BLS_TO_EXECUTION_CHANGES": "16", - "GOSSIP_MAX_SIZE": "10485760", - "DOMAIN_BEACON_ATTESTER": "0x01000000", - "EPOCHS_PER_SUBNET_SUBSCRIPTION": "256", - "MAX_ATTESTATIONS_ELECTRA": "8", - "ATTESTATION_SUBNET_COUNT": "64", - "GENESIS_DELAY": "300", - "MAX_SEED_LOOKAHEAD": "4", - "ETH1_FOLLOW_DISTANCE": "2048", - "SECONDS_PER_SLOT": "12", - "REORG_PARENT_WEIGHT_THRESHOLD": "160", - "MIN_SYNC_COMMITTEE_PARTICIPANTS": "1", - "BELLATRIX_FORK_VERSION": "0x03017000", - "PROPORTIONAL_SLASHING_MULTIPLIER_BELLATRIX": "3", - "EFFECTIVE_BALANCE_INCREMENT": "1000000000", - "FIELD_ELEMENTS_PER_BLOB": "4096", - "MIN_EPOCHS_TO_INACTIVITY_PENALTY": "4", - "BASE_REWARD_FACTOR": "64", - "MAX_EXTRA_DATA_BYTES": "32", - "CONFIG_NAME": "holesky", - "MAX_PROPOSER_SLASHINGS": "16", - "INACTIVITY_SCORE_RECOVERY_RATE": "16", - "MIN_EPOCHS_FOR_BLOB_SIDECARS_REQUESTS": "4096", - "MAX_TRANSACTIONS_PER_PAYLOAD": "1048576", - "DEPOSIT_CONTRACT_ADDRESS": "0x4242424242424242424242424242424242424242", - "MIN_ATTESTATION_INCLUSION_DELAY": "1", - "SHUFFLE_ROUND_COUNT": "90", - "TERMINAL_BLOCK_HASH_ACTIVATION_EPOCH": "18446744073709551615", - "MAX_EFFECTIVE_BALANCE": "32000000000", - "DOMAIN_BEACON_PROPOSER": "0x00000000", - "DENEB_FORK_EPOCH": "29696", - "DOMAIN_SYNC_COMMITTEE": "0x07000000", - "PROPOSER_SCORE_BOOST": "40", - "DOMAIN_SELECTION_PROOF": "0x05000000", - "MIN_SLASHING_PENALTY_QUOTIENT_BELLATRIX": "32", - "MAX_PER_EPOCH_ACTIVATION_CHURN_LIMIT": "8", - "HYSTERESIS_UPWARD_MULTIPLIER": "5", - "SUBNETS_PER_NODE": "2", - "MIN_DEPOSIT_AMOUNT": "1000000000", - "MIN_SLASHING_PENALTY_QUOTIENT_ELECTRA": "4096", - "PROPORTIONAL_SLASHING_MULTIPLIER_ALTAIR": "2", - "MAX_BLOBS_PER_BLOCK": "6", - "MIN_VALIDATOR_WITHDRAWABILITY_DELAY": "256", - "MAXIMUM_GOSSIP_CLOCK_DISPARITY": "500", - "TARGET_COMMITTEE_SIZE": "128", - "TERMINAL_BLOCK_HASH": "0x0000000000000000000000000000000000000000000000000000000000000000", - "DOMAIN_DEPOSIT": "0x03000000", - "DOMAIN_CONTRIBUTION_AND_PROOF": "0x09000000", - "UPDATE_TIMEOUT": "8192", - "ELECTRA_FORK_EPOCH": "18446744073709551615", - "SYNC_COMMITTEE_BRANCH_LENGTH": "5", - "DEPOSIT_CHAIN_ID": "17000", - "MAX_BLOB_COMMITMENTS_PER_BLOCK": "4096", - "DOMAIN_RANDAO": "0x02000000", - "CAPELLA_FORK_VERSION": "0x04017000", - "MAX_EFFECTIVE_BALANCE_ELECTRA": "2048000000000", - "MIN_SLASHING_PENALTY_QUOTIENT_ALTAIR": "64", - "EPOCHS_PER_ETH1_VOTING_PERIOD": "64", - "WHISTLEBLOWER_REWARD_QUOTIENT_ELECTRA": "4096", - "HISTORICAL_ROOTS_LIMIT": "16777216", - "ATTESTATION_PROPAGATION_SLOT_RANGE": "32", - "SYNC_COMMITTEE_SIZE": "512", - "ATTESTATION_SUBNET_PREFIX_BITS": "6", - "PROPORTIONAL_SLASHING_MULTIPLIER": "1", - "MAX_WITHDRAWAL_REQUESTS_PER_PAYLOAD": "16", - "MESSAGE_DOMAIN_VALID_SNAPPY": "0x01000000", - "MAX_VOLUNTARY_EXITS": "16", - "PENDING_CONSOLIDATIONS_LIMIT": "262144", - "HYSTERESIS_DOWNWARD_MULTIPLIER": "1", - "DOMAIN_APPLICATION_BUILDER": "0x00000001", - "MAX_PENDING_PARTIALS_PER_WITHDRAWALS_SWEEP": "8", - "EPOCHS_PER_SYNC_COMMITTEE_PERIOD": "256", - "BYTES_PER_LOGS_BLOOM": "256", - "MAX_DEPOSIT_REQUESTS_PER_PAYLOAD": "8192", - "MIN_GENESIS_ACTIVE_VALIDATOR_COUNT": "16384", - "MAX_ATTESTATIONS": "128", - "MIN_EPOCHS_FOR_BLOCK_REQUESTS": "33024", - "DENEB_FORK_VERSION": "0x05017000", - "ELECTRA_FORK_VERSION": "0x06017000", - "MAX_REQUEST_BLOCKS": "1024", - "GENESIS_FORK_VERSION": "0x01017000", - "KZG_COMMITMENT_INCLUSION_PROOF_DEPTH": "17", - "DEPOSIT_NETWORK_ID": "17000", - "MAX_CONSOLIDATION_REQUESTS_PER_PAYLOAD": "1", - "MAX_REQUEST_BLOCKS_DENEB": "128", - "BLOB_SIDECAR_SUBNET_COUNT": "6", - "SYNC_COMMITTEE_SUBNET_COUNT": "4", - "CAPELLA_FORK_EPOCH": "256", - "EJECTION_BALANCE": "28000000000", - "ATTESTATION_SUBNET_EXTRA_BITS": "0", - "MAX_COMMITTEES_PER_SLOT": "64", - "SHARD_COMMITTEE_PERIOD": "256", - "INACTIVITY_PENALTY_QUOTIENT_ALTAIR": "50331648", - "DOMAIN_AGGREGATE_AND_PROOF": "0x06000000", - "CHURN_LIMIT_QUOTIENT": "65536", - "BLS_WITHDRAWAL_PREFIX": "0x00", - "MIN_ACTIVATION_BALANCE": "32000000000" + "data": { + "SLOTS_PER_EPOCH": "32", + "PRESET_BASE": "mainnet", + "TERMINAL_TOTAL_DIFFICULTY": "0", + "INACTIVITY_SCORE_BIAS": "4", + "MAX_ATTESTER_SLASHINGS": "2", + "MAX_WITHDRAWALS_PER_PAYLOAD": "16", + "INACTIVITY_PENALTY_QUOTIENT_BELLATRIX": "16777216", + "PENDING_PARTIAL_WITHDRAWALS_LIMIT": "134217728", + "INACTIVITY_PENALTY_QUOTIENT": "67108864", + "SAFE_SLOTS_TO_UPDATE_JUSTIFIED": "8", + "SECONDS_PER_ETH1_BLOCK": "14", + "MIN_SEED_LOOKAHEAD": "1", + "VALIDATOR_REGISTRY_LIMIT": "1099511627776", + "REORG_MAX_EPOCHS_SINCE_FINALIZATION": "2", + "SLOTS_PER_HISTORICAL_ROOT": "8192", + "FIELD_ELEMENTS_PER_EXT_BLOB": "8192", + "RESP_TIMEOUT": "10", + "DOMAIN_VOLUNTARY_EXIT": "0x04000000", + "MAX_VALIDATORS_PER_COMMITTEE": "2048", + "MIN_GENESIS_TIME": "1695902100", + "ALTAIR_FORK_EPOCH": "0", + "MAX_PER_EPOCH_ACTIVATION_EXIT_CHURN_LIMIT": "256000000000", + "HYSTERESIS_QUOTIENT": "4", + "ALTAIR_FORK_VERSION": "0x02017000", + "MAX_BYTES_PER_TRANSACTION": "1073741824", + "TTFB_TIMEOUT": "5", + "MAX_CHUNK_SIZE": "10485760", + "WHISTLEBLOWER_REWARD_QUOTIENT": "512", + "PROPOSER_REWARD_QUOTIENT": "8", + "MAX_VALIDATORS_PER_WITHDRAWALS_SWEEP": "16384", + "EPOCHS_PER_HISTORICAL_VECTOR": "65536", + "MIN_PER_EPOCH_CHURN_LIMIT": "4", + "MAX_ATTESTER_SLASHINGS_ELECTRA": "1", + "TARGET_AGGREGATORS_PER_SYNC_SUBCOMMITTEE": "16", + "MAX_DEPOSITS": "16", + "FIELD_ELEMENTS_PER_CELL": "64", + "BELLATRIX_FORK_EPOCH": "0", + "MAX_REQUEST_BLOB_SIDECARS": "768", + "REORG_HEAD_WEIGHT_THRESHOLD": "20", + "TARGET_AGGREGATORS_PER_COMMITTEE": "16", + "DOMAIN_SYNC_COMMITTEE_SELECTION_PROOF": "0x08000000", + "MESSAGE_DOMAIN_INVALID_SNAPPY": "0x00000000", + "EPOCHS_PER_SLASHINGS_VECTOR": "8192", + "MIN_SLASHING_PENALTY_QUOTIENT": "128", + "MAX_BLS_TO_EXECUTION_CHANGES": "16", + "GOSSIP_MAX_SIZE": "10485760", + "DOMAIN_BEACON_ATTESTER": "0x01000000", + "EPOCHS_PER_SUBNET_SUBSCRIPTION": "256", + "PENDING_DEPOSITS_LIMIT": "134217728", + "MAX_ATTESTATIONS_ELECTRA": "8", + "ATTESTATION_SUBNET_COUNT": "64", + "GENESIS_DELAY": "300", + "MAX_SEED_LOOKAHEAD": "4", + "ETH1_FOLLOW_DISTANCE": "2048", + "KZG_COMMITMENTS_INCLUSION_PROOF_DEPTH": "4", + "SECONDS_PER_SLOT": "12", + "REORG_PARENT_WEIGHT_THRESHOLD": "160", + "MIN_SYNC_COMMITTEE_PARTICIPANTS": "1", + "DATA_COLUMN_SIDECAR_SUBNET_COUNT": "128", + "MAX_PENDING_DEPOSITS_PER_EPOCH": "16", + "BELLATRIX_FORK_VERSION": "0x03017000", + "PROPORTIONAL_SLASHING_MULTIPLIER_BELLATRIX": "3", + "SAMPLES_PER_SLOT": "8", + "EFFECTIVE_BALANCE_INCREMENT": "1000000000", + "MAX_PAYLOAD_SIZE": "10485760", + "MIN_PER_EPOCH_CHURN_LIMIT_ELECTRA": "128000000000", + "MIN_EPOCHS_FOR_DATA_COLUMN_SIDECARS_REQUESTS": "4096", + "FIELD_ELEMENTS_PER_BLOB": "4096", + "MIN_EPOCHS_TO_INACTIVITY_PENALTY": "4", + "BASE_REWARD_FACTOR": "64", + "MAX_EXTRA_DATA_BYTES": "32", + "CONFIG_NAME": "holesky", + "MAX_PROPOSER_SLASHINGS": "16", + "INACTIVITY_SCORE_RECOVERY_RATE": "16", + "MIN_EPOCHS_FOR_BLOB_SIDECARS_REQUESTS": "4096", + "MAX_TRANSACTIONS_PER_PAYLOAD": "1048576", + "DEPOSIT_CONTRACT_ADDRESS": "0x4242424242424242424242424242424242424242", + "MIN_ATTESTATION_INCLUSION_DELAY": "1", + "SHUFFLE_ROUND_COUNT": "90", + "TERMINAL_BLOCK_HASH_ACTIVATION_EPOCH": "18446744073709551615", + "MAX_EFFECTIVE_BALANCE": "32000000000", + "DOMAIN_BEACON_PROPOSER": "0x00000000", + "DENEB_FORK_EPOCH": "29696", + "DOMAIN_SYNC_COMMITTEE": "0x07000000", + "PROPOSER_SCORE_BOOST": "40", + "FULU_FORK_EPOCH": "165120", + "MAX_BLOBS_PER_BLOCK_FULU": "12", + "DOMAIN_SELECTION_PROOF": "0x05000000", + "MIN_SLASHING_PENALTY_QUOTIENT_BELLATRIX": "32", + "MAX_PER_EPOCH_ACTIVATION_CHURN_LIMIT": "8", + "HYSTERESIS_UPWARD_MULTIPLIER": "5", + "SUBNETS_PER_NODE": "2", + "MIN_DEPOSIT_AMOUNT": "1000000000", + "MIN_SLASHING_PENALTY_QUOTIENT_ELECTRA": "4096", + "PROPORTIONAL_SLASHING_MULTIPLIER_ALTAIR": "2", + "MAX_BLOBS_PER_BLOCK": "6", + "VALIDATOR_CUSTODY_REQUIREMENT": "8", + "MIN_VALIDATOR_WITHDRAWABILITY_DELAY": "256", + "MAXIMUM_GOSSIP_CLOCK_DISPARITY": "500", + "TARGET_COMMITTEE_SIZE": "128", + "TERMINAL_BLOCK_HASH": "0x0000000000000000000000000000000000000000000000000000000000000000", + "DOMAIN_DEPOSIT": "0x03000000", + "DOMAIN_CONTRIBUTION_AND_PROOF": "0x09000000", + "UPDATE_TIMEOUT": "8192", + "ELECTRA_FORK_EPOCH": "115968", + "SYNC_COMMITTEE_BRANCH_LENGTH": "5", + "DEPOSIT_CHAIN_ID": "17000", + "MAX_BLOB_COMMITMENTS_PER_BLOCK": "4096", + "DOMAIN_RANDAO": "0x02000000", + "CAPELLA_FORK_VERSION": "0x04017000", + "MAX_EFFECTIVE_BALANCE_ELECTRA": "2048000000000", + "MIN_SLASHING_PENALTY_QUOTIENT_ALTAIR": "64", + "EPOCHS_PER_ETH1_VOTING_PERIOD": "64", + "WHISTLEBLOWER_REWARD_QUOTIENT_ELECTRA": "4096", + "HISTORICAL_ROOTS_LIMIT": "16777216", + "ATTESTATION_PROPAGATION_SLOT_RANGE": "32", + "MAX_BLOBS_PER_BLOCK_ELECTRA": "9", + "SYNC_COMMITTEE_SIZE": "512", + "MAX_REQUEST_DATA_COLUMN_SIDECARS": "512", + "ATTESTATION_SUBNET_PREFIX_BITS": "6", + "NUMBER_OF_COLUMNS": "128", + "PROPORTIONAL_SLASHING_MULTIPLIER": "1", + "MAX_WITHDRAWAL_REQUESTS_PER_PAYLOAD": "16", + "MESSAGE_DOMAIN_VALID_SNAPPY": "0x01000000", + "MAX_VOLUNTARY_EXITS": "16", + "PENDING_CONSOLIDATIONS_LIMIT": "262144", + "HYSTERESIS_DOWNWARD_MULTIPLIER": "1", + "DOMAIN_APPLICATION_BUILDER": "0x00000001", + "MAX_PENDING_PARTIALS_PER_WITHDRAWALS_SWEEP": "8", + "FULU_FORK_VERSION": "0x07017000", + "EPOCHS_PER_SYNC_COMMITTEE_PERIOD": "256", + "BYTES_PER_LOGS_BLOOM": "256", + "MAX_DEPOSIT_REQUESTS_PER_PAYLOAD": "8192", + "CUSTODY_REQUIREMENT": "4", + "MIN_GENESIS_ACTIVE_VALIDATOR_COUNT": "16384", + "BLOB_SIDECAR_SUBNET_COUNT_ELECTRA": "9", + "MAX_REQUEST_BLOB_SIDECARS_ELECTRA": "1152", + "MAX_ATTESTATIONS": "128", + "MIN_EPOCHS_FOR_BLOCK_REQUESTS": "33024", + "DENEB_FORK_VERSION": "0x05017000", + "ELECTRA_FORK_VERSION": "0x06017000", + "MAX_REQUEST_BLOCKS": "1024", + "GENESIS_FORK_VERSION": "0x01017000", + "KZG_COMMITMENT_INCLUSION_PROOF_DEPTH": "17", + "DEPOSIT_NETWORK_ID": "17000", + "MAX_CONSOLIDATION_REQUESTS_PER_PAYLOAD": "2", + "MAX_REQUEST_BLOCKS_DENEB": "128", + "BLOB_SIDECAR_SUBNET_COUNT": "6", + "SYNC_COMMITTEE_SUBNET_COUNT": "4", + "CAPELLA_FORK_EPOCH": "256", + "EJECTION_BALANCE": "28000000000", + "ATTESTATION_SUBNET_EXTRA_BITS": "0", + "NUMBER_OF_CUSTODY_GROUPS": "128", + "MAX_COMMITTEES_PER_SLOT": "64", + "SHARD_COMMITTEE_PERIOD": "256", + "INACTIVITY_PENALTY_QUOTIENT_ALTAIR": "50331648", + "DOMAIN_AGGREGATE_AND_PROOF": "0x06000000", + "CHURN_LIMIT_QUOTIENT": "65536", + "BLS_WITHDRAWAL_PREFIX": "0x00", + "MIN_ACTIVATION_BALANCE": "32000000000" + } } \ No newline at end of file diff --git a/tests/data/hoodi_spec.json b/tests/data/hoodi_spec.json index df9801f1..4a8443ed 100644 --- a/tests/data/hoodi_spec.json +++ b/tests/data/hoodi_spec.json @@ -20,7 +20,9 @@ "ELECTRA_FORK_VERSION": "0x60000910", "ELECTRA_FORK_EPOCH": "2048", "FULU_FORK_VERSION": "0x70000910", - "FULU_FORK_EPOCH": "18446744073709551615", + "FULU_FORK_EPOCH": "50688", + "GLOAS_FORK_VERSION": "0x80000910", + "GLOAS_FORK_EPOCH": "18446744073709551615", "SECONDS_PER_SLOT": "12", "SECONDS_PER_ETH1_BLOCK": "12", "MIN_VALIDATOR_WITHDRAWABILITY_DELAY": "256", @@ -38,10 +40,9 @@ "DEPOSIT_NETWORK_ID": "560048", "DEPOSIT_CONTRACT_ADDRESS": "0x00000000219ab540356cbb839cbe05303d7705fa", "GAS_LIMIT_ADJUSTMENT_FACTOR": "1024", - "GOSSIP_MAX_SIZE": "10485760", + "MAX_PAYLOAD_SIZE": "10485760", "MAX_REQUEST_BLOCKS": "1024", "MIN_EPOCHS_FOR_BLOCK_REQUESTS": "33024", - "MAX_CHUNK_SIZE": "10485760", "TTFB_TIMEOUT": "5", "RESP_TIMEOUT": "10", "ATTESTATION_PROPAGATION_SLOT_RANGE": "32", @@ -60,11 +61,23 @@ "MAX_BLOBS_PER_BLOCK_ELECTRA": "9", "BLOB_SIDECAR_SUBNET_COUNT_ELECTRA": "9", "MAX_REQUEST_BLOB_SIDECARS_ELECTRA": "1152", - "NUMBER_OF_COLUMNS": "128", "NUMBER_OF_CUSTODY_GROUPS": "128", "DATA_COLUMN_SIDECAR_SUBNET_COUNT": "128", "SAMPLES_PER_SLOT": "8", "CUSTODY_REQUIREMENT": "4", + "BLOB_SCHEDULE": [ + { + "EPOCH": "52480", + "MAX_BLOBS_PER_BLOCK": "15" + }, + { + "EPOCH": "54016", + "MAX_BLOBS_PER_BLOCK": "21" + } + ], + "VALIDATOR_CUSTODY_REQUIREMENT": "8", + "BALANCE_PER_ADDITIONAL_CUSTODY_GROUP": "32000000000", + "MIN_EPOCHS_FOR_DATA_COLUMN_SIDECARS_REQUESTS": "4096", "MAX_COMMITTEES_PER_SLOT": "64", "TARGET_COMMITTEE_SIZE": "128", "MAX_VALIDATORS_PER_COMMITTEE": "2048", @@ -119,37 +132,40 @@ "MAX_EFFECTIVE_BALANCE_ELECTRA": "2048000000000", "MIN_SLASHING_PENALTY_QUOTIENT_ELECTRA": "4096", "WHISTLEBLOWER_REWARD_QUOTIENT_ELECTRA": "4096", - "MAX_PENDING_PARTIALS_PER_WITHDRAWALS_SWEEP": "8", "PENDING_DEPOSITS_LIMIT": "134217728", "PENDING_PARTIAL_WITHDRAWALS_LIMIT": "134217728", "PENDING_CONSOLIDATIONS_LIMIT": "262144", - "MAX_CONSOLIDATION_REQUESTS_PER_PAYLOAD": "2", - "MAX_DEPOSIT_REQUESTS_PER_PAYLOAD": "8192", "MAX_ATTESTER_SLASHINGS_ELECTRA": "1", "MAX_ATTESTATIONS_ELECTRA": "8", + "MAX_DEPOSIT_REQUESTS_PER_PAYLOAD": "8192", "MAX_WITHDRAWAL_REQUESTS_PER_PAYLOAD": "16", + "MAX_CONSOLIDATION_REQUESTS_PER_PAYLOAD": "2", + "MAX_PENDING_PARTIALS_PER_WITHDRAWALS_SWEEP": "8", + "MAX_PENDING_DEPOSITS_PER_EPOCH": "16", "FIELD_ELEMENTS_PER_CELL": "64", "FIELD_ELEMENTS_PER_EXT_BLOB": "8192", "KZG_COMMITMENTS_INCLUSION_PROOF_DEPTH": "4", - "VERSIONED_HASH_VERSION_KZG": "1", + "CELLS_PER_EXT_BLOB": "128", + "NUMBER_OF_COLUMNS": "128", + "DOMAIN_SYNC_COMMITTEE_SELECTION_PROOF": "0x08000000", + "DOMAIN_RANDAO": "0x02000000", + "COMPOUNDING_WITHDRAWAL_PREFIX": "0x02", + "TARGET_AGGREGATORS_PER_SYNC_SUBCOMMITTEE": "16", + "DOMAIN_CONTRIBUTION_AND_PROOF": "0x09000000", + "DOMAIN_AGGREGATE_AND_PROOF": "0x06000000", "DOMAIN_SYNC_COMMITTEE": "0x07000000", + "ETH1_ADDRESS_WITHDRAWAL_PREFIX": "0x01", + "DOMAIN_APPLICATION_MASK": "0x00000001", + "DOMAIN_DEPOSIT": "0x03000000", + "DOMAIN_BEACON_ATTESTER": "0x01000000", "DOMAIN_VOLUNTARY_EXIT": "0x04000000", "TARGET_AGGREGATORS_PER_COMMITTEE": "16", - "SYNC_COMMITTEE_SUBNET_COUNT": "4", - "DOMAIN_BEACON_ATTESTER": "0x01000000", - "FULL_EXIT_REQUEST_AMOUNT": "0", "BLS_WITHDRAWAL_PREFIX": "0x00", "DOMAIN_SELECTION_PROOF": "0x05000000", - "DOMAIN_AGGREGATE_AND_PROOF": "0x06000000", - "DOMAIN_DEPOSIT": "0x03000000", - "DOMAIN_CONTRIBUTION_AND_PROOF": "0x09000000", - "DOMAIN_SYNC_COMMITTEE_SELECTION_PROOF": "0x08000000", - "COMPOUNDING_WITHDRAWAL_PREFIX": "0x02", - "DOMAIN_APPLICATION_MASK": "0x00000001", - "DOMAIN_RANDAO": "0x02000000", - "UNSET_DEPOSIT_REQUESTS_START_INDEX": "18446744073709551615", - "TARGET_AGGREGATORS_PER_SYNC_SUBCOMMITTEE": "16", + "SYNC_COMMITTEE_SUBNET_COUNT": "4", + "VERSIONED_HASH_VERSION_KZG": "1", "DOMAIN_BEACON_PROPOSER": "0x00000000", - "ETH1_ADDRESS_WITHDRAWAL_PREFIX": "0x01" + "UNSET_DEPOSIT_REQUESTS_START_INDEX": "18446744073709551615", + "FULL_EXIT_REQUEST_AMOUNT": "0" } } \ No newline at end of file diff --git a/tests/data/mainnet_spec_data.json b/tests/data/mainnet_spec_data.json index e60edc6a..9416561e 100644 --- a/tests/data/mainnet_spec_data.json +++ b/tests/data/mainnet_spec_data.json @@ -1,145 +1,158 @@ { "data": { - "SLOTS_PER_EPOCH": "32", + "CONFIG_NAME": "mainnet", "PRESET_BASE": "mainnet", "TERMINAL_TOTAL_DIFFICULTY": "58750000000000000000000", - "INACTIVITY_SCORE_BIAS": "4", - "PENDING_BALANCE_DEPOSITS_LIMIT": "134217728", - "MAX_ATTESTER_SLASHINGS": "2", - "MAX_WITHDRAWALS_PER_PAYLOAD": "16", - "INACTIVITY_PENALTY_QUOTIENT_BELLATRIX": "16777216", - "PENDING_PARTIAL_WITHDRAWALS_LIMIT": "134217728", - "INACTIVITY_PENALTY_QUOTIENT": "67108864", - "SAFE_SLOTS_TO_UPDATE_JUSTIFIED": "8", - "SECONDS_PER_ETH1_BLOCK": "14", - "MIN_SEED_LOOKAHEAD": "1", - "VALIDATOR_REGISTRY_LIMIT": "1099511627776", - "REORG_MAX_EPOCHS_SINCE_FINALIZATION": "2", - "SLOTS_PER_HISTORICAL_ROOT": "8192", - "RESP_TIMEOUT": "10", - "DOMAIN_VOLUNTARY_EXIT": "0x04000000", - "MAX_VALIDATORS_PER_COMMITTEE": "2048", + "TERMINAL_BLOCK_HASH": "0x0000000000000000000000000000000000000000000000000000000000000000", + "TERMINAL_BLOCK_HASH_ACTIVATION_EPOCH": "18446744073709551615", + "MIN_GENESIS_ACTIVE_VALIDATOR_COUNT": "16384", "MIN_GENESIS_TIME": "1606824000", - "ALTAIR_FORK_EPOCH": "74240", - "MAX_PER_EPOCH_ACTIVATION_EXIT_CHURN_LIMIT": "256000000000", - "HYSTERESIS_QUOTIENT": "4", + "GENESIS_FORK_VERSION": "0x00000000", + "GENESIS_DELAY": "604800", "ALTAIR_FORK_VERSION": "0x01000000", - "MAX_BYTES_PER_TRANSACTION": "1073741824", - "MAX_CHUNK_SIZE": "10485760", - "TTFB_TIMEOUT": "5", - "WHISTLEBLOWER_REWARD_QUOTIENT": "512", - "PROPOSER_REWARD_QUOTIENT": "8", - "MAX_VALIDATORS_PER_WITHDRAWALS_SWEEP": "16384", - "EPOCHS_PER_HISTORICAL_VECTOR": "65536", - "MIN_PER_EPOCH_CHURN_LIMIT": "4", - "MAX_ATTESTER_SLASHINGS_ELECTRA": "1", - "TARGET_AGGREGATORS_PER_SYNC_SUBCOMMITTEE": "16", - "MAX_DEPOSITS": "16", + "ALTAIR_FORK_EPOCH": "74240", + "BELLATRIX_FORK_VERSION": "0x02000000", "BELLATRIX_FORK_EPOCH": "144896", - "MAX_REQUEST_BLOB_SIDECARS": "768", - "REORG_HEAD_WEIGHT_THRESHOLD": "20", - "TARGET_AGGREGATORS_PER_COMMITTEE": "16", - "DOMAIN_SYNC_COMMITTEE_SELECTION_PROOF": "0x08000000", - "MESSAGE_DOMAIN_INVALID_SNAPPY": "0x00000000", - "EPOCHS_PER_SLASHINGS_VECTOR": "8192", - "MIN_SLASHING_PENALTY_QUOTIENT": "128", - "MAX_BLS_TO_EXECUTION_CHANGES": "16", - "GOSSIP_MAX_SIZE": "10485760", - "DOMAIN_BEACON_ATTESTER": "0x01000000", - "EPOCHS_PER_SUBNET_SUBSCRIPTION": "256", - "MAX_ATTESTATIONS_ELECTRA": "8", - "ATTESTATION_SUBNET_COUNT": "64", - "GENESIS_DELAY": "604800", - "MAX_SEED_LOOKAHEAD": "4", - "ETH1_FOLLOW_DISTANCE": "2048", + "CAPELLA_FORK_VERSION": "0x03000000", + "CAPELLA_FORK_EPOCH": "194048", + "DENEB_FORK_VERSION": "0x04000000", + "DENEB_FORK_EPOCH": "269568", + "ELECTRA_FORK_VERSION": "0x05000000", + "ELECTRA_FORK_EPOCH": "364032", + "FULU_FORK_VERSION": "0x06000000", + "FULU_FORK_EPOCH": "18446744073709551615", "SECONDS_PER_SLOT": "12", - "REORG_PARENT_WEIGHT_THRESHOLD": "160", - "MIN_SYNC_COMMITTEE_PARTICIPANTS": "1", - "BELLATRIX_FORK_VERSION": "0x02000000", - "PROPORTIONAL_SLASHING_MULTIPLIER_BELLATRIX": "3", - "EFFECTIVE_BALANCE_INCREMENT": "1000000000", - "MIN_PER_EPOCH_CHURN_LIMIT_ELECTRA": "128000000000", - "FIELD_ELEMENTS_PER_BLOB": "4096", - "MIN_EPOCHS_TO_INACTIVITY_PENALTY": "4", - "BASE_REWARD_FACTOR": "64", - "MAX_EXTRA_DATA_BYTES": "32", - "CONFIG_NAME": "mainnet", - "MAX_PROPOSER_SLASHINGS": "16", - "MAX_CONSOLIDATIONS": "1", + "SECONDS_PER_ETH1_BLOCK": "14", + "MIN_VALIDATOR_WITHDRAWABILITY_DELAY": "256", + "SHARD_COMMITTEE_PERIOD": "256", + "ETH1_FOLLOW_DISTANCE": "2048", + "SUBNETS_PER_NODE": "2", + "INACTIVITY_SCORE_BIAS": "4", "INACTIVITY_SCORE_RECOVERY_RATE": "16", + "EJECTION_BALANCE": "16000000000", + "MIN_PER_EPOCH_CHURN_LIMIT": "4", + "MAX_PER_EPOCH_ACTIVATION_CHURN_LIMIT": "8", + "CHURN_LIMIT_QUOTIENT": "65536", + "PROPOSER_SCORE_BOOST": "40", + "DEPOSIT_CHAIN_ID": "1", + "DEPOSIT_NETWORK_ID": "1", + "DEPOSIT_CONTRACT_ADDRESS": "0x00000000219ab540356cbb839cbe05303d7705fa", + "GAS_LIMIT_ADJUSTMENT_FACTOR": "1024", + "MAX_PAYLOAD_SIZE": "10485760", + "MAX_REQUEST_BLOCKS": "1024", + "MIN_EPOCHS_FOR_BLOCK_REQUESTS": "33024", + "TTFB_TIMEOUT": "5", + "RESP_TIMEOUT": "10", + "ATTESTATION_PROPAGATION_SLOT_RANGE": "32", + "MAXIMUM_GOSSIP_CLOCK_DISPARITY_MILLIS": "500", + "MESSAGE_DOMAIN_INVALID_SNAPPY": "0x00000000", + "MESSAGE_DOMAIN_VALID_SNAPPY": "0x01000000", + "ATTESTATION_SUBNET_PREFIX_BITS": "6", + "MAX_REQUEST_BLOCKS_DENEB": "128", + "MAX_REQUEST_BLOB_SIDECARS": "768", + "MAX_REQUEST_DATA_COLUMN_SIDECARS": "16384", "MIN_EPOCHS_FOR_BLOB_SIDECARS_REQUESTS": "4096", - "MAX_TRANSACTIONS_PER_PAYLOAD": "1048576", - "DEPOSIT_CONTRACT_ADDRESS": "0x00000000219ab540356cBB839Cbe05303d7705Fa", - "MIN_ATTESTATION_INCLUSION_DELAY": "1", + "BLOB_SIDECAR_SUBNET_COUNT": "6", + "MAX_BLOBS_PER_BLOCK": "6", + "MIN_PER_EPOCH_CHURN_LIMIT_ELECTRA": "128000000000", + "MAX_PER_EPOCH_ACTIVATION_EXIT_CHURN_LIMIT": "256000000000", + "MAX_BLOBS_PER_BLOCK_ELECTRA": "9", + "BLOB_SIDECAR_SUBNET_COUNT_ELECTRA": "9", + "MAX_REQUEST_BLOB_SIDECARS_ELECTRA": "1152", + "NUMBER_OF_COLUMNS": "128", + "NUMBER_OF_CUSTODY_GROUPS": "128", + "DATA_COLUMN_SIDECAR_SUBNET_COUNT": "128", + "SAMPLES_PER_SLOT": "8", + "CUSTODY_REQUIREMENT": "4", + "VALIDATOR_CUSTODY_REQUIREMENT": "8", + "BALANCE_PER_ADDITIONAL_CUSTODY_GROUP": "32000000000", + "MIN_EPOCHS_FOR_DATA_COLUMN_SIDECARS_REQUESTS": "4096", + "MAX_COMMITTEES_PER_SLOT": "64", + "TARGET_COMMITTEE_SIZE": "128", + "MAX_VALIDATORS_PER_COMMITTEE": "2048", "SHUFFLE_ROUND_COUNT": "90", - "TERMINAL_BLOCK_HASH_ACTIVATION_EPOCH": "18446744073709551615", - "MAX_EFFECTIVE_BALANCE": "32000000000", - "DOMAIN_BEACON_PROPOSER": "0x00000000", - "DENEB_FORK_EPOCH": "269568", - "DOMAIN_SYNC_COMMITTEE": "0x07000000", - "PROPOSER_SCORE_BOOST": "40", - "DOMAIN_SELECTION_PROOF": "0x05000000", - "MIN_SLASHING_PENALTY_QUOTIENT_BELLATRIX": "32", - "MAX_PER_EPOCH_ACTIVATION_CHURN_LIMIT": "8", + "HYSTERESIS_QUOTIENT": "4", + "HYSTERESIS_DOWNWARD_MULTIPLIER": "1", "HYSTERESIS_UPWARD_MULTIPLIER": "5", - "SUBNETS_PER_NODE": "2", "MIN_DEPOSIT_AMOUNT": "1000000000", - "MIN_SLASHING_PENALTY_QUOTIENT_ELECTRA": "4096", - "PROPORTIONAL_SLASHING_MULTIPLIER_ALTAIR": "2", - "MAX_BLOBS_PER_BLOCK": "6", - "MIN_VALIDATOR_WITHDRAWABILITY_DELAY": "256", - "MAXIMUM_GOSSIP_CLOCK_DISPARITY": "500", - "TARGET_COMMITTEE_SIZE": "128", - "TERMINAL_BLOCK_HASH": "0x0000000000000000000000000000000000000000000000000000000000000000", - "DOMAIN_DEPOSIT": "0x03000000", - "DOMAIN_CONTRIBUTION_AND_PROOF": "0x09000000", - "UPDATE_TIMEOUT": "8192", - "ELECTRA_FORK_EPOCH": "18446744073709551615", - "SYNC_COMMITTEE_BRANCH_LENGTH": "5", - "DEPOSIT_CHAIN_ID": "1", - "MAX_BLOB_COMMITMENTS_PER_BLOCK": "4096", - "DOMAIN_RANDAO": "0x02000000", - "CAPELLA_FORK_VERSION": "0x03000000", - "MAX_EFFECTIVE_BALANCE_ELECTRA": "2048000000000", - "MIN_SLASHING_PENALTY_QUOTIENT_ALTAIR": "64", + "MAX_EFFECTIVE_BALANCE": "32000000000", + "EFFECTIVE_BALANCE_INCREMENT": "1000000000", + "MIN_ATTESTATION_INCLUSION_DELAY": "1", + "SLOTS_PER_EPOCH": "32", + "MIN_SEED_LOOKAHEAD": "1", + "MAX_SEED_LOOKAHEAD": "4", "EPOCHS_PER_ETH1_VOTING_PERIOD": "64", - "MAX_DEPOSIT_RECEIPTS_PER_PAYLOAD": "8192", - "WHISTLEBLOWER_REWARD_QUOTIENT_ELECTRA": "4096", + "SLOTS_PER_HISTORICAL_ROOT": "8192", + "MIN_EPOCHS_TO_INACTIVITY_PENALTY": "4", + "EPOCHS_PER_HISTORICAL_VECTOR": "65536", + "EPOCHS_PER_SLASHINGS_VECTOR": "8192", "HISTORICAL_ROOTS_LIMIT": "16777216", - "ATTESTATION_PROPAGATION_SLOT_RANGE": "32", - "SYNC_COMMITTEE_SIZE": "512", - "ATTESTATION_SUBNET_PREFIX_BITS": "6", + "VALIDATOR_REGISTRY_LIMIT": "1099511627776", + "BASE_REWARD_FACTOR": "64", + "WHISTLEBLOWER_REWARD_QUOTIENT": "512", + "PROPOSER_REWARD_QUOTIENT": "8", + "INACTIVITY_PENALTY_QUOTIENT": "67108864", + "MIN_SLASHING_PENALTY_QUOTIENT": "128", "PROPORTIONAL_SLASHING_MULTIPLIER": "1", - "MAX_WITHDRAWAL_REQUESTS_PER_PAYLOAD": "16", - "MESSAGE_DOMAIN_VALID_SNAPPY": "0x01000000", + "MAX_PROPOSER_SLASHINGS": "16", + "MAX_ATTESTER_SLASHINGS": "2", + "MAX_ATTESTATIONS": "128", + "MAX_DEPOSITS": "16", "MAX_VOLUNTARY_EXITS": "16", - "PENDING_CONSOLIDATIONS_LIMIT": "262144", - "HYSTERESIS_DOWNWARD_MULTIPLIER": "1", - "DOMAIN_APPLICATION_BUILDER": "0x00000001", - "MAX_PENDING_PARTIALS_PER_WITHDRAWALS_SWEEP": "8", + "INACTIVITY_PENALTY_QUOTIENT_ALTAIR": "50331648", + "MIN_SLASHING_PENALTY_QUOTIENT_ALTAIR": "64", + "PROPORTIONAL_SLASHING_MULTIPLIER_ALTAIR": "2", + "SYNC_COMMITTEE_SIZE": "512", "EPOCHS_PER_SYNC_COMMITTEE_PERIOD": "256", + "MIN_SYNC_COMMITTEE_PARTICIPANTS": "1", + "INACTIVITY_PENALTY_QUOTIENT_BELLATRIX": "16777216", + "MIN_SLASHING_PENALTY_QUOTIENT_BELLATRIX": "32", + "PROPORTIONAL_SLASHING_MULTIPLIER_BELLATRIX": "3", + "MAX_BYTES_PER_TRANSACTION": "1073741824", + "MAX_TRANSACTIONS_PER_PAYLOAD": "1048576", "BYTES_PER_LOGS_BLOOM": "256", - "MIN_GENESIS_ACTIVE_VALIDATOR_COUNT": "16384", - "MAX_ATTESTATIONS": "128", - "MIN_EPOCHS_FOR_BLOCK_REQUESTS": "33024", - "DENEB_FORK_VERSION": "0x04000000", - "ELECTRA_FORK_VERSION": "0x05000000", - "MAX_REQUEST_BLOCKS": "1024", - "GENESIS_FORK_VERSION": "0x00000000", - "KZG_COMMITMENT_INCLUSION_PROOF_DEPTH": "17", - "DEPOSIT_NETWORK_ID": "1", - "MAX_REQUEST_BLOCKS_DENEB": "128", - "BLOB_SIDECAR_SUBNET_COUNT": "6", - "SYNC_COMMITTEE_SUBNET_COUNT": "4", - "CAPELLA_FORK_EPOCH": "194048", - "EJECTION_BALANCE": "16000000000", - "ATTESTATION_SUBNET_EXTRA_BITS": "0", - "MAX_COMMITTEES_PER_SLOT": "64", - "SHARD_COMMITTEE_PERIOD": "256", - "INACTIVITY_PENALTY_QUOTIENT_ALTAIR": "50331648", + "MAX_EXTRA_DATA_BYTES": "32", + "MAX_BLS_TO_EXECUTION_CHANGES": "16", + "MAX_WITHDRAWALS_PER_PAYLOAD": "16", + "MAX_VALIDATORS_PER_WITHDRAWALS_SWEEP": "16384", + "MAX_BLOB_COMMITMENTS_PER_BLOCK": "4096", + "FIELD_ELEMENTS_PER_BLOB": "4096", + "MIN_ACTIVATION_BALANCE": "32000000000", + "MAX_EFFECTIVE_BALANCE_ELECTRA": "2048000000000", + "MIN_SLASHING_PENALTY_QUOTIENT_ELECTRA": "4096", + "WHISTLEBLOWER_REWARD_QUOTIENT_ELECTRA": "4096", + "PENDING_DEPOSITS_LIMIT": "134217728", + "PENDING_PARTIAL_WITHDRAWALS_LIMIT": "134217728", + "PENDING_CONSOLIDATIONS_LIMIT": "262144", + "MAX_ATTESTER_SLASHINGS_ELECTRA": "1", + "MAX_ATTESTATIONS_ELECTRA": "8", + "MAX_DEPOSIT_REQUESTS_PER_PAYLOAD": "8192", + "MAX_WITHDRAWAL_REQUESTS_PER_PAYLOAD": "16", + "MAX_CONSOLIDATION_REQUESTS_PER_PAYLOAD": "2", + "MAX_PENDING_PARTIALS_PER_WITHDRAWALS_SWEEP": "8", + "MAX_PENDING_DEPOSITS_PER_EPOCH": "16", + "FIELD_ELEMENTS_PER_CELL": "64", + "FIELD_ELEMENTS_PER_EXT_BLOB": "8192", + "KZG_COMMITMENTS_INCLUSION_PROOF_DEPTH": "4", + "DOMAIN_CONTRIBUTION_AND_PROOF": "0x09000000", + "DOMAIN_BEACON_ATTESTER": "0x01000000", "DOMAIN_AGGREGATE_AND_PROOF": "0x06000000", - "CHURN_LIMIT_QUOTIENT": "65536", + "TARGET_AGGREGATORS_PER_COMMITTEE": "16", + "FULL_EXIT_REQUEST_AMOUNT": "0", + "DOMAIN_DEPOSIT": "0x03000000", + "COMPOUNDING_WITHDRAWAL_PREFIX": "0x02", + "DOMAIN_VOLUNTARY_EXIT": "0x04000000", + "DOMAIN_SELECTION_PROOF": "0x05000000", + "ETH1_ADDRESS_WITHDRAWAL_PREFIX": "0x01", + "UNSET_DEPOSIT_REQUESTS_START_INDEX": "18446744073709551615", + "VERSIONED_HASH_VERSION_KZG": "1", + "DOMAIN_RANDAO": "0x02000000", + "SYNC_COMMITTEE_SUBNET_COUNT": "4", + "DOMAIN_APPLICATION_MASK": "0x00000001", + "DOMAIN_SYNC_COMMITTEE_SELECTION_PROOF": "0x08000000", + "DOMAIN_BEACON_PROPOSER": "0x00000000", + "DOMAIN_SYNC_COMMITTEE": "0x07000000", "BLS_WITHDRAWAL_PREFIX": "0x00", - "MIN_ACTIVATION_BALANCE": "32000000000" + "TARGET_AGGREGATORS_PER_SYNC_SUBCOMMITTEE": "16" } } \ No newline at end of file diff --git a/tests/data/sepolia_spec_data.json b/tests/data/sepolia_spec_data.json index 6e20afd0..228c12c3 100644 --- a/tests/data/sepolia_spec_data.json +++ b/tests/data/sepolia_spec_data.json @@ -4,7 +4,6 @@ "PRESET_BASE": "mainnet", "TERMINAL_TOTAL_DIFFICULTY": "17000000000000000", "INACTIVITY_SCORE_BIAS": "4", - "PENDING_BALANCE_DEPOSITS_LIMIT": "134217728", "MAX_ATTESTER_SLASHINGS": "2", "MAX_WITHDRAWALS_PER_PAYLOAD": "16", "INACTIVITY_PENALTY_QUOTIENT_BELLATRIX": "16777216", @@ -14,17 +13,20 @@ "SECONDS_PER_ETH1_BLOCK": "14", "MIN_SEED_LOOKAHEAD": "1", "VALIDATOR_REGISTRY_LIMIT": "1099511627776", + "REORG_MAX_EPOCHS_SINCE_FINALIZATION": "2", "SLOTS_PER_HISTORICAL_ROOT": "8192", + "FIELD_ELEMENTS_PER_EXT_BLOB": "8192", "RESP_TIMEOUT": "10", "DOMAIN_VOLUNTARY_EXIT": "0x04000000", "MAX_VALIDATORS_PER_COMMITTEE": "2048", "MIN_GENESIS_TIME": "1655647200", "ALTAIR_FORK_EPOCH": "50", + "MAX_PER_EPOCH_ACTIVATION_EXIT_CHURN_LIMIT": "256000000000", "HYSTERESIS_QUOTIENT": "4", "ALTAIR_FORK_VERSION": "0x90000070", "MAX_BYTES_PER_TRANSACTION": "1073741824", - "MAX_CHUNK_SIZE": "10485760", "TTFB_TIMEOUT": "5", + "MAX_CHUNK_SIZE": "10485760", "WHISTLEBLOWER_REWARD_QUOTIENT": "512", "PROPOSER_REWARD_QUOTIENT": "8", "MAX_VALIDATORS_PER_WITHDRAWALS_SWEEP": "16384", @@ -33,8 +35,10 @@ "MAX_ATTESTER_SLASHINGS_ELECTRA": "1", "TARGET_AGGREGATORS_PER_SYNC_SUBCOMMITTEE": "16", "MAX_DEPOSITS": "16", + "FIELD_ELEMENTS_PER_CELL": "64", "BELLATRIX_FORK_EPOCH": "100", "MAX_REQUEST_BLOB_SIDECARS": "768", + "REORG_HEAD_WEIGHT_THRESHOLD": "20", "TARGET_AGGREGATORS_PER_COMMITTEE": "16", "DOMAIN_SYNC_COMMITTEE_SELECTION_PROOF": "0x08000000", "MESSAGE_DOMAIN_INVALID_SNAPPY": "0x00000000", @@ -44,30 +48,36 @@ "GOSSIP_MAX_SIZE": "10485760", "DOMAIN_BEACON_ATTESTER": "0x01000000", "EPOCHS_PER_SUBNET_SUBSCRIPTION": "256", + "PENDING_DEPOSITS_LIMIT": "134217728", "MAX_ATTESTATIONS_ELECTRA": "8", "ATTESTATION_SUBNET_COUNT": "64", "GENESIS_DELAY": "86400", "MAX_SEED_LOOKAHEAD": "4", "ETH1_FOLLOW_DISTANCE": "2048", + "KZG_COMMITMENTS_INCLUSION_PROOF_DEPTH": "4", "SECONDS_PER_SLOT": "12", + "REORG_PARENT_WEIGHT_THRESHOLD": "160", "MIN_SYNC_COMMITTEE_PARTICIPANTS": "1", + "MAX_PENDING_DEPOSITS_PER_EPOCH": "16", "BELLATRIX_FORK_VERSION": "0x90000071", "PROPORTIONAL_SLASHING_MULTIPLIER_BELLATRIX": "3", "EFFECTIVE_BALANCE_INCREMENT": "1000000000", + "MAX_PAYLOAD_SIZE": "10485760", + "MIN_PER_EPOCH_CHURN_LIMIT_ELECTRA": "128000000000", "FIELD_ELEMENTS_PER_BLOB": "4096", "MIN_EPOCHS_TO_INACTIVITY_PENALTY": "4", "BASE_REWARD_FACTOR": "64", "MAX_EXTRA_DATA_BYTES": "32", + "FULU_FORK_EPOCH": "272640", "CONFIG_NAME": "sepolia", "MAX_PROPOSER_SLASHINGS": "16", - "MAX_CONSOLIDATIONS": "1", "INACTIVITY_SCORE_RECOVERY_RATE": "16", "MIN_EPOCHS_FOR_BLOB_SIDECARS_REQUESTS": "4096", "MAX_TRANSACTIONS_PER_PAYLOAD": "1048576", "DEPOSIT_CONTRACT_ADDRESS": "0x7f02C3E3c98b133055B8B348B2Ac625669Ed295D", "MIN_ATTESTATION_INCLUSION_DELAY": "1", "SHUFFLE_ROUND_COUNT": "90", - "TERMINAL_BLOCK_HASH_ACTIVATION_EPOCH": "18446744073709551615", + "TERMINAL_BLOCK_HASH_ACTIVATION_EPOCH": "3599", "MAX_EFFECTIVE_BALANCE": "32000000000", "DOMAIN_BEACON_PROPOSER": "0x00000000", "DENEB_FORK_EPOCH": "132608", @@ -85,11 +95,11 @@ "MIN_VALIDATOR_WITHDRAWABILITY_DELAY": "256", "MAXIMUM_GOSSIP_CLOCK_DISPARITY": "500", "TARGET_COMMITTEE_SIZE": "128", - "TERMINAL_BLOCK_HASH": "0x0000000000000000000000000000000000000000000000000000000000000000", + "TERMINAL_BLOCK_HASH": "0xd07cce9785d39c0dd2409b7d8e69d6bff26a69a0fa5308ac781c63ffe2a37bc1", "DOMAIN_DEPOSIT": "0x03000000", "DOMAIN_CONTRIBUTION_AND_PROOF": "0x09000000", "UPDATE_TIMEOUT": "8192", - "ELECTRA_FORK_EPOCH": "18446744073709551615", + "ELECTRA_FORK_EPOCH": "222464", "SYNC_COMMITTEE_BRANCH_LENGTH": "5", "DEPOSIT_CHAIN_ID": "11155111", "MAX_BLOB_COMMITMENTS_PER_BLOCK": "4096", @@ -98,10 +108,10 @@ "MAX_EFFECTIVE_BALANCE_ELECTRA": "2048000000000", "MIN_SLASHING_PENALTY_QUOTIENT_ALTAIR": "64", "EPOCHS_PER_ETH1_VOTING_PERIOD": "64", - "MAX_DEPOSIT_RECEIPTS_PER_PAYLOAD": "8192", "WHISTLEBLOWER_REWARD_QUOTIENT_ELECTRA": "4096", "HISTORICAL_ROOTS_LIMIT": "16777216", "ATTESTATION_PROPAGATION_SLOT_RANGE": "32", + "MAX_BLOBS_PER_BLOCK_ELECTRA": "9", "SYNC_COMMITTEE_SIZE": "512", "ATTESTATION_SUBNET_PREFIX_BITS": "6", "PROPORTIONAL_SLASHING_MULTIPLIER": "1", @@ -114,7 +124,10 @@ "MAX_PENDING_PARTIALS_PER_WITHDRAWALS_SWEEP": "8", "EPOCHS_PER_SYNC_COMMITTEE_PERIOD": "256", "BYTES_PER_LOGS_BLOOM": "256", + "MAX_DEPOSIT_REQUESTS_PER_PAYLOAD": "8192", "MIN_GENESIS_ACTIVE_VALIDATOR_COUNT": "1300", + "BLOB_SIDECAR_SUBNET_COUNT_ELECTRA": "9", + "MAX_REQUEST_BLOB_SIDECARS_ELECTRA": "1152", "MAX_ATTESTATIONS": "128", "MIN_EPOCHS_FOR_BLOCK_REQUESTS": "33024", "DENEB_FORK_VERSION": "0x90000073", @@ -123,6 +136,7 @@ "GENESIS_FORK_VERSION": "0x90000069", "KZG_COMMITMENT_INCLUSION_PROOF_DEPTH": "17", "DEPOSIT_NETWORK_ID": "11155111", + "MAX_CONSOLIDATION_REQUESTS_PER_PAYLOAD": "2", "MAX_REQUEST_BLOCKS_DENEB": "128", "BLOB_SIDECAR_SUBNET_COUNT": "6", "SYNC_COMMITTEE_SUBNET_COUNT": "4", From 18b89db44b3817d116a0e4bc674ae1a7cab92169 Mon Sep 17 00:00:00 2001 From: eltitanb Date: Wed, 1 Oct 2025 18:19:08 +0100 Subject: [PATCH 7/9] fix edge case --- crates/common/src/pbs/types/mod.rs | 2 + crates/pbs/src/mev_boost/submit_block.rs | 122 ++++++++++++++++------- 2 files changed, 87 insertions(+), 37 deletions(-) diff --git a/crates/common/src/pbs/types/mod.rs b/crates/common/src/pbs/types/mod.rs index c18f1119..93364948 100644 --- a/crates/common/src/pbs/types/mod.rs +++ b/crates/common/src/pbs/types/mod.rs @@ -40,6 +40,8 @@ pub type BuilderBidElectra = lh_types::builder_bid::BuilderBidElectra; +pub type KzgCommitments = lh_types::beacon_block_body::KzgCommitments; + /// Response params of GET /// `/eth/v1/builder/header/{slot}/{parent_hash}/{pubkey}` #[derive(Debug, Serialize, Deserialize, Clone)] diff --git a/crates/pbs/src/mev_boost/submit_block.rs b/crates/pbs/src/mev_boost/submit_block.rs index ee124a94..68a3384e 100644 --- a/crates/pbs/src/mev_boost/submit_block.rs +++ b/crates/pbs/src/mev_boost/submit_block.rs @@ -1,12 +1,14 @@ -use std::time::{Duration, Instant}; +use std::{ + str::FromStr, + time::{Duration, Instant}, +}; -use alloy::eips::eip7594::CELLS_PER_EXT_BLOB; +use alloy::{eips::eip7594::CELLS_PER_EXT_BLOB, primitives::B256}; use axum::http::{HeaderMap, HeaderValue}; use cb_common::{ pbs::{ - BlindedBeaconBlock, BlindedBeaconBlockElectra, BlindedBeaconBlockFulu, BlobsBundle, - BuilderApiVersion, ExecutionPayload, ExecutionPayloadElectra, ExecutionPayloadFulu, - HEADER_CONSENSUS_VERSION, HEADER_START_TIME_UNIX_MS, RelayClient, SignedBlindedBeaconBlock, + BlindedBeaconBlock, BlobsBundle, BuilderApiVersion, ForkName, HEADER_CONSENSUS_VERSION, + HEADER_START_TIME_UNIX_MS, KzgCommitments, RelayClient, SignedBlindedBeaconBlock, SubmitBlindedBlockResponse, error::{PbsError, ValidationError}, }, @@ -35,14 +37,21 @@ pub async fn submit_block( api_version: &BuilderApiVersion, ) -> eyre::Result> { debug!(?req_headers, "received headers"); - let consensus_version = - req_headers.get(HEADER_CONSENSUS_VERSION).cloned().unwrap_or_else(|| { + + let fork_name = req_headers + .get(HEADER_CONSENSUS_VERSION) + .and_then(|h| { + let str = h.to_str().ok()?; + ForkName::from_str(str).ok() + }) + .unwrap_or_else(|| { let slot = signed_blinded_block.slot().as_u64(); - let fork = state.config.chain.fork_by_slot(slot); - // safe because ForkName is visible ASCII chars - HeaderValue::from_str(&fork.to_string()).unwrap() + state.config.chain.fork_by_slot(slot) }); + // safe because ForkName is visible ASCII chars + let consensus_version = HeaderValue::from_str(&fork_name.to_string()).unwrap(); + // prepare headers let mut send_headers = HeaderMap::new(); send_headers.insert(HEADER_START_TIME_UNIX_MS, HeaderValue::from(utcnow_ms())); @@ -58,6 +67,7 @@ pub async fn submit_block( send_headers.clone(), state.pbs_config().timeout_get_payload_ms, api_version, + fork_name, ))); } @@ -76,6 +86,7 @@ async fn submit_block_with_timeout( headers: HeaderMap, timeout_ms: u64, api_version: &BuilderApiVersion, + fork_name: ForkName, ) -> Result, PbsError> { let url = relay.submit_block_url(*api_version)?; let mut remaining_timeout_ms = timeout_ms; @@ -92,6 +103,7 @@ async fn submit_block_with_timeout( remaining_timeout_ms, retry, api_version, + fork_name, ) .await { @@ -118,6 +130,7 @@ async fn submit_block_with_timeout( // submits blinded signed block and expects the execution payload + blobs bundle // back +#[allow(clippy::too_many_arguments)] async fn send_submit_block( url: Url, signed_blinded_block: &SignedBlindedBeaconBlock, @@ -126,6 +139,7 @@ async fn send_submit_block( timeout_ms: u64, retry: u32, api_version: &BuilderApiVersion, + fork_name: ForkName, ) -> Result, PbsError> { let start_request = Instant::now(); let res = match relay @@ -194,23 +208,36 @@ async fn send_submit_block( "received unblinded block" ); + let got_block_hash = block_response.data.execution_payload.block_hash().0; + // request has different type so cant be deserialized in the wrong version, // response has a "version" field - match (&signed_blinded_block.message(), &block_response.data.execution_payload) { - ( - BlindedBeaconBlock::Electra(blinded_block), - ExecutionPayload::Electra(execution_payload), - ) => validate_unblinded_block_electra( - blinded_block, - execution_payload, - &block_response.data.blobs_bundle, - ), + match &signed_blinded_block.message() { + BlindedBeaconBlock::Electra(blinded_block) => { + let expected_block_hash = + blinded_block.body.execution_payload.execution_payload_header.block_hash.0; + let expected_commitments = &blinded_block.body.blob_kzg_commitments; + + validate_unblinded_block( + expected_block_hash, + got_block_hash, + expected_commitments, + &block_response.data.blobs_bundle, + fork_name, + ) + } + + BlindedBeaconBlock::Fulu(blinded_block) => { + let expected_block_hash = + blinded_block.body.execution_payload.execution_payload_header.block_hash.0; + let expected_commitments = &blinded_block.body.blob_kzg_commitments; - (BlindedBeaconBlock::Fulu(blinded_block), ExecutionPayload::Fulu(execution_payload)) => { - validate_unblinded_block_fulu( - blinded_block, - execution_payload, + validate_unblinded_block( + expected_block_hash, + got_block_hash, + expected_commitments, &block_response.data.blobs_bundle, + fork_name, ) } @@ -220,15 +247,41 @@ async fn send_submit_block( Ok(Some(block_response)) } -fn validate_unblinded_block_electra( - signed_blinded_block: &BlindedBeaconBlockElectra, - execution_payload: &ExecutionPayloadElectra, +fn validate_unblinded_block( + expected_block_hash: B256, + got_block_hash: B256, + expected_commitments: &KzgCommitments, blobs_bundle: &BlobsBundle, + fork_name: ForkName, ) -> Result<(), PbsError> { - let expected_block_hash = - signed_blinded_block.body.execution_payload.execution_payload_header.block_hash.0; - let got_block_hash = execution_payload.block_hash.0; + match fork_name { + ForkName::Base | + ForkName::Altair | + ForkName::Bellatrix | + ForkName::Capella | + ForkName::Deneb | + ForkName::Gloas => Err(PbsError::Validation(ValidationError::UnsupportedFork)), + ForkName::Electra => validate_unblinded_block_electra( + expected_block_hash, + got_block_hash, + expected_commitments, + blobs_bundle, + ), + ForkName::Fulu => validate_unblinded_block_fulu( + expected_block_hash, + got_block_hash, + expected_commitments, + blobs_bundle, + ), + } +} +fn validate_unblinded_block_electra( + expected_block_hash: B256, + got_block_hash: B256, + expected_commitments: &KzgCommitments, + blobs_bundle: &BlobsBundle, +) -> Result<(), PbsError> { if expected_block_hash != got_block_hash { return Err(PbsError::Validation(ValidationError::BlockHashMismatch { expected: expected_block_hash, @@ -236,7 +289,6 @@ fn validate_unblinded_block_electra( })); } - let expected_commitments = &signed_blinded_block.body.blob_kzg_commitments; if expected_commitments.len() != blobs_bundle.blobs.len() || expected_commitments.len() != blobs_bundle.commitments.len() || expected_commitments.len() != blobs_bundle.proofs.len() @@ -264,14 +316,11 @@ fn validate_unblinded_block_electra( } fn validate_unblinded_block_fulu( - signed_blinded_block: &BlindedBeaconBlockFulu, - execution_payload: &ExecutionPayloadFulu, + expected_block_hash: B256, + got_block_hash: B256, + expected_commitments: &KzgCommitments, blobs_bundle: &BlobsBundle, ) -> Result<(), PbsError> { - let expected_block_hash = - signed_blinded_block.body.execution_payload.execution_payload_header.block_hash.0; - let got_block_hash = execution_payload.block_hash.0; - if expected_block_hash != got_block_hash { return Err(PbsError::Validation(ValidationError::BlockHashMismatch { expected: expected_block_hash, @@ -279,7 +328,6 @@ fn validate_unblinded_block_fulu( })); } - let expected_commitments = &signed_blinded_block.body.blob_kzg_commitments; if expected_commitments.len() != blobs_bundle.blobs.len() || expected_commitments.len() != blobs_bundle.commitments.len() || expected_commitments.len() * CELLS_PER_EXT_BLOB != blobs_bundle.proofs.len() From dc6ae940797d69037cacbae5e61fcf103f43d5e3 Mon Sep 17 00:00:00 2001 From: eltitanb Date: Wed, 1 Oct 2025 19:47:20 +0100 Subject: [PATCH 8/9] fix tests --- config.example.toml | 2 +- tests/data/configs/pbs.happy.toml | 22 +++++++++++----------- tests/tests/config.rs | 4 ---- 3 files changed, 12 insertions(+), 16 deletions(-) diff --git a/config.example.toml b/config.example.toml index 5936d2d2..ad0c5340 100644 --- a/config.example.toml +++ b/config.example.toml @@ -54,7 +54,7 @@ late_in_slot_time_ms = 2000 extra_validation_enabled = false # Execution Layer RPC url to use for extra validation # OPTIONAL -rpc_url = "https://ethereum-holesky-rpc.publicnode.com" +# rpc_url = "https://ethereum-holesky-rpc.publicnode.com" # Timeout for any HTTP requests sent from the PBS module to other services, in seconds # OPTIONAL, DEFAULT: 10 http_timeout_seconds = 10 diff --git a/tests/data/configs/pbs.happy.toml b/tests/data/configs/pbs.happy.toml index 54c57de6..d77af2b6 100644 --- a/tests/data/configs/pbs.happy.toml +++ b/tests/data/configs/pbs.happy.toml @@ -2,24 +2,24 @@ chain = "Holesky" [pbs] docker_image = "ghcr.io/commit-boost/pbs:latest" -with_signer = false +extra_validation_enabled = false host = "127.0.0.1" +late_in_slot_time_ms = 2000 +min_bid_eth = 0.5 port = 18550 relay_check = true -wait_all_registrations = true +skip_sigverify = false timeout_get_header_ms = 950 timeout_get_payload_ms = 4000 timeout_register_validator_ms = 3000 -skip_sigverify = false -min_bid_eth = 0.5 -late_in_slot_time_ms = 2000 -extra_validation_enabled = false -rpc_url = "https://ethereum-holesky-rpc.publicnode.com" +wait_all_registrations = true +with_signer = false + [[relays]] -id = "example-relay" -url = "http://0xa1cec75a3f0661e99299274182938151e8433c61a19222347ea1313d839229cb4ce4e3e5aa2bdeb71c8fcf1b084963c2@abc.xyz" -headers = { X-MyCustomHeader = "MyCustomHeader" } enable_timing_games = false -target_first_request_ms = 200 frequency_get_header_ms = 300 +headers = { X-MyCustomHeader = "MyCustomHeader" } +id = "example-relay" +target_first_request_ms = 200 +url = "http://0xa1cec75a3f0661e99299274182938151e8433c61a19222347ea1313d839229cb4ce4e3e5aa2bdeb71c8fcf1b084963c2@abc.xyz" diff --git a/tests/tests/config.rs b/tests/tests/config.rs index 2cf9f92d..bffefcbc 100644 --- a/tests/tests/config.rs +++ b/tests/tests/config.rs @@ -55,10 +55,6 @@ async fn test_load_pbs_happy() -> Result<()> { assert_eq!(config.pbs.pbs_config.min_bid_wei, U256::from((0.5 * WEI_PER_ETH as f64) as u64)); assert_eq!(config.pbs.pbs_config.late_in_slot_time_ms, 2000); assert!(!config.pbs.pbs_config.extra_validation_enabled); - assert_eq!( - config.pbs.pbs_config.rpc_url, - Some("https://ethereum-holesky-rpc.publicnode.com".parse::().unwrap()) - ); // Relay specific settings let relay = &config.relays[0]; From d140c790f12b211d76e84629153bdc062dc3553e Mon Sep 17 00:00:00 2001 From: eltitanb Date: Wed, 1 Oct 2025 20:44:41 +0100 Subject: [PATCH 9/9] typo --- crates/common/src/pbs/types/mod.rs | 4 ++-- crates/pbs/src/routes/submit_block.rs | 2 +- tests/src/mock_relay.rs | 2 +- tests/tests/pbs_post_blinded_blocks.rs | 2 +- 4 files changed, 5 insertions(+), 5 deletions(-) diff --git a/crates/common/src/pbs/types/mod.rs b/crates/common/src/pbs/types/mod.rs index 93364948..8ad87c08 100644 --- a/crates/common/src/pbs/types/mod.rs +++ b/crates/common/src/pbs/types/mod.rs @@ -79,13 +79,13 @@ impl GetHeaderInfo for GetHeaderResponse { } } -pub trait GetPyloadInfo { +pub trait GetPayloadInfo { fn block_hash(&self) -> B256; fn block_number(&self) -> u64; fn parent_hash(&self) -> B256; } -impl GetPyloadInfo for SignedBlindedBeaconBlock { +impl GetPayloadInfo for SignedBlindedBeaconBlock { fn block_hash(&self) -> B256 { // Block hash is only missing for Base and Altair forks self.message().body().execution_payload().map(|r| r.block_hash().0).unwrap_or_default() diff --git a/crates/pbs/src/routes/submit_block.rs b/crates/pbs/src/routes/submit_block.rs index 577fc887..b3e98553 100644 --- a/crates/pbs/src/routes/submit_block.rs +++ b/crates/pbs/src/routes/submit_block.rs @@ -1,6 +1,6 @@ use axum::{Json, extract::State, http::HeaderMap, response::IntoResponse}; use cb_common::{ - pbs::{BuilderApiVersion, GetPyloadInfo, SignedBlindedBeaconBlock}, + pbs::{BuilderApiVersion, GetPayloadInfo, SignedBlindedBeaconBlock}, utils::{get_user_agent, timestamp_of_slot_start_millis, utcnow_ms}, }; use reqwest::StatusCode; diff --git a/tests/src/mock_relay.rs b/tests/src/mock_relay.rs index 91001c46..6f004c97 100644 --- a/tests/src/mock_relay.rs +++ b/tests/src/mock_relay.rs @@ -18,7 +18,7 @@ use cb_common::{ pbs::{ BUILDER_V1_API_PATH, BUILDER_V2_API_PATH, BlobsBundle, BuilderBid, BuilderBidElectra, ExecutionPayloadElectra, ExecutionPayloadHeaderElectra, ExecutionRequests, ForkName, - GET_HEADER_PATH, GET_STATUS_PATH, GetHeaderParams, GetHeaderResponse, GetPyloadInfo, + GET_HEADER_PATH, GET_STATUS_PATH, GetHeaderParams, GetHeaderResponse, GetPayloadInfo, PayloadAndBlobs, REGISTER_VALIDATOR_PATH, SUBMIT_BLOCK_PATH, SignedBlindedBeaconBlock, SignedBuilderBid, SubmitBlindedBlockResponse, }, diff --git a/tests/tests/pbs_post_blinded_blocks.rs b/tests/tests/pbs_post_blinded_blocks.rs index fc2a8fa6..37e9612c 100644 --- a/tests/tests/pbs_post_blinded_blocks.rs +++ b/tests/tests/pbs_post_blinded_blocks.rs @@ -1,7 +1,7 @@ use std::{sync::Arc, time::Duration}; use cb_common::{ - pbs::{BuilderApiVersion, GetPyloadInfo, SubmitBlindedBlockResponse}, + pbs::{BuilderApiVersion, GetPayloadInfo, SubmitBlindedBlockResponse}, signer::random_secret, types::Chain, };