| 4715 | } |
| 4716 | |
| 4717 | void CChainState::CheckBlockIndex() |
| 4718 | { |
| 4719 | if (!fCheckBlockIndex) { |
| 4720 | return; |
| 4721 | } |
| 4722 | |
| 4723 | LOCK(cs_main); |
| 4724 | |
| 4725 | // During a reindex, we read the genesis block and call CheckBlockIndex before ActivateBestChain, |
| 4726 | // so we have the genesis block in m_blockman.m_block_index but no active chain. (A few of the |
| 4727 | // tests when iterating the block tree require that m_chain has been initialized.) |
| 4728 | if (m_chain.Height() < 0) { |
| 4729 | assert(m_blockman.m_block_index.size() <= 1); |
| 4730 | return; |
| 4731 | } |
| 4732 | |
| 4733 | // Build forward-pointing map of the entire block tree. |
| 4734 | std::multimap<CBlockIndex*,CBlockIndex*> forward; |
| 4735 | for (const std::pair<const uint256, CBlockIndex*>& entry : m_blockman.m_block_index) { |
| 4736 | forward.insert(std::make_pair(entry.second->pprev, entry.second)); |
| 4737 | } |
| 4738 | |
| 4739 | assert(forward.size() == m_blockman.m_block_index.size()); |
| 4740 | |
| 4741 | std::pair<std::multimap<CBlockIndex*,CBlockIndex*>::iterator,std::multimap<CBlockIndex*,CBlockIndex*>::iterator> rangeGenesis = forward.equal_range(nullptr); |
| 4742 | CBlockIndex *pindex = rangeGenesis.first->second; |
| 4743 | rangeGenesis.first++; |
| 4744 | assert(rangeGenesis.first == rangeGenesis.second); // There is only one index entry with parent nullptr. |
| 4745 | |
| 4746 | // Iterate over the entire block tree, using depth-first search. |
| 4747 | // Along the way, remember whether there are blocks on the path from genesis |
| 4748 | // block being explored which are the first to have certain properties. |
| 4749 | size_t nNodes = 0; |
| 4750 | int nHeight = 0; |
| 4751 | CBlockIndex* pindexFirstInvalid = nullptr; // Oldest ancestor of pindex which is invalid. |
| 4752 | CBlockIndex* pindexFirstMissing = nullptr; // Oldest ancestor of pindex which does not have BLOCK_HAVE_DATA. |
| 4753 | CBlockIndex* pindexFirstNeverProcessed = nullptr; // Oldest ancestor of pindex for which nTx == 0. |
| 4754 | CBlockIndex* pindexFirstNotTreeValid = nullptr; // Oldest ancestor of pindex which does not have BLOCK_VALID_TREE (regardless of being valid or not). |
| 4755 | CBlockIndex* pindexFirstNotTransactionsValid = nullptr; // Oldest ancestor of pindex which does not have BLOCK_VALID_TRANSACTIONS (regardless of being valid or not). |
| 4756 | CBlockIndex* pindexFirstNotChainValid = nullptr; // Oldest ancestor of pindex which does not have BLOCK_VALID_CHAIN (regardless of being valid or not). |
| 4757 | CBlockIndex* pindexFirstNotScriptsValid = nullptr; // Oldest ancestor of pindex which does not have BLOCK_VALID_SCRIPTS (regardless of being valid or not). |
| 4758 | while (pindex != nullptr) { |
| 4759 | nNodes++; |
| 4760 | if (pindexFirstInvalid == nullptr && pindex->nStatus & BLOCK_FAILED_VALID) pindexFirstInvalid = pindex; |
| 4761 | // Assumed-valid index entries will not have data since we haven't downloaded the |
| 4762 | // full block yet. |
| 4763 | if (pindexFirstMissing == nullptr && !(pindex->nStatus & BLOCK_HAVE_DATA) && !pindex->IsAssumedValid()) { |
| 4764 | pindexFirstMissing = pindex; |
| 4765 | } |
| 4766 | if (pindexFirstNeverProcessed == nullptr && pindex->nTx == 0) pindexFirstNeverProcessed = pindex; |
| 4767 | if (pindex->pprev != nullptr && pindexFirstNotTreeValid == nullptr && (pindex->nStatus & BLOCK_VALID_MASK) < BLOCK_VALID_TREE) pindexFirstNotTreeValid = pindex; |
| 4768 | |
| 4769 | if (pindex->pprev != nullptr && !pindex->IsAssumedValid()) { |
| 4770 | // Skip validity flag checks for BLOCK_ASSUMED_VALID index entries, since these |
| 4771 | // *_VALID_MASK flags will not be present for index entries we are temporarily assuming |
| 4772 | // valid. |
| 4773 | if (pindexFirstNotTransactionsValid == nullptr && |
| 4774 | (pindex->nStatus & BLOCK_VALID_MASK) < BLOCK_VALID_TRANSACTIONS) { |
no test coverage detected