From 2305c3ebeb69617f7495dc9ae4ad2ddd14bad620 Mon Sep 17 00:00:00 2001 From: Georgios Konstantopoulos Date: Wed, 21 Jan 2026 14:22:05 -0800 Subject: [PATCH] feat(rpc): respect history expiry in block() and map to PrunedHistoryUnavailable (#21270) --- crates/rpc/rpc-eth-types/src/error/mod.rs | 1 + crates/storage/errors/src/provider.rs | 10 ++++++++++ .../provider/src/providers/database/provider.rs | 13 ++++++++++--- 3 files changed, 21 insertions(+), 3 deletions(-) diff --git a/crates/rpc/rpc-eth-types/src/error/mod.rs b/crates/rpc/rpc-eth-types/src/error/mod.rs index c7e39527b2..8c738f87a9 100644 --- a/crates/rpc/rpc-eth-types/src/error/mod.rs +++ b/crates/rpc/rpc-eth-types/src/error/mod.rs @@ -507,6 +507,7 @@ impl From for EthApiError { ProviderError::BlockNumberForTransactionIndexNotFound => Self::UnknownBlockOrTxIndex, ProviderError::FinalizedBlockNotFound => Self::HeaderNotFound(BlockId::finalized()), ProviderError::SafeBlockNotFound => Self::HeaderNotFound(BlockId::safe()), + ProviderError::BlockExpired { .. } => Self::PrunedHistoryUnavailable, err => Self::Internal(err.into()), } } diff --git a/crates/storage/errors/src/provider.rs b/crates/storage/errors/src/provider.rs index 13f8a0faa9..6536b255ac 100644 --- a/crates/storage/errors/src/provider.rs +++ b/crates/storage/errors/src/provider.rs @@ -104,6 +104,16 @@ pub enum ProviderError { /// State is not available for the given block number because it is pruned. #[error("state at block #{_0} is pruned")] StateAtBlockPruned(BlockNumber), + /// Block data is not available because history has expired. + /// + /// The requested block number is below the earliest available block. + #[error("block #{requested} is not available, history has expired (earliest available: #{earliest_available})")] + BlockExpired { + /// The block number that was requested. + requested: BlockNumber, + /// The earliest available block number. + earliest_available: BlockNumber, + }, /// Provider does not support this particular request. #[error("this provider does not support this request")] UnsupportedProvider, diff --git a/crates/storage/provider/src/providers/database/provider.rs b/crates/storage/provider/src/providers/database/provider.rs index 9a41bc243d..e26cdcbc12 100644 --- a/crates/storage/provider/src/providers/database/provider.rs +++ b/crates/storage/provider/src/providers/database/provider.rs @@ -1504,10 +1504,17 @@ impl BlockReader for DatabaseProvid /// If the header for this block is not found, this returns `None`. /// If the header is found, but the transactions either do not exist, or are not indexed, this /// will return None. + /// + /// Returns an error if the requested block is below the earliest available history. fn block(&self, id: BlockHashOrNumber) -> ProviderResult> { - if let Some(number) = self.convert_hash_or_number(id)? && - let Some(header) = self.header_by_number(number)? - { + if let Some(number) = self.convert_hash_or_number(id)? { + let earliest_available = self.static_file_provider.earliest_history_height(); + if number < earliest_available { + return Err(ProviderError::BlockExpired { requested: number, earliest_available }) + } + + let Some(header) = self.header_by_number(number)? else { return Ok(None) }; + // If the body indices are not found, this means that the transactions either do not // exist in the database yet, or they do exit but are not indexed. // If they exist but are not indexed, we don't have enough