MCPcopy Create free account
hub / github.com/ElementsProject/elements / ReplayBlocks

Method ReplayBlocks

src/validation.cpp:4441–4506  ·  view source on GitHub ↗

Source from the content-addressed store, hash-verified

4439}
4440
4441bool CChainState::ReplayBlocks()
4442{
4443 LOCK(cs_main);
4444
4445 CCoinsView& db = this->CoinsDB();
4446 CCoinsViewCache cache(&db);
4447
4448 std::vector<uint256> hashHeads = db.GetHeadBlocks();
4449 if (hashHeads.empty()) return true; // We're already in a consistent state.
4450 if (hashHeads.size() != 2) return error("ReplayBlocks(): unknown inconsistent state");
4451
4452 uiInterface.ShowProgress(_("Replaying blocks…").translated, 0, false);
4453 LogPrintf("Replaying blocks\n");
4454
4455 const CBlockIndex* pindexOld = nullptr; // Old tip during the interrupted flush.
4456 const CBlockIndex* pindexNew; // New tip during the interrupted flush.
4457 const CBlockIndex* pindexFork = nullptr; // Latest block common to both the old and the new tip.
4458
4459 if (m_blockman.m_block_index.count(hashHeads[0]) == 0) {
4460 return error("ReplayBlocks(): reorganization to unknown block requested");
4461 }
4462 pindexNew = m_blockman.m_block_index[hashHeads[0]];
4463
4464 if (!hashHeads[1].IsNull()) { // The old tip is allowed to be 0, indicating it's the first flush.
4465 if (m_blockman.m_block_index.count(hashHeads[1]) == 0) {
4466 return error("ReplayBlocks(): reorganization from unknown block requested");
4467 }
4468 pindexOld = m_blockman.m_block_index[hashHeads[1]];
4469 pindexFork = LastCommonAncestor(pindexOld, pindexNew);
4470 assert(pindexFork != nullptr);
4471 }
4472
4473 // Rollback along the old branch.
4474 while (pindexOld != pindexFork) {
4475 if (pindexOld->nHeight > 0) { // Never disconnect the genesis block.
4476 CBlock block;
4477 if (!ReadBlockFromDisk(block, pindexOld, m_params.GetConsensus())) {
4478 return error("RollbackBlock(): ReadBlockFromDisk() failed at %d, hash=%s", pindexOld->nHeight, pindexOld->GetBlockHash().ToString());
4479 }
4480 LogPrintf("Rolling back %s (%i)\n", pindexOld->GetBlockHash().ToString(), pindexOld->nHeight);
4481 DisconnectResult res = DisconnectBlock(block, pindexOld, cache);
4482 if (res == DISCONNECT_FAILED) {
4483 return error("RollbackBlock(): DisconnectBlock failed at %d, hash=%s", pindexOld->nHeight, pindexOld->GetBlockHash().ToString());
4484 }
4485 // If DISCONNECT_UNCLEAN is returned, it means a non-existing UTXO was deleted, or an existing UTXO was
4486 // overwritten. It corresponds to cases where the block-to-be-disconnect never had all its operations
4487 // applied to the UTXO set. However, as both writing a UTXO and deleting a UTXO are idempotent operations,
4488 // the result is still a version of the UTXO set with the effects of that block undone.
4489 }
4490 pindexOld = pindexOld->pprev;
4491 }
4492
4493 // Roll forward from the forking point to the new tip.
4494 int nForkHeight = pindexFork ? pindexFork->nHeight : 0;
4495 for (int nHeight = nForkHeight + 1; nHeight <= pindexNew->nHeight; ++nHeight) {
4496 const CBlockIndex* pindex = pindexNew->GetAncestor(nHeight);
4497 LogPrintf("Rolling forward %s (%i)\n", pindex->GetBlockHash().ToString(), nHeight);
4498 uiInterface.ShowProgress(_("Replaying blocks…").translated, (int) ((nHeight - nForkHeight) * 100.0 / (pindexNew->nHeight - nForkHeight)) , false);

Callers 1

LoadChainstateFunction · 0.80

Calls 15

errorFunction · 0.85
_Function · 0.85
LastCommonAncestorFunction · 0.85
ReadBlockFromDiskFunction · 0.85
ShowProgressMethod · 0.80
countMethod · 0.80
GetAncestorMethod · 0.80
SetBestBlockMethod · 0.80
GetHeadBlocksMethod · 0.45
emptyMethod · 0.45
sizeMethod · 0.45
IsNullMethod · 0.45

Tested by

no test coverage detected