| 10 | |
| 11 | namespace node { |
| 12 | std::optional<ChainstateLoadingError> LoadChainstate(bool fReset, |
| 13 | ChainstateManager& chainman, |
| 14 | CTxMemPool* mempool, |
| 15 | bool fPruneMode, |
| 16 | const Consensus::Params& consensus_params, |
| 17 | bool fReindexChainState, |
| 18 | int64_t nBlockTreeDBCache, |
| 19 | int64_t nCoinDBCache, |
| 20 | int64_t nCoinCacheUsage, |
| 21 | bool block_tree_db_in_memory, |
| 22 | bool coins_db_in_memory, |
| 23 | std::function<bool()> shutdown_requested, |
| 24 | std::function<void()> coins_error_cb) |
| 25 | { |
| 26 | auto is_coinsview_empty = [&](CChainState* chainstate) EXCLUSIVE_LOCKS_REQUIRED(::cs_main) { |
| 27 | return fReset || fReindexChainState || chainstate->CoinsTip().GetBestBlock().IsNull(); |
| 28 | }; |
| 29 | |
| 30 | LOCK(cs_main); |
| 31 | chainman.InitializeChainstate(mempool); |
| 32 | chainman.m_total_coinstip_cache = nCoinCacheUsage; |
| 33 | chainman.m_total_coinsdb_cache = nCoinDBCache; |
| 34 | |
| 35 | UnloadBlockIndex(mempool, chainman); |
| 36 | |
| 37 | auto& pblocktree{chainman.m_blockman.m_block_tree_db}; |
| 38 | // new CBlockTreeDB tries to delete the existing file, which |
| 39 | // fails if it's still open from the previous loop. Close it first: |
| 40 | pblocktree.reset(); |
| 41 | pblocktree.reset(new CBlockTreeDB(nBlockTreeDBCache, block_tree_db_in_memory, fReset)); |
| 42 | |
| 43 | if (fReset) { |
| 44 | pblocktree->WriteReindexing(true); |
| 45 | //If we're reindexing in prune mode, wipe away unusable block files and all undo data files |
| 46 | if (fPruneMode) |
| 47 | CleanupBlockRevFiles(); |
| 48 | } |
| 49 | |
| 50 | if (shutdown_requested && shutdown_requested()) return ChainstateLoadingError::SHUTDOWN_PROBED; |
| 51 | |
| 52 | // LoadBlockIndex will load fHavePruned if we've ever removed a |
| 53 | // block file from disk. |
| 54 | // Note that it also sets fReindex based on the disk flag! |
| 55 | // From here on out fReindex and fReset mean something different! |
| 56 | if (!chainman.LoadBlockIndex()) { |
| 57 | if (shutdown_requested && shutdown_requested()) return ChainstateLoadingError::SHUTDOWN_PROBED; |
| 58 | return ChainstateLoadingError::ERROR_LOADING_BLOCK_DB; |
| 59 | } |
| 60 | |
| 61 | if (!chainman.BlockIndex().empty() && |
| 62 | !chainman.m_blockman.LookupBlockIndex(consensus_params.hashGenesisBlock)) { |
| 63 | return ChainstateLoadingError::ERROR_BAD_GENESIS_BLOCK; |
| 64 | } |
| 65 | |
| 66 | // Check for changed -prune state. What we are concerned about is a user who has pruned blocks |
| 67 | // in the past, but is now trying to run unpruned. |
| 68 | if (fHavePruned && !fPruneMode) { |
| 69 | return ChainstateLoadingError::ERROR_PRUNED_NEEDS_REINDEX; |