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