| 5299 | } |
| 5300 | |
| 5301 | bool ChainstateManager::PopulateAndValidateSnapshot( |
| 5302 | CChainState& snapshot_chainstate, |
| 5303 | CAutoFile& coins_file, |
| 5304 | const SnapshotMetadata& metadata) |
| 5305 | { |
| 5306 | // It's okay to release cs_main before we're done using `coins_cache` because we know |
| 5307 | // that nothing else will be referencing the newly created snapshot_chainstate yet. |
| 5308 | CCoinsViewCache& coins_cache = *WITH_LOCK(::cs_main, return &snapshot_chainstate.CoinsTip()); |
| 5309 | |
| 5310 | uint256 base_blockhash = metadata.m_base_blockhash; |
| 5311 | |
| 5312 | CBlockIndex* snapshot_start_block = WITH_LOCK(::cs_main, return m_blockman.LookupBlockIndex(base_blockhash)); |
| 5313 | |
| 5314 | if (!snapshot_start_block) { |
| 5315 | // Needed for GetUTXOStats and ExpectedAssumeutxo to determine the height and to avoid a crash when base_blockhash.IsNull() |
| 5316 | LogPrintf("[snapshot] Did not find snapshot start blockheader %s\n", |
| 5317 | base_blockhash.ToString()); |
| 5318 | return false; |
| 5319 | } |
| 5320 | |
| 5321 | int base_height = snapshot_start_block->nHeight; |
| 5322 | auto maybe_au_data = ExpectedAssumeutxo(base_height, ::Params()); |
| 5323 | |
| 5324 | if (!maybe_au_data) { |
| 5325 | LogPrintf("[snapshot] assumeutxo height in snapshot metadata not recognized " /* Continued */ |
| 5326 | "(%d) - refusing to load snapshot\n", base_height); |
| 5327 | return false; |
| 5328 | } |
| 5329 | |
| 5330 | const AssumeutxoData& au_data = *maybe_au_data; |
| 5331 | |
| 5332 | COutPoint outpoint; |
| 5333 | Coin coin; |
| 5334 | const uint64_t coins_count = metadata.m_coins_count; |
| 5335 | uint64_t coins_left = metadata.m_coins_count; |
| 5336 | |
| 5337 | LogPrintf("[snapshot] loading coins from snapshot %s\n", base_blockhash.ToString()); |
| 5338 | int64_t coins_processed{0}; |
| 5339 | |
| 5340 | while (coins_left > 0) { |
| 5341 | try { |
| 5342 | coins_file >> outpoint; |
| 5343 | coins_file >> coin; |
| 5344 | } catch (const std::ios_base::failure&) { |
| 5345 | LogPrintf("[snapshot] bad snapshot format or truncated snapshot after deserializing %d coins\n", |
| 5346 | coins_count - coins_left); |
| 5347 | return false; |
| 5348 | } |
| 5349 | if (coin.nHeight > base_height || |
| 5350 | outpoint.n >= std::numeric_limits<decltype(outpoint.n)>::max() // Avoid integer wrap-around in coinstats.cpp:ApplyHash |
| 5351 | ) { |
| 5352 | LogPrintf("[snapshot] bad snapshot data after deserializing %d coins\n", |
| 5353 | coins_count - coins_left); |
| 5354 | return false; |
| 5355 | } |
| 5356 | |
| 5357 | coins_cache.EmplaceCoinInternalDANGER(std::move(outpoint), std::move(coin)); |
| 5358 |
no test coverage detected