MCPcopy Create free account
hub / github.com/bitcoin/bitcoin / ReplayBlocks

Method ReplayBlocks

src/validation.cpp:4793–4878  ·  view source on GitHub ↗

Source from the content-addressed store, hash-verified

4791}
4792
4793bool Chainstate::ReplayBlocks()
4794{
4795 LOCK(cs_main);
4796
4797 CCoinsView& db = this->CoinsDB();
4798 CCoinsViewCache cache(&db);
4799
4800 std::vector<uint256> hashHeads = db.GetHeadBlocks();
4801 if (hashHeads.empty()) return true; // We're already in a consistent state.
4802 if (hashHeads.size() != 2) {
4803 LogError("ReplayBlocks(): unknown inconsistent state\n");
4804 return false;
4805 }
4806
4807 m_chainman.GetNotifications().progress(_("Replaying blocks…"), 0, false);
4808 LogInfo("Replaying blocks");
4809
4810 const CBlockIndex* pindexOld = nullptr; // Old tip during the interrupted flush.
4811 const CBlockIndex* pindexNew; // New tip during the interrupted flush.
4812 const CBlockIndex* pindexFork = nullptr; // Latest block common to both the old and the new tip.
4813
4814 if (!m_blockman.m_block_index.contains(hashHeads[0])) {
4815 LogError("ReplayBlocks(): reorganization to unknown block requested\n");
4816 return false;
4817 }
4818 pindexNew = &(m_blockman.m_block_index[hashHeads[0]]);
4819
4820 if (!hashHeads[1].IsNull()) { // The old tip is allowed to be 0, indicating it's the first flush.
4821 if (!m_blockman.m_block_index.contains(hashHeads[1])) {
4822 LogError("ReplayBlocks(): reorganization from unknown block requested\n");
4823 return false;
4824 }
4825 pindexOld = &(m_blockman.m_block_index[hashHeads[1]]);
4826 pindexFork = LastCommonAncestor(pindexOld, pindexNew);
4827 assert(pindexFork != nullptr);
4828 }
4829
4830 // Rollback along the old branch.
4831 const int nForkHeight{pindexFork ? pindexFork->nHeight : 0};
4832 if (pindexOld != pindexFork) {
4833 LogInfo("Rolling back from %s (%i to %i)", pindexOld->GetBlockHash().ToString(), pindexOld->nHeight, nForkHeight);
4834 while (pindexOld != pindexFork) {
4835 if (pindexOld->nHeight > 0) { // Never disconnect the genesis block.
4836 CBlock block;
4837 if (!m_blockman.ReadBlock(block, *pindexOld)) {
4838 LogError("RollbackBlock(): ReadBlock() failed at %d, hash=%s\n", pindexOld->nHeight, pindexOld->GetBlockHash().ToString());
4839 return false;
4840 }
4841 if (pindexOld->nHeight % 10'000 == 0) {
4842 LogInfo("Rolling back %s (%i)", pindexOld->GetBlockHash().ToString(), pindexOld->nHeight);
4843 }
4844 DisconnectResult res = DisconnectBlock(block, pindexOld, cache);
4845 if (res == DISCONNECT_FAILED) {
4846 LogError("RollbackBlock(): DisconnectBlock failed at %d, hash=%s\n", pindexOld->nHeight, pindexOld->GetBlockHash().ToString());
4847 return false;
4848 }
4849 // If DISCONNECT_UNCLEAN is returned, it means a non-existing UTXO was deleted, or an existing UTXO was
4850 // overwritten. It corresponds to cases where the block-to-be-disconnect never had all its operations

Callers 1

EXCLUSIVE_LOCKS_REQUIREDFunction · 0.80

Calls 14

_Function · 0.85
LastCommonAncestorFunction · 0.85
GetHeadBlocksMethod · 0.45
emptyMethod · 0.45
sizeMethod · 0.45
progressMethod · 0.45
containsMethod · 0.45
IsNullMethod · 0.45
ToStringMethod · 0.45
GetBlockHashMethod · 0.45
ReadBlockMethod · 0.45
GetAncestorMethod · 0.45

Tested by

no test coverage detected