@@ -3383,10 +3383,30 @@ bool CChainState::AcceptBlockHeader(const CBlockHeader& block, CValidationState&
3383
3383
if (!ContextualCheckBlockHeader (block, state, chainparams, pindexPrev, GetAdjustedTime ()))
3384
3384
return error (" %s: Consensus::ContextualCheckBlockHeader: %s, %s" , __func__, hash.ToString (), FormatStateMessage (state));
3385
3385
3386
- // If the previous block index isn't valid, determine if it descends from any block which
3387
- // has been found invalid (m_failed_blocks), then mark pindexPrev and any blocks
3388
- // between them as failed.
3386
+ /* Determine if this block descends from any block which has been found
3387
+ * invalid (m_failed_blocks), then mark pindexPrev and any blocks between
3388
+ * them as failed. For example:
3389
+ *
3390
+ * D3
3391
+ * /
3392
+ * B2 - C2
3393
+ * / \
3394
+ * A D2 - E2 - F2
3395
+ * \
3396
+ * B1 - C1 - D1 - E1
3397
+ *
3398
+ * In the case that we attempted to reorg from E1 to F2, only to find
3399
+ * C2 to be invalid, we would mark D2, E2, and F2 as BLOCK_FAILED_CHILD
3400
+ * but NOT D3 (it was not in any of our candidate sets at the time).
3401
+ *
3402
+ * In any case D3 will also be marked as BLOCK_FAILED_CHILD at restart
3403
+ * in LoadBlockIndex.
3404
+ */
3389
3405
if (!pindexPrev->IsValid (BLOCK_VALID_SCRIPTS)) {
3406
+ // The above does not mean "invalid": it checks if the previous block
3407
+ // hasn't been validated up to BLOCK_VALID_SCRIPTS. This is a performance
3408
+ // optimization, in the common case of adding a new block to the tip,
3409
+ // we don't need to iterate over the failed blocks list.
3390
3410
for (const CBlockIndex* failedit : m_failed_blocks) {
3391
3411
if (pindexPrev->GetAncestor (failedit->nHeight ) == failedit) {
3392
3412
assert (failedit->nStatus & BLOCK_FAILED_VALID);
0 commit comments