* Return the tip of the chain with the most work in it, that isn't * known to be invalid (it's however far from certain to be valid). */
| 2985 | * known to be invalid (it's however far from certain to be valid). |
| 2986 | */ |
| 2987 | CBlockIndex* CChainState::FindMostWorkChain() |
| 2988 | { |
| 2989 | AssertLockHeld(::cs_main); |
| 2990 | do { |
| 2991 | CBlockIndex *pindexNew = nullptr; |
| 2992 | |
| 2993 | // Find the best candidate header. |
| 2994 | { |
| 2995 | std::set<CBlockIndex*, CBlockIndexWorkComparator>::reverse_iterator it = setBlockIndexCandidates.rbegin(); |
| 2996 | if (it == setBlockIndexCandidates.rend()) |
| 2997 | return nullptr; |
| 2998 | pindexNew = *it; |
| 2999 | } |
| 3000 | |
| 3001 | // Check whether all blocks on the path between the currently active chain and the candidate are valid. |
| 3002 | // Just going until the active chain is an optimization, as we know all blocks in it are valid already. |
| 3003 | CBlockIndex *pindexTest = pindexNew; |
| 3004 | bool fInvalidAncestor = false; |
| 3005 | while (pindexTest && !m_chain.Contains(pindexTest)) { |
| 3006 | assert(pindexTest->HaveTxsDownloaded() || pindexTest->nHeight == 0); |
| 3007 | |
| 3008 | // Pruned nodes may have entries in setBlockIndexCandidates for |
| 3009 | // which block files have been deleted. Remove those as candidates |
| 3010 | // for the most work chain if we come across them; we can't switch |
| 3011 | // to a chain unless we have all the non-active-chain parent blocks. |
| 3012 | bool fFailedChain = pindexTest->nStatus & BLOCK_FAILED_MASK; |
| 3013 | bool fMissingData = !(pindexTest->nStatus & BLOCK_HAVE_DATA); |
| 3014 | if (fFailedChain || fMissingData) { |
| 3015 | // Candidate chain is not usable (either invalid or missing data) |
| 3016 | if (fFailedChain && (m_chainman.m_best_invalid == nullptr || pindexNew->nChainWork > m_chainman.m_best_invalid->nChainWork)) { |
| 3017 | m_chainman.m_best_invalid = pindexNew; |
| 3018 | } |
| 3019 | CBlockIndex *pindexFailed = pindexNew; |
| 3020 | // Remove the entire chain from the set. |
| 3021 | while (pindexTest != pindexFailed) { |
| 3022 | if (fFailedChain) { |
| 3023 | pindexFailed->nStatus |= BLOCK_FAILED_CHILD; |
| 3024 | } else if (fMissingData) { |
| 3025 | // If we're missing data, then add back to m_blocks_unlinked, |
| 3026 | // so that if the block arrives in the future we can try adding |
| 3027 | // to setBlockIndexCandidates again. |
| 3028 | m_blockman.m_blocks_unlinked.insert( |
| 3029 | std::make_pair(pindexFailed->pprev, pindexFailed)); |
| 3030 | } |
| 3031 | setBlockIndexCandidates.erase(pindexFailed); |
| 3032 | pindexFailed = pindexFailed->pprev; |
| 3033 | } |
| 3034 | setBlockIndexCandidates.erase(pindexTest); |
| 3035 | fInvalidAncestor = true; |
| 3036 | break; |
| 3037 | } |
| 3038 | pindexTest = pindexTest->pprev; |
| 3039 | } |
| 3040 | if (!fInvalidAncestor) |
| 3041 | return pindexNew; |
| 3042 | } while(true); |
| 3043 | } |
| 3044 |