@@ -14,7 +14,7 @@ use cb_common::{
14
14
pbs:: {
15
15
error:: { PbsError , ValidationError } ,
16
16
GetHeaderParams , GetHeaderResponse , RelayClient , VersionedResponse , EMPTY_TX_ROOT_HASH ,
17
- HEADER_START_TIME_UNIX_MS ,
17
+ HEADER_START_TIME_UNIX_MS , HEADER_TIMEOUT_MS ,
18
18
} ,
19
19
signature:: verify_signed_message,
20
20
types:: { BlsPublicKey , BlsSignature , Chain } ,
@@ -81,6 +81,19 @@ pub async fn get_header<S: BuilderApiState>(
81
81
return Ok ( None ) ;
82
82
}
83
83
84
+ // Use the minimum of the time left and the user provided timeout header
85
+ let max_timeout_ms = req_headers
86
+ . get ( HEADER_TIMEOUT_MS )
87
+ . map ( |header| match header. to_str ( ) . ok ( ) . and_then ( |v| v. parse :: < u64 > ( ) . ok ( ) ) {
88
+ None | Some ( 0 ) => {
89
+ // Header can't be stringified, or parsed, or it's set to 0
90
+ warn ! ( ?header, "invalid user-supplied timeout header, using {max_timeout_ms}ms" ) ;
91
+ max_timeout_ms
92
+ }
93
+ Some ( user_timeout) => user_timeout. min ( max_timeout_ms) ,
94
+ } )
95
+ . unwrap_or ( max_timeout_ms) ;
96
+
84
97
// prepare headers, except for start time which is set in `send_one_get_header`
85
98
let mut send_headers = HeaderMap :: new ( ) ;
86
99
send_headers. insert ( USER_AGENT , get_user_agent_with_version ( & req_headers) ?) ;
@@ -301,6 +314,10 @@ async fn send_one_get_header(
301
314
let start_request_time = utcnow_ms ( ) ;
302
315
req_config. headers . insert ( HEADER_START_TIME_UNIX_MS , HeaderValue :: from ( start_request_time) ) ;
303
316
317
+ // The timeout header indicating how long a relay has to respond, so they can
318
+ // minimize timing games without losing the bid
319
+ req_config. headers . insert ( HEADER_TIMEOUT_MS , HeaderValue :: from ( req_config. timeout_ms ) ) ;
320
+
304
321
let start_request = Instant :: now ( ) ;
305
322
let res = match relay
306
323
. client
0 commit comments