From cc601dbe9f1451b39caa96f6cd35ffe0699dae35 Mon Sep 17 00:00:00 2001 From: Dan Cline <6798349+Rjected@users.noreply.github.com> Date: Fri, 12 May 2023 16:00:16 -0400 Subject: [PATCH] feat: add safe and finalized tags to StateProviderFactory (#2654) --- crates/interfaces/src/provider.rs | 5 ---- crates/storage/provider/src/providers/mod.rs | 8 +++--- .../storage/provider/src/test_utils/mock.rs | 4 +-- .../storage/provider/src/test_utils/noop.rs | 4 +-- .../storage/provider/src/traits/block_id.rs | 24 +++++++++++++++-- crates/storage/provider/src/traits/state.rs | 26 +++++++++++++++---- 6 files changed, 51 insertions(+), 20 deletions(-) diff --git a/crates/interfaces/src/provider.rs b/crates/interfaces/src/provider.rs index d690f7b4d4..3caf0840be 100644 --- a/crates/interfaces/src/provider.rs +++ b/crates/interfaces/src/provider.rs @@ -95,9 +95,4 @@ pub enum ProviderError { /// Unable to compute state root on top of historical block #[error("Unable to compute state root on top of historical block")] StateRootNotAvailableForHistoricalBlock, - - #[error("Safe tag currently unsupported")] - SafeTagUnsupported, - #[error("Finalized tag currently unsupported")] - FinalizedTagUnsupported, } diff --git a/crates/storage/provider/src/providers/mod.rs b/crates/storage/provider/src/providers/mod.rs index 239fb46a3f..924d4b0674 100644 --- a/crates/storage/provider/src/providers/mod.rs +++ b/crates/storage/provider/src/providers/mod.rs @@ -137,12 +137,12 @@ where DB: Database, Tree: BlockchainTreeViewer + Send + Sync, { - fn safe_block_num(&self) -> Result> { - Ok(self.chain_info.get_safe_num_hash().map(|num_hash| num_hash.number)) + fn safe_block_num_hash(&self) -> Result> { + Ok(self.chain_info.get_safe_num_hash()) } - fn finalized_block_num(&self) -> Result> { - Ok(self.chain_info.get_finalized_num_hash().map(|num_hash| num_hash.number)) + fn finalized_block_num_hash(&self) -> Result> { + Ok(self.chain_info.get_finalized_num_hash()) } fn pending_block_num_hash(&self) -> Result> { diff --git a/crates/storage/provider/src/test_utils/mock.rs b/crates/storage/provider/src/test_utils/mock.rs index e98556e60d..3b2172e011 100644 --- a/crates/storage/provider/src/test_utils/mock.rs +++ b/crates/storage/provider/src/test_utils/mock.rs @@ -263,7 +263,7 @@ impl BlockNumProvider for MockEthProvider { } impl BlockIdProvider for MockEthProvider { - fn safe_block_num(&self) -> Result> { + fn safe_block_num_hash(&self) -> Result> { Ok(None) } @@ -271,7 +271,7 @@ impl BlockIdProvider for MockEthProvider { Ok(None) } - fn finalized_block_num(&self) -> Result> { + fn finalized_block_num_hash(&self) -> Result> { Ok(None) } } diff --git a/crates/storage/provider/src/test_utils/noop.rs b/crates/storage/provider/src/test_utils/noop.rs index 9d614ba2ae..d3bf077cac 100644 --- a/crates/storage/provider/src/test_utils/noop.rs +++ b/crates/storage/provider/src/test_utils/noop.rs @@ -76,11 +76,11 @@ impl BlockIdProvider for NoopProvider { Ok(None) } - fn safe_block_num(&self) -> Result> { + fn safe_block_num_hash(&self) -> Result> { Ok(None) } - fn finalized_block_num(&self) -> Result> { + fn finalized_block_num_hash(&self) -> Result> { Ok(None) } } diff --git a/crates/storage/provider/src/traits/block_id.rs b/crates/storage/provider/src/traits/block_id.rs index 9376ddc688..5ef0e38487 100644 --- a/crates/storage/provider/src/traits/block_id.rs +++ b/crates/storage/provider/src/traits/block_id.rs @@ -104,9 +104,29 @@ pub trait BlockIdProvider: BlockNumProvider + Send + Sync { /// Get the current pending block number and hash. fn pending_block_num_hash(&self) -> Result>; + /// Get the current safe block number and hash. + fn safe_block_num_hash(&self) -> Result>; + + /// Get the current finalized block number and hash. + fn finalized_block_num_hash(&self) -> Result>; + /// Get the safe block number. - fn safe_block_num(&self) -> Result>; + fn safe_block_num(&self) -> Result> { + self.safe_block_num_hash().map(|res_opt| res_opt.map(|num_hash| num_hash.number)) + } /// Get the finalized block number. - fn finalized_block_num(&self) -> Result>; + fn finalized_block_num(&self) -> Result> { + self.finalized_block_num_hash().map(|res_opt| res_opt.map(|num_hash| num_hash.number)) + } + + /// Get the safe block hash. + fn safe_block_hash(&self) -> Result> { + self.safe_block_num_hash().map(|res_opt| res_opt.map(|num_hash| num_hash.hash)) + } + + /// Get the finalized block hash. + fn finalized_block_hash(&self) -> Result> { + self.finalized_block_num_hash().map(|res_opt| res_opt.map(|num_hash| num_hash.hash)) + } } diff --git a/crates/storage/provider/src/traits/state.rs b/crates/storage/provider/src/traits/state.rs index 00ffa2029b..e5ed7e5fcc 100644 --- a/crates/storage/provider/src/traits/state.rs +++ b/crates/storage/provider/src/traits/state.rs @@ -1,5 +1,5 @@ use super::AccountProvider; -use crate::{post_state::PostState, BlockHashProvider}; +use crate::{post_state::PostState, BlockHashProvider, BlockIdProvider}; use auto_impl::auto_impl; use reth_interfaces::{provider::ProviderError, Result}; use reth_primitives::{ @@ -96,7 +96,7 @@ pub trait StateProvider: /// This affects tracing, or replaying blocks, which will need to be executed on top of the state of /// the parent block. For example, in order to trace block `n`, the state after block `n - 1` needs /// to be used, since block `n` was executed on its parent block's state. -pub trait StateProviderFactory: Send + Sync { +pub trait StateProviderFactory: BlockIdProvider + Send + Sync { /// Storage provider for latest block. fn latest(&self) -> Result>; @@ -108,15 +108,31 @@ pub trait StateProviderFactory: Send + Sync { } } - /// Returns a [StateProvider] indexed by the given block number or tag + /// Returns a [StateProvider] indexed by the given block number or tag. fn history_by_block_number_or_tag( &self, number_or_tag: BlockNumberOrTag, ) -> Result> { match number_or_tag { BlockNumberOrTag::Latest => self.latest(), - BlockNumberOrTag::Finalized => Err(ProviderError::FinalizedTagUnsupported.into()), - BlockNumberOrTag::Safe => Err(ProviderError::SafeTagUnsupported.into()), + BlockNumberOrTag::Finalized => { + // we can only get the finalized state by hash, not by num + let hash = match self.finalized_block_hash()? { + Some(hash) => hash, + None => return Err(ProviderError::HeaderNotFound.into()), + }; + + self.state_by_block_hash(hash) + } + BlockNumberOrTag::Safe => { + // we can only get the safe state by hash, not by num + let hash = match self.safe_block_hash()? { + Some(hash) => hash, + None => return Err(ProviderError::HeaderNotFound.into()), + }; + + self.state_by_block_hash(hash) + } BlockNumberOrTag::Earliest => self.history_by_block_number(0), BlockNumberOrTag::Pending => self.pending(), BlockNumberOrTag::Number(num) => self.history_by_block_number(num),