aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorJames O'Beirne <james.obeirne@pm.me>2023-05-05 15:54:13 -0400
committerJames O'Beirne <james.obeirne@pm.me>2023-09-30 06:40:17 -0400
commit4c3b8ca35c2e4a441264749bb312df2bd054b5b8 (patch)
treec0a671b1c728c3039f08a103713fa5d9a930b836 /src
parent49ef778158c43859946a592e11ec34fe1b93a5b6 (diff)
validation: populate nChainTx value for assumedvalid chainstates
Use the expected AssumeutxoData in order to bootstrap nChainTx values for assumedvalid blockindex entries in the snapshot chainstate. This is necessary because nChainTx is normally built up from nTx values, which are populated using blockdata which the snapshot chainstate does not yet have.
Diffstat (limited to 'src')
-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)) {