diff --git a/config.example.yml b/config.example.yml index 352fbae6..48f60b89 100644 --- a/config.example.yml +++ b/config.example.yml @@ -52,6 +52,8 @@ block_merging_config: # collateral_safe: "0x0000000000000000000000000000000000000000" target_get_payload_propagation_duration_ms: 0 get_payload_v1_response_buffer_ms: 800 +# Maximum per-IP get_header frequency that permits payload sharing with operator peers. +ip_frequency_threshold: 0.2 primev_config: null discord_webhook_url: null is_submission_instance: true diff --git a/crates/common/src/config.rs b/crates/common/src/config.rs index f12950f8..57554396 100644 --- a/crates/common/src/config.rs +++ b/crates/common/src/config.rs @@ -62,6 +62,10 @@ pub struct RelayConfig { pub cores: CoresConfig, #[serde(default = "default_bool::")] pub gossip_payload_on_header: bool, + /// Maximum per-IP `get_header` frequency that still permits sharing the payload with + /// operator peers. + #[serde(default = "default_ip_frequency_threshold")] + pub ip_frequency_threshold: f64, #[serde(default = "default_u16::<4040>")] pub api_port: u16, #[serde(default = "default_u16::<4041>")] @@ -124,6 +128,7 @@ impl RelayConfig { housekeeper: None, }, gossip_payload_on_header: false, + ip_frequency_threshold: default_ip_frequency_threshold(), api_port: 4040, tcp_port: 4041, tcp_max_connections: 512, @@ -358,6 +363,12 @@ pub const fn default_u64() -> u64 { D } +const DEFAULT_IP_FREQUENCY_THRESHOLD: f64 = 0.2; + +const fn default_ip_frequency_threshold() -> f64 { + DEFAULT_IP_FREQUENCY_THRESHOLD +} + #[derive(Serialize, Deserialize, Clone, Debug)] pub struct AlertsConfig { pub telegram_bot_token: String, @@ -793,6 +804,20 @@ impl Default for HeaderStreamConfig { mod tests { use super::*; + #[test] + fn test_ip_frequency_threshold_config_default_and_override() { + let threshold_key = serde_yaml::Value::String("ip_frequency_threshold".to_owned()); + let mut value = serde_yaml::to_value(RelayConfig::empty_for_test()).unwrap(); + value.as_mapping_mut().unwrap().remove(&threshold_key); + + let default_config: RelayConfig = serde_yaml::from_value(value.clone()).unwrap(); + assert_eq!(default_config.ip_frequency_threshold, DEFAULT_IP_FREQUENCY_THRESHOLD); + + value.as_mapping_mut().unwrap().insert(threshold_key, serde_yaml::to_value(0.5).unwrap()); + let overridden_config: RelayConfig = serde_yaml::from_value(value).unwrap(); + assert_eq!(overridden_config.ip_frequency_threshold, 0.5); + } + fn create_router_config(routes: Vec) -> RouterConfig { RouterConfig { enabled_routes: routes diff --git a/crates/relay/src/api/proposer/get_header.rs b/crates/relay/src/api/proposer/get_header.rs index d1704c49..793ec0cc 100644 --- a/crates/relay/src/api/proposer/get_header.rs +++ b/crates/relay/src/api/proposer/get_header.rs @@ -32,9 +32,6 @@ use crate::api::{ router::Terminating, }; -/// Gate for p2p payload sharing - get_header reqs in < 20% of previous epoch slots. -const IP_FREQUENCY_THRESHOLD: f64 = 0.2; - pub(super) struct ValidatedHeaderRequest { pub ms_into_slot: u64, pub validation_complete_ns: u64, @@ -209,7 +206,7 @@ impl ProposerApi { Cow::Owned(payload_and_blobs), fork, Cow::Owned(bid_data), - ip_gate < IP_FREQUENCY_THRESHOLD, + ip_gate < proposer_api.relay_config.ip_frequency_threshold, ) .await; }