diff options
Diffstat (limited to 'src')
122 files changed, 829 insertions, 291 deletions
diff --git a/src/Makefile.am b/src/Makefile.am index 507e5cbb9f..ff4f071a3c 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -146,6 +146,7 @@ BITCOIN_CORE_H = \ dbwrapper.h \ limitedmap.h \ logging.h \ + logging/timer.h \ memusage.h \ merkleblock.h \ miner.h \ @@ -161,6 +162,7 @@ BITCOIN_CORE_H = \ node/context.h \ node/psbt.h \ node/transaction.h \ + node/utxo_snapshot.h \ noui.h \ optional.h \ outputtype.h \ diff --git a/src/Makefile.bench.include b/src/Makefile.bench.include index fbcab86d8f..c9e4fcc4bc 100644 --- a/src/Makefile.bench.include +++ b/src/Makefile.bench.include @@ -40,10 +40,10 @@ bench_bench_bitcoin_SOURCES = \ bench/lockedpool.cpp \ bench/poly1305.cpp \ bench/prevector.cpp \ - test/lib/transaction_utils.h \ - test/lib/transaction_utils.cpp \ - test/setup_common.h \ - test/setup_common.cpp \ + test/util/transaction_utils.h \ + test/util/transaction_utils.cpp \ + test/util/setup_common.h \ + test/util/setup_common.cpp \ test/util.h \ test/util.cpp diff --git a/src/Makefile.qttest.include b/src/Makefile.qttest.include index c309340fd7..562b393b22 100644 --- a/src/Makefile.qttest.include +++ b/src/Makefile.qttest.include @@ -27,10 +27,10 @@ TEST_QT_H = \ qt/test/wallettests.h TEST_BITCOIN_CPP = \ - test/setup_common.cpp + test/util/setup_common.cpp TEST_BITCOIN_H = \ - test/setup_common.h + test/util/setup_common.h qt_test_test_bitcoin_qt_CPPFLAGS = $(AM_CPPFLAGS) $(BITCOIN_INCLUDES) $(BITCOIN_QT_INCLUDES) \ $(QT_INCLUDES) $(QT_TEST_INCLUDES) diff --git a/src/Makefile.test.include b/src/Makefile.test.include index 48afa815d6..6d2b546a28 100644 --- a/src/Makefile.test.include +++ b/src/Makefile.test.include @@ -57,13 +57,15 @@ RAW_TEST_FILES = GENERATED_TEST_FILES = $(JSON_TEST_FILES:.json=.json.h) $(RAW_TEST_FILES:.raw=.raw.h) BITCOIN_TEST_SUITE = \ - test/lib/blockfilter.cpp \ - test/lib/blockfilter.h \ - test/lib/transaction_utils.cpp \ - test/lib/transaction_utils.h \ + test/util/blockfilter.cpp \ + test/util/blockfilter.h \ + test/util/logging.cpp \ + test/util/logging.h \ + test/util/transaction_utils.cpp \ + test/util/transaction_utils.h \ test/main.cpp \ - test/setup_common.h \ - test/setup_common.cpp \ + test/util/setup_common.h \ + test/util/setup_common.cpp \ test/util/str.h \ test/util/str.cpp @@ -71,8 +73,8 @@ FUZZ_SUITE = \ test/fuzz/fuzz.cpp \ test/fuzz/fuzz.h \ test/fuzz/FuzzedDataProvider.h \ - test/setup_common.cpp \ - test/setup_common.h \ + test/util/setup_common.cpp \ + test/util/setup_common.h \ test/util/str.cpp \ test/util/str.h @@ -125,6 +127,7 @@ BITCOIN_TESTS =\ test/key_io_tests.cpp \ test/key_tests.cpp \ test/limitedmap_tests.cpp \ + test/logging_tests.cpp \ test/dbwrapper_tests.cpp \ test/validation_tests.cpp \ test/mempool_tests.cpp \ diff --git a/src/bench/bench.cpp b/src/bench/bench.cpp index 1b6b1736a9..cc159eb191 100644 --- a/src/bench/bench.cpp +++ b/src/bench/bench.cpp @@ -5,7 +5,7 @@ #include <bench/bench.h> #include <chainparams.h> -#include <test/setup_common.h> +#include <test/util/setup_common.h> #include <validation.h> #include <algorithm> diff --git a/src/bench/verify_script.cpp b/src/bench/verify_script.cpp index c9947f192e..1c025e29d3 100644 --- a/src/bench/verify_script.cpp +++ b/src/bench/verify_script.cpp @@ -10,7 +10,7 @@ #include <script/script.h> #include <script/standard.h> #include <streams.h> -#include <test/lib/transaction_utils.h> +#include <test/util/transaction_utils.h> #include <array> diff --git a/src/bitcoin-cli.cpp b/src/bitcoin-cli.cpp index d7b6891503..592fcbe8dd 100644 --- a/src/bitcoin-cli.cpp +++ b/src/bitcoin-cli.cpp @@ -265,7 +265,7 @@ public: result.pushKV("proxy", batch[ID_NETWORKINFO]["result"]["networks"][0]["proxy"]); result.pushKV("difficulty", batch[ID_BLOCKCHAININFO]["result"]["difficulty"]); result.pushKV("chain", UniValue(batch[ID_BLOCKCHAININFO]["result"]["chain"])); - if (!batch[ID_WALLETINFO].isNull()) { + if (!batch[ID_WALLETINFO]["result"].isNull()) { result.pushKV("walletversion", batch[ID_WALLETINFO]["result"]["walletversion"]); result.pushKV("balance", batch[ID_WALLETINFO]["result"]["balance"]); result.pushKV("keypoololdest", batch[ID_WALLETINFO]["result"]["keypoololdest"]); diff --git a/src/init.cpp b/src/init.cpp index 1a99ca9abc..f02740786d 100644 --- a/src/init.cpp +++ b/src/init.cpp @@ -372,7 +372,7 @@ void SetupServerArgs() gArgs.AddArg("-debuglogfile=<file>", strprintf("Specify location of debug log file. Relative paths will be prefixed by a net-specific datadir location. (-nodebuglogfile to disable; default: %s)", DEFAULT_DEBUGLOGFILE), ArgsManager::ALLOW_ANY, OptionsCategory::OPTIONS); gArgs.AddArg("-feefilter", strprintf("Tell other nodes to filter invs to us by our mempool min fee (default: %u)", DEFAULT_FEEFILTER), ArgsManager::ALLOW_ANY | ArgsManager::DEBUG_ONLY, OptionsCategory::OPTIONS); gArgs.AddArg("-includeconf=<file>", "Specify additional configuration file, relative to the -datadir path (only useable from configuration file, not command line)", ArgsManager::ALLOW_ANY, OptionsCategory::OPTIONS); - gArgs.AddArg("-loadblock=<file>", "Imports blocks from external blk000??.dat file on startup", ArgsManager::ALLOW_ANY, OptionsCategory::OPTIONS); + gArgs.AddArg("-loadblock=<file>", "Imports blocks from external file on startup", ArgsManager::ALLOW_ANY, OptionsCategory::OPTIONS); gArgs.AddArg("-maxmempool=<n>", strprintf("Keep the transaction memory pool below <n> megabytes (default: %u)", DEFAULT_MAX_MEMPOOL_SIZE), ArgsManager::ALLOW_ANY, OptionsCategory::OPTIONS); gArgs.AddArg("-maxorphantx=<n>", strprintf("Keep at most <n> unconnectable transactions in memory (default: %u)", DEFAULT_MAX_ORPHAN_TRANSACTIONS), ArgsManager::ALLOW_ANY, OptionsCategory::OPTIONS); gArgs.AddArg("-mempoolexpiry=<n>", strprintf("Do not keep transactions in the mempool longer than <n> hours (default: %u)", DEFAULT_MEMPOOL_EXPIRY), ArgsManager::ALLOW_ANY, OptionsCategory::OPTIONS); @@ -684,20 +684,6 @@ static void ThreadImport(std::vector<fs::path> vImportFiles) LoadGenesisBlock(chainparams); } - // hardcoded $DATADIR/bootstrap.dat - fs::path pathBootstrap = GetDataDir() / "bootstrap.dat"; - if (fs::exists(pathBootstrap)) { - FILE *file = fsbridge::fopen(pathBootstrap, "rb"); - if (file) { - fs::path pathBootstrapOld = GetDataDir() / "bootstrap.dat.old"; - LogPrintf("Importing bootstrap.dat...\n"); - LoadExternalBlockFile(chainparams, file); - RenameOver(pathBootstrap, pathBootstrapOld); - } else { - LogPrintf("Warning: Could not open bootstrap file %s\n", pathBootstrap.string()); - } - } - // -loadblock= for (const fs::path& path : vImportFiles) { FILE *file = fsbridge::fopen(path, "rb"); @@ -1061,15 +1047,6 @@ bool AppInitParameterInteraction() incrementalRelayFee = CFeeRate(n); } - // -par=0 means autodetect, but nScriptCheckThreads==0 means no concurrency - nScriptCheckThreads = gArgs.GetArg("-par", DEFAULT_SCRIPTCHECK_THREADS); - if (nScriptCheckThreads <= 0) - nScriptCheckThreads += GetNumCores(); - if (nScriptCheckThreads <= 1) - nScriptCheckThreads = 0; - else if (nScriptCheckThreads > MAX_SCRIPTCHECK_THREADS) - nScriptCheckThreads = MAX_SCRIPTCHECK_THREADS; - // block pruning; get the amount of disk space (in MiB) to allot for block & undo files int64_t nPruneArg = gArgs.GetArg("-prune", 0); if (nPruneArg < 0) { @@ -1256,10 +1233,25 @@ bool AppInitMain(NodeContext& node) InitSignatureCache(); InitScriptExecutionCache(); - LogPrintf("Script verification uses %d additional threads\n", std::max(nScriptCheckThreads - 1, 0)); - if (nScriptCheckThreads) { - for (int i=0; i<nScriptCheckThreads-1; i++) + int script_threads = gArgs.GetArg("-par", DEFAULT_SCRIPTCHECK_THREADS); + if (script_threads <= 0) { + // -par=0 means autodetect (number of cores - 1 script threads) + // -par=-n means "leave n cores free" (number of cores - n - 1 script threads) + script_threads += GetNumCores(); + } + + // Subtract 1 because the main thread counts towards the par threads + script_threads = std::max(script_threads - 1, 0); + + // Number of script-checking threads <= MAX_SCRIPTCHECK_THREADS + script_threads = std::min(script_threads, MAX_SCRIPTCHECK_THREADS); + + LogPrintf("Script verification uses %d additional threads\n", script_threads); + if (script_threads >= 1) { + g_parallel_script_checks = true; + for (int i = 0; i < script_threads; ++i) { threadGroup.create_thread([i]() { return ThreadScriptCheck(i); }); + } } // Start the lightweight task scheduler thread diff --git a/src/logging.cpp b/src/logging.cpp index 60ab486198..b01177f23f 100644 --- a/src/logging.cpp +++ b/src/logging.cpp @@ -67,6 +67,9 @@ bool BCLog::Logger::StartLogging() if (m_print_to_file) FileWriteStr(s, m_fileout); if (m_print_to_console) fwrite(s.data(), 1, s.size(), stdout); + for (const auto& cb : m_print_callbacks) { + cb(s); + } m_msgs_before_open.pop_front(); } @@ -81,6 +84,7 @@ void BCLog::Logger::DisconnectTestLogger() m_buffering = true; if (m_fileout != nullptr) fclose(m_fileout); m_fileout = nullptr; + m_print_callbacks.clear(); } void BCLog::Logger::EnableCategory(BCLog::LogFlags flag) @@ -270,6 +274,9 @@ void BCLog::Logger::LogPrintStr(const std::string& str) fwrite(str_prefixed.data(), 1, str_prefixed.size(), stdout); fflush(stdout); } + for (const auto& cb : m_print_callbacks) { + cb(str_prefixed); + } if (m_print_to_file) { assert(m_fileout != nullptr); diff --git a/src/logging.h b/src/logging.h index e37c0c823b..9ed41c2b98 100644 --- a/src/logging.h +++ b/src/logging.h @@ -77,6 +77,9 @@ namespace BCLog { std::string LogTimestampStr(const std::string& str); + /** Slots that connect to the print signal */ + std::list<std::function<void(const std::string&)>> m_print_callbacks /* GUARDED_BY(m_cs) */ {}; + public: bool m_print_to_console = false; bool m_print_to_file = false; @@ -95,7 +98,22 @@ namespace BCLog { bool Enabled() const { std::lock_guard<std::mutex> scoped_lock(m_cs); - return m_buffering || m_print_to_console || m_print_to_file; + return m_buffering || m_print_to_console || m_print_to_file || !m_print_callbacks.empty(); + } + + /** Connect a slot to the print signal and return the connection */ + std::list<std::function<void(const std::string&)>>::iterator PushBackCallback(std::function<void(const std::string&)> fun) + { + std::lock_guard<std::mutex> scoped_lock(m_cs); + m_print_callbacks.push_back(std::move(fun)); + return --m_print_callbacks.end(); + } + + /** Delete a connection */ + void DeleteCallback(std::list<std::function<void(const std::string&)>>::iterator it) + { + std::lock_guard<std::mutex> scoped_lock(m_cs); + m_print_callbacks.erase(it); } /** Start logging (and flush all buffered messages) */ diff --git a/src/logging/timer.h b/src/logging/timer.h new file mode 100644 index 0000000000..34dbb942c5 --- /dev/null +++ b/src/logging/timer.h @@ -0,0 +1,104 @@ +// Copyright (c) 2009-2010 Satoshi Nakamoto +// Copyright (c) 2009-2018 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_LOGGING_TIMER_H +#define BITCOIN_LOGGING_TIMER_H + +#include <logging.h> +#include <util/macros.h> +#include <util/time.h> + +#include <chrono> +#include <string> + + +namespace BCLog { + +//! RAII-style object that outputs timing information to logs. +template <typename TimeType> +class Timer +{ +public: + //! If log_category is left as the default, end_msg will log unconditionally + //! (instead of being filtered by category). + Timer( + std::string prefix, + std::string end_msg, + BCLog::LogFlags log_category = BCLog::LogFlags::ALL) : + m_prefix(std::move(prefix)), + m_title(std::move(end_msg)), + m_log_category(log_category) + { + this->Log(strprintf("%s started", m_title)); + m_start_t = GetTime<std::chrono::microseconds>(); + } + + ~Timer() + { + this->Log(strprintf("%s completed", m_title)); + } + + void Log(const std::string& msg) + { + const std::string full_msg = this->LogMsg(msg); + + if (m_log_category == BCLog::LogFlags::ALL) { + LogPrintf("%s\n", full_msg); + } else { + LogPrint(m_log_category, "%s\n", full_msg); + } + } + + std::string LogMsg(const std::string& msg) + { + const auto end_time = GetTime<std::chrono::microseconds>() - m_start_t; + if (m_start_t.count() <= 0) { + return strprintf("%s: %s", m_prefix, msg); + } + + std::string units = ""; + float divisor = 1; + + if (std::is_same<TimeType, std::chrono::microseconds>::value) { + units = "μs"; + } else if (std::is_same<TimeType, std::chrono::milliseconds>::value) { + units = "ms"; + divisor = 1000.; + } else if (std::is_same<TimeType, std::chrono::seconds>::value) { + units = "s"; + divisor = 1000. * 1000.; + } + + const float time_ms = end_time.count() / divisor; + return strprintf("%s: %s (%.2f%s)", m_prefix, msg, time_ms, units); + } + +private: + std::chrono::microseconds m_start_t{}; + + //! Log prefix; usually the name of the function this was created in. + const std::string m_prefix{}; + + //! A descriptive message of what is being timed. + const std::string m_title{}; + + //! Forwarded on to LogPrint if specified - has the effect of only + //! outputing the timing log when a particular debug= category is specified. + const BCLog::LogFlags m_log_category{}; + +}; + +} // namespace BCLog + + +#define LOG_TIME_MICROS(end_msg, ...) \ + BCLog::Timer<std::chrono::microseconds> PASTE2(logging_timer, __COUNTER__)(__func__, end_msg, ## __VA_ARGS__) +#define LOG_TIME_MILLIS(end_msg, ...) \ + BCLog::Timer<std::chrono::milliseconds> PASTE2(logging_timer, __COUNTER__)(__func__, end_msg, ## __VA_ARGS__) +#define LOG_TIME_SECONDS(end_msg, ...) \ + BCLog::Timer<std::chrono::seconds> PASTE2(logging_timer, __COUNTER__)(__func__, end_msg, ## __VA_ARGS__) + + +#endif // BITCOIN_LOGGING_TIMER_H diff --git a/src/node/coinstats.cpp b/src/node/coinstats.cpp index 57fa158ad2..a818f06d51 100644 --- a/src/node/coinstats.cpp +++ b/src/node/coinstats.cpp @@ -14,9 +14,6 @@ #include <map> -#include <boost/thread.hpp> - - static void ApplyStats(CCoinsStats &stats, CHashWriter& ss, const uint256& hash, const std::map<uint32_t, Coin>& outputs) { assert(!outputs.empty()); @@ -38,6 +35,7 @@ static void ApplyStats(CCoinsStats &stats, CHashWriter& ss, const uint256& hash, //! Calculate statistics about the unspent transaction output set bool GetUTXOStats(CCoinsView *view, CCoinsStats &stats) { + stats = CCoinsStats(); std::unique_ptr<CCoinsViewCursor> pcursor(view->Cursor()); assert(pcursor); @@ -51,7 +49,6 @@ bool GetUTXOStats(CCoinsView *view, CCoinsStats &stats) uint256 prevkey; std::map<uint32_t, Coin> outputs; while (pcursor->Valid()) { - boost::this_thread::interruption_point(); COutPoint key; Coin coin; if (pcursor->GetKey(key) && pcursor->GetValue(coin)) { @@ -61,6 +58,7 @@ bool GetUTXOStats(CCoinsView *view, CCoinsStats &stats) } prevkey = key.hash; outputs[key.n] = std::move(coin); + stats.coins_count++; } else { return error("%s: unable to read value", __func__); } diff --git a/src/node/coinstats.h b/src/node/coinstats.h index 7c11aab8bd..a19af0fd1b 100644 --- a/src/node/coinstats.h +++ b/src/node/coinstats.h @@ -15,16 +15,17 @@ class CCoinsView; struct CCoinsStats { - int nHeight; - uint256 hashBlock; - uint64_t nTransactions; - uint64_t nTransactionOutputs; - uint64_t nBogoSize; - uint256 hashSerialized; - uint64_t nDiskSize; - CAmount nTotalAmount; - - CCoinsStats() : nHeight(0), nTransactions(0), nTransactionOutputs(0), nBogoSize(0), nDiskSize(0), nTotalAmount(0) {} + int nHeight{0}; + uint256 hashBlock{}; + uint64_t nTransactions{0}; + uint64_t nTransactionOutputs{0}; + uint64_t nBogoSize{0}; + uint256 hashSerialized{}; + uint64_t nDiskSize{0}; + CAmount nTotalAmount{0}; + + //! The number of coins contained. + uint64_t coins_count{0}; }; //! Calculate statistics about the unspent transaction output set diff --git a/src/node/utxo_snapshot.h b/src/node/utxo_snapshot.h new file mode 100644 index 0000000000..702a0cbe53 --- /dev/null +++ b/src/node/utxo_snapshot.h @@ -0,0 +1,50 @@ +// Copyright (c) 2009-2010 Satoshi Nakamoto +// Copyright (c) 2009-2019 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_NODE_UTXO_SNAPSHOT_H +#define BITCOIN_NODE_UTXO_SNAPSHOT_H + +#include <uint256.h> +#include <serialize.h> + +//! Metadata describing a serialized version of a UTXO set from which an +//! assumeutxo CChainState can be constructed. +class SnapshotMetadata +{ +public: + //! The hash of the block that reflects the tip of the chain for the + //! UTXO set contained in this snapshot. + uint256 m_base_blockhash; + + //! The number of coins in the UTXO set contained in this snapshot. Used + //! during snapshot load to estimate progress of UTXO set reconstruction. + uint64_t m_coins_count = 0; + + //! Necessary to "fake" the base nChainTx so that we can estimate progress during + //! initial block download for the assumeutxo chainstate. + unsigned int m_nchaintx = 0; + + SnapshotMetadata() { } + SnapshotMetadata( + const uint256& base_blockhash, + uint64_t coins_count, + unsigned int nchaintx) : + m_base_blockhash(base_blockhash), + m_coins_count(coins_count), + m_nchaintx(nchaintx) { } + + ADD_SERIALIZE_METHODS; + + template <typename Stream, typename Operation> + inline void SerializationOp(Stream& s, Operation ser_action) + { + READWRITE(m_base_blockhash); + READWRITE(m_coins_count); + READWRITE(m_nchaintx); + } + +}; + +#endif // BITCOIN_NODE_UTXO_SNAPSHOT_H diff --git a/src/noui.cpp b/src/noui.cpp index 11c8f1e13d..a5b7a2d591 100644 --- a/src/noui.cpp +++ b/src/noui.cpp @@ -66,28 +66,31 @@ void noui_connect() noui_InitMessageConn = uiInterface.InitMessage_connect(noui_InitMessage); } -bool noui_ThreadSafeMessageBoxSuppressed(const std::string& message, const std::string& caption, unsigned int style) +bool noui_ThreadSafeMessageBoxRedirect(const std::string& message, const std::string& caption, unsigned int style) { + LogPrintf("%s: %s\n", caption, message); return false; } -bool noui_ThreadSafeQuestionSuppressed(const std::string& /* ignored interactive message */, const std::string& message, const std::string& caption, unsigned int style) +bool noui_ThreadSafeQuestionRedirect(const std::string& /* ignored interactive message */, const std::string& message, const std::string& caption, unsigned int style) { + LogPrintf("%s: %s\n", caption, message); return false; } -void noui_InitMessageSuppressed(const std::string& message) +void noui_InitMessageRedirect(const std::string& message) { + LogPrintf("init message: %s\n", message); } -void noui_suppress() +void noui_test_redirect() { noui_ThreadSafeMessageBoxConn.disconnect(); noui_ThreadSafeQuestionConn.disconnect(); noui_InitMessageConn.disconnect(); - noui_ThreadSafeMessageBoxConn = uiInterface.ThreadSafeMessageBox_connect(noui_ThreadSafeMessageBoxSuppressed); - noui_ThreadSafeQuestionConn = uiInterface.ThreadSafeQuestion_connect(noui_ThreadSafeQuestionSuppressed); - noui_InitMessageConn = uiInterface.InitMessage_connect(noui_InitMessageSuppressed); + noui_ThreadSafeMessageBoxConn = uiInterface.ThreadSafeMessageBox_connect(noui_ThreadSafeMessageBoxRedirect); + noui_ThreadSafeQuestionConn = uiInterface.ThreadSafeQuestion_connect(noui_ThreadSafeQuestionRedirect); + noui_InitMessageConn = uiInterface.InitMessage_connect(noui_InitMessageRedirect); } void noui_reconnect() diff --git a/src/noui.h b/src/noui.h index 854aeeacca..621e9c2798 100644 --- a/src/noui.h +++ b/src/noui.h @@ -17,10 +17,10 @@ void noui_InitMessage(const std::string& message); /** Connect all bitcoind signal handlers */ void noui_connect(); -/** Suppress all bitcoind signal handlers. Used to suppress output during test runs that produce expected errors */ -void noui_suppress(); +/** Redirect all bitcoind signal handlers to LogPrintf. Used to check or suppress output during test runs that produce expected errors */ +void noui_test_redirect(); -/** Reconnects the regular Non-GUI handlers after having used noui_suppress */ +/** Reconnects the regular Non-GUI handlers after having used noui_test_redirect */ void noui_reconnect(); #endif // BITCOIN_NOUI_H diff --git a/src/qt/forms/sendcoinsdialog.ui b/src/qt/forms/sendcoinsdialog.ui index 386d559281..7190d59240 100644 --- a/src/qt/forms/sendcoinsdialog.ui +++ b/src/qt/forms/sendcoinsdialog.ui @@ -797,7 +797,7 @@ <item> <widget class="QPushButton" name="buttonMinimizeFee"> <property name="toolTip"> - <string>collapse fee-settings</string> + <string>Hide transaction fee settings</string> </property> <property name="text"> <string>Hide</string> diff --git a/src/qt/test/addressbooktests.cpp b/src/qt/test/addressbooktests.cpp index 8b32b70d1e..6e8d383847 100644 --- a/src/qt/test/addressbooktests.cpp +++ b/src/qt/test/addressbooktests.cpp @@ -1,6 +1,6 @@ #include <qt/test/addressbooktests.h> #include <qt/test/util.h> -#include <test/setup_common.h> +#include <test/util/setup_common.h> #include <interfaces/chain.h> #include <interfaces/node.h> diff --git a/src/qt/test/apptests.cpp b/src/qt/test/apptests.cpp index e730c8f6d5..664826ecf2 100644 --- a/src/qt/test/apptests.cpp +++ b/src/qt/test/apptests.cpp @@ -11,7 +11,7 @@ #include <qt/networkstyle.h> #include <qt/rpcconsole.h> #include <shutdown.h> -#include <test/setup_common.h> +#include <test/util/setup_common.h> #include <univalue.h> #include <validation.h> diff --git a/src/qt/test/rpcnestedtests.cpp b/src/qt/test/rpcnestedtests.cpp index 1772de4c1b..971d9f4a7c 100644 --- a/src/qt/test/rpcnestedtests.cpp +++ b/src/qt/test/rpcnestedtests.cpp @@ -7,7 +7,7 @@ #include <interfaces/node.h> #include <rpc/server.h> #include <qt/rpcconsole.h> -#include <test/setup_common.h> +#include <test/util/setup_common.h> #include <univalue.h> #include <util/system.h> diff --git a/src/qt/test/test_main.cpp b/src/qt/test/test_main.cpp index e6870cf1be..243c10d7da 100644 --- a/src/qt/test/test_main.cpp +++ b/src/qt/test/test_main.cpp @@ -12,7 +12,7 @@ #include <qt/test/rpcnestedtests.h> #include <qt/test/uritests.h> #include <qt/test/compattests.h> -#include <test/setup_common.h> +#include <test/util/setup_common.h> #ifdef ENABLE_WALLET #include <qt/test/addressbooktests.h> diff --git a/src/qt/test/wallettests.cpp b/src/qt/test/wallettests.cpp index 6e009145a2..980de711db 100644 --- a/src/qt/test/wallettests.cpp +++ b/src/qt/test/wallettests.cpp @@ -13,7 +13,7 @@ #include <qt/transactionview.h> #include <qt/walletmodel.h> #include <key_io.h> -#include <test/setup_common.h> +#include <test/util/setup_common.h> #include <validation.h> #include <wallet/wallet.h> #include <qt/overviewpage.h> diff --git a/src/rpc/blockchain.cpp b/src/rpc/blockchain.cpp index d08f852751..2f4b4412f5 100644 --- a/src/rpc/blockchain.cpp +++ b/src/rpc/blockchain.cpp @@ -15,6 +15,7 @@ #include <hash.h> #include <index/blockfilterindex.h> #include <node/coinstats.h> +#include <node/utxo_snapshot.h> #include <policy/feerate.h> #include <policy/policy.h> #include <policy/rbf.h> @@ -38,8 +39,6 @@ #include <univalue.h> -#include <boost/thread/thread.hpp> // boost::thread::interrupt - #include <condition_variable> #include <memory> #include <mutex> @@ -1975,7 +1974,6 @@ bool FindScriptPubKey(std::atomic<int>& scan_progress, const std::atomic<bool>& Coin coin; if (!cursor->GetKey(key) || !cursor->GetValue(coin)) return false; if (++count % 8192 == 0) { - boost::this_thread::interruption_point(); if (should_abort) { // allow to abort the scan via the abort reference return false; @@ -2245,6 +2243,113 @@ static UniValue getblockfilter(const JSONRPCRequest& request) return ret; } +/** + * Serialize the UTXO set to a file for loading elsewhere. + * + * @see SnapshotMetadata + */ +UniValue dumptxoutset(const JSONRPCRequest& request) +{ + RPCHelpMan{ + "dumptxoutset", + "\nWrite the serialized UTXO set to disk.\n" + "Incidentally flushes the latest coinsdb (leveldb) to disk.\n", + { + {"path", + RPCArg::Type::STR, + RPCArg::Optional::NO, + /* default_val */ "", + "path to the output file. If relative, will be prefixed by datadir."}, + }, + RPCResult{ + "{\n" + " \"coins_written\": n, (numeric) the number of coins written in the snapshot\n" + " \"base_hash\": \"...\", (string) the hash of the base of the snapshot\n" + " \"base_height\": n, (string) the height of the base of the snapshot\n" + " \"path\": \"...\" (string) the absolute path that the snapshot was written to\n" + "]\n" + }, + RPCExamples{ + HelpExampleCli("dumptxoutset", "utxo.dat") + } + }.Check(request); + + fs::path path = fs::absolute(request.params[0].get_str(), GetDataDir()); + // Write to a temporary path and then move into `path` on completion + // to avoid confusion due to an interruption. + fs::path temppath = fs::absolute(request.params[0].get_str() + ".incomplete", GetDataDir()); + + if (fs::exists(path)) { + throw JSONRPCError( + RPC_INVALID_PARAMETER, + path.string() + " already exists. If you are sure this is what you want, " + "move it out of the way first"); + } + + FILE* file{fsbridge::fopen(temppath, "wb")}; + CAutoFile afile{file, SER_DISK, CLIENT_VERSION}; + std::unique_ptr<CCoinsViewCursor> pcursor; + CCoinsStats stats; + CBlockIndex* tip; + + { + // We need to lock cs_main to ensure that the coinsdb isn't written to + // between (i) flushing coins cache to disk (coinsdb), (ii) getting stats + // based upon the coinsdb, and (iii) constructing a cursor to the + // coinsdb for use below this block. + // + // Cursors returned by leveldb iterate over snapshots, so the contents + // of the pcursor will not be affected by simultaneous writes during + // use below this block. + // + // See discussion here: + // https://github.com/bitcoin/bitcoin/pull/15606#discussion_r274479369 + // + LOCK(::cs_main); + + ::ChainstateActive().ForceFlushStateToDisk(); + + if (!GetUTXOStats(&::ChainstateActive().CoinsDB(), stats)) { + throw JSONRPCError(RPC_INTERNAL_ERROR, "Unable to read UTXO set"); + } + + pcursor = std::unique_ptr<CCoinsViewCursor>(::ChainstateActive().CoinsDB().Cursor()); + tip = LookupBlockIndex(stats.hashBlock); + CHECK_NONFATAL(tip); + } + + SnapshotMetadata metadata{tip->GetBlockHash(), stats.coins_count, tip->nChainTx}; + + afile << metadata; + + COutPoint key; + Coin coin; + unsigned int iter{0}; + + while (pcursor->Valid()) { + if (iter % 5000 == 0 && !IsRPCRunning()) { + throw JSONRPCError(RPC_CLIENT_NOT_CONNECTED, "Shutting down"); + } + ++iter; + if (pcursor->GetKey(key) && pcursor->GetValue(coin)) { + afile << key; + afile << coin; + } + + pcursor->Next(); + } + + afile.fclose(); + fs::rename(temppath, path); + + UniValue result(UniValue::VOBJ); + result.pushKV("coins_written", stats.coins_count); + result.pushKV("base_hash", tip->GetBlockHash().ToString()); + result.pushKV("base_height", tip->nHeight); + result.pushKV("path", path.string()); + return result; +} + // clang-format off static const CRPCCommand commands[] = { // category name actor (function) argNames @@ -2281,6 +2386,7 @@ static const CRPCCommand commands[] = { "hidden", "waitforblock", &waitforblock, {"blockhash","timeout"} }, { "hidden", "waitforblockheight", &waitforblockheight, {"height","timeout"} }, { "hidden", "syncwithvalidationinterfacequeue", &syncwithvalidationinterfacequeue, {} }, + { "hidden", "dumptxoutset", &dumptxoutset, {"path"} }, }; // clang-format on diff --git a/src/test/README.md b/src/test/README.md index 96dcb072bc..731720f654 100644 --- a/src/test/README.md +++ b/src/test/README.md @@ -7,8 +7,8 @@ configure some other framework (we want as few impediments to creating unit tests as possible). The build system is set up to compile an executable called `test_bitcoin` -that runs all of the unit tests. The main source file is called -`setup_common.cpp`. +that runs all of the unit tests. The main source file for the test library is found in +`util/setup_common.cpp`. ### Compiling/running unit tests diff --git a/src/test/addrman_tests.cpp b/src/test/addrman_tests.cpp index da0abd495a..c034216bc1 100644 --- a/src/test/addrman_tests.cpp +++ b/src/test/addrman_tests.cpp @@ -2,7 +2,7 @@ // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. #include <addrman.h> -#include <test/setup_common.h> +#include <test/util/setup_common.h> #include <string> #include <boost/test/unit_test.hpp> diff --git a/src/test/allocator_tests.cpp b/src/test/allocator_tests.cpp index e333763f27..d33d668a04 100644 --- a/src/test/allocator_tests.cpp +++ b/src/test/allocator_tests.cpp @@ -5,7 +5,7 @@ #include <util/memory.h> #include <util/system.h> -#include <test/setup_common.h> +#include <test/util/setup_common.h> #include <memory> diff --git a/src/test/amount_tests.cpp b/src/test/amount_tests.cpp index 378fe285d5..e20900ed13 100644 --- a/src/test/amount_tests.cpp +++ b/src/test/amount_tests.cpp @@ -4,7 +4,7 @@ #include <amount.h> #include <policy/feerate.h> -#include <test/setup_common.h> +#include <test/util/setup_common.h> #include <boost/test/unit_test.hpp> diff --git a/src/test/arith_uint256_tests.cpp b/src/test/arith_uint256_tests.cpp index 9ac87261b6..3723a48903 100644 --- a/src/test/arith_uint256_tests.cpp +++ b/src/test/arith_uint256_tests.cpp @@ -11,7 +11,7 @@ #include <uint256.h> #include <arith_uint256.h> #include <string> -#include <test/setup_common.h> +#include <test/util/setup_common.h> BOOST_FIXTURE_TEST_SUITE(arith_uint256_tests, BasicTestingSetup) diff --git a/src/test/base32_tests.cpp b/src/test/base32_tests.cpp index b3bed2434c..bd6ece935b 100644 --- a/src/test/base32_tests.cpp +++ b/src/test/base32_tests.cpp @@ -3,7 +3,7 @@ // file COPYING or http://www.opensource.org/licenses/mit-license.php. #include <util/strencodings.h> -#include <test/setup_common.h> +#include <test/util/setup_common.h> #include <boost/test/unit_test.hpp> diff --git a/src/test/base58_tests.cpp b/src/test/base58_tests.cpp index cb376cddb6..52301f799a 100644 --- a/src/test/base58_tests.cpp +++ b/src/test/base58_tests.cpp @@ -5,7 +5,7 @@ #include <test/data/base58_encode_decode.json.h> #include <base58.h> -#include <test/setup_common.h> +#include <test/util/setup_common.h> #include <util/strencodings.h> #include <univalue.h> diff --git a/src/test/base64_tests.cpp b/src/test/base64_tests.cpp index 9ffffb0b7d..a5fed55504 100644 --- a/src/test/base64_tests.cpp +++ b/src/test/base64_tests.cpp @@ -3,7 +3,7 @@ // file COPYING or http://www.opensource.org/licenses/mit-license.php. #include <util/strencodings.h> -#include <test/setup_common.h> +#include <test/util/setup_common.h> #include <boost/test/unit_test.hpp> diff --git a/src/test/bech32_tests.cpp b/src/test/bech32_tests.cpp index a1dabee579..a2098f4f56 100644 --- a/src/test/bech32_tests.cpp +++ b/src/test/bech32_tests.cpp @@ -3,7 +3,7 @@ // file COPYING or http://www.opensource.org/licenses/mit-license.php. #include <bech32.h> -#include <test/setup_common.h> +#include <test/util/setup_common.h> #include <test/util/str.h> #include <boost/test/unit_test.hpp> diff --git a/src/test/bip32_tests.cpp b/src/test/bip32_tests.cpp index e46cf624cf..53df032252 100644 --- a/src/test/bip32_tests.cpp +++ b/src/test/bip32_tests.cpp @@ -9,7 +9,7 @@ #include <key_io.h> #include <streams.h> #include <util/strencodings.h> -#include <test/setup_common.h> +#include <test/util/setup_common.h> #include <string> #include <vector> diff --git a/src/test/blockchain_tests.cpp b/src/test/blockchain_tests.cpp index ca75563ef0..29935c09f8 100644 --- a/src/test/blockchain_tests.cpp +++ b/src/test/blockchain_tests.cpp @@ -4,7 +4,7 @@ #include <chain.h> #include <rpc/blockchain.h> -#include <test/setup_common.h> +#include <test/util/setup_common.h> /* Equality between doubles is imprecise. Comparison should be done * with a small threshold of tolerance, rather than exact equality. diff --git a/src/test/blockencodings_tests.cpp b/src/test/blockencodings_tests.cpp index df589b63bf..8694891a51 100644 --- a/src/test/blockencodings_tests.cpp +++ b/src/test/blockencodings_tests.cpp @@ -8,7 +8,7 @@ #include <pow.h> #include <streams.h> -#include <test/setup_common.h> +#include <test/util/setup_common.h> #include <boost/test/unit_test.hpp> diff --git a/src/test/blockfilter_index_tests.cpp b/src/test/blockfilter_index_tests.cpp index acc6d6a21b..2b616f4c2b 100644 --- a/src/test/blockfilter_index_tests.cpp +++ b/src/test/blockfilter_index_tests.cpp @@ -9,8 +9,8 @@ #include <miner.h> #include <pow.h> #include <script/standard.h> -#include <test/lib/blockfilter.h> -#include <test/setup_common.h> +#include <test/util/blockfilter.h> +#include <test/util/setup_common.h> #include <util/time.h> #include <validation.h> diff --git a/src/test/blockfilter_tests.cpp b/src/test/blockfilter_tests.cpp index df0a041e0e..e69503ef35 100644 --- a/src/test/blockfilter_tests.cpp +++ b/src/test/blockfilter_tests.cpp @@ -3,7 +3,7 @@ // file COPYING or http://www.opensource.org/licenses/mit-license.php. #include <test/data/blockfilters.json.h> -#include <test/setup_common.h> +#include <test/util/setup_common.h> #include <blockfilter.h> #include <core_io.h> diff --git a/src/test/bloom_tests.cpp b/src/test/bloom_tests.cpp index 4421494007..4a7ad9b38b 100644 --- a/src/test/bloom_tests.cpp +++ b/src/test/bloom_tests.cpp @@ -15,7 +15,7 @@ #include <uint256.h> #include <util/system.h> #include <util/strencodings.h> -#include <test/setup_common.h> +#include <test/util/setup_common.h> #include <vector> @@ -461,7 +461,7 @@ static std::vector<unsigned char> RandomData() BOOST_AUTO_TEST_CASE(rolling_bloom) { - SeedInsecureRand(/* deterministic */ true); + SeedInsecureRand(SeedRand::ZEROS); g_mock_deterministic_tests = true; // last-100-entry, 1% false positive: diff --git a/src/test/bswap_tests.cpp b/src/test/bswap_tests.cpp index 8fd4e5d5d6..d5e2344a8b 100644 --- a/src/test/bswap_tests.cpp +++ b/src/test/bswap_tests.cpp @@ -3,7 +3,7 @@ // file COPYING or http://www.opensource.org/licenses/mit-license.php. #include <compat/byteswap.h> -#include <test/setup_common.h> +#include <test/util/setup_common.h> #include <boost/test/unit_test.hpp> diff --git a/src/test/checkqueue_tests.cpp b/src/test/checkqueue_tests.cpp index d796444419..6745bb9015 100644 --- a/src/test/checkqueue_tests.cpp +++ b/src/test/checkqueue_tests.cpp @@ -5,9 +5,8 @@ #include <util/memory.h> #include <util/system.h> #include <util/time.h> -#include <validation.h> -#include <test/setup_common.h> +#include <test/util/setup_common.h> #include <checkqueue.h> #include <boost/test/unit_test.hpp> #include <boost/thread.hpp> @@ -19,11 +18,10 @@ #include <unordered_set> -// BasicTestingSetup not sufficient because nScriptCheckThreads is not set -// otherwise. BOOST_FIXTURE_TEST_SUITE(checkqueue_tests, TestingSetup) static const unsigned int QUEUE_BATCH_SIZE = 128; +static const int SCRIPT_CHECK_THREADS = 3; struct FakeCheck { bool operator()() @@ -149,7 +147,7 @@ static void Correct_Queue_range(std::vector<size_t> range) { auto small_queue = MakeUnique<Correct_Queue>(QUEUE_BATCH_SIZE); boost::thread_group tg; - for (auto x = 0; x < nScriptCheckThreads; ++x) { + for (auto x = 0; x < SCRIPT_CHECK_THREADS; ++x) { tg.create_thread([&]{small_queue->Thread();}); } // Make vChecks here to save on malloc (this test can be slow...) @@ -214,7 +212,7 @@ BOOST_AUTO_TEST_CASE(test_CheckQueue_Catches_Failure) auto fail_queue = MakeUnique<Failing_Queue>(QUEUE_BATCH_SIZE); boost::thread_group tg; - for (auto x = 0; x < nScriptCheckThreads; ++x) { + for (auto x = 0; x < SCRIPT_CHECK_THREADS; ++x) { tg.create_thread([&]{fail_queue->Thread();}); } @@ -246,7 +244,7 @@ BOOST_AUTO_TEST_CASE(test_CheckQueue_Recovers_From_Failure) { auto fail_queue = MakeUnique<Failing_Queue>(QUEUE_BATCH_SIZE); boost::thread_group tg; - for (auto x = 0; x < nScriptCheckThreads; ++x) { + for (auto x = 0; x < SCRIPT_CHECK_THREADS; ++x) { tg.create_thread([&]{fail_queue->Thread();}); } @@ -274,7 +272,7 @@ BOOST_AUTO_TEST_CASE(test_CheckQueue_UniqueCheck) { auto queue = MakeUnique<Unique_Queue>(QUEUE_BATCH_SIZE); boost::thread_group tg; - for (auto x = 0; x < nScriptCheckThreads; ++x) { + for (auto x = 0; x < SCRIPT_CHECK_THREADS; ++x) { tg.create_thread([&]{queue->Thread();}); } @@ -310,7 +308,7 @@ BOOST_AUTO_TEST_CASE(test_CheckQueue_Memory) { auto queue = MakeUnique<Memory_Queue>(QUEUE_BATCH_SIZE); boost::thread_group tg; - for (auto x = 0; x < nScriptCheckThreads; ++x) { + for (auto x = 0; x < SCRIPT_CHECK_THREADS; ++x) { tg.create_thread([&]{queue->Thread();}); } for (size_t i = 0; i < 1000; ++i) { @@ -342,7 +340,7 @@ BOOST_AUTO_TEST_CASE(test_CheckQueue_FrozenCleanup) auto queue = MakeUnique<FrozenCleanup_Queue>(QUEUE_BATCH_SIZE); boost::thread_group tg; bool fails = false; - for (auto x = 0; x < nScriptCheckThreads; ++x) { + for (auto x = 0; x < SCRIPT_CHECK_THREADS; ++x) { tg.create_thread([&]{queue->Thread();}); } std::thread t0([&]() { diff --git a/src/test/coins_tests.cpp b/src/test/coins_tests.cpp index 948591196c..436c1bffa0 100644 --- a/src/test/coins_tests.cpp +++ b/src/test/coins_tests.cpp @@ -7,7 +7,7 @@ #include <coins.h> #include <script/standard.h> #include <streams.h> -#include <test/setup_common.h> +#include <test/util/setup_common.h> #include <uint256.h> #include <undo.h> #include <util/strencodings.h> @@ -279,7 +279,7 @@ UtxoData::iterator FindRandomFrom(const std::set<COutPoint> &utxoSet) { // has the expected effect (the other duplicate is overwritten at all cache levels) BOOST_AUTO_TEST_CASE(updatecoins_simulation_test) { - SeedInsecureRand(/* deterministic */ true); + SeedInsecureRand(SeedRand::ZEROS); g_mock_deterministic_tests = true; bool spent_a_duplicate_coinbase = false; diff --git a/src/test/compilerbug_tests.cpp b/src/test/compilerbug_tests.cpp index 74e1eac3ea..1a6fcda009 100644 --- a/src/test/compilerbug_tests.cpp +++ b/src/test/compilerbug_tests.cpp @@ -2,7 +2,7 @@ // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. -#include <test/setup_common.h> +#include <test/util/setup_common.h> #include <boost/test/unit_test.hpp> BOOST_FIXTURE_TEST_SUITE(compilerbug_tests, BasicTestingSetup) diff --git a/src/test/compress_tests.cpp b/src/test/compress_tests.cpp index c6a08b293f..22eae91cf0 100644 --- a/src/test/compress_tests.cpp +++ b/src/test/compress_tests.cpp @@ -3,7 +3,7 @@ // file COPYING or http://www.opensource.org/licenses/mit-license.php. #include <compressor.h> -#include <test/setup_common.h> +#include <test/util/setup_common.h> #include <script/standard.h> #include <stdint.h> diff --git a/src/test/crypto_tests.cpp b/src/test/crypto_tests.cpp index 4ac12bf969..591a317d17 100644 --- a/src/test/crypto_tests.cpp +++ b/src/test/crypto_tests.cpp @@ -15,7 +15,7 @@ #include <crypto/sha512.h> #include <random.h> #include <util/strencodings.h> -#include <test/setup_common.h> +#include <test/util/setup_common.h> #include <vector> diff --git a/src/test/cuckoocache_tests.cpp b/src/test/cuckoocache_tests.cpp index a3017da3e7..119d4b3295 100644 --- a/src/test/cuckoocache_tests.cpp +++ b/src/test/cuckoocache_tests.cpp @@ -4,7 +4,7 @@ #include <boost/test/unit_test.hpp> #include <cuckoocache.h> #include <script/sigcache.h> -#include <test/setup_common.h> +#include <test/util/setup_common.h> #include <random.h> #include <thread> @@ -29,7 +29,7 @@ BOOST_AUTO_TEST_SUITE(cuckoocache_tests); */ BOOST_AUTO_TEST_CASE(test_cuckoocache_no_fakes) { - SeedInsecureRand(true); + SeedInsecureRand(SeedRand::ZEROS); CuckooCache::cache<uint256, SignatureCacheHasher> cc{}; size_t megabytes = 4; cc.setup_bytes(megabytes << 20); @@ -47,7 +47,7 @@ BOOST_AUTO_TEST_CASE(test_cuckoocache_no_fakes) template <typename Cache> static double test_cache(size_t megabytes, double load) { - SeedInsecureRand(true); + SeedInsecureRand(SeedRand::ZEROS); std::vector<uint256> hashes; Cache set{}; size_t bytes = megabytes * (1 << 20); @@ -118,7 +118,7 @@ template <typename Cache> static void test_cache_erase(size_t megabytes) { double load = 1; - SeedInsecureRand(true); + SeedInsecureRand(SeedRand::ZEROS); std::vector<uint256> hashes; Cache set{}; size_t bytes = megabytes * (1 << 20); @@ -181,7 +181,7 @@ template <typename Cache> static void test_cache_erase_parallel(size_t megabytes) { double load = 1; - SeedInsecureRand(true); + SeedInsecureRand(SeedRand::ZEROS); std::vector<uint256> hashes; Cache set{}; size_t bytes = megabytes * (1 << 20); @@ -285,7 +285,7 @@ static void test_cache_generations() // iterations with non-deterministic values, so it isn't "overfit" to the // specific entropy in FastRandomContext(true) and implementation of the // cache. - SeedInsecureRand(true); + SeedInsecureRand(SeedRand::ZEROS); // block_activity models a chunk of network activity. n_insert elements are // added to the cache. The first and last n/4 are stored for removal later diff --git a/src/test/dbwrapper_tests.cpp b/src/test/dbwrapper_tests.cpp index 2ffe4dccdb..57d5b2bb5c 100644 --- a/src/test/dbwrapper_tests.cpp +++ b/src/test/dbwrapper_tests.cpp @@ -4,7 +4,7 @@ #include <dbwrapper.h> #include <uint256.h> -#include <test/setup_common.h> +#include <test/util/setup_common.h> #include <util/memory.h> #include <memory> diff --git a/src/test/denialofservice_tests.cpp b/src/test/denialofservice_tests.cpp index 1928324b27..632151793e 100644 --- a/src/test/denialofservice_tests.cpp +++ b/src/test/denialofservice_tests.cpp @@ -17,7 +17,7 @@ #include <util/time.h> #include <validation.h> -#include <test/setup_common.h> +#include <test/util/setup_common.h> #include <stdint.h> diff --git a/src/test/descriptor_tests.cpp b/src/test/descriptor_tests.cpp index 55726a4a8f..bcce8854e3 100644 --- a/src/test/descriptor_tests.cpp +++ b/src/test/descriptor_tests.cpp @@ -6,7 +6,7 @@ #include <string> #include <script/sign.h> #include <script/standard.h> -#include <test/setup_common.h> +#include <test/util/setup_common.h> #include <boost/test/unit_test.hpp> #include <script/descriptor.h> #include <util/strencodings.h> diff --git a/src/test/flatfile_tests.cpp b/src/test/flatfile_tests.cpp index 740d805cce..9bb0b3ef02 100644 --- a/src/test/flatfile_tests.cpp +++ b/src/test/flatfile_tests.cpp @@ -5,7 +5,7 @@ #include <clientversion.h> #include <flatfile.h> #include <streams.h> -#include <test/setup_common.h> +#include <test/util/setup_common.h> #include <util/system.h> #include <boost/test/unit_test.hpp> diff --git a/src/test/fs_tests.cpp b/src/test/fs_tests.cpp index b504a3cbb1..d02c3613ba 100644 --- a/src/test/fs_tests.cpp +++ b/src/test/fs_tests.cpp @@ -3,7 +3,7 @@ // file COPYING or http://www.opensource.org/licenses/mit-license.php. // #include <fs.h> -#include <test/setup_common.h> +#include <test/util/setup_common.h> #include <util/system.h> #include <boost/test/unit_test.hpp> diff --git a/src/test/getarg_tests.cpp b/src/test/getarg_tests.cpp index 77304fe918..5abd1087ec 100644 --- a/src/test/getarg_tests.cpp +++ b/src/test/getarg_tests.cpp @@ -4,7 +4,7 @@ #include <util/strencodings.h> #include <util/system.h> -#include <test/setup_common.h> +#include <test/util/setup_common.h> #include <string> #include <utility> diff --git a/src/test/hash_tests.cpp b/src/test/hash_tests.cpp index d91fcb0034..b864e6e599 100644 --- a/src/test/hash_tests.cpp +++ b/src/test/hash_tests.cpp @@ -6,7 +6,7 @@ #include <crypto/siphash.h> #include <hash.h> #include <util/strencodings.h> -#include <test/setup_common.h> +#include <test/util/setup_common.h> #include <boost/test/unit_test.hpp> diff --git a/src/test/key_io_tests.cpp b/src/test/key_io_tests.cpp index e924f27d1b..b52513f4af 100644 --- a/src/test/key_io_tests.cpp +++ b/src/test/key_io_tests.cpp @@ -9,7 +9,7 @@ #include <key_io.h> #include <script/script.h> #include <util/strencodings.h> -#include <test/setup_common.h> +#include <test/util/setup_common.h> #include <boost/test/unit_test.hpp> diff --git a/src/test/key_properties.cpp b/src/test/key_properties.cpp index 95587130fc..0e45a2549d 100644 --- a/src/test/key_properties.cpp +++ b/src/test/key_properties.cpp @@ -4,7 +4,7 @@ #include <key.h> #include <uint256.h> -#include <test/setup_common.h> +#include <test/util/setup_common.h> #include <vector> #include <boost/test/unit_test.hpp> diff --git a/src/test/key_tests.cpp b/src/test/key_tests.cpp index 3e99dcaa40..85dc961bea 100644 --- a/src/test/key_tests.cpp +++ b/src/test/key_tests.cpp @@ -8,7 +8,7 @@ #include <uint256.h> #include <util/system.h> #include <util/strencodings.h> -#include <test/setup_common.h> +#include <test/util/setup_common.h> #include <string> #include <vector> diff --git a/src/test/limitedmap_tests.cpp b/src/test/limitedmap_tests.cpp index 00b36f51fb..ea18debbd3 100644 --- a/src/test/limitedmap_tests.cpp +++ b/src/test/limitedmap_tests.cpp @@ -4,7 +4,7 @@ #include <limitedmap.h> -#include <test/setup_common.h> +#include <test/util/setup_common.h> #include <boost/test/unit_test.hpp> diff --git a/src/test/logging_tests.cpp b/src/test/logging_tests.cpp new file mode 100644 index 0000000000..25655b8894 --- /dev/null +++ b/src/test/logging_tests.cpp @@ -0,0 +1,36 @@ +// Copyright (c) 2019 The Bitcoin Core developers +// Distributed under the MIT software license, see the accompanying +// file COPYING or http://www.opensource.org/licenses/mit-license.php. + +#include <logging.h> +#include <logging/timer.h> +#include <test/util/setup_common.h> + +#include <chrono> + +#include <boost/test/unit_test.hpp> + +BOOST_FIXTURE_TEST_SUITE(logging_tests, BasicTestingSetup) + +BOOST_AUTO_TEST_CASE(logging_timer) +{ + + SetMockTime(1); + auto sec_timer = BCLog::Timer<std::chrono::seconds>("tests", "end_msg"); + SetMockTime(2); + BOOST_CHECK_EQUAL(sec_timer.LogMsg("test secs"), "tests: test secs (1.00s)"); + + SetMockTime(1); + auto ms_timer = BCLog::Timer<std::chrono::milliseconds>("tests", "end_msg"); + SetMockTime(2); + BOOST_CHECK_EQUAL(ms_timer.LogMsg("test ms"), "tests: test ms (1000.00ms)"); + + SetMockTime(1); + auto micro_timer = BCLog::Timer<std::chrono::microseconds>("tests", "end_msg"); + SetMockTime(2); + BOOST_CHECK_EQUAL(micro_timer.LogMsg("test micros"), "tests: test micros (1000000.00μs)"); + + SetMockTime(0); +} + +BOOST_AUTO_TEST_SUITE_END() diff --git a/src/test/mempool_tests.cpp b/src/test/mempool_tests.cpp index fe5d31b7d3..38fed51af2 100644 --- a/src/test/mempool_tests.cpp +++ b/src/test/mempool_tests.cpp @@ -7,7 +7,7 @@ #include <util/system.h> #include <util/time.h> -#include <test/setup_common.h> +#include <test/util/setup_common.h> #include <boost/test/unit_test.hpp> #include <vector> @@ -749,6 +749,43 @@ BOOST_AUTO_TEST_CASE(MempoolAncestryTests) pool.GetTransactionAncestry(ty6->GetHash(), ancestors, descendants); BOOST_CHECK_EQUAL(ancestors, 9ULL); BOOST_CHECK_EQUAL(descendants, 6ULL); + + /* Ancestors represented more than once ("diamond") */ + // + // [ta].0 <- [tb].0 -----<------- [td].0 + // | | + // \---1 <- [tc].0 --<--/ + // + CTransactionRef ta, tb, tc, td; + ta = make_tx(/* output_values */ {10 * COIN}); + tb = make_tx(/* output_values */ {5 * COIN, 3 * COIN}, /* inputs */ {ta}); + tc = make_tx(/* output_values */ {2 * COIN}, /* inputs */ {tb}, /* input_indices */ {1}); + td = make_tx(/* output_values */ {6 * COIN}, /* inputs */ {tb, tc}, /* input_indices */ {0, 0}); + pool.clear(); + pool.addUnchecked(entry.Fee(10000LL).FromTx(ta)); + pool.addUnchecked(entry.Fee(10000LL).FromTx(tb)); + pool.addUnchecked(entry.Fee(10000LL).FromTx(tc)); + pool.addUnchecked(entry.Fee(10000LL).FromTx(td)); + + // Ancestors / descendants should be: + // transaction ancestors descendants + // ============ =================== =========== + // ta 1 (ta 4 (ta,tb,tc,td) + // tb 2 (ta,tb) 4 (ta,tb,tc,td) + // tc 3 (ta,tb,tc) 4 (ta,tb,tc,td) + // td 4 (ta,tb,tc,td) 4 (ta,tb,tc,td) + pool.GetTransactionAncestry(ta->GetHash(), ancestors, descendants); + BOOST_CHECK_EQUAL(ancestors, 1ULL); + BOOST_CHECK_EQUAL(descendants, 4ULL); + pool.GetTransactionAncestry(tb->GetHash(), ancestors, descendants); + BOOST_CHECK_EQUAL(ancestors, 2ULL); + BOOST_CHECK_EQUAL(descendants, 4ULL); + pool.GetTransactionAncestry(tc->GetHash(), ancestors, descendants); + BOOST_CHECK_EQUAL(ancestors, 3ULL); + BOOST_CHECK_EQUAL(descendants, 4ULL); + pool.GetTransactionAncestry(td->GetHash(), ancestors, descendants); + BOOST_CHECK_EQUAL(ancestors, 4ULL); + BOOST_CHECK_EQUAL(descendants, 4ULL); } BOOST_AUTO_TEST_SUITE_END() diff --git a/src/test/merkle_tests.cpp b/src/test/merkle_tests.cpp index dc38a1a818..8813921df5 100644 --- a/src/test/merkle_tests.cpp +++ b/src/test/merkle_tests.cpp @@ -3,7 +3,7 @@ // file COPYING or http://www.opensource.org/licenses/mit-license.php. #include <consensus/merkle.h> -#include <test/setup_common.h> +#include <test/util/setup_common.h> #include <boost/test/unit_test.hpp> diff --git a/src/test/merkleblock_tests.cpp b/src/test/merkleblock_tests.cpp index eac43471c7..9f8c4ba5c5 100644 --- a/src/test/merkleblock_tests.cpp +++ b/src/test/merkleblock_tests.cpp @@ -4,7 +4,7 @@ #include <merkleblock.h> #include <uint256.h> -#include <test/setup_common.h> +#include <test/util/setup_common.h> #include <boost/test/unit_test.hpp> diff --git a/src/test/miner_tests.cpp b/src/test/miner_tests.cpp index c9661b730d..6ed7350ea2 100644 --- a/src/test/miner_tests.cpp +++ b/src/test/miner_tests.cpp @@ -17,7 +17,7 @@ #include <util/time.h> #include <validation.h> -#include <test/setup_common.h> +#include <test/util/setup_common.h> #include <memory> diff --git a/src/test/multisig_tests.cpp b/src/test/multisig_tests.cpp index 7c60abb93f..97a918da45 100644 --- a/src/test/multisig_tests.cpp +++ b/src/test/multisig_tests.cpp @@ -11,7 +11,7 @@ #include <script/signingprovider.h> #include <tinyformat.h> #include <uint256.h> -#include <test/setup_common.h> +#include <test/util/setup_common.h> #include <boost/test/unit_test.hpp> diff --git a/src/test/net_tests.cpp b/src/test/net_tests.cpp index 0c1452822d..daf7fea6ad 100644 --- a/src/test/net_tests.cpp +++ b/src/test/net_tests.cpp @@ -5,7 +5,7 @@ #include <addrdb.h> #include <addrman.h> #include <clientversion.h> -#include <test/setup_common.h> +#include <test/util/setup_common.h> #include <string> #include <boost/test/unit_test.hpp> #include <serialize.h> diff --git a/src/test/netbase_tests.cpp b/src/test/netbase_tests.cpp index a3d0831624..78c11ff202 100644 --- a/src/test/netbase_tests.cpp +++ b/src/test/netbase_tests.cpp @@ -4,7 +4,7 @@ #include <netbase.h> #include <net_permissions.h> -#include <test/setup_common.h> +#include <test/util/setup_common.h> #include <util/strencodings.h> #include <string> diff --git a/src/test/pmt_tests.cpp b/src/test/pmt_tests.cpp index c5513ae9fa..bf58bd63b9 100644 --- a/src/test/pmt_tests.cpp +++ b/src/test/pmt_tests.cpp @@ -9,7 +9,7 @@ #include <uint256.h> #include <arith_uint256.h> #include <version.h> -#include <test/setup_common.h> +#include <test/util/setup_common.h> #include <vector> @@ -30,7 +30,6 @@ BOOST_FIXTURE_TEST_SUITE(pmt_tests, BasicTestingSetup) BOOST_AUTO_TEST_CASE(pmt_test1) { - SeedInsecureRand(false); static const unsigned int nTxCounts[] = {1, 4, 7, 17, 56, 100, 127, 256, 312, 513, 1000, 4095}; for (int i = 0; i < 12; i++) { diff --git a/src/test/policyestimator_tests.cpp b/src/test/policyestimator_tests.cpp index 5368f82ffe..025e2b78ca 100644 --- a/src/test/policyestimator_tests.cpp +++ b/src/test/policyestimator_tests.cpp @@ -8,7 +8,7 @@ #include <uint256.h> #include <util/time.h> -#include <test/setup_common.h> +#include <test/util/setup_common.h> #include <boost/test/unit_test.hpp> diff --git a/src/test/pow_tests.cpp b/src/test/pow_tests.cpp index 6c99021d97..0f9872f434 100644 --- a/src/test/pow_tests.cpp +++ b/src/test/pow_tests.cpp @@ -5,7 +5,7 @@ #include <chain.h> #include <chainparams.h> #include <pow.h> -#include <test/setup_common.h> +#include <test/util/setup_common.h> #include <boost/test/unit_test.hpp> diff --git a/src/test/prevector_tests.cpp b/src/test/prevector_tests.cpp index fc1f946bba..9782b78f2c 100644 --- a/src/test/prevector_tests.cpp +++ b/src/test/prevector_tests.cpp @@ -9,7 +9,7 @@ #include <serialize.h> #include <streams.h> -#include <test/setup_common.h> +#include <test/util/setup_common.h> #include <boost/test/unit_test.hpp> diff --git a/src/test/raii_event_tests.cpp b/src/test/raii_event_tests.cpp index 41ca8029e5..04bf7c20c1 100644 --- a/src/test/raii_event_tests.cpp +++ b/src/test/raii_event_tests.cpp @@ -12,7 +12,7 @@ #include <support/events.h> -#include <test/setup_common.h> +#include <test/util/setup_common.h> #include <boost/test/unit_test.hpp> diff --git a/src/test/random_tests.cpp b/src/test/random_tests.cpp index e6fbe2355d..e0df41a971 100644 --- a/src/test/random_tests.cpp +++ b/src/test/random_tests.cpp @@ -4,7 +4,7 @@ #include <random.h> -#include <test/setup_common.h> +#include <test/util/setup_common.h> #include <boost/test/unit_test.hpp> diff --git a/src/test/reverselock_tests.cpp b/src/test/reverselock_tests.cpp index 69db9dcf4e..532fe143ae 100644 --- a/src/test/reverselock_tests.cpp +++ b/src/test/reverselock_tests.cpp @@ -3,7 +3,7 @@ // file COPYING or http://www.opensource.org/licenses/mit-license.php. #include <reverselock.h> -#include <test/setup_common.h> +#include <test/util/setup_common.h> #include <boost/test/unit_test.hpp> diff --git a/src/test/rpc_tests.cpp b/src/test/rpc_tests.cpp index faff1931cd..52dd22de7e 100644 --- a/src/test/rpc_tests.cpp +++ b/src/test/rpc_tests.cpp @@ -9,7 +9,7 @@ #include <core_io.h> #include <interfaces/chain.h> #include <node/context.h> -#include <test/setup_common.h> +#include <test/util/setup_common.h> #include <util/time.h> #include <boost/algorithm/string.hpp> diff --git a/src/test/sanity_tests.cpp b/src/test/sanity_tests.cpp index 891aa8e5c3..4d50845256 100644 --- a/src/test/sanity_tests.cpp +++ b/src/test/sanity_tests.cpp @@ -4,7 +4,7 @@ #include <compat/sanity.h> #include <key.h> -#include <test/setup_common.h> +#include <test/util/setup_common.h> #include <boost/test/unit_test.hpp> diff --git a/src/test/scheduler_tests.cpp b/src/test/scheduler_tests.cpp index 42242b962b..b292d5b0d0 100644 --- a/src/test/scheduler_tests.cpp +++ b/src/test/scheduler_tests.cpp @@ -5,7 +5,7 @@ #include <random.h> #include <scheduler.h> -#include <test/setup_common.h> +#include <test/util/setup_common.h> #include <boost/thread.hpp> #include <boost/test/unit_test.hpp> diff --git a/src/test/script_p2sh_tests.cpp b/src/test/script_p2sh_tests.cpp index ec28d6a0ad..8c1e843b0b 100644 --- a/src/test/script_p2sh_tests.cpp +++ b/src/test/script_p2sh_tests.cpp @@ -11,7 +11,7 @@ #include <policy/settings.h> #include <script/sign.h> #include <script/signingprovider.h> -#include <test/setup_common.h> +#include <test/util/setup_common.h> #include <vector> diff --git a/src/test/script_standard_tests.cpp b/src/test/script_standard_tests.cpp index 412a57dd9d..de990d9254 100644 --- a/src/test/script_standard_tests.cpp +++ b/src/test/script_standard_tests.cpp @@ -6,7 +6,7 @@ #include <script/script.h> #include <script/signingprovider.h> #include <script/standard.h> -#include <test/setup_common.h> +#include <test/util/setup_common.h> #include <boost/test/unit_test.hpp> diff --git a/src/test/script_tests.cpp b/src/test/script_tests.cpp index caa99805c3..26015ca4c2 100644 --- a/src/test/script_tests.cpp +++ b/src/test/script_tests.cpp @@ -12,8 +12,8 @@ #include <script/signingprovider.h> #include <util/system.h> #include <util/strencodings.h> -#include <test/lib/transaction_utils.h> -#include <test/setup_common.h> +#include <test/util/transaction_utils.h> +#include <test/util/setup_common.h> #include <rpc/util.h> #include <streams.h> diff --git a/src/test/scriptnum_tests.cpp b/src/test/scriptnum_tests.cpp index e7916f5000..40a6f69668 100644 --- a/src/test/scriptnum_tests.cpp +++ b/src/test/scriptnum_tests.cpp @@ -4,7 +4,7 @@ #include <test/scriptnum10.h> #include <script/script.h> -#include <test/setup_common.h> +#include <test/util/setup_common.h> #include <boost/test/unit_test.hpp> #include <limits.h> diff --git a/src/test/serialize_tests.cpp b/src/test/serialize_tests.cpp index b90be15fba..303bb9b88c 100644 --- a/src/test/serialize_tests.cpp +++ b/src/test/serialize_tests.cpp @@ -5,7 +5,7 @@ #include <serialize.h> #include <streams.h> #include <hash.h> -#include <test/setup_common.h> +#include <test/util/setup_common.h> #include <util/strencodings.h> #include <stdint.h> diff --git a/src/test/sighash_tests.cpp b/src/test/sighash_tests.cpp index b18f9df72d..2c56bbdbb0 100644 --- a/src/test/sighash_tests.cpp +++ b/src/test/sighash_tests.cpp @@ -10,7 +10,7 @@ #include <script/script.h> #include <serialize.h> #include <streams.h> -#include <test/setup_common.h> +#include <test/util/setup_common.h> #include <util/system.h> #include <util/strencodings.h> #include <version.h> @@ -119,8 +119,6 @@ BOOST_FIXTURE_TEST_SUITE(sighash_tests, BasicTestingSetup) BOOST_AUTO_TEST_CASE(sighash_test) { - SeedInsecureRand(false); - #if defined(PRINT_SIGHASH_JSON) std::cout << "[\n"; std::cout << "\t[\"raw_transaction, script, input_index, hashType, signature_hash (result)\"],\n"; diff --git a/src/test/sigopcount_tests.cpp b/src/test/sigopcount_tests.cpp index a32f2cda92..6462fcefe3 100644 --- a/src/test/sigopcount_tests.cpp +++ b/src/test/sigopcount_tests.cpp @@ -9,7 +9,7 @@ #include <script/script.h> #include <script/standard.h> #include <uint256.h> -#include <test/setup_common.h> +#include <test/util/setup_common.h> #include <vector> diff --git a/src/test/skiplist_tests.cpp b/src/test/skiplist_tests.cpp index 1cba3a1297..7ede79279f 100644 --- a/src/test/skiplist_tests.cpp +++ b/src/test/skiplist_tests.cpp @@ -3,7 +3,7 @@ // file COPYING or http://www.opensource.org/licenses/mit-license.php. #include <chain.h> -#include <test/setup_common.h> +#include <test/util/setup_common.h> #include <vector> diff --git a/src/test/streams_tests.cpp b/src/test/streams_tests.cpp index 6075fbfeca..177d8fda73 100644 --- a/src/test/streams_tests.cpp +++ b/src/test/streams_tests.cpp @@ -3,7 +3,7 @@ // file COPYING or http://www.opensource.org/licenses/mit-license.php. #include <streams.h> -#include <test/setup_common.h> +#include <test/util/setup_common.h> #include <boost/test/unit_test.hpp> @@ -338,7 +338,7 @@ BOOST_AUTO_TEST_CASE(streams_buffered_file) BOOST_AUTO_TEST_CASE(streams_buffered_file_rand) { // Make this test deterministic. - SeedInsecureRand(true); + SeedInsecureRand(SeedRand::ZEROS); for (int rep = 0; rep < 50; ++rep) { FILE* file = fsbridge::fopen("streams_test_tmp", "w+b"); diff --git a/src/test/sync_tests.cpp b/src/test/sync_tests.cpp index c1399d2dbe..188e9986ff 100644 --- a/src/test/sync_tests.cpp +++ b/src/test/sync_tests.cpp @@ -3,7 +3,7 @@ // file COPYING or http://www.opensource.org/licenses/mit-license.php. #include <sync.h> -#include <test/setup_common.h> +#include <test/util/setup_common.h> #include <boost/test/unit_test.hpp> diff --git a/src/test/timedata_tests.cpp b/src/test/timedata_tests.cpp index 7b00222ab7..4721151197 100644 --- a/src/test/timedata_tests.cpp +++ b/src/test/timedata_tests.cpp @@ -5,7 +5,8 @@ #include <netaddress.h> #include <noui.h> -#include <test/setup_common.h> +#include <test/util/logging.h> +#include <test/util/setup_common.h> #include <timedata.h> #include <warnings.h> @@ -59,9 +60,10 @@ BOOST_AUTO_TEST_CASE(addtimedata) MultiAddTimeData(3, DEFAULT_MAX_TIME_ADJUSTMENT + 1); // Filter size is 1 + 3 = 4: It is always initialized with a single element (offset 0) - noui_suppress(); - MultiAddTimeData(1, DEFAULT_MAX_TIME_ADJUSTMENT + 1); //filter size 5 - noui_reconnect(); + { + ASSERT_DEBUG_LOG("Please check that your computer's date and time are correct!"); + MultiAddTimeData(1, DEFAULT_MAX_TIME_ADJUSTMENT + 1); //filter size 5 + } BOOST_CHECK(GetWarnings("gui").find("clock is wrong") != std::string::npos); diff --git a/src/test/torcontrol_tests.cpp b/src/test/torcontrol_tests.cpp index d846062d9b..41aa17988c 100644 --- a/src/test/torcontrol_tests.cpp +++ b/src/test/torcontrol_tests.cpp @@ -2,7 +2,7 @@ // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. // -#include <test/setup_common.h> +#include <test/util/setup_common.h> #include <boost/test/unit_test.hpp> diff --git a/src/test/transaction_tests.cpp b/src/test/transaction_tests.cpp index a8c8918733..2d55554acb 100644 --- a/src/test/transaction_tests.cpp +++ b/src/test/transaction_tests.cpp @@ -4,7 +4,7 @@ #include <test/data/tx_invalid.json.h> #include <test/data/tx_valid.json.h> -#include <test/setup_common.h> +#include <test/util/setup_common.h> #include <clientversion.h> #include <checkqueue.h> diff --git a/src/test/txindex_tests.cpp b/src/test/txindex_tests.cpp index 0ac4b7ebc9..4b0214a15a 100644 --- a/src/test/txindex_tests.cpp +++ b/src/test/txindex_tests.cpp @@ -5,7 +5,7 @@ #include <chainparams.h> #include <index/txindex.h> #include <script/standard.h> -#include <test/setup_common.h> +#include <test/util/setup_common.h> #include <util/time.h> #include <boost/test/unit_test.hpp> diff --git a/src/test/txvalidation_tests.cpp b/src/test/txvalidation_tests.cpp index 391ebfadfb..245c03d774 100644 --- a/src/test/txvalidation_tests.cpp +++ b/src/test/txvalidation_tests.cpp @@ -6,7 +6,7 @@ #include <consensus/validation.h> #include <primitives/transaction.h> #include <script/script.h> -#include <test/setup_common.h> +#include <test/util/setup_common.h> #include <boost/test/unit_test.hpp> diff --git a/src/test/txvalidationcache_tests.cpp b/src/test/txvalidationcache_tests.cpp index 144230b114..a5bc15bb9f 100644 --- a/src/test/txvalidationcache_tests.cpp +++ b/src/test/txvalidationcache_tests.cpp @@ -9,7 +9,7 @@ #include <script/standard.h> #include <script/sign.h> #include <script/signingprovider.h> -#include <test/setup_common.h> +#include <test/util/setup_common.h> #include <boost/test/unit_test.hpp> diff --git a/src/test/uint256_tests.cpp b/src/test/uint256_tests.cpp index 33a118c2bb..7293ecd325 100644 --- a/src/test/uint256_tests.cpp +++ b/src/test/uint256_tests.cpp @@ -6,7 +6,7 @@ #include <streams.h> #include <uint256.h> #include <version.h> -#include <test/setup_common.h> +#include <test/util/setup_common.h> #include <boost/test/unit_test.hpp> #include <sstream> diff --git a/src/test/util/README.md b/src/test/util/README.md new file mode 100644 index 0000000000..36ad645201 --- /dev/null +++ b/src/test/util/README.md @@ -0,0 +1,11 @@ +# Test library + +This contains files for the test library, which is used by the test binaries (unit tests, benchmarks, fuzzers, gui +tests). + +Generally, the files in this folder should be well-separated modules. New code should be added to existing modules or +(when in doubt) a new module should be created. + +The utilities in here are compiled into a library, which does not hold any state. However, the main file `setup_common` +defines the common test setup for all test binaries. The test binaries will handle the global state when they +instantiate the `BasicTestingSetup` (or one of its derived classes). diff --git a/src/test/lib/blockfilter.cpp b/src/test/util/blockfilter.cpp index ddcee85d7e..bccff5e5a6 100644 --- a/src/test/lib/blockfilter.cpp +++ b/src/test/util/blockfilter.cpp @@ -2,7 +2,7 @@ // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. -#include <test/lib/blockfilter.h> +#include <test/util/blockfilter.h> #include <chainparams.h> #include <validation.h> diff --git a/src/test/lib/blockfilter.h b/src/test/util/blockfilter.h index 392dacbe80..79d11dcad8 100644 --- a/src/test/lib/blockfilter.h +++ b/src/test/util/blockfilter.h @@ -2,12 +2,12 @@ // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. -#ifndef BITCOIN_TEST_LIB_BLOCKFILTER_H -#define BITCOIN_TEST_LIB_BLOCKFILTER_H +#ifndef BITCOIN_TEST_UTIL_BLOCKFILTER_H +#define BITCOIN_TEST_UTIL_BLOCKFILTER_H #include <blockfilter.h> class CBlockIndex; bool ComputeFilter(BlockFilterType filter_type, const CBlockIndex* block_index, BlockFilter& filter); -#endif // BITCOIN_TEST_LIB_BLOCKFILTER_H +#endif // BITCOIN_TEST_UTIL_BLOCKFILTER_H diff --git a/src/test/util/logging.cpp b/src/test/util/logging.cpp new file mode 100644 index 0000000000..fe2e69104b --- /dev/null +++ b/src/test/util/logging.cpp @@ -0,0 +1,32 @@ +// Copyright (c) 2019 The Bitcoin Core developers +// Distributed under the MIT software license, see the accompanying +// file COPYING or http://www.opensource.org/licenses/mit-license.php. + +#include <test/util/logging.h> + +#include <logging.h> +#include <noui.h> +#include <tinyformat.h> +#include <util/memory.h> + +#include <stdexcept> + +DebugLogHelper::DebugLogHelper(std::string message) + : m_message{std::move(message)} +{ + m_print_connection = LogInstance().PushBackCallback( + [this](const std::string& s) { + if (m_found) return; + m_found = s.find(m_message) != std::string::npos; + }); + noui_test_redirect(); +} + +void DebugLogHelper::check_found() +{ + noui_reconnect(); + LogInstance().DeleteCallback(m_print_connection); + if (!m_found) { + throw std::runtime_error(strprintf("'%s' not found in debug log\n", m_message)); + } +} diff --git a/src/test/util/logging.h b/src/test/util/logging.h new file mode 100644 index 0000000000..45ec44173c --- /dev/null +++ b/src/test/util/logging.h @@ -0,0 +1,29 @@ +// Copyright (c) 2019 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_TEST_UTIL_LOGGING_H +#define BITCOIN_TEST_UTIL_LOGGING_H + +#include <util/macros.h> + +#include <functional> +#include <list> +#include <string> + +class DebugLogHelper +{ + const std::string m_message; + bool m_found{false}; + std::list<std::function<void(const std::string&)>>::iterator m_print_connection; + + void check_found(); + +public: + DebugLogHelper(std::string message); + ~DebugLogHelper() { check_found(); } +}; + +#define ASSERT_DEBUG_LOG(message) DebugLogHelper PASTE2(debugloghelper, __COUNTER__)(message) + +#endif // BITCOIN_TEST_UTIL_LOGGING_H diff --git a/src/test/setup_common.cpp b/src/test/util/setup_common.cpp index 797b72ff59..0c6ecdf69d 100644 --- a/src/test/setup_common.cpp +++ b/src/test/util/setup_common.cpp @@ -2,7 +2,7 @@ // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. -#include <test/setup_common.h> +#include <test/util/setup_common.h> #include <banman.h> #include <chainparams.h> @@ -34,6 +34,27 @@ const std::function<std::string(const char*)> G_TRANSLATION_FUN = nullptr; FastRandomContext g_insecure_rand_ctx; +/** Random context to get unique temp data dirs. Separate from g_insecure_rand_ctx, which can be seeded from a const env var */ +static FastRandomContext g_insecure_rand_ctx_temp_path; + +/** Return the unsigned from the environment var if available, otherwise 0 */ +static uint256 GetUintFromEnv(const std::string& env_name) +{ + const char* num = std::getenv(env_name.c_str()); + if (!num) return {}; + return uint256S(num); +} + +void Seed(FastRandomContext& ctx) +{ + // Should be enough to get the seed once for the process + static uint256 seed{}; + static const std::string RANDOM_CTX_SEED{"RANDOM_CTX_SEED"}; + if (seed.IsNull()) seed = GetUintFromEnv(RANDOM_CTX_SEED); + if (seed.IsNull()) seed = GetRandHash(); + LogPrintf("%s: Setting random seed for current tests to %s=%s\n", __func__, RANDOM_CTX_SEED, seed.GetHex()); + ctx = FastRandomContext(seed); +} std::ostream& operator<<(std::ostream& os, const uint256& num) { @@ -42,12 +63,13 @@ std::ostream& operator<<(std::ostream& os, const uint256& num) } BasicTestingSetup::BasicTestingSetup(const std::string& chainName) - : m_path_root(fs::temp_directory_path() / "test_common_" PACKAGE_NAME / strprintf("%lu_%i", (unsigned long)GetTime(), (int)(InsecureRandRange(1 << 30)))) + : m_path_root{fs::temp_directory_path() / "test_common_" PACKAGE_NAME / std::to_string(g_insecure_rand_ctx_temp_path.rand32())} { fs::create_directories(m_path_root); gArgs.ForceSetArg("-datadir", m_path_root.string()); ClearDatadirCache(); SelectParams(chainName); + SeedInsecureRand(); gArgs.ForceSetArg("-printtoconsole", "0"); InitLogging(); LogInstance().StartLogging(); @@ -102,9 +124,12 @@ TestingSetup::TestingSetup(const std::string& chainName) : BasicTestingSetup(cha throw std::runtime_error(strprintf("ActivateBestChain failed. (%s)", FormatStateMessage(state))); } - nScriptCheckThreads = 3; - for (int i = 0; i < nScriptCheckThreads - 1; i++) + // Start script-checking threads. Set g_parallel_script_checks to true so they are used. + constexpr int script_check_threads = 2; + for (int i = 0; i < script_check_threads; ++i) { threadGroup.create_thread([i]() { return ThreadScriptCheck(i); }); + } + g_parallel_script_checks = true; m_node.banman = MakeUnique<BanMan>(GetDataDir() / "banlist.dat", nullptr, DEFAULT_MISBEHAVING_BANTIME); m_node.connman = MakeUnique<CConnman>(0x1337, 0x1337); // Deterministic randomness for tests. diff --git a/src/test/setup_common.h b/src/test/util/setup_common.h index 465baf90c3..1e2e059a56 100644 --- a/src/test/setup_common.h +++ b/src/test/util/setup_common.h @@ -2,8 +2,8 @@ // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. -#ifndef BITCOIN_TEST_SETUP_COMMON_H -#define BITCOIN_TEST_SETUP_COMMON_H +#ifndef BITCOIN_TEST_UTIL_SETUP_COMMON_H +#define BITCOIN_TEST_UTIL_SETUP_COMMON_H #include <chainparamsbase.h> #include <fs.h> @@ -39,9 +39,21 @@ extern FastRandomContext g_insecure_rand_ctx; */ extern bool g_mock_deterministic_tests; -static inline void SeedInsecureRand(bool deterministic = false) +enum class SeedRand { + ZEROS, //!< Seed with a compile time constant of zeros + SEED, //!< Call the Seed() helper +}; + +/** Seed the given random ctx or use the seed passed in via an environment var */ +void Seed(FastRandomContext& ctx); + +static inline void SeedInsecureRand(SeedRand seed = SeedRand::SEED) { - g_insecure_rand_ctx = FastRandomContext(deterministic); + if (seed == SeedRand::ZEROS) { + g_insecure_rand_ctx = FastRandomContext(/* deterministic */ true); + } else { + Seed(g_insecure_rand_ctx); + } } static inline uint32_t InsecureRand32() { return g_insecure_rand_ctx.rand32(); } diff --git a/src/test/lib/transaction_utils.cpp b/src/test/util/transaction_utils.cpp index 2619fb9006..90b78effb0 100644 --- a/src/test/lib/transaction_utils.cpp +++ b/src/test/util/transaction_utils.cpp @@ -2,7 +2,7 @@ // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. -#include <test/lib/transaction_utils.h> +#include <test/util/transaction_utils.h> CMutableTransaction BuildCreditingTransaction(const CScript& scriptPubKey, int nValue) { diff --git a/src/test/lib/transaction_utils.h b/src/test/util/transaction_utils.h index 6f297ac34f..57604646e7 100644 --- a/src/test/lib/transaction_utils.h +++ b/src/test/util/transaction_utils.h @@ -2,8 +2,8 @@ // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. -#ifndef BITCOIN_TEST_LIB_TRANSACTION_UTILS_H -#define BITCOIN_TEST_LIB_TRANSACTION_UTILS_H +#ifndef BITCOIN_TEST_UTIL_TRANSACTION_UTILS_H +#define BITCOIN_TEST_UTIL_TRANSACTION_UTILS_H #include <primitives/transaction.h> @@ -16,4 +16,4 @@ CMutableTransaction BuildCreditingTransaction(const CScript& scriptPubKey, int n // 1 output with empty scriptPubKey, full value of referenced transaction] CMutableTransaction BuildSpendingTransaction(const CScript& scriptSig, const CScriptWitness& scriptWitness, const CTransaction& txCredit); -#endif // BITCOIN_TEST_LIB_TRANSACTION_UTILS_H +#endif // BITCOIN_TEST_UTIL_TRANSACTION_UTILS_H diff --git a/src/test/util_tests.cpp b/src/test/util_tests.cpp index 569ce53092..daf6d951bc 100644 --- a/src/test/util_tests.cpp +++ b/src/test/util_tests.cpp @@ -6,7 +6,7 @@ #include <clientversion.h> #include <sync.h> -#include <test/setup_common.h> +#include <test/util/setup_common.h> #include <test/util.h> #include <util/moneystr.h> #include <util/strencodings.h> @@ -231,6 +231,60 @@ BOOST_AUTO_TEST_CASE(util_ParseParameters) BOOST_CHECK(testArgs.GetArgs("-ccc").size() == 2); } +static void TestParse(const std::string& str, bool expected_bool, int64_t expected_int) +{ + TestArgsManager test; + test.SetupArgs({{"-value", ArgsManager::ALLOW_ANY}}); + std::string arg = "-value=" + str; + const char* argv[] = {"ignored", arg.c_str()}; + std::string error; + BOOST_CHECK(test.ParseParameters(2, (char**)argv, error)); + BOOST_CHECK_EQUAL(test.GetBoolArg("-value", false), expected_bool); + BOOST_CHECK_EQUAL(test.GetBoolArg("-value", true), expected_bool); + BOOST_CHECK_EQUAL(test.GetArg("-value", 99998), expected_int); + BOOST_CHECK_EQUAL(test.GetArg("-value", 99999), expected_int); +} + +// Test bool and int parsing. +BOOST_AUTO_TEST_CASE(util_ArgParsing) +{ + // Some of these cases could be ambiguous or surprising to users, and might + // be worth triggering errors or warnings in the future. But for now basic + // test coverage is useful to avoid breaking backwards compatibility + // unintentionally. + TestParse("", true, 0); + TestParse(" ", false, 0); + TestParse("0", false, 0); + TestParse("0 ", false, 0); + TestParse(" 0", false, 0); + TestParse("+0", false, 0); + TestParse("-0", false, 0); + TestParse("5", true, 5); + TestParse("5 ", true, 5); + TestParse(" 5", true, 5); + TestParse("+5", true, 5); + TestParse("-5", true, -5); + TestParse("0 5", false, 0); + TestParse("5 0", true, 5); + TestParse("050", true, 50); + TestParse("0.", false, 0); + TestParse("5.", true, 5); + TestParse("0.0", false, 0); + TestParse("0.5", false, 0); + TestParse("5.0", true, 5); + TestParse("5.5", true, 5); + TestParse("x", false, 0); + TestParse("x0", false, 0); + TestParse("x5", false, 0); + TestParse("0x", false, 0); + TestParse("5x", true, 5); + TestParse("0x5", false, 0); + TestParse("false", false, 0); + TestParse("true", false, 0); + TestParse("yes", false, 0); + TestParse("no", false, 0); +} + BOOST_AUTO_TEST_CASE(util_GetBoolArg) { TestArgsManager testArgs; @@ -890,6 +944,7 @@ BOOST_FIXTURE_TEST_CASE(util_ChainMerge, ChainMergeTestingSetup) desc += " "; desc += argstr + 1; conf += argstr + 1; + conf += "\n"; } std::istringstream conf_stream(conf); BOOST_CHECK(parser.ReadConfigStream(conf_stream, "filepath", error)); @@ -928,7 +983,7 @@ BOOST_FIXTURE_TEST_CASE(util_ChainMerge, ChainMergeTestingSetup) // Results file is formatted like: // // <input> || <output> - BOOST_CHECK_EQUAL(out_sha_hex, "94b4ad55c8ac639a56b93e36f7e32e4c611fd7d7dd7b2be6a71707b1eadcaec7"); + BOOST_CHECK_EQUAL(out_sha_hex, "f0b3a3c29869edc765d579c928f7f1690a71fbb673b49ccf39cbc4de18156a0d"); } BOOST_AUTO_TEST_CASE(util_FormatMoney) @@ -1051,7 +1106,7 @@ BOOST_AUTO_TEST_CASE(util_IsHexNumber) BOOST_AUTO_TEST_CASE(util_seed_insecure_rand) { - SeedInsecureRand(true); + SeedInsecureRand(SeedRand::ZEROS); for (int mod=2;mod<11;mod++) { int mask = 1; diff --git a/src/test/util_threadnames_tests.cpp b/src/test/util_threadnames_tests.cpp index 71c0168ca3..33f840d9c5 100644 --- a/src/test/util_threadnames_tests.cpp +++ b/src/test/util_threadnames_tests.cpp @@ -3,7 +3,7 @@ // file COPYING or http://www.opensource.org/licenses/mit-license.php. #include <util/threadnames.h> -#include <test/setup_common.h> +#include <test/util/setup_common.h> #include <thread> #include <vector> diff --git a/src/test/validation_block_tests.cpp b/src/test/validation_block_tests.cpp index 26ca9a3162..b7cf82906a 100644 --- a/src/test/validation_block_tests.cpp +++ b/src/test/validation_block_tests.cpp @@ -11,7 +11,7 @@ #include <pow.h> #include <random.h> #include <script/standard.h> -#include <test/setup_common.h> +#include <test/util/setup_common.h> #include <util/time.h> #include <validation.h> #include <validationinterface.h> diff --git a/src/test/validation_tests.cpp b/src/test/validation_tests.cpp index 101025d31e..3b961db52d 100644 --- a/src/test/validation_tests.cpp +++ b/src/test/validation_tests.cpp @@ -6,7 +6,7 @@ #include <net.h> #include <validation.h> -#include <test/setup_common.h> +#include <test/util/setup_common.h> #include <boost/signals2/signal.hpp> #include <boost/test/unit_test.hpp> diff --git a/src/test/versionbits_tests.cpp b/src/test/versionbits_tests.cpp index 0ca3a17974..7b59d539a6 100644 --- a/src/test/versionbits_tests.cpp +++ b/src/test/versionbits_tests.cpp @@ -4,7 +4,7 @@ #include <chain.h> #include <versionbits.h> -#include <test/setup_common.h> +#include <test/util/setup_common.h> #include <chainparams.h> #include <validation.h> #include <consensus/params.h> diff --git a/src/validation.cpp b/src/validation.cpp index 7be97df78a..cc7687ae05 100644 --- a/src/validation.cpp +++ b/src/validation.cpp @@ -18,6 +18,8 @@ #include <flatfile.h> #include <hash.h> #include <index/txindex.h> +#include <logging.h> +#include <logging/timer.h> #include <policy/fees.h> #include <policy/policy.h> #include <policy/settings.h> @@ -107,7 +109,7 @@ CBlockIndex *pindexBestHeader = nullptr; Mutex g_best_block_mutex; std::condition_variable g_best_block_cv; uint256 g_best_block; -int nScriptCheckThreads = 0; +bool g_parallel_script_checks{false}; std::atomic_bool fImporting(false); std::atomic_bool fReindex(false); bool fHavePruned = false; @@ -2069,7 +2071,7 @@ bool CChainState::ConnectBlock(const CBlock& block, BlockValidationState& state, CBlockUndo blockundo; - CCheckQueueControl<CScriptCheck> control(fScriptChecks && nScriptCheckThreads ? &scriptcheckqueue : nullptr); + CCheckQueueControl<CScriptCheck> control(fScriptChecks && g_parallel_script_checks ? &scriptcheckqueue : nullptr); std::vector<int> prevheights; CAmount nFees = 0; @@ -2130,7 +2132,7 @@ bool CChainState::ConnectBlock(const CBlock& block, BlockValidationState& state, std::vector<CScriptCheck> vChecks; bool fCacheResults = fJustCheck; /* Don't cache results if we're actually connecting blocks (still consult the cache, though) */ TxValidationState tx_state; - if (fScriptChecks && !CheckInputs(tx, tx_state, view, flags, fCacheResults, fCacheResults, txdata[i], nScriptCheckThreads ? &vChecks : nullptr)) { + if (fScriptChecks && !CheckInputs(tx, tx_state, view, flags, fCacheResults, fCacheResults, txdata[i], g_parallel_script_checks ? &vChecks : nullptr)) { // Any transaction validation failure in ConnectBlock is a block consensus failure state.Invalid(BlockValidationResult::BLOCK_CONSENSUS, tx_state.GetRejectReason(), tx_state.GetDebugMessage()); @@ -2199,6 +2201,10 @@ bool CChainState::FlushStateToDisk( static int64_t nLastFlush = 0; std::set<int> setFilesToPrune; bool full_flush_completed = false; + + const size_t coins_count = CoinsTip().GetCacheSize(); + const size_t coins_mem_usage = CoinsTip().DynamicMemoryUsage(); + try { { bool fFlushForPrune = false; @@ -2206,8 +2212,12 @@ bool CChainState::FlushStateToDisk( LOCK(cs_LastBlockFile); if (fPruneMode && (fCheckForPruning || nManualPruneHeight > 0) && !fReindex) { if (nManualPruneHeight > 0) { + LOG_TIME_MILLIS("find files to prune (manual)", BCLog::BENCH); + FindFilesToPruneManual(setFilesToPrune, nManualPruneHeight); } else { + LOG_TIME_MILLIS("find files to prune", BCLog::BENCH); + FindFilesToPrune(setFilesToPrune, chainparams.PruneAfterHeight()); fCheckForPruning = false; } @@ -2246,10 +2256,17 @@ bool CChainState::FlushStateToDisk( if (!CheckDiskSpace(GetBlocksDir())) { return AbortNode(state, "Disk space is too low!", _("Error: Disk space is too low!").translated, CClientUIInterface::MSG_NOPREFIX); } - // First make sure all block and undo data is flushed to disk. - FlushBlockFile(); + { + LOG_TIME_MILLIS("write block and undo data to disk", BCLog::BENCH); + + // First make sure all block and undo data is flushed to disk. + FlushBlockFile(); + } + // Then update all block file information (which may refer to block and undo files). { + LOG_TIME_MILLIS("write block index to disk", BCLog::BENCH); + std::vector<std::pair<int, const CBlockFileInfo*> > vFiles; vFiles.reserve(setDirtyFileInfo.size()); for (std::set<int>::iterator it = setDirtyFileInfo.begin(); it != setDirtyFileInfo.end(); ) { @@ -2267,12 +2284,18 @@ bool CChainState::FlushStateToDisk( } } // Finally remove any pruned files - if (fFlushForPrune) + if (fFlushForPrune) { + LOG_TIME_MILLIS("unlink pruned files", BCLog::BENCH); + UnlinkPrunedFiles(setFilesToPrune); + } nLastWrite = nNow; } // Flush best chain related state. This can only be done if the blocks / block index write was also done. if (fDoFullFlush && !CoinsTip().GetBestBlock().IsNull()) { + LOG_TIME_SECONDS(strprintf("write coins cache to disk (%d coins, %.2fkB)", + coins_count, coins_mem_usage / 1000)); + // Typical Coin structures on disk are around 48 bytes in size. // Pushing a new one to the database can cause it to be written // twice (once in the log, and once in the tables). This is already diff --git a/src/validation.h b/src/validation.h index 7f9582adfd..31721cfbf7 100644 --- a/src/validation.h +++ b/src/validation.h @@ -21,6 +21,7 @@ #include <txmempool.h> // For CTxMemPool::cs #include <txdb.h> #include <versionbits.h> +#include <serialize.h> #include <algorithm> #include <atomic> @@ -76,8 +77,8 @@ static const unsigned int BLOCKFILE_CHUNK_SIZE = 0x1000000; // 16 MiB /** The pre-allocation chunk size for rev?????.dat files (since 0.8) */ static const unsigned int UNDOFILE_CHUNK_SIZE = 0x100000; // 1 MiB -/** Maximum number of script-checking threads allowed */ -static const int MAX_SCRIPTCHECK_THREADS = 16; +/** Maximum number of dedicated script-checking threads allowed */ +static const int MAX_SCRIPTCHECK_THREADS = 15; /** -par default (number of script-checking threads, 0 = auto) */ static const int DEFAULT_SCRIPTCHECK_THREADS = 0; /** Number of blocks that can be requested at any given time from a single peer. */ @@ -146,7 +147,10 @@ extern std::condition_variable g_best_block_cv; extern uint256 g_best_block; extern std::atomic_bool fImporting; extern std::atomic_bool fReindex; -extern int nScriptCheckThreads; +/** Whether there are dedicated script-checking threads running. + * False indicates all script checking is done on the main threadMessageHandler thread. + */ +extern bool g_parallel_script_checks; extern bool fRequireStandard; extern bool fCheckBlockIndex; extern bool fCheckpointsEnabled; diff --git a/src/wallet/rpcdump.cpp b/src/wallet/rpcdump.cpp index 0d14d86d02..d95481500d 100644 --- a/src/wallet/rpcdump.cpp +++ b/src/wallet/rpcdump.cpp @@ -87,15 +87,6 @@ static void RescanWallet(CWallet& wallet, const WalletRescanReserver& reserver, } } -static LegacyScriptPubKeyMan& GetLegacyScriptPubKeyMan(CWallet& wallet) -{ - LegacyScriptPubKeyMan* spk_man = wallet.GetLegacyScriptPubKeyMan(); - if (!spk_man) { - throw JSONRPCError(RPC_WALLET_ERROR, "This type of wallet does not support this command"); - } - return *spk_man; -} - UniValue importprivkey(const JSONRPCRequest& request) { std::shared_ptr<CWallet> const wallet = GetWalletForJSONRPCRequest(request); @@ -134,7 +125,7 @@ UniValue importprivkey(const JSONRPCRequest& request) throw JSONRPCError(RPC_WALLET_ERROR, "Cannot import private keys to a wallet with private keys disabled"); } - LegacyScriptPubKeyMan& spk_man = GetLegacyScriptPubKeyMan(*wallet); + EnsureLegacyScriptPubKeyMan(*wallet); WalletRescanReserver reserver(pwallet); bool fRescan = true; @@ -262,7 +253,7 @@ UniValue importaddress(const JSONRPCRequest& request) }, }.Check(request); - LegacyScriptPubKeyMan& spk_man = GetLegacyScriptPubKeyMan(*pwallet); + EnsureLegacyScriptPubKeyMan(*pwallet); std::string strLabel; if (!request.params[1].isNull()) @@ -463,7 +454,7 @@ UniValue importpubkey(const JSONRPCRequest& request) }, }.Check(request); - LegacyScriptPubKeyMan& spk_man = GetLegacyScriptPubKeyMan(*wallet); + EnsureLegacyScriptPubKeyMan(*wallet); std::string strLabel; if (!request.params[1].isNull()) @@ -547,7 +538,7 @@ UniValue importwallet(const JSONRPCRequest& request) }, }.Check(request); - LegacyScriptPubKeyMan& spk_man = GetLegacyScriptPubKeyMan(*wallet); + EnsureLegacyScriptPubKeyMan(*wallet); if (pwallet->chain().havePruned()) { // Exit early and print an error. @@ -706,7 +697,7 @@ UniValue dumpprivkey(const JSONRPCRequest& request) }, }.Check(request); - LegacyScriptPubKeyMan& spk_man = GetLegacyScriptPubKeyMan(*wallet); + LegacyScriptPubKeyMan& spk_man = EnsureLegacyScriptPubKeyMan(*wallet); auto locked_chain = pwallet->chain().lock(); LOCK(pwallet->cs_wallet); @@ -757,7 +748,7 @@ UniValue dumpwallet(const JSONRPCRequest& request) }, }.Check(request); - LegacyScriptPubKeyMan& spk_man = GetLegacyScriptPubKeyMan(*wallet); + LegacyScriptPubKeyMan& spk_man = EnsureLegacyScriptPubKeyMan(*wallet); auto locked_chain = pwallet->chain().lock(); LOCK(pwallet->cs_wallet); @@ -1344,7 +1335,7 @@ UniValue importmulti(const JSONRPCRequest& mainRequest) RPCTypeCheck(mainRequest.params, {UniValue::VARR, UniValue::VOBJ}); - LegacyScriptPubKeyMan& spk_man = GetLegacyScriptPubKeyMan(*wallet); + EnsureLegacyScriptPubKeyMan(*wallet); const UniValue& requests = mainRequest.params[0]; diff --git a/src/wallet/rpcwallet.cpp b/src/wallet/rpcwallet.cpp index f3bd223b98..0f146563bf 100644 --- a/src/wallet/rpcwallet.cpp +++ b/src/wallet/rpcwallet.cpp @@ -124,6 +124,15 @@ void EnsureWalletIsUnlocked(const CWallet* pwallet) } } +LegacyScriptPubKeyMan& EnsureLegacyScriptPubKeyMan(CWallet& wallet) +{ + LegacyScriptPubKeyMan* spk_man = wallet.GetLegacyScriptPubKeyMan(); + if (!spk_man) { + throw JSONRPCError(RPC_WALLET_ERROR, "This type of wallet does not support this command"); + } + return *spk_man; +} + static void WalletTxToJSON(interfaces::Chain& chain, interfaces::Chain::Lock& locked_chain, const CWalletTx& wtx, UniValue& entry) { int confirms = wtx.GetDepthInMainChain(); @@ -966,10 +975,7 @@ static UniValue addmultisigaddress(const JSONRPCRequest& request) }, }.Check(request); - LegacyScriptPubKeyMan* spk_man = pwallet->GetLegacyScriptPubKeyMan(); - if (!spk_man) { - throw JSONRPCError(RPC_WALLET_ERROR, "This type of wallet does not support this command"); - } + LegacyScriptPubKeyMan& spk_man = EnsureLegacyScriptPubKeyMan(*pwallet); auto locked_chain = pwallet->chain().lock(); LOCK(pwallet->cs_wallet); @@ -987,7 +993,7 @@ static UniValue addmultisigaddress(const JSONRPCRequest& request) if (IsHex(keys_or_addrs[i].get_str()) && (keys_or_addrs[i].get_str().length() == 66 || keys_or_addrs[i].get_str().length() == 130)) { pubkeys.push_back(HexToPubKey(keys_or_addrs[i].get_str())); } else { - pubkeys.push_back(AddrToPubKey(spk_man, keys_or_addrs[i].get_str())); + pubkeys.push_back(AddrToPubKey(&spk_man, keys_or_addrs[i].get_str())); } } @@ -1000,7 +1006,7 @@ static UniValue addmultisigaddress(const JSONRPCRequest& request) // Construct using pay-to-script-hash: CScript inner; - CTxDestination dest = AddAndGetMultisigDestination(required, pubkeys, output_type, *spk_man, inner); + CTxDestination dest = AddAndGetMultisigDestination(required, pubkeys, output_type, spk_man, inner); pwallet->SetAddressBook(dest, label, "send"); UniValue result(UniValue::VOBJ); @@ -3758,15 +3764,7 @@ UniValue getaddressinfo(const JSONRPCRequest& request) ScriptPubKeyMan* spk_man = pwallet->GetScriptPubKeyMan(); if (spk_man) { - CKeyID key_id = GetKeyForDestination(*provider, dest); - const CKeyMetadata* meta = nullptr; - if (!key_id.IsNull()) { - meta = spk_man->GetMetadata(key_id); - } - if (!meta) { - meta = spk_man->GetMetadata(CScriptID(scriptPubKey)); - } - if (meta) { + if (const CKeyMetadata* meta = spk_man->GetMetadata(dest)) { ret.pushKV("timestamp", meta->nCreateTime); if (meta->has_key_origin) { ret.pushKV("hdkeypath", WriteHDKeypath(meta->key_origin.path)); @@ -3932,10 +3930,7 @@ UniValue sethdseed(const JSONRPCRequest& request) }, }.Check(request); - LegacyScriptPubKeyMan* spk_man = pwallet->GetLegacyScriptPubKeyMan(); - if (!spk_man) { - throw JSONRPCError(RPC_WALLET_ERROR, "This type of wallet does not support this command"); - } + LegacyScriptPubKeyMan& spk_man = EnsureLegacyScriptPubKeyMan(*pwallet); if (pwallet->chain().isInitialBlockDownload()) { throw JSONRPCError(RPC_CLIENT_IN_INITIAL_DOWNLOAD, "Cannot set a new HD seed while still in Initial Block Download"); @@ -3962,22 +3957,22 @@ UniValue sethdseed(const JSONRPCRequest& request) CPubKey master_pub_key; if (request.params[1].isNull()) { - master_pub_key = spk_man->GenerateNewSeed(); + master_pub_key = spk_man.GenerateNewSeed(); } else { CKey key = DecodeSecret(request.params[1].get_str()); if (!key.IsValid()) { throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Invalid private key"); } - if (HaveKey(*spk_man, key)) { + if (HaveKey(spk_man, key)) { throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Already have this key (either as an HD seed or as a loose private key)"); } - master_pub_key = spk_man->DeriveNewSeed(key); + master_pub_key = spk_man.DeriveNewSeed(key); } - spk_man->SetHDSeed(master_pub_key); - if (flush_key_pool) spk_man->NewKeyPool(); + spk_man.SetHDSeed(master_pub_key); + if (flush_key_pool) spk_man.NewKeyPool(); return NullUniValue; } diff --git a/src/wallet/rpcwallet.h b/src/wallet/rpcwallet.h index 31d3f7a5f9..becca455f6 100644 --- a/src/wallet/rpcwallet.h +++ b/src/wallet/rpcwallet.h @@ -12,6 +12,7 @@ class CRPCTable; class CWallet; class JSONRPCRequest; +class LegacyScriptPubKeyMan; class UniValue; struct PartiallySignedTransaction; class CTransaction; @@ -40,6 +41,7 @@ std::shared_ptr<CWallet> GetWalletForJSONRPCRequest(const JSONRPCRequest& reques std::string HelpRequiringPassphrase(const CWallet*); void EnsureWalletIsUnlocked(const CWallet*); bool EnsureWalletIsAvailable(const CWallet*, bool avoidException); +LegacyScriptPubKeyMan& EnsureLegacyScriptPubKeyMan(CWallet& wallet); UniValue getaddressinfo(const JSONRPCRequest& request); UniValue signrawtransactionwithwallet(const JSONRPCRequest& request); diff --git a/src/wallet/scriptpubkeyman.cpp b/src/wallet/scriptpubkeyman.cpp index bb13db11ba..3eaaf3786c 100644 --- a/src/wallet/scriptpubkeyman.cpp +++ b/src/wallet/scriptpubkeyman.cpp @@ -14,7 +14,7 @@ bool LegacyScriptPubKeyMan::GetNewDestination(const OutputType type, CTxDestination& dest, std::string& error) { error.clear(); - TopUpKeyPool(); + TopUp(); // Generate a new key that is added to wallet CPubKey new_key; @@ -264,10 +264,8 @@ bool LegacyScriptPubKeyMan::EncryptKeys(CKeyingMaterial& vMasterKeyIn) bool LegacyScriptPubKeyMan::GetReservedDestination(const OutputType type, bool internal, int64_t& index, CKeyPool& keypool) { - { - if (!ReserveKeyFromKeyPool(index, keypool, internal)) { - return false; - } + if (!ReserveKeyFromKeyPool(index, keypool, internal)) { + return false; } return true; } @@ -282,11 +280,6 @@ void LegacyScriptPubKeyMan::ReturnDestination(int64_t index, bool internal, cons ReturnKey(index, internal, pubkey); } -bool LegacyScriptPubKeyMan::TopUp(unsigned int size) -{ - return TopUpKeyPool(size); -} - void LegacyScriptPubKeyMan::MarkUnusedAddresses(const CScript& script) { AssertLockHeld(cs_wallet); @@ -297,7 +290,7 @@ void LegacyScriptPubKeyMan::MarkUnusedAddresses(const CScript& script) WalletLogPrintf("%s: Detected a used keypool key, mark all keypool key up to this key as used\n", __func__); MarkReserveKeysAsUsed(mi->second); - if (!TopUpKeyPool()) { + if (!TopUp()) { WalletLogPrintf("%s: Topping up keypool failed (locked wallet)\n", __func__); } } @@ -401,7 +394,7 @@ bool LegacyScriptPubKeyMan::Upgrade(int prev_version, std::string& error) } // Regenerate the keypool if upgraded to HD if (hd_upgrade) { - if (!TopUpKeyPool()) { + if (!TopUp()) { error = _("Unable to generate keys").translated; return false; } @@ -476,18 +469,24 @@ int64_t LegacyScriptPubKeyMan::GetTimeFirstKey() const return nTimeFirstKey; } -const CKeyMetadata* LegacyScriptPubKeyMan::GetMetadata(uint160 id) const +const CKeyMetadata* LegacyScriptPubKeyMan::GetMetadata(const CTxDestination& dest) const { AssertLockHeld(cs_wallet); - auto it = mapKeyMetadata.find(CKeyID(id)); - if (it != mapKeyMetadata.end()) { - return &it->second; - } else { - auto it2 = m_script_metadata.find(CScriptID(id)); - if (it2 != m_script_metadata.end()) { - return &it2->second; + + CKeyID key_id = GetKeyForDestination(*this, dest); + if (!key_id.IsNull()) { + auto it = mapKeyMetadata.find(key_id); + if (it != mapKeyMetadata.end()) { + return &it->second; } } + + CScript scriptPubKey = GetScriptForDestination(dest); + auto it = m_script_metadata.find(CScriptID(scriptPubKey)); + if (it != m_script_metadata.end()) { + return &it->second; + } + return nullptr; } @@ -1023,7 +1022,7 @@ bool LegacyScriptPubKeyMan::NewKeyPool() m_pool_key_to_index.clear(); - if (!TopUpKeyPool()) { + if (!TopUp()) { return false; } WalletLogPrintf("LegacyScriptPubKeyMan::NewKeyPool rewrote keypool\n"); @@ -1031,7 +1030,7 @@ bool LegacyScriptPubKeyMan::NewKeyPool() return true; } -bool LegacyScriptPubKeyMan::TopUpKeyPool(unsigned int kpSize) +bool LegacyScriptPubKeyMan::TopUp(unsigned int kpSize) { if (!CanGenerateKeys()) { return false; @@ -1148,7 +1147,7 @@ bool LegacyScriptPubKeyMan::ReserveKeyFromKeyPool(int64_t& nIndex, CKeyPool& key { LOCK(cs_wallet); - TopUpKeyPool(); + TopUp(); bool fReturningInternal = fRequestedInternal; fReturningInternal &= (IsHDEnabled() && m_storage.CanSupportFeature(FEATURE_HD_SPLIT)) || m_storage.IsWalletFlagSet(WALLET_FLAG_DISABLE_PRIVATE_KEYS); diff --git a/src/wallet/scriptpubkeyman.h b/src/wallet/scriptpubkeyman.h index 0dbf98ee94..4f17156792 100644 --- a/src/wallet/scriptpubkeyman.h +++ b/src/wallet/scriptpubkeyman.h @@ -186,7 +186,8 @@ public: virtual int64_t GetTimeFirstKey() const { return 0; } - virtual const CKeyMetadata* GetMetadata(uint160 id) const { return nullptr; } + //! Return address metadata + virtual const CKeyMetadata* GetMetadata(const CTxDestination& dest) const { return nullptr; } }; class LegacyScriptPubKeyMan : public ScriptPubKeyMan, public FillableSigningProvider @@ -302,7 +303,7 @@ public: int64_t GetTimeFirstKey() const override; - const CKeyMetadata* GetMetadata(uint160 id) const override; + const CKeyMetadata* GetMetadata(const CTxDestination& dest) const override; bool CanGetAddresses(bool internal = false) override; @@ -355,7 +356,6 @@ public: //! Load a keypool entry void LoadKeyPool(int64_t nIndex, const CKeyPool &keypool) EXCLUSIVE_LOCKS_REQUIRED(cs_wallet); - bool TopUpKeyPool(unsigned int kpSize = 0); bool NewKeyPool(); void MarkPreSplitKeys() EXCLUSIVE_LOCKS_REQUIRED(cs_wallet); diff --git a/src/wallet/test/coinselector_tests.cpp b/src/wallet/test/coinselector_tests.cpp index 397e6ea9d3..bc068f1499 100644 --- a/src/wallet/test/coinselector_tests.cpp +++ b/src/wallet/test/coinselector_tests.cpp @@ -9,7 +9,7 @@ #include <amount.h> #include <primitives/transaction.h> #include <random.h> -#include <test/setup_common.h> +#include <test/util/setup_common.h> #include <wallet/test/wallet_test_fixture.h> #include <boost/test/unit_test.hpp> diff --git a/src/wallet/test/db_tests.cpp b/src/wallet/test/db_tests.cpp index c961456572..f4a4c9fa7c 100644 --- a/src/wallet/test/db_tests.cpp +++ b/src/wallet/test/db_tests.cpp @@ -7,7 +7,7 @@ #include <boost/test/unit_test.hpp> #include <fs.h> -#include <test/setup_common.h> +#include <test/util/setup_common.h> #include <wallet/db.h> diff --git a/src/wallet/test/init_test_fixture.h b/src/wallet/test/init_test_fixture.h index eb4e72c88b..6ba7d66b7c 100644 --- a/src/wallet/test/init_test_fixture.h +++ b/src/wallet/test/init_test_fixture.h @@ -7,7 +7,7 @@ #include <interfaces/chain.h> #include <node/context.h> -#include <test/setup_common.h> +#include <test/util/setup_common.h> struct InitWalletDirTestingSetup: public BasicTestingSetup { diff --git a/src/wallet/test/init_tests.cpp b/src/wallet/test/init_tests.cpp index 279542ffad..c228e06009 100644 --- a/src/wallet/test/init_tests.cpp +++ b/src/wallet/test/init_tests.cpp @@ -5,7 +5,8 @@ #include <boost/test/unit_test.hpp> #include <noui.h> -#include <test/setup_common.h> +#include <test/util/logging.h> +#include <test/util/setup_common.h> #include <util/system.h> #include <wallet/test/init_test_fixture.h> @@ -34,28 +35,31 @@ BOOST_AUTO_TEST_CASE(walletinit_verify_walletdir_custom) BOOST_AUTO_TEST_CASE(walletinit_verify_walletdir_does_not_exist) { SetWalletDir(m_walletdir_path_cases["nonexistent"]); - noui_suppress(); - bool result = m_chain_client->verify(); - noui_reconnect(); - BOOST_CHECK(result == false); + { + ASSERT_DEBUG_LOG("does not exist"); + bool result = m_chain_client->verify(); + BOOST_CHECK(result == false); + } } BOOST_AUTO_TEST_CASE(walletinit_verify_walletdir_is_not_directory) { SetWalletDir(m_walletdir_path_cases["file"]); - noui_suppress(); - bool result = m_chain_client->verify(); - noui_reconnect(); - BOOST_CHECK(result == false); + { + ASSERT_DEBUG_LOG("is not a directory"); + bool result = m_chain_client->verify(); + BOOST_CHECK(result == false); + } } BOOST_AUTO_TEST_CASE(walletinit_verify_walletdir_is_not_relative) { SetWalletDir(m_walletdir_path_cases["relative"]); - noui_suppress(); - bool result = m_chain_client->verify(); - noui_reconnect(); - BOOST_CHECK(result == false); + { + ASSERT_DEBUG_LOG("is a relative path"); + bool result = m_chain_client->verify(); + BOOST_CHECK(result == false); + } } BOOST_AUTO_TEST_CASE(walletinit_verify_walletdir_no_trailing) diff --git a/src/wallet/test/ismine_tests.cpp b/src/wallet/test/ismine_tests.cpp index 24636fd599..76c3639d16 100644 --- a/src/wallet/test/ismine_tests.cpp +++ b/src/wallet/test/ismine_tests.cpp @@ -6,7 +6,7 @@ #include <node/context.h> #include <script/script.h> #include <script/standard.h> -#include <test/setup_common.h> +#include <test/util/setup_common.h> #include <wallet/ismine.h> #include <wallet/wallet.h> diff --git a/src/wallet/test/psbt_wallet_tests.cpp b/src/wallet/test/psbt_wallet_tests.cpp index 27a64ff12f..d930ca6bea 100644 --- a/src/wallet/test/psbt_wallet_tests.cpp +++ b/src/wallet/test/psbt_wallet_tests.cpp @@ -9,7 +9,7 @@ #include <wallet/wallet.h> #include <boost/test/unit_test.hpp> -#include <test/setup_common.h> +#include <test/util/setup_common.h> #include <wallet/test/wallet_test_fixture.h> BOOST_FIXTURE_TEST_SUITE(psbt_wallet_tests, WalletTestingSetup) diff --git a/src/wallet/test/wallet_crypto_tests.cpp b/src/wallet/test/wallet_crypto_tests.cpp index 2f41813234..97f8c94fa6 100644 --- a/src/wallet/test/wallet_crypto_tests.cpp +++ b/src/wallet/test/wallet_crypto_tests.cpp @@ -2,7 +2,7 @@ // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. -#include <test/setup_common.h> +#include <test/util/setup_common.h> #include <util/strencodings.h> #include <wallet/crypter.h> diff --git a/src/wallet/test/wallet_test_fixture.h b/src/wallet/test/wallet_test_fixture.h index def6f1934e..4e4129fb2c 100644 --- a/src/wallet/test/wallet_test_fixture.h +++ b/src/wallet/test/wallet_test_fixture.h @@ -5,7 +5,7 @@ #ifndef BITCOIN_WALLET_TEST_WALLET_TEST_FIXTURE_H #define BITCOIN_WALLET_TEST_WALLET_TEST_FIXTURE_H -#include <test/setup_common.h> +#include <test/util/setup_common.h> #include <interfaces/chain.h> #include <interfaces/wallet.h> diff --git a/src/wallet/test/wallet_tests.cpp b/src/wallet/test/wallet_tests.cpp index 93d2a716a3..34520bb549 100644 --- a/src/wallet/test/wallet_tests.cpp +++ b/src/wallet/test/wallet_tests.cpp @@ -12,7 +12,7 @@ #include <node/context.h> #include <policy/policy.h> #include <rpc/server.h> -#include <test/setup_common.h> +#include <test/util/setup_common.h> #include <validation.h> #include <wallet/coincontrol.h> #include <wallet/test/wallet_test_fixture.h> diff --git a/src/wallet/wallet.cpp b/src/wallet/wallet.cpp index 2bc39ea3d9..8ac551d03a 100644 --- a/src/wallet/wallet.cpp +++ b/src/wallet/wallet.cpp @@ -572,7 +572,9 @@ bool CWallet::EncryptWallet(const SecureString& strWalletPassphrase) // if we are using HD, replace the HD seed with a new one if (auto spk_man = m_spk_man.get()) { if (spk_man->IsHDEnabled()) { - spk_man->SetupGeneration(true); + if (!spk_man->SetupGeneration(true)) { + return false; + } } } Lock(); |