p2p/channels/snark_job_commitment/
p2p_channels_snark_job_commitment_actions.rs

1use 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}