node/rpc/
rpc_actions.rs

1use ledger::{
2    transaction_pool::{diff, ValidCommandWithHash},
3    Account, AccountId,
4};
5use mina_p2p_messages::v2::{LedgerHash, MinaBaseUserCommandStableV2, TokenIdKeyHash};
6use openmina_core::{block::AppliedBlock, snark::SnarkJobId, ActionEvent};
7use openmina_node_account::AccountPublicKey;
8use p2p::PeerId;
9use serde::{Deserialize, Serialize};
10
11use crate::{
12    external_snark_worker::SnarkWorkId,
13    p2p::connection::{
14        incoming::P2pConnectionIncomingInitOpts,
15        outgoing::{P2pConnectionOutgoingError, P2pConnectionOutgoingInitOpts},
16        P2pConnectionResponse,
17    },
18};
19
20use super::{
21    ActionStatsQuery, ConsensusTimeQuery, GetBlockQuery, PooledUserCommandsQuery,
22    PooledZkappsCommandsQuery, RpcId, RpcLedgerAccountDelegatorsGetResponse,
23    RpcLedgerStatusGetResponse, RpcScanStateSummaryGetQuery, RpcScanStateSummaryScanStateJob,
24    SyncStatsQuery,
25};
26
27#[derive(Serialize, Deserialize, Debug, Clone, ActionEvent)]
28pub enum RpcAction {
29    GlobalStateGet {
30        rpc_id: RpcId,
31        filter: Option<String>,
32    },
33    StatusGet {
34        rpc_id: RpcId,
35    },
36    HeartbeatGet {
37        rpc_id: RpcId,
38    },
39
40    // Stats
41    ActionStatsGet {
42        rpc_id: RpcId,
43        query: ActionStatsQuery,
44    },
45    SyncStatsGet {
46        rpc_id: RpcId,
47        query: SyncStatsQuery,
48    },
49    BlockProducerStatsGet {
50        rpc_id: RpcId,
51    },
52
53    MessageProgressGet {
54        rpc_id: RpcId,
55    },
56
57    PeersGet {
58        rpc_id: RpcId,
59    },
60
61    P2pConnectionOutgoingInit {
62        rpc_id: RpcId,
63        opts: P2pConnectionOutgoingInitOpts,
64    },
65    P2pConnectionOutgoingPending {
66        rpc_id: RpcId,
67    },
68    P2pConnectionOutgoingError {
69        rpc_id: RpcId,
70        error: P2pConnectionOutgoingError,
71    },
72    P2pConnectionOutgoingSuccess {
73        rpc_id: RpcId,
74    },
75
76    P2pConnectionIncomingInit {
77        rpc_id: RpcId,
78        opts: P2pConnectionIncomingInitOpts,
79    },
80    P2pConnectionIncomingPending {
81        rpc_id: RpcId,
82    },
83    P2pConnectionIncomingRespond {
84        rpc_id: RpcId,
85        response: P2pConnectionResponse,
86    },
87    P2pConnectionIncomingAnswerReady {
88        rpc_id: RpcId,
89        peer_id: PeerId,
90        answer: P2pConnectionResponse,
91    },
92    P2pConnectionIncomingError {
93        rpc_id: RpcId,
94        error: String,
95    },
96    P2pConnectionIncomingSuccess {
97        rpc_id: RpcId,
98    },
99
100    ScanStateSummaryGetInit {
101        rpc_id: RpcId,
102        query: RpcScanStateSummaryGetQuery,
103    },
104    ScanStateSummaryLedgerGetInit {
105        rpc_id: RpcId,
106    },
107    ScanStateSummaryGetPending {
108        rpc_id: RpcId,
109        block: Option<AppliedBlock>,
110    },
111    ScanStateSummaryGetSuccess {
112        rpc_id: RpcId,
113        scan_state: Result<Vec<Vec<RpcScanStateSummaryScanStateJob>>, String>,
114    },
115
116    SnarkPoolAvailableJobsGet {
117        rpc_id: RpcId,
118    },
119    SnarkPoolJobGet {
120        job_id: SnarkWorkId,
121        rpc_id: RpcId,
122    },
123    SnarkPoolCompletedJobsGet {
124        rpc_id: RpcId,
125    },
126    SnarkPoolPendingJobsGet {
127        rpc_id: RpcId,
128    },
129    SnarkerConfigGet {
130        rpc_id: RpcId,
131    },
132    SnarkerJobCommit {
133        rpc_id: RpcId,
134        job_id: SnarkJobId,
135    },
136    SnarkerJobSpec {
137        rpc_id: RpcId,
138        job_id: SnarkJobId,
139    },
140
141    SnarkerWorkersGet {
142        rpc_id: RpcId,
143    },
144
145    HealthCheck {
146        rpc_id: RpcId,
147    },
148    ReadinessCheck {
149        rpc_id: RpcId,
150    },
151
152    DiscoveryRoutingTable {
153        rpc_id: RpcId,
154    },
155    DiscoveryBoostrapStats {
156        rpc_id: RpcId,
157    },
158
159    TransactionPool {
160        rpc_id: RpcId,
161    },
162    #[action_event(level = info)]
163    LedgerAccountsGetInit {
164        rpc_id: RpcId,
165        account_query: AccountQuery,
166    },
167    #[action_event(level = info)]
168    LedgerAccountsGetPending {
169        rpc_id: RpcId,
170    },
171    #[action_event(level = info)]
172    LedgerAccountsGetSuccess {
173        rpc_id: RpcId,
174        accounts: Vec<Account>,
175        account_query: AccountQuery,
176    },
177    #[action_event(level = info)]
178    TransactionInjectInit {
179        rpc_id: RpcId,
180        commands: Vec<MinaBaseUserCommandStableV2>,
181    },
182    #[action_event(level = info)]
183    TransactionInjectPending {
184        rpc_id: RpcId,
185    },
186    #[action_event(level = info)]
187    TransactionInjectSuccess {
188        rpc_id: RpcId,
189        response: Vec<ValidCommandWithHash>,
190    },
191    #[action_event(level = info)]
192    TransactionInjectRejected {
193        rpc_id: RpcId,
194        response: Vec<(ValidCommandWithHash, diff::Error)>,
195    },
196    #[action_event(level = warn)]
197    TransactionInjectFailure {
198        rpc_id: RpcId,
199        errors: Vec<String>,
200    },
201    #[action_event(level = info)]
202    TransitionFrontierUserCommandsGet {
203        rpc_id: RpcId,
204    },
205
206    BestChain {
207        rpc_id: RpcId,
208        max_length: u32,
209    },
210    ConsensusConstantsGet {
211        rpc_id: RpcId,
212    },
213
214    TransactionStatusGet {
215        rpc_id: RpcId,
216        tx: MinaBaseUserCommandStableV2,
217    },
218
219    BlockGet {
220        rpc_id: RpcId,
221        query: GetBlockQuery,
222    },
223    ConsensusTimeGet {
224        rpc_id: RpcId,
225        query: ConsensusTimeQuery,
226    },
227    LedgerStatusGetInit {
228        rpc_id: RpcId,
229        ledger_hash: LedgerHash,
230    },
231    LedgerStatusGetPending {
232        rpc_id: RpcId,
233    },
234    LedgerStatusGetSuccess {
235        rpc_id: RpcId,
236        response: RpcLedgerStatusGetResponse,
237    },
238    #[action_event(level = info)]
239    LedgerAccountDelegatorsGetInit {
240        rpc_id: RpcId,
241        ledger_hash: LedgerHash,
242        account_id: AccountId,
243    },
244    #[action_event(level = info)]
245    LedgerAccountDelegatorsGetPending {
246        rpc_id: RpcId,
247    },
248    #[action_event(level = info)]
249    LedgerAccountDelegatorsGetSuccess {
250        rpc_id: RpcId,
251        response: RpcLedgerAccountDelegatorsGetResponse,
252    },
253
254    PooledUserCommands {
255        rpc_id: RpcId,
256        query: PooledUserCommandsQuery,
257    },
258    PooledZkappCommands {
259        rpc_id: RpcId,
260        query: PooledZkappsCommandsQuery,
261    },
262    GenesisBlock {
263        rpc_id: RpcId,
264    },
265
266    Finish {
267        rpc_id: RpcId,
268    },
269}
270
271#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
272pub enum AccountQuery {
273    All,
274    SinglePublicKey(AccountPublicKey),
275    MultipleIds(Vec<AccountId>),
276    PubKeyWithTokenId(AccountPublicKey, TokenIdKeyHash),
277}
278
279impl redux::EnablingCondition<crate::State> for RpcAction {
280    fn is_enabled(&self, state: &crate::State, _time: redux::Timestamp) -> bool {
281        match self {
282            RpcAction::GlobalStateGet { .. } => true,
283            RpcAction::StatusGet { .. } => true,
284            RpcAction::HeartbeatGet { .. } => true,
285            RpcAction::ActionStatsGet { .. } => true,
286            RpcAction::SyncStatsGet { .. } => true,
287            RpcAction::BlockProducerStatsGet { .. } => true,
288            RpcAction::MessageProgressGet { .. } => true,
289            RpcAction::PeersGet { .. } => true,
290            RpcAction::P2pConnectionOutgoingInit { rpc_id, .. } => {
291                !state.rpc.requests.contains_key(rpc_id)
292            }
293            RpcAction::P2pConnectionOutgoingPending { rpc_id } => state
294                .rpc
295                .requests
296                .get(rpc_id)
297                .is_some_and(|v| v.status.is_init()),
298            RpcAction::P2pConnectionOutgoingError { rpc_id, .. } => state
299                .rpc
300                .requests
301                .get(rpc_id)
302                .is_some_and(|v| v.status.is_pending()),
303            RpcAction::P2pConnectionOutgoingSuccess { rpc_id } => state
304                .rpc
305                .requests
306                .get(rpc_id)
307                .is_some_and(|v| v.status.is_pending()),
308            RpcAction::P2pConnectionIncomingInit { rpc_id, .. } => {
309                !state.rpc.requests.contains_key(rpc_id)
310            }
311            RpcAction::P2pConnectionIncomingPending { rpc_id } => state
312                .rpc
313                .requests
314                .get(rpc_id)
315                .is_some_and(|v| v.status.is_init()),
316            RpcAction::P2pConnectionIncomingRespond { rpc_id, .. }
317            | RpcAction::P2pConnectionIncomingAnswerReady { rpc_id, .. } => state
318                .rpc
319                .requests
320                .get(rpc_id)
321                .is_some_and(|v| v.status.is_init() || v.status.is_pending()),
322            RpcAction::P2pConnectionIncomingError { rpc_id, .. } => state
323                .rpc
324                .requests
325                .get(rpc_id)
326                .is_some_and(|v| v.status.is_init() || v.status.is_pending()),
327            RpcAction::P2pConnectionIncomingSuccess { rpc_id } => state
328                .rpc
329                .requests
330                .get(rpc_id)
331                .is_some_and(|v| v.status.is_pending()),
332            RpcAction::ScanStateSummaryGetInit { .. } => true,
333            RpcAction::ScanStateSummaryLedgerGetInit { rpc_id, .. } => state
334                .rpc
335                .requests
336                .get(rpc_id)
337                .is_some_and(|v| v.status.is_init()),
338            RpcAction::ScanStateSummaryGetPending { rpc_id, .. } => state
339                .rpc
340                .requests
341                .get(rpc_id)
342                .is_some_and(|v| v.status.is_init()),
343            RpcAction::ScanStateSummaryGetSuccess { rpc_id, .. } => state
344                .rpc
345                .requests
346                .get(rpc_id)
347                .is_some_and(|v| v.status.is_pending()),
348            RpcAction::SnarkPoolAvailableJobsGet { .. } => true,
349            RpcAction::SnarkPoolJobGet { .. } => true,
350            RpcAction::SnarkPoolCompletedJobsGet { .. } => true,
351            RpcAction::SnarkPoolPendingJobsGet { .. } => true,
352            RpcAction::SnarkerConfigGet { .. } => true,
353            RpcAction::SnarkerJobCommit { .. } => true,
354            RpcAction::SnarkerJobSpec { .. } => true,
355            RpcAction::SnarkerWorkersGet { .. } => true,
356            RpcAction::HealthCheck { .. } => true,
357            RpcAction::ReadinessCheck { .. } => true,
358            RpcAction::DiscoveryRoutingTable { .. } => true,
359            RpcAction::DiscoveryBoostrapStats { .. } => true,
360            RpcAction::TransactionPool { .. } => true,
361            RpcAction::ConsensusConstantsGet { .. } => true,
362            RpcAction::BestChain { .. } => state.transition_frontier.best_tip().is_some(),
363            RpcAction::TransactionStatusGet { .. } => true,
364            RpcAction::PooledUserCommands { .. } => true,
365            RpcAction::PooledZkappCommands { .. } => true,
366            RpcAction::GenesisBlock { .. } => true,
367            RpcAction::LedgerAccountsGetInit { .. } => {
368                state.transition_frontier.best_tip().is_some()
369            }
370            RpcAction::LedgerAccountsGetPending { rpc_id, .. } => state
371                .rpc
372                .requests
373                .get(rpc_id)
374                .is_some_and(|v| v.status.is_init()),
375            RpcAction::LedgerAccountsGetSuccess { rpc_id, .. } => state
376                .rpc
377                .requests
378                .get(rpc_id)
379                .is_some_and(|v| v.status.is_pending()),
380
381            RpcAction::TransactionInjectInit { .. } => true,
382            RpcAction::TransactionInjectPending { rpc_id } => state
383                .rpc
384                .requests
385                .get(rpc_id)
386                .is_some_and(|v| v.status.is_init()),
387            RpcAction::TransactionInjectSuccess { rpc_id, .. } => state
388                .rpc
389                .requests
390                .get(rpc_id)
391                .is_some_and(|v| v.status.is_pending()),
392            RpcAction::TransactionInjectRejected { rpc_id, .. } => state
393                .rpc
394                .requests
395                .get(rpc_id)
396                .is_some_and(|v| v.status.is_pending()),
397            RpcAction::TransactionInjectFailure { rpc_id, .. } => state
398                .rpc
399                .requests
400                .get(rpc_id)
401                .is_some_and(|v| v.status.is_pending()),
402            RpcAction::TransitionFrontierUserCommandsGet { .. } => true,
403            RpcAction::BlockGet { .. } => true,
404            RpcAction::ConsensusTimeGet { .. } => true,
405            RpcAction::LedgerStatusGetInit { .. } => state.transition_frontier.best_tip().is_some(),
406            RpcAction::LedgerStatusGetPending { rpc_id } => state
407                .rpc
408                .requests
409                .get(rpc_id)
410                .is_some_and(|v| v.status.is_init()),
411            RpcAction::LedgerStatusGetSuccess { rpc_id, .. } => state
412                .rpc
413                .requests
414                .get(rpc_id)
415                .is_some_and(|v| v.status.is_pending()),
416            RpcAction::LedgerAccountDelegatorsGetInit { .. } => {
417                state.transition_frontier.best_tip().is_some()
418            }
419            RpcAction::LedgerAccountDelegatorsGetPending { rpc_id } => state
420                .rpc
421                .requests
422                .get(rpc_id)
423                .is_some_and(|v| v.status.is_init()),
424            RpcAction::LedgerAccountDelegatorsGetSuccess { rpc_id, .. } => state
425                .rpc
426                .requests
427                .get(rpc_id)
428                .is_some_and(|v| v.status.is_pending()),
429            RpcAction::Finish { rpc_id } => state
430                .rpc
431                .requests
432                .get(rpc_id)
433                .is_some_and(|v| v.status.is_finished()),
434        }
435    }
436}