diff --git a/crates/blockchain-tree/src/blockchain_tree.rs b/crates/blockchain-tree/src/blockchain_tree.rs index f869eb4859..2aec2d2454 100644 --- a/crates/blockchain-tree/src/blockchain_tree.rs +++ b/crates/blockchain-tree/src/blockchain_tree.rs @@ -209,10 +209,22 @@ impl BlockchainTree { /// Returns the block with matching hash from any side-chain. /// /// Caution: This will not return blocks from the canonical chain. + #[inline] pub fn block_by_hash(&self, block_hash: BlockHash) -> Option<&SealedBlock> { self.state.block_by_hash(block_hash) } + /// Returns the block with matching hash from any side-chain. + /// + /// Caution: This will not return blocks from the canonical chain. + #[inline] + pub fn block_with_senders_by_hash( + &self, + block_hash: BlockHash, + ) -> Option<&SealedBlockWithSenders> { + self.state.block_with_senders_by_hash(block_hash) + } + /// Returns the block's receipts with matching hash from any side-chain. /// /// Caution: This will not return blocks from the canonical chain. diff --git a/crates/blockchain-tree/src/noop.rs b/crates/blockchain-tree/src/noop.rs index 95709dc7de..732a7d1a09 100644 --- a/crates/blockchain-tree/src/noop.rs +++ b/crates/blockchain-tree/src/noop.rs @@ -74,6 +74,10 @@ impl BlockchainTreeViewer for NoopBlockchainTree { None } + fn block_with_senders_by_hash(&self, _hash: BlockHash) -> Option { + None + } + fn buffered_block_by_hash(&self, _block_hash: BlockHash) -> Option { None } diff --git a/crates/blockchain-tree/src/shareable.rs b/crates/blockchain-tree/src/shareable.rs index ebb57ca1c7..d4776a67ce 100644 --- a/crates/blockchain-tree/src/shareable.rs +++ b/crates/blockchain-tree/src/shareable.rs @@ -117,6 +117,11 @@ impl BlockchainTreeViewer for ShareableBlockc self.tree.read().block_by_hash(block_hash).cloned() } + fn block_with_senders_by_hash(&self, block_hash: BlockHash) -> Option { + trace!(target: "blockchain_tree", ?block_hash, "Returning block by hash"); + self.tree.read().block_with_senders_by_hash(block_hash).cloned() + } + fn buffered_block_by_hash(&self, block_hash: BlockHash) -> Option { self.tree.read().get_buffered_block(&block_hash).map(|b| b.block.clone()) } diff --git a/crates/blockchain-tree/src/state.rs b/crates/blockchain-tree/src/state.rs index bca7ddf409..8c4c582294 100644 --- a/crates/blockchain-tree/src/state.rs +++ b/crates/blockchain-tree/src/state.rs @@ -56,10 +56,21 @@ impl TreeState { /// Returns the block with matching hash from any side-chain. /// /// Caution: This will not return blocks from the canonical chain. + #[inline] pub(crate) fn block_by_hash(&self, block_hash: BlockHash) -> Option<&SealedBlock> { + self.block_with_senders_by_hash(block_hash).map(|block| &block.block) + } + /// Returns the block with matching hash from any side-chain. + /// + /// Caution: This will not return blocks from the canonical chain. + #[inline] + pub(crate) fn block_with_senders_by_hash( + &self, + block_hash: BlockHash, + ) -> Option<&SealedBlockWithSenders> { let id = self.block_indices.get_blocks_chain_id(&block_hash)?; let chain = self.chains.get(&id)?; - chain.block(block_hash) + chain.block_with_senders(block_hash) } /// Returns the block's receipts with matching hash from any side-chain. diff --git a/crates/interfaces/src/blockchain_tree/mod.rs b/crates/interfaces/src/blockchain_tree/mod.rs index 8a365361bd..3d77fef03c 100644 --- a/crates/interfaces/src/blockchain_tree/mod.rs +++ b/crates/interfaces/src/blockchain_tree/mod.rs @@ -237,6 +237,12 @@ pub trait BlockchainTreeViewer: Send + Sync { /// disconnected from the canonical chain. fn block_by_hash(&self, hash: BlockHash) -> Option; + /// Returns the block with matching hash from the tree, if it exists. + /// + /// Caution: This will not return blocks from the canonical chain or buffered blocks that are + /// disconnected from the canonical chain. + fn block_with_senders_by_hash(&self, hash: BlockHash) -> Option; + /// Returns the _buffered_ (disconnected) block with matching hash from the internal buffer if /// it exists. /// @@ -295,6 +301,11 @@ pub trait BlockchainTreeViewer: Send + Sync { self.block_by_hash(self.pending_block_num_hash()?.hash) } + /// Returns the pending block if there is one. + fn pending_block_with_senders(&self) -> Option { + self.block_with_senders_by_hash(self.pending_block_num_hash()?.hash) + } + /// Returns the pending block and its receipts in one call. /// /// This exists to prevent a potential data race if the pending block changes in between diff --git a/crates/primitives/src/block.rs b/crates/primitives/src/block.rs index a432cdbc20..54e0085f53 100644 --- a/crates/primitives/src/block.rs +++ b/crates/primitives/src/block.rs @@ -98,7 +98,17 @@ impl BlockWithSenders { (!block.body.len() != senders.len()).then_some(Self { block, senders }) } + /// Seal the block with a known hash. + /// + /// WARNING: This method does not perform validation whether the hash is correct. + #[inline] + pub fn seal(self, hash: B256) -> SealedBlockWithSenders { + let Self { block, senders } = self; + SealedBlockWithSenders { block: block.seal(hash), senders } + } + /// Split Structure to its components + #[inline] pub fn into_components(self) -> (Block, Vec
) { (self.block, self.senders) } @@ -288,6 +298,13 @@ impl SealedBlockWithSenders { (self.block, self.senders) } + /// Returns the unsealed [BlockWithSenders] + #[inline] + pub fn unseal(self) -> BlockWithSenders { + let Self { block, senders } = self; + BlockWithSenders { block: block.unseal(), senders } + } + /// Returns an iterator over all transactions in the block. #[inline] pub fn transactions(&self) -> impl Iterator + '_ { diff --git a/crates/rpc/rpc-types-compat/src/block.rs b/crates/rpc/rpc-types-compat/src/block.rs index 570697dffb..578a47b369 100644 --- a/crates/rpc/rpc-types-compat/src/block.rs +++ b/crates/rpc/rpc-types-compat/src/block.rs @@ -2,7 +2,9 @@ use crate::transaction::from_recovered_with_block_context; use alloy_rlp::Encodable; -use reth_primitives::{Block as PrimitiveBlock, Header as PrimitiveHeader, B256, U256, U64}; +use reth_primitives::{ + Block as PrimitiveBlock, BlockWithSenders, Header as PrimitiveHeader, B256, U256, U64, +}; use reth_rpc_types::{Block, BlockError, BlockTransactions, BlockTransactionsKind, Header}; /// Converts the given primitive block into a [Block] response with the given @@ -10,7 +12,7 @@ use reth_rpc_types::{Block, BlockError, BlockTransactions, BlockTransactionsKind /// /// If a `block_hash` is provided, then this is used, otherwise the block hash is computed. pub fn from_block( - block: PrimitiveBlock, + block: BlockWithSenders, total_difficulty: U256, kind: BlockTransactionsKind, block_hash: Option, @@ -29,7 +31,7 @@ pub fn from_block( /// This will populate the `transactions` field with only the hashes of the transactions in the /// block: [BlockTransactions::Hashes] pub fn from_block_with_tx_hashes( - block: PrimitiveBlock, + block: BlockWithSenders, total_difficulty: U256, block_hash: Option, ) -> Block { @@ -39,7 +41,7 @@ pub fn from_block_with_tx_hashes( from_block_with_transactions( block.length(), block_hash, - block, + block.block, total_difficulty, BlockTransactions::Hashes(transactions), ) @@ -51,35 +53,38 @@ pub fn from_block_with_tx_hashes( /// This will populate the `transactions` field with the _full_ /// [Transaction](reth_rpc_types::Transaction) objects: [BlockTransactions::Full] pub fn from_block_full( - mut block: PrimitiveBlock, + mut block: BlockWithSenders, total_difficulty: U256, block_hash: Option, ) -> Result { - let block_hash = block_hash.unwrap_or_else(|| block.header.hash_slow()); - let block_number = block.number; - let base_fee_per_gas = block.base_fee_per_gas; + let block_hash = block_hash.unwrap_or_else(|| block.block.header.hash_slow()); + let block_number = block.block.number; + let base_fee_per_gas = block.block.base_fee_per_gas; // 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.length(); - let body = std::mem::take(&mut block.body); + 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 = transactions_with_senders + .enumerate() + .map(|(idx, (tx, sender))| { + let signed_tx_ec_recovered = tx.with_signer(sender); - let mut transactions = Vec::with_capacity(block.body.len()); - for (idx, tx) in body.into_iter().enumerate() { - let signed_tx = tx.into_ecrecovered().ok_or(BlockError::InvalidSignature)?; - transactions.push(from_recovered_with_block_context( - signed_tx, - block_hash, - block_number, - base_fee_per_gas, - U256::from(idx), - )) - } + from_recovered_with_block_context( + signed_tx_ec_recovered, + block_hash, + block_number, + base_fee_per_gas, + U256::from(idx), + ) + }) + .collect::>(); Ok(from_block_with_transactions( block_length, block_hash, - block, + block.block, total_difficulty, BlockTransactions::Full(transactions), )) diff --git a/crates/rpc/rpc/src/eth/api/block.rs b/crates/rpc/rpc/src/eth/api/block.rs index 3cd33be201..c1c835107c 100644 --- a/crates/rpc/rpc/src/eth/api/block.rs +++ b/crates/rpc/rpc/src/eth/api/block.rs @@ -146,13 +146,23 @@ where &self, block_id: impl Into, ) -> EthResult> { + self.block_with_senders(block_id) + .await + .map(|maybe_block| maybe_block.map(|block| block.block)) + } + + /// Returns the block object for the given block id. + pub(crate) async fn block_with_senders( + &self, + block_id: impl Into, + ) -> EthResult> { let block_id = block_id.into(); if block_id.is_pending() { // Pending block can be fetched directly without need for caching - let maybe_pending = self.provider().pending_block()?; + let maybe_pending = self.provider().pending_block_with_senders()?; return if maybe_pending.is_some() { - return Ok(maybe_pending) + Ok(maybe_pending) } else { self.local_pending_block().await } @@ -163,7 +173,7 @@ where None => return Ok(None), }; - Ok(self.cache().get_sealed_block(block_hash).await?) + Ok(self.cache().get_sealed_block_with_senders(block_hash).await?) } /// Returns the populated rpc block object for the given block id. @@ -175,7 +185,7 @@ where block_id: impl Into, full: bool, ) -> EthResult> { - let block = match self.block(block_id).await? { + let block = match self.block_with_senders(block_id).await? { Some(block) => block, None => return Ok(None), }; @@ -184,7 +194,7 @@ where .provider() .header_td_by_number(block.number)? .ok_or(EthApiError::UnknownBlockNumber)?; - let block = from_block(block.into(), total_difficulty, full.into(), Some(block_hash))?; + let block = from_block(block.unseal(), total_difficulty, full.into(), Some(block_hash))?; Ok(Some(block.into())) } } diff --git a/crates/rpc/rpc/src/eth/api/mod.rs b/crates/rpc/rpc/src/eth/api/mod.rs index 5312c82292..4ff22571de 100644 --- a/crates/rpc/rpc/src/eth/api/mod.rs +++ b/crates/rpc/rpc/src/eth/api/mod.rs @@ -15,7 +15,7 @@ use reth_interfaces::RethResult; use reth_network_api::NetworkInfo; use reth_primitives::{ revm_primitives::{BlockEnv, CfgEnv}, - Address, BlockId, BlockNumberOrTag, ChainInfo, SealedBlock, B256, U256, U64, + Address, BlockId, BlockNumberOrTag, ChainInfo, SealedBlockWithSenders, B256, U256, U64, }; use reth_provider::{ BlockReaderIdExt, ChainSpecProvider, EvmEnvProvider, StateProviderBox, StateProviderFactory, @@ -246,7 +246,7 @@ where /// /// If no pending block is available, this will derive it from the `latest` block pub(crate) fn pending_block_env_and_cfg(&self) -> EthResult { - let origin = if let Some(pending) = self.provider().pending_block()? { + let origin = if let Some(pending) = self.provider().pending_block_with_senders()? { PendingBlockEnvOrigin::ActualPending(pending) } else { // no pending block from the CL yet, so we use the latest block and modify the env @@ -281,7 +281,7 @@ where } /// Returns the locally built pending block - pub(crate) async fn local_pending_block(&self) -> EthResult> { + pub(crate) async fn local_pending_block(&self) -> EthResult> { let pending = self.pending_block_env_and_cfg()?; if pending.origin.is_actual_pending() { return Ok(pending.origin.into_actual_pending()) diff --git a/crates/rpc/rpc/src/eth/api/pending_block.rs b/crates/rpc/rpc/src/eth/api/pending_block.rs index 827dfec1a1..3c6f6b5879 100644 --- a/crates/rpc/rpc/src/eth/api/pending_block.rs +++ b/crates/rpc/rpc/src/eth/api/pending_block.rs @@ -9,7 +9,7 @@ use reth_primitives::{ BlockEnv, CfgEnv, EVMError, Env, InvalidTransaction, ResultAndState, SpecId, }, Block, BlockId, BlockNumberOrTag, ChainSpec, Header, IntoRecoveredTransaction, Receipt, - Receipts, SealedBlock, SealedHeader, B256, EMPTY_OMMER_ROOT_HASH, U256, + Receipts, SealedBlockWithSenders, SealedHeader, B256, EMPTY_OMMER_ROOT_HASH, U256, }; use reth_provider::{BundleStateWithReceipts, ChainSpecProvider, StateProviderFactory}; use reth_revm::{ @@ -42,7 +42,7 @@ impl PendingBlockEnv { self, client: &Client, pool: &Pool, - ) -> EthResult + ) -> EthResult where Client: StateProviderFactory + ChainSpecProvider, Pool: TransactionPool, @@ -61,6 +61,7 @@ impl PendingBlockEnv { let block_number = block_env.number.to::(); let mut executed_txs = Vec::new(); + let mut senders = Vec::new(); let mut best_txs = pool.best_transactions_with_base_fee(base_fee); let (withdrawals, withdrawals_root) = match origin { @@ -176,7 +177,9 @@ impl PendingBlockEnv { })); // append transaction to the list of executed transactions - executed_txs.push(tx.into_signed()); + let (tx, sender) = tx.to_components(); + executed_txs.push(tx); + senders.push(sender); } // executes the withdrawals and commits them to the Database and BundleState. @@ -236,9 +239,7 @@ impl PendingBlockEnv { // seal the block let block = Block { header, body: executed_txs, ommers: vec![], withdrawals }; - let sealed_block = block.seal_slow(); - - Ok(sealed_block) + Ok(SealedBlockWithSenders { block: block.seal_slow(), senders }) } } @@ -286,7 +287,7 @@ where #[derive(Clone, Debug)] pub(crate) enum PendingBlockEnvOrigin { /// The pending block as received from the CL. - ActualPending(SealedBlock), + ActualPending(SealedBlockWithSenders), /// The header of the latest block DerivedFromLatest(SealedHeader), } @@ -298,7 +299,7 @@ impl PendingBlockEnvOrigin { } /// Consumes the type and returns the actual pending block. - pub(crate) fn into_actual_pending(self) -> Option { + pub(crate) fn into_actual_pending(self) -> Option { match self { PendingBlockEnvOrigin::ActualPending(block) => Some(block), _ => None, @@ -337,7 +338,7 @@ impl PendingBlockEnvOrigin { #[derive(Debug)] pub(crate) struct PendingBlock { /// The cached pending block - pub(crate) block: SealedBlock, + pub(crate) block: SealedBlockWithSenders, /// Timestamp when the pending block is considered outdated pub(crate) expires_at: Instant, } diff --git a/crates/rpc/rpc/src/eth/cache/mod.rs b/crates/rpc/rpc/src/eth/cache/mod.rs index fb1f65d1db..735d15418d 100644 --- a/crates/rpc/rpc/src/eth/cache/mod.rs +++ b/crates/rpc/rpc/src/eth/cache/mod.rs @@ -2,9 +2,12 @@ use futures::{future::Either, Stream, StreamExt}; use reth_interfaces::provider::{ProviderError, ProviderResult}; -use reth_primitives::{Block, Receipt, SealedBlock, TransactionSigned, B256}; +use reth_primitives::{ + Block, BlockHashOrNumber, BlockWithSenders, Receipt, SealedBlock, SealedBlockWithSenders, + TransactionSigned, B256, +}; use reth_provider::{ - BlockReader, BlockSource, CanonStateNotification, EvmEnvProvider, StateProviderFactory, + BlockReader, CanonStateNotification, EvmEnvProvider, StateProviderFactory, TransactionVariant, }; use reth_tasks::{TaskSpawner, TokioTaskExecutor}; use revm::primitives::{BlockEnv, CfgEnv}; @@ -29,13 +32,13 @@ mod metrics; mod multi_consumer; pub use multi_consumer::MultiConsumerLruCache; -/// The type that can send the response to a requested [Block] -type BlockResponseSender = oneshot::Sender>>; - /// The type that can send the response to a requested [Block] type BlockTransactionsResponseSender = oneshot::Sender>>>; +/// The type that can send the response to a requested [BlockWithSenders] +type BlockWithSendersResponseSender = oneshot::Sender>>; + /// The type that can send the response to the requested receipts of a block. type ReceiptsResponseSender = oneshot::Sender>>>; @@ -44,9 +47,9 @@ type EnvResponseSender = oneshot::Sender>; type BlockLruCache = MultiConsumerLruCache< B256, - Block, + BlockWithSenders, L, - Either, + Either, >; type ReceiptsLruCache = MultiConsumerLruCache, L, ReceiptsResponseSender>; @@ -130,8 +133,15 @@ impl EthStateCache { /// Returns `None` if the block does not exist. pub(crate) async fn get_block(&self, block_hash: B256) -> ProviderResult> { let (response_tx, rx) = oneshot::channel(); - let _ = self.to_service.send(CacheAction::GetBlock { block_hash, response_tx }); - rx.await.map_err(|_| ProviderError::CacheServiceUnavailable)? + let _ = self.to_service.send(CacheAction::GetBlockWithSenders { block_hash, response_tx }); + let block_with_senders_res = + rx.await.map_err(|_| ProviderError::CacheServiceUnavailable)?; + + if let Ok(Some(block_with_senders)) = block_with_senders_res { + Ok(Some(block_with_senders.block)) + } else { + Ok(None) + } } /// Requests the [Block] for the block hash, sealed with the given block hash. @@ -169,6 +179,28 @@ impl EthStateCache { Ok(transactions.zip(receipts)) } + /// Requests the [BlockWithSenders] for the block hash + /// + /// Returns `None` if the block does not exist. + pub(crate) async fn get_block_with_senders( + &self, + block_hash: B256, + ) -> ProviderResult> { + let (response_tx, rx) = oneshot::channel(); + let _ = self.to_service.send(CacheAction::GetBlockWithSenders { block_hash, response_tx }); + rx.await.map_err(|_| ProviderError::CacheServiceUnavailable)? + } + + /// Requests the [SealedBlockWithSenders] for the block hash + /// + /// Returns `None` if the block does not exist. + pub(crate) async fn get_sealed_block_with_senders( + &self, + block_hash: B256, + ) -> ProviderResult> { + Ok(self.get_block_with_senders(block_hash).await?.map(|block| block.seal(block_hash))) + } + /// Requests the [Receipt] for the block hash /// /// Returns `None` if the block was not found. @@ -228,7 +260,7 @@ pub(crate) struct EthStateCacheService< LimitReceipts = ByLength, LimitEnvs = ByLength, > where - LimitBlocks: Limiter, + LimitBlocks: Limiter, LimitReceipts: Limiter>, LimitEnvs: Limiter, { @@ -255,17 +287,18 @@ where Provider: StateProviderFactory + BlockReader + EvmEnvProvider + Clone + Unpin + 'static, Tasks: TaskSpawner + Clone + 'static, { - fn on_new_block(&mut self, block_hash: B256, res: ProviderResult>) { + fn on_new_block(&mut self, block_hash: B256, res: ProviderResult>) { if let Some(queued) = self.full_block_cache.remove(&block_hash) { // send the response to queued senders for tx in queued { match tx { - Either::Left(block_tx) => { - let _ = block_tx.send(res.clone()); + Either::Left(block_with_senders) => { + 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.body)), + res.clone() + .map(|maybe_block| maybe_block.map(|block| block.block.body)), ); } } @@ -316,8 +349,7 @@ where } Some(action) => { match action { - CacheAction::GetBlock { block_hash, response_tx } => { - // check if block is cached + CacheAction::GetBlockWithSenders { block_hash, response_tx } => { if let Some(block) = this.full_block_cache.get(&block_hash).cloned() { let _ = response_tx.send(Ok(Some(block))); continue @@ -333,10 +365,14 @@ where let _permit = rate_limiter.acquire().await; // Only look in the database to prevent situations where we // looking up the tree is blocking - let res = provider - .find_block_by_hash(block_hash, BlockSource::Database); - let _ = action_tx - .send(CacheAction::BlockResult { block_hash, res }); + let block_sender = provider.block_with_senders( + BlockHashOrNumber::Hash(block_hash), + TransactionVariant::WithHash, + ); + let _ = action_tx.send(CacheAction::BlockWithSendersResult { + block_hash, + res: block_sender, + }); })); } } @@ -357,10 +393,14 @@ where let _permit = rate_limiter.acquire().await; // Only look in the database to prevent situations where we // looking up the tree is blocking - let res = provider - .find_block_by_hash(block_hash, BlockSource::Database); - let _ = action_tx - .send(CacheAction::BlockResult { block_hash, res }); + let res = provider.block_with_senders( + BlockHashOrNumber::Hash(block_hash), + TransactionVariant::WithHash, + ); + let _ = action_tx.send(CacheAction::BlockWithSendersResult { + block_hash, + res, + }); })); } } @@ -413,12 +453,20 @@ where })); } } - CacheAction::BlockResult { block_hash, res } => { - this.on_new_block(block_hash, res); - } CacheAction::ReceiptsResult { block_hash, res } => { this.on_new_receipts(block_hash, res); } + CacheAction::BlockWithSendersResult { block_hash, res } => match res { + Ok(Some(block_with_senders)) => { + this.on_new_block(block_hash, Ok(Some(block_with_senders))); + } + Ok(None) => { + this.on_new_block(block_hash, Ok(None)); + } + Err(e) => { + this.on_new_block(block_hash, Err(e)); + } + }, CacheAction::EnvResult { block_hash, res } => { let res = *res; if let Some(queued) = this.evm_env_cache.remove(&block_hash) { @@ -457,14 +505,14 @@ where /// All message variants sent through the channel enum CacheAction { - GetBlock { block_hash: B256, response_tx: BlockResponseSender }, + GetBlockWithSenders { block_hash: B256, response_tx: BlockWithSendersResponseSender }, GetBlockTransactions { block_hash: B256, response_tx: BlockTransactionsResponseSender }, GetEnv { block_hash: B256, response_tx: EnvResponseSender }, GetReceipts { block_hash: B256, response_tx: ReceiptsResponseSender }, - BlockResult { block_hash: B256, res: ProviderResult> }, + BlockWithSendersResult { block_hash: B256, res: ProviderResult> }, ReceiptsResult { block_hash: B256, res: ProviderResult>> }, EnvResult { block_hash: B256, res: Box> }, - CacheNewCanonicalChain { blocks: Vec, receipts: Vec }, + CacheNewCanonicalChain { blocks: Vec, receipts: Vec }, } struct BlockReceipts { @@ -483,13 +531,13 @@ where // we're only interested in new committed blocks let (blocks, state) = committed.inner(); - let blocks = blocks.iter().map(|(_, block)| block.block.clone()).collect::>(); + let blocks = blocks.iter().map(|(_, block)| block.clone()).collect::>(); // also cache all receipts of the blocks let mut receipts = Vec::with_capacity(blocks.len()); for block in &blocks { let block_receipts = BlockReceipts { - block_hash: block.hash, + block_hash: block.block.hash, receipts: state.receipts_by_block(block.number).to_vec(), }; receipts.push(block_receipts); diff --git a/crates/storage/provider/src/chain.rs b/crates/storage/provider/src/chain.rs index ea240dc6d8..3a6ae3fffc 100644 --- a/crates/storage/provider/src/chain.rs +++ b/crates/storage/provider/src/chain.rs @@ -71,9 +71,12 @@ impl Chain { /// Returns the block with matching hash. pub fn block(&self, block_hash: BlockHash) -> Option<&SealedBlock> { - self.blocks - .iter() - .find_map(|(_num, block)| (block.hash() == block_hash).then_some(&block.block)) + self.block_with_senders(block_hash).map(|block| &block.block) + } + + /// Returns the block with matching hash. + pub fn block_with_senders(&self, block_hash: BlockHash) -> Option<&SealedBlockWithSenders> { + self.blocks.iter().find_map(|(_num, block)| (block.hash() == block_hash).then_some(block)) } /// Return post state of the block at the `block_number` or None if block is not known diff --git a/crates/storage/provider/src/providers/database/mod.rs b/crates/storage/provider/src/providers/database/mod.rs index 48fa6eaa09..6b6c0842d0 100644 --- a/crates/storage/provider/src/providers/database/mod.rs +++ b/crates/storage/provider/src/providers/database/mod.rs @@ -15,9 +15,9 @@ use reth_primitives::{ snapshot::HighestSnapshots, stage::{StageCheckpoint, StageId}, Address, Block, BlockHash, BlockHashOrNumber, BlockNumber, BlockWithSenders, ChainInfo, - ChainSpec, Header, PruneCheckpoint, PruneSegment, Receipt, SealedBlock, SealedHeader, - TransactionMeta, TransactionSigned, TransactionSignedNoHash, TxHash, TxNumber, Withdrawal, - B256, U256, + ChainSpec, Header, PruneCheckpoint, PruneSegment, Receipt, SealedBlock, SealedBlockWithSenders, + SealedHeader, TransactionMeta, TransactionSigned, TransactionSignedNoHash, TxHash, TxNumber, + Withdrawal, B256, U256, }; use revm::primitives::{BlockEnv, CfgEnv}; use std::{ @@ -290,6 +290,10 @@ impl BlockReader for ProviderFactory { self.provider()?.pending_block() } + fn pending_block_with_senders(&self) -> ProviderResult> { + self.provider()?.pending_block_with_senders() + } + fn pending_block_and_receipts(&self) -> ProviderResult)>> { self.provider()?.pending_block_and_receipts() } diff --git a/crates/storage/provider/src/providers/database/provider.rs b/crates/storage/provider/src/providers/database/provider.rs index 81daf53de7..244011c7b6 100644 --- a/crates/storage/provider/src/providers/database/provider.rs +++ b/crates/storage/provider/src/providers/database/provider.rs @@ -1073,6 +1073,10 @@ impl BlockReader for DatabaseProvider { Ok(None) } + fn pending_block_with_senders(&self) -> ProviderResult> { + Ok(None) + } + fn pending_block_and_receipts(&self) -> ProviderResult)>> { Ok(None) } diff --git a/crates/storage/provider/src/providers/mod.rs b/crates/storage/provider/src/providers/mod.rs index df782365e6..11dba5e6a6 100644 --- a/crates/storage/provider/src/providers/mod.rs +++ b/crates/storage/provider/src/providers/mod.rs @@ -252,6 +252,10 @@ where Ok(self.tree.pending_block()) } + fn pending_block_with_senders(&self) -> ProviderResult> { + Ok(self.tree.pending_block_with_senders()) + } + fn pending_block_and_receipts(&self) -> ProviderResult)>> { Ok(self.tree.pending_block_and_receipts()) } @@ -637,6 +641,10 @@ where self.tree.block_by_hash(block_hash) } + fn block_with_senders_by_hash(&self, block_hash: BlockHash) -> Option { + self.tree.block_with_senders_by_hash(block_hash) + } + fn buffered_block_by_hash(&self, block_hash: BlockHash) -> Option { self.tree.buffered_block_by_hash(block_hash) } diff --git a/crates/storage/provider/src/test_utils/mock.rs b/crates/storage/provider/src/test_utils/mock.rs index b9f3dd6674..8a1cb6ca37 100644 --- a/crates/storage/provider/src/test_utils/mock.rs +++ b/crates/storage/provider/src/test_utils/mock.rs @@ -12,8 +12,8 @@ use reth_interfaces::provider::{ProviderError, ProviderResult}; use reth_primitives::{ keccak256, trie::AccountProof, Account, Address, Block, BlockHash, BlockHashOrNumber, BlockId, BlockNumber, BlockWithSenders, Bytecode, Bytes, ChainInfo, ChainSpec, Header, Receipt, - SealedBlock, SealedHeader, StorageKey, StorageValue, TransactionMeta, TransactionSigned, - TransactionSignedNoHash, TxHash, TxNumber, B256, U256, + SealedBlock, SealedBlockWithSenders, SealedHeader, StorageKey, StorageValue, TransactionMeta, + TransactionSigned, TransactionSignedNoHash, TxHash, TxNumber, B256, U256, }; use reth_trie::updates::TrieUpdates; use revm::primitives::{BlockEnv, CfgEnv}; @@ -438,6 +438,10 @@ impl BlockReader for MockEthProvider { Ok(None) } + fn pending_block_with_senders(&self) -> ProviderResult> { + Ok(None) + } + fn pending_block_and_receipts(&self) -> ProviderResult)>> { Ok(None) } diff --git a/crates/storage/provider/src/test_utils/noop.rs b/crates/storage/provider/src/test_utils/noop.rs index 87632f1d98..dc36ac948f 100644 --- a/crates/storage/provider/src/test_utils/noop.rs +++ b/crates/storage/provider/src/test_utils/noop.rs @@ -14,8 +14,8 @@ use reth_primitives::{ trie::AccountProof, Account, Address, Block, BlockHash, BlockHashOrNumber, BlockId, BlockNumber, Bytecode, ChainInfo, ChainSpec, Header, PruneCheckpoint, PruneSegment, Receipt, SealedBlock, - SealedHeader, StorageKey, StorageValue, TransactionMeta, TransactionSigned, - TransactionSignedNoHash, TxHash, TxNumber, B256, MAINNET, U256, + SealedBlockWithSenders, SealedHeader, StorageKey, StorageValue, TransactionMeta, + TransactionSigned, TransactionSignedNoHash, TxHash, TxNumber, B256, MAINNET, U256, }; use reth_trie::updates::TrieUpdates; use revm::primitives::{BlockEnv, CfgEnv}; @@ -85,6 +85,10 @@ impl BlockReader for NoopProvider { Ok(None) } + fn pending_block_with_senders(&self) -> ProviderResult> { + Ok(None) + } + fn pending_block_and_receipts(&self) -> ProviderResult)>> { Ok(None) } diff --git a/crates/storage/provider/src/traits/block.rs b/crates/storage/provider/src/traits/block.rs index 7669058062..44951a3fca 100644 --- a/crates/storage/provider/src/traits/block.rs +++ b/crates/storage/provider/src/traits/block.rs @@ -85,6 +85,12 @@ pub trait BlockReader: /// and the caller does not know the hash. fn pending_block(&self) -> ProviderResult>; + /// Returns the pending block if available + /// + /// Note: This returns a [SealedBlockWithSenders] because it's expected that this is sealed by + /// the provider and the caller does not know the hash. + fn pending_block_with_senders(&self) -> ProviderResult>; + /// Returns the pending block and receipts if available. fn pending_block_and_receipts(&self) -> ProviderResult)>>;