snark/block_verify/
snark_block_verify_reducer.rs1use openmina_core::{Substate, SubstateAccess};
2use redux::EnablingCondition;
3
4use crate::block_verify_effectful::SnarkBlockVerifyEffectfulAction;
5
6use super::{
7 SnarkBlockVerifyAction, SnarkBlockVerifyActionWithMetaRef, SnarkBlockVerifyState,
8 SnarkBlockVerifyStatus,
9};
10
11pub fn reducer<State, Action>(
12 mut state_context: Substate<Action, State, SnarkBlockVerifyState>,
13 action: SnarkBlockVerifyActionWithMetaRef<'_>,
14) where
15 State: SubstateAccess<SnarkBlockVerifyState> + SubstateAccess<crate::SnarkState>,
16 Action: From<SnarkBlockVerifyAction>
17 + From<SnarkBlockVerifyEffectfulAction>
18 + From<redux::AnyAction>
19 + EnablingCondition<State>,
20{
21 let Ok(state) = state_context.get_substate_mut() else {
22 return;
24 };
25 let (action, meta) = action.split();
26
27 match action {
28 SnarkBlockVerifyAction::Init {
29 block,
30 on_init,
31 on_success,
32 on_error,
33 } => {
34 let req_id = state.jobs.add(SnarkBlockVerifyStatus::Init {
35 time: meta.time(),
36 block: block.clone(),
37 on_success: on_success.clone(),
38 on_error: on_error.clone(),
39 });
40
41 let verifier_index = state.verifier_index.clone();
43 let verifier_srs = state.verifier_srs.clone();
44 let dispatcher = state_context.into_dispatcher();
45 dispatcher.push_callback(on_init.clone(), (block.hash_ref().clone(), req_id));
46 dispatcher.push(SnarkBlockVerifyEffectfulAction::Init {
47 req_id,
48 block: block.clone(),
49 verifier_index,
50 verifier_srs,
51 });
52 dispatcher.push(SnarkBlockVerifyAction::Pending { req_id });
53 }
54 SnarkBlockVerifyAction::Pending { req_id } => {
55 if let Some(req) = state.jobs.get_mut(*req_id) {
56 *req = match req {
57 SnarkBlockVerifyStatus::Init {
58 block,
59 on_success,
60 on_error,
61 ..
62 } => SnarkBlockVerifyStatus::Pending {
63 time: meta.time(),
64 block: block.clone(),
65 on_success: on_success.clone(),
66 on_error: on_error.clone(),
67 },
68 _ => return,
69 };
70 }
71 }
72 SnarkBlockVerifyAction::Error { req_id, error, .. } => {
73 let callback_and_arg = state.jobs.get_mut(*req_id).and_then(|req| {
74 if let SnarkBlockVerifyStatus::Pending {
75 block, on_error, ..
76 } = req
77 {
78 let callback = on_error.clone();
79 let block_hash = block.hash_ref().clone();
80 *req = SnarkBlockVerifyStatus::Error {
81 time: meta.time(),
82 block: block.clone(),
83 error: error.clone(),
84 };
85
86 Some((callback, (block_hash, error.clone())))
87 } else {
88 None
89 }
90 });
91
92 let dispatcher = state_context.into_dispatcher();
94
95 if let Some((callback, args)) = callback_and_arg {
96 dispatcher.push_callback(callback, args);
97 }
98
99 dispatcher.push(SnarkBlockVerifyAction::Finish { req_id: *req_id });
100 }
101 SnarkBlockVerifyAction::Success { req_id, .. } => {
102 let callback_and_arg = state.jobs.get_mut(*req_id).and_then(|req| {
103 if let SnarkBlockVerifyStatus::Pending {
104 block, on_success, ..
105 } = req
106 {
107 let callback = on_success.clone();
108 let block_hash = block.hash_ref().clone();
109 *req = SnarkBlockVerifyStatus::Success {
110 time: meta.time(),
111 block: block.clone(),
112 };
113 Some((callback, block_hash))
114 } else {
115 None
116 }
117 });
118
119 let dispatcher = state_context.into_dispatcher();
121
122 if let Some((callback, block_hash)) = callback_and_arg {
123 dispatcher.push_callback(callback, block_hash);
124 }
125
126 dispatcher.push(SnarkBlockVerifyAction::Finish { req_id: *req_id });
127 }
128 SnarkBlockVerifyAction::Finish { req_id, .. } => {
129 state.jobs.remove(*req_id);
130 }
131 }
132}