GET_BLOCK_HEADER_BY_HASH

This commit is contained in:
Sean Darcy 2021-11-05 15:21:38 +11:00
parent 445fab4ac5
commit d476f216cc
7 changed files with 52 additions and 58 deletions

View file

@ -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<GET_BLOCK_HEADER_BY_HASH>(std::move(bhreq), bhres, "Failed to query block header by hash"))
return false;
if (bhres.block_headers.size() != chain.length + 1)
std::vector<std::string> hashes{chain.block_hashes};
hashes.push_back(chain.main_chain_parent_block);
auto maybe_headers = try_running([&] { return invoke<GET_BLOCK_HEADER_BY_HASH>(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<uint64_t>(t0, block_header.timestamp);
t1 = std::max<uint64_t>(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

View file

@ -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<GET_BLOCK_HEADER_BY_HASH>(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<txin_gen>(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<txin_gen>(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_header_response> 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)

View file

@ -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);

View file

@ -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);
}
}

View file

@ -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);
}

View file

@ -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)

View file

@ -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<std::string> 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_response> block_header; // Block header information for the requested `hash` block
std::vector<block_header_response> 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