Changeset View
Changeset View
Standalone View
Standalone View
src/validation.cpp
Show First 20 Lines • Show All 99 Lines • ▼ Show 20 Lines | |||||
uint256 g_best_block; | uint256 g_best_block; | ||||
std::atomic_bool fImporting(false); | std::atomic_bool fImporting(false); | ||||
std::atomic_bool fReindex(false); | std::atomic_bool fReindex(false); | ||||
bool fHavePruned = false; | bool fHavePruned = false; | ||||
bool fPruneMode = false; | bool fPruneMode = false; | ||||
bool fRequireStandard = true; | bool fRequireStandard = true; | ||||
bool fCheckBlockIndex = false; | bool fCheckBlockIndex = false; | ||||
bool fCheckpointsEnabled = DEFAULT_CHECKPOINTS_ENABLED; | bool fCheckpointsEnabled = DEFAULT_CHECKPOINTS_ENABLED; | ||||
size_t nCoinCacheUsage = 5000 * 300; | |||||
uint64_t nPruneTarget = 0; | uint64_t nPruneTarget = 0; | ||||
int64_t nMaxTipAge = DEFAULT_MAX_TIP_AGE; | int64_t nMaxTipAge = DEFAULT_MAX_TIP_AGE; | ||||
BlockHash hashAssumeValid; | BlockHash hashAssumeValid; | ||||
arith_uint256 nMinimumChainWork; | arith_uint256 nMinimumChainWork; | ||||
CFeeRate minRelayTxFee = CFeeRate(DEFAULT_MIN_RELAY_TX_FEE_PER_KB); | CFeeRate minRelayTxFee = CFeeRate(DEFAULT_MIN_RELAY_TX_FEE_PER_KB); | ||||
▲ Show 20 Lines • Show All 766 Lines • ▼ Show 20 Lines | void CChainState::InitCoinsDB(size_t cache_size_bytes, bool in_memory, | ||||
bool should_wipe, std::string leveldb_name) { | bool should_wipe, std::string leveldb_name) { | ||||
if (!m_from_snapshot_blockhash.IsNull()) { | if (!m_from_snapshot_blockhash.IsNull()) { | ||||
leveldb_name += "_" + m_from_snapshot_blockhash.ToString(); | leveldb_name += "_" + m_from_snapshot_blockhash.ToString(); | ||||
} | } | ||||
m_coins_views = std::make_unique<CoinsViews>(leveldb_name, cache_size_bytes, | m_coins_views = std::make_unique<CoinsViews>(leveldb_name, cache_size_bytes, | ||||
in_memory, should_wipe); | in_memory, should_wipe); | ||||
} | } | ||||
void CChainState::InitCoinsCache() { | void CChainState::InitCoinsCache(size_t cache_size_bytes) { | ||||
assert(m_coins_views != nullptr); | assert(m_coins_views != nullptr); | ||||
m_coinstip_cache_size_bytes = cache_size_bytes; | |||||
m_coins_views->InitCache(); | m_coins_views->InitCache(); | ||||
} | } | ||||
// Note that though this is marked const, we may end up modifying | // Note that though this is marked const, we may end up modifying | ||||
// `m_cached_finished_ibd`, which is a performance-related implementation | // `m_cached_finished_ibd`, which is a performance-related implementation | ||||
// detail. This function must be marked `const` so that `CValidationInterface` | // detail. This function must be marked `const` so that `CValidationInterface` | ||||
// clients (which are given a `const CChainState*`) can call it. | // clients (which are given a `const CChainState*`) can call it. | ||||
// | // | ||||
▲ Show 20 Lines • Show All 1,151 Lines • ▼ Show 20 Lines | LogPrint(BCLog::BENCH, " - Callbacks: %.2fms [%.2fs (%.2fms/blk)]\n", | ||||
nTimeCallbacks * MILLI / nBlocksTotal); | nTimeCallbacks * MILLI / nBlocksTotal); | ||||
return true; | return true; | ||||
} | } | ||||
CoinsCacheSizeState | CoinsCacheSizeState | ||||
CChainState::GetCoinsCacheSizeState(const CTxMemPool &tx_pool) { | CChainState::GetCoinsCacheSizeState(const CTxMemPool &tx_pool) { | ||||
return this->GetCoinsCacheSizeState( | return this->GetCoinsCacheSizeState( | ||||
tx_pool, nCoinCacheUsage, | tx_pool, m_coinstip_cache_size_bytes, | ||||
gArgs.GetArg("-maxmempool", DEFAULT_MAX_MEMPOOL_SIZE) * 1000000); | gArgs.GetArg("-maxmempool", DEFAULT_MAX_MEMPOOL_SIZE) * 1000000); | ||||
} | } | ||||
CoinsCacheSizeState | CoinsCacheSizeState | ||||
CChainState::GetCoinsCacheSizeState(const CTxMemPool &tx_pool, | CChainState::GetCoinsCacheSizeState(const CTxMemPool &tx_pool, | ||||
size_t max_coins_cache_size_bytes, | size_t max_coins_cache_size_bytes, | ||||
size_t max_mempool_size_bytes) { | size_t max_mempool_size_bytes) { | ||||
int64_t nMempoolUsage = tx_pool.DynamicMemoryUsage(); | int64_t nMempoolUsage = tx_pool.DynamicMemoryUsage(); | ||||
▲ Show 20 Lines • Show All 2,871 Lines • ▼ Show 20 Lines | for (pindex = ::ChainActive().Tip(); pindex && pindex->pprev; | ||||
if (!pindex->GetUndoPos().IsNull()) { | if (!pindex->GetUndoPos().IsNull()) { | ||||
if (!UndoReadFromDisk(undo, pindex)) { | if (!UndoReadFromDisk(undo, pindex)) { | ||||
return error( | return error( | ||||
"VerifyDB(): *** found bad undo data at %d, hash=%s\n", | "VerifyDB(): *** found bad undo data at %d, hash=%s\n", | ||||
pindex->nHeight, pindex->GetBlockHash().ToString()); | pindex->nHeight, pindex->GetBlockHash().ToString()); | ||||
} | } | ||||
} | } | ||||
} | } | ||||
// check level 3: check for inconsistencies during memory-only | // check level 3: check for inconsistencies during memory-only | ||||
// disconnect of tip blocks | // disconnect of tip blocks | ||||
if (nCheckLevel >= 3 && | if (nCheckLevel >= 3 && | ||||
(coins.DynamicMemoryUsage() + | (coins.DynamicMemoryUsage() + | ||||
::ChainstateActive().CoinsTip().DynamicMemoryUsage()) <= | ::ChainstateActive().CoinsTip().DynamicMemoryUsage()) <= | ||||
nCoinCacheUsage) { | ::ChainstateActive().m_coinstip_cache_size_bytes) { | ||||
assert(coins.GetBestBlock() == pindex->GetBlockHash()); | assert(coins.GetBestBlock() == pindex->GetBlockHash()); | ||||
DisconnectResult res = | DisconnectResult res = | ||||
::ChainstateActive().DisconnectBlock(block, pindex, coins); | ::ChainstateActive().DisconnectBlock(block, pindex, coins); | ||||
if (res == DisconnectResult::FAILED) { | if (res == DisconnectResult::FAILED) { | ||||
return error("VerifyDB(): *** irrecoverable inconsistency in " | return error("VerifyDB(): *** irrecoverable inconsistency in " | ||||
"block data at %d, hash=%s", | "block data at %d, hash=%s", | ||||
pindex->nHeight, | pindex->nHeight, | ||||
pindex->GetBlockHash().ToString()); | pindex->GetBlockHash().ToString()); | ||||
▲ Show 20 Lines • Show All 762 Lines • ▼ Show 20 Lines | |||||
std::string CChainState::ToString() { | std::string CChainState::ToString() { | ||||
CBlockIndex *tip = m_chain.Tip(); | CBlockIndex *tip = m_chain.Tip(); | ||||
return strprintf("Chainstate [%s] @ height %d (%s)", | return strprintf("Chainstate [%s] @ height %d (%s)", | ||||
m_from_snapshot_blockhash.IsNull() ? "ibd" : "snapshot", | m_from_snapshot_blockhash.IsNull() ? "ibd" : "snapshot", | ||||
tip ? tip->nHeight : -1, | tip ? tip->nHeight : -1, | ||||
tip ? tip->GetBlockHash().ToString() : "null"); | tip ? tip->GetBlockHash().ToString() : "null"); | ||||
} | } | ||||
bool CChainState::ResizeCoinsCaches(size_t coinstip_size, size_t coinsdb_size) { | |||||
if (coinstip_size == m_coinstip_cache_size_bytes && | |||||
coinsdb_size == m_coinsdb_cache_size_bytes) { | |||||
// Cache sizes are unchanged, no need to continue. | |||||
return true; | |||||
} | |||||
size_t old_coinstip_size = m_coinstip_cache_size_bytes; | |||||
m_coinstip_cache_size_bytes = coinstip_size; | |||||
m_coinsdb_cache_size_bytes = coinsdb_size; | |||||
CoinsDB().ResizeCache(coinsdb_size); | |||||
LogPrintf("[%s] resized coinsdb cache to %.1f MiB\n", this->ToString(), | |||||
coinsdb_size * (1.0 / 1024 / 1024)); | |||||
LogPrintf("[%s] resized coinstip cache to %.1f MiB\n", this->ToString(), | |||||
coinstip_size * (1.0 / 1024 / 1024)); | |||||
BlockValidationState state; | |||||
const CChainParams &chainparams = Params(); | |||||
bool ret; | |||||
if (coinstip_size > old_coinstip_size) { | |||||
// Likely no need to flush if cache sizes have grown. | |||||
ret = FlushStateToDisk(chainparams, state, FlushStateMode::IF_NEEDED); | |||||
} else { | |||||
// Otherwise, flush state to disk and deallocate the in-memory coins | |||||
// map. | |||||
ret = FlushStateToDisk(chainparams, state, FlushStateMode::ALWAYS); | |||||
CoinsTip().ReallocateCache(); | |||||
} | |||||
return ret; | |||||
} | |||||
std::string CBlockFileInfo::ToString() const { | std::string CBlockFileInfo::ToString() const { | ||||
return strprintf( | return strprintf( | ||||
"CBlockFileInfo(blocks=%u, size=%u, heights=%u...%u, time=%s...%s)", | "CBlockFileInfo(blocks=%u, size=%u, heights=%u...%u, time=%s...%s)", | ||||
nBlocks, nSize, nHeightFirst, nHeightLast, | nBlocks, nSize, nHeightFirst, nHeightLast, | ||||
FormatISO8601DateTime(nTimeFirst), FormatISO8601DateTime(nTimeLast)); | FormatISO8601DateTime(nTimeFirst), FormatISO8601DateTime(nTimeLast)); | ||||
} | } | ||||
CBlockFileInfo *GetBlockFileInfo(size_t n) { | CBlockFileInfo *GetBlockFileInfo(size_t n) { | ||||
▲ Show 20 Lines • Show All 321 Lines • ▼ Show 20 Lines | |||||
} | } | ||||
void ChainstateManager::Reset() { | void ChainstateManager::Reset() { | ||||
m_ibd_chainstate.reset(); | m_ibd_chainstate.reset(); | ||||
m_snapshot_chainstate.reset(); | m_snapshot_chainstate.reset(); | ||||
m_active_chainstate = nullptr; | m_active_chainstate = nullptr; | ||||
m_snapshot_validated = false; | m_snapshot_validated = false; | ||||
} | } | ||||
void ChainstateManager::MaybeRebalanceCaches() { | |||||
if (m_ibd_chainstate && !m_snapshot_chainstate) { | |||||
LogPrintf("[snapshot] allocating all cache to the IBD chainstate\n"); | |||||
// Allocate everything to the IBD chainstate. | |||||
m_ibd_chainstate->ResizeCoinsCaches(m_total_coinstip_cache, | |||||
m_total_coinsdb_cache); | |||||
} else if (m_snapshot_chainstate && !m_ibd_chainstate) { | |||||
LogPrintf( | |||||
"[snapshot] allocating all cache to the snapshot chainstate\n"); | |||||
// Allocate everything to the snapshot chainstate. | |||||
m_snapshot_chainstate->ResizeCoinsCaches(m_total_coinstip_cache, | |||||
m_total_coinsdb_cache); | |||||
} else if (m_ibd_chainstate && m_snapshot_chainstate) { | |||||
// If both chainstates exist, determine who needs more cache based on | |||||
// IBD status. | |||||
// | |||||
// Note: shrink caches first so that we don't inadvertently overwhelm | |||||
// available memory. | |||||
if (m_snapshot_chainstate->IsInitialBlockDownload()) { | |||||
m_ibd_chainstate->ResizeCoinsCaches(m_total_coinstip_cache * 0.05, | |||||
m_total_coinsdb_cache * 0.05); | |||||
m_snapshot_chainstate->ResizeCoinsCaches( | |||||
m_total_coinstip_cache * 0.95, m_total_coinsdb_cache * 0.95); | |||||
} else { | |||||
m_snapshot_chainstate->ResizeCoinsCaches( | |||||
m_total_coinstip_cache * 0.05, m_total_coinsdb_cache * 0.05); | |||||
m_ibd_chainstate->ResizeCoinsCaches(m_total_coinstip_cache * 0.95, | |||||
m_total_coinsdb_cache * 0.95); | |||||
} | |||||
} | |||||
} |