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_nonexistent (const transaction &tx) const
 check if any utxo in a transaction has already been spent (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 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 143 of file blockchain.cpp.

143  :
144  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),
145  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),
146  m_long_term_block_weights_window(CRYPTONOTE_LONG_TERM_BLOCK_WEIGHT_WINDOW_SIZE),
147  m_long_term_effective_median_block_weight(0),
148  m_long_term_block_weights_cache_tip_hash(crypto::null_hash),
149  m_long_term_block_weights_cache_rolling_median(CRYPTONOTE_LONG_TERM_BLOCK_WEIGHT_WINDOW_SIZE),
150  m_difficulty_for_next_block_top_hash(crypto::null_hash),
151  m_difficulty_for_next_block(1),
152  m_btc_valid(false),
153  m_batch_success(true)
154 {
155  LOG_PRINT_L3("Blockchain::" << __func__);
156 }
#define CRYPTONOTE_LONG_TERM_BLOCK_WEIGHT_WINDOW_SIZE
#define LOG_PRINT_L3(x)
Definition: misc_log_ex.h:102
@ db_async
handle syncing calls instead of the backing db, asynchronously
Definition: blockchain.h:81

◆ ~Blockchain()

Blockchain::~Blockchain ( )

Blockchain destructor.

Definition at line 158 of file blockchain.cpp.

159 {
160  try { deinit(); }
161  catch (const std::exception &e) { /* ignore */ }
162 }
bool deinit()
Uninitializes the blockchain state.
Definition: blockchain.cpp:546
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 4048 of file blockchain.cpp.

4049 {
4050  LOG_PRINT_L3("Blockchain::" << __func__);
4051  crypto::hash id = get_block_hash(bl);
4052  CRITICAL_REGION_LOCAL(m_tx_pool);//to avoid deadlock lets lock tx_pool for whole add/reorganize process
4053  CRITICAL_REGION_LOCAL1(m_blockchain_lock);
4054  db_rtxn_guard rtxn_guard(m_db);
4055  if(have_block(id))
4056  {
4057  LOG_PRINT_L3("block with id = " << id << " already exists");
4058  bvc.m_already_exists = true;
4059  m_blocks_txs_check.clear();
4060  return false;
4061  }
4062 
4063  //check that block refers to chain tail
4064  if(!(bl.prev_id == get_tail_id()))
4065  {
4066  //chain switching or wrong block
4067  bvc.m_added_to_main_chain = false;
4068  rtxn_guard.stop();
4069  bool r = handle_alternative_block(bl, id, bvc);
4070  m_blocks_txs_check.clear();
4071  return r;
4072  //never relay alternative blocks
4073  }
4074 
4075  rtxn_guard.stop();
4076  return handle_block_to_main_chain(bl, id, bvc);
4077 }
crypto::hash get_tail_id() const
get the hash of the most recent block on the blockchain
Definition: blockchain.cpp:723
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
bool get_block_hash(const block &b, crypto::hash &res)
#define CRITICAL_REGION_LOCAL1(x)
Definition: syncobj.h:230
#define CRITICAL_REGION_LOCAL(x)
Definition: syncobj.h:228
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 4615 of file blockchain.cpp.

4616 {
4617  m_db->add_txpool_tx(txid, blob, meta);
4618 }
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 2275 of file blockchain.cpp.

2276 {
2277  LOG_PRINT_L3("Blockchain::" << __func__);
2278  // WARNING: this function does not take m_blockchain_lock, and thus should only call read only
2279  // m_db functions which do not depend on one another (ie, no getheight + gethash(height-1), as
2280  // well as not accessing class members, even read only (ie, m_invalid_blocks). The caller must
2281  // lock if it is otherwise needed.
2282  try
2283  {
2284  return m_db->get_block_difficulty(i);
2285  }
2286  catch (const BLOCK_DNE& e)
2287  {
2288  MERROR("Attempted to get block difficulty for height above blockchain height");
2289  }
2290  return 0;
2291 }
thrown when a requested block does not exist
virtual difficulty_type get_block_difficulty(const uint64_t &height) const =0
fetch a block's difficulty
#define MERROR(x)
Definition: misc_log_ex.h:73
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 4160 of file blockchain.cpp.

4161 {
4162  TIME_MEASURE_START(t);
4164 
4165  for (const auto & block : blocks)
4166  {
4167  if (m_cancel)
4168  break;
4171  map.emplace(id, pow);
4172  }
4173 
4176 }
uint64_t height
Definition: blockchain.cpp:91
void slow_hash_allocate_state()
void slow_hash_free_state()
bool get_block_longhash(const block &b, crypto::hash &res, uint64_t height)
#define TIME_MEASURE_FINISH(var_name)
Definition: profile_tools.h:64
#define TIME_MEASURE_START(var_name)
Definition: profile_tools.h:61
Here is the call graph for this function:
Here is the caller graph for this function:

◆ cancel()

void Blockchain::cancel ( )

Definition at line 4780 of file blockchain.cpp.

4781 {
4782  m_cancel = true;
4783 }
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 4081 of file blockchain.cpp.

4082 {
4083  const auto& pts = points.get_points();
4084  bool stop_batch;
4085 
4086  CRITICAL_REGION_LOCAL(m_blockchain_lock);
4087  stop_batch = m_db->batch_start();
4088  const uint64_t blockchain_height = m_db->height();
4089  for (const auto& pt : pts)
4090  {
4091  // if the checkpoint is for a block we don't have yet, move on
4092  if (pt.first >= blockchain_height)
4093  {
4094  continue;
4095  }
4096 
4097  if (!points.check_block(pt.first, m_db->get_block_hash_from_height(pt.first)))
4098  {
4099  // if asked to enforce checkpoints, roll back to a couple of blocks before the checkpoint
4100  if (enforce)
4101  {
4102  LOG_ERROR("Local blockchain failed to pass a checkpoint, rolling back!");
4103  std::list<block> empty;
4104  rollback_blockchain_switching(empty, pt.first - 2);
4105  }
4106  else
4107  {
4108  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");
4109  }
4110  }
4111  }
4112  if (stop_batch)
4113  m_db->batch_stop();
4114 }
virtual void batch_stop()=0
ends a batch transaction
virtual uint64_t height() const =0
fetch the current blockchain height
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
virtual crypto::hash get_block_hash_from_height(const uint64_t &height) const =0
fetch a block's hash
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
const std::map< uint64_t, crypto::hash > & get_points() const
gets the checkpoints container
#define LOG_ERROR(x)
Definition: misc_log_ex.h:98
unsigned __int64 uint64_t
Definition: stdint.h:136
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 3943 of file blockchain.cpp.

3944 {
3945  m_tx_pool.lock();
3947  CRITICAL_REGION_LOCAL(m_blockchain_lock);
3948 
3949  return m_db->check_pruning();
3950 }
virtual bool check_pruning()=0
checks pruning was done correctly, iff enabled
void unlock() const
unlocks the transaction pool
Definition: tx_pool.cpp:1083
void lock() const
locks the transaction pool
Definition: tx_pool.cpp:1078
boost::shared_ptr< call_befor_die_base > auto_scope_leave_caller
auto_scope_leave_caller create_scope_leave_handler(t_scope_leave_handler f)
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 3246 of file blockchain.cpp.

3247 {
3249  const uint64_t blockchain_height = m_db->height();
3250 
3251  uint64_t median = 0;
3252  uint64_t already_generated_coins = 0;
3253  uint64_t base_reward = 0;
3255  {
3256  median = m_current_block_cumul_weight_limit / 2;
3257  const uint64_t blockchain_height = m_db->height();
3258  already_generated_coins = blockchain_height ? m_db->get_block_already_generated_coins(blockchain_height - 1) : 0;
3259  if (!get_block_reward(median, 1, already_generated_coins, base_reward, version, blockchain_height, get_nettype()))
3260  return false;
3261  }
3262 
3263  uint64_t needed_fee;
3265  {
3266  const bool use_long_term_median_in_fee = version >= HF_VERSION_LONG_TERM_BLOCK_WEIGHT;
3267  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);
3268  MDEBUG("Using " << print_etn(fee_per_byte) << "/byte fee");
3269  needed_fee = tx_weight * fee_per_byte;
3270  // quantize fee up to 8 decimals
3271  const uint64_t mask = get_fee_quantization_mask();
3272  needed_fee = (needed_fee + mask - 1) / mask * mask;
3273  }
3274  else
3275  {
3276  uint64_t fee_per_kb;
3278  {
3279  fee_per_kb = version >= 6 ? FEE_PER_KB_V6 : FEE_PER_KB;
3280  }
3281  else
3282  {
3283  fee_per_kb = get_dynamic_base_fee(base_reward, median, version);
3284  }
3285  MDEBUG("Using " << print_etn(fee_per_kb) << "/kB fee");
3286 
3287  needed_fee = tx_weight / 1024;
3288  needed_fee += (tx_weight % 1024) ? 1 : 0;
3289  needed_fee *= fee_per_kb;
3290  }
3291 
3292  if (fee < needed_fee - needed_fee / 50) // keep a little 2% buffer on acceptance - no integer overflow
3293  {
3294  MERROR_VER("transaction fee is not enough: " << print_etn(fee) << ", minimum fee: " << print_etn(needed_fee));
3295  return false;
3296  }
3297  return true;
3298 }
uint8_t version
Definition: blockchain.cpp:90
#define MERROR_VER(x)
Definition: blockchain.cpp:84
virtual uint64_t get_block_already_generated_coins(const uint64_t &height) const =0
fetch a block's already generated coins
uint8_t get_current_hard_fork_version() const
gets the current hardfork version in use/voted for
Definition: blockchain.h:815
network_type get_nettype() const
get blockchain nettype
Definition: blockchain.h:1048
static uint64_t get_fee_quantization_mask()
get fee quantization mask
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 HF_VERSION_DYNAMIC_FEE
#define FEE_PER_KB_V6
#define HF_VERSION_LONG_TERM_BLOCK_WEIGHT
#define FEE_PER_KB
#define HF_VERSION_PER_BYTE_FEE
#define MDEBUG(x)
Definition: misc_log_ex.h:76
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)
std::string print_etn(uint64_t amount, unsigned int decimal_point)
type_vec_type median(std::vector< type_vec_type > &v)
unsigned char uint8_t
Definition: stdint.h:124
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 2741 of file blockchain.cpp.

2742 {
2743  LOG_PRINT_L3("Blockchain::" << __func__);
2744  CRITICAL_REGION_LOCAL(m_blockchain_lock);
2745 
2746 #if defined(PER_BLOCK_CHECKPOINT)
2747  // check if we're doing per-block checkpointing
2748  if (m_db->height() < m_blocks_hash_check.size() && kept_by_block)
2749  {
2750  max_used_block_id = null_hash;
2751  max_used_block_height = 0;
2752  return true;
2753  }
2754 #endif
2755 
2757  bool res = check_tx_inputs(tx, tvc, &max_used_block_height);
2759  if(m_show_time_stats)
2760  {
2761  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;
2762  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));
2763  }
2764  if (!res)
2765  return false;
2766 
2767  // 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.
2768  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());
2769  max_used_block_id = m_db->get_block_hash_from_height(max_used_block_height);
2770  return true;
2771 }
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
const char * res
Definition: hmac_keccak.cpp:41
#define CHECK_AND_ASSERT_MES(expr, fail_ret_val, message)
Definition: misc_log_ex.h:181
#define MINFO(x)
Definition: misc_log_ex.h:75
crypto::hash get_transaction_hash(const transaction &t)
size_t get_object_blobsize(const t_object &o)
uint64_t get_transaction_weight(const transaction &tx, size_t blob_size)
const GenericPointer< typename T::ValueType > T2 T::AllocatorType & a
Definition: pointer.h:1124
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 2773 of file blockchain.cpp.

2774 {
2775  LOG_PRINT_L3("Blockchain::" << __func__);
2776  CRITICAL_REGION_LOCAL(m_blockchain_lock);
2777 
2778  const uint8_t hf_version = m_hardfork->get_current_version();
2779 
2780  // from hard fork 2, we forbid dust and compound outputs
2781  if (hf_version >= HF_VERSION_FORBID_DUST_OUTPUTS) {
2782  for (auto &o: tx.vout) {
2783  if (!is_valid_decomposed_amount(o.amount)) {
2784  tvc.m_invalid_output = true;
2785  return false;
2786  }
2787  }
2788  }
2789 
2790  // from v4, forbid invalid pubkeys
2791  if (hf_version >= HF_VERSION_FORBID_INVALID_PUBKEYS) {
2792  for (const auto &o: tx.vout) {
2793  if (hf_version < HF_VERSION_PUBLIC_TX) {
2794  if (o.target.type() == typeid(txout_to_key)) {
2795  const txout_to_key &out_to_key = boost::get<txout_to_key>(o.target);
2796  if (!crypto::check_key(out_to_key.key)) {
2797  tvc.m_invalid_output = true;
2798  return false;
2799  }
2800  }
2801  }
2802  else {
2803  //do a sanity check on output type before checking destination
2804  if (o.target.type() != typeid(txout_to_key_public)) {
2805  return false;
2806  }
2807  const txout_to_key_public &out_to_key_public = boost::get<txout_to_key_public>(o.target);
2808  if (!crypto::check_key(out_to_key_public.address.m_spend_public_key) ||
2809  !crypto::check_key(out_to_key_public.address.m_view_public_key)) {
2810  tvc.m_invalid_output = true;
2811  return false;
2812  }
2813 
2814  uint64_t address_prefix = get_config(m_nettype).CRYPTONOTE_PUBLIC_ADDRESS_BASE58_PREFIX;
2815  uint64_t integrated_address_prefix = get_config(m_nettype).CRYPTONOTE_PUBLIC_INTEGRATED_ADDRESS_BASE58_PREFIX;
2816  uint64_t subaddress_prefix = get_config(m_nettype).CRYPTONOTE_PUBLIC_SUBADDRESS_BASE58_PREFIX;
2817 
2818  std::vector<uint64_t> supported_prefixes{address_prefix, integrated_address_prefix, subaddress_prefix};
2819 
2820  if(std::find(supported_prefixes.begin(), supported_prefixes.end(), out_to_key_public.m_address_prefix) == supported_prefixes.end()) {
2821  tvc.m_invalid_output = true;
2822  return false;
2823  }
2824  }
2825  }
2826  }
2827  return true;
2828 }
uint8_t get_current_version() const
returns the current version
Definition: hardfork.cpp:361
#define HF_VERSION_PUBLIC_TX
#define HF_VERSION_FORBID_INVALID_PUBKEYS
#define HF_VERSION_FORBID_DUST_OUTPUTS
bool check_key(const public_key &key)
Definition: crypto.h:254
bool is_valid_decomposed_amount(uint64_t amount)
const config_t & get_config(network_type nettype)
uint64_t const CRYPTONOTE_PUBLIC_SUBADDRESS_BASE58_PREFIX
uint64_t const CRYPTONOTE_PUBLIC_INTEGRATED_ADDRESS_BASE58_PREFIX
uint64_t const CRYPTONOTE_PUBLIC_ADDRESS_BASE58_PREFIX
cryptonote::account_public_address address
crypto::public_key key
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 4179 of file blockchain.cpp.

4180 {
4181  bool success = false;
4182 
4183  MTRACE("Blockchain::" << __func__);
4184  CRITICAL_REGION_BEGIN(m_blockchain_lock);
4186 
4187  try
4188  {
4189  if (m_batch_success)
4190  m_db->batch_stop();
4191  else
4192  m_db->batch_abort();
4193  success = true;
4194  }
4195  catch (const std::exception &e)
4196  {
4197  MERROR("Exception in cleanup_handle_incoming_blocks: " << e.what());
4198  }
4199 
4200  if (success && m_sync_counter > 0)
4201  {
4202  if (force_sync)
4203  {
4204  if(m_db_sync_mode != db_nosync)
4205  store_blockchain();
4206  m_sync_counter = 0;
4207  }
4208  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)))
4209  {
4210  MDEBUG("Sync threshold met, syncing");
4211  if(m_db_sync_mode == db_async)
4212  {
4213  m_sync_counter = 0;
4214  m_bytes_to_sync = 0;
4215  m_async_service.dispatch(boost::bind(&Blockchain::store_blockchain, this));
4216  }
4217  else if(m_db_sync_mode == db_sync)
4218  {
4219  store_blockchain();
4220  }
4221  else // db_nosync
4222  {
4223  // DO NOTHING, not required to call sync.
4224  }
4225  }
4226  }
4227 
4229  m_blocks_longhash_table.clear();
4230  m_scan_table.clear();
4231  m_blocks_txs_check.clear();
4232  m_check_txin_table.clear();
4233 
4235  m_tx_pool.unlock();
4236 
4238 
4239  return success;
4240 }
virtual void batch_abort()=0
aborts a batch transaction
bool store_blockchain()
stores the blockchain
Definition: blockchain.cpp:516
expect< void > success() noexcept
Definition: expect.h:397
#define MTRACE(x)
Definition: misc_log_ex.h:77
@ db_nosync
Leave syncing up to the backing db (safest, but slowest because of disk I/O)
Definition: blockchain.h:82
@ db_sync
handle syncing calls instead of the backing db, synchronously
Definition: blockchain.h:80
t1
Definition: pow22523.h:58
#define CRITICAL_REGION_END()
Definition: syncobj.h:233
#define CRITICAL_REGION_BEGIN(x)
Definition: syncobj.h:229
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 1710 of file blockchain.cpp.

1711 {
1712  return create_block_template(b, NULL, miner_address, diffic, height, expected_reward, ex_nonce);
1713 }
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 1455 of file blockchain.cpp.

1456 {
1457  LOG_PRINT_L3("Blockchain::" << __func__);
1458  size_t median_weight;
1459  uint64_t already_generated_coins;
1460  //uint64_t pool_cookie;
1461 
1462  m_tx_pool.lock();
1463  const auto unlock_guard = epee::misc_utils::create_scope_leave_handler([&]() { m_tx_pool.unlock(); });
1464  CRITICAL_REGION_LOCAL(m_blockchain_lock);
1465  if (m_btc_valid && !from_block) {
1466  // The pool cookie is atomic. The lack of locking is OK, as if it changes
1467  // just as we compare it, we'll just use a slightly old template, but
1468  // this would be the case anyway if we'd lock, and the change happened
1469  // just after the block template was created
1470  if (!memcmp(&miner_address, &m_btc_address, sizeof(cryptonote::account_public_address)) && m_btc_nonce == ex_nonce
1471  && m_btc_pool_cookie == m_tx_pool.cookie() && m_btc.prev_id == get_tail_id()) {
1472  MDEBUG("Using cached template");
1473  m_btc.timestamp = time(NULL); // update timestamp unconditionally
1474  b = m_btc;
1475  diffic = m_btc_difficulty;
1476  height = m_btc_height;
1477  expected_reward = m_btc_expected_reward;
1478  return true;
1479  }
1480  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));
1481  invalidate_block_template_cache();
1482  }
1483 
1484  if (from_block)
1485  {
1486  //build alternative subchain, front -> mainchain, back -> alternative head
1487  //block is not related with head of main chain
1488  //first of all - look in alternative chains container
1489  auto it_prev = m_alternative_chains.find(*from_block);
1490  bool parent_in_main = m_db->block_exists(*from_block);
1491  if(it_prev == m_alternative_chains.end() && !parent_in_main)
1492  {
1493  MERROR("Unknown from block");
1494  return false;
1495  }
1496 
1497  //we have new block in alternative chain
1498  std::list<blocks_ext_by_hash::const_iterator> alt_chain;
1499  block_verification_context bvc = boost::value_initialized<block_verification_context>();
1500  std::vector<uint64_t> timestamps;
1501  if (!build_alt_chain(*from_block, alt_chain, timestamps, bvc))
1502  return false;
1503 
1504  if (parent_in_main)
1505  {
1506  cryptonote::block prev_block;
1507  CHECK_AND_ASSERT_MES(get_block_by_hash(*from_block, prev_block), false, "From block not found"); // TODO
1508  uint64_t from_block_height = cryptonote::get_block_height(prev_block);
1509  height = from_block_height + 1;
1510  }
1511  else
1512  {
1513  height = alt_chain.back()->second.height + 1;
1514  }
1515  b.major_version = m_hardfork->get_ideal_version(height);
1516  b.minor_version = m_hardfork->get_ideal_version();
1517  b.prev_id = *from_block;
1518 
1519  // cheat and use the weight of the block we start from, virtually certain to be acceptable
1520  // and use 1.9 times rather than 2 times so we're even more sure
1521  if (parent_in_main)
1522  {
1523  median_weight = m_db->get_block_weight(height - 1);
1524  already_generated_coins = m_db->get_block_already_generated_coins(height - 1);
1525  }
1526  else
1527  {
1528  median_weight = it_prev->second.block_cumulative_weight - it_prev->second.block_cumulative_weight / 20;
1529  already_generated_coins = alt_chain.back()->second.already_generated_coins;
1530  }
1531 
1532  // FIXME: consider moving away from block_extended_info at some point
1533  block_extended_info bei = boost::value_initialized<block_extended_info>();
1534  bei.bl = b;
1535  bei.height = alt_chain.size() ? it_prev->second.height + 1 : m_db->get_block_height(*from_block) + 1;
1536 
1537  diffic = get_next_difficulty_for_alternative_chain(alt_chain, bei);
1538  }
1539  else
1540  {
1541  height = m_db->height();
1542  b.major_version = m_hardfork->get_current_version();
1543  b.minor_version = m_hardfork->get_ideal_version();
1544  b.prev_id = get_tail_id();
1545  median_weight = m_current_block_cumul_weight_limit / 2;
1546  diffic = get_difficulty_for_next_block();
1547  already_generated_coins = m_db->get_block_already_generated_coins(height - 1);
1548  }
1549  b.timestamp = time(NULL);
1550 
1551  uint64_t median_ts;
1552  if (!check_block_timestamp(b, median_ts))
1553  {
1554  b.timestamp = median_ts;
1555  }
1556 
1557  CHECK_AND_ASSERT_MES(diffic, false, "difficulty overhead.");
1558 
1559  size_t txs_weight;
1560  uint64_t fee;
1561  if (!m_tx_pool.fill_block_template(b, median_weight, already_generated_coins, txs_weight, fee, expected_reward, b.major_version))
1562  {
1563  return false;
1564  }
1565  //pool_cookie = m_tx_pool.cookie();
1566 #if defined(DEBUG_CREATE_BLOCK_TEMPLATE)
1567  size_t real_txs_weight = 0;
1568  uint64_t real_fee = 0;
1569  for(crypto::hash &cur_hash: b.tx_hashes)
1570  {
1571  auto cur_res = m_tx_pool.m_transactions.find(cur_hash);
1572  if (cur_res == m_tx_pool.m_transactions.end())
1573  {
1574  LOG_ERROR("Creating block template: error: transaction not found");
1575  continue;
1576  }
1577  tx_memory_pool::tx_details &cur_tx = cur_res->second;
1578  real_txs_weight += cur_tx.weight;
1579  real_fee += cur_tx.fee;
1580  if (cur_tx.weight != get_transaction_weight(cur_tx.tx))
1581  {
1582  LOG_ERROR("Creating block template: error: invalid transaction weight");
1583  }
1584 
1585  uint64_t inputs_amount;
1586  if (!get_inputs_etn_amount(cur_tx.tx, inputs_amount))
1587  {
1588  LOG_ERROR("Creating block template: error: cannot get inputs amount");
1589  }
1590  else if (cur_tx.fee != inputs_amount - get_outs_etn_amount(cur_tx.tx))
1591  {
1592  LOG_ERROR("Creating block template: error: invalid fee");
1593  }
1594  }
1595  if (txs_weight != real_txs_weight)
1596  {
1597  LOG_ERROR("Creating block template: error: wrongly calculated transaction weight");
1598  }
1599  if (fee != real_fee)
1600  {
1601  LOG_ERROR("Creating block template: error: wrongly calculated fee");
1602  }
1603  MDEBUG("Creating block template: height " << height <<
1604  ", median weight " << median_weight <<
1605  ", already generated coins " << already_generated_coins <<
1606  ", transaction weight " << txs_weight <<
1607  ", fee " << fee);
1608 #endif
1609 
1610  /*
1611  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
1612  block weight, so first miner transaction generated with fake amount of etn, and with phase we know think we know expected block weight
1613  */
1614  //make blocks coin-base tx looks close to real coinbase tx to get truthful blob weight
1615  uint8_t hf_version = b.major_version;
1616  size_t max_outs = hf_version >= 4 ? 1 : 11;
1617  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);
1618  CHECK_AND_ASSERT_MES(r, false, "Failed to construct miner tx, first chance");
1619  size_t cumulative_weight = txs_weight + get_transaction_weight(b.miner_tx);
1620 #if defined(DEBUG_CREATE_BLOCK_TEMPLATE)
1621  MDEBUG("Creating block template: miner tx weight " << get_transaction_weight(b.miner_tx) <<
1622  ", cumulative weight " << cumulative_weight);
1623 #endif
1624  for (size_t try_count = 0; try_count != 10; ++try_count)
1625  {
1626  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);
1627 
1628  CHECK_AND_ASSERT_MES(r, false, "Failed to construct miner tx, second chance");
1629  size_t coinbase_weight = get_transaction_weight(b.miner_tx);
1630  if (coinbase_weight > cumulative_weight - txs_weight)
1631  {
1632  cumulative_weight = txs_weight + coinbase_weight;
1633 #if defined(DEBUG_CREATE_BLOCK_TEMPLATE)
1634  MDEBUG("Creating block template: miner tx weight " << coinbase_weight <<
1635  ", cumulative weight " << cumulative_weight << " is greater than before");
1636 #endif
1637  continue;
1638  }
1639 
1640  if (coinbase_weight < cumulative_weight - txs_weight)
1641  {
1642  size_t delta = cumulative_weight - txs_weight - coinbase_weight;
1643 #if defined(DEBUG_CREATE_BLOCK_TEMPLATE)
1644  MDEBUG("Creating block template: miner tx weight " << coinbase_weight <<
1645  ", cumulative weight " << txs_weight + coinbase_weight <<
1646  " is less than before, adding " << delta << " zero bytes");
1647 #endif
1648  b.miner_tx.extra.insert(b.miner_tx.extra.end(), delta, 0);
1649  //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.
1650  if (cumulative_weight != txs_weight + get_transaction_weight(b.miner_tx))
1651  {
1652  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));
1653  b.miner_tx.extra.resize(b.miner_tx.extra.size() - 1);
1654  if (cumulative_weight != txs_weight + get_transaction_weight(b.miner_tx))
1655  {
1656  //fuck, not lucky, -1 makes varint-counter size smaller, in that case we continue to grow with cumulative_weight
1657  MDEBUG("Miner tx creation has no luck with delta_extra size = " << delta << " and " << delta - 1);
1658  cumulative_weight += delta - 1;
1659  continue;
1660  }
1661  MDEBUG("Setting extra for block: " << b.miner_tx.extra.size() << ", try_count=" << try_count);
1662  }
1663  }
1664  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));
1665 #if defined(DEBUG_CREATE_BLOCK_TEMPLATE)
1666  MDEBUG("Creating block template: miner tx weight " << coinbase_weight <<
1667  ", cumulative weight " << cumulative_weight << " is now good");
1668 #endif
1669 
1670  //if (!from_block)
1671  // cache_block_template(b, miner_address, ex_nonce, diffic, height, expected_reward, pool_cookie);
1672 
1673  if(!m_fallback_to_pow && hf_version >= 8) {
1674  sign_block(b, m_validator_key);
1675  }
1676 
1677  return true;
1678  }
1679  LOG_ERROR("Failed to create_block_template with " << 10 << " tries");
1680  return false;
1681 }
time_t time
Definition: blockchain.cpp:93
virtual uint64_t get_block_height(const crypto::hash &h) const =0
gets the height of the block with a given hash
virtual size_t get_block_weight(const uint64_t &height) const =0
fetch a block's weight
virtual bool block_exists(const crypto::hash &h, uint64_t *height=NULL) const =0
checks if a block exists
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:814
difficulty_type get_difficulty_for_next_block()
returns the difficulty target the next block to be added must meet
Definition: blockchain.cpp:857
uint8_t get_ideal_version() const
returns the latest "ideal" version
Definition: hardfork.cpp:367
std::vector< uint8_t > extra
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:1358
uint64_t cookie() const
return the cookie
Definition: tx_pool.h:373
uint64_t get_outs_etn_amount(const transaction &tx)
uint64_t get_block_height(const block &b)
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)
bool get_inputs_etn_amount(const transaction &tx, uint64_t &etn)
std::vector< crypto::hash > tx_hashes
information about a single transaction
Definition: tx_pool.h:396
transaction tx
the transaction
Definition: tx_pool.h:397
uint64_t fee
the transaction's fee amount
Definition: tx_pool.h:400
size_t weight
the transaction's weight
Definition: tx_pool.h:399
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 546 of file blockchain.cpp.

547 {
548  LOG_PRINT_L3("Blockchain::" << __func__);
549 
550  MTRACE("Stopping blockchain read/write activity");
551 
552  // stop async service
553  m_async_work_idle.reset();
554  m_async_pool.join_all();
555  m_async_service.stop();
556 
557  // as this should be called if handling a SIGSEGV, need to check
558  // if m_db is a NULL pointer (and thus may have caused the illegal
559  // memory operation), otherwise we may cause a loop.
560  try
561  {
562  if (m_db)
563  {
564  m_db->close();
565  MTRACE("Local blockchain read/write activity stopped successfully");
566  }
567  }
568  catch (const std::exception& e)
569  {
570  LOG_ERROR(std::string("Error closing blockchain db: ") + e.what());
571  }
572  catch (...)
573  {
574  LOG_ERROR("There was an issue closing/storing the blockchain, shutting down now to prevent issues!");
575  }
576 
577  delete m_hardfork;
578  m_hardfork = NULL;
579  delete m_db;
580  m_db = NULL;
581  return true;
582 }
virtual void close()=0
close the BlockchainDB
::std::string string
Definition: gtest-port.h:1097
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,
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 2470 of file blockchain.cpp.

2471 {
2472  LOG_PRINT_L3("Blockchain::" << __func__);
2473  CRITICAL_REGION_LOCAL(m_blockchain_lock);
2474 
2475  bool result = find_blockchain_supplement(qblock_ids, resp.m_block_ids, resp.start_height, resp.total_height, true);
2476  if (result)
2477  {
2478  cryptonote::difficulty_type wide_cumulative_difficulty = m_db->get_block_cumulative_difficulty(resp.total_height - 1);
2479  resp.cumulative_difficulty = (wide_cumulative_difficulty & 0xffffffffffffffff).convert_to<uint64_t>();
2480  resp.cumulative_difficulty_top64 = ((wide_cumulative_difficulty >> 64) & 0xffffffffffffffff).convert_to<uint64_t>();
2481  }
2482 
2483  return result;
2484 }
virtual difficulty_type get_block_cumulative_difficulty(const uint64_t &height) const =0
fetch a block's cumulative difficulty
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
boost::multiprecision::uint128_t difficulty_type
Definition: difficulty.h:43
Here is the call graph for this function:

◆ find_blockchain_supplement() [2/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 2440 of file blockchain.cpp.

2441 {
2442  LOG_PRINT_L3("Blockchain::" << __func__);
2443  CRITICAL_REGION_LOCAL(m_blockchain_lock);
2444 
2445  // if we can't find the split point, return false
2446  if(!find_blockchain_supplement(qblock_ids, start_height))
2447  {
2448  return false;
2449  }
2450 
2451  db_rtxn_guard rtxn_guard(m_db);
2452  current_height = get_current_blockchain_height();
2453  uint64_t stop_height = current_height;
2454  if (clip_pruned)
2455  {
2456  const uint32_t pruning_seed = get_blockchain_pruning_seed();
2457  start_height = tools::get_next_unpruned_block_height(start_height, current_height, pruning_seed);
2458  stop_height = tools::get_next_pruned_block_height(start_height, current_height, pruning_seed);
2459  }
2460  size_t count = 0;
2461  hashes.reserve(std::min((size_t)(stop_height - start_height), (size_t)BLOCKS_IDS_SYNCHRONIZING_DEFAULT_COUNT));
2462  for(size_t i = start_height; i < stop_height && count < BLOCKS_IDS_SYNCHRONIZING_DEFAULT_COUNT; i++, count++)
2463  {
2464  hashes.push_back(m_db->get_block_hash_from_height(i));
2465  }
2466 
2467  return true;
2468 }
uint32_t get_blockchain_pruning_seed() const
Definition: blockchain.h:1007
uint64_t get_current_blockchain_height() const
get the current height of the blockchain
Definition: blockchain.cpp:319
#define BLOCKS_IDS_SYNCHRONIZING_DEFAULT_COUNT
mdb_size_t count(MDB_cursor *cur)
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_next_unpruned_block_height(uint64_t block_height, uint64_t blockchain_height, uint32_t pruning_seed)
Definition: pruning.cpp:69
unsigned int uint32_t
Definition: stdint.h:126
struct hash_func hashes[]
Here is the call graph for this function:
Here is the caller 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 2220 of file blockchain.cpp.

2221 {
2222  LOG_PRINT_L3("Blockchain::" << __func__);
2223  CRITICAL_REGION_LOCAL(m_blockchain_lock);
2224 
2225  // make sure the request includes at least the genesis block, otherwise
2226  // how can we expect to sync from the client that the block list came from?
2227  if(qblock_ids.empty())
2228  {
2229  MCERROR("net.p2p", "Client sent wrong NOTIFY_REQUEST_CHAIN: m_block_ids.size()=" << qblock_ids.size() << ", dropping connection");
2230  return false;
2231  }
2232 
2233  db_rtxn_guard rtxn_guard(m_db);
2234  // make sure that the last block in the request's block list matches
2235  // the genesis block
2236  auto gen_hash = m_db->get_block_hash_from_height(0);
2237  if(qblock_ids.back() != gen_hash)
2238  {
2239  LOG_PRINT_L0("Genesis Block Mismatch");
2240  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");
2241  return false;
2242  }
2243 
2244  // Find the first block the foreign chain has that we also have.
2245  // Assume qblock_ids is in reverse-chronological order.
2246  auto bl_it = qblock_ids.begin();
2247  uint64_t split_height = 0;
2248  for(; bl_it != qblock_ids.end(); bl_it++)
2249  {
2250  try
2251  {
2252  if (m_db->block_exists(*bl_it, &split_height))
2253  break;
2254  }
2255  catch (const std::exception& e)
2256  {
2257  MWARNING("Non-critical error trying to find block by hash in BlockchainDB, hash: " << *bl_it);
2258  return false;
2259  }
2260  }
2261 
2262  // this should be impossible, as we checked that we share the genesis block,
2263  // but just in case...
2264  if(bl_it == qblock_ids.end())
2265  {
2266  MERROR("Internal error handling connection, can't find split point");
2267  return false;
2268  }
2269 
2270  //we start to put block ids INCLUDING last known id, just to make other side be sure
2271  starter_offset = split_height;
2272  return true;
2273 }
#define MCERROR(cat, x)
Definition: misc_log_ex.h:51
#define MWARNING(x)
Definition: misc_log_ex.h:74
#define LOG_PRINT_L0(x)
Definition: misc_log_ex.h:99
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 2490 of file blockchain.cpp.

2491 {
2492  LOG_PRINT_L3("Blockchain::" << __func__);
2493  CRITICAL_REGION_LOCAL(m_blockchain_lock);
2494 
2495  // if a specific start height has been requested
2496  if(req_start_block > 0)
2497  {
2498  // if requested height is higher than our chain, return false -- we can't help
2499  if (req_start_block >= m_db->height())
2500  {
2501  return false;
2502  }
2503  start_height = req_start_block;
2504  }
2505  else
2506  {
2507  if(!find_blockchain_supplement(qblock_ids, start_height))
2508  {
2509  return false;
2510  }
2511  }
2512 
2513  db_rtxn_guard rtxn_guard(m_db);
2514  total_height = get_current_blockchain_height();
2515  size_t count = 0, size = 0;
2516  blocks.reserve(std::min(std::min(max_count, (size_t)10000), (size_t)(total_height - start_height)));
2517  for(uint64_t i = start_height; i < total_height && count < max_count && (size < FIND_BLOCKCHAIN_SUPPLEMENT_MAX_SIZE || count < 3); i++, count++)
2518  {
2519  blocks.resize(blocks.size()+1);
2520  blocks.back().first.first = m_db->get_block_blob_from_height(i);
2521  block b;
2522  CHECK_AND_ASSERT_MES(parse_and_validate_block_from_blob(blocks.back().first.first, b), false, "internal error, invalid block");
2523  blocks.back().first.second = get_miner_tx_hash ? cryptonote::get_transaction_hash(b.miner_tx) : crypto::null_hash;
2524  std::vector<crypto::hash> mis;
2525  std::vector<cryptonote::blobdata> txs;
2526  get_transactions_blobs(b.tx_hashes, txs, mis, pruned);
2527  CHECK_AND_ASSERT_MES(!mis.size(), false, "internal error, transaction from block not found");
2528  size += blocks.back().first.first.size();
2529  for (const auto &t: txs)
2530  size += t.size();
2531 
2532  CHECK_AND_ASSERT_MES(txs.size() == b.tx_hashes.size(), false, "mismatched sizes of b.tx_hashes and txs");
2533  blocks.back().second.reserve(txs.size());
2534  for (size_t i = 0; i < txs.size(); ++i)
2535  {
2536  blocks.back().second.push_back(std::make_pair(b.tx_hashes[i], std::move(txs[i])));
2537  }
2538  }
2539  return true;
2540 }
#define FIND_BLOCKCHAIN_SUPPLEMENT_MAX_SIZE
Definition: blockchain.cpp:65
virtual cryptonote::blobdata get_block_blob_from_height(const uint64_t &height) const =0
fetch a block blob by height
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
crypto namespace.
Definition: crypto.cpp:58
bool parse_and_validate_block_from_blob(const blobdata &b_blob, block &b, crypto::hash *block_hash)
const T & move(const T &t)
Definition: gtest-port.h:1317
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 3509 of file blockchain.cpp.

3510 {
3511  CRITICAL_REGION_LOCAL(m_tx_pool);
3512 
3513  bool res = true;
3514  for (const auto &txid: txids)
3515  {
3517  cryptonote::blobdata txblob;
3518  size_t tx_weight;
3519  uint64_t fee;
3520  bool relayed, do_not_relay, double_spend_seen, nonexistent_utxo_seen;
3521  MINFO("Removing txid " << txid << " from the pool");
3522  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))
3523  {
3524  MERROR("Failed to remove txid " << txid << " from the pool");
3525  res = false;
3526  }
3527  }
3528  return res;
3529 }
bool have_tx(const crypto::hash &id) const
checks if the pool has a transaction with the given hash
Definition: tx_pool.cpp:1025
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:531
std::string blobdata
Definition: blobdatatype.h:39
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 4888 of file blockchain.cpp.

4889 {
4890  return m_db->for_all_key_images(f);
4891 }
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 4903 of file blockchain.cpp.

4904 {
4905  return m_db->for_all_outputs(f);;
4906 }
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 4908 of file blockchain.cpp.

4909 {
4910  return m_db->for_all_outputs(amount, f);;
4911 }
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 4898 of file blockchain.cpp.

4899 {
4900  return m_db->for_all_transactions(f, pruned);
4901 }
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:

◆ 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 4650 of file blockchain.cpp.

4651 {
4652  return m_db->for_all_txpool_txes(f, include_blob, include_unrelayed_txes);
4653 }
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 4893 of file blockchain.cpp.

4894 {
4895  return m_db->for_blocks_range(h1, h2, f);
4896 }
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 2065 of file blockchain.cpp.

2066 {
2067  LOG_PRINT_L3("Blockchain::" << __func__);
2068  CRITICAL_REGION_LOCAL(m_blockchain_lock);
2069 
2070  blocks.reserve(m_alternative_chains.size());
2071  for (const auto& alt_bl: m_alternative_chains)
2072  {
2073  blocks.push_back(alt_bl.second.bl);
2074  }
2075  return true;
2076 }
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 2078 of file blockchain.cpp.

2079 {
2080  LOG_PRINT_L3("Blockchain::" << __func__);
2081  CRITICAL_REGION_LOCAL(m_blockchain_lock);
2082  return m_alternative_chains.size();
2083 }
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 4747 of file blockchain.cpp.

4748 {
4749  std::list<std::pair<Blockchain::block_extended_info,std::vector<crypto::hash>>> chains;
4750 
4751  for (const auto &i: m_alternative_chains)
4752  {
4753  const crypto::hash &top = i.first;
4754  bool found = false;
4755  for (const auto &j: m_alternative_chains)
4756  {
4757  if (j.second.bl.prev_id == top)
4758  {
4759  found = true;
4760  break;
4761  }
4762  }
4763  if (!found)
4764  {
4765  std::vector<crypto::hash> chain;
4766  auto h = i.second.bl.prev_id;
4767  chain.push_back(top);
4768  blocks_ext_by_hash::const_iterator prev;
4769  while ((prev = m_alternative_chains.find(h)) != m_alternative_chains.end())
4770  {
4771  chain.push_back(h);
4772  h = prev->second.bl.prev_id;
4773  }
4774  chains.push_back(std::make_pair(i.second, chain));
4775  }
4776  }
4777  return chains;
4778 }

◆ 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 814 of file blockchain.cpp.

815 {
816  LOG_PRINT_L3("Blockchain::" << __func__);
817  CRITICAL_REGION_LOCAL(m_blockchain_lock);
818 
819  // try to find block in main chain
820  try
821  {
822  blk = m_db->get_block(h);
823  if (orphan)
824  *orphan = false;
825  return true;
826  }
827  // try to find block in alternative chain
828  catch (const BLOCK_DNE& e)
829  {
830  blocks_ext_by_hash::const_iterator it_alt = m_alternative_chains.find(h);
831  if (m_alternative_chains.end() != it_alt)
832  {
833  blk = it_alt->second.bl;
834  if (orphan)
835  *orphan = true;
836  return true;
837  }
838  }
839  catch (const std::exception& e)
840  {
841  MERROR(std::string("Something went wrong fetching block by hash: ") + e.what());
842  throw;
843  }
844  catch (...)
845  {
846  MERROR(std::string("Something went wrong fetching block hash by hash"));
847  throw;
848  }
849 
850  return false;
851 }
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 787 of file blockchain.cpp.

788 {
789  LOG_PRINT_L3("Blockchain::" << __func__);
790  // WARNING: this function does not take m_blockchain_lock, and thus should only call read only
791  // m_db functions which do not depend on one another (ie, no getheight + gethash(height-1), as
792  // well as not accessing class members, even read only (ie, m_invalid_blocks). The caller must
793  // lock if it is otherwise needed.
794  try
795  {
796  return m_db->get_block_hash_from_height(height);
797  }
798  catch (const BLOCK_DNE& e)
799  {
800  }
801  catch (const std::exception& e)
802  {
803  MERROR(std::string("Something went wrong fetching block hash by height: ") + e.what());
804  throw;
805  }
806  catch (...)
807  {
808  MERROR(std::string("Something went wrong fetching block hash by height"));
809  throw;
810  }
811  return null_hash;
812 }
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 1007 of file blockchain.h.

1007 { 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]

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 2299 of file blockchain.cpp.

2300 {
2301  LOG_PRINT_L3("Blockchain::" << __func__);
2302  CRITICAL_REGION_LOCAL(m_blockchain_lock);
2303 
2304  reserve_container(blocks, block_ids.size());
2305  for (const auto& block_hash : block_ids)
2306  {
2307  try
2308  {
2309  uint64_t height = 0;
2310  if (m_db->block_exists(block_hash, &height))
2311  {
2312  blocks.push_back(std::make_pair(m_db->get_block_blob_from_height(height), block()));
2313  if (!parse_and_validate_block_from_blob(blocks.back().first, blocks.back().second))
2314  {
2315  LOG_ERROR("Invalid block: " << block_hash);
2316  blocks.pop_back();
2317  missed_bs.push_back(block_hash);
2318  }
2319  }
2320  else
2321  missed_bs.push_back(block_hash);
2322  }
2323  catch (const std::exception& e)
2324  {
2325  return false;
2326  }
2327  }
2328  return true;
2329 }
void reserve_container(std::vector< T > &v, size_t N)
Here is the call 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 1990 of file blockchain.cpp.

1991 {
1992  LOG_PRINT_L3("Blockchain::" << __func__);
1993  CRITICAL_REGION_LOCAL(m_blockchain_lock);
1994  const uint64_t height = m_db->height();
1995  if(start_offset >= height)
1996  return false;
1997 
1998  blocks.reserve(blocks.size() + height - start_offset);
1999  for(size_t i = start_offset; i < start_offset + count && i < height;i++)
2000  {
2001  blocks.push_back(std::make_pair(m_db->get_block_blob_from_height(i), block()));
2002  if (!parse_and_validate_block_from_blob(blocks.back().first, blocks.back().second))
2003  {
2004  LOG_ERROR("Invalid block");
2005  return false;
2006  }
2007  }
2008  return true;
2009 }
Here is the call graph for this function:

◆ get_blocks() [3/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 1968 of file blockchain.cpp.

1969 {
1970  LOG_PRINT_L3("Blockchain::" << __func__);
1971  CRITICAL_REGION_LOCAL(m_blockchain_lock);
1972  if(start_offset >= m_db->height())
1973  return false;
1974 
1975  if (!get_blocks(start_offset, count, blocks))
1976  {
1977  return false;
1978  }
1979 
1980  for(const auto& blk : blocks)
1981  {
1982  std::vector<crypto::hash> missed_ids;
1983  get_transactions_blobs(blk.second.tx_hashes, txs, missed_ids);
1984  CHECK_AND_ASSERT_MES(!missed_ids.size(), false, "has missed transactions in own block in main blockchain");
1985  }
1986 
1987  return true;
1988 }
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
Here is the call graph for this function:
Here is the caller 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 319 of file blockchain.cpp.

320 {
321  LOG_PRINT_L3("Blockchain::" << __func__);
322  // WARNING: this function does not take m_blockchain_lock, and thus should only call read only
323  // m_db functions which do not depend on one another (ie, no getheight + gethash(height-1), as
324  // well as not accessing class members, even read only (ie, m_invalid_blocks). The caller must
325  // lock if it is otherwise needed.
326  return m_db->height();
327 }
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 1432 of file blockchain.cpp.

1433 {
1434  LOG_PRINT_L3("Blockchain::" << __func__);
1435  return m_current_block_cumul_weight_limit;
1436 }
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 1438 of file blockchain.cpp.

1439 {
1440  LOG_PRINT_L3("Blockchain::" << __func__);
1441  return m_current_block_cumul_weight_median;
1442 }
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 815 of file blockchain.h.

815 { return m_hardfork->get_current_version(); }
Here is the call graph for this function:
Here is the caller graph for this function:

◆ get_db() [1/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 963 of file blockchain.h.

964  {
965  return *m_db;
966  }

◆ get_db() [2/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 953 of file blockchain.h.

954  {
955  return *m_db;
956  }
Here is the caller graph for this function:

◆ 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 857 of file blockchain.cpp.

858 {
859  if (m_fixed_difficulty)
860  {
861  return m_db->height() ? m_fixed_difficulty : 1;
862  }
863 
864  LOG_PRINT_L3("Blockchain::" << __func__);
865 
866  crypto::hash top_hash = get_tail_id();
867  {
868  CRITICAL_REGION_LOCAL(m_difficulty_lock);
869  // we can call this without the blockchain lock, it might just give us
870  // something a bit out of date, but that's fine since anything which
871  // requires the blockchain lock will have acquired it in the first place,
872  // and it will be unlocked only when called from the getinfo RPC
873  if (top_hash == m_difficulty_for_next_block_top_hash)
874  return m_difficulty_for_next_block;
875  }
876 
877  CRITICAL_REGION_LOCAL(m_blockchain_lock);
878  std::vector<uint64_t> timestamps;
879  std::vector<difficulty_type> difficulties;
881  top_hash = get_tail_id(height); // get it again now that we have the lock
882  ++height; // top block height to blockchain height
883 
884  uint64_t v6height = 0, v7height = 0, v8height = 0;
885  if(m_nettype == MAINNET) {
886  v6height = mainnet_hard_forks[1].height;
887  v7height = mainnet_hard_forks[2].height;
888  v8height = mainnet_hard_forks[3].height;
889  } else if(m_nettype == TESTNET) {
890  v6height = testnet_hard_forks[1].height;
891  v7height = testnet_hard_forks[2].height;
892  v8height = testnet_hard_forks[3].height;
893  } else if(m_nettype == STAGENET) {
894  v6height = stagenet_hard_forks[5].height;
895  v7height = stagenet_hard_forks[5].height;
896  v8height = stagenet_hard_forks[5].height;
897  } else if(m_nettype == UNDEFINED){
898  MERROR(std::string("Something went wrong defining the network type."));
899  }
900 
901 
902  uint32_t difficultyBlocksCount = (height >= v6height && height < v7height) ? DIFFICULTY_BLOCKS_COUNT_V6 : DIFFICULTY_BLOCKS_COUNT;
903 
904  // After v8 allow the difficulty window to grow linearly (from zero) back to DIFFICULTY_BLOCKS_COUNT.
905  if((height >= v8height) && (height < v8height + 720))
906  {
907  // Initial clear of the caches when we hit v8.
908  if(height == v8height)
909  {
910  m_timestamps.clear();
911  m_difficulties.clear();
912  }
913  difficultyBlocksCount = height - v8height;
914  }
915 
916  // ND: Speedup
917  // 1. Keep a list of the last 735 (or less) blocks that is used to compute difficulty,
918  // then when the next block difficulty is queried, push the latest height data and
919  // pop the oldest one from the list. This only requires 1x read per height instead
920  // of doing 735 (DIFFICULTY_BLOCKS_COUNT).
921  // Post v8 we will only re-enter this scope after the first DIFFICULTY_BLOCKS_COUNT blocks due to the last condition.
922  if (m_timestamps_and_difficulties_height != 0 && ((height - m_timestamps_and_difficulties_height) == 1) && m_timestamps.size() >= difficultyBlocksCount)
923  {
924  uint64_t index = height - 1;
925  m_timestamps.push_back(m_db->get_block_timestamp(index));
926  m_difficulties.push_back(m_db->get_block_cumulative_difficulty(index));
927 
928  while (m_timestamps.size() > difficultyBlocksCount)
929  m_timestamps.erase(m_timestamps.begin());
930  while (m_difficulties.size() > difficultyBlocksCount)
931  m_difficulties.erase(m_difficulties.begin());
932 
933  m_timestamps_and_difficulties_height = height;
934  timestamps = m_timestamps;
935  difficulties = m_difficulties;
936  }
937  else
938  {
939  uint64_t offset = height - std::min < uint64_t > (height, static_cast<uint64_t>(difficultyBlocksCount));
940  if (offset == 0)
941  ++offset;
942 
943  timestamps.clear();
944  difficulties.clear();
945  if (height > offset)
946  {
947  timestamps.reserve(height - offset);
948  difficulties.reserve(height - offset);
949  }
950  for (; offset < height; offset++)
951  {
952  timestamps.push_back(m_db->get_block_timestamp(offset));
953  difficulties.push_back(m_db->get_block_cumulative_difficulty(offset));
954  }
955 
956  m_timestamps_and_difficulties_height = height;
957  m_timestamps = timestamps;
958  m_difficulties = difficulties;
959  }
960  size_t target = get_difficulty_target();
961  const uint8_t version = (height >= v6height && height < v7height) ? 6 : 1;
962  difficulty_type diff = next_difficulty(timestamps, difficulties, target, version);
963 
964  CRITICAL_REGION_LOCAL1(m_difficulty_lock);
965  m_difficulty_for_next_block_top_hash = top_hash;
966  m_difficulty_for_next_block = diff;
967  return diff;
968 }
virtual uint64_t get_block_timestamp(const uint64_t &height) const =0
fetch a block's timestamp
uint64_t get_difficulty_target() const
get difficulty target based on chain and hardfork version
#define DIFFICULTY_BLOCKS_COUNT_V6
#define DIFFICULTY_BLOCKS_COUNT
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
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 4737 of file blockchain.cpp.

4738 {
4740 }
#define DIFFICULTY_TARGET
#define DIFFICULTY_TARGET_V6
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 3208 of file blockchain.cpp.

3209 {
3210  const uint64_t min_block_weight = get_min_block_weight(version);
3211  if (median_block_weight < min_block_weight)
3212  median_block_weight = min_block_weight;
3213  uint64_t hi, lo;
3214 
3216  {
3217  lo = mul128(block_reward, DYNAMIC_FEE_REFERENCE_TRANSACTION_WEIGHT, &hi);
3218  div128_32(hi, lo, min_block_weight, &hi, &lo);
3219  div128_32(hi, lo, median_block_weight, &hi, &lo);
3220  assert(hi == 0);
3221  lo /= 5;
3222  return lo;
3223  }
3224 
3226 
3227  uint64_t unscaled_fee_base = (fee_base * min_block_weight / median_block_weight);
3228  lo = mul128(unscaled_fee_base, block_reward, &hi);
3229  static_assert(DYNAMIC_FEE_PER_KB_BASE_BLOCK_REWARD % 1000000 == 0, "DYNAMIC_FEE_PER_KB_BASE_BLOCK_REWARD must be divisible by 1000000");
3230  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");
3231 
3232  // divide in two steps, since the divisor must be 32 bits, but DYNAMIC_FEE_PER_KB_BASE_BLOCK_REWARD isn't
3233  div128_32(hi, lo, DYNAMIC_FEE_PER_KB_BASE_BLOCK_REWARD / 1000000, &hi, &lo);
3234  div128_32(hi, lo, 1000000, &hi, &lo);
3235  assert(hi == 0);
3236 
3237  // quantize fee up to 8 decimals
3239  uint64_t qlo = (lo + mask - 1) / mask * mask;
3240  MDEBUG("lo " << print_etn(lo) << ", qlo " << print_etn(qlo) << ", mask " << mask);
3241 
3242  return qlo;
3243 }
#define DYNAMIC_FEE_PER_KB_BASE_FEE_V5
#define DYNAMIC_FEE_PER_KB_BASE_BLOCK_REWARD
#define DYNAMIC_FEE_REFERENCE_TRANSACTION_WEIGHT
#define DYNAMIC_FEE_PER_KB_BASE_FEE
size_t get_min_block_weight(uint8_t version)
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 3301 of file blockchain.cpp.

3302 {
3304  const uint64_t db_height = m_db->height();
3305 
3307  if(version == 1)
3308  return FEE_PER_KB;
3309  else
3310  return FEE_PER_KB_V6;
3311  }
3312 
3313  if (grace_blocks >= CRYPTONOTE_REWARD_BLOCKS_WINDOW)
3314  grace_blocks = CRYPTONOTE_REWARD_BLOCKS_WINDOW - 1;
3315 
3316  const uint64_t min_block_weight = get_min_block_weight(version);
3317  std::vector<uint64_t> weights;
3318  get_last_n_blocks_weights(weights, CRYPTONOTE_REWARD_BLOCKS_WINDOW - grace_blocks);
3319  weights.reserve(grace_blocks);
3320  for (size_t i = 0; i < grace_blocks; ++i)
3321  weights.push_back(min_block_weight);
3322 
3324  if(median <= min_block_weight)
3325  median = min_block_weight;
3326 
3327  uint64_t already_generated_coins = db_height ? m_db->get_block_already_generated_coins(db_height - 1) : 0;
3328  uint64_t base_reward;
3329  if (!get_block_reward(median, 1, already_generated_coins, base_reward, version, get_current_blockchain_height(), get_nettype()))
3330  {
3331  MERROR("Failed to determine block reward, using placeholder " << print_etn(BLOCK_REWARD_OVERESTIMATE) << " as a high bound");
3332  base_reward = BLOCK_REWARD_OVERESTIMATE;
3333  }
3334 
3335  const bool use_long_term_median_in_fee = version >= HF_VERSION_LONG_TERM_BLOCK_WEIGHT;
3336  uint64_t fee = get_dynamic_base_fee(base_reward, use_long_term_median_in_fee ? m_long_term_effective_median_block_weight : median, version);
3337  const bool per_byte = version < HF_VERSION_PER_BYTE_FEE;
3338  MDEBUG("Estimating " << grace_blocks << "-block fee at " << print_etn(fee) << "/" << (per_byte ? "byte" : "kB"));
3339  return fee;
3340 }
#define BLOCK_REWARD_OVERESTIMATE
Definition: blockchain.cpp:87
#define CRYPTONOTE_REWARD_BLOCKS_WINDOW
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 855 of file blockchain.h.

855 { return m_hardfork->get_earliest_ideal_height_for_version(version); }
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
version
Supported socks variants.
Definition: socks.h:58
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 3195 of file blockchain.cpp.

3196 {
3197  static uint64_t mask = 0;
3198  if (mask == 0)
3199  {
3200  mask = 1;
3202  mask *= 10;
3203  }
3204  return mask;
3205 }
#define PER_KB_FEE_QUANTIZATION_DECIMALS
#define CRYPTONOTE_DISPLAY_DECIMAL_POINT
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 4699 of file blockchain.cpp.

4700 {
4701  static const std::vector<HardFork::Params> mainnet_heights = []()
4702  {
4703  std::vector<HardFork::Params> heights;
4704  for (const auto& i : mainnet_hard_forks)
4705  heights.emplace_back(i.version, i.height, i.threshold, i.time);
4706  return heights;
4707  }();
4708  static const std::vector<HardFork::Params> testnet_heights = []()
4709  {
4710  std::vector<HardFork::Params> heights;
4711  for (const auto& i : testnet_hard_forks)
4712  heights.emplace_back(i.version, i.height, i.threshold, i.time);
4713  return heights;
4714  }();
4715  static const std::vector<HardFork::Params> stagenet_heights = []()
4716  {
4717  std::vector<HardFork::Params> heights;
4718  for (const auto& i : stagenet_hard_forks)
4719  heights.emplace_back(i.version, i.height, i.threshold, i.time);
4720  return heights;
4721  }();
4722  static const std::vector<HardFork::Params> dummy;
4723  switch (nettype)
4724  {
4725  case MAINNET: return mainnet_heights;
4726  case TESTNET: return testnet_heights;
4727  case STAGENET: return stagenet_heights;
4728  default: return dummy;
4729  }
4730 }

◆ 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 4694 of file blockchain.cpp.

4695 {
4696  return m_hardfork->get_state();
4697 }
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 848 of file blockchain.h.

848 { return m_hardfork->get(height); }
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 4732 of file blockchain.cpp.

4733 {
4734  return m_hardfork->get_voting_info(version, window, votes, threshold, earliest_height, voting);
4735 }
uint8_t threshold
Definition: blockchain.cpp:92
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
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 822 of file blockchain.h.

822 { return m_hardfork->get_ideal_version(); }
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 839 of file blockchain.h.

839 { return m_hardfork->get_ideal_version(height); }
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 970 of file blockchain.cpp.

971 {
972  uint64_t height = m_db->height();
973  if (blocks > height)
974  blocks = height;
975  std::vector<time_t> timestamps(blocks);
976  while (blocks--)
977  timestamps[blocks] = m_db->get_block_timestamp(height - blocks - 1);
978  return timestamps;
979 }
Here is the call graph for this function:

◆ get_mempool_tx_livetime()

uint32_t Blockchain::get_mempool_tx_livetime ( ) const

Definition at line 4655 of file blockchain.cpp.

4656 {
4658  {
4660  }
4662 }
uint8_t get_hard_fork_version(uint64_t height) const
returns the actual hardfork version for a given block height
Definition: blockchain.h:848
#define CRYPTONOTE_MEMPOOL_TX_LIVETIME
#define CRYPTONOTE_MEMPOOL_TX_LIVETIME_V6
Here is the call graph for this function:

◆ get_nettype()

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

get blockchain nettype

Definition at line 1048 of file blockchain.h.

1048 { 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 829 of file blockchain.h.

829 { 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 3952 of file blockchain.cpp.

3953 {
3955 
3956  const uint64_t db_height = m_db->height();
3957  const uint64_t nblocks = std::min<uint64_t>(m_long_term_block_weights_window, db_height);
3958 
3959  const uint8_t hf_version = get_current_hard_fork_version();
3960  if (hf_version < HF_VERSION_LONG_TERM_BLOCK_WEIGHT)
3961  return block_weight;
3962 
3963  uint64_t long_term_median = get_long_term_block_weight_median(db_height - nblocks, nblocks);
3964  uint64_t long_term_effective_median_block_weight = std::max<uint64_t>(CRYPTONOTE_BLOCK_GRANTED_FULL_REWARD_ZONE_V5, long_term_median);
3965 
3966  uint64_t short_term_constraint = long_term_effective_median_block_weight + long_term_effective_median_block_weight * 2 / 5;
3967  uint64_t long_term_block_weight = std::min<uint64_t>(block_weight, short_term_constraint);
3968 
3969  return long_term_block_weight;
3970 }
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
#define PERF_TIMER(name)
Definition: perf_timer.h:82
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 2087 of file blockchain.cpp.

2088 {
2089  uint64_t num_outs = m_db->get_num_outputs(amount);
2090  // ensure we don't include outputs that aren't yet eligible to be used
2091  // outpouts are sorted by height
2092  const uint64_t blockchain_height = m_db->height();
2093  while (num_outs > 0)
2094  {
2095  const tx_out_index toi = m_db->get_output_tx_and_index(amount, num_outs - 1);
2096  const uint64_t height = m_db->get_tx_block_height(toi.first);
2098  break;
2099  --num_outs;
2100  }
2101 
2102  return num_outs;
2103 }
virtual uint64_t get_tx_block_height(const crypto::hash &h) const =0
fetches the height of a transaction's block
virtual uint64_t get_num_outputs(const uint64_t &amount) const =0
fetches the number of outputs of a given amount
virtual tx_out_index get_output_tx_and_index(const uint64_t &amount, const uint64_t &index) const =0
gets an output's tx hash and index
#define ETN_DEFAULT_TX_SPENDABLE_AGE_V8
#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 2165 of file blockchain.cpp.

2166 {
2167  // rct outputs don't exist before v4
2168  if (amount == 0)
2169  {
2170  switch (m_nettype)
2171  {
2172  case STAGENET: start_height = stagenet_hard_forks[3].height; break;
2173  case TESTNET: start_height = testnet_hard_forks[3].height; break;
2174  case MAINNET: start_height = mainnet_hard_forks[3].height; break;
2175  case FAKECHAIN: start_height = 0; break;
2176  default: return false;
2177  }
2178  }
2179  else
2180  start_height = 0;
2181  base = 0;
2182 
2183  if (to_height > 0 && to_height < from_height)
2184  return false;
2185 
2186  const uint64_t real_start_height = start_height;
2187  if (from_height > start_height)
2188  start_height = from_height;
2189 
2190  distribution.clear();
2191  uint64_t db_height = m_db->height();
2192  if (db_height == 0)
2193  return false;
2194  if (start_height >= db_height || to_height >= db_height)
2195  return false;
2196  if (amount == 0)
2197  {
2198  std::vector<uint64_t> heights;
2199  heights.reserve(to_height + 1 - start_height);
2200  uint64_t real_start_height = start_height > 0 ? start_height-1 : start_height;
2201  for (uint64_t h = real_start_height; h <= to_height; ++h)
2202  heights.push_back(h);
2203  distribution = m_db->get_block_cumulative_rct_outputs(heights);
2204  if (start_height > 0)
2205  {
2206  base = distribution[0];
2207  distribution.erase(distribution.begin());
2208  }
2209  return true;
2210  }
2211  else
2212  {
2213  return m_db->get_output_distribution(amount, start_height, to_height, distribution, base);
2214  }
2215 }
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'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 4742 of file blockchain.cpp.

4743 {
4744  return m_db->get_output_histogram(amounts, unlocked, recent_cutoff, min_count);
4745 }
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 2105 of file blockchain.cpp.

2106 {
2107  output_data_t data = m_db->get_output_key(amount, global_index);
2108  return data.pubkey;
2109 }
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's data
a struct containing output metadata
crypto::public_key pubkey
the output's public key (for spend verification)
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 2156 of file blockchain.cpp.

2157 {
2158  const auto o_data = m_db->get_output_key(amount, index);
2159  key = o_data.pubkey;
2160  mask = o_data.commitment;
2161  tx_out_index toi = m_db->get_output_tx_and_index(amount, index);
2162  unlocked = is_tx_spendtime_unlocked(m_db->get_tx_unlock_time(toi.first));
2163 }
virtual uint64_t get_tx_unlock_time(const crypto::hash &h) const =0
fetch a transaction's unlock time/height
const char * key
Definition: hmac_keccak.cpp:39
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 2112 of file blockchain.cpp.

2113 {
2114  LOG_PRINT_L3("Blockchain::" << __func__);
2115  CRITICAL_REGION_LOCAL(m_blockchain_lock);
2116 
2117  res.outs.clear();
2118  res.outs.reserve(req.outputs.size());
2119 
2120  std::vector<cryptonote::output_data_t> data;
2121  try
2122  {
2123  std::vector<uint64_t> amounts, offsets;
2124  amounts.reserve(req.outputs.size());
2125  offsets.reserve(req.outputs.size());
2126  for (const auto &i: req.outputs)
2127  {
2128  amounts.push_back(i.amount);
2129  offsets.push_back(i.index);
2130  }
2131  m_db->get_output_key(epee::span<const uint64_t>(amounts.data(), amounts.size()), offsets, data);
2132  if (data.size() != req.outputs.size())
2133  {
2134  MERROR("Unexpected output data size: expected " << req.outputs.size() << ", got " << data.size());
2135  return false;
2136  }
2137  for (const auto &t: data)
2138  res.outs.push_back({t.pubkey, t.commitment, is_tx_spendtime_unlocked(t.unlock_time), t.height, crypto::null_hash});
2139 
2140  if (req.get_txid)
2141  {
2142  for (size_t i = 0; i < req.outputs.size(); ++i)
2143  {
2144  tx_out_index toi = m_db->get_output_tx_and_index(req.outputs[i].amount, req.outputs[i].index);
2145  res.outs[i].txid = toi.first;
2146  }
2147  }
2148  }
2149  catch (const std::exception &e)
2150  {
2151  return false;
2152  }
2153  return true;
2154 }
Non-owning sequence of data. Does not deep copy.
Definition: span.h:57
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 745 of file blockchain.cpp.

746 {
747  LOG_PRINT_L3("Blockchain::" << __func__);
748  CRITICAL_REGION_LOCAL(m_blockchain_lock);
749  uint64_t i = 0;
750  uint64_t current_multiplier = 1;
751  uint64_t sz = m_db->height();
752 
753  if(!sz)
754  return true;
755 
756  db_rtxn_guard rtxn_guard(m_db);
757  bool genesis_included = false;
758  uint64_t current_back_offset = 1;
759  while(current_back_offset < sz)
760  {
761  ids.push_back(m_db->get_block_hash_from_height(sz - current_back_offset));
762 
763  if(sz-current_back_offset == 0)
764  {
765  genesis_included = true;
766  }
767  if(i < 10)
768  {
769  ++current_back_offset;
770  }
771  else
772  {
773  current_multiplier *= 2;
774  current_back_offset += current_multiplier;
775  }
776  ++i;
777  }
778 
779  if (!genesis_included)
780  {
781  ids.push_back(m_db->get_block_hash_from_height(0));
782  }
783 
784  return true;
785 }
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 2372 of file blockchain.cpp.

2373 {
2374  LOG_PRINT_L3("Blockchain::" << __func__);
2375  CRITICAL_REGION_LOCAL(m_blockchain_lock);
2376 
2377  reserve_container(txs, txs_ids.size());
2378  for (const auto& tx_hash : txs_ids)
2379  {
2380  try
2381  {
2383  if (m_db->get_pruned_tx_blob(tx_hash, tx))
2384  {
2385  txs.push_back(std::make_tuple(tx_hash, std::move(tx), crypto::null_hash, cryptonote::blobdata()));
2386  if (!is_v1_tx(std::get<1>(txs.back())) && !m_db->get_prunable_tx_hash(tx_hash, std::get<2>(txs.back())))
2387  {
2388  MERROR("Prunable data hash not found for " << tx_hash);
2389  return false;
2390  }
2391  if (!m_db->get_prunable_tx_blob(tx_hash, std::get<3>(txs.back())))
2392  std::get<3>(txs.back()).clear();
2393  }
2394  else
2395  missed_txs.push_back(tx_hash);
2396  }
2397  catch (const std::exception& e)
2398  {
2399  return false;
2400  }
2401  }
2402  return true;
2403 }
virtual bool get_prunable_tx_hash(const crypto::hash &tx_hash, crypto::hash &prunable_hash) const =0
fetches the prunable transaction 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
virtual bool get_prunable_tx_blob(const crypto::hash &h, cryptonote::blobdata &tx) const =0
fetches the prunable transaction blob with the given hash
bool is_v1_tx(const blobdata_ref &tx_blob)
tuple make_tuple()
Definition: gtest-tuple.h:675
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 723 of file blockchain.cpp.

724 {
725  LOG_PRINT_L3("Blockchain::" << __func__);
726  // WARNING: this function does not take m_blockchain_lock, and thus should only call read only
727  // m_db functions which do not depend on one another (ie, no getheight + gethash(height-1), as
728  // well as not accessing class members, even read only (ie, m_invalid_blocks). The caller must
729  // lock if it is otherwise needed.
730  return m_db->top_block_hash();
731 }
virtual crypto::hash top_block_hash(uint64_t *block_height=NULL) const =0
fetch the top block'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 716 of file blockchain.cpp.

717 {
718  LOG_PRINT_L3("Blockchain::" << __func__);
719  CRITICAL_REGION_LOCAL(m_blockchain_lock);
720  return m_db->top_block_hash(&height);
721 }
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 2593 of file blockchain.cpp.

2594 {
2595  LOG_PRINT_L3("Blockchain::" << __func__);
2596  // WARNING: this function does not take m_blockchain_lock, and thus should only call read only
2597  // m_db functions which do not depend on one another (ie, no getheight + gethash(height-1), as
2598  // well as not accessing class members, even read only (ie, m_invalid_blocks). The caller must
2599  // lock if it is otherwise needed.
2600  return m_db->get_tx_count();
2601 }
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 2406 of file blockchain.cpp.

2407 {
2408  LOG_PRINT_L3("Blockchain::" << __func__);
2409  CRITICAL_REGION_LOCAL(m_blockchain_lock);
2410 
2411  reserve_container(txs, txs_ids.size());
2412  for (const auto& tx_hash : txs_ids)
2413  {
2414  try
2415  {
2417  if (m_db->get_tx_blob(tx_hash, tx))
2418  {
2419  txs.push_back(transaction());
2420  if (!parse_and_validate_tx_from_blob(tx, txs.back()))
2421  {
2422  LOG_ERROR("Invalid transaction");
2423  return false;
2424  }
2425  }
2426  else
2427  missed_txs.push_back(tx_hash);
2428  }
2429  catch (const std::exception& e)
2430  {
2431  return false;
2432  }
2433  }
2434  return true;
2435 }
virtual bool get_tx_blob(const crypto::hash &h, cryptonote::blobdata &tx) const =0
fetches the transaction blob with the given hash
bool parse_and_validate_tx_from_blob(const blobdata &tx_blob, transaction &tx)
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 2334 of file blockchain.cpp.

2335 {
2336  LOG_PRINT_L3("Blockchain::" << __func__);
2337  CRITICAL_REGION_LOCAL(m_blockchain_lock);
2338 
2339  reserve_container(txs, txs_ids.size());
2340  for (const auto& tx_hash : txs_ids)
2341  {
2342  try
2343  {
2345  if (pruned && m_db->get_pruned_tx_blob(tx_hash, tx))
2346  txs.push_back(std::move(tx));
2347  else if (!pruned && m_db->get_tx_blob(tx_hash, tx))
2348  txs.push_back(std::move(tx));
2349  else
2350  missed_txs.push_back(tx_hash);
2351  }
2352  catch (const std::exception& e)
2353  {
2354  return false;
2355  }
2356  }
2357  return true;
2358 }
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,
size_t  n_txes,
std::vector< std::vector< uint64_t >> &  indexs 
) const

Definition at line 2673 of file blockchain.cpp.

2674 {
2675  LOG_PRINT_L3("Blockchain::" << __func__);
2676  CRITICAL_REGION_LOCAL(m_blockchain_lock);
2677  uint64_t tx_index;
2678  if (!m_db->tx_exists(tx_id, tx_index))
2679  {
2680  MERROR_VER("get_tx_outputs_gindexs failed to find transaction with id = " << tx_id);
2681  return false;
2682  }
2683 
2684  //no output indexes for tx.version >= 2 (public tx)
2685  if (m_db->get_tx(tx_id).version >= 2)
2686  return true;
2687 
2688  indexs = m_db->get_tx_amount_output_indices(tx_index, n_txes);
2689  CHECK_AND_ASSERT_MES(n_txes == indexs.size(), false, "Wrong indexs size");
2690 
2691  return true;
2692 }
virtual bool tx_exists(const crypto::hash &h) const =0
check if a transaction with a given hash exists
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's outputs
virtual transaction get_tx(const crypto::hash &h) const
fetches the transaction with the given hash
Here is the call graph for this function:

◆ get_tx_outputs_gindexs() [2/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 2694 of file blockchain.cpp.

2695 {
2696  LOG_PRINT_L3("Blockchain::" << __func__);
2697  CRITICAL_REGION_LOCAL(m_blockchain_lock);
2698  uint64_t tx_index;
2699  if (!m_db->tx_exists(tx_id, tx_index))
2700  {
2701  MERROR_VER("get_tx_outputs_gindexs failed to find transaction with id = " << tx_id);
2702  return false;
2703  }
2704 
2705  //no output indexes for tx.version >= 2 (public tx)
2706  if (m_db->get_tx(tx_id).version >= 2)
2707  return true;
2708 
2709  std::vector<std::vector<uint64_t>> indices = m_db->get_tx_amount_output_indices(tx_index, 1);
2710  CHECK_AND_ASSERT_MES(indices.size() == 1, false, "Wrong indices size");
2711  indexs = indices.front();
2712  return true;
2713 }
Here is the call graph for this function:
Here is the caller graph for this function:

◆ get_txpool_tx_blob() [1/2]

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

Definition at line 4645 of file blockchain.cpp.

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

◆ get_txpool_tx_blob() [2/2]

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

Definition at line 4640 of file blockchain.cpp.

4641 {
4642  return m_db->get_txpool_tx_blob(txid, bd);
4643 }
Here is the call graph for this function:
Here is the caller graph for this function:

◆ get_txpool_tx_count()

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

Definition at line 4630 of file blockchain.cpp.

4631 {
4632  return m_db->get_txpool_tx_count(include_unrelayed_txes);
4633 }
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 4635 of file blockchain.cpp.

4636 {
4637  return m_db->get_txpool_tx_meta(txid, meta);
4638 }
virtual bool get_txpool_tx_meta(const crypto::hash &txid, txpool_tx_meta_t &meta) const =0
get a txpool transaction'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 4932 of file blockchain.cpp.

4932  {
4933 
4934  block blk;
4936 
4937  std::string signatory = std::string(blk.signatory.begin(), blk.signatory.end());
4938  return m_validators->getValidatorByKey(boost::algorithm::hex(signatory));
4939 
4940 }
crypto::hash get_block_id_by_height(uint64_t height) const
gets a block's hash given a height
Definition: blockchain.cpp:787
Validator getValidatorByKey(string key)
Definition: validators.h:188
std::vector< uint8_t > signatory
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 2018 of file blockchain.cpp.

2019 {
2020  LOG_PRINT_L3("Blockchain::" << __func__);
2021  CRITICAL_REGION_LOCAL(m_blockchain_lock);
2022  db_rtxn_guard rtxn_guard (m_db);
2023  rsp.current_blockchain_height = get_current_blockchain_height();
2024  std::vector<std::pair<cryptonote::blobdata,block>> blocks;
2025  get_blocks(arg.blocks, blocks, rsp.missed_ids);
2026 
2027  for (auto& bl: blocks)
2028  {
2029  std::vector<crypto::hash> missed_tx_ids;
2030 
2031  rsp.blocks.push_back(block_complete_entry());
2032  block_complete_entry& e = rsp.blocks.back();
2033 
2034  // FIXME: s/rsp.missed_ids/missed_tx_id/ ? Seems like rsp.missed_ids
2035  // is for missed blocks, not missed transactions as well.
2036  get_transactions_blobs(bl.second.tx_hashes, e.txs, missed_tx_ids);
2037 
2038  if (missed_tx_ids.size() != 0)
2039  {
2040  // do not display an error if the peer asked for an unpruned block which we are not meant to have
2042  {
2043  LOG_ERROR("Error retrieving blocks, missed " << missed_tx_ids.size()
2044  << " transactions for block with hash: " << get_block_hash(bl.second)
2045  << std::endl
2046  );
2047  }
2048 
2049  // append missed transaction hashes to response missed_ids field,
2050  // as done below if any standalone transactions were requested
2051  // and missed.
2052  rsp.missed_ids.insert(rsp.missed_ids.end(), missed_tx_ids.begin(), missed_tx_ids.end());
2053  return false;
2054  }
2055 
2056  //pack block
2057  e.block = std::move(bl.first);
2058  }
2059  //get and pack other transactions, if needed
2060  get_transactions_blobs(arg.txs, rsp.txs, rsp.missed_ids);
2061 
2062  return true;
2063 }
bool has_unpruned_block(uint64_t block_height, uint64_t blockchain_height, uint32_t pruning_seed)
Definition: pruning.cpp:44
std::vector< blobdata > txs
blobdata block
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 2560 of file blockchain.cpp.

2561 {
2562  LOG_PRINT_L3("Blockchain::" << __func__);
2563  CRITICAL_REGION_LOCAL(m_blockchain_lock);
2564 
2565  if(m_db->block_exists(id))
2566  {
2567  LOG_PRINT_L2("block " << id << " found in main chain");
2568  return true;
2569  }
2570 
2571  if(m_alternative_chains.count(id))
2572  {
2573  LOG_PRINT_L2("block " << id << " found in m_alternative_chains");
2574  return true;
2575  }
2576 
2577  if(m_invalid_blocks.count(id))
2578  {
2579  LOG_PRINT_L2("block " << id << " found in m_invalid_blocks");
2580  return true;
2581  }
2582 
2583  return false;
2584 }
#define LOG_PRINT_L2(x)
Definition: misc_log_ex.h:101
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 164 of file blockchain.cpp.

165 {
166  LOG_PRINT_L3("Blockchain::" << __func__);
167  // WARNING: this function does not take m_blockchain_lock, and thus should only call read only
168  // m_db functions which do not depend on one another (ie, no getheight + gethash(height-1), as
169  // well as not accessing class members, even read only (ie, m_invalid_blocks). The caller must
170  // lock if it is otherwise needed.
171  return m_db->tx_exists(id);
172 }
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 174 of file blockchain.cpp.

175 {
176  LOG_PRINT_L3("Blockchain::" << __func__);
177  // WARNING: this function does not take m_blockchain_lock, and thus should only call read only
178  // m_db functions which do not depend on one another (ie, no getheight + gethash(height-1), as
179  // well as not accessing class members, even read only (ie, m_invalid_blocks). The caller must
180  // lock if it is otherwise needed.
181  return m_db->has_key_image(key_im);
182 }
virtual bool has_key_image(const crypto::key_image &img) const =0
check if a key image is stored as spent
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 331 of file blockchain.cpp.

332 {
333  LOG_PRINT_L3("Blockchain::" << __func__);
334 
335  CHECK_AND_ASSERT_MES(nettype != FAKECHAIN || test_options, false, "fake chain network type used without options");
336 
337  CRITICAL_REGION_LOCAL(m_tx_pool);
338  CRITICAL_REGION_LOCAL1(m_blockchain_lock);
339 
340  if (db == nullptr)
341  {
342  LOG_ERROR("Attempted to init Blockchain with null DB");
343  return false;
344  }
345  if (!db->is_open())
346  {
347  LOG_ERROR("Attempted to init Blockchain with unopened DB");
348  delete db;
349  return false;
350  }
351 
352  m_db = db;
353 
354  m_nettype = test_options != NULL ? FAKECHAIN : nettype;
355  m_offline = offline;
356  m_fixed_difficulty = fixed_difficulty;
357  m_ignore_bsig = ignore_bsig;
358  m_fallback_to_pow = fallback_to_pow;
359  if (m_hardfork == nullptr)
360  {
361  if (m_nettype == FAKECHAIN || m_nettype == STAGENET)
362  m_hardfork = new HardFork(*db, 1, 0);
363  else if (m_nettype == TESTNET)
364  m_hardfork = new HardFork(*db, 1, testnet_hard_fork_version_1_till);
365  else
366  m_hardfork = new HardFork(*db, 1, mainnet_hard_fork_version_1_till);
367  }
368  if (m_nettype == FAKECHAIN)
369  {
370  for (size_t n = 0; test_options->hard_forks[n].first; ++n)
371  m_hardfork->add_fork(test_options->hard_forks[n].first, test_options->hard_forks[n].second, 0, n + 1);
372  }
373  else if (m_nettype == TESTNET)
374  {
375  for (size_t n = 0; n < sizeof(testnet_hard_forks) / sizeof(testnet_hard_forks[0]); ++n)
376  m_hardfork->add_fork(testnet_hard_forks[n].version, testnet_hard_forks[n].height, testnet_hard_forks[n].threshold, testnet_hard_forks[n].time);
377  }
378  else if (m_nettype == STAGENET)
379  {
380  for (size_t n = 0; n < sizeof(stagenet_hard_forks) / sizeof(stagenet_hard_forks[0]); ++n)
381  m_hardfork->add_fork(stagenet_hard_forks[n].version, stagenet_hard_forks[n].height, stagenet_hard_forks[n].threshold, stagenet_hard_forks[n].time);
382  }
383  else
384  {
385  for (size_t n = 0; n < sizeof(mainnet_hard_forks) / sizeof(mainnet_hard_forks[0]); ++n)
386  m_hardfork->add_fork(mainnet_hard_forks[n].version, mainnet_hard_forks[n].height, mainnet_hard_forks[n].threshold, mainnet_hard_forks[n].time);
387  }
388  m_hardfork->init();
389 
390  m_db->set_hard_fork(m_hardfork);
391 
392  // if the blockchain is new, add the genesis block
393  // this feels kinda kludgy to do it this way, but can be looked at later.
394  // TODO: add function to create and store genesis block,
395  // taking testnet into account
396  if(!m_db->height())
397  {
398  MINFO("Blockchain not loaded, generating genesis block.");
399  block bl;
400  block_verification_context bvc = boost::value_initialized<block_verification_context>();
402  db_wtxn_guard wtxn_guard(m_db);
403  add_new_block(bl, bvc);
404  CHECK_AND_ASSERT_MES(!bvc.m_verification_failed, false, "Failed to add genesis block to blockchain");
405  }
406  // TODO: if blockchain load successful, verify blockchain against both
407  // hard-coded and runtime-loaded (and enforced) checkpoints.
408  else
409  {
410  }
411 
412  if (m_nettype != FAKECHAIN)
413  {
414  m_db->set_batch_transactions(true);
415  }
416 
417  db_rtxn_guard rtxn_guard(m_db);
418 
419  // check how far behind we are
420  uint64_t top_block_timestamp = m_db->get_top_block_timestamp();
421  uint64_t timestamp_diff = time(NULL) - top_block_timestamp;
422 
423  // genesis block has no timestamp, could probably change it to have timestamp of 1397818133...
424  if(!top_block_timestamp)
425  timestamp_diff = time(NULL) - 1397818133;
426 
427  // create general purpose async service queue
428 
429  m_async_work_idle = std::unique_ptr < boost::asio::io_service::work > (new boost::asio::io_service::work(m_async_service));
430  // we only need 1
431  m_async_pool.create_thread(boost::bind(&boost::asio::io_service::run, &m_async_service));
432 
433 #if defined(PER_BLOCK_CHECKPOINT)
434  if (m_nettype != FAKECHAIN)
435  load_compiled_in_block_hashes(get_checkpoints);
436 #endif
437 
438  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());
439 
440  rtxn_guard.stop();
441 
442  uint64_t num_popped_blocks = 0;
443  while (!m_db->is_read_only())
444  {
445  uint64_t top_height;
446  const crypto::hash top_id = m_db->top_block_hash(&top_height);
447  const block top_block = m_db->get_top_block();
448  const uint8_t ideal_hf_version = get_ideal_hard_fork_version(top_height);
449  if (ideal_hf_version <= 1 || ideal_hf_version == top_block.major_version)
450  {
451  if (num_popped_blocks > 0)
452  MGINFO("Initial popping done, top block: " << top_id << ", top height: " << top_height << ", block version: " << (uint64_t)top_block.major_version);
453  break;
454  }
455  else
456  {
457  if (num_popped_blocks == 0)
458  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);
459  if (num_popped_blocks % 100 == 0)
460  MGINFO("Popping blocks... " << top_height);
461  ++num_popped_blocks;
462  block popped_block;
463  std::vector<transaction> popped_txs;
464  try
465  {
466  m_db->pop_block(popped_block, popped_txs);
467  }
468  // anything that could cause this to throw is likely catastrophic,
469  // so we re-throw
470  catch (const std::exception& e)
471  {
472  MERROR("Error popping block from blockchain: " << e.what());
473  throw;
474  }
475  catch (...)
476  {
477  MERROR("Error popping block from blockchain, throwing!");
478  throw;
479  }
480  }
481  }
482 
483  if (num_popped_blocks > 0)
484  {
485  m_timestamps_and_difficulties_height = 0;
487  uint64_t top_block_height;
488  crypto::hash top_block_hash = get_tail_id(top_block_height);
489  m_tx_pool.on_blockchain_dec(top_block_height, top_block_hash);
490  }
491 
493  {
494  m_long_term_block_weights_window = test_options->long_term_block_weight_window;
495  m_long_term_block_weights_cache_rolling_median = epee::misc_utils::rolling_median_t<uint64_t>(m_long_term_block_weights_window);
496  }
497 
498  {
499  db_txn_guard txn_guard(m_db, m_db->is_read_only());
500  if (!update_next_cumulative_weight_limit())
501  return false;
502  }
503  return true;
504 }
virtual void set_hard_fork(HardFork *hf)
virtual bool is_read_only() const =0
is BlockchainDB in read-only mode?
virtual uint64_t get_top_block_timestamp() const =0
fetch the top block's timestamp
virtual block get_top_block() const =0
fetch the top block
bool is_open() const
Gets the current open/ready state of the BlockchainDB.
virtual void set_batch_transactions(bool)=0
sets whether or not to batch transactions
uint8_t get_ideal_hard_fork_version() const
returns the newest hardfork version known to the blockchain
Definition: blockchain.h:822
bool add_new_block(const block &bl_, block_verification_context &bvc)
adds a block to the blockchain
void init()
initialize the object
Definition: hardfork.cpp:169
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 reorganize_from_chain_height(uint64_t height)
Definition: hardfork.cpp:242
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:1017
#define MGINFO(x)
Definition: misc_log_ex.h:80
std::string const GENESIS_TX
uint32_t const GENESIS_NONCE
bool generate_genesis_block(block &bl, std::string const &genesis_tx, uint32_t nonce)
std::string get_time_interval_string(const time_t &time_)
Definition: time_helper.h:120
const size_t long_term_block_weight_window
const std::pair< uint8_t, uint64_t > * hard_forks
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 506 of file blockchain.cpp.

507 {
508  if (hf != nullptr)
509  m_hardfork = hf;
510  bool res = init(db, nettype, offline, NULL);
511  if (hf == nullptr)
512  hf = m_hardfork;
513  return res;
514 }
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:331
Here is the call graph for this function:

◆ is_within_compiled_block_hash_area() [1/2]

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

Definition at line 1006 of file blockchain.h.

1006 { return is_within_compiled_block_hash_area(m_db->height()); }
bool is_within_compiled_block_hash_area() const
Definition: blockchain.h:1006
Here is the call graph for this function:
Here is the caller graph for this function:

◆ is_within_compiled_block_hash_area() [2/2]

bool Blockchain::is_within_compiled_block_hash_area ( uint64_t  height) const

Definition at line 4869 of file blockchain.cpp.

4870 {
4871 #if defined(PER_BLOCK_CHECKPOINT)
4872  return height < m_blocks_hash_check.size();
4873 #else
4874  return false;
4875 #endif
4876 }

◆ 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 2830 of file blockchain.cpp.

2831 {
2832  LOG_PRINT_L3("Blockchain::" << __func__);
2833 
2834  for (const txin_v& in: tx.vin)
2835  {
2836  if(in.type() == typeid(txin_to_key))
2837  {
2838  const auto &in_to_key = boost::get<txin_to_key>(in);
2839  if(have_tx_keyimg_as_spent(in_to_key.k_image))
2840  return true;
2841  }
2842  }
2843 
2844  return false;
2845 }
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:174
boost::variant< txin_gen, txin_to_script, txin_to_scripthash, txin_to_key, txin_to_key_public > txin_v
Here is the call graph for this function:

◆ lock()

void Blockchain::lock ( void  )

Definition at line 4878 of file blockchain.cpp.

4879 {
4880  m_blockchain_lock.lock();
4881 }
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 984 of file blockchain.cpp.

984  {
985 
986  auto height = m_db->height();
987  const uint64_t v8height = m_nettype == TESTNET ? 446674 : 589169;
988 
989  if(height != v8height) {
990  return;
991  }
992 
993  const uint64_t v7height = m_nettype == TESTNET ? 215000 : 324500;
994  const size_t V7_DIFFICULTY_BLOCKS_COUNT = 735;
995  const size_t V7_DIFFICULTY_TARGET = 120;
996 
997  std::vector<uint64_t> timestamps;
998  std::vector<difficulty_type> difficulties;
999 
1000  uint64_t start_height = v7height - V7_DIFFICULTY_BLOCKS_COUNT;
1001 
1002  // Populate the timestamps & difficulties vectors with data from 735 blocks prior to V7 fork height (324500)
1003  for(uint64_t i = 0; start_height + i < v7height; i++) {
1004  timestamps.push_back(m_db->get_block_timestamp(start_height + i));
1005  difficulties.push_back(m_db->get_block_cumulative_difficulty(start_height + i));
1006  }
1007 
1008  // Calculate the cumulative difficulty of block 324500 based on the 735 prior blocks' timestamp and difficulty values
1009  difficulty_type diff = difficulties.back() + next_difficulty(timestamps, difficulties, V7_DIFFICULTY_TARGET, 1);
1010 
1011  // Override block's 324500 cumulative difficulty
1012  m_db->set_block_cumulative_difficulty(v7height, diff);
1013 
1014  // Iterate over V7 blocks, starting from 324500 until current block height
1015  for(uint64_t i = v7height; i < height - 1; i++) {
1016 
1017  // Add "324500 + i" timestamp & difficulty into the vectors
1018  timestamps.push_back(m_db->get_block_timestamp(i));
1019  difficulties.push_back(m_db->get_block_cumulative_difficulty(i));
1020 
1021  // Erase the vector's first position maintaining its 735 size
1022  timestamps.erase(timestamps.begin());
1023  difficulties.erase(difficulties.begin());
1024 
1025  // Calculate/set the correct cumulative difficulty of block "324500 + i"
1026  diff = difficulties.back() + next_difficulty(timestamps, difficulties, V7_DIFFICULTY_TARGET, 1);
1027  m_db->set_block_cumulative_difficulty(i + 1, diff);
1028  }
1029 
1030  m_timestamps.clear();
1031  m_difficulties.clear();
1032 }
virtual void set_block_cumulative_difficulty(uint64_t height, difficulty_type diff)=0
sets a block's cumulative difficulty
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 2715 of file blockchain.cpp.

2716 {
2717 #if defined(PER_BLOCK_CHECKPOINT)
2718  // check if we're doing per-block checkpointing
2719  if (m_db->height() < m_blocks_hash_check.size())
2720  {
2722  m_blocks_txs_check.push_back(get_transaction_hash(tx));
2724  if(m_show_time_stats)
2725  {
2726  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;
2727  MINFO("HASH: " << "-" << " I/M/O: " << tx.vin.size() << "/" << ring_size << "/" << tx.vout.size() << " H: " << 0 << " chcktx: " << a);
2728  }
2729  }
2730 #endif
2731 }
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 4243 of file blockchain.cpp.

4244 {
4245  try
4246  {
4247  m_db->get_output_key(epee::span<const uint64_t>(&amount, 1), offsets, outputs, true);
4248  }
4249  catch (const std::exception& e)
4250  {
4251  MERROR_VER("EXCEPTION: " << e.what());
4252  }
4253  catch (...)
4254  {
4255 
4256  }
4257 }
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 586 of file blockchain.cpp.

587 {
588  uint64_t i;
589  CRITICAL_REGION_LOCAL(m_tx_pool);
590  CRITICAL_REGION_LOCAL1(m_blockchain_lock);
591 
592  bool stop_batch = m_db->batch_start();
593 
594  try
595  {
596  const uint64_t blockchain_height = m_db->height();
597  if (blockchain_height > 0)
598  nblocks = std::min(nblocks, blockchain_height - 1);
599  for (i=0; i < nblocks; ++i)
600  {
601  pop_block_from_blockchain();
602  }
603  }
604  catch (const std::exception& e)
605  {
606  LOG_ERROR("Error when popping blocks after processing " << i << " blocks: " << e.what());
607  if (stop_batch)
608  m_db->batch_abort();
609  return;
610  }
611 
612  if (stop_batch)
613  m_db->batch_stop();
614 }
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 4266 of file blockchain.cpp.

4267 {
4268  MTRACE("Blockchain::" << __func__);
4269  TIME_MEASURE_START(prepare);
4270  bool stop_batch;
4271  uint64_t bytes = 0;
4272  size_t total_txs = 0;
4273  blocks.clear();
4274 
4275  // Order of locking must be:
4276  // m_incoming_tx_lock (optional)
4277  // m_tx_pool lock
4278  // blockchain lock
4279  //
4280  // Something which takes the blockchain lock may never take the txpool lock
4281  // if it has not provably taken the txpool lock earlier
4282  //
4283  // The txpool lock is now taken in prepare_handle_incoming_blocks
4284  // and released in cleanup_handle_incoming_blocks. This avoids issues
4285  // when something uses the pool, which now uses the blockchain and
4286  // needs a batch, since a batch could otherwise be active while the
4287  // txpool and blockchain locks were not held
4288 
4289  m_tx_pool.lock();
4290  CRITICAL_REGION_LOCAL1(m_blockchain_lock);
4291 
4292  if(blocks_entry.size() == 0)
4293  return false;
4294 
4295  for (const auto &entry : blocks_entry)
4296  {
4297  bytes += entry.block.size();
4298  for (const auto &tx_blob : entry.txs)
4299  {
4300  bytes += tx_blob.size();
4301  }
4302  total_txs += entry.txs.size();
4303  }
4304  m_bytes_to_sync += bytes;
4305  while (!(stop_batch = m_db->batch_start(blocks_entry.size(), bytes))) {
4306  m_blockchain_lock.unlock();
4307  m_tx_pool.unlock();
4309  m_tx_pool.lock();
4310  m_blockchain_lock.lock();
4311  }
4312  m_batch_success = true;
4313 
4314  const uint64_t height = m_db->height();
4315  if ((height + blocks_entry.size()) < m_blocks_hash_check.size())
4316  return true;
4317 
4318  bool blocks_exist = false;
4320  unsigned threads = tpool.get_max_concurrency();
4321  blocks.resize(blocks_entry.size());
4322 
4323  if (1)
4324  {
4325  // limit threads, default limit = 4
4326  if(threads > m_max_prepare_blocks_threads)
4327  threads = m_max_prepare_blocks_threads;
4328 
4329  unsigned int batches = blocks_entry.size() / threads;
4330  unsigned int extra = blocks_entry.size() % threads;
4331  MDEBUG("block_batches: " << batches);
4332  std::vector<std::unordered_map<crypto::hash, crypto::hash>> maps(threads);
4333  auto it = blocks_entry.begin();
4334  unsigned blockidx = 0;
4335 
4336  const crypto::hash tophash = m_db->top_block_hash();
4337  for (unsigned i = 0; i < threads; i++)
4338  {
4339  for (unsigned int j = 0; j < batches; j++, ++blockidx)
4340  {
4341  block &block = blocks[blockidx];
4342  crypto::hash block_hash;
4343 
4344  if (!parse_and_validate_block_from_blob(it->block, block, block_hash))
4345  return false;
4346 
4347  // check first block and skip all blocks if its not chained properly
4348  if (blockidx == 0)
4349  {
4350  if (block.prev_id != tophash)
4351  {
4352  MDEBUG("Skipping prepare blocks. New blocks don't belong to chain.");
4353  blocks.clear();
4354  return true;
4355  }
4356  }
4357  if (have_block(block_hash))
4358  blocks_exist = true;
4359 
4360  std::advance(it, 1);
4361  }
4362  }
4363 
4364  for (unsigned i = 0; i < extra && !blocks_exist; i++, blockidx++)
4365  {
4366  block &block = blocks[blockidx];
4367  crypto::hash block_hash;
4368 
4369  if (!parse_and_validate_block_from_blob(it->block, block, block_hash))
4370  return false;
4371 
4372  if (have_block(block_hash))
4373  blocks_exist = true;
4374 
4375  std::advance(it, 1);
4376  }
4377 
4378  if (!blocks_exist)
4379  {
4380  m_blocks_longhash_table.clear();
4381  uint64_t thread_height = height;
4383  for (unsigned int i = 0; i < threads; i++)
4384  {
4385  unsigned nblocks = batches;
4386  if (i < extra)
4387  ++nblocks;
4388  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);
4389  thread_height += nblocks;
4390  }
4391 
4392  waiter.wait(&tpool);
4393 
4394  if (m_cancel)
4395  return false;
4396 
4397  for (const auto & map : maps)
4398  {
4399  m_blocks_longhash_table.insert(map.begin(), map.end());
4400  }
4401  }
4402  }
4403 
4404  if (m_cancel)
4405  return false;
4406 
4407  if (blocks_exist)
4408  {
4409  MDEBUG("Skipping remainder of prepare blocks. Blocks exist.");
4410  return true;
4411  }
4412 
4413  m_fake_scan_time = 0;
4414  m_fake_pow_calc_time = 0;
4415 
4416  m_scan_table.clear();
4417  m_check_txin_table.clear();
4418 
4419  TIME_MEASURE_FINISH(prepare);
4420  m_fake_pow_calc_time = prepare / blocks_entry.size();
4421 
4422  if (blocks_entry.size() > 1 && threads > 1 && m_show_time_stats)
4423  MDEBUG("Prepare blocks took: " << prepare << " ms");
4424 
4425  TIME_MEASURE_START(scantable);
4426 
4427  // [input] stores all unique amounts found
4428  std::vector < uint64_t > amounts;
4429  // [input] stores all absolute_offsets for each amount
4430  std::map<uint64_t, std::vector<uint64_t>> offset_map;
4431  // [output] stores all output_data_t for each absolute_offset
4432  std::map<uint64_t, std::vector<output_data_t>> tx_map;
4433  std::vector<std::pair<cryptonote::transaction, crypto::hash>> txes(total_txs);
4434 
4435 #define SCAN_TABLE_QUIT(m) \
4436  do { \
4437  MERROR_VER(m) ;\
4438  m_scan_table.clear(); \
4439  return false; \
4440  } while(0); \
4441 
4442  // generate sorted tables for all amounts and absolute offsets
4443  size_t tx_index = 0, block_index = 0;
4444  for (const auto &entry : blocks_entry)
4445  {
4446  if (m_cancel)
4447  return false;
4448 
4449  for (const auto &tx_blob : entry.txs)
4450  {
4451  if (tx_index >= txes.size())
4452  SCAN_TABLE_QUIT("tx_index is out of sync");
4453  transaction &tx = txes[tx_index].first;
4454  crypto::hash &tx_prefix_hash = txes[tx_index].second;
4455  ++tx_index;
4456 
4457  if (!parse_and_validate_tx_base_from_blob(tx_blob, tx))
4458  SCAN_TABLE_QUIT("Could not parse tx from incoming blocks.");
4459  cryptonote::get_transaction_prefix_hash(tx, tx_prefix_hash);
4460 
4461  auto its = m_scan_table.find(tx_prefix_hash);
4462  if (its != m_scan_table.end())
4463  SCAN_TABLE_QUIT("Duplicate tx found from incoming blocks.");
4464 
4465  m_scan_table.emplace(tx_prefix_hash, std::unordered_map<crypto::key_image, std::vector<output_data_t>>());
4466  its = m_scan_table.find(tx_prefix_hash);
4467  assert(its != m_scan_table.end());
4468 
4469  if(tx.version <= 2)
4470  {
4471  // get all amounts from tx.vin(s)
4472  for (const auto &txin : tx.vin)
4473  {
4474  const txin_to_key &in_to_key = boost::get < txin_to_key > (txin);
4475 
4476  // check for duplicate
4477  auto it = its->second.find(in_to_key.k_image);
4478  if (it != its->second.end())
4479  SCAN_TABLE_QUIT("Duplicate key_image found from incoming blocks.");
4480 
4481  amounts.push_back(in_to_key.amount);
4482  }
4483  }
4484 
4485  // sort and remove duplicate amounts from amounts list
4486  std::sort(amounts.begin(), amounts.end());
4487  auto last = std::unique(amounts.begin(), amounts.end());
4488  amounts.erase(last, amounts.end());
4489 
4490  // add amount to the offset_map and tx_map
4491  for (const uint64_t &amount : amounts)
4492  {
4493  if (offset_map.find(amount) == offset_map.end())
4494  offset_map.emplace(amount, std::vector<uint64_t>());
4495 
4496  if (tx_map.find(amount) == tx_map.end())
4497  tx_map.emplace(amount, std::vector<output_data_t>());
4498  }
4499 
4500  if(tx.version <= 2)
4501  {
4502  // add new absolute_offsets to offset_map
4503  for (const auto &txin : tx.vin)
4504  {
4505  const txin_to_key &in_to_key = boost::get < txin_to_key > (txin);
4506  // no need to check for duplicate here.
4507  auto absolute_offsets = relative_output_offsets_to_absolute(in_to_key.key_offsets);
4508  for (const auto & offset : absolute_offsets)
4509  offset_map[in_to_key.amount].push_back(offset);
4510 
4511  }
4512  }
4513  }
4514  ++block_index;
4515  }
4516 
4517  // sort and remove duplicate absolute_offsets in offset_map
4518  for (auto &offsets : offset_map)
4519  {
4520  std::sort(offsets.second.begin(), offsets.second.end());
4521  auto last = std::unique(offsets.second.begin(), offsets.second.end());
4522  offsets.second.erase(last, offsets.second.end());
4523  }
4524 
4525  // gather all the output keys
4526  threads = tpool.get_max_concurrency();
4527  if (!m_db->can_thread_bulk_indices())
4528  threads = 1;
4529 
4530  if (threads > 1 && amounts.size() > 1)
4531  {
4533 
4534  for (size_t i = 0; i < amounts.size(); i++)
4535  {
4536  uint64_t amount = amounts[i];
4537  tpool.submit(&waiter, boost::bind(&Blockchain::output_scan_worker, this, amount, std::cref(offset_map[amount]), std::ref(tx_map[amount])), true);
4538  }
4539  waiter.wait(&tpool);
4540  }
4541  else
4542  {
4543  for (size_t i = 0; i < amounts.size(); i++)
4544  {
4545  uint64_t amount = amounts[i];
4546  output_scan_worker(amount, offset_map[amount], tx_map[amount]);
4547  }
4548  }
4549 
4550  // now generate a table for each tx_prefix and k_image hashes
4551  tx_index = 0;
4552  for (const auto &entry : blocks_entry)
4553  {
4554  if (m_cancel)
4555  return false;
4556 
4557  for (const auto &tx_blob : entry.txs)
4558  {
4559  if (tx_index >= txes.size())
4560  SCAN_TABLE_QUIT("tx_index is out of sync");
4561  const transaction &tx = txes[tx_index].first;
4562  const crypto::hash &tx_prefix_hash = txes[tx_index].second;
4563  ++tx_index;
4564 
4565  auto its = m_scan_table.find(tx_prefix_hash);
4566  if (its == m_scan_table.end())
4567  SCAN_TABLE_QUIT("Tx not found on scan table from incoming blocks.");
4568 
4569  if(tx.version >= 3) continue;
4570 
4571  for (const auto &txin : tx.vin)
4572  {
4573  const txin_to_key &in_to_key = boost::get < txin_to_key > (txin);
4574  auto needed_offsets = relative_output_offsets_to_absolute(in_to_key.key_offsets);
4575 
4576  std::vector<output_data_t> outputs;
4577  for (const uint64_t & offset_needed : needed_offsets)
4578  {
4579  size_t pos = 0;
4580  bool found = false;
4581 
4582  for (const uint64_t &offset_found : offset_map[in_to_key.amount])
4583  {
4584  if (offset_needed == offset_found)
4585  {
4586  found = true;
4587  break;
4588  }
4589 
4590  ++pos;
4591  }
4592 
4593  if (found && pos < tx_map[in_to_key.amount].size())
4594  outputs.push_back(tx_map[in_to_key.amount].at(pos));
4595  else
4596  break;
4597  }
4598 
4599  its->second.emplace(in_to_key.k_image, outputs);
4600  }
4601  }
4602  }
4603 
4604  TIME_MEASURE_FINISH(scantable);
4605  if (total_txs > 0)
4606  {
4607  m_fake_scan_time = scantable / total_txs;
4608  if(m_show_time_stats)
4609  MDEBUG("Prepare scantable took: " << scantable << " ms");
4610  }
4611 
4612  return true;
4613 }
#define SCAN_TABLE_QUIT(m)
virtual bool can_thread_bulk_indices() const =0
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 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
void wait(threadpool *tpool)
Definition: threadpool.cpp:115
A global thread pool.
Definition: threadpool.h:43
static threadpool & getInstance()
Definition: threadpool.h:45
void submit(waiter *waiter, std::function< void()> f, bool leaf=false)
Definition: threadpool.cpp:69
unsigned int get_max_concurrency() const
Definition: threadpool.cpp:92
POD_CLASS key_image
Definition: crypto.h:102
void get_transaction_prefix_hash(const transaction_prefix &tx, crypto::hash &h)
std::vector< uint64_t > relative_output_offsets_to_absolute(const std::vector< uint64_t > &off)
bool parse_and_validate_tx_base_from_blob(const blobdata &tx_blob, transaction &tx)
bool sleep_no_w(long ms)
crypto::key_image k_image
std::vector< uint64_t > key_offsets
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 3925 of file blockchain.cpp.

3926 {
3927  m_tx_pool.lock();
3929  CRITICAL_REGION_LOCAL(m_blockchain_lock);
3930 
3931  return m_db->prune_blockchain(pruning_seed);
3932 }
virtual bool prune_blockchain(uint32_t pruning_seed=0)=0
prunes the blockchain
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 4625 of file blockchain.cpp.

4626 {
4627  m_db->remove_txpool_tx(txid);
4628 }
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 698 of file blockchain.cpp.

699 {
700  LOG_PRINT_L3("Blockchain::" << __func__);
701  CRITICAL_REGION_LOCAL(m_blockchain_lock);
702  m_timestamps_and_difficulties_height = 0;
703  m_alternative_chains.clear();
704  invalidate_block_template_cache();
705  m_db->reset();
706  m_hardfork->init();
707 
708  db_wtxn_guard wtxn_guard(m_db);
709  block_verification_context bvc = boost::value_initialized<block_verification_context>();
710  add_new_block(b, bvc);
711  if (!update_next_cumulative_weight_limit())
712  return false;
713  return bvc.m_added_to_main_chain && !bvc.m_verification_failed;
714 }
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 4682 of file blockchain.cpp.

4683 {
4684  /* all of this is no-op'd if the user set a specific
4685  * --db-sync-mode at startup.
4686  */
4687  if (m_db_default_sync)
4688  {
4689  m_db->safesyncmode(onoff);
4690  m_db_sync_mode = onoff ? db_nosync : db_async;
4691  }
4692 }
virtual void safesyncmode(const bool onoff)=0
toggle safe syncs for the DB
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 775 of file blockchain.h.

775 { 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 4154 of file blockchain.cpp.

4155 {
4156  m_enforce_dns_checkpoints = enforce_checkpoints;
4157 }
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 782 of file blockchain.h.

782 { 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 794 of file blockchain.h.

794 { 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 4664 of file blockchain.cpp.

4665 {
4666  if (sync_mode == db_defaultsync)
4667  {
4668  m_db_default_sync = true;
4669  sync_mode = db_async;
4670  }
4671  m_db_sync_mode = sync_mode;
4672  m_fast_sync = fast_sync;
4673  m_db_sync_on_blocks = sync_on_blocks;
4674  m_db_sync_threshold = sync_threshold;
4675  m_max_prepare_blocks_threads = maxthreads;
4676 
4677  if(!validator_key.empty()) {
4678  m_validator_key = boost::algorithm::unhex(validator_key);
4679  }
4680 }
@ db_defaultsync
user didn'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 1039 of file blockchain.h.

1039 { m_validator_key = boost::algorithm::unhex(key); }
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 1041 of file blockchain.h.

1041 { m_validators = v.get(); }

◆ 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 516 of file blockchain.cpp.

517 {
518  LOG_PRINT_L3("Blockchain::" << __func__);
519  // lock because the rpc_thread command handler also calls this
521 
523  // TODO: make sure sync(if this throws that it is not simply ignored higher
524  // up the call stack
525  try
526  {
527  m_db->sync();
528  }
529  catch (const std::exception& e)
530  {
531  MERROR(std::string("Error syncing blockchain db: ") + e.what() + "-- shutting down now to prevent issues!");
532  throw;
533  }
534  catch (...)
535  {
536  MERROR("There was an issue storing the blockchain, shutting down now to prevent issues!");
537  throw;
538  }
539 
541  if(m_show_time_stats)
542  MINFO("Blockchain stored OK, took: " << save << " ms");
543  return true;
544 }
epee::critical_section m_synchronization_lock
A lock, currently for when BlockchainLMDB needs to resize the backing db file.
virtual void sync()=0
sync the BlockchainDB with disk
void save(Archive &a, const std::unordered_map< h_key, hval > &x, const boost::serialization::version_type ver)
Here is the call graph for this function:
Here is the caller graph for this function:

◆ unlock()

void Blockchain::unlock ( void  )

Definition at line 4883 of file blockchain.cpp.

4884 {
4885  m_blockchain_lock.unlock();
4886 }
Here is the call graph for this function:

◆ update_blockchain_pruning()

bool Blockchain::update_blockchain_pruning ( )

Definition at line 3934 of file blockchain.cpp.

3935 {
3936  m_tx_pool.lock();
3938  CRITICAL_REGION_LOCAL(m_blockchain_lock);
3939 
3940  return m_db->update_pruning();
3941 }
virtual bool update_pruning()=0
prunes recent blockchain changes as needed, iff pruning is enabled
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 4119 of file blockchain.cpp.

4120 {
4121  if (!m_checkpoints.load_checkpoints_from_json(file_path))
4122  {
4123  return false;
4124  }
4125 
4126  // if we're checking both dns and json, load checkpoints from dns.
4127  // if we're not hard-enforcing dns checkpoints, handle accordingly
4128  if (m_enforce_dns_checkpoints && check_dns && !m_offline)
4129  {
4130  if (!m_checkpoints.load_checkpoints_from_dns())
4131  {
4132  return false;
4133  }
4134  }
4135  else if (check_dns && !m_offline)
4136  {
4137  checkpoints dns_points;
4138  dns_points.load_checkpoints_from_dns();
4139  if (m_checkpoints.check_for_conflicts(dns_points))
4140  {
4141  check_against_checkpoints(dns_points, false);
4142  }
4143  else
4144  {
4145  MERROR("One or more checkpoints fetched from DNS conflicted with existing checkpoints!");
4146  }
4147  }
4148 
4149  check_against_checkpoints(m_checkpoints, true);
4150 
4151  return true;
4152 }
void check_against_checkpoints(const checkpoints &points, bool enforce)
check the blockchain against a set of checkpoints
A container for blockchain checkpoints.
Definition: checkpoints.h:52
bool load_checkpoints_from_dns(network_type nettype=MAINNET)
load new checkpoints from DNS
bool check_for_conflicts(const checkpoints &other) const
checks if our checkpoints container conflicts with another
bool load_checkpoints_from_json(const std::string &json_hashfile_fullpath)
load new checkpoints from json
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 4620 of file blockchain.cpp.

4621 {
4622  m_db->update_txpool_tx(txid, meta);
4623 }
virtual void update_txpool_tx(const crypto::hash &txid, const txpool_tx_meta_t &details)=0
update a txpool transaction's metadata
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 (v3 tx onwards)

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

Definition at line 2847 of file blockchain.cpp.

2848 {
2849  LOG_PRINT_L3("Blockchain::" << __func__);
2850 
2851  for (const txin_v& in: tx.vin)
2852  {
2853  if(in.type() == typeid(txin_to_key_public))
2854  {
2855  const auto &in_to_key = boost::get<txin_to_key_public>(in);
2856  if(!m_db->check_chainstate_utxo(in_to_key.tx_hash, in_to_key.relative_offset))
2857  return true;
2858  }
2859  }
2860 
2861  return false;
2862 }
virtual bool check_chainstate_utxo(const crypto::hash tx_hash, const uint32_t relative_out_index)=0
Here is the call graph for this function:

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