mirror of
https://github.com/hl-archive-node/nanoreth.git
synced 2025-12-06 10:59:55 +00:00
refactor: avoid using NoopTransactionPool in OP payload builder (#13547)
This commit is contained in:
1
Cargo.lock
generated
1
Cargo.lock
generated
@ -8563,6 +8563,7 @@ dependencies = [
|
|||||||
"alloy-rlp",
|
"alloy-rlp",
|
||||||
"alloy-rpc-types-debug",
|
"alloy-rpc-types-debug",
|
||||||
"alloy-rpc-types-engine",
|
"alloy-rpc-types-engine",
|
||||||
|
"derive_more",
|
||||||
"op-alloy-consensus",
|
"op-alloy-consensus",
|
||||||
"op-alloy-rpc-types-engine",
|
"op-alloy-rpc-types-engine",
|
||||||
"reth-basic-payload-builder",
|
"reth-basic-payload-builder",
|
||||||
|
|||||||
@ -47,6 +47,7 @@ alloy-rpc-types-debug.workspace = true
|
|||||||
alloy-consensus.workspace = true
|
alloy-consensus.workspace = true
|
||||||
|
|
||||||
# misc
|
# misc
|
||||||
|
derive_more.workspace = true
|
||||||
tracing.workspace = true
|
tracing.workspace = true
|
||||||
thiserror.workspace = true
|
thiserror.workspace = true
|
||||||
sha2.workspace = true
|
sha2.workspace = true
|
||||||
|
|||||||
@ -22,7 +22,7 @@ use reth_optimism_consensus::calculate_receipt_root_no_memo_optimism;
|
|||||||
use reth_optimism_forks::OpHardforks;
|
use reth_optimism_forks::OpHardforks;
|
||||||
use reth_payload_builder_primitives::PayloadBuilderError;
|
use reth_payload_builder_primitives::PayloadBuilderError;
|
||||||
use reth_payload_primitives::PayloadBuilderAttributes;
|
use reth_payload_primitives::PayloadBuilderAttributes;
|
||||||
use reth_payload_util::PayloadTransactions;
|
use reth_payload_util::{NoopPayloadTransactions, PayloadTransactions};
|
||||||
use reth_primitives::{
|
use reth_primitives::{
|
||||||
proofs, transaction::SignedTransactionIntoRecoveredExt, Block, BlockBody, BlockExt, Receipt,
|
proofs, transaction::SignedTransactionIntoRecoveredExt, Block, BlockBody, BlockExt, Receipt,
|
||||||
SealedHeader, TransactionSigned, TxType,
|
SealedHeader, TransactionSigned, TxType,
|
||||||
@ -33,8 +33,7 @@ use reth_provider::{
|
|||||||
};
|
};
|
||||||
use reth_revm::{database::StateProviderDatabase, witness::ExecutionWitnessRecord};
|
use reth_revm::{database::StateProviderDatabase, witness::ExecutionWitnessRecord};
|
||||||
use reth_transaction_pool::{
|
use reth_transaction_pool::{
|
||||||
noop::NoopTransactionPool, pool::BestPayloadTransactions, BestTransactionsAttributes,
|
pool::BestPayloadTransactions, BestTransactionsAttributes, PoolTransaction, TransactionPool,
|
||||||
PoolTransaction, TransactionPool,
|
|
||||||
};
|
};
|
||||||
use revm::{
|
use revm::{
|
||||||
db::{states::bundle_state::BundleRetention, State},
|
db::{states::bundle_state::BundleRetention, State},
|
||||||
@ -103,10 +102,9 @@ impl<EvmConfig, Txs> OpPayloadBuilder<EvmConfig, Txs> {
|
|||||||
self.compute_pending_block
|
self.compute_pending_block
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
impl<EvmConfig, Txs> OpPayloadBuilder<EvmConfig, Txs>
|
impl<EvmConfig, T> OpPayloadBuilder<EvmConfig, T>
|
||||||
where
|
where
|
||||||
EvmConfig: ConfigureEvm<Header = Header, Transaction = TransactionSigned>,
|
EvmConfig: ConfigureEvm<Header = Header, Transaction = TransactionSigned>,
|
||||||
Txs: OpPayloadTransactions,
|
|
||||||
{
|
{
|
||||||
/// Constructs an Optimism payload from the transactions sent via the
|
/// Constructs an Optimism payload from the transactions sent via the
|
||||||
/// Payload attributes by the sequencer. If the `no_tx_pool` argument is passed in
|
/// Payload attributes by the sequencer. If the `no_tx_pool` argument is passed in
|
||||||
@ -116,20 +114,22 @@ where
|
|||||||
/// Given build arguments including an Optimism client, transaction pool,
|
/// Given build arguments including an Optimism client, transaction pool,
|
||||||
/// and configuration, this function creates a transaction payload. Returns
|
/// and configuration, this function creates a transaction payload. Returns
|
||||||
/// a result indicating success with the payload or an error in case of failure.
|
/// a result indicating success with the payload or an error in case of failure.
|
||||||
fn build_payload<Client, Pool>(
|
fn build_payload<'a, Client, Pool, Txs>(
|
||||||
&self,
|
&self,
|
||||||
args: BuildArguments<Pool, Client, OpPayloadBuilderAttributes, OpBuiltPayload>,
|
args: BuildArguments<Pool, Client, OpPayloadBuilderAttributes, OpBuiltPayload>,
|
||||||
|
best: impl FnOnce(BestTransactionsAttributes) -> Txs + Send + Sync + 'a,
|
||||||
) -> Result<BuildOutcome<OpBuiltPayload>, PayloadBuilderError>
|
) -> Result<BuildOutcome<OpBuiltPayload>, PayloadBuilderError>
|
||||||
where
|
where
|
||||||
Client: StateProviderFactory + ChainSpecProvider<ChainSpec = OpChainSpec>,
|
Client: StateProviderFactory + ChainSpecProvider<ChainSpec = OpChainSpec>,
|
||||||
Pool: TransactionPool<Transaction: PoolTransaction<Consensus = TransactionSigned>>,
|
Txs: PayloadTransactions<Transaction = TransactionSigned>,
|
||||||
{
|
{
|
||||||
let evm_env = self
|
let evm_env = self
|
||||||
.cfg_and_block_env(&args.config.attributes, &args.config.parent_header)
|
.cfg_and_block_env(&args.config.attributes, &args.config.parent_header)
|
||||||
.map_err(PayloadBuilderError::other)?;
|
.map_err(PayloadBuilderError::other)?;
|
||||||
let EvmEnv { cfg_env_with_handler_cfg, block_env } = evm_env;
|
let EvmEnv { cfg_env_with_handler_cfg, block_env } = evm_env;
|
||||||
|
|
||||||
let BuildArguments { client, pool, mut cached_reads, config, cancel, best_payload } = args;
|
let BuildArguments { client, pool: _, mut cached_reads, config, cancel, best_payload } =
|
||||||
|
args;
|
||||||
|
|
||||||
let ctx = OpPayloadBuilderCtx {
|
let ctx = OpPayloadBuilderCtx {
|
||||||
evm_config: self.evm_config.clone(),
|
evm_config: self.evm_config.clone(),
|
||||||
@ -141,7 +141,7 @@ where
|
|||||||
best_payload,
|
best_payload,
|
||||||
};
|
};
|
||||||
|
|
||||||
let builder = OpBuilder { pool, best: self.best_transactions.clone() };
|
let builder = OpBuilder::new(best);
|
||||||
|
|
||||||
let state_provider = client.state_by_block_hash(ctx.parent().hash())?;
|
let state_provider = client.state_by_block_hash(ctx.parent().hash())?;
|
||||||
let state = StateProviderDatabase::new(state_provider);
|
let state = StateProviderDatabase::new(state_provider);
|
||||||
@ -159,12 +159,7 @@ where
|
|||||||
}
|
}
|
||||||
.map(|out| out.with_cached_reads(cached_reads))
|
.map(|out| out.with_cached_reads(cached_reads))
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
impl<EvmConfig, Txs> OpPayloadBuilder<EvmConfig, Txs>
|
|
||||||
where
|
|
||||||
EvmConfig: ConfigureEvm<Header = Header, Transaction = TransactionSigned>,
|
|
||||||
{
|
|
||||||
/// Returns the configured [`EvmEnv`] for the targeted payload
|
/// Returns the configured [`EvmEnv`] for the targeted payload
|
||||||
/// (that has the `parent` as its parent).
|
/// (that has the `parent` as its parent).
|
||||||
pub fn cfg_and_block_env(
|
pub fn cfg_and_block_env(
|
||||||
@ -213,7 +208,7 @@ where
|
|||||||
let state = StateProviderDatabase::new(state_provider);
|
let state = StateProviderDatabase::new(state_provider);
|
||||||
let mut state = State::builder().with_database(state).with_bundle_update().build();
|
let mut state = State::builder().with_database(state).with_bundle_update().build();
|
||||||
|
|
||||||
let builder = OpBuilder { pool: NoopTransactionPool::default(), best: () };
|
let builder = OpBuilder::new(|_| NoopPayloadTransactions::default());
|
||||||
builder.witness(&mut state, &ctx)
|
builder.witness(&mut state, &ctx)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -233,7 +228,8 @@ where
|
|||||||
&self,
|
&self,
|
||||||
args: BuildArguments<Pool, Client, OpPayloadBuilderAttributes, OpBuiltPayload>,
|
args: BuildArguments<Pool, Client, OpPayloadBuilderAttributes, OpBuiltPayload>,
|
||||||
) -> Result<BuildOutcome<OpBuiltPayload>, PayloadBuilderError> {
|
) -> Result<BuildOutcome<OpBuiltPayload>, PayloadBuilderError> {
|
||||||
self.build_payload(args)
|
let pool = args.pool.clone();
|
||||||
|
self.build_payload(args, |attrs| self.best_transactions.best_transactions(pool, attrs))
|
||||||
}
|
}
|
||||||
|
|
||||||
fn on_missing_payload(
|
fn on_missing_payload(
|
||||||
@ -256,12 +252,14 @@ where
|
|||||||
client,
|
client,
|
||||||
config,
|
config,
|
||||||
// we use defaults here because for the empty payload we don't need to execute anything
|
// we use defaults here because for the empty payload we don't need to execute anything
|
||||||
pool: NoopTransactionPool::default(),
|
pool: (),
|
||||||
cached_reads: Default::default(),
|
cached_reads: Default::default(),
|
||||||
cancel: Default::default(),
|
cancel: Default::default(),
|
||||||
best_payload: None,
|
best_payload: None,
|
||||||
};
|
};
|
||||||
self.build_payload(args)?.into_payload().ok_or_else(|| PayloadBuilderError::MissingPayload)
|
self.build_payload(args, |_| NoopPayloadTransactions::default())?
|
||||||
|
.into_payload()
|
||||||
|
.ok_or_else(|| PayloadBuilderError::MissingPayload)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -280,18 +278,22 @@ where
|
|||||||
///
|
///
|
||||||
/// And finally
|
/// And finally
|
||||||
/// 5. build the block: compute all roots (txs, state)
|
/// 5. build the block: compute all roots (txs, state)
|
||||||
#[derive(Debug)]
|
#[derive(derive_more::Debug)]
|
||||||
pub struct OpBuilder<Pool, Txs> {
|
pub struct OpBuilder<'a, Txs> {
|
||||||
/// The transaction pool
|
|
||||||
pool: Pool,
|
|
||||||
/// Yields the best transaction to include if transactions from the mempool are allowed.
|
/// Yields the best transaction to include if transactions from the mempool are allowed.
|
||||||
best: Txs,
|
#[debug(skip)]
|
||||||
|
best: Box<dyn FnOnce(BestTransactionsAttributes) -> Txs + 'a>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<Pool, Txs> OpBuilder<Pool, Txs>
|
impl<'a, Txs> OpBuilder<'a, Txs> {
|
||||||
|
fn new(best: impl FnOnce(BestTransactionsAttributes) -> Txs + Send + Sync + 'a) -> Self {
|
||||||
|
Self { best: Box::new(best) }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<Txs> OpBuilder<'_, Txs>
|
||||||
where
|
where
|
||||||
Pool: TransactionPool<Transaction: PoolTransaction<Consensus = TransactionSigned>>,
|
Txs: PayloadTransactions<Transaction = TransactionSigned>,
|
||||||
Txs: OpPayloadTransactions,
|
|
||||||
{
|
{
|
||||||
/// Executes the payload and returns the outcome.
|
/// Executes the payload and returns the outcome.
|
||||||
pub fn execute<EvmConfig, DB>(
|
pub fn execute<EvmConfig, DB>(
|
||||||
@ -303,7 +305,7 @@ where
|
|||||||
EvmConfig: ConfigureEvm<Header = Header, Transaction = TransactionSigned>,
|
EvmConfig: ConfigureEvm<Header = Header, Transaction = TransactionSigned>,
|
||||||
DB: Database<Error = ProviderError>,
|
DB: Database<Error = ProviderError>,
|
||||||
{
|
{
|
||||||
let Self { pool, best } = self;
|
let Self { best } = self;
|
||||||
debug!(target: "payload_builder", id=%ctx.payload_id(), parent_header = ?ctx.parent().hash(), parent_number = ctx.parent().number, "building new payload");
|
debug!(target: "payload_builder", id=%ctx.payload_id(), parent_header = ?ctx.parent().hash(), parent_number = ctx.parent().number, "building new payload");
|
||||||
|
|
||||||
// 1. apply eip-4788 pre block contract call
|
// 1. apply eip-4788 pre block contract call
|
||||||
@ -317,8 +319,8 @@ where
|
|||||||
|
|
||||||
// 4. if mem pool transactions are requested we execute them
|
// 4. if mem pool transactions are requested we execute them
|
||||||
if !ctx.attributes().no_tx_pool {
|
if !ctx.attributes().no_tx_pool {
|
||||||
let best_txs = best.best_transactions(pool, ctx.best_transaction_attributes());
|
let best_txs = best(ctx.best_transaction_attributes());
|
||||||
if ctx.execute_best_transactions::<_, Pool>(&mut info, state, best_txs)?.is_some() {
|
if ctx.execute_best_transactions(&mut info, state, best_txs)?.is_some() {
|
||||||
return Ok(BuildOutcomeKind::Cancelled)
|
return Ok(BuildOutcomeKind::Cancelled)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -838,7 +840,7 @@ where
|
|||||||
/// Executes the given best transactions and updates the execution info.
|
/// Executes the given best transactions and updates the execution info.
|
||||||
///
|
///
|
||||||
/// Returns `Ok(Some(())` if the job was cancelled.
|
/// Returns `Ok(Some(())` if the job was cancelled.
|
||||||
pub fn execute_best_transactions<DB, Pool>(
|
pub fn execute_best_transactions<DB>(
|
||||||
&self,
|
&self,
|
||||||
info: &mut ExecutionInfo,
|
info: &mut ExecutionInfo,
|
||||||
db: &mut State<DB>,
|
db: &mut State<DB>,
|
||||||
|
|||||||
@ -11,5 +11,5 @@
|
|||||||
mod traits;
|
mod traits;
|
||||||
mod transaction;
|
mod transaction;
|
||||||
|
|
||||||
pub use traits::PayloadTransactions;
|
pub use traits::{NoopPayloadTransactions, PayloadTransactions};
|
||||||
pub use transaction::{PayloadTransactionsChain, PayloadTransactionsFixed};
|
pub use transaction::{PayloadTransactionsChain, PayloadTransactionsFixed};
|
||||||
|
|||||||
@ -21,3 +21,17 @@ pub trait PayloadTransactions {
|
|||||||
/// because this transaction won't be included in the block.
|
/// because this transaction won't be included in the block.
|
||||||
fn mark_invalid(&mut self, sender: Address, nonce: u64);
|
fn mark_invalid(&mut self, sender: Address, nonce: u64);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// [`PayloadTransactions`] implementation that produces nothing.
|
||||||
|
#[derive(Debug, Default, Clone, Copy)]
|
||||||
|
pub struct NoopPayloadTransactions<T>(core::marker::PhantomData<T>);
|
||||||
|
|
||||||
|
impl<T> PayloadTransactions for NoopPayloadTransactions<T> {
|
||||||
|
type Transaction = T;
|
||||||
|
|
||||||
|
fn next(&mut self, _ctx: ()) -> Option<RecoveredTx<Self::Transaction>> {
|
||||||
|
None
|
||||||
|
}
|
||||||
|
|
||||||
|
fn mark_invalid(&mut self, _sender: Address, _nonce: u64) {}
|
||||||
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user