From 7c555578b7e5c84e158c2efe38049eda81235aab Mon Sep 17 00:00:00 2001 From: Glenn Willen Date: Tue, 8 Nov 2022 00:19:32 -0800 Subject: [PATCH] Add a flag for header-trimming; clear P2P network feature bits when enabled. --- src/init.cpp | 25 ++++++++++++++++++++++++- src/node/blockstorage.cpp | 3 +++ src/node/blockstorage.h | 7 +++++++ 3 files changed, 34 insertions(+), 1 deletion(-) diff --git a/src/init.cpp b/src/init.cpp index 468d65147d..9f9ffbe5d6 100644 --- a/src/init.cpp +++ b/src/init.cpp @@ -425,6 +425,7 @@ void SetupServerArgs(ArgsManager& argsman) hidden_args.emplace_back("-sysperms"); #endif argsman.AddArg("-txindex", strprintf("Maintain a full transaction index, used by the getrawtransaction rpc call (default: %u)", DEFAULT_TXINDEX), ArgsManager::ALLOW_ANY, OptionsCategory::OPTIONS); + argsman.AddArg("-trim_headers", strprintf("Trim old headers in memory, removing blocksigning and dynafed-related fields. Saves memory, but blocks us from serving blocks or headers to peers, and removes trimmed fields from some JSON RPC outputs. (default: false)"), ArgsManager::ALLOW_ANY, OptionsCategory::OPTIONS); argsman.AddArg("-blockfilterindex=", strprintf("Maintain an index of compact filters by block (default: %s, values: %s).", DEFAULT_BLOCKFILTERINDEX, ListBlockFilterTypes()) + " If is not supplied or if = 1, indexes for all known types are enabled.", @@ -979,6 +980,23 @@ bool AppInitParameterInteraction(const ArgsManager& args) fPruneMode = true; } + if (args.IsArgSet("-trim_headers")) { + LogPrintf("Configured for header-trimming mode. This will reduce memory usage substantially, but we will be unable to serve as a full P2P peer, and certain header fields may be missing from JSON RPC output.\n"); + fTrimHeaders = true; + // This calculation is driven by GetValidFedpegScripts in pegins.cpp, which walks the chain + // back to current epoch start, and then an additional total_valid_epochs on top of that. + // We add one epoch here for the current partial epoch, and then another one for good luck. + // NB: If we're non-dynafed, then: + // - total_valid_epochs = 1 + // - dynamic_epoch_length = std::numeric_limits::max() + // So this will work out to an unhelpfully-large number. XXX: Is this a problem? + nMustKeepFullHeaders = (chainparams.GetConsensus().total_valid_epochs + 2) * (chainparams.GetConsensus().dynamic_epoch_length); + // This is the number of headers we can have in flight downloading at a time, beyond the + // set of blocks we've already validated. Capping this is necessary to keep memory usage + // bounded during IBD. + } + nHeaderDownloadBuffer = chainparams.GetConsensus().dynamic_epoch_length * 2; + nConnectTimeout = args.GetArg("-timeout", DEFAULT_CONNECT_TIMEOUT); if (nConnectTimeout <= 0) { nConnectTimeout = DEFAULT_CONNECT_TIMEOUT; @@ -1690,7 +1708,7 @@ bool AppInitMain(NodeContext& node, interfaces::BlockAndHeaderTipInfo* tip_info) // if pruning, unset the service bit and perform the initial blockstore prune // after any wallet rescanning has taken place. - if (fPruneMode) { + if (fPruneMode || fTrimHeaders) { LogPrintf("Unsetting NODE_NETWORK on prune mode\n"); nLocalServices = ServiceFlags(nLocalServices & ~NODE_NETWORK); if (!fReindex) { @@ -1702,6 +1720,11 @@ bool AppInitMain(NodeContext& node, interfaces::BlockAndHeaderTipInfo* tip_info) } } + if (fTrimHeaders) { + LogPrintf("Unsetting NODE_NETWORK_LIMITED on header trim mode\n"); + nLocalServices = ServiceFlags(nLocalServices & ~NODE_NETWORK_LIMITED); + } + if (DeploymentEnabled(chainparams.GetConsensus(), Consensus::DEPLOYMENT_SEGWIT)) { // Advertise witness capabilities. // The option to not set NODE_WITNESS is only used in the tests and should be removed. diff --git a/src/node/blockstorage.cpp b/src/node/blockstorage.cpp index da817aea3b..b014785a67 100644 --- a/src/node/blockstorage.cpp +++ b/src/node/blockstorage.cpp @@ -25,6 +25,9 @@ std::atomic_bool fReindex(false); bool fHavePruned = false; bool fPruneMode = false; uint64_t nPruneTarget = 0; +bool fTrimHeaders = false; +uint64_t nMustKeepFullHeaders = std::numeric_limits::max(); +uint64_t nHeaderDownloadBuffer = std::numeric_limits::max(); // TODO make namespace { RecursiveMutex cs_LastBlockFile; diff --git a/src/node/blockstorage.h b/src/node/blockstorage.h index 7c7bf68178..07c13052b3 100644 --- a/src/node/blockstorage.h +++ b/src/node/blockstorage.h @@ -44,6 +44,13 @@ extern bool fHavePruned; extern bool fPruneMode; /** Number of MiB of block files that we're trying to stay below. */ extern uint64_t nPruneTarget; +/** True if we're running in -trim_headers mode. */ +extern bool fTrimHeaders; +/** Minimum number of full untrimmed headers to keep, for blocks we have. */ +extern uint64_t nMustKeepFullHeaders; +/** Target number of headers to download beyond the blocks we have. */ +// XXX: this currently only operates when in header trim mode, but it's really independent of that. +extern uint64_t nHeaderDownloadBuffer; //! Check whether the block associated with this index entry is pruned or not. bool IsBlockPruned(const CBlockIndex* pblockindex);