From a3f36a28ef4e7346898c662d5b54e9511227b113 Mon Sep 17 00:00:00 2001 From: Matthias Seitz Date: Thu, 12 Dec 2024 17:41:14 +0100 Subject: [PATCH] chore: relax some op pool validator internals --- crates/optimism/evm/src/l1.rs | 25 ++++++++++---- crates/optimism/node/src/txpool.rs | 38 +++++++++++++-------- crates/transaction-pool/src/validate/eth.rs | 4 +-- 3 files changed, 45 insertions(+), 22 deletions(-) diff --git a/crates/optimism/evm/src/l1.rs b/crates/optimism/evm/src/l1.rs index 1194dd63c2b1..1a092b831a56 100644 --- a/crates/optimism/evm/src/l1.rs +++ b/crates/optimism/evm/src/l1.rs @@ -33,14 +33,21 @@ const L1_BLOCK_ECOTONE_SELECTOR: [u8; 4] = hex!("440a5e20"); /// /// Returns an error if the L1 info transaction is not found, if the block is empty. pub fn extract_l1_info(body: &B) -> Result { - let l1_info_tx_data = body - .transactions() - .first() - .ok_or_else(|| OpBlockExecutionError::L1BlockInfoError { + let l1_info_tx = + body.transactions().first().ok_or_else(|| OpBlockExecutionError::L1BlockInfoError { message: "could not find l1 block info tx in the L2 block".to_string(), - }) - .map(|tx| tx.input())?; + })?; + extract_l1_info_from_tx(l1_info_tx) +} +/// Extracts the [`L1BlockInfo`] from the the L1 info transaction (first transaction) in the L2 +/// block. +/// +/// Returns an error if the calldata is shorter than 4 bytes. +pub fn extract_l1_info_from_tx( + tx: &T, +) -> Result { + let l1_info_tx_data = tx.input(); if l1_info_tx_data.len() < 4 { return Err(OpBlockExecutionError::L1BlockInfoError { message: "invalid l1 block info transaction calldata in the L2 block".to_string(), @@ -53,6 +60,12 @@ pub fn extract_l1_info(body: &B) -> Result Result { // If the first 4 bytes of the calldata are the L1BlockInfoEcotone selector, then we parse the // calldata as an Ecotone hardfork L1BlockInfo transaction. Otherwise, we parse it as a diff --git a/crates/optimism/node/src/txpool.rs b/crates/optimism/node/src/txpool.rs index a3e474a60760..6ccc38c2d2a2 100644 --- a/crates/optimism/node/src/txpool.rs +++ b/crates/optimism/node/src/txpool.rs @@ -1,11 +1,11 @@ //! OP transaction pool types +use alloy_consensus::{BlockHeader, Transaction}; use alloy_eips::eip2718::Encodable2718; use parking_lot::RwLock; use reth_chainspec::ChainSpec; +use reth_node_api::{Block, BlockBody}; use reth_optimism_evm::RethL1BlockInfo; -use reth_primitives::{ - Block, GotExpected, InvalidTransactionError, SealedBlock, TransactionSigned, -}; +use reth_primitives::{GotExpected, InvalidTransactionError, SealedBlock, TransactionSigned}; use reth_provider::{BlockReaderIdExt, StateProviderFactory}; use reth_revm::L1BlockInfo; use reth_transaction_pool::{ @@ -40,7 +40,7 @@ pub struct OpTransactionValidator { impl OpTransactionValidator { /// Returns the configured chain spec - pub fn chain_spec(&self) -> Arc { + pub fn chain_spec(&self) -> &Arc { self.inner.chain_spec() } @@ -69,7 +69,7 @@ impl OpTransactionValidator { impl OpTransactionValidator where - Client: StateProviderFactory + BlockReaderIdExt, + Client: StateProviderFactory + BlockReaderIdExt, Tx: EthPoolTransaction, { /// Create a new [`OpTransactionValidator`]. @@ -80,10 +80,10 @@ where { // genesis block has no txs, so we can't extract L1 info, we set the block info to empty // so that we will accept txs into the pool before the first block - if block.number == 0 { - this.block_info.timestamp.store(block.timestamp, Ordering::Relaxed); + if block.header().number() == 0 { + this.block_info.timestamp.store(block.header().timestamp(), Ordering::Relaxed); } else { - this.update_l1_block_info(&block); + this.update_l1_block_info(block.header(), block.body().transactions().first()); } } @@ -98,10 +98,17 @@ where Self { inner, block_info: Arc::new(block_info), require_l1_data_gas_fee: true } } - /// Update the L1 block info. - fn update_l1_block_info(&self, block: &Block) { - self.block_info.timestamp.store(block.timestamp, Ordering::Relaxed); - if let Ok(cost_addition) = reth_optimism_evm::extract_l1_info(&block.body) { + /// Update the L1 block info for the given header and system transaction, if any. + /// + /// Note: this supports optional system transaction, in case this is used in a dev setuo + pub fn update_l1_block_info(&self, header: &H, tx: Option<&T>) + where + H: BlockHeader, + T: Transaction, + { + self.block_info.timestamp.store(header.timestamp(), Ordering::Relaxed); + + if let Some(Ok(cost_addition)) = tx.map(reth_optimism_evm::extract_l1_info_from_tx) { *self.block_info.l1_block_info.write() = cost_addition; } } @@ -146,7 +153,7 @@ where tx.encode_2718(&mut encoded); let cost_addition = match l1_block_info.l1_tx_data_fee( - &self.chain_spec(), + self.chain_spec(), self.block_timestamp(), &encoded, false, @@ -217,7 +224,10 @@ where fn on_new_head_block(&self, new_tip_block: &SealedBlock) { self.inner.on_new_head_block(new_tip_block); - self.update_l1_block_info(&new_tip_block.clone().unseal()); + self.update_l1_block_info( + new_tip_block.header(), + new_tip_block.body.transactions().first(), + ); } } diff --git a/crates/transaction-pool/src/validate/eth.rs b/crates/transaction-pool/src/validate/eth.rs index 3c93b384c734..e92fbc2c9d7d 100644 --- a/crates/transaction-pool/src/validate/eth.rs +++ b/crates/transaction-pool/src/validate/eth.rs @@ -45,8 +45,8 @@ pub struct EthTransactionValidator { impl EthTransactionValidator { /// Returns the configured chain spec - pub fn chain_spec(&self) -> Arc { - self.inner.chain_spec.clone() + pub fn chain_spec(&self) -> &Arc { + &self.inner.chain_spec } /// Returns the configured client