Page MenuHomePhabricator

D11145.diff
No OneTemporary

D11145.diff

diff --git a/src/index/base.cpp b/src/index/base.cpp
--- a/src/index/base.cpp
+++ b/src/index/base.cpp
@@ -66,6 +66,48 @@
m_best_block_index = FindForkInGlobalIndex(::ChainActive(), locator);
}
m_synced = m_best_block_index.load() == ::ChainActive().Tip();
+ if (!m_synced) {
+ bool prune_violation = false;
+ if (!m_best_block_index) {
+ // index is not built yet
+ // make sure we have all block data back to the genesis
+ const CBlockIndex *block = ::ChainActive().Tip();
+ while (block->pprev && block->pprev->nStatus.hasData()) {
+ block = block->pprev;
+ }
+ prune_violation = block != ::ChainActive().Genesis();
+ }
+ // in case the index has a best block set and is not fully synced
+ // check if we have the required blocks to continue building the index
+ else {
+ const CBlockIndex *block_to_test = m_best_block_index.load();
+ if (!ChainActive().Contains(block_to_test)) {
+ // if the bestblock is not part of the mainchain, find the fork
+ // and make sure we have all data down to the fork
+ block_to_test = ::ChainActive().FindFork(block_to_test);
+ }
+ const CBlockIndex *block = ::ChainActive().Tip();
+ prune_violation = true;
+ // check backwards from the tip if we have all block data until we
+ // reach the indexes bestblock
+ while (block_to_test && block && block->nStatus.hasData()) {
+ if (block_to_test == block) {
+ prune_violation = false;
+ break;
+ }
+ assert(block->pprev);
+ block = block->pprev;
+ }
+ }
+ if (prune_violation) {
+ // throw error and graceful shutdown if we can't build the index
+ FatalError("%s: %s best block of the index goes beyond pruned "
+ "data. Please disable the index or reindex (which will "
+ "download the whole blockchain again)",
+ __func__, GetName());
+ return false;
+ }
+ }
return true;
}
@@ -181,6 +223,10 @@
assert(current_tip->GetAncestor(new_tip->nHeight) == new_tip);
// In the case of a reorg, ensure persisted block locator is not stale.
+ // Pruning has a minimum of 288 blocks-to-keep and getting the index
+ // out of sync may be possible but a users fault.
+ // In case we reorg beyond the pruned depth, ReadBlockFromDisk would
+ // throw and lead to a graceful shutdown
m_best_block_index = new_tip;
if (!Commit()) {
// If commit fails, revert the best block index to avoid corruption.
@@ -332,6 +378,7 @@
IndexSummary summary{};
summary.name = GetName();
summary.synced = m_synced;
- summary.best_block_height = m_best_block_index.load()->nHeight;
+ summary.best_block_height =
+ m_best_block_index ? m_best_block_index.load()->nHeight : 0;
return summary;
}
diff --git a/src/init.cpp b/src/init.cpp
--- a/src/init.cpp
+++ b/src/init.cpp
@@ -1900,10 +1900,6 @@
if (args.GetBoolArg("-txindex", DEFAULT_TXINDEX)) {
return InitError(_("Prune mode is incompatible with -txindex."));
}
- if (!g_enabled_filter_types.empty()) {
- return InitError(
- _("Prune mode is incompatible with -blockfilterindex."));
- }
}
// -bind and -whitebind can't be set when not listening
diff --git a/src/validation.h b/src/validation.h
--- a/src/validation.h
+++ b/src/validation.h
@@ -615,7 +615,7 @@
*/
void FindFilesToPrune(std::set<int> &setFilesToPrune,
uint64_t nPruneAfterHeight, int chain_tip_height,
- bool is_ibd);
+ int prune_height, bool is_ibd);
public:
BlockMap m_block_index GUARDED_BY(cs_main);
diff --git a/src/validation.cpp b/src/validation.cpp
--- a/src/validation.cpp
+++ b/src/validation.cpp
@@ -21,6 +21,7 @@
#include <consensus/tx_verify.h>
#include <consensus/validation.h>
#include <hash.h>
+#include <index/blockfilterindex.h>
#include <index/txindex.h>
#include <logging.h>
#include <logging/timer.h>
@@ -2116,22 +2117,36 @@
{
bool fFlushForPrune = false;
bool fDoFullFlush = false;
+
CoinsCacheSizeState cache_state =
GetCoinsCacheSizeState(&m_mempool);
LOCK(cs_LastBlockFile);
if (fPruneMode && (fCheckForPruning || nManualPruneHeight > 0) &&
!fReindex) {
+ // make sure we don't prune above the blockfilterindexes
+ // bestblocks
+ // pruning is height-based
+ // last height we can prune
+ int last_prune = m_chain.Height();
+ ForEachBlockFilterIndex([&](BlockFilterIndex &index) {
+ last_prune = std::max(
+ 1, std::min(last_prune,
+ index.GetSummary().best_block_height));
+ });
+
if (nManualPruneHeight > 0) {
LOG_TIME_MILLIS_WITH_CATEGORY(
"find files to prune (manual)", BCLog::BENCH);
m_blockman.FindFilesToPruneManual(
- setFilesToPrune, nManualPruneHeight, m_chain.Height());
+ setFilesToPrune,
+ std::min(last_prune, nManualPruneHeight),
+ m_chain.Height());
} else {
LOG_TIME_MILLIS_WITH_CATEGORY("find files to prune",
BCLog::BENCH);
m_blockman.FindFilesToPrune(
setFilesToPrune, chainparams.PruneAfterHeight(),
- m_chain.Height(), IsInitialBlockDownload());
+ m_chain.Height(), last_prune, IsInitialBlockDownload());
fCheckForPruning = false;
}
if (!setFilesToPrune.empty()) {
@@ -4585,7 +4600,8 @@
void BlockManager::FindFilesToPrune(std::set<int> &setFilesToPrune,
uint64_t nPruneAfterHeight,
- int chain_tip_height, bool is_ibd) {
+ int chain_tip_height, int prune_height,
+ bool is_ibd) {
LOCK2(cs_main, cs_LastBlockFile);
if (chain_tip_height < 0 || nPruneTarget == 0) {
return;
@@ -4594,7 +4610,8 @@
return;
}
- unsigned int nLastBlockWeCanPrune = chain_tip_height - MIN_BLOCKS_TO_KEEP;
+ unsigned int nLastBlockWeCanPrune = std::min(
+ prune_height, chain_tip_height - static_cast<int>(MIN_BLOCKS_TO_KEEP));
uint64_t nCurrentUsage = CalculateCurrentUsage();
// We don't check to prune until after we've allocated new space for files,
// so we should leave a buffer under our target to account for another

File Metadata

Mime Type
text/plain
Expires
Sat, Apr 26, 12:05 (2 h, 37 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
5573499
Default Alt Text
D11145.diff (7 KB)

Event Timeline