| 56 | } |
| 57 | |
| 58 | bool BaseIndex::Init() |
| 59 | { |
| 60 | CBlockLocator locator; |
| 61 | if (!GetDB().ReadBestBlock(locator)) { |
| 62 | locator.SetNull(); |
| 63 | } |
| 64 | |
| 65 | LOCK(cs_main); |
| 66 | CChain& active_chain = m_chainstate->m_chain; |
| 67 | if (locator.IsNull()) { |
| 68 | m_best_block_index = nullptr; |
| 69 | } else { |
| 70 | m_best_block_index = m_chainstate->FindForkInGlobalIndex(locator); |
| 71 | } |
| 72 | m_synced = m_best_block_index.load() == active_chain.Tip(); |
| 73 | if (!m_synced) { |
| 74 | bool prune_violation = false; |
| 75 | if (!m_best_block_index) { |
| 76 | // index is not built yet |
| 77 | // make sure we have all block data back to the genesis |
| 78 | const CBlockIndex* block = active_chain.Tip(); |
| 79 | while (block->pprev && (block->pprev->nStatus & BLOCK_HAVE_DATA)) { |
| 80 | block = block->pprev; |
| 81 | } |
| 82 | prune_violation = block != active_chain.Genesis(); |
| 83 | } |
| 84 | // in case the index has a best block set and is not fully synced |
| 85 | // check if we have the required blocks to continue building the index |
| 86 | else { |
| 87 | const CBlockIndex* block_to_test = m_best_block_index.load(); |
| 88 | if (!active_chain.Contains(block_to_test)) { |
| 89 | // if the bestblock is not part of the mainchain, find the fork |
| 90 | // and make sure we have all data down to the fork |
| 91 | block_to_test = active_chain.FindFork(block_to_test); |
| 92 | } |
| 93 | const CBlockIndex* block = active_chain.Tip(); |
| 94 | prune_violation = true; |
| 95 | // check backwards from the tip if we have all block data until we reach the indexes bestblock |
| 96 | while (block_to_test && block && (block->nStatus & BLOCK_HAVE_DATA)) { |
| 97 | if (block_to_test == block) { |
| 98 | prune_violation = false; |
| 99 | break; |
| 100 | } |
| 101 | // block->pprev must exist at this point, since block_to_test is part of the chain |
| 102 | // and thus must be encountered when going backwards from the tip |
| 103 | assert(block->pprev); |
| 104 | block = block->pprev; |
| 105 | } |
| 106 | } |
| 107 | if (prune_violation) { |
| 108 | return InitError(strprintf(Untranslated("%s best block of the index goes beyond pruned data. Please disable the index or reindex (which will download the whole blockchain again)"), GetName())); |
| 109 | } |
| 110 | } |
| 111 | return true; |
| 112 | } |
| 113 | |
| 114 | static const CBlockIndex* NextSyncBlock(const CBlockIndex* pindex_prev, CChain& chain) EXCLUSIVE_LOCKS_REQUIRED(cs_main) |
| 115 | { |