Skip to content

Commit

Permalink
Rework based on discussion
Browse files Browse the repository at this point in the history
  • Loading branch information
0x00101010 committed Sep 11, 2024
1 parent 737a348 commit 40a9310
Show file tree
Hide file tree
Showing 15 changed files with 68 additions and 65 deletions.
2 changes: 1 addition & 1 deletion bin/reth/src/commands/debug_cmd/build_block.rs
Original file line number Diff line number Diff line change
Expand Up @@ -261,7 +261,7 @@ impl<C: ChainSpecParser<ChainSpec = ChainSpec>> Command<C> {
SealedBlockWithSenders::new(block.clone(), senders).unwrap();

let db = StateProviderDatabase::new(blockchain_db.latest()?);
let executor =
let mut executor =
EthExecutorProvider::ethereum(provider_factory.chain_spec()).executor(db);

let block_execution_output =
Expand Down
3 changes: 2 additions & 1 deletion bin/reth/src/commands/debug_cmd/in_memory_merkle.rs
Original file line number Diff line number Diff line change
Expand Up @@ -136,7 +136,8 @@ impl<C: ChainSpecParser<ChainSpec = ChainSpec>> Command<C> {
provider_factory.static_file_provider(),
));

let executor = EthExecutorProvider::ethereum(provider_factory.chain_spec()).executor(db);
let mut executor =
EthExecutorProvider::ethereum(provider_factory.chain_spec()).executor(db);

let merkle_block_td =
provider.header_td_by_number(merkle_block_number)?.unwrap_or_default();
Expand Down
2 changes: 1 addition & 1 deletion crates/blockchain-tree/src/chain.rs
Original file line number Diff line number Diff line change
Expand Up @@ -203,7 +203,7 @@ impl AppendableChain {
let provider = BundleStateProvider::new(state_provider, bundle_state_data_provider);

let db = StateProviderDatabase::new(&provider);
let executor = externals.executor_factory.executor(db);
let mut executor = externals.executor_factory.executor(db);
let block_hash = block.hash();
let block = block.unseal();

Expand Down
3 changes: 2 additions & 1 deletion crates/engine/tree/src/tree/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2136,7 +2136,8 @@ where
return Err(e.into())
}

let executor = self.executor_provider.executor(StateProviderDatabase::new(&state_provider));
let mut executor =
self.executor_provider.executor(StateProviderDatabase::new(&state_provider));

let block_number = block.number;
let block_hash = block.hash();
Expand Down
18 changes: 8 additions & 10 deletions crates/ethereum/evm/src/execute.rs
Original file line number Diff line number Diff line change
Expand Up @@ -372,21 +372,19 @@ where
/// Returns the receipts of the transactions in the block.
///
/// Returns an error if the block could not be executed or failed verification.
fn execute(mut self, input: Self::Input<'_>) -> Result<Self::Output, Self::Error> {
fn execute(&mut self, input: Self::Input<'_>) -> Result<Self::Output, Self::Error> {
let BlockExecutionInput { block, total_difficulty } = input;
let EthExecuteOutput { receipts, requests, gas_used } =
self.execute_without_verification(block, total_difficulty)?;

// NOTE: we need to merge keep the reverts for the bundle retention
self.state.merge_transitions(BundleRetention::Reverts);

Ok(BlockExecutionOutput {
state: self.state.take_bundle(),
cache: core::mem::take(&mut self.state.cache),
receipts,
requests,
gas_used,
})
Ok(BlockExecutionOutput { state: self.state.take_bundle(), receipts, requests, gas_used })
}

fn state_ref(&self) -> &State<DB> {
&self.state
}
}

Expand Down Expand Up @@ -1309,7 +1307,7 @@ mod tests {

let provider = executor_provider(chain_spec);

let executor = provider.executor(StateProviderDatabase::new(&db));
let mut executor = provider.executor(StateProviderDatabase::new(&db));

let BlockExecutionOutput { receipts, requests, .. } = executor
.execute(
Expand Down Expand Up @@ -1397,7 +1395,7 @@ mod tests {
);

// Create an executor from the state provider
let executor = executor_provider(chain_spec).executor(StateProviderDatabase::new(&db));
let mut executor = executor_provider(chain_spec).executor(StateProviderDatabase::new(&db));

// Execute the block and capture the result
let exec_result = executor.execute(
Expand Down
4 changes: 1 addition & 3 deletions crates/evm/execution-types/src/execute.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
use reth_primitives::{Request, U256};
use revm::{db::BundleState, CacheState};
use revm::db::BundleState;

/// A helper type for ethereum block inputs that consists of a block and the total difficulty.
#[derive(Debug)]
Expand Down Expand Up @@ -30,8 +30,6 @@ impl<'a, Block> From<(&'a Block, U256)> for BlockExecutionInput<'a, Block> {
pub struct BlockExecutionOutput<T> {
/// The changed state of the block after execution.
pub state: BundleState,
/// cache state of the block after execution.
pub cache: CacheState,
/// All the receipts of the transactions in the block.
pub receipts: Vec<T>,
/// All the EIP-7685 requests of the transactions in the block.
Expand Down
10 changes: 9 additions & 1 deletion crates/evm/src/either.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ use reth_execution_types::{BlockExecutionInput, BlockExecutionOutput, ExecutionO
use reth_primitives::{BlockNumber, BlockWithSenders, Receipt};
use reth_prune_types::PruneModes;
use reth_storage_errors::provider::ProviderError;
use revm::db::State;
use revm_primitives::db::Database;

// re-export Either
Expand Down Expand Up @@ -65,12 +66,19 @@ where
type Output = BlockExecutionOutput<Receipt>;
type Error = BlockExecutionError;

fn execute(self, input: Self::Input<'_>) -> Result<Self::Output, Self::Error> {
fn execute(&mut self, input: Self::Input<'_>) -> Result<Self::Output, Self::Error> {
match self {
Self::Left(a) => a.execute(input),
Self::Right(b) => b.execute(input),
}
}

fn state_ref(&self) -> &State<DB> {
match self {
Self::Left(a) => a.state_ref(),
Self::Right(b) => b.state_ref(),
}
}
}

impl<A, B, DB> BatchExecutor<DB> for Either<A, B>
Expand Down
16 changes: 11 additions & 5 deletions crates/evm/src/execute.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
pub use reth_execution_errors::{BlockExecutionError, BlockValidationError};
pub use reth_execution_types::{BlockExecutionInput, BlockExecutionOutput, ExecutionOutcome};
pub use reth_storage_errors::provider::ProviderError;
use revm::db::State;

use core::fmt::Display;

Expand All @@ -23,15 +24,16 @@ pub trait Executor<DB> {
/// The error type returned by the executor.
type Error;

/// Consumes the type and executes the block.
///
/// # Note
/// Execution happens without any validation of the output. To validate the output, use the
/// [`BatchExecutor`].
///
/// # Returns
/// The output of the block execution.
fn execute(self, input: Self::Input<'_>) -> Result<Self::Output, Self::Error>;
fn execute(&mut self, input: Self::Input<'_>) -> Result<Self::Output, Self::Error>;

/// The method returns a reference to the state.
fn state_ref(&self) -> &State<DB>;
}

/// A general purpose executor that can execute multiple inputs in sequence, validate the outputs,
Expand Down Expand Up @@ -175,9 +177,13 @@ mod tests {
type Output = BlockExecutionOutput<Receipt>;
type Error = BlockExecutionError;

fn execute(self, _input: Self::Input<'_>) -> Result<Self::Output, Self::Error> {
fn execute(&mut self, _input: Self::Input<'_>) -> Result<Self::Output, Self::Error> {
Err(BlockExecutionError::msg("execution unavailable for tests"))
}

fn state_ref(&self) -> &State<DB> {
todo!()
}
}

impl<DB> BatchExecutor<DB> for TestExecutor<DB> {
Expand Down Expand Up @@ -210,7 +216,7 @@ mod tests {
fn test_provider() {
let provider = TestExecutorProvider;
let db = CacheDB::<EmptyDBTyped<ProviderError>>::default();
let executor = provider.executor(db);
let mut executor = provider.executor(db);
let block = Block {
header: Default::default(),
body: vec![],
Expand Down
7 changes: 6 additions & 1 deletion crates/evm/src/noop.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ use reth_execution_types::{BlockExecutionInput, BlockExecutionOutput, ExecutionO
use reth_primitives::{BlockNumber, BlockWithSenders, Receipt};
use reth_prune_types::PruneModes;
use reth_storage_errors::provider::ProviderError;
use revm::db::State;
use revm_primitives::db::Database;

use crate::execute::{BatchExecutor, BlockExecutorProvider, Executor};
Expand Down Expand Up @@ -43,9 +44,13 @@ impl<DB> Executor<DB> for NoopBlockExecutorProvider {
type Output = BlockExecutionOutput<Receipt>;
type Error = BlockExecutionError;

fn execute(self, _: Self::Input<'_>) -> Result<Self::Output, Self::Error> {
fn execute(&mut self, _: Self::Input<'_>) -> Result<Self::Output, Self::Error> {
Err(BlockExecutionError::msg(UNAVAILABLE_FOR_NOOP))
}

fn state_ref(&self) -> &State<DB> {
todo!()
}
}

impl<DB> BatchExecutor<DB> for NoopBlockExecutorProvider {
Expand Down
8 changes: 6 additions & 2 deletions crates/evm/src/test_utils.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ use reth_execution_types::ExecutionOutcome;
use reth_primitives::{BlockNumber, BlockWithSenders, Receipt};
use reth_prune_types::PruneModes;
use reth_storage_errors::provider::ProviderError;
use revm::db::State;
use revm_primitives::db::Database;
use std::{fmt::Display, sync::Arc};

Expand Down Expand Up @@ -50,17 +51,20 @@ impl<DB> Executor<DB> for MockExecutorProvider {
type Output = BlockExecutionOutput<Receipt>;
type Error = BlockExecutionError;

fn execute(self, _: Self::Input<'_>) -> Result<Self::Output, Self::Error> {
fn execute(&mut self, _: Self::Input<'_>) -> Result<Self::Output, Self::Error> {
let ExecutionOutcome { bundle, receipts, requests, first_block: _ } =
self.exec_results.lock().pop().unwrap();
Ok(BlockExecutionOutput {
state: bundle,
cache: Default::default(),
receipts: receipts.into_iter().flatten().flatten().collect(),
requests: requests.into_iter().flatten().collect(),
gas_used: 0,
})
}

fn state_ref(&self) -> &State<DB> {
todo!()
}
}

impl<DB> BatchExecutor<DB> for MockExecutorProvider {
Expand Down
2 changes: 1 addition & 1 deletion crates/exex/exex/src/backfill/job.rs
Original file line number Diff line number Diff line change
Expand Up @@ -199,7 +199,7 @@ where
.ok_or_else(|| ProviderError::HeaderNotFound(block_number.into()))?;

// Configure the executor to use the previous block's state.
let executor = self.executor.executor(StateProviderDatabase::new(
let mut executor = self.executor.executor(StateProviderDatabase::new(
self.provider.history_by_block_number(block_number.saturating_sub(1))?,
));

Expand Down
7 changes: 5 additions & 2 deletions crates/optimism/evm/src/execute.rs
Original file line number Diff line number Diff line change
Expand Up @@ -350,7 +350,7 @@ where
/// Returns an error if the block could not be executed or failed verification.
///
/// State changes are committed to the database.
fn execute(mut self, input: Self::Input<'_>) -> Result<Self::Output, Self::Error> {
fn execute(&mut self, input: Self::Input<'_>) -> Result<Self::Output, Self::Error> {
let BlockExecutionInput { block, total_difficulty } = input;
let (receipts, gas_used) = self.execute_without_verification(block, total_difficulty)?;

Expand All @@ -359,12 +359,15 @@ where

Ok(BlockExecutionOutput {
state: self.state.take_bundle(),
cache: core::mem::take(&mut self.state.cache),
receipts,
requests: vec![],
gas_used,
})
}

fn state_ref(&self) -> &State<DB> {
&self.state
}
}

/// An executor for a batch of blocks.
Expand Down
6 changes: 3 additions & 3 deletions crates/rpc/rpc-builder/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1774,7 +1774,7 @@ impl TransportRpcModules {
/// Returns [Ok(false)] if no http transport is configured.
pub fn merge_http(&mut self, other: impl Into<Methods>) -> Result<bool, RegisterMethodError> {
if let Some(ref mut http) = self.http {
return http.merge(other.into()).map(|_| true);
return http.merge(other.into()).map(|_| true)
}
Ok(false)
}
Expand All @@ -1786,7 +1786,7 @@ impl TransportRpcModules {
/// Returns [Ok(false)] if no ws transport is configured.
pub fn merge_ws(&mut self, other: impl Into<Methods>) -> Result<bool, RegisterMethodError> {
if let Some(ref mut ws) = self.ws {
return ws.merge(other.into()).map(|_| true);
return ws.merge(other.into()).map(|_| true)
}
Ok(false)
}
Expand All @@ -1798,7 +1798,7 @@ impl TransportRpcModules {
/// Returns [Ok(false)] if no ipc transport is configured.
pub fn merge_ipc(&mut self, other: impl Into<Methods>) -> Result<bool, RegisterMethodError> {
if let Some(ref mut ipc) = self.ipc {
return ipc.merge(other.into()).map(|_| true);
return ipc.merge(other.into()).map(|_| true)
}
Ok(false)
}
Expand Down
44 changes: 12 additions & 32 deletions crates/rpc/rpc/src/debug.rs
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ use reth_rpc_types::{
Block as RpcBlock, BlockError, Bundle, StateContext, TransactionRequest,
};
use reth_tasks::pool::BlockingTaskGuard;
use reth_trie::{HashedPostState, HashedStorage};
use reth_trie::HashedPostState;
use revm::{
db::CacheDB,
primitives::{db::DatabaseCommit, BlockEnv, CfgEnvWithHandlerCfg, Env, EnvWithHandlerCfg},
Expand Down Expand Up @@ -588,47 +588,27 @@ where
.eth_api
.spawn_with_state_at_block(block.parent_hash.into(), move |state| {
let db = StateProviderDatabase::new(&state);
let block_executor = this.inner.block_executor.executor(db);
let block_execution_output = block_executor
let mut block_executor = this.inner.block_executor.executor(db);
let _ = block_executor
.execute((&block.clone().unseal(), block.difficulty).into())
.map_err(|err| EthApiError::Internal(err.into()))?;

let bundle_state = block_execution_output.state;
let cache_state = block_execution_output.cache;
let cache_state = &block_executor.state_ref().cache;
let hashed_state = HashedPostState::from_cache_state(&cache_state.accounts);

// Initialize a map of preimages.
let mut state_preimages: HashMap<revm_primitives::FixedBytes<32>, Bytes> =
HashMap::new();

// Grab all account proofs for the data accessed during block execution.
//
// Note: We grab *all* accounts in the cache here, as the `BundleState` prunes
// referenced accounts + storage slots.
let mut hashed_state = HashedPostState::from_bundle_state(&bundle_state.state);
for (address, account) in cache_state.accounts {
let hashed_address = keccak256(address);
hashed_state.accounts.insert(
hashed_address,
account.account.as_ref().map(|a| a.info.clone().into()),
);

let storage = hashed_state
.storages
.entry(hashed_address)
.or_insert_with(|| HashedStorage::new(account.status.was_destroyed()));

if let Some(account) = account.account {
if include_preimages {
if include_preimages {
for (address, account) in &cache_state.accounts {
let hashed_address = keccak256(address);
if let Some(account) = &account.account {
state_preimages
.insert(hashed_address, alloy_rlp::encode(address).into());
}

for (slot, value) in account.storage {
let slot = B256::from(slot);
let hashed_slot = keccak256(slot);
storage.storage.insert(hashed_slot, value);

if include_preimages {
for slot in account.storage.keys() {
let slot = B256::from(*slot);
let hashed_slot = keccak256(slot);
state_preimages.insert(hashed_slot, alloy_rlp::encode(slot).into());
}
}
Expand Down
1 change: 0 additions & 1 deletion examples/rpc-db/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -69,7 +69,6 @@ async fn main() -> eyre::Result<()> {
.with_evm_config(EthEvmConfig::new(spec))
.with_events(TestCanonStateSubscriptions::default())
.with_block_executor(EthExecutorProvider::ethereum(provider.chain_spec()));
>>>>>>> 7d9b7e746 (Add block_executor to debug_execution_witness to execute blocks)

// Pick which namespaces to expose.
let config = TransportRpcModuleConfig::default().with_http([RethRpcModule::Eth]);
Expand Down

0 comments on commit 40a9310

Please sign in to comment.