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:
2026-06-30 16:27:34 -05:00
parent 1f2b109d95
commit 84aefb5475
9 changed files with 2 additions and 703 deletions

View File

@@ -862,76 +862,6 @@ UniValue gettxoutsetinfo(const UniValue& params, bool fHelp, const CPubKey& mypk
return ret;
}
UniValue dumptxoutset(const UniValue& params, bool fHelp, const CPubKey& mypk)
{
if (fHelp || params.size() != 1)
throw runtime_error(
"dumptxoutset \"path\"\n"
"\nWrite a trusted snapshot of the current chainstate (UTXO set + Sapling commitment\n"
"trees, nullifier set and pool value) to disk. The snapshot can be loaded by a fresh\n"
"node with -loadutxosnapshot=<file> to skip replaying the chain from genesis.\n"
"\nThis is intended to be run at a final/checkpoint height; the node must be fully synced.\n"
"\nArguments:\n"
"1. \"path\" (string, required) path to write the snapshot file (must not already exist)\n"
"\nResult:\n"
"{\n"
" \"height\": n, (numeric) snapshot height H\n"
" \"base_hash\": \"hex\", (string) block hash at height H\n"
" \"snapshot_hash\": \"hex\", (string) content hash to hardcode for verification\n"
" \"coins\": n, (numeric) number of UTXO records\n"
" \"sapling_anchors\": n, (numeric) number of Sapling anchor records\n"
" \"sapling_nullifiers\": n, (numeric) number of Sapling nullifier records\n"
" \"path\": \"...\" (string) the file written\n"
"}\n"
"\nExamples:\n"
+ HelpExampleCli("dumptxoutset", "/path/to/dragonx-utxo.dat")
+ HelpExampleRpc("dumptxoutset", "\"/path/to/dragonx-utxo.dat\"")
);
boost::filesystem::path path = boost::filesystem::absolute(params[0].get_str());
if (boost::filesystem::exists(path))
throw JSONRPCError(RPC_INVALID_PARAMETER, "path already exists, refusing to overwrite: " + path.string());
LOCK(cs_main);
if (pcoinsdbview == nullptr || pcoinsTip == nullptr)
throw JSONRPCError(RPC_INTERNAL_ERROR, "chainstate not available");
// Flush so the on-disk chainstate matches the in-memory tip before we iterate it.
FlushStateToDisk();
CBlockIndex *tip = chainActive.Tip();
if (tip == nullptr)
throw JSONRPCError(RPC_INTERNAL_ERROR, "no chain tip");
CUTXOSnapshotHeader header;
header.nMagic = UTXO_SNAPSHOT_MAGIC;
header.nVersion = UTXO_SNAPSHOT_VERSION;
memcpy(&header.nNetworkMagic, Params().MessageStart(), 4);
header.baseBlockHash = tip->GetBlockHash();
header.nHeight = tip->GetHeight();
header.nChainTx = tip->nChainTx;
if (tip->nChainSaplingValue) {
header.fHasChainSaplingValue = 1;
header.nChainSaplingValue = *tip->nChainSaplingValue;
}
header.bestSaplingAnchor = pcoinsdbview->GetBestAnchor(SAPLING);
uint256 snapshotHash;
std::string strError;
if (!pcoinsdbview->DumpSnapshot(path.string(), header, snapshotHash, strError))
throw JSONRPCError(RPC_INTERNAL_ERROR, "dumptxoutset failed: " + strError);
UniValue ret(UniValue::VOBJ);
ret.push_back(Pair("height", (int64_t)header.nHeight));
ret.push_back(Pair("base_hash", header.baseBlockHash.GetHex()));
ret.push_back(Pair("snapshot_hash", snapshotHash.GetHex()));
ret.push_back(Pair("coins", (int64_t)header.nCoins));
ret.push_back(Pair("sapling_anchors", (int64_t)header.nSaplingAnchors));
ret.push_back(Pair("sapling_nullifiers", (int64_t)header.nSaplingNullifiers));
ret.push_back(Pair("path", path.string()));
return ret;
}
UniValue getblockmerkletree(const UniValue& params, bool fHelp, const CPubKey& mypk)
{
@@ -1924,7 +1854,6 @@ static const CRPCCommand commands[] =
{ "blockchain", "getrawmempool", &getrawmempool, true },
{ "blockchain", "gettxout", &gettxout, true },
{ "blockchain", "gettxoutsetinfo", &gettxoutsetinfo, true },
{ "blockchain", "dumptxoutset", &dumptxoutset, true },
{ "blockchain", "verifychain", &verifychain, true },
/* Not shown in help */