aboutsummaryrefslogtreecommitdiff
path: root/src/rpc
diff options
context:
space:
mode:
Diffstat (limited to 'src/rpc')
-rw-r--r--src/rpc/core_rpc_server.cpp202
-rw-r--r--src/rpc/core_rpc_server.h2
-rw-r--r--src/rpc/core_rpc_server_commands_defs.h18
3 files changed, 117 insertions, 105 deletions
diff --git a/src/rpc/core_rpc_server.cpp b/src/rpc/core_rpc_server.cpp
index 8c201097e..bd1455c43 100644
--- a/src/rpc/core_rpc_server.cpp
+++ b/src/rpc/core_rpc_server.cpp
@@ -91,7 +91,7 @@ namespace cryptonote
command_line::add_arg(desc, arg_rpc_ssl);
command_line::add_arg(desc, arg_rpc_ssl_private_key);
command_line::add_arg(desc, arg_rpc_ssl_certificate);
- command_line::add_arg(desc, arg_rpc_ssl_allowed_certificates);
+ command_line::add_arg(desc, arg_rpc_ssl_ca_certificates);
command_line::add_arg(desc, arg_rpc_ssl_allowed_fingerprints);
command_line::add_arg(desc, arg_rpc_ssl_allow_any_cert);
command_line::add_arg(desc, arg_bootstrap_daemon_address);
@@ -149,36 +149,38 @@ namespace cryptonote
if (rpc_config->login)
http_login.emplace(std::move(rpc_config->login->username), std::move(rpc_config->login->password).password());
- epee::net_utils::ssl_support_t ssl_support;
- const std::string ssl = command_line::get_arg(vm, arg_rpc_ssl);
- if (!epee::net_utils::ssl_support_from_string(ssl_support, ssl))
+ epee::net_utils::ssl_options_t ssl_options = epee::net_utils::ssl_support_t::e_ssl_support_autodetect;
+ if (command_line::get_arg(vm, arg_rpc_ssl_allow_any_cert))
+ ssl_options.verification = epee::net_utils::ssl_verification_t::none;
+ else
{
- MFATAL("Invalid RPC SSL support: " << ssl);
- return false;
+ std::string ssl_ca_path = command_line::get_arg(vm, arg_rpc_ssl_ca_certificates);
+ const std::vector<std::string> ssl_allowed_fingerprint_strings = command_line::get_arg(vm, arg_rpc_ssl_allowed_fingerprints);
+ std::vector<std::vector<uint8_t>> ssl_allowed_fingerprints{ ssl_allowed_fingerprint_strings.size() };
+ std::transform(ssl_allowed_fingerprint_strings.begin(), ssl_allowed_fingerprint_strings.end(), ssl_allowed_fingerprints.begin(), epee::from_hex::vector);
+
+ if (!ssl_ca_path.empty() || !ssl_allowed_fingerprints.empty())
+ ssl_options = epee::net_utils::ssl_options_t{std::move(ssl_allowed_fingerprints), std::move(ssl_ca_path)};
}
- const std::string ssl_private_key = command_line::get_arg(vm, arg_rpc_ssl_private_key);
- const std::string ssl_certificate = command_line::get_arg(vm, arg_rpc_ssl_certificate);
- const std::vector<std::string> ssl_allowed_certificate_paths = command_line::get_arg(vm, arg_rpc_ssl_allowed_certificates);
- std::list<std::string> ssl_allowed_certificates;
- for (const std::string &path: ssl_allowed_certificate_paths)
+
+ ssl_options.auth = epee::net_utils::ssl_authentication_t{
+ command_line::get_arg(vm, arg_rpc_ssl_private_key), command_line::get_arg(vm, arg_rpc_ssl_certificate)
+ };
+
+ // user specified CA file or fingeprints implies enabled SSL by default
+ if (ssl_options.verification != epee::net_utils::ssl_verification_t::user_certificates || !command_line::is_arg_defaulted(vm, arg_rpc_ssl))
{
- ssl_allowed_certificates.push_back({});
- if (!epee::file_io_utils::load_file_to_string(path, ssl_allowed_certificates.back()))
+ const std::string ssl = command_line::get_arg(vm, arg_rpc_ssl);
+ if (!epee::net_utils::ssl_support_from_string(ssl_options.support, ssl))
{
- MERROR("Failed to load certificate: " << path);
- ssl_allowed_certificates.back() = std::string();
+ MFATAL("Invalid RPC SSL support: " << ssl);
+ return false;
}
}
- const std::vector<std::string> ssl_allowed_fingerprint_strings = command_line::get_arg(vm, arg_rpc_ssl_allowed_fingerprints);
- std::vector<std::vector<uint8_t>> ssl_allowed_fingerprints{ ssl_allowed_fingerprint_strings.size() };
- std::transform(ssl_allowed_fingerprint_strings.begin(), ssl_allowed_fingerprint_strings.end(), ssl_allowed_fingerprints.begin(), epee::from_hex::vector);
- const bool ssl_allow_any_cert = command_line::get_arg(vm, arg_rpc_ssl_allow_any_cert);
-
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(
- rng, std::move(port), std::move(rpc_config->bind_ip), std::move(rpc_config->access_control_origins), std::move(http_login),
- ssl_support, std::make_pair(ssl_private_key, ssl_certificate), std::move(ssl_allowed_certificates), std::move(ssl_allowed_fingerprints), ssl_allow_any_cert
+ rng, std::move(port), std::move(rpc_config->bind_ip), std::move(rpc_config->access_control_origins), std::move(http_login), std::move(ssl_options)
);
}
//------------------------------------------------------------------------------------------------------------------------------
@@ -200,7 +202,9 @@ namespace cryptonote
if (use_bootstrap_daemon_if_necessary<COMMAND_RPC_GET_HEIGHT>(invoke_http_mode::JON, "/getheight", req, res, r))
return r;
- res.height = m_core.get_current_blockchain_height();
+ crypto::hash hash;
+ m_core.get_blockchain_top(res.height, hash);
+ res.hash = string_tools::pod_to_hex(hash);
res.status = CORE_RPC_STATUS_OK;
return true;
}
@@ -247,7 +251,6 @@ namespace cryptonote
res.cumulative_difficulty, res.wide_cumulative_difficulty, res.cumulative_difficulty_top64);
res.block_size_limit = res.block_weight_limit = m_core.get_blockchain_storage().get_current_cumulative_block_weight_limit();
res.block_size_median = res.block_weight_median = m_core.get_blockchain_storage().get_current_cumulative_block_weight_median();
- res.status = CORE_RPC_STATUS_OK;
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();
@@ -265,6 +268,8 @@ namespace cryptonote
res.database_size = round_up(res.database_size, 5ull* 1024 * 1024 * 1024);
res.update_available = restricted ? false : m_core.is_update_available();
res.version = restricted ? "" : MONERO_VERSION;
+
+ res.status = CORE_RPC_STATUS_OK;
return true;
}
//------------------------------------------------------------------------------------------------------------------------------
@@ -491,6 +496,7 @@ namespace cryptonote
cryptonote::COMMAND_RPC_GET_OUTPUTS_BIN::request req_bin;
req_bin.outputs = req.outputs;
+ req_bin.get_txid = req.get_txid;
cryptonote::COMMAND_RPC_GET_OUTPUTS_BIN::response res_bin;
if(!m_core.get_outs(req_bin, res_bin))
{
@@ -646,30 +652,61 @@ namespace cryptonote
e.prunable_hash = epee::string_tools::pod_to_hex(std::get<2>(tx));
if (req.split || req.prune || std::get<3>(tx).empty())
{
+ // use splitted form with pruned and prunable (filled only when prune=false and the daemon has it), leaving as_hex as empty
e.pruned_as_hex = string_tools::buff_to_hex_nodelimer(std::get<1>(tx));
if (!req.prune)
e.prunable_as_hex = string_tools::buff_to_hex_nodelimer(std::get<3>(tx));
- }
- else
- {
- cryptonote::blobdata tx_data;
- if (req.prune)
- tx_data = std::get<1>(tx);
- else
- tx_data = std::get<1>(tx) + std::get<3>(tx);
- e.as_hex = string_tools::buff_to_hex_nodelimer(tx_data);
- if (req.decode_as_json && !tx_data.empty())
+ if (req.decode_as_json)
{
+ cryptonote::blobdata tx_data;
cryptonote::transaction t;
- if (cryptonote::parse_and_validate_tx_from_blob(tx_data, t))
+ if (req.prune || std::get<3>(tx).empty())
{
- if (req.prune)
+ // decode pruned tx to JSON
+ tx_data = std::get<1>(tx);
+ if (cryptonote::parse_and_validate_tx_base_from_blob(tx_data, t))
{
pruned_transaction pruned_tx{t};
e.as_json = obj_to_json_str(pruned_tx);
}
else
+ {
+ res.status = "Failed to parse and validate pruned tx from blob";
+ return true;
+ }
+ }
+ else
+ {
+ // decode full tx to JSON
+ tx_data = std::get<1>(tx) + std::get<3>(tx);
+ if (cryptonote::parse_and_validate_tx_from_blob(tx_data, t))
+ {
e.as_json = obj_to_json_str(t);
+ }
+ else
+ {
+ res.status = "Failed to parse and validate tx from blob";
+ return true;
+ }
+ }
+ }
+ }
+ else
+ {
+ // use non-splitted form, leaving pruned_as_hex and prunable_as_hex as empty
+ cryptonote::blobdata tx_data = std::get<1>(tx) + std::get<3>(tx);
+ e.as_hex = string_tools::buff_to_hex_nodelimer(tx_data);
+ if (req.decode_as_json)
+ {
+ cryptonote::transaction t;
+ if (cryptonote::parse_and_validate_tx_from_blob(tx_data, t))
+ {
+ e.as_json = obj_to_json_str(t);
+ }
+ else
+ {
+ res.status = "Failed to parse and validate tx from blob";
+ return true;
}
}
}
@@ -939,6 +976,7 @@ namespace cryptonote
const miner& lMiner = m_core.get_miner();
res.active = lMiner.is_mining();
res.is_background_mining_enabled = lMiner.get_is_background_mining_enabled();
+ store_difficulty(m_core.get_blockchain_storage().get_difficulty_for_next_block(), res.difficulty, res.wide_difficulty, res.difficulty_top64);
res.block_target = m_core.get_blockchain_storage().get_current_hard_fork_version() < 2 ? DIFFICULTY_TARGET_V1 : DIFFICULTY_TARGET_V2;
if ( lMiner.is_mining() ) {
@@ -1222,7 +1260,17 @@ namespace cryptonote
cryptonote::blobdata blob_reserve;
blob_reserve.resize(req.reserve_size, 0);
cryptonote::difficulty_type wdiff;
- if(!m_core.get_block_template(b, info.address, wdiff, res.height, res.expected_reward, blob_reserve))
+ crypto::hash prev_block;
+ if (!req.prev_block.empty())
+ {
+ if (!epee::string_tools::hex_to_pod(req.prev_block, prev_block))
+ {
+ error_resp.code = CORE_RPC_ERROR_CODE_INTERNAL_ERROR;
+ error_resp.message = "Invalid prev_block";
+ return false;
+ }
+ }
+ if(!m_core.get_block_template(b, req.prev_block.empty() ? NULL : &prev_block, info.address, wdiff, res.height, res.expected_reward, blob_reserve))
{
error_resp.code = CORE_RPC_ERROR_CODE_INTERNAL_ERROR;
error_resp.message = "Internal error: failed to create block template";
@@ -1308,7 +1356,8 @@ namespace cryptonote
return false;
}
- if(!m_core.handle_block_found(b))
+ block_verification_context bvc;
+ if(!m_core.handle_block_found(b, bvc))
{
error_resp.code = CORE_RPC_ERROR_CODE_BLOCK_NOT_ACCEPTED;
error_resp.message = "Block not accepted";
@@ -1340,15 +1389,17 @@ namespace cryptonote
template_req.reserve_size = 1;
template_req.wallet_address = req.wallet_address;
+ template_req.prev_block = req.prev_block;
submit_req.push_back(boost::value_initialized<std::string>());
res.height = m_core.get_blockchain_storage().get_current_blockchain_height();
- bool r;
+ bool r = CORE_RPC_STATUS_OK;
for(size_t i = 0; i < req.amount_of_blocks; i++)
{
r = on_getblocktemplate(template_req, template_res, error_resp, ctx);
res.status = template_res.status;
+ template_req.prev_block.clear();
if (!r) return false;
@@ -1366,6 +1417,7 @@ namespace cryptonote
error_resp.message = "Wrong block blob";
return false;
}
+ b.nonce = req.starting_nonce;
miner::find_nonce_for_given_block(b, template_res.difficulty, template_res.height);
submit_req.front() = string_tools::buff_to_hex_nodelimer(block_to_blob(b));
@@ -1374,6 +1426,8 @@ namespace cryptonote
if (!r) return false;
+ res.blocks.push_back(epee::string_tools::pod_to_hex(get_block_hash(b)));
+ template_req.prev_block = res.blocks.back();
res.height = template_res.height;
}
@@ -1718,67 +1772,7 @@ namespace cryptonote
//------------------------------------------------------------------------------------------------------------------------------
bool core_rpc_server::on_get_info_json(const COMMAND_RPC_GET_INFO::request& req, COMMAND_RPC_GET_INFO::response& res, epee::json_rpc::error& error_resp, const connection_context *ctx)
{
- PERF_TIMER(on_get_info_json);
- bool r;
- if (use_bootstrap_daemon_if_necessary<COMMAND_RPC_GET_INFO>(invoke_http_mode::JON_RPC, "get_info", req, res, r))
- {
- 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;
-
- crypto::hash top_hash;
- m_core.get_blockchain_top(res.height, top_hash);
- ++res.height; // turn top block height into blockchain height
- res.top_block_hash = string_tools::pod_to_hex(top_hash);
- res.target_height = m_core.get_target_blockchain_height();
- store_difficulty(m_core.get_blockchain_storage().get_difficulty_for_next_block(),
- res.difficulty, res.wide_difficulty, res.difficulty_top64);
- res.target = m_core.get_blockchain_storage().get_current_hard_fork_version() < 2 ? DIFFICULTY_TARGET_V1 : DIFFICULTY_TARGET_V2;
- res.tx_count = m_core.get_blockchain_storage().get_total_transactions() - res.height; //without coinbase
- res.tx_pool_size = m_core.get_pool_transactions_count();
- res.alt_blocks_count = restricted ? 0 : m_core.get_blockchain_storage().get_alternative_blocks_count();
- uint64_t total_conn = restricted ? 0 : m_p2p.get_public_connections_count();
- res.outgoing_connections_count = restricted ? 0 : m_p2p.get_public_outgoing_connections_count();
- res.incoming_connections_count = restricted ? 0 : (total_conn - res.outgoing_connections_count);
- res.rpc_connections_count = restricted ? 0 : get_connections_count();
- res.white_peerlist_size = restricted ? 0 : m_p2p.get_public_white_peers_count();
- res.grey_peerlist_size = restricted ? 0 : m_p2p.get_public_gray_peers_count();
-
- cryptonote::network_type net_type = nettype();
- res.mainnet = net_type == MAINNET;
- res.testnet = net_type == TESTNET;
- res.stagenet = net_type == STAGENET;
- res.nettype = net_type == MAINNET ? "mainnet" : net_type == TESTNET ? "testnet" : net_type == STAGENET ? "stagenet" : "fakechain";
-
- store_difficulty(m_core.get_blockchain_storage().get_db().get_block_cumulative_difficulty(res.height - 1),
- res.cumulative_difficulty, res.wide_cumulative_difficulty, res.cumulative_difficulty_top64);
- res.block_size_limit = res.block_weight_limit = m_core.get_blockchain_storage().get_current_cumulative_block_weight_limit();
- res.block_size_median = res.block_weight_median = m_core.get_blockchain_storage().get_current_cumulative_block_weight_median();
- res.status = CORE_RPC_STATUS_OK;
- 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.bootstrap_daemon_address = restricted ? "" : m_bootstrap_daemon_address;
- res.height_without_bootstrap = restricted ? 0 : res.height;
- if (restricted)
- res.was_bootstrap_ever_used = false;
- else
- {
- boost::shared_lock<boost::shared_mutex> lock(m_bootstrap_daemon_mutex);
- 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);
- res.update_available = restricted ? false : m_core.is_update_available();
- res.version = restricted ? "" : MONERO_VERSION;
- return true;
+ return on_get_info(req, res, ctx);
}
//------------------------------------------------------------------------------------------------------------------------------
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)
@@ -2436,9 +2430,9 @@ namespace cryptonote
, ""
};
- const command_line::arg_descriptor<std::vector<std::string>> core_rpc_server::arg_rpc_ssl_allowed_certificates = {
- "rpc-ssl-allowed-certificates"
- , "List of paths to PEM format certificates of allowed peers (all allowed if empty)"
+ const command_line::arg_descriptor<std::string> core_rpc_server::arg_rpc_ssl_ca_certificates = {
+ "rpc-ssl-ca-certificates"
+ , "Path to file containing concatenated PEM format certificate(s) to replace system CA(s)."
};
const command_line::arg_descriptor<std::vector<std::string>> core_rpc_server::arg_rpc_ssl_allowed_fingerprints = {
@@ -2448,7 +2442,7 @@ namespace cryptonote
const command_line::arg_descriptor<bool> core_rpc_server::arg_rpc_ssl_allow_any_cert = {
"rpc-ssl-allow-any-cert"
- , "Allow any peer certificate, rather than just those on the allowed list"
+ , "Allow any peer certificate"
, false
};
diff --git a/src/rpc/core_rpc_server.h b/src/rpc/core_rpc_server.h
index 8f5d83f1b..a42ca2494 100644
--- a/src/rpc/core_rpc_server.h
+++ b/src/rpc/core_rpc_server.h
@@ -60,7 +60,7 @@ namespace cryptonote
static const command_line::arg_descriptor<std::string> arg_rpc_ssl;
static const command_line::arg_descriptor<std::string> arg_rpc_ssl_private_key;
static const command_line::arg_descriptor<std::string> arg_rpc_ssl_certificate;
- static const command_line::arg_descriptor<std::vector<std::string>> arg_rpc_ssl_allowed_certificates;
+ 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;
diff --git a/src/rpc/core_rpc_server_commands_defs.h b/src/rpc/core_rpc_server_commands_defs.h
index 1f14267f6..d2aba8d67 100644
--- a/src/rpc/core_rpc_server_commands_defs.h
+++ b/src/rpc/core_rpc_server_commands_defs.h
@@ -102,11 +102,13 @@ namespace cryptonote
uint64_t height;
std::string status;
bool untrusted;
+ std::string hash;
BEGIN_KV_SERIALIZE_MAP()
KV_SERIALIZE(height)
KV_SERIALIZE(status)
KV_SERIALIZE(untrusted)
+ KV_SERIALIZE(hash)
END_KV_SERIALIZE_MAP()
};
typedef epee::misc_utils::struct_init<response_t> response;
@@ -528,9 +530,11 @@ namespace cryptonote
struct request_t
{
std::vector<get_outputs_out> outputs;
+ bool get_txid;
BEGIN_KV_SERIALIZE_MAP()
KV_SERIALIZE(outputs)
+ KV_SERIALIZE(get_txid)
END_KV_SERIALIZE_MAP()
};
typedef epee::misc_utils::struct_init<request_t> request;
@@ -821,6 +825,9 @@ namespace cryptonote
uint8_t bg_target;
uint32_t block_target;
uint64_t block_reward;
+ uint64_t difficulty;
+ std::string wide_difficulty;
+ uint64_t difficulty_top64;
BEGIN_KV_SERIALIZE_MAP()
KV_SERIALIZE(status)
@@ -836,6 +843,9 @@ namespace cryptonote
KV_SERIALIZE(bg_target)
KV_SERIALIZE(block_target)
KV_SERIALIZE(block_reward)
+ KV_SERIALIZE(difficulty)
+ KV_SERIALIZE(wide_difficulty)
+ KV_SERIALIZE(difficulty_top64)
END_KV_SERIALIZE_MAP()
};
typedef epee::misc_utils::struct_init<response_t> response;
@@ -896,10 +906,12 @@ namespace cryptonote
{
uint64_t reserve_size; //max 255 bytes
std::string wallet_address;
+ std::string prev_block;
BEGIN_KV_SERIALIZE_MAP()
KV_SERIALIZE(reserve_size)
KV_SERIALIZE(wallet_address)
+ KV_SERIALIZE(prev_block)
END_KV_SERIALIZE_MAP()
};
typedef epee::misc_utils::struct_init<request_t> request;
@@ -956,10 +968,14 @@ namespace cryptonote
{
uint64_t amount_of_blocks;
std::string wallet_address;
+ std::string prev_block;
+ uint32_t starting_nonce;
BEGIN_KV_SERIALIZE_MAP()
KV_SERIALIZE(amount_of_blocks)
KV_SERIALIZE(wallet_address)
+ KV_SERIALIZE(prev_block)
+ KV_SERIALIZE_OPT(starting_nonce, (uint32_t)0)
END_KV_SERIALIZE_MAP()
};
typedef epee::misc_utils::struct_init<request_t> request;
@@ -967,10 +983,12 @@ namespace cryptonote
struct response_t
{
uint64_t height;
+ std::vector<std::string> blocks;
std::string status;
BEGIN_KV_SERIALIZE_MAP()
KV_SERIALIZE(height)
+ KV_SERIALIZE(blocks)
KV_SERIALIZE(status)
END_KV_SERIALIZE_MAP()
};