Remove assumeutxo / UTXO-snapshot feature
Removes the dumptxoutset RPC, -loadutxosnapshot / -loadutxosnapshotunsafe, the CCoinsViewDB Dump/LoadSnapshot machinery + CUTXOSnapshotHeader, the AssumeutxoData chainparams anchor, the LoadSnapshotChainstate activation + reorg-below-H guard, the persisted assumeutxo-height flag, and the gtest. Rationale: it duplicated the existing bootstrap (same skip-the-genesis-grind fast-sync, no speed advantage), its only real edge was a trust model we don't need for this chain, and it was inert anyway (no published snapshot hash in chainparams). The -loadutxosnapshot load path adopted an external UTXO set and bypassed genesis validation, so removing it also drops that attack surface. Builds clean (no dangling references); the kept IBD speedups (RandomX pre-verify, adaptive dbcache, tlsmanager) are untouched. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
58
src/main.cpp
58
src/main.cpp
@@ -85,7 +85,6 @@ void hush_pricesupdate(int32_t height,CBlock *pblock);
|
||||
BlockMap mapBlockIndex;
|
||||
CChain chainActive;
|
||||
CBlockIndex *pindexBestHeader = NULL;
|
||||
int nAssumeutxoSnapshotHeight = -1; // height H of a loaded UTXO snapshot; reorgs below H are refused (-1 = none)
|
||||
static int64_t nTimeBestReceived = 0;
|
||||
CWaitableCriticalSection csBestBlock;
|
||||
CConditionVariable cvBlockChange;
|
||||
@@ -4201,45 +4200,6 @@ static void PruneBlockIndexCandidates() {
|
||||
assert(!setBlockIndexCandidates.empty());
|
||||
}
|
||||
|
||||
// Activate a trusted UTXO snapshot (assumeutxo-style) as the chain tip WITHOUT replaying blocks
|
||||
// 0..H. The chainstate has already been populated by CCoinsViewDB::LoadSnapshot(); here we mark the
|
||||
// snapshot's base block (height H) as fully validated and set it as the active tip. Blocks above H
|
||||
// then connect normally with full PoW + script + Sapling-proof validation. Requires that the block
|
||||
// HEADERS for height H are already present in mapBlockIndex (from prior header sync or bootstrap).
|
||||
// NOTE: below-H blocks have no body/undo data, so reorgs below H are impossible (see Stage D guard).
|
||||
bool LoadSnapshotChainstate(const CUTXOSnapshotHeader& header, std::string& strError)
|
||||
{
|
||||
LOCK(cs_main);
|
||||
BlockMap::iterator it = mapBlockIndex.find(header.baseBlockHash);
|
||||
if (it == mapBlockIndex.end() || it->second == NULL) {
|
||||
strError = "block header for the snapshot height is not present; sync headers (or use the bootstrap) before loading a UTXO snapshot";
|
||||
return false;
|
||||
}
|
||||
CBlockIndex* pindexH = it->second;
|
||||
if (pindexH->GetHeight() != header.nHeight) {
|
||||
strError = "snapshot base block height does not match its header index";
|
||||
return false;
|
||||
}
|
||||
|
||||
// Only nChainTx is consensus-relevant for tip selection; nTx must merely be non-zero so the
|
||||
// (nChainTx != 0) candidate-eligibility checks hold. Ancestors legitimately have nTx==0 here
|
||||
// because we never received their bodies — this is the assumeutxo trust assumption.
|
||||
if (pindexH->nTx == 0)
|
||||
pindexH->nTx = (header.nChainTx > 0 ? (unsigned int)header.nChainTx : 1);
|
||||
pindexH->nChainTx = (unsigned int)header.nChainTx;
|
||||
if (header.fHasChainSaplingValue)
|
||||
pindexH->nChainSaplingValue = header.nChainSaplingValue;
|
||||
|
||||
pindexH->RaiseValidity(BLOCK_VALID_SCRIPTS);
|
||||
nAssumeutxoSnapshotHeight = pindexH->GetHeight(); // arm the reorg-below-H guard (Stage D)
|
||||
setBlockIndexCandidates.insert(pindexH);
|
||||
chainActive.SetTip(pindexH);
|
||||
if (pindexBestHeader == NULL || pindexBestHeader->GetHeight() < pindexH->GetHeight())
|
||||
pindexBestHeader = pindexH;
|
||||
PruneBlockIndexCandidates();
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Try to make some progress towards making pindexMostWork the active block.
|
||||
* pblock is either NULL or a pointer to a CBlock corresponding to pindexMostWork.
|
||||
@@ -4288,15 +4248,6 @@ static bool ActivateBestChainStep(bool fSkipdpow, CValidationState &state, CBloc
|
||||
return state.DoS(100, error("ActivateBestChainStep(): pindexOldTip->GetHeight().%d > notarizedht %d && pindexFork->GetHeight().%d is < notarizedht %d, so ignore it",(int32_t)pindexOldTip->GetHeight(),notarizedht,(int32_t)pindexFork->GetHeight(),notarizedht),
|
||||
REJECT_INVALID, "past-notarized-height");
|
||||
}
|
||||
// Refuse reorgs whose fork point is below a loaded UTXO snapshot height (Stage D): the node has
|
||||
// no block/undo data for 0..H, so disconnecting below H is impossible. Belt-and-suspenders on top
|
||||
// of checkpoint fork-rejection (H sits at/below the last hardcoded checkpoint).
|
||||
if ( nAssumeutxoSnapshotHeight >= 0 && pindexFork != 0 && pindexFork->GetHeight() < nAssumeutxoSnapshotHeight )
|
||||
{
|
||||
return state.DoS(100, error("ActivateBestChainStep(): reorg fork height %d is below the loaded UTXO snapshot height %d; refusing",
|
||||
(int32_t)pindexFork->GetHeight(), nAssumeutxoSnapshotHeight),
|
||||
REJECT_INVALID, "below-assumeutxo-snapshot");
|
||||
}
|
||||
|
||||
// - On ChainDB initialization, pindexOldTip will be null, so there are no removable blocks.
|
||||
// - If pindexMostWork is in a chain that doesn't have the same genesis block as our chain,
|
||||
@@ -6101,15 +6052,6 @@ bool static LoadBlockIndexDB()
|
||||
pblocktree->ReadReindexing(fReindexing);
|
||||
fReindex |= fReindexing;
|
||||
|
||||
// Restore the loaded-UTXO-snapshot height so the reorg-below-H guard survives restarts.
|
||||
{
|
||||
int snapHeight = -1;
|
||||
if (pblocktree->ReadAssumeutxoHeight(snapHeight) && snapHeight >= 0) {
|
||||
nAssumeutxoSnapshotHeight = snapHeight;
|
||||
LogPrintf("%s: loaded-from-UTXO-snapshot height is %d; reorgs below it are refused\n", __func__, snapHeight);
|
||||
}
|
||||
}
|
||||
|
||||
// Check whether we have a transaction index
|
||||
pblocktree->ReadFlag("txindex", fTxIndex);
|
||||
LogPrintf("%s: transaction index %s\n", __func__, fTxIndex ? "enabled" : "disabled");
|
||||
|
||||
Reference in New Issue
Block a user