@@ -2367,7 +2367,7 @@ void static UpdateTip(CBlockIndex *pindexNew) {
2367
2367
}
2368
2368
2369
2369
/* * 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 )
2371
2371
{
2372
2372
CBlockIndex *pindexDelete = chainActive.Tip ();
2373
2373
assert (pindexDelete);
@@ -2387,6 +2387,9 @@ bool static DisconnectTip(CValidationState& state, const Consensus::Params& cons
2387
2387
// Write the chain state to disk, if necessary.
2388
2388
if (!FlushStateToDisk (state, FLUSH_STATE_IF_NEEDED))
2389
2389
return false ;
2390
+ if (fBare )
2391
+ return true ;
2392
+
2390
2393
// Resurrect mempool transactions from the disconnected block.
2391
2394
std::vector<uint256> vHashUpdate;
2392
2395
BOOST_FOREACH (const CTransaction &tx, block.vtx ) {
@@ -2823,7 +2826,7 @@ bool ReceivedBlockTransactions(const CBlock &block, CValidationState& state, CBl
2823
2826
pindexNew->nFile = pos.nFile ;
2824
2827
pindexNew->nDataPos = pos.nPos ;
2825
2828
pindexNew->nUndoPos = 0 ;
2826
- pindexNew->nStatus |= BLOCK_HAVE_DATA;
2829
+ pindexNew->nStatus |= BLOCK_HAVE_DATA | BLOCK_OPT_WITNESS ;
2827
2830
pindexNew->RaiseValidity (BLOCK_VALID_TRANSACTIONS);
2828
2831
setDirtyBlockIndex.insert (pindexNew);
2829
2832
@@ -3048,7 +3051,7 @@ static bool CheckIndexAgainstCheckpoint(const CBlockIndex* pindexPrev, CValidati
3048
3051
return true ;
3049
3052
}
3050
3053
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)
3052
3055
{
3053
3056
return (block.nVersion >= 5 && pindexPrev->nHeight + 1 >= params.SegWitHeight && IsSuperMajority (5 , pindexPrev, params.nMajorityEnforceBlockUpgrade , params));
3054
3057
}
@@ -3779,6 +3782,54 @@ bool CVerifyDB::VerifyDB(const CChainParams& chainparams, CCoinsView *coinsview,
3779
3782
return true ;
3780
3783
}
3781
3784
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
+
3782
3833
void UnloadBlockIndex ()
3783
3834
{
3784
3835
LOCK (cs_main);
0 commit comments