@@ -2367,7 +2367,7 @@ void static UpdateTip(CBlockIndex *pindexNew) {
23672367}
23682368
23692369/* * Disconnect chainActive's tip. You probably want to call mempool.removeForReorg and manually re-limit mempool size after this, with cs_main held. */
2370- bool static DisconnectTip (CValidationState& state, const Consensus::Params& consensusParams)
2370+ bool static DisconnectTip (CValidationState& state, const Consensus::Params& consensusParams, bool fBare = false )
23712371{
23722372 CBlockIndex *pindexDelete = chainActive.Tip ();
23732373 assert (pindexDelete);
@@ -2387,6 +2387,9 @@ bool static DisconnectTip(CValidationState& state, const Consensus::Params& cons
23872387 // Write the chain state to disk, if necessary.
23882388 if (!FlushStateToDisk (state, FLUSH_STATE_IF_NEEDED))
23892389 return false ;
2390+ if (fBare )
2391+ return true ;
2392+
23902393 // Resurrect mempool transactions from the disconnected block.
23912394 std::vector<uint256> vHashUpdate;
23922395 BOOST_FOREACH (const CTransaction &tx, block.vtx ) {
@@ -2823,7 +2826,7 @@ bool ReceivedBlockTransactions(const CBlock &block, CValidationState& state, CBl
28232826 pindexNew->nFile = pos.nFile ;
28242827 pindexNew->nDataPos = pos.nPos ;
28252828 pindexNew->nUndoPos = 0 ;
2826- pindexNew->nStatus |= BLOCK_HAVE_DATA;
2829+ pindexNew->nStatus |= BLOCK_HAVE_DATA | BLOCK_OPT_WITNESS ;
28272830 pindexNew->RaiseValidity (BLOCK_VALID_TRANSACTIONS);
28282831 setDirtyBlockIndex.insert (pindexNew);
28292832
@@ -3048,7 +3051,7 @@ static bool CheckIndexAgainstCheckpoint(const CBlockIndex* pindexPrev, CValidati
30483051 return true ;
30493052}
30503053
3051- bool IsWitnessEnabled (const CBlock & block, const CBlockIndex* pindexPrev, const Consensus::Params& params)
3054+ bool IsWitnessEnabled (const CBlockHeader & block, const CBlockIndex* pindexPrev, const Consensus::Params& params)
30523055{
30533056 return (block.nVersion >= 5 && pindexPrev->nHeight + 1 >= params.SegWitHeight && IsSuperMajority (5 , pindexPrev, params.nMajorityEnforceBlockUpgrade , params));
30543057}
@@ -3779,6 +3782,54 @@ bool CVerifyDB::VerifyDB(const CChainParams& chainparams, CCoinsView *coinsview,
37793782 return true ;
37803783}
37813784
3785+ bool RewindBlockIndex (const Consensus::Params& params)
3786+ {
3787+ LOCK (cs_main);
3788+
3789+ int nHeight = 1 ;
3790+ while (nHeight <= chainActive.Height ()) {
3791+ CBlockHeader header = chainActive[nHeight]->GetBlockHeader ();
3792+ if (IsWitnessEnabled (header, chainActive[nHeight - 1 ], params) && !(chainActive[nHeight]->nStatus & BLOCK_OPT_WITNESS)) {
3793+ break ;
3794+ }
3795+ nHeight++;
3796+ }
3797+
3798+ // nHeight is now the height of the first insufficiently-validated block, or tipheight + 1
3799+ CValidationState state;
3800+ CBlockIndex* pindex = chainActive.Tip ();
3801+ while (chainActive.Height () >= nHeight) {
3802+ if (!DisconnectTip (state, Params ().GetConsensus (), true )) {
3803+ return error (" RewindBlockIndex: unable to disconnect block at height %i" , pindex->nHeight );
3804+ }
3805+ // Occasionally flush state to disk.
3806+ if (!FlushStateToDisk (state, FLUSH_STATE_PERIODIC))
3807+ return false ;
3808+ }
3809+
3810+ // Reduce validity flag and have-data flags.
3811+ // We do this after actual disconnecting, otherwise we'll end up writing the lack of data
3812+ // to disk before writing the chainstate, resulting in a failure to continue if interrupted.
3813+ while (pindex->nHeight >= nHeight) {
3814+ // Reduce validity
3815+ pindex->nStatus = std::min<unsigned int >(pindex->nStatus & BLOCK_VALID_MASK, BLOCK_VALID_TREE) | (pindex->nStatus & ~BLOCK_VALID_MASK);
3816+ // Remove have-data flags.
3817+ pindex->nStatus &= ~(BLOCK_HAVE_DATA | BLOCK_HAVE_UNDO);
3818+ // Remove storage location.
3819+ pindex->nFile = 0 ;
3820+ pindex->nDataPos = 0 ;
3821+ pindex->nUndoPos = 0 ;
3822+ // Make sure it gets written.
3823+ setDirtyBlockIndex.insert (pindex);
3824+ }
3825+
3826+ if (!FlushStateToDisk (state, FLUSH_STATE_ALWAYS)) {
3827+ return false ;
3828+ }
3829+
3830+ return true ;
3831+ }
3832+
37823833void UnloadBlockIndex ()
37833834{
37843835 LOCK (cs_main);
0 commit comments