diff --git a/crates/ethereum/payload/src/lib.rs b/crates/ethereum/payload/src/lib.rs index c4e689ed6..f5373569f 100644 --- a/crates/ethereum/payload/src/lib.rs +++ b/crates/ethereum/payload/src/lib.rs @@ -10,9 +10,7 @@ #![allow(clippy::useless_let_if_seq)] use alloy_consensus::{BlockHeader, Header, Transaction, Typed2718, EMPTY_OMMER_ROOT_HASH}; -use alloy_eips::{ - eip4844::MAX_DATA_GAS_PER_BLOCK, eip6110, eip7685::Requests, merge::BEACON_NONCE, -}; +use alloy_eips::{eip4844::DATA_GAS_PER_BLOB, eip6110, eip7685::Requests, merge::BEACON_NONCE}; use alloy_primitives::U256; use reth_basic_payload_builder::{ commit_withdrawals, is_better_payload, BuildArguments, BuildOutcome, PayloadBuilder, @@ -52,6 +50,7 @@ use tracing::{debug, trace, warn}; mod config; pub use config::*; +use reth_transaction_pool::error::Eip4844PoolTransactionError; type BestTransactionsIter = Box< dyn BestTransactions::Transaction>>>, @@ -185,7 +184,6 @@ where debug!(target: "payload_builder", id=%attributes.id, parent_header = ?parent_header.hash(), parent_number = parent_header.number, "building new payload"); let mut cumulative_gas_used = 0; - let mut sum_blob_gas_used = 0; let block_gas_limit: u64 = evm_env.block_env.gas_limit.to::(); let base_fee = evm_env.block_env.basefee.to::(); @@ -228,6 +226,11 @@ where let mut evm = evm_config.evm_with_env(&mut db, evm_env); let mut receipts = Vec::new(); + let mut block_blob_count = 0; + let blob_params = chain_spec.blob_params_at_timestamp(attributes.timestamp); + let max_blob_count = + blob_params.as_ref().map(|params| params.max_blob_count).unwrap_or_default(); + while let Some(pool_tx) = best_txs.next() { // ensure we still have capacity for this transaction if cumulative_gas_used + pool_tx.gas_limit() > block_gas_limit { @@ -252,18 +255,21 @@ where // There's only limited amount of blob space available per block, so we need to check if // the EIP-4844 can still fit in the block if let Some(blob_tx) = tx.as_eip4844() { - let tx_blob_gas = blob_tx.blob_gas(); - if sum_blob_gas_used + tx_blob_gas > MAX_DATA_GAS_PER_BLOCK { + let tx_blob_count = blob_tx.blob_versioned_hashes.len() as u64; + + if block_blob_count + tx_blob_count > max_blob_count { // we can't fit this _blob_ transaction into the block, so we mark it as // invalid, which removes its dependent transactions from // the iterator. This is similar to the gas limit condition // for regular transactions above. - trace!(target: "payload_builder", tx=?tx.hash(), ?sum_blob_gas_used, ?tx_blob_gas, "skipping blob transaction because it would exceed the max data gas per block"); + trace!(target: "payload_builder", tx=?tx.hash(), ?block_blob_count, "skipping blob transaction because it would exceed the max blob count per block"); best_txs.mark_invalid( &pool_tx, - InvalidPoolTransactionError::ExceedsGasLimit( - tx_blob_gas, - MAX_DATA_GAS_PER_BLOCK, + InvalidPoolTransactionError::Eip4844( + Eip4844PoolTransactionError::TooManyEip4844Blobs { + have: (block_blob_count + tx_blob_count) as usize, + permitted: max_blob_count as usize, + }, ), ); continue @@ -303,11 +309,10 @@ where // add to the total blob gas used if the transaction successfully executed if let Some(blob_tx) = tx.as_eip4844() { - let tx_blob_gas = blob_tx.blob_gas(); - sum_blob_gas_used += tx_blob_gas; + block_blob_count += blob_tx.blob_versioned_hashes.len() as u64; - // if we've reached the max data gas per block, we can skip blob txs entirely - if sum_blob_gas_used == MAX_DATA_GAS_PER_BLOCK { + // if we've reached the max blob count, we can skip blob txs entirely + if block_blob_count == max_blob_count { best_txs.skip_blobs(); } } @@ -418,16 +423,14 @@ where .map_err(PayloadBuilderError::other)?; excess_blob_gas = if chain_spec.is_cancun_active_at_timestamp(parent_header.timestamp) { - parent_header.maybe_next_block_excess_blob_gas( - chain_spec.blob_params_at_timestamp(attributes.timestamp), - ) + parent_header.maybe_next_block_excess_blob_gas(blob_params) } else { // for the first post-fork block, both parent.blob_gas_used and // parent.excess_blob_gas are evaluated as 0 Some(alloy_eips::eip7840::BlobParams::cancun().next_block_excess_blob_gas(0, 0)) }; - blob_gas_used = Some(sum_blob_gas_used); + blob_gas_used = Some(block_blob_count * DATA_GAS_PER_BLOB); } let header = Header {