Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

refactor(evm): set prune modes optionally for the batch executor #9176

Merged
merged 3 commits into from
Jul 3, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 4 additions & 6 deletions bin/reth/src/commands/debug_cmd/merkle.rs
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,6 @@ use reth_provider::{
BlockNumReader, BlockWriter, ChainSpecProvider, HeaderProvider, LatestStateProviderRef,
OriginalValuesKnown, ProviderError, ProviderFactory, StateWriter,
};
use reth_prune::PruneModes;
use reth_revm::database::StateProviderDatabase;
use reth_stages::{
stages::{AccountHashingStage, MerkleStage, StorageHashingStage},
Expand Down Expand Up @@ -148,13 +147,12 @@ impl Command {
provider_rw.insert_block(sealed_block.clone(), None)?;

td += sealed_block.difficulty;
let mut executor = executor_provider.batch_executor(
StateProviderDatabase::new(LatestStateProviderRef::new(
let mut executor = executor_provider.batch_executor(StateProviderDatabase::new(
LatestStateProviderRef::new(
provider_rw.tx_ref(),
provider_rw.static_file_provider().clone(),
)),
PruneModes::none(),
);
),
));
executor.execute_and_verify_one((&sealed_block.clone().unseal(), td).into())?;
executor.finalize().write_to_storage(
provider_rw.tx_ref(),
Expand Down
34 changes: 15 additions & 19 deletions crates/ethereum/evm/src/execute.rs
Original file line number Diff line number Diff line change
Expand Up @@ -93,14 +93,14 @@ where
self.eth_executor(db)
}

fn batch_executor<DB>(&self, db: DB, prune_modes: PruneModes) -> Self::BatchExecutor<DB>
fn batch_executor<DB>(&self, db: DB) -> Self::BatchExecutor<DB>
where
DB: Database<Error: Into<ProviderError> + Display>,
{
let executor = self.eth_executor(db);
EthBatchExecutor {
executor,
batch_record: BlockBatchRecord::new(prune_modes),
batch_record: BlockBatchRecord::default(),
stats: BlockExecutorStats::default(),
}
}
Expand Down Expand Up @@ -451,6 +451,10 @@ where
self.batch_record.set_tip(tip);
}

fn set_prune_modes(&mut self, prune_modes: PruneModes) {
self.batch_record.set_prune_modes(prune_modes);
}
Comment on lines +454 to +456
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this should not be part of the interface at all.

none of the pruning stuff should happen in the executor itself, this is just weird.


fn size_hint(&self) -> Option<usize> {
Some(self.executor.state.bundle_state.size_hint())
}
Expand Down Expand Up @@ -634,7 +638,7 @@ mod tests {

// attempt to execute an empty block with parent beacon block root, this should not fail
provider
.batch_executor(StateProviderDatabase::new(&db), PruneModes::none())
.batch_executor(StateProviderDatabase::new(&db))
.execute_and_verify_one(
(
&BlockWithSenders {
Expand Down Expand Up @@ -684,8 +688,7 @@ mod tests {
..Header::default()
};

let mut executor =
provider.batch_executor(StateProviderDatabase::new(&db), PruneModes::none());
let mut executor = provider.batch_executor(StateProviderDatabase::new(&db));

// attempt to execute an empty block with parent beacon block root, this should not fail
executor
Expand Down Expand Up @@ -728,8 +731,7 @@ mod tests {

let mut header = chain_spec.genesis_header();
let provider = executor_provider(chain_spec);
let mut executor =
provider.batch_executor(StateProviderDatabase::new(&db), PruneModes::none());
let mut executor = provider.batch_executor(StateProviderDatabase::new(&db));

// attempt to execute the genesis block with non-zero parent beacon block root, expect err
header.parent_beacon_block_root = Some(B256::with_last_byte(0x69));
Expand Down Expand Up @@ -816,8 +818,7 @@ mod tests {
let provider = executor_provider(chain_spec);

// execute header
let mut executor =
provider.batch_executor(StateProviderDatabase::new(&db), PruneModes::none());
let mut executor = provider.batch_executor(StateProviderDatabase::new(&db));

// Now execute a block with the fixed header, ensure that it does not fail
executor
Expand Down Expand Up @@ -884,8 +885,7 @@ mod tests {
);

let provider = executor_provider(chain_spec);
let mut executor =
provider.batch_executor(StateProviderDatabase::new(&db), PruneModes::none());
let mut executor = provider.batch_executor(StateProviderDatabase::new(&db));

// construct the header for block one
let header = Header { timestamp: 1, number: 1, ..Header::default() };
Expand Down Expand Up @@ -938,8 +938,7 @@ mod tests {

let header = chain_spec.genesis_header();
let provider = executor_provider(chain_spec);
let mut executor =
provider.batch_executor(StateProviderDatabase::new(&db), PruneModes::none());
let mut executor = provider.batch_executor(StateProviderDatabase::new(&db));

// attempt to execute genesis block, this should not fail
executor
Expand Down Expand Up @@ -996,8 +995,7 @@ mod tests {
..Header::default()
};
let provider = executor_provider(chain_spec);
let mut executor =
provider.batch_executor(StateProviderDatabase::new(&db), PruneModes::none());
let mut executor = provider.batch_executor(StateProviderDatabase::new(&db));

// attempt to execute the fork activation block, this should not fail
executor
Expand Down Expand Up @@ -1052,8 +1050,7 @@ mod tests {
);

let provider = executor_provider(chain_spec);
let mut executor =
provider.batch_executor(StateProviderDatabase::new(&db), PruneModes::none());
let mut executor = provider.batch_executor(StateProviderDatabase::new(&db));

let header = Header {
parent_hash: B256::random(),
Expand Down Expand Up @@ -1115,8 +1112,7 @@ mod tests {
let header_hash = header.hash_slow();

let provider = executor_provider(chain_spec);
let mut executor =
provider.batch_executor(StateProviderDatabase::new(&db), PruneModes::none());
let mut executor = provider.batch_executor(StateProviderDatabase::new(&db));

// attempt to execute the genesis block, this should not fail
executor
Expand Down
13 changes: 10 additions & 3 deletions crates/evm/src/either.rs
Original file line number Diff line number Diff line change
Expand Up @@ -36,13 +36,13 @@ where
}
}

fn batch_executor<DB>(&self, db: DB, prune_modes: PruneModes) -> Self::BatchExecutor<DB>
fn batch_executor<DB>(&self, db: DB) -> Self::BatchExecutor<DB>
where
DB: Database<Error: Into<ProviderError> + Display>,
{
match self {
Self::Left(a) => Either::Left(a.batch_executor(db, prune_modes)),
Self::Right(b) => Either::Right(b.batch_executor(db, prune_modes)),
Self::Left(a) => Either::Left(a.batch_executor(db)),
Self::Right(b) => Either::Right(b.batch_executor(db)),
}
}
}
Expand Down Expand Up @@ -116,6 +116,13 @@ where
}
}

fn set_prune_modes(&mut self, prune_modes: PruneModes) {
match self {
Self::Left(a) => a.set_prune_modes(prune_modes),
Self::Right(b) => b.set_prune_modes(prune_modes),
}
}

fn size_hint(&self) -> Option<usize> {
match self {
Self::Left(a) => a.size_hint(),
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 @@ -85,6 +85,11 @@ pub trait BatchExecutor<DB> {
/// This can be used to optimize state pruning during execution.
fn set_tip(&mut self, tip: BlockNumber);

/// Set the prune modes.
///
/// They are used to determine which parts of the state should be kept during execution.
fn set_prune_modes(&mut self, prune_modes: PruneModes);
Comment on lines +88 to +91
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this is more or less the same thing just with extra steps


/// The size hint of the batch's tracked state size.
///
/// This is used to optimize DB commits depending on the size of the state.
Expand Down Expand Up @@ -169,10 +174,7 @@ pub trait BlockExecutorProvider: Send + Sync + Clone + Unpin + 'static {
///
/// Batch executor is used to execute multiple blocks in sequence and keep track of the state
/// during historical sync which involves executing multiple blocks in sequence.
///
/// The pruning modes are used to determine which parts of the state should be kept during
/// execution.
fn batch_executor<DB>(&self, db: DB, prune_modes: PruneModes) -> Self::BatchExecutor<DB>
fn batch_executor<DB>(&self, db: DB) -> Self::BatchExecutor<DB>
where
DB: Database<Error: Into<ProviderError> + Display>;
}
Expand All @@ -198,7 +200,7 @@ mod tests {
TestExecutor(PhantomData)
}

fn batch_executor<DB>(&self, _db: DB, _prune_modes: PruneModes) -> Self::BatchExecutor<DB>
fn batch_executor<DB>(&self, _db: DB) -> Self::BatchExecutor<DB>
where
DB: Database<Error: Into<ProviderError> + Display>,
{
Expand Down Expand Up @@ -235,6 +237,10 @@ mod tests {
todo!()
}

fn set_prune_modes(&mut self, _prune_modes: PruneModes) {
todo!()
}

fn size_hint(&self) -> Option<usize> {
None
}
Expand Down
4 changes: 3 additions & 1 deletion crates/evm/src/noop.rs
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ impl BlockExecutorProvider for NoopBlockExecutorProvider {
Self
}

fn batch_executor<DB>(&self, _: DB, _: PruneModes) -> Self::BatchExecutor<DB>
fn batch_executor<DB>(&self, _: DB) -> Self::BatchExecutor<DB>
where
DB: Database<Error: Into<ProviderError> + Display>,
{
Expand Down Expand Up @@ -65,6 +65,8 @@ impl<DB> BatchExecutor<DB> for NoopBlockExecutorProvider {

fn set_tip(&mut self, _: BlockNumber) {}

fn set_prune_modes(&mut self, _: PruneModes) {}

fn size_hint(&self) -> Option<usize> {
None
}
Expand Down
4 changes: 3 additions & 1 deletion crates/evm/src/test_utils.rs
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ impl BlockExecutorProvider for MockExecutorProvider {
self.clone()
}

fn batch_executor<DB>(&self, _: DB, _: PruneModes) -> Self::BatchExecutor<DB>
fn batch_executor<DB>(&self, _: DB) -> Self::BatchExecutor<DB>
where
DB: Database<Error: Into<ProviderError> + Display>,
{
Expand Down Expand Up @@ -77,6 +77,8 @@ impl<DB> BatchExecutor<DB> for MockExecutorProvider {

fn set_tip(&mut self, _: BlockNumber) {}

fn set_prune_modes(&mut self, _: PruneModes) {}

fn size_hint(&self) -> Option<usize> {
None
}
Expand Down
54 changes: 27 additions & 27 deletions crates/exex/exex/src/backfill.rs
Original file line number Diff line number Diff line change
Expand Up @@ -24,8 +24,19 @@ pub struct BackfillJobFactory<E, P> {

impl<E, P> BackfillJobFactory<E, P> {
/// Creates a new [`BackfillJobFactory`].
pub fn new(executor: E, provider: P, prune_modes: PruneModes) -> Self {
Self { executor, provider, prune_modes, thresholds: ExecutionStageThresholds::default() }
pub fn new(executor: E, provider: P) -> Self {
Self {
executor,
provider,
prune_modes: PruneModes::none(),
thresholds: ExecutionStageThresholds::default(),
}
}

/// Sets the prune modes
pub fn with_prune_modes(mut self, prune_modes: PruneModes) -> Self {
self.prune_modes = prune_modes;
self
}

/// Sets the thresholds
Expand Down Expand Up @@ -53,12 +64,10 @@ impl BackfillJobFactory<(), ()> {
/// Creates a new [`BackfillJobFactory`] from [`FullNodeComponents`].
pub fn new_from_components<Node: FullNodeComponents>(
components: Node,
prune_modes: PruneModes,
) -> BackfillJobFactory<Node::Executor, Node::Provider> {
BackfillJobFactory::<_, _>::new(
components.block_executor().clone(),
components.provider().clone(),
prune_modes,
)
}
}
Expand All @@ -72,8 +81,8 @@ pub struct BackfillJob<E, DB, P> {
executor: E,
provider: P,
prune_modes: PruneModes,
range: RangeInclusive<BlockNumber>,
thresholds: ExecutionStageThresholds,
range: RangeInclusive<BlockNumber>,
_db: PhantomData<DB>,
}

Expand Down Expand Up @@ -101,12 +110,10 @@ where
P: FullProvider<DB>,
{
fn execute_range(&mut self) -> Result<Chain, BlockExecutionError> {
let mut executor = self.executor.batch_executor(
StateProviderDatabase::new(
self.provider.history_by_block_number(self.range.start().saturating_sub(1))?,
),
self.prune_modes.clone(),
);
let mut executor = self.executor.batch_executor(StateProviderDatabase::new(
self.provider.history_by_block_number(self.range.start().saturating_sub(1))?,
));
executor.set_prune_modes(self.prune_modes.clone());

let mut fetch_block_duration = Duration::default();
let mut execution_duration = Duration::default();
Expand Down Expand Up @@ -204,7 +211,6 @@ mod tests {
providers::BlockchainProvider, test_utils::create_test_provider_factory_with_chain_spec,
BlockWriter, LatestStateProviderRef,
};
use reth_prune_types::PruneModes;
use reth_revm::database::StateProviderDatabase;
use reth_testing_utils::generators::{self, sign_tx_with_key_pair};
use secp256k1::Keypair;
Expand Down Expand Up @@ -288,24 +294,18 @@ mod tests {
let provider = provider_factory.provider()?;
// Execute only the first block on top of genesis state
let mut outcome_single = EthExecutorProvider::ethereum(chain_spec.clone())
.batch_executor(
StateProviderDatabase::new(LatestStateProviderRef::new(
provider.tx_ref(),
provider.static_file_provider().clone(),
)),
PruneModes::none(),
)
.batch_executor(StateProviderDatabase::new(LatestStateProviderRef::new(
provider.tx_ref(),
provider.static_file_provider().clone(),
)))
.execute_and_verify_batch([(&block1, U256::ZERO).into()])?;
outcome_single.bundle.reverts.sort();
// Execute both blocks on top of the genesis state
let outcome_batch = EthExecutorProvider::ethereum(chain_spec)
.batch_executor(
StateProviderDatabase::new(LatestStateProviderRef::new(
provider.tx_ref(),
provider.static_file_provider().clone(),
)),
PruneModes::none(),
)
.batch_executor(StateProviderDatabase::new(LatestStateProviderRef::new(
provider.tx_ref(),
provider.static_file_provider().clone(),
)))
.execute_and_verify_batch([
(&block1, U256::ZERO).into(),
(&block2, U256::ZERO).into(),
Expand All @@ -327,7 +327,7 @@ mod tests {
provider_rw.commit()?;

// Backfill the first block
let factory = BackfillJobFactory::new(executor, blockchain_db, PruneModes::none());
let factory = BackfillJobFactory::new(executor, blockchain_db);
let job = factory.backfill(1..=1);
let chains = job.collect::<Result<Vec<_>, _>>()?;

Expand Down
Loading
Loading