Skip to content

Commit

Permalink
Outputs where all amounts are known spent can now be pruned
Browse files Browse the repository at this point in the history
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.
  • Loading branch information
moneromooo-monero committed Nov 27, 2018
1 parent 58ce16d commit 17b4572
Show file tree
Hide file tree
Showing 6 changed files with 377 additions and 4 deletions.
7 changes: 7 additions & 0 deletions src/blockchain_db/blockchain_db.h
Expand Up @@ -1405,6 +1405,13 @@ class BlockchainDB
*/
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
*
Expand Down
70 changes: 66 additions & 4 deletions src/blockchain_db/lmdb/db_lmdb.cpp
Expand Up @@ -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__);
Expand Down Expand Up @@ -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
Expand Down
2 changes: 2 additions & 0 deletions src/blockchain_db/lmdb/db_lmdb.h
Expand Up @@ -345,6 +345,8 @@ class BlockchainLMDB : public BlockchainDB

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);
Expand Down
33 changes: 33 additions & 0 deletions src/blockchain_utilities/CMakeLists.txt
Expand Up @@ -81,6 +81,17 @@ monero_private_headers(blockchain_usage



set(blockchain_prune_known_spent_data_sources
blockchain_prune_known_spent_data.cpp
)

set(blockchain_prune_known_spent_data_private_headers)

monero_private_headers(blockchain_prune_known_spent_data
${blockchain_prune_known_spent_data_private_headers})



set(blockchain_ancestry_sources
blockchain_ancestry.cpp
)
Expand Down Expand Up @@ -265,3 +276,25 @@ set_property(TARGET blockchain_stats
PROPERTY
OUTPUT_NAME "monero-blockchain-stats")
install(TARGETS blockchain_stats DESTINATION bin)

monero_add_executable(blockchain_prune_known_spent_data
${blockchain_prune_known_spent_data_sources}
${blockchain_prune_known_spent_data_private_headers})

target_link_libraries(blockchain_prune_known_spent_data
PRIVATE
cryptonote_core
blockchain_db
p2p
version
epee
${Boost_FILESYSTEM_LIBRARY}
${Boost_SYSTEM_LIBRARY}
${Boost_THREAD_LIBRARY}
${CMAKE_THREAD_LIBS_INIT}
${EXTRA_LIBRARIES})

set_property(TARGET blockchain_prune_known_spent_data
PROPERTY
OUTPUT_NAME "monero-blockchain-prune-known-spent-data")
install(TARGETS blockchain_prune_known_spent_data DESTINATION bin)

0 comments on commit 17b4572

Please sign in to comment.