aboutsummaryrefslogtreecommitdiff
path: root/src/rpc
diff options
context:
space:
mode:
Diffstat (limited to 'src/rpc')
-rwxr-xr-xsrc/rpc/core_rpc_server.cpp55
-rw-r--r--src/rpc/core_rpc_server.h10
-rw-r--r--src/rpc/core_rpc_server_commands_defs.h8
-rw-r--r--src/rpc/message_data_structs.h1
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;