Skip to content

Commit 8f5710f

Browse files
committed
validation: fix CheckBlockIndex for multiple chainstates
Adjust CheckBlockIndex to account for - assumed-valid block indexes lacking transaction data, and - setBlockIndexCandidates for the background chainstate not containing certain entries which rely on assumed-valid ancestors.
1 parent 5a80773 commit 8f5710f

File tree

1 file changed

+45
-7
lines changed

1 file changed

+45
-7
lines changed

src/validation.cpp

Lines changed: 45 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -4354,12 +4354,33 @@ void CChainState::CheckBlockIndex()
43544354
while (pindex != nullptr) {
43554355
nNodes++;
43564356
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+
}
43584362
if (pindexFirstNeverProcessed == nullptr && pindex->nTx == 0) pindexFirstNeverProcessed = pindex;
43594363
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+
}
43634384

43644385
// Begin: actual consistency checks.
43654386
if (pindex->pprev == nullptr) {
@@ -4370,7 +4391,9 @@ void CChainState::CheckBlockIndex()
43704391
if (!pindex->HaveTxsDownloaded()) assert(pindex->nSequenceId <= 0); // nSequenceId can't be set positive for blocks that aren't linked (negative is used for preciousblock)
43714392
// VALID_TRANSACTIONS is equivalent to nTx > 0 for all nodes (whether or not pruning has occurred).
43724393
// 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()) {
43744397
// If we've never pruned, then HAVE_DATA should be equivalent to nTx > 0
43754398
assert(!(pindex->nStatus & BLOCK_HAVE_DATA) == (pindex->nTx == 0));
43764399
assert(pindexFirstMissing == pindexFirstNeverProcessed);
@@ -4379,7 +4402,16 @@ void CChainState::CheckBlockIndex()
43794402
if (pindex->nStatus & BLOCK_HAVE_DATA) assert(pindex->nTx > 0);
43804403
}
43814404
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+
}
43834415
// All parents having had data (at some point) is equivalent to all parents being VALID_TRANSACTIONS, which is equivalent to HaveTxsDownloaded().
43844416
assert((pindexFirstNeverProcessed == nullptr) == pindex->HaveTxsDownloaded());
43854417
assert((pindexFirstNotTransactionsValid == nullptr) == pindex->HaveTxsDownloaded());
@@ -4396,11 +4428,17 @@ void CChainState::CheckBlockIndex()
43964428
}
43974429
if (!CBlockIndexWorkComparator()(pindex, m_chain.Tip()) && pindexFirstNeverProcessed == nullptr) {
43984430
if (pindexFirstInvalid == nullptr) {
4431+
const bool is_active = this == &m_chainman.ActiveChainstate();
4432+
43994433
// If this block sorts at least as good as the current tip and
44004434
// is valid and we have all data for its parents, it must be in
44014435
// setBlockIndexCandidates. m_chain.Tip() must also be there
44024436
// 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())) {
44044442
assert(setBlockIndexCandidates.count(pindex));
44054443
}
44064444
// If some parent is missing, then it could be that this block was in

0 commit comments

Comments
 (0)