aboutsummaryrefslogtreecommitdiff
path: root/src/blockchain_db
diff options
context:
space:
mode:
Diffstat (limited to 'src/blockchain_db')
-rw-r--r--src/blockchain_db/blockchain_db.cpp84
-rw-r--r--src/blockchain_db/blockchain_db.h49
-rw-r--r--src/blockchain_db/lmdb/db_lmdb.cpp58
-rw-r--r--src/blockchain_db/lmdb/db_lmdb.h10
-rw-r--r--src/blockchain_db/testdb.h10
5 files changed, 180 insertions, 31 deletions
diff --git a/src/blockchain_db/blockchain_db.cpp b/src/blockchain_db/blockchain_db.cpp
index 63ac38a88..1a6a19da5 100644
--- a/src/blockchain_db/blockchain_db.cpp
+++ b/src/blockchain_db/blockchain_db.cpp
@@ -44,6 +44,71 @@ using epee::string_tools::pod_to_hex;
namespace cryptonote
{
+bool matches_category(relay_method method, relay_category category) noexcept
+{
+ switch (category)
+ {
+ default:
+ return false;
+ case relay_category::all:
+ return true;
+ case relay_category::relayable:
+ if (method == relay_method::none)
+ return false;
+ return true;
+ case relay_category::broadcasted:
+ case relay_category::legacy:
+ break;
+ }
+ // check for "broadcasted" or "legacy" methods:
+ switch (method)
+ {
+ default:
+ case relay_method::local:
+ return false;
+ case relay_method::block:
+ case relay_method::fluff:
+ return true;
+ case relay_method::none:
+ break;
+ }
+ return category == relay_category::legacy;
+}
+
+void txpool_tx_meta_t::set_relay_method(relay_method method) noexcept
+{
+ kept_by_block = 0;
+ do_not_relay = 0;
+ is_local = 0;
+
+ switch (method)
+ {
+ case relay_method::none:
+ do_not_relay = 1;
+ break;
+ case relay_method::local:
+ is_local = 1;
+ break;
+ default:
+ case relay_method::fluff:
+ break;
+ case relay_method::block:
+ kept_by_block = 1;
+ break;
+ }
+}
+
+relay_method txpool_tx_meta_t::get_relay_method() const noexcept
+{
+ if (kept_by_block)
+ return relay_method::block;
+ if (do_not_relay)
+ return relay_method::none;
+ if (is_local)
+ return relay_method::local;
+ return relay_method::fluff;
+}
+
const command_line::arg_descriptor<std::string> arg_db_sync_mode = {
"db-sync-mode"
, "Specify sync option, using format [safe|fast|fastest]:[sync|async]:[<nblocks_per_sync>[blocks]|<nbytes_per_sync>[bytes]]."
@@ -924,4 +989,23 @@ void BlockchainDB::fixup()
batch_stop();
}
+bool BlockchainDB::txpool_tx_matches_category(const crypto::hash& tx_hash, relay_category category)
+{
+ try
+ {
+ txpool_tx_meta_t meta{};
+ if (!get_txpool_tx_meta(tx_hash, meta))
+ {
+ MERROR("Failed to get tx meta from txpool");
+ return false;
+ }
+ return meta.matches(category);
+ }
+ catch (const std::exception &e)
+ {
+ MERROR("Failed to get tx meta from txpool: " << e.what());
+ }
+ return false;
+}
+
} // namespace cryptonote
diff --git a/src/blockchain_db/blockchain_db.h b/src/blockchain_db/blockchain_db.h
index 21700d5d3..e9fc85803 100644
--- a/src/blockchain_db/blockchain_db.h
+++ b/src/blockchain_db/blockchain_db.h
@@ -39,6 +39,7 @@
#include "cryptonote_basic/cryptonote_basic.h"
#include "cryptonote_basic/difficulty.h"
#include "cryptonote_basic/hardfork.h"
+#include "cryptonote_protocol/enums.h"
/** \file
* Cryptonote Blockchain Database Interface
@@ -105,6 +106,16 @@ typedef std::pair<crypto::hash, uint64_t> tx_out_index;
extern const command_line::arg_descriptor<std::string> arg_db_sync_mode;
extern const command_line::arg_descriptor<bool, false> arg_db_salvage;
+enum class relay_category : uint8_t
+{
+ broadcasted = 0,//!< Public txes received via block/fluff
+ relayable, //!< Every tx not marked `relay_method::none`
+ legacy, //!< `relay_category::broadcasted` + `relay_method::none` for rpc relay requests or historical reasons
+ all //!< Everything in the db
+};
+
+bool matches_category(relay_method method, relay_category category) noexcept;
+
#pragma pack(push, 1)
/**
@@ -156,11 +167,22 @@ struct txpool_tx_meta_t
uint8_t do_not_relay;
uint8_t double_spend_seen: 1;
uint8_t pruned: 1;
- uint8_t bf_padding: 6;
+ uint8_t is_local: 1;
+ uint8_t bf_padding: 5;
uint8_t padding[76]; // till 192 bytes
+
+ void set_relay_method(relay_method method) noexcept;
+ relay_method get_relay_method() const noexcept;
+
+ //! See `relay_category` description
+ bool matches(const relay_category category) const noexcept
+ {
+ return matches_category(get_relay_method(), category);
+ }
};
+
#define DBF_SAFE 1
#define DBF_FAST 2
#define DBF_FASTEST 4
@@ -1481,12 +1503,12 @@ public:
/**
* @brief get the number of transactions in the txpool
*/
- virtual uint64_t get_txpool_tx_count(bool include_unrelayed_txes = true) const = 0;
+ virtual uint64_t get_txpool_tx_count(relay_category tx_category = relay_category::broadcasted) const = 0;
/**
- * @brief check whether a txid is in the txpool
+ * @brief check whether a txid is in the txpool and meets tx_category requirements
*/
- virtual bool txpool_has_tx(const crypto::hash &txid) const = 0;
+ virtual bool txpool_has_tx(const crypto::hash &txid, relay_category tx_category) const = 0;
/**
* @brief remove a txpool transaction
@@ -1510,10 +1532,11 @@ public:
*
* @param txid the transaction id of the transation to lookup
* @param bd the blob to return
+ * @param tx_category for filtering out hidden/private txes
*
- * @return true if the txid was in the txpool, false otherwise
+ * @return True iff `txid` is in the pool and meets `tx_category` requirements
*/
- virtual bool get_txpool_tx_blob(const crypto::hash& txid, cryptonote::blobdata &bd) const = 0;
+ virtual bool get_txpool_tx_blob(const crypto::hash& txid, cryptonote::blobdata &bd, relay_category tx_category) const = 0;
/**
* @brief get a txpool transaction's blob
@@ -1522,7 +1545,17 @@ public:
*
* @return the blob for that transaction
*/
- virtual cryptonote::blobdata get_txpool_tx_blob(const crypto::hash& txid) const = 0;
+ virtual cryptonote::blobdata get_txpool_tx_blob(const crypto::hash& txid, relay_category tx_category) const = 0;
+
+ /**
+ * @brief Check if `tx_hash` relay status is in `category`.
+ *
+ * @param tx_hash hash of the transaction to lookup
+ * @param category relay status category to test against
+ *
+ * @return True if `tx_hash` latest relay status is in `category`.
+ */
+ bool txpool_tx_matches_category(const crypto::hash& tx_hash, relay_category category);
/**
* @brief prune output data for the given amount
@@ -1620,7 +1653,7 @@ public:
*
* @return false if the function returns false for any transaction, otherwise true
*/
- virtual 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 = 0;
+ virtual bool for_all_txpool_txes(std::function<bool(const crypto::hash&, const txpool_tx_meta_t&, const cryptonote::blobdata*)>, bool include_blob = false, relay_category category = relay_category::broadcasted) const = 0;
/**
* @brief runs a function over all key images stored
diff --git a/src/blockchain_db/lmdb/db_lmdb.cpp b/src/blockchain_db/lmdb/db_lmdb.cpp
index 495d70e7d..5093015f2 100644
--- a/src/blockchain_db/lmdb/db_lmdb.cpp
+++ b/src/blockchain_db/lmdb/db_lmdb.cpp
@@ -163,7 +163,15 @@ int BlockchainLMDB::compare_string(const MDB_val *a, const MDB_val *b)
{
const char *va = (const char*) a->mv_data;
const char *vb = (const char*) b->mv_data;
- return strcmp(va, vb);
+ const size_t sz = std::min(a->mv_size, b->mv_size);
+ int ret = strncmp(va, vb, sz);
+ if (ret)
+ return ret;
+ if (a->mv_size < b->mv_size)
+ return -1;
+ if (a->mv_size > b->mv_size)
+ return 1;
+ return 0;
}
}
@@ -1771,7 +1779,7 @@ void BlockchainLMDB::update_txpool_tx(const crypto::hash &txid, const txpool_tx_
}
}
-uint64_t BlockchainLMDB::get_txpool_tx_count(bool include_unrelayed_txes) const
+uint64_t BlockchainLMDB::get_txpool_tx_count(relay_category category) const
{
LOG_PRINT_L3("BlockchainLMDB::" << __func__);
check_open();
@@ -1781,7 +1789,7 @@ uint64_t BlockchainLMDB::get_txpool_tx_count(bool include_unrelayed_txes) const
TXN_PREFIX_RDONLY();
- if (include_unrelayed_txes)
+ if (category == relay_category::all)
{
// No filtering, we can get the number of tx the "fast" way
MDB_stat db_stats;
@@ -1807,7 +1815,7 @@ uint64_t BlockchainLMDB::get_txpool_tx_count(bool include_unrelayed_txes) const
if (result)
throw0(DB_ERROR(lmdb_error("Failed to enumerate txpool tx metadata: ", result).c_str()));
const txpool_tx_meta_t &meta = *(const txpool_tx_meta_t*)v.mv_data;
- if (!meta.do_not_relay)
+ if (meta.matches(category))
++num_entries;
}
}
@@ -1816,7 +1824,7 @@ uint64_t BlockchainLMDB::get_txpool_tx_count(bool include_unrelayed_txes) const
return num_entries;
}
-bool BlockchainLMDB::txpool_has_tx(const crypto::hash& txid) const
+bool BlockchainLMDB::txpool_has_tx(const crypto::hash& txid, relay_category tx_category) const
{
LOG_PRINT_L3("BlockchainLMDB::" << __func__);
check_open();
@@ -1825,11 +1833,21 @@ bool BlockchainLMDB::txpool_has_tx(const crypto::hash& txid) const
RCURSOR(txpool_meta)
MDB_val k = {sizeof(txid), (void *)&txid};
- auto result = mdb_cursor_get(m_cur_txpool_meta, &k, NULL, MDB_SET);
+ MDB_val v;
+ auto result = mdb_cursor_get(m_cur_txpool_meta, &k, &v, MDB_SET);
if (result != 0 && result != MDB_NOTFOUND)
throw1(DB_ERROR(lmdb_error("Error finding txpool tx meta: ", result).c_str()));
+ if (result == MDB_NOTFOUND)
+ return false;
+
+ bool found = true;
+ if (tx_category != relay_category::all)
+ {
+ const txpool_tx_meta_t &meta = *(const txpool_tx_meta_t*)v.mv_data;
+ found = meta.matches(tx_category);
+ }
TXN_POSTFIX_RDONLY();
- return result != MDB_NOTFOUND;
+ return found;
}
void BlockchainLMDB::remove_txpool_tx(const crypto::hash& txid)
@@ -1883,7 +1901,7 @@ bool BlockchainLMDB::get_txpool_tx_meta(const crypto::hash& txid, txpool_tx_meta
return true;
}
-bool BlockchainLMDB::get_txpool_tx_blob(const crypto::hash& txid, cryptonote::blobdata &bd) const
+bool BlockchainLMDB::get_txpool_tx_blob(const crypto::hash& txid, cryptonote::blobdata &bd, relay_category tx_category) const
{
LOG_PRINT_L3("BlockchainLMDB::" << __func__);
check_open();
@@ -1893,6 +1911,21 @@ bool BlockchainLMDB::get_txpool_tx_blob(const crypto::hash& txid, cryptonote::bl
MDB_val k = {sizeof(txid), (void *)&txid};
MDB_val v;
+
+ // if filtering, make sure those requirements are met before copying blob
+ if (tx_category != relay_category::all)
+ {
+ auto result = mdb_cursor_get(m_cur_txpool_meta, &k, &v, MDB_SET);
+ if (result == MDB_NOTFOUND)
+ return false;
+ if (result != 0)
+ throw1(DB_ERROR(lmdb_error("Error finding txpool tx meta: ", result).c_str()));
+
+ const txpool_tx_meta_t& meta = *(const txpool_tx_meta_t*)v.mv_data;
+ if (!meta.matches(tx_category))
+ return false;
+ }
+
auto result = mdb_cursor_get(m_cur_txpool_blob, &k, &v, MDB_SET);
if (result == MDB_NOTFOUND)
return false;
@@ -1904,10 +1937,10 @@ bool BlockchainLMDB::get_txpool_tx_blob(const crypto::hash& txid, cryptonote::bl
return true;
}
-cryptonote::blobdata BlockchainLMDB::get_txpool_tx_blob(const crypto::hash& txid) const
+cryptonote::blobdata BlockchainLMDB::get_txpool_tx_blob(const crypto::hash& txid, relay_category tx_category) const
{
cryptonote::blobdata bd;
- if (!get_txpool_tx_blob(txid, bd))
+ if (!get_txpool_tx_blob(txid, bd, tx_category))
throw1(DB_ERROR("Tx not found in txpool: "));
return bd;
}
@@ -2245,7 +2278,7 @@ bool BlockchainLMDB::check_pruning()
return prune_worker(prune_mode_check, 0);
}
-bool BlockchainLMDB::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
+bool BlockchainLMDB::for_all_txpool_txes(std::function<bool(const crypto::hash&, const txpool_tx_meta_t&, const cryptonote::blobdata*)> f, bool include_blob, relay_category category) const
{
LOG_PRINT_L3("BlockchainLMDB::" << __func__);
check_open();
@@ -2269,8 +2302,7 @@ bool BlockchainLMDB::for_all_txpool_txes(std::function<bool(const crypto::hash&,
throw0(DB_ERROR(lmdb_error("Failed to enumerate txpool tx metadata: ", result).c_str()));
const crypto::hash txid = *(const crypto::hash*)k.mv_data;
const txpool_tx_meta_t &meta = *(const txpool_tx_meta_t*)v.mv_data;
- if (!include_unrelayed_txes && meta.do_not_relay)
- // Skipping that tx
+ if (!meta.matches(category))
continue;
const cryptonote::blobdata *passed_bd = NULL;
cryptonote::blobdata bd;
diff --git a/src/blockchain_db/lmdb/db_lmdb.h b/src/blockchain_db/lmdb/db_lmdb.h
index 5dd44ec67..7c0b4c72c 100644
--- a/src/blockchain_db/lmdb/db_lmdb.h
+++ b/src/blockchain_db/lmdb/db_lmdb.h
@@ -282,12 +282,12 @@ public:
virtual void add_txpool_tx(const crypto::hash &txid, const cryptonote::blobdata &blob, const txpool_tx_meta_t& meta);
virtual void update_txpool_tx(const crypto::hash &txid, const txpool_tx_meta_t& meta);
- virtual uint64_t get_txpool_tx_count(bool include_unrelayed_txes = true) const;
- virtual bool txpool_has_tx(const crypto::hash &txid) const;
+ virtual uint64_t get_txpool_tx_count(relay_category category = relay_category::broadcasted) const;
+ virtual bool txpool_has_tx(const crypto::hash &txid, relay_category tx_category) const;
virtual void remove_txpool_tx(const crypto::hash& txid);
virtual bool get_txpool_tx_meta(const crypto::hash& txid, txpool_tx_meta_t &meta) const;
- virtual bool get_txpool_tx_blob(const crypto::hash& txid, cryptonote::blobdata &bd) const;
- virtual cryptonote::blobdata get_txpool_tx_blob(const crypto::hash& txid) const;
+ virtual bool get_txpool_tx_blob(const crypto::hash& txid, cryptonote::blobdata& bd, relay_category tx_category) const;
+ virtual cryptonote::blobdata get_txpool_tx_blob(const crypto::hash& txid, relay_category tx_category) const;
virtual uint32_t get_blockchain_pruning_seed() const;
virtual bool prune_blockchain(uint32_t pruning_seed = 0);
virtual bool update_pruning();
@@ -299,7 +299,7 @@ public:
virtual uint64_t get_alt_block_count();
virtual void drop_alt_blocks();
- virtual bool for_all_txpool_txes(std::function<bool(const crypto::hash&, const txpool_tx_meta_t&, const cryptonote::blobdata*)> f, bool include_blob = false, bool include_unrelayed_txes = true) const;
+ virtual bool for_all_txpool_txes(std::function<bool(const crypto::hash&, const txpool_tx_meta_t&, const cryptonote::blobdata*)> f, bool include_blob = false, relay_category category = relay_category::broadcasted) const;
virtual bool for_all_key_images(std::function<bool(const crypto::key_image&)>) const;
virtual bool for_blocks_range(const uint64_t& h1, const uint64_t& h2, std::function<bool(uint64_t, const crypto::hash&, const cryptonote::block&)>) const;
diff --git a/src/blockchain_db/testdb.h b/src/blockchain_db/testdb.h
index 4176e087c..46de38c7e 100644
--- a/src/blockchain_db/testdb.h
+++ b/src/blockchain_db/testdb.h
@@ -127,14 +127,14 @@ public:
virtual void add_txpool_tx(const crypto::hash &txid, const cryptonote::blobdata &blob, const cryptonote::txpool_tx_meta_t& details) override {}
virtual void update_txpool_tx(const crypto::hash &txid, const cryptonote::txpool_tx_meta_t& details) override {}
- virtual uint64_t get_txpool_tx_count(bool include_unrelayed_txes = true) const override { return 0; }
- virtual bool txpool_has_tx(const crypto::hash &txid) const override { return false; }
+ virtual uint64_t get_txpool_tx_count(relay_category tx_relay = relay_category::broadcasted) const override { return 0; }
+ virtual bool txpool_has_tx(const crypto::hash &txid, relay_category tx_category) const override { return false; }
virtual void remove_txpool_tx(const crypto::hash& txid) override {}
virtual bool get_txpool_tx_meta(const crypto::hash& txid, cryptonote::txpool_tx_meta_t &meta) const override { return false; }
- virtual bool get_txpool_tx_blob(const crypto::hash& txid, cryptonote::blobdata &bd) const override { return false; }
+ virtual bool get_txpool_tx_blob(const crypto::hash& txid, cryptonote::blobdata &bd, relay_category tx_category) const override { return false; }
virtual uint64_t get_database_size() const override { return 0; }
- virtual cryptonote::blobdata get_txpool_tx_blob(const crypto::hash& txid) const override { return ""; }
- virtual bool for_all_txpool_txes(std::function<bool(const crypto::hash&, const cryptonote::txpool_tx_meta_t&, const cryptonote::blobdata*)>, bool include_blob = false, bool include_unrelayed_txes = false) const override { return false; }
+ virtual cryptonote::blobdata get_txpool_tx_blob(const crypto::hash& txid, relay_category tx_category) const override { return ""; }
+ virtual bool for_all_txpool_txes(std::function<bool(const crypto::hash&, const cryptonote::txpool_tx_meta_t&, const cryptonote::blobdata*)>, bool include_blob = false, relay_category category = relay_category::broadcasted) const override { return false; }
virtual void add_block( const cryptonote::block& blk
, size_t block_weight