diff --git a/crates/storage/provider/src/providers/blockchain_provider.rs b/crates/storage/provider/src/providers/blockchain_provider.rs index 0dc828fdf9b..24fe49fb7cd 100644 --- a/crates/storage/provider/src/providers/blockchain_provider.rs +++ b/crates/storage/provider/src/providers/blockchain_provider.rs @@ -514,6 +514,37 @@ impl StateProviderFactory for BlockchainProvider { } } + /// Returns a [`StateProviderBox`] indexed by the given block number or tag. + fn state_by_block_number_or_tag( + &self, + number_or_tag: BlockNumberOrTag, + ) -> ProviderResult { + match number_or_tag { + BlockNumberOrTag::Latest => self.latest(), + BlockNumberOrTag::Finalized => { + // we can only get the finalized state by hash, not by num + let hash = + self.finalized_block_hash()?.ok_or(ProviderError::FinalizedBlockNotFound)?; + self.state_by_block_hash(hash) + } + BlockNumberOrTag::Safe => { + // we can only get the safe state by hash, not by num + let hash = self.safe_block_hash()?.ok_or(ProviderError::SafeBlockNotFound)?; + self.state_by_block_hash(hash) + } + BlockNumberOrTag::Earliest => { + self.history_by_block_number(self.earliest_block_number()?) + } + BlockNumberOrTag::Pending => self.pending(), + BlockNumberOrTag::Number(num) => { + let hash = self + .block_hash(num)? + .ok_or_else(|| ProviderError::HeaderNotFound(num.into()))?; + self.state_by_block_hash(hash) + } + } + } + fn history_by_block_number( &self, block_number: BlockNumber, @@ -571,35 +602,12 @@ impl StateProviderFactory for BlockchainProvider { Ok(None) } - /// Returns a [`StateProviderBox`] indexed by the given block number or tag. - fn state_by_block_number_or_tag( - &self, - number_or_tag: BlockNumberOrTag, - ) -> ProviderResult { - match number_or_tag { - BlockNumberOrTag::Latest => self.latest(), - BlockNumberOrTag::Finalized => { - // we can only get the finalized state by hash, not by num - let hash = - self.finalized_block_hash()?.ok_or(ProviderError::FinalizedBlockNotFound)?; - self.state_by_block_hash(hash) - } - BlockNumberOrTag::Safe => { - // we can only get the safe state by hash, not by num - let hash = self.safe_block_hash()?.ok_or(ProviderError::SafeBlockNotFound)?; - self.state_by_block_hash(hash) - } - BlockNumberOrTag::Earliest => { - self.history_by_block_number(self.earliest_block_number()?) - } - BlockNumberOrTag::Pending => self.pending(), - BlockNumberOrTag::Number(num) => { - let hash = self - .block_hash(num)? - .ok_or_else(|| ProviderError::HeaderNotFound(num.into()))?; - self.state_by_block_hash(hash) - } + fn maybe_pending(&self) -> ProviderResult> { + if let Some(pending) = self.canonical_in_memory_state.pending_state() { + return Ok(Some(Box::new(self.block_state_provider(&pending)?))) } + + Ok(None) } } diff --git a/crates/storage/provider/src/test_utils/mock.rs b/crates/storage/provider/src/test_utils/mock.rs index 07bc8026616..9e47f8b6f1f 100644 --- a/crates/storage/provider/src/test_utils/mock.rs +++ b/crates/storage/provider/src/test_utils/mock.rs @@ -944,6 +944,10 @@ impl StatePr fn pending_state_by_hash(&self, _block_hash: B256) -> ProviderResult> { Ok(Some(Box::new(self.clone()))) } + + fn maybe_pending(&self) -> ProviderResult> { + Ok(Some(Box::new(self.clone()))) + } } impl BlockBodyIndicesProvider diff --git a/crates/storage/rpc-provider/src/lib.rs b/crates/storage/rpc-provider/src/lib.rs index 1e3c288e8a4..86908932096 100644 --- a/crates/storage/rpc-provider/src/lib.rs +++ b/crates/storage/rpc-provider/src/lib.rs @@ -803,6 +803,10 @@ where // RPC provider doesn't support pending state by hash Err(ProviderError::UnsupportedProvider) } + + fn maybe_pending(&self) -> Result, ProviderError> { + Ok(None) + } } impl DatabaseProviderFactory for RpcBlockchainProvider @@ -812,8 +816,8 @@ where Node: NodeTypes, { type DB = DatabaseMock; - type ProviderRW = RpcBlockchainStateProvider; type Provider = RpcBlockchainStateProvider; + type ProviderRW = RpcBlockchainStateProvider; fn database_provider_ro(&self) -> Result { // RPC provider returns a new state provider @@ -1363,14 +1367,14 @@ where TxMock::default() } - fn prune_modes_ref(&self) -> &reth_prune_types::PruneModes { - unimplemented!("prune modes not supported for RPC provider") - } - fn disable_long_read_transaction_safety(self) -> Self { // No-op for RPC provider self } + + fn prune_modes_ref(&self) -> &reth_prune_types::PruneModes { + unimplemented!("prune modes not supported for RPC provider") + } } impl BlockNumReader for RpcBlockchainStateProvider @@ -1817,6 +1821,10 @@ where // RPC provider doesn't support pending state by hash Err(ProviderError::UnsupportedProvider) } + + fn maybe_pending(&self) -> ProviderResult> { + Ok(None) + } } impl ChainSpecProvider for RpcBlockchainStateProvider diff --git a/crates/storage/storage-api/src/noop.rs b/crates/storage/storage-api/src/noop.rs index 1cb924ce113..ca66ac6931c 100644 --- a/crates/storage/storage-api/src/noop.rs +++ b/crates/storage/storage-api/src/noop.rs @@ -557,6 +557,10 @@ impl StateProviderFactory for NoopP fn pending_state_by_hash(&self, _block_hash: B256) -> ProviderResult> { Ok(Some(Box::new(self.clone()))) } + + fn maybe_pending(&self) -> ProviderResult> { + Ok(Some(Box::new(self.clone()))) + } } impl StageCheckpointReader for NoopProvider { diff --git a/crates/storage/storage-api/src/state.rs b/crates/storage/storage-api/src/state.rs index 6f508289d5f..dc8241fb95f 100644 --- a/crates/storage/storage-api/src/state.rs +++ b/crates/storage/storage-api/src/state.rs @@ -194,4 +194,9 @@ pub trait StateProviderFactory: BlockIdReader + Send + Sync { /// /// If the block couldn't be found, returns `None`. fn pending_state_by_hash(&self, block_hash: B256) -> ProviderResult>; + + /// Returns a pending [`StateProvider`] if it exists. + /// + /// This will return `None` if there's no pending state. + fn maybe_pending(&self) -> ProviderResult>; }