mina_node/transition_frontier/
transition_frontier_reducer.rs1use super::{
2 sync::{SyncError, TransitionFrontierSyncState},
3 TransitionFrontierAction, TransitionFrontierActionWithMetaRef, TransitionFrontierState,
4};
5use mina_core::block::AppliedBlock;
6
7impl TransitionFrontierState {
8 pub fn reducer(
9 mut state_context: crate::Substate<Self>,
10 action: TransitionFrontierActionWithMetaRef<'_>,
11 skip_proof_verification: bool,
12 ) {
13 let Ok(state) = state_context.get_substate_mut() else {
14 return;
16 };
17 let (action, meta) = action.split();
18
19 state.chain_diff.take();
21
22 match action {
23 TransitionFrontierAction::Genesis(a) => {
24 super::genesis::TransitionFrontierGenesisState::reducer(
25 mina_core::Substate::from_compatible_substate(state_context),
26 meta.with_action(a),
27 skip_proof_verification,
28 )
29 }
30 TransitionFrontierAction::GenesisEffect(_) => {}
31 TransitionFrontierAction::GenesisInject => {
32 let Some(genesis) = state.genesis.block_with_real_or_dummy_proof() else {
33 return;
34 };
35 let genesis = AppliedBlock {
36 block: genesis,
37 just_emitted_a_proof: true,
38 };
39 state.best_chain = vec![genesis];
40 state.sync = TransitionFrontierSyncState::Synced { time: meta.time() };
41 }
42 TransitionFrontierAction::GenesisProvenInject => {
43 let Some(genesis) = state.genesis.proven_block() else {
44 return;
45 };
46 if let Some(block) = state.best_chain.get_mut(0) {
47 block.block = genesis.clone();
48 } else {
49 let genesis = AppliedBlock {
50 block: genesis.clone(),
51 just_emitted_a_proof: true,
52 };
53 state.best_chain = vec![genesis];
54 }
55 if !state.sync.is_pending() {
56 state.sync = TransitionFrontierSyncState::Synced { time: meta.time() };
57 }
58 }
59 TransitionFrontierAction::Candidate(a) => {
60 super::candidate::TransitionFrontierCandidatesState::reducer(
61 mina_core::Substate::from_compatible_substate(state_context),
62 meta.with_action(a),
63 );
64 }
65 TransitionFrontierAction::Sync(a) => {
66 let best_chain = state.best_chain.clone();
67 super::sync::TransitionFrontierSyncState::reducer(
68 mina_core::Substate::from_compatible_substate(state_context),
69 meta.with_action(a),
70 &best_chain,
71 );
72 }
73 TransitionFrontierAction::Synced {
74 needed_protocol_states: needed_protocol_state_hashes,
75 } => {
76 let TransitionFrontierSyncState::CommitSuccess {
77 chain,
78 needed_protocol_states,
79 ..
80 } = &mut state.sync
81 else {
82 return;
83 };
84 let mut needed_protocol_state_hashes = needed_protocol_state_hashes.clone();
85 let new_chain = std::mem::take(chain);
86 let needed_protocol_states = std::mem::take(needed_protocol_states);
87
88 state.needed_protocol_states.extend(needed_protocol_states);
89 state
90 .needed_protocol_states
91 .retain(|k, _| needed_protocol_state_hashes.remove(k));
92
93 for hash in needed_protocol_state_hashes {
94 let block = state
95 .best_chain
96 .iter()
97 .find(|b| b.hash() == &hash)
98 .or_else(|| new_chain.iter().find(|b| b.hash() == &hash));
99 let block = block.expect("we lack needed block!");
101 let protocol_state = block.header().protocol_state.clone();
102 state.needed_protocol_states.insert(hash, protocol_state);
103 }
104
105 state.blacklist.retain(|_, height| {
106 let tip = new_chain.last().unwrap();
110 height
111 .checked_add(tip.constants().k.as_u32())
112 .expect("overflow")
113 > tip.height()
114 });
115 state.chain_diff = state.maybe_make_chain_diff(&new_chain);
116 state.best_chain = new_chain;
117 state.sync = TransitionFrontierSyncState::Synced { time: meta.time() };
118 }
119 TransitionFrontierAction::SyncFailed { error, .. } => {
120 match error {
121 SyncError::BlockApplyFailed(block, _) => {
122 state.blacklist.insert(block.hash().clone(), block.height());
123 }
124 }
125 state.sync = TransitionFrontierSyncState::Synced { time: meta.time() };
126 }
127 }
128 }
129}