1mod rpc_state;
2use std::{collections::BTreeMap, str::FromStr};
3
4use ledger::{
5 scan_state::{
6 currency::{Amount, Balance, Fee, Nonce, Slot},
7 transaction_logic::{signed_command, signed_command::SignedCommandPayload, valid, Memo},
8 },
9 transaction_pool::{diff, ValidCommandWithHash},
10 Account, AccountId,
11};
12use mina_core::{
13 block::{AppliedBlock, ArcBlockWithHash},
14 consensus::{ConsensusConstants, ConsensusTime},
15};
16use mina_node_account::AccountPublicKey;
17use mina_p2p_messages::{
18 bigint::{BigInt, InvalidBigInt},
19 v2::{
20 LedgerHash, MinaBaseSignedCommandPayloadBodyStableV2, MinaBaseSignedCommandStableV2,
21 MinaBaseTransactionStatusStableV2, MinaBaseUserCommandStableV2,
22 MinaBaseZkappCommandTStableV1WireStableV1, MinaTransactionTransactionStableV2,
23 SnarkWorkerWorkerRpcsVersionedGetWorkV2TResponse, StateHash, TransactionHash,
24 TransactionSnarkWorkTStableV2,
25 },
26};
27use p2p::bootstrap::P2pNetworkKadBootstrapStats;
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")]
186pub enum ActionStatsResponse {
187 SinceStart { stats: ActionStatsSnapshot },
188 ForBlock(ActionStatsForBlock),
189}
190
191#[derive(Serialize, Deserialize, Debug, Clone, strum_macros::Display)]
192pub enum PeerConnectionStatus {
193 Disconnecting,
194 Disconnected,
195 Connecting,
196 Connected,
197}
198
199#[derive(Serialize, Deserialize, Debug, Clone)]
200pub struct RpcPeerInfo {
201 pub peer_id: PeerId,
202 pub best_tip: Option<StateHash>,
203 pub best_tip_height: Option<u32>,
204 pub best_tip_global_slot: Option<u32>,
205 pub best_tip_timestamp: Option<u64>,
206 pub connection_status: PeerConnectionStatus,
207 pub connecting_details: Option<String>,
208 pub address: Option<String>,
209 pub incoming: bool,
210 pub is_libp2p: bool,
211 pub time: u64,
212}
213
214#[derive(Serialize, Deserialize, Debug, Clone)]
215pub struct RpcScanStateSummary {
216 pub block: RpcScanStateSummaryBlock,
217 pub scan_state: Vec<Vec<RpcScanStateSummaryScanStateJob>>,
218}
219
220#[derive(Serialize, Deserialize, Debug, Clone)]
221pub struct RpcScanStateSummaryBlock {
222 pub hash: StateHash,
223 pub height: u32,
224 pub global_slot: u32,
225 pub transactions: Vec<RpcScanStateSummaryBlockTransaction>,
226 pub completed_works: Vec<SnarkJobId>,
227}
228
229#[derive(Serialize, Deserialize, Debug, Clone)]
230pub struct RpcScanStateSummaryBlockTransaction {
231 pub hash: Option<TransactionHash>,
233 pub kind: RpcScanStateSummaryBlockTransactionKind,
234 pub status: MinaBaseTransactionStatusStableV2,
235}
236
237#[derive(Serialize, Deserialize, Debug, Clone)]
238pub enum RpcScanStateSummaryBlockTransactionKind {
239 Payment,
240 StakeDelegation,
241 Zkapp,
242 FeeTransfer,
243 Coinbase,
244}
245
246#[derive(Serialize, Deserialize, Debug, Clone)]
247#[serde(tag = "status")]
248pub enum RpcScanStateSummaryScanStateJob {
249 Empty,
250 Todo {
251 job_id: SnarkJobId,
252 bundle_job_id: SnarkJobId,
253 job: RpcScanStateSummaryScanStateJobKind,
254 seq_no: u64,
255 },
256 Pending {
257 job_id: SnarkJobId,
258 bundle_job_id: SnarkJobId,
259 job: Box<RpcScanStateSummaryScanStateJobKind>,
260 seq_no: u64,
261 commitment: Option<Box<JobCommitment>>,
262 snark: Option<Box<RpcSnarkPoolJobSnarkWork>>,
263 },
264 Done {
265 job_id: SnarkJobId,
266 bundle_job_id: SnarkJobId,
267 job: Box<RpcScanStateSummaryScanStateJobKind>,
268 seq_no: u64,
269 snark: Box<RpcSnarkPoolJobSnarkWorkDone>,
270 },
271}
272
273#[derive(Serialize, Deserialize, Debug, Clone)]
274#[serde(tag = "kind")]
275pub enum RpcScanStateSummaryScanStateJobKind {
276 Base(RpcScanStateSummaryBlockTransaction),
277 Merge,
278}
279
280#[derive(Serialize, Deserialize, Debug, Clone)]
281pub enum RpcScanStateSummaryScanStateJobStatus {
282 Todo,
283 Done,
284}
285
286#[derive(Serialize, Debug, Clone)]
287pub struct RpcSnarkPoolJobSummary {
288 pub time: Timestamp,
289 pub id: SnarkJobId,
290 pub commitment: Option<JobCommitment>,
291 pub snark: Option<RpcSnarkPoolJobSnarkWork>,
292}
293
294#[derive(Serialize, Debug, Clone)]
295pub struct RpcSnarkPoolJobFull {
296 pub time: Timestamp,
297 pub id: SnarkJobId,
298 pub job: OneOrTwo<AvailableJobMessage>,
299 pub commitment: Option<JobCommitment>,
300 pub snark: Option<RpcSnarkPoolJobSnarkWork>,
301}
302
303#[derive(Serialize, Deserialize, Debug, Clone)]
304pub struct RpcSnarkPoolJobSnarkWork {
305 pub snarker: NonZeroCurvePoint,
306 pub fee: CurrencyFeeStableV1,
307 pub received_t: Timestamp,
308 pub sender: PeerId,
309}
310
311#[derive(Serialize, Deserialize, Debug, Clone)]
312pub struct RpcSnarkPoolJobSnarkWorkDone {
313 pub snarker: NonZeroCurvePoint,
314 pub fee: CurrencyFeeStableV1,
315}
316
317#[derive(Serialize, Deserialize, Debug, Clone)]
318#[serde(tag = "kind")]
319pub enum RpcSnarkerJobCommitResponse {
320 Ok,
321 JobNotFound,
322 JobTaken,
323 SnarkerBusy,
324}
325
326#[derive(Serialize, Deserialize, Debug, Clone)]
327#[serde(tag = "kind")]
328pub enum RpcSnarkerJobSpecResponse {
329 Ok(SnarkWorkerWorkerRpcsVersionedGetWorkV2TResponse),
330 Err(SnarkWorkSpecError),
331 JobNotFound,
332}
333
334#[derive(Serialize, Deserialize, Debug, Clone)]
335pub struct RpcMessageProgressResponse {
336 pub messages_stats: BTreeMap<PeerId, MessagesStats>,
337 pub staking_ledger_sync: Option<LedgerSyncProgress>,
338 pub next_epoch_ledger_sync: Option<LedgerSyncProgress>,
339 pub root_ledger_sync: Option<RootLedgerSyncProgress>,
340}
341
342#[derive(Serialize, Deserialize, Debug, Clone)]
343pub struct MessagesStats {
344 pub current_request: Option<CurrentMessageProgress>,
345 pub responses: BTreeMap<String, usize>,
346}
347
348#[derive(Serialize, Deserialize, Debug, Clone)]
349pub struct LedgerSyncProgress {
350 pub fetched: u64,
351 pub estimation: u64,
352}
353
354#[derive(Serialize, Deserialize, Debug, Clone)]
355pub struct RootLedgerSyncProgress {
356 pub fetched: u64,
357 pub estimation: u64,
358 pub staged: Option<RootStagedLedgerSyncProgress>,
359}
360
361#[derive(Serialize, Deserialize, Debug, Clone)]
362pub struct RootStagedLedgerSyncProgress {
363 pub fetched: u64,
364 pub total: u64,
365}
366
367#[derive(Serialize, Deserialize, Debug, Clone)]
368pub struct CurrentMessageProgress {
369 pub name: String,
370 pub received_bytes: usize,
371 pub total_bytes: usize,
372}
373
374#[derive(Serialize, Deserialize, Debug, Clone, thiserror::Error)]
375pub enum RpcStateGetError {
376 #[error("failed to parse filter expression: {0}")]
377 FilterError(String),
378}
379
380pub type RpcStateGetResponse = Result<serde_json::Value, RpcStateGetError>;
381pub type RpcStatusGetResponse = Option<RpcNodeStatus>;
382pub type RpcHeartbeatGetResponse = Option<SignedNodeHeartbeat>;
383pub type RpcActionStatsGetResponse = Option<ActionStatsResponse>;
384pub type RpcSyncStatsGetResponse = Option<Vec<SyncStatsSnapshot>>;
385pub type RpcBlockProducerStatsGetResponse = Option<RpcBlockProducerStats>;
386pub type RpcPeersGetResponse = Vec<RpcPeerInfo>;
387pub type RpcP2pConnectionOutgoingResponse = Result<(), String>;
388pub type RpcScanStateSummaryGetResponse = Result<RpcScanStateSummary, String>;
389pub type RpcSnarkPoolGetResponse = Vec<RpcSnarkPoolJobSummary>;
390pub type RpcSnarkPoolCompletedJobsResponse = Vec<TransactionSnarkWorkTStableV2>;
391pub type RpcSnarkPoolPendingJobsGetResponse = Vec<JobState>;
392pub type RpcSnarkPoolJobGetResponse = Option<RpcSnarkPoolJobFull>;
393pub type RpcSnarkerConfigGetResponse = Option<RpcSnarkerConfig>;
394pub type RpcTransactionPoolResponse = Vec<ValidCommandWithHash>;
395pub type RpcLedgerSlimAccountsResponse = Vec<AccountSlim>;
396pub type RpcLedgerAccountsResponse = Vec<Account>;
397pub type RpcTransitionFrontierUserCommandsResponse = Vec<MinaBaseUserCommandStableV2>;
398pub type RpcBestChainResponse = Vec<AppliedBlock>;
399pub type RpcConsensusConstantsGetResponse = ConsensusConstants;
400pub type RpcTransactionStatusGetResponse = TransactionStatus;
401pub type RpcPooledUserCommandsResponse = Vec<MinaBaseSignedCommandStableV2>;
402pub type RpcPooledZkappCommandsResponse = Vec<MinaBaseZkappCommandTStableV1WireStableV1>;
403pub type RpcGenesisBlockResponse = Option<ArcBlockWithHash>;
404pub type RpcConsensusTimeGetResponse = Option<ConsensusTime>;
405pub type RpcLedgerStatusGetResponse = Option<LedgerStatus>;
406pub type RpcLedgerAccountDelegatorsGetResponse = Option<Vec<Account>>;
407
408#[derive(Serialize, Deserialize, Debug, Clone, strum_macros::Display)]
409#[strum(serialize_all = "SCREAMING_SNAKE_CASE")]
410pub enum TransactionStatus {
411 Pending,
412 Included,
413 Unknown,
414}
415
416#[derive(Serialize, Deserialize, Debug, Clone)]
418pub struct RpcTransactionInjectedPayment {
419 pub amount: Amount,
420 pub fee: Fee,
421 pub from: AccountPublicKey,
423 pub to: AccountPublicKey,
424 pub hash: String, pub is_delegation: bool,
427 pub memo: String, pub nonce: Nonce,
430}
431
432pub type RpcTransactionInjectSuccess = Vec<valid::UserCommand>;
441pub type RpcTransactionInjectRejected = Vec<(valid::UserCommand, diff::Error)>;
442pub type RpcTransactionInjectFailure = Vec<String>;
444
445#[derive(Serialize, Deserialize, Debug, Clone)]
446#[serde(untagged)]
447pub enum RpcTransactionInjectResponse {
448 Success(RpcTransactionInjectSuccess),
449 Rejected(RpcTransactionInjectRejected),
450 Failure(RpcTransactionInjectFailure),
451}
452
453#[derive(Serialize, Debug, Clone)]
505pub struct AccountSlim {
506 pub public_key: AccountPublicKey,
507 pub balance: Balance,
508 pub nonce: Nonce,
509}
510
511impl From<Account> for AccountSlim {
512 fn from(value: Account) -> Self {
513 Self {
514 public_key: AccountPublicKey::from(value.public_key),
515 balance: value.balance,
516 nonce: value.nonce,
517 }
518 }
519}
520
521#[derive(Serialize, Debug, Clone)]
522pub struct RpcNodeStatus {
523 pub chain_id: Option<String>,
524 pub transition_frontier: RpcNodeStatusTransitionFrontier,
525 pub ledger: RpcNodeStatusLedger,
526 pub snark_pool: RpcNodeStatusSnarkPool,
527 pub transaction_pool: RpcNodeStatusTransactionPool,
528 pub current_block_production_attempt: Option<BlockProductionAttempt>,
529 pub previous_block_production_attempt: Option<BlockProductionAttempt>,
530 pub peers: Vec<RpcPeerInfo>,
531 pub resources_status: RpcNodeStatusResources,
532 pub service_queues: Queues,
533 pub network_info: RpcNodeStatusNetworkInfo,
534 pub block_producer: Option<AccountPublicKey>,
535 pub coinbase_receiver: Option<AccountPublicKey>,
536}
537
538#[derive(Serialize, Debug, Clone)]
539pub struct RpcNodeStatusNetworkInfo {
540 pub bind_ip: String,
541 pub external_ip: Option<String>,
542 pub client_port: Option<u16>,
543 pub libp2p_port: Option<u16>,
544}
545
546#[derive(Serialize, Debug, Clone)]
547pub struct RpcNodeStatusLedger {
548 pub alive_masks_after_last_commit: usize,
549 pub pending_writes: Vec<(LedgerWriteKind, redux::Timestamp)>,
550 pub pending_reads: Vec<(LedgerReadId, LedgerReadKind, redux::Timestamp)>,
551}
552
553#[derive(Serialize, Debug, Clone)]
554pub struct RpcNodeStatusResources {
555 pub p2p_malloc_size: usize,
556 pub transition_frontier: serde_json::Value,
557 pub snark_pool: serde_json::Value,
558}
559
560#[derive(Serialize, Deserialize, Debug, Clone)]
561pub struct RpcNodeStatusTransitionFrontier {
562 pub best_tip: Option<RpcNodeStatusTransitionFrontierBlockSummary>,
563 pub sync: RpcNodeStatusTransitionFrontierSync,
564}
565
566#[derive(Serialize, Deserialize, Debug, Clone)]
567pub struct RpcNodeStatusTransitionFrontierSync {
568 pub time: Option<redux::Timestamp>,
569 pub status: String,
570 pub phase: String,
571 pub target: Option<RpcNodeStatusTransitionFrontierBlockSummary>,
572}
573
574#[derive(Serialize, Deserialize, Debug, Clone)]
575pub struct RpcNodeStatusTransitionFrontierBlockSummary {
576 pub hash: StateHash,
577 pub height: u32,
578 pub global_slot: u32,
579}
580
581#[derive(Serialize, Deserialize, Debug, Default, Clone)]
582pub struct RpcNodeStatusTransactionPool {
583 pub transactions: usize,
584 pub transactions_for_propagation: usize,
585 pub transaction_candidates: usize,
586}
587
588#[derive(Serialize, Deserialize, Debug, Default, Clone)]
589pub struct RpcNodeStatusSnarkPool {
590 pub total_jobs: usize,
591 pub snarks: usize,
592}
593
594#[derive(Serialize, Deserialize, Debug, Clone)]
595pub struct RpcBlockProducerStats {
596 pub current_time: redux::Timestamp,
597 pub current_global_slot: Option<u32>,
598 pub current_epoch: Option<u32>,
599 pub epoch_start: Option<u32>,
600 pub epoch_end: Option<u32>,
601 pub public_key: AccountPublicKey,
602 pub attempts: Vec<BlockProductionAttempt>,
603 pub future_won_slots: Vec<BlockProductionAttemptWonSlot>,
604 pub current_epoch_vrf_stats: Option<VrfEvaluatorStats>,
605 pub vrf_stats: BTreeMap<u32, VrfEvaluatorStats>,
606}
607
608#[derive(Serialize, Deserialize, Debug, Clone)]
609pub struct RpcSnarkerConfig {
610 pub public_key: NonZeroCurvePoint,
611 pub fee: CurrencyFeeStableV1,
612}
613
614#[derive(Serialize, Debug, Clone)]
615pub struct RpcSnarkWorker {
616 pub time: Option<Timestamp>,
617 pub id: Option<String>,
618 pub status: RpcSnarkWorkerStatus,
619}
620
621#[derive(Serialize, Deserialize, Debug, Clone)]
622#[serde(tag = "kind")]
623pub enum RpcSnarkWorkerStatus {
624 None,
625 Starting,
626 Idle,
627 Working {
628 job_id: SnarkJobId,
629 summary: JobSummary,
630 },
631 WorkReady {
632 job_id: SnarkJobId,
633 },
634 WorkError {
635 job_id: SnarkJobId,
636 error: ExternalSnarkWorkerWorkError,
637 },
638 Cancelling {
639 job_id: SnarkJobId,
640 },
641 Cancelled {
642 job_id: SnarkJobId,
643 },
644 Error {
645 error: ExternalSnarkWorkerError,
646 permanent: bool,
647 },
648 Killing,
649}
650
651pub type RpcSnarkerWorkersResponse = Vec<RpcSnarkWorker>;
652
653impl From<&MinaTransactionTransactionStableV2> for RpcScanStateSummaryBlockTransactionKind {
654 fn from(value: &MinaTransactionTransactionStableV2) -> Self {
655 match value {
656 MinaTransactionTransactionStableV2::Command(v) => (&**v).into(),
657 MinaTransactionTransactionStableV2::FeeTransfer(_) => Self::FeeTransfer,
658 MinaTransactionTransactionStableV2::Coinbase(_) => Self::Coinbase,
659 }
660 }
661}
662
663impl From<&MinaBaseUserCommandStableV2> for RpcScanStateSummaryBlockTransactionKind {
664 fn from(value: &MinaBaseUserCommandStableV2) -> Self {
665 match value {
666 MinaBaseUserCommandStableV2::SignedCommand(v) => match &v.payload.body {
667 MinaBaseSignedCommandPayloadBodyStableV2::Payment(_) => Self::Payment,
668 MinaBaseSignedCommandPayloadBodyStableV2::StakeDelegation(_) => {
669 Self::StakeDelegation
670 }
671 },
672 MinaBaseUserCommandStableV2::ZkappCommand(_) => Self::Zkapp,
673 }
674 }
675}
676
677pub type RpcHealthCheckResponse = Result<(), String>;
678pub type RpcReadinessCheckResponse = Result<(), String>;
679
680pub type RpcDiscoveryRoutingTableResponse = Option<discovery::RpcDiscoveryRoutingTable>;
681pub type RpcDiscoveryBoostrapStatsResponse = Option<P2pNetworkKadBootstrapStats>;
682
683#[derive(Serialize, Deserialize, Debug, Clone)]
684pub enum GetBlockQuery {
685 Hash(StateHash),
686 Height(u32),
687}
688
689pub type RpcGetBlockResponse = Option<AppliedBlock>;
690
691#[derive(Serialize, Deserialize, Debug, Clone)]
692pub struct PooledCommandsQuery<ID> {
693 pub public_key: Option<AccountPublicKey>,
694 pub hashes: Option<Vec<TransactionHash>>,
695 pub ids: Option<Vec<ID>>,
696}
697
698pub type PooledUserCommandsQuery = PooledCommandsQuery<MinaBaseSignedCommandStableV2>;
699pub type PooledZkappsCommandsQuery = PooledCommandsQuery<MinaBaseZkappCommandTStableV1WireStableV1>;
700
701pub mod discovery {
702 use p2p::{
703 libp2p_identity::DecodingError, ConnectionType, P2pNetworkKadBucket, P2pNetworkKadDist,
704 P2pNetworkKadEntry, P2pNetworkKadKey, P2pNetworkKadRoutingTable, PeerId,
705 };
706 use serde::{Deserialize, Serialize};
707
708 #[derive(Serialize, Deserialize, Debug, Clone)]
709 pub struct RpcDiscoveryRoutingTable {
710 this_key: P2pNetworkKadKey,
711 buckets: Vec<RpcKBucket>,
712 }
713
714 impl TryFrom<&P2pNetworkKadRoutingTable> for RpcDiscoveryRoutingTable {
715 type Error = DecodingError;
716
717 fn try_from(value: &P2pNetworkKadRoutingTable) -> Result<Self, Self::Error> {
718 let mut buckets = Vec::new();
719
720 for (i, b) in value.buckets.iter().enumerate() {
721 buckets.push((b, P2pNetworkKadDist::from(i), &value.this_key).try_into()?);
722 }
723
724 Ok(RpcDiscoveryRoutingTable {
725 this_key: value.this_key,
726 buckets,
727 })
728 }
729 }
730
731 #[derive(Serialize, Deserialize, Debug, Clone)]
732 pub struct RpcKBucket {
733 max_dist: P2pNetworkKadDist,
734 entries: Vec<RpcEntry>,
735 }
736
737 impl<const K: usize>
738 TryFrom<(
739 &P2pNetworkKadBucket<K>,
740 P2pNetworkKadDist,
741 &P2pNetworkKadKey,
742 )> for RpcKBucket
743 {
744 type Error = DecodingError;
745
746 fn try_from(
747 (bucket, max_dist, this_key): (
748 &P2pNetworkKadBucket<K>,
749 P2pNetworkKadDist,
750 &P2pNetworkKadKey,
751 ),
752 ) -> Result<Self, Self::Error> {
753 let mut entries = Vec::new();
754
755 for entry in bucket.iter() {
756 entries.push((entry, this_key).try_into()?);
757 }
758 Ok(RpcKBucket { max_dist, entries })
759 }
760 }
761
762 #[derive(Serialize, Deserialize, Debug, Clone)]
763 pub struct RpcEntry {
764 peer_id: PeerId,
765 libp2p: p2p::libp2p_identity::PeerId,
766 key: P2pNetworkKadKey,
767 dist: P2pNetworkKadDist,
768 addrs: Vec<p2p::multiaddr::Multiaddr>,
769 connection: ConnectionType,
770 }
771
772 impl TryFrom<(&P2pNetworkKadEntry, &P2pNetworkKadKey)> for RpcEntry {
773 type Error = DecodingError;
774
775 fn try_from(
776 (value, this_key): (&P2pNetworkKadEntry, &P2pNetworkKadKey),
777 ) -> Result<Self, Self::Error> {
778 Ok(RpcEntry {
779 peer_id: value.peer_id,
780 libp2p: value.peer_id.try_into()?,
781 key: value.key,
782 dist: this_key.distance(&value.key),
783 addrs: value.addresses().clone(),
784 connection: value.connection,
785 })
786 }
787 }
788}