From fb7dddb99d50257955dd80ff8f54a38130dc2ee3 Mon Sep 17 00:00:00 2001 From: Joe Clapis Date: Wed, 30 Jul 2025 23:09:47 -0400 Subject: [PATCH 1/3] Started implementing blinded block v2 support --- crates/cli/src/docker_init.rs | 4 +- crates/common/src/pbs/builder.rs | 30 +++++++++ crates/common/src/pbs/constants.rs | 3 +- crates/common/src/pbs/event.rs | 6 +- crates/common/src/pbs/mod.rs | 2 + crates/common/src/pbs/relay.rs | 25 +++++--- crates/common/src/pbs/types/beacon_block.rs | 6 +- .../common/src/pbs/types/execution_payload.rs | 2 +- crates/common/src/pbs/types/get_header.rs | 4 +- crates/pbs/src/api.rs | 9 ++- crates/pbs/src/mev_boost/submit_block.rs | 29 ++++++--- crates/pbs/src/routes/mod.rs | 2 +- crates/pbs/src/routes/router.rs | 21 ++++-- crates/pbs/src/routes/submit_block.rs | 62 ++++++++++++++++-- crates/pbs/src/service.rs | 4 +- tests/src/mock_relay.rs | 22 +++++-- tests/src/mock_validator.rs | 21 +++++- tests/tests/payloads.rs | 18 ++---- tests/tests/pbs_get_header.rs | 4 +- tests/tests/pbs_get_status.rs | 4 +- tests/tests/pbs_mux.rs | 13 ++-- tests/tests/pbs_post_blinded_blocks.rs | 64 ++++++++++++------- tests/tests/pbs_post_validators.rs | 8 +-- 23 files changed, 257 insertions(+), 106 deletions(-) create mode 100644 crates/common/src/pbs/builder.rs diff --git a/crates/cli/src/docker_init.rs b/crates/cli/src/docker_init.rs index cc307f85..f0f322fc 100644 --- a/crates/cli/src/docker_init.rs +++ b/crates/cli/src/docker_init.rs @@ -17,7 +17,7 @@ use cb_common::{ SIGNER_DIR_SECRETS_ENV, SIGNER_ENDPOINT_ENV, SIGNER_KEYS_ENV, SIGNER_MODULE_NAME, SIGNER_URL_ENV, }, - pbs::{BUILDER_API_PATH, GET_STATUS_PATH}, + pbs::{BUILDER_V1_API_PATH, GET_STATUS_PATH}, signer::{ProxyStore, SignerLoader, DEFAULT_SIGNER_PORT}, types::ModuleId, utils::random_jwt_secret, @@ -308,7 +308,7 @@ pub async fn handle_docker_init(config_path: PathBuf, output_dir: PathBuf) -> Re healthcheck: Some(Healthcheck { test: Some(HealthcheckTest::Single(format!( "curl -f http://localhost:{}{}{}", - cb_config.pbs.pbs_config.port, BUILDER_API_PATH, GET_STATUS_PATH + cb_config.pbs.pbs_config.port, BUILDER_V1_API_PATH, GET_STATUS_PATH ))), interval: Some("30s".into()), timeout: Some("5s".into()), diff --git a/crates/common/src/pbs/builder.rs b/crates/common/src/pbs/builder.rs new file mode 100644 index 00000000..a207a889 --- /dev/null +++ b/crates/common/src/pbs/builder.rs @@ -0,0 +1,30 @@ +use std::fmt::{Display, Formatter, Result}; + +use serde::{Deserialize, Serialize}; + +use crate::pbs::{BUILDER_V1_API_PATH, BUILDER_V2_API_PATH}; + +// Version of the builder API for various routes +#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)] +#[serde(rename_all = "lowercase")] +pub enum BuilderApiVersion { + V1 = 1, + V2, +} +impl BuilderApiVersion { + pub const fn path(&self) -> &'static str { + match self { + BuilderApiVersion::V1 => BUILDER_V1_API_PATH, + BuilderApiVersion::V2 => BUILDER_V2_API_PATH, + } + } +} +impl Display for BuilderApiVersion { + fn fmt(&self, f: &mut Formatter<'_>) -> Result { + let s = match self { + BuilderApiVersion::V1 => "v1", + BuilderApiVersion::V2 => "v2", + }; + write!(f, "{}", s) + } +} diff --git a/crates/common/src/pbs/constants.rs b/crates/common/src/pbs/constants.rs index 314915ce..d3b060d9 100644 --- a/crates/common/src/pbs/constants.rs +++ b/crates/common/src/pbs/constants.rs @@ -1,6 +1,7 @@ use crate::constants::COMMIT_BOOST_VERSION; -pub const BUILDER_API_PATH: &str = "/eth/v1/builder"; +pub const BUILDER_V1_API_PATH: &str = "/eth/v1/builder"; +pub const BUILDER_V2_API_PATH: &str = "/eth/v2/builder"; pub const GET_HEADER_PATH: &str = "/header/{slot}/{parent_hash}/{pubkey}"; pub const GET_STATUS_PATH: &str = "/status"; diff --git a/crates/common/src/pbs/event.rs b/crates/common/src/pbs/event.rs index 98276d14..e25beb03 100644 --- a/crates/common/src/pbs/event.rs +++ b/crates/common/src/pbs/event.rs @@ -20,7 +20,7 @@ use super::{ }; use crate::{ config::{load_optional_env_var, BUILDER_URLS_ENV, HTTP_TIMEOUT_SECONDS_DEFAULT}, - pbs::BUILDER_EVENTS_PATH, + pbs::{BuilderApiVersion, BUILDER_EVENTS_PATH}, }; #[derive(Debug, Clone, Serialize, Deserialize)] @@ -29,8 +29,8 @@ pub enum BuilderEvent { GetHeaderResponse(Box>), GetStatusEvent, GetStatusResponse, - SubmitBlockRequest(Box), - SubmitBlockResponse(Box), + SubmitBlockRequest(Box, BuilderApiVersion), + SubmitBlockResponse(Box, BuilderApiVersion), MissedPayload { /// Hash for the block for which no payload was received block_hash: B256, diff --git a/crates/common/src/pbs/mod.rs b/crates/common/src/pbs/mod.rs index 05f4f77b..53baced4 100644 --- a/crates/common/src/pbs/mod.rs +++ b/crates/common/src/pbs/mod.rs @@ -1,9 +1,11 @@ +mod builder; mod constants; pub mod error; mod event; mod relay; mod types; +pub use builder::*; pub use constants::*; pub use event::*; pub use relay::*; diff --git a/crates/common/src/pbs/relay.rs b/crates/common/src/pbs/relay.rs index 1169175a..6f582a13 100644 --- a/crates/common/src/pbs/relay.rs +++ b/crates/common/src/pbs/relay.rs @@ -10,11 +10,11 @@ use serde::{Deserialize, Serialize}; use url::Url; use super::{ - constants::{BUILDER_API_PATH, GET_STATUS_PATH, REGISTER_VALIDATOR_PATH, SUBMIT_BLOCK_PATH}, + constants::{GET_STATUS_PATH, REGISTER_VALIDATOR_PATH, SUBMIT_BLOCK_PATH}, error::PbsError, HEADER_VERSION_KEY, HEADER_VERSION_VALUE, }; -use crate::{config::RelayConfig, DEFAULT_REQUEST_TIMEOUT}; +use crate::{config::RelayConfig, pbs::BuilderApiVersion, DEFAULT_REQUEST_TIMEOUT}; /// A parsed entry of the relay url in the format: scheme://pubkey@host #[derive(Debug, Clone)] @@ -101,8 +101,12 @@ impl RelayClient { Ok(url) } - pub fn builder_api_url(&self, path: &str) -> Result { - self.get_url(&format!("{BUILDER_API_PATH}{path}")) + pub fn builder_api_url( + &self, + path: &str, + api_version: BuilderApiVersion, + ) -> Result { + self.get_url(&format!("{}{path}", api_version.path())) } pub fn get_header_url( @@ -111,19 +115,22 @@ impl RelayClient { parent_hash: B256, validator_pubkey: BlsPublicKey, ) -> Result { - self.builder_api_url(&format!("/header/{slot}/{parent_hash}/{validator_pubkey}")) + self.builder_api_url( + &format!("/header/{slot}/{parent_hash}/{validator_pubkey}"), + BuilderApiVersion::V1, + ) } pub fn get_status_url(&self) -> Result { - self.builder_api_url(GET_STATUS_PATH) + self.builder_api_url(GET_STATUS_PATH, BuilderApiVersion::V1) } pub fn register_validator_url(&self) -> Result { - self.builder_api_url(REGISTER_VALIDATOR_PATH) + self.builder_api_url(REGISTER_VALIDATOR_PATH, BuilderApiVersion::V1) } - pub fn submit_block_url(&self) -> Result { - self.builder_api_url(SUBMIT_BLOCK_PATH) + pub fn submit_block_url(&self, api_version: BuilderApiVersion) -> Result { + self.builder_api_url(SUBMIT_BLOCK_PATH, api_version) } } diff --git a/crates/common/src/pbs/types/beacon_block.rs b/crates/common/src/pbs/types/beacon_block.rs index f377123a..485876e9 100644 --- a/crates/common/src/pbs/types/beacon_block.rs +++ b/crates/common/src/pbs/types/beacon_block.rs @@ -99,7 +99,7 @@ mod tests { // 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); + let block = test_encode_decode::(data); assert!(matches!(block.message, BlindedBeaconBlock::Electra(_))); } @@ -166,7 +166,7 @@ mod tests { // 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); + 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"); @@ -181,7 +181,7 @@ mod tests { // 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 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(); diff --git a/crates/common/src/pbs/types/execution_payload.rs b/crates/common/src/pbs/types/execution_payload.rs index f851e8da..fcf4cdda 100644 --- a/crates/common/src/pbs/types/execution_payload.rs +++ b/crates/common/src/pbs/types/execution_payload.rs @@ -129,7 +129,7 @@ mod tests { "excess_blob_gas": "95158272" }"#; - let parsed = test_encode_decode::>(&data); + let parsed = test_encode_decode::>(data); assert_eq!( parsed.parent_hash, diff --git a/crates/common/src/pbs/types/get_header.rs b/crates/common/src/pbs/types/get_header.rs index 76cde408..18d5361f 100644 --- a/crates/common/src/pbs/types/get_header.rs +++ b/crates/common/src/pbs/types/get_header.rs @@ -166,7 +166,7 @@ mod tests { } }"#; - let parsed = test_encode_decode::(&data); + let parsed = test_encode_decode::(data); let VersionedResponse::Electra(parsed) = parsed; assert_eq!(parsed.message.value, U256::from(1)); @@ -187,7 +187,7 @@ mod tests { let data_json = include_str!("testdata/get-header-response.json"); let block_json = test_encode_decode::< SignedExecutionPayloadHeader, - >(&data_json); + >(data_json); let data_ssz = include_bytes!("testdata/get-header-response.ssz"); let data_ssz = alloy::primitives::hex::decode(data_ssz).unwrap(); diff --git a/crates/pbs/src/api.rs b/crates/pbs/src/api.rs index 8a76a423..3598e340 100644 --- a/crates/pbs/src/api.rs +++ b/crates/pbs/src/api.rs @@ -2,7 +2,8 @@ use alloy::rpc::types::beacon::relay::ValidatorRegistration; use async_trait::async_trait; use axum::{http::HeaderMap, Router}; use cb_common::pbs::{ - GetHeaderParams, GetHeaderResponse, SignedBlindedBeaconBlock, SubmitBlindedBlockResponse, + BuilderApiVersion, GetHeaderParams, GetHeaderResponse, SignedBlindedBeaconBlock, + SubmitBlindedBlockResponse, }; use crate::{ @@ -31,13 +32,15 @@ pub trait BuilderApi: 'static { mev_boost::get_status(req_headers, state).await } - /// https://ethereum.github.io/builder-specs/#/Builder/submitBlindedBlock + /// https://ethereum.github.io/builder-specs/#/Builder/submitBlindedBlock and + /// https://ethereum.github.io/builder-specs/#/Builder/submitBlindedBlockV2 async fn submit_block( signed_blinded_block: SignedBlindedBeaconBlock, req_headers: HeaderMap, state: PbsState, + api_version: &BuilderApiVersion, ) -> eyre::Result { - mev_boost::submit_block(signed_blinded_block, req_headers, state).await + mev_boost::submit_block(signed_blinded_block, req_headers, state, api_version).await } /// https://ethereum.github.io/builder-specs/#/Builder/registerValidator diff --git a/crates/pbs/src/mev_boost/submit_block.rs b/crates/pbs/src/mev_boost/submit_block.rs index 1f8a9789..dc365097 100644 --- a/crates/pbs/src/mev_boost/submit_block.rs +++ b/crates/pbs/src/mev_boost/submit_block.rs @@ -4,8 +4,8 @@ use axum::http::{HeaderMap, HeaderValue}; use cb_common::{ pbs::{ error::{PbsError, ValidationError}, - BlindedBeaconBlock, BlindedBeaconBlockElectra, PayloadAndBlobsElectra, RelayClient, - SignedBlindedBeaconBlock, SubmitBlindedBlockResponse, VersionedResponse, + BlindedBeaconBlock, BlindedBeaconBlockElectra, BuilderApiVersion, PayloadAndBlobsElectra, + RelayClient, SignedBlindedBeaconBlock, SubmitBlindedBlockResponse, VersionedResponse, HEADER_START_TIME_UNIX_MS, }, utils::{get_user_agent_with_version, read_chunked_body_with_max, utcnow_ms}, @@ -23,11 +23,14 @@ use crate::{ state::{BuilderApiState, PbsState}, }; -/// Implements https://ethereum.github.io/builder-specs/#/Builder/submitBlindedBlock +/// Implements https://ethereum.github.io/builder-specs/#/Builder/submitBlindedBlock and +/// https://ethereum.github.io/builder-specs/#/Builder/submitBlindedBlockV2. Use `api_version` to +/// distinguish between the two. pub async fn submit_block( signed_blinded_block: SignedBlindedBeaconBlock, req_headers: HeaderMap, state: PbsState, + api_version: &BuilderApiVersion, ) -> eyre::Result { // prepare headers let mut send_headers = HeaderMap::new(); @@ -42,6 +45,7 @@ pub async fn submit_block( relay, send_headers.clone(), state.pbs_config().timeout_get_payload_ms, + api_version, ))); } @@ -59,8 +63,9 @@ async fn submit_block_with_timeout( relay: &RelayClient, headers: HeaderMap, timeout_ms: u64, + api_version: &BuilderApiVersion, ) -> Result { - let url = relay.submit_block_url()?; + let url = relay.submit_block_url(api_version.clone())?; let mut remaining_timeout_ms = timeout_ms; let mut retry = 0; let mut backoff = Duration::from_millis(250); @@ -74,6 +79,7 @@ async fn submit_block_with_timeout( headers.clone(), remaining_timeout_ms, retry, + *api_version == BuilderApiVersion::V1, // only validate unblinded block for v1 ) .await { @@ -107,6 +113,7 @@ async fn send_submit_block( headers: HeaderMap, timeout_ms: u64, retry: u32, + validate_unblinded_block: bool, ) -> Result { let start_request = Instant::now(); let res = match relay @@ -180,12 +187,14 @@ async fn send_submit_block( // request has different type so cant be deserialized in the wrong version, // response has a "version" field - match (&signed_blinded_block.message, &block_response) { - ( - BlindedBeaconBlock::Electra(signed_blinded_block), - VersionedResponse::Electra(block_response), - ) => validate_unblinded_block_electra(signed_blinded_block, block_response), - }?; + if validate_unblinded_block { + match (&signed_blinded_block.message, &block_response) { + ( + BlindedBeaconBlock::Electra(signed_blinded_block), + VersionedResponse::Electra(block_response), + ) => validate_unblinded_block_electra(signed_blinded_block, block_response), + }?; + } Ok(block_response) } diff --git a/crates/pbs/src/routes/mod.rs b/crates/pbs/src/routes/mod.rs index 33a07500..84853d9e 100644 --- a/crates/pbs/src/routes/mod.rs +++ b/crates/pbs/src/routes/mod.rs @@ -9,4 +9,4 @@ use get_header::handle_get_header; use register_validator::handle_register_validator; pub use router::create_app_router; use status::handle_get_status; -use submit_block::handle_submit_block; +use submit_block::handle_submit_block_v1; diff --git a/crates/pbs/src/routes/router.rs b/crates/pbs/src/routes/router.rs index 37095f27..80b6156d 100644 --- a/crates/pbs/src/routes/router.rs +++ b/crates/pbs/src/routes/router.rs @@ -7,18 +7,19 @@ use axum::{ }; use axum_extra::headers::{ContentType, HeaderMapExt, UserAgent}; use cb_common::pbs::{ - BUILDER_API_PATH, GET_HEADER_PATH, GET_STATUS_PATH, REGISTER_VALIDATOR_PATH, RELOAD_PATH, - SUBMIT_BLOCK_PATH, + BUILDER_V1_API_PATH, BUILDER_V2_API_PATH, GET_HEADER_PATH, GET_STATUS_PATH, + REGISTER_VALIDATOR_PATH, RELOAD_PATH, SUBMIT_BLOCK_PATH, }; use tracing::trace; use uuid::Uuid; use super::{ - handle_get_header, handle_get_status, handle_register_validator, handle_submit_block, + handle_get_header, handle_get_status, handle_register_validator, handle_submit_block_v1, reload::handle_reload, }; use crate::{ api::BuilderApi, + routes::submit_block::handle_submit_block_v2, state::{BuilderApiState, PbsStateGuard}, MAX_SIZE_REGISTER_VALIDATOR_REQUEST, MAX_SIZE_SUBMIT_BLOCK_RESPONSE, }; @@ -27,7 +28,7 @@ pub fn create_app_router>(state: PbsStateGu // DefaultBodyLimit is 2Mib by default, so we only increase it for a few routes // thay may need more - let builder_routes = Router::new() + let v1_builder_routes = Router::new() .route(GET_HEADER_PATH, get(handle_get_header::)) .route(GET_STATUS_PATH, get(handle_get_status::)) .route( @@ -37,11 +38,19 @@ pub fn create_app_router>(state: PbsStateGu ) .route( SUBMIT_BLOCK_PATH, - post(handle_submit_block::) + post(handle_submit_block_v1::) .route_layer(DefaultBodyLimit::max(MAX_SIZE_SUBMIT_BLOCK_RESPONSE)), ); // header is smaller than the response but err on the safe side + let v2_builder_routes = Router::new().route( + SUBMIT_BLOCK_PATH, + post(handle_submit_block_v2::) + .route_layer(DefaultBodyLimit::max(MAX_SIZE_SUBMIT_BLOCK_RESPONSE)), + ); + let v1_builder_router = Router::new().nest(BUILDER_V1_API_PATH, v1_builder_routes); + let v2_builder_router = Router::new().nest(BUILDER_V2_API_PATH, v2_builder_routes); let reload_router = Router::new().route(RELOAD_PATH, post(handle_reload::)); - let builder_api = Router::new().nest(BUILDER_API_PATH, builder_routes).merge(reload_router); + let builder_api = + Router::new().merge(v1_builder_router).merge(v2_builder_router).merge(reload_router); let app = if let Some(extra_routes) = A::extra_routes() { builder_api.merge(extra_routes) diff --git a/crates/pbs/src/routes/submit_block.rs b/crates/pbs/src/routes/submit_block.rs index 0124a826..ba789bbe 100644 --- a/crates/pbs/src/routes/submit_block.rs +++ b/crates/pbs/src/routes/submit_block.rs @@ -1,6 +1,6 @@ use axum::{extract::State, http::HeaderMap, response::IntoResponse, Json}; use cb_common::{ - pbs::{BuilderEvent, SignedBlindedBeaconBlock}, + pbs::{BuilderApiVersion, BuilderEvent, SignedBlindedBeaconBlock}, utils::{get_user_agent, timestamp_of_slot_start_millis, utcnow_ms}, }; use reqwest::StatusCode; @@ -14,11 +14,41 @@ use crate::{ state::{BuilderApiState, PbsStateGuard}, }; -pub async fn handle_submit_block>( +pub async fn handle_submit_block_v1>( + state: State>, + req_headers: HeaderMap, + signed_blinded_block: Json, +) -> Result { + handle_submit_block_impl::( + state, + req_headers, + signed_blinded_block, + BuilderApiVersion::V1, + ) + .await +} + +pub async fn handle_submit_block_v2>( + state: State>, + req_headers: HeaderMap, + signed_blinded_block: Json, +) -> Result { + handle_submit_block_impl::( + state, + req_headers, + signed_blinded_block, + BuilderApiVersion::V2, + ) + .await +} + +async fn handle_submit_block_impl>( State(state): State>, req_headers: HeaderMap, Json(signed_blinded_block): Json, + api_version: BuilderApiVersion, ) -> Result { + tracing::Span::current().record("block_api_version", api_version.to_string()); tracing::Span::current().record("slot", signed_blinded_block.slot()); tracing::Span::current() .record("block_hash", tracing::field::debug(signed_blinded_block.block_hash())); @@ -28,7 +58,10 @@ pub async fn handle_submit_block>( let state = state.read().clone(); - state.publish_event(BuilderEvent::SubmitBlockRequest(Box::new(signed_blinded_block.clone()))); + state.publish_event(BuilderEvent::SubmitBlockRequest( + Box::new(signed_blinded_block.clone()), + api_version.clone(), + )); let now = utcnow_ms(); let slot = signed_blinded_block.slot(); @@ -38,14 +71,29 @@ pub async fn handle_submit_block>( info!(ua, ms_into_slot = now.saturating_sub(slot_start_ms), "new request"); - match A::submit_block(signed_blinded_block, req_headers, state.clone()).await { + match A::submit_block(signed_blinded_block, req_headers, state.clone(), &api_version).await { Ok(res) => { trace!(?res); - state.publish_event(BuilderEvent::SubmitBlockResponse(Box::new(res.clone()))); + state.publish_event(BuilderEvent::SubmitBlockResponse( + Box::new(res.clone()), + api_version.clone(), + )); info!("received unblinded block"); - BEACON_NODE_STATUS.with_label_values(&["200", SUBMIT_BLINDED_BLOCK_ENDPOINT_TAG]).inc(); - Ok((StatusCode::OK, Json(res).into_response())) + match api_version { + BuilderApiVersion::V1 => { + BEACON_NODE_STATUS + .with_label_values(&["200", SUBMIT_BLINDED_BLOCK_ENDPOINT_TAG]) + .inc(); + Ok((StatusCode::OK, Json(res).into_response())) + } + BuilderApiVersion::V2 => { + BEACON_NODE_STATUS + .with_label_values(&["202", SUBMIT_BLINDED_BLOCK_ENDPOINT_TAG]) + .inc(); + Ok((StatusCode::ACCEPTED, "".into_response())) + } + } } Err(err) => { diff --git a/crates/pbs/src/service.rs b/crates/pbs/src/service.rs index ce8162e4..730e229f 100644 --- a/crates/pbs/src/service.rs +++ b/crates/pbs/src/service.rs @@ -2,7 +2,7 @@ use std::time::Duration; use cb_common::{ constants::{COMMIT_BOOST_COMMIT, COMMIT_BOOST_VERSION}, - pbs::{BUILDER_API_PATH, GET_STATUS_PATH}, + pbs::{BUILDER_V1_API_PATH, GET_STATUS_PATH}, types::Chain, }; use cb_metrics::provider::MetricsProvider; @@ -40,7 +40,7 @@ impl PbsService { // wait for the server to start tokio::time::sleep(Duration::from_millis(250)).await; let local_url = - Url::parse(&format!("http://{}{}{}", addr, BUILDER_API_PATH, GET_STATUS_PATH))?; + Url::parse(&format!("http://{}{}{}", addr, BUILDER_V1_API_PATH, GET_STATUS_PATH))?; let status = reqwest::get(local_url).await?; if !status.status().is_success() { diff --git a/tests/src/mock_relay.rs b/tests/src/mock_relay.rs index a91a70c6..04ebfc24 100644 --- a/tests/src/mock_relay.rs +++ b/tests/src/mock_relay.rs @@ -17,8 +17,9 @@ use axum::{ use cb_common::{ pbs::{ ExecutionPayloadHeaderMessageElectra, GetHeaderParams, GetHeaderResponse, - SignedExecutionPayloadHeader, SubmitBlindedBlockResponse, BUILDER_API_PATH, - GET_HEADER_PATH, GET_STATUS_PATH, REGISTER_VALIDATOR_PATH, SUBMIT_BLOCK_PATH, + SignedExecutionPayloadHeader, SubmitBlindedBlockResponse, BUILDER_V1_API_PATH, + BUILDER_V2_API_PATH, GET_HEADER_PATH, GET_STATUS_PATH, REGISTER_VALIDATOR_PATH, + SUBMIT_BLOCK_PATH, }, signature::sign_builder_root, signer::BlsSecretKey, @@ -92,14 +93,17 @@ impl MockRelayState { } pub fn mock_relay_app_router(state: Arc) -> Router { - let builder_routes = Router::new() + let v1_builder_routes = Router::new() .route(GET_HEADER_PATH, get(handle_get_header)) .route(GET_STATUS_PATH, get(handle_get_status)) .route(REGISTER_VALIDATOR_PATH, post(handle_register_validator)) - .route(SUBMIT_BLOCK_PATH, post(handle_submit_block)) - .with_state(state); + .route(SUBMIT_BLOCK_PATH, post(handle_submit_block_v1)); - Router::new().nest(BUILDER_API_PATH, builder_routes) + let v2_builder_routes = Router::new().route(SUBMIT_BLOCK_PATH, post(handle_submit_block_v2)); + + let builder_router_v1 = Router::new().nest(BUILDER_V1_API_PATH, v1_builder_routes); + let builder_router_v2 = Router::new().nest(BUILDER_V2_API_PATH, v2_builder_routes); + Router::new().merge(builder_router_v1).merge(builder_router_v2).with_state(state) } async fn handle_get_header( @@ -143,7 +147,7 @@ async fn handle_register_validator( StatusCode::OK.into_response() } -async fn handle_submit_block(State(state): State>) -> Response { +async fn handle_submit_block_v1(State(state): State>) -> Response { state.received_submit_block.fetch_add(1, Ordering::Relaxed); if state.large_body() { (StatusCode::OK, Json(vec![1u8; 1 + MAX_SIZE_SUBMIT_BLOCK_RESPONSE])).into_response() @@ -152,3 +156,7 @@ async fn handle_submit_block(State(state): State>) -> Respon (StatusCode::OK, Json(response)).into_response() } } +async fn handle_submit_block_v2(State(state): State>) -> Response { + state.received_submit_block.fetch_add(1, Ordering::Relaxed); + (StatusCode::ACCEPTED, "").into_response() +} diff --git a/tests/src/mock_validator.rs b/tests/src/mock_validator.rs index 7d31f770..ee860189 100644 --- a/tests/src/mock_validator.rs +++ b/tests/src/mock_validator.rs @@ -2,7 +2,7 @@ use alloy::{ primitives::B256, rpc::types::beacon::{relay::ValidatorRegistration, BlsPublicKey}, }; -use cb_common::pbs::{RelayClient, SignedBlindedBeaconBlock}; +use cb_common::pbs::{BuilderApiVersion, RelayClient, SignedBlindedBeaconBlock}; use reqwest::Response; use crate::utils::generate_mock_relay; @@ -39,11 +39,26 @@ impl MockValidator { Ok(self.comm_boost.client.post(url).json(®istrations).send().await?) } - pub async fn do_submit_block( + pub async fn do_submit_block_v1( &self, signed_blinded_block: Option, ) -> eyre::Result { - let url = self.comm_boost.submit_block_url().unwrap(); + self.do_submit_block_impl(signed_blinded_block, BuilderApiVersion::V1).await + } + + pub async fn do_submit_block_v2( + &self, + signed_blinded_block: Option, + ) -> eyre::Result { + self.do_submit_block_impl(signed_blinded_block, BuilderApiVersion::V2).await + } + + async fn do_submit_block_impl( + &self, + signed_blinded_block: Option, + api_version: BuilderApiVersion, + ) -> eyre::Result { + let url = self.comm_boost.submit_block_url(api_version).unwrap(); Ok(self .comm_boost diff --git a/tests/tests/payloads.rs b/tests/tests/payloads.rs index a1bd5b52..c43df7ef 100644 --- a/tests/tests/payloads.rs +++ b/tests/tests/payloads.rs @@ -9,19 +9,19 @@ use serde_json::Value; #[test] fn test_registrations() { let data = include_str!("../data/registration_holesky.json"); - test_encode_decode::>(&data); + test_encode_decode::>(data); } #[test] fn test_signed_blinded_block() { let data = include_str!("../data/signed_blinded_block_holesky.json"); - test_encode_decode::(&data); + test_encode_decode::(data); } #[test] fn test_submit_block_response() { let data = include_str!("../data/submit_block_response_holesky.json"); - test_encode_decode::(&data); + test_encode_decode::(data); } // Unhappy path tests @@ -32,10 +32,8 @@ fn test_missing_registration_field(field_name: &str) -> String { // Remove specified field from the first validator's message if let Value::Array(arr) = &mut values { if let Some(first_validator) = arr.get_mut(0) { - if let Some(message) = first_validator.get_mut("message") { - if let Value::Object(msg_obj) = message { - msg_obj.remove(field_name); - } + if let Some(Value::Object(msg_obj)) = first_validator.get_mut("message") { + msg_obj.remove(field_name); } } } @@ -66,10 +64,8 @@ fn test_missing_signed_blinded_block_field(field_name: &str) -> String { let mut values: Value = serde_json::from_str(data).unwrap(); // Remove specified field from the message - if let Some(message) = values.get_mut("message") { - if let Value::Object(msg_obj) = message { - msg_obj.remove(field_name); - } + if let Some(Value::Object(msg_obj)) = values.get_mut("message") { + msg_obj.remove(field_name); } // This should fail since the field is required diff --git a/tests/tests/pbs_get_header.rs b/tests/tests/pbs_get_header.rs index 02cceb0a..10f30b6a 100644 --- a/tests/tests/pbs_get_header.rs +++ b/tests/tests/pbs_get_header.rs @@ -67,7 +67,7 @@ async fn test_get_header() -> Result<()> { async fn test_get_header_returns_204_if_relay_down() -> Result<()> { setup_test_env(); let signer = random_secret(); - let pubkey: BlsPublicKey = blst_pubkey_to_alloy(&signer.sk_to_pk()).into(); + let pubkey: BlsPublicKey = blst_pubkey_to_alloy(&signer.sk_to_pk()); let chain = Chain::Holesky; let pbs_port = 3300; @@ -101,7 +101,7 @@ async fn test_get_header_returns_204_if_relay_down() -> Result<()> { async fn test_get_header_returns_400_if_request_is_invalid() -> Result<()> { setup_test_env(); let signer = random_secret(); - let pubkey: BlsPublicKey = blst_pubkey_to_alloy(&signer.sk_to_pk()).into(); + let pubkey: BlsPublicKey = blst_pubkey_to_alloy(&signer.sk_to_pk()); let chain = Chain::Holesky; let pbs_port = 3400; diff --git a/tests/tests/pbs_get_status.rs b/tests/tests/pbs_get_status.rs index 0694b97a..3e913dc5 100644 --- a/tests/tests/pbs_get_status.rs +++ b/tests/tests/pbs_get_status.rs @@ -19,7 +19,7 @@ use tracing::info; async fn test_get_status() -> Result<()> { setup_test_env(); let signer = random_secret(); - let pubkey: BlsPublicKey = blst_pubkey_to_alloy(&signer.sk_to_pk()).into(); + let pubkey: BlsPublicKey = blst_pubkey_to_alloy(&signer.sk_to_pk()); let chain = Chain::Holesky; let pbs_port = 3500; @@ -55,7 +55,7 @@ async fn test_get_status() -> Result<()> { async fn test_get_status_returns_502_if_relay_down() -> Result<()> { setup_test_env(); let signer = random_secret(); - let pubkey: BlsPublicKey = blst_pubkey_to_alloy(&signer.sk_to_pk()).into(); + let pubkey: BlsPublicKey = blst_pubkey_to_alloy(&signer.sk_to_pk()); let chain = Chain::Holesky; let pbs_port = 3600; diff --git a/tests/tests/pbs_mux.rs b/tests/tests/pbs_mux.rs index a8f3ed1c..4d830e20 100644 --- a/tests/tests/pbs_mux.rs +++ b/tests/tests/pbs_mux.rs @@ -20,7 +20,7 @@ use tracing::info; async fn test_mux() -> Result<()> { setup_test_env(); let signer = random_secret(); - let pubkey: BlsPublicKey = blst_pubkey_to_alloy(&signer.sk_to_pk()).into(); + let pubkey: BlsPublicKey = blst_pubkey_to_alloy(&signer.sk_to_pk()); let chain = Chain::Holesky; let pbs_port = 3700; @@ -82,10 +82,15 @@ async fn test_mux() -> Result<()> { assert_eq!(mock_validator.do_register_validator().await?.status(), StatusCode::OK); assert_eq!(mock_state.received_register_validator(), 3); // default + 2 mux relays were used - // Submit block requests should go to all relays - info!("Sending submit block"); - assert_eq!(mock_validator.do_submit_block(None).await?.status(), StatusCode::OK); + // v1 Submit block requests should go to all relays + info!("Sending submit block v1"); + assert_eq!(mock_validator.do_submit_block_v1(None).await?.status(), StatusCode::OK); assert_eq!(mock_state.received_submit_block(), 3); // default + 2 mux relays were used + // v2 Submit block requests should go to all relays + info!("Sending submit block v2"); + assert_eq!(mock_validator.do_submit_block_v2(None).await?.status(), StatusCode::ACCEPTED); + assert_eq!(mock_state.received_submit_block(), 6); // default + 2 mux relays were used + Ok(()) } diff --git a/tests/tests/pbs_post_blinded_blocks.rs b/tests/tests/pbs_post_blinded_blocks.rs index 3ab378a4..9e91dfa9 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::{SignedBlindedBeaconBlock, SubmitBlindedBlockResponse}, + pbs::{BuilderApiVersion, SignedBlindedBeaconBlock, SubmitBlindedBlockResponse}, signer::{random_secret, BlsPublicKey}, types::Chain, utils::blst_pubkey_to_alloy, @@ -13,24 +13,40 @@ use cb_tests::{ utils::{generate_mock_relay, get_pbs_static_config, setup_test_env, to_pbs_config}, }; use eyre::Result; -use reqwest::StatusCode; +use reqwest::{Response, StatusCode}; use tracing::info; #[tokio::test] -async fn test_submit_block() -> Result<()> { +async fn test_submit_block_v1() -> Result<()> { + let res = submit_block_impl(3800, &BuilderApiVersion::V1).await?; + assert_eq!(res.status(), StatusCode::OK); + + let response_body = serde_json::from_slice::(&res.bytes().await?)?; + assert_eq!(response_body.block_hash(), SubmitBlindedBlockResponse::default().block_hash()); + Ok(()) +} + +#[tokio::test] +async fn test_submit_block_v2() -> Result<()> { + let res = submit_block_impl(3850, &BuilderApiVersion::V2).await?; + assert_eq!(res.status(), StatusCode::ACCEPTED); + assert_eq!(res.bytes().await?.len(), 0); + Ok(()) +} + +#[tokio::test] +async fn test_submit_block_too_large() -> Result<()> { setup_test_env(); let signer = random_secret(); - let pubkey: BlsPublicKey = blst_pubkey_to_alloy(&signer.sk_to_pk()).into(); + let pubkey: BlsPublicKey = blst_pubkey_to_alloy(&signer.sk_to_pk()); let chain = Chain::Holesky; - let pbs_port = 3800; + let pbs_port = 3900; - // Run a mock relay let relays = vec![generate_mock_relay(pbs_port + 1, pubkey)?]; - let mock_state = Arc::new(MockRelayState::new(chain, signer)); + let mock_state = Arc::new(MockRelayState::new(chain, signer).with_large_body()); tokio::spawn(start_mock_relay_service(mock_state.clone(), pbs_port + 1)); - // Run the PBS service let config = to_pbs_config(chain, get_pbs_static_config(pbs_port), relays); let state = PbsState::new(config); tokio::spawn(PbsService::run::<(), DefaultBuilderApi>(state)); @@ -40,29 +56,27 @@ async fn test_submit_block() -> Result<()> { let mock_validator = MockValidator::new(pbs_port)?; info!("Sending submit block"); - let res = mock_validator.do_submit_block(Some(SignedBlindedBeaconBlock::default())).await?; + let res = mock_validator.do_submit_block_v1(None).await; - assert_eq!(res.status(), StatusCode::OK); + // response size exceeds max size: max: 20971520 + assert_eq!(res.unwrap().status(), StatusCode::BAD_GATEWAY); assert_eq!(mock_state.received_submit_block(), 1); - - let response_body = serde_json::from_slice::(&res.bytes().await?)?; - assert_eq!(response_body.block_hash(), SubmitBlindedBlockResponse::default().block_hash()); Ok(()) } -#[tokio::test] -async fn test_submit_block_too_large() -> Result<()> { +async fn submit_block_impl(pbs_port: u16, api_version: &BuilderApiVersion) -> Result { setup_test_env(); let signer = random_secret(); - let pubkey: BlsPublicKey = blst_pubkey_to_alloy(&signer.sk_to_pk()).into(); + let pubkey: BlsPublicKey = blst_pubkey_to_alloy(&signer.sk_to_pk()); let chain = Chain::Holesky; - let pbs_port = 3900; + // Run a mock relay let relays = vec![generate_mock_relay(pbs_port + 1, pubkey)?]; - let mock_state = Arc::new(MockRelayState::new(chain, signer).with_large_body()); + let mock_state = Arc::new(MockRelayState::new(chain, signer)); tokio::spawn(start_mock_relay_service(mock_state.clone(), pbs_port + 1)); + // Run the PBS service let config = to_pbs_config(chain, get_pbs_static_config(pbs_port), relays); let state = PbsState::new(config); tokio::spawn(PbsService::run::<(), DefaultBuilderApi>(state)); @@ -72,10 +86,14 @@ async fn test_submit_block_too_large() -> Result<()> { let mock_validator = MockValidator::new(pbs_port)?; info!("Sending submit block"); - let res = mock_validator.do_submit_block(None).await; - - // response size exceeds max size: max: 20971520 - assert_eq!(res.unwrap().status(), StatusCode::BAD_GATEWAY); + let res = match api_version { + BuilderApiVersion::V1 => { + mock_validator.do_submit_block_v1(Some(SignedBlindedBeaconBlock::default())).await? + } + BuilderApiVersion::V2 => { + mock_validator.do_submit_block_v2(Some(SignedBlindedBeaconBlock::default())).await? + } + }; assert_eq!(mock_state.received_submit_block(), 1); - Ok(()) + Ok(res) } diff --git a/tests/tests/pbs_post_validators.rs b/tests/tests/pbs_post_validators.rs index 4c70ac01..f2480ac1 100644 --- a/tests/tests/pbs_post_validators.rs +++ b/tests/tests/pbs_post_validators.rs @@ -20,7 +20,7 @@ use tracing::info; async fn test_register_validators() -> Result<()> { setup_test_env(); let signer = random_secret(); - let pubkey: BlsPublicKey = blst_pubkey_to_alloy(&signer.sk_to_pk()).into(); + let pubkey: BlsPublicKey = blst_pubkey_to_alloy(&signer.sk_to_pk()); let chain = Chain::Holesky; let pbs_port = 4000; @@ -66,7 +66,7 @@ async fn test_register_validators() -> Result<()> { async fn test_register_validators_returns_422_if_request_is_malformed() -> Result<()> { setup_test_env(); let signer = random_secret(); - let pubkey: BlsPublicKey = blst_pubkey_to_alloy(&signer.sk_to_pk()).into(); + let pubkey: BlsPublicKey = blst_pubkey_to_alloy(&signer.sk_to_pk()); let chain = Chain::Holesky; let pbs_port = 4100; @@ -206,7 +206,7 @@ async fn test_register_validators_returns_422_if_request_is_malformed() -> Resul async fn test_register_validators_does_not_retry_on_429() -> Result<()> { setup_test_env(); let signer = random_secret(); - let pubkey: BlsPublicKey = blst_pubkey_to_alloy(&signer.sk_to_pk()).into(); + let pubkey: BlsPublicKey = blst_pubkey_to_alloy(&signer.sk_to_pk()); let chain = Chain::Holesky; let pbs_port = 4200; @@ -259,7 +259,7 @@ async fn test_register_validators_does_not_retry_on_429() -> Result<()> { async fn test_register_validators_retries_on_500() -> Result<()> { setup_test_env(); let signer = random_secret(); - let pubkey: BlsPublicKey = blst_pubkey_to_alloy(&signer.sk_to_pk()).into(); + let pubkey: BlsPublicKey = blst_pubkey_to_alloy(&signer.sk_to_pk()); let chain = Chain::Holesky; let pbs_port = 4300; From 2302b75d8cb86d61d50f68c0b51ea840c4c8a5ce Mon Sep 17 00:00:00 2001 From: Joe Clapis Date: Fri, 1 Aug 2025 01:38:19 -0400 Subject: [PATCH 2/3] Made unblinded block payloads optional for v2 support --- crates/common/src/pbs/event.rs | 3 +- crates/pbs/src/api.rs | 2 +- crates/pbs/src/mev_boost/submit_block.rs | 32 +++++++++--------- crates/pbs/src/routes/submit_block.rs | 42 ++++++++++++------------ 4 files changed, 41 insertions(+), 38 deletions(-) diff --git a/crates/common/src/pbs/event.rs b/crates/common/src/pbs/event.rs index e25beb03..653b5bea 100644 --- a/crates/common/src/pbs/event.rs +++ b/crates/common/src/pbs/event.rs @@ -30,7 +30,8 @@ pub enum BuilderEvent { GetStatusEvent, GetStatusResponse, SubmitBlockRequest(Box, BuilderApiVersion), - SubmitBlockResponse(Box, BuilderApiVersion), + SubmitBlockResponseV1(Box), + SubmitBlockResponseV2, MissedPayload { /// Hash for the block for which no payload was received block_hash: B256, diff --git a/crates/pbs/src/api.rs b/crates/pbs/src/api.rs index 3598e340..1f6e31d8 100644 --- a/crates/pbs/src/api.rs +++ b/crates/pbs/src/api.rs @@ -39,7 +39,7 @@ pub trait BuilderApi: 'static { req_headers: HeaderMap, state: PbsState, api_version: &BuilderApiVersion, - ) -> eyre::Result { + ) -> eyre::Result> { mev_boost::submit_block(signed_blinded_block, req_headers, state, api_version).await } diff --git a/crates/pbs/src/mev_boost/submit_block.rs b/crates/pbs/src/mev_boost/submit_block.rs index dc365097..94037e72 100644 --- a/crates/pbs/src/mev_boost/submit_block.rs +++ b/crates/pbs/src/mev_boost/submit_block.rs @@ -31,7 +31,7 @@ pub async fn submit_block( req_headers: HeaderMap, state: PbsState, api_version: &BuilderApiVersion, -) -> eyre::Result { +) -> eyre::Result> { // prepare headers let mut send_headers = HeaderMap::new(); send_headers.insert(HEADER_START_TIME_UNIX_MS, HeaderValue::from(utcnow_ms())); @@ -64,7 +64,7 @@ async fn submit_block_with_timeout( headers: HeaderMap, timeout_ms: u64, api_version: &BuilderApiVersion, -) -> Result { +) -> Result, PbsError> { let url = relay.submit_block_url(api_version.clone())?; let mut remaining_timeout_ms = timeout_ms; let mut retry = 0; @@ -79,7 +79,7 @@ async fn submit_block_with_timeout( headers.clone(), remaining_timeout_ms, retry, - *api_version == BuilderApiVersion::V1, // only validate unblinded block for v1 + api_version, ) .await { @@ -113,8 +113,8 @@ async fn send_submit_block( headers: HeaderMap, timeout_ms: u64, retry: u32, - validate_unblinded_block: bool, -) -> Result { + api_version: &BuilderApiVersion, +) -> Result, PbsError> { let start_request = Instant::now(); let res = match relay .client @@ -158,6 +158,10 @@ async fn send_submit_block( warn!(relay_id = relay.id.as_ref(), retry, %err, "failed to get payload (this might be ok if other relays have it)"); return Err(err); }; + if api_version != &BuilderApiVersion::V1 { + // v2 response is going to be empty, so just break here + return Ok(None); + } let block_response = match serde_json::from_slice::(&response_bytes) { @@ -187,16 +191,14 @@ async fn send_submit_block( // request has different type so cant be deserialized in the wrong version, // response has a "version" field - if validate_unblinded_block { - match (&signed_blinded_block.message, &block_response) { - ( - BlindedBeaconBlock::Electra(signed_blinded_block), - VersionedResponse::Electra(block_response), - ) => validate_unblinded_block_electra(signed_blinded_block, block_response), - }?; - } - - Ok(block_response) + match (&signed_blinded_block.message, &block_response) { + ( + BlindedBeaconBlock::Electra(signed_blinded_block), + VersionedResponse::Electra(block_response), + ) => validate_unblinded_block_electra(signed_blinded_block, block_response), + }?; + + Ok(Some(block_response)) } fn validate_unblinded_block_electra( diff --git a/crates/pbs/src/routes/submit_block.rs b/crates/pbs/src/routes/submit_block.rs index ba789bbe..b21046d1 100644 --- a/crates/pbs/src/routes/submit_block.rs +++ b/crates/pbs/src/routes/submit_block.rs @@ -72,29 +72,29 @@ async fn handle_submit_block_impl>( info!(ua, ms_into_slot = now.saturating_sub(slot_start_ms), "new request"); match A::submit_block(signed_blinded_block, req_headers, state.clone(), &api_version).await { - Ok(res) => { - trace!(?res); - state.publish_event(BuilderEvent::SubmitBlockResponse( - Box::new(res.clone()), - api_version.clone(), - )); - info!("received unblinded block"); + Ok(res) => match res { + Some(block_response) => { + trace!(?block_response); + state.publish_event(BuilderEvent::SubmitBlockResponseV1(Box::new( + block_response.clone(), + ))); + info!("received unblinded block (v1)"); - match api_version { - BuilderApiVersion::V1 => { - BEACON_NODE_STATUS - .with_label_values(&["200", SUBMIT_BLINDED_BLOCK_ENDPOINT_TAG]) - .inc(); - Ok((StatusCode::OK, Json(res).into_response())) - } - BuilderApiVersion::V2 => { - BEACON_NODE_STATUS - .with_label_values(&["202", SUBMIT_BLINDED_BLOCK_ENDPOINT_TAG]) - .inc(); - Ok((StatusCode::ACCEPTED, "".into_response())) - } + BEACON_NODE_STATUS + .with_label_values(&["200", SUBMIT_BLINDED_BLOCK_ENDPOINT_TAG]) + .inc(); + Ok((StatusCode::OK, Json(block_response).into_response())) } - } + None => { + state.publish_event(BuilderEvent::SubmitBlockResponseV2); + info!("received unblinded block (v2)"); + + BEACON_NODE_STATUS + .with_label_values(&["202", SUBMIT_BLINDED_BLOCK_ENDPOINT_TAG]) + .inc(); + Ok((StatusCode::ACCEPTED, "".into_response())) + } + }, Err(err) => { error!(%err, %block_hash, "CRITICAL: no payload received from relays. Check previous logs or use the Relay Data API"); From 855d6ca5d67476637f76a09927704c5a9c9034f5 Mon Sep 17 00:00:00 2001 From: Joe Clapis Date: Tue, 12 Aug 2025 12:49:34 -0400 Subject: [PATCH 3/3] Optimization based on feedback --- crates/common/src/pbs/builder.rs | 2 +- crates/common/src/signer/store.rs | 6 ++-- crates/common/src/utils.rs | 2 +- crates/pbs/src/mev_boost/submit_block.rs | 2 +- crates/pbs/src/routes/submit_block.rs | 3 +- crates/signer/src/manager/local.rs | 46 ++++++++---------------- 6 files changed, 21 insertions(+), 40 deletions(-) diff --git a/crates/common/src/pbs/builder.rs b/crates/common/src/pbs/builder.rs index a207a889..0656ac2d 100644 --- a/crates/common/src/pbs/builder.rs +++ b/crates/common/src/pbs/builder.rs @@ -5,7 +5,7 @@ use serde::{Deserialize, Serialize}; use crate::pbs::{BUILDER_V1_API_PATH, BUILDER_V2_API_PATH}; // Version of the builder API for various routes -#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)] +#[derive(Debug, Copy, Clone, Serialize, Deserialize, PartialEq, Eq)] #[serde(rename_all = "lowercase")] pub enum BuilderApiVersion { V1 = 1, diff --git a/crates/common/src/signer/store.rs b/crates/common/src/signer/store.rs index bd23c120..479a4016 100644 --- a/crates/common/src/signer/store.rs +++ b/crates/common/src/signer/store.rs @@ -542,12 +542,12 @@ mod test { .join(consensus_signer.pubkey().to_string()) .join("TEST_MODULE") .join("bls") - .join(format!("{}.json", proxy_signer.pubkey().to_string())); + .join(format!("{}.json", proxy_signer.pubkey())); let sig_path = keys_path .join(consensus_signer.pubkey().to_string()) .join("TEST_MODULE") .join("bls") - .join(format!("{}.sig", proxy_signer.pubkey().to_string())); + .join(format!("{}.sig", proxy_signer.pubkey())); let pass_path = secrets_path .join(consensus_signer.pubkey().to_string()) .join("TEST_MODULE") @@ -674,7 +674,7 @@ mod test { .join(consensus_signer.pubkey().to_string()) .join("TEST_MODULE") .join("bls") - .join(format!("{}.sig", proxy_signer.pubkey().to_string())) + .join(format!("{}.sig", proxy_signer.pubkey())) ) .unwrap() ) diff --git a/crates/common/src/utils.rs b/crates/common/src/utils.rs index ccaf8888..6d39465c 100644 --- a/crates/common/src/utils.rs +++ b/crates/common/src/utils.rs @@ -457,7 +457,7 @@ mod test { let jwt = create_jwt(&ModuleId("DA_COMMIT".to_string()), "secret").unwrap(); let module_id = decode_jwt(jwt.clone()).unwrap(); assert_eq!(module_id, ModuleId("DA_COMMIT".to_string())); - let response = validate_jwt(jwt, "secret".as_ref()); + let response = validate_jwt(jwt, "secret"); assert!(response.is_ok()); // Check expired JWT diff --git a/crates/pbs/src/mev_boost/submit_block.rs b/crates/pbs/src/mev_boost/submit_block.rs index 94037e72..ac633f2c 100644 --- a/crates/pbs/src/mev_boost/submit_block.rs +++ b/crates/pbs/src/mev_boost/submit_block.rs @@ -65,7 +65,7 @@ async fn submit_block_with_timeout( timeout_ms: u64, api_version: &BuilderApiVersion, ) -> Result, PbsError> { - let url = relay.submit_block_url(api_version.clone())?; + let url = relay.submit_block_url(*api_version)?; let mut remaining_timeout_ms = timeout_ms; let mut retry = 0; let mut backoff = Duration::from_millis(250); diff --git a/crates/pbs/src/routes/submit_block.rs b/crates/pbs/src/routes/submit_block.rs index b21046d1..10674c09 100644 --- a/crates/pbs/src/routes/submit_block.rs +++ b/crates/pbs/src/routes/submit_block.rs @@ -48,7 +48,6 @@ async fn handle_submit_block_impl>( Json(signed_blinded_block): Json, api_version: BuilderApiVersion, ) -> Result { - tracing::Span::current().record("block_api_version", api_version.to_string()); tracing::Span::current().record("slot", signed_blinded_block.slot()); tracing::Span::current() .record("block_hash", tracing::field::debug(signed_blinded_block.block_hash())); @@ -60,7 +59,7 @@ async fn handle_submit_block_impl>( state.publish_event(BuilderEvent::SubmitBlockRequest( Box::new(signed_blinded_block.clone()), - api_version.clone(), + api_version, )); let now = utcnow_ms(); diff --git a/crates/signer/src/manager/local.rs b/crates/signer/src/manager/local.rs index 6d9e35fe..a613df0a 100644 --- a/crates/signer/src/manager/local.rs +++ b/crates/signer/src/manager/local.rs @@ -298,10 +298,8 @@ mod tests { async fn test_proxy_key_is_valid_proxy_for_consensus_key() { let (mut signing_manager, consensus_pk) = init_signing_manager(); - let signed_delegation = signing_manager - .create_proxy_bls(MODULE_ID.clone(), consensus_pk.clone()) - .await - .unwrap(); + let signed_delegation = + signing_manager.create_proxy_bls(MODULE_ID.clone(), consensus_pk).await.unwrap(); let validation_result = signed_delegation.validate(CHAIN); @@ -321,10 +319,8 @@ mod tests { async fn test_tampered_proxy_key_is_invalid() { let (mut signing_manager, consensus_pk) = init_signing_manager(); - let mut signed_delegation = signing_manager - .create_proxy_bls(MODULE_ID.clone(), consensus_pk.clone()) - .await - .unwrap(); + let mut signed_delegation = + signing_manager.create_proxy_bls(MODULE_ID.clone(), consensus_pk).await.unwrap(); let m = &mut signed_delegation.signature.0[0]; (*m, _) = m.overflowing_add(1); @@ -338,18 +334,13 @@ mod tests { async fn test_proxy_key_signs_message() { let (mut signing_manager, consensus_pk) = init_signing_manager(); - let signed_delegation = signing_manager - .create_proxy_bls(MODULE_ID.clone(), consensus_pk.clone()) - .await - .unwrap(); + let signed_delegation = + signing_manager.create_proxy_bls(MODULE_ID.clone(), consensus_pk).await.unwrap(); let proxy_pk = signed_delegation.message.proxy; let data_root = B256::random(); - let sig = signing_manager - .sign_proxy_bls(&proxy_pk.try_into().unwrap(), &data_root) - .await - .unwrap(); + let sig = signing_manager.sign_proxy_bls(&proxy_pk, &data_root).await.unwrap(); // Verify signature let domain = compute_domain(CHAIN, COMMIT_BOOST_DOMAIN); @@ -376,10 +367,8 @@ mod tests { async fn test_proxy_key_is_valid_proxy_for_consensus_key() { let (mut signing_manager, consensus_pk) = init_signing_manager(); - let signed_delegation = signing_manager - .create_proxy_ecdsa(MODULE_ID.clone(), consensus_pk.clone()) - .await - .unwrap(); + let signed_delegation = + signing_manager.create_proxy_ecdsa(MODULE_ID.clone(), consensus_pk).await.unwrap(); let validation_result = signed_delegation.validate(CHAIN); @@ -399,10 +388,8 @@ mod tests { async fn test_tampered_proxy_key_is_invalid() { let (mut signing_manager, consensus_pk) = init_signing_manager(); - let mut signed_delegation = signing_manager - .create_proxy_ecdsa(MODULE_ID.clone(), consensus_pk.clone()) - .await - .unwrap(); + let mut signed_delegation = + signing_manager.create_proxy_ecdsa(MODULE_ID.clone(), consensus_pk).await.unwrap(); let m = &mut signed_delegation.signature.0[0]; (*m, _) = m.overflowing_add(1); @@ -416,18 +403,13 @@ mod tests { async fn test_proxy_key_signs_message() { let (mut signing_manager, consensus_pk) = init_signing_manager(); - let signed_delegation = signing_manager - .create_proxy_ecdsa(MODULE_ID.clone(), consensus_pk.clone()) - .await - .unwrap(); + let signed_delegation = + signing_manager.create_proxy_ecdsa(MODULE_ID.clone(), consensus_pk).await.unwrap(); let proxy_pk = signed_delegation.message.proxy; let data_root = B256::random(); - let sig = signing_manager - .sign_proxy_ecdsa(&proxy_pk.try_into().unwrap(), &data_root) - .await - .unwrap(); + let sig = signing_manager.sign_proxy_ecdsa(&proxy_pk, &data_root).await.unwrap(); // Verify signature let domain = compute_domain(CHAIN, COMMIT_BOOST_DOMAIN);