p2p/channels/snark_job_commitment/
p2p_channels_snark_job_commitment_actions.rs1use openmina_core::ActionEvent;
2use serde::{Deserialize, Serialize};
3
4use crate::{P2pState, PeerId};
5
6use super::{
7 P2pChannelsSnarkJobCommitmentState, SnarkJobCommitment, SnarkJobCommitmentPropagationState,
8};
9
10pub type P2pChannelsSnarkJobCommitmentActionWithMetaRef<'a> =
11 redux::ActionWithMeta<&'a P2pChannelsSnarkJobCommitmentAction>;
12
13#[derive(Debug, Clone, Serialize, Deserialize, ActionEvent)]
14#[action_event(fields(display(peer_id)))]
15pub enum P2pChannelsSnarkJobCommitmentAction {
16 Init {
17 peer_id: PeerId,
18 },
19 Pending {
20 peer_id: PeerId,
21 },
22 Ready {
23 peer_id: PeerId,
24 },
25 RequestSend {
26 peer_id: PeerId,
27 limit: u8,
28 },
29 PromiseReceived {
30 peer_id: PeerId,
31 promised_count: u8,
32 },
33 Received {
34 peer_id: PeerId,
35 commitment: Box<SnarkJobCommitment>,
36 },
37 RequestReceived {
38 peer_id: PeerId,
39 limit: u8,
40 },
41 ResponseSend {
42 peer_id: PeerId,
43 commitments: Vec<SnarkJobCommitment>,
44 first_index: u64,
45 last_index: u64,
46 },
47}
48
49impl P2pChannelsSnarkJobCommitmentAction {
50 pub fn peer_id(&self) -> &PeerId {
51 match self {
52 Self::Init { peer_id }
53 | Self::Pending { peer_id }
54 | Self::Ready { peer_id }
55 | Self::RequestSend { peer_id, .. }
56 | Self::PromiseReceived { peer_id, .. }
57 | Self::Received { peer_id, .. }
58 | Self::RequestReceived { peer_id, .. }
59 | Self::ResponseSend { peer_id, .. } => peer_id,
60 }
61 }
62}
63
64impl redux::EnablingCondition<P2pState> for P2pChannelsSnarkJobCommitmentAction {
65 fn is_enabled(&self, state: &P2pState, _time: redux::Timestamp) -> bool {
66 match self {
67 P2pChannelsSnarkJobCommitmentAction::Init { peer_id } => {
68 state.get_ready_peer(peer_id).is_some_and(|p| {
69 matches!(
70 &p.channels.snark_job_commitment,
71 P2pChannelsSnarkJobCommitmentState::Enabled
72 )
73 })
74 }
75 P2pChannelsSnarkJobCommitmentAction::Pending { peer_id } => {
76 state.get_ready_peer(peer_id).is_some_and(|p| {
77 matches!(
78 &p.channels.snark_job_commitment,
79 P2pChannelsSnarkJobCommitmentState::Init { .. }
80 )
81 })
82 }
83 P2pChannelsSnarkJobCommitmentAction::Ready { peer_id } => {
84 state.get_ready_peer(peer_id).is_some_and(|p| {
85 matches!(
86 &p.channels.snark_job_commitment,
87 P2pChannelsSnarkJobCommitmentState::Pending { .. }
88 )
89 })
90 }
91 P2pChannelsSnarkJobCommitmentAction::RequestSend { peer_id, .. } => {
92 state.get_ready_peer(peer_id).is_some_and(|p| {
93 matches!(
94 &p.channels.snark_job_commitment,
95 P2pChannelsSnarkJobCommitmentState::Ready {
96 local: SnarkJobCommitmentPropagationState::WaitingForRequest { .. }
97 | SnarkJobCommitmentPropagationState::Responded { .. },
98 ..
99 }
100 )
101 })
102 }
103 P2pChannelsSnarkJobCommitmentAction::PromiseReceived {
104 peer_id,
105 promised_count,
106 } => state.get_ready_peer(peer_id).is_some_and(|p| {
107 matches!(
108 &p.channels.snark_job_commitment,
109 P2pChannelsSnarkJobCommitmentState::Ready {
110 local: SnarkJobCommitmentPropagationState::Requested {
111 requested_limit, ..
112 },
113 ..
114 } if *promised_count > 0 && promised_count <= requested_limit
115 )
116 }),
117 P2pChannelsSnarkJobCommitmentAction::Received { peer_id, .. } => {
118 state.get_ready_peer(peer_id).is_some_and(|p| {
119 matches!(
120 &p.channels.snark_job_commitment,
121 P2pChannelsSnarkJobCommitmentState::Ready {
122 local: SnarkJobCommitmentPropagationState::Responding { .. },
123 ..
124 }
125 )
126 })
127 }
128 P2pChannelsSnarkJobCommitmentAction::RequestReceived { peer_id, limit } => {
129 *limit > 0
130 && state.get_ready_peer(peer_id).is_some_and(|p| {
131 matches!(
132 &p.channels.snark_job_commitment,
133 P2pChannelsSnarkJobCommitmentState::Ready {
134 remote: SnarkJobCommitmentPropagationState::WaitingForRequest { .. }
135 | SnarkJobCommitmentPropagationState::Responded { .. },
136 ..
137 }
138 )
139 })
140 }
141 P2pChannelsSnarkJobCommitmentAction::ResponseSend {
142 peer_id,
143 commitments,
144 first_index,
145 last_index,
146 } => {
147 !commitments.is_empty()
148 && first_index <= last_index
149 && state.get_ready_peer(peer_id).is_some_and(|p| {
150 match &p.channels.snark_job_commitment {
151 P2pChannelsSnarkJobCommitmentState::Ready {
152 remote,
153 next_send_index,
154 ..
155 } => {
156 if first_index < next_send_index {
157 return false;
158 }
159 match remote {
160 SnarkJobCommitmentPropagationState::Requested {
161 requested_limit,
162 ..
163 } => commitments.len() <= *requested_limit as usize,
164 _ => false,
165 }
166 }
167 _ => false,
168 }
169 })
170 }
171 }
172 }
173}
174
175use crate::channels::P2pChannelsAction;
176
177impl From<P2pChannelsSnarkJobCommitmentAction> for crate::P2pAction {
178 fn from(action: P2pChannelsSnarkJobCommitmentAction) -> Self {
179 Self::Channels(P2pChannelsAction::SnarkJobCommitment(action))
180 }
181}