Electroneum
cryptonote::BlockchainLMDB Class Reference

#include <db_lmdb.h>

Inheritance diagram for cryptonote::BlockchainLMDB:
Collaboration diagram for cryptonote::BlockchainLMDB:

Public Member Functions

 BlockchainLMDB (bool batch_transactions=true)
 
 ~BlockchainLMDB ()
 
virtual void open (const std::string &filename, const int mdb_flags=0)
 open a db, or create it if necessary. More...
 
virtual void close ()
 close the BlockchainDB More...
 
virtual void sync ()
 sync the BlockchainDB with disk More...
 
virtual void safesyncmode (const bool onoff)
 toggle safe syncs for the DB More...
 
virtual void reset ()
 Remove everything from the BlockchainDB. More...
 
virtual std::vector< std::string > get_filenames () const
 get all files used by the BlockchainDB (if any) More...
 
virtual bool remove_data_file (const std::string &folder) const
 remove file(s) storing the database More...
 
virtual std::string get_db_name () const
 gets the name of the folder the BlockchainDB's file(s) should be in More...
 
virtual bool lock ()
 acquires the BlockchainDB lock More...
 
virtual void unlock ()
 This function releases the BlockchainDB lock. More...
 
virtual bool block_exists (const crypto::hash &h, uint64_t *height=NULL) const
 checks if a block exists More...
 
virtual uint64_t get_block_height (const crypto::hash &h) const
 gets the height of the block with a given hash More...
 
virtual block_header get_block_header (const crypto::hash &h) const
 fetch a block header More...
 
virtual cryptonote::blobdata get_block_blob (const crypto::hash &h) const
 fetches the block with the given hash More...
 
virtual cryptonote::blobdata get_block_blob_from_height (const uint64_t &height) const
 fetch a block blob by height More...
 
virtual std::vector< uint64_tget_block_cumulative_rct_outputs (const std::vector< uint64_t > &heights) const
 fetch a block's cumulative number of rct outputs More...
 
virtual uint64_t get_block_timestamp (const uint64_t &height) const
 fetch a block's timestamp More...
 
virtual uint64_t get_top_block_timestamp () const
 fetch the top block's timestamp More...
 
virtual size_t get_block_weight (const uint64_t &height) const
 fetch a block's weight More...
 
virtual std::vector< uint64_tget_block_weights (uint64_t start_height, size_t count) const
 fetch the last N blocks' weights More...
 
virtual void set_block_cumulative_difficulty (uint64_t height, difficulty_type diff)
 sets a block's cumulative difficulty More...
 
virtual difficulty_type get_block_cumulative_difficulty (const uint64_t &height) const
 fetch a block's cumulative difficulty More...
 
virtual difficulty_type get_block_difficulty (const uint64_t &height) const
 fetch a block's difficulty More...
 
virtual uint64_t get_block_already_generated_coins (const uint64_t &height) const
 fetch a block's already generated coins More...
 
virtual uint64_t get_block_long_term_weight (const uint64_t &height) const
 fetch a block's long term weight More...
 
virtual std::vector< uint64_tget_long_term_block_weights (uint64_t start_height, size_t count) const
 fetch the last N blocks' long term weights More...
 
virtual crypto::hash get_block_hash_from_height (const uint64_t &height) const
 fetch a block's hash More...
 
virtual std::vector< blockget_blocks_range (const uint64_t &h1, const uint64_t &h2) const
 fetch a list of blocks More...
 
virtual std::vector< crypto::hashget_hashes_range (const uint64_t &h1, const uint64_t &h2) const
 fetch a list of block hashes More...
 
virtual crypto::hash top_block_hash (uint64_t *block_height=NULL) const
 fetch the top block's hash More...
 
virtual block get_top_block () const
 fetch the top block More...
 
virtual uint64_t height () const
 fetch the current blockchain height More...
 
virtual bool tx_exists (const crypto::hash &h) const
 check if a transaction with a given hash exists More...
 
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
 fetch a transaction's unlock time/height More...
 
virtual bool get_tx_blob (const crypto::hash &h, cryptonote::blobdata &tx) const
 fetches the transaction blob with the given hash More...
 
virtual bool get_pruned_tx_blob (const crypto::hash &h, cryptonote::blobdata &tx) const
 fetches the pruned transaction blob with the given hash More...
 
virtual bool get_prunable_tx_blob (const crypto::hash &h, cryptonote::blobdata &tx) const
 fetches the prunable transaction blob with the given hash More...
 
virtual bool get_prunable_tx_hash (const crypto::hash &tx_hash, crypto::hash &prunable_hash) const
 fetches the prunable transaction hash More...
 
virtual uint64_t get_tx_count () const
 fetches the total number of transactions ever More...
 
virtual std::vector< transactionget_tx_list (const std::vector< crypto::hash > &hlist) const
 fetches a list of transactions based on their hashes More...
 
virtual uint64_t get_tx_block_height (const crypto::hash &h) const
 fetches the height of a transaction's block More...
 
virtual uint64_t get_num_outputs (const uint64_t &amount) const
 fetches the number of outputs of a given amount More...
 
virtual output_data_t get_output_key (const uint64_t &amount, const uint64_t &index, bool include_commitmemt) const
 get some of an output's data More...
 
virtual void get_output_key (const epee::span< const uint64_t > &amounts, const std::vector< uint64_t > &offsets, std::vector< output_data_t > &outputs, bool allow_partial=false) const
 gets outputs' data More...
 
virtual tx_out_index get_output_tx_and_index_from_global (const uint64_t &index) const
 gets an output's tx hash and index More...
 
virtual void get_output_tx_and_index_from_global (const std::vector< uint64_t > &global_indices, std::vector< tx_out_index > &tx_out_indices) const
 
virtual tx_out_index get_output_tx_and_index (const uint64_t &amount, const uint64_t &index) const
 gets an output's tx hash and index More...
 
virtual void get_output_tx_and_index (const uint64_t &amount, const std::vector< uint64_t > &offsets, std::vector< tx_out_index > &indices) const
 gets some outputs' tx hashes and indices More...
 
virtual std::vector< std::vector< uint64_t > > get_tx_amount_output_indices (const uint64_t tx_id, size_t n_txes) const
 gets output indices (amount-specific) for a transaction's outputs More...
 
virtual bool has_key_image (const crypto::key_image &img) const
 check if a key image is stored as spent More...
 
virtual void add_txpool_tx (const crypto::hash &txid, const cryptonote::blobdata &blob, const txpool_tx_meta_t &meta)
 add a txpool transaction More...
 
virtual void update_txpool_tx (const crypto::hash &txid, const txpool_tx_meta_t &meta)
 update a txpool transaction's metadata More...
 
virtual uint64_t get_txpool_tx_count (bool include_unrelayed_txes=true) const
 get the number of transactions in the txpool More...
 
virtual bool txpool_has_tx (const crypto::hash &txid) const
 check whether a txid is in the txpool More...
 
virtual void remove_txpool_tx (const crypto::hash &txid)
 remove a txpool transaction More...
 
virtual bool get_txpool_tx_meta (const crypto::hash &txid, txpool_tx_meta_t &meta) const
 get a txpool transaction's metadata More...
 
virtual bool get_txpool_tx_blob (const crypto::hash &txid, cryptonote::blobdata &bd) const
 get a txpool transaction's blob More...
 
virtual cryptonote::blobdata get_txpool_tx_blob (const crypto::hash &txid) const
 get a txpool transaction's blob More...
 
virtual uint32_t get_blockchain_pruning_seed () const
 get the blockchain pruning seed More...
 
virtual bool prune_blockchain (uint32_t pruning_seed=0)
 prunes the blockchain More...
 
virtual bool update_pruning ()
 prunes recent blockchain changes as needed, iff pruning is enabled More...
 
virtual bool check_pruning ()
 checks pruning was done correctly, iff enabled More...
 
virtual bool for_all_txpool_txes (std::function< bool(const crypto::hash &, const txpool_tx_meta_t &, const cryptonote::blobdata *)> f, bool include_blob=false, bool include_unrelayed_txes=true) const
 runs a function over all txpool transactions More...
 
virtual bool for_all_key_images (std::function< bool(const crypto::key_image &)>) const
 runs a function over all key images stored More...
 
virtual bool for_blocks_range (const uint64_t &h1, const uint64_t &h2, std::function< bool(uint64_t, const crypto::hash &, const cryptonote::block &)>) const
 runs a function over a range of blocks More...
 
virtual bool for_all_transactions (std::function< bool(const crypto::hash &, const cryptonote::transaction &)>, bool pruned) const
 runs a function over all transactions stored More...
 
virtual bool for_all_outputs (std::function< bool(uint64_t amount, const crypto::hash &tx_hash, uint64_t height, size_t tx_idx)> f) const
 runs a function over all outputs stored More...
 
virtual bool for_all_outputs (uint64_t amount, const std::function< bool(uint64_t height)> &f) const
 
virtual uint64_t add_block (const std::pair< block, blobdata > &blk, size_t block_weight, uint64_t long_term_block_weight, const difficulty_type &cumulative_difficulty, const uint64_t &coins_generated, const std::vector< std::pair< transaction, blobdata >> &txs)
 handles the addition of a new block to BlockchainDB More...
 
virtual void set_batch_transactions (bool batch_transactions)
 sets whether or not to batch transactions More...
 
virtual bool batch_start (uint64_t batch_num_blocks=0, uint64_t batch_bytes=0)
 tells the BlockchainDB to start a new "batch" of blocks More...
 
virtual void batch_commit ()
 
virtual void batch_stop ()
 ends a batch transaction More...
 
virtual void batch_abort ()
 aborts a batch transaction More...
 
virtual void block_wtxn_start ()
 
virtual void block_wtxn_stop ()
 
virtual void block_wtxn_abort ()
 
virtual bool block_rtxn_start () const
 
virtual void block_rtxn_stop () const
 
virtual void block_rtxn_abort () const
 
bool block_rtxn_start (MDB_txn **mtxn, mdb_txn_cursors **mcur) const
 
virtual void pop_block (block &blk, std::vector< transaction > &txs)
 pops the top block off the blockchain More...
 
virtual bool can_thread_bulk_indices () const
 
std::map< uint64_t, std::tuple< uint64_t, uint64_t, uint64_t > > get_output_histogram (const std::vector< uint64_t > &amounts, bool unlocked, uint64_t recent_cutoff, uint64_t min_count) const
 return a histogram of outputs on the blockchain More...
 
bool get_output_distribution (uint64_t amount, uint64_t from_height, uint64_t to_height, std::vector< uint64_t > &distribution, uint64_t &base) const
 
virtual std::vector< address_outputsget_addr_output_all (const crypto::public_key &combined_key)
 
virtual std::vector< address_outputsget_addr_output_batch (const crypto::public_key &combined_key, uint64_t start_db_index=0, uint64_t batch_size=100, bool desc=false)
 
virtual uint64_t get_balance (const crypto::public_key &combined_key)
 
virtual tx_input_t get_tx_input (const crypto::hash tx_hash, const uint32_t relative_out_index)
 
- Public Member Functions inherited from cryptonote::BlockchainDB
 BlockchainDB ()
 An empty constructor. More...
 
virtual ~BlockchainDB ()
 An empty destructor. More...
 
void reset_stats ()
 reset profiling stats More...
 
void show_stats ()
 show profiling stats More...
 
bool is_open () const
 Gets the current open/ready state of the BlockchainDB. More...
 
virtual void set_hard_fork (HardFork *hf)
 
virtual block get_block (const crypto::hash &h) const
 fetches the block with the given hash More...
 
virtual block get_block_from_height (const uint64_t &height) const
 fetch a block by height More...
 
virtual transaction get_tx (const crypto::hash &h) const
 fetches the transaction with the given hash More...
 
virtual transaction get_pruned_tx (const crypto::hash &h) const
 fetches the transaction base with the given hash More...
 
virtual bool get_tx (const crypto::hash &h, transaction &tx) const
 fetches the transaction with the given hash More...
 
virtual bool get_pruned_tx (const crypto::hash &h, transaction &tx) const
 fetches the transaction base with the given hash More...
 
virtual uint64_t get_indexing_base () const
 return index of the first element (should be hidden, but isn't) More...
 
void set_auto_remove_logs (bool auto_remove)
 set whether or not to automatically remove logs More...
 

Static Public Member Functions

static int compare_uint64 (const MDB_val *a, const MDB_val *b)
 
static int compare_hash32 (const MDB_val *a, const MDB_val *b)
 
static int compare_string (const MDB_val *a, const MDB_val *b)
 
static int compare_data (const MDB_val *a, const MDB_val *b)
 
static int compare_publickey (const MDB_val *a, const MDB_val *b)
 
- Static Public Member Functions inherited from cryptonote::BlockchainDB
static void init_options (boost::program_options::options_description &desc)
 init command line options More...
 

Additional Inherited Members

- Public Attributes inherited from cryptonote::BlockchainDB
bool m_open
 Whether or not the BlockchainDB is open/ready for use. More...
 
epee::critical_section m_synchronization_lock
 A lock, currently for when BlockchainLMDB needs to resize the backing db file. More...
 
- Protected Member Functions inherited from cryptonote::BlockchainDB
void add_transaction (const crypto::hash &blk_hash, const std::pair< transaction, blobdata > &tx, const crypto::hash *tx_hash_ptr=NULL, const crypto::hash *tx_prunable_hash_ptr=NULL)
 helper function for add_transactions, to add each individual transaction More...
 
- Protected Attributes inherited from cryptonote::BlockchainDB
uint64_t time_tx_exists = 0
 a performance metric More...
 
uint64_t time_commit1 = 0
 a performance metric More...
 
bool m_auto_remove_logs = true
 whether or not to automatically remove old logs More...
 
HardForkm_hardfork
 

Detailed Description

Definition at line 191 of file db_lmdb.h.

Constructor & Destructor Documentation

◆ BlockchainLMDB()

cryptonote::BlockchainLMDB::BlockchainLMDB ( bool  batch_transactions = true)

Definition at line 1331 of file db_lmdb.cpp.

1331  : BlockchainDB()
1332 {
1333  LOG_PRINT_L3("BlockchainLMDB::" << __func__);
1334  // initialize folder to something "safe" just in case
1335  // someone accidentally misuses this class...
1336  m_folder = "thishsouldnotexistbecauseitisgibberish";
1337 
1338  m_batch_transactions = batch_transactions;
1339  m_write_txn = nullptr;
1340  m_write_batch_txn = nullptr;
1341  m_batch_active = false;
1342  m_cum_size = 0;
1343  m_cum_count = 0;
1344 
1345  // reset may also need changing when initialize things here
1346 
1347  m_hardfork = nullptr;
1348 }
BlockchainDB()
An empty constructor.
#define LOG_PRINT_L3(x)
Definition: misc_log_ex.h:102

◆ ~BlockchainLMDB()

cryptonote::BlockchainLMDB::~BlockchainLMDB ( )

Definition at line 1317 of file db_lmdb.cpp.

1318 {
1319  LOG_PRINT_L3("BlockchainLMDB::" << __func__);
1320 
1321  // batch transaction shouldn't be active at this point. If it is, consider it aborted.
1322  if (m_batch_active)
1323  {
1324  try { batch_abort(); }
1325  catch (...) { /* ignore */ }
1326  }
1327  if (m_open)
1328  close();
1329 }
bool m_open
Whether or not the BlockchainDB is open/ready for use.
virtual void batch_abort()
aborts a batch transaction
Definition: db_lmdb.cpp:4120
virtual void close()
close the BlockchainDB
Definition: db_lmdb.cpp:1605

Member Function Documentation

◆ add_block()

uint64_t cryptonote::BlockchainLMDB::add_block ( const std::pair< block, blobdata > &  blk,
size_t  block_weight,
uint64_t  long_term_block_weight,
const difficulty_type cumulative_difficulty,
const uint64_t coins_generated,
const std::vector< std::pair< transaction, blobdata >> &  txs 
)
virtual

handles the addition of a new block to BlockchainDB

This function organizes block addition and calls various functions as necessary.

NOTE: subclass implementations of this (or the functions it calls) need to handle undoing any partially-added blocks in the event of a failure.

If any of this cannot be done, the subclass should throw the corresponding subclass of DB_EXCEPTION

Parameters
blkthe block to be added
block_weightthe size of the block (transactions and all)
long_term_block_weightthe long term weight of the block (transactions and all)
cumulative_difficultythe accumulated difficulty after this block
coins_generatedthe number of coins generated total after this block
txsthe transactions in the block
Returns
the height of the chain post-addition

Reimplemented from cryptonote::BlockchainDB.

Definition at line 4284 of file db_lmdb.cpp.

4286 {
4287  LOG_PRINT_L3("BlockchainLMDB::" << __func__);
4288  check_open();
4289  uint64_t m_height = height();
4290 
4291  if (m_height % 1024 == 0)
4292  {
4293  // for batch mode, DB resize check is done at start of batch transaction
4294  if (! m_batch_active && need_resize())
4295  {
4296  LOG_PRINT_L0("LMDB memory map needs to be resized, doing that now.");
4297  do_resize();
4298  }
4299  }
4300 
4301  try
4302  {
4303  BlockchainDB::add_block(blk, block_weight, long_term_block_weight, cumulative_difficulty, coins_generated, txs);
4304  }
4305  catch (const DB_ERROR_TXN_START& e)
4306  {
4307  throw;
4308  }
4309 
4310  return ++m_height;
4311 }
virtual uint64_t height() const
fetch the current blockchain height
Definition: db_lmdb.cpp:3332
#define LOG_PRINT_L0(x)
Definition: misc_log_ex.h:99
unsigned __int64 uint64_t
Definition: stdint.h:136
Here is the call graph for this function:

◆ add_txpool_tx()

void cryptonote::BlockchainLMDB::add_txpool_tx ( const crypto::hash txid,
const cryptonote::blobdata blob,
const txpool_tx_meta_t details 
)
virtual

add a txpool transaction

Parameters
detailsthe details of the transaction to add

Implements cryptonote::BlockchainDB.

Definition at line 2215 of file db_lmdb.cpp.

2216 {
2217  LOG_PRINT_L3("BlockchainLMDB::" << __func__);
2218  check_open();
2219  mdb_txn_cursors *m_cursors = &m_wcursors;
2220 
2221  CURSOR(txpool_meta)
2222  CURSOR(txpool_blob)
2223 
2224  MDB_val k = {sizeof(txid), (void *)&txid};
2225  MDB_val v = {sizeof(meta), (void *)&meta};
2226  if (auto result = mdb_cursor_put(m_cur_txpool_meta, &k, &v, MDB_NODUPDATA)) {
2227  if (result == MDB_KEYEXIST)
2228  throw1(DB_ERROR("Attempting to add txpool tx metadata that's already in the db"));
2229  else
2230  throw1(DB_ERROR(lmdb_error("Error adding txpool tx metadata to db transaction: ", result).c_str()));
2231  }
2232  MDB_val_sized(blob_val, blob);
2233  if (auto result = mdb_cursor_put(m_cur_txpool_blob, &k, &blob_val, MDB_NODUPDATA)) {
2234  if (result == MDB_KEYEXIST)
2235  throw1(DB_ERROR("Attempting to add txpool tx blob that's already in the db"));
2236  else
2237  throw1(DB_ERROR(lmdb_error("Error adding txpool tx blob to db transaction: ", result).c_str()));
2238  }
2239 }
#define MDB_val_sized(var, val)
Definition: db_lmdb.cpp:91
#define CURSOR(name)
Definition: db_lmdb.cpp:283
#define m_cur_txpool_blob
Definition: db_lmdb.h:94
#define m_cur_txpool_meta
Definition: db_lmdb.h:93
#define MDB_KEYEXIST
Definition: lmdb.h:437
int mdb_cursor_put(MDB_cursor *cursor, MDB_val *key, MDB_val *data, unsigned int flags)
Store by cursor.
#define MDB_NODUPDATA
Definition: lmdb.h:369
struct cryptonote::mdb_txn_cursors mdb_txn_cursors
Generic structure used for passing keys and data in and out of the database.
Definition: lmdb.h:286
Here is the call graph for this function:

◆ batch_abort()

void cryptonote::BlockchainLMDB::batch_abort ( )
virtual

aborts a batch transaction

If the subclass implements batching, this function should abort the batch it is currently on.

If no batch is in-progress, this function should throw a DB_ERROR. This exception may change in the future if it is deemed necessary to have a more granular exception type for this scenario.

If any of this cannot be done, the subclass should throw the corresponding subclass of DB_EXCEPTION

Implements cryptonote::BlockchainDB.

Definition at line 4120 of file db_lmdb.cpp.

4121 {
4122  LOG_PRINT_L3("BlockchainLMDB::" << __func__);
4123  if (! m_batch_transactions)
4124  throw0(DB_ERROR("batch transactions not enabled"));
4125  if (! m_batch_active)
4126  throw1(DB_ERROR("batch transaction not in progress"));
4127  if (m_write_batch_txn == nullptr)
4128  throw1(DB_ERROR("batch transaction not in progress"));
4129  if (m_writer != boost::this_thread::get_id())
4130  throw1(DB_ERROR("batch transaction owned by other thread"));
4131  check_open();
4132  // for destruction of batch transaction
4133  m_write_txn = nullptr;
4134  // explicitly call in case mdb_env_close() (BlockchainLMDB::close()) called before BlockchainLMDB destructor called.
4135  m_write_batch_txn->abort();
4136  delete m_write_batch_txn;
4137  m_write_batch_txn = nullptr;
4138  m_batch_active = false;
4139  memset(&m_wcursors, 0, sizeof(m_wcursors));
4140  LOG_PRINT_L3("batch transaction: aborted");
4141 }
Here is the call graph for this function:
Here is the caller graph for this function:

◆ batch_commit()

void cryptonote::BlockchainLMDB::batch_commit ( )
virtual

Definition at line 4054 of file db_lmdb.cpp.

4055 {
4056  LOG_PRINT_L3("BlockchainLMDB::" << __func__);
4057  if (! m_batch_transactions)
4058  throw0(DB_ERROR("batch transactions not enabled"));
4059  if (! m_batch_active)
4060  throw1(DB_ERROR("batch transaction not in progress"));
4061  if (m_write_batch_txn == nullptr)
4062  throw1(DB_ERROR("batch transaction not in progress"));
4063  if (m_writer != boost::this_thread::get_id())
4064  throw1(DB_ERROR("batch transaction owned by other thread"));
4065 
4066  check_open();
4067 
4068  LOG_PRINT_L3("batch transaction: committing...");
4069  TIME_MEASURE_START(time1);
4070  m_write_txn->commit();
4071  TIME_MEASURE_FINISH(time1);
4072  time_commit1 += time1;
4073  LOG_PRINT_L3("batch transaction: committed");
4074 
4075  m_write_txn = nullptr;
4076  delete m_write_batch_txn;
4077  m_write_batch_txn = nullptr;
4078  memset(&m_wcursors, 0, sizeof(m_wcursors));
4079 }
uint64_t time_commit1
a performance metric
#define TIME_MEASURE_FINISH(var_name)
Definition: profile_tools.h:64
#define TIME_MEASURE_START(var_name)
Definition: profile_tools.h:61
void commit(std::string message="")
Definition: db_lmdb.cpp:446
Here is the call graph for this function:

◆ batch_start()

bool cryptonote::BlockchainLMDB::batch_start ( uint64_t  batch_num_blocks = 0,
uint64_t  batch_bytes = 0 
)
virtual

tells the BlockchainDB to start a new "batch" of blocks

If the subclass implements a batching method of caching blocks in RAM to be added to a backing store in groups, it should start a batch which will end either when <batch_num_blocks> has been added or batch_stop() has been called. In either case, it should end the batch and write to its backing store.

If a batch is already in-progress, this function must return false. If a batch was started by this call, it must return true.

If any of this cannot be done, the subclass should throw the corresponding subclass of DB_EXCEPTION

Parameters
batch_num_blocksnumber of blocks to batch together
Returns
true if we started the batch, false if already started

Implements cryptonote::BlockchainDB.

Definition at line 4011 of file db_lmdb.cpp.

4012 {
4013  LOG_PRINT_L3("BlockchainLMDB::" << __func__);
4014  if (! m_batch_transactions)
4015  throw0(DB_ERROR("batch transactions not enabled"));
4016  if (m_batch_active)
4017  return false;
4018  if (m_write_batch_txn != nullptr)
4019  return false;
4020  if (m_write_txn)
4021  throw0(DB_ERROR("batch transaction attempted, but m_write_txn already in use"));
4022  check_open();
4023 
4024  m_writer = boost::this_thread::get_id();
4025  check_and_resize_for_batch(batch_num_blocks, batch_bytes);
4026 
4027  m_write_batch_txn = new mdb_txn_safe();
4028 
4029  // NOTE: need to make sure it's destroyed properly when done
4030  if (auto mdb_res = lmdb_txn_begin(m_env, NULL, 0, *m_write_batch_txn))
4031  {
4032  delete m_write_batch_txn;
4033  m_write_batch_txn = nullptr;
4034  throw0(DB_ERROR(lmdb_error("Failed to create a transaction for the db: ", mdb_res).c_str()));
4035  }
4036  // indicates this transaction is for batch transactions, but not whether it's
4037  // active
4038  m_write_batch_txn->m_batch_txn = true;
4039  m_write_txn = m_write_batch_txn;
4040 
4041  m_batch_active = true;
4042  memset(&m_wcursors, 0, sizeof(m_wcursors));
4043  if (m_tinfo.get())
4044  {
4045  if (m_tinfo->m_ti_rflags.m_rf_txn)
4046  mdb_txn_reset(m_tinfo->m_ti_rtxn);
4047  memset(&m_tinfo->m_ti_rflags, 0, sizeof(m_tinfo->m_ti_rflags));
4048  }
4049 
4050  LOG_PRINT_L3("batch transaction: begin");
4051  return true;
4052 }
void mdb_txn_reset(MDB_txn *txn)
Reset a read-only transaction.
int lmdb_txn_begin(MDB_env *env, MDB_txn *parent, unsigned int flags, MDB_txn **txn)
Definition: db_lmdb.cpp:520
Here is the call graph for this function:

◆ batch_stop()

void cryptonote::BlockchainLMDB::batch_stop ( )
virtual

ends a batch transaction

If the subclass implements batching, this function should store the batch it is currently on and mark it finished.

If no batch is in-progress, this function should throw a DB_ERROR. This exception may change in the future if it is deemed necessary to have a more granular exception type for this scenario.

If any of this cannot be done, the subclass should throw the corresponding subclass of DB_EXCEPTION

Implements cryptonote::BlockchainDB.

Definition at line 4091 of file db_lmdb.cpp.

4092 {
4093  LOG_PRINT_L3("BlockchainLMDB::" << __func__);
4094  if (! m_batch_transactions)
4095  throw0(DB_ERROR("batch transactions not enabled"));
4096  if (! m_batch_active)
4097  throw1(DB_ERROR("batch transaction not in progress"));
4098  if (m_write_batch_txn == nullptr)
4099  throw1(DB_ERROR("batch transaction not in progress"));
4100  if (m_writer != boost::this_thread::get_id())
4101  throw1(DB_ERROR("batch transaction owned by other thread"));
4102  check_open();
4103  LOG_PRINT_L3("batch transaction: committing...");
4104  TIME_MEASURE_START(time1);
4105  try
4106  {
4107  m_write_txn->commit();
4108  TIME_MEASURE_FINISH(time1);
4109  time_commit1 += time1;
4110  cleanup_batch();
4111  }
4112  catch (const std::exception &e)
4113  {
4114  cleanup_batch();
4115  throw;
4116  }
4117  LOG_PRINT_L3("batch transaction: end");
4118 }
Here is the call graph for this function:

◆ block_exists()

bool cryptonote::BlockchainLMDB::block_exists ( const crypto::hash h,
uint64_t height = NULL 
) const
virtual

checks if a block exists

Parameters
hthe hash of the requested block
heightif non NULL, returns the block's height if found
Returns
true of the block exists, otherwise false

Implements cryptonote::BlockchainDB.

Definition at line 2793 of file db_lmdb.cpp.

2794 {
2795  LOG_PRINT_L3("BlockchainLMDB::" << __func__);
2796  check_open();
2797 
2799  RCURSOR(block_heights);
2800 
2801  bool ret = false;
2802  MDB_val_set(key, h);
2803  auto get_result = mdb_cursor_get(m_cur_block_heights, (MDB_val *)&zerokval, &key, MDB_GET_BOTH);
2804  if (get_result == MDB_NOTFOUND)
2805  {
2806  LOG_PRINT_L3("Block with hash " << epee::string_tools::pod_to_hex(h) << " not found in db");
2807  }
2808  else if (get_result)
2809  throw0(DB_ERROR(lmdb_error("DB error attempting to fetch block index from hash", get_result).c_str()));
2810  else
2811  {
2812  if (height)
2813  {
2814  const blk_height *bhp = (const blk_height *)key.mv_data;
2815  *height = bhp->bh_height;
2816  }
2817  ret = true;
2818  }
2819 
2821  return ret;
2822 }
#define TXN_POSTFIX_RDONLY()
Definition: db_lmdb.cpp:1772
#define RCURSOR(name)
Definition: db_lmdb.cpp:290
#define TXN_PREFIX_RDONLY()
Definition: db_lmdb.cpp:1765
#define MDB_val_set(var, val)
Definition: db_lmdb.cpp:89
#define m_cur_block_heights
Definition: db_lmdb.h:81
#define MDB_NOTFOUND
Definition: lmdb.h:439
int mdb_cursor_get(MDB_cursor *cursor, MDB_val *key, MDB_val *data, MDB_cursor_op op)
Retrieve by cursor.
@ MDB_GET_BOTH
Definition: lmdb.h:402
const char * key
Definition: hmac_keccak.cpp:39
struct cryptonote::blk_height blk_height
std::string pod_to_hex(const t_pod_type &s)
Definition: string_tools.h:317
Here is the call graph for this function:

◆ block_rtxn_abort()

void cryptonote::BlockchainLMDB::block_rtxn_abort ( ) const
virtual

Implements cryptonote::BlockchainDB.

Definition at line 4277 of file db_lmdb.cpp.

4278 {
4279  LOG_PRINT_L3("BlockchainLMDB::" << __func__);
4280  mdb_txn_reset(m_tinfo->m_ti_rtxn);
4281  memset(&m_tinfo->m_ti_rflags, 0, sizeof(m_tinfo->m_ti_rflags));
4282 }
Here is the call graph for this function:

◆ block_rtxn_start() [1/2]

bool cryptonote::BlockchainLMDB::block_rtxn_start ( ) const
virtual

Implements cryptonote::BlockchainDB.

Definition at line 4199 of file db_lmdb.cpp.

4200 {
4201  MDB_txn *mtxn;
4202  mdb_txn_cursors *mcur;
4203  return block_rtxn_start(&mtxn, &mcur);
4204 }
virtual bool block_rtxn_start() const
Definition: db_lmdb.cpp:4199
struct MDB_txn MDB_txn
Opaque structure for a transaction handle.
Definition: lmdb.h:267

◆ block_rtxn_start() [2/2]

bool cryptonote::BlockchainLMDB::block_rtxn_start ( MDB_txn **  mtxn,
mdb_txn_cursors **  mcur 
) const

Definition at line 4155 of file db_lmdb.cpp.

4156 {
4157  bool ret = false;
4158  mdb_threadinfo *tinfo;
4159  if (m_write_txn && m_writer == boost::this_thread::get_id()) {
4160  *mtxn = m_write_txn->m_txn;
4161  *mcur = (mdb_txn_cursors *)&m_wcursors;
4162  return ret;
4163  }
4164  /* Check for existing info and force reset if env doesn't match -
4165  * only happens if env was opened/closed multiple times in same process
4166  */
4167  if (!(tinfo = m_tinfo.get()) || mdb_txn_env(tinfo->m_ti_rtxn) != m_env)
4168  {
4169  tinfo = new mdb_threadinfo;
4170  m_tinfo.reset(tinfo);
4171  memset(&tinfo->m_ti_rcursors, 0, sizeof(tinfo->m_ti_rcursors));
4172  memset(&tinfo->m_ti_rflags, 0, sizeof(tinfo->m_ti_rflags));
4173  if (auto mdb_res = lmdb_txn_begin(m_env, NULL, MDB_RDONLY, &tinfo->m_ti_rtxn))
4174  throw0(DB_ERROR_TXN_START(lmdb_error("Failed to create a read transaction for the db: ", mdb_res).c_str()));
4175  ret = true;
4176  } else if (!tinfo->m_ti_rflags.m_rf_txn)
4177  {
4178  if (auto mdb_res = lmdb_txn_renew(tinfo->m_ti_rtxn))
4179  throw0(DB_ERROR_TXN_START(lmdb_error("Failed to renew a read transaction for the db: ", mdb_res).c_str()));
4180  ret = true;
4181  }
4182  if (ret)
4183  tinfo->m_ti_rflags.m_rf_txn = true;
4184  *mtxn = tinfo->m_ti_rtxn;
4185  *mcur = &tinfo->m_ti_rcursors;
4186 
4187  if (ret)
4188  LOG_PRINT_L3("BlockchainLMDB::" << __func__);
4189  return ret;
4190 }
MDB_env * mdb_txn_env(MDB_txn *txn)
Returns the transaction's MDB_env.
#define MDB_RDONLY
Definition: lmdb.h:320
struct cryptonote::mdb_threadinfo mdb_threadinfo
int lmdb_txn_renew(MDB_txn *txn)
Definition: db_lmdb.cpp:530
Here is the call graph for this function:

◆ block_rtxn_stop()

void cryptonote::BlockchainLMDB::block_rtxn_stop ( ) const
virtual

Implements cryptonote::BlockchainDB.

Definition at line 4192 of file db_lmdb.cpp.

4193 {
4194  LOG_PRINT_L3("BlockchainLMDB::" << __func__);
4195  mdb_txn_reset(m_tinfo->m_ti_rtxn);
4196  memset(&m_tinfo->m_ti_rflags, 0, sizeof(m_tinfo->m_ti_rflags));
4197 }
Here is the call graph for this function:

◆ block_wtxn_abort()

void cryptonote::BlockchainLMDB::block_wtxn_abort ( )
virtual

Implements cryptonote::BlockchainDB.

Definition at line 4261 of file db_lmdb.cpp.

4262 {
4263  LOG_PRINT_L3("BlockchainLMDB::" << __func__);
4264  if (!m_write_txn)
4265  throw0(DB_ERROR_TXN_START((std::string("Attempted to abort write txn when no such txn exists in ")+__FUNCTION__).c_str()));
4266  if (m_writer != boost::this_thread::get_id())
4267  throw0(DB_ERROR_TXN_START((std::string("Attempted to abort write txn from the wrong thread in ")+__FUNCTION__).c_str()));
4268 
4269  if (! m_batch_active)
4270  {
4271  delete m_write_txn;
4272  m_write_txn = nullptr;
4273  memset(&m_wcursors, 0, sizeof(m_wcursors));
4274  }
4275 }
::std::string string
Definition: gtest-port.h:1097
Here is the caller graph for this function:

◆ block_wtxn_start()

void cryptonote::BlockchainLMDB::block_wtxn_start ( )
virtual

Implements cryptonote::BlockchainDB.

Definition at line 4206 of file db_lmdb.cpp.

4207 {
4208  LOG_PRINT_L3("BlockchainLMDB::" << __func__);
4209  // Distinguish the exceptions here from exceptions that would be thrown while
4210  // using the txn and committing it.
4211  //
4212  // If an exception is thrown in this setup, we don't want the caller to catch
4213  // it and proceed as if there were an existing write txn, such as trying to
4214  // call block_txn_abort(). It also indicates a serious issue which will
4215  // probably be thrown up another layer.
4216  if (! m_batch_active && m_write_txn)
4217  throw0(DB_ERROR_TXN_START((std::string("Attempted to start new write txn when write txn already exists in ")+__FUNCTION__).c_str()));
4218  if (! m_batch_active)
4219  {
4220  m_writer = boost::this_thread::get_id();
4221  m_write_txn = new mdb_txn_safe();
4222  if (auto mdb_res = lmdb_txn_begin(m_env, NULL, 0, *m_write_txn))
4223  {
4224  delete m_write_txn;
4225  m_write_txn = nullptr;
4226  throw0(DB_ERROR_TXN_START(lmdb_error("Failed to create a transaction for the db: ", mdb_res).c_str()));
4227  }
4228  memset(&m_wcursors, 0, sizeof(m_wcursors));
4229  if (m_tinfo.get())
4230  {
4231  if (m_tinfo->m_ti_rflags.m_rf_txn)
4232  mdb_txn_reset(m_tinfo->m_ti_rtxn);
4233  memset(&m_tinfo->m_ti_rflags, 0, sizeof(m_tinfo->m_ti_rflags));
4234  }
4235  } else if (m_writer != boost::this_thread::get_id())
4236  throw0(DB_ERROR_TXN_START((std::string("Attempted to start new write txn when batch txn already exists in ")+__FUNCTION__).c_str()));
4237 }
Here is the call graph for this function:
Here is the caller graph for this function:

◆ block_wtxn_stop()

void cryptonote::BlockchainLMDB::block_wtxn_stop ( )
virtual

Implements cryptonote::BlockchainDB.

Definition at line 4239 of file db_lmdb.cpp.

4240 {
4241  LOG_PRINT_L3("BlockchainLMDB::" << __func__);
4242  if (!m_write_txn)
4243  throw0(DB_ERROR_TXN_START((std::string("Attempted to stop write txn when no such txn exists in ")+__FUNCTION__).c_str()));
4244  if (m_writer != boost::this_thread::get_id())
4245  throw0(DB_ERROR_TXN_START((std::string("Attempted to stop write txn from the wrong thread in ")+__FUNCTION__).c_str()));
4246  {
4247  if (! m_batch_active)
4248  {
4249  TIME_MEASURE_START(time1);
4250  m_write_txn->commit();
4251  TIME_MEASURE_FINISH(time1);
4252  time_commit1 += time1;
4253 
4254  delete m_write_txn;
4255  m_write_txn = nullptr;
4256  memset(&m_wcursors, 0, sizeof(m_wcursors));
4257  }
4258  }
4259 }
Here is the call graph for this function:
Here is the caller graph for this function:

◆ can_thread_bulk_indices()

virtual bool cryptonote::BlockchainLMDB::can_thread_bulk_indices ( ) const
inlinevirtual

Implements cryptonote::BlockchainDB.

Definition at line 339 of file db_lmdb.h.

339 { return true; }

◆ check_pruning()

bool cryptonote::BlockchainLMDB::check_pruning ( )
virtual

checks pruning was done correctly, iff enabled

Returns
success iff true

Implements cryptonote::BlockchainDB.

Definition at line 2736 of file db_lmdb.cpp.

2737 {
2738  return prune_worker(prune_mode_check, 0);
2739 }
@ prune_mode_check
Definition: db_lmdb.cpp:2441

◆ close()

void cryptonote::BlockchainLMDB::close ( )
virtual

close the BlockchainDB

At minimum, this call ensures that further use of the BlockchainDB instance will not have effect. In any case where it is necessary to do so, a subclass implementing this will sync with disk.

If any of this cannot be done, the subclass should throw the corresponding subclass of DB_EXCEPTION

Implements cryptonote::BlockchainDB.

Definition at line 1605 of file db_lmdb.cpp.

1606 {
1607  LOG_PRINT_L3("BlockchainLMDB::" << __func__);
1608  if (m_batch_active)
1609  {
1610  LOG_PRINT_L3("close() first calling batch_abort() due to active batch transaction");
1611  batch_abort();
1612  }
1613  this->sync();
1614  m_tinfo.reset();
1615 
1616  // FIXME: not yet thread safe!!! Use with care.
1617  mdb_env_close(m_env);
1618  m_open = false;
1619 }
virtual void sync()
sync the BlockchainDB with disk
Definition: db_lmdb.cpp:1621
void mdb_env_close(MDB_env *env)
Close the environment and release the memory map.
Here is the call graph for this function:

◆ compare_data()

int cryptonote::BlockchainLMDB::compare_data ( const MDB_val a,
const MDB_val b 
)
static

Definition at line 172 of file db_lmdb.cpp.

173 {
174  size_t size = std::max(a->mv_size, b->mv_size);
175 
176  uint8_t *va = (uint8_t*) a->mv_data;
177  uint8_t *vb = (uint8_t*) b->mv_data;
178  for (size_t n = 0; n < size; ++n)
179  {
180  if (va[n] == vb[n])
181  continue;
182  return va[n] < vb[n] ? -1 : 1;
183  }
184 
185  return 0;
186 }
void * mv_data
Definition: lmdb.h:288
size_t mv_size
Definition: lmdb.h:287
const GenericPointer< typename T::ValueType > T2 T::AllocatorType & a
Definition: pointer.h:1124
unsigned char uint8_t
Definition: stdint.h:124

◆ compare_hash32()

int cryptonote::BlockchainLMDB::compare_hash32 ( const MDB_val a,
const MDB_val b 
)
static

Definition at line 151 of file db_lmdb.cpp.

152 {
153  uint32_t *va = (uint32_t*) a->mv_data;
154  uint32_t *vb = (uint32_t*) b->mv_data;
155  for (int n = 7; n >= 0; n--)
156  {
157  if (va[n] == vb[n])
158  continue;
159  return va[n] < vb[n] ? -1 : 1;
160  }
161 
162  return 0;
163 }
unsigned int uint32_t
Definition: stdint.h:126

◆ compare_publickey()

int cryptonote::BlockchainLMDB::compare_publickey ( const MDB_val a,
const MDB_val b 
)
static

Definition at line 188 of file db_lmdb.cpp.

189 {
190  uint8_t *va = (uint8_t*) a->mv_data;
191  uint8_t *vb = (uint8_t*) b->mv_data;
192  for (int n = 0; n < 32; ++n)
193  {
194  if (va[n] == vb[n])
195  continue;
196  return va[n] < vb[n] ? -1 : 1;
197  }
198 
199  return 0;
200 }

◆ compare_string()

int cryptonote::BlockchainLMDB::compare_string ( const MDB_val a,
const MDB_val b 
)
static

Definition at line 165 of file db_lmdb.cpp.

166 {
167  const char *va = (const char*) a->mv_data;
168  const char *vb = (const char*) b->mv_data;
169  return strcmp(va, vb);
170 }

◆ compare_uint64()

int cryptonote::BlockchainLMDB::compare_uint64 ( const MDB_val a,
const MDB_val b 
)
static

Definition at line 143 of file db_lmdb.cpp.

144 {
145  uint64_t va, vb;
146  memcpy(&va, a->mv_data, sizeof(va));
147  memcpy(&vb, b->mv_data, sizeof(vb));
148  return (va < vb) ? -1 : va > vb;
149 }
void * memcpy(void *a, const void *b, size_t c)
Here is the call graph for this function:

◆ for_all_key_images()

bool cryptonote::BlockchainLMDB::for_all_key_images ( std::function< bool(const crypto::key_image &)>  ) const
virtual

runs a function over all key images stored

The subclass should run the passed function for each key image it has stored, passing the key image as its parameter.

If any call to the function returns false, the subclass should return false. Otherwise, the subclass returns true.

Parameters
std::functionfn the function to run
Returns
false if the function returns false for any key image, otherwise true

Implements cryptonote::BlockchainDB.

Definition at line 3789 of file db_lmdb.cpp.

3790 {
3791  LOG_PRINT_L3("BlockchainLMDB::" << __func__);
3792  check_open();
3793 
3795  RCURSOR(spent_keys);
3796 
3797  MDB_val k, v;
3798  bool fret = true;
3799 
3800  k = zerokval;
3801  MDB_cursor_op op = MDB_FIRST;
3802  while (1)
3803  {
3804  int ret = mdb_cursor_get(m_cur_spent_keys, &k, &v, op);
3805  op = MDB_NEXT;
3806  if (ret == MDB_NOTFOUND)
3807  break;
3808  if (ret < 0)
3809  throw0(DB_ERROR("Failed to enumerate key images"));
3810  const crypto::key_image k_image = *(const crypto::key_image*)v.mv_data;
3811  if (!f(k_image)) {
3812  fret = false;
3813  break;
3814  }
3815  }
3816 
3818 
3819  return fret;
3820 }
else if(0==res)
#define m_cur_spent_keys
Definition: db_lmdb.h:92
MDB_cursor_op
Cursor Get operations.
Definition: lmdb.h:398
@ MDB_FIRST
Definition: lmdb.h:399
@ MDB_NEXT
Definition: lmdb.h:411
POD_CLASS key_image
Definition: crypto.h:102

◆ for_all_outputs() [1/2]

bool cryptonote::BlockchainLMDB::for_all_outputs ( std::function< bool(uint64_t amount, const crypto::hash &tx_hash, uint64_t height, size_t tx_idx)>  f) const
virtual

runs a function over all outputs stored

The subclass should run the passed function for each output it has stored, passing (amount, transaction_hash, tx_local_output_index) as its parameters.

If any call to the function returns false, the subclass should return false. Otherwise, the subclass returns true.

The subclass should throw DB_ERROR if any of the expected values are not found. Current implementations simply return false.

Parameters
std::functionf the function to run
Returns
false if the function returns false for any output, otherwise true

Implements cryptonote::BlockchainDB.

Definition at line 3935 of file db_lmdb.cpp.

3936 {
3937  LOG_PRINT_L3("BlockchainLMDB::" << __func__);
3938  check_open();
3939 
3941  RCURSOR(output_amounts);
3942 
3943  MDB_val k;
3944  MDB_val v;
3945  bool fret = true;
3946 
3947  MDB_cursor_op op = MDB_FIRST;
3948  while (1)
3949  {
3950  int ret = mdb_cursor_get(m_cur_output_amounts, &k, &v, op);
3951  op = MDB_NEXT;
3952  if (ret == MDB_NOTFOUND)
3953  break;
3954  if (ret)
3955  throw0(DB_ERROR("Failed to enumerate outputs"));
3956  uint64_t amount = *(const uint64_t*)k.mv_data;
3957  outkey *ok = (outkey *)v.mv_data;
3959  if (!f(amount, toi.first, ok->data.height, toi.second)) {
3960  fret = false;
3961  break;
3962  }
3963  }
3964 
3966 
3967  return fret;
3968 }
virtual tx_out_index get_output_tx_and_index_from_global(const uint64_t &index) const
gets an output's tx hash and index
Definition: db_lmdb.cpp:3693
#define m_cur_output_amounts
Definition: db_lmdb.h:84
struct cryptonote::outkey outkey
std::pair< crypto::hash, uint64_t > tx_out_index
Here is the call graph for this function:

◆ for_all_outputs() [2/2]

bool cryptonote::BlockchainLMDB::for_all_outputs ( uint64_t  amount,
const std::function< bool(uint64_t height)> &  f 
) const
virtual

Implements cryptonote::BlockchainDB.

Definition at line 3970 of file db_lmdb.cpp.

3971 {
3972  LOG_PRINT_L3("BlockchainLMDB::" << __func__);
3973  check_open();
3974 
3976  RCURSOR(output_amounts);
3977 
3978  MDB_val_set(k, amount);
3979  MDB_val v;
3980  bool fret = true;
3981 
3982  MDB_cursor_op op = MDB_SET;
3983  while (1)
3984  {
3985  int ret = mdb_cursor_get(m_cur_output_amounts, &k, &v, op);
3986  op = MDB_NEXT_DUP;
3987  if (ret == MDB_NOTFOUND)
3988  break;
3989  if (ret)
3990  throw0(DB_ERROR("Failed to enumerate outputs"));
3991  uint64_t out_amount = *(const uint64_t*)k.mv_data;
3992  if (amount != out_amount)
3993  {
3994  MERROR("Amount is not the expected amount");
3995  fret = false;
3996  break;
3997  }
3998  const outkey *ok = (const outkey *)v.mv_data;
3999  if (!f(ok->data.height)) {
4000  fret = false;
4001  break;
4002  }
4003  }
4004 
4006 
4007  return fret;
4008 }
@ MDB_SET
Definition: lmdb.h:422
@ MDB_NEXT_DUP
Definition: lmdb.h:412
#define MERROR(x)
Definition: misc_log_ex.h:73
Here is the call graph for this function:

◆ for_all_transactions()

bool cryptonote::BlockchainLMDB::for_all_transactions ( std::function< bool(const crypto::hash &, const cryptonote::transaction &)>  ,
bool  pruned 
) const
virtual

runs a function over all transactions stored

The subclass should run the passed function for each transaction it has stored, passing (transaction_hash, transaction) as its parameters.

If any call to the function returns false, the subclass should return false. Otherwise, the subclass returns true.

The subclass should throw DB_ERROR if any of the expected values are not found. Current implementations simply return false.

Parameters
std::functionfn the function to run
boolpruned whether to only get pruned tx data, or the whole
Returns
false if the function returns false for any transaction, otherwise true

Implements cryptonote::BlockchainDB.

Definition at line 3873 of file db_lmdb.cpp.

3874 {
3875  LOG_PRINT_L3("BlockchainLMDB::" << __func__);
3876  check_open();
3877 
3879  RCURSOR(txs_pruned);
3880  RCURSOR(txs_prunable);
3881  RCURSOR(tx_indices);
3882 
3883  MDB_val k;
3884  MDB_val v;
3885  bool fret = true;
3886 
3887  MDB_cursor_op op = MDB_FIRST;
3888  while (1)
3889  {
3890  int ret = mdb_cursor_get(m_cur_tx_indices, &k, &v, op);
3891  op = MDB_NEXT;
3892  if (ret == MDB_NOTFOUND)
3893  break;
3894  if (ret)
3895  throw0(DB_ERROR(lmdb_error("Failed to enumerate transactions: ", ret).c_str()));
3896 
3897  txindex *ti = (txindex *)v.mv_data;
3898  const crypto::hash hash = ti->key;
3899  k.mv_data = (void *)&ti->data.tx_id;
3900  k.mv_size = sizeof(ti->data.tx_id);
3901 
3902  ret = mdb_cursor_get(m_cur_txs_pruned, &k, &v, MDB_SET);
3903  if (ret == MDB_NOTFOUND)
3904  break;
3905  if (ret)
3906  throw0(DB_ERROR(lmdb_error("Failed to enumerate transactions: ", ret).c_str()));
3907  transaction tx;
3908  blobdata bd;
3909  bd.assign(reinterpret_cast<char*>(v.mv_data), v.mv_size);
3910  if (pruned)
3911  {
3913  throw0(DB_ERROR("Failed to parse tx from blob retrieved from the db"));
3914  }
3915  else
3916  {
3917  ret = mdb_cursor_get(m_cur_txs_prunable, &k, &v, MDB_SET);
3918  if (ret)
3919  throw0(DB_ERROR(lmdb_error("Failed to get prunable tx data the db: ", ret).c_str()));
3920  bd.append(reinterpret_cast<char*>(v.mv_data), v.mv_size);
3921  if (!parse_and_validate_tx_from_blob(bd, tx))
3922  throw0(DB_ERROR("Failed to parse tx from blob retrieved from the db"));
3923  }
3924  if (!f(hash, tx)) {
3925  fret = false;
3926  break;
3927  }
3928  }
3929 
3931 
3932  return fret;
3933 }
#define m_cur_txs_prunable
Definition: db_lmdb.h:87
#define m_cur_txs_pruned
Definition: db_lmdb.h:86
#define m_cur_tx_indices
Definition: db_lmdb.h:90
POD_CLASS hash
Definition: hash.h:50
struct cryptonote::txindex txindex
std::string blobdata
Definition: blobdatatype.h:39
bool parse_and_validate_tx_from_blob(const blobdata &tx_blob, transaction &tx)
bool parse_and_validate_tx_base_from_blob(const blobdata &tx_blob, transaction &tx)
Here is the call graph for this function:

◆ for_all_txpool_txes()

bool cryptonote::BlockchainLMDB::for_all_txpool_txes ( std::function< bool(const crypto::hash &, const txpool_tx_meta_t &, const cryptonote::blobdata *)>  ,
bool  include_blob = false,
bool  include_unrelayed_txes = true 
) const
virtual

runs a function over all txpool transactions

The subclass should run the passed function for each txpool tx it has stored, passing the tx id and metadata as its parameters.

If any call to the function returns false, the subclass should return false. Otherwise, the subclass returns true.

Parameters
std::functionfn the function to run
Returns
false if the function returns false for any transaction, otherwise true

Implements cryptonote::BlockchainDB.

Definition at line 2741 of file db_lmdb.cpp.

2742 {
2743  LOG_PRINT_L3("BlockchainLMDB::" << __func__);
2744  check_open();
2745 
2747  RCURSOR(txpool_meta);
2748  RCURSOR(txpool_blob);
2749 
2750  MDB_val k;
2751  MDB_val v;
2752  bool ret = true;
2753 
2754  MDB_cursor_op op = MDB_FIRST;
2755  while (1)
2756  {
2757  int result = mdb_cursor_get(m_cur_txpool_meta, &k, &v, op);
2758  op = MDB_NEXT;
2759  if (result == MDB_NOTFOUND)
2760  break;
2761  if (result)
2762  throw0(DB_ERROR(lmdb_error("Failed to enumerate txpool tx metadata: ", result).c_str()));
2763  const crypto::hash txid = *(const crypto::hash*)k.mv_data;
2764  const txpool_tx_meta_t &meta = *(const txpool_tx_meta_t*)v.mv_data;
2765  if (!include_unrelayed_txes && meta.do_not_relay)
2766  // Skipping that tx
2767  continue;
2768  const cryptonote::blobdata *passed_bd = NULL;
2770  if (include_blob)
2771  {
2772  MDB_val b;
2773  result = mdb_cursor_get(m_cur_txpool_blob, &k, &b, MDB_SET);
2774  if (result == MDB_NOTFOUND)
2775  throw0(DB_ERROR("Failed to find txpool tx blob to match metadata"));
2776  if (result)
2777  throw0(DB_ERROR(lmdb_error("Failed to enumerate txpool tx blob: ", result).c_str()));
2778  bd.assign(reinterpret_cast<const char*>(b.mv_data), b.mv_size);
2779  passed_bd = &bd;
2780  }
2781 
2782  if (!f(txid, meta, passed_bd)) {
2783  ret = false;
2784  break;
2785  }
2786  }
2787 
2789 
2790  return ret;
2791 }
Here is the call graph for this function:

◆ for_blocks_range()

bool cryptonote::BlockchainLMDB::for_blocks_range ( const uint64_t h1,
const uint64_t h2,
std::function< bool(uint64_t, const crypto::hash &, const cryptonote::block &)>   
) const
virtual

runs a function over a range of blocks

The subclass should run the passed function for each block in the specified range, passing (block_height, block_hash, block) as its parameters.

If any call to the function returns false, the subclass should return false. Otherwise, the subclass returns true.

The subclass should throw DB_ERROR if any of the expected values are not found. Current implementations simply return false.

Parameters
h1the start height
h2the end height
std::functionfn the function to run
Returns
false if the function returns false for any block, otherwise true

Implements cryptonote::BlockchainDB.

Definition at line 3822 of file db_lmdb.cpp.

3823 {
3824  LOG_PRINT_L3("BlockchainLMDB::" << __func__);
3825  check_open();
3826 
3828  RCURSOR(blocks);
3829 
3830  MDB_val k;
3831  MDB_val v;
3832  bool fret = true;
3833 
3834  MDB_cursor_op op;
3835  if (h1)
3836  {
3837  k = MDB_val{sizeof(h1), (void*)&h1};
3838  op = MDB_SET;
3839  } else
3840  {
3841  op = MDB_FIRST;
3842  }
3843  while (1)
3844  {
3845  int ret = mdb_cursor_get(m_cur_blocks, &k, &v, op);
3846  op = MDB_NEXT;
3847  if (ret == MDB_NOTFOUND)
3848  break;
3849  if (ret)
3850  throw0(DB_ERROR("Failed to enumerate blocks"));
3851  uint64_t height = *(const uint64_t*)k.mv_data;
3852  blobdata bd;
3853  bd.assign(reinterpret_cast<char*>(v.mv_data), v.mv_size);
3854  block b;
3856  throw0(DB_ERROR("Failed to parse block from blob retrieved from the db"));
3858  if (!get_block_hash(b, hash))
3859  throw0(DB_ERROR("Failed to get block hash from blob retrieved from the db"));
3860  if (!f(height, hash, b)) {
3861  fret = false;
3862  break;
3863  }
3864  if (height >= h2)
3865  break;
3866  }
3867 
3869 
3870  return fret;
3871 }
#define m_cur_blocks
Definition: db_lmdb.h:80
bool get_block_hash(const block &b, crypto::hash &res)
bool parse_and_validate_block_from_blob(const blobdata &b_blob, block &b, crypto::hash *block_hash)
Here is the call graph for this function:

◆ get_addr_output_all()

std::vector< address_outputs > cryptonote::BlockchainLMDB::get_addr_output_all ( const crypto::public_key combined_key)
virtual

Implements cryptonote::BlockchainDB.

Definition at line 2040 of file db_lmdb.cpp.

2041 {
2042  LOG_PRINT_L3("BlockchainLMDB::" << __func__);
2043  check_open();
2044 
2046  RCURSOR(addr_outputs);
2047 
2048  int result = 0;
2049  std::vector<address_outputs> address_outputs;
2050 
2051  MDB_val k = {sizeof(combined_key), (void *)&combined_key};
2052 
2054  while (1) {
2055  MDB_val v;
2056  int ret = mdb_cursor_get(m_cur_addr_outputs, &k, &v, op);
2057  op = MDB_NEXT_DUP;
2058  if (ret == MDB_NOTFOUND)
2059  break;
2060  if (ret)
2061  throw0(DB_ERROR("Failed to enumerate address outputs"));
2062 
2063  const acc_outs_t res = *(const acc_outs_t *) v.mv_data;
2064 
2065  cryptonote::address_outputs addr_out;
2066  addr_out.out_id = res.db_index;
2067  addr_out.tx_hash = res.tx_hash;
2068  addr_out.relative_out_index = res.relative_out_index;
2069  addr_out.amount = res.amount;
2070  addr_out.spent = !check_chainstate_utxo(res.tx_hash, res.relative_out_index);
2071 
2072  address_outputs.push_back(addr_out);
2073 
2074  }
2075 
2077 
2078  return address_outputs;
2079 }
#define m_cur_addr_outputs
Definition: db_lmdb.h:99
@ MDB_SET_KEY
Definition: lmdb.h:423
const char * res
Definition: hmac_keccak.cpp:41
struct cryptonote::acc_outs_t acc_outs_t
Here is the call graph for this function:

◆ get_addr_output_batch()

std::vector< address_outputs > cryptonote::BlockchainLMDB::get_addr_output_batch ( const crypto::public_key combined_key,
uint64_t  start_db_index = 0,
uint64_t  batch_size = 100,
bool  desc = false 
)
virtual

Implements cryptonote::BlockchainDB.

Definition at line 2081 of file db_lmdb.cpp.

2082 {
2083  LOG_PRINT_L3("BlockchainLMDB::" << __func__);
2084  check_open();
2085 
2087  RCURSOR(addr_outputs);
2088 
2089  std::vector<address_outputs> address_outputs;
2090 
2091  MDB_val k = {sizeof(combined_key), (void *)&combined_key};
2092  MDB_val v;
2093 
2094  MDB_cursor_op op;
2095  if (start_db_index)
2096  op = MDB_GET_BOTH;
2097  else
2098  {
2099  op = desc ? MDB_LAST_DUP : MDB_FIRST_DUP;
2100  int result = mdb_cursor_get(m_cur_addr_outputs, &k, &v, MDB_SET_KEY);
2101  if (result != 0 && result != MDB_NOTFOUND)
2102  throw1(DB_ERROR(lmdb_error("Failed to enumerate address outputs", result).c_str()));
2103  }
2104 
2105  std::set<std::string> tx_hashes;
2106  for(size_t i = 0; i < batch_size + 1; ++i) {
2107  if(op == MDB_GET_BOTH)
2108  v = MDB_val{sizeof(start_db_index), (void*)&start_db_index};
2109 
2110  int ret = mdb_cursor_get(m_cur_addr_outputs, &k, &v, op);
2111  op = desc ? MDB_PREV_DUP : MDB_NEXT_DUP;
2112  if (ret == MDB_NOTFOUND)
2113  break;
2114  if (ret)
2115  throw0(DB_ERROR("Failed to enumerate address outputs"));
2116 
2117  const acc_outs_t res = *(const acc_outs_t *) v.mv_data;
2118 
2119  std::string tx_hash_hex = epee::string_tools::pod_to_hex(res.tx_hash);
2120  if(tx_hashes.find(tx_hash_hex) != tx_hashes.end())
2121  {
2122  --i;
2123  continue;
2124  }
2125 
2126  cryptonote::address_outputs addr_out;
2127  addr_out.out_id = res.db_index;
2128  addr_out.tx_hash = res.tx_hash;
2129  addr_out.relative_out_index = res.relative_out_index;
2130  addr_out.amount = res.amount;
2131  addr_out.spent = !check_chainstate_utxo(res.tx_hash, res.relative_out_index);
2132 
2133  address_outputs.push_back(addr_out);
2134  tx_hashes.emplace(tx_hash_hex);
2135  }
2136 
2138  return address_outputs;
2139 }
@ MDB_FIRST_DUP
Definition: lmdb.h:400
@ MDB_LAST_DUP
Definition: lmdb.h:409
@ MDB_PREV_DUP
Definition: lmdb.h:419
Here is the call graph for this function:

◆ get_balance()

uint64_t cryptonote::BlockchainLMDB::get_balance ( const crypto::public_key combined_key)
virtual

Implements cryptonote::BlockchainDB.

Definition at line 2141 of file db_lmdb.cpp.

2142 {
2143  LOG_PRINT_L3("BlockchainLMDB::" << __func__);
2144  check_open();
2145 
2147  RCURSOR(addr_outputs);
2148 
2149  uint64_t balance = 0;
2150 
2151  MDB_val k = {sizeof(combined_key), (void *)&combined_key};
2152 
2154  while (1) {
2155  MDB_val v;
2156  int ret = mdb_cursor_get(m_cur_addr_outputs, &k, &v, op);
2157  op = MDB_NEXT_DUP;
2158  if (ret == MDB_NOTFOUND)
2159  break;
2160  if (ret)
2161  throw0(DB_ERROR("Failed to enumerate address outputs"));
2162 
2163  const acc_outs_t res = *(const acc_outs_t *) v.mv_data;
2164 
2165  if(check_chainstate_utxo(res.tx_hash, res.relative_out_index))
2166  balance += res.amount;
2167  }
2168 
2170 
2171  return balance;
2172 }
Here is the call graph for this function:

◆ get_block_already_generated_coins()

uint64_t cryptonote::BlockchainLMDB::get_block_already_generated_coins ( const uint64_t height) const
virtual

fetch a block's already generated coins

The subclass should return the total coins generated as of the block with the given height.

If the block does not exist, the subclass should throw BLOCK_DNE

Parameters
heightthe height requested
Returns
the already generated coins

Implements cryptonote::BlockchainDB.

Definition at line 3205 of file db_lmdb.cpp.

3206 {
3207  LOG_PRINT_L3("BlockchainLMDB::" << __func__);
3208  check_open();
3209 
3211  RCURSOR(block_info);
3212 
3213  MDB_val_set(result, height);
3214  auto get_result = mdb_cursor_get(m_cur_block_info, (MDB_val *)&zerokval, &result, MDB_GET_BOTH);
3215  if (get_result == MDB_NOTFOUND)
3216  {
3217  throw0(BLOCK_DNE(std::string("Attempt to get generated coins from height ").append(boost::lexical_cast<std::string>(height)).append(" failed -- block size not in db").c_str()));
3218  }
3219  else if (get_result)
3220  throw0(DB_ERROR("Error attempting to retrieve a total generated coins from the db"));
3221 
3222  mdb_block_info *bi = (mdb_block_info *)result.mv_data;
3223  uint64_t ret = bi->bi_coins;
3225  return ret;
3226 }
#define m_cur_block_info
Definition: db_lmdb.h:82
mdb_block_info_4 mdb_block_info
Definition: db_lmdb.cpp:353
Here is the call graph for this function:

◆ get_block_blob()

cryptonote::blobdata cryptonote::BlockchainLMDB::get_block_blob ( const crypto::hash h) const
virtual

fetches the block with the given hash

The subclass should return the requested block.

If the block does not exist, the subclass should throw BLOCK_DNE

Parameters
hthe hash to look for
Returns
the block requested

Implements cryptonote::BlockchainDB.

Definition at line 2824 of file db_lmdb.cpp.

2825 {
2826  LOG_PRINT_L3("BlockchainLMDB::" << __func__);
2827  check_open();
2828 
2830 }
virtual uint64_t get_block_height(const crypto::hash &h) const
gets the height of the block with a given hash
Definition: db_lmdb.cpp:2832
virtual cryptonote::blobdata get_block_blob_from_height(const uint64_t &height) const
fetch a block blob by height
Definition: db_lmdb.cpp:2862
Here is the call graph for this function:

◆ get_block_blob_from_height()

cryptonote::blobdata cryptonote::BlockchainLMDB::get_block_blob_from_height ( const uint64_t height) const
virtual

fetch a block blob by height

The subclass should return the block at the given height.

If the block does not exist, that is to say if the blockchain is not that high, then the subclass should throw BLOCK_DNE

Parameters
heightthe height to look for
Returns
the block blob

Implements cryptonote::BlockchainDB.

Definition at line 2862 of file db_lmdb.cpp.

2863 {
2864  LOG_PRINT_L3("BlockchainLMDB::" << __func__);
2865  check_open();
2866 
2868  RCURSOR(blocks);
2869 
2870  MDB_val_copy<uint64_t> key(height);
2871  MDB_val result;
2872  auto get_result = mdb_cursor_get(m_cur_blocks, &key, &result, MDB_SET);
2873  if (get_result == MDB_NOTFOUND)
2874  {
2875  throw0(BLOCK_DNE(std::string("Attempt to get block from height ").append(boost::lexical_cast<std::string>(height)).append(" failed -- block not in db").c_str()));
2876  }
2877  else if (get_result)
2878  throw0(DB_ERROR("Error attempting to retrieve a block from the db"));
2879 
2880  blobdata bd;
2881  bd.assign(reinterpret_cast<char*>(result.mv_data), result.mv_size);
2882 
2884 
2885  return bd;
2886 }
Here is the call graph for this function:
Here is the caller graph for this function:

◆ get_block_cumulative_difficulty()

difficulty_type cryptonote::BlockchainLMDB::get_block_cumulative_difficulty ( const uint64_t height) const
virtual

fetch a block's cumulative difficulty

The subclass should return the cumulative difficulty of the block with the given height.

If the block does not exist, the subclass should throw BLOCK_DNE

Parameters
heightthe height requested
Returns
the cumulative difficulty

Implements cryptonote::BlockchainDB.

Definition at line 3163 of file db_lmdb.cpp.

3164 {
3165  LOG_PRINT_L3("BlockchainLMDB::" << __func__ << " height: " << height);
3166  check_open();
3167 
3169  RCURSOR(block_info);
3170 
3171  MDB_val_set(result, height);
3172  auto get_result = mdb_cursor_get(m_cur_block_info, (MDB_val *)&zerokval, &result, MDB_GET_BOTH);
3173  if (get_result == MDB_NOTFOUND)
3174  {
3175  throw0(BLOCK_DNE(std::string("Attempt to get cumulative difficulty from height ").append(boost::lexical_cast<std::string>(height)).append(" failed -- difficulty not in db").c_str()));
3176  }
3177  else if (get_result)
3178  throw0(DB_ERROR("Error attempting to retrieve a cumulative difficulty from the db"));
3179 
3180  mdb_block_info *bi = (mdb_block_info *)result.mv_data;
3181  difficulty_type ret = bi->bi_diff_hi;
3182  ret <<= 64;
3183  ret |= bi->bi_diff_lo;
3185  return ret;
3186 }
boost::multiprecision::uint128_t difficulty_type
Definition: difficulty.h:43
Here is the call graph for this function:
Here is the caller graph for this function:

◆ get_block_cumulative_rct_outputs()

std::vector< uint64_t > cryptonote::BlockchainLMDB::get_block_cumulative_rct_outputs ( const std::vector< uint64_t > &  heights) const
virtual

fetch a block's cumulative number of rct outputs

The subclass should return the numer of rct outputs in the blockchain up to the block with the given height (inclusive).

If the block does not exist, the subclass should throw BLOCK_DNE

Parameters
heightthe height requested
Returns
the cumulative number of rct outputs

Implements cryptonote::BlockchainDB.

Definition at line 2911 of file db_lmdb.cpp.

2912 {
2913  LOG_PRINT_L3("BlockchainLMDB::" << __func__);
2914  check_open();
2915  std::vector<uint64_t> res;
2916  int result;
2917 
2918  if (heights.empty())
2919  return {};
2920  res.reserve(heights.size());
2921 
2923  RCURSOR(block_info);
2924 
2925  MDB_stat db_stats;
2926  if ((result = mdb_stat(m_txn, m_blocks, &db_stats)))
2927  throw0(DB_ERROR(lmdb_error("Failed to query m_blocks: ", result).c_str()));
2928  for (size_t i = 0; i < heights.size(); ++i)
2929  if (heights[i] >= db_stats.ms_entries)
2930  throw0(BLOCK_DNE(std::string("Attempt to get rct distribution from height " + std::to_string(heights[i]) + " failed -- block size not in db").c_str()));
2931 
2932  MDB_val v;
2933 
2934  uint64_t prev_height = heights[0];
2935  uint64_t range_begin = 0, range_end = 0;
2936  for (uint64_t height: heights)
2937  {
2938  if (height >= range_begin && height < range_end)
2939  {
2940  // nohting to do
2941  }
2942  else
2943  {
2944  if (height == prev_height + 1)
2945  {
2946  MDB_val k2;
2948  range_begin = ((const mdb_block_info*)v.mv_data)->bi_height;
2949  range_end = range_begin + v.mv_size / sizeof(mdb_block_info); // whole records please
2950  if (height < range_begin || height >= range_end)
2951  throw0(DB_ERROR(("Height " + std::to_string(height) + " not included in multuple record range: " + std::to_string(range_begin) + "-" + std::to_string(range_end)).c_str()));
2952  }
2953  else
2954  {
2955  v.mv_size = sizeof(uint64_t);
2956  v.mv_data = (void*)&height;
2957  result = mdb_cursor_get(m_cur_block_info, (MDB_val *)&zerokval, &v, MDB_GET_BOTH);
2958  range_begin = height;
2959  range_end = range_begin + 1;
2960  }
2961  if (result)
2962  throw0(DB_ERROR(lmdb_error("Error attempting to retrieve rct distribution from the db: ", result).c_str()));
2963  }
2964  const mdb_block_info *bi = ((const mdb_block_info *)v.mv_data) + (height - range_begin);
2965  res.push_back(bi->bi_cum_rct);
2966  prev_height = height;
2967  }
2968 
2970  return res;
2971 }
int mdb_stat(MDB_txn *txn, MDB_dbi dbi, MDB_stat *stat)
Retrieve statistics for a database.
@ MDB_NEXT_MULTIPLE
Definition: lmdb.h:414
mdb_size_t ms_entries
Definition: lmdb.h:497
std::string to_string(t_connection_type type)
Statistics for a database in the environment.
Definition: lmdb.h:490
Here is the call graph for this function:

◆ get_block_difficulty()

difficulty_type cryptonote::BlockchainLMDB::get_block_difficulty ( const uint64_t height) const
virtual

fetch a block's difficulty

The subclass should return the difficulty of the block with the given height.

If the block does not exist, the subclass should throw BLOCK_DNE

Parameters
heightthe height requested
Returns
the difficulty

Implements cryptonote::BlockchainDB.

Definition at line 3188 of file db_lmdb.cpp.

3189 {
3190  LOG_PRINT_L3("BlockchainLMDB::" << __func__);
3191  check_open();
3192 
3193  difficulty_type diff1 = 0;
3194  difficulty_type diff2 = 0;
3195 
3197  if (height != 0)
3198  {
3200  }
3201 
3202  return diff1 - diff2;
3203 }
virtual difficulty_type get_block_cumulative_difficulty(const uint64_t &height) const
fetch a block's cumulative difficulty
Definition: db_lmdb.cpp:3163
Here is the call graph for this function:

◆ get_block_hash_from_height()

crypto::hash cryptonote::BlockchainLMDB::get_block_hash_from_height ( const uint64_t height) const
virtual

fetch a block's hash

The subclass should return hash of the block with the given height.

If the block does not exist, the subclass should throw BLOCK_DNE

Parameters
heightthe height requested
Returns
the hash

Implements cryptonote::BlockchainDB.

Definition at line 3251 of file db_lmdb.cpp.

3252 {
3253  LOG_PRINT_L3("BlockchainLMDB::" << __func__);
3254  check_open();
3255 
3257  RCURSOR(block_info);
3258 
3259  MDB_val_set(result, height);
3260  auto get_result = mdb_cursor_get(m_cur_block_info, (MDB_val *)&zerokval, &result, MDB_GET_BOTH);
3261  if (get_result == MDB_NOTFOUND)
3262  {
3263  throw0(BLOCK_DNE(std::string("Attempt to get hash from height ").append(boost::lexical_cast<std::string>(height)).append(" failed -- hash not in db").c_str()));
3264  }
3265  else if (get_result)
3266  throw0(DB_ERROR(lmdb_error("Error attempting to retrieve a block hash from the db: ", get_result).c_str()));
3267 
3268  mdb_block_info *bi = (mdb_block_info *)result.mv_data;
3269  crypto::hash ret = bi->bi_hash;
3271  return ret;
3272 }
Here is the call graph for this function:
Here is the caller graph for this function:

◆ get_block_header()

block_header cryptonote::BlockchainLMDB::get_block_header ( const crypto::hash h) const
virtual

fetch a block header

The subclass should return the block header from the block with the given hash.

If the block does not exist, the subclass should throw BLOCK_DNE

Parameters
hthe hash to look for
Returns
the block header

Implements cryptonote::BlockchainDB.

Definition at line 2853 of file db_lmdb.cpp.

2854 {
2855  LOG_PRINT_L3("BlockchainLMDB::" << __func__);
2856  check_open();
2857 
2858  // block_header object is automatically cast from block object
2859  return get_block(h);
2860 }
virtual block get_block(const crypto::hash &h) const
fetches the block with the given hash
Here is the call graph for this function:

◆ get_block_height()

uint64_t cryptonote::BlockchainLMDB::get_block_height ( const crypto::hash h) const
virtual

gets the height of the block with a given hash

The subclass should return the requested height.

If the block does not exist, the subclass should throw BLOCK_DNE

Parameters
hthe hash to look for
Returns
the height

Implements cryptonote::BlockchainDB.

Definition at line 2832 of file db_lmdb.cpp.

2833 {
2834  LOG_PRINT_L3("BlockchainLMDB::" << __func__);
2835  check_open();
2836 
2838  RCURSOR(block_heights);
2839 
2840  MDB_val_set(key, h);
2841  auto get_result = mdb_cursor_get(m_cur_block_heights, (MDB_val *)&zerokval, &key, MDB_GET_BOTH);
2842  if (get_result == MDB_NOTFOUND)
2843  throw1(BLOCK_DNE("Attempted to retrieve non-existent block height"));
2844  else if (get_result)
2845  throw0(DB_ERROR("Error attempting to retrieve a block height from the db"));
2846 
2847  blk_height *bhp = (blk_height *)key.mv_data;
2848  uint64_t ret = bhp->bh_height;
2850  return ret;
2851 }
Here is the call graph for this function:
Here is the caller graph for this function:

◆ get_block_long_term_weight()

uint64_t cryptonote::BlockchainLMDB::get_block_long_term_weight ( const uint64_t height) const
virtual

fetch a block's long term weight

If the block does not exist, the subclass should throw BLOCK_DNE

Parameters
heightthe height requested
Returns
the long term weight

Implements cryptonote::BlockchainDB.

Definition at line 3228 of file db_lmdb.cpp.

3229 {
3230  LOG_PRINT_L3("BlockchainLMDB::" << __func__);
3231  check_open();
3232 
3234  RCURSOR(block_info);
3235 
3236  MDB_val_set(result, height);
3237  auto get_result = mdb_cursor_get(m_cur_block_info, (MDB_val *)&zerokval, &result, MDB_GET_BOTH);
3238  if (get_result == MDB_NOTFOUND)
3239  {
3240  throw0(BLOCK_DNE(std::string("Attempt to get block long term weight from height ").append(boost::lexical_cast<std::string>(height)).append(" failed -- block info not in db").c_str()));
3241  }
3242  else if (get_result)
3243  throw0(DB_ERROR("Error attempting to retrieve a long term block weight from the db"));
3244 
3245  mdb_block_info *bi = (mdb_block_info *)result.mv_data;
3248  return ret;
3249 }
Here is the call graph for this function:

◆ get_block_timestamp()

uint64_t cryptonote::BlockchainLMDB::get_block_timestamp ( const uint64_t height) const
virtual

fetch a block's timestamp

The subclass should return the timestamp of the block with the given height.

If the block does not exist, the subclass should throw BLOCK_DNE

Parameters
heightthe height requested
Returns
the timestamp

Implements cryptonote::BlockchainDB.

Definition at line 2888 of file db_lmdb.cpp.

2889 {
2890  LOG_PRINT_L3("BlockchainLMDB::" << __func__);
2891  check_open();
2892 
2894  RCURSOR(block_info);
2895 
2896  MDB_val_set(result, height);
2897  auto get_result = mdb_cursor_get(m_cur_block_info, (MDB_val *)&zerokval, &result, MDB_GET_BOTH);
2898  if (get_result == MDB_NOTFOUND)
2899  {
2900  throw0(BLOCK_DNE(std::string("Attempt to get timestamp from height ").append(boost::lexical_cast<std::string>(height)).append(" failed -- timestamp not in db").c_str()));
2901  }
2902  else if (get_result)
2903  throw0(DB_ERROR("Error attempting to retrieve a timestamp from the db"));
2904 
2905  mdb_block_info *bi = (mdb_block_info *)result.mv_data;
2906  uint64_t ret = bi->bi_timestamp;
2908  return ret;
2909 }
Here is the call graph for this function:
Here is the caller graph for this function:

◆ get_block_weight()

size_t cryptonote::BlockchainLMDB::get_block_weight ( const uint64_t height) const
virtual

fetch a block's weight

The subclass should return the weight of the block with the given height.

If the block does not exist, the subclass should throw BLOCK_DNE

Parameters
heightthe height requested
Returns
the weight

Implements cryptonote::BlockchainDB.

Definition at line 2988 of file db_lmdb.cpp.

2989 {
2990  LOG_PRINT_L3("BlockchainLMDB::" << __func__);
2991  check_open();
2992 
2994  RCURSOR(block_info);
2995 
2996  MDB_val_set(result, height);
2997  auto get_result = mdb_cursor_get(m_cur_block_info, (MDB_val *)&zerokval, &result, MDB_GET_BOTH);
2998  if (get_result == MDB_NOTFOUND)
2999  {
3000  throw0(BLOCK_DNE(std::string("Attempt to get block size from height ").append(boost::lexical_cast<std::string>(height)).append(" failed -- block size not in db").c_str()));
3001  }
3002  else if (get_result)
3003  throw0(DB_ERROR("Error attempting to retrieve a block size from the db"));
3004 
3005  mdb_block_info *bi = (mdb_block_info *)result.mv_data;
3006  size_t ret = bi->bi_weight;
3008  return ret;
3009 }
Here is the call graph for this function:

◆ get_block_weights()

std::vector< uint64_t > cryptonote::BlockchainLMDB::get_block_weights ( uint64_t  start_height,
size_t  count 
) const
virtual

fetch the last N blocks' weights

If there are fewer than N blocks, the returned array will be smaller than N

Parameters
countthe number of blocks requested
Returns
the weights

Implements cryptonote::BlockchainDB.

Definition at line 3117 of file db_lmdb.cpp.

3118 {
3119  return get_block_info_64bit_fields(start_height, count, offsetof(mdb_block_info, bi_weight));
3120 }
mdb_size_t count(MDB_cursor *cur)
Here is the call graph for this function:

◆ get_blockchain_pruning_seed()

uint32_t cryptonote::BlockchainLMDB::get_blockchain_pruning_seed ( ) const
virtual

get the blockchain pruning seed

Returns
the blockchain pruning seed

Implements cryptonote::BlockchainDB.

Definition at line 2408 of file db_lmdb.cpp.

2409 {
2410  LOG_PRINT_L3("BlockchainLMDB::" << __func__);
2411  check_open();
2412 
2414  RCURSOR(properties)
2415  MDB_val_str(k, "pruning_seed");
2416  MDB_val v;
2417  int result = mdb_cursor_get(m_cur_properties, &k, &v, MDB_SET);
2418  if (result == MDB_NOTFOUND)
2419  return 0;
2420  if (result)
2421  throw0(DB_ERROR(lmdb_error("Failed to retrieve pruning seed: ", result).c_str()));
2422  if (v.mv_size != sizeof(uint32_t))
2423  throw0(DB_ERROR("Failed to retrieve or create pruning seed: unexpected value size"));
2424  uint32_t pruning_seed;
2425  memcpy(&pruning_seed, v.mv_data, sizeof(pruning_seed));
2427  return pruning_seed;
2428 }
#define MDB_val_str(var, val)
Definition: db_lmdb.cpp:93
#define m_cur_properties
Definition: db_lmdb.h:96
Here is the call graph for this function:

◆ get_blocks_range()

std::vector< block > cryptonote::BlockchainLMDB::get_blocks_range ( const uint64_t h1,
const uint64_t h2 
) const
virtual

fetch a list of blocks

The subclass should return a vector of blocks with heights starting at h1 and ending at h2, inclusively.

If the height range requested goes past the end of the blockchain, the subclass should throw BLOCK_DNE. (current implementations simply don't catch this exception as thrown by methods called within)

Parameters
h1the start height
h2the end height
Returns
a vector of blocks

Implements cryptonote::BlockchainDB.

Definition at line 3274 of file db_lmdb.cpp.

3275 {
3276  LOG_PRINT_L3("BlockchainLMDB::" << __func__);
3277  check_open();
3278  std::vector<block> v;
3279 
3280  for (uint64_t height = h1; height <= h2; ++height)
3281  {
3282  v.push_back(get_block_from_height(height));
3283  }
3284 
3285  return v;
3286 }
virtual block get_block_from_height(const uint64_t &height) const
fetch a block by height
Here is the call graph for this function:

◆ get_db_name()

std::string cryptonote::BlockchainLMDB::get_db_name ( ) const
virtual

gets the name of the folder the BlockchainDB's file(s) should be in

The subclass implementation should return the name of the folder in which it stores files, or an empty string if there is none.

Returns
the name of the folder with the BlockchainDB's files, if any.

Implements cryptonote::BlockchainDB.

Definition at line 1732 of file db_lmdb.cpp.

1733 {
1734  LOG_PRINT_L3("BlockchainLMDB::" << __func__);
1735 
1736  return std::string("lmdb");
1737 }

◆ get_filenames()

std::vector< std::string > cryptonote::BlockchainLMDB::get_filenames ( ) const
virtual

get all files used by the BlockchainDB (if any)

This function is largely for ease of automation, namely for unit tests.

The subclass implementation should return all filenames it uses.

Returns
a list of filenames

Implements cryptonote::BlockchainDB.

Definition at line 1701 of file db_lmdb.cpp.

1702 {
1703  LOG_PRINT_L3("BlockchainLMDB::" << __func__);
1704  std::vector<std::string> filenames;
1705 
1706  boost::filesystem::path datafile(m_folder);
1708  boost::filesystem::path lockfile(m_folder);
1710 
1711  filenames.push_back(datafile.string());
1712  filenames.push_back(lockfile.string());
1713 
1714  return filenames;
1715 }
#define CRYPTONOTE_BLOCKCHAINDATA_LOCK_FILENAME
#define CRYPTONOTE_BLOCKCHAINDATA_FILENAME

◆ get_hashes_range()

std::vector< crypto::hash > cryptonote::BlockchainLMDB::get_hashes_range ( const uint64_t h1,
const uint64_t h2 
) const
virtual

fetch a list of block hashes

The subclass should return a vector of block hashes from blocks with heights starting at h1 and ending at h2, inclusively.

If the height range requested goes past the end of the blockchain, the subclass should throw BLOCK_DNE. (current implementations simply don't catch this exception as thrown by methods called within)

Parameters
h1the start height
h2the end height
Returns
a vector of block hashes

Implements cryptonote::BlockchainDB.

Definition at line 3288 of file db_lmdb.cpp.

3289 {
3290  LOG_PRINT_L3("BlockchainLMDB::" << __func__);
3291  check_open();
3292  std::vector<crypto::hash> v;
3293 
3294  for (uint64_t height = h1; height <= h2; ++height)
3295  {
3296  v.push_back(get_block_hash_from_height(height));
3297  }
3298 
3299  return v;
3300 }
virtual crypto::hash get_block_hash_from_height(const uint64_t &height) const
fetch a block's hash
Definition: db_lmdb.cpp:3251
Here is the call graph for this function:

◆ get_long_term_block_weights()

std::vector< uint64_t > cryptonote::BlockchainLMDB::get_long_term_block_weights ( uint64_t  start_height,
size_t  count 
) const
virtual

fetch the last N blocks' long term weights

If there are fewer than N blocks, the returned array will be smaller than N

Parameters
countthe number of blocks requested
Returns
the weights

Implements cryptonote::BlockchainDB.

Definition at line 3122 of file db_lmdb.cpp.

3123 {
3124  return get_block_info_64bit_fields(start_height, count, offsetof(mdb_block_info, bi_long_term_block_weight));
3125 }
Here is the call graph for this function:

◆ get_num_outputs()

uint64_t cryptonote::BlockchainLMDB::get_num_outputs ( const uint64_t amount) const
virtual

fetches the number of outputs of a given amount

The subclass should return a count of outputs of the given amount, or zero if there are none.

Parameters
amountthe output amount being looked up
Returns
the number of outputs of the given amount

Implements cryptonote::BlockchainDB.

Definition at line 3635 of file db_lmdb.cpp.

3636 {
3637  LOG_PRINT_L3("BlockchainLMDB::" << __func__);
3638  check_open();
3639 
3641  RCURSOR(output_amounts);
3642 
3643  MDB_val_copy<uint64_t> k(amount);
3644  MDB_val v;
3645  mdb_size_t num_elems = 0;
3646  auto result = mdb_cursor_get(m_cur_output_amounts, &k, &v, MDB_SET);
3647  if (result == MDB_SUCCESS)
3648  {
3650  }
3651  else if (result != MDB_NOTFOUND)
3652  throw0(DB_ERROR("DB error attempting to get number of outputs of an amount"));
3653 
3655 
3656  return num_elems;
3657 }
#define MDB_SUCCESS
Definition: lmdb.h:435
int mdb_cursor_count(MDB_cursor *cursor, mdb_size_t *countp)
Return count of duplicates for current key.
size_t mdb_size_t
Definition: lmdb.h:196
Here is the call graph for this function:
Here is the caller graph for this function:

◆ get_output_distribution()

bool cryptonote::BlockchainLMDB::get_output_distribution ( uint64_t  amount,
uint64_t  from_height,
uint64_t  to_height,
std::vector< uint64_t > &  distribution,
uint64_t base 
) const
virtual

Implements cryptonote::BlockchainDB.

Definition at line 4544 of file db_lmdb.cpp.

4545 {
4546  LOG_PRINT_L3("BlockchainLMDB::" << __func__);
4547  check_open();
4548 
4550  RCURSOR(output_amounts);
4551 
4552  distribution.clear();
4553  const uint64_t db_height = height();
4554  if (from_height >= db_height)
4555  return false;
4556  distribution.resize(db_height - from_height, 0);
4557 
4558  bool fret = true;
4559  MDB_val_set(k, amount);
4560  MDB_val v;
4561  MDB_cursor_op op = MDB_SET;
4562  base = 0;
4563  while (1)
4564  {
4565  int ret = mdb_cursor_get(m_cur_output_amounts, &k, &v, op);
4566  op = MDB_NEXT_DUP;
4567  if (ret == MDB_NOTFOUND)
4568  break;
4569  if (ret)
4570  throw0(DB_ERROR("Failed to enumerate outputs"));
4571  const outkey *ok = (const outkey *)v.mv_data;
4572  const uint64_t height = ok->data.height;
4573  if (height >= from_height)
4574  distribution[height - from_height]++;
4575  else
4576  base++;
4577  if (to_height > 0 && height > to_height)
4578  break;
4579  }
4580 
4581  distribution[0] += base;
4582  for (size_t n = 1; n < distribution.size(); ++n)
4583  distribution[n] += distribution[n - 1];
4584  base = 0;
4585 
4587 
4588  return true;
4589 }
Here is the call graph for this function:

◆ get_output_histogram()

std::map< uint64_t, std::tuple< uint64_t, uint64_t, uint64_t > > cryptonote::BlockchainLMDB::get_output_histogram ( const std::vector< uint64_t > &  amounts,
bool  unlocked,
uint64_t  recent_cutoff,
uint64_t  min_count 
) const
virtual

return a histogram of outputs on the blockchain

Parameters
amountsoptional set of amounts to lookup
unlockedwhether to restrict count to unlocked outputs
recent_cutofftimestamp to determine which outputs are recent
min_countreturn only amounts with at least that many instances
Returns
a set of amount/instances

Implements cryptonote::BlockchainDB.

Definition at line 4451 of file db_lmdb.cpp.

4452 {
4453  LOG_PRINT_L3("BlockchainLMDB::" << __func__);
4454  check_open();
4455 
4457  RCURSOR(output_amounts);
4458 
4459  std::map<uint64_t, std::tuple<uint64_t, uint64_t, uint64_t>> histogram;
4460  MDB_val k;
4461  MDB_val v;
4462 
4463  if (amounts.empty())
4464  {
4465  MDB_cursor_op op = MDB_FIRST;
4466  while (1)
4467  {
4468  int ret = mdb_cursor_get(m_cur_output_amounts, &k, &v, op);
4469  op = MDB_NEXT_NODUP;
4470  if (ret == MDB_NOTFOUND)
4471  break;
4472  if (ret)
4473  throw0(DB_ERROR(lmdb_error("Failed to enumerate outputs: ", ret).c_str()));
4474  mdb_size_t num_elems = 0;
4476  uint64_t amount = *(const uint64_t*)k.mv_data;
4477  if (num_elems >= min_count)
4478  histogram[amount] = std::make_tuple(num_elems, 0, 0);
4479  }
4480  }
4481  else
4482  {
4483  for (const auto &amount: amounts)
4484  {
4485  MDB_val_copy<uint64_t> k(amount);
4486  int ret = mdb_cursor_get(m_cur_output_amounts, &k, &v, MDB_SET);
4487  if (ret == MDB_NOTFOUND)
4488  {
4489  if (0 >= min_count)
4490  histogram[amount] = std::make_tuple(0, 0, 0);
4491  }
4492  else if (ret == MDB_SUCCESS)
4493  {
4494  mdb_size_t num_elems = 0;
4496  if (num_elems >= min_count)
4497  histogram[amount] = std::make_tuple(num_elems, 0, 0);
4498  }
4499  else
4500  {
4501  throw0(DB_ERROR(lmdb_error("Failed to enumerate outputs: ", ret).c_str()));
4502  }
4503  }
4504  }
4505 
4506  if (unlocked || recent_cutoff > 0) {
4507  const uint64_t blockchain_height = height();
4508  for (std::map<uint64_t, std::tuple<uint64_t, uint64_t, uint64_t>>::iterator i = histogram.begin(); i != histogram.end(); ++i) {
4509  uint64_t amount = i->first;
4510  uint64_t num_elems = std::get<0>(i->second);
4511  while (num_elems > 0) {
4512  const tx_out_index toi = get_output_tx_and_index(amount, num_elems - 1);
4513  const uint64_t height = get_tx_block_height(toi.first);
4514  if (height + (get_hard_fork_version(height) > 7 ? ETN_DEFAULT_TX_SPENDABLE_AGE_V8 : CRYPTONOTE_DEFAULT_TX_SPENDABLE_AGE) <= blockchain_height)
4515  break;
4516  --num_elems;
4517  }
4518  // modifying second does not invalidate the iterator
4519  std::get<1>(i->second) = num_elems;
4520 
4521  if (recent_cutoff > 0)
4522  {
4523  uint64_t recent = 0;
4524  while (num_elems > 0) {
4525  const tx_out_index toi = get_output_tx_and_index(amount, num_elems - 1);
4526  const uint64_t height = get_tx_block_height(toi.first);
4527  const uint64_t ts = get_block_timestamp(height);
4528  if (ts < recent_cutoff)
4529  break;
4530  --num_elems;
4531  ++recent;
4532  }
4533  // modifying second does not invalidate the iterator
4534  std::get<2>(i->second) = recent;
4535  }
4536  }
4537  }
4538 
4540 
4541  return histogram;
4542 }
virtual uint64_t get_block_timestamp(const uint64_t &height) const
fetch a block's timestamp
Definition: db_lmdb.cpp:2888
virtual tx_out_index get_output_tx_and_index(const uint64_t &amount, const uint64_t &index) const
gets an output's tx hash and index
Definition: db_lmdb.cpp:3716
virtual uint64_t get_tx_block_height(const crypto::hash &h) const
fetches the height of a transaction's block
Definition: db_lmdb.cpp:3612
#define ETN_DEFAULT_TX_SPENDABLE_AGE_V8
#define CRYPTONOTE_DEFAULT_TX_SPENDABLE_AGE
@ MDB_NEXT_NODUP
Definition: lmdb.h:417
tuple make_tuple()
Definition: gtest-tuple.h:675
Here is the call graph for this function:

◆ get_output_key() [1/2]

void cryptonote::BlockchainLMDB::get_output_key ( const epee::span< const uint64_t > &  amounts,
const std::vector< uint64_t > &  offsets,
std::vector< output_data_t > &  outputs,
bool  allow_partial = false 
) const
virtual

gets outputs' data

This function is a mirror of get_output_data(const uint64_t& amount, const uint64_t& index) but for a list of outputs rather than just one.

Parameters
amountsan output amount, or as many as offsets
offsetsa list of amount-specific output indices
outputsreturn-by-reference a list of outputs' metadata

Implements cryptonote::BlockchainDB.

Definition at line 4360 of file db_lmdb.cpp.

4361 {
4362  if (amounts.size() != 1 && amounts.size() != offsets.size())
4363  throw0(DB_ERROR("Invalid sizes of amounts and offets"));
4364 
4365  LOG_PRINT_L3("BlockchainLMDB::" << __func__);
4366  TIME_MEASURE_START(db3);
4367  check_open();
4368  outputs.clear();
4369  outputs.reserve(offsets.size());
4370 
4372 
4373  RCURSOR(output_amounts);
4374 
4375  for (size_t i = 0; i < offsets.size(); ++i)
4376  {
4377  const uint64_t amount = amounts.size() == 1 ? amounts[0] : amounts[i];
4378  MDB_val_set(k, amount);
4379  MDB_val_set(v, offsets[i]);
4380 
4381  auto get_result = mdb_cursor_get(m_cur_output_amounts, &k, &v, MDB_GET_BOTH);
4382  if (get_result == MDB_NOTFOUND)
4383  {
4384  if (allow_partial)
4385  {
4386  MDEBUG("Partial result: " << outputs.size() << "/" << offsets.size());
4387  break;
4388  }
4389  throw1(OUTPUT_DNE((std::string("Attempting to get output pubkey by global index (amount ") + boost::lexical_cast<std::string>(amount) + ", index " + boost::lexical_cast<std::string>(offsets[i]) + ", count " + boost::lexical_cast<std::string>(get_num_outputs(amount)) + "), but key does not exist (current height " + boost::lexical_cast<std::string>(height()) + ")").c_str()));
4390  }
4391  else if (get_result)
4392  throw0(DB_ERROR(lmdb_error("Error attempting to retrieve an output pubkey from the db", get_result).c_str()));
4393 
4394  if (amount == 0)
4395  {
4396  const outkey *okp = (const outkey *)v.mv_data;
4397  outputs.push_back(okp->data);
4398  }
4399  else
4400  {
4401  const pre_rct_outkey *okp = (const pre_rct_outkey *)v.mv_data;
4402  outputs.resize(outputs.size() + 1);
4403  output_data_t &data = outputs.back();
4404  memcpy(&data, &okp->data, sizeof(pre_rct_output_data_t));
4405  data.commitment = rct::zeroCommit(amount);
4406  }
4407  }
4408 
4410 
4411  TIME_MEASURE_FINISH(db3);
4412  LOG_PRINT_L3("db3: " << db3);
4413 }
virtual uint64_t get_num_outputs(const uint64_t &amount) const
fetches the number of outputs of a given amount
Definition: db_lmdb.cpp:3635
constexpr std::size_t size() const noexcept
Definition: span.h:111
#define MDEBUG(x)
Definition: misc_log_ex.h:76
struct cryptonote::pre_rct_outkey pre_rct_outkey
key zeroCommit(etn_amount amount)
Definition: rctOps.cpp:322
Here is the call graph for this function:

◆ get_output_key() [2/2]

output_data_t cryptonote::BlockchainLMDB::get_output_key ( const uint64_t amount,
const uint64_t index,
bool  include_commitmemt 
) const
virtual

get some of an output's data

The subclass should return the public key, unlock time, and block height for the output with the given amount and index, collected in a struct.

If the output cannot be found, the subclass should throw OUTPUT_DNE.

If any of these parts cannot be found, but some are, the subclass should throw DB_ERROR with a message stating as much.

Parameters
amountthe output amount
indexthe output's index (indexed by amount)
Returns
the requested output data

Implements cryptonote::BlockchainDB.

Definition at line 3659 of file db_lmdb.cpp.

3660 {
3661  LOG_PRINT_L3("BlockchainLMDB::" << __func__);
3662  check_open();
3663 
3665  RCURSOR(output_amounts);
3666 
3667  MDB_val_set(k, amount);
3668  MDB_val_set(v, index);
3669  auto get_result = mdb_cursor_get(m_cur_output_amounts, &k, &v, MDB_GET_BOTH);
3670  if (get_result == MDB_NOTFOUND)
3671  throw1(OUTPUT_DNE(std::string("Attempting to get output pubkey by index, but key does not exist: amount " +
3672  std::to_string(amount) + ", index " + std::to_string(index)).c_str()));
3673  else if (get_result)
3674  throw0(DB_ERROR("Error attempting to retrieve an output pubkey from the db"));
3675 
3676  output_data_t ret;
3677  if (amount == 0)
3678  {
3679  const outkey *okp = (const outkey *)v.mv_data;
3680  ret = okp->data;
3681  }
3682  else
3683  {
3684  const pre_rct_outkey *okp = (const pre_rct_outkey *)v.mv_data;
3685  memcpy(&ret, &okp->data, sizeof(pre_rct_output_data_t));;
3686  if (include_commitmemt)
3687  ret.commitment = rct::zeroCommit(amount);
3688  }
3690  return ret;
3691 }
output_data_t data
Definition: db_lmdb.cpp:369
Here is the call graph for this function:

◆ get_output_tx_and_index() [1/2]

void cryptonote::BlockchainLMDB::get_output_tx_and_index ( const uint64_t amount,
const std::vector< uint64_t > &  offsets,
std::vector< tx_out_index > &  indices 
) const
virtual

gets some outputs' tx hashes and indices

This function is a mirror of get_output_tx_and_index(const uint64_t& amount, const uint64_t& index), but for a list of outputs rather than just one.

Parameters
amountan output amount
offsetsa list of amount-specific output indices
indicesreturn-by-reference a list of tx hashes and output indices (as pairs)

Implements cryptonote::BlockchainDB.

Definition at line 4415 of file db_lmdb.cpp.

4416 {
4417  LOG_PRINT_L3("BlockchainLMDB::" << __func__);
4418  check_open();
4419  indices.clear();
4420 
4421  std::vector <uint64_t> tx_indices;
4422  tx_indices.reserve(offsets.size());
4424 
4425  RCURSOR(output_amounts);
4426 
4427  MDB_val_set(k, amount);
4428  for (const uint64_t &index : offsets)
4429  {
4430  MDB_val_set(v, index);
4431 
4432  auto get_result = mdb_cursor_get(m_cur_output_amounts, &k, &v, MDB_GET_BOTH);
4433  if (get_result == MDB_NOTFOUND)
4434  throw1(OUTPUT_DNE("Attempting to get output by index, but key does not exist"));
4435  else if (get_result)
4436  throw0(DB_ERROR(lmdb_error("Error attempting to retrieve an output from the db", get_result).c_str()));
4437 
4438  const outkey *okp = (const outkey *)v.mv_data;
4439  tx_indices.push_back(okp->output_id);
4440  }
4441 
4442  TIME_MEASURE_START(db3);
4443  if(tx_indices.size() > 0)
4444  {
4445  get_output_tx_and_index_from_global(tx_indices, indices);
4446  }
4447  TIME_MEASURE_FINISH(db3);
4448  LOG_PRINT_L3("db3: " << db3);
4449 }
Here is the call graph for this function:

◆ get_output_tx_and_index() [2/2]

tx_out_index cryptonote::BlockchainLMDB::get_output_tx_and_index ( const uint64_t amount,
const uint64_t index 
) const
virtual

gets an output's tx hash and index

The subclass should return the hash of the transaction which created the output with the amount and index given, as well as its index in that transaction.

Parameters
amountan output amount
indexan output's amount-specific index
Returns
the tx hash and output index

Implements cryptonote::BlockchainDB.

Definition at line 3716 of file db_lmdb.cpp.

3717 {
3718  LOG_PRINT_L3("BlockchainLMDB::" << __func__);
3719  std::vector < uint64_t > offsets;
3720  std::vector<tx_out_index> indices;
3721  offsets.push_back(index);
3722  get_output_tx_and_index(amount, offsets, indices);
3723  if (!indices.size())
3724  throw1(OUTPUT_DNE("Attempting to get an output index by amount and amount index, but amount not found"));
3725 
3726  return indices[0];
3727 }
Here is the caller graph for this function:

◆ get_output_tx_and_index_from_global() [1/2]

void cryptonote::BlockchainLMDB::get_output_tx_and_index_from_global ( const std::vector< uint64_t > &  global_indices,
std::vector< tx_out_index > &  tx_out_indices 
) const
virtual

Definition at line 4332 of file db_lmdb.cpp.

4334 {
4335  LOG_PRINT_L3("BlockchainLMDB::" << __func__);
4336  check_open();
4337  tx_out_indices.clear();
4338  tx_out_indices.reserve(global_indices.size());
4339 
4341  RCURSOR(output_txs);
4342 
4343  for (const uint64_t &output_id : global_indices)
4344  {
4345  MDB_val_set(v, output_id);
4346 
4347  auto get_result = mdb_cursor_get(m_cur_output_txs, (MDB_val *)&zerokval, &v, MDB_GET_BOTH);
4348  if (get_result == MDB_NOTFOUND)
4349  throw1(OUTPUT_DNE("output with given index not in db"));
4350  else if (get_result)
4351  throw0(DB_ERROR("DB error attempting to fetch output tx hash"));
4352 
4353  const outtx *ot = (const outtx *)v.mv_data;
4354  tx_out_indices.push_back(tx_out_index(ot->tx_hash, ot->local_index));
4355  }
4356 
4358 }
#define m_cur_output_txs
Definition: db_lmdb.h:83
struct cryptonote::outtx outtx
Here is the call graph for this function:

◆ get_output_tx_and_index_from_global() [2/2]

tx_out_index cryptonote::BlockchainLMDB::get_output_tx_and_index_from_global ( const uint64_t index) const
virtual

gets an output's tx hash and index

The subclass should return the hash of the transaction which created the output with the global index given, as well as its index in that transaction.

Parameters
indexan output's global index
Returns
the tx hash and output index

Implements cryptonote::BlockchainDB.

Definition at line 3693 of file db_lmdb.cpp.

3694 {
3695  LOG_PRINT_L3("BlockchainLMDB::" << __func__);
3696  check_open();
3697 
3699  RCURSOR(output_txs);
3700 
3701  MDB_val_set(v, output_id);
3702 
3703  auto get_result = mdb_cursor_get(m_cur_output_txs, (MDB_val *)&zerokval, &v, MDB_GET_BOTH);
3704  if (get_result == MDB_NOTFOUND)
3705  throw1(OUTPUT_DNE("output with given index not in db"));
3706  else if (get_result)
3707  throw0(DB_ERROR("DB error attempting to fetch output tx hash"));
3708 
3709  outtx *ot = (outtx *)v.mv_data;
3710  tx_out_index ret = tx_out_index(ot->tx_hash, ot->local_index);
3711 
3713  return ret;
3714 }
Here is the call graph for this function:
Here is the caller graph for this function:

◆ get_prunable_tx_blob()

bool cryptonote::BlockchainLMDB::get_prunable_tx_blob ( const crypto::hash h,
cryptonote::blobdata tx 
) const
virtual

fetches the prunable transaction blob with the given hash

The subclass should return the prunable transaction stored which has the given hash.

If the transaction does not exist, or if we do not have that prunable data, the subclass should return false.

Parameters
hthe hash to look for
Returns
true iff the transaction was found and we have its prunable data

Implements cryptonote::BlockchainDB.

Definition at line 3521 of file db_lmdb.cpp.

3522 {
3523  LOG_PRINT_L3("BlockchainLMDB::" << __func__);
3524  check_open();
3525 
3527  RCURSOR(tx_indices);
3528  RCURSOR(txs_prunable);
3529 
3530  MDB_val_set(v, h);
3531  MDB_val result;
3532  auto get_result = mdb_cursor_get(m_cur_tx_indices, (MDB_val *)&zerokval, &v, MDB_GET_BOTH);
3533  if (get_result == 0)
3534  {
3535  const txindex *tip = (const txindex *)v.mv_data;
3536  MDB_val_set(val_tx_id, tip->data.tx_id);
3537  get_result = mdb_cursor_get(m_cur_txs_prunable, &val_tx_id, &result, MDB_SET);
3538  }
3539  if (get_result == MDB_NOTFOUND)
3540  return false;
3541  else if (get_result)
3542  throw0(DB_ERROR(lmdb_error("DB error attempting to fetch tx from hash", get_result).c_str()));
3543 
3544  bd.assign(reinterpret_cast<char*>(result.mv_data), result.mv_size);
3545 
3547 
3548  return true;
3549 }
Here is the call graph for this function:

◆ get_prunable_tx_hash()

bool cryptonote::BlockchainLMDB::get_prunable_tx_hash ( const crypto::hash tx_hash,
crypto::hash prunable_hash 
) const
virtual

fetches the prunable transaction hash

The subclass should return the hash of the prunable transaction data.

If the transaction hash does not exist, the subclass should return false.

Parameters
hthe tx hash to look for
Returns
true iff the transaction was found

Implements cryptonote::BlockchainDB.

Definition at line 3551 of file db_lmdb.cpp.

3552 {
3553  LOG_PRINT_L3("BlockchainLMDB::" << __func__);
3554  check_open();
3555 
3557  RCURSOR(tx_indices);
3558  RCURSOR(txs_prunable_hash);
3559 
3560  MDB_val_set(v, tx_hash);
3561  MDB_val result, val_tx_prunable_hash;
3562  auto get_result = mdb_cursor_get(m_cur_tx_indices, (MDB_val *)&zerokval, &v, MDB_GET_BOTH);
3563  if (get_result == 0)
3564  {
3565  txindex *tip = (txindex *)v.mv_data;
3566  MDB_val_set(val_tx_id, tip->data.tx_id);
3567  get_result = mdb_cursor_get(m_cur_txs_prunable_hash, &val_tx_id, &result, MDB_SET);
3568  }
3569  if (get_result == MDB_NOTFOUND)
3570  return false;
3571  else if (get_result)
3572  throw0(DB_ERROR(lmdb_error("DB error attempting to fetch tx prunable hash from tx hash", get_result).c_str()));
3573 
3574  prunable_hash = *(const crypto::hash*)result.mv_data;
3575 
3577 
3578  return true;
3579 }
#define m_cur_txs_prunable_hash
Definition: db_lmdb.h:88
Here is the call graph for this function:

◆ get_pruned_tx_blob()

bool cryptonote::BlockchainLMDB::get_pruned_tx_blob ( const crypto::hash h,
cryptonote::blobdata tx 
) const
virtual

fetches the pruned transaction blob with the given hash

The subclass should return the pruned transaction stored which has the given hash.

If the transaction does not exist, the subclass should return false.

Parameters
hthe hash to look for
Returns
true iff the transaction was found

Implements cryptonote::BlockchainDB.

Definition at line 3491 of file db_lmdb.cpp.

3492 {
3493  LOG_PRINT_L3("BlockchainLMDB::" << __func__);
3494  check_open();
3495 
3497  RCURSOR(tx_indices);
3498  RCURSOR(txs_pruned);
3499 
3500  MDB_val_set(v, h);
3501  MDB_val result;
3502  auto get_result = mdb_cursor_get(m_cur_tx_indices, (MDB_val *)&zerokval, &v, MDB_GET_BOTH);
3503  if (get_result == 0)
3504  {
3505  txindex *tip = (txindex *)v.mv_data;
3506  MDB_val_set(val_tx_id, tip->data.tx_id);
3507  get_result = mdb_cursor_get(m_cur_txs_pruned, &val_tx_id, &result, MDB_SET);
3508  }
3509  if (get_result == MDB_NOTFOUND)
3510  return false;
3511  else if (get_result)
3512  throw0(DB_ERROR(lmdb_error("DB error attempting to fetch tx from hash", get_result).c_str()));
3513 
3514  bd.assign(reinterpret_cast<char*>(result.mv_data), result.mv_size);
3515 
3517 
3518  return true;
3519 }
Here is the call graph for this function:

◆ get_top_block()

block cryptonote::BlockchainLMDB::get_top_block ( ) const
virtual

fetch the top block

The subclass should return most recent block

Returns
the top block

Implements cryptonote::BlockchainDB.

Definition at line 3317 of file db_lmdb.cpp.

3318 {
3319  LOG_PRINT_L3("BlockchainLMDB::" << __func__);
3320  check_open();
3321  uint64_t m_height = height();
3322 
3323  if (m_height != 0)
3324  {
3325  return get_block_from_height(m_height - 1);
3326  }
3327 
3328  block b;
3329  return b;
3330 }
Here is the call graph for this function:

◆ get_top_block_timestamp()

uint64_t cryptonote::BlockchainLMDB::get_top_block_timestamp ( ) const
virtual

fetch the top block's timestamp

The subclass should return the timestamp of the most recent block.

Returns
the top block's timestamp

Implements cryptonote::BlockchainDB.

Definition at line 2973 of file db_lmdb.cpp.

2974 {
2975  LOG_PRINT_L3("BlockchainLMDB::" << __func__);
2976  check_open();
2977  uint64_t m_height = height();
2978 
2979  // if no blocks, return 0
2980  if (m_height == 0)
2981  {
2982  return 0;
2983  }
2984 
2985  return get_block_timestamp(m_height - 1);
2986 }
Here is the call graph for this function:

◆ get_tx_amount_output_indices()

std::vector< std::vector< uint64_t > > cryptonote::BlockchainLMDB::get_tx_amount_output_indices ( const uint64_t  tx_id,
size_t  n_txes 
) const
virtual

gets output indices (amount-specific) for a transaction's outputs

The subclass should fetch the amount-specific output indices for each output in the transaction with the given ID.

If the transaction does not exist, the subclass should throw TX_DNE.

If an output cannot be found, the subclass should throw OUTPUT_DNE.

Parameters
tx_ida transaction ID
n_txeshow many txes to get data for, starting with tx_id
Returns
a list of amount-specific output indices

Implements cryptonote::BlockchainDB.

Definition at line 3729 of file db_lmdb.cpp.

3730 {
3731  LOG_PRINT_L3("BlockchainLMDB::" << __func__);
3732 
3733  check_open();
3734 
3736  RCURSOR(tx_outputs);
3737 
3738  MDB_val_set(k_tx_id, tx_id);
3739  MDB_val v;
3740  std::vector<std::vector<uint64_t>> amount_output_indices_set;
3741  amount_output_indices_set.reserve(n_txes);
3742 
3743  MDB_cursor_op op = MDB_SET;
3744  while (n_txes-- > 0)
3745  {
3746  int result = mdb_cursor_get(m_cur_tx_outputs, &k_tx_id, &v, op);
3747  if (result == MDB_NOTFOUND)
3748  LOG_PRINT_L0("WARNING: Unexpected: tx has no amount indices stored in "
3749  "tx_outputs, but it should have an empty entry even if it's a tx without "
3750  "outputs");
3751  else if (result)
3752  throw0(DB_ERROR(lmdb_error("DB error attempting to get data for tx_outputs[tx_index]", result).c_str()));
3753 
3754  op = MDB_NEXT;
3755 
3756  const uint64_t* indices = (const uint64_t*)v.mv_data;
3757  size_t num_outputs = v.mv_size / sizeof(uint64_t);
3758 
3759  amount_output_indices_set.resize(amount_output_indices_set.size() + 1);
3760  std::vector<uint64_t> &amount_output_indices = amount_output_indices_set.back();
3761  amount_output_indices.reserve(num_outputs);
3762  for (size_t i = 0; i < num_outputs; ++i)
3763  {
3764  amount_output_indices.push_back(indices[i]);
3765  }
3766  }
3767 
3769  return amount_output_indices_set;
3770 }
#define m_cur_tx_outputs
Definition: db_lmdb.h:91
Here is the call graph for this function:

◆ get_tx_blob()

bool cryptonote::BlockchainLMDB::get_tx_blob ( const crypto::hash h,
cryptonote::blobdata tx 
) const
virtual

fetches the transaction blob with the given hash

The subclass should return the transaction stored which has the given hash.

If the transaction does not exist, the subclass should return false.

Parameters
hthe hash to look for
Returns
true iff the transaction was found

Implements cryptonote::BlockchainDB.

Definition at line 3455 of file db_lmdb.cpp.

3456 {
3457  LOG_PRINT_L3("BlockchainLMDB::" << __func__);
3458  check_open();
3459 
3461  RCURSOR(tx_indices);
3462  RCURSOR(txs_pruned);
3463  RCURSOR(txs_prunable);
3464 
3465  MDB_val_set(v, h);
3466  MDB_val result0, result1;
3467  auto get_result = mdb_cursor_get(m_cur_tx_indices, (MDB_val *)&zerokval, &v, MDB_GET_BOTH);
3468  if (get_result == 0)
3469  {
3470  txindex *tip = (txindex *)v.mv_data;
3471  MDB_val_set(val_tx_id, tip->data.tx_id);
3472  get_result = mdb_cursor_get(m_cur_txs_pruned, &val_tx_id, &result0, MDB_SET);
3473  if (get_result == 0)
3474  {
3475  get_result = mdb_cursor_get(m_cur_txs_prunable, &val_tx_id, &result1, MDB_SET);
3476  }
3477  }
3478  if (get_result == MDB_NOTFOUND)
3479  return false;
3480  else if (get_result)
3481  throw0(DB_ERROR(lmdb_error("DB error attempting to fetch tx from hash", get_result).c_str()));
3482 
3483  bd.assign(reinterpret_cast<char*>(result0.mv_data), result0.mv_size);
3484  bd.append(reinterpret_cast<char*>(result1.mv_data), result1.mv_size);
3485 
3487 
3488  return true;
3489 }
Here is the call graph for this function:

◆ get_tx_block_height()

uint64_t cryptonote::BlockchainLMDB::get_tx_block_height ( const crypto::hash h) const
virtual

fetches the height of a transaction's block

The subclass should attempt to return the height of the block containing the transaction with the given hash.

If the transaction cannot be found, the subclass should throw TX_DNE.

Parameters
hthe hash of the transaction
Returns
the height of the transaction's block

Implements cryptonote::BlockchainDB.

Definition at line 3612 of file db_lmdb.cpp.

3613 {
3614  LOG_PRINT_L3("BlockchainLMDB::" << __func__);
3615  check_open();
3616 
3618  RCURSOR(tx_indices);
3619 
3620  MDB_val_set(v, h);
3621  auto get_result = mdb_cursor_get(m_cur_tx_indices, (MDB_val *)&zerokval, &v, MDB_GET_BOTH);
3622  if (get_result == MDB_NOTFOUND)
3623  {
3624  throw1(TX_DNE(std::string("tx_data_t with hash ").append(epee::string_tools::pod_to_hex(h)).append(" not found in db").c_str()));
3625  }
3626  else if (get_result)
3627  throw0(DB_ERROR(lmdb_error("DB error attempting to fetch tx height from hash", get_result).c_str()));
3628 
3629  txindex *tip = (txindex *)v.mv_data;
3630  uint64_t ret = tip->data.block_id;
3632  return ret;
3633 }
tx_data_t data
Definition: db_lmdb.h:46
Here is the call graph for this function:
Here is the caller graph for this function:

◆ get_tx_count()

uint64_t cryptonote::BlockchainLMDB::get_tx_count ( ) const
virtual

fetches the total number of transactions ever

The subclass should return a count of all the transactions from all blocks.

Returns
the number of transactions in the blockchain

Implements cryptonote::BlockchainDB.

Definition at line 3581 of file db_lmdb.cpp.

3582 {
3583  LOG_PRINT_L3("BlockchainLMDB::" << __func__);
3584  check_open();
3585 
3587  int result;
3588 
3589  MDB_stat db_stats;
3590  if ((result = mdb_stat(m_txn, m_txs_pruned, &db_stats)))
3591  throw0(DB_ERROR(lmdb_error("Failed to query m_txs_pruned: ", result).c_str()));
3592 
3594 
3595  return db_stats.ms_entries;
3596 }
Here is the call graph for this function:

◆ get_tx_input()

tx_input_t cryptonote::BlockchainLMDB::get_tx_input ( const crypto::hash  tx_hash,
const uint32_t  relative_out_index 
)
virtual

Implements cryptonote::BlockchainDB.

Definition at line 1944 of file db_lmdb.cpp.

1945 {
1946  LOG_PRINT_L3("BlockchainLMDB::" << __func__);
1947  check_open();
1948 
1950  RCURSOR(tx_inputs)
1951 
1952  chainstate_key_t key;
1953  key.tx_hash = tx_hash;
1954  key.relative_out_index = relative_out_index;
1955 
1956  MDB_val k = {sizeof(key), (void *)&key};
1957  MDB_val v;
1958  auto result = mdb_cursor_get(m_cur_tx_inputs, &k, &v, MDB_SET_KEY);
1959  if (result == MDB_NOTFOUND)
1960  return tx_input_t();
1961  if (result != 0)
1962  throw1(DB_ERROR(lmdb_error("Error finding tx input: ", result).c_str()));
1963 
1965  return *(const tx_input_t *) v.mv_data;
1966 }
#define m_cur_tx_inputs
Definition: db_lmdb.h:100
Here is the call graph for this function:

◆ get_tx_list()

std::vector< transaction > cryptonote::BlockchainLMDB::get_tx_list ( const std::vector< crypto::hash > &  hlist) const
virtual

fetches a list of transactions based on their hashes

The subclass should attempt to fetch each transaction referred to by the hashes passed.

Currently, if any of the transactions is not in BlockchainDB, the call to get_tx in the implementation will throw TX_DNE.

Parameters
hlista list of hashes
Returns
the list of transactions

Implements cryptonote::BlockchainDB.

Definition at line 3598 of file db_lmdb.cpp.

3599 {
3600  LOG_PRINT_L3("BlockchainLMDB::" << __func__);
3601  check_open();
3602  std::vector<transaction> v;
3603 
3604  for (auto& h : hlist)
3605  {
3606  v.push_back(get_tx(h));
3607  }
3608 
3609  return v;
3610 }
virtual transaction get_tx(const crypto::hash &h) const
fetches the transaction with the given hash
Here is the call graph for this function:

◆ get_tx_unlock_time()

uint64_t cryptonote::BlockchainLMDB::get_tx_unlock_time ( const crypto::hash h) const
virtual

fetch a transaction's unlock time/height

The subclass should return the stored unlock time for the transaction with the given hash.

If no such transaction exists, the subclass should throw TX_DNE.

Parameters
hthe hash of the requested transaction
Returns
the unlock time/height

Implements cryptonote::BlockchainDB.

Definition at line 3434 of file db_lmdb.cpp.

3435 {
3436  LOG_PRINT_L3("BlockchainLMDB::" << __func__);
3437  check_open();
3438 
3440  RCURSOR(tx_indices);
3441 
3442  MDB_val_set(v, h);
3443  auto get_result = mdb_cursor_get(m_cur_tx_indices, (MDB_val *)&zerokval, &v, MDB_GET_BOTH);
3444  if (get_result == MDB_NOTFOUND)
3445  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()));
3446  else if (get_result)
3447  throw0(DB_ERROR(lmdb_error("DB error attempting to fetch tx data from hash: ", get_result).c_str()));
3448 
3449  txindex *tip = (txindex *)v.mv_data;
3450  uint64_t ret = tip->data.unlock_time;
3452  return ret;
3453 }
Here is the call graph for this function:

◆ get_txpool_tx_blob() [1/2]

cryptonote::blobdata cryptonote::BlockchainLMDB::get_txpool_tx_blob ( const crypto::hash txid) const
virtual

get a txpool transaction's blob

Parameters
txidthe transaction id of the transation to lookup
Returns
the blob for that transaction

Implements cryptonote::BlockchainDB.

Definition at line 2400 of file db_lmdb.cpp.

2401 {
2403  if (!get_txpool_tx_blob(txid, bd))
2404  throw1(DB_ERROR("Tx not found in txpool: "));
2405  return bd;
2406 }
virtual bool get_txpool_tx_blob(const crypto::hash &txid, cryptonote::blobdata &bd) const
get a txpool transaction's blob
Definition: db_lmdb.cpp:2379
Here is the call graph for this function:

◆ get_txpool_tx_blob() [2/2]

bool cryptonote::BlockchainLMDB::get_txpool_tx_blob ( const crypto::hash txid,
cryptonote::blobdata bd 
) const
virtual

get a txpool transaction's blob

Parameters
txidthe transaction id of the transation to lookup
bdthe blob to return
Returns
true if the txid was in the txpool, false otherwise

Implements cryptonote::BlockchainDB.

Definition at line 2379 of file db_lmdb.cpp.

2380 {
2381  LOG_PRINT_L3("BlockchainLMDB::" << __func__);
2382  check_open();
2383 
2385  RCURSOR(txpool_blob)
2386 
2387  MDB_val k = {sizeof(txid), (void *)&txid};
2388  MDB_val v;
2389  auto result = mdb_cursor_get(m_cur_txpool_blob, &k, &v, MDB_SET);
2390  if (result == MDB_NOTFOUND)
2391  return false;
2392  if (result != 0)
2393  throw1(DB_ERROR(lmdb_error("Error finding txpool tx blob: ", result).c_str()));
2394 
2395  bd.assign(reinterpret_cast<const char*>(v.mv_data), v.mv_size);
2397  return true;
2398 }
Here is the call graph for this function:
Here is the caller graph for this function:

◆ get_txpool_tx_count()

uint64_t cryptonote::BlockchainLMDB::get_txpool_tx_count ( bool  include_unrelayed_txes = true) const
virtual

get the number of transactions in the txpool

Implements cryptonote::BlockchainDB.

Definition at line 2267 of file db_lmdb.cpp.

2268 {
2269  LOG_PRINT_L3("BlockchainLMDB::" << __func__);
2270  check_open();
2271 
2272  int result;
2273  uint64_t num_entries = 0;
2274 
2276 
2277  if (include_unrelayed_txes)
2278  {
2279  // No filtering, we can get the number of tx the "fast" way
2280  MDB_stat db_stats;
2281  if ((result = mdb_stat(m_txn, m_txpool_meta, &db_stats)))
2282  throw0(DB_ERROR(lmdb_error("Failed to query m_txpool_meta: ", result).c_str()));
2283  num_entries = db_stats.ms_entries;
2284  }
2285  else
2286  {
2287  // Filter unrelayed tx out of the result, so we need to loop over transactions and check their meta data
2288  RCURSOR(txpool_meta);
2289  RCURSOR(txpool_blob);
2290 
2291  MDB_val k;
2292  MDB_val v;
2293  MDB_cursor_op op = MDB_FIRST;
2294  while (1)
2295  {
2296  result = mdb_cursor_get(m_cur_txpool_meta, &k, &v, op);
2297  op = MDB_NEXT;
2298  if (result == MDB_NOTFOUND)
2299  break;
2300  if (result)
2301  throw0(DB_ERROR(lmdb_error("Failed to enumerate txpool tx metadata: ", result).c_str()));
2302  const txpool_tx_meta_t &meta = *(const txpool_tx_meta_t*)v.mv_data;
2303  if (!meta.do_not_relay)
2304  ++num_entries;
2305  }
2306  }
2308 
2309  return num_entries;
2310 }
Here is the call graph for this function:

◆ get_txpool_tx_meta()

bool cryptonote::BlockchainLMDB::get_txpool_tx_meta ( const crypto::hash txid,
txpool_tx_meta_t meta 
) const
virtual

get a txpool transaction's metadata

Parameters
txidthe transaction id of the transation to lookup
metathe metadata to return
Returns
true if the tx meta was found, false otherwise

Implements cryptonote::BlockchainDB.

Definition at line 2358 of file db_lmdb.cpp.

2359 {
2360  LOG_PRINT_L3("BlockchainLMDB::" << __func__);
2361  check_open();
2362 
2364  RCURSOR(txpool_meta)
2365 
2366  MDB_val k = {sizeof(txid), (void *)&txid};
2367  MDB_val v;
2368  auto result = mdb_cursor_get(m_cur_txpool_meta, &k, &v, MDB_SET);
2369  if (result == MDB_NOTFOUND)
2370  return false;
2371  if (result != 0)
2372  throw1(DB_ERROR(lmdb_error("Error finding txpool tx meta: ", result).c_str()));
2373 
2374  meta = *(const txpool_tx_meta_t*)v.mv_data;
2376  return true;
2377 }
Here is the call graph for this function:

◆ has_key_image()

bool cryptonote::BlockchainLMDB::has_key_image ( const crypto::key_image img) const
virtual

check if a key image is stored as spent

Parameters
imgthe key image to check for
Returns
true if the image is present, otherwise false

Implements cryptonote::BlockchainDB.

Definition at line 3772 of file db_lmdb.cpp.

3773 {
3774  LOG_PRINT_L3("BlockchainLMDB::" << __func__);
3775  check_open();
3776 
3777  bool ret;
3778 
3780  RCURSOR(spent_keys);
3781 
3782  MDB_val k = {sizeof(img), (void *)&img};
3783  ret = (mdb_cursor_get(m_cur_spent_keys, (MDB_val *)&zerokval, &k, MDB_GET_BOTH) == 0);
3784 
3786  return ret;
3787 }
Here is the call graph for this function:

◆ height()

uint64_t cryptonote::BlockchainLMDB::height ( ) const
virtual

fetch the current blockchain height

The subclass should return the current blockchain height

Returns
the current blockchain height

Implements cryptonote::BlockchainDB.

Definition at line 3332 of file db_lmdb.cpp.

3333 {
3334  LOG_PRINT_L3("BlockchainLMDB::" << __func__);
3335  check_open();
3337  int result;
3338 
3339  // get current height
3340  MDB_stat db_stats;
3341  if ((result = mdb_stat(m_txn, m_blocks, &db_stats)))
3342  throw0(DB_ERROR(lmdb_error("Failed to query m_blocks: ", result).c_str()));
3343  return db_stats.ms_entries;
3344 }
Here is the call graph for this function:
Here is the caller graph for this function:

◆ lock()

bool cryptonote::BlockchainLMDB::lock ( )
virtual

acquires the BlockchainDB lock

This function is a stub until such a time as locking is implemented at this level.

The subclass implementation should return true unless implementing a locking scheme of some sort, in which case it should return true upon acquisition of the lock and block until then.

If any of this cannot be done, the subclass should throw the corresponding subclass of DB_EXCEPTION

Returns
true, unless at a future time false makes sense (timeout, etc)

Implements cryptonote::BlockchainDB.

Definition at line 1740 of file db_lmdb.cpp.

1741 {
1742  LOG_PRINT_L3("BlockchainLMDB::" << __func__);
1743  check_open();
1744  return false;
1745 }

◆ open()

void cryptonote::BlockchainLMDB::open ( const std::string &  filename,
const int  db_flags = 0 
)
virtual

open a db, or create it if necessary.

This function opens an existing database or creates it if it does not exist.

The subclass implementing this will handle all file opening/creation, and is responsible for maintaining its state.

The parameter <filename> may not refer to a file name, necessarily, but could be an IP:PORT for a database which needs it, and so on. Calling it <filename> is convenient and should be descriptive enough, however.

For now, db_flags are specific to the subclass being instantiated. This is subject to change, and the db_flags parameter may be deprecated.

If any of this cannot be done, the subclass should throw the corresponding subclass of DB_EXCEPTION

Parameters
filenamea string referring to the BlockchainDB to open
db_flagsflags relevant to how to open/use the BlockchainDB

Implements cryptonote::BlockchainDB.

Definition at line 1350 of file db_lmdb.cpp.

1351 {
1352  int result;
1353  int mdb_flags = MDB_NORDAHEAD;
1354 
1355  LOG_PRINT_L3("BlockchainLMDB::" << __func__);
1356 
1357  if (m_open)
1358  throw0(DB_OPEN_FAILURE("Attempted to open db, but it's already open"));
1359 
1360  boost::filesystem::path direc(filename);
1361  if (boost::filesystem::exists(direc))
1362  {
1363  if (!boost::filesystem::is_directory(direc))
1364  throw0(DB_OPEN_FAILURE("LMDB needs a directory path, but a file was passed"));
1365  }
1366  else
1367  {
1368  if (!boost::filesystem::create_directories(direc))
1369  throw0(DB_OPEN_FAILURE(std::string("Failed to create directory ").append(filename).c_str()));
1370  }
1371 
1372  // check for existing LMDB files in base directory
1373  boost::filesystem::path old_files = direc.parent_path();
1374  if (boost::filesystem::exists(old_files / CRYPTONOTE_BLOCKCHAINDATA_FILENAME)
1375  || boost::filesystem::exists(old_files / CRYPTONOTE_BLOCKCHAINDATA_LOCK_FILENAME))
1376  {
1377  LOG_PRINT_L0("Found existing LMDB files in " << old_files.string());
1378  LOG_PRINT_L0("Move " << CRYPTONOTE_BLOCKCHAINDATA_FILENAME << " and/or " << CRYPTONOTE_BLOCKCHAINDATA_LOCK_FILENAME << " to " << filename << ", or delete them, and then restart");
1379  throw DB_ERROR("Database could not be opened");
1380  }
1381 
1382  boost::optional<bool> is_hdd_result = tools::is_hdd(filename.c_str());
1383  if (is_hdd_result)
1384  {
1385  if (is_hdd_result.value())
1386  MCLOG_RED(el::Level::Warning, "global", "The blockchain is on a rotating drive: this will be very slow, use an SSD if possible");
1387  }
1388 
1389  m_folder = filename;
1390 
1391 #ifdef __OpenBSD__
1392  if ((mdb_flags & MDB_WRITEMAP) == 0) {
1393  MCLOG_RED(el::Level::Info, "global", "Running on OpenBSD: forcing WRITEMAP");
1394  mdb_flags |= MDB_WRITEMAP;
1395  }
1396 #endif
1397  // set up lmdb environment
1398  if ((result = mdb_env_create(&m_env)))
1399  throw0(DB_ERROR(lmdb_error("Failed to create lmdb environment: ", result).c_str()));
1400  if ((result = mdb_env_set_maxdbs(m_env, 25)))
1401  throw0(DB_ERROR(lmdb_error("Failed to set max number of dbs: ", result).c_str()));
1402 
1403  int threads = tools::get_max_concurrency();
1404  if (threads > 110 && /* maxreaders default is 126, leave some slots for other read processes */
1405  (result = mdb_env_set_maxreaders(m_env, threads+16)))
1406  throw0(DB_ERROR(lmdb_error("Failed to set max number of readers: ", result).c_str()));
1407 
1408  size_t mapsize = DEFAULT_MAPSIZE;
1409 
1410  if (db_flags & DBF_FAST)
1411  mdb_flags |= MDB_NOSYNC;
1412  if (db_flags & DBF_FASTEST)
1413  mdb_flags |= MDB_NOSYNC | MDB_WRITEMAP | MDB_MAPASYNC;
1414  if (db_flags & DBF_RDONLY)
1415  mdb_flags = MDB_RDONLY;
1416  if (db_flags & DBF_SALVAGE)
1417  mdb_flags |= MDB_PREVSNAPSHOT;
1418 
1419  if (auto result = mdb_env_open(m_env, filename.c_str(), mdb_flags, 0644))
1420  throw0(DB_ERROR(lmdb_error("Failed to open lmdb environment: ", result).c_str()));
1421 
1422  MDB_envinfo mei;
1423  mdb_env_info(m_env, &mei);
1424  uint64_t cur_mapsize = (uint64_t)mei.me_mapsize;
1425 
1426  if (cur_mapsize < mapsize)
1427  {
1428  if (auto result = mdb_env_set_mapsize(m_env, mapsize))
1429  throw0(DB_ERROR(lmdb_error("Failed to set max memory map size: ", result).c_str()));
1430  mdb_env_info(m_env, &mei);
1431  cur_mapsize = (uint64_t)mei.me_mapsize;
1432  LOG_PRINT_L1("LMDB memory map size: " << cur_mapsize);
1433  }
1434 
1435  if (need_resize())
1436  {
1437  LOG_PRINT_L0("LMDB memory map needs to be resized, doing that now.");
1438  do_resize();
1439  }
1440 
1441  int txn_flags = 0;
1442  if (mdb_flags & MDB_RDONLY)
1443  txn_flags |= MDB_RDONLY;
1444 
1445  // get a read/write MDB_txn, depending on mdb_flags
1446  mdb_txn_safe txn;
1447  if (auto mdb_res = mdb_txn_begin(m_env, NULL, txn_flags, txn))
1448  throw0(DB_ERROR(lmdb_error("Failed to create a transaction for the db: ", mdb_res).c_str()));
1449 
1450  // open necessary databases, and set properties as needed
1451  // uses macros to avoid having to change things too many places
1452  // also change blockchain_prune.cpp to match
1453  lmdb_db_open(txn, LMDB_BLOCKS, MDB_INTEGERKEY | MDB_CREATE, m_blocks, "Failed to open db handle for m_blocks");
1454 
1455  lmdb_db_open(txn, LMDB_BLOCK_INFO, MDB_INTEGERKEY | MDB_CREATE | MDB_DUPSORT | MDB_DUPFIXED, m_block_info, "Failed to open db handle for m_block_info");
1456  lmdb_db_open(txn, LMDB_BLOCK_HEIGHTS, MDB_INTEGERKEY | MDB_CREATE | MDB_DUPSORT | MDB_DUPFIXED, m_block_heights, "Failed to open db handle for m_block_heights");
1457 
1458  lmdb_db_open(txn, LMDB_TXS, MDB_INTEGERKEY | MDB_CREATE, m_txs, "Failed to open db handle for m_txs");
1459  lmdb_db_open(txn, LMDB_TXS_PRUNED, MDB_INTEGERKEY | MDB_CREATE, m_txs_pruned, "Failed to open db handle for m_txs_pruned");
1460  lmdb_db_open(txn, LMDB_TXS_PRUNABLE, MDB_INTEGERKEY | MDB_CREATE, m_txs_prunable, "Failed to open db handle for m_txs_prunable");
1461  lmdb_db_open(txn, LMDB_TXS_PRUNABLE_HASH, MDB_INTEGERKEY | MDB_DUPSORT | MDB_DUPFIXED | MDB_CREATE, m_txs_prunable_hash, "Failed to open db handle for m_txs_prunable_hash");
1462  if (!(mdb_flags & MDB_RDONLY))
1463  lmdb_db_open(txn, LMDB_TXS_PRUNABLE_TIP, MDB_INTEGERKEY | MDB_DUPSORT | MDB_DUPFIXED | MDB_CREATE, m_txs_prunable_tip, "Failed to open db handle for m_txs_prunable_tip");
1464  lmdb_db_open(txn, LMDB_TX_INDICES, MDB_INTEGERKEY | MDB_CREATE | MDB_DUPSORT | MDB_DUPFIXED, m_tx_indices, "Failed to open db handle for m_tx_indices");
1465  lmdb_db_open(txn, LMDB_TX_OUTPUTS, MDB_INTEGERKEY | MDB_CREATE, m_tx_outputs, "Failed to open db handle for m_tx_outputs");
1466 
1467  lmdb_db_open(txn, LMDB_OUTPUT_TXS, MDB_INTEGERKEY | MDB_CREATE | MDB_DUPSORT | MDB_DUPFIXED, m_output_txs, "Failed to open db handle for m_output_txs");
1468  lmdb_db_open(txn, LMDB_OUTPUT_AMOUNTS, MDB_INTEGERKEY | MDB_DUPSORT | MDB_DUPFIXED | MDB_CREATE, m_output_amounts, "Failed to open db handle for m_output_amounts");
1469 
1470  lmdb_db_open(txn, LMDB_SPENT_KEYS, MDB_INTEGERKEY | MDB_CREATE | MDB_DUPSORT | MDB_DUPFIXED, m_spent_keys, "Failed to open db handle for m_spent_keys");
1471 
1472  lmdb_db_open(txn, LMDB_TXPOOL_META, MDB_CREATE, m_txpool_meta, "Failed to open db handle for m_txpool_meta");
1473  lmdb_db_open(txn, LMDB_TXPOOL_BLOB, MDB_CREATE, m_txpool_blob, "Failed to open db handle for m_txpool_blob");
1474 
1475  // this subdb is dropped on sight, so it may not be present when we open the DB.
1476  // Since we use MDB_CREATE, we'll get an exception if we open read-only and it does not exist.
1477  // So we don't open for read-only, and also not drop below. It is not used elsewhere.
1478  if (!(mdb_flags & MDB_RDONLY))
1479  lmdb_db_open(txn, LMDB_HF_STARTING_HEIGHTS, MDB_CREATE, m_hf_starting_heights, "Failed to open db handle for m_hf_starting_heights");
1480 
1481  lmdb_db_open(txn, LMDB_HF_VERSIONS, MDB_INTEGERKEY | MDB_CREATE, m_hf_versions, "Failed to open db handle for m_hf_versions");
1482 
1483  lmdb_db_open(txn, LMDB_VALIDATORS, MDB_INTEGERKEY | MDB_CREATE, m_validators, "Failed to open db handle for m_validators");
1484  lmdb_db_open(txn, LMDB_UTXOS, MDB_CREATE, m_utxos, "Failed to open db handle for m_utxos");
1485  lmdb_db_open(txn, LMDB_ADDR_OUTPUTS, MDB_CREATE | MDB_DUPSORT | MDB_DUPFIXED, m_addr_outputs, "Failed to open db handle for m_addr_outputs");
1486  lmdb_db_open(txn, LMDB_TX_INPUTS, MDB_CREATE, m_tx_inputs, "Failed to open db handle for m_tx_inputs");
1487  lmdb_db_open(txn, LMDB_PROPERTIES, MDB_CREATE, m_properties, "Failed to open db handle for m_properties");
1488 
1489  mdb_set_dupsort(txn, m_spent_keys, compare_hash32);
1490  mdb_set_dupsort(txn, m_block_heights, compare_hash32);
1491  mdb_set_dupsort(txn, m_tx_indices, compare_hash32);
1492  mdb_set_dupsort(txn, m_output_amounts, compare_uint64);
1493  mdb_set_dupsort(txn, m_output_txs, compare_uint64);
1494  mdb_set_dupsort(txn, m_block_info, compare_uint64);
1495  if (!(mdb_flags & MDB_RDONLY))
1496  mdb_set_dupsort(txn, m_txs_prunable_tip, compare_uint64);
1497  mdb_set_compare(txn, m_txs_prunable, compare_uint64);
1498  mdb_set_dupsort(txn, m_txs_prunable_hash, compare_uint64);
1499 
1500  mdb_set_compare(txn, m_utxos, compare_data);
1501  mdb_set_compare(txn, m_txpool_meta, compare_hash32);
1502  mdb_set_compare(txn, m_txpool_blob, compare_hash32);
1503  mdb_set_compare(txn, m_properties, compare_string);
1504 
1505  mdb_set_dupsort(txn, m_addr_outputs, compare_uint64);
1506  mdb_set_compare(txn, m_addr_outputs, compare_publickey);
1507 
1508  mdb_set_compare(txn, m_tx_inputs, compare_data);
1509 
1510 
1511  if (!(mdb_flags & MDB_RDONLY))
1512  {
1513  result = mdb_drop(txn, m_hf_starting_heights, 1);
1514  if (result && result != MDB_NOTFOUND)
1515  throw0(DB_ERROR(lmdb_error("Failed to drop m_hf_starting_heights: ", result).c_str()));
1516  }
1517 
1518  // get and keep current height
1519  MDB_stat db_stats;
1520  if ((result = mdb_stat(txn, m_blocks, &db_stats)))
1521  throw0(DB_ERROR(lmdb_error("Failed to query m_blocks: ", result).c_str()));
1522  LOG_PRINT_L2("Setting m_height to: " << db_stats.ms_entries);
1523  uint64_t m_height = db_stats.ms_entries;
1524 
1525  bool compatible = true;
1526 
1527  MDB_val_str(k, "version");
1528  MDB_val v;
1529  auto get_result = mdb_get(txn, m_properties, &k, &v);
1530  if(get_result == MDB_SUCCESS)
1531  {
1532  const uint32_t db_version = *(const uint32_t*)v.mv_data;
1533  if (db_version > VERSION)
1534  {
1535  MWARNING("Existing lmdb database was made by a later version (" << db_version << "). We don't know how it will change yet.");
1536  compatible = false;
1537  }
1538 #if VERSION > 0
1539  else if (db_version < VERSION)
1540  {
1541  if (mdb_flags & MDB_RDONLY)
1542  {
1543  txn.abort();
1544  mdb_env_close(m_env);
1545  m_open = false;
1546  MFATAL("Existing lmdb database needs to be converted, which cannot be done on a read-only database.");
1547  MFATAL("Please run electroneumd once to convert the database.");
1548  return;
1549  }
1550  // Note that there was a schema change within version 0 as well.
1551  // See commit e5d2680094ee15889934fe28901e4e133cda56f2 2015/07/10
1552  // We don't handle the old format previous to that commit.
1553  txn.commit();
1554  m_open = true;
1555  migrate(db_version);
1556  return;
1557  }
1558 #endif
1559  }
1560  else
1561  {
1562  // if not found, and the DB is non-empty, this is probably
1563  // an "old" version 0, which we don't handle. If the DB is
1564  // empty it's fine.
1565  if (VERSION > 0 && m_height > 0)
1566  compatible = false;
1567  }
1568 
1569  if (!compatible)
1570  {
1571  txn.abort();
1572  mdb_env_close(m_env);
1573  m_open = false;
1574  MFATAL("Existing lmdb database is incompatible with this version.");
1575  MFATAL("Please delete the existing database and resync.");
1576  return;
1577  }
1578 
1579  if (!(mdb_flags & MDB_RDONLY))
1580  {
1581  // only write version on an empty DB
1582  if (m_height == 0)
1583  {
1584  MDB_val_str(k, "version");
1585  MDB_val_copy<uint32_t> v(VERSION);
1586  auto put_result = mdb_put(txn, m_properties, &k, &v, 0);
1587  if (put_result != MDB_SUCCESS)
1588  {
1589  txn.abort();
1590  mdb_env_close(m_env);
1591  m_open = false;
1592  MERROR("Failed to write version to database.");
1593  return;
1594  }
1595  }
1596  }
1597 
1598  // commit the transaction
1599  txn.commit();
1600 
1601  m_open = true;
1602  // from here, init should be finished
1603 }
#define DBF_RDONLY
#define DBF_FAST
#define DBF_FASTEST
#define DBF_SALVAGE
static int compare_string(const MDB_val *a, const MDB_val *b)
Definition: db_lmdb.cpp:165
static int compare_data(const MDB_val *a, const MDB_val *b)
Definition: db_lmdb.cpp:172
static int compare_publickey(const MDB_val *a, const MDB_val *b)
Definition: db_lmdb.cpp:188
static int compare_hash32(const MDB_val *a, const MDB_val *b)
Definition: db_lmdb.cpp:151
static int compare_uint64(const MDB_val *a, const MDB_val *b)
Definition: db_lmdb.cpp:143
#define VERSION
Definition: db_lmdb.cpp:60
int mdb_env_info(MDB_env *env, MDB_envinfo *stat)
Return information about the LMDB environment.
int mdb_env_open(MDB_env *env, const char *path, unsigned int flags, mdb_mode_t mode)
Open an environment handle.
int mdb_env_set_mapsize(MDB_env *env, mdb_size_t size)
Set the size of the memory map to use for this environment.
int mdb_put(MDB_txn *txn, MDB_dbi dbi, MDB_val *key, MDB_val *data, unsigned int flags)
Store items into a database.
int mdb_set_compare(MDB_txn *txn, MDB_dbi dbi, MDB_cmp_func *cmp)
Set a custom key comparison function for a database.
int mdb_get(MDB_txn *txn, MDB_dbi dbi, MDB_val *key, MDB_val *data)
Get items from a database.
int mdb_env_set_maxdbs(MDB_env *env, MDB_dbi dbs)
Set the maximum number of named databases for the environment.
int mdb_env_create(MDB_env **env)
Create an LMDB environment handle.
int mdb_drop(MDB_txn *txn, MDB_dbi dbi, int del)
Empty or delete+close a database.
int mdb_set_dupsort(MDB_txn *txn, MDB_dbi dbi, MDB_cmp_func *cmp)
Set a custom data comparison function for a MDB_DUPSORT database.
int mdb_txn_begin(MDB_env *env, MDB_txn *parent, unsigned int flags, MDB_txn **txn)
Create a transaction for use with the environment.
int mdb_env_set_maxreaders(MDB_env *env, unsigned int readers)
Set the maximum number of threads/reader slots for the environment.
#define MDB_INTEGERKEY
Definition: lmdb.h:349
#define MDB_DUPFIXED
Definition: lmdb.h:351
#define MDB_DUPSORT
Definition: lmdb.h:345
#define MDB_CREATE
Definition: lmdb.h:357
#define MDB_NORDAHEAD
Definition: lmdb.h:332
#define MDB_NOSYNC
Definition: lmdb.h:318
#define MDB_PREVSNAPSHOT
Definition: lmdb.h:336
#define MDB_WRITEMAP
Definition: lmdb.h:324
#define MDB_MAPASYNC
Definition: lmdb.h:326
mdb_size_t me_mapsize
Definition: lmdb.h:503
#define MFATAL(x)
Definition: misc_log_ex.h:72
#define MWARNING(x)
Definition: misc_log_ex.h:74
#define MCLOG_RED(level, cat, x)
Definition: misc_log_ex.h:58
#define LOG_PRINT_L1(x)
Definition: misc_log_ex.h:100
#define LOG_PRINT_L2(x)
Definition: misc_log_ex.h:101
@ Warning
Useful when application has potentially harmful situtaions.
@ Info
Mainly useful to represent current progress of application.
boost::optional< bool > is_hdd(const char *file_path)
Definition: util.cpp:813
unsigned get_max_concurrency()
Definition: util.cpp:868
Information about the environment.
Definition: lmdb.h:501

◆ pop_block()

void cryptonote::BlockchainLMDB::pop_block ( block blk,
std::vector< transaction > &  txs 
)
virtual

pops the top block off the blockchain

The subclass should remove the most recent block from the blockchain, along with all transactions, outputs, and other metadata created as a result of its addition to the blockchain. Most of this is handled by the concrete members of the base class provided the subclass correctly implements remove_* functions.

The subclass should return by reference the popped block and its associated transactions

Parameters
blkreturn-by-reference the block which was popped
txsreturn-by-reference the transactions from the popped block

Reimplemented from cryptonote::BlockchainDB.

Definition at line 4313 of file db_lmdb.cpp.

4314 {
4315  LOG_PRINT_L3("BlockchainLMDB::" << __func__);
4316  check_open();
4317 
4318  block_wtxn_start();
4319 
4320  try
4321  {
4322  BlockchainDB::pop_block(blk, txs);
4323  block_wtxn_stop();
4324  }
4325  catch (...)
4326  {
4327  block_wtxn_abort();
4328  throw;
4329  }
4330 }
virtual void block_wtxn_abort()
Definition: db_lmdb.cpp:4261
virtual void block_wtxn_start()
Definition: db_lmdb.cpp:4206
virtual void block_wtxn_stop()
Definition: db_lmdb.cpp:4239
Here is the call graph for this function:

◆ prune_blockchain()

bool cryptonote::BlockchainLMDB::prune_blockchain ( uint32_t  pruning_seed = 0)
virtual

prunes the blockchain

Parameters
pruning_seedthe seed to use, 0 for default (highly recommended)
Returns
success iff true

Implements cryptonote::BlockchainDB.

Definition at line 2726 of file db_lmdb.cpp.

2727 {
2728  return prune_worker(prune_mode_prune, pruning_seed);
2729 }
@ prune_mode_prune
Definition: db_lmdb.cpp:2441

◆ remove_data_file()

bool cryptonote::BlockchainLMDB::remove_data_file ( const std::string &  folder) const
virtual

remove file(s) storing the database

This function is for resetting the database (for core tests, functional tests, etc). The function reset() is not usable because it needs to open the database file first which can fail if the existing database file is in an incompatible format. As such, this function needs to be called before calling open().

Parameters
folderThe path of the folder containing the database file(s) which must not end with slash '/'.
Returns
true if the operation is succesfull

Implements cryptonote::BlockchainDB.

Definition at line 1717 of file db_lmdb.cpp.

1718 {
1719  const std::string filename = folder + "/data.mdb";
1720  try
1721  {
1722  boost::filesystem::remove(filename);
1723  }
1724  catch (const std::exception &e)
1725  {
1726  MERROR("Failed to remove " << filename << ": " << e.what());
1727  return false;
1728  }
1729  return true;
1730 }

◆ remove_txpool_tx()

void cryptonote::BlockchainLMDB::remove_txpool_tx ( const crypto::hash txid)
virtual

remove a txpool transaction

Parameters
txidthe transaction id of the transation to remove

Implements cryptonote::BlockchainDB.

Definition at line 2328 of file db_lmdb.cpp.

2329 {
2330  LOG_PRINT_L3("BlockchainLMDB::" << __func__);
2331  check_open();
2332  mdb_txn_cursors *m_cursors = &m_wcursors;
2333 
2334  CURSOR(txpool_meta)
2335  CURSOR(txpool_blob)
2336 
2337  MDB_val k = {sizeof(txid), (void *)&txid};
2338  auto result = mdb_cursor_get(m_cur_txpool_meta, &k, NULL, MDB_SET);
2339  if (result != 0 && result != MDB_NOTFOUND)
2340  throw1(DB_ERROR(lmdb_error("Error finding txpool tx meta to remove: ", result).c_str()));
2341  if (!result)
2342  {
2343  result = mdb_cursor_del(m_cur_txpool_meta, 0);
2344  if (result)
2345  throw1(DB_ERROR(lmdb_error("Error adding removal of txpool tx metadata to db transaction: ", result).c_str()));
2346  }
2347  result = mdb_cursor_get(m_cur_txpool_blob, &k, NULL, MDB_SET);
2348  if (result != 0 && result != MDB_NOTFOUND)
2349  throw1(DB_ERROR(lmdb_error("Error finding txpool tx blob to remove: ", result).c_str()));
2350  if (!result)
2351  {
2352  result = mdb_cursor_del(m_cur_txpool_blob, 0);
2353  if (result)
2354  throw1(DB_ERROR(lmdb_error("Error adding removal of txpool tx blob to db transaction: ", result).c_str()));
2355  }
2356 }
int mdb_cursor_del(MDB_cursor *cursor, unsigned int flags)
Delete current key/data pair.
Here is the call graph for this function:

◆ reset()

void cryptonote::BlockchainLMDB::reset ( )
virtual

Remove everything from the BlockchainDB.

This function should completely remove all data from a BlockchainDB.

Use with caution!

If any of this cannot be done, the subclass should throw the corresponding subclass of DB_EXCEPTION

Implements cryptonote::BlockchainDB.

Definition at line 1643 of file db_lmdb.cpp.

1644 {
1645  LOG_PRINT_L3("BlockchainLMDB::" << __func__);
1646  check_open();
1647 
1648  mdb_txn_safe txn;
1649  if (auto result = lmdb_txn_begin(m_env, NULL, 0, txn))
1650  throw0(DB_ERROR(lmdb_error("Failed to create a transaction for the db: ", result).c_str()));
1651 
1652  if (auto result = mdb_drop(txn, m_blocks, 0))
1653  throw0(DB_ERROR(lmdb_error("Failed to drop m_blocks: ", result).c_str()));
1654  if (auto result = mdb_drop(txn, m_block_info, 0))
1655  throw0(DB_ERROR(lmdb_error("Failed to drop m_block_info: ", result).c_str()));
1656  if (auto result = mdb_drop(txn, m_block_heights, 0))
1657  throw0(DB_ERROR(lmdb_error("Failed to drop m_block_heights: ", result).c_str()));
1658  if (auto result = mdb_drop(txn, m_txs_pruned, 0))
1659  throw0(DB_ERROR(lmdb_error("Failed to drop m_txs_pruned: ", result).c_str()));
1660  if (auto result = mdb_drop(txn, m_txs_prunable, 0))
1661  throw0(DB_ERROR(lmdb_error("Failed to drop m_txs_prunable: ", result).c_str()));
1662  if (auto result = mdb_drop(txn, m_txs_prunable_hash, 0))
1663  throw0(DB_ERROR(lmdb_error("Failed to drop m_txs_prunable_hash: ", result).c_str()));
1664  if (auto result = mdb_drop(txn, m_txs_prunable_tip, 0))
1665  throw0(DB_ERROR(lmdb_error("Failed to drop m_txs_prunable_tip: ", result).c_str()));
1666  if (auto result = mdb_drop(txn, m_tx_indices, 0))
1667  throw0(DB_ERROR(lmdb_error("Failed to drop m_tx_indices: ", result).c_str()));
1668  if (auto result = mdb_drop(txn, m_tx_outputs, 0))
1669  throw0(DB_ERROR(lmdb_error("Failed to drop m_tx_outputs: ", result).c_str()));
1670  if (auto result = mdb_drop(txn, m_output_txs, 0))
1671  throw0(DB_ERROR(lmdb_error("Failed to drop m_output_txs: ", result).c_str()));
1672  if (auto result = mdb_drop(txn, m_output_amounts, 0))
1673  throw0(DB_ERROR(lmdb_error("Failed to drop m_output_amounts: ", result).c_str()));
1674  if (auto result = mdb_drop(txn, m_spent_keys, 0))
1675  throw0(DB_ERROR(lmdb_error("Failed to drop m_spent_keys: ", result).c_str()));
1676  (void)mdb_drop(txn, m_hf_starting_heights, 0); // this one is dropped in new code
1677  if (auto result = mdb_drop(txn, m_hf_versions, 0))
1678  throw0(DB_ERROR(lmdb_error("Failed to drop m_hf_versions: ", result).c_str()));
1679  if (auto result = mdb_drop(txn, m_validators, 0))
1680  throw0(DB_ERROR(lmdb_error("Failed to drop m_validators: ", result).c_str()));
1681  if (auto result = mdb_drop(txn, m_utxos, 0))
1682  throw0(DB_ERROR(lmdb_error("Failed to drop m_utxos: ", result).c_str()));
1683  if (auto result = mdb_drop(txn, m_addr_outputs, 0))
1684  throw0(DB_ERROR(lmdb_error("Failed to drop m_addr_outputs: ", result).c_str()));
1685  if (auto result = mdb_drop(txn, m_tx_inputs, 0))
1686  throw0(DB_ERROR(lmdb_error("Failed to drop m_tx_inputs: ", result).c_str()));
1687  if (auto result = mdb_drop(txn, m_properties, 0))
1688  throw0(DB_ERROR(lmdb_error("Failed to drop m_properties: ", result).c_str()));
1689 
1690  // init with current version
1691  MDB_val_str(k, "version");
1692  MDB_val_copy<uint32_t> v(VERSION);
1693  if (auto result = mdb_put(txn, m_properties, &k, &v, 0))
1694  throw0(DB_ERROR(lmdb_error("Failed to write version to database: ", result).c_str()));
1695 
1696  txn.commit();
1697  m_cum_size = 0;
1698  m_cum_count = 0;
1699 }
Here is the call graph for this function:

◆ safesyncmode()

void cryptonote::BlockchainLMDB::safesyncmode ( const bool  onoff)
virtual

toggle safe syncs for the DB

Used to switch DBF_SAFE on or off after starting up with DBF_FAST.

Implements cryptonote::BlockchainDB.

Definition at line 1637 of file db_lmdb.cpp.

1638 {
1639  MINFO("switching safe mode " << (onoff ? "on" : "off"));
1640  mdb_env_set_flags(m_env, MDB_NOSYNC|MDB_MAPASYNC, !onoff);
1641 }
int mdb_env_set_flags(MDB_env *env, unsigned int flags, int onoff)
Set environment flags.
#define MINFO(x)
Definition: misc_log_ex.h:75
Here is the call graph for this function:

◆ set_batch_transactions()

void cryptonote::BlockchainLMDB::set_batch_transactions ( bool  )
virtual

sets whether or not to batch transactions

If the subclass implements batching, this function tells it to begin batching automatically.

If the subclass implements batching and has a batch in-progress, a parameter of false should disable batching and call batch_stop() to store the current batch.

If any of this cannot be done, the subclass should throw the corresponding subclass of DB_EXCEPTION

Parameters
boolbatch whether or not to use batch transactions.

Implements cryptonote::BlockchainDB.

Definition at line 4143 of file db_lmdb.cpp.

4144 {
4145  LOG_PRINT_L3("BlockchainLMDB::" << __func__);
4146  if ((batch_transactions) && (m_batch_transactions))
4147  {
4148  MINFO("batch transaction mode already enabled, but asked to enable batch mode");
4149  }
4150  m_batch_transactions = batch_transactions;
4151  MINFO("batch transactions " << (m_batch_transactions ? "enabled" : "disabled"));
4152 }

◆ set_block_cumulative_difficulty()

void cryptonote::BlockchainLMDB::set_block_cumulative_difficulty ( uint64_t  height,
difficulty_type  diff 
)
virtual

sets a block's cumulative difficulty

The subclass should return true if the cumulative difficulty is set successfully

If the block does not exist, the subclass should throw BLOCK_DNE

Parameters
heightthe height requested
diffthe cumulative difficulty value to be set
Returns
true | false

Implements cryptonote::BlockchainDB.

Definition at line 3127 of file db_lmdb.cpp.

3128 {
3129  LOG_PRINT_L3("BlockchainLMDB::" << __func__ << " height: " << height);
3130  check_open();
3131  mdb_txn_cursors *m_cursors = &m_wcursors;
3132 
3133  int result;
3134 
3135  CURSOR(block_info)
3136 
3137  MDB_val_set(val_bi, height);
3138  result = mdb_cursor_get(m_cur_block_info, (MDB_val *)&zerokval, &val_bi, MDB_GET_BOTH);
3139  if (result == MDB_NOTFOUND)
3140  {
3141  throw0(BLOCK_DNE(std::string("Attempt to set cumulative difficulty from height ").append(boost::lexical_cast<std::string>(height)).append(" failed -- difficulty not in db").c_str()));
3142  }
3143  else if (result)
3144  throw0(DB_ERROR("Error attempting to set a cumulative difficulty"));
3145 
3146  mdb_block_info *result_bi = (mdb_block_info *)val_bi.mv_data;
3147 
3148  mdb_block_info bi;
3149  bi.bi_height = result_bi->bi_height;
3150  bi.bi_timestamp = result_bi->bi_timestamp;
3151  bi.bi_coins = result_bi->bi_coins;
3152  bi.bi_weight = result_bi->bi_weight;
3153  //bi.bi_diff_lo = diff; // TODO
3154  bi.bi_hash = result_bi->bi_hash;
3155 
3156  MDB_val_set(val, bi);
3157  result = mdb_cursor_put(m_cur_block_info, (MDB_val *)&val_bi, &val, MDB_CURRENT);
3158  if (result)
3159  throw0(DB_ERROR(lmdb_error("Failed to set cumulative difficulty to db transaction: ", result).c_str()));
3160 
3161 }
#define MDB_CURRENT
Definition: lmdb.h:371
Here is the call graph for this function:

◆ sync()

void cryptonote::BlockchainLMDB::sync ( )
virtual

sync the BlockchainDB with disk

This function should write any changes to whatever permanent backing store the subclass uses. Example: a BlockchainDB instance which keeps the whole blockchain in RAM won't need to regularly access a disk, but should write out its state when this is called.

If any of this cannot be done, the subclass should throw the corresponding subclass of DB_EXCEPTION

Implements cryptonote::BlockchainDB.

Definition at line 1621 of file db_lmdb.cpp.

1622 {
1623  LOG_PRINT_L3("BlockchainLMDB::" << __func__);
1624  check_open();
1625 
1626  if (is_read_only())
1627  return;
1628 
1629  // Does nothing unless LMDB environment was opened with MDB_NOSYNC or in part
1630  // MDB_NOMETASYNC. Force flush to be synchronous.
1631  if (auto result = mdb_env_sync(m_env, true))
1632  {
1633  throw0(DB_ERROR(lmdb_error("Failed to sync database: ", result).c_str()));
1634  }
1635 }
int mdb_env_sync(MDB_env *env, int force)
Flush the data buffers to disk.
Here is the call graph for this function:
Here is the caller graph for this function:

◆ top_block_hash()

crypto::hash cryptonote::BlockchainLMDB::top_block_hash ( uint64_t block_height = NULL) const
virtual

fetch the top block's hash

The subclass should return the hash of the most recent block

Parameters
block_heightif non NULL, returns the height of that block (ie, the blockchain height minus 1)
Returns
the top block's hash

Implements cryptonote::BlockchainDB.

Definition at line 3302 of file db_lmdb.cpp.

3303 {
3304  LOG_PRINT_L3("BlockchainLMDB::" << __func__);
3305  check_open();
3306  uint64_t m_height = height();
3307  if (block_height)
3308  *block_height = m_height - 1;
3309  if (m_height != 0)
3310  {
3311  return get_block_hash_from_height(m_height - 1);
3312  }
3313 
3314  return null_hash;
3315 }
Here is the call graph for this function:

◆ tx_exists() [1/2]

bool cryptonote::BlockchainLMDB::tx_exists ( const crypto::hash h) const
virtual

check if a transaction with a given hash exists

The subclass should check if a transaction is stored which has the given hash and return true if so, false otherwise.

Parameters
hthe hash to check against
tx_id(optional) returns the tx_id for the tx hash
Returns
true if the transaction exists, otherwise false

Implements cryptonote::BlockchainDB.

Definition at line 3368 of file db_lmdb.cpp.

3369 {
3370  LOG_PRINT_L3("BlockchainLMDB::" << __func__);
3371  check_open();
3372 
3374  RCURSOR(tx_indices);
3375 
3376  MDB_val_set(key, h);
3377  bool tx_found = false;
3378 
3379  TIME_MEASURE_START(time1);
3380  auto get_result = mdb_cursor_get(m_cur_tx_indices, (MDB_val *)&zerokval, &key, MDB_GET_BOTH);
3381  if (get_result == 0)
3382  tx_found = true;
3383  else if (get_result != MDB_NOTFOUND)
3384  throw0(DB_ERROR(lmdb_error(std::string("DB error attempting to fetch transaction index from hash ") + epee::string_tools::pod_to_hex(h) + ": ", get_result).c_str()));
3385 
3386  TIME_MEASURE_FINISH(time1);
3387  time_tx_exists += time1;
3388 
3390 
3391  if (! tx_found)
3392  {
3393  LOG_PRINT_L1("transaction with hash " << epee::string_tools::pod_to_hex(h) << " not found in db");
3394  return false;
3395  }
3396 
3397  return true;
3398 }
uint64_t time_tx_exists
a performance metric
Here is the call graph for this function:

◆ tx_exists() [2/2]

bool cryptonote::BlockchainLMDB::tx_exists ( const crypto::hash h,
uint64_t tx_index 
) const
virtual

Implements cryptonote::BlockchainDB.

Definition at line 3400 of file db_lmdb.cpp.

3401 {
3402  LOG_PRINT_L3("BlockchainLMDB::" << __func__);
3403  check_open();
3404 
3406  RCURSOR(tx_indices);
3407 
3408  MDB_val_set(v, h);
3409 
3410  TIME_MEASURE_START(time1);
3411  auto get_result = mdb_cursor_get(m_cur_tx_indices, (MDB_val *)&zerokval, &v, MDB_GET_BOTH);
3412  TIME_MEASURE_FINISH(time1);
3413  time_tx_exists += time1;
3414  if (!get_result) {
3415  txindex *tip = (txindex *)v.mv_data;
3416  tx_id = tip->data.tx_id;
3417  }
3418 
3420 
3421  bool ret = false;
3422  if (get_result == MDB_NOTFOUND)
3423  {
3424  LOG_PRINT_L1("transaction with hash " << epee::string_tools::pod_to_hex(h) << " not found in db");
3425  }
3426  else if (get_result)
3427  throw0(DB_ERROR(lmdb_error("DB error attempting to fetch transaction from hash", get_result).c_str()));
3428  else
3429  ret = true;
3430 
3431  return ret;
3432 }
Here is the call graph for this function:

◆ txpool_has_tx()

bool cryptonote::BlockchainLMDB::txpool_has_tx ( const crypto::hash txid) const
virtual

check whether a txid is in the txpool

Implements cryptonote::BlockchainDB.

Definition at line 2312 of file db_lmdb.cpp.

2313 {
2314  LOG_PRINT_L3("BlockchainLMDB::" << __func__);
2315  check_open();
2316 
2318  RCURSOR(txpool_meta)
2319 
2320  MDB_val k = {sizeof(txid), (void *)&txid};
2321  auto result = mdb_cursor_get(m_cur_txpool_meta, &k, NULL, MDB_SET);
2322  if (result != 0 && result != MDB_NOTFOUND)
2323  throw1(DB_ERROR(lmdb_error("Error finding txpool tx meta: ", result).c_str()));
2325  return result != MDB_NOTFOUND;
2326 }
Here is the call graph for this function:

◆ unlock()

void cryptonote::BlockchainLMDB::unlock ( )
virtual

This function releases the BlockchainDB lock.

The subclass, should it have implemented lock(), will release any lock held by the calling thread. In the case of recursive locking, it should release one instance of a lock.

If any of this cannot be done, the subclass should throw the corresponding subclass of DB_EXCEPTION

Implements cryptonote::BlockchainDB.

Definition at line 1748 of file db_lmdb.cpp.

1749 {
1750  LOG_PRINT_L3("BlockchainLMDB::" << __func__);
1751  check_open();
1752 }

◆ update_pruning()

bool cryptonote::BlockchainLMDB::update_pruning ( )
virtual

prunes recent blockchain changes as needed, iff pruning is enabled

Returns
success iff true

Implements cryptonote::BlockchainDB.

Definition at line 2731 of file db_lmdb.cpp.

2732 {
2733  return prune_worker(prune_mode_update, 0);
2734 }
@ prune_mode_update
Definition: db_lmdb.cpp:2441

◆ update_txpool_tx()

void cryptonote::BlockchainLMDB::update_txpool_tx ( const crypto::hash txid,
const txpool_tx_meta_t details 
)
virtual

update a txpool transaction's metadata

Parameters
txidthe txid of the transaction to update
detailsthe details of the transaction to update

Implements cryptonote::BlockchainDB.

Definition at line 2241 of file db_lmdb.cpp.

2242 {
2243  LOG_PRINT_L3("BlockchainLMDB::" << __func__);
2244  check_open();
2245  mdb_txn_cursors *m_cursors = &m_wcursors;
2246 
2247  CURSOR(txpool_meta)
2248  CURSOR(txpool_blob)
2249 
2250  MDB_val k = {sizeof(txid), (void *)&txid};
2251  MDB_val v;
2252  auto result = mdb_cursor_get(m_cur_txpool_meta, &k, &v, MDB_SET);
2253  if (result != 0)
2254  throw1(DB_ERROR(lmdb_error("Error finding txpool tx meta to update: ", result).c_str()));
2255  result = mdb_cursor_del(m_cur_txpool_meta, 0);
2256  if (result)
2257  throw1(DB_ERROR(lmdb_error("Error adding removal of txpool tx metadata to db transaction: ", result).c_str()));
2258  v = MDB_val({sizeof(meta), (void *)&meta});
2259  if ((result = mdb_cursor_put(m_cur_txpool_meta, &k, &v, MDB_NODUPDATA)) != 0) {
2260  if (result == MDB_KEYEXIST)
2261  throw1(DB_ERROR("Attempting to add txpool tx metadata that's already in the db"));
2262  else
2263  throw1(DB_ERROR(lmdb_error("Error adding txpool tx metadata to db transaction: ", result).c_str()));
2264  }
2265 }
struct MDB_val MDB_val
Generic structure used for passing keys and data in and out of the database.
Here is the call graph for this function:

The documentation for this class was generated from the following files: