mirror of
https://github.com/hl-archive-node/nanoreth.git
synced 2025-12-06 10:59:55 +00:00
feat(provider): add *StateProviderRef creation methods to DatabaseProvider (#11776)
This commit is contained in:
@ -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 {
|
||||||
|
|||||||
@ -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> {
|
||||||
|
|||||||
Reference in New Issue
Block a user