| 4737 | } |
| 4738 | |
| 4739 | void CChainState::CheckBlockIndex(const Consensus::Params& consensusParams) |
| 4740 | { |
| 4741 | if (!fCheckBlockIndex) { |
| 4742 | return; |
| 4743 | } |
| 4744 | |
| 4745 | LOCK(cs_main); |
| 4746 | |
| 4747 | // During a reindex, we read the genesis block and call CheckBlockIndex before ActivateBestChain, |
| 4748 | // so we have the genesis block in mapBlockIndex but no active chain. (A few of the tests when |
| 4749 | // iterating the block tree require that chainActive has been initialized.) |
| 4750 | if (chainActive.Height() < 0) { |
| 4751 | assert(mapBlockIndex.size() <= 1); |
| 4752 | return; |
| 4753 | } |
| 4754 | |
| 4755 | // Build forward-pointing map of the entire block tree. |
| 4756 | std::multimap<CBlockIndex*,CBlockIndex*> forward; |
| 4757 | for (auto& entry : mapBlockIndex) { |
| 4758 | forward.insert(std::make_pair(entry.second->pprev, entry.second)); |
| 4759 | } |
| 4760 | |
| 4761 | assert(forward.size() == mapBlockIndex.size()); |
| 4762 | |
| 4763 | std::pair<std::multimap<CBlockIndex*,CBlockIndex*>::iterator,std::multimap<CBlockIndex*,CBlockIndex*>::iterator> rangeGenesis = forward.equal_range(nullptr); |
| 4764 | CBlockIndex *pindex = rangeGenesis.first->second; |
| 4765 | rangeGenesis.first++; |
| 4766 | assert(rangeGenesis.first == rangeGenesis.second); // There is only one index entry with parent nullptr. |
| 4767 | |
| 4768 | // Iterate over the entire block tree, using depth-first search. |
| 4769 | // Along the way, remember whether there are blocks on the path from genesis |
| 4770 | // block being explored which are the first to have certain properties. |
| 4771 | size_t nNodes = 0; |
| 4772 | int nHeight = 0; |
| 4773 | CBlockIndex* pindexFirstInvalid = nullptr; // Oldest ancestor of pindex which is invalid. |
| 4774 | CBlockIndex* pindexFirstMissing = nullptr; // Oldest ancestor of pindex which does not have BLOCK_HAVE_DATA. |
| 4775 | CBlockIndex* pindexFirstNeverProcessed = nullptr; // Oldest ancestor of pindex for which nTx == 0. |
| 4776 | CBlockIndex* pindexFirstNotTreeValid = nullptr; // Oldest ancestor of pindex which does not have BLOCK_VALID_TREE (regardless of being valid or not). |
| 4777 | CBlockIndex* pindexFirstNotTransactionsValid = nullptr; // Oldest ancestor of pindex which does not have BLOCK_VALID_TRANSACTIONS (regardless of being valid or not). |
| 4778 | CBlockIndex* pindexFirstNotChainValid = nullptr; // Oldest ancestor of pindex which does not have BLOCK_VALID_CHAIN (regardless of being valid or not). |
| 4779 | CBlockIndex* pindexFirstNotScriptsValid = nullptr; // Oldest ancestor of pindex which does not have BLOCK_VALID_SCRIPTS (regardless of being valid or not). |
| 4780 | while (pindex != nullptr) { |
| 4781 | nNodes++; |
| 4782 | if (pindexFirstInvalid == nullptr && pindex->nStatus & BLOCK_FAILED_VALID) pindexFirstInvalid = pindex; |
| 4783 | if (pindexFirstMissing == nullptr && !(pindex->nStatus & BLOCK_HAVE_DATA)) pindexFirstMissing = pindex; |
| 4784 | if (pindexFirstNeverProcessed == nullptr && pindex->nTx == 0) pindexFirstNeverProcessed = pindex; |
| 4785 | if (pindex->pprev != nullptr && pindexFirstNotTreeValid == nullptr && (pindex->nStatus & BLOCK_VALID_MASK) < BLOCK_VALID_TREE) pindexFirstNotTreeValid = pindex; |
| 4786 | if (pindex->pprev != nullptr && pindexFirstNotTransactionsValid == nullptr && (pindex->nStatus & BLOCK_VALID_MASK) < BLOCK_VALID_TRANSACTIONS) pindexFirstNotTransactionsValid = pindex; |
| 4787 | if (pindex->pprev != nullptr && pindexFirstNotChainValid == nullptr && (pindex->nStatus & BLOCK_VALID_MASK) < BLOCK_VALID_CHAIN) pindexFirstNotChainValid = pindex; |
| 4788 | if (pindex->pprev != nullptr && pindexFirstNotScriptsValid == nullptr && (pindex->nStatus & BLOCK_VALID_MASK) < BLOCK_VALID_SCRIPTS) pindexFirstNotScriptsValid = pindex; |
| 4789 | |
| 4790 | // Begin: actual consistency checks. |
| 4791 | if (pindex->pprev == nullptr) { |
| 4792 | // Genesis block checks. |
| 4793 | assert(pindex->GetBlockHash() == consensusParams.hashGenesisBlock); // Genesis block's hash must match. |
| 4794 | assert(pindex == chainActive.Genesis()); // The current active chain's genesis block must be this block. |
| 4795 | } |
| 4796 | if (pindex->nChainTx == 0) assert(pindex->nSequenceId <= 0); // nSequenceId can't be set positive for blocks that aren't linked (negative is used for preciousblock) |
nothing calls this directly
no test coverage detected