bootstrap_daemon: proxy configuration support

This commit is contained in:
xiphon 2021-01-19 08:50:12 +00:00
parent 964ad0e51a
commit cf266d66dd
9 changed files with 126 additions and 28 deletions

View file

@ -986,17 +986,67 @@ bool t_command_parser_executor::check_blockchain_pruning(const std::vector<std::
bool t_command_parser_executor::set_bootstrap_daemon(const std::vector<std::string>& args) bool t_command_parser_executor::set_bootstrap_daemon(const std::vector<std::string>& args)
{ {
const size_t args_count = args.size(); struct parsed_t
if (args_count < 1 || args_count > 3) {
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; std::cout << "Invalid syntax: Wrong number of parameters. For more details, use the help command." << std::endl;
return true; return true;
} }
return m_executor.set_bootstrap_daemon( return m_executor.set_bootstrap_daemon(parsed->address, parsed->user, parsed->password, parsed->proxy);
args[0] != "none" ? args[0] : std::string(),
args_count > 1 ? args[1] : std::string(),
args_count > 2 ? args[2] : std::string());
} }
bool t_command_parser_executor::flush_cache(const std::vector<std::string>& args) bool t_command_parser_executor::flush_cache(const std::vector<std::string>& args)

View file

@ -326,7 +326,7 @@ t_command_server::t_command_server(
m_command_lookup.set_handler( m_command_lookup.set_handler(
"set_bootstrap_daemon" "set_bootstrap_daemon"
, std::bind(&t_command_parser_executor::set_bootstrap_daemon, &m_parser, p::_1) , std::bind(&t_command_parser_executor::set_bootstrap_daemon, &m_parser, p::_1)
, "set_bootstrap_daemon (auto | none | host[:port] [username] [password])" , "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" , "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" "Use 'auto' to enable automatic public nodes discovering and bootstrap daemon switching"
); );

View file

@ -2405,7 +2405,8 @@ bool t_rpc_command_executor::check_blockchain_pruning()
bool t_rpc_command_executor::set_bootstrap_daemon( bool t_rpc_command_executor::set_bootstrap_daemon(
const std::string &address, const std::string &address,
const std::string &username, const std::string &username,
const std::string &password) const std::string &password,
const std::string &proxy)
{ {
cryptonote::COMMAND_RPC_SET_BOOTSTRAP_DAEMON::request req; cryptonote::COMMAND_RPC_SET_BOOTSTRAP_DAEMON::request req;
cryptonote::COMMAND_RPC_SET_BOOTSTRAP_DAEMON::response res; cryptonote::COMMAND_RPC_SET_BOOTSTRAP_DAEMON::response res;
@ -2414,6 +2415,7 @@ bool t_rpc_command_executor::set_bootstrap_daemon(
req.address = address; req.address = address;
req.username = username; req.username = username;
req.password = password; req.password = password;
req.proxy = proxy;
if (m_is_rpc) if (m_is_rpc)
{ {

View file

@ -168,7 +168,8 @@ public:
bool set_bootstrap_daemon( bool set_bootstrap_daemon(
const std::string &address, const std::string &address,
const std::string &username, const std::string &username,
const std::string &password); const std::string &password,
const std::string &proxy);
bool rpc_payments(); bool rpc_payments();

View file

@ -7,6 +7,7 @@
#include "crypto/crypto.h" #include "crypto/crypto.h"
#include "cryptonote_core/cryptonote_core.h" #include "cryptonote_core/cryptonote_core.h"
#include "misc_log_ex.h" #include "misc_log_ex.h"
#include "net/parse.h"
#undef MONERO_DEFAULT_LOG_CATEGORY #undef MONERO_DEFAULT_LOG_CATEGORY
#define MONERO_DEFAULT_LOG_CATEGORY "daemon.rpc.bootstrap_daemon" #define MONERO_DEFAULT_LOG_CATEGORY "daemon.rpc.bootstrap_daemon"
@ -16,19 +17,23 @@ namespace cryptonote
bootstrap_daemon::bootstrap_daemon( bootstrap_daemon::bootstrap_daemon(
std::function<std::map<std::string, bool>()> get_public_nodes, std::function<std::map<std::string, bool>()> get_public_nodes,
bool rpc_payment_enabled) bool rpc_payment_enabled,
const std::string &proxy)
: m_selector(new bootstrap_node::selector_auto(std::move(get_public_nodes))) : m_selector(new bootstrap_node::selector_auto(std::move(get_public_nodes)))
, m_rpc_payment_enabled(rpc_payment_enabled) , m_rpc_payment_enabled(rpc_payment_enabled)
{ {
set_proxy(proxy);
} }
bootstrap_daemon::bootstrap_daemon( bootstrap_daemon::bootstrap_daemon(
const std::string &address, const std::string &address,
boost::optional<epee::net_utils::http::login> credentials, boost::optional<epee::net_utils::http::login> credentials,
bool rpc_payment_enabled) bool rpc_payment_enabled,
const std::string &proxy)
: m_selector(nullptr) : m_selector(nullptr)
, m_rpc_payment_enabled(rpc_payment_enabled) , m_rpc_payment_enabled(rpc_payment_enabled)
{ {
set_proxy(proxy);
if (!set_server(address, std::move(credentials))) if (!set_server(address, std::move(credentials)))
{ {
throw std::runtime_error("invalid bootstrap daemon address or credentials"); throw std::runtime_error("invalid bootstrap daemon address or credentials");
@ -78,6 +83,18 @@ namespace cryptonote
return success; 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 */) 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)) if (!m_http_client.set_server(address, credentials))

View file

@ -8,7 +8,7 @@
#include <boost/thread/mutex.hpp> #include <boost/thread/mutex.hpp>
#include <boost/utility/string_ref.hpp> #include <boost/utility/string_ref.hpp>
#include "net/http_client.h" #include "net/http.h"
#include "storages/http_abstract_invoke.h" #include "storages/http_abstract_invoke.h"
#include "bootstrap_node_selector.h" #include "bootstrap_node_selector.h"
@ -21,11 +21,13 @@ namespace cryptonote
public: public:
bootstrap_daemon( bootstrap_daemon(
std::function<std::map<std::string, bool>()> get_public_nodes, std::function<std::map<std::string, bool>()> get_public_nodes,
bool rpc_payment_enabled); bool rpc_payment_enabled,
const std::string &proxy);
bootstrap_daemon( bootstrap_daemon(
const std::string &address, const std::string &address,
boost::optional<epee::net_utils::http::login> credentials, boost::optional<epee::net_utils::http::login> credentials,
bool rpc_payment_enabled); bool rpc_payment_enabled,
const std::string &proxy);
std::string address() const noexcept; std::string address() const noexcept;
boost::optional<std::pair<uint64_t, uint64_t>> get_height(); boost::optional<std::pair<uint64_t, uint64_t>> get_height();
@ -72,12 +74,14 @@ namespace cryptonote
return handle_result(result, result_struct.status); return handle_result(result, result_struct.status);
} }
void set_proxy(const std::string &address);
private: private:
bool set_server(const std::string &address, const boost::optional<epee::net_utils::http::login> &credentials = boost::none); bool set_server(const std::string &address, const boost::optional<epee::net_utils::http::login> &credentials = boost::none);
bool switch_server_if_needed(); bool switch_server_if_needed();
private: private:
epee::net_utils::http::http_simple_client m_http_client; net::http::client m_http_client;
const bool m_rpc_payment_enabled; const bool m_rpc_payment_enabled;
const std::unique_ptr<bootstrap_node::selector> m_selector; const std::unique_ptr<bootstrap_node::selector> m_selector;
boost::mutex m_selector_mutex; boost::mutex m_selector_mutex;

View file

@ -154,6 +154,7 @@ namespace cryptonote
command_line::add_arg(desc, arg_restricted_rpc); 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_address);
command_line::add_arg(desc, arg_bootstrap_daemon_login); 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); cryptonote::rpc_args::init_options(desc, true);
command_line::add_arg(desc, arg_rpc_payment_address); command_line::add_arg(desc, arg_rpc_payment_address);
command_line::add_arg(desc, arg_rpc_payment_difficulty); command_line::add_arg(desc, arg_rpc_payment_difficulty);
@ -172,7 +173,10 @@ namespace cryptonote
, m_rpc_payment_allow_free_loopback(false) , m_rpc_payment_allow_free_loopback(false)
{} {}
//------------------------------------------------------------------------------------------------------------------------------ //------------------------------------------------------------------------------------------------------------------------------
bool core_rpc_server::set_bootstrap_daemon(const std::string &address, const std::string &username_password) 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; boost::optional<epee::net_utils::http::login> credentials;
const auto loc = username_password.find(':'); const auto loc = username_password.find(':');
@ -180,7 +184,7 @@ namespace cryptonote
{ {
credentials = epee::net_utils::http::login(username_password.substr(0, loc), username_password.substr(loc + 1)); credentials = epee::net_utils::http::login(username_password.substr(0, loc), username_password.substr(loc + 1));
} }
return set_bootstrap_daemon(address, credentials); return set_bootstrap_daemon(address, credentials, proxy);
} }
//------------------------------------------------------------------------------------------------------------------------------ //------------------------------------------------------------------------------------------------------------------------------
std::map<std::string, bool> core_rpc_server::get_public_nodes(uint32_t credits_per_hash_threshold/* = 0*/) std::map<std::string, bool> core_rpc_server::get_public_nodes(uint32_t credits_per_hash_threshold/* = 0*/)
@ -217,7 +221,10 @@ namespace cryptonote
return result; return result;
} }
//------------------------------------------------------------------------------------------------------------------------------ //------------------------------------------------------------------------------------------------------------------------------
bool core_rpc_server::set_bootstrap_daemon(const std::string &address, const boost::optional<epee::net_utils::http::login> &credentials) 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); boost::unique_lock<boost::shared_mutex> lock(m_bootstrap_daemon_mutex);
@ -233,11 +240,11 @@ namespace cryptonote
auto get_nodes = [this]() { auto get_nodes = [this]() {
return get_public_nodes(credits_per_hash_threshold); return get_public_nodes(credits_per_hash_threshold);
}; };
m_bootstrap_daemon.reset(new bootstrap_daemon(std::move(get_nodes), rpc_payment_enabled)); m_bootstrap_daemon.reset(new bootstrap_daemon(std::move(get_nodes), rpc_payment_enabled, proxy));
} }
else else
{ {
m_bootstrap_daemon.reset(new bootstrap_daemon(address, credentials, rpc_payment_enabled)); m_bootstrap_daemon.reset(new bootstrap_daemon(address, credentials, rpc_payment_enabled, proxy));
} }
m_should_use_bootstrap_daemon = m_bootstrap_daemon.get() != nullptr; m_should_use_bootstrap_daemon = m_bootstrap_daemon.get() != nullptr;
@ -318,8 +325,10 @@ namespace cryptonote
MWARNING("The RPC server is accessible from the outside, but no RPC payment was setup. RPC access will be free for all."); MWARNING("The RPC server is accessible from the outside, but no RPC payment was setup. RPC access will be free for all.");
} }
if (!set_bootstrap_daemon(command_line::get_arg(vm, arg_bootstrap_daemon_address), if (!set_bootstrap_daemon(
command_line::get_arg(vm, arg_bootstrap_daemon_login))) 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"); MFATAL("Failed to parse bootstrap daemon address");
return false; return false;
@ -1596,15 +1605,15 @@ namespace cryptonote
{ {
credentials = epee::net_utils::http::login(req.username, req.password); credentials = epee::net_utils::http::login(req.username, req.password);
} }
if (set_bootstrap_daemon(req.address, credentials)) if (set_bootstrap_daemon(req.address, credentials, req.proxy))
{ {
res.status = CORE_RPC_STATUS_OK; res.status = CORE_RPC_STATUS_OK;
} }
else else
{ {
res.status = "Failed to set bootstrap daemon"; res.status = "Failed to set bootstrap daemon";
} }
return true; return true;
} }
@ -3349,6 +3358,12 @@ namespace cryptonote
, "" , ""
}; };
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::string> core_rpc_server::arg_rpc_payment_address = { const command_line::arg_descriptor<std::string> core_rpc_server::arg_rpc_payment_address = {
"rpc-payment-address" "rpc-payment-address"
, "Restrict RPC to clients sending micropayment to this address" , "Restrict RPC to clients sending micropayment to this address"

View file

@ -72,6 +72,7 @@ namespace cryptonote
static const command_line::arg_descriptor<bool> arg_rpc_ssl_allow_any_cert; 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_address;
static const command_line::arg_descriptor<std::string> arg_bootstrap_daemon_login; 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::string> arg_rpc_payment_address; static const command_line::arg_descriptor<std::string> arg_rpc_payment_address;
static const command_line::arg_descriptor<uint64_t> arg_rpc_payment_difficulty; static const command_line::arg_descriptor<uint64_t> arg_rpc_payment_difficulty;
static const command_line::arg_descriptor<uint64_t> arg_rpc_payment_credits; static const command_line::arg_descriptor<uint64_t> arg_rpc_payment_credits;
@ -268,8 +269,14 @@ private:
uint64_t get_block_reward(const block& blk); 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); 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); 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); bool set_bootstrap_daemon(
bool set_bootstrap_daemon(const std::string &address, const boost::optional<epee::net_utils::http::login> &credentials); 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 }; enum invoke_http_mode { JON, BIN, JON_RPC };
template <typename COMMAND_TYPE> 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 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);

View file

@ -88,7 +88,7 @@ namespace cryptonote
// advance which version they will stop working with // advance which version they will stop working with
// Don't go over 32767 for any of these // Don't go over 32767 for any of these
#define CORE_RPC_VERSION_MAJOR 3 #define CORE_RPC_VERSION_MAJOR 3
#define CORE_RPC_VERSION_MINOR 5 #define CORE_RPC_VERSION_MINOR 6
#define MAKE_CORE_RPC_VERSION(major,minor) (((major)<<16)|(minor)) #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) #define CORE_RPC_VERSION MAKE_CORE_RPC_VERSION(CORE_RPC_VERSION_MAJOR, CORE_RPC_VERSION_MINOR)
@ -1613,11 +1613,13 @@ namespace cryptonote
std::string address; std::string address;
std::string username; std::string username;
std::string password; std::string password;
std::string proxy;
BEGIN_KV_SERIALIZE_MAP() BEGIN_KV_SERIALIZE_MAP()
KV_SERIALIZE(address) KV_SERIALIZE(address)
KV_SERIALIZE(username) KV_SERIALIZE(username)
KV_SERIALIZE(password) KV_SERIALIZE(password)
KV_SERIALIZE(proxy)
END_KV_SERIALIZE_MAP() END_KV_SERIALIZE_MAP()
}; };
typedef epee::misc_utils::struct_init<request_t> request; typedef epee::misc_utils::struct_init<request_t> request;