From 3465c4ebc7d38b9825e2bc95a9279de7f03e7594 Mon Sep 17 00:00:00 2001 From: moneromooo-monero Date: Thu, 1 Dec 2016 14:26:18 +0000 Subject: [PATCH 1/4] db_lmdb: set same packing format for output_data_t and pre_rct_output_data_t For safety, though it seems to have been the case already. Also add a comment about the necessary layout identity. --- src/blockchain_db/lmdb/db_lmdb.cpp | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/blockchain_db/lmdb/db_lmdb.cpp b/src/blockchain_db/lmdb/db_lmdb.cpp index b5459b56b..2281c1da0 100644 --- a/src/blockchain_db/lmdb/db_lmdb.cpp +++ b/src/blockchain_db/lmdb/db_lmdb.cpp @@ -51,12 +51,15 @@ using epee::string_tools::pod_to_hex; namespace { +#pragma pack(push, 1) +// This MUST be identical to output_data_t, without the extra rct data at the end struct pre_rct_output_data_t { crypto::public_key pubkey; //!< the output's public key (for spend verification) uint64_t unlock_time; //!< the output's unlock time (or height) uint64_t height; //!< the height of the block which created the output }; +#pragma pack(pop) template inline void throw0(const T &e) From bef51e677e4338291b03eb32a34731c445678be0 Mon Sep 17 00:00:00 2001 From: moneromooo-monero Date: Thu, 1 Dec 2016 14:28:09 +0000 Subject: [PATCH 2/4] db_lmdb: minor pedantic tweaks Add consts in a few places where it makes sense, avoid unnecessary memory reallocation where we know the full size needed at the outset, simplify and avoid memory copy. --- src/blockchain_db/lmdb/db_lmdb.cpp | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/src/blockchain_db/lmdb/db_lmdb.cpp b/src/blockchain_db/lmdb/db_lmdb.cpp index 2281c1da0..ea33dc6c9 100644 --- a/src/blockchain_db/lmdb/db_lmdb.cpp +++ b/src/blockchain_db/lmdb/db_lmdb.cpp @@ -880,12 +880,11 @@ void BlockchainLMDB::remove_tx_outputs(const uint64_t tx_id, const transaction& throw0(DB_ERROR("tx has outputs, but no output indices found")); } - bool is_miner_tx = tx.vin.size() == 1 && tx.vin[0].type() == typeid(txin_gen); - for (uint64_t i = tx.vout.size(); i > 0; --i) + bool is_pseudo_rct = tx.version >= 2 && tx.vin.size() == 1 && tx.vin[0].type() == typeid(txin_gen); + for (size_t i = tx.vout.size(); i-- > 0;) { - const tx_out tx_output = tx.vout[i-1]; - uint64_t amount = is_miner_tx && tx.version >= 2 ? 0 : tx_output.amount; - remove_output(amount, amount_output_indices[i-1]); + uint64_t amount = is_pseudo_rct ? 0 : tx.vout[i].amount; + remove_output(amount, amount_output_indices[i]); } } @@ -906,7 +905,7 @@ void BlockchainLMDB::remove_output(const uint64_t amount, const uint64_t& out_in else if (result) throw0(DB_ERROR(lmdb_error("DB error attempting to get an output", result).c_str())); - outkey *ok = (outkey *)v.mv_data; + const pre_rct_outkey *ok = (const pre_rct_outkey *)v.mv_data; 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) @@ -2044,9 +2043,10 @@ std::vector BlockchainLMDB::get_tx_amount_output_indices(const uint64_ else if (result) throw0(DB_ERROR(lmdb_error("DB error attempting to get data for tx_outputs[tx_index]", result).c_str())); - uint64_t* indices = (uint64_t*)v.mv_data; + const uint64_t* indices = (const uint64_t*)v.mv_data; int num_outputs = v.mv_size / sizeof(uint64_t); + amount_output_indices.reserve(num_outputs); for (int i = 0; i < num_outputs; ++i) { // LOG_PRINT_L0("amount output index[" << 2*i << "]" << ": " << paired_indices[2*i] << " global output index: " << paired_indices[2*i+1]); @@ -2647,7 +2647,7 @@ void BlockchainLMDB::get_output_tx_and_index(const uint64_t& amount, const std:: else if (get_result) throw0(DB_ERROR(lmdb_error("Error attempting to retrieve an output from the db", get_result).c_str())); - outkey *okp = (outkey *)v.mv_data; + const outkey *okp = (const outkey *)v.mv_data; tx_indices.push_back(okp->output_id); } From c96f9b0255dc8b62055a693a24bfdc8e1b6e1b90 Mon Sep 17 00:00:00 2001 From: moneromooo-monero Date: Thu, 1 Dec 2016 14:29:35 +0000 Subject: [PATCH 3/4] db_lmdb: guard against going out of sync on unexpected db results m_num_outputs keeps track of the number of outputs, which should be the same as the size of both the output_txs and output_amounts databases. If one goes out of sync, we need to throw to abort whatever it is we were doing. --- src/blockchain_db/lmdb/db_lmdb.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/blockchain_db/lmdb/db_lmdb.cpp b/src/blockchain_db/lmdb/db_lmdb.cpp index ea33dc6c9..91a576b4e 100644 --- a/src/blockchain_db/lmdb/db_lmdb.cpp +++ b/src/blockchain_db/lmdb/db_lmdb.cpp @@ -910,7 +910,7 @@ void BlockchainLMDB::remove_output(const uint64_t amount, const uint64_t& out_in result = mdb_cursor_get(m_cur_output_txs, (MDB_val *)&zerokval, &otxk, MDB_GET_BOTH); if (result == MDB_NOTFOUND) { - LOG_PRINT_L0("Unexpected: global output index not found in m_output_txs"); + throw0(DB_ERROR("Unexpected: global output index not found in m_output_txs")); } else if (result) { From 0e18f4652200bbfd1173ad44f9766b9740a75524 Mon Sep 17 00:00:00 2001 From: moneromooo-monero Date: Thu, 1 Dec 2016 14:31:40 +0000 Subject: [PATCH 4/4] db_lmdb: add info in an error message when we can't get an output Will be useful to debug --- src/blockchain_db/lmdb/db_lmdb.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/blockchain_db/lmdb/db_lmdb.cpp b/src/blockchain_db/lmdb/db_lmdb.cpp index 91a576b4e..1ad9876ac 100644 --- a/src/blockchain_db/lmdb/db_lmdb.cpp +++ b/src/blockchain_db/lmdb/db_lmdb.cpp @@ -2600,7 +2600,7 @@ void BlockchainLMDB::get_output_key(const uint64_t &amount, const std::vector(amount) + ", index " + boost::lexical_cast(index) + ", count " + boost::lexical_cast(get_num_outputs(amount)) + "), but key does not exist").c_str())); else if (get_result) throw0(DB_ERROR(lmdb_error("Error attempting to retrieve an output pubkey from the db", get_result).c_str()));