feat: get rid of lifetime GATs (#5478)

This commit is contained in:
Matthias Seitz
2023-11-19 16:21:50 +01:00
committed by GitHub
parent 631eb2b624
commit aea11405ad
57 changed files with 297 additions and 398 deletions

View File

@ -50,7 +50,7 @@ impl<DB: Database> ProviderFactory<DB> {
/// Returns a provider with a created `DbTx` inside, which allows fetching data from the
/// database using different types of providers. Example: [`HeaderProvider`]
/// [`BlockHashReader`]. This may fail if the inner read database transaction fails to open.
pub fn provider(&self) -> ProviderResult<DatabaseProviderRO<'_, DB>> {
pub fn provider(&self) -> ProviderResult<DatabaseProviderRO<DB>> {
let mut provider = DatabaseProvider::new(self.db.tx()?, self.chain_spec.clone());
if let Some(snapshot_provider) = &self.snapshot_provider {
@ -64,7 +64,7 @@ impl<DB: Database> ProviderFactory<DB> {
/// data from the database using different types of providers. Example: [`HeaderProvider`]
/// [`BlockHashReader`]. This may fail if the inner read/write database transaction fails to
/// open.
pub fn provider_rw(&self) -> ProviderResult<DatabaseProviderRW<'_, DB>> {
pub fn provider_rw(&self) -> ProviderResult<DatabaseProviderRW<DB>> {
let mut provider = DatabaseProvider::new_rw(self.db.tx_mut()?, self.chain_spec.clone());
if let Some(snapshot_provider) = &self.snapshot_provider {
@ -123,7 +123,7 @@ impl<DB: Clone> Clone for ProviderFactory<DB> {
impl<DB: Database> ProviderFactory<DB> {
/// Storage provider for latest block
pub fn latest(&self) -> ProviderResult<StateProviderBox<'_>> {
pub fn latest(&self) -> ProviderResult<StateProviderBox> {
trace!(target: "providers::db", "Returning latest state provider");
Ok(Box::new(LatestStateProvider::new(self.db.tx()?)))
}
@ -132,7 +132,7 @@ impl<DB: Database> ProviderFactory<DB> {
fn state_provider_by_block_number(
&self,
mut block_number: BlockNumber,
) -> ProviderResult<StateProviderBox<'_>> {
) -> ProviderResult<StateProviderBox> {
let provider = self.provider()?;
if block_number == provider.best_block_number().unwrap_or_default() &&
@ -175,17 +175,14 @@ impl<DB: Database> ProviderFactory<DB> {
pub fn history_by_block_number(
&self,
block_number: BlockNumber,
) -> ProviderResult<StateProviderBox<'_>> {
) -> ProviderResult<StateProviderBox> {
let state_provider = self.state_provider_by_block_number(block_number)?;
trace!(target: "providers::db", ?block_number, "Returning historical state provider for block number");
Ok(state_provider)
}
/// Storage provider for state at that given block hash
pub fn history_by_block_hash(
&self,
block_hash: BlockHash,
) -> ProviderResult<StateProviderBox<'_>> {
pub fn history_by_block_hash(&self, block_hash: BlockHash) -> ProviderResult<StateProviderBox> {
let block_number = self
.provider()?
.block_number(block_hash)?

View File

@ -14,7 +14,7 @@ use itertools::{izip, Itertools};
use reth_db::{
common::KeyValue,
cursor::{DbCursorRO, DbCursorRW, DbDupCursorRO},
database::{Database, DatabaseGAT},
database::Database,
models::{
sharded_key, storage_sharded_key::StorageShardedKey, AccountBeforeTx, BlockNumberAddress,
ShardedKey, StoredBlockBodyIndices, StoredBlockOmmers, StoredBlockWithdrawals,
@ -55,39 +55,37 @@ use std::{
use tracing::{debug, warn};
/// A [`DatabaseProvider`] that holds a read-only database transaction.
pub type DatabaseProviderRO<'this, DB> = DatabaseProvider<<DB as DatabaseGAT<'this>>::TX>;
pub type DatabaseProviderRO<DB> = DatabaseProvider<<DB as Database>::TX>;
/// A [`DatabaseProvider`] that holds a read-write database transaction.
///
/// Ideally this would be an alias type. However, there's some weird compiler error (<https://github.com/rust-lang/rust/issues/102211>), that forces us to wrap this in a struct instead.
/// Once that issue is solved, we can probably revert back to being an alias type.
#[derive(Debug)]
pub struct DatabaseProviderRW<'this, DB: Database>(
pub DatabaseProvider<<DB as DatabaseGAT<'this>>::TXMut>,
);
pub struct DatabaseProviderRW<DB: Database>(pub DatabaseProvider<<DB as Database>::TXMut>);
impl<'this, DB: Database> Deref for DatabaseProviderRW<'this, DB> {
type Target = DatabaseProvider<<DB as DatabaseGAT<'this>>::TXMut>;
impl<DB: Database> Deref for DatabaseProviderRW<DB> {
type Target = DatabaseProvider<<DB as Database>::TXMut>;
fn deref(&self) -> &Self::Target {
&self.0
}
}
impl<DB: Database> DerefMut for DatabaseProviderRW<'_, DB> {
impl<DB: Database> DerefMut for DatabaseProviderRW<DB> {
fn deref_mut(&mut self) -> &mut Self::Target {
&mut self.0
}
}
impl<'this, DB: Database> DatabaseProviderRW<'this, DB> {
impl<DB: Database> DatabaseProviderRW<DB> {
/// Commit database transaction
pub fn commit(self) -> ProviderResult<bool> {
self.0.commit()
}
/// Consume `DbTx` or `DbTxMut`.
pub fn into_tx(self) -> <DB as DatabaseGAT<'this>>::TXMut {
pub fn into_tx(self) -> <DB as Database>::TXMut {
self.0.into_tx()
}
}

View File

@ -508,7 +508,7 @@ where
Tree: BlockchainTreePendingStateProvider + BlockchainTreeViewer,
{
/// Storage provider for latest block
fn latest(&self) -> ProviderResult<StateProviderBox<'_>> {
fn latest(&self) -> ProviderResult<StateProviderBox> {
trace!(target: "providers::blockchain", "Getting latest block state provider");
self.database.latest()
}
@ -516,18 +516,18 @@ where
fn history_by_block_number(
&self,
block_number: BlockNumber,
) -> ProviderResult<StateProviderBox<'_>> {
) -> ProviderResult<StateProviderBox> {
trace!(target: "providers::blockchain", ?block_number, "Getting history by block number");
self.ensure_canonical_block(block_number)?;
self.database.history_by_block_number(block_number)
}
fn history_by_block_hash(&self, block_hash: BlockHash) -> ProviderResult<StateProviderBox<'_>> {
fn history_by_block_hash(&self, block_hash: BlockHash) -> ProviderResult<StateProviderBox> {
trace!(target: "providers::blockchain", ?block_hash, "Getting history by block hash");
self.database.history_by_block_hash(block_hash)
}
fn state_by_block_hash(&self, block: BlockHash) -> ProviderResult<StateProviderBox<'_>> {
fn state_by_block_hash(&self, block: BlockHash) -> ProviderResult<StateProviderBox> {
trace!(target: "providers::blockchain", ?block, "Getting state by block hash");
let mut state = self.history_by_block_hash(block);
@ -546,7 +546,7 @@ where
///
/// If there's no pending block available then the latest state provider is returned:
/// [Self::latest]
fn pending(&self) -> ProviderResult<StateProviderBox<'_>> {
fn pending(&self) -> ProviderResult<StateProviderBox> {
trace!(target: "providers::blockchain", "Getting provider for pending state");
if let Some(block) = self.tree.pending_block_num_hash() {
@ -559,10 +559,7 @@ where
self.latest()
}
fn pending_state_by_hash(
&self,
block_hash: B256,
) -> ProviderResult<Option<StateProviderBox<'_>>> {
fn pending_state_by_hash(&self, block_hash: B256) -> ProviderResult<Option<StateProviderBox>> {
if let Some(state) = self.tree.find_pending_state_provider(block_hash) {
return Ok(Some(self.pending_with_provider(state)?))
}
@ -572,7 +569,7 @@ where
fn pending_with_provider(
&self,
bundle_state_data: Box<dyn BundleStateDataProvider>,
) -> ProviderResult<StateProviderBox<'_>> {
) -> ProviderResult<StateProviderBox> {
let canonical_fork = bundle_state_data.canonical_fork();
trace!(target: "providers::blockchain", ?canonical_fork, "Returning post state provider");

View File

@ -10,7 +10,7 @@ use reth_primitives::{
use std::collections::HashMap;
/// Assert genesis block
pub fn assert_genesis_block<DB: Database>(provider: &DatabaseProviderRW<'_, DB>, g: SealedBlock) {
pub fn assert_genesis_block<DB: Database>(provider: &DatabaseProviderRW<DB>, g: SealedBlock) {
let n = g.number;
let h = B256::ZERO;
let tx = provider;

View File

@ -581,73 +581,67 @@ impl EvmEnvProvider for MockEthProvider {
}
impl StateProviderFactory for MockEthProvider {
fn latest(&self) -> ProviderResult<StateProviderBox<'_>> {
fn latest(&self) -> ProviderResult<StateProviderBox> {
Ok(Box::new(self.clone()))
}
fn history_by_block_number(&self, _block: BlockNumber) -> ProviderResult<StateProviderBox<'_>> {
fn history_by_block_number(&self, _block: BlockNumber) -> ProviderResult<StateProviderBox> {
Ok(Box::new(self.clone()))
}
fn history_by_block_hash(&self, _block: BlockHash) -> ProviderResult<StateProviderBox<'_>> {
fn history_by_block_hash(&self, _block: BlockHash) -> ProviderResult<StateProviderBox> {
Ok(Box::new(self.clone()))
}
fn state_by_block_hash(&self, _block: BlockHash) -> ProviderResult<StateProviderBox<'_>> {
fn state_by_block_hash(&self, _block: BlockHash) -> ProviderResult<StateProviderBox> {
Ok(Box::new(self.clone()))
}
fn pending(&self) -> ProviderResult<StateProviderBox<'_>> {
fn pending(&self) -> ProviderResult<StateProviderBox> {
Ok(Box::new(self.clone()))
}
fn pending_state_by_hash(
&self,
_block_hash: B256,
) -> ProviderResult<Option<StateProviderBox<'_>>> {
fn pending_state_by_hash(&self, _block_hash: B256) -> ProviderResult<Option<StateProviderBox>> {
Ok(Some(Box::new(self.clone())))
}
fn pending_with_provider<'a>(
&'a self,
_bundle_state_data: Box<dyn BundleStateDataProvider + 'a>,
) -> ProviderResult<StateProviderBox<'a>> {
) -> ProviderResult<StateProviderBox> {
Ok(Box::new(self.clone()))
}
}
impl StateProviderFactory for Arc<MockEthProvider> {
fn latest(&self) -> ProviderResult<StateProviderBox<'_>> {
fn latest(&self) -> ProviderResult<StateProviderBox> {
Ok(Box::new(self.clone()))
}
fn history_by_block_number(&self, _block: BlockNumber) -> ProviderResult<StateProviderBox<'_>> {
fn history_by_block_number(&self, _block: BlockNumber) -> ProviderResult<StateProviderBox> {
Ok(Box::new(self.clone()))
}
fn history_by_block_hash(&self, _block: BlockHash) -> ProviderResult<StateProviderBox<'_>> {
fn history_by_block_hash(&self, _block: BlockHash) -> ProviderResult<StateProviderBox> {
Ok(Box::new(self.clone()))
}
fn state_by_block_hash(&self, _block: BlockHash) -> ProviderResult<StateProviderBox<'_>> {
fn state_by_block_hash(&self, _block: BlockHash) -> ProviderResult<StateProviderBox> {
Ok(Box::new(self.clone()))
}
fn pending(&self) -> ProviderResult<StateProviderBox<'_>> {
fn pending(&self) -> ProviderResult<StateProviderBox> {
Ok(Box::new(self.clone()))
}
fn pending_state_by_hash(
&self,
_block_hash: B256,
) -> ProviderResult<Option<StateProviderBox<'_>>> {
fn pending_state_by_hash(&self, _block_hash: B256) -> ProviderResult<Option<StateProviderBox>> {
Ok(Some(Box::new(self.clone())))
}
fn pending_with_provider<'a>(
&'a self,
_bundle_state_data: Box<dyn BundleStateDataProvider + 'a>,
) -> ProviderResult<StateProviderBox<'a>> {
) -> ProviderResult<StateProviderBox> {
Ok(Box::new(self.clone()))
}
}

View File

@ -347,37 +347,34 @@ impl EvmEnvProvider for NoopProvider {
}
impl StateProviderFactory for NoopProvider {
fn latest(&self) -> ProviderResult<StateProviderBox<'_>> {
fn latest(&self) -> ProviderResult<StateProviderBox> {
Ok(Box::new(*self))
}
fn history_by_block_number(&self, _block: BlockNumber) -> ProviderResult<StateProviderBox<'_>> {
fn history_by_block_number(&self, _block: BlockNumber) -> ProviderResult<StateProviderBox> {
Ok(Box::new(*self))
}
fn history_by_block_hash(&self, _block: BlockHash) -> ProviderResult<StateProviderBox<'_>> {
fn history_by_block_hash(&self, _block: BlockHash) -> ProviderResult<StateProviderBox> {
Ok(Box::new(*self))
}
fn state_by_block_hash(&self, _block: BlockHash) -> ProviderResult<StateProviderBox<'_>> {
fn state_by_block_hash(&self, _block: BlockHash) -> ProviderResult<StateProviderBox> {
Ok(Box::new(*self))
}
fn pending(&self) -> ProviderResult<StateProviderBox<'_>> {
fn pending(&self) -> ProviderResult<StateProviderBox> {
Ok(Box::new(*self))
}
fn pending_state_by_hash(
&self,
_block_hash: B256,
) -> ProviderResult<Option<StateProviderBox<'_>>> {
fn pending_state_by_hash(&self, _block_hash: B256) -> ProviderResult<Option<StateProviderBox>> {
Ok(Some(Box::new(*self)))
}
fn pending_with_provider<'a>(
&'a self,
_bundle_state_data: Box<dyn crate::BundleStateDataProvider + 'a>,
) -> ProviderResult<StateProviderBox<'a>> {
) -> ProviderResult<StateProviderBox> {
Ok(Box::new(*self))
}
}

View File

@ -9,7 +9,7 @@ use reth_primitives::{
use reth_trie::updates::TrieUpdates;
/// Type alias of boxed [StateProvider].
pub type StateProviderBox<'a> = Box<dyn StateProvider + 'a>;
pub type StateProviderBox = Box<dyn StateProvider>;
/// An abstraction for a type that provides state data.
#[auto_impl(&, Arc, Box)]
@ -100,13 +100,13 @@ pub trait StateProvider: BlockHashReader + AccountReader + StateRootProvider + S
/// to be used, since block `n` was executed on its parent block's state.
pub trait StateProviderFactory: BlockIdReader + Send + Sync {
/// Storage provider for latest block.
fn latest(&self) -> ProviderResult<StateProviderBox<'_>>;
fn latest(&self) -> ProviderResult<StateProviderBox>;
/// Returns a [StateProvider] indexed by the given [BlockId].
///
/// Note: if a number or hash is provided this will __only__ look at historical(canonical)
/// state.
fn state_by_block_id(&self, block_id: BlockId) -> ProviderResult<StateProviderBox<'_>> {
fn state_by_block_id(&self, block_id: BlockId) -> ProviderResult<StateProviderBox> {
match block_id {
BlockId::Number(block_number) => self.state_by_block_number_or_tag(block_number),
BlockId::Hash(block_hash) => self.history_by_block_hash(block_hash.into()),
@ -119,7 +119,7 @@ pub trait StateProviderFactory: BlockIdReader + Send + Sync {
fn state_by_block_number_or_tag(
&self,
number_or_tag: BlockNumberOrTag,
) -> ProviderResult<StateProviderBox<'_>> {
) -> ProviderResult<StateProviderBox> {
match number_or_tag {
BlockNumberOrTag::Latest => self.latest(),
BlockNumberOrTag::Finalized => {
@ -153,40 +153,37 @@ pub trait StateProviderFactory: BlockIdReader + Send + Sync {
///
///
/// Note: this only looks at historical blocks, not pending blocks.
fn history_by_block_number(&self, block: BlockNumber) -> ProviderResult<StateProviderBox<'_>>;
fn history_by_block_number(&self, block: BlockNumber) -> ProviderResult<StateProviderBox>;
/// Returns a historical [StateProvider] indexed by the given block hash.
///
/// Note: this only looks at historical blocks, not pending blocks.
fn history_by_block_hash(&self, block: BlockHash) -> ProviderResult<StateProviderBox<'_>>;
fn history_by_block_hash(&self, block: BlockHash) -> ProviderResult<StateProviderBox>;
/// Returns _any_[StateProvider] with matching block hash.
///
/// This will return a [StateProvider] for either a historical or pending block.
fn state_by_block_hash(&self, block: BlockHash) -> ProviderResult<StateProviderBox<'_>>;
fn state_by_block_hash(&self, block: BlockHash) -> ProviderResult<StateProviderBox>;
/// Storage provider for pending state.
///
/// Represents the state at the block that extends the canonical chain by one.
/// If there's no `pending` block, then this is equal to [StateProviderFactory::latest]
fn pending(&self) -> ProviderResult<StateProviderBox<'_>>;
fn pending(&self) -> ProviderResult<StateProviderBox>;
/// Storage provider for pending state for the given block hash.
///
/// Represents the state at the block that extends the canonical chain.
///
/// If the block couldn't be found, returns `None`.
fn pending_state_by_hash(
&self,
block_hash: B256,
) -> ProviderResult<Option<StateProviderBox<'_>>>;
fn pending_state_by_hash(&self, block_hash: B256) -> ProviderResult<Option<StateProviderBox>>;
/// Return a [StateProvider] that contains bundle state data provider.
/// Used to inspect or execute transaction on the pending state.
fn pending_with_provider(
&self,
bundle_state_data: Box<dyn BundleStateDataProvider>,
) -> ProviderResult<StateProviderBox<'_>>;
) -> ProviderResult<StateProviderBox>;
}
/// Blockchain trait provider that gives access to the blockchain state that is not yet committed