diff options
Diffstat (limited to 'src/rpc/core_rpc_server.cpp')
-rw-r--r-- | src/rpc/core_rpc_server.cpp | 76 |
1 files changed, 46 insertions, 30 deletions
diff --git a/src/rpc/core_rpc_server.cpp b/src/rpc/core_rpc_server.cpp index 3645c494e..dc7b6b30f 100644 --- a/src/rpc/core_rpc_server.cpp +++ b/src/rpc/core_rpc_server.cpp @@ -47,6 +47,7 @@ using namespace epee; #include "rpc/rpc_args.h" #include "core_rpc_server_error_codes.h" #include "p2p/net_node.h" +#include "get_output_distribution_cache.h" #include "version.h" #undef MONERO_DEFAULT_LOG_CATEGORY @@ -218,18 +219,6 @@ namespace cryptonote return ss.str(); } //------------------------------------------------------------------------------------------------------------------------------ - static cryptonote::blobdata get_pruned_tx_blob(const cryptonote::blobdata &blobdata) - { - cryptonote::transaction tx; - - if (!cryptonote::parse_and_validate_tx_from_blob(blobdata, tx)) - { - MERROR("Failed to parse and validate tx from blob"); - return cryptonote::blobdata(); - } - return get_pruned_tx_blob(tx); - } - //------------------------------------------------------------------------------------------------------------------------------ bool core_rpc_server::on_get_blocks(const COMMAND_RPC_GET_BLOCKS_FAST::request& req, COMMAND_RPC_GET_BLOCKS_FAST::response& res) { PERF_TIMER(on_get_blocks); @@ -239,7 +228,7 @@ namespace cryptonote std::list<std::pair<cryptonote::blobdata, std::list<cryptonote::blobdata> > > bs; - if(!m_core.find_blockchain_supplement(req.start_height, req.block_ids, bs, res.current_height, res.start_height, COMMAND_RPC_GET_BLOCKS_FAST_MAX_COUNT)) + if(!m_core.find_blockchain_supplement(req.start_height, req.block_ids, bs, res.current_height, res.start_height, req.prune, COMMAND_RPC_GET_BLOCKS_FAST_MAX_COUNT)) { res.status = "Failed"; return false; @@ -271,10 +260,7 @@ namespace cryptonote for (std::list<cryptonote::blobdata>::iterator i = bd.second.begin(); i != bd.second.end(); ++i) { unpruned_size += i->size(); - if (req.prune) - res.blocks.back().txs.push_back(get_pruned_tx_blob(std::move(*i))); - else - res.blocks.back().txs.push_back(std::move(*i)); + res.blocks.back().txs.push_back(std::move(*i)); i->clear(); i->shrink_to_fit(); pruned_size += res.blocks.back().txs.back().size(); @@ -1233,7 +1219,7 @@ namespace cryptonote return reward; } //------------------------------------------------------------------------------------------------------------------------------ - bool core_rpc_server::fill_block_header_response(const block& blk, bool orphan_status, uint64_t height, const crypto::hash& hash, block_header_response& response) + bool core_rpc_server::fill_block_header_response(const block& blk, bool orphan_status, uint64_t height, const crypto::hash& hash, block_header_response& response, bool fill_pow_hash) { PERF_TIMER(fill_block_header_response); response.major_version = blk.major_version; @@ -1249,6 +1235,7 @@ namespace cryptonote response.reward = get_block_reward(blk); response.block_size = m_core.get_blockchain_storage().get_db().get_block_size(height); response.num_txes = blk.tx_hashes.size(); + response.pow_hash = fill_pow_hash ? string_tools::pod_to_hex(get_block_longhash(blk, height)) : ""; return true; } //------------------------------------------------------------------------------------------------------------------------------ @@ -1338,7 +1325,7 @@ namespace cryptonote error_resp.message = "Internal error: can't get last block."; return false; } - bool response_filled = fill_block_header_response(last_block, false, last_block_height, last_block_hash, res.block_header); + bool response_filled = fill_block_header_response(last_block, false, last_block_height, last_block_hash, res.block_header, req.fill_pow_hash); if (!response_filled) { error_resp.code = CORE_RPC_ERROR_CODE_INTERNAL_ERROR; @@ -1379,7 +1366,7 @@ namespace cryptonote 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, res.block_header); + bool response_filled = fill_block_header_response(blk, orphan, block_height, block_hash, res.block_header, req.fill_pow_hash); if (!response_filled) { error_resp.code = CORE_RPC_ERROR_CODE_INTERNAL_ERROR; @@ -1428,7 +1415,7 @@ namespace cryptonote return false; } res.headers.push_back(block_header_response()); - bool response_filled = fill_block_header_response(blk, false, block_height, block_hash, res.headers.back()); + bool response_filled = fill_block_header_response(blk, false, block_height, block_hash, res.headers.back(), req.fill_pow_hash); if (!response_filled) { error_resp.code = CORE_RPC_ERROR_CODE_INTERNAL_ERROR; @@ -1461,7 +1448,7 @@ namespace cryptonote error_resp.message = "Internal error: can't get block by height. Height = " + std::to_string(req.height) + '.'; return false; } - bool response_filled = fill_block_header_response(blk, false, req.height, block_hash, res.block_header); + bool response_filled = fill_block_header_response(blk, false, req.height, block_hash, res.block_header, req.fill_pow_hash); if (!response_filled) { error_resp.code = CORE_RPC_ERROR_CODE_INTERNAL_ERROR; @@ -1515,7 +1502,7 @@ namespace cryptonote 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, res.block_header); + bool response_filled = fill_block_header_response(blk, orphan, block_height, block_hash, res.block_header, req.fill_pow_hash); if (!response_filled) { error_resp.code = CORE_RPC_ERROR_CODE_INTERNAL_ERROR; @@ -2100,12 +2087,40 @@ namespace cryptonote if (d.cached && amount == 0 && d.cached_from == req.from_height && d.cached_to == req.to_height) { res.distributions.push_back({amount, d.cached_start_height, d.cached_distribution, d.cached_base}); + if (req.cumulative) + { + auto &distribution = res.distributions.back().distribution; + distribution[0] += d.cached_base; + for (size_t n = 1; n < distribution.size(); ++n) + distribution[n] += distribution[n-1]; + } continue; } + // this is a slow operation, so we have precomputed caches of common cases + bool found = false; + for (const auto &slot: get_output_distribution_cache) + { + if (slot.amount == amount && slot.from_height == req.from_height && slot.to_height == req.to_height) + { + res.distributions.push_back({amount, slot.start_height, slot.distribution, slot.base}); + found = true; + if (req.cumulative) + { + auto &distribution = res.distributions.back().distribution; + distribution[0] += slot.base; + for (size_t n = 1; n < distribution.size(); ++n) + distribution[n] += distribution[n-1]; + } + break; + } + } + if (found) + continue; + std::vector<uint64_t> distribution; uint64_t start_height, base; - if (!m_core.get_output_distribution(amount, req.from_height, start_height, distribution, base)) + if (!m_core.get_output_distribution(amount, req.from_height, req.to_height, start_height, distribution, base)) { error_resp.code = CORE_RPC_ERROR_CODE_INTERNAL_ERROR; error_resp.message = "Failed to get rct distribution"; @@ -2117,12 +2132,6 @@ namespace cryptonote if (offset <= req.to_height && req.to_height - offset + 1 < distribution.size()) distribution.resize(req.to_height - offset + 1); } - if (req.cumulative) - { - distribution[0] += base; - for (size_t n = 1; n < distribution.size(); ++n) - distribution[n] += distribution[n-1]; - } if (amount == 0) { @@ -2134,6 +2143,13 @@ namespace cryptonote d.cached = true; } + if (req.cumulative) + { + distribution[0] += base; + for (size_t n = 1; n < distribution.size(); ++n) + distribution[n] += distribution[n-1]; + } + res.distributions.push_back({amount, start_height, std::move(distribution), base}); } } |