aboutsummaryrefslogtreecommitdiff
path: root/src/rpc
diff options
context:
space:
mode:
Diffstat (limited to 'src/rpc')
-rw-r--r--src/rpc/bootstrap_daemon.cpp21
-rw-r--r--src/rpc/bootstrap_daemon.h12
-rw-r--r--src/rpc/core_rpc_server.cpp182
-rw-r--r--src/rpc/core_rpc_server.h13
-rw-r--r--src/rpc/core_rpc_server_commands_defs.h50
5 files changed, 255 insertions, 23 deletions
diff --git a/src/rpc/bootstrap_daemon.cpp b/src/rpc/bootstrap_daemon.cpp
index 2fdd28406..ffea906d5 100644
--- a/src/rpc/bootstrap_daemon.cpp
+++ b/src/rpc/bootstrap_daemon.cpp
@@ -7,6 +7,7 @@
#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"
@@ -16,19 +17,23 @@ namespace cryptonote
bootstrap_daemon::bootstrap_daemon(
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_rpc_payment_enabled(rpc_payment_enabled)
{
+ set_proxy(proxy);
}
bootstrap_daemon::bootstrap_daemon(
const std::string &address,
boost::optional<epee::net_utils::http::login> credentials,
- bool rpc_payment_enabled)
+ bool rpc_payment_enabled,
+ const std::string &proxy)
: m_selector(nullptr)
, m_rpc_payment_enabled(rpc_payment_enabled)
{
+ set_proxy(proxy);
if (!set_server(address, std::move(credentials)))
{
throw std::runtime_error("invalid bootstrap daemon address or credentials");
@@ -78,6 +83,18 @@ namespace cryptonote
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))
diff --git a/src/rpc/bootstrap_daemon.h b/src/rpc/bootstrap_daemon.h
index d54042b11..1e4477123 100644
--- a/src/rpc/bootstrap_daemon.h
+++ b/src/rpc/bootstrap_daemon.h
@@ -8,7 +8,7 @@
#include <boost/thread/mutex.hpp>
#include <boost/utility/string_ref.hpp>
-#include "net/http_client.h"
+#include "net/http.h"
#include "storages/http_abstract_invoke.h"
#include "bootstrap_node_selector.h"
@@ -21,11 +21,13 @@ namespace cryptonote
public:
bootstrap_daemon(
std::function<std::map<std::string, bool>()> get_public_nodes,
- bool rpc_payment_enabled);
+ bool rpc_payment_enabled,
+ const std::string &proxy);
bootstrap_daemon(
const std::string &address,
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;
boost::optional<std::pair<uint64_t, uint64_t>> get_height();
@@ -72,12 +74,14 @@ namespace cryptonote
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:
- epee::net_utils::http::http_simple_client m_http_client;
+ net::http::client m_http_client;
const bool m_rpc_payment_enabled;
const std::unique_ptr<bootstrap_node::selector> m_selector;
boost::mutex m_selector_mutex;
diff --git a/src/rpc/core_rpc_server.cpp b/src/rpc/core_rpc_server.cpp
index db228dd94..40c04b4f9 100644
--- a/src/rpc/core_rpc_server.cpp
+++ b/src/rpc/core_rpc_server.cpp
@@ -44,6 +44,7 @@ using namespace epee;
#include "cryptonote_basic/cryptonote_format_utils.h"
#include "cryptonote_basic/account.h"
#include "cryptonote_basic/cryptonote_basic_impl.h"
+#include "cryptonote_basic/merge_mining.h"
#include "cryptonote_core/tx_sanity_check.h"
#include "misc_language.h"
#include "net/parse.h"
@@ -154,6 +155,7 @@ namespace cryptonote
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_payment_address);
command_line::add_arg(desc, arg_rpc_payment_difficulty);
@@ -172,7 +174,10 @@ namespace cryptonote
, 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;
const auto loc = username_password.find(':');
@@ -180,7 +185,7 @@ namespace cryptonote
{
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*/)
@@ -217,7 +222,10 @@ namespace cryptonote
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);
@@ -233,11 +241,11 @@ namespace cryptonote
auto get_nodes = [this]() {
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
{
- 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;
@@ -278,6 +286,7 @@ namespace cryptonote
}
}
disable_rpc_ban = rpc_config->disable_rpc_ban;
+ const std::string data_dir{command_line::get_arg(vm, cryptonote::arg_data_dir)};
std::string address = command_line::get_arg(vm, arg_rpc_payment_address);
if (!address.empty() && allow_rpc_payment)
{
@@ -306,7 +315,7 @@ namespace cryptonote
}
m_rpc_payment_allow_free_loopback = command_line::get_arg(vm, arg_rpc_payment_allow_free_loopback);
m_rpc_payment.reset(new rpc_payment(info.address, diff, credits));
- m_rpc_payment->load(command_line::get_arg(vm, cryptonote::arg_data_dir));
+ m_rpc_payment->load(data_dir);
m_p2p.set_rpc_credits_per_hash(RPC_CREDITS_PER_HASH_SCALE * (credits / (float)diff));
}
@@ -318,8 +327,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.");
}
- if (!set_bootstrap_daemon(command_line::get_arg(vm, arg_bootstrap_daemon_address),
- command_line::get_arg(vm, arg_bootstrap_daemon_login)))
+ 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;
@@ -333,12 +344,32 @@ namespace cryptonote
if (m_rpc_payment)
m_net_server.add_idle_handler([this](){ return m_rpc_payment->on_idle(); }, 60 * 1000);
+ bool store_ssl_key = !restricted && rpc_config->ssl_options && rpc_config->ssl_options.auth.certificate_path.empty();
+ const auto ssl_base_path = (boost::filesystem::path{data_dir} / "rpc_ssl").string();
+ if (store_ssl_key && boost::filesystem::exists(ssl_base_path + ".crt"))
+ {
+ // load key from previous run, password prompted by OpenSSL
+ store_ssl_key = false;
+ rpc_config->ssl_options.auth =
+ epee::net_utils::ssl_authentication_t{ssl_base_path + ".key", ssl_base_path + ".crt"};
+ }
+
auto rng = [](size_t len, uint8_t *ptr){ return crypto::rand(len, ptr); };
- return epee::http_server_impl_base<core_rpc_server, connection_context>::init(
+ const bool inited = epee::http_server_impl_base<core_rpc_server, connection_context>::init(
rng, std::move(port), std::move(bind_ip_str),
std::move(bind_ipv6_str), std::move(rpc_config->use_ipv6), std::move(rpc_config->require_ipv4),
std::move(rpc_config->access_control_origins), std::move(http_login), std::move(rpc_config->ssl_options)
);
+
+ if (store_ssl_key && inited)
+ {
+ // new keys were generated, store for next run
+ const auto error = epee::net_utils::store_ssl_keys(m_net_server.get_ssl_context(), ssl_base_path);
+ if (error)
+ MFATAL("Failed to store HTTP SSL cert/key for " << (restricted ? "restricted " : "") << "RPC server: " << error.message());
+ return !bool(error);
+ }
+ return inited;
}
//------------------------------------------------------------------------------------------------------------------------------
bool core_rpc_server::check_payment(const std::string &client_message, uint64_t payment, const std::string &rpc, bool same_ts, std::string &message, uint64_t &credits, std::string &top_hash)
@@ -367,7 +398,6 @@ namespace cryptonote
message = "Client signature does not verify for " + rpc;
return false;
}
- crypto::public_key local_client;
if (!m_rpc_payment->pay(client, ts, payment, rpc, same_ts, credits))
{
message = CORE_RPC_STATUS_PAYMENT_REQUIRED;
@@ -1596,15 +1626,15 @@ namespace cryptonote
{
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;
}
else
{
res.status = "Failed to set bootstrap daemon";
- }
+ }
return true;
}
@@ -1806,7 +1836,6 @@ namespace cryptonote
return false;
}
}
- uint64_t seed_height;
crypto::hash seed_hash, next_seed_hash;
if (!get_block_template(info.address, req.prev_block.empty() ? NULL : &prev_block, blob_reserve, reserved_offset, wdiff, res.height, res.expected_reward, b, res.seed_height, seed_hash, next_seed_hash, error_resp))
return false;
@@ -1828,6 +1857,125 @@ namespace cryptonote
return true;
}
//------------------------------------------------------------------------------------------------------------------------------
+ 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;
+
+ if (req.aux_pow.empty())
+ {
+ error_resp.code = CORE_RPC_ERROR_CODE_WRONG_PARAM;
+ error_resp.message = "Empty aux pow hash vector";
+ return false;
+ }
+
+ crypto::hash merkle_root;
+ size_t merkle_tree_depth = 0;
+ std::vector<std::pair<crypto::hash, crypto::hash>> aux_pow;
+ std::vector<crypto::hash> aux_pow_raw;
+ aux_pow.reserve(req.aux_pow.size());
+ aux_pow_raw.reserve(req.aux_pow.size());
+ for (const auto &s: req.aux_pow)
+ {
+ aux_pow.push_back({});
+ if (!epee::string_tools::hex_to_pod(s.id, aux_pow.back().first))
+ {
+ error_resp.code = CORE_RPC_ERROR_CODE_WRONG_PARAM;
+ error_resp.message = "Invalid aux pow id";
+ return false;
+ }
+ if (!epee::string_tools::hex_to_pod(s.hash, aux_pow.back().second))
+ {
+ error_resp.code = CORE_RPC_ERROR_CODE_WRONG_PARAM;
+ error_resp.message = "Invalid aux pow hash";
+ return false;
+ }
+ aux_pow_raw.push_back(aux_pow.back().second);
+ }
+
+ size_t path_domain = 1;
+ while ((1u << path_domain) < aux_pow.size())
+ ++path_domain;
+ uint32_t nonce;
+ const uint32_t max_nonce = 65535;
+ bool collision = true;
+ for (nonce = 0; nonce <= max_nonce; ++nonce)
+ {
+ std::vector<bool> slots(aux_pow.size(), false);
+ collision = false;
+ for (size_t idx = 0; idx < aux_pow.size(); ++idx)
+ {
+ const uint32_t slot = cryptonote::get_aux_slot(aux_pow[idx].first, nonce, aux_pow.size());
+ if (slot >= aux_pow.size())
+ {
+ error_resp.code = CORE_RPC_ERROR_CODE_INTERNAL_ERROR;
+ error_resp.message = "Computed slot is out of range";
+ return false;
+ }
+ if (slots[slot])
+ {
+ collision = true;
+ break;
+ }
+ slots[slot] = true;
+ }
+ if (!collision)
+ break;
+ }
+ if (collision)
+ {
+ error_resp.code = CORE_RPC_ERROR_CODE_INTERNAL_ERROR;
+ error_resp.message = "Failed to find a suitable nonce";
+ return false;
+ }
+
+ crypto::tree_hash((const char(*)[crypto::HASH_SIZE])aux_pow_raw.data(), aux_pow_raw.size(), merkle_root.data);
+ res.merkle_root = epee::string_tools::pod_to_hex(merkle_root);
+ res.merkle_tree_depth = cryptonote::encode_mm_depth(aux_pow.size(), nonce);
+
+ blobdata blocktemplate_blob;
+ if (!epee::string_tools::parse_hexstr_to_binbuff(req.blocktemplate_blob, blocktemplate_blob))
+ {
+ error_resp.code = CORE_RPC_ERROR_CODE_WRONG_PARAM;
+ error_resp.message = "Invalid blocktemplate_blob";
+ return false;
+ }
+
+ block b;
+ if (!parse_and_validate_block_from_blob(blocktemplate_blob, b))
+ {
+ error_resp.code = CORE_RPC_ERROR_CODE_WRONG_BLOCKBLOB;
+ error_resp.message = "Wrong blocktemplate_blob";
+ return false;
+ }
+
+ if (!remove_field_from_tx_extra(b.miner_tx.extra, typeid(cryptonote::tx_extra_merge_mining_tag)))
+ {
+ error_resp.code = CORE_RPC_ERROR_CODE_INTERNAL_ERROR;
+ error_resp.message = "Error removing existing merkle root";
+ return false;
+ }
+ if (!add_mm_merkle_root_to_tx_extra(b.miner_tx.extra, merkle_root, merkle_tree_depth))
+ {
+ error_resp.code = CORE_RPC_ERROR_CODE_INTERNAL_ERROR;
+ error_resp.message = "Error adding merkle root";
+ return false;
+ }
+ b.invalidate_hashes();
+ b.miner_tx.invalidate_hashes();
+
+ const blobdata block_blob = t_serializable_object_to_blob(b);
+ const blobdata hashing_blob = get_block_hashing_blob(b);
+
+ res.blocktemplate_blob = string_tools::buff_to_hex_nodelimer(block_blob);
+ res.blockhashing_blob = string_tools::buff_to_hex_nodelimer(hashing_blob);
+ res.aux_pow = req.aux_pow;
+ res.status = CORE_RPC_STATUS_OK;
+ return true;
+ }
+ //------------------------------------------------------------------------------------------------------------------------------
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);
@@ -3349,6 +3497,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 = {
"rpc-payment-address"
, "Restrict RPC to clients sending micropayment to this address"
diff --git a/src/rpc/core_rpc_server.h b/src/rpc/core_rpc_server.h
index dcf6b4e4b..b21e43ab0 100644
--- a/src/rpc/core_rpc_server.h
+++ b/src/rpc/core_rpc_server.h
@@ -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<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::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_credits;
@@ -146,6 +147,7 @@ namespace cryptonote
MAP_JON_RPC_WE("on_getblockhash", on_getblockhash, COMMAND_RPC_GETBLOCKHASH)
MAP_JON_RPC_WE("get_block_template", on_getblocktemplate, COMMAND_RPC_GETBLOCKTEMPLATE)
MAP_JON_RPC_WE("getblocktemplate", on_getblocktemplate, COMMAND_RPC_GETBLOCKTEMPLATE)
+ MAP_JON_RPC_WE("add_aux_pow", on_add_aux_pow, COMMAND_RPC_ADD_AUX_POW)
MAP_JON_RPC_WE("submit_block", on_submitblock, COMMAND_RPC_SUBMITBLOCK)
MAP_JON_RPC_WE("submitblock", on_submitblock, COMMAND_RPC_SUBMITBLOCK)
MAP_JON_RPC_WE_IF("generateblocks", on_generateblocks, COMMAND_RPC_GENERATEBLOCKS, !m_restricted)
@@ -226,6 +228,7 @@ namespace cryptonote
bool on_getblockcount(const COMMAND_RPC_GETBLOCKCOUNT::request& req, COMMAND_RPC_GETBLOCKCOUNT::response& res, const connection_context *ctx = NULL);
bool on_getblockhash(const COMMAND_RPC_GETBLOCKHASH::request& req, COMMAND_RPC_GETBLOCKHASH::response& res, epee::json_rpc::error& error_resp, const connection_context *ctx = NULL);
bool on_getblocktemplate(const COMMAND_RPC_GETBLOCKTEMPLATE::request& req, COMMAND_RPC_GETBLOCKTEMPLATE::response& res, epee::json_rpc::error& error_resp, const connection_context *ctx = NULL);
+ bool 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 = NULL);
bool on_submitblock(const COMMAND_RPC_SUBMITBLOCK::request& req, COMMAND_RPC_SUBMITBLOCK::response& res, epee::json_rpc::error& error_resp, const connection_context *ctx = NULL);
bool on_generateblocks(const COMMAND_RPC_GENERATEBLOCKS::request& req, COMMAND_RPC_GENERATEBLOCKS::response& res, epee::json_rpc::error& error_resp, const connection_context *ctx = NULL);
bool 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 = NULL);
@@ -268,8 +271,14 @@ private:
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);
- bool set_bootstrap_daemon(const std::string &address, const boost::optional<epee::net_utils::http::login> &credentials);
+ 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);
diff --git a/src/rpc/core_rpc_server_commands_defs.h b/src/rpc/core_rpc_server_commands_defs.h
index bbcb27f1c..5ebe4f654 100644
--- a/src/rpc/core_rpc_server_commands_defs.h
+++ b/src/rpc/core_rpc_server_commands_defs.h
@@ -88,7 +88,7 @@ namespace cryptonote
// advance which version they will stop working with
// Don't go over 32767 for any of these
#define CORE_RPC_VERSION_MAJOR 3
-#define CORE_RPC_VERSION_MINOR 5
+#define CORE_RPC_VERSION_MINOR 6
#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)
@@ -938,6 +938,52 @@ namespace cryptonote
typedef epee::misc_utils::struct_init<response_t> response;
};
+ struct COMMAND_RPC_ADD_AUX_POW
+ {
+ struct aux_pow_t
+ {
+ std::string id;
+ std::string hash;
+
+ BEGIN_KV_SERIALIZE_MAP()
+ KV_SERIALIZE(id)
+ KV_SERIALIZE(hash)
+ END_KV_SERIALIZE_MAP()
+ };
+
+ struct request_t: public rpc_request_base
+ {
+ blobdata blocktemplate_blob;
+ std::vector<aux_pow_t> aux_pow;
+
+ BEGIN_KV_SERIALIZE_MAP()
+ KV_SERIALIZE_PARENT(rpc_request_base)
+ KV_SERIALIZE(blocktemplate_blob)
+ KV_SERIALIZE(aux_pow)
+ END_KV_SERIALIZE_MAP()
+ };
+ typedef epee::misc_utils::struct_init<request_t> request;
+
+ struct response_t: public rpc_response_base
+ {
+ blobdata blocktemplate_blob;
+ blobdata blockhashing_blob;
+ std::string merkle_root;
+ uint32_t merkle_tree_depth;
+ std::vector<aux_pow_t> aux_pow;
+
+ BEGIN_KV_SERIALIZE_MAP()
+ KV_SERIALIZE_PARENT(rpc_response_base)
+ KV_SERIALIZE(blocktemplate_blob)
+ KV_SERIALIZE(blockhashing_blob)
+ KV_SERIALIZE(merkle_root)
+ KV_SERIALIZE(merkle_tree_depth)
+ KV_SERIALIZE(aux_pow)
+ END_KV_SERIALIZE_MAP()
+ };
+ typedef epee::misc_utils::struct_init<response_t> response;
+ };
+
struct COMMAND_RPC_SUBMITBLOCK
{
typedef std::vector<std::string> request;
@@ -1613,11 +1659,13 @@ namespace cryptonote
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;