| 126 | } |
| 127 | |
| 128 | std::optional<ChainstateLoadVerifyError> VerifyLoadedChainstate(ChainstateManager& chainman, |
| 129 | bool fReset, |
| 130 | bool fReindexChainState, |
| 131 | const Consensus::Params& consensus_params, |
| 132 | int check_blocks, |
| 133 | int check_level, |
| 134 | std::function<int64_t()> get_unix_time_seconds) |
| 135 | { |
| 136 | auto is_coinsview_empty = [&](CChainState* chainstate) EXCLUSIVE_LOCKS_REQUIRED(::cs_main) { |
| 137 | return fReset || fReindexChainState || chainstate->CoinsTip().GetBestBlock().IsNull(); |
| 138 | }; |
| 139 | |
| 140 | LOCK(cs_main); |
| 141 | |
| 142 | for (CChainState* chainstate : chainman.GetAll()) { |
| 143 | if (!is_coinsview_empty(chainstate)) { |
| 144 | const CBlockIndex* tip = chainstate->m_chain.Tip(); |
| 145 | if (tip && tip->nTime > get_unix_time_seconds() + MAX_FUTURE_BLOCK_TIME) { |
| 146 | return ChainstateLoadVerifyError::ERROR_BLOCK_FROM_FUTURE; |
| 147 | } |
| 148 | |
| 149 | if (!CVerifyDB().VerifyDB( |
| 150 | *chainstate, consensus_params, chainstate->CoinsDB(), |
| 151 | check_level, |
| 152 | check_blocks)) { |
| 153 | return ChainstateLoadVerifyError::ERROR_CORRUPTED_BLOCK_DB; |
| 154 | } |
| 155 | } |
| 156 | } |
| 157 | |
| 158 | return std::nullopt; |
| 159 | } |
| 160 | } // namespace node |