diff options
Diffstat (limited to 'src/rpc')
-rw-r--r-- | src/rpc/core_rpc_server.cpp | 111 | ||||
-rw-r--r-- | src/rpc/core_rpc_server.h | 2 | ||||
-rw-r--r-- | src/rpc/core_rpc_server_commands_defs.h | 69 | ||||
-rw-r--r-- | src/rpc/daemon_messages.cpp | 201 | ||||
-rw-r--r-- | src/rpc/rpc_payment.h | 8 | ||||
-rw-r--r-- | src/rpc/zmq_server.cpp | 23 |
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())); + } } } } |