validation: indexing changes for assumeutxo

When using an assumedvalid chainstate, only process validationinterface
callbacks from the background chainstate within indexes. This ensures
that all indexes are built in-order.

Later, we can possibly designate indexes which can be built out of order
and continue their operation during snapshot use.

Once the background sync has completed, restart the indexes so that
they continue to index the now-validated snapshot chainstate.
This commit is contained in:
James O'Beirne
2019-09-23 14:44:54 -04:00
committed by James O'Beirne
parent 1fffdd76a1
commit 373cf91531
5 changed files with 95 additions and 11 deletions

View File

@@ -1478,6 +1478,25 @@ bool AppInitMain(NodeContext& node, interfaces::BlockAndHeaderTipInfo* tip_info)
node.chainman = std::make_unique<ChainstateManager>(node.kernel->interrupt, chainman_opts, blockman_opts);
ChainstateManager& chainman = *node.chainman;
// This is defined and set here instead of inline in validation.h to avoid a hard
// dependency between validation and index/base, since the latter is not in
// libbitcoinkernel.
chainman.restart_indexes = [&node]() {
LogPrintf("[snapshot] restarting indexes\n");
// Drain the validation interface queue to ensure that the old indexes
// don't have any pending work.
SyncWithValidationInterfaceQueue();
for (auto* index : node.indexes) {
index->Interrupt();
index->Stop();
if (!(index->Init() && index->StartBackgroundSync())) {
LogPrintf("[snapshot] WARNING failed to restart index %s on snapshot chain\n", index->GetName());
}
}
};
node::ChainstateLoadOptions options;
options.mempool = Assert(node.mempool.get());
options.reindex = node::fReindex;
@@ -1906,18 +1925,19 @@ bool StartIndexBackgroundSync(NodeContext& node)
// indexes_start_block='nullptr' means "start from height 0".
std::optional<const CBlockIndex*> indexes_start_block;
std::string older_index_name;
ChainstateManager& chainman = *Assert(node.chainman);
const Chainstate& chainstate = WITH_LOCK(::cs_main, return chainman.GetChainstateForIndexing());
const CChain& index_chain = chainstate.m_chain;
for (auto index : node.indexes) {
const IndexSummary& summary = index->GetSummary();
if (summary.synced) continue;
// Get the last common block between the index best block and the active chain
LOCK(::cs_main);
const CChain& active_chain = chainman.ActiveChain();
const CBlockIndex* pindex = chainman.m_blockman.LookupBlockIndex(summary.best_block_hash);
if (!active_chain.Contains(pindex)) {
pindex = active_chain.FindFork(pindex);
if (!index_chain.Contains(pindex)) {
pindex = index_chain.FindFork(pindex);
}
if (!indexes_start_block || !pindex || pindex->nHeight < indexes_start_block.value()->nHeight) {
@@ -1932,7 +1952,7 @@ bool StartIndexBackgroundSync(NodeContext& node)
LOCK(::cs_main);
const CBlockIndex* start_block = *indexes_start_block;
if (!start_block) start_block = chainman.ActiveChain().Genesis();
if (!chainman.m_blockman.CheckBlockDataAvailability(*chainman.ActiveChain().Tip(), *Assert(start_block))) {
if (!chainman.m_blockman.CheckBlockDataAvailability(*index_chain.Tip(), *Assert(start_block))) {
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)"), older_index_name));
}
}