| 4300 | } |
| 4301 | |
| 4302 | bool CVerifyDB::VerifyDB( |
| 4303 | CChainState& chainstate, |
| 4304 | const Consensus::Params& consensus_params, |
| 4305 | CCoinsView& coinsview, |
| 4306 | int nCheckLevel, int nCheckDepth) |
| 4307 | { |
| 4308 | AssertLockHeld(cs_main); |
| 4309 | |
| 4310 | if (chainstate.m_chain.Tip() == nullptr || chainstate.m_chain.Tip()->pprev == nullptr) { |
| 4311 | return true; |
| 4312 | } |
| 4313 | |
| 4314 | // Verify blocks in the best chain |
| 4315 | if (nCheckDepth <= 0 || nCheckDepth > chainstate.m_chain.Height()) { |
| 4316 | nCheckDepth = chainstate.m_chain.Height(); |
| 4317 | } |
| 4318 | nCheckLevel = std::max(0, std::min(4, nCheckLevel)); |
| 4319 | LogPrintf("Verifying last %i blocks at level %i\n", nCheckDepth, nCheckLevel); |
| 4320 | CCoinsViewCache coins(&coinsview); |
| 4321 | CBlockIndex* pindex; |
| 4322 | CBlockIndex* pindexFailure = nullptr; |
| 4323 | int nGoodTransactions = 0; |
| 4324 | BlockValidationState state; |
| 4325 | int reportDone = 0; |
| 4326 | LogPrintf("[0%%]..."); /* Continued */ |
| 4327 | |
| 4328 | const bool is_snapshot_cs{!chainstate.m_from_snapshot_blockhash}; |
| 4329 | |
| 4330 | for (pindex = chainstate.m_chain.Tip(); pindex && pindex->pprev; pindex = pindex->pprev) { |
| 4331 | const int percentageDone = std::max(1, std::min(99, (int)(((double)(chainstate.m_chain.Height() - pindex->nHeight)) / (double)nCheckDepth * (nCheckLevel >= 4 ? 50 : 100)))); |
| 4332 | if (reportDone < percentageDone / 10) { |
| 4333 | // report every 10% step |
| 4334 | LogPrintf("[%d%%]...", percentageDone); /* Continued */ |
| 4335 | reportDone = percentageDone / 10; |
| 4336 | } |
| 4337 | uiInterface.ShowProgress(_("Verifying blocks…").translated, percentageDone, false); |
| 4338 | if (pindex->nHeight <= chainstate.m_chain.Height() - nCheckDepth) { |
| 4339 | break; |
| 4340 | } |
| 4341 | if ((fPruneMode || is_snapshot_cs) && !(pindex->nStatus & BLOCK_HAVE_DATA)) { |
| 4342 | // If pruning or running under an assumeutxo snapshot, only go |
| 4343 | // back as far as we have data. |
| 4344 | LogPrintf("VerifyDB(): block verification stopping at height %d (pruning, no data)\n", pindex->nHeight); |
| 4345 | break; |
| 4346 | } |
| 4347 | CBlock block; |
| 4348 | // check level 0: read from disk |
| 4349 | if (!ReadBlockFromDisk(block, pindex, consensus_params)) { |
| 4350 | return error("VerifyDB(): *** ReadBlockFromDisk failed at %d, hash=%s", pindex->nHeight, pindex->GetBlockHash().ToString()); |
| 4351 | } |
| 4352 | // check level 1: verify block validity |
| 4353 | if (nCheckLevel >= 1 && !CheckBlock(block, state, consensus_params)) { |
| 4354 | return error("%s: *** found bad block at %d, hash=%s (%s)\n", __func__, |
| 4355 | pindex->nHeight, pindex->GetBlockHash().ToString(), state.ToString()); |
| 4356 | } |
| 4357 | // check level 2: verify undo validity |
| 4358 | if (nCheckLevel >= 2 && pindex) { |
| 4359 | CBlockUndo undo; |
no test coverage detected