@@ -4354,12 +4354,33 @@ void CChainState::CheckBlockIndex()
4354
4354
while (pindex != nullptr ) {
4355
4355
nNodes++;
4356
4356
if (pindexFirstInvalid == nullptr && pindex->nStatus & BLOCK_FAILED_VALID) pindexFirstInvalid = pindex;
4357
- if (pindexFirstMissing == nullptr && !(pindex->nStatus & BLOCK_HAVE_DATA)) pindexFirstMissing = pindex;
4357
+ // Assumed-valid index entries will not have data since we haven't downloaded the
4358
+ // full block yet.
4359
+ if (pindexFirstMissing == nullptr && !(pindex->nStatus & BLOCK_HAVE_DATA) && !pindex->IsAssumedValid ()) {
4360
+ pindexFirstMissing = pindex;
4361
+ }
4358
4362
if (pindexFirstNeverProcessed == nullptr && pindex->nTx == 0 ) pindexFirstNeverProcessed = pindex;
4359
4363
if (pindex->pprev != nullptr && pindexFirstNotTreeValid == nullptr && (pindex->nStatus & BLOCK_VALID_MASK) < BLOCK_VALID_TREE) pindexFirstNotTreeValid = pindex;
4360
- if (pindex->pprev != nullptr && pindexFirstNotTransactionsValid == nullptr && (pindex->nStatus & BLOCK_VALID_MASK) < BLOCK_VALID_TRANSACTIONS) pindexFirstNotTransactionsValid = pindex;
4361
- if (pindex->pprev != nullptr && pindexFirstNotChainValid == nullptr && (pindex->nStatus & BLOCK_VALID_MASK) < BLOCK_VALID_CHAIN) pindexFirstNotChainValid = pindex;
4362
- if (pindex->pprev != nullptr && pindexFirstNotScriptsValid == nullptr && (pindex->nStatus & BLOCK_VALID_MASK) < BLOCK_VALID_SCRIPTS) pindexFirstNotScriptsValid = pindex;
4364
+
4365
+ if (pindex->pprev != nullptr && !pindex->IsAssumedValid ()) {
4366
+ // Skip validity flag checks for BLOCK_ASSUMED_VALID index entries, since these
4367
+ // *_VALID_MASK flags will not be present for index entries we are temporarily assuming
4368
+ // valid.
4369
+ if (pindexFirstNotTransactionsValid == nullptr &&
4370
+ (pindex->nStatus & BLOCK_VALID_MASK) < BLOCK_VALID_TRANSACTIONS) {
4371
+ pindexFirstNotTransactionsValid = pindex;
4372
+ }
4373
+
4374
+ if (pindexFirstNotChainValid == nullptr &&
4375
+ (pindex->nStatus & BLOCK_VALID_MASK) < BLOCK_VALID_CHAIN) {
4376
+ pindexFirstNotChainValid = pindex;
4377
+ }
4378
+
4379
+ if (pindexFirstNotScriptsValid == nullptr &&
4380
+ (pindex->nStatus & BLOCK_VALID_MASK) < BLOCK_VALID_SCRIPTS) {
4381
+ pindexFirstNotScriptsValid = pindex;
4382
+ }
4383
+ }
4363
4384
4364
4385
// Begin: actual consistency checks.
4365
4386
if (pindex->pprev == nullptr ) {
@@ -4370,7 +4391,9 @@ void CChainState::CheckBlockIndex()
4370
4391
if (!pindex->HaveTxsDownloaded ()) assert (pindex->nSequenceId <= 0 ); // nSequenceId can't be set positive for blocks that aren't linked (negative is used for preciousblock)
4371
4392
// VALID_TRANSACTIONS is equivalent to nTx > 0 for all nodes (whether or not pruning has occurred).
4372
4393
// HAVE_DATA is only equivalent to nTx > 0 (or VALID_TRANSACTIONS) if no pruning has occurred.
4373
- if (!fHavePruned ) {
4394
+ // Unless these indexes are assumed valid and pending block download on a
4395
+ // background chainstate.
4396
+ if (!fHavePruned && !pindex->IsAssumedValid ()) {
4374
4397
// If we've never pruned, then HAVE_DATA should be equivalent to nTx > 0
4375
4398
assert (!(pindex->nStatus & BLOCK_HAVE_DATA) == (pindex->nTx == 0 ));
4376
4399
assert (pindexFirstMissing == pindexFirstNeverProcessed);
@@ -4379,7 +4402,16 @@ void CChainState::CheckBlockIndex()
4379
4402
if (pindex->nStatus & BLOCK_HAVE_DATA) assert (pindex->nTx > 0 );
4380
4403
}
4381
4404
if (pindex->nStatus & BLOCK_HAVE_UNDO) assert (pindex->nStatus & BLOCK_HAVE_DATA);
4382
- assert (((pindex->nStatus & BLOCK_VALID_MASK) >= BLOCK_VALID_TRANSACTIONS) == (pindex->nTx > 0 )); // This is pruning-independent.
4405
+ if (pindex->IsAssumedValid ()) {
4406
+ // Assumed-valid blocks should have some nTx value.
4407
+ assert (pindex->nTx > 0 );
4408
+ // Assumed-valid blocks should connect to the main chain.
4409
+ assert ((pindex->nStatus & BLOCK_VALID_MASK) >= BLOCK_VALID_TREE);
4410
+ } else {
4411
+ // Otherwise there should only be an nTx value if we have
4412
+ // actually seen a block's transactions.
4413
+ assert (((pindex->nStatus & BLOCK_VALID_MASK) >= BLOCK_VALID_TRANSACTIONS) == (pindex->nTx > 0 )); // This is pruning-independent.
4414
+ }
4383
4415
// All parents having had data (at some point) is equivalent to all parents being VALID_TRANSACTIONS, which is equivalent to HaveTxsDownloaded().
4384
4416
assert ((pindexFirstNeverProcessed == nullptr ) == pindex->HaveTxsDownloaded ());
4385
4417
assert ((pindexFirstNotTransactionsValid == nullptr ) == pindex->HaveTxsDownloaded ());
@@ -4396,11 +4428,17 @@ void CChainState::CheckBlockIndex()
4396
4428
}
4397
4429
if (!CBlockIndexWorkComparator ()(pindex, m_chain.Tip ()) && pindexFirstNeverProcessed == nullptr ) {
4398
4430
if (pindexFirstInvalid == nullptr ) {
4431
+ const bool is_active = this == &m_chainman.ActiveChainstate ();
4432
+
4399
4433
// If this block sorts at least as good as the current tip and
4400
4434
// is valid and we have all data for its parents, it must be in
4401
4435
// setBlockIndexCandidates. m_chain.Tip() must also be there
4402
4436
// even if some data has been pruned.
4403
- if (pindexFirstMissing == nullptr || pindex == m_chain.Tip ()) {
4437
+ //
4438
+ // Don't perform this check for the background chainstate since
4439
+ // its setBlockIndexCandidates shouldn't have some entries (i.e. those past the
4440
+ // snapshot block) which do exist in the block index for the active chainstate.
4441
+ if (is_active && (pindexFirstMissing == nullptr || pindex == m_chain.Tip ())) {
4404
4442
assert (setBlockIndexCandidates.count (pindex));
4405
4443
}
4406
4444
// If some parent is missing, then it could be that this block was in
0 commit comments