feat(provider): add *StateProviderRef creation methods to DatabaseProvider (#11776)

This commit is contained in:
joshieDo
2024-10-16 17:52:56 +09:00
committed by GitHub
parent 183cea4577
commit a6358d2e6f
2 changed files with 84 additions and 8 deletions

View File

@ -9,12 +9,12 @@ use crate::{
AccountReader, BlockExecutionReader, BlockExecutionWriter, BlockHashReader, BlockNumReader, AccountReader, BlockExecutionReader, BlockExecutionWriter, BlockHashReader, BlockNumReader,
BlockReader, BlockWriter, BundleStateInit, ChainStateBlockReader, ChainStateBlockWriter, BlockReader, BlockWriter, BundleStateInit, ChainStateBlockReader, ChainStateBlockWriter,
DBProvider, EvmEnvProvider, HashingWriter, HeaderProvider, HeaderSyncGap, DBProvider, EvmEnvProvider, HashingWriter, HeaderProvider, HeaderSyncGap,
HeaderSyncGapProvider, HistoricalStateProvider, HistoryWriter, LatestStateProvider, HeaderSyncGapProvider, HistoricalStateProvider, HistoricalStateProviderRef, HistoryWriter,
OriginalValuesKnown, ProviderError, PruneCheckpointReader, PruneCheckpointWriter, LatestStateProvider, LatestStateProviderRef, OriginalValuesKnown, ProviderError,
RequestsProvider, RevertsInit, StageCheckpointReader, StateChangeWriter, StateProviderBox, PruneCheckpointReader, PruneCheckpointWriter, RequestsProvider, RevertsInit,
StateReader, StateWriter, StaticFileProviderFactory, StatsReader, StorageReader, StageCheckpointReader, StateChangeWriter, StateProviderBox, StateReader, StateWriter,
StorageTrieWriter, TransactionVariant, TransactionsProvider, TransactionsProviderExt, StaticFileProviderFactory, StatsReader, StorageReader, StorageTrieWriter, TransactionVariant,
TrieWriter, WithdrawalsProvider, TransactionsProvider, TransactionsProviderExt, TrieWriter, WithdrawalsProvider,
}; };
use alloy_eips::BlockHashOrNumber; use alloy_eips::BlockHashOrNumber;
use alloy_primitives::{keccak256, Address, BlockHash, BlockNumber, TxHash, TxNumber, B256, U256}; use alloy_primitives::{keccak256, Address, BlockHash, BlockNumber, TxHash, TxNumber, B256, U256};
@ -47,7 +47,7 @@ use reth_primitives::{
}; };
use reth_prune_types::{PruneCheckpoint, PruneModes, PruneSegment}; use reth_prune_types::{PruneCheckpoint, PruneModes, PruneSegment};
use reth_stages_types::{StageCheckpoint, StageId}; use reth_stages_types::{StageCheckpoint, StageId};
use reth_storage_api::{StorageChangeSetReader, TryIntoHistoricalStateProvider}; use reth_storage_api::{StateProvider, StorageChangeSetReader, TryIntoHistoricalStateProvider};
use reth_storage_errors::provider::{ProviderResult, RootMismatch}; use reth_storage_errors::provider::{ProviderResult, RootMismatch};
use reth_trie::{ use reth_trie::{
prefix_set::{PrefixSet, PrefixSetMut, TriePrefixSets}, prefix_set::{PrefixSet, PrefixSetMut, TriePrefixSets},
@ -68,7 +68,7 @@ use std::{
time::{Duration, Instant}, time::{Duration, Instant},
}; };
use tokio::sync::watch; use tokio::sync::watch;
use tracing::{debug, error, warn}; use tracing::{debug, error, trace, warn};
/// A [`DatabaseProvider`] that holds a read-only database transaction. /// A [`DatabaseProvider`] that holds a read-only database transaction.
pub type DatabaseProviderRO<DB, Spec> = DatabaseProvider<<DB as Database>::TX, Spec>; pub type DatabaseProviderRO<DB, Spec> = DatabaseProvider<<DB as Database>::TX, Spec>;
@ -145,6 +145,64 @@ impl<TX, Spec> DatabaseProvider<TX, Spec> {
} }
} }
impl<TX: DbTx, Spec: Send + Sync> DatabaseProvider<TX, Spec> {
/// State provider for latest block
pub fn latest<'a>(&'a self) -> ProviderResult<Box<dyn StateProvider + 'a>> {
trace!(target: "providers::db", "Returning latest state provider");
Ok(Box::new(LatestStateProviderRef::new(&self.tx, self.static_file_provider.clone())))
}
/// Storage provider for state at that given block hash
pub fn history_by_block_hash<'a>(
&'a self,
block_hash: BlockHash,
) -> ProviderResult<Box<dyn StateProvider + 'a>> {
let mut block_number =
self.block_number(block_hash)?.ok_or(ProviderError::BlockHashNotFound(block_hash))?;
if block_number == self.best_block_number().unwrap_or_default() &&
block_number == self.last_block_number().unwrap_or_default()
{
return Ok(Box::new(LatestStateProviderRef::new(
&self.tx,
self.static_file_provider.clone(),
)))
}
// +1 as the changeset that we want is the one that was applied after this block.
block_number += 1;
let account_history_prune_checkpoint =
self.get_prune_checkpoint(PruneSegment::AccountHistory)?;
let storage_history_prune_checkpoint =
self.get_prune_checkpoint(PruneSegment::StorageHistory)?;
let mut state_provider = HistoricalStateProviderRef::new(
&self.tx,
block_number,
self.static_file_provider.clone(),
);
// If we pruned account or storage history, we can't return state on every historical block.
// Instead, we should cap it at the latest prune checkpoint for corresponding prune segment.
if let Some(prune_checkpoint_block_number) =
account_history_prune_checkpoint.and_then(|checkpoint| checkpoint.block_number)
{
state_provider = state_provider.with_lowest_available_account_history_block_number(
prune_checkpoint_block_number + 1,
);
}
if let Some(prune_checkpoint_block_number) =
storage_history_prune_checkpoint.and_then(|checkpoint| checkpoint.block_number)
{
state_provider = state_provider.with_lowest_available_storage_history_block_number(
prune_checkpoint_block_number + 1,
);
}
Ok(Box::new(state_provider))
}
}
impl<TX, Spec> StaticFileProviderFactory for DatabaseProvider<TX, Spec> { impl<TX, Spec> StaticFileProviderFactory for DatabaseProvider<TX, Spec> {
/// Returns a static file provider /// Returns a static file provider
fn static_file_provider(&self) -> StaticFileProvider { fn static_file_provider(&self) -> StaticFileProvider {

View File

@ -227,6 +227,24 @@ impl<'b, TX: DbTx> HistoricalStateProviderRef<'b, TX> {
Ok(HistoryInfo::NotYetWritten) Ok(HistoryInfo::NotYetWritten)
} }
} }
/// Set the lowest block number at which the account history is available.
pub const fn with_lowest_available_account_history_block_number(
mut self,
block_number: BlockNumber,
) -> Self {
self.lowest_available_blocks.account_history_block_number = Some(block_number);
self
}
/// Set the lowest block number at which the storage history is available.
pub const fn with_lowest_available_storage_history_block_number(
mut self,
block_number: BlockNumber,
) -> Self {
self.lowest_available_blocks.storage_history_block_number = Some(block_number);
self
}
} }
impl<TX: DbTx> AccountReader for HistoricalStateProviderRef<'_, TX> { impl<TX: DbTx> AccountReader for HistoricalStateProviderRef<'_, TX> {