@@ -4431,143 +4431,23 @@ bool CChainState::ReplayBlocks(const CChainParams& params)
4431
4431
return true ;
4432
4432
}
4433
4433
4434
- // ! Helper for CChainState::RewindBlockIndex
4435
- void CChainState::EraseBlockData (CBlockIndex* index)
4434
+ bool CChainState::NeedsRedownload (const CChainParams& params) const
4436
4435
{
4437
4436
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!
4473
4437
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 };
4485
4441
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 ;
4567
4446
}
4447
+ block = block->pprev ;
4568
4448
}
4569
4449
4570
- return true ;
4450
+ return false ;
4571
4451
}
4572
4452
4573
4453
void CChainState::UnloadBlockIndex () {
0 commit comments