0
0
Fork 0
mirror of https://github.com/bitcoin/bitcoin.git synced 2025-02-02 09:46:52 -05:00

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.
This commit is contained in:
James O'Beirne 2023-05-05 15:54:13 -04:00
parent 49ef778158
commit 4c3b8ca35c
3 changed files with 29 additions and 7 deletions

View file

@ -378,13 +378,26 @@ CBlockIndex* BlockManager::InsertBlockIndex(const uint256& hash)
return pindex; return pindex;
} }
bool BlockManager::LoadBlockIndex() bool BlockManager::LoadBlockIndex(const std::optional<uint256>& snapshot_blockhash)
{ {
if (!m_block_tree_db->LoadBlockIndexGuts( if (!m_block_tree_db->LoadBlockIndexGuts(
GetConsensus(), [this](const uint256& hash) EXCLUSIVE_LOCKS_REQUIRED(cs_main) { return this->InsertBlockIndex(hash); }, m_interrupt)) { GetConsensus(), [this](const uint256& hash) EXCLUSIVE_LOCKS_REQUIRED(cs_main) { return this->InsertBlockIndex(hash); }, m_interrupt)) {
return false; 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 // Calculate nChainWork
std::vector<CBlockIndex*> vSortedByHeight{GetAllBlockIndices()}; std::vector<CBlockIndex*> vSortedByHeight{GetAllBlockIndices()};
std::sort(vSortedByHeight.begin(), vSortedByHeight.end(), std::sort(vSortedByHeight.begin(), vSortedByHeight.end(),
@ -401,7 +414,11 @@ bool BlockManager::LoadBlockIndex()
// Pruned nodes may have deleted the block. // Pruned nodes may have deleted the block.
if (pindex->nTx > 0) { if (pindex->nTx > 0) {
if (pindex->pprev) { 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; pindex->nChainTx = pindex->pprev->nChainTx + pindex->nTx;
} else { } else {
pindex->nChainTx = 0; pindex->nChainTx = 0;
@ -444,9 +461,9 @@ bool BlockManager::WriteBlockIndexDB()
return true; return true;
} }
bool BlockManager::LoadBlockIndexDB() bool BlockManager::LoadBlockIndexDB(const std::optional<uint256>& snapshot_blockhash)
{ {
if (!LoadBlockIndex()) { if (!LoadBlockIndex(snapshot_blockhash)) {
return false; return false;
} }

View file

@ -118,7 +118,7 @@ private:
* per index entry (nStatus, nChainWork, nTimeMax, etc.) as well as peripheral * per index entry (nStatus, nChainWork, nTimeMax, etc.) as well as peripheral
* collections like m_dirty_blockindex. * collections like m_dirty_blockindex.
*/ */
bool LoadBlockIndex() bool LoadBlockIndex(const std::optional<uint256>& snapshot_blockhash)
EXCLUSIVE_LOCKS_REQUIRED(cs_main); EXCLUSIVE_LOCKS_REQUIRED(cs_main);
/** Return false if block file or undo file flushing fails. */ /** 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); std::unique_ptr<BlockTreeDB> m_block_tree_db GUARDED_BY(::cs_main);
bool WriteBlockIndexDB() EXCLUSIVE_LOCKS_REQUIRED(::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. * Remove any pruned block & undo files that are still on disk.

View file

@ -4542,7 +4542,7 @@ bool ChainstateManager::LoadBlockIndex()
// Load block index from databases // Load block index from databases
bool needs_init = fReindex; bool needs_init = fReindex;
if (!fReindex) { if (!fReindex) {
bool ret{m_blockman.LoadBlockIndexDB()}; bool ret{m_blockman.LoadBlockIndexDB(SnapshotBlockhash())};
if (!ret) return false; if (!ret) return false;
m_blockman.ScanAndUnlinkAlreadyPrunedFiles(); m_blockman.ScanAndUnlinkAlreadyPrunedFiles();
@ -4838,6 +4838,10 @@ void ChainstateManager::CheckBlockIndex()
CBlockIndex* pindexFirstAssumeValid = nullptr; // Oldest ancestor of pindex which has BLOCK_ASSUMED_VALID CBlockIndex* pindexFirstAssumeValid = nullptr; // Oldest ancestor of pindex which has BLOCK_ASSUMED_VALID
while (pindex != nullptr) { while (pindex != nullptr) {
nNodes++; 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 (pindexFirstAssumeValid == nullptr && pindex->nStatus & BLOCK_ASSUMED_VALID) pindexFirstAssumeValid = pindex;
if (pindexFirstInvalid == nullptr && pindex->nStatus & BLOCK_FAILED_VALID) pindexFirstInvalid = pindex; if (pindexFirstInvalid == nullptr && pindex->nStatus & BLOCK_FAILED_VALID) pindexFirstInvalid = pindex;
if (pindexFirstMissing == nullptr && !(pindex->nStatus & BLOCK_HAVE_DATA)) { if (pindexFirstMissing == nullptr && !(pindex->nStatus & BLOCK_HAVE_DATA)) {