feat: add safe and finalized tags to StateProviderFactory (#2654)

This commit is contained in:
Dan Cline
2023-05-12 16:00:16 -04:00
committed by GitHub
parent 52b5418a63
commit cc601dbe9f
6 changed files with 51 additions and 20 deletions

View File

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

View File

@@ -137,12 +137,12 @@ where
DB: Database,
Tree: BlockchainTreeViewer + Send + Sync,
{
fn safe_block_num(&self) -> Result<Option<reth_primitives::BlockNumber>> {
Ok(self.chain_info.get_safe_num_hash().map(|num_hash| num_hash.number))
fn safe_block_num_hash(&self) -> Result<Option<reth_primitives::BlockNumHash>> {
Ok(self.chain_info.get_safe_num_hash())
}
fn finalized_block_num(&self) -> Result<Option<reth_primitives::BlockNumber>> {
Ok(self.chain_info.get_finalized_num_hash().map(|num_hash| num_hash.number))
fn finalized_block_num_hash(&self) -> Result<Option<reth_primitives::BlockNumHash>> {
Ok(self.chain_info.get_finalized_num_hash())
}
fn pending_block_num_hash(&self) -> Result<Option<reth_primitives::BlockNumHash>> {

View File

@@ -263,7 +263,7 @@ impl BlockNumProvider for MockEthProvider {
}
impl BlockIdProvider for MockEthProvider {
fn safe_block_num(&self) -> Result<Option<reth_primitives::BlockNumber>> {
fn safe_block_num_hash(&self) -> Result<Option<reth_primitives::BlockNumHash>> {
Ok(None)
}
@@ -271,7 +271,7 @@ impl BlockIdProvider for MockEthProvider {
Ok(None)
}
fn finalized_block_num(&self) -> Result<Option<reth_primitives::BlockNumber>> {
fn finalized_block_num_hash(&self) -> Result<Option<reth_primitives::BlockNumHash>> {
Ok(None)
}
}

View File

@@ -76,11 +76,11 @@ impl BlockIdProvider for NoopProvider {
Ok(None)
}
fn safe_block_num(&self) -> Result<Option<reth_primitives::BlockNumber>> {
fn safe_block_num_hash(&self) -> Result<Option<reth_primitives::BlockNumHash>> {
Ok(None)
}
fn finalized_block_num(&self) -> Result<Option<reth_primitives::BlockNumber>> {
fn finalized_block_num_hash(&self) -> Result<Option<reth_primitives::BlockNumHash>> {
Ok(None)
}
}

View File

@@ -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<Option<reth_primitives::BlockNumHash>>;
/// Get the current safe block number and hash.
fn safe_block_num_hash(&self) -> Result<Option<reth_primitives::BlockNumHash>>;
/// Get the current finalized block number and hash.
fn finalized_block_num_hash(&self) -> Result<Option<reth_primitives::BlockNumHash>>;
/// Get the safe block number.
fn safe_block_num(&self) -> Result<Option<reth_primitives::BlockNumber>>;
fn safe_block_num(&self) -> Result<Option<reth_primitives::BlockNumber>> {
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<Option<reth_primitives::BlockNumber>>;
fn finalized_block_num(&self) -> Result<Option<reth_primitives::BlockNumber>> {
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<Option<H256>> {
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<Option<H256>> {
self.finalized_block_num_hash().map(|res_opt| res_opt.map(|num_hash| num_hash.hash))
}
}

View File

@@ -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<StateProviderBox<'_>>;
@@ -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<StateProviderBox<'_>> {
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),