aboutsummaryrefslogtreecommitdiff
path: root/src/blockchain_db
diff options
context:
space:
mode:
Diffstat (limited to 'src/blockchain_db')
-rw-r--r--src/blockchain_db/berkeleydb/db_bdb.cpp23
-rw-r--r--src/blockchain_db/berkeleydb/db_bdb.h18
-rw-r--r--src/blockchain_db/blockchain_db.cpp10
-rw-r--r--src/blockchain_db/blockchain_db.h7
-rw-r--r--src/blockchain_db/lmdb/db_lmdb.cpp108
-rw-r--r--src/blockchain_db/lmdb/db_lmdb.h22
6 files changed, 88 insertions, 100 deletions
diff --git a/src/blockchain_db/berkeleydb/db_bdb.cpp b/src/blockchain_db/berkeleydb/db_bdb.cpp
index 6c79120e8..b27a00a69 100644
--- a/src/blockchain_db/berkeleydb/db_bdb.cpp
+++ b/src/blockchain_db/berkeleydb/db_bdb.cpp
@@ -714,29 +714,6 @@ bool BlockchainBDB::for_all_outputs(std::function<bool(uint64_t amount, const cr
return ret;
}
-blobdata BlockchainBDB::output_to_blob(const tx_out& output) const
-{
- LOG_PRINT_L3("BlockchainBDB::" << __func__);
- blobdata b;
- if (!t_serializable_object_to_blob(output, b))
- throw1(DB_ERROR("Error serializing output to blob"));
- return b;
-}
-
-tx_out BlockchainBDB::output_from_blob(const blobdata& blob) const
-{
- LOG_PRINT_L3("BlockchainBDB::" << __func__);
- std::stringstream ss;
- ss << blob;
- binary_archive<false> ba(ss);
- tx_out o;
-
- if (!(::serialization::serialize(ba, o)))
- throw1(DB_ERROR("Error deserializing tx output blob"));
-
- return o;
-}
-
uint64_t BlockchainBDB::get_output_global_index(const uint64_t& amount, const uint64_t& index)
{
LOG_PRINT_L3("BlockchainBDB::" << __func__);
diff --git a/src/blockchain_db/berkeleydb/db_bdb.h b/src/blockchain_db/berkeleydb/db_bdb.h
index 76d0a0517..e80adae9e 100644
--- a/src/blockchain_db/berkeleydb/db_bdb.h
+++ b/src/blockchain_db/berkeleydb/db_bdb.h
@@ -392,24 +392,6 @@ private:
virtual void drop_hard_fork_info();
/**
- * @brief convert a tx output to a blob for storage
- *
- * @param output the output to convert
- *
- * @return the resultant blob
- */
- blobdata output_to_blob(const tx_out& output) const;
-
- /**
- * @brief convert a tx output blob to a tx output
- *
- * @param blob the blob to convert
- *
- * @return the resultant tx output
- */
- tx_out output_from_blob(const blobdata& blob) const;
-
- /**
* @brief get the global index of the index-th output of the given amount
*
* @param amount the output amount
diff --git a/src/blockchain_db/blockchain_db.cpp b/src/blockchain_db/blockchain_db.cpp
index be0ffeac3..c25798c1e 100644
--- a/src/blockchain_db/blockchain_db.cpp
+++ b/src/blockchain_db/blockchain_db.cpp
@@ -170,7 +170,7 @@ void BlockchainDB::add_transaction(const crypto::hash& blk_hash, const transacti
uint64_t tx_id = add_transaction_data(blk_hash, tx, tx_hash, tx_prunable_hash);
- std::vector<uint64_t> amount_output_indices;
+ std::vector<uint64_t> amount_output_indices(tx.vout.size());
// iterate tx.vout using indices instead of C++11 foreach syntax because
// we need the index
@@ -183,13 +183,13 @@ void BlockchainDB::add_transaction(const crypto::hash& blk_hash, const transacti
cryptonote::tx_out vout = tx.vout[i];
rct::key commitment = rct::zeroCommit(vout.amount);
vout.amount = 0;
- amount_output_indices.push_back(add_output(tx_hash, vout, i, tx.unlock_time,
- &commitment));
+ amount_output_indices[i] = add_output(tx_hash, vout, i, tx.unlock_time,
+ &commitment);
}
else
{
- amount_output_indices.push_back(add_output(tx_hash, tx.vout[i], i, tx.unlock_time,
- tx.version > 1 ? &tx.rct_signatures.outPk[i].mask : NULL));
+ amount_output_indices[i] = add_output(tx_hash, tx.vout[i], i, tx.unlock_time,
+ tx.version > 1 ? &tx.rct_signatures.outPk[i].mask : NULL);
}
}
add_tx_amount_output_indices(tx_id, amount_output_indices);
diff --git a/src/blockchain_db/blockchain_db.h b/src/blockchain_db/blockchain_db.h
index 7870a2efd..f13aa0cae 100644
--- a/src/blockchain_db/blockchain_db.h
+++ b/src/blockchain_db/blockchain_db.h
@@ -1405,6 +1405,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 5af5d1903..acda777f9 100644
--- a/src/blockchain_db/lmdb/db_lmdb.cpp
+++ b/src/blockchain_db/lmdb/db_lmdb.cpp
@@ -456,6 +456,12 @@ inline int lmdb_txn_renew(MDB_txn *txn)
return res;
}
+inline void BlockchainLMDB::check_open() const
+{
+ if (!m_open)
+ throw0(DB_ERROR("DB operation attempted on a not-open DB instance"));
+}
+
void BlockchainLMDB::do_resize(uint64_t increase_size)
{
LOG_PRINT_L3("BlockchainLMDB::" << __func__);
@@ -1075,6 +1081,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__);
@@ -1112,36 +1172,6 @@ void BlockchainLMDB::remove_spent_key(const crypto::key_image& k_image)
}
}
-blobdata BlockchainLMDB::output_to_blob(const tx_out& output) const
-{
- LOG_PRINT_L3("BlockchainLMDB::" << __func__);
- blobdata b;
- if (!t_serializable_object_to_blob(output, b))
- throw1(DB_ERROR("Error serializing output to blob"));
- return b;
-}
-
-tx_out BlockchainLMDB::output_from_blob(const blobdata& blob) const
-{
- LOG_PRINT_L3("BlockchainLMDB::" << __func__);
- std::stringstream ss;
- ss << blob;
- binary_archive<false> ba(ss);
- tx_out o;
-
- if (!(::serialization::serialize(ba, o)))
- throw1(DB_ERROR("Error deserializing tx output blob"));
-
- return o;
-}
-
-void BlockchainLMDB::check_open() const
-{
-// LOG_PRINT_L3("BlockchainLMDB::" << __func__);
- if (!m_open)
- throw0(DB_ERROR("DB operation attempted on a not-open DB instance"));
-}
-
BlockchainLMDB::~BlockchainLMDB()
{
LOG_PRINT_L3("BlockchainLMDB::" << __func__);
@@ -2229,11 +2259,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
@@ -3130,7 +3168,7 @@ uint64_t BlockchainLMDB::add_block(const block& blk, size_t block_weight, const
check_open();
uint64_t m_height = height();
- if (m_height % 1000 == 0)
+ if (m_height % 1024 == 0)
{
// for batch mode, DB resize check is done at start of batch transaction
if (! m_batch_active && need_resize())
diff --git a/src/blockchain_db/lmdb/db_lmdb.h b/src/blockchain_db/lmdb/db_lmdb.h
index 26159ab4d..b7b1b04d5 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);
@@ -357,25 +359,7 @@ private:
virtual void check_hard_fork_info();
virtual void drop_hard_fork_info();
- /**
- * @brief convert a tx output to a blob for storage
- *
- * @param output the output to convert
- *
- * @return the resultant blob
- */
- blobdata output_to_blob(const tx_out& output) const;
-
- /**
- * @brief convert a tx output blob to a tx output
- *
- * @param blob the blob to convert
- *
- * @return the resultant tx output
- */
- tx_out output_from_blob(const blobdata& blob) const;
-
- void check_open() const;
+ inline void check_open() const;
virtual bool is_read_only() const;