mirror of
https://github.com/monero-project/monero.git
synced 2026-08-03 09:21:35 -07:00
daemon: guard against rare 'difficulty drift' bug with checkpoints and recalculation
On startup, it checks against the difficulty checkpoints, and if any mismatch is found, recalculates all the blocks with wrong difficulties. Additionally, once a week it recalculates difficulties of blocks after the last difficulty checkpoint.
This commit is contained in:
@@ -1038,6 +1038,16 @@ public:
|
||||
*/
|
||||
virtual difficulty_type get_block_difficulty(const uint64_t& height) const = 0;
|
||||
|
||||
/**
|
||||
* @brief correct blocks cumulative difficulties that were incorrectly calculated due to the 'difficulty drift' bug
|
||||
*
|
||||
* If the block does not exist, the subclass should throw BLOCK_DNE
|
||||
*
|
||||
* @param start_height the height where the drift starts
|
||||
* @param new_cumulative_difficulties new cumulative difficulties to be stored
|
||||
*/
|
||||
virtual void correct_block_cumulative_difficulties(const uint64_t& start_height, const std::vector<difficulty_type>& new_cumulative_difficulties) = 0;
|
||||
|
||||
/**
|
||||
* @brief fetch a block's already generated coins
|
||||
*
|
||||
|
||||
@@ -2750,6 +2750,44 @@ difficulty_type BlockchainLMDB::get_block_difficulty(const uint64_t& height) con
|
||||
return diff1 - diff2;
|
||||
}
|
||||
|
||||
void BlockchainLMDB::correct_block_cumulative_difficulties(const uint64_t& start_height, const std::vector<difficulty_type>& new_cumulative_difficulties)
|
||||
{
|
||||
LOG_PRINT_L3("BlockchainLMDB::" << __func__);
|
||||
check_open();
|
||||
mdb_txn_cursors *m_cursors = &m_wcursors;
|
||||
|
||||
int result = 0;
|
||||
block_wtxn_start();
|
||||
CURSOR(block_info)
|
||||
|
||||
const uint64_t bc_height = height();
|
||||
if (start_height + new_cumulative_difficulties.size() != bc_height)
|
||||
{
|
||||
block_wtxn_abort();
|
||||
throw0(DB_ERROR("Incorrect new_cumulative_difficulties size"));
|
||||
}
|
||||
|
||||
for (uint64_t height = start_height; height < bc_height; ++height)
|
||||
{
|
||||
MDB_val_set(key, height);
|
||||
result = mdb_cursor_get(m_cur_block_info, (MDB_val *)&zerokval, &key, MDB_GET_BOTH);
|
||||
if (result)
|
||||
throw1(BLOCK_DNE(lmdb_error("Failed to get block info: ", result).c_str()));
|
||||
|
||||
mdb_block_info bi = *(mdb_block_info*)key.mv_data;
|
||||
const difficulty_type d = new_cumulative_difficulties[height - start_height];
|
||||
bi.bi_diff_hi = ((d >> 64) & 0xffffffffffffffff).convert_to<uint64_t>();
|
||||
bi.bi_diff_lo = (d & 0xffffffffffffffff).convert_to<uint64_t>();
|
||||
|
||||
MDB_val_set(key2, height);
|
||||
MDB_val_set(val, bi);
|
||||
result = mdb_cursor_put(m_cur_block_info, &key2, &val, MDB_CURRENT);
|
||||
if (result)
|
||||
throw0(DB_ERROR(lmdb_error("Failed to overwrite block info to db transaction: ", result).c_str()));
|
||||
}
|
||||
block_wtxn_stop();
|
||||
}
|
||||
|
||||
uint64_t BlockchainLMDB::get_block_already_generated_coins(const uint64_t& height) const
|
||||
{
|
||||
LOG_PRINT_L3("BlockchainLMDB::" << __func__);
|
||||
|
||||
@@ -229,6 +229,8 @@ public:
|
||||
|
||||
virtual difficulty_type get_block_difficulty(const uint64_t& height) const;
|
||||
|
||||
virtual void correct_block_cumulative_difficulties(const uint64_t& start_height, const std::vector<difficulty_type>& new_cumulative_difficulties);
|
||||
|
||||
virtual uint64_t get_block_already_generated_coins(const uint64_t& height) const;
|
||||
|
||||
virtual uint64_t get_block_long_term_weight(const uint64_t& height) const;
|
||||
|
||||
@@ -82,6 +82,7 @@ public:
|
||||
virtual std::vector<uint64_t> get_block_weights(uint64_t start_height, size_t count) const override { return {}; }
|
||||
virtual cryptonote::difficulty_type get_block_cumulative_difficulty(const uint64_t& height) const override { return 10; }
|
||||
virtual cryptonote::difficulty_type get_block_difficulty(const uint64_t& height) const override { return 0; }
|
||||
virtual void correct_block_cumulative_difficulties(const uint64_t& start_height, const std::vector<difficulty_type>& new_cumulative_difficulties) override {}
|
||||
virtual uint64_t get_block_already_generated_coins(const uint64_t& height) const override { return 10000000000; }
|
||||
virtual uint64_t get_block_long_term_weight(const uint64_t& height) const override { return 128; }
|
||||
virtual std::vector<uint64_t> get_long_term_block_weights(uint64_t start_height, size_t count) const override { return {}; }
|
||||
|
||||
Reference in New Issue
Block a user