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

@@ -79,9 +79,15 @@ BaseIndex::~BaseIndex()
bool BaseIndex::Init()
{
AssertLockNotHeld(cs_main);
// May need reset if index is being restarted.
m_interrupt.reset();
// m_chainstate member gives indexing code access to node internals. It is
// removed in followup https://github.com/bitcoin/bitcoin/pull/24230
m_chainstate = &m_chain->context()->chainman->ActiveChainstate();
m_chainstate = WITH_LOCK(::cs_main,
return &m_chain->context()->chainman->GetChainstateForIndexing());
// Register to validation interface before setting the 'm_synced' flag, so that
// callbacks are not missed once m_synced is true.
RegisterValidationInterface(this);
@@ -92,7 +98,8 @@ bool BaseIndex::Init()
}
LOCK(cs_main);
CChain& active_chain = m_chainstate->m_chain;
CChain& index_chain = m_chainstate->m_chain;
if (locator.IsNull()) {
SetBestBlockIndex(nullptr);
} else {
@@ -114,7 +121,7 @@ bool BaseIndex::Init()
// Note: this will latch to true immediately if the user starts up with an empty
// datadir and an index enabled. If this is the case, indexation will happen solely
// via `BlockConnected` signals until, possibly, the next restart.
m_synced = start_block == active_chain.Tip();
m_synced = start_block == index_chain.Tip();
m_init = true;
return true;
}
@@ -143,6 +150,8 @@ void BaseIndex::ThreadSync()
std::chrono::steady_clock::time_point last_locator_write_time{0s};
while (true) {
if (m_interrupt) {
LogPrintf("%s: m_interrupt set; exiting ThreadSync\n", GetName());
SetBestBlockIndex(pindex);
// No need to handle errors in Commit. If it fails, the error will be already be
// logged. The best way to recover is to continue, as index cannot be corrupted by
@@ -252,6 +261,17 @@ bool BaseIndex::Rewind(const CBlockIndex* current_tip, const CBlockIndex* new_ti
void BaseIndex::BlockConnected(ChainstateRole role, const std::shared_ptr<const CBlock>& block, const CBlockIndex* pindex)
{
// Ignore events from the assumed-valid chain; we will process its blocks
// (sequentially) after it is fully verified by the background chainstate. This
// is to avoid any out-of-order indexing.
//
// TODO at some point we could parameterize whether a particular index can be
// built out of order, but for now just do the conservative simple thing.
if (role == ChainstateRole::ASSUMEDVALID) {
return;
}
// Ignore BlockConnected signals until we have fully indexed the chain.
if (!m_synced) {
return;
}
@@ -298,6 +318,12 @@ void BaseIndex::BlockConnected(ChainstateRole role, const std::shared_ptr<const
void BaseIndex::ChainStateFlushed(ChainstateRole role, const CBlockLocator& locator)
{
// Ignore events from the assumed-valid chain; we will process its blocks
// (sequentially) after it is fully verified by the background chainstate.
if (role == ChainstateRole::ASSUMEDVALID) {
return;
}
if (!m_synced) {
return;
}