From 6b824c37dca841006189227bcf7b9a0a24f5bd4f Mon Sep 17 00:00:00 2001 From: glozow Date: Thu, 4 Aug 2022 16:40:56 +0100 Subject: [PATCH] Merge bitcoin/bitcoin#25527: [kernel 3c/n] Decouple validation cache initialization from `ArgsManager` 0f3a2532c38074dd9789d1c4c667db6ca46ff0ab validationcaches: Use size_t for sizes (Carl Dong) 41c5201a90bbc2893333e334e8945759ef24e7dd validationcaches: Add and use ValidationCacheSizes (Carl Dong) 82d3058539f54ebad745e2b02b61df01aa832a54 cuckoocache: Check for uint32 overflow in setup_bytes (Carl Dong) b370164b319df1a500b70694b077f92265a777fb validationcaches: Abolish arbitrary limit (Carl Dong) 08dbc6ef72db48168dc03991f5f838dae42c8dfd cuckoocache: Return approximate memory size (Carl Dong) 0dbce4b1034b53d19b88af332385a006098b6d48 tests: Reduce calls to InitS*Cache() (Carl Dong) --- src/Makefile.am | 3 +++ src/cuckoocache.h | 23 +++++++++++++----- src/init.cpp | 16 ++++++++++--- src/kernel/validation_cache_sizes.h | 20 ++++++++++++++++ src/node/validation_cache_args.cpp | 36 ++++++++++++++++++++++++++++ src/node/validation_cache_args.h | 17 +++++++++++++ src/script/sigcache.cpp | 18 +++++++------- src/script/sigcache.h | 11 ++++----- src/test/fuzz/script_sigcache.cpp | 10 +++++--- src/test/txvalidationcache_tests.cpp | 5 ---- src/test/util/setup_common.cpp | 12 ++++++++-- src/validation.cpp | 17 +++++++------ src/validation.h | 2 +- 13 files changed, 149 insertions(+), 41 deletions(-) create mode 100644 src/kernel/validation_cache_sizes.h create mode 100644 src/node/validation_cache_args.cpp create mode 100644 src/node/validation_cache_args.h diff --git a/src/Makefile.am b/src/Makefile.am index f76c844973a4..2d3840d1395b 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -257,6 +257,7 @@ BITCOIN_CORE_H = \ instantsend/net_instantsend.h \ instantsend/signing.h \ kernel/coinstats.h \ + kernel/validation_cache_sizes.h \ key.h \ key_io.h \ limitedmap.h \ @@ -314,6 +315,7 @@ BITCOIN_CORE_H = \ node/txreconciliation.h \ node/interface_ui.h \ node/utxo_snapshot.h \ + node/validation_cache_args.h \ noui.h \ outputtype.h \ policy/feerate.h \ @@ -572,6 +574,7 @@ libbitcoin_node_a_SOURCES = \ node/transaction.cpp \ node/txreconciliation.cpp \ node/interface_ui.cpp \ + node/validation_cache_args.cpp \ noui.cpp \ policy/fees.cpp \ policy/packages.cpp \ diff --git a/src/cuckoocache.h b/src/cuckoocache.h index 22c06d89735a..c61bf379d2d2 100644 --- a/src/cuckoocache.h +++ b/src/cuckoocache.h @@ -12,7 +12,9 @@ #include #include #include +#include #include +#include #include #include @@ -326,7 +328,7 @@ class cache } /** setup initializes the container to store no more than new_size - * elements. + * elements and no less than 2 elements. * * setup should only be called once. * @@ -336,8 +338,8 @@ class cache uint32_t setup(uint32_t new_size) { // depth_limit must be at least one otherwise errors can occur. - depth_limit = static_cast(std::log2(static_cast(std::max((uint32_t)2, new_size)))); size = std::max(2, new_size); + depth_limit = static_cast(std::log2(static_cast(size))); table.resize(size); collection_flags.setup(size); epoch_flags.resize(size); @@ -357,12 +359,21 @@ class cache * * @param bytes the approximate number of bytes to use for this data * structure - * @returns the maximum number of elements storable (see setup() - * documentation for more detail) + * @returns A pair of the maximum number of elements storable (see setup() + * documentation for more detail) and the approxmiate total size of these + * elements in bytes or std::nullopt if the size requested is too large. */ - uint32_t setup_bytes(size_t bytes) + std::optional> setup_bytes(size_t bytes) { - return setup(bytes/sizeof(Element)); + size_t requested_num_elems = bytes / sizeof(Element); + if (std::numeric_limits::max() < requested_num_elems) { + return std::nullopt; + } + + auto num_elems = setup(bytes/sizeof(Element)); + + size_t approx_size_bytes = num_elems * sizeof(Element); + return std::make_pair(num_elems, approx_size_bytes); } /** insert loops at most depth_limit times trying to insert a hash diff --git a/src/init.cpp b/src/init.cpp index bfe1b42ac36e..edfe9277089e 100644 --- a/src/init.cpp +++ b/src/init.cpp @@ -10,6 +10,8 @@ #include +#include + #include #include #include @@ -45,6 +47,7 @@ #include #include #include +#include #include #include #include @@ -138,7 +141,9 @@ #endif using kernel::CoinStatsHashType; +using kernel::ValidationCacheSizes; +using node::ApplyArgsManOptions; using node::CacheSizes; using node::CalculateCacheSizes; using node::ChainstateLoadingError; @@ -763,7 +768,7 @@ void SetupServerArgs(ArgsManager& argsman) argsman.AddArg("-watchquorums=", strprintf("Watch and validate quorum communication (default: %u)", llmq::DEFAULT_WATCH_QUORUMS), ArgsManager::ALLOW_ANY | ArgsManager::DEBUG_ONLY, OptionsCategory::DEBUG_TEST); argsman.AddArg("-capturemessages", "Capture all P2P messages to disk", ArgsManager::ALLOW_ANY | ArgsManager::DEBUG_ONLY, OptionsCategory::DEBUG_TEST); argsman.AddArg("-disablegovernance", strprintf("Disable governance validation (0-1, default: %u)", 0), ArgsManager::ALLOW_ANY, OptionsCategory::DEBUG_TEST); - argsman.AddArg("-maxsigcachesize=", strprintf("Limit sum of signature cache and script execution cache sizes to MiB (default: %u)", DEFAULT_MAX_SIG_CACHE_SIZE), ArgsManager::ALLOW_ANY | ArgsManager::DEBUG_ONLY, OptionsCategory::DEBUG_TEST); + argsman.AddArg("-maxsigcachesize=", strprintf("Limit sum of signature cache and script execution cache sizes to MiB (default: %u)", DEFAULT_MAX_SIG_CACHE_BYTES >> 20), ArgsManager::ALLOW_ANY | ArgsManager::DEBUG_ONLY, OptionsCategory::DEBUG_TEST); argsman.AddArg("-maxtipage=", strprintf("Maximum tip age in seconds to consider node in initial block download (default: %u)", DEFAULT_MAX_TIP_AGE), ArgsManager::ALLOW_ANY | ArgsManager::DEBUG_ONLY, OptionsCategory::DEBUG_TEST); argsman.AddArg("-mocktime=", "Replace actual time with " + UNIX_EPOCH_TIME + " (default: 0)", ArgsManager::ALLOW_ANY | ArgsManager::DEBUG_ONLY, OptionsCategory::DEBUG_TEST); argsman.AddArg("-minsporkkeys=", "Overrides minimum spork signers to change spork value. Only useful for regtest and devnet. Using this on mainnet or testnet will ban you.", ArgsManager::ALLOW_ANY, OptionsCategory::DEBUG_TEST); @@ -1518,8 +1523,13 @@ bool AppInitMain(NodeContext& node, interfaces::BlockAndHeaderTipInfo* tip_info) args.GetArg("-datadir", ""), fs::PathToString(fs::current_path())); } - InitSignatureCache(); - InitScriptExecutionCache(); + ValidationCacheSizes validation_cache_sizes{}; + ApplyArgsManOptions(args, validation_cache_sizes); + if (!InitSignatureCache(validation_cache_sizes.signature_cache_bytes) + || !InitScriptExecutionCache(validation_cache_sizes.script_execution_cache_bytes)) + { + return InitError(strprintf(_("Unable to allocate memory for -maxsigcachesize: '%s' MiB"), args.GetIntArg("-maxsigcachesize", DEFAULT_MAX_SIG_CACHE_BYTES >> 20))); + } int script_threads = args.GetIntArg("-par", DEFAULT_SCRIPTCHECK_THREADS); if (script_threads <= 0) { diff --git a/src/kernel/validation_cache_sizes.h b/src/kernel/validation_cache_sizes.h new file mode 100644 index 000000000000..72e4d1a52cc6 --- /dev/null +++ b/src/kernel/validation_cache_sizes.h @@ -0,0 +1,20 @@ +// Copyright (c) 2022 The Bitcoin Core developers +// Distributed under the MIT software license, see the accompanying +// file COPYING or http://www.opensource.org/licenses/mit-license.php. + +#ifndef BITCOIN_KERNEL_VALIDATION_CACHE_SIZES_H +#define BITCOIN_KERNEL_VALIDATION_CACHE_SIZES_H + +#include