* 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). */
| 3126 | * known to be invalid (it's however far from certain to be valid). |
| 3127 | */ |
| 3128 | CBlockIndex* Chainstate::FindMostWorkChain() |
| 3129 | { |
| 3130 | AssertLockHeld(::cs_main); |
| 3131 | do { |
| 3132 | CBlockIndex *pindexNew = nullptr; |
| 3133 | |
| 3134 | // Find the best candidate header. |
| 3135 | { |
| 3136 | std::set<CBlockIndex*, CBlockIndexWorkComparator>::reverse_iterator it = setBlockIndexCandidates.rbegin(); |
| 3137 | if (it == setBlockIndexCandidates.rend()) |
| 3138 | return nullptr; |
| 3139 | pindexNew = *it; |
| 3140 | } |
| 3141 | |
| 3142 | // Check whether all blocks on the path between the currently active chain and the candidate are valid. |
| 3143 | // Just going until the active chain is an optimization, as we know all blocks in it are valid already. |
| 3144 | bool fInvalidAncestor = false; |
| 3145 | for (CBlockIndex *pindexTest = pindexNew; pindexTest && !m_chain.Contains(*pindexTest); pindexTest = pindexTest->pprev) { |
| 3146 | assert(pindexTest->HaveNumChainTxs() || pindexTest->nHeight == 0); |
| 3147 | |
| 3148 | // Pruned nodes may have entries in setBlockIndexCandidates for |
| 3149 | // which block files have been deleted. Remove those as candidates |
| 3150 | // for the most work chain if we come across them; we can't switch |
| 3151 | // to a chain unless we have all the non-active-chain parent blocks. |
| 3152 | bool fFailedChain = pindexTest->nStatus & BLOCK_FAILED_VALID; |
| 3153 | bool fMissingData = !(pindexTest->nStatus & BLOCK_HAVE_DATA); |
| 3154 | if (fFailedChain || fMissingData) { |
| 3155 | // Candidate chain is not usable (either invalid or missing data) |
| 3156 | if (fFailedChain && (m_chainman.m_best_invalid == nullptr || pindexNew->nChainWork > m_chainman.m_best_invalid->nChainWork)) { |
| 3157 | m_chainman.m_best_invalid = pindexNew; |
| 3158 | } |
| 3159 | // Remove the entire chain from the set. |
| 3160 | for (CBlockIndex *pindexFailed = pindexNew; pindexFailed != pindexTest; pindexFailed = pindexFailed->pprev) { |
| 3161 | // If we're missing data and not a descendant of an invalid block, |
| 3162 | // then add back to m_blocks_unlinked, so that if the block arrives in the future |
| 3163 | // we can try adding to setBlockIndexCandidates again. |
| 3164 | if (fMissingData && !fFailedChain) { |
| 3165 | // Avoid duplicate entries in m_blocks_unlinked. If the same entry is |
| 3166 | // processed twice in ReceivedBlockTransactions(), it may be re-added to |
| 3167 | // setBlockIndexCandidates with a modified nSequenceId, breaking ordering |
| 3168 | // guarantees and leading to undefined behavior. |
| 3169 | m_blockman.AddUnlinkedBlock(pindexFailed); |
| 3170 | } |
| 3171 | setBlockIndexCandidates.erase(pindexFailed); |
| 3172 | } |
| 3173 | setBlockIndexCandidates.erase(pindexTest); |
| 3174 | fInvalidAncestor = true; |
| 3175 | break; |
| 3176 | } |
| 3177 | } |
| 3178 | if (!fInvalidAncestor) |
| 3179 | return pindexNew; |
| 3180 | } while(true); |
| 3181 | } |
| 3182 | |
| 3183 | /** Delete all entries in setBlockIndexCandidates that are worse than the current tip. */ |
| 3184 | void Chainstate::PruneBlockIndexCandidates() { |
nothing calls this directly
no test coverage detected