diff --git a/src/blockchain_db/blockchain_db.cpp b/src/blockchain_db/blockchain_db.cpp index 8cde4f138..68f635d18 100644 --- a/src/blockchain_db/blockchain_db.cpp +++ b/src/blockchain_db/blockchain_db.cpp @@ -82,21 +82,17 @@ void BlockchainDB::add_transaction(const crypto::hash& blk_hash, const transacti } } - uint64_t tx_index = add_transaction_data(blk_hash, tx, tx_hash); + uint64_t tx_id = add_transaction_data(blk_hash, tx, tx_hash); std::vector amount_output_indices; - std::vector global_output_indices; // iterate tx.vout using indices instead of C++11 foreach syntax because // we need the index for (uint64_t i = 0; i < tx.vout.size(); ++i) { - uint64_t amount_output_index, global_output_index; - add_output(tx_hash, tx.vout[i], i, tx.unlock_time, amount_output_index, global_output_index); - amount_output_indices.push_back(amount_output_index); - global_output_indices.push_back(global_output_index); + amount_output_indices.push_back(add_output(tx_hash, tx.vout[i], i, tx.unlock_time)); } - add_amount_and_global_output_indices(tx_index, amount_output_indices, global_output_indices); + add_tx_amount_output_indices(tx_id, amount_output_indices); } uint64_t BlockchainDB::add_block( const block& blk diff --git a/src/blockchain_db/blockchain_db.h b/src/blockchain_db/blockchain_db.h index 665cccd40..99b520d8b 100644 --- a/src/blockchain_db/blockchain_db.h +++ b/src/blockchain_db/blockchain_db.h @@ -63,6 +63,26 @@ * of this interface call to private members of the interface to be added * later that will then populate as needed. * + * Indices and Identifiers: + * The word "index" is used ambiguously throughout this code. It is + * particularly confusing when talking about the output or transaction + * tables since their indexing can refer to themselves or each other. + * I have attempted to clarify these usages here: + * + * Blocks, transactions, and outputs are all identified by a hash. + * For storage efficiency, a 64-bit integer ID is used instead of the hash + * inside the DB. Tables exist to map between hash and ID. A block ID is + * also referred to as its "height". Transactions and outputs generally are + * not referred to by ID outside of this module, but the tx ID is returned + * by tx_exists() and used by get_tx_amount_output_indices(). Like their + * corresponding hashes, IDs are globally unique. + * + * The remaining uses of the word "index" refer to local offsets, and are + * not globally unique. An "amount output index" N refers to the Nth output + * of a specific amount. An "output local index" N refers to the Nth output + * of a specific tx. + * + * * General: * open() * is_open() @@ -99,7 +119,7 @@ * void pop_block(block&, tx_list&) * * Transactions: - * bool tx_exists(hash) + * bool tx_exists(hash, tx_id) * uint64_t get_tx_unlock_time(hash) * tx get_tx(hash) * uint64_t get_tx_count() @@ -111,7 +131,7 @@ * pub_key get_output_key(amount, index) * hash,index get_output_tx_and_index_from_global(index) * hash,index get_output_tx_and_index(amount, index) - * vec get_tx_output_indices(tx_hash) + * vec get_tx_amount_output_indices(tx_id) * * * Spent Output Key Images: @@ -151,9 +171,9 @@ struct output_data_t #pragma pack(push, 1) struct tx_data_t { - uint64_t tx_index; + uint64_t tx_id; uint64_t unlock_time; - uint64_t height; + uint64_t block_id; }; #pragma pack(pop) @@ -299,25 +319,22 @@ private: // tells the subclass to remove data about the top block virtual void remove_block() = 0; - // tells the subclass to store the transaction and its metadata + // tells the subclass to store the transaction and its metadata, returns tx ID virtual uint64_t add_transaction_data(const crypto::hash& blk_hash, const transaction& tx, const crypto::hash& tx_hash) = 0; // tells the subclass to remove data about a transaction virtual void remove_transaction_data(const crypto::hash& tx_hash, const transaction& tx) = 0; - // tells the subclass to store an output - virtual void add_output(const crypto::hash& tx_hash, + // tells the subclass to store an output, returns amount output index + virtual uint64_t add_output(const crypto::hash& tx_hash, const tx_out& tx_output, const uint64_t& local_index, - const uint64_t unlock_time, - uint64_t& amount_output_index, - uint64_t& global_output_index + const uint64_t unlock_time ) = 0; - // tells the subclass to store indices for a tx's outputs, both amount output indices and global output indices - virtual void add_amount_and_global_output_indices(const uint64_t tx_index, - const std::vector& amount_output_indices, - const std::vector& global_output_indices + // tells the subclass to store amount output indices for a tx's outputs + virtual void add_tx_amount_output_indices(const uint64_t tx_id, + const std::vector& amount_output_indices ) = 0; // tells the subclass to remove an output @@ -482,7 +499,7 @@ public: // return true if a transaction with hash exists virtual bool tx_exists(const crypto::hash& h) const = 0; - virtual bool tx_exists(const crypto::hash& h, uint64_t& tx_index) const = 0; + virtual bool tx_exists(const crypto::hash& h, uint64_t& tx_id) const = 0; // return unlock time of tx with hash virtual uint64_t get_tx_unlock_time(const crypto::hash& h) const = 0; @@ -523,16 +540,9 @@ public: virtual bool can_thread_bulk_indices() const = 0; - // return two vectors of indices: vector of amount output indices and global - // output indices, corresponding to each output in the transaction with hash - // - virtual void get_amount_and_global_output_indices(const uint64_t tx_index, - std::vector& amount_output_indices, - std::vector& global_output_indices) const = 0; - // return a vector of indices corresponding to the amount output index for - // each output in the transaction with hash - virtual std::vector get_tx_amount_output_indices(const uint64_t tx_index) const = 0; + // each output in the transaction with ID + virtual std::vector get_tx_amount_output_indices(const uint64_t tx_id) const = 0; // returns true if key image is present in spent key images storage virtual bool has_key_image(const crypto::key_image& img) const = 0; diff --git a/src/blockchain_db/lmdb/db_lmdb.cpp b/src/blockchain_db/lmdb/db_lmdb.cpp index b9e07427b..a9645a95e 100644 --- a/src/blockchain_db/lmdb/db_lmdb.cpp +++ b/src/blockchain_db/lmdb/db_lmdb.cpp @@ -145,9 +145,34 @@ int compare_string(const MDB_val *a, const MDB_val *b) return strcmp(va, vb); } +/* DB schema: + * + * Table Key Data + * ----- --- ---- + * blocks block ID block blob + * block_heights block hash block height + * block_info block ID {block metadata} + * + * txs txn ID txn blob + * tx_indices txn hash {txn ID, metadata} + * tx_outputs txn ID [txn amount output indices] + * + * output_txs output ID {txn hash, local index} + * output_amounts amount [{amount output index, metadata}...] + * + * spent_keys output hash - + * + * Note: where the data items are of uniform size, DUPFIXED tables have + * been used to save space. In most of these cases, a dummy "zerokval" + * key is used when accessing the table; the Key listed above will be + * attached as a prefix on the Data to serve as the DUPSORT key. + * (DUPFIXED saves 8 bytes per record.) + * + * The output_amounts table doesn't use a dummy key, but uses DUPSORT. + */ const char* const LMDB_BLOCKS = "blocks"; -const char* const LMDB_BLOCK_INFO = "block_info"; const char* const LMDB_BLOCK_HEIGHTS = "block_heights"; +const char* const LMDB_BLOCK_INFO = "block_info"; const char* const LMDB_TXS = "txs"; const char* const LMDB_TX_INDICES = "tx_indices"; @@ -215,8 +240,8 @@ typedef struct mdb_block_info } mdb_block_info; typedef struct blk_height { - crypto::hash key; - uint64_t height; + crypto::hash bh_hash; + uint64_t bh_height; } blk_height; typedef struct txindex { @@ -226,12 +251,12 @@ typedef struct txindex { typedef struct outkey { uint64_t amount_index; - uint64_t tx_index; + uint64_t output_id; output_data_t data; } outkey; typedef struct outtx { - uint64_t txnum; + uint64_t output_id; crypto::hash tx_hash; uint64_t local_index; } outtx; @@ -560,14 +585,13 @@ void BlockchainLMDB::add_block(const block& blk, const size_t& block_size, const CURSOR(block_heights) blk_height bh = {blk_hash, m_height}; - MDB_val val_h = {sizeof(bh), (void *)&bh}; + MDB_val_set(val_h, bh); if (mdb_cursor_get(m_cur_block_heights, (MDB_val *)&zerokval, &val_h, MDB_GET_BOTH) == 0) throw1(BLOCK_EXISTS("Attempting to add block that's already in the db")); if (m_height > 0) { - blk_height ph = {blk.prev_id, 0}; - MDB_val parent_key = {sizeof(ph), (void *)&ph}; + MDB_val_set(parent_key, blk.prev_id); int result = mdb_cursor_get(m_cur_block_heights, (MDB_val *)&zerokval, &parent_key, MDB_GET_BOTH); if (result) { @@ -576,13 +600,13 @@ void BlockchainLMDB::add_block(const block& blk, const size_t& block_size, const throw0(DB_ERROR(lmdb_error("Failed to get top block hash to check for new block's parent: ", result).c_str())); } blk_height *prev = (blk_height *)parent_key.mv_data; - if (prev->height != m_height - 1) + if (prev->bh_height != m_height - 1) throw0(BLOCK_PARENT_DNE("Top block is not new block's parent")); } int result = 0; - MDB_val_copy key(m_height); + MDB_val_set(key, m_height); CURSOR(blocks) CURSOR(block_info) @@ -600,7 +624,7 @@ void BlockchainLMDB::add_block(const block& blk, const size_t& block_size, const bi.bi_diff = cumulative_difficulty; bi.bi_hash = blk_hash; - MDB_val val = {sizeof(bi), (void *)&bi}; + MDB_val_set(val, bi); result = mdb_cursor_put(m_cur_block_info, (MDB_val *)&zerokval, &val, MDB_APPENDDUP); if (result) throw0(DB_ERROR(lmdb_error("Failed to add block info to db transaction: ", result).c_str())); @@ -657,26 +681,27 @@ uint64_t BlockchainLMDB::add_transaction_data(const crypto::hash& blk_hash, cons check_open(); mdb_txn_cursors *m_cursors = &m_wcursors; - int result = 0; - uint64_t tx_index = m_num_txs; + int result; + uint64_t tx_id = m_num_txs; CURSOR(txs) CURSOR(tx_indices) - txindex ti = {tx_hash}; - MDB_val_copy val_tx_index(tx_index); - MDB_val val_h = {sizeof(ti), (void *)&ti}; + MDB_val_set(val_tx_id, tx_id); + MDB_val_set(val_h, tx_hash); result = mdb_cursor_get(m_cur_tx_indices, (MDB_val *)&zerokval, &val_h, MDB_GET_BOTH); if (result == 0) { txindex *tip = (txindex *)val_h.mv_data; - throw1(TX_EXISTS(std::string("Attempting to add transaction that's already in the db (tx index ").append(boost::lexical_cast(tip->data.tx_index)).append(")").c_str())); + throw1(TX_EXISTS(std::string("Attempting to add transaction that's already in the db (tx id ").append(boost::lexical_cast(tip->data.tx_id)).append(")").c_str())); } else if (result != MDB_NOTFOUND) { throw1(DB_ERROR(lmdb_error(std::string("Error checking if tx index exists for tx hash ") + epee::string_tools::pod_to_hex(tx_hash) + ": ", result).c_str())); } - ti.data.tx_index = tx_index; + txindex ti; + ti.key = tx_hash; + ti.data.tx_id = tx_id; ti.data.unlock_time = tx.unlock_time; - ti.data.height = m_height; + ti.data.block_id = m_height; // we don't need blk_hash since we know m_height val_h.mv_size = sizeof(ti); val_h.mv_data = (void *)&ti; @@ -686,12 +711,12 @@ uint64_t BlockchainLMDB::add_transaction_data(const crypto::hash& blk_hash, cons throw0(DB_ERROR(lmdb_error("Failed to add tx data to db transaction: ", result).c_str())); MDB_val_copy blob(tx_to_blob(tx)); - result = mdb_cursor_put(m_cur_txs, &val_tx_index, &blob, MDB_APPEND); + result = mdb_cursor_put(m_cur_txs, &val_tx_id, &blob, MDB_APPEND); if (result) throw0(DB_ERROR(lmdb_error("Failed to add tx blob to db transaction: ", result).c_str())); m_num_txs++; - return tx_index; + return tx_id; } // TODO: compare pros and cons of looking up the tx hash's tx index once and @@ -708,24 +733,22 @@ void BlockchainLMDB::remove_transaction_data(const crypto::hash& tx_hash, const CURSOR(txs) CURSOR(tx_outputs) - txindex ti = {tx_hash}; - MDB_val val_h = {sizeof(ti), (void *)&ti}; + MDB_val_set(val_h, tx_hash); if (mdb_cursor_get(m_cur_tx_indices, (MDB_val *)&zerokval, &val_h, MDB_GET_BOTH)) throw1(TX_DNE("Attempting to remove transaction that isn't in the db")); txindex *tip = (txindex *)val_h.mv_data; - uint64_t tx_index = tip->data.tx_index; - MDB_val_copy val_tx_index(tx_index); + MDB_val_set(val_tx_id, tip->data.tx_id); - if ((result = mdb_cursor_get(m_cur_txs, &val_tx_index, NULL, MDB_SET))) + if ((result = mdb_cursor_get(m_cur_txs, &val_tx_id, NULL, MDB_SET))) throw1(DB_ERROR(lmdb_error("Failed to locate tx for removal: ", result).c_str())); result = mdb_cursor_del(m_cur_txs, 0); if (result) throw1(DB_ERROR(lmdb_error("Failed to add removal of tx to db transaction: ", result).c_str())); - remove_tx_outputs(tx_index, tx); + remove_tx_outputs(tip->data.tx_id, tx); - result = mdb_cursor_get(m_cur_tx_outputs, &val_tx_index, NULL, MDB_SET); + result = mdb_cursor_get(m_cur_tx_outputs, &val_tx_id, NULL, MDB_SET); if (result == MDB_NOTFOUND) LOG_PRINT_L1("tx has no outputs to remove: " << tx_hash); else if (result) @@ -737,24 +760,17 @@ void BlockchainLMDB::remove_transaction_data(const crypto::hash& tx_hash, const throw1(DB_ERROR(lmdb_error("Failed to add removal of tx outputs to db transaction: ", result).c_str())); } - // Though other things could change, so long as earlier functions (like - // remove_tx_outputs) need to do the lookup of tx hash -> tx index, don't - // delete the tx_indices entry until the end. - if (mdb_cursor_get(m_cur_tx_indices, (MDB_val *)&zerokval, &val_h, MDB_GET_BOTH)) - throw1(TX_DNE("Attempting to remove transaction that isn't in the db")); + // Don't delete the tx_indices entry until the end, after we're done with val_tx_id if (mdb_cursor_del(m_cur_tx_indices, 0)) throw1(DB_ERROR("Failed to add removal of tx index to db transaction")); m_num_txs--; } -// global_output_index is no longer used for locating outputs -void BlockchainLMDB::add_output(const crypto::hash& tx_hash, +uint64_t BlockchainLMDB::add_output(const crypto::hash& tx_hash, const tx_out& tx_output, const uint64_t& local_index, - const uint64_t unlock_time, - uint64_t& amount_output_index, - uint64_t& global_output_index) + const uint64_t unlock_time) { LOG_PRINT_L3("BlockchainLMDB::" << __func__); check_open(); @@ -791,7 +807,7 @@ void BlockchainLMDB::add_output(const crypto::hash& tx_hash, throw0(DB_ERROR(lmdb_error("Failed to get output amount in db transaction: ", result).c_str())); else ok.amount_index = 0; - ok.tx_index = m_num_outputs; + ok.output_id = m_num_outputs; ok.data.pubkey = boost::get < txout_to_key > (tx_output.target).key; ok.data.unlock_time = unlock_time; ok.data.height = m_height; @@ -801,16 +817,12 @@ void BlockchainLMDB::add_output(const crypto::hash& tx_hash, if ((result = mdb_cursor_put(m_cur_output_amounts, &val_amount, &data, MDB_APPENDDUP))) throw0(DB_ERROR(lmdb_error("Failed to add output pubkey to db transaction: ", result).c_str())); - amount_output_index = ok.amount_index; - global_output_index = m_num_outputs; - m_num_outputs++; + return ok.amount_index; } -// global_output_indices is now ignored -void BlockchainLMDB::add_amount_and_global_output_indices(const uint64_t tx_index, - const std::vector& amount_output_indices, - const std::vector& global_output_indices) +void BlockchainLMDB::add_tx_amount_output_indices(const uint64_t tx_id, + const std::vector& amount_output_indices) { LOG_PRINT_L3("BlockchainLMDB::" << __func__); check_open(); @@ -821,24 +833,22 @@ void BlockchainLMDB::add_amount_and_global_output_indices(const uint64_t tx_inde int num_outputs = amount_output_indices.size(); - MDB_val_copy k_tx_index(tx_index); + MDB_val_set(k_tx_id, tx_id); MDB_val v; v.mv_data = (void *)amount_output_indices.data(); v.mv_size = sizeof(uint64_t) * num_outputs; // LOG_PRINT_L1("tx_outputs[tx_hash] size: " << v.mv_size); - result = mdb_cursor_put(m_cur_tx_outputs, &k_tx_index, &v, MDB_APPEND); + result = mdb_cursor_put(m_cur_tx_outputs, &k_tx_id, &v, MDB_APPEND); if (result) throw0(DB_ERROR(std::string("Failed to add to db transaction: ").append(mdb_strerror(result)).c_str())); } -void BlockchainLMDB::remove_tx_outputs(const uint64_t tx_index, const transaction& tx) +void BlockchainLMDB::remove_tx_outputs(const uint64_t tx_id, const transaction& tx) { LOG_PRINT_L3("BlockchainLMDB::" << __func__); - // only need amount_output_indices - std::vector amount_output_indices, global_output_indices; - get_amount_and_global_output_indices(tx_index, amount_output_indices, global_output_indices); + std::vector amount_output_indices = get_tx_amount_output_indices(tx_id); if (amount_output_indices.empty()) { @@ -880,7 +890,7 @@ void BlockchainLMDB::remove_output(const uint64_t& out_index, const uint64_t amo throw0(DB_ERROR(lmdb_error("DB error attempting to get an output", result).c_str())); outkey *ok = (outkey *)v.mv_data; - MDB_val_set(otxk, ok->tx_index); + MDB_val_set(otxk, ok->output_id); result = mdb_cursor_get(m_cur_output_txs, (MDB_val *)&zerokval, &otxk, MDB_GET_BOTH); if (result == MDB_NOTFOUND) { @@ -1333,8 +1343,7 @@ bool BlockchainLMDB::block_exists(const crypto::hash& h) const RCURSOR(block_heights); bool ret = false; - blk_height bh = {h, 0}; - MDB_val key = {sizeof(bh), (void *)&bh}; + MDB_val_set(key, h); auto get_result = mdb_cursor_get(m_cur_block_heights, (MDB_val *)&zerokval, &key, MDB_GET_BOTH); if (get_result == MDB_NOTFOUND) { @@ -1365,8 +1374,7 @@ uint64_t BlockchainLMDB::get_block_height(const crypto::hash& h) const TXN_PREFIX_RDONLY(); RCURSOR(block_heights); - blk_height bh = {h, 0}; - MDB_val key = {sizeof(bh), (void *)&bh}; + MDB_val_set(key, h); auto get_result = mdb_cursor_get(m_cur_block_heights, (MDB_val *)&zerokval, &key, MDB_GET_BOTH); if (get_result == MDB_NOTFOUND) throw1(BLOCK_DNE("Attempted to retrieve non-existent block height")); @@ -1374,7 +1382,7 @@ uint64_t BlockchainLMDB::get_block_height(const crypto::hash& h) const throw0(DB_ERROR("Error attempting to retrieve a block height from the db")); blk_height *bhp = (blk_height *)key.mv_data; - uint64_t ret = bhp->height; + uint64_t ret = bhp->bh_height; TXN_POSTFIX_RDONLY(); return ret; } @@ -1635,7 +1643,7 @@ bool BlockchainLMDB::tx_exists(const crypto::hash& h) const RCURSOR(tx_indices); RCURSOR(txs); - MDB_val_copy key(h); + MDB_val_set(key, h); bool tx_found = false; TIME_MEASURE_START(time1); @@ -1666,7 +1674,7 @@ bool BlockchainLMDB::tx_exists(const crypto::hash& h) const return true; } -bool BlockchainLMDB::tx_exists(const crypto::hash& h, uint64_t& tx_index) const +bool BlockchainLMDB::tx_exists(const crypto::hash& h, uint64_t& tx_id) const { LOG_PRINT_L3("BlockchainLMDB::" << __func__); check_open(); @@ -1674,8 +1682,7 @@ bool BlockchainLMDB::tx_exists(const crypto::hash& h, uint64_t& tx_index) const TXN_PREFIX_RDONLY(); RCURSOR(tx_indices); - txindex ti = {h}; - MDB_val v = {sizeof(ti), (void *)&ti}; + MDB_val_set(v, h); TIME_MEASURE_START(time1); auto get_result = mdb_cursor_get(m_cur_tx_indices, (MDB_val *)&zerokval, &v, MDB_GET_BOTH); @@ -1683,7 +1690,7 @@ bool BlockchainLMDB::tx_exists(const crypto::hash& h, uint64_t& tx_index) const time_tx_exists += time1; if (!get_result) { txindex *tip = (txindex *)v.mv_data; - tx_index = tip->data.tx_index; + tx_id = tip->data.tx_id; } TXN_POSTFIX_RDONLY(); @@ -1709,8 +1716,7 @@ uint64_t BlockchainLMDB::get_tx_unlock_time(const crypto::hash& h) const TXN_PREFIX_RDONLY(); RCURSOR(tx_indices); - txindex ti = {h}; - MDB_val v = {sizeof(ti), (void *)&ti}; + MDB_val_set(v, h); auto get_result = mdb_cursor_get(m_cur_tx_indices, (MDB_val *)&zerokval, &v, MDB_GET_BOTH); if (get_result == MDB_NOTFOUND) throw1(TX_DNE(lmdb_error(std::string("tx data with hash ") + epee::string_tools::pod_to_hex(h) + " not found in db: ", get_result).c_str())); @@ -1732,16 +1738,14 @@ transaction BlockchainLMDB::get_tx(const crypto::hash& h) const RCURSOR(tx_indices); RCURSOR(txs); - txindex ti = {h}; - MDB_val v = {sizeof(ti), (void *)&ti}; + MDB_val_set(v, h); MDB_val result; auto get_result = mdb_cursor_get(m_cur_tx_indices, (MDB_val *)&zerokval, &v, MDB_GET_BOTH); if (get_result == 0) { txindex *tip = (txindex *)v.mv_data; - uint64_t tx_index = tip->data.tx_index; - MDB_val_copy val_tx_index(tx_index); - get_result = mdb_cursor_get(m_cur_txs, &val_tx_index, &result, MDB_SET); + MDB_val_set(val_tx_id, tip->data.tx_id); + get_result = mdb_cursor_get(m_cur_txs, &val_tx_id, &result, MDB_SET); } if (get_result == MDB_NOTFOUND) throw1(TX_DNE(std::string("tx with hash ").append(epee::string_tools::pod_to_hex(h)).append(" not found in db").c_str())); @@ -1798,8 +1802,7 @@ uint64_t BlockchainLMDB::get_tx_block_height(const crypto::hash& h) const TXN_PREFIX_RDONLY(); RCURSOR(tx_indices); - txindex ti = {h}; - MDB_val v = {sizeof(ti), (void *)&ti}; + MDB_val_set(v, h); auto get_result = mdb_cursor_get(m_cur_tx_indices, (MDB_val *)&zerokval, &v, MDB_GET_BOTH); if (get_result == MDB_NOTFOUND) { @@ -1809,7 +1812,7 @@ uint64_t BlockchainLMDB::get_tx_block_height(const crypto::hash& h) const throw0(DB_ERROR(lmdb_error("DB error attempting to fetch tx height from hash", get_result).c_str())); txindex *tip = (txindex *)v.mv_data; - uint64_t ret = tip->data.height; + uint64_t ret = tip->data.block_id; TXN_POSTFIX_RDONLY(); return ret; } @@ -1867,7 +1870,7 @@ output_data_t BlockchainLMDB::get_output_key(const uint64_t& amount, const uint6 return ret; } -tx_out_index BlockchainLMDB::get_output_tx_and_index_from_global(const uint64_t& index) const +tx_out_index BlockchainLMDB::get_output_tx_and_index_from_global(const uint64_t& output_id) const { LOG_PRINT_L3("BlockchainLMDB::" << __func__); check_open(); @@ -1875,7 +1878,7 @@ tx_out_index BlockchainLMDB::get_output_tx_and_index_from_global(const uint64_t& TXN_PREFIX_RDONLY(); RCURSOR(output_txs); - MDB_val_set(v, index); + MDB_val_set(v, output_id); auto get_result = mdb_cursor_get(m_cur_output_txs, (MDB_val *)&zerokval, &v, MDB_GET_BOTH); if (get_result == MDB_NOTFOUND) @@ -1903,29 +1906,21 @@ tx_out_index BlockchainLMDB::get_output_tx_and_index(const uint64_t& amount, con return indices[0]; } -// we don't have global_output_indices -void BlockchainLMDB::get_amount_and_global_output_indices(const uint64_t tx_index, - std::vector& amount_output_indices, - std::vector& global_output_indices) const +std::vector BlockchainLMDB::get_tx_amount_output_indices(const uint64_t tx_id) const { LOG_PRINT_L3("BlockchainLMDB::" << __func__); check_open(); - // If a new txn is created, it only needs to read. - // - // This must existence of m_write_txn too (not only m_batch_active), as - // that's what remove_tx_outputs() expected to use instead of creating a new - // txn, regardless of batch mode. Otherwise, remove_tx_outputs() would now - // create a new read-only txn here, which is incorrect. TXN_PREFIX_RDONLY(); RCURSOR(tx_outputs); int result = 0; - MDB_val_copy k_tx_index(tx_index); + MDB_val_set(k_tx_id, tx_id); MDB_val v; + std::vector amount_output_indices; - result = mdb_cursor_get(m_cur_tx_outputs, &k_tx_index, &v, MDB_SET); + result = mdb_cursor_get(m_cur_tx_outputs, &k_tx_id, &v, MDB_SET); if (result == MDB_NOTFOUND) LOG_PRINT_L0("WARNING: Unexpected: tx has no amount indices stored in " "tx_outputs, but it should have an empty entry even if it's a tx without " @@ -1944,21 +1939,10 @@ void BlockchainLMDB::get_amount_and_global_output_indices(const uint64_t tx_inde indices = nullptr; TXN_POSTFIX_RDONLY(); -} - -std::vector BlockchainLMDB::get_tx_amount_output_indices(const uint64_t tx_index) const -{ - LOG_PRINT_L3("BlockchainLMDB::" << __func__); - - std::vector amount_output_indices, global_output_indices; - // only need amount_output_indices - get_amount_and_global_output_indices(tx_index, amount_output_indices, global_output_indices); - return amount_output_indices; } - bool BlockchainLMDB::has_key_image(const crypto::key_image& img) const { LOG_PRINT_L3("BlockchainLMDB::" << __func__); @@ -2110,7 +2094,7 @@ bool BlockchainLMDB::for_all_outputs(std::functiontx_index); + tx_out_index toi = get_output_tx_and_index_from_global(ok->output_id); if (!f(amount, toi.first, toi.second)) { ret = false; break; @@ -2453,9 +2437,9 @@ void BlockchainLMDB::get_output_tx_and_index_from_global(const std::vectortx_index); + tx_indices.push_back(okp->output_id); } TIME_MEASURE_START(db3); diff --git a/src/blockchain_db/lmdb/db_lmdb.h b/src/blockchain_db/lmdb/db_lmdb.h index 2ac8b94d8..534f5575f 100644 --- a/src/blockchain_db/lmdb/db_lmdb.h +++ b/src/blockchain_db/lmdb/db_lmdb.h @@ -227,11 +227,7 @@ public: virtual tx_out_index get_output_tx_and_index(const uint64_t& amount, const uint64_t& index); virtual void get_output_tx_and_index(const uint64_t& amount, const std::vector &offsets, std::vector &indices); - virtual void get_amount_and_global_output_indices(const uint64_t tx_index, - std::vector& amount_output_indices, - std::vector& global_output_indices) const; - - virtual std::vector get_tx_amount_output_indices(const uint64_t tx_index) const; + virtual std::vector get_tx_amount_output_indices(const uint64_t tx_id) const; virtual bool has_key_image(const crypto::key_image& img) const; @@ -282,22 +278,19 @@ private: virtual void remove_transaction_data(const crypto::hash& tx_hash, const transaction& tx); - virtual void add_output(const crypto::hash& tx_hash, + virtual uint64_t add_output(const crypto::hash& tx_hash, const tx_out& tx_output, const uint64_t& local_index, - const uint64_t unlock_time, - uint64_t& amount_output_index, - uint64_t& global_output_index + const uint64_t unlock_time ); - virtual void add_amount_and_global_output_indices(const uint64_t tx_index, - const std::vector& amount_output_indices, - const std::vector& global_output_indices + virtual void add_tx_amount_output_indices(const uint64_t tx_id, + const std::vector& amount_output_indices ); virtual void remove_output(const tx_out& tx_output); - void remove_tx_outputs(const uint64_t tx_index, const transaction& tx); + void remove_tx_outputs(const uint64_t tx_id, const transaction& tx); void remove_output(const uint64_t& out_index, const uint64_t amount);