* 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). */
| 2625 | * known to be invalid (it's however far from certain to be valid). |
| 2626 | */ |
| 2627 | CBlockIndex* CChainState::FindMostWorkChain() { |
| 2628 | do { |
| 2629 | CBlockIndex *pindexNew = nullptr; |
| 2630 | |
| 2631 | // Find the best candidate header. |
| 2632 | { |
| 2633 | std::set<CBlockIndex*, CBlockIndexWorkComparator>::reverse_iterator it = setBlockIndexCandidates.rbegin(); |
| 2634 | if (it == setBlockIndexCandidates.rend()) |
| 2635 | return nullptr; |
| 2636 | pindexNew = *it; |
| 2637 | } |
| 2638 | |
| 2639 | // If this block will cause a finalized block to be reorged, then we |
| 2640 | // mark it as invalid. |
| 2641 | if (pindexFinalized && !AreOnTheSameFork(pindexNew, pindexFinalized)) { |
| 2642 | LogPrintf("Mark block %s invalid because it forks prior to the finalization point %d.\n", |
| 2643 | pindexNew->GetBlockHash().ToString(), |
| 2644 | pindexFinalized->nHeight); |
| 2645 | pindexNew->nStatus |= BLOCK_FAILED_VALID; |
| 2646 | InvalidChainFound(pindexNew); |
| 2647 | } |
| 2648 | |
| 2649 | // Check whether all blocks on the path between the currently active chain and the candidate are valid. |
| 2650 | // Just going until the active chain is an optimization, as we know all blocks in it are valid already. |
| 2651 | CBlockIndex *pindexTest = pindexNew; |
| 2652 | bool fInvalidAncestor = false; |
| 2653 | while (pindexTest && !chainActive.Contains(pindexTest)) { |
| 2654 | assert(pindexTest->nChainTx || pindexTest->nHeight == 0); |
| 2655 | |
| 2656 | // Pruned nodes may have entries in setBlockIndexCandidates for |
| 2657 | // which block files have been deleted. Remove those as candidates |
| 2658 | // for the most work chain if we come across them; we can't switch |
| 2659 | // to a chain unless we have all the non-active-chain parent blocks. |
| 2660 | bool fFailedChain = pindexTest->nStatus & BLOCK_FAILED_MASK; |
| 2661 | bool fMissingData = !(pindexTest->nStatus & BLOCK_HAVE_DATA); |
| 2662 | if (fFailedChain || fMissingData) { |
| 2663 | // Candidate chain is not usable (either invalid or missing data) |
| 2664 | if (fFailedChain && (pindexBestInvalid == nullptr || pindexNew->nChainWork > pindexBestInvalid->nChainWork)) |
| 2665 | pindexBestInvalid = pindexNew; |
| 2666 | CBlockIndex *pindexFailed = pindexNew; |
| 2667 | // Remove the entire chain from the set. |
| 2668 | while (pindexTest != pindexFailed) { |
| 2669 | if (fFailedChain) { |
| 2670 | pindexFailed->nStatus |= BLOCK_FAILED_CHILD; |
| 2671 | } else if (fMissingData) { |
| 2672 | // If we're missing data, then add back to mapBlocksUnlinked, |
| 2673 | // so that if the block arrives in the future we can try adding |
| 2674 | // to setBlockIndexCandidates again. |
| 2675 | mapBlocksUnlinked.insert(std::make_pair(pindexFailed->pprev, pindexFailed)); |
| 2676 | } |
| 2677 | setBlockIndexCandidates.erase(pindexFailed); |
| 2678 | pindexFailed = pindexFailed->pprev; |
| 2679 | } |
| 2680 | |
| 2681 | if (fFailedChain) { |
| 2682 | // We discovered a new chain tip that is either parked or |
| 2683 | // invalid, we may want to warn. |
| 2684 | CheckForkWarningConditionsOnNewFork(pindexNew); |
nothing calls this directly
no test coverage detected