From d0c6e61f5dd3b6af818459d9d03b7ba316c5a3f7 Mon Sep 17 00:00:00 2001 From: James O'Beirne Date: Thu, 28 Oct 2021 15:15:10 -0400 Subject: validation: don't modify genesis during snapshot load Avoid modifying the genesis block index entry during snapshot load. This is because, in a future change that fixes LoadBlockIndex for UTXO snapshots, we detect block index entries that are reliant on assumed-valid ancestors and treat them specially. Since the genesis block doesn't have BLOCK_VALID_SCRIPTS, it would be erroneously marked BLOCK_ASSUMED_VALID during snapshot load if we didn't skip it here. This would cause a "setBlockIndexCandidates() empty" assertion to be tripped since all block index entries would be marked assume-valid due to genesis, which is never re-validated. There's probably no good reason to modify the genesis block index entry during snapshot load anyway... --- src/validation.cpp | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-) (limited to 'src/validation.cpp') diff --git a/src/validation.cpp b/src/validation.cpp index 207cdc8233..110218de36 100644 --- a/src/validation.cpp +++ b/src/validation.cpp @@ -4909,7 +4909,14 @@ bool ChainstateManager::PopulateAndValidateSnapshot( // Fake various pieces of CBlockIndex state: CBlockIndex* index = nullptr; - for (int i = 0; i <= snapshot_chainstate.m_chain.Height(); ++i) { + + // Don't make any modifications to the genesis block. + // This is especially important because we don't want to erroneously + // apply BLOCK_ASSUMED_VALID to genesis, which would happen if we didn't skip + // it here (since it apparently isn't BLOCK_VALID_SCRIPTS). + constexpr int AFTER_GENESIS_START{1}; + + for (int i = AFTER_GENESIS_START; i <= snapshot_chainstate.m_chain.Height(); ++i) { index = snapshot_chainstate.m_chain[i]; // Fake nTx so that LoadBlockIndex() loads assumed-valid CBlockIndex @@ -4918,7 +4925,7 @@ bool ChainstateManager::PopulateAndValidateSnapshot( index->nTx = 1; } // Fake nChainTx so that GuessVerificationProgress reports accurately - index->nChainTx = index->pprev ? index->pprev->nChainTx + index->nTx : 1; + index->nChainTx = index->pprev->nChainTx + index->nTx; // Mark unvalidated block index entries beneath the snapshot base block as assumed-valid. if (!index->IsValid(BLOCK_VALID_SCRIPTS)) { @@ -4929,7 +4936,7 @@ bool ChainstateManager::PopulateAndValidateSnapshot( // Fake BLOCK_OPT_WITNESS so that CChainState::NeedsRedownload() // won't ask to rewind the entire assumed-valid chain on startup. - if (index->pprev && DeploymentActiveAt(*index, ::Params().GetConsensus(), Consensus::DEPLOYMENT_SEGWIT)) { + if (DeploymentActiveAt(*index, ::Params().GetConsensus(), Consensus::DEPLOYMENT_SEGWIT)) { index->nStatus |= BLOCK_OPT_WITNESS; } -- cgit v1.2.3