diff --git a/Cargo.lock b/Cargo.lock index ac29662..55f17a1 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -764,6 +764,8 @@ version = "0.0.0" dependencies = [ "cuprate-epee-encoding", "cuprate-fixed-bytes", + "cuprate-json-rpc", + "cuprate-test-utils", "cuprate-types", "monero-serai", "paste", diff --git a/rpc/types/Cargo.toml b/rpc/types/Cargo.toml index fcec453..9c99681 100644 --- a/rpc/types/Cargo.toml +++ b/rpc/types/Cargo.toml @@ -23,5 +23,8 @@ paste = { workspace = true } serde = { workspace = true, optional = true } [dev-dependencies] +cuprate-test-utils = { path = "../../test-utils" } +cuprate-json-rpc = { path = "../json-rpc" } + serde_json = { workspace = true } -pretty_assertions = { workspace = true } +pretty_assertions = { workspace = true } \ No newline at end of file diff --git a/rpc/types/src/base.rs b/rpc/types/src/base.rs index 4990cdd..c131e41 100644 --- a/rpc/types/src/base.rs +++ b/rpc/types/src/base.rs @@ -57,6 +57,64 @@ pub struct ResponseBase { pub untrusted: bool, } +impl ResponseBase { + /// `const` version of [`Default::default`]. + /// + /// ```rust + /// use cuprate_rpc_types::{misc::*, base::*}; + /// + /// let new = ResponseBase::new(); + /// assert_eq!(new, ResponseBase { + /// status: Status::Ok, + /// untrusted: false, + /// }); + /// ``` + pub const fn new() -> Self { + Self { + status: Status::Ok, + untrusted: false, + } + } + + /// Returns OK and trusted [`Self`]. + /// + /// This is the most common version of [`Self`]. + /// + /// ```rust + /// use cuprate_rpc_types::{misc::*, base::*}; + /// + /// let ok = ResponseBase::ok(); + /// assert_eq!(ok, ResponseBase { + /// status: Status::Ok, + /// untrusted: false, + /// }); + /// ``` + pub const fn ok() -> Self { + Self { + status: Status::Ok, + untrusted: false, + } + } + + /// Same as [`Self::ok`] but with [`Self::untrusted`] set to `true`. + /// + /// ```rust + /// use cuprate_rpc_types::{misc::*, base::*}; + /// + /// let ok_untrusted = ResponseBase::ok_untrusted(); + /// assert_eq!(ok_untrusted, ResponseBase { + /// status: Status::Ok, + /// untrusted: true, + /// }); + /// ``` + pub const fn ok_untrusted() -> Self { + Self { + status: Status::Ok, + untrusted: true, + } + } +} + #[cfg(feature = "epee")] epee_object! { ResponseBase, @@ -80,6 +138,74 @@ pub struct AccessResponseBase { pub top_hash: String, } +impl AccessResponseBase { + /// Creates a new [`Self`] with default values. + /// + /// Since RPC payment is semi-deprecated, [`Self::credits`] + /// and [`Self::top_hash`] will always be set to the default + /// values. + /// + /// ```rust + /// use cuprate_rpc_types::{misc::*, base::*}; + /// + /// let new = AccessResponseBase::new(ResponseBase::ok()); + /// assert_eq!(new, AccessResponseBase { + /// response_base: ResponseBase::ok(), + /// credits: 0, + /// top_hash: "".into(), + /// }); + /// ``` + pub const fn new(response_base: ResponseBase) -> Self { + Self { + response_base, + credits: 0, + top_hash: String::new(), + } + } + + /// Returns OK and trusted [`Self`]. + /// + /// This is the most common version of [`Self`]. + /// + /// ```rust + /// use cuprate_rpc_types::{misc::*, base::*}; + /// + /// let ok = AccessResponseBase::ok(); + /// assert_eq!(ok, AccessResponseBase { + /// response_base: ResponseBase::ok(), + /// credits: 0, + /// top_hash: "".into(), + /// }); + /// ``` + pub const fn ok() -> Self { + Self { + response_base: ResponseBase::ok(), + credits: 0, + top_hash: String::new(), + } + } + + /// Same as [`Self::ok`] but with `untrusted` set to `true`. + /// + /// ```rust + /// use cuprate_rpc_types::{misc::*, base::*}; + /// + /// let ok_untrusted = AccessResponseBase::ok_untrusted(); + /// assert_eq!(ok_untrusted, AccessResponseBase { + /// response_base: ResponseBase::ok_untrusted(), + /// credits: 0, + /// top_hash: "".into(), + /// }); + /// ``` + pub const fn ok_untrusted() -> Self { + Self { + response_base: ResponseBase::ok_untrusted(), + credits: 0, + top_hash: String::new(), + } + } +} + #[cfg(feature = "epee")] epee_object! { AccessResponseBase, diff --git a/rpc/types/src/defaults.rs b/rpc/types/src/defaults.rs index 9366a26..6addd0a 100644 --- a/rpc/types/src/defaults.rs +++ b/rpc/types/src/defaults.rs @@ -53,6 +53,12 @@ pub(crate) fn default_zero>() -> T { T::from(0) } +/// Default `1` value used in request/response types. +#[inline] +pub(crate) fn default_one>() -> T { + T::from(1) +} + //---------------------------------------------------------------------------------------------------- Tests #[cfg(test)] mod test { diff --git a/rpc/types/src/json.rs b/rpc/types/src/json.rs index f4bca99..dd2e648 100644 --- a/rpc/types/src/json.rs +++ b/rpc/types/src/json.rs @@ -5,15 +5,78 @@ //---------------------------------------------------------------------------------------------------- Import use crate::{ base::{AccessResponseBase, ResponseBase}, - defaults::{default_false, default_height, default_string, default_vec, default_zero}, + defaults::{ + default_false, default_height, default_one, default_string, default_true, default_vec, + default_zero, + }, free::{is_one, is_zero}, macros::define_request_and_response, misc::{ - AuxPow, BlockHeader, ChainInfo, ConnectionInfo, Distribution, GetBan, HardforkEntry, - HistogramEntry, OutputDistributionData, SetBan, Span, Status, SyncInfoPeer, TxBacklogEntry, + AuxPow, BlockHeader, ChainInfo, ConnectionInfo, Distribution, GetBan, + GetMinerDataTxBacklogEntry, HardforkEntry, HistogramEntry, OutputDistributionData, SetBan, + Span, Status, SyncInfoPeer, TxBacklogEntry, }, }; +//---------------------------------------------------------------------------------------------------- Macro +/// Adds a (de)serialization doc-test to a type in `json.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 { + ( + // `const` string from `cuprate_test_utils::rpc::data` + // v + $cuprate_test_utils_rpc_const:ident => $expected:expr + // ^ + // Expected value as an expression + ) => { + paste::paste! { + concat!( + "```rust\n", + "use cuprate_test_utils::rpc::data::json::*;\n", + "use cuprate_rpc_types::{misc::*, base::*, json::*};\n", + "use serde_json::{Value, from_str, from_value};\n", + "\n", + "// The expected data.\n", + "let expected = ", + stringify!($expected), + ";\n", + "\n", + "// Assert it can be turned into a JSON value.\n", + "let value = from_str::(", + stringify!($cuprate_test_utils_rpc_const), + ").unwrap();\n", + "let Value::Object(map) = value else {\n", + " panic!();\n", + "};\n", + "\n", + "// If a request...\n", + "if let Some(params) = map.get(\"params\") {\n", + " let response = from_value::<", + stringify!([<$cuprate_test_utils_rpc_const:camel>]), + ">(params.clone()).unwrap();\n", + " assert_eq!(response, expected);\n", + " return;\n", + "}\n", + "\n", + "// Else, if a response...\n", + "let result = map.get(\"result\").unwrap().clone();\n", + "let response = from_value::<", + stringify!([<$cuprate_test_utils_rpc_const:camel>]), + ">(result.clone()).unwrap();\n", + "assert_eq!(response, expected);\n", + "```\n", + ) + } + }; +} + //---------------------------------------------------------------------------------------------------- Definitions // This generates 2 structs: // @@ -41,7 +104,22 @@ define_request_and_response! { // // If there are any additional attributes (`/// docs` or `#[derive]`s) // for the struct, they go here, e.g.: - // #[derive(Copy)] + // + #[doc = serde_doc_test!( + // ^ This is a macro that adds a doc-test to this type. + // It is optional but it is added to nearly all types. + // The syntax is: + // `$const` => `$expected` + // where `$const` is a `const` string from + // `cuprate_test_utils::rpc::data` and `$expected` is an + // actual expression that the string _should_ (de)serialize into/from. + GET_BLOCK_TEMPLATE_REQUEST => GetBlockTemplateRequest { + extra_nonce: String::default(), + prev_block: String::default(), + reserve_size: 60, + wallet_address: "44GBHzv6ZyQdJkjqZje6KLZ3xSyN1hBSFAnLP6EAqJtCRVzMzZmeXTC2AHKDS9aEDTRKmo6a6o9r9j86pYfhCWDkKjbtcns".into(), + } + )] Request { // Within the `{}` is an infinite matching pattern of: // ``` @@ -66,17 +144,16 @@ define_request_and_response! { // // This is a HACK since `serde`'s default attribute only takes in // string literals and macros (stringify) within attributes do not work. - extra_nonce: String /* = default_expression, "default_literal" */, + extra_nonce: String = default_string(), "default_string", + prev_block: String = default_string(), "default_string", // Another optional expression: // This indicates to the macro to (de)serialize // this field as another type in epee. // // See `cuprate_epee_encoding::epee_object` for info. - prev_block: String /* as Type */, + reserve_size: u64 /* as Type */, - // Regular fields. - reserve_size: u64, wallet_address: String, }, @@ -92,6 +169,23 @@ define_request_and_response! { // "Flatten" means the field(s) of a struct gets inlined // directly into the struct during (de)serialization, see: // . + #[doc = serde_doc_test!( + GET_BLOCK_TEMPLATE_RESPONSE => GetBlockTemplateResponse { + base: ResponseBase::ok(), + blockhashing_blob: "1010f4bae0b4069d648e741d85ca0e7acb4501f051b27e9b107d3cd7a3f03aa7f776089117c81a00000000e0c20372be23d356347091025c5b5e8f2abf83ab618378565cce2b703491523401".into(), + blocktemplate_blob: "1010f4bae0b4069d648e741d85ca0e7acb4501f051b27e9b107d3cd7a3f03aa7f776089117c81a0000000002c681c30101ff8a81c3010180e0a596bb11033b7eedf47baf878f3490cb20b696079c34bd017fe59b0d070e74d73ffabc4bb0e05f011decb630f3148d0163b3bd39690dde4078e4cfb69fecf020d6278a27bad10c58023c0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000".into(), + difficulty_top64: 0, + difficulty: 283305047039, + expected_reward: 600000000000, + height: 3195018, + next_seed_hash: "".into(), + prev_hash: "9d648e741d85ca0e7acb4501f051b27e9b107d3cd7a3f03aa7f776089117c81a".into(), + reserved_offset: 131, + seed_hash: "e2aa0b7b55042cd48b02e395d78fa66a29815ccc1584e38db2d1f0e8485cd44f".into(), + seed_height: 3194880, + wide_difficulty: "0x41f64bf3ff".into(), + } + )] ResponseBase { // This is using [`crate::base::ResponseBase`], // so the type we generate will contain this field: @@ -131,6 +225,12 @@ define_request_and_response! { // type alias to `()` instead of a `struct`. Request {}, + #[doc = serde_doc_test!( + GET_BLOCK_COUNT_RESPONSE => GetBlockCountResponse { + base: ResponseBase::ok(), + count: 3195019, + } + )] ResponseBase { count: u64, } @@ -140,15 +240,14 @@ define_request_and_response! { on_get_block_hash, cc73fe71162d564ffda8e549b79a350bca53c454 => core_rpc_server_commands_defs.h => 935..=939, + OnGetBlockHash, - /// ```rust - /// use serde_json::*; - /// use cuprate_rpc_types::json::*; - /// - /// let x = OnGetBlockHashRequest { block_height: [3] }; - /// let x = to_string(&x).unwrap(); - /// assert_eq!(x, "[3]"); - /// ``` + + #[doc = serde_doc_test!( + ON_GET_BLOCK_HASH_REQUEST => OnGetBlockHashRequest { + block_height: [912345], + } + )] #[cfg_attr(feature = "serde", serde(transparent))] #[repr(transparent)] #[derive(Copy)] @@ -157,14 +256,12 @@ define_request_and_response! { // it must be a 1 length array or else it will error. block_height: [u64; 1], }, - /// ```rust - /// use serde_json::*; - /// use cuprate_rpc_types::json::*; - /// - /// let x = OnGetBlockHashResponse { block_hash: String::from("asdf") }; - /// let x = to_string(&x).unwrap(); - /// assert_eq!(x, "\"asdf\""); - /// ``` + + #[doc = serde_doc_test!( + ON_GET_BLOCK_HASH_RESPONSE => OnGetBlockHashResponse { + block_hash: "e22cf75f39ae720e8b71b3d120a5ac03f0db50bba6379e2850975b4859190bc6".into(), + } + )] #[cfg_attr(feature = "serde", serde(transparent))] #[repr(transparent)] Response { @@ -176,15 +273,14 @@ define_request_and_response! { submit_block, cc73fe71162d564ffda8e549b79a350bca53c454 => core_rpc_server_commands_defs.h => 1114..=1128, + SubmitBlock, - /// ```rust - /// use serde_json::*; - /// use cuprate_rpc_types::json::*; - /// - /// let x = SubmitBlockRequest { block_blob: ["a".into()] }; - /// let x = to_string(&x).unwrap(); - /// assert_eq!(x, r#"["a"]"#); - /// ``` + + #[doc = serde_doc_test!( + SUBMIT_BLOCK_REQUEST => SubmitBlockRequest { + block_blob: ["0707e6bdfedc053771512f1bc27c62731ae9e8f2443db64ce742f4e57f5cf8d393de28551e441a0000000002fb830a01ffbf830a018cfe88bee283060274c0aae2ef5730e680308d9c00b6da59187ad0352efe3c71d36eeeb28782f29f2501bd56b952c3ddc3e350c2631d3a5086cac172c56893831228b17de296ff4669de020200000000".into()], + } + )] #[cfg_attr(feature = "serde", serde(transparent))] #[repr(transparent)] Request { @@ -192,6 +288,8 @@ define_request_and_response! { // it must be a 1 length array or else it will error. block_blob: [String; 1], }, + + // FIXME: `cuprate_test_utils` only has an `error` response for this. ResponseBase { block_id: String, } @@ -201,13 +299,31 @@ define_request_and_response! { generateblocks, cc73fe71162d564ffda8e549b79a350bca53c454 => core_rpc_server_commands_defs.h => 1130..=1161, + GenerateBlocks, + + #[doc = serde_doc_test!( + GENERATE_BLOCKS_REQUEST => GenerateBlocksRequest { + amount_of_blocks: 1, + prev_block: String::default(), + wallet_address: "44AFFq5kSiGBoZ4NMDwYtN18obc8AemS33DBLWs3H7otXft3XjrpDtQGv7SqSsaBYBb98uNbr2VBBEt7f2wfn3RVGQBEP3A".into(), + starting_nonce: 0 + } + )] Request { amount_of_blocks: u64, - prev_block: String, + prev_block: String = default_string(), "default_string", starting_nonce: u32, wallet_address: String, }, + + #[doc = serde_doc_test!( + GENERATE_BLOCKS_RESPONSE => GenerateBlocksResponse { + base: ResponseBase::ok(), + blocks: vec!["49b712db7760e3728586f8434ee8bc8d7b3d410dac6bb6e98bf5845c83b917e4".into()], + height: 9783, + } + )] ResponseBase { blocks: Vec, height: u64, @@ -218,11 +334,43 @@ define_request_and_response! { get_last_block_header, cc73fe71162d564ffda8e549b79a350bca53c454 => core_rpc_server_commands_defs.h => 1214..=1238, + GetLastBlockHeader, + #[derive(Copy)] Request { fill_pow_hash: bool = default_false(), "default_false", }, + + #[doc = serde_doc_test!( + GET_LAST_BLOCK_HEADER_RESPONSE => GetLastBlockHeaderResponse { + base: AccessResponseBase::ok(), + block_header: BlockHeader { + block_size: 200419, + block_weight: 200419, + cumulative_difficulty: 366125734645190820, + cumulative_difficulty_top64: 0, + depth: 0, + difficulty: 282052561854, + difficulty_top64: 0, + hash: "57238217820195ac4c08637a144a885491da167899cf1d20e8e7ce0ae0a3434e".into(), + height: 3195020, + long_term_weight: 200419, + major_version: 16, + miner_tx_hash: "7a42667237d4f79891bb407c49c712a9299fb87fce799833a7b633a3a9377dbd".into(), + minor_version: 16, + nonce: 1885649739, + num_txes: 37, + orphan_status: false, + pow_hash: "".into(), + prev_hash: "22c72248ae9c5a2863c94735d710a3525c499f70707d1c2f395169bc5c8a0da3".into(), + reward: 615702960000, + timestamp: 1721245548, + wide_cumulative_difficulty: "0x514bd6a74a7d0a4".into(), + wide_difficulty: "0x41aba48bbe".into() + } + } + )] AccessResponseBase { block_header: BlockHeader, } @@ -233,14 +381,52 @@ define_request_and_response! { cc73fe71162d564ffda8e549b79a350bca53c454 => core_rpc_server_commands_defs.h => 1240..=1269, GetBlockHeaderByHash, + #[doc = serde_doc_test!( + GET_BLOCK_HEADER_BY_HASH_REQUEST => GetBlockHeaderByHashRequest { + hash: "e22cf75f39ae720e8b71b3d120a5ac03f0db50bba6379e2850975b4859190bc6".into(), + hashes: vec![], + fill_pow_hash: false, + } + )] Request { hash: String, - hashes: Vec, + hashes: Vec = default_vec::(), "default_vec", fill_pow_hash: bool = default_false(), "default_false", }, + + #[doc = serde_doc_test!( + GET_BLOCK_HEADER_BY_HASH_RESPONSE => GetBlockHeaderByHashResponse { + base: AccessResponseBase::ok(), + block_headers: vec![], + block_header: BlockHeader { + block_size: 210, + block_weight: 210, + cumulative_difficulty: 754734824984346, + cumulative_difficulty_top64: 0, + depth: 2282676, + difficulty: 815625611, + difficulty_top64: 0, + hash: "e22cf75f39ae720e8b71b3d120a5ac03f0db50bba6379e2850975b4859190bc6".into(), + height: 912345, + long_term_weight: 210, + major_version: 1, + miner_tx_hash: "c7da3965f25c19b8eb7dd8db48dcd4e7c885e2491db77e289f0609bf8e08ec30".into(), + minor_version: 2, + nonce: 1646, + num_txes: 0, + orphan_status: false, + pow_hash: "".into(), + prev_hash: "b61c58b2e0be53fad5ef9d9731a55e8a81d972b8d90ed07c04fd37ca6403ff78".into(), + reward: 7388968946286, + timestamp: 1452793716, + wide_cumulative_difficulty: "0x2ae6d65248f1a".into(), + wide_difficulty: "0x309d758b".into() + }, + } + )] AccessResponseBase { block_header: BlockHeader, - block_headers: Vec, + block_headers: Vec = default_vec::(), "default_vec", } } @@ -248,12 +434,50 @@ define_request_and_response! { get_block_header_by_height, cc73fe71162d564ffda8e549b79a350bca53c454 => core_rpc_server_commands_defs.h => 1271..=1296, + GetBlockHeaderByHeight, + #[derive(Copy)] + #[doc = serde_doc_test!( + GET_BLOCK_HEADER_BY_HEIGHT_REQUEST => GetBlockHeaderByHeightRequest { + height: 912345, + fill_pow_hash: false, + } + )] Request { height: u64, fill_pow_hash: bool = default_false(), "default_false", }, + + #[doc = serde_doc_test!( + GET_BLOCK_HEADER_BY_HEIGHT_RESPONSE => GetBlockHeaderByHeightResponse { + base: AccessResponseBase::ok(), + block_header: BlockHeader { + block_size: 210, + block_weight: 210, + cumulative_difficulty: 754734824984346, + cumulative_difficulty_top64: 0, + depth: 2282677, + difficulty: 815625611, + difficulty_top64: 0, + hash: "e22cf75f39ae720e8b71b3d120a5ac03f0db50bba6379e2850975b4859190bc6".into(), + height: 912345, + long_term_weight: 210, + major_version: 1, + miner_tx_hash: "c7da3965f25c19b8eb7dd8db48dcd4e7c885e2491db77e289f0609bf8e08ec30".into(), + minor_version: 2, + nonce: 1646, + num_txes: 0, + orphan_status: false, + pow_hash: "".into(), + prev_hash: "b61c58b2e0be53fad5ef9d9731a55e8a81d972b8d90ed07c04fd37ca6403ff78".into(), + reward: 7388968946286, + timestamp: 1452793716, + wide_cumulative_difficulty: "0x2ae6d65248f1a".into(), + wide_difficulty: "0x309d758b".into() + }, + } + )] AccessResponseBase { block_header: BlockHeader, } @@ -263,13 +487,78 @@ define_request_and_response! { get_block_headers_range, cc73fe71162d564ffda8e549b79a350bca53c454 => core_rpc_server_commands_defs.h => 1756..=1783, + GetBlockHeadersRange, + #[derive(Copy)] + #[doc = serde_doc_test!( + GET_BLOCK_HEADERS_RANGE_REQUEST => GetBlockHeadersRangeRequest { + start_height: 1545999, + end_height: 1546000, + fill_pow_hash: false, + } + )] Request { start_height: u64, end_height: u64, fill_pow_hash: bool = default_false(), "default_false", }, + + #[doc = serde_doc_test!( + GET_BLOCK_HEADERS_RANGE_RESPONSE => GetBlockHeadersRangeResponse { + base: AccessResponseBase::ok(), + headers: vec![ + BlockHeader { + block_size: 301413, + block_weight: 301413, + cumulative_difficulty: 13185267971483472, + cumulative_difficulty_top64: 0, + depth: 1649024, + difficulty: 134636057921, + difficulty_top64: 0, + hash: "86d1d20a40cefcf3dd410ff6967e0491613b77bf73ea8f1bf2e335cf9cf7d57a".into(), + height: 1545999, + long_term_weight: 301413, + major_version: 6, + miner_tx_hash: "9909c6f8a5267f043c3b2b079fb4eacc49ef9c1dee1c028eeb1a259b95e6e1d9".into(), + minor_version: 6, + nonce: 3246403956, + num_txes: 20, + orphan_status: false, + pow_hash: "".into(), + prev_hash: "0ef6e948f77b8f8806621003f5de24b1bcbea150bc0e376835aea099674a5db5".into(), + reward: 5025593029981, + timestamp: 1523002893, + wide_cumulative_difficulty: "0x2ed7ee6db56750".into(), + wide_difficulty: "0x1f58ef3541".into() + }, + BlockHeader { + block_size: 13322, + block_weight: 13322, + cumulative_difficulty: 13185402687569710, + cumulative_difficulty_top64: 0, + depth: 1649023, + difficulty: 134716086238, + difficulty_top64: 0, + hash: "b408bf4cfcd7de13e7e370c84b8314c85b24f0ba4093ca1d6eeb30b35e34e91a".into(), + height: 1546000, + long_term_weight: 13322, + major_version: 7, + miner_tx_hash: "7f749c7c64acb35ef427c7454c45e6688781fbead9bbf222cb12ad1a96a4e8f6".into(), + minor_version: 7, + nonce: 3737164176, + num_txes: 1, + orphan_status: false, + pow_hash: "".into(), + prev_hash: "86d1d20a40cefcf3dd410ff6967e0491613b77bf73ea8f1bf2e335cf9cf7d57a".into(), + reward: 4851952181070, + timestamp: 1523002931, + wide_cumulative_difficulty: "0x2ed80dcb69bf2e".into(), + wide_difficulty: "0x1f5db457de".into() + } + ], + } + )] AccessResponseBase { headers: Vec, } @@ -280,6 +569,14 @@ define_request_and_response! { cc73fe71162d564ffda8e549b79a350bca53c454 => core_rpc_server_commands_defs.h => 1298..=1313, GetBlock, + + #[doc = serde_doc_test!( + GET_BLOCK_REQUEST => GetBlockRequest { + height: 2751506, + hash: String::default(), + fill_pow_hash: false, + } + )] Request { // `monerod` has both `hash` and `height` fields. // In the RPC handler, if `hash.is_empty()`, it will use it, else, it uses `height`. @@ -288,12 +585,46 @@ define_request_and_response! { height: u64 = default_height(), "default_height", fill_pow_hash: bool = default_false(), "default_false", }, + + #[doc = serde_doc_test!( + GET_BLOCK_RESPONSE => GetBlockResponse { + base: AccessResponseBase::ok(), + blob: "1010c58bab9b06b27bdecfc6cd0a46172d136c08831cf67660377ba992332363228b1b722781e7807e07f502cef8a70101ff92f8a7010180e0a596bb1103d7cbf826b665d7a532c316982dc8dbc24f285cbc18bbcc27c7164cd9b3277a85d034019f629d8b36bd16a2bfce3ea80c31dc4d8762c67165aec21845494e32b7582fe00211000000297a787a000000000000000000000000".into(), + block_header: BlockHeader { + block_size: 106, + block_weight: 106, + cumulative_difficulty: 236046001376524168, + cumulative_difficulty_top64: 0, + depth: 443517, + difficulty: 313732272488, + difficulty_top64: 0, + hash: "43bd1f2b6556dcafa413d8372974af59e4e8f37dbf74dc6b2a9b7212d0577428".into(), + height: 2751506, + long_term_weight: 176470, + major_version: 16, + miner_tx_hash: "e49b854c5f339d7410a77f2a137281d8042a0ffc7ef9ab24cd670b67139b24cd".into(), + minor_version: 16, + nonce: 4110909056, + num_txes: 0, + orphan_status: false, + pow_hash: "".into(), + prev_hash: "b27bdecfc6cd0a46172d136c08831cf67660377ba992332363228b1b722781e7".into(), + reward: 600000000000, + timestamp: 1667941829, + wide_cumulative_difficulty: "0x3469a966eb2f788".into(), + wide_difficulty: "0x490be69168".into() + }, + 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(), + miner_tx_hash: "e49b854c5f339d7410a77f2a137281d8042a0ffc7ef9ab24cd670b67139b24cd".into(), + tx_hashes: vec![], + } + )] AccessResponseBase { blob: String, block_header: BlockHeader, json: String, // FIXME: this should be defined in a struct, it has many fields. miner_tx_hash: String, - tx_hashes: Vec, + tx_hashes: Vec = default_vec::(), "default_vec", } } @@ -301,8 +632,72 @@ define_request_and_response! { get_connections, cc73fe71162d564ffda8e549b79a350bca53c454 => core_rpc_server_commands_defs.h => 1734..=1754, + GetConnections, + Request {}, + + #[doc = serde_doc_test!( + GET_CONNECTIONS_RESPONSE => GetConnectionsResponse { + base: ResponseBase::ok(), + connections: vec![ + ConnectionInfo { + address: "3evk3kezfjg44ma6tvesy7rbxwwpgpympj45xar5fo4qajrsmkoaqdqd.onion:18083".into(), + address_type: 4, + avg_download: 0, + avg_upload: 0, + connection_id: "22ef856d0f1d44cc95e84fecfd065fe2".into(), + current_download: 0, + current_upload: 0, + height: 3195026, + host: "3evk3kezfjg44ma6tvesy7rbxwwpgpympj45xar5fo4qajrsmkoaqdqd.onion".into(), + incoming: false, + ip: "".into(), + live_time: 76651, + local_ip: false, + localhost: false, + peer_id: "0000000000000001".into(), + port: "".into(), + pruning_seed: 0, + recv_count: 240328, + recv_idle_time: 34, + rpc_credits_per_hash: 0, + rpc_port: 0, + send_count: 3406572, + send_idle_time: 30, + state: "normal".into(), + support_flags: 0 + }, + ConnectionInfo { + address: "4iykytmumafy5kjahdqc7uzgcs34s2vwsadfjpk4znvsa5vmcxeup2qd.onion:18083".into(), + address_type: 4, + avg_download: 0, + avg_upload: 0, + connection_id: "c7734e15936f485a86d2b0534f87e499".into(), + current_download: 0, + current_upload: 0, + height: 3195024, + host: "4iykytmumafy5kjahdqc7uzgcs34s2vwsadfjpk4znvsa5vmcxeup2qd.onion".into(), + incoming: false, + ip: "".into(), + live_time: 76755, + local_ip: false, + localhost: false, + peer_id: "0000000000000001".into(), + port: "".into(), + pruning_seed: 389, + recv_count: 237657, + recv_idle_time: 120, + rpc_credits_per_hash: 0, + rpc_port: 0, + send_count: 3370566, + send_idle_time: 120, + state: "normal".into(), + support_flags: 0 + } + ], + } + )] ResponseBase { // FIXME: This is a `std::list` in `monerod` because...? connections: Vec, @@ -315,6 +710,51 @@ define_request_and_response! { core_rpc_server_commands_defs.h => 693..=789, GetInfo, Request {}, + + #[doc = serde_doc_test!( + GET_INFO_RESPONSE => GetInfoResponse { + base: AccessResponseBase::ok(), + adjusted_time: 1721245289, + alt_blocks_count: 16, + block_size_limit: 600000, + block_size_median: 300000, + block_weight_limit: 600000, + block_weight_median: 300000, + bootstrap_daemon_address: "".into(), + busy_syncing: false, + cumulative_difficulty: 366127702242611947, + cumulative_difficulty_top64: 0, + database_size: 235169075200, + difficulty: 280716748706, + difficulty_top64: 0, + free_space: 30521749504, + grey_peerlist_size: 4996, + height: 3195028, + height_without_bootstrap: 3195028, + incoming_connections_count: 62, + mainnet: true, + nettype: "mainnet".into(), + offline: false, + outgoing_connections_count: 1143, + restricted: false, + rpc_connections_count: 1, + stagenet: false, + start_time: 1720462427, + synchronized: true, + target: 120, + target_height: 0, + testnet: false, + top_block_hash: "bdf06d18ed1931a8ee62654e9b6478cc459bc7072628b8e36f4524d339552946".into(), + tx_count: 43205750, + tx_pool_size: 12, + update_available: false, + version: "0.18.3.3-release".into(), + was_bootstrap_ever_used: false, + white_peerlist_size: 1000, + wide_cumulative_difficulty: "0x514bf349299d2eb".into(), + wide_difficulty: "0x415c05a7a2".into() + } + )] AccessResponseBase { adjusted_time: u64, alt_blocks_count: u64, @@ -364,6 +804,20 @@ define_request_and_response! { core_rpc_server_commands_defs.h => 1958..=1995, HardForkInfo, Request {}, + + #[doc = serde_doc_test!( + HARD_FORK_INFO_RESPONSE => HardForkInfoResponse { + base: AccessResponseBase::ok(), + earliest_height: 2689608, + enabled: true, + state: 0, + threshold: 0, + version: 16, + votes: 10080, + voting: 16, + window: 10080 + } + )] AccessResponseBase { earliest_height: u64, enabled: bool, @@ -381,9 +835,26 @@ define_request_and_response! { cc73fe71162d564ffda8e549b79a350bca53c454 => core_rpc_server_commands_defs.h => 2032..=2067, SetBans, + + #[doc = serde_doc_test!( + SET_BANS_REQUEST => SetBansRequest { + bans: vec![ SetBan { + host: "192.168.1.51".into(), + ip: 0, + ban: true, + seconds: 30 + }] + } + )] Request { bans: Vec, }, + + #[doc = serde_doc_test!( + SET_BANS_RESPONSE => SetBansResponse { + base: ResponseBase::ok(), + } + )] ResponseBase {} } @@ -393,6 +864,24 @@ define_request_and_response! { core_rpc_server_commands_defs.h => 1997..=2030, GetBans, Request {}, + + #[doc = serde_doc_test!( + GET_BANS_RESPONSE => GetBansResponse { + base: ResponseBase::ok(), + bans: vec![ + GetBan { + host: "104.248.206.131".into(), + ip: 2211379304, + seconds: 689754 + }, + GetBan { + host: "209.222.252.0/24".into(), + ip: 0, + seconds: 689754 + } + ] + } + )] ResponseBase { bans: Vec, } @@ -403,11 +892,23 @@ define_request_and_response! { cc73fe71162d564ffda8e549b79a350bca53c454 => core_rpc_server_commands_defs.h => 2069..=2094, Banned, - #[cfg_attr(feature = "serde", serde(transparent))] - #[repr(transparent)] + + #[doc = serde_doc_test!( + BANNED_REQUEST => BannedRequest { + address: "95.216.203.255".into(), + } + )] Request { address: String, }, + + #[doc = serde_doc_test!( + BANNED_RESPONSE => BannedResponse { + banned: true, + seconds: 689655, + status: Status::Ok, + } + )] Response { banned: bool, seconds: u32, @@ -420,10 +921,21 @@ define_request_and_response! { cc73fe71162d564ffda8e549b79a350bca53c454 => core_rpc_server_commands_defs.h => 2096..=2116, FlushTransactionPool, + + #[doc = serde_doc_test!( + FLUSH_TRANSACTION_POOL_REQUEST => FlushTransactionPoolRequest { + txids: vec!["dc16fa8eaffe1484ca9014ea050e13131d3acf23b419f33bb4cc0b32b6c49308".into()], + } + )] Request { txids: Vec = default_vec::(), "default_vec", }, - #[cfg_attr(feature = "serde", serde(transparent))] + + #[doc = serde_doc_test!( + FLUSH_TRANSACTION_POOL_RESPONSE => FlushTransactionPoolResponse { + status: Status::Ok, + } + )] #[repr(transparent)] Response { status: Status, @@ -435,13 +947,35 @@ define_request_and_response! { cc73fe71162d564ffda8e549b79a350bca53c454 => core_rpc_server_commands_defs.h => 2118..=2168, GetOutputHistogram, + + #[doc = serde_doc_test!( + GET_OUTPUT_HISTOGRAM_REQUEST => GetOutputHistogramRequest { + amounts: vec![20000000000], + min_count: 0, + max_count: 0, + unlocked: false, + recent_cutoff: 0, + } + )] Request { amounts: Vec, - min_count: u64, - max_count: u64, - unlocked: bool, - recent_cutoff: u64, + min_count: u64 = default_zero::(), "default_zero", + max_count: u64 = default_zero::(), "default_zero", + unlocked: bool = default_false(), "default_false", + recent_cutoff: u64 = default_zero::(), "default_zero", }, + + #[doc = serde_doc_test!( + GET_OUTPUT_HISTOGRAM_RESPONSE => GetOutputHistogramResponse { + base: AccessResponseBase::ok(), + histogram: vec![HistogramEntry { + amount: 20000000000, + recent_instances: 0, + total_instances: 381490, + unlocked_instances: 0 + }] + } + )] AccessResponseBase { histogram: Vec, } @@ -451,11 +985,31 @@ define_request_and_response! { get_coinbase_tx_sum, cc73fe71162d564ffda8e549b79a350bca53c454 => core_rpc_server_commands_defs.h => 2213..=2248, + GetCoinbaseTxSum, + + #[doc = serde_doc_test!( + GET_COINBASE_TX_SUM_REQUEST => GetCoinbaseTxSumRequest { + height: 1563078, + count: 2 + } + )] Request { height: u64, count: u64, }, + + #[doc = serde_doc_test!( + GET_COINBASE_TX_SUM_RESPONSE => GetCoinbaseTxSumResponse { + base: AccessResponseBase::ok(), + emission_amount: 9387854817320, + emission_amount_top64: 0, + fee_amount: 83981380000, + fee_amount_top64: 0, + wide_emission_amount: "0x889c7c06828".into(), + wide_fee_amount: "0x138dae29a0".into() + } + )] AccessResponseBase { emission_amount: u64, emission_amount_top64: u64, @@ -470,16 +1024,90 @@ define_request_and_response! { get_version, cc73fe71162d564ffda8e549b79a350bca53c454 => core_rpc_server_commands_defs.h => 2170..=2211, + GetVersion, Request {}, + + #[doc = serde_doc_test!( + GET_VERSION_RESPONSE => GetVersionResponse { + base: ResponseBase::ok(), + current_height: 3195051, + hard_forks: vec![ + HardforkEntry { + height: 1, + hf_version: 1 + }, + HardforkEntry { + height: 1009827, + hf_version: 2 + }, + HardforkEntry { + height: 1141317, + hf_version: 3 + }, + HardforkEntry { + height: 1220516, + hf_version: 4 + }, + HardforkEntry { + height: 1288616, + hf_version: 5 + }, + HardforkEntry { + height: 1400000, + hf_version: 6 + }, + HardforkEntry { + height: 1546000, + hf_version: 7 + }, + HardforkEntry { + height: 1685555, + hf_version: 8 + }, + HardforkEntry { + height: 1686275, + hf_version: 9 + }, + HardforkEntry { + height: 1788000, + hf_version: 10 + }, + HardforkEntry { + height: 1788720, + hf_version: 11 + }, + HardforkEntry { + height: 1978433, + hf_version: 12 + }, + HardforkEntry { + height: 2210000, + hf_version: 13 + }, + HardforkEntry { + height: 2210720, + hf_version: 14 + }, + HardforkEntry { + height: 2688888, + hf_version: 15 + }, + HardforkEntry { + height: 2689608, + hf_version: 16 + } + ], + release: true, + version: 196621, + target_height: 0, + } + )] ResponseBase { version: u32, release: bool, - #[serde(skip_serializing_if = "is_zero")] current_height: u64 = default_zero::(), "default_zero", - #[serde(skip_serializing_if = "is_zero")] target_height: u64 = default_zero::(), "default_zero", - #[serde(skip_serializing_if = "Vec::is_empty")] hard_forks: Vec = default_vec(), "default_vec", } } @@ -490,11 +1118,19 @@ define_request_and_response! { core_rpc_server_commands_defs.h => 2250..=2277, GetFeeEstimate, Request {}, + + #[doc = serde_doc_test!( + GET_FEE_ESTIMATE_RESPONSE => GetFeeEstimateResponse { + base: AccessResponseBase::ok(), + fee: 20000, + fees: vec![20000,80000,320000,4000000], + quantization_mask: 10000, + } + )] AccessResponseBase { fee: u64, fees: Vec, - #[serde(skip_serializing_if = "is_one")] - quantization_mask: u64, + quantization_mask: u64 = default_one::(), "default_one", } } @@ -504,6 +1140,34 @@ define_request_and_response! { core_rpc_server_commands_defs.h => 2279..=2310, GetAlternateChains, Request {}, + + #[doc = serde_doc_test!( + GET_ALTERNATE_CHAINS_RESPONSE => GetAlternateChainsResponse { + base: ResponseBase::ok(), + chains: vec![ + ChainInfo { + block_hash: "4826c7d45d7cf4f02985b5c405b0e5d7f92c8d25e015492ce19aa3b209295dce".into(), + block_hashes: vec!["4826c7d45d7cf4f02985b5c405b0e5d7f92c8d25e015492ce19aa3b209295dce".into()], + difficulty: 357404825113208373, + difficulty_top64: 0, + height: 3167471, + length: 1, + main_chain_parent_block: "69b5075ea627d6ba06b1c30b7e023884eeaef5282cf58ec847dab838ddbcdd86".into(), + wide_difficulty: "0x4f5c1cb79e22635".into(), + }, + ChainInfo { + block_hash: "33ee476f5a1c5b9d889274cbbe171f5e0112df7ed69021918042525485deb401".into(), + block_hashes: vec!["33ee476f5a1c5b9d889274cbbe171f5e0112df7ed69021918042525485deb401".into()], + difficulty: 354736121711617293, + difficulty_top64: 0, + height: 3157465, + length: 1, + main_chain_parent_block: "fd522fcc4cefe5c8c0e5c5600981b3151772c285df3a4e38e5c4011cf466d2cb".into(), + wide_difficulty: "0x4ec469f8b9ee50d".into(), + } + ], + } + )] ResponseBase { chains: Vec, } @@ -513,11 +1177,23 @@ define_request_and_response! { relay_tx, cc73fe71162d564ffda8e549b79a350bca53c454 => core_rpc_server_commands_defs.h => 2361..=2381, + RelayTx, + + #[doc = serde_doc_test!( + RELAY_TX_REQUEST => RelayTxRequest { + txids: vec!["9fd75c429cbe52da9a52f2ffc5fbd107fe7fd2099c0d8de274dc8a67e0c98613".into()] + } + )] Request { txids: Vec, }, - #[cfg_attr(feature = "serde", serde(transparent))] + + #[doc = serde_doc_test!( + RELAY_TX_RESPONSE => RelayTxResponse { + status: Status::Ok, + } + )] #[repr(transparent)] Response { status: Status, @@ -528,16 +1204,88 @@ define_request_and_response! { sync_info, cc73fe71162d564ffda8e549b79a350bca53c454 => core_rpc_server_commands_defs.h => 2383..=2443, + SyncInfo, Request {}, + + #[doc = serde_doc_test!( + SYNC_INFO_RESPONSE => SyncInfoResponse { + base: AccessResponseBase::ok(), + height: 3195157, + next_needed_pruning_seed: 0, + overview: "[]".into(), + spans: vec![], + peers: vec![ + SyncInfoPeer { + info: ConnectionInfo { + address: "142.93.128.65:44986".into(), + address_type: 1, + avg_download: 1, + avg_upload: 1, + connection_id: "a5803c4c2dac49e7b201dccdef54c862".into(), + current_download: 2, + current_upload: 1, + height: 3195157, + host: "142.93.128.65".into(), + incoming: true, + ip: "142.93.128.65".into(), + live_time: 18, + local_ip: false, + localhost: false, + peer_id: "6830e9764d3e5687".into(), + port: "44986".into(), + pruning_seed: 0, + recv_count: 20340, + recv_idle_time: 0, + rpc_credits_per_hash: 0, + rpc_port: 18089, + send_count: 32235, + send_idle_time: 6, + state: "normal".into(), + support_flags: 1 + } + }, + SyncInfoPeer { + info: ConnectionInfo { + address: "4iykytmumafy5kjahdqc7uzgcs34s2vwsadfjpk4znvsa5vmcxeup2qd.onion:18083".into(), + address_type: 4, + avg_download: 0, + avg_upload: 0, + connection_id: "277f7c821bc546878c8bd29977e780f5".into(), + current_download: 0, + current_upload: 0, + height: 3195157, + host: "4iykytmumafy5kjahdqc7uzgcs34s2vwsadfjpk4znvsa5vmcxeup2qd.onion".into(), + incoming: false, + ip: "".into(), + live_time: 2246, + local_ip: false, + localhost: false, + peer_id: "0000000000000001".into(), + port: "".into(), + pruning_seed: 389, + recv_count: 65164, + recv_idle_time: 15, + rpc_credits_per_hash: 0, + rpc_port: 0, + send_count: 99120, + send_idle_time: 15, + state: "normal".into(), + support_flags: 0 + } + } + ], + target_height: 0, + } + )] AccessResponseBase { height: u64, next_needed_pruning_seed: u32, overview: String, // FIXME: This is a `std::list` in `monerod` because...? - peers: Vec, + peers: Vec = default_vec::(), "default_vec", // FIXME: This is a `std::list` in `monerod` because...? - spans: Vec, + spans: Vec = default_vec::(), "default_vec", target_height: u64, } } @@ -548,6 +1296,14 @@ define_request_and_response! { core_rpc_server_commands_defs.h => 1637..=1664, GetTransactionPoolBacklog, Request {}, + + // TODO: enable test after binary string impl. + // #[doc = serde_doc_test!( + // GET_TRANSACTION_POOL_BACKLOG_RESPONSE => GetTransactionPoolBacklogResponse { + // base: ResponseBase::ok(), + // backlog: "...Binary...".into(), + // } + // )] ResponseBase { // TODO: this is a [`BinaryString`]. backlog: Vec, @@ -558,18 +1314,44 @@ define_request_and_response! { get_output_distribution, cc73fe71162d564ffda8e549b79a350bca53c454 => core_rpc_server_commands_defs.h => 2445..=2520, + /// This type is also used in the (undocumented) /// [`/get_output_distribution.bin`](https://github.com/monero-project/monero/blob/cc73fe71162d564ffda8e549b79a350bca53c454/src/rpc/core_rpc_server.h#L138) /// binary endpoint. GetOutputDistribution, + + #[doc = serde_doc_test!( + GET_OUTPUT_DISTRIBUTION_REQUEST => GetOutputDistributionRequest { + amounts: vec![628780000], + from_height: 1462078, + binary: true, + compress: false, + cumulative: false, + to_height: 0, + } + )] Request { amounts: Vec, - binary: bool, - compress: bool, - cumulative: bool, - from_height: u64, - to_height: u64, + binary: bool = default_true(), "default_true", + compress: bool = default_false(), "default_false", + cumulative: bool = default_false(), "default_false", + from_height: u64 = default_zero::(), "default_zero", + to_height: u64 = default_zero::(), "default_zero", }, + + // TODO: enable test after binary string impl. + // #[doc = serde_doc_test!( + // GET_OUTPUT_DISTRIBUTION_RESPONSE => GetOutputDistributionResponse { + // base: AccessResponseBase::ok(), + // distributions: vec![Distribution::Uncompressed(DistributionUncompressed { + // start_height: 1462078, + // base: 0, + // distribution: vec![], + // amount: 2628780000, + // binary: true, + // })], + // } + // )] AccessResponseBase { distributions: Vec, } @@ -581,6 +1363,31 @@ define_request_and_response! { core_rpc_server_commands_defs.h => 996..=1044, GetMinerData, Request {}, + + #[doc = serde_doc_test!( + GET_MINER_DATA_RESPONSE => GetMinerDataResponse { + base: ResponseBase::ok(), + already_generated_coins: 18186022843595960691, + difficulty: "0x48afae42de".into(), + height: 2731375, + major_version: 16, + median_weight: 300000, + prev_id: "78d50c5894d187c4946d54410990ca59a75017628174a9e8c7055fa4ca5c7c6d".into(), + seed_hash: "a6b869d50eca3a43ec26fe4c369859cf36ae37ce6ecb76457d31ffeb8a6ca8a6".into(), + tx_backlog: vec![ + GetMinerDataTxBacklogEntry { + fee: 30700000, + id: "9868490d6bb9207fdd9cf17ca1f6c791b92ca97de0365855ea5c089f67c22208".into(), + weight: 1535 + }, + GetMinerDataTxBacklogEntry { + fee: 44280000, + id: "b6000b02bbec71e18ad704bcae09fb6e5ae86d897ced14a718753e76e86c0a0a".into(), + weight: 2214 + }, + ], + } + )] ResponseBase { major_version: u8, height: u64, @@ -589,6 +1396,7 @@ define_request_and_response! { difficulty: String, median_weight: u64, already_generated_coins: u64, + tx_backlog: Vec, } } @@ -596,11 +1404,26 @@ define_request_and_response! { prune_blockchain, cc73fe71162d564ffda8e549b79a350bca53c454 => core_rpc_server_commands_defs.h => 2747..=2772, + PruneBlockchain, + #[derive(Copy)] + #[doc = serde_doc_test!( + PRUNE_BLOCKCHAIN_REQUEST => PruneBlockchainRequest { + check: true + } + )] Request { check: bool = default_false(), "default_false", }, + + #[doc = serde_doc_test!( + PRUNE_BLOCKCHAIN_RESPONSE => PruneBlockchainResponse { + base: ResponseBase::ok(), + pruned: true, + pruning_seed: 387, + } + )] ResponseBase { pruned: bool, pruning_seed: u32, @@ -611,13 +1434,29 @@ define_request_and_response! { calc_pow, cc73fe71162d564ffda8e549b79a350bca53c454 => core_rpc_server_commands_defs.h => 1046..=1066, + CalcPow, + + #[doc = serde_doc_test!( + CALC_POW_REQUEST => CalcPowRequest { + major_version: 14, + height: 2286447, + block_blob: "0e0ed286da8006ecdc1aab3033cf1716c52f13f9d8ae0051615a2453643de94643b550d543becd0000000002abc78b0101ffefc68b0101fcfcf0d4b422025014bb4a1eade6622fd781cb1063381cad396efa69719b41aa28b4fce8c7ad4b5f019ce1dc670456b24a5e03c2d9058a2df10fec779e2579753b1847b74ee644f16b023c00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000051399a1bc46a846474f5b33db24eae173a26393b976054ee14f9feefe99925233802867097564c9db7a36af5bb5ed33ab46e63092bd8d32cef121608c3258edd55562812e21cc7e3ac73045745a72f7d74581d9a0849d6f30e8b2923171253e864f4e9ddea3acb5bc755f1c4a878130a70c26297540bc0b7a57affb6b35c1f03d8dbd54ece8457531f8cba15bb74516779c01193e212050423020e45aa2c15dcb".into(), + seed_hash: "d432f499205150873b2572b5f033c9c6e4b7c6f3394bd2dd93822cd7085e7307".into(), + } + )] Request { major_version: u8, height: u64, block_blob: String, seed_hash: String, }, + + #[doc = serde_doc_test!( + CALC_POW_RESPONSE => CalcPowResponse { + pow_hash: "d0402d6834e26fb94a9ce38c6424d27d2069896a9b8b1ce685d79936bca6e0a8".into(), + } + )] #[cfg_attr(feature = "serde", serde(transparent))] #[repr(transparent)] Response { @@ -629,12 +1468,26 @@ define_request_and_response! { flush_cache, cc73fe71162d564ffda8e549b79a350bca53c454 => core_rpc_server_commands_defs.h => 2774..=2796, + FlushCache, + #[derive(Copy)] + #[doc = serde_doc_test!( + FLUSH_CACHE_REQUEST => FlushCacheRequest { + bad_txs: true, + bad_blocks: true + } + )] Request { bad_txs: bool = default_false(), "default_false", bad_blocks: bool = default_false(), "default_false", }, + + #[doc = serde_doc_test!( + FLUSH_CACHE_RESPONSE => FlushCacheResponse { + base: ResponseBase::ok(), + } + )] ResponseBase {} } @@ -642,11 +1495,36 @@ define_request_and_response! { add_aux_pow, cc73fe71162d564ffda8e549b79a350bca53c454 => core_rpc_server_commands_defs.h => 1068..=1112, + AddAuxPow, + + #[doc = serde_doc_test!( + ADD_AUX_POW_REQUEST => AddAuxPowRequest { + blocktemplate_blob: "1010f4bae0b4069d648e741d85ca0e7acb4501f051b27e9b107d3cd7a3f03aa7f776089117c81a0000000002c681c30101ff8a81c3010180e0a596bb11033b7eedf47baf878f3490cb20b696079c34bd017fe59b0d070e74d73ffabc4bb0e05f011decb630f3148d0163b3bd39690dde4078e4cfb69fecf020d6278a27bad10c58023c0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000".into(), + aux_pow: vec![AuxPow { + id: "3200b4ea97c3b2081cd4190b58e49572b2319fed00d030ad51809dff06b5d8c8".into(), + hash: "7b35762de164b20885e15dbe656b1138db06bb402fa1796f5765a23933d8859a".into() + }] + } + )] Request { blocktemplate_blob: String, aux_pow: Vec, }, + + #[doc = serde_doc_test!( + ADD_AUX_POW_RESPONSE => AddAuxPowResponse { + base: ResponseBase::ok(), + aux_pow: vec![AuxPow { + hash: "7b35762de164b20885e15dbe656b1138db06bb402fa1796f5765a23933d8859a".into(), + id: "3200b4ea97c3b2081cd4190b58e49572b2319fed00d030ad51809dff06b5d8c8".into(), + }], + blockhashing_blob: "1010ee97e2a106e9f8ebe8887e5b609949ac8ea6143e560ed13552b110cb009b21f0cfca1eaccf00000000b2685c1283a646bc9020c758daa443be145b7370ce5a6efacb3e614117032e2c22".into(), + blocktemplate_blob: "1010f4bae0b4069d648e741d85ca0e7acb4501f051b27e9b107d3cd7a3f03aa7f776089117c81a0000000002c681c30101ff8a81c3010180e0a596bb11033b7eedf47baf878f3490cb20b696079c34bd017fe59b0d070e74d73ffabc4bb0e05f011decb630f3148d0163b3bd39690dde4078e4cfb69fecf020d6278a27bad10c58023c0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000".into(), + merkle_root: "7b35762de164b20885e15dbe656b1138db06bb402fa1796f5765a23933d8859a".into(), + merkle_tree_depth: 0, + } + )] ResponseBase { blocktemplate_blob: String, blockhashing_blob: String, diff --git a/rpc/types/src/misc/misc.rs b/rpc/types/src/misc/misc.rs index 4643ecc..2b31cab 100644 --- a/rpc/types/src/misc/misc.rs +++ b/rpc/types/src/misc/misc.rs @@ -22,7 +22,7 @@ use crate::{ CORE_RPC_STATUS_BUSY, CORE_RPC_STATUS_NOT_MINING, CORE_RPC_STATUS_OK, CORE_RPC_STATUS_PAYMENT_REQUIRED, }, - defaults::default_zero, + defaults::{default_string, default_zero}, macros::monero_definition_link, }; @@ -51,9 +51,9 @@ macro_rules! define_struct_and_impl_epee { )* } ) => { - $( #[$struct_attr] )* #[derive(Clone, Debug, Default, PartialEq, Eq, PartialOrd, Ord, Hash)] #[cfg_attr(feature = "serde", derive(Serialize, Deserialize))] + $( #[$struct_attr] )* pub struct $struct_name { $( $( #[$field_attr] )* @@ -142,7 +142,9 @@ define_struct_and_impl_epee! { rpc_port: u16, send_count: u64, send_idle_time: u64, - ssl: bool, + // Exists in the original definition, but isn't + // used or (de)serialized for RPC purposes. + // ssl: bool, state: String, support_flags: u32, } @@ -156,7 +158,9 @@ define_struct_and_impl_epee! { )] /// Used in [`crate::json::SetBansRequest`]. SetBan { + #[cfg_attr(feature = "serde", serde(default = "default_string"))] host: String, + #[cfg_attr(feature = "serde", serde(default = "default_zero"))] ip: u32, ban: bool, seconds: u32, diff --git a/rpc/types/src/other.rs b/rpc/types/src/other.rs index 41530cb..c140777 100644 --- a/rpc/types/src/other.rs +++ b/rpc/types/src/other.rs @@ -5,7 +5,7 @@ //---------------------------------------------------------------------------------------------------- Import use crate::{ base::{AccessResponseBase, ResponseBase}, - defaults::{default_false, default_string, default_true}, + defaults::{default_false, default_string, default_true, default_vec, default_zero}, macros::define_request_and_response, misc::{ GetOutputsOut, KeyImageSpentStatus, OutKey, Peer, PublicNode, SpentKeyImageInfo, Status, @@ -13,6 +13,81 @@ use crate::{ }, }; +//---------------------------------------------------------------------------------------------------- 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 + // ^ + // 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, @@ -20,6 +95,14 @@ define_request_and_response! { core_rpc_server_commands_defs.h => 138..=160, GetHeight, Request {}, + + #[doc = serde_doc_test!( + GET_HEIGHT_RESPONSE => GetHeightResponse { + base: ResponseBase::ok(), + hash: "68bb1a1cff8e2a44c3221e8e1aff80bc6ca45d06fa8eff4d2a3a7ac31d4efe3f".into(), + height: 3195160, + } + )] ResponseBase { hash: String, height: u64, @@ -31,6 +114,15 @@ define_request_and_response! { cc73fe71162d564ffda8e549b79a350bca53c454 => 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 @@ -40,11 +132,13 @@ define_request_and_response! { prune: bool = default_false(), "default_false", split: bool = default_false(), "default_false", }, + + #[doc = serde_doc_test!(GET_TRANSACTIONS_RESPONSE)] AccessResponseBase { - txs_as_hex: Vec, - txs_as_json: Vec, - missed_tx: Vec, - txs: Vec, + txs_as_hex: Vec = default_vec::(), "default_vec", + txs_as_json: Vec = default_vec::(), "default_vec", + missed_tx: Vec = default_vec::(), "default_vec", + txs: Vec = default_vec::(), "default_vec", } } @@ -54,6 +148,13 @@ define_request_and_response! { core_rpc_server_commands_defs.h => 288..=308, GetAltBlocksHashes, Request {}, + + #[doc = serde_doc_test!( + GET_ALT_BLOCKS_HASHES_RESPONSE => GetAltBlocksHashesResponse { + base: AccessResponseBase::ok(), + blks_hashes: vec!["8ee10db35b1baf943f201b303890a29e7d45437bd76c2bd4df0d2f2ee34be109".into()], + } + )] AccessResponseBase { blks_hashes: Vec, } @@ -63,10 +164,27 @@ define_request_and_response! { is_key_image_spent, cc73fe71162d564ffda8e549b79a350bca53c454 => core_rpc_server_commands_defs.h => 454..=484, + 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`] in [`u8`] form. spent_status: Vec, @@ -77,19 +195,54 @@ define_request_and_response! { send_raw_transaction, cc73fe71162d564ffda8e549b79a350bca53c454 => core_rpc_server_commands_defs.h => 370..=451, + 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, invalid_input: bool, invalid_output: bool, low_mixin: bool, - nonzero_unlock_time: bool, + nonzero_unlock_time: bool = default_false(), "default_false", not_relayed: bool, overspend: bool, reason: String, @@ -104,13 +257,29 @@ define_request_and_response! { start_mining, cc73fe71162d564ffda8e549b79a350bca53c454 => core_rpc_server_commands_defs.h => 665..=691, + StartMining, + + #[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, do_background_mining: bool, ignore_battery: bool, }, + + #[doc = serde_doc_test!( + START_MINING_RESPONSE => StartMiningResponse { + base: ResponseBase::ok(), + } + )] ResponseBase {} } @@ -120,6 +289,12 @@ define_request_and_response! { core_rpc_server_commands_defs.h => 825..=843, StopMining, Request {}, + + #[doc = serde_doc_test!( + STOP_MINING_RESPONSE => StopMiningResponse { + base: ResponseBase::ok(), + } + )] ResponseBase {} } @@ -129,6 +304,27 @@ define_request_and_response! { core_rpc_server_commands_defs.h => 846..=895, MiningStatus, 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, @@ -154,6 +350,12 @@ define_request_and_response! { core_rpc_server_commands_defs.h => 898..=916, SaveBc, Request {}, + + #[doc = serde_doc_test!( + SAVE_BC_RESPONSE => SaveBcResponse { + base: ResponseBase::ok(), + } + )] ResponseBase {} } @@ -161,11 +363,79 @@ define_request_and_response! { get_peer_list, cc73fe71162d564ffda8e549b79a350bca53c454 => core_rpc_server_commands_defs.h => 1369..=1417, + GetPeerList, + + #[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, @@ -177,10 +447,22 @@ define_request_and_response! { cc73fe71162d564ffda8e549b79a350bca53c454 => core_rpc_server_commands_defs.h => 1450..=1470, SetLogHashRate, + #[derive(Copy)] + #[doc = serde_doc_test!( + SET_LOG_HASH_RATE_REQUEST => SetLogHashRateRequest { + visible: true, + } + )] Request { - visible: bool, + visible: bool = default_false(), "default_false", }, + + #[doc = serde_doc_test!( + SET_LOG_HASH_RATE_RESPONSE => SetLogHashRateResponse { + base: ResponseBase::ok(), + } + )] ResponseBase {} } @@ -188,11 +470,24 @@ define_request_and_response! { set_log_level, cc73fe71162d564ffda8e549b79a350bca53c454 => core_rpc_server_commands_defs.h => 1450..=1470, + SetLogLevel, + #[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 {} } @@ -200,10 +495,24 @@ define_request_and_response! { set_log_categories, cc73fe71162d564ffda8e549b79a350bca53c454 => core_rpc_server_commands_defs.h => 1494..=1517, + SetLogCategories, + + #[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, } @@ -213,13 +522,29 @@ define_request_and_response! { set_bootstrap_daemon, cc73fe71162d564ffda8e549b79a350bca53c454 => core_rpc_server_commands_defs.h => 1785..=1812, + SetBootstrapDaemon, + + #[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, - password: String, - proxy: String, + username: String = default_string(), "default_string", + password: String = default_string(), "default_string", + proxy: String = default_string(), "default_string", }, + + #[doc = serde_doc_test!( + SET_BOOTSTRAP_DAEMON_RESPONSE => SetBootstrapDaemonResponse { + status: Status::Ok, + } + )] Response { status: Status, } @@ -229,8 +554,11 @@ define_request_and_response! { get_transaction_pool, cc73fe71162d564ffda8e549b79a350bca53c454 => core_rpc_server_commands_defs.h => 1569..=1591, + GetTransactionPool, Request {}, + + #[doc = serde_doc_test!(GET_TRANSACTION_POOL_RESPONSE)] AccessResponseBase { transactions: Vec, spent_key_images: Vec, @@ -241,8 +569,41 @@ define_request_and_response! { get_transaction_pool_stats, cc73fe71162d564ffda8e549b79a350bca53c454 => core_rpc_server_commands_defs.h => 1712..=1732, + GetTransactionPoolStats, 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, } @@ -252,9 +613,16 @@ define_request_and_response! { stop_daemon, cc73fe71162d564ffda8e549b79a350bca53c454 => core_rpc_server_commands_defs.h => 1814..=1831, + StopDaemon, Request {}, - ResponseBase { + + #[doc = serde_doc_test!( + STOP_DAEMON_RESPONSE => StopDaemonResponse { + status: Status::Ok, + } + )] + Response { status: Status, } } @@ -263,8 +631,17 @@ define_request_and_response! { get_limit, cc73fe71162d564ffda8e549b79a350bca53c454 => core_rpc_server_commands_defs.h => 1852..=1874, + GetLimit, 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, @@ -275,11 +652,27 @@ define_request_and_response! { set_limit, cc73fe71162d564ffda8e549b79a350bca53c454 => core_rpc_server_commands_defs.h => 1876..=1903, + SetLimit, + #[doc = serde_doc_test!( + SET_LIMIT_REQUEST => SetLimitRequest { + limit_down: 1024, + limit_up: 0, + } + )] Request { - limit_down: i64, - limit_up: i64, + // 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, @@ -290,11 +683,26 @@ define_request_and_response! { out_peers, cc73fe71162d564ffda8e549b79a350bca53c454 => core_rpc_server_commands_defs.h => 1876..=1903, + OutPeers, + + #[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, } @@ -304,8 +712,20 @@ define_request_and_response! { get_net_stats, cc73fe71162d564ffda8e549b79a350bca53c454 => core_rpc_server_commands_defs.h => 793..=822, + GetNetStats, 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, @@ -319,11 +739,43 @@ 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, } @@ -333,11 +785,31 @@ define_request_and_response! { update, cc73fe71162d564ffda8e549b79a350bca53c454 => core_rpc_server_commands_defs.h => 2324..=2359, + Update, + + #[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, @@ -352,35 +824,62 @@ define_request_and_response! { pop_blocks, cc73fe71162d564ffda8e549b79a350bca53c454 => core_rpc_server_commands_defs.h => 2722..=2745, + PopBlocks, + + #[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, } } -define_request_and_response! { - UNDOCUMENTED_ENDPOINT, - cc73fe71162d564ffda8e549b79a350bca53c454 => - core_rpc_server_commands_defs.h => 2798..=2823, - GetTxIdsLoose, - Request { - txid_template: String, - num_matching_bits: u32, - }, - ResponseBase { - txids: Vec, - } -} - define_request_and_response! { UNDOCUMENTED_ENDPOINT, cc73fe71162d564ffda8e549b79a350bca53c454 => core_rpc_server_commands_defs.h => 1615..=1635, + GetTransactionPoolHashes, 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, } @@ -391,14 +890,43 @@ define_request_and_response! { cc73fe71162d564ffda8e549b79a350bca53c454 => core_rpc_server_commands_defs.h => 1419..=1448, GetPublicNodes, + + #[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, - white: Vec, + gray: Vec = default_vec::(), "default_vec", + white: Vec = default_vec::(), "default_vec", } } diff --git a/test-utils/src/rpc/data/json.rs b/test-utils/src/rpc/data/json.rs index 2463e45..a05af67 100644 --- a/test-utils/src/rpc/data/json.rs +++ b/test-utils/src/rpc/data/json.rs @@ -771,7 +771,7 @@ r#"{ "id": "0", "method": "get_output_histogram", "params": { - "amounts": ["20000000000"] + "amounts": [20000000000] } }"#; Response = @@ -1106,13 +1106,17 @@ r#"{ "id": "0", "jsonrpc": "2.0", "result": { + "credits": 0, "distributions": [{ "amount": 2628780000, "base": 0, "distribution": "", - "start_height": 1462078 + "start_height": 1462078, + "binary": false }], - "status": "OK" + "status": "OK", + "top_hash": "", + "untrusted": false } }"#; } diff --git a/test-utils/src/rpc/data/other.rs b/test-utils/src/rpc/data/other.rs index 2559bbe..80a48ab 100644 --- a/test-utils/src/rpc/data/other.rs +++ b/test-utils/src/rpc/data/other.rs @@ -234,11 +234,13 @@ define_request_and_response! { set_log_hash_rate (other), SET_LOG_HASH_RATE: &str, Request = -r#"{}"#; +r#"{ + "visible": true +}"#; Response = r#" { - "status": "OK" + "status": "OK", "untrusted": false }"#; } @@ -252,7 +254,7 @@ r#"{ }"#; Response = r#"{ - "status": "OK" + "status": "OK", "untrusted": false }"#; } @@ -673,7 +675,7 @@ r#"{ "limit_down": 1280000, "limit_up": 1280000, "status": "OK", - "untrusted": true + "untrusted": false }"#; } @@ -688,7 +690,7 @@ r#"{ r#"{ "limit_down": 1024, "limit_up": 128, - "status": "OK" + "status": "OK", "untrusted": false }"#; } @@ -712,13 +714,15 @@ define_request_and_response! { get_net_stats (other), GET_NET_STATS: &str, Request = -r#"{ - "in_peers": 3232235535 -}"#; +r#"{}"#; Response = r#"{ - "in_peers": 3232235535, + "start_time": 1721251858, "status": "OK", + "total_bytes_in": 16283817214, + "total_bytes_out": 34225244079, + "total_packets_in": 5981922, + "total_packets_out": 3627107, "untrusted": false }"#; } @@ -804,7 +808,26 @@ r#"{ "credits": 0, "status": "OK", "top_hash": "", - "tx_hashes": ["aa928aed888acd6152c60194d50a4df29b0b851be6169acf11b6a8e304dd6c03","794345f321a98f3135151f3056c0fdf8188646a8dab27de971428acf3551dd11","1e9d2ae11f2168a228942077483e70940d34e8658c972bbc3e7f7693b90edf17","7375c928f261d00f07197775eb0bfa756e5f23319819152faa0b3c670fe54c1b","2e4d5f8c5a45498f37fb8b6ca4ebc1efa0c371c38c901c77e66b08c072287329","eee6d596cf855adfb10e1597d2018e3a61897ac467ef1d4a5406b8d20bfbd52f","59c574d7ba9bb4558470f74503c7518946a85ea22c60fccfbdec108ce7d8f236","0d57bec1e1075a9e1ac45cf3b3ced1ad95ccdf2a50ce360190111282a0178655","60d627b2369714a40009c07d6185ebe7fa4af324fdfa8d95a37a936eb878d062","661d7e728a901a8cb4cf851447d9cd5752462687ed0b776b605ba706f06bdc7d","b80e1f09442b00b3fffe6db5d263be6267c7586620afff8112d5a8775a6fc58e","974063906d1ddfa914baf85176b0f689d616d23f3d71ed4798458c8b4f9b9d8f","d2575ae152a180be4981a9d2fc009afcd073adaa5c6d8b022c540a62d6c905bb","3d78aa80ee50f506683bab9f02855eb10257a08adceda7cbfbdfc26b10f6b1bb","8b5bc125bdb73b708500f734501d55088c5ac381a0879e1141634eaa72b6a4da","11c06f4d2f00c912ca07313ed2ea5366f3cae914a762bed258731d3d9e3706df","b3644dc7c9a3a53465fe80ad3769e516edaaeb7835e16fdd493aac110d472ae1","ed2478ad793b923dbf652c8612c40799d764e5468897021234a14a37346bc6ee"], + "tx_hashes": [ + "aa928aed888acd6152c60194d50a4df29b0b851be6169acf11b6a8e304dd6c03", + "794345f321a98f3135151f3056c0fdf8188646a8dab27de971428acf3551dd11", + "1e9d2ae11f2168a228942077483e70940d34e8658c972bbc3e7f7693b90edf17", + "7375c928f261d00f07197775eb0bfa756e5f23319819152faa0b3c670fe54c1b", + "2e4d5f8c5a45498f37fb8b6ca4ebc1efa0c371c38c901c77e66b08c072287329", + "eee6d596cf855adfb10e1597d2018e3a61897ac467ef1d4a5406b8d20bfbd52f", + "59c574d7ba9bb4558470f74503c7518946a85ea22c60fccfbdec108ce7d8f236", + "0d57bec1e1075a9e1ac45cf3b3ced1ad95ccdf2a50ce360190111282a0178655", + "60d627b2369714a40009c07d6185ebe7fa4af324fdfa8d95a37a936eb878d062", + "661d7e728a901a8cb4cf851447d9cd5752462687ed0b776b605ba706f06bdc7d", + "b80e1f09442b00b3fffe6db5d263be6267c7586620afff8112d5a8775a6fc58e", + "974063906d1ddfa914baf85176b0f689d616d23f3d71ed4798458c8b4f9b9d8f", + "d2575ae152a180be4981a9d2fc009afcd073adaa5c6d8b022c540a62d6c905bb", + "3d78aa80ee50f506683bab9f02855eb10257a08adceda7cbfbdfc26b10f6b1bb", + "8b5bc125bdb73b708500f734501d55088c5ac381a0879e1141634eaa72b6a4da", + "11c06f4d2f00c912ca07313ed2ea5366f3cae914a762bed258731d3d9e3706df", + "b3644dc7c9a3a53465fe80ad3769e516edaaeb7835e16fdd493aac110d472ae1", + "ed2478ad793b923dbf652c8612c40799d764e5468897021234a14a37346bc6ee" + ], "untrusted": false }"#; } diff --git a/typos.toml b/typos.toml index 0317c40..fbd66d0 100644 --- a/typos.toml +++ b/typos.toml @@ -18,4 +18,5 @@ extend-exclude = [ "/misc/gpg_keys/", "cryptonight/", "/test-utils/src/rpc/data/json.rs", + "rpc/types/src/json.rs", ]