From d9157034a6783fd333c5be7f3abf2d77299d406e Mon Sep 17 00:00:00 2001 From: Aiwe Date: Mon, 4 Jul 2022 17:26:51 +0300 Subject: [PATCH] Implement simple block info by hash --- src/Rpc/CoreRpcServerCommandsDefinitions.h | 12 ++ src/Rpc/RpcServer.cpp | 127 +++++++++++++++++++++ src/Rpc/RpcServer.h | 1 + 3 files changed, 140 insertions(+) diff --git a/src/Rpc/CoreRpcServerCommandsDefinitions.h b/src/Rpc/CoreRpcServerCommandsDefinitions.h index fbfe487c24..2c95c6481b 100755 --- a/src/Rpc/CoreRpcServerCommandsDefinitions.h +++ b/src/Rpc/CoreRpcServerCommandsDefinitions.h @@ -321,6 +321,18 @@ struct COMMAND_EXPLORER { typedef std::string response; }; +struct COMMAND_EXPLORER_GET_BLOCK_DETAILS_BY_HASH { + struct request { + std::string hash; + + void serialize(ISerializer& s) { + KV_MEMBER(hash) + } + }; + + typedef std::string response; +}; + //----------------------------------------------- struct COMMAND_RPC_GET_INFO { typedef EMPTY_STRUCT request; diff --git a/src/Rpc/RpcServer.cpp b/src/Rpc/RpcServer.cpp index 18d95c7dad..9b1ba59521 100755 --- a/src/Rpc/RpcServer.cpp +++ b/src/Rpc/RpcServer.cpp @@ -468,6 +468,26 @@ void RpcServer::processRequest(const httplib::Request& request, httplib::Respons std::string tx_method = "/explorer/tx/"; if (Common::starts_with(url, block_method)) { + std::string hash_str = url.substr(block_method.size()); + if (hash_str.size() < 64) { // assume it's height + //on_get_explorer_block_by_height + + } + else { + COMMAND_EXPLORER_GET_BLOCK_DETAILS_BY_HASH::request req; + req.hash = hash_str; + COMMAND_EXPLORER_GET_BLOCK_DETAILS_BY_HASH::response rsp; + bool r = on_get_explorer_block_by_hash(req, rsp); + if (r) { + response.status = 200; + response.set_content(rsp, "text/html"); + } + else { + response.status = 500; + response.set_content("Internal error", "text/html"); + } + return; + } return; } @@ -1552,11 +1572,118 @@ bool RpcServer::on_get_explorer(const COMMAND_EXPLORER::request& req, COMMAND_EX body += std::to_string(next_page); body += "\">next page

"; + body += index_finish; + res = body; return true; } +bool RpcServer::on_get_explorer_block_by_hash(const COMMAND_EXPLORER_GET_BLOCK_DETAILS_BY_HASH::request& req, COMMAND_EXPLORER_GET_BLOCK_DETAILS_BY_HASH::response& res) { + try { + Crypto::Hash block_hash; + if (!parse_hash256(req.hash, block_hash)) { + throw JsonRpc::JsonRpcError{ + CORE_RPC_ERROR_CODE_WRONG_PARAM, + "Failed to parse hex representation of block hash. Hex = " + req.hash + '.' }; + } + Block blk; + if (!m_core.getBlockByHash(block_hash, blk)) { + throw JsonRpc::JsonRpcError{ + CORE_RPC_ERROR_CODE_INTERNAL_ERROR, + "Internal error: can't get block by hash. Hash = " + req.hash + '.' }; + } + + Crypto::Hash blockHash = get_block_hash(blk); + uint32_t blockIndex = boost::get(blk.baseTransaction.inputs.front()).blockIndex; + + std::string body = index_start + (m_core.currency().isTestnet() ? "testnet" : "mainnet") + "\n

"; + + body += "

Block " + Common::podToHex(blockHash) + "

\n"; + + body += ""; + + body += "

Transactions

\n"; + + // simple list of tx hashes without details + body += "
    \n"; + body += "
  1. \n"; + Crypto::Hash coinbaseHash = getObjectHash(blk.baseTransaction); + std::string txHashStr = Common::podToHex(coinbaseHash); + body += " "; + body += txHashStr; + body += ""; + body += "
  2. \n"; + + for (const auto& t : blk.transactionHashes) { + body += "
  3. \n"; + body += " "; + body += Common::podToHex(t); + body += "
  4. \n"; + } + + body += "
\n"; + + body += index_finish; + + res = body; + } + catch (std::system_error& e) { + throw JsonRpc::JsonRpcError{ CORE_RPC_ERROR_CODE_INTERNAL_ERROR, e.what() }; + return false; + } + catch (std::exception& e) { + throw JsonRpc::JsonRpcError{ CORE_RPC_ERROR_CODE_INTERNAL_ERROR, "Error: " + std::string(e.what()) }; + return false; + } + + return true; +} + // // JSON handlers diff --git a/src/Rpc/RpcServer.h b/src/Rpc/RpcServer.h index 896f89468a..36a05c32e5 100755 --- a/src/Rpc/RpcServer.h +++ b/src/Rpc/RpcServer.h @@ -91,6 +91,7 @@ class RpcServer { // explorer bool on_get_explorer(const COMMAND_EXPLORER::request& req, COMMAND_EXPLORER::response& res); + bool on_get_explorer_block_by_hash(const COMMAND_EXPLORER_GET_BLOCK_DETAILS_BY_HASH::request& req, COMMAND_EXPLORER_GET_BLOCK_DETAILS_BY_HASH::response& res); // json handlers bool on_get_info(const COMMAND_RPC_GET_INFO::request& req, COMMAND_RPC_GET_INFO::response& res);