Schema update: tx_indices - improve further with less indirection
This commit is contained in:
parent
7c013f66e9
commit
8d12a8df2c
|
@ -473,6 +473,7 @@ public:
|
||||||
|
|
||||||
// return true if a transaction with hash <h> exists
|
// return true if a transaction with hash <h> exists
|
||||||
virtual bool tx_exists(const crypto::hash& h) const = 0;
|
virtual bool tx_exists(const crypto::hash& h) const = 0;
|
||||||
|
virtual bool tx_exists(const crypto::hash& h, uint64_t& tx_index) const = 0;
|
||||||
|
|
||||||
// return unlock time of tx with hash <h>
|
// return unlock time of tx with hash <h>
|
||||||
virtual uint64_t get_tx_unlock_time(const crypto::hash& h) const = 0;
|
virtual uint64_t get_tx_unlock_time(const crypto::hash& h) const = 0;
|
||||||
|
@ -516,13 +517,13 @@ public:
|
||||||
// return two vectors of indices: vector of amount output indices and global
|
// return two vectors of indices: vector of amount output indices and global
|
||||||
// output indices, corresponding to each output in the transaction with hash
|
// output indices, corresponding to each output in the transaction with hash
|
||||||
// <h>
|
// <h>
|
||||||
virtual void get_amount_and_global_output_indices(const crypto::hash& h,
|
virtual void get_amount_and_global_output_indices(const uint64_t tx_index,
|
||||||
std::vector<uint64_t>& amount_output_indices,
|
std::vector<uint64_t>& amount_output_indices,
|
||||||
std::vector<uint64_t>& global_output_indices) const = 0;
|
std::vector<uint64_t>& global_output_indices) const = 0;
|
||||||
|
|
||||||
// return a vector of indices corresponding to the amount output index for
|
// return a vector of indices corresponding to the amount output index for
|
||||||
// each output in the transaction with hash <h>
|
// each output in the transaction with hash <h>
|
||||||
virtual std::vector<uint64_t> get_tx_amount_output_indices(const crypto::hash& h) const = 0;
|
virtual std::vector<uint64_t> get_tx_amount_output_indices(const uint64_t tx_index) const = 0;
|
||||||
|
|
||||||
// returns true if key image <img> is present in spent key images storage
|
// returns true if key image <img> is present in spent key images storage
|
||||||
virtual bool has_key_image(const crypto::key_image& img) const = 0;
|
virtual bool has_key_image(const crypto::key_image& img) const = 0;
|
||||||
|
|
|
@ -672,6 +672,7 @@ void BlockchainLMDB::remove_transaction_data(const crypto::hash& tx_hash, const
|
||||||
|
|
||||||
if (mdb_get(*m_write_txn, m_tx_indices, &val_h, &val_tx_index))
|
if (mdb_get(*m_write_txn, m_tx_indices, &val_h, &val_tx_index))
|
||||||
throw1(TX_DNE("Attempting to remove transaction that isn't in the db"));
|
throw1(TX_DNE("Attempting to remove transaction that isn't in the db"));
|
||||||
|
uint64_t tx_index = *(uint64_t*)val_tx_index.mv_data;
|
||||||
|
|
||||||
if (mdb_del(*m_write_txn, m_txs, &val_tx_index, NULL))
|
if (mdb_del(*m_write_txn, m_txs, &val_tx_index, NULL))
|
||||||
throw1(DB_ERROR("Failed to add removal of tx to db transaction"));
|
throw1(DB_ERROR("Failed to add removal of tx to db transaction"));
|
||||||
|
@ -680,7 +681,7 @@ void BlockchainLMDB::remove_transaction_data(const crypto::hash& tx_hash, const
|
||||||
if (mdb_del(*m_write_txn, m_tx_heights, &val_tx_index, NULL))
|
if (mdb_del(*m_write_txn, m_tx_heights, &val_tx_index, NULL))
|
||||||
throw1(DB_ERROR("Failed to add removal of tx block height to db transaction"));
|
throw1(DB_ERROR("Failed to add removal of tx block height to db transaction"));
|
||||||
|
|
||||||
remove_tx_outputs(tx_hash, tx);
|
remove_tx_outputs(tx_index, tx);
|
||||||
|
|
||||||
int result = mdb_del(*m_write_txn, m_tx_outputs, &val_tx_index, NULL);
|
int result = mdb_del(*m_write_txn, m_tx_outputs, &val_tx_index, NULL);
|
||||||
if (result == MDB_NOTFOUND)
|
if (result == MDB_NOTFOUND)
|
||||||
|
@ -796,13 +797,13 @@ void BlockchainLMDB::add_amount_and_global_output_indices(const crypto::hash& tx
|
||||||
throw0(DB_ERROR(std::string("Failed to add <tx hash, amount output index array> to db transaction: ").append(mdb_strerror(result)).c_str()));
|
throw0(DB_ERROR(std::string("Failed to add <tx hash, amount output index array> to db transaction: ").append(mdb_strerror(result)).c_str()));
|
||||||
}
|
}
|
||||||
|
|
||||||
void BlockchainLMDB::remove_tx_outputs(const crypto::hash& tx_hash, const transaction& tx)
|
void BlockchainLMDB::remove_tx_outputs(const uint64_t tx_index, const transaction& tx)
|
||||||
{
|
{
|
||||||
LOG_PRINT_L3("BlockchainLMDB::" << __func__);
|
LOG_PRINT_L3("BlockchainLMDB::" << __func__);
|
||||||
|
|
||||||
// only need global_output_indices
|
// only need global_output_indices
|
||||||
std::vector<uint64_t> amount_output_indices, global_output_indices;
|
std::vector<uint64_t> amount_output_indices, global_output_indices;
|
||||||
get_amount_and_global_output_indices(tx_hash, amount_output_indices, global_output_indices);
|
get_amount_and_global_output_indices(tx_index, amount_output_indices, global_output_indices);
|
||||||
|
|
||||||
if (global_output_indices.empty())
|
if (global_output_indices.empty())
|
||||||
{
|
{
|
||||||
|
@ -1122,6 +1123,7 @@ void BlockchainLMDB::open(const std::string& filename, const int mdb_flags)
|
||||||
mdb_set_compare(txn, m_spent_keys, compare_hash32);
|
mdb_set_compare(txn, m_spent_keys, compare_hash32);
|
||||||
mdb_set_compare(txn, m_block_heights, compare_hash32);
|
mdb_set_compare(txn, m_block_heights, compare_hash32);
|
||||||
mdb_set_compare(txn, m_tx_indices, compare_hash32);
|
mdb_set_compare(txn, m_tx_indices, compare_hash32);
|
||||||
|
|
||||||
mdb_set_compare(txn, m_hf_starting_heights, compare_uint8);
|
mdb_set_compare(txn, m_hf_starting_heights, compare_uint8);
|
||||||
mdb_set_compare(txn, m_hf_versions, compare_uint64);
|
mdb_set_compare(txn, m_hf_versions, compare_uint64);
|
||||||
mdb_set_compare(txn, m_properties, compare_string);
|
mdb_set_compare(txn, m_properties, compare_string);
|
||||||
|
@ -1726,6 +1728,43 @@ bool BlockchainLMDB::tx_exists(const crypto::hash& h) const
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool BlockchainLMDB::tx_exists(const crypto::hash& h, uint64_t& tx_index) const
|
||||||
|
{
|
||||||
|
LOG_PRINT_L3("BlockchainLMDB::" << __func__);
|
||||||
|
check_open();
|
||||||
|
|
||||||
|
TXN_PREFIX_RDONLY();
|
||||||
|
const mdb_txn_cursors *m_cursors = m_write_txn ? &m_wcursors : &m_tinfo->m_ti_rcursors;
|
||||||
|
RCURSOR(tx_indices);
|
||||||
|
RCURSOR(txs);
|
||||||
|
|
||||||
|
MDB_val_copy<crypto::hash> key(h);
|
||||||
|
MDB_val val_tx_index;
|
||||||
|
MDB_val result;
|
||||||
|
|
||||||
|
TIME_MEASURE_START(time1);
|
||||||
|
auto get_result = mdb_cursor_get(m_cur_tx_indices, &key, &val_tx_index, MDB_SET);
|
||||||
|
if (get_result == 0) {
|
||||||
|
get_result = mdb_cursor_get(m_cur_txs, &val_tx_index, &result, MDB_SET);
|
||||||
|
}
|
||||||
|
TIME_MEASURE_FINISH(time1);
|
||||||
|
time_tx_exists += time1;
|
||||||
|
|
||||||
|
TXN_POSTFIX_RDONLY();
|
||||||
|
|
||||||
|
if (get_result == MDB_NOTFOUND)
|
||||||
|
{
|
||||||
|
LOG_PRINT_L1("transaction with hash " << epee::string_tools::pod_to_hex(h) << " not found in db");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
else if (get_result)
|
||||||
|
throw0(DB_ERROR("DB error attempting to fetch transaction from hash"));
|
||||||
|
else
|
||||||
|
tx_index = *(uint64_t*)val_tx_index.mv_data;
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
uint64_t BlockchainLMDB::get_tx_unlock_time(const crypto::hash& h) const
|
uint64_t BlockchainLMDB::get_tx_unlock_time(const crypto::hash& h) const
|
||||||
{
|
{
|
||||||
LOG_PRINT_L3("BlockchainLMDB::" << __func__);
|
LOG_PRINT_L3("BlockchainLMDB::" << __func__);
|
||||||
|
@ -1950,7 +1989,7 @@ tx_out_index BlockchainLMDB::get_output_tx_and_index(const uint64_t& amount, con
|
||||||
return indices[0];
|
return indices[0];
|
||||||
}
|
}
|
||||||
|
|
||||||
void BlockchainLMDB::get_amount_and_global_output_indices(const crypto::hash& h,
|
void BlockchainLMDB::get_amount_and_global_output_indices(const uint64_t tx_index,
|
||||||
std::vector<uint64_t>& amount_output_indices,
|
std::vector<uint64_t>& amount_output_indices,
|
||||||
std::vector<uint64_t>& global_output_indices) const
|
std::vector<uint64_t>& global_output_indices) const
|
||||||
{
|
{
|
||||||
|
@ -1970,16 +2009,9 @@ void BlockchainLMDB::get_amount_and_global_output_indices(const crypto::hash& h,
|
||||||
RCURSOR(tx_outputs);
|
RCURSOR(tx_outputs);
|
||||||
|
|
||||||
int result = 0;
|
int result = 0;
|
||||||
MDB_val_copy<crypto::hash> k(h);
|
MDB_val_copy<uint64_t> val_tx_index(tx_index);
|
||||||
MDB_val val_tx_index;
|
|
||||||
MDB_val v;
|
MDB_val v;
|
||||||
|
|
||||||
result = mdb_cursor_get(m_cur_tx_indices, &k, &val_tx_index, MDB_SET);
|
|
||||||
if (result == MDB_NOTFOUND)
|
|
||||||
throw1(OUTPUT_DNE(std::string("Failed to get tx index for tx hash ").append(epee::string_tools::pod_to_hex(h)).c_str()));
|
|
||||||
else if (result)
|
|
||||||
throw0(DB_ERROR(lmdb_error(std::string("DB error attempting to fetch transaction index from hash ") + epee::string_tools::pod_to_hex(h) + ": ", result).c_str()));
|
|
||||||
|
|
||||||
result = mdb_cursor_get(m_cur_tx_outputs, &val_tx_index, &v, MDB_SET);
|
result = mdb_cursor_get(m_cur_tx_outputs, &val_tx_index, &v, MDB_SET);
|
||||||
if (result == MDB_NOTFOUND)
|
if (result == MDB_NOTFOUND)
|
||||||
LOG_PRINT_L0("WARNING: Unexpected: tx has no amount and global indices stored in "
|
LOG_PRINT_L0("WARNING: Unexpected: tx has no amount and global indices stored in "
|
||||||
|
@ -2005,13 +2037,13 @@ void BlockchainLMDB::get_amount_and_global_output_indices(const crypto::hash& h,
|
||||||
TXN_POSTFIX_RDONLY();
|
TXN_POSTFIX_RDONLY();
|
||||||
}
|
}
|
||||||
|
|
||||||
std::vector<uint64_t> BlockchainLMDB::get_tx_amount_output_indices(const crypto::hash& h) const
|
std::vector<uint64_t> BlockchainLMDB::get_tx_amount_output_indices(const uint64_t tx_index) const
|
||||||
{
|
{
|
||||||
LOG_PRINT_L3("BlockchainLMDB::" << __func__);
|
LOG_PRINT_L3("BlockchainLMDB::" << __func__);
|
||||||
|
|
||||||
std::vector<uint64_t> amount_output_indices, global_output_indices;
|
std::vector<uint64_t> amount_output_indices, global_output_indices;
|
||||||
// only need amount_output_indices
|
// only need amount_output_indices
|
||||||
get_amount_and_global_output_indices(h, amount_output_indices, global_output_indices);
|
get_amount_and_global_output_indices(tx_index, amount_output_indices, global_output_indices);
|
||||||
|
|
||||||
return amount_output_indices;
|
return amount_output_indices;
|
||||||
}
|
}
|
||||||
|
|
|
@ -212,6 +212,7 @@ public:
|
||||||
virtual uint64_t height() const;
|
virtual uint64_t height() const;
|
||||||
|
|
||||||
virtual bool tx_exists(const crypto::hash& h) const;
|
virtual bool tx_exists(const crypto::hash& h) const;
|
||||||
|
virtual bool tx_exists(const crypto::hash& h, uint64_t& tx_index) const;
|
||||||
|
|
||||||
virtual uint64_t get_tx_unlock_time(const crypto::hash& h) const;
|
virtual uint64_t get_tx_unlock_time(const crypto::hash& h) const;
|
||||||
|
|
||||||
|
@ -237,11 +238,11 @@ public:
|
||||||
virtual void get_output_tx_and_index(const uint64_t& amount, const std::vector<uint64_t> &offsets, std::vector<tx_out_index> &indices);
|
virtual void get_output_tx_and_index(const uint64_t& amount, const std::vector<uint64_t> &offsets, std::vector<tx_out_index> &indices);
|
||||||
virtual void get_output_global_indices(const uint64_t& amount, const std::vector<uint64_t> &offsets, std::vector<uint64_t> &indices);
|
virtual void get_output_global_indices(const uint64_t& amount, const std::vector<uint64_t> &offsets, std::vector<uint64_t> &indices);
|
||||||
|
|
||||||
virtual void get_amount_and_global_output_indices(const crypto::hash& h,
|
virtual void get_amount_and_global_output_indices(const uint64_t tx_index,
|
||||||
std::vector<uint64_t>& amount_output_indices,
|
std::vector<uint64_t>& amount_output_indices,
|
||||||
std::vector<uint64_t>& global_output_indices) const;
|
std::vector<uint64_t>& global_output_indices) const;
|
||||||
|
|
||||||
virtual std::vector<uint64_t> get_tx_amount_output_indices(const crypto::hash& h) const;
|
virtual std::vector<uint64_t> get_tx_amount_output_indices(const uint64_t tx_index) const;
|
||||||
|
|
||||||
virtual bool has_key_image(const crypto::key_image& img) const;
|
virtual bool has_key_image(const crypto::key_image& img) const;
|
||||||
|
|
||||||
|
@ -307,7 +308,7 @@ private:
|
||||||
|
|
||||||
virtual void remove_output(const tx_out& tx_output);
|
virtual void remove_output(const tx_out& tx_output);
|
||||||
|
|
||||||
void remove_tx_outputs(const crypto::hash& tx_hash, const transaction& tx);
|
void remove_tx_outputs(const uint64_t tx_index, const transaction& tx);
|
||||||
|
|
||||||
void remove_output(const uint64_t& out_index, const uint64_t amount);
|
void remove_output(const uint64_t& out_index, const uint64_t amount);
|
||||||
void remove_amount_output_index(const uint64_t amount, const uint64_t global_output_index);
|
void remove_amount_output_index(const uint64_t amount, const uint64_t global_output_index);
|
||||||
|
|
|
@ -1949,14 +1949,15 @@ bool Blockchain::get_tx_outputs_gindexs(const crypto::hash& tx_id, std::vector<u
|
||||||
{
|
{
|
||||||
LOG_PRINT_L3("Blockchain::" << __func__);
|
LOG_PRINT_L3("Blockchain::" << __func__);
|
||||||
CRITICAL_REGION_LOCAL(m_blockchain_lock);
|
CRITICAL_REGION_LOCAL(m_blockchain_lock);
|
||||||
if (!m_db->tx_exists(tx_id))
|
uint64_t tx_index;
|
||||||
|
if (!m_db->tx_exists(tx_id, tx_index))
|
||||||
{
|
{
|
||||||
LOG_PRINT_RED_L1("warning: get_tx_outputs_gindexs failed to find transaction with id = " << tx_id);
|
LOG_PRINT_RED_L1("warning: get_tx_outputs_gindexs failed to find transaction with id = " << tx_id);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
// get amount output indexes, currently referred to in parts as "output global indices", but they are actually specific to amounts
|
// get amount output indexes, currently referred to in parts as "output global indices", but they are actually specific to amounts
|
||||||
indexs = m_db->get_tx_amount_output_indices(tx_id);
|
indexs = m_db->get_tx_amount_output_indices(tx_index);
|
||||||
CHECK_AND_ASSERT_MES(indexs.size(), false, "internal error: global indexes for transaction " << tx_id << " is empty");
|
CHECK_AND_ASSERT_MES(indexs.size(), false, "internal error: global indexes for transaction " << tx_id << " is empty");
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
|
|
Loading…
Reference in New Issue