From 5b8cacd6b3aaf62d70af4a567c5c4c571006d1e5 Mon Sep 17 00:00:00 2001 From: "hinto.janai" Date: Fri, 6 Dec 2024 18:02:05 -0500 Subject: [PATCH] !! --- rpc/types/src/other.rs | 1157 +++++++++++++++++++++++----------------- 1 file changed, 670 insertions(+), 487 deletions(-) diff --git a/rpc/types/src/other.rs b/rpc/types/src/other.rs index 97132f1..123f4d4 100644 --- a/rpc/types/src/other.rs +++ b/rpc/types/src/other.rs @@ -18,81 +18,6 @@ use crate::{ #[cfg(any(feature = "serde", feature = "epee"))] use crate::defaults::{default_false, default_string, default_true, default_vec, default_zero}; -//---------------------------------------------------------------------------------------------------- Macro -/// Adds a (de)serialization doc-test to a type in `other.rs`. -/// -/// It expects a const string from `cuprate_test_utils::rpc::data` -/// and the expected value it should (de)serialize into/from. -/// -/// It tests that the provided const JSON string can properly -/// (de)serialize into the expected value. -/// -/// See below for example usage. This macro is only used in this file. -macro_rules! serde_doc_test { - // This branch _only_ tests that the type can be deserialize - // from the string, not that any value is correct. - // - // Practically, this is used for structs that have - // many values that are complicated to test, e.g. `GET_TRANSACTIONS_RESPONSE`. - // - // HACK: - // The type itself doesn't need to be specified because it happens - // to just be the `CamelCase` version of the provided const. - ( - // `const` string from `cuprate_test_utils::rpc::data`. - $cuprate_test_utils_rpc_const:ident - ) => { - paste::paste! { - concat!( - "```rust\n", - "use cuprate_test_utils::rpc::data::other::*;\n", - "use cuprate_rpc_types::{misc::*, base::*, other::*};\n", - "use serde_json::{Value, from_str, from_value};\n", - "\n", - "let string = from_str::<", - stringify!([<$cuprate_test_utils_rpc_const:camel>]), - ">(", - stringify!($cuprate_test_utils_rpc_const), - ").unwrap();\n", - "```\n", - ) - } - }; - - // This branch tests that the type can be deserialize - // from the string AND that values are correct. - ( - // `const` string from `cuprate_test_utils::rpc::data` - // v - $cuprate_test_utils_rpc_const:ident => $expected:expr_2021 - // ^ - // Expected value as an expression - ) => { - paste::paste! { - concat!( - "```rust\n", - "use cuprate_test_utils::rpc::data::other::*;\n", - "use cuprate_rpc_types::{misc::*, base::*, other::*};\n", - "use serde_json::{Value, from_str, from_value};\n", - "\n", - "// The expected data.\n", - "let expected = ", - stringify!($expected), - ";\n", - "\n", - "let string = from_str::<", - stringify!([<$cuprate_test_utils_rpc_const:camel>]), - ">(", - stringify!($cuprate_test_utils_rpc_const), - ").unwrap();\n", - "\n", - "assert_eq!(string, expected);\n", - "```\n", - ) - } - }; -} - //---------------------------------------------------------------------------------------------------- Definitions define_request_and_response! { get_height, @@ -101,13 +26,6 @@ define_request_and_response! { GetHeight (empty), Request {}, - #[doc = serde_doc_test!( - GET_HEIGHT_RESPONSE => GetHeightResponse { - base: ResponseBase::OK, - hash: "68bb1a1cff8e2a44c3221e8e1aff80bc6ca45d06fa8eff4d2a3a7ac31d4efe3f".into(), - height: 3195160, - } - )] ResponseBase { hash: String, height: u64, @@ -120,14 +38,6 @@ define_request_and_response! { core_rpc_server_commands_defs.h => 370..=451, GetTransactions, - #[doc = serde_doc_test!( - GET_TRANSACTIONS_REQUEST => GetTransactionsRequest { - txs_hashes: vec!["d6e48158472848e6687173a91ae6eebfa3e1d778e65252ee99d7515d63090408".into()], - decode_as_json: false, - prune: false, - split: false, - } - )] Request { txs_hashes: Vec, // FIXME: this is documented as optional but it isn't serialized as an optional @@ -138,7 +48,6 @@ define_request_and_response! { split: bool = default_false(), "default_false", }, - #[doc = serde_doc_test!(GET_TRANSACTIONS_RESPONSE)] AccessResponseBase { txs_as_hex: Vec = default_vec::(), "default_vec", /// `cuprate_rpc_types::json::tx::Transaction` should be used @@ -156,12 +65,6 @@ define_request_and_response! { GetAltBlocksHashes (empty), Request {}, - #[doc = serde_doc_test!( - GET_ALT_BLOCKS_HASHES_RESPONSE => GetAltBlocksHashesResponse { - base: AccessResponseBase::OK, - blks_hashes: vec!["8ee10db35b1baf943f201b303890a29e7d45437bd76c2bd4df0d2f2ee34be109".into()], - } - )] AccessResponseBase { blks_hashes: Vec, } @@ -174,24 +77,10 @@ define_request_and_response! { IsKeyImageSpent, - #[doc = serde_doc_test!( - IS_KEY_IMAGE_SPENT_REQUEST => IsKeyImageSpentRequest { - key_images: vec![ - "8d1bd8181bf7d857bdb281e0153d84cd55a3fcaa57c3e570f4a49f935850b5e3".into(), - "7319134bfc50668251f5b899c66b005805ee255c136f0e1cecbb0f3a912e09d4".into() - ] - } - )] Request { key_images: Vec, }, - #[doc = serde_doc_test!( - IS_KEY_IMAGE_SPENT_RESPONSE => IsKeyImageSpentResponse { - base: AccessResponseBase::OK, - spent_status: vec![1, 1], - } - )] AccessResponseBase { /// FIXME: These are [`KeyImageSpentStatus`](crate::misc::KeyImageSpentStatus) in [`u8`] form. spent_status: Vec, @@ -205,44 +94,12 @@ define_request_and_response! { SendRawTransaction, - #[doc = serde_doc_test!( - SEND_RAW_TRANSACTION_REQUEST => SendRawTransactionRequest { - tx_as_hex: "dc16fa8eaffe1484ca9014ea050e13131d3acf23b419f33bb4cc0b32b6c49308".into(), - do_not_relay: false, - do_sanity_checks: true, - } - )] Request { tx_as_hex: String, do_not_relay: bool = default_false(), "default_false", do_sanity_checks: bool = default_true(), "default_true", }, - #[doc = serde_doc_test!( - SEND_RAW_TRANSACTION_RESPONSE => SendRawTransactionResponse { - base: AccessResponseBase { - response_base: ResponseBase { - status: Status::Other("Failed".into()), - untrusted: false, - }, - credits: 0, - top_hash: "".into(), - }, - double_spend: false, - fee_too_low: false, - invalid_input: false, - invalid_output: false, - low_mixin: false, - not_relayed: false, - overspend: false, - reason: "".into(), - sanity_check_failed: false, - too_big: false, - too_few_outputs: false, - tx_extra_too_big: false, - nonzero_unlock_time: false, - } - )] AccessResponseBase { double_spend: bool, fee_too_low: bool, @@ -267,14 +124,6 @@ define_request_and_response! { StartMining (restricted), - #[doc = serde_doc_test!( - START_MINING_REQUEST => StartMiningRequest { - do_background_mining: false, - ignore_battery: true, - miner_address: "47xu3gQpF569au9C2ajo5SSMrWji6xnoE5vhr94EzFRaKAGw6hEGFXYAwVADKuRpzsjiU1PtmaVgcjUJF89ghGPhUXkndHc".into(), - threads_count: 1 - } - )] Request { miner_address: String, threads_count: u64, @@ -282,11 +131,6 @@ define_request_and_response! { ignore_battery: bool, }, - #[doc = serde_doc_test!( - START_MINING_RESPONSE => StartMiningResponse { - base: ResponseBase::OK, - } - )] ResponseBase {} } @@ -297,11 +141,6 @@ define_request_and_response! { StopMining (restricted, empty), Request {}, - #[doc = serde_doc_test!( - STOP_MINING_RESPONSE => StopMiningResponse { - base: ResponseBase::OK, - } - )] ResponseBase {} } @@ -312,26 +151,6 @@ define_request_and_response! { MiningStatus (restricted), Request {}, - #[doc = serde_doc_test!( - MINING_STATUS_RESPONSE => MiningStatusResponse { - base: ResponseBase::OK, - active: false, - address: "".into(), - bg_idle_threshold: 0, - bg_ignore_battery: false, - bg_min_idle_seconds: 0, - bg_target: 0, - block_reward: 0, - block_target: 120, - difficulty: 292022797663, - difficulty_top64: 0, - is_background_mining_enabled: false, - pow_algorithm: "RandomX".into(), - speed: 0, - threads_count: 0, - wide_difficulty: "0x43fdea455f".into(), - } - )] ResponseBase { active: bool, address: String, @@ -358,11 +177,6 @@ define_request_and_response! { SaveBc (restricted), Request {}, - #[doc = serde_doc_test!( - SAVE_BC_RESPONSE => SaveBcResponse { - base: ResponseBase::OK, - } - )] ResponseBase {} } @@ -373,76 +187,11 @@ define_request_and_response! { GetPeerList (restricted), - #[doc = serde_doc_test!( - GET_PEER_LIST_REQUEST => GetPeerListRequest { - public_only: true, - include_blocked: false, - } - )] Request { public_only: bool = default_true(), "default_true", include_blocked: bool = default_false(), "default_false", }, - #[doc = serde_doc_test!( - GET_PEER_LIST_RESPONSE => GetPeerListResponse { - base: ResponseBase::OK, - gray_list: vec![ - Peer { - host: "161.97.193.0".into(), - id: 18269586253849566614, - ip: 12673441, - last_seen: 0, - port: 18080, - rpc_port: 0, - rpc_credits_per_hash: 0, - pruning_seed: 0, - }, - Peer { - host: "193.142.4.2".into(), - id: 10865563782170056467, - ip: 33853121, - last_seen: 0, - port: 18085, - pruning_seed: 387, - rpc_port: 19085, - rpc_credits_per_hash: 0, - } - ], - white_list: vec![ - Peer { - host: "78.27.98.0".into(), - id: 11368279936682035606, - ip: 6429518, - last_seen: 1721246387, - port: 18080, - pruning_seed: 384, - rpc_port: 0, - rpc_credits_per_hash: 0, - }, - Peer { - host: "67.4.163.2".into(), - id: 16545113262826842499, - ip: 44237891, - last_seen: 1721246387, - port: 18080, - rpc_port: 0, - rpc_credits_per_hash: 0, - pruning_seed: 0, - }, - Peer { - host: "70.52.75.3".into(), - id: 3863337548778177169, - ip: 55260230, - last_seen: 1721246387, - port: 18080, - rpc_port: 18081, - rpc_credits_per_hash: 0, - pruning_seed: 0, - } - ] - } - )] ResponseBase { white_list: Vec, gray_list: Vec, @@ -457,20 +206,10 @@ define_request_and_response! { SetLogHashRate (restricted), #[derive(Copy)] - #[doc = serde_doc_test!( - SET_LOG_HASH_RATE_REQUEST => SetLogHashRateRequest { - visible: true, - } - )] Request { visible: bool = default_false(), "default_false", }, - #[doc = serde_doc_test!( - SET_LOG_HASH_RATE_RESPONSE => SetLogHashRateResponse { - base: ResponseBase::OK, - } - )] ResponseBase {} } @@ -482,20 +221,10 @@ define_request_and_response! { SetLogLevel (restricted), #[derive(Copy)] - #[doc = serde_doc_test!( - SET_LOG_LEVEL_REQUEST => SetLogLevelRequest { - level: 1 - } - )] Request { level: u8, }, - #[doc = serde_doc_test!( - SET_LOG_LEVEL_RESPONSE => SetLogLevelResponse { - base: ResponseBase::OK, - } - )] ResponseBase {} } @@ -506,21 +235,10 @@ define_request_and_response! { SetLogCategories (restricted), - #[doc = serde_doc_test!( - SET_LOG_CATEGORIES_REQUEST => SetLogCategoriesRequest { - categories: "*:INFO".into(), - } - )] Request { categories: String = default_string(), "default_string", }, - #[doc = serde_doc_test!( - SET_LOG_CATEGORIES_RESPONSE => SetLogCategoriesResponse { - base: ResponseBase::OK, - categories: "*:INFO".into(), - } - )] ResponseBase { categories: String, } @@ -533,14 +251,6 @@ define_request_and_response! { SetBootstrapDaemon (restricted), - #[doc = serde_doc_test!( - SET_BOOTSTRAP_DAEMON_REQUEST => SetBootstrapDaemonRequest { - address: "http://getmonero.org:18081".into(), - username: String::new(), - password: String::new(), - proxy: String::new(), - } - )] Request { address: String, username: String = default_string(), "default_string", @@ -548,11 +258,6 @@ define_request_and_response! { proxy: String = default_string(), "default_string", }, - #[doc = serde_doc_test!( - SET_BOOTSTRAP_DAEMON_RESPONSE => SetBootstrapDaemonResponse { - status: Status::Ok, - } - )] Response { status: Status, } @@ -566,7 +271,6 @@ define_request_and_response! { GetTransactionPool (empty), Request {}, - #[doc = serde_doc_test!(GET_TRANSACTION_POOL_RESPONSE)] AccessResponseBase { transactions: Vec, spent_key_images: Vec, @@ -581,37 +285,6 @@ define_request_and_response! { GetTransactionPoolStats (empty), Request {}, - #[doc = serde_doc_test!( - GET_TRANSACTION_POOL_STATS_RESPONSE => GetTransactionPoolStatsResponse { - base: AccessResponseBase::OK, - pool_stats: TxpoolStats { - bytes_max: 11843, - bytes_med: 2219, - bytes_min: 1528, - bytes_total: 144192, - fee_total: 7018100000, - histo: vec![ - TxpoolHisto { bytes: 11219, txs: 4 }, - TxpoolHisto { bytes: 9737, txs: 5 }, - TxpoolHisto { bytes: 8757, txs: 4 }, - TxpoolHisto { bytes: 14763, txs: 4 }, - TxpoolHisto { bytes: 15007, txs: 6 }, - TxpoolHisto { bytes: 15924, txs: 6 }, - TxpoolHisto { bytes: 17869, txs: 8 }, - TxpoolHisto { bytes: 10894, txs: 5 }, - TxpoolHisto { bytes: 38485, txs: 10 }, - TxpoolHisto { bytes: 1537, txs: 1 }, - ], - histo_98pc: 186, - num_10m: 0, - num_double_spends: 0, - num_failing: 0, - num_not_relayed: 0, - oldest: 1721261651, - txs_total: 53 - } - } - )] AccessResponseBase { pool_stats: TxpoolStats, } @@ -625,11 +298,6 @@ define_request_and_response! { StopDaemon (restricted, empty), Request {}, - #[doc = serde_doc_test!( - STOP_DAEMON_RESPONSE => StopDaemonResponse { - status: Status::Ok, - } - )] Response { status: Status, } @@ -643,13 +311,6 @@ define_request_and_response! { GetLimit (empty), Request {}, - #[doc = serde_doc_test!( - GET_LIMIT_RESPONSE => GetLimitResponse { - base: ResponseBase::OK, - limit_down: 1280000, - limit_up: 1280000, - } - )] ResponseBase { limit_down: u64, limit_up: u64, @@ -663,25 +324,12 @@ define_request_and_response! { SetLimit (restricted), - #[doc = serde_doc_test!( - SET_LIMIT_REQUEST => SetLimitRequest { - limit_down: 1024, - limit_up: 0, - } - )] Request { // FIXME: These may need to be `Option`. limit_down: i64 = default_zero::(), "default_zero", limit_up: i64 = default_zero::(), "default_zero", }, - #[doc = serde_doc_test!( - SET_LIMIT_RESPONSE => SetLimitResponse { - base: ResponseBase::OK, - limit_down: 1024, - limit_up: 128, - } - )] ResponseBase { limit_down: i64, limit_up: i64, @@ -695,23 +343,11 @@ define_request_and_response! { OutPeers (restricted), - #[doc = serde_doc_test!( - OUT_PEERS_REQUEST => OutPeersRequest { - out_peers: 3232235535, - set: true, - } - )] Request { set: bool = default_true(), "default_true", out_peers: u32, }, - #[doc = serde_doc_test!( - OUT_PEERS_RESPONSE => OutPeersResponse { - base: ResponseBase::OK, - out_peers: 3232235535, - } - )] ResponseBase { out_peers: u32, } @@ -739,16 +375,6 @@ define_request_and_response! { GetNetStats (restricted, empty), Request {}, - #[doc = serde_doc_test!( - GET_NET_STATS_RESPONSE => GetNetStatsResponse { - base: ResponseBase::OK, - start_time: 1721251858, - total_bytes_in: 16283817214, - total_bytes_out: 34225244079, - total_packets_in: 5981922, - total_packets_out: 3627107, - } - )] ResponseBase { start_time: u64, total_packets_in: u64, @@ -762,43 +388,13 @@ define_request_and_response! { get_outs, cc73fe71162d564ffda8e549b79a350bca53c454 => core_rpc_server_commands_defs.h => 567..=609, - GetOuts, - #[doc = serde_doc_test!( - GET_OUTS_REQUEST => GetOutsRequest { - outputs: vec![ - GetOutputsOut { amount: 1, index: 0 }, - GetOutputsOut { amount: 1, index: 1 }, - ], - get_txid: true - } - )] + Request { outputs: Vec, get_txid: bool, }, - #[doc = serde_doc_test!( - GET_OUTS_RESPONSE => GetOutsResponse { - base: ResponseBase::OK, - outs: vec![ - OutKey { - height: 51941, - key: "08980d939ec297dd597119f498ad69fed9ca55e3a68f29f2782aae887ef0cf8e".into(), - mask: "1738eb7a677c6149228a2beaa21bea9e3370802d72a3eec790119580e02bd522".into(), - txid: "9d651903b80fb70b9935b72081cd967f543662149aed3839222511acd9100601".into(), - unlocked: true - }, - OutKey { - height: 51945, - key: "454fe46c405be77625fa7e3389a04d3be392346983f27603561ac3a3a74f4a75".into(), - mask: "1738eb7a677c6149228a2beaa21bea9e3370802d72a3eec790119580e02bd522".into(), - txid: "230bff732dc5f225df14fff82aadd1bf11b3fb7ad3a03413c396a617e843f7d0".into(), - unlocked: true - }, - ] - } - )] ResponseBase { outs: Vec, } @@ -811,28 +407,10 @@ define_request_and_response! { Update (restricted), - #[doc = serde_doc_test!( - UPDATE_REQUEST => UpdateRequest { - command: "check".into(), - path: "".into(), - } - )] Request { command: String, path: String = default_string(), "default_string", }, - - #[doc = serde_doc_test!( - UPDATE_RESPONSE => UpdateResponse { - base: ResponseBase::OK, - auto_uri: "".into(), - hash: "".into(), - path: "".into(), - update: false, - user_uri: "".into(), - version: "".into(), - } - )] ResponseBase { auto_uri: String, hash: String, @@ -850,21 +428,11 @@ define_request_and_response! { PopBlocks (restricted), - #[doc = serde_doc_test!( - POP_BLOCKS_REQUEST => PopBlocksRequest { - nblocks: 6 - } - )] + Request { nblocks: u64, }, - #[doc = serde_doc_test!( - POP_BLOCKS_RESPONSE => PopBlocksResponse { - base: ResponseBase::OK, - height: 76482, - } - )] ResponseBase { height: u64, } @@ -878,31 +446,6 @@ define_request_and_response! { GetTransactionPoolHashes (empty), Request {}, - #[doc = serde_doc_test!( - GET_TRANSACTION_POOL_HASHES_RESPONSE => GetTransactionPoolHashesResponse { - base: ResponseBase::OK, - tx_hashes: vec![ - "aa928aed888acd6152c60194d50a4df29b0b851be6169acf11b6a8e304dd6c03".into(), - "794345f321a98f3135151f3056c0fdf8188646a8dab27de971428acf3551dd11".into(), - "1e9d2ae11f2168a228942077483e70940d34e8658c972bbc3e7f7693b90edf17".into(), - "7375c928f261d00f07197775eb0bfa756e5f23319819152faa0b3c670fe54c1b".into(), - "2e4d5f8c5a45498f37fb8b6ca4ebc1efa0c371c38c901c77e66b08c072287329".into(), - "eee6d596cf855adfb10e1597d2018e3a61897ac467ef1d4a5406b8d20bfbd52f".into(), - "59c574d7ba9bb4558470f74503c7518946a85ea22c60fccfbdec108ce7d8f236".into(), - "0d57bec1e1075a9e1ac45cf3b3ced1ad95ccdf2a50ce360190111282a0178655".into(), - "60d627b2369714a40009c07d6185ebe7fa4af324fdfa8d95a37a936eb878d062".into(), - "661d7e728a901a8cb4cf851447d9cd5752462687ed0b776b605ba706f06bdc7d".into(), - "b80e1f09442b00b3fffe6db5d263be6267c7586620afff8112d5a8775a6fc58e".into(), - "974063906d1ddfa914baf85176b0f689d616d23f3d71ed4798458c8b4f9b9d8f".into(), - "d2575ae152a180be4981a9d2fc009afcd073adaa5c6d8b022c540a62d6c905bb".into(), - "3d78aa80ee50f506683bab9f02855eb10257a08adceda7cbfbdfc26b10f6b1bb".into(), - "8b5bc125bdb73b708500f734501d55088c5ac381a0879e1141634eaa72b6a4da".into(), - "11c06f4d2f00c912ca07313ed2ea5366f3cae914a762bed258731d3d9e3706df".into(), - "b3644dc7c9a3a53465fe80ad3769e516edaaeb7835e16fdd493aac110d472ae1".into(), - "ed2478ad793b923dbf652c8612c40799d764e5468897021234a14a37346bc6ee".into() - ], - } - )] ResponseBase { tx_hashes: Vec, } @@ -915,39 +458,12 @@ define_request_and_response! { GetPublicNodes (restricted), - #[doc = serde_doc_test!( - GET_PUBLIC_NODES_REQUEST => GetPublicNodesRequest { - gray: false, - white: true, - include_blocked: false, - } - )] Request { gray: bool = default_false(), "default_false", white: bool = default_true(), "default_true", include_blocked: bool = default_false(), "default_false", }, - #[doc = serde_doc_test!( - GET_PUBLIC_NODES_RESPONSE => GetPublicNodesResponse { - base: ResponseBase::OK, - gray: vec![], - white: vec![ - PublicNode { - host: "70.52.75.3".into(), - last_seen: 1721246387, - rpc_credits_per_hash: 0, - rpc_port: 18081, - }, - PublicNode { - host: "zbjkbsxc5munw3qusl7j2hpcmikhqocdf4pqhnhtpzw5nt5jrmofptid.onion:18083".into(), - last_seen: 1720186288, - rpc_credits_per_hash: 0, - rpc_port: 18089, - } - ] - } - )] ResponseBase { gray: Vec = default_vec::(), "default_vec", white: Vec = default_vec::(), "default_vec", @@ -1127,5 +643,672 @@ pub enum OtherResponse { //---------------------------------------------------------------------------------------------------- Tests #[cfg(test)] mod test { - // use super::*; + use std::fmt::Debug; + + use hex_literal::hex; + use pretty_assertions::assert_eq; + use serde::de::DeserializeOwned; + use serde_json::{from_str, from_value, Value}; + + use cuprate_test_utils::rpc::data::other; + use cuprate_types::HardFork; + + use super::*; + + #[expect(clippy::needless_pass_by_value)] + fn test_json( + cuprate_test_utils_example_data: &str, + expected_type: Option, + ) { + let string = from_str::(cuprate_test_utils_example_data).unwrap(); + + // This is `Option` for structs that have values + // that are complicated to provide/test, e.g. `GET_TRANSACTIONS_RESPONSE`. + if let Some(expected_type) = expected_type { + assert_eq!(string, expected_type); + } + } + + #[test] + fn get_height_response() { + test_json( + other::GET_HEIGHT_RESPONSE, + Some(GetHeightResponse { + base: ResponseBase::OK, + hash: "68bb1a1cff8e2a44c3221e8e1aff80bc6ca45d06fa8eff4d2a3a7ac31d4efe3f".into(), + height: 3195160, + }), + ); + } + + #[test] + fn get_transactions_request() { + test_json( + other::GET_TRANSACTIONS_REQUEST, + Some(GetTransactionsRequest { + txs_hashes: vec![ + "d6e48158472848e6687173a91ae6eebfa3e1d778e65252ee99d7515d63090408".into(), + ], + decode_as_json: false, + prune: false, + split: false, + }), + ); + } + + #[test] + fn get_transactions_response() { + test_json::(other::GET_TRANSACTIONS_RESPONSE, None); + } + + #[test] + fn get_alt_blocks_hashes_response() { + test_json( + other::GET_ALT_BLOCKS_HASHES_RESPONSE, + Some(GetAltBlocksHashesResponse { + base: AccessResponseBase::OK, + blks_hashes: vec![ + "8ee10db35b1baf943f201b303890a29e7d45437bd76c2bd4df0d2f2ee34be109".into(), + ], + }), + ); + } + + #[test] + fn is_key_image_spent_request() { + test_json( + other::IS_KEY_IMAGE_SPENT_REQUEST, + Some(IsKeyImageSpentRequest { + key_images: vec![ + "8d1bd8181bf7d857bdb281e0153d84cd55a3fcaa57c3e570f4a49f935850b5e3".into(), + "7319134bfc50668251f5b899c66b005805ee255c136f0e1cecbb0f3a912e09d4".into(), + ], + }), + ); + } + + #[test] + fn is_key_image_response() { + test_json( + other::IS_KEY_IMAGE_SPENT_RESPONSE, + Some(IsKeyImageSpentResponse { + base: AccessResponseBase::OK, + spent_status: vec![1, 1], + }), + ); + } + + #[test] + fn send_raw_transaction_request() { + test_json( + other::SEND_RAW_TRANSACTION_REQUEST, + Some(SendRawTransactionRequest { + tx_as_hex: "dc16fa8eaffe1484ca9014ea050e13131d3acf23b419f33bb4cc0b32b6c49308" + .into(), + do_not_relay: false, + do_sanity_checks: true, + }), + ); + } + + #[test] + fn send_raw_transaction_response() { + test_json( + other::SEND_RAW_TRANSACTION_RESPONSE, + Some(SendRawTransactionResponse { + base: AccessResponseBase { + response_base: ResponseBase { + status: Status::Other("Failed".into()), + untrusted: false, + }, + credits: 0, + top_hash: String::new(), + }, + double_spend: false, + fee_too_low: false, + invalid_input: false, + invalid_output: false, + low_mixin: false, + not_relayed: false, + overspend: false, + reason: String::new(), + sanity_check_failed: false, + too_big: false, + too_few_outputs: false, + tx_extra_too_big: false, + nonzero_unlock_time: false, + }), + ); + } + + #[test] + fn start_mining_request() { + test_json(other::START_MINING_REQUEST, Some(StartMiningRequest { + do_background_mining: false, + ignore_battery: true, + miner_address: "47xu3gQpF569au9C2ajo5SSMrWji6xnoE5vhr94EzFRaKAGw6hEGFXYAwVADKuRpzsjiU1PtmaVgcjUJF89ghGPhUXkndHc".into(), + threads_count: 1 + })); + } + + #[test] + fn start_mining_response() { + test_json( + other::START_MINING_RESPONSE, + Some(StartMiningResponse { + base: ResponseBase::OK, + }), + ); + } + + #[test] + fn STOP_MINING_RESPONSE() { + test_json( + other::STOP_MINING_RESPONSE, + Some(StopMiningResponse { + base: ResponseBase::OK, + }), + ); + } + + #[test] + fn MINING_STATUS_RESPONSE() { + test_json( + other::MINING_STATUS_RESPONSE, + Some(MiningStatusResponse { + base: ResponseBase::OK, + active: false, + address: String::new(), + bg_idle_threshold: 0, + bg_ignore_battery: false, + bg_min_idle_seconds: 0, + bg_target: 0, + block_reward: 0, + block_target: 120, + difficulty: 292022797663, + difficulty_top64: 0, + is_background_mining_enabled: false, + pow_algorithm: "RandomX".into(), + speed: 0, + threads_count: 0, + wide_difficulty: "0x43fdea455f".into(), + }), + ); + } + + #[test] + fn SAVE_BC_RESPONSE() { + test_json( + other::SAVE_BC_RESPONSE, + Some(SaveBcResponse { + base: ResponseBase::OK, + }), + ); + } + + #[test] + fn GET_PEER_LIST_REQUEST() { + test_json( + other::GET_PEER_LIST_REQUEST, + Some(GetPeerListRequest { + public_only: true, + include_blocked: false, + }), + ); + } + + #[test] + fn GET_PEER_LIST_RESPONSE() { + test_json( + other::GET_PEER_LIST_RESPONSE, + Some(GetPeerListResponse { + base: ResponseBase::OK, + gray_list: vec![ + Peer { + host: "161.97.193.0".into(), + id: 18269586253849566614, + ip: 12673441, + last_seen: 0, + port: 18080, + rpc_port: 0, + rpc_credits_per_hash: 0, + pruning_seed: 0, + }, + Peer { + host: "193.142.4.2".into(), + id: 10865563782170056467, + ip: 33853121, + last_seen: 0, + port: 18085, + pruning_seed: 387, + rpc_port: 19085, + rpc_credits_per_hash: 0, + }, + ], + white_list: vec![ + Peer { + host: "78.27.98.0".into(), + id: 11368279936682035606, + ip: 6429518, + last_seen: 1721246387, + port: 18080, + pruning_seed: 384, + rpc_port: 0, + rpc_credits_per_hash: 0, + }, + Peer { + host: "67.4.163.2".into(), + id: 16545113262826842499, + ip: 44237891, + last_seen: 1721246387, + port: 18080, + rpc_port: 0, + rpc_credits_per_hash: 0, + pruning_seed: 0, + }, + Peer { + host: "70.52.75.3".into(), + id: 3863337548778177169, + ip: 55260230, + last_seen: 1721246387, + port: 18080, + rpc_port: 18081, + rpc_credits_per_hash: 0, + pruning_seed: 0, + }, + ], + }), + ); + } + + #[test] + fn SET_LOG_HASH_RATE_REQUEST() { + test_json( + other::SET_LOG_HASH_RATE_REQUEST, + Some(SetLogHashRateRequest { visible: true }), + ); + } + + #[test] + fn SET_LOG_HASH_RATE_RESPONSE() { + test_json( + other::SET_LOG_HASH_RATE_RESPONSE, + Some(SetLogHashRateResponse { + base: ResponseBase::OK, + }), + ); + } + + #[test] + fn SET_LOG_LEVEL_REQUEST() { + test_json( + other::SET_LOG_LEVEL_REQUEST, + Some(SetLogLevelRequest { level: 1 }), + ); + } + + #[test] + fn SET_LOG_LEVEL_RESPONSE() { + test_json( + other::SET_LOG_LEVEL_RESPONSE, + Some(SetLogLevelResponse { + base: ResponseBase::OK, + }), + ); + } + + #[test] + fn SET_LOG_CATEGORIES_REQUEST() { + test_json( + other::SET_LOG_CATEGORIES_REQUEST, + Some(SetLogCategoriesRequest { + categories: "*:INFO".into(), + }), + ); + } + + #[test] + fn SET_LOG_CATEGORIES_RESPONSE() { + test_json( + other::SET_LOG_CATEGORIES_RESPONSE, + Some(SetLogCategoriesResponse { + base: ResponseBase::OK, + categories: "*:INFO".into(), + }), + ); + } + + #[test] + fn SET_BOOTSTRAP_DAEMON_REQUEST() { + test_json( + other::SET_BOOTSTRAP_DAEMON_REQUEST, + Some(SetBootstrapDaemonRequest { + address: "http://getmonero.org:18081".into(), + username: String::new(), + password: String::new(), + proxy: String::new(), + }), + ); + } + + #[test] + fn SET_BOOTSTRAP_DAEMON_RESPONSE() { + test_json( + other::SET_BOOTSTRAP_DAEMON_RESPONSE, + Some(SetBootstrapDaemonResponse { status: Status::Ok }), + ); + } + + #[test] + fn GET_TRANSACTION_POOL_STATS_RESPONSE() { + test_json( + other::GET_TRANSACTION_POOL_STATS_RESPONSE, + Some(GetTransactionPoolStatsResponse { + base: AccessResponseBase::OK, + pool_stats: TxpoolStats { + bytes_max: 11843, + bytes_med: 2219, + bytes_min: 1528, + bytes_total: 144192, + fee_total: 7018100000, + histo: vec![ + TxpoolHisto { + bytes: 11219, + txs: 4, + }, + TxpoolHisto { + bytes: 9737, + txs: 5, + }, + TxpoolHisto { + bytes: 8757, + txs: 4, + }, + TxpoolHisto { + bytes: 14763, + txs: 4, + }, + TxpoolHisto { + bytes: 15007, + txs: 6, + }, + TxpoolHisto { + bytes: 15924, + txs: 6, + }, + TxpoolHisto { + bytes: 17869, + txs: 8, + }, + TxpoolHisto { + bytes: 10894, + txs: 5, + }, + TxpoolHisto { + bytes: 38485, + txs: 10, + }, + TxpoolHisto { + bytes: 1537, + txs: 1, + }, + ], + histo_98pc: 186, + num_10m: 0, + num_double_spends: 0, + num_failing: 0, + num_not_relayed: 0, + oldest: 1721261651, + txs_total: 53, + }, + }), + ); + } + + #[test] + fn STOP_DAEMON_RESPONSE() { + test_json( + other::STOP_DAEMON_RESPONSE, + Some(StopDaemonResponse { status: Status::Ok }), + ); + } + + #[test] + fn GET_LIMIT_RESPONSE() { + test_json( + other::GET_LIMIT_RESPONSE, + Some(GetLimitResponse { + base: ResponseBase::OK, + limit_down: 1280000, + limit_up: 1280000, + }), + ); + } + + #[test] + fn SET_LIMIT_REQUEST() { + test_json( + other::SET_LIMIT_REQUEST, + Some(SetLimitRequest { + limit_down: 1024, + limit_up: 0, + }), + ); + } + + #[test] + fn SET_LIMIT_RESPONSE() { + test_json( + other::SET_LIMIT_RESPONSE, + Some(SetLimitResponse { + base: ResponseBase::OK, + limit_down: 1024, + limit_up: 128, + }), + ); + } + + #[test] + fn OUT_PEERS_REQUEST() { + test_json( + other::OUT_PEERS_REQUEST, + Some(OutPeersRequest { + out_peers: 3232235535, + set: true, + }), + ); + } + + #[test] + fn OUT_PEERS_RESPONSE() { + test_json( + other::OUT_PEERS_RESPONSE, + Some(OutPeersResponse { + base: ResponseBase::OK, + out_peers: 3232235535, + }), + ); + } + + #[test] + fn GET_NET_STATS_RESPONSE() { + test_json( + other::GET_NET_STATS_RESPONSE, + Some(GetNetStatsResponse { + base: ResponseBase::OK, + start_time: 1721251858, + total_bytes_in: 16283817214, + total_bytes_out: 34225244079, + total_packets_in: 5981922, + total_packets_out: 3627107, + }), + ); + } + + #[test] + fn GET_OUTS_REQUEST() { + test_json( + other::GET_OUTS_REQUEST, + Some(GetOutsRequest { + outputs: vec![ + GetOutputsOut { + amount: 1, + index: 0, + }, + GetOutputsOut { + amount: 1, + index: 1, + }, + ], + get_txid: true, + }), + ); + } + + #[test] + fn GET_OUTS_RESPONSE() { + test_json( + other::GET_OUTS_RESPONSE, + Some(GetOutsResponse { + base: ResponseBase::OK, + outs: vec![ + OutKey { + height: 51941, + key: "08980d939ec297dd597119f498ad69fed9ca55e3a68f29f2782aae887ef0cf8e" + .into(), + mask: "1738eb7a677c6149228a2beaa21bea9e3370802d72a3eec790119580e02bd522" + .into(), + txid: "9d651903b80fb70b9935b72081cd967f543662149aed3839222511acd9100601" + .into(), + unlocked: true, + }, + OutKey { + height: 51945, + key: "454fe46c405be77625fa7e3389a04d3be392346983f27603561ac3a3a74f4a75" + .into(), + mask: "1738eb7a677c6149228a2beaa21bea9e3370802d72a3eec790119580e02bd522" + .into(), + txid: "230bff732dc5f225df14fff82aadd1bf11b3fb7ad3a03413c396a617e843f7d0" + .into(), + unlocked: true, + }, + ], + }), + ); + } + + #[test] + fn UPDATE_REQUEST() { + test_json( + other::UPDATE_REQUEST, + Some(UpdateRequest { + command: "check".into(), + path: String::new(), + }), + ); + } + + #[test] + fn UPDATE_RESPONSE() { + test_json( + other::UPDATE_RESPONSE, + Some(UpdateResponse { + base: ResponseBase::OK, + auto_uri: String::new(), + hash: String::new(), + path: String::new(), + update: false, + user_uri: String::new(), + version: String::new(), + }), + ); + } + + #[test] + fn POP_BLOCKS_REQUEST() { + test_json( + other::POP_BLOCKS_REQUEST, + Some(PopBlocksRequest { nblocks: 6 }), + ); + } + + #[test] + fn POP_BLOCKS_RESPONSE() { + test_json( + other::POP_BLOCKS_RESPONSE, + Some(PopBlocksResponse { + base: ResponseBase::OK, + height: 76482, + }), + ); + } + + #[test] + fn GET_TRANSACTION_POOL_HASHES_RESPONSE() { + test_json( + other::GET_TRANSACTION_POOL_HASHES_RESPONSE, + Some(GetTransactionPoolHashesResponse { + base: ResponseBase::OK, + tx_hashes: vec![ + "aa928aed888acd6152c60194d50a4df29b0b851be6169acf11b6a8e304dd6c03".into(), + "794345f321a98f3135151f3056c0fdf8188646a8dab27de971428acf3551dd11".into(), + "1e9d2ae11f2168a228942077483e70940d34e8658c972bbc3e7f7693b90edf17".into(), + "7375c928f261d00f07197775eb0bfa756e5f23319819152faa0b3c670fe54c1b".into(), + "2e4d5f8c5a45498f37fb8b6ca4ebc1efa0c371c38c901c77e66b08c072287329".into(), + "eee6d596cf855adfb10e1597d2018e3a61897ac467ef1d4a5406b8d20bfbd52f".into(), + "59c574d7ba9bb4558470f74503c7518946a85ea22c60fccfbdec108ce7d8f236".into(), + "0d57bec1e1075a9e1ac45cf3b3ced1ad95ccdf2a50ce360190111282a0178655".into(), + "60d627b2369714a40009c07d6185ebe7fa4af324fdfa8d95a37a936eb878d062".into(), + "661d7e728a901a8cb4cf851447d9cd5752462687ed0b776b605ba706f06bdc7d".into(), + "b80e1f09442b00b3fffe6db5d263be6267c7586620afff8112d5a8775a6fc58e".into(), + "974063906d1ddfa914baf85176b0f689d616d23f3d71ed4798458c8b4f9b9d8f".into(), + "d2575ae152a180be4981a9d2fc009afcd073adaa5c6d8b022c540a62d6c905bb".into(), + "3d78aa80ee50f506683bab9f02855eb10257a08adceda7cbfbdfc26b10f6b1bb".into(), + "8b5bc125bdb73b708500f734501d55088c5ac381a0879e1141634eaa72b6a4da".into(), + "11c06f4d2f00c912ca07313ed2ea5366f3cae914a762bed258731d3d9e3706df".into(), + "b3644dc7c9a3a53465fe80ad3769e516edaaeb7835e16fdd493aac110d472ae1".into(), + "ed2478ad793b923dbf652c8612c40799d764e5468897021234a14a37346bc6ee".into(), + ], + }), + ); + } + + #[test] + fn GET_PUBLIC_NODES_REQUEST() { + test_json( + other::GET_PUBLIC_NODES_REQUEST, + Some(GetPublicNodesRequest { + gray: false, + white: true, + include_blocked: false, + }), + ); + } + + #[test] + fn GET_PUBLIC_NODES_RESPONSE() { + test_json( + other::GET_PUBLIC_NODES_RESPONSE, + Some(GetPublicNodesResponse { + base: ResponseBase::OK, + gray: vec![], + white: vec![ + PublicNode { + host: "70.52.75.3".into(), + last_seen: 1721246387, + rpc_credits_per_hash: 0, + rpc_port: 18081, + }, + PublicNode { + host: + "zbjkbsxc5munw3qusl7j2hpcmikhqocdf4pqhnhtpzw5nt5jrmofptid.onion:18083" + .into(), + last_seen: 1720186288, + rpc_credits_per_hash: 0, + rpc_port: 18089, + }, + ], + }), + ); + } }