aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorMarcoFalke <falke.marco@gmail.com>2021-04-27 13:30:04 +0200
committerMarcoFalke <falke.marco@gmail.com>2021-04-27 13:31:29 +0200
commitc6d6bc8abb721be68a3d2cdba11ceb5e9814c9b1 (patch)
tree06fd5a252041c4e8044c4098cffa51334cda4b36 /src
parentac219dcbcc18a48210d58cdfaf7cf27ca5e7435b (diff)
parent844ad0eccaa1dbfefc30d19804d95d67c3d5f06d (diff)
Merge bitcoin/bitcoin#21523: validation: run VerifyDB on all chainstates
844ad0eccaa1dbfefc30d19804d95d67c3d5f06d doc: IsSnapshotActive (James O'Beirne) 9b604c0207b526c008617cdca210f35db5e344db validation: prepare VerifyDB for assumeutxo (James O'Beirne) 7901647d722bcc5b0554ad73b14481cbe73608e4 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: #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 844ad0eccaa1dbfefc30d19804d95d67c3d5f06d MarcoFalke: review ACK 844ad0eccaa1dbfefc30d19804d95d67c3d5f06d 🐥 Tree-SHA512: 26a398cf4dabc1aa0850743921dba0452b4813848a3c777586dc981716737e98e17b8110254a5c41af95dd236e0c00dc8b4eee891d69bef825a5e1911fc499d0
Diffstat (limited to 'src')
-rw-r--r--src/init.cpp7
-rw-r--r--src/rpc/blockchain.cpp3
-rw-r--r--src/validation.cpp48
-rw-r--r--src/validation.h9
4 files changed, 41 insertions, 26 deletions
diff --git a/src/init.cpp b/src/init.cpp
index 24d67f48dc..3f9838f2e0 100644
--- a/src/init.cpp
+++ b/src/init.cpp
@@ -1525,11 +1525,8 @@ bool AppInitMain(NodeContext& node, interfaces::BlockAndHeaderTipInfo* tip_info)
break;
}
- // Only verify the DB of the active chainstate. This is fixed in later
- // work when we allow VerifyDB to be parameterized by chainstate.
- if (&::ChainstateActive() == chainstate &&
- !CVerifyDB().VerifyDB(
- chainparams, *chainstate, &chainstate->CoinsDB(),
+ if (!CVerifyDB().VerifyDB(
+ *chainstate, chainparams, chainstate->CoinsDB(),
args.GetArg("-checklevel", DEFAULT_CHECKLEVEL),
args.GetArg("-checkblocks", DEFAULT_CHECKBLOCKS))) {
strLoadError = _("Corrupted block database detected");
diff --git a/src/rpc/blockchain.cpp b/src/rpc/blockchain.cpp
index e7fd97ee1f..d36814716b 100644
--- a/src/rpc/blockchain.cpp
+++ b/src/rpc/blockchain.cpp
@@ -1239,7 +1239,8 @@ static RPCHelpMan verifychain()
LOCK(cs_main);
CChainState& active_chainstate = chainman.ActiveChainstate();
- return CVerifyDB().VerifyDB(Params(), active_chainstate, &active_chainstate.CoinsTip(), check_level, check_depth);
+ return CVerifyDB().VerifyDB(
+ active_chainstate, Params(), active_chainstate.CoinsTip(), check_level, check_depth);
},
};
}
diff --git a/src/validation.cpp b/src/validation.cpp
index 09b7bb4398..1ddafa5613 100644
--- a/src/validation.cpp
+++ b/src/validation.cpp
@@ -4101,38 +4101,46 @@ CVerifyDB::~CVerifyDB()
uiInterface.ShowProgress("", 100, false);
}
-bool CVerifyDB::VerifyDB(const CChainParams& chainparams, CChainState& active_chainstate, CCoinsView *coinsview, int nCheckLevel, int nCheckDepth)
+bool CVerifyDB::VerifyDB(
+ CChainState& chainstate,
+ const CChainParams& chainparams,
+ CCoinsView& coinsview,
+ int nCheckLevel, int nCheckDepth)
{
AssertLockHeld(cs_main);
- assert(std::addressof(::ChainstateActive()) == std::addressof(active_chainstate));
- if (active_chainstate.m_chain.Tip() == nullptr || active_chainstate.m_chain.Tip()->pprev == nullptr)
+ assert(std::addressof(::ChainstateActive()) == std::addressof(chainstate));
+ if (chainstate.m_chain.Tip() == nullptr || chainstate.m_chain.Tip()->pprev == nullptr)
return true;
// Verify blocks in the best chain
- if (nCheckDepth <= 0 || nCheckDepth > active_chainstate.m_chain.Height())
- nCheckDepth = active_chainstate.m_chain.Height();
+ if (nCheckDepth <= 0 || nCheckDepth > chainstate.m_chain.Height())
+ nCheckDepth = chainstate.m_chain.Height();
nCheckLevel = std::max(0, std::min(4, nCheckLevel));
LogPrintf("Verifying last %i blocks at level %i\n", nCheckDepth, nCheckLevel);
- CCoinsViewCache coins(coinsview);
+ CCoinsViewCache coins(&coinsview);
CBlockIndex* pindex;
CBlockIndex* pindexFailure = nullptr;
int nGoodTransactions = 0;
BlockValidationState state;
int reportDone = 0;
LogPrintf("[0%%]..."); /* Continued */
- for (pindex = active_chainstate.m_chain.Tip(); pindex && pindex->pprev; pindex = pindex->pprev) {
- const int percentageDone = std::max(1, std::min(99, (int)(((double)(active_chainstate.m_chain.Height() - pindex->nHeight)) / (double)nCheckDepth * (nCheckLevel >= 4 ? 50 : 100))));
+
+ bool is_snapshot_cs = !chainstate.m_from_snapshot_blockhash.IsNull();
+
+ for (pindex = chainstate.m_chain.Tip(); pindex && pindex->pprev; pindex = pindex->pprev) {
+ const int percentageDone = std::max(1, std::min(99, (int)(((double)(chainstate.m_chain.Height() - pindex->nHeight)) / (double)nCheckDepth * (nCheckLevel >= 4 ? 50 : 100))));
if (reportDone < percentageDone/10) {
// report every 10% step
LogPrintf("[%d%%]...", percentageDone); /* Continued */
reportDone = percentageDone/10;
}
uiInterface.ShowProgress(_("Verifying blocks...").translated, percentageDone, false);
- if (pindex->nHeight <= active_chainstate.m_chain.Height()-nCheckDepth)
+ if (pindex->nHeight <= chainstate.m_chain.Height()-nCheckDepth)
break;
- if (fPruneMode && !(pindex->nStatus & BLOCK_HAVE_DATA)) {
- // If pruning, only go back as far as we have data.
+ if ((fPruneMode || is_snapshot_cs) && !(pindex->nStatus & BLOCK_HAVE_DATA)) {
+ // If pruning or running under an assumeutxo snapshot, only go
+ // back as far as we have data.
LogPrintf("VerifyDB(): block verification stopping at height %d (pruning, no data)\n", pindex->nHeight);
break;
}
@@ -4154,9 +4162,11 @@ bool CVerifyDB::VerifyDB(const CChainParams& chainparams, CChainState& active_ch
}
}
// check level 3: check for inconsistencies during memory-only disconnect of tip blocks
- if (nCheckLevel >= 3 && (coins.DynamicMemoryUsage() + active_chainstate.CoinsTip().DynamicMemoryUsage()) <= active_chainstate.m_coinstip_cache_size_bytes) {
+ size_t curr_coins_usage = coins.DynamicMemoryUsage() + chainstate.CoinsTip().DynamicMemoryUsage();
+
+ if (nCheckLevel >= 3 && curr_coins_usage <= chainstate.m_coinstip_cache_size_bytes) {
assert(coins.GetBestBlock() == pindex->GetBlockHash());
- DisconnectResult res = active_chainstate.DisconnectBlock(block, pindex, coins);
+ DisconnectResult res = chainstate.DisconnectBlock(block, pindex, coins);
if (res == DISCONNECT_FAILED) {
return error("VerifyDB(): *** irrecoverable inconsistency in block data at %d, hash=%s", pindex->nHeight, pindex->GetBlockHash().ToString());
}
@@ -4170,26 +4180,26 @@ bool CVerifyDB::VerifyDB(const CChainParams& chainparams, CChainState& active_ch
if (ShutdownRequested()) return true;
}
if (pindexFailure)
- 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);
+ return error("VerifyDB(): *** coin database inconsistencies found (last %i blocks, %i good transactions before that)\n", chainstate.m_chain.Height() - pindexFailure->nHeight + 1, nGoodTransactions);
// store block count as we move pindex at check level >= 4
- int block_count = active_chainstate.m_chain.Height() - pindex->nHeight;
+ int block_count = chainstate.m_chain.Height() - pindex->nHeight;
// check level 4: try reconnecting blocks
if (nCheckLevel >= 4) {
- while (pindex != active_chainstate.m_chain.Tip()) {
- const int percentageDone = std::max(1, std::min(99, 100 - (int)(((double)(active_chainstate.m_chain.Height() - pindex->nHeight)) / (double)nCheckDepth * 50)));
+ while (pindex != chainstate.m_chain.Tip()) {
+ const int percentageDone = std::max(1, std::min(99, 100 - (int)(((double)(chainstate.m_chain.Height() - pindex->nHeight)) / (double)nCheckDepth * 50)));
if (reportDone < percentageDone/10) {
// report every 10% step
LogPrintf("[%d%%]...", percentageDone); /* Continued */
reportDone = percentageDone/10;
}
uiInterface.ShowProgress(_("Verifying blocks...").translated, percentageDone, false);
- pindex = active_chainstate.m_chain.Next(pindex);
+ pindex = chainstate.m_chain.Next(pindex);
CBlock block;
if (!ReadBlockFromDisk(block, pindex, chainparams.GetConsensus()))
return error("VerifyDB(): *** ReadBlockFromDisk failed at %d, hash=%s", pindex->nHeight, pindex->GetBlockHash().ToString());
- if (!active_chainstate.ConnectBlock(block, state, pindex, coins, chainparams))
+ if (!chainstate.ConnectBlock(block, state, pindex, coins, chainparams))
return error("VerifyDB(): *** found unconnectable block at %d, hash=%s (%s)", pindex->nHeight, pindex->GetBlockHash().ToString(), state.ToString());
if (ShutdownRequested()) return true;
}
diff --git a/src/validation.h b/src/validation.h
index 9ae2838ead..a5e6892aa9 100644
--- a/src/validation.h
+++ b/src/validation.h
@@ -329,7 +329,12 @@ class CVerifyDB {
public:
CVerifyDB();
~CVerifyDB();
- bool VerifyDB(const CChainParams& chainparams, CChainState& active_chainstate, CCoinsView *coinsview, int nCheckLevel, int nCheckDepth) EXCLUSIVE_LOCKS_REQUIRED(cs_main);
+ bool VerifyDB(
+ CChainState& chainstate,
+ const CChainParams& chainparams,
+ CCoinsView& coinsview,
+ int nCheckLevel,
+ int nCheckDepth) EXCLUSIVE_LOCKS_REQUIRED(cs_main);
};
enum DisconnectResult
@@ -913,6 +918,8 @@ public:
return m_blockman.m_block_index;
}
+ //! @returns true if a snapshot-based chainstate is in use. Also implies
+ //! that a background validation chainstate is also in use.
bool IsSnapshotActive() const;
std::optional<uint256> SnapshotBlockhash() const;