Skip to content

Commit 9a653ff

Browse files
committed
feat: platform-specific limit extension
1 parent 0c12e18 commit 9a653ff

File tree

16 files changed

+96
-32
lines changed

16 files changed

+96
-32
lines changed

examples/custom-bundle-type.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,7 @@ impl Platform for CustomPlatform {
3232
type Bundle = CustomBundleType;
3333
type DefaultLimits = types::DefaultLimits<Optimism>;
3434
type EvmConfig = types::EvmConfig<Optimism>;
35+
type ExtraLimits = types::ExtraLimits<Optimism>;
3536
type NodeTypes = types::NodeTypes<Optimism>;
3637
type PooledTransaction = types::PooledTransaction<Optimism>;
3738

src/pipelines/exec/scope.rs

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -82,7 +82,7 @@ impl<P: Platform> RootScope<P> {
8282
}
8383

8484
/// Given a path to a step in the pipeline, returns its current limits.
85-
pub(crate) fn limits_of(&self, step_path: &StepPath) -> Option<Limits> {
85+
pub(crate) fn limits_of(&self, step_path: &StepPath) -> Option<Limits<P>> {
8686
self
8787
.root
8888
.read()
@@ -169,7 +169,7 @@ fn scope_of(step: &StepPath) -> StepPath {
169169
/// that contain it. When a scope is active, then all its parent scopes are
170170
/// active as well.
171171
pub(crate) struct Scope<P: Platform> {
172-
limits: Limits,
172+
limits: Limits<P>,
173173
metrics: Metrics,
174174
limits_factory: Option<Arc<dyn ScopedLimits<P>>>,
175175
entered_at: Option<Instant>,
@@ -197,7 +197,7 @@ impl<P: Platform> Scope<P> {
197197
}
198198

199199
/// Returns the payload limits for steps running within the current scope.
200-
pub(crate) const fn limits(&self) -> &Limits {
200+
pub(crate) const fn limits(&self) -> &Limits<P> {
201201
&self.limits
202202
}
203203
}
@@ -240,7 +240,7 @@ impl<P: Platform> Scope<P> {
240240
}
241241
}
242242

243-
fn enter(&mut self, checkpoint: &Checkpoint<P>, enclosing: &Limits) {
243+
fn enter(&mut self, checkpoint: &Checkpoint<P>, enclosing: &Limits<P>) {
244244
assert!(!self.is_active(), "Scope is already active");
245245

246246
// refresh limits of this scope
@@ -308,7 +308,7 @@ impl<P: Platform> Scope<P> {
308308
checkpoint: &Checkpoint<P>,
309309
path: &StepPath,
310310
root_name: &str,
311-
enclosing: &Limits,
311+
enclosing: &Limits<P>,
312312
) -> Self {
313313
let limits_factory = local.limits().cloned();
314314
let scope_limits = limits_factory

src/pipelines/limits.rs

Lines changed: 8 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,8 @@ pub trait ScopedLimits<P: Platform>: Send + Sync + 'static {
1818
/// As an input this method receives the current payload checkpoint and the
1919
/// limits imposed by its parent scope (or limits created by
2020
/// `PlatformLimits`).
21-
fn create(&self, payload: &Checkpoint<P>, enclosing: &Limits) -> Limits;
21+
fn create(&self, payload: &Checkpoint<P>, enclosing: &Limits<P>)
22+
-> Limits<P>;
2223
}
2324

2425
/// Convenience trait that allows API users to either use a `ScopedLimits` type
@@ -34,11 +35,11 @@ impl<T: ScopedLimits<P>, P: Platform> IntoScopedLimits<P, Variant<0>> for T {
3435
}
3536
}
3637

37-
impl<P: Platform> IntoScopedLimits<P, Variant<1>> for Limits {
38+
impl<P: Platform> IntoScopedLimits<P, Variant<1>> for Limits<P> {
3839
fn into_scoped_limits(self) -> impl ScopedLimits<P> {
39-
struct FixedLimits(Limits);
40-
impl<P: Platform> ScopedLimits<P> for FixedLimits {
41-
fn create(&self, _: &Checkpoint<P>, _: &Limits) -> Limits {
40+
struct FixedLimits<P: Platform>(Limits<P>);
41+
impl<P: Platform> ScopedLimits<P> for FixedLimits<P> {
42+
fn create(&self, _: &Checkpoint<P>, _: &Limits<P>) -> Limits<P> {
4243
self.0
4344
}
4445
}
@@ -104,7 +105,7 @@ impl<T> From<Zero> for ScaleOp<T> {
104105
}
105106

106107
impl<P: Platform> ScopedLimits<P> for Scaled {
107-
fn create(&self, _: &Checkpoint<P>, enclosing: &Limits) -> Limits {
108+
fn create(&self, _: &Checkpoint<P>, enclosing: &Limits<P>) -> Limits<P> {
108109
self.from(enclosing)
109110
}
110111
}
@@ -121,7 +122,7 @@ impl Scaled {
121122
}
122123
}
123124

124-
pub fn from(&self, limits: &Limits) -> Limits {
125+
pub fn from<P: Platform>(&self, limits: &Limits<P>) -> Limits<P> {
125126
let mut limits = *limits;
126127

127128
if let Some(ref op) = self.gas {

src/pipelines/mod.rs

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -409,12 +409,20 @@ pub mod traits {
409409
}
410410

411411
pub trait PlatformExecBounds<P: Platform>:
412-
Platform<NodeTypes = types::NodeTypes<P>, EvmConfig = types::EvmConfig<P>>
412+
Platform<
413+
NodeTypes = types::NodeTypes<P>,
414+
EvmConfig = types::EvmConfig<P>,
415+
ExtraLimits = types::ExtraLimits<P>,
416+
>
413417
{
414418
}
415419

416420
impl<T, P: Platform> PlatformExecBounds<T> for P where
417-
T: Platform<NodeTypes = types::NodeTypes<P>, EvmConfig = types::EvmConfig<P>>
421+
T: Platform<
422+
NodeTypes = types::NodeTypes<P>,
423+
EvmConfig = types::EvmConfig<P>,
424+
ExtraLimits = types::ExtraLimits<P>,
425+
>
418426
{
419427
}
420428
}

src/pipelines/step/context.rs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ use {
1616
#[derive(Debug, Clone)]
1717
pub struct StepContext<P: Platform> {
1818
block: BlockContext<P>,
19-
limits: Limits,
19+
limits: Limits<P>,
2020
events_bus: Arc<EventsBus<P>>,
2121
started_at: Option<Instant>,
2222
}
@@ -25,7 +25,7 @@ impl<P: Platform> StepContext<P> {
2525
pub(crate) fn new(
2626
block: &BlockContext<P>,
2727
step: &StepNavigator<P>,
28-
limits: Limits,
28+
limits: Limits<P>,
2929
in_scope_since: Option<Instant>,
3030
) -> Self {
3131
let block = block.clone();
@@ -60,7 +60,7 @@ impl<P: Platform> StepContext<P> {
6060
}
6161

6262
/// Payload limits for the scope of the step.
63-
pub const fn limits(&self) -> &Limits {
63+
pub const fn limits(&self) -> &Limits<P> {
6464
&self.limits
6565
}
6666

src/pipelines/tests/syntax.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -104,7 +104,7 @@ fn flashblocks_example_closure() {
104104
#[derive(Debug)]
105105
struct FlashblockLimits(FlashblocksConfig);
106106
impl<P: Platform> ScopedLimits<P> for FlashblockLimits {
107-
fn create(&self, _: &Checkpoint<P>, _: &Limits) -> Limits {
107+
fn create(&self, _: &Checkpoint<P>, _: &Limits<P>) -> Limits<P> {
108108
unimplemented!()
109109
}
110110
}

src/platform/ethereum/limits.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@ impl EthereumDefaultLimits {
2323
}
2424

2525
impl PlatformLimits<Ethereum> for EthereumDefaultLimits {
26-
fn create(&self, block: &BlockContext<Ethereum>) -> Limits {
26+
fn create(&self, block: &BlockContext<Ethereum>) -> Limits<Ethereum> {
2727
let timestamp = block.attributes().timestamp();
2828
let parent_gas_limit = block.parent().gas_limit();
2929
let gas_limit = self.0.gas_limit(parent_gas_limit);

src/platform/ethereum/mod.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -69,6 +69,7 @@ impl Platform for Ethereum {
6969
type Bundle = FlashbotsBundle<Self>;
7070
type DefaultLimits = EthereumDefaultLimits;
7171
type EvmConfig = EthEvmConfig;
72+
type ExtraLimits = ();
7273
type NodeTypes = EthereumNode;
7374
type PooledTransaction = EthPooledTransaction;
7475

src/platform/limits.rs

Lines changed: 27 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ use {
22
crate::{alloy::eips::eip7840::BlobParams, prelude::*},
33
core::time::Duration,
44
serde::{Deserialize, Serialize},
5-
std::time::Instant,
5+
std::{fmt::Debug, time::Instant},
66
};
77

88
/// This type specifies the limits that payloads should stay within.
@@ -12,8 +12,8 @@ use {
1212
/// - Limits are specified on a pipeline scope level. If a pipeline scope
1313
/// doesn't explicitly specify its limits it will inherit its enclosing scope
1414
/// limits.
15-
#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
16-
pub struct Limits {
15+
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
16+
pub struct Limits<P: Platform> {
1717
/// The maximum cumulative gas that can be used in the block.
1818
/// This includes all transactions, epilogues, prologues, and other
1919
/// gas-consuming operations.
@@ -24,12 +24,30 @@ pub struct Limits {
2424

2525
/// The maximum number of transactions that can be included in the block.
2626
///
27-
/// This is not a standard known ethereum limit, however it can be imposed by
28-
/// custom limits factories.
27+
/// This is not a standard known ethereum limit; however, it can be imposed
28+
/// by custom limits factories.
2929
pub max_transactions: Option<usize>,
3030

3131
/// The time a pipeline is allowed to spend on execution.
3232
pub deadline: Option<Duration>,
33+
34+
/// Per platform extension.
35+
pub ext: P::ExtraLimits,
36+
}
37+
38+
impl<P: Platform> Copy for Limits<P> {}
39+
40+
/// This trait must be implemented by extension limits
41+
pub trait LimitExtension:
42+
Copy + Debug + Default + Send + Sync + 'static
43+
{
44+
fn clamp(&self, other: &Self) -> Self;
45+
}
46+
47+
impl LimitExtension for () {
48+
fn clamp(&self, _: &Self) -> Self {
49+
()
50+
}
3351
}
3452

3553
/// Types implementing this trait are responsible for calculating top-level
@@ -39,16 +57,17 @@ pub struct Limits {
3957
/// Implementations of this type are always called exactly once at the beginning
4058
/// of a new payload job.
4159
pub trait PlatformLimits<P: Platform>: Default + Send + Sync + 'static {
42-
fn create(&self, block: &BlockContext<P>) -> Limits;
60+
fn create(&self, block: &BlockContext<P>) -> Limits<P>;
4361
}
4462

45-
impl Limits {
63+
impl<P: Platform> Limits<P> {
4664
pub fn gas_limit(gas_limit: u64) -> Self {
4765
Self {
4866
gas_limit,
4967
blob_params: None,
5068
deadline: None,
5169
max_transactions: None,
70+
ext: P::ExtraLimits::default(),
5271
}
5372
}
5473

@@ -109,6 +128,7 @@ impl Limits {
109128
},
110129
max_transactions: self.max_transactions.min(other.max_transactions),
111130
deadline: self.deadline.min(other.deadline),
131+
ext: self.ext.clamp(&other.ext),
112132
}
113133
}
114134
}

src/platform/mod.rs

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,7 @@ mod optimism;
3131
#[cfg(feature = "optimism")]
3232
pub use optimism::*;
3333

34-
/// This type abstracts the platform specific types of the underlying node that
34+
/// This type abstracts the platform-specific types of the underlying node that
3535
/// is building block payloads.
3636
///
3737
/// The payload builder API is agnostic to the underlying payload types, header
@@ -85,6 +85,11 @@ pub trait Platform:
8585
/// type will be used automatically.
8686
type DefaultLimits: PlatformLimits<Self>;
8787

88+
/// Type that can provide extra limits for the payload building process.
89+
/// This type is used to provide platform-specific limits that are not
90+
/// covered by the default `Limits` type.
91+
type ExtraLimits: LimitExtension;
92+
8893
/// Instantiate the EVM configuration for the platform with a given chain
8994
/// specification.
9095
fn evm_config<P>(chainspec: Arc<types::ChainSpec<P>>) -> Self::EvmConfig

0 commit comments

Comments
 (0)