diff --git a/crates/transaction-pool/src/validate/eth.rs b/crates/transaction-pool/src/validate/eth.rs index 7859e2bf8..b17d79827 100644 --- a/crates/transaction-pool/src/validate/eth.rs +++ b/crates/transaction-pool/src/validate/eth.rs @@ -19,8 +19,7 @@ use alloy_consensus::{ BlockHeader, }; use alloy_eips::{ - eip1559::ETHEREUM_BLOCK_GAS_LIMIT, - eip4844::{env_settings::EnvKzgSettings, MAX_BLOBS_PER_BLOCK}, + eip1559::ETHEREUM_BLOCK_GAS_LIMIT, eip4844::env_settings::EnvKzgSettings, eip7840::BlobParams, }; use reth_chainspec::{ChainSpecProvider, EthChainSpec, EthereumHardforks}; use reth_primitives::{InvalidTransactionError, SealedBlock}; @@ -340,14 +339,14 @@ where ) } - if blob_count > MAX_BLOBS_PER_BLOCK { - // too many blobs + let max_blob_count = self.fork_tracker.max_blob_count() as usize; + if blob_count > max_blob_count { return TransactionValidationOutcome::Invalid( transaction, InvalidPoolTransactionError::Eip4844( Eip4844PoolTransactionError::TooManyEip4844Blobs { have: blob_count, - permitted: MAX_BLOBS_PER_BLOCK, + permitted: max_blob_count, }, ), ) @@ -527,6 +526,14 @@ where self.fork_tracker.prague.store(true, std::sync::atomic::Ordering::Relaxed); } + if let Some(blob_params) = + self.chain_spec().blob_params_at_timestamp(new_tip_block.timestamp()) + { + self.fork_tracker + .max_blob_count + .store(blob_params.max_blob_count, std::sync::atomic::Ordering::Relaxed); + } + self.block_gas_limit.store(new_tip_block.gas_limit(), std::sync::atomic::Ordering::Relaxed); } @@ -545,6 +552,8 @@ pub struct EthTransactionValidatorBuilder { cancun: bool, /// Fork indicator whether we are in the Cancun hardfork. prague: bool, + /// Max blob count at the block's timestamp. + max_blob_count: u64, /// Whether using EIP-2718 type transactions is allowed eip2718: bool, /// Whether using EIP-1559 type transactions is allowed @@ -603,6 +612,9 @@ impl EthTransactionValidatorBuilder { // prague not yet activated prague: false, + + // max blob count is cancun by default + max_blob_count: BlobParams::cancun().max_blob_count, } } @@ -709,6 +721,12 @@ impl EthTransactionValidatorBuilder { self.cancun = self.client.chain_spec().is_cancun_active_at_timestamp(timestamp); self.shanghai = self.client.chain_spec().is_shanghai_active_at_timestamp(timestamp); self.prague = self.client.chain_spec().is_prague_active_at_timestamp(timestamp); + self.max_blob_count = self + .client + .chain_spec() + .blob_params_at_timestamp(timestamp) + .unwrap_or_else(BlobParams::cancun) + .max_blob_count; self } @@ -748,10 +766,17 @@ impl EthTransactionValidatorBuilder { .. } = self; + let max_blob_count = if prague { + BlobParams::prague().max_blob_count + } else { + BlobParams::cancun().max_blob_count + }; + let fork_tracker = ForkTracker { shanghai: AtomicBool::new(shanghai), cancun: AtomicBool::new(cancun), prague: AtomicBool::new(prague), + max_blob_count: AtomicU64::new(max_blob_count), }; let inner = EthTransactionValidatorInner { @@ -825,6 +850,8 @@ pub struct ForkTracker { pub cancun: AtomicBool, /// Tracks if prague is activated at the block's timestamp. pub prague: AtomicBool, + /// Tracks max blob count at the block's timestamp. + pub max_blob_count: AtomicU64, } impl ForkTracker { @@ -842,6 +869,11 @@ impl ForkTracker { pub fn is_prague_activated(&self) -> bool { self.prague.load(std::sync::atomic::Ordering::Relaxed) } + + /// Returns the max blob count. + pub fn max_blob_count(&self) -> u64 { + self.max_blob_count.load(std::sync::atomic::Ordering::Relaxed) + } } /// Ensures that gas limit of the transaction exceeds the intrinsic gas of the transaction. @@ -902,8 +934,12 @@ mod tests { #[tokio::test] async fn validate_transaction() { let transaction = get_transaction(); - let mut fork_tracker = - ForkTracker { shanghai: false.into(), cancun: false.into(), prague: false.into() }; + let mut fork_tracker = ForkTracker { + shanghai: false.into(), + cancun: false.into(), + prague: false.into(), + max_blob_count: 0.into(), + }; let res = ensure_intrinsic_gas(&transaction, &fork_tracker); assert!(res.is_ok());