diff --git a/src/simplewallet/simplewallet.cpp b/src/simplewallet/simplewallet.cpp index f59af575e50..115d3350583 100644 --- a/src/simplewallet/simplewallet.cpp +++ b/src/simplewallet/simplewallet.cpp @@ -64,7 +64,6 @@ #include "cryptonote_basic/cryptonote_format_utils.h" #include "storages/http_abstract_invoke.h" #include "rpc/core_rpc_server_commands_defs.h" -#include "rpc/rpc_payment_signature.h" #include "crypto/crypto.h" // for crypto::secret_key definition #include "mnemonics/electrum-words.h" #include "rapidjson/document.h" @@ -105,15 +104,12 @@ typedef cryptonote::simple_wallet sw; bool auto_refresh_enabled = m_auto_refresh_enabled.load(std::memory_order_relaxed); \ m_auto_refresh_enabled.store(false, std::memory_order_relaxed); \ /* stop any background refresh and other processes, and take over */ \ - m_suspend_rpc_payment_mining.store(true, std::memory_order_relaxed); \ m_wallet->stop(); \ boost::unique_lock lock(m_idle_mutex); \ m_idle_cond.notify_all(); \ epee::misc_utils::auto_scope_leave_caller scope_exit_handler = epee::misc_utils::create_scope_leave_handler([&](){ \ /* m_idle_mutex is still locked here */ \ m_auto_refresh_enabled.store(auto_refresh_enabled, std::memory_order_relaxed); \ - m_suspend_rpc_payment_mining.store(false, std::memory_order_relaxed); \ - m_rpc_payment_checker.trigger(); \ m_idle_cond.notify_one(); \ }) @@ -137,9 +133,6 @@ typedef cryptonote::simple_wallet sw; #define REFRESH_PERIOD 90 // seconds -#define CREDITS_TARGET 50000 -#define MAX_PAYMENT_DIFF 10000 -#define MIN_PAYMENT_RATE 0.01f // per hash #define MAX_MNEW_ADDRESSES 1000 #define CHECK_MULTISIG_ENABLED() \ @@ -167,7 +160,6 @@ namespace { const std::array allowed_priority_strings = {{"default", "unimportant", "normal", "elevated", "priority"}}; const auto arg_wallet_file = wallet_args::arg_wallet_file(); - const auto arg_rpc_client_secret_key = wallet_args::arg_rpc_client_secret_key(); const command_line::arg_descriptor arg_generate_new_wallet = {"generate-new-wallet", sw::tr("Generate new wallet and save it to "), ""}; const command_line::arg_descriptor arg_generate_from_device = {"generate-from-device", sw::tr("Generate new wallet from device and save it to "), ""}; const command_line::arg_descriptor arg_generate_from_view_key = {"generate-from-view-key", sw::tr("Generate incoming-only wallet from view key"), ""}; @@ -283,9 +275,6 @@ namespace const char* USAGE_NET_STATS("net_stats"); const char* USAGE_PUBLIC_NODES("public_nodes"); const char* USAGE_WELCOME("welcome"); - const char* USAGE_RPC_PAYMENT_INFO("rpc_payment_info"); - const char* USAGE_START_MINING_FOR_RPC("start_mining_for_rpc []"); - const char* USAGE_STOP_MINING_FOR_RPC("stop_mining_for_rpc"); const char* USAGE_SHOW_QR_CODE("show_qr_code []"); const char* USAGE_VERSION("version"); const char* USAGE_HELP("help [ | all]"); @@ -540,10 +529,9 @@ void simple_wallet::handle_transfer_exception(const std::exception_ptr &e, bool { std::rethrow_exception(e); } - catch (const tools::error::payment_required&) + catch (const tools::error::deprecated_rpc_access&) { - fail_msg_writer() << tr("Payment required, see the 'rpc_payment_info' command"); - m_need_payment = true; + fail_msg_writer() << tr("Daemon requires deprecated RPC payment. See https://github.com/monero-project/monero/issues/8722"); } catch (const tools::error::no_connection_to_daemon&) { @@ -1924,77 +1912,6 @@ bool simple_wallet::unset_ring(const std::vector &args) return true; } -bool simple_wallet::rpc_payment_info(const std::vector &args) -{ - if (!try_connect_to_daemon()) - return true; - - LOCK_IDLE_SCOPE(); - - try - { - bool payment_required; - uint64_t credits, diff, credits_per_hash_found, height, seed_height; - uint32_t cookie; - std::string hashing_blob; - crypto::hash seed_hash, next_seed_hash; - crypto::public_key pkey; - crypto::secret_key_to_public_key(m_wallet->get_rpc_client_secret_key(), pkey); - message_writer() << tr("RPC client ID: ") << pkey; - message_writer() << tr("RPC client secret key: ") << m_wallet->get_rpc_client_secret_key(); - if (!m_wallet->get_rpc_payment_info(false, payment_required, credits, diff, credits_per_hash_found, hashing_blob, height, seed_height, seed_hash, next_seed_hash, cookie)) - { - fail_msg_writer() << tr("Failed to query daemon"); - return true; - } - if (payment_required) - { - uint64_t target = m_wallet->credits_target(); - if (target == 0) - target = CREDITS_TARGET; - message_writer() << tr("Using daemon: ") << m_wallet->get_daemon_address(); - message_writer() << tr("Payments required for node use, current credits: ") << credits; - message_writer() << tr("Credits target: ") << target; - uint64_t expected, discrepancy; - m_wallet->credit_report(expected, discrepancy); - message_writer() << tr("Credits spent this session: ") << expected; - if (expected) - message_writer() << tr("Credit discrepancy this session: ") << discrepancy << " (" << 100.0f * discrepancy / expected << "%)"; - float cph = credits_per_hash_found / (float)diff; - message_writer() << tr("Difficulty: ") << diff << ", " << credits_per_hash_found << " " << tr("credits per hash found, ") << cph << " " << tr("credits/hash"); - const boost::posix_time::ptime now = boost::posix_time::microsec_clock::universal_time(); - bool mining = (now - m_last_rpc_payment_mining_time).total_microseconds() < 1000000; - if (mining) - { - float hash_rate = m_rpc_payment_hash_rate; - if (hash_rate > 0) - { - message_writer() << (boost::format(tr("Mining for payment at %.1f H/s")) % hash_rate).str(); - if (credits < target) - { - std::chrono::seconds seconds((unsigned)((target - credits) / cph / hash_rate)); - std::string target_string = get_human_readable_timespan(seconds); - message_writer() << (boost::format(tr("Estimated time till %u credits target mined: %s")) % target % target_string).str(); - } - } - else - message_writer() << tr("Mining for payment"); - } - else - message_writer() << tr("Not mining"); - } - else - message_writer() << tr("No payment needed for node use"); - } - catch (const std::exception& e) - { - LOG_ERROR("unexpected error: " << e.what()); - fail_msg_writer() << tr("unexpected error: ") << e.what(); - } - - return true; -} - bool simple_wallet::blackball(const std::vector &args) { uint64_t amount = std::numeric_limits::max(), offset, num_offsets; @@ -2242,31 +2159,19 @@ bool simple_wallet::public_nodes(const std::vector &args) try { auto nodes = m_wallet->get_public_nodes(false); - m_claimed_cph.clear(); if (nodes.empty()) { fail_msg_writer() << tr("No known public nodes"); return true; } - std::sort(nodes.begin(), nodes.end(), [](const public_node &node0, const public_node &node1) { - if (node0.rpc_credits_per_hash && node1.rpc_credits_per_hash == 0) - return true; - if (node0.rpc_credits_per_hash && node1.rpc_credits_per_hash) - return node0.rpc_credits_per_hash < node1.rpc_credits_per_hash; - return false; - }); const uint64_t now = time(NULL); - message_writer() << boost::format("%32s %12s %16s") % tr("address") % tr("credits/hash") % tr("last_seen"); + message_writer() << boost::format("%32s %16s") % tr("address") % tr("last_seen"); for (const auto &node: nodes) { - const float cph = node.rpc_credits_per_hash / RPC_CREDITS_PER_HASH_SCALE; - char cphs[9]; - snprintf(cphs, sizeof(cphs), "%.3f", cph); const std::string last_seen = node.last_seen == 0 ? tr("never") : get_human_readable_timespan(std::chrono::seconds(now - node.last_seen)); std::string host = node.host + ":" + std::to_string(node.rpc_port); - message_writer() << boost::format("%32s %12s %16s") % host % cphs % last_seen; - m_claimed_cph[host] = node.rpc_credits_per_hash; + message_writer() << boost::format("%32s %16s") % host % last_seen; } } catch (const std::exception &e) @@ -2341,68 +2246,6 @@ bool simple_wallet::cold_sign_tx(const std::vector& return m_wallet->import_key_images(exported_txs, 0, true); } -bool simple_wallet::start_mining_for_rpc(const std::vector &args) -{ - if (!try_connect_to_daemon()) - return true; - - bool ok = true; - if(args.size() >= 1) - { - uint16_t num = 0; - ok = string_tools::get_xtype_from_string(num, args[0]); - m_rpc_payment_threads = num; - } - else - { - m_rpc_payment_threads = 0; - } - - if (!ok) - { - PRINT_USAGE(USAGE_START_MINING_FOR_RPC); - return true; - } - - LOCK_IDLE_SCOPE(); - - bool payment_required; - uint64_t credits, diff, credits_per_hash_found, height, seed_height; - uint32_t cookie; - std::string hashing_blob; - crypto::hash seed_hash, next_seed_hash; - if (!m_wallet->get_rpc_payment_info(true, payment_required, credits, diff, credits_per_hash_found, hashing_blob, height, seed_height, seed_hash, next_seed_hash, cookie)) - { - fail_msg_writer() << tr("Failed to query daemon"); - return true; - } - if (!payment_required) - { - fail_msg_writer() << tr("Daemon does not require payment for RPC access"); - return true; - } - - m_rpc_payment_mining_requested = true; - m_rpc_payment_checker.trigger(); - const float cph = credits_per_hash_found / (float)diff; - bool low = (diff > MAX_PAYMENT_DIFF || cph < MIN_PAYMENT_RATE); - success_msg_writer() << (boost::format(tr("Starting mining for RPC access: diff %llu, %f credits/hash%s")) % diff % cph % (low ? " - this is low" : "")).str(); - success_msg_writer() << tr("Run stop_mining_for_rpc to stop"); - return true; -} - -bool simple_wallet::stop_mining_for_rpc(const std::vector &args) -{ - if (!try_connect_to_daemon()) - return true; - - LOCK_IDLE_SCOPE(); - m_rpc_payment_mining_requested = false; - m_last_rpc_payment_mining_time = boost::posix_time::ptime(boost::gregorian::date(1970, 1, 1)); - m_rpc_payment_hash_rate = -1.0f; - return true; -} - bool simple_wallet::show_qr_code(const std::vector &args) { uint32_t subaddress_index = 0; @@ -2812,53 +2655,6 @@ bool simple_wallet::set_segregate_pre_fork_outputs(const std::vector &args/* = std::vector()*/) -{ - const auto pwd_container = get_and_verify_password(); - if (pwd_container) - { - parse_bool_and_use(args[1], [&](bool r) { - m_wallet->persistent_rpc_client_id(r); - m_wallet->rewrite(m_wallet_file, pwd_container->password()); - }); - } - return true; -} - -bool simple_wallet::set_auto_mine_for_rpc_payment_threshold(const std::vector &args/* = std::vector()*/) -{ - const auto pwd_container = get_and_verify_password(); - if (pwd_container) - { - float threshold; - if (!epee::string_tools::get_xtype_from_string(threshold, args[1]) || threshold < 0.0f) - { - fail_msg_writer() << tr("Invalid threshold"); - return true; - } - m_wallet->auto_mine_for_rpc_payment_threshold(threshold); - m_wallet->rewrite(m_wallet_file, pwd_container->password()); - } - return true; -} - -bool simple_wallet::set_credits_target(const std::vector &args/* = std::vector()*/) -{ - const auto pwd_container = get_and_verify_password(); - if (pwd_container) - { - uint64_t target; - if (!epee::string_tools::get_xtype_from_string(target, args[1])) - { - fail_msg_writer() << tr("Invalid target"); - return true; - } - m_wallet->credits_target(target); - m_wallet->rewrite(m_wallet_file, pwd_container->password()); - } - return true; -} - bool simple_wallet::set_key_reuse_mitigation2(const std::vector &args/* = std::vector()*/) { const auto pwd_container = get_and_verify_password(); @@ -3246,12 +3042,6 @@ simple_wallet::simple_wallet() , m_last_activity_time(time(NULL)) , m_locked(false) , m_in_command(false) - , m_need_payment(false) - , m_rpc_payment_mining_requested(false) - , m_last_rpc_payment_mining_time(boost::gregorian::date(1970, 1, 1)) - , m_daemon_rpc_payment_message_displayed(false) - , m_rpc_payment_hash_rate(-1.0f) - , m_suspend_rpc_payment_mining(false) { m_cmd_binder.set_handler("start_mining", boost::bind(&simple_wallet::on_command, this, &simple_wallet::start_mining, _1), @@ -3433,12 +3223,6 @@ simple_wallet::simple_wallet() " Device name for hardware wallet.\n " "export-format <\"binary\"|\"ascii\">\n " " Save all exported files as binary (cannot be copied and pasted) or ascii (can be).\n " - "persistent-rpc-client-id <1|0>\n " - " Whether to keep using the same client id for RPC payment over wallet restarts.\n" - "auto-mine-for-rpc-payment-threshold \n " - " Whether to automatically start mining for RPC payment if the daemon requires it.\n" - "credits-target \n" - " The RPC payment credits balance to target (0 for default).\n " "show-wallet-name-when-locked <1|0>\n " " Set this if you would like to display the wallet name when locked.\n " "enable-multisig-experimental <1|0>\n " @@ -3759,18 +3543,6 @@ simple_wallet::simple_wallet() boost::bind(&simple_wallet::on_command, this, &simple_wallet::version, _1), tr(USAGE_VERSION), tr("Returns version information")); - m_cmd_binder.set_handler("rpc_payment_info", - boost::bind(&simple_wallet::on_command, this, &simple_wallet::rpc_payment_info, _1), - tr(USAGE_RPC_PAYMENT_INFO), - tr("Get info about RPC payments to current node")); - m_cmd_binder.set_handler("start_mining_for_rpc", - boost::bind(&simple_wallet::on_command, this, &simple_wallet::start_mining_for_rpc, _1), - tr(USAGE_START_MINING_FOR_RPC), - tr("Start mining to pay for RPC access")); - m_cmd_binder.set_handler("stop_mining_for_rpc", - boost::bind(&simple_wallet::on_command, this, &simple_wallet::stop_mining_for_rpc, _1), - tr(USAGE_STOP_MINING_FOR_RPC), - tr("Stop mining to pay for RPC access")); m_cmd_binder.set_handler("show_qr_code", boost::bind(&simple_wallet::on_command, this, &simple_wallet::show_qr_code, _1), tr(USAGE_SHOW_QR_CODE), @@ -3854,9 +3626,6 @@ bool simple_wallet::set_variable(const std::vector &args) << " (disabled on Windows)" #endif ; - success_msg_writer() << "persistent-rpc-client-id = " << m_wallet->persistent_rpc_client_id(); - success_msg_writer() << "auto-mine-for-rpc-payment-threshold = " << m_wallet->auto_mine_for_rpc_payment_threshold(); - success_msg_writer() << "credits-target = " << m_wallet->credits_target(); success_msg_writer() << "load-deprecated-formats = " << m_wallet->load_deprecated_formats(); success_msg_writer() << "enable-multisig-experimental = " << m_wallet->is_multisig_enabled(); return true; @@ -3922,9 +3691,6 @@ bool simple_wallet::set_variable(const std::vector &args) CHECK_SIMPLE_VARIABLE("device-name", set_device_name, tr("")); CHECK_SIMPLE_VARIABLE("export-format", set_export_format, tr("\"binary\" or \"ascii\"")); CHECK_SIMPLE_VARIABLE("load-deprecated-formats", set_load_deprecated_formats, tr("0 or 1")); - CHECK_SIMPLE_VARIABLE("persistent-rpc-client-id", set_persistent_rpc_client_id, tr("0 or 1")); - CHECK_SIMPLE_VARIABLE("auto-mine-for-rpc-payment-threshold", set_auto_mine_for_rpc_payment_threshold, tr("floating point >= 0")); - CHECK_SIMPLE_VARIABLE("credits-target", set_credits_target, tr("unsigned integer")); CHECK_SIMPLE_VARIABLE("enable-multisig-experimental", set_enable_multisig, tr("0 or 1")); } fail_msg_writer() << tr("set: unrecognized argument(s)"); @@ -4694,17 +4460,6 @@ bool simple_wallet::init(const boost::program_options::variables_map& vm) return false; } - if (!command_line::is_arg_defaulted(vm, arg_rpc_client_secret_key)) - { - crypto::secret_key rpc_client_secret_key; - if (!epee::string_tools::hex_to_pod(command_line::get_arg(vm, arg_rpc_client_secret_key), rpc_client_secret_key)) - { - fail_msg_writer() << tr("RPC client secret key should be 32 byte in hex format"); - return false; - } - m_wallet->set_rpc_client_secret_key(rpc_client_secret_key); - } - if (!m_wallet->is_trusted_daemon()) { message_writer(console_color_red, true) << (boost::format(tr("Warning: using an untrusted daemon at %s")) % m_wallet->get_daemon_address()).str(); @@ -5243,7 +4998,6 @@ bool simple_wallet::close_wallet() if (m_idle_run.load(std::memory_order_relaxed)) { m_idle_run.store(false, std::memory_order_relaxed); - m_suspend_rpc_payment_mining.store(true, std::memory_order_relaxed); m_wallet->stop(); { boost::unique_lock lock(m_idle_mutex); @@ -5519,40 +5273,6 @@ bool simple_wallet::stop_mining(const std::vector& args) return true; } //---------------------------------------------------------------------------------------------------- -bool simple_wallet::check_daemon_rpc_prices(const std::string &daemon_url, uint32_t &actual_cph, uint32_t &claimed_cph) -{ - try - { - auto i = m_claimed_cph.find(daemon_url); - if (i == m_claimed_cph.end()) - return false; - - claimed_cph = m_claimed_cph[daemon_url]; - bool payment_required; - uint64_t credits, diff, credits_per_hash_found, height, seed_height; - uint32_t cookie; - cryptonote::blobdata hashing_blob; - crypto::hash seed_hash, next_seed_hash; - if (m_wallet->get_rpc_payment_info(false, payment_required, credits, diff, credits_per_hash_found, hashing_blob, height, seed_height, seed_hash, next_seed_hash, cookie) && payment_required) - { - actual_cph = RPC_CREDITS_PER_HASH_SCALE * (credits_per_hash_found / (float)diff); - return true; - } - else - { - fail_msg_writer() << tr("Error checking daemon RPC access prices"); - } - } - catch (const std::exception &e) - { - // can't check - fail_msg_writer() << tr("Error checking daemon RPC access prices: ") << e.what(); - return false; - } - // no record found for this daemon - return false; -} -//---------------------------------------------------------------------------------------------------- bool simple_wallet::set_daemon(const std::vector& args) { std::string daemon_url; @@ -5647,20 +5367,6 @@ bool simple_wallet::set_daemon(const std::vector& args) } success_msg_writer() << boost::format("Daemon set to %s, %s") % daemon_url % (m_wallet->is_trusted_daemon() ? tr("trusted") : tr("untrusted")); - - // check whether the daemon's prices match the claim, and disconnect if not, to disincentivize daemons lying - uint32_t actual_cph, claimed_cph; - if (check_daemon_rpc_prices(daemon_url, actual_cph, claimed_cph)) - { - if (actual_cph < claimed_cph) - { - fail_msg_writer() << tr("Daemon RPC credits/hash is less than was claimed. Either this daemon is cheating, or it changed its setup recently."); - fail_msg_writer() << tr("Claimed: ") << claimed_cph / (float)RPC_CREDITS_PER_HASH_SCALE; - fail_msg_writer() << tr("Actual: ") << actual_cph / (float)RPC_CREDITS_PER_HASH_SCALE; - } - } - - m_daemon_rpc_payment_message_displayed = false; } else { fail_msg_writer() << tr("This does not seem to be a valid daemon URL."); } @@ -5924,10 +5630,9 @@ bool simple_wallet::refresh_main(uint64_t start_height, enum ResetType reset, bo { ss << tr("no connection to daemon. Please make sure daemon is running."); } - catch (const tools::error::payment_required&) + catch (const tools::error::deprecated_rpc_access&) { - ss << tr("payment required."); - m_need_payment = true; + ss << tr("Daemon requires deprecated RPC payment. See https://github.com/monero-project/monero/issues/8722"); } catch (const tools::error::wallet_rpc_error& e) { @@ -6263,10 +5968,9 @@ bool simple_wallet::rescan_spent(const std::vector &args) { fail_msg_writer() << tr("no connection to daemon. Please make sure daemon is running."); } - catch (const tools::error::payment_required&) + catch (const tools::error::deprecated_rpc_access&) { - fail_msg_writer() << tr("payment required."); - m_need_payment = true; + fail_msg_writer() << tr("Daemon requires deprecated RPC payment. See https://github.com/monero-project/monero/issues/8722"); } catch (const tools::error::is_key_image_spent_error&) { @@ -6377,7 +6081,6 @@ bool simple_wallet::process_ring_members(const std::vectorget_rpc_client_secret_key()); bool r = m_wallet->invoke_http_bin("/get_outs.bin", req, res); err = interpret_rpc_response(r, res.status); if (!err.empty()) @@ -9273,7 +8976,6 @@ void simple_wallet::wallet_idle_thread() #endif m_refresh_checker.do_call(boost::bind(&simple_wallet::check_refresh, this)); m_mms_checker.do_call(boost::bind(&simple_wallet::check_mms, this)); - m_rpc_payment_checker.do_call(boost::bind(&simple_wallet::check_rpc_payment, this)); if (!m_idle_run.load(std::memory_order_relaxed)) break; @@ -9333,78 +9035,6 @@ bool simple_wallet::check_mms() return true; } //---------------------------------------------------------------------------------------------------- -bool simple_wallet::check_rpc_payment() -{ - if (!m_rpc_payment_mining_requested && m_wallet->auto_mine_for_rpc_payment_threshold() == 0.0f) - return true; - - uint64_t target = m_wallet->credits_target(); - if (target == 0) - target = CREDITS_TARGET; - if (m_rpc_payment_mining_requested) - target = std::numeric_limits::max(); - bool need_payment = m_need_payment || m_rpc_payment_mining_requested || (m_wallet->credits() < target && m_wallet->daemon_requires_payment()); - if (need_payment) - { - const boost::posix_time::ptime start_time = boost::posix_time::microsec_clock::universal_time(); - auto startfunc = [this](uint64_t diff, uint64_t credits_per_hash_found) - { - const float cph = credits_per_hash_found / (float)diff; - bool low = (diff > MAX_PAYMENT_DIFF || cph < MIN_PAYMENT_RATE); - if (credits_per_hash_found > 0 && cph >= m_wallet->auto_mine_for_rpc_payment_threshold()) - { - MINFO(std::to_string(cph) << " credits per hash is >= our threshold (" << m_wallet->auto_mine_for_rpc_payment_threshold() << "), starting mining"); - return true; - } - else if (m_rpc_payment_mining_requested) - { - MINFO("Mining for RPC payment was requested, starting mining"); - return true; - } - else - { - if (!m_daemon_rpc_payment_message_displayed) - { - success_msg_writer() << boost::format(tr("Daemon requests payment at diff %llu, with %f credits/hash%s. Run start_mining_for_rpc to start mining to pay for RPC access, or use another daemon")) % - diff % cph % (low ? " - this is low" : ""); - m_cmd_binder.print_prompt(); - m_daemon_rpc_payment_message_displayed = true; - } - return false; - } - }; - auto contfunc = [&,this](unsigned n_hashes) - { - if (m_suspend_rpc_payment_mining.load(std::memory_order_relaxed)) - return false; - const boost::posix_time::ptime now = boost::posix_time::microsec_clock::universal_time(); - m_last_rpc_payment_mining_time = now; - if ((now - start_time).total_microseconds() >= 2 * 1000000) - m_rpc_payment_hash_rate = n_hashes / (float)((now - start_time).total_seconds()); - if ((now - start_time).total_microseconds() >= REFRESH_PERIOD * 1000000) - return false; - return true; - }; - auto foundfunc = [this, target](uint64_t credits) - { - m_need_payment = false; - return credits < target; - }; - auto errorfunc = [this](const std::string &error) - { - fail_msg_writer() << tr("Error mining to daemon: ") << error; - m_cmd_binder.print_prompt(); - }; - bool ret = m_wallet->search_for_rpc_payment(target, m_rpc_payment_threads, startfunc, contfunc, foundfunc, errorfunc); - if (!ret) - { - fail_msg_writer() << tr("Failed to start mining for RPC payment"); - m_cmd_binder.print_prompt(); - } - } - return true; -} -//---------------------------------------------------------------------------------------------------- std::string simple_wallet::get_prompt() const { if (m_locked) @@ -10658,7 +10288,6 @@ int main(int argc, char* argv[]) command_line::add_arg(desc_params, arg_create_address_file); command_line::add_arg(desc_params, arg_subaddress_lookahead); command_line::add_arg(desc_params, arg_use_english_language_names); - command_line::add_arg(desc_params, arg_rpc_client_secret_key); po::positional_options_description positional_options; positional_options.add(arg_command.name, -1); diff --git a/src/simplewallet/simplewallet.h b/src/simplewallet/simplewallet.h index 7c45d45e826..f616a87b5dc 100644 --- a/src/simplewallet/simplewallet.h +++ b/src/simplewallet/simplewallet.h @@ -154,9 +154,6 @@ namespace cryptonote bool set_export_format(const std::vector &args = std::vector()); bool set_load_deprecated_formats(const std::vector &args = std::vector()); bool set_enable_multisig(const std::vector &args = std::vector()); - bool set_persistent_rpc_client_id(const std::vector &args = std::vector()); - bool set_auto_mine_for_rpc_payment_threshold(const std::vector &args = std::vector()); - bool set_credits_target(const std::vector &args = std::vector()); bool help(const std::vector &args = std::vector()); bool apropos(const std::vector &args); bool scan_tx(const std::vector &args); @@ -258,9 +255,6 @@ namespace cryptonote bool thaw(const std::vector& args); bool frozen(const std::vector& args); bool lock(const std::vector& args); - bool rpc_payment_info(const std::vector &args); - bool start_mining_for_rpc(const std::vector &args); - bool stop_mining_for_rpc(const std::vector &args); bool show_qr_code(const std::vector &args); bool net_stats(const std::vector& args); bool public_nodes(const std::vector& args); @@ -338,7 +332,6 @@ namespace cryptonote bool check_inactivity(); bool check_refresh(); bool check_mms(); - bool check_rpc_payment(); void handle_transfer_exception(const std::exception_ptr &e, bool trusted_daemon); @@ -458,17 +451,6 @@ namespace cryptonote epee::math_helper::once_a_time_seconds<1> m_inactivity_checker; epee::math_helper::once_a_time_seconds_range> m_refresh_checker; epee::math_helper::once_a_time_seconds_range> m_mms_checker; - epee::math_helper::once_a_time_seconds_range> m_rpc_payment_checker; - - std::atomic m_need_payment; - boost::posix_time::ptime m_last_rpc_payment_mining_time; - bool m_rpc_payment_mining_requested; - uint32_t m_rpc_payment_threads = 0; - bool m_daemon_rpc_payment_message_displayed; - float m_rpc_payment_hash_rate; - std::atomic m_suspend_rpc_payment_mining; - - std::unordered_map m_claimed_cph; // MMS mms::message_store& get_message_store() const { return m_wallet->get_message_store(); }; diff --git a/src/wallet/CMakeLists.txt b/src/wallet/CMakeLists.txt index 6095f99d52d..ee3f00f9f53 100644 --- a/src/wallet/CMakeLists.txt +++ b/src/wallet/CMakeLists.txt @@ -37,7 +37,6 @@ set(wallet_sources node_rpc_proxy.cpp message_store.cpp message_transporter.cpp - wallet_rpc_payments.cpp ) monero_find_all_headers(wallet_private_headers "${CMAKE_CURRENT_SOURCE_DIR}") diff --git a/src/wallet/node_rpc_proxy.cpp b/src/wallet/node_rpc_proxy.cpp index 0a9ea8f7bab..36e5711b5c0 100644 --- a/src/wallet/node_rpc_proxy.cpp +++ b/src/wallet/node_rpc_proxy.cpp @@ -28,8 +28,6 @@ #include "node_rpc_proxy.h" #include "rpc/core_rpc_server_commands_defs.h" -#include "rpc/rpc_payment_signature.h" -#include "rpc/rpc_payment_costs.h" #include "storages/http_abstract_invoke.h" #include @@ -37,7 +35,6 @@ #define RETURN_ON_RPC_RESPONSE_ERROR(r, error, res, method) \ do { \ CHECK_AND_ASSERT_MES(error.code == 0, error.message, error.message); \ - handle_payment_changes(res, std::integral_constant::Has>()); \ CHECK_AND_ASSERT_MES(r, std::string("Failed to connect to daemon"), "Failed to connect to daemon"); \ /* empty string -> not connection */ \ CHECK_AND_ASSERT_MES(!res.status.empty(), res.status, "No connection to daemon"); \ @@ -53,9 +50,8 @@ namespace tools static const std::chrono::seconds rpc_timeout = std::chrono::minutes(3) + std::chrono::seconds(30); -NodeRPCProxy::NodeRPCProxy(epee::net_utils::http::abstract_http_client &http_client, rpc_payment_state_t &rpc_payment_state, boost::recursive_mutex &mutex) +NodeRPCProxy::NodeRPCProxy(epee::net_utils::http::abstract_http_client &http_client, boost::recursive_mutex &mutex) : m_http_client(http_client) - , m_rpc_payment_state(rpc_payment_state) , m_daemon_rpc_mutex(mutex) , m_offline(false) { @@ -77,16 +73,8 @@ void NodeRPCProxy::invalidate() m_block_weight_limit = 0; m_adjusted_time = 0; m_get_info_time = 0; - m_rpc_payment_info_time = 0; - m_rpc_payment_seed_height = 0; - m_rpc_payment_seed_hash = crypto::null_hash; - m_rpc_payment_next_seed_hash = crypto::null_hash; m_height_time = 0; m_target_height_time = 0; - m_rpc_payment_diff = 0; - m_rpc_payment_credits_per_hash_found = 0; - m_rpc_payment_height = 0; - m_rpc_payment_cookie = 0; m_daemon_hard_forks.clear(); } @@ -147,11 +135,8 @@ boost::optional NodeRPCProxy::get_info() { const boost::lock_guard lock{m_daemon_rpc_mutex}; - uint64_t pre_call_credits = m_rpc_payment_state.credits; - req_t.client = cryptonote::make_rpc_payment_signature(m_client_id_secret_key); bool r = net_utils::invoke_http_json_rpc("/json_rpc", "get_info", req_t, resp_t, m_http_client, rpc_timeout); RETURN_ON_RPC_RESPONSE_ERROR(r, epee::json_rpc::error{}, resp_t, "get_info"); - check_rpc_cost(m_rpc_payment_state, "get_info", resp_t.credits, pre_call_credits, COST_PER_GET_INFO); } m_height = resp_t.height; @@ -227,11 +212,8 @@ boost::optional NodeRPCProxy::get_earliest_height(uint8_t version, { const boost::lock_guard lock{m_daemon_rpc_mutex}; - uint64_t pre_call_credits = m_rpc_payment_state.credits; - req_t.client = cryptonote::make_rpc_payment_signature(m_client_id_secret_key); bool r = net_utils::invoke_http_json_rpc("/json_rpc", "hard_fork_info", req_t, resp_t, m_http_client, rpc_timeout); RETURN_ON_RPC_RESPONSE_ERROR(r, epee::json_rpc::error{}, resp_t, "hard_fork_info"); - check_rpc_cost(m_rpc_payment_state, "hard_fork_info", resp_t.credits, pre_call_credits, COST_PER_HARD_FORK_INFO); } m_earliest_height[version] = resp_t.earliest_height; @@ -259,11 +241,8 @@ boost::optional NodeRPCProxy::get_dynamic_base_fee_estimate_2021_sc { const boost::lock_guard lock{m_daemon_rpc_mutex}; - uint64_t pre_call_credits = m_rpc_payment_state.credits; - req_t.client = cryptonote::make_rpc_payment_signature(m_client_id_secret_key); bool r = net_utils::invoke_http_json_rpc("/json_rpc", "get_fee_estimate", req_t, resp_t, m_http_client, rpc_timeout); RETURN_ON_RPC_RESPONSE_ERROR(r, epee::json_rpc::error{}, resp_t, "get_fee_estimate"); - check_rpc_cost(m_rpc_payment_state, "get_fee_estimate", resp_t.credits, pre_call_credits, COST_PER_FEE_ESTIMATE); } m_dynamic_base_fee_estimate = resp_t.fee; @@ -305,11 +284,8 @@ boost::optional NodeRPCProxy::get_fee_quantization_mask(uint64_t &f { const boost::lock_guard lock{m_daemon_rpc_mutex}; - uint64_t pre_call_credits = m_rpc_payment_state.credits; - req_t.client = cryptonote::make_rpc_payment_signature(m_client_id_secret_key); bool r = net_utils::invoke_http_json_rpc("/json_rpc", "get_fee_estimate", req_t, resp_t, m_http_client, rpc_timeout); RETURN_ON_RPC_RESPONSE_ERROR(r, epee::json_rpc::error{}, resp_t, "get_fee_estimate"); - check_rpc_cost(m_rpc_payment_state, "get_fee_estimate", resp_t.credits, pre_call_credits, COST_PER_FEE_ESTIMATE); } m_dynamic_base_fee_estimate = resp_t.fee; @@ -325,71 +301,4 @@ boost::optional NodeRPCProxy::get_fee_quantization_mask(uint64_t &f } return boost::optional(); } - -boost::optional NodeRPCProxy::get_rpc_payment_info(bool mining, bool &payment_required, uint64_t &credits, uint64_t &diff, uint64_t &credits_per_hash_found, cryptonote::blobdata &blob, uint64_t &height, uint64_t &seed_height, crypto::hash &seed_hash, crypto::hash &next_seed_hash, uint32_t &cookie) -{ - const time_t now = time(NULL); - if (m_rpc_payment_state.stale || now >= m_rpc_payment_info_time + 5*60 || (mining && now >= m_rpc_payment_info_time + 10)) // re-cache every 10 seconds if mining, 5 minutes otherwise - { - cryptonote::COMMAND_RPC_ACCESS_INFO::request req_t = AUTO_VAL_INIT(req_t); - cryptonote::COMMAND_RPC_ACCESS_INFO::response resp_t = AUTO_VAL_INIT(resp_t); - - { - const boost::lock_guard lock{m_daemon_rpc_mutex}; - req_t.client = cryptonote::make_rpc_payment_signature(m_client_id_secret_key); - bool r = net_utils::invoke_http_json_rpc("/json_rpc", "rpc_access_info", req_t, resp_t, m_http_client, rpc_timeout); - RETURN_ON_RPC_RESPONSE_ERROR(r, epee::json_rpc::error{}, resp_t, "rpc_access_info"); - m_rpc_payment_state.stale = false; - } - - m_rpc_payment_diff = resp_t.diff; - m_rpc_payment_credits_per_hash_found = resp_t.credits_per_hash_found; - m_rpc_payment_height = resp_t.height; - m_rpc_payment_seed_height = resp_t.seed_height; - m_rpc_payment_cookie = resp_t.cookie; - - if (m_rpc_payment_diff == 0) - { - // If no payment required daemon doesn't give us back a hashing blob - m_rpc_payment_blob.clear(); - } - else if (!epee::string_tools::parse_hexstr_to_binbuff(resp_t.hashing_blob, m_rpc_payment_blob) || m_rpc_payment_blob.size() < 43) - { - MERROR("Invalid hashing blob: " << resp_t.hashing_blob); - return std::string("Invalid hashing blob"); - } - if (resp_t.seed_hash.empty()) - { - m_rpc_payment_seed_hash = crypto::null_hash; - } - else if (!epee::string_tools::hex_to_pod(resp_t.seed_hash, m_rpc_payment_seed_hash)) - { - MERROR("Invalid seed_hash: " << resp_t.seed_hash); - return std::string("Invalid seed hash"); - } - if (resp_t.next_seed_hash.empty()) - { - m_rpc_payment_next_seed_hash = crypto::null_hash; - } - else if (!epee::string_tools::hex_to_pod(resp_t.next_seed_hash, m_rpc_payment_next_seed_hash)) - { - MERROR("Invalid next_seed_hash: " << resp_t.next_seed_hash); - return std::string("Invalid next seed hash"); - } - m_rpc_payment_info_time = now; - } - - payment_required = m_rpc_payment_diff > 0; - credits = m_rpc_payment_state.credits; - diff = m_rpc_payment_diff; - credits_per_hash_found = m_rpc_payment_credits_per_hash_found; - blob = m_rpc_payment_blob; - height = m_rpc_payment_height; - seed_height = m_rpc_payment_seed_height; - seed_hash = m_rpc_payment_seed_hash; - next_seed_hash = m_rpc_payment_next_seed_hash; - cookie = m_rpc_payment_cookie; - return boost::none; -} - } diff --git a/src/wallet/node_rpc_proxy.h b/src/wallet/node_rpc_proxy.h index e320565aca4..bbb81ff06ac 100644 --- a/src/wallet/node_rpc_proxy.h +++ b/src/wallet/node_rpc_proxy.h @@ -34,7 +34,6 @@ #include "include_base_utils.h" #include "net/abstract_http_client.h" #include "rpc/core_rpc_server_commands_defs.h" -#include "wallet_rpc_helpers.h" namespace tools { @@ -42,9 +41,8 @@ namespace tools class NodeRPCProxy { public: - NodeRPCProxy(epee::net_utils::http::abstract_http_client &http_client, rpc_payment_state_t &rpc_payment_state, boost::recursive_mutex &mutex); + NodeRPCProxy(epee::net_utils::http::abstract_http_client &http_client, boost::recursive_mutex &mutex); - void set_client_secret_key(const crypto::secret_key &skey) { m_client_id_secret_key = skey; } void invalidate(); void set_offline(bool offline) { m_offline = offline; } @@ -58,27 +56,12 @@ class NodeRPCProxy boost::optional get_dynamic_base_fee_estimate(uint64_t grace_blocks, uint64_t &fee); boost::optional get_dynamic_base_fee_estimate_2021_scaling(uint64_t grace_blocks, std::vector &fees); boost::optional get_fee_quantization_mask(uint64_t &fee_quantization_mask); - boost::optional get_rpc_payment_info(bool mining, bool &payment_required, uint64_t &credits, uint64_t &diff, uint64_t &credits_per_hash_found, cryptonote::blobdata &blob, uint64_t &height, uint64_t &seed_height, crypto::hash &seed_hash, crypto::hash &next_seed_hash, uint32_t &cookie); - -private: - template void handle_payment_changes(const T &res, std::true_type) { - if (res.status == CORE_RPC_STATUS_OK || res.status == CORE_RPC_STATUS_PAYMENT_REQUIRED) - m_rpc_payment_state.credits = res.credits; - if (res.top_hash != m_rpc_payment_state.top_hash) - { - m_rpc_payment_state.top_hash = res.top_hash; - m_rpc_payment_state.stale = true; - } - } - template void handle_payment_changes(const T &res, std::false_type) {} private: boost::optional get_info(); epee::net_utils::http::abstract_http_client &m_http_client; - rpc_payment_state_t &m_rpc_payment_state; boost::recursive_mutex &m_daemon_rpc_mutex; - crypto::secret_key m_client_id_secret_key; bool m_offline; uint64_t m_height; @@ -93,15 +76,6 @@ class NodeRPCProxy uint64_t m_target_height; uint64_t m_block_weight_limit; time_t m_get_info_time; - time_t m_rpc_payment_info_time; - uint64_t m_rpc_payment_diff; - uint64_t m_rpc_payment_credits_per_hash_found; - cryptonote::blobdata m_rpc_payment_blob; - uint64_t m_rpc_payment_height; - uint64_t m_rpc_payment_seed_height; - crypto::hash m_rpc_payment_seed_hash; - crypto::hash m_rpc_payment_next_seed_hash; - uint32_t m_rpc_payment_cookie; time_t m_height_time; time_t m_target_height_time; std::vector> m_daemon_hard_forks; diff --git a/src/wallet/wallet2.cpp b/src/wallet/wallet2.cpp index 9e99cac8316..34cb687c150 100644 --- a/src/wallet/wallet2.cpp +++ b/src/wallet/wallet2.cpp @@ -51,15 +51,12 @@ using namespace epee; #include "cryptonote_config.h" #include "hardforks/hardforks.h" #include "cryptonote_core/tx_sanity_check.h" -#include "wallet_rpc_helpers.h" #include "wallet2.h" #include "wallet_args.h" #include "cryptonote_basic/cryptonote_format_utils.h" #include "net/parse.h" #include "rpc/core_rpc_server_commands_defs.h" #include "rpc/core_rpc_server_error_codes.h" -#include "rpc/rpc_payment_signature.h" -#include "rpc/rpc_payment_costs.h" #include "misc_language.h" #include "cryptonote_basic/cryptonote_basic_impl.h" #include "multisig/multisig.h" @@ -1191,15 +1188,13 @@ wallet2::wallet2(network_type nettype, uint64_t kdf_rounds, bool unattended, std m_show_wallet_name_when_locked(false), m_inactivity_lock_timeout(DEFAULT_INACTIVITY_LOCK_TIMEOUT), m_setup_background_mining(BackgroundMiningMaybe), - m_persistent_rpc_client_id(false), - m_auto_mine_for_rpc_payment_threshold(-1.0f), m_is_initialized(false), m_kdf_rounds(kdf_rounds), is_old_file_format(false), m_watch_only(false), m_multisig(false), m_multisig_threshold(0), - m_node_rpc_proxy(*m_http_client, m_rpc_payment_state, m_daemon_rpc_mutex), + m_node_rpc_proxy(*m_http_client, m_daemon_rpc_mutex), m_account_public_address{crypto::null_pkey, crypto::null_pkey}, m_subaddress_lookahead_major(SUBADDRESS_LOOKAHEAD_MAJOR), m_subaddress_lookahead_minor(SUBADDRESS_LOOKAHEAD_MINOR), @@ -1223,12 +1218,10 @@ wallet2::wallet2(network_type nettype, uint64_t kdf_rounds, bool unattended, std m_rpc_version(0), m_export_format(ExportFormat::Binary), m_load_deprecated_formats(false), - m_credits_target(0), m_enable_multisig(false), m_has_ever_refreshed_from_node(false), m_allow_mismatched_daemon_version(false) { - set_rpc_client_secret_key(rct::rct2sk(rct::skGen())); } wallet2::~wallet2() @@ -1342,11 +1335,6 @@ bool wallet2::set_daemon(std::string daemon_address, boost::optional &txids) { const boost::lock_guard lock{m_daemon_rpc_mutex}; - req.client = get_client_signature(); bool r = epee::net_utils::invoke_http_json("/gettransactions", req, res, *m_http_client, rpc_timeout); THROW_WALLET_EXCEPTION_IF(!r, error::wallet_internal_error, "Failed to get transaction from daemon"); THROW_WALLET_EXCEPTION_IF(res.txs.size() != req.txs_hashes.size(), error::wallet_internal_error, "Failed to get transaction from daemon"); @@ -2678,14 +2665,11 @@ void wallet2::pull_blocks(uint64_t start_height, uint64_t &blocks_start_height, { const boost::lock_guard lock{m_daemon_rpc_mutex}; - uint64_t pre_call_credits = m_rpc_payment_state.credits; - req.client = get_client_signature(); bool r = net_utils::invoke_http_bin("/getblocks.bin", req, res, *m_http_client, rpc_timeout); THROW_ON_RPC_RESPONSE_ERROR(r, {}, res, "getblocks.bin", error::get_blocks_error, get_rpc_status(res.status)); THROW_WALLET_EXCEPTION_IF(res.blocks.size() != res.output_indices.size(), error::wallet_internal_error, "mismatched blocks (" + boost::lexical_cast(res.blocks.size()) + ") and output_indices (" + boost::lexical_cast(res.output_indices.size()) + ") sizes from daemon"); - check_rpc_cost("/getblocks.bin", res.credits, pre_call_credits, 1 + res.blocks.size() * COST_PER_BLOCK); } blocks_start_height = res.start_height; @@ -2707,11 +2691,8 @@ void wallet2::pull_hashes(uint64_t start_height, uint64_t &blocks_start_height, { const boost::lock_guard lock{m_daemon_rpc_mutex}; - req.client = get_client_signature(); - uint64_t pre_call_credits = m_rpc_payment_state.credits; bool r = net_utils::invoke_http_bin("/gethashes.bin", req, res, *m_http_client, rpc_timeout); THROW_ON_RPC_RESPONSE_ERROR(r, {}, res, "gethashes.bin", error::get_hashes_error, get_rpc_status(res.status)); - check_rpc_cost("/gethashes.bin", res.credits, pre_call_credits, 1 + res.m_block_ids.size() * COST_PER_BLOCK_HASH); } blocks_start_height = res.start_height; @@ -3072,11 +3053,8 @@ void wallet2::update_pool_state(std::vector lock{m_daemon_rpc_mutex}; - uint64_t pre_call_credits = m_rpc_payment_state.credits; - req.client = get_client_signature(); bool r = epee::net_utils::invoke_http_json("/get_transaction_pool_hashes.bin", req, res, *m_http_client, rpc_timeout); THROW_ON_RPC_RESPONSE_ERROR(r, {}, res, "get_transaction_pool_hashes.bin", error::get_tx_pool_error); - check_rpc_cost("/get_transaction_pool_hashes.bin", res.credits, pre_call_credits, 1 + res.tx_hashes.size() * COST_PER_POOL_HASH); } MTRACE("update_pool_state got pool"); @@ -3226,11 +3204,7 @@ void wallet2::update_pool_state(std::vector lock{m_daemon_rpc_mutex}; - uint64_t pre_call_credits = m_rpc_payment_state.credits; - req.client = get_client_signature(); r = epee::net_utils::invoke_http_json("/gettransactions", req, res, *m_http_client, rpc_timeout); - if (r && res.status == CORE_RPC_STATUS_OK) - check_rpc_cost("/gettransactions", res.credits, pre_call_credits, res.txs.size() * COST_PER_TX); } MDEBUG("Got " << r << " and " << res.status); @@ -3613,9 +3587,8 @@ void wallet2::refresh(bool trusted_daemon, uint64_t start_height, uint64_t & blo THROW_WALLET_EXCEPTION_IF(!waiter.wait(), error::wallet_internal_error, "Exception in thread pool"); throw; } - catch (const error::payment_required&) + catch (const error::deprecated_rpc_access&) { - // no point in trying again, it'd just eat up credits THROW_WALLET_EXCEPTION_IF(!waiter.wait(), error::wallet_internal_error, "Exception in thread pool"); throw; } @@ -3700,11 +3673,8 @@ bool wallet2::get_rct_distribution(uint64_t &start_height, std::vector try { const boost::lock_guard lock{m_daemon_rpc_mutex}; - uint64_t pre_call_credits = m_rpc_payment_state.credits; - req.client = get_client_signature(); r = net_utils::invoke_http_bin("/get_output_distribution.bin", req, res, *m_http_client, rpc_timeout); THROW_ON_RPC_RESPONSE_ERROR_GENERIC(r, {}, res, "/get_output_distribution.bin"); - check_rpc_cost("/get_output_distribution.bin", res.credits, pre_call_credits, COST_PER_OUTPUT_DISTRIBUTION_0); } catch(...) { @@ -4078,13 +4048,16 @@ boost::optional wallet2::get_keys_file_data(const epee: json.AddMember("original_view_secret_key", value, json.GetAllocator()); } - value2.SetInt(m_persistent_rpc_client_id ? 1 : 0); + // This value is serialized for compatibility with wallets which support the pay-to-use RPC system + value2.SetInt(0); json.AddMember("persistent_rpc_client_id", value2, json.GetAllocator()); - value2.SetFloat(m_auto_mine_for_rpc_payment_threshold); + // This value is serialized for compatibility with wallets which support the pay-to-use RPC system + value2.SetFloat(0.0f); json.AddMember("auto_mine_for_rpc_payment", value2, json.GetAllocator()); - value2.SetUint64(m_credits_target); + // This value is serialized for compatibility with wallets which support the pay-to-use RPC system + value2.SetUint64(0); json.AddMember("credits_target", value2, json.GetAllocator()); value2.SetInt(m_enable_multisig ? 1 : 0); @@ -4235,9 +4208,6 @@ bool wallet2::load_keys_buf(const std::string& keys_buf, const epee::wipeable_st m_device_derivation_path = ""; m_key_device_type = hw::device::device_type::SOFTWARE; encrypted_secret_keys = false; - m_persistent_rpc_client_id = false; - m_auto_mine_for_rpc_payment_threshold = -1.0f; - m_credits_target = 0; m_enable_multisig = false; m_allow_mismatched_daemon_version = false; } @@ -4465,13 +4435,6 @@ bool wallet2::load_keys_buf(const std::string& keys_buf, const epee::wipeable_st m_original_keys_available = false; } - GET_FIELD_FROM_JSON_RETURN_ON_ERROR(json, persistent_rpc_client_id, int, Int, false, false); - m_persistent_rpc_client_id = field_persistent_rpc_client_id; - // save as float, load as double, because it can happen you can't load back as float... - GET_FIELD_FROM_JSON_RETURN_ON_ERROR(json, auto_mine_for_rpc_payment, float, Double, false, FLT_MAX); - m_auto_mine_for_rpc_payment_threshold = field_auto_mine_for_rpc_payment; - GET_FIELD_FROM_JSON_RETURN_ON_ERROR(json, credits_target, uint64_t, Uint64, false, 0); - m_credits_target = field_credits_target; GET_FIELD_FROM_JSON_RETURN_ON_ERROR(json, enable_multisig, int, Int, false, false); m_enable_multisig = field_enable_multisig; } @@ -5700,9 +5663,6 @@ void wallet2::load(const std::string& wallet_, const epee::wipeable_string& pass error::wallet_files_doesnt_correspond, m_keys_file, m_wallet_file); } - if (!m_persistent_rpc_client_id) - set_rpc_client_secret_key(rct::rct2sk(rct::skGen())); - cryptonote::block genesis; generate_genesis(genesis); crypto::hash genesis_hash = get_block_hash(genesis); @@ -5760,11 +5720,7 @@ void wallet2::trim_hashchain() { const boost::lock_guard lock{m_daemon_rpc_mutex}; req.height = m_blockchain.size() - 1; - uint64_t pre_call_credits = m_rpc_payment_state.credits; - req.client = get_client_signature(); r = net_utils::invoke_http_json_rpc("/json_rpc", "getblockheaderbyheight", req, res, *m_http_client, rpc_timeout); - if (r && res.status == CORE_RPC_STATUS_OK) - check_rpc_cost("getblockheaderbyheight", res.credits, pre_call_credits, COST_PER_BLOCK_HEADER); } if (r && res.status == CORE_RPC_STATUS_OK) @@ -6176,14 +6132,11 @@ void wallet2::rescan_spent() { const boost::lock_guard lock{m_daemon_rpc_mutex}; - uint64_t pre_call_credits = m_rpc_payment_state.credits; - req.client = get_client_signature(); bool r = epee::net_utils::invoke_http_json("/is_key_image_spent", req, daemon_resp, *m_http_client, rpc_timeout); THROW_ON_RPC_RESPONSE_ERROR(r, {}, daemon_resp, "is_key_image_spent", error::is_key_image_spent_error, get_rpc_status(daemon_resp.status)); THROW_WALLET_EXCEPTION_IF(daemon_resp.spent_status.size() != n_outputs, error::wallet_internal_error, "daemon returned wrong response for is_key_image_spent, wrong amounts count = " + std::to_string(daemon_resp.spent_status.size()) + ", expected " + std::to_string(n_outputs)); - check_rpc_cost("/is_key_image_spent", daemon_resp.credits, pre_call_credits, n_outputs * COST_PER_KEY_IMAGE); } std::copy(daemon_resp.spent_status.begin(), daemon_resp.spent_status.end(), std::back_inserter(spent_status)); @@ -6526,11 +6479,8 @@ void wallet2::commit_tx(pending_tx& ptx) { const boost::lock_guard lock{m_daemon_rpc_mutex}; - uint64_t pre_call_credits = m_rpc_payment_state.credits; - req.client = get_client_signature(); bool r = epee::net_utils::invoke_http_json("/sendrawtransaction", req, daemon_send_resp, *m_http_client, rpc_timeout); THROW_ON_RPC_RESPONSE_ERROR(r, {}, daemon_send_resp, "sendrawtransaction", error::tx_rejected, ptx.tx, get_rpc_status(daemon_send_resp.status), get_text_reason(daemon_send_resp)); - check_rpc_cost("/sendrawtransaction", daemon_send_resp.credits, pre_call_credits, COST_PER_TX_RELAY); } // sanity checks @@ -7654,11 +7604,8 @@ uint32_t wallet2::adjust_priority(uint32_t priority) { const boost::lock_guard lock{m_daemon_rpc_mutex}; - uint64_t pre_call_credits = m_rpc_payment_state.credits; - getbh_req.client = get_client_signature(); bool r = net_utils::invoke_http_json_rpc("/json_rpc", "getblockheadersrange", getbh_req, getbh_res, *m_http_client, rpc_timeout); THROW_ON_RPC_RESPONSE_ERROR(r, {}, getbh_res, "getblockheadersrange", error::get_blocks_error, get_rpc_status(getbh_res.status)); - check_rpc_cost("/getblockheadersrange", getbh_res.credits, pre_call_credits, N * COST_PER_BLOCK_HEADER); } if (getbh_res.headers.size() != N) @@ -7897,14 +7844,11 @@ bool wallet2::find_and_save_rings(bool force) { const boost::lock_guard lock{m_daemon_rpc_mutex}; - uint64_t pre_call_credits = m_rpc_payment_state.credits; - req.client = get_client_signature(); bool r = epee::net_utils::invoke_http_json("/gettransactions", req, res, *m_http_client, rpc_timeout); THROW_ON_RPC_RESPONSE_ERROR_GENERIC(r, {}, res, "/gettransactions"); THROW_WALLET_EXCEPTION_IF(res.txs.size() != req.txs_hashes.size(), error::wallet_internal_error, "daemon returned wrong response for gettransactions, wrong txs count = " + std::to_string(res.txs.size()) + ", expected " + std::to_string(req.txs_hashes.size())); - check_rpc_cost("/gettransactions", res.credits, pre_call_credits, res.txs.size() * COST_PER_TX); } MDEBUG("Scanning " << res.txs.size() << " transactions"); @@ -8242,11 +8186,8 @@ void wallet2::get_outs(std::vector> { const boost::lock_guard lock{m_daemon_rpc_mutex}; - uint64_t pre_call_credits = m_rpc_payment_state.credits; - req_t.client = get_client_signature(); bool r = net_utils::invoke_http_json_rpc("/json_rpc", "get_output_histogram", req_t, resp_t, *m_http_client, rpc_timeout); THROW_ON_RPC_RESPONSE_ERROR(r, {}, resp_t, "get_output_histogram", error::get_histogram_error, get_rpc_status(resp_t.status)); - check_rpc_cost("get_output_histogram", resp_t.credits, pre_call_credits, COST_PER_OUTPUT_HISTOGRAM * req_t.amounts.size()); } } @@ -8269,13 +8210,8 @@ void wallet2::get_outs(std::vector> { const boost::lock_guard lock{m_daemon_rpc_mutex}; - uint64_t pre_call_credits = m_rpc_payment_state.credits; - req_t.client = get_client_signature(); bool r = net_utils::invoke_http_json_rpc("/json_rpc", "get_output_distribution", req_t, resp_t, *m_http_client, rpc_timeout * 1000); THROW_ON_RPC_RESPONSE_ERROR(r, {}, resp_t, "get_output_distribution", error::get_output_distribution, get_rpc_status(resp_t.status)); - uint64_t expected_cost = 0; - for (uint64_t amount: req_t.amounts) expected_cost += (amount ? COST_PER_OUTPUT_DISTRIBUTION : COST_PER_OUTPUT_DISTRIBUTION_0); - check_rpc_cost("get_output_distribution", resp_t.credits, pre_call_credits, expected_cost); } // check we got all data @@ -8657,14 +8593,11 @@ void wallet2::get_outs(std::vector> chunk_req.outputs.push_back(req.outputs[offset + i]); const boost::lock_guard lock{m_daemon_rpc_mutex}; - uint64_t pre_call_credits = m_rpc_payment_state.credits; - chunk_req.client = get_client_signature(); bool r = epee::net_utils::invoke_http_bin("/get_outs.bin", chunk_req, chunk_daemon_resp, *m_http_client, rpc_timeout); THROW_ON_RPC_RESPONSE_ERROR(r, {}, chunk_daemon_resp, "get_outs.bin", error::get_outs_error, get_rpc_status(chunk_daemon_resp.status)); THROW_WALLET_EXCEPTION_IF(chunk_daemon_resp.outs.size() != chunk_req.outputs.size(), error::wallet_internal_error, "daemon returned wrong response for get_outs.bin, wrong amounts count = " + std::to_string(chunk_daemon_resp.outs.size()) + ", expected " + std::to_string(chunk_req.outputs.size())); - check_rpc_cost("/get_outs.bin", chunk_daemon_resp.credits, pre_call_credits, chunk_daemon_resp.outs.size() * COST_PER_OUT); offset += chunk_size; for (size_t i = 0; i < chunk_daemon_resp.outs.size(); ++i) @@ -11097,12 +11030,8 @@ std::vector wallet2::select_available_outputs_from_histogram(uint64_t co { const boost::lock_guard lock{m_daemon_rpc_mutex}; - uint64_t pre_call_credits = m_rpc_payment_state.credits; - req_t.client = get_client_signature(); bool r = net_utils::invoke_http_json_rpc("/json_rpc", "get_output_histogram", req_t, resp_t, *m_http_client, rpc_timeout); THROW_ON_RPC_RESPONSE_ERROR(r, {}, resp_t, "get_output_histogram", error::get_histogram_error, resp_t.status); - uint64_t cost = req_t.amounts.empty() ? COST_PER_FULL_OUTPUT_HISTOGRAM : (COST_PER_OUTPUT_HISTOGRAM * req_t.amounts.size()); - check_rpc_cost("get_output_histogram", resp_t.credits, pre_call_credits, cost); } std::set mixable; @@ -11139,13 +11068,10 @@ uint64_t wallet2::get_num_rct_outputs() { const boost::lock_guard lock{m_daemon_rpc_mutex}; - uint64_t pre_call_credits = m_rpc_payment_state.credits; - req_t.client = get_client_signature(); bool r = net_utils::invoke_http_json_rpc("/json_rpc", "get_output_histogram", req_t, resp_t, *m_http_client, rpc_timeout); THROW_ON_RPC_RESPONSE_ERROR(r, {}, resp_t, "get_output_histogram", error::get_histogram_error, resp_t.status); THROW_WALLET_EXCEPTION_IF(resp_t.histogram.size() != 1, error::get_histogram_error, "Expected exactly one response"); THROW_WALLET_EXCEPTION_IF(resp_t.histogram[0].amount != 0, error::get_histogram_error, "Expected 0 amount"); - check_rpc_cost("get_output_histogram", resp_t.credits, pre_call_credits, COST_PER_OUTPUT_HISTOGRAM); } return resp_t.histogram[0].total_instances; @@ -11270,12 +11196,9 @@ bool wallet2::get_tx_key(const crypto::hash &txid, crypto::secret_key &tx_key, s { const boost::lock_guard lock{m_daemon_rpc_mutex}; - req.client = get_client_signature(); - uint64_t pre_call_credits = m_rpc_payment_state.credits; bool ok = epee::net_utils::invoke_http_json("/gettransactions", req, res, *m_http_client); THROW_WALLET_EXCEPTION_IF(!ok || (res.txs.size() != 1 && res.txs_as_hex.size() != 1), error::wallet_internal_error, "Failed to get transaction from daemon"); - check_rpc_cost("/gettransactions", res.credits, pre_call_credits, res.txs.size() * COST_PER_TX); } cryptonote::transaction tx; @@ -11320,17 +11243,13 @@ void wallet2::set_tx_key(const crypto::hash &txid, const crypto::secret_key &tx_ req.prune = true; COMMAND_RPC_GET_TRANSACTIONS::response res = AUTO_VAL_INIT(res); bool r; - uint64_t pre_call_credits; { const boost::lock_guard lock{m_daemon_rpc_mutex}; - pre_call_credits = m_rpc_payment_state.credits; - req.client = get_client_signature(); r = epee::net_utils::invoke_http_json("/gettransactions", req, res, *m_http_client, rpc_timeout); THROW_ON_RPC_RESPONSE_ERROR_GENERIC(r, {}, res, "/gettransactions"); THROW_WALLET_EXCEPTION_IF(res.txs.size() != 1, error::wallet_internal_error, "daemon returned wrong response for gettransactions, wrong txs count = " + std::to_string(res.txs.size()) + ", expected 1"); - check_rpc_cost("/gettransactions", res.credits, pre_call_credits, COST_PER_TX); } cryptonote::transaction tx; @@ -11383,17 +11302,13 @@ std::string wallet2::get_spend_proof(const crypto::hash &txid, const std::string req.prune = true; COMMAND_RPC_GET_TRANSACTIONS::response res = AUTO_VAL_INIT(res); bool r; - uint64_t pre_call_credits; { const boost::lock_guard lock{m_daemon_rpc_mutex}; - pre_call_credits = m_rpc_payment_state.credits; - req.client = get_client_signature(); r = epee::net_utils::invoke_http_json("/gettransactions", req, res, *m_http_client, rpc_timeout); THROW_ON_RPC_RESPONSE_ERROR_GENERIC(r, {}, res, "gettransactions"); THROW_WALLET_EXCEPTION_IF(res.txs.size() != 1, error::wallet_internal_error, "daemon returned wrong response for gettransactions, wrong txs count = " + std::to_string(res.txs.size()) + ", expected 1"); - check_rpc_cost("/gettransactions", res.credits, pre_call_credits, COST_PER_TX); } cryptonote::transaction tx; @@ -11446,17 +11361,13 @@ std::string wallet2::get_spend_proof(const crypto::hash &txid, const std::string } COMMAND_RPC_GET_OUTPUTS_BIN::response res = AUTO_VAL_INIT(res); bool r; - uint64_t pre_call_credits; { const boost::lock_guard lock{m_daemon_rpc_mutex}; - pre_call_credits = m_rpc_payment_state.credits; - req.client = get_client_signature(); r = epee::net_utils::invoke_http_bin("/get_outs.bin", req, res, *m_http_client, rpc_timeout); THROW_ON_RPC_RESPONSE_ERROR(r, {}, res, "get_outs.bin", error::get_outs_error, res.status); THROW_WALLET_EXCEPTION_IF(res.outs.size() != ring_size, error::wallet_internal_error, "daemon returned wrong response for get_outs.bin, wrong amounts count = " + std::to_string(res.outs.size()) + ", expected " + std::to_string(ring_size)); - check_rpc_cost("/get_outs.bin", res.credits, pre_call_credits, ring_size * COST_PER_OUT); } // copy pubkey pointers @@ -11504,17 +11415,13 @@ bool wallet2::check_spend_proof(const crypto::hash &txid, const std::string &mes req.prune = true; COMMAND_RPC_GET_TRANSACTIONS::response res = AUTO_VAL_INIT(res); bool r; - uint64_t pre_call_credits; { const boost::lock_guard lock{m_daemon_rpc_mutex}; - pre_call_credits = m_rpc_payment_state.credits; - req.client = get_client_signature(); r = epee::net_utils::invoke_http_json("/gettransactions", req, res, *m_http_client, rpc_timeout); THROW_ON_RPC_RESPONSE_ERROR_GENERIC(r, {}, res, "gettransactions"); THROW_WALLET_EXCEPTION_IF(res.txs.size() != 1, error::wallet_internal_error, "daemon returned wrong response for gettransactions, wrong txs count = " + std::to_string(res.txs.size()) + ", expected 1"); - check_rpc_cost("/gettransactions", res.credits, pre_call_credits, COST_PER_TX); } cryptonote::transaction tx; @@ -11579,17 +11486,13 @@ bool wallet2::check_spend_proof(const crypto::hash &txid, const std::string &mes } COMMAND_RPC_GET_OUTPUTS_BIN::response res = AUTO_VAL_INIT(res); bool r; - uint64_t pre_call_credits; { const boost::lock_guard lock{m_daemon_rpc_mutex}; - pre_call_credits = m_rpc_payment_state.credits; - req.client = get_client_signature(); r = epee::net_utils::invoke_http_bin("/get_outs.bin", req, res, *m_http_client, rpc_timeout); THROW_ON_RPC_RESPONSE_ERROR(r, {}, res, "get_outs.bin", error::get_outs_error, res.status); THROW_WALLET_EXCEPTION_IF(res.outs.size() != req.outputs.size(), error::wallet_internal_error, "daemon returned wrong response for get_outs.bin, wrong amounts count = " + std::to_string(res.outs.size()) + ", expected " + std::to_string(req.outputs.size())); - check_rpc_cost("/get_outs.bin", res.credits, pre_call_credits, req.outputs.size() * COST_PER_OUT); } // copy pointers @@ -11675,12 +11578,9 @@ void wallet2::check_tx_key_helper(const crypto::hash &txid, const crypto::key_de bool ok; { const boost::lock_guard lock{m_daemon_rpc_mutex}; - uint64_t pre_call_credits = m_rpc_payment_state.credits; - req.client = get_client_signature(); ok = epee::net_utils::invoke_http_json("/gettransactions", req, res, *m_http_client); THROW_WALLET_EXCEPTION_IF(!ok || (res.txs.size() != 1 && res.txs_as_hex.size() != 1), error::wallet_internal_error, "Failed to get transaction from daemon"); - check_rpc_cost("/gettransactions", res.credits, pre_call_credits, COST_PER_TX); } cryptonote::transaction tx; @@ -11773,12 +11673,9 @@ std::string wallet2::get_tx_proof(const crypto::hash &txid, const cryptonote::ac bool ok; { const boost::lock_guard lock{m_daemon_rpc_mutex}; - uint64_t pre_call_credits = m_rpc_payment_state.credits; - req.client = get_client_signature(); ok = net_utils::invoke_http_json("/gettransactions", req, res, *m_http_client); THROW_WALLET_EXCEPTION_IF(!ok || (res.txs.size() != 1 && res.txs_as_hex.size() != 1), error::wallet_internal_error, "Failed to get transaction from daemon"); - check_rpc_cost("/gettransactions", res.credits, pre_call_credits, COST_PER_TX); } cryptonote::transaction tx; @@ -11934,12 +11831,9 @@ bool wallet2::check_tx_proof(const crypto::hash &txid, const cryptonote::account bool ok; { const boost::lock_guard lock{m_daemon_rpc_mutex}; - uint64_t pre_call_credits = m_rpc_payment_state.credits; - req.client = get_client_signature(); ok = net_utils::invoke_http_json("/gettransactions", req, res, *m_http_client); THROW_WALLET_EXCEPTION_IF(!ok || (res.txs.size() != 1 && res.txs_as_hex.size() != 1), error::wallet_internal_error, "Failed to get transaction from daemon"); - check_rpc_cost("/gettransactions", res.credits, pre_call_credits, COST_PER_TX); } cryptonote::transaction tx; @@ -12257,12 +12151,9 @@ bool wallet2::check_reserve_proof(const cryptonote::account_public_address &addr { const boost::lock_guard lock{m_daemon_rpc_mutex}; - uint64_t pre_call_credits = m_rpc_payment_state.credits; - gettx_req.client = get_client_signature(); bool ok = net_utils::invoke_http_json("/gettransactions", gettx_req, gettx_res, *m_http_client); THROW_WALLET_EXCEPTION_IF(!ok || gettx_res.txs.size() != proofs.size(), error::wallet_internal_error, "Failed to get transaction from daemon"); - check_rpc_cost("/gettransactions", gettx_res.credits, pre_call_credits, gettx_res.txs.size() * COST_PER_TX); } // check spent status @@ -12274,12 +12165,9 @@ bool wallet2::check_reserve_proof(const cryptonote::account_public_address &addr bool ok; { const boost::lock_guard lock{m_daemon_rpc_mutex}; - uint64_t pre_call_credits = m_rpc_payment_state.credits; - kispent_req.client = get_client_signature(); ok = epee::net_utils::invoke_http_json("/is_key_image_spent", kispent_req, kispent_res, *m_http_client, rpc_timeout); THROW_WALLET_EXCEPTION_IF(!ok || kispent_res.spent_status.size() != proofs.size(), error::wallet_internal_error, "Failed to get key image spent status from daemon"); - check_rpc_cost("/is_key_image_spent", kispent_res.credits, pre_call_credits, kispent_res.spent_status.size() * COST_PER_KEY_IMAGE); } total = spent = 0; @@ -12929,14 +12817,11 @@ uint64_t wallet2::import_key_images(const std::vector lock{m_daemon_rpc_mutex}; - uint64_t pre_call_credits = m_rpc_payment_state.credits; - req.client = get_client_signature(); bool r = epee::net_utils::invoke_http_json("/is_key_image_spent", req, daemon_resp, *m_http_client, rpc_timeout); THROW_ON_RPC_RESPONSE_ERROR_GENERIC(r, {}, daemon_resp, "is_key_image_spent"); THROW_WALLET_EXCEPTION_IF(daemon_resp.spent_status.size() != signed_key_images.size(), error::wallet_internal_error, "daemon returned wrong response for is_key_image_spent, wrong amounts count = " + std::to_string(daemon_resp.spent_status.size()) + ", expected " + std::to_string(signed_key_images.size())); - check_rpc_cost("/is_key_image_spent", daemon_resp.credits, pre_call_credits, daemon_resp.spent_status.size() * COST_PER_KEY_IMAGE); } for (size_t n = 0; n < daemon_resp.spent_status.size(); ++n) @@ -13018,13 +12903,10 @@ uint64_t wallet2::import_key_images(const std::vector lock{m_daemon_rpc_mutex}; - gettxs_req.client = get_client_signature(); - uint64_t pre_call_credits = m_rpc_payment_state.credits; bool r = epee::net_utils::invoke_http_json("/gettransactions", gettxs_req, gettxs_res, *m_http_client, rpc_timeout); THROW_ON_RPC_RESPONSE_ERROR_GENERIC(r, {}, gettxs_res, "gettransactions"); THROW_WALLET_EXCEPTION_IF(gettxs_res.txs.size() != spent_txids.size(), error::wallet_internal_error, "daemon returned wrong response for gettransactions, wrong count = " + std::to_string(gettxs_res.txs.size()) + ", expected " + std::to_string(spent_txids.size())); - check_rpc_cost("/gettransactions", gettxs_res.credits, pre_call_credits, spent_txids.size() * COST_PER_TX); } PERF_TIMER_STOP(import_key_images_E); @@ -14174,11 +14056,7 @@ uint64_t wallet2::get_blockchain_height_by_date(uint16_t year, uint8_t month, ui bool r; { const boost::lock_guard lock{m_daemon_rpc_mutex}; - uint64_t pre_call_credits = m_rpc_payment_state.credits; - req.client = get_client_signature(); r = net_utils::invoke_http_bin("/getblocks_by_height.bin", req, res, *m_http_client, rpc_timeout); - if (r && res.status == CORE_RPC_STATUS_OK) - check_rpc_cost("/getblocks_by_height.bin", res.credits, pre_call_credits, 3 * COST_PER_BLOCK); } if (!r || res.status != CORE_RPC_STATUS_OK) @@ -14252,11 +14130,8 @@ std::vector> wallet2::estimate_backlog(const std:: { const boost::lock_guard lock{m_daemon_rpc_mutex}; - uint64_t pre_call_credits = m_rpc_payment_state.credits; - req.client = get_client_signature(); bool r = net_utils::invoke_http_json_rpc("/json_rpc", "get_txpool_backlog", req, res, *m_http_client, rpc_timeout); THROW_ON_RPC_RESPONSE_ERROR(r, {}, res, "get_txpool_backlog", error::get_tx_pool_error); - check_rpc_cost("get_txpool_backlog", res.credits, pre_call_credits, COST_PER_TX_POOL_STATS * res.backlog.size()); } uint64_t block_weight_limit = 0; @@ -14407,13 +14282,17 @@ std::string wallet2::get_rpc_status(const std::string &s) const //---------------------------------------------------------------------------------------------------- void wallet2::throw_on_rpc_response_error(bool r, const epee::json_rpc::error &error, const std::string &status, const char *method) const { + // Treat all RPC payment access errors the same, whether payment is actually required or not + THROW_WALLET_EXCEPTION_IF(error.code == CORE_RPC_ERROR_CODE_INVALID_CLIENT, tools::error::deprecated_rpc_access, method); THROW_WALLET_EXCEPTION_IF(error.code, tools::error::wallet_coded_rpc_error, method, error.code, get_rpc_server_error_message(error.code)); THROW_WALLET_EXCEPTION_IF(!r, tools::error::no_connection_to_daemon, method); // empty string -> not connection THROW_WALLET_EXCEPTION_IF(status.empty(), tools::error::no_connection_to_daemon, method); THROW_WALLET_EXCEPTION_IF(status == CORE_RPC_STATUS_BUSY, tools::error::daemon_busy, method); - THROW_WALLET_EXCEPTION_IF(status == CORE_RPC_STATUS_PAYMENT_REQUIRED, tools::error::payment_required, method); + THROW_WALLET_EXCEPTION_IF(status == CORE_RPC_STATUS_PAYMENT_REQUIRED, tools::error::deprecated_rpc_access, method); + // Deprecated RPC payment access endpoints would set status to "Client signature does not verify for " + THROW_WALLET_EXCEPTION_IF(status.compare(0, 16, "Client signature") == 0, tools::error::deprecated_rpc_access, method); } //---------------------------------------------------------------------------------------------------- diff --git a/src/wallet/wallet2.h b/src/wallet/wallet2.h index 3ee40a5f042..f1c3d7c7e4c 100644 --- a/src/wallet/wallet2.h +++ b/src/wallet/wallet2.h @@ -71,14 +71,12 @@ #include "node_rpc_proxy.h" #include "message_store.h" #include "wallet_light_rpc.h" -#include "wallet_rpc_helpers.h" #undef MONERO_DEFAULT_LOG_CATEGORY #define MONERO_DEFAULT_LOG_CATEGORY "wallet.wallet2" #define THROW_ON_RPC_RESPONSE_ERROR(r, error, res, method, ...) \ do { \ - handle_payment_changes(res, std::integral_constant::Has>()); \ throw_on_rpc_response_error(r, error, res.status, method); \ THROW_WALLET_EXCEPTION_IF(res.status != CORE_RPC_STATUS_OK, ## __VA_ARGS__); \ } while(0) @@ -1232,7 +1230,8 @@ namespace tools a & m_cold_key_images.parent(); if(ver < 29) return; - a & m_rpc_client_secret_key; + crypto::secret_key dummy_rpc_client_secret_key; // Compatibility for old RPC payment system + a & dummy_rpc_client_secret_key; if(ver < 30) { m_has_ever_refreshed_from_node = false; @@ -1268,7 +1267,8 @@ namespace tools FIELD(m_tx_device) FIELD(m_device_last_key_image_sync) FIELD(m_cold_key_images) - FIELD(m_rpc_client_secret_key) + crypto::secret_key dummy_rpc_client_secret_key; // Compatibility for old RPC payment system + FIELD_N("m_rpc_client_secret_key", dummy_rpc_client_secret_key) if (version < 1) { m_has_ever_refreshed_from_node = false; @@ -1352,14 +1352,6 @@ namespace tools inline void set_export_format(const ExportFormat& export_format) { m_export_format = export_format; } bool load_deprecated_formats() const { return m_load_deprecated_formats; } void load_deprecated_formats(bool load) { m_load_deprecated_formats = load; } - bool persistent_rpc_client_id() const { return m_persistent_rpc_client_id; } - void persistent_rpc_client_id(bool persistent) { m_persistent_rpc_client_id = persistent; } - void auto_mine_for_rpc_payment_threshold(float threshold) { m_auto_mine_for_rpc_payment_threshold = threshold; } - float auto_mine_for_rpc_payment_threshold() const { return m_auto_mine_for_rpc_payment_threshold; } - crypto::secret_key get_rpc_client_secret_key() const { return m_rpc_client_secret_key; } - void set_rpc_client_secret_key(const crypto::secret_key &key) { m_rpc_client_secret_key = key; m_node_rpc_proxy.set_client_secret_key(key); } - uint64_t credits_target() const { return m_credits_target; } - void credits_target(uint64_t threshold) { m_credits_target = threshold; } bool is_multisig_enabled() const { return m_enable_multisig; } void enable_multisig(bool enable) { m_enable_multisig = enable; } bool is_mismatched_daemon_version_allowed() const { return m_allow_mismatched_daemon_version; } @@ -1543,21 +1535,6 @@ namespace tools std::pair estimate_tx_size_and_weight(bool use_rct, int n_inputs, int ring_size, int n_outputs, size_t extra_size); - bool get_rpc_payment_info(bool mining, bool &payment_required, uint64_t &credits, uint64_t &diff, uint64_t &credits_per_hash_found, cryptonote::blobdata &hashing_blob, uint64_t &height, uint64_t &seed_height, crypto::hash &seed_hash, crypto::hash &next_seed_hash, uint32_t &cookie); - bool daemon_requires_payment(); - bool make_rpc_payment(uint32_t nonce, uint32_t cookie, uint64_t &credits, uint64_t &balance); - bool search_for_rpc_payment(uint64_t credits_target, uint32_t n_threads, const std::function &startfunc, const std::function &contfunc, const std::function &foundfunc = NULL, const std::function &errorfunc = NULL); - template void handle_payment_changes(const T &res, std::true_type) { - if (res.status == CORE_RPC_STATUS_OK || res.status == CORE_RPC_STATUS_PAYMENT_REQUIRED) - m_rpc_payment_state.credits = res.credits; - if (res.top_hash != m_rpc_payment_state.top_hash) - { - m_rpc_payment_state.top_hash = res.top_hash; - m_rpc_payment_state.stale = true; - } - } - template void handle_payment_changes(const T &res, std::false_type) {} - // Light wallet specific functions // fetch unspent outs from lw node and store in m_transfers void light_wallet_get_unspent_outs(); @@ -1672,9 +1649,6 @@ namespace tools void set_offline(bool offline = true); bool is_offline() const { return m_offline; } - uint64_t credits() const { return m_rpc_payment_state.credits; } - void credit_report(uint64_t &expected_spent, uint64_t &discrepancy) const { expected_spent = m_rpc_payment_state.expected_spent; discrepancy = m_rpc_payment_state.discrepancy; } - static std::string get_default_daemon_address() { CRITICAL_REGION_LOCAL(default_daemon_address_lock); return default_daemon_address; } private: @@ -1778,9 +1752,6 @@ namespace tools std::string get_rpc_status(const std::string &s) const; void throw_on_rpc_response_error(bool r, const epee::json_rpc::error &error, const std::string &status, const char *method) const; - std::string get_client_signature() const; - void check_rpc_cost(const char *call, uint64_t post_call_credits, uint64_t pre_credits, double expected_cost); - bool should_expand(const cryptonote::subaddress_index &index) const; bool spends_one_of_ours(const cryptonote::transaction &tx) const; @@ -1865,7 +1836,6 @@ namespace tools bool m_show_wallet_name_when_locked; uint32_t m_inactivity_lock_timeout; BackgroundMiningSetupType m_setup_background_mining; - bool m_persistent_rpc_client_id; float m_auto_mine_for_rpc_payment_threshold; bool m_is_initialized; NodeRPCProxy m_node_rpc_proxy; @@ -1877,9 +1847,6 @@ namespace tools bool m_use_dns; bool m_offline; uint32_t m_rpc_version; - crypto::secret_key m_rpc_client_secret_key; - rpc_payment_state_t m_rpc_payment_state; - uint64_t m_credits_target; bool m_enable_multisig; bool m_allow_mismatched_daemon_version; diff --git a/src/wallet/wallet_args.cpp b/src/wallet/wallet_args.cpp index ce13fc57332..c60c8f26172 100644 --- a/src/wallet/wallet_args.cpp +++ b/src/wallet/wallet_args.cpp @@ -76,10 +76,6 @@ namespace wallet_args { return {"wallet-file", wallet_args::tr("Use wallet "), ""}; } - command_line::arg_descriptor arg_rpc_client_secret_key() - { - return {"rpc-client-secret-key", wallet_args::tr("Set RPC client secret key for RPC payments"), ""}; - } command_line::arg_descriptor arg_password_file() { return {"password-file", wallet_args::tr("Wallet password file"), ""}; diff --git a/src/wallet/wallet_args.h b/src/wallet/wallet_args.h index 350fce24eb5..e801ce07531 100644 --- a/src/wallet/wallet_args.h +++ b/src/wallet/wallet_args.h @@ -36,7 +36,6 @@ namespace wallet_args { command_line::arg_descriptor arg_generate_from_json(); command_line::arg_descriptor arg_wallet_file(); - command_line::arg_descriptor arg_rpc_client_secret_key(); command_line::arg_descriptor arg_password_file(); const char* tr(const char* str); diff --git a/src/wallet/wallet_errors.h b/src/wallet/wallet_errors.h index 0b85121630f..7a494e80187 100644 --- a/src/wallet/wallet_errors.h +++ b/src/wallet/wallet_errors.h @@ -91,7 +91,7 @@ namespace tools // is_key_image_spent_error // get_histogram_error // get_output_distribution - // payment_required + // deprecated_rpc_access // wallet_files_doesnt_correspond // // * - class with protected ctor @@ -865,10 +865,11 @@ namespace tools } }; //---------------------------------------------------------------------------------------------------- - struct payment_required: public wallet_rpc_error + struct deprecated_rpc_access: public wallet_rpc_error { - explicit payment_required(std::string&& loc, const std::string& request) - : wallet_rpc_error(std::move(loc), "payment required", request) + // The daemon we connected to has enabled the old pay-to-access RPC feature + explicit deprecated_rpc_access(std::string&& loc, const std::string& request) + : wallet_rpc_error(std::move(loc), "daemon requires deprecated RPC payment", request) { } }; diff --git a/src/wallet/wallet_rpc_helpers.h b/src/wallet/wallet_rpc_helpers.h deleted file mode 100644 index 93fa6996a41..00000000000 --- a/src/wallet/wallet_rpc_helpers.h +++ /dev/null @@ -1,95 +0,0 @@ -// Copyright (c) 2018-2022, The Monero Project -// -// All rights reserved. -// -// Redistribution and use in source and binary forms, with or without modification, are -// permitted provided that the following conditions are met: -// -// 1. Redistributions of source code must retain the above copyright notice, this list of -// conditions and the following disclaimer. -// -// 2. Redistributions in binary form must reproduce the above copyright notice, this list -// of conditions and the following disclaimer in the documentation and/or other -// materials provided with the distribution. -// -// 3. Neither the name of the copyright holder nor the names of its contributors may be -// used to endorse or promote products derived from this software without specific -// prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY -// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF -// MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL -// THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, -// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS -// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, -// STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF -// THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -#pragma once - -#include -#include - -namespace -{ - // credits to yrp (https://stackoverflow.com/questions/87372/check-if-a-class-has-a-member-function-of-a-given-signature - template - struct HasCredits - { - template struct SFINAE {}; - template static char Test(SFINAE*); - template static int Test(...); - static const bool Has = sizeof(Test(0)) == sizeof(char); - }; -} - -namespace tools -{ - struct rpc_payment_state_t - { - uint64_t credits; - uint64_t expected_spent; - uint64_t discrepancy; - std::string top_hash; - bool stale; - - rpc_payment_state_t(): credits(0), expected_spent(0), discrepancy(0), stale(true) {} - }; - - static inline void check_rpc_cost(rpc_payment_state_t &rpc_payment_state, const char *call, uint64_t post_call_credits, uint64_t pre_call_credits, double expected_cost) - { - uint64_t expected_credits = (uint64_t)expected_cost; - if (expected_credits == 0) - expected_credits = 1; - - rpc_payment_state.credits = post_call_credits; - rpc_payment_state.expected_spent += expected_credits; - - if (pre_call_credits <= post_call_credits) - return; - - uint64_t cost = pre_call_credits - post_call_credits; - - if (cost == expected_credits) - { - MDEBUG("Call " << call << " cost " << cost << " credits"); - return; - } - MWARNING("Call " << call << " cost " << cost << " credits, expected " << expected_credits); - - if (cost > expected_credits) - { - uint64_t d = cost - expected_credits; - if (rpc_payment_state.discrepancy > std::numeric_limits::max() - d) - { - MERROR("Integer overflow in credit discrepancy calculation, setting to max"); - rpc_payment_state.discrepancy = std::numeric_limits::max(); - } - else - { - rpc_payment_state.discrepancy += d; - } - } - } -} diff --git a/src/wallet/wallet_rpc_payments.cpp b/src/wallet/wallet_rpc_payments.cpp deleted file mode 100644 index 06910ebbb7a..00000000000 --- a/src/wallet/wallet_rpc_payments.cpp +++ /dev/null @@ -1,212 +0,0 @@ -// Copyright (c) 2018-2022, The Monero Project -// -// All rights reserved. -// -// Redistribution and use in source and binary forms, with or without modification, are -// permitted provided that the following conditions are met: -// -// 1. Redistributions of source code must retain the above copyright notice, this list of -// conditions and the following disclaimer. -// -// 2. Redistributions in binary form must reproduce the above copyright notice, this list -// of conditions and the following disclaimer in the documentation and/or other -// materials provided with the distribution. -// -// 3. Neither the name of the copyright holder nor the names of its contributors may be -// used to endorse or promote products derived from this software without specific -// prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY -// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF -// MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL -// THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, -// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS -// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, -// STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF -// THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -#include -#include -#include "include_base_utils.h" -#include "cryptonote_config.h" -#include "wallet_rpc_helpers.h" -#include "wallet2.h" -#include "cryptonote_basic/cryptonote_format_utils.h" -#include "rpc/core_rpc_server_commands_defs.h" -#include "rpc/rpc_payment_signature.h" -#include "misc_language.h" -#include "cryptonote_basic/cryptonote_basic_impl.h" -#include "int-util.h" -#include "crypto/crypto.h" -#include "cryptonote_basic/blobdatatype.h" -#include "common/i18n.h" -#include "common/util.h" -#include "common/threadpool.h" - -#undef MONERO_DEFAULT_LOG_CATEGORY -#define MONERO_DEFAULT_LOG_CATEGORY "wallet.wallet2.rpc_payments" - -#define RPC_PAYMENT_POLL_PERIOD 10 /* seconds*/ - -namespace tools -{ -//---------------------------------------------------------------------------------------------------- -std::string wallet2::get_client_signature() const -{ - return cryptonote::make_rpc_payment_signature(m_rpc_client_secret_key); -} -//---------------------------------------------------------------------------------------------------- -bool wallet2::get_rpc_payment_info(bool mining, bool &payment_required, uint64_t &credits, uint64_t &diff, uint64_t &credits_per_hash_found, cryptonote::blobdata &hashing_blob, uint64_t &height, uint64_t &seed_height, crypto::hash &seed_hash, crypto::hash &next_seed_hash, uint32_t &cookie) -{ - boost::optional result = m_node_rpc_proxy.get_rpc_payment_info(mining, payment_required, credits, diff, credits_per_hash_found, hashing_blob, height, seed_height, seed_hash, next_seed_hash, cookie); - credits = m_rpc_payment_state.credits; - if (result && *result != CORE_RPC_STATUS_OK) - return false; - return true; -} -//---------------------------------------------------------------------------------------------------- -bool wallet2::daemon_requires_payment() -{ - bool payment_required = false; - uint64_t credits, diff, credits_per_hash_found, height, seed_height; - uint32_t cookie; - cryptonote::blobdata blob; - crypto::hash seed_hash, next_seed_hash; - return get_rpc_payment_info(false, payment_required, credits, diff, credits_per_hash_found, blob, height, seed_height, seed_hash, next_seed_hash, cookie) && payment_required; -} -//---------------------------------------------------------------------------------------------------- -bool wallet2::make_rpc_payment(uint32_t nonce, uint32_t cookie, uint64_t &credits, uint64_t &balance) -{ - cryptonote::COMMAND_RPC_ACCESS_SUBMIT_NONCE::request req = AUTO_VAL_INIT(req); - cryptonote::COMMAND_RPC_ACCESS_SUBMIT_NONCE::response res = AUTO_VAL_INIT(res); - req.nonce = nonce; - req.cookie = cookie; - m_daemon_rpc_mutex.lock(); - uint64_t pre_call_credits = m_rpc_payment_state.credits; - req.client = get_client_signature(); - epee::json_rpc::error error; - bool r = epee::net_utils::invoke_http_json_rpc("/json_rpc", "rpc_access_submit_nonce", req, res, error, *m_http_client, rpc_timeout); - m_daemon_rpc_mutex.unlock(); - THROW_ON_RPC_RESPONSE_ERROR_GENERIC(r, error, res, "rpc_access_submit_nonce"); - THROW_WALLET_EXCEPTION_IF(res.credits < pre_call_credits, error::wallet_internal_error, "RPC payment did not increase balance"); - if (m_rpc_payment_state.top_hash != res.top_hash) - { - m_rpc_payment_state.top_hash = res.top_hash; - m_rpc_payment_state.stale = true; - } - - m_rpc_payment_state.credits = res.credits; - balance = res.credits; - credits = balance - pre_call_credits; - return true; -} -//---------------------------------------------------------------------------------------------------- -bool wallet2::search_for_rpc_payment(uint64_t credits_target, uint32_t n_threads, const std::function &startfunc, const std::function &contfunc, const std::function &foundfunc, const std::function &errorfunc) -{ - bool need_payment = false; - bool payment_required; - uint64_t credits, diff, credits_per_hash_found, height, seed_height; - uint32_t cookie; - unsigned int n_hashes = 0; - cryptonote::blobdata hashing_blob; - crypto::hash seed_hash, next_seed_hash; - try - { - need_payment = get_rpc_payment_info(false, payment_required, credits, diff, credits_per_hash_found, hashing_blob, height, seed_height, seed_hash, next_seed_hash, cookie) && payment_required && credits < credits_target; - if (!need_payment) - return true; - if (!startfunc(diff, credits_per_hash_found)) - return true; - } - catch (const std::exception &e) { return false; } - - static std::atomic nonce(0); - while (contfunc(n_hashes)) - { - try - { - need_payment = get_rpc_payment_info(true, payment_required, credits, diff, credits_per_hash_found, hashing_blob, height, seed_height, seed_hash, next_seed_hash, cookie) && payment_required && credits < credits_target; - if (!need_payment) - return true; - } - catch (const std::exception &e) { return false; } - if (hashing_blob.empty()) - { - MERROR("Bad hashing blob from daemon"); - if (errorfunc) - errorfunc("Bad hashing blob from daemon, trying again"); - epee::misc_utils::sleep_no_w(1000); - continue; - } - - if(n_threads == 0) - n_threads = boost::thread::hardware_concurrency(); - - std::vector hash(n_threads); - tools::threadpool& tpool = tools::threadpool::getInstanceForCompute(); - tools::threadpool::waiter waiter(tpool); - - const uint32_t local_nonce = nonce += n_threads; // wrapping's OK - for (size_t i = 0; i < n_threads; i++) - { - tpool.submit(&waiter, [&, i] { - *(uint32_t*)(hashing_blob.data() + 39) = SWAP32LE(local_nonce-i); - const uint8_t major_version = hashing_blob[0]; - if (major_version >= RX_BLOCK_VERSION) - { - crypto::rx_slow_hash(seed_hash.data, hashing_blob.data(), hashing_blob.size(), hash[i].data); - } - else - { - int cn_variant = hashing_blob[0] >= 7 ? hashing_blob[0] - 6 : 0; - crypto::cn_slow_hash(hashing_blob.data(), hashing_blob.size(), hash[i], cn_variant, height); - } - }); - } - waiter.wait(); - n_hashes += n_threads; - - for(size_t i=0; i < n_threads; i++) - { - if (cryptonote::check_hash(hash[i], diff)) - { - uint64_t credits, balance; - try - { - make_rpc_payment(local_nonce-i, cookie, credits, balance); - if (credits != credits_per_hash_found) - { - MERROR("Found nonce, but daemon did not credit us with the expected amount"); - if (errorfunc) - errorfunc("Found nonce, but daemon did not credit us with the expected amount"); - return false; - } - MDEBUG("Found nonce " << local_nonce-i << " at diff " << diff << ", gets us " << credits_per_hash_found << ", now " << balance << " credits"); - if (!foundfunc(credits)) - break; - } - catch (const tools::error::wallet_coded_rpc_error &e) - { - MWARNING("Found a local_nonce at diff " << diff << ", but failed to send it to the daemon"); - if (errorfunc) - errorfunc("Found nonce, but daemon errored out with error " + std::to_string(e.code()) + ": " + e.status() + ", continuing"); - } - catch (const std::exception &e) - { - MWARNING("Found a local_nonce at diff " << diff << ", but failed to send it to the daemon"); - if (errorfunc) - errorfunc("Found nonce, but daemon errored out with: '" + std::string(e.what()) + "', continuing"); - } - } - } - } - return true; -} -//---------------------------------------------------------------------------------------------------- -void wallet2::check_rpc_cost(const char *call, uint64_t post_call_credits, uint64_t pre_call_credits, double expected_cost) -{ - return tools::check_rpc_cost(m_rpc_payment_state, call, post_call_credits, pre_call_credits, expected_cost); -} -//---------------------------------------------------------------------------------------------------- -} diff --git a/src/wallet/wallet_rpc_server.cpp b/src/wallet/wallet_rpc_server.cpp index cecf2428929..9449f81665e 100644 --- a/src/wallet/wallet_rpc_server.cpp +++ b/src/wallet/wallet_rpc_server.cpp @@ -4517,7 +4517,6 @@ class t_daemon const auto arg_wallet_file = wallet_args::arg_wallet_file(); const auto arg_from_json = wallet_args::arg_generate_from_json(); - const auto arg_rpc_client_secret_key = wallet_args::arg_rpc_client_secret_key(); const auto arg_password_file = wallet_args::arg_password_file(); const auto wallet_file = command_line::get_arg(vm, arg_wallet_file); @@ -4575,17 +4574,6 @@ class t_daemon return false; } - if (!command_line::is_arg_defaulted(vm, arg_rpc_client_secret_key)) - { - crypto::secret_key client_secret_key; - if (!epee::string_tools::hex_to_pod(command_line::get_arg(vm, arg_rpc_client_secret_key), client_secret_key)) - { - MERROR(arg_rpc_client_secret_key.name << ": RPC client secret key should be 32 byte in hex format"); - return false; - } - wal->set_rpc_client_secret_key(client_secret_key); - } - bool quit = false; tools::signal_handler::install([&wal, &quit](int) { assert(wal); @@ -4692,7 +4680,6 @@ int main(int argc, char** argv) { const auto arg_wallet_file = wallet_args::arg_wallet_file(); const auto arg_from_json = wallet_args::arg_generate_from_json(); - const auto arg_rpc_client_secret_key = wallet_args::arg_rpc_client_secret_key(); po::options_description hidden_options("Hidden"); @@ -4706,7 +4693,6 @@ int main(int argc, char** argv) { command_line::add_arg(desc_params, arg_from_json); command_line::add_arg(desc_params, arg_wallet_dir); command_line::add_arg(desc_params, arg_prompt_for_password); - command_line::add_arg(desc_params, arg_rpc_client_secret_key); command_line::add_arg(desc_params, arg_no_initial_sync); daemonizer::init_options(hidden_options, desc_params);