Introduce HashedPostStateProvider (#12607)

Co-authored-by: Matthias Seitz <matthias.seitz@outlook.de>
This commit is contained in:
frisitano
2024-12-04 00:56:17 +08:00
committed by GitHub
parent e4c7fac9db
commit 886471d693
42 changed files with 318 additions and 137 deletions

View File

@ -4,8 +4,8 @@ use crate::{
AccountReader, BlockHashReader, BlockIdReader, BlockNumReader, BlockReader, BlockReaderIdExt,
BlockSource, CanonChainTracker, CanonStateNotifications, CanonStateSubscriptions,
ChainSpecProvider, ChainStateBlockReader, ChangeSetReader, DatabaseProvider,
DatabaseProviderFactory, EvmEnvProvider, FullProvider, HeaderProvider, ProviderError,
ProviderFactory, PruneCheckpointReader, ReceiptProvider, ReceiptProviderIdExt,
DatabaseProviderFactory, EvmEnvProvider, FullProvider, HashedPostStateProvider, HeaderProvider,
ProviderError, ProviderFactory, PruneCheckpointReader, ReceiptProvider, ReceiptProviderIdExt,
StageCheckpointReader, StateProviderBox, StateProviderFactory, StateReader,
StaticFileProviderFactory, TransactionVariant, TransactionsProvider, WithdrawalsProvider,
};
@ -34,9 +34,16 @@ use reth_primitives::{
use reth_primitives_traits::BlockBody as _;
use reth_prune_types::{PruneCheckpoint, PruneSegment};
use reth_stages_types::{StageCheckpoint, StageId};
use reth_storage_api::{DBProvider, NodePrimitivesProvider, StorageChangeSetReader};
use reth_storage_api::{
DBProvider, NodePrimitivesProvider, StateCommitmentProvider, StorageChangeSetReader,
};
use reth_storage_errors::provider::ProviderResult;
use revm::primitives::{BlockEnv, CfgEnvWithHandlerCfg};
use reth_trie::HashedPostState;
use reth_trie_db::StateCommitment;
use revm::{
db::BundleState,
primitives::{BlockEnv, CfgEnvWithHandlerCfg},
};
use std::{
ops::{Add, RangeBounds, RangeInclusive, Sub},
sync::Arc,
@ -171,6 +178,10 @@ impl<N: ProviderNodeTypes> DatabaseProviderFactory for BlockchainProvider2<N> {
}
}
impl<N: ProviderNodeTypes> StateCommitmentProvider for BlockchainProvider2<N> {
type StateCommitment = N::StateCommitment;
}
impl<N: ProviderNodeTypes> StaticFileProviderFactory for BlockchainProvider2<N> {
fn static_file_provider(&self) -> StaticFileProvider<Self::Primitives> {
self.database.static_file_provider()
@ -663,6 +674,14 @@ impl<N: ProviderNodeTypes> StateProviderFactory for BlockchainProvider2<N> {
}
}
impl<N: NodeTypesWithDB> HashedPostStateProvider for BlockchainProvider2<N> {
fn hashed_post_state(&self, bundle_state: &BundleState) -> HashedPostState {
HashedPostState::from_bundle_state::<<N::StateCommitment as StateCommitment>::KeyHasher>(
bundle_state.state(),
)
}
}
impl<N: ProviderNodeTypes> CanonChainTracker for BlockchainProvider2<N> {
type Header = HeaderTy<N>;

View File

@ -6,7 +6,7 @@ use alloy_primitives::{
Address, BlockNumber, Bytes, B256,
};
use reth_primitives::{Account, Bytecode};
use reth_storage_api::{StateProofProvider, StorageRootProvider};
use reth_storage_api::{HashedPostStateProvider, StateProofProvider, StorageRootProvider};
use reth_storage_errors::provider::ProviderResult;
use reth_trie::{
updates::TrieUpdates, AccountProof, HashedPostState, HashedStorage, MultiProof,
@ -87,7 +87,7 @@ impl<SP: StateProvider, EDP: ExecutionDataProvider> StateRootProvider
{
fn state_root(&self, hashed_state: HashedPostState) -> ProviderResult<B256> {
let bundle_state = self.block_execution_data_provider.execution_outcome().state();
let mut state = HashedPostState::from_bundle_state(&bundle_state.state);
let mut state = self.hashed_post_state(bundle_state);
state.extend(hashed_state);
self.state_provider.state_root(state)
}
@ -101,7 +101,7 @@ impl<SP: StateProvider, EDP: ExecutionDataProvider> StateRootProvider
hashed_state: HashedPostState,
) -> ProviderResult<(B256, TrieUpdates)> {
let bundle_state = self.block_execution_data_provider.execution_outcome().state();
let mut state = HashedPostState::from_bundle_state(&bundle_state.state);
let mut state = self.hashed_post_state(bundle_state);
state.extend(hashed_state);
self.state_provider.state_root_with_updates(state)
}
@ -111,7 +111,7 @@ impl<SP: StateProvider, EDP: ExecutionDataProvider> StateRootProvider
mut input: TrieInput,
) -> ProviderResult<(B256, TrieUpdates)> {
let bundle_state = self.block_execution_data_provider.execution_outcome().state();
input.prepend(HashedPostState::from_bundle_state(&bundle_state.state));
input.prepend(self.hashed_post_state(bundle_state));
self.state_provider.state_root_from_nodes_with_updates(input)
}
}
@ -162,7 +162,7 @@ impl<SP: StateProvider, EDP: ExecutionDataProvider> StateProofProvider
slots: &[B256],
) -> ProviderResult<AccountProof> {
let bundle_state = self.block_execution_data_provider.execution_outcome().state();
input.prepend(HashedPostState::from_bundle_state(&bundle_state.state));
input.prepend(self.hashed_post_state(bundle_state));
self.state_provider.proof(input, address, slots)
}
@ -172,7 +172,7 @@ impl<SP: StateProvider, EDP: ExecutionDataProvider> StateProofProvider
targets: HashMap<B256, HashSet<B256>>,
) -> ProviderResult<MultiProof> {
let bundle_state = self.block_execution_data_provider.execution_outcome().state();
input.prepend(HashedPostState::from_bundle_state(&bundle_state.state));
input.prepend(self.hashed_post_state(bundle_state));
self.state_provider.multiproof(input, targets)
}
@ -182,11 +182,19 @@ impl<SP: StateProvider, EDP: ExecutionDataProvider> StateProofProvider
target: HashedPostState,
) -> ProviderResult<HashMap<B256, Bytes>> {
let bundle_state = self.block_execution_data_provider.execution_outcome().state();
input.prepend(HashedPostState::from_bundle_state(&bundle_state.state));
input.prepend(self.hashed_post_state(bundle_state));
self.state_provider.witness(input, target)
}
}
impl<SP: StateProvider, EDP: ExecutionDataProvider> HashedPostStateProvider
for BundleStateProvider<SP, EDP>
{
fn hashed_post_state(&self, bundle_state: &revm::db::BundleState) -> HashedPostState {
self.state_provider.hashed_post_state(bundle_state)
}
}
impl<SP: StateProvider, EDP: ExecutionDataProvider> StateProvider for BundleStateProvider<SP, EDP> {
fn storage(
&self,

View File

@ -2,11 +2,11 @@ use crate::{BlockNumReader, DatabaseProviderFactory, HeaderProvider};
use alloy_primitives::B256;
use reth_errors::ProviderError;
use reth_primitives::GotExpected;
use reth_storage_api::{BlockReader, DBProvider};
use reth_storage_api::{BlockReader, DBProvider, StateCommitmentProvider};
use reth_storage_errors::provider::ProviderResult;
use reth_trie::HashedPostState;
use reth_trie_db::DatabaseHashedPostState;
use reth_trie_db::{DatabaseHashedPostState, StateCommitment};
pub use reth_storage_errors::provider::ConsistentViewError;
@ -33,7 +33,7 @@ pub struct ConsistentDbView<Factory> {
impl<Factory> ConsistentDbView<Factory>
where
Factory: DatabaseProviderFactory<Provider: BlockReader>,
Factory: DatabaseProviderFactory<Provider: BlockReader> + StateCommitmentProvider,
{
/// Creates new consistent database view.
pub const fn new(factory: Factory, tip: Option<B256>) -> Self {
@ -59,7 +59,9 @@ where
{
Ok(HashedPostState::default())
} else {
Ok(HashedPostState::from_reverts(provider.tx_ref(), block_number + 1)?)
Ok(HashedPostState::from_reverts::<
<Factory::StateCommitment as StateCommitment>::KeyHasher,
>(provider.tx_ref(), block_number + 1)?)
}
}

View File

@ -3,9 +3,9 @@ use crate::{
to_range,
traits::{BlockSource, ReceiptProvider},
BlockHashReader, BlockNumReader, BlockReader, ChainSpecProvider, DatabaseProviderFactory,
EvmEnvProvider, HeaderProvider, HeaderSyncGap, HeaderSyncGapProvider, ProviderError,
PruneCheckpointReader, StageCheckpointReader, StateProviderBox, StaticFileProviderFactory,
TransactionVariant, TransactionsProvider, WithdrawalsProvider,
EvmEnvProvider, HashedPostStateProvider, HeaderProvider, HeaderSyncGap, HeaderSyncGapProvider,
ProviderError, PruneCheckpointReader, StageCheckpointReader, StateProviderBox,
StaticFileProviderFactory, TransactionVariant, TransactionsProvider, WithdrawalsProvider,
};
use alloy_eips::{
eip4895::{Withdrawal, Withdrawals},
@ -25,9 +25,16 @@ use reth_primitives::{
};
use reth_prune_types::{PruneCheckpoint, PruneModes, PruneSegment};
use reth_stages_types::{StageCheckpoint, StageId};
use reth_storage_api::{NodePrimitivesProvider, TryIntoHistoricalStateProvider};
use reth_storage_api::{
NodePrimitivesProvider, StateCommitmentProvider, TryIntoHistoricalStateProvider,
};
use reth_storage_errors::provider::ProviderResult;
use revm::primitives::{BlockEnv, CfgEnvWithHandlerCfg};
use reth_trie::HashedPostState;
use reth_trie_db::StateCommitment;
use revm::{
db::BundleState,
primitives::{BlockEnv, CfgEnvWithHandlerCfg},
};
use std::{
ops::{RangeBounds, RangeInclusive},
path::Path,
@ -219,6 +226,10 @@ impl<N: ProviderNodeTypes> DatabaseProviderFactory for ProviderFactory<N> {
}
}
impl<N: NodeTypesWithDB> StateCommitmentProvider for ProviderFactory<N> {
type StateCommitment = N::StateCommitment;
}
impl<N: NodeTypesWithDB> StaticFileProviderFactory for ProviderFactory<N> {
/// Returns static file provider
fn static_file_provider(&self) -> StaticFileProvider<Self::Primitives> {
@ -651,6 +662,14 @@ impl<N: ProviderNodeTypes> PruneCheckpointReader for ProviderFactory<N> {
}
}
impl<N: ProviderNodeTypes> HashedPostStateProvider for ProviderFactory<N> {
fn hashed_post_state(&self, bundle_state: &BundleState) -> HashedPostState {
HashedPostState::from_bundle_state::<<N::StateCommitment as StateCommitment>::KeyHasher>(
bundle_state.state(),
)
}
}
impl<N: NodeTypesWithDB> Clone for ProviderFactory<N> {
fn clone(&self) -> Self {
Self {

View File

@ -1,6 +1,6 @@
use crate::{
providers::state::macros::delegate_provider_impls, AccountReader, BlockHashReader,
ProviderError, StateProvider, StateRootProvider,
HashedPostStateProvider, ProviderError, StateProvider, StateRootProvider,
};
use alloy_eips::merge::EPOCH_SLOTS;
use alloy_primitives::{
@ -28,7 +28,7 @@ use reth_trie::{
};
use reth_trie_db::{
DatabaseHashedPostState, DatabaseHashedStorage, DatabaseProof, DatabaseStateRoot,
DatabaseStorageProof, DatabaseStorageRoot, DatabaseTrieWitness,
DatabaseStorageProof, DatabaseStorageRoot, DatabaseTrieWitness, StateCommitment,
};
use std::fmt::Debug;
@ -136,7 +136,9 @@ impl<'b, Provider: DBProvider + BlockNumReader + StateCommitmentProvider>
);
}
Ok(HashedPostState::from_reverts(self.tx(), self.block_number)?)
Ok(HashedPostState::from_reverts::<
<Provider::StateCommitment as StateCommitment>::KeyHasher,
>(self.tx(), self.block_number)?)
}
/// Retrieve revert hashed storage for this history provider and target address.
@ -394,6 +396,16 @@ impl<Provider: DBProvider + BlockNumReader + StateCommitmentProvider> StateProof
}
}
impl<Provider: StateCommitmentProvider> HashedPostStateProvider
for HistoricalStateProviderRef<'_, Provider>
{
fn hashed_post_state(&self, bundle_state: &revm::db::BundleState) -> HashedPostState {
HashedPostState::from_bundle_state::<
<Provider::StateCommitment as StateCommitment>::KeyHasher,
>(bundle_state.state())
}
}
impl<Provider: DBProvider + BlockNumReader + BlockHashReader + StateCommitmentProvider>
StateProvider for HistoricalStateProviderRef<'_, Provider>
{
@ -433,6 +445,12 @@ impl<Provider: DBProvider + BlockNumReader + BlockHashReader + StateCommitmentPr
}
}
impl<Provider: StateCommitmentProvider> StateCommitmentProvider
for HistoricalStateProviderRef<'_, Provider>
{
type StateCommitment = Provider::StateCommitment;
}
/// State provider for a given block number.
/// For more detailed description, see [`HistoricalStateProviderRef`].
#[derive(Debug)]
@ -482,6 +500,12 @@ impl<Provider: DBProvider + BlockNumReader + StateCommitmentProvider>
}
}
impl<Provider: StateCommitmentProvider> StateCommitmentProvider
for HistoricalStateProvider<Provider>
{
type StateCommitment = Provider::StateCommitment;
}
// Delegates all provider impls to [HistoricalStateProviderRef]
delegate_provider_impls!(HistoricalStateProvider<Provider> where [Provider: DBProvider + BlockNumReader + BlockHashReader + StateCommitmentProvider]);

View File

@ -1,6 +1,6 @@
use crate::{
providers::state::macros::delegate_provider_impls, AccountReader, BlockHashReader,
StateProvider, StateRootProvider,
HashedPostStateProvider, StateProvider, StateRootProvider,
};
use alloy_primitives::{
map::{HashMap, HashSet},
@ -22,7 +22,7 @@ use reth_trie::{
};
use reth_trie_db::{
DatabaseProof, DatabaseStateRoot, DatabaseStorageProof, DatabaseStorageRoot,
DatabaseTrieWitness,
DatabaseTrieWitness, StateCommitment,
};
/// State provider over latest state that takes tx reference.
@ -157,6 +157,16 @@ impl<Provider: DBProvider + StateCommitmentProvider> StateProofProvider
}
}
impl<Provider: DBProvider + StateCommitmentProvider> HashedPostStateProvider
for LatestStateProviderRef<'_, Provider>
{
fn hashed_post_state(&self, bundle_state: &revm::db::BundleState) -> HashedPostState {
HashedPostState::from_bundle_state::<
<Provider::StateCommitment as StateCommitment>::KeyHasher,
>(bundle_state.state())
}
}
impl<Provider: DBProvider + BlockHashReader + StateCommitmentProvider> StateProvider
for LatestStateProviderRef<'_, Provider>
{
@ -181,11 +191,17 @@ impl<Provider: DBProvider + BlockHashReader + StateCommitmentProvider> StateProv
}
}
impl<Provider: StateCommitmentProvider> StateCommitmentProvider
for LatestStateProviderRef<'_, Provider>
{
type StateCommitment = Provider::StateCommitment;
}
/// State provider for the latest state.
#[derive(Debug)]
pub struct LatestStateProvider<Provider>(Provider);
impl<Provider: DBProvider> LatestStateProvider<Provider> {
impl<Provider: DBProvider + StateCommitmentProvider> LatestStateProvider<Provider> {
/// Create new state provider
pub const fn new(db: Provider) -> Self {
Self(db)
@ -198,6 +214,10 @@ impl<Provider: DBProvider> LatestStateProvider<Provider> {
}
}
impl<Provider: StateCommitmentProvider> StateCommitmentProvider for LatestStateProvider<Provider> {
type StateCommitment = Provider::StateCommitment;
}
// Delegates all provider impls to [LatestStateProviderRef]
delegate_provider_impls!(LatestStateProvider<Provider> where [Provider: DBProvider + BlockHashReader + StateCommitmentProvider]);

View File

@ -57,6 +57,9 @@ macro_rules! delegate_provider_impls {
fn multiproof(&self, input: reth_trie::TrieInput, targets: alloy_primitives::map::HashMap<alloy_primitives::B256, alloy_primitives::map::HashSet<alloy_primitives::B256>>) -> reth_storage_errors::provider::ProviderResult<reth_trie::MultiProof>;
fn witness(&self, input: reth_trie::TrieInput, target: reth_trie::HashedPostState) -> reth_storage_errors::provider::ProviderResult<alloy_primitives::map::HashMap<alloy_primitives::B256, alloy_primitives::Bytes>>;
}
HashedPostStateProvider $(where [$($generics)*])? {
fn hashed_post_state(&self, bundle_state: &revm::db::BundleState) -> reth_trie::HashedPostState;
}
);
}
}

View File

@ -29,7 +29,8 @@ use reth_primitives::{
use reth_primitives_traits::SignedTransaction;
use reth_stages_types::{StageCheckpoint, StageId};
use reth_storage_api::{
DatabaseProviderFactory, StageCheckpointReader, StateProofProvider, StorageRootProvider,
DatabaseProviderFactory, HashedPostStateProvider, StageCheckpointReader,
StateCommitmentProvider, StateProofProvider, StorageRootProvider,
};
use reth_storage_errors::provider::{ConsistentViewError, ProviderError, ProviderResult};
use reth_trie::{
@ -164,6 +165,10 @@ impl NodeTypes for MockNode {
type Storage = EthStorage;
}
impl StateCommitmentProvider for MockEthProvider {
type StateCommitment = <MockNode as NodeTypes>::StateCommitment;
}
impl DatabaseProviderFactory for MockEthProvider {
type DB = DatabaseMock;
type Provider = DatabaseProvider<TxMock, MockNode>;
@ -682,6 +687,12 @@ impl StateProofProvider for MockEthProvider {
}
}
impl HashedPostStateProvider for MockEthProvider {
fn hashed_post_state(&self, _state: &revm::db::BundleState) -> HashedPostState {
HashedPostState::default()
}
}
impl StateProvider for MockEthProvider {
fn storage(
&self,

View File

@ -27,7 +27,9 @@ use reth_primitives::{
};
use reth_prune_types::{PruneCheckpoint, PruneSegment};
use reth_stages_types::{StageCheckpoint, StageId};
use reth_storage_api::{NodePrimitivesProvider, StateProofProvider, StorageRootProvider};
use reth_storage_api::{
HashedPostStateProvider, NodePrimitivesProvider, StateProofProvider, StorageRootProvider,
};
use reth_storage_errors::provider::ProviderResult;
use reth_trie::{
updates::TrieUpdates, AccountProof, HashedPostState, HashedStorage, MultiProof, TrieInput,
@ -413,6 +415,12 @@ impl StateProofProvider for NoopProvider {
}
}
impl HashedPostStateProvider for NoopProvider {
fn hashed_post_state(&self, _bundle_state: &revm::db::BundleState) -> HashedPostState {
HashedPostState::default()
}
}
impl StateProvider for NoopProvider {
fn storage(
&self,

View File

@ -234,7 +234,7 @@ mod tests {
};
use reth_execution_types::ExecutionOutcome;
use reth_primitives::{Account, Receipt, Receipts, StorageEntry};
use reth_storage_api::DatabaseProviderFactory;
use reth_storage_api::{DatabaseProviderFactory, HashedPostStateProvider};
use reth_trie::{
test_utils::{state_root, storage_root_prehashed},
HashedPostState, HashedStorage, StateRoot, StorageRoot,
@ -1118,13 +1118,7 @@ mod tests {
assert_eq!(
StateRoot::overlay_root(
tx,
ExecutionOutcome::<Receipt>::new(
state.bundle_state.clone(),
Receipts::default(),
0,
Vec::new()
)
.hash_state_slow(),
provider_factory.hashed_post_state(&state.bundle_state)
)
.unwrap(),
state_root(expected.clone().into_iter().map(|(address, (account, storage))| (

View File

@ -25,6 +25,7 @@ reth-storage-errors.workspace = true
reth-trie.workspace = true
reth-trie-db.workspace = true
reth-db.workspace = true
revm.workspace = true
# ethereum
alloy-eips.workspace = true

View File

@ -2,9 +2,9 @@
use crate::{
AccountReader, BlockHashReader, BlockIdReader, BlockNumReader, BlockReader, BlockReaderIdExt,
BlockSource, ChangeSetReader, HeaderProvider, NodePrimitivesProvider, PruneCheckpointReader,
ReceiptProvider, ReceiptProviderIdExt, StageCheckpointReader, StateProofProvider,
StateProvider, StateRootProvider, StorageRootProvider, TransactionVariant,
BlockSource, ChangeSetReader, HashedPostStateProvider, HeaderProvider, NodePrimitivesProvider,
PruneCheckpointReader, ReceiptProvider, ReceiptProviderIdExt, StageCheckpointReader,
StateProofProvider, StateProvider, StateRootProvider, StorageRootProvider, TransactionVariant,
TransactionsProvider, WithdrawalsProvider,
};
use alloy_eips::{
@ -456,6 +456,12 @@ impl<C: Send + Sync, N: NodePrimitives> StateProofProvider for NoopProvider<C, N
}
}
impl<C: Send + Sync, N: NodePrimitives> HashedPostStateProvider for NoopProvider<C, N> {
fn hashed_post_state(&self, _bundle_state: &revm::db::BundleState) -> HashedPostState {
HashedPostState::default()
}
}
impl<C: Send + Sync, N: NodePrimitives> StateProvider for NoopProvider<C, N> {
fn storage(
&self,

View File

@ -8,7 +8,9 @@ use alloy_primitives::{Address, BlockHash, BlockNumber, StorageKey, StorageValue
use auto_impl::auto_impl;
use reth_primitives::Bytecode;
use reth_storage_errors::provider::ProviderResult;
use reth_trie::HashedPostState;
use reth_trie_db::StateCommitment;
use revm::db::states::BundleState;
/// Type alias of boxed [`StateProvider`].
pub type StateProviderBox = Box<dyn StateProvider>;
@ -21,6 +23,7 @@ pub trait StateProvider:
+ StateRootProvider
+ StorageRootProvider
+ StateProofProvider
+ HashedPostStateProvider
+ Send
+ Sync
{
@ -83,11 +86,18 @@ pub trait StateProvider:
}
/// Trait implemented for database providers that can provide the [`StateCommitment`] type.
pub trait StateCommitmentProvider {
pub trait StateCommitmentProvider: Send + Sync {
/// The [`StateCommitment`] type that can be used to perform state commitment operations.
type StateCommitment: StateCommitment;
}
/// Trait that provides the hashed state from various sources.
#[auto_impl(&, Arc, Box)]
pub trait HashedPostStateProvider: Send + Sync {
/// Returns the `HashedPostState` of the provided [`BundleState`].
fn hashed_post_state(&self, bundle_state: &BundleState) -> HashedPostState;
}
/// Trait implemented for database providers that can be converted into a historical state provider.
pub trait TryIntoHistoricalStateProvider {
/// Returns a historical [`StateProvider`] indexed by the given historic block number.