node/transition_frontier/sync/ledger/
transition_frontier_sync_ledger_state.rs

1use std::collections::BTreeMap;
2
3use mina_p2p_messages::v2::{MinaStateProtocolStateValueStableV2, StateHash};
4use redux::Timestamp;
5use serde::{Deserialize, Serialize};
6
7use super::{
8    snarked::TransitionFrontierSyncLedgerSnarkedState,
9    staged::TransitionFrontierSyncLedgerStagedState, SyncLedgerTarget, SyncLedgerTargetKind,
10};
11
12#[derive(derive_more::From, Serialize, Deserialize, Debug, Clone)]
13pub enum TransitionFrontierSyncLedgerState {
14    Init {
15        time: Timestamp,
16        target: SyncLedgerTarget,
17    },
18    #[from]
19    Snarked(TransitionFrontierSyncLedgerSnarkedState),
20    #[from]
21    Staged(TransitionFrontierSyncLedgerStagedState),
22    Success {
23        time: Timestamp,
24        target: SyncLedgerTarget,
25        needed_protocol_states: BTreeMap<StateHash, MinaStateProtocolStateValueStableV2>,
26    },
27}
28
29impl TransitionFrontierSyncLedgerState {
30    pub fn snarked(&self) -> Option<&TransitionFrontierSyncLedgerSnarkedState> {
31        match self {
32            Self::Snarked(v) => Some(v),
33            _ => None,
34        }
35    }
36
37    pub fn snarked_mut(&mut self) -> Option<&mut TransitionFrontierSyncLedgerSnarkedState> {
38        match self {
39            Self::Snarked(v) => Some(v),
40            _ => None,
41        }
42    }
43
44    pub fn staged(&self) -> Option<&TransitionFrontierSyncLedgerStagedState> {
45        match self {
46            Self::Staged(v) => Some(v),
47            _ => None,
48        }
49    }
50
51    pub fn staged_mut(&mut self) -> Option<&mut TransitionFrontierSyncLedgerStagedState> {
52        match self {
53            Self::Staged(v) => Some(v),
54            _ => None,
55        }
56    }
57
58    pub fn is_snarked_ledger_synced(&self) -> bool {
59        match self {
60            Self::Init { .. } => false,
61            Self::Snarked(s) if s.is_pending() => false,
62            _ => true,
63        }
64    }
65
66    // TODO(binier): maybe avoid extra cloning.
67    pub fn target(&self) -> SyncLedgerTarget {
68        match self {
69            Self::Init { target, .. } | Self::Success { target, .. } => target.clone(),
70            Self::Snarked(s) => s.target().clone(),
71            Self::Staged(s) => s.target().clone().into(),
72        }
73    }
74
75    pub fn target_kind(&self) -> SyncLedgerTargetKind {
76        match self {
77            Self::Init { target, .. } | Self::Success { target, .. } => target.kind,
78            Self::Snarked(s) => s.target().kind,
79            Self::Staged(s) => s.target().kind,
80        }
81    }
82
83    pub fn update_target(&mut self, time: Timestamp, new_target: SyncLedgerTarget) {
84        match self {
85            Self::Snarked(
86                TransitionFrontierSyncLedgerSnarkedState::NumAccountsPending { target, .. }
87                | TransitionFrontierSyncLedgerSnarkedState::MerkleTreeSyncPending { target, .. },
88            ) => {
89                if target.snarked_ledger_hash == new_target.snarked_ledger_hash {
90                    *target = new_target;
91                } else {
92                    *self = Self::Init {
93                        time,
94                        target: new_target,
95                    };
96                }
97            }
98            Self::Staged(staged) => {
99                if new_target
100                    .staged
101                    .as_ref()
102                    .is_some_and(|cur| cur.hashes == staged.target().staged.hashes)
103                {
104                    // root staged ledger hash is still the same. Do nothing.
105                } else if staged.target().snarked_ledger_hash == new_target.snarked_ledger_hash {
106                    *self = TransitionFrontierSyncLedgerSnarkedState::Success {
107                        time,
108                        target: new_target.clone(),
109                    }
110                    .into();
111                } else {
112                    *self = Self::Init {
113                        time,
114                        target: new_target,
115                    };
116                }
117            }
118            _ => {
119                // should be impossible.
120            }
121        }
122    }
123}