@@ -4646,143 +4646,23 @@ bool CChainState::ReplayBlocks(const CChainParams& params)
4646
4646
return true ;
4647
4647
}
4648
4648
4649
- // ! Helper for CChainState::RewindBlockIndex
4650
- void CChainState::EraseBlockData (CBlockIndex* index)
4649
+ bool CChainState::NeedsRedownload (const CChainParams& params) const
4651
4650
{
4652
4651
AssertLockHeld (cs_main);
4653
- assert (!m_chain.Contains (index)); // Make sure this block isn't active
4654
-
4655
- // Reduce validity
4656
- index->nStatus = std::min<unsigned int >(index->nStatus & BLOCK_VALID_MASK, BLOCK_VALID_TREE) | (index->nStatus & ~BLOCK_VALID_MASK);
4657
- // Remove have-data flags.
4658
- index->nStatus &= ~(BLOCK_HAVE_DATA | BLOCK_HAVE_UNDO);
4659
- // Remove storage location.
4660
- index->nFile = 0 ;
4661
- index->nDataPos = 0 ;
4662
- index->nUndoPos = 0 ;
4663
- // Remove various other things
4664
- index->nTx = 0 ;
4665
- index->nChainTx = 0 ;
4666
- index->nSequenceId = 0 ;
4667
- // Make sure it gets written.
4668
- setDirtyBlockIndex.insert (index);
4669
- // Update indexes
4670
- setBlockIndexCandidates.erase (index);
4671
- auto ret = m_blockman.m_blocks_unlinked .equal_range (index->pprev );
4672
- while (ret.first != ret.second ) {
4673
- if (ret.first ->second == index) {
4674
- m_blockman.m_blocks_unlinked .erase (ret.first ++);
4675
- } else {
4676
- ++ret.first ;
4677
- }
4678
- }
4679
- // Mark parent as eligible for main chain again
4680
- if (index->pprev && index->pprev ->IsValid (BLOCK_VALID_TRANSACTIONS) && index->pprev ->HaveTxsDownloaded ()) {
4681
- setBlockIndexCandidates.insert (index->pprev );
4682
- }
4683
- }
4684
-
4685
- bool CChainState::RewindBlockIndex (const CChainParams& params)
4686
- {
4687
- // Note that during -reindex-chainstate we are called with an empty m_chain!
4688
4652
4689
- // First erase all post-segwit blocks without witness not in the main chain,
4690
- // as this can we done without costly DisconnectTip calls. Active
4691
- // blocks will be dealt with below (releasing cs_main in between).
4692
- {
4693
- LOCK (cs_main);
4694
- for (const auto & entry : m_blockman.m_block_index ) {
4695
- if (IsWitnessEnabled (entry.second ->pprev , params.GetConsensus ()) && !(entry.second ->nStatus & BLOCK_OPT_WITNESS) && !m_chain.Contains (entry.second )) {
4696
- EraseBlockData (entry.second );
4697
- }
4698
- }
4699
- }
4653
+ // At and above params.SegwitHeight, segwit consensus rules must be validated
4654
+ CBlockIndex* block{m_chain.Tip ()};
4655
+ const int segwit_height{params.GetConsensus ().SegwitHeight };
4700
4656
4701
- // Find what height we need to reorganize to.
4702
- CBlockIndex *tip;
4703
- int nHeight = 1 ;
4704
- {
4705
- LOCK (cs_main);
4706
- while (nHeight <= m_chain.Height ()) {
4707
- // Although SCRIPT_VERIFY_WITNESS is now generally enforced on all
4708
- // blocks in ConnectBlock, we don't need to go back and
4709
- // re-download/re-verify blocks from before segwit actually activated.
4710
- if (IsWitnessEnabled (m_chain[nHeight - 1 ], params.GetConsensus ()) && !(m_chain[nHeight]->nStatus & BLOCK_OPT_WITNESS)) {
4711
- break ;
4712
- }
4713
- nHeight++;
4714
- }
4715
-
4716
- tip = m_chain.Tip ();
4717
- }
4718
- // nHeight is now the height of the first insufficiently-validated block, or tipheight + 1
4719
-
4720
- BlockValidationState state;
4721
- // Loop until the tip is below nHeight, or we reach a pruned block.
4722
- while (!ShutdownRequested ()) {
4723
- {
4724
- LOCK (cs_main);
4725
- LOCK (m_mempool.cs );
4726
- // Make sure nothing changed from under us (this won't happen because RewindBlockIndex runs before importing/network are active)
4727
- assert (tip == m_chain.Tip ());
4728
- if (tip == nullptr || tip->nHeight < nHeight) break ;
4729
- if (fPruneMode && !(tip->nStatus & BLOCK_HAVE_DATA)) {
4730
- // If pruning, don't try rewinding past the HAVE_DATA point;
4731
- // since older blocks can't be served anyway, there's
4732
- // no need to walk further, and trying to DisconnectTip()
4733
- // will fail (and require a needless reindex/redownload
4734
- // of the blockchain).
4735
- break ;
4736
- }
4737
-
4738
- // Disconnect block
4739
- if (!DisconnectTip (state, params, nullptr )) {
4740
- return error (" RewindBlockIndex: unable to disconnect block at height %i (%s)" , tip->nHeight , state.ToString ());
4741
- }
4742
-
4743
- // Reduce validity flag and have-data flags.
4744
- // We do this after actual disconnecting, otherwise we'll end up writing the lack of data
4745
- // to disk before writing the chainstate, resulting in a failure to continue if interrupted.
4746
- // Note: If we encounter an insufficiently validated block that
4747
- // is on m_chain, it must be because we are a pruning node, and
4748
- // this block or some successor doesn't HAVE_DATA, so we were unable to
4749
- // rewind all the way. Blocks remaining on m_chain at this point
4750
- // must not have their validity reduced.
4751
- EraseBlockData (tip);
4752
-
4753
- tip = tip->pprev ;
4754
- }
4755
- // Make sure the queue of validation callbacks doesn't grow unboundedly.
4756
- LimitValidationInterfaceQueue ();
4757
-
4758
- // Occasionally flush state to disk.
4759
- if (!FlushStateToDisk (params, state, FlushStateMode::PERIODIC)) {
4760
- LogPrintf (" RewindBlockIndex: unable to flush state to disk (%s)\n " , state.ToString ());
4761
- return false ;
4762
- }
4763
- }
4764
-
4765
- {
4766
- LOCK (cs_main);
4767
- if (m_chain.Tip () != nullptr ) {
4768
- // We can't prune block index candidates based on our tip if we have
4769
- // no tip due to m_chain being empty!
4770
- PruneBlockIndexCandidates ();
4771
-
4772
- CheckBlockIndex (params.GetConsensus ());
4773
-
4774
- // FlushStateToDisk can possibly read ::ChainActive(). Be conservative
4775
- // and skip it here, we're about to -reindex-chainstate anyway, so
4776
- // it'll get called a bunch real soon.
4777
- BlockValidationState state;
4778
- if (!FlushStateToDisk (params, state, FlushStateMode::ALWAYS)) {
4779
- LogPrintf (" RewindBlockIndex: unable to flush state to disk (%s)\n " , state.ToString ());
4780
- return false ;
4781
- }
4657
+ while (block != nullptr && block->nHeight >= segwit_height) {
4658
+ if (!(block->nStatus & BLOCK_OPT_WITNESS)) {
4659
+ // block is insufficiently validated for a segwit client
4660
+ return true ;
4782
4661
}
4662
+ block = block->pprev ;
4783
4663
}
4784
4664
4785
- return true ;
4665
+ return false ;
4786
4666
}
4787
4667
4788
4668
void CChainState::UnloadBlockIndex () {
0 commit comments