From d476f216cc762362a3186b584522c4f1e3b35402 Mon Sep 17 00:00:00 2001 From: Sean Darcy Date: Fri, 5 Nov 2021 15:21:38 +1100 Subject: [PATCH] GET_BLOCK_HEADER_BY_HASH --- src/daemon/rpc_command_executor.cpp | 24 ++++++++--------- src/rpc/core_rpc_server.cpp | 28 ++++++++++---------- src/rpc/core_rpc_server.h | 2 +- src/rpc/core_rpc_server_command_parser.cpp | 7 +++++ src/rpc/core_rpc_server_command_parser.h | 3 ++- src/rpc/core_rpc_server_commands_defs.cpp | 16 ------------ src/rpc/core_rpc_server_commands_defs.h | 30 +++++++++++----------- 7 files changed, 52 insertions(+), 58 deletions(-) diff --git a/src/daemon/rpc_command_executor.cpp b/src/daemon/rpc_command_executor.cpp index d8839d9e8..effec5732 100644 --- a/src/daemon/rpc_command_executor.cpp +++ b/src/daemon/rpc_command_executor.cpp @@ -1316,21 +1316,21 @@ bool rpc_command_executor::alt_chain_info(const std::string &tip, size_t above, for (const std::string &block_id: chain.block_hashes) tools::msg_writer() << " " << block_id; tools::msg_writer() << "Chain parent on main chain: " << chain.main_chain_parent_block; - GET_BLOCK_HEADER_BY_HASH::request bhreq{}; - GET_BLOCK_HEADER_BY_HASH::response bhres{}; - bhreq.hashes = chain.block_hashes; - bhreq.hashes.push_back(chain.main_chain_parent_block); - bhreq.fill_pow_hash = false; - if (!invoke(std::move(bhreq), bhres, "Failed to query block header by hash")) - return false; - if (bhres.block_headers.size() != chain.length + 1) + std::vector hashes{chain.block_hashes}; + hashes.push_back(chain.main_chain_parent_block); + auto maybe_headers = try_running([&] { return invoke(json{{"hashes", hashes}, {"fill_pow_hash", false}}); }, "Failed to query block header by hash"); + if (!maybe_headers) + return false; + auto headers = *maybe_headers; + + if (headers["block_headers"].size() != chain.length + 1) { tools::fail_msg_writer() << "Failed to get block header info for alt chain"; return true; } - uint64_t t0 = bhres.block_headers.front().timestamp, t1 = t0; - for (const block_header_response &block_header: bhres.block_headers) + uint64_t t0 = headers["block_headers"].front()["timestamp"], t1 = t0; + for (const block_header_response &block_header: headers["block_headers"]) { t0 = std::min(t0, block_header.timestamp); t1 = std::max(t1, block_header.timestamp); @@ -1341,11 +1341,11 @@ bool rpc_command_executor::alt_chain_info(const std::string &tip, size_t above, if (chain.length > 1) { tools::msg_writer() << "Time span: " << tools::get_human_readable_timespan(std::chrono::seconds(dt)); - cryptonote::difficulty_type start_difficulty = bhres.block_headers.back().difficulty; + cryptonote::difficulty_type start_difficulty = headers["block_headers"].back()["difficulty"]; if (start_difficulty > 0) tools::msg_writer() << "Approximated " << 100.f * tools::to_seconds(TARGET_BLOCK_TIME) * chain.length / dt << "% of network hash rate"; else - tools::fail_msg_writer() << "Bad cmumulative difficulty reported by dameon"; + tools::fail_msg_writer() << "Bad cumulative difficulty reported by dameon"; } } else diff --git a/src/rpc/core_rpc_server.cpp b/src/rpc/core_rpc_server.cpp index 2525f1a12..92e704fa6 100644 --- a/src/rpc/core_rpc_server.cpp +++ b/src/rpc/core_rpc_server.cpp @@ -1695,15 +1695,12 @@ namespace cryptonote::rpc { } //------------------------------------------------------------------------------------------------------------------------------ - GET_BLOCK_HEADER_BY_HASH::response core_rpc_server::invoke(GET_BLOCK_HEADER_BY_HASH::request&& req, rpc_context context) + void core_rpc_server::invoke(GET_BLOCK_HEADER_BY_HASH& get_block_header_by_hash, rpc_context context) { - GET_BLOCK_HEADER_BY_HASH::response res{}; PERF_TIMER(on_get_block_header_by_hash); - if (use_bootstrap_daemon_if_necessary(req, res)) - return res; - auto get = [this, &req, admin=context.admin](const std::string &hash, block_header_response &block_header) { + auto get = [this, &get_block_header_by_hash, admin=context.admin](const std::string &hash, block_header_response &block_header) { crypto::hash block_hash; if (!tools::hex_to_type(hash, block_hash)) throw rpc_error{ERROR_WRONG_PARAM, "Failed to parse hex representation of block hash. Hex = " + hash + '.'}; @@ -1715,18 +1712,23 @@ namespace cryptonote::rpc { if (blk.miner_tx.vin.size() != 1 || !std::holds_alternative(blk.miner_tx.vin.front())) throw rpc_error{ERROR_INTERNAL, "Internal error: coinbase transaction in the block has the wrong type"}; uint64_t block_height = var::get(blk.miner_tx.vin.front()).height; - fill_block_header_response(blk, orphan, block_height, block_hash, block_header, req.fill_pow_hash && admin, req.get_tx_hashes); + fill_block_header_response(blk, orphan, block_height, block_hash, block_header, get_block_header_by_hash.request.fill_pow_hash && admin, get_block_header_by_hash.request.get_tx_hashes); }; - if (!req.hash.empty()) - get(req.hash, res.block_header.emplace()); + if (!get_block_header_by_hash.request.hash.empty()) + { + block_header_response block_header; + get(get_block_header_by_hash.request.hash, block_header); + get_block_header_by_hash.response["block_header"] = block_header; + } - res.block_headers.reserve(req.hashes.size()); - for (const std::string &hash: req.hashes) - get(hash, res.block_headers.emplace_back()); + std::vector block_headers; + for (const std::string &hash: get_block_header_by_hash.request.hashes) + get(hash, block_headers.emplace_back()); - res.status = STATUS_OK; - return res; + get_block_header_by_hash.response["block_headers"] = block_headers; + get_block_header_by_hash.response["status"] = STATUS_OK; + return; } //------------------------------------------------------------------------------------------------------------------------------ GET_BLOCK_HEADERS_RANGE::response core_rpc_server::invoke(GET_BLOCK_HEADERS_RANGE::request&& req, rpc_context context) diff --git a/src/rpc/core_rpc_server.h b/src/rpc/core_rpc_server.h index d79876a9e..cfef7015a 100644 --- a/src/rpc/core_rpc_server.h +++ b/src/rpc/core_rpc_server.h @@ -245,6 +245,7 @@ namespace cryptonote::rpc { void invoke(REPORT_PEER_STATUS& report_peer_status, rpc_context context); void invoke(FLUSH_CACHE& flush_cache, rpc_context context); void invoke(GET_LAST_BLOCK_HEADER& get_last_block_header, rpc_context context); + void invoke(GET_BLOCK_HEADER_BY_HASH& get_block_header_by_hash, rpc_context context); // Deprecated Monero NIH binary endpoints: GET_ALT_BLOCKS_HASHES_BIN::response invoke(GET_ALT_BLOCKS_HASHES_BIN::request&& req, rpc_context context); @@ -260,7 +261,6 @@ namespace cryptonote::rpc { // FIXME: unconverted JSON RPC endpoints: SET_BOOTSTRAP_DAEMON::response invoke(SET_BOOTSTRAP_DAEMON::request&& req, rpc_context context); GET_OUTPUT_DISTRIBUTION::response invoke(GET_OUTPUT_DISTRIBUTION::request&& req, rpc_context context, bool binary = false); - GET_BLOCK_HEADER_BY_HASH::response invoke(GET_BLOCK_HEADER_BY_HASH::request&& req, rpc_context context); GET_BLOCK_HEADER_BY_HEIGHT::response invoke(GET_BLOCK_HEADER_BY_HEIGHT::request&& req, rpc_context context); GET_BLOCK_HEADERS_RANGE::response invoke(GET_BLOCK_HEADERS_RANGE::request&& req, rpc_context context); GET_BLOCK::response invoke(GET_BLOCK::request&& req, rpc_context context); diff --git a/src/rpc/core_rpc_server_command_parser.cpp b/src/rpc/core_rpc_server_command_parser.cpp index 705d1c4fc..2b4a0a7e6 100644 --- a/src/rpc/core_rpc_server_command_parser.cpp +++ b/src/rpc/core_rpc_server_command_parser.cpp @@ -471,4 +471,11 @@ namespace cryptonote::rpc { get_values(in, "fill_pow_hash", get_last_block_header.request.fill_pow_hash); get_values(in, "get_tx_hashes", get_last_block_header.request.get_tx_hashes); } + + void parse_request(GET_BLOCK_HEADER_BY_HASH& get_block_header_by_hash, rpc_input in) { + get_values(in, "hash", get_block_header_by_hash.request.hash); + get_values(in, "hashes", get_block_header_by_hash.request.hashes); + get_values(in, "fill_pow_hash", get_block_header_by_hash.request.fill_pow_hash); + get_values(in, "get_tx_hashes", get_block_header_by_hash.request.get_tx_hashes); + } } diff --git a/src/rpc/core_rpc_server_command_parser.h b/src/rpc/core_rpc_server_command_parser.h index 0d2774a21..cb1ddbdfe 100644 --- a/src/rpc/core_rpc_server_command_parser.h +++ b/src/rpc/core_rpc_server_command_parser.h @@ -37,5 +37,6 @@ namespace cryptonote::rpc { void parse_request(GET_SN_STATE_CHANGES& get_sn_state_changes, rpc_input in); void parse_request(REPORT_PEER_STATUS& report_peer_status, rpc_input in); void parse_request(FLUSH_CACHE& flush_cache, rpc_input in); - void parse_request(GET_LAST_BLOCK_HEADER& get_lash_block_header, rpc_input in); + void parse_request(GET_LAST_BLOCK_HEADER& get_last_block_header, rpc_input in); + void parse_request(GET_BLOCK_HEADER_BY_HASH& get_block_header_by_hash, rpc_input in); } diff --git a/src/rpc/core_rpc_server_commands_defs.cpp b/src/rpc/core_rpc_server_commands_defs.cpp index f81d97e2d..d3b9805e5 100644 --- a/src/rpc/core_rpc_server_commands_defs.cpp +++ b/src/rpc/core_rpc_server_commands_defs.cpp @@ -102,22 +102,6 @@ KV_SERIALIZE_MAP_CODE_BEGIN(block_header_response) KV_SERIALIZE_MAP_CODE_END() -KV_SERIALIZE_MAP_CODE_BEGIN(GET_BLOCK_HEADER_BY_HASH::request) - KV_SERIALIZE(hash) - KV_SERIALIZE(hashes) - KV_SERIALIZE_OPT(fill_pow_hash, false); - KV_SERIALIZE_OPT(get_tx_hashes, false); -KV_SERIALIZE_MAP_CODE_END() - - -KV_SERIALIZE_MAP_CODE_BEGIN(GET_BLOCK_HEADER_BY_HASH::response) - KV_SERIALIZE(block_header) - KV_SERIALIZE(block_headers) - KV_SERIALIZE(status) - KV_SERIALIZE(untrusted) -KV_SERIALIZE_MAP_CODE_END() - - KV_SERIALIZE_MAP_CODE_BEGIN(GET_BLOCK_HEADER_BY_HEIGHT::request) KV_SERIALIZE(height) KV_SERIALIZE(heights) diff --git a/src/rpc/core_rpc_server_commands_defs.h b/src/rpc/core_rpc_server_commands_defs.h index 5e850051b..a2af136d7 100644 --- a/src/rpc/core_rpc_server_commands_defs.h +++ b/src/rpc/core_rpc_server_commands_defs.h @@ -793,30 +793,30 @@ namespace cryptonote::rpc { }; OXEN_RPC_DOC_INTROSPECT - // Block header information can be retrieved using either a block's hash or height. This method includes a block's hash as an input parameter to retrieve basic information about the block. + /// Block header information can be retrieved using either a block's hash or height. This method includes a block's hash as an input parameter to retrieve basic information about the block. + /// + /// Inputs: + /// - \p hash The block's SHA256 hash. + /// - \p hashes Request multiple blocks via an array of hashes + /// - \p fill_pow_hash Tell the daemon if it should fill out pow_hash field. + /// - \p get_tx_hashes If true (default false) then include the hashes of non-coinbase transactions + /// + /// Output values available from a public RPC endpoint: + /// + /// - \p status General RPC status string. `"OK"` means everything looks good. + /// - \p block_header Block header information for the requested `hash` block + /// - \p block_headers Block header information for the requested `hashes` blocks struct GET_BLOCK_HEADER_BY_HASH : PUBLIC { static constexpr auto names() { return NAMES("get_block_header_by_hash", "getblockheaderbyhash"); } - struct request + struct request_parameters { std::string hash; // The block's SHA256 hash. std::vector hashes; // Request multiple blocks via an array of hashes bool fill_pow_hash; // Tell the daemon if it should fill out pow_hash field. bool get_tx_hashes; // If true (default false) then include the hashes of non-coinbase transactions - - KV_MAP_SERIALIZABLE - }; - - struct response - { - std::string status; // General RPC error code. "OK" means everything looks good. - std::optional block_header; // Block header information for the requested `hash` block - std::vector block_headers; // Block header information for the requested `hashes` blocks - bool untrusted; // States if the result is obtained using the bootstrap mode, and is therefore not trusted (`true`), or when the daemon is fully synced (`false`). - - KV_MAP_SERIALIZABLE - }; + } request; }; OXEN_RPC_DOC_INTROSPECT