| 5205 | } |
| 5206 | |
| 5207 | bool ChainstateManager::ActivateSnapshot( |
| 5208 | CAutoFile& coins_file, |
| 5209 | const SnapshotMetadata& metadata, |
| 5210 | bool in_memory) |
| 5211 | { |
| 5212 | uint256 base_blockhash = metadata.m_base_blockhash; |
| 5213 | |
| 5214 | if (this->SnapshotBlockhash()) { |
| 5215 | LogPrintf("[snapshot] can't activate a snapshot-based chainstate more than once\n"); |
| 5216 | return false; |
| 5217 | } |
| 5218 | |
| 5219 | int64_t current_coinsdb_cache_size{0}; |
| 5220 | int64_t current_coinstip_cache_size{0}; |
| 5221 | |
| 5222 | // Cache percentages to allocate to each chainstate. |
| 5223 | // |
| 5224 | // These particular percentages don't matter so much since they will only be |
| 5225 | // relevant during snapshot activation; caches are rebalanced at the conclusion of |
| 5226 | // this function. We want to give (essentially) all available cache capacity to the |
| 5227 | // snapshot to aid the bulk load later in this function. |
| 5228 | static constexpr double IBD_CACHE_PERC = 0.01; |
| 5229 | static constexpr double SNAPSHOT_CACHE_PERC = 0.99; |
| 5230 | |
| 5231 | { |
| 5232 | LOCK(::cs_main); |
| 5233 | // Resize the coins caches to ensure we're not exceeding memory limits. |
| 5234 | // |
| 5235 | // Allocate the majority of the cache to the incoming snapshot chainstate, since |
| 5236 | // (optimistically) getting to its tip will be the top priority. We'll need to call |
| 5237 | // `MaybeRebalanceCaches()` once we're done with this function to ensure |
| 5238 | // the right allocation (including the possibility that no snapshot was activated |
| 5239 | // and that we should restore the active chainstate caches to their original size). |
| 5240 | // |
| 5241 | current_coinsdb_cache_size = this->ActiveChainstate().m_coinsdb_cache_size_bytes; |
| 5242 | current_coinstip_cache_size = this->ActiveChainstate().m_coinstip_cache_size_bytes; |
| 5243 | |
| 5244 | // Temporarily resize the active coins cache to make room for the newly-created |
| 5245 | // snapshot chain. |
| 5246 | this->ActiveChainstate().ResizeCoinsCaches( |
| 5247 | static_cast<size_t>(current_coinstip_cache_size * IBD_CACHE_PERC), |
| 5248 | static_cast<size_t>(current_coinsdb_cache_size * IBD_CACHE_PERC)); |
| 5249 | } |
| 5250 | |
| 5251 | auto snapshot_chainstate = WITH_LOCK(::cs_main, |
| 5252 | return std::make_unique<CChainState>( |
| 5253 | /* mempool */ nullptr, m_blockman, *this, base_blockhash)); |
| 5254 | |
| 5255 | { |
| 5256 | LOCK(::cs_main); |
| 5257 | snapshot_chainstate->InitCoinsDB( |
| 5258 | static_cast<size_t>(current_coinsdb_cache_size * SNAPSHOT_CACHE_PERC), |
| 5259 | in_memory, false, "chainstate"); |
| 5260 | snapshot_chainstate->InitCoinsCache( |
| 5261 | static_cast<size_t>(current_coinstip_cache_size * SNAPSHOT_CACHE_PERC)); |
| 5262 | } |
| 5263 | |
| 5264 | const bool snapshot_ok = this->PopulateAndValidateSnapshot( |