Electroneum
cryptonote::Blockchain Class Reference

#include <blockchain.h>

Classes

struct  block_extended_info
 container for passing a block and metadata about it on the blockchain More...
 
struct  transaction_chain_entry
 Now-defunct (TODO: remove) struct from in-memory blockchain. More...
 

Public Member Functions

 Blockchain (tx_memory_pool &tx_pool)
 Blockchain constructor. More...
 
 ~Blockchain ()
 Blockchain destructor. More...
 
bool init (BlockchainDB *db, const network_type nettype=MAINNET, bool offline=false, const cryptonote::test_options *test_options=NULL, difficulty_type fixed_difficulty=0, const GetCheckpointsCallback &get_checkpoints=nullptr, bool ignore_bsig=false, bool fallback_to_pow=false)
 Initialize the Blockchain state. More...
 
bool init (BlockchainDB *db, HardFork *&hf, const network_type nettype=MAINNET, bool offline=false)
 Initialize the Blockchain state. More...
 
bool deinit ()
 Uninitializes the blockchain state. More...
 
void set_checkpoints (checkpoints &&chk_pts)
 assign a set of blockchain checkpoint hashes More...
 
bool get_blocks (uint64_t start_offset, size_t count, std::vector< std::pair< cryptonote::blobdata, block >> &blocks, std::vector< cryptonote::blobdata > &txs) const
 get blocks and transactions from blocks based on start height and count More...
 
bool get_blocks (uint64_t start_offset, size_t count, std::vector< std::pair< cryptonote::blobdata, block >> &blocks) const
 get blocks from blocks based on start height and count More...
 
bool get_alternative_blocks (std::vector< block > &blocks) const
 compiles a list of all blocks stored as alternative chains More...
 
size_t get_alternative_blocks_count () const
 returns the number of alternative blocks stored More...
 
crypto::hash get_block_id_by_height (uint64_t height) const
 gets a block's hash given a height More...
 
bool get_block_by_hash (const crypto::hash &h, block &blk, bool *orphan=NULL) const
 gets the block with a given hash More...
 
bool prepare_handle_incoming_blocks (const std::vector< block_complete_entry > &blocks_entry, std::vector< block > &blocks)
 performs some preprocessing on a group of incoming blocks to speed up verification More...
 
bool cleanup_handle_incoming_blocks (bool force_sync=false)
 incoming blocks post-processing, cleanup, and disk sync More...
 
bool have_tx (const crypto::hash &id) const
 search the blockchain for a transaction by hash More...
 
bool key_images_already_spent (const transaction &tx) const
 check if any key image in a transaction has already been spent More...
 
bool utxo_nonexistence_from_output (const txin_to_key_public &public_output) const
 check if a single utxo in a transaction has already been spent using the hash and out index (v3 tx onwards) More...
 
bool utxo_nonexistent (const transaction &tx) const
 check if any utxo in a transaction has already been spent using the tx (v3 tx onwards) More...
 
bool have_tx_keyimg_as_spent (const crypto::key_image &key_im) const
 check if a key image is already spent on the blockchain More...
 
uint64_t get_current_blockchain_height () const
 get the current height of the blockchain More...
 
crypto::hash get_tail_id () const
 get the hash of the most recent block on the blockchain More...
 
crypto::hash get_tail_id (uint64_t &height) const
 get the height and hash of the most recent block on the blockchain More...
 
difficulty_type get_difficulty_for_next_block ()
 returns the difficulty target the next block to be added must meet More...
 
void normalize_v7_difficulties ()
 Normalize the cumulative difficulty for V7 blocks, fixing the differing difficulty among nodes. More...
 
bool add_new_block (const block &bl_, block_verification_context &bvc)
 adds a block to the blockchain More...
 
bool reset_and_set_genesis_block (const block &b)
 clears the blockchain and starts a new one More...
 
bool create_block_template (block &b, const account_public_address &miner_address, difficulty_type &di, uint64_t &height, uint64_t &expected_reward, const blobdata &ex_nonce)
 creates a new block to mine against More...
 
bool create_block_template (block &b, const crypto::hash *from_block, const account_public_address &miner_address, difficulty_type &di, uint64_t &height, uint64_t &expected_reward, const blobdata &ex_nonce)
 
bool have_block (const crypto::hash &id) const
 checks if a block is known about with a given hash More...
 
size_t get_total_transactions () const
 gets the total number of transactions on the main chain More...
 
bool get_short_chain_history (std::list< crypto::hash > &ids) const
 gets the hashes for a subset of the blockchain More...
 
bool find_blockchain_supplement (const std::list< crypto::hash > &qblock_ids, std::vector< crypto::hash > &hashes, uint64_t &start_height, uint64_t &current_height, bool clip_pruned) const
 get recent block hashes for a foreign chain More...
 
bool find_blockchain_supplement (const std::list< crypto::hash > &qblock_ids, NOTIFY_RESPONSE_CHAIN_ENTRY::request &resp) const
 get recent block hashes for a foreign chain More...
 
bool find_blockchain_supplement (const std::list< crypto::hash > &qblock_ids, uint64_t &starter_offset) const
 find the most recent common point between ours and a foreign chain More...
 
bool find_blockchain_supplement (const uint64_t req_start_block, const std::list< crypto::hash > &qblock_ids, std::vector< std::pair< std::pair< cryptonote::blobdata, crypto::hash >, std::vector< std::pair< crypto::hash, cryptonote::blobdata > > > > &blocks, uint64_t &total_height, uint64_t &start_height, bool pruned, bool get_miner_tx_hash, size_t max_count) const
 get recent blocks for a foreign chain More...
 
bool handle_get_objects (NOTIFY_REQUEST_GET_OBJECTS::request &arg, NOTIFY_RESPONSE_GET_OBJECTS::request &rsp)
 retrieves a set of blocks and their transactions, and possibly other transactions More...
 
uint64_t get_num_mature_outputs (uint64_t amount) const
 get number of outputs of an amount past the minimum spendable age More...
 
crypto::public_key get_output_key (uint64_t amount, uint64_t global_index) const
 get the public key for an output More...
 
bool get_outs (const COMMAND_RPC_GET_OUTPUTS_BIN::request &req, COMMAND_RPC_GET_OUTPUTS_BIN::response &res) const
 gets specific outputs to mix with More...
 
void get_output_key_mask_unlocked (const uint64_t &amount, const uint64_t &index, crypto::public_key &key, rct::key &mask, bool &unlocked) const
 gets an output's key and unlocked state More...
 
bool get_output_distribution (uint64_t amount, uint64_t from_height, uint64_t to_height, uint64_t &start_height, std::vector< uint64_t > &distribution, uint64_t &base) const
 gets per block distribution of outputs of a given amount More...
 
bool get_tx_outputs_gindexs (const crypto::hash &tx_id, std::vector< uint64_t > &indexs) const
 gets the global indices for outputs from a given transaction More...
 
bool get_tx_outputs_gindexs (const crypto::hash &tx_id, size_t n_txes, std::vector< std::vector< uint64_t >> &indexs) const
 
bool store_blockchain ()
 stores the blockchain More...
 
bool check_tx_inputs (transaction &tx, uint64_t &pmax_used_block_height, crypto::hash &max_used_block_id, tx_verification_context &tvc, bool kept_by_block=false)
 validates a transaction's inputs More...
 
uint64_t get_dynamic_base_fee_estimate (uint64_t grace_blocks) const
 get dynamic per kB or byte fee estimate for the next few blocks More...
 
bool check_fee (size_t tx_weight, uint64_t fee) const
 validate a transaction's fee More...
 
bool check_tx_outputs (const transaction &tx, tx_verification_context &tvc)
 check that a transaction's outputs conform to current standards More...
 
uint64_t get_current_cumulative_block_weight_limit () const
 gets the block weight limit based on recent blocks More...
 
uint64_t get_next_long_term_block_weight (uint64_t block_weight) const
 gets the long term block weight for a new block More...
 
uint64_t get_current_cumulative_block_weight_median () const
 gets the block weight median based on recent blocks (same window as for the limit) More...
 
difficulty_type block_difficulty (uint64_t i) const
 gets the difficulty of the block with a given height More...
 
template<class t_ids_container , class t_blocks_container , class t_missed_container >
bool get_blocks (const t_ids_container &block_ids, t_blocks_container &blocks, t_missed_container &missed_bs) const
 gets blocks based on a list of block hashes More...
 
template<class t_ids_container , class t_tx_container , class t_missed_container >
bool get_transactions_blobs (const t_ids_container &txs_ids, t_tx_container &txs, t_missed_container &missed_txs, bool pruned=false) const
 gets transactions based on a list of transaction hashes More...
 
template<class t_ids_container , class t_tx_container , class t_missed_container >
bool get_split_transactions_blobs (const t_ids_container &txs_ids, t_tx_container &txs, t_missed_container &missed_txs) const
 
template<class t_ids_container , class t_tx_container , class t_missed_container >
bool get_transactions (const t_ids_container &txs_ids, t_tx_container &txs, t_missed_container &missed_txs) const
 
void check_against_checkpoints (const checkpoints &points, bool enforce)
 check the blockchain against a set of checkpoints More...
 
void set_enforce_dns_checkpoints (bool enforce)
 configure whether or not to enforce DNS-based checkpoints More...
 
bool update_checkpoints (const std::string &file_path, bool check_dns)
 loads new checkpoints from a file and optionally from DNS More...
 
void set_user_options (uint64_t maxthreads, bool sync_on_blocks, uint64_t sync_threshold, blockchain_db_sync_mode sync_mode, bool fast_sync, std::string validator_key)
 Update the validators public key by fetching data from electroneum's endpoint. More...
 
void set_block_notify (const std::shared_ptr< tools::Notify > &notify)
 sets a block notify object to call for every new block More...
 
void set_reorg_notify (const std::shared_ptr< tools::Notify > &notify)
 sets a reorg notify object to call for every reorg More...
 
void safesyncmode (const bool onoff)
 Put DB in safe sync mode. More...
 
void set_show_time_stats (bool stats)
 set whether or not to show/print time statistics More...
 
HardFork::State get_hard_fork_state () const
 gets the hardfork voting state object More...
 
uint8_t get_current_hard_fork_version () const
 gets the current hardfork version in use/voted for More...
 
uint8_t get_ideal_hard_fork_version () const
 returns the newest hardfork version known to the blockchain More...
 
uint8_t get_next_hard_fork_version () const
 returns the next hardfork version More...
 
uint8_t get_ideal_hard_fork_version (uint64_t height) const
 returns the newest hardfork version voted to be enabled as of a certain height More...
 
uint8_t get_hard_fork_version (uint64_t height) const
 returns the actual hardfork version for a given block height More...
 
uint64_t get_earliest_ideal_height_for_version (uint8_t version) const
 returns the earliest block a given version may activate More...
 
bool get_hard_fork_voting_info (uint8_t version, uint32_t &window, uint32_t &votes, uint32_t &threshold, uint64_t &earliest_height, uint8_t &voting) const
 get information about hardfork voting for a version More...
 
uint64_t get_difficulty_target () const
 get difficulty target based on chain and hardfork version More...
 
bool flush_txes_from_pool (const std::vector< crypto::hash > &txids)
 remove transactions from the transaction pool (if present) More...
 
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=0) const
 return a histogram of outputs on the blockchain More...
 
bool for_all_key_images (std::function< bool(const crypto::key_image &)>) const
 perform a check on all key images in the blockchain More...
 
bool for_blocks_range (const uint64_t &h1, const uint64_t &h2, std::function< bool(uint64_t, const crypto::hash &, const block &)>) const
 perform a check on all blocks in the blockchain in the given range More...
 
bool for_all_transactions (std::function< bool(const crypto::hash &, const cryptonote::transaction &)>, bool pruned) const
 perform a check on all transactions in the blockchain More...
 
bool for_all_outputs (std::function< bool(uint64_t amount, const crypto::hash &tx_hash, uint64_t height, size_t tx_idx)>) const
 perform a check on all outputs in the blockchain More...
 
bool for_all_outputs (uint64_t amount, std::function< bool(uint64_t height)>) const
 perform a check on all outputs of a given amount in the blockchain More...
 
const BlockchainDBget_db () const
 get a reference to the BlockchainDB in use by Blockchain More...
 
BlockchainDBget_db ()
 get a reference to the BlockchainDB in use by Blockchain More...
 
void output_scan_worker (const uint64_t amount, const std::vector< uint64_t > &offsets, std::vector< output_data_t > &outputs) const
 get a number of outputs of a specific amount More...
 
void block_longhash_worker (uint64_t height, const epee::span< const block > &blocks, std::unordered_map< crypto::hash, crypto::hash > &map) const
 computes the "short" and "long" hashes for a set of blocks More...
 
std::list< std::pair< block_extended_info, std::vector< crypto::hash > > > get_alternative_chains () const
 returns a set of known alternate chains More...
 
void add_txpool_tx (const crypto::hash &txid, const cryptonote::blobdata &blob, const txpool_tx_meta_t &meta)
 
void update_txpool_tx (const crypto::hash &txid, const txpool_tx_meta_t &meta)
 
void remove_txpool_tx (const crypto::hash &txid)
 
uint64_t get_txpool_tx_count (bool include_unrelayed_txes=true) const
 
bool get_txpool_tx_meta (const crypto::hash &txid, txpool_tx_meta_t &meta) const
 
bool get_txpool_tx_blob (const crypto::hash &txid, cryptonote::blobdata &bd) const
 
cryptonote::blobdata get_txpool_tx_blob (const crypto::hash &txid) const
 
bool 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
 
uint32_t get_mempool_tx_livetime () const
 
bool is_within_compiled_block_hash_area (uint64_t height) const
 
bool is_within_compiled_block_hash_area () const
 
uint32_t get_blockchain_pruning_seed () const
 
bool prune_blockchain (uint32_t pruning_seed=0)
 
bool update_blockchain_pruning ()
 
bool check_blockchain_pruning ()
 
void lock ()
 
void unlock ()
 
void cancel ()
 
void on_new_tx_from_block (const cryptonote::transaction &tx)
 called when we see a tx originating from a block More...
 
std::vector< time_t > get_last_block_timestamps (unsigned int blocks) const
 returns the timestamps of the last N blocks More...
 
void pop_blocks (uint64_t nblocks)
 removes blocks from the top of the blockchain More...
 
void sign_block (block &b, std::string privateKey)
 Digitally sign the block. More...
 
bool verify_block_signature (const block &b)
 Verify block's digital signature. More...
 
void set_validator_key (std::string key)
 set validator key More...
 
void set_validators_list_instance (std::unique_ptr< electroneum::basic::Validators > &v)
 
electroneum::basic::Validator get_validator_by_height (uint64_t height)
 
network_type get_nettype () const
 get blockchain nettype More...
 

Static Public Member Functions

static uint64_t get_fee_quantization_mask ()
 get fee quantization mask More...
 
static uint64_t get_dynamic_base_fee (uint64_t block_reward, size_t median_block_weight, uint8_t version)
 get dynamic per kB or byte fee for a given block weight More...
 
static const std::vector< HardFork::Params > & get_hard_fork_heights (network_type nettype)
 gets the hardfork heights of given network More...
 

Detailed Description

Definition at line 97 of file blockchain.h.

Constructor & Destructor Documentation

◆ Blockchain()

Blockchain::Blockchain ( tx_memory_pool tx_pool)

Blockchain constructor.

Parameters
tx_poola reference to the transaction pool to be kept by the Blockchain

Definition at line 146 of file blockchain.cpp.

146  :
147  m_db(), m_tx_pool(tx_pool), m_hardfork(NULL), m_timestamps_and_difficulties_height(0), m_current_block_cumul_weight_limit(0), m_current_block_cumul_weight_median(0),
148  m_enforce_dns_checkpoints(false), m_max_prepare_blocks_threads(4), m_db_sync_on_blocks(true), m_db_sync_threshold(1), m_db_sync_mode(db_async), m_db_default_sync(false), m_fast_sync(true), m_show_time_stats(false), m_sync_counter(0), m_bytes_to_sync(0), m_cancel(false),
149  m_long_term_block_weights_window(CRYPTONOTE_LONG_TERM_BLOCK_WEIGHT_WINDOW_SIZE),
150  m_long_term_effective_median_block_weight(0),
151  m_long_term_block_weights_cache_tip_hash(crypto::null_hash),
152  m_long_term_block_weights_cache_rolling_median(CRYPTONOTE_LONG_TERM_BLOCK_WEIGHT_WINDOW_SIZE),
153  m_difficulty_for_next_block_top_hash(crypto::null_hash),
154  m_difficulty_for_next_block(1),
155  m_btc_valid(false),
156  m_batch_success(true)
157 {
158  LOG_PRINT_L3("Blockchain::" << __func__);
159 }
#define CRYPTONOTE_LONG_TERM_BLOCK_WEIGHT_WINDOW_SIZE
handle syncing calls instead of the backing db, asynchronously
Definition: blockchain.h:81
#define LOG_PRINT_L3(x)
Definition: misc_log_ex.h:102

◆ ~Blockchain()

Blockchain::~Blockchain ( )

Blockchain destructor.

Definition at line 161 of file blockchain.cpp.

162 {
163  try { deinit(); }
164  catch (const std::exception &e) { /* ignore */ }
165 }
bool deinit()
Uninitializes the blockchain state.
Definition: blockchain.cpp:660
Here is the call graph for this function:

Member Function Documentation

◆ add_new_block()

bool Blockchain::add_new_block ( const block bl_,
block_verification_context bvc 
)

adds a block to the blockchain

Adds a new block to the blockchain. If the block's parent is not the current top of the blockchain, the block may be added to an alternate chain. If the block does not belong, is already in the blockchain or an alternate chain, or is invalid, return false.

Parameters
bl_the block to be added
bvcmetadata about the block addition's success/failure
Returns
true on successful addition to the blockchain, else false

Definition at line 4196 of file blockchain.cpp.

4197 {
4198  LOG_PRINT_L3("Blockchain::" << __func__);
4199  crypto::hash id = get_block_hash(bl);
4200  CRITICAL_REGION_LOCAL(m_tx_pool);//to avoid deadlock lets lock tx_pool for whole add/reorganize process
4201  CRITICAL_REGION_LOCAL1(m_blockchain_lock);
4202  db_rtxn_guard rtxn_guard(m_db);
4203  if(have_block(id))
4204  {
4205  LOG_PRINT_L3("block with id = " << id << " already exists");
4206  bvc.m_already_exists = true;
4207  m_blocks_txs_check.clear();
4208  return false;
4209  }
4210 
4211  //check that block refers to chain tail
4212  if(!(bl.prev_id == get_tail_id()))
4213  {
4214  //chain switching or wrong block
4215  bvc.m_added_to_main_chain = false;
4216  rtxn_guard.stop();
4217  bool r = handle_alternative_block(bl, id, bvc);
4218  m_blocks_txs_check.clear();
4219  return r;
4220  //never relay alternative blocks
4221  }
4222 
4223  rtxn_guard.stop();
4224  return handle_block_to_main_chain(bl, id, bvc);
4225 }
#define CRITICAL_REGION_LOCAL1(x)
Definition: syncobj.h:230
crypto::hash get_tail_id() const
get the hash of the most recent block on the blockchain
Definition: blockchain.cpp:837
bool get_block_hash(const block &b, crypto::hash &res)
#define CRITICAL_REGION_LOCAL(x)
Definition: syncobj.h:228
#define LOG_PRINT_L3(x)
Definition: misc_log_ex.h:102
bool have_block(const crypto::hash &id) const
checks if a block is known about with a given hash
POD_CLASS hash
Definition: hash.h:50
Here is the call graph for this function:
Here is the caller graph for this function:

◆ add_txpool_tx()

void Blockchain::add_txpool_tx ( const crypto::hash txid,
const cryptonote::blobdata blob,
const txpool_tx_meta_t meta 
)

Definition at line 4768 of file blockchain.cpp.

4769 {
4770  m_db->add_txpool_tx(txid, blob, meta);
4771 }
virtual void add_txpool_tx(const crypto::hash &txid, const cryptonote::blobdata &blob, const txpool_tx_meta_t &details)=0
add a txpool transaction
Here is the call graph for this function:

◆ block_difficulty()

difficulty_type Blockchain::block_difficulty ( uint64_t  i) const

gets the difficulty of the block with a given height

Parameters
ithe height
Returns
the difficulty

Definition at line 2403 of file blockchain.cpp.

2404 {
2405  LOG_PRINT_L3("Blockchain::" << __func__);
2406  // WARNING: this function does not take m_blockchain_lock, and thus should only call read only
2407  // m_db functions which do not depend on one another (ie, no getheight + gethash(height-1), as
2408  // well as not accessing class members, even read only (ie, m_invalid_blocks). The caller must
2409  // lock if it is otherwise needed.
2410  try
2411  {
2412  return m_db->get_block_difficulty(i);
2413  }
2414  catch (const BLOCK_DNE& e)
2415  {
2416  MERROR("Attempted to get block difficulty for height above blockchain height");
2417  }
2418  return 0;
2419 }
#define MERROR(x)
Definition: misc_log_ex.h:73
thrown when a requested block does not exist
#define LOG_PRINT_L3(x)
Definition: misc_log_ex.h:102
virtual difficulty_type get_block_difficulty(const uint64_t &height) const =0
fetch a block&#39;s difficulty
Here is the call graph for this function:

◆ block_longhash_worker()

void Blockchain::block_longhash_worker ( uint64_t  height,
const epee::span< const block > &  blocks,
std::unordered_map< crypto::hash, crypto::hash > &  map 
) const

computes the "short" and "long" hashes for a set of blocks

Parameters
heightthe height of the first block
blocksthe blocks to be hashed
mapreturn-by-reference the hashes for each block

Definition at line 4313 of file blockchain.cpp.

4314 {
4315  TIME_MEASURE_START(t);
4317 
4318  for (const auto & block : blocks)
4319  {
4320  if (m_cancel)
4321  break;
4324  map.emplace(id, pow);
4325  }
4326 
4329 }
void slow_hash_allocate_state()
void slow_hash_free_state()
uint64_t height
Definition: blockchain.cpp:91
bool get_block_longhash(const block &b, crypto::hash &res, uint64_t height)
bool get_block_hash(const block &b, crypto::hash &res)
#define TIME_MEASURE_START(var_name)
Definition: profile_tools.h:61
#define TIME_MEASURE_FINISH(var_name)
Definition: profile_tools.h:64
POD_CLASS hash
Definition: hash.h:50
Here is the call graph for this function:
Here is the caller graph for this function:

◆ cancel()

void Blockchain::cancel ( )

Definition at line 4933 of file blockchain.cpp.

4934 {
4935  m_cancel = true;
4936 }
Here is the caller graph for this function:

◆ check_against_checkpoints()

void Blockchain::check_against_checkpoints ( const checkpoints points,
bool  enforce 
)

check the blockchain against a set of checkpoints

If a block fails a checkpoint and enforce is enabled, the blockchain will be rolled back to two blocks prior to that block. If enforce is disabled, as is currently the default case with DNS-based checkpoints, an error will be printed to the user but no other action will be taken.

Parameters
pointsthe checkpoints to check against
enforcewhether or not to take action on failure

Definition at line 4229 of file blockchain.cpp.

4230 {
4231  const auto& pts = points.get_points();
4232  bool stop_batch;
4233 
4234  CRITICAL_REGION_LOCAL(m_blockchain_lock);
4235  stop_batch = m_db->batch_start();
4236  const uint64_t blockchain_height = m_db->height();
4237  for (const auto& pt : pts)
4238  {
4239  // if the checkpoint is for a block we don't have yet, move on
4240  if (pt.first >= blockchain_height)
4241  {
4242  continue;
4243  }
4244 
4245  if (!points.check_block(pt.first, m_db->get_block_hash_from_height(pt.first)))
4246  {
4247  // if asked to enforce checkpoints, roll back to a couple of blocks before the checkpoint
4248  if (enforce)
4249  {
4250  LOG_ERROR("Local blockchain failed to pass a checkpoint, rolling back!");
4251  std::list<block> empty;
4252  rollback_blockchain_switching(empty, pt.first - 2);
4253 
4254  //Flush the txpool if we've just popped blocks due to failed checkpoint.
4255  std::vector<crypto::hash> txs;
4256  m_tx_pool.get_transaction_hashes(txs, true);
4257  flush_txes_from_pool(txs);
4258  }
4259  else
4260  {
4261  LOG_ERROR("WARNING: local blockchain failed to pass a ElectroneumPulse checkpoint, and you could be on a fork. You should either sync up from scratch, OR download a fresh blockchain bootstrap, OR enable checkpoint enforcing with the --enforce-dns-checkpointing command-line option");
4262  }
4263  }
4264  }
4265  if (stop_batch)
4266  m_db->batch_stop();
4267 }
virtual crypto::hash get_block_hash_from_height(const uint64_t &height) const =0
fetch a block&#39;s hash
void get_transaction_hashes(std::vector< crypto::hash > &txs, bool include_unrelayed_txes=true) const
get a list of all transaction hashes in the pool
Definition: tx_pool.cpp:923
bool check_block(uint64_t height, const crypto::hash &h, bool &is_a_checkpoint) const
checks if the given height and hash agree with the checkpoints
Definition: checkpoints.cpp:96
bool flush_txes_from_pool(const std::vector< crypto::hash > &txids)
remove transactions from the transaction pool (if present)
unsigned __int64 uint64_t
Definition: stdint.h:136
#define CRITICAL_REGION_LOCAL(x)
Definition: syncobj.h:228
virtual uint64_t height() const =0
fetch the current blockchain height
virtual void batch_stop()=0
ends a batch transaction
#define LOG_ERROR(x)
Definition: misc_log_ex.h:98
const std::map< uint64_t, crypto::hash > & get_points() const
gets the checkpoints container
virtual bool batch_start(uint64_t batch_num_blocks=0, uint64_t batch_bytes=0)=0
tells the BlockchainDB to start a new "batch" of blocks
Here is the call graph for this function:
Here is the caller graph for this function:

◆ check_blockchain_pruning()

bool Blockchain::check_blockchain_pruning ( )

Definition at line 4091 of file blockchain.cpp.

4092 {
4093  m_tx_pool.lock();
4095  CRITICAL_REGION_LOCAL(m_blockchain_lock);
4096 
4097  return m_db->check_pruning();
4098 }
auto_scope_leave_caller create_scope_leave_handler(t_scope_leave_handler f)
boost::shared_ptr< call_befor_die_base > auto_scope_leave_caller
#define CRITICAL_REGION_LOCAL(x)
Definition: syncobj.h:228
void unlock() const
unlocks the transaction pool
Definition: tx_pool.cpp:1260
virtual bool check_pruning()=0
checks pruning was done correctly, iff enabled
void lock() const
locks the transaction pool
Definition: tx_pool.cpp:1255
Here is the call graph for this function:
Here is the caller graph for this function:

◆ check_fee()

bool Blockchain::check_fee ( size_t  tx_weight,
uint64_t  fee 
) const

validate a transaction's fee

This function validates the fee is enough for the transaction. This is based on the weight of the transaction, and, after a height threshold, on the average weight of transaction in a past window

Parameters
tx_weightthe transaction weight
feethe fee
Returns
true if the fee is enough, false otherwise

Definition at line 3385 of file blockchain.cpp.

3386 {
3388  const uint64_t blockchain_height = m_db->height();
3389 
3390  uint64_t median = 0;
3391  uint64_t already_generated_coins = 0;
3392  uint64_t base_reward = 0;
3394  {
3395  median = m_current_block_cumul_weight_limit / 2;
3396  const uint64_t blockchain_height = m_db->height();
3397  already_generated_coins = blockchain_height ? m_db->get_block_already_generated_coins(blockchain_height - 1) : 0;
3398  if (!get_block_reward(median, 1, already_generated_coins, base_reward, version, blockchain_height, get_nettype()))
3399  return false;
3400  }
3401 
3402  uint64_t needed_fee;
3404  {
3405  const bool use_long_term_median_in_fee = version >= HF_VERSION_LONG_TERM_BLOCK_WEIGHT;
3406  uint64_t fee_per_byte = get_dynamic_base_fee(base_reward, use_long_term_median_in_fee ? m_long_term_effective_median_block_weight : median, version);
3407  MDEBUG("Using " << print_etn(fee_per_byte) << "/byte fee");
3408  needed_fee = tx_weight * fee_per_byte;
3409  // quantize fee up to 8 decimals
3410  const uint64_t mask = get_fee_quantization_mask();
3411  needed_fee = (needed_fee + mask - 1) / mask * mask;
3412  }
3413  else
3414  {
3415  uint64_t fee_per_kb;
3417  {
3418  if (version >= 11) {
3419  fee_per_kb = FEE_PER_KB_V11;
3420  } else if (version < 11 && version >= 6) {
3421  fee_per_kb = FEE_PER_KB_V6;
3422  } else {
3423  fee_per_kb = FEE_PER_KB;
3424  }
3425  }
3426  else
3427  {
3428  fee_per_kb = get_dynamic_base_fee(base_reward, median, version);
3429  }
3430  MDEBUG("Using " << print_etn(fee_per_kb) << "/kB fee");
3431 
3432  needed_fee = tx_weight / 1024;
3433  needed_fee += (tx_weight % 1024) ? 1 : 0;
3434  needed_fee *= fee_per_kb;
3435  }
3436 
3437  if (fee < needed_fee - needed_fee / 50) // keep a little 2% buffer on acceptance - no integer overflow
3438  {
3439  MERROR_VER("transaction fee is not enough: " << print_etn(fee) << ", minimum fee: " << print_etn(needed_fee));
3440  return false;
3441  }
3442  return true;
3443 }
#define FEE_PER_KB_V11
std::string print_etn(uint64_t amount, unsigned int decimal_point)
#define FEE_PER_KB
unsigned char uint8_t
Definition: stdint.h:124
static uint64_t get_dynamic_base_fee(uint64_t block_reward, size_t median_block_weight, uint8_t version)
get dynamic per kB or byte fee for a given block weight
#define MERROR_VER(x)
Definition: blockchain.cpp:84
#define MDEBUG(x)
Definition: misc_log_ex.h:76
uint8_t get_current_hard_fork_version() const
gets the current hardfork version in use/voted for
Definition: blockchain.h:825
#define HF_VERSION_LONG_TERM_BLOCK_WEIGHT
#define FEE_PER_KB_V6
#define HF_VERSION_DYNAMIC_FEE
static uint64_t get_fee_quantization_mask()
get fee quantization mask
unsigned __int64 uint64_t
Definition: stdint.h:136
virtual uint64_t height() const =0
fetch the current blockchain height
uint8_t version
Definition: blockchain.cpp:90
type_vec_type median(std::vector< type_vec_type > &v)
network_type get_nettype() const
get blockchain nettype
Definition: blockchain.h:1073
bool get_block_reward(size_t median_weight, size_t current_block_weight, uint64_t already_generated_coins, uint64_t &reward, uint8_t version, uint64_t current_block_height, network_type nettype)
virtual uint64_t get_block_already_generated_coins(const uint64_t &height) const =0
fetch a block&#39;s already generated coins
#define HF_VERSION_PER_BYTE_FEE
Here is the call graph for this function:
Here is the caller graph for this function:

◆ check_tx_inputs()

bool Blockchain::check_tx_inputs ( transaction tx,
uint64_t pmax_used_block_height,
crypto::hash max_used_block_id,
tx_verification_context tvc,
bool  kept_by_block = false 
)

validates a transaction's inputs

validates a transaction's inputs as correctly used and not previously spent. also returns the hash and height of the most recent block which contains an output that was used as an input to the transaction. The transaction's rct signatures, if any, are expanded.

Parameters
txthe transaction to validate
pmax_used_block_heightreturn-by-reference block height of most recent input
max_used_block_idreturn-by-reference block hash of most recent input
tvcreturned information about tx verification
kept_by_blockwhether or not the transaction is from a previously-verified block
Returns
false if any input is invalid, otherwise true

Definition at line 2869 of file blockchain.cpp.

2870 {
2871  LOG_PRINT_L3("Blockchain::" << __func__);
2872  CRITICAL_REGION_LOCAL(m_blockchain_lock);
2873 
2874 #if defined(PER_BLOCK_CHECKPOINT)
2875  // check if we're doing per-block checkpointing
2876  if (m_db->height() < m_blocks_hash_check.size() && kept_by_block)
2877  {
2878  max_used_block_id = null_hash;
2879  max_used_block_height = 0;
2880  return true;
2881  }
2882 #endif
2883 
2885  bool res = check_tx_inputs(tx, tvc, &max_used_block_height);
2887  if(m_show_time_stats)
2888  {
2889  size_t ring_size = !tx.vin.empty() && tx.vin[0].type() == typeid(txin_to_key) ? boost::get<txin_to_key>(tx.vin[0]).key_offsets.size() : 0;
2890  MINFO("HASH: " << get_transaction_hash(tx) << " I/M/O: " << tx.vin.size() << "/" << ring_size << "/" << tx.vout.size() << " H: " << max_used_block_height << " ms: " << a + m_fake_scan_time << " B: " << get_object_blobsize(tx) << " W: " << get_transaction_weight(tx));
2891  }
2892  if (!res)
2893  return false;
2894 
2895  // If kept_by_block we might witness max_used_block_height > chain height because the tx inputs are referencing outputs at a higher height on the orphaned chain.
2896  CHECK_AND_ASSERT_MES(max_used_block_height < m_db->height(), false, "internal error: max used block index=" << max_used_block_height << " is not less then blockchain size = " << m_db->height());
2897  max_used_block_id = m_db->get_block_hash_from_height(max_used_block_height);
2898  return true;
2899 }
const char * res
Definition: hmac_keccak.cpp:41
#define MINFO(x)
Definition: misc_log_ex.h:75
#define CHECK_AND_ASSERT_MES(expr, fail_ret_val, message)
Definition: misc_log_ex.h:181
virtual crypto::hash get_block_hash_from_height(const uint64_t &height) const =0
fetch a block&#39;s hash
size_t get_object_blobsize(const t_object &o)
uint64_t height
Definition: blockchain.cpp:91
uint64_t get_transaction_weight(const transaction &tx, size_t blob_size)
bool check_tx_inputs(transaction &tx, uint64_t &pmax_used_block_height, crypto::hash &max_used_block_id, tx_verification_context &tvc, bool kept_by_block=false)
validates a transaction&#39;s inputs
#define CRITICAL_REGION_LOCAL(x)
Definition: syncobj.h:228
virtual uint64_t height() const =0
fetch the current blockchain height
#define TIME_MEASURE_START(var_name)
Definition: profile_tools.h:61
#define LOG_PRINT_L3(x)
Definition: misc_log_ex.h:102
#define TIME_MEASURE_FINISH(var_name)
Definition: profile_tools.h:64
const GenericPointer< typename T::ValueType > T2 T::AllocatorType & a
Definition: pointer.h:1124
crypto::hash get_transaction_hash(const transaction &t)
Here is the call graph for this function:

◆ check_tx_outputs()

bool Blockchain::check_tx_outputs ( const transaction tx,
tx_verification_context tvc 
)

check that a transaction's outputs conform to current standards

This function checks, for example at the time of this writing, that each output is of the form a * 10^b (phrased differently, that if written out would have only one non-zero digit in base 10).

Parameters
txthe transaction to check the outputs of
tvcreturned info about tx verification
Returns
false if any outputs do not conform, otherwise true

Definition at line 2901 of file blockchain.cpp.

2902 {
2903  LOG_PRINT_L3("Blockchain::" << __func__);
2904  CRITICAL_REGION_LOCAL(m_blockchain_lock);
2905 
2906  const uint8_t hf_version = m_hardfork->get_current_version();
2907 
2908  // from hard fork 2, we forbid dust and compound outputs
2909  if (hf_version >= HF_VERSION_FORBID_DUST_OUTPUTS) {
2910  for (auto &o: tx.vout) {
2911  if (!is_valid_decomposed_amount(o.amount)) {
2912  tvc.m_invalid_output = true;
2913  return false;
2914  }
2915  }
2916  }
2917 
2918  // from v4, forbid invalid pubkeys
2919  if (hf_version >= HF_VERSION_FORBID_INVALID_PUBKEYS) {
2920  for (const auto &o: tx.vout) {
2921  if (hf_version < HF_VERSION_PUBLIC_TX) {
2922  if (o.target.type() == typeid(txout_to_key)) {
2923  const txout_to_key &out_to_key = boost::get<txout_to_key>(o.target);
2924  if (!crypto::check_key(out_to_key.key)) {
2925  tvc.m_invalid_output = true;
2926  return false;
2927  }
2928  }
2929  }
2930  else {
2931  //do a sanity check on output type before checking destination
2932  if (o.target.type() != typeid(txout_to_key_public)) {
2933  return false;
2934  }
2935  const txout_to_key_public &out_to_key_public = boost::get<txout_to_key_public>(o.target);
2936  if (!crypto::check_key(out_to_key_public.address.m_spend_public_key) ||
2937  !crypto::check_key(out_to_key_public.address.m_view_public_key)) {
2938  tvc.m_invalid_output = true;
2939  return false;
2940  }
2941 
2942  uint64_t address_prefix = get_config(m_nettype).CRYPTONOTE_PUBLIC_ADDRESS_BASE58_PREFIX;
2943  uint64_t integrated_address_prefix = get_config(m_nettype).CRYPTONOTE_PUBLIC_INTEGRATED_ADDRESS_BASE58_PREFIX;
2944  uint64_t subaddress_prefix = get_config(m_nettype).CRYPTONOTE_PUBLIC_SUBADDRESS_BASE58_PREFIX;
2945 
2946  std::vector<uint64_t> supported_prefixes{address_prefix, integrated_address_prefix, subaddress_prefix};
2947 
2948  if(std::find(supported_prefixes.begin(), supported_prefixes.end(), out_to_key_public.m_address_prefix) == supported_prefixes.end()) {
2949  tvc.m_invalid_output = true;
2950  return false;
2951  }
2952  }
2953  }
2954  }
2955  return true;
2956 }
const config_t & get_config(network_type nettype)
uint8_t get_current_version() const
returns the current version
Definition: hardfork.cpp:361
#define HF_VERSION_FORBID_INVALID_PUBKEYS
uint64_t const CRYPTONOTE_PUBLIC_ADDRESS_BASE58_PREFIX
cryptonote::account_public_address address
unsigned char uint8_t
Definition: stdint.h:124
#define HF_VERSION_FORBID_DUST_OUTPUTS
bool is_valid_decomposed_amount(uint64_t amount)
unsigned __int64 uint64_t
Definition: stdint.h:136
#define CRITICAL_REGION_LOCAL(x)
Definition: syncobj.h:228
#define LOG_PRINT_L3(x)
Definition: misc_log_ex.h:102
crypto::public_key key
uint64_t const CRYPTONOTE_PUBLIC_SUBADDRESS_BASE58_PREFIX
#define HF_VERSION_PUBLIC_TX
bool check_key(const public_key &key)
Definition: crypto.h:256
uint64_t const CRYPTONOTE_PUBLIC_INTEGRATED_ADDRESS_BASE58_PREFIX
Here is the call graph for this function:
Here is the caller graph for this function:

◆ cleanup_handle_incoming_blocks()

bool Blockchain::cleanup_handle_incoming_blocks ( bool  force_sync = false)

incoming blocks post-processing, cleanup, and disk sync

Parameters
force_syncif true, and Blockchain is handling syncing to disk, always sync
Returns
true

Definition at line 4332 of file blockchain.cpp.

4333 {
4334  bool success = false;
4335 
4336  MTRACE("Blockchain::" << __func__);
4337  CRITICAL_REGION_BEGIN(m_blockchain_lock);
4339 
4340  try
4341  {
4342  if (m_batch_success)
4343  m_db->batch_stop();
4344  else
4345  m_db->batch_abort();
4346  success = true;
4347  }
4348  catch (const std::exception &e)
4349  {
4350  MERROR("Exception in cleanup_handle_incoming_blocks: " << e.what());
4351  }
4352 
4353  if (success && m_sync_counter > 0)
4354  {
4355  if (force_sync)
4356  {
4357  if(m_db_sync_mode != db_nosync)
4358  store_blockchain();
4359  m_sync_counter = 0;
4360  }
4361  else if (m_db_sync_threshold && ((m_db_sync_on_blocks && m_sync_counter >= m_db_sync_threshold) || (!m_db_sync_on_blocks && m_bytes_to_sync >= m_db_sync_threshold)))
4362  {
4363  MDEBUG("Sync threshold met, syncing");
4364  if(m_db_sync_mode == db_async)
4365  {
4366  m_sync_counter = 0;
4367  m_bytes_to_sync = 0;
4368  m_async_service.dispatch(boost::bind(&Blockchain::store_blockchain, this));
4369  }
4370  else if(m_db_sync_mode == db_sync)
4371  {
4372  store_blockchain();
4373  }
4374  else // db_nosync
4375  {
4376  // DO NOTHING, not required to call sync.
4377  }
4378  }
4379  }
4380 
4382  m_blocks_longhash_table.clear();
4383  m_scan_table.clear();
4384  m_blocks_txs_check.clear();
4385  m_check_txin_table.clear();
4386 
4388  m_tx_pool.unlock();
4389 
4391 
4392  return success;
4393 }
#define MERROR(x)
Definition: misc_log_ex.h:73
#define MTRACE(x)
Definition: misc_log_ex.h:77
handle syncing calls instead of the backing db, asynchronously
Definition: blockchain.h:81
virtual void batch_abort()=0
aborts a batch transaction
bool store_blockchain()
stores the blockchain
Definition: blockchain.cpp:630
handle syncing calls instead of the backing db, synchronously
Definition: blockchain.h:80
#define CRITICAL_REGION_END()
Definition: syncobj.h:233
#define MDEBUG(x)
Definition: misc_log_ex.h:76
#define CRITICAL_REGION_BEGIN(x)
Definition: syncobj.h:229
Leave syncing up to the backing db (safest, but slowest because of disk I/O)
Definition: blockchain.h:82
virtual void batch_stop()=0
ends a batch transaction
#define TIME_MEASURE_START(var_name)
Definition: profile_tools.h:61
#define TIME_MEASURE_FINISH(var_name)
Definition: profile_tools.h:64
expect< void > success() noexcept
Definition: expect.h:397
void unlock() const
unlocks the transaction pool
Definition: tx_pool.cpp:1260
t1
Definition: pow22523.h:58
Here is the call graph for this function:
Here is the caller graph for this function:

◆ create_block_template() [1/2]

bool Blockchain::create_block_template ( block b,
const account_public_address miner_address,
difficulty_type di,
uint64_t height,
uint64_t expected_reward,
const blobdata ex_nonce 
)

creates a new block to mine against

Parameters
breturn-by-reference block to be filled in
from_blockoptional block hash to start mining from (main chain tip if NULL)
miner_addressaddress new coins for the block will go to
direturn-by-reference tells the miner what the difficulty target is
heightreturn-by-reference tells the miner what height it's mining against
expected_rewardreturn-by-reference the total reward awarded to the miner finding this block, including transaction fees
ex_nonceextra data to be added to the miner transaction's extra
Returns
true if block template filled in successfully, else false

Definition at line 1838 of file blockchain.cpp.

1839 {
1840  return create_block_template(b, NULL, miner_address, diffic, height, expected_reward, ex_nonce);
1841 }
uint64_t height
Definition: blockchain.cpp:91
bool create_block_template(block &b, const account_public_address &miner_address, difficulty_type &di, uint64_t &height, uint64_t &expected_reward, const blobdata &ex_nonce)
creates a new block to mine against
Here is the caller graph for this function:

◆ create_block_template() [2/2]

bool Blockchain::create_block_template ( block b,
const crypto::hash from_block,
const account_public_address miner_address,
difficulty_type di,
uint64_t height,
uint64_t expected_reward,
const blobdata ex_nonce 
)

Definition at line 1583 of file blockchain.cpp.

1584 {
1585  LOG_PRINT_L3("Blockchain::" << __func__);
1586  size_t median_weight;
1587  uint64_t already_generated_coins;
1588  //uint64_t pool_cookie;
1589 
1590  m_tx_pool.lock();
1591  const auto unlock_guard = epee::misc_utils::create_scope_leave_handler([&]() { m_tx_pool.unlock(); });
1592  CRITICAL_REGION_LOCAL(m_blockchain_lock);
1593  if (m_btc_valid && !from_block) {
1594  // The pool cookie is atomic. The lack of locking is OK, as if it changes
1595  // just as we compare it, we'll just use a slightly old template, but
1596  // this would be the case anyway if we'd lock, and the change happened
1597  // just after the block template was created
1598  if (!memcmp(&miner_address, &m_btc_address, sizeof(cryptonote::account_public_address)) && m_btc_nonce == ex_nonce
1599  && m_btc_pool_cookie == m_tx_pool.cookie() && m_btc.prev_id == get_tail_id()) {
1600  MDEBUG("Using cached template");
1601  m_btc.timestamp = time(NULL); // update timestamp unconditionally
1602  b = m_btc;
1603  diffic = m_btc_difficulty;
1604  height = m_btc_height;
1605  expected_reward = m_btc_expected_reward;
1606  return true;
1607  }
1608  MDEBUG("Not using cached template: address " << (!memcmp(&miner_address, &m_btc_address, sizeof(cryptonote::account_public_address))) << ", nonce " << (m_btc_nonce == ex_nonce) << ", cookie " << (m_btc_pool_cookie == m_tx_pool.cookie()) << ", from_block " << (!!from_block));
1609  invalidate_block_template_cache();
1610  }
1611 
1612  if (from_block)
1613  {
1614  //build alternative subchain, front -> mainchain, back -> alternative head
1615  //block is not related with head of main chain
1616  //first of all - look in alternative chains container
1617  auto it_prev = m_alternative_chains.find(*from_block);
1618  bool parent_in_main = m_db->block_exists(*from_block);
1619  if(it_prev == m_alternative_chains.end() && !parent_in_main)
1620  {
1621  MERROR("Unknown from block");
1622  return false;
1623  }
1624 
1625  //we have new block in alternative chain
1626  std::list<blocks_ext_by_hash::const_iterator> alt_chain;
1627  block_verification_context bvc = boost::value_initialized<block_verification_context>();
1628  std::vector<uint64_t> timestamps;
1629  if (!build_alt_chain(*from_block, alt_chain, timestamps, bvc))
1630  return false;
1631 
1632  if (parent_in_main)
1633  {
1634  cryptonote::block prev_block;
1635  CHECK_AND_ASSERT_MES(get_block_by_hash(*from_block, prev_block), false, "From block not found"); // TODO
1636  uint64_t from_block_height = cryptonote::get_block_height(prev_block);
1637  height = from_block_height + 1;
1638  }
1639  else
1640  {
1641  height = alt_chain.back()->second.height + 1;
1642  }
1643  b.major_version = m_hardfork->get_ideal_version(height);
1644  b.minor_version = m_hardfork->get_ideal_version();
1645  b.prev_id = *from_block;
1646 
1647  // cheat and use the weight of the block we start from, virtually certain to be acceptable
1648  // and use 1.9 times rather than 2 times so we're even more sure
1649  if (parent_in_main)
1650  {
1651  median_weight = m_db->get_block_weight(height - 1);
1652  already_generated_coins = m_db->get_block_already_generated_coins(height - 1);
1653  }
1654  else
1655  {
1656  median_weight = it_prev->second.block_cumulative_weight - it_prev->second.block_cumulative_weight / 20;
1657  already_generated_coins = alt_chain.back()->second.already_generated_coins;
1658  }
1659 
1660  // FIXME: consider moving away from block_extended_info at some point
1661  block_extended_info bei = boost::value_initialized<block_extended_info>();
1662  bei.bl = b;
1663  bei.height = alt_chain.size() ? it_prev->second.height + 1 : m_db->get_block_height(*from_block) + 1;
1664 
1665  diffic = get_next_difficulty_for_alternative_chain(alt_chain, bei);
1666  }
1667  else
1668  {
1669  height = m_db->height();
1670  b.major_version = m_hardfork->get_current_version();
1671  b.minor_version = m_hardfork->get_ideal_version();
1672  b.prev_id = get_tail_id();
1673  median_weight = m_current_block_cumul_weight_limit / 2;
1674  diffic = get_difficulty_for_next_block();
1675  already_generated_coins = m_db->get_block_already_generated_coins(height - 1);
1676  }
1677  b.timestamp = time(NULL);
1678 
1679  uint64_t median_ts;
1680  if (!check_block_timestamp(b, median_ts))
1681  {
1682  b.timestamp = median_ts;
1683  }
1684 
1685  CHECK_AND_ASSERT_MES(diffic, false, "difficulty overhead.");
1686 
1687  size_t txs_weight;
1688  uint64_t fee;
1689  if (!m_tx_pool.fill_block_template(b, median_weight, already_generated_coins, txs_weight, fee, expected_reward, b.major_version))
1690  {
1691  return false;
1692  }
1693  //pool_cookie = m_tx_pool.cookie();
1694 #if defined(DEBUG_CREATE_BLOCK_TEMPLATE)
1695  size_t real_txs_weight = 0;
1696  uint64_t real_fee = 0;
1697  for(crypto::hash &cur_hash: b.tx_hashes)
1698  {
1699  auto cur_res = m_tx_pool.m_transactions.find(cur_hash);
1700  if (cur_res == m_tx_pool.m_transactions.end())
1701  {
1702  LOG_ERROR("Creating block template: error: transaction not found");
1703  continue;
1704  }
1705  tx_memory_pool::tx_details &cur_tx = cur_res->second;
1706  real_txs_weight += cur_tx.weight;
1707  real_fee += cur_tx.fee;
1708  if (cur_tx.weight != get_transaction_weight(cur_tx.tx))
1709  {
1710  LOG_ERROR("Creating block template: error: invalid transaction weight");
1711  }
1712 
1713  uint64_t inputs_amount;
1714  if (!get_inputs_etn_amount(cur_tx.tx, inputs_amount))
1715  {
1716  LOG_ERROR("Creating block template: error: cannot get inputs amount");
1717  }
1718  else if (cur_tx.fee != inputs_amount - get_outs_etn_amount(cur_tx.tx))
1719  {
1720  LOG_ERROR("Creating block template: error: invalid fee");
1721  }
1722  }
1723  if (txs_weight != real_txs_weight)
1724  {
1725  LOG_ERROR("Creating block template: error: wrongly calculated transaction weight");
1726  }
1727  if (fee != real_fee)
1728  {
1729  LOG_ERROR("Creating block template: error: wrongly calculated fee");
1730  }
1731  MDEBUG("Creating block template: height " << height <<
1732  ", median weight " << median_weight <<
1733  ", already generated coins " << already_generated_coins <<
1734  ", transaction weight " << txs_weight <<
1735  ", fee " << fee);
1736 #endif
1737 
1738  /*
1739  two-phase miner transaction generation: we don't know exact block weight until we prepare block, but we don't know reward until we know
1740  block weight, so first miner transaction generated with fake amount of etn, and with phase we know think we know expected block weight
1741  */
1742  //make blocks coin-base tx looks close to real coinbase tx to get truthful blob weight
1743  uint8_t hf_version = b.major_version;
1744  size_t max_outs = hf_version >= 4 ? 1 : 11;
1745  bool r = construct_miner_tx(height, median_weight, already_generated_coins, txs_weight, fee, miner_address, b.miner_tx, ex_nonce, max_outs, hf_version, m_nettype);
1746  CHECK_AND_ASSERT_MES(r, false, "Failed to construct miner tx, first chance");
1747  size_t cumulative_weight = txs_weight + get_transaction_weight(b.miner_tx);
1748 #if defined(DEBUG_CREATE_BLOCK_TEMPLATE)
1749  MDEBUG("Creating block template: miner tx weight " << get_transaction_weight(b.miner_tx) <<
1750  ", cumulative weight " << cumulative_weight);
1751 #endif
1752  for (size_t try_count = 0; try_count != 10; ++try_count)
1753  {
1754  r = construct_miner_tx(height, median_weight, already_generated_coins, cumulative_weight, fee, miner_address, b.miner_tx, ex_nonce, max_outs, hf_version, m_nettype);
1755 
1756  CHECK_AND_ASSERT_MES(r, false, "Failed to construct miner tx, second chance");
1757  size_t coinbase_weight = get_transaction_weight(b.miner_tx);
1758  if (coinbase_weight > cumulative_weight - txs_weight)
1759  {
1760  cumulative_weight = txs_weight + coinbase_weight;
1761 #if defined(DEBUG_CREATE_BLOCK_TEMPLATE)
1762  MDEBUG("Creating block template: miner tx weight " << coinbase_weight <<
1763  ", cumulative weight " << cumulative_weight << " is greater than before");
1764 #endif
1765  continue;
1766  }
1767 
1768  if (coinbase_weight < cumulative_weight - txs_weight)
1769  {
1770  size_t delta = cumulative_weight - txs_weight - coinbase_weight;
1771 #if defined(DEBUG_CREATE_BLOCK_TEMPLATE)
1772  MDEBUG("Creating block template: miner tx weight " << coinbase_weight <<
1773  ", cumulative weight " << txs_weight + coinbase_weight <<
1774  " is less than before, adding " << delta << " zero bytes");
1775 #endif
1776  b.miner_tx.extra.insert(b.miner_tx.extra.end(), delta, 0);
1777  //here could be 1 byte difference, because of extra field counter is varint, and it can become from 1-byte len to 2-bytes len.
1778  if (cumulative_weight != txs_weight + get_transaction_weight(b.miner_tx))
1779  {
1780  CHECK_AND_ASSERT_MES(cumulative_weight + 1 == txs_weight + get_transaction_weight(b.miner_tx), false, "unexpected case: cumulative_weight=" << cumulative_weight << " + 1 is not equal txs_cumulative_weight=" << txs_weight << " + get_transaction_weight(b.miner_tx)=" << get_transaction_weight(b.miner_tx));
1781  b.miner_tx.extra.resize(b.miner_tx.extra.size() - 1);
1782  if (cumulative_weight != txs_weight + get_transaction_weight(b.miner_tx))
1783  {
1784  //fuck, not lucky, -1 makes varint-counter size smaller, in that case we continue to grow with cumulative_weight
1785  MDEBUG("Miner tx creation has no luck with delta_extra size = " << delta << " and " << delta - 1);
1786  cumulative_weight += delta - 1;
1787  continue;
1788  }
1789  MDEBUG("Setting extra for block: " << b.miner_tx.extra.size() << ", try_count=" << try_count);
1790  }
1791  }
1792  CHECK_AND_ASSERT_MES(cumulative_weight == txs_weight + get_transaction_weight(b.miner_tx), false, "unexpected case: cumulative_weight=" << cumulative_weight << " is not equal txs_cumulative_weight=" << txs_weight << " + get_transaction_weight(b.miner_tx)=" << get_transaction_weight(b.miner_tx));
1793 #if defined(DEBUG_CREATE_BLOCK_TEMPLATE)
1794  MDEBUG("Creating block template: miner tx weight " << coinbase_weight <<
1795  ", cumulative weight " << cumulative_weight << " is now good");
1796 #endif
1797 
1798  //if (!from_block)
1799  // cache_block_template(b, miner_address, ex_nonce, diffic, height, expected_reward, pool_cookie);
1800 
1801  if(!m_fallback_to_pow && hf_version >= 8) {
1802  sign_block(b, m_validator_key);
1803  }
1804 
1805  return true;
1806  }
1807  LOG_ERROR("Failed to create_block_template with " << 10 << " tries");
1808  return false;
1809 }
#define MERROR(x)
Definition: misc_log_ex.h:73
uint64_t cookie() const
return the cookie
Definition: tx_pool.h:381
std::vector< crypto::hash > tx_hashes
uint8_t get_current_version() const
returns the current version
Definition: hardfork.cpp:361
uint64_t get_outs_etn_amount(const transaction &tx)
auto_scope_leave_caller create_scope_leave_handler(t_scope_leave_handler f)
#define CHECK_AND_ASSERT_MES(expr, fail_ret_val, message)
Definition: misc_log_ex.h:181
uint64_t height
Definition: blockchain.cpp:91
virtual uint64_t get_block_height(const crypto::hash &h) const =0
gets the height of the block with a given hash
transaction tx
the transaction
Definition: tx_pool.h:405
unsigned char uint8_t
Definition: stdint.h:124
uint64_t get_transaction_weight(const transaction &tx, size_t blob_size)
std::vector< uint8_t > extra
#define MDEBUG(x)
Definition: misc_log_ex.h:76
virtual size_t get_block_weight(const uint64_t &height) const =0
fetch a block&#39;s weight
time_t time
Definition: blockchain.cpp:93
crypto::hash get_tail_id() const
get the hash of the most recent block on the blockchain
Definition: blockchain.cpp:837
void sign_block(block &b, std::string privateKey)
Digitally sign the block.
unsigned __int64 uint64_t
Definition: stdint.h:136
#define CRITICAL_REGION_LOCAL(x)
Definition: syncobj.h:228
difficulty_type get_difficulty_for_next_block()
returns the difficulty target the next block to be added must meet
Definition: blockchain.cpp:971
virtual uint64_t height() const =0
fetch the current blockchain height
virtual bool block_exists(const crypto::hash &h, uint64_t *height=NULL) const =0
checks if a block exists
uint64_t fee
the transaction&#39;s fee amount
Definition: tx_pool.h:408
#define LOG_PRINT_L3(x)
Definition: misc_log_ex.h:102
size_t weight
the transaction&#39;s weight
Definition: tx_pool.h:407
uint8_t get_ideal_version() const
returns the latest "ideal" version
Definition: hardfork.cpp:367
void unlock() const
unlocks the transaction pool
Definition: tx_pool.cpp:1260
#define LOG_ERROR(x)
Definition: misc_log_ex.h:98
information about a single transaction
Definition: tx_pool.h:403
bool fill_block_template(block &bl, size_t median_weight, uint64_t already_generated_coins, size_t &total_weight, uint64_t &fee, uint64_t &expected_reward, uint8_t version)
Chooses transactions for a block to include.
Definition: tx_pool.cpp:1535
bool get_inputs_etn_amount(const transaction &tx, uint64_t &etn)
POD_CLASS hash
Definition: hash.h:50
bool get_block_by_hash(const crypto::hash &h, block &blk, bool *orphan=NULL) const
gets the block with a given hash
Definition: blockchain.cpp:928
bool construct_miner_tx(size_t height, size_t median_weight, uint64_t already_generated_coins, size_t current_block_weight, uint64_t fee, const account_public_address &miner_address, transaction &tx, const blobdata &extra_nonce, size_t max_outs, uint8_t hard_fork_version, network_type nettype)
virtual uint64_t get_block_already_generated_coins(const uint64_t &height) const =0
fetch a block&#39;s already generated coins
void lock() const
locks the transaction pool
Definition: tx_pool.cpp:1255
uint64_t get_block_height(const block &b)
Here is the call graph for this function:

◆ deinit()

bool Blockchain::deinit ( )

Uninitializes the blockchain state.

Saves to disk any state that needs to be maintained

Returns
true on success, false if any uninitialization steps fail

Definition at line 660 of file blockchain.cpp.

661 {
662  LOG_PRINT_L3("Blockchain::" << __func__);
663 
664  MTRACE("Stopping blockchain read/write activity");
665 
666  // stop async service
667  m_async_work_idle.reset();
668  m_async_pool.join_all();
669  m_async_service.stop();
670 
671  // as this should be called if handling a SIGSEGV, need to check
672  // if m_db is a NULL pointer (and thus may have caused the illegal
673  // memory operation), otherwise we may cause a loop.
674  try
675  {
676  if (m_db)
677  {
678  m_db->close();
679  MTRACE("Local blockchain read/write activity stopped successfully");
680  }
681  }
682  catch (const std::exception& e)
683  {
684  LOG_ERROR(std::string("Error closing blockchain db: ") + e.what());
685  }
686  catch (...)
687  {
688  LOG_ERROR("There was an issue closing/storing the blockchain, shutting down now to prevent issues!");
689  }
690 
691  delete m_hardfork;
692  m_hardfork = NULL;
693  delete m_db;
694  m_db = NULL;
695  return true;
696 }
#define MTRACE(x)
Definition: misc_log_ex.h:77
::std::string string
Definition: gtest-port.h:1097
virtual void close()=0
close the BlockchainDB
#define LOG_PRINT_L3(x)
Definition: misc_log_ex.h:102
#define LOG_ERROR(x)
Definition: misc_log_ex.h:98
Here is the call graph for this function:
Here is the caller graph for this function:

◆ find_blockchain_supplement() [1/4]

bool Blockchain::find_blockchain_supplement ( const std::list< crypto::hash > &  qblock_ids,
std::vector< crypto::hash > &  hashes,
uint64_t start_height,
uint64_t current_height,
bool  clip_pruned 
) const

get recent block hashes for a foreign chain

Find the split point between us and foreign blockchain and return (by reference) the most recent common block hash along with up to BLOCKS_IDS_SYNCHRONIZING_DEFAULT_COUNT additional (more recent) hashes.

Parameters
qblock_idsthe foreign chain's "short history" (see get_short_chain_history)
hashesthe hashes to be returned, return-by-reference
start_heightthe start height, return-by-reference
current_heightthe current blockchain height, return-by-reference
clip_prunedwhether to constrain results to unpruned data
Returns
true if a block found in common, else false

Definition at line 2568 of file blockchain.cpp.

2569 {
2570  LOG_PRINT_L3("Blockchain::" << __func__);
2571  CRITICAL_REGION_LOCAL(m_blockchain_lock);
2572 
2573  // if we can't find the split point, return false
2574  if(!find_blockchain_supplement(qblock_ids, start_height))
2575  {
2576  return false;
2577  }
2578 
2579  db_rtxn_guard rtxn_guard(m_db);
2580  current_height = get_current_blockchain_height();
2581  uint64_t stop_height = current_height;
2582  if (clip_pruned)
2583  {
2584  const uint32_t pruning_seed = get_blockchain_pruning_seed();
2585  start_height = tools::get_next_unpruned_block_height(start_height, current_height, pruning_seed);
2586  stop_height = tools::get_next_pruned_block_height(start_height, current_height, pruning_seed);
2587  }
2588  size_t count = 0;
2589  hashes.reserve(std::min((size_t)(stop_height - start_height), (size_t)BLOCKS_IDS_SYNCHRONIZING_DEFAULT_COUNT));
2590  for(size_t i = start_height; i < stop_height && count < BLOCKS_IDS_SYNCHRONIZING_DEFAULT_COUNT; i++, count++)
2591  {
2592  hashes.push_back(m_db->get_block_hash_from_height(i));
2593  }
2594 
2595  return true;
2596 }
virtual crypto::hash get_block_hash_from_height(const uint64_t &height) const =0
fetch a block&#39;s hash
bool find_blockchain_supplement(const std::list< crypto::hash > &qblock_ids, std::vector< crypto::hash > &hashes, uint64_t &start_height, uint64_t &current_height, bool clip_pruned) const
get recent block hashes for a foreign chain
#define BLOCKS_IDS_SYNCHRONIZING_DEFAULT_COUNT
uint64_t get_next_pruned_block_height(uint64_t block_height, uint64_t blockchain_height, uint32_t pruning_seed)
Definition: pruning.cpp:93
uint64_t get_current_blockchain_height() const
get the current height of the blockchain
Definition: blockchain.cpp:322
struct hash_func hashes[]
mdb_size_t count(MDB_cursor *cur)
unsigned int uint32_t
Definition: stdint.h:126
uint64_t get_next_unpruned_block_height(uint64_t block_height, uint64_t blockchain_height, uint32_t pruning_seed)
Definition: pruning.cpp:69
unsigned __int64 uint64_t
Definition: stdint.h:136
#define CRITICAL_REGION_LOCAL(x)
Definition: syncobj.h:228
#define LOG_PRINT_L3(x)
Definition: misc_log_ex.h:102
uint32_t get_blockchain_pruning_seed() const
Definition: blockchain.h:1017
Here is the call graph for this function:
Here is the caller graph for this function:

◆ find_blockchain_supplement() [2/4]

bool Blockchain::find_blockchain_supplement ( const std::list< crypto::hash > &  qblock_ids,
NOTIFY_RESPONSE_CHAIN_ENTRY::request resp 
) const

get recent block hashes for a foreign chain

Find the split point between us and foreign blockchain and return (by reference) the most recent common block hash along with up to BLOCKS_IDS_SYNCHRONIZING_DEFAULT_COUNT additional (more recent) hashes.

Parameters
qblock_idsthe foreign chain's "short history" (see get_short_chain_history)
respreturn-by-reference the split height and subsequent blocks' hashes
Returns
true if a block found in common, else false

Definition at line 2598 of file blockchain.cpp.

2599 {
2600  LOG_PRINT_L3("Blockchain::" << __func__);
2601  CRITICAL_REGION_LOCAL(m_blockchain_lock);
2602 
2603  bool result = find_blockchain_supplement(qblock_ids, resp.m_block_ids, resp.start_height, resp.total_height, true);
2604  if (result)
2605  {
2606  cryptonote::difficulty_type wide_cumulative_difficulty = m_db->get_block_cumulative_difficulty(resp.total_height - 1);
2607  resp.cumulative_difficulty = (wide_cumulative_difficulty & 0xffffffffffffffff).convert_to<uint64_t>();
2608  resp.cumulative_difficulty_top64 = ((wide_cumulative_difficulty >> 64) & 0xffffffffffffffff).convert_to<uint64_t>();
2609  }
2610 
2611  return result;
2612 }
bool find_blockchain_supplement(const std::list< crypto::hash > &qblock_ids, std::vector< crypto::hash > &hashes, uint64_t &start_height, uint64_t &current_height, bool clip_pruned) const
get recent block hashes for a foreign chain
virtual difficulty_type get_block_cumulative_difficulty(const uint64_t &height) const =0
fetch a block&#39;s cumulative difficulty
unsigned __int64 uint64_t
Definition: stdint.h:136
#define CRITICAL_REGION_LOCAL(x)
Definition: syncobj.h:228
#define LOG_PRINT_L3(x)
Definition: misc_log_ex.h:102
boost::multiprecision::uint128_t difficulty_type
Definition: difficulty.h:43
Here is the call graph for this function:

◆ find_blockchain_supplement() [3/4]

bool Blockchain::find_blockchain_supplement ( const std::list< crypto::hash > &  qblock_ids,
uint64_t starter_offset 
) const

find the most recent common point between ours and a foreign chain

This function takes a list of block hashes from another node on the network to find where the split point is between us and them. This is used to see what to send another node that needs to sync.

Parameters
qblock_idsthe foreign chain's "short history" (see get_short_chain_history)
starter_offsetreturn-by-reference the most recent common block's height
Returns
true if a block found in common, else false

Definition at line 2348 of file blockchain.cpp.

2349 {
2350  LOG_PRINT_L3("Blockchain::" << __func__);
2351  CRITICAL_REGION_LOCAL(m_blockchain_lock);
2352 
2353  // make sure the request includes at least the genesis block, otherwise
2354  // how can we expect to sync from the client that the block list came from?
2355  if(qblock_ids.empty())
2356  {
2357  MCERROR("net.p2p", "Client sent wrong NOTIFY_REQUEST_CHAIN: m_block_ids.size()=" << qblock_ids.size() << ", dropping connection");
2358  return false;
2359  }
2360 
2361  db_rtxn_guard rtxn_guard(m_db);
2362  // make sure that the last block in the request's block list matches
2363  // the genesis block
2364  auto gen_hash = m_db->get_block_hash_from_height(0);
2365  if(qblock_ids.back() != gen_hash)
2366  {
2367  LOG_PRINT_L0("Genesis Block Mismatch");
2368  MCERROR("net.p2p", "Client sent wrong NOTIFY_REQUEST_CHAIN: genesis block mismatch: " << std::endl << "id: " << qblock_ids.back() << ", " << std::endl << "expected: " << gen_hash << "," << std::endl << " dropping connection");
2369  return false;
2370  }
2371 
2372  // Find the first block the foreign chain has that we also have.
2373  // Assume qblock_ids is in reverse-chronological order.
2374  auto bl_it = qblock_ids.begin();
2375  uint64_t split_height = 0;
2376  for(; bl_it != qblock_ids.end(); bl_it++)
2377  {
2378  try
2379  {
2380  if (m_db->block_exists(*bl_it, &split_height))
2381  break;
2382  }
2383  catch (const std::exception& e)
2384  {
2385  MWARNING("Non-critical error trying to find block by hash in BlockchainDB, hash: " << *bl_it);
2386  return false;
2387  }
2388  }
2389 
2390  // this should be impossible, as we checked that we share the genesis block,
2391  // but just in case...
2392  if(bl_it == qblock_ids.end())
2393  {
2394  MERROR("Internal error handling connection, can't find split point");
2395  return false;
2396  }
2397 
2398  //we start to put block ids INCLUDING last known id, just to make other side be sure
2399  starter_offset = split_height;
2400  return true;
2401 }
#define MERROR(x)
Definition: misc_log_ex.h:73
virtual crypto::hash get_block_hash_from_height(const uint64_t &height) const =0
fetch a block&#39;s hash
#define LOG_PRINT_L0(x)
Definition: misc_log_ex.h:99
#define MCERROR(cat, x)
Definition: misc_log_ex.h:51
unsigned __int64 uint64_t
Definition: stdint.h:136
#define CRITICAL_REGION_LOCAL(x)
Definition: syncobj.h:228
virtual bool block_exists(const crypto::hash &h, uint64_t *height=NULL) const =0
checks if a block exists
#define LOG_PRINT_L3(x)
Definition: misc_log_ex.h:102
#define MWARNING(x)
Definition: misc_log_ex.h:74
Here is the call graph for this function:

◆ find_blockchain_supplement() [4/4]

bool Blockchain::find_blockchain_supplement ( const uint64_t  req_start_block,
const std::list< crypto::hash > &  qblock_ids,
std::vector< std::pair< std::pair< cryptonote::blobdata, crypto::hash >, std::vector< std::pair< crypto::hash, cryptonote::blobdata > > > > &  blocks,
uint64_t total_height,
uint64_t start_height,
bool  pruned,
bool  get_miner_tx_hash,
size_t  max_count 
) const

get recent blocks for a foreign chain

This function gets recent blocks relative to a foreign chain, starting either at a requested height or whatever height is the most recent ours and the foreign chain have in common.

Parameters
req_start_blockif non-zero, specifies a start point (otherwise find most recent commonality)
qblock_idsthe foreign chain's "short history" (see get_short_chain_history)
blocksreturn-by-reference the blocks and their transactions
total_heightreturn-by-reference our current blockchain height
start_heightreturn-by-reference the height of the first block returned
prunedwhether to return full or pruned tx blobs
max_countthe max number of blocks to get
Returns
true if a block found in common or req_start_block specified, else false

Definition at line 2618 of file blockchain.cpp.

2619 {
2620  LOG_PRINT_L3("Blockchain::" << __func__);
2621  CRITICAL_REGION_LOCAL(m_blockchain_lock);
2622 
2623  // if a specific start height has been requested
2624  if(req_start_block > 0)
2625  {
2626  // if requested height is higher than our chain, return false -- we can't help
2627  if (req_start_block >= m_db->height())
2628  {
2629  return false;
2630  }
2631  start_height = req_start_block;
2632  }
2633  else
2634  {
2635  if(!find_blockchain_supplement(qblock_ids, start_height))
2636  {
2637  return false;
2638  }
2639  }
2640 
2641  db_rtxn_guard rtxn_guard(m_db);
2642  total_height = get_current_blockchain_height();
2643  size_t count = 0, size = 0;
2644  blocks.reserve(std::min(std::min(max_count, (size_t)10000), (size_t)(total_height - start_height)));
2645  for(uint64_t i = start_height; i < total_height && count < max_count && (size < FIND_BLOCKCHAIN_SUPPLEMENT_MAX_SIZE || count < 3); i++, count++)
2646  {
2647  blocks.resize(blocks.size()+1);
2648  blocks.back().first.first = m_db->get_block_blob_from_height(i);
2649  block b;
2650  CHECK_AND_ASSERT_MES(parse_and_validate_block_from_blob(blocks.back().first.first, b), false, "internal error, invalid block");
2651  blocks.back().first.second = get_miner_tx_hash ? cryptonote::get_transaction_hash(b.miner_tx) : crypto::null_hash;
2652  std::vector<crypto::hash> mis;
2653  std::vector<cryptonote::blobdata> txs;
2654  get_transactions_blobs(b.tx_hashes, txs, mis, pruned);
2655  CHECK_AND_ASSERT_MES(!mis.size(), false, "internal error, transaction from block not found");
2656  size += blocks.back().first.first.size();
2657  for (const auto &t: txs)
2658  size += t.size();
2659 
2660  CHECK_AND_ASSERT_MES(txs.size() == b.tx_hashes.size(), false, "mismatched sizes of b.tx_hashes and txs");
2661  blocks.back().second.reserve(txs.size());
2662  for (size_t i = 0; i < txs.size(); ++i)
2663  {
2664  blocks.back().second.push_back(std::make_pair(b.tx_hashes[i], std::move(txs[i])));
2665  }
2666  }
2667  return true;
2668 }
std::vector< crypto::hash > tx_hashes
virtual cryptonote::blobdata get_block_blob_from_height(const uint64_t &height) const =0
fetch a block blob by height
#define CHECK_AND_ASSERT_MES(expr, fail_ret_val, message)
Definition: misc_log_ex.h:181
bool find_blockchain_supplement(const std::list< crypto::hash > &qblock_ids, std::vector< crypto::hash > &hashes, uint64_t &start_height, uint64_t &current_height, bool clip_pruned) const
get recent block hashes for a foreign chain
crypto namespace.
Definition: crypto.cpp:58
uint64_t get_current_blockchain_height() const
get the current height of the blockchain
Definition: blockchain.cpp:322
#define FIND_BLOCKCHAIN_SUPPLEMENT_MAX_SIZE
Definition: blockchain.cpp:65
mdb_size_t count(MDB_cursor *cur)
unsigned __int64 uint64_t
Definition: stdint.h:136
#define CRITICAL_REGION_LOCAL(x)
Definition: syncobj.h:228
virtual uint64_t height() const =0
fetch the current blockchain height
#define LOG_PRINT_L3(x)
Definition: misc_log_ex.h:102
bool get_transactions_blobs(const t_ids_container &txs_ids, t_tx_container &txs, t_missed_container &missed_txs, bool pruned=false) const
gets transactions based on a list of transaction hashes
const T & move(const T &t)
Definition: gtest-port.h:1317
crypto::hash get_transaction_hash(const transaction &t)
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:

◆ flush_txes_from_pool()

bool Blockchain::flush_txes_from_pool ( const std::vector< crypto::hash > &  txids)

remove transactions from the transaction pool (if present)

Parameters
txidsa list of hashes of transactions to be removed
Returns
false if any removals fail, otherwise true

Definition at line 3657 of file blockchain.cpp.

3658 {
3659  CRITICAL_REGION_LOCAL(m_tx_pool);
3660 
3661  bool res = true;
3662  for (const auto &txid: txids)
3663  {
3665  cryptonote::blobdata txblob;
3666  size_t tx_weight;
3667  uint64_t fee;
3668  bool relayed, do_not_relay, double_spend_seen, nonexistent_utxo_seen;
3669  MINFO("Removing txid " << txid << " from the pool");
3670  if(m_tx_pool.have_tx(txid) && !m_tx_pool.take_tx(txid, tx, txblob, tx_weight, fee, relayed, do_not_relay, double_spend_seen, nonexistent_utxo_seen))
3671  {
3672  MERROR("Failed to remove txid " << txid << " from the pool");
3673  res = false;
3674  }
3675  }
3676  return res;
3677 }
const char * res
Definition: hmac_keccak.cpp:41
#define MERROR(x)
Definition: misc_log_ex.h:73
#define MINFO(x)
Definition: misc_log_ex.h:75
bool take_tx(const crypto::hash &id, transaction &tx, cryptonote::blobdata &txblob, size_t &tx_weight, uint64_t &fee, bool &relayed, bool &do_not_relay, bool &double_spend_seen, bool &nonexistent_utxo_seen)
takes a transaction with the given hash from the pool
Definition: tx_pool.cpp:702
unsigned __int64 uint64_t
Definition: stdint.h:136
#define CRITICAL_REGION_LOCAL(x)
Definition: syncobj.h:228
std::string blobdata
Definition: blobdatatype.h:39
bool have_tx(const crypto::hash &id) const
checks if the pool has a transaction with the given hash
Definition: tx_pool.cpp:1196
Here is the call graph for this function:
Here is the caller graph for this function:

◆ for_all_key_images()

bool Blockchain::for_all_key_images ( std::function< bool(const crypto::key_image &)>  f) const

perform a check on all key images in the blockchain

Parameters
std::functionthe check to perform, pass/fail
Returns
false if any key image fails the check, otherwise true

Definition at line 5041 of file blockchain.cpp.

5042 {
5043  return m_db->for_all_key_images(f);
5044 }
virtual bool for_all_key_images(std::function< bool(const crypto::key_image &)>) const =0
runs a function over all key images stored
Here is the call graph for this function:

◆ for_all_outputs() [1/2]

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

perform a check on all outputs in the blockchain

Parameters
std::functionthe check to perform, pass/fail
Returns
false if any output fails the check, otherwise true

Definition at line 5056 of file blockchain.cpp.

5057 {
5058  return m_db->for_all_outputs(f);;
5059 }
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 =0
runs a function over all outputs stored
Here is the call graph for this function:

◆ for_all_outputs() [2/2]

bool Blockchain::for_all_outputs ( uint64_t  amount,
std::function< bool(uint64_t height)>  f 
) const

perform a check on all outputs of a given amount in the blockchain

Parameters
amountthe amount to iterate through
std::functionthe check to perform, pass/fail
Returns
false if any output fails the check, otherwise true

Definition at line 5061 of file blockchain.cpp.

5062 {
5063  return m_db->for_all_outputs(amount, f);;
5064 }
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 =0
runs a function over all outputs stored
Here is the call graph for this function:

◆ for_all_transactions()

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

perform a check on all transactions in the blockchain

Parameters
std::functionthe check to perform, pass/fail
boolpruned whether to return pruned txes only
Returns
false if any transaction fails the check, otherwise true

Definition at line 5051 of file blockchain.cpp.

5052 {
5053  return m_db->for_all_transactions(f, pruned);
5054 }
virtual bool for_all_transactions(std::function< bool(const crypto::hash &, const cryptonote::transaction &)>, bool pruned) const =0
runs a function over all transactions stored
Here is the call graph for this function:
Here is the caller graph for this function:

◆ for_all_txpool_txes()

bool Blockchain::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

Definition at line 4803 of file blockchain.cpp.

4804 {
4805  return m_db->for_all_txpool_txes(f, include_blob, include_unrelayed_txes);
4806 }
virtual bool 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 =0
runs a function over all txpool transactions
Here is the call graph for this function:
Here is the caller graph for this function:

◆ for_blocks_range()

bool Blockchain::for_blocks_range ( const uint64_t h1,
const uint64_t h2,
std::function< bool(uint64_t, const crypto::hash &, const block &)>  f 
) const

perform a check on all blocks in the blockchain in the given range

Parameters
h1the start height
h2the end height
std::functionthe check to perform, pass/fail
Returns
false if any block fails the check, otherwise true

Definition at line 5046 of file blockchain.cpp.

5047 {
5048  return m_db->for_blocks_range(h1, h2, f);
5049 }
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 =0
runs a function over a range of blocks
Here is the call graph for this function:
Here is the caller graph for this function:

◆ get_alternative_blocks()

bool Blockchain::get_alternative_blocks ( std::vector< block > &  blocks) const

compiles a list of all blocks stored as alternative chains

Parameters
blocksreturn-by-reference container to put result blocks in
Returns
true

Definition at line 2193 of file blockchain.cpp.

2194 {
2195  LOG_PRINT_L3("Blockchain::" << __func__);
2196  CRITICAL_REGION_LOCAL(m_blockchain_lock);
2197 
2198  blocks.reserve(m_alternative_chains.size());
2199  for (const auto& alt_bl: m_alternative_chains)
2200  {
2201  blocks.push_back(alt_bl.second.bl);
2202  }
2203  return true;
2204 }
#define CRITICAL_REGION_LOCAL(x)
Definition: syncobj.h:228
#define LOG_PRINT_L3(x)
Definition: misc_log_ex.h:102
Here is the caller graph for this function:

◆ get_alternative_blocks_count()

size_t Blockchain::get_alternative_blocks_count ( ) const

returns the number of alternative blocks stored

Returns
the number of alternative blocks stored

Definition at line 2206 of file blockchain.cpp.

2207 {
2208  LOG_PRINT_L3("Blockchain::" << __func__);
2209  CRITICAL_REGION_LOCAL(m_blockchain_lock);
2210  return m_alternative_chains.size();
2211 }
#define CRITICAL_REGION_LOCAL(x)
Definition: syncobj.h:228
#define LOG_PRINT_L3(x)
Definition: misc_log_ex.h:102
Here is the caller graph for this function:

◆ get_alternative_chains()

std::list< std::pair< Blockchain::block_extended_info, std::vector< crypto::hash > > > Blockchain::get_alternative_chains ( ) const

returns a set of known alternate chains

Returns
a list of chains

Definition at line 4900 of file blockchain.cpp.

4901 {
4902  std::list<std::pair<Blockchain::block_extended_info,std::vector<crypto::hash>>> chains;
4903 
4904  for (const auto &i: m_alternative_chains)
4905  {
4906  const crypto::hash &top = i.first;
4907  bool found = false;
4908  for (const auto &j: m_alternative_chains)
4909  {
4910  if (j.second.bl.prev_id == top)
4911  {
4912  found = true;
4913  break;
4914  }
4915  }
4916  if (!found)
4917  {
4918  std::vector<crypto::hash> chain;
4919  auto h = i.second.bl.prev_id;
4920  chain.push_back(top);
4921  blocks_ext_by_hash::const_iterator prev;
4922  while ((prev = m_alternative_chains.find(h)) != m_alternative_chains.end())
4923  {
4924  chain.push_back(h);
4925  h = prev->second.bl.prev_id;
4926  }
4927  chains.push_back(std::make_pair(i.second, chain));
4928  }
4929  }
4930  return chains;
4931 }
POD_CLASS hash
Definition: hash.h:50

◆ get_block_by_hash()

bool Blockchain::get_block_by_hash ( const crypto::hash h,
block blk,
bool orphan = NULL 
) const

gets the block with a given hash

Parameters
hthe hash to look for
blkreturn-by-reference variable to put result block in
orphanif non-NULL, will be set to true if not in the main chain, false otherwise
Returns
true if the block was found, else false

Definition at line 928 of file blockchain.cpp.

929 {
930  LOG_PRINT_L3("Blockchain::" << __func__);
931  CRITICAL_REGION_LOCAL(m_blockchain_lock);
932 
933  // try to find block in main chain
934  try
935  {
936  blk = m_db->get_block(h);
937  if (orphan)
938  *orphan = false;
939  return true;
940  }
941  // try to find block in alternative chain
942  catch (const BLOCK_DNE& e)
943  {
944  blocks_ext_by_hash::const_iterator it_alt = m_alternative_chains.find(h);
945  if (m_alternative_chains.end() != it_alt)
946  {
947  blk = it_alt->second.bl;
948  if (orphan)
949  *orphan = true;
950  return true;
951  }
952  }
953  catch (const std::exception& e)
954  {
955  MERROR(std::string("Something went wrong fetching block by hash: ") + e.what());
956  throw;
957  }
958  catch (...)
959  {
960  MERROR(std::string("Something went wrong fetching block hash by hash"));
961  throw;
962  }
963 
964  return false;
965 }
#define MERROR(x)
Definition: misc_log_ex.h:73
::std::string string
Definition: gtest-port.h:1097
#define CRITICAL_REGION_LOCAL(x)
Definition: syncobj.h:228
thrown when a requested block does not exist
#define LOG_PRINT_L3(x)
Definition: misc_log_ex.h:102
virtual block get_block(const crypto::hash &h) const
fetches the block with the given hash
Here is the call graph for this function:
Here is the caller graph for this function:

◆ get_block_id_by_height()

crypto::hash Blockchain::get_block_id_by_height ( uint64_t  height) const

gets a block's hash given a height

Parameters
heightthe height of the block
Returns
the hash of the block at the requested height, or a zeroed hash if there is no such block

Definition at line 901 of file blockchain.cpp.

902 {
903  LOG_PRINT_L3("Blockchain::" << __func__);
904  // WARNING: this function does not take m_blockchain_lock, and thus should only call read only
905  // m_db functions which do not depend on one another (ie, no getheight + gethash(height-1), as
906  // well as not accessing class members, even read only (ie, m_invalid_blocks). The caller must
907  // lock if it is otherwise needed.
908  try
909  {
910  return m_db->get_block_hash_from_height(height);
911  }
912  catch (const BLOCK_DNE& e)
913  {
914  }
915  catch (const std::exception& e)
916  {
917  MERROR(std::string("Something went wrong fetching block hash by height: ") + e.what());
918  throw;
919  }
920  catch (...)
921  {
922  MERROR(std::string("Something went wrong fetching block hash by height"));
923  throw;
924  }
925  return null_hash;
926 }
#define MERROR(x)
Definition: misc_log_ex.h:73
::std::string string
Definition: gtest-port.h:1097
virtual crypto::hash get_block_hash_from_height(const uint64_t &height) const =0
fetch a block&#39;s hash
uint64_t height
Definition: blockchain.cpp:91
thrown when a requested block does not exist
#define LOG_PRINT_L3(x)
Definition: misc_log_ex.h:102
Here is the call graph for this function:
Here is the caller graph for this function:

◆ get_blockchain_pruning_seed()

uint32_t cryptonote::Blockchain::get_blockchain_pruning_seed ( ) const
inline

Definition at line 1017 of file blockchain.h.

1017 { return m_db->get_blockchain_pruning_seed(); }
virtual uint32_t get_blockchain_pruning_seed() const =0
get the blockchain pruning seed
Here is the call graph for this function:
Here is the caller graph for this function:

◆ get_blocks() [1/3]

bool Blockchain::get_blocks ( uint64_t  start_offset,
size_t  count,
std::vector< std::pair< cryptonote::blobdata, block >> &  blocks,
std::vector< cryptonote::blobdata > &  txs 
) const

get blocks and transactions from blocks based on start height and count

Parameters
start_offsetthe height on the blockchain to start at
countthe number of blocks to get, if there are as many after start_offset
blocksreturn-by-reference container to put result blocks in
txsreturn-by-reference container to put result transactions in
Returns
false if start_offset > blockchain height, else true

Definition at line 2096 of file blockchain.cpp.

2097 {
2098  LOG_PRINT_L3("Blockchain::" << __func__);
2099  CRITICAL_REGION_LOCAL(m_blockchain_lock);
2100  if(start_offset >= m_db->height())
2101  return false;
2102 
2103  if (!get_blocks(start_offset, count, blocks))
2104  {
2105  return false;
2106  }
2107 
2108  for(const auto& blk : blocks)
2109  {
2110  std::vector<crypto::hash> missed_ids;
2111  get_transactions_blobs(blk.second.tx_hashes, txs, missed_ids);
2112  CHECK_AND_ASSERT_MES(!missed_ids.size(), false, "has missed transactions in own block in main blockchain");
2113  }
2114 
2115  return true;
2116 }
bool get_blocks(uint64_t start_offset, size_t count, std::vector< std::pair< cryptonote::blobdata, block >> &blocks, std::vector< cryptonote::blobdata > &txs) const
get blocks and transactions from blocks based on start height and count
#define CHECK_AND_ASSERT_MES(expr, fail_ret_val, message)
Definition: misc_log_ex.h:181
mdb_size_t count(MDB_cursor *cur)
#define CRITICAL_REGION_LOCAL(x)
Definition: syncobj.h:228
virtual uint64_t height() const =0
fetch the current blockchain height
#define LOG_PRINT_L3(x)
Definition: misc_log_ex.h:102
bool get_transactions_blobs(const t_ids_container &txs_ids, t_tx_container &txs, t_missed_container &missed_txs, bool pruned=false) const
gets transactions based on a list of transaction hashes
Here is the call graph for this function:
Here is the caller graph for this function:

◆ get_blocks() [2/3]

bool Blockchain::get_blocks ( uint64_t  start_offset,
size_t  count,
std::vector< std::pair< cryptonote::blobdata, block >> &  blocks 
) const

get blocks from blocks based on start height and count

Parameters
start_offsetthe height on the blockchain to start at
countthe number of blocks to get, if there are as many after start_offset
blocksreturn-by-reference container to put result blocks in
Returns
false if start_offset > blockchain height, else true

Definition at line 2118 of file blockchain.cpp.

2119 {
2120  LOG_PRINT_L3("Blockchain::" << __func__);
2121  CRITICAL_REGION_LOCAL(m_blockchain_lock);
2122  const uint64_t height = m_db->height();
2123  if(start_offset >= height)
2124  return false;
2125 
2126  blocks.reserve(blocks.size() + height - start_offset);
2127  for(size_t i = start_offset; i < start_offset + count && i < height;i++)
2128  {
2129  blocks.push_back(std::make_pair(m_db->get_block_blob_from_height(i), block()));
2130  if (!parse_and_validate_block_from_blob(blocks.back().first, blocks.back().second))
2131  {
2132  LOG_ERROR("Invalid block");
2133  return false;
2134  }
2135  }
2136  return true;
2137 }
virtual cryptonote::blobdata get_block_blob_from_height(const uint64_t &height) const =0
fetch a block blob by height
uint64_t height
Definition: blockchain.cpp:91
mdb_size_t count(MDB_cursor *cur)
unsigned __int64 uint64_t
Definition: stdint.h:136
#define CRITICAL_REGION_LOCAL(x)
Definition: syncobj.h:228
virtual uint64_t height() const =0
fetch the current blockchain height
#define LOG_PRINT_L3(x)
Definition: misc_log_ex.h:102
#define LOG_ERROR(x)
Definition: misc_log_ex.h:98
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_blocks() [3/3]

template<class t_ids_container , class t_blocks_container , class t_missed_container >
bool Blockchain::get_blocks ( const t_ids_container &  block_ids,
t_blocks_container &  blocks,
t_missed_container &  missed_bs 
) const

gets blocks based on a list of block hashes

Template Parameters
t_ids_containera standard-iterable container
t_blocks_containera standard-iterable container
t_missed_containera standard-iterable container
Parameters
block_idsa container of block hashes for which to get the corresponding blocks
blocksreturn-by-reference a container to store result blocks in
missed_bsreturn-by-reference a container to store missed blocks in
Returns
false if an unexpected exception occurs, else true

Definition at line 2427 of file blockchain.cpp.

2428 {
2429  LOG_PRINT_L3("Blockchain::" << __func__);
2430  CRITICAL_REGION_LOCAL(m_blockchain_lock);
2431 
2432  reserve_container(blocks, block_ids.size());
2433  for (const auto& block_hash : block_ids)
2434  {
2435  try
2436  {
2437  uint64_t height = 0;
2438  if (m_db->block_exists(block_hash, &height))
2439  {
2440  blocks.push_back(std::make_pair(m_db->get_block_blob_from_height(height), block()));
2441  if (!parse_and_validate_block_from_blob(blocks.back().first, blocks.back().second))
2442  {
2443  LOG_ERROR("Invalid block: " << block_hash);
2444  blocks.pop_back();
2445  missed_bs.push_back(block_hash);
2446  }
2447  }
2448  else
2449  missed_bs.push_back(block_hash);
2450  }
2451  catch (const std::exception& e)
2452  {
2453  return false;
2454  }
2455  }
2456  return true;
2457 }
virtual cryptonote::blobdata get_block_blob_from_height(const uint64_t &height) const =0
fetch a block blob by height
uint64_t height
Definition: blockchain.cpp:91
unsigned __int64 uint64_t
Definition: stdint.h:136
#define CRITICAL_REGION_LOCAL(x)
Definition: syncobj.h:228
virtual bool block_exists(const crypto::hash &h, uint64_t *height=NULL) const =0
checks if a block exists
#define LOG_PRINT_L3(x)
Definition: misc_log_ex.h:102
#define LOG_ERROR(x)
Definition: misc_log_ex.h:98
void reserve_container(std::vector< T > &v, size_t N)
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_current_blockchain_height()

uint64_t Blockchain::get_current_blockchain_height ( ) const

get the current height of the blockchain

Returns
the height

Definition at line 322 of file blockchain.cpp.

323 {
324  LOG_PRINT_L3("Blockchain::" << __func__);
325  // WARNING: this function does not take m_blockchain_lock, and thus should only call read only
326  // m_db functions which do not depend on one another (ie, no getheight + gethash(height-1), as
327  // well as not accessing class members, even read only (ie, m_invalid_blocks). The caller must
328  // lock if it is otherwise needed.
329  return m_db->height();
330 }
virtual uint64_t height() const =0
fetch the current blockchain height
#define LOG_PRINT_L3(x)
Definition: misc_log_ex.h:102
Here is the call graph for this function:
Here is the caller graph for this function:

◆ get_current_cumulative_block_weight_limit()

uint64_t Blockchain::get_current_cumulative_block_weight_limit ( ) const

gets the block weight limit based on recent blocks

Returns
the limit

Definition at line 1560 of file blockchain.cpp.

1561 {
1562  LOG_PRINT_L3("Blockchain::" << __func__);
1563  return m_current_block_cumul_weight_limit;
1564 }
#define LOG_PRINT_L3(x)
Definition: misc_log_ex.h:102
Here is the caller graph for this function:

◆ get_current_cumulative_block_weight_median()

uint64_t Blockchain::get_current_cumulative_block_weight_median ( ) const

gets the block weight median based on recent blocks (same window as for the limit)

Returns
the median

Definition at line 1566 of file blockchain.cpp.

1567 {
1568  LOG_PRINT_L3("Blockchain::" << __func__);
1569  return m_current_block_cumul_weight_median;
1570 }
#define LOG_PRINT_L3(x)
Definition: misc_log_ex.h:102
Here is the caller graph for this function:

◆ get_current_hard_fork_version()

uint8_t cryptonote::Blockchain::get_current_hard_fork_version ( ) const
inline

gets the current hardfork version in use/voted for

Returns
the version

Definition at line 825 of file blockchain.h.

825 { return m_hardfork->get_current_version(); }
uint8_t get_current_version() const
returns the current version
Definition: hardfork.cpp:361
Here is the call graph for this function:
Here is the caller graph for this function:

◆ get_db() [1/2]

const BlockchainDB& cryptonote::Blockchain::get_db ( ) const
inline

get a reference to the BlockchainDB in use by Blockchain

Returns
a reference to the BlockchainDB instance

Definition at line 963 of file blockchain.h.

964  {
965  return *m_db;
966  }
Here is the caller graph for this function:

◆ get_db() [2/2]

BlockchainDB& cryptonote::Blockchain::get_db ( )
inline

get a reference to the BlockchainDB in use by Blockchain

Returns
a reference to the BlockchainDB instance

Definition at line 973 of file blockchain.h.

974  {
975  return *m_db;
976  }

◆ get_difficulty_for_next_block()

difficulty_type Blockchain::get_difficulty_for_next_block ( )

returns the difficulty target the next block to be added must meet

Returns
the target

Definition at line 971 of file blockchain.cpp.

972 {
973  if (m_fixed_difficulty)
974  {
975  return m_db->height() ? m_fixed_difficulty : 1;
976  }
977 
978  LOG_PRINT_L3("Blockchain::" << __func__);
979 
980  crypto::hash top_hash = get_tail_id();
981  {
982  CRITICAL_REGION_LOCAL(m_difficulty_lock);
983  // we can call this without the blockchain lock, it might just give us
984  // something a bit out of date, but that's fine since anything which
985  // requires the blockchain lock will have acquired it in the first place,
986  // and it will be unlocked only when called from the getinfo RPC
987  if (top_hash == m_difficulty_for_next_block_top_hash)
988  return m_difficulty_for_next_block;
989  }
990 
991  CRITICAL_REGION_LOCAL(m_blockchain_lock);
992  std::vector<uint64_t> timestamps;
993  std::vector<difficulty_type> difficulties;
995  top_hash = get_tail_id(height); // get it again now that we have the lock
996  ++height; // top block height to blockchain height
997 
998  uint64_t v6height = 0, v7height = 0, v8height = 0;
999  if(m_nettype == MAINNET) {
1000  v6height = mainnet_hard_forks[1].height;
1001  v7height = mainnet_hard_forks[2].height;
1002  v8height = mainnet_hard_forks[3].height;
1003  } else if(m_nettype == TESTNET) {
1004  v6height = testnet_hard_forks[1].height;
1005  v7height = testnet_hard_forks[2].height;
1006  v8height = testnet_hard_forks[3].height;
1007  } else if(m_nettype == STAGENET) {
1008  v6height = stagenet_hard_forks[5].height;
1009  v7height = stagenet_hard_forks[5].height;
1010  v8height = stagenet_hard_forks[5].height;
1011  } else if(m_nettype == UNDEFINED){
1012  MERROR(std::string("Something went wrong defining the network type."));
1013  }
1014 
1015 
1016  uint32_t difficultyBlocksCount = (height >= v6height && height < v7height) ? DIFFICULTY_BLOCKS_COUNT_V6 : DIFFICULTY_BLOCKS_COUNT;
1017 
1018  // After v8 allow the difficulty window to grow linearly (from zero) back to DIFFICULTY_BLOCKS_COUNT.
1019  if((height >= v8height) && (height < v8height + 720))
1020  {
1021  // Initial clear of the caches when we hit v8.
1022  if(height == v8height)
1023  {
1024  m_timestamps.clear();
1025  m_difficulties.clear();
1026  }
1027  difficultyBlocksCount = height - v8height;
1028  }
1029 
1030  // ND: Speedup
1031  // 1. Keep a list of the last 735 (or less) blocks that is used to compute difficulty,
1032  // then when the next block difficulty is queried, push the latest height data and
1033  // pop the oldest one from the list. This only requires 1x read per height instead
1034  // of doing 735 (DIFFICULTY_BLOCKS_COUNT).
1035  // Post v8 we will only re-enter this scope after the first DIFFICULTY_BLOCKS_COUNT blocks due to the last condition.
1036  if (m_timestamps_and_difficulties_height != 0 && ((height - m_timestamps_and_difficulties_height) == 1) && m_timestamps.size() >= difficultyBlocksCount)
1037  {
1038  uint64_t index = height - 1;
1039  m_timestamps.push_back(m_db->get_block_timestamp(index));
1040  m_difficulties.push_back(m_db->get_block_cumulative_difficulty(index));
1041 
1042  while (m_timestamps.size() > difficultyBlocksCount)
1043  m_timestamps.erase(m_timestamps.begin());
1044  while (m_difficulties.size() > difficultyBlocksCount)
1045  m_difficulties.erase(m_difficulties.begin());
1046 
1047  m_timestamps_and_difficulties_height = height;
1048  timestamps = m_timestamps;
1049  difficulties = m_difficulties;
1050  }
1051  else
1052  {
1053  uint64_t offset = height - std::min < uint64_t > (height, static_cast<uint64_t>(difficultyBlocksCount));
1054  if (offset == 0)
1055  ++offset;
1056 
1057  timestamps.clear();
1058  difficulties.clear();
1059  if (height > offset)
1060  {
1061  timestamps.reserve(height - offset);
1062  difficulties.reserve(height - offset);
1063  }
1064  for (; offset < height; offset++)
1065  {
1066  timestamps.push_back(m_db->get_block_timestamp(offset));
1067  difficulties.push_back(m_db->get_block_cumulative_difficulty(offset));
1068  }
1069 
1070  m_timestamps_and_difficulties_height = height;
1071  m_timestamps = timestamps;
1072  m_difficulties = difficulties;
1073  }
1074  size_t target = get_difficulty_target();
1075  const uint8_t version = (height >= v6height && height < v7height) ? 6 : 1;
1076  difficulty_type diff = next_difficulty(timestamps, difficulties, target, version);
1077 
1078  CRITICAL_REGION_LOCAL1(m_difficulty_lock);
1079  m_difficulty_for_next_block_top_hash = top_hash;
1080  m_difficulty_for_next_block = diff;
1081  return diff;
1082 }
#define CRITICAL_REGION_LOCAL1(x)
Definition: syncobj.h:230
#define MERROR(x)
Definition: misc_log_ex.h:73
difficulty_type next_difficulty(std::vector< uint64_t > timestamps, std::vector< difficulty_type > cumulative_difficulties, size_t target_seconds, uint8_t version)
Definition: difficulty.cpp:210
virtual uint64_t get_block_timestamp(const uint64_t &height) const =0
fetch a block&#39;s timestamp
::std::string string
Definition: gtest-port.h:1097
uint64_t height
Definition: blockchain.cpp:91
virtual difficulty_type get_block_cumulative_difficulty(const uint64_t &height) const =0
fetch a block&#39;s cumulative difficulty
unsigned char uint8_t
Definition: stdint.h:124
crypto::hash get_tail_id() const
get the hash of the most recent block on the blockchain
Definition: blockchain.cpp:837
unsigned int uint32_t
Definition: stdint.h:126
unsigned __int64 uint64_t
Definition: stdint.h:136
#define CRITICAL_REGION_LOCAL(x)
Definition: syncobj.h:228
#define DIFFICULTY_BLOCKS_COUNT
virtual uint64_t height() const =0
fetch the current blockchain height
#define LOG_PRINT_L3(x)
Definition: misc_log_ex.h:102
uint8_t version
Definition: blockchain.cpp:90
boost::multiprecision::uint128_t difficulty_type
Definition: difficulty.h:43
uint64_t get_difficulty_target() const
get difficulty target based on chain and hardfork version
POD_CLASS hash
Definition: hash.h:50
#define DIFFICULTY_BLOCKS_COUNT_V6
Here is the call graph for this function:
Here is the caller graph for this function:

◆ get_difficulty_target()

uint64_t Blockchain::get_difficulty_target ( ) const

get difficulty target based on chain and hardfork version

Returns
difficulty target

Definition at line 4890 of file blockchain.cpp.

4891 {
4893 }
uint8_t get_current_hard_fork_version() const
gets the current hardfork version in use/voted for
Definition: blockchain.h:825
#define DIFFICULTY_TARGET_V6
#define DIFFICULTY_TARGET
Here is the call graph for this function:
Here is the caller graph for this function:

◆ get_dynamic_base_fee()

uint64_t Blockchain::get_dynamic_base_fee ( uint64_t  block_reward,
size_t  median_block_weight,
uint8_t  version 
)
static

get dynamic per kB or byte fee for a given block weight

The dynamic fee is based on the block weight in a past window, and the current block reward. It is expressed by kB before v8, and per byte from v8.

Parameters
block_rewardthe current block reward
median_block_weightthe median block weight in the past window
versionhard fork version for rules and constants to use
Returns
the fee

Definition at line 3347 of file blockchain.cpp.

3348 {
3349  const uint64_t min_block_weight = get_min_block_weight(version);
3350  if (median_block_weight < min_block_weight)
3351  median_block_weight = min_block_weight;
3352  uint64_t hi, lo;
3353 
3355  {
3356  lo = mul128(block_reward, DYNAMIC_FEE_REFERENCE_TRANSACTION_WEIGHT, &hi);
3357  div128_32(hi, lo, min_block_weight, &hi, &lo);
3358  div128_32(hi, lo, median_block_weight, &hi, &lo);
3359  assert(hi == 0);
3360  lo /= 5;
3361  return lo;
3362  }
3363 
3365 
3366  uint64_t unscaled_fee_base = (fee_base * min_block_weight / median_block_weight);
3367  lo = mul128(unscaled_fee_base, block_reward, &hi);
3368  static_assert(DYNAMIC_FEE_PER_KB_BASE_BLOCK_REWARD % 1000000 == 0, "DYNAMIC_FEE_PER_KB_BASE_BLOCK_REWARD must be divisible by 1000000");
3369  static_assert(DYNAMIC_FEE_PER_KB_BASE_BLOCK_REWARD / 1000000 <= std::numeric_limits<uint32_t>::max(), "DYNAMIC_FEE_PER_KB_BASE_BLOCK_REWARD is too large");
3370 
3371  // divide in two steps, since the divisor must be 32 bits, but DYNAMIC_FEE_PER_KB_BASE_BLOCK_REWARD isn't
3372  div128_32(hi, lo, DYNAMIC_FEE_PER_KB_BASE_BLOCK_REWARD / 1000000, &hi, &lo);
3373  div128_32(hi, lo, 1000000, &hi, &lo);
3374  assert(hi == 0);
3375 
3376  // quantize fee up to 8 decimals
3378  uint64_t qlo = (lo + mask - 1) / mask * mask;
3379  MDEBUG("lo " << print_etn(lo) << ", qlo " << print_etn(qlo) << ", mask " << mask);
3380 
3381  return qlo;
3382 }
std::string print_etn(uint64_t amount, unsigned int decimal_point)
size_t get_min_block_weight(uint8_t version)
#define DYNAMIC_FEE_PER_KB_BASE_BLOCK_REWARD
#define DYNAMIC_FEE_REFERENCE_TRANSACTION_WEIGHT
#define MDEBUG(x)
Definition: misc_log_ex.h:76
static uint64_t get_fee_quantization_mask()
get fee quantization mask
#define DYNAMIC_FEE_PER_KB_BASE_FEE_V5
#define DYNAMIC_FEE_PER_KB_BASE_FEE
unsigned __int64 uint64_t
Definition: stdint.h:136
uint8_t version
Definition: blockchain.cpp:90
#define HF_VERSION_PER_BYTE_FEE
Here is the call graph for this function:
Here is the caller graph for this function:

◆ get_dynamic_base_fee_estimate()

uint64_t Blockchain::get_dynamic_base_fee_estimate ( uint64_t  grace_blocks) const

get dynamic per kB or byte fee estimate for the next few blocks

The dynamic fee is based on the block weight in a past window, and the current block reward. It is expressed by kB before v8, and per byte from v8. This function calculates an estimate for a dynamic fee which will be valid for the next grace_blocks

Parameters
grace_blocksnumber of blocks we want the fee to be valid for
Returns
the fee estimate

Definition at line 3446 of file blockchain.cpp.

3447 {
3449  const uint64_t db_height = m_db->height();
3450 
3452  if (version >= 11) {
3453  return FEE_PER_KB_V11;
3454  } else if (version < 11 && version >= 6) {
3455  return FEE_PER_KB_V6;
3456  } else {
3457  return FEE_PER_KB;
3458  }
3459  }
3460 
3461  if (grace_blocks >= CRYPTONOTE_REWARD_BLOCKS_WINDOW)
3462  grace_blocks = CRYPTONOTE_REWARD_BLOCKS_WINDOW - 1;
3463 
3464  const uint64_t min_block_weight = get_min_block_weight(version);
3465  std::vector<uint64_t> weights;
3466  get_last_n_blocks_weights(weights, CRYPTONOTE_REWARD_BLOCKS_WINDOW - grace_blocks);
3467  weights.reserve(grace_blocks);
3468  for (size_t i = 0; i < grace_blocks; ++i)
3469  weights.push_back(min_block_weight);
3470 
3472  if(median <= min_block_weight)
3473  median = min_block_weight;
3474 
3475  uint64_t already_generated_coins = db_height ? m_db->get_block_already_generated_coins(db_height - 1) : 0;
3476  uint64_t base_reward;
3477  if (!get_block_reward(median, 1, already_generated_coins, base_reward, version, get_current_blockchain_height(), get_nettype()))
3478  {
3479  MERROR("Failed to determine block reward, using placeholder " << print_etn(BLOCK_REWARD_OVERESTIMATE) << " as a high bound");
3480  base_reward = BLOCK_REWARD_OVERESTIMATE;
3481  }
3482 
3483  const bool use_long_term_median_in_fee = version >= HF_VERSION_LONG_TERM_BLOCK_WEIGHT;
3484  uint64_t fee = get_dynamic_base_fee(base_reward, use_long_term_median_in_fee ? m_long_term_effective_median_block_weight : median, version);
3485  const bool per_byte = version < HF_VERSION_PER_BYTE_FEE;
3486  MDEBUG("Estimating " << grace_blocks << "-block fee at " << print_etn(fee) << "/" << (per_byte ? "byte" : "kB"));
3487  return fee;
3488 }
#define MERROR(x)
Definition: misc_log_ex.h:73
#define FEE_PER_KB_V11
std::string print_etn(uint64_t amount, unsigned int decimal_point)
size_t get_min_block_weight(uint8_t version)
#define FEE_PER_KB
uint64_t get_current_blockchain_height() const
get the current height of the blockchain
Definition: blockchain.cpp:322
unsigned char uint8_t
Definition: stdint.h:124
static uint64_t get_dynamic_base_fee(uint64_t block_reward, size_t median_block_weight, uint8_t version)
get dynamic per kB or byte fee for a given block weight
#define MDEBUG(x)
Definition: misc_log_ex.h:76
uint8_t get_current_hard_fork_version() const
gets the current hardfork version in use/voted for
Definition: blockchain.h:825
#define BLOCK_REWARD_OVERESTIMATE
Definition: blockchain.cpp:87
#define HF_VERSION_LONG_TERM_BLOCK_WEIGHT
#define FEE_PER_KB_V6
#define HF_VERSION_DYNAMIC_FEE
unsigned __int64 uint64_t
Definition: stdint.h:136
virtual uint64_t height() const =0
fetch the current blockchain height
uint8_t version
Definition: blockchain.cpp:90
type_vec_type median(std::vector< type_vec_type > &v)
#define CRYPTONOTE_REWARD_BLOCKS_WINDOW
network_type get_nettype() const
get blockchain nettype
Definition: blockchain.h:1073
bool get_block_reward(size_t median_weight, size_t current_block_weight, uint64_t already_generated_coins, uint64_t &reward, uint8_t version, uint64_t current_block_height, network_type nettype)
virtual uint64_t get_block_already_generated_coins(const uint64_t &height) const =0
fetch a block&#39;s already generated coins
#define HF_VERSION_PER_BYTE_FEE
Here is the call graph for this function:
Here is the caller graph for this function:

◆ get_earliest_ideal_height_for_version()

uint64_t cryptonote::Blockchain::get_earliest_ideal_height_for_version ( uint8_t  version) const
inline

returns the earliest block a given version may activate

Returns
the height

Definition at line 865 of file blockchain.h.

865 { return m_hardfork->get_earliest_ideal_height_for_version(version); }
version
Supported socks variants.
Definition: socks.h:57
uint64_t get_earliest_ideal_height_for_version(uint8_t version) const
returns the earliest block a given version may activate
Definition: hardfork.cpp:384
Here is the call graph for this function:
Here is the caller graph for this function:

◆ get_fee_quantization_mask()

uint64_t Blockchain::get_fee_quantization_mask ( )
static

get fee quantization mask

The dynamic fee may be quantized, to mask out the last decimal places

Returns
the fee quantized mask

Definition at line 3334 of file blockchain.cpp.

3335 {
3336  static uint64_t mask = 0;
3337  if (mask == 0)
3338  {
3339  mask = 1;
3341  mask *= 10;
3342  }
3343  return mask;
3344 }
#define CRYPTONOTE_DISPLAY_DECIMAL_POINT
#define PER_KB_FEE_QUANTIZATION_DECIMALS
unsigned __int64 uint64_t
Definition: stdint.h:136
Here is the caller graph for this function:

◆ get_hard_fork_heights()

const std::vector< HardFork::Params > & Blockchain::get_hard_fork_heights ( network_type  nettype)
static

gets the hardfork heights of given network

Returns
the HardFork object

Definition at line 4852 of file blockchain.cpp.

4853 {
4854  static const std::vector<HardFork::Params> mainnet_heights = []()
4855  {
4856  std::vector<HardFork::Params> heights;
4857  for (const auto& i : mainnet_hard_forks)
4858  heights.emplace_back(i.version, i.height, i.threshold, i.time);
4859  return heights;
4860  }();
4861  static const std::vector<HardFork::Params> testnet_heights = []()
4862  {
4863  std::vector<HardFork::Params> heights;
4864  for (const auto& i : testnet_hard_forks)
4865  heights.emplace_back(i.version, i.height, i.threshold, i.time);
4866  return heights;
4867  }();
4868  static const std::vector<HardFork::Params> stagenet_heights = []()
4869  {
4870  std::vector<HardFork::Params> heights;
4871  for (const auto& i : stagenet_hard_forks)
4872  heights.emplace_back(i.version, i.height, i.threshold, i.time);
4873  return heights;
4874  }();
4875  static const std::vector<HardFork::Params> dummy;
4876  switch (nettype)
4877  {
4878  case MAINNET: return mainnet_heights;
4879  case TESTNET: return testnet_heights;
4880  case STAGENET: return stagenet_heights;
4881  default: return dummy;
4882  }
4883 }

◆ get_hard_fork_state()

HardFork::State Blockchain::get_hard_fork_state ( ) const

gets the hardfork voting state object

Returns
the HardFork object

Definition at line 4847 of file blockchain.cpp.

4848 {
4849  return m_hardfork->get_state();
4850 }
State get_state(time_t t) const
returns current state at the given time
Definition: hardfork.cpp:327
Here is the call graph for this function:
Here is the caller graph for this function:

◆ get_hard_fork_version()

uint8_t cryptonote::Blockchain::get_hard_fork_version ( uint64_t  height) const
inline

returns the actual hardfork version for a given block height

Parameters
heightthe height for which to check version info
Returns
the version

Definition at line 858 of file blockchain.h.

858 { return m_hardfork->get(height); }
uint64_t height
Definition: blockchain.cpp:91
uint8_t get(uint64_t height) const
returns the hard fork version for the given block height
Definition: hardfork.cpp:348
Here is the call graph for this function:
Here is the caller graph for this function:

◆ get_hard_fork_voting_info()

bool Blockchain::get_hard_fork_voting_info ( uint8_t  version,
uint32_t window,
uint32_t votes,
uint32_t threshold,
uint64_t earliest_height,
uint8_t voting 
) const

get information about hardfork voting for a version

Parameters
versionthe version in question
windowthe size of the voting window
votesthe number of votes to enable <version>
thresholdthe number of votes required to enable <version>
earliest_heightthe earliest height at which <version> is allowed
votingwhich version this node is voting for/using
Returns
whether the version queried is enabled

Definition at line 4885 of file blockchain.cpp.

4886 {
4887  return m_hardfork->get_voting_info(version, window, votes, threshold, earliest_height, voting);
4888 }
uint8_t version
Definition: blockchain.cpp:90
bool get_voting_info(uint8_t version, uint32_t &window, uint32_t &votes, uint32_t &threshold, uint64_t &earliest_height, uint8_t &voting) const
returns information about current voting state
Definition: hardfork.cpp:409
uint8_t threshold
Definition: blockchain.cpp:92
Here is the call graph for this function:
Here is the caller graph for this function:

◆ get_ideal_hard_fork_version() [1/2]

uint8_t cryptonote::Blockchain::get_ideal_hard_fork_version ( ) const
inline

returns the newest hardfork version known to the blockchain

Returns
the version

Definition at line 832 of file blockchain.h.

832 { return m_hardfork->get_ideal_version(); }
uint8_t get_ideal_version() const
returns the latest "ideal" version
Definition: hardfork.cpp:367
Here is the call graph for this function:
Here is the caller graph for this function:

◆ get_ideal_hard_fork_version() [2/2]

uint8_t cryptonote::Blockchain::get_ideal_hard_fork_version ( uint64_t  height) const
inline

returns the newest hardfork version voted to be enabled as of a certain height

Parameters
heightthe height for which to check version info
Returns
the version

Definition at line 849 of file blockchain.h.

849 { return m_hardfork->get_ideal_version(height); }
uint64_t height
Definition: blockchain.cpp:91
uint8_t get_ideal_version() const
returns the latest "ideal" version
Definition: hardfork.cpp:367
Here is the call graph for this function:

◆ get_last_block_timestamps()

std::vector< time_t > Blockchain::get_last_block_timestamps ( unsigned int  blocks) const

returns the timestamps of the last N blocks

Definition at line 1084 of file blockchain.cpp.

1085 {
1086  uint64_t height = m_db->height();
1087  if (blocks > height)
1088  blocks = height;
1089  std::vector<time_t> timestamps(blocks);
1090  while (blocks--)
1091  timestamps[blocks] = m_db->get_block_timestamp(height - blocks - 1);
1092  return timestamps;
1093 }
virtual uint64_t get_block_timestamp(const uint64_t &height) const =0
fetch a block&#39;s timestamp
uint64_t height
Definition: blockchain.cpp:91
unsigned __int64 uint64_t
Definition: stdint.h:136
virtual uint64_t height() const =0
fetch the current blockchain height
Here is the call graph for this function:

◆ get_mempool_tx_livetime()

uint32_t Blockchain::get_mempool_tx_livetime ( ) const

Definition at line 4808 of file blockchain.cpp.

4809 {
4811  {
4813  }
4815 }
#define CRYPTONOTE_MEMPOOL_TX_LIVETIME_V6
uint64_t get_current_blockchain_height() const
get the current height of the blockchain
Definition: blockchain.cpp:322
#define CRYPTONOTE_MEMPOOL_TX_LIVETIME
uint8_t get_hard_fork_version(uint64_t height) const
returns the actual hardfork version for a given block height
Definition: blockchain.h:858
Here is the call graph for this function:

◆ get_nettype()

network_type cryptonote::Blockchain::get_nettype ( ) const
inline

get blockchain nettype

Definition at line 1073 of file blockchain.h.

1073 { return m_nettype; };
Here is the caller graph for this function:

◆ get_next_hard_fork_version()

uint8_t cryptonote::Blockchain::get_next_hard_fork_version ( ) const
inline

returns the next hardfork version

Returns
the version

Definition at line 839 of file blockchain.h.

839 { return m_hardfork->get_next_version(); }
uint8_t get_next_version() const
returns the next version
Definition: hardfork.cpp:397
Here is the call graph for this function:
Here is the caller graph for this function:

◆ get_next_long_term_block_weight()

uint64_t Blockchain::get_next_long_term_block_weight ( uint64_t  block_weight) const

gets the long term block weight for a new block

Returns
the long term block weight

Definition at line 4100 of file blockchain.cpp.

4101 {
4103 
4104  const uint64_t db_height = m_db->height();
4105  const uint64_t nblocks = std::min<uint64_t>(m_long_term_block_weights_window, db_height);
4106 
4107  const uint8_t hf_version = get_current_hard_fork_version();
4108  if (hf_version < HF_VERSION_LONG_TERM_BLOCK_WEIGHT)
4109  return block_weight;
4110 
4111  uint64_t long_term_median = get_long_term_block_weight_median(db_height - nblocks, nblocks);
4112  uint64_t long_term_effective_median_block_weight = std::max<uint64_t>(CRYPTONOTE_BLOCK_GRANTED_FULL_REWARD_ZONE_V5, long_term_median);
4113 
4114  uint64_t short_term_constraint = long_term_effective_median_block_weight + long_term_effective_median_block_weight * 2 / 5;
4115  uint64_t long_term_block_weight = std::min<uint64_t>(block_weight, short_term_constraint);
4116 
4117  return long_term_block_weight;
4118 }
#define PERF_TIMER(name)
Definition: perf_timer.h:82
unsigned char uint8_t
Definition: stdint.h:124
uint8_t get_current_hard_fork_version() const
gets the current hardfork version in use/voted for
Definition: blockchain.h:825
#define HF_VERSION_LONG_TERM_BLOCK_WEIGHT
unsigned __int64 uint64_t
Definition: stdint.h:136
virtual uint64_t height() const =0
fetch the current blockchain height
uint64_t get_next_long_term_block_weight(uint64_t block_weight) const
gets the long term block weight for a new block
#define CRYPTONOTE_BLOCK_GRANTED_FULL_REWARD_ZONE_V5
Here is the call graph for this function:
Here is the caller graph for this function:

◆ get_num_mature_outputs()

uint64_t Blockchain::get_num_mature_outputs ( uint64_t  amount) const

get number of outputs of an amount past the minimum spendable age

Parameters
amountthe output amount
Returns
the number of mature outputs

Definition at line 2215 of file blockchain.cpp.

2216 {
2217  uint64_t num_outs = m_db->get_num_outputs(amount);
2218  // ensure we don't include outputs that aren't yet eligible to be used
2219  // outpouts are sorted by height
2220  const uint64_t blockchain_height = m_db->height();
2221  while (num_outs > 0)
2222  {
2223  const tx_out_index toi = m_db->get_output_tx_and_index(amount, num_outs - 1);
2224  const uint64_t height = m_db->get_tx_block_height(toi.first);
2226  break;
2227  --num_outs;
2228  }
2229 
2230  return num_outs;
2231 }
virtual uint64_t get_tx_block_height(const crypto::hash &h) const =0
fetches the height of a transaction&#39;s block
uint64_t height
Definition: blockchain.cpp:91
#define ETN_DEFAULT_TX_SPENDABLE_AGE_V8
virtual tx_out_index get_output_tx_and_index(const uint64_t &amount, const uint64_t &index) const =0
gets an output&#39;s tx hash and index
virtual uint64_t get_num_outputs(const uint64_t &amount) const =0
fetches the number of outputs of a given amount
uint8_t get_current_hard_fork_version() const
gets the current hardfork version in use/voted for
Definition: blockchain.h:825
unsigned __int64 uint64_t
Definition: stdint.h:136
virtual uint64_t height() const =0
fetch the current blockchain height
#define CRYPTONOTE_DEFAULT_TX_SPENDABLE_AGE
std::pair< crypto::hash, uint64_t > tx_out_index
Here is the call graph for this function:

◆ get_output_distribution()

bool Blockchain::get_output_distribution ( uint64_t  amount,
uint64_t  from_height,
uint64_t  to_height,
uint64_t start_height,
std::vector< uint64_t > &  distribution,
uint64_t base 
) const

gets per block distribution of outputs of a given amount

Parameters
amountthe amount to get a ditribution for
from_heightthe height before which we do not care about the data
to_heightthe height after which we do not care about the data
return-by-referencestart_height the height of the first rct output
return-by-referencedistribution the start offset of the first rct output in this block (same as previous if none)
return-by-referencebase how many outputs of that amount are before the stated distribution

Definition at line 2293 of file blockchain.cpp.

2294 {
2295  // rct outputs don't exist before v4
2296  if (amount == 0)
2297  {
2298  switch (m_nettype)
2299  {
2300  case STAGENET: start_height = stagenet_hard_forks[3].height; break;
2301  case TESTNET: start_height = testnet_hard_forks[3].height; break;
2302  case MAINNET: start_height = mainnet_hard_forks[3].height; break;
2303  case FAKECHAIN: start_height = 0; break;
2304  default: return false;
2305  }
2306  }
2307  else
2308  start_height = 0;
2309  base = 0;
2310 
2311  if (to_height > 0 && to_height < from_height)
2312  return false;
2313 
2314  const uint64_t real_start_height = start_height;
2315  if (from_height > start_height)
2316  start_height = from_height;
2317 
2318  distribution.clear();
2319  uint64_t db_height = m_db->height();
2320  if (db_height == 0)
2321  return false;
2322  if (start_height >= db_height || to_height >= db_height)
2323  return false;
2324  if (amount == 0)
2325  {
2326  std::vector<uint64_t> heights;
2327  heights.reserve(to_height + 1 - start_height);
2328  uint64_t real_start_height = start_height > 0 ? start_height-1 : start_height;
2329  for (uint64_t h = real_start_height; h <= to_height; ++h)
2330  heights.push_back(h);
2331  distribution = m_db->get_block_cumulative_rct_outputs(heights);
2332  if (start_height > 0)
2333  {
2334  base = distribution[0];
2335  distribution.erase(distribution.begin());
2336  }
2337  return true;
2338  }
2339  else
2340  {
2341  return m_db->get_output_distribution(amount, start_height, to_height, distribution, base);
2342  }
2343 }
unsigned __int64 uint64_t
Definition: stdint.h:136
virtual uint64_t height() const =0
fetch the current blockchain height
virtual bool get_output_distribution(uint64_t amount, uint64_t from_height, uint64_t to_height, std::vector< uint64_t > &distribution, uint64_t &base) const =0
virtual std::vector< uint64_t > get_block_cumulative_rct_outputs(const std::vector< uint64_t > &heights) const =0
fetch a block&#39;s cumulative number of rct outputs
Here is the caller graph for this function:

◆ get_output_histogram()

std::map< uint64_t, std::tuple< uint64_t, uint64_t, uint64_t > > Blockchain::get_output_histogram ( const std::vector< uint64_t > &  amounts,
bool  unlocked,
uint64_t  recent_cutoff,
uint64_t  min_count = 0 
) const

return a histogram of outputs on the blockchain

Parameters
amountsoptional set of amounts to lookup
unlockedwhether to restrict instances to unlocked ones
recent_cutofftimestamp to consider outputs as recent
min_countreturn only amounts with at least that many instances
Returns
a set of amount/instances

Definition at line 4895 of file blockchain.cpp.

4896 {
4897  return m_db->get_output_histogram(amounts, unlocked, recent_cutoff, min_count);
4898 }
virtual 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 =0
return a histogram of outputs on the blockchain
Here is the call graph for this function:
Here is the caller graph for this function:

◆ get_output_key()

crypto::public_key Blockchain::get_output_key ( uint64_t  amount,
uint64_t  global_index 
) const

get the public key for an output

Parameters
amountthe output amount
global_indexthe output amount-global index
Returns
the public key

Definition at line 2233 of file blockchain.cpp.

2234 {
2235  output_data_t data = m_db->get_output_key(amount, global_index);
2236  return data.pubkey;
2237 }
virtual output_data_t get_output_key(const uint64_t &amount, const uint64_t &index, bool include_commitmemt=true) const =0
get some of an output&#39;s data
crypto::public_key pubkey
the output&#39;s public key (for spend verification)
a struct containing output metadata
Here is the call graph for this function:

◆ get_output_key_mask_unlocked()

void Blockchain::get_output_key_mask_unlocked ( const uint64_t amount,
const uint64_t index,
crypto::public_key key,
rct::key mask,
bool unlocked 
) const

gets an output's key and unlocked state

Parameters
amountin - the output amount
indexin - the output global amount index
maskout - the output's RingCT mask
keyout - the output's key
unlockedout - the output's unlocked state

Definition at line 2284 of file blockchain.cpp.

2285 {
2286  const auto o_data = m_db->get_output_key(amount, index);
2287  key = o_data.pubkey;
2288  mask = o_data.commitment;
2289  tx_out_index toi = m_db->get_output_tx_and_index(amount, index);
2290  unlocked = is_tx_spendtime_unlocked(m_db->get_tx_unlock_time(toi.first));
2291 }
const char * key
Definition: hmac_keccak.cpp:39
virtual tx_out_index get_output_tx_and_index(const uint64_t &amount, const uint64_t &index) const =0
gets an output&#39;s tx hash and index
virtual output_data_t get_output_key(const uint64_t &amount, const uint64_t &index, bool include_commitmemt=true) const =0
get some of an output&#39;s data
virtual uint64_t get_tx_unlock_time(const crypto::hash &h) const =0
fetch a transaction&#39;s unlock time/height
std::pair< crypto::hash, uint64_t > tx_out_index
Here is the call graph for this function:
Here is the caller graph for this function:

◆ get_outs()

bool Blockchain::get_outs ( const COMMAND_RPC_GET_OUTPUTS_BIN::request req,
COMMAND_RPC_GET_OUTPUTS_BIN::response res 
) const

gets specific outputs to mix with

This function takes an RPC request for outputs to mix with and creates an RPC response with the resultant output indices.

Outputs to mix with are specified in the request.

Parameters
reqthe outputs to return
resreturn-by-reference the resultant output indices and keys
Returns
true

Definition at line 2240 of file blockchain.cpp.

2241 {
2242  LOG_PRINT_L3("Blockchain::" << __func__);
2243  CRITICAL_REGION_LOCAL(m_blockchain_lock);
2244 
2245  res.outs.clear();
2246  res.outs.reserve(req.outputs.size());
2247 
2248  std::vector<cryptonote::output_data_t> data;
2249  try
2250  {
2251  std::vector<uint64_t> amounts, offsets;
2252  amounts.reserve(req.outputs.size());
2253  offsets.reserve(req.outputs.size());
2254  for (const auto &i: req.outputs)
2255  {
2256  amounts.push_back(i.amount);
2257  offsets.push_back(i.index);
2258  }
2259  m_db->get_output_key(epee::span<const uint64_t>(amounts.data(), amounts.size()), offsets, data);
2260  if (data.size() != req.outputs.size())
2261  {
2262  MERROR("Unexpected output data size: expected " << req.outputs.size() << ", got " << data.size());
2263  return false;
2264  }
2265  for (const auto &t: data)
2266  res.outs.push_back({t.pubkey, t.commitment, is_tx_spendtime_unlocked(t.unlock_time), t.height, crypto::null_hash});
2267 
2268  if (req.get_txid)
2269  {
2270  for (size_t i = 0; i < req.outputs.size(); ++i)
2271  {
2272  tx_out_index toi = m_db->get_output_tx_and_index(req.outputs[i].amount, req.outputs[i].index);
2273  res.outs[i].txid = toi.first;
2274  }
2275  }
2276  }
2277  catch (const std::exception &e)
2278  {
2279  return false;
2280  }
2281  return true;
2282 }
const char * res
Definition: hmac_keccak.cpp:41
#define MERROR(x)
Definition: misc_log_ex.h:73
virtual tx_out_index get_output_tx_and_index(const uint64_t &amount, const uint64_t &index) const =0
gets an output&#39;s tx hash and index
Non-owning sequence of data. Does not deep copy.
Definition: span.h:56
virtual output_data_t get_output_key(const uint64_t &amount, const uint64_t &index, bool include_commitmemt=true) const =0
get some of an output&#39;s data
#define CRITICAL_REGION_LOCAL(x)
Definition: syncobj.h:228
#define LOG_PRINT_L3(x)
Definition: misc_log_ex.h:102
std::pair< crypto::hash, uint64_t > tx_out_index
Here is the call graph for this function:
Here is the caller graph for this function:

◆ get_short_chain_history()

bool Blockchain::get_short_chain_history ( std::list< crypto::hash > &  ids) const

gets the hashes for a subset of the blockchain

puts into list <ids> a list of hashes representing certain blocks from the blockchain in reverse chronological order

the blocks chosen, at the time of this writing, are: the most recent 11 powers of 2 less recent from there, so 13, 17, 25, etc...

Parameters
idsreturn-by-reference list to put the resulting hashes in
Returns
true

Definition at line 859 of file blockchain.cpp.

860 {
861  LOG_PRINT_L3("Blockchain::" << __func__);
862  CRITICAL_REGION_LOCAL(m_blockchain_lock);
863  uint64_t i = 0;
864  uint64_t current_multiplier = 1;
865  uint64_t sz = m_db->height();
866 
867  if(!sz)
868  return true;
869 
870  db_rtxn_guard rtxn_guard(m_db);
871  bool genesis_included = false;
872  uint64_t current_back_offset = 1;
873  while(current_back_offset < sz)
874  {
875  ids.push_back(m_db->get_block_hash_from_height(sz - current_back_offset));
876 
877  if(sz-current_back_offset == 0)
878  {
879  genesis_included = true;
880  }
881  if(i < 10)
882  {
883  ++current_back_offset;
884  }
885  else
886  {
887  current_multiplier *= 2;
888  current_back_offset += current_multiplier;
889  }
890  ++i;
891  }
892 
893  if (!genesis_included)
894  {
895  ids.push_back(m_db->get_block_hash_from_height(0));
896  }
897 
898  return true;
899 }
virtual crypto::hash get_block_hash_from_height(const uint64_t &height) const =0
fetch a block&#39;s hash
unsigned __int64 uint64_t
Definition: stdint.h:136
#define CRITICAL_REGION_LOCAL(x)
Definition: syncobj.h:228
virtual uint64_t height() const =0
fetch the current blockchain height
#define LOG_PRINT_L3(x)
Definition: misc_log_ex.h:102
Here is the call graph for this function:
Here is the caller graph for this function:

◆ get_split_transactions_blobs()

template<class t_ids_container , class t_tx_container , class t_missed_container >
template bool cryptonote::Blockchain::get_split_transactions_blobs ( const t_ids_container &  txs_ids,
t_tx_container &  txs,
t_missed_container &  missed_txs 
) const

Definition at line 2500 of file blockchain.cpp.

2501 {
2502  LOG_PRINT_L3("Blockchain::" << __func__);
2503  CRITICAL_REGION_LOCAL(m_blockchain_lock);
2504 
2505  reserve_container(txs, txs_ids.size());
2506  for (const auto& tx_hash : txs_ids)
2507  {
2508  try
2509  {
2511  if (m_db->get_pruned_tx_blob(tx_hash, tx))
2512  {
2513  txs.push_back(std::make_tuple(tx_hash, std::move(tx), crypto::null_hash, cryptonote::blobdata()));
2514  if (!is_v1_tx(std::get<1>(txs.back())) && !m_db->get_prunable_tx_hash(tx_hash, std::get<2>(txs.back())))
2515  {
2516  MERROR("Prunable data hash not found for " << tx_hash);
2517  return false;
2518  }
2519  if (!m_db->get_prunable_tx_blob(tx_hash, std::get<3>(txs.back())))
2520  std::get<3>(txs.back()).clear();
2521  }
2522  else
2523  missed_txs.push_back(tx_hash);
2524  }
2525  catch (const std::exception& e)
2526  {
2527  return false;
2528  }
2529  }
2530  return true;
2531 }
#define MERROR(x)
Definition: misc_log_ex.h:73
tuple make_tuple()
Definition: gtest-tuple.h:675
virtual bool get_pruned_tx_blob(const crypto::hash &h, cryptonote::blobdata &tx) const =0
fetches the pruned transaction blob with the given hash
virtual bool get_prunable_tx_blob(const crypto::hash &h, cryptonote::blobdata &tx) const =0
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 =0
fetches the prunable transaction hash
#define CRITICAL_REGION_LOCAL(x)
Definition: syncobj.h:228
#define LOG_PRINT_L3(x)
Definition: misc_log_ex.h:102
std::string blobdata
Definition: blobdatatype.h:39
const T & move(const T &t)
Definition: gtest-port.h:1317
void reserve_container(std::vector< T > &v, size_t N)
bool is_v1_tx(const blobdata_ref &tx_blob)
Here is the call graph for this function:
Here is the caller graph for this function:

◆ get_tail_id() [1/2]

crypto::hash Blockchain::get_tail_id ( ) const

get the hash of the most recent block on the blockchain

Returns
the hash

Definition at line 837 of file blockchain.cpp.

838 {
839  LOG_PRINT_L3("Blockchain::" << __func__);
840  // WARNING: this function does not take m_blockchain_lock, and thus should only call read only
841  // m_db functions which do not depend on one another (ie, no getheight + gethash(height-1), as
842  // well as not accessing class members, even read only (ie, m_invalid_blocks). The caller must
843  // lock if it is otherwise needed.
844  return m_db->top_block_hash();
845 }
#define LOG_PRINT_L3(x)
Definition: misc_log_ex.h:102
virtual crypto::hash top_block_hash(uint64_t *block_height=NULL) const =0
fetch the top block&#39;s hash
Here is the call graph for this function:
Here is the caller graph for this function:

◆ get_tail_id() [2/2]

crypto::hash Blockchain::get_tail_id ( uint64_t height) const

get the height and hash of the most recent block on the blockchain

Parameters
heightreturn-by-reference variable to store the height in
Returns
the hash

Definition at line 830 of file blockchain.cpp.

831 {
832  LOG_PRINT_L3("Blockchain::" << __func__);
833  CRITICAL_REGION_LOCAL(m_blockchain_lock);
834  return m_db->top_block_hash(&height);
835 }
uint64_t height
Definition: blockchain.cpp:91
#define CRITICAL_REGION_LOCAL(x)
Definition: syncobj.h:228
#define LOG_PRINT_L3(x)
Definition: misc_log_ex.h:102
virtual crypto::hash top_block_hash(uint64_t *block_height=NULL) const =0
fetch the top block&#39;s hash
Here is the call graph for this function:

◆ get_total_transactions()

size_t Blockchain::get_total_transactions ( ) const

gets the total number of transactions on the main chain

Returns
the number of transactions on the main chain

Definition at line 2721 of file blockchain.cpp.

2722 {
2723  LOG_PRINT_L3("Blockchain::" << __func__);
2724  // WARNING: this function does not take m_blockchain_lock, and thus should only call read only
2725  // m_db functions which do not depend on one another (ie, no getheight + gethash(height-1), as
2726  // well as not accessing class members, even read only (ie, m_invalid_blocks). The caller must
2727  // lock if it is otherwise needed.
2728  return m_db->get_tx_count();
2729 }
#define LOG_PRINT_L3(x)
Definition: misc_log_ex.h:102
virtual uint64_t get_tx_count() const =0
fetches the total number of transactions ever
Here is the call graph for this function:
Here is the caller graph for this function:

◆ get_transactions()

template<class t_ids_container , class t_tx_container , class t_missed_container >
template bool cryptonote::Blockchain::get_transactions ( const t_ids_container &  txs_ids,
t_tx_container &  txs,
t_missed_container &  missed_txs 
) const

Definition at line 2534 of file blockchain.cpp.

2535 {
2536  LOG_PRINT_L3("Blockchain::" << __func__);
2537  CRITICAL_REGION_LOCAL(m_blockchain_lock);
2538 
2539  reserve_container(txs, txs_ids.size());
2540  for (const auto& tx_hash : txs_ids)
2541  {
2542  try
2543  {
2545  if (m_db->get_tx_blob(tx_hash, tx))
2546  {
2547  txs.push_back(transaction());
2548  if (!parse_and_validate_tx_from_blob(tx, txs.back()))
2549  {
2550  LOG_ERROR("Invalid transaction");
2551  return false;
2552  }
2553  }
2554  else
2555  missed_txs.push_back(tx_hash);
2556  }
2557  catch (const std::exception& e)
2558  {
2559  return false;
2560  }
2561  }
2562  return true;
2563 }
virtual bool get_tx_blob(const crypto::hash &h, cryptonote::blobdata &tx) const =0
fetches the transaction blob with the given hash
#define CRITICAL_REGION_LOCAL(x)
Definition: syncobj.h:228
bool parse_and_validate_tx_from_blob(const blobdata &tx_blob, transaction &tx)
#define LOG_PRINT_L3(x)
Definition: misc_log_ex.h:102
std::string blobdata
Definition: blobdatatype.h:39
#define LOG_ERROR(x)
Definition: misc_log_ex.h:98
void reserve_container(std::vector< T > &v, size_t N)
Here is the call graph for this function:
Here is the caller graph for this function:

◆ get_transactions_blobs()

template<class t_ids_container , class t_tx_container , class t_missed_container >
template bool cryptonote::Blockchain::get_transactions_blobs ( const t_ids_container &  txs_ids,
t_tx_container &  txs,
t_missed_container &  missed_txs,
bool  pruned = false 
) const

gets transactions based on a list of transaction hashes

Template Parameters
t_ids_containera standard-iterable container
t_tx_containera standard-iterable container
t_missed_containera standard-iterable container
Parameters
txs_idsa container of hashes for which to get the corresponding transactions
txsreturn-by-reference a container to store result transactions in
missed_txsreturn-by-reference a container to store missed transactions in
prunedwhether to return full or pruned blobs
Returns
false if an unexpected exception occurs, else true

Definition at line 2462 of file blockchain.cpp.

2463 {
2464  LOG_PRINT_L3("Blockchain::" << __func__);
2465  CRITICAL_REGION_LOCAL(m_blockchain_lock);
2466 
2467  reserve_container(txs, txs_ids.size());
2468  for (const auto& tx_hash : txs_ids)
2469  {
2470  try
2471  {
2473  if (pruned && m_db->get_pruned_tx_blob(tx_hash, tx))
2474  txs.push_back(std::move(tx));
2475  else if (!pruned && m_db->get_tx_blob(tx_hash, tx))
2476  txs.push_back(std::move(tx));
2477  else
2478  missed_txs.push_back(tx_hash);
2479  }
2480  catch (const std::exception& e)
2481  {
2482  return false;
2483  }
2484  }
2485  return true;
2486 }
virtual bool get_tx_blob(const crypto::hash &h, cryptonote::blobdata &tx) const =0
fetches the transaction blob with the given hash
virtual bool get_pruned_tx_blob(const crypto::hash &h, cryptonote::blobdata &tx) const =0
fetches the pruned transaction blob with the given hash
#define CRITICAL_REGION_LOCAL(x)
Definition: syncobj.h:228
#define LOG_PRINT_L3(x)
Definition: misc_log_ex.h:102
std::string blobdata
Definition: blobdatatype.h:39
const T & move(const T &t)
Definition: gtest-port.h:1317
void reserve_container(std::vector< T > &v, size_t N)
Here is the call graph for this function:
Here is the caller graph for this function:

◆ get_tx_outputs_gindexs() [1/2]

bool Blockchain::get_tx_outputs_gindexs ( const crypto::hash tx_id,
std::vector< uint64_t > &  indexs 
) const

gets the global indices for outputs from a given transaction

This function gets the global indices for all outputs belonging to a specific transaction.

Parameters
tx_idthe hash of the transaction to fetch indices for
indexsreturn-by-reference the global indices for the transaction's outputs
n_txeshow many txes in a row to get results for
Returns
false if the transaction does not exist, or if no indices are found, otherwise true

Definition at line 2822 of file blockchain.cpp.

2823 {
2824  LOG_PRINT_L3("Blockchain::" << __func__);
2825  CRITICAL_REGION_LOCAL(m_blockchain_lock);
2826  uint64_t tx_index;
2827  if (!m_db->tx_exists(tx_id, tx_index))
2828  {
2829  MERROR_VER("get_tx_outputs_gindexs failed to find transaction with id = " << tx_id);
2830  return false;
2831  }
2832 
2833  //no output indexes for tx.version >= 2 (public tx)
2834  if (m_db->get_tx(tx_id).version >= 2)
2835  return true;
2836 
2837  std::vector<std::vector<uint64_t>> indices = m_db->get_tx_amount_output_indices(tx_index, 1);
2838  CHECK_AND_ASSERT_MES(indices.size() == 1, false, "Wrong indices size");
2839  indexs = indices.front();
2840  return true;
2841 }
#define CHECK_AND_ASSERT_MES(expr, fail_ret_val, message)
Definition: misc_log_ex.h:181
virtual bool tx_exists(const crypto::hash &h) const =0
check if a transaction with a given hash exists
#define MERROR_VER(x)
Definition: blockchain.cpp:84
virtual std::vector< std::vector< uint64_t > > get_tx_amount_output_indices(const uint64_t tx_id, size_t n_txes=1) const =0
gets output indices (amount-specific) for a transaction&#39;s outputs
virtual transaction get_tx(const crypto::hash &h) const
fetches the transaction with the given hash
unsigned __int64 uint64_t
Definition: stdint.h:136
#define CRITICAL_REGION_LOCAL(x)
Definition: syncobj.h:228
#define LOG_PRINT_L3(x)
Definition: misc_log_ex.h:102
Here is the call graph for this function:
Here is the caller graph for this function:

◆ get_tx_outputs_gindexs() [2/2]

bool Blockchain::get_tx_outputs_gindexs ( const crypto::hash tx_id,
size_t  n_txes,
std::vector< std::vector< uint64_t >> &  indexs 
) const

Definition at line 2801 of file blockchain.cpp.

2802 {
2803  LOG_PRINT_L3("Blockchain::" << __func__);
2804  CRITICAL_REGION_LOCAL(m_blockchain_lock);
2805  uint64_t tx_index;
2806  if (!m_db->tx_exists(tx_id, tx_index))
2807  {
2808  MERROR_VER("get_tx_outputs_gindexs failed to find transaction with id = " << tx_id);
2809  return false;
2810  }
2811 
2812  //no output indexes for tx.version >= 2 (public tx)
2813  if (m_db->get_tx(tx_id).version >= 2)
2814  return true;
2815 
2816  indexs = m_db->get_tx_amount_output_indices(tx_index, n_txes);
2817  CHECK_AND_ASSERT_MES(n_txes == indexs.size(), false, "Wrong indexs size");
2818 
2819  return true;
2820 }
#define CHECK_AND_ASSERT_MES(expr, fail_ret_val, message)
Definition: misc_log_ex.h:181
virtual bool tx_exists(const crypto::hash &h) const =0
check if a transaction with a given hash exists
#define MERROR_VER(x)
Definition: blockchain.cpp:84
virtual std::vector< std::vector< uint64_t > > get_tx_amount_output_indices(const uint64_t tx_id, size_t n_txes=1) const =0
gets output indices (amount-specific) for a transaction&#39;s outputs
virtual transaction get_tx(const crypto::hash &h) const
fetches the transaction with the given hash
unsigned __int64 uint64_t
Definition: stdint.h:136
#define CRITICAL_REGION_LOCAL(x)
Definition: syncobj.h:228
#define LOG_PRINT_L3(x)
Definition: misc_log_ex.h:102
Here is the call graph for this function:

◆ get_txpool_tx_blob() [1/2]

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

Definition at line 4793 of file blockchain.cpp.

4794 {
4795  return m_db->get_txpool_tx_blob(txid, bd);
4796 }
virtual bool get_txpool_tx_blob(const crypto::hash &txid, cryptonote::blobdata &bd) const =0
get a txpool transaction&#39;s blob
Here is the call graph for this function:
Here is the caller graph for this function:

◆ get_txpool_tx_blob() [2/2]

cryptonote::blobdata Blockchain::get_txpool_tx_blob ( const crypto::hash txid) const

Definition at line 4798 of file blockchain.cpp.

4799 {
4800  return m_db->get_txpool_tx_blob(txid);
4801 }
virtual bool get_txpool_tx_blob(const crypto::hash &txid, cryptonote::blobdata &bd) const =0
get a txpool transaction&#39;s blob
Here is the call graph for this function:

◆ get_txpool_tx_count()

uint64_t Blockchain::get_txpool_tx_count ( bool  include_unrelayed_txes = true) const

Definition at line 4783 of file blockchain.cpp.

4784 {
4785  return m_db->get_txpool_tx_count(include_unrelayed_txes);
4786 }
virtual uint64_t get_txpool_tx_count(bool include_unrelayed_txes=true) const =0
get the number of transactions in the txpool
Here is the call graph for this function:
Here is the caller graph for this function:

◆ get_txpool_tx_meta()

bool Blockchain::get_txpool_tx_meta ( const crypto::hash txid,
txpool_tx_meta_t meta 
) const

Definition at line 4788 of file blockchain.cpp.

4789 {
4790  return m_db->get_txpool_tx_meta(txid, meta);
4791 }
virtual bool get_txpool_tx_meta(const crypto::hash &txid, txpool_tx_meta_t &meta) const =0
get a txpool transaction&#39;s metadata
Here is the call graph for this function:
Here is the caller graph for this function:

◆ get_validator_by_height()

electroneum::basic::Validator Blockchain::get_validator_by_height ( uint64_t  height)

Definition at line 5085 of file blockchain.cpp.

5085  {
5086 
5087  block blk;
5089 
5090  std::string signatory = std::string(blk.signatory.begin(), blk.signatory.end());
5091  return m_validators->getValidatorByKey(boost::algorithm::hex(signatory));
5092 
5093 }
::std::string string
Definition: gtest-port.h:1097
std::vector< uint8_t > signatory
Validator getValidatorByKey(string key)
Definition: validators.h:188
uint64_t height
Definition: blockchain.cpp:91
crypto::hash get_block_id_by_height(uint64_t height) const
gets a block&#39;s hash given a height
Definition: blockchain.cpp:901
bool get_block_by_hash(const crypto::hash &h, block &blk, bool *orphan=NULL) const
gets the block with a given hash
Definition: blockchain.cpp:928
Here is the call graph for this function:

◆ handle_get_objects()

bool Blockchain::handle_get_objects ( NOTIFY_REQUEST_GET_OBJECTS::request arg,
NOTIFY_RESPONSE_GET_OBJECTS::request rsp 
)

retrieves a set of blocks and their transactions, and possibly other transactions

the request object encapsulates a list of block hashes and a (possibly empty) list of transaction hashes. for each block hash, the block is fetched along with all of that block's transactions. Any transactions requested separately are fetched afterwards.

Parameters
argthe request
rspreturn-by-reference the response to fill in
Returns
true unless any blocks or transactions are missing

Definition at line 2146 of file blockchain.cpp.

2147 {
2148  LOG_PRINT_L3("Blockchain::" << __func__);
2149  CRITICAL_REGION_LOCAL(m_blockchain_lock);
2150  db_rtxn_guard rtxn_guard (m_db);
2151  rsp.current_blockchain_height = get_current_blockchain_height();
2152  std::vector<std::pair<cryptonote::blobdata,block>> blocks;
2153  get_blocks(arg.blocks, blocks, rsp.missed_ids);
2154 
2155  for (auto& bl: blocks)
2156  {
2157  std::vector<crypto::hash> missed_tx_ids;
2158 
2159  rsp.blocks.push_back(block_complete_entry());
2160  block_complete_entry& e = rsp.blocks.back();
2161 
2162  // FIXME: s/rsp.missed_ids/missed_tx_id/ ? Seems like rsp.missed_ids
2163  // is for missed blocks, not missed transactions as well.
2164  get_transactions_blobs(bl.second.tx_hashes, e.txs, missed_tx_ids);
2165 
2166  if (missed_tx_ids.size() != 0)
2167  {
2168  // do not display an error if the peer asked for an unpruned block which we are not meant to have
2170  {
2171  LOG_ERROR("Error retrieving blocks, missed " << missed_tx_ids.size()
2172  << " transactions for block with hash: " << get_block_hash(bl.second)
2173  << std::endl
2174  );
2175  }
2176 
2177  // append missed transaction hashes to response missed_ids field,
2178  // as done below if any standalone transactions were requested
2179  // and missed.
2180  rsp.missed_ids.insert(rsp.missed_ids.end(), missed_tx_ids.begin(), missed_tx_ids.end());
2181  return false;
2182  }
2183 
2184  //pack block
2185  e.block = std::move(bl.first);
2186  }
2187  //get and pack other transactions, if needed
2188  get_transactions_blobs(arg.txs, rsp.txs, rsp.missed_ids);
2189 
2190  return true;
2191 }
bool get_blocks(uint64_t start_offset, size_t count, std::vector< std::pair< cryptonote::blobdata, block >> &blocks, std::vector< cryptonote::blobdata > &txs) const
get blocks and transactions from blocks based on start height and count
std::vector< blobdata > txs
uint64_t get_current_blockchain_height() const
get the current height of the blockchain
Definition: blockchain.cpp:322
bool get_block_hash(const block &b, crypto::hash &res)
#define CRITICAL_REGION_LOCAL(x)
Definition: syncobj.h:228
blobdata block
#define LOG_PRINT_L3(x)
Definition: misc_log_ex.h:102
uint32_t get_blockchain_pruning_seed() const
Definition: blockchain.h:1017
bool get_transactions_blobs(const t_ids_container &txs_ids, t_tx_container &txs, t_missed_container &missed_txs, bool pruned=false) const
gets transactions based on a list of transaction hashes
const T & move(const T &t)
Definition: gtest-port.h:1317
#define LOG_ERROR(x)
Definition: misc_log_ex.h:98
bool has_unpruned_block(uint64_t block_height, uint64_t blockchain_height, uint32_t pruning_seed)
Definition: pruning.cpp:44
uint64_t get_block_height(const block &b)
Here is the call graph for this function:
Here is the caller graph for this function:

◆ have_block()

bool Blockchain::have_block ( const crypto::hash id) const

checks if a block is known about with a given hash

This function checks the main chain, alternate chains, and invalid blocks for a block with the given hash

Parameters
idthe hash to search for
Returns
true if the block is known, else false

Definition at line 2688 of file blockchain.cpp.

2689 {
2690  LOG_PRINT_L3("Blockchain::" << __func__);
2691  CRITICAL_REGION_LOCAL(m_blockchain_lock);
2692 
2693  if(m_db->block_exists(id))
2694  {
2695  LOG_PRINT_L2("block " << id << " found in main chain");
2696  return true;
2697  }
2698 
2699  if(m_alternative_chains.count(id))
2700  {
2701  LOG_PRINT_L2("block " << id << " found in m_alternative_chains");
2702  return true;
2703  }
2704 
2705  if(m_invalid_blocks.count(id))
2706  {
2707  LOG_PRINT_L2("block " << id << " found in m_invalid_blocks");
2708  return true;
2709  }
2710 
2711  return false;
2712 }
#define LOG_PRINT_L2(x)
Definition: misc_log_ex.h:101
#define CRITICAL_REGION_LOCAL(x)
Definition: syncobj.h:228
virtual bool block_exists(const crypto::hash &h, uint64_t *height=NULL) const =0
checks if a block exists
#define LOG_PRINT_L3(x)
Definition: misc_log_ex.h:102
Here is the call graph for this function:
Here is the caller graph for this function:

◆ have_tx()

bool Blockchain::have_tx ( const crypto::hash id) const

search the blockchain for a transaction by hash

Parameters
idthe hash to search for
Returns
true if the tx exists, else false

Definition at line 167 of file blockchain.cpp.

168 {
169  LOG_PRINT_L3("Blockchain::" << __func__);
170  // WARNING: this function does not take m_blockchain_lock, and thus should only call read only
171  // m_db functions which do not depend on one another (ie, no getheight + gethash(height-1), as
172  // well as not accessing class members, even read only (ie, m_invalid_blocks). The caller must
173  // lock if it is otherwise needed.
174  return m_db->tx_exists(id);
175 }
virtual bool tx_exists(const crypto::hash &h) const =0
check if a transaction with a given hash exists
#define LOG_PRINT_L3(x)
Definition: misc_log_ex.h:102
Here is the call graph for this function:
Here is the caller graph for this function:

◆ have_tx_keyimg_as_spent()

bool Blockchain::have_tx_keyimg_as_spent ( const crypto::key_image key_im) const

check if a key image is already spent on the blockchain

Whenever a transaction output is used as an input for another transaction (a true input, not just one of a mixing set), a key image is generated and stored in the transaction in order to prevent double spending. If this key image is seen again, the transaction using it is rejected.

Parameters
key_imthe key image to search for
Returns
true if the key image is already spent in the blockchain, else false

Definition at line 177 of file blockchain.cpp.

178 {
179  LOG_PRINT_L3("Blockchain::" << __func__);
180  // WARNING: this function does not take m_blockchain_lock, and thus should only call read only
181  // m_db functions which do not depend on one another (ie, no getheight + gethash(height-1), as
182  // well as not accessing class members, even read only (ie, m_invalid_blocks). The caller must
183  // lock if it is otherwise needed.
184  return m_db->has_key_image(key_im);
185 }
virtual bool has_key_image(const crypto::key_image &img) const =0
check if a key image is stored as spent
#define LOG_PRINT_L3(x)
Definition: misc_log_ex.h:102
Here is the call graph for this function:
Here is the caller graph for this function:

◆ init() [1/2]

bool Blockchain::init ( BlockchainDB db,
const network_type  nettype = MAINNET,
bool  offline = false,
const cryptonote::test_options test_options = NULL,
difficulty_type  fixed_difficulty = 0,
const GetCheckpointsCallback get_checkpoints = nullptr,
bool  ignore_bsig = false,
bool  fallback_to_pow = false 
)

Initialize the Blockchain state.

Parameters
dba pointer to the backing store to use for the blockchain
nettypenetwork type
offlinetrue if running offline, else false
test_optionstest parameters
fixed_difficultyfixed difficulty for testing purposes; 0 means disabled
get_checkpointsif set, will be called to get checkpoints data
Returns
true on success, false if any initialization steps fail

Definition at line 334 of file blockchain.cpp.

335 {
336  LOG_PRINT_L3("Blockchain::" << __func__);
337 
338  CHECK_AND_ASSERT_MES(nettype != FAKECHAIN || test_options, false, "fake chain network type used without options");
339 
340  CRITICAL_REGION_LOCAL(m_tx_pool);
341  CRITICAL_REGION_LOCAL1(m_blockchain_lock);
342 
343  if (db == nullptr)
344  {
345  LOG_ERROR("Attempted to init Blockchain with null DB");
346  return false;
347  }
348  if (!db->is_open())
349  {
350  LOG_ERROR("Attempted to init Blockchain with unopened DB");
351  delete db;
352  return false;
353  }
354 
355  m_db = db;
356 
357  m_nettype = test_options != NULL ? FAKECHAIN : nettype;
358  m_offline = offline;
359  m_fixed_difficulty = fixed_difficulty;
360  m_ignore_bsig = ignore_bsig;
361  m_fallback_to_pow = fallback_to_pow;
362  if (m_hardfork == nullptr)
363  {
364  if (m_nettype == FAKECHAIN || m_nettype == STAGENET)
365  m_hardfork = new HardFork(*db, 1, 0);
366  else if (m_nettype == TESTNET)
367  m_hardfork = new HardFork(*db, 1, testnet_hard_fork_version_1_till);
368  else
369  m_hardfork = new HardFork(*db, 1, mainnet_hard_fork_version_1_till);
370  }
371  if (m_nettype == FAKECHAIN)
372  {
373  for (size_t n = 0; test_options->hard_forks[n].first; ++n)
374  m_hardfork->add_fork(test_options->hard_forks[n].first, test_options->hard_forks[n].second, 0, n + 1);
375  }
376  else if (m_nettype == TESTNET)
377  {
378  for (size_t n = 0; n < sizeof(testnet_hard_forks) / sizeof(testnet_hard_forks[0]); ++n)
379  m_hardfork->add_fork(testnet_hard_forks[n].version, testnet_hard_forks[n].height, testnet_hard_forks[n].threshold, testnet_hard_forks[n].time);
380  }
381  else if (m_nettype == STAGENET)
382  {
383  for (size_t n = 0; n < sizeof(stagenet_hard_forks) / sizeof(stagenet_hard_forks[0]); ++n)
384  m_hardfork->add_fork(stagenet_hard_forks[n].version, stagenet_hard_forks[n].height, stagenet_hard_forks[n].threshold, stagenet_hard_forks[n].time);
385  }
386  else
387  {
388  for (size_t n = 0; n < sizeof(mainnet_hard_forks) / sizeof(mainnet_hard_forks[0]); ++n)
389  m_hardfork->add_fork(mainnet_hard_forks[n].version, mainnet_hard_forks[n].height, mainnet_hard_forks[n].threshold, mainnet_hard_forks[n].time);
390  }
391  m_hardfork->init();
392 
393  m_db->set_hard_fork(m_hardfork);
394 
395  // if the blockchain is new, add the genesis block
396  // this feels kinda kludgy to do it this way, but can be looked at later.
397  // TODO: add function to create and store genesis block,
398  // taking testnet into account
399  if(!m_db->height())
400  {
401  MINFO("Blockchain not loaded, generating genesis block.");
402  block bl;
403  block_verification_context bvc = boost::value_initialized<block_verification_context>();
405  db_wtxn_guard wtxn_guard(m_db);
406  add_new_block(bl, bvc);
407  CHECK_AND_ASSERT_MES(!bvc.m_verification_failed, false, "Failed to add genesis block to blockchain");
408  }
409  // TODO: if blockchain load successful, verify blockchain against both
410  // hard-coded and runtime-loaded (and enforced) checkpoints.
411  else
412  {
413  }
414 
415  if (m_nettype != FAKECHAIN)
416  {
417  m_db->set_batch_transactions(true);
418  }
419 
420  db_rtxn_guard rtxn_guard(m_db);
421 
422  // check how far behind we are
423  uint64_t top_block_timestamp = m_db->get_top_block_timestamp();
424  uint64_t timestamp_diff = time(NULL) - top_block_timestamp;
425 
426  // genesis block has no timestamp, could probably change it to have timestamp of 1397818133...
427  if(!top_block_timestamp)
428  timestamp_diff = time(NULL) - 1397818133;
429 
430  // create general purpose async service queue
431 
432  m_async_work_idle = std::unique_ptr < boost::asio::io_service::work > (new boost::asio::io_service::work(m_async_service));
433  // we only need 1
434  m_async_pool.create_thread(boost::bind(&boost::asio::io_service::run, &m_async_service));
435 
436 #if defined(PER_BLOCK_CHECKPOINT)
437  if (m_nettype != FAKECHAIN)
438  load_compiled_in_block_hashes(get_checkpoints);
439 #endif
440 
441  MINFO("Blockchain initialized. last block: " << m_db->height() - 1 << ", " << epee::misc_utils::get_time_interval_string(timestamp_diff) << " time ago, current difficulty: " << get_difficulty_for_next_block());
442 
443  rtxn_guard.stop();
444 
445  uint64_t num_popped_blocks = 0;
446  while (!m_db->is_read_only())
447  {
448  uint64_t top_height;
449  const crypto::hash top_id = m_db->top_block_hash(&top_height);
450  const block top_block = m_db->get_top_block();
451  const uint8_t ideal_hf_version = get_ideal_hard_fork_version(top_height);
452  if (ideal_hf_version <= 1 || ideal_hf_version == top_block.major_version)
453  {
454  if (num_popped_blocks > 0)
455  MGINFO("Initial popping done, top block: " << top_id << ", top height: " << top_height << ", block version: " << (uint64_t)top_block.major_version);
456  break;
457  }
458  else
459  {
460  if (num_popped_blocks == 0)
461  MGINFO("Current top block " << top_id << " at height " << top_height << " has version " << (uint64_t)top_block.major_version << " which disagrees with the ideal version " << (uint64_t)ideal_hf_version);
462  if (num_popped_blocks % 100 == 0)
463  MGINFO("Popping blocks... " << top_height);
464  ++num_popped_blocks;
465  block popped_block;
466  std::vector<transaction> popped_txs;
467  try
468  {
469  m_db->pop_block(popped_block, popped_txs);
470  }
471  // anything that could cause this to throw is likely catastrophic,
472  // so we re-throw
473  catch (const std::exception& e)
474  {
475  MERROR("Error popping block from blockchain: " << e.what());
476  throw;
477  }
478  catch (...)
479  {
480  MERROR("Error popping block from blockchain, throwing!");
481  throw;
482  }
483  }
484  }
485 
486  if (num_popped_blocks > 0)
487  {
488  m_timestamps_and_difficulties_height = 0;
490  uint64_t top_block_height;
491  crypto::hash top_block_hash = get_tail_id(top_block_height);
492  m_tx_pool.on_blockchain_dec(top_block_height, top_block_hash);
493  }
494 
496  {
497  m_long_term_block_weights_window = test_options->long_term_block_weight_window;
498  m_long_term_block_weights_cache_rolling_median = epee::misc_utils::rolling_median_t<uint64_t>(m_long_term_block_weights_window);
499  }
500 
501  {
502  db_txn_guard txn_guard(m_db, m_db->is_read_only());
503  if (!update_next_cumulative_weight_limit())
504  return false;
505  }
506 
507  {
508  if(!m_db->is_read_only())
509  {
510  uint64_t top_height;
511  m_db->top_block_hash(&top_height);
512 
513  if(top_height >= 1175315)
514  {
515  block b = m_db->get_block_from_height(1175315);
516  const auto &txout = boost::get<txout_to_key_public>(b.miner_tx.vout[0].target);
517  std::vector<cryptonote::address_outputs> addr_outs = m_db->get_addr_output_all(addKeys(txout.address.m_view_public_key, txout.address.m_spend_public_key));
518 
519  if(addr_outs.empty()) {
520  MGINFO("Recomputing address_outputs database...");
521  m_db->top_block_hash(&top_height);
522  uint64_t diff = top_height - 1175200;
523  for(auto i = 0; i < diff; i++) {
524  block popped_block;
525  std::vector<transaction> popped_txs;
526  try
527  {
528  m_db->pop_block(popped_block, popped_txs);
529  }
530  catch (const std::exception& e)
531  {
532  MERROR("Error popping block from blockchain: " << e.what());
533  throw;
534  }
535  catch (...)
536  {
537  MERROR("Error popping block from blockchain, throwing!");
538  throw;
539  }
540  }
541  if (diff > 0)
542  {
544  uint64_t top_block_height;
545  crypto::hash top_block_hash = get_tail_id(top_block_height);
546  m_tx_pool.on_blockchain_dec(top_block_height, top_block_hash);
547  }
548  MGINFO("Address_outputs database recomputed OK");
549  }
550  }
551  }
552  }
553 
554  // GO BACK AND POPULATE A DATABASE OF KEY: COMBINED KEY , VALUE: TX INPUT
555  {
556  db_txn_guard txn_guard(m_db, m_db->is_read_only());
557  if(!m_db->is_read_only())
558  {
559  uint64_t top_height;
560  m_db->top_block_hash(&top_height);
561  uint64_t private_to_public_fork_height = m_nettype == MAINNET ? 1175315 : 1086402;
562  if(top_height >= private_to_public_fork_height)
563  {
564  block b = m_db->get_block_from_height(private_to_public_fork_height);
565  const auto &txout = boost::get<txout_to_key_public>(b.miner_tx.vout[0].target);
566  std::vector<cryptonote::address_txs> addr_txs = m_db->get_addr_tx_all(addKeys(txout.address.m_view_public_key, txout.address.m_spend_public_key));
567  if(addr_txs.empty()) {
568  MGINFO("Populating addr tx database...");
569  m_db->top_block_hash(&top_height);
570  // begin at the private to public fork block and store the data in addr_tx db one block at a time
571  uint64_t working_height = private_to_public_fork_height;
572  while (working_height <= top_height) {
573  block working_block = m_db->get_block_from_height(working_height);
574  //deal with miner tx first
575  for( auto vout: working_block.miner_tx.vout){ // all vouts are of type txout to key public
576  const auto &txout = boost::get<txout_to_key_public>(vout.target);
577  m_db->add_addr_tx(get_transaction_hash(working_block.miner_tx), addKeys(txout.address.m_view_public_key, txout.address.m_spend_public_key));
578 
579  }
580  //deal with all other tx
581  std::vector<transaction> transactions = m_db->get_tx_list(working_block.tx_hashes);
582  for (auto tx : transactions){
583  auto hash = get_transaction_hash(tx);
584  std::unordered_set<crypto::public_key> addr_tx_addresses;
585  for (size_t i = 0; i < tx.vin.size(); i++){
586  if (tx.vin[i].type() == typeid(txin_to_key_public))
587  {
588  const auto &txin = boost::get<txin_to_key_public>(tx.vin[i]);
589  transaction parent_tx = m_db->get_tx(txin.tx_hash);
590  const auto &txout = boost::get<txout_to_key_public>(parent_tx.vout[txin.relative_offset].target); //previous tx out that this tx in references
591  crypto::public_key combined_key = addKeys(txout.address.m_view_public_key, txout.address.m_spend_public_key);
592  if(addr_tx_addresses.find(combined_key) == addr_tx_addresses.end()){ //if addr hasn't been used for another input yet, add the unique addr tx record for this address
593  m_db->add_addr_tx(hash, combined_key);
594  addr_tx_addresses.emplace(combined_key);
595  }
596  }
597  }
598  for(size_t i = 0; i < tx.vout.size(); i++){ // all vouts are of type txout to key public
599  const auto &txout = boost::get<txout_to_key_public>(tx.vout[i].target);
600  crypto::public_key combined_key = addKeys(txout.address.m_view_public_key, txout.address.m_spend_public_key);
601  if(addr_tx_addresses.find(combined_key) == addr_tx_addresses.end()){ //if addr hasn't been used for another input yet, add the unique addr tx record for this address
602  m_db->add_addr_tx(tx.hash, combined_key);
603  addr_tx_addresses.emplace(combined_key);
604  }
605  }
606  }
607  ++working_height;
608  }
609  MGINFO("Addr_txs database recomputed OK");
610  }
611 
612  }
613  }
614 
615  txn_guard.stop();
616  }
617  return true;
618 }
#define CRITICAL_REGION_LOCAL1(x)
Definition: syncobj.h:230
#define MERROR(x)
Definition: misc_log_ex.h:73
const config_t & get_config(network_type nettype)
std::vector< crypto::hash > tx_hashes
bool reorganize_from_chain_height(uint64_t height)
Definition: hardfork.cpp:242
#define MINFO(x)
Definition: misc_log_ex.h:75
#define CHECK_AND_ASSERT_MES(expr, fail_ret_val, message)
Definition: misc_log_ex.h:181
void init()
initialize the object
Definition: hardfork.cpp:169
virtual std::vector< address_txs > get_addr_tx_all(const crypto::public_key &combined_key)=0
public_key addKeys(const public_key &A, const public_key &B)
Definition: crypto.h:339
uint64_t get_current_blockchain_height() const
get the current height of the blockchain
Definition: blockchain.cpp:322
unsigned char uint8_t
Definition: stdint.h:124
virtual void set_batch_transactions(bool)=0
sets whether or not to batch transactions
bool add_new_block(const block &bl_, block_verification_context &bvc)
adds a block to the blockchain
#define MGINFO(x)
Definition: misc_log_ex.h:80
virtual std::vector< address_outputs > get_addr_output_all(const crypto::public_key &combined_key)=0
time_t time
Definition: blockchain.cpp:93
crypto::hash get_tail_id() const
get the hash of the most recent block on the blockchain
Definition: blockchain.cpp:837
bool generate_genesis_block(block &bl, std::string const &genesis_tx, uint32_t nonce)
virtual block get_block_from_height(const uint64_t &height) const
fetch a block by height
virtual bool is_read_only() const =0
is BlockchainDB in read-only mode?
std::string const GENESIS_TX
virtual transaction get_tx(const crypto::hash &h) const
fetches the transaction with the given hash
unsigned __int64 uint64_t
Definition: stdint.h:136
std::string get_time_interval_string(const time_t &time_)
Definition: time_helper.h:120
#define CRITICAL_REGION_LOCAL(x)
Definition: syncobj.h:228
difficulty_type get_difficulty_for_next_block()
returns the difficulty target the next block to be added must meet
Definition: blockchain.cpp:971
virtual block get_top_block() const =0
fetch the top block
virtual uint64_t height() const =0
fetch the current blockchain height
virtual void add_addr_tx(const crypto::hash tx_hash, const crypto::public_key &combined_key)=0
#define LOG_PRINT_L3(x)
Definition: misc_log_ex.h:102
POD_CLASS public_key
Definition: crypto.h:76
bool is_open() const
Gets the current open/ready state of the BlockchainDB.
virtual void set_hard_fork(HardFork *hf)
#define LOG_ERROR(x)
Definition: misc_log_ex.h:98
virtual crypto::hash top_block_hash(uint64_t *block_height=NULL) const =0
fetch the top block&#39;s hash
uint8_t get_ideal_hard_fork_version() const
returns the newest hardfork version known to the blockchain
Definition: blockchain.h:832
crypto::hash get_transaction_hash(const transaction &t)
uint32_t const GENESIS_NONCE
virtual std::vector< transaction > get_tx_list(const std::vector< crypto::hash > &hlist) const =0
fetches a list of transactions based on their hashes
POD_CLASS hash
Definition: hash.h:50
bool add_fork(uint8_t version, uint64_t height, uint8_t threshold, time_t time)
add a new hardfork height
Definition: hardfork.cpp:74
bool on_blockchain_dec(uint64_t new_block_height, const crypto::hash &top_block_id)
action to take when notified of a block removed from the blockchain
Definition: tx_pool.cpp:1188
const std::pair< uint8_t, uint64_t > * hard_forks
virtual uint64_t get_top_block_timestamp() const =0
fetch the top block&#39;s timestamp
const size_t long_term_block_weight_window
Here is the call graph for this function:
Here is the caller graph for this function:

◆ init() [2/2]

bool Blockchain::init ( BlockchainDB db,
HardFork *&  hf,
const network_type  nettype = MAINNET,
bool  offline = false 
)

Initialize the Blockchain state.

Parameters
dba pointer to the backing store to use for the blockchain
hfa structure containing hardfork information
nettypenetwork type
offlinetrue if running offline, else false
Returns
true on success, false if any initialization steps fail

Definition at line 620 of file blockchain.cpp.

621 {
622  if (hf != nullptr)
623  m_hardfork = hf;
624  bool res = init(db, nettype, offline, NULL);
625  if (hf == nullptr)
626  hf = m_hardfork;
627  return res;
628 }
const char * res
Definition: hmac_keccak.cpp:41
bool init(BlockchainDB *db, const network_type nettype=MAINNET, bool offline=false, const cryptonote::test_options *test_options=NULL, difficulty_type fixed_difficulty=0, const GetCheckpointsCallback &get_checkpoints=nullptr, bool ignore_bsig=false, bool fallback_to_pow=false)
Initialize the Blockchain state.
Definition: blockchain.cpp:334
Here is the call graph for this function:

◆ is_within_compiled_block_hash_area() [1/2]

bool Blockchain::is_within_compiled_block_hash_area ( uint64_t  height) const

Definition at line 5022 of file blockchain.cpp.

5023 {
5024 #if defined(PER_BLOCK_CHECKPOINT)
5025  return height < m_blocks_hash_check.size();
5026 #else
5027  return false;
5028 #endif
5029 }
uint64_t height
Definition: blockchain.cpp:91

◆ is_within_compiled_block_hash_area() [2/2]

bool cryptonote::Blockchain::is_within_compiled_block_hash_area ( ) const
inline

Definition at line 1016 of file blockchain.h.

1016 { return is_within_compiled_block_hash_area(m_db->height()); }
bool is_within_compiled_block_hash_area() const
Definition: blockchain.h:1016
virtual uint64_t height() const =0
fetch the current blockchain height
Here is the call graph for this function:
Here is the caller graph for this function:

◆ key_images_already_spent()

bool Blockchain::key_images_already_spent ( const transaction tx) const

check if any key image in a transaction has already been spent

Parameters
txthe transaction to check
Returns
true if any key image is already spent in the blockchain, else false

Definition at line 2958 of file blockchain.cpp.

2959 {
2960  LOG_PRINT_L3("Blockchain::" << __func__);
2961 
2962  for (const txin_v& in: tx.vin)
2963  {
2964  if(in.type() == typeid(txin_to_key))
2965  {
2966  const auto &in_to_key = boost::get<txin_to_key>(in);
2967  if(have_tx_keyimg_as_spent(in_to_key.k_image))
2968  return true;
2969  }
2970  }
2971 
2972  return false;
2973 }
boost::variant< txin_gen, txin_to_script, txin_to_scripthash, txin_to_key, txin_to_key_public > txin_v
#define LOG_PRINT_L3(x)
Definition: misc_log_ex.h:102
bool have_tx_keyimg_as_spent(const crypto::key_image &key_im) const
check if a key image is already spent on the blockchain
Definition: blockchain.cpp:177
Here is the call graph for this function:

◆ lock()

void Blockchain::lock ( void  )

Definition at line 5031 of file blockchain.cpp.

5032 {
5033  m_blockchain_lock.lock();
5034 }
Here is the call graph for this function:

◆ normalize_v7_difficulties()

void Blockchain::normalize_v7_difficulties ( )

Normalize the cumulative difficulty for V7 blocks, fixing the differing difficulty among nodes.

Definition at line 1098 of file blockchain.cpp.

1098  {
1099 
1100  auto height = m_db->height();
1101  const uint64_t v8height = m_nettype == TESTNET ? 446674 : 589169;
1102 
1103  if(height != v8height) {
1104  return;
1105  }
1106 
1107  const uint64_t v7height = m_nettype == TESTNET ? 215000 : 324500;
1108  const size_t V7_DIFFICULTY_BLOCKS_COUNT = 735;
1109  const size_t V7_DIFFICULTY_TARGET = 120;
1110 
1111  std::vector<uint64_t> timestamps;
1112  std::vector<difficulty_type> difficulties;
1113 
1114  uint64_t start_height = v7height - V7_DIFFICULTY_BLOCKS_COUNT;
1115 
1116  // Populate the timestamps & difficulties vectors with data from 735 blocks prior to V7 fork height (324500)
1117  for(uint64_t i = 0; start_height + i < v7height; i++) {
1118  timestamps.push_back(m_db->get_block_timestamp(start_height + i));
1119  difficulties.push_back(m_db->get_block_cumulative_difficulty(start_height + i));
1120  }
1121 
1122  // Calculate the cumulative difficulty of block 324500 based on the 735 prior blocks' timestamp and difficulty values
1123  difficulty_type diff = difficulties.back() + next_difficulty(timestamps, difficulties, V7_DIFFICULTY_TARGET, 1);
1124 
1125  // Override block's 324500 cumulative difficulty
1126  m_db->set_block_cumulative_difficulty(v7height, diff);
1127 
1128  // Iterate over V7 blocks, starting from 324500 until current block height
1129  for(uint64_t i = v7height; i < height - 1; i++) {
1130 
1131  // Add "324500 + i" timestamp & difficulty into the vectors
1132  timestamps.push_back(m_db->get_block_timestamp(i));
1133  difficulties.push_back(m_db->get_block_cumulative_difficulty(i));
1134 
1135  // Erase the vector's first position maintaining its 735 size
1136  timestamps.erase(timestamps.begin());
1137  difficulties.erase(difficulties.begin());
1138 
1139  // Calculate/set the correct cumulative difficulty of block "324500 + i"
1140  diff = difficulties.back() + next_difficulty(timestamps, difficulties, V7_DIFFICULTY_TARGET, 1);
1141  m_db->set_block_cumulative_difficulty(i + 1, diff);
1142  }
1143 
1144  m_timestamps.clear();
1145  m_difficulties.clear();
1146 }
difficulty_type next_difficulty(std::vector< uint64_t > timestamps, std::vector< difficulty_type > cumulative_difficulties, size_t target_seconds, uint8_t version)
Definition: difficulty.cpp:210
virtual uint64_t get_block_timestamp(const uint64_t &height) const =0
fetch a block&#39;s timestamp
uint64_t height
Definition: blockchain.cpp:91
virtual difficulty_type get_block_cumulative_difficulty(const uint64_t &height) const =0
fetch a block&#39;s cumulative difficulty
virtual void set_block_cumulative_difficulty(uint64_t height, difficulty_type diff)=0
sets a block&#39;s cumulative difficulty
unsigned __int64 uint64_t
Definition: stdint.h:136
virtual uint64_t height() const =0
fetch the current blockchain height
boost::multiprecision::uint128_t difficulty_type
Definition: difficulty.h:43
Here is the call graph for this function:

◆ on_new_tx_from_block()

void Blockchain::on_new_tx_from_block ( const cryptonote::transaction tx)

called when we see a tx originating from a block

Used for handling txes from historical blocks in a fast way

Definition at line 2843 of file blockchain.cpp.

2844 {
2845 #if defined(PER_BLOCK_CHECKPOINT)
2846  // check if we're doing per-block checkpointing
2847  if (m_db->height() < m_blocks_hash_check.size())
2848  {
2850  m_blocks_txs_check.push_back(get_transaction_hash(tx));
2852  if(m_show_time_stats)
2853  {
2854  size_t ring_size = !tx.vin.empty() && tx.vin[0].type() == typeid(txin_to_key) ? boost::get<txin_to_key>(tx.vin[0]).key_offsets.size() : 0;
2855  MINFO("HASH: " << "-" << " I/M/O: " << tx.vin.size() << "/" << ring_size << "/" << tx.vout.size() << " H: " << 0 << " chcktx: " << a);
2856  }
2857  }
2858 #endif
2859 }
#define MINFO(x)
Definition: misc_log_ex.h:75
virtual uint64_t height() const =0
fetch the current blockchain height
#define TIME_MEASURE_START(var_name)
Definition: profile_tools.h:61
#define TIME_MEASURE_FINISH(var_name)
Definition: profile_tools.h:64
const GenericPointer< typename T::ValueType > T2 T::AllocatorType & a
Definition: pointer.h:1124
crypto::hash get_transaction_hash(const transaction &t)
Here is the call graph for this function:
Here is the caller graph for this function:

◆ output_scan_worker()

void Blockchain::output_scan_worker ( const uint64_t  amount,
const std::vector< uint64_t > &  offsets,
std::vector< output_data_t > &  outputs 
) const

get a number of outputs of a specific amount

Parameters
amountthe amount
offsetsthe indices (indexed to the amount) of the outputs
outputsreturn-by-reference the outputs collected

Definition at line 4396 of file blockchain.cpp.

4397 {
4398  try
4399  {
4400  m_db->get_output_key(epee::span<const uint64_t>(&amount, 1), offsets, outputs, true);
4401  }
4402  catch (const std::exception& e)
4403  {
4404  MERROR_VER("EXCEPTION: " << e.what());
4405  }
4406  catch (...)
4407  {
4408 
4409  }
4410 }
Non-owning sequence of data. Does not deep copy.
Definition: span.h:56
#define MERROR_VER(x)
Definition: blockchain.cpp:84
virtual output_data_t get_output_key(const uint64_t &amount, const uint64_t &index, bool include_commitmemt=true) const =0
get some of an output&#39;s data
Here is the call graph for this function:
Here is the caller graph for this function:

◆ pop_blocks()

void Blockchain::pop_blocks ( uint64_t  nblocks)

removes blocks from the top of the blockchain

Parameters
nblocksnumber of blocks to be removed

Definition at line 700 of file blockchain.cpp.

701 {
702  uint64_t i;
703  CRITICAL_REGION_LOCAL(m_tx_pool);
704  CRITICAL_REGION_LOCAL1(m_blockchain_lock);
705 
706  bool stop_batch = m_db->batch_start();
707 
708  try
709  {
710  const uint64_t blockchain_height = m_db->height();
711  if (blockchain_height > 0)
712  nblocks = std::min(nblocks, blockchain_height - 1);
713  for (i=0; i < nblocks; ++i)
714  {
715  pop_block_from_blockchain();
716  }
717  }
718  catch (const std::exception& e)
719  {
720  LOG_ERROR("Error when popping blocks after processing " << i << " blocks: " << e.what());
721  if (stop_batch)
722  m_db->batch_abort();
723  return;
724  }
725 
726  if (stop_batch)
727  m_db->batch_stop();
728 }
#define CRITICAL_REGION_LOCAL1(x)
Definition: syncobj.h:230
virtual void batch_abort()=0
aborts a batch transaction
unsigned __int64 uint64_t
Definition: stdint.h:136
#define CRITICAL_REGION_LOCAL(x)
Definition: syncobj.h:228
virtual uint64_t height() const =0
fetch the current blockchain height
virtual void batch_stop()=0
ends a batch transaction
#define LOG_ERROR(x)
Definition: misc_log_ex.h:98
virtual bool batch_start(uint64_t batch_num_blocks=0, uint64_t batch_bytes=0)=0
tells the BlockchainDB to start a new "batch" of blocks
Here is the call graph for this function:

◆ prepare_handle_incoming_blocks()

bool Blockchain::prepare_handle_incoming_blocks ( const std::vector< block_complete_entry > &  blocks_entry,
std::vector< block > &  blocks 
)

performs some preprocessing on a group of incoming blocks to speed up verification

Parameters
blocks_entrya list of incoming blocks
blocksthe parsed blocks
Returns
false on erroneous blocks, else true

Definition at line 4419 of file blockchain.cpp.

4420 {
4421  MTRACE("Blockchain::" << __func__);
4422  TIME_MEASURE_START(prepare);
4423  bool stop_batch;
4424  uint64_t bytes = 0;
4425  size_t total_txs = 0;
4426  blocks.clear();
4427 
4428  // Order of locking must be:
4429  // m_incoming_tx_lock (optional)
4430  // m_tx_pool lock
4431  // blockchain lock
4432  //
4433  // Something which takes the blockchain lock may never take the txpool lock
4434  // if it has not provably taken the txpool lock earlier
4435  //
4436  // The txpool lock is now taken in prepare_handle_incoming_blocks
4437  // and released in cleanup_handle_incoming_blocks. This avoids issues
4438  // when something uses the pool, which now uses the blockchain and
4439  // needs a batch, since a batch could otherwise be active while the
4440  // txpool and blockchain locks were not held
4441 
4442  m_tx_pool.lock();
4443  CRITICAL_REGION_LOCAL1(m_blockchain_lock);
4444 
4445  if(blocks_entry.size() == 0)
4446  return false;
4447 
4448  for (const auto &entry : blocks_entry)
4449  {
4450  bytes += entry.block.size();
4451  for (const auto &tx_blob : entry.txs)
4452  {
4453  bytes += tx_blob.size();
4454  }
4455  total_txs += entry.txs.size();
4456  }
4457  m_bytes_to_sync += bytes;
4458  while (!(stop_batch = m_db->batch_start(blocks_entry.size(), bytes))) {
4459  m_blockchain_lock.unlock();
4460  m_tx_pool.unlock();
4462  m_tx_pool.lock();
4463  m_blockchain_lock.lock();
4464  }
4465  m_batch_success = true;
4466 
4467  const uint64_t height = m_db->height();
4468  if ((height + blocks_entry.size()) < m_blocks_hash_check.size())
4469  return true;
4470 
4471  bool blocks_exist = false;
4473  unsigned threads = tpool.get_max_concurrency();
4474  blocks.resize(blocks_entry.size());
4475 
4476  if (1)
4477  {
4478  // limit threads, default limit = 4
4479  if(threads > m_max_prepare_blocks_threads)
4480  threads = m_max_prepare_blocks_threads;
4481 
4482  unsigned int batches = blocks_entry.size() / threads;
4483  unsigned int extra = blocks_entry.size() % threads;
4484  MDEBUG("block_batches: " << batches);
4485  std::vector<std::unordered_map<crypto::hash, crypto::hash>> maps(threads);
4486  auto it = blocks_entry.begin();
4487  unsigned blockidx = 0;
4488 
4489  const crypto::hash tophash = m_db->top_block_hash();
4490  for (unsigned i = 0; i < threads; i++)
4491  {
4492  for (unsigned int j = 0; j < batches; j++, ++blockidx)
4493  {
4494  block &block = blocks[blockidx];
4495  crypto::hash block_hash;
4496 
4497  if (!parse_and_validate_block_from_blob(it->block, block, block_hash))
4498  return false;
4499 
4500  // check first block and skip all blocks if its not chained properly
4501  if (blockidx == 0)
4502  {
4503  if (block.prev_id != tophash)
4504  {
4505  MDEBUG("Skipping prepare blocks. New blocks don't belong to chain.");
4506  blocks.clear();
4507  return true;
4508  }
4509  }
4510  if (have_block(block_hash))
4511  blocks_exist = true;
4512 
4513  std::advance(it, 1);
4514  }
4515  }
4516 
4517  for (unsigned i = 0; i < extra && !blocks_exist; i++, blockidx++)
4518  {
4519  block &block = blocks[blockidx];
4520  crypto::hash block_hash;
4521 
4522  if (!parse_and_validate_block_from_blob(it->block, block, block_hash))
4523  return false;
4524 
4525  if (have_block(block_hash))
4526  blocks_exist = true;
4527 
4528  std::advance(it, 1);
4529  }
4530 
4531  if (!blocks_exist)
4532  {
4533  m_blocks_longhash_table.clear();
4534  uint64_t thread_height = height;
4536  for (unsigned int i = 0; i < threads; i++)
4537  {
4538  unsigned nblocks = batches;
4539  if (i < extra)
4540  ++nblocks;
4541  tpool.submit(&waiter, boost::bind(&Blockchain::block_longhash_worker, this, thread_height, epee::span<const block>(&blocks[thread_height - height], nblocks), std::ref(maps[i])), true);
4542  thread_height += nblocks;
4543  }
4544 
4545  waiter.wait(&tpool);
4546 
4547  if (m_cancel)
4548  return false;
4549 
4550  for (const auto & map : maps)
4551  {
4552  m_blocks_longhash_table.insert(map.begin(), map.end());
4553  }
4554  }
4555  }
4556 
4557  if (m_cancel)
4558  return false;
4559 
4560  if (blocks_exist)
4561  {
4562  MDEBUG("Skipping remainder of prepare blocks. Blocks exist.");
4563  return true;
4564  }
4565 
4566  m_fake_scan_time = 0;
4567  m_fake_pow_calc_time = 0;
4568 
4569  m_scan_table.clear();
4570  m_check_txin_table.clear();
4571 
4572  TIME_MEASURE_FINISH(prepare);
4573  m_fake_pow_calc_time = prepare / blocks_entry.size();
4574 
4575  if (blocks_entry.size() > 1 && threads > 1 && m_show_time_stats)
4576  MDEBUG("Prepare blocks took: " << prepare << " ms");
4577 
4578  TIME_MEASURE_START(scantable);
4579 
4580  // [input] stores all unique amounts found
4581  std::vector < uint64_t > amounts;
4582  // [input] stores all absolute_offsets for each amount
4583  std::map<uint64_t, std::vector<uint64_t>> offset_map;
4584  // [output] stores all output_data_t for each absolute_offset
4585  std::map<uint64_t, std::vector<output_data_t>> tx_map;
4586  std::vector<std::pair<cryptonote::transaction, crypto::hash>> txes(total_txs);
4587 
4588 #define SCAN_TABLE_QUIT(m) \
4589  do { \
4590  MERROR_VER(m) ;\
4591  m_scan_table.clear(); \
4592  return false; \
4593  } while(0); \
4594 
4595  // generate sorted tables for all amounts and absolute offsets
4596  size_t tx_index = 0, block_index = 0;
4597  for (const auto &entry : blocks_entry)
4598  {
4599  if (m_cancel)
4600  return false;
4601 
4602  for (const auto &tx_blob : entry.txs)
4603  {
4604  if (tx_index >= txes.size())
4605  SCAN_TABLE_QUIT("tx_index is out of sync");
4606  transaction &tx = txes[tx_index].first;
4607  crypto::hash &tx_prefix_hash = txes[tx_index].second;
4608  ++tx_index;
4609 
4610  if (!parse_and_validate_tx_base_from_blob(tx_blob, tx))
4611  SCAN_TABLE_QUIT("Could not parse tx from incoming blocks.");
4612  cryptonote::get_transaction_prefix_hash(tx, tx_prefix_hash);
4613 
4614  auto its = m_scan_table.find(tx_prefix_hash);
4615  if (its != m_scan_table.end())
4616  SCAN_TABLE_QUIT("Duplicate tx found from incoming blocks.");
4617 
4618  m_scan_table.emplace(tx_prefix_hash, std::unordered_map<crypto::key_image, std::vector<output_data_t>>());
4619  its = m_scan_table.find(tx_prefix_hash);
4620  assert(its != m_scan_table.end());
4621 
4622  if(tx.version <= 2)
4623  {
4624  // get all amounts from tx.vin(s)
4625  for (const auto &txin : tx.vin)
4626  {
4627  const txin_to_key &in_to_key = boost::get < txin_to_key > (txin);
4628 
4629  // check for duplicate
4630  auto it = its->second.find(in_to_key.k_image);
4631  if (it != its->second.end())
4632  SCAN_TABLE_QUIT("Duplicate key_image found from incoming blocks.");
4633 
4634  amounts.push_back(in_to_key.amount);
4635  }
4636  }
4637 
4638  // sort and remove duplicate amounts from amounts list
4639  std::sort(amounts.begin(), amounts.end());
4640  auto last = std::unique(amounts.begin(), amounts.end());
4641  amounts.erase(last, amounts.end());
4642 
4643  // add amount to the offset_map and tx_map
4644  for (const uint64_t &amount : amounts)
4645  {
4646  if (offset_map.find(amount) == offset_map.end())
4647  offset_map.emplace(amount, std::vector<uint64_t>());
4648 
4649  if (tx_map.find(amount) == tx_map.end())
4650  tx_map.emplace(amount, std::vector<output_data_t>());
4651  }
4652 
4653  if(tx.version <= 2)
4654  {
4655  // add new absolute_offsets to offset_map
4656  for (const auto &txin : tx.vin)
4657  {
4658  const txin_to_key &in_to_key = boost::get < txin_to_key > (txin);
4659  // no need to check for duplicate here.
4660  auto absolute_offsets = relative_output_offsets_to_absolute(in_to_key.key_offsets);
4661  for (const auto & offset : absolute_offsets)
4662  offset_map[in_to_key.amount].push_back(offset);
4663 
4664  }
4665  }
4666  }
4667  ++block_index;
4668  }
4669 
4670  // sort and remove duplicate absolute_offsets in offset_map
4671  for (auto &offsets : offset_map)
4672  {
4673  std::sort(offsets.second.begin(), offsets.second.end());
4674  auto last = std::unique(offsets.second.begin(), offsets.second.end());
4675  offsets.second.erase(last, offsets.second.end());
4676  }
4677 
4678  // gather all the output keys
4679  threads = tpool.get_max_concurrency();
4680  if (!m_db->can_thread_bulk_indices())
4681  threads = 1;
4682 
4683  if (threads > 1 && amounts.size() > 1)
4684  {
4686 
4687  for (size_t i = 0; i < amounts.size(); i++)
4688  {
4689  uint64_t amount = amounts[i];
4690  tpool.submit(&waiter, boost::bind(&Blockchain::output_scan_worker, this, amount, std::cref(offset_map[amount]), std::ref(tx_map[amount])), true);
4691  }
4692  waiter.wait(&tpool);
4693  }
4694  else
4695  {
4696  for (size_t i = 0; i < amounts.size(); i++)
4697  {
4698  uint64_t amount = amounts[i];
4699  output_scan_worker(amount, offset_map[amount], tx_map[amount]);
4700  }
4701  }
4702 
4703  // now generate a table for each tx_prefix and k_image hashes
4704  tx_index = 0;
4705  for (const auto &entry : blocks_entry)
4706  {
4707  if (m_cancel)
4708  return false;
4709 
4710  for (const auto &tx_blob : entry.txs)
4711  {
4712  if (tx_index >= txes.size())
4713  SCAN_TABLE_QUIT("tx_index is out of sync");
4714  const transaction &tx = txes[tx_index].first;
4715  const crypto::hash &tx_prefix_hash = txes[tx_index].second;
4716  ++tx_index;
4717 
4718  auto its = m_scan_table.find(tx_prefix_hash);
4719  if (its == m_scan_table.end())
4720  SCAN_TABLE_QUIT("Tx not found on scan table from incoming blocks.");
4721 
4722  if(tx.version >= 3) continue;
4723 
4724  for (const auto &txin : tx.vin)
4725  {
4726  const txin_to_key &in_to_key = boost::get < txin_to_key > (txin);
4727  auto needed_offsets = relative_output_offsets_to_absolute(in_to_key.key_offsets);
4728 
4729  std::vector<output_data_t> outputs;
4730  for (const uint64_t & offset_needed : needed_offsets)
4731  {
4732  size_t pos = 0;
4733  bool found = false;
4734 
4735  for (const uint64_t &offset_found : offset_map[in_to_key.amount])
4736  {
4737  if (offset_needed == offset_found)
4738  {
4739  found = true;
4740  break;
4741  }
4742 
4743  ++pos;
4744  }
4745 
4746  if (found && pos < tx_map[in_to_key.amount].size())
4747  outputs.push_back(tx_map[in_to_key.amount].at(pos));
4748  else
4749  break;
4750  }
4751 
4752  its->second.emplace(in_to_key.k_image, outputs);
4753  }
4754  }
4755  }
4756 
4757  TIME_MEASURE_FINISH(scantable);
4758  if (total_txs > 0)
4759  {
4760  m_fake_scan_time = scantable / total_txs;
4761  if(m_show_time_stats)
4762  MDEBUG("Prepare scantable took: " << scantable << " ms");
4763  }
4764 
4765  return true;
4766 }
#define CRITICAL_REGION_LOCAL1(x)
Definition: syncobj.h:230
#define MTRACE(x)
Definition: misc_log_ex.h:77
A global thread pool.
Definition: threadpool.h:43
uint64_t height
Definition: blockchain.cpp:91
#define SCAN_TABLE_QUIT(m)
std::vector< uint64_t > key_offsets
Non-owning sequence of data. Does not deep copy.
Definition: span.h:56
std::vector< uint64_t > relative_output_offsets_to_absolute(const std::vector< uint64_t > &off)
static threadpool & getInstance()
Definition: threadpool.h:46
#define MDEBUG(x)
Definition: misc_log_ex.h:76
void wait(threadpool *tpool)
Definition: threadpool.cpp:115
void block_longhash_worker(uint64_t height, const epee::span< const block > &blocks, std::unordered_map< crypto::hash, crypto::hash > &map) const
computes the "short" and "long" hashes for a set of blocks
virtual bool can_thread_bulk_indices() const =0
unsigned int get_max_concurrency() const
Definition: threadpool.cpp:92
unsigned __int64 uint64_t
Definition: stdint.h:136
virtual uint64_t height() const =0
fetch the current blockchain height
#define TIME_MEASURE_START(var_name)
Definition: profile_tools.h:61
bool sleep_no_w(long ms)
bool parse_and_validate_tx_base_from_blob(const blobdata &tx_blob, transaction &tx)
#define TIME_MEASURE_FINISH(var_name)
Definition: profile_tools.h:64
void output_scan_worker(const uint64_t amount, const std::vector< uint64_t > &offsets, std::vector< output_data_t > &outputs) const
get a number of outputs of a specific amount
void unlock() const
unlocks the transaction pool
Definition: tx_pool.cpp:1260
void submit(waiter *waiter, std::function< void()> f, bool leaf=false)
Definition: threadpool.cpp:69
void get_transaction_prefix_hash(const transaction_prefix &tx, crypto::hash &h)
virtual crypto::hash top_block_hash(uint64_t *block_height=NULL) const =0
fetch the top block&#39;s hash
bool have_block(const crypto::hash &id) const
checks if a block is known about with a given hash
POD_CLASS key_image
Definition: crypto.h:102
crypto::key_image k_image
POD_CLASS hash
Definition: hash.h:50
void lock() const
locks the transaction pool
Definition: tx_pool.cpp:1255
bool parse_and_validate_block_from_blob(const blobdata &b_blob, block &b, crypto::hash *block_hash)
virtual bool batch_start(uint64_t batch_num_blocks=0, uint64_t batch_bytes=0)=0
tells the BlockchainDB to start a new "batch" of blocks
Here is the call graph for this function:
Here is the caller graph for this function:

◆ prune_blockchain()

bool Blockchain::prune_blockchain ( uint32_t  pruning_seed = 0)

Definition at line 4073 of file blockchain.cpp.

4074 {
4075  m_tx_pool.lock();
4077  CRITICAL_REGION_LOCAL(m_blockchain_lock);
4078 
4079  return m_db->prune_blockchain(pruning_seed);
4080 }
auto_scope_leave_caller create_scope_leave_handler(t_scope_leave_handler f)
boost::shared_ptr< call_befor_die_base > auto_scope_leave_caller
#define CRITICAL_REGION_LOCAL(x)
Definition: syncobj.h:228
void unlock() const
unlocks the transaction pool
Definition: tx_pool.cpp:1260
virtual bool prune_blockchain(uint32_t pruning_seed=0)=0
prunes the blockchain
void lock() const
locks the transaction pool
Definition: tx_pool.cpp:1255
Here is the call graph for this function:
Here is the caller graph for this function:

◆ remove_txpool_tx()

void Blockchain::remove_txpool_tx ( const crypto::hash txid)

Definition at line 4778 of file blockchain.cpp.

4779 {
4780  m_db->remove_txpool_tx(txid);
4781 }
virtual void remove_txpool_tx(const crypto::hash &txid)=0
remove a txpool transaction
Here is the call graph for this function:
Here is the caller graph for this function:

◆ reset_and_set_genesis_block()

bool Blockchain::reset_and_set_genesis_block ( const block b)

clears the blockchain and starts a new one

Parameters
bthe first block in the new chain (the genesis block)
Returns
true on success, else false

Definition at line 812 of file blockchain.cpp.

813 {
814  LOG_PRINT_L3("Blockchain::" << __func__);
815  CRITICAL_REGION_LOCAL(m_blockchain_lock);
816  m_timestamps_and_difficulties_height = 0;
817  m_alternative_chains.clear();
818  invalidate_block_template_cache();
819  m_db->reset();
820  m_hardfork->init();
821 
822  db_wtxn_guard wtxn_guard(m_db);
823  block_verification_context bvc = boost::value_initialized<block_verification_context>();
824  add_new_block(b, bvc);
825  if (!update_next_cumulative_weight_limit())
826  return false;
827  return bvc.m_added_to_main_chain && !bvc.m_verification_failed;
828 }
void init()
initialize the object
Definition: hardfork.cpp:169
bool add_new_block(const block &bl_, block_verification_context &bvc)
adds a block to the blockchain
#define CRITICAL_REGION_LOCAL(x)
Definition: syncobj.h:228
#define LOG_PRINT_L3(x)
Definition: misc_log_ex.h:102
virtual void reset()=0
Remove everything from the BlockchainDB.
Here is the call graph for this function:
Here is the caller graph for this function:

◆ safesyncmode()

void Blockchain::safesyncmode ( const bool  onoff)

Put DB in safe sync mode.

Definition at line 4835 of file blockchain.cpp.

4836 {
4837  /* all of this is no-op'd if the user set a specific
4838  * --db-sync-mode at startup.
4839  */
4840  if (m_db_default_sync)
4841  {
4842  m_db->safesyncmode(onoff);
4843  m_db_sync_mode = onoff ? db_nosync : db_async;
4844  }
4845 }
handle syncing calls instead of the backing db, asynchronously
Definition: blockchain.h:81
virtual void safesyncmode(const bool onoff)=0
toggle safe syncs for the DB
Leave syncing up to the backing db (safest, but slowest because of disk I/O)
Definition: blockchain.h:82
Here is the call graph for this function:
Here is the caller graph for this function:

◆ set_block_notify()

void cryptonote::Blockchain::set_block_notify ( const std::shared_ptr< tools::Notify > &  notify)
inline

sets a block notify object to call for every new block

Parameters
notifythe notify object to call at every new block

Definition at line 785 of file blockchain.h.

785 { m_block_notify = notify; }

◆ set_checkpoints()

void cryptonote::Blockchain::set_checkpoints ( checkpoints &&  chk_pts)
inline

assign a set of blockchain checkpoint hashes

Parameters
chk_ptsthe set of checkpoints to assign

Definition at line 175 of file blockchain.h.

175 { m_checkpoints = chk_pts; }
Here is the caller graph for this function:

◆ set_enforce_dns_checkpoints()

void Blockchain::set_enforce_dns_checkpoints ( bool  enforce)

configure whether or not to enforce DNS-based checkpoints

Parameters
enforcethe new enforcement setting

Definition at line 4307 of file blockchain.cpp.

4308 {
4309  m_enforce_dns_checkpoints = enforce_checkpoints;
4310 }
Here is the caller graph for this function:

◆ set_reorg_notify()

void cryptonote::Blockchain::set_reorg_notify ( const std::shared_ptr< tools::Notify > &  notify)
inline

sets a reorg notify object to call for every reorg

Parameters
notifythe notify object to call at every reorg

Definition at line 792 of file blockchain.h.

792 { m_reorg_notify = notify; }

◆ set_show_time_stats()

void cryptonote::Blockchain::set_show_time_stats ( bool  stats)
inline

set whether or not to show/print time statistics

Parameters
statsthe new time stats setting

Definition at line 804 of file blockchain.h.

804 { m_show_time_stats = stats; }

◆ set_user_options()

void Blockchain::set_user_options ( uint64_t  maxthreads,
bool  sync_on_blocks,
uint64_t  sync_threshold,
blockchain_db_sync_mode  sync_mode,
bool  fast_sync,
std::string  validator_key 
)

Update the validators public key by fetching data from electroneum's endpoint.

Returns
true if successfull sets various performance options
Parameters
maxthreadsmax number of threads when preparing blocks for addition
sync_on_blockswhether to sync based on blocks or bytes
sync_thresholdnumber of blocks/bytes to cache before syncing to database
sync_modethe blockchain_db_sync_mode to use
fast_syncsync using built-in block hashes as trusted

Definition at line 4817 of file blockchain.cpp.

4818 {
4819  if (sync_mode == db_defaultsync)
4820  {
4821  m_db_default_sync = true;
4822  sync_mode = db_async;
4823  }
4824  m_db_sync_mode = sync_mode;
4825  m_fast_sync = fast_sync;
4826  m_db_sync_on_blocks = sync_on_blocks;
4827  m_db_sync_threshold = sync_threshold;
4828  m_max_prepare_blocks_threads = maxthreads;
4829 
4830  if(!validator_key.empty()) {
4831  m_validator_key = boost::algorithm::unhex(validator_key);
4832  }
4833 }
handle syncing calls instead of the backing db, asynchronously
Definition: blockchain.h:81
user didn&#39;t specify, use db_async
Definition: blockchain.h:79

◆ set_validator_key()

void cryptonote::Blockchain::set_validator_key ( std::string  key)
inline

set validator key

Definition at line 1064 of file blockchain.h.

1064 { m_validator_key = boost::algorithm::unhex(key); }
const char * key
Definition: hmac_keccak.cpp:39
Here is the caller graph for this function:

◆ set_validators_list_instance()

void cryptonote::Blockchain::set_validators_list_instance ( std::unique_ptr< electroneum::basic::Validators > &  v)
inline

Definition at line 1066 of file blockchain.h.

1066 { m_validators = v.get(); }

◆ sign_block()

void Blockchain::sign_block ( block b,
std::string  privateKey 
)

Digitally sign the block.

Parameters
bthe block to be digitally signed
privateKeykey to generate the signature

Definition at line 1811 of file blockchain.cpp.

1811  {
1812  crypto::hash tx_tree_hash = get_tx_tree_hash(b);
1813 
1814  std::string signature = crypto::sign_message(std::string(reinterpret_cast<char const*>(tx_tree_hash.data), sizeof(tx_tree_hash.data)), privateKey);
1815  if(signature.empty() || signature.size() != 64) {
1816  LOG_ERROR("The daemon has failed to digitally sign a block and therefore it cannot be accepted by the network. Please check your validator-key configuration before resuming mining.");
1817  return;
1818  }
1819 
1820  b.signature = std::vector<uint8_t>(signature.begin(), signature.end());
1821 }
::std::string string
Definition: gtest-port.h:1097
std::string privateKey
POD_CLASS signature
Definition: crypto.h:108
std::vector< uint8_t > signature
#define LOG_ERROR(x)
Definition: misc_log_ex.h:98
POD_CLASS hash
Definition: hash.h:50
void get_tx_tree_hash(const std::vector< crypto::hash > &tx_hashes, crypto::hash &h)
std::string sign_message(const std::string &message, const std::string &privateKey)
Definition: crypto.h:376
Here is the call graph for this function:
Here is the caller graph for this function:

◆ store_blockchain()

bool Blockchain::store_blockchain ( )

stores the blockchain

If Blockchain is handling storing of the blockchain (rather than BlockchainDB), this initiates a blockchain save.

Returns
true unless saving the blockchain fails

Definition at line 630 of file blockchain.cpp.

631 {
632  LOG_PRINT_L3("Blockchain::" << __func__);
633  // lock because the rpc_thread command handler also calls this
635 
637  // TODO: make sure sync(if this throws that it is not simply ignored higher
638  // up the call stack
639  try
640  {
641  m_db->sync();
642  }
643  catch (const std::exception& e)
644  {
645  MERROR(std::string("Error syncing blockchain db: ") + e.what() + "-- shutting down now to prevent issues!");
646  throw;
647  }
648  catch (...)
649  {
650  MERROR("There was an issue storing the blockchain, shutting down now to prevent issues!");
651  throw;
652  }
653 
655  if(m_show_time_stats)
656  MINFO("Blockchain stored OK, took: " << save << " ms");
657  return true;
658 }
#define MERROR(x)
Definition: misc_log_ex.h:73
#define MINFO(x)
Definition: misc_log_ex.h:75
void save(Archive &a, const std::unordered_map< h_key, hval > &x, const boost::serialization::version_type ver)
::std::string string
Definition: gtest-port.h:1097
epee::critical_section m_synchronization_lock
A lock, currently for when BlockchainLMDB needs to resize the backing db file.
#define CRITICAL_REGION_LOCAL(x)
Definition: syncobj.h:228
virtual void sync()=0
sync the BlockchainDB with disk
#define TIME_MEASURE_START(var_name)
Definition: profile_tools.h:61
#define LOG_PRINT_L3(x)
Definition: misc_log_ex.h:102
#define TIME_MEASURE_FINISH(var_name)
Definition: profile_tools.h:64
Here is the call graph for this function:
Here is the caller graph for this function:

◆ unlock()

void Blockchain::unlock ( void  )

Definition at line 5036 of file blockchain.cpp.

5037 {
5038  m_blockchain_lock.unlock();
5039 }
Here is the call graph for this function:

◆ update_blockchain_pruning()

bool Blockchain::update_blockchain_pruning ( )

Definition at line 4082 of file blockchain.cpp.

4083 {
4084  m_tx_pool.lock();
4086  CRITICAL_REGION_LOCAL(m_blockchain_lock);
4087 
4088  return m_db->update_pruning();
4089 }
virtual bool update_pruning()=0
prunes recent blockchain changes as needed, iff pruning is enabled
auto_scope_leave_caller create_scope_leave_handler(t_scope_leave_handler f)
boost::shared_ptr< call_befor_die_base > auto_scope_leave_caller
#define CRITICAL_REGION_LOCAL(x)
Definition: syncobj.h:228
void unlock() const
unlocks the transaction pool
Definition: tx_pool.cpp:1260
void lock() const
locks the transaction pool
Definition: tx_pool.cpp:1255
Here is the call graph for this function:
Here is the caller graph for this function:

◆ update_checkpoints()

bool Blockchain::update_checkpoints ( const std::string &  file_path,
bool  check_dns 
)

loads new checkpoints from a file and optionally from DNS

Parameters
file_paththe path of the file to look for and load checkpoints from
check_dnswhether or not to check for new DNS-based checkpoints
Returns
false if any enforced checkpoint type fails to load, otherwise true

Definition at line 4272 of file blockchain.cpp.

4273 {
4274  if (!m_checkpoints.load_checkpoints_from_json(file_path))
4275  {
4276  return false;
4277  }
4278 
4279  // if we're checking both dns and json, load checkpoints from dns.
4280  // if we're not hard-enforcing dns checkpoints, handle accordingly
4281  if (m_enforce_dns_checkpoints && check_dns && !m_offline)
4282  {
4283  if (!m_checkpoints.load_checkpoints_from_dns())
4284  {
4285  return false;
4286  }
4287  }
4288  else if (check_dns && !m_offline)
4289  {
4290  checkpoints dns_points;
4291  dns_points.load_checkpoints_from_dns();
4292  if (m_checkpoints.check_for_conflicts(dns_points))
4293  {
4294  check_against_checkpoints(dns_points, false);
4295  }
4296  else
4297  {
4298  MERROR("One or more checkpoints fetched from DNS conflicted with existing checkpoints!");
4299  }
4300  }
4301 
4302  check_against_checkpoints(m_checkpoints, true);
4303 
4304  return true;
4305 }
#define MERROR(x)
Definition: misc_log_ex.h:73
void check_against_checkpoints(const checkpoints &points, bool enforce)
check the blockchain against a set of checkpoints
bool load_checkpoints_from_json(const std::string &json_hashfile_fullpath)
load new checkpoints from json
bool load_checkpoints_from_dns(network_type nettype=MAINNET)
load new checkpoints from DNS
A container for blockchain checkpoints.
Definition: checkpoints.h:51
bool check_for_conflicts(const checkpoints &other) const
checks if our checkpoints container conflicts with another
Here is the call graph for this function:
Here is the caller graph for this function:

◆ update_txpool_tx()

void Blockchain::update_txpool_tx ( const crypto::hash txid,
const txpool_tx_meta_t meta 
)

Definition at line 4773 of file blockchain.cpp.

4774 {
4775  m_db->update_txpool_tx(txid, meta);
4776 }
virtual void update_txpool_tx(const crypto::hash &txid, const txpool_tx_meta_t &details)=0
update a txpool transaction&#39;s metadata
Here is the call graph for this function:
Here is the caller graph for this function:

◆ utxo_nonexistence_from_output()

bool Blockchain::utxo_nonexistence_from_output ( const txin_to_key_public public_output) const

check if a single utxo in a transaction has already been spent using the hash and out index (v3 tx onwards)

Parameters
public_outputthe output to check
Returns
true if any utxo is nonexistent, else false

Definition at line 2993 of file blockchain.cpp.

2994 {
2995  LOG_PRINT_L3("Blockchain::" << __func__);
2996 
2997  if(!m_db->check_chainstate_utxo(public_output.tx_hash, public_output.relative_offset))
2998  return true;
2999 
3000  return false;
3001 }
virtual bool check_chainstate_utxo(const crypto::hash tx_hash, const uint32_t relative_out_index)=0
#define LOG_PRINT_L3(x)
Definition: misc_log_ex.h:102
Here is the call graph for this function:
Here is the caller graph for this function:

◆ utxo_nonexistent()

bool Blockchain::utxo_nonexistent ( const transaction tx) const

check if any utxo in a transaction has already been spent using the tx (v3 tx onwards)

Parameters
txthe transaction to check
Returns
true if any utxo is nonexistent, else false

Definition at line 2975 of file blockchain.cpp.

2976 {
2977  LOG_PRINT_L3("Blockchain::" << __func__);
2978 
2979  for (const txin_v& in: tx.vin)
2980  {
2981  if(in.type() == typeid(txin_to_key_public))
2982  {
2983  const auto &in_to_key = boost::get<txin_to_key_public>(in);
2984  if(!m_db->check_chainstate_utxo(in_to_key.tx_hash, in_to_key.relative_offset))
2985  return true;
2986  }
2987  }
2988  return false;
2989 }
boost::variant< txin_gen, txin_to_script, txin_to_scripthash, txin_to_key, txin_to_key_public > txin_v
virtual bool check_chainstate_utxo(const crypto::hash tx_hash, const uint32_t relative_out_index)=0
#define LOG_PRINT_L3(x)
Definition: misc_log_ex.h:102
Here is the call graph for this function:

◆ verify_block_signature()

bool Blockchain::verify_block_signature ( const block b)

Verify block's digital signature.

Parameters
bblock to be verified

Definition at line 1823 of file blockchain.cpp.

1823  {
1824  crypto::hash tx_tree_hash = get_tx_tree_hash(b);
1825  const std::vector<std::string> public_keys = m_validators->getApplicablePublicKeys(m_db->height(), true);
1826 
1827  for(auto &key : public_keys) {
1828  if(crypto::verify_signature(std::string(reinterpret_cast<char const *>(tx_tree_hash.data), sizeof(tx_tree_hash.data)),
1829  key, std::string(b.signature.begin(), b.signature.end()))){
1830  b.signatory = std::vector<uint8_t>(key.begin(), key.end());
1831  return true;
1832  }
1833  }
1834  return false;
1835 }
vector< string > getApplicablePublicKeys(uint64_t height, bool convert_to_byte=false)
Definition: validators.h:176
::std::string string
Definition: gtest-port.h:1097
std::vector< uint8_t > signatory
const char * key
Definition: hmac_keccak.cpp:39
bool verify_signature(const std::string &message, const std::string &publicKey, const std::string &signature)
Definition: crypto.h:380
virtual uint64_t height() const =0
fetch the current blockchain height
std::vector< uint8_t > signature
POD_CLASS hash
Definition: hash.h:50
void get_tx_tree_hash(const std::vector< crypto::hash > &tx_hashes, crypto::hash &h)
Here is the call graph for this function:

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