| 332 | } |
| 333 | |
| 334 | void BaseIndex::BlockConnected(const ChainstateRole& role, const std::shared_ptr<const CBlock>& block, const CBlockIndex* pindex) |
| 335 | { |
| 336 | // Ignore events from not fully validated chains to avoid out-of-order indexing. |
| 337 | // |
| 338 | // TODO at some point we could parameterize whether a particular index can be |
| 339 | // built out of order, but for now just do the conservative simple thing. |
| 340 | if (!role.validated) { |
| 341 | return; |
| 342 | } |
| 343 | |
| 344 | // Ignore BlockConnected signals until we have fully indexed the chain. |
| 345 | if (!m_synced) { |
| 346 | return; |
| 347 | } |
| 348 | |
| 349 | const CBlockIndex* best_block_index = m_best_block_index.load(); |
| 350 | if (!best_block_index) { |
| 351 | if (pindex->nHeight != 0) { |
| 352 | FatalErrorf("First block connected is not the genesis block (height=%d)", |
| 353 | pindex->nHeight); |
| 354 | return; |
| 355 | } |
| 356 | } else { |
| 357 | // Ensure block connects to an ancestor of the current best block. This should be the case |
| 358 | // most of the time, but may not be immediately after the sync thread catches up and sets |
| 359 | // m_synced. Consider the case where there is a reorg and the blocks on the stale branch are |
| 360 | // in the ValidationInterface queue backlog even after the sync thread has caught up to the |
| 361 | // new chain tip. In this unlikely event, log a warning and let the queue clear. |
| 362 | if (best_block_index->GetAncestor(pindex->nHeight - 1) != pindex->pprev) { |
| 363 | LogWarning("Block %s does not connect to an ancestor of " |
| 364 | "known best chain (tip=%s); not updating index", |
| 365 | pindex->GetBlockHash().ToString(), |
| 366 | best_block_index->GetBlockHash().ToString()); |
| 367 | return; |
| 368 | } |
| 369 | if (best_block_index != pindex->pprev && !Rewind(best_block_index, pindex->pprev)) { |
| 370 | FatalErrorf("Failed to rewind %s to a previous chain tip", |
| 371 | GetName()); |
| 372 | return; |
| 373 | } |
| 374 | } |
| 375 | |
| 376 | // Dispatch block to child class; errors are logged internally and abort the node. |
| 377 | if (ProcessBlock(pindex, block.get())) { |
| 378 | // Setting the best block index is intentionally the last step of this |
| 379 | // function, so BlockUntilSyncedToCurrentChain callers waiting for the |
| 380 | // best block index to be updated can rely on the block being fully |
| 381 | // processed, and the index object being safe to delete. |
| 382 | SetBestBlockIndex(pindex); |
| 383 | } |
| 384 | } |
| 385 | |
| 386 | void BaseIndex::ChainStateFlushed(const ChainstateRole& role, const CBlockLocator& locator) |
| 387 | { |
no test coverage detected