Skip to content

Commit

Permalink
feat: impl StateReader for BlockchainProvider2 (#10618)
Browse files Browse the repository at this point in the history
  • Loading branch information
Rjected committed Sep 3, 2024
1 parent 9d46b06 commit 5744ad1
Show file tree
Hide file tree
Showing 4 changed files with 48 additions and 13 deletions.
17 changes: 16 additions & 1 deletion crates/storage/provider/src/providers/blockchain_provider.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ use crate::{
CanonStateSubscriptions, ChainSpecProvider, ChangeSetReader, DatabaseProviderFactory,
DatabaseProviderRO, EvmEnvProvider, FinalizedBlockReader, HeaderProvider, ProviderError,
ProviderFactory, PruneCheckpointReader, ReceiptProvider, ReceiptProviderIdExt,
RequestsProvider, StageCheckpointReader, StateProviderBox, StateProviderFactory,
RequestsProvider, StageCheckpointReader, StateProviderBox, StateProviderFactory, StateReader,
StaticFileProviderFactory, TransactionVariant, TransactionsProvider, WithdrawalsProvider,
};
use alloy_rpc_types_engine::ForkchoiceState;
Expand All @@ -18,6 +18,7 @@ use reth_db_api::{
models::{AccountBeforeTx, StoredBlockBodyIndices},
};
use reth_evm::ConfigureEvmEnv;
use reth_execution_types::ExecutionOutcome;
use reth_primitives::{
Account, Address, Block, BlockHash, BlockHashOrNumber, BlockId, BlockNumHash, BlockNumber,
BlockNumberOrTag, BlockWithSenders, EthereumHardforks, Header, Receipt, SealedBlock,
Expand Down Expand Up @@ -1433,6 +1434,20 @@ where
}
}

impl<DB> StateReader for BlockchainProvider2<DB>
where
DB: Database + Sync + Send,
{
fn get_state(&self, block: BlockNumber) -> ProviderResult<Option<ExecutionOutcome>> {
if let Some(state) = self.canonical_in_memory_state.state_by_number(block) {
let state = state.block().execution_outcome().clone();
Ok(Some(state))
} else {
self.database.provider()?.get_state(block..=block)
}
}
}

#[cfg(test)]
mod tests {
use std::{
Expand Down
1 change: 1 addition & 0 deletions crates/storage/provider/src/providers/database/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -603,6 +603,7 @@ impl<DB, Spec> Clone for ProviderFactory<DB, Spec> {
}
}
}

#[cfg(test)]
mod tests {
use super::*;
Expand Down
34 changes: 23 additions & 11 deletions crates/storage/provider/src/providers/database/provider.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,8 +11,8 @@ use crate::{
FinalizedBlockWriter, HashingWriter, HeaderProvider, HeaderSyncGap, HeaderSyncGapProvider,
HistoricalStateProvider, HistoryWriter, LatestStateProvider, OriginalValuesKnown,
ProviderError, PruneCheckpointReader, PruneCheckpointWriter, RequestsProvider, RevertsInit,
StageCheckpointReader, StateChangeWriter, StateProviderBox, StateWriter, StatsReader,
StorageReader, StorageTrieWriter, TransactionVariant, TransactionsProvider,
StageCheckpointReader, StateChangeWriter, StateProviderBox, StateReader, StateWriter,
StatsReader, StorageReader, StorageTrieWriter, TransactionVariant, TransactionsProvider,
TransactionsProviderExt, TrieWriter, WithdrawalsProvider,
};
use itertools::{izip, Itertools};
Expand Down Expand Up @@ -777,23 +777,29 @@ impl<TX: DbTx> DatabaseProvider<TX> {
/// 1. Take the old value from the changeset
/// 2. Take the new value from the local state
/// 3. Set the local state to the value in the changeset
///
/// If the range is empty, or there are no blocks for the given range, then this returns `None`.
pub fn get_state(
&self,
range: RangeInclusive<BlockNumber>,
) -> ProviderResult<ExecutionOutcome> {
) -> ProviderResult<Option<ExecutionOutcome>> {
if range.is_empty() {
return Ok(ExecutionOutcome::default())
return Ok(None)
}
let start_block_number = *range.start();

// We are not removing block meta as it is used to get block changesets.
let block_bodies = self.get::<tables::BlockBodyIndices>(range.clone())?;

// get transaction receipts
let from_transaction_num =
block_bodies.first().expect("already checked if there are blocks").1.first_tx_num();
let to_transaction_num =
block_bodies.last().expect("already checked if there are blocks").1.last_tx_num();
let Some(from_transaction_num) = block_bodies.first().map(|bodies| bodies.1.first_tx_num())
else {
return Ok(None)
};
let Some(to_transaction_num) = block_bodies.last().map(|bodies| bodies.1.last_tx_num())
else {
return Ok(None)
};

let storage_range = BlockNumberAddress::range(range.clone());

Expand Down Expand Up @@ -830,14 +836,14 @@ impl<TX: DbTx> DatabaseProvider<TX> {
receipts.push(block_receipts);
}

Ok(ExecutionOutcome::new_init(
Ok(Some(ExecutionOutcome::new_init(
state,
reverts,
Vec::new(),
receipts.into(),
start_block_number,
Vec::new(),
))
)))
}

/// Populate a [`BundleStateInit`] and [`RevertsInit`] using cursors over the
Expand Down Expand Up @@ -3223,12 +3229,18 @@ impl<TX: DbTx> BlockExecutionReader for DatabaseProvider<TX> {
let blocks = self.get_block_range(range.clone())?;

// get execution res
let execution_state = self.get_state(range)?;
let execution_state = self.get_state(range)?.unwrap_or_default();

Ok(Chain::new(blocks, execution_state, None))
}
}

impl<TX: DbTx> StateReader for DatabaseProvider<TX> {
fn get_state(&self, block: BlockNumber) -> ProviderResult<Option<ExecutionOutcome>> {
self.get_state(block..=block)
}
}

impl<TX: DbTxMut + DbTx> BlockExecutionWriter for DatabaseProvider<TX> {
fn take_block_and_execution_range(
&self,
Expand Down
9 changes: 8 additions & 1 deletion crates/storage/provider/src/traits/block.rs
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ pub trait BlockExecutionWriter: BlockWriter + Send + Sync {
) -> ProviderResult<()>;
}

/// BlockExecution Writer
/// BlockExecution Reader
#[auto_impl::auto_impl(&, Arc, Box)]
pub trait BlockExecutionReader: BlockReader + Send + Sync {
/// Get range of blocks and its execution result
Expand All @@ -32,6 +32,13 @@ pub trait BlockExecutionReader: BlockReader + Send + Sync {
) -> ProviderResult<Chain>;
}

/// This just receives state, or [`ExecutionOutcome`], from the provider
#[auto_impl::auto_impl(&, Arc, Box)]
pub trait StateReader: Send + Sync {
/// Get the [`ExecutionOutcome`] for the given block
fn get_state(&self, block: BlockNumber) -> ProviderResult<Option<ExecutionOutcome>>;
}

/// Block Writer
#[auto_impl::auto_impl(&, Arc, Box)]
pub trait BlockWriter: Send + Sync {
Expand Down

0 comments on commit 5744ad1

Please sign in to comment.