perf: Reduce unnecessary MDBX transaction creation when constructing StateProvider (#16884)

This commit is contained in:
nekomoto911
2025-06-19 22:14:07 +08:00
committed by GitHub
parent 0288a2d14d
commit 54cd8b34a4
2 changed files with 25 additions and 11 deletions

View File

@@ -526,20 +526,12 @@ impl<N: ProviderNodeTypes> StateProviderFactory for BlockchainProvider<N> {
let hash = provider
.block_hash(block_number)?
.ok_or_else(|| ProviderError::HeaderNotFound(block_number.into()))?;
self.history_by_block_hash(hash)
provider.into_state_provider_at_block_hash(hash)
}
fn history_by_block_hash(&self, block_hash: BlockHash) -> ProviderResult<StateProviderBox> {
trace!(target: "providers::blockchain", ?block_hash, "Getting history by block hash");
self.consistent_provider()?.get_in_memory_or_storage_by_block(
block_hash.into(),
|_| self.database.history_by_block_hash(block_hash),
|block_state| {
let state_provider = self.block_state_provider(block_state)?;
Ok(Box::new(state_provider))
},
)
self.consistent_provider()?.into_state_provider_at_block_hash(block_hash)
}
fn state_by_block_hash(&self, hash: BlockHash) -> ProviderResult<StateProviderBox> {

View File

@@ -27,7 +27,7 @@ use reth_prune_types::{PruneCheckpoint, PruneSegment};
use reth_stages_types::{StageCheckpoint, StageId};
use reth_storage_api::{
BlockBodyIndicesProvider, DatabaseProviderFactory, NodePrimitivesProvider, StateProvider,
StorageChangeSetReader,
StorageChangeSetReader, TryIntoHistoricalStateProvider,
};
use reth_storage_errors::provider::ProviderResult;
use revm_database::states::PlainStorageRevert;
@@ -591,6 +591,28 @@ impl<N: ProviderNodeTypes> ConsistentProvider<N> {
}
fetch_from_db(&self.storage_provider)
}
/// Consumes the provider and returns a state provider for the specific block hash.
pub(crate) fn into_state_provider_at_block_hash(
self,
block_hash: BlockHash,
) -> ProviderResult<Box<dyn StateProvider>> {
let Self { storage_provider, head_block, .. } = self;
let into_history_at_block_hash = |block_hash| -> ProviderResult<Box<dyn StateProvider>> {
let block_number = storage_provider
.block_number(block_hash)?
.ok_or(ProviderError::BlockHashNotFound(block_hash))?;
storage_provider.try_into_history_at_block(block_number)
};
if let Some(Some(block_state)) =
head_block.as_ref().map(|b| b.block_on_chain(block_hash.into()))
{
let anchor_hash = block_state.anchor().hash;
let latest_historical = into_history_at_block_hash(anchor_hash)?;
return Ok(Box::new(block_state.state_provider(latest_historical)));
}
into_history_at_block_hash(block_hash)
}
}
impl<N: ProviderNodeTypes> ConsistentProvider<N> {