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
81 changes: 81 additions & 0 deletions crates/rbuilder-primitives/src/mev_boost/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -181,6 +181,9 @@ pub struct ValidatorSlotData {
/// (Bloxroute) Collection of regional endpoints validator is connected to.
#[serde(default)]
pub regional_endpoints: Vec<BloxrouteRegionalEndpoint>,
/// (Titan) Validator preferences.
#[serde(default)]
pub preferences: Option<TitanValidatorPreferences>,
}

/// Bloxroute validator RProxy details.
Expand All @@ -198,6 +201,13 @@ pub struct BloxrouteRegionalEndpoint {
pub websocket_endpoint: String,
}

/// Titan validator preferences.
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize, Hash)]
pub struct TitanValidatorPreferences {
/// Flag indicating whether the validator is censoring.
pub censoring: bool,
}

#[derive(Clone, Debug)]
pub struct BidMetadata {
pub sequence: u64,
Expand All @@ -217,3 +227,74 @@ pub struct SubmitBlockRequestWithMetadata {
pub submission: SubmitBlockRequest,
pub metadata: BidMetadata,
}

#[cfg(test)]
mod tests {
use super::*;

#[test]
fn validator_slot_data_ser_deser() {
let registrations = [
r#"
{
"slot": "123",
"validator_index": "123",
"entry": {
"message": {
"fee_recipient": "0x0000000000000000000000000000000000000000",
"gas_limit": "60000000",
"timestamp": "123",
"pubkey": "0x000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000"
},
"signature": "0x000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000"
}
}
"#,
r#"
{
"slot": "123",
"validator_index": "123",
"entry": {
"message": {
"fee_recipient": "0x0000000000000000000000000000000000000000",
"gas_limit": "60000000",
"timestamp": "123",
"pubkey": "0x000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000"
},
"signature": "0x000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000"
},
"regional_endpoints": [
{
"name": "",
"region": "",
"http_endpoint": "http://0.0.0.0",
"grpc_endpoint": "grpc://0.0.0.0",
"websocket_endpoint": "ws://0.0.0.0"
}
]
}
"#,
r#"
{
"slot": "123",
"validator_index": "123",
"entry": {
"message": {
"fee_recipient": "0x0000000000000000000000000000000000000000",
"gas_limit": "60000000",
"timestamp": "123",
"pubkey": "0x000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000"
},
"signature": "0x000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000"
},
"preferences": {
"censoring": false
}
}
"#,
];
for raw in registrations {
assert!(serde_json::from_str::<ValidatorSlotData>(raw).is_ok());
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -237,6 +237,7 @@ mod test {
validator_index: 1,
slot: 2,
regional_endpoints: Vec::new(),
preferences: None,
},
adjustment_fee_payer: None,
}
Expand Down
24 changes: 18 additions & 6 deletions crates/rbuilder/src/mev_boost/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -102,9 +102,10 @@ pub struct RelayConfig {
/// Flag indicating whether the builder should only submit to rproxy endpoinds if available.
#[serde(default)]
pub bloxroute_rproxy_only: 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
/// Retrieves registrations for all validators, including filtering ones.
/// For ultrasound relay, the behavior is to add `filtering=true` as a query parameter.
/// For titan relay if the value is not set, the registrations will be filtered by `censoring=false` by default.
/// If the value is set to `true`, `censoring=true` validators would be included.
pub ask_for_filtering_validators: Option<bool>,
/// If we submit a block with a different gas than the one the validator registered with in this relay the relay does not mind.
/// None -> false
Expand Down Expand Up @@ -674,15 +675,25 @@ impl RelayClient {
let mut headers = HeaderMap::new();
self.add_auth_headers(&mut headers)
.map_err(|_| RelayError::InvalidHeader)?;
let validators = req
let registrations = req
.headers(headers)
.send()
.await?
.json::<RelayResponse<Vec<ValidatorSlotData>>>()
.await?;

match validators {
RelayResponse::Ok(validators) => Ok(validators),
match registrations {
RelayResponse::Ok(registrations) => {
let registrations = registrations
.into_iter()
.filter(|r| {
r.preferences
.as_ref()
.is_none_or(|p| !p.censoring || self.ask_for_filtering_validators)
})
.collect();
Ok(registrations)
}
RelayResponse::Error(error) => Err(RelayError::RelayError(error)),
}
}
Expand Down Expand Up @@ -1314,6 +1325,7 @@ mod tests {
signature: Default::default(),
},
regional_endpoints: Vec::new(),
preferences: None,
};
relay
.submit_block(&sub_relay, &registration, true, true, false, false)
Expand Down
Loading