diff --git a/crates/rbuilder/src/live_builder/block_output/relay_submit.rs b/crates/rbuilder/src/live_builder/block_output/relay_submit.rs index 8445aa30b..5679ed160 100644 --- a/crates/rbuilder/src/live_builder/block_output/relay_submit.rs +++ b/crates/rbuilder/src/live_builder/block_output/relay_submit.rs @@ -6,7 +6,10 @@ use crate::{ submission::{BidMetadata, BidValueMetadata, SubmitBlockRequestWithMetadata}, BLSBlockSigner, RelayError, SubmitBlockErr, }, - primitives::mev_boost::{MevBoostRelayBidSubmitter, MevBoostRelayID}, + primitives::{ + mev_boost::{MevBoostRelayBidSubmitter, MevBoostRelayID}, + Order, + }, telemetry::{ add_relay_submit_time, add_subsidy_value, inc_conn_relay_errors, inc_failed_block_simulations, inc_initiated_submissions, inc_other_relay_errors, @@ -23,7 +26,7 @@ use reth_chainspec::ChainSpec; use std::sync::Arc; use tokio::{sync::Notify, time::Instant}; use tokio_util::sync::CancellationToken; -use tracing::{error, info, info_span, trace, warn, Instrument}; +use tracing::{error, info, info_span, trace, warn, Instrument, Span}; use super::{ bid_observer::BidObserver, @@ -101,6 +104,8 @@ pub struct SubmissionConfig { pub optimistic_config: Option, pub bid_observer: Box, + /// Bids above this value will only go to fast relays. + pub fast_bid_threshold: U256, } /// Configuration for optimistic block submission to relays. @@ -232,7 +237,8 @@ async fn run_submit_to_relays_job( parent: &submission_span, "Submitting bid", ); - inc_initiated_submissions(optimistic_config.is_some()); + let send_to_slow_relays = can_send_to_slow_relay(&block, config.fast_bid_threshold); + inc_initiated_submissions(optimistic_config.is_some(), send_to_slow_relays); let (normal_signed_submission, optimistic_signed_submission) = { let normal_signed_submission = match sign_block_for_relay( @@ -286,47 +292,34 @@ async fn run_submit_to_relays_job( }; mark_submission_start_time(block.trace.orders_sealed_at); - - for relay in &normal_relays { - let span = info_span!(parent: &submission_span, "relay_submit", relay = &relay.id(), optimistic = false); - let relay = relay.clone(); - let cancel = cancel.clone(); - let submission = normal_signed_submission.clone(); - tokio::spawn( - async move { - submit_bid_to_the_relay(&relay, cancel.clone(), submission, false).await; - } - .instrument(span), - ); - } + submit_block_to_relays( + &normal_relays, + &normal_signed_submission, + send_to_slow_relays, + false, + &submission_span, + &cancel, + ); if let Some((optimistic_signed_submission, _)) = &optimistic_signed_submission { - for relay in &optimistic_relays { - let span = info_span!(parent: &submission_span, "relay_submit", relay = &relay.id(), optimistic = true); - let relay = relay.clone(); - let cancel = cancel.clone(); - let submission = optimistic_signed_submission.clone(); - tokio::spawn( - async move { - submit_bid_to_the_relay(&relay, cancel.clone(), submission, true).await; - } - .instrument(span), - ); - } + submit_block_to_relays( + &optimistic_relays, + optimistic_signed_submission, + send_to_slow_relays, + true, + &submission_span, + &cancel, + ); } else { // non-optimistic submission to optimistic relays - for relay in &optimistic_relays { - let span = info_span!(parent: &submission_span, "relay_submit", relay = &relay.id(), optimistic = false); - let relay = relay.clone(); - let cancel = cancel.clone(); - let submission = normal_signed_submission.clone(); - tokio::spawn( - async move { - submit_bid_to_the_relay(&relay, cancel.clone(), submission, false).await; - } - .instrument(span), - ); - } + submit_block_to_relays( + &optimistic_relays, + &normal_signed_submission, + send_to_slow_relays, + false, + &submission_span, + &cancel, + ); } submission_span.in_scope(|| { @@ -342,6 +335,46 @@ async fn run_submit_to_relays_job( } } +fn submit_block_to_relays( + relays: &Vec, + submission: &SubmitBlockRequestWithMetadata, + send_to_slow_relays: bool, + optimistic: bool, + submission_span: &Span, + cancel: &CancellationToken, +) { + for relay in relays { + if relay.is_fast() || send_to_slow_relays { + let span = info_span!(parent: submission_span, "relay_submit", relay = &relay.id(), optimistic); + let relay = relay.clone(); + let cancel = cancel.clone(); + let submission = submission.clone(); + tokio::spawn( + async move { + submit_bid_to_the_relay(&relay, cancel.clone(), submission, optimistic).await; + } + .instrument(span), + ); + } + } +} + +/// can send only cheap blocks with no bundle replacement data. +fn can_send_to_slow_relay(block: &Block, fast_bid_threshold: U256) -> bool { + let has_replacement_uuid = block + .trace + .included_orders + .iter() + .flat_map(|exec_res| exec_res.order.original_orders()) + .any(|o| match o { + Order::Bundle(bundle) => bundle.replacement_data.is_some(), + Order::Tx(_) => false, + Order::ShareBundle(_) => false, + }); + let is_expensive_block = block.trace.bid_value > fast_bid_threshold; + !has_replacement_uuid && !is_expensive_block +} + pub async fn run_submit_to_relays_job_and_metrics( pending_bid: Arc, slot_data: MevBoostSlotData, diff --git a/crates/rbuilder/src/live_builder/config.rs b/crates/rbuilder/src/live_builder/config.rs index 9ae04aeab..c432907f2 100644 --- a/crates/rbuilder/src/live_builder/config.rs +++ b/crates/rbuilder/src/live_builder/config.rs @@ -125,12 +125,15 @@ pub struct L1Config { /// Bids above this value will always be submitted in non-optimistic mode. pub optimistic_max_bid_value_eth: String, - ///Name kept singular for backwards compatibility + /// Name kept singular for backwards compatibility #[serde_as(deserialize_as = "OneOrMany>")] pub cl_node_url: Vec>, /// Genesis fork version for the chain. If not provided it will be fetched from the beacon client. pub genesis_fork_version: Option, + + /// Bids above this value will only go to fast relays. + pub fast_bid_threshold_eth: String, } impl Default for L1Config { @@ -144,6 +147,7 @@ impl Default for L1Config { optimistic_max_bid_value_eth: "0.0".to_string(), cl_node_url: vec![EnvOrValue::from("http://127.0.0.1:3500")], genesis_fork_version: None, + fast_bid_threshold_eth: "0".to_owned(), } } } @@ -184,6 +188,7 @@ impl L1Config { relay_config.name.clone(), submit_config, relay_config.mode == RelayMode::Test, + relay_config.is_fast(), )); } else { eyre::bail!( @@ -301,6 +306,7 @@ impl L1Config { signer, optimistic_config, bid_observer, + fast_bid_threshold: parse_ether(&self.fast_bid_threshold_eth)?, }) } @@ -691,6 +697,7 @@ lazy_static! { authorization_header: None, builder_id_header: None, api_token_header: None, + is_fast: None, }, ); map.insert( @@ -709,6 +716,7 @@ lazy_static! { authorization_header: None, builder_id_header: None, api_token_header: None, + is_fast: None, }, ); map.insert( @@ -727,6 +735,7 @@ lazy_static! { authorization_header: None, builder_id_header: None, api_token_header: None, + is_fast: None, }, ); map.insert( @@ -744,6 +753,7 @@ lazy_static! { authorization_header: None, builder_id_header: None, api_token_header: None, + is_fast: None, }, ); map.insert( @@ -762,6 +772,7 @@ lazy_static! { authorization_header: None, builder_id_header: None, api_token_header: None, + is_fast: None, }, ); map diff --git a/crates/rbuilder/src/primitives/mev_boost.rs b/crates/rbuilder/src/primitives/mev_boost.rs index e86285c19..f9372174b 100644 --- a/crates/rbuilder/src/primitives/mev_boost.rs +++ b/crates/rbuilder/src/primitives/mev_boost.rs @@ -61,8 +61,11 @@ pub struct RelayConfig { pub submit_config: Option, /// Deprecated field that is not used pub priority: Option, + /// critical blocks go only to fast relays. None -> true + pub is_fast: Option, } +const IS_FAST_DEFAULT: bool = true; #[derive(Debug, Clone, Deserialize, PartialEq, Eq, Default)] #[serde(deny_unknown_fields)] pub struct RelaySubmitConfig { @@ -91,6 +94,10 @@ impl RelayConfig { ..self } } + + pub fn is_fast(&self) -> bool { + self.is_fast.unwrap_or(IS_FAST_DEFAULT) + } } /// Wrapper in RelayClient to submit blocks. @@ -112,6 +119,7 @@ pub struct MevBoostRelayBidSubmitter { test_relay: bool, /// Parameter for the relay cancellations: bool, + is_fast: bool, } impl MevBoostRelayBidSubmitter { @@ -120,6 +128,7 @@ impl MevBoostRelayBidSubmitter { id: String, config: &RelaySubmitConfig, test_relay: bool, + is_fast: bool, ) -> Self { let submission_rate_limiter = config.interval_between_submissions_ms.map(|d| { Arc::new(RateLimiter::direct( @@ -135,9 +144,14 @@ impl MevBoostRelayBidSubmitter { submission_rate_limiter, test_relay, cancellations: true, + is_fast, } } + pub fn is_fast(&self) -> bool { + self.is_fast + } + pub fn test_relay(&self) -> bool { self.test_relay } diff --git a/crates/rbuilder/src/telemetry/metrics/mod.rs b/crates/rbuilder/src/telemetry/metrics/mod.rs index 075c5f578..be00336b7 100644 --- a/crates/rbuilder/src/telemetry/metrics/mod.rs +++ b/crates/rbuilder/src/telemetry/metrics/mod.rs @@ -133,9 +133,10 @@ register_metrics! { "initiated_submissions", "Number of initiated submissions to the relays" ), - &["optimistic"], + &["optimistic","sent_to_slow"], ) .unwrap(); + pub static RELAY_SUBMIT_TIME: HistogramVec = HistogramVec::new( HistogramOpts::new("relay_submit_time", "Time to send bid to the relay (ms)") .buckets(linear_buckets_range(0.0, 3000.0, 50)), @@ -298,6 +299,7 @@ register_metrics! { &[] ) .unwrap(); + } // This function should be called periodically to reset histogram metrics. @@ -466,10 +468,10 @@ pub fn inc_active_slots() { ACTIVE_SLOTS.inc(); } -pub fn inc_initiated_submissions(optimistic: bool) { +pub fn inc_initiated_submissions(optimistic: bool, sent_to_slow_relays: bool) { INITIATED_SUBMISSIONS - .with_label_values(&[&optimistic.to_string()]) - .inc() + .with_label_values(&[&optimistic.to_string(), &sent_to_slow_relays.to_string()]) + .inc(); } pub fn add_relay_submit_time(relay: &MevBoostRelayID, duration: Duration) {