Skip to content

Commit 1cc7b47

Browse files
authored
Trace warn if order execution takes to long (#764)
## 📝 Summary This PR add a new config: max_order_execution_duration_warning_us (optional u64): If set, while building a block if an order execution duration is greater than this, we will log a warning with some info about the order. ## ✅ I have completed the following steps: * [X] Run `make lint` * [X] Run `make test` * [ ] Added tests (if applicable)
1 parent a21de88 commit 1cc7b47

File tree

10 files changed

+177
-25
lines changed

10 files changed

+177
-25
lines changed

crates/rbuilder-operator/src/flashbots_config.rs

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -170,7 +170,10 @@ impl LiveBuilderConfig for FlashbotsConfig {
170170
handle_subsidise_block(bidding_service.clone(), params)
171171
})?;
172172
let live_builder = live_builder.with_extra_rpc(module);
173-
let builders = create_builders(self.live_builders()?);
173+
let builders = create_builders(
174+
self.live_builders()?,
175+
self.base_config.max_order_execution_duration_warning(),
176+
);
174177
Ok(live_builder.with_builders(builders))
175178
}
176179

crates/rbuilder/src/bin/run-bundle-on-prefix.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -170,6 +170,7 @@ impl LandedBlockInfo {
170170
false,
171171
order_statistics,
172172
CancellationToken::new(),
173+
None,
173174
)?)
174175
}
175176
}

crates/rbuilder/src/building/builders/block_building_helper.rs

Lines changed: 67 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
use alloy_primitives::{utils::format_ether, U256};
1+
use alloy_primitives::{utils::format_ether, Address, TxHash, U256};
22
use reth_provider::StateProvider;
33
use std::{
44
cmp::max,
@@ -7,7 +7,7 @@ use std::{
77
};
88
use time::OffsetDateTime;
99
use tokio_util::sync::CancellationToken;
10-
use tracing::{debug, error, trace};
10+
use tracing::{debug, error, trace, warn};
1111

1212
use crate::{
1313
building::{
@@ -21,7 +21,10 @@ use crate::{
2121
telemetry::{self, add_block_fill_time, add_order_simulation_time},
2222
utils::{check_block_hash_reader_health, elapsed_ms, HistoricalBlockError},
2323
};
24-
use rbuilder_primitives::{order_statistics::OrderStatistics, SimValue, SimulatedOrder};
24+
use rbuilder_primitives::{
25+
order_statistics::OrderStatistics, SimValue, SimulatedOrder,
26+
TransactionSignedEcRecoveredWithBlobs,
27+
};
2528

2629
use super::Block;
2730

@@ -157,6 +160,10 @@ pub struct BlockBuildingHelperFromProvider<
157160
cancel_on_fatal_error: CancellationToken,
158161

159162
finalize_adjustment_state: Option<FinalizeAdjustmentState>,
163+
164+
/// If an order execution duration (commit_order) is greater than this, we will log a warning with some info about the order.
165+
/// This probably should not be implemented here and should be a wrapper but this is simpler.
166+
max_order_execution_duration_warning: Option<Duration>,
160167
}
161168

162169
#[derive(Debug, thiserror::Error)]
@@ -209,6 +216,7 @@ impl BlockBuildingHelperFromProvider<NullPartialBlockExecutionTracer> {
209216
discard_txs: bool,
210217
available_orders_statistics: OrderStatistics,
211218
cancel_on_fatal_error: CancellationToken,
219+
max_order_execution_duration_warning: Option<Duration>,
212220
) -> Result<Self, BlockBuildingHelperError> {
213221
BlockBuildingHelperFromProvider::new_with_execution_tracer(
214222
built_block_id,
@@ -220,6 +228,7 @@ impl BlockBuildingHelperFromProvider<NullPartialBlockExecutionTracer> {
220228
available_orders_statistics,
221229
cancel_on_fatal_error,
222230
NullPartialBlockExecutionTracer {},
231+
max_order_execution_duration_warning,
223232
)
224233
}
225234
}
@@ -244,6 +253,7 @@ impl<
244253
available_orders_statistics: OrderStatistics,
245254
cancel_on_fatal_error: CancellationToken,
246255
partial_block_execution_tracer: PartialBlockExecutionTracerType,
256+
max_order_execution_duration_warning: Option<Duration>,
247257
) -> Result<Self, BlockBuildingHelperError> {
248258
let last_committed_block = building_ctx.block() - 1;
249259
check_block_hash_reader_health(last_committed_block, &state_provider)?;
@@ -280,6 +290,7 @@ impl<
280290
built_block_trace,
281291
cancel_on_fatal_error,
282292
finalize_adjustment_state: None,
293+
max_order_execution_duration_warning,
283294
})
284295
}
285296

@@ -464,6 +475,52 @@ impl<
464475
};
465476
Ok(FinalizeBlockResult { block })
466477
}
478+
479+
fn trace_slow_order_execution(
480+
&self,
481+
order: &SimulatedOrder,
482+
sim_time: Duration,
483+
result: &Result<Result<ExecutionResult, ExecutionError>, CriticalCommitOrderError>,
484+
) {
485+
#[derive(Debug)]
486+
#[allow(dead_code)]
487+
struct TxInfo {
488+
pub hash: TxHash,
489+
pub signer: Address,
490+
pub to: Option<Address>,
491+
}
492+
impl From<&TransactionSignedEcRecoveredWithBlobs> for TxInfo {
493+
fn from(tx: &TransactionSignedEcRecoveredWithBlobs) -> Self {
494+
Self {
495+
hash: tx.hash(),
496+
signer: tx.signer(),
497+
to: tx.to(),
498+
}
499+
}
500+
}
501+
impl TxInfo {
502+
fn parse_order(order: &SimulatedOrder) -> Vec<Self> {
503+
order
504+
.order
505+
.list_txs()
506+
.iter()
507+
.map(|(tx, _)| (*tx).into())
508+
.collect::<Vec<_>>()
509+
}
510+
}
511+
match result {
512+
Ok(Ok(result)) => {
513+
warn!(?sim_time,builder_name=self.builder_name,id = ?order.id(),tob_sim_value = ?order.sim_value,txs = ?TxInfo::parse_order(order),
514+
space_used = ?result.space_used,coinbase_profit = ?result.coinbase_profit,inplace_sim = ?result.inplace_sim, "Slow order ok execution");
515+
}
516+
Ok(Err(err)) => {
517+
warn!(?err,?sim_time,builder_name=self.builder_name,id = ?order.id(),tob_sim_value = ?order.sim_value,txs = ?TxInfo::parse_order(order), "Slow order failed execution.");
518+
}
519+
Err(err) => {
520+
warn!(?err,?sim_time,builder_name=self.builder_name,id = ?order.id(),tob_sim_value = ?order.sim_value,txs = ?TxInfo::parse_order(order), "Slow order critical execution error.");
521+
}
522+
}
523+
}
467524
}
468525

469526
impl<
@@ -487,6 +544,13 @@ impl<
487544
result_filter,
488545
);
489546
let sim_time = start.elapsed();
547+
if self
548+
.max_order_execution_duration_warning
549+
.is_some_and(|max_dur| sim_time > max_dur)
550+
{
551+
self.trace_slow_order_execution(order, sim_time, &result);
552+
}
553+
490554
let (result, sim_ok) = match result {
491555
Ok(ok_result) => match ok_result {
492556
Ok(res) => {

crates/rbuilder/src/building/builders/mod.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@ use std::{
2727
atomic::{AtomicU64, Ordering},
2828
Arc,
2929
},
30+
time::Duration,
3031
};
3132
use tokio::sync::{
3233
broadcast,
@@ -91,6 +92,7 @@ pub struct LiveBuilderInput<P> {
9192
pub cancel: CancellationToken,
9293
pub built_block_cache: Arc<BuiltBlockCache>,
9394
pub built_block_id_source: Arc<BuiltBlockIdSource>,
95+
pub max_order_execution_duration_warning: Option<Duration>,
9496
}
9597

9698
/// Struct that helps reading new orders/cancellations

crates/rbuilder/src/building/builders/ordering_builder.rs

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -116,6 +116,7 @@ pub fn run_ordering_builder<P, OrderPriorityType>(
116116
input.builder_name,
117117
input.ctx,
118118
config.clone(),
119+
input.max_order_execution_duration_warning,
119120
input.built_block_cache,
120121
);
121122

@@ -185,6 +186,7 @@ where
185186
input.builder_name,
186187
input.ctx.clone(),
187188
ordering_config,
189+
None,
188190
Arc::new(BuiltBlockCache::new()),
189191
);
190192
let mut block_builder = builder.build_block_with_execution_tracer(
@@ -208,6 +210,8 @@ pub struct OrderingBuilderContext {
208210
builder_name: String,
209211
ctx: BlockBuildingContext,
210212
config: OrderingBuilderConfig,
213+
/// See [BlockBuildingHelperFromProvider::max_order_execution_duration_warning]
214+
max_order_execution_duration_warning: Option<Duration>,
211215

212216
// caches
213217
local_ctx: ThreadBlockBuildingContext,
@@ -224,6 +228,7 @@ impl OrderingBuilderContext {
224228
builder_name: String,
225229
ctx: BlockBuildingContext,
226230
config: OrderingBuilderConfig,
231+
max_order_execution_duration_warning: Option<Duration>,
227232
built_block_cache: Arc<BuiltBlockCache>,
228233
) -> Self {
229234
Self {
@@ -235,6 +240,7 @@ impl OrderingBuilderContext {
235240
failed_orders: HashSet::default(),
236241
order_attempts: HashMap::default(),
237242
built_block_cache,
243+
max_order_execution_duration_warning,
238244
}
239245
}
240246

@@ -285,6 +291,7 @@ impl OrderingBuilderContext {
285291
block_orders.orders_statistics(),
286292
cancel_block,
287293
partial_block_execution_tracer,
294+
self.max_order_execution_duration_warning,
288295
)?;
289296
self.fill_orders(
290297
&mut block_building_helper,
@@ -449,15 +456,21 @@ impl OrderingBuilderContext {
449456
pub struct OrderingBuildingAlgorithm<OrderPriorityType> {
450457
config: OrderingBuilderConfig,
451458
name: String,
459+
max_order_execution_duration_warning: Option<Duration>,
452460
/// The ordering priority type used to sort simulated orders.
453461
order_priority: PhantomData<OrderPriorityType>,
454462
}
455463

456464
impl<OrderPriorityType> OrderingBuildingAlgorithm<OrderPriorityType> {
457-
pub fn new(config: OrderingBuilderConfig, name: String) -> Self {
465+
pub fn new(
466+
config: OrderingBuilderConfig,
467+
max_order_execution_duration_warning: Option<Duration>,
468+
name: String,
469+
) -> Self {
458470
Self {
459471
config,
460472
name,
473+
max_order_execution_duration_warning,
461474
order_priority: PhantomData,
462475
}
463476
}
@@ -483,6 +496,7 @@ where
483496
cancel: input.cancel,
484497
built_block_cache: input.built_block_cache,
485498
built_block_id_source: input.built_block_id_source,
499+
max_order_execution_duration_warning: self.max_order_execution_duration_warning,
486500
};
487501
run_ordering_builder::<P, OrderPriorityType>(live_input, &self.config);
488502
}

crates/rbuilder/src/building/builders/parallel_builder/block_building_result_assembler.rs

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,10 @@ use super::{
55
use ahash::HashMap;
66
use alloy_primitives::utils::format_ether;
77
use reth_provider::StateProvider;
8-
use std::{sync::Arc, time::Instant};
8+
use std::{
9+
sync::Arc,
10+
time::{Duration, Instant},
11+
};
912
use time::OffsetDateTime;
1013
use tokio_util::sync::CancellationToken;
1114
use tracing::{info_span, trace};
@@ -39,6 +42,7 @@ pub struct BlockBuildingResultAssembler {
3942
run_id: u64,
4043
last_version: Option<u64>,
4144
built_block_id_source: Arc<BuiltBlockIdSource>,
45+
max_order_execution_duration_warning: Option<Duration>,
4246
}
4347

4448
impl BlockBuildingResultAssembler {
@@ -60,6 +64,7 @@ impl BlockBuildingResultAssembler {
6064
builder_name: String,
6165
sink: Option<UnfinishedBuiltBlocksInput>,
6266
built_block_id_source: Arc<BuiltBlockIdSource>,
67+
max_order_execution_duration_warning: Option<Duration>,
6368
) -> Self {
6469
Self {
6570
state,
@@ -73,6 +78,7 @@ impl BlockBuildingResultAssembler {
7378
run_id: 0,
7479
last_version: None,
7580
built_block_id_source,
81+
max_order_execution_duration_warning,
7682
}
7783
}
7884

@@ -189,6 +195,7 @@ impl BlockBuildingResultAssembler {
189195
self.discard_txs,
190196
OrderStatistics::default(),
191197
self.cancellation_token.clone(),
198+
self.max_order_execution_duration_warning,
192199
)?;
193200
block_building_helper.set_trace_orders_closed_at(orders_closed_at);
194201

@@ -263,6 +270,7 @@ impl BlockBuildingResultAssembler {
263270
self.discard_txs,
264271
OrderStatistics::default(),
265272
CancellationToken::new(),
273+
self.max_order_execution_duration_warning,
266274
)?;
267275

268276
block_building_helper.set_trace_orders_closed_at(orders_closed_at);

crates/rbuilder/src/building/builders/parallel_builder/mod.rs

Lines changed: 15 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@ use simulation_cache::SharedSimulationCache;
2222
use std::{
2323
sync::{mpsc as std_mpsc, Arc},
2424
thread,
25-
time::Instant,
25+
time::{Duration, Instant},
2626
};
2727
use task::*;
2828
use time::OffsetDateTime;
@@ -134,6 +134,7 @@ where
134134
input.builder_name.clone(),
135135
Some(input.sink.clone()),
136136
input.built_block_id_source.clone(),
137+
input.max_order_execution_duration_warning,
137138
);
138139

139140
let order_intake_consumer = OrderIntakeStore::new(input.input);
@@ -352,6 +353,7 @@ where
352353
String::from("backtest_builder"),
353354
None,
354355
Arc::new(BuiltBlockIdSource::new()),
356+
None,
355357
);
356358
let assembler_duration = assembler_start.elapsed();
357359

@@ -394,12 +396,21 @@ where
394396
#[derive(Debug)]
395397
pub struct ParallelBuildingAlgorithm {
396398
config: ParallelBuilderConfig,
399+
max_order_execution_duration_warning: Option<Duration>,
397400
name: String,
398401
}
399402

400403
impl ParallelBuildingAlgorithm {
401-
pub fn new(config: ParallelBuilderConfig, name: String) -> Self {
402-
Self { config, name }
404+
pub fn new(
405+
config: ParallelBuilderConfig,
406+
max_order_execution_duration_warning: Option<Duration>,
407+
name: String,
408+
) -> Self {
409+
Self {
410+
config,
411+
max_order_execution_duration_warning,
412+
name,
413+
}
403414
}
404415
}
405416

@@ -421,6 +432,7 @@ where
421432
cancel: input.cancel,
422433
built_block_cache: input.built_block_cache,
423434
built_block_id_source: input.built_block_id_source,
435+
max_order_execution_duration_warning: self.max_order_execution_duration_warning,
424436
};
425437
run_parallel_builder(live_input, &self.config);
426438
}

crates/rbuilder/src/live_builder/base_config.rs

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -140,6 +140,9 @@ pub struct BaseConfig {
140140
/// List of `builders` to be used for live building
141141
pub live_builders: Vec<String>,
142142

143+
/// See [BlockBuildingHelperFromProvider::max_order_execution_duration_warning]
144+
pub max_order_execution_duration_warning_us: Option<u64>,
145+
143146
/// Config for IPC state provider
144147
pub ipc_provider: Option<IpcProviderConfig>,
145148

@@ -466,6 +469,10 @@ impl BaseConfig {
466469

467470
Ok(path_expanded.parse()?)
468471
}
472+
pub fn max_order_execution_duration_warning(&self) -> Option<Duration> {
473+
self.max_order_execution_duration_warning_us
474+
.map(Duration::from_micros)
475+
}
469476
}
470477

471478
pub const DEFAULT_CL_NODE_URL: &str = "http://127.0.0.1:3500";
@@ -530,6 +537,7 @@ impl Default for BaseConfig {
530537
orderflow_tracing_store_path: None,
531538
orderflow_tracing_max_blocks: 0,
532539
system_recipient_allowlist: Vec::new(),
540+
max_order_execution_duration_warning_us: None,
533541
}
534542
}
535543
}

0 commit comments

Comments
 (0)