aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/init.cpp5
-rw-r--r--src/validation.cpp17
2 files changed, 17 insertions, 5 deletions
diff --git a/src/init.cpp b/src/init.cpp
index 8fec69c2b8..2ea778a5b1 100644
--- a/src/init.cpp
+++ b/src/init.cpp
@@ -1452,7 +1452,10 @@ bool AppInitMain(boost::thread_group& threadGroup, CScheduler& scheduler)
assert(chainActive.Tip() != NULL);
}
- if (!fReindex && chainActive.Tip() != NULL) {
+ if (!fReindex) {
+ // Note that RewindBlockIndex MUST run even if we're about to -reindex-chainstate.
+ // It both disconnects blocks based on chainActive, and drops block data in
+ // mapBlockIndex based on lack of available witness data.
uiInterface.InitMessage(_("Rewinding blocks..."));
if (!RewindBlockIndex(chainparams)) {
strLoadError = _("Unable to rewind the database to a pre-fork state. You will need to redownload the blockchain");
diff --git a/src/validation.cpp b/src/validation.cpp
index 91982ead90..7ec77406ec 100644
--- a/src/validation.cpp
+++ b/src/validation.cpp
@@ -3763,6 +3763,8 @@ bool RewindBlockIndex(const CChainParams& params)
{
LOCK(cs_main);
+ // Note that during -reindex-chainstate we are called with an empty chainActive!
+
int nHeight = 1;
while (nHeight <= chainActive.Height()) {
if (IsWitnessEnabled(chainActive[nHeight - 1], params.GetConsensus()) && !(chainActive[nHeight]->nStatus & BLOCK_OPT_WITNESS)) {
@@ -3832,12 +3834,19 @@ bool RewindBlockIndex(const CChainParams& params)
}
}
- PruneBlockIndexCandidates();
+ if (chainActive.Tip() != NULL) {
+ // We can't prune block index candidates based on our tip if we have
+ // no tip due to chainActive being empty!
+ PruneBlockIndexCandidates();
- CheckBlockIndex(params.GetConsensus());
+ CheckBlockIndex(params.GetConsensus());
- if (!FlushStateToDisk(params, state, FLUSH_STATE_ALWAYS)) {
- return false;
+ // FlushStateToDisk can possibly read chainActive. Be conservative
+ // and skip it here, we're about to -reindex-chainstate anyway, so
+ // it'll get called a bunch real soon.
+ if (!FlushStateToDisk(params, state, FLUSH_STATE_ALWAYS)) {
+ return false;
+ }
}
return true;