aboutsummaryrefslogtreecommitdiff
path: root/src/rpc
diff options
context:
space:
mode:
Diffstat (limited to 'src/rpc')
-rw-r--r--src/rpc/CMakeLists.txt3
-rw-r--r--src/rpc/core_rpc_server.cpp148
-rw-r--r--src/rpc/core_rpc_server.h7
-rw-r--r--src/rpc/core_rpc_server_commands_defs.h91
-rw-r--r--src/rpc/daemon_handler.cpp4
-rw-r--r--src/rpc/daemon_messages.cpp72
-rw-r--r--src/rpc/message_data_structs.h1
-rw-r--r--src/rpc/rpc_handler.cpp23
-rw-r--r--src/rpc/rpc_handler.h2
-rw-r--r--src/rpc/zmq_server.cpp1
10 files changed, 228 insertions, 124 deletions
diff --git a/src/rpc/CMakeLists.txt b/src/rpc/CMakeLists.txt
index 8fc42b7e3..d2c4a33cb 100644
--- a/src/rpc/CMakeLists.txt
+++ b/src/rpc/CMakeLists.txt
@@ -112,6 +112,7 @@ target_link_libraries(rpc
common
cryptonote_core
cryptonote_protocol
+ version
${Boost_REGEX_LIBRARY}
${Boost_THREAD_LIBRARY}
PRIVATE
@@ -121,6 +122,7 @@ target_link_libraries(daemon_messages
LINK_PRIVATE
cryptonote_core
cryptonote_protocol
+ version
serialization
${EXTRA_LIBRARIES})
@@ -129,6 +131,7 @@ target_link_libraries(daemon_rpc_server
rpc
cryptonote_core
cryptonote_protocol
+ version
daemon_messages
serialization
${Boost_CHRONO_LIBRARY}
diff --git a/src/rpc/core_rpc_server.cpp b/src/rpc/core_rpc_server.cpp
index c2e71bef8..3851af3c8 100644
--- a/src/rpc/core_rpc_server.cpp
+++ b/src/rpc/core_rpc_server.cpp
@@ -91,12 +91,10 @@ namespace cryptonote
bool core_rpc_server::init(
const boost::program_options::variables_map& vm
, const bool restricted
- , const network_type nettype
, const std::string& port
)
{
m_restricted = restricted;
- m_nettype = nettype;
m_net_server.set_threads_prefix("RPC");
auto rpc_config = cryptonote::rpc_args::process(vm);
@@ -184,17 +182,19 @@ namespace cryptonote
res.target = m_core.get_blockchain_storage().get_difficulty_target();
res.tx_count = m_core.get_blockchain_storage().get_total_transactions() - res.height; //without coinbase
res.tx_pool_size = m_core.get_pool_transactions_count();
- res.alt_blocks_count = m_core.get_blockchain_storage().get_alternative_blocks_count();
- uint64_t total_conn = m_p2p.get_connections_count();
- res.outgoing_connections_count = m_p2p.get_outgoing_connections_count();
- res.incoming_connections_count = total_conn - res.outgoing_connections_count;
- res.rpc_connections_count = get_connections_count();
- res.white_peerlist_size = m_p2p.get_peerlist_manager().get_white_peers_count();
- res.grey_peerlist_size = m_p2p.get_peerlist_manager().get_gray_peers_count();
- res.mainnet = m_nettype == MAINNET;
- res.testnet = m_nettype == TESTNET;
- res.stagenet = m_nettype == STAGENET;
- res.nettype = m_nettype == MAINNET ? "mainnet" : m_nettype == TESTNET ? "testnet" : m_nettype == STAGENET ? "stagenet" : "fakechain";
+ res.alt_blocks_count = m_restricted ? 0 : m_core.get_blockchain_storage().get_alternative_blocks_count();
+ uint64_t total_conn = m_restricted ? 0 : m_p2p.get_connections_count();
+ res.outgoing_connections_count = m_restricted ? 0 : m_p2p.get_outgoing_connections_count();
+ res.incoming_connections_count = m_restricted ? 0 : (total_conn - res.outgoing_connections_count);
+ res.rpc_connections_count = m_restricted ? 0 : get_connections_count();
+ res.white_peerlist_size = m_restricted ? 0 : m_p2p.get_peerlist_manager().get_white_peers_count();
+ res.grey_peerlist_size = m_restricted ? 0 : m_p2p.get_peerlist_manager().get_gray_peers_count();
+
+ cryptonote::network_type net_type = nettype();
+ res.mainnet = net_type == MAINNET;
+ res.testnet = net_type == TESTNET;
+ res.stagenet = net_type == STAGENET;
+ res.nettype = net_type == MAINNET ? "mainnet" : net_type == TESTNET ? "testnet" : net_type == STAGENET ? "stagenet" : "fakechain";
res.cumulative_difficulty = m_core.get_blockchain_storage().get_db().get_block_cumulative_difficulty(res.height - 1);
res.block_size_limit = res.block_weight_limit = m_core.get_blockchain_storage().get_current_cumulative_block_weight_limit();
res.block_size_median = res.block_weight_median = m_core.get_blockchain_storage().get_current_cumulative_block_weight_median();
@@ -202,14 +202,18 @@ namespace cryptonote
res.start_time = m_restricted ? 0 : (uint64_t)m_core.get_start_time();
res.free_space = m_restricted ? std::numeric_limits<uint64_t>::max() : m_core.get_free_space();
res.offline = m_core.offline();
- res.bootstrap_daemon_address = m_bootstrap_daemon_address;
- res.height_without_bootstrap = res.height;
+ res.bootstrap_daemon_address = m_restricted ? "" : m_bootstrap_daemon_address;
+ res.height_without_bootstrap = m_restricted ? 0 : res.height;
+ if (m_restricted)
+ res.was_bootstrap_ever_used = false;
+ else
{
boost::shared_lock<boost::shared_mutex> lock(m_bootstrap_daemon_mutex);
res.was_bootstrap_ever_used = m_was_bootstrap_ever_used;
}
- res.database_size = m_core.get_blockchain_storage().get_db().get_database_size();
- res.update_available = m_core.is_update_available();
+ res.database_size = m_restricted ? 0 : m_core.get_blockchain_storage().get_db().get_database_size();
+ res.update_available = m_restricted ? false : m_core.is_update_available();
+ res.version = m_restricted ? "" : MONERO_VERSION;
return true;
}
//------------------------------------------------------------------------------------------------------------------------------
@@ -750,7 +754,7 @@ namespace cryptonote
PERF_TIMER(on_start_mining);
CHECK_CORE_READY();
cryptonote::address_parse_info info;
- if(!get_account_address_from_str(info, m_nettype, req.miner_address))
+ if(!get_account_address_from_str(info, nettype(), req.miner_address))
{
res.status = "Failed, wrong address";
LOG_PRINT_L0(res.status);
@@ -831,7 +835,7 @@ namespace cryptonote
res.speed = lMiner.get_speed();
res.threads_count = lMiner.get_threads_count();
const account_public_address& lMiningAdr = lMiner.get_mining_address();
- res.address = get_account_address_as_str(m_nettype, false, lMiningAdr);
+ res.address = get_account_address_as_str(nettype(), false, lMiningAdr);
}
res.status = CORE_RPC_STATUS_OK;
@@ -1026,7 +1030,7 @@ namespace cryptonote
//------------------------------------------------------------------------------------------------------------------------------
// equivalent of strstr, but with arbitrary bytes (ie, NULs)
// This does not differentiate between "not found" and "found at offset 0"
- uint64_t slow_memmem(const void* start_buff, size_t buflen,const void* pat,size_t patlen)
+ size_t slow_memmem(const void* start_buff, size_t buflen,const void* pat,size_t patlen)
{
const void* buf = start_buff;
const void* end=(const char*)buf+buflen;
@@ -1064,7 +1068,7 @@ namespace cryptonote
cryptonote::address_parse_info info;
- if(!req.wallet_address.size() || !cryptonote::get_account_address_from_str(info, m_nettype, req.wallet_address))
+ if(!req.wallet_address.size() || !cryptonote::get_account_address_from_str(info, nettype(), req.wallet_address))
{
error_resp.code = CORE_RPC_ERROR_CODE_WRONG_WALLET_ADDRESS;
error_resp.message = "Failed to parse wallet address";
@@ -1077,7 +1081,7 @@ namespace cryptonote
return false;
}
- block b = AUTO_VAL_INIT(b);
+ block b;
cryptonote::blobdata blob_reserve;
blob_reserve.resize(req.reserve_size, 0);
if(!m_core.get_block_template(b, info.address, res.difficulty, res.height, res.expected_reward, blob_reserve))
@@ -1148,7 +1152,7 @@ namespace cryptonote
// Fixing of high orphan issue for most pools
// Thanks Boolberry!
- block b = AUTO_VAL_INIT(b);
+ block b;
if(!parse_and_validate_block_from_blob(blockblob, b))
{
error_resp.code = CORE_RPC_ERROR_CODE_WRONG_BLOCKBLOB;
@@ -1216,7 +1220,7 @@ namespace cryptonote
error_resp.message = "Wrong block blob";
return false;
}
- block b = AUTO_VAL_INIT(b);
+ block b;
if(!parse_and_validate_block_from_blob(blockblob, b))
{
error_resp.code = CORE_RPC_ERROR_CODE_WRONG_BLOCKBLOB;
@@ -1583,32 +1587,39 @@ namespace cryptonote
res.target = m_core.get_blockchain_storage().get_current_hard_fork_version() < 2 ? DIFFICULTY_TARGET_V1 : DIFFICULTY_TARGET_V2;
res.tx_count = m_core.get_blockchain_storage().get_total_transactions() - res.height; //without coinbase
res.tx_pool_size = m_core.get_pool_transactions_count();
- res.alt_blocks_count = m_core.get_blockchain_storage().get_alternative_blocks_count();
- uint64_t total_conn = m_p2p.get_connections_count();
- res.outgoing_connections_count = m_p2p.get_outgoing_connections_count();
- res.incoming_connections_count = total_conn - res.outgoing_connections_count;
- res.rpc_connections_count = get_connections_count();
- res.white_peerlist_size = m_p2p.get_peerlist_manager().get_white_peers_count();
- res.grey_peerlist_size = m_p2p.get_peerlist_manager().get_gray_peers_count();
- res.mainnet = m_nettype == MAINNET;
- res.testnet = m_nettype == TESTNET;
- res.stagenet = m_nettype == STAGENET;
- res.nettype = m_nettype == MAINNET ? "mainnet" : m_nettype == TESTNET ? "testnet" : m_nettype == STAGENET ? "stagenet" : "fakechain";
+ res.alt_blocks_count = m_restricted ? 0 : m_core.get_blockchain_storage().get_alternative_blocks_count();
+ uint64_t total_conn = m_restricted ? 0 : m_p2p.get_connections_count();
+ res.outgoing_connections_count = m_restricted ? 0 : m_p2p.get_outgoing_connections_count();
+ res.incoming_connections_count = m_restricted ? 0 : (total_conn - res.outgoing_connections_count);
+ res.rpc_connections_count = m_restricted ? 0 : get_connections_count();
+ res.white_peerlist_size = m_restricted ? 0 : m_p2p.get_peerlist_manager().get_white_peers_count();
+ res.grey_peerlist_size = m_restricted ? 0 : m_p2p.get_peerlist_manager().get_gray_peers_count();
+
+ cryptonote::network_type net_type = nettype();
+ res.mainnet = net_type == MAINNET;
+ res.testnet = net_type == TESTNET;
+ res.stagenet = net_type == STAGENET;
+ res.nettype = net_type == MAINNET ? "mainnet" : net_type == TESTNET ? "testnet" : net_type == STAGENET ? "stagenet" : "fakechain";
+
res.cumulative_difficulty = m_core.get_blockchain_storage().get_db().get_block_cumulative_difficulty(res.height - 1);
res.block_size_limit = res.block_weight_limit = m_core.get_blockchain_storage().get_current_cumulative_block_weight_limit();
res.block_size_median = res.block_weight_median = m_core.get_blockchain_storage().get_current_cumulative_block_weight_median();
res.status = CORE_RPC_STATUS_OK;
- res.start_time = (uint64_t)m_core.get_start_time();
+ res.start_time = m_restricted ? 0 : (uint64_t)m_core.get_start_time();
res.free_space = m_restricted ? std::numeric_limits<uint64_t>::max() : m_core.get_free_space();
res.offline = m_core.offline();
- res.bootstrap_daemon_address = m_bootstrap_daemon_address;
- res.height_without_bootstrap = res.height;
+ res.bootstrap_daemon_address = m_restricted ? "" : m_bootstrap_daemon_address;
+ res.height_without_bootstrap = m_restricted ? 0 : res.height;
+ if (m_restricted)
+ res.was_bootstrap_ever_used = false;
+ else
{
boost::shared_lock<boost::shared_mutex> lock(m_bootstrap_daemon_mutex);
res.was_bootstrap_ever_used = m_was_bootstrap_ever_used;
}
- res.database_size = m_core.get_blockchain_storage().get_db().get_database_size();
- res.update_available = m_core.is_update_available();
+ res.database_size = m_restricted ? 0 : m_core.get_blockchain_storage().get_db().get_database_size();
+ res.update_available = m_restricted ? false : m_core.is_update_available();
+ res.version = m_restricted ? "" : MONERO_VERSION;
return true;
}
//------------------------------------------------------------------------------------------------------------------------------
@@ -2021,6 +2032,18 @@ namespace cryptonote
return true;
}
//------------------------------------------------------------------------------------------------------------------------------
+ bool core_rpc_server::on_pop_blocks(const COMMAND_RPC_POP_BLOCKS::request& req, COMMAND_RPC_POP_BLOCKS::response& res)
+ {
+ PERF_TIMER(on_pop_blocks);
+
+ m_core.get_blockchain_storage().pop_blocks(req.nblocks);
+
+ res.height = m_core.get_current_blockchain_height();
+ res.status = CORE_RPC_STATUS_OK;
+
+ return true;
+ }
+ //------------------------------------------------------------------------------------------------------------------------------
bool core_rpc_server::on_relay_tx(const COMMAND_RPC_RELAY_TX::request& req, COMMAND_RPC_RELAY_TX::response& res, epee::json_rpc::error& error_resp)
{
PERF_TIMER(on_relay_tx);
@@ -2125,7 +2148,7 @@ namespace cryptonote
const uint64_t req_to_height = req.to_height ? req.to_height : (m_core.get_current_blockchain_height() - 1);
for (uint64_t amount: req.amounts)
{
- auto data = rpc::RpcHandler::get_output_distribution(m_core, amount, req.from_height, req_to_height, req.cumulative);
+ auto data = rpc::RpcHandler::get_output_distribution([this](uint64_t amount, uint64_t from, uint64_t to, uint64_t &start_height, std::vector<uint64_t> &distribution, uint64_t &base) { return m_core.get_output_distribution(amount, from, to, start_height, distribution, base); }, amount, req.from_height, req_to_height, req.cumulative);
if (!data)
{
error_resp.code = CORE_RPC_ERROR_CODE_INTERNAL_ERROR;
@@ -2133,7 +2156,7 @@ namespace cryptonote
return false;
}
- res.distributions.push_back({std::move(*data), amount, req.binary});
+ res.distributions.push_back({std::move(*data), amount, "", req.binary, req.compress});
}
}
catch (const std::exception &e)
@@ -2147,6 +2170,47 @@ namespace cryptonote
return true;
}
//------------------------------------------------------------------------------------------------------------------------------
+ bool core_rpc_server::on_get_output_distribution_bin(const COMMAND_RPC_GET_OUTPUT_DISTRIBUTION::request& req, COMMAND_RPC_GET_OUTPUT_DISTRIBUTION::response& res)
+ {
+ PERF_TIMER(on_get_output_distribution_bin);
+
+ bool r;
+ if (use_bootstrap_daemon_if_necessary<COMMAND_RPC_GET_OUTPUT_DISTRIBUTION>(invoke_http_mode::BIN, "/get_output_distribution.bin", req, res, r))
+ return r;
+
+ res.status = "Failed";
+
+ if (!req.binary)
+ {
+ res.status = "Binary only call";
+ return false;
+ }
+ try
+ {
+ // 0 is placeholder for the whole chain
+ const uint64_t req_to_height = req.to_height ? req.to_height : (m_core.get_current_blockchain_height() - 1);
+ for (uint64_t amount: req.amounts)
+ {
+ auto data = rpc::RpcHandler::get_output_distribution([this](uint64_t amount, uint64_t from, uint64_t to, uint64_t &start_height, std::vector<uint64_t> &distribution, uint64_t &base) { return m_core.get_output_distribution(amount, from, to, start_height, distribution, base); }, amount, req.from_height, req_to_height, req.cumulative);
+ if (!data)
+ {
+ res.status = "Failed to get output distribution";
+ return false;
+ }
+
+ res.distributions.push_back({std::move(*data), amount, "", req.binary, req.compress});
+ }
+ }
+ catch (const std::exception &e)
+ {
+ res.status = "Failed to get output distribution";
+ return false;
+ }
+
+ res.status = CORE_RPC_STATUS_OK;
+ return true;
+ }
+ //------------------------------------------------------------------------------------------------------------------------------
const command_line::arg_descriptor<std::string, false, true, 2> core_rpc_server::arg_rpc_bind_port = {
diff --git a/src/rpc/core_rpc_server.h b/src/rpc/core_rpc_server.h
index 3ba882b23..081ccc25d 100644
--- a/src/rpc/core_rpc_server.h
+++ b/src/rpc/core_rpc_server.h
@@ -70,10 +70,9 @@ namespace cryptonote
bool init(
const boost::program_options::variables_map& vm,
const bool restricted,
- const network_type nettype,
const std::string& port
);
- network_type nettype() const { return m_nettype; }
+ network_type nettype() const { return m_core.get_nettype(); }
CHAIN_HTTP_TO_MAP2(connection_context); //forward http requests to uri map
@@ -117,6 +116,8 @@ namespace cryptonote
MAP_URI_AUTO_JON2_IF("/stop_save_graph", on_stop_save_graph, COMMAND_RPC_STOP_SAVE_GRAPH, !m_restricted)
MAP_URI_AUTO_JON2("/get_outs", on_get_outs, COMMAND_RPC_GET_OUTPUTS)
MAP_URI_AUTO_JON2_IF("/update", on_update, COMMAND_RPC_UPDATE, !m_restricted)
+ MAP_URI_AUTO_BIN2("/get_output_distribution.bin", on_get_output_distribution_bin, COMMAND_RPC_GET_OUTPUT_DISTRIBUTION)
+ MAP_URI_AUTO_JON2_IF("/pop_blocks", on_pop_blocks, COMMAND_RPC_POP_BLOCKS, !m_restricted)
BEGIN_JSON_RPC_MAP("/json_rpc")
MAP_JON_RPC("get_block_count", on_getblockcount, COMMAND_RPC_GETBLOCKCOUNT)
MAP_JON_RPC("getblockcount", on_getblockcount, COMMAND_RPC_GETBLOCKCOUNT)
@@ -187,6 +188,8 @@ namespace cryptonote
bool on_start_save_graph(const COMMAND_RPC_START_SAVE_GRAPH::request& req, COMMAND_RPC_START_SAVE_GRAPH::response& res);
bool on_stop_save_graph(const COMMAND_RPC_STOP_SAVE_GRAPH::request& req, COMMAND_RPC_STOP_SAVE_GRAPH::response& res);
bool on_update(const COMMAND_RPC_UPDATE::request& req, COMMAND_RPC_UPDATE::response& res);
+ bool on_get_output_distribution_bin(const COMMAND_RPC_GET_OUTPUT_DISTRIBUTION::request& req, COMMAND_RPC_GET_OUTPUT_DISTRIBUTION::response& res);
+ bool on_pop_blocks(const COMMAND_RPC_POP_BLOCKS::request& req, COMMAND_RPC_POP_BLOCKS::response& res);
//json_rpc
bool on_getblockcount(const COMMAND_RPC_GETBLOCKCOUNT::request& req, COMMAND_RPC_GETBLOCKCOUNT::response& res);
diff --git a/src/rpc/core_rpc_server_commands_defs.h b/src/rpc/core_rpc_server_commands_defs.h
index 8e8df7a52..0a07930ec 100644
--- a/src/rpc/core_rpc_server_commands_defs.h
+++ b/src/rpc/core_rpc_server_commands_defs.h
@@ -34,6 +34,40 @@
#include "cryptonote_basic/difficulty.h"
#include "crypto/hash.h"
#include "rpc/rpc_handler.h"
+#include "common/varint.h"
+#include "common/perf_timer.h"
+
+namespace
+{
+ template<typename T>
+ std::string compress_integer_array(const std::vector<T> &v)
+ {
+ std::string s;
+ s.resize(v.size() * (sizeof(T) * 8 / 7 + 1));
+ char *ptr = (char*)s.data();
+ for (const T &t: v)
+ tools::write_varint(ptr, t);
+ s.resize(ptr - s.data());
+ return s;
+ }
+
+ template<typename T>
+ std::vector<T> decompress_integer_array(const std::string &s)
+ {
+ std::vector<T> v;
+ v.reserve(s.size());
+ int read = 0;
+ const std::string::const_iterator end = s.end();
+ for (std::string::const_iterator i = s.begin(); i != end; std::advance(i, read))
+ {
+ T t;
+ read = tools::read_varint(std::string::const_iterator(i), s.end(), t);
+ CHECK_AND_ASSERT_THROW_MES(read > 0 && read <= 256, "Error decompressing data");
+ v.push_back(t);
+ }
+ return v;
+ }
+}
namespace cryptonote
{
@@ -50,7 +84,7 @@ namespace cryptonote
// advance which version they will stop working with
// Don't go over 32767 for any of these
#define CORE_RPC_VERSION_MAJOR 2
-#define CORE_RPC_VERSION_MINOR 1
+#define CORE_RPC_VERSION_MINOR 2
#define MAKE_CORE_RPC_VERSION(major,minor) (((major)<<16)|(minor))
#define CORE_RPC_VERSION MAKE_CORE_RPC_VERSION(CORE_RPC_VERSION_MAJOR, CORE_RPC_VERSION_MINOR)
@@ -697,9 +731,11 @@ namespace cryptonote
struct request
{
std::vector<get_outputs_out> outputs;
+ bool get_txid;
BEGIN_KV_SERIALIZE_MAP()
KV_SERIALIZE(outputs)
+ KV_SERIALIZE_OPT(get_txid, true)
END_KV_SERIALIZE_MAP()
};
@@ -892,6 +928,7 @@ namespace cryptonote
bool was_bootstrap_ever_used;
uint64_t database_size;
bool update_available;
+ std::string version;
BEGIN_KV_SERIALIZE_MAP()
KV_SERIALIZE(status)
@@ -926,6 +963,7 @@ namespace cryptonote
KV_SERIALIZE(was_bootstrap_ever_used)
KV_SERIALIZE(database_size)
KV_SERIALIZE(update_available)
+ KV_SERIALIZE(version)
END_KV_SERIALIZE_MAP()
};
};
@@ -2222,6 +2260,7 @@ namespace cryptonote
uint64_t to_height;
bool cumulative;
bool binary;
+ bool compress;
BEGIN_KV_SERIALIZE_MAP()
KV_SERIALIZE(amounts)
@@ -2229,6 +2268,7 @@ namespace cryptonote
KV_SERIALIZE_OPT(to_height, (uint64_t)0)
KV_SERIALIZE_OPT(cumulative, false)
KV_SERIALIZE_OPT(binary, true)
+ KV_SERIALIZE_OPT(compress, false)
END_KV_SERIALIZE_MAP()
};
@@ -2236,14 +2276,38 @@ namespace cryptonote
{
rpc::output_distribution_data data;
uint64_t amount;
+ std::string compressed_data;
bool binary;
+ bool compress;
BEGIN_KV_SERIALIZE_MAP()
KV_SERIALIZE(amount)
KV_SERIALIZE_N(data.start_height, "start_height")
KV_SERIALIZE(binary)
+ KV_SERIALIZE(compress)
if (this_ref.binary)
- KV_SERIALIZE_CONTAINER_POD_AS_BLOB_N(data.distribution, "distribution")
+ {
+ if (is_store)
+ {
+ if (this_ref.compress)
+ {
+ const_cast<std::string&>(this_ref.compressed_data) = compress_integer_array(this_ref.data.distribution);
+ KV_SERIALIZE(compressed_data)
+ }
+ else
+ KV_SERIALIZE_CONTAINER_POD_AS_BLOB_N(data.distribution, "distribution")
+ }
+ else
+ {
+ if (this_ref.compress)
+ {
+ KV_SERIALIZE(compressed_data)
+ const_cast<std::vector<uint64_t>&>(this_ref.data.distribution) = decompress_integer_array<uint64_t>(this_ref.compressed_data);
+ }
+ else
+ KV_SERIALIZE_CONTAINER_POD_AS_BLOB_N(data.distribution, "distribution")
+ }
+ }
else
KV_SERIALIZE_N(data.distribution, "distribution")
KV_SERIALIZE_N(data.base, "base")
@@ -2264,4 +2328,27 @@ namespace cryptonote
};
};
+ struct COMMAND_RPC_POP_BLOCKS
+ {
+ struct request
+ {
+ uint64_t nblocks;
+
+ BEGIN_KV_SERIALIZE_MAP()
+ KV_SERIALIZE(nblocks);
+ END_KV_SERIALIZE_MAP()
+ };
+
+ struct response
+ {
+ std::string status;
+ uint64_t height;
+
+ BEGIN_KV_SERIALIZE_MAP()
+ KV_SERIALIZE(status)
+ KV_SERIALIZE(height)
+ END_KV_SERIALIZE_MAP()
+ };
+ };
+
}
diff --git a/src/rpc/daemon_handler.cpp b/src/rpc/daemon_handler.cpp
index 8822bd378..e2885dbb5 100644
--- a/src/rpc/daemon_handler.cpp
+++ b/src/rpc/daemon_handler.cpp
@@ -34,6 +34,7 @@
#include "cryptonote_basic/cryptonote_format_utils.h"
#include "cryptonote_basic/blobdatatype.h"
#include "ringct/rctSigs.h"
+#include "version.h"
namespace cryptonote
{
@@ -437,6 +438,7 @@ namespace rpc
res.info.block_size_limit = res.info.block_weight_limit = m_core.get_blockchain_storage().get_current_cumulative_block_weight_limit();
res.info.block_size_median = res.info.block_weight_median = m_core.get_blockchain_storage().get_current_cumulative_block_weight_median();
res.info.start_time = (uint64_t)m_core.get_start_time();
+ res.info.version = MONERO_VERSION;
res.status = Message::STATUS_OK;
res.error_details = "";
@@ -751,7 +753,7 @@ namespace rpc
const uint64_t req_to_height = req.to_height ? req.to_height : (m_core.get_current_blockchain_height() - 1);
for (std::uint64_t amount : req.amounts)
{
- auto data = get_output_distribution(m_core, amount, req.from_height, req_to_height, req.cumulative);
+ auto data = rpc::RpcHandler::get_output_distribution([this](uint64_t amount, uint64_t from, uint64_t to, uint64_t &start_height, std::vector<uint64_t> &distribution, uint64_t &base) { return m_core.get_output_distribution(amount, from, to, start_height, distribution, base); }, amount, req.from_height, req_to_height, req.cumulative);
if (!data)
{
res.distributions.clear();
diff --git a/src/rpc/daemon_messages.cpp b/src/rpc/daemon_messages.cpp
index fa848cff4..7c7442014 100644
--- a/src/rpc/daemon_messages.cpp
+++ b/src/rpc/daemon_messages.cpp
@@ -177,8 +177,6 @@ rapidjson::Value GetTransactions::Request::toJson(rapidjson::Document& doc) cons
{
auto val = Message::toJson(doc);
- auto& al = doc.GetAllocator();
-
INSERT_INTO_JSON_OBJECT(val, doc, tx_hashes, tx_hashes);
return val;
@@ -193,8 +191,6 @@ rapidjson::Value GetTransactions::Response::toJson(rapidjson::Document& doc) con
{
rapidjson::Value val(rapidjson::kObjectType);
- auto& al = doc.GetAllocator();
-
INSERT_INTO_JSON_OBJECT(val, doc, txs, txs);
INSERT_INTO_JSON_OBJECT(val, doc, missed_hashes, missed_hashes);
@@ -212,8 +208,6 @@ rapidjson::Value KeyImagesSpent::Request::toJson(rapidjson::Document& doc) const
{
auto val = Message::toJson(doc);
- auto& al = doc.GetAllocator();
-
INSERT_INTO_JSON_OBJECT(val, doc, key_images, key_images);
return val;
@@ -228,8 +222,6 @@ rapidjson::Value KeyImagesSpent::Response::toJson(rapidjson::Document& doc) cons
{
auto val = Message::toJson(doc);
- auto& al = doc.GetAllocator();
-
INSERT_INTO_JSON_OBJECT(val, doc, spent_status, spent_status);
return val;
@@ -245,8 +237,6 @@ rapidjson::Value GetTxGlobalOutputIndices::Request::toJson(rapidjson::Document&
{
auto val = Message::toJson(doc);
- auto& al = doc.GetAllocator();
-
INSERT_INTO_JSON_OBJECT(val, doc, tx_hash, tx_hash);
return val;
@@ -261,8 +251,6 @@ rapidjson::Value GetTxGlobalOutputIndices::Response::toJson(rapidjson::Document&
{
auto val = Message::toJson(doc);
- auto& al = doc.GetAllocator();
-
INSERT_INTO_JSON_OBJECT(val, doc, output_indices, output_indices);
return val;
@@ -277,8 +265,6 @@ rapidjson::Value SendRawTx::Request::toJson(rapidjson::Document& doc) const
{
auto val = Message::toJson(doc);
- auto& al = doc.GetAllocator();
-
INSERT_INTO_JSON_OBJECT(val, doc, tx, tx);
INSERT_INTO_JSON_OBJECT(val, doc, relay, relay);
@@ -295,8 +281,6 @@ rapidjson::Value SendRawTx::Response::toJson(rapidjson::Document& doc) const
{
auto val = Message::toJson(doc);
- auto& al = doc.GetAllocator();
-
INSERT_INTO_JSON_OBJECT(val, doc, relayed, relayed);
return val;
@@ -312,8 +296,6 @@ rapidjson::Value StartMining::Request::toJson(rapidjson::Document& doc) const
{
auto val = Message::toJson(doc);
- auto& al = doc.GetAllocator();
-
INSERT_INTO_JSON_OBJECT(val, doc, miner_address, miner_address);
INSERT_INTO_JSON_OBJECT(val, doc, threads_count, threads_count);
INSERT_INTO_JSON_OBJECT(val, doc, do_background_mining, do_background_mining);
@@ -372,8 +354,6 @@ rapidjson::Value MiningStatus::Response::toJson(rapidjson::Document& doc) const
{
auto val = Message::toJson(doc);
- auto& al = doc.GetAllocator();
-
INSERT_INTO_JSON_OBJECT(val, doc, active, active);
INSERT_INTO_JSON_OBJECT(val, doc, speed, speed);
INSERT_INTO_JSON_OBJECT(val, doc, threads_count, threads_count);
@@ -406,8 +386,6 @@ rapidjson::Value GetInfo::Response::toJson(rapidjson::Document& doc) const
{
auto val = Message::toJson(doc);
- auto& al = doc.GetAllocator();
-
INSERT_INTO_JSON_OBJECT(val, doc, info, info);
return val;
@@ -423,8 +401,6 @@ rapidjson::Value SaveBC::Request::toJson(rapidjson::Document& doc) const
{
auto val = Message::toJson(doc);
- auto& al = doc.GetAllocator();
-
return val;
}
@@ -436,8 +412,6 @@ rapidjson::Value SaveBC::Response::toJson(rapidjson::Document& doc) const
{
auto val = Message::toJson(doc);
- auto& al = doc.GetAllocator();
-
return val;
}
@@ -450,8 +424,6 @@ rapidjson::Value GetBlockHash::Request::toJson(rapidjson::Document& doc) const
{
auto val = Message::toJson(doc);
- auto& al = doc.GetAllocator();
-
INSERT_INTO_JSON_OBJECT(val, doc, height, height);
return val;
@@ -466,8 +438,6 @@ rapidjson::Value GetBlockHash::Response::toJson(rapidjson::Document& doc) const
{
auto val = Message::toJson(doc);
- auto& al = doc.GetAllocator();
-
INSERT_INTO_JSON_OBJECT(val, doc, hash, hash);
return val;
@@ -483,8 +453,6 @@ rapidjson::Value GetLastBlockHeader::Request::toJson(rapidjson::Document& doc) c
{
auto val = Message::toJson(doc);
- auto& al = doc.GetAllocator();
-
return val;
}
@@ -496,8 +464,6 @@ rapidjson::Value GetLastBlockHeader::Response::toJson(rapidjson::Document& doc)
{
auto val = Message::toJson(doc);
- auto& al = doc.GetAllocator();
-
INSERT_INTO_JSON_OBJECT(val, doc, header, header);
return val;
@@ -513,8 +479,6 @@ rapidjson::Value GetBlockHeaderByHash::Request::toJson(rapidjson::Document& doc)
{
auto val = Message::toJson(doc);
- auto& al = doc.GetAllocator();
-
INSERT_INTO_JSON_OBJECT(val, doc, hash, hash);
return val;
@@ -529,8 +493,6 @@ rapidjson::Value GetBlockHeaderByHash::Response::toJson(rapidjson::Document& doc
{
auto val = Message::toJson(doc);
- auto& al = doc.GetAllocator();
-
INSERT_INTO_JSON_OBJECT(val, doc, header, header);
return val;
@@ -546,8 +508,6 @@ rapidjson::Value GetBlockHeaderByHeight::Request::toJson(rapidjson::Document& do
{
auto val = Message::toJson(doc);
- auto& al = doc.GetAllocator();
-
INSERT_INTO_JSON_OBJECT(val, doc, height, height);
return val;
@@ -562,8 +522,6 @@ rapidjson::Value GetBlockHeaderByHeight::Response::toJson(rapidjson::Document& d
{
auto val = Message::toJson(doc);
- auto& al = doc.GetAllocator();
-
INSERT_INTO_JSON_OBJECT(val, doc, header, header);
return val;
@@ -579,8 +537,6 @@ rapidjson::Value GetBlockHeadersByHeight::Request::toJson(rapidjson::Document& d
{
auto val = Message::toJson(doc);
- auto& al = doc.GetAllocator();
-
INSERT_INTO_JSON_OBJECT(val, doc, heights, heights);
return val;
@@ -595,8 +551,6 @@ rapidjson::Value GetBlockHeadersByHeight::Response::toJson(rapidjson::Document&
{
auto val = Message::toJson(doc);
- auto& al = doc.GetAllocator();
-
INSERT_INTO_JSON_OBJECT(val, doc, headers, headers);
return val;
@@ -612,8 +566,6 @@ rapidjson::Value GetPeerList::Request::toJson(rapidjson::Document& doc) const
{
auto val = Message::toJson(doc);
- auto& al = doc.GetAllocator();
-
return val;
}
@@ -625,8 +577,6 @@ rapidjson::Value GetPeerList::Response::toJson(rapidjson::Document& doc) const
{
auto val = Message::toJson(doc);
- auto& al = doc.GetAllocator();
-
INSERT_INTO_JSON_OBJECT(val, doc, white_list, white_list);
INSERT_INTO_JSON_OBJECT(val, doc, gray_list, gray_list);
@@ -679,8 +629,6 @@ rapidjson::Value GetTransactionPool::Response::toJson(rapidjson::Document& doc)
{
auto val = Message::toJson(doc);
- auto& al = doc.GetAllocator();
-
INSERT_INTO_JSON_OBJECT(val, doc, transactions, transactions);
INSERT_INTO_JSON_OBJECT(val, doc, key_images, key_images);
@@ -698,8 +646,6 @@ rapidjson::Value HardForkInfo::Request::toJson(rapidjson::Document& doc) const
{
auto val = Message::toJson(doc);
- auto& al = doc.GetAllocator();
-
INSERT_INTO_JSON_OBJECT(val, doc, version, version);
return val;
@@ -714,8 +660,6 @@ rapidjson::Value HardForkInfo::Response::toJson(rapidjson::Document& doc) const
{
auto val = Message::toJson(doc);
- auto& al = doc.GetAllocator();
-
INSERT_INTO_JSON_OBJECT(val, doc, info, info);
return val;
@@ -731,8 +675,6 @@ rapidjson::Value GetOutputHistogram::Request::toJson(rapidjson::Document& doc) c
{
auto val = Message::toJson(doc);
- auto& al = doc.GetAllocator();
-
INSERT_INTO_JSON_OBJECT(val, doc, amounts, amounts);
INSERT_INTO_JSON_OBJECT(val, doc, min_count, min_count);
INSERT_INTO_JSON_OBJECT(val, doc, max_count, max_count);
@@ -755,8 +697,6 @@ rapidjson::Value GetOutputHistogram::Response::toJson(rapidjson::Document& doc)
{
auto val = Message::toJson(doc);
- auto& al = doc.GetAllocator();
-
INSERT_INTO_JSON_OBJECT(val, doc, histogram, histogram);
return val;
@@ -772,8 +712,6 @@ rapidjson::Value GetOutputKeys::Request::toJson(rapidjson::Document& doc) const
{
auto val = Message::toJson(doc);
- auto& al = doc.GetAllocator();
-
INSERT_INTO_JSON_OBJECT(val, doc, outputs, outputs);
return val;
@@ -788,8 +726,6 @@ rapidjson::Value GetOutputKeys::Response::toJson(rapidjson::Document& doc) const
{
auto val = Message::toJson(doc);
- auto& al = doc.GetAllocator();
-
INSERT_INTO_JSON_OBJECT(val, doc, keys, keys);
return val;
@@ -814,8 +750,6 @@ rapidjson::Value GetRPCVersion::Response::toJson(rapidjson::Document& doc) const
{
auto val = Message::toJson(doc);
- auto& al = doc.GetAllocator();
-
INSERT_INTO_JSON_OBJECT(val, doc, version, version);
return val;
@@ -830,8 +764,6 @@ rapidjson::Value GetFeeEstimate::Request::toJson(rapidjson::Document& doc) const
{
auto val = Message::toJson(doc);
- auto& al = doc.GetAllocator();
-
INSERT_INTO_JSON_OBJECT(val, doc, num_grace_blocks, num_grace_blocks);
return val;
@@ -846,8 +778,6 @@ rapidjson::Value GetFeeEstimate::Response::toJson(rapidjson::Document& doc) cons
{
auto val = Message::toJson(doc);
- auto& al = doc.GetAllocator();
-
INSERT_INTO_JSON_OBJECT(val, doc, estimated_base_fee, estimated_base_fee);
INSERT_INTO_JSON_OBJECT(val, doc, fee_mask, fee_mask);
INSERT_INTO_JSON_OBJECT(val, doc, size_scale, size_scale);
@@ -867,7 +797,6 @@ void GetFeeEstimate::Response::fromJson(rapidjson::Value& val)
rapidjson::Value GetOutputDistribution::Request::toJson(rapidjson::Document& doc) const
{
auto val = Message::toJson(doc);
- auto& al = doc.GetAllocator();
INSERT_INTO_JSON_OBJECT(val, doc, amounts, amounts);
INSERT_INTO_JSON_OBJECT(val, doc, from_height, from_height);
@@ -888,7 +817,6 @@ void GetOutputDistribution::Request::fromJson(rapidjson::Value& val)
rapidjson::Value GetOutputDistribution::Response::toJson(rapidjson::Document& doc) const
{
auto val = Message::toJson(doc);
- auto& al = doc.GetAllocator();
INSERT_INTO_JSON_OBJECT(val, doc, status, status);
INSERT_INTO_JSON_OBJECT(val, doc, distributions, distributions);
diff --git a/src/rpc/message_data_structs.h b/src/rpc/message_data_structs.h
index 3b56aff15..e09b6749e 100644
--- a/src/rpc/message_data_structs.h
+++ b/src/rpc/message_data_structs.h
@@ -191,6 +191,7 @@ namespace rpc
uint64_t block_size_median;
uint64_t block_weight_median;
uint64_t start_time;
+ std::string version;
};
struct output_distribution
diff --git a/src/rpc/rpc_handler.cpp b/src/rpc/rpc_handler.cpp
index d4beb1928..e0a81c70f 100644
--- a/src/rpc/rpc_handler.cpp
+++ b/src/rpc/rpc_handler.cpp
@@ -26,7 +26,7 @@ namespace rpc
}
boost::optional<output_distribution_data>
- RpcHandler::get_output_distribution(core& src, std::uint64_t amount, std::uint64_t from_height, std::uint64_t to_height, bool cumulative)
+ RpcHandler::get_output_distribution(const std::function<bool(uint64_t, uint64_t, uint64_t, uint64_t&, std::vector<uint64_t>&, uint64_t&)> &f, uint64_t amount, uint64_t from_height, uint64_t to_height, bool cumulative)
{
static struct D
{
@@ -43,8 +43,25 @@ namespace rpc
std::vector<std::uint64_t> distribution;
std::uint64_t start_height, base;
- if (!src.get_output_distribution(amount, from_height, to_height, start_height, distribution, base))
- return boost::none;
+
+ // see if we can extend the cache - a common case
+ if (d.cached && amount == 0 && d.cached_from == from_height && to_height > d.cached_to)
+ {
+ std::vector<std::uint64_t> new_distribution;
+ if (!f(amount, d.cached_to + 1, to_height, start_height, new_distribution, base))
+ return boost::none;
+ distribution = d.cached_distribution;
+ distribution.reserve(distribution.size() + new_distribution.size());
+ for (const auto &e: new_distribution)
+ distribution.push_back(e);
+ start_height = d.cached_start_height;
+ base = d.cached_base;
+ }
+ else
+ {
+ if (!f(amount, from_height, to_height, start_height, distribution, base))
+ return boost::none;
+ }
if (to_height > 0 && to_height >= from_height)
{
diff --git a/src/rpc/rpc_handler.h b/src/rpc/rpc_handler.h
index 3cccef78a..e0d520408 100644
--- a/src/rpc/rpc_handler.h
+++ b/src/rpc/rpc_handler.h
@@ -56,7 +56,7 @@ class RpcHandler
virtual std::string handle(const std::string& request) = 0;
static boost::optional<output_distribution_data>
- get_output_distribution(core& src, std::uint64_t amount, std::uint64_t from_height, std::uint64_t to_height, bool cumulative);
+ get_output_distribution(const std::function<bool(uint64_t, uint64_t, uint64_t, uint64_t&, std::vector<uint64_t>&, uint64_t&)> &f, uint64_t amount, uint64_t from_height, uint64_t to_height, bool cumulative);
};
diff --git a/src/rpc/zmq_server.cpp b/src/rpc/zmq_server.cpp
index edd3e6669..a2ff76668 100644
--- a/src/rpc/zmq_server.cpp
+++ b/src/rpc/zmq_server.cpp
@@ -27,7 +27,6 @@
// THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include "zmq_server.h"
-#include <boost/chrono/chrono.hpp>
namespace cryptonote
{