diff --git a/crates/rpc/rpc-eth-api/src/helpers/receipt.rs b/crates/rpc/rpc-eth-api/src/helpers/receipt.rs index 201bd83ac32..2e9d6f3c896 100644 --- a/crates/rpc/rpc-eth-api/src/helpers/receipt.rs +++ b/crates/rpc/rpc-eth-api/src/helpers/receipt.rs @@ -21,7 +21,7 @@ pub trait LoadReceipt: { /// Helper method for `eth_getBlockReceipts` and `eth_getTransactionReceipt`. /// - /// If `all_receipts` is `Some`, skips the cache lookup for receipts entirely. + /// If a value is `Some`, skips the corresponding cache lookup entirely. fn build_transaction_receipt( &self, tx: Recovered>, @@ -32,15 +32,34 @@ pub trait LoadReceipt: ) -> impl Future, Self::Error>> + Send { async move { let hash = meta.block_hash; - // Use pre-fetched receipts if available, otherwise fetch from cache. - let all_receipts = match all_receipts { - Some(receipts) => receipts, - None => self - .cache() - .get_receipts(hash) - .await - .map_err(Self::Error::from_eth_err)? - .ok_or(EthApiError::HeaderNotFound(hash.into()))?, + let (block, all_receipts) = match (block, all_receipts) { + (Some(block), Some(all_receipts)) => (Some(block), all_receipts), + (Some(block), None) => { + let all_receipts = self + .cache() + .get_receipts(hash) + .await + .map_err(Self::Error::from_eth_err)? + .ok_or(EthApiError::HeaderNotFound(hash.into()))?; + (Some(block), all_receipts) + } + (None, Some(all_receipts)) => { + let block = self + .cache() + .get_maybe_block(hash) + .await + .map_err(Self::Error::from_eth_err)?; + (block, all_receipts) + } + (None, None) => { + let (all_receipts, block) = self + .cache() + .get_receipts_and_maybe_block(hash) + .await + .map_err(Self::Error::from_eth_err)? + .ok_or(EthApiError::HeaderNotFound(hash.into()))?; + (block, all_receipts) + } }; let (gas_used, next_log_index) = diff --git a/crates/rpc/rpc-eth-types/src/cache/mod.rs b/crates/rpc/rpc-eth-types/src/cache/mod.rs index c2cc51bf659..40a186e234d 100644 --- a/crates/rpc/rpc-eth-types/src/cache/mod.rs +++ b/crates/rpc/rpc-eth-types/src/cache/mod.rs @@ -157,6 +157,16 @@ impl EthStateCache { rx.await.map_err(|_| CacheServiceUnavailable)? } + /// Requests the block for the given block hash if it is cached. + pub async fn get_maybe_block( + &self, + block_hash: B256, + ) -> ProviderResult>>> { + let (response_tx, rx) = oneshot::channel(); + let _ = self.to_service.send(CacheAction::GetCachedBlock { block_hash, response_tx }); + rx.await.map_err(|_| CacheServiceUnavailable.into()) + } + /// Requests the receipts for the block hash /// /// Returns `None` if the block was not found.