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
1 change: 1 addition & 0 deletions benches/pbs/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand Down
5 changes: 4 additions & 1 deletion config.example.toml
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand Down Expand Up @@ -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"
Expand Down
2 changes: 2 additions & 0 deletions crates/common/src/config/pbs.rs
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,8 @@ pub struct RelayConfig {
pub entry: RelayEntry,
/// Optional headers to send with each request
pub headers: Option<HashMap<String, String>>,
/// Optional GET parameters to add to each request
pub get_params: Option<HashMap<String, String>>,
/// Whether to enable timing games
#[serde(default = "default_bool::<false>")]
pub enable_timing_games: bool,
Expand Down
42 changes: 41 additions & 1 deletion crates/common/src/pbs/relay.rs
Original file line number Diff line number Diff line change
Expand Up @@ -90,7 +90,16 @@ impl RelayClient {

// URL builders
pub fn get_url(&self, path: &str) -> Result<Url, PbsError> {
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<Url, PbsError> {
self.get_url(&format!("{BUILDER_API_PATH}{path}"))
Expand Down Expand Up @@ -120,6 +129,8 @@ impl RelayClient {

#[cfg(test)]
mod tests {
use std::collections::HashMap;

use alloy::{
primitives::{hex::FromHex, B256},
rpc::types::beacon::BlsPublicKey,
Expand Down Expand Up @@ -172,4 +183,33 @@ 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::<RelayConfig>(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"));
}
}
2 changes: 2 additions & 0 deletions tests/src/utils.rs
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ pub fn generate_mock_relay(port: u16, pubkey: BlsPublicKey) -> Result<RelayClien
entry,
id: None,
headers: None,
get_params: None,
enable_timing_games: false,
target_first_request_ms: None,
frequency_get_header_ms: None,
Expand All @@ -48,6 +49,7 @@ pub fn generate_mock_relay_with_batch_size(
entry,
id: None,
headers: None,
get_params: None,
enable_timing_games: false,
target_first_request_ms: None,
frequency_get_header_ms: None,
Expand Down