save some database calls when getting top block hash and height

This commit is contained in:
moneromooo-monero 2018-11-20 20:19:39 +00:00
parent 9827880877
commit 79b4e9f377
No known key found for this signature in database
GPG key ID: 686F07454D6CEFC3
7 changed files with 49 additions and 31 deletions

View file

@ -1052,9 +1052,11 @@ public:
* *
* The subclass should return the hash of the most recent block * The subclass should return the hash of the most recent block
* *
* @param block_height if non NULL, returns the height of that block (ie, the blockchain height minus 1)
*
* @return the top block's hash * @return the top block's hash
*/ */
virtual crypto::hash top_block_hash() const = 0; virtual crypto::hash top_block_hash(uint64_t *block_height = NULL) const = 0;
/** /**
* @brief fetch the top block * @brief fetch the top block

View file

@ -2582,11 +2582,13 @@ std::vector<crypto::hash> BlockchainLMDB::get_hashes_range(const uint64_t& h1, c
return v; return v;
} }
crypto::hash BlockchainLMDB::top_block_hash() const crypto::hash BlockchainLMDB::top_block_hash(uint64_t *block_height) const
{ {
LOG_PRINT_L3("BlockchainLMDB::" << __func__); LOG_PRINT_L3("BlockchainLMDB::" << __func__);
check_open(); check_open();
uint64_t m_height = height(); uint64_t m_height = height();
if (block_height)
*block_height = m_height - 1;
if (m_height != 0) if (m_height != 0)
{ {
return get_block_hash_from_height(m_height - 1); return get_block_hash_from_height(m_height - 1);

View file

@ -233,7 +233,7 @@ public:
virtual std::vector<crypto::hash> get_hashes_range(const uint64_t& h1, const uint64_t& h2) const; virtual std::vector<crypto::hash> get_hashes_range(const uint64_t& h1, const uint64_t& h2) const;
virtual crypto::hash top_block_hash() const; virtual crypto::hash top_block_hash(uint64_t *block_height = NULL) const;
virtual block get_top_block() const; virtual block get_top_block() const;

View file

@ -79,7 +79,7 @@ public:
virtual crypto::hash get_block_hash_from_height(const uint64_t& height) const { return crypto::hash(); } virtual crypto::hash get_block_hash_from_height(const uint64_t& height) const { return crypto::hash(); }
virtual std::vector<cryptonote::block> get_blocks_range(const uint64_t& h1, const uint64_t& h2) const { return std::vector<cryptonote::block>(); } virtual std::vector<cryptonote::block> get_blocks_range(const uint64_t& h1, const uint64_t& h2) const { return std::vector<cryptonote::block>(); }
virtual std::vector<crypto::hash> get_hashes_range(const uint64_t& h1, const uint64_t& h2) const { return std::vector<crypto::hash>(); } virtual std::vector<crypto::hash> get_hashes_range(const uint64_t& h1, const uint64_t& h2) const { return std::vector<crypto::hash>(); }
virtual crypto::hash top_block_hash() const { return crypto::hash(); } virtual crypto::hash top_block_hash(uint64_t *block_height = NULL) const { if (block_height) *block_height = 0; return crypto::hash(); }
virtual cryptonote::block get_top_block() const { return cryptonote::block(); } virtual cryptonote::block get_top_block() const { return cryptonote::block(); }
virtual uint64_t height() const { return 1; } virtual uint64_t height() const { return 1; }
virtual bool tx_exists(const crypto::hash& h) const { return false; } virtual bool tx_exists(const crypto::hash& h) const { return false; }

View file

@ -468,8 +468,8 @@ bool Blockchain::init(BlockchainDB* db, const network_type nettype, bool offline
uint64_t num_popped_blocks = 0; uint64_t num_popped_blocks = 0;
while (!m_db->is_read_only()) while (!m_db->is_read_only())
{ {
const uint64_t top_height = m_db->height() - 1; uint64_t top_height;
const crypto::hash top_id = m_db->top_block_hash(); const crypto::hash top_id = m_db->top_block_hash(&top_height);
const block top_block = m_db->get_top_block(); const block top_block = m_db->get_top_block();
const uint8_t ideal_hf_version = get_ideal_hard_fork_version(top_height); const uint8_t ideal_hf_version = get_ideal_hard_fork_version(top_height);
if (ideal_hf_version <= 1 || ideal_hf_version == top_block.major_version) if (ideal_hf_version <= 1 || ideal_hf_version == top_block.major_version)
@ -509,7 +509,9 @@ bool Blockchain::init(BlockchainDB* db, const network_type nettype, bool offline
{ {
m_timestamps_and_difficulties_height = 0; m_timestamps_and_difficulties_height = 0;
m_hardfork->reorganize_from_chain_height(get_current_blockchain_height()); m_hardfork->reorganize_from_chain_height(get_current_blockchain_height());
m_tx_pool.on_blockchain_dec(m_db->height()-1, get_tail_id()); uint64_t top_block_height;
crypto::hash top_block_hash = get_tail_id(top_block_height);
m_tx_pool.on_blockchain_dec(top_block_height, top_block_hash);
} }
if (test_options && test_options->long_term_block_weight_window) if (test_options && test_options->long_term_block_weight_window)
@ -702,7 +704,9 @@ block Blockchain::pop_block_from_blockchain()
m_check_txin_table.clear(); m_check_txin_table.clear();
CHECK_AND_ASSERT_THROW_MES(update_next_cumulative_weight_limit(), "Error updating next cumulative weight limit"); CHECK_AND_ASSERT_THROW_MES(update_next_cumulative_weight_limit(), "Error updating next cumulative weight limit");
m_tx_pool.on_blockchain_dec(m_db->height()-1, get_tail_id()); uint64_t top_block_height;
crypto::hash top_block_hash = get_tail_id(top_block_height);
m_tx_pool.on_blockchain_dec(top_block_height, top_block_hash);
invalidate_block_template_cache(); invalidate_block_template_cache();
return popped_block; return popped_block;
@ -729,8 +733,7 @@ crypto::hash Blockchain::get_tail_id(uint64_t& height) const
{ {
LOG_PRINT_L3("Blockchain::" << __func__); LOG_PRINT_L3("Blockchain::" << __func__);
CRITICAL_REGION_LOCAL(m_blockchain_lock); CRITICAL_REGION_LOCAL(m_blockchain_lock);
height = m_db->height() - 1; return m_db->top_block_hash(&height);
return get_tail_id();
} }
//------------------------------------------------------------------ //------------------------------------------------------------------
crypto::hash Blockchain::get_tail_id() const crypto::hash Blockchain::get_tail_id() const
@ -891,8 +894,9 @@ difficulty_type Blockchain::get_difficulty_for_next_block()
CRITICAL_REGION_LOCAL(m_blockchain_lock); CRITICAL_REGION_LOCAL(m_blockchain_lock);
std::vector<uint64_t> timestamps; std::vector<uint64_t> timestamps;
std::vector<difficulty_type> difficulties; std::vector<difficulty_type> difficulties;
auto height = m_db->height(); uint64_t height;
top_hash = get_tail_id(); // get it again now that we have the lock top_hash = get_tail_id(height); // get it again now that we have the lock
++height; // top block height to blockchain height
// ND: Speedup // ND: Speedup
// 1. Keep a list of the last 735 (or less) blocks that is used to compute difficulty, // 1. Keep a list of the last 735 (or less) blocks that is used to compute difficulty,
// then when the next block difficulty is queried, push the latest height data and // then when the next block difficulty is queried, push the latest height data and
@ -1806,11 +1810,12 @@ uint64_t Blockchain::get_num_mature_outputs(uint64_t amount) const
uint64_t num_outs = m_db->get_num_outputs(amount); uint64_t num_outs = m_db->get_num_outputs(amount);
// ensure we don't include outputs that aren't yet eligible to be used // ensure we don't include outputs that aren't yet eligible to be used
// outpouts are sorted by height // outpouts are sorted by height
const uint64_t blockchain_height = m_db->height();
while (num_outs > 0) while (num_outs > 0)
{ {
const tx_out_index toi = m_db->get_output_tx_and_index(amount, num_outs - 1); const tx_out_index toi = m_db->get_output_tx_and_index(amount, num_outs - 1);
const uint64_t height = m_db->get_tx_block_height(toi.first); const uint64_t height = m_db->get_tx_block_height(toi.first);
if (height + CRYPTONOTE_DEFAULT_TX_SPENDABLE_AGE <= m_db->height()) if (height + CRYPTONOTE_DEFAULT_TX_SPENDABLE_AGE <= blockchain_height)
break; break;
--num_outs; --num_outs;
} }
@ -3325,14 +3330,15 @@ bool Blockchain::check_block_timestamp(const block& b, uint64_t& median_ts) cons
return false; return false;
} }
const auto h = m_db->height();
// if not enough blocks, no proper median yet, return true // if not enough blocks, no proper median yet, return true
if(m_db->height() < BLOCKCHAIN_TIMESTAMP_CHECK_WINDOW) if(h < BLOCKCHAIN_TIMESTAMP_CHECK_WINDOW)
{ {
return true; return true;
} }
std::vector<uint64_t> timestamps; std::vector<uint64_t> timestamps;
auto h = m_db->height();
// need most recent 60 blocks, get index of first of those // need most recent 60 blocks, get index of first of those
size_t offset = h - BLOCKCHAIN_TIMESTAMP_CHECK_WINDOW; size_t offset = h - BLOCKCHAIN_TIMESTAMP_CHECK_WINDOW;
@ -3401,9 +3407,12 @@ bool Blockchain::handle_block_to_main_chain(const block& bl, const crypto::hash&
static bool seen_future_version = false; static bool seen_future_version = false;
m_db->block_txn_start(true); m_db->block_txn_start(true);
if(bl.prev_id != get_tail_id()) uint64_t blockchain_height;
const crypto::hash top_hash = get_tail_id(blockchain_height);
++blockchain_height; // block height to chain height
if(bl.prev_id != top_hash)
{ {
MERROR_VER("Block with id: " << id << std::endl << "has wrong prev_id: " << bl.prev_id << std::endl << "expected: " << get_tail_id()); MERROR_VER("Block with id: " << id << std::endl << "has wrong prev_id: " << bl.prev_id << std::endl << "expected: " << top_hash);
bvc.m_verifivation_failed = true; bvc.m_verifivation_failed = true;
leave: leave:
m_db->block_txn_stop(); m_db->block_txn_stop();
@ -3472,9 +3481,9 @@ leave:
bool precomputed = false; bool precomputed = false;
bool fast_check = false; bool fast_check = false;
#if defined(PER_BLOCK_CHECKPOINT) #if defined(PER_BLOCK_CHECKPOINT)
if (m_db->height() < m_blocks_hash_check.size()) if (blockchain_height < m_blocks_hash_check.size())
{ {
const auto &expected_hash = m_blocks_hash_check[m_db->height()]; const auto &expected_hash = m_blocks_hash_check[blockchain_height];
if (expected_hash != crypto::null_hash) if (expected_hash != crypto::null_hash)
{ {
if (memcmp(&id, &expected_hash, sizeof(hash)) != 0) if (memcmp(&id, &expected_hash, sizeof(hash)) != 0)
@ -3487,7 +3496,7 @@ leave:
} }
else else
{ {
MCINFO("verify", "No pre-validated hash at height " << m_db->height() << ", verifying fully"); MCINFO("verify", "No pre-validated hash at height " << blockchain_height << ", verifying fully");
} }
} }
else else
@ -3500,7 +3509,7 @@ leave:
proof_of_work = it->second; proof_of_work = it->second;
} }
else else
proof_of_work = get_block_longhash(bl, m_db->height()); proof_of_work = get_block_longhash(bl, blockchain_height);
// validate proof_of_work versus difficulty target // validate proof_of_work versus difficulty target
if(!check_hash(proof_of_work, current_diffic)) if(!check_hash(proof_of_work, current_diffic))
@ -3513,9 +3522,9 @@ leave:
// If we're at a checkpoint, ensure that our hardcoded checkpoint hash // If we're at a checkpoint, ensure that our hardcoded checkpoint hash
// is correct. // is correct.
if(m_checkpoints.is_in_checkpoint_zone(get_current_blockchain_height())) if(m_checkpoints.is_in_checkpoint_zone(blockchain_height))
{ {
if(!m_checkpoints.check_block(get_current_blockchain_height(), id)) if(!m_checkpoints.check_block(blockchain_height, id))
{ {
LOG_ERROR("CHECKPOINT VALIDATION FAILED"); LOG_ERROR("CHECKPOINT VALIDATION FAILED");
bvc.m_verifivation_failed = true; bvc.m_verifivation_failed = true;
@ -3530,7 +3539,7 @@ leave:
TIME_MEASURE_START(t3); TIME_MEASURE_START(t3);
// sanity check basic miner tx properties; // sanity check basic miner tx properties;
if(!prevalidate_miner_transaction(bl, m_db->height())) if(!prevalidate_miner_transaction(bl, blockchain_height))
{ {
MERROR_VER("Block with id: " << id << " failed to pass prevalidation"); MERROR_VER("Block with id: " << id << " failed to pass prevalidation");
bvc.m_verifivation_failed = true; bvc.m_verifivation_failed = true;
@ -3659,7 +3668,7 @@ leave:
TIME_MEASURE_START(vmt); TIME_MEASURE_START(vmt);
uint64_t base_reward = 0; uint64_t base_reward = 0;
uint64_t already_generated_coins = m_db->height() ? m_db->get_block_already_generated_coins(m_db->height() - 1) : 0; uint64_t already_generated_coins = blockchain_height ? m_db->get_block_already_generated_coins(blockchain_height - 1) : 0;
if(!validate_miner_transaction(bl, cumulative_block_weight, fee_summary, base_reward, already_generated_coins, bvc.m_partial_block_reward, m_hardfork->get_current_version())) if(!validate_miner_transaction(bl, cumulative_block_weight, fee_summary, base_reward, already_generated_coins, bvc.m_partial_block_reward, m_hardfork->get_current_version()))
{ {
MERROR_VER("Block with id: " << id << " has incorrect miner transaction"); MERROR_VER("Block with id: " << id << " has incorrect miner transaction");
@ -3680,8 +3689,8 @@ leave:
// at MONEY_SUPPLY. already_generated_coins is only used to compute the block subsidy and MONEY_SUPPLY yields a // at MONEY_SUPPLY. already_generated_coins is only used to compute the block subsidy and MONEY_SUPPLY yields a
// subsidy of 0 under the base formula and therefore the minimum subsidy >0 in the tail state. // subsidy of 0 under the base formula and therefore the minimum subsidy >0 in the tail state.
already_generated_coins = base_reward < (MONEY_SUPPLY-already_generated_coins) ? already_generated_coins + base_reward : MONEY_SUPPLY; already_generated_coins = base_reward < (MONEY_SUPPLY-already_generated_coins) ? already_generated_coins + base_reward : MONEY_SUPPLY;
if(m_db->height()) if(blockchain_height)
cumulative_difficulty += m_db->get_block_cumulative_difficulty(m_db->height() - 1); cumulative_difficulty += m_db->get_block_cumulative_difficulty(blockchain_height - 1);
TIME_MEASURE_FINISH(block_processing_time); TIME_MEASURE_FINISH(block_processing_time);
if(precomputed) if(precomputed)
@ -3922,10 +3931,11 @@ void Blockchain::check_against_checkpoints(const checkpoints& points, bool enfor
CRITICAL_REGION_LOCAL(m_blockchain_lock); CRITICAL_REGION_LOCAL(m_blockchain_lock);
stop_batch = m_db->batch_start(); stop_batch = m_db->batch_start();
const uint64_t blockchain_height = m_db->height();
for (const auto& pt : pts) for (const auto& pt : pts)
{ {
// if the checkpoint is for a block we don't have yet, move on // if the checkpoint is for a block we don't have yet, move on
if (pt.first >= m_db->height()) if (pt.first >= blockchain_height)
{ {
continue; continue;
} }
@ -4269,6 +4279,7 @@ bool Blockchain::prepare_handle_incoming_blocks(const std::vector<block_complete
auto it = blocks_entry.begin(); auto it = blocks_entry.begin();
unsigned blockidx = 0; unsigned blockidx = 0;
const crypto::hash tophash = m_db->top_block_hash();
for (unsigned i = 0; i < threads; i++) for (unsigned i = 0; i < threads; i++)
{ {
for (unsigned int j = 0; j < batches; j++, ++blockidx) for (unsigned int j = 0; j < batches; j++, ++blockidx)
@ -4281,7 +4292,6 @@ bool Blockchain::prepare_handle_incoming_blocks(const std::vector<block_complete
// check first block and skip all blocks if its not chained properly // check first block and skip all blocks if its not chained properly
if (blockidx == 0) if (blockidx == 0)
{ {
crypto::hash tophash = m_db->top_block_hash();
if (block.prev_id != tophash) if (block.prev_id != tophash)
{ {
MDEBUG("Skipping prepare blocks. New blocks don't belong to chain."); MDEBUG("Skipping prepare blocks. New blocks don't belong to chain.");

View file

@ -72,11 +72,13 @@ public:
virtual uint64_t height() const override { return blocks.size(); } virtual uint64_t height() const override { return blocks.size(); }
virtual size_t get_block_weight(const uint64_t &h) const override { return blocks[h].weight; } virtual size_t get_block_weight(const uint64_t &h) const override { return blocks[h].weight; }
virtual uint64_t get_block_long_term_weight(const uint64_t &h) const override { return blocks[h].long_term_weight; } virtual uint64_t get_block_long_term_weight(const uint64_t &h) const override { return blocks[h].long_term_weight; }
virtual crypto::hash top_block_hash() const override { virtual crypto::hash top_block_hash(uint64_t *block_height = NULL) const override {
uint64_t h = height(); uint64_t h = height();
crypto::hash top = crypto::null_hash; crypto::hash top = crypto::null_hash;
if (h) if (h)
*(uint64_t*)&top = h - 1; *(uint64_t*)&top = h - 1;
if (block_height)
*block_height = h - 1;
return top; return top;
} }
virtual void pop_block(cryptonote::block &blk, std::vector<cryptonote::transaction> &txs) override { blocks.pop_back(); } virtual void pop_block(cryptonote::block &blk, std::vector<cryptonote::transaction> &txs) override { blocks.pop_back(); }

View file

@ -64,11 +64,13 @@ public:
virtual uint64_t height() const override { return blocks.size(); } virtual uint64_t height() const override { return blocks.size(); }
virtual size_t get_block_weight(const uint64_t &h) const override { return blocks[h].weight; } virtual size_t get_block_weight(const uint64_t &h) const override { return blocks[h].weight; }
virtual uint64_t get_block_long_term_weight(const uint64_t &h) const override { return blocks[h].long_term_weight; } virtual uint64_t get_block_long_term_weight(const uint64_t &h) const override { return blocks[h].long_term_weight; }
virtual crypto::hash top_block_hash() const override { virtual crypto::hash top_block_hash(uint64_t *block_height = NULL) const override {
uint64_t h = height(); uint64_t h = height();
crypto::hash top = crypto::null_hash; crypto::hash top = crypto::null_hash;
if (h) if (h)
*(uint64_t*)&top = h - 1; *(uint64_t*)&top = h - 1;
if (block_height)
*block_height = h - 1;
return top; return top;
} }
virtual void pop_block(cryptonote::block &blk, std::vector<cryptonote::transaction> &txs) override { blocks.pop_back(); } virtual void pop_block(cryptonote::block &blk, std::vector<cryptonote::transaction> &txs) override { blocks.pop_back(); }