From 19e8fd93c9aec77710f1f5d922240fc5a1cdd0de Mon Sep 17 00:00:00 2001 From: Peter John Bushnell Date: Wed, 9 Oct 2024 16:15:47 +0100 Subject: [PATCH] Prune undos on startup (#3087) --- src/chainparams.cpp | 4 +++- src/init.cpp | 19 +++++++++++++++++ src/validation.cpp | 50 ++++++++++++++++++++++++++------------------- src/validation.h | 6 ++++++ 4 files changed, 57 insertions(+), 22 deletions(-) diff --git a/src/chainparams.cpp b/src/chainparams.cpp index 0f205fc4350..34bcf99ffe0 100644 --- a/src/chainparams.cpp +++ b/src/chainparams.cpp @@ -376,7 +376,9 @@ class CMainParams : public CChainParams { {3600000,uint256S("cd7fb7dd41b2f77a6895133d15b81a4294663963512d756c75e6974e09a1e335")}, {3700000,uint256S("e579ea61173bce909b2bf13f2ede98c1025cef51350209953f235209a73bad01")}, {3800000,uint256S("8930b8a43a6413dc8739bec47123b0bb556f6ce2dac3583acefa533b966cb719")}, - + {3900000,uint256S("1118ddefb8b3c550421ccd71bf13794f0969f2f72f6ab72e0bf411e21a7bce96")}, + {4000000,uint256S("bc04577f86b72eb5fb4db79fb19a1f019afa6378ce6ef7e6401d3e14f55d6cb4")}, + {4100000,uint256S("5a173418adc9a1aa5bab4370871b2526771ec81ea445e963971bfafe88cba4b5")}, } }; diff --git a/src/init.cpp b/src/init.cpp index d9c605d1f47..2d1b608c887 100644 --- a/src/init.cpp +++ b/src/init.cpp @@ -2048,6 +2048,25 @@ bool AppInitMain(InitInterfaces& interfaces) break; } } + + // Prune based on checkpoints + auto &checkpoints = chainparams.Checkpoints().mapCheckpoints; + auto it = checkpoints.lower_bound(::ChainActive().Tip()->nHeight); + if (it != checkpoints.begin()) { + auto &[height, _] = *(--it); + std::vector compactBegin; + std::vector compactEnd; + PruneCheckpoint(*pcustomcsview, height, compactBegin, compactEnd); + if (!compactBegin.empty() && !compactEnd.empty()) { + pcustomcsview->Flush(); + pcustomcsDB->Flush(); + auto time = GetTimeMillis(); + pcustomcsDB->Compact(compactBegin, compactEnd); + compactBegin.clear(); + compactEnd.clear(); + LogPrint(BCLog::BENCH, " - DB compacting takes: %dms\n", GetTimeMillis() - time); + } + } } catch (const std::exception& e) { LogPrintf("%s\n", e.what()); strLoadError = _("Error opening block database").translated; diff --git a/src/validation.cpp b/src/validation.cpp index 09ad19e2dba..77f3af87a0f 100644 --- a/src/validation.cpp +++ b/src/validation.cpp @@ -3416,27 +3416,8 @@ bool CChainState::ConnectBlock(const CBlock &block, auto &checkpoints = chainparams.Checkpoints().mapCheckpoints; auto it = checkpoints.find(pindex->nHeight); if (it != checkpoints.end()) { - bool pruneStarted = false; - auto time = GetTimeMillis(); - CCustomCSView pruned(mnview); - mnview.ForEachUndo([&](const UndoKey &key, CLazySerialize) { - if (key.height >= static_cast(it->first)) { // don't erase checkpoint height - return false; - } - if (!pruneStarted) { - pruneStarted = true; - LogPrintf("Pruning undo data prior %d, it can take a while...\n", it->first); - } - return pruned.DelUndo(key).ok; - }); - if (pruneStarted) { - auto &map = pruned.GetStorage().GetRaw(); - compactBegin = map.begin()->first; - compactEnd = map.rbegin()->first; - pruned.Flush(); - LogPrintf("Pruning undo data finished.\n"); - LogPrint(BCLog::BENCH, " - Pruning undo data takes: %dms\n", GetTimeMillis() - time); - } + auto &[height, _] = *it; + PruneCheckpoint(mnview, height, compactBegin, compactEnd); // we can safety delete old interest keys if (it->first > consensus.DF14FortCanningHillHeight) { CCustomCSView view(mnview); @@ -3476,6 +3457,33 @@ bool CChainState::ConnectBlock(const CBlock &block, return true; } +void PruneCheckpoint(CCustomCSView &mnview, + const int height, + std::vector &begin, + std::vector &end) { + bool pruneStarted{}; + auto time = GetTimeMillis(); + CCustomCSView pruned(mnview); + mnview.ForEachUndo([&](const UndoKey &key, CLazySerialize) { + if (key.height >= static_cast(height)) { // don't erase checkpoint height + return false; + } + if (!pruneStarted) { + pruneStarted = true; + LogPrintf("Pruning undo data prior %d, it can take a while...\n", height); + } + return pruned.DelUndo(key).ok; + }); + if (pruneStarted) { + auto &map = pruned.GetStorage().GetRaw(); + begin = map.begin()->first; + end = map.rbegin()->first; + pruned.Flush(); + LogPrintf("Pruning undo data finished.\n"); + LogPrint(BCLog::BENCH, " - Pruning undo data takes: %dms\n", GetTimeMillis() - time); + } +} + bool CChainState::FlushStateToDisk(const CChainParams &chainparams, CValidationState &state, FlushStateMode mode, diff --git a/src/validation.h b/src/validation.h index 8e6b60ae920..a2d9a064bf9 100644 --- a/src/validation.h +++ b/src/validation.h @@ -254,6 +254,12 @@ bool ProcessNewBlock(const CChainParams &chainparams, bool fForceProcessing, bool *fNewBlock) LOCKS_EXCLUDED(cs_main); +// Prunes undos based on checkpoints +void PruneCheckpoint(CCustomCSView &mnview, + const int height, + std::vector &begin, + std::vector &end); + /** * Process incoming block headers. *