* Try to make some progress towards making pindexMostWork the active block. * pblock is either NULL or a pointer to a CBlock corresponding to pindexMostWork. */
| 3838 | * pblock is either NULL or a pointer to a CBlock corresponding to pindexMostWork. |
| 3839 | */ |
| 3840 | static bool ActivateBestChainStep(CValidationState& state, const CChainParams& chainparams, CBlockIndex* pindexMostWork, const CBlock* pblock) |
| 3841 | { |
| 3842 | AssertLockHeld(cs_main); |
| 3843 | bool fInvalidFound = false; |
| 3844 | const CBlockIndex* pindexOldTip = chainActive.Tip(); |
| 3845 | const CBlockIndex* pindexFork = chainActive.FindFork(pindexMostWork); |
| 3846 | |
| 3847 | // Disconnect active blocks which are no longer in the best chain. |
| 3848 | while (chainActive.Tip() && chainActive.Tip() != pindexFork) { |
| 3849 | if (!DisconnectTip(state, chainparams)) |
| 3850 | return false; |
| 3851 | } |
| 3852 | |
| 3853 | // Build list of new blocks to connect. |
| 3854 | std::vector<CBlockIndex*> vpindexToConnect; |
| 3855 | bool fContinue = true; |
| 3856 | int nHeight = pindexFork ? pindexFork->nHeight : -1; |
| 3857 | while (fContinue && nHeight != pindexMostWork->nHeight) { |
| 3858 | // Don't iterate the entire list of potential improvements toward the best tip, as we likely only need |
| 3859 | // a few blocks along the way. |
| 3860 | int nTargetHeight = std::min(nHeight + 32, pindexMostWork->nHeight); |
| 3861 | vpindexToConnect.clear(); |
| 3862 | vpindexToConnect.reserve(nTargetHeight - nHeight); |
| 3863 | CBlockIndex* pindexIter = pindexMostWork->GetAncestor(nTargetHeight); |
| 3864 | while (pindexIter && pindexIter->nHeight != nHeight) { |
| 3865 | vpindexToConnect.push_back(pindexIter); |
| 3866 | pindexIter = pindexIter->pprev; |
| 3867 | } |
| 3868 | nHeight = nTargetHeight; |
| 3869 | |
| 3870 | // Connect new blocks. |
| 3871 | for (CBlockIndex* pindexConnect : reverse_iterate(vpindexToConnect)) { |
| 3872 | if (!ConnectTip(state, chainparams, pindexConnect, pindexConnect == pindexMostWork ? pblock : NULL)) { |
| 3873 | if (state.IsInvalid()) { |
| 3874 | // The block violates a consensus rule. |
| 3875 | if (!state.CorruptionPossible()) { |
| 3876 | InvalidChainFound(vpindexToConnect.front()); |
| 3877 | } |
| 3878 | state = CValidationState(); |
| 3879 | fInvalidFound = true; |
| 3880 | fContinue = false; |
| 3881 | break; |
| 3882 | } else { |
| 3883 | // A system error occurred (disk space, database error, ...). |
| 3884 | return false; |
| 3885 | } |
| 3886 | } else { |
| 3887 | PruneBlockIndexCandidates(); |
| 3888 | if (!pindexOldTip || chainActive.Tip()->nChainWork > pindexOldTip->nChainWork) { |
| 3889 | // We're in a better position than we were. Return temporarily to release the lock. |
| 3890 | fContinue = false; |
| 3891 | break; |
| 3892 | } |
| 3893 | } |
| 3894 | } |
| 3895 | } |
| 3896 | |
| 3897 | // Callbacks/notifications for a new best chain. |
no test coverage detected