1mod rpc_state;
2use std::{collections::BTreeMap, str::FromStr};
3
4use crate::p2p::bootstrap::P2pNetworkKadBootstrapStats;
5use ledger::{
6 scan_state::{
7 currency::{Amount, Balance, Fee, Nonce, Slot},
8 transaction_logic::{signed_command, signed_command::SignedCommandPayload, valid, Memo},
9 },
10 transaction_pool::{diff, ValidCommandWithHash},
11 Account, AccountId,
12};
13use mina_core::{
14 block::{AppliedBlock, ArcBlockWithHash},
15 consensus::{ConsensusConstants, ConsensusTime},
16};
17use mina_node_account::AccountPublicKey;
18use mina_p2p_messages::{
19 bigint::{BigInt, InvalidBigInt},
20 v2::{
21 LedgerHash, MinaBaseSignedCommandPayloadBodyStableV2, MinaBaseSignedCommandStableV2,
22 MinaBaseTransactionStatusStableV2, MinaBaseUserCommandStableV2,
23 MinaBaseZkappCommandTStableV1WireStableV1, MinaTransactionTransactionStableV2,
24 SnarkWorkerWorkerRpcsVersionedGetWorkV2TResponse, StateHash, TransactionHash,
25 TransactionSnarkWorkTStableV2,
26 },
27};
28pub use rpc_state::*;
29
30mod rpc_actions;
31pub use rpc_actions::*;
32
33mod rpc_reducer;
34pub use rpc_reducer::collect_rpc_peers_info;
35
36mod rpc_impls;
37
38mod heartbeat;
39pub use heartbeat::{NodeHeartbeat, ProducedBlockInfo, SignedNodeHeartbeat};
40
41pub use mina_core::requests::{RpcId, RpcIdType};
42
43use ledger::scan_state::scan_state::{transaction_snark::OneOrTwo, AvailableJobMessage};
44use mina_core::snark::SnarkJobId;
45use mina_p2p_messages::v2::{CurrencyFeeStableV1, NonZeroCurvePoint};
46use redux::Timestamp;
47use serde::{Deserialize, Serialize};
48
49use crate::{
50 external_snark_worker::{
51 ExternalSnarkWorkerError, ExternalSnarkWorkerWorkError, SnarkWorkSpecError,
52 },
53 ledger::{
54 read::{LedgerReadId, LedgerReadKind, LedgerStatus},
55 write::LedgerWriteKind,
56 },
57 p2p::{
58 connection::{
59 incoming::P2pConnectionIncomingInitOpts, outgoing::P2pConnectionOutgoingInitOpts,
60 },
61 PeerId,
62 },
63 service::Queues,
64 snark_pool::{JobCommitment, JobState, JobSummary},
65 stats::{
66 actions::{ActionStatsForBlock, ActionStatsSnapshot},
67 block_producer::{
68 BlockProductionAttempt, BlockProductionAttemptWonSlot, VrfEvaluatorStats,
69 },
70 sync::SyncStatsSnapshot,
71 },
72};
73
74#[derive(Serialize, Deserialize, Debug, Clone)]
75pub enum RpcRequest {
76 StateGet(Option<String>),
77 StatusGet,
78 HeartbeatGet,
79 ActionStatsGet(ActionStatsQuery),
80 SyncStatsGet(SyncStatsQuery),
81 BlockProducerStatsGet,
82 MessageProgressGet,
83 PeersGet,
84 P2pConnectionOutgoing(P2pConnectionOutgoingInitOpts),
85 P2pConnectionIncoming(P2pConnectionIncomingInitOpts),
86 ScanStateSummaryGet(RpcScanStateSummaryGetQuery),
87 SnarkPoolGet,
88 SnarkPoolJobGet { job_id: SnarkJobId },
89 SnarkPoolCompletedJobsGet,
90 SnarkPoolPendingJobsGet,
91 SnarkerConfig,
92 SnarkerJobCommit { job_id: SnarkJobId },
93 SnarkerJobSpec { job_id: SnarkJobId },
94 SnarkerWorkers,
95 HealthCheck,
96 ReadinessCheck,
97 DiscoveryRoutingTable,
98 DiscoveryBoostrapStats,
99 TransactionPoolGet,
100 LedgerAccountsGet(AccountQuery),
101 TransactionInject(Vec<MinaBaseUserCommandStableV2>),
102 TransitionFrontierUserCommandsGet,
103 BestChain(MaxLength),
104 ConsensusConstantsGet,
105 TransactionStatusGet(MinaBaseUserCommandStableV2),
106 GetBlock(GetBlockQuery),
107 PooledUserCommands(PooledUserCommandsQuery),
108 PooledZkappCommands(PooledZkappsCommandsQuery),
109 GenesisBlockGet,
110 ConsensusTimeGet(ConsensusTimeQuery),
111 LedgerStatusGet(LedgerHash),
112 LedgerAccountDelegatorsGet(LedgerHash, AccountId),
113}
114
115#[derive(Serialize, Deserialize, Debug, Clone)]
116pub enum ConsensusTimeQuery {
117 Now,
118 BestTip,
119}
120
121pub type MaxLength = u32;
122
123#[derive(Serialize, Deserialize, Debug, Clone)]
124pub struct RpcInjectPayment {
125 fee: u64,
126 amount: u64,
127 to: AccountPublicKey,
128 from: AccountPublicKey,
129 memo: String,
130 nonce: u32,
131 valid_until: u32,
132 signature_field: BigInt,
133 signature_scalar: BigInt,
134}
135impl TryFrom<RpcInjectPayment> for MinaBaseUserCommandStableV2 {
137 type Error = InvalidBigInt;
138
139 fn try_from(value: RpcInjectPayment) -> Result<Self, Self::Error> {
140 let signature = mina_signer::Signature {
141 rx: value.signature_field.try_into()?,
142 s: value.signature_scalar.try_into()?,
143 };
144 println!("Signature: {signature}");
145 let sc = signed_command::SignedCommand {
146 payload: SignedCommandPayload::create(
147 Fee::from_u64(value.fee),
148 value.from.clone().try_into().map_err(|_| InvalidBigInt)?,
149 Nonce::from_u32(value.nonce),
150 Some(Slot::from_u32(value.valid_until)),
151 Memo::from_str(&value.memo).unwrap(),
152 signed_command::Body::Payment(signed_command::PaymentPayload {
153 receiver_pk: value.to.try_into().map_err(|_| InvalidBigInt)?,
154 amount: Amount::from_u64(value.amount),
155 }),
156 ),
157 signer: value.from.try_into().map_err(|_| InvalidBigInt)?,
158 signature,
159 };
160
161 Ok(MinaBaseUserCommandStableV2::SignedCommand(sc.into()))
162 }
163}
164
165#[derive(Serialize, Deserialize, Debug, Clone, Copy)]
166pub enum ActionStatsQuery {
167 SinceStart,
168 ForLatestBlock,
169 ForBlockWithId(u64),
170}
171
172#[derive(Serialize, Deserialize, Debug, Clone, Copy)]
173pub struct SyncStatsQuery {
174 pub limit: Option<usize>,
175}
176
177#[derive(Serialize, Deserialize, Debug, Clone)]
178pub enum RpcScanStateSummaryGetQuery {
179 ForBestTip,
180 ForBlockWithHash(StateHash),
181 ForBlockWithHeight(u32),
182}
183
184#[derive(Serialize, Deserialize, Debug, Clone)]
185#[serde(tag = "kind")]
186#[cfg_attr(feature = "openapi", derive(utoipa::ToSchema))]
187pub enum ActionStatsResponse {
188 SinceStart { stats: ActionStatsSnapshot },
189 ForBlock(ActionStatsForBlock),
190}
191
192#[derive(Serialize, Deserialize, Debug, Clone, strum_macros::Display)]
193#[cfg_attr(feature = "openapi", derive(utoipa::ToSchema))]
194pub enum PeerConnectionStatus {
195 Disconnecting,
196 Disconnected,
197 Connecting,
198 Connected,
199}
200
201#[derive(Serialize, Deserialize, Debug, Clone)]
202#[cfg_attr(feature = "openapi", derive(utoipa::ToSchema))]
203pub struct RpcPeerInfo {
204 pub peer_id: PeerId,
205 #[cfg_attr(feature = "openapi", schema(value_type = Option<String>))]
207 pub best_tip: Option<StateHash>,
208 pub best_tip_height: Option<u32>,
209 pub best_tip_global_slot: Option<u32>,
210 pub best_tip_timestamp: Option<u64>,
211 pub connection_status: PeerConnectionStatus,
212 pub connecting_details: Option<String>,
213 pub address: Option<String>,
214 pub incoming: bool,
215 pub is_libp2p: bool,
216 pub time: u64,
217}
218
219#[derive(Serialize, Deserialize, Debug, Clone)]
220#[cfg_attr(feature = "openapi", derive(utoipa::ToSchema))]
221pub struct RpcScanStateSummary {
222 pub block: RpcScanStateSummaryBlock,
223 pub scan_state: Vec<Vec<RpcScanStateSummaryScanStateJob>>,
224}
225
226#[derive(Serialize, Deserialize, Debug, Clone)]
227#[cfg_attr(feature = "openapi", derive(utoipa::ToSchema))]
228pub struct RpcScanStateSummaryBlock {
229 pub hash: StateHash,
230 pub height: u32,
231 pub global_slot: u32,
232 pub transactions: Vec<RpcScanStateSummaryBlockTransaction>,
233 pub completed_works: Vec<SnarkJobId>,
234}
235
236#[derive(Serialize, Deserialize, Debug, Clone)]
237#[cfg_attr(feature = "openapi", derive(utoipa::ToSchema))]
238pub struct RpcScanStateSummaryBlockTransaction {
239 pub hash: Option<TransactionHash>,
241 pub kind: RpcScanStateSummaryBlockTransactionKind,
242 pub status: MinaBaseTransactionStatusStableV2,
243}
244
245#[derive(Serialize, Deserialize, Debug, Clone)]
246#[cfg_attr(feature = "openapi", derive(utoipa::ToSchema))]
247pub enum RpcScanStateSummaryBlockTransactionKind {
248 Payment,
249 StakeDelegation,
250 Zkapp,
251 FeeTransfer,
252 Coinbase,
253}
254
255#[derive(Serialize, Deserialize, Debug, Clone)]
256#[cfg_attr(feature = "openapi", derive(utoipa::ToSchema))]
257#[serde(tag = "status")]
258pub enum RpcScanStateSummaryScanStateJob {
259 Empty,
260 Todo {
261 job_id: SnarkJobId,
262 bundle_job_id: SnarkJobId,
263 job: RpcScanStateSummaryScanStateJobKind,
264 seq_no: u64,
265 },
266 Pending {
267 job_id: SnarkJobId,
268 bundle_job_id: SnarkJobId,
269 job: Box<RpcScanStateSummaryScanStateJobKind>,
270 seq_no: u64,
271 commitment: Option<Box<JobCommitment>>,
272 snark: Option<Box<RpcSnarkPoolJobSnarkWork>>,
273 },
274 Done {
275 job_id: SnarkJobId,
276 bundle_job_id: SnarkJobId,
277 job: Box<RpcScanStateSummaryScanStateJobKind>,
278 seq_no: u64,
279 snark: Box<RpcSnarkPoolJobSnarkWorkDone>,
280 },
281}
282
283#[derive(Serialize, Deserialize, Debug, Clone)]
284#[cfg_attr(feature = "openapi", derive(utoipa::ToSchema))]
285#[serde(tag = "kind")]
286pub enum RpcScanStateSummaryScanStateJobKind {
287 Base(RpcScanStateSummaryBlockTransaction),
288 Merge,
289}
290
291#[derive(Serialize, Deserialize, Debug, Clone)]
292#[cfg_attr(feature = "openapi", derive(utoipa::ToSchema))]
293pub enum RpcScanStateSummaryScanStateJobStatus {
294 Todo,
295 Done,
296}
297
298#[derive(Serialize, Debug, Clone)]
299#[cfg_attr(feature = "openapi", derive(utoipa::ToSchema))]
300pub struct RpcSnarkPoolJobSummary {
301 pub time: Timestamp,
302 pub id: SnarkJobId,
303 pub commitment: Option<JobCommitment>,
304 pub snark: Option<RpcSnarkPoolJobSnarkWork>,
305}
306
307#[derive(Serialize, Debug, Clone)]
308#[cfg_attr(feature = "openapi", derive(utoipa::ToSchema))]
309pub struct RpcSnarkPoolJobFull {
310 pub time: Timestamp,
311 pub id: SnarkJobId,
312 #[cfg_attr(feature = "openapi", schema(value_type = Object))]
313 pub job: OneOrTwo<AvailableJobMessage>,
314 pub commitment: Option<JobCommitment>,
315 pub snark: Option<RpcSnarkPoolJobSnarkWork>,
316}
317
318#[derive(Serialize, Deserialize, Debug, Clone)]
319#[cfg_attr(feature = "openapi", derive(utoipa::ToSchema))]
320pub struct RpcSnarkPoolJobSnarkWork {
321 pub snarker: NonZeroCurvePoint,
322 pub fee: CurrencyFeeStableV1,
323 pub received_t: Timestamp,
324 pub sender: PeerId,
325}
326
327#[derive(Serialize, Deserialize, Debug, Clone)]
328#[cfg_attr(feature = "openapi", derive(utoipa::ToSchema))]
329pub struct RpcSnarkPoolJobSnarkWorkDone {
330 pub snarker: NonZeroCurvePoint,
331 pub fee: CurrencyFeeStableV1,
332}
333
334#[derive(Serialize, Deserialize, Debug, Clone)]
335#[serde(tag = "kind")]
336pub enum RpcSnarkerJobCommitResponse {
337 Ok,
338 JobNotFound,
339 JobTaken,
340 SnarkerBusy,
341}
342
343#[derive(Serialize, Deserialize, Debug, Clone)]
344#[serde(tag = "kind")]
345pub enum RpcSnarkerJobSpecResponse {
346 Ok(Box<SnarkWorkerWorkerRpcsVersionedGetWorkV2TResponse>),
347 Err(SnarkWorkSpecError),
348 JobNotFound,
349}
350
351#[derive(Serialize, Deserialize, Debug, Clone)]
352#[cfg_attr(feature = "openapi", derive(utoipa::ToSchema))]
353pub struct RpcMessageProgressResponse {
354 pub messages_stats: BTreeMap<PeerId, MessagesStats>,
355 pub staking_ledger_sync: Option<LedgerSyncProgress>,
356 pub next_epoch_ledger_sync: Option<LedgerSyncProgress>,
357 pub root_ledger_sync: Option<RootLedgerSyncProgress>,
358}
359
360#[derive(Serialize, Deserialize, Debug, Clone)]
361#[cfg_attr(feature = "openapi", derive(utoipa::ToSchema))]
362pub struct MessagesStats {
363 pub current_request: Option<CurrentMessageProgress>,
364 pub responses: BTreeMap<String, usize>,
365}
366
367#[derive(Serialize, Deserialize, Debug, Clone)]
368#[cfg_attr(feature = "openapi", derive(utoipa::ToSchema))]
369pub struct LedgerSyncProgress {
370 pub fetched: u64,
371 pub estimation: u64,
372}
373
374#[derive(Serialize, Deserialize, Debug, Clone)]
375#[cfg_attr(feature = "openapi", derive(utoipa::ToSchema))]
376pub struct RootLedgerSyncProgress {
377 pub fetched: u64,
378 pub estimation: u64,
379 pub staged: Option<RootStagedLedgerSyncProgress>,
380}
381
382#[derive(Serialize, Deserialize, Debug, Clone)]
383#[cfg_attr(feature = "openapi", derive(utoipa::ToSchema))]
384pub struct RootStagedLedgerSyncProgress {
385 pub fetched: u64,
386 pub total: u64,
387}
388
389#[derive(Serialize, Deserialize, Debug, Clone)]
390#[cfg_attr(feature = "openapi", derive(utoipa::ToSchema))]
391pub struct CurrentMessageProgress {
392 pub name: String,
393 pub received_bytes: usize,
394 pub total_bytes: usize,
395}
396
397#[derive(Serialize, Deserialize, Debug, Clone, thiserror::Error)]
398pub enum RpcStateGetError {
399 #[error("failed to parse filter expression: {0}")]
400 FilterError(String),
401}
402
403pub type RpcStateGetResponse = Result<serde_json::Value, RpcStateGetError>;
404pub type RpcStatusGetResponse = Option<RpcNodeStatus>;
405pub type RpcHeartbeatGetResponse = Option<SignedNodeHeartbeat>;
406pub type RpcActionStatsGetResponse = Option<ActionStatsResponse>;
407pub type RpcSyncStatsGetResponse = Option<Vec<SyncStatsSnapshot>>;
408pub type RpcBlockProducerStatsGetResponse = Option<RpcBlockProducerStats>;
409pub type RpcPeersGetResponse = Vec<RpcPeerInfo>;
410pub type RpcP2pConnectionOutgoingResponse = Result<(), String>;
411pub type RpcScanStateSummaryGetResponse = Result<RpcScanStateSummary, String>;
412pub type RpcSnarkPoolGetResponse = Vec<RpcSnarkPoolJobSummary>;
413pub type RpcSnarkPoolCompletedJobsResponse = Vec<TransactionSnarkWorkTStableV2>;
414pub type RpcSnarkPoolPendingJobsGetResponse = Vec<JobState>;
415pub type RpcSnarkPoolJobGetResponse = Option<RpcSnarkPoolJobFull>;
416pub type RpcSnarkerConfigGetResponse = Option<RpcSnarkerConfig>;
417pub type RpcTransactionPoolResponse = Vec<ValidCommandWithHash>;
418pub type RpcLedgerSlimAccountsResponse = Vec<AccountSlim>;
419pub type RpcLedgerAccountsResponse = Vec<Account>;
420pub type RpcTransitionFrontierUserCommandsResponse = Vec<MinaBaseUserCommandStableV2>;
421pub type RpcBestChainResponse = Vec<AppliedBlock>;
422pub type RpcConsensusConstantsGetResponse = ConsensusConstants;
423pub type RpcTransactionStatusGetResponse = TransactionStatus;
424pub type RpcPooledUserCommandsResponse = Vec<MinaBaseSignedCommandStableV2>;
425pub type RpcPooledZkappCommandsResponse = Vec<MinaBaseZkappCommandTStableV1WireStableV1>;
426pub type RpcGenesisBlockResponse = Option<ArcBlockWithHash>;
427pub type RpcConsensusTimeGetResponse = Option<ConsensusTime>;
428pub type RpcLedgerStatusGetResponse = Option<LedgerStatus>;
429pub type RpcLedgerAccountDelegatorsGetResponse = Option<Vec<Account>>;
430
431#[derive(Serialize, Deserialize, Debug, Clone, strum_macros::Display)]
432#[strum(serialize_all = "SCREAMING_SNAKE_CASE")]
433pub enum TransactionStatus {
434 Pending,
435 Included,
436 Unknown,
437}
438
439#[derive(Serialize, Deserialize, Debug, Clone)]
441pub struct RpcTransactionInjectedPayment {
442 pub amount: Amount,
443 pub fee: Fee,
444 pub from: AccountPublicKey,
446 pub to: AccountPublicKey,
447 pub hash: String, pub is_delegation: bool,
450 pub memo: String, pub nonce: Nonce,
453}
454
455pub type RpcTransactionInjectSuccess = Vec<valid::UserCommand>;
464pub type RpcTransactionInjectRejected = Vec<(valid::UserCommand, diff::Error)>;
465pub type RpcTransactionInjectFailure = Vec<String>;
467
468#[derive(Serialize, Deserialize, Debug, Clone)]
469#[serde(untagged)]
470pub enum RpcTransactionInjectResponse {
471 Success(RpcTransactionInjectSuccess),
472 Rejected(RpcTransactionInjectRejected),
473 Failure(RpcTransactionInjectFailure),
474}
475
476#[derive(Serialize, Debug, Clone)]
528pub struct AccountSlim {
529 pub public_key: AccountPublicKey,
530 pub balance: Balance,
531 pub nonce: Nonce,
532}
533
534impl From<Account> for AccountSlim {
535 fn from(value: Account) -> Self {
536 Self {
537 public_key: AccountPublicKey::from(value.public_key),
538 balance: value.balance,
539 nonce: value.nonce,
540 }
541 }
542}
543
544#[derive(Serialize, Debug, Clone)]
549#[cfg_attr(feature = "openapi", derive(utoipa::ToSchema))]
550pub struct RpcNodeStatus {
551 pub chain_id: Option<String>,
553 pub transition_frontier: RpcNodeStatusTransitionFrontier,
555 pub ledger: RpcNodeStatusLedger,
557 pub snark_pool: RpcNodeStatusSnarkPool,
559 pub transaction_pool: RpcNodeStatusTransactionPool,
561 pub current_block_production_attempt: Option<BlockProductionAttempt>,
563 pub previous_block_production_attempt: Option<BlockProductionAttempt>,
565 pub peers: Vec<RpcPeerInfo>,
567 pub resources_status: RpcNodeStatusResources,
569 pub service_queues: Queues,
571 pub network_info: RpcNodeStatusNetworkInfo,
573 pub block_producer: Option<AccountPublicKey>,
575 pub coinbase_receiver: Option<AccountPublicKey>,
577}
578
579#[derive(Serialize, Debug, Clone)]
581#[cfg_attr(feature = "openapi", derive(utoipa::ToSchema))]
582pub struct RpcNodeStatusNetworkInfo {
583 pub bind_ip: String,
585 pub external_ip: Option<String>,
587 pub client_port: Option<u16>,
589 pub libp2p_port: Option<u16>,
591}
592
593#[derive(Serialize, Debug, Clone)]
595#[cfg_attr(feature = "openapi", derive(utoipa::ToSchema))]
596pub struct RpcNodeStatusLedger {
597 pub alive_masks_after_last_commit: usize,
599 pub pending_writes: Vec<(LedgerWriteKind, redux::Timestamp)>,
601 pub pending_reads: Vec<(LedgerReadId, LedgerReadKind, redux::Timestamp)>,
603}
604
605#[derive(Serialize, Debug, Clone)]
607#[cfg_attr(feature = "openapi", derive(utoipa::ToSchema))]
608pub struct RpcNodeStatusResources {
609 pub p2p_malloc_size: usize,
611 pub transition_frontier: serde_json::Value,
613 pub snark_pool: serde_json::Value,
615}
616
617#[derive(Serialize, Deserialize, Debug, Clone)]
619#[cfg_attr(feature = "openapi", derive(utoipa::ToSchema))]
620pub struct RpcNodeStatusTransitionFrontier {
621 pub best_tip: Option<RpcNodeStatusTransitionFrontierBlockSummary>,
623 pub sync: RpcNodeStatusTransitionFrontierSync,
625}
626
627#[derive(Serialize, Deserialize, Debug, Clone)]
629#[cfg_attr(feature = "openapi", derive(utoipa::ToSchema))]
630pub struct RpcNodeStatusTransitionFrontierSync {
631 pub time: Option<redux::Timestamp>,
633 pub status: String,
635 pub phase: String,
637 pub target: Option<RpcNodeStatusTransitionFrontierBlockSummary>,
639}
640
641#[derive(Serialize, Deserialize, Debug, Clone)]
643#[cfg_attr(feature = "openapi", derive(utoipa::ToSchema))]
644pub struct RpcNodeStatusTransitionFrontierBlockSummary {
645 pub hash: StateHash,
647 pub height: u32,
649 pub global_slot: u32,
651}
652
653#[derive(Serialize, Deserialize, Debug, Default, Clone)]
655#[cfg_attr(feature = "openapi", derive(utoipa::ToSchema))]
656pub struct RpcNodeStatusTransactionPool {
657 pub transactions: usize,
659 pub transactions_for_propagation: usize,
661 pub transaction_candidates: usize,
663}
664
665#[derive(Serialize, Deserialize, Debug, Default, Clone)]
667#[cfg_attr(feature = "openapi", derive(utoipa::ToSchema))]
668pub struct RpcNodeStatusSnarkPool {
669 pub total_jobs: usize,
671 pub snarks: usize,
673}
674
675#[derive(Serialize, Deserialize, Debug, Clone)]
676#[cfg_attr(feature = "openapi", derive(utoipa::ToSchema))]
677pub struct RpcBlockProducerStats {
678 pub current_time: redux::Timestamp,
679 pub current_global_slot: Option<u32>,
680 pub current_epoch: Option<u32>,
681 pub epoch_start: Option<u32>,
682 pub epoch_end: Option<u32>,
683 pub public_key: AccountPublicKey,
684 pub attempts: Vec<BlockProductionAttempt>,
685 pub future_won_slots: Vec<BlockProductionAttemptWonSlot>,
686 pub current_epoch_vrf_stats: Option<VrfEvaluatorStats>,
687 pub vrf_stats: BTreeMap<u32, VrfEvaluatorStats>,
688}
689
690#[derive(Serialize, Deserialize, Debug, Clone)]
691pub struct RpcSnarkerConfig {
692 pub public_key: NonZeroCurvePoint,
693 pub fee: CurrencyFeeStableV1,
694}
695
696#[derive(Serialize, Debug, Clone)]
697pub struct RpcSnarkWorker {
698 pub time: Option<Timestamp>,
699 pub id: Option<String>,
700 pub status: RpcSnarkWorkerStatus,
701}
702
703#[derive(Serialize, Deserialize, Debug, Clone)]
704#[serde(tag = "kind")]
705pub enum RpcSnarkWorkerStatus {
706 None,
707 Starting,
708 Idle,
709 Working {
710 job_id: SnarkJobId,
711 summary: JobSummary,
712 },
713 WorkReady {
714 job_id: SnarkJobId,
715 },
716 WorkError {
717 job_id: SnarkJobId,
718 error: ExternalSnarkWorkerWorkError,
719 },
720 Cancelling {
721 job_id: SnarkJobId,
722 },
723 Cancelled {
724 job_id: SnarkJobId,
725 },
726 Error {
727 error: ExternalSnarkWorkerError,
728 permanent: bool,
729 },
730 Killing,
731}
732
733pub type RpcSnarkerWorkersResponse = Vec<RpcSnarkWorker>;
734
735impl From<&MinaTransactionTransactionStableV2> for RpcScanStateSummaryBlockTransactionKind {
736 fn from(value: &MinaTransactionTransactionStableV2) -> Self {
737 match value {
738 MinaTransactionTransactionStableV2::Command(v) => (&**v).into(),
739 MinaTransactionTransactionStableV2::FeeTransfer(_) => Self::FeeTransfer,
740 MinaTransactionTransactionStableV2::Coinbase(_) => Self::Coinbase,
741 }
742 }
743}
744
745impl From<&MinaBaseUserCommandStableV2> for RpcScanStateSummaryBlockTransactionKind {
746 fn from(value: &MinaBaseUserCommandStableV2) -> Self {
747 match value {
748 MinaBaseUserCommandStableV2::SignedCommand(v) => match &v.payload.body {
749 MinaBaseSignedCommandPayloadBodyStableV2::Payment(_) => Self::Payment,
750 MinaBaseSignedCommandPayloadBodyStableV2::StakeDelegation(_) => {
751 Self::StakeDelegation
752 }
753 },
754 MinaBaseUserCommandStableV2::ZkappCommand(_) => Self::Zkapp,
755 }
756 }
757}
758
759pub type RpcHealthCheckResponse = Result<(), String>;
760pub type RpcReadinessCheckResponse = Result<(), String>;
761
762pub type RpcDiscoveryRoutingTableResponse = Option<discovery::RpcDiscoveryRoutingTable>;
763pub type RpcDiscoveryBoostrapStatsResponse = Option<P2pNetworkKadBootstrapStats>;
764
765#[derive(Serialize, Deserialize, Debug, Clone)]
766pub enum GetBlockQuery {
767 Hash(StateHash),
768 Height(u32),
769}
770
771pub type RpcGetBlockResponse = Option<AppliedBlock>;
772
773#[derive(Serialize, Deserialize, Debug, Clone)]
774pub struct PooledCommandsQuery<ID> {
775 pub public_key: Option<AccountPublicKey>,
776 pub hashes: Option<Vec<TransactionHash>>,
777 pub ids: Option<Vec<ID>>,
778}
779
780pub type PooledUserCommandsQuery = PooledCommandsQuery<MinaBaseSignedCommandStableV2>;
781pub type PooledZkappsCommandsQuery = PooledCommandsQuery<MinaBaseZkappCommandTStableV1WireStableV1>;
782
783pub mod discovery {
784 use crate::p2p::{
785 libp2p_identity::DecodingError, ConnectionType, P2pNetworkKadBucket, P2pNetworkKadDist,
786 P2pNetworkKadEntry, P2pNetworkKadKey, P2pNetworkKadRoutingTable, PeerId,
787 };
788 use serde::{Deserialize, Serialize};
789
790 #[derive(Serialize, Deserialize, Debug, Clone)]
791 pub struct RpcDiscoveryRoutingTable {
792 this_key: P2pNetworkKadKey,
793 buckets: Vec<RpcKBucket>,
794 }
795
796 impl TryFrom<&P2pNetworkKadRoutingTable> for RpcDiscoveryRoutingTable {
797 type Error = DecodingError;
798
799 fn try_from(value: &P2pNetworkKadRoutingTable) -> Result<Self, Self::Error> {
800 let mut buckets = Vec::new();
801
802 for (i, b) in value.buckets.iter().enumerate() {
803 buckets.push((b, P2pNetworkKadDist::from(i), &value.this_key).try_into()?);
804 }
805
806 Ok(RpcDiscoveryRoutingTable {
807 this_key: value.this_key,
808 buckets,
809 })
810 }
811 }
812
813 #[derive(Serialize, Deserialize, Debug, Clone)]
814 pub struct RpcKBucket {
815 max_dist: P2pNetworkKadDist,
816 entries: Vec<RpcEntry>,
817 }
818
819 impl<const K: usize>
820 TryFrom<(
821 &P2pNetworkKadBucket<K>,
822 P2pNetworkKadDist,
823 &P2pNetworkKadKey,
824 )> for RpcKBucket
825 {
826 type Error = DecodingError;
827
828 fn try_from(
829 (bucket, max_dist, this_key): (
830 &P2pNetworkKadBucket<K>,
831 P2pNetworkKadDist,
832 &P2pNetworkKadKey,
833 ),
834 ) -> Result<Self, Self::Error> {
835 let mut entries = Vec::new();
836
837 for entry in bucket.iter() {
838 entries.push((entry, this_key).try_into()?);
839 }
840 Ok(RpcKBucket { max_dist, entries })
841 }
842 }
843
844 #[derive(Serialize, Deserialize, Debug, Clone)]
845 pub struct RpcEntry {
846 peer_id: PeerId,
847 libp2p: crate::p2p::libp2p_identity::PeerId,
848 key: P2pNetworkKadKey,
849 dist: P2pNetworkKadDist,
850 addrs: Vec<crate::p2p::multiaddr::Multiaddr>,
851 connection: ConnectionType,
852 }
853
854 impl TryFrom<(&P2pNetworkKadEntry, &P2pNetworkKadKey)> for RpcEntry {
855 type Error = DecodingError;
856
857 fn try_from(
858 (value, this_key): (&P2pNetworkKadEntry, &P2pNetworkKadKey),
859 ) -> Result<Self, Self::Error> {
860 Ok(RpcEntry {
861 peer_id: value.peer_id,
862 libp2p: value.peer_id.try_into()?,
863 key: value.key,
864 dist: this_key.distance(&value.key),
865 addrs: value.addresses().clone(),
866 connection: value.connection,
867 })
868 }
869 }
870}