Skip to content

Commit 44009e1

Browse files
committed
feat: support relay bid sequencing
1 parent 4ee212e commit 44009e1

File tree

4 files changed

+40
-13
lines changed

4 files changed

+40
-13
lines changed

crates/rbuilder-primitives/src/mev_boost/mod.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -203,6 +203,7 @@ pub struct BloxrouteRegionalEndpoint {
203203

204204
#[derive(Clone, Debug)]
205205
pub struct BidMetadata {
206+
pub sequence: u64,
206207
pub value: BidValueMetadata,
207208
pub order_ids: Vec<OrderId>,
208209
pub bundle_hashes: Vec<B256>,

crates/rbuilder-primitives/src/mev_boost/submit_header.rs

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,22 @@
11
use crate::mev_boost::{
22
adjustment::BidAdjustmentDataV2,
33
ssz_roots::{calculate_transactions_root_ssz, calculate_withdrawals_root_ssz},
4+
BidMetadata,
45
};
56
use alloy_primitives::{Address, Bloom, Bytes, B256, U256};
67
use alloy_rpc_types_beacon::{relay::BidTrace, requests::ExecutionRequestsV4, BlsSignature};
78
use alloy_rpc_types_engine::ExecutionPayloadV3;
89
use serde_with::{serde_as, DisplayFromStr};
910

11+
/// Optimistic V3 bid submission with metadata.
12+
#[derive(Clone, Debug)]
13+
pub struct SubmitHeaderRequestWithMetadata {
14+
/// Header submission.
15+
pub submission: SubmitHeaderRequest,
16+
/// Bid metadata.
17+
pub metadata: BidMetadata,
18+
}
19+
1020
/// Optimistic V3 bid submission.
1121
#[derive(
1222
PartialEq,
@@ -18,7 +28,7 @@ use serde_with::{serde_as, DisplayFromStr};
1828
ssz_derive::Encode,
1929
ssz_derive::Decode,
2030
)]
21-
pub struct HeaderSubmissionOptimisticV3 {
31+
pub struct SubmitHeaderRequest {
2232
/// URL pointing to the builder's server endpoint for retrieving
2333
/// the full block payload if this header is selected.
2434
pub url: Vec<u8>,

crates/rbuilder/src/live_builder/block_output/relay_submit.rs

Lines changed: 14 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -23,13 +23,14 @@ use rbuilder_primitives::{
2323
built_block::{block_to_execution_payload, SignedBuiltBlock},
2424
mev_boost::{
2525
BidAdjustmentData, BidMetadata, BidValueMetadata, ExecutionPayloadHeaderElectra,
26-
HeaderSubmission, HeaderSubmissionElectra, HeaderSubmissionOptimisticV3, MevBoostRelayID,
27-
SignedHeaderSubmission, SubmitBlockRequest, SubmitBlockRequestWithMetadata,
28-
ValidatorSlotData,
26+
HeaderSubmission, HeaderSubmissionElectra, MevBoostRelayID, SignedHeaderSubmission,
27+
SubmitBlockRequest, SubmitBlockRequestWithMetadata, SubmitHeaderRequest,
28+
SubmitHeaderRequestWithMetadata, ValidatorSlotData,
2929
},
3030
};
3131
use reth_chainspec::ChainSpec;
3232
use std::sync::Arc;
33+
use time::OffsetDateTime;
3334
use tokio::{
3435
sync::{broadcast, Notify},
3536
time::Instant,
@@ -192,12 +193,15 @@ async fn run_submit_to_relays_job(
192193
}
193194
});
194195

196+
// SAFETY: UNIX timestamp in nanos won't exceed u64::MAX until year 2554
197+
let sequence = OffsetDateTime::now_utc().unix_timestamp_nanos() as u64;
195198
let executed_orders = block
196199
.trace
197200
.included_orders
198201
.iter()
199202
.flat_map(|exec_res| exec_res.order.original_orders());
200203
let bid_metadata = BidMetadata {
204+
sequence,
201205
value: BidValueMetadata {
202206
coinbase_reward: block.trace.coinbase_reward,
203207
top_competitor_bid: block.trace.seen_competition_bid,
@@ -362,7 +366,7 @@ fn create_optimistic_v3_request(
362366
request: &SubmitBlockRequest,
363367
maybe_adjustment_data: Option<&BidAdjustmentData>,
364368
adjustment_data_required: bool,
365-
) -> eyre::Result<HeaderSubmissionOptimisticV3> {
369+
) -> eyre::Result<SubmitHeaderRequest> {
366370
let maybe_adjustment_data_v2 = maybe_adjustment_data.map(|d| d.clone().into_v2());
367371
if maybe_adjustment_data_v2.is_none() && adjustment_data_required {
368372
eyre::bail!("adjustment data is required")
@@ -393,7 +397,7 @@ fn create_optimistic_v3_request(
393397
};
394398

395399
let tx_count = request.execution_payload_v1().transactions.len();
396-
Ok(HeaderSubmissionOptimisticV3 {
400+
Ok(SubmitHeaderRequest {
397401
url: builder_url.to_vec(),
398402
tx_count: tx_count as u32,
399403
submission: SignedHeaderSubmission {
@@ -444,7 +448,10 @@ fn submit_block_to_relays(
444448
maybe_adjustment_data,
445449
relay.optimistic_v3_bid_adjustment_required(),
446450
)
447-
.map(|request| (config.clone(), request))
451+
.map(|request| (config.clone(), SubmitHeaderRequestWithMetadata {
452+
submission: request,
453+
metadata: bid_metadata.clone()
454+
}))
448455
.inspect_err(|error| {
449456
error!(parent: submission_span, ?error, "Unable to create optimistic V3 request");
450457
})
@@ -489,7 +496,7 @@ fn submit_block_to_relays(
489496
async fn submit_bid_to_the_relay(
490497
relay: &MevBoostRelayBidSubmitter,
491498
submit_block_request: SubmitBlockRequestWithMetadata,
492-
optimistic_v3_request: Option<(OptimisticV3Config, HeaderSubmissionOptimisticV3)>,
499+
optimistic_v3_request: Option<(OptimisticV3Config, SubmitHeaderRequestWithMetadata)>,
493500
registration: ValidatorSlotData,
494501
optimistic: bool,
495502
cancel: CancellationToken,

crates/rbuilder/src/mev_boost/mod.rs

Lines changed: 14 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -4,8 +4,8 @@ use alloy_rpc_types_beacon::BlsPublicKey;
44
use flate2::{write::GzEncoder, Compression};
55
use governor::{DefaultDirectRateLimiter, Quota, RateLimiter};
66
use rbuilder_primitives::mev_boost::{
7-
HeaderSubmissionOptimisticV3, KnownRelay, MevBoostRelayID, RelayMode,
8-
SubmitBlockRequestNoBlobs, SubmitBlockRequestWithMetadata, ValidatorRegistration,
7+
KnownRelay, MevBoostRelayID, RelayMode, SubmitBlockRequestNoBlobs,
8+
SubmitBlockRequestWithMetadata, SubmitHeaderRequestWithMetadata, ValidatorRegistration,
99
ValidatorSlotData, MEV_BOOST_SLOT_INFO_REQUEST_TIMEOUT,
1010
};
1111
use reqwest::{
@@ -35,6 +35,7 @@ const BUNDLE_HASHES_HEADER: &str = "Bundle-Hashes";
3535
const TOP_BID_HEADER: &str = "Top-Bid";
3636
const BLOXROUTE_SHARE_HEADER: &str = "share";
3737
const BLOXROUTE_BUILDER_VALUE_HEADER: &str = "builder-value";
38+
const X_SEQUENCE_HEADER: &str = "x-sequence";
3839

3940
const JSON_CONTENT_TYPE: &str = "application/json";
4041
const SSZ_CONTENT_TYPE: &str = "application/octet-stream";
@@ -335,7 +336,7 @@ impl MevBoostRelayBidSubmitter {
335336

336337
pub async fn submit_optimistic_v3(
337338
&self,
338-
data: HeaderSubmissionOptimisticV3,
339+
data: SubmitHeaderRequestWithMetadata,
339340
registration: ValidatorSlotData,
340341
) -> Result<(), SubmitBlockErr> {
341342
self.client
@@ -692,6 +693,7 @@ impl RelayClient {
692693
} = submission_with_metadata;
693694

694695
let mut headers = HeaderMap::new();
696+
headers.insert(X_SEQUENCE_HEADER, metadata.sequence.into());
695697
self.add_auth_headers(&mut headers)
696698
.map_err(|_| SubmitBlockErr::InvalidHeader)?;
697699

@@ -889,11 +891,17 @@ impl RelayClient {
889891

890892
pub async fn submit_optimistic_v3(
891893
&self,
892-
request: &HeaderSubmissionOptimisticV3,
894+
request: &SubmitHeaderRequestWithMetadata,
893895
registration: &ValidatorSlotData,
894896
cancellations: bool,
895897
) -> Result<(), SubmitBlockErr> {
898+
let SubmitHeaderRequestWithMetadata {
899+
submission,
900+
metadata,
901+
} = request;
902+
896903
let mut headers = HeaderMap::new();
904+
headers.insert(X_SEQUENCE_HEADER, metadata.sequence.into());
897905
self.add_auth_headers(&mut headers)
898906
.map_err(|_| SubmitBlockErr::InvalidHeader)?;
899907

@@ -902,7 +910,7 @@ impl RelayClient {
902910
url.query_pairs_mut()
903911
.append_pair("cancellations", if cancellations { "1" } else { "0" });
904912

905-
let body = request.as_ssz_bytes();
913+
let body = submission.as_ssz_bytes();
906914
headers.insert(CONTENT_TYPE, HeaderValue::from_static(SSZ_CONTENT_TYPE));
907915

908916
let response = self
@@ -1262,6 +1270,7 @@ mod tests {
12621270
let sub_relay = SubmitBlockRequestWithMetadata {
12631271
submission,
12641272
metadata: BidMetadata {
1273+
sequence: 0,
12651274
value: BidValueMetadata {
12661275
coinbase_reward: Default::default(),
12671276
top_competitor_bid: None,

0 commit comments

Comments
 (0)