diff options
Diffstat (limited to 'src/rpc')
-rwxr-xr-x | src/rpc/core_rpc_server.cpp | 55 | ||||
-rw-r--r-- | src/rpc/core_rpc_server.h | 10 | ||||
-rw-r--r-- | src/rpc/core_rpc_server_commands_defs.h | 8 | ||||
-rw-r--r-- | src/rpc/message_data_structs.h | 1 |
4 files changed, 55 insertions, 19 deletions
diff --git a/src/rpc/core_rpc_server.cpp b/src/rpc/core_rpc_server.cpp index 1e3bf1b3a..776b8c5c0 100755 --- a/src/rpc/core_rpc_server.cpp +++ b/src/rpc/core_rpc_server.cpp @@ -478,15 +478,17 @@ namespace cryptonote // try the pool for any missing txes size_t found_in_pool = 0; std::unordered_set<crypto::hash> pool_tx_hashes; + std::unordered_map<crypto::hash, bool> double_spend_seen; if (!missed_txs.empty()) { - std::list<transaction> pool_txs; - bool r = m_core.get_pool_transactions(pool_txs); + std::vector<tx_info> pool_tx_info; + std::vector<spent_key_image_info> pool_key_image_info; + bool r = m_core.get_pool_transactions_and_spent_keys_info(pool_tx_info, pool_key_image_info); if(r) { // sort to match original request std::list<transaction> sorted_txs; - std::list<cryptonote::transaction>::const_iterator i; + std::vector<tx_info>::const_iterator i; for (const crypto::hash &h: vh) { if (std::find(missed_txs.begin(), missed_txs.end(), h) == missed_txs.end()) @@ -500,11 +502,26 @@ namespace cryptonote sorted_txs.push_back(std::move(txs.front())); txs.pop_front(); } - else if ((i = std::find_if(pool_txs.begin(), pool_txs.end(), [h](cryptonote::transaction &tx) { return h == cryptonote::get_transaction_hash(tx); })) != pool_txs.end()) + else if ((i = std::find_if(pool_tx_info.begin(), pool_tx_info.end(), [h](const tx_info &txi) { return epee::string_tools::pod_to_hex(h) == txi.id_hash; })) != pool_tx_info.end()) { - sorted_txs.push_back(*i); + cryptonote::transaction tx; + if (!cryptonote::parse_and_validate_tx_from_blob(i->tx_blob, tx)) + { + res.status = "Failed to parse and validate tx from blob"; + return true; + } + sorted_txs.push_back(tx); missed_txs.remove(h); pool_tx_hashes.insert(h); + const std::string hash_string = epee::string_tools::pod_to_hex(h); + for (const auto &ti: pool_tx_info) + { + if (ti.id_hash == hash_string) + { + double_spend_seen.insert(std::make_pair(h, ti.double_spend_seen)); + break; + } + } ++found_in_pool; } } @@ -530,11 +547,21 @@ namespace cryptonote if (e.in_pool) { e.block_height = e.block_timestamp = std::numeric_limits<uint64_t>::max(); + if (double_spend_seen.find(tx_hash) != double_spend_seen.end()) + { + e.double_spend_seen = double_spend_seen[tx_hash]; + } + else + { + MERROR("Failed to determine double spend status for " << tx_hash); + e.double_spend_seen = false; + } } else { e.block_height = m_core.get_blockchain_storage().get_db().get_tx_block_height(tx_hash); e.block_timestamp = m_core.get_blockchain_storage().get_db().get_block_timestamp(e.block_height); + e.double_spend_seen = false; } // fill up old style responses too, in case an old wallet asks @@ -564,7 +591,7 @@ namespace cryptonote return true; } //------------------------------------------------------------------------------------------------------------------------------ - bool core_rpc_server::on_is_key_image_spent(const COMMAND_RPC_IS_KEY_IMAGE_SPENT::request& req, COMMAND_RPC_IS_KEY_IMAGE_SPENT::response& res) + bool core_rpc_server::on_is_key_image_spent(const COMMAND_RPC_IS_KEY_IMAGE_SPENT::request& req, COMMAND_RPC_IS_KEY_IMAGE_SPENT::response& res, bool request_has_rpc_origin) { CHECK_CORE_BUSY(); std::vector<crypto::key_image> key_images; @@ -596,7 +623,7 @@ namespace cryptonote // check the pool too std::vector<cryptonote::tx_info> txs; std::vector<cryptonote::spent_key_image_info> ki; - r = m_core.get_pool_transactions_and_spent_keys_info(txs, ki); + r = m_core.get_pool_transactions_and_spent_keys_info(txs, ki, !request_has_rpc_origin || !m_restricted); if(!r) { res.status = "Failed"; @@ -843,26 +870,26 @@ namespace cryptonote return true; } //------------------------------------------------------------------------------------------------------------------------------ - bool core_rpc_server::on_get_transaction_pool(const COMMAND_RPC_GET_TRANSACTION_POOL::request& req, COMMAND_RPC_GET_TRANSACTION_POOL::response& res) + bool core_rpc_server::on_get_transaction_pool(const COMMAND_RPC_GET_TRANSACTION_POOL::request& req, COMMAND_RPC_GET_TRANSACTION_POOL::response& res, bool request_has_rpc_origin) { CHECK_CORE_BUSY(); - m_core.get_pool_transactions_and_spent_keys_info(res.transactions, res.spent_key_images); + m_core.get_pool_transactions_and_spent_keys_info(res.transactions, res.spent_key_images, !request_has_rpc_origin || !m_restricted); res.status = CORE_RPC_STATUS_OK; return true; } //------------------------------------------------------------------------------------------------------------------------------ - bool core_rpc_server::on_get_transaction_pool_hashes(const COMMAND_RPC_GET_TRANSACTION_POOL_HASHES::request& req, COMMAND_RPC_GET_TRANSACTION_POOL_HASHES::response& res) + bool core_rpc_server::on_get_transaction_pool_hashes(const COMMAND_RPC_GET_TRANSACTION_POOL_HASHES::request& req, COMMAND_RPC_GET_TRANSACTION_POOL_HASHES::response& res, bool request_has_rpc_origin) { CHECK_CORE_BUSY(); - m_core.get_pool_transaction_hashes(res.tx_hashes); + m_core.get_pool_transaction_hashes(res.tx_hashes, !request_has_rpc_origin || !m_restricted); res.status = CORE_RPC_STATUS_OK; return true; } //------------------------------------------------------------------------------------------------------------------------------ - bool core_rpc_server::on_get_transaction_pool_stats(const COMMAND_RPC_GET_TRANSACTION_POOL_STATS::request& req, COMMAND_RPC_GET_TRANSACTION_POOL_STATS::response& res) + bool core_rpc_server::on_get_transaction_pool_stats(const COMMAND_RPC_GET_TRANSACTION_POOL_STATS::request& req, COMMAND_RPC_GET_TRANSACTION_POOL_STATS::response& res, bool request_has_rpc_origin) { CHECK_CORE_BUSY(); - m_core.get_pool_transaction_stats(res.pool_stats); + m_core.get_pool_transaction_stats(res.pool_stats, !request_has_rpc_origin || !m_restricted); res.status = CORE_RPC_STATUS_OK; return true; } @@ -1826,7 +1853,7 @@ namespace cryptonote const command_line::arg_descriptor<bool> core_rpc_server::arg_restricted_rpc = { "restricted-rpc" - , "Restrict RPC to view only commands" + , "Restrict RPC to view only commands and do not return privacy sensitive data in RPC calls" , false }; } // namespace cryptonote diff --git a/src/rpc/core_rpc_server.h b/src/rpc/core_rpc_server.h index 73a308a72..7f252258c 100644 --- a/src/rpc/core_rpc_server.h +++ b/src/rpc/core_rpc_server.h @@ -122,7 +122,7 @@ namespace cryptonote MAP_JON_RPC_WE_IF("flush_txpool", on_flush_txpool, COMMAND_RPC_FLUSH_TRANSACTION_POOL, !m_restricted) MAP_JON_RPC_WE("get_output_histogram", on_get_output_histogram, COMMAND_RPC_GET_OUTPUT_HISTOGRAM) MAP_JON_RPC_WE("get_version", on_get_version, COMMAND_RPC_GET_VERSION) - MAP_JON_RPC_WE("get_coinbase_tx_sum", on_get_coinbase_tx_sum, COMMAND_RPC_GET_COINBASE_TX_SUM) + MAP_JON_RPC_WE_IF("get_coinbase_tx_sum", on_get_coinbase_tx_sum, COMMAND_RPC_GET_COINBASE_TX_SUM, !m_restricted) MAP_JON_RPC_WE("get_fee_estimate", on_get_per_kb_fee_estimate, COMMAND_RPC_GET_PER_KB_FEE_ESTIMATE) MAP_JON_RPC_WE_IF("get_alternate_chains",on_get_alternate_chains, COMMAND_RPC_GET_ALTERNATE_CHAINS, !m_restricted) MAP_JON_RPC_WE_IF("relay_tx", on_relay_tx, COMMAND_RPC_RELAY_TX, !m_restricted) @@ -137,7 +137,7 @@ namespace cryptonote bool on_get_blocks_by_height(const COMMAND_RPC_GET_BLOCKS_BY_HEIGHT::request& req, COMMAND_RPC_GET_BLOCKS_BY_HEIGHT::response& res); bool on_get_hashes(const COMMAND_RPC_GET_HASHES_FAST::request& req, COMMAND_RPC_GET_HASHES_FAST::response& res); bool on_get_transactions(const COMMAND_RPC_GET_TRANSACTIONS::request& req, COMMAND_RPC_GET_TRANSACTIONS::response& res); - bool on_is_key_image_spent(const COMMAND_RPC_IS_KEY_IMAGE_SPENT::request& req, COMMAND_RPC_IS_KEY_IMAGE_SPENT::response& res); + bool on_is_key_image_spent(const COMMAND_RPC_IS_KEY_IMAGE_SPENT::request& req, COMMAND_RPC_IS_KEY_IMAGE_SPENT::response& res, bool request_has_rpc_origin = true); bool on_get_indexes(const COMMAND_RPC_GET_TX_GLOBAL_OUTPUTS_INDEXES::request& req, COMMAND_RPC_GET_TX_GLOBAL_OUTPUTS_INDEXES::response& res); bool on_send_raw_tx(const COMMAND_RPC_SEND_RAW_TX::request& req, COMMAND_RPC_SEND_RAW_TX::response& res); bool on_start_mining(const COMMAND_RPC_START_MINING::request& req, COMMAND_RPC_START_MINING::response& res); @@ -153,9 +153,9 @@ namespace cryptonote bool on_set_log_hash_rate(const COMMAND_RPC_SET_LOG_HASH_RATE::request& req, COMMAND_RPC_SET_LOG_HASH_RATE::response& res); bool on_set_log_level(const COMMAND_RPC_SET_LOG_LEVEL::request& req, COMMAND_RPC_SET_LOG_LEVEL::response& res); bool on_set_log_categories(const COMMAND_RPC_SET_LOG_CATEGORIES::request& req, COMMAND_RPC_SET_LOG_CATEGORIES::response& res); - bool on_get_transaction_pool(const COMMAND_RPC_GET_TRANSACTION_POOL::request& req, COMMAND_RPC_GET_TRANSACTION_POOL::response& res); - bool on_get_transaction_pool_hashes(const COMMAND_RPC_GET_TRANSACTION_POOL_HASHES::request& req, COMMAND_RPC_GET_TRANSACTION_POOL_HASHES::response& res); - bool on_get_transaction_pool_stats(const COMMAND_RPC_GET_TRANSACTION_POOL_STATS::request& req, COMMAND_RPC_GET_TRANSACTION_POOL_STATS::response& res); + bool on_get_transaction_pool(const COMMAND_RPC_GET_TRANSACTION_POOL::request& req, COMMAND_RPC_GET_TRANSACTION_POOL::response& res, bool request_has_rpc_origin = true); + bool on_get_transaction_pool_hashes(const COMMAND_RPC_GET_TRANSACTION_POOL_HASHES::request& req, COMMAND_RPC_GET_TRANSACTION_POOL_HASHES::response& res, bool request_has_rpc_origin = true); + bool on_get_transaction_pool_stats(const COMMAND_RPC_GET_TRANSACTION_POOL_STATS::request& req, COMMAND_RPC_GET_TRANSACTION_POOL_STATS::response& res, bool request_has_rpc_origin = true); bool on_stop_daemon(const COMMAND_RPC_STOP_DAEMON::request& req, COMMAND_RPC_STOP_DAEMON::response& res); bool on_get_limit(const COMMAND_RPC_GET_LIMIT::request& req, COMMAND_RPC_GET_LIMIT::response& res); bool on_set_limit(const COMMAND_RPC_SET_LIMIT::request& req, COMMAND_RPC_SET_LIMIT::response& res); diff --git a/src/rpc/core_rpc_server_commands_defs.h b/src/rpc/core_rpc_server_commands_defs.h index d4c1a673e..d3b4db64f 100644 --- a/src/rpc/core_rpc_server_commands_defs.h +++ b/src/rpc/core_rpc_server_commands_defs.h @@ -566,6 +566,7 @@ namespace cryptonote std::string as_hex; std::string as_json; bool in_pool; + bool double_spend_seen; uint64_t block_height; uint64_t block_timestamp; std::vector<uint64_t> output_indices; @@ -575,6 +576,7 @@ namespace cryptonote KV_SERIALIZE(as_hex) KV_SERIALIZE(as_json) KV_SERIALIZE(in_pool) + KV_SERIALIZE(double_spend_seen) KV_SERIALIZE(block_height) KV_SERIALIZE(block_timestamp) KV_SERIALIZE(output_indices) @@ -1359,6 +1361,8 @@ namespace cryptonote bool relayed; uint64_t last_relayed_time; bool do_not_relay; + bool double_spend_seen; + std::string tx_blob; BEGIN_KV_SERIALIZE_MAP() KV_SERIALIZE(id_hash) @@ -1374,6 +1378,8 @@ namespace cryptonote KV_SERIALIZE(relayed) KV_SERIALIZE(last_relayed_time) KV_SERIALIZE(do_not_relay) + KV_SERIALIZE(double_spend_seen) + KV_SERIALIZE(tx_blob) END_KV_SERIALIZE_MAP() }; @@ -1482,6 +1488,7 @@ namespace cryptonote uint32_t num_not_relayed; uint64_t histo_98pc; std::vector<txpool_histo> histo; + uint32_t num_double_spends; BEGIN_KV_SERIALIZE_MAP() KV_SERIALIZE(bytes_total) @@ -1496,6 +1503,7 @@ namespace cryptonote KV_SERIALIZE(num_not_relayed) KV_SERIALIZE(histo_98pc) KV_SERIALIZE_CONTAINER_POD_AS_BLOB(histo) + KV_SERIALIZE(num_double_spends) END_KV_SERIALIZE_MAP() }; diff --git a/src/rpc/message_data_structs.h b/src/rpc/message_data_structs.h index 00f1e0caa..581048eaf 100644 --- a/src/rpc/message_data_structs.h +++ b/src/rpc/message_data_structs.h @@ -95,6 +95,7 @@ namespace rpc uint64_t last_relayed_time; bool relayed; bool do_not_relay; + bool double_spend_seen; }; typedef std::unordered_map<crypto::key_image, std::vector<crypto::hash> > key_images_with_tx_hashes; |