Skip to content
This repository was archived by the owner on Jan 12, 2026. It is now read-only.

Commit 790bb25

Browse files
committed
feat: add --builder.enforce-resource-metering flag
When false (default), transactions that exceed execution time limits are logged and metrics recorded, but not rejected. Only the first transaction to exceed the limit triggers logging/metrics. When true, transactions exceeding limits are marked invalid and excluded from the block.
1 parent e11c195 commit 790bb25

9 files changed

Lines changed: 58 additions & 11 deletions

File tree

crates/op-rbuilder/src/args/op.rs

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -51,7 +51,10 @@ pub struct OpRbuilderArgs {
5151
/// Whether to enable TIPS Resource Metering
5252
#[arg(long = "builder.enable-resource-metering", default_value = "false")]
5353
pub enable_resource_metering: bool,
54-
/// Whether to enable TIPS Resource Metering
54+
/// Whether to enforce resource metering limits (reject transactions that exceed limits)
55+
#[arg(long = "builder.enforce-resource-metering", default_value = "false")]
56+
pub enforce_resource_metering: bool,
57+
/// Buffer size for resource metering data
5558
#[arg(
5659
long = "builder.resource-metering-buffer-size",
5760
default_value = "10000"

crates/op-rbuilder/src/base/context.rs

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,15 +8,18 @@ use super::metrics::BaseMetrics;
88
pub struct BaseBuilderCtx {
99
/// Block execution time limit in microseconds
1010
pub block_execution_time_limit_us: u128,
11+
/// Whether to enforce resource metering limits
12+
pub enforce_limits: bool,
1113
/// Base-specific metrics
1214
pub metrics: BaseMetrics,
1315
}
1416

1517
impl BaseBuilderCtx {
1618
/// Create a new BaseBuilderCtx with the given execution time limit.
17-
pub fn new(block_execution_time_limit_us: u128) -> Self {
19+
pub fn new(block_execution_time_limit_us: u128, enforce_limits: bool) -> Self {
1820
Self {
1921
block_execution_time_limit_us,
22+
enforce_limits,
2023
metrics: Default::default(),
2124
}
2225
}

crates/op-rbuilder/src/base/execution.rs

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,19 @@ pub enum BaseLimitExceeded {
3838
}
3939

4040
impl BaseLimitExceeded {
41+
/// Returns the tx usage that caused the limit to be exceeded.
42+
pub fn usage(&self) -> BaseTxUsage {
43+
match self {
44+
Self::ExecutionTime { tx_us, .. } => BaseTxUsage {
45+
execution_time_us: *tx_us,
46+
},
47+
}
48+
}
49+
4150
/// Log and record metrics for this limit exceeded event.
51+
///
52+
/// Only logs/records if this is the first tx to exceed the limit
53+
/// (i.e., cumulative was within the limit before this tx).
4254
pub fn log_and_record(&self, metrics: &BaseMetrics) {
4355
match self {
4456
Self::ExecutionTime {
@@ -49,6 +61,11 @@ impl BaseLimitExceeded {
4961
tx_gas,
5062
remaining_gas,
5163
} => {
64+
// Only log/record for the first tx that exceeds the limit
65+
if *cumulative_us > *limit_us {
66+
return;
67+
}
68+
5269
let remaining_us = limit_us.saturating_sub(*cumulative_us);
5370
let exceeded_by_us = tx_us.saturating_sub(remaining_us);
5471
warn!(
@@ -97,6 +114,7 @@ impl BaseExecutionState {
97114
let total = self
98115
.cumulative_execution_time_us
99116
.saturating_add(usage.execution_time_us);
117+
100118
if total > execution_time_limit_us {
101119
let remaining_gas = block_gas_limit.saturating_sub(cumulative_gas_used);
102120
return Err(BaseLimitExceeded::ExecutionTime {

crates/op-rbuilder/src/base/flashblocks.rs

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -10,19 +10,22 @@ pub struct BaseFlashblocksCtx {
1010
pub target_execution_time_us: u128,
1111
/// Execution time (us) limit per flashblock batch
1212
pub execution_time_per_batch_us: u128,
13+
/// Whether to enforce resource metering limits
14+
pub enforce_limits: bool,
1315
}
1416

1517
impl BaseFlashblocksCtx {
1618
/// Create a new BaseFlashblocksCtx with the given execution time limit per batch.
17-
pub fn new(execution_time_per_batch_us: u128) -> Self {
19+
pub fn new(execution_time_per_batch_us: u128, enforce_limits: bool) -> Self {
1820
Self {
1921
target_execution_time_us: execution_time_per_batch_us,
2022
execution_time_per_batch_us,
23+
enforce_limits,
2124
}
2225
}
2326

2427
/// Advance to the next batch, updating the target execution time.
25-
///
28+
///
2629
/// Unlike gas and DA, execution time does not carry over to the next batch.
2730
pub fn next(self, cumulative_execution_time_us: u128) -> Self {
2831
Self {
@@ -34,6 +37,6 @@ impl BaseFlashblocksCtx {
3437

3538
impl From<&BaseFlashblocksCtx> for BaseBuilderCtx {
3639
fn from(ctx: &BaseFlashblocksCtx) -> Self {
37-
BaseBuilderCtx::new(ctx.target_execution_time_us)
40+
BaseBuilderCtx::new(ctx.target_execution_time_us, ctx.enforce_limits)
3841
}
3942
}

crates/op-rbuilder/src/builders/context.rs

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -500,8 +500,11 @@ impl<ExtraCtx: Debug + Default> OpPayloadBuilderCtx<ExtraCtx> {
500500
Ok(usage) => usage,
501501
Err(exceeded) => {
502502
exceeded.log_and_record(&self.base_ctx.metrics);
503-
best_txs.mark_invalid(tx.signer(), tx.nonce());
504-
continue;
503+
if self.base_ctx.enforce_limits {
504+
best_txs.mark_invalid(tx.signer(), tx.nonce());
505+
continue;
506+
}
507+
exceeded.usage()
505508
}
506509
};
507510

crates/op-rbuilder/src/builders/flashblocks/ctx.rs

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -55,7 +55,10 @@ impl OpPayloadSyncerCtx {
5555
max_gas_per_txn: builder_config.max_gas_per_txn,
5656
metrics,
5757
resource_metering: builder_config.resource_metering,
58-
base_ctx: BaseBuilderCtx::new(builder_config.block_time.as_micros()),
58+
base_ctx: BaseBuilderCtx::new(
59+
builder_config.block_time.as_micros(),
60+
builder_config.enforce_resource_metering,
61+
),
5962
})
6063
}
6164

crates/op-rbuilder/src/builders/flashblocks/payload.rs

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -288,7 +288,10 @@ where
288288
max_gas_per_txn: self.config.max_gas_per_txn,
289289
address_gas_limiter: self.address_gas_limiter.clone(),
290290
resource_metering: self.config.resource_metering.clone(),
291-
base_ctx: BaseBuilderCtx::new(self.config.block_time.as_micros()),
291+
base_ctx: BaseBuilderCtx::new(
292+
self.config.block_time.as_micros(),
293+
self.config.enforce_resource_metering,
294+
),
292295
})
293296
}
294297

@@ -471,7 +474,10 @@ where
471474
da_footprint_per_batch,
472475
disable_state_root,
473476
target_da_footprint_for_batch: da_footprint_per_batch,
474-
base_ctx: BaseFlashblocksCtx::new(self.config.specific.interval.as_micros()),
477+
base_ctx: BaseFlashblocksCtx::new(
478+
self.config.specific.interval.as_micros(),
479+
self.config.enforce_resource_metering,
480+
),
475481
};
476482

477483
let mut fb_cancel = block_cancel.child_token();

crates/op-rbuilder/src/builders/mod.rs

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -130,6 +130,9 @@ pub struct BuilderConfig<Specific: Clone> {
130130

131131
/// Resource metering context
132132
pub resource_metering: ResourceMetering,
133+
134+
/// Whether to enforce resource metering limits
135+
pub enforce_resource_metering: bool,
133136
}
134137

135138
impl<S: Debug + Clone> core::fmt::Debug for BuilderConfig<S> {
@@ -171,6 +174,7 @@ impl<S: Default + Clone> Default for BuilderConfig<S> {
171174
max_gas_per_txn: None,
172175
gas_limiter_config: GasLimiterArgs::default(),
173176
resource_metering: ResourceMetering::default(),
177+
enforce_resource_metering: false,
174178
}
175179
}
176180
}
@@ -197,6 +201,7 @@ where
197201
args.enable_resource_metering,
198202
args.resource_metering_buffer_size,
199203
),
204+
enforce_resource_metering: args.enforce_resource_metering,
200205
specific: S::try_from(args)?,
201206
})
202207
}

crates/op-rbuilder/src/builders/standard/payload.rs

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -253,7 +253,10 @@ where
253253
max_gas_per_txn: self.config.max_gas_per_txn,
254254
address_gas_limiter: self.address_gas_limiter.clone(),
255255
resource_metering: self.config.resource_metering.clone(),
256-
base_ctx: BaseBuilderCtx::new(self.config.block_time.as_micros()),
256+
base_ctx: BaseBuilderCtx::new(
257+
self.config.block_time.as_micros(),
258+
self.config.enforce_resource_metering,
259+
),
257260
};
258261

259262
let builder = OpBuilder::new(best);

0 commit comments

Comments
 (0)