IBD/sync speedups: parallel RandomX pre-verify, adaptive dbcache, P2P download fixes
- Parallel RandomX PoW pre-verification pool (CCheckQueue) run ahead of the serial connect; consensus-neutral (inline CheckRandomXSolution fallback still verifies anything not pre-verified). New -randomxverifythreads (default = -par). - Adaptive dbcache: default sizes the UTXO/coins cache to most of RAM and shrinks under memory pressure, always leaving a reserve free; -dbcache pins a fixed value. - P2P block download: bounded socket recv-drain loop (tlsmanager); frontier-block reassignment to break head-of-line stalls (-blockreassigntimeout); ProcessGetData serves a bounded batch of blocks per pass instead of one (fixes the serve-side one-block-per-tick throttle that caps download network-wide). - assumeutxo: dumptxoutset RPC + LoadSnapshot machinery + AssumeutxoData chainparams. - Signed bootstrap verification (util/bootstrap-dragonx.sh, util/sign-bootstrap.md). - gtest: RandomX pre-verify consensus-equivalence test + UTXO-snapshot round-trip; revived the gtest harness (Makefile.am include fix, Makefile.gtest.include). Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -30,7 +30,9 @@
|
||||
#include "rpc/server.h"
|
||||
#include "streams.h"
|
||||
#include "sync.h"
|
||||
#include "txdb.h"
|
||||
#include "util.h"
|
||||
#include <boost/filesystem.hpp>
|
||||
#include "script/script.h"
|
||||
#include "script/script_error.h"
|
||||
#include "script/sign.h"
|
||||
@@ -860,6 +862,77 @@ 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)
|
||||
{
|
||||
if (fHelp || params.size() != 1 )
|
||||
@@ -1851,6 +1924,7 @@ 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 */
|
||||
|
||||
Reference in New Issue
Block a user