From 40978a312459cad83f5076ad8b079a2ef4fa86cd Mon Sep 17 00:00:00 2001 From: "s. rannou" Date: Thu, 27 Mar 2025 17:21:45 +0100 Subject: [PATCH 1/2] feat: add the ability to set GET parameters in relayer calls --- benches/pbs/src/main.rs | 1 + config.example.toml | 5 ++++- crates/common/src/config/pbs.rs | 2 ++ crates/common/src/pbs/relay.rs | 40 ++++++++++++++++++++++++++++++++- tests/src/utils.rs | 2 ++ 5 files changed, 48 insertions(+), 2 deletions(-) diff --git a/benches/pbs/src/main.rs b/benches/pbs/src/main.rs index 19a79687..c013fd61 100644 --- a/benches/pbs/src/main.rs +++ b/benches/pbs/src/main.rs @@ -157,6 +157,7 @@ fn get_mock_validator(bench: BenchConfig) -> RelayClient { entry, id: None, headers: None, + get_params: None, enable_timing_games: false, target_first_request_ms: None, frequency_get_header_ms: None, diff --git a/config.example.toml b/config.example.toml index e5e7f777..fed61954 100644 --- a/config.example.toml +++ b/config.example.toml @@ -66,6 +66,9 @@ url = "http://0xa1cec75a3f0661e99299274182938151e8433c61a19222347ea1313d839229cb # Headers to send with each request for this relay # OPTIONAL headers = { X-MyCustomHeader = "MyCustomValue" } +# GET parameters to add to each request URL for this relay +# OPTIONAL +get_params = { param1 = "value1", param2 = "value2" } # Whether to enable timing games, as tuned by `target_first_request_ms` and `frequency_get_header_ms`. # These values should be carefully chosen for each relay, as each relay has different latency and timing games setups. # They should only be used by advanced users, and if mis-configured can result in unforeseen effects, e.g. fetching a lower header value, @@ -130,7 +133,7 @@ timeout_get_header_ms = 900 late_in_slot_time_ms = 1500 # For each mux, one or more [[mux.relays]] can be defined, which will be used for the matching validator pubkeys # Only the relays defined here will be used, and the relays defined in the main [[relays]] config will be ignored -# The fields specified here are the same as in [[relays]] (headers, enable_timing_games, target_first_request_ms, frequency_get_header_ms) +# The fields specified here are the same as in [[relays]] (headers, get_params, enable_timing_games, target_first_request_ms, frequency_get_header_ms) [[mux.relays]] id = "mux-relay-1" url = "http://0xa119589bb33ef52acbb8116832bec2b58fca590fe5c85eac5d3230b44d5bc09fe73ccd21f88eab31d6de16194d17782e@def.xyz" diff --git a/crates/common/src/config/pbs.rs b/crates/common/src/config/pbs.rs index 5b46c9b2..769b9cfa 100644 --- a/crates/common/src/config/pbs.rs +++ b/crates/common/src/config/pbs.rs @@ -43,6 +43,8 @@ pub struct RelayConfig { pub entry: RelayEntry, /// Optional headers to send with each request pub headers: Option>, + /// Optional GET parameters to add to each request + pub get_params: Option>, /// Whether to enable timing games #[serde(default = "default_bool::")] pub enable_timing_games: bool, diff --git a/crates/common/src/pbs/relay.rs b/crates/common/src/pbs/relay.rs index c74a6516..7ab56c3f 100644 --- a/crates/common/src/pbs/relay.rs +++ b/crates/common/src/pbs/relay.rs @@ -90,7 +90,16 @@ impl RelayClient { // URL builders pub fn get_url(&self, path: &str) -> Result { - self.config.entry.url.join(path).map_err(PbsError::UrlParsing) + let mut url = self.config.entry.url.join(path).map_err(PbsError::UrlParsing)?; + + if let Some(get_params) = &self.config.get_params { + let mut query_pairs = url.query_pairs_mut(); + for (key, value) in get_params { + query_pairs.append_pair(key, value); + } + } + + Ok(url) } pub fn builder_api_url(&self, path: &str) -> Result { self.get_url(&format!("{BUILDER_API_PATH}{path}")) @@ -120,6 +129,7 @@ impl RelayClient { #[cfg(test)] mod tests { + use std::collections::HashMap; use alloy::{ primitives::{hex::FromHex, B256}, rpc::types::beacon::BlsPublicKey, @@ -172,4 +182,32 @@ mod tests { expected ); } + + #[test] + fn test_relay_url_with_get_params() { + let slot = 0; + let parent_hash = B256::ZERO; + let validator_pubkey = BlsPublicKey::ZERO; + // Note: HashMap iteration order is not guaranteed, so we can't predict the exact order of parameters + // Instead of hard-coding the order, we'll check that both parameters are present in the URL + let url_prefix = format!("http://0xa1cec75a3f0661e99299274182938151e8433c61a19222347ea1313d839229cb4ce4e3e5aa2bdeb71c8fcf1b084963c2@abc.xyz/eth/v1/builder/header/{slot}/{parent_hash}/{validator_pubkey}?"); + + let mut get_params = HashMap::new(); + get_params.insert("param1".to_string(), "value1".to_string()); + get_params.insert("param2".to_string(), "value2".to_string()); + + let relay_config = r#" + { + "url": "http://0xa1cec75a3f0661e99299274182938151e8433c61a19222347ea1313d839229cb4ce4e3e5aa2bdeb71c8fcf1b084963c2@abc.xyz" + }"#; + + let mut config = serde_json::from_str::(relay_config).unwrap(); + config.get_params = Some(get_params); + let relay = RelayClient::new(config).unwrap(); + + let url = relay.get_header_url(slot, parent_hash, validator_pubkey).unwrap().to_string(); + assert!(url.starts_with(&url_prefix)); + assert!(url.contains("param1=value1")); + assert!(url.contains("param2=value2")); + } } diff --git a/tests/src/utils.rs b/tests/src/utils.rs index 973d02c9..f2ae9157 100644 --- a/tests/src/utils.rs +++ b/tests/src/utils.rs @@ -29,6 +29,7 @@ pub fn generate_mock_relay(port: u16, pubkey: BlsPublicKey) -> Result Date: Thu, 27 Mar 2025 17:35:24 +0100 Subject: [PATCH 2/2] fix: lint --- crates/common/src/pbs/relay.rs | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/crates/common/src/pbs/relay.rs b/crates/common/src/pbs/relay.rs index 7ab56c3f..1169175a 100644 --- a/crates/common/src/pbs/relay.rs +++ b/crates/common/src/pbs/relay.rs @@ -130,6 +130,7 @@ impl RelayClient { #[cfg(test)] mod tests { use std::collections::HashMap; + use alloy::{ primitives::{hex::FromHex, B256}, rpc::types::beacon::BlsPublicKey, @@ -188,8 +189,9 @@ mod tests { let slot = 0; let parent_hash = B256::ZERO; let validator_pubkey = BlsPublicKey::ZERO; - // Note: HashMap iteration order is not guaranteed, so we can't predict the exact order of parameters - // Instead of hard-coding the order, we'll check that both parameters are present in the URL + // Note: HashMap iteration order is not guaranteed, so we can't predict the + // exact order of parameters Instead of hard-coding the order, we'll + // check that both parameters are present in the URL let url_prefix = format!("http://0xa1cec75a3f0661e99299274182938151e8433c61a19222347ea1313d839229cb4ce4e3e5aa2bdeb71c8fcf1b084963c2@abc.xyz/eth/v1/builder/header/{slot}/{parent_hash}/{validator_pubkey}?"); let mut get_params = HashMap::new();