reth_snap_sync/generation.rs
1//! Identifies one attempt at downloading state, and how far it has progressed.
2
3use crate::SnapSyncError;
4use alloy_eips::BlockNumHash;
5use alloy_primitives::B256;
6use reth_storage_api::HeaderProvider;
7
8/// One attempt at downloading state, anchored to the pivot block it targets.
9///
10/// The anchor is kept as both a number-hash pair and a state root: the hash decides whether the
11/// attempt is still on the canonical chain, and the root is what downloaded ranges authenticate
12/// against.
13#[derive(Clone, Copy, Debug, Eq, PartialEq)]
14pub struct SnapGeneration {
15 // Pivot block this attempt is anchored to.
16 target: BlockNumHash,
17 // Root downloaded ranges authenticate against.
18 state_root: B256,
19 // Stage reached so far.
20 phase: SnapPhase,
21}
22
23impl SnapGeneration {
24 /// Creates a generation anchored to the given pivot, before any range is downloaded.
25 pub const fn new(target: BlockNumHash, state_root: B256) -> Self {
26 Self { target, state_root, phase: SnapPhase::Accounts }
27 }
28
29 /// Pivot block this generation is anchored to.
30 pub const fn target(&self) -> BlockNumHash {
31 self.target
32 }
33
34 /// State root that downloaded ranges authenticate against.
35 pub const fn state_root(&self) -> B256 {
36 self.state_root
37 }
38
39 /// Stage this generation has reached.
40 pub const fn phase(&self) -> SnapPhase {
41 self.phase
42 }
43
44 /// Returns how far the canonical head has moved past this generation's anchor.
45 pub const fn lag(&self, head: u64) -> u64 {
46 head.saturating_sub(self.target.number)
47 }
48
49 /// Returns whether the block this generation is anchored to is still canonical.
50 ///
51 /// Separate from whether it is worth finishing: an orphaned anchor is recoverable from the
52 /// abandoned branch's lists.
53 pub fn is_canonical(&self, provider: &impl HeaderProvider) -> Result<bool, SnapSyncError> {
54 let header = provider.sealed_header(self.target.number)?;
55 Ok(header.is_some_and(|header| header.hash() == self.target.hash))
56 }
57
58 /// Returns this generation moved to `phase`.
59 #[cfg(test)]
60 pub(crate) const fn with_phase(mut self, phase: SnapPhase) -> Self {
61 self.phase = phase;
62 self
63 }
64}
65
66/// The stage a [`SnapGeneration`] has reached.
67#[derive(Clone, Copy, Debug, Eq, PartialEq)]
68pub enum SnapPhase {
69 /// Account, storage and bytecode ranges are being downloaded.
70 Accounts,
71 /// Authenticated block access lists are being applied.
72 BlockAccessLists,
73 /// The final state trie is being rebuilt and checked.
74 Trie,
75}