Skip to content

Commit 4c3b8ca

Browse files
committed
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.
1 parent 49ef778 commit 4c3b8ca

File tree

3 files changed

+29
-7
lines changed

3 files changed

+29
-7
lines changed

src/node/blockstorage.cpp

Lines changed: 21 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -378,13 +378,26 @@ CBlockIndex* BlockManager::InsertBlockIndex(const uint256& hash)
378378
return pindex;
379379
}
380380

381-
bool BlockManager::LoadBlockIndex()
381+
bool BlockManager::LoadBlockIndex(const std::optional<uint256>& snapshot_blockhash)
382382
{
383383
if (!m_block_tree_db->LoadBlockIndexGuts(
384384
GetConsensus(), [this](const uint256& hash) EXCLUSIVE_LOCKS_REQUIRED(cs_main) { return this->InsertBlockIndex(hash); }, m_interrupt)) {
385385
return false;
386386
}
387387

388+
int snapshot_height = -1;
389+
if (snapshot_blockhash) {
390+
const AssumeutxoData au_data = *Assert(GetParams().AssumeutxoForBlockhash(*snapshot_blockhash));
391+
snapshot_height = au_data.height;
392+
CBlockIndex* base{LookupBlockIndex(*snapshot_blockhash)};
393+
394+
// Since nChainTx (responsible for estiamted progress) isn't persisted
395+
// to disk, we must bootstrap the value for assumedvalid chainstates
396+
// from the hardcoded assumeutxo chainparams.
397+
base->nChainTx = au_data.nChainTx;
398+
LogPrintf("[snapshot] set nChainTx=%d for %s\n", au_data.nChainTx, snapshot_blockhash->ToString());
399+
}
400+
388401
// Calculate nChainWork
389402
std::vector<CBlockIndex*> vSortedByHeight{GetAllBlockIndices()};
390403
std::sort(vSortedByHeight.begin(), vSortedByHeight.end(),
@@ -401,7 +414,11 @@ bool BlockManager::LoadBlockIndex()
401414
// Pruned nodes may have deleted the block.
402415
if (pindex->nTx > 0) {
403416
if (pindex->pprev) {
404-
if (pindex->pprev->nChainTx > 0) {
417+
if (snapshot_blockhash && pindex->nHeight == snapshot_height &&
418+
pindex->GetBlockHash() == *snapshot_blockhash) {
419+
// Should have been set above; don't disturb it with code below.
420+
Assert(pindex->nChainTx > 0);
421+
} else if (pindex->pprev->nChainTx > 0) {
405422
pindex->nChainTx = pindex->pprev->nChainTx + pindex->nTx;
406423
} else {
407424
pindex->nChainTx = 0;
@@ -444,9 +461,9 @@ bool BlockManager::WriteBlockIndexDB()
444461
return true;
445462
}
446463

447-
bool BlockManager::LoadBlockIndexDB()
464+
bool BlockManager::LoadBlockIndexDB(const std::optional<uint256>& snapshot_blockhash)
448465
{
449-
if (!LoadBlockIndex()) {
466+
if (!LoadBlockIndex(snapshot_blockhash)) {
450467
return false;
451468
}
452469

src/node/blockstorage.h

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -118,7 +118,7 @@ class BlockManager
118118
* per index entry (nStatus, nChainWork, nTimeMax, etc.) as well as peripheral
119119
* collections like m_dirty_blockindex.
120120
*/
121-
bool LoadBlockIndex()
121+
bool LoadBlockIndex(const std::optional<uint256>& snapshot_blockhash)
122122
EXCLUSIVE_LOCKS_REQUIRED(cs_main);
123123

124124
/** Return false if block file or undo file flushing fails. */
@@ -231,7 +231,8 @@ class BlockManager
231231
std::unique_ptr<BlockTreeDB> m_block_tree_db GUARDED_BY(::cs_main);
232232

233233
bool WriteBlockIndexDB() EXCLUSIVE_LOCKS_REQUIRED(::cs_main);
234-
bool LoadBlockIndexDB() EXCLUSIVE_LOCKS_REQUIRED(::cs_main);
234+
bool LoadBlockIndexDB(const std::optional<uint256>& snapshot_blockhash)
235+
EXCLUSIVE_LOCKS_REQUIRED(::cs_main);
235236

236237
/**
237238
* Remove any pruned block & undo files that are still on disk.

src/validation.cpp

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4542,7 +4542,7 @@ bool ChainstateManager::LoadBlockIndex()
45424542
// Load block index from databases
45434543
bool needs_init = fReindex;
45444544
if (!fReindex) {
4545-
bool ret{m_blockman.LoadBlockIndexDB()};
4545+
bool ret{m_blockman.LoadBlockIndexDB(SnapshotBlockhash())};
45464546
if (!ret) return false;
45474547

45484548
m_blockman.ScanAndUnlinkAlreadyPrunedFiles();
@@ -4838,6 +4838,10 @@ void ChainstateManager::CheckBlockIndex()
48384838
CBlockIndex* pindexFirstAssumeValid = nullptr; // Oldest ancestor of pindex which has BLOCK_ASSUMED_VALID
48394839
while (pindex != nullptr) {
48404840
nNodes++;
4841+
if (pindex->pprev && pindex->nTx > 0) {
4842+
// nChainTx should increase monotonically
4843+
assert(pindex->pprev->nChainTx <= pindex->nChainTx);
4844+
}
48414845
if (pindexFirstAssumeValid == nullptr && pindex->nStatus & BLOCK_ASSUMED_VALID) pindexFirstAssumeValid = pindex;
48424846
if (pindexFirstInvalid == nullptr && pindex->nStatus & BLOCK_FAILED_VALID) pindexFirstInvalid = pindex;
48434847
if (pindexFirstMissing == nullptr && !(pindex->nStatus & BLOCK_HAVE_DATA)) {

0 commit comments

Comments
 (0)