@@ -106,6 +106,12 @@ const std::vector<std::string> CHECKLEVEL_DOC {
106
106
" level 4 tries to reconnect the blocks" ,
107
107
" each level includes the checks of the previous levels" ,
108
108
};
109
+ /* * The number of blocks to keep below the deepest prune lock.
110
+ * There is nothing special about this number. It is higher than what we
111
+ * expect to see in regular mainnet reorgs, but not so high that it would
112
+ * noticeably interfere with the pruning mechanism.
113
+ * */
114
+ static constexpr int PRUNE_LOCK_BUFFER{10 };
109
115
110
116
/* *
111
117
* Mutex to guard access to validation specific variables, such as reading
@@ -2338,13 +2344,29 @@ bool CChainState::FlushStateToDisk(
2338
2344
CoinsCacheSizeState cache_state = GetCoinsCacheSizeState ();
2339
2345
LOCK (m_blockman.cs_LastBlockFile );
2340
2346
if (fPruneMode && (m_blockman.m_check_for_pruning || nManualPruneHeight > 0 ) && !fReindex ) {
2341
- // make sure we don't prune above the blockfilterindexes bestblocks
2347
+ // make sure we don't prune above any of the prune locks bestblocks
2342
2348
// pruning is height-based
2343
- int last_prune = m_chain.Height (); // last height we can prune
2349
+ int last_prune{m_chain.Height ()}; // last height we can prune
2350
+ std::optional<std::string> limiting_lock; // prune lock that actually was the limiting factor, only used for logging
2351
+
2344
2352
ForEachBlockFilterIndex ([&](BlockFilterIndex& index) {
2345
- last_prune = std::max (1 , std::min (last_prune, index.GetSummary ().best_block_height ));
2353
+ last_prune = std::max (1 , std::min (last_prune, index.GetSummary ().best_block_height ));
2346
2354
});
2347
2355
2356
+ for (const auto & prune_lock : m_blockman.m_prune_locks ) {
2357
+ if (prune_lock.second .height_first == std::numeric_limits<int >::max ()) continue ;
2358
+ // Remove the buffer and one additional block here to get actual height that is outside of the buffer
2359
+ const int lock_height{prune_lock.second .height_first - PRUNE_LOCK_BUFFER - 1 };
2360
+ last_prune = std::max (1 , std::min (last_prune, lock_height));
2361
+ if (last_prune == lock_height) {
2362
+ limiting_lock = prune_lock.first ;
2363
+ }
2364
+ }
2365
+
2366
+ if (limiting_lock) {
2367
+ LogPrint (BCLog::PRUNE, " %s limited pruning to height %d\n " , limiting_lock.value (), last_prune);
2368
+ }
2369
+
2348
2370
if (nManualPruneHeight > 0 ) {
2349
2371
LOG_TIME_MILLIS_WITH_CATEGORY (" find files to prune (manual)" , BCLog::BENCH);
2350
2372
@@ -2581,6 +2603,18 @@ bool CChainState::DisconnectTip(BlockValidationState& state, DisconnectedBlockTr
2581
2603
assert (flushed);
2582
2604
}
2583
2605
LogPrint (BCLog::BENCH, " - Disconnect block: %.2fms\n " , (GetTimeMicros () - nStart) * MILLI);
2606
+
2607
+ {
2608
+ // Prune locks that began at or after the tip should be moved backward so they get a chance to reorg
2609
+ const int max_height_first{pindexDelete->nHeight - 1 };
2610
+ for (auto & prune_lock : m_blockman.m_prune_locks ) {
2611
+ if (prune_lock.second .height_first <= max_height_first) continue ;
2612
+
2613
+ prune_lock.second .height_first = max_height_first;
2614
+ LogPrint (BCLog::PRUNE, " %s prune lock moved back to %d\n " , prune_lock.first , max_height_first);
2615
+ }
2616
+ }
2617
+
2584
2618
// Write the chain state to disk, if necessary.
2585
2619
if (!FlushStateToDisk (state, FlushStateMode::IF_NEEDED)) {
2586
2620
return false ;
0 commit comments