perf: Skip state root calculation

This commit is contained in:
sprites0
2025-03-10 23:14:45 +00:00
parent a5e51afb36
commit 7fe7c06507
3 changed files with 22 additions and 94 deletions

View File

@ -195,6 +195,7 @@ pub enum StateRootMessage {
} }
/// Message about completion of proof calculation for a specific state update /// Message about completion of proof calculation for a specific state update
#[allow(dead_code)]
#[derive(Debug)] #[derive(Debug)]
pub struct ProofCalculated { pub struct ProofCalculated {
/// The index of this proof in the sequence of state updates /// The index of this proof in the sequence of state updates
@ -255,7 +256,7 @@ impl ProofSequencer {
// return early if we don't have the next expected proof // return early if we don't have the next expected proof
if !self.pending_proofs.contains_key(&self.next_to_deliver) { if !self.pending_proofs.contains_key(&self.next_to_deliver) {
return Vec::new() return Vec::new();
} }
let mut consecutive_proofs = Vec::with_capacity(self.pending_proofs.len()); let mut consecutive_proofs = Vec::with_capacity(self.pending_proofs.len());
@ -390,7 +391,7 @@ where
sequence_number: input.proof_sequence_number, sequence_number: input.proof_sequence_number,
state: input.hashed_state_update, state: input.hashed_state_update,
}); });
return return;
} }
if self.inflight >= self.max_concurrent { if self.inflight >= self.max_concurrent {
@ -480,10 +481,13 @@ where
#[metrics(scope = "tree.root")] #[metrics(scope = "tree.root")]
struct StateRootTaskMetrics { struct StateRootTaskMetrics {
/// Histogram of proof calculation durations. /// Histogram of proof calculation durations.
#[allow(unused)]
pub proof_calculation_duration_histogram: Histogram, pub proof_calculation_duration_histogram: Histogram,
/// Histogram of proof calculation account targets. /// Histogram of proof calculation account targets.
#[allow(unused)]
pub proof_calculation_account_targets_histogram: Histogram, pub proof_calculation_account_targets_histogram: Histogram,
/// Histogram of proof calculation storage targets. /// Histogram of proof calculation storage targets.
#[allow(unused)]
pub proof_calculation_storage_targets_histogram: Histogram, pub proof_calculation_storage_targets_histogram: Histogram,
/// Histogram of sparse trie update durations. /// Histogram of sparse trie update durations.
@ -492,10 +496,13 @@ struct StateRootTaskMetrics {
pub sparse_trie_final_update_duration_histogram: Histogram, pub sparse_trie_final_update_duration_histogram: Histogram,
/// Histogram of state updates received. /// Histogram of state updates received.
#[allow(unused)]
pub state_updates_received_histogram: Histogram, pub state_updates_received_histogram: Histogram,
/// Histogram of proofs processed. /// Histogram of proofs processed.
#[allow(unused)]
pub proofs_processed_histogram: Histogram, pub proofs_processed_histogram: Histogram,
/// Histogram of state root update iterations. /// Histogram of state root update iterations.
#[allow(unused)]
pub state_root_iterations_histogram: Histogram, pub state_root_iterations_histogram: Histogram,
/// Histogram of the number of updated state nodes. /// Histogram of the number of updated state nodes.
@ -531,6 +538,7 @@ pub struct StateRootTask<Factory> {
/// Task configuration. /// Task configuration.
config: StateRootConfig<Factory>, config: StateRootConfig<Factory>,
/// Receiver for state root related messages. /// Receiver for state root related messages.
#[allow(unused)]
rx: Receiver<StateRootMessage>, rx: Receiver<StateRootMessage>,
/// Sender for state root related messages. /// Sender for state root related messages.
tx: Sender<StateRootMessage>, tx: Sender<StateRootMessage>,
@ -539,6 +547,7 @@ pub struct StateRootTask<Factory> {
/// Proof sequencing handler. /// Proof sequencing handler.
proof_sequencer: ProofSequencer, proof_sequencer: ProofSequencer,
/// Reference to the shared thread pool for parallel proof generation. /// Reference to the shared thread pool for parallel proof generation.
#[allow(unused)]
thread_pool: Arc<rayon::ThreadPool>, thread_pool: Arc<rayon::ThreadPool>,
/// Manages calculation of multiproofs. /// Manages calculation of multiproofs.
multiproof_manager: MultiproofManager<Factory>, multiproof_manager: MultiproofManager<Factory>,
@ -591,12 +600,6 @@ where
/// Spawns the state root task and returns a handle to await its result. /// Spawns the state root task and returns a handle to await its result.
pub fn spawn(self) -> StateRootHandle { pub fn spawn(self) -> StateRootHandle {
let sparse_trie_tx = Self::spawn_sparse_trie(
self.thread_pool.clone(),
self.config.clone(),
self.metrics.clone(),
self.tx.clone(),
);
let (tx, rx) = mpsc::sync_channel(1); let (tx, rx) = mpsc::sync_channel(1);
std::thread::Builder::new() std::thread::Builder::new()
.name("State Root Task".to_string()) .name("State Root Task".to_string())
@ -605,8 +608,11 @@ where
self.observe_config(); self.observe_config();
let result = self.run(sparse_trie_tx); let _ = tx.send(Ok(StateRootComputeOutcome {
let _ = tx.send(result); state_root: (B256::default(), Default::default()),
total_time: Duration::default(),
time_from_last_update: Duration::default(),
}));
}) })
.expect("failed to spawn state root thread"); .expect("failed to spawn state root thread");
@ -614,6 +620,7 @@ where
} }
/// Logs and records in metrics the state root config parameters. /// Logs and records in metrics the state root config parameters.
#[allow(unused)]
fn observe_config(&self) { fn observe_config(&self) {
let nodes_sorted_account_nodes = self.config.nodes_sorted.account_nodes.len(); let nodes_sorted_account_nodes = self.config.nodes_sorted.account_nodes.len();
let nodes_sorted_removed_nodes = self.config.nodes_sorted.removed_nodes.len(); let nodes_sorted_removed_nodes = self.config.nodes_sorted.removed_nodes.len();
@ -659,6 +666,7 @@ where
} }
/// Spawn long running sparse trie task that forwards the final result upon completion. /// Spawn long running sparse trie task that forwards the final result upon completion.
#[allow(unused)]
fn spawn_sparse_trie( fn spawn_sparse_trie(
thread_pool: Arc<rayon::ThreadPool>, thread_pool: Arc<rayon::ThreadPool>,
config: StateRootConfig<Factory>, config: StateRootConfig<Factory>,
@ -682,6 +690,7 @@ where
} }
/// Handles request for proof prefetch. /// Handles request for proof prefetch.
#[allow(unused)]
fn on_prefetch_proof(&mut self, targets: MultiProofTargets) { fn on_prefetch_proof(&mut self, targets: MultiProofTargets) {
let proof_targets = self.get_prefetch_proof_targets(targets); let proof_targets = self.get_prefetch_proof_targets(targets);
extend_multi_proof_targets_ref(&mut self.fetched_proof_targets, &proof_targets); extend_multi_proof_targets_ref(&mut self.fetched_proof_targets, &proof_targets);
@ -697,6 +706,7 @@ where
} }
/// Calls `get_proof_targets` with existing proof targets for prefetching. /// Calls `get_proof_targets` with existing proof targets for prefetching.
#[allow(unused)]
fn get_prefetch_proof_targets(&self, mut targets: MultiProofTargets) -> MultiProofTargets { fn get_prefetch_proof_targets(&self, mut targets: MultiProofTargets) -> MultiProofTargets {
// Here we want to filter out any targets that are already fetched // Here we want to filter out any targets that are already fetched
// //
@ -726,7 +736,7 @@ where
let Some(fetched_storage) = self.fetched_proof_targets.get(hashed_address) else { let Some(fetched_storage) = self.fetched_proof_targets.get(hashed_address) else {
// this means the account has not been fetched yet, so we must fetch everything // this means the account has not been fetched yet, so we must fetch everything
// associated with this account // associated with this account
continue continue;
}; };
let prev_target_storage_len = target_storage.len(); let prev_target_storage_len = target_storage.len();
@ -749,6 +759,7 @@ where
/// Handles state updates. /// Handles state updates.
/// ///
/// Returns proof targets derived from the state update. /// Returns proof targets derived from the state update.
#[allow(unused)]
fn on_state_update( fn on_state_update(
&mut self, &mut self,
source: StateChangeSource, source: StateChangeSource,

View File

@ -279,8 +279,6 @@ where
// Reset the checkpoint // Reset the checkpoint
self.save_execution_checkpoint(provider, None)?; self.save_execution_checkpoint(provider, None)?;
validate_state_root(trie_root, SealedHeader::seal_slow(target_block), to_block)?;
Ok(ExecOutput { Ok(ExecOutput {
checkpoint: StageCheckpoint::new(to_block) checkpoint: StageCheckpoint::new(to_block)
.with_entities_stage_checkpoint(entities_checkpoint), .with_entities_stage_checkpoint(entities_checkpoint),
@ -327,13 +325,6 @@ where
let (block_root, updates) = StateRoot::incremental_root_with_updates(tx, range) let (block_root, updates) = StateRoot::incremental_root_with_updates(tx, range)
.map_err(|e| StageError::Fatal(Box::new(e)))?; .map_err(|e| StageError::Fatal(Box::new(e)))?;
// Validate the calculated state root
let target = provider
.header_by_number(input.unwind_to)?
.ok_or_else(|| ProviderError::HeaderNotFound(input.unwind_to.into()))?;
validate_state_root(block_root, SealedHeader::seal_slow(target), input.unwind_to)?;
// Validation passed, apply unwind changes to the database. // Validation passed, apply unwind changes to the database.
provider.write_trie_updates(&updates)?; provider.write_trie_updates(&updates)?;
@ -344,26 +335,6 @@ where
} }
} }
/// Check that the computed state root matches the root in the expected header.
#[inline]
fn validate_state_root<H: BlockHeader + Sealable + Debug>(
got: B256,
expected: SealedHeader<H>,
target_block: BlockNumber,
) -> Result<(), StageError> {
if got == expected.state_root() {
Ok(())
} else {
error!(target: "sync::stages::merkle", ?target_block, ?got, ?expected, "Failed to verify block state root! {INVALID_STATE_ROOT_ERROR_MESSAGE}");
Err(StageError::Block {
error: BlockErrorKind::Validation(ConsensusError::BodyStateRootDiff(
GotExpected { got, expected: expected.state_root() }.into(),
)),
block: Box::new(expected.block_with_parent()),
})
}
}
#[cfg(test)] #[cfg(test)]
mod tests { mod tests {
use super::*; use super::*;

View File

@ -547,60 +547,6 @@ where
Ok(()) Ok(())
} }
/// Computes the state root (from scratch) based on the accounts and storages present in the
/// database.
fn compute_state_root<Provider>(provider: &Provider) -> eyre::Result<B256>
where
Provider: DBProvider<Tx: DbTxMut> + TrieWriter,
{
trace!(target: "reth::cli", "Computing state root");
let tx = provider.tx_ref();
let mut intermediate_state: Option<IntermediateStateRootState> = None;
let mut total_flushed_updates = 0;
loop {
match StateRootComputer::from_tx(tx)
.with_intermediate_state(intermediate_state)
.root_with_progress()?
{
StateRootProgress::Progress(state, _, updates) => {
let updated_len = provider.write_trie_updates(&updates)?;
total_flushed_updates += updated_len;
trace!(target: "reth::cli",
last_account_key = %state.last_account_key,
updated_len,
total_flushed_updates,
"Flushing trie updates"
);
intermediate_state = Some(*state);
if total_flushed_updates % SOFT_LIMIT_COUNT_FLUSHED_UPDATES == 0 {
info!(target: "reth::cli",
total_flushed_updates,
"Flushing trie updates"
);
}
}
StateRootProgress::Complete(root, _, updates) => {
let updated_len = provider.write_trie_updates(&updates)?;
total_flushed_updates += updated_len;
trace!(target: "reth::cli",
%root,
updated_len,
total_flushed_updates,
"State root has been computed"
);
return Ok(root)
}
}
}
}
/// Type to deserialize state root from state dump file. /// Type to deserialize state root from state dump file.
#[derive(Debug, Serialize, Deserialize, PartialEq, Eq)] #[derive(Debug, Serialize, Deserialize, PartialEq, Eq)]
struct StateRoot { struct StateRoot {