diff --git a/crates/optimism/node/src/node.rs b/crates/optimism/node/src/node.rs index 14088e636f..ae146a6088 100644 --- a/crates/optimism/node/src/node.rs +++ b/crates/optimism/node/src/node.rs @@ -21,6 +21,7 @@ use reth_node_builder::{ use reth_optimism_chainspec::OpChainSpec; use reth_optimism_consensus::OpBeaconConsensus; use reth_optimism_evm::{OpEvmConfig, OpExecutionStrategyFactory}; +use reth_optimism_payload_builder::builder::OpPayloadTransactions; use reth_optimism_rpc::OpEthApi; use reth_payload_builder::{PayloadBuilderHandle, PayloadBuilderService}; use reth_primitives::{Block, Header}; @@ -286,7 +287,7 @@ where /// A basic optimism payload service builder #[derive(Debug, Default, Clone)] -pub struct OpPayloadBuilder { +pub struct OpPayloadBuilder { /// By default the pending block equals the latest block /// to save resources and not leak txs from the tx-pool, /// this flag enables computing of the pending block @@ -296,12 +297,30 @@ pub struct OpPayloadBuilder { /// will use the payload attributes from the latest block. Note /// that this flag is not yet functional. pub compute_pending_block: bool, + /// The type responsible for yielding the best transactions for the payload if mempool + /// transactions are allowed. + pub best_transactions: Txs, } impl OpPayloadBuilder { /// Create a new instance with the given `compute_pending_block` flag. pub const fn new(compute_pending_block: bool) -> Self { - Self { compute_pending_block } + Self { compute_pending_block, best_transactions: () } + } +} + +impl OpPayloadBuilder +where + Txs: OpPayloadTransactions, +{ + /// Configures the type responsible for yielding the transactions that should be included in the + /// payload. + pub fn with_transactions( + self, + best_transactions: T, + ) -> OpPayloadBuilder { + let Self { compute_pending_block, .. } = self; + OpPayloadBuilder { compute_pending_block, best_transactions } } /// A helper method to initialize [`PayloadBuilderService`] with the given EVM config. @@ -319,6 +338,7 @@ impl OpPayloadBuilder { Evm: ConfigureEvm
, { let payload_builder = reth_optimism_payload_builder::OpPayloadBuilder::new(evm_config) + .with_transactions(self.best_transactions) .set_compute_pending_block(self.compute_pending_block); let conf = ctx.payload_builder_config(); @@ -345,11 +365,12 @@ impl OpPayloadBuilder { } } -impl PayloadServiceBuilder for OpPayloadBuilder +impl PayloadServiceBuilder for OpPayloadBuilder where Node: FullNodeTypes>, Pool: TransactionPool + Unpin + 'static, + Txs: OpPayloadTransactions, { async fn spawn_payload_service( self, diff --git a/crates/optimism/payload/src/builder.rs b/crates/optimism/payload/src/builder.rs index 35e1d905a4..f0c6c04ce7 100644 --- a/crates/optimism/payload/src/builder.rs +++ b/crates/optimism/payload/src/builder.rs @@ -42,26 +42,41 @@ use op_alloy_consensus::DepositTransaction; /// Optimism's payload builder #[derive(Debug, Clone, PartialEq, Eq)] -pub struct OpPayloadBuilder { +pub struct OpPayloadBuilder { /// The rollup's compute pending block configuration option. // TODO(clabby): Implement this feature. pub compute_pending_block: bool, /// The type responsible for creating the evm. pub evm_config: EvmConfig, + /// The type responsible for yielding the best transactions for the payload if mempool + /// transactions are allowed. + pub best_transactions: Txs, } impl OpPayloadBuilder { /// `OpPayloadBuilder` constructor. pub const fn new(evm_config: EvmConfig) -> Self { - Self { compute_pending_block: true, evm_config } + Self { compute_pending_block: true, evm_config, best_transactions: () } } +} +impl OpPayloadBuilder { /// Sets the rollup's compute pending block configuration option. pub const fn set_compute_pending_block(mut self, compute_pending_block: bool) -> Self { self.compute_pending_block = compute_pending_block; self } + /// Configures the type responsible for yielding the transactions that should be included in the + /// payload. + pub fn with_transactions( + self, + best_transactions: T, + ) -> OpPayloadBuilder { + let Self { compute_pending_block, evm_config, .. } = self; + OpPayloadBuilder { compute_pending_block, evm_config, best_transactions } + } + /// Enables the rollup's compute pending block configuration option. pub const fn compute_pending_block(self) -> Self { self.set_compute_pending_block(true) @@ -72,9 +87,10 @@ impl OpPayloadBuilder { self.compute_pending_block } } -impl OpPayloadBuilder +impl OpPayloadBuilder where EvmConfig: ConfigureEvm
, + Txs: OpPayloadTransactions, { /// Returns the configured [`CfgEnvWithHandlerCfg`] and [`BlockEnv`] for the targeted payload /// (that has the `parent` as its parent). @@ -123,12 +139,7 @@ where best_payload, }; - let builder = OpBuilder { - pool, - // TODO(mattsse): make this configurable in the `OpPayloadBuilder` directly via an - // additional generic - best: best_txs::, - }; + let builder = OpBuilder { pool, best: self.best_transactions.clone() }; let state_provider = client.state_by_block_hash(ctx.parent().hash())?; let state = StateProviderDatabase::new(state_provider); @@ -149,11 +160,12 @@ where } /// Implementation of the [`PayloadBuilder`] trait for [`OpPayloadBuilder`]. -impl PayloadBuilder for OpPayloadBuilder +impl PayloadBuilder for OpPayloadBuilder where Client: StateProviderFactory + ChainSpecProvider, Pool: TransactionPool, EvmConfig: ConfigureEvm
, + Txs: OpPayloadTransactions, { type Attributes = OpPayloadBuilderAttributes; type BuiltPayload = OpBuiltPayload; @@ -210,18 +222,17 @@ where /// And finally /// 5. build the block: compute all roots (txs, state) #[derive(Debug)] -pub struct OpBuilder { +pub struct OpBuilder { /// The transaction pool pool: Pool, /// Yields the best transaction to include if transactions from the mempool are allowed. - // TODO(mattsse): convert this to a trait - best: Best, + best: Txs, } -impl OpBuilder +impl OpBuilder where Pool: TransactionPool, - Best: FnOnce(Pool, BestTransactionsAttributes) -> BestTransactionsFor, + Txs: OpPayloadTransactions, { /// Builds the payload on top of the state. pub fn build( @@ -248,7 +259,7 @@ where // 4. if mem pool transactions are requested we execute them if !ctx.attributes().no_tx_pool { - let best_txs = best(pool, ctx.best_transaction_attributes()); + let best_txs = best.best_transactions(pool, ctx.best_transaction_attributes()); if let Some(cancelled) = ctx.execute_best_transactions::<_, Pool>(&mut info, &mut db, best_txs)? { @@ -379,11 +390,25 @@ where } } -fn best_txs( - pool: Pool, - attr: BestTransactionsAttributes, -) -> BestTransactionsFor { - pool.best_transactions_with_attributes(attr) +/// A type that returns a the [`BestTransactions`] that should be included in the pool. +pub trait OpPayloadTransactions: Clone + Send + Sync + Unpin + 'static { + /// Returns an iterator that yields the transaction in the order they should get included in the + /// new payload. + fn best_transactions( + &self, + pool: Pool, + attr: BestTransactionsAttributes, + ) -> BestTransactionsFor; +} + +impl OpPayloadTransactions for () { + fn best_transactions( + &self, + pool: Pool, + attr: BestTransactionsAttributes, + ) -> BestTransactionsFor { + pool.best_transactions_with_attributes(attr) + } } /// This acts as the container for executed transactions and its byproducts (receipts, gas used)