feat(storage): implement BundleStateDataProvider for BundleStateWithReceipts (#8282)

This commit is contained in:
Alexey Shekhirin
2024-05-15 17:19:41 +03:00
committed by GitHub
parent 530dbdbb54
commit aefcfff25f
10 changed files with 71 additions and 34 deletions

View File

@ -1,7 +1,7 @@
//! [BundleStateDataProvider] implementations used by the tree.
use reth_primitives::{BlockHash, BlockNumber, ForkBlock};
use reth_provider::{BundleStateDataProvider, BundleStateWithReceipts};
use reth_provider::{BundleStateDataProvider, BundleStateForkProvider, BundleStateWithReceipts};
use std::collections::BTreeMap;
/// Structure that combines references of required data to be a [`BundleStateDataProvider`].
@ -30,7 +30,9 @@ impl<'a> BundleStateDataProvider for BundleStateDataRef<'a> {
self.canonical_block_hashes.get(&block_number).cloned()
}
}
impl<'a> BundleStateForkProvider for BundleStateDataRef<'a> {
fn canonical_fork(&self) -> ForkBlock {
self.canonical_fork
}
@ -57,7 +59,9 @@ impl BundleStateDataProvider for BundleStateData {
fn block_hash(&self, block_number: BlockNumber) -> Option<BlockHash> {
self.parent_block_hashes.get(&block_number).cloned()
}
}
impl BundleStateForkProvider for BundleStateData {
fn canonical_fork(&self) -> ForkBlock {
self.canonical_fork
}

View File

@ -21,7 +21,7 @@ use reth_primitives::{
};
use reth_provider::{
providers::{BundleStateProvider, ConsistentDbView},
BundleStateDataProvider, BundleStateWithReceipts, Chain, ProviderError, StateRootProvider,
BundleStateWithReceipts, Chain, FullBundleStateDataProvider, ProviderError, StateRootProvider,
};
use reth_revm::database::StateProviderDatabase;
use reth_trie::updates::TrieUpdates;
@ -178,7 +178,7 @@ impl AppendableChain {
block_validation_kind: BlockValidationKind,
) -> RethResult<(BundleStateWithReceipts, Option<TrieUpdates>)>
where
BSDP: BundleStateDataProvider,
BSDP: FullBundleStateDataProvider,
DB: Database + Clone,
E: BlockExecutorProvider,
{

View File

@ -12,8 +12,8 @@ use reth_primitives::{
SealedHeader,
};
use reth_provider::{
BlockchainTreePendingStateProvider, BundleStateDataProvider, CanonStateNotificationSender,
CanonStateNotifications, CanonStateSubscriptions,
BlockchainTreePendingStateProvider, CanonStateNotificationSender, CanonStateNotifications,
CanonStateSubscriptions, FullBundleStateDataProvider,
};
use std::collections::{BTreeMap, HashSet};
@ -138,7 +138,7 @@ impl BlockchainTreePendingStateProvider for NoopBlockchainTree {
fn find_pending_state_provider(
&self,
_block_hash: BlockHash,
) -> Option<Box<dyn BundleStateDataProvider>> {
) -> Option<Box<dyn FullBundleStateDataProvider>> {
None
}
}

View File

@ -17,7 +17,7 @@ use reth_primitives::{
SealedHeader,
};
use reth_provider::{
BlockchainTreePendingStateProvider, BundleStateDataProvider, CanonStateSubscriptions,
BlockchainTreePendingStateProvider, CanonStateSubscriptions, FullBundleStateDataProvider,
ProviderError,
};
use std::{
@ -199,7 +199,7 @@ where
fn find_pending_state_provider(
&self,
block_hash: BlockHash,
) -> Option<Box<dyn BundleStateDataProvider>> {
) -> Option<Box<dyn FullBundleStateDataProvider>> {
trace!(target: "blockchain_tree", ?block_hash, "Finding pending state provider");
let provider = self.tree.read().post_state_data(block_hash)?;
Some(Box::new(provider))

View File

@ -1,4 +1,7 @@
use crate::{providers::StaticFileProviderRWRefMut, StateChanges, StateReverts, StateWriter};
use crate::{
providers::StaticFileProviderRWRefMut, BundleStateDataProvider, StateChanges, StateReverts,
StateWriter,
};
use reth_db::{
cursor::{DbCursorRO, DbCursorRW},
tables,
@ -9,8 +12,8 @@ use reth_interfaces::provider::{ProviderError, ProviderResult};
use reth_primitives::{
logs_bloom,
revm::compat::{into_reth_acc, into_revm_acc},
Account, Address, BlockNumber, Bloom, Bytecode, Log, Receipt, Receipts, StaticFileSegment,
StorageEntry, B256, U256,
Account, Address, BlockHash, BlockNumber, Bloom, Bytecode, Log, Receipt, Receipts,
StaticFileSegment, StorageEntry, B256, U256,
};
use reth_trie::HashedPostState;
pub use revm::db::states::OriginalValuesKnown;
@ -365,6 +368,17 @@ impl StateWriter for BundleStateWithReceipts {
}
}
impl BundleStateDataProvider for BundleStateWithReceipts {
fn state(&self) -> &BundleStateWithReceipts {
self
}
/// Always returns [None] because we don't have any information about the block header.
fn block_hash(&self, _block_number: BlockNumber) -> Option<BlockHash> {
None
}
}
#[cfg(test)]
mod tests {
use super::*;

View File

@ -1,11 +1,11 @@
use crate::{
AccountReader, BlockHashReader, BlockIdReader, BlockNumReader, BlockReader, BlockReaderIdExt,
BlockSource, BlockchainTreePendingStateProvider, BundleStateDataProvider, CanonChainTracker,
CanonStateNotifications, CanonStateSubscriptions, ChainSpecProvider, ChangeSetReader,
DatabaseProviderFactory, EvmEnvProvider, HeaderProvider, ProviderError, PruneCheckpointReader,
ReceiptProvider, ReceiptProviderIdExt, StageCheckpointReader, StateProviderBox,
StateProviderFactory, StaticFileProviderFactory, TransactionVariant, TransactionsProvider,
TreeViewer, WithdrawalsProvider,
BlockSource, BlockchainTreePendingStateProvider, CanonChainTracker, CanonStateNotifications,
CanonStateSubscriptions, ChainSpecProvider, ChangeSetReader, DatabaseProviderFactory,
EvmEnvProvider, FullBundleStateDataProvider, HeaderProvider, ProviderError,
PruneCheckpointReader, ReceiptProvider, ReceiptProviderIdExt, StageCheckpointReader,
StateProviderBox, StateProviderFactory, StaticFileProviderFactory, TransactionVariant,
TransactionsProvider, TreeViewer, WithdrawalsProvider,
};
use reth_db::{
database::Database,
@ -638,7 +638,7 @@ where
fn pending_with_provider(
&self,
bundle_state_data: Box<dyn BundleStateDataProvider>,
bundle_state_data: Box<dyn FullBundleStateDataProvider>,
) -> ProviderResult<StateProviderBox> {
let canonical_fork = bundle_state_data.canonical_fork();
trace!(target: "providers::blockchain", ?canonical_fork, "Returning post state provider");
@ -871,7 +871,7 @@ where
fn find_pending_state_provider(
&self,
block_hash: BlockHash,
) -> Option<Box<dyn BundleStateDataProvider>> {
) -> Option<Box<dyn FullBundleStateDataProvider>> {
self.tree.find_pending_state_provider(block_hash)
}
}

View File

@ -1,9 +1,9 @@
use crate::{
traits::{BlockSource, ReceiptProvider},
AccountReader, BlockHashReader, BlockIdReader, BlockNumReader, BlockReader, BlockReaderIdExt,
BundleStateDataProvider, ChainSpecProvider, ChangeSetReader, EvmEnvProvider, HeaderProvider,
ReceiptProviderIdExt, StateProvider, StateProviderBox, StateProviderFactory, StateRootProvider,
TransactionVariant, TransactionsProvider, WithdrawalsProvider,
ChainSpecProvider, ChangeSetReader, EvmEnvProvider, FullBundleStateDataProvider,
HeaderProvider, ReceiptProviderIdExt, StateProvider, StateProviderBox, StateProviderFactory,
StateRootProvider, TransactionVariant, TransactionsProvider, WithdrawalsProvider,
};
use parking_lot::Mutex;
use reth_db::models::{AccountBeforeTx, StoredBlockBodyIndices};
@ -660,7 +660,7 @@ impl StateProviderFactory for MockEthProvider {
fn pending_with_provider<'a>(
&'a self,
_bundle_state_data: Box<dyn BundleStateDataProvider + 'a>,
_bundle_state_data: Box<dyn FullBundleStateDataProvider + 'a>,
) -> ProviderResult<StateProviderBox> {
Ok(Box::new(self.clone()))
}

View File

@ -419,7 +419,7 @@ impl StateProviderFactory for NoopProvider {
fn pending_with_provider<'a>(
&'a self,
_bundle_state_data: Box<dyn crate::BundleStateDataProvider + 'a>,
_bundle_state_data: Box<dyn crate::FullBundleStateDataProvider + 'a>,
) -> ProviderResult<StateProviderBox> {
Ok(Box::new(*self))
}

View File

@ -35,8 +35,9 @@ pub use receipts::{ReceiptProvider, ReceiptProviderIdExt};
mod state;
pub use state::{
BlockchainTreePendingStateProvider, BundleStateDataProvider, StateProvider, StateProviderBox,
StateProviderFactory, StateWriter,
BlockchainTreePendingStateProvider, BundleStateDataProvider, BundleStateForkProvider,
FullBundleStateDataProvider, StateProvider, StateProviderBox, StateProviderFactory,
StateWriter,
};
mod trie;

View File

@ -187,7 +187,7 @@ pub trait StateProviderFactory: BlockIdReader + Send + Sync {
/// Used to inspect or execute transaction on the pending state.
fn pending_with_provider(
&self,
bundle_state_data: Box<dyn BundleStateDataProvider>,
bundle_state_data: Box<dyn FullBundleStateDataProvider>,
) -> ProviderResult<StateProviderBox>;
}
@ -201,7 +201,7 @@ pub trait BlockchainTreePendingStateProvider: Send + Sync {
fn pending_state_provider(
&self,
block_hash: BlockHash,
) -> ProviderResult<Box<dyn BundleStateDataProvider>> {
) -> ProviderResult<Box<dyn FullBundleStateDataProvider>> {
self.find_pending_state_provider(block_hash)
.ok_or(ProviderError::StateForHashNotFound(block_hash))
}
@ -210,28 +210,46 @@ pub trait BlockchainTreePendingStateProvider: Send + Sync {
fn find_pending_state_provider(
&self,
block_hash: BlockHash,
) -> Option<Box<dyn BundleStateDataProvider>>;
) -> Option<Box<dyn FullBundleStateDataProvider>>;
}
/// Post state data needs for execution on it.
/// This trait is used to create a state provider over pending state.
/// Post state data needed for execution on it.
///
/// Pending state contains:
/// State contains:
/// * [`BundleStateWithReceipts`] contains all changed of accounts and storage of pending chain
/// * block hashes of pending chain and canonical blocks.
/// * canonical fork, the block on what pending chain was forked from.
#[auto_impl(&, Box)]
pub trait BundleStateDataProvider: Send + Sync {
/// Return post state
fn state(&self) -> &BundleStateWithReceipts;
/// Return block hash by block number of pending or canonical chain.
fn block_hash(&self, block_number: BlockNumber) -> Option<BlockHash>;
/// return canonical fork, the block on what post state was forked from.
}
/// Fork data needed for execution on it.
///
/// It contains a canonical fork, the block on what pending chain was forked from.
#[auto_impl(&, Box)]
pub trait BundleStateForkProvider {
/// Return canonical fork, the block on what post state was forked from.
///
/// Needed to create state provider.
fn canonical_fork(&self) -> BlockNumHash;
}
/// Full post state data needed for execution on it.
/// This trait is used to create a state provider over pending state.
///
/// This trait is a combination of [`BundleStateDataProvider`] and [`BundleStateForkProvider`].
///
/// Pending state contains:
/// * [`BundleStateWithReceipts`] contains all changed of accounts and storage of pending chain
/// * block hashes of pending chain and canonical blocks.
/// * canonical fork, the block on what pending chain was forked from.
pub trait FullBundleStateDataProvider: BundleStateDataProvider + BundleStateForkProvider {}
impl<T> FullBundleStateDataProvider for T where T: BundleStateDataProvider + BundleStateForkProvider {}
/// A helper trait for [BundleStateWithReceipts] to write state and receipts to storage.
pub trait StateWriter {
/// Write the data and receipts to the database or static files if `static_file_producer` is