diff --git a/Cargo.lock b/Cargo.lock index 1997267..5caae0e 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1072,7 +1072,9 @@ dependencies = [ "cuprate-test-utils", "cuprate-types", "hex", + "hex-literal", "paste", + "pretty_assertions", "serde", "serde_json", ] diff --git a/binaries/cuprated/src/rpc/helper.rs b/binaries/cuprated/src/rpc/helper.rs index 98305df..bba2120 100644 --- a/binaries/cuprated/src/rpc/helper.rs +++ b/binaries/cuprated/src/rpc/helper.rs @@ -76,7 +76,6 @@ pub(super) async fn block_header( let (cumulative_difficulty_top64, cumulative_difficulty) = split_u128_into_low_high_bits(header.cumulative_difficulty); let (difficulty_top64, difficulty) = split_u128_into_low_high_bits(difficulty); - let wide_difficulty = hex::encode(difficulty.to_ne_bytes()); let reward = block .miner_transaction diff --git a/binaries/cuprated/src/rpc/json.rs b/binaries/cuprated/src/rpc/json.rs index 998d351..c42d6e4 100644 --- a/binaries/cuprated/src/rpc/json.rs +++ b/binaries/cuprated/src/rpc/json.rs @@ -34,24 +34,25 @@ use cuprate_rpc_types::{ GetBlockCountRequest, GetBlockCountResponse, GetBlockHeaderByHashRequest, GetBlockHeaderByHashResponse, GetBlockHeaderByHeightRequest, GetBlockHeaderByHeightResponse, GetBlockHeadersRangeRequest, GetBlockHeadersRangeResponse, - GetBlockRequest, GetBlockResponse, GetCoinbaseTxSumRequest, GetCoinbaseTxSumResponse, - GetConnectionsRequest, GetConnectionsResponse, GetFeeEstimateRequest, - GetFeeEstimateResponse, GetInfoRequest, GetInfoResponse, GetLastBlockHeaderRequest, - GetLastBlockHeaderResponse, GetMinerDataRequest, GetMinerDataResponse, - GetOutputDistributionRequest, GetOutputDistributionResponse, GetOutputHistogramRequest, - GetOutputHistogramResponse, GetTransactionPoolBacklogRequest, - GetTransactionPoolBacklogResponse, GetTxIdsLooseRequest, GetTxIdsLooseResponse, - GetVersionRequest, GetVersionResponse, HardForkInfoRequest, HardForkInfoResponse, - JsonRpcRequest, JsonRpcResponse, OnGetBlockHashRequest, OnGetBlockHashResponse, - PruneBlockchainRequest, PruneBlockchainResponse, RelayTxRequest, RelayTxResponse, - SetBansRequest, SetBansResponse, SubmitBlockRequest, SubmitBlockResponse, SyncInfoRequest, - SyncInfoResponse, + GetBlockRequest, GetBlockResponse, GetBlockTemplateRequest, GetBlockTemplateResponse, + GetCoinbaseTxSumRequest, GetCoinbaseTxSumResponse, GetConnectionsRequest, + GetConnectionsResponse, GetFeeEstimateRequest, GetFeeEstimateResponse, GetInfoRequest, + GetInfoResponse, GetLastBlockHeaderRequest, GetLastBlockHeaderResponse, + GetMinerDataRequest, GetMinerDataResponse, GetOutputDistributionRequest, + GetOutputDistributionResponse, GetOutputHistogramRequest, GetOutputHistogramResponse, + GetTransactionPoolBacklogRequest, GetTransactionPoolBacklogResponse, GetTxIdsLooseRequest, + GetTxIdsLooseResponse, GetVersionRequest, GetVersionResponse, HardForkInfoRequest, + HardForkInfoResponse, JsonRpcRequest, JsonRpcResponse, OnGetBlockHashRequest, + OnGetBlockHashResponse, PruneBlockchainRequest, PruneBlockchainResponse, RelayTxRequest, + RelayTxResponse, SetBansRequest, SetBansResponse, SubmitBlockRequest, SubmitBlockResponse, + SyncInfoRequest, SyncInfoResponse, }, misc::{BlockHeader, ChainInfo, Distribution, GetBan, HistogramEntry, Status, SyncInfoPeer}, CORE_RPC_VERSION, }; use cuprate_types::{ - rpc::{AuxPow, CoinbaseTxSum, GetMinerDataTxBacklogEntry, HardforkEntry, TxBacklogEntry}, + hex::Hex, + rpc::{AuxPow, CoinbaseTxSum, GetMinerDataTxBacklogEntry, HardForkEntry, TxBacklogEntry}, HardFork, }; @@ -76,6 +77,7 @@ pub(super) async fn map_request( use JsonRpcResponse as Resp; Ok(match request { + Req::GetBlockTemplate(r) => Resp::GetBlockTemplate(get_block_template(state, r).await?), Req::GetBlockCount(r) => Resp::GetBlockCount(get_block_count(state, r).await?), Req::OnGetBlockHash(r) => Resp::OnGetBlockHash(on_get_block_hash(state, r).await?), Req::SubmitBlock(r) => Resp::SubmitBlock(submit_block(state, r).await?), @@ -125,6 +127,101 @@ pub(super) async fn map_request( }) } +/// +async fn get_block_template( + mut state: CupratedRpcHandler, + request: GetBlockTemplateRequest, +) -> Result { + if request.reserve_size > 255 { + return Err(anyhow!("Too big reserved size, maximum 255")); + } + + if request.reserve_size != 0 && !request.extra_nonce.is_empty() { + return Err(anyhow!( + "Cannot specify both a reserve_size and an extra_nonce" + )); + } + + if request.extra_nonce.len() > 510 { + return Err(anyhow!("Too big extra_nonce size")); + } + + // cryptonote::address_parse_info info; + + if request.wallet_address.is_empty() + || todo!( + "!cryptonote::get_account_address_from_str(info, nettype(), request.wallet_address))" + ) + { + return Err(anyhow!("Failed to parse wallet address")); + } + + if todo!("info.is_subaddress") { + return Err(anyhow!("Mining to subaddress is not supported yet")); + } + + // block b; + // cryptonote::blobdata blob_reserve; + // size_t reserved_offset; + // if(!request.extra_nonce.empty()) + // { + // if(!string_tools::parse_hexstr_to_binbuff(request.extra_nonce, blob_reserve)) + // { + // error_resp.code = CORE_RPC_ERROR_CODE_WRONG_PARAM; + // error_resp.message = "Parameter extra_nonce should be a hex string"; + // return false; + // } + // } + // else + // blob_reserve.resize(request.reserve_size, 0); + // cryptonote::difficulty_type wdiff; + // crypto::hash prev_block; + // if (!request.prev_block.empty()) + // { + // if (!epee::string_tools::hex_to_pod(request.prev_block, prev_block)) + // { + // error_resp.code = CORE_RPC_ERROR_CODE_INTERNAL_ERROR; + // error_resp.message = "Invalid prev_block"; + // return false; + // } + // } + // crypto::hash seed_hash, next_seed_hash; + // if (!get_block_template(info.address, request.prev_block.empty() ? NULL : &prev_block, blob_reserve, reserved_offset, wdiff, res.height, res.expected_reward, res.cumulative_weight, b, res.seed_height, seed_hash, next_seed_hash, error_resp)) + // return false; + // if (b.major_version >= RX_BLOCK_VERSION) + // { + // res.seed_hash = string_tools::pod_to_hex(seed_hash); + // if (seed_hash != next_seed_hash) + // res.next_seed_hash = string_tools::pod_to_hex(next_seed_hash); + // } + + // res.reserved_offset = reserved_offset; + // store_difficulty(wdiff, res.difficulty, res.wide_difficulty, res.difficulty_top64); + // blobdata block_blob = t_serializable_object_to_blob(b); + // blobdata hashing_blob = get_block_hashing_blob(b); + // res.prev_hash = string_tools::pod_to_hex(b.prev_id); + // res.blocktemplate_blob = string_tools::buff_to_hex_nodelimer(block_blob); + // res.blockhashing_blob = string_tools::buff_to_hex_nodelimer(hashing_blob); + // res.status = CORE_RPC_STATUS_OK; + // return true; + + Ok(GetBlockTemplateResponse { + base: ResponseBase::OK, + blockhashing_blob: todo!(), + blocktemplate_blob: todo!(), + difficulty_top64: todo!(), + difficulty: todo!(), + expected_reward: todo!(), + height: todo!(), + next_seed_hash: todo!(), + prev_hash: todo!(), + reserved_offset: todo!(), + seed_hash: todo!(), + seed_height: todo!(), + wide_difficulty: todo!(), + }) +} + /// async fn get_block_count( mut state: CupratedRpcHandler, @@ -148,9 +245,10 @@ async fn on_get_block_hash( todo!("access to `cuprated`'s Chain"), ) .await?; - let block_hash = hex::encode(hash); - Ok(OnGetBlockHashResponse { block_hash }) + Ok(OnGetBlockHashResponse { + block_hash: Hex(hash), + }) } /// @@ -232,19 +330,19 @@ async fn get_block_header_by_hash( async fn get( state: &mut CupratedRpcHandler, - hex: String, + hash: [u8; 32], fill_pow_hash: bool, ) -> Result { - let hash = helper::hex_to_hash(hex)?; let block_header = helper::block_header_by_hash(state, hash, fill_pow_hash).await?; Ok(block_header) } - let block_header = get(&mut state, request.hash, request.fill_pow_hash).await?; + let block_header = get(&mut state, request.hash.0, request.fill_pow_hash).await?; // FIXME PERF: could make a `Vec` on await on all tasks at the same time. let mut block_headers = Vec::with_capacity(request.hashes.len()); for hash in request.hashes { + let hash = helper::hex_to_hash(hash)?; let hash = get(&mut state, hash, request.fill_pow_hash).await?; block_headers.push(hash); } @@ -736,7 +834,7 @@ async fn get_version( for hf in HardFork::VARIANTS { if let Ok(hf) = blockchain_context::hard_fork_info(&mut state.blockchain_context, *hf).await { - let entry = HardforkEntry { + let entry = HardForkEntry { height: hf.earliest_height, hf_version: HardFork::from_version(hf.version) .expect("blockchain context should not be responding with invalid hardforks"), @@ -1196,7 +1294,7 @@ fn add_aux_pow_inner( let blocktemplate_blob = hex::encode(blocktemplate_blob); let blockhashing_blob = hex::encode(blockhashing_blob); - let merkle_root = hex::encode(merkle_root); + let merkle_root = Hex(merkle_root); let aux_pow = aux_pow.into_vec(); Ok(AddAuxPowResponse { diff --git a/helper/Cargo.toml b/helper/Cargo.toml index 7ebbf8a..73c33c4 100644 --- a/helper/Cargo.toml +++ b/helper/Cargo.toml @@ -23,7 +23,7 @@ map = ["cast", "dep:monero-serai", "dep:cuprate-constants"] time = ["dep:chrono", "std"] thread = ["std", "dep:target_os_lib"] tx = ["dep:monero-serai"] -fmt = ["map"] +fmt = ["map", "std"] [dependencies] cuprate-constants = { workspace = true, optional = true, features = ["block"] } diff --git a/helper/src/lib.rs b/helper/src/lib.rs index 7142bd9..bf46404 100644 --- a/helper/src/lib.rs +++ b/helper/src/lib.rs @@ -11,7 +11,7 @@ pub mod atomic; #[cfg(feature = "cast")] pub mod cast; -#[cfg(all(feature = "fs", feature = "std"))] +#[cfg(feature = "fs")] pub mod fs; pub mod network; diff --git a/rpc/interface/src/rpc_handler_dummy.rs b/rpc/interface/src/rpc_handler_dummy.rs index 77bff6a..e7bf41a 100644 --- a/rpc/interface/src/rpc_handler_dummy.rs +++ b/rpc/interface/src/rpc_handler_dummy.rs @@ -59,6 +59,7 @@ impl Service for RpcHandlerDummy { #[expect(clippy::default_trait_access)] let resp = match req { + Req::GetBlockTemplate(_) => Resp::GetBlockTemplate(Default::default()), Req::GetBlockCount(_) => Resp::GetBlockCount(Default::default()), Req::OnGetBlockHash(_) => Resp::OnGetBlockHash(Default::default()), Req::SubmitBlock(_) => Resp::SubmitBlock(Default::default()), diff --git a/rpc/types/Cargo.toml b/rpc/types/Cargo.toml index 55fac9c..a0e7476 100644 --- a/rpc/types/Cargo.toml +++ b/rpc/types/Cargo.toml @@ -16,6 +16,7 @@ from = [ "dep:cuprate-helper", "cuprate-helper/map", "cuprate-helper/fmt", + "cuprate-types/rpc", "dep:cuprate-p2p-core", "dep:hex" ] @@ -34,8 +35,10 @@ hex = { workspace = true, optional = true } [dev-dependencies] cuprate-test-utils = { workspace = true } -serde = { workspace = true } -serde_json = { workspace = true } +hex-literal = { workspace = true } +pretty_assertions = { workspace = true } +serde = { workspace = true } +serde_json = { workspace = true } [lints] workspace = true diff --git a/rpc/types/src/defaults.rs b/rpc/types/src/defaults.rs index def5df4..8badde7 100644 --- a/rpc/types/src/defaults.rs +++ b/rpc/types/src/defaults.rs @@ -8,6 +8,7 @@ //! `height`, it will use [`default_height`] to fill that in. //---------------------------------------------------------------------------------------------------- Import +// use cuprate_types::hex::Hex; //---------------------------------------------------------------------------------------------------- TODO /// Default [`bool`] type used in request/response types, `false`. @@ -28,6 +29,12 @@ pub(crate) const fn default_string() -> String { String::new() } +// /// Default [`Hex`] type used in request/response types. +// #[inline] +// pub(crate) const fn default_hex() -> Hex { +// Hex([0; N]) +// } + /// Default block height used in request/response types. #[inline] pub(crate) const fn default_height() -> u64 { diff --git a/rpc/types/src/json.rs b/rpc/types/src/json.rs index 4d51252..e2fd09a 100644 --- a/rpc/types/src/json.rs +++ b/rpc/types/src/json.rs @@ -6,7 +6,10 @@ #[cfg(feature = "serde")] use serde::{Deserialize, Serialize}; -use cuprate_types::rpc::{AuxPow, GetMinerDataTxBacklogEntry, HardforkEntry, TxBacklogEntry}; +use cuprate_types::{ + hex::Hex, + rpc::{AuxPow, GetMinerDataTxBacklogEntry, HardForkEntry, TxBacklogEntry}, +}; use crate::{ base::{AccessResponseBase, ResponseBase}, @@ -24,65 +27,6 @@ use crate::defaults::{ default_zero, }; -//---------------------------------------------------------------------------------------------------- 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_2021 - // ^ - // 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: // @@ -119,23 +63,7 @@ define_request_and_response! { // instead of a `struct`, see below in other macro definitions for an example. // // If there are any additional attributes (`/// docs` or `#[derive]`s) - // for the struct, they go here, e.g.: - // - #[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(), - } - )] + // for the struct, they go here. Request { // Within the `{}` is an infinite matching pattern of: // ``` @@ -168,7 +96,7 @@ define_request_and_response! { // this field as another type in epee. // // See `cuprate_epee_encoding::epee_object` for info. - reserve_size: u64 /* as Type */, + reserve_size: u64 = default_zero::(), "default_zero" /* as Type */, wallet_address: String, }, @@ -185,23 +113,6 @@ 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: @@ -221,10 +132,10 @@ define_request_and_response! { difficulty: u64, expected_reward: u64, height: u64, - next_seed_hash: String, - prev_hash: String, + next_seed_hash: String = default_string(), "default_string", + prev_hash: Hex<32>, reserved_offset: u64, - seed_hash: String, + seed_hash: Hex<32>, seed_height: u64, wide_difficulty: String, } @@ -241,12 +152,6 @@ 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, } @@ -259,11 +164,6 @@ define_request_and_response! { OnGetBlockHash, - #[doc = serde_doc_test!( - ON_GET_BLOCK_HASH_REQUEST => OnGetBlockHashRequest { - block_height: [912345], - } - )] #[cfg_attr(feature = "serde", serde(transparent))] #[repr(transparent)] #[derive(Copy)] @@ -273,15 +173,10 @@ define_request_and_response! { block_height: [u64; 1], }, - #[doc = serde_doc_test!( - ON_GET_BLOCK_HASH_RESPONSE => OnGetBlockHashResponse { - block_hash: "e22cf75f39ae720e8b71b3d120a5ac03f0db50bba6379e2850975b4859190bc6".into(), - } - )] #[cfg_attr(feature = "serde", serde(transparent))] #[repr(transparent)] Response { - block_hash: String, + block_hash: Hex<32>, } } @@ -292,11 +187,6 @@ define_request_and_response! { SubmitBlock, - #[doc = serde_doc_test!( - SUBMIT_BLOCK_REQUEST => SubmitBlockRequest { - block_blob: ["0707e6bdfedc053771512f1bc27c62731ae9e8f2443db64ce742f4e57f5cf8d393de28551e441a0000000002fb830a01ffbf830a018cfe88bee283060274c0aae2ef5730e680308d9c00b6da59187ad0352efe3c71d36eeeb28782f29f2501bd56b952c3ddc3e350c2631d3a5086cac172c56893831228b17de296ff4669de020200000000".into()], - } - )] #[cfg_attr(feature = "serde", serde(transparent))] #[repr(transparent)] Request { @@ -318,14 +208,6 @@ define_request_and_response! { GenerateBlocks (restricted), - #[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 = default_string(), "default_string", @@ -333,13 +215,6 @@ define_request_and_response! { 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, @@ -358,35 +233,6 @@ define_request_and_response! { 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, } @@ -397,49 +243,13 @@ 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, + hash: Hex<32>, 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 = default_vec::(), "default_vec", @@ -454,46 +264,11 @@ define_request_and_response! { 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, } @@ -507,74 +282,12 @@ define_request_and_response! { 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, } @@ -586,13 +299,6 @@ define_request_and_response! { 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`. @@ -602,39 +308,6 @@ define_request_and_response! { 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, @@ -655,67 +328,6 @@ define_request_and_response! { Request {}, - #[doc = serde_doc_test!( - GET_CONNECTIONS_RESPONSE => GetConnectionsResponse { - base: ResponseBase::OK, - connections: vec![ - ConnectionInfo { - address: "3evk3kezfjg44ma6tvesy7rbxwwpgpympj45xar5fo4qajrsmkoaqdqd.onion:18083".into(), - address_type: cuprate_types::AddressType::Tor, - 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: cuprate_types::ConnectionState::Normal, - support_flags: 0 - }, - ConnectionInfo { - address: "4iykytmumafy5kjahdqc7uzgcs34s2vwsadfjpk4znvsa5vmcxeup2qd.onion:18083".into(), - address_type: cuprate_types::AddressType::Tor, - 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: cuprate_types::ConnectionState::Normal, - support_flags: 0 - } - ], - } - )] ResponseBase { // FIXME: This is a `std::list` in `monerod` because...? connections: Vec, @@ -729,50 +341,6 @@ define_request_and_response! { GetInfo (empty), 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, @@ -822,29 +390,11 @@ define_request_and_response! { core_rpc_server_commands_defs.h => 1958..=1995, HardForkInfo, - #[doc = serde_doc_test!( - HARD_FORK_INFO_REQUEST => HardForkInfoRequest { - version: 16, - } - )] #[derive(Copy)] Request { version: u8, }, - #[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, @@ -864,25 +414,10 @@ define_request_and_response! { SetBans (restricted), - #[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 {} } @@ -893,23 +428,6 @@ define_request_and_response! { GetBans (restricted, empty), 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, } @@ -922,22 +440,10 @@ define_request_and_response! { Banned (restricted), - #[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, @@ -952,20 +458,10 @@ define_request_and_response! { FlushTransactionPool (restricted), - #[doc = serde_doc_test!( - FLUSH_TRANSACTION_POOL_REQUEST => FlushTransactionPoolRequest { - txids: vec!["dc16fa8eaffe1484ca9014ea050e13131d3acf23b419f33bb4cc0b32b6c49308".into()], - } - )] Request { txids: Vec = default_vec::(), "default_vec", }, - #[doc = serde_doc_test!( - FLUSH_TRANSACTION_POOL_RESPONSE => FlushTransactionPoolResponse { - status: Status::Ok, - } - )] #[repr(transparent)] Response { status: Status, @@ -978,15 +474,6 @@ define_request_and_response! { 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 = default_zero::(), "default_zero", @@ -995,17 +482,6 @@ define_request_and_response! { 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, } @@ -1018,28 +494,11 @@ define_request_and_response! { GetCoinbaseTxSum (restricted), - #[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, @@ -1058,87 +517,12 @@ define_request_and_response! { GetVersion (empty), 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, current_height: u64 = default_zero::(), "default_zero", target_height: u64 = default_zero::(), "default_zero", - hard_forks: Vec = default_vec(), "default_vec", + hard_forks: Vec = default_vec(), "default_vec", } } @@ -1153,14 +537,6 @@ define_request_and_response! { grace_blocks: u64 = default_zero::(), "default_zero", }, - #[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, @@ -1175,33 +551,6 @@ define_request_and_response! { GetAlternateChains (restricted, empty), 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, } @@ -1214,20 +563,10 @@ define_request_and_response! { RelayTx (restricted), - #[doc = serde_doc_test!( - RELAY_TX_REQUEST => RelayTxRequest { - txids: vec!["9fd75c429cbe52da9a52f2ffc5fbd107fe7fd2099c0d8de274dc8a67e0c98613".into()] - } - )] Request { txids: Vec, }, - #[doc = serde_doc_test!( - RELAY_TX_RESPONSE => RelayTxResponse { - status: Status::Ok, - } - )] #[repr(transparent)] Response { status: Status, @@ -1243,76 +582,6 @@ define_request_and_response! { 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: cuprate_types::AddressType::Ipv4, - 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: cuprate_types::ConnectionState::Normal, - support_flags: 1 - } - }, - SyncInfoPeer { - info: ConnectionInfo { - address: "4iykytmumafy5kjahdqc7uzgcs34s2vwsadfjpk4znvsa5vmcxeup2qd.onion:18083".into(), - address_type: cuprate_types::AddressType::Tor, - 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: cuprate_types::ConnectionState::Normal, - support_flags: 0 - } - } - ], - target_height: 0, - } - )] AccessResponseBase { height: u64, next_needed_pruning_seed: u32, @@ -1332,13 +601,6 @@ define_request_and_response! { GetTransactionPoolBacklog (empty), 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, @@ -1355,16 +617,6 @@ define_request_and_response! { /// 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 = default_true(), "default_true", @@ -1374,19 +626,6 @@ define_request_and_response! { 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, } @@ -1399,30 +638,6 @@ define_request_and_response! { GetMinerData (empty), 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, @@ -1443,22 +658,10 @@ define_request_and_response! { PruneBlockchain (restricted), #[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, @@ -1472,14 +675,6 @@ define_request_and_response! { CalcPow (restricted), - #[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, @@ -1487,11 +682,6 @@ define_request_and_response! { seed_hash: String, }, - #[doc = serde_doc_test!( - CALC_POW_RESPONSE => CalcPowResponse { - pow_hash: "d0402d6834e26fb94a9ce38c6424d27d2069896a9b8b1ce685d79936bca6e0a8".into(), - } - )] #[cfg_attr(feature = "serde", serde(transparent))] #[repr(transparent)] Response { @@ -1507,22 +697,11 @@ define_request_and_response! { FlushCache (restricted), #[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 {} } @@ -1533,37 +712,15 @@ define_request_and_response! { 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, - merkle_root: String, + merkle_root: Hex<32>, merkle_tree_depth: u64, aux_pow: Vec, } @@ -1600,6 +757,7 @@ define_request_and_response! { serde(rename_all = "snake_case", tag = "method", content = "params") )] pub enum JsonRpcRequest { + GetBlockTemplate(GetBlockTemplateRequest), GetBlockCount(GetBlockCountRequest), OnGetBlockHash(OnGetBlockHashRequest), SubmitBlock(SubmitBlockRequest), @@ -1635,6 +793,7 @@ pub enum JsonRpcRequest { impl RpcCallValue for JsonRpcRequest { fn is_restricted(&self) -> bool { match self { + Self::GetBlockTemplate(x) => x.is_restricted(), Self::GetBlockCount(x) => x.is_restricted(), Self::OnGetBlockHash(x) => x.is_restricted(), Self::SubmitBlock(x) => x.is_restricted(), @@ -1670,6 +829,7 @@ impl RpcCallValue for JsonRpcRequest { fn is_empty(&self) -> bool { match self { + Self::GetBlockTemplate(x) => x.is_empty(), Self::GetBlockCount(x) => x.is_empty(), Self::OnGetBlockHash(x) => x.is_empty(), Self::SubmitBlock(x) => x.is_empty(), @@ -1732,6 +892,7 @@ impl RpcCallValue for JsonRpcRequest { #[cfg_attr(feature = "serde", derive(Deserialize, Serialize))] #[cfg_attr(feature = "serde", serde(untagged, rename_all = "snake_case"))] pub enum JsonRpcResponse { + GetBlockTemplate(GetBlockTemplateResponse), GetBlockCount(GetBlockCountResponse), OnGetBlockHash(OnGetBlockHashResponse), SubmitBlock(SubmitBlockResponse), @@ -1767,5 +928,1053 @@ pub enum JsonRpcResponse { //---------------------------------------------------------------------------------------------------- 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::json; + use cuprate_types::HardFork; + + use super::*; + + #[expect(clippy::needless_pass_by_value)] + fn test_json_request( + cuprate_test_utils_example_data: &str, + expected_type: T, + ) { + let value = from_str::(cuprate_test_utils_example_data).unwrap(); + let Value::Object(map) = value else { + unreachable!(); + }; + + let params = map.get("params").unwrap(); + let response = from_value::(params.clone()).unwrap(); + assert_eq!(response, expected_type); + } + + #[expect(clippy::needless_pass_by_value)] + fn test_json_response( + cuprate_test_utils_example_data: &str, + expected_type: T, + ) { + let value = from_str::(cuprate_test_utils_example_data).unwrap(); + let Value::Object(map) = value else { + unreachable!(); + }; + + let result = map.get("result").unwrap().clone(); + let response = from_value::(result).unwrap(); + assert_eq!(response, expected_type); + } + + #[test] + fn get_block_template_request() { + test_json_request(json::GET_BLOCK_TEMPLATE_REQUEST, GetBlockTemplateRequest { + reserve_size: 60, + extra_nonce: String::default(), + prev_block: String::default(), + wallet_address: "44GBHzv6ZyQdJkjqZje6KLZ3xSyN1hBSFAnLP6EAqJtCRVzMzZmeXTC2AHKDS9aEDTRKmo6a6o9r9j86pYfhCWDkKjbtcns".into(), + }); + } + + #[test] + fn get_block_template_response() { + test_json_response(json::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: String::new(), + prev_hash: Hex(hex!("9d648e741d85ca0e7acb4501f051b27e9b107d3cd7a3f03aa7f776089117c81a")), + reserved_offset: 131, + seed_hash: Hex(hex!("e2aa0b7b55042cd48b02e395d78fa66a29815ccc1584e38db2d1f0e8485cd44f")), + seed_height: 3194880, + wide_difficulty: "0x41f64bf3ff".into(), + }); + } + + #[test] + fn get_block_count_response() { + test_json_response( + json::GET_BLOCK_COUNT_RESPONSE, + GetBlockCountResponse { + base: ResponseBase::OK, + count: 3195019, + }, + ); + } + + #[test] + fn get_block_hash_request() { + test_json_request( + json::ON_GET_BLOCK_HASH_REQUEST, + OnGetBlockHashRequest { + block_height: [912345], + }, + ); + } + + #[test] + fn get_block_hash_response() { + test_json_response( + json::ON_GET_BLOCK_HASH_RESPONSE, + OnGetBlockHashResponse { + block_hash: Hex(hex!( + "e22cf75f39ae720e8b71b3d120a5ac03f0db50bba6379e2850975b4859190bc6" + )), + }, + ); + } + + #[test] + fn submit_block_request() { + test_json_request(json::SUBMIT_BLOCK_REQUEST, SubmitBlockRequest { + block_blob: ["0707e6bdfedc053771512f1bc27c62731ae9e8f2443db64ce742f4e57f5cf8d393de28551e441a0000000002fb830a01ffbf830a018cfe88bee283060274c0aae2ef5730e680308d9c00b6da59187ad0352efe3c71d36eeeb28782f29f2501bd56b952c3ddc3e350c2631d3a5086cac172c56893831228b17de296ff4669de020200000000".into()], + }); + } + + #[test] + fn generate_blocks_request() { + test_json_request(json::GENERATE_BLOCKS_REQUEST, GenerateBlocksRequest { + amount_of_blocks: 1, + prev_block: String::default(), + wallet_address: "44AFFq5kSiGBoZ4NMDwYtN18obc8AemS33DBLWs3H7otXft3XjrpDtQGv7SqSsaBYBb98uNbr2VBBEt7f2wfn3RVGQBEP3A".into(), + starting_nonce: 0 + }); + } + + #[test] + fn generate_blocks_response() { + test_json_response( + json::GENERATE_BLOCKS_RESPONSE, + GenerateBlocksResponse { + base: ResponseBase::OK, + blocks: vec![ + "49b712db7760e3728586f8434ee8bc8d7b3d410dac6bb6e98bf5845c83b917e4".into(), + ], + height: 9783, + }, + ); + } + + #[test] + fn get_last_block_header_response() { + test_json_response( + json::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: Hex(hex!( + "57238217820195ac4c08637a144a885491da167899cf1d20e8e7ce0ae0a3434e" + )), + height: 3195020, + long_term_weight: 200419, + major_version: HardFork::V16, + miner_tx_hash: Hex(hex!( + "7a42667237d4f79891bb407c49c712a9299fb87fce799833a7b633a3a9377dbd" + )), + minor_version: 16, + nonce: 1885649739, + num_txes: 37, + orphan_status: false, + pow_hash: String::new(), + prev_hash: Hex(hex!( + "22c72248ae9c5a2863c94735d710a3525c499f70707d1c2f395169bc5c8a0da3" + )), + reward: 615702960000, + timestamp: 1721245548, + wide_cumulative_difficulty: "0x514bd6a74a7d0a4".into(), + wide_difficulty: "0x41aba48bbe".into(), + }, + }, + ); + } + + #[test] + fn get_block_header_by_hash_request() { + test_json_request( + json::GET_BLOCK_HEADER_BY_HASH_REQUEST, + GetBlockHeaderByHashRequest { + hash: Hex(hex!( + "e22cf75f39ae720e8b71b3d120a5ac03f0db50bba6379e2850975b4859190bc6" + )), + hashes: vec![], + fill_pow_hash: false, + }, + ); + } + + #[test] + fn get_block_header_by_hash_response() { + test_json_response( + json::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: Hex(hex!( + "e22cf75f39ae720e8b71b3d120a5ac03f0db50bba6379e2850975b4859190bc6" + )), + height: 912345, + long_term_weight: 210, + major_version: HardFork::V1, + miner_tx_hash: Hex(hex!( + "c7da3965f25c19b8eb7dd8db48dcd4e7c885e2491db77e289f0609bf8e08ec30" + )), + minor_version: 2, + nonce: 1646, + num_txes: 0, + orphan_status: false, + pow_hash: String::new(), + prev_hash: Hex(hex!( + "b61c58b2e0be53fad5ef9d9731a55e8a81d972b8d90ed07c04fd37ca6403ff78" + )), + reward: 7388968946286, + timestamp: 1452793716, + wide_cumulative_difficulty: "0x2ae6d65248f1a".into(), + wide_difficulty: "0x309d758b".into(), + }, + }, + ); + } + + #[test] + fn block_header_by_height_request() { + test_json_request( + json::GET_BLOCK_HEADER_BY_HEIGHT_REQUEST, + GetBlockHeaderByHeightRequest { + height: 912345, + fill_pow_hash: false, + }, + ); + } + + #[test] + fn block_header_by_height_response() { + test_json_response( + json::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: Hex(hex!( + "e22cf75f39ae720e8b71b3d120a5ac03f0db50bba6379e2850975b4859190bc6" + )), + height: 912345, + long_term_weight: 210, + major_version: HardFork::V1, + miner_tx_hash: Hex(hex!( + "c7da3965f25c19b8eb7dd8db48dcd4e7c885e2491db77e289f0609bf8e08ec30" + )), + minor_version: 2, + nonce: 1646, + num_txes: 0, + orphan_status: false, + pow_hash: String::new(), + prev_hash: Hex(hex!( + "b61c58b2e0be53fad5ef9d9731a55e8a81d972b8d90ed07c04fd37ca6403ff78" + )), + reward: 7388968946286, + timestamp: 1452793716, + wide_cumulative_difficulty: "0x2ae6d65248f1a".into(), + wide_difficulty: "0x309d758b".into(), + }, + }, + ); + } + + #[test] + fn block_headers_range_request() { + test_json_request( + json::GET_BLOCK_HEADERS_RANGE_REQUEST, + GetBlockHeadersRangeRequest { + start_height: 1545999, + end_height: 1546000, + fill_pow_hash: false, + }, + ); + } + + #[test] + fn block_headers_range_response() { + test_json_response( + json::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: Hex(hex!( + "86d1d20a40cefcf3dd410ff6967e0491613b77bf73ea8f1bf2e335cf9cf7d57a" + )), + height: 1545999, + long_term_weight: 301413, + major_version: HardFork::V6, + miner_tx_hash: Hex(hex!( + "9909c6f8a5267f043c3b2b079fb4eacc49ef9c1dee1c028eeb1a259b95e6e1d9" + )), + minor_version: 6, + nonce: 3246403956, + num_txes: 20, + orphan_status: false, + pow_hash: String::new(), + prev_hash: Hex(hex!( + "0ef6e948f77b8f8806621003f5de24b1bcbea150bc0e376835aea099674a5db5" + )), + 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: Hex(hex!( + "b408bf4cfcd7de13e7e370c84b8314c85b24f0ba4093ca1d6eeb30b35e34e91a" + )), + height: 1546000, + long_term_weight: 13322, + major_version: HardFork::V7, + miner_tx_hash: Hex(hex!( + "7f749c7c64acb35ef427c7454c45e6688781fbead9bbf222cb12ad1a96a4e8f6" + )), + minor_version: 7, + nonce: 3737164176, + num_txes: 1, + orphan_status: false, + pow_hash: String::new(), + prev_hash: Hex(hex!( + "86d1d20a40cefcf3dd410ff6967e0491613b77bf73ea8f1bf2e335cf9cf7d57a" + )), + reward: 4851952181070, + timestamp: 1523002931, + wide_cumulative_difficulty: "0x2ed80dcb69bf2e".into(), + wide_difficulty: "0x1f5db457de".into(), + }, + ], + }, + ); + } + + #[test] + fn get_block_request() { + test_json_request( + json::GET_BLOCK_REQUEST, + GetBlockRequest { + height: 2751506, + hash: String::default(), + fill_pow_hash: false, + }, + ); + } + + #[test] + fn get_block_response() { + test_json_response(json::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: Hex(hex!("43bd1f2b6556dcafa413d8372974af59e4e8f37dbf74dc6b2a9b7212d0577428")), + height: 2751506, + long_term_weight: 176470, + major_version: HardFork::V16, + miner_tx_hash: Hex(hex!("e49b854c5f339d7410a77f2a137281d8042a0ffc7ef9ab24cd670b67139b24cd")), + minor_version: 16, + nonce: 4110909056, + num_txes: 0, + orphan_status: false, + pow_hash: String::new(), + prev_hash: Hex(hex!("b27bdecfc6cd0a46172d136c08831cf67660377ba992332363228b1b722781e7")), + 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![], + }); + } + + #[test] + fn get_connections_response() { + test_json_response( + json::GET_CONNECTIONS_RESPONSE, + GetConnectionsResponse { + base: ResponseBase::OK, + connections: vec![ + ConnectionInfo { + address: + "3evk3kezfjg44ma6tvesy7rbxwwpgpympj45xar5fo4qajrsmkoaqdqd.onion:18083" + .into(), + address_type: cuprate_types::AddressType::Tor, + 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: String::new(), + live_time: 76651, + local_ip: false, + localhost: false, + peer_id: "0000000000000001".into(), + port: String::new(), + 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: cuprate_types::ConnectionState::Normal, + support_flags: 0, + }, + ConnectionInfo { + address: + "4iykytmumafy5kjahdqc7uzgcs34s2vwsadfjpk4znvsa5vmcxeup2qd.onion:18083" + .into(), + address_type: cuprate_types::AddressType::Tor, + 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: String::new(), + live_time: 76755, + local_ip: false, + localhost: false, + peer_id: "0000000000000001".into(), + port: String::new(), + 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: cuprate_types::ConnectionState::Normal, + support_flags: 0, + }, + ], + }, + ); + } + + #[test] + fn get_info_response() { + test_json_response( + json::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: String::new(), + 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(), + }, + ); + } + + #[test] + fn hard_fork_info_request() { + test_json_request( + json::HARD_FORK_INFO_REQUEST, + HardForkInfoRequest { version: 16 }, + ); + } + + #[test] + fn hard_fork_info_response() { + test_json_response( + json::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, + }, + ); + } + + #[test] + fn set_bans_request() { + test_json_request( + json::SET_BANS_REQUEST, + SetBansRequest { + bans: vec![SetBan { + host: "192.168.1.51".into(), + ip: 0, + ban: true, + seconds: 30, + }], + }, + ); + } + + #[test] + fn set_bans_response() { + test_json_response( + json::SET_BANS_RESPONSE, + SetBansResponse { + base: ResponseBase::OK, + }, + ); + } + + #[test] + fn get_bans_response() { + test_json_response( + json::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, + }, + ], + }, + ); + } + + #[test] + fn banned_request() { + test_json_request( + json::BANNED_REQUEST, + BannedRequest { + address: "95.216.203.255".into(), + }, + ); + } + + #[test] + fn banned_response() { + test_json_response( + json::BANNED_RESPONSE, + BannedResponse { + banned: true, + seconds: 689655, + status: Status::Ok, + }, + ); + } + + #[test] + fn flush_transaction_pool_request() { + test_json_request( + json::FLUSH_TRANSACTION_POOL_REQUEST, + FlushTransactionPoolRequest { + txids: vec![ + "dc16fa8eaffe1484ca9014ea050e13131d3acf23b419f33bb4cc0b32b6c49308".into(), + ], + }, + ); + } + + #[test] + fn flush_transaction_pool_response() { + test_json_response( + json::FLUSH_TRANSACTION_POOL_RESPONSE, + FlushTransactionPoolResponse { status: Status::Ok }, + ); + } + + #[test] + fn get_output_histogram_request() { + test_json_request( + json::GET_OUTPUT_HISTOGRAM_REQUEST, + GetOutputHistogramRequest { + amounts: vec![20000000000], + min_count: 0, + max_count: 0, + unlocked: false, + recent_cutoff: 0, + }, + ); + } + + #[test] + fn get_output_histogram_response() { + test_json_response( + json::GET_OUTPUT_HISTOGRAM_RESPONSE, + GetOutputHistogramResponse { + base: AccessResponseBase::OK, + histogram: vec![HistogramEntry { + amount: 20000000000, + recent_instances: 0, + total_instances: 381490, + unlocked_instances: 0, + }], + }, + ); + } + + #[test] + fn get_coinbase_tx_sum_request() { + test_json_request( + json::GET_COINBASE_TX_SUM_REQUEST, + GetCoinbaseTxSumRequest { + height: 1563078, + count: 2, + }, + ); + } + + #[test] + fn get_coinbase_tx_sum_response() { + test_json_response( + json::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(), + }, + ); + } + + #[test] + fn get_version_response() { + test_json_response( + json::GET_VERSION_RESPONSE, + GetVersionResponse { + base: ResponseBase::OK, + current_height: 3195051, + hard_forks: [ + (1, HardFork::V1), + (1009827, HardFork::V2), + (1141317, HardFork::V3), + (1220516, HardFork::V4), + (1288616, HardFork::V5), + (1400000, HardFork::V6), + (1546000, HardFork::V7), + (1685555, HardFork::V8), + (1686275, HardFork::V9), + (1788000, HardFork::V10), + (1788720, HardFork::V11), + (1978433, HardFork::V12), + (2210000, HardFork::V13), + (2210720, HardFork::V14), + (2688888, HardFork::V15), + (2689608, HardFork::V16), + ] + .into_iter() + .map(|(height, hf_version)| HardForkEntry { height, hf_version }) + .collect(), + release: true, + version: 196621, + target_height: 0, + }, + ); + } + + #[test] + fn get_fee_estimate_response() { + test_json_response( + json::GET_FEE_ESTIMATE_RESPONSE, + GetFeeEstimateResponse { + base: AccessResponseBase::OK, + fee: 20000, + fees: vec![20000, 80000, 320000, 4000000], + quantization_mask: 10000, + }, + ); + } + + #[test] + fn get_alternate_chains_response() { + test_json_response( + json::GET_ALTERNATE_CHAINS_RESPONSE, + GetAlternateChainsResponse { + base: ResponseBase::OK, + chains: vec![ + ChainInfo { + block_hash: Hex(hex!( + "4826c7d45d7cf4f02985b5c405b0e5d7f92c8d25e015492ce19aa3b209295dce" + )), + block_hashes: vec![ + "4826c7d45d7cf4f02985b5c405b0e5d7f92c8d25e015492ce19aa3b209295dce" + .into(), + ], + difficulty: 357404825113208373, + difficulty_top64: 0, + height: 3167471, + length: 1, + main_chain_parent_block: Hex(hex!( + "69b5075ea627d6ba06b1c30b7e023884eeaef5282cf58ec847dab838ddbcdd86" + )), + wide_difficulty: "0x4f5c1cb79e22635".into(), + }, + ChainInfo { + block_hash: Hex(hex!( + "33ee476f5a1c5b9d889274cbbe171f5e0112df7ed69021918042525485deb401" + )), + block_hashes: vec![ + "33ee476f5a1c5b9d889274cbbe171f5e0112df7ed69021918042525485deb401" + .into(), + ], + difficulty: 354736121711617293, + difficulty_top64: 0, + height: 3157465, + length: 1, + main_chain_parent_block: Hex(hex!( + "fd522fcc4cefe5c8c0e5c5600981b3151772c285df3a4e38e5c4011cf466d2cb" + )), + wide_difficulty: "0x4ec469f8b9ee50d".into(), + }, + ], + }, + ); + } + + #[test] + fn relay_tx_request() { + test_json_request( + json::RELAY_TX_REQUEST, + RelayTxRequest { + txids: vec![ + "9fd75c429cbe52da9a52f2ffc5fbd107fe7fd2099c0d8de274dc8a67e0c98613".into(), + ], + }, + ); + } + + #[test] + fn relay_tx_response() { + test_json_response( + json::RELAY_TX_RESPONSE, + RelayTxResponse { status: Status::Ok }, + ); + } + + #[test] + fn sync_info_response() { + test_json_response(json::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: cuprate_types::AddressType::Ipv4, + 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: cuprate_types::ConnectionState::Normal, + support_flags: 1 + } + }, + SyncInfoPeer { + info: ConnectionInfo { + address: "4iykytmumafy5kjahdqc7uzgcs34s2vwsadfjpk4znvsa5vmcxeup2qd.onion:18083".into(), + address_type: cuprate_types::AddressType::Tor, + 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: String::new(), + live_time: 2246, + local_ip: false, + localhost: false, + peer_id: "0000000000000001".into(), + port: String::new(), + 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: cuprate_types::ConnectionState::Normal, + support_flags: 0 + } + } + ], + target_height: 0, + }); + } + + // TODO: enable test after binary string imp} + // #[test] + // fn asdf() { + // test_json_response(json::GET_TRANSACTION_POOL_BACKLOG_RESPONSE => GetTransactionPoolBacklogResponse { + // base: ResponseBase::OK, + // backlog: "...Binary...".into(), + // }); + // } + + #[test] + fn get_output_distribution_request() { + test_json_request( + json::GET_OUTPUT_DISTRIBUTION_REQUEST, + GetOutputDistributionRequest { + amounts: vec![628780000], + from_height: 1462078, + binary: true, + compress: false, + cumulative: false, + to_height: 0, + }, + ); + } + + // TODO: enable test after binary string imp} + // #[test] + // fn get_output_distribution_response() { + // test_json_response(json::GET_OUTPUT_DISTRIBUTION_RESPONSE => GetOutputDistributionResponse { + // base: AccessResponseBase::OK, + // distributions: vec![Distribution::Uncompressed(DistributionUncompressed { + // start_height: 1462078, + // base: 0, + // distribution: vec![], + // amount: 2628780000, + // binary: true, + // })], + // }); + // } + + #[test] + fn get_miner_data_response() { + test_json_response( + json::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, + }, + ], + }, + ); + } + + #[test] + fn prune_blockchain_request() { + test_json_request( + json::PRUNE_BLOCKCHAIN_REQUEST, + PruneBlockchainRequest { check: true }, + ); + } + + #[test] + fn prune_blockchain_response() { + test_json_response( + json::PRUNE_BLOCKCHAIN_RESPONSE, + PruneBlockchainResponse { + base: ResponseBase::OK, + pruned: true, + pruning_seed: 387, + }, + ); + } + + #[test] + fn calc_pow_request() { + test_json_request(json::CALC_POW_REQUEST, CalcPowRequest { + major_version: 14, + height: 2286447, + block_blob: "0e0ed286da8006ecdc1aab3033cf1716c52f13f9d8ae0051615a2453643de94643b550d543becd0000000002abc78b0101ffefc68b0101fcfcf0d4b422025014bb4a1eade6622fd781cb1063381cad396efa69719b41aa28b4fce8c7ad4b5f019ce1dc670456b24a5e03c2d9058a2df10fec779e2579753b1847b74ee644f16b023c00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000051399a1bc46a846474f5b33db24eae173a26393b976054ee14f9feefe99925233802867097564c9db7a36af5bb5ed33ab46e63092bd8d32cef121608c3258edd55562812e21cc7e3ac73045745a72f7d74581d9a0849d6f30e8b2923171253e864f4e9ddea3acb5bc755f1c4a878130a70c26297540bc0b7a57affb6b35c1f03d8dbd54ece8457531f8cba15bb74516779c01193e212050423020e45aa2c15dcb".into(), + seed_hash: "d432f499205150873b2572b5f033c9c6e4b7c6f3394bd2dd93822cd7085e7307".into(), + }); + } + + #[test] + fn calc_pow_response() { + test_json_response( + json::CALC_POW_RESPONSE, + CalcPowResponse { + pow_hash: "d0402d6834e26fb94a9ce38c6424d27d2069896a9b8b1ce685d79936bca6e0a8".into(), + }, + ); + } + + #[test] + fn flush_cache_request() { + test_json_request( + json::FLUSH_CACHE_REQUEST, + FlushCacheRequest { + bad_txs: true, + bad_blocks: true, + }, + ); + } + + #[test] + fn flush_cache_response() { + test_json_response( + json::FLUSH_CACHE_RESPONSE, + FlushCacheResponse { + base: ResponseBase::OK, + }, + ); + } + + #[test] + fn add_aux_pow_request() { + test_json_request(json::ADD_AUX_POW_REQUEST, AddAuxPowRequest { + blocktemplate_blob: "1010f4bae0b4069d648e741d85ca0e7acb4501f051b27e9b107d3cd7a3f03aa7f776089117c81a0000000002c681c30101ff8a81c3010180e0a596bb11033b7eedf47baf878f3490cb20b696079c34bd017fe59b0d070e74d73ffabc4bb0e05f011decb630f3148d0163b3bd39690dde4078e4cfb69fecf020d6278a27bad10c58023c0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000".into(), + aux_pow: vec![AuxPow { + id: Hex(hex!("3200b4ea97c3b2081cd4190b58e49572b2319fed00d030ad51809dff06b5d8c8")), + hash: Hex(hex!("7b35762de164b20885e15dbe656b1138db06bb402fa1796f5765a23933d8859a")) + }] + }); + } + + #[test] + fn add_aux_pow_response() { + test_json_response(json::ADD_AUX_POW_RESPONSE, AddAuxPowResponse { + base: ResponseBase::OK, + aux_pow: vec![AuxPow { + hash: Hex(hex!("7b35762de164b20885e15dbe656b1138db06bb402fa1796f5765a23933d8859a")), + id: Hex(hex!("3200b4ea97c3b2081cd4190b58e49572b2319fed00d030ad51809dff06b5d8c8")), + }], + blockhashing_blob: "1010ee97e2a106e9f8ebe8887e5b609949ac8ea6143e560ed13552b110cb009b21f0cfca1eaccf00000000b2685c1283a646bc9020c758daa443be145b7370ce5a6efacb3e614117032e2c22".into(), + blocktemplate_blob: "1010f4bae0b4069d648e741d85ca0e7acb4501f051b27e9b107d3cd7a3f03aa7f776089117c81a0000000002c681c30101ff8a81c3010180e0a596bb11033b7eedf47baf878f3490cb20b696079c34bd017fe59b0d070e74d73ffabc4bb0e05f011decb630f3148d0163b3bd39690dde4078e4cfb69fecf020d6278a27bad10c58023c0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000".into(), + merkle_root: Hex(hex!("7b35762de164b20885e15dbe656b1138db06bb402fa1796f5765a23933d8859a")), + merkle_tree_depth: 0, + }); + } } diff --git a/types/Cargo.toml b/types/Cargo.toml index f58524d..51bb238 100644 --- a/types/Cargo.toml +++ b/types/Cargo.toml @@ -18,7 +18,7 @@ json = ["hex", "dep:cuprate-helper"] # We sadly have no choice but to enable serde here as otherwise we will get warnings from the `hex` dep being unused. # This isn't too bad as `Hex` only makes sense with serde anyway. hex = ["serde", "dep:hex"] -rpc = ["hex"] +rpc = ["hex", "json"] [dependencies] cuprate-epee-encoding = { workspace = true, optional = true, features = ["std"] } diff --git a/types/src/hard_fork.rs b/types/src/hard_fork.rs index 95ffec1..07770e6 100644 --- a/types/src/hard_fork.rs +++ b/types/src/hard_fork.rs @@ -59,6 +59,7 @@ pub enum HardForkError { )] #[cfg_attr(any(feature = "proptest"), derive(proptest_derive::Arbitrary))] #[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] +#[cfg_attr(feature = "serde", serde(try_from = "u8", into = "u8"))] #[repr(u8)] pub enum HardFork { #[default] @@ -203,6 +204,19 @@ impl HardFork { } } +impl TryFrom for HardFork { + type Error = HardForkError; + fn try_from(version: u8) -> Result { + Self::from_version(version) + } +} + +impl From for u8 { + fn from(value: HardFork) -> Self { + value.as_u8() + } +} + #[cfg(feature = "epee")] impl EpeeValue for HardFork { const MARKER: Marker = u8::MARKER; diff --git a/types/src/hex.rs b/types/src/hex.rs index 801d818..3dd451f 100644 --- a/types/src/hex.rs +++ b/types/src/hex.rs @@ -56,6 +56,37 @@ impl Default for Hex { } } +impl From> for [u8; N] { + fn from(hex: Hex) -> Self { + hex.0 + } +} + +impl From<[u8; N]> for Hex { + fn from(value: [u8; N]) -> Self { + Self(value) + } +} + +impl TryFrom for Hex { + type Error = hex::FromHexError; + fn try_from(value: String) -> Result { + let vec = hex::decode(value)?; + match <[u8; N]>::try_from(vec) { + Ok(s) => Ok(Self(s)), + Err(_) => Err(hex::FromHexError::InvalidStringLength), + } + } +} + +impl TryFrom<&str> for Hex { + type Error = hex::FromHexError; + fn try_from(value: &str) -> Result { + let mut bytes = [0; N]; + hex::decode_to_slice(value, &mut bytes).map(|()| Self(bytes)) + } +} + #[cfg(test)] mod test { use super::*; diff --git a/types/src/rpc/mod.rs b/types/src/rpc/mod.rs index 74f31b8..490885d 100644 --- a/types/src/rpc/mod.rs +++ b/types/src/rpc/mod.rs @@ -16,7 +16,7 @@ pub use pool_info::PoolInfo; pub use pool_info_extent::PoolInfoExtent; pub use types::{ AddAuxPow, AuxPow, BlockHeader, BlockOutputIndices, ChainInfo, CoinbaseTxSum, ConnectionInfo, - FeeEstimate, GetBan, GetMinerDataTxBacklogEntry, GetOutputsOut, HardForkInfo, HardforkEntry, + FeeEstimate, GetBan, GetMinerDataTxBacklogEntry, GetOutputsOut, HardForkEntry, HardForkInfo, HistogramEntry, MinerData, MinerDataTxBacklogEntry, OutKey, OutKeyBin, OutputDistributionData, OutputHistogramEntry, OutputHistogramInput, Peer, PoolInfoFull, PoolInfoIncremental, PoolTxInfo, PublicNode, SetBan, Span, SpentKeyImageInfo, SyncInfoPeer, TxBacklogEntry, TxInfo, diff --git a/types/src/rpc/types.rs b/types/src/rpc/types.rs index 2939b35..02bba39 100644 --- a/types/src/rpc/types.rs +++ b/types/src/rpc/types.rs @@ -190,7 +190,7 @@ define_struct_and_impl_epee! { 2180..=2191 )] #[derive(Copy)] - HardforkEntry { + HardForkEntry { height: u64, hf_version: HardFork, }