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