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