0
0
Fork 0
mirror of https://github.com/bitcoin/bitcoin.git synced 2025-02-01 09:35:52 -05:00

Compare commits

...

2 commits

Author SHA1 Message Date
Pieter Wuille
05cb0fd765
Merge 1ede4803f1 into 8fa10edcd1 2025-01-31 02:38:11 +01:00
Pieter Wuille
1ede4803f1 validation: do not wipe utxo cache for stats/scans/snapshots 2024-08-16 15:19:47 -04:00
8 changed files with 26 additions and 24 deletions

View file

@ -261,7 +261,7 @@ epilogue:
LOCK(cs_main);
for (Chainstate* chainstate : chainman.GetAll()) {
if (chainstate->CanFlushToDisk()) {
chainstate->ForceFlushStateToDisk();
chainstate->ForceFlushStateToDisk(/*wipe_cache=*/true);
chainstate->ResetCoinsViews();
}
}

View file

@ -341,7 +341,7 @@ void Shutdown(NodeContext& node)
LOCK(cs_main);
for (Chainstate* chainstate : node.chainman->GetAll()) {
if (chainstate->CanFlushToDisk()) {
chainstate->ForceFlushStateToDisk();
chainstate->ForceFlushStateToDisk(/*wipe_cache=*/true);
}
}
}
@ -367,7 +367,7 @@ void Shutdown(NodeContext& node)
LOCK(cs_main);
for (Chainstate* chainstate : node.chainman->GetAll()) {
if (chainstate->CanFlushToDisk()) {
chainstate->ForceFlushStateToDisk();
chainstate->ForceFlushStateToDisk(/*wipe_cache=*/true);
chainstate->ResetCoinsViews();
}
}

View file

@ -1000,7 +1000,7 @@ static RPCHelpMan gettxoutsetinfo()
NodeContext& node = EnsureAnyNodeContext(request.context);
ChainstateManager& chainman = EnsureChainman(node);
Chainstate& active_chainstate = chainman.ActiveChainstate();
active_chainstate.ForceFlushStateToDisk();
active_chainstate.ForceFlushStateToDisk(/*wipe_cache=*/false);
CCoinsView* coins_view;
BlockManager* blockman;
@ -2319,7 +2319,7 @@ static RPCHelpMan scantxoutset()
ChainstateManager& chainman = EnsureChainman(node);
LOCK(cs_main);
Chainstate& active_chainstate = chainman.ActiveChainstate();
active_chainstate.ForceFlushStateToDisk();
active_chainstate.ForceFlushStateToDisk(/*wipe_cache=*/false);
pcursor = CHECK_NONFATAL(active_chainstate.CoinsDB().Cursor());
tip = CHECK_NONFATAL(active_chainstate.m_chain.Tip());
}
@ -3123,7 +3123,7 @@ PrepareUTXOSnapshot(
//
AssertLockHeld(::cs_main);
chainstate.ForceFlushStateToDisk();
chainstate.ForceFlushStateToDisk(/*wipe_cache=*/false);
maybe_stats = GetUTXOStats(&chainstate.CoinsDB(), chainstate.m_blockman, CoinStatsHashType::HASH_SERIALIZED, interruption_point);
if (!maybe_stats) {

View file

@ -87,9 +87,9 @@ FUZZ_TARGET(utxo_total_supply)
tx.vin.emplace_back(txo.first);
tx.vout.emplace_back(txo.second.nValue, txo.second.scriptPubKey); // "Forward" coin with no fee
};
const auto UpdateUtxoStats = [&]() {
const auto UpdateUtxoStats = [&](bool wipe_cache) {
LOCK(chainman.GetMutex());
chainman.ActiveChainstate().ForceFlushStateToDisk();
chainman.ActiveChainstate().ForceFlushStateToDisk(/*wipe_cache=*/wipe_cache);
utxo_stats = std::move(
*Assert(kernel::ComputeUTXOStats(kernel::CoinStatsHashType::NONE, &chainman.ActiveChainstate().CoinsDB(), chainman.m_blockman, {})));
// Check that miner can't print more money than they are allowed to
@ -99,7 +99,7 @@ FUZZ_TARGET(utxo_total_supply)
// Update internal state to chain tip
StoreLastTxo();
UpdateUtxoStats();
UpdateUtxoStats(/*wipe_cache=*/fuzzed_data_provider.ConsumeBool());
assert(ActiveHeight() == 0);
// Get at which height we duplicate the coinbase
// Assuming that the fuzzer will mine relatively short chains (less than 200 blocks), we want the duplicate coinbase to be not too high.
@ -124,7 +124,7 @@ FUZZ_TARGET(utxo_total_supply)
circulation += GetBlockSubsidy(ActiveHeight(), Params().GetConsensus());
assert(ActiveHeight() == 1);
UpdateUtxoStats();
UpdateUtxoStats(/*wipe_cache=*/fuzzed_data_provider.ConsumeBool());
current_block = PrepareNextBlock();
StoreLastTxo();
@ -163,7 +163,7 @@ FUZZ_TARGET(utxo_total_supply)
circulation += GetBlockSubsidy(ActiveHeight(), Params().GetConsensus());
}
UpdateUtxoStats();
UpdateUtxoStats(/*wipe_cache=*/fuzzed_data_provider.ConsumeBool());
if (!was_valid) {
// utxo stats must not change

View file

@ -375,7 +375,7 @@ struct SnapshotTestSetup : TestChain100Setup {
{
for (Chainstate* cs : chainman.GetAll()) {
LOCK(::cs_main);
cs->ForceFlushStateToDisk();
cs->ForceFlushStateToDisk(/*wipe_cache=*/true);
}
// Process all callbacks referring to the old manager before wiping it.
m_node.validation_signals->SyncWithValidationInterfaceQueue();

View file

@ -2895,7 +2895,7 @@ bool Chainstate::FlushStateToDisk(
// It's been very long since we flushed the cache. Do this infrequently, to optimize cache usage.
bool fPeriodicFlush = mode == FlushStateMode::PERIODIC && nNow > m_last_flush + DATABASE_FLUSH_INTERVAL;
// Combine all conditions that result in a full cache flush.
fDoFullFlush = (mode == FlushStateMode::ALWAYS) || fCacheLarge || fCacheCritical || fPeriodicFlush || fFlushForPrune;
fDoFullFlush = (mode == FlushStateMode::FORCE_FLUSH) || (mode == FlushStateMode::FORCE_SYNC) || fCacheLarge || fCacheCritical || fPeriodicFlush || fFlushForPrune;
// Write blocks and block index to disk.
if (fDoFullFlush || fPeriodicWrite) {
// Ensure we can write block index
@ -2944,7 +2944,7 @@ bool Chainstate::FlushStateToDisk(
return FatalError(m_chainman.GetNotifications(), state, _("Disk space is too low!"));
}
// Flush the chainstate (which may refer to block index entries).
const auto empty_cache{(mode == FlushStateMode::ALWAYS) || fCacheLarge || fCacheCritical};
const auto empty_cache{(mode == FlushStateMode::FORCE_FLUSH) || fCacheLarge || fCacheCritical};
if (empty_cache ? !CoinsTip().Flush() : !CoinsTip().Sync()) {
return FatalError(m_chainman.GetNotifications(), state, _("Failed to write to coin database."));
}
@ -2968,10 +2968,10 @@ bool Chainstate::FlushStateToDisk(
return true;
}
void Chainstate::ForceFlushStateToDisk()
void Chainstate::ForceFlushStateToDisk(bool wipe_cache)
{
BlockValidationState state;
if (!this->FlushStateToDisk(state, FlushStateMode::ALWAYS)) {
if (!this->FlushStateToDisk(state, wipe_cache ? FlushStateMode::FORCE_FLUSH : FlushStateMode::FORCE_SYNC)) {
LogPrintf("%s: failed to flush state (%s)\n", __func__, state.ToString());
}
}
@ -5609,7 +5609,7 @@ bool Chainstate::ResizeCoinsCaches(size_t coinstip_size, size_t coinsdb_size)
ret = FlushStateToDisk(state, FlushStateMode::IF_NEEDED);
} else {
// Otherwise, flush state to disk and deallocate the in-memory coins map.
ret = FlushStateToDisk(state, FlushStateMode::ALWAYS);
ret = FlushStateToDisk(state, FlushStateMode::FORCE_FLUSH);
}
return ret;
}
@ -6081,7 +6081,7 @@ util::Result<void> ChainstateManager::PopulateAndValidateSnapshot(
// returns in `ActivateSnapshot()`, when `MaybeRebalanceCaches()` is
// called, since we've added a snapshot chainstate and therefore will
// have to downsize the IBD chainstate, which will result in a call to
// `FlushStateToDisk(ALWAYS)`.
// `FlushStateToDisk(FORCE_FLUSH)`.
}
assert(index);
@ -6181,7 +6181,7 @@ SnapshotCompletionResult ChainstateManager::MaybeCompleteSnapshotValidation()
assert(this->GetAll().size() == 2);
CCoinsViewDB& ibd_coins_db = m_ibd_chainstate->CoinsDB();
m_ibd_chainstate->ForceFlushStateToDisk();
m_ibd_chainstate->ForceFlushStateToDisk(/*wipe_cache=*/true);
const auto& maybe_au_data = m_options.chainparams.AssumeutxoForHeight(curr_height);
if (!maybe_au_data) {

View file

@ -440,7 +440,8 @@ enum class FlushStateMode {
NONE,
IF_NEEDED,
PERIODIC,
ALWAYS
FORCE_SYNC,
FORCE_FLUSH,
};
/**
@ -670,7 +671,7 @@ public:
int nManualPruneHeight = 0);
//! Unconditionally flush all changes to disk.
void ForceFlushStateToDisk();
void ForceFlushStateToDisk(bool wipe_cache);
//! Prune blockfiles from the disk if necessary and then flush chainstate changes
//! if we pruned.

View file

@ -100,7 +100,8 @@ FLUSHMODE_NAME = {
0: "NONE",
1: "IF_NEEDED",
2: "PERIODIC",
3: "ALWAYS",
3: "FORCE_SYNC",
4: "FORCE_FLUSH",
}
@ -368,8 +369,8 @@ class UTXOCacheTracepointTest(BitcoinTestFramework):
# A node shutdown causes two flushes. One that flushes UTXOS_IN_CACHE
# UTXOs and one that flushes 0 UTXOs. Normally the 0-UTXO-flush is the
# second flush, however it can happen that the order changes.
expected_flushes.append({"mode": "ALWAYS", "for_prune": False, "size": UTXOS_IN_CACHE})
expected_flushes.append({"mode": "ALWAYS", "for_prune": False, "size": 0})
expected_flushes.append({"mode": "FORCE_FLUSH", "for_prune": False, "size": UTXOS_IN_CACHE})
expected_flushes.append({"mode": "FORCE_FLUSH", "for_prune": False, "size": 0})
self.stop_node(0)
bpf.perf_buffer_poll(timeout=200)