diff options
Diffstat (limited to 'src/rpc')
-rw-r--r-- | src/rpc/core_rpc_server.cpp | 71 | ||||
-rw-r--r-- | src/rpc/core_rpc_server.h | 4 | ||||
-rw-r--r-- | src/rpc/core_rpc_server_commands_defs.h | 23 | ||||
-rw-r--r-- | src/rpc/daemon_handler.cpp | 16 | ||||
-rw-r--r-- | src/rpc/rpc_args.cpp | 3 | ||||
-rw-r--r-- | src/rpc/rpc_args.h | 2 | ||||
-rw-r--r-- | src/rpc/rpc_payment.cpp | 4 |
7 files changed, 82 insertions, 41 deletions
diff --git a/src/rpc/core_rpc_server.cpp b/src/rpc/core_rpc_server.cpp index 85ef50a57..5b79310c6 100644 --- a/src/rpc/core_rpc_server.cpp +++ b/src/rpc/core_rpc_server.cpp @@ -87,10 +87,14 @@ namespace RPCTracker(const char *rpc, tools::LoggingPerformanceTimer &timer): rpc(rpc), timer(timer) { } ~RPCTracker() { - boost::unique_lock<boost::mutex> lock(mutex); - auto &e = tracker[rpc]; - ++e.count; - e.time += timer.value(); + try + { + boost::unique_lock<boost::mutex> lock(mutex); + auto &e = tracker[rpc]; + ++e.count; + e.time += timer.value(); + } + catch (...) { /* ignore */ } } void pay(uint64_t amount) { boost::unique_lock<boost::mutex> lock(mutex); @@ -121,11 +125,16 @@ namespace return (value + quantum - 1) / quantum * quantum; } + void store_128(boost::multiprecision::uint128_t value, uint64_t &slow64, std::string &swide, uint64_t &stop64) + { + slow64 = (value & 0xffffffffffffffff).convert_to<uint64_t>(); + swide = cryptonote::hex(value); + stop64 = ((value >> 64) & 0xffffffffffffffff).convert_to<uint64_t>(); + } + void store_difficulty(cryptonote::difficulty_type difficulty, uint64_t &sdiff, std::string &swdiff, uint64_t &stop64) { - sdiff = (difficulty & 0xffffffffffffffff).convert_to<uint64_t>(); - swdiff = cryptonote::hex(difficulty); - stop64 = ((difficulty >> 64) & 0xffffffffffffffff).convert_to<uint64_t>(); + store_128(difficulty, sdiff, swdiff, stop64); } } @@ -153,6 +162,7 @@ namespace cryptonote : m_core(cr) , m_p2p(p2p) , m_was_bootstrap_ever_used(false) + , disable_rpc_ban(false) {} //------------------------------------------------------------------------------------------------------------------------------ bool core_rpc_server::set_bootstrap_daemon(const std::string &address, const std::string &username_password) @@ -232,6 +242,7 @@ namespace cryptonote const boost::program_options::variables_map& vm , const bool restricted , const std::string& port + , bool allow_rpc_payment ) { m_restricted = restricted; @@ -242,8 +253,9 @@ namespace cryptonote if (!rpc_config) return false; + disable_rpc_ban = rpc_config->disable_rpc_ban; std::string address = command_line::get_arg(vm, arg_rpc_payment_address); - if (!address.empty()) + if (!address.empty() && allow_rpc_payment) { if (!m_restricted && nettype() != FAKECHAIN) { @@ -354,7 +366,7 @@ namespace cryptonote //------------------------------------------------------------------------------------------------------------------------------ bool core_rpc_server::add_host_fail(const connection_context *ctx, unsigned int score) { - if(!ctx || !ctx->m_remote_address.is_blockable()) + if(!ctx || !ctx->m_remote_address.is_blockable() || disable_rpc_ban) return false; CRITICAL_REGION_LOCAL(m_host_fails_score_lock); @@ -539,7 +551,7 @@ namespace cryptonote CHECK_PAYMENT_SAME_TS(req, res, bs.size() * COST_PER_BLOCK); - size_t pruned_size = 0, unpruned_size = 0, ntxes = 0; + size_t size = 0, ntxes = 0; res.blocks.reserve(bs.size()); res.output_indices.reserve(bs.size()); for(auto& bd: bs) @@ -547,8 +559,7 @@ namespace cryptonote res.blocks.resize(res.blocks.size()+1); res.blocks.back().pruned = req.prune; res.blocks.back().block = bd.first.first; - pruned_size += bd.first.first.size(); - unpruned_size += bd.first.first.size(); + size += bd.first.first.size(); res.output_indices.push_back(COMMAND_RPC_GET_BLOCKS_FAST::block_output_indices()); ntxes += bd.second.size(); res.output_indices.back().indices.reserve(1 + bd.second.size()); @@ -557,11 +568,10 @@ namespace cryptonote res.blocks.back().txs.reserve(bd.second.size()); for (std::vector<std::pair<crypto::hash, cryptonote::blobdata>>::iterator i = bd.second.begin(); i != bd.second.end(); ++i) { - unpruned_size += i->second.size(); res.blocks.back().txs.push_back({std::move(i->second), crypto::null_hash}); i->second.clear(); i->second.shrink_to_fit(); - pruned_size += res.blocks.back().txs.back().blob.size(); + size += res.blocks.back().txs.back().blob.size(); } const size_t n_txes_to_lookup = bd.second.size() + (req.no_miner_tx ? 0 : 1); @@ -584,7 +594,7 @@ namespace cryptonote } } - MDEBUG("on_get_blocks: " << bs.size() << " blocks, " << ntxes << " txes, pruned size " << pruned_size << ", unpruned size " << unpruned_size); + MDEBUG("on_get_blocks: " << bs.size() << " blocks, " << ntxes << " txes, size " << size); res.status = CORE_RPC_STATUS_OK; return true; } @@ -954,18 +964,21 @@ namespace cryptonote { e.double_spend_seen = it->second.double_spend_seen; e.relayed = it->second.relayed; + e.received_timestamp = it->second.receive_time; } else { MERROR("Failed to determine pool info for " << tx_hash); e.double_spend_seen = false; e.relayed = false; + e.received_timestamp = 0; } } else { e.block_height = m_core.get_blockchain_storage().get_db().get_tx_block_height(tx_hash); e.block_timestamp = m_core.get_blockchain_storage().get_db().get_block_timestamp(e.block_height); + e.received_timestamp = 0; e.double_spend_seen = false; e.relayed = false; } @@ -1958,7 +1971,11 @@ namespace cryptonote m_was_bootstrap_ever_used = true; } - r = r && res.status == CORE_RPC_STATUS_OK; + if (r && res.status != CORE_RPC_STATUS_PAYMENT_REQUIRED && res.status != CORE_RPC_STATUS_OK) + { + MINFO("Failing RPC " << command_name << " due to peer return status " << res.status); + r = false; + } res.untrusted = true; return true; } @@ -2223,8 +2240,7 @@ namespace cryptonote //------------------------------------------------------------------------------------------------------------------------------ bool core_rpc_server::on_get_info_json(const COMMAND_RPC_GET_INFO::request& req, COMMAND_RPC_GET_INFO::response& res, epee::json_rpc::error& error_resp, const connection_context *ctx) { - on_get_info(req, res, ctx); - if (res.status != CORE_RPC_STATUS_OK) + if (!on_get_info(req, res, ctx) || res.status != CORE_RPC_STATUS_OK) { error_resp.code = CORE_RPC_ERROR_CODE_INTERNAL_ERROR; error_resp.message = res.status; @@ -2487,9 +2503,9 @@ namespace cryptonote return true; } CHECK_PAYMENT_MIN1(req, res, COST_PER_COINBASE_TX_SUM_BLOCK * req.count, false); - std::pair<uint64_t, uint64_t> amounts = m_core.get_coinbase_tx_sum(req.height, req.count); - res.emission_amount = amounts.first; - res.fee_amount = amounts.second; + std::pair<boost::multiprecision::uint128_t, boost::multiprecision::uint128_t> amounts = m_core.get_coinbase_tx_sum(req.height, req.count); + store_128(amounts.first, res.emission_amount, res.wide_emission_amount, res.emission_amount_top64); + store_128(amounts.second, res.fee_amount, res.wide_fee_amount, res.fee_amount_top64); res.status = CORE_RPC_STATUS_OK; return true; } @@ -2618,6 +2634,7 @@ namespace cryptonote { RPC_TRACKER(update); + res.update = false; if (m_core.offline()) { res.status = "Daemon is running offline"; @@ -2939,7 +2956,7 @@ namespace cryptonote RPC_TRACKER(rpc_access_info); bool r; - if (use_bootstrap_daemon_if_necessary<COMMAND_RPC_ACCESS_INFO>(invoke_http_mode::JON, "rpc_access_info", req, res, r)) + if (use_bootstrap_daemon_if_necessary<COMMAND_RPC_ACCESS_INFO>(invoke_http_mode::JON_RPC, "rpc_access_info", req, res, r)) return r; // if RPC payment is not enabled @@ -3003,6 +3020,8 @@ namespace cryptonote RPC_TRACKER(flush_cache); if (req.bad_txs) m_core.flush_bad_txs_cache(); + if (req.bad_blocks) + m_core.flush_invalid_blocks(); res.status = CORE_RPC_STATUS_OK; return true; } @@ -3011,7 +3030,7 @@ namespace cryptonote { RPC_TRACKER(rpc_access_submit_nonce); bool r; - if (use_bootstrap_daemon_if_necessary<COMMAND_RPC_ACCESS_SUBMIT_NONCE>(invoke_http_mode::JON, "rpc_access_submit_nonce", req, res, r)) + if (use_bootstrap_daemon_if_necessary<COMMAND_RPC_ACCESS_SUBMIT_NONCE>(invoke_http_mode::JON_RPC, "rpc_access_submit_nonce", req, res, r)) return r; // if RPC payment is not enabled @@ -3070,7 +3089,7 @@ namespace cryptonote RPC_TRACKER(rpc_access_pay); bool r; - if (use_bootstrap_daemon_if_necessary<COMMAND_RPC_ACCESS_PAY>(invoke_http_mode::JON, "rpc_access_pay", req, res, r)) + if (use_bootstrap_daemon_if_necessary<COMMAND_RPC_ACCESS_PAY>(invoke_http_mode::JON_RPC, "rpc_access_pay", req, res, r)) return r; // if RPC payment is not enabled @@ -3129,7 +3148,7 @@ namespace cryptonote RPC_TRACKER(rpc_access_data); bool r; - if (use_bootstrap_daemon_if_necessary<COMMAND_RPC_ACCESS_DATA>(invoke_http_mode::JON, "rpc_access_data", req, res, r)) + if (use_bootstrap_daemon_if_necessary<COMMAND_RPC_ACCESS_DATA>(invoke_http_mode::JON_RPC, "rpc_access_data", req, res, r)) return r; if (!m_rpc_payment) @@ -3157,7 +3176,7 @@ namespace cryptonote RPC_TRACKER(rpc_access_account); bool r; - if (use_bootstrap_daemon_if_necessary<COMMAND_RPC_ACCESS_ACCOUNT>(invoke_http_mode::JON, "rpc_access_account", req, res, r)) + if (use_bootstrap_daemon_if_necessary<COMMAND_RPC_ACCESS_ACCOUNT>(invoke_http_mode::JON_RPC, "rpc_access_account", req, res, r)) return r; if (!m_rpc_payment) diff --git a/src/rpc/core_rpc_server.h b/src/rpc/core_rpc_server.h index 23c611470..3b8e9c20a 100644 --- a/src/rpc/core_rpc_server.h +++ b/src/rpc/core_rpc_server.h @@ -88,7 +88,8 @@ namespace cryptonote bool init( const boost::program_options::variables_map& vm, const bool restricted, - const std::string& port + const std::string& port, + bool allow_rpc_payment ); network_type nettype() const { return m_core.get_nettype(); } @@ -285,6 +286,7 @@ private: epee::critical_section m_host_fails_score_lock; std::map<std::string, uint64_t> m_host_fails_score; std::unique_ptr<rpc_payment> m_rpc_payment; + bool disable_rpc_ban; }; } diff --git a/src/rpc/core_rpc_server_commands_defs.h b/src/rpc/core_rpc_server_commands_defs.h index 855ea854c..dbb1d4472 100644 --- a/src/rpc/core_rpc_server_commands_defs.h +++ b/src/rpc/core_rpc_server_commands_defs.h @@ -88,7 +88,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 3 -#define CORE_RPC_VERSION_MINOR 0 +#define CORE_RPC_VERSION_MINOR 1 #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) @@ -351,6 +351,7 @@ namespace cryptonote bool double_spend_seen; uint64_t block_height; uint64_t block_timestamp; + uint64_t received_timestamp; std::vector<uint64_t> output_indices; bool relayed; @@ -372,6 +373,7 @@ namespace cryptonote else { KV_SERIALIZE(relayed) + KV_SERIALIZE(received_timestamp) } END_KV_SERIALIZE_MAP() }; @@ -2021,12 +2023,20 @@ namespace cryptonote struct response_t: public rpc_access_response_base { uint64_t emission_amount; + std::string wide_emission_amount; + uint64_t emission_amount_top64; uint64_t fee_amount; + std::string wide_fee_amount; + uint64_t fee_amount_top64; BEGIN_KV_SERIALIZE_MAP() KV_SERIALIZE_PARENT(rpc_access_response_base) KV_SERIALIZE(emission_amount) + KV_SERIALIZE(wide_emission_amount) + KV_SERIALIZE(emission_amount_top64) KV_SERIALIZE(fee_amount) + KV_SERIALIZE(wide_fee_amount) + KV_SERIALIZE(fee_amount_top64) END_KV_SERIALIZE_MAP() }; typedef epee::misc_utils::struct_init<response_t> response; @@ -2556,22 +2566,23 @@ namespace cryptonote struct COMMAND_RPC_FLUSH_CACHE { - struct request_t + struct request_t: public rpc_request_base { bool bad_txs; + bool bad_blocks; BEGIN_KV_SERIALIZE_MAP() + KV_SERIALIZE_PARENT(rpc_request_base) KV_SERIALIZE_OPT(bad_txs, false) + KV_SERIALIZE_OPT(bad_blocks, false) END_KV_SERIALIZE_MAP() }; typedef epee::misc_utils::struct_init<request_t> request; - struct response_t + struct response_t: public rpc_response_base { - std::string status; - BEGIN_KV_SERIALIZE_MAP() - KV_SERIALIZE(status) + KV_SERIALIZE_PARENT(rpc_response_base) END_KV_SERIALIZE_MAP() }; typedef epee::misc_utils::struct_init<response_t> response; diff --git a/src/rpc/daemon_handler.cpp b/src/rpc/daemon_handler.cpp index 0b6cd6c7a..24800ff20 100644 --- a/src/rpc/daemon_handler.cpp +++ b/src/rpc/daemon_handler.cpp @@ -311,42 +311,42 @@ namespace rpc if (tvc.m_double_spend) { if (!res.error_details.empty()) res.error_details += " and "; - res.error_details = "double spend"; + res.error_details += "double spend"; } if (tvc.m_invalid_input) { if (!res.error_details.empty()) res.error_details += " and "; - res.error_details = "invalid input"; + res.error_details += "invalid input"; } if (tvc.m_invalid_output) { if (!res.error_details.empty()) res.error_details += " and "; - res.error_details = "invalid output"; + res.error_details += "invalid output"; } if (tvc.m_too_big) { if (!res.error_details.empty()) res.error_details += " and "; - res.error_details = "too big"; + res.error_details += "too big"; } if (tvc.m_overspend) { if (!res.error_details.empty()) res.error_details += " and "; - res.error_details = "overspend"; + res.error_details += "overspend"; } if (tvc.m_fee_too_low) { if (!res.error_details.empty()) res.error_details += " and "; - res.error_details = "fee too low"; + res.error_details += "fee too low"; } if (tvc.m_not_rct) { if (!res.error_details.empty()) res.error_details += " and "; - res.error_details = "tx is not ringct"; + res.error_details += "tx is not ringct"; } if (tvc.m_too_few_outputs) { if (!res.error_details.empty()) res.error_details += " and "; - res.error_details = "too few outputs"; + res.error_details += "too few outputs"; } if (res.error_details.empty()) { diff --git a/src/rpc/rpc_args.cpp b/src/rpc/rpc_args.cpp index 0eaa0ef0e..dcb804d3e 100644 --- a/src/rpc/rpc_args.cpp +++ b/src/rpc/rpc_args.cpp @@ -103,6 +103,7 @@ namespace cryptonote , rpc_ssl_allowed_fingerprints({"rpc-ssl-allowed-fingerprints", rpc_args::tr("List of certificate fingerprints to allow")}) , rpc_ssl_allow_chained({"rpc-ssl-allow-chained", rpc_args::tr("Allow user (via --rpc-ssl-certificates) chain certificates"), false}) , rpc_ssl_allow_any_cert({"rpc-ssl-allow-any-cert", rpc_args::tr("Allow any peer certificate"), false}) + , disable_rpc_ban({"disable-rpc-ban", rpc_args::tr("Do not ban hosts on RPC errors"), false, false}) {} const char* rpc_args::tr(const char* str) { return i18n_translate(str, "cryptonote::rpc_args"); } @@ -123,6 +124,7 @@ namespace cryptonote command_line::add_arg(desc, arg.rpc_ssl_ca_certificates); command_line::add_arg(desc, arg.rpc_ssl_allowed_fingerprints); command_line::add_arg(desc, arg.rpc_ssl_allow_chained); + command_line::add_arg(desc, arg.disable_rpc_ban); if (any_cert_option) command_line::add_arg(desc, arg.rpc_ssl_allow_any_cert); } @@ -136,6 +138,7 @@ namespace cryptonote config.bind_ipv6_address = command_line::get_arg(vm, arg.rpc_bind_ipv6_address); config.use_ipv6 = command_line::get_arg(vm, arg.rpc_use_ipv6); config.require_ipv4 = !command_line::get_arg(vm, arg.rpc_ignore_ipv4); + config.disable_rpc_ban = command_line::get_arg(vm, arg.disable_rpc_ban); if (!config.bind_ip.empty()) { // always parse IP here for error consistency diff --git a/src/rpc/rpc_args.h b/src/rpc/rpc_args.h index bdb9c70d5..ac6eb2744 100644 --- a/src/rpc/rpc_args.h +++ b/src/rpc/rpc_args.h @@ -65,6 +65,7 @@ namespace cryptonote const command_line::arg_descriptor<std::vector<std::string>> rpc_ssl_allowed_fingerprints; const command_line::arg_descriptor<bool> rpc_ssl_allow_chained; const command_line::arg_descriptor<bool> rpc_ssl_allow_any_cert; + const command_line::arg_descriptor<bool> disable_rpc_ban; }; // `allow_any_cert` bool toggles `--rpc-ssl-allow-any-cert` configuration @@ -85,5 +86,6 @@ namespace cryptonote std::vector<std::string> access_control_origins; boost::optional<tools::login> login; // currently `boost::none` if unspecified by user epee::net_utils::ssl_options_t ssl_options = epee::net_utils::ssl_support_t::e_ssl_support_enabled; + bool disable_rpc_ban = false; }; } diff --git a/src/rpc/rpc_payment.cpp b/src/rpc/rpc_payment.cpp index 0637db728..b363c27b2 100644 --- a/src/rpc/rpc_payment.cpp +++ b/src/rpc/rpc_payment.cpp @@ -59,6 +59,10 @@ namespace cryptonote { rpc_payment::client_info::client_info(): + previous_seed_height(0), + seed_height(0), + previous_seed_hash(crypto::null_hash), + seed_hash(crypto::null_hash), cookie(0), top(crypto::null_hash), previous_top(crypto::null_hash), |