Electroneum
Loading...
Searching...
No Matches
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.
virtual void close ()
 close the BlockchainDB
virtual void sync ()
 sync the BlockchainDB with disk
virtual void safesyncmode (const bool onoff)
 toggle safe syncs for the DB
virtual void reset ()
 Remove everything from the BlockchainDB.
virtual std::vector< std::string > get_filenames () const
 get all files used by the BlockchainDB (if any)
virtual bool remove_data_file (const std::string &folder) const
 remove file(s) storing the database
virtual std::string get_db_name () const
 gets the name of the folder the BlockchainDB's file(s) should be in
virtual bool lock ()
 acquires the BlockchainDB lock
virtual void unlock ()
 This function releases the BlockchainDB lock.
virtual bool block_exists (const crypto::hash &h, uint64_t *height=NULL) const
 checks if a block exists
virtual uint64_t get_block_height (const crypto::hash &h) const
 gets the height of the block with a given hash
virtual block_header get_block_header (const crypto::hash &h) const
 fetch a block header
virtual cryptonote::blobdata get_block_blob (const crypto::hash &h) const
 fetches the block with the given hash
virtual cryptonote::blobdata get_block_blob_from_height (const uint64_t &height) const
 fetch a block blob by height
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
virtual uint64_t get_block_timestamp (const uint64_t &height) const
 fetch a block's timestamp
virtual uint64_t get_top_block_timestamp () const
 fetch the top block's timestamp
virtual size_t get_block_weight (const uint64_t &height) const
 fetch a block's weight
virtual std::vector< uint64_tget_block_weights (uint64_t start_height, size_t count) const
 fetch the last N blocks' weights
virtual void set_block_cumulative_difficulty (uint64_t height, difficulty_type diff)
 sets a block's cumulative difficulty
virtual difficulty_type get_block_cumulative_difficulty (const uint64_t &height) const
 fetch a block's cumulative difficulty
virtual difficulty_type get_block_difficulty (const uint64_t &height) const
 fetch a block's difficulty
virtual uint64_t get_block_already_generated_coins (const uint64_t &height) const
 fetch a block's already generated coins
virtual uint64_t get_block_long_term_weight (const uint64_t &height) const
 fetch a block's long term weight
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
virtual crypto::hash get_block_hash_from_height (const uint64_t &height) const
 fetch a block's hash
virtual std::vector< blockget_blocks_range (const uint64_t &h1, const uint64_t &h2) const
 fetch a list of blocks
virtual std::vector< crypto::hashget_hashes_range (const uint64_t &h1, const uint64_t &h2) const
 fetch a list of block hashes
virtual crypto::hash top_block_hash (uint64_t *block_height=NULL) const
 fetch the top block's hash
virtual block get_top_block () const
 fetch the top block
virtual uint64_t height () const
 fetch the current blockchain height
virtual bool tx_exists (const crypto::hash &h) const
 check if a transaction with a given hash exists
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
virtual bool get_tx_blob (const crypto::hash &h, cryptonote::blobdata &tx) const
 fetches the transaction blob with the given hash
virtual bool get_pruned_tx_blob (const crypto::hash &h, cryptonote::blobdata &tx) const
 fetches the pruned transaction blob with the given hash
virtual bool get_prunable_tx_blob (const crypto::hash &h, cryptonote::blobdata &tx) const
 fetches the prunable transaction blob with the given hash
virtual bool get_prunable_tx_hash (const crypto::hash &tx_hash, crypto::hash &prunable_hash) const
 fetches the prunable transaction hash
virtual uint64_t get_tx_count () const
 fetches the total number of transactions ever
virtual std::vector< transactionget_tx_list (const std::vector< crypto::hash > &hlist) const
 fetches a list of transactions based on their hashes
virtual uint64_t get_tx_block_height (const crypto::hash &h) const
 fetches the height of a transaction's block
virtual uint64_t get_num_outputs (const uint64_t &amount) const
 fetches the number of outputs of a given amount
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
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
virtual tx_out_index get_output_tx_and_index_from_global (const uint64_t &index) const
 gets an output's tx hash and index
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
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
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
virtual bool has_key_image (const crypto::key_image &img) const
 check if a key image is stored as spent
virtual void add_txpool_tx (const crypto::hash &txid, const cryptonote::blobdata &blob, const txpool_tx_meta_t &meta)
 add a txpool transaction
virtual void update_txpool_tx (const crypto::hash &txid, const txpool_tx_meta_t &meta)
 update a txpool transaction's metadata
virtual uint64_t get_txpool_tx_count (bool include_unrelayed_txes=true) const
 get the number of transactions in the txpool
virtual bool txpool_has_tx (const crypto::hash &txid) const
 check whether a txid is in the txpool
virtual void remove_txpool_tx (const crypto::hash &txid)
 remove a txpool transaction
virtual bool get_txpool_tx_meta (const crypto::hash &txid, txpool_tx_meta_t &meta) const
 get a txpool transaction's metadata
virtual bool get_txpool_tx_blob (const crypto::hash &txid, cryptonote::blobdata &bd) const
 get a txpool transaction's blob
virtual cryptonote::blobdata get_txpool_tx_blob (const crypto::hash &txid) const
 get a txpool transaction's blob
virtual uint32_t get_blockchain_pruning_seed () const
 get the blockchain pruning seed
virtual bool prune_blockchain (uint32_t pruning_seed=0)
 prunes the blockchain
virtual bool update_pruning ()
 prunes recent blockchain changes as needed, iff pruning is enabled
virtual bool check_pruning ()
 checks pruning was done correctly, iff enabled
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
virtual bool for_all_key_images (std::function< bool(const crypto::key_image &)>) const
 runs a function over all key images stored
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
virtual bool for_all_transactions (std::function< bool(const crypto::hash &, const cryptonote::transaction &)>, bool pruned) const
 runs a function over all transactions stored
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
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
virtual void set_batch_transactions (bool batch_transactions)
 sets whether or not to batch transactions
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
virtual void batch_commit ()
virtual void batch_stop ()
 ends a batch transaction
virtual void batch_abort ()
 aborts a batch transaction
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
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
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 std::vector< address_txsget_addr_tx_all (const crypto::public_key &combined_key)
virtual std::vector< address_txsget_addr_tx_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.
virtual ~BlockchainDB ()
 An empty destructor.
void reset_stats ()
 reset profiling stats
void show_stats ()
 show profiling stats
bool is_open () const
 Gets the current open/ready state of the BlockchainDB.
virtual void set_hard_fork (HardFork *hf)
virtual block get_block (const crypto::hash &h) const
 fetches the block with the given hash
virtual block get_block_from_height (const uint64_t &height) const
 fetch a block by height
virtual transaction get_tx (const crypto::hash &h) const
 fetches the transaction with the given hash
virtual transaction get_pruned_tx (const crypto::hash &h) const
 fetches the transaction base with the given hash
virtual bool get_tx (const crypto::hash &h, transaction &tx) const
 fetches the transaction with the given hash
virtual bool get_pruned_tx (const crypto::hash &h, transaction &tx) const
 fetches the transaction base with the given hash
virtual uint64_t get_indexing_base () const
 return index of the first element (should be hidden, but isn't)
void set_auto_remove_logs (bool auto_remove)
 set whether or not to automatically remove logs

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

Additional Inherited Members

Public Attributes inherited from cryptonote::BlockchainDB
bool m_open
 Whether or not the BlockchainDB is open/ready for use.
epee::critical_section m_synchronization_lock
 A lock, currently for when BlockchainLMDB needs to resize the backing db file.
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
Protected Attributes inherited from cryptonote::BlockchainDB
uint64_t time_tx_exists = 0
 a performance metric
uint64_t time_commit1 = 0
 a performance metric
bool m_auto_remove_logs = true
 whether or not to automatically remove old logs
HardForkm_hardfork

Detailed Description

Definition at line 194 of file db_lmdb.h.

Constructor & Destructor Documentation

◆ BlockchainLMDB()

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

Definition at line 1338 of file db_lmdb.cpp.

1338 : BlockchainDB()
1339{
1340 LOG_PRINT_L3("BlockchainLMDB::" << __func__);
1341 // initialize folder to something "safe" just in case
1342 // someone accidentally misuses this class...
1343 m_folder = "thishsouldnotexistbecauseitisgibberish";
1344
1345 m_batch_transactions = batch_transactions;
1346 m_write_txn = nullptr;
1347 m_write_batch_txn = nullptr;
1348 m_batch_active = false;
1349 m_cum_size = 0;
1350 m_cum_count = 0;
1351
1352 // reset may also need changing when initialize things here
1353
1354 m_hardfork = nullptr;
1355}
BlockchainDB()
An empty constructor.
#define LOG_PRINT_L3(x)
Here is the call graph for this function:

◆ ~BlockchainLMDB()

cryptonote::BlockchainLMDB::~BlockchainLMDB ( )

Definition at line 1324 of file db_lmdb.cpp.

1325{
1326 LOG_PRINT_L3("BlockchainLMDB::" << __func__);
1327
1328 // batch transaction shouldn't be active at this point. If it is, consider it aborted.
1329 if (m_batch_active)
1330 {
1331 try { batch_abort(); }
1332 catch (...) { /* ignore */ }
1333 }
1334 if (m_open)
1335 close();
1336}
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:4320
virtual void close()
close the BlockchainDB
Definition db_lmdb.cpp:1624
Here is the call graph for this function:

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 4484 of file db_lmdb.cpp.

4486{
4487 LOG_PRINT_L3("BlockchainLMDB::" << __func__);
4488 check_open();
4489 uint64_t m_height = height();
4490
4491 if (m_height % 1024 == 0)
4492 {
4493 // for batch mode, DB resize check is done at start of batch transaction
4494 if (! m_batch_active && need_resize())
4495 {
4496 LOG_PRINT_L0("LMDB memory map needs to be resized, doing that now.");
4497 do_resize();
4498 }
4499 }
4500
4501 try
4502 {
4503 BlockchainDB::add_block(blk, block_weight, long_term_block_weight, cumulative_difficulty, coins_generated, txs);
4504 }
4505 catch (const DB_ERROR_TXN_START& e)
4506 {
4507 throw;
4508 }
4509
4510 return ++m_height;
4511}
virtual uint64_t height() const
fetch the current blockchain height
Definition db_lmdb.cpp:3532
#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 2415 of file db_lmdb.cpp.

2416{
2417 LOG_PRINT_L3("BlockchainLMDB::" << __func__);
2418 check_open();
2419 mdb_txn_cursors *m_cursors = &m_wcursors;
2420
2421 CURSOR(txpool_meta)
2422 CURSOR(txpool_blob)
2423
2424 MDB_val k = {sizeof(txid), (void *)&txid};
2425 MDB_val v = {sizeof(meta), (void *)&meta};
2426 if (auto result = mdb_cursor_put(m_cur_txpool_meta, &k, &v, MDB_NODUPDATA)) {
2427 if (result == MDB_KEYEXIST)
2428 throw1(DB_ERROR("Attempting to add txpool tx metadata that's already in the db"));
2429 else
2430 throw1(DB_ERROR(lmdb_error("Error adding txpool tx metadata to db transaction: ", result).c_str()));
2431 }
2432 MDB_val_sized(blob_val, blob);
2433 if (auto result = mdb_cursor_put(m_cur_txpool_blob, &k, &blob_val, MDB_NODUPDATA)) {
2434 if (result == MDB_KEYEXIST)
2435 throw1(DB_ERROR("Attempting to add txpool tx blob that's already in the db"));
2436 else
2437 throw1(DB_ERROR(lmdb_error("Error adding txpool tx blob to db transaction: ", result).c_str()));
2438 }
2439}
#define MDB_val_sized(var, val)
Definition db_lmdb.cpp:91
#define CURSOR(name)
Definition db_lmdb.cpp:285
#define m_cur_txpool_blob
Definition db_lmdb.h:95
#define m_cur_txpool_meta
Definition db_lmdb.h:94
#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 MDB_val MDB_val
Generic structure used for passing keys and data in and out of the database.
struct cryptonote::mdb_txn_cursors mdb_txn_cursors
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 4320 of file db_lmdb.cpp.

4321{
4322 LOG_PRINT_L3("BlockchainLMDB::" << __func__);
4323 if (! m_batch_transactions)
4324 throw0(DB_ERROR("batch transactions not enabled"));
4325 if (! m_batch_active)
4326 throw1(DB_ERROR("batch transaction not in progress"));
4327 if (m_write_batch_txn == nullptr)
4328 throw1(DB_ERROR("batch transaction not in progress"));
4329 if (m_writer != boost::this_thread::get_id())
4330 throw1(DB_ERROR("batch transaction owned by other thread"));
4331 check_open();
4332 // for destruction of batch transaction
4333 m_write_txn = nullptr;
4334 // explicitly call in case mdb_env_close() (BlockchainLMDB::close()) called before BlockchainLMDB destructor called.
4335 m_write_batch_txn->abort();
4336 delete m_write_batch_txn;
4337 m_write_batch_txn = nullptr;
4338 m_batch_active = false;
4339 memset(&m_wcursors, 0, sizeof(m_wcursors));
4340 LOG_PRINT_L3("batch transaction: aborted");
4341}
Here is the caller graph for this function:

◆ batch_commit()

void cryptonote::BlockchainLMDB::batch_commit ( )
virtual

Definition at line 4254 of file db_lmdb.cpp.

4255{
4256 LOG_PRINT_L3("BlockchainLMDB::" << __func__);
4257 if (! m_batch_transactions)
4258 throw0(DB_ERROR("batch transactions not enabled"));
4259 if (! m_batch_active)
4260 throw1(DB_ERROR("batch transaction not in progress"));
4261 if (m_write_batch_txn == nullptr)
4262 throw1(DB_ERROR("batch transaction not in progress"));
4263 if (m_writer != boost::this_thread::get_id())
4264 throw1(DB_ERROR("batch transaction owned by other thread"));
4265
4266 check_open();
4267
4268 LOG_PRINT_L3("batch transaction: committing...");
4269 TIME_MEASURE_START(time1);
4270 m_write_txn->commit();
4271 TIME_MEASURE_FINISH(time1);
4272 time_commit1 += time1;
4273 LOG_PRINT_L3("batch transaction: committed");
4274
4275 m_write_txn = nullptr;
4276 delete m_write_batch_txn;
4277 m_write_batch_txn = nullptr;
4278 memset(&m_wcursors, 0, sizeof(m_wcursors));
4279}
uint64_t time_commit1
a performance metric
#define TIME_MEASURE_FINISH(var_name)
#define TIME_MEASURE_START(var_name)

◆ 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 4211 of file db_lmdb.cpp.

4212{
4213 LOG_PRINT_L3("BlockchainLMDB::" << __func__);
4214 if (! m_batch_transactions)
4215 throw0(DB_ERROR("batch transactions not enabled"));
4216 if (m_batch_active)
4217 return false;
4218 if (m_write_batch_txn != nullptr)
4219 return false;
4220 if (m_write_txn)
4221 throw0(DB_ERROR("batch transaction attempted, but m_write_txn already in use"));
4222 check_open();
4223
4224 m_writer = boost::this_thread::get_id();
4225 check_and_resize_for_batch(batch_num_blocks, batch_bytes);
4226
4227 m_write_batch_txn = new mdb_txn_safe();
4228
4229 // NOTE: need to make sure it's destroyed properly when done
4230 if (auto mdb_res = lmdb_txn_begin(m_env, NULL, 0, *m_write_batch_txn))
4231 {
4232 delete m_write_batch_txn;
4233 m_write_batch_txn = nullptr;
4234 throw0(DB_ERROR(lmdb_error("Failed to create a transaction for the db: ", mdb_res).c_str()));
4235 }
4236 // indicates this transaction is for batch transactions, but not whether it's
4237 // active
4238 m_write_batch_txn->m_batch_txn = true;
4239 m_write_txn = m_write_batch_txn;
4240
4241 m_batch_active = true;
4242 memset(&m_wcursors, 0, sizeof(m_wcursors));
4243 if (m_tinfo.get())
4244 {
4245 if (m_tinfo->m_ti_rflags.m_rf_txn)
4246 mdb_txn_reset(m_tinfo->m_ti_rtxn);
4247 memset(&m_tinfo->m_ti_rflags, 0, sizeof(m_tinfo->m_ti_rflags));
4248 }
4249
4250 LOG_PRINT_L3("batch transaction: begin");
4251 return true;
4252}
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:527
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 4291 of file db_lmdb.cpp.

4292{
4293 LOG_PRINT_L3("BlockchainLMDB::" << __func__);
4294 if (! m_batch_transactions)
4295 throw0(DB_ERROR("batch transactions not enabled"));
4296 if (! m_batch_active)
4297 throw1(DB_ERROR("batch transaction not in progress"));
4298 if (m_write_batch_txn == nullptr)
4299 throw1(DB_ERROR("batch transaction not in progress"));
4300 if (m_writer != boost::this_thread::get_id())
4301 throw1(DB_ERROR("batch transaction owned by other thread"));
4302 check_open();
4303 LOG_PRINT_L3("batch transaction: committing...");
4304 TIME_MEASURE_START(time1);
4305 try
4306 {
4307 m_write_txn->commit();
4308 TIME_MEASURE_FINISH(time1);
4309 time_commit1 += time1;
4310 cleanup_batch();
4311 }
4312 catch (const std::exception &e)
4313 {
4314 cleanup_batch();
4315 throw;
4316 }
4317 LOG_PRINT_L3("batch transaction: end");
4318}

◆ 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 2993 of file db_lmdb.cpp.

2994{
2995 LOG_PRINT_L3("BlockchainLMDB::" << __func__);
2996 check_open();
2997
2999 RCURSOR(block_heights);
3000
3001 bool ret = false;
3002 MDB_val_set(key, h);
3003 auto get_result = mdb_cursor_get(m_cur_block_heights, (MDB_val *)&zerokval, &key, MDB_GET_BOTH);
3004 if (get_result == MDB_NOTFOUND)
3005 {
3006 LOG_PRINT_L3("Block with hash " << epee::string_tools::pod_to_hex(h) << " not found in db");
3007 }
3008 else if (get_result)
3009 throw0(DB_ERROR(lmdb_error("DB error attempting to fetch block index from hash", get_result).c_str()));
3010 else
3011 {
3012 if (height)
3013 {
3014 const blk_height *bhp = (const blk_height *)key.mv_data;
3015 *height = bhp->bh_height;
3016 }
3017 ret = true;
3018 }
3019
3021 return ret;
3022}
#define TXN_POSTFIX_RDONLY()
Definition db_lmdb.cpp:1795
#define RCURSOR(name)
Definition db_lmdb.cpp:292
#define TXN_PREFIX_RDONLY()
Definition db_lmdb.cpp:1788
#define MDB_val_set(var, val)
Definition db_lmdb.cpp:89
#define m_cur_block_heights
Definition db_lmdb.h:82
#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
struct cryptonote::blk_height blk_height
std::string pod_to_hex(const t_pod_type &s)
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 4477 of file db_lmdb.cpp.

4478{
4479 LOG_PRINT_L3("BlockchainLMDB::" << __func__);
4480 mdb_txn_reset(m_tinfo->m_ti_rtxn);
4481 memset(&m_tinfo->m_ti_rflags, 0, sizeof(m_tinfo->m_ti_rflags));
4482}
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 4399 of file db_lmdb.cpp.

4400{
4401 MDB_txn *mtxn;
4402 mdb_txn_cursors *mcur;
4403 return block_rtxn_start(&mtxn, &mcur);
4404}
virtual bool block_rtxn_start() const
Definition db_lmdb.cpp:4399
struct MDB_txn MDB_txn
Opaque structure for a transaction handle.
Definition lmdb.h:267
Here is the call graph for this function:
Here is the caller graph for this function:

◆ block_rtxn_start() [2/2]

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

Definition at line 4355 of file db_lmdb.cpp.

4356{
4357 bool ret = false;
4358 mdb_threadinfo *tinfo;
4359 if (m_write_txn && m_writer == boost::this_thread::get_id()) {
4360 *mtxn = m_write_txn->m_txn;
4361 *mcur = (mdb_txn_cursors *)&m_wcursors;
4362 return ret;
4363 }
4364 /* Check for existing info and force reset if env doesn't match -
4365 * only happens if env was opened/closed multiple times in same process
4366 */
4367 if (!(tinfo = m_tinfo.get()) || mdb_txn_env(tinfo->m_ti_rtxn) != m_env)
4368 {
4369 tinfo = new mdb_threadinfo;
4370 m_tinfo.reset(tinfo);
4371 memset(&tinfo->m_ti_rcursors, 0, sizeof(tinfo->m_ti_rcursors));
4372 memset(&tinfo->m_ti_rflags, 0, sizeof(tinfo->m_ti_rflags));
4373 if (auto mdb_res = lmdb_txn_begin(m_env, NULL, MDB_RDONLY, &tinfo->m_ti_rtxn))
4374 throw0(DB_ERROR_TXN_START(lmdb_error("Failed to create a read transaction for the db: ", mdb_res).c_str()));
4375 ret = true;
4376 } else if (!tinfo->m_ti_rflags.m_rf_txn)
4377 {
4378 if (auto mdb_res = lmdb_txn_renew(tinfo->m_ti_rtxn))
4379 throw0(DB_ERROR_TXN_START(lmdb_error("Failed to renew a read transaction for the db: ", mdb_res).c_str()));
4380 ret = true;
4381 }
4382 if (ret)
4383 tinfo->m_ti_rflags.m_rf_txn = true;
4384 *mtxn = tinfo->m_ti_rtxn;
4385 *mcur = &tinfo->m_ti_rcursors;
4386
4387 if (ret)
4388 LOG_PRINT_L3("BlockchainLMDB::" << __func__);
4389 return ret;
4390}
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:537
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 4392 of file db_lmdb.cpp.

4393{
4394 LOG_PRINT_L3("BlockchainLMDB::" << __func__);
4395 mdb_txn_reset(m_tinfo->m_ti_rtxn);
4396 memset(&m_tinfo->m_ti_rflags, 0, sizeof(m_tinfo->m_ti_rflags));
4397}
Here is the call graph for this function:

◆ block_wtxn_abort()

void cryptonote::BlockchainLMDB::block_wtxn_abort ( )
virtual

Implements cryptonote::BlockchainDB.

Definition at line 4461 of file db_lmdb.cpp.

4462{
4463 LOG_PRINT_L3("BlockchainLMDB::" << __func__);
4464 if (!m_write_txn)
4465 throw0(DB_ERROR_TXN_START((std::string("Attempted to abort write txn when no such txn exists in ")+__FUNCTION__).c_str()));
4466 if (m_writer != boost::this_thread::get_id())
4467 throw0(DB_ERROR_TXN_START((std::string("Attempted to abort write txn from the wrong thread in ")+__FUNCTION__).c_str()));
4468
4469 if (! m_batch_active)
4470 {
4471 delete m_write_txn;
4472 m_write_txn = nullptr;
4473 memset(&m_wcursors, 0, sizeof(m_wcursors));
4474 }
4475}
Here is the caller graph for this function:

◆ block_wtxn_start()

void cryptonote::BlockchainLMDB::block_wtxn_start ( )
virtual

Implements cryptonote::BlockchainDB.

Definition at line 4406 of file db_lmdb.cpp.

4407{
4408 LOG_PRINT_L3("BlockchainLMDB::" << __func__);
4409 // Distinguish the exceptions here from exceptions that would be thrown while
4410 // using the txn and committing it.
4411 //
4412 // If an exception is thrown in this setup, we don't want the caller to catch
4413 // it and proceed as if there were an existing write txn, such as trying to
4414 // call block_txn_abort(). It also indicates a serious issue which will
4415 // probably be thrown up another layer.
4416 if (! m_batch_active && m_write_txn)
4417 throw0(DB_ERROR_TXN_START((std::string("Attempted to start new write txn when write txn already exists in ")+__FUNCTION__).c_str()));
4418 if (! m_batch_active)
4419 {
4420 m_writer = boost::this_thread::get_id();
4421 m_write_txn = new mdb_txn_safe();
4422 if (auto mdb_res = lmdb_txn_begin(m_env, NULL, 0, *m_write_txn))
4423 {
4424 delete m_write_txn;
4425 m_write_txn = nullptr;
4426 throw0(DB_ERROR_TXN_START(lmdb_error("Failed to create a transaction for the db: ", mdb_res).c_str()));
4427 }
4428 memset(&m_wcursors, 0, sizeof(m_wcursors));
4429 if (m_tinfo.get())
4430 {
4431 if (m_tinfo->m_ti_rflags.m_rf_txn)
4432 mdb_txn_reset(m_tinfo->m_ti_rtxn);
4433 memset(&m_tinfo->m_ti_rflags, 0, sizeof(m_tinfo->m_ti_rflags));
4434 }
4435 } else if (m_writer != boost::this_thread::get_id())
4436 throw0(DB_ERROR_TXN_START((std::string("Attempted to start new write txn when batch txn already exists in ")+__FUNCTION__).c_str()));
4437}
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 4439 of file db_lmdb.cpp.

4440{
4441 LOG_PRINT_L3("BlockchainLMDB::" << __func__);
4442 if (!m_write_txn)
4443 throw0(DB_ERROR_TXN_START((std::string("Attempted to stop write txn when no such txn exists in ")+__FUNCTION__).c_str()));
4444 if (m_writer != boost::this_thread::get_id())
4445 throw0(DB_ERROR_TXN_START((std::string("Attempted to stop write txn from the wrong thread in ")+__FUNCTION__).c_str()));
4446 {
4447 if (! m_batch_active)
4448 {
4449 TIME_MEASURE_START(time1);
4450 m_write_txn->commit();
4451 TIME_MEASURE_FINISH(time1);
4452 time_commit1 += time1;
4453
4454 delete m_write_txn;
4455 m_write_txn = nullptr;
4456 memset(&m_wcursors, 0, sizeof(m_wcursors));
4457 }
4458 }
4459}
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 342 of file db_lmdb.h.

342{ 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 2936 of file db_lmdb.cpp.

2937{
2938 return prune_worker(prune_mode_check, 0);
2939}

◆ 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 1624 of file db_lmdb.cpp.

1625{
1626 LOG_PRINT_L3("BlockchainLMDB::" << __func__);
1627 if (m_batch_active)
1628 {
1629 LOG_PRINT_L3("close() first calling batch_abort() due to active batch transaction");
1630 batch_abort();
1631 }
1632 this->sync();
1633 m_tinfo.reset();
1634
1635 // FIXME: not yet thread safe!!! Use with care.
1636 mdb_env_close(m_env);
1637 m_open = false;
1638}
virtual void sync()
sync the BlockchainDB with disk
Definition db_lmdb.cpp:1640
void mdb_env_close(MDB_env *env)
Close the environment and release the memory map.
Here is the call graph for this function:
Here is the caller 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
Here is the caller graph for this function:

◆ 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
Here is the caller graph for this function:

◆ 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}
Here is the caller graph for this function:

◆ 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}
Here is the caller graph for this function:

◆ 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:
Here is the caller 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 3989 of file db_lmdb.cpp.

3990{
3991 LOG_PRINT_L3("BlockchainLMDB::" << __func__);
3992 check_open();
3993
3995 RCURSOR(spent_keys);
3996
3997 MDB_val k, v;
3998 bool fret = true;
3999
4000 k = zerokval;
4002 while (1)
4003 {
4004 int ret = mdb_cursor_get(m_cur_spent_keys, &k, &v, op);
4005 op = MDB_NEXT;
4006 if (ret == MDB_NOTFOUND)
4007 break;
4008 if (ret < 0)
4009 throw0(DB_ERROR("Failed to enumerate key images"));
4010 const crypto::key_image k_image = *(const crypto::key_image*)v.mv_data;
4011 if (!f(k_image)) {
4012 fret = false;
4013 break;
4014 }
4015 }
4016
4018
4019 return fret;
4020}
#define m_cur_spent_keys
Definition db_lmdb.h:93
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:105
Here is the call graph for this function:

◆ 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 4135 of file db_lmdb.cpp.

4136{
4137 LOG_PRINT_L3("BlockchainLMDB::" << __func__);
4138 check_open();
4139
4141 RCURSOR(output_amounts);
4142
4143 MDB_val k;
4144 MDB_val v;
4145 bool fret = true;
4146
4148 while (1)
4149 {
4150 int ret = mdb_cursor_get(m_cur_output_amounts, &k, &v, op);
4151 op = MDB_NEXT;
4152 if (ret == MDB_NOTFOUND)
4153 break;
4154 if (ret)
4155 throw0(DB_ERROR("Failed to enumerate outputs"));
4156 uint64_t amount = *(const uint64_t*)k.mv_data;
4157 outkey *ok = (outkey *)v.mv_data;
4159 if (!f(amount, toi.first, ok->data.height, toi.second)) {
4160 fret = false;
4161 break;
4162 }
4163 }
4164
4166
4167 return fret;
4168}
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:3893
#define m_cur_output_amounts
Definition db_lmdb.h:85
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 4170 of file db_lmdb.cpp.

4171{
4172 LOG_PRINT_L3("BlockchainLMDB::" << __func__);
4173 check_open();
4174
4176 RCURSOR(output_amounts);
4177
4178 MDB_val_set(k, amount);
4179 MDB_val v;
4180 bool fret = true;
4181
4183 while (1)
4184 {
4185 int ret = mdb_cursor_get(m_cur_output_amounts, &k, &v, op);
4186 op = MDB_NEXT_DUP;
4187 if (ret == MDB_NOTFOUND)
4188 break;
4189 if (ret)
4190 throw0(DB_ERROR("Failed to enumerate outputs"));
4191 uint64_t out_amount = *(const uint64_t*)k.mv_data;
4192 if (amount != out_amount)
4193 {
4194 MERROR("Amount is not the expected amount");
4195 fret = false;
4196 break;
4197 }
4198 const outkey *ok = (const outkey *)v.mv_data;
4199 if (!f(ok->data.height)) {
4200 fret = false;
4201 break;
4202 }
4203 }
4204
4206
4207 return fret;
4208}
@ 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 4073 of file db_lmdb.cpp.

4074{
4075 LOG_PRINT_L3("BlockchainLMDB::" << __func__);
4076 check_open();
4077
4079 RCURSOR(txs_pruned);
4080 RCURSOR(txs_prunable);
4081 RCURSOR(tx_indices);
4082
4083 MDB_val k;
4084 MDB_val v;
4085 bool fret = true;
4086
4088 while (1)
4089 {
4090 int ret = mdb_cursor_get(m_cur_tx_indices, &k, &v, op);
4091 op = MDB_NEXT;
4092 if (ret == MDB_NOTFOUND)
4093 break;
4094 if (ret)
4095 throw0(DB_ERROR(lmdb_error("Failed to enumerate transactions: ", ret).c_str()));
4096
4097 txindex *ti = (txindex *)v.mv_data;
4098 const crypto::hash hash = ti->key;
4099 k.mv_data = (void *)&ti->data.tx_id;
4100 k.mv_size = sizeof(ti->data.tx_id);
4101
4102 ret = mdb_cursor_get(m_cur_txs_pruned, &k, &v, MDB_SET);
4103 if (ret == MDB_NOTFOUND)
4104 break;
4105 if (ret)
4106 throw0(DB_ERROR(lmdb_error("Failed to enumerate transactions: ", ret).c_str()));
4107 transaction tx;
4108 blobdata bd;
4109 bd.assign(reinterpret_cast<char*>(v.mv_data), v.mv_size);
4110 if (pruned)
4111 {
4113 throw0(DB_ERROR("Failed to parse tx from blob retrieved from the db"));
4114 }
4115 else
4116 {
4118 if (ret)
4119 throw0(DB_ERROR(lmdb_error("Failed to get prunable tx data the db: ", ret).c_str()));
4120 bd.append(reinterpret_cast<char*>(v.mv_data), v.mv_size);
4122 throw0(DB_ERROR("Failed to parse tx from blob retrieved from the db"));
4123 }
4124 if (!f(hash, tx)) {
4125 fret = false;
4126 break;
4127 }
4128 }
4129
4131
4132 return fret;
4133}
#define m_cur_txs_prunable
Definition db_lmdb.h:88
#define m_cur_txs_pruned
Definition db_lmdb.h:87
#define m_cur_tx_indices
Definition db_lmdb.h:91
POD_CLASS hash
Definition hash.h:50
struct cryptonote::txindex txindex
std::string blobdata
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 2941 of file db_lmdb.cpp.

2942{
2943 LOG_PRINT_L3("BlockchainLMDB::" << __func__);
2944 check_open();
2945
2947 RCURSOR(txpool_meta);
2948 RCURSOR(txpool_blob);
2949
2950 MDB_val k;
2951 MDB_val v;
2952 bool ret = true;
2953
2955 while (1)
2956 {
2957 int result = mdb_cursor_get(m_cur_txpool_meta, &k, &v, op);
2958 op = MDB_NEXT;
2959 if (result == MDB_NOTFOUND)
2960 break;
2961 if (result)
2962 throw0(DB_ERROR(lmdb_error("Failed to enumerate txpool tx metadata: ", result).c_str()));
2963 const crypto::hash txid = *(const crypto::hash*)k.mv_data;
2964 const txpool_tx_meta_t &meta = *(const txpool_tx_meta_t*)v.mv_data;
2965 if (!include_unrelayed_txes && meta.do_not_relay)
2966 // Skipping that tx
2967 continue;
2968 const cryptonote::blobdata *passed_bd = NULL;
2970 if (include_blob)
2971 {
2972 MDB_val b;
2973 result = mdb_cursor_get(m_cur_txpool_blob, &k, &b, MDB_SET);
2974 if (result == MDB_NOTFOUND)
2975 throw0(DB_ERROR("Failed to find txpool tx blob to match metadata"));
2976 if (result)
2977 throw0(DB_ERROR(lmdb_error("Failed to enumerate txpool tx blob: ", result).c_str()));
2978 bd.assign(reinterpret_cast<const char*>(b.mv_data), b.mv_size);
2979 passed_bd = &bd;
2980 }
2981
2982 if (!f(txid, meta, passed_bd)) {
2983 ret = false;
2984 break;
2985 }
2986 }
2987
2989
2990 return ret;
2991}
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 4022 of file db_lmdb.cpp.

4023{
4024 LOG_PRINT_L3("BlockchainLMDB::" << __func__);
4025 check_open();
4026
4028 RCURSOR(blocks);
4029
4030 MDB_val k;
4031 MDB_val v;
4032 bool fret = true;
4033
4034 MDB_cursor_op op;
4035 if (h1)
4036 {
4037 k = MDB_val{sizeof(h1), (void*)&h1};
4038 op = MDB_SET;
4039 } else
4040 {
4041 op = MDB_FIRST;
4042 }
4043 while (1)
4044 {
4045 int ret = mdb_cursor_get(m_cur_blocks, &k, &v, op);
4046 op = MDB_NEXT;
4047 if (ret == MDB_NOTFOUND)
4048 break;
4049 if (ret)
4050 throw0(DB_ERROR("Failed to enumerate blocks"));
4051 uint64_t height = *(const uint64_t*)k.mv_data;
4052 blobdata bd;
4053 bd.assign(reinterpret_cast<char*>(v.mv_data), v.mv_size);
4054 block b;
4056 throw0(DB_ERROR("Failed to parse block from blob retrieved from the db"));
4058 if (!get_block_hash(b, hash))
4059 throw0(DB_ERROR("Failed to get block hash from blob retrieved from the db"));
4060 if (!f(height, hash, b)) {
4061 fret = false;
4062 break;
4063 }
4064 if (height >= h2)
4065 break;
4066 }
4067
4069
4070 return fret;
4071}
#define m_cur_blocks
Definition db_lmdb.h:81
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 2071 of file db_lmdb.cpp.

2072{
2073 LOG_PRINT_L3("BlockchainLMDB::" << __func__);
2074 check_open();
2075
2077 RCURSOR(addr_outputs);
2078
2079 int result = 0;
2080 std::vector<address_outputs> address_outputs;
2081
2082 MDB_val k = {sizeof(combined_key), (void *)&combined_key};
2083
2085 while (1) {
2086 MDB_val v;
2087 int ret = mdb_cursor_get(m_cur_addr_outputs, &k, &v, op);
2088 op = MDB_NEXT_DUP;
2089 if (ret == MDB_NOTFOUND)
2090 break;
2091 if (ret)
2092 throw0(DB_ERROR("Failed to enumerate address outputs"));
2093
2094 const acc_outs_t res = *(const acc_outs_t *) v.mv_data;
2095
2096 cryptonote::address_outputs addr_out;
2097 addr_out.out_id = res.db_index;
2098 addr_out.tx_hash = res.tx_hash;
2099 addr_out.relative_out_index = res.relative_out_index;
2100 addr_out.amount = res.amount;
2101 addr_out.spent = !check_chainstate_utxo(res.tx_hash, res.relative_out_index);
2102
2103 address_outputs.push_back(addr_out);
2104
2105 }
2106
2108
2109 return address_outputs;
2110}
#define m_cur_addr_outputs
Definition db_lmdb.h:100
@ MDB_SET_KEY
Definition lmdb.h:423
const char * res
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 2112 of file db_lmdb.cpp.

2113{
2114 LOG_PRINT_L3("BlockchainLMDB::" << __func__);
2115 check_open();
2116
2118 RCURSOR(addr_outputs);
2119
2120 std::vector<address_outputs> address_outputs;
2121
2122 MDB_val k = {sizeof(combined_key), (void *)&combined_key};
2123 MDB_val v;
2124
2125 MDB_cursor_op op;
2126 if (start_db_index)
2127 op = MDB_GET_BOTH;
2128 else
2129 {
2130 op = desc ? MDB_LAST_DUP : MDB_FIRST_DUP;
2131 int result = mdb_cursor_get(m_cur_addr_outputs, &k, &v, MDB_SET_KEY);
2132 if (result != 0 && result != MDB_NOTFOUND)
2133 throw1(DB_ERROR(lmdb_error("Failed to enumerate address outputs", result).c_str()));
2134 }
2135
2136 std::set<std::string> tx_hashes;
2137 for(size_t i = 0; i < batch_size + 1; ++i) {
2138 if(op == MDB_GET_BOTH)
2139 v = MDB_val{sizeof(start_db_index), (void*)&start_db_index};
2140
2141 int ret = mdb_cursor_get(m_cur_addr_outputs, &k, &v, op);
2142 op = desc ? MDB_PREV_DUP : MDB_NEXT_DUP;
2143 if (ret == MDB_NOTFOUND)
2144 break;
2145 if (ret)
2146 throw0(DB_ERROR("Failed to enumerate address outputs"));
2147
2148 const acc_outs_t res = *(const acc_outs_t *) v.mv_data;
2149
2150 std::string tx_hash_hex = epee::string_tools::pod_to_hex(res.tx_hash);
2151 if(tx_hashes.find(tx_hash_hex) != tx_hashes.end())
2152 {
2153 --i;
2154 continue;
2155 }
2156
2157 cryptonote::address_outputs addr_out;
2158 addr_out.out_id = res.db_index;
2159 addr_out.tx_hash = res.tx_hash;
2160 addr_out.relative_out_index = res.relative_out_index;
2161 addr_out.amount = res.amount;
2162 addr_out.spent = !check_chainstate_utxo(res.tx_hash, res.relative_out_index);
2163
2164 address_outputs.push_back(addr_out);
2165 tx_hashes.emplace(tx_hash_hex);
2166 }
2167
2169 return address_outputs;
2170}
@ 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_addr_tx_all()

std::vector< address_txs > cryptonote::BlockchainLMDB::get_addr_tx_all ( const crypto::public_key & combined_key)
virtual

Implements cryptonote::BlockchainDB.

Definition at line 2214 of file db_lmdb.cpp.

2215{
2216 LOG_PRINT_L3("BlockchainLMDB::" << __func__);
2217 check_open();
2218
2220 RCURSOR(addr_txs);
2221
2222 int result = 0;
2223 std::vector<address_txs> address_txs;
2224
2225 MDB_val k = {sizeof(combined_key), (void *)&combined_key};
2226
2228 while (1) {
2229 MDB_val v;
2230 int ret = mdb_cursor_get(m_cur_addr_txs, &k, &v, op);
2231 op = MDB_NEXT_DUP;
2232 if (ret == MDB_NOTFOUND)
2233 break;
2234 if (ret)
2235 throw0(DB_ERROR("Failed to enumerate address txs"));
2236
2237 const acc_addr_tx_t res = *(const acc_addr_tx_t *) v.mv_data;
2238
2239 cryptonote::address_txs addr_tx;
2240 addr_tx.addr_tx_id = res.db_index;
2241 addr_tx.tx_hash = res.tx_hash;
2242 address_txs.push_back(addr_tx);
2243 }
2244
2246 return address_txs;
2247}
#define m_cur_addr_txs
Definition db_lmdb.h:101
struct cryptonote::acc_addr_tx_t acc_addr_tx_t
Here is the call graph for this function:

◆ get_addr_tx_batch()

std::vector< address_txs > cryptonote::BlockchainLMDB::get_addr_tx_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 2249 of file db_lmdb.cpp.

2250{
2251 LOG_PRINT_L3("BlockchainLMDB::" << __func__);
2252 check_open();
2253
2255 RCURSOR(addr_txs);
2256
2257 std::vector<address_txs> address_txs;
2258
2259 MDB_val k = {sizeof(combined_key), (void *)&combined_key};
2260 MDB_val v;
2261
2262 MDB_cursor_op op;
2263 if (start_db_index)
2264 op = MDB_GET_BOTH;
2265 else
2266 {
2267 op = desc ? MDB_LAST_DUP : MDB_FIRST_DUP;
2268 int result = mdb_cursor_get(m_cur_addr_txs, &k, &v, MDB_SET_KEY);
2269 if (result != 0 && result != MDB_NOTFOUND)
2270 throw1(DB_ERROR(lmdb_error("Failed to enumerate address txs", result).c_str()));
2271 }
2272
2273 std::set<std::string> tx_hashes;
2274 for(size_t i = 0; i < batch_size + 1; ++i) {
2275 if(op == MDB_GET_BOTH)
2276 v = MDB_val{sizeof(start_db_index), (void*)&start_db_index};
2277
2278 int ret = mdb_cursor_get(m_cur_addr_txs, &k, &v, op);
2279 op = desc ? MDB_PREV_DUP : MDB_NEXT_DUP;
2280 if (ret == MDB_NOTFOUND)
2281 break;
2282 if (ret)
2283 throw0(DB_ERROR("Failed to enumerate address txs"));
2284
2285 const acc_addr_tx_t res = *(const acc_addr_tx_t *) v.mv_data;
2286
2287 cryptonote::address_txs addr_tx;
2288 addr_tx.addr_tx_id = res.db_index;
2289 addr_tx.tx_hash = res.tx_hash;
2290
2291 address_txs.push_back(addr_tx);
2292 }
2293
2295 return address_txs;
2296}
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 2298 of file db_lmdb.cpp.

2299{
2300 LOG_PRINT_L3("BlockchainLMDB::" << __func__);
2301 check_open();
2302
2304 RCURSOR(addr_outputs);
2305
2306 uint64_t balance = 0;
2307
2308 MDB_val k = {sizeof(combined_key), (void *)&combined_key};
2309
2311 while (1) {
2312 MDB_val v;
2313 int ret = mdb_cursor_get(m_cur_addr_outputs, &k, &v, op);
2314 op = MDB_NEXT_DUP;
2315 if (ret == MDB_NOTFOUND)
2316 break;
2317 if (ret)
2318 throw0(DB_ERROR("Failed to enumerate address outputs"));
2319
2320 const acc_outs_t res = *(const acc_outs_t *) v.mv_data;
2321
2322 if(check_chainstate_utxo(res.tx_hash, res.relative_out_index))
2323 balance += res.amount;
2324 }
2325
2327
2328 return balance;
2329}
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 3405 of file db_lmdb.cpp.

3406{
3407 LOG_PRINT_L3("BlockchainLMDB::" << __func__);
3408 check_open();
3409
3411 RCURSOR(block_info);
3412
3413 MDB_val_set(result, height);
3414 auto get_result = mdb_cursor_get(m_cur_block_info, (MDB_val *)&zerokval, &result, MDB_GET_BOTH);
3415 if (get_result == MDB_NOTFOUND)
3416 {
3417 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()));
3418 }
3419 else if (get_result)
3420 throw0(DB_ERROR("Error attempting to retrieve a total generated coins from the db"));
3421
3422 mdb_block_info *bi = (mdb_block_info *)result.mv_data;
3423 uint64_t ret = bi->bi_coins;
3425 return ret;
3426}
#define m_cur_block_info
Definition db_lmdb.h:83
mdb_block_info_4 mdb_block_info
Definition db_lmdb.cpp:355
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 3024 of file db_lmdb.cpp.

3025{
3026 LOG_PRINT_L3("BlockchainLMDB::" << __func__);
3027 check_open();
3028
3030}
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:3032
virtual cryptonote::blobdata get_block_blob_from_height(const uint64_t &height) const
fetch a block blob by height
Definition db_lmdb.cpp:3062
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 3062 of file db_lmdb.cpp.

3063{
3064 LOG_PRINT_L3("BlockchainLMDB::" << __func__);
3065 check_open();
3066
3068 RCURSOR(blocks);
3069
3070 MDB_val_copy<uint64_t> key(height);
3071 MDB_val result;
3072 auto get_result = mdb_cursor_get(m_cur_blocks, &key, &result, MDB_SET);
3073 if (get_result == MDB_NOTFOUND)
3074 {
3075 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()));
3076 }
3077 else if (get_result)
3078 throw0(DB_ERROR("Error attempting to retrieve a block from the db"));
3079
3080 blobdata bd;
3081 bd.assign(reinterpret_cast<char*>(result.mv_data), result.mv_size);
3082
3084
3085 return bd;
3086}
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 3363 of file db_lmdb.cpp.

3364{
3365 LOG_PRINT_L3("BlockchainLMDB::" << __func__ << " height: " << height);
3366 check_open();
3367
3369 RCURSOR(block_info);
3370
3371 MDB_val_set(result, height);
3372 auto get_result = mdb_cursor_get(m_cur_block_info, (MDB_val *)&zerokval, &result, MDB_GET_BOTH);
3373 if (get_result == MDB_NOTFOUND)
3374 {
3375 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()));
3376 }
3377 else if (get_result)
3378 throw0(DB_ERROR("Error attempting to retrieve a cumulative difficulty from the db"));
3379
3380 mdb_block_info *bi = (mdb_block_info *)result.mv_data;
3381 difficulty_type ret = bi->bi_diff_hi;
3382 ret <<= 64;
3383 ret |= bi->bi_diff_lo;
3385 return ret;
3386}
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 3111 of file db_lmdb.cpp.

3112{
3113 LOG_PRINT_L3("BlockchainLMDB::" << __func__);
3114 check_open();
3115 std::vector<uint64_t> res;
3116 int result;
3117
3118 if (heights.empty())
3119 return {};
3120 res.reserve(heights.size());
3121
3123 RCURSOR(block_info);
3124
3125 MDB_stat db_stats;
3126 if ((result = mdb_stat(m_txn, m_blocks, &db_stats)))
3127 throw0(DB_ERROR(lmdb_error("Failed to query m_blocks: ", result).c_str()));
3128 for (size_t i = 0; i < heights.size(); ++i)
3129 if (heights[i] >= db_stats.ms_entries)
3130 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()));
3131
3132 MDB_val v;
3133
3134 uint64_t prev_height = heights[0];
3135 uint64_t range_begin = 0, range_end = 0;
3136 for (uint64_t height: heights)
3137 {
3138 if (height >= range_begin && height < range_end)
3139 {
3140 // nohting to do
3141 }
3142 else
3143 {
3144 if (height == prev_height + 1)
3145 {
3146 MDB_val k2;
3148 range_begin = ((const mdb_block_info*)v.mv_data)->bi_height;
3149 range_end = range_begin + v.mv_size / sizeof(mdb_block_info); // whole records please
3150 if (height < range_begin || height >= range_end)
3151 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()));
3152 }
3153 else
3154 {
3155 v.mv_size = sizeof(uint64_t);
3156 v.mv_data = (void*)&height;
3157 result = mdb_cursor_get(m_cur_block_info, (MDB_val *)&zerokval, &v, MDB_GET_BOTH);
3158 range_begin = height;
3159 range_end = range_begin + 1;
3160 }
3161 if (result)
3162 throw0(DB_ERROR(lmdb_error("Error attempting to retrieve rct distribution from the db: ", result).c_str()));
3163 }
3164 const mdb_block_info *bi = ((const mdb_block_info *)v.mv_data) + (height - range_begin);
3165 res.push_back(bi->bi_cum_rct);
3166 prev_height = height;
3167 }
3168
3170 return res;
3171}
struct MDB_stat MDB_stat
Statistics for a database in the environment.
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
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 3388 of file db_lmdb.cpp.

3389{
3390 LOG_PRINT_L3("BlockchainLMDB::" << __func__);
3391 check_open();
3392
3393 difficulty_type diff1 = 0;
3394 difficulty_type diff2 = 0;
3395
3397 if (height != 0)
3398 {
3400 }
3401
3402 return diff1 - diff2;
3403}
virtual difficulty_type get_block_cumulative_difficulty(const uint64_t &height) const
fetch a block's cumulative difficulty
Definition db_lmdb.cpp:3363
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 3451 of file db_lmdb.cpp.

3452{
3453 LOG_PRINT_L3("BlockchainLMDB::" << __func__);
3454 check_open();
3455
3457 RCURSOR(block_info);
3458
3459 MDB_val_set(result, height);
3460 auto get_result = mdb_cursor_get(m_cur_block_info, (MDB_val *)&zerokval, &result, MDB_GET_BOTH);
3461 if (get_result == MDB_NOTFOUND)
3462 {
3463 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()));
3464 }
3465 else if (get_result)
3466 throw0(DB_ERROR(lmdb_error("Error attempting to retrieve a block hash from the db: ", get_result).c_str()));
3467
3468 mdb_block_info *bi = (mdb_block_info *)result.mv_data;
3469 crypto::hash ret = bi->bi_hash;
3471 return ret;
3472}
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 3053 of file db_lmdb.cpp.

3054{
3055 LOG_PRINT_L3("BlockchainLMDB::" << __func__);
3056 check_open();
3057
3058 // block_header object is automatically cast from block object
3059 return get_block(h);
3060}
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 3032 of file db_lmdb.cpp.

3033{
3034 LOG_PRINT_L3("BlockchainLMDB::" << __func__);
3035 check_open();
3036
3038 RCURSOR(block_heights);
3039
3040 MDB_val_set(key, h);
3041 auto get_result = mdb_cursor_get(m_cur_block_heights, (MDB_val *)&zerokval, &key, MDB_GET_BOTH);
3042 if (get_result == MDB_NOTFOUND)
3043 throw1(BLOCK_DNE("Attempted to retrieve non-existent block height"));
3044 else if (get_result)
3045 throw0(DB_ERROR("Error attempting to retrieve a block height from the db"));
3046
3047 blk_height *bhp = (blk_height *)key.mv_data;
3048 uint64_t ret = bhp->bh_height;
3050 return ret;
3051}
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 3428 of file db_lmdb.cpp.

3429{
3430 LOG_PRINT_L3("BlockchainLMDB::" << __func__);
3431 check_open();
3432
3434 RCURSOR(block_info);
3435
3436 MDB_val_set(result, height);
3437 auto get_result = mdb_cursor_get(m_cur_block_info, (MDB_val *)&zerokval, &result, MDB_GET_BOTH);
3438 if (get_result == MDB_NOTFOUND)
3439 {
3440 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()));
3441 }
3442 else if (get_result)
3443 throw0(DB_ERROR("Error attempting to retrieve a long term block weight from the db"));
3444
3445 mdb_block_info *bi = (mdb_block_info *)result.mv_data;
3446 uint64_t ret = bi->bi_long_term_block_weight;
3448 return ret;
3449}
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 3088 of file db_lmdb.cpp.

3089{
3090 LOG_PRINT_L3("BlockchainLMDB::" << __func__);
3091 check_open();
3092
3094 RCURSOR(block_info);
3095
3096 MDB_val_set(result, height);
3097 auto get_result = mdb_cursor_get(m_cur_block_info, (MDB_val *)&zerokval, &result, MDB_GET_BOTH);
3098 if (get_result == MDB_NOTFOUND)
3099 {
3100 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()));
3101 }
3102 else if (get_result)
3103 throw0(DB_ERROR("Error attempting to retrieve a timestamp from the db"));
3104
3105 mdb_block_info *bi = (mdb_block_info *)result.mv_data;
3106 uint64_t ret = bi->bi_timestamp;
3108 return ret;
3109}
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 3188 of file db_lmdb.cpp.

3189{
3190 LOG_PRINT_L3("BlockchainLMDB::" << __func__);
3191 check_open();
3192
3194 RCURSOR(block_info);
3195
3196 MDB_val_set(result, height);
3197 auto get_result = mdb_cursor_get(m_cur_block_info, (MDB_val *)&zerokval, &result, MDB_GET_BOTH);
3198 if (get_result == MDB_NOTFOUND)
3199 {
3200 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()));
3201 }
3202 else if (get_result)
3203 throw0(DB_ERROR("Error attempting to retrieve a block size from the db"));
3204
3205 mdb_block_info *bi = (mdb_block_info *)result.mv_data;
3206 size_t ret = bi->bi_weight;
3208 return ret;
3209}
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 3317 of file db_lmdb.cpp.

3318{
3319 return get_block_info_64bit_fields(start_height, count, offsetof(mdb_block_info, bi_weight));
3320}

◆ 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 2608 of file db_lmdb.cpp.

2609{
2610 LOG_PRINT_L3("BlockchainLMDB::" << __func__);
2611 check_open();
2612
2614 RCURSOR(properties)
2615 MDB_val_str(k, "pruning_seed");
2616 MDB_val v;
2617 int result = mdb_cursor_get(m_cur_properties, &k, &v, MDB_SET);
2618 if (result == MDB_NOTFOUND)
2619 return 0;
2620 if (result)
2621 throw0(DB_ERROR(lmdb_error("Failed to retrieve pruning seed: ", result).c_str()));
2622 if (v.mv_size != sizeof(uint32_t))
2623 throw0(DB_ERROR("Failed to retrieve or create pruning seed: unexpected value size"));
2624 uint32_t pruning_seed;
2625 memcpy(&pruning_seed, v.mv_data, sizeof(pruning_seed));
2627 return pruning_seed;
2628}
#define MDB_val_str(var, val)
Definition db_lmdb.cpp:93
#define m_cur_properties
Definition db_lmdb.h:97
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 3474 of file db_lmdb.cpp.

3475{
3476 LOG_PRINT_L3("BlockchainLMDB::" << __func__);
3477 check_open();
3478 std::vector<block> v;
3479
3480 for (uint64_t height = h1; height <= h2; ++height)
3481 {
3482 v.push_back(get_block_from_height(height));
3483 }
3484
3485 return v;
3486}
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 1755 of file db_lmdb.cpp.

1756{
1757 LOG_PRINT_L3("BlockchainLMDB::" << __func__);
1758
1759 return std::string("lmdb");
1760}

◆ 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 1724 of file db_lmdb.cpp.

1725{
1726 LOG_PRINT_L3("BlockchainLMDB::" << __func__);
1727 std::vector<std::string> filenames;
1728
1729 boost::filesystem::path datafile(m_folder);
1731 boost::filesystem::path lockfile(m_folder);
1733
1734 filenames.push_back(datafile.string());
1735 filenames.push_back(lockfile.string());
1736
1737 return filenames;
1738}
#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 3488 of file db_lmdb.cpp.

3489{
3490 LOG_PRINT_L3("BlockchainLMDB::" << __func__);
3491 check_open();
3492 std::vector<crypto::hash> v;
3493
3494 for (uint64_t height = h1; height <= h2; ++height)
3495 {
3496 v.push_back(get_block_hash_from_height(height));
3497 }
3498
3499 return v;
3500}
virtual crypto::hash get_block_hash_from_height(const uint64_t &height) const
fetch a block's hash
Definition db_lmdb.cpp:3451
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 3322 of file db_lmdb.cpp.

3323{
3324 return get_block_info_64bit_fields(start_height, count, offsetof(mdb_block_info, bi_long_term_block_weight));
3325}

◆ 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 3835 of file db_lmdb.cpp.

3836{
3837 LOG_PRINT_L3("BlockchainLMDB::" << __func__);
3838 check_open();
3839
3841 RCURSOR(output_amounts);
3842
3843 MDB_val_copy<uint64_t> k(amount);
3844 MDB_val v;
3845 mdb_size_t num_elems = 0;
3846 auto result = mdb_cursor_get(m_cur_output_amounts, &k, &v, MDB_SET);
3847 if (result == MDB_SUCCESS)
3848 {
3850 }
3851 else if (result != MDB_NOTFOUND)
3852 throw0(DB_ERROR("DB error attempting to get number of outputs of an amount"));
3853
3855
3856 return num_elems;
3857}
#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 4744 of file db_lmdb.cpp.

4745{
4746 LOG_PRINT_L3("BlockchainLMDB::" << __func__);
4747 check_open();
4748
4750 RCURSOR(output_amounts);
4751
4752 distribution.clear();
4753 const uint64_t db_height = height();
4754 if (from_height >= db_height)
4755 return false;
4756 distribution.resize(db_height - from_height, 0);
4757
4758 bool fret = true;
4759 MDB_val_set(k, amount);
4760 MDB_val v;
4762 base = 0;
4763 while (1)
4764 {
4765 int ret = mdb_cursor_get(m_cur_output_amounts, &k, &v, op);
4766 op = MDB_NEXT_DUP;
4767 if (ret == MDB_NOTFOUND)
4768 break;
4769 if (ret)
4770 throw0(DB_ERROR("Failed to enumerate outputs"));
4771 const outkey *ok = (const outkey *)v.mv_data;
4772 const uint64_t height = ok->data.height;
4773 if (height >= from_height)
4774 distribution[height - from_height]++;
4775 else
4776 base++;
4777 if (to_height > 0 && height > to_height)
4778 break;
4779 }
4780
4781 distribution[0] += base;
4782 for (size_t n = 1; n < distribution.size(); ++n)
4783 distribution[n] += distribution[n - 1];
4784 base = 0;
4785
4787
4788 return true;
4789}
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 4651 of file db_lmdb.cpp.

4652{
4653 LOG_PRINT_L3("BlockchainLMDB::" << __func__);
4654 check_open();
4655
4657 RCURSOR(output_amounts);
4658
4659 std::map<uint64_t, std::tuple<uint64_t, uint64_t, uint64_t>> histogram;
4660 MDB_val k;
4661 MDB_val v;
4662
4663 if (amounts.empty())
4664 {
4666 while (1)
4667 {
4668 int ret = mdb_cursor_get(m_cur_output_amounts, &k, &v, op);
4669 op = MDB_NEXT_NODUP;
4670 if (ret == MDB_NOTFOUND)
4671 break;
4672 if (ret)
4673 throw0(DB_ERROR(lmdb_error("Failed to enumerate outputs: ", ret).c_str()));
4674 mdb_size_t num_elems = 0;
4676 uint64_t amount = *(const uint64_t*)k.mv_data;
4677 if (num_elems >= min_count)
4678 histogram[amount] = std::make_tuple(num_elems, 0, 0);
4679 }
4680 }
4681 else
4682 {
4683 for (const auto &amount: amounts)
4684 {
4685 MDB_val_copy<uint64_t> k(amount);
4686 int ret = mdb_cursor_get(m_cur_output_amounts, &k, &v, MDB_SET);
4687 if (ret == MDB_NOTFOUND)
4688 {
4689 if (0 >= min_count)
4690 histogram[amount] = std::make_tuple(0, 0, 0);
4691 }
4692 else if (ret == MDB_SUCCESS)
4693 {
4694 mdb_size_t num_elems = 0;
4696 if (num_elems >= min_count)
4697 histogram[amount] = std::make_tuple(num_elems, 0, 0);
4698 }
4699 else
4700 {
4701 throw0(DB_ERROR(lmdb_error("Failed to enumerate outputs: ", ret).c_str()));
4702 }
4703 }
4704 }
4705
4706 if (unlocked || recent_cutoff > 0) {
4707 const uint64_t blockchain_height = height();
4708 for (std::map<uint64_t, std::tuple<uint64_t, uint64_t, uint64_t>>::iterator i = histogram.begin(); i != histogram.end(); ++i) {
4709 uint64_t amount = i->first;
4710 uint64_t num_elems = std::get<0>(i->second);
4711 while (num_elems > 0) {
4712 const tx_out_index toi = get_output_tx_and_index(amount, num_elems - 1);
4713 const uint64_t height = get_tx_block_height(toi.first);
4714 if (height + (get_hard_fork_version(height) > 7 ? ETN_DEFAULT_TX_SPENDABLE_AGE_V8 : CRYPTONOTE_DEFAULT_TX_SPENDABLE_AGE) <= blockchain_height)
4715 break;
4716 --num_elems;
4717 }
4718 // modifying second does not invalidate the iterator
4719 std::get<1>(i->second) = num_elems;
4720
4721 if (recent_cutoff > 0)
4722 {
4723 uint64_t recent = 0;
4724 while (num_elems > 0) {
4725 const tx_out_index toi = get_output_tx_and_index(amount, num_elems - 1);
4726 const uint64_t height = get_tx_block_height(toi.first);
4728 if (ts < recent_cutoff)
4729 break;
4730 --num_elems;
4731 ++recent;
4732 }
4733 // modifying second does not invalidate the iterator
4734 std::get<2>(i->second) = recent;
4735 }
4736 }
4737 }
4738
4740
4741 return histogram;
4742}
virtual uint64_t get_block_timestamp(const uint64_t &height) const
fetch a block's timestamp
Definition db_lmdb.cpp:3088
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:3916
virtual uint64_t get_tx_block_height(const crypto::hash &h) const
fetches the height of a transaction's block
Definition db_lmdb.cpp:3812
#define ETN_DEFAULT_TX_SPENDABLE_AGE_V8
#define CRYPTONOTE_DEFAULT_TX_SPENDABLE_AGE
@ MDB_NEXT_NODUP
Definition lmdb.h:417
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 4560 of file db_lmdb.cpp.

4561{
4562 if (amounts.size() != 1 && amounts.size() != offsets.size())
4563 throw0(DB_ERROR("Invalid sizes of amounts and offets"));
4564
4565 LOG_PRINT_L3("BlockchainLMDB::" << __func__);
4566 TIME_MEASURE_START(db3);
4567 check_open();
4568 outputs.clear();
4569 outputs.reserve(offsets.size());
4570
4572
4573 RCURSOR(output_amounts);
4574
4575 for (size_t i = 0; i < offsets.size(); ++i)
4576 {
4577 const uint64_t amount = amounts.size() == 1 ? amounts[0] : amounts[i];
4578 MDB_val_set(k, amount);
4579 MDB_val_set(v, offsets[i]);
4580
4581 auto get_result = mdb_cursor_get(m_cur_output_amounts, &k, &v, MDB_GET_BOTH);
4582 if (get_result == MDB_NOTFOUND)
4583 {
4584 if (allow_partial)
4585 {
4586 MDEBUG("Partial result: " << outputs.size() << "/" << offsets.size());
4587 break;
4588 }
4589 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()));
4590 }
4591 else if (get_result)
4592 throw0(DB_ERROR(lmdb_error("Error attempting to retrieve an output pubkey from the db", get_result).c_str()));
4593
4594 if (amount == 0)
4595 {
4596 const outkey *okp = (const outkey *)v.mv_data;
4597 outputs.push_back(okp->data);
4598 }
4599 else
4600 {
4601 const pre_rct_outkey *okp = (const pre_rct_outkey *)v.mv_data;
4602 outputs.resize(outputs.size() + 1);
4603 output_data_t &data = outputs.back();
4604 memcpy(&data, &okp->data, sizeof(pre_rct_output_data_t));
4605 data.commitment = rct::zeroCommit(amount);
4606 }
4607 }
4608
4610
4612 LOG_PRINT_L3("db3: " << db3);
4613}
virtual uint64_t get_num_outputs(const uint64_t &amount) const
fetches the number of outputs of a given amount
Definition db_lmdb.cpp:3835
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 3859 of file db_lmdb.cpp.

3860{
3861 LOG_PRINT_L3("BlockchainLMDB::" << __func__);
3862 check_open();
3863
3865 RCURSOR(output_amounts);
3866
3867 MDB_val_set(k, amount);
3868 MDB_val_set(v, index);
3869 auto get_result = mdb_cursor_get(m_cur_output_amounts, &k, &v, MDB_GET_BOTH);
3870 if (get_result == MDB_NOTFOUND)
3871 throw1(OUTPUT_DNE(std::string("Attempting to get output pubkey by index, but key does not exist: amount " +
3872 std::to_string(amount) + ", index " + std::to_string(index)).c_str()));
3873 else if (get_result)
3874 throw0(DB_ERROR("Error attempting to retrieve an output pubkey from the db"));
3875
3876 output_data_t ret;
3877 if (amount == 0)
3878 {
3879 const outkey *okp = (const outkey *)v.mv_data;
3880 ret = okp->data;
3881 }
3882 else
3883 {
3884 const pre_rct_outkey *okp = (const pre_rct_outkey *)v.mv_data;
3885 memcpy(&ret, &okp->data, sizeof(pre_rct_output_data_t));;
3886 if (include_commitmemt)
3887 ret.commitment = rct::zeroCommit(amount);
3888 }
3890 return ret;
3891}
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 4615 of file db_lmdb.cpp.

4616{
4617 LOG_PRINT_L3("BlockchainLMDB::" << __func__);
4618 check_open();
4619 indices.clear();
4620
4621 std::vector <uint64_t> tx_indices;
4622 tx_indices.reserve(offsets.size());
4624
4625 RCURSOR(output_amounts);
4626
4627 MDB_val_set(k, amount);
4628 for (const uint64_t &index : offsets)
4629 {
4630 MDB_val_set(v, index);
4631
4632 auto get_result = mdb_cursor_get(m_cur_output_amounts, &k, &v, MDB_GET_BOTH);
4633 if (get_result == MDB_NOTFOUND)
4634 throw1(OUTPUT_DNE("Attempting to get output by index, but key does not exist"));
4635 else if (get_result)
4636 throw0(DB_ERROR(lmdb_error("Error attempting to retrieve an output from the db", get_result).c_str()));
4637
4638 const outkey *okp = (const outkey *)v.mv_data;
4639 tx_indices.push_back(okp->output_id);
4640 }
4641
4642 TIME_MEASURE_START(db3);
4643 if(tx_indices.size() > 0)
4644 {
4645 get_output_tx_and_index_from_global(tx_indices, indices);
4646 }
4648 LOG_PRINT_L3("db3: " << db3);
4649}
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 3916 of file db_lmdb.cpp.

3917{
3918 LOG_PRINT_L3("BlockchainLMDB::" << __func__);
3919 std::vector < uint64_t > offsets;
3920 std::vector<tx_out_index> indices;
3921 offsets.push_back(index);
3922 get_output_tx_and_index(amount, offsets, indices);
3923 if (!indices.size())
3924 throw1(OUTPUT_DNE("Attempting to get an output index by amount and amount index, but amount not found"));
3925
3926 return indices[0];
3927}
Here is the call graph for this function:
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 4532 of file db_lmdb.cpp.

4534{
4535 LOG_PRINT_L3("BlockchainLMDB::" << __func__);
4536 check_open();
4537 tx_out_indices.clear();
4538 tx_out_indices.reserve(global_indices.size());
4539
4541 RCURSOR(output_txs);
4542
4543 for (const uint64_t &output_id : global_indices)
4544 {
4545 MDB_val_set(v, output_id);
4546
4547 auto get_result = mdb_cursor_get(m_cur_output_txs, (MDB_val *)&zerokval, &v, MDB_GET_BOTH);
4548 if (get_result == MDB_NOTFOUND)
4549 throw1(OUTPUT_DNE("output with given index not in db"));
4550 else if (get_result)
4551 throw0(DB_ERROR("DB error attempting to fetch output tx hash"));
4552
4553 const outtx *ot = (const outtx *)v.mv_data;
4554 tx_out_indices.push_back(tx_out_index(ot->tx_hash, ot->local_index));
4555 }
4556
4558}
#define m_cur_output_txs
Definition db_lmdb.h:84
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 3893 of file db_lmdb.cpp.

3894{
3895 LOG_PRINT_L3("BlockchainLMDB::" << __func__);
3896 check_open();
3897
3899 RCURSOR(output_txs);
3900
3901 MDB_val_set(v, output_id);
3902
3903 auto get_result = mdb_cursor_get(m_cur_output_txs, (MDB_val *)&zerokval, &v, MDB_GET_BOTH);
3904 if (get_result == MDB_NOTFOUND)
3905 throw1(OUTPUT_DNE("output with given index not in db"));
3906 else if (get_result)
3907 throw0(DB_ERROR("DB error attempting to fetch output tx hash"));
3908
3909 outtx *ot = (outtx *)v.mv_data;
3910 tx_out_index ret = tx_out_index(ot->tx_hash, ot->local_index);
3911
3913 return ret;
3914}
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 3721 of file db_lmdb.cpp.

3722{
3723 LOG_PRINT_L3("BlockchainLMDB::" << __func__);
3724 check_open();
3725
3727 RCURSOR(tx_indices);
3728 RCURSOR(txs_prunable);
3729
3730 MDB_val_set(v, h);
3731 MDB_val result;
3732 auto get_result = mdb_cursor_get(m_cur_tx_indices, (MDB_val *)&zerokval, &v, MDB_GET_BOTH);
3733 if (get_result == 0)
3734 {
3735 const txindex *tip = (const txindex *)v.mv_data;
3736 MDB_val_set(val_tx_id, tip->data.tx_id);
3737 get_result = mdb_cursor_get(m_cur_txs_prunable, &val_tx_id, &result, MDB_SET);
3738 }
3739 if (get_result == MDB_NOTFOUND)
3740 return false;
3741 else if (get_result)
3742 throw0(DB_ERROR(lmdb_error("DB error attempting to fetch tx from hash", get_result).c_str()));
3743
3744 bd.assign(reinterpret_cast<char*>(result.mv_data), result.mv_size);
3745
3747
3748 return true;
3749}
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 3751 of file db_lmdb.cpp.

3752{
3753 LOG_PRINT_L3("BlockchainLMDB::" << __func__);
3754 check_open();
3755
3757 RCURSOR(tx_indices);
3758 RCURSOR(txs_prunable_hash);
3759
3760 MDB_val_set(v, tx_hash);
3761 MDB_val result, val_tx_prunable_hash;
3762 auto get_result = mdb_cursor_get(m_cur_tx_indices, (MDB_val *)&zerokval, &v, MDB_GET_BOTH);
3763 if (get_result == 0)
3764 {
3765 txindex *tip = (txindex *)v.mv_data;
3766 MDB_val_set(val_tx_id, tip->data.tx_id);
3767 get_result = mdb_cursor_get(m_cur_txs_prunable_hash, &val_tx_id, &result, MDB_SET);
3768 }
3769 if (get_result == MDB_NOTFOUND)
3770 return false;
3771 else if (get_result)
3772 throw0(DB_ERROR(lmdb_error("DB error attempting to fetch tx prunable hash from tx hash", get_result).c_str()));
3773
3774 prunable_hash = *(const crypto::hash*)result.mv_data;
3775
3777
3778 return true;
3779}
#define m_cur_txs_prunable_hash
Definition db_lmdb.h:89
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 3691 of file db_lmdb.cpp.

3692{
3693 LOG_PRINT_L3("BlockchainLMDB::" << __func__);
3694 check_open();
3695
3697 RCURSOR(tx_indices);
3698 RCURSOR(txs_pruned);
3699
3700 MDB_val_set(v, h);
3701 MDB_val result;
3702 auto get_result = mdb_cursor_get(m_cur_tx_indices, (MDB_val *)&zerokval, &v, MDB_GET_BOTH);
3703 if (get_result == 0)
3704 {
3705 txindex *tip = (txindex *)v.mv_data;
3706 MDB_val_set(val_tx_id, tip->data.tx_id);
3707 get_result = mdb_cursor_get(m_cur_txs_pruned, &val_tx_id, &result, MDB_SET);
3708 }
3709 if (get_result == MDB_NOTFOUND)
3710 return false;
3711 else if (get_result)
3712 throw0(DB_ERROR(lmdb_error("DB error attempting to fetch tx from hash", get_result).c_str()));
3713
3714 bd.assign(reinterpret_cast<char*>(result.mv_data), result.mv_size);
3715
3717
3718 return true;
3719}
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 3517 of file db_lmdb.cpp.

3518{
3519 LOG_PRINT_L3("BlockchainLMDB::" << __func__);
3520 check_open();
3521 uint64_t m_height = height();
3522
3523 if (m_height != 0)
3524 {
3525 return get_block_from_height(m_height - 1);
3526 }
3527
3528 block b;
3529 return b;
3530}
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 3173 of file db_lmdb.cpp.

3174{
3175 LOG_PRINT_L3("BlockchainLMDB::" << __func__);
3176 check_open();
3177 uint64_t m_height = height();
3178
3179 // if no blocks, return 0
3180 if (m_height == 0)
3181 {
3182 return 0;
3183 }
3184
3185 return get_block_timestamp(m_height - 1);
3186}
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 3929 of file db_lmdb.cpp.

3930{
3931 LOG_PRINT_L3("BlockchainLMDB::" << __func__);
3932
3933 check_open();
3934
3936 RCURSOR(tx_outputs);
3937
3938 MDB_val_set(k_tx_id, tx_id);
3939 MDB_val v;
3940 std::vector<std::vector<uint64_t>> amount_output_indices_set;
3941 amount_output_indices_set.reserve(n_txes);
3942
3944 while (n_txes-- > 0)
3945 {
3946 int result = mdb_cursor_get(m_cur_tx_outputs, &k_tx_id, &v, op);
3947 if (result == MDB_NOTFOUND)
3948 LOG_PRINT_L0("WARNING: Unexpected: tx has no amount indices stored in "
3949 "tx_outputs, but it should have an empty entry even if it's a tx without "
3950 "outputs");
3951 else if (result)
3952 throw0(DB_ERROR(lmdb_error("DB error attempting to get data for tx_outputs[tx_index]", result).c_str()));
3953
3954 op = MDB_NEXT;
3955
3956 const uint64_t* indices = (const uint64_t*)v.mv_data;
3957 size_t num_outputs = v.mv_size / sizeof(uint64_t);
3958
3959 amount_output_indices_set.resize(amount_output_indices_set.size() + 1);
3960 std::vector<uint64_t> &amount_output_indices = amount_output_indices_set.back();
3961 amount_output_indices.reserve(num_outputs);
3962 for (size_t i = 0; i < num_outputs; ++i)
3963 {
3964 amount_output_indices.push_back(indices[i]);
3965 }
3966 }
3967
3969 return amount_output_indices_set;
3970}
#define m_cur_tx_outputs
Definition db_lmdb.h:92
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 3655 of file db_lmdb.cpp.

3656{
3657 LOG_PRINT_L3("BlockchainLMDB::" << __func__);
3658 check_open();
3659
3661 RCURSOR(tx_indices);
3662 RCURSOR(txs_pruned);
3663 RCURSOR(txs_prunable);
3664
3665 MDB_val_set(v, h);
3666 MDB_val result0, result1;
3667 auto get_result = mdb_cursor_get(m_cur_tx_indices, (MDB_val *)&zerokval, &v, MDB_GET_BOTH);
3668 if (get_result == 0)
3669 {
3670 txindex *tip = (txindex *)v.mv_data;
3671 MDB_val_set(val_tx_id, tip->data.tx_id);
3672 get_result = mdb_cursor_get(m_cur_txs_pruned, &val_tx_id, &result0, MDB_SET);
3673 if (get_result == 0)
3674 {
3675 get_result = mdb_cursor_get(m_cur_txs_prunable, &val_tx_id, &result1, MDB_SET);
3676 }
3677 }
3678 if (get_result == MDB_NOTFOUND)
3679 return false;
3680 else if (get_result)
3681 throw0(DB_ERROR(lmdb_error("DB error attempting to fetch tx from hash", get_result).c_str()));
3682
3683 bd.assign(reinterpret_cast<char*>(result0.mv_data), result0.mv_size);
3684 bd.append(reinterpret_cast<char*>(result1.mv_data), result1.mv_size);
3685
3687
3688 return true;
3689}
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 3812 of file db_lmdb.cpp.

3813{
3814 LOG_PRINT_L3("BlockchainLMDB::" << __func__);
3815 check_open();
3816
3818 RCURSOR(tx_indices);
3819
3820 MDB_val_set(v, h);
3821 auto get_result = mdb_cursor_get(m_cur_tx_indices, (MDB_val *)&zerokval, &v, MDB_GET_BOTH);
3822 if (get_result == MDB_NOTFOUND)
3823 {
3824 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()));
3825 }
3826 else if (get_result)
3827 throw0(DB_ERROR(lmdb_error("DB error attempting to fetch tx height from hash", get_result).c_str()));
3828
3829 txindex *tip = (txindex *)v.mv_data;
3830 uint64_t ret = tip->data.block_id;
3832 return ret;
3833}
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 3781 of file db_lmdb.cpp.

3782{
3783 LOG_PRINT_L3("BlockchainLMDB::" << __func__);
3784 check_open();
3785
3787 int result;
3788
3789 MDB_stat db_stats;
3790 if ((result = mdb_stat(m_txn, m_txs_pruned, &db_stats)))
3791 throw0(DB_ERROR(lmdb_error("Failed to query m_txs_pruned: ", result).c_str()));
3792
3794
3795 return db_stats.ms_entries;
3796}
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 1973 of file db_lmdb.cpp.

1974{
1975 LOG_PRINT_L3("BlockchainLMDB::" << __func__);
1976 check_open();
1977
1978 std::string hex_hash;
1979 hex_hash = epee::string_tools::pod_to_hex(tx_hash);
1981 RCURSOR(tx_inputs)
1982
1983 chainstate_key_t key;
1984 key.tx_hash = tx_hash;
1985 key.relative_out_index = relative_out_index;
1986
1987 MDB_val k = {sizeof(key), (void *)&key};
1988 MDB_val v;
1989 auto result = mdb_cursor_get(m_cur_tx_inputs, &k, &v, MDB_SET_KEY);
1990 if (result == MDB_NOTFOUND)
1991 return tx_input_t();
1992 if (result != 0)
1993 throw1(DB_ERROR(lmdb_error("Error finding tx input: ", result).c_str()));
1994
1996 return *(const tx_input_t *) v.mv_data;
1997}
#define m_cur_tx_inputs
Definition db_lmdb.h:102
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 3798 of file db_lmdb.cpp.

3799{
3800 LOG_PRINT_L3("BlockchainLMDB::" << __func__);
3801 check_open();
3802 std::vector<transaction> v;
3803
3804 for (auto& h : hlist)
3805 {
3806 v.push_back(get_tx(h));
3807 }
3808
3809 return v;
3810}
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 3634 of file db_lmdb.cpp.

3635{
3636 LOG_PRINT_L3("BlockchainLMDB::" << __func__);
3637 check_open();
3638
3640 RCURSOR(tx_indices);
3641
3642 MDB_val_set(v, h);
3643 auto get_result = mdb_cursor_get(m_cur_tx_indices, (MDB_val *)&zerokval, &v, MDB_GET_BOTH);
3644 if (get_result == MDB_NOTFOUND)
3645 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()));
3646 else if (get_result)
3647 throw0(DB_ERROR(lmdb_error("DB error attempting to fetch tx data from hash: ", get_result).c_str()));
3648
3649 txindex *tip = (txindex *)v.mv_data;
3650 uint64_t ret = tip->data.unlock_time;
3652 return ret;
3653}
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 2600 of file db_lmdb.cpp.

2601{
2603 if (!get_txpool_tx_blob(txid, bd))
2604 throw1(DB_ERROR("Tx not found in txpool: "));
2605 return bd;
2606}
virtual bool get_txpool_tx_blob(const crypto::hash &txid, cryptonote::blobdata &bd) const
get a txpool transaction's blob
Definition db_lmdb.cpp:2579
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 2579 of file db_lmdb.cpp.

2580{
2581 LOG_PRINT_L3("BlockchainLMDB::" << __func__);
2582 check_open();
2583
2585 RCURSOR(txpool_blob)
2586
2587 MDB_val k = {sizeof(txid), (void *)&txid};
2588 MDB_val v;
2589 auto result = mdb_cursor_get(m_cur_txpool_blob, &k, &v, MDB_SET);
2590 if (result == MDB_NOTFOUND)
2591 return false;
2592 if (result != 0)
2593 throw1(DB_ERROR(lmdb_error("Error finding txpool tx blob: ", result).c_str()));
2594
2595 bd.assign(reinterpret_cast<const char*>(v.mv_data), v.mv_size);
2597 return true;
2598}
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 2467 of file db_lmdb.cpp.

2468{
2469 LOG_PRINT_L3("BlockchainLMDB::" << __func__);
2470 check_open();
2471
2472 int result;
2473 uint64_t num_entries = 0;
2474
2476
2477 if (include_unrelayed_txes)
2478 {
2479 // No filtering, we can get the number of tx the "fast" way
2480 MDB_stat db_stats;
2481 if ((result = mdb_stat(m_txn, m_txpool_meta, &db_stats)))
2482 throw0(DB_ERROR(lmdb_error("Failed to query m_txpool_meta: ", result).c_str()));
2483 num_entries = db_stats.ms_entries;
2484 }
2485 else
2486 {
2487 // Filter unrelayed tx out of the result, so we need to loop over transactions and check their meta data
2488 RCURSOR(txpool_meta);
2489 RCURSOR(txpool_blob);
2490
2491 MDB_val k;
2492 MDB_val v;
2494 while (1)
2495 {
2496 result = mdb_cursor_get(m_cur_txpool_meta, &k, &v, op);
2497 op = MDB_NEXT;
2498 if (result == MDB_NOTFOUND)
2499 break;
2500 if (result)
2501 throw0(DB_ERROR(lmdb_error("Failed to enumerate txpool tx metadata: ", result).c_str()));
2502 const txpool_tx_meta_t &meta = *(const txpool_tx_meta_t*)v.mv_data;
2503 if (!meta.do_not_relay)
2504 ++num_entries;
2505 }
2506 }
2508
2509 return num_entries;
2510}
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 2558 of file db_lmdb.cpp.

2559{
2560 LOG_PRINT_L3("BlockchainLMDB::" << __func__);
2561 check_open();
2562
2564 RCURSOR(txpool_meta)
2565
2566 MDB_val k = {sizeof(txid), (void *)&txid};
2567 MDB_val v;
2568 auto result = mdb_cursor_get(m_cur_txpool_meta, &k, &v, MDB_SET);
2569 if (result == MDB_NOTFOUND)
2570 return false;
2571 if (result != 0)
2572 throw1(DB_ERROR(lmdb_error("Error finding txpool tx meta: ", result).c_str()));
2573
2574 meta = *(const txpool_tx_meta_t*)v.mv_data;
2576 return true;
2577}
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 3972 of file db_lmdb.cpp.

3973{
3974 LOG_PRINT_L3("BlockchainLMDB::" << __func__);
3975 check_open();
3976
3977 bool ret;
3978
3980 RCURSOR(spent_keys);
3981
3982 MDB_val k = {sizeof(img), (void *)&img};
3983 ret = (mdb_cursor_get(m_cur_spent_keys, (MDB_val *)&zerokval, &k, MDB_GET_BOTH) == 0);
3984
3986 return ret;
3987}
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 3532 of file db_lmdb.cpp.

3533{
3534 LOG_PRINT_L3("BlockchainLMDB::" << __func__);
3535 check_open();
3537 int result;
3538
3539 // get current height
3540 MDB_stat db_stats;
3541 if ((result = mdb_stat(m_txn, m_blocks, &db_stats)))
3542 throw0(DB_ERROR(lmdb_error("Failed to query m_blocks: ", result).c_str()));
3543 return db_stats.ms_entries;
3544}
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 1763 of file db_lmdb.cpp.

1764{
1765 LOG_PRINT_L3("BlockchainLMDB::" << __func__);
1766 check_open();
1767 return false;
1768}

◆ 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 1357 of file db_lmdb.cpp.

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

◆ 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 4513 of file db_lmdb.cpp.

4514{
4515 LOG_PRINT_L3("BlockchainLMDB::" << __func__);
4516 check_open();
4517
4519
4520 try
4521 {
4522 BlockchainDB::pop_block(blk, txs);
4524 }
4525 catch (...)
4526 {
4528 throw;
4529 }
4530}
virtual void block_wtxn_abort()
Definition db_lmdb.cpp:4461
virtual void block_wtxn_start()
Definition db_lmdb.cpp:4406
virtual void block_wtxn_stop()
Definition db_lmdb.cpp:4439
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 2926 of file db_lmdb.cpp.

2927{
2928 return prune_worker(prune_mode_prune, pruning_seed);
2929}

◆ 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 1740 of file db_lmdb.cpp.

1741{
1742 const std::string filename = folder + "/data.mdb";
1743 try
1744 {
1745 boost::filesystem::remove(filename);
1746 }
1747 catch (const std::exception &e)
1748 {
1749 MERROR("Failed to remove " << filename << ": " << e.what());
1750 return false;
1751 }
1752 return true;
1753}

◆ 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 2528 of file db_lmdb.cpp.

2529{
2530 LOG_PRINT_L3("BlockchainLMDB::" << __func__);
2531 check_open();
2532 mdb_txn_cursors *m_cursors = &m_wcursors;
2533
2534 CURSOR(txpool_meta)
2535 CURSOR(txpool_blob)
2536
2537 MDB_val k = {sizeof(txid), (void *)&txid};
2538 auto result = mdb_cursor_get(m_cur_txpool_meta, &k, NULL, MDB_SET);
2539 if (result != 0 && result != MDB_NOTFOUND)
2540 throw1(DB_ERROR(lmdb_error("Error finding txpool tx meta to remove: ", result).c_str()));
2541 if (!result)
2542 {
2543 result = mdb_cursor_del(m_cur_txpool_meta, 0);
2544 if (result)
2545 throw1(DB_ERROR(lmdb_error("Error adding removal of txpool tx metadata to db transaction: ", result).c_str()));
2546 }
2547 result = mdb_cursor_get(m_cur_txpool_blob, &k, NULL, MDB_SET);
2548 if (result != 0 && result != MDB_NOTFOUND)
2549 throw1(DB_ERROR(lmdb_error("Error finding txpool tx blob to remove: ", result).c_str()));
2550 if (!result)
2551 {
2552 result = mdb_cursor_del(m_cur_txpool_blob, 0);
2553 if (result)
2554 throw1(DB_ERROR(lmdb_error("Error adding removal of txpool tx blob to db transaction: ", result).c_str()));
2555 }
2556}
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 1662 of file db_lmdb.cpp.

1663{
1664 LOG_PRINT_L3("BlockchainLMDB::" << __func__);
1665 check_open();
1666
1667 mdb_txn_safe txn;
1668 if (auto result = lmdb_txn_begin(m_env, NULL, 0, txn))
1669 throw0(DB_ERROR(lmdb_error("Failed to create a transaction for the db: ", result).c_str()));
1670
1671 if (auto result = mdb_drop(txn, m_blocks, 0))
1672 throw0(DB_ERROR(lmdb_error("Failed to drop m_blocks: ", result).c_str()));
1673 if (auto result = mdb_drop(txn, m_block_info, 0))
1674 throw0(DB_ERROR(lmdb_error("Failed to drop m_block_info: ", result).c_str()));
1675 if (auto result = mdb_drop(txn, m_block_heights, 0))
1676 throw0(DB_ERROR(lmdb_error("Failed to drop m_block_heights: ", result).c_str()));
1677 if (auto result = mdb_drop(txn, m_txs_pruned, 0))
1678 throw0(DB_ERROR(lmdb_error("Failed to drop m_txs_pruned: ", result).c_str()));
1679 if (auto result = mdb_drop(txn, m_txs_prunable, 0))
1680 throw0(DB_ERROR(lmdb_error("Failed to drop m_txs_prunable: ", result).c_str()));
1681 if (auto result = mdb_drop(txn, m_txs_prunable_hash, 0))
1682 throw0(DB_ERROR(lmdb_error("Failed to drop m_txs_prunable_hash: ", result).c_str()));
1683 if (auto result = mdb_drop(txn, m_txs_prunable_tip, 0))
1684 throw0(DB_ERROR(lmdb_error("Failed to drop m_txs_prunable_tip: ", result).c_str()));
1685 if (auto result = mdb_drop(txn, m_tx_indices, 0))
1686 throw0(DB_ERROR(lmdb_error("Failed to drop m_tx_indices: ", result).c_str()));
1687 if (auto result = mdb_drop(txn, m_tx_outputs, 0))
1688 throw0(DB_ERROR(lmdb_error("Failed to drop m_tx_outputs: ", result).c_str()));
1689 if (auto result = mdb_drop(txn, m_output_txs, 0))
1690 throw0(DB_ERROR(lmdb_error("Failed to drop m_output_txs: ", result).c_str()));
1691 if (auto result = mdb_drop(txn, m_output_amounts, 0))
1692 throw0(DB_ERROR(lmdb_error("Failed to drop m_output_amounts: ", result).c_str()));
1693 if (auto result = mdb_drop(txn, m_spent_keys, 0))
1694 throw0(DB_ERROR(lmdb_error("Failed to drop m_spent_keys: ", result).c_str()));
1695 (void)mdb_drop(txn, m_hf_starting_heights, 0); // this one is dropped in new code
1696 if (auto result = mdb_drop(txn, m_hf_versions, 0))
1697 throw0(DB_ERROR(lmdb_error("Failed to drop m_hf_versions: ", result).c_str()));
1698 if (auto result = mdb_drop(txn, m_validators, 0))
1699 throw0(DB_ERROR(lmdb_error("Failed to drop m_validators: ", result).c_str()));
1700 if (auto result = mdb_drop(txn, m_utxos, 0))
1701 throw0(DB_ERROR(lmdb_error("Failed to drop m_utxos: ", result).c_str()));
1702 if (auto result = mdb_drop(txn, m_addr_outputs, 0))
1703 throw0(DB_ERROR(lmdb_error("Failed to drop m_addr_outputs: ", result).c_str()));
1704 if (auto result = mdb_drop(txn, m_addr_txs, 0))
1705 throw0(DB_ERROR(lmdb_error("Failed to drop m_addr_txs: ", result).c_str()));
1706 if (auto result = mdb_drop(txn, m_addr_txs_old, 0))
1707 throw0(DB_ERROR(lmdb_error("Failed to drop m_addr_txs_old: ", result).c_str()));
1708 if (auto result = mdb_drop(txn, m_tx_inputs, 0))
1709 throw0(DB_ERROR(lmdb_error("Failed to drop m_tx_inputs: ", result).c_str()));
1710 if (auto result = mdb_drop(txn, m_properties, 0))
1711 throw0(DB_ERROR(lmdb_error("Failed to drop m_properties: ", result).c_str()));
1712
1713 // init with current version
1714 MDB_val_str(k, "version");
1715 MDB_val_copy<uint32_t> v(VERSION);
1716 if (auto result = mdb_put(txn, m_properties, &k, &v, 0))
1717 throw0(DB_ERROR(lmdb_error("Failed to write version to database: ", result).c_str()));
1718
1719 txn.commit();
1720 m_cum_size = 0;
1721 m_cum_count = 0;
1722}
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 1656 of file db_lmdb.cpp.

1657{
1658 MINFO("switching safe mode " << (onoff ? "on" : "off"));
1660}
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 4343 of file db_lmdb.cpp.

4344{
4345 LOG_PRINT_L3("BlockchainLMDB::" << __func__);
4346 if ((batch_transactions) && (m_batch_transactions))
4347 {
4348 MINFO("batch transaction mode already enabled, but asked to enable batch mode");
4349 }
4350 m_batch_transactions = batch_transactions;
4351 MINFO("batch transactions " << (m_batch_transactions ? "enabled" : "disabled"));
4352}

◆ 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 3327 of file db_lmdb.cpp.

3328{
3329 LOG_PRINT_L3("BlockchainLMDB::" << __func__ << " height: " << height);
3330 check_open();
3331 mdb_txn_cursors *m_cursors = &m_wcursors;
3332
3333 int result;
3334
3335 CURSOR(block_info)
3336
3337 MDB_val_set(val_bi, height);
3338 result = mdb_cursor_get(m_cur_block_info, (MDB_val *)&zerokval, &val_bi, MDB_GET_BOTH);
3339 if (result == MDB_NOTFOUND)
3340 {
3341 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()));
3342 }
3343 else if (result)
3344 throw0(DB_ERROR("Error attempting to set a cumulative difficulty"));
3345
3346 mdb_block_info *result_bi = (mdb_block_info *)val_bi.mv_data;
3347
3348 mdb_block_info bi;
3349 bi.bi_height = result_bi->bi_height;
3350 bi.bi_timestamp = result_bi->bi_timestamp;
3351 bi.bi_coins = result_bi->bi_coins;
3352 bi.bi_weight = result_bi->bi_weight;
3353 //bi.bi_diff_lo = diff; // TODO
3354 bi.bi_hash = result_bi->bi_hash;
3355
3356 MDB_val_set(val, bi);
3357 result = mdb_cursor_put(m_cur_block_info, (MDB_val *)&val_bi, &val, MDB_CURRENT);
3358 if (result)
3359 throw0(DB_ERROR(lmdb_error("Failed to set cumulative difficulty to db transaction: ", result).c_str()));
3360
3361}
#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 1640 of file db_lmdb.cpp.

1641{
1642 LOG_PRINT_L3("BlockchainLMDB::" << __func__);
1643 check_open();
1644
1645 if (is_read_only())
1646 return;
1647
1648 // Does nothing unless LMDB environment was opened with MDB_NOSYNC or in part
1649 // MDB_NOMETASYNC. Force flush to be synchronous.
1650 if (auto result = mdb_env_sync(m_env, true))
1651 {
1652 throw0(DB_ERROR(lmdb_error("Failed to sync database: ", result).c_str()));
1653 }
1654}
virtual bool is_read_only() const =0
is BlockchainDB in read-only mode?
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 3502 of file db_lmdb.cpp.

3503{
3504 LOG_PRINT_L3("BlockchainLMDB::" << __func__);
3505 check_open();
3506 uint64_t m_height = height();
3507 if (block_height)
3508 *block_height = m_height - 1;
3509 if (m_height != 0)
3510 {
3511 return get_block_hash_from_height(m_height - 1);
3512 }
3513
3514 return null_hash;
3515}
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 3568 of file db_lmdb.cpp.

3569{
3570 LOG_PRINT_L3("BlockchainLMDB::" << __func__);
3571 check_open();
3572
3574 RCURSOR(tx_indices);
3575
3576 MDB_val_set(key, h);
3577 bool tx_found = false;
3578
3579 TIME_MEASURE_START(time1);
3580 auto get_result = mdb_cursor_get(m_cur_tx_indices, (MDB_val *)&zerokval, &key, MDB_GET_BOTH);
3581 if (get_result == 0)
3582 tx_found = true;
3583 else if (get_result != MDB_NOTFOUND)
3584 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()));
3585
3586 TIME_MEASURE_FINISH(time1);
3587 time_tx_exists += time1;
3588
3590
3591 if (! tx_found)
3592 {
3593 LOG_PRINT_L1("transaction with hash " << epee::string_tools::pod_to_hex(h) << " not found in db");
3594 return false;
3595 }
3596
3597 return true;
3598}
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 3600 of file db_lmdb.cpp.

3601{
3602 LOG_PRINT_L3("BlockchainLMDB::" << __func__);
3603 check_open();
3604
3606 RCURSOR(tx_indices);
3607
3608 MDB_val_set(v, h);
3609
3610 TIME_MEASURE_START(time1);
3611 auto get_result = mdb_cursor_get(m_cur_tx_indices, (MDB_val *)&zerokval, &v, MDB_GET_BOTH);
3612 TIME_MEASURE_FINISH(time1);
3613 time_tx_exists += time1;
3614 if (!get_result) {
3615 txindex *tip = (txindex *)v.mv_data;
3616 tx_id = tip->data.tx_id;
3617 }
3618
3620
3621 bool ret = false;
3622 if (get_result == MDB_NOTFOUND)
3623 {
3624 LOG_PRINT_L1("transaction with hash " << epee::string_tools::pod_to_hex(h) << " not found in db");
3625 }
3626 else if (get_result)
3627 throw0(DB_ERROR(lmdb_error("DB error attempting to fetch transaction from hash", get_result).c_str()));
3628 else
3629 ret = true;
3630
3631 return ret;
3632}
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 2512 of file db_lmdb.cpp.

2513{
2514 LOG_PRINT_L3("BlockchainLMDB::" << __func__);
2515 check_open();
2516
2518 RCURSOR(txpool_meta)
2519
2520 MDB_val k = {sizeof(txid), (void *)&txid};
2521 auto result = mdb_cursor_get(m_cur_txpool_meta, &k, NULL, MDB_SET);
2522 if (result != 0 && result != MDB_NOTFOUND)
2523 throw1(DB_ERROR(lmdb_error("Error finding txpool tx meta: ", result).c_str()));
2525 return result != MDB_NOTFOUND;
2526}
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 1771 of file db_lmdb.cpp.

1772{
1773 LOG_PRINT_L3("BlockchainLMDB::" << __func__);
1774 check_open();
1775}

◆ 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 2931 of file db_lmdb.cpp.

2932{
2933 return prune_worker(prune_mode_update, 0);
2934}
@ prune_mode_update
Definition db_lmdb.cpp:2641

◆ 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 2441 of file db_lmdb.cpp.

2442{
2443 LOG_PRINT_L3("BlockchainLMDB::" << __func__);
2444 check_open();
2445 mdb_txn_cursors *m_cursors = &m_wcursors;
2446
2447 CURSOR(txpool_meta)
2448 CURSOR(txpool_blob)
2449
2450 MDB_val k = {sizeof(txid), (void *)&txid};
2451 MDB_val v;
2452 auto result = mdb_cursor_get(m_cur_txpool_meta, &k, &v, MDB_SET);
2453 if (result != 0)
2454 throw1(DB_ERROR(lmdb_error("Error finding txpool tx meta to update: ", result).c_str()));
2455 result = mdb_cursor_del(m_cur_txpool_meta, 0);
2456 if (result)
2457 throw1(DB_ERROR(lmdb_error("Error adding removal of txpool tx metadata to db transaction: ", result).c_str()));
2458 v = MDB_val({sizeof(meta), (void *)&meta});
2459 if ((result = mdb_cursor_put(m_cur_txpool_meta, &k, &v, MDB_NODUPDATA)) != 0) {
2460 if (result == MDB_KEYEXIST)
2461 throw1(DB_ERROR("Attempting to add txpool tx metadata that's already in the db"));
2462 else
2463 throw1(DB_ERROR(lmdb_error("Error adding txpool tx metadata to db transaction: ", result).c_str()));
2464 }
2465}
Here is the call graph for this function:

The documentation for this class was generated from the following files:
  • /home/abuild/rpmbuild/BUILD/electroneum-5.1.3.1-build/electroneum-5.1.3.1/src/blockchain_db/lmdb/db_lmdb.h
  • /home/abuild/rpmbuild/BUILD/electroneum-5.1.3.1-build/electroneum-5.1.3.1/src/blockchain_db/lmdb/db_lmdb.cpp