@@ -4234,40 +4234,43 @@ bool CChainState::RewindBlockIndex(const CChainParams& params)
4234
4234
4235
4235
// nHeight is now the height of the first insufficiently-validated block, or tipheight + 1
4236
4236
CValidationState state;
4237
- CBlockIndex* pindex = chainActive.Tip ();
4238
- CBlockIndex* tip = pindex;
4239
- while (chainActive.Height () >= nHeight) {
4240
- if (fPruneMode && !(chainActive.Tip ()->nStatus & BLOCK_HAVE_DATA)) {
4237
+ CBlockIndex* tip = chainActive.Tip ();
4238
+ // Loop until the tip is below nHeight, or we reach a pruned block.
4239
+ while (true ) {
4240
+ // Make sure nothing changed from under us (this won't happen because RewindBlockIndex runs before importing/network are active)
4241
+ assert (tip == chainActive.Tip ());
4242
+ if (tip == nullptr || tip->nHeight < nHeight) break ;
4243
+ if (fPruneMode && !(tip->nStatus & BLOCK_HAVE_DATA)) {
4241
4244
// If pruning, don't try rewinding past the HAVE_DATA point;
4242
4245
// since older blocks can't be served anyway, there's
4243
4246
// no need to walk further, and trying to DisconnectTip()
4244
4247
// will fail (and require a needless reindex/redownload
4245
4248
// of the blockchain).
4246
4249
break ;
4247
4250
}
4251
+
4252
+ // Disconnect block
4248
4253
if (!DisconnectTip (state, params, nullptr )) {
4249
- return error (" RewindBlockIndex: unable to disconnect block at height %i (%s)" , pindex->nHeight , FormatStateMessage (state));
4250
- }
4251
- // Occasionally flush state to disk.
4252
- if (!FlushStateToDisk (params, state, FlushStateMode::PERIODIC)) {
4253
- LogPrintf (" RewindBlockIndex: unable to flush state to disk (%s)\n " , FormatStateMessage (state));
4254
- return false ;
4254
+ return error (" RewindBlockIndex: unable to disconnect block at height %i (%s)" , tip->nHeight , FormatStateMessage (state));
4255
4255
}
4256
- }
4257
4256
4258
- // Reduce validity flag and have-data flags.
4259
- // We do this after actual disconnecting, otherwise we'll end up writing the lack of data
4260
- // to disk before writing the chainstate, resulting in a failure to continue if interrupted.
4261
- while (tip->nHeight > chainActive.Height ()) {
4257
+ // Reduce validity flag and have-data flags.
4258
+ // We do this after actual disconnecting, otherwise we'll end up writing the lack of data
4259
+ // to disk before writing the chainstate, resulting in a failure to continue if interrupted.
4262
4260
// Note: If we encounter an insufficiently validated block that
4263
4261
// is on chainActive, it must be because we are a pruning node, and
4264
4262
// this block or some successor doesn't HAVE_DATA, so we were unable to
4265
4263
// rewind all the way. Blocks remaining on chainActive at this point
4266
4264
// must not have their validity reduced.
4267
- if (IsWitnessEnabled (tip->pprev , params.GetConsensus ()) && !(tip->nStatus & BLOCK_OPT_WITNESS)) {
4268
- EraseBlockData (tip);
4269
- }
4265
+ EraseBlockData (tip);
4266
+
4270
4267
tip = tip->pprev ;
4268
+
4269
+ // Occasionally flush state to disk.
4270
+ if (!FlushStateToDisk (params, state, FlushStateMode::PERIODIC)) {
4271
+ LogPrintf (" RewindBlockIndex: unable to flush state to disk (%s)\n " , FormatStateMessage (state));
4272
+ return false ;
4273
+ }
4271
4274
}
4272
4275
4273
4276
if (chainActive.Tip () != nullptr ) {
0 commit comments