| 3988 | } |
| 3989 | |
| 3990 | bool CVerifyDB::VerifyDB(CCoinsView *coinsview, int nCheckLevel, int nCheckDepth) |
| 3991 | { |
| 3992 | LOCK(cs_main); |
| 3993 | if (chainActive.Tip() == NULL || chainActive.Tip()->pprev == NULL) |
| 3994 | return true; |
| 3995 | |
| 3996 | // Verify blocks in the best chain |
| 3997 | if (nCheckDepth <= 0) |
| 3998 | nCheckDepth = 1000000000; // suffices until the year 19000 |
| 3999 | if (nCheckDepth > chainActive.Height()) |
| 4000 | nCheckDepth = chainActive.Height(); |
| 4001 | nCheckLevel = std::max(0, std::min(4, nCheckLevel)); |
| 4002 | LogPrintf("Verifying last %i blocks at level %i\n", nCheckDepth, nCheckLevel); |
| 4003 | CCoinsViewCache coins(coinsview); |
| 4004 | CBlockIndex* pindexState = chainActive.Tip(); |
| 4005 | CBlockIndex* pindexFailure = NULL; |
| 4006 | int nGoodTransactions = 0; |
| 4007 | CValidationState state; |
| 4008 | for (CBlockIndex* pindex = chainActive.Tip(); pindex && pindex->pprev; pindex = pindex->pprev) |
| 4009 | { |
| 4010 | boost::this_thread::interruption_point(); |
| 4011 | uiInterface.ShowProgress(_("Verifying blocks..."), std::max(1, std::min(99, (int)(((double)(chainActive.Height() - pindex->nHeight)) / (double)nCheckDepth * (nCheckLevel >= 4 ? 50 : 100))))); |
| 4012 | if (pindex->nHeight < chainActive.Height()-nCheckDepth) |
| 4013 | break; |
| 4014 | CBlock block; |
| 4015 | // check level 0: read from disk |
| 4016 | if (!ReadBlockFromDisk(block, pindex)) |
| 4017 | return error("VerifyDB(): *** ReadBlockFromDisk failed at %d, hash=%s", pindex->nHeight, pindex->GetBlockHash().ToString()); |
| 4018 | // check level 1: verify block validity |
| 4019 | if (nCheckLevel >= 1 && !CheckBlock(block, state)) |
| 4020 | return error("VerifyDB(): *** found bad block at %d, hash=%s\n", pindex->nHeight, pindex->GetBlockHash().ToString()); |
| 4021 | // check level 2: verify undo validity |
| 4022 | if (nCheckLevel >= 2 && pindex) { |
| 4023 | CBlockUndo undo; |
| 4024 | CDiskBlockPos pos = pindex->GetUndoPos(); |
| 4025 | if (!pos.IsNull()) { |
| 4026 | if (!UndoReadFromDisk(undo, pos, pindex->pprev->GetBlockHash())) |
| 4027 | return error("VerifyDB(): *** found bad undo data at %d, hash=%s\n", pindex->nHeight, pindex->GetBlockHash().ToString()); |
| 4028 | } |
| 4029 | } |
| 4030 | // check level 3: check for inconsistencies during memory-only disconnect of tip blocks |
| 4031 | if (nCheckLevel >= 3 && pindex == pindexState && (coins.DynamicMemoryUsage() + pcoinsTip->DynamicMemoryUsage()) <= nCoinCacheUsage) { |
| 4032 | bool fClean = true; |
| 4033 | if (!DisconnectBlock(block, state, pindex, coins, &fClean)) |
| 4034 | return error("VerifyDB(): *** irrecoverable inconsistency in block data at %d, hash=%s", pindex->nHeight, pindex->GetBlockHash().ToString()); |
| 4035 | pindexState = pindex->pprev; |
| 4036 | if (!fClean) { |
| 4037 | nGoodTransactions = 0; |
| 4038 | pindexFailure = pindex; |
| 4039 | } else |
| 4040 | nGoodTransactions += block.vtx.size(); |
| 4041 | } |
| 4042 | if (ShutdownRequested()) |
| 4043 | return true; |
| 4044 | } |
| 4045 | if (pindexFailure) |
| 4046 | return error("VerifyDB(): *** coin database inconsistencies found (last %i blocks, %i good transactions before that)\n", chainActive.Height() - pindexFailure->nHeight + 1, nGoodTransactions); |
| 4047 |
no test coverage detected