| 5151 | } |
| 5152 | |
| 5153 | void ChainstateManager::CheckBlockIndex() const |
| 5154 | { |
| 5155 | if (!ShouldCheckBlockIndex()) { |
| 5156 | return; |
| 5157 | } |
| 5158 | |
| 5159 | LOCK(cs_main); |
| 5160 | |
| 5161 | // During a reindex, we read the genesis block and call CheckBlockIndex before ActivateBestChain, |
| 5162 | // so we have the genesis block in m_blockman.m_block_index but no active chain. (A few of the |
| 5163 | // tests when iterating the block tree require that m_chain has been initialized.) |
| 5164 | if (ActiveChain().Height() < 0) { |
| 5165 | assert(m_blockman.m_block_index.size() <= 1); |
| 5166 | return; |
| 5167 | } |
| 5168 | |
| 5169 | // Build forward-pointing data structure for the entire block tree. |
| 5170 | // For performance reasons, indexes of the best header chain are stored in a vector (within CChain). |
| 5171 | // All remaining blocks are stored in a multimap. |
| 5172 | // The best header chain can differ from the active chain: E.g. its entries may belong to blocks that |
| 5173 | // are not yet validated. |
| 5174 | CChain best_hdr_chain; |
| 5175 | assert(m_best_header); |
| 5176 | assert(!(m_best_header->nStatus & BLOCK_FAILED_VALID)); |
| 5177 | best_hdr_chain.SetTip(*m_best_header); |
| 5178 | |
| 5179 | std::multimap<const CBlockIndex*, const CBlockIndex*> forward; |
| 5180 | for (auto& [_, block_index] : m_blockman.m_block_index) { |
| 5181 | // Only save indexes in forward that are not part of the best header chain. |
| 5182 | if (!best_hdr_chain.Contains(block_index)) { |
| 5183 | // Only genesis, which must be part of the best header chain, can have a nullptr parent. |
| 5184 | assert(block_index.pprev); |
| 5185 | forward.emplace(block_index.pprev, &block_index); |
| 5186 | } |
| 5187 | } |
| 5188 | assert(forward.size() + best_hdr_chain.Height() + 1 == m_blockman.m_block_index.size()); |
| 5189 | |
| 5190 | const CBlockIndex* pindex = best_hdr_chain[0]; |
| 5191 | assert(pindex); |
| 5192 | // Iterate over the entire block tree, using depth-first search. |
| 5193 | // Along the way, remember whether there are blocks on the path from genesis |
| 5194 | // block being explored which are the first to have certain properties. |
| 5195 | size_t nNodes = 0; |
| 5196 | int nHeight = 0; |
| 5197 | const CBlockIndex* pindexFirstInvalid = nullptr; // Oldest ancestor of pindex which is invalid. |
| 5198 | const CBlockIndex* pindexFirstMissing = nullptr; // Oldest ancestor of pindex which does not have BLOCK_HAVE_DATA, since assumeutxo snapshot if used. |
| 5199 | const CBlockIndex* pindexFirstNeverProcessed = nullptr; // Oldest ancestor of pindex for which nTx == 0, since assumeutxo snapshot if used. |
| 5200 | const CBlockIndex* pindexFirstNotTreeValid = nullptr; // Oldest ancestor of pindex which does not have BLOCK_VALID_TREE (regardless of being valid or not). |
| 5201 | const CBlockIndex* pindexFirstNotTransactionsValid = nullptr; // Oldest ancestor of pindex which does not have BLOCK_VALID_TRANSACTIONS (regardless of being valid or not), since assumeutxo snapshot if used. |
| 5202 | const CBlockIndex* pindexFirstNotChainValid = nullptr; // Oldest ancestor of pindex which does not have BLOCK_VALID_CHAIN (regardless of being valid or not), since assumeutxo snapshot if used. |
| 5203 | const CBlockIndex* pindexFirstNotScriptsValid = nullptr; // Oldest ancestor of pindex which does not have BLOCK_VALID_SCRIPTS (regardless of being valid or not), since assumeutxo snapshot if used. |
| 5204 | |
| 5205 | // After checking an assumeutxo snapshot block, reset pindexFirst pointers |
| 5206 | // to earlier blocks that have not been downloaded or validated yet, so |
| 5207 | // checks for later blocks can assume the earlier blocks were validated and |
| 5208 | // be stricter, testing for more requirements. |
| 5209 | const CBlockIndex* snap_base{CurrentChainstate().SnapshotBase()}; |
| 5210 | const CBlockIndex *snap_first_missing{}, *snap_first_notx{}, *snap_first_notv{}, *snap_first_nocv{}, *snap_first_nosv{}; |
no test coverage detected