@@ -4209,9 +4209,18 @@ void CChainState::EraseBlockData(CBlockIndex* index)
42094209bool CChainState::RewindBlockIndex (const CChainParams& params)
42104210{
42114211 LOCK (cs_main);
4212-
42134212 // Note that during -reindex-chainstate we are called with an empty chainActive!
42144213
4214+ // First erase all post-segwit blocks without witness not in the main chain,
4215+ // as this can we done without costly DisconnectTip calls. Active
4216+ // blocks will be dealt with below.
4217+ for (const auto & entry : mapBlockIndex) {
4218+ if (IsWitnessEnabled (entry.second ->pprev , params.GetConsensus ()) && !(entry.second ->nStatus & BLOCK_OPT_WITNESS) && !chainActive.Contains (entry.second )) {
4219+ EraseBlockData (entry.second );
4220+ }
4221+ }
4222+
4223+ // Find what height we need to reorganize to.
42154224 int nHeight = 1 ;
42164225 while (nHeight <= chainActive.Height ()) {
42174226 // Although SCRIPT_VERIFY_WITNESS is now generally enforced on all
@@ -4226,6 +4235,7 @@ bool CChainState::RewindBlockIndex(const CChainParams& params)
42264235 // nHeight is now the height of the first insufficiently-validated block, or tipheight + 1
42274236 CValidationState state;
42284237 CBlockIndex* pindex = chainActive.Tip ();
4238+ CBlockIndex* tip = pindex;
42294239 while (chainActive.Height () >= nHeight) {
42304240 if (fPruneMode && !(chainActive.Tip ()->nStatus & BLOCK_HAVE_DATA)) {
42314241 // If pruning, don't try rewinding past the HAVE_DATA point;
@@ -4248,17 +4258,16 @@ bool CChainState::RewindBlockIndex(const CChainParams& params)
42484258 // Reduce validity flag and have-data flags.
42494259 // We do this after actual disconnecting, otherwise we'll end up writing the lack of data
42504260 // to disk before writing the chainstate, resulting in a failure to continue if interrupted.
4251- for (const auto & entry : mapBlockIndex) {
4252- CBlockIndex* pindexIter = entry.second ;
4253-
4261+ while (tip->nHeight > chainActive.Height ()) {
42544262 // Note: If we encounter an insufficiently validated block that
42554263 // is on chainActive, it must be because we are a pruning node, and
42564264 // this block or some successor doesn't HAVE_DATA, so we were unable to
42574265 // rewind all the way. Blocks remaining on chainActive at this point
42584266 // must not have their validity reduced.
4259- if (IsWitnessEnabled (pindexIter ->pprev , params.GetConsensus ()) && !(pindexIter ->nStatus & BLOCK_OPT_WITNESS) && !chainActive. Contains (pindexIter )) {
4260- EraseBlockData (pindexIter );
4267+ if (IsWitnessEnabled (tip ->pprev , params.GetConsensus ()) && !(tip ->nStatus & BLOCK_OPT_WITNESS)) {
4268+ EraseBlockData (tip );
42614269 }
4270+ tip = tip->pprev ;
42624271 }
42634272
42644273 if (chainActive.Tip () != nullptr ) {
0 commit comments