diff --git a/crates/blockchain-tree-api/src/error.rs b/crates/blockchain-tree-api/src/error.rs index 5dbd4cf17..867580e3c 100644 --- a/crates/blockchain-tree-api/src/error.rs +++ b/crates/blockchain-tree-api/src/error.rs @@ -189,7 +189,7 @@ impl std::fmt::Debug for InsertBlockErrorData { .field("hash", &self.block.hash()) .field("number", &self.block.number) .field("parent_hash", &self.block.parent_hash) - .field("num_txs", &self.block.body.len()) + .field("num_txs", &self.block.body.transactions.len()) .finish_non_exhaustive() } } @@ -235,7 +235,7 @@ impl std::fmt::Debug for InsertBlockErrorDataTwo { .field("hash", &self.block.hash()) .field("number", &self.block.number) .field("parent_hash", &self.block.parent_hash) - .field("num_txs", &self.block.body.len()) + .field("num_txs", &self.block.body.transactions.len()) .finish_non_exhaustive() } } diff --git a/crates/blockchain-tree/src/blockchain_tree.rs b/crates/blockchain-tree/src/blockchain_tree.rs index f028237b0..ed702bff1 100644 --- a/crates/blockchain-tree/src/blockchain_tree.rs +++ b/crates/blockchain-tree/src/blockchain_tree.rs @@ -1389,8 +1389,8 @@ mod tests { constants::{EIP1559_INITIAL_BASE_FEE, EMPTY_ROOT_HASH}, proofs::{calculate_receipt_root, calculate_transaction_root}, revm_primitives::AccountInfo, - Account, Header, Signature, Transaction, TransactionSigned, TransactionSignedEcRecovered, - TxEip1559, Withdrawals, + Account, BlockBody, Header, Signature, Transaction, TransactionSigned, + TransactionSignedEcRecovered, TxEip1559, Withdrawals, }; use reth_provider::{ test_utils::{ @@ -1628,10 +1628,12 @@ mod tests { SealedBlockWithSenders::new( SealedBlock { header: SealedHeader::new(header, seal), - body: body.clone().into_iter().map(|tx| tx.into_signed()).collect(), - ommers: Vec::new(), - withdrawals: Some(Withdrawals::default()), - requests: None, + body: BlockBody { + transactions: body.clone().into_iter().map(|tx| tx.into_signed()).collect(), + ommers: Vec::new(), + withdrawals: Some(Withdrawals::default()), + requests: None, + }, }, body.iter().map(|tx| tx.signer()).collect(), ) diff --git a/crates/chain-state/src/in_memory.rs b/crates/chain-state/src/in_memory.rs index a098e10c2..2051fb308 100644 --- a/crates/chain-state/src/in_memory.rs +++ b/crates/chain-state/src/in_memory.rs @@ -542,7 +542,9 @@ impl CanonicalInMemoryState { /// Returns a `TransactionSigned` for the given `TxHash` if found. pub fn transaction_by_hash(&self, hash: TxHash) -> Option { for block_state in self.canonical_chain() { - if let Some(tx) = block_state.block().block().body.iter().find(|tx| tx.hash() == hash) { + if let Some(tx) = + block_state.block().block().body.transactions().find(|tx| tx.hash() == hash) + { return Some(tx.clone()) } } @@ -560,7 +562,7 @@ impl CanonicalInMemoryState { .block() .block() .body - .iter() + .transactions() .enumerate() .find(|(_, tx)| tx.hash() == tx_hash) { diff --git a/crates/chain-state/src/test_utils.rs b/crates/chain-state/src/test_utils.rs index c2b0f516d..6fa072f82 100644 --- a/crates/chain-state/src/test_utils.rs +++ b/crates/chain-state/src/test_utils.rs @@ -12,8 +12,8 @@ use reth_primitives::{ alloy_primitives::Sealable, constants::{EIP1559_INITIAL_BASE_FEE, EMPTY_ROOT_HASH}, proofs::{calculate_receipt_root, calculate_transaction_root, calculate_withdrawals_root}, - Header, Receipt, Receipts, Requests, SealedBlock, SealedBlockWithSenders, SealedHeader, - Transaction, TransactionSigned, TransactionSignedEcRecovered, TxEip1559, + BlockBody, Header, Receipt, Receipts, Requests, SealedBlock, SealedBlockWithSenders, + SealedHeader, Transaction, TransactionSigned, TransactionSignedEcRecovered, TxEip1559, }; use reth_trie::{root::state_root_unhashed, updates::TrieUpdates, HashedPostState}; use revm::{db::BundleState, primitives::AccountInfo}; @@ -165,10 +165,12 @@ impl TestBlockBuilder { let block = SealedBlock { header: SealedHeader::new(header, seal), - body: transactions.into_iter().map(|tx| tx.into_signed()).collect(), - ommers: Vec::new(), - withdrawals: Some(vec![].into()), - requests: None, + body: BlockBody { + transactions: transactions.into_iter().map(|tx| tx.into_signed()).collect(), + ommers: Vec::new(), + withdrawals: Some(vec![].into()), + requests: None, + }, }; SealedBlockWithSenders::new(block, vec![self.signer; num_txs as usize]).unwrap() @@ -254,6 +256,7 @@ impl TestBlockBuilder { pub fn get_execution_outcome(&mut self, block: SealedBlockWithSenders) -> ExecutionOutcome { let receipts = block .body + .transactions .iter() .enumerate() .map(|(idx, tx)| Receipt { @@ -266,7 +269,7 @@ impl TestBlockBuilder { let mut bundle_state_builder = BundleState::builder(block.number..=block.number); - for tx in &block.body { + for tx in &block.body.transactions { self.signer_execute_account_info.balance -= Self::single_tx_cost(); bundle_state_builder = bundle_state_builder.state_present_account_info( self.signer, diff --git a/crates/consensus/auto-seal/src/lib.rs b/crates/consensus/auto-seal/src/lib.rs index cb80f6b23..3f338e942 100644 --- a/crates/consensus/auto-seal/src/lib.rs +++ b/crates/consensus/auto-seal/src/lib.rs @@ -365,10 +365,12 @@ impl StorageInner { let block = Block { header, - body: transactions, - ommers: ommers.clone(), - withdrawals: withdrawals.clone(), - requests: requests.clone(), + body: BlockBody { + transactions, + ommers: ommers.clone(), + withdrawals: withdrawals.clone(), + requests: requests.clone(), + }, } .with_recovered_senders() .ok_or(BlockExecutionError::Validation(BlockValidationError::SenderRecoveryError))?; @@ -391,7 +393,7 @@ impl StorageInner { // root here let Block { mut header, body, .. } = block.block; - let body = BlockBody { transactions: body, ommers, withdrawals, requests }; + let body = BlockBody { transactions: body.transactions, ommers, withdrawals, requests }; trace!(target: "consensus::auto", ?execution_outcome, ?header, ?body, "executed block, calculating state root and completing header"); diff --git a/crates/consensus/beacon/src/engine/mod.rs b/crates/consensus/beacon/src/engine/mod.rs index 4c39c052a..74515f6c3 100644 --- a/crates/consensus/beacon/src/engine/mod.rs +++ b/crates/consensus/beacon/src/engine/mod.rs @@ -2862,7 +2862,7 @@ mod tests { block1 = block1.unseal().seal_slow(); let (block2, exec_result2) = data.blocks[1].clone(); let mut block2 = block2.unseal().block; - block2.withdrawals = None; + block2.body.withdrawals = None; block2.header.parent_hash = block1.hash(); block2.header.base_fee_per_gas = Some(100); block2.header.difficulty = U256::ZERO; diff --git a/crates/consensus/common/src/validation.rs b/crates/consensus/common/src/validation.rs index edb287d58..646ab7b47 100644 --- a/crates/consensus/common/src/validation.rs +++ b/crates/consensus/common/src/validation.rs @@ -44,7 +44,8 @@ pub fn validate_header_base_fee( /// [EIP-4895]: https://eips.ethereum.org/EIPS/eip-4895 #[inline] pub fn validate_shanghai_withdrawals(block: &SealedBlock) -> Result<(), ConsensusError> { - let withdrawals = block.withdrawals.as_ref().ok_or(ConsensusError::BodyWithdrawalsMissing)?; + let withdrawals = + block.body.withdrawals.as_ref().ok_or(ConsensusError::BodyWithdrawalsMissing)?; let withdrawals_root = reth_primitives::proofs::calculate_withdrawals_root(withdrawals); let header_withdrawals_root = block.withdrawals_root.as_ref().ok_or(ConsensusError::WithdrawalsRootMissing)?; @@ -84,13 +85,12 @@ pub fn validate_cancun_gas(block: &SealedBlock) -> Result<(), ConsensusError> { /// [EIP-7685]: https://eips.ethereum.org/EIPS/eip-7685 #[inline] pub fn validate_prague_request(block: &SealedBlock) -> Result<(), ConsensusError> { - let requests = block.requests.as_ref().ok_or(ConsensusError::BodyRequestsMissing)?; - let requests_root = reth_primitives::proofs::calculate_requests_root(&requests.0); - let header_requests_root = - block.requests_root.as_ref().ok_or(ConsensusError::RequestsRootMissing)?; + let requests_root = + block.body.calculate_requests_root().ok_or(ConsensusError::BodyRequestsMissing)?; + let header_requests_root = block.requests_root.ok_or(ConsensusError::RequestsRootMissing)?; if requests_root != *header_requests_root { return Err(ConsensusError::BodyRequestsRootDiff( - GotExpected { got: requests_root, expected: *header_requests_root }.into(), + GotExpected { got: requests_root, expected: header_requests_root }.into(), )); } Ok(()) @@ -107,7 +107,7 @@ pub fn validate_block_pre_execution( chain_spec: &ChainSpec, ) -> Result<(), ConsensusError> { // Check ommers hash - let ommers_hash = reth_primitives::proofs::calculate_ommers_root(&block.ommers); + let ommers_hash = block.body.calculate_ommers_root(); if block.header.ommers_hash != ommers_hash { return Err(ConsensusError::BodyOmmersHashDiff( GotExpected { got: ommers_hash, expected: block.header.ommers_hash }.into(), @@ -473,7 +473,7 @@ mod tests { parent.timestamp -= 1; let ommers = Vec::new(); - let body = Vec::new(); + let transactions = Vec::new(); let sealed = header.seal_slow(); let (header, seal) = sealed.into_parts(); @@ -481,10 +481,7 @@ mod tests { ( SealedBlock { header: SealedHeader::new(header, seal), - body, - ommers, - withdrawals: None, - requests: None, + body: BlockBody { transactions, ommers, withdrawals: None, requests: None }, }, parent, ) @@ -511,8 +508,7 @@ mod tests { SealedBlock { header: SealedHeader::new(header, seal), - withdrawals: Some(withdrawals), - ..Default::default() + body: BlockBody { withdrawals: Some(withdrawals), ..Default::default() }, } }; diff --git a/crates/e2e-test-utils/src/payload.rs b/crates/e2e-test-utils/src/payload.rs index e2f1445e7..1f9a89307 100644 --- a/crates/e2e-test-utils/src/payload.rs +++ b/crates/e2e-test-utils/src/payload.rs @@ -50,7 +50,7 @@ impl PayloadTestContext { pub async fn wait_for_built_payload(&self, payload_id: PayloadId) { loop { let payload = self.payload_builder.best_payload(payload_id).await.unwrap().unwrap(); - if payload.block().body.is_empty() { + if payload.block().body.transactions.is_empty() { tokio::time::sleep(std::time::Duration::from_millis(20)).await; continue } diff --git a/crates/engine/util/src/reorg.rs b/crates/engine/util/src/reorg.rs index d72115294..5c775ce7c 100644 --- a/crates/engine/util/src/reorg.rs +++ b/crates/engine/util/src/reorg.rs @@ -10,7 +10,7 @@ use reth_ethereum_forks::EthereumHardforks; use reth_evm::{system_calls::apply_beacon_root_contract_call, ConfigureEvm}; use reth_payload_validator::ExecutionPayloadValidator; use reth_primitives::{ - eip4844::calculate_excess_blob_gas, proofs, Block, Header, Receipt, Receipts, + eip4844::calculate_excess_blob_gas, proofs, Block, BlockBody, Header, Receipt, Receipts, }; use reth_provider::{BlockReader, ExecutionOutcome, ProviderError, StateProviderFactory}; use reth_revm::{ @@ -251,7 +251,7 @@ where // Fetch reorg target block depending on its depth and its parent. let mut previous_hash = next_block.parent_hash; - let mut candidate_transactions = next_block.body; + let mut candidate_transactions = next_block.body.transactions; let reorg_target = 'target: { loop { let reorg_target = provider @@ -263,7 +263,7 @@ where depth -= 1; previous_hash = reorg_target.parent_hash; - candidate_transactions = reorg_target.body; + candidate_transactions = reorg_target.body.transactions; } }; let reorg_target_parent = provider @@ -347,7 +347,7 @@ where } drop(evm); - if let Some(withdrawals) = &reorg_target.withdrawals { + if let Some(withdrawals) = &reorg_target.body.withdrawals { state.increment_balances(post_block_withdrawals_balance_increments( chain_spec, reorg_target.timestamp, @@ -407,10 +407,12 @@ where excess_blob_gas: excess_blob_gas.map(Into::into), state_root: state_provider.state_root(hashed_state)?, }, - body: transactions, - ommers: reorg_target.ommers, - withdrawals: reorg_target.withdrawals, - requests: None, // TODO(prague) + body: BlockBody { + transactions, + ommers: reorg_target.body.ommers, + withdrawals: reorg_target.body.withdrawals, + requests: None, // TODO(prague) + }, } .seal_slow(); diff --git a/crates/ethereum/evm/src/execute.rs b/crates/ethereum/evm/src/execute.rs index f8b6efe42..b0ab89a7e 100644 --- a/crates/ethereum/evm/src/execute.rs +++ b/crates/ethereum/evm/src/execute.rs @@ -163,7 +163,7 @@ where // execute transactions let mut cumulative_gas_used = 0; - let mut receipts = Vec::with_capacity(block.body.len()); + let mut receipts = Vec::with_capacity(block.body.transactions.len()); for (sender, transaction) in block.transactions_with_sender() { // The sum of the transaction’s gas limit, Tg, and the gas utilized in this block prior, // must be no greater than the block’s gasLimit. @@ -481,7 +481,8 @@ mod tests { use reth_chainspec::{ChainSpecBuilder, ForkCondition}; use reth_primitives::{ constants::{EMPTY_ROOT_HASH, ETH_TO_WEI}, - keccak256, public_key_to_address, Account, Block, Transaction, TxKind, TxLegacy, B256, + keccak256, public_key_to_address, Account, Block, BlockBody, Transaction, TxKind, TxLegacy, + B256, }; use reth_revm::{ database::StateProviderDatabase, test_utils::StateProviderTest, TransitionState, @@ -557,10 +558,12 @@ mod tests { &BlockWithSenders { block: Block { header: header.clone(), - body: vec![], - ommers: vec![], - withdrawals: None, - requests: None, + body: BlockBody { + transactions: vec![], + ommers: vec![], + withdrawals: None, + requests: None, + }, }, senders: vec![], }, @@ -588,10 +591,12 @@ mod tests { &BlockWithSenders { block: Block { header: header.clone(), - body: vec![], - ommers: vec![], - withdrawals: None, - requests: None, + body: BlockBody { + transactions: vec![], + ommers: vec![], + withdrawals: None, + requests: None, + }, }, senders: vec![], }, @@ -654,10 +659,12 @@ mod tests { &BlockWithSenders { block: Block { header, - body: vec![], - ommers: vec![], - withdrawals: None, - requests: None, + body: BlockBody { + transactions: vec![], + ommers: vec![], + withdrawals: None, + requests: None, + }, }, senders: vec![], }, @@ -707,10 +714,12 @@ mod tests { &BlockWithSenders { block: Block { header, - body: vec![], - ommers: vec![], - withdrawals: None, - requests: None, + body: BlockBody { + transactions: vec![], + ommers: vec![], + withdrawals: None, + requests: None, + }, }, senders: vec![], }, @@ -749,13 +758,7 @@ mod tests { .execute_and_verify_one( ( &BlockWithSenders { - block: Block { - header: header.clone(), - body: vec![], - ommers: vec![], - withdrawals: None, - requests: None, - }, + block: Block { header: header.clone(), body: Default::default() }, senders: vec![], }, U256::ZERO, @@ -776,13 +779,7 @@ mod tests { .execute_and_verify_one( ( &BlockWithSenders { - block: Block { - header, - body: vec![], - ommers: vec![], - withdrawals: None, - requests: None, - }, + block: Block { header, body: Default::default() }, senders: vec![], }, U256::ZERO, @@ -835,13 +832,7 @@ mod tests { .execute_and_verify_one( ( &BlockWithSenders { - block: Block { - header: header.clone(), - body: vec![], - ommers: vec![], - withdrawals: None, - requests: None, - }, + block: Block { header: header.clone(), body: Default::default() }, senders: vec![], }, U256::ZERO, @@ -920,13 +911,7 @@ mod tests { .execute_and_verify_one( ( &BlockWithSenders { - block: Block { - header, - body: vec![], - ommers: vec![], - withdrawals: None, - requests: None, - }, + block: Block { header, body: Default::default() }, senders: vec![], }, U256::ZERO, @@ -970,13 +955,7 @@ mod tests { .execute_and_verify_one( ( &BlockWithSenders { - block: Block { - header, - body: vec![], - ommers: vec![], - withdrawals: None, - requests: None, - }, + block: Block { header, body: Default::default() }, senders: vec![], }, U256::ZERO, @@ -1027,13 +1006,7 @@ mod tests { .execute_and_verify_one( ( &BlockWithSenders { - block: Block { - header, - body: vec![], - ommers: vec![], - withdrawals: None, - requests: None, - }, + block: Block { header, body: Default::default() }, senders: vec![], }, U256::ZERO, @@ -1090,13 +1063,7 @@ mod tests { .execute_and_verify_one( ( &BlockWithSenders { - block: Block { - header, - body: vec![], - ommers: vec![], - withdrawals: None, - requests: None, - }, + block: Block { header, body: Default::default() }, senders: vec![], }, U256::ZERO, @@ -1144,13 +1111,7 @@ mod tests { .execute_and_verify_one( ( &BlockWithSenders { - block: Block { - header, - body: vec![], - ommers: vec![], - withdrawals: None, - requests: None, - }, + block: Block { header, body: Default::default() }, senders: vec![], }, U256::ZERO, @@ -1186,13 +1147,7 @@ mod tests { .execute_and_verify_one( ( &BlockWithSenders { - block: Block { - header, - body: vec![], - ommers: vec![], - withdrawals: None, - requests: None, - }, + block: Block { header, body: Default::default() }, senders: vec![], }, U256::ZERO, @@ -1228,13 +1183,7 @@ mod tests { .execute_and_verify_one( ( &BlockWithSenders { - block: Block { - header, - body: vec![], - ommers: vec![], - withdrawals: None, - requests: None, - }, + block: Block { header, body: Default::default() }, senders: vec![], }, U256::ZERO, @@ -1319,10 +1268,7 @@ mod tests { ( &Block { header, - body: vec![tx], - ommers: vec![], - withdrawals: None, - requests: None, + body: BlockBody { transactions: vec![tx], ..Default::default() }, } .with_recovered_senders() .unwrap(), @@ -1405,15 +1351,9 @@ mod tests { // Execute the block and capture the result let exec_result = executor.execute( ( - &Block { - header, - body: vec![tx], - ommers: vec![], - withdrawals: None, - requests: None, - } - .with_recovered_senders() - .unwrap(), + &Block { header, body: BlockBody { transactions: vec![tx], ..Default::default() } } + .with_recovered_senders() + .unwrap(), U256::ZERO, ) .into(), diff --git a/crates/ethereum/payload/src/lib.rs b/crates/ethereum/payload/src/lib.rs index 0678d73c9..168b51444 100644 --- a/crates/ethereum/payload/src/lib.rs +++ b/crates/ethereum/payload/src/lib.rs @@ -32,8 +32,8 @@ use reth_primitives::{ eip4844::calculate_excess_blob_gas, proofs::{self, calculate_requests_root}, revm_primitives::{BlockEnv, CfgEnvWithHandlerCfg}, - Block, EthereumHardforks, Header, IntoRecoveredTransaction, Receipt, EMPTY_OMMER_ROOT_HASH, - U256, + Block, BlockBody, EthereumHardforks, Header, IntoRecoveredTransaction, Receipt, + EMPTY_OMMER_ROOT_HASH, U256, }; use reth_provider::StateProviderFactory; use reth_revm::database::StateProviderDatabase; @@ -427,7 +427,10 @@ where }; // seal the block - let block = Block { header, body: executed_txs, ommers: vec![], withdrawals, requests }; + let block = Block { + header, + body: BlockBody { transactions: executed_txs, ommers: vec![], withdrawals, requests }, + }; let sealed_block = block.seal_slow(); debug!(target: "payload_builder", ?sealed_block, "sealed built block"); diff --git a/crates/evm/execution-types/src/chain.rs b/crates/evm/execution-types/src/chain.rs index ca88fa87a..4d0dc694a 100644 --- a/crates/evm/execution-types/src/chain.rs +++ b/crates/evm/execution-types/src/chain.rs @@ -231,7 +231,7 @@ impl Chain { self.blocks().iter().zip(self.execution_outcome.receipts().iter()) { let mut tx_receipts = Vec::new(); - for (tx, receipt) in block.body.iter().zip(receipts.iter()) { + for (tx, receipt) in block.body.transactions().zip(receipts.iter()) { tx_receipts.push(( tx.hash(), receipt.as_ref().expect("receipts have not been pruned").clone(), @@ -412,7 +412,7 @@ impl<'a> ChainBlocks<'a> { /// Returns an iterator over all transactions in the chain. #[inline] pub fn transactions(&self) -> impl Iterator + '_ { - self.blocks.values().flat_map(|block| block.body.iter()) + self.blocks.values().flat_map(|block| block.body.transactions()) } /// Returns an iterator over all transactions and their senders. diff --git a/crates/evm/src/execute.rs b/crates/evm/src/execute.rs index f3ff794cd..60a29d4de 100644 --- a/crates/evm/src/execute.rs +++ b/crates/evm/src/execute.rs @@ -151,7 +151,6 @@ pub trait BlockExecutorProvider: Send + Sync + Clone + Unpin + 'static { #[cfg(test)] mod tests { use super::*; - use reth_primitives::Block; use revm::db::{CacheDB, EmptyDBTyped}; use revm_primitives::U256; use std::marker::PhantomData; @@ -232,14 +231,6 @@ mod tests { let provider = TestExecutorProvider; let db = CacheDB::>::default(); let executor = provider.executor(db); - let block = Block { - header: Default::default(), - body: vec![], - ommers: vec![], - withdrawals: None, - requests: None, - }; - let block = BlockWithSenders::new(block, Default::default()).unwrap(); - let _ = executor.execute(BlockExecutionInput::new(&block, U256::ZERO)); + let _ = executor.execute(BlockExecutionInput::new(&Default::default(), U256::ZERO)); } } diff --git a/crates/exex/exex/src/backfill/job.rs b/crates/exex/exex/src/backfill/job.rs index 948f8f606..6e7307f1f 100644 --- a/crates/exex/exex/src/backfill/job.rs +++ b/crates/exex/exex/src/backfill/job.rs @@ -8,7 +8,7 @@ use alloy_primitives::BlockNumber; use reth_evm::execute::{ BatchExecutor, BlockExecutionError, BlockExecutionOutput, BlockExecutorProvider, Executor, }; -use reth_primitives::{Block, BlockWithSenders, Receipt}; +use reth_primitives::{Block, BlockBody, BlockWithSenders, Receipt}; use reth_primitives_traits::format_gas_throughput; use reth_provider::{ BlockReader, Chain, HeaderProvider, ProviderError, StateProviderFactory, TransactionVariant, @@ -95,7 +95,7 @@ where cumulative_gas += block.gas_used; // Configure the executor to use the current state. - trace!(target: "exex::backfill", number = block_number, txs = block.body.len(), "Executing block"); + trace!(target: "exex::backfill", number = block_number, txs = block.body.transactions.len(), "Executing block"); // Execute the block let execute_start = Instant::now(); @@ -105,10 +105,12 @@ where let (unsealed_header, hash) = block.header.split(); let block = Block { header: unsealed_header, - body: block.body, - ommers: block.ommers, - withdrawals: block.withdrawals, - requests: block.requests, + body: BlockBody { + transactions: block.body.transactions, + ommers: block.body.ommers, + withdrawals: block.body.withdrawals, + requests: block.body.requests, + }, } .with_senders_unchecked(senders); @@ -204,7 +206,7 @@ where self.provider.history_by_block_number(block_number.saturating_sub(1))?, )); - trace!(target: "exex::backfill", number = block_number, txs = block_with_senders.block.body.len(), "Executing block"); + trace!(target: "exex::backfill", number = block_number, txs = block_with_senders.block.body.transactions.len(), "Executing block"); let block_execution_output = executor.execute((&block_with_senders, td).into())?; diff --git a/crates/exex/exex/src/backfill/test_utils.rs b/crates/exex/exex/src/backfill/test_utils.rs index 780a714b5..8c99ea7f1 100644 --- a/crates/exex/exex/src/backfill/test_utils.rs +++ b/crates/exex/exex/src/backfill/test_utils.rs @@ -8,8 +8,8 @@ use reth_evm::execute::{ }; use reth_evm_ethereum::execute::EthExecutorProvider; use reth_primitives::{ - constants::ETH_TO_WEI, Block, BlockWithSenders, Genesis, GenesisAccount, Header, Receipt, - Requests, SealedBlockWithSenders, Transaction, TxEip2930, + constants::ETH_TO_WEI, Block, BlockBody, BlockWithSenders, Genesis, GenesisAccount, Header, + Receipt, Requests, SealedBlockWithSenders, Transaction, TxEip2930, }; use reth_provider::{ providers::ProviderNodeTypes, BlockWriter as _, ExecutionOutcome, LatestStateProviderRef, @@ -103,19 +103,21 @@ fn blocks( gas_used: MIN_TRANSACTION_GAS.into(), ..Default::default() }, - body: vec![sign_tx_with_key_pair( - key_pair, - Transaction::Eip2930(TxEip2930 { - chain_id: chain_spec.chain.id(), - nonce: 0, - gas_limit: MIN_TRANSACTION_GAS as u128, - gas_price: 1_500_000_000, - to: TxKind::Call(Address::ZERO), - value: U256::from(0.1 * ETH_TO_WEI as f64), - ..Default::default() - }), - )], - ..Default::default() + body: BlockBody { + transactions: vec![sign_tx_with_key_pair( + key_pair, + Transaction::Eip2930(TxEip2930 { + chain_id: chain_spec.chain.id(), + nonce: 0, + gas_limit: MIN_TRANSACTION_GAS as u128, + gas_price: 1_500_000_000, + to: TxKind::Call(Address::ZERO), + value: U256::from(0.1 * ETH_TO_WEI as f64), + ..Default::default() + }), + )], + ..Default::default() + }, } .with_recovered_senders() .ok_or_eyre("failed to recover senders")?; @@ -133,19 +135,21 @@ fn blocks( gas_used: MIN_TRANSACTION_GAS.into(), ..Default::default() }, - body: vec![sign_tx_with_key_pair( - key_pair, - Transaction::Eip2930(TxEip2930 { - chain_id: chain_spec.chain.id(), - nonce: 1, - gas_limit: MIN_TRANSACTION_GAS as u128, - gas_price: 1_500_000_000, - to: TxKind::Call(Address::ZERO), - value: U256::from(0.1 * ETH_TO_WEI as f64), - ..Default::default() - }), - )], - ..Default::default() + body: BlockBody { + transactions: vec![sign_tx_with_key_pair( + key_pair, + Transaction::Eip2930(TxEip2930 { + chain_id: chain_spec.chain.id(), + nonce: 1, + gas_limit: MIN_TRANSACTION_GAS as u128, + gas_price: 1_500_000_000, + to: TxKind::Call(Address::ZERO), + value: U256::from(0.1 * ETH_TO_WEI as f64), + ..Default::default() + }), + )], + ..Default::default() + }, } .with_recovered_senders() .ok_or_eyre("failed to recover senders")?; diff --git a/crates/net/downloaders/src/bodies/bodies.rs b/crates/net/downloaders/src/bodies/bodies.rs index 21b7cd81c..314f3a090 100644 --- a/crates/net/downloaders/src/bodies/bodies.rs +++ b/crates/net/downloaders/src/bodies/bodies.rs @@ -607,7 +607,6 @@ mod tests { use reth_chainspec::MAINNET; use reth_consensus::test_utils::TestConsensus; use reth_db::test_utils::{create_test_rw_db, create_test_static_files_dir}; - use reth_primitives::BlockBody; use reth_provider::{ providers::StaticFileProvider, test_utils::MockNodeTypesWithDB, ProviderFactory, }; @@ -661,20 +660,8 @@ mod tests { ); let headers = blocks.iter().map(|block| block.header.clone()).collect::>(); - let bodies = blocks - .into_iter() - .map(|block| { - ( - block.hash(), - BlockBody { - transactions: block.body, - ommers: block.ommers, - withdrawals: None, - requests: None, - }, - ) - }) - .collect::>(); + let bodies = + blocks.into_iter().map(|block| (block.hash(), block.body)).collect::>(); insert_headers(db.db(), &headers); diff --git a/crates/net/downloaders/src/bodies/test_utils.rs b/crates/net/downloaders/src/bodies/test_utils.rs index 76d2201f0..d61e1f7fb 100644 --- a/crates/net/downloaders/src/bodies/test_utils.rs +++ b/crates/net/downloaders/src/bodies/test_utils.rs @@ -20,13 +20,7 @@ pub(crate) fn zip_blocks<'a>( if header.is_empty() { BlockResponse::Empty(header.clone()) } else { - BlockResponse::Full(SealedBlock { - header: header.clone(), - body: body.transactions, - ommers: body.ommers, - withdrawals: body.withdrawals, - requests: body.requests, - }) + BlockResponse::Full(SealedBlock { header: header.clone(), body }) } }) .collect() diff --git a/crates/net/downloaders/src/test_utils/mod.rs b/crates/net/downloaders/src/test_utils/mod.rs index e83b7ee58..7755c5e60 100644 --- a/crates/net/downloaders/src/test_utils/mod.rs +++ b/crates/net/downloaders/src/test_utils/mod.rs @@ -29,20 +29,7 @@ pub(crate) fn generate_bodies( ); let headers = blocks.iter().map(|block| block.header.clone()).collect(); - let bodies = blocks - .into_iter() - .map(|block| { - ( - block.hash(), - BlockBody { - transactions: block.body, - ommers: block.ommers, - withdrawals: block.withdrawals, - requests: block.requests, - }, - ) - }) - .collect(); + let bodies = blocks.into_iter().map(|block| (block.hash(), block.body)).collect(); (headers, bodies) } diff --git a/crates/net/network/tests/it/requests.rs b/crates/net/network/tests/it/requests.rs index 779c90ef0..5c32ce46f 100644 --- a/crates/net/network/tests/it/requests.rs +++ b/crates/net/network/tests/it/requests.rs @@ -16,8 +16,7 @@ use reth_network_p2p::{ headers::client::{HeadersClient, HeadersRequest}, }; use reth_primitives::{ - alloy_primitives::Parity, Block, BlockBody, Header, Signature, Transaction, TransactionSigned, - TxEip2930, + alloy_primitives::Parity, Block, Header, Signature, Transaction, TransactionSigned, TxEip2930, }; use reth_provider::test_utils::MockEthProvider; @@ -67,7 +66,7 @@ async fn test_get_body() { // Set a new random block to the mock storage and request it via the network let block_hash = rng.gen(); let mut block = Block::default(); - block.body.push(rng_transaction(&mut rng)); + block.body.transactions.push(rng_transaction(&mut rng)); mock_provider.add_block(block_hash, block.clone()); @@ -76,13 +75,7 @@ async fn test_get_body() { let blocks = res.unwrap().1; assert_eq!(blocks.len(), 1); - let expected = BlockBody { - transactions: block.body, - ommers: block.ommers, - withdrawals: None, - requests: None, - }; - assert_eq!(blocks[0], expected); + assert_eq!(blocks[0], block.body); } } diff --git a/crates/node/core/src/utils.rs b/crates/node/core/src/utils.rs index e6b970b90..ae9b1f021 100644 --- a/crates/node/core/src/utils.rs +++ b/crates/node/core/src/utils.rs @@ -91,14 +91,8 @@ where eyre::bail!("Invalid number of bodies received. Expected: 1. Received: 0") } - let block = response.unwrap(); - let block = SealedBlock { - header, - body: block.transactions, - ommers: block.ommers, - withdrawals: block.withdrawals, - requests: block.requests, - }; + let body = response.unwrap(); + let block = SealedBlock { header, body }; validate_block_pre_execution(&block, &chain_spec)?; diff --git a/crates/node/events/src/node.rs b/crates/node/events/src/node.rs index d72c64f29..9375b948d 100644 --- a/crates/node/events/src/node.rs +++ b/crates/node/events/src/node.rs @@ -259,7 +259,7 @@ impl NodeState { number=block.number, hash=?block.hash(), peers=self.num_connected_peers(), - txs=block.body.len(), + txs=block.body.transactions.len(), gas=%format_gas(block.header.gas_used as u64), gas_throughput=%format_gas_throughput(block.header.gas_used as u64, elapsed), full=%format!("{:.1}%", block.header.gas_used as f64 * 100.0 / block.header.gas_limit as f64), diff --git a/crates/optimism/consensus/src/lib.rs b/crates/optimism/consensus/src/lib.rs index bcad8facd..1f529a9a9 100644 --- a/crates/optimism/consensus/src/lib.rs +++ b/crates/optimism/consensus/src/lib.rs @@ -124,7 +124,7 @@ impl Consensus for OptimismBeaconConsensus { fn validate_block_pre_execution(&self, block: &SealedBlock) -> Result<(), ConsensusError> { // Check ommers hash - let ommers_hash = reth_primitives::proofs::calculate_ommers_root(&block.ommers); + let ommers_hash = reth_primitives::proofs::calculate_ommers_root(&block.body.ommers); if block.header.ommers_hash != ommers_hash { return Err(ConsensusError::BodyOmmersHashDiff( GotExpected { got: ommers_hash, expected: block.header.ommers_hash }.into(), diff --git a/crates/optimism/evm/src/execute.rs b/crates/optimism/evm/src/execute.rs index af61e37e9..ceae0314f 100644 --- a/crates/optimism/evm/src/execute.rs +++ b/crates/optimism/evm/src/execute.rs @@ -144,7 +144,7 @@ where .map_err(|_| OptimismBlockExecutionError::ForceCreate2DeployerFail)?; let mut cumulative_gas_used = 0; - let mut receipts = Vec::with_capacity(block.body.len()); + let mut receipts = Vec::with_capacity(block.body.transactions.len()); for (sender, transaction) in block.transactions_with_sender() { // The sum of the transaction’s gas limit, Tg, and the gas utilized in this block prior, // must be no greater than the block’s gasLimit. @@ -468,7 +468,8 @@ mod tests { use reth_chainspec::{ChainSpecBuilder, MIN_TRANSACTION_GAS}; use reth_optimism_chainspec::optimism_deposit_tx_signature; use reth_primitives::{ - Account, Block, Signature, Transaction, TransactionSigned, TxEip1559, BASE_MAINNET, + Account, Block, BlockBody, Signature, Transaction, TransactionSigned, TxEip1559, + BASE_MAINNET, }; use reth_revm::{ database::StateProviderDatabase, test_utils::StateProviderTest, L1_BLOCK_CONTRACT, @@ -569,10 +570,10 @@ mod tests { &BlockWithSenders { block: Block { header, - body: vec![tx, tx_deposit], - ommers: vec![], - withdrawals: None, - requests: None, + body: BlockBody { + transactions: vec![tx, tx_deposit], + ..Default::default() + }, }, senders: vec![addr, addr], }, @@ -653,10 +654,10 @@ mod tests { &BlockWithSenders { block: Block { header, - body: vec![tx, tx_deposit], - ommers: vec![], - withdrawals: None, - requests: None, + body: BlockBody { + transactions: vec![tx, tx_deposit], + ..Default::default() + }, }, senders: vec![addr, addr], }, diff --git a/crates/optimism/evm/src/l1.rs b/crates/optimism/evm/src/l1.rs index e15ad2fbf..081e21d80 100644 --- a/crates/optimism/evm/src/l1.rs +++ b/crates/optimism/evm/src/l1.rs @@ -33,6 +33,7 @@ const L1_BLOCK_ECOTONE_SELECTOR: [u8; 4] = hex!("440a5e20"); pub fn extract_l1_info(block: &Block) -> Result { let l1_info_tx_data = block .body + .transactions .first() .ok_or_else(|| OptimismBlockExecutionError::L1BlockInfoError { message: "could not find l1 block info tx in the L2 block".to_string(), @@ -299,7 +300,7 @@ where mod tests { use reth_optimism_chainspec::OP_MAINNET; use reth_optimism_forks::OptimismHardforks; - use reth_primitives::TransactionSigned; + use reth_primitives::{BlockBody, TransactionSigned}; use super::*; @@ -312,10 +313,7 @@ mod tests { let l1_info_tx = TransactionSigned::decode_enveloped(&mut bytes.as_ref()).unwrap(); let mock_block = Block { header: Header::default(), - body: vec![l1_info_tx], - ommers: Vec::default(), - withdrawals: None, - requests: None, + body: BlockBody { transactions: vec![l1_info_tx], ..Default::default() }, }; let l1_info: L1BlockInfo = extract_l1_info(&mock_block).unwrap(); @@ -341,7 +339,10 @@ mod tests { const TX: [u8; 251] = hex!("7ef8f8a0a539eb753df3b13b7e386e147d45822b67cb908c9ddc5618e3dbaa22ed00850b94deaddeaddeaddeaddeaddeaddeaddeaddead00019442000000000000000000000000000000000000158080830f424080b8a4440a5e2000000558000c5fc50000000000000000000000006605a89f00000000012a10d90000000000000000000000000000000000000000000000000000000af39ac3270000000000000000000000000000000000000000000000000000000d5ea528d24e582fa68786f080069bdbfe06a43f8e67bfd31b8e4d8a8837ba41da9a82a54a0000000000000000000000006887246668a3b87f54deb3b94ba47a6f63f32985"); let tx = TransactionSigned::decode_enveloped(&mut TX.as_slice()).unwrap(); - let block = Block { body: vec![tx], ..Default::default() }; + let block = Block { + body: BlockBody { transactions: vec![tx], ..Default::default() }, + ..Default::default() + }; // expected l1 block info let expected_l1_base_fee = U256::from_be_bytes(hex!( diff --git a/crates/optimism/payload/src/builder.rs b/crates/optimism/payload/src/builder.rs index 2565329eb..447431536 100644 --- a/crates/optimism/payload/src/builder.rs +++ b/crates/optimism/payload/src/builder.rs @@ -18,7 +18,7 @@ use reth_primitives::{ eip4844::calculate_excess_blob_gas, proofs, revm_primitives::{BlockEnv, CfgEnvWithHandlerCfg}, - Block, Header, IntoRecoveredTransaction, Receipt, TxType, EMPTY_OMMER_ROOT_HASH, + Block, BlockBody, Header, IntoRecoveredTransaction, Receipt, TxType, EMPTY_OMMER_ROOT_HASH, }; use reth_provider::StateProviderFactory; use reth_revm::database::StateProviderDatabase; @@ -514,7 +514,10 @@ where }; // seal the block - let block = Block { header, body: executed_txs, ommers: vec![], withdrawals, requests: None }; + let block = Block { + header, + body: BlockBody { transactions: executed_txs, ommers: vec![], withdrawals, requests: None }, + }; let sealed_block = block.seal_slow(); debug!(target: "payload_builder", ?sealed_block, "sealed built block"); diff --git a/crates/optimism/rpc/src/eth/block.rs b/crates/optimism/rpc/src/eth/block.rs index ec210dbe1..41267a1e7 100644 --- a/crates/optimism/rpc/src/eth/block.rs +++ b/crates/optimism/rpc/src/eth/block.rs @@ -48,6 +48,7 @@ where return block .body + .transactions .into_iter() .zip(receipts.iter()) .enumerate() diff --git a/crates/optimism/rpc/src/eth/receipt.rs b/crates/optimism/rpc/src/eth/receipt.rs index c08cbf5d3..a98ee68d6 100644 --- a/crates/optimism/rpc/src/eth/receipt.rs +++ b/crates/optimism/rpc/src/eth/receipt.rs @@ -300,7 +300,7 @@ impl OpReceiptBuilder { mod test { use alloy_primitives::hex; use reth_optimism_chainspec::OP_MAINNET; - use reth_primitives::Block; + use reth_primitives::{Block, BlockBody}; use super::*; @@ -349,7 +349,10 @@ mod test { TransactionSigned::decode_enveloped(&mut TX_1_OP_MAINNET_BLOCK_124665056.as_slice()) .unwrap(); - let block = Block { body: [tx_0, tx_1.clone()].to_vec(), ..Default::default() }; + let block = Block { + body: BlockBody { transactions: [tx_0, tx_1.clone()].to_vec(), ..Default::default() }, + ..Default::default() + }; let l1_block_info = reth_evm_optimism::extract_l1_info(&block).expect("should extract l1 info"); diff --git a/crates/payload/validator/src/lib.rs b/crates/payload/validator/src/lib.rs index a9e686b1e..55002b0a9 100644 --- a/crates/payload/validator/src/lib.rs +++ b/crates/payload/validator/src/lib.rs @@ -160,7 +160,7 @@ impl ExecutionPayloadValidator { } let shanghai_active = self.is_shanghai_active_at_timestamp(sealed_block.timestamp); - if !shanghai_active && sealed_block.withdrawals.is_some() { + if !shanghai_active && sealed_block.body.withdrawals.is_some() { // shanghai not active but withdrawals present return Err(PayloadError::PreShanghaiBlockWithWitdrawals) } diff --git a/crates/primitives/src/alloy_compat.rs b/crates/primitives/src/alloy_compat.rs index 94cf4bad4..8f8ec1b39 100644 --- a/crates/primitives/src/alloy_compat.rs +++ b/crates/primitives/src/alloy_compat.rs @@ -1,9 +1,9 @@ //! Common conversions from alloy types. use crate::{ - constants::EMPTY_TRANSACTIONS, transaction::extract_chain_id, Block, Signature, Transaction, - TransactionSigned, TransactionSignedEcRecovered, TransactionSignedNoHash, TxEip1559, TxEip2930, - TxEip4844, TxLegacy, TxType, + constants::EMPTY_TRANSACTIONS, transaction::extract_chain_id, Block, BlockBody, Signature, + Transaction, TransactionSigned, TransactionSignedEcRecovered, TransactionSignedNoHash, + TxEip1559, TxEip2930, TxEip4844, TxLegacy, TxType, }; use alloc::{string::ToString, vec::Vec}; use alloy_primitives::{Parity, TxKind}; @@ -19,7 +19,7 @@ impl TryFrom Result { use alloy_rpc_types::ConversionError; - let body = { + let transactions = { let transactions: Result, ConversionError> = match block .transactions { @@ -42,12 +42,14 @@ impl TryFrom, - /// Ommers/uncles header. - pub ommers: Vec
, - /// Block withdrawals. - pub withdrawals: Option, - /// Block requests. - pub requests: Option, + /// Block body. + pub body: BlockBody, } impl Block { @@ -53,31 +44,19 @@ impl Block { pub fn seal_slow(self) -> SealedBlock { let sealed = self.header.seal_slow(); let (header, seal) = sealed.into_parts(); - SealedBlock { - header: SealedHeader::new(header, seal), - body: self.body, - ommers: self.ommers, - withdrawals: self.withdrawals, - requests: self.requests, - } + SealedBlock { header: SealedHeader::new(header, seal), body: self.body } } /// Seal the block with a known hash. /// /// WARNING: This method does not perform validation whether the hash is correct. pub fn seal(self, hash: B256) -> SealedBlock { - SealedBlock { - header: SealedHeader::new(self.header, hash), - body: self.body, - ommers: self.ommers, - withdrawals: self.withdrawals, - requests: self.requests, - } + SealedBlock { header: SealedHeader::new(self.header, hash), body: self.body } } /// Expensive operation that recovers transaction signer. See [`SealedBlockWithSenders`]. pub fn senders(&self) -> Option> { - TransactionSigned::recover_signers(&self.body, self.body.len()) + self.body.recover_signers() } /// Transform into a [`BlockWithSenders`]. @@ -105,14 +84,10 @@ impl Block { self, senders: Vec
, ) -> Result { - let senders = if self.body.len() == senders.len() { + let senders = if self.body.transactions.len() == senders.len() { senders } else { - let Some(senders) = - TransactionSigned::recover_signers_unchecked(&self.body, self.body.len()) - else { - return Err(self) - }; + let Some(senders) = self.body.recover_signers() else { return Err(self) }; senders }; @@ -128,52 +103,104 @@ impl Block { Some(BlockWithSenders { block: self, senders }) } - /// Returns whether or not the block contains any blob transactions. - #[inline] - pub fn has_blob_transactions(&self) -> bool { - self.body.iter().any(|tx| tx.is_eip4844()) - } - - /// Returns whether or not the block contains any EIP-7702 transactions. - #[inline] - pub fn has_eip7702_transactions(&self) -> bool { - self.body.iter().any(|tx| tx.is_eip7702()) - } - - /// Returns an iterator over all blob transactions of the block - #[inline] - pub fn blob_transactions_iter(&self) -> impl Iterator + '_ { - self.body.iter().filter(|tx| tx.is_eip4844()) - } - - /// Returns only the blob transactions, if any, from the block body. - #[inline] - pub fn blob_transactions(&self) -> Vec<&TransactionSigned> { - self.blob_transactions_iter().collect() - } - - /// Returns an iterator over all blob versioned hashes from the block body. - #[inline] - pub fn blob_versioned_hashes_iter(&self) -> impl Iterator + '_ { - self.blob_transactions_iter() - .filter_map(|tx| tx.as_eip4844().map(|blob_tx| &blob_tx.blob_versioned_hashes)) - .flatten() - } - - /// Returns all blob versioned hashes from the block body. - #[inline] - pub fn blob_versioned_hashes(&self) -> Vec<&B256> { - self.blob_versioned_hashes_iter().collect() - } - /// Calculates a heuristic for the in-memory size of the [`Block`]. #[inline] pub fn size(&self) -> usize { - self.header.size() + - // take into account capacity - self.body.iter().map(TransactionSigned::size).sum::() + self.body.capacity() * core::mem::size_of::() + - self.ommers.iter().map(Header::size).sum::() + self.ommers.capacity() * core::mem::size_of::
() + - self.withdrawals.as_ref().map_or(core::mem::size_of::>(), Withdrawals::total_size) + self.header.size() + self.body.size() + } +} + +/// We need to implement RLP traits manually because we currently don't have a way to flatten +/// [`BlockBody`] into [`Block`]. +mod block_rlp { + use super::*; + + #[derive(RlpDecodable)] + #[rlp(trailing)] + struct Helper { + header: H, + transactions: Vec, + ommers: Vec
, + withdrawals: Option, + requests: Option, + } + + #[derive(RlpEncodable)] + #[rlp(trailing)] + struct HelperRef<'a, H> { + header: &'a H, + transactions: &'a Vec, + ommers: &'a Vec
, + withdrawals: Option<&'a Withdrawals>, + requests: Option<&'a Requests>, + } + + impl<'a> From<&'a Block> for HelperRef<'a, Header> { + fn from(block: &'a Block) -> Self { + let Block { header, body: BlockBody { transactions, ommers, withdrawals, requests } } = + block; + Self { + header, + transactions, + ommers, + withdrawals: withdrawals.as_ref(), + requests: requests.as_ref(), + } + } + } + + impl<'a> From<&'a SealedBlock> for HelperRef<'a, SealedHeader> { + fn from(block: &'a SealedBlock) -> Self { + let SealedBlock { + header, + body: BlockBody { transactions, ommers, withdrawals, requests }, + } = block; + Self { + header, + transactions, + ommers, + withdrawals: withdrawals.as_ref(), + requests: requests.as_ref(), + } + } + } + + impl Decodable for Block { + fn decode(b: &mut &[u8]) -> alloy_rlp::Result { + let Helper { header, transactions, ommers, withdrawals, requests } = Helper::decode(b)?; + Ok(Self { header, body: BlockBody { transactions, ommers, withdrawals, requests } }) + } + } + + impl Decodable for SealedBlock { + fn decode(b: &mut &[u8]) -> alloy_rlp::Result { + let Helper { header, transactions, ommers, withdrawals, requests } = Helper::decode(b)?; + Ok(Self { header, body: BlockBody { transactions, ommers, withdrawals, requests } }) + } + } + + impl Encodable for Block { + fn length(&self) -> usize { + let helper: HelperRef<'_, _> = self.into(); + helper.length() + } + + fn encode(&self, out: &mut dyn bytes::BufMut) { + let helper: HelperRef<'_, _> = self.into(); + helper.encode(out) + } + } + + impl Encodable for SealedBlock { + fn length(&self) -> usize { + let helper: HelperRef<'_, _> = self.into(); + helper.length() + } + + fn encode(&self, out: &mut dyn bytes::BufMut) { + let helper: HelperRef<'_, _> = self.into(); + helper.encode(out) + } } } @@ -205,11 +232,13 @@ impl<'a> arbitrary::Arbitrary<'a> for Block { Ok(Self { header: u.arbitrary()?, - body: transactions, - ommers, - // for now just generate empty requests, see HACK above - requests: u.arbitrary()?, - withdrawals: u.arbitrary()?, + body: BlockBody { + transactions, + ommers, + // for now just generate empty requests, see HACK above + requests: u.arbitrary()?, + withdrawals: u.arbitrary()?, + }, }) } } @@ -228,7 +257,7 @@ pub struct BlockWithSenders { impl BlockWithSenders { /// New block with senders. Return none if len of tx and senders does not match pub fn new(block: Block, senders: Vec
) -> Option { - (block.body.len() == senders.len()).then_some(Self { block, senders }) + (block.body.transactions.len() == senders.len()).then_some(Self { block, senders }) } /// Seal the block with a known hash. @@ -252,24 +281,12 @@ impl BlockWithSenders { (self.block, self.senders) } - /// Returns an iterator over all transactions in the block. - #[inline] - pub fn transactions(&self) -> impl Iterator + '_ { - self.block.body.iter() - } - /// Returns an iterator over all transactions and their sender. #[inline] pub fn transactions_with_sender( &self, ) -> impl Iterator + '_ { - self.senders.iter().zip(self.block.body.iter()) - } - - /// Consumes the block and returns the transactions of the block. - #[inline] - pub fn into_transactions(self) -> Vec { - self.block.body + self.senders.iter().zip(self.block.body.transactions()) } /// Returns an iterator over all transactions in the chain. @@ -277,7 +294,18 @@ impl BlockWithSenders { pub fn into_transactions_ecrecovered( self, ) -> impl Iterator { - self.block.body.into_iter().zip(self.senders).map(|(tx, sender)| tx.with_signer(sender)) + self.block + .body + .transactions + .into_iter() + .zip(self.senders) + .map(|(tx, sender)| tx.with_signer(sender)) + } + + /// Consumes the block and returns the transactions of the block. + #[inline] + pub fn into_transactions(self) -> Vec { + self.block.body.transactions } } @@ -286,41 +314,21 @@ impl BlockWithSenders { /// Withdrawals can be optionally included at the end of the RLP encoded message. #[cfg_attr(any(test, feature = "arbitrary"), derive(arbitrary::Arbitrary))] #[cfg_attr(any(test, feature = "reth-codec"), reth_codecs::add_arbitrary_tests(rlp, 32))] -#[derive( - Debug, - Clone, - PartialEq, - Eq, - Default, - Serialize, - Deserialize, - Deref, - DerefMut, - RlpEncodable, - RlpDecodable, -)] -#[rlp(trailing)] +#[derive(Debug, Clone, PartialEq, Eq, Default, Serialize, Deserialize, Deref, DerefMut)] pub struct SealedBlock { /// Locked block header. #[deref] #[deref_mut] pub header: SealedHeader, - /// Transactions with signatures. - pub body: Vec, - /// Ommer/uncle headers - pub ommers: Vec
, - /// Block withdrawals. - pub withdrawals: Option, - /// Block requests. - pub requests: Option, + /// Block body. + pub body: BlockBody, } impl SealedBlock { /// Create a new sealed block instance using the sealed header and block body. #[inline] - pub fn new(header: SealedHeader, body: BlockBody) -> Self { - let BlockBody { transactions, ommers, withdrawals, requests } = body; - Self { header, body: transactions, ommers, withdrawals, requests } + pub const fn new(header: SealedHeader, body: BlockBody) -> Self { + Self { header, body } } /// Header hash. @@ -332,27 +340,19 @@ impl SealedBlock { /// Splits the sealed block into underlying components #[inline] pub fn split(self) -> (SealedHeader, Vec, Vec
) { - (self.header, self.body, self.ommers) + (self.header, self.body.transactions, self.body.ommers) } /// Splits the [`BlockBody`] and [`SealedHeader`] into separate components #[inline] pub fn split_header_body(self) -> (SealedHeader, BlockBody) { - ( - self.header, - BlockBody { - transactions: self.body, - ommers: self.ommers, - withdrawals: self.withdrawals, - requests: self.requests, - }, - ) + (self.header, self.body) } /// Returns an iterator over all blob transactions of the block #[inline] pub fn blob_transactions_iter(&self) -> impl Iterator + '_ { - self.body.iter().filter(|tx| tx.is_eip4844()) + self.body.blob_transactions_iter() } /// Returns only the blob transactions, if any, from the block body. @@ -377,7 +377,7 @@ impl SealedBlock { /// Expensive operation that recovers transaction signer. See [`SealedBlockWithSenders`]. pub fn senders(&self) -> Option> { - TransactionSigned::recover_signers(&self.body, self.body.len()) + self.body.recover_signers() } /// Seal sealed block with recovered transaction senders. @@ -416,14 +416,10 @@ impl SealedBlock { self, senders: Vec
, ) -> Result { - let senders = if self.body.len() == senders.len() { + let senders = if self.body.transactions.len() == senders.len() { senders } else { - let Some(senders) = - TransactionSigned::recover_signers_unchecked(&self.body, self.body.len()) - else { - return Err(self) - }; + let Some(senders) = self.body.recover_signers() else { return Err(self) }; senders }; @@ -432,23 +428,13 @@ impl SealedBlock { /// Unseal the block pub fn unseal(self) -> Block { - Block { - header: self.header.unseal(), - body: self.body, - ommers: self.ommers, - withdrawals: self.withdrawals, - requests: self.requests, - } + Block { header: self.header.unseal(), body: self.body } } /// Calculates a heuristic for the in-memory size of the [`SealedBlock`]. #[inline] pub fn size(&self) -> usize { - self.header.size() + - // take into account capacity - self.body.iter().map(TransactionSigned::size).sum::() + self.body.capacity() * core::mem::size_of::() + - self.ommers.iter().map(Header::size).sum::() + self.ommers.capacity() * core::mem::size_of::
() + - self.withdrawals.as_ref().map_or(core::mem::size_of::>(), Withdrawals::total_size) + self.header.size() + self.body.size() } /// Calculates the total gas used by blob transactions in the sealed block. @@ -459,13 +445,13 @@ impl SealedBlock { /// Returns whether or not the block contains any blob transactions. #[inline] pub fn has_blob_transactions(&self) -> bool { - self.body.iter().any(|tx| tx.is_eip4844()) + self.body.has_blob_transactions() } /// Returns whether or not the block contains any eip-7702 transactions. #[inline] pub fn has_eip7702_transactions(&self) -> bool { - self.body.iter().any(|tx| tx.is_eip7702()) + self.body.has_eip7702_transactions() } /// Ensures that the transaction root in the block header is valid. @@ -481,7 +467,7 @@ impl SealedBlock { /// Returns `Err(error)` if the transaction root validation fails, providing a `GotExpected` /// error containing the calculated and expected roots. pub fn ensure_transaction_root_valid(&self) -> Result<(), GotExpected> { - let calculated_root = crate::proofs::calculate_transaction_root(&self.body); + let calculated_root = self.body.calculate_tx_root(); if self.header.transactions_root != calculated_root { return Err(GotExpected { @@ -495,7 +481,7 @@ impl SealedBlock { /// Returns a vector of transactions RLP encoded with [`TransactionSigned::encode_enveloped`]. pub fn raw_transactions(&self) -> Vec { - self.body.iter().map(|tx| tx.envelope_encoded()).collect() + self.body.transactions().map(|tx| tx.envelope_encoded()).collect() } } @@ -519,7 +505,7 @@ pub struct SealedBlockWithSenders { impl SealedBlockWithSenders { /// New sealed block with sender. Return none if len of tx and senders does not match pub fn new(block: SealedBlock, senders: Vec
) -> Option { - (block.body.len() == senders.len()).then_some(Self { block, senders }) + (block.body.transactions.len() == senders.len()).then_some(Self { block, senders }) } /// Split Structure to its components @@ -538,7 +524,7 @@ impl SealedBlockWithSenders { /// Returns an iterator over all transactions in the block. #[inline] pub fn transactions(&self) -> impl Iterator + '_ { - self.block.body.iter() + self.block.body.transactions() } /// Returns an iterator over all transactions and their sender. @@ -546,13 +532,13 @@ impl SealedBlockWithSenders { pub fn transactions_with_sender( &self, ) -> impl Iterator + '_ { - self.senders.iter().zip(self.block.body.iter()) + self.senders.iter().zip(self.block.body.transactions()) } /// Consumes the block and returns the transactions of the block. #[inline] pub fn into_transactions(self) -> Vec { - self.block.body + self.block.body.transactions } /// Returns an iterator over all transactions in the chain. @@ -560,7 +546,12 @@ impl SealedBlockWithSenders { pub fn into_transactions_ecrecovered( self, ) -> impl Iterator { - self.block.body.into_iter().zip(self.senders).map(|(tx, sender)| tx.with_signer(sender)) + self.block + .body + .transactions + .into_iter() + .zip(self.senders) + .map(|(tx, sender)| tx.with_signer(sender)) } } @@ -589,10 +580,12 @@ impl BlockBody { pub fn create_block(&self, header: Header) -> Block { Block { header, - body: self.transactions.clone(), - ommers: self.ommers.clone(), - withdrawals: self.withdrawals.clone(), - requests: self.requests.clone(), + body: Self { + transactions: self.transactions.clone(), + ommers: self.ommers.clone(), + withdrawals: self.withdrawals.clone(), + requests: self.requests.clone(), + }, } } @@ -618,6 +611,55 @@ impl BlockBody { self.requests.as_ref().map(|r| crate::proofs::calculate_requests_root(&r.0)) } + /// Recover signer addresses for all transactions in the block body. + pub fn recover_signers(&self) -> Option> { + TransactionSigned::recover_signers(&self.transactions, self.transactions.len()) + } + + /// Returns whether or not the block body contains any blob transactions. + #[inline] + pub fn has_blob_transactions(&self) -> bool { + self.transactions.iter().any(|tx| tx.is_eip4844()) + } + + /// Returns whether or not the block body contains any EIP-7702 transactions. + #[inline] + pub fn has_eip7702_transactions(&self) -> bool { + self.transactions.iter().any(|tx| tx.is_eip7702()) + } + + /// Returns an iterator over all blob transactions of the block + #[inline] + pub fn blob_transactions_iter(&self) -> impl Iterator + '_ { + self.transactions.iter().filter(|tx| tx.is_eip4844()) + } + + /// Returns only the blob transactions, if any, from the block body. + #[inline] + pub fn blob_transactions(&self) -> Vec<&TransactionSigned> { + self.blob_transactions_iter().collect() + } + + /// Returns an iterator over all blob versioned hashes from the block body. + #[inline] + pub fn blob_versioned_hashes_iter(&self) -> impl Iterator + '_ { + self.blob_transactions_iter() + .filter_map(|tx| tx.as_eip4844().map(|blob_tx| &blob_tx.blob_versioned_hashes)) + .flatten() + } + + /// Returns all blob versioned hashes from the block body. + #[inline] + pub fn blob_versioned_hashes(&self) -> Vec<&B256> { + self.blob_versioned_hashes_iter().collect() + } + + /// Returns an iterator over all transactions. + #[inline] + pub fn transactions(&self) -> impl Iterator + '_ { + self.transactions.iter() + } + /// Calculates a heuristic for the in-memory size of the [`BlockBody`]. #[inline] pub fn size(&self) -> usize { @@ -634,10 +676,10 @@ impl BlockBody { impl From for BlockBody { fn from(block: Block) -> Self { Self { - transactions: block.body, - ommers: block.ommers, - withdrawals: block.withdrawals, - requests: block.requests, + transactions: block.body.transactions, + ommers: block.body.ommers, + withdrawals: block.body.withdrawals, + requests: block.body.requests, } } } @@ -837,7 +879,7 @@ mod tests { fn block_with_senders() { let mut block = Block::default(); let sender = Address::random(); - block.body.push(TransactionSigned::default()); + block.body.transactions.push(TransactionSigned::default()); assert_eq!(BlockWithSenders::new(block.clone(), vec![]), None); assert_eq!( BlockWithSenders::new(block.clone(), vec![sender]), diff --git a/crates/primitives/src/proofs.rs b/crates/primitives/src/proofs.rs index 3f2fc7665..63ec5c731 100644 --- a/crates/primitives/src/proofs.rs +++ b/crates/primitives/src/proofs.rs @@ -123,7 +123,7 @@ mod tests { let block_rlp = &mut data.as_slice(); let block: Block = Block::decode(block_rlp).unwrap(); - let tx_root = calculate_transaction_root(&block.body); + let tx_root = calculate_transaction_root(&block.body.transactions); assert_eq!(block.transactions_root, tx_root, "Must be the same"); } @@ -155,8 +155,8 @@ mod tests { // https://github.com/ethereum/tests/blob/9760400e667eba241265016b02644ef62ab55de2/BlockchainTests/EIPTests/bc4895-withdrawals/amountIs0.json let data = &hex!("f90238f90219a0151934ad9b654c50197f37018ee5ee9bb922dec0a1b5e24a6d679cb111cdb107a01dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347942adc25665018aa1fe0e6bc666dac8fc2697ff9baa0046119afb1ab36aaa8f66088677ed96cd62762f6d3e65642898e189fbe702d51a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421b90100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000008001887fffffffffffffff8082079e42a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b42188000000000000000009a048a703da164234812273ea083e4ec3d09d028300cd325b46a6a75402e5a7ab95c0c0d9d8808094c94f5374fce5edbc8e2a8697c15331677e6ebf0b80"); let block: Block = Block::decode(&mut data.as_slice()).unwrap(); - assert!(block.withdrawals.is_some()); - let withdrawals = block.withdrawals.as_ref().unwrap(); + assert!(block.body.withdrawals.is_some()); + let withdrawals = block.body.withdrawals.as_ref().unwrap(); assert_eq!(withdrawals.len(), 1); let withdrawals_root = calculate_withdrawals_root(withdrawals); assert_eq!(block.withdrawals_root, Some(withdrawals_root)); @@ -165,8 +165,8 @@ mod tests { // https://github.com/ethereum/tests/blob/9760400e667eba241265016b02644ef62ab55de2/BlockchainTests/EIPTests/bc4895-withdrawals/twoIdenticalIndex.json let data = &hex!("f9028cf90219a0151934ad9b654c50197f37018ee5ee9bb922dec0a1b5e24a6d679cb111cdb107a01dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347942adc25665018aa1fe0e6bc666dac8fc2697ff9baa0ccf7b62d616c2ad7af862d67b9dcd2119a90cebbff8c3cd1e5d7fc99f8755774a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421b90100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000008001887fffffffffffffff8082079e42a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b42188000000000000000009a0a95b9a7b58a6b3cb4001eb0be67951c5517141cb0183a255b5cae027a7b10b36c0c0f86cda808094c94f5374fce5edbc8e2a8697c15331677e6ebf0b822710da028094c94f5374fce5edbc8e2a8697c15331677e6ebf0b822710da018094c94f5374fce5edbc8e2a8697c15331677e6ebf0b822710da028094c94f5374fce5edbc8e2a8697c15331677e6ebf0b822710"); let block: Block = Block::decode(&mut data.as_slice()).unwrap(); - assert!(block.withdrawals.is_some()); - let withdrawals = block.withdrawals.as_ref().unwrap(); + assert!(block.body.withdrawals.is_some()); + let withdrawals = block.body.withdrawals.as_ref().unwrap(); assert_eq!(withdrawals.len(), 4); let withdrawals_root = calculate_withdrawals_root(withdrawals); assert_eq!(block.withdrawals_root, Some(withdrawals_root)); diff --git a/crates/prune/prune/src/segments/receipts.rs b/crates/prune/prune/src/segments/receipts.rs index 944531fe7..05482d659 100644 --- a/crates/prune/prune/src/segments/receipts.rs +++ b/crates/prune/prune/src/segments/receipts.rs @@ -109,7 +109,7 @@ mod tests { let mut receipts = Vec::new(); for block in &blocks { - for transaction in &block.body { + for transaction in &block.body.transactions { receipts .push((receipts.len() as u64, random_receipt(&mut rng, transaction, Some(0)))); } @@ -118,7 +118,7 @@ mod tests { assert_eq!( db.table::().unwrap().len(), - blocks.iter().map(|block| block.body.len()).sum::() + blocks.iter().map(|block| block.body.transactions.len()).sum::() ); assert_eq!( db.table::().unwrap().len(), @@ -152,7 +152,7 @@ mod tests { let last_pruned_tx_number = blocks .iter() .take(to_block as usize) - .map(|block| block.body.len()) + .map(|block| block.body.transactions.len()) .sum::() .min( next_tx_number_to_prune as usize + @@ -180,7 +180,7 @@ mod tests { let last_pruned_block_number = blocks .iter() .fold_while((0, 0), |(_, mut tx_count), block| { - tx_count += block.body.len(); + tx_count += block.body.transactions.len(); if tx_count > last_pruned_tx_number { Done((block.number, tx_count)) diff --git a/crates/prune/prune/src/segments/static_file/transactions.rs b/crates/prune/prune/src/segments/static_file/transactions.rs index 0daf7e254..12772af5f 100644 --- a/crates/prune/prune/src/segments/static_file/transactions.rs +++ b/crates/prune/prune/src/segments/static_file/transactions.rs @@ -114,7 +114,8 @@ mod tests { ); db.insert_blocks(blocks.iter(), StorageKind::Database(None)).expect("insert blocks"); - let transactions = blocks.iter().flat_map(|block| &block.body).collect::>(); + let transactions = + blocks.iter().flat_map(|block| &block.body.transactions).collect::>(); assert_eq!(db.table::().unwrap().len(), transactions.len()); @@ -164,7 +165,7 @@ mod tests { let last_pruned_tx_number = blocks .iter() .take(to_block as usize) - .map(|block| block.body.len()) + .map(|block| block.body.transactions.len()) .sum::() .min( next_tx_number_to_prune as usize + @@ -175,7 +176,7 @@ mod tests { let last_pruned_block_number = blocks .iter() .fold_while((0, 0), |(_, mut tx_count), block| { - tx_count += block.body.len(); + tx_count += block.body.transactions.len(); if tx_count > last_pruned_tx_number { Done((block.number, tx_count)) diff --git a/crates/prune/prune/src/segments/user/receipts_by_logs.rs b/crates/prune/prune/src/segments/user/receipts_by_logs.rs index fbb353b41..489df7e72 100644 --- a/crates/prune/prune/src/segments/user/receipts_by_logs.rs +++ b/crates/prune/prune/src/segments/user/receipts_by_logs.rs @@ -263,11 +263,15 @@ mod tests { let (deposit_contract_addr, _) = random_eoa_account(&mut rng); for block in &blocks { - for (txi, transaction) in block.body.iter().enumerate() { + for (txi, transaction) in block.body.transactions.iter().enumerate() { let mut receipt = random_receipt(&mut rng, transaction, Some(1)); receipt.logs.push(random_log( &mut rng, - if txi == (block.body.len() - 1) { Some(deposit_contract_addr) } else { None }, + if txi == (block.body.transactions.len() - 1) { + Some(deposit_contract_addr) + } else { + None + }, Some(1), )); receipts.push((receipts.len() as u64, receipt)); @@ -277,7 +281,7 @@ mod tests { assert_eq!( db.table::().unwrap().len(), - blocks.iter().map(|block| block.body.len()).sum::() + blocks.iter().map(|block| block.body.transactions.len()).sum::() ); assert_eq!( db.table::().unwrap().len(), @@ -326,7 +330,7 @@ mod tests { assert_eq!( db.table::().unwrap().len(), - blocks.iter().map(|block| block.body.len()).sum::() - + blocks.iter().map(|block| block.body.transactions.len()).sum::() - ((pruned_tx + 1) - unprunable) as usize ); diff --git a/crates/prune/prune/src/segments/user/sender_recovery.rs b/crates/prune/prune/src/segments/user/sender_recovery.rs index de3fd686f..bd86f3e65 100644 --- a/crates/prune/prune/src/segments/user/sender_recovery.rs +++ b/crates/prune/prune/src/segments/user/sender_recovery.rs @@ -110,7 +110,7 @@ mod tests { let mut transaction_senders = Vec::new(); for block in &blocks { - for transaction in &block.body { + for transaction in &block.body.transactions { transaction_senders.push(( transaction_senders.len() as u64, transaction.recover_signer().expect("recover signer"), @@ -122,7 +122,7 @@ mod tests { assert_eq!( db.table::().unwrap().len(), - blocks.iter().map(|block| block.body.len()).sum::() + blocks.iter().map(|block| block.body.transactions.len()).sum::() ); assert_eq!( db.table::().unwrap().len(), @@ -157,7 +157,7 @@ mod tests { let last_pruned_tx_number = blocks .iter() .take(to_block as usize) - .map(|block| block.body.len()) + .map(|block| block.body.transactions.len()) .sum::() .min( next_tx_number_to_prune as usize + @@ -168,7 +168,7 @@ mod tests { let last_pruned_block_number = blocks .iter() .fold_while((0, 0), |(_, mut tx_count), block| { - tx_count += block.body.len(); + tx_count += block.body.transactions.len(); if tx_count > last_pruned_tx_number { Done((block.number, tx_count)) diff --git a/crates/prune/prune/src/segments/user/transaction_lookup.rs b/crates/prune/prune/src/segments/user/transaction_lookup.rs index 5b9b7454f..bb8196cdb 100644 --- a/crates/prune/prune/src/segments/user/transaction_lookup.rs +++ b/crates/prune/prune/src/segments/user/transaction_lookup.rs @@ -140,7 +140,7 @@ mod tests { let mut tx_hash_numbers = Vec::new(); for block in &blocks { - for transaction in &block.body { + for transaction in &block.body.transactions { tx_hash_numbers.push((transaction.hash, tx_hash_numbers.len() as u64)); } } @@ -148,7 +148,7 @@ mod tests { assert_eq!( db.table::().unwrap().len(), - blocks.iter().map(|block| block.body.len()).sum::() + blocks.iter().map(|block| block.body.transactions.len()).sum::() ); assert_eq!( db.table::().unwrap().len(), @@ -183,7 +183,7 @@ mod tests { let last_pruned_tx_number = blocks .iter() .take(to_block as usize) - .map(|block| block.body.len()) + .map(|block| block.body.transactions.len()) .sum::() .min( next_tx_number_to_prune as usize + @@ -194,7 +194,7 @@ mod tests { let last_pruned_block_number = blocks .iter() .fold_while((0, 0), |(_, mut tx_count), block| { - tx_count += block.body.len(); + tx_count += block.body.transactions.len(); if tx_count > last_pruned_tx_number { Done((block.number, tx_count)) diff --git a/crates/revm/src/state_change.rs b/crates/revm/src/state_change.rs index 6ac900186..6376957f3 100644 --- a/crates/revm/src/state_change.rs +++ b/crates/revm/src/state_change.rs @@ -20,21 +20,21 @@ pub fn post_block_balance_increments( calc::base_block_reward(chain_spec, block.number, block.difficulty, total_difficulty) { // Ommer rewards - for ommer in &block.ommers { + for ommer in &block.body.ommers { *balance_increments.entry(ommer.beneficiary).or_default() += calc::ommer_reward(base_block_reward, block.number, ommer.number); } // Full block reward *balance_increments.entry(block.beneficiary).or_default() += - calc::block_reward(base_block_reward, block.ommers.len()); + calc::block_reward(base_block_reward, block.body.ommers.len()); } // process withdrawals insert_post_block_withdrawals_balance_increments( chain_spec, block.timestamp, - block.withdrawals.as_ref().map(Withdrawals::as_ref), + block.body.withdrawals.as_ref().map(Withdrawals::as_ref), &mut balance_increments, ); diff --git a/crates/rpc/rpc-engine-api/tests/it/payload.rs b/crates/rpc/rpc-engine-api/tests/it/payload.rs index dd6f3ffd5..ccb6878e9 100644 --- a/crates/rpc/rpc-engine-api/tests/it/payload.rs +++ b/crates/rpc/rpc-engine-api/tests/it/payload.rs @@ -22,16 +22,14 @@ fn transform_block Block>(src: SealedBlock, f: F) -> Executi let unsealed = src.unseal(); let mut transformed: Block = f(unsealed); // Recalculate roots - transformed.header.transactions_root = proofs::calculate_transaction_root(&transformed.body); - transformed.header.ommers_hash = proofs::calculate_ommers_root(&transformed.ommers); + transformed.header.transactions_root = + proofs::calculate_transaction_root(&transformed.body.transactions); + transformed.header.ommers_hash = proofs::calculate_ommers_root(&transformed.body.ommers); let sealed = transformed.header.seal_slow(); let (header, seal) = sealed.into_parts(); block_to_payload(SealedBlock { header: SealedHeader::new(header, seal), body: transformed.body, - ommers: transformed.ommers, - withdrawals: transformed.withdrawals, - requests: transformed.requests, }) } @@ -47,7 +45,7 @@ fn payload_body_roundtrip() { let payload_body: ExecutionPayloadBodyV1 = convert_to_payload_body_v1(unsealed); assert_eq!( - Ok(block.body), + Ok(block.body.transactions), payload_body .transactions .iter() @@ -55,7 +53,7 @@ fn payload_body_roundtrip() { .collect::, _>>(), ); let withdraw = payload_body.withdrawals.map(Withdrawals::new); - assert_eq!(block.withdrawals, withdraw); + assert_eq!(block.body.withdrawals, withdraw); } } @@ -115,7 +113,7 @@ fn payload_validation() { // Non empty ommers let block_with_ommers = transform_block(block.clone(), |mut b| { - b.ommers.push(random_header(&mut rng, 100, None).unseal()); + b.body.ommers.push(random_header(&mut rng, 100, None).unseal()); b }); assert_matches!( diff --git a/crates/rpc/rpc-eth-api/src/helpers/block.rs b/crates/rpc/rpc-eth-api/src/helpers/block.rs index 381c8c505..3a26536cc 100644 --- a/crates/rpc/rpc-eth-api/src/helpers/block.rs +++ b/crates/rpc/rpc-eth-api/src/helpers/block.rs @@ -75,7 +75,7 @@ pub trait EthBlocks: LoadBlock { return Ok(LoadBlock::provider(self) .pending_block() .map_err(Self::Error::from_eth_err)? - .map(|block| block.body.len())); + .map(|block| block.body.transactions.len())) } let block_hash = match LoadBlock::provider(self) @@ -169,7 +169,7 @@ pub trait EthBlocks: LoadBlock { LoadBlock::provider(self) .pending_block() .map_err(Self::Error::from_eth_err)? - .map(|block| block.ommers) + .map(|block| block.body.ommers) } else { LoadBlock::provider(self) .ommers_by_id(block_id) diff --git a/crates/rpc/rpc-eth-api/src/helpers/call.rs b/crates/rpc/rpc-eth-api/src/helpers/call.rs index 70fab6edd..99e240bf3 100644 --- a/crates/rpc/rpc-eth-api/src/helpers/call.rs +++ b/crates/rpc/rpc-eth-api/src/helpers/call.rs @@ -265,11 +265,11 @@ pub trait EthCall: Call + LoadPendingBlock { let mut at = block.parent_hash; let mut replay_block_txs = true; - let num_txs = transaction_index.index().unwrap_or(block.body.len()); + let num_txs = transaction_index.index().unwrap_or(block.body.transactions.len()); // but if all transactions are to be replayed, we can use the state at the block itself, // however only if we're not targeting the pending block, because for pending we can't // rely on the block's state being available - if !is_block_target_pending && num_txs == block.body.len() { + if !is_block_target_pending && num_txs == block.body.transactions.len() { at = block.hash(); replay_block_txs = false; } diff --git a/crates/rpc/rpc-eth-api/src/helpers/pending_block.rs b/crates/rpc/rpc-eth-api/src/helpers/pending_block.rs index e116274b0..6593d23db 100644 --- a/crates/rpc/rpc-eth-api/src/helpers/pending_block.rs +++ b/crates/rpc/rpc-eth-api/src/helpers/pending_block.rs @@ -20,7 +20,7 @@ use reth_primitives::{ BlockEnv, CfgEnv, CfgEnvWithHandlerCfg, EVMError, Env, ExecutionResult, InvalidTransaction, ResultAndState, SpecId, }, - Block, Header, IntoRecoveredTransaction, Receipt, Requests, SealedBlockWithSenders, + Block, BlockBody, Header, IntoRecoveredTransaction, Receipt, Requests, SealedBlockWithSenders, SealedHeader, TransactionSignedEcRecovered, EMPTY_OMMER_ROOT_HASH, }; use reth_provider::{ @@ -255,7 +255,7 @@ pub trait LoadPendingBlock: EthApiTypes { let (withdrawals, withdrawals_root) = match origin { PendingBlockEnvOrigin::ActualPending(ref block) => { - (block.withdrawals.clone(), block.withdrawals_root) + (block.body.withdrawals.clone(), block.withdrawals_root) } PendingBlockEnvOrigin::DerivedFromLatest(_) => (None, None), }; @@ -460,7 +460,10 @@ pub trait LoadPendingBlock: EthApiTypes { let receipts: Vec = receipts.into_iter().flatten().collect(); // seal the block - let block = Block { header, body: executed_txs, ommers: vec![], withdrawals, requests }; + let block = Block { + header, + body: BlockBody { transactions: executed_txs, ommers: vec![], withdrawals, requests }, + }; Ok((SealedBlockWithSenders { block: block.seal_slow(), senders }, receipts)) } } diff --git a/crates/rpc/rpc-eth-api/src/helpers/trace.rs b/crates/rpc/rpc-eth-api/src/helpers/trace.rs index 0bebb1408..15e272c07 100644 --- a/crates/rpc/rpc-eth-api/src/helpers/trace.rs +++ b/crates/rpc/rpc-eth-api/src/helpers/trace.rs @@ -291,7 +291,7 @@ pub trait Trace: LoadState { let Some(block) = block else { return Ok(None) }; - if block.body.is_empty() { + if block.body.transactions.is_empty() { // nothing to trace return Ok(Some(Vec::new())) } @@ -308,10 +308,11 @@ pub trait Trace: LoadState { // prepare transactions, we do everything upfront to reduce time spent with open // state - let max_transactions = highest_index.map_or(block.body.len(), |highest| { - // we need + 1 because the index is 0-based - highest as usize + 1 - }); + let max_transactions = + highest_index.map_or(block.body.transactions.len(), |highest| { + // we need + 1 because the index is 0-based + highest as usize + 1 + }); let mut results = Vec::with_capacity(max_transactions); let mut transactions = block diff --git a/crates/rpc/rpc-eth-types/src/cache/mod.rs b/crates/rpc/rpc-eth-types/src/cache/mod.rs index 0df853330..fac611571 100644 --- a/crates/rpc/rpc-eth-types/src/cache/mod.rs +++ b/crates/rpc/rpc-eth-types/src/cache/mod.rs @@ -327,10 +327,9 @@ where let _ = block_with_senders.send(res.clone()); } Either::Right(transaction_tx) => { - let _ = transaction_tx.send( - res.clone() - .map(|maybe_block| maybe_block.map(|block| block.block.body)), - ); + let _ = transaction_tx.send(res.clone().map(|maybe_block| { + maybe_block.map(|block| block.block.body.transactions) + })); } } } @@ -369,10 +368,9 @@ where let _ = block_with_senders.send(res.clone()); } Either::Right(transaction_tx) => { - let _ = transaction_tx.send( - res.clone() - .map(|maybe_block| maybe_block.map(|block| block.block.body)), - ); + let _ = transaction_tx.send(res.clone().map(|maybe_block| { + maybe_block.map(|block| block.block.body.transactions) + })); } } } @@ -447,7 +445,7 @@ where CacheAction::GetBlockTransactions { block_hash, response_tx } => { // check if block is cached if let Some(block) = this.full_block_cache.get(&block_hash) { - let _ = response_tx.send(Ok(Some(block.body.clone()))); + let _ = response_tx.send(Ok(Some(block.body.transactions.clone()))); continue } diff --git a/crates/rpc/rpc-eth-types/src/fee_history.rs b/crates/rpc/rpc-eth-types/src/fee_history.rs index 0aa5a245b..34b7bff82 100644 --- a/crates/rpc/rpc-eth-types/src/fee_history.rs +++ b/crates/rpc/rpc-eth-types/src/fee_history.rs @@ -89,7 +89,7 @@ impl FeeHistoryCache { &percentiles, fee_history_entry.gas_used, fee_history_entry.base_fee_per_gas, - &block.body, + &block.body.transactions, &receipts, ) .unwrap_or_default(); diff --git a/crates/rpc/rpc-eth-types/src/gas_oracle.rs b/crates/rpc/rpc-eth-types/src/gas_oracle.rs index 173668a07..e2dcb0b06 100644 --- a/crates/rpc/rpc-eth-types/src/gas_oracle.rs +++ b/crates/rpc/rpc-eth-types/src/gas_oracle.rs @@ -221,13 +221,13 @@ where let parent_hash = block.parent_hash; // sort the functions by ascending effective tip first - block.body.sort_by_cached_key(|tx| { + block.body.transactions.sort_by_cached_key(|tx| { tx.effective_tip_per_gas(base_fee_per_gas.map(|base_fee| base_fee as u64)) }); let mut prices = Vec::with_capacity(limit); - for tx in &block.body { + for tx in block.body.transactions() { let mut effective_gas_tip = None; // ignore transactions with a tip under the configured threshold if let Some(ignore_under) = self.ignore_price { diff --git a/crates/rpc/rpc-eth-types/src/simulate.rs b/crates/rpc/rpc-eth-types/src/simulate.rs index 996200c56..0db5e14da 100644 --- a/crates/rpc/rpc-eth-types/src/simulate.rs +++ b/crates/rpc/rpc-eth-types/src/simulate.rs @@ -11,7 +11,8 @@ use jsonrpsee_types::ErrorObject; use reth_primitives::{ logs_bloom, proofs::{calculate_receipt_root, calculate_transaction_root}, - BlockWithSenders, Receipt, Signature, Transaction, TransactionSigned, TransactionSignedNoHash, + BlockBody, BlockWithSenders, Receipt, Signature, Transaction, TransactionSigned, + TransactionSignedNoHash, }; use reth_revm::database::StateProviderDatabase; use reth_rpc_server_types::result::rpc_err; @@ -293,7 +294,10 @@ pub fn build_block( }; let block = BlockWithSenders { - block: reth_primitives::Block { header, body: transactions, ..Default::default() }, + block: reth_primitives::Block { + header, + body: BlockBody { transactions, ..Default::default() }, + }, senders, }; diff --git a/crates/rpc/rpc-types-compat/src/block.rs b/crates/rpc/rpc-types-compat/src/block.rs index d20aa3bfb..6febe8e81 100644 --- a/crates/rpc/rpc-types-compat/src/block.rs +++ b/crates/rpc/rpc-types-compat/src/block.rs @@ -40,7 +40,7 @@ pub fn from_block_with_tx_hashes( block_hash: Option, ) -> Block { let block_hash = block_hash.unwrap_or_else(|| block.header.hash_slow()); - let transactions = block.body.iter().map(|tx| tx.hash()).collect(); + let transactions = block.body.transactions().map(|tx| tx.hash()).collect(); from_block_with_transactions( block.length(), @@ -68,8 +68,8 @@ pub fn from_block_full( // NOTE: we can safely remove the body here because not needed to finalize the `Block` in // `from_block_with_transactions`, however we need to compute the length before let block_length = block.block.length(); - let body = std::mem::take(&mut block.block.body); - let transactions_with_senders = body.into_iter().zip(block.senders); + let transactions = std::mem::take(&mut block.block.body.transactions); + let transactions_with_senders = transactions.into_iter().zip(block.senders); let transactions = transactions_with_senders .enumerate() .map(|(idx, (tx, sender))| { @@ -162,14 +162,14 @@ fn from_block_with_transactions( total_difficulty: U256, transactions: BlockTransactions, ) -> Block { - let uncles = block.ommers.into_iter().map(|h| h.hash_slow()).collect(); + let uncles = block.body.ommers.into_iter().map(|h| h.hash_slow()).collect(); let mut header = from_primitive_with_hash(SealedHeader::new(block.header, block_hash)); header.total_difficulty = Some(total_difficulty); let withdrawals = header .withdrawals_root .is_some() - .then(|| block.withdrawals.map(Withdrawals::into_inner)) + .then(|| block.body.withdrawals.map(Withdrawals::into_inner)) .flatten(); Block { header, uncles, transactions, size: Some(U256::from(block_length)), withdrawals } diff --git a/crates/rpc/rpc-types-compat/src/engine/payload.rs b/crates/rpc/rpc-types-compat/src/engine/payload.rs index 8b52d8225..f4e9dc6c7 100644 --- a/crates/rpc/rpc-types-compat/src/engine/payload.rs +++ b/crates/rpc/rpc-types-compat/src/engine/payload.rs @@ -4,7 +4,8 @@ use alloy_primitives::{B256, U256}; use reth_primitives::{ constants::{EMPTY_OMMER_ROOT_HASH, MAXIMUM_EXTRA_DATA_SIZE}, - proofs, Block, Header, Request, SealedBlock, TransactionSigned, Withdrawals, + proofs::{self}, + Block, BlockBody, Header, Request, SealedBlock, TransactionSigned, Withdrawals, }; use reth_rpc_types::engine::{ payload::{ExecutionPayloadBodyV1, ExecutionPayloadFieldV2, ExecutionPayloadInputV2}, @@ -63,13 +64,7 @@ pub fn try_payload_v1_to_block(payload: ExecutionPayloadV1) -> Result Result Result ExecutionPayload { } else if value.header.parent_beacon_block_root.is_some() { // block with parent beacon block root: V3 ExecutionPayload::V3(block_to_payload_v3(value)) - } else if value.withdrawals.is_some() { + } else if value.body.withdrawals.is_some() { // block with withdrawals: V2 ExecutionPayload::V2(block_to_payload_v2(value)) } else { @@ -179,7 +174,7 @@ pub fn block_to_payload_v2(value: SealedBlock) -> ExecutionPayloadV2 { block_hash: value.hash(), transactions, }, - withdrawals: value.withdrawals.unwrap_or_default().into_inner(), + withdrawals: value.body.withdrawals.unwrap_or_default().into_inner(), } } @@ -206,7 +201,7 @@ pub fn block_to_payload_v3(value: SealedBlock) -> ExecutionPayloadV3 { block_hash: value.hash(), transactions, }, - withdrawals: value.withdrawals.unwrap_or_default().into_inner(), + withdrawals: value.body.withdrawals.unwrap_or_default().into_inner(), }, } } @@ -214,7 +209,7 @@ pub fn block_to_payload_v3(value: SealedBlock) -> ExecutionPayloadV3 { /// Converts [`SealedBlock`] to [`ExecutionPayloadV4`] pub fn block_to_payload_v4(mut value: SealedBlock) -> ExecutionPayloadV4 { let (deposit_requests, withdrawal_requests, consolidation_requests) = - value.requests.take().unwrap_or_default().into_iter().fold( + value.body.requests.take().unwrap_or_default().into_iter().fold( (Vec::new(), Vec::new(), Vec::new()), |(mut deposits, mut withdrawals, mut consolidation_requests), request| { match request { @@ -245,7 +240,7 @@ pub fn block_to_payload_v4(mut value: SealedBlock) -> ExecutionPayloadV4 { /// Converts [`SealedBlock`] to [`ExecutionPayloadFieldV2`] pub fn convert_block_to_payload_field_v2(value: SealedBlock) -> ExecutionPayloadFieldV2 { // if there are withdrawals, return V2 - if value.withdrawals.is_some() { + if value.body.withdrawals.is_some() { ExecutionPayloadFieldV2::V2(block_to_payload_v2(value)) } else { ExecutionPayloadFieldV2::V1(block_to_payload_v1(value)) @@ -291,7 +286,7 @@ pub fn convert_payload_input_v2_to_payload(value: ExecutionPayloadInputV2) -> Ex /// Converts [`SealedBlock`] to [`ExecutionPayloadInputV2`] pub fn convert_block_to_payload_input_v2(value: SealedBlock) -> ExecutionPayloadInputV2 { ExecutionPayloadInputV2 { - withdrawals: value.withdrawals.clone().map(Withdrawals::into_inner), + withdrawals: value.body.withdrawals.clone().map(Withdrawals::into_inner), execution_payload: block_to_payload_v1(value), } } @@ -363,20 +358,20 @@ pub fn validate_block_hash( /// Converts [`Block`] to [`ExecutionPayloadBodyV1`] pub fn convert_to_payload_body_v1(value: Block) -> ExecutionPayloadBodyV1 { - let transactions = value.body.into_iter().map(|tx| { + let transactions = value.body.transactions.into_iter().map(|tx| { let mut out = Vec::new(); tx.encode_enveloped(&mut out); out.into() }); ExecutionPayloadBodyV1 { transactions: transactions.collect(), - withdrawals: value.withdrawals.map(Withdrawals::into_inner), + withdrawals: value.body.withdrawals.map(Withdrawals::into_inner), } } /// Converts [`Block`] to [`ExecutionPayloadBodyV2`] pub fn convert_to_payload_body_v2(value: Block) -> ExecutionPayloadBodyV2 { - let transactions = value.body.into_iter().map(|tx| { + let transactions = value.body.transactions.into_iter().map(|tx| { let mut out = Vec::new(); tx.encode_enveloped(&mut out); out.into() @@ -384,13 +379,13 @@ pub fn convert_to_payload_body_v2(value: Block) -> ExecutionPayloadBodyV2 { let mut payload = ExecutionPayloadBodyV2 { transactions: transactions.collect(), - withdrawals: value.withdrawals.map(Withdrawals::into_inner), + withdrawals: value.body.withdrawals.map(Withdrawals::into_inner), deposit_requests: None, withdrawal_requests: None, consolidation_requests: None, }; - if let Some(requests) = value.requests { + if let Some(requests) = value.body.requests { let (deposit_requests, withdrawal_requests, consolidation_requests) = requests.into_iter().fold( (Vec::new(), Vec::new(), Vec::new()), diff --git a/crates/rpc/rpc/src/debug.rs b/crates/rpc/rpc/src/debug.rs index 426cd0898..9bfb47330 100644 --- a/crates/rpc/rpc/src/debug.rs +++ b/crates/rpc/rpc/src/debug.rs @@ -163,6 +163,7 @@ where if self.inner.provider.chain_spec().is_homestead_active_at_block(block.number) { block .body + .transactions .into_iter() .map(|tx| { tx.into_ecrecovered() @@ -173,6 +174,7 @@ where } else { block .body + .transactions .into_iter() .map(|tx| { tx.into_ecrecovered_unchecked() @@ -507,11 +509,11 @@ where let mut replay_block_txs = true; // if a transaction index is provided, we need to replay the transactions until the index - let num_txs = transaction_index.index().unwrap_or(block.body.len()); + let num_txs = transaction_index.index().unwrap_or(block.body.transactions.len()); // but if all transactions are to be replayed, we can use the state at the block itself // this works with the exception of the PENDING block, because its state might not exist if // built locally - if !target_block.is_pending() && num_txs == block.body.len() { + if !target_block.is_pending() && num_txs == block.body.transactions.len() { at = block.hash(); replay_block_txs = false; } diff --git a/crates/rpc/rpc/src/eth/core.rs b/crates/rpc/rpc/src/eth/core.rs index 31ecc818e..cc1843c23 100644 --- a/crates/rpc/rpc/src/eth/core.rs +++ b/crates/rpc/rpc/src/eth/core.rs @@ -379,7 +379,7 @@ mod tests { use reth_chainspec::{BaseFeeParams, ChainSpec}; use reth_evm_ethereum::EthEvmConfig; use reth_network_api::noop::NoopNetwork; - use reth_primitives::{Block, BlockNumberOrTag, Header, TransactionSigned}; + use reth_primitives::{Block, BlockBody, BlockNumberOrTag, Header, TransactionSigned}; use reth_provider::{ test_utils::{MockEthProvider, NoopProvider}, BlockReader, BlockReaderIdExt, ChainSpecProvider, EvmEnvProvider, StateProviderFactory, @@ -493,7 +493,10 @@ mod tests { mock_provider.add_block( hash, - Block { header: header.clone(), body: transactions, ..Default::default() }, + Block { + header: header.clone(), + body: BlockBody { transactions, ..Default::default() }, + }, ); mock_provider.add_header(hash, header); diff --git a/crates/rpc/rpc/src/eth/helpers/block.rs b/crates/rpc/rpc/src/eth/helpers/block.rs index cc6df1aa0..4935cf624 100644 --- a/crates/rpc/rpc/src/eth/helpers/block.rs +++ b/crates/rpc/rpc/src/eth/helpers/block.rs @@ -41,6 +41,7 @@ where return block .body + .transactions .into_iter() .zip(receipts.iter()) .enumerate() diff --git a/crates/rpc/rpc/src/trace.rs b/crates/rpc/rpc/src/trace.rs index 37c05bc19..7435fde9e 100644 --- a/crates/rpc/rpc/src/trace.rs +++ b/crates/rpc/rpc/src/trace.rs @@ -311,8 +311,11 @@ where // add reward traces for all blocks for block in &blocks { if let Some(base_block_reward) = self.calculate_base_block_reward(&block.header)? { - let mut traces = - self.extract_reward_traces(&block.header, &block.ommers, base_block_reward); + let mut traces = self.extract_reward_traces( + &block.header, + &block.body.ommers, + base_block_reward, + ); traces.retain(|trace| matcher.matches(&trace.trace)); all_traces.extend(traces); } else { @@ -383,7 +386,7 @@ where if let Some(base_block_reward) = self.calculate_base_block_reward(&block.header)? { traces.extend(self.extract_reward_traces( &block.header, - &block.ommers, + &block.body.ommers, base_block_reward, )); } diff --git a/crates/stages/stages/src/stages/bodies.rs b/crates/stages/stages/src/stages/bodies.rs index 1625237b9..7f6d2d6a0 100644 --- a/crates/stages/stages/src/stages/bodies.rs +++ b/crates/stages/stages/src/stages/bodies.rs @@ -172,7 +172,7 @@ where let block_indices = StoredBlockBodyIndices { first_tx_num: next_tx_num, tx_count: match &response { - BlockResponse::Full(block) => block.body.len() as u64, + BlockResponse::Full(block) => block.body.transactions.len() as u64, BlockResponse::Empty(_) => 0, }, }; @@ -195,12 +195,12 @@ where match response { BlockResponse::Full(block) => { // write transaction block index - if !block.body.is_empty() { + if !block.body.transactions.is_empty() { tx_block_cursor.append(block_indices.last_tx_num(), block.number)?; } // Write transactions - for transaction in block.body { + for transaction in block.body.transactions { let appended_tx_number = static_file_producer .append_transaction(next_tx_num, &transaction.into())?; @@ -219,13 +219,15 @@ where } // Write ommers if any - if !block.ommers.is_empty() { - ommers_cursor - .append(block_number, StoredBlockOmmers { ommers: block.ommers })?; + if !block.body.ommers.is_empty() { + ommers_cursor.append( + block_number, + StoredBlockOmmers { ommers: block.body.ommers }, + )?; } // Write withdrawals if any - if let Some(withdrawals) = block.withdrawals { + if let Some(withdrawals) = block.body.withdrawals { if !withdrawals.is_empty() { withdrawals_cursor .append(block_number, StoredBlockWithdrawals { withdrawals })?; @@ -233,7 +235,7 @@ where } // Write requests if any - if let Some(requests) = block.requests { + if let Some(requests) = block.body.requests { if !requests.0.is_empty() { requests_cursor.append(block_number, requests)?; } @@ -657,15 +659,7 @@ mod tests { /// A helper to create a collection of block bodies keyed by their hash. pub(crate) fn body_by_hash(block: &SealedBlock) -> (B256, BlockBody) { - ( - block.hash(), - BlockBody { - transactions: block.body.clone(), - ommers: block.ommers.clone(), - withdrawals: block.withdrawals.clone(), - requests: block.requests.clone(), - }, - ) + (block.hash(), block.body.clone()) } /// A helper struct for running the [`BodyStage`]. @@ -738,7 +732,7 @@ mod tests { let body = StoredBlockBodyIndices { first_tx_num: 0, - tx_count: progress.body.len() as u64, + tx_count: progress.body.transactions.len() as u64, }; static_file_producer.set_block_range(0..=progress.number); @@ -762,7 +756,7 @@ mod tests { if !progress.ommers_hash_is_empty() { tx.put::( progress.number, - StoredBlockOmmers { ommers: progress.ommers.clone() }, + StoredBlockOmmers { ommers: progress.body.ommers.clone() }, )?; } @@ -945,13 +939,7 @@ mod tests { } else { let body = this.responses.remove(&header.hash()).expect("requested unknown body"); - response.push(BlockResponse::Full(SealedBlock { - header, - body: body.transactions, - ommers: body.ommers, - withdrawals: body.withdrawals, - requests: body.requests, - })); + response.push(BlockResponse::Full(SealedBlock { header, body })); } if response.len() as u64 >= this.batch_size { diff --git a/crates/stages/stages/src/stages/execution.rs b/crates/stages/stages/src/stages/execution.rs index 6f6e6d6f3..57a9cdaab 100644 --- a/crates/stages/stages/src/stages/execution.rs +++ b/crates/stages/stages/src/stages/execution.rs @@ -271,7 +271,7 @@ where cumulative_gas += block.gas_used; // Configure the executor to use the current state. - trace!(target: "sync::stages::execution", number = block_number, txs = block.body.len(), "Executing block"); + trace!(target: "sync::stages::execution", number = block_number, txs = block.body.transactions.len(), "Executing block"); // Execute the block let execute_start = Instant::now(); diff --git a/crates/stages/stages/src/stages/hashing_storage.rs b/crates/stages/stages/src/stages/hashing_storage.rs index 0d2821128..54a9921dd 100644 --- a/crates/stages/stages/src/stages/hashing_storage.rs +++ b/crates/stages/stages/src/stages/hashing_storage.rs @@ -351,7 +351,7 @@ mod tests { // Insert last progress data let block_number = progress.number; self.db.commit(|tx| { - progress.body.iter().try_for_each( + progress.body.transactions.iter().try_for_each( |transaction| -> Result<(), reth_db::DatabaseError> { tx.put::( transaction.hash(), @@ -399,7 +399,7 @@ mod tests { let body = StoredBlockBodyIndices { first_tx_num, - tx_count: progress.body.len() as u64, + tx_count: progress.body.transactions.len() as u64, }; first_tx_num = next_tx_num; diff --git a/crates/stages/stages/src/stages/merkle.rs b/crates/stages/stages/src/stages/merkle.rs index 392179303..83c8c52ce 100644 --- a/crates/stages/stages/src/stages/merkle.rs +++ b/crates/stages/stages/src/stages/merkle.rs @@ -523,7 +523,7 @@ mod tests { accounts.iter().map(|(addr, acc)| (*addr, (*acc, std::iter::empty()))), )?; - let SealedBlock { header, body, ommers, withdrawals, requests } = random_block( + let SealedBlock { header, body } = random_block( &mut rng, stage_progress, BlockParams { parent: preblocks.last().map(|b| b.hash()), ..Default::default() }, @@ -536,16 +536,9 @@ mod tests { .into_iter() .map(|(address, account)| (address, (account, std::iter::empty()))), ); - let sealed = header.seal_slow(); let (header, seal) = sealed.into_parts(); - let sealed_head = SealedBlock { - header: SealedHeader::new(header, seal), - body, - ommers, - withdrawals, - requests, - }; + let sealed_head = SealedBlock { header: SealedHeader::new(header, seal), body }; let head_hash = sealed_head.hash(); let mut blocks = vec![sealed_head]; diff --git a/crates/stages/stages/src/stages/mod.rs b/crates/stages/stages/src/stages/mod.rs index a5d537da4..4eb3c6f14 100644 --- a/crates/stages/stages/src/stages/mod.rs +++ b/crates/stages/stages/src/stages/mod.rs @@ -268,8 +268,8 @@ mod tests { let mut receipts = Vec::new(); let mut tx_num = 0u64; for block in &blocks { - let mut block_receipts = Vec::with_capacity(block.body.len()); - for transaction in &block.body { + let mut block_receipts = Vec::with_capacity(block.body.transactions.len()); + for transaction in &block.body.transactions { block_receipts.push((tx_num, random_receipt(&mut rng, transaction, Some(0)))); tx_num += 1; } diff --git a/crates/stages/stages/src/stages/prune.rs b/crates/stages/stages/src/stages/prune.rs index 1995bc000..3512e6210 100644 --- a/crates/stages/stages/src/stages/prune.rs +++ b/crates/stages/stages/src/stages/prune.rs @@ -213,9 +213,9 @@ mod tests { ); self.db.insert_blocks(blocks.iter(), StorageKind::Static)?; self.db.insert_transaction_senders( - blocks.iter().flat_map(|block| block.body.iter()).enumerate().map(|(i, tx)| { - (i as u64, tx.recover_signer().expect("failed to recover signer")) - }), + blocks.iter().flat_map(|block| block.body.transactions.iter()).enumerate().map( + |(i, tx)| (i as u64, tx.recover_signer().expect("failed to recover signer")), + ), )?; Ok(blocks) } diff --git a/crates/stages/stages/src/stages/sender_recovery.rs b/crates/stages/stages/src/stages/sender_recovery.rs index 5ec7ee798..bf7df6147 100644 --- a/crates/stages/stages/src/stages/sender_recovery.rs +++ b/crates/stages/stages/src/stages/sender_recovery.rs @@ -444,7 +444,7 @@ mod tests { let expected_progress = seed .iter() .find(|x| { - tx_count += x.body.len(); + tx_count += x.body.transactions.len(); tx_count as u64 > threshold }) .map(|x| x.number) @@ -503,7 +503,7 @@ mod tests { let mut tx_senders = Vec::new(); let mut tx_number = 0; for block in &blocks[..=max_processed_block] { - for transaction in &block.body { + for transaction in &block.body.transactions { if block.number > max_pruned_block { tx_senders .push((tx_number, transaction.recover_signer().expect("recover signer"))); @@ -522,7 +522,7 @@ mod tests { tx_number: Some( blocks[..=max_pruned_block as usize] .iter() - .map(|block| block.body.len() as u64) + .map(|block| block.body.transactions.len() as u64) .sum::(), ), prune_mode: PruneMode::Full, @@ -537,9 +537,9 @@ mod tests { EntitiesCheckpoint { processed: blocks[..=max_processed_block] .iter() - .map(|block| block.body.len() as u64) + .map(|block| block.body.transactions.len() as u64) .sum::(), - total: blocks.iter().map(|block| block.body.len() as u64).sum::() + total: blocks.iter().map(|block| block.body.transactions.len() as u64).sum::() } ); } diff --git a/crates/stages/stages/src/stages/tx_lookup.rs b/crates/stages/stages/src/stages/tx_lookup.rs index 35c0d8637..e636c2818 100644 --- a/crates/stages/stages/src/stages/tx_lookup.rs +++ b/crates/stages/stages/src/stages/tx_lookup.rs @@ -380,7 +380,7 @@ mod tests { let mut tx_hash_numbers = Vec::new(); let mut tx_hash_number = 0; for block in &blocks[..=max_processed_block] { - for transaction in &block.body { + for transaction in &block.body.transactions { if block.number > max_pruned_block { tx_hash_numbers.push((transaction.hash, tx_hash_number)); } @@ -398,7 +398,7 @@ mod tests { tx_number: Some( blocks[..=max_pruned_block as usize] .iter() - .map(|block| block.body.len() as u64) + .map(|block| block.body.transactions.len() as u64) .sum::() .sub(1), // `TxNumber` is 0-indexed ), @@ -414,9 +414,9 @@ mod tests { EntitiesCheckpoint { processed: blocks[..=max_processed_block] .iter() - .map(|block| block.body.len() as u64) + .map(|block| block.body.transactions.len() as u64) .sum::(), - total: blocks.iter().map(|block| block.body.len() as u64).sum::() + total: blocks.iter().map(|block| block.body.transactions.len() as u64).sum::() } ); } diff --git a/crates/stages/stages/src/test_utils/test_db.rs b/crates/stages/stages/src/test_utils/test_db.rs index 9a44d9bac..5fef9d6a2 100644 --- a/crates/stages/stages/src/test_utils/test_db.rs +++ b/crates/stages/stages/src/test_utils/test_db.rs @@ -252,10 +252,10 @@ impl TestStageDB { // Insert into body tables. let block_body_indices = StoredBlockBodyIndices { first_tx_num: next_tx_num, - tx_count: block.body.len() as u64, + tx_count: block.body.transactions.len() as u64, }; - if !block.body.is_empty() { + if !block.body.transactions.is_empty() { tx.put::( block_body_indices.last_tx_num(), block.number, @@ -263,7 +263,7 @@ impl TestStageDB { } tx.put::(block.number, block_body_indices)?; - let res = block.body.iter().try_for_each(|body_tx| { + let res = block.body.transactions.iter().try_for_each(|body_tx| { if let Some(txs_writer) = &mut txs_writer { txs_writer.append_transaction(next_tx_num, &body_tx.clone().into())?; } else { diff --git a/crates/static-file/static-file/src/static_file_producer.rs b/crates/static-file/static-file/src/static_file_producer.rs index d15451202..32565fd6d 100644 --- a/crates/static-file/static-file/src/static_file_producer.rs +++ b/crates/static-file/static-file/src/static_file_producer.rs @@ -311,7 +311,7 @@ mod tests { let mut receipts = Vec::new(); for block in &blocks { - for transaction in &block.body { + for transaction in &block.body.transactions { receipts .push((receipts.len() as u64, random_receipt(&mut rng, transaction, Some(0)))); } diff --git a/crates/storage/provider/src/providers/blockchain_provider.rs b/crates/storage/provider/src/providers/blockchain_provider.rs index 9b1e93624..cb90cc08a 100644 --- a/crates/storage/provider/src/providers/blockchain_provider.rs +++ b/crates/storage/provider/src/providers/blockchain_provider.rs @@ -228,7 +228,7 @@ impl BlockchainProvider2 { let executed_block = block_state.block(); let block = executed_block.block(); - for tx_index in 0..block.body.len() { + for tx_index in 0..block.body.transactions.len() { if id == in_memory_tx_num { return Ok(Some((Some(block_state), tx_index))) } @@ -499,7 +499,7 @@ impl BlockReader for BlockchainProvider2 { // Check in-memory state first self.canonical_in_memory_state .state_by_number(number) - .map(|o| o.block().block().ommers.clone()) + .map(|o| o.block().block().body.ommers.clone()) .map_or_else(|| self.database.ommers(id), |ommers| Ok(Some(ommers))) } None => self.database.ommers(id), @@ -526,7 +526,7 @@ impl BlockReader for BlockchainProvider2 { stored_indices.first_tx_num = stored_indices.next_tx_num(); for state in parent_chain { - let txs = state.block().block.body.len() as u64; + let txs = state.block().block.body.transactions.len() as u64; if state.block().block().number == number { stored_indices.tx_count = txs; } else { @@ -673,7 +673,7 @@ impl TransactionsProvider for BlockchainProvider2 { .canonical_in_memory_state .state_by_number(block_number) .ok_or(ProviderError::StateForNumberNotFound(block_number))?; - for tx in &block_state.block().block().body { + for tx in block_state.block().block().body.transactions() { if tx.hash() == tx_hash { return Ok(Some(in_memory_tx_id)) } @@ -692,7 +692,7 @@ impl TransactionsProvider for BlockchainProvider2 { }; if let Some(block_state) = block_state { - let transaction = block_state.block().block().body.get(tx_index).cloned(); + let transaction = block_state.block().block().body.transactions.get(tx_index).cloned(); Ok(transaction) } else { provider.transaction_by_id(id) @@ -709,8 +709,14 @@ impl TransactionsProvider for BlockchainProvider2 { }; if let Some(block_state) = block_state { - let transaction = - block_state.block().block().body.get(tx_index).cloned().map(Into::into); + let transaction = block_state + .block() + .block() + .body + .transactions + .get(tx_index) + .cloned() + .map(Into::into); Ok(transaction) } else { provider.transaction_by_id_no_hash(id) @@ -753,12 +759,12 @@ impl TransactionsProvider for BlockchainProvider2 { match id { BlockHashOrNumber::Hash(hash) => { if let Some(block_state) = self.canonical_in_memory_state.state_by_hash(hash) { - return Ok(Some(block_state.block().block().body.clone())); + return Ok(Some(block_state.block().block().body.transactions.clone())); } } BlockHashOrNumber::Number(number) => { if let Some(block_state) = self.canonical_in_memory_state.state_by_number(number) { - return Ok(Some(block_state.block().block().body.clone())); + return Ok(Some(block_state.block().block().body.transactions.clone())); } } } @@ -780,7 +786,7 @@ impl TransactionsProvider for BlockchainProvider2 { if let Some(block_state) = self.canonical_in_memory_state.state_by_number(number) { // TODO: there might be an update between loop iterations, we // need to handle that situation. - transactions.push(block_state.block().block().body.clone()); + transactions.push(block_state.block().block().body.transactions.clone()); last_in_memory_block = Some(number); } else { break @@ -825,6 +831,7 @@ impl TransactionsProvider for BlockchainProvider2 { .block() .block() .body + .transactions .get(tx_index) .and_then(|transaction| transaction.recover_signer()); Ok(sender) @@ -857,12 +864,13 @@ impl ReceiptProvider for BlockchainProvider2 { // assuming 1:1 correspondence between transactions and receipts debug_assert_eq!( - block.body.len(), + block.body.transactions.len(), receipts.len(), "Mismatch between transaction and receipt count" ); - if let Some(tx_index) = block.body.iter().position(|tx| tx.hash() == hash) { + if let Some(tx_index) = block.body.transactions.iter().position(|tx| tx.hash() == hash) + { // safe to use tx_index for receipts due to 1:1 correspondence return Ok(receipts.get(tx_index).cloned()); } @@ -940,7 +948,7 @@ impl WithdrawalsProvider for BlockchainProvider2 { let Some(number) = self.convert_hash_or_number(id)? else { return Ok(None) }; if let Some(block) = self.canonical_in_memory_state.state_by_number(number) { - Ok(block.block().block().withdrawals.clone()) + Ok(block.block().block().body.withdrawals.clone()) } else { self.database.withdrawals_by_block(id, timestamp) } @@ -952,7 +960,7 @@ impl WithdrawalsProvider for BlockchainProvider2 { // If the best block is in memory, use that. Otherwise, use the latest withdrawal in the // database. if let Some(block) = self.canonical_in_memory_state.state_by_number(best_block_num) { - Ok(block.block().block().withdrawals.clone().and_then(|mut w| w.pop())) + Ok(block.block().block().body.withdrawals.clone().and_then(|mut w| w.pop())) } else { self.database.latest_withdrawal() } @@ -970,7 +978,7 @@ impl RequestsProvider for BlockchainProvider2 { } let Some(number) = self.convert_hash_or_number(id)? else { return Ok(None) }; if let Some(block) = self.canonical_in_memory_state.state_by_number(number) { - Ok(block.block().block().requests.clone()) + Ok(block.block().block().body.requests.clone()) } else { self.database.requests_by_block(id, timestamp) } @@ -1501,7 +1509,7 @@ mod tests { let receipts: Vec> = database_blocks .iter() .chain(in_memory_blocks.iter()) - .map(|block| block.body.iter()) + .map(|block| block.body.transactions.iter()) .map(|tx| tx.map(|tx| random_receipt(rng, tx, Some(2))).collect()) .collect(); @@ -1826,11 +1834,11 @@ mod tests { // First in memory block ommers should be found assert_eq!( provider.ommers(first_in_mem_block.number.into())?, - Some(first_in_mem_block.ommers.clone()) + Some(first_in_mem_block.body.ommers.clone()) ); assert_eq!( provider.ommers(first_in_mem_block.hash().into())?, - Some(first_in_mem_block.ommers.clone()) + Some(first_in_mem_block.body.ommers.clone()) ); // A random hash should return None as the block number is not found @@ -2779,7 +2787,7 @@ mod tests { shainghai_timestamp )? .unwrap(), - block.withdrawals.unwrap(), + block.body.withdrawals.unwrap(), "Expected withdrawals_by_block to return correct withdrawals" ); } @@ -2789,7 +2797,7 @@ mod tests { assert_eq!( Some(provider.latest_withdrawal()?.unwrap()), - canonical_block.withdrawals.clone().unwrap().pop(), + canonical_block.body.withdrawals.clone().unwrap().pop(), "Expected latest withdrawal to be equal to last withdrawal entry in canonical block" ); @@ -2986,11 +2994,11 @@ mod tests { assert_eq!( provider.ommers_by_id(block_number.into()).unwrap().unwrap_or_default(), - database_block.ommers + database_block.body.ommers ); assert_eq!( provider.ommers_by_id(block_hash.into()).unwrap().unwrap_or_default(), - database_block.ommers + database_block.body.ommers ); let block_number = in_memory_block.number; @@ -2998,11 +3006,11 @@ mod tests { assert_eq!( provider.ommers_by_id(block_number.into()).unwrap().unwrap_or_default(), - in_memory_block.ommers + in_memory_block.body.ommers ); assert_eq!( provider.ommers_by_id(block_hash.into()).unwrap().unwrap_or_default(), - in_memory_block.ommers + in_memory_block.body.ommers ); Ok(()) @@ -3022,8 +3030,8 @@ mod tests { for block in blocks { let block_number = block.number as usize; - for (txn_number, _) in block.body.iter().enumerate() { - let txn_hash = block.body.get(txn_number).unwrap().hash(); + for (txn_number, _) in block.body.transactions.iter().enumerate() { + let txn_hash = block.body.transactions.get(txn_number).unwrap().hash(); let txn_id = provider.transaction_id(txn_hash)?.unwrap(); assert_eq!( provider.receipt(txn_id)?.unwrap(), @@ -3265,11 +3273,11 @@ mod tests { assert_eq!( provider.requests_by_block(database_block.number.into(), prague_timestamp,)?, - database_block.requests.clone() + database_block.body.requests.clone() ); assert_eq!( provider.requests_by_block(in_memory_block.number.into(), prague_timestamp,)?, - in_memory_block.requests.clone() + in_memory_block.body.requests.clone() ); Ok(()) @@ -3535,7 +3543,7 @@ mod tests { // Database // Choose a random transaction from the database blocks - let tx = &database_blocks[0].body[0]; + let tx = &database_blocks[0].body.transactions[0]; let tx_hash = tx.hash(); // Ensure the transaction ID can be found in the database @@ -3544,7 +3552,7 @@ mod tests { // In memory // Choose a random transaction from the in-memory blocks - let tx = &in_memory_blocks[0].body[0]; + let tx = &in_memory_blocks[0].body.transactions[0]; let tx_hash = tx.hash(); // Ensure the transaction ID can be found in the in-memory state @@ -3587,7 +3595,7 @@ mod tests { // In memory // Choose a random transaction ID from in-memory blocks - let tx = &in_memory_blocks[0].body[0]; + let tx = &in_memory_blocks[0].body.transactions[0]; let tx_hash = tx.hash(); // Fetch the transaction ID @@ -3603,7 +3611,7 @@ mod tests { // Database // Choose a random transaction ID from the database blocks - let tx = &database_blocks[0].body[0]; + let tx = &database_blocks[0].body.transactions[0]; let tx_hash = tx.hash(); // Fetch the transaction ID @@ -3643,7 +3651,7 @@ mod tests { // In memory // Choose a random transaction ID from in-memory blocks - let tx = &in_memory_blocks[0].body[0]; + let tx = &in_memory_blocks[0].body.transactions[0]; let tx_hash = tx.hash(); // Fetch the transaction ID @@ -3660,7 +3668,7 @@ mod tests { // Database // Choose a random transaction ID from the database blocks - let tx = &database_blocks[0].body[0]; + let tx = &database_blocks[0].body.transactions[0]; let tx_hash = tx.hash(); // Fetch the transaction ID @@ -3700,7 +3708,7 @@ mod tests { // In memory // Choose a random transaction hash from the in-memory blocks - let tx = &in_memory_blocks[0].body[0]; + let tx = &in_memory_blocks[0].body.transactions[0]; let tx_hash = tx.hash(); // Ensure the transaction can be retrieved by its hash from the in-memory state @@ -3713,7 +3721,7 @@ mod tests { // Database // Choose a random transaction hash from the database blocks - let tx = &database_blocks[0].body[0]; + let tx = &database_blocks[0].body.transactions[0]; let tx_hash = tx.hash(); // Ensure the transaction can be retrieved by its hash from the database @@ -3749,7 +3757,7 @@ mod tests { // In memory // Choose a random transaction from the in-memory block - let tx = &in_memory_blocks[0].body[0]; + let tx = &in_memory_blocks[0].body.transactions[0]; let tx_hash = tx.hash(); // Create the expected metadata for this transaction @@ -3780,7 +3788,7 @@ mod tests { // Database // Choose a random transaction from the database blocks - let tx = &database_blocks[0].body[0]; + let tx = &database_blocks[0].body.transactions[0]; let tx_hash = tx.hash(); // Create the expected metadata for this transaction @@ -3834,7 +3842,7 @@ mod tests { // In memory // Choose a random transaction ID from in-memory blocks - let tx = &in_memory_blocks[0].body[0]; + let tx = &in_memory_blocks[0].body.transactions[0]; let tx_hash = tx.hash(); // Fetch the transaction ID @@ -3852,7 +3860,7 @@ mod tests { // Database // Choose a random transaction from the database block - let tx = &database_blocks[0].body[0]; + let tx = &database_blocks[0].body.transactions[0]; let tx_hash = tx.hash(); // Fetch the transaction ID @@ -3896,7 +3904,7 @@ mod tests { // Ensure the transactions match the expected transactions in the block assert_eq!( - transactions, in_memory_blocks[0].body, + transactions, in_memory_blocks[0].body.transactions, "The transactions should match the in-memory block transactions" ); @@ -3910,7 +3918,7 @@ mod tests { // Ensure the transactions match the expected transactions in the block assert_eq!( - transactions, database_blocks[0].body, + transactions, database_blocks[0].body.transactions, "The transactions should match the database block transactions" ); @@ -3949,7 +3957,7 @@ mod tests { // Ensure the transactions match the expected transactions in the block assert_eq!( - transactions, in_memory_blocks[0].body, + transactions, in_memory_blocks[0].body.transactions, "The transactions should match the in-memory block transactions" ); @@ -3963,7 +3971,7 @@ mod tests { // Ensure the transactions match the expected transactions in the block assert_eq!( - transactions, database_blocks[0].body, + transactions, database_blocks[0].body.transactions, "The transactions should match the database block transactions" ); @@ -4006,8 +4014,8 @@ mod tests { // Ensure the transactions match the expected transactions in the in-memory blocks assert_eq!(result.len(), 2); - assert_eq!(result[0], in_memory_blocks[0].body); - assert_eq!(result[1], in_memory_blocks[1].body); + assert_eq!(result[0], in_memory_blocks[0].body.transactions); + assert_eq!(result[1], in_memory_blocks[1].body.transactions); // Database // Define a block range entirely within database blocks @@ -4019,8 +4027,8 @@ mod tests { // Ensure the transactions match the expected transactions in the database blocks assert_eq!(result.len(), 2); - assert_eq!(result[0], database_blocks[0].body); - assert_eq!(result[1], database_blocks[1].body); + assert_eq!(result[0], database_blocks[0].body.transactions); + assert_eq!(result[1], database_blocks[1].body.transactions); Ok(()) } @@ -4047,8 +4055,8 @@ mod tests { // Ensure the transactions match the expected transactions in the database assert_eq!(result.len(), 2); - assert_eq!(result[0], database_blocks[0].body[0].clone().into()); - assert_eq!(result[1], database_blocks[0].body[1].clone().into()); + assert_eq!(result[0], database_blocks[0].body.transactions[0].clone().into()); + assert_eq!(result[1], database_blocks[0].body.transactions[1].clone().into()); // Define an empty range that should return no transactions let start_tx_num = u64::MAX; @@ -4130,7 +4138,7 @@ mod tests { // In memory // Choose a random transaction from the in-memory block - let tx = &in_memory_blocks[0].body[0]; + let tx = &in_memory_blocks[0].body.transactions[0]; // Retrieve the transaction ID let tx_id = provider.transaction_id(tx.hash())?.unwrap(); @@ -4148,7 +4156,7 @@ mod tests { // Database // Choose a random transaction from the database block - let tx = &database_blocks[0].body[0]; + let tx = &database_blocks[0].body.transactions[0]; // Retrieve the transaction ID let tx_id = provider.transaction_id(tx.hash())?.unwrap(); diff --git a/crates/storage/provider/src/providers/database/mod.rs b/crates/storage/provider/src/providers/database/mod.rs index ab1a008bb..520b51452 100644 --- a/crates/storage/provider/src/providers/database/mod.rs +++ b/crates/storage/provider/src/providers/database/mod.rs @@ -708,9 +708,9 @@ mod tests { ); assert_matches!( provider.transaction_sender(0), Ok(Some(sender)) - if sender == block.body[0].recover_signer().unwrap() + if sender == block.body.transactions[0].recover_signer().unwrap() ); - assert_matches!(provider.transaction_id(block.body[0].hash), Ok(Some(0))); + assert_matches!(provider.transaction_id(block.body.transactions[0].hash), Ok(Some(0))); } { @@ -725,7 +725,7 @@ mod tests { Ok(_) ); assert_matches!(provider.transaction_sender(0), Ok(None)); - assert_matches!(provider.transaction_id(block.body[0].hash), Ok(None)); + assert_matches!(provider.transaction_id(block.body.transactions[0].hash), Ok(None)); } } @@ -753,7 +753,7 @@ mod tests { .clone() .map(|tx_number| ( tx_number, - block.body[tx_number as usize].recover_signer().unwrap() + block.body.transactions[tx_number as usize].recover_signer().unwrap() )) .collect()) ); @@ -766,7 +766,13 @@ mod tests { result, Ok(vec![( 0, - block.body.iter().cloned().map(|tx| tx.into_ecrecovered().unwrap()).collect() + block + .body + .transactions + .iter() + .cloned() + .map(|tx| tx.into_ecrecovered().unwrap()) + .collect() )]) ) } diff --git a/crates/storage/provider/src/providers/database/provider.rs b/crates/storage/provider/src/providers/database/provider.rs index 61ee88f3d..e326ad6e1 100644 --- a/crates/storage/provider/src/providers/database/provider.rs +++ b/crates/storage/provider/src/providers/database/provider.rs @@ -39,7 +39,7 @@ use reth_evm::ConfigureEvmEnv; use reth_execution_types::{Chain, ExecutionOutcome}; use reth_network_p2p::headers::downloader::SyncTarget; use reth_primitives::{ - Account, Block, BlockWithSenders, Bytecode, GotExpected, Header, Receipt, Requests, + Account, Block, BlockBody, BlockWithSenders, Bytecode, GotExpected, Header, Receipt, Requests, SealedBlock, SealedBlockWithSenders, SealedHeader, StaticFileSegment, StorageEntry, TransactionMeta, TransactionSigned, TransactionSignedEcRecovered, TransactionSignedNoHash, Withdrawal, Withdrawals, @@ -754,7 +754,7 @@ impl DatabaseProvider { { let header = SealedHeader::new(header, header_hash); - let (body, senders) = tx.into_iter().map(|tx| tx.to_components()).unzip(); + let (transactions, senders) = tx.into_iter().map(|tx| tx.to_components()).unzip(); // Ommers can be missing let mut ommers = Vec::new(); @@ -795,7 +795,10 @@ impl DatabaseProvider { } blocks.push(SealedBlockWithSenders { - block: SealedBlock { header, body, ommers, withdrawals, requests }, + block: SealedBlock { + header, + body: BlockBody { transactions, ommers, withdrawals, requests }, + }, senders, }) } @@ -1250,7 +1253,7 @@ impl DatabaseProvider { { let header = SealedHeader::new(header, header_hash); - let (body, senders) = tx.into_iter().map(|tx| tx.to_components()).unzip(); + let (transactions, senders) = tx.into_iter().map(|tx| tx.to_components()).unzip(); // Ommers can be missing let mut ommers = Vec::new(); @@ -1291,7 +1294,10 @@ impl DatabaseProvider { } blocks.push(SealedBlockWithSenders { - block: SealedBlock { header, body, ommers, withdrawals, requests }, + block: SealedBlock { + header, + body: BlockBody { transactions, ommers, withdrawals, requests }, + }, senders, }) } @@ -1654,7 +1660,10 @@ impl BlockReader for DatabasePr None => return Ok(None), }; - return Ok(Some(Block { header, body: transactions, ommers, withdrawals, requests })) + return Ok(Some(Block { + header, + body: BlockBody { transactions, ommers, withdrawals, requests }, + })) } } @@ -1713,8 +1722,8 @@ impl BlockReader for DatabasePr id, transaction_kind, |block_number| self.header_by_number(block_number), - |header, body, senders, ommers, withdrawals, requests| { - Block { header, body, ommers, withdrawals, requests } + |header, transactions, senders, ommers, withdrawals, requests| { + Block { header, body: BlockBody { transactions, ommers, withdrawals, requests } } // Note: we're using unchecked here because we know the block contains valid txs // wrt to its height and can ignore the s value check so pre // EIP-2 txs are allowed @@ -1734,14 +1743,17 @@ impl BlockReader for DatabasePr id, transaction_kind, |block_number| self.sealed_header(block_number), - |header, body, senders, ommers, withdrawals, requests| { - SealedBlock { header, body, ommers, withdrawals, requests } - // Note: we're using unchecked here because we know the block contains valid txs - // wrt to its height and can ignore the s value check so pre - // EIP-2 txs are allowed - .try_with_senders_unchecked(senders) - .map(Some) - .map_err(|_| ProviderError::SenderRecoveryError) + |header, transactions, senders, ommers, withdrawals, requests| { + SealedBlock { + header, + body: BlockBody { transactions, ommers, withdrawals, requests }, + } + // Note: we're using unchecked here because we know the block contains valid txs + // wrt to its height and can ignore the s value check so pre + // EIP-2 txs are allowed + .try_with_senders_unchecked(senders) + .map(Some) + .map_err(|_| ProviderError::SenderRecoveryError) }, ) } @@ -1752,7 +1764,7 @@ impl BlockReader for DatabasePr range, |range| self.headers_range(range), |header, tx_range, ommers, withdrawals, requests| { - let body = if tx_range.is_empty() { + let transactions = if tx_range.is_empty() { Vec::new() } else { self.transactions_by_tx_range_with_cursor(tx_range, &mut tx_cursor)? @@ -1760,7 +1772,10 @@ impl BlockReader for DatabasePr .map(Into::into) .collect() }; - Ok(Block { header, body, ommers, withdrawals, requests }) + Ok(Block { + header, + body: BlockBody { transactions, ommers, withdrawals, requests }, + }) }, ) } @@ -1772,8 +1787,8 @@ impl BlockReader for DatabasePr self.block_with_senders_range( range, |range| self.headers_range(range), - |header, body, ommers, withdrawals, requests, senders| { - Block { header, body, ommers, withdrawals, requests } + |header, transactions, ommers, withdrawals, requests, senders| { + Block { header, body: BlockBody { transactions, ommers, withdrawals, requests } } .try_with_senders_unchecked(senders) .map_err(|_| ProviderError::SenderRecoveryError) }, @@ -1787,9 +1802,12 @@ impl BlockReader for DatabasePr self.block_with_senders_range( range, |range| self.sealed_headers_range(range), - |header, body, ommers, withdrawals, requests, senders| { + |header, transactions, ommers, withdrawals, requests, senders| { SealedBlockWithSenders::new( - SealedBlock { header, body, ommers, withdrawals, requests }, + SealedBlock { + header, + body: BlockBody { transactions, ommers, withdrawals, requests }, + }, senders, ) .ok_or(ProviderError::SenderRecoveryError) @@ -3362,10 +3380,10 @@ impl( block_number, - StoredBlockOmmers { ommers: block.block.ommers }, + StoredBlockOmmers { ommers: block.block.body.ommers }, )?; durations_recorder.record_relative(metrics::Action::InsertBlockOmmers); } @@ -3379,14 +3397,16 @@ impl( block_number, @@ -3447,7 +3467,7 @@ impl(block_number, requests)?; durations_recorder.record_relative(metrics::Action::InsertBlockRequests); diff --git a/crates/storage/provider/src/test_utils/blocks.rs b/crates/storage/provider/src/test_utils/blocks.rs index 13c94de06..43df70f5c 100644 --- a/crates/storage/provider/src/test_utils/blocks.rs +++ b/crates/storage/provider/src/test_utils/blocks.rs @@ -1,14 +1,13 @@ //! Dummy blocks and data for tests use crate::{DatabaseProviderRW, ExecutionOutcome}; -use alloy_primitives::{ - b256, hex_literal::hex, Address, BlockNumber, Bytes, Log, Parity, Sealable, TxKind, B256, U256, -}; +use alloy_primitives::{Log, Parity, Sealable}; use once_cell::sync::Lazy; use reth_db::tables; use reth_db_api::{database::Database, models::StoredBlockBodyIndices}; use reth_primitives::{ - Account, Header, Receipt, Requests, SealedBlock, SealedBlockWithSenders, SealedHeader, - Signature, Transaction, TransactionSigned, TxLegacy, TxType, Withdrawal, Withdrawals, + alloy_primitives, b256, hex_literal::hex, Account, Address, BlockBody, BlockNumber, Bytes, + Header, Receipt, SealedBlock, SealedBlockWithSenders, SealedHeader, Signature, Transaction, + TransactionSigned, TxKind, TxLegacy, TxType, Withdrawal, Withdrawals, B256, U256, }; use reth_trie::root::{state_root_unhashed, storage_root_unhashed}; use revm::{ @@ -87,27 +86,29 @@ pub(crate) static TEST_BLOCK: Lazy = Lazy::new(|| SealedBlock { }, hex!("cf7b274520720b50e6a4c3e5c4d553101f44945396827705518ce17cb7219a42").into(), ), - body: vec![TransactionSigned { - hash: hex!("3541dd1d17e76adeb25dcf2b0a9b60a1669219502e58dcf26a2beafbfb550397").into(), - signature: Signature::new( - U256::from_str( - "51983300959770368863831494747186777928121405155922056726144551509338672451120", - ) - .unwrap(), - U256::from_str( - "29056683545955299640297374067888344259176096769870751649153779895496107008675", - ) - .unwrap(), - Parity::NonEip155(false), - ), - transaction: Transaction::Legacy(TxLegacy { - gas_price: 10, - gas_limit: 400_000, - to: TxKind::Call(hex!("095e7baea6a6c7c4c2dfeb977efac326af552d87").into()), - ..Default::default() - }), - }], - ..Default::default() + body: BlockBody { + transactions: vec![TransactionSigned { + hash: hex!("3541dd1d17e76adeb25dcf2b0a9b60a1669219502e58dcf26a2beafbfb550397").into(), + signature: Signature::new( + U256::from_str( + "51983300959770368863831494747186777928121405155922056726144551509338672451120", + ) + .unwrap(), + U256::from_str( + "29056683545955299640297374067888344259176096769870751649153779895496107008675", + ) + .unwrap(), + Parity::NonEip155(false), + ), + transaction: Transaction::Legacy(TxLegacy { + gas_price: 10, + gas_limit: 400_000, + to: TxKind::Call(hex!("095e7baea6a6c7c4c2dfeb977efac326af552d87").into()), + ..Default::default() + }), + }], + ..Default::default() + }, }); /// Test chain with genesis, blocks, execution results @@ -158,10 +159,7 @@ pub fn genesis() -> SealedBlock { Header { number: 0, difficulty: U256::from(1), ..Default::default() }, B256::ZERO, ), - body: vec![], - ommers: vec![], - withdrawals: Some(Withdrawals::default()), - requests: Some(Requests::default()), + body: Default::default(), } } @@ -229,7 +227,7 @@ fn block1(number: BlockNumber) -> (SealedBlockWithSenders, ExecutionOutcome) { ); let mut block = TEST_BLOCK.clone(); - block.withdrawals = Some(Withdrawals::new(vec![Withdrawal::default()])); + block.body.withdrawals = Some(Withdrawals::new(vec![Withdrawal::default()])); let mut header = block.header.clone().unseal(); header.number = number; header.state_root = state_root; @@ -294,7 +292,7 @@ fn block2( let mut block = TEST_BLOCK.clone(); - block.withdrawals = Some(Withdrawals::new(vec![Withdrawal::default()])); + block.body.withdrawals = Some(Withdrawals::new(vec![Withdrawal::default()])); let mut header = block.header.clone().unseal(); header.number = number; header.state_root = state_root; @@ -361,7 +359,7 @@ fn block3( let state_root = bundle_state_root(&extended); let mut block = TEST_BLOCK.clone(); - block.withdrawals = Some(Withdrawals::new(vec![Withdrawal::default()])); + block.body.withdrawals = Some(Withdrawals::new(vec![Withdrawal::default()])); let mut header = block.header.clone().unseal(); header.number = number; header.state_root = state_root; @@ -454,7 +452,7 @@ fn block4( let state_root = bundle_state_root(&extended); let mut block = TEST_BLOCK.clone(); - block.withdrawals = Some(Withdrawals::new(vec![Withdrawal::default()])); + block.body.withdrawals = Some(Withdrawals::new(vec![Withdrawal::default()])); let mut header = block.header.clone().unseal(); header.number = number; header.state_root = state_root; @@ -542,7 +540,7 @@ fn block5( let state_root = bundle_state_root(&extended); let mut block = TEST_BLOCK.clone(); - block.withdrawals = Some(Withdrawals::new(vec![Withdrawal::default()])); + block.body.withdrawals = Some(Withdrawals::new(vec![Withdrawal::default()])); let mut header = block.header.clone().unseal(); header.number = number; header.state_root = state_root; diff --git a/crates/storage/provider/src/test_utils/mock.rs b/crates/storage/provider/src/test_utils/mock.rs index e7a79c339..9277df6e6 100644 --- a/crates/storage/provider/src/test_utils/mock.rs +++ b/crates/storage/provider/src/test_utils/mock.rs @@ -238,7 +238,7 @@ impl TransactionsProvider for MockEthProvider { let lock = self.blocks.lock(); let tx_number = lock .values() - .flat_map(|block| &block.body) + .flat_map(|block| &block.body.transactions) .position(|tx| tx.hash() == tx_hash) .map(|pos| pos as TxNumber); @@ -247,7 +247,8 @@ impl TransactionsProvider for MockEthProvider { fn transaction_by_id(&self, id: TxNumber) -> ProviderResult> { let lock = self.blocks.lock(); - let transaction = lock.values().flat_map(|block| &block.body).nth(id as usize).cloned(); + let transaction = + lock.values().flat_map(|block| &block.body.transactions).nth(id as usize).cloned(); Ok(transaction) } @@ -259,7 +260,7 @@ impl TransactionsProvider for MockEthProvider { let lock = self.blocks.lock(); let transaction = lock .values() - .flat_map(|block| &block.body) + .flat_map(|block| &block.body.transactions) .nth(id as usize) .map(|tx| Into::::into(tx.clone())); @@ -267,11 +268,9 @@ impl TransactionsProvider for MockEthProvider { } fn transaction_by_hash(&self, hash: TxHash) -> ProviderResult> { - Ok(self - .blocks - .lock() - .iter() - .find_map(|(_, block)| block.body.iter().find(|tx| tx.hash() == hash).cloned())) + Ok(self.blocks.lock().iter().find_map(|(_, block)| { + block.body.transactions.iter().find(|tx| tx.hash() == hash).cloned() + })) } fn transaction_by_hash_with_meta( @@ -280,7 +279,7 @@ impl TransactionsProvider for MockEthProvider { ) -> ProviderResult> { let lock = self.blocks.lock(); for (block_hash, block) in lock.iter() { - for (index, tx) in block.body.iter().enumerate() { + for (index, tx) in block.body.transactions.iter().enumerate() { if tx.hash() == hash { let meta = TransactionMeta { tx_hash: hash, @@ -308,10 +307,10 @@ impl TransactionsProvider for MockEthProvider { let lock = self.blocks.lock(); let mut current_tx_number: TxNumber = 0; for block in lock.values() { - if current_tx_number + (block.body.len() as TxNumber) > id { + if current_tx_number + (block.body.transactions.len() as TxNumber) > id { return Ok(Some(block.header.number)) } - current_tx_number += block.body.len() as TxNumber; + current_tx_number += block.body.transactions.len() as TxNumber; } Ok(None) } @@ -320,7 +319,7 @@ impl TransactionsProvider for MockEthProvider { &self, id: BlockHashOrNumber, ) -> ProviderResult>> { - Ok(self.block(id)?.map(|b| b.body)) + Ok(self.block(id)?.map(|b| b.body.transactions)) } fn transactions_by_block_range( @@ -331,7 +330,7 @@ impl TransactionsProvider for MockEthProvider { let mut map = BTreeMap::new(); for (_, block) in self.blocks.lock().iter() { if range.contains(&block.number) { - map.insert(block.number, block.body.clone()); + map.insert(block.number, block.body.transactions.clone()); } } @@ -345,7 +344,7 @@ impl TransactionsProvider for MockEthProvider { let lock = self.blocks.lock(); let transactions = lock .values() - .flat_map(|block| &block.body) + .flat_map(|block| &block.body.transactions) .enumerate() .filter_map(|(tx_number, tx)| { if range.contains(&(tx_number as TxNumber)) { @@ -366,7 +365,7 @@ impl TransactionsProvider for MockEthProvider { let lock = self.blocks.lock(); let transactions = lock .values() - .flat_map(|block| &block.body) + .flat_map(|block| &block.body.transactions) .enumerate() .filter_map(|(tx_number, tx)| { if range.contains(&(tx_number as TxNumber)) { diff --git a/crates/storage/provider/src/writer/mod.rs b/crates/storage/provider/src/writer/mod.rs index 63bbbf3e0..17bf9db81 100644 --- a/crates/storage/provider/src/writer/mod.rs +++ b/crates/storage/provider/src/writer/mod.rs @@ -252,8 +252,13 @@ where self.static_file().get_writer(block.number, StaticFileSegment::Transactions)?; let mut storage_writer = UnifiedStorageWriter::from(self.database(), transactions_writer); - let no_hash_transactions = - block.body.clone().into_iter().map(TransactionSignedNoHash::from).collect(); + let no_hash_transactions = block + .body + .transactions + .clone() + .into_iter() + .map(TransactionSignedNoHash::from) + .collect(); storage_writer.append_transactions_from_blocks( block.header().number, std::iter::once(&no_hash_transactions), diff --git a/crates/transaction-pool/src/blobstore/tracker.rs b/crates/transaction-pool/src/blobstore/tracker.rs index 238316708..e6041fa12 100644 --- a/crates/transaction-pool/src/blobstore/tracker.rs +++ b/crates/transaction-pool/src/blobstore/tracker.rs @@ -38,9 +38,12 @@ impl BlobStoreCanonTracker { /// Note: In case this is a chain that's part of a reorg, this replaces previously tracked /// blocks. pub fn add_new_chain_blocks(&mut self, blocks: &ChainBlocks<'_>) { - let blob_txs = blocks.iter().map(|(num, blocks)| { - let iter = - blocks.body.iter().filter(|tx| tx.transaction.is_eip4844()).map(|tx| tx.hash); + let blob_txs = blocks.iter().map(|(num, block)| { + let iter = block + .body + .transactions() + .filter(|tx| tx.transaction.is_eip4844()) + .map(|tx| tx.hash); (*num, iter) }); self.add_blocks(blob_txs); diff --git a/testing/testing-utils/src/generators.rs b/testing/testing-utils/src/generators.rs index 5915596b9..83006b2be 100644 --- a/testing/testing-utils/src/generators.rs +++ b/testing/testing-utils/src/generators.rs @@ -9,7 +9,7 @@ use rand::{ distributions::uniform::SampleRange, rngs::StdRng, seq::SliceRandom, thread_rng, SeedableRng, }; use reth_primitives::{ - proofs, sign_message, Account, Header, Log, Receipt, Request, Requests, SealedBlock, + proofs, sign_message, Account, BlockBody, Header, Log, Receipt, Request, Requests, SealedBlock, SealedHeader, StorageEntry, Transaction, TransactionSigned, TxLegacy, Withdrawal, Withdrawals, }; use secp256k1::{Keypair, Secp256k1}; @@ -224,10 +224,12 @@ pub fn random_block(rng: &mut R, number: u64, block_params: BlockParams) SealedBlock { header: SealedHeader::new(header, seal), - body: transactions, - ommers, - withdrawals: withdrawals.map(Withdrawals::new), - requests: requests.map(Requests), + body: BlockBody { + transactions, + ommers, + withdrawals: withdrawals.map(Withdrawals::new), + requests: requests.map(Requests), + }, } }