| 5611 | } |
| 5612 | |
| 5613 | bool CVerifyDB::VerifyDB(const CChainParams& chainparams, CCoinsView* coinsview, int nCheckLevel, int nCheckDepth) |
| 5614 | { |
| 5615 | LOCK(cs_main); |
| 5616 | if (chainActive.Tip() == NULL || chainActive.Tip()->pprev == NULL) |
| 5617 | return true; |
| 5618 | |
| 5619 | // Verify blocks in the best chain |
| 5620 | if (nCheckDepth <= 0 || nCheckDepth > chainActive.Height()) |
| 5621 | nCheckDepth = chainActive.Height(); |
| 5622 | nCheckLevel = std::max(0, std::min(4, nCheckLevel)); |
| 5623 | LogPrintf("Verifying last %i blocks at level %i\n", nCheckDepth, nCheckLevel); |
| 5624 | CCoinsViewCache coins(coinsview); |
| 5625 | CBlockIndex* pindex; |
| 5626 | CBlockIndex* pindexFailure = NULL; |
| 5627 | int nGoodTransactions = 0; |
| 5628 | CValidationState state; |
| 5629 | |
| 5630 | CBlockIndex* pindexState = chainActive.Tip(); |
| 5631 | dev::h256 oldHashStateRoot = getGlobalStateRoot(pindexState); |
| 5632 | dev::h256 oldHashUTXORoot = getGlobalStateUTXO(pindexState); |
| 5633 | |
| 5634 | for (pindex = chainActive.Tip(); pindex && pindex->pprev; pindex = pindex->pprev) { |
| 5635 | boost::this_thread::interruption_point(); |
| 5636 | uiInterface.ShowProgress(_("Verifying blocks..."), std::max(1, std::min(99, (int)(((double)(chainActive.Height() - pindex->nHeight)) / (double)nCheckDepth * (nCheckLevel >= 4 ? 50 : 100))))); |
| 5637 | if (pindex->nHeight < chainActive.Height() - nCheckDepth) |
| 5638 | break; |
| 5639 | CBlock block; |
| 5640 | // check level 0: read from disk |
| 5641 | if (!ReadBlockFromDisk(block, pindex, chainparams.GetConsensus())) |
| 5642 | return error("VerifyDB() : *** ReadBlockFromDisk failed at %d, hash=%s", pindex->nHeight, pindex->GetBlockHash().ToString()); |
| 5643 | // check level 1: verify block validity |
| 5644 | if (nCheckLevel >= 1 && !CheckBlock(block, state, chainparams.GetConsensus())) |
| 5645 | return error("%s: *** found bad block at %d, hash=%s (%s)\n", __func__, pindex->nHeight, pindex->GetBlockHash().ToString(), FormatStateMessage(state)); |
| 5646 | // check level 2: verify undo validity |
| 5647 | if (nCheckLevel >= 2 && pindex) { |
| 5648 | CBlockUndo undo; |
| 5649 | CDiskBlockPos pos = pindex->GetUndoPos(); |
| 5650 | if (!pos.IsNull()) { |
| 5651 | if (!UndoReadFromDisk(undo, pos, pindex->pprev->GetBlockHash())) |
| 5652 | return error("VerifyDB: *** found bad undo data at %d, hash=%s\n", pindex->nHeight, pindex->GetBlockHash().GetHex()); |
| 5653 | } |
| 5654 | } |
| 5655 | if ((coins.DynamicMemoryUsage() + pcoinsTip->DynamicMemoryUsage()) > nCoinCacheUsage) { |
| 5656 | LogPrintf("%s: WARNING nCoinCache reached (%zu > %zu), please increase -dbcache\n", __func__, |
| 5657 | (coins.DynamicMemoryUsage() + pcoinsTip->DynamicMemoryUsage()), nCoinCacheUsage); |
| 5658 | } |
| 5659 | // check level 3: check for inconsistencies during memory-only disconnect of tip blocks |
| 5660 | if (nCheckLevel >= 3) { |
| 5661 | bool fClean = true; |
| 5662 | DisconnectResult res = DisconnectBlock(block, state, pindex, coins, &fClean); |
| 5663 | if (res == DISCONNECT_FAILED) { |
| 5664 | return error("VerifyDB: *** irrecoverable inconsistency in block data at %d, hash=%s", |
| 5665 | pindex->nHeight, pindex->GetBlockHash().ToString()); |
| 5666 | } |
| 5667 | if (res == DISCONNECT_UNCLEAN) { |
| 5668 | nGoodTransactions = 0; |
| 5669 | pindexFailure = pindex; |
| 5670 | } else |
no test coverage detected