cuprate_rpc_types/
json.rs

1//! JSON types from the [`/json_rpc`](https://www.getmonero.org/resources/developer-guides/daemon-rpc.html#json-rpc-methods) endpoint.
2//!
3//! All types are originally defined in [`rpc/core_rpc_server_commands_defs.h`](https://github.com/monero-project/monero/blob/cc73fe71162d564ffda8e549b79a350bca53c454/src/rpc/core_rpc_server_commands_defs.h).
4
5//---------------------------------------------------------------------------------------------------- Import
6#[cfg(feature = "serde")]
7use serde::{Deserialize, Serialize};
8
9use crate::{
10    base::{AccessResponseBase, ResponseBase},
11    macros::define_request_and_response,
12    misc::{
13        AuxPow, BlockHeader, ChainInfo, ConnectionInfo, Distribution, GetBan,
14        GetMinerDataTxBacklogEntry, HardforkEntry, HistogramEntry, SetBan, Span, Status,
15        SyncInfoPeer, TxBacklogEntry,
16    },
17    rpc_call::RpcCallValue,
18};
19
20#[cfg(any(feature = "epee", feature = "serde"))]
21use crate::defaults::{
22    default_false, default_height, default_one, default_string, default_true, default_vec,
23    default_zero,
24};
25
26//---------------------------------------------------------------------------------------------------- Macro
27/// Adds a (de)serialization doc-test to a type in `json.rs`.
28///
29/// It expects a const string from `cuprate_test_utils::rpc::data`
30/// and the expected value it should (de)serialize into/from.
31///
32/// It tests that the provided const JSON string can properly
33/// (de)serialize into the expected value.
34///
35/// See below for example usage. This macro is only used in this file.
36macro_rules! serde_doc_test {
37    (
38        // `const` string from `cuprate_test_utils::rpc::data`
39        //  v
40        $cuprate_test_utils_rpc_const:ident => $expected:expr_2021
41        //                                     ^
42        //                     Expected value as an expression
43    ) => {
44        paste::paste! {
45            concat!(
46                "```rust\n",
47                "use cuprate_test_utils::rpc::data::json::*;\n",
48                "use cuprate_rpc_types::{misc::*, base::*, json::*};\n",
49                "use serde_json::{Value, from_str, from_value};\n",
50                "\n",
51                "// The expected data.\n",
52                "let expected = ",
53                stringify!($expected),
54                ";\n",
55                "\n",
56                "// Assert it can be turned into a JSON value.\n",
57                "let value = from_str::<Value>(",
58                stringify!($cuprate_test_utils_rpc_const),
59                ").unwrap();\n",
60                "let Value::Object(map) = value else {\n",
61                "    panic!();\n",
62                "};\n",
63                "\n",
64                "// If a request...\n",
65                "if let Some(params) = map.get(\"params\") {\n",
66                "    let response = from_value::<",
67                stringify!([<$cuprate_test_utils_rpc_const:camel>]),
68                ">(params.clone()).unwrap();\n",
69                "    assert_eq!(response, expected);\n",
70                "    return;\n",
71                "}\n",
72                "\n",
73                "// Else, if a response...\n",
74                "let result = map.get(\"result\").unwrap().clone();\n",
75                "let response = from_value::<",
76                stringify!([<$cuprate_test_utils_rpc_const:camel>]),
77                ">(result.clone()).unwrap();\n",
78                "assert_eq!(response, expected);\n",
79                "```\n",
80            )
81        }
82    };
83}
84
85//---------------------------------------------------------------------------------------------------- Definitions
86// This generates 2 structs:
87//
88// - `GetBlockTemplateRequest`
89// - `GetBlockTemplateResponse`
90//
91// with some interconnected documentation.
92define_request_and_response! {
93    // The markdown tag for Monero RPC documentation. Not necessarily the endpoint.
94    get_block_template,
95
96    // The commit hash and `$file.$extension` in which this type is defined in
97    // the Monero codebase in the `rpc/` directory, followed by the specific lines.
98    cc73fe71162d564ffda8e549b79a350bca53c454 => core_rpc_server_commands_defs.h => 943..=994,
99
100    // The base type name.
101    //
102    // After the type name, 2 optional idents are allowed:
103    // - `restricted`
104    // - `empty`
105    //
106    // These have to be within `()` and will affect the
107    // [`crate::RpcCall`] implementation on the request type.
108    //
109    // This type is not either restricted or empty so nothing is
110    // here, but the correct syntax is shown in a comment below:
111    GetBlockTemplate /* (restricted, empty) */,
112
113    // The request type.
114    //
115    // If `Request {/* fields */}` is provided, a struct is generate as-is.
116    //
117    // If `Request {}` is specified here, it will create a `pub type YOUR_REQUEST_TYPE = ()`
118    // instead of a `struct`, see below in other macro definitions for an example.
119    //
120    // If there are any additional attributes (`/// docs` or `#[derive]`s)
121    // for the struct, they go here, e.g.:
122    //
123    #[doc = serde_doc_test!(
124        // ^ This is a macro that adds a doc-test to this type.
125        // It is optional but it is added to nearly all types.
126        // The syntax is:
127        // `$const` => `$expected`
128        // where `$const` is a `const` string from
129        // `cuprate_test_utils::rpc::data` and `$expected` is an
130        // actual expression that the string _should_ (de)serialize into/from.
131        GET_BLOCK_TEMPLATE_REQUEST => GetBlockTemplateRequest {
132            extra_nonce: String::default(),
133            prev_block: String::default(),
134            reserve_size: 60,
135            wallet_address: "44GBHzv6ZyQdJkjqZje6KLZ3xSyN1hBSFAnLP6EAqJtCRVzMzZmeXTC2AHKDS9aEDTRKmo6a6o9r9j86pYfhCWDkKjbtcns".into(),
136        }
137    )]
138    Request {
139        // Within the `{}` is an infinite matching pattern of:
140        // ```
141        // $ATTRIBUTES
142        // $FIELD_NAME: $FIELD_TYPE,
143        // ```
144        // The struct generated and all fields are `pub`.
145
146        // This optional expression can be placed after
147        // a `field: field_type`. this indicates to the
148        // macro to (de)serialize this field using this
149        // default expression if it doesn't exist in epee.
150        //
151        // See `cuprate_epee_encoding::epee_object` for info.
152        //
153        // The default function must be specified twice:
154        //
155        // 1. As an expression
156        // 2. As a string literal
157        //
158        // For example: `extra_nonce: String /* = default_string(), "default_string" */,`
159        //
160        // This is a HACK since `serde`'s default attribute only takes in
161        // string literals and macros (stringify) within attributes do not work.
162        extra_nonce: String = default_string(), "default_string",
163        prev_block: String = default_string(), "default_string",
164
165        // Another optional expression:
166        // This indicates to the macro to (de)serialize
167        // this field as another type in epee.
168        //
169        // See `cuprate_epee_encoding::epee_object` for info.
170        reserve_size: u64 /* as Type */,
171
172        wallet_address: String,
173    },
174
175    // The response type.
176    //
177    // If `Response {/* fields */}` is used,
178    // this will generate a struct as-is.
179    //
180    // If a type found in [`crate::base`] is used,
181    // It acts as a "base" that gets flattened into
182    // the actual request type.
183    //
184    // "Flatten" means the field(s) of a struct gets inlined
185    // directly into the struct during (de)serialization, see:
186    // <https://serde.rs/field-attrs.html#flatten>.
187    #[doc = serde_doc_test!(
188        GET_BLOCK_TEMPLATE_RESPONSE => GetBlockTemplateResponse {
189            base: ResponseBase::OK,
190            blockhashing_blob: "1010f4bae0b4069d648e741d85ca0e7acb4501f051b27e9b107d3cd7a3f03aa7f776089117c81a00000000e0c20372be23d356347091025c5b5e8f2abf83ab618378565cce2b703491523401".into(),
191            blocktemplate_blob: "1010f4bae0b4069d648e741d85ca0e7acb4501f051b27e9b107d3cd7a3f03aa7f776089117c81a0000000002c681c30101ff8a81c3010180e0a596bb11033b7eedf47baf878f3490cb20b696079c34bd017fe59b0d070e74d73ffabc4bb0e05f011decb630f3148d0163b3bd39690dde4078e4cfb69fecf020d6278a27bad10c58023c0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000".into(),
192            difficulty_top64: 0,
193            difficulty: 283305047039,
194            expected_reward: 600000000000,
195            height: 3195018,
196            next_seed_hash: "".into(),
197            prev_hash: "9d648e741d85ca0e7acb4501f051b27e9b107d3cd7a3f03aa7f776089117c81a".into(),
198            reserved_offset: 131,
199            seed_hash: "e2aa0b7b55042cd48b02e395d78fa66a29815ccc1584e38db2d1f0e8485cd44f".into(),
200            seed_height: 3194880,
201            wide_difficulty: "0x41f64bf3ff".into(),
202        }
203    )]
204    ResponseBase {
205        // This is using [`crate::base::ResponseBase`],
206        // so the type we generate will contain this field:
207        // ```
208        // base: crate::base::ResponseBase,
209        // ```
210        //
211        // This is flattened with serde and epee, so during
212        // (de)serialization, it will act as if there are 2 extra fields here:
213        // ```
214        // status: crate::Status,
215        // untrusted: bool,
216        // ```
217        blockhashing_blob: String,
218        blocktemplate_blob: String,
219        difficulty_top64: u64,
220        difficulty: u64,
221        expected_reward: u64,
222        height: u64,
223        next_seed_hash: String,
224        prev_hash: String,
225        reserved_offset: u64,
226        seed_hash: String,
227        seed_height: u64,
228        wide_difficulty: String,
229    }
230}
231
232define_request_and_response! {
233    get_block_count,
234    cc73fe71162d564ffda8e549b79a350bca53c454 =>
235    core_rpc_server_commands_defs.h => 919..=933,
236    GetBlockCount (empty),
237
238    // There are no request fields specified,
239    // this will cause the macro to generate a
240    // type alias to `()` instead of a `struct`.
241    Request {},
242
243    #[doc = serde_doc_test!(
244        GET_BLOCK_COUNT_RESPONSE => GetBlockCountResponse {
245            base: ResponseBase::OK,
246            count: 3195019,
247        }
248    )]
249    ResponseBase {
250        count: u64,
251    }
252}
253
254define_request_and_response! {
255    on_get_block_hash,
256    cc73fe71162d564ffda8e549b79a350bca53c454 =>
257    core_rpc_server_commands_defs.h => 935..=939,
258
259    OnGetBlockHash,
260
261    #[doc = serde_doc_test!(
262        ON_GET_BLOCK_HASH_REQUEST => OnGetBlockHashRequest {
263            block_height: [912345],
264        }
265    )]
266    #[cfg_attr(feature = "serde", serde(transparent))]
267    #[repr(transparent)]
268    #[derive(Copy)]
269    Request {
270        // This is `std::vector<u64>` in `monerod` but
271        // it must be a 1 length array or else it will error.
272        block_height: [u64; 1],
273    },
274
275    #[doc = serde_doc_test!(
276        ON_GET_BLOCK_HASH_RESPONSE => OnGetBlockHashResponse {
277            block_hash: "e22cf75f39ae720e8b71b3d120a5ac03f0db50bba6379e2850975b4859190bc6".into(),
278        }
279    )]
280    #[cfg_attr(feature = "serde", serde(transparent))]
281    #[repr(transparent)]
282    Response {
283        block_hash: String,
284    }
285}
286
287define_request_and_response! {
288    submit_block,
289    cc73fe71162d564ffda8e549b79a350bca53c454 =>
290    core_rpc_server_commands_defs.h => 1114..=1128,
291
292    SubmitBlock,
293
294    #[doc = serde_doc_test!(
295        SUBMIT_BLOCK_REQUEST => SubmitBlockRequest {
296            block_blob: ["0707e6bdfedc053771512f1bc27c62731ae9e8f2443db64ce742f4e57f5cf8d393de28551e441a0000000002fb830a01ffbf830a018cfe88bee283060274c0aae2ef5730e680308d9c00b6da59187ad0352efe3c71d36eeeb28782f29f2501bd56b952c3ddc3e350c2631d3a5086cac172c56893831228b17de296ff4669de020200000000".into()],
297        }
298    )]
299    #[cfg_attr(feature = "serde", serde(transparent))]
300    #[repr(transparent)]
301    Request {
302        // This is `std::vector<std::string>` in `monerod` but
303        // it must be a 1 length array or else it will error.
304        block_blob: [String; 1],
305    },
306
307    // FIXME: `cuprate_test_utils` only has an `error` response for this.
308    ResponseBase {
309        block_id: String,
310    }
311}
312
313define_request_and_response! {
314    generateblocks,
315    cc73fe71162d564ffda8e549b79a350bca53c454 =>
316    core_rpc_server_commands_defs.h => 1130..=1161,
317
318    GenerateBlocks (restricted),
319
320    #[doc = serde_doc_test!(
321        GENERATE_BLOCKS_REQUEST => GenerateBlocksRequest {
322            amount_of_blocks: 1,
323            prev_block: String::default(),
324            wallet_address: "44AFFq5kSiGBoZ4NMDwYtN18obc8AemS33DBLWs3H7otXft3XjrpDtQGv7SqSsaBYBb98uNbr2VBBEt7f2wfn3RVGQBEP3A".into(),
325            starting_nonce: 0
326        }
327    )]
328    Request {
329        amount_of_blocks: u64,
330        prev_block: String = default_string(), "default_string",
331        starting_nonce: u32,
332        wallet_address: String,
333    },
334
335    #[doc = serde_doc_test!(
336        GENERATE_BLOCKS_RESPONSE => GenerateBlocksResponse {
337            base: ResponseBase::OK,
338            blocks: vec!["49b712db7760e3728586f8434ee8bc8d7b3d410dac6bb6e98bf5845c83b917e4".into()],
339            height: 9783,
340        }
341    )]
342    ResponseBase {
343        blocks: Vec<String>,
344        height: u64,
345    }
346}
347
348define_request_and_response! {
349    get_last_block_header,
350    cc73fe71162d564ffda8e549b79a350bca53c454 =>
351    core_rpc_server_commands_defs.h => 1214..=1238,
352
353    GetLastBlockHeader,
354
355    #[derive(Copy)]
356    Request {
357        fill_pow_hash: bool = default_false(), "default_false",
358    },
359
360    #[doc = serde_doc_test!(
361        GET_LAST_BLOCK_HEADER_RESPONSE => GetLastBlockHeaderResponse {
362            base: AccessResponseBase::OK,
363            block_header: BlockHeader {
364                block_size: 200419,
365                block_weight: 200419,
366                cumulative_difficulty: 366125734645190820,
367                cumulative_difficulty_top64: 0,
368                depth: 0,
369                difficulty: 282052561854,
370                difficulty_top64: 0,
371                hash: "57238217820195ac4c08637a144a885491da167899cf1d20e8e7ce0ae0a3434e".into(),
372                height: 3195020,
373                long_term_weight: 200419,
374                major_version: 16,
375                miner_tx_hash: "7a42667237d4f79891bb407c49c712a9299fb87fce799833a7b633a3a9377dbd".into(),
376                minor_version: 16,
377                nonce: 1885649739,
378                num_txes: 37,
379                orphan_status: false,
380                pow_hash: "".into(),
381                prev_hash: "22c72248ae9c5a2863c94735d710a3525c499f70707d1c2f395169bc5c8a0da3".into(),
382                reward: 615702960000,
383                timestamp: 1721245548,
384                wide_cumulative_difficulty: "0x514bd6a74a7d0a4".into(),
385                wide_difficulty: "0x41aba48bbe".into()
386            }
387        }
388    )]
389    AccessResponseBase {
390        block_header: BlockHeader,
391    }
392}
393
394define_request_and_response! {
395    get_block_header_by_hash,
396    cc73fe71162d564ffda8e549b79a350bca53c454 =>
397    core_rpc_server_commands_defs.h => 1240..=1269,
398    GetBlockHeaderByHash,
399    #[doc = serde_doc_test!(
400        GET_BLOCK_HEADER_BY_HASH_REQUEST => GetBlockHeaderByHashRequest {
401            hash: "e22cf75f39ae720e8b71b3d120a5ac03f0db50bba6379e2850975b4859190bc6".into(),
402            hashes: vec![],
403            fill_pow_hash: false,
404        }
405    )]
406    Request {
407        hash: String,
408        hashes: Vec<String> = default_vec::<String>(), "default_vec",
409        fill_pow_hash: bool = default_false(), "default_false",
410    },
411
412    #[doc = serde_doc_test!(
413        GET_BLOCK_HEADER_BY_HASH_RESPONSE => GetBlockHeaderByHashResponse {
414            base: AccessResponseBase::OK,
415            block_headers: vec![],
416            block_header: BlockHeader {
417                block_size: 210,
418                block_weight: 210,
419                cumulative_difficulty: 754734824984346,
420                cumulative_difficulty_top64: 0,
421                depth: 2282676,
422                difficulty: 815625611,
423                difficulty_top64: 0,
424                hash: "e22cf75f39ae720e8b71b3d120a5ac03f0db50bba6379e2850975b4859190bc6".into(),
425                height: 912345,
426                long_term_weight: 210,
427                major_version: 1,
428                miner_tx_hash: "c7da3965f25c19b8eb7dd8db48dcd4e7c885e2491db77e289f0609bf8e08ec30".into(),
429                minor_version: 2,
430                nonce: 1646,
431                num_txes: 0,
432                orphan_status: false,
433                pow_hash: "".into(),
434                prev_hash: "b61c58b2e0be53fad5ef9d9731a55e8a81d972b8d90ed07c04fd37ca6403ff78".into(),
435                reward: 7388968946286,
436                timestamp: 1452793716,
437                wide_cumulative_difficulty: "0x2ae6d65248f1a".into(),
438                wide_difficulty: "0x309d758b".into()
439            },
440        }
441    )]
442    AccessResponseBase {
443        block_header: BlockHeader,
444        block_headers: Vec<BlockHeader> = default_vec::<BlockHeader>(), "default_vec",
445    }
446}
447
448define_request_and_response! {
449    get_block_header_by_height,
450    cc73fe71162d564ffda8e549b79a350bca53c454 =>
451    core_rpc_server_commands_defs.h => 1271..=1296,
452
453    GetBlockHeaderByHeight,
454
455    #[derive(Copy)]
456    #[doc = serde_doc_test!(
457        GET_BLOCK_HEADER_BY_HEIGHT_REQUEST => GetBlockHeaderByHeightRequest {
458            height: 912345,
459            fill_pow_hash: false,
460        }
461    )]
462    Request {
463        height: u64,
464        fill_pow_hash: bool = default_false(), "default_false",
465    },
466
467    #[doc = serde_doc_test!(
468        GET_BLOCK_HEADER_BY_HEIGHT_RESPONSE => GetBlockHeaderByHeightResponse {
469            base: AccessResponseBase::OK,
470            block_header: BlockHeader {
471                block_size: 210,
472                block_weight: 210,
473                cumulative_difficulty: 754734824984346,
474                cumulative_difficulty_top64: 0,
475                depth: 2282677,
476                difficulty: 815625611,
477                difficulty_top64: 0,
478                hash: "e22cf75f39ae720e8b71b3d120a5ac03f0db50bba6379e2850975b4859190bc6".into(),
479                height: 912345,
480                long_term_weight: 210,
481                major_version: 1,
482                miner_tx_hash: "c7da3965f25c19b8eb7dd8db48dcd4e7c885e2491db77e289f0609bf8e08ec30".into(),
483                minor_version: 2,
484                nonce: 1646,
485                num_txes: 0,
486                orphan_status: false,
487                pow_hash: "".into(),
488                prev_hash: "b61c58b2e0be53fad5ef9d9731a55e8a81d972b8d90ed07c04fd37ca6403ff78".into(),
489                reward: 7388968946286,
490                timestamp: 1452793716,
491                wide_cumulative_difficulty: "0x2ae6d65248f1a".into(),
492                wide_difficulty: "0x309d758b".into()
493            },
494        }
495    )]
496    AccessResponseBase {
497        block_header: BlockHeader,
498    }
499}
500
501define_request_and_response! {
502    get_block_headers_range,
503    cc73fe71162d564ffda8e549b79a350bca53c454 =>
504    core_rpc_server_commands_defs.h => 1756..=1783,
505
506    GetBlockHeadersRange,
507
508    #[derive(Copy)]
509    #[doc = serde_doc_test!(
510        GET_BLOCK_HEADERS_RANGE_REQUEST => GetBlockHeadersRangeRequest {
511            start_height: 1545999,
512            end_height: 1546000,
513            fill_pow_hash: false,
514        }
515    )]
516    Request {
517        start_height: u64,
518        end_height: u64,
519        fill_pow_hash: bool = default_false(), "default_false",
520    },
521
522    #[doc = serde_doc_test!(
523        GET_BLOCK_HEADERS_RANGE_RESPONSE => GetBlockHeadersRangeResponse {
524            base: AccessResponseBase::OK,
525            headers: vec![
526                BlockHeader {
527                    block_size: 301413,
528                    block_weight: 301413,
529                    cumulative_difficulty: 13185267971483472,
530                    cumulative_difficulty_top64: 0,
531                    depth: 1649024,
532                    difficulty: 134636057921,
533                    difficulty_top64: 0,
534                    hash: "86d1d20a40cefcf3dd410ff6967e0491613b77bf73ea8f1bf2e335cf9cf7d57a".into(),
535                    height: 1545999,
536                    long_term_weight: 301413,
537                    major_version: 6,
538                    miner_tx_hash: "9909c6f8a5267f043c3b2b079fb4eacc49ef9c1dee1c028eeb1a259b95e6e1d9".into(),
539                    minor_version: 6,
540                    nonce: 3246403956,
541                    num_txes: 20,
542                    orphan_status: false,
543                    pow_hash: "".into(),
544                    prev_hash: "0ef6e948f77b8f8806621003f5de24b1bcbea150bc0e376835aea099674a5db5".into(),
545                    reward: 5025593029981,
546                    timestamp: 1523002893,
547                    wide_cumulative_difficulty: "0x2ed7ee6db56750".into(),
548                    wide_difficulty: "0x1f58ef3541".into()
549                },
550                BlockHeader {
551                    block_size: 13322,
552                    block_weight: 13322,
553                    cumulative_difficulty: 13185402687569710,
554                    cumulative_difficulty_top64: 0,
555                    depth: 1649023,
556                    difficulty: 134716086238,
557                    difficulty_top64: 0,
558                    hash: "b408bf4cfcd7de13e7e370c84b8314c85b24f0ba4093ca1d6eeb30b35e34e91a".into(),
559                    height: 1546000,
560                    long_term_weight: 13322,
561                    major_version: 7,
562                    miner_tx_hash: "7f749c7c64acb35ef427c7454c45e6688781fbead9bbf222cb12ad1a96a4e8f6".into(),
563                    minor_version: 7,
564                    nonce: 3737164176,
565                    num_txes: 1,
566                    orphan_status: false,
567                    pow_hash: "".into(),
568                    prev_hash: "86d1d20a40cefcf3dd410ff6967e0491613b77bf73ea8f1bf2e335cf9cf7d57a".into(),
569                    reward: 4851952181070,
570                    timestamp: 1523002931,
571                    wide_cumulative_difficulty: "0x2ed80dcb69bf2e".into(),
572                    wide_difficulty: "0x1f5db457de".into()
573                }
574            ],
575        }
576    )]
577    AccessResponseBase {
578        headers: Vec<BlockHeader>,
579    }
580}
581
582define_request_and_response! {
583    get_block,
584    cc73fe71162d564ffda8e549b79a350bca53c454 =>
585    core_rpc_server_commands_defs.h => 1298..=1313,
586    GetBlock,
587
588    #[doc = serde_doc_test!(
589        GET_BLOCK_REQUEST => GetBlockRequest {
590            height: 2751506,
591            hash: String::default(),
592            fill_pow_hash: false,
593        }
594    )]
595    Request {
596        // `monerod` has both `hash` and `height` fields.
597        // In the RPC handler, if `hash.is_empty()`, it will use it, else, it uses `height`.
598        // <https://github.com/monero-project/monero/blob/cc73fe71162d564ffda8e549b79a350bca53c454/src/rpc/core_rpc_server.cpp#L2674>
599        hash: String = default_string(), "default_string",
600        height: u64 = default_height(), "default_height",
601        fill_pow_hash: bool = default_false(), "default_false",
602    },
603
604    #[doc = serde_doc_test!(
605        GET_BLOCK_RESPONSE => GetBlockResponse {
606            base: AccessResponseBase::OK,
607            blob: "1010c58bab9b06b27bdecfc6cd0a46172d136c08831cf67660377ba992332363228b1b722781e7807e07f502cef8a70101ff92f8a7010180e0a596bb1103d7cbf826b665d7a532c316982dc8dbc24f285cbc18bbcc27c7164cd9b3277a85d034019f629d8b36bd16a2bfce3ea80c31dc4d8762c67165aec21845494e32b7582fe00211000000297a787a000000000000000000000000".into(),
608            block_header: BlockHeader {
609                block_size: 106,
610                block_weight: 106,
611                cumulative_difficulty: 236046001376524168,
612                cumulative_difficulty_top64: 0,
613                depth: 443517,
614                difficulty: 313732272488,
615                difficulty_top64: 0,
616                hash: "43bd1f2b6556dcafa413d8372974af59e4e8f37dbf74dc6b2a9b7212d0577428".into(),
617                height: 2751506,
618                long_term_weight: 176470,
619                major_version: 16,
620                miner_tx_hash: "e49b854c5f339d7410a77f2a137281d8042a0ffc7ef9ab24cd670b67139b24cd".into(),
621                minor_version: 16,
622                nonce: 4110909056,
623                num_txes: 0,
624                orphan_status: false,
625                pow_hash: "".into(),
626                prev_hash: "b27bdecfc6cd0a46172d136c08831cf67660377ba992332363228b1b722781e7".into(),
627                reward: 600000000000,
628                timestamp: 1667941829,
629                wide_cumulative_difficulty: "0x3469a966eb2f788".into(),
630                wide_difficulty: "0x490be69168".into()
631            },
632            json: "{\n  \"major_version\": 16, \n  \"minor_version\": 16, \n  \"timestamp\": 1667941829, \n  \"prev_id\": \"b27bdecfc6cd0a46172d136c08831cf67660377ba992332363228b1b722781e7\", \n  \"nonce\": 4110909056, \n  \"miner_tx\": {\n    \"version\": 2, \n    \"unlock_time\": 2751566, \n    \"vin\": [ {\n        \"gen\": {\n          \"height\": 2751506\n        }\n      }\n    ], \n    \"vout\": [ {\n        \"amount\": 600000000000, \n        \"target\": {\n          \"tagged_key\": {\n            \"key\": \"d7cbf826b665d7a532c316982dc8dbc24f285cbc18bbcc27c7164cd9b3277a85\", \n            \"view_tag\": \"d0\"\n          }\n        }\n      }\n    ], \n    \"extra\": [ 1, 159, 98, 157, 139, 54, 189, 22, 162, 191, 206, 62, 168, 12, 49, 220, 77, 135, 98, 198, 113, 101, 174, 194, 24, 69, 73, 78, 50, 183, 88, 47, 224, 2, 17, 0, 0, 0, 41, 122, 120, 122, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0\n    ], \n    \"rct_signatures\": {\n      \"type\": 0\n    }\n  }, \n  \"tx_hashes\": [ ]\n}".into(),
633            miner_tx_hash: "e49b854c5f339d7410a77f2a137281d8042a0ffc7ef9ab24cd670b67139b24cd".into(),
634            tx_hashes: vec![],
635        }
636    )]
637    AccessResponseBase {
638        blob: String,
639        block_header: BlockHeader,
640        /// `cuprate_rpc_types::json::block::Block` should be used
641        /// to create this JSON string in a type-safe manner.
642        json: String,
643        miner_tx_hash: String,
644        tx_hashes: Vec<String> = default_vec::<String>(), "default_vec",
645    }
646}
647
648define_request_and_response! {
649    get_connections,
650    cc73fe71162d564ffda8e549b79a350bca53c454 =>
651    core_rpc_server_commands_defs.h => 1734..=1754,
652
653    GetConnections (restricted, empty),
654
655    Request {},
656
657    #[doc = serde_doc_test!(
658        GET_CONNECTIONS_RESPONSE => GetConnectionsResponse {
659            base: ResponseBase::OK,
660            connections: vec![
661                ConnectionInfo {
662                    address: "3evk3kezfjg44ma6tvesy7rbxwwpgpympj45xar5fo4qajrsmkoaqdqd.onion:18083".into(),
663                    address_type: cuprate_types::AddressType::Tor,
664                    avg_download: 0,
665                    avg_upload: 0,
666                    connection_id: "22ef856d0f1d44cc95e84fecfd065fe2".into(),
667                    current_download: 0,
668                    current_upload: 0,
669                    height: 3195026,
670                    host: "3evk3kezfjg44ma6tvesy7rbxwwpgpympj45xar5fo4qajrsmkoaqdqd.onion".into(),
671                    incoming: false,
672                    ip: "".into(),
673                    live_time: 76651,
674                    local_ip: false,
675                    localhost: false,
676                    peer_id: "0000000000000001".into(),
677                    port: "".into(),
678                    pruning_seed: 0,
679                    recv_count: 240328,
680                    recv_idle_time: 34,
681                    rpc_credits_per_hash: 0,
682                    rpc_port: 0,
683                    send_count: 3406572,
684                    send_idle_time: 30,
685                    state: cuprate_types::ConnectionState::Normal,
686                    support_flags: 0
687                },
688                ConnectionInfo {
689                    address: "4iykytmumafy5kjahdqc7uzgcs34s2vwsadfjpk4znvsa5vmcxeup2qd.onion:18083".into(),
690                    address_type: cuprate_types::AddressType::Tor,
691                    avg_download: 0,
692                    avg_upload: 0,
693                    connection_id: "c7734e15936f485a86d2b0534f87e499".into(),
694                    current_download: 0,
695                    current_upload: 0,
696                    height: 3195024,
697                    host: "4iykytmumafy5kjahdqc7uzgcs34s2vwsadfjpk4znvsa5vmcxeup2qd.onion".into(),
698                    incoming: false,
699                    ip: "".into(),
700                    live_time: 76755,
701                    local_ip: false,
702                    localhost: false,
703                    peer_id: "0000000000000001".into(),
704                    port: "".into(),
705                    pruning_seed: 389,
706                    recv_count: 237657,
707                    recv_idle_time: 120,
708                    rpc_credits_per_hash: 0,
709                    rpc_port: 0,
710                    send_count: 3370566,
711                    send_idle_time: 120,
712                    state: cuprate_types::ConnectionState::Normal,
713                    support_flags: 0
714                }
715            ],
716        }
717    )]
718    ResponseBase {
719        // FIXME: This is a `std::list` in `monerod` because...?
720        connections: Vec<ConnectionInfo>,
721    }
722}
723
724define_request_and_response! {
725    get_info,
726    cc73fe71162d564ffda8e549b79a350bca53c454 =>
727    core_rpc_server_commands_defs.h => 693..=789,
728    GetInfo (empty),
729    Request {},
730
731    #[doc = serde_doc_test!(
732        GET_INFO_RESPONSE => GetInfoResponse {
733            base: AccessResponseBase::OK,
734            adjusted_time: 1721245289,
735            alt_blocks_count: 16,
736            block_size_limit: 600000,
737            block_size_median: 300000,
738            block_weight_limit: 600000,
739            block_weight_median: 300000,
740            bootstrap_daemon_address: "".into(),
741            busy_syncing: false,
742            cumulative_difficulty: 366127702242611947,
743            cumulative_difficulty_top64: 0,
744            database_size: 235169075200,
745            difficulty: 280716748706,
746            difficulty_top64: 0,
747            free_space: 30521749504,
748            grey_peerlist_size: 4996,
749            height: 3195028,
750            height_without_bootstrap: 3195028,
751            incoming_connections_count: 62,
752            mainnet: true,
753            nettype: "mainnet".into(),
754            offline: false,
755            outgoing_connections_count: 1143,
756            restricted: false,
757            rpc_connections_count: 1,
758            stagenet: false,
759            start_time: 1720462427,
760            synchronized: true,
761            target: 120,
762            target_height: 0,
763            testnet: false,
764            top_block_hash: "bdf06d18ed1931a8ee62654e9b6478cc459bc7072628b8e36f4524d339552946".into(),
765            tx_count: 43205750,
766            tx_pool_size: 12,
767            update_available: false,
768            version: "0.18.3.3-release".into(),
769            was_bootstrap_ever_used: false,
770            white_peerlist_size: 1000,
771            wide_cumulative_difficulty: "0x514bf349299d2eb".into(),
772            wide_difficulty: "0x415c05a7a2".into()
773        }
774    )]
775    AccessResponseBase {
776        adjusted_time: u64,
777        alt_blocks_count: u64,
778        block_size_limit: u64,
779        block_size_median: u64,
780        block_weight_limit: u64,
781        block_weight_median: u64,
782        bootstrap_daemon_address: String,
783        busy_syncing: bool,
784        cumulative_difficulty_top64: u64,
785        cumulative_difficulty: u64,
786        database_size: u64,
787        difficulty_top64: u64,
788        difficulty: u64,
789        free_space: u64,
790        grey_peerlist_size: u64,
791        height: u64,
792        height_without_bootstrap: u64,
793        incoming_connections_count: u64,
794        mainnet: bool,
795        nettype: String,
796        offline: bool,
797        outgoing_connections_count: u64,
798        restricted: bool,
799        rpc_connections_count: u64,
800        stagenet: bool,
801        start_time: u64,
802        synchronized: bool,
803        target_height: u64,
804        target: u64,
805        testnet: bool,
806        top_block_hash: String,
807        tx_count: u64,
808        tx_pool_size: u64,
809        update_available: bool,
810        version: String,
811        was_bootstrap_ever_used: bool,
812        white_peerlist_size: u64,
813        wide_cumulative_difficulty: String,
814        wide_difficulty: String,
815    }
816}
817
818define_request_and_response! {
819    hard_fork_info,
820    cc73fe71162d564ffda8e549b79a350bca53c454 =>
821    core_rpc_server_commands_defs.h => 1958..=1995,
822    HardForkInfo,
823
824    #[doc = serde_doc_test!(
825        HARD_FORK_INFO_REQUEST => HardForkInfoRequest {
826            version: 16,
827        }
828    )]
829    #[derive(Copy)]
830    Request {
831        version: u8,
832    },
833
834    #[doc = serde_doc_test!(
835        HARD_FORK_INFO_RESPONSE => HardForkInfoResponse {
836            base: AccessResponseBase::OK,
837            earliest_height: 2689608,
838            enabled: true,
839            state: 0,
840            threshold: 0,
841            version: 16,
842            votes: 10080,
843            voting: 16,
844            window: 10080
845        }
846    )]
847    AccessResponseBase {
848        earliest_height: u64,
849        enabled: bool,
850        state: u32,
851        threshold: u32,
852        version: u8,
853        votes: u32,
854        voting: u8,
855        window: u32,
856    }
857}
858
859define_request_and_response! {
860    set_bans,
861    cc73fe71162d564ffda8e549b79a350bca53c454 =>
862    core_rpc_server_commands_defs.h => 2032..=2067,
863
864    SetBans (restricted),
865
866    #[doc = serde_doc_test!(
867        SET_BANS_REQUEST => SetBansRequest {
868            bans: vec![ SetBan {
869                host: "192.168.1.51".into(),
870                ip: 0,
871                ban: true,
872                seconds: 30
873            }]
874        }
875    )]
876    Request {
877        bans: Vec<SetBan>,
878    },
879
880    #[doc = serde_doc_test!(
881        SET_BANS_RESPONSE => SetBansResponse {
882            base: ResponseBase::OK,
883        }
884    )]
885    ResponseBase {}
886}
887
888define_request_and_response! {
889    get_bans,
890    cc73fe71162d564ffda8e549b79a350bca53c454 =>
891    core_rpc_server_commands_defs.h => 1997..=2030,
892    GetBans (restricted, empty),
893    Request {},
894
895    #[doc = serde_doc_test!(
896        GET_BANS_RESPONSE => GetBansResponse {
897            base: ResponseBase::OK,
898            bans: vec![
899                GetBan {
900                    host: "104.248.206.131".into(),
901                    ip: 2211379304,
902                    seconds: 689754
903                },
904                GetBan {
905                    host: "209.222.252.0/24".into(),
906                    ip: 0,
907                    seconds: 689754
908                }
909            ]
910        }
911    )]
912    ResponseBase {
913        bans: Vec<GetBan>,
914    }
915}
916
917define_request_and_response! {
918    banned,
919    cc73fe71162d564ffda8e549b79a350bca53c454 =>
920    core_rpc_server_commands_defs.h => 2069..=2094,
921
922    Banned (restricted),
923
924    #[doc = serde_doc_test!(
925        BANNED_REQUEST => BannedRequest {
926            address: "95.216.203.255".into(),
927        }
928    )]
929    Request {
930        address: String,
931    },
932
933    #[doc = serde_doc_test!(
934        BANNED_RESPONSE => BannedResponse {
935            banned: true,
936            seconds: 689655,
937            status: Status::Ok,
938        }
939    )]
940    Response {
941        banned: bool,
942        seconds: u32,
943        status: Status,
944    }
945}
946
947define_request_and_response! {
948    flush_txpool,
949    cc73fe71162d564ffda8e549b79a350bca53c454 =>
950    core_rpc_server_commands_defs.h => 2096..=2116,
951
952    FlushTransactionPool (restricted),
953
954    #[doc = serde_doc_test!(
955        FLUSH_TRANSACTION_POOL_REQUEST => FlushTransactionPoolRequest {
956            txids: vec!["dc16fa8eaffe1484ca9014ea050e13131d3acf23b419f33bb4cc0b32b6c49308".into()],
957        }
958    )]
959    Request {
960        txids: Vec<String> = default_vec::<String>(), "default_vec",
961    },
962
963    #[doc = serde_doc_test!(
964        FLUSH_TRANSACTION_POOL_RESPONSE => FlushTransactionPoolResponse {
965            status: Status::Ok,
966        }
967    )]
968    #[repr(transparent)]
969    Response {
970        status: Status,
971    }
972}
973
974define_request_and_response! {
975    get_output_histogram,
976    cc73fe71162d564ffda8e549b79a350bca53c454 =>
977    core_rpc_server_commands_defs.h => 2118..=2168,
978    GetOutputHistogram,
979
980    #[doc = serde_doc_test!(
981        GET_OUTPUT_HISTOGRAM_REQUEST => GetOutputHistogramRequest {
982            amounts: vec![20000000000],
983            min_count: 0,
984            max_count: 0,
985            unlocked: false,
986            recent_cutoff: 0,
987        }
988    )]
989    Request {
990        amounts: Vec<u64>,
991        min_count: u64 = default_zero::<u64>(), "default_zero",
992        max_count: u64 = default_zero::<u64>(), "default_zero",
993        unlocked: bool = default_false(), "default_false",
994        recent_cutoff: u64 = default_zero::<u64>(), "default_zero",
995    },
996
997    #[doc = serde_doc_test!(
998        GET_OUTPUT_HISTOGRAM_RESPONSE => GetOutputHistogramResponse {
999            base: AccessResponseBase::OK,
1000            histogram: vec![HistogramEntry {
1001                amount: 20000000000,
1002                recent_instances: 0,
1003                total_instances: 381490,
1004                unlocked_instances: 0
1005            }]
1006        }
1007    )]
1008    AccessResponseBase {
1009        histogram: Vec<HistogramEntry>,
1010    }
1011}
1012
1013define_request_and_response! {
1014    get_coinbase_tx_sum,
1015    cc73fe71162d564ffda8e549b79a350bca53c454 =>
1016    core_rpc_server_commands_defs.h => 2213..=2248,
1017
1018    GetCoinbaseTxSum (restricted),
1019
1020    #[doc = serde_doc_test!(
1021        GET_COINBASE_TX_SUM_REQUEST => GetCoinbaseTxSumRequest {
1022            height: 1563078,
1023            count: 2
1024        }
1025    )]
1026    Request {
1027        height: u64,
1028        count: u64,
1029    },
1030
1031    #[doc = serde_doc_test!(
1032        GET_COINBASE_TX_SUM_RESPONSE => GetCoinbaseTxSumResponse {
1033            base: AccessResponseBase::OK,
1034            emission_amount: 9387854817320,
1035            emission_amount_top64: 0,
1036            fee_amount: 83981380000,
1037            fee_amount_top64: 0,
1038            wide_emission_amount: "0x889c7c06828".into(),
1039            wide_fee_amount: "0x138dae29a0".into()
1040        }
1041    )]
1042    AccessResponseBase {
1043        emission_amount: u64,
1044        emission_amount_top64: u64,
1045        fee_amount: u64,
1046        fee_amount_top64: u64,
1047        wide_emission_amount: String,
1048        wide_fee_amount: String,
1049    }
1050}
1051
1052define_request_and_response! {
1053    get_version,
1054    cc73fe71162d564ffda8e549b79a350bca53c454 =>
1055    core_rpc_server_commands_defs.h => 2170..=2211,
1056
1057    GetVersion (empty),
1058    Request {},
1059
1060    #[doc = serde_doc_test!(
1061        GET_VERSION_RESPONSE => GetVersionResponse {
1062            base: ResponseBase::OK,
1063            current_height: 3195051,
1064            hard_forks: vec![
1065                HardforkEntry {
1066                    height: 1,
1067                    hf_version: 1
1068                },
1069                HardforkEntry {
1070                    height: 1009827,
1071                    hf_version: 2
1072                },
1073                HardforkEntry {
1074                    height: 1141317,
1075                    hf_version: 3
1076                },
1077                HardforkEntry {
1078                    height: 1220516,
1079                    hf_version: 4
1080                },
1081                HardforkEntry {
1082                    height: 1288616,
1083                    hf_version: 5
1084                },
1085                HardforkEntry {
1086                    height: 1400000,
1087                    hf_version: 6
1088                },
1089                HardforkEntry {
1090                    height: 1546000,
1091                    hf_version: 7
1092                },
1093                HardforkEntry {
1094                    height: 1685555,
1095                    hf_version: 8
1096                },
1097                HardforkEntry {
1098                    height: 1686275,
1099                    hf_version: 9
1100                },
1101                HardforkEntry {
1102                    height: 1788000,
1103                    hf_version: 10
1104                },
1105                HardforkEntry {
1106                    height: 1788720,
1107                    hf_version: 11
1108                },
1109                HardforkEntry {
1110                    height: 1978433,
1111                    hf_version: 12
1112                },
1113                HardforkEntry {
1114                    height: 2210000,
1115                    hf_version: 13
1116                },
1117                HardforkEntry {
1118                    height: 2210720,
1119                    hf_version: 14
1120                },
1121                HardforkEntry {
1122                    height: 2688888,
1123                    hf_version: 15
1124                },
1125                HardforkEntry {
1126                    height: 2689608,
1127                    hf_version: 16
1128                }
1129            ],
1130            release: true,
1131            version: 196621,
1132            target_height: 0,
1133        }
1134    )]
1135    ResponseBase {
1136        version: u32,
1137        release: bool,
1138        current_height: u64 = default_zero::<u64>(), "default_zero",
1139        target_height: u64 = default_zero::<u64>(), "default_zero",
1140        hard_forks: Vec<HardforkEntry> = default_vec(), "default_vec",
1141    }
1142}
1143
1144define_request_and_response! {
1145    get_fee_estimate,
1146    cc73fe71162d564ffda8e549b79a350bca53c454 =>
1147    core_rpc_server_commands_defs.h => 2250..=2277,
1148
1149    GetFeeEstimate,
1150
1151    Request {
1152        grace_blocks: u64 = default_zero::<u64>(), "default_zero",
1153    },
1154
1155    #[doc = serde_doc_test!(
1156        GET_FEE_ESTIMATE_RESPONSE => GetFeeEstimateResponse {
1157            base: AccessResponseBase::OK,
1158            fee: 20000,
1159            fees: vec![20000,80000,320000,4000000],
1160            quantization_mask: 10000,
1161        }
1162    )]
1163    AccessResponseBase {
1164        fee: u64,
1165        fees: Vec<u64>,
1166        quantization_mask: u64 = default_one::<u64>(), "default_one",
1167    }
1168}
1169
1170define_request_and_response! {
1171    get_alternate_chains,
1172    cc73fe71162d564ffda8e549b79a350bca53c454 =>
1173    core_rpc_server_commands_defs.h => 2279..=2310,
1174    GetAlternateChains (restricted, empty),
1175    Request {},
1176
1177    #[doc = serde_doc_test!(
1178        GET_ALTERNATE_CHAINS_RESPONSE => GetAlternateChainsResponse {
1179            base: ResponseBase::OK,
1180            chains: vec![
1181                ChainInfo {
1182                    block_hash: "4826c7d45d7cf4f02985b5c405b0e5d7f92c8d25e015492ce19aa3b209295dce".into(),
1183                    block_hashes: vec!["4826c7d45d7cf4f02985b5c405b0e5d7f92c8d25e015492ce19aa3b209295dce".into()],
1184                    difficulty: 357404825113208373,
1185                    difficulty_top64: 0,
1186                    height: 3167471,
1187                    length: 1,
1188                    main_chain_parent_block: "69b5075ea627d6ba06b1c30b7e023884eeaef5282cf58ec847dab838ddbcdd86".into(),
1189                    wide_difficulty: "0x4f5c1cb79e22635".into(),
1190                },
1191                ChainInfo {
1192                    block_hash: "33ee476f5a1c5b9d889274cbbe171f5e0112df7ed69021918042525485deb401".into(),
1193                    block_hashes: vec!["33ee476f5a1c5b9d889274cbbe171f5e0112df7ed69021918042525485deb401".into()],
1194                    difficulty: 354736121711617293,
1195                    difficulty_top64: 0,
1196                    height: 3157465,
1197                    length: 1,
1198                    main_chain_parent_block: "fd522fcc4cefe5c8c0e5c5600981b3151772c285df3a4e38e5c4011cf466d2cb".into(),
1199                    wide_difficulty: "0x4ec469f8b9ee50d".into(),
1200                }
1201            ],
1202        }
1203    )]
1204    ResponseBase {
1205        chains: Vec<ChainInfo>,
1206    }
1207}
1208
1209define_request_and_response! {
1210    relay_tx,
1211    cc73fe71162d564ffda8e549b79a350bca53c454 =>
1212    core_rpc_server_commands_defs.h => 2361..=2381,
1213
1214    RelayTx (restricted),
1215
1216    #[doc = serde_doc_test!(
1217        RELAY_TX_REQUEST => RelayTxRequest {
1218            txids: vec!["9fd75c429cbe52da9a52f2ffc5fbd107fe7fd2099c0d8de274dc8a67e0c98613".into()]
1219        }
1220    )]
1221    Request {
1222        txids: Vec<String>,
1223    },
1224
1225    #[doc = serde_doc_test!(
1226        RELAY_TX_RESPONSE => RelayTxResponse {
1227            status: Status::Ok,
1228        }
1229    )]
1230    #[repr(transparent)]
1231    Response {
1232        status: Status,
1233    }
1234}
1235
1236define_request_and_response! {
1237    sync_info,
1238    cc73fe71162d564ffda8e549b79a350bca53c454 =>
1239    core_rpc_server_commands_defs.h => 2383..=2443,
1240
1241    SyncInfo (restricted, empty),
1242
1243    Request {},
1244
1245    #[doc = serde_doc_test!(
1246        SYNC_INFO_RESPONSE => SyncInfoResponse {
1247            base: AccessResponseBase::OK,
1248            height: 3195157,
1249            next_needed_pruning_seed: 0,
1250            overview: "[]".into(),
1251            spans: vec![],
1252            peers: vec![
1253                SyncInfoPeer {
1254                    info: ConnectionInfo {
1255                        address: "142.93.128.65:44986".into(),
1256                        address_type: cuprate_types::AddressType::Ipv4,
1257                        avg_download: 1,
1258                        avg_upload: 1,
1259                        connection_id: "a5803c4c2dac49e7b201dccdef54c862".into(),
1260                        current_download: 2,
1261                        current_upload: 1,
1262                        height: 3195157,
1263                        host: "142.93.128.65".into(),
1264                        incoming: true,
1265                        ip: "142.93.128.65".into(),
1266                        live_time: 18,
1267                        local_ip: false,
1268                        localhost: false,
1269                        peer_id: "6830e9764d3e5687".into(),
1270                        port: "44986".into(),
1271                        pruning_seed: 0,
1272                        recv_count: 20340,
1273                        recv_idle_time: 0,
1274                        rpc_credits_per_hash: 0,
1275                        rpc_port: 18089,
1276                        send_count: 32235,
1277                        send_idle_time: 6,
1278                        state: cuprate_types::ConnectionState::Normal,
1279                        support_flags: 1
1280                    }
1281                },
1282                SyncInfoPeer {
1283                    info: ConnectionInfo {
1284                        address: "4iykytmumafy5kjahdqc7uzgcs34s2vwsadfjpk4znvsa5vmcxeup2qd.onion:18083".into(),
1285                        address_type: cuprate_types::AddressType::Tor,
1286                        avg_download: 0,
1287                        avg_upload: 0,
1288                        connection_id: "277f7c821bc546878c8bd29977e780f5".into(),
1289                        current_download: 0,
1290                        current_upload: 0,
1291                        height: 3195157,
1292                        host: "4iykytmumafy5kjahdqc7uzgcs34s2vwsadfjpk4znvsa5vmcxeup2qd.onion".into(),
1293                        incoming: false,
1294                        ip: "".into(),
1295                        live_time: 2246,
1296                        local_ip: false,
1297                        localhost: false,
1298                        peer_id: "0000000000000001".into(),
1299                        port: "".into(),
1300                        pruning_seed: 389,
1301                        recv_count: 65164,
1302                        recv_idle_time: 15,
1303                        rpc_credits_per_hash: 0,
1304                        rpc_port: 0,
1305                        send_count: 99120,
1306                        send_idle_time: 15,
1307                        state: cuprate_types::ConnectionState::Normal,
1308                        support_flags: 0
1309                    }
1310                }
1311            ],
1312            target_height: 0,
1313        }
1314    )]
1315    AccessResponseBase {
1316        height: u64,
1317        next_needed_pruning_seed: u32,
1318        overview: String,
1319        // FIXME: This is a `std::list` in `monerod` because...?
1320        peers: Vec<SyncInfoPeer> = default_vec::<SyncInfoPeer>(), "default_vec",
1321        // FIXME: This is a `std::list` in `monerod` because...?
1322        spans: Vec<Span> = default_vec::<Span>(), "default_vec",
1323        target_height: u64,
1324    }
1325}
1326
1327define_request_and_response! {
1328    get_txpool_backlog,
1329    cc73fe71162d564ffda8e549b79a350bca53c454 =>
1330    core_rpc_server_commands_defs.h => 1637..=1664,
1331    GetTransactionPoolBacklog (empty),
1332    Request {},
1333
1334    // TODO: enable test after binary string impl.
1335    // #[doc = serde_doc_test!(
1336    //     GET_TRANSACTION_POOL_BACKLOG_RESPONSE => GetTransactionPoolBacklogResponse {
1337    //         base: ResponseBase::OK,
1338    //         backlog: "...Binary...".into(),
1339    //     }
1340    // )]
1341    ResponseBase {
1342        // TODO: this is a [`BinaryString`].
1343        backlog: Vec<TxBacklogEntry>,
1344    }
1345}
1346
1347define_request_and_response! {
1348    get_output_distribution,
1349    cc73fe71162d564ffda8e549b79a350bca53c454 =>
1350    core_rpc_server_commands_defs.h => 2445..=2520,
1351
1352    /// This type is also used in the (undocumented)
1353    /// [`/get_output_distribution.bin`](https://github.com/monero-project/monero/blob/cc73fe71162d564ffda8e549b79a350bca53c454/src/rpc/core_rpc_server.h#L138)
1354    /// binary endpoint.
1355    GetOutputDistribution,
1356
1357    #[doc = serde_doc_test!(
1358        GET_OUTPUT_DISTRIBUTION_REQUEST => GetOutputDistributionRequest {
1359            amounts: vec![628780000],
1360            from_height: 1462078,
1361            binary: true,
1362            compress: false,
1363            cumulative: false,
1364            to_height: 0,
1365        }
1366    )]
1367    Request {
1368        amounts: Vec<u64>,
1369        binary: bool = default_true(), "default_true",
1370        compress: bool = default_false(), "default_false",
1371        cumulative: bool = default_false(), "default_false",
1372        from_height: u64 = default_zero::<u64>(), "default_zero",
1373        to_height: u64 = default_zero::<u64>(), "default_zero",
1374    },
1375
1376    // TODO: enable test after binary string impl.
1377    // #[doc = serde_doc_test!(
1378    //     GET_OUTPUT_DISTRIBUTION_RESPONSE => GetOutputDistributionResponse {
1379    //         base: AccessResponseBase::OK,
1380    //         distributions: vec![Distribution::Uncompressed(DistributionUncompressed {
1381    //             start_height: 1462078,
1382    //             base: 0,
1383    //             distribution: vec![],
1384    //             amount: 2628780000,
1385    //             binary: true,
1386    //         })],
1387    //     }
1388    // )]
1389    AccessResponseBase {
1390        distributions: Vec<Distribution>,
1391    }
1392}
1393
1394define_request_and_response! {
1395    get_miner_data,
1396    cc73fe71162d564ffda8e549b79a350bca53c454 =>
1397    core_rpc_server_commands_defs.h => 996..=1044,
1398    GetMinerData (empty),
1399    Request {},
1400
1401    #[doc = serde_doc_test!(
1402        GET_MINER_DATA_RESPONSE => GetMinerDataResponse {
1403            base: ResponseBase::OK,
1404            already_generated_coins: 18186022843595960691,
1405            difficulty: "0x48afae42de".into(),
1406            height: 2731375,
1407            major_version: 16,
1408            median_weight: 300000,
1409            prev_id: "78d50c5894d187c4946d54410990ca59a75017628174a9e8c7055fa4ca5c7c6d".into(),
1410            seed_hash: "a6b869d50eca3a43ec26fe4c369859cf36ae37ce6ecb76457d31ffeb8a6ca8a6".into(),
1411            tx_backlog: vec![
1412                GetMinerDataTxBacklogEntry {
1413                    fee: 30700000,
1414                    id: "9868490d6bb9207fdd9cf17ca1f6c791b92ca97de0365855ea5c089f67c22208".into(),
1415                    weight: 1535
1416                },
1417                GetMinerDataTxBacklogEntry {
1418                    fee: 44280000,
1419                    id: "b6000b02bbec71e18ad704bcae09fb6e5ae86d897ced14a718753e76e86c0a0a".into(),
1420                    weight: 2214
1421                },
1422            ],
1423        }
1424    )]
1425    ResponseBase {
1426        major_version: u8,
1427        height: u64,
1428        prev_id: String,
1429        seed_hash: String,
1430        difficulty: String,
1431        median_weight: u64,
1432        already_generated_coins: u64,
1433        tx_backlog: Vec<GetMinerDataTxBacklogEntry>,
1434    }
1435}
1436
1437define_request_and_response! {
1438    prune_blockchain,
1439    cc73fe71162d564ffda8e549b79a350bca53c454 =>
1440    core_rpc_server_commands_defs.h => 2747..=2772,
1441
1442    PruneBlockchain (restricted),
1443
1444    #[derive(Copy)]
1445    #[doc = serde_doc_test!(
1446        PRUNE_BLOCKCHAIN_REQUEST => PruneBlockchainRequest {
1447            check: true
1448        }
1449    )]
1450    Request {
1451        check: bool = default_false(), "default_false",
1452    },
1453
1454    #[doc = serde_doc_test!(
1455        PRUNE_BLOCKCHAIN_RESPONSE => PruneBlockchainResponse {
1456            base: ResponseBase::OK,
1457            pruned: true,
1458            pruning_seed: 387,
1459        }
1460    )]
1461    ResponseBase {
1462        pruned: bool,
1463        pruning_seed: u32,
1464    }
1465}
1466
1467define_request_and_response! {
1468    calc_pow,
1469    cc73fe71162d564ffda8e549b79a350bca53c454 =>
1470    core_rpc_server_commands_defs.h => 1046..=1066,
1471
1472    CalcPow (restricted),
1473
1474    #[doc = serde_doc_test!(
1475        CALC_POW_REQUEST => CalcPowRequest {
1476            major_version: 14,
1477            height: 2286447,
1478            block_blob: "0e0ed286da8006ecdc1aab3033cf1716c52f13f9d8ae0051615a2453643de94643b550d543becd0000000002abc78b0101ffefc68b0101fcfcf0d4b422025014bb4a1eade6622fd781cb1063381cad396efa69719b41aa28b4fce8c7ad4b5f019ce1dc670456b24a5e03c2d9058a2df10fec779e2579753b1847b74ee644f16b023c00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000051399a1bc46a846474f5b33db24eae173a26393b976054ee14f9feefe99925233802867097564c9db7a36af5bb5ed33ab46e63092bd8d32cef121608c3258edd55562812e21cc7e3ac73045745a72f7d74581d9a0849d6f30e8b2923171253e864f4e9ddea3acb5bc755f1c4a878130a70c26297540bc0b7a57affb6b35c1f03d8dbd54ece8457531f8cba15bb74516779c01193e212050423020e45aa2c15dcb".into(),
1479            seed_hash: "d432f499205150873b2572b5f033c9c6e4b7c6f3394bd2dd93822cd7085e7307".into(),
1480        }
1481    )]
1482    Request {
1483        major_version: u8,
1484        height: u64,
1485        block_blob: String,
1486        seed_hash: String,
1487    },
1488
1489    #[doc = serde_doc_test!(
1490        CALC_POW_RESPONSE => CalcPowResponse {
1491            pow_hash: "d0402d6834e26fb94a9ce38c6424d27d2069896a9b8b1ce685d79936bca6e0a8".into(),
1492        }
1493    )]
1494    #[cfg_attr(feature = "serde", serde(transparent))]
1495    #[repr(transparent)]
1496    Response {
1497        pow_hash: String,
1498    }
1499}
1500
1501define_request_and_response! {
1502    flush_cache,
1503    cc73fe71162d564ffda8e549b79a350bca53c454 =>
1504    core_rpc_server_commands_defs.h => 2774..=2796,
1505
1506    FlushCache (restricted),
1507
1508    #[derive(Copy)]
1509    #[doc = serde_doc_test!(
1510        FLUSH_CACHE_REQUEST => FlushCacheRequest {
1511            bad_txs: true,
1512            bad_blocks: true
1513        }
1514    )]
1515    Request {
1516        bad_txs: bool = default_false(), "default_false",
1517        bad_blocks: bool = default_false(), "default_false",
1518    },
1519
1520    #[doc = serde_doc_test!(
1521        FLUSH_CACHE_RESPONSE => FlushCacheResponse {
1522            base: ResponseBase::OK,
1523        }
1524    )]
1525    ResponseBase {}
1526}
1527
1528define_request_and_response! {
1529    add_aux_pow,
1530    cc73fe71162d564ffda8e549b79a350bca53c454 =>
1531    core_rpc_server_commands_defs.h => 1068..=1112,
1532
1533    AddAuxPow,
1534
1535    #[doc = serde_doc_test!(
1536        ADD_AUX_POW_REQUEST => AddAuxPowRequest {
1537            blocktemplate_blob: "1010f4bae0b4069d648e741d85ca0e7acb4501f051b27e9b107d3cd7a3f03aa7f776089117c81a0000000002c681c30101ff8a81c3010180e0a596bb11033b7eedf47baf878f3490cb20b696079c34bd017fe59b0d070e74d73ffabc4bb0e05f011decb630f3148d0163b3bd39690dde4078e4cfb69fecf020d6278a27bad10c58023c0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000".into(),
1538            aux_pow: vec![AuxPow {
1539                id: "3200b4ea97c3b2081cd4190b58e49572b2319fed00d030ad51809dff06b5d8c8".into(),
1540                hash: "7b35762de164b20885e15dbe656b1138db06bb402fa1796f5765a23933d8859a".into()
1541            }]
1542        }
1543    )]
1544    Request {
1545        blocktemplate_blob: String,
1546        aux_pow: Vec<AuxPow>,
1547    },
1548
1549    #[doc = serde_doc_test!(
1550        ADD_AUX_POW_RESPONSE => AddAuxPowResponse {
1551            base: ResponseBase::OK,
1552            aux_pow: vec![AuxPow {
1553                hash: "7b35762de164b20885e15dbe656b1138db06bb402fa1796f5765a23933d8859a".into(),
1554                id: "3200b4ea97c3b2081cd4190b58e49572b2319fed00d030ad51809dff06b5d8c8".into(),
1555            }],
1556            blockhashing_blob: "1010ee97e2a106e9f8ebe8887e5b609949ac8ea6143e560ed13552b110cb009b21f0cfca1eaccf00000000b2685c1283a646bc9020c758daa443be145b7370ce5a6efacb3e614117032e2c22".into(),
1557            blocktemplate_blob: "1010f4bae0b4069d648e741d85ca0e7acb4501f051b27e9b107d3cd7a3f03aa7f776089117c81a0000000002c681c30101ff8a81c3010180e0a596bb11033b7eedf47baf878f3490cb20b696079c34bd017fe59b0d070e74d73ffabc4bb0e05f011decb630f3148d0163b3bd39690dde4078e4cfb69fecf020d6278a27bad10c58023c0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000".into(),
1558            merkle_root: "7b35762de164b20885e15dbe656b1138db06bb402fa1796f5765a23933d8859a".into(),
1559            merkle_tree_depth: 0,
1560        }
1561    )]
1562    ResponseBase {
1563      blocktemplate_blob: String,
1564      blockhashing_blob: String,
1565      merkle_root: String,
1566      merkle_tree_depth: u64,
1567      aux_pow: Vec<AuxPow>,
1568    }
1569}
1570
1571define_request_and_response! {
1572    UNDOCUMENTED_METHOD,
1573    cc73fe71162d564ffda8e549b79a350bca53c454 =>
1574    core_rpc_server_commands_defs.h => 2798..=2823,
1575
1576    GetTxIdsLoose,
1577
1578    Request {
1579        txid_template: String,
1580        num_matching_bits: u32,
1581    },
1582    ResponseBase {
1583        txids: Vec<String>,
1584    }
1585}
1586
1587//---------------------------------------------------------------------------------------------------- Request
1588/// JSON-RPC requests.
1589///
1590/// This enum contains all [`crate::json`] requests.
1591///
1592/// See also: [`JsonRpcResponse`].
1593///
1594/// TODO: document and test (de)serialization behavior after figuring out `method/params`.
1595#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
1596#[cfg_attr(feature = "serde", derive(Deserialize, Serialize))]
1597#[cfg_attr(
1598    feature = "serde",
1599    serde(rename_all = "snake_case", tag = "method", content = "params")
1600)]
1601pub enum JsonRpcRequest {
1602    GetBlockCount(GetBlockCountRequest),
1603    OnGetBlockHash(OnGetBlockHashRequest),
1604    SubmitBlock(SubmitBlockRequest),
1605    GenerateBlocks(GenerateBlocksRequest),
1606    GetLastBlockHeader(GetLastBlockHeaderRequest),
1607    GetBlockHeaderByHash(GetBlockHeaderByHashRequest),
1608    GetBlockHeaderByHeight(GetBlockHeaderByHeightRequest),
1609    GetBlockHeadersRange(GetBlockHeadersRangeRequest),
1610    GetBlock(GetBlockRequest),
1611    GetConnections(GetConnectionsRequest),
1612    GetInfo(GetInfoRequest),
1613    HardForkInfo(HardForkInfoRequest),
1614    SetBans(SetBansRequest),
1615    GetBans(GetBansRequest),
1616    Banned(BannedRequest),
1617    FlushTransactionPool(FlushTransactionPoolRequest),
1618    GetOutputHistogram(GetOutputHistogramRequest),
1619    GetCoinbaseTxSum(GetCoinbaseTxSumRequest),
1620    GetVersion(GetVersionRequest),
1621    GetFeeEstimate(GetFeeEstimateRequest),
1622    GetAlternateChains(GetAlternateChainsRequest),
1623    RelayTx(RelayTxRequest),
1624    SyncInfo(SyncInfoRequest),
1625    GetTransactionPoolBacklog(GetTransactionPoolBacklogRequest),
1626    GetMinerData(GetMinerDataRequest),
1627    PruneBlockchain(PruneBlockchainRequest),
1628    CalcPow(CalcPowRequest),
1629    FlushCache(FlushCacheRequest),
1630    AddAuxPow(AddAuxPowRequest),
1631    GetTxIdsLoose(GetTxIdsLooseRequest),
1632}
1633
1634impl RpcCallValue for JsonRpcRequest {
1635    fn is_restricted(&self) -> bool {
1636        match self {
1637            Self::GetBlockCount(x) => x.is_restricted(),
1638            Self::OnGetBlockHash(x) => x.is_restricted(),
1639            Self::SubmitBlock(x) => x.is_restricted(),
1640            Self::GetLastBlockHeader(x) => x.is_restricted(),
1641            Self::GetBlockHeaderByHash(x) => x.is_restricted(),
1642            Self::GetBlockHeaderByHeight(x) => x.is_restricted(),
1643            Self::GetBlockHeadersRange(x) => x.is_restricted(),
1644            Self::GetBlock(x) => x.is_restricted(),
1645            Self::GetInfo(x) => x.is_restricted(),
1646            Self::HardForkInfo(x) => x.is_restricted(),
1647            Self::GetOutputHistogram(x) => x.is_restricted(),
1648            Self::GetVersion(x) => x.is_restricted(),
1649            Self::GetFeeEstimate(x) => x.is_restricted(),
1650            Self::GetTransactionPoolBacklog(x) => x.is_restricted(),
1651            Self::GetMinerData(x) => x.is_restricted(),
1652            Self::AddAuxPow(x) => x.is_restricted(),
1653            Self::GetTxIdsLoose(x) => x.is_restricted(),
1654            Self::GenerateBlocks(x) => x.is_restricted(),
1655            Self::GetConnections(x) => x.is_restricted(),
1656            Self::SetBans(x) => x.is_restricted(),
1657            Self::GetBans(x) => x.is_restricted(),
1658            Self::Banned(x) => x.is_restricted(),
1659            Self::FlushTransactionPool(x) => x.is_restricted(),
1660            Self::GetCoinbaseTxSum(x) => x.is_restricted(),
1661            Self::GetAlternateChains(x) => x.is_restricted(),
1662            Self::RelayTx(x) => x.is_restricted(),
1663            Self::SyncInfo(x) => x.is_restricted(),
1664            Self::PruneBlockchain(x) => x.is_restricted(),
1665            Self::CalcPow(x) => x.is_restricted(),
1666            Self::FlushCache(x) => x.is_restricted(),
1667        }
1668    }
1669
1670    fn is_empty(&self) -> bool {
1671        match self {
1672            Self::GetBlockCount(x) => x.is_empty(),
1673            Self::OnGetBlockHash(x) => x.is_empty(),
1674            Self::SubmitBlock(x) => x.is_empty(),
1675            Self::GetLastBlockHeader(x) => x.is_empty(),
1676            Self::GetBlockHeaderByHash(x) => x.is_empty(),
1677            Self::GetBlockHeaderByHeight(x) => x.is_empty(),
1678            Self::GetBlockHeadersRange(x) => x.is_empty(),
1679            Self::GetBlock(x) => x.is_empty(),
1680            Self::GetInfo(x) => x.is_empty(),
1681            Self::HardForkInfo(x) => x.is_empty(),
1682            Self::GetOutputHistogram(x) => x.is_empty(),
1683            Self::GetVersion(x) => x.is_empty(),
1684            Self::GetFeeEstimate(x) => x.is_empty(),
1685            Self::GetTransactionPoolBacklog(x) => x.is_empty(),
1686            Self::GetMinerData(x) => x.is_empty(),
1687            Self::AddAuxPow(x) => x.is_empty(),
1688            Self::GetTxIdsLoose(x) => x.is_empty(),
1689            Self::GenerateBlocks(x) => x.is_empty(),
1690            Self::GetConnections(x) => x.is_empty(),
1691            Self::SetBans(x) => x.is_empty(),
1692            Self::GetBans(x) => x.is_empty(),
1693            Self::Banned(x) => x.is_empty(),
1694            Self::FlushTransactionPool(x) => x.is_empty(),
1695            Self::GetCoinbaseTxSum(x) => x.is_empty(),
1696            Self::GetAlternateChains(x) => x.is_empty(),
1697            Self::RelayTx(x) => x.is_empty(),
1698            Self::SyncInfo(x) => x.is_empty(),
1699            Self::PruneBlockchain(x) => x.is_empty(),
1700            Self::CalcPow(x) => x.is_empty(),
1701            Self::FlushCache(x) => x.is_empty(),
1702        }
1703    }
1704}
1705
1706//---------------------------------------------------------------------------------------------------- Response
1707/// JSON-RPC responses.
1708///
1709/// This enum contains all [`crate::json`] responses.
1710///
1711/// See also: [`JsonRpcRequest`].
1712///
1713/// # (De)serialization
1714/// The `serde` implementation will (de)serialize from
1715/// the inner variant itself, e.g. [`JsonRpcRequest::Banned`]
1716/// has the same (de)serialization as [`BannedResponse`].
1717///
1718/// ```rust
1719/// use cuprate_rpc_types::{misc::*, json::*};
1720///
1721/// let response = JsonRpcResponse::Banned(BannedResponse {
1722///     banned: true,
1723///     seconds: 123,
1724///     status: Status::Ok,
1725/// });
1726/// let json = serde_json::to_string(&response).unwrap();
1727/// assert_eq!(json, r#"{"banned":true,"seconds":123,"status":"OK"}"#);
1728/// let response: JsonRpcResponse = serde_json::from_str(&json).unwrap();
1729/// ```
1730#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
1731#[cfg_attr(feature = "serde", derive(Deserialize, Serialize))]
1732#[cfg_attr(feature = "serde", serde(untagged, rename_all = "snake_case"))]
1733pub enum JsonRpcResponse {
1734    GetBlockCount(GetBlockCountResponse),
1735    OnGetBlockHash(OnGetBlockHashResponse),
1736    SubmitBlock(SubmitBlockResponse),
1737    GenerateBlocks(GenerateBlocksResponse),
1738    GetLastBlockHeader(GetLastBlockHeaderResponse),
1739    GetBlockHeaderByHash(GetBlockHeaderByHashResponse),
1740    GetBlockHeaderByHeight(GetBlockHeaderByHeightResponse),
1741    GetBlockHeadersRange(GetBlockHeadersRangeResponse),
1742    GetBlock(GetBlockResponse),
1743    GetConnections(GetConnectionsResponse),
1744    GetInfo(GetInfoResponse),
1745    HardForkInfo(HardForkInfoResponse),
1746    SetBans(SetBansResponse),
1747    GetBans(GetBansResponse),
1748    Banned(BannedResponse),
1749    FlushTransactionPool(FlushTransactionPoolResponse),
1750    GetOutputHistogram(GetOutputHistogramResponse),
1751    GetCoinbaseTxSum(GetCoinbaseTxSumResponse),
1752    GetVersion(GetVersionResponse),
1753    GetFeeEstimate(GetFeeEstimateResponse),
1754    GetAlternateChains(GetAlternateChainsResponse),
1755    RelayTx(RelayTxResponse),
1756    SyncInfo(SyncInfoResponse),
1757    GetTransactionPoolBacklog(GetTransactionPoolBacklogResponse),
1758    GetMinerData(GetMinerDataResponse),
1759    PruneBlockchain(PruneBlockchainResponse),
1760    CalcPow(CalcPowResponse),
1761    FlushCache(FlushCacheResponse),
1762    AddAuxPow(AddAuxPowResponse),
1763    GetTxIdsLoose(GetTxIdsLooseResponse),
1764}
1765
1766//---------------------------------------------------------------------------------------------------- Tests
1767#[cfg(test)]
1768mod test {
1769    // use super::*;
1770}