Skip to content

Commit

Permalink
Merge pull request bitcoin#8 from bitcoin-dev-tools/assumeutxo-for-be…
Browse files Browse the repository at this point in the history
…nchmarking
  • Loading branch information
willcl-ark authored Nov 5, 2024
2 parents 017a633 + 963472a commit 68aab6d
Show file tree
Hide file tree
Showing 6 changed files with 71 additions and 4 deletions.
59 changes: 58 additions & 1 deletion src/init.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
// file COPYING or http://www.opensource.org/licenses/mit-license.php.

#include <bitcoin-build-config.h> // IWYU pragma: keep
#include "node/utxo_snapshot.h"

#include <init.h>

Expand Down Expand Up @@ -140,6 +141,7 @@ using node::VerifyLoadedChainstate;
using util::Join;
using util::ReplaceAll;
using util::ToString;
using node::SnapshotMetadata;

static constexpr bool DEFAULT_PROXYRANDOMIZE{true};
static constexpr bool DEFAULT_REST_ENABLE{false};
Expand All @@ -158,6 +160,44 @@ static constexpr bool DEFAULT_STOPAFTERBLOCKIMPORT{false};
static constexpr int MIN_CORE_FDS = MIN_LEVELDB_FDS + NUM_FDS_MESSAGE_CAPTURE;
static const char* DEFAULT_ASMAP_FILENAME="ip_asn.map";

bool LoadUTXOSnapshot(NodeContext& node, const fs::path& snapshot_path) {
ChainstateManager& chainman = *node.chainman;

FILE* file{fsbridge::fopen(snapshot_path, "rb")};
AutoFile afile{file};
if (afile.IsNull()) {
LogPrintf("Error: Couldn't open UTXO snapshot file %s for reading\n", snapshot_path.utf8string());
return false;
}

SnapshotMetadata metadata{chainman.GetParams().MessageStart()};
try {
afile >> metadata;
} catch (const std::ios_base::failure& e) {
LogPrintf("Error: Unable to parse snapshot metadata: %s\n", e.what());
return false;
}

auto activation_result{chainman.ActivateSnapshot(afile, metadata, false)};
if (!activation_result) {
LogPrintf("Error: Unable to load UTXO snapshot: %s\n",
util::ErrorString(activation_result).original);
return false;
}

// Update services to reflect limited peer capabilities during sync
node.connman->RemoveLocalServices(NODE_NETWORK);
node.connman->AddLocalServices(NODE_NETWORK_LIMITED);

CBlockIndex& snapshot_index{*CHECK_NONFATAL(*activation_result)};
LogPrintf("Loaded UTXO snapshot: coins=%d, height=%d, hash=%s\n",
metadata.m_coins_count,
snapshot_index.nHeight,
snapshot_index.GetBlockHash().ToString());

return true;
}

/**
* The PID file facilities.
*/
Expand Down Expand Up @@ -495,6 +535,12 @@ void SetupServerArgs(ArgsManager& argsman, bool can_listen_ipc)
argsman.AddArg("-minimumchainwork=<hex>", strprintf("Minimum work assumed to exist on a valid chain in hex (default: %s, testnet3: %s, testnet4: %s, signet: %s)", defaultChainParams->GetConsensus().nMinimumChainWork.GetHex(), testnetChainParams->GetConsensus().nMinimumChainWork.GetHex(), testnet4ChainParams->GetConsensus().nMinimumChainWork.GetHex(), signetChainParams->GetConsensus().nMinimumChainWork.GetHex()), ArgsManager::ALLOW_ANY | ArgsManager::DEBUG_ONLY, OptionsCategory::OPTIONS);
argsman.AddArg("-par=<n>", strprintf("Set the number of script verification threads (0 = auto, up to %d, <0 = leave that many cores free, default: %d)",
MAX_SCRIPTCHECK_THREADS, DEFAULT_SCRIPTCHECK_THREADS), ArgsManager::ALLOW_ANY, OptionsCategory::OPTIONS);
argsman.AddArg("-pausebackgroundsync", strprintf("When a UTXO snapshot is loaded, pause the verification of historical blocks in the background (default: %u)", DEFAULT_PAUSE_BACKGROUND_SYNC), ArgsManager::ALLOW_ANY, OptionsCategory::OPTIONS);
gArgs.AddArg("-loadutxosnapshot=<path>",
"Load UTXO set from snapshot file at startup. "
"This allows fast synchronization by loading a pre-built UTXO "
"snapshot while the full chain validation happens in background.",
ArgsManager::ALLOW_ANY, OptionsCategory::OPTIONS);
argsman.AddArg("-persistmempool", strprintf("Whether to save the mempool on shutdown and load on restart (default: %u)", DEFAULT_PERSIST_MEMPOOL), ArgsManager::ALLOW_ANY, OptionsCategory::OPTIONS);
argsman.AddArg("-persistmempoolv1",
strprintf("Whether a mempool.dat file created by -persistmempool or the savemempool RPC will be written in the legacy format "
Expand Down Expand Up @@ -1661,6 +1707,15 @@ bool AppInitMain(NodeContext& node, interfaces::BlockAndHeaderTipInfo* tip_info)

ChainstateManager& chainman = *Assert(node.chainman);

if (args.IsArgSet("-loadutxosnapshot")) {
fs::path snapshot_path = fs::u8path(args.GetArg("-loadutxosnapshot", ""));
snapshot_path = AbsPathForConfigVal(args, snapshot_path);

if (!LoadUTXOSnapshot(node, snapshot_path)) {
LogPrintf("Failed to load UTXO snapshot from %s", snapshot_path.utf8string());
}
}

assert(!node.peerman);
node.peerman = PeerManager::make(*node.connman, *node.addrman,
node.banman.get(), chainman,
Expand Down Expand Up @@ -1800,7 +1855,9 @@ bool AppInitMain(NodeContext& node, interfaces::BlockAndHeaderTipInfo* tip_info)
});
}

if (ShutdownRequested(node)) {
// if loadutxosnapshot is set, we want to load the snapshot then shut down so that only
// syncing to chaintip is benchmarked
if (ShutdownRequested(node) || args.IsArgSet("-loadutxosnapshot")) {
return false;
}

Expand Down
2 changes: 2 additions & 0 deletions src/kernel/chainstatemanager_opts.h
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,8 @@ struct ChainstateManagerOpts {
int worker_threads_num{0};
size_t script_execution_cache_bytes{DEFAULT_SCRIPT_EXECUTION_CACHE_BYTES};
size_t signature_cache_bytes{DEFAULT_SIGNATURE_CACHE_BYTES};
//! Whether to defer syncing the background chainstate after an assumeutxo snapshot is loaded
bool pause_background_sync{false};
};

} // namespace kernel
Expand Down
2 changes: 2 additions & 0 deletions src/node/chainstatemanager_args.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -73,6 +73,8 @@ util::Result<void> ApplyArgsManOptions(const ArgsManager& args, ChainstateManage
opts.signature_cache_bytes = clamped_size_each;
}

opts.pause_background_sync = args.GetBoolArg("-pausebackgroundsync", DEFAULT_PAUSE_BACKGROUND_SYNC);

return {};
}
} // namespace node
2 changes: 2 additions & 0 deletions src/node/chainstatemanager_args.h
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,8 @@ class ArgsManager;
static constexpr int MAX_SCRIPTCHECK_THREADS{15};
/** -par default (number of script-checking threads, 0 = auto) */
static constexpr int DEFAULT_SCRIPTCHECK_THREADS{0};
/** -pausebackgroundsync default */
static const bool DEFAULT_PAUSE_BACKGROUND_SYNC{false};

namespace node {
[[nodiscard]] util::Result<void> ApplyArgsManOptions(const ArgsManager& args, ChainstateManager::Options& opts);
Expand Down
6 changes: 6 additions & 0 deletions src/validation.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -6394,6 +6394,12 @@ std::optional<int> ChainstateManager::GetSnapshotBaseHeight() const
return base ? std::make_optional(base->nHeight) : std::nullopt;
}

bool ChainstateManager::BackgroundSyncInProgress() const EXCLUSIVE_LOCKS_REQUIRED(GetMutex()) {
if (!IsUsable(m_snapshot_chainstate.get())) return false;
if (!IsUsable(m_ibd_chainstate.get())) return false;
return !m_options.pause_background_sync;
}

bool ChainstateManager::ValidatedSnapshotCleanup()
{
AssertLockHeld(::cs_main);
Expand Down
4 changes: 1 addition & 3 deletions src/validation.h
Original file line number Diff line number Diff line change
Expand Up @@ -1113,9 +1113,7 @@ class ChainstateManager
CBlockIndex* ActiveTip() const EXCLUSIVE_LOCKS_REQUIRED(GetMutex()) { return ActiveChain().Tip(); }

//! The state of a background sync (for net processing)
bool BackgroundSyncInProgress() const EXCLUSIVE_LOCKS_REQUIRED(GetMutex()) {
return IsUsable(m_snapshot_chainstate.get()) && IsUsable(m_ibd_chainstate.get());
}
bool BackgroundSyncInProgress() const EXCLUSIVE_LOCKS_REQUIRED(GetMutex());

//! The tip of the background sync chain
const CBlockIndex* GetBackgroundSyncTip() const EXCLUSIVE_LOCKS_REQUIRED(GetMutex()) {
Expand Down

0 comments on commit 68aab6d

Please sign in to comment.