Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions examples/custom-bundle-type.rs
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ impl Platform for CustomPlatform {
type Bundle = CustomBundleType;
type DefaultLimits = types::DefaultLimits<Optimism>;
type EvmConfig = types::EvmConfig<Optimism>;
type ExtraLimits = types::ExtraLimits<Optimism>;
type NodeTypes = types::NodeTypes<Optimism>;
type PooledTransaction = types::PooledTransaction<Optimism>;

Expand Down
10 changes: 5 additions & 5 deletions src/pipelines/exec/scope.rs
Original file line number Diff line number Diff line change
Expand Up @@ -82,7 +82,7 @@ impl<P: Platform> RootScope<P> {
}

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

/// Returns the payload limits for steps running within the current scope.
pub(crate) const fn limits(&self) -> &Limits {
pub(crate) const fn limits(&self) -> &Limits<P> {
&self.limits
}
}
Expand Down Expand Up @@ -240,7 +240,7 @@ impl<P: Platform> Scope<P> {
}
}

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

// refresh limits of this scope
Expand Down Expand Up @@ -308,7 +308,7 @@ impl<P: Platform> Scope<P> {
checkpoint: &Checkpoint<P>,
path: &StepPath,
root_name: &str,
enclosing: &Limits,
enclosing: &Limits<P>,
) -> Self {
let limits_factory = local.limits().cloned();
let scope_limits = limits_factory
Expand Down
15 changes: 8 additions & 7 deletions src/pipelines/limits.rs
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,8 @@ pub trait ScopedLimits<P: Platform>: Send + Sync + 'static {
/// As an input this method receives the current payload checkpoint and the
/// limits imposed by its parent scope (or limits created by
/// `PlatformLimits`).
fn create(&self, payload: &Checkpoint<P>, enclosing: &Limits) -> Limits;
fn create(&self, payload: &Checkpoint<P>, enclosing: &Limits<P>)
-> Limits<P>;
}

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

impl<P: Platform> IntoScopedLimits<P, Variant<1>> for Limits {
impl<P: Platform> IntoScopedLimits<P, Variant<1>> for Limits<P> {
fn into_scoped_limits(self) -> impl ScopedLimits<P> {
struct FixedLimits(Limits);
impl<P: Platform> ScopedLimits<P> for FixedLimits {
fn create(&self, _: &Checkpoint<P>, _: &Limits) -> Limits {
struct FixedLimits<P: Platform>(Limits<P>);
impl<P: Platform> ScopedLimits<P> for FixedLimits<P> {
fn create(&self, _: &Checkpoint<P>, _: &Limits<P>) -> Limits<P> {
self.0
}
}
Expand Down Expand Up @@ -104,7 +105,7 @@ impl<T> From<Zero> for ScaleOp<T> {
}

impl<P: Platform> ScopedLimits<P> for Scaled {
fn create(&self, _: &Checkpoint<P>, enclosing: &Limits) -> Limits {
fn create(&self, _: &Checkpoint<P>, enclosing: &Limits<P>) -> Limits<P> {
self.from(enclosing)
}
}
Expand All @@ -121,7 +122,7 @@ impl Scaled {
}
}

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

if let Some(ref op) = self.gas {
Expand Down
12 changes: 10 additions & 2 deletions src/pipelines/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -409,12 +409,20 @@ pub mod traits {
}

pub trait PlatformExecBounds<P: Platform>:
Platform<NodeTypes = types::NodeTypes<P>, EvmConfig = types::EvmConfig<P>>
Platform<
NodeTypes = types::NodeTypes<P>,
EvmConfig = types::EvmConfig<P>,
ExtraLimits = types::ExtraLimits<P>,
>
{
}

impl<T, P: Platform> PlatformExecBounds<T> for P where
T: Platform<NodeTypes = types::NodeTypes<P>, EvmConfig = types::EvmConfig<P>>
T: Platform<
NodeTypes = types::NodeTypes<P>,
EvmConfig = types::EvmConfig<P>,
ExtraLimits = types::ExtraLimits<P>,
>
{
}
}
Expand Down
6 changes: 3 additions & 3 deletions src/pipelines/step/context.rs
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ use {
#[derive(Debug, Clone)]
pub struct StepContext<P: Platform> {
block: BlockContext<P>,
limits: Limits,
limits: Limits<P>,
events_bus: Arc<EventsBus<P>>,
started_at: Option<Instant>,
}
Expand All @@ -25,7 +25,7 @@ impl<P: Platform> StepContext<P> {
pub(crate) fn new(
block: &BlockContext<P>,
step: &StepNavigator<P>,
limits: Limits,
limits: Limits<P>,
in_scope_since: Option<Instant>,
) -> Self {
let block = block.clone();
Expand Down Expand Up @@ -60,7 +60,7 @@ impl<P: Platform> StepContext<P> {
}

/// Payload limits for the scope of the step.
pub const fn limits(&self) -> &Limits {
pub const fn limits(&self) -> &Limits<P> {
&self.limits
}

Expand Down
2 changes: 1 addition & 1 deletion src/pipelines/tests/syntax.rs
Original file line number Diff line number Diff line change
Expand Up @@ -104,7 +104,7 @@ fn flashblocks_example_closure() {
#[derive(Debug)]
struct FlashblockLimits(FlashblocksConfig);
impl<P: Platform> ScopedLimits<P> for FlashblockLimits {
fn create(&self, _: &Checkpoint<P>, _: &Limits) -> Limits {
fn create(&self, _: &Checkpoint<P>, _: &Limits<P>) -> Limits<P> {
unimplemented!()
}
}
Expand Down
2 changes: 1 addition & 1 deletion src/platform/ethereum/limits.rs
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ impl EthereumDefaultLimits {
}

impl PlatformLimits<Ethereum> for EthereumDefaultLimits {
fn create(&self, block: &BlockContext<Ethereum>) -> Limits {
fn create(&self, block: &BlockContext<Ethereum>) -> Limits<Ethereum> {
let timestamp = block.attributes().timestamp();
let parent_gas_limit = block.parent().gas_limit();
let gas_limit = self.0.gas_limit(parent_gas_limit);
Expand Down
1 change: 1 addition & 0 deletions src/platform/ethereum/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,7 @@ impl Platform for Ethereum {
type Bundle = FlashbotsBundle<Self>;
type DefaultLimits = EthereumDefaultLimits;
type EvmConfig = EthEvmConfig;
type ExtraLimits = ();
type NodeTypes = EthereumNode;
type PooledTransaction = EthPooledTransaction;

Expand Down
33 changes: 26 additions & 7 deletions src/platform/limits.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ use {
crate::{alloy::eips::eip7840::BlobParams, prelude::*},
core::time::Duration,
serde::{Deserialize, Serialize},
std::time::Instant,
std::{fmt::Debug, time::Instant},
};

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

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

/// The time a pipeline is allowed to spend on execution.
pub deadline: Option<Duration>,

/// Per platform extension.
pub ext: P::ExtraLimits,
}

impl<P: Platform> Copy for Limits<P> {}

/// This trait must be implemented by extension limits
pub trait LimitExtension:
Copy + Debug + Default + Send + Sync + 'static
{
#[must_use]
fn clamp(&self, other: &Self) -> Self;
}

impl LimitExtension for () {
fn clamp(&self, (): &Self) -> Self {}
}

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

impl Limits {
impl<P: Platform> Limits<P> {
pub fn gas_limit(gas_limit: u64) -> Self {
Self {
gas_limit,
blob_params: None,
deadline: None,
max_transactions: None,
ext: P::ExtraLimits::default(),
}
}

Expand Down Expand Up @@ -109,6 +127,7 @@ impl Limits {
},
max_transactions: self.max_transactions.min(other.max_transactions),
deadline: self.deadline.min(other.deadline),
ext: self.ext.clamp(&other.ext),
}
}
}
7 changes: 6 additions & 1 deletion src/platform/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ mod optimism;
#[cfg(feature = "optimism")]
pub use optimism::*;

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

/// Type that can provide extra limits for the payload building process.
/// This type is used to provide platform-specific limits that are not
/// covered by the default `Limits` type.
type ExtraLimits: LimitExtension;

/// Instantiate the EVM configuration for the platform with a given chain
/// specification.
fn evm_config<P>(chainspec: Arc<types::ChainSpec<P>>) -> Self::EvmConfig
Expand Down
22 changes: 21 additions & 1 deletion src/platform/optimism/limits.rs
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,26 @@ use {
#[derive(Debug, Clone, Default)]
pub struct OptimismDefaultLimits;

#[allow(clippy::struct_field_names)]
#[derive(Default, Debug, Clone, Copy)]
pub struct OpLimitsExt {
pub max_tx_da: Option<u64>,
pub max_block_da: Option<u64>,
pub max_block_da_footprint: Option<u64>,
}

impl LimitExtension for OpLimitsExt {
fn clamp(&self, other: &Self) -> Self {
Self {
max_tx_da: self.max_tx_da.min(other.max_tx_da),
max_block_da: self.max_block_da.min(other.max_block_da),
max_block_da_footprint: self
.max_block_da_footprint
.min(other.max_block_da_footprint),
}
}
}

impl<P> PlatformLimits<P> for OptimismDefaultLimits
where
P: Platform<
Expand All @@ -28,7 +48,7 @@ where
>,
>,
{
fn create(&self, block: &BlockContext<P>) -> Limits {
fn create(&self, block: &BlockContext<P>) -> Limits<P> {
let mut limits = Limits::gas_limit(
block
.attributes()
Expand Down
4 changes: 3 additions & 1 deletion src/platform/optimism/mod.rs
Original file line number Diff line number Diff line change
@@ -1,10 +1,11 @@
use {
crate::{alloy, prelude::*, reth},
crate::{alloy, platform, prelude::*, reth},
alloy::{
eips::Encodable2718,
optimism::consensus::OpPooledTransaction as AlloyPoolTx,
primitives::Bytes,
},
platform::optimism::limits::OpLimitsExt,
reth::{
api::NodeTypes,
chainspec::EthChainSpec,
Expand Down Expand Up @@ -32,6 +33,7 @@ impl Platform for Optimism {
type Bundle = FlashbotsBundle<Self>;
type DefaultLimits = OptimismDefaultLimits;
type EvmConfig = OpEvmConfig;
type ExtraLimits = OpLimitsExt;
type NodeTypes = OpNode;
type PooledTransaction = OpPooledTransaction;

Expand Down
3 changes: 3 additions & 0 deletions src/platform/types.rs
Original file line number Diff line number Diff line change
Expand Up @@ -100,6 +100,9 @@ pub type EvmHaltReason<P: Platform> =
/// process.
pub type DefaultLimits<P: Platform> = P::DefaultLimits;

/// Extracts the type that can provide additional limits.
pub type ExtraLimits<P: Platform> = P::ExtraLimits;

/// The result of executing a transaction in the EVM.
pub type TransactionExecutionResult<P: Platform> =
ExecutionResult<EvmHaltReason<P>>;
Expand Down
2 changes: 1 addition & 1 deletion src/pool/step.rs
Original file line number Diff line number Diff line change
Expand Up @@ -251,7 +251,7 @@ impl<'a, P: Platform> Run<'a, P> {
}
}

const fn limits(&self) -> &Limits {
const fn limits(&self) -> &Limits<P> {
self.ctx.limits()
}

Expand Down
6 changes: 5 additions & 1 deletion src/steps/builder.rs
Original file line number Diff line number Diff line change
Expand Up @@ -134,7 +134,11 @@ struct LimitsMinusEpilogue<P: Platform> {
}

impl<P: Platform> ScopedLimits<P> for LimitsMinusEpilogue<P> {
fn create(&self, payload: &Checkpoint<P>, enclosing: &Limits) -> Limits {
fn create(
&self,
payload: &Checkpoint<P>,
enclosing: &Limits<P>,
) -> Limits<P> {
// calculate the gas usage for the epilogue transaction
let message = (self.message_fn)(payload.block());
let gas_estimate = estimate_gas_for_tx(message.as_bytes());
Expand Down
2 changes: 1 addition & 1 deletion src/test_utils/step.rs
Original file line number Diff line number Diff line change
Expand Up @@ -198,7 +198,7 @@ impl<P: PlatformWithRpcTypes + TestNodeFactory<P>> OneStep<P> {
}

#[must_use]
pub fn with_limits(mut self, limits: Limits) -> Self {
pub fn with_limits(mut self, limits: Limits<P>) -> Self {
self.pipeline = self.pipeline.with_limits(limits);
self
}
Expand Down
Loading