node/transition_frontier/candidate/
transition_frontier_candidate_actions.rs1use mina_p2p_messages::v2::StateHash;
2use openmina_core::{
3 action_event,
4 block::{prevalidate::BlockPrevalidationError, ArcBlockWithHash},
5 consensus::consensus_take,
6 ActionEvent,
7};
8use serde::{Deserialize, Serialize};
9use snark::block_verify::SnarkBlockVerifyError;
10
11use crate::snark::block_verify::SnarkBlockVerifyId;
12
13pub type TransitionFrontierCandidateActionWithMeta =
14 redux::ActionWithMeta<TransitionFrontierCandidateAction>;
15pub type TransitionFrontierCandidateActionWithMetaRef<'a> =
16 redux::ActionWithMeta<&'a TransitionFrontierCandidateAction>;
17
18#[derive(Serialize, Deserialize, Debug, Clone, ActionEvent)]
21#[action_event(level = debug, fields(debug(hash), debug(error)))]
22pub enum TransitionFrontierCandidateAction {
23 P2pBestTipUpdate {
24 best_tip: ArcBlockWithHash,
25 },
26 BlockReceived {
27 block: ArcBlockWithHash,
28 chain_proof: Option<(Vec<StateHash>, ArcBlockWithHash)>,
29 },
30 BlockPrevalidateSuccess {
31 hash: StateHash,
32 },
33 BlockPrevalidateError {
34 hash: StateHash,
35 error: BlockPrevalidationError,
36 },
37 BlockChainProofUpdate {
38 hash: StateHash,
39 chain_proof: (Vec<StateHash>, ArcBlockWithHash),
40 },
41 BlockSnarkVerifyPending {
42 req_id: SnarkBlockVerifyId,
43 hash: StateHash,
44 },
45 #[action_event(level = info)]
46 BlockSnarkVerifySuccess {
47 hash: StateHash,
48 },
49 #[action_event(level = warn)]
50 BlockSnarkVerifyError {
51 hash: StateHash,
52 error: SnarkBlockVerifyError,
53 },
54 TransitionFrontierSyncTargetUpdate,
55 Prune,
56}
57
58impl redux::EnablingCondition<crate::State> for TransitionFrontierCandidateAction {
59 fn is_enabled(&self, state: &crate::State, _time: redux::Timestamp) -> bool {
60 match self {
61 TransitionFrontierCandidateAction::P2pBestTipUpdate { .. } => true,
62 TransitionFrontierCandidateAction::BlockReceived { block, .. } => {
63 !block.is_genesis() && !state.transition_frontier.candidates.contains(block.hash())
64 }
65 TransitionFrontierCandidateAction::BlockPrevalidateSuccess { hash }
66 | TransitionFrontierCandidateAction::BlockPrevalidateError { hash, .. } => state
67 .transition_frontier
68 .candidates
69 .get(hash)
70 .is_some_and(|block| block.status.is_received()),
71 TransitionFrontierCandidateAction::BlockChainProofUpdate { hash, .. } => state
72 .transition_frontier
73 .candidates
74 .is_chain_proof_needed(hash),
75 TransitionFrontierCandidateAction::BlockSnarkVerifyPending { req_id, hash } => {
76 state
77 .transition_frontier
78 .candidates
79 .get(hash)
80 .is_some_and(|block| block.status.is_prevalidated())
81 && state.snark.block_verify.jobs.contains(*req_id)
82 }
83 TransitionFrontierCandidateAction::BlockSnarkVerifySuccess { hash } => state
84 .transition_frontier
85 .candidates
86 .get(hash)
87 .is_some_and(|block| block.status.is_snark_verify_pending()),
88 TransitionFrontierCandidateAction::BlockSnarkVerifyError { hash, .. } => state
89 .transition_frontier
90 .candidates
91 .get(hash)
92 .is_some_and(|block| block.status.is_snark_verify_pending()),
93 TransitionFrontierCandidateAction::TransitionFrontierSyncTargetUpdate => {
94 let Some(best_candidate) =
95 state.transition_frontier.candidates.best_verified_block()
96 else {
97 return false;
98 };
99 if IntoIterator::into_iter([
101 state.transition_frontier.best_tip(),
102 state.transition_frontier.sync.best_tip(),
103 ])
104 .flatten()
105 .any(|b| {
106 b.hash() == best_candidate.hash()
107 || !consensus_take(
108 b.consensus_state(),
109 best_candidate.consensus_state(),
110 b.hash(),
111 best_candidate.hash(),
112 )
113 }) {
114 return false;
115 }
116
117 state
119 .transition_frontier
120 .candidates
121 .best_verified_block_chain_proof(&state.transition_frontier)
122 .is_some()
123 }
124 TransitionFrontierCandidateAction::Prune => {
125 state.transition_frontier.candidates.best().is_some()
126 }
127 }
128 }
129}
130
131impl From<TransitionFrontierCandidateAction> for crate::Action {
132 fn from(value: TransitionFrontierCandidateAction) -> Self {
133 Self::TransitionFrontier(crate::TransitionFrontierAction::Candidate(value))
134 }
135}