diff options
-rw-r--r-- | src/node/blockstorage.cpp | 25 | ||||
-rw-r--r-- | src/node/blockstorage.h | 5 | ||||
-rw-r--r-- | src/validation.cpp | 6 |
3 files changed, 29 insertions, 7 deletions
diff --git a/src/node/blockstorage.cpp b/src/node/blockstorage.cpp index 9ae4ad67b4..7ed2346ae4 100644 --- a/src/node/blockstorage.cpp +++ b/src/node/blockstorage.cpp @@ -378,13 +378,26 @@ CBlockIndex* BlockManager::InsertBlockIndex(const uint256& hash) return pindex; } -bool BlockManager::LoadBlockIndex() +bool BlockManager::LoadBlockIndex(const std::optional<uint256>& snapshot_blockhash) { if (!m_block_tree_db->LoadBlockIndexGuts( GetConsensus(), [this](const uint256& hash) EXCLUSIVE_LOCKS_REQUIRED(cs_main) { return this->InsertBlockIndex(hash); }, m_interrupt)) { return false; } + int snapshot_height = -1; + if (snapshot_blockhash) { + const AssumeutxoData au_data = *Assert(GetParams().AssumeutxoForBlockhash(*snapshot_blockhash)); + snapshot_height = au_data.height; + CBlockIndex* base{LookupBlockIndex(*snapshot_blockhash)}; + + // Since nChainTx (responsible for estiamted progress) isn't persisted + // to disk, we must bootstrap the value for assumedvalid chainstates + // from the hardcoded assumeutxo chainparams. + base->nChainTx = au_data.nChainTx; + LogPrintf("[snapshot] set nChainTx=%d for %s\n", au_data.nChainTx, snapshot_blockhash->ToString()); + } + // Calculate nChainWork std::vector<CBlockIndex*> vSortedByHeight{GetAllBlockIndices()}; std::sort(vSortedByHeight.begin(), vSortedByHeight.end(), @@ -401,7 +414,11 @@ bool BlockManager::LoadBlockIndex() // Pruned nodes may have deleted the block. if (pindex->nTx > 0) { if (pindex->pprev) { - if (pindex->pprev->nChainTx > 0) { + if (snapshot_blockhash && pindex->nHeight == snapshot_height && + pindex->GetBlockHash() == *snapshot_blockhash) { + // Should have been set above; don't disturb it with code below. + Assert(pindex->nChainTx > 0); + } else if (pindex->pprev->nChainTx > 0) { pindex->nChainTx = pindex->pprev->nChainTx + pindex->nTx; } else { pindex->nChainTx = 0; @@ -444,9 +461,9 @@ bool BlockManager::WriteBlockIndexDB() return true; } -bool BlockManager::LoadBlockIndexDB() +bool BlockManager::LoadBlockIndexDB(const std::optional<uint256>& snapshot_blockhash) { - if (!LoadBlockIndex()) { + if (!LoadBlockIndex(snapshot_blockhash)) { return false; } diff --git a/src/node/blockstorage.h b/src/node/blockstorage.h index 6448858406..fcd9fb9f67 100644 --- a/src/node/blockstorage.h +++ b/src/node/blockstorage.h @@ -118,7 +118,7 @@ private: * per index entry (nStatus, nChainWork, nTimeMax, etc.) as well as peripheral * collections like m_dirty_blockindex. */ - bool LoadBlockIndex() + bool LoadBlockIndex(const std::optional<uint256>& snapshot_blockhash) EXCLUSIVE_LOCKS_REQUIRED(cs_main); /** Return false if block file or undo file flushing fails. */ @@ -231,7 +231,8 @@ public: std::unique_ptr<BlockTreeDB> m_block_tree_db GUARDED_BY(::cs_main); bool WriteBlockIndexDB() EXCLUSIVE_LOCKS_REQUIRED(::cs_main); - bool LoadBlockIndexDB() EXCLUSIVE_LOCKS_REQUIRED(::cs_main); + bool LoadBlockIndexDB(const std::optional<uint256>& snapshot_blockhash) + EXCLUSIVE_LOCKS_REQUIRED(::cs_main); /** * Remove any pruned block & undo files that are still on disk. diff --git a/src/validation.cpp b/src/validation.cpp index b5cff0a4fd..9c783ece65 100644 --- a/src/validation.cpp +++ b/src/validation.cpp @@ -4542,7 +4542,7 @@ bool ChainstateManager::LoadBlockIndex() // Load block index from databases bool needs_init = fReindex; if (!fReindex) { - bool ret{m_blockman.LoadBlockIndexDB()}; + bool ret{m_blockman.LoadBlockIndexDB(SnapshotBlockhash())}; if (!ret) return false; m_blockman.ScanAndUnlinkAlreadyPrunedFiles(); @@ -4838,6 +4838,10 @@ void ChainstateManager::CheckBlockIndex() CBlockIndex* pindexFirstAssumeValid = nullptr; // Oldest ancestor of pindex which has BLOCK_ASSUMED_VALID while (pindex != nullptr) { nNodes++; + if (pindex->pprev && pindex->nTx > 0) { + // nChainTx should increase monotonically + assert(pindex->pprev->nChainTx <= pindex->nChainTx); + } if (pindexFirstAssumeValid == nullptr && pindex->nStatus & BLOCK_ASSUMED_VALID) pindexFirstAssumeValid = pindex; if (pindexFirstInvalid == nullptr && pindex->nStatus & BLOCK_FAILED_VALID) pindexFirstInvalid = pindex; if (pindexFirstMissing == nullptr && !(pindex->nStatus & BLOCK_HAVE_DATA)) { |