aboutsummaryrefslogtreecommitdiff
path: root/src/rpc
diff options
context:
space:
mode:
Diffstat (limited to 'src/rpc')
-rw-r--r--src/rpc/core_rpc_server.cpp139
-rw-r--r--src/rpc/core_rpc_server.h20
-rw-r--r--src/rpc/core_rpc_server_commands_defs.h93
3 files changed, 245 insertions, 7 deletions
diff --git a/src/rpc/core_rpc_server.cpp b/src/rpc/core_rpc_server.cpp
index 4c392c606..bab373c86 100644
--- a/src/rpc/core_rpc_server.cpp
+++ b/src/rpc/core_rpc_server.cpp
@@ -11,6 +11,7 @@ using namespace epee;
#include "common/command_line.h"
#include "cryptonote_core/cryptonote_format_utils.h"
#include "cryptonote_core/account.h"
+#include "cryptonote_core/cryptonote_basic_impl.h"
#include "misc_language.h"
#include "crypto/hash.h"
#include "core_rpc_server_error_codes.h"
@@ -413,6 +414,140 @@ namespace cryptonote
return true;
}
//------------------------------------------------------------------------------------------------------------------------------
-
-
+ uint64_t core_rpc_server::get_block_reward(const block& blk)
+ {
+ uint64_t reward = 0;
+ BOOST_FOREACH(const tx_out& out, blk.miner_tx.vout)
+ {
+ reward += out.amount;
+ }
+ return reward;
+ }
+ //------------------------------------------------------------------------------------------------------------------------------
+ bool core_rpc_server::fill_block_header_responce(const block& blk, bool orphan_status, uint64_t height, const crypto::hash& hash, block_header_responce& responce)
+ {
+ responce.major_version = blk.major_version;
+ responce.minor_version = blk.minor_version;
+ responce.timestamp = blk.timestamp;
+ responce.prev_hash = string_tools::pod_to_hex(blk.prev_id);
+ responce.nonce = blk.nonce;
+ responce.orphan_status = orphan_status;
+ responce.height = height;
+ responce.depth = m_core.get_current_blockchain_height() - height - 1;
+ responce.hash = string_tools::pod_to_hex(hash);
+ responce.difficulty = m_core.get_blockchain_storage().block_difficulty(height);
+ responce.reward = get_block_reward(blk);
+ return true;
+ }
+ //------------------------------------------------------------------------------------------------------------------------------
+ bool core_rpc_server::on_get_last_block_header(const COMMAND_RPC_GET_LAST_BLOCK_HEADER::request& req, COMMAND_RPC_GET_LAST_BLOCK_HEADER::response& res, epee::json_rpc::error& error_resp, connection_context& cntx)
+ {
+ if(!check_core_ready())
+ {
+ error_resp.code = CORE_RPC_ERROR_CODE_CORE_BUSY;
+ error_resp.message = "Core is busy.";
+ return false;
+ }
+ uint64_t last_block_height;
+ crypto::hash last_block_hash;
+ bool have_last_block_hash = m_core.get_blockchain_top(last_block_height, last_block_hash);
+ if (!have_last_block_hash)
+ {
+ error_resp.code = CORE_RPC_ERROR_CODE_INTERNAL_ERROR;
+ error_resp.message = "Internal error: can't get last block hash.";
+ return false;
+ }
+ block last_block;
+ bool have_last_block = m_core.get_block_by_hash(last_block_hash, last_block);
+ if (!have_last_block)
+ {
+ error_resp.code = CORE_RPC_ERROR_CODE_INTERNAL_ERROR;
+ error_resp.message = "Internal error: can't get last block.";
+ return false;
+ }
+ bool responce_filled = fill_block_header_responce(last_block, false, last_block_height, last_block_hash, res.block_header);
+ if (!responce_filled)
+ {
+ error_resp.code = CORE_RPC_ERROR_CODE_INTERNAL_ERROR;
+ error_resp.message = "Internal error: can't produce valid response.";
+ return false;
+ }
+ res.status = CORE_RPC_STATUS_OK;
+ return true;
+ }
+ //------------------------------------------------------------------------------------------------------------------------------
+ bool core_rpc_server::on_get_block_header_by_hash(const COMMAND_RPC_GET_BLOCK_HEADER_BY_HASH::request& req, COMMAND_RPC_GET_BLOCK_HEADER_BY_HASH::response& res, epee::json_rpc::error& error_resp, connection_context& cntx){
+ if(!check_core_ready())
+ {
+ error_resp.code = CORE_RPC_ERROR_CODE_CORE_BUSY;
+ error_resp.message = "Core is busy.";
+ return false;
+ }
+ 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 have_block = m_core.get_block_by_hash(block_hash, blk);
+ 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.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 responce_filled = fill_block_header_responce(blk, false, block_height, block_hash, res.block_header);
+ if (!responce_filled)
+ {
+ error_resp.code = CORE_RPC_ERROR_CODE_INTERNAL_ERROR;
+ error_resp.message = "Internal error: can't produce valid response.";
+ return false;
+ }
+ res.status = CORE_RPC_STATUS_OK;
+ return true;
+ }
+ //------------------------------------------------------------------------------------------------------------------------------
+ bool core_rpc_server::on_get_block_header_by_height(const COMMAND_RPC_GET_BLOCK_HEADER_BY_HEIGHT::request& req, COMMAND_RPC_GET_BLOCK_HEADER_BY_HEIGHT::response& res, epee::json_rpc::error& error_resp, connection_context& cntx){
+ if(!check_core_ready())
+ {
+ error_resp.code = CORE_RPC_ERROR_CODE_CORE_BUSY;
+ error_resp.message = "Core is busy.";
+ return false;
+ }
+ if(m_core.get_current_blockchain_height() <= req.height)
+ {
+ error_resp.code = CORE_RPC_ERROR_CODE_TOO_BIG_HEIGHT;
+ error_resp.message = std::string("To big height: ") + std::to_string(req.height) + ", current blockchain height = " + std::to_string(m_core.get_current_blockchain_height());
+ return false;
+ }
+ crypto::hash block_hash = m_core.get_block_id_by_height(req.height);
+ block blk;
+ bool have_block = m_core.get_block_by_hash(block_hash, blk);
+ if (!have_block)
+ {
+ error_resp.code = CORE_RPC_ERROR_CODE_INTERNAL_ERROR;
+ error_resp.message = "Internal error: can't get block by height. Height = " + req.height + '.';
+ return false;
+ }
+ bool responce_filled = fill_block_header_responce(blk, false, req.height, block_hash, res.block_header);
+ if (!responce_filled)
+ {
+ error_resp.code = CORE_RPC_ERROR_CODE_INTERNAL_ERROR;
+ error_resp.message = "Internal error: can't produce valid response.";
+ return false;
+ }
+ res.status = CORE_RPC_STATUS_OK;
+ return true;
+ }
+ //------------------------------------------------------------------------------------------------------------------------------
}
diff --git a/src/rpc/core_rpc_server.h b/src/rpc/core_rpc_server.h
index fb3e92216..7b14e741a 100644
--- a/src/rpc/core_rpc_server.h
+++ b/src/rpc/core_rpc_server.h
@@ -42,10 +42,13 @@ namespace cryptonote
MAP_URI_AUTO_JON2("/stop_mining", on_stop_mining, COMMAND_RPC_STOP_MINING)
MAP_URI_AUTO_JON2("/getinfo", on_get_info, COMMAND_RPC_GET_INFO)
BEGIN_JSON_RPC_MAP("/json_rpc")
- MAP_JON_RPC("getblockcount", on_getblockcount, COMMAND_RPC_GETBLOCKCOUNT)
- MAP_JON_RPC_WE("on_getblockhash", on_getblockhash, COMMAND_RPC_GETBLOCKHASH)
- MAP_JON_RPC_WE("getblocktemplate",on_getblocktemplate, COMMAND_RPC_GETBLOCKTEMPLATE)
- MAP_JON_RPC_WE("submitblock", on_submitblock, COMMAND_RPC_SUBMITBLOCK)
+ MAP_JON_RPC("getblockcount", on_getblockcount, COMMAND_RPC_GETBLOCKCOUNT)
+ MAP_JON_RPC_WE("on_getblockhash", on_getblockhash, COMMAND_RPC_GETBLOCKHASH)
+ MAP_JON_RPC_WE("getblocktemplate", on_getblocktemplate, COMMAND_RPC_GETBLOCKTEMPLATE)
+ MAP_JON_RPC_WE("submitblock", on_submitblock, COMMAND_RPC_SUBMITBLOCK)
+ MAP_JON_RPC_WE("getlastblockheader", on_get_last_block_header, COMMAND_RPC_GET_LAST_BLOCK_HEADER)
+ MAP_JON_RPC_WE("getblockheaderbyhash", on_get_block_header_by_hash, COMMAND_RPC_GET_BLOCK_HEADER_BY_HASH)
+ MAP_JON_RPC_WE("getblockheaderbyheight", on_get_block_header_by_height, COMMAND_RPC_GET_BLOCK_HEADER_BY_HEIGHT)
END_JSON_RPC_MAP()
END_URI_MAP2()
@@ -64,10 +67,17 @@ namespace cryptonote
bool on_getblockhash(const COMMAND_RPC_GETBLOCKHASH::request& req, COMMAND_RPC_GETBLOCKHASH::response& res, epee::json_rpc::error& error_resp, connection_context& cntx);
bool on_getblocktemplate(const COMMAND_RPC_GETBLOCKTEMPLATE::request& req, COMMAND_RPC_GETBLOCKTEMPLATE::response& res, epee::json_rpc::error& error_resp, connection_context& cntx);
bool on_submitblock(const COMMAND_RPC_SUBMITBLOCK::request& req, COMMAND_RPC_SUBMITBLOCK::response& res, epee::json_rpc::error& error_resp, connection_context& cntx);
+ bool on_get_last_block_header(const COMMAND_RPC_GET_LAST_BLOCK_HEADER::request& req, COMMAND_RPC_GET_LAST_BLOCK_HEADER::response& res, epee::json_rpc::error& error_resp, connection_context& cntx);
+ bool on_get_block_header_by_hash(const COMMAND_RPC_GET_BLOCK_HEADER_BY_HASH::request& req, COMMAND_RPC_GET_BLOCK_HEADER_BY_HASH::response& res, epee::json_rpc::error& error_resp, connection_context& cntx);
+ bool on_get_block_header_by_height(const COMMAND_RPC_GET_BLOCK_HEADER_BY_HEIGHT::request& req, COMMAND_RPC_GET_BLOCK_HEADER_BY_HEIGHT::response& res, epee::json_rpc::error& error_resp, connection_context& cntx);
//-----------------------
bool handle_command_line(const boost::program_options::variables_map& vm);
bool check_core_ready();
-
+
+ //utils
+ uint64_t get_block_reward(const block& blk);
+ bool fill_block_header_responce(const block& blk, bool orphan_status, uint64_t height, const crypto::hash& hash, block_header_responce& responce);
+
core& m_core;
nodetool::node_server<cryptonote::t_cryptonote_protocol_handler<cryptonote::core> >& m_p2p;
std::string m_port;
diff --git a/src/rpc/core_rpc_server_commands_defs.h b/src/rpc/core_rpc_server_commands_defs.h
index 5e8210775..d67ebfdd7 100644
--- a/src/rpc/core_rpc_server_commands_defs.h
+++ b/src/rpc/core_rpc_server_commands_defs.h
@@ -5,6 +5,7 @@
#pragma once
#include "cryptonote_protocol/cryptonote_protocol_defs.h"
#include "cryptonote_core/cryptonote_basic.h"
+#include "cryptonote_core/difficulty.h"
#include "crypto/hash.h"
namespace cryptonote
@@ -330,8 +331,100 @@ namespace cryptonote
END_KV_SERIALIZE_MAP()
};
};
+
+ struct block_header_responce
+ {
+ uint8_t major_version;
+ uint8_t minor_version;
+ uint64_t timestamp;
+ std::string prev_hash;
+ uint32_t nonce;
+ bool orphan_status;
+ uint64_t height;
+ uint64_t depth;
+ std::string hash;
+ difficulty_type difficulty;
+ uint64_t reward;
+
+ BEGIN_KV_SERIALIZE_MAP()
+ KV_SERIALIZE(major_version)
+ KV_SERIALIZE(minor_version)
+ KV_SERIALIZE(timestamp)
+ KV_SERIALIZE(prev_hash)
+ KV_SERIALIZE(nonce)
+ KV_SERIALIZE(orphan_status)
+ KV_SERIALIZE(height)
+ KV_SERIALIZE(depth)
+ KV_SERIALIZE(hash)
+ KV_SERIALIZE(difficulty)
+ KV_SERIALIZE(reward)
+ END_KV_SERIALIZE_MAP()
+ };
+
+ struct COMMAND_RPC_GET_LAST_BLOCK_HEADER
+ {
+ typedef std::list<std::string> request;
+
+ struct response
+ {
+ std::string status;
+ block_header_responce block_header;
+
+ BEGIN_KV_SERIALIZE_MAP()
+ KV_SERIALIZE(block_header)
+ KV_SERIALIZE(status)
+ END_KV_SERIALIZE_MAP()
+ };
+
+ };
+
+ struct COMMAND_RPC_GET_BLOCK_HEADER_BY_HASH
+ {
+ struct request
+ {
+ std::string hash;
+
+ BEGIN_KV_SERIALIZE_MAP()
+ KV_SERIALIZE(hash)
+ END_KV_SERIALIZE_MAP()
+ };
+
+ struct response
+ {
+ std::string status;
+ block_header_responce block_header;
+
+ BEGIN_KV_SERIALIZE_MAP()
+ KV_SERIALIZE(block_header)
+ KV_SERIALIZE(status)
+ END_KV_SERIALIZE_MAP()
+ };
+ };
+ struct COMMAND_RPC_GET_BLOCK_HEADER_BY_HEIGHT
+ {
+ struct request
+ {
+ uint64_t height;
+
+ BEGIN_KV_SERIALIZE_MAP()
+ KV_SERIALIZE(height)
+ END_KV_SERIALIZE_MAP()
+ };
+
+ struct response
+ {
+ std::string status;
+ block_header_responce block_header;
+
+ BEGIN_KV_SERIALIZE_MAP()
+ KV_SERIALIZE(block_header)
+ KV_SERIALIZE(status)
+ END_KV_SERIALIZE_MAP()
+ };
+
+ };
}