What changed, and why it matters
This commit removes the 'bootstrap mode' feature from the Monero daemon. Bootstrap mode let a not-yet-fully-synced local daemon forward wallet and mining RPC requests to a remote daemon. Removing it means wallets and miners now only get data from the local daemon. This is a hardening change: it shrinks the attack surface by eliminating a feature that could expose users to untrusted remote nodes, but it is not a fix for a specific known exploit.
Treat as a hardening/feature-removal commit rather than an urgent security patch. Review release notes for any additional context on why bootstrap mode was removed. Operators who relied on bootstrap mode must now run a fully synced local daemon or explicitly connect wallets/miners to a trusted remote daemon.
Security signals we found
Feature removal that eliminates proxying of RPC requests to potentially untrusted remote daemons
Removal of automatic public-node discovery and switching for bootstrap mode
Removal of 'untrusted' flag from RPC response base
No new input validation, bounds checks, or memory safety fixes present in diff
Evidence from the diff
The patch deletes the bootstrap daemon implementation (bootstrap_daemon.cpp/h, bootstrap_node_selector.cpp/h), removes the set_bootstrap_daemon RPC command and CLI options, strips all use_bootstrap_daemon_if_necessary() forwarding logic from core_rpc_server, removes the untrusted flag from rpc_response_base, and updates tests, shell completions, and Python RPC helpers. The change forces local-only responses for endpoints that previously could be proxied to a remote bootstrap node. There is no evidence in the commit of a specific vulnerability being patched; it is a feature removal for security hardening.
Changed components
src/rpc/core_rpc_server.cppsrc/rpc/core_rpc_server.hsrc/rpc/core_rpc_server_commands_defs.hsrc/rpc/bootstrap_daemon.cppsrc/rpc/bootstrap_daemon.hsrc/rpc/bootstrap_node_selector.cppsrc/rpc/bootstrap_node_selector.hsrc/daemon/command_parser_executor.cppsrc/daemon/rpc_command_executor.cppsrc/simplewallet/simplewallet.cpptests/fuzz/fuzz_rpcutils/python-rpc/framework/daemon.pyInspect captured patch +48 / −1304
diff --git a/src/daemon/command_parser_executor.cpp b/src/daemon/command_parser_executor.cpp
index 728df58..6b2637b 100644
--- a/src/daemon/command_parser_executor.cpp
+++ b/src/daemon/command_parser_executor.cpp
@@ -986,71 +986,6 @@ bool t_command_parser_executor::check_blockchain_pruning(const std::vector<std::
return m_executor.check_blockchain_pruning();
}
-bool t_command_parser_executor::set_bootstrap_daemon(const std::vector<std::string>& args)
-{
- struct parsed_t
- {
- std::string address;
- std::string user;
- std::string password;
- std::string proxy;
- };
-
- boost::optional<parsed_t> parsed = [&args]() -> boost::optional<parsed_t> {
- const size_t args_count = args.size();
- if (args_count == 0)
- {
- return {};
- }
- if (args[0] == "auto")
- {
- if (args_count == 1)
- {
- return {{args[0], "", "", ""}};
- }
- if (args_count == 2)
- {
- return {{args[0], "", "", args[1]}};
- }
- }
- else if (args[0] == "none")
- {
- if (args_count == 1)
- {
- return {{"", "", "", ""}};
- }
- }
- else
- {
- if (args_count == 1)
- {
- return {{args[0], "", "", ""}};
- }
- if (args_count == 2)
- {
- return {{args[0], "", "", args[1]}};
- }
- if (args_count == 3)
- {
- return {{args[0], args[1], args[2], ""}};
- }
- if (args_count == 4)
- {
- return {{args[0], args[1], args[2], args[3]}};
- }
- }
- return {};
- }();
-
- if (!parsed)
- {
- std::cout << "Invalid syntax: Wrong number of parameters. For more details, use the help command." << std::endl;
- return true;
- }
-
- return m_executor.set_bootstrap_daemon(parsed->address, parsed->user, parsed->password, parsed->proxy);
-}
-
bool t_command_parser_executor::flush_cache(const std::vector<std::string>& args)
{
bool bad_blocks = false;
diff --git a/src/daemon/command_parser_executor.h b/src/daemon/command_parser_executor.h
index a053d01..77b365a 100644
--- a/src/daemon/command_parser_executor.h
+++ b/src/daemon/command_parser_executor.h
@@ -150,8 +150,6 @@ public:
bool print_net_stats(const std::vector<std::string>& args);
- bool set_bootstrap_daemon(const std::vector<std::string>& args);
-
bool flush_cache(const std::vector<std::string>& args);
};
diff --git a/src/daemon/command_server.cpp b/src/daemon/command_server.cpp
index 1950b22..bb26c8d 100644
--- a/src/daemon/command_server.cpp
+++ b/src/daemon/command_server.cpp
@@ -318,13 +318,6 @@ t_command_server::t_command_server(
, std::bind(&t_command_parser_executor::check_blockchain_pruning, &m_parser, p::_1)
, "Check the blockchain pruning."
);
- m_command_lookup.set_handler(
- "set_bootstrap_daemon"
- , std::bind(&t_command_parser_executor::set_bootstrap_daemon, &m_parser, p::_1)
- , "set_bootstrap_daemon (auto | none | host[:port] [username] [password]) [proxy_ip:proxy_port]"
- , "URL of a 'bootstrap' remote daemon that the connected wallets can use while this daemon is still not fully synced.\n"
- "Use 'auto' to enable automatic public nodes discovering and bootstrap daemon switching"
- );
m_command_lookup.set_handler(
"flush_cache"
, std::bind(&t_command_parser_executor::flush_cache, &m_parser, p::_1)
diff --git a/src/daemon/rpc_command_executor.cpp b/src/daemon/rpc_command_executor.cpp
index 1385a85..c943cca 100644
--- a/src/daemon/rpc_command_executor.cpp
+++ b/src/daemon/rpc_command_executor.cpp
@@ -436,10 +436,6 @@ static float get_sync_percentage(uint64_t height, uint64_t target_height)
return 99.9f; // to avoid 100% when not fully synced
return pc;
}
-static float get_sync_percentage(const cryptonote::COMMAND_RPC_GET_INFO::response &ires)
-{
- return get_sync_percentage(ires.height, ires.target_height);
-}
bool t_rpc_command_executor::show_status() {
cryptonote::COMMAND_RPC_GET_INFO::request ireq;
@@ -499,27 +495,13 @@ bool t_rpc_command_executor::show_status() {
std::time_t uptime = std::time(nullptr) - ires.start_time;
uint64_t net_height = ires.target_height > ires.height ? ires.target_height : ires.height;
- std::string bootstrap_msg;
- if (ires.was_bootstrap_ever_used)
- {
- bootstrap_msg = ", bootstrapping from " + ires.bootstrap_daemon_address;
- if (ires.untrusted)
- {
- bootstrap_msg += (boost::format(", local height: %llu (%.1f%%)") % ires.height_without_bootstrap % get_sync_percentage(ires.height_without_bootstrap, net_height)).str();
- }
- else
- {
- bootstrap_msg += " was used before";
- }
- }
std::stringstream str;
- str << boost::format("Height: %llu/%llu (%.1f%%) on %s%s, %s, net hash %s, v%u%s, %u(out)+%u(in) connections")
+ str << boost::format("Height: %llu/%llu (%.1f%%) on %s, %s, net hash %s, v%u%s, %u(out)+%u(in) connections")
% (unsigned long long)ires.height
% (unsigned long long)net_height
- % get_sync_percentage(ires)
+ % get_sync_percentage(ires.height, ires.target_height)
% (ires.testnet ? "testnet" : ires.stagenet ? "stagenet" : "mainnet")
- % bootstrap_msg
% (!has_mining_info ? "mining info unavailable" : mining_busy ? "syncing" : mres.active ? ( ( mres.is_background_mining_enabled ? "smart " : "" ) + std::string("mining at ") + get_mining_speed(mres.speed)) : "not mining")
% get_mining_speed(cryptonote::difficulty_type(ires.wide_difficulty) / ires.target)
% (unsigned)hfres.version
@@ -2402,44 +2384,6 @@ bool t_rpc_command_executor::check_blockchain_pruning()
return true;
}
-bool t_rpc_command_executor::set_bootstrap_daemon(
- const std::string &address,
- const std::string &username,
- const std::string &password,
- const std::string &proxy)
-{
- cryptonote::COMMAND_RPC_SET_BOOTSTRAP_DAEMON::request req;
- cryptonote::COMMAND_RPC_SET_BOOTSTRAP_DAEMON::response res;
- const std::string fail_message = "Unsuccessful";
-
- req.address = address;
- req.username = username;
- req.password = password;
- req.proxy = proxy;
-
- if (m_is_rpc)
- {
- if (!m_rpc_client->rpc_request(req, res, "/set_bootstrap_daemon", fail_message))
- {
- return true;
- }
- }
- else
- {
- if (!m_rpc_server->on_set_bootstrap_daemon(req, res) || res.status != CORE_RPC_STATUS_OK)
- {
- tools::fail_msg_writer() << make_error(fail_message, res.status);
- return true;
- }
- }
-
- tools::success_msg_writer()
- << "Successfully set bootstrap daemon address to "
- << (!req.address.empty() ? req.address : "none");
-
- return true;
-}
-
bool t_rpc_command_executor::flush_cache(bool bad_blocks)
{
cryptonote::COMMAND_RPC_FLUSH_CACHE::request req;
diff --git a/src/daemon/rpc_command_executor.h b/src/daemon/rpc_command_executor.h
index 0469c9f..c606581 100644
--- a/src/daemon/rpc_command_executor.h
+++ b/src/daemon/rpc_command_executor.h
@@ -164,12 +164,6 @@ public:
bool version();
- bool set_bootstrap_daemon(
- const std::string &address,
- const std::string &username,
- const std::string &password,
- const std::string &proxy);
-
bool flush_cache(bool invalid_blocks);
};
diff --git a/src/rpc/CMakeLists.txt b/src/rpc/CMakeLists.txt
index a1d3d9f..bd1efa6 100644
--- a/src/rpc/CMakeLists.txt
+++ b/src/rpc/CMakeLists.txt
@@ -31,8 +31,6 @@ set(rpc_base_sources
rpc_handler.cpp)
set(rpc_sources
- bootstrap_daemon.cpp
- bootstrap_node_selector.cpp
core_rpc_server.cpp
rpc_version_str.cpp
instanciations.cpp)
@@ -63,7 +61,6 @@ set(rpc_pub_headers zmq_pub.h)
set(daemon_rpc_server_headers)
set(rpc_private_headers
- bootstrap_daemon.h
core_rpc_server.h
core_rpc_server_commands_defs.h
core_rpc_server_error_codes.h)
diff --git a/src/rpc/bootstrap_daemon.cpp b/src/rpc/bootstrap_daemon.cpp
deleted file mode 100644
index b3aecb3..0000000
--- a/src/rpc/bootstrap_daemon.cpp
+++ /dev/null
@@ -1,126 +0,0 @@
-#include "bootstrap_daemon.h"
-
-#include <stdexcept>
-
-#include <boost/thread/locks.hpp>
-
-#include "crypto/crypto.h"
-#include "cryptonote_core/cryptonote_core.h"
-#include "misc_log_ex.h"
-#include "net/parse.h"
-
-#undef MONERO_DEFAULT_LOG_CATEGORY
-#define MONERO_DEFAULT_LOG_CATEGORY "daemon.rpc.bootstrap_daemon"
-
-namespace cryptonote
-{
-
- bootstrap_daemon::bootstrap_daemon(
- std::function<std::map<std::string, bool>()> get_public_nodes,
- const std::string &proxy)
- : m_selector(new bootstrap_node::selector_auto(std::move(get_public_nodes)))
- {
- set_proxy(proxy);
- }
-
- bootstrap_daemon::bootstrap_daemon(
- const std::string &address,
- boost::optional<epee::net_utils::http::login> credentials,
- const std::string &proxy)
- : m_selector(nullptr)
- {
- set_proxy(proxy);
- if (!set_server(address, std::move(credentials)))
- {
- throw std::runtime_error("invalid bootstrap daemon address or credentials");
- }
- }
-
- std::string bootstrap_daemon::address() const noexcept
- {
- const auto& host = m_http_client.get_host();
- if (host.empty())
- {
- return std::string();
- }
- return host + ":" + m_http_client.get_port();
- }
-
- boost::optional<std::pair<uint64_t, uint64_t>> bootstrap_daemon::get_height()
- {
- cryptonote::COMMAND_RPC_GET_INFO::request req;
- cryptonote::COMMAND_RPC_GET_INFO::response res;
-
- if (!invoke_http_json("/getinfo", req, res))
- {
- return boost::none;
- }
-
- if (res.status != CORE_RPC_STATUS_OK)
- {
- return boost::none;
- }
-
- return {{res.height, res.target_height}};
- }
-
- bool bootstrap_daemon::handle_result(bool success, const std::string &status)
- {
- const bool failed = !success || (status == CORE_RPC_STATUS_PAYMENT_REQUIRED);
- if (failed && m_selector)
- {
- const std::string current_address = address();
- m_http_client.disconnect();
-
- const boost::unique_lock<boost::mutex> lock(m_selector_mutex);
- m_selector->handle_result(current_address, !failed);
- }
-
- return success;
- }
-
- void bootstrap_daemon::set_proxy(const std::string &address)
- {
- if (!address.empty() && !net::get_tcp_endpoint(address))
- {
- throw std::runtime_error("invalid proxy address format");
- }
- if (!m_http_client.set_proxy(address))
- {
- throw std::runtime_error("failed to set proxy address");
- }
- }
-
- bool bootstrap_daemon::set_server(const std::string &address, const boost::optional<epee::net_utils::http::login> &credentials /* = boost::none */)
- {
- if (!m_http_client.set_server(address, credentials))
- {
- MERROR("Failed to set bootstrap daemon address " << address);
- return false;
- }
-
- MINFO("Changed bootstrap daemon address to " << address);
- return true;
- }
-
-
- bool bootstrap_daemon::switch_server_if_needed()
- {
- if (m_http_client.is_connected() || !m_selector)
- {
- return true;
- }
-
- boost::optional<bootstrap_node::node_info> node;
- {
- const boost::unique_lock<boost::mutex> lock(m_selector_mutex);
- node = m_selector->next_node();
- }
- if (node) {
- return set_server(node->address, node->credentials);
- }
-
- return false;
- }
-
-}
diff --git a/src/rpc/bootstrap_daemon.h b/src/rpc/bootstrap_daemon.h
deleted file mode 100644
index 259bdfe..0000000
--- a/src/rpc/bootstrap_daemon.h
+++ /dev/null
@@ -1,87 +0,0 @@
-#pragma once
-
-#include <functional>
-#include <map>
-#include <utility>
-
-#include <boost/optional/optional.hpp>
-#include <boost/thread/mutex.hpp>
-#include <boost/utility/string_ref.hpp>
-
-#include "net/http.h"
-#include "storages/http_abstract_invoke.h"
-
-#include "bootstrap_node_selector.h"
-
-namespace cryptonote
-{
-
- class bootstrap_daemon
- {
- public:
- bootstrap_daemon(
- std::function<std::map<std::string, bool>()> get_public_nodes,
- const std::string &proxy);
- bootstrap_daemon(
- const std::string &address,
- boost::optional<epee::net_utils::http::login> credentials,
- const std::string &proxy);
-
- std::string address() const noexcept;
- boost::optional<std::pair<uint64_t, uint64_t>> get_height();
- bool handle_result(bool success, const std::string &status);
-
- template <class t_request, class t_response>
- bool invoke_http_json(const boost::string_ref uri, const t_request &out_struct, t_response &result_struct)
- {
- if (!switch_server_if_needed())
- {
- return false;
- }
-
- const bool result = epee::net_utils::invoke_http_json(uri, out_struct, result_struct, m_http_client);
- return handle_result(result, result_struct.status);
- }
-
- template <class t_request, class t_response>
- bool invoke_http_bin(const boost::string_ref uri, const t_request &out_struct, t_response &result_struct)
- {
- if (!switch_server_if_needed())
- {
- return false;
- }
-
- const bool result = epee::net_utils::invoke_http_bin(uri, out_struct, result_struct, m_http_client);
- return handle_result(result, result_struct.status);
- }
-
- template <class t_request, class t_response>
- bool invoke_http_json_rpc(const boost::string_ref command_name, const t_request &out_struct, t_response &result_struct)
- {
- if (!switch_server_if_needed())
- {
- return false;
- }
-
- const bool result = epee::net_utils::invoke_http_json_rpc(
- "/json_rpc",
- std::string(command_name.begin(), command_name.end()),
- out_struct,
- result_struct,
- m_http_client);
- return handle_result(result, result_struct.status);
- }
-
- void set_proxy(const std::string &address);
-
- private:
- bool set_server(const std::string &address, const boost::optional<epee::net_utils::http::login> &credentials = boost::none);
- bool switch_server_if_needed();
-
- private:
- net::http::client m_http_client;
- const std::unique_ptr<bootstrap_node::selector> m_selector;
- boost::mutex m_selector_mutex;
- };
-
-}
diff --git a/src/rpc/bootstrap_node_selector.cpp b/src/rpc/bootstrap_node_selector.cpp
deleted file mode 100644
index 9f2f9a8..0000000
--- a/src/rpc/bootstrap_node_selector.cpp
+++ /dev/null
@@ -1,117 +0,0 @@
-// Copyright (c) 2020-2024, 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 "bootstrap_node_selector.h"
-
-#include "crypto/crypto.h"
-
-namespace cryptonote
-{
-namespace bootstrap_node
-{
-
- void selector_auto::node::handle_result(bool success)
- {
- if (!success)
- {
- fails = std::min(std::numeric_limits<size_t>::max() - 2, fails) + 2;
- }
- else
- {
- fails = std::max(std::numeric_limits<size_t>::min() + 2, fails) - 2;
- }
- }
-
- void selector_auto::handle_result(const std::string &address, bool success)
- {
- auto &nodes_by_address = m_nodes.get<by_address>();
- const auto it = nodes_by_address.find(address);
- if (it != nodes_by_address.end())
- {
- nodes_by_address.modify(it, [success](node &entry) {
- entry.handle_result(success);
- });
- }
- }
-
- boost::optional<node_info> selector_auto::next_node()
- {
- if (!has_at_least_one_good_node())
- {
- append_new_nodes();
- }
-
- if (m_nodes.empty())
- {
- return {};
- }
-
- auto node = m_nodes.get<by_fails>().begin();
- const size_t count = std::distance(node, m_nodes.get<by_fails>().upper_bound(node->fails));
- std::advance(node, crypto::rand_idx(count));
-
- return {{node->address, {}}};
- }
-
- bool selector_auto::has_at_least_one_good_node() const
- {
- return !m_nodes.empty() && m_nodes.get<by_fails>().begin()->fails == 0;
- }
-
- void selector_auto::append_new_nodes()
- {
- bool updated = false;
-
- for (const auto &node : m_get_nodes())
- {
- const auto &address = node.first;
- const auto &white = node.second;
- const size_t initial_score = white ? 0 : 1;
- updated |= m_nodes.get<by_address>().insert({address, initial_score}).second;
- }
-
- if (updated)
- {
- truncate();
- }
- }
-
- void selector_auto::truncate()
- {
- const size_t total = m_nodes.size();
- if (total > m_max_nodes)
- {
- auto &nodes_by_fails = m_nodes.get<by_fails>();
- auto from = nodes_by_fails.rbegin();
- std::advance(from, total - m_max_nodes);
- nodes_by_fails.erase(from.base(), nodes_by_fails.end());
- }
- }
-
-}
-}
diff --git a/src/rpc/bootstrap_node_selector.h b/src/rpc/bootstrap_node_selector.h
deleted file mode 100644
index 431e93d..0000000
--- a/src/rpc/bootstrap_node_selector.h
+++ /dev/null
@@ -1,105 +0,0 @@
-// Copyright (c) 2020-2024, 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 <functional>
-#include <limits>
-#include <map>
-#include <string>
-#include <utility>
-
-#include <boost/multi_index_container.hpp>
-#include <boost/multi_index/member.hpp>
-#include <boost/multi_index/ordered_index.hpp>
-#include <boost/optional/optional.hpp>
-
-#include "net/http_client.h"
-
-namespace cryptonote
-{
-namespace bootstrap_node
-{
-
- struct node_info
- {
- std::string address;
- boost::optional<epee::net_utils::http::login> credentials;
- };
-
- struct selector
- {
- virtual ~selector() = default;
-
- virtual void handle_result(const std::string &address, bool success) = 0;
- virtual boost::optional<node_info> next_node() = 0;
- };
-
- class selector_auto : public selector
- {
- public:
- selector_auto(std::function<std::map<std::string, bool>()> get_nodes, size_t max_nodes = 1000)
- : m_get_nodes(std::move(get_nodes))
- , m_max_nodes(max_nodes)
- {}
-
- void handle_result(const std::string &address, bool success) final;
- boost::optional<node_info> next_node() final;
-
- private:
- bool has_at_least_one_good_node() const;
- void append_new_nodes();
- void truncate();
-
- private:
- struct node
- {
- std::string address;
- size_t fails;
-
- void handle_result(bool success);
- };
-
- struct by_address {};
- struct by_fails {};
-
- typedef boost::multi_index_container<
- node,
- boost::multi_index::indexed_by<
- boost::multi_index::ordered_unique<boost::multi_index::tag<by_address>, boost::multi_index::member<node, std::string, &node::address>>,
- boost::multi_index::ordered_non_unique<boost::multi_index::tag<by_fails>, boost::multi_index::member<node, size_t, &node::fails>>
- >
- > nodes_list;
-
- const std::function<std::map<std::string, bool>()> m_get_nodes;
- const size_t m_max_nodes;
- nodes_list m_nodes;
- };
-
-}
-}
diff --git a/src/rpc/core_rpc_server.cpp b/src/rpc/core_rpc_server.cpp
index a6885a6..9e66736 100644
--- a/src/rpc/core_rpc_server.cpp
+++ b/src/rpc/core_rpc_server.cpp
@@ -153,9 +153,6 @@ namespace cryptonote
command_line::add_arg(desc, arg_rpc_bind_port);
command_line::add_arg(desc, arg_rpc_restricted_bind_port);
command_line::add_arg(desc, arg_restricted_rpc);
- command_line::add_arg(desc, arg_bootstrap_daemon_address);
- command_line::add_arg(desc, arg_bootstrap_daemon_login);
- command_line::add_arg(desc, arg_bootstrap_daemon_proxy);
cryptonote::rpc_args::init_options(desc, true);
command_line::add_arg(desc, arg_rpc_max_connections_per_public_ip);
command_line::add_arg(desc, arg_rpc_max_connections_per_private_ip);
@@ -169,79 +166,9 @@ 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,
- const std::string &proxy)
- {
- boost::optional<epee::net_utils::http::login> credentials;
- const auto loc = username_password.find(':');
- if (loc != std::string::npos)
- {
- credentials = epee::net_utils::http::login(username_password.substr(0, loc), username_password.substr(loc + 1));
- }
- return set_bootstrap_daemon(address, credentials, proxy);
- }
- //------------------------------------------------------------------------------------------------------------------------------
- std::map<std::string, bool> core_rpc_server::get_public_nodes(uint32_t/* = 0*/)
- {
- COMMAND_RPC_GET_PUBLIC_NODES::request request;
- COMMAND_RPC_GET_PUBLIC_NODES::response response;
-
- request.gray = true;
- request.white = true;
- request.include_blocked = false;
- if (!on_get_public_nodes(request, response) || response.status != CORE_RPC_STATUS_OK)
- {
- return {};
- }
-
- std::map<std::string, bool> result;
-
- const auto append = [&result](const std::vector<public_node> &nodes, bool white) {
- for (const auto &node : nodes)
- {
- result.insert(std::make_pair(node.host + ":" + std::to_string(node.rpc_port), white));
- }
- };
-
- append(response.white, true);
- append(response.gray, false);
-
- return result;
- }
- //------------------------------------------------------------------------------------------------------------------------------
- bool core_rpc_server::set_bootstrap_daemon(
- const std::string &address,
- const boost::optional<epee::net_utils::http::login> &credentials,
- const std::string &proxy)
- {
- boost::unique_lock<boost::shared_mutex> lock(m_bootstrap_daemon_mutex);
-
- if (address.empty())
- {
- m_bootstrap_daemon.reset(nullptr);
- }
- else if (address == "auto")
- {
- auto get_nodes = [this]() {
- return get_public_nodes(0);
- };
- m_bootstrap_daemon.reset(new bootstrap_daemon(std::move(get_nodes), m_bootstrap_daemon_proxy.empty() ? proxy : m_bootstrap_daemon_proxy));
- }
- else
- {
- m_bootstrap_daemon.reset(new bootstrap_daemon(address, credentials, m_bootstrap_daemon_proxy.empty() ? proxy : m_bootstrap_daemon_proxy));
- }
-
- m_should_use_bootstrap_daemon = m_bootstrap_daemon.get() != nullptr;
-
- return true;
- }
core_rpc_server::~core_rpc_server()
{
}
@@ -253,7 +180,6 @@ namespace cryptonote
, const std::string& proxy
)
{
- m_bootstrap_daemon_proxy = proxy;
m_restricted = restricted;
m_net_server.set_threads_prefix("RPC");
m_net_server.set_connection_filter(&m_p2p);
@@ -277,15 +203,6 @@ namespace cryptonote
disable_rpc_ban = rpc_config->disable_rpc_ban;
const std::string data_dir{command_line::get_arg(vm, cryptonote::arg_data_dir)};
- if (!set_bootstrap_daemon(
- command_line::get_arg(vm, arg_bootstrap_daemon_address),
- command_line::get_arg(vm, arg_bootstrap_daemon_login),
- command_line::get_arg(vm, arg_bootstrap_daemon_proxy)))
- {
- MFATAL("Failed to parse bootstrap daemon address");
- return false;
- }
-
boost::optional<epee::net_utils::http::login> http_login{};
if (rpc_config->login)
@@ -408,9 +325,6 @@ namespace cryptonote
bool core_rpc_server::on_get_height(const COMMAND_RPC_GET_HEIGHT::request& req, COMMAND_RPC_GET_HEIGHT::response& res, const connection_context *ctx)
{
RPC_TRACKER(get_height);
- bool r;
- if (use_bootstrap_daemon_if_necessary<COMMAND_RPC_GET_HEIGHT>(invoke_http_mode::JON, "/getheight", req, res, r))
- return r;
crypto::hash hash;
m_core.get_blockchain_top(res.height, hash);
@@ -423,22 +337,6 @@ namespace cryptonote
bool core_rpc_server::on_get_info(const COMMAND_RPC_GET_INFO::request& req, COMMAND_RPC_GET_INFO::response& res, const connection_context *ctx)
{
RPC_TRACKER(get_info);
- bool r;
- if (use_bootstrap_daemon_if_necessary<COMMAND_RPC_GET_INFO>(invoke_http_mode::JON, "/getinfo", req, res, r))
- {
- {
- boost::shared_lock<boost::shared_mutex> lock(m_bootstrap_daemon_mutex);
- if (m_bootstrap_daemon.get() != nullptr)
- {
- res.bootstrap_daemon_address = m_bootstrap_daemon->address();
- }
- }
- crypto::hash top_hash;
- m_core.get_blockchain_top(res.height_without_bootstrap, top_hash);
- ++res.height_without_bootstrap; // turn top block height into blockchain height
- res.was_bootstrap_ever_used = true;
- return r;
- }
const bool restricted = m_restricted && ctx;
@@ -473,21 +371,6 @@ namespace cryptonote
res.start_time = restricted ? 0 : (uint64_t)m_core.get_start_time();
res.free_space = restricted ? std::numeric_limits<uint64_t>::max() : m_core.get_free_space();
res.offline = m_core.offline();
- res.height_without_bootstrap = restricted ? 0 : res.height;
- if (restricted)
- {
- res.bootstrap_daemon_address = "";
- res.was_bootstrap_ever_used = false;
- }
- else
- {
- boost::shared_lock<boost::shared_mutex> lock(m_bootstrap_daemon_mutex);
- if (m_bootstrap_daemon.get() != nullptr)
- {
- res.bootstrap_daemon_address = m_bootstrap_daemon->address();
- }
- res.was_bootstrap_ever_used = m_was_bootstrap_ever_used;
- }
res.database_size = m_core.get_blockchain_storage().get_db().get_database_size();
if (restricted)
res.database_size = round_up(res.database_size, 5ull* 1024 * 1024 * 1024);
@@ -504,7 +387,7 @@ namespace cryptonote
bool core_rpc_server::on_get_net_stats(const COMMAND_RPC_GET_NET_STATS::request& req, COMMAND_RPC_GET_NET_STATS::response& res, const connection_context *ctx)
{
RPC_TRACKER(get_net_stats);
- // No bootstrap daemon check: Only ever get stats about local server
+
res.start_time = (uint64_t)m_core.get_start_time();
{
CRITICAL_REGION_LOCAL(epee::net_utils::network_throttle_manager::m_lock_get_global_throttle_in);
@@ -532,17 +415,6 @@ namespace cryptonote
{
RPC_TRACKER(get_blocks);
- bool use_bootstrap_daemon;
- {
- boost::shared_lock<boost::shared_mutex> lock(m_bootstrap_daemon_mutex);
- use_bootstrap_daemon = m_should_use_bootstrap_daemon;
- }
- if (use_bootstrap_daemon)
- {
- bool r;
- return use_bootstrap_daemon_if_necessary<COMMAND_RPC_GET_BLOCKS_FAST>(invoke_http_mode::BIN, "/getblocks.bin", req, res, r);
- }
-
res.daemon_time = (uint64_t)time(NULL);
// Always set daemon time, and set it early rather than late, as delivering some incremental pool
// info twice because of slightly overlapping time intervals is no problem, whereas producing gaps
@@ -713,9 +585,6 @@ namespace cryptonote
bool core_rpc_server::on_get_alt_blocks_hashes(const COMMAND_RPC_GET_ALT_BLOCKS_HASHES::request& req, COMMAND_RPC_GET_ALT_BLOCKS_HASHES::response& res, const connection_context *ctx)
{
RPC_TRACKER(get_alt_blocks_hashes);
- bool r;
- if (use_bootstrap_daemon_if_necessary<COMMAND_RPC_GET_ALT_BLOCKS_HASHES>(invoke_http_mode::JON, "/get_alt_blocks_hashes", req, res, r))
- return r;
std::vector<block> blks;
@@ -740,9 +609,6 @@ namespace cryptonote
bool core_rpc_server::on_get_blocks_by_height(const COMMAND_RPC_GET_BLOCKS_BY_HEIGHT::request& req, COMMAND_RPC_GET_BLOCKS_BY_HEIGHT::response& res, const connection_context *ctx)
{
RPC_TRACKER(get_blocks_by_height);
- bool r;
- if (use_bootstrap_daemon_if_necessary<COMMAND_RPC_GET_BLOCKS_BY_HEIGHT>(invoke_http_mode::BIN, "/getblocks_by_height.bin", req, res, r))
- return r;
const bool restricted = m_restricted && ctx;
if (restricted && req.heights.size() > RESTRICTED_BLOCK_COUNT)
@@ -781,9 +647,6 @@ namespace cryptonote
bool core_rpc_server::on_get_hashes(const COMMAND_RPC_GET_HASHES_FAST::request& req, COMMAND_RPC_GET_HASHES_FAST::response& res, const connection_context *ctx)
{
RPC_TRACKER(get_hashes);
- bool r;
- if (use_bootstrap_daemon_if_necessary<COMMAND_RPC_GET_HASHES_FAST>(invoke_http_mode::BIN, "/gethashes.bin", req, res, r))
- return r;
res.start_height = req.start_height;
if(!m_core.get_blockchain_storage().find_blockchain_supplement(req.block_ids, res.m_block_ids, NULL, res.start_height, res.current_height, false))
@@ -800,9 +663,6 @@ namespace cryptonote
bool core_rpc_server::on_get_outs_bin(const COMMAND_RPC_GET_OUTPUTS_BIN::request& req, COMMAND_RPC_GET_OUTPUTS_BIN::response& res, const connection_context *ctx)
{
RPC_TRACKER(get_outs_bin);
- bool r;
- if (use_bootstrap_daemon_if_necessary<COMMAND_RPC_GET_OUTPUTS_BIN>(invoke_http_mode::BIN, "/get_outs.bin", req, res, r))
- return r;
res.status = "Failed";
@@ -828,9 +688,6 @@ namespace cryptonote
bool core_rpc_server::on_get_outs(const COMMAND_RPC_GET_OUTPUTS::request& req, COMMAND_RPC_GET_OUTPUTS::response& res, const connection_context *ctx)
{
RPC_TRACKER(get_outs);
- bool r;
- if (use_bootstrap_daemon_if_necessary<COMMAND_RPC_GET_OUTPUTS>(invoke_http_mode::JON, "/get_outs", req, res, r))
- return r;
res.status = "Failed";
@@ -873,9 +730,6 @@ namespace cryptonote
bool core_rpc_server::on_get_indexes(const COMMAND_RPC_GET_TX_GLOBAL_OUTPUTS_INDEXES::request& req, COMMAND_RPC_GET_TX_GLOBAL_OUTPUTS_INDEXES::response& res, const connection_context *ctx)
{
RPC_TRACKER(get_indexes);
- bool ok;
- if (use_bootstrap_daemon_if_necessary<COMMAND_RPC_GET_TX_GLOBAL_OUTPUTS_INDEXES>(invoke_http_mode::BIN, "/get_o_indexes.bin", req, res, ok))
- return ok;
bool r = m_core.get_tx_outputs_gindexs(req.txid, res.o_indexes);
if(!r)
@@ -891,9 +745,6 @@ namespace cryptonote
bool core_rpc_server::on_get_transactions(const COMMAND_RPC_GET_TRANSACTIONS::request& req, COMMAND_RPC_GET_TRANSACTIONS::response& res, const connection_context *ctx)
{
RPC_TRACKER(get_transactions);
- bool ok;
- if (use_bootstrap_daemon_if_necessary<COMMAND_RPC_GET_TRANSACTIONS>(invoke_http_mode::JON, "/gettransactions", req, res, ok))
- return ok;
const bool restricted = m_restricted && ctx;
const bool request_has_rpc_origin = ctx != NULL;
@@ -1139,9 +990,6 @@ namespace cryptonote
bool core_rpc_server::on_is_key_image_spent(const COMMAND_RPC_IS_KEY_IMAGE_SPENT::request& req, COMMAND_RPC_IS_KEY_IMAGE_SPENT::response& res, const connection_context *ctx)
{
RPC_TRACKER(is_key_image_spent);
- bool ok;
- if (use_bootstrap_daemon_if_necessary<COMMAND_RPC_IS_KEY_IMAGE_SPENT>(invoke_http_mode::JON, "/is_key_image_spent", req, res, ok))
- return ok;
const bool restricted = m_restricted && ctx;
if (restricted && req.key_images.size() > RESTRICTED_SPENT_KEY_IMAGES_COUNT)
@@ -1226,30 +1074,7 @@ namespace cryptonote
{
RPC_TRACKER(send_raw_tx);
- {
- bool ok;
- use_bootstrap_daemon_if_necessary<COMMAND_RPC_SEND_RAW_TX>(invoke_http_mode::JON, "/sendrawtransaction", req, res, ok);
- }
-
- const bool restricted = m_restricted && ctx;
-
- bool skip_validation = false;
- if (!restricted)
- {
- boost::shared_lock<boost::shared_mutex> lock(m_bootstrap_daemon_mutex);
- if (m_should_use_bootstrap_daemon)
- {
- skip_validation = !check_core_ready();
- }
- else
- {
- CHECK_CORE_READY();
- }
- }
- else
- {
- CHECK_CORE_READY();
- }
+ CHECK_CORE_READY();
std::string tx_blob;
if(!string_tools::parse_hexstr_to_binbuff(req.tx_as_hex, tx_blob))
@@ -1269,53 +1094,50 @@ namespace cryptonote
}
res.sanity_check_failed = false;
- if (!skip_validation)
+ tx_verification_context tvc{};
+ if(!m_core.handle_incoming_tx(tx_blob, tvc, (req.do_not_relay ? relay_method::none : relay_method::local), false) || tvc.m_verifivation_failed)
{
- tx_verification_context tvc{};
- if(!m_core.handle_incoming_tx(tx_blob, tvc, (req.do_not_relay ? relay_method::none : relay_method::local), false) || tvc.m_verifivation_failed)
- {
- res.status = "Failed";
- std::string reason = "";
- if ((res.low_mixin = tvc.m_low_mixin))
- add_reason(reason, "bad ring size");
- if ((res.double_spend = tvc.m_double_spend))
- add_reason(reason, "double spend");
- if ((res.invalid_input = tvc.m_invalid_input))
- add_reason(reason, "invalid input");
- if ((res.invalid_output = tvc.m_invalid_output))
- add_reason(reason, "invalid output");
- if ((res.too_big = tvc.m_too_big))
- add_reason(reason, "too big");
- if ((res.overspend = tvc.m_overspend))
- add_reason(reason, "overspend");
- if ((res.fee_too_low = tvc.m_fee_too_low))
- add_reason(reason, "fee too low");
- if ((res.too_few_outputs = tvc.m_too_few_outputs))
- add_reason(reason, "too few outputs");
- if ((res.tx_extra_too_big = tvc.m_tx_extra_too_big))
- add_reason(reason, "tx-extra too big");
- if ((res.nonzero_unlock_time = tvc.m_nonzero_unlock_time))
- add_reason(reason, "tx unlock time is not zero");
- const std::string punctuation = reason.empty() ? "" : ": ";
- if (tvc.m_verifivation_failed)
- {
- LOG_PRINT_L0("[on_send_raw_tx]: tx verification failed" << punctuation << reason);
- }
- else
- {
- LOG_PRINT_L0("[on_send_raw_tx]: Failed to process tx" << punctuation << reason);
- }
- return true;
+ res.status = "Failed";
+ std::string reason = "";
+ if ((res.low_mixin = tvc.m_low_mixin))
+ add_reason(reason, "bad ring size");
+ if ((res.double_spend = tvc.m_double_spend))
+ add_reason(reason, "double spend");
+ if ((res.invalid_input = tvc.m_invalid_input))
+ add_reason(reason, "invalid input");
+ if ((res.invalid_output = tvc.m_invalid_output))
+ add_reason(reason, "invalid output");
+ if ((res.too_big = tvc.m_too_big))
+ add_reason(reason, "too big");
+ if ((res.overspend = tvc.m_overspend))
+ add_reason(reason, "overspend");
+ if ((res.fee_too_low = tvc.m_fee_too_low))
+ add_reason(reason, "fee too low");
+ if ((res.too_few_outputs = tvc.m_too_few_outputs))
+ add_reason(reason, "too few outputs");
+ if ((res.tx_extra_too_big = tvc.m_tx_extra_too_big))
+ add_reason(reason, "tx-extra too big");
+ if ((res.nonzero_unlock_time = tvc.m_nonzero_unlock_time))
+ add_reason(reason, "tx unlock time is not zero");
+ const std::string punctuation = reason.empty() ? "" : ": ";
+ if (tvc.m_verifivation_failed)
+ {
+ LOG_PRINT_L0("[on_send_raw_tx]: tx verification failed" << punctuation << reason);
}
-
- if(tvc.m_relay == relay_method::none)
+ else
{
- LOG_PRINT_L0("[on_send_raw_tx]: tx accepted, but not relayed");
- res.reason = "Not relayed";
- res.not_relayed = true;
- res.status = CORE_RPC_STATUS_OK;
- return true;
+ LOG_PRINT_L0("[on_send_raw_tx]: Failed to process tx" << punctuation << reason);
}
+ return true;
+ }
+
+ if(tvc.m_relay == relay_method::none)
+ {
+ LOG_PRINT_L0("[on_send_raw_tx]: tx accepted, but not relayed");
+ res.reason = "Not relayed";
+ res.not_relayed = true;
+ res.status = CORE_RPC_STATUS_OK;
+ return true;
}
NOTIFY_NEW_TRANSACTIONS::request r;
@@ -1579,9 +1401,6 @@ namespace cryptonote
bool core_rpc_server::on_get_transaction_pool(const COMMAND_RPC_GET_TRANSACTION_POOL::request& req, COMMAND_RPC_GET_TRANSACTION_POOL::response& res, const connection_context *ctx)
{
RPC_TRACKER(get_transaction_pool);
- bool r;
- if (use_bootstrap_daemon_if_necessary<COMMAND_RPC_GET_TRANSACTION_POOL>(invoke_http_mode::JON, "/get_transaction_pool", req, res, r))
- return r;
const bool restricted = m_restricted && ctx;
const bool request_has_rpc_origin = ctx != NULL;
@@ -1602,9 +1421,6 @@ namespace cryptonote
bool core_rpc_server::on_get_transaction_pool_hashes_bin(const COMMAND_RPC_GET_TRANSACTION_POOL_HASHES_BIN::request& req, COMMAND_RPC_GET_TRANSACTION_POOL_HASHES_BIN::response& res, const connection_context *ctx)
{
RPC_TRACKER(get_transaction_pool_hashes);
- bool r;
- if (use_bootstrap_daemon_if_necessary<COMMAND_RPC_GET_TRANSACTION_POOL_HASHES_BIN>(invoke_http_mode::JON, "/get_transaction_pool_hashes.bin", req, res, r))
- return r;
const bool restricted = m_restricted && ctx;
const bool request_has_rpc_origin = ctx != NULL;
@@ -1623,9 +1439,6 @@ namespace cryptonote
bool core_rpc_server::on_get_transaction_pool_hashes(const COMMAND_RPC_GET_TRANSACTION_POOL_HASHES::request& req, COMMAND_RPC_GET_TRANSACTION_POOL_HASHES::response& res, const connection_context *ctx)
{
RPC_TRACKER(get_transaction_pool_hashes);
- bool r;
- if (use_bootstrap_daemon_if_necessary<COMMAND_RPC_GET_TRANSACTION_POOL_HASHES>(invoke_http_mode::JON, "/get_transaction_pool_hashes", req, res, r))
- return r;
const bool restricted = m_restricted && ctx;
const bool request_has_rpc_origin = ctx != NULL;
@@ -1648,9 +1461,6 @@ namespace cryptonote
bool core_rpc_server::on_get_transaction_pool_stats(const COMMAND_RPC_GET_TRANSACTION_POOL_STATS::request& req, COMMAND_RPC_GET_TRANSACTION_POOL_STATS::response& res, const connection_context *ctx)
{
RPC_TRACKER(get_transaction_pool_stats);
- bool r;
- if (use_bootstrap_daemon_if_necessary<COMMAND_RPC_GET_TRANSACTION_POOL_STATS>(invoke_http_mode::JON, "/get_transaction_pool_stats", req, res, r))
- return r;
const bool restricted = m_restricted && ctx;
const bool request_has_rpc_origin = ctx != NULL;
@@ -1660,28 +1470,6 @@ namespace cryptonote
return true;
}
//------------------------------------------------------------------------------------------------------------------------------
- bool core_rpc_server::on_set_bootstrap_daemon(const COMMAND_RPC_SET_BOOTSTRAP_DAEMON::request& req, COMMAND_RPC_SET_BOOTSTRAP_DAEMON::response& res, const connection_context *ctx)
- {
- PERF_TIMER(on_set_bootstrap_daemon);
-
- boost::optional<epee::net_utils::http::login> credentials;
- if (!req.username.empty() || !req.password.empty())
- {
- credentials = epee::net_utils::http::login(req.username, req.password);
- }
-
- if (set_bootstrap_daemon(req.address, credentials, req.proxy))
- {
- res.status = CORE_RPC_STATUS_OK;
- }
- else
- {
- res.status = "Failed to set bootstrap daemon";
- }
-
- return true;
- }
- //------------------------------------------------------------------------------------------------------------------------------
bool core_rpc_server::on_stop_daemon(const COMMAND_RPC_STOP_DAEMON::request& req, COMMAND_RPC_STOP_DAEMON::response& res, const connection_context *ctx)
{
RPC_TRACKER(stop_daemon);
@@ -1695,14 +1483,7 @@ namespace cryptonote
bool core_rpc_server::on_getblockcount(const COMMAND_RPC_GETBLOCKCOUNT::request& req, COMMAND_RPC_GETBLOCKCOUNT::response& res, const connection_context *ctx)
{
RPC_TRACKER(getblockcount);
- {
- boost::shared_lock<boost::shared_mutex> lock(m_bootstrap_daemon_mutex);
- if (m_should_use_bootstrap_daemon)
- {
- res.status = "This command is unsupported for bootstrap daemon";
- return true;
- }
- }
+
res.count = m_core.get_current_blockchain_height();
res.status = CORE_RPC_STATUS_OK;
return true;
@@ -1711,14 +1492,7 @@ namespace cryptonote
bool core_rpc_server::on_getblockhash(const COMMAND_RPC_GETBLOCKHASH::request& req, COMMAND_RPC_GETBLOCKHASH::response& res, epee::json_rpc::error& error_resp, const connection_context *ctx)
{
RPC_TRACKER(getblockhash);
- {
- boost::shared_lock<boost::shared_mutex> lock(m_bootstrap_daemon_mutex);
- if (m_should_use_bootstrap_daemon)
- {
- res = "This command is unsupported for bootstrap daemon";
- return true;
- }
- }
+
if(req.size() != 1)
{
error_resp.code = CORE_RPC_ERROR_CODE_WRONG_PARAM;
@@ -1808,9 +1582,6 @@ namespace cryptonote
bool core_rpc_server::on_getblocktemplate(const COMMAND_RPC_GETBLOCKTEMPLATE::request& req, COMMAND_RPC_GETBLOCKTEMPLATE::response& res, epee::json_rpc::error& error_resp, const connection_context *ctx)
{
RPC_TRACKER(getblocktemplate);
- bool r;
- if (use_bootstrap_daemon_if_necessary<COMMAND_RPC_GETBLOCKTEMPLATE>(invoke_http_mode::JON_RPC, "getblocktemplate", req, res, r))
- return r;
if(!check_core_ready())
{
@@ -2002,9 +1773,6 @@ namespace cryptonote
bool core_rpc_server::on_add_aux_pow(const COMMAND_RPC_ADD_AUX_POW::request& req, COMMAND_RPC_ADD_AUX_POW::response& res, epee::json_rpc::error& error_resp, const connection_context *ctx)
{
RPC_TRACKER(add_aux_pow);
- bool r;
- if (use_bootstrap_daemon_if_necessary<COMMAND_RPC_ADD_AUX_POW>(invoke_http_mode::JON_RPC, "add_aux_pow", req, res, r))
- return r;
const bool restricted = m_restricted && ctx;
@@ -2148,15 +1916,7 @@ namespace cryptonote
bool core_rpc_server::on_submitblock(const COMMAND_RPC_SUBMITBLOCK::request& req, COMMAND_RPC_SUBMITBLOCK::response& res, epee::json_rpc::error& error_resp, const connection_context *ctx)
{
RPC_TRACKER(submitblock);
- {
- boost::shared_lock<boost::shared_mutex> lock(m_bootstrap_daemon_mutex);
- if (m_should_use_bootstrap_daemon)
- {
- error_resp.code = CORE_RPC_ERROR_CODE_UNSUPPORTED_BOOTSTRAP;
- error_resp.message = "This command is unsupported for bootstrap daemon";
- return false;
- }
- }
+
CHECK_CORE_READY();
if(req.size()!=1)
{
@@ -2313,103 +2073,9 @@ namespace cryptonote
return true;
}
//------------------------------------------------------------------------------------------------------------------------------
- template <typename COMMAND_TYPE>
- bool core_rpc_server::use_bootstrap_daemon_if_necessary(const invoke_http_mode &mode, const std::string &command_name, const typename COMMAND_TYPE::request& req, typename COMMAND_TYPE::response& res, bool &r)
- {
- res.untrusted = false;
- r = false;
-
- boost::upgrade_lock<boost::shared_mutex> upgrade_lock(m_bootstrap_daemon_mutex);
-
- if (m_bootstrap_daemon.get() == nullptr)
- {
- return false;
- }
-
- if (!m_should_use_bootstrap_daemon)
- {
- MINFO("The local daemon is fully synced. Not switching back to the bootstrap daemon");
- return false;
- }
-
- auto current_time = std::chrono::system_clock::now();
- if (current_time - m_bootstrap_height_check_time > std::chrono::seconds(30)) // update every 30s
- {
- {
- boost::upgrade_to_unique_lock<boost::shared_mutex> lock(upgrade_lock);
- m_bootstrap_height_check_time = current_time;
- }
-
- boost::optional<std::pair<uint64_t, uint64_t>> bootstrap_daemon_height_info = m_bootstrap_daemon->get_height();
- if (!bootstrap_daemon_height_info)
- {
- MERROR("Failed to fetch bootstrap daemon height");
- return false;
- }
-
- const uint64_t bootstrap_daemon_height = bootstrap_daemon_height_info->first;
- const uint64_t bootstrap_daemon_target_height = bootstrap_daemon_height_info->second;
- if (bootstrap_daemon_height < bootstrap_daemon_target_height)
- {
- MINFO("Bootstrap daemon is out of sync");
- return m_bootstrap_daemon->handle_result(false, {});
- }
-
- if (bootstrap_daemon_height < m_core.get_checkpoints().get_max_height())
- {
- MINFO("Bootstrap daemon height is lower than the latest checkpoint");
- return m_bootstrap_daemon->handle_result(false, {});
- }
-
- if (!m_p2p.get_payload_object().no_sync())
- {
- uint64_t top_height = m_core.get_current_blockchain_height();
- m_should_use_bootstrap_daemon = top_height + 10 < bootstrap_daemon_height;
- MINFO((m_should_use_bootstrap_daemon ? "Using" : "Not using") << " the bootstrap daemon (our height: " << top_height << ", bootstrap daemon's height: " << bootstrap_daemon_height << ")");
-
- if (!m_should_use_bootstrap_daemon)
- return false;
- }
- }
-
- if (mode == invoke_http_mode::JON)
- {
- r = m_bootstrap_daemon->invoke_http_json(command_name, req, res);
- }
- else if (mode == invoke_http_mode::BIN)
- {
- r = m_bootstrap_daemon->invoke_http_bin(command_name, req, res);
- }
- else if (mode == invoke_http_mode::JON_RPC)
- {
- r = m_bootstrap_daemon->invoke_http_json_rpc(command_name, req, res);
- }
- else
- {
- MERROR("Unknown invoke_http_mode: " << mode);
- return false;
- }
-
- {
- boost::upgrade_to_unique_lock<boost::shared_mutex> lock(upgrade_lock);
- m_was_bootstrap_ever_used = true;
- }
-
- 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 r;
- }
- //------------------------------------------------------------------------------------------------------------------------------
bool core_rpc_server::on_get_last_block_header(const COMMAND_RPC_GET_LAST_BLOCK_HEADER::request& req, COMMAND_RPC_GET_LAST_BLOCK_HEADER::response& res, epee::json_rpc::error& error_resp, const connection_context *ctx)
{
RPC_TRACKER(get_last_block_header);
- bool r;
- if (use_bootstrap_daemon_if_necessary<COMMAND_RPC_GET_LAST_BLOCK_HEADER>(invoke_http_mode::JON_RPC, "getlastblockheader", req, res, r))
- return r;
CHECK_CORE_READY();
uint64_t last_block_height;
@@ -2438,9 +2104,6 @@ namespace cryptonote
bool core_rpc_server::on_get_block_header_by_hash(const COMMAND_RPC_GET_BLOCK_HEADER_BY_HASH::request& req, COMMAND_RPC_GET_BLOCK_HEADER_BY_HASH::response& res, epee::json_rpc::error& error_resp, const connection_context *ctx)
{
RPC_TRACKER(get_block_header_by_hash);
- bool r;
- if (use_bootstrap_daemon_if_necessary<COMMAND_RPC_GET_BLOCK_HEADER_BY_HASH>(invoke_http_mode::JON_RPC, "getblockheaderbyhash", req, res, r))
- return r;
const bool restricted = m_restricted && ctx;
if (restricted && req.hashes.size() > RESTRICTED_BLOCK_COUNT)
@@ -2505,9 +2168,6 @@ namespace cryptonote
bool core_rpc_server::on_get_block_headers_range(const COMMAND_RPC_GET_BLOCK_HEADERS_RANGE::request& req, COMMAND_RPC_GET_BLOCK_HEADERS_RANGE::response& res, epee::json_rpc::error& error_resp, const connection_context *ctx)
{
RPC_TRACKER(get_block_headers_range);
- bool r;
- if (use_bootstrap_daemon_if_necessary<COMMAND_RPC_GET_BLOCK_HEADERS_RANGE>(invoke_http_mode::JON_RPC, "getblockheadersrange", req, res, r))
- return r;
const uint64_t bc_height = m_core.get_current_blockchain_height();
if (req.start_height >= bc_height || req.end_height >= bc_height || req.start_height > req.end_height)
@@ -2564,9 +2224,6 @@ namespace cryptonote
bool core_rpc_server::on_get_block_header_by_height(const COMMAND_RPC_GET_BLOCK_HEADER_BY_HEIGHT::request& req, COMMAND_RPC_GET_BLOCK_HEADER_BY_HEIGHT::response& res, epee::json_rpc::error& error_resp, const connection_context *ctx)
{
RPC_TRACKER(get_block_header_by_height);
- bool r;
- if (use_bootstrap_daemon_if_necessary<COMMAND_RPC_GET_BLOCK_HEADER_BY_HEIGHT>(invoke_http_mode::JON_RPC, "getblockheaderbyheight", req, res, r))
- return r;
if(m_core.get_current_blockchain_height() <= req.height)
{
@@ -2598,9 +2255,6 @@ namespace cryptonote
bool core_rpc_server::on_get_block(const COMMAND_RPC_GET_BLOCK::request& req, COMMAND_RPC_GET_BLOCK::response& res, epee::json_rpc::error& error_resp, const connection_context *ctx)
{
RPC_TRACKER(get_block);
- bool r;
- if (use_bootstrap_daemon_if_necessary<COMMAND_RPC_GET_BLOCK>(invoke_http_mode::JON_RPC, "getblock", req, res, r))
- return r;
crypto::hash block_hash;
if (!req.hash.empty())
@@ -2683,9 +2337,6 @@ namespace cryptonote
bool core_rpc_server::on_hard_fork_info(const COMMAND_RPC_HARD_FORK_INFO::request& req, COMMAND_RPC_HARD_FORK_INFO::response& res, epee::json_rpc::error& error_resp, const connection_context *ctx)
{
RPC_TRACKER(hard_fork_info);
- bool r;
- if (use_bootstrap_daemon_if_necessary<COMMAND_RPC_HARD_FORK_INFO>(invoke_http_mode::JON_RPC, "hard_fork_info", req, res, r))
- return r;
const Blockchain &blockchain = m_core.get_blockchain_storage();
uint8_t version = req.version > 0 ? req.version : blockchain.get_next_hard_fork_version();
@@ -2871,9 +2522,6 @@ namespace cryptonote
bool core_rpc_server::on_get_output_histogram(const COMMAND_RPC_GET_OUTPUT_HISTOGRAM::request& req, COMMAND_RPC_GET_OUTPUT_HISTOGRAM::response& res, epee::json_rpc::error& error_resp, const connection_context *ctx)
{
RPC_TRACKER(get_output_histogram);
- bool r;
- if (use_bootstrap_daemon_if_necessary<COMMAND_RPC_GET_OUTPUT_HISTOGRAM>(invoke_http_mode::JON_RPC, "get_output_histogram", req, res, r))
- return r;
const bool restricted = m_restricted && ctx;
size_t amounts = req.amounts.size();
@@ -2915,9 +2563,6 @@ namespace cryptonote
bool core_rpc_server::on_get_version(const COMMAND_RPC_GET_VERSION::request& req, COMMAND_RPC_GET_VERSION::response& res, epee::json_rpc::error& error_resp, const connection_context *ctx)
{
RPC_TRACKER(get_version);
- bool r;
- if (use_bootstrap_daemon_if_necessary<COMMAND_RPC_GET_VERSION>(invoke_http_mode::JON_RPC, "get_version", req, res, r))
- return r;
res.version = CORE_RPC_VERSION;
res.release = MONERO_VERSION_IS_RELEASE;
@@ -2948,9 +2593,6 @@ namespace cryptonote
bool core_rpc_server::on_get_base_fee_estimate(const COMMAND_RPC_GET_BASE_FEE_ESTIMATE::request& req, COMMAND_RPC_GET_BASE_FEE_ESTIMATE::response& res, epee::json_rpc::error& error_resp, const connection_context *ctx)
{
RPC_TRACKER(get_base_fee_estimate);
- bool r;
- if (use_bootstrap_daemon_if_necessary<COMMAND_RPC_GET_BASE_FEE_ESTIMATE>(invoke_http_mode::JON_RPC, "get_fee_estimate", req, res, r))
- return r;
{
m_core.get_blockchain_storage().get_dynamic_base_fee_estimate_2021_scaling(req.grace_blocks, res.fees);
@@ -2997,9 +2639,6 @@ namespace cryptonote
bool core_rpc_server::on_get_limit(const COMMAND_RPC_GET_LIMIT::request& req, COMMAND_RPC_GET_LIMIT::response& res, const connection_context *ctx)
{
RPC_TRACKER(get_limit);
- bool r;
- if (use_bootstrap_daemon_if_necessary<COMMAND_RPC_GET_LIMIT>(invoke_http_mode::JON, "/get_limit", req, res, r))
- return r;
res.limit_down = epee::net_utils::connection_basic::get_rate_down_limit();
res.limit_up = epee::net_utils::connection_basic::get_rate_up_limit();
@@ -3261,9 +2900,6 @@ namespace cryptonote
bool core_rpc_server::on_get_txpool_backlog(const COMMAND_RPC_GET_TRANSACTION_POOL_BACKLOG::request& req, COMMAND_RPC_GET_TRANSACTION_POOL_BACKLOG::response& res, epee::json_rpc::error& error_resp, const connection_context *ctx)
{
RPC_TRACKER(get_txpool_backlog);
- bool r;
- if (use_bootstrap_daemon_if_necessary<COMMAND_RPC_GET_TRANSACTION_POOL_BACKLOG>(invoke_http_mode::JON_RPC, "get_txpool_backlog", req, res, r))
- return r;
if (!m_core.get_txpool_backlog(res.backlog))
{
@@ -3279,9 +2915,6 @@ namespace cryptonote
bool core_rpc_server::on_get_output_distribution(const COMMAND_RPC_GET_OUTPUT_DISTRIBUTION::request& req, COMMAND_RPC_GET_OUTPUT_DISTRIBUTION::response& res, epee::json_rpc::error& error_resp, const connection_context *ctx)
{
RPC_TRACKER(get_output_distribution);
- bool r;
- if (use_bootstrap_daemon_if_necessary<COMMAND_RPC_GET_OUTPUT_DISTRIBUTION>(invoke_http_mode::JON_RPC, "get_output_distribution", req, res, r))
- return r;
const bool restricted = m_restricted && ctx;
if (restricted && req.amounts != std::vector<uint64_t>(1, 0))
@@ -3323,10 +2956,6 @@ namespace cryptonote
{
RPC_TRACKER(get_output_distribution_bin);
- bool r;
- if (use_bootstrap_daemon_if_necessary<COMMAND_RPC_GET_OUTPUT_DISTRIBUTION>(invoke_http_mode::BIN, "/get_output_distribution.bin", req, res, r))
- return r;
-
const bool restricted = m_restricted && ctx;
if (restricted && req.amounts != std::vector<uint64_t>(1, 0))
{
@@ -3405,9 +3034,6 @@ namespace cryptonote
{
RPC_TRACKER(get_txids_loose);
- // Maybe don't use bootstrap since this endpoint is meant to retrieve TXIDs w/ k-anonymity,
- // so shunting this request to a random node seems counterproductive.
-
#if BYTE_ORDER == LITTLE_ENDIAN
const uint64_t max_num_txids = RESTRICTED_SPENT_KEY_IMAGES_COUNT * (m_restricted ? 1 : 10);
@@ -3503,25 +3129,6 @@ namespace cryptonote
, false
};
- const command_line::arg_descriptor<std::string> core_rpc_server::arg_bootstrap_daemon_address = {
- "bootstrap-daemon-address"
- , "URL of a 'bootstrap' remote daemon that the connected wallets can use while this daemon is still not fully synced.\n"
- "Use 'auto' to enable automatic public nodes discovering and bootstrap daemon switching"
- , ""
- };
-
- const command_line::arg_descriptor<std::string> core_rpc_server::arg_bootstrap_daemon_login = {
- "bootstrap-daemon-login"
- , "Specify username:password for the bootstrap daemon login"
- , ""
- };
-
- const command_line::arg_descriptor<std::string> core_rpc_server::arg_bootstrap_daemon_proxy = {
- "bootstrap-daemon-proxy"
- , "<ip>:<port> socks proxy to use for bootstrap daemon connections"
- , ""
- };
-
const command_line::arg_descriptor<std::size_t> core_rpc_server::arg_rpc_max_connections_per_public_ip = {
"rpc-max-connections-per-public-ip"
, "Max RPC connections per public IP permitted"
diff --git a/src/rpc/core_rpc_server.h b/src/rpc/core_rpc_server.h
index f263101..5902093 100644
--- a/src/rpc/core_rpc_server.h
+++ b/src/rpc/core_rpc_server.h
@@ -35,7 +35,6 @@
#include <boost/program_options/options_description.hpp>
#include <boost/program_options/variables_map.hpp>
-#include "bootstrap_daemon.h"
#include "net/http_server_impl_base.h"
#include "net/http_client.h"
#include "core_rpc_server_commands_defs.h"
@@ -64,9 +63,6 @@ namespace cryptonote
static const command_line::arg_descriptor<std::string> arg_rpc_ssl_ca_certificates;
static const command_line::arg_descriptor<std::vector<std::string>> arg_rpc_ssl_allowed_fingerprints;
static const command_line::arg_descriptor<bool> arg_rpc_ssl_allow_any_cert;
- static const command_line::arg_descriptor<std::string> arg_bootstrap_daemon_address;
- static const command_line::arg_descriptor<std::string> arg_bootstrap_daemon_login;
- static const command_line::arg_descriptor<std::string> arg_bootstrap_daemon_proxy;
static const command_line::arg_descriptor<std::size_t> arg_rpc_max_connections_per_public_ip;
static const command_line::arg_descriptor<std::size_t> arg_rpc_max_connections_per_private_ip;
static const command_line::arg_descriptor<std::size_t> arg_rpc_max_connections;
@@ -121,7 +117,6 @@ namespace cryptonote
MAP_URI_AUTO_JON2("/get_transaction_pool_hashes.bin", on_get_transaction_pool_hashes_bin, COMMAND_RPC_GET_TRANSACTION_POOL_HASHES_BIN)
MAP_URI_AUTO_JON2("/get_transaction_pool_hashes", on_get_transaction_pool_hashes, COMMAND_RPC_GET_TRANSACTION_POOL_HASHES)
MAP_URI_AUTO_JON2("/get_transaction_pool_stats", on_get_transaction_pool_stats, COMMAND_RPC_GET_TRANSACTION_POOL_STATS)
- MAP_URI_AUTO_JON2_IF("/set_bootstrap_daemon", on_set_bootstrap_daemon, COMMAND_RPC_SET_BOOTSTRAP_DAEMON, !m_restricted)
MAP_URI_AUTO_JON2_IF("/stop_daemon", on_stop_daemon, COMMAND_RPC_STOP_DAEMON, !m_restricted)
MAP_URI_AUTO_JON2("/get_info", on_get_info, COMMAND_RPC_GET_INFO)
MAP_URI_AUTO_JON2("/getinfo", on_get_info, COMMAND_RPC_GET_INFO)
@@ -205,7 +200,6 @@ namespace cryptonote
bool on_get_transaction_pool_hashes_bin(const COMMAND_RPC_GET_TRANSACTION_POOL_HASHES_BIN::request& req, COMMAND_RPC_GET_TRANSACTION_POOL_HASHES_BIN::response& res, const connection_context *ctx = NULL);
bool on_get_transaction_pool_hashes(const COMMAND_RPC_GET_TRANSACTION_POOL_HASHES::request& req, COMMAND_RPC_GET_TRANSACTION_POOL_HASHES::response& res, const connection_context *ctx = NULL);
bool on_get_transaction_pool_stats(const COMMAND_RPC_GET_TRANSACTION_POOL_STATS::request& req, COMMAND_RPC_GET_TRANSACTION_POOL_STATS::response& res, const connection_context *ctx = NULL);
- bool on_set_bootstrap_daemon(const COMMAND_RPC_SET_BOOTSTRAP_DAEMON::request& req, COMMAND_RPC_SET_BOOTSTRAP_DAEMON::response& res, const connection_context *ctx = NULL);
bool on_stop_daemon(const COMMAND_RPC_STOP_DAEMON::request& req, COMMAND_RPC_STOP_DAEMON::response& res, const connection_context *ctx = NULL);
bool on_get_limit(const COMMAND_RPC_GET_LIMIT::request& req, COMMAND_RPC_GET_LIMIT::response& res, const connection_context *ctx = NULL);
bool on_set_limit(const COMMAND_RPC_SET_LIMIT::request& req, COMMAND_RPC_SET_LIMIT::response& res, const connection_context *ctx = NULL);
@@ -258,28 +252,10 @@ private:
//utils
uint64_t get_block_reward(const block& blk);
bool fill_block_header_response(const block& blk, bool orphan_status, uint64_t height, const crypto::hash& hash, block_header_response& response, bool fill_pow_hash);
- std::map<std::string, bool> get_public_nodes(uint32_t credits_per_hash_threshold = 0);
- bool set_bootstrap_daemon(
- const std::string &address,
- const std::string &username_password,
- const std::string &proxy);
- bool set_bootstrap_daemon(
- const std::string &address,
- const boost::optional<epee::net_utils::http::login> &credentials,
- const std::string &proxy);
- enum invoke_http_mode { JON, BIN, JON_RPC };
- template <typename COMMAND_TYPE>
- bool use_bootstrap_daemon_if_necessary(const invoke_http_mode &mode, const std::string &command_name, const typename COMMAND_TYPE::request& req, typename COMMAND_TYPE::response& res, bool &r);
bool get_block_template(const account_public_address &address, const crypto::hash *prev_block, const cryptonote::blobdata &extra_nonce, size_t &reserved_offset, cryptonote::difficulty_type &difficulty, uint64_t &height, uint64_t &expected_reward, uint64_t& cumulative_weight, block &b, uint64_t &seed_height, crypto::hash &seed_hash, crypto::hash &next_seed_hash, epee::json_rpc::error &error_resp);
core& m_core;
nodetool::node_server<cryptonote::t_cryptonote_protocol_handler<cryptonote::core> >& m_p2p;
- boost::shared_mutex m_bootstrap_daemon_mutex;
- std::unique_ptr<bootstrap_daemon> m_bootstrap_daemon;
- std::string m_bootstrap_daemon_proxy;
- bool m_should_use_bootstrap_daemon;
- std::chrono::system_clock::time_point m_bootstrap_height_check_time;
- bool m_was_bootstrap_ever_used;
bool m_restricted;
epee::critical_section m_host_fails_score_lock;
std::map<std::string, uint64_t> m_host_fails_score;
diff --git a/src/rpc/core_rpc_server_commands_defs.h b/src/rpc/core_rpc_server_commands_defs.h
index 7815964..edc0058 100644
--- a/src/rpc/core_rpc_server_commands_defs.h
+++ b/src/rpc/core_rpc_server_commands_defs.h
@@ -101,7 +101,7 @@ inline const std::string get_rpc_status(const bool trusted_daemon, const std::st
// 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 17
+#define CORE_RPC_VERSION_MINOR 18
#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)
@@ -114,13 +114,9 @@ inline const std::string get_rpc_status(const bool trusted_daemon, const std::st
struct rpc_response_base
{
std::string status;
- bool untrusted;
-
- rpc_response_base(): untrusted(false) {}
BEGIN_KV_SERIALIZE_MAP()
KV_SERIALIZE(status)
- KV_SERIALIZE(untrusted)
END_KV_SERIALIZE_MAP()
};
@@ -723,9 +719,6 @@ inline const std::string get_rpc_status(const bool trusted_daemon, const std::st
uint64_t start_time;
uint64_t free_space;
bool offline;
- std::string bootstrap_daemon_address;
- uint64_t height_without_bootstrap;
- bool was_bootstrap_ever_used;
uint64_t database_size;
bool update_available;
bool busy_syncing;
@@ -765,9 +758,6 @@ inline const std::string get_rpc_status(const bool trusted_daemon, const std::st
KV_SERIALIZE(start_time)
KV_SERIALIZE(free_space)
KV_SERIALIZE(offline)
- KV_SERIALIZE(bootstrap_daemon_address)
- KV_SERIALIZE(height_without_bootstrap)
- KV_SERIALIZE(was_bootstrap_ever_used)
KV_SERIALIZE(database_size)
KV_SERIALIZE(update_available)
KV_SERIALIZE(busy_syncing)
@@ -1775,35 +1765,6 @@ inline const std::string get_rpc_status(const bool trusted_daemon, const std::st
typedef epee::misc_utils::struct_init<response_t> response;
};
- struct COMMAND_RPC_SET_BOOTSTRAP_DAEMON
- {
- struct request_t
- {
- std::string address;
- std::string username;
- std::string password;
- std::string proxy;
-
- BEGIN_KV_SERIALIZE_MAP()
- KV_SERIALIZE(address)
- KV_SERIALIZE(username)
- KV_SERIALIZE(password)
- KV_SERIALIZE(proxy)
- END_KV_SERIALIZE_MAP()
- };
- typedef epee::misc_utils::struct_init<request_t> request;
-
- struct response_t
- {
- std::string status;
-
- BEGIN_KV_SERIALIZE_MAP()
- KV_SERIALIZE(status)
- END_KV_SERIALIZE_MAP()
- };
- typedef epee::misc_utils::struct_init<response_t> response;
- };
-
struct COMMAND_RPC_STOP_DAEMON
{
struct request_t: public rpc_request_base
diff --git a/src/simplewallet/simplewallet.cpp b/src/simplewallet/simplewallet.cpp
index 50c61d4..bc1a7cc 100644
--- a/src/simplewallet/simplewallet.cpp
+++ b/src/simplewallet/simplewallet.cpp
@@ -4602,13 +4602,6 @@ bool simple_wallet::init(const boost::program_options::variables_map& vm)
message_writer(console_color_red, true) << boost::format(tr("Using your own without SSL exposes your RPC traffic to monitoring"));
message_writer(console_color_red, true) << boost::format(tr("You are strongly encouraged to connect to the Monero network using your own daemon"));
message_writer(console_color_red, true) << boost::format(tr("If you or someone you trust are operating this daemon, you can use --trusted-daemon"));
-
- COMMAND_RPC_GET_INFO::request req;
- COMMAND_RPC_GET_INFO::response res;
- bool r = m_wallet->invoke_http_json("/get_info", req, res);
- std::string err = interpret_rpc_response(r, res.status);
- if (r && err.empty() && (res.was_bootstrap_ever_used || !res.bootstrap_daemon_address.empty()))
- message_writer(console_color_red, true) << boost::format(tr("Moreover, a daemon is also less secure when running in bootstrap mode"));
}
if (m_wallet->get_ring_database().empty())
diff --git a/tests/fuzz/fuzz_rpc/fuzz_rpc.cpp b/tests/fuzz/fuzz_rpc/fuzz_rpc.cpp
index 92ffe99..1f38da3 100644
--- a/tests/fuzz/fuzz_rpc/fuzz_rpc.cpp
+++ b/tests/fuzz/fuzz_rpc/fuzz_rpc.cpp
@@ -67,9 +67,6 @@ extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) {
return 0;
}
- // Disable bootstrap daemon
- disable_bootstrap_daemon(*rpc_handler->rpc);
-
for (unsigned selector : selectors) {
try {
// Fuzz the target function
diff --git a/tests/fuzz/fuzz_rpc/rpc_endpoints.cpp b/tests/fuzz/fuzz_rpc/rpc_endpoints.cpp
index b794e91..2a4d658 100644
--- a/tests/fuzz/fuzz_rpc/rpc_endpoints.cpp
+++ b/tests/fuzz/fuzz_rpc/rpc_endpoints.cpp
@@ -7,19 +7,6 @@
cryptonote::core_rpc_server::connection_context ctx;
epee::json_rpc::error error_resp;
-// Helper function to disable bootstrap daemon
-void disable_bootstrap_daemon(cryptonote::core_rpc_server& rpc) {
- cryptonote::COMMAND_RPC_SET_BOOTSTRAP_DAEMON::request req;
- cryptonote::COMMAND_RPC_SET_BOOTSTRAP_DAEMON::response res;
-
- req.address = "";
- req.username = "";
- req.password = "";
- req.proxy = "";
-
- rpc.on_set_bootstrap_daemon(req, res, &ctx);
-}
-
// Retrieve fuzz targets base on SAFE settings
std::map<int, std::function<void(cryptonote::core_rpc_server& rpc, FuzzedDataProvider&)>> get_fuzz_targets(bool safe) {
std::map<int, std::function<void(cryptonote::core_rpc_server& rpc, FuzzedDataProvider&)>> results;
@@ -313,21 +300,6 @@ void fuzz_get_transaction_pool_stats(cryptonote::core_rpc_server& rpc, FuzzedDat
rpc.on_get_transaction_pool_stats(req, res, &ctx);
}
-void fuzz_set_bootstrap_daemon(cryptonote::core_rpc_server& rpc, FuzzedDataProvider& provider) {
- cryptonote::COMMAND_RPC_SET_BOOTSTRAP_DAEMON::request req;
- cryptonote::COMMAND_RPC_SET_BOOTSTRAP_DAEMON::response res;
-
- req.address = provider.ConsumeRandomLengthString(64);
- req.username = provider.ConsumeRandomLengthString(32);
- req.password = provider.ConsumeRandomLengthString(32);
- req.proxy = provider.ConsumeRandomLengthString(32);
-
- rpc.on_set_bootstrap_daemon(req, res, &ctx);
-
- // Immediate reset bootstrap daemon to avoid affecting other fuzzing with external calls
- disable_bootstrap_daemon(rpc);
-}
-
void fuzz_stop_daemon(cryptonote::core_rpc_server& rpc, FuzzedDataProvider& provider) {
cryptonote::COMMAND_RPC_STOP_DAEMON::request req;
cryptonote::COMMAND_RPC_STOP_DAEMON::response res;
@@ -865,7 +837,6 @@ std::map<int, std::function<void(cryptonote::core_rpc_server&, FuzzedDataProvide
{56, fuzz_stop_mining},
{57, fuzz_mining_status},
{58, fuzz_save_bc},
- {59, fuzz_set_bootstrap_daemon},
{60, fuzz_stop_daemon},
{61, fuzz_update},
{62, fuzz_add_aux_pow},
diff --git a/tests/fuzz/fuzz_rpc/rpc_endpoints.h b/tests/fuzz/fuzz_rpc/rpc_endpoints.h
index c720c18..ca34bd8 100644
--- a/tests/fuzz/fuzz_rpc/rpc_endpoints.h
+++ b/tests/fuzz/fuzz_rpc/rpc_endpoints.h
@@ -9,7 +9,6 @@ namespace tools {
extern __thread std::vector<LoggingPerformanceTimer*> *performance_timers;
}
-void disable_bootstrap_daemon(cryptonote::core_rpc_server& rpc);
std::map<int, std::function<void(cryptonote::core_rpc_server& rpc, FuzzedDataProvider&)>> get_fuzz_targets(bool safe);
void fuzz_get_height(cryptonote::core_rpc_server&, FuzzedDataProvider& provider);
@@ -35,7 +34,6 @@ void fuzz_get_transaction_pool(cryptonote::core_rpc_server&, FuzzedDataProvider&
void fuzz_get_transaction_pool_hashes_bin(cryptonote::core_rpc_server&, FuzzedDataProvider& provider);
void fuzz_get_transaction_pool_hashes(cryptonote::core_rpc_server&, FuzzedDataProvider& provider);
void fuzz_get_transaction_pool_stats(cryptonote::core_rpc_server&, FuzzedDataProvider& provider);
-void fuzz_set_bootstrap_daemon(cryptonote::core_rpc_server&, FuzzedDataProvider& provider);
void fuzz_stop_daemon(cryptonote::core_rpc_server&, FuzzedDataProvider& provider);
void fuzz_get_info(cryptonote::core_rpc_server&, FuzzedDataProvider& provider);
void fuzz_get_net_stats(cryptonote::core_rpc_server&, FuzzedDataProvider& provider);
diff --git a/tests/unit_tests/CMakeLists.txt b/tests/unit_tests/CMakeLists.txt
index dc30a24..0aea4ff 100644
--- a/tests/unit_tests/CMakeLists.txt
+++ b/tests/unit_tests/CMakeLists.txt
@@ -34,7 +34,6 @@ set(unit_tests_sources
blockchain_db.cpp
block_queue.cpp
block_reward.cpp
- bootstrap_node_selector.cpp
bulletproofs.cpp
bulletproofs_plus.cpp
canonical_amounts.cpp
diff --git a/tests/unit_tests/bootstrap_node_selector.cpp b/tests/unit_tests/bootstrap_node_selector.cpp
deleted file mode 100644
index 1ac9b91..0000000
--- a/tests/unit_tests/bootstrap_node_selector.cpp
+++ /dev/null
@@ -1,173 +0,0 @@
-// Copyright (c) 2020-2024, 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 <gtest/gtest.h>
-
-#include "rpc/bootstrap_node_selector.h"
-
-class bootstrap_node_selector : public ::testing::Test
-{
-protected:
- void SetUp() override
- {
- nodes.insert(white_nodes.begin(), white_nodes.end());
- nodes.insert(gray_nodes.begin(), gray_nodes.end());
- }
-
- const std::map<std::string, bool> white_nodes = {
- {
- "white_node_1:18089", true
- },
- {
- "white_node_2:18081", true
- }
- };
- const std::map<std::string, bool> gray_nodes = {
- {
- "gray_node_1:18081", false
- },
- {
- "gray_node_2:18089", false
- }
- };
-
- std::map<std::string, bool> nodes;
-};
-
-TEST_F(bootstrap_node_selector, selector_auto_empty)
-{
- cryptonote::bootstrap_node::selector_auto selector([]() {
- return std::map<std::string, bool>();
- });
-
- EXPECT_FALSE(selector.next_node());
-}
-
-TEST_F(bootstrap_node_selector, selector_auto_no_credentials)
-{
- cryptonote::bootstrap_node::selector_auto selector([this]() {
- return nodes;
- });
-
- for (size_t fails = 0; fails < nodes.size(); ++fails)
- {
- const auto current = selector.next_node();
- EXPECT_FALSE(current->credentials);
-
- selector.handle_result(current->address, false);
- }
-}
-
-TEST_F(bootstrap_node_selector, selector_auto_success)
-{
- cryptonote::bootstrap_node::selector_auto selector([this]() {
- return nodes;
- });
-
- auto current = selector.next_node();
- for (size_t fails = 0; fails < nodes.size(); ++fails)
- {
- selector.handle_result(current->address, true);
-
- current = selector.next_node();
- EXPECT_TRUE(white_nodes.count(current->address) > 0);
- }
-}
-
-TEST_F(bootstrap_node_selector, selector_auto_failure)
-{
- cryptonote::bootstrap_node::selector_auto selector([this]() {
- return nodes;
- });
-
- auto current = selector.next_node();
- for (size_t fails = 0; fails < nodes.size(); ++fails)
- {
- const auto previous = current;
-
- selector.handle_result(current->address, false);
-
- current = selector.next_node();
- EXPECT_NE(current->address, previous->address);
- }
-}
-
-TEST_F(bootstrap_node_selector, selector_auto_white_nodes_first)
-{
- cryptonote::bootstrap_node::selector_auto selector([this]() {
- return nodes;
- });
-
- for (size_t iterations = 0; iterations < 2; ++iterations)
- {
- for (size_t fails = 0; fails < white_nodes.size(); ++fails)
- {
- const auto current = selector.next_node();
- EXPECT_TRUE(white_nodes.count(current->address) > 0);
-
- selector.handle_result(current->address, false);
- }
-
- for (size_t fails = 0; fails < gray_nodes.size(); ++fails)
- {
- const auto current = selector.next_node();
- EXPECT_TRUE(gray_nodes.count(current->address) > 0);
-
- selector.handle_result(current->address, false);
- }
- }
-}
-
-TEST_F(bootstrap_node_selector, selector_auto_max_nodes)
-{
- const size_t max_nodes = nodes.size() / 2;
-
- bool populated_once = false;
- cryptonote::bootstrap_node::selector_auto selector([this, &populated_once]() {
- if (!populated_once)
- {
- populated_once = true;
- return nodes;
- }
-
- return std::map<std::string, bool>();
- }, max_nodes);
-
- std::set<std::string> unique_nodes;
-
- for (size_t fails = 0; fails < nodes.size(); ++fails)
- {
- const auto current = selector.next_node();
- unique_nodes.insert(current->address);
-
- selector.handle_result(current->address, false);
- }
-
- EXPECT_EQ(unique_nodes.size(), max_nodes);
-}
diff --git a/utils/fish/monerod.fish b/utils/fish/monerod.fish
index c8d2b8c..3b2b2b3 100644
--- a/utils/fish/monerod.fish
+++ b/utils/fish/monerod.fish
@@ -83,9 +83,6 @@ complete -c monerod -l max-connections-per-ip -r -d "Maximum number of connectio
complete -c monerod -l rpc-bind-port -r -d "Port for RPC server. Default: 18081, 28081 if 'testnet', 38081 if 'stagenet'"
complete -c monerod -l rpc-restricted-bind-port -r -d "Port for restricted RPC server"
complete -c monerod -l restricted-rpc -d "Restrict RPC to view only commands and do not return privacy sensitive data in RPC calls"
-complete -c monerod -l bootstrap-daemon-address -r -d "URL of a 'bootstrap' remote daemon that the connected wallets can use while this daemon is still not fully synced. Use 'auto' to enable automatic public nodes discovering and bootstrap daemon switching"
-complete -c monerod -l bootstrap-daemon-login -r -d "Specify username:password for the bootstrap daemon login"
-complete -c monerod -l bootstrap-daemon-proxy -r -d "<ip>:<port> socks proxy to use for bootstrap daemon connections"
complete -c monerod -l rpc-bind-ip -r -d "Specify IP to bind RPC server. Default: 127.0.0.1"
complete -c monerod -l rpc-bind-ipv6-address -r -d "Specify IPv6 address to bind RPC server. Default: ::1"
complete -c monerod -l rpc-restricted-bind-ip -r -d "Specify IP to bind restricted RPC server. Default: 127.0.0.1"
diff --git a/utils/python-rpc/framework/daemon.py b/utils/python-rpc/framework/daemon.py
index adab420..8dacc40 100644
--- a/utils/python-rpc/framework/daemon.py
+++ b/utils/python-rpc/framework/daemon.py
@@ -329,14 +329,6 @@ class Daemon(object):
}
return self.rpc.send_json_rpc_request(banned)
- def set_bootstrap_daemon(self, address, username = '', password = ''):
- set_bootstrap_daemon = {
- 'address': address,
- 'username': username,
- 'password': password,
- }
- return self.rpc.send_request('/set_bootstrap_daemon', set_bootstrap_daemon)
-
def get_public_nodes(self, gray = False, white = True):
get_public_nodes = {
'gray': gray,
Why this scored 22/100
Community notes
Notes can correct, qualify, or add evidence to the AI analysis. Every note shown here has been validated by a human moderator.
The AI analysis stands alone for now. Submit a note if you can add evidence or important context.