Skip to content

Commit 1e402fa

Browse files
rkrasiukshekhirin
andauthored
feat(root): support proof prefetch in the task (#13428)
Co-authored-by: Alexey Shekhirin <[email protected]>
1 parent 48fee88 commit 1e402fa

File tree

1 file changed

+99
-41
lines changed

1 file changed

+99
-41
lines changed

crates/engine/tree/src/tree/root.rs

Lines changed: 99 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,9 @@
11
//! State root task related functionality.
22
3-
use alloy_primitives::map::HashSet;
3+
use alloy_primitives::{map::HashSet, Address};
44
use derive_more::derive::Deref;
55
use rayon::iter::{ParallelBridge, ParallelIterator};
6-
use reth_errors::ProviderError;
6+
use reth_errors::{ProviderError, ProviderResult};
77
use reth_evm::system_calls::OnStateHook;
88
use reth_provider::{
99
providers::ConsistentDbView, BlockReader, DBProvider, DatabaseProviderFactory,
@@ -108,6 +108,8 @@ impl<Factory> StateRootConfig<Factory> {
108108
#[derive(Debug)]
109109
#[allow(dead_code)]
110110
pub enum StateRootMessage<BPF: BlindedProviderFactory> {
111+
/// Prefetch proof targets
112+
PrefetchProofs(HashSet<Address>),
111113
/// New state update from transaction execution
112114
StateUpdate(EvmState),
113115
/// Proof calculation completed for a specific state update
@@ -340,6 +342,29 @@ where
340342
}
341343
}
342344

345+
/// Handles request for proof prefetch.
346+
fn on_prefetch_proof(
347+
scope: &rayon::Scope<'env>,
348+
config: StateRootConfig<Factory>,
349+
targets: HashSet<Address>,
350+
fetched_proof_targets: &mut MultiProofTargets,
351+
proof_sequence_number: u64,
352+
state_root_message_sender: Sender<StateRootMessage<BPF>>,
353+
) {
354+
let proof_targets =
355+
targets.into_iter().map(|address| (keccak256(address), Default::default())).collect();
356+
extend_multi_proof_targets_ref(fetched_proof_targets, &proof_targets);
357+
358+
Self::spawn_multiproof(
359+
scope,
360+
config,
361+
Default::default(),
362+
proof_targets,
363+
proof_sequence_number,
364+
state_root_message_sender,
365+
);
366+
}
367+
343368
/// Handles state updates.
344369
///
345370
/// Returns proof targets derived from the state update.
@@ -356,46 +381,39 @@ where
356381
let proof_targets = get_proof_targets(&hashed_state_update, fetched_proof_targets);
357382
extend_multi_proof_targets_ref(fetched_proof_targets, &proof_targets);
358383

384+
Self::spawn_multiproof(
385+
scope,
386+
config,
387+
hashed_state_update,
388+
proof_targets,
389+
proof_sequence_number,
390+
state_root_message_sender,
391+
);
392+
}
393+
394+
fn spawn_multiproof(
395+
scope: &rayon::Scope<'env>,
396+
config: StateRootConfig<Factory>,
397+
hashed_state_update: HashedPostState,
398+
proof_targets: MultiProofTargets,
399+
proof_sequence_number: u64,
400+
state_root_message_sender: Sender<StateRootMessage<BPF>>,
401+
) {
359402
// Dispatch proof gathering for this state update
360-
scope.spawn(move |_| {
361-
let provider = match config.consistent_view.provider_ro() {
362-
Ok(provider) => provider,
363-
Err(error) => {
364-
error!(target: "engine::root", ?error, "Could not get provider");
365-
let _ = state_root_message_sender
366-
.send(StateRootMessage::ProofCalculationError(error));
367-
return;
368-
}
369-
};
370-
371-
// TODO: replace with parallel proof
372-
let result = Proof::from_tx(provider.tx_ref())
373-
.with_trie_cursor_factory(InMemoryTrieCursorFactory::new(
374-
DatabaseTrieCursorFactory::new(provider.tx_ref()),
375-
&config.nodes_sorted,
376-
))
377-
.with_hashed_cursor_factory(HashedPostStateCursorFactory::new(
378-
DatabaseHashedCursorFactory::new(provider.tx_ref()),
379-
&config.state_sorted,
380-
))
381-
.with_prefix_sets_mut(config.prefix_sets.as_ref().clone())
382-
.with_branch_node_hash_masks(true)
383-
.multiproof(proof_targets.clone());
384-
match result {
385-
Ok(proof) => {
386-
let _ = state_root_message_sender.send(StateRootMessage::ProofCalculated(
387-
Box::new(ProofCalculated {
388-
state_update: hashed_state_update,
389-
targets: proof_targets,
390-
proof,
391-
sequence_number: proof_sequence_number,
392-
}),
393-
));
394-
}
395-
Err(error) => {
396-
let _ = state_root_message_sender
397-
.send(StateRootMessage::ProofCalculationError(error.into()));
398-
}
403+
scope.spawn(move |_| match calculate_multiproof(config, proof_targets.clone()) {
404+
Ok(proof) => {
405+
let _ = state_root_message_sender.send(StateRootMessage::ProofCalculated(
406+
Box::new(ProofCalculated {
407+
state_update: hashed_state_update,
408+
targets: proof_targets,
409+
proof,
410+
sequence_number: proof_sequence_number,
411+
}),
412+
));
413+
}
414+
Err(error) => {
415+
let _ =
416+
state_root_message_sender.send(StateRootMessage::ProofCalculationError(error));
399417
}
400418
});
401419
}
@@ -486,6 +504,21 @@ where
486504
loop {
487505
match self.rx.recv() {
488506
Ok(message) => match message {
507+
StateRootMessage::PrefetchProofs(targets) => {
508+
debug!(
509+
target: "engine::root",
510+
len = targets.len(),
511+
"Prefetching proofs"
512+
);
513+
Self::on_prefetch_proof(
514+
scope,
515+
self.config.clone(),
516+
targets,
517+
&mut self.fetched_proof_targets,
518+
self.proof_sequencer.next_sequence(),
519+
self.tx.clone(),
520+
);
521+
}
489522
StateRootMessage::StateUpdate(update) => {
490523
if updates_received == 0 {
491524
first_update_time = Some(Instant::now());
@@ -681,6 +714,31 @@ fn get_proof_targets(
681714
targets
682715
}
683716

717+
/// Calculate multiproof for the targets.
718+
#[inline]
719+
fn calculate_multiproof<Factory>(
720+
config: StateRootConfig<Factory>,
721+
proof_targets: MultiProofTargets,
722+
) -> ProviderResult<MultiProof>
723+
where
724+
Factory: DatabaseProviderFactory<Provider: BlockReader> + StateCommitmentProvider,
725+
{
726+
let provider = config.consistent_view.provider_ro()?;
727+
728+
Ok(Proof::from_tx(provider.tx_ref())
729+
.with_trie_cursor_factory(InMemoryTrieCursorFactory::new(
730+
DatabaseTrieCursorFactory::new(provider.tx_ref()),
731+
&config.nodes_sorted,
732+
))
733+
.with_hashed_cursor_factory(HashedPostStateCursorFactory::new(
734+
DatabaseHashedCursorFactory::new(provider.tx_ref()),
735+
&config.state_sorted,
736+
))
737+
.with_prefix_sets_mut(config.prefix_sets.as_ref().clone())
738+
.with_branch_node_hash_masks(true)
739+
.multiproof(proof_targets)?)
740+
}
741+
684742
/// Updates the sparse trie with the given proofs and state, and returns the updated trie and the
685743
/// time it took.
686744
fn update_sparse_trie<

0 commit comments

Comments
 (0)