1use std::collections::BTreeMap;
3
4use binprot::{BinProtRead, BinProtWrite};
5use binprot_derive::{BinProtRead, BinProtWrite};
6use serde::{Deserialize, Serialize};
7
8use crate::{
9 common::*,
10 core,
11 core::InetAddrV1Versioned,
12 list::List,
13 rpc_kernel::*,
14 string::CharString,
15 v2,
16 v2::MinaBaseSparseLedgerBaseStableV2,
17 versioned::{Ver, Versioned},
18};
19
20macro_rules! mina_rpc {
21 ($name:ident, $tag:literal, $version:literal, $query:ty, $response:ty $(,)?) => {
22 #[derive(Debug)]
23 pub struct $name;
24 impl crate::rpc_kernel::RpcMethod for $name {
25 const NAME: crate::rpc_kernel::RpcTag = $tag.as_bytes();
26 const NAME_STR: &'static str = $tag;
27 const VERSION: crate::versioned::Ver = $version;
28 type Query = $query;
29 type Response = $response;
30 }
31 };
32}
33
34mina_rpc!(
35 SendArchiveDiffUnversioned,
36 "Send_archive_diff",
37 0,
38 v2::ArchiveRpc,
39 ()
40);
41
42mina_rpc!(
43 VersionedRpcMenuV1,
44 "__Versioned_rpc.Menu",
45 1,
46 (),
47 List<(CharString, Ver)>
48);
49
50mina_rpc!(
51 GetSomeInitialPeersV1ForV2,
52 "get_some_initial_peers",
53 1,
54 (),
55 List<v2::NetworkPeerPeerStableV1>
56);
57
58pub type GetStagedLedgerAuxAndPendingCoinbasesAtHashV2Response = Option<(
59 v2::TransactionSnarkScanStateStableV2,
60 LedgerHashV1,
61 v2::MinaBasePendingCoinbaseStableV2,
62 List<v2::MinaStateProtocolStateValueStableV2>,
63)>;
64
65mina_rpc!(
66 GetStagedLedgerAuxAndPendingCoinbasesAtHashV2,
67 "get_staged_ledger_aux_and_pending_coinbases_at_hash",
68 2,
69 StateHashV1,
70 GetStagedLedgerAuxAndPendingCoinbasesAtHashV2Response,
71);
72
73mina_rpc!(
74 AnswerSyncLedgerQueryV2,
75 "answer_sync_ledger_query",
76 3,
77 (LedgerHashV1, v2::MinaLedgerSyncLedgerQueryStableV1),
78 RpcResult<v2::MinaLedgerSyncLedgerAnswerStableV2, core::Error>
79);
80
81mina_rpc!(
82 GetTransitionChainV2,
83 "get_transition_chain",
84 2,
85 List<StateHashV1>,
86 Option<List<v2::MinaBlockBlockStableV2>>
87);
88
89pub type GetTransitionChainProofV1ForV2Response = Option<(StateHashV1, List<StateBodyHashV1>)>;
90mina_rpc!(
91 GetTransitionChainProofV1ForV2,
92 "get_transition_chain_proof",
93 1,
94 StateHashV1,
95 GetTransitionChainProofV1ForV2Response,
96);
97
98mina_rpc!(
99 GetTransitionKnowledgeV1,
100 "Get_transition_knowledge",
101 1,
102 (),
103 List<StateHashV1Versioned>
104);
105
106mina_rpc!(
107 GetTransitionKnowledgeV1ForV2,
108 "Get_transition_knowledge",
109 1,
110 (),
111 List<StateHashV1>
112);
113
114#[derive(Clone, Debug, PartialEq, Serialize, Deserialize, BinProtRead, BinProtWrite)]
116pub struct WithHashV1<A, H> {
117 pub data: A,
118 pub hash: H,
119}
120pub type WithHashV1Versioned<A, H> = Versioned<WithHashV1<A, H>, 1>;
121
122#[derive(Clone, Debug, PartialEq, Serialize, Deserialize, BinProtRead, BinProtWrite)]
123pub struct ProofCarryingDataWithHashV1<A, B> {
124 pub data: A,
125 pub proof: B,
126}
127pub type ProofCarryingDataWithHashV1Versioned<A, B> =
128 Versioned<ProofCarryingDataWithHashV1<A, B>, 1>;
129
130pub type GetAncestryV2Query =
131 WithHashV1<v2::ConsensusProofOfStakeDataConsensusStateValueStableV2, StateHashV1>;
132pub type GetAncestryV2Response = Option<
133 ProofCarryingDataWithHashV1<
134 v2::MinaBlockBlockStableV2,
135 (List<StateBodyHashV1>, v2::MinaBlockBlockStableV2),
136 >,
137>;
138mina_rpc!(
139 GetAncestryV2,
140 "get_ancestry",
141 2,
142 GetAncestryV2Query,
143 GetAncestryV2Response,
144);
145
146mina_rpc!(BanNotifyV1, "ban_notify", 1, core::Time, ());
147
148#[derive(Clone, Debug, PartialEq, Serialize, Deserialize, BinProtRead, BinProtWrite)]
149pub struct ProofCarryingDataStableV1<A, B> {
150 pub data: A,
151 pub proof: B,
152}
153pub type ProofCarryingDataStableV1Versioned<A, B> = Versioned<ProofCarryingDataStableV1<A, B>, 1>;
154pub type GetBestTipV2Response = Option<
155 ProofCarryingDataStableV1<
156 v2::MinaBlockBlockStableV2,
157 (
158 List<v2::MinaBaseStateBodyHashStableV1>,
159 v2::MinaBlockBlockStableV2,
160 ),
161 >,
162>;
163mina_rpc!(GetBestTipV2, "get_best_tip", 2, (), GetBestTipV2Response);
164
165#[derive(Clone, Debug, PartialEq, Serialize, Deserialize, BinProtRead, BinProtWrite)]
166pub struct NodeStatusV2 {
167 node_ip_addr: InetAddrV1Versioned,
168 node_peer_id: v2::NetworkPeerPeerIdStableV1,
169 sync_status: v2::SyncStatusTStableV1,
170 peers: List<v2::NetworkPeerPeerIdStableV1>,
171 block_producers: List<v2::NonZeroCurvePoint>,
172 protocol_state_hash: v2::StateHash,
173 ban_statuses: List<(
174 v2::NetworkPeerPeerIdStableV1,
175 v2::TrustSystemPeerStatusStableV1,
176 )>,
177 k_block_hashes_and_timestamps: List<(v2::StateHash, CharString)>,
178 git_commit: CharString,
179 uptime_minutes: i32,
180 block_height_opt: Option<i32>,
181}
182mina_rpc!(GetNodeStatusV2, "get_node_status", 2, (), RpcResult<NodeStatusV2, core::Error>);
183
184mina_rpc!(GetEpochLedgerV2, "get_epoch_ledger", 2, LedgerHashV1, RpcResult<MinaBaseSparseLedgerBaseStableV2, CharString>);
185
186pub struct JSONifyPayloadRegistry {
195 table: BTreeMap<(&'static [u8], Ver), Box<dyn JSONinifyPayloadReader>>,
196}
197
198impl Default for JSONifyPayloadRegistry {
199 fn default() -> Self {
200 Self::v2()
201 }
202}
203
204impl JSONifyPayloadRegistry {
205 #[deprecated = "Use `[v2]` method instead."]
206 pub fn new() -> Self {
207 Self::v2()
208 }
209
210 pub fn v2() -> Self {
212 let mut this = Self {
213 table: BTreeMap::new(),
214 };
215 this.insert(VersionedRpcMenuV1);
216 this.insert(GetSomeInitialPeersV1ForV2);
217 this.insert(GetStagedLedgerAuxAndPendingCoinbasesAtHashV2);
218 this.insert(AnswerSyncLedgerQueryV2);
219 this.insert(GetTransitionChainV2);
220 this.insert(GetTransitionChainProofV1ForV2);
221 this.insert(GetTransitionKnowledgeV1ForV2);
222 this.insert(BanNotifyV1);
223 this.insert(GetAncestryV2);
224 this.insert(GetBestTipV2);
225 this.insert(GetNodeStatusV2);
226 this.insert(GetEpochLedgerV2);
227 this
228 }
229
230 pub fn get<'a, 'b: 'a>(
231 &'a self,
232 name: &'b [u8],
233 version: Ver,
234 ) -> Option<&'a dyn JSONinifyPayloadReader> {
235 self.table.get(&(name, version)).map(Box::as_ref)
236 }
237
238 fn insert<T>(&mut self, t: T)
239 where
240 T: RpcMethod + 'static,
241 T::Query: Serialize,
242 T::Response: Serialize,
243 {
244 self.table.insert((T::NAME, T::VERSION), Box::new(t));
245 }
246}
247
248#[cfg(test)]
249mod tests {
250 use crate::JSONifyPayloadRegistry;
251
252 #[test]
253 fn jsonify_registry_content_v2() {
254 let r = JSONifyPayloadRegistry::v2();
255 for (name, version) in [
256 ("__Versioned_rpc.Menu", 1),
257 ("get_some_initial_peers", 1),
258 ("get_staged_ledger_aux_and_pending_coinbases_at_hash", 2),
259 ("answer_sync_ledger_query", 2),
260 ("get_transition_chain", 2),
261 ("get_transition_chain_proof", 1),
262 ("Get_transition_knowledge", 1),
263 ("get_ancestry", 2),
264 ("ban_notify", 1),
265 ("get_best_tip", 2),
266 ("get_node_status", 2),
267 ("get_epoch_ledger", 2),
268 ] {
269 assert!(r.get(name.as_bytes(), version).is_some());
270 }
271 }
272
273 #[test]
274 fn jsonify_registry_query() {
275 let r = JSONifyPayloadRegistry::v2();
276 let payload =
277 hex::decode("220101e7dd9b0d45abb2e4dec2c5d22e1f1bd8ae5133047914209a0229e90a62ecfb0e")
278 .unwrap();
279 let mut ptr = payload.as_slice();
280 let jsonify = r.get(b"get_transition_chain", 1).unwrap();
281 let json = jsonify.read_query(&mut ptr).unwrap();
282 let expected = serde_json::json!([
283 "0x0efbec620ae929029a201479043351aed81b1f2ed2c5c2dee4b2ab450d9bdde7"
284 ]);
285 assert_eq!(json, expected);
286 }
287}