diff --git a/src/node/blockstorage.cpp b/src/node/blockstorage.cpp index 53f616de23..f635cd2be2 100644 --- a/src/node/blockstorage.cpp +++ b/src/node/blockstorage.cpp @@ -165,6 +165,13 @@ bool CBlockIndexHeightOnlyComparator::operator()(const CBlockIndex* pa, const CB return pa->nHeight < pb->nHeight; } +/** The number of blocks to keep below the deepest prune lock. + * There is nothing special about this number. It is higher than what we + * expect to see in regular mainnet reorgs, but not so high that it would + * noticeably interfere with the pruning mechanism. + * */ +static constexpr int PRUNE_LOCK_BUFFER{10}; + std::vector BlockManager::GetAllBlockIndices() { AssertLockHeld(cs_main); @@ -258,6 +265,21 @@ void BlockManager::PruneOneBlockFile(const int fileNumber) m_dirty_fileinfo.insert(fileNumber); } +bool BlockManager::DoPruneLocksForbidPruning(const CBlockFileInfo& block_file_info) +{ + AssertLockHeld(cs_main); + for (const auto& prune_lock : m_prune_locks) { + if (prune_lock.second.height_first == std::numeric_limits::max()) continue; + // Remove the buffer and one additional block here to get actual height that is outside of the buffer + const unsigned int lock_height{(unsigned)std::max(1, prune_lock.second.height_first - PRUNE_LOCK_BUFFER - 1)}; + if (block_file_info.nHeightLast > lock_height) { + LogPrint(BCLog::PRUNE, "%s limited pruning to height %d\n", prune_lock.first, lock_height); + return true; + } + } + return false; +} + void BlockManager::FindFilesToPruneManual( std::set& setFilesToPrune, int nManualPruneHeight, @@ -280,6 +302,8 @@ void BlockManager::FindFilesToPruneManual( continue; } + if (DoPruneLocksForbidPruning(m_blockfile_info[fileNumber])) continue; + PruneOneBlockFile(fileNumber); setFilesToPrune.insert(fileNumber); count++; @@ -344,6 +368,8 @@ void BlockManager::FindFilesToPrune( continue; } + if (DoPruneLocksForbidPruning(m_blockfile_info[fileNumber])) continue; + PruneOneBlockFile(fileNumber); // Queue up the files for removal setFilesToPrune.insert(fileNumber); diff --git a/src/node/blockstorage.h b/src/node/blockstorage.h index ba44d31581..17c9e939e4 100644 --- a/src/node/blockstorage.h +++ b/src/node/blockstorage.h @@ -167,6 +167,8 @@ private: bool WriteBlockToDisk(const CBlock& block, FlatFilePos& pos) const; bool UndoWriteToDisk(const CBlockUndo& blockundo, FlatFilePos& pos, const uint256& hashBlock) const; + bool DoPruneLocksForbidPruning(const CBlockFileInfo& block_file_info) EXCLUSIVE_LOCKS_REQUIRED(::cs_main); + /* Calculate the block/rev files to delete based on height specified by user with RPC command pruneblockchain */ void FindFilesToPruneManual( std::set& setFilesToPrune, diff --git a/src/validation.cpp b/src/validation.cpp index 1d4a5f1ec3..831ef11470 100644 --- a/src/validation.cpp +++ b/src/validation.cpp @@ -98,12 +98,6 @@ const std::vector CHECKLEVEL_DOC { "level 4 tries to reconnect the blocks", "each level includes the checks of the previous levels", }; -/** The number of blocks to keep below the deepest prune lock. - * There is nothing special about this number. It is higher than what we - * expect to see in regular mainnet reorgs, but not so high that it would - * noticeably interfere with the pruning mechanism. - * */ -static constexpr int PRUNE_LOCK_BUFFER{10}; GlobalMutex g_best_block_mutex; std::condition_variable g_best_block_cv; @@ -2540,21 +2534,6 @@ bool Chainstate::FlushStateToDisk( // make sure we don't prune above any of the prune locks bestblocks // pruning is height-based int last_prune{m_chain.Height()}; // last height we can prune - std::optional limiting_lock; // prune lock that actually was the limiting factor, only used for logging - - for (const auto& prune_lock : m_blockman.m_prune_locks) { - if (prune_lock.second.height_first == std::numeric_limits::max()) continue; - // Remove the buffer and one additional block here to get actual height that is outside of the buffer - const int lock_height{prune_lock.second.height_first - PRUNE_LOCK_BUFFER - 1}; - last_prune = std::max(1, std::min(last_prune, lock_height)); - if (last_prune == lock_height) { - limiting_lock = prune_lock.first; - } - } - - if (limiting_lock) { - LogPrint(BCLog::PRUNE, "%s limited pruning to height %d\n", limiting_lock.value(), last_prune); - } if (nManualPruneHeight > 0) { LOG_TIME_MILLIS_WITH_CATEGORY("find files to prune (manual)", BCLog::BENCH); diff --git a/test/functional/feature_index_prune.py b/test/functional/feature_index_prune.py index d6e802b399..d9642f5434 100755 --- a/test/functional/feature_index_prune.py +++ b/test/functional/feature_index_prune.py @@ -70,7 +70,7 @@ class FeatureIndexPruneTest(BitcoinTestFramework): self.log.info("prune some blocks") for node in self.nodes[:2]: - with node.assert_debug_log(['limited pruning to height 689']): + with node.assert_debug_log(['Prune: UnlinkPrunedFiles deleted blk/rev (00000)']): pruneheight_new = node.pruneblockchain(400) # the prune heights used here and below are magic numbers that are determined by the # thresholds at which block files wrap, so they depend on disk serialization and default block file size. @@ -143,7 +143,7 @@ class FeatureIndexPruneTest(BitcoinTestFramework): self.sync_index(height=2500) for node in self.nodes[:2]: - with node.assert_debug_log(['limited pruning to height 2489']): + with node.assert_debug_log(['Prune: UnlinkPrunedFiles deleted blk/rev (00007)']): pruneheight_new = node.pruneblockchain(2500) assert_equal(pruneheight_new, 2005)