@@ -4431,143 +4431,23 @@ bool CChainState::ReplayBlocks(const CChainParams& params)
44314431 return true ;
44324432}
44334433
4434- // ! Helper for CChainState::RewindBlockIndex
4435- void CChainState::EraseBlockData (CBlockIndex* index)
4434+ bool CChainState::NeedsRedownload (const CChainParams& params) const
44364435{
44374436 AssertLockHeld (cs_main);
4438- assert (!m_chain.Contains (index)); // Make sure this block isn't active
4439-
4440- // Reduce validity
4441- index->nStatus = std::min<unsigned int >(index->nStatus & BLOCK_VALID_MASK, BLOCK_VALID_TREE) | (index->nStatus & ~BLOCK_VALID_MASK);
4442- // Remove have-data flags.
4443- index->nStatus &= ~(BLOCK_HAVE_DATA | BLOCK_HAVE_UNDO);
4444- // Remove storage location.
4445- index->nFile = 0 ;
4446- index->nDataPos = 0 ;
4447- index->nUndoPos = 0 ;
4448- // Remove various other things
4449- index->nTx = 0 ;
4450- index->nChainTx = 0 ;
4451- index->nSequenceId = 0 ;
4452- // Make sure it gets written.
4453- setDirtyBlockIndex.insert (index);
4454- // Update indexes
4455- setBlockIndexCandidates.erase (index);
4456- auto ret = m_blockman.m_blocks_unlinked .equal_range (index->pprev );
4457- while (ret.first != ret.second ) {
4458- if (ret.first ->second == index) {
4459- m_blockman.m_blocks_unlinked .erase (ret.first ++);
4460- } else {
4461- ++ret.first ;
4462- }
4463- }
4464- // Mark parent as eligible for main chain again
4465- if (index->pprev && index->pprev ->IsValid (BLOCK_VALID_TRANSACTIONS) && index->pprev ->HaveTxsDownloaded ()) {
4466- setBlockIndexCandidates.insert (index->pprev );
4467- }
4468- }
4469-
4470- bool CChainState::RewindBlockIndex (const CChainParams& params)
4471- {
4472- // Note that during -reindex-chainstate we are called with an empty m_chain!
44734437
4474- // First erase all post-segwit blocks without witness not in the main chain,
4475- // as this can we done without costly DisconnectTip calls. Active
4476- // blocks will be dealt with below (releasing cs_main in between).
4477- {
4478- LOCK (cs_main);
4479- for (const auto & entry : m_blockman.m_block_index ) {
4480- if (IsWitnessEnabled (entry.second ->pprev , params.GetConsensus ()) && !(entry.second ->nStatus & BLOCK_OPT_WITNESS) && !m_chain.Contains (entry.second )) {
4481- EraseBlockData (entry.second );
4482- }
4483- }
4484- }
4438+ // At and above params.SegwitHeight, segwit consensus rules must be validated
4439+ CBlockIndex* block{m_chain.Tip ()};
4440+ const int segwit_height{params.GetConsensus ().SegwitHeight };
44854441
4486- // Find what height we need to reorganize to.
4487- CBlockIndex *tip;
4488- int nHeight = 1 ;
4489- {
4490- LOCK (cs_main);
4491- while (nHeight <= m_chain.Height ()) {
4492- // Although SCRIPT_VERIFY_WITNESS is now generally enforced on all
4493- // blocks in ConnectBlock, we don't need to go back and
4494- // re-download/re-verify blocks from before segwit actually activated.
4495- if (IsWitnessEnabled (m_chain[nHeight - 1 ], params.GetConsensus ()) && !(m_chain[nHeight]->nStatus & BLOCK_OPT_WITNESS)) {
4496- break ;
4497- }
4498- nHeight++;
4499- }
4500-
4501- tip = m_chain.Tip ();
4502- }
4503- // nHeight is now the height of the first insufficiently-validated block, or tipheight + 1
4504-
4505- BlockValidationState state;
4506- // Loop until the tip is below nHeight, or we reach a pruned block.
4507- while (!ShutdownRequested ()) {
4508- {
4509- LOCK (cs_main);
4510- LOCK (m_mempool.cs );
4511- // Make sure nothing changed from under us (this won't happen because RewindBlockIndex runs before importing/network are active)
4512- assert (tip == m_chain.Tip ());
4513- if (tip == nullptr || tip->nHeight < nHeight) break ;
4514- if (fPruneMode && !(tip->nStatus & BLOCK_HAVE_DATA)) {
4515- // If pruning, don't try rewinding past the HAVE_DATA point;
4516- // since older blocks can't be served anyway, there's
4517- // no need to walk further, and trying to DisconnectTip()
4518- // will fail (and require a needless reindex/redownload
4519- // of the blockchain).
4520- break ;
4521- }
4522-
4523- // Disconnect block
4524- if (!DisconnectTip (state, params, nullptr )) {
4525- return error (" RewindBlockIndex: unable to disconnect block at height %i (%s)" , tip->nHeight , state.ToString ());
4526- }
4527-
4528- // Reduce validity flag and have-data flags.
4529- // We do this after actual disconnecting, otherwise we'll end up writing the lack of data
4530- // to disk before writing the chainstate, resulting in a failure to continue if interrupted.
4531- // Note: If we encounter an insufficiently validated block that
4532- // is on m_chain, it must be because we are a pruning node, and
4533- // this block or some successor doesn't HAVE_DATA, so we were unable to
4534- // rewind all the way. Blocks remaining on m_chain at this point
4535- // must not have their validity reduced.
4536- EraseBlockData (tip);
4537-
4538- tip = tip->pprev ;
4539- }
4540- // Make sure the queue of validation callbacks doesn't grow unboundedly.
4541- LimitValidationInterfaceQueue ();
4542-
4543- // Occasionally flush state to disk.
4544- if (!FlushStateToDisk (params, state, FlushStateMode::PERIODIC)) {
4545- LogPrintf (" RewindBlockIndex: unable to flush state to disk (%s)\n " , state.ToString ());
4546- return false ;
4547- }
4548- }
4549-
4550- {
4551- LOCK (cs_main);
4552- if (m_chain.Tip () != nullptr ) {
4553- // We can't prune block index candidates based on our tip if we have
4554- // no tip due to m_chain being empty!
4555- PruneBlockIndexCandidates ();
4556-
4557- CheckBlockIndex (params.GetConsensus ());
4558-
4559- // FlushStateToDisk can possibly read ::ChainActive(). Be conservative
4560- // and skip it here, we're about to -reindex-chainstate anyway, so
4561- // it'll get called a bunch real soon.
4562- BlockValidationState state;
4563- if (!FlushStateToDisk (params, state, FlushStateMode::ALWAYS)) {
4564- LogPrintf (" RewindBlockIndex: unable to flush state to disk (%s)\n " , state.ToString ());
4565- return false ;
4566- }
4442+ while (block != nullptr && block->nHeight >= segwit_height) {
4443+ if (!(block->nStatus & BLOCK_OPT_WITNESS)) {
4444+ // block is insufficiently validated for a segwit client
4445+ return true ;
45674446 }
4447+ block = block->pprev ;
45684448 }
45694449
4570- return true ;
4450+ return false ;
45714451}
45724452
45734453void CChainState::UnloadBlockIndex () {
0 commit comments