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