This commit is contained in:
Brian Picciano
2025-12-18 18:09:16 +01:00
parent e06e6f3d25
commit 0946449b67
9 changed files with 32 additions and 30 deletions

View File

@@ -5,14 +5,14 @@ use reth_errors::ProviderResult;
use reth_primitives_traits::{Account, Bytecode, NodePrimitives};
use reth_storage_api::{
AccountReader, BlockHashReader, BytecodeReader, HashedPostStateProvider, StateProofProvider,
StateProvider, StateRootProvider, StorageRootProvider,
StateProvider, StateProviderBox, StateRootProvider, StorageRootProvider,
};
use reth_trie::{
updates::TrieUpdates, AccountProof, HashedPostState, HashedStorage, MultiProof,
MultiProofTargets, StorageMultiProof, TrieInput,
};
use revm_database::BundleState;
use std::sync::OnceLock;
use std::{borrow::Cow, sync::OnceLock};
/// A state provider that stores references to in-memory blocks along with their state as well as a
/// reference of the historical state provider for fallback lookups.
@@ -24,7 +24,7 @@ pub struct MemoryOverlayStateProviderRef<
/// Historical state provider for state lookups that are not found in memory blocks.
pub(crate) historical: Box<dyn StateProvider + 'a>,
/// The collection of executed parent blocks. Expected order is newest to oldest.
pub(crate) in_memory: &'a Vec<ExecutedBlock<N>>,
pub(crate) in_memory: Cow<'a, Vec<ExecutedBlock<N>>>,
/// Lazy-loaded in-memory trie data.
pub(crate) trie_input: OnceLock<TrieInput>,
}
@@ -37,11 +37,8 @@ impl<'a, N: NodePrimitives> MemoryOverlayStateProviderRef<'a, N> {
/// - `in_memory` - the collection of executed ancestor blocks in reverse.
/// - `historical` - a historical state provider for the latest ancestor block stored in the
/// database.
pub fn new(
historical: Box<dyn StateProvider + 'a>,
in_memory: &'a Vec<ExecutedBlock<N>>,
) -> Self {
Self { historical, in_memory, trie_input: OnceLock::new() }
pub fn new(historical: Box<dyn StateProvider + 'a>, in_memory: Vec<ExecutedBlock<N>>) -> Self {
Self { historical, in_memory: Cow::Owned(in_memory), trie_input: OnceLock::new() }
}
/// Turn this state provider into a state provider
@@ -70,7 +67,7 @@ impl<'a, N: NodePrimitives> MemoryOverlayStateProviderRef<'a, N> {
impl<N: NodePrimitives> BlockHashReader for MemoryOverlayStateProviderRef<'_, N> {
fn block_hash(&self, number: BlockNumber) -> ProviderResult<Option<B256>> {
for block in self.in_memory {
for block in self.in_memory.iter() {
if block.recovered_block().number() == number {
return Ok(Some(block.recovered_block().hash()));
}
@@ -89,7 +86,7 @@ impl<N: NodePrimitives> BlockHashReader for MemoryOverlayStateProviderRef<'_, N>
let mut in_memory_hashes = Vec::with_capacity(range.size_hint().0);
// iterate in ascending order (oldest to newest = low to high)
for block in self.in_memory {
for block in self.in_memory.iter() {
let block_num = block.recovered_block().number();
if range.contains(&block_num) {
in_memory_hashes.push(block.recovered_block().hash());
@@ -111,7 +108,7 @@ impl<N: NodePrimitives> BlockHashReader for MemoryOverlayStateProviderRef<'_, N>
impl<N: NodePrimitives> AccountReader for MemoryOverlayStateProviderRef<'_, N> {
fn basic_account(&self, address: &Address) -> ProviderResult<Option<Account>> {
for block in self.in_memory {
for block in self.in_memory.iter() {
if let Some(account) = block.execution_output.account(address) {
return Ok(account);
}
@@ -215,7 +212,7 @@ impl<N: NodePrimitives> StateProvider for MemoryOverlayStateProviderRef<'_, N> {
address: Address,
storage_key: StorageKey,
) -> ProviderResult<Option<StorageValue>> {
for block in self.in_memory {
for block in self.in_memory.iter() {
if let Some(value) = block.execution_output.storage(&address, storage_key.into()) {
return Ok(Some(value));
}
@@ -227,7 +224,7 @@ impl<N: NodePrimitives> StateProvider for MemoryOverlayStateProviderRef<'_, N> {
impl<N: NodePrimitives> BytecodeReader for MemoryOverlayStateProviderRef<'_, N> {
fn bytecode_by_hash(&self, code_hash: &B256) -> ProviderResult<Option<Bytecode>> {
for block in self.in_memory {
for block in self.in_memory.iter() {
if let Some(contract) = block.execution_output.bytecode(code_hash) {
return Ok(Some(contract));
}
@@ -242,7 +239,7 @@ impl<N: NodePrimitives> BytecodeReader for MemoryOverlayStateProviderRef<'_, N>
#[expect(missing_debug_implementations)]
pub struct MemoryOverlayStateProvider<N: NodePrimitives = reth_ethereum_primitives::EthPrimitives> {
/// Historical state provider for state lookups that are not found in memory blocks.
pub(crate) historical: Box<dyn StateProvider>,
pub(crate) historical: StateProviderBox,
/// The collection of executed parent blocks. Expected order is newest to oldest.
pub(crate) in_memory: Vec<ExecutedBlock<N>>,
/// Lazy-loaded in-memory trie data.
@@ -257,7 +254,7 @@ impl<N: NodePrimitives> MemoryOverlayStateProvider<N> {
/// - `in_memory` - the collection of executed ancestor blocks in reverse.
/// - `historical` - a historical state provider for the latest ancestor block stored in the
/// database.
pub fn new(historical: Box<dyn StateProvider>, in_memory: Vec<ExecutedBlock<N>>) -> Self {
pub fn new(historical: StateProviderBox, in_memory: Vec<ExecutedBlock<N>>) -> Self {
Self { historical, in_memory, trie_input: OnceLock::new() }
}
@@ -266,10 +263,15 @@ impl<N: NodePrimitives> MemoryOverlayStateProvider<N> {
fn as_ref(&self) -> MemoryOverlayStateProviderRef<'_, N> {
MemoryOverlayStateProviderRef {
historical: Box::new(self.historical.as_ref()),
in_memory: &self.in_memory,
in_memory: Cow::Borrowed(&self.in_memory),
trie_input: self.trie_input.clone(),
}
}
/// Wraps the [`Self`] in a `Box`.
pub fn boxed(self) -> StateProviderBox {
Box::new(self)
}
}
// Delegates all provider impls to [`MemoryOverlayStateProviderRef`]

View File

@@ -435,8 +435,7 @@ where
}
// Execute the block and handle any execution errors
let (output, senders) = match self.execute_block(&state_provider, env, &input, &mut handle)
{
let (output, senders) = match self.execute_block(state_provider, env, &input, &mut handle) {
Ok(output) => output,
Err(err) => return self.handle_execution_error(input, err, &parent_block),
};
@@ -603,7 +602,7 @@ where
handle: &mut PayloadHandle<impl ExecutableTxFor<Evm>, Err, N::Receipt>,
) -> Result<(BlockExecutionOutput<N::Receipt>, Vec<Address>), InsertBlockErrorKind>
where
S: StateProvider,
S: StateProvider + Send,
Err: core::error::Error + Send + Sync + 'static,
V: PayloadValidator<T, Block = N::Block>,
T: PayloadTypes<BuiltPayload: BuiltPayload<Primitives = N>>,

View File

@@ -116,7 +116,7 @@ where
/// these stages that this work has already been done. Otherwise, there might be some conflict with
/// database integrity.
pub fn save_stage_checkpoints<P>(
provider: &P,
provider: P,
from: BlockNumber,
to: BlockNumber,
processed: u64,

View File

@@ -155,7 +155,7 @@ where
let state_provider = client.state_by_block_hash(parent_header.hash())?;
let state = StateProviderDatabase::new(state_provider);
let mut db =
State::builder().with_database_ref(cached_reads.as_db(state)).with_bundle_update().build();
State::builder().with_database(cached_reads.as_db_mut(state)).with_bundle_update().build();
let mut builder = evm_config
.builder_for_next_block(
@@ -358,6 +358,7 @@ where
return Ok(BuildOutcome::Aborted { fees: total_fees, cached_reads })
}
let state_provider = client.state_by_block_hash(parent_header.hash())?;
let BlockBuilderOutcome { execution_result, block, .. } = builder.finish(state_provider)?;
let requests = chain_spec

View File

@@ -9,7 +9,7 @@ use revm::{bytecode::Bytecode, state::AccountInfo, Database, DatabaseRef};
/// A helper trait responsible for providing state necessary for EVM execution.
///
/// This serves as the data layer for [`Database`].
pub trait EvmStateProvider: Send {
pub trait EvmStateProvider {
/// Get basic account information.
///
/// Returns [`None`] if the account doesn't exist.
@@ -34,7 +34,7 @@ pub trait EvmStateProvider: Send {
}
// Blanket implementation of EvmStateProvider for any type that implements StateProvider.
impl<T: StateProvider + Send> EvmStateProvider for T {
impl<T: StateProvider> EvmStateProvider for T {
fn basic_account(&self, address: &Address) -> ProviderResult<Option<Account>> {
<T as AccountReader>::basic_account(self, address)
}

View File

@@ -33,7 +33,7 @@ use reth_rpc_eth_types::{
simulate::{self, EthSimulateError},
EthApiError, StateCacheDb,
};
use reth_storage_api::{BlockIdReader, ProviderTx, StateProvider};
use reth_storage_api::{BlockIdReader, ProviderTx, StateProviderBox};
use revm::{
context::Block,
context_interface::{result::ResultAndState, Transaction},
@@ -491,11 +491,11 @@ pub trait Call:
) -> impl Future<Output = Result<R, Self::Error>> + Send
where
R: Send + 'static,
F: FnOnce(Self, &dyn StateProvider) -> Result<R, Self::Error> + Send + 'static,
F: FnOnce(Self, StateProviderBox) -> Result<R, Self::Error> + Send + 'static,
{
self.spawn_blocking_io_fut(move |this| async move {
let state = this.state_at_block_id(at).await?;
f(this, &state)
f(this, state)
})
}

View File

@@ -20,8 +20,8 @@ pub use traits::*;
pub mod providers;
pub use providers::{
DatabaseProvider, DatabaseProviderRO, DatabaseProviderRW, HistoricalStateProvider,
HistoricalStateProviderRef, LatestStateProvider, ProviderFactory, StaticFileAccess,
StaticFileProviderBuilder, StaticFileWriter,
HistoricalStateProviderRef, LatestStateProvider, LatestStateProviderRef, ProviderFactory,
StaticFileAccess, StaticFileProviderBuilder, StaticFileWriter,
};
pub mod changesets_utils;

View File

@@ -19,7 +19,7 @@ pub trait StageCheckpointReader: Send {
/// The trait for updating stage checkpoint related data.
#[auto_impl::auto_impl(&)]
pub trait StageCheckpointWriter: Send {
pub trait StageCheckpointWriter {
/// Save stage checkpoint.
fn save_stage_checkpoint(&self, id: StageId, checkpoint: StageCheckpoint)
-> ProviderResult<()>;

View File

@@ -2,7 +2,7 @@ use reth_db_api::table::Table;
/// The trait for fetching provider statistics.
#[auto_impl::auto_impl(&)]
pub trait StatsReader: Send {
pub trait StatsReader {
/// Fetch the number of entries in the corresponding [Table]. Depending on the provider, it may
/// route to different data sources other than [Table].
fn count_entries<T: Table>(&self) -> reth_storage_errors::provider::ProviderResult<usize>;