aboutsummaryrefslogtreecommitdiff
path: root/src/cryptonote_core
diff options
context:
space:
mode:
authorbinaryFate <binaryfate@users.noreply.github.com>2017-11-08 13:06:41 +0100
committerbinaryFate <binaryfate@users.noreply.github.com>2017-11-08 13:07:07 +0100
commit10013e94342c0d9ca2f10c79779b08affc5209c1 (patch)
treebf0a97c4a827807d50977861f6a33838ec6b6991 /src/cryptonote_core
parentMerge pull request #2764 (diff)
downloadmonero-10013e94342c0d9ca2f10c79779b08affc5209c1.tar.xz
Protect node privacy by proper filtering in restricted-mode RPC answers
This patch allows to filter out sensitive information for queries that rely on the pool state, when running in restricted mode. This filtering is only applied to data sent back to RPC queries. Results of inline commands typed locally in the daemon are not affected. In practice, when running with `--restricted-rpc`: * get_transaction_pool will list relayed transactions with the fields "last relayed time" and "received time" set to zero. * get_transaction_pool will not list transaction that have do_not_relay set to true, and will not list key images that are used only for such transactions * get_transaction_pool_hashes.bin will not list such transaction * get_transaction_pool_stats will not count such transactions in any of the aggregated values that are computed The implementation does not make filtering the default, so developers should be mindful of this if they add new RPC functionality. Fixes #2590.
Diffstat (limited to 'src/cryptonote_core')
-rw-r--r--src/cryptonote_core/blockchain.cpp8
-rw-r--r--src/cryptonote_core/blockchain.h4
-rw-r--r--src/cryptonote_core/cryptonote_core.cpp16
-rw-r--r--src/cryptonote_core/cryptonote_core.h14
-rw-r--r--src/cryptonote_core/tx_pool.cpp62
-rw-r--r--src/cryptonote_core/tx_pool.h22
6 files changed, 80 insertions, 46 deletions
diff --git a/src/cryptonote_core/blockchain.cpp b/src/cryptonote_core/blockchain.cpp
index 9d89c6280..ba64a230d 100644
--- a/src/cryptonote_core/blockchain.cpp
+++ b/src/cryptonote_core/blockchain.cpp
@@ -4211,9 +4211,9 @@ void Blockchain::remove_txpool_tx(const crypto::hash &txid)
m_db->remove_txpool_tx(txid);
}
-uint64_t Blockchain::get_txpool_tx_count() const
+uint64_t Blockchain::get_txpool_tx_count(bool include_unrelayed_txes) const
{
- return m_db->get_txpool_tx_count();
+ return m_db->get_txpool_tx_count(include_unrelayed_txes);
}
txpool_tx_meta_t Blockchain::get_txpool_tx_meta(const crypto::hash& txid) const
@@ -4231,9 +4231,9 @@ cryptonote::blobdata Blockchain::get_txpool_tx_blob(const crypto::hash& txid) co
return m_db->get_txpool_tx_blob(txid);
}
-bool Blockchain::for_all_txpool_txes(std::function<bool(const crypto::hash&, const txpool_tx_meta_t&, const cryptonote::blobdata*)> f, bool include_blob) const
+bool Blockchain::for_all_txpool_txes(std::function<bool(const crypto::hash&, const txpool_tx_meta_t&, const cryptonote::blobdata*)> f, bool include_blob, bool include_unrelayed_txes) const
{
- return m_db->for_all_txpool_txes(f, include_blob);
+ return m_db->for_all_txpool_txes(f, include_blob, include_unrelayed_txes);
}
void Blockchain::set_user_options(uint64_t maxthreads, uint64_t blocks_per_sync, blockchain_db_sync_mode sync_mode, bool fast_sync)
diff --git a/src/cryptonote_core/blockchain.h b/src/cryptonote_core/blockchain.h
index f64bd35e3..3f2930fb0 100644
--- a/src/cryptonote_core/blockchain.h
+++ b/src/cryptonote_core/blockchain.h
@@ -947,11 +947,11 @@ namespace cryptonote
void add_txpool_tx(transaction &tx, const txpool_tx_meta_t &meta);
void update_txpool_tx(const crypto::hash &txid, const txpool_tx_meta_t &meta);
void remove_txpool_tx(const crypto::hash &txid);
- uint64_t get_txpool_tx_count() const;
+ uint64_t get_txpool_tx_count(bool include_unrelayed_txes = true) const;
txpool_tx_meta_t get_txpool_tx_meta(const crypto::hash& txid) const;
bool get_txpool_tx_blob(const crypto::hash& txid, cryptonote::blobdata &bd) const;
cryptonote::blobdata get_txpool_tx_blob(const crypto::hash& txid) const;
- bool for_all_txpool_txes(std::function<bool(const crypto::hash&, const txpool_tx_meta_t&, const cryptonote::blobdata*)>, bool include_blob = false) const;
+ bool for_all_txpool_txes(std::function<bool(const crypto::hash&, const txpool_tx_meta_t&, const cryptonote::blobdata*)>, bool include_blob = false, bool include_unrelayed_txes = true) const;
bool is_within_compiled_block_hash_area(uint64_t height) const;
bool is_within_compiled_block_hash_area() const { return is_within_compiled_block_hash_area(m_db->height()); }
diff --git a/src/cryptonote_core/cryptonote_core.cpp b/src/cryptonote_core/cryptonote_core.cpp
index 61f844612..3f56ffac7 100644
--- a/src/cryptonote_core/cryptonote_core.cpp
+++ b/src/cryptonote_core/cryptonote_core.cpp
@@ -1182,21 +1182,21 @@ namespace cryptonote
return true;
}
//-----------------------------------------------------------------------------------------------
- bool core::get_pool_transactions(std::list<transaction>& txs) const
+ bool core::get_pool_transactions(std::list<transaction>& txs, bool include_sensitive_data) const
{
- m_mempool.get_transactions(txs);
+ m_mempool.get_transactions(txs, include_sensitive_data);
return true;
}
//-----------------------------------------------------------------------------------------------
- bool core::get_pool_transaction_hashes(std::vector<crypto::hash>& txs) const
+ bool core::get_pool_transaction_hashes(std::vector<crypto::hash>& txs, bool include_sensitive_data) const
{
- m_mempool.get_transaction_hashes(txs);
+ m_mempool.get_transaction_hashes(txs, include_sensitive_data);
return true;
}
//-----------------------------------------------------------------------------------------------
- bool core::get_pool_transaction_stats(struct txpool_stats& stats) const
+ bool core::get_pool_transaction_stats(struct txpool_stats& stats, bool include_sensitive_data) const
{
- m_mempool.get_transaction_stats(stats);
+ m_mempool.get_transaction_stats(stats, include_sensitive_data);
return true;
}
//-----------------------------------------------------------------------------------------------
@@ -1210,9 +1210,9 @@ namespace cryptonote
return m_mempool.have_tx(id);
}
//-----------------------------------------------------------------------------------------------
- bool core::get_pool_transactions_and_spent_keys_info(std::vector<tx_info>& tx_infos, std::vector<spent_key_image_info>& key_image_infos) const
+ bool core::get_pool_transactions_and_spent_keys_info(std::vector<tx_info>& tx_infos, std::vector<spent_key_image_info>& key_image_infos, bool include_sensitive_data) const
{
- return m_mempool.get_transactions_and_spent_keys_info(tx_infos, key_image_infos);
+ return m_mempool.get_transactions_and_spent_keys_info(tx_infos, key_image_infos, include_sensitive_data);
}
//-----------------------------------------------------------------------------------------------
bool core::get_pool_for_rpc(std::vector<cryptonote::rpc::tx_in_pool>& tx_infos, cryptonote::rpc::key_images_with_tx_hashes& key_image_infos) const
diff --git a/src/cryptonote_core/cryptonote_core.h b/src/cryptonote_core/cryptonote_core.h
index 7340e1024..a3d47280a 100644
--- a/src/cryptonote_core/cryptonote_core.h
+++ b/src/cryptonote_core/cryptonote_core.h
@@ -420,11 +420,12 @@ namespace cryptonote
/**
* @copydoc tx_memory_pool::get_transactions
+ * @param include_unrelayed_txes include unrelayed txes in result
*
* @note see tx_memory_pool::get_transactions
*/
- bool get_pool_transactions(std::list<transaction>& txs) const;
-
+ bool get_pool_transactions(std::list<transaction>& txs, bool include_unrelayed_txes = true) const;
+
/**
* @copydoc tx_memory_pool::get_txpool_backlog
*
@@ -434,17 +435,19 @@ namespace cryptonote
/**
* @copydoc tx_memory_pool::get_transactions
+ * @param include_unrelayed_txes include unrelayed txes in result
*
* @note see tx_memory_pool::get_transactions
*/
- bool get_pool_transaction_hashes(std::vector<crypto::hash>& txs) const;
+ bool get_pool_transaction_hashes(std::vector<crypto::hash>& txs, bool include_unrelayed_txes = true) const;
/**
* @copydoc tx_memory_pool::get_transactions
+ * @param include_unrelayed_txes include unrelayed txes in result
*
* @note see tx_memory_pool::get_transactions
*/
- bool get_pool_transaction_stats(struct txpool_stats& stats) const;
+ bool get_pool_transaction_stats(struct txpool_stats& stats, bool include_unrelayed_txes = true) const;
/**
* @copydoc tx_memory_pool::get_transaction
@@ -455,10 +458,11 @@ namespace cryptonote
/**
* @copydoc tx_memory_pool::get_pool_transactions_and_spent_keys_info
+ * @param include_unrelayed_txes include unrelayed txes in result
*
* @note see tx_memory_pool::get_pool_transactions_and_spent_keys_info
*/
- bool get_pool_transactions_and_spent_keys_info(std::vector<tx_info>& tx_infos, std::vector<spent_key_image_info>& key_image_infos) const;
+ bool get_pool_transactions_and_spent_keys_info(std::vector<tx_info>& tx_infos, std::vector<spent_key_image_info>& key_image_infos, bool include_unrelayed_txes = true) const;
/**
* @copydoc tx_memory_pool::get_pool_for_rpc
diff --git a/src/cryptonote_core/tx_pool.cpp b/src/cryptonote_core/tx_pool.cpp
index 9071c330c..9f4b2fe0f 100644
--- a/src/cryptonote_core/tx_pool.cpp
+++ b/src/cryptonote_core/tx_pool.cpp
@@ -432,7 +432,7 @@ namespace cryptonote
remove.insert(txid);
}
return true;
- });
+ }, false);
if (!remove.empty())
{
@@ -494,7 +494,7 @@ namespace cryptonote
}
}
return true;
- });
+ }, false);
return true;
}
//---------------------------------------------------------------------------------
@@ -521,14 +521,14 @@ namespace cryptonote
}
}
//---------------------------------------------------------------------------------
- size_t tx_memory_pool::get_transactions_count() const
+ size_t tx_memory_pool::get_transactions_count(bool include_unrelayed_txes) const
{
CRITICAL_REGION_LOCAL(m_transactions_lock);
CRITICAL_REGION_LOCAL1(m_blockchain);
- return m_blockchain.get_txpool_tx_count();
+ return m_blockchain.get_txpool_tx_count(include_unrelayed_txes);
}
//---------------------------------------------------------------------------------
- void tx_memory_pool::get_transactions(std::list<transaction>& txs) const
+ void tx_memory_pool::get_transactions(std::list<transaction>& txs, bool include_unrelayed_txes) const
{
CRITICAL_REGION_LOCAL(m_transactions_lock);
CRITICAL_REGION_LOCAL1(m_blockchain);
@@ -542,20 +542,20 @@ namespace cryptonote
}
txs.push_back(tx);
return true;
- }, true);
+ }, true, include_unrelayed_txes);
}
//------------------------------------------------------------------
- void tx_memory_pool::get_transaction_hashes(std::vector<crypto::hash>& txs) const
+ void tx_memory_pool::get_transaction_hashes(std::vector<crypto::hash>& txs, bool include_unrelayed_txes) const
{
CRITICAL_REGION_LOCAL(m_transactions_lock);
CRITICAL_REGION_LOCAL1(m_blockchain);
m_blockchain.for_all_txpool_txes([&txs](const crypto::hash &txid, const txpool_tx_meta_t &meta, const cryptonote::blobdata *bd){
txs.push_back(txid);
return true;
- });
+ }, false, include_unrelayed_txes);
}
//------------------------------------------------------------------
- void tx_memory_pool::get_transaction_backlog(std::vector<tx_backlog_entry>& backlog) const
+ void tx_memory_pool::get_transaction_backlog(std::vector<tx_backlog_entry>& backlog, bool include_unrelayed_txes) const
{
CRITICAL_REGION_LOCAL(m_transactions_lock);
CRITICAL_REGION_LOCAL1(m_blockchain);
@@ -563,16 +563,16 @@ namespace cryptonote
m_blockchain.for_all_txpool_txes([&backlog, now](const crypto::hash &txid, const txpool_tx_meta_t &meta, const cryptonote::blobdata *bd){
backlog.push_back({meta.blob_size, meta.fee, meta.receive_time - now});
return true;
- });
+ }, false, include_unrelayed_txes);
}
//------------------------------------------------------------------
- void tx_memory_pool::get_transaction_stats(struct txpool_stats& stats) const
+ void tx_memory_pool::get_transaction_stats(struct txpool_stats& stats, bool include_unrelayed_txes) const
{
CRITICAL_REGION_LOCAL(m_transactions_lock);
CRITICAL_REGION_LOCAL1(m_blockchain);
const uint64_t now = time(NULL);
std::map<uint64_t, txpool_histo> agebytes;
- stats.txs_total = m_blockchain.get_txpool_tx_count();
+ stats.txs_total = m_blockchain.get_txpool_tx_count(include_unrelayed_txes);
std::vector<uint32_t> sizes;
sizes.reserve(stats.txs_total);
m_blockchain.for_all_txpool_txes([&stats, &sizes, now, &agebytes](const crypto::hash &txid, const txpool_tx_meta_t &meta, const cryptonote::blobdata *bd){
@@ -595,7 +595,7 @@ namespace cryptonote
agebytes[age].txs++;
agebytes[age].bytes += meta.blob_size;
return true;
- });
+ }, false, include_unrelayed_txes);
stats.bytes_med = epee::misc_utils::median(sizes);
if (stats.txs_total > 1)
{
@@ -642,11 +642,11 @@ namespace cryptonote
}
//------------------------------------------------------------------
//TODO: investigate whether boolean return is appropriate
- bool tx_memory_pool::get_transactions_and_spent_keys_info(std::vector<tx_info>& tx_infos, std::vector<spent_key_image_info>& key_image_infos) const
+ bool tx_memory_pool::get_transactions_and_spent_keys_info(std::vector<tx_info>& tx_infos, std::vector<spent_key_image_info>& key_image_infos, bool include_sensitive_data) const
{
CRITICAL_REGION_LOCAL(m_transactions_lock);
CRITICAL_REGION_LOCAL1(m_blockchain);
- m_blockchain.for_all_txpool_txes([&tx_infos, key_image_infos](const crypto::hash &txid, const txpool_tx_meta_t &meta, const cryptonote::blobdata *bd){
+ m_blockchain.for_all_txpool_txes([&tx_infos, key_image_infos, include_sensitive_data](const crypto::hash &txid, const txpool_tx_meta_t &meta, const cryptonote::blobdata *bd){
tx_info txi;
txi.id_hash = epee::string_tools::pod_to_hex(txid);
transaction tx;
@@ -664,14 +664,17 @@ namespace cryptonote
txi.max_used_block_id_hash = epee::string_tools::pod_to_hex(meta.max_used_block_id);
txi.last_failed_height = meta.last_failed_height;
txi.last_failed_id_hash = epee::string_tools::pod_to_hex(meta.last_failed_id);
- txi.receive_time = meta.receive_time;
+ // In restricted mode we do not include this data:
+ txi.receive_time = include_sensitive_data ? meta.receive_time : 0;
txi.relayed = meta.relayed;
- txi.last_relayed_time = meta.last_relayed_time;
+ // In restricted mode we do not include this data:
+ txi.last_relayed_time = include_sensitive_data ? meta.last_relayed_time : 0;
txi.do_not_relay = meta.do_not_relay;
tx_infos.push_back(txi);
return true;
- }, true);
+ }, true, include_sensitive_data);
+ txpool_tx_meta_t meta;
for (const key_images_container::value_type& kee : m_spent_key_images) {
const crypto::key_image& k_image = kee.first;
const std::unordered_set<crypto::hash>& kei_image_set = kee.second;
@@ -679,9 +682,26 @@ namespace cryptonote
ki.id_hash = epee::string_tools::pod_to_hex(k_image);
for (const crypto::hash& tx_id_hash : kei_image_set)
{
+ if (!include_sensitive_data)
+ {
+ try
+ {
+ meta = m_blockchain.get_txpool_tx_meta(tx_id_hash);
+ if (!meta.relayed)
+ // Do not include that transaction if in restricted mode and it's not relayed
+ continue;
+ }
+ catch (const std::exception &e)
+ {
+ MERROR("Failed to get tx meta from txpool: " << e.what());
+ return false;
+ }
+ }
ki.txs_hashes.push_back(epee::string_tools::pod_to_hex(tx_id_hash));
}
- key_image_infos.push_back(ki);
+ // Only return key images for which we have at least one tx that we can show for them
+ if (!ki.txs_hashes.empty())
+ key_image_infos.push_back(ki);
}
return true;
}
@@ -714,7 +734,7 @@ namespace cryptonote
txi.do_not_relay = meta.do_not_relay;
tx_infos.push_back(txi);
return true;
- }, true);
+ }, true, false);
for (const key_images_container::value_type& kee : m_spent_key_images) {
std::vector<crypto::hash> tx_hashes;
@@ -1044,7 +1064,7 @@ namespace cryptonote
remove.insert(txid);
}
return true;
- });
+ }, false);
size_t n_removed = 0;
if (!remove.empty())
diff --git a/src/cryptonote_core/tx_pool.h b/src/cryptonote_core/tx_pool.h
index 3e4ccb338..6bdc9f54e 100644
--- a/src/cryptonote_core/tx_pool.h
+++ b/src/cryptonote_core/tx_pool.h
@@ -233,29 +233,37 @@ namespace cryptonote
* @brief get a list of all transactions in the pool
*
* @param txs return-by-reference the list of transactions
+ * @param include_unrelayed_txes include unrelayed txes in the result
+ *
*/
- void get_transactions(std::list<transaction>& txs) const;
+ void get_transactions(std::list<transaction>& txs, bool include_unrelayed_txes = true) const;
/**
* @brief get a list of all transaction hashes in the pool
*
* @param txs return-by-reference the list of transactions
+ * @param include_unrelayed_txes include unrelayed txes in the result
+ *
*/
- void get_transaction_hashes(std::vector<crypto::hash>& txs) const;
+ void get_transaction_hashes(std::vector<crypto::hash>& txs, bool include_unrelayed_txes = true) const;
/**
* @brief get (size, fee, receive time) for all transaction in the pool
*
* @param txs return-by-reference that data
+ * @param include_unrelayed_txes include unrelayed txes in the result
+ *
*/
- void get_transaction_backlog(std::vector<tx_backlog_entry>& backlog) const;
+ void get_transaction_backlog(std::vector<tx_backlog_entry>& backlog, bool include_unrelayed_txes = true) const;
/**
* @brief get a summary statistics of all transaction hashes in the pool
*
* @param stats return-by-reference the pool statistics
+ * @param include_unrelayed_txes include unrelayed txes in the result
+ *
*/
- void get_transaction_stats(struct txpool_stats& stats) const;
+ void get_transaction_stats(struct txpool_stats& stats, bool include_unrelayed_txes = true) const;
/**
* @brief get information about all transactions and key images in the pool
@@ -264,10 +272,11 @@ namespace cryptonote
*
* @param tx_infos return-by-reference the transactions' information
* @param key_image_infos return-by-reference the spent key images' information
+ * @param include_sensitive_data include unrelayed txes and fields that are sensitive to the node privacy
*
* @return true
*/
- bool get_transactions_and_spent_keys_info(std::vector<tx_info>& tx_infos, std::vector<spent_key_image_info>& key_image_infos) const;
+ bool get_transactions_and_spent_keys_info(std::vector<tx_info>& tx_infos, std::vector<spent_key_image_info>& key_image_infos, bool include_sensitive_data = true) const;
/**
* @brief get information about all transactions and key images in the pool
@@ -308,6 +317,7 @@ namespace cryptonote
* nonzero fee
* hasn't been relayed too recently
* isn't old enough that relaying it is considered harmful
+ * Note a transaction can be "relayable" even if do_not_relay is true
*
* @param txs return-by-reference the transactions and their hashes
*
@@ -327,7 +337,7 @@ namespace cryptonote
*
* @return the number of transactions in the pool
*/
- size_t get_transactions_count() const;
+ size_t get_transactions_count(bool include_unrelayed_txes = true) const;
/**
* @brief get a string containing human-readable pool information