Skip to content

Commit c6d6bc8

Browse files
author
MarcoFalke
committed
Merge bitcoin#21523: validation: run VerifyDB on all chainstates
844ad0e doc: IsSnapshotActive (James O'Beirne) 9b604c0 validation: prepare VerifyDB for assumeutxo (James O'Beirne) 7901647 refactor: rename active_chainstate in VerifyDB (James O'Beirne) Pull request description: This is part of the [assumeutxo project](https://github.com/bitcoin/bitcoin/projects/11) (parent PR: bitcoin#15606) --- ~~Pretty cut and dry; parameterizes `CVerifyDB` methods so that we can run the verify procedure on multiple chainstates.~~ Two minor tweaks to ensure that `VerifyDB` can be run on multiple chainstates and a corresponding rename. ACKs for top commit: fjahr: Code review re-ACK 844ad0e MarcoFalke: review ACK 844ad0e 🐥 Tree-SHA512: 26a398cf4dabc1aa0850743921dba0452b4813848a3c777586dc981716737e98e17b8110254a5c41af95dd236e0c00dc8b4eee891d69bef825a5e1911fc499d0
2 parents ac219dc + 844ad0e commit c6d6bc8

File tree

4 files changed

+41
-26
lines changed

4 files changed

+41
-26
lines changed

src/init.cpp

Lines changed: 2 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1525,11 +1525,8 @@ bool AppInitMain(NodeContext& node, interfaces::BlockAndHeaderTipInfo* tip_info)
15251525
break;
15261526
}
15271527

1528-
// Only verify the DB of the active chainstate. This is fixed in later
1529-
// work when we allow VerifyDB to be parameterized by chainstate.
1530-
if (&::ChainstateActive() == chainstate &&
1531-
!CVerifyDB().VerifyDB(
1532-
chainparams, *chainstate, &chainstate->CoinsDB(),
1528+
if (!CVerifyDB().VerifyDB(
1529+
*chainstate, chainparams, chainstate->CoinsDB(),
15331530
args.GetArg("-checklevel", DEFAULT_CHECKLEVEL),
15341531
args.GetArg("-checkblocks", DEFAULT_CHECKBLOCKS))) {
15351532
strLoadError = _("Corrupted block database detected");

src/rpc/blockchain.cpp

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1239,7 +1239,8 @@ static RPCHelpMan verifychain()
12391239
LOCK(cs_main);
12401240

12411241
CChainState& active_chainstate = chainman.ActiveChainstate();
1242-
return CVerifyDB().VerifyDB(Params(), active_chainstate, &active_chainstate.CoinsTip(), check_level, check_depth);
1242+
return CVerifyDB().VerifyDB(
1243+
active_chainstate, Params(), active_chainstate.CoinsTip(), check_level, check_depth);
12431244
},
12441245
};
12451246
}

src/validation.cpp

Lines changed: 29 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -4101,38 +4101,46 @@ CVerifyDB::~CVerifyDB()
41014101
uiInterface.ShowProgress("", 100, false);
41024102
}
41034103

4104-
bool CVerifyDB::VerifyDB(const CChainParams& chainparams, CChainState& active_chainstate, CCoinsView *coinsview, int nCheckLevel, int nCheckDepth)
4104+
bool CVerifyDB::VerifyDB(
4105+
CChainState& chainstate,
4106+
const CChainParams& chainparams,
4107+
CCoinsView& coinsview,
4108+
int nCheckLevel, int nCheckDepth)
41054109
{
41064110
AssertLockHeld(cs_main);
41074111

4108-
assert(std::addressof(::ChainstateActive()) == std::addressof(active_chainstate));
4109-
if (active_chainstate.m_chain.Tip() == nullptr || active_chainstate.m_chain.Tip()->pprev == nullptr)
4112+
assert(std::addressof(::ChainstateActive()) == std::addressof(chainstate));
4113+
if (chainstate.m_chain.Tip() == nullptr || chainstate.m_chain.Tip()->pprev == nullptr)
41104114
return true;
41114115

41124116
// Verify blocks in the best chain
4113-
if (nCheckDepth <= 0 || nCheckDepth > active_chainstate.m_chain.Height())
4114-
nCheckDepth = active_chainstate.m_chain.Height();
4117+
if (nCheckDepth <= 0 || nCheckDepth > chainstate.m_chain.Height())
4118+
nCheckDepth = chainstate.m_chain.Height();
41154119
nCheckLevel = std::max(0, std::min(4, nCheckLevel));
41164120
LogPrintf("Verifying last %i blocks at level %i\n", nCheckDepth, nCheckLevel);
4117-
CCoinsViewCache coins(coinsview);
4121+
CCoinsViewCache coins(&coinsview);
41184122
CBlockIndex* pindex;
41194123
CBlockIndex* pindexFailure = nullptr;
41204124
int nGoodTransactions = 0;
41214125
BlockValidationState state;
41224126
int reportDone = 0;
41234127
LogPrintf("[0%%]..."); /* Continued */
4124-
for (pindex = active_chainstate.m_chain.Tip(); pindex && pindex->pprev; pindex = pindex->pprev) {
4125-
const int percentageDone = std::max(1, std::min(99, (int)(((double)(active_chainstate.m_chain.Height() - pindex->nHeight)) / (double)nCheckDepth * (nCheckLevel >= 4 ? 50 : 100))));
4128+
4129+
bool is_snapshot_cs = !chainstate.m_from_snapshot_blockhash.IsNull();
4130+
4131+
for (pindex = chainstate.m_chain.Tip(); pindex && pindex->pprev; pindex = pindex->pprev) {
4132+
const int percentageDone = std::max(1, std::min(99, (int)(((double)(chainstate.m_chain.Height() - pindex->nHeight)) / (double)nCheckDepth * (nCheckLevel >= 4 ? 50 : 100))));
41264133
if (reportDone < percentageDone/10) {
41274134
// report every 10% step
41284135
LogPrintf("[%d%%]...", percentageDone); /* Continued */
41294136
reportDone = percentageDone/10;
41304137
}
41314138
uiInterface.ShowProgress(_("Verifying blocks...").translated, percentageDone, false);
4132-
if (pindex->nHeight <= active_chainstate.m_chain.Height()-nCheckDepth)
4139+
if (pindex->nHeight <= chainstate.m_chain.Height()-nCheckDepth)
41334140
break;
4134-
if (fPruneMode && !(pindex->nStatus & BLOCK_HAVE_DATA)) {
4135-
// If pruning, only go back as far as we have data.
4141+
if ((fPruneMode || is_snapshot_cs) && !(pindex->nStatus & BLOCK_HAVE_DATA)) {
4142+
// If pruning or running under an assumeutxo snapshot, only go
4143+
// back as far as we have data.
41364144
LogPrintf("VerifyDB(): block verification stopping at height %d (pruning, no data)\n", pindex->nHeight);
41374145
break;
41384146
}
@@ -4154,9 +4162,11 @@ bool CVerifyDB::VerifyDB(const CChainParams& chainparams, CChainState& active_ch
41544162
}
41554163
}
41564164
// check level 3: check for inconsistencies during memory-only disconnect of tip blocks
4157-
if (nCheckLevel >= 3 && (coins.DynamicMemoryUsage() + active_chainstate.CoinsTip().DynamicMemoryUsage()) <= active_chainstate.m_coinstip_cache_size_bytes) {
4165+
size_t curr_coins_usage = coins.DynamicMemoryUsage() + chainstate.CoinsTip().DynamicMemoryUsage();
4166+
4167+
if (nCheckLevel >= 3 && curr_coins_usage <= chainstate.m_coinstip_cache_size_bytes) {
41584168
assert(coins.GetBestBlock() == pindex->GetBlockHash());
4159-
DisconnectResult res = active_chainstate.DisconnectBlock(block, pindex, coins);
4169+
DisconnectResult res = chainstate.DisconnectBlock(block, pindex, coins);
41604170
if (res == DISCONNECT_FAILED) {
41614171
return error("VerifyDB(): *** irrecoverable inconsistency in block data at %d, hash=%s", pindex->nHeight, pindex->GetBlockHash().ToString());
41624172
}
@@ -4170,26 +4180,26 @@ bool CVerifyDB::VerifyDB(const CChainParams& chainparams, CChainState& active_ch
41704180
if (ShutdownRequested()) return true;
41714181
}
41724182
if (pindexFailure)
4173-
return error("VerifyDB(): *** coin database inconsistencies found (last %i blocks, %i good transactions before that)\n", active_chainstate.m_chain.Height() - pindexFailure->nHeight + 1, nGoodTransactions);
4183+
return error("VerifyDB(): *** coin database inconsistencies found (last %i blocks, %i good transactions before that)\n", chainstate.m_chain.Height() - pindexFailure->nHeight + 1, nGoodTransactions);
41744184

41754185
// store block count as we move pindex at check level >= 4
4176-
int block_count = active_chainstate.m_chain.Height() - pindex->nHeight;
4186+
int block_count = chainstate.m_chain.Height() - pindex->nHeight;
41774187

41784188
// check level 4: try reconnecting blocks
41794189
if (nCheckLevel >= 4) {
4180-
while (pindex != active_chainstate.m_chain.Tip()) {
4181-
const int percentageDone = std::max(1, std::min(99, 100 - (int)(((double)(active_chainstate.m_chain.Height() - pindex->nHeight)) / (double)nCheckDepth * 50)));
4190+
while (pindex != chainstate.m_chain.Tip()) {
4191+
const int percentageDone = std::max(1, std::min(99, 100 - (int)(((double)(chainstate.m_chain.Height() - pindex->nHeight)) / (double)nCheckDepth * 50)));
41824192
if (reportDone < percentageDone/10) {
41834193
// report every 10% step
41844194
LogPrintf("[%d%%]...", percentageDone); /* Continued */
41854195
reportDone = percentageDone/10;
41864196
}
41874197
uiInterface.ShowProgress(_("Verifying blocks...").translated, percentageDone, false);
4188-
pindex = active_chainstate.m_chain.Next(pindex);
4198+
pindex = chainstate.m_chain.Next(pindex);
41894199
CBlock block;
41904200
if (!ReadBlockFromDisk(block, pindex, chainparams.GetConsensus()))
41914201
return error("VerifyDB(): *** ReadBlockFromDisk failed at %d, hash=%s", pindex->nHeight, pindex->GetBlockHash().ToString());
4192-
if (!active_chainstate.ConnectBlock(block, state, pindex, coins, chainparams))
4202+
if (!chainstate.ConnectBlock(block, state, pindex, coins, chainparams))
41934203
return error("VerifyDB(): *** found unconnectable block at %d, hash=%s (%s)", pindex->nHeight, pindex->GetBlockHash().ToString(), state.ToString());
41944204
if (ShutdownRequested()) return true;
41954205
}

src/validation.h

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -329,7 +329,12 @@ class CVerifyDB {
329329
public:
330330
CVerifyDB();
331331
~CVerifyDB();
332-
bool VerifyDB(const CChainParams& chainparams, CChainState& active_chainstate, CCoinsView *coinsview, int nCheckLevel, int nCheckDepth) EXCLUSIVE_LOCKS_REQUIRED(cs_main);
332+
bool VerifyDB(
333+
CChainState& chainstate,
334+
const CChainParams& chainparams,
335+
CCoinsView& coinsview,
336+
int nCheckLevel,
337+
int nCheckDepth) EXCLUSIVE_LOCKS_REQUIRED(cs_main);
333338
};
334339

335340
enum DisconnectResult
@@ -913,6 +918,8 @@ class ChainstateManager
913918
return m_blockman.m_block_index;
914919
}
915920

921+
//! @returns true if a snapshot-based chainstate is in use. Also implies
922+
//! that a background validation chainstate is also in use.
916923
bool IsSnapshotActive() const;
917924

918925
std::optional<uint256> SnapshotBlockhash() const;

0 commit comments

Comments
 (0)