| 218 | } |
| 219 | |
| 220 | bool BlockManager::LoadBlockIndex( |
| 221 | const Consensus::Params& consensus_params, |
| 222 | ChainstateManager& chainman) |
| 223 | { |
| 224 | int trim_below_height = 0; |
| 225 | if (fTrimHeaders) { |
| 226 | trim_below_height = std::numeric_limits<int>::max(); |
| 227 | } |
| 228 | if (!m_block_tree_db->LoadBlockIndexGuts(consensus_params, [this](const uint256& hash) EXCLUSIVE_LOCKS_REQUIRED(cs_main) { return this->InsertBlockIndex(hash); }, trim_below_height)) { |
| 229 | return false; |
| 230 | } |
| 231 | |
| 232 | // Calculate nChainWork |
| 233 | std::vector<std::pair<int, CBlockIndex*>> vSortedByHeight; |
| 234 | vSortedByHeight.reserve(m_block_index.size()); |
| 235 | for (const std::pair<const uint256, CBlockIndex*>& item : m_block_index) { |
| 236 | CBlockIndex* pindex = item.second; |
| 237 | vSortedByHeight.push_back(std::make_pair(pindex->nHeight, pindex)); |
| 238 | } |
| 239 | sort(vSortedByHeight.begin(), vSortedByHeight.end()); |
| 240 | |
| 241 | // Find start of assumed-valid region. |
| 242 | int first_assumed_valid_height = std::numeric_limits<int>::max(); |
| 243 | |
| 244 | for (const auto& [height, block] : vSortedByHeight) { |
| 245 | if (block->IsAssumedValid()) { |
| 246 | auto chainstates = chainman.GetAll(); |
| 247 | |
| 248 | // If we encounter an assumed-valid block index entry, ensure that we have |
| 249 | // one chainstate that tolerates assumed-valid entries and another that does |
| 250 | // not (i.e. the background validation chainstate), since assumed-valid |
| 251 | // entries should always be pending validation by a fully-validated chainstate. |
| 252 | auto any_chain = [&](auto fnc) { return std::any_of(chainstates.cbegin(), chainstates.cend(), fnc); }; |
| 253 | assert(any_chain([](auto chainstate) { return chainstate->reliesOnAssumedValid(); })); |
| 254 | assert(any_chain([](auto chainstate) { return !chainstate->reliesOnAssumedValid(); })); |
| 255 | |
| 256 | first_assumed_valid_height = height; |
| 257 | break; |
| 258 | } |
| 259 | } |
| 260 | |
| 261 | for (const std::pair<int, CBlockIndex*>& item : vSortedByHeight) { |
| 262 | if (ShutdownRequested()) return false; |
| 263 | CBlockIndex* pindex = item.second; |
| 264 | pindex->nChainWork = (pindex->pprev ? pindex->pprev->nChainWork : 0) + GetBlockProof(*pindex); |
| 265 | pindex->nTimeMax = (pindex->pprev ? std::max(pindex->pprev->nTimeMax, pindex->nTime) : pindex->nTime); |
| 266 | |
| 267 | // We can link the chain of blocks for which we've received transactions at some point, or |
| 268 | // blocks that are assumed-valid on the basis of snapshot load (see |
| 269 | // PopulateAndValidateSnapshot()). |
| 270 | // Pruned nodes may have deleted the block. |
| 271 | if (pindex->nTx > 0) { |
| 272 | if (pindex->pprev) { |
| 273 | if (pindex->pprev->nChainTx > 0) { |
| 274 | pindex->nChainTx = pindex->pprev->nChainTx + pindex->nTx; |
| 275 | } else { |
| 276 | pindex->nChainTx = 0; |
| 277 | m_blocks_unlinked.insert(std::make_pair(pindex->pprev, pindex)); |