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,
BlockReader, BlockWriter, BundleStateInit, ChainStateBlockReader, ChainStateBlockWriter,
DBProvider, EvmEnvProvider, HashingWriter, HeaderProvider, HeaderSyncGap,
HeaderSyncGapProvider, HistoricalStateProvider, HistoryWriter, LatestStateProvider,
OriginalValuesKnown, ProviderError, PruneCheckpointReader, PruneCheckpointWriter,
RequestsProvider, RevertsInit, StageCheckpointReader, StateChangeWriter, StateProviderBox,
StateReader, StateWriter, StaticFileProviderFactory, StatsReader, StorageReader,
StorageTrieWriter, TransactionVariant, TransactionsProvider, TransactionsProviderExt,
TrieWriter, WithdrawalsProvider,
HeaderSyncGapProvider, HistoricalStateProvider, HistoricalStateProviderRef, HistoryWriter,
LatestStateProvider, LatestStateProviderRef, OriginalValuesKnown, ProviderError,
PruneCheckpointReader, PruneCheckpointWriter, RequestsProvider, RevertsInit,
StageCheckpointReader, StateChangeWriter, StateProviderBox, StateReader, StateWriter,
StaticFileProviderFactory, StatsReader, StorageReader, StorageTrieWriter, TransactionVariant,
TransactionsProvider, TransactionsProviderExt, TrieWriter, WithdrawalsProvider,
};
use alloy_eips::BlockHashOrNumber;
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_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_trie::{
prefix_set::{PrefixSet, PrefixSetMut, TriePrefixSets},
@ -68,7 +68,7 @@ use std::{
time::{Duration, Instant},
};
use tokio::sync::watch;
use tracing::{debug, error, warn};
use tracing::{debug, error, trace, warn};
/// A [`DatabaseProvider`] that holds a read-only database transaction.
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> {
/// Returns a static file provider
fn static_file_provider(&self) -> StaticFileProvider {

View File

@ -227,6 +227,24 @@ impl<'b, TX: DbTx> HistoricalStateProviderRef<'b, TX> {
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> {