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