aboutsummaryrefslogtreecommitdiff
path: root/src/blockchain_db
diff options
context:
space:
mode:
authormoneromooo-monero <moneromooo-monero@users.noreply.github.com>2018-11-24 14:49:04 +0000
committermoneromooo-monero <moneromooo-monero@users.noreply.github.com>2018-11-27 15:45:42 +0000
commit17b45725af754a3887f0c59bd5c67c58278d71eb (patch)
tree320c7ce2fc49f5eba4bdeca9263c9e7345ec18e5 /src/blockchain_db
parentMerge pull request #4821 (diff)
downloadmonero-17b45725af754a3887f0c59bd5c67c58278d71eb.tar.xz
Outputs where all amounts are known spent can now be pruned
Only for pre rct for obvious reasons. Note: DO NOT use a known spent list which includes outputs which are not known spent. If the list includes any output that's just strongly thought to be spent, but not provably so, you risk finding yourself unable to sync past the point where that output is spent. I estimate only 200 MB saved on current mainnet though, unless the new blackballing rule unearths a good amount of large-amount-set extra spent outs.
Diffstat (limited to 'src/blockchain_db')
-rw-r--r--src/blockchain_db/blockchain_db.h7
-rw-r--r--src/blockchain_db/lmdb/db_lmdb.cpp70
-rw-r--r--src/blockchain_db/lmdb/db_lmdb.h2
3 files changed, 75 insertions, 4 deletions
diff --git a/src/blockchain_db/blockchain_db.h b/src/blockchain_db/blockchain_db.h
index 53e33898a..a8f4eafe0 100644
--- a/src/blockchain_db/blockchain_db.h
+++ b/src/blockchain_db/blockchain_db.h
@@ -1406,6 +1406,13 @@ public:
virtual cryptonote::blobdata get_txpool_tx_blob(const crypto::hash& txid) const = 0;
/**
+ * @brief prune output data for the given amount
+ *
+ * @param amount the amount for which to prune data
+ */
+ virtual void prune_outputs(uint64_t amount) = 0;
+
+ /**
* @brief runs a function over all txpool transactions
*
* The subclass should run the passed function for each txpool tx it has
diff --git a/src/blockchain_db/lmdb/db_lmdb.cpp b/src/blockchain_db/lmdb/db_lmdb.cpp
index d260caa75..142e86b5d 100644
--- a/src/blockchain_db/lmdb/db_lmdb.cpp
+++ b/src/blockchain_db/lmdb/db_lmdb.cpp
@@ -1077,6 +1077,60 @@ void BlockchainLMDB::remove_output(const uint64_t amount, const uint64_t& out_in
throw0(DB_ERROR(lmdb_error(std::string("Error deleting amount for output index ").append(boost::lexical_cast<std::string>(out_index).append(": ")).c_str(), result).c_str()));
}
+void BlockchainLMDB::prune_outputs(uint64_t amount)
+{
+ LOG_PRINT_L3("BlockchainLMDB::" << __func__);
+ check_open();
+ mdb_txn_cursors *m_cursors = &m_wcursors;
+ CURSOR(output_amounts);
+ CURSOR(output_txs);
+
+ MINFO("Pruning outputs for amount " << amount);
+
+ MDB_val v;
+ MDB_val_set(k, amount);
+ int result = mdb_cursor_get(m_cur_output_amounts, &k, &v, MDB_SET);
+ if (result == MDB_NOTFOUND)
+ return;
+ if (result)
+ throw0(DB_ERROR(lmdb_error("Error looking up outputs: ", result).c_str()));
+
+ // gather output ids
+ mdb_size_t num_elems;
+ mdb_cursor_count(m_cur_output_amounts, &num_elems);
+ MINFO(num_elems << " outputs found");
+ std::vector<uint64_t> output_ids;
+ output_ids.reserve(num_elems);
+ while (1)
+ {
+ const pre_rct_outkey *okp = (const pre_rct_outkey *)v.mv_data;
+ output_ids.push_back(okp->output_id);
+ MDEBUG("output id " << okp->output_id);
+ result = mdb_cursor_get(m_cur_output_amounts, &k, &v, MDB_NEXT_DUP);
+ if (result == MDB_NOTFOUND)
+ break;
+ if (result)
+ throw0(DB_ERROR(lmdb_error("Error counting outputs: ", result).c_str()));
+ }
+ if (output_ids.size() != num_elems)
+ throw0(DB_ERROR("Unexpected number of outputs"));
+
+ result = mdb_cursor_del(m_cur_output_amounts, MDB_NODUPDATA);
+ if (result)
+ throw0(DB_ERROR(lmdb_error("Error deleting outputs: ", result).c_str()));
+
+ for (uint64_t output_id: output_ids)
+ {
+ MDB_val_set(v, output_id);
+ result = mdb_cursor_get(m_cur_output_txs, (MDB_val *)&zerokval, &v, MDB_GET_BOTH);
+ if (result)
+ throw0(DB_ERROR(lmdb_error("Error looking up output: ", result).c_str()));
+ result = mdb_cursor_del(m_cur_output_txs, 0);
+ if (result)
+ throw0(DB_ERROR(lmdb_error("Error deleting output: ", result).c_str()));
+ }
+}
+
void BlockchainLMDB::add_spent_key(const crypto::key_image& k_image)
{
LOG_PRINT_L3("BlockchainLMDB::" << __func__);
@@ -2231,11 +2285,19 @@ uint64_t BlockchainLMDB::num_outputs() const
TXN_PREFIX_RDONLY();
int result;
- // get current height
- MDB_stat db_stats;
- if ((result = mdb_stat(m_txn, m_output_txs, &db_stats)))
+ RCURSOR(output_txs)
+
+ uint64_t num = 0;
+ MDB_val k, v;
+ result = mdb_cursor_get(m_cur_output_txs, &k, &v, MDB_LAST);
+ if (result == MDB_NOTFOUND)
+ num = 0;
+ else if (result == 0)
+ num = 1 + ((const outtx*)v.mv_data)->output_id;
+ else
throw0(DB_ERROR(lmdb_error("Failed to query m_output_txs: ", result).c_str()));
- return db_stats.ms_entries;
+
+ return num;
}
bool BlockchainLMDB::tx_exists(const crypto::hash& h) const
diff --git a/src/blockchain_db/lmdb/db_lmdb.h b/src/blockchain_db/lmdb/db_lmdb.h
index 26159ab4d..6db241240 100644
--- a/src/blockchain_db/lmdb/db_lmdb.h
+++ b/src/blockchain_db/lmdb/db_lmdb.h
@@ -345,6 +345,8 @@ private:
void remove_output(const uint64_t amount, const uint64_t& out_index);
+ virtual void prune_outputs(uint64_t amount);
+
virtual void add_spent_key(const crypto::key_image& k_image);
virtual void remove_spent_key(const crypto::key_image& k_image);