diff options
author | stoffu <stoffu@protonmail.ch> | 2020-05-15 10:56:23 +0900 |
---|---|---|
committer | stoffu <stoffu@protonmail.ch> | 2020-06-09 10:40:51 +0900 |
commit | 7bd66b01bfb62ecaf8ff02b20d14db3a77322abc (patch) | |
tree | c6a4db2a82193471570360734f4c4955271a69ba /src/blockchain_db/lmdb/db_lmdb.cpp | |
parent | Merge pull request #6576 (diff) | |
download | monero-7bd66b01bfb62ecaf8ff02b20d14db3a77322abc.tar.xz |
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.
Diffstat (limited to 'src/blockchain_db/lmdb/db_lmdb.cpp')
-rw-r--r-- | src/blockchain_db/lmdb/db_lmdb.cpp | 38 |
1 files changed, 38 insertions, 0 deletions
diff --git a/src/blockchain_db/lmdb/db_lmdb.cpp b/src/blockchain_db/lmdb/db_lmdb.cpp index 5cec8879d..db19fb1a7 100644 --- a/src/blockchain_db/lmdb/db_lmdb.cpp +++ b/src/blockchain_db/lmdb/db_lmdb.cpp @@ -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__); |