feat(rpc): respect history expiry in block() and map to PrunedHistoryUnavailable (#21270)

This commit is contained in:
Georgios Konstantopoulos
2026-01-21 14:22:05 -08:00
committed by GitHub
parent eb55c3c3da
commit 2305c3ebeb
3 changed files with 21 additions and 3 deletions

View File

@@ -507,6 +507,7 @@ impl From<reth_errors::ProviderError> 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()),
}
}

View File

@@ -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,

View File

@@ -1504,10 +1504,17 @@ impl<TX: DbTx + 'static, N: NodeTypesForProvider> 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<Option<Self::Block>> {
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