|
|
|
@ -1593,38 +1593,55 @@ namespace cryptonote
|
|
|
|
|
if (use_bootstrap_daemon_if_necessary<COMMAND_RPC_GET_BLOCK_HEADER_BY_HASH>(invoke_http_mode::JON_RPC, "getblockheaderbyhash", req, res, r))
|
|
|
|
|
return r;
|
|
|
|
|
|
|
|
|
|
crypto::hash block_hash;
|
|
|
|
|
bool hash_parsed = parse_hash256(req.hash, block_hash);
|
|
|
|
|
if(!hash_parsed)
|
|
|
|
|
{
|
|
|
|
|
error_resp.code = CORE_RPC_ERROR_CODE_WRONG_PARAM;
|
|
|
|
|
error_resp.message = "Failed to parse hex representation of block hash. Hex = " + req.hash + '.';
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
block blk;
|
|
|
|
|
bool orphan = false;
|
|
|
|
|
bool have_block = m_core.get_block_by_hash(block_hash, blk, &orphan);
|
|
|
|
|
if (!have_block)
|
|
|
|
|
{
|
|
|
|
|
error_resp.code = CORE_RPC_ERROR_CODE_INTERNAL_ERROR;
|
|
|
|
|
error_resp.message = "Internal error: can't get block by hash. Hash = " + req.hash + '.';
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
if (blk.miner_tx.vin.size() != 1 || blk.miner_tx.vin.front().type() != typeid(txin_gen))
|
|
|
|
|
auto get = [this](const std::string &hash, bool fill_pow_hash, block_header_response &block_header, bool restricted, epee::json_rpc::error& error_resp) -> bool {
|
|
|
|
|
crypto::hash block_hash;
|
|
|
|
|
bool hash_parsed = parse_hash256(hash, block_hash);
|
|
|
|
|
if(!hash_parsed)
|
|
|
|
|
{
|
|
|
|
|
error_resp.code = CORE_RPC_ERROR_CODE_WRONG_PARAM;
|
|
|
|
|
error_resp.message = "Failed to parse hex representation of block hash. Hex = " + hash + '.';
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
block blk;
|
|
|
|
|
bool orphan = false;
|
|
|
|
|
bool have_block = m_core.get_block_by_hash(block_hash, blk, &orphan);
|
|
|
|
|
if (!have_block)
|
|
|
|
|
{
|
|
|
|
|
error_resp.code = CORE_RPC_ERROR_CODE_INTERNAL_ERROR;
|
|
|
|
|
error_resp.message = "Internal error: can't get block by hash. Hash = " + hash + '.';
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
if (blk.miner_tx.vin.size() != 1 || blk.miner_tx.vin.front().type() != typeid(txin_gen))
|
|
|
|
|
{
|
|
|
|
|
error_resp.code = CORE_RPC_ERROR_CODE_INTERNAL_ERROR;
|
|
|
|
|
error_resp.message = "Internal error: coinbase transaction in the block has the wrong type";
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
uint64_t block_height = boost::get<txin_gen>(blk.miner_tx.vin.front()).height;
|
|
|
|
|
bool response_filled = fill_block_header_response(blk, orphan, block_height, block_hash, block_header, fill_pow_hash && !restricted);
|
|
|
|
|
if (!response_filled)
|
|
|
|
|
{
|
|
|
|
|
error_resp.code = CORE_RPC_ERROR_CODE_INTERNAL_ERROR;
|
|
|
|
|
error_resp.message = "Internal error: can't produce valid response.";
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
return true;
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
const bool restricted = m_restricted && ctx;
|
|
|
|
|
if (!req.hash.empty())
|
|
|
|
|
{
|
|
|
|
|
error_resp.code = CORE_RPC_ERROR_CODE_INTERNAL_ERROR;
|
|
|
|
|
error_resp.message = "Internal error: coinbase transaction in the block has the wrong type";
|
|
|
|
|
return false;
|
|
|
|
|
if (!get(req.hash, req.fill_pow_hash, res.block_header, restricted, error_resp))
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
uint64_t block_height = boost::get<txin_gen>(blk.miner_tx.vin.front()).height;
|
|
|
|
|
const bool restricted = m_restricted && ctx;
|
|
|
|
|
bool response_filled = fill_block_header_response(blk, orphan, block_height, block_hash, res.block_header, req.fill_pow_hash && !restricted);
|
|
|
|
|
if (!response_filled)
|
|
|
|
|
res.block_headers.reserve(req.hashes.size());
|
|
|
|
|
for (const std::string &hash: req.hashes)
|
|
|
|
|
{
|
|
|
|
|
error_resp.code = CORE_RPC_ERROR_CODE_INTERNAL_ERROR;
|
|
|
|
|
error_resp.message = "Internal error: can't produce valid response.";
|
|
|
|
|
return false;
|
|
|
|
|
res.block_headers.push_back({});
|
|
|
|
|
if (!get(hash, req.fill_pow_hash, res.block_headers.back(), restricted, error_resp))
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
res.status = CORE_RPC_STATUS_OK;
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|