Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 5 additions & 4 deletions config-live-example.toml
Original file line number Diff line number Diff line change
Expand Up @@ -35,10 +35,11 @@ live_builders = ["mp-ordering", "mgp-ordering", "parallel"]
enabled_relays = ["flashbots"]

# This can be used with test-relay
# [[relays]]
# name = "flashbots_test"
# url = "http://localhost:80"
# priority = 0
[[relays]]
name = "flashbots_test"
url = "http://localhost:80"
mode = "full"
max_bid_eth = "0.05"

[[builders]]
name = "mgp-ordering"
Expand Down
53 changes: 8 additions & 45 deletions crates/rbuilder/src/live_builder/block_output/relay_submit.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,10 +6,7 @@ use crate::{
submission::{BidMetadata, BidValueMetadata, SubmitBlockRequestWithMetadata},
BLSBlockSigner, RelayError, SubmitBlockErr,
},
primitives::{
mev_boost::{MevBoostRelayBidSubmitter, MevBoostRelayID},
Order,
},
primitives::mev_boost::{MevBoostRelayBidSubmitter, MevBoostRelayID},
telemetry::{
add_relay_submit_time, add_subsidy_value, inc_conn_relay_errors,
inc_failed_block_simulations, inc_initiated_submissions, inc_other_relay_errors,
Expand Down Expand Up @@ -104,10 +101,6 @@ pub struct SubmissionConfig {

pub optimistic_config: Option<OptimisticConfig>,
pub bid_observer: Box<dyn BidObserver + Send + Sync>,
/// Bids above this value will only go to independent relays.
pub independent_bid_threshold: U256,
/// For bids below this value we ignore RelayConfig::is_fast (it's like is_fast is true for all relays)
pub ignore_fast_bid_threshold: U256,
}

/// Configuration for optimistic block submission to relays.
Expand Down Expand Up @@ -249,12 +242,8 @@ async fn run_submit_to_relays_job(
failed_orders_statistics = ?block.trace.failed_orders_statistics,
"Submitting bid",
);
let relay_filter = get_relay_filter_and_update_metrics(
&block,
optimistic_config.is_some(),
config.independent_bid_threshold,
config.ignore_fast_bid_threshold,
);
inc_initiated_submissions(optimistic_config.is_some());
let relay_filter = get_relay_filter(&block);

let (normal_signed_submission, optimistic_signed_submission) = {
let normal_signed_submission = match sign_block_for_relay(
Expand Down Expand Up @@ -377,38 +366,12 @@ fn submit_block_to_relays(
}

/// Creates a Fn to decide if the block should go to a relay.
/// The cfg defines 2 flags on relays: fast and independent.
/// If a block has replacement ids it should NOT go to a relay that is not fast since it needs fast cancellations.
/// If a block is expensive it should NOT go to a non independent relay.
fn get_relay_filter_and_update_metrics(
block: &Block,
optimistic: bool,
independent_bid_threshold: U256,
ignore_fast_bid_threshold: U256,
) -> impl Fn(&MevBoostRelayBidSubmitter) -> bool {
// only_independent = expensive blocks.
let only_independent = block.trace.bid_value > independent_bid_threshold;
// only_fast = bid > ignore_fast_bid_threshold && blocks with replaceable orders
let only_fast = block.trace.bid_value > ignore_fast_bid_threshold
&& 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,
});
inc_initiated_submissions(optimistic, !only_fast, !only_independent);
/// It's a Fn because the code changes a lot (used to be more complex).
/// Blocks go only to relays that have a max bid >= bid_value (or no max bid).
fn get_relay_filter(block: &Block) -> impl Fn(&MevBoostRelayBidSubmitter) -> bool {
let bid_value = block.trace.bid_value;
move |relay: &MevBoostRelayBidSubmitter| {
if only_independent && !relay.is_independent() {
return false; // Sorry relay but this block is expensive and you are not independent :(
}
if only_fast && !relay.is_fast() {
return false; // Sorry relay but this block contains replacements and you are slow :(
}
true
relay.max_bid().is_none_or(|max_bid| bid_value <= max_bid)
}
}

Expand Down
31 changes: 6 additions & 25 deletions crates/rbuilder/src/live_builder/config.rs
Original file line number Diff line number Diff line change
Expand Up @@ -115,8 +115,6 @@ pub struct Config {
}

const DEFAULT_SLOT_DELTA_TO_START_BIDDING_MS: i64 = -8000;
const DEFAULT_INDEPENDENT_BID_THRESHOLD_ETH: &str = "0";
const DEFAULT_IGNORE_FAST_BID_THRESHOLD_ETH: &str = "0";
const DEFAULT_ASK_FOR_FILTERING_VALIDATORS: bool = false;

#[serde_as]
Expand All @@ -143,12 +141,6 @@ pub struct L1Config {

/// Genesis fork version for the chain. If not provided it will be fetched from the beacon client.
pub genesis_fork_version: Option<String>,

/// Bids above this value will only go to independent relays.
pub independent_bid_threshold_eth: String,

/// For bids below this value we ignore RelayConfig::is_fast (it's like is_fast is true for all relays)
pub ignore_fast_bid_threshold_eth: String,
}

impl Default for L1Config {
Expand All @@ -162,8 +154,6 @@ 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,
independent_bid_threshold_eth: DEFAULT_INDEPENDENT_BID_THRESHOLD_ETH.to_owned(),
ignore_fast_bid_threshold_eth: DEFAULT_IGNORE_FAST_BID_THRESHOLD_ETH.to_owned(),
}
}
}
Expand Down Expand Up @@ -204,9 +194,7 @@ impl L1Config {
relay_config.name.clone(),
submit_config,
relay_config.mode == RelayMode::Test,
relay_config.is_fast(),
relay_config.is_independent(),
));
)?);
} else {
eyre::bail!(
"Relay {} in mode {:?} has no submit config",
Expand Down Expand Up @@ -326,8 +314,6 @@ impl L1Config {
signer,
optimistic_config,
bid_observer,
independent_bid_threshold: parse_ether(&self.independent_bid_threshold_eth)?,
ignore_fast_bid_threshold: parse_ether(&self.ignore_fast_bid_threshold_eth)?,
})
}

Expand Down Expand Up @@ -766,13 +752,12 @@ lazy_static! {
use_gzip_for_submit: false,
optimistic: false,
interval_between_submissions_ms: Some(250),
max_bid_eth: None,
}),
priority: Some(0),
authorization_header: None,
builder_id_header: None,
api_token_header: None,
is_fast: None,
is_independent: None,
ask_for_filtering_validators: None,
},
);
Expand All @@ -787,13 +772,12 @@ lazy_static! {
use_gzip_for_submit: true,
optimistic: true,
interval_between_submissions_ms: None,
max_bid_eth: None,
}),
priority: Some(0),
authorization_header: None,
builder_id_header: None,
api_token_header: None,
is_fast: None,
is_independent: None,
ask_for_filtering_validators: None,
},
);
Expand All @@ -808,13 +792,12 @@ lazy_static! {
use_gzip_for_submit: true,
optimistic: true,
interval_between_submissions_ms: None,
max_bid_eth: None,
}),
priority: Some(0),
authorization_header: None,
builder_id_header: None,
api_token_header: None,
is_fast: None,
is_independent: None,
ask_for_filtering_validators: None,
},
);
Expand All @@ -829,12 +812,11 @@ lazy_static! {
use_gzip_for_submit: true,
optimistic: true,
interval_between_submissions_ms: None,
max_bid_eth: None,
}), priority: Some(0),
authorization_header: None,
builder_id_header: None,
api_token_header: None,
is_fast: None,
is_independent: None,
ask_for_filtering_validators: None,
},
);
Expand All @@ -849,13 +831,12 @@ lazy_static! {
use_gzip_for_submit: false,
optimistic: false,
interval_between_submissions_ms: None,
max_bid_eth: None,
}),
priority: Some(0),
authorization_header: None,
builder_id_header: None,
api_token_header: None,
is_fast: None,
is_independent: None,
ask_for_filtering_validators: None,
},
);
Expand Down
52 changes: 21 additions & 31 deletions crates/rbuilder/src/primitives/mev_boost.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ use crate::mev_boost::{
submission::SubmitBlockRequestWithMetadata, RelayClient, RelayError, SubmitBlockErr,
ValidatorSlotData,
};
use alloy_primitives::{utils::parse_ether, U256};
use governor::{DefaultDirectRateLimiter, Quota, RateLimiter};
use serde::{Deserialize, Deserializer};
use std::{env, sync::Arc, time::Duration};
Expand Down Expand Up @@ -61,18 +62,12 @@ pub struct RelayConfig {
pub submit_config: Option<RelaySubmitConfig>,
/// Deprecated field that is not used
pub priority: Option<usize>,
/// Critical blocks (containing bundles with replacement ids) go only to fast relays. None -> true
pub is_fast: Option<bool>,
/// Big blocks (bid > [L1Config::independent_bid_threshold_eth]) go only to independent relays. None -> true
pub is_independent: Option<bool>,
/// Adds "filtering=true" as query to the call relay/v1/builder/validators to get all validators (including those filtering OFAC)
/// On 2025/06/24 (my birthday!) only supported by ultrasound.
/// None -> false
pub ask_for_filtering_validators: Option<bool>,
}

const IS_FAST_DEFAULT: bool = true;
const IS_INDEPENDENT_DEFAULT: bool = true;
#[derive(Debug, Clone, Deserialize, PartialEq, Eq, Default)]
#[serde(deny_unknown_fields)]
pub struct RelaySubmitConfig {
Expand All @@ -85,6 +80,9 @@ pub struct RelaySubmitConfig {
pub optimistic: bool,
#[serde(default)]
pub interval_between_submissions_ms: Option<u64>,
/// Max bid we can submit to this relay. Any bid above this will be skipped.
/// None -> No limit.
pub max_bid_eth: Option<String>,
}

impl RelayConfig {
Expand All @@ -101,14 +99,6 @@ impl RelayConfig {
..self
}
}

pub fn is_fast(&self) -> bool {
self.is_fast.unwrap_or(IS_FAST_DEFAULT)
}

pub fn is_independent(&self) -> bool {
self.is_independent.unwrap_or(IS_INDEPENDENT_DEFAULT)
}
}

/// Wrapper in RelayClient to submit blocks.
Expand All @@ -130,8 +120,9 @@ pub struct MevBoostRelayBidSubmitter {
test_relay: bool,
/// Parameter for the relay
cancellations: bool,
is_fast: bool,
is_independent: bool,
/// Max bid we can submit to this relay. Any bid above this will be skipped.
/// None -> No limit.
max_bid: Option<U256>,
}

impl MevBoostRelayBidSubmitter {
Expand All @@ -140,15 +131,19 @@ impl MevBoostRelayBidSubmitter {
id: String,
config: &RelaySubmitConfig,
test_relay: bool,
is_fast: bool,
is_independent: bool,
) -> Self {
) -> eyre::Result<Self> {
let max_bid = config
.max_bid_eth
.as_ref()
.map(|s| parse_ether(s))
.transpose()
.map_err(|e| eyre::eyre!("Failed to parse max bid: {}", e))?;
let submission_rate_limiter = config.interval_between_submissions_ms.map(|d| {
Arc::new(RateLimiter::direct(
Quota::with_period(Duration::from_millis(d)).expect("Rate limiter time period"),
))
});
Self {
Ok(Self {
id,
client,
use_ssz_for_submit: config.use_ssz_for_submit,
Expand All @@ -157,17 +152,8 @@ impl MevBoostRelayBidSubmitter {
submission_rate_limiter,
test_relay,
cancellations: true,
is_fast,
is_independent,
}
}

pub fn is_fast(&self) -> bool {
self.is_fast
}

pub fn is_independent(&self) -> bool {
self.is_independent
max_bid,
})
}

pub fn test_relay(&self) -> bool {
Expand All @@ -182,6 +168,10 @@ impl MevBoostRelayBidSubmitter {
self.optimistic
}

pub fn max_bid(&self) -> Option<U256> {
self.max_bid
}

/// false -> rate limiter don't allow
pub fn can_submit_bid(&self) -> bool {
if let Some(limiter) = &self.submission_rate_limiter {
Expand Down
14 changes: 3 additions & 11 deletions crates/rbuilder/src/telemetry/metrics/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -152,7 +152,7 @@ register_metrics! {
"initiated_submissions",
"Number of initiated submissions to the relays"
),
&["optimistic","sent_to_slow","send_to_non_independent"],
&["optimistic"],
)
.unwrap();

Expand Down Expand Up @@ -501,17 +501,9 @@ pub fn inc_active_slots() {
ACTIVE_SLOTS.inc();
}

pub fn inc_initiated_submissions(
optimistic: bool,
sent_to_slow_relays: bool,
send_to_non_independent: bool,
) {
pub fn inc_initiated_submissions(optimistic: bool) {
INITIATED_SUBMISSIONS
.with_label_values(&[
&optimistic.to_string(),
&sent_to_slow_relays.to_string(),
&send_to_non_independent.to_string(),
])
.with_label_values(&[&optimistic.to_string()])
.inc();
}

Expand Down
Loading