aboutsummaryrefslogtreecommitdiff
path: root/src/rpc
diff options
context:
space:
mode:
Diffstat (limited to 'src/rpc')
-rw-r--r--src/rpc/core_rpc_server.cpp111
-rw-r--r--src/rpc/core_rpc_server.h2
-rw-r--r--src/rpc/core_rpc_server_commands_defs.h69
-rw-r--r--src/rpc/daemon_messages.cpp201
-rw-r--r--src/rpc/rpc_payment.h8
-rw-r--r--src/rpc/zmq_server.cpp23
6 files changed, 374 insertions, 40 deletions
diff --git a/src/rpc/core_rpc_server.cpp b/src/rpc/core_rpc_server.cpp
index 03e9ec494..9a0b02f70 100644
--- a/src/rpc/core_rpc_server.cpp
+++ b/src/rpc/core_rpc_server.cpp
@@ -2082,11 +2082,12 @@ namespace cryptonote
}
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;
+ std::vector<crypto::hash> aux_pow_id_raw;
aux_pow.reserve(req.aux_pow.size());
- aux_pow_raw.reserve(req.aux_pow.size());
+ aux_pow_raw.resize(req.aux_pow.size());
+ aux_pow_id_raw.resize(req.aux_pow.size());
for (const auto &s: req.aux_pow)
{
aux_pow.push_back({});
@@ -2102,7 +2103,6 @@ namespace cryptonote
error_resp.message = "Invalid aux pow hash";
return false;
}
- aux_pow_raw.push_back(aux_pow.back().second);
}
size_t path_domain = 1;
@@ -2111,11 +2111,14 @@ namespace cryptonote
uint32_t nonce;
const uint32_t max_nonce = 65535;
bool collision = true;
+ std::vector<uint32_t> slots(aux_pow.size());
for (nonce = 0; nonce <= max_nonce; ++nonce)
{
- std::vector<bool> slots(aux_pow.size(), false);
+ std::vector<bool> slot_seen(aux_pow.size(), false);
collision = false;
for (size_t idx = 0; idx < aux_pow.size(); ++idx)
+ slots[idx] = 0xffffffff;
+ 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())
@@ -2124,12 +2127,13 @@ namespace cryptonote
error_resp.message = "Computed slot is out of range";
return false;
}
- if (slots[slot])
+ if (slot_seen[slot])
{
collision = true;
break;
}
- slots[slot] = true;
+ slot_seen[slot] = true;
+ slots[idx] = slot;
}
if (!collision)
break;
@@ -2141,6 +2145,19 @@ namespace cryptonote
return false;
}
+ // set the order determined above
+ for (size_t i = 0; i < aux_pow.size(); ++i)
+ {
+ if (slots[i] >= aux_pow.size())
+ {
+ error_resp.code = CORE_RPC_ERROR_CODE_INTERNAL_ERROR;
+ error_resp.message = "Slot value out of range";
+ return false;
+ }
+ aux_pow_raw[slots[i]] = aux_pow[i].second;
+ aux_pow_id_raw[slots[i]] = aux_pow[i].first;
+ }
+
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);
@@ -2167,7 +2184,7 @@ namespace cryptonote
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))
+ if (!add_mm_merkle_root_to_tx_extra(b.miner_tx.extra, merkle_root, res.merkle_tree_depth))
{
error_resp.code = CORE_RPC_ERROR_CODE_INTERNAL_ERROR;
error_resp.message = "Error adding merkle root";
@@ -2181,7 +2198,8 @@ namespace cryptonote
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;
+ for (size_t i = 0; i < aux_pow_raw.size(); ++i)
+ res.aux_pow.push_back({epee::string_tools::pod_to_hex(aux_pow_id_raw[i]), epee::string_tools::pod_to_hex(aux_pow_raw[i])});
res.status = CORE_RPC_STATUS_OK;
return true;
}
@@ -2358,6 +2376,7 @@ namespace cryptonote
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);
@@ -3535,6 +3554,82 @@ namespace cryptonote
return true;
}
//------------------------------------------------------------------------------------------------------------------------------
+ bool core_rpc_server::on_get_txids_loose(const COMMAND_RPC_GET_TXIDS_LOOSE::request& req, COMMAND_RPC_GET_TXIDS_LOOSE::response& res, epee::json_rpc::error& error_resp, const connection_context *ctx)
+ {
+ RPC_TRACKER(get_txids_loose);
+
+ // Maybe don't use bootstrap since this endpoint is meant to retreive 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);
+
+ // Sanity check parameters
+ if (req.num_matching_bits > 256)
+ {
+ error_resp.code = CORE_RPC_ERROR_CODE_WRONG_PARAM;
+ error_resp.message = "There are only 256 bits in a hash, you gave too many";
+ return false;
+ }
+
+ // Attempt to guess when bit count is too low before fetching, within a certain margin of error
+ const uint64_t num_txs_ever = m_core.get_blockchain_storage().get_db().get_tx_count();
+ const uint64_t num_expected_fetch = (num_txs_ever >> std::min((int) req.num_matching_bits, 63));
+ const uint64_t max_num_txids_with_margin = 2 * max_num_txids;
+ if (num_expected_fetch > max_num_txids_with_margin)
+ {
+ error_resp.code = CORE_RPC_ERROR_CODE_WRONG_PARAM;
+ error_resp.message = "Trying to search with too few matching bits, detected before fetching";
+ return false;
+ }
+
+ // Convert txid template to a crypto::hash
+ crypto::hash search_hash;
+ if (!epee::string_tools::hex_to_pod(req.txid_template, search_hash))
+ {
+ error_resp.code = CORE_RPC_ERROR_CODE_WRONG_PARAM;
+ error_resp.message = "Could not decode hex txid";
+ return false;
+ }
+ // Check that txid template is zeroed correctly for number of given matchign bits
+ else if (search_hash != make_hash32_loose_template(req.num_matching_bits, search_hash))
+ {
+ error_resp.code = CORE_RPC_ERROR_CODE_WRONG_PARAM;
+ error_resp.message = "Txid template is not zeroed correctly for number of bits. You could be leaking true txid!";
+ return false;
+ }
+
+ try
+ {
+ // Do the DB fetch
+ const auto txids = m_core.get_blockchain_storage().get_db().get_txids_loose(search_hash, req.num_matching_bits, max_num_txids);
+ // Fill out response form
+ for (const auto& txid : txids)
+ res.txids.emplace_back(epee::string_tools::pod_to_hex(txid));
+ }
+ catch (const TX_EXISTS&)
+ {
+ error_resp.code = CORE_RPC_ERROR_CODE_WRONG_PARAM;
+ error_resp.message = "Trying to search with too few matching bits";
+ return false;
+ }
+ catch (const std::exception& e)
+ {
+ error_resp.code = CORE_RPC_ERROR_CODE_INTERNAL_ERROR;
+ error_resp.message = std::string("Error during get_txids_loose: ") + e.what();
+ return false;
+ }
+
+ res.status = CORE_RPC_STATUS_OK;
+ return true;
+#else // BYTE_ORDER == BIG_ENDIAN
+ // BlockchainLMDB::compare_hash32 has different key ordering (thus different txid templates) on BE systems
+ error_resp.code = CORE_RPC_ERROR_CODE_INTERNAL_ERROR;
+ error_resp.message = "Due to implementation details, this feature is not available on big-endian daemons";
+ return false;
+#endif
+ }
+ //------------------------------------------------------------------------------------------------------------------------------
bool core_rpc_server::on_rpc_access_submit_nonce(const COMMAND_RPC_ACCESS_SUBMIT_NONCE::request& req, COMMAND_RPC_ACCESS_SUBMIT_NONCE::response& res, epee::json_rpc::error& error_resp, const connection_context *ctx)
{
RPC_TRACKER(rpc_access_submit_nonce);
diff --git a/src/rpc/core_rpc_server.h b/src/rpc/core_rpc_server.h
index 790d5eb23..7c31d2539 100644
--- a/src/rpc/core_rpc_server.h
+++ b/src/rpc/core_rpc_server.h
@@ -178,6 +178,7 @@ namespace cryptonote
MAP_JON_RPC_WE("get_output_distribution", on_get_output_distribution, COMMAND_RPC_GET_OUTPUT_DISTRIBUTION)
MAP_JON_RPC_WE_IF("prune_blockchain", on_prune_blockchain, COMMAND_RPC_PRUNE_BLOCKCHAIN, !m_restricted)
MAP_JON_RPC_WE_IF("flush_cache", on_flush_cache, COMMAND_RPC_FLUSH_CACHE, !m_restricted)
+ MAP_JON_RPC_WE("get_txids_loose", on_get_txids_loose, COMMAND_RPC_GET_TXIDS_LOOSE)
MAP_JON_RPC_WE("rpc_access_info", on_rpc_access_info, COMMAND_RPC_ACCESS_INFO)
MAP_JON_RPC_WE("rpc_access_submit_nonce",on_rpc_access_submit_nonce, COMMAND_RPC_ACCESS_SUBMIT_NONCE)
MAP_JON_RPC_WE("rpc_access_pay", on_rpc_access_pay, COMMAND_RPC_ACCESS_PAY)
@@ -255,6 +256,7 @@ namespace cryptonote
bool 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 = NULL);
bool on_prune_blockchain(const COMMAND_RPC_PRUNE_BLOCKCHAIN::request& req, COMMAND_RPC_PRUNE_BLOCKCHAIN::response& res, epee::json_rpc::error& error_resp, const connection_context *ctx = NULL);
bool on_flush_cache(const COMMAND_RPC_FLUSH_CACHE::request& req, COMMAND_RPC_FLUSH_CACHE::response& res, epee::json_rpc::error& error_resp, const connection_context *ctx = NULL);
+ bool on_get_txids_loose(const COMMAND_RPC_GET_TXIDS_LOOSE::request& req, COMMAND_RPC_GET_TXIDS_LOOSE::response& res, epee::json_rpc::error& error_resp, const connection_context *ctx = NULL);
bool on_rpc_access_info(const COMMAND_RPC_ACCESS_INFO::request& req, COMMAND_RPC_ACCESS_INFO::response& res, epee::json_rpc::error& error_resp, const connection_context *ctx = NULL);
bool on_rpc_access_submit_nonce(const COMMAND_RPC_ACCESS_SUBMIT_NONCE::request& req, COMMAND_RPC_ACCESS_SUBMIT_NONCE::response& res, epee::json_rpc::error& error_resp, const connection_context *ctx = NULL);
bool on_rpc_access_pay(const COMMAND_RPC_ACCESS_PAY::request& req, COMMAND_RPC_ACCESS_PAY::response& res, epee::json_rpc::error& error_resp, const connection_context *ctx = NULL);
diff --git a/src/rpc/core_rpc_server_commands_defs.h b/src/rpc/core_rpc_server_commands_defs.h
index 819d77c1f..2a0a6201d 100644
--- a/src/rpc/core_rpc_server_commands_defs.h
+++ b/src/rpc/core_rpc_server_commands_defs.h
@@ -617,7 +617,7 @@ namespace cryptonote
bool do_sanity_checks;
BEGIN_KV_SERIALIZE_MAP()
- KV_SERIALIZE_PARENT(rpc_access_request_base);
+ KV_SERIALIZE_PARENT(rpc_access_request_base)
KV_SERIALIZE(tx_as_hex)
KV_SERIALIZE_OPT(do_not_relay, false)
KV_SERIALIZE_OPT(do_sanity_checks, true)
@@ -693,7 +693,7 @@ namespace cryptonote
struct request_t: public rpc_access_request_base
{
BEGIN_KV_SERIALIZE_MAP()
- KV_SERIALIZE_PARENT(rpc_access_request_base);
+ KV_SERIALIZE_PARENT(rpc_access_request_base)
END_KV_SERIALIZE_MAP()
};
typedef epee::misc_utils::struct_init<request_t> request;
@@ -1094,7 +1094,7 @@ namespace cryptonote
blobdata blocktemplate_blob;
blobdata blockhashing_blob;
std::string merkle_root;
- uint32_t merkle_tree_depth;
+ uint64_t merkle_tree_depth;
std::vector<aux_pow_t> aux_pow;
BEGIN_KV_SERIALIZE_MAP()
@@ -1217,7 +1217,7 @@ namespace cryptonote
BEGIN_KV_SERIALIZE_MAP()
KV_SERIALIZE_PARENT(rpc_access_request_base)
- KV_SERIALIZE_OPT(fill_pow_hash, false);
+ KV_SERIALIZE_OPT(fill_pow_hash, false)
END_KV_SERIALIZE_MAP()
};
typedef epee::misc_utils::struct_init<request_t> request;
@@ -1247,7 +1247,7 @@ namespace cryptonote
KV_SERIALIZE_PARENT(rpc_access_request_base)
KV_SERIALIZE(hash)
KV_SERIALIZE(hashes)
- KV_SERIALIZE_OPT(fill_pow_hash, false);
+ KV_SERIALIZE_OPT(fill_pow_hash, false)
END_KV_SERIALIZE_MAP()
};
typedef epee::misc_utils::struct_init<request_t> request;
@@ -1276,7 +1276,7 @@ namespace cryptonote
BEGIN_KV_SERIALIZE_MAP()
KV_SERIALIZE_PARENT(rpc_access_request_base)
KV_SERIALIZE(height)
- KV_SERIALIZE_OPT(fill_pow_hash, false);
+ KV_SERIALIZE_OPT(fill_pow_hash, false)
END_KV_SERIALIZE_MAP()
};
typedef epee::misc_utils::struct_init<request_t> request;
@@ -1305,7 +1305,7 @@ namespace cryptonote
KV_SERIALIZE_PARENT(rpc_access_request_base)
KV_SERIALIZE(hash)
KV_SERIALIZE(height)
- KV_SERIALIZE_OPT(fill_pow_hash, false);
+ KV_SERIALIZE_OPT(fill_pow_hash, false)
END_KV_SERIALIZE_MAP()
};
typedef epee::misc_utils::struct_init<request_t> request;
@@ -1763,7 +1763,7 @@ namespace cryptonote
KV_SERIALIZE_PARENT(rpc_access_request_base)
KV_SERIALIZE(start_height)
KV_SERIALIZE(end_height)
- KV_SERIALIZE_OPT(fill_pow_hash, false);
+ KV_SERIALIZE_OPT(fill_pow_hash, false)
END_KV_SERIALIZE_MAP()
};
typedef epee::misc_utils::struct_init<request_t> request;
@@ -2124,12 +2124,12 @@ namespace cryptonote
uint64_t recent_cutoff;
BEGIN_KV_SERIALIZE_MAP()
- KV_SERIALIZE_PARENT(rpc_access_request_base);
- KV_SERIALIZE(amounts);
- KV_SERIALIZE(min_count);
- KV_SERIALIZE(max_count);
- KV_SERIALIZE(unlocked);
- KV_SERIALIZE(recent_cutoff);
+ KV_SERIALIZE_PARENT(rpc_access_request_base)
+ KV_SERIALIZE(amounts)
+ KV_SERIALIZE(min_count)
+ KV_SERIALIZE(max_count)
+ KV_SERIALIZE(unlocked)
+ KV_SERIALIZE(recent_cutoff)
END_KV_SERIALIZE_MAP()
};
typedef epee::misc_utils::struct_init<request_t> request;
@@ -2142,10 +2142,10 @@ namespace cryptonote
uint64_t recent_instances;
BEGIN_KV_SERIALIZE_MAP()
- KV_SERIALIZE(amount);
- KV_SERIALIZE(total_instances);
- KV_SERIALIZE(unlocked_instances);
- KV_SERIALIZE(recent_instances);
+ KV_SERIALIZE(amount)
+ KV_SERIALIZE(total_instances)
+ KV_SERIALIZE(unlocked_instances)
+ KV_SERIALIZE(recent_instances)
END_KV_SERIALIZE_MAP()
entry(uint64_t amount, uint64_t total_instances, uint64_t unlocked_instances, uint64_t recent_instances):
@@ -2216,9 +2216,9 @@ namespace cryptonote
uint64_t count;
BEGIN_KV_SERIALIZE_MAP()
- KV_SERIALIZE_PARENT(rpc_access_request_base);
- KV_SERIALIZE(height);
- KV_SERIALIZE(count);
+ KV_SERIALIZE_PARENT(rpc_access_request_base)
+ KV_SERIALIZE(height)
+ KV_SERIALIZE(count)
END_KV_SERIALIZE_MAP()
};
typedef epee::misc_utils::struct_init<request_t> request;
@@ -2793,4 +2793,31 @@ namespace cryptonote
typedef epee::misc_utils::struct_init<response_t> response;
};
+ struct COMMAND_RPC_GET_TXIDS_LOOSE
+ {
+ struct request_t: public rpc_request_base
+ {
+ std::string txid_template;
+ std::uint32_t num_matching_bits;
+
+ BEGIN_KV_SERIALIZE_MAP()
+ KV_SERIALIZE_PARENT(rpc_request_base)
+ KV_SERIALIZE(txid_template)
+ KV_SERIALIZE(num_matching_bits)
+ END_KV_SERIALIZE_MAP()
+ };
+ typedef epee::misc_utils::struct_init<request_t> request;
+
+ struct response_t: public rpc_response_base
+ {
+ std::vector<std::string> txids;
+
+ BEGIN_KV_SERIALIZE_MAP()
+ KV_SERIALIZE_PARENT(rpc_response_base)
+ KV_SERIALIZE(txids)
+ END_KV_SERIALIZE_MAP()
+ };
+ typedef epee::misc_utils::struct_init<response_t> response;
+ };
+
}
diff --git a/src/rpc/daemon_messages.cpp b/src/rpc/daemon_messages.cpp
index 0da22f15f..36528fcea 100644
--- a/src/rpc/daemon_messages.cpp
+++ b/src/rpc/daemon_messages.cpp
@@ -48,6 +48,11 @@ void GetHeight::Response::doToJson(rapidjson::Writer<epee::byte_stream>& dest) c
void GetHeight::Response::fromJson(const rapidjson::Value& val)
{
+ if (!val.IsObject())
+ {
+ throw json::WRONG_TYPE("json object");
+ }
+
GET_FROM_JSON_OBJECT(val, height, height);
}
@@ -61,6 +66,11 @@ void GetBlocksFast::Request::doToJson(rapidjson::Writer<epee::byte_stream>& dest
void GetBlocksFast::Request::fromJson(const rapidjson::Value& val)
{
+ if (!val.IsObject())
+ {
+ throw json::WRONG_TYPE("json object");
+ }
+
GET_FROM_JSON_OBJECT(val, block_ids, block_ids);
GET_FROM_JSON_OBJECT(val, start_height, start_height);
GET_FROM_JSON_OBJECT(val, prune, prune);
@@ -76,6 +86,11 @@ void GetBlocksFast::Response::doToJson(rapidjson::Writer<epee::byte_stream>& des
void GetBlocksFast::Response::fromJson(const rapidjson::Value& val)
{
+ if (!val.IsObject())
+ {
+ throw json::WRONG_TYPE("json object");
+ }
+
GET_FROM_JSON_OBJECT(val, blocks, blocks);
GET_FROM_JSON_OBJECT(val, start_height, start_height);
GET_FROM_JSON_OBJECT(val, current_height, current_height);
@@ -91,6 +106,11 @@ void GetHashesFast::Request::doToJson(rapidjson::Writer<epee::byte_stream>& dest
void GetHashesFast::Request::fromJson(const rapidjson::Value& val)
{
+ if (!val.IsObject())
+ {
+ throw json::WRONG_TYPE("json object");
+ }
+
GET_FROM_JSON_OBJECT(val, known_hashes, known_hashes);
GET_FROM_JSON_OBJECT(val, start_height, start_height);
}
@@ -100,10 +120,16 @@ void GetHashesFast::Response::doToJson(rapidjson::Writer<epee::byte_stream>& des
INSERT_INTO_JSON_OBJECT(dest, hashes, hashes);
INSERT_INTO_JSON_OBJECT(dest, start_height, start_height);
INSERT_INTO_JSON_OBJECT(dest, current_height, current_height);
+
}
void GetHashesFast::Response::fromJson(const rapidjson::Value& val)
{
+ if (!val.IsObject())
+ {
+ throw json::WRONG_TYPE("json object");
+ }
+
GET_FROM_JSON_OBJECT(val, hashes, hashes);
GET_FROM_JSON_OBJECT(val, start_height, start_height);
GET_FROM_JSON_OBJECT(val, current_height, current_height);
@@ -117,6 +143,11 @@ void GetTransactions::Request::doToJson(rapidjson::Writer<epee::byte_stream>& de
void GetTransactions::Request::fromJson(const rapidjson::Value& val)
{
+ if (!val.IsObject())
+ {
+ throw json::WRONG_TYPE("json object");
+ }
+
GET_FROM_JSON_OBJECT(val, tx_hashes, tx_hashes);
}
@@ -128,6 +159,11 @@ void GetTransactions::Response::doToJson(rapidjson::Writer<epee::byte_stream>& d
void GetTransactions::Response::fromJson(const rapidjson::Value& val)
{
+ if (!val.IsObject())
+ {
+ throw json::WRONG_TYPE("json object");
+ }
+
GET_FROM_JSON_OBJECT(val, txs, txs);
GET_FROM_JSON_OBJECT(val, missed_hashes, missed_hashes);
}
@@ -140,6 +176,11 @@ void KeyImagesSpent::Request::doToJson(rapidjson::Writer<epee::byte_stream>& des
void KeyImagesSpent::Request::fromJson(const rapidjson::Value& val)
{
+ if (!val.IsObject())
+ {
+ throw json::WRONG_TYPE("json object");
+ }
+
GET_FROM_JSON_OBJECT(val, key_images, key_images);
}
@@ -150,6 +191,11 @@ void KeyImagesSpent::Response::doToJson(rapidjson::Writer<epee::byte_stream>& de
void KeyImagesSpent::Response::fromJson(const rapidjson::Value& val)
{
+ if (!val.IsObject())
+ {
+ throw json::WRONG_TYPE("json object");
+ }
+
GET_FROM_JSON_OBJECT(val, spent_status, spent_status);
}
@@ -161,6 +207,11 @@ void GetTxGlobalOutputIndices::Request::doToJson(rapidjson::Writer<epee::byte_st
void GetTxGlobalOutputIndices::Request::fromJson(const rapidjson::Value& val)
{
+ if (!val.IsObject())
+ {
+ throw json::WRONG_TYPE("json object");
+ }
+
GET_FROM_JSON_OBJECT(val, tx_hash, tx_hash);
}
@@ -171,6 +222,11 @@ void GetTxGlobalOutputIndices::Response::doToJson(rapidjson::Writer<epee::byte_s
void GetTxGlobalOutputIndices::Response::fromJson(const rapidjson::Value& val)
{
+ if (!val.IsObject())
+ {
+ throw json::WRONG_TYPE("json object");
+ }
+
GET_FROM_JSON_OBJECT(val, output_indices, output_indices);
}
@@ -182,6 +238,11 @@ void SendRawTx::Request::doToJson(rapidjson::Writer<epee::byte_stream>& dest) co
void SendRawTx::Request::fromJson(const rapidjson::Value& val)
{
+ if (!val.IsObject())
+ {
+ throw json::WRONG_TYPE("json object");
+ }
+
GET_FROM_JSON_OBJECT(val, tx, tx);
GET_FROM_JSON_OBJECT(val, relay, relay);
}
@@ -194,6 +255,11 @@ void SendRawTx::Response::doToJson(rapidjson::Writer<epee::byte_stream>& dest) c
void SendRawTx::Response::fromJson(const rapidjson::Value& val)
{
+ if (!val.IsObject())
+ {
+ throw json::WRONG_TYPE("json object");
+ }
+
GET_FROM_JSON_OBJECT(val, relayed, relayed);
}
@@ -205,6 +271,11 @@ void SendRawTxHex::Request::doToJson(rapidjson::Writer<epee::byte_stream>& dest)
void SendRawTxHex::Request::fromJson(const rapidjson::Value& val)
{
+ if (!val.IsObject())
+ {
+ throw json::WRONG_TYPE("json object");
+ }
+
GET_FROM_JSON_OBJECT(val, tx_as_hex, tx_as_hex);
GET_FROM_JSON_OBJECT(val, relay, relay);
}
@@ -219,6 +290,11 @@ void StartMining::Request::doToJson(rapidjson::Writer<epee::byte_stream>& dest)
void StartMining::Request::fromJson(const rapidjson::Value& val)
{
+ if (!val.IsObject())
+ {
+ throw json::WRONG_TYPE("json object");
+ }
+
GET_FROM_JSON_OBJECT(val, miner_address, miner_address);
GET_FROM_JSON_OBJECT(val, threads_count, threads_count);
GET_FROM_JSON_OBJECT(val, do_background_mining, do_background_mining);
@@ -266,6 +342,11 @@ void MiningStatus::Response::doToJson(rapidjson::Writer<epee::byte_stream>& dest
void MiningStatus::Response::fromJson(const rapidjson::Value& val)
{
+ if (!val.IsObject())
+ {
+ throw json::WRONG_TYPE("json object");
+ }
+
GET_FROM_JSON_OBJECT(val, active, active);
GET_FROM_JSON_OBJECT(val, speed, speed);
GET_FROM_JSON_OBJECT(val, threads_count, threads_count);
@@ -288,6 +369,11 @@ void GetInfo::Response::doToJson(rapidjson::Writer<epee::byte_stream>& dest) con
void GetInfo::Response::fromJson(const rapidjson::Value& val)
{
+ if (!val.IsObject())
+ {
+ throw json::WRONG_TYPE("json object");
+ }
+
GET_FROM_JSON_OBJECT(val, info, info);
}
@@ -314,6 +400,11 @@ void GetBlockHash::Request::doToJson(rapidjson::Writer<epee::byte_stream>& dest)
void GetBlockHash::Request::fromJson(const rapidjson::Value& val)
{
+ if (!val.IsObject())
+ {
+ throw json::WRONG_TYPE("json object");
+ }
+
GET_FROM_JSON_OBJECT(val, height, height);
}
@@ -324,6 +415,11 @@ void GetBlockHash::Response::doToJson(rapidjson::Writer<epee::byte_stream>& dest
void GetBlockHash::Response::fromJson(const rapidjson::Value& val)
{
+ if (!val.IsObject())
+ {
+ throw json::WRONG_TYPE("json object");
+ }
+
GET_FROM_JSON_OBJECT(val, hash, hash);
}
@@ -342,6 +438,11 @@ void GetLastBlockHeader::Response::doToJson(rapidjson::Writer<epee::byte_stream>
void GetLastBlockHeader::Response::fromJson(const rapidjson::Value& val)
{
+ if (!val.IsObject())
+ {
+ throw json::WRONG_TYPE("json object");
+ }
+
GET_FROM_JSON_OBJECT(val, header, header);
}
@@ -353,6 +454,11 @@ void GetBlockHeaderByHash::Request::doToJson(rapidjson::Writer<epee::byte_stream
void GetBlockHeaderByHash::Request::fromJson(const rapidjson::Value& val)
{
+ if (!val.IsObject())
+ {
+ throw json::WRONG_TYPE("json object");
+ }
+
GET_FROM_JSON_OBJECT(val, hash, hash);
}
@@ -363,6 +469,11 @@ void GetBlockHeaderByHash::Response::doToJson(rapidjson::Writer<epee::byte_strea
void GetBlockHeaderByHash::Response::fromJson(const rapidjson::Value& val)
{
+ if (!val.IsObject())
+ {
+ throw json::WRONG_TYPE("json object");
+ }
+
GET_FROM_JSON_OBJECT(val, header, header);
}
@@ -374,6 +485,11 @@ void GetBlockHeaderByHeight::Request::doToJson(rapidjson::Writer<epee::byte_stre
void GetBlockHeaderByHeight::Request::fromJson(const rapidjson::Value& val)
{
+ if (!val.IsObject())
+ {
+ throw json::WRONG_TYPE("json object");
+ }
+
GET_FROM_JSON_OBJECT(val, height, height);
}
@@ -384,6 +500,11 @@ void GetBlockHeaderByHeight::Response::doToJson(rapidjson::Writer<epee::byte_str
void GetBlockHeaderByHeight::Response::fromJson(const rapidjson::Value& val)
{
+ if (!val.IsObject())
+ {
+ throw json::WRONG_TYPE("json object");
+ }
+
GET_FROM_JSON_OBJECT(val, header, header);
}
@@ -395,6 +516,11 @@ void GetBlockHeadersByHeight::Request::doToJson(rapidjson::Writer<epee::byte_str
void GetBlockHeadersByHeight::Request::fromJson(const rapidjson::Value& val)
{
+ if (!val.IsObject())
+ {
+ throw json::WRONG_TYPE("json object");
+ }
+
GET_FROM_JSON_OBJECT(val, heights, heights);
}
@@ -405,6 +531,11 @@ void GetBlockHeadersByHeight::Response::doToJson(rapidjson::Writer<epee::byte_st
void GetBlockHeadersByHeight::Response::fromJson(const rapidjson::Value& val)
{
+ if (!val.IsObject())
+ {
+ throw json::WRONG_TYPE("json object");
+ }
+
GET_FROM_JSON_OBJECT(val, headers, headers);
}
@@ -424,6 +555,11 @@ void GetPeerList::Response::doToJson(rapidjson::Writer<epee::byte_stream>& dest)
void GetPeerList::Response::fromJson(const rapidjson::Value& val)
{
+ if (!val.IsObject())
+ {
+ throw json::WRONG_TYPE("json object");
+ }
+
GET_FROM_JSON_OBJECT(val, white_list, white_list);
GET_FROM_JSON_OBJECT(val, gray_list, gray_list);
}
@@ -436,6 +572,11 @@ void SetLogLevel::Request::doToJson(rapidjson::Writer<epee::byte_stream>& dest)
void SetLogLevel::Request::fromJson(const rapidjson::Value& val)
{
+ if (!val.IsObject())
+ {
+ throw json::WRONG_TYPE("json object");
+ }
+
GET_FROM_JSON_OBJECT(val, level, level);
}
@@ -462,6 +603,11 @@ void GetTransactionPool::Response::doToJson(rapidjson::Writer<epee::byte_stream>
void GetTransactionPool::Response::fromJson(const rapidjson::Value& val)
{
+ if (!val.IsObject())
+ {
+ throw json::WRONG_TYPE("json object");
+ }
+
GET_FROM_JSON_OBJECT(val, transactions, transactions);
GET_FROM_JSON_OBJECT(val, key_images, key_images);
}
@@ -474,6 +620,11 @@ void HardForkInfo::Request::doToJson(rapidjson::Writer<epee::byte_stream>& dest)
void HardForkInfo::Request::fromJson(const rapidjson::Value& val)
{
+ if (!val.IsObject())
+ {
+ throw json::WRONG_TYPE("json object");
+ }
+
GET_FROM_JSON_OBJECT(val, version, version);
}
@@ -484,6 +635,11 @@ void HardForkInfo::Response::doToJson(rapidjson::Writer<epee::byte_stream>& dest
void HardForkInfo::Response::fromJson(const rapidjson::Value& val)
{
+ if (!val.IsObject())
+ {
+ throw json::WRONG_TYPE("json object");
+ }
+
GET_FROM_JSON_OBJECT(val, info, info);
}
@@ -499,6 +655,11 @@ void GetOutputHistogram::Request::doToJson(rapidjson::Writer<epee::byte_stream>&
void GetOutputHistogram::Request::fromJson(const rapidjson::Value& val)
{
+ if (!val.IsObject())
+ {
+ throw json::WRONG_TYPE("json object");
+ }
+
GET_FROM_JSON_OBJECT(val, amounts, amounts);
GET_FROM_JSON_OBJECT(val, min_count, min_count);
GET_FROM_JSON_OBJECT(val, max_count, max_count);
@@ -513,6 +674,11 @@ void GetOutputHistogram::Response::doToJson(rapidjson::Writer<epee::byte_stream>
void GetOutputHistogram::Response::fromJson(const rapidjson::Value& val)
{
+ if (!val.IsObject())
+ {
+ throw json::WRONG_TYPE("json object");
+ }
+
GET_FROM_JSON_OBJECT(val, histogram, histogram);
}
@@ -524,6 +690,11 @@ void GetOutputKeys::Request::doToJson(rapidjson::Writer<epee::byte_stream>& dest
void GetOutputKeys::Request::fromJson(const rapidjson::Value& val)
{
+ if (!val.IsObject())
+ {
+ throw json::WRONG_TYPE("json object");
+ }
+
GET_FROM_JSON_OBJECT(val, outputs, outputs);
}
@@ -534,6 +705,11 @@ void GetOutputKeys::Response::doToJson(rapidjson::Writer<epee::byte_stream>& des
void GetOutputKeys::Response::fromJson(const rapidjson::Value& val)
{
+ if (!val.IsObject())
+ {
+ throw json::WRONG_TYPE("json object");
+ }
+
GET_FROM_JSON_OBJECT(val, keys, keys);
}
@@ -552,6 +728,11 @@ void GetRPCVersion::Response::doToJson(rapidjson::Writer<epee::byte_stream>& des
void GetRPCVersion::Response::fromJson(const rapidjson::Value& val)
{
+ if (!val.IsObject())
+ {
+ throw json::WRONG_TYPE("json object");
+ }
+
GET_FROM_JSON_OBJECT(val, version, version);
}
@@ -562,6 +743,11 @@ void GetFeeEstimate::Request::doToJson(rapidjson::Writer<epee::byte_stream>& des
void GetFeeEstimate::Request::fromJson(const rapidjson::Value& val)
{
+ if (!val.IsObject())
+ {
+ throw json::WRONG_TYPE("json object");
+ }
+
GET_FROM_JSON_OBJECT(val, num_grace_blocks, num_grace_blocks);
}
@@ -575,6 +761,11 @@ void GetFeeEstimate::Response::doToJson(rapidjson::Writer<epee::byte_stream>& de
void GetFeeEstimate::Response::fromJson(const rapidjson::Value& val)
{
+ if (!val.IsObject())
+ {
+ throw json::WRONG_TYPE("json object");
+ }
+
GET_FROM_JSON_OBJECT(val, estimated_base_fee, estimated_base_fee);
GET_FROM_JSON_OBJECT(val, fee_mask, fee_mask);
GET_FROM_JSON_OBJECT(val, size_scale, size_scale);
@@ -591,6 +782,11 @@ void GetOutputDistribution::Request::doToJson(rapidjson::Writer<epee::byte_strea
void GetOutputDistribution::Request::fromJson(const rapidjson::Value& val)
{
+ if (!val.IsObject())
+ {
+ throw json::WRONG_TYPE("json object");
+ }
+
GET_FROM_JSON_OBJECT(val, amounts, amounts);
GET_FROM_JSON_OBJECT(val, from_height, from_height);
GET_FROM_JSON_OBJECT(val, to_height, to_height);
@@ -605,6 +801,11 @@ void GetOutputDistribution::Response::doToJson(rapidjson::Writer<epee::byte_stre
void GetOutputDistribution::Response::fromJson(const rapidjson::Value& val)
{
+ if (!val.IsObject())
+ {
+ throw json::WRONG_TYPE("json object");
+ }
+
GET_FROM_JSON_OBJECT(val, status, status);
GET_FROM_JSON_OBJECT(val, distributions, distributions);
}
diff --git a/src/rpc/rpc_payment.h b/src/rpc/rpc_payment.h
index 4ead5a344..a4cc6db57 100644
--- a/src/rpc/rpc_payment.h
+++ b/src/rpc/rpc_payment.h
@@ -148,8 +148,8 @@ namespace cryptonote
template <class t_archive>
inline void serialize(t_archive &a, const unsigned int ver)
{
- a & m_client_info.parent();
- a & m_hashrate.parent();
+ a & m_client_info;
+ a & m_hashrate;
a & m_credits_total;
a & m_credits_used;
a & m_nonces_good;
@@ -177,9 +177,9 @@ namespace cryptonote
cryptonote::account_public_address m_address;
uint64_t m_diff;
uint64_t m_credits_per_hash_found;
- serializable_unordered_map<crypto::public_key, client_info> m_client_info;
+ std::unordered_map<crypto::public_key, client_info> m_client_info;
std::string m_directory;
- serializable_map<uint64_t, uint64_t> m_hashrate;
+ std::map<uint64_t, uint64_t> m_hashrate;
uint64_t m_credits_total;
uint64_t m_credits_used;
uint64_t m_nonces_good;
diff --git a/src/rpc/zmq_server.cpp b/src/rpc/zmq_server.cpp
index cb8a8bea4..d73ea3bc9 100644
--- a/src/rpc/zmq_server.cpp
+++ b/src/rpc/zmq_server.cpp
@@ -158,13 +158,22 @@ void ZmqServer::serve()
if (!pub || sockets[2].revents)
{
- std::string message = MONERO_UNWRAP(net::zmq::receive(rep.get(), read_flags));
- MDEBUG("Received RPC request: \"" << message << "\"");
- epee::byte_slice response = handler.handle(std::move(message));
-
- const boost::string_ref response_view{reinterpret_cast<const char*>(response.data()), response.size()};
- MDEBUG("Sending RPC reply: \"" << response_view << "\"");
- MONERO_UNWRAP(net::zmq::send(std::move(response), rep.get()));
+ expect<std::string> message = net::zmq::receive(rep.get(), read_flags);
+ if (!message)
+ {
+ // EAGAIN can occur when using `zmq_poll`, which doesn't inspect for message validity
+ if (message != net::zmq::make_error_code(EAGAIN))
+ MONERO_THROW(message.error(), "Read failure on ZMQ-RPC");
+ }
+ else // no errors
+ {
+ MDEBUG("Received RPC request: \"" << *message << "\"");
+ epee::byte_slice response = handler.handle(std::move(*message));
+
+ const boost::string_ref response_view{reinterpret_cast<const char*>(response.data()), response.size()};
+ MDEBUG("Sending RPC reply: \"" << response_view << "\"");
+ MONERO_UNWRAP(net::zmq::send(std::move(response), rep.get()));
+ }
}
}
}