aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/node/blockstorage.cpp25
-rw-r--r--src/node/blockstorage.h5
-rw-r--r--src/validation.cpp6
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)) {