diff options
96 files changed, 557 insertions, 191 deletions
diff --git a/src/init.cpp b/src/init.cpp index ff8f3cb753..45689f7ecd 100644 --- a/src/init.cpp +++ b/src/init.cpp @@ -443,7 +443,7 @@ void SetupServerArgs() gArgs.AddArg("-debug=<category>", "Output debugging information (default: -nodebug, supplying <category> is optional). " "If <category> is not supplied or if <category> = 1, output all debugging information. <category> can be: " + ListLogCategories() + ".", false, OptionsCategory::DEBUG_TEST); gArgs.AddArg("-debugexclude=<category>", strprintf("Exclude debugging information for a category. Can be used in conjunction with -debug=1 to output debug logs for all categories except one or more specified categories."), false, OptionsCategory::DEBUG_TEST); - gArgs.AddArg("-help-debug", "Show all debugging options (usage: --help -help-debug)", false, OptionsCategory::DEBUG_TEST); + gArgs.AddArg("-help-debug", "Print help message with debugging options and exit", false, OptionsCategory::DEBUG_TEST); gArgs.AddArg("-logips", strprintf("Include IP addresses in debug output (default: %u)", DEFAULT_LOGIPS), false, OptionsCategory::DEBUG_TEST); gArgs.AddArg("-logtimestamps", strprintf("Prepend debug output with timestamp (default: %u)", DEFAULT_LOGTIMESTAMPS), false, OptionsCategory::DEBUG_TEST); gArgs.AddArg("-logtimemicros", strprintf("Add microsecond precision to debug timestamps (default: %u)", DEFAULT_LOGTIMEMICROS), true, OptionsCategory::DEBUG_TEST); diff --git a/src/key.cpp b/src/key.cpp index df452cd330..80d6589a3c 100644 --- a/src/key.cpp +++ b/src/key.cpp @@ -89,7 +89,7 @@ static int ec_privkey_import_der(const secp256k1_context* ctx, unsigned char *ou * will be set to the number of bytes used in the buffer. * key32 must point to a 32-byte raw private key. */ -static int ec_privkey_export_der(const secp256k1_context *ctx, unsigned char *privkey, size_t *privkeylen, const unsigned char *key32, int compressed) { +static int ec_privkey_export_der(const secp256k1_context *ctx, unsigned char *privkey, size_t *privkeylen, const unsigned char *key32, bool compressed) { assert(*privkeylen >= CKey::PRIVATE_KEY_SIZE); secp256k1_pubkey pubkey; size_t pubkeylen = 0; @@ -170,7 +170,7 @@ CPrivKey CKey::GetPrivKey() const { size_t privkeylen; privkey.resize(PRIVATE_KEY_SIZE); privkeylen = PRIVATE_KEY_SIZE; - ret = ec_privkey_export_der(secp256k1_context_sign, privkey.data(), &privkeylen, begin(), fCompressed ? SECP256K1_EC_COMPRESSED : SECP256K1_EC_UNCOMPRESSED); + ret = ec_privkey_export_der(secp256k1_context_sign, privkey.data(), &privkeylen, begin(), fCompressed); assert(ret); privkey.resize(privkeylen); return privkey; diff --git a/src/logging.h b/src/logging.h index 6400b131c2..0c8e7f5291 100644 --- a/src/logging.h +++ b/src/logging.h @@ -125,42 +125,31 @@ std::vector<CLogCategoryActive> ListActiveLogCategories(); /** Return true if str parses as a log category and set the flag */ bool GetLogCategory(BCLog::LogFlags& flag, const std::string& str); -/** Get format string from VA_ARGS for error reporting */ -template<typename... Args> std::string FormatStringFromLogArgs(const char *fmt, const Args&... args) { return fmt; } - -static inline void MarkUsed() {} -template<typename T, typename... Args> static inline void MarkUsed(const T& t, const Args&... args) -{ - (void)t; - MarkUsed(args...); -} - // Be conservative when using LogPrintf/error or other things which // unconditionally log to debug.log! It should not be the case that an inbound // peer can fill up a user's disk with debug.log entries. -#ifdef USE_COVERAGE -#define LogPrintf(...) do { MarkUsed(__VA_ARGS__); } while(0) -#define LogPrint(category, ...) do { MarkUsed(__VA_ARGS__); } while(0) -#else -#define LogPrintf(...) do { \ - if (g_logger->Enabled()) { \ - std::string _log_msg_; /* Unlikely name to avoid shadowing variables */ \ - try { \ - _log_msg_ = tfm::format(__VA_ARGS__); \ - } catch (tinyformat::format_error &fmterr) { \ - /* Original format string will have newline so don't add one here */ \ - _log_msg_ = "Error \"" + std::string(fmterr.what()) + "\" while formatting log message: " + FormatStringFromLogArgs(__VA_ARGS__); \ - } \ - g_logger->LogPrintStr(_log_msg_); \ - } \ -} while(0) - -#define LogPrint(category, ...) do { \ - if (LogAcceptCategory((category))) { \ - LogPrintf(__VA_ARGS__); \ - } \ -} while(0) -#endif +template <typename... Args> +static inline void LogPrintf(const char* fmt, const Args&... args) +{ + if (g_logger->Enabled()) { + std::string log_msg; + try { + log_msg = tfm::format(fmt, args...); + } catch (tinyformat::format_error& fmterr) { + /* Original format string will have newline so don't add one here */ + log_msg = "Error \"" + std::string(fmterr.what()) + "\" while formatting log message: " + fmt; + } + g_logger->LogPrintStr(log_msg); + } +} + +template <typename... Args> +static inline void LogPrint(const BCLog::LogFlags& category, const Args&... args) +{ + if (LogAcceptCategory((category))) { + LogPrintf(args...); + } +} #endif // BITCOIN_LOGGING_H diff --git a/src/netbase.cpp b/src/netbase.cpp index 4b63757f3d..093fd0bdb7 100644 --- a/src/netbase.cpp +++ b/src/netbase.cpp @@ -17,6 +17,8 @@ #ifndef WIN32 #include <fcntl.h> +#else +#include <codecvt> #endif #if !defined(MSG_NOSIGNAL) @@ -649,13 +651,13 @@ bool LookupSubNet(const char* pszName, CSubNet& ret) #ifdef WIN32 std::string NetworkErrorString(int err) { - char buf[256]; + wchar_t buf[256]; buf[0] = 0; - if(FormatMessageA(FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS | FORMAT_MESSAGE_MAX_WIDTH_MASK, + if(FormatMessageW(FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS | FORMAT_MESSAGE_MAX_WIDTH_MASK, nullptr, err, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), - buf, sizeof(buf), nullptr)) + buf, ARRAYSIZE(buf), nullptr)) { - return strprintf("%s (%d)", buf, err); + return strprintf("%s (%d)", std::wstring_convert<std::codecvt_utf8_utf16<wchar_t>,wchar_t>().to_bytes(buf), err); } else { diff --git a/src/qt/paymentrequestplus.cpp b/src/qt/paymentrequestplus.cpp index 944bcc8ad0..a989988c45 100644 --- a/src/qt/paymentrequestplus.cpp +++ b/src/qt/paymentrequestplus.cpp @@ -142,7 +142,6 @@ bool PaymentRequestPlus::getMerchant(X509_STORE* certStore, QString& merchant) c if (result != 1) { int error = X509_STORE_CTX_get_error(store_ctx); // For testing payment requests, we allow self signed root certs! - // This option is just shown in the UI options, if -help-debug is enabled. if (!(error == X509_V_ERR_DEPTH_ZERO_SELF_SIGNED_CERT && gArgs.GetBoolArg("-allowselfsignedrootcertificates", DEFAULT_SELFSIGNED_ROOTCERTS))) { throw SSLVerifyError(X509_verify_cert_error_string(error)); } else { diff --git a/src/rpc/mining.cpp b/src/rpc/mining.cpp index 885ad834cf..b1bea85fef 100644 --- a/src/rpc/mining.cpp +++ b/src/rpc/mining.cpp @@ -750,11 +750,7 @@ static UniValue submitblock(const JSONRPCRequest& request) RegisterValidationInterface(&sc); bool accepted = ProcessNewBlock(Params(), blockptr, /* fForceProcessing */ true, /* fNewBlock */ &new_block); UnregisterValidationInterface(&sc); - if (!new_block) { - if (!accepted) { - // TODO Maybe pass down fNewBlock to AcceptBlockHeader, so it is properly set to true in this case? - return "invalid"; - } + if (!new_block && accepted) { return "duplicate"; } if (!sc.found) { diff --git a/src/util.cpp b/src/util.cpp index 20bdc5d0d8..ee8bc94584 100644 --- a/src/util.cpp +++ b/src/util.cpp @@ -660,7 +660,7 @@ std::string ArgsManager::GetHelpMessage() const bool HelpRequested(const ArgsManager& args) { - return args.IsArgSet("-?") || args.IsArgSet("-h") || args.IsArgSet("-help"); + return args.IsArgSet("-?") || args.IsArgSet("-h") || args.IsArgSet("-help") || args.IsArgSet("-help-debug"); } static const int screenWidth = 79; @@ -998,7 +998,7 @@ void CreatePidFile(const fs::path &path, pid_t pid) bool RenameOver(fs::path src, fs::path dest) { #ifdef WIN32 - return MoveFileExA(src.string().c_str(), dest.string().c_str(), + return MoveFileExW(src.wstring().c_str(), dest.wstring().c_str(), MOVEFILE_REPLACE_EXISTING) != 0; #else int rc = std::rename(src.string().c_str(), dest.string().c_str()); diff --git a/src/validation.cpp b/src/validation.cpp index d4a84c53b5..947192be0e 100644 --- a/src/validation.cpp +++ b/src/validation.cpp @@ -4133,6 +4133,7 @@ bool CChainState::ReplayBlocks(const CChainParams& params, CCoinsView* view) for (int nHeight = nForkHeight + 1; nHeight <= pindexNew->nHeight; ++nHeight) { const CBlockIndex* pindex = pindexNew->GetAncestor(nHeight); LogPrintf("Rolling forward %s (%i)\n", pindex->GetBlockHash().ToString(), nHeight); + uiInterface.ShowProgress(_("Replaying blocks..."), (int) ((nHeight - nForkHeight) * 100.0 / (pindexNew->nHeight - nForkHeight)) , false); if (!RollforwardBlock(pindex, cache, params)) return false; } diff --git a/test/functional/data/rpc_psbt.json b/test/functional/data/rpc_psbt.json index 9f970b4961..dd40a096de 100644 --- a/test/functional/data/rpc_psbt.json +++ b/test/functional/data/rpc_psbt.json @@ -69,14 +69,6 @@ }, { "privkeys" : [ - "cT7J9YpCwY3AVRFSjN6ukeEeWY6mhpbJPxRaDaP5QTdygQRxP9Au", - "cNBc3SWUip9PPm1GjRoLEJT6T41iNzCYtD7qro84FMnM5zEqeJsE" - ], - "psbt" : "cHNidP8BAJoCAAAAAljoeiG1ba8MI76OcHBFbDNvfLqlyHV5JPVFiHuyq911AAAAAAD/////g40EJ9DsZQpoqka7CwmK6kQiwHGyyng1Kgd5WdB86h0BAAAAAP////8CcKrwCAAAAAAWABTYXCtx0AYLCcmIauuBXlCZHdoSTQDh9QUAAAAAFgAUAK6pouXw+HaliN9VRuh0LR2HAI8AAAAAAAEAuwIAAAABqtc5MQGL0l+ErkALaISL4J23BurCrBgpi6vucatlb4sAAAAASEcwRAIgWPb8fGoz4bMVSNSByCbAFb0wE1qtQs1neQ2rZtKtJDsCIEoc7SYExnNbY5PltBaR3XiwDwxZQvufdRhW+qk4FX26Af7///8CgPD6AgAAAAAXqRQPuUY0IWlrgsgzryQceMF9295JNIfQ8gonAQAAABepFCnKdPigj4GZlCgYXJe12FLkBj9hh2UAAAABBEdSIQKVg785rgpgl0etGZrd1jT6YQhVnWxc05tMIYPxq5bgfyEC2rYf9JoU22p9ArDNH7t4/EsYMStbTlTa5Nui+/71NtdSriIGApWDvzmuCmCXR60Zmt3WNPphCFWdbFzTm0whg/GrluB/ENkMak8AAACAAAAAgAAAAIAiBgLath/0mhTban0CsM0fu3j8SxgxK1tOVNrk26L7/vU21xDZDGpPAAAAgAAAAIABAACAAQMEAQAAAAABASAAwusLAAAAABepFLf1+vQOPUClpFmx2zU18rcvqSHohwEEIgAgjCNTFzdDtZXftKB7crqOQuN5fadOh/59nXSX47ICiQMBBUdSIQMIncEMesbbVPkTKa9hczPbOIzq0MIx9yM3nRuZAwsC3CECOt2QTz1tz1nduQaw3uI1Kbf/ue1Q5ehhUZJoYCIfDnNSriIGAjrdkE89bc9Z3bkGsN7iNSm3/7ntUOXoYVGSaGAiHw5zENkMak8AAACAAAAAgAMAAIAiBgMIncEMesbbVPkTKa9hczPbOIzq0MIx9yM3nRuZAwsC3BDZDGpPAAAAgAAAAIACAACAAQMEAQAAAAAiAgOppMN/WZbTqiXbrGtXCvBlA5RJKUJGCzVHU+2e7KWHcRDZDGpPAAAAgAAAAIAEAACAACICAn9jmXV9Lv9VoTatAsaEsYOLZVbl8bazQoKpS2tQBRCWENkMak8AAACAAAAAgAUAAIAA", - "result" : "cHNidP8BAJoCAAAAAljoeiG1ba8MI76OcHBFbDNvfLqlyHV5JPVFiHuyq911AAAAAAD/////g40EJ9DsZQpoqka7CwmK6kQiwHGyyng1Kgd5WdB86h0BAAAAAP////8CcKrwCAAAAAAWABTYXCtx0AYLCcmIauuBXlCZHdoSTQDh9QUAAAAAFgAUAK6pouXw+HaliN9VRuh0LR2HAI8AAAAAAAEAuwIAAAABqtc5MQGL0l+ErkALaISL4J23BurCrBgpi6vucatlb4sAAAAASEcwRAIgWPb8fGoz4bMVSNSByCbAFb0wE1qtQs1neQ2rZtKtJDsCIEoc7SYExnNbY5PltBaR3XiwDwxZQvufdRhW+qk4FX26Af7///8CgPD6AgAAAAAXqRQPuUY0IWlrgsgzryQceMF9295JNIfQ8gonAQAAABepFCnKdPigj4GZlCgYXJe12FLkBj9hh2UAAAAiAgLath/0mhTban0CsM0fu3j8SxgxK1tOVNrk26L7/vU210cwRAIgYxqYn+c4qSrQGYYCMxLBkhT+KAKznly8GsNniAbGksMCIDnbbDh70mdxbf2z1NjaULjoXSEzJrp8faqkwM5B65IjAQEDBAEAAAABBEdSIQKVg785rgpgl0etGZrd1jT6YQhVnWxc05tMIYPxq5bgfyEC2rYf9JoU22p9ArDNH7t4/EsYMStbTlTa5Nui+/71NtdSriIGApWDvzmuCmCXR60Zmt3WNPphCFWdbFzTm0whg/GrluB/ENkMak8AAACAAAAAgAAAAIAiBgLath/0mhTban0CsM0fu3j8SxgxK1tOVNrk26L7/vU21xDZDGpPAAAAgAAAAIABAACAAAEBIADC6wsAAAAAF6kUt/X69A49QKWkWbHbNTXyty+pIeiHIgICOt2QTz1tz1nduQaw3uI1Kbf/ue1Q5ehhUZJoYCIfDnNHMEQCIGX0W6WZi1mif/4ae+0BavHx+Q1Us6qPdFCqX1aiUQO9AiB/ckcDrR7blmgLKEtW1P/LiPf7dZ6rvgiqMPKbhROD0gEBAwQBAAAAAQQiACCMI1MXN0O1ld+0oHtyuo5C43l9p06H/n2ddJfjsgKJAwEFR1IhAwidwQx6xttU+RMpr2FzM9s4jOrQwjH3IzedG5kDCwLcIQI63ZBPPW3PWd25BrDe4jUpt/+57VDl6GFRkmhgIh8Oc1KuIgYCOt2QTz1tz1nduQaw3uI1Kbf/ue1Q5ehhUZJoYCIfDnMQ2QxqTwAAAIAAAACAAwAAgCIGAwidwQx6xttU+RMpr2FzM9s4jOrQwjH3IzedG5kDCwLcENkMak8AAACAAAAAgAIAAIAAIgIDqaTDf1mW06ol26xrVwrwZQOUSSlCRgs1R1Ptnuylh3EQ2QxqTwAAAIAAAACABAAAgAAiAgJ/Y5l1fS7/VaE2rQLGhLGDi2VW5fG2s0KCqUtrUAUQlhDZDGpPAAAAgAAAAIAFAACAAA==" - }, - { - "privkeys" : [ "cNBc3SWUip9PPm1GjRoLEJT6T41iNzCYtD7qro84FMnM5zEqeJsE" ], "psbt" : "cHNidP8BAKACAAAAAqsJSaCMWvfEm4IS9Bfi8Vqz9cM9zxU4IagTn4d6W3vkAAAAAAD+////qwlJoIxa98SbghL0F+LxWrP1wz3PFTghqBOfh3pbe+QBAAAAAP7///8CYDvqCwAAAAAZdqkUdopAu9dAy+gdmI5x3ipNXHE5ax2IrI4kAAAAAAAAGXapFG9GILVT+glechue4O/p+gOcykWXiKwAAAAAAAEBItPf9QUAAAAAGXapFNSO0xELlAFMsRS9Mtb00GbcdCVriKwAAQEgAOH1BQAAAAAXqRQ1RebjO4MsRwUPJNPuuTycA5SLx4cBBBYAFIXRNTfy4mVAWjTbr6nj3aAfuCMIACICAurVlmh8qAYEPtw94RbN8p1eklfBls0FXPaYyNAr8k6ZELSmumcAAACAAAAAgAIAAIAAIgIDlPYr6d8ZlSxVh3aK63aYBhrSxKJciU9H2MFitNchPQUQtKa6ZwAAAIABAACAAgAAgAA=", diff --git a/test/functional/example_test.py b/test/functional/example_test.py index 3edd760b90..4c9d60b337 100755 --- a/test/functional/example_test.py +++ b/test/functional/example_test.py @@ -67,10 +67,11 @@ def custom_function(): # self.log.info("running custom_function") # Oops! Can't run self.log outside the BitcoinTestFramework pass + class ExampleTest(BitcoinTestFramework): # Each functional test is a subclass of the BitcoinTestFramework class. - # Override the set_test_params(), add_options(), setup_chain(), setup_network() + # Override the set_test_params(), skip_test_if_missing_module(), add_options(), setup_chain(), setup_network() # and setup_nodes() methods to customize the test setup as required. def set_test_params(self): @@ -84,6 +85,9 @@ class ExampleTest(BitcoinTestFramework): # self.log.info("I've finished set_test_params") # Oops! Can't run self.log before run_test() + def skip_test_if_missing_module(self): + self.skip_if_no_wallet() + # Use add_options() to add specific command-line options for your test. # In practice this is not used very much, since the tests are mostly written # to be run in automated environments without command-line options. diff --git a/test/functional/feature_bip68_sequence.py b/test/functional/feature_bip68_sequence.py index 4a9445f503..8466f851ca 100755 --- a/test/functional/feature_bip68_sequence.py +++ b/test/functional/feature_bip68_sequence.py @@ -25,6 +25,9 @@ class BIP68Test(BitcoinTestFramework): self.num_nodes = 2 self.extra_args = [[], ["-acceptnonstdtxn=0"]] + def skip_test_if_missing_module(self): + self.skip_if_no_wallet() + def run_test(self): self.relayfee = self.nodes[0].getnetworkinfo()["relayfee"] diff --git a/test/functional/feature_block.py b/test/functional/feature_block.py index 71c3a396c1..6e36ea5601 100755 --- a/test/functional/feature_block.py +++ b/test/functional/feature_block.py @@ -75,6 +75,9 @@ class FullBlockTest(BitcoinTestFramework): self.setup_clean_chain = True self.extra_args = [[]] + def skip_test_if_missing_module(self): + self.skip_if_no_wallet() + def run_test(self): node = self.nodes[0] # convenience reference to the node diff --git a/test/functional/feature_blocksdir.py b/test/functional/feature_blocksdir.py index 784dc2865f..824f0d7e09 100755 --- a/test/functional/feature_blocksdir.py +++ b/test/functional/feature_blocksdir.py @@ -16,6 +16,9 @@ class BlocksdirTest(BitcoinTestFramework): self.setup_clean_chain = True self.num_nodes = 1 + def skip_test_if_missing_module(self): + self.skip_if_no_wallet() + def run_test(self): self.stop_node(0) shutil.rmtree(self.nodes[0].datadir) diff --git a/test/functional/feature_cltv.py b/test/functional/feature_cltv.py index 615b0f8a4a..f84b08a199 100755 --- a/test/functional/feature_cltv.py +++ b/test/functional/feature_cltv.py @@ -62,6 +62,9 @@ class BIP65Test(BitcoinTestFramework): self.extra_args = [['-whitelist=127.0.0.1', '-par=1']] # Use only one script thread to get the exact reject reason for testing self.setup_clean_chain = True + def skip_test_if_missing_module(self): + self.skip_if_no_wallet() + def run_test(self): self.nodes[0].add_p2p_connection(P2PInterface()) diff --git a/test/functional/feature_config_args.py b/test/functional/feature_config_args.py index 9be59b32b4..1124119e2b 100755 --- a/test/functional/feature_config_args.py +++ b/test/functional/feature_config_args.py @@ -14,6 +14,9 @@ class ConfArgsTest(BitcoinTestFramework): self.setup_clean_chain = True self.num_nodes = 1 + def skip_test_if_missing_module(self): + self.skip_if_no_wallet() + def test_config_file_parser(self): # Assume node is stopped diff --git a/test/functional/feature_csv_activation.py b/test/functional/feature_csv_activation.py index 302cfe4266..df79c4312c 100755 --- a/test/functional/feature_csv_activation.py +++ b/test/functional/feature_csv_activation.py @@ -145,6 +145,9 @@ class BIP68_112_113Test(BitcoinTestFramework): self.setup_clean_chain = True self.extra_args = [['-whitelist=127.0.0.1', '-blockversion=4', '-addresstype=legacy']] + def skip_test_if_missing_module(self): + self.skip_if_no_wallet() + def generate_blocks(self, number, version, test_blocks=None): if test_blocks is None: test_blocks = [] diff --git a/test/functional/feature_dbcrash.py b/test/functional/feature_dbcrash.py index d612dbe2bc..ae1eacf2d7 100755 --- a/test/functional/feature_dbcrash.py +++ b/test/functional/feature_dbcrash.py @@ -63,6 +63,9 @@ class ChainstateWriteCrashTest(BitcoinTestFramework): self.node3_args = ["-blockmaxweight=4000000"] self.extra_args = [self.node0_args, self.node1_args, self.node2_args, self.node3_args] + def skip_test_if_missing_module(self): + self.skip_if_no_wallet() + def setup_network(self): self.add_nodes(self.num_nodes, extra_args=self.extra_args) self.start_nodes() diff --git a/test/functional/feature_dersig.py b/test/functional/feature_dersig.py index 6072c5c178..16272877e7 100755 --- a/test/functional/feature_dersig.py +++ b/test/functional/feature_dersig.py @@ -49,6 +49,9 @@ class BIP66Test(BitcoinTestFramework): self.extra_args = [['-whitelist=127.0.0.1', '-par=1', '-enablebip61']] # Use only one script thread to get the exact reject reason for testing self.setup_clean_chain = True + def skip_test_if_missing_module(self): + self.skip_if_no_wallet() + def run_test(self): self.nodes[0].add_p2p_connection(P2PInterface()) diff --git a/test/functional/feature_fee_estimation.py b/test/functional/feature_fee_estimation.py index 709910f2e4..aaab4279b5 100755 --- a/test/functional/feature_fee_estimation.py +++ b/test/functional/feature_fee_estimation.py @@ -126,6 +126,9 @@ class EstimateFeeTest(BitcoinTestFramework): def set_test_params(self): self.num_nodes = 3 + def skip_test_if_missing_module(self): + self.skip_if_no_wallet() + def setup_network(self): """ We'll setup the network to have 3 nodes that all mine with different parameters. @@ -168,6 +171,11 @@ class EstimateFeeTest(BitcoinTestFramework): newmem.append(utx) self.memutxo = newmem + def import_deterministic_coinbase_privkeys(self): + self.start_nodes() + super().import_deterministic_coinbase_privkeys() + self.stop_nodes() + def run_test(self): self.log.info("This test is time consuming, please be patient") self.log.info("Splitting inputs so we can generate tx's") diff --git a/test/functional/feature_logging.py b/test/functional/feature_logging.py index 8bb7e02695..a74c413440 100755 --- a/test/functional/feature_logging.py +++ b/test/functional/feature_logging.py @@ -15,6 +15,9 @@ class LoggingTest(BitcoinTestFramework): self.num_nodes = 1 self.setup_clean_chain = True + def skip_test_if_missing_module(self): + self.skip_if_no_wallet() + def relative_log_path(self, name): return os.path.join(self.nodes[0].datadir, "regtest", name) diff --git a/test/functional/feature_maxuploadtarget.py b/test/functional/feature_maxuploadtarget.py index a81ebb4220..87c318de9a 100755 --- a/test/functional/feature_maxuploadtarget.py +++ b/test/functional/feature_maxuploadtarget.py @@ -40,6 +40,9 @@ class MaxUploadTest(BitcoinTestFramework): # Cache for utxos, as the listunspent may take a long time later in the test self.utxo_cache = [] + def skip_test_if_missing_module(self): + self.skip_if_no_wallet() + def run_test(self): # Before we connect anything, we first set the time on the node # to be in the past, otherwise things break because the CNode diff --git a/test/functional/feature_minchainwork.py b/test/functional/feature_minchainwork.py index a1cced0bc7..5d180c2244 100755 --- a/test/functional/feature_minchainwork.py +++ b/test/functional/feature_minchainwork.py @@ -31,6 +31,9 @@ class MinimumChainWorkTest(BitcoinTestFramework): self.extra_args = [[], ["-minimumchainwork=0x65"], ["-minimumchainwork=0x65"]] self.node_min_work = [0, 101, 101] + def skip_test_if_missing_module(self): + self.skip_if_no_wallet() + def setup_network(self): # This test relies on the chain setup being: # node0 <- node1 <- node2 diff --git a/test/functional/feature_notifications.py b/test/functional/feature_notifications.py index 71e5e493aa..25a7329a0d 100755 --- a/test/functional/feature_notifications.py +++ b/test/functional/feature_notifications.py @@ -13,6 +13,9 @@ class NotificationsTest(BitcoinTestFramework): self.num_nodes = 2 self.setup_clean_chain = True + def skip_test_if_missing_module(self): + self.skip_if_no_wallet() + def setup_network(self): self.alert_filename = os.path.join(self.options.tmpdir, "alert.txt") self.block_filename = os.path.join(self.options.tmpdir, "blocks.txt") diff --git a/test/functional/feature_nulldummy.py b/test/functional/feature_nulldummy.py index 9d1805ec2d..a79cc3d34b 100755 --- a/test/functional/feature_nulldummy.py +++ b/test/functional/feature_nulldummy.py @@ -44,9 +44,12 @@ class NULLDUMMYTest(BitcoinTestFramework): # normal segwit activation here (and don't use the default always-on behaviour). self.extra_args = [['-whitelist=127.0.0.1', '-vbparams=segwit:0:999999999999', '-addresstype=legacy', "-deprecatedrpc=addwitnessaddress"]] + def skip_test_if_missing_module(self): + self.skip_if_no_wallet() + def run_test(self): self.address = self.nodes[0].getnewaddress() - self.ms_address = self.nodes[0].addmultisigaddress(1,[self.address])['address'] + self.ms_address = self.nodes[0].addmultisigaddress(1, [self.address])['address'] self.wit_address = self.nodes[0].addwitnessaddress(self.address) self.wit_ms_address = self.nodes[0].addmultisigaddress(1, [self.address], '', 'p2sh-segwit')['address'] diff --git a/test/functional/feature_pruning.py b/test/functional/feature_pruning.py index c8f4b7f8b5..772151dc4b 100755 --- a/test/functional/feature_pruning.py +++ b/test/functional/feature_pruning.py @@ -33,15 +33,20 @@ class PruneTest(BitcoinTestFramework): # Create nodes 0 and 1 to mine. # Create node 2 to test pruning. - self.full_node_default_args = ["-maxreceivebuffer=20000", "-checkblocks=5", "-limitdescendantcount=100", "-limitdescendantsize=5000", "-limitancestorcount=100", "-limitancestorsize=5000" ] + self.full_node_default_args = ["-maxreceivebuffer=20000", "-checkblocks=5", "-limitdescendantcount=100", "-limitdescendantsize=5000", "-limitancestorcount=100", "-limitancestorsize=5000"] # Create nodes 3 and 4 to test manual pruning (they will be re-started with manual pruning later) # Create nodes 5 to test wallet in prune mode, but do not connect - self.extra_args = [self.full_node_default_args, - self.full_node_default_args, - ["-maxreceivebuffer=20000", "-prune=550"], - ["-maxreceivebuffer=20000"], - ["-maxreceivebuffer=20000"], - ["-prune=550"]] + self.extra_args = [ + self.full_node_default_args, + self.full_node_default_args, + ["-maxreceivebuffer=20000", "-prune=550"], + ["-maxreceivebuffer=20000"], + ["-maxreceivebuffer=20000"], + ["-prune=550"], + ] + + def skip_test_if_missing_module(self): + self.skip_if_no_wallet() def setup_network(self): self.setup_nodes() diff --git a/test/functional/feature_rbf.py b/test/functional/feature_rbf.py index 7e84ba43b5..ff7c2b23bf 100755 --- a/test/functional/feature_rbf.py +++ b/test/functional/feature_rbf.py @@ -61,17 +61,26 @@ def make_utxo(node, amount, confirmed=True, scriptPubKey=CScript([1])): return COutPoint(int(txid, 16), 0) -class ReplaceByFeeTest(BitcoinTestFramework): +class ReplaceByFeeTest(BitcoinTestFramework): def set_test_params(self): self.num_nodes = 2 - self.extra_args= [["-maxorphantx=1000", - "-whitelist=127.0.0.1", - "-limitancestorcount=50", - "-limitancestorsize=101", - "-limitdescendantcount=200", - "-limitdescendantsize=101"], - ["-mempoolreplacement=0"]] + self.extra_args = [ + [ + "-maxorphantx=1000", + "-whitelist=127.0.0.1", + "-limitancestorcount=50", + "-limitancestorsize=101", + "-limitdescendantcount=200", + "-limitdescendantsize=101", + ], + [ + "-mempoolreplacement=0", + ], + ] + + def skip_test_if_missing_module(self): + self.skip_if_no_wallet() def run_test(self): # Leave IBD diff --git a/test/functional/feature_reindex.py b/test/functional/feature_reindex.py index f30e1191e3..3727eeaeae 100755 --- a/test/functional/feature_reindex.py +++ b/test/functional/feature_reindex.py @@ -18,6 +18,9 @@ class ReindexTest(BitcoinTestFramework): self.setup_clean_chain = True self.num_nodes = 1 + def skip_test_if_missing_module(self): + self.skip_if_no_wallet() + def reindex(self, justchainstate=False): self.nodes[0].generate(3) blockcount = self.nodes[0].getblockcount() diff --git a/test/functional/feature_segwit.py b/test/functional/feature_segwit.py index 13d7758e13..2cbfc26e89 100755 --- a/test/functional/feature_segwit.py +++ b/test/functional/feature_segwit.py @@ -46,9 +46,30 @@ class SegWitTest(BitcoinTestFramework): self.setup_clean_chain = True self.num_nodes = 3 # This test tests SegWit both pre and post-activation, so use the normal BIP9 activation. - self.extra_args = [["-rpcserialversion=0", "-vbparams=segwit:0:999999999999", "-addresstype=legacy", "-deprecatedrpc=addwitnessaddress"], - ["-blockversion=4", "-rpcserialversion=1", "-vbparams=segwit:0:999999999999", "-addresstype=legacy", "-deprecatedrpc=addwitnessaddress"], - ["-blockversion=536870915", "-vbparams=segwit:0:999999999999", "-addresstype=legacy", "-deprecatedrpc=addwitnessaddress"]] + self.extra_args = [ + [ + "-rpcserialversion=0", + "-vbparams=segwit:0:999999999999", + "-addresstype=legacy", + "-deprecatedrpc=addwitnessaddress", + ], + [ + "-blockversion=4", + "-rpcserialversion=1", + "-vbparams=segwit:0:999999999999", + "-addresstype=legacy", + "-deprecatedrpc=addwitnessaddress", + ], + [ + "-blockversion=536870915", + "-vbparams=segwit:0:999999999999", + "-addresstype=legacy", + "-deprecatedrpc=addwitnessaddress", + ], + ] + + def skip_test_if_missing_module(self): + self.skip_if_no_wallet() def setup_network(self): super().setup_network() diff --git a/test/functional/feature_versionbits_warning.py b/test/functional/feature_versionbits_warning.py index 896c36fa53..cf77720437 100755 --- a/test/functional/feature_versionbits_warning.py +++ b/test/functional/feature_versionbits_warning.py @@ -31,6 +31,9 @@ class VersionBitsWarningTest(BitcoinTestFramework): self.setup_clean_chain = True self.num_nodes = 1 + def skip_test_if_missing_module(self): + self.skip_if_no_wallet() + def setup_network(self): self.alert_filename = os.path.join(self.options.tmpdir, "alert.txt") # Open and close to create zero-length file diff --git a/test/functional/interface_bitcoin_cli.py b/test/functional/interface_bitcoin_cli.py index d3b85ce948..f311858bee 100755 --- a/test/functional/interface_bitcoin_cli.py +++ b/test/functional/interface_bitcoin_cli.py @@ -12,6 +12,9 @@ class TestBitcoinCli(BitcoinTestFramework): self.setup_clean_chain = True self.num_nodes = 1 + def skip_test_if_missing_module(self): + self.skip_if_no_wallet() + def run_test(self): """Main test logic""" diff --git a/test/functional/interface_rest.py b/test/functional/interface_rest.py index 41a1b4a35d..afa9de580f 100755 --- a/test/functional/interface_rest.py +++ b/test/functional/interface_rest.py @@ -43,6 +43,9 @@ class RESTTest (BitcoinTestFramework): self.num_nodes = 2 self.extra_args = [["-rest"], []] + def skip_test_if_missing_module(self): + self.skip_if_no_wallet() + def test_rest_request(self, uri, http_method='GET', req_type=ReqType.JSON, body='', status=200, ret_type=RetType.JSON): rest_uri = '/rest' + uri if req_type == ReqType.JSON: diff --git a/test/functional/interface_zmq.py b/test/functional/interface_zmq.py index 72de696259..c853ba7e3f 100755 --- a/test/functional/interface_zmq.py +++ b/test/functional/interface_zmq.py @@ -5,15 +5,16 @@ """Test the ZMQ notification interface.""" import struct -from test_framework.test_framework import ( - BitcoinTestFramework, skip_if_no_bitcoind_zmq, skip_if_no_py3_zmq) +from test_framework.test_framework import BitcoinTestFramework from test_framework.messages import CTransaction -from test_framework.util import (assert_equal, - bytes_to_hex_str, - hash256, - ) +from test_framework.util import ( + assert_equal, + bytes_to_hex_str, + hash256, +) from io import BytesIO + class ZMQSubscriber: def __init__(self, socket, topic): self.sequence = 0 @@ -37,9 +38,18 @@ class ZMQTest (BitcoinTestFramework): def set_test_params(self): self.num_nodes = 2 + def skip_test_if_missing_module(self): + self.skip_if_no_py3_zmq() + self.skip_if_no_bitcoind_zmq() + self.skip_if_no_wallet() + def setup_nodes(self): - skip_if_no_py3_zmq() - skip_if_no_bitcoind_zmq(self) + # Import keys + self.add_nodes(self.num_nodes) + self.start_nodes() + super().import_deterministic_coinbase_privkeys() + self.stop_nodes() + import zmq # Initialize ZMQ context and socket. @@ -59,10 +69,12 @@ class ZMQTest (BitcoinTestFramework): self.rawblock = ZMQSubscriber(socket, b"rawblock") self.rawtx = ZMQSubscriber(socket, b"rawtx") - self.extra_args = [["-zmqpub%s=%s" % (sub.topic.decode(), address) for sub in [self.hashblock, self.hashtx, self.rawblock, self.rawtx]], []] - self.add_nodes(self.num_nodes, self.extra_args) + self.nodes[0].extra_args = ["-zmqpub%s=%s" % (sub.topic.decode(), address) for sub in [self.hashblock, self.hashtx, self.rawblock, self.rawtx]] self.start_nodes() + def import_deterministic_coinbase_privkeys(self): + pass + def run_test(self): try: self._zmq_test() diff --git a/test/functional/mempool_accept.py b/test/functional/mempool_accept.py index 44426a0ff7..8847777ba7 100755 --- a/test/functional/mempool_accept.py +++ b/test/functional/mempool_accept.py @@ -40,6 +40,9 @@ class MempoolAcceptanceTest(BitcoinTestFramework): '-acceptnonstdtxn=0', # Try to mimic main-net ]] * self.num_nodes + def skip_test_if_missing_module(self): + self.skip_if_no_wallet() + def check_mempool_result(self, result_expected, *args, **kwargs): """Wrapper to check result of testmempoolaccept on node_0's mempool""" result_test = self.nodes[0].testmempoolaccept(*args, **kwargs) diff --git a/test/functional/mempool_limit.py b/test/functional/mempool_limit.py index 55422b67df..c0918893cd 100755 --- a/test/functional/mempool_limit.py +++ b/test/functional/mempool_limit.py @@ -15,6 +15,9 @@ class MempoolLimitTest(BitcoinTestFramework): self.num_nodes = 1 self.extra_args = [["-maxmempool=5", "-spendzeroconfchange=0"]] + def skip_test_if_missing_module(self): + self.skip_if_no_wallet() + def run_test(self): txouts = gen_return_txouts() relayfee = self.nodes[0].getnetworkinfo()['relayfee'] diff --git a/test/functional/mempool_packages.py b/test/functional/mempool_packages.py index da254181fe..9336547a6b 100755 --- a/test/functional/mempool_packages.py +++ b/test/functional/mempool_packages.py @@ -18,6 +18,9 @@ class MempoolPackagesTest(BitcoinTestFramework): self.num_nodes = 2 self.extra_args = [["-maxorphantx=1000"], ["-maxorphantx=1000", "-limitancestorcount=5"]] + def skip_test_if_missing_module(self): + self.skip_if_no_wallet() + # Build a transaction that spends parent_txid:vout # Return amount sent def chain_transaction(self, node, parent_txid, vout, value, fee, num_outputs): @@ -34,7 +37,7 @@ class MempoolPackagesTest(BitcoinTestFramework): return (txid, send_value) def run_test(self): - ''' Mine some blocks and have them mature. ''' + # Mine some blocks and have them mature. self.nodes[0].generate(101) utxo = self.nodes[0].listunspent(10) txid = utxo[0]['txid'] diff --git a/test/functional/mempool_persist.py b/test/functional/mempool_persist.py index 6e5f89efb8..b4e9d967fd 100755 --- a/test/functional/mempool_persist.py +++ b/test/functional/mempool_persist.py @@ -47,6 +47,9 @@ class MempoolPersistTest(BitcoinTestFramework): self.num_nodes = 3 self.extra_args = [[], ["-persistmempool=0"], []] + def skip_test_if_missing_module(self): + self.skip_if_no_wallet() + def run_test(self): chain_height = self.nodes[0].getblockcount() assert_equal(chain_height, 200) diff --git a/test/functional/mempool_reorg.py b/test/functional/mempool_reorg.py index faa00d56cf..123f0b4c28 100755 --- a/test/functional/mempool_reorg.py +++ b/test/functional/mempool_reorg.py @@ -17,6 +17,9 @@ class MempoolCoinbaseTest(BitcoinTestFramework): def set_test_params(self): self.num_nodes = 2 + def skip_test_if_missing_module(self): + self.skip_if_no_wallet() + alert_filename = None # Set by setup_network def run_test(self): diff --git a/test/functional/mempool_resurrect.py b/test/functional/mempool_resurrect.py index 23939f0be5..d035ca907a 100755 --- a/test/functional/mempool_resurrect.py +++ b/test/functional/mempool_resurrect.py @@ -13,6 +13,9 @@ class MempoolCoinbaseTest(BitcoinTestFramework): def set_test_params(self): self.num_nodes = 1 + def skip_test_if_missing_module(self): + self.skip_if_no_wallet() + def run_test(self): node0_address = self.nodes[0].getnewaddress() # Spend block 1/2/3's coinbase transactions diff --git a/test/functional/mempool_spend_coinbase.py b/test/functional/mempool_spend_coinbase.py index ce3bc3b7e0..854d506f0d 100755 --- a/test/functional/mempool_spend_coinbase.py +++ b/test/functional/mempool_spend_coinbase.py @@ -21,6 +21,9 @@ class MempoolSpendCoinbaseTest(BitcoinTestFramework): def set_test_params(self): self.num_nodes = 1 + def skip_test_if_missing_module(self): + self.skip_if_no_wallet() + def run_test(self): chain_height = self.nodes[0].getblockcount() assert_equal(chain_height, 200) diff --git a/test/functional/mining_basic.py b/test/functional/mining_basic.py index b675cd882f..f95ad31e7c 100755 --- a/test/functional/mining_basic.py +++ b/test/functional/mining_basic.py @@ -38,9 +38,18 @@ class MiningTest(BitcoinTestFramework): self.num_nodes = 2 self.setup_clean_chain = False + def skip_test_if_missing_module(self): + self.skip_if_no_wallet() + def run_test(self): node = self.nodes[0] + def assert_submitblock(block, result_str_1, result_str_2=None): + block.solve() + result_str_2 = result_str_2 or 'duplicate-invalid' + assert_equal(result_str_1, node.submitblock(hexdata=b2x(block.serialize()))) + assert_equal(result_str_2, node.submitblock(hexdata=b2x(block.serialize()))) + self.log.info('getmininginfo') mining_info = node.getmininginfo() assert_equal(mining_info['blocks'], 200) @@ -93,6 +102,7 @@ class MiningTest(BitcoinTestFramework): bad_block = copy.deepcopy(block) bad_block.vtx.append(bad_block.vtx[0]) assert_template(node, bad_block, 'bad-txns-duplicate') + assert_submitblock(bad_block, 'bad-txns-duplicate', 'bad-txns-duplicate') self.log.info("getblocktemplate: Test invalid transaction") bad_block = copy.deepcopy(block) @@ -101,12 +111,14 @@ class MiningTest(BitcoinTestFramework): bad_tx.rehash() bad_block.vtx.append(bad_tx) assert_template(node, bad_block, 'bad-txns-inputs-missingorspent') + assert_submitblock(bad_block, 'bad-txns-inputs-missingorspent') self.log.info("getblocktemplate: Test nonfinal transaction") bad_block = copy.deepcopy(block) bad_block.vtx[0].nLockTime = 2 ** 32 - 1 bad_block.vtx[0].rehash() assert_template(node, bad_block, 'bad-txns-nonfinal') + assert_submitblock(bad_block, 'bad-txns-nonfinal') self.log.info("getblocktemplate: Test bad tx count") # The tx count is immediately after the block header @@ -125,24 +137,29 @@ class MiningTest(BitcoinTestFramework): bad_block = copy.deepcopy(block) bad_block.hashMerkleRoot += 1 assert_template(node, bad_block, 'bad-txnmrklroot', False) + assert_submitblock(bad_block, 'bad-txnmrklroot', 'bad-txnmrklroot') self.log.info("getblocktemplate: Test bad timestamps") bad_block = copy.deepcopy(block) bad_block.nTime = 2 ** 31 - 1 assert_template(node, bad_block, 'time-too-new') + assert_submitblock(bad_block, 'time-too-new', 'time-too-new') bad_block.nTime = 0 assert_template(node, bad_block, 'time-too-old') + assert_submitblock(bad_block, 'time-too-old', 'time-too-old') self.log.info("getblocktemplate: Test not best block") bad_block = copy.deepcopy(block) bad_block.hashPrevBlock = 123 assert_template(node, bad_block, 'inconclusive-not-best-prevblk') + assert_submitblock(bad_block, 'prev-blk-not-found', 'prev-blk-not-found') self.log.info('submitheader tests') assert_raises_rpc_error(-22, 'Block header decode failed', lambda: node.submitheader(hexdata='xx' * 80)) assert_raises_rpc_error(-22, 'Block header decode failed', lambda: node.submitheader(hexdata='ff' * 78)) assert_raises_rpc_error(-25, 'Must submit previous header', lambda: node.submitheader(hexdata='ff' * 80)) + block.nTime += 1 block.solve() def chain_tip(b_hash, *, status='headers-only', branchlen=1): @@ -161,7 +178,8 @@ class MiningTest(BitcoinTestFramework): node.submitheader(hexdata=b2x(CBlockHeader(bad_block_root).serialize())) assert chain_tip(bad_block_root.hash) in node.getchaintips() # Should still reject invalid blocks, even if we have the header: - assert_equal(node.submitblock(hexdata=b2x(bad_block_root.serialize())), 'invalid') + assert_equal(node.submitblock(hexdata=b2x(bad_block_root.serialize())), 'bad-txnmrklroot') + assert_equal(node.submitblock(hexdata=b2x(bad_block_root.serialize())), 'bad-txnmrklroot') assert chain_tip(bad_block_root.hash) in node.getchaintips() # We know the header for this invalid block, so should just return early without error: node.submitheader(hexdata=b2x(CBlockHeader(bad_block_root).serialize())) @@ -172,7 +190,8 @@ class MiningTest(BitcoinTestFramework): bad_block_lock.vtx[0].rehash() bad_block_lock.hashMerkleRoot = bad_block_lock.calc_merkle_root() bad_block_lock.solve() - assert_equal(node.submitblock(hexdata=b2x(bad_block_lock.serialize())), 'invalid') + assert_equal(node.submitblock(hexdata=b2x(bad_block_lock.serialize())), 'bad-txns-nonfinal') + assert_equal(node.submitblock(hexdata=b2x(bad_block_lock.serialize())), 'duplicate-invalid') # Build a "good" block on top of the submitted bad block bad_block2 = copy.deepcopy(block) bad_block2.hashPrevBlock = bad_block_lock.sha256 @@ -198,6 +217,7 @@ class MiningTest(BitcoinTestFramework): assert_raises_rpc_error(-25, 'bad-prevblk', lambda: node.submitheader(hexdata=b2x(CBlockHeader(bad_block2).serialize()))) node.submitheader(hexdata=b2x(CBlockHeader(block).serialize())) node.submitheader(hexdata=b2x(CBlockHeader(bad_block_root).serialize())) + assert_equal(node.submitblock(hexdata=b2x(block.serialize())), 'duplicate') # valid if __name__ == '__main__': diff --git a/test/functional/mining_getblocktemplate_longpoll.py b/test/functional/mining_getblocktemplate_longpoll.py index 1259754c5a..9a3c15a4a7 100755 --- a/test/functional/mining_getblocktemplate_longpoll.py +++ b/test/functional/mining_getblocktemplate_longpoll.py @@ -28,6 +28,9 @@ class GetBlockTemplateLPTest(BitcoinTestFramework): def set_test_params(self): self.num_nodes = 2 + def skip_test_if_missing_module(self): + self.skip_if_no_wallet() + def run_test(self): self.log.info("Warning: this test will take about 70 seconds in the best case. Be patient.") self.nodes[0].generate(10) @@ -70,4 +73,3 @@ class GetBlockTemplateLPTest(BitcoinTestFramework): if __name__ == '__main__': GetBlockTemplateLPTest().main() - diff --git a/test/functional/mining_prioritisetransaction.py b/test/functional/mining_prioritisetransaction.py index bb0cc082ab..92590717f3 100755 --- a/test/functional/mining_prioritisetransaction.py +++ b/test/functional/mining_prioritisetransaction.py @@ -16,6 +16,9 @@ class PrioritiseTransactionTest(BitcoinTestFramework): self.num_nodes = 2 self.extra_args = [["-printpriority=1"], ["-printpriority=1"]] + def skip_test_if_missing_module(self): + self.skip_if_no_wallet() + def run_test(self): # Test `prioritisetransaction` required parameters assert_raises_rpc_error(-1, "prioritisetransaction", self.nodes[0].prioritisetransaction) diff --git a/test/functional/p2p_compactblocks.py b/test/functional/p2p_compactblocks.py index 5cec5dc6f0..3a5bdf806b 100755 --- a/test/functional/p2p_compactblocks.py +++ b/test/functional/p2p_compactblocks.py @@ -102,6 +102,9 @@ class CompactBlocksTest(BitcoinTestFramework): self.extra_args = [["-vbparams=segwit:0:0"], ["-vbparams=segwit:0:999999999999", "-txindex", "-deprecatedrpc=addwitnessaddress"]] self.utxos = [] + def skip_test_if_missing_module(self): + self.skip_if_no_wallet() + def build_block_on_tip(self, node, segwit=False): height = node.getblockcount() tip = node.getbestblockhash() diff --git a/test/functional/p2p_feefilter.py b/test/functional/p2p_feefilter.py index 3bc7734e75..d589519e45 100755 --- a/test/functional/p2p_feefilter.py +++ b/test/functional/p2p_feefilter.py @@ -42,6 +42,9 @@ class FeeFilterTest(BitcoinTestFramework): def set_test_params(self): self.num_nodes = 2 + def skip_test_if_missing_module(self): + self.skip_if_no_wallet() + def run_test(self): node1 = self.nodes[1] node0 = self.nodes[0] diff --git a/test/functional/p2p_fingerprint.py b/test/functional/p2p_fingerprint.py index 4a6ffced93..884fb4b063 100755 --- a/test/functional/p2p_fingerprint.py +++ b/test/functional/p2p_fingerprint.py @@ -30,6 +30,9 @@ class P2PFingerprintTest(BitcoinTestFramework): self.setup_clean_chain = True self.num_nodes = 1 + def skip_test_if_missing_module(self): + self.skip_if_no_wallet() + # Build a chain of blocks on top of given one def build_chain(self, nblocks, prev_hash, prev_height, prev_median_time): blocks = [] diff --git a/test/functional/p2p_invalid_block.py b/test/functional/p2p_invalid_block.py index b3f4d721f9..fd6b84f8b2 100755 --- a/test/functional/p2p_invalid_block.py +++ b/test/functional/p2p_invalid_block.py @@ -24,6 +24,9 @@ class InvalidBlockRequestTest(BitcoinTestFramework): self.setup_clean_chain = True self.extra_args = [["-whitelist=127.0.0.1"]] + def skip_test_if_missing_module(self): + self.skip_if_no_wallet() + def run_test(self): # Add p2p connection to node0 node = self.nodes[0] # convenience reference to the node diff --git a/test/functional/p2p_invalid_locator.py b/test/functional/p2p_invalid_locator.py index 3b1654f920..4cc43a4fa4 100755 --- a/test/functional/p2p_invalid_locator.py +++ b/test/functional/p2p_invalid_locator.py @@ -15,6 +15,9 @@ class InvalidLocatorTest(BitcoinTestFramework): self.num_nodes = 1 self.setup_clean_chain = False + def skip_test_if_missing_module(self): + self.skip_if_no_wallet() + def run_test(self): node = self.nodes[0] # convenience reference to the node node.generate(1) # Get node out of IBD diff --git a/test/functional/p2p_invalid_tx.py b/test/functional/p2p_invalid_tx.py index 69d5dd9f9a..2f19b4d933 100755 --- a/test/functional/p2p_invalid_tx.py +++ b/test/functional/p2p_invalid_tx.py @@ -26,6 +26,9 @@ class InvalidTxRequestTest(BitcoinTestFramework): self.num_nodes = 1 self.setup_clean_chain = True + def skip_test_if_missing_module(self): + self.skip_if_no_wallet() + def bootstrap_p2p(self, *, num_connections=1): """Add a P2P connection to the node. diff --git a/test/functional/p2p_leak.py b/test/functional/p2p_leak.py index dcbf833e7c..05354d17e1 100755 --- a/test/functional/p2p_leak.py +++ b/test/functional/p2p_leak.py @@ -93,6 +93,9 @@ class P2PLeakTest(BitcoinTestFramework): self.num_nodes = 1 self.extra_args = [['-banscore=' + str(banscore)]] + def skip_test_if_missing_module(self): + self.skip_if_no_wallet() + def run_test(self): no_version_bannode = self.nodes[0].add_p2p_connection(CNodeNoVersionBan(), send_version=False, wait_for_verack=False) no_version_idlenode = self.nodes[0].add_p2p_connection(CNodeNoVersionIdle(), send_version=False, wait_for_verack=False) diff --git a/test/functional/p2p_node_network_limited.py b/test/functional/p2p_node_network_limited.py index 4740740d42..a16c6a1d47 100755 --- a/test/functional/p2p_node_network_limited.py +++ b/test/functional/p2p_node_network_limited.py @@ -34,6 +34,9 @@ class NodeNetworkLimitedTest(BitcoinTestFramework): self.num_nodes = 3 self.extra_args = [['-prune=550', '-addrmantest'], [], []] + def skip_test_if_missing_module(self): + self.skip_if_no_wallet() + def disconnect_all(self): disconnect_nodes(self.nodes[0], 1) disconnect_nodes(self.nodes[1], 0) diff --git a/test/functional/p2p_segwit.py b/test/functional/p2p_segwit.py index 043fa67f77..de12ab1ed6 100755 --- a/test/functional/p2p_segwit.py +++ b/test/functional/p2p_segwit.py @@ -188,6 +188,9 @@ class SegWitTest(BitcoinTestFramework): # This test tests SegWit both pre and post-activation, so use the normal BIP9 activation. self.extra_args = [["-whitelist=127.0.0.1", "-vbparams=segwit:0:999999999999"], ["-whitelist=127.0.0.1", "-acceptnonstdtxn=0", "-vbparams=segwit:0:999999999999"], ["-whitelist=127.0.0.1", "-vbparams=segwit:0:0"]] + def skip_test_if_missing_module(self): + self.skip_if_no_wallet() + def setup_network(self): self.setup_nodes() connect_nodes(self.nodes[0], 1) diff --git a/test/functional/p2p_sendheaders.py b/test/functional/p2p_sendheaders.py index 9cc496d510..9a782c0bb9 100755 --- a/test/functional/p2p_sendheaders.py +++ b/test/functional/p2p_sendheaders.py @@ -208,6 +208,9 @@ class SendHeadersTest(BitcoinTestFramework): self.setup_clean_chain = True self.num_nodes = 2 + def skip_test_if_missing_module(self): + self.skip_if_no_wallet() + def mine_blocks(self, count): """Mine count blocks and return the new tip.""" diff --git a/test/functional/p2p_unrequested_blocks.py b/test/functional/p2p_unrequested_blocks.py index 2e86954aba..232274f59e 100755 --- a/test/functional/p2p_unrequested_blocks.py +++ b/test/functional/p2p_unrequested_blocks.py @@ -66,6 +66,9 @@ class AcceptBlockTest(BitcoinTestFramework): self.num_nodes = 2 self.extra_args = [[], ["-minimumchainwork=0x10"]] + def skip_test_if_missing_module(self): + self.skip_if_no_wallet() + def setup_network(self): # Node0 will be used to test behavior of processing unrequested blocks # from peers which are not whitelisted, while Node1 will be used for diff --git a/test/functional/rpc_blockchain.py b/test/functional/rpc_blockchain.py index d681cdc8ab..00317a2c08 100755 --- a/test/functional/rpc_blockchain.py +++ b/test/functional/rpc_blockchain.py @@ -47,9 +47,13 @@ from test_framework.mininode import ( class BlockchainTest(BitcoinTestFramework): def set_test_params(self): self.num_nodes = 1 - self.extra_args = [['-stopatheight=207', '-prune=1']] + + def skip_test_if_missing_module(self): + self.skip_if_no_wallet() def run_test(self): + self.restart_node(0, extra_args=['-stopatheight=207', '-prune=1']) # Set extra args with pruning after rescan is complete + self._test_getblockchaininfo() self._test_getchaintxstats() self._test_gettxoutsetinfo() @@ -169,7 +173,7 @@ class BlockchainTest(BitcoinTestFramework): assert_equal(res['transactions'], 200) assert_equal(res['height'], 200) assert_equal(res['txouts'], 200) - assert_equal(res['bogosize'], 17000), + assert_equal(res['bogosize'], 15000), assert_equal(res['bestblock'], node.getblockhash(200)) size = res['disk_size'] assert size > 6400 diff --git a/test/functional/rpc_createmultisig.py b/test/functional/rpc_createmultisig.py index f346e1ebfc..3cc35a7b9a 100755 --- a/test/functional/rpc_createmultisig.py +++ b/test/functional/rpc_createmultisig.py @@ -12,8 +12,11 @@ class RpcCreateMultiSigTest(BitcoinTestFramework): self.setup_clean_chain = True self.num_nodes = 3 + def skip_test_if_missing_module(self): + self.skip_if_no_wallet() + def get_keys(self): - node0,node1,node2 = self.nodes + node0, node1, node2 = self.nodes self.add = [node1.getnewaddress() for _ in range(self.nkeys)] self.pub = [node1.getaddressinfo(a)["pubkey"] for a in self.add] self.priv = [node1.dumpprivkey(a) for a in self.add] diff --git a/test/functional/rpc_fundrawtransaction.py b/test/functional/rpc_fundrawtransaction.py index a806de43b4..daa890ab15 100755 --- a/test/functional/rpc_fundrawtransaction.py +++ b/test/functional/rpc_fundrawtransaction.py @@ -29,6 +29,9 @@ class RawTransactionsTest(BitcoinTestFramework): self.num_nodes = 4 self.setup_clean_chain = True + def skip_test_if_missing_module(self): + self.skip_if_no_wallet() + def setup_network(self, split=False): self.setup_nodes() diff --git a/test/functional/rpc_getchaintips.py b/test/functional/rpc_getchaintips.py index 07929ca0a1..bc19c60dde 100755 --- a/test/functional/rpc_getchaintips.py +++ b/test/functional/rpc_getchaintips.py @@ -17,15 +17,18 @@ class GetChainTipsTest (BitcoinTestFramework): def set_test_params(self): self.num_nodes = 4 - def run_test (self): - tips = self.nodes[0].getchaintips () - assert_equal (len (tips), 1) - assert_equal (tips[0]['branchlen'], 0) - assert_equal (tips[0]['height'], 200) - assert_equal (tips[0]['status'], 'active') + def skip_test_if_missing_module(self): + self.skip_if_no_wallet() + + def run_test(self): + tips = self.nodes[0].getchaintips() + assert_equal(len(tips), 1) + assert_equal(tips[0]['branchlen'], 0) + assert_equal(tips[0]['height'], 200) + assert_equal(tips[0]['status'], 'active') # Split the network and build two chains of different lengths. - self.split_network () + self.split_network() self.nodes[0].generate(10) self.nodes[2].generate(20) self.sync_all([self.nodes[:2], self.nodes[2:]]) diff --git a/test/functional/rpc_help.py b/test/functional/rpc_help.py index ceca40527f..be096af892 100755 --- a/test/functional/rpc_help.py +++ b/test/functional/rpc_help.py @@ -4,9 +4,10 @@ # file COPYING or http://www.opensource.org/licenses/mit-license.php. """Test RPC help output.""" -from test_framework.test_framework import BitcoinTestFramework, is_zmq_enabled +from test_framework.test_framework import BitcoinTestFramework from test_framework.util import assert_equal, assert_raises_rpc_error + class HelpRpcTest(BitcoinTestFramework): def set_test_params(self): self.num_nodes = 1 @@ -26,12 +27,16 @@ class HelpRpcTest(BitcoinTestFramework): # command titles titles = [line[3:-3] for line in node.help().splitlines() if line.startswith('==')] - components = ['Blockchain', 'Control', 'Generating', 'Mining', 'Network', 'Rawtransactions', 'Util', 'Wallet'] + components = ['Blockchain', 'Control', 'Generating', 'Mining', 'Network', 'Rawtransactions', 'Util'] + + if self.is_wallet_compiled(): + components.append('Wallet') - if is_zmq_enabled(self): + if self.is_zmq_compiled(): components.append('Zmq') assert_equal(titles, components) + if __name__ == '__main__': HelpRpcTest().main() diff --git a/test/functional/rpc_invalidateblock.py b/test/functional/rpc_invalidateblock.py index f40710ef74..84f7cd05fb 100755 --- a/test/functional/rpc_invalidateblock.py +++ b/test/functional/rpc_invalidateblock.py @@ -14,6 +14,9 @@ class InvalidateTest(BitcoinTestFramework): self.setup_clean_chain = True self.num_nodes = 3 + def skip_test_if_missing_module(self): + self.skip_if_no_wallet() + def setup_network(self): self.setup_nodes() diff --git a/test/functional/rpc_preciousblock.py b/test/functional/rpc_preciousblock.py index 1e20d1a046..f383b82bb5 100755 --- a/test/functional/rpc_preciousblock.py +++ b/test/functional/rpc_preciousblock.py @@ -38,6 +38,9 @@ class PreciousTest(BitcoinTestFramework): self.setup_clean_chain = True self.num_nodes = 3 + def skip_test_if_missing_module(self): + self.skip_if_no_wallet() + def setup_network(self): self.setup_nodes() diff --git a/test/functional/rpc_psbt.py b/test/functional/rpc_psbt.py index a693b7e4bb..54dc871448 100755 --- a/test/functional/rpc_psbt.py +++ b/test/functional/rpc_psbt.py @@ -20,6 +20,9 @@ class PSBTTest(BitcoinTestFramework): self.setup_clean_chain = False self.num_nodes = 3 + def skip_test_if_missing_module(self): + self.skip_if_no_wallet() + def run_test(self): # Create and fund a raw tx for sending 10 BTC psbtx1 = self.nodes[0].walletcreatefundedpsbt([], {self.nodes[2].getnewaddress():10})['psbt'] diff --git a/test/functional/rpc_rawtransaction.py b/test/functional/rpc_rawtransaction.py index 8169f2b981..d86b546c7d 100755 --- a/test/functional/rpc_rawtransaction.py +++ b/test/functional/rpc_rawtransaction.py @@ -44,6 +44,9 @@ class RawTransactionsTest(BitcoinTestFramework): self.num_nodes = 3 self.extra_args = [["-addresstype=legacy"], ["-addresstype=legacy"], ["-addresstype=legacy"]] + def skip_test_if_missing_module(self): + self.skip_if_no_wallet() + def setup_network(self, split=False): super().setup_network() connect_nodes_bi(self.nodes, 0, 2) diff --git a/test/functional/rpc_scantxoutset.py b/test/functional/rpc_scantxoutset.py index ceb38e969a..96f9ccdbdb 100755 --- a/test/functional/rpc_scantxoutset.py +++ b/test/functional/rpc_scantxoutset.py @@ -14,6 +14,10 @@ class ScantxoutsetTest(BitcoinTestFramework): def set_test_params(self): self.num_nodes = 1 self.setup_clean_chain = True + + def skip_test_if_missing_module(self): + self.skip_if_no_wallet() + def run_test(self): self.log.info("Mining blocks...") self.nodes[0].generate(110) diff --git a/test/functional/rpc_signmessage.py b/test/functional/rpc_signmessage.py index 449c4075bd..ad0e29b451 100755 --- a/test/functional/rpc_signmessage.py +++ b/test/functional/rpc_signmessage.py @@ -13,6 +13,9 @@ class SignMessagesTest(BitcoinTestFramework): self.num_nodes = 1 self.extra_args = [["-addresstype=legacy"]] + def skip_test_if_missing_module(self): + self.skip_if_no_wallet() + def run_test(self): message = 'This is just a test message' diff --git a/test/functional/rpc_signrawtransaction.py b/test/functional/rpc_signrawtransaction.py index f6eea1a027..5c07f2ccae 100755 --- a/test/functional/rpc_signrawtransaction.py +++ b/test/functional/rpc_signrawtransaction.py @@ -14,6 +14,9 @@ class SignRawTransactionsTest(BitcoinTestFramework): self.num_nodes = 1 self.extra_args = [["-deprecatedrpc=signrawtransaction"]] + def skip_test_if_missing_module(self): + self.skip_if_no_wallet() + def successful_signing_test(self): """Create and sign a valid raw transaction with one input. diff --git a/test/functional/rpc_txoutproof.py b/test/functional/rpc_txoutproof.py index f9f8574646..867ba25022 100755 --- a/test/functional/rpc_txoutproof.py +++ b/test/functional/rpc_txoutproof.py @@ -15,6 +15,9 @@ class MerkleBlockTest(BitcoinTestFramework): # Nodes 0/1 are "wallet" nodes, Nodes 2/3 are used for testing self.extra_args = [[], [], [], ["-txindex"]] + def skip_test_if_missing_module(self): + self.skip_if_no_wallet() + def setup_network(self): self.setup_nodes() connect_nodes(self.nodes[0], 1) diff --git a/test/functional/rpc_zmq.py b/test/functional/rpc_zmq.py index 6dbc726d5e..bfa6b06f67 100755 --- a/test/functional/rpc_zmq.py +++ b/test/functional/rpc_zmq.py @@ -4,8 +4,7 @@ # file COPYING or http://www.opensource.org/licenses/mit-license.php. """Test for the ZMQ RPC methods.""" -from test_framework.test_framework import ( - BitcoinTestFramework, skip_if_no_py3_zmq, skip_if_no_bitcoind_zmq) +from test_framework.test_framework import BitcoinTestFramework from test_framework.util import assert_equal @@ -17,9 +16,11 @@ class RPCZMQTest(BitcoinTestFramework): self.num_nodes = 1 self.setup_clean_chain = True + def skip_test_if_missing_module(self): + self.skip_if_no_py3_zmq() + self.skip_if_no_bitcoind_zmq() + def run_test(self): - skip_if_no_py3_zmq() - skip_if_no_bitcoind_zmq(self) self._test_getzmqnotifications() def _test_getzmqnotifications(self): diff --git a/test/functional/test_framework/test_framework.py b/test/functional/test_framework/test_framework.py index 0e76b52570..57c985b2a2 100755 --- a/test/functional/test_framework/test_framework.py +++ b/test/functional/test_framework/test_framework.py @@ -44,6 +44,13 @@ TEST_EXIT_FAILED = 1 TEST_EXIT_SKIPPED = 77 +class SkipTest(Exception): + """This exception is raised to skip a test""" + + def __init__(self, message): + self.message = message + + class BitcoinTestMetaClass(type): """Metaclass for BitcoinTestFramework. @@ -156,8 +163,10 @@ class BitcoinTestFramework(metaclass=BitcoinTestMetaClass): try: if self.options.usecli and not self.supports_cli: raise SkipTest("--usecli specified but test does not support using CLI") + self.skip_test_if_missing_module() self.setup_chain() self.setup_network() + self.import_deterministic_coinbase_privkeys() self.run_test() success = TestStatus.PASSED except JSONRPCException as e: @@ -220,6 +229,10 @@ class BitcoinTestFramework(metaclass=BitcoinTestMetaClass): """Override this method to add command-line options to the test""" pass + def skip_test_if_missing_module(self): + """Override this method to skip a test if a module is not compiled""" + pass + def setup_chain(self): """Override this method to customize blockchain setup""" self.log.info("Initializing test directory " + self.options.tmpdir) @@ -247,6 +260,19 @@ class BitcoinTestFramework(metaclass=BitcoinTestMetaClass): self.add_nodes(self.num_nodes, extra_args) self.start_nodes() + def import_deterministic_coinbase_privkeys(self): + if self.setup_clean_chain: + return + + for n in self.nodes: + try: + n.getwalletinfo() + except JSONRPCException as e: + assert str(e).startswith('Method not found') + continue + + n.importprivkey(n.get_deterministic_priv_key()[1]) + def run_test(self): """Tests must override this method to define test logic""" raise NotImplementedError @@ -415,7 +441,7 @@ class BitcoinTestFramework(metaclass=BitcoinTestMetaClass): # Create cache directories, run bitcoinds: for i in range(MAX_NODES): datadir = initialize_datadir(self.options.cachedir, i) - args = [self.options.bitcoind, "-datadir=" + datadir] + args = [self.options.bitcoind, "-datadir=" + datadir, '-disablewallet'] if i > 0: args.append("-connect=127.0.0.1:" + str(p2p_port(0))) self.nodes.append(TestNode(i, get_datadir_path(self.options.cachedir, i), extra_conf=["bind=127.0.0.1"], extra_args=[], rpchost=None, timewait=self.rpc_timewait, bitcoind=self.options.bitcoind, bitcoin_cli=self.options.bitcoincli, mocktime=self.mocktime, coverage_dir=None)) @@ -439,7 +465,7 @@ class BitcoinTestFramework(metaclass=BitcoinTestMetaClass): for peer in range(4): for j in range(25): set_node_times(self.nodes, block_time) - self.nodes[peer].generate(1) + self.nodes[peer].generatetoaddress(1, self.nodes[peer].get_deterministic_priv_key()[0]) block_time += 10 * 60 # Must sync before next peer starts generating blocks sync_blocks(self.nodes) @@ -453,8 +479,9 @@ class BitcoinTestFramework(metaclass=BitcoinTestMetaClass): return os.path.join(get_datadir_path(self.options.cachedir, n), "regtest", *paths) for i in range(MAX_NODES): + os.rmdir(cache_path(i, 'wallets')) # Remove empty wallets dir for entry in os.listdir(cache_path(i)): - if entry not in ['wallets', 'chainstate', 'blocks']: + if entry not in ['chainstate', 'blocks']: os.remove(cache_path(i, entry)) for i in range(self.num_nodes): @@ -471,30 +498,45 @@ class BitcoinTestFramework(metaclass=BitcoinTestMetaClass): for i in range(self.num_nodes): initialize_datadir(self.options.tmpdir, i) + def skip_if_no_py3_zmq(self): + """Attempt to import the zmq package and skip the test if the import fails.""" + try: + import zmq # noqa + except ImportError: + raise SkipTest("python3-zmq module not available.") + + def skip_if_no_bitcoind_zmq(self): + """Skip the running test if bitcoind has not been compiled with zmq support.""" + if not self.is_zmq_compiled(): + raise SkipTest("bitcoind has not been built with zmq enabled.") + + def skip_if_no_wallet(self): + """Skip the running test if wallet has not been compiled.""" + if not self.is_wallet_compiled(): + raise SkipTest("wallet has not been compiled.") + + def skip_if_no_cli(self): + """Skip the running test if bitcoin-cli has not been compiled.""" + if not self.is_cli_compiled(): + raise SkipTest("bitcoin-cli has not been compiled.") + + def is_cli_compiled(self): + """Checks whether bitcoin-cli was compiled.""" + config = configparser.ConfigParser() + config.read_file(open(self.options.configfile)) -class SkipTest(Exception): - """This exception is raised to skip a test""" - def __init__(self, message): - self.message = message - - -def skip_if_no_py3_zmq(): - """Attempt to import the zmq package and skip the test if the import fails.""" - try: - import zmq # noqa - except ImportError: - raise SkipTest("python3-zmq module not available.") - + return config["components"].getboolean("ENABLE_UTILS") -def skip_if_no_bitcoind_zmq(test_instance): - """Skip the running test if bitcoind has not been compiled with zmq support.""" - if not is_zmq_enabled(test_instance): - raise SkipTest("bitcoind has not been built with zmq enabled.") + def is_wallet_compiled(self): + """Checks whether the wallet module was compiled.""" + config = configparser.ConfigParser() + config.read_file(open(self.options.configfile)) + return config["components"].getboolean("ENABLE_WALLET") -def is_zmq_enabled(test_instance): - """Checks whether zmq is enabled or not.""" - config = configparser.ConfigParser() - config.read_file(open(test_instance.options.configfile)) + def is_zmq_compiled(self): + """Checks whether the zmq module was compiled.""" + config = configparser.ConfigParser() + config.read_file(open(self.options.configfile)) - return config["components"].getboolean("ENABLE_ZMQ") + return config["components"].getboolean("ENABLE_ZMQ") diff --git a/test/functional/test_framework/test_node.py b/test/functional/test_framework/test_node.py index a831fdcd5d..908dda94c5 100755 --- a/test/functional/test_framework/test_node.py +++ b/test/functional/test_framework/test_node.py @@ -97,6 +97,22 @@ class TestNode(): self.p2ps = [] + def get_deterministic_priv_key(self): + """Return a deterministic priv key in base58, that only depends on the node's index""" + PRIV_KEYS = [ + # adress , privkey + ('mjTkW3DjgyZck4KbiRusZsqTgaYTxdSz6z', 'cVpF924EspNh8KjYsfhgY96mmxvT6DgdWiTYMtMjuM74hJaU5psW'), + ('msX6jQXvxiNhx3Q62PKeLPrhrqZQdSimTg', 'cUxsWyKyZ9MAQTaAhUQWJmBbSvHMwSmuv59KgxQV7oZQU3PXN3KE'), + ('mnonCMyH9TmAsSj3M59DsbH8H63U3RKoFP', 'cTrh7dkEAeJd6b3MRX9bZK8eRmNqVCMH3LSUkE3dSFDyzjU38QxK'), + ('mqJupas8Dt2uestQDvV2NH3RU8uZh2dqQR', 'cVuKKa7gbehEQvVq717hYcbE9Dqmq7KEBKqWgWrYBa2CKKrhtRim'), + ('msYac7Rvd5ywm6pEmkjyxhbCDKqWsVeYws', 'cQDCBuKcjanpXDpCqacNSjYfxeQj8G6CAtH1Dsk3cXyqLNC4RPuh'), + ('n2rnuUnwLgXqf9kk2kjvVm8R5BZK1yxQBi', 'cQakmfPSLSqKHyMFGwAqKHgWUiofJCagVGhiB4KCainaeCSxeyYq'), + ('myzuPxRwsf3vvGzEuzPfK9Nf2RfwauwYe6', 'cQMpDLJwA8DBe9NcQbdoSb1BhmFxVjWD5gRyrLZCtpuF9Zi3a9RK'), + ('mumwTaMtbxEPUswmLBBN3vM9oGRtGBrys8', 'cSXmRKXVcoouhNNVpcNKFfxsTsToY5pvB9DVsFksF1ENunTzRKsy'), + ('mpV7aGShMkJCZgbW7F6iZgrvuPHjZjH9qg', 'cSoXt6tm3pqy43UMabY6eUTmR3eSUYFtB2iNQDGgb3VUnRsQys2k'), + ] + return PRIV_KEYS[self.index] + def _node_msg(self, msg: str) -> str: """Return a modified msg that identifies this node by its index as a debugging aid.""" return "[node %d] %s" % (self.index, msg) diff --git a/test/functional/test_runner.py b/test/functional/test_runner.py index 13c687fd92..37b378e9ca 100755 --- a/test/functional/test_runner.py +++ b/test/functional/test_runner.py @@ -236,8 +236,6 @@ def main(): logging.debug("Temporary test directory at %s" % tmpdir) - enable_wallet = config["components"].getboolean("ENABLE_WALLET") - enable_utils = config["components"].getboolean("ENABLE_UTILS") enable_bitcoind = config["components"].getboolean("ENABLE_BITCOIND") if config["environment"]["EXEEXT"] == ".exe" and not args.force: @@ -246,9 +244,9 @@ def main(): print("Tests currently disabled on Windows by default. Use --force option to enable") sys.exit(0) - if not (enable_wallet and enable_utils and enable_bitcoind): - print("No functional tests to run. Wallet, utils, and bitcoind must all be enabled") - print("Rerun `configure` with -enable-wallet, -with-utils and -with-daemon and rerun make") + if not enable_bitcoind: + print("No functional tests to run.") + print("Rerun ./configure with --with-daemon and then make") sys.exit(0) # Build list of tests diff --git a/test/functional/wallet_abandonconflict.py b/test/functional/wallet_abandonconflict.py index 8a57b55ca9..e5ac2c8bd4 100755 --- a/test/functional/wallet_abandonconflict.py +++ b/test/functional/wallet_abandonconflict.py @@ -20,6 +20,9 @@ class AbandonConflictTest(BitcoinTestFramework): self.num_nodes = 2 self.extra_args = [["-minrelaytxfee=0.00001"], []] + def skip_test_if_missing_module(self): + self.skip_if_no_wallet() + def run_test(self): self.nodes[1].generate(100) sync_blocks(self.nodes) diff --git a/test/functional/wallet_address_types.py b/test/functional/wallet_address_types.py index 30851893b8..0f75045c9d 100755 --- a/test/functional/wallet_address_types.py +++ b/test/functional/wallet_address_types.py @@ -63,6 +63,7 @@ from test_framework.util import ( sync_mempools, ) + class AddressTypeTest(BitcoinTestFramework): def set_test_params(self): self.num_nodes = 6 @@ -72,9 +73,12 @@ class AddressTypeTest(BitcoinTestFramework): ["-addresstype=p2sh-segwit", "-changetype=bech32"], ["-addresstype=bech32"], ["-changetype=p2sh-segwit"], - [] + [], ] + def skip_test_if_missing_module(self): + self.skip_if_no_wallet() + def setup_network(self): self.setup_nodes() diff --git a/test/functional/wallet_backup.py b/test/functional/wallet_backup.py index 4ef8f4776b..32ec385fa1 100755 --- a/test/functional/wallet_backup.py +++ b/test/functional/wallet_backup.py @@ -45,6 +45,9 @@ class WalletBackupTest(BitcoinTestFramework): # nodes 1, 2,3 are spenders, let's give them a keypool=100 self.extra_args = [["-keypool=100"], ["-keypool=100"], ["-keypool=100"], []] + def skip_test_if_missing_module(self): + self.skip_if_no_wallet() + def setup_network(self, split=False): self.setup_nodes() connect_nodes(self.nodes[0], 3) diff --git a/test/functional/wallet_basic.py b/test/functional/wallet_basic.py index ea0346543a..4079d05491 100755 --- a/test/functional/wallet_basic.py +++ b/test/functional/wallet_basic.py @@ -23,6 +23,9 @@ class WalletTest(BitcoinTestFramework): self.num_nodes = 4 self.setup_clean_chain = True + def skip_test_if_missing_module(self): + self.skip_if_no_wallet() + def setup_network(self): self.add_nodes(4) self.start_node(0) diff --git a/test/functional/wallet_bumpfee.py b/test/functional/wallet_bumpfee.py index a49590df19..2ea72896bb 100755 --- a/test/functional/wallet_bumpfee.py +++ b/test/functional/wallet_bumpfee.py @@ -31,8 +31,14 @@ class BumpFeeTest(BitcoinTestFramework): def set_test_params(self): self.num_nodes = 2 self.setup_clean_chain = True - self.extra_args = [["-deprecatedrpc=addwitnessaddress", "-walletrbf={}".format(i), "-mintxfee=0.00002"] - for i in range(self.num_nodes)] + self.extra_args = [[ + "-deprecatedrpc=addwitnessaddress", + "-walletrbf={}".format(i), + "-mintxfee=0.00002", + ] for i in range(self.num_nodes)] + + def skip_test_if_missing_module(self): + self.skip_if_no_wallet() def run_test(self): # Encrypt wallet for test_locked_wallet_fails test diff --git a/test/functional/wallet_disableprivatekeys.py b/test/functional/wallet_disableprivatekeys.py index 0ba2cfe9be..34ff525255 100755 --- a/test/functional/wallet_disableprivatekeys.py +++ b/test/functional/wallet_disableprivatekeys.py @@ -17,6 +17,9 @@ class DisablePrivateKeysTest(BitcoinTestFramework): self.num_nodes = 1 self.supports_cli = True + def skip_test_if_missing_module(self): + self.skip_if_no_wallet() + def run_test(self): node = self.nodes[0] self.log.info("Test disableprivatekeys creation.") diff --git a/test/functional/wallet_dump.py b/test/functional/wallet_dump.py index 63316d9644..db731b2a34 100755 --- a/test/functional/wallet_dump.py +++ b/test/functional/wallet_dump.py @@ -29,50 +29,54 @@ def read_dump(file_name, addrs, script_addrs, hd_master_addr_old): # only read non comment lines if line[0] != "#" and len(line) > 10: # split out some data - key_label, comment = line.split("#") - # key = key_label.split(" ")[0] - keytype = key_label.split(" ")[2] - if len(comment) > 1: - addr_keypath = comment.split(" addr=")[1] - addr = addr_keypath.split(" ")[0] + key_date_label, comment = line.split("#") + key_date_label = key_date_label.split(" ") + # key = key_date_label[0] + date = key_date_label[1] + keytype = key_date_label[2] + if not len(comment) or date.startswith('1970'): + continue + + addr_keypath = comment.split(" addr=")[1] + addr = addr_keypath.split(" ")[0] + keypath = None + if keytype == "inactivehdseed=1": + # ensure the old master is still available + assert (hd_master_addr_old == addr) + elif keytype == "hdseed=1": + # ensure we have generated a new hd master key + assert (hd_master_addr_old != addr) + hd_master_addr_ret = addr + elif keytype == "script=1": + # scripts don't have keypaths keypath = None - if keytype == "inactivehdseed=1": - # ensure the old master is still available - assert(hd_master_addr_old == addr) - elif keytype == "hdseed=1": - # ensure we have generated a new hd master key - assert(hd_master_addr_old != addr) - hd_master_addr_ret = addr - elif keytype == "script=1": - # scripts don't have keypaths - keypath = None - else: - keypath = addr_keypath.rstrip().split("hdkeypath=")[1] - - # count key types - for addrObj in addrs: - if addrObj['address'] == addr.split(",")[0] and addrObj['hdkeypath'] == keypath and keytype == "label=": - # a labeled entry in the wallet should contain both a native address - # and the p2sh-p2wpkh address that was added at wallet setup - if len(addr.split(",")) == 2: - addr_list = addr.split(",") - # the entry should be of the first key in the wallet - assert_equal(addrs[0]['address'], addr_list[0]) - witness_addr_ret = addr_list[1] - found_addr += 1 - break - elif keytype == "change=1": - found_addr_chg += 1 - break - elif keytype == "reserve=1": - found_addr_rsv += 1 - break - - # count scripts - for script_addr in script_addrs: - if script_addr == addr.rstrip() and keytype == "script=1": - found_script_addr += 1 - break + else: + keypath = addr_keypath.rstrip().split("hdkeypath=")[1] + + # count key types + for addrObj in addrs: + if addrObj['address'] == addr.split(",")[0] and addrObj['hdkeypath'] == keypath and keytype == "label=": + # a labeled entry in the wallet should contain both a native address + # and the p2sh-p2wpkh address that was added at wallet setup + if len(addr.split(",")) == 2: + addr_list = addr.split(",") + # the entry should be of the first key in the wallet + assert_equal(addrs[0]['address'], addr_list[0]) + witness_addr_ret = addr_list[1] + found_addr += 1 + break + elif keytype == "change=1": + found_addr_chg += 1 + break + elif keytype == "reserve=1": + found_addr_rsv += 1 + break + + # count scripts + for script_addr in script_addrs: + if script_addr == addr.rstrip() and keytype == "script=1": + found_script_addr += 1 + break return found_addr, found_script_addr, found_addr_chg, found_addr_rsv, hd_master_addr_ret, witness_addr_ret @@ -83,6 +87,9 @@ class WalletDumpTest(BitcoinTestFramework): self.extra_args = [["-keypool=90", "-addresstype=legacy", "-deprecatedrpc=addwitnessaddress"]] self.rpc_timeout = 120 + def skip_test_if_missing_module(self): + self.skip_if_no_wallet() + def setup_network(self, split=False): self.add_nodes(self.num_nodes, extra_args=self.extra_args) self.start_nodes() @@ -116,9 +123,9 @@ class WalletDumpTest(BitcoinTestFramework): read_dump(wallet_unenc_dump, addrs, script_addrs, None) assert_equal(found_addr, test_addr_count) # all keys must be in the dump assert_equal(found_script_addr, 2) # all scripts must be in the dump - assert_equal(found_addr_chg, 50) # 50 blocks where mined - assert_equal(found_addr_rsv, 90*2) # 90 keys plus 100% internal keys - assert_equal(witness_addr_ret, witness_addr) # p2sh-p2wsh address added to the first key + assert_equal(found_addr_chg, 0) # 0 blocks where mined + assert_equal(found_addr_rsv, 90 * 2) # 90 keys plus 100% internal keys + assert_equal(witness_addr_ret, witness_addr) # p2sh-p2wsh address added to the first key #encrypt wallet, restart, unlock and dump self.nodes[0].node_encrypt_wallet('test') @@ -132,8 +139,8 @@ class WalletDumpTest(BitcoinTestFramework): read_dump(wallet_enc_dump, addrs, script_addrs, hd_master_addr_unenc) assert_equal(found_addr, test_addr_count) assert_equal(found_script_addr, 2) - assert_equal(found_addr_chg, 90*2 + 50) # old reserve keys are marked as change now - assert_equal(found_addr_rsv, 90*2) + assert_equal(found_addr_chg, 90 * 2) # old reserve keys are marked as change now + assert_equal(found_addr_rsv, 90 * 2) assert_equal(witness_addr_ret, witness_addr) # Overwriting should fail diff --git a/test/functional/wallet_encryption.py b/test/functional/wallet_encryption.py index cec9660259..d8c27b09d9 100755 --- a/test/functional/wallet_encryption.py +++ b/test/functional/wallet_encryption.py @@ -19,6 +19,9 @@ class WalletEncryptionTest(BitcoinTestFramework): self.setup_clean_chain = True self.num_nodes = 1 + def skip_test_if_missing_module(self): + self.skip_if_no_wallet() + def run_test(self): passphrase = "WalletPassphrase" passphrase2 = "SecondWalletPassphrase" diff --git a/test/functional/wallet_fallbackfee.py b/test/functional/wallet_fallbackfee.py index 91dbae8939..0c67982bbe 100755 --- a/test/functional/wallet_fallbackfee.py +++ b/test/functional/wallet_fallbackfee.py @@ -11,6 +11,9 @@ class WalletRBFTest(BitcoinTestFramework): self.num_nodes = 1 self.setup_clean_chain = True + def skip_test_if_missing_module(self): + self.skip_if_no_wallet() + def run_test(self): self.nodes[0].generate(101) diff --git a/test/functional/wallet_groups.py b/test/functional/wallet_groups.py index 12dac145bd..9d61483868 100755 --- a/test/functional/wallet_groups.py +++ b/test/functional/wallet_groups.py @@ -23,7 +23,10 @@ class WalletGroupTest(BitcoinTestFramework): self.extra_args = [[], [], ['-avoidpartialspends']] self.rpc_timewait = 120 - def run_test (self): + def skip_test_if_missing_module(self): + self.skip_if_no_wallet() + + def run_test(self): # Mine some coins self.nodes[0].generate(110) diff --git a/test/functional/wallet_hd.py b/test/functional/wallet_hd.py index 2a5f1934b7..48e71f6c40 100755 --- a/test/functional/wallet_hd.py +++ b/test/functional/wallet_hd.py @@ -21,6 +21,9 @@ class WalletHDTest(BitcoinTestFramework): self.num_nodes = 2 self.extra_args = [[], ['-keypool=0']] + def skip_test_if_missing_module(self): + self.skip_if_no_wallet() + def run_test(self): # Make sure can't switch off usehd after wallet creation self.stop_node(1) diff --git a/test/functional/wallet_import_rescan.py b/test/functional/wallet_import_rescan.py index aec9e870f8..fab415987e 100755 --- a/test/functional/wallet_import_rescan.py +++ b/test/functional/wallet_import_rescan.py @@ -109,6 +109,9 @@ class ImportRescanTest(BitcoinTestFramework): def set_test_params(self): self.num_nodes = 2 + len(IMPORT_NODES) + def skip_test_if_missing_module(self): + self.skip_if_no_wallet() + def setup_network(self): extra_args = [["-addresstype=legacy"] for _ in range(self.num_nodes)] for i, import_node in enumerate(IMPORT_NODES, 2): @@ -116,10 +119,19 @@ class ImportRescanTest(BitcoinTestFramework): extra_args[i] += ["-prune=1"] self.add_nodes(self.num_nodes, extra_args=extra_args) + + # Import keys + self.start_nodes(extra_args=[[]] * self.num_nodes) + super().import_deterministic_coinbase_privkeys() + self.stop_nodes() + self.start_nodes() for i in range(1, self.num_nodes): connect_nodes(self.nodes[i], 0) + def import_deterministic_coinbase_privkeys(self): + pass + def run_test(self): # Create one transaction on node 0 with a unique amount for # each possible type of wallet import RPC. diff --git a/test/functional/wallet_importmulti.py b/test/functional/wallet_importmulti.py index 50c48ab5e0..f78ff19791 100755 --- a/test/functional/wallet_importmulti.py +++ b/test/functional/wallet_importmulti.py @@ -20,6 +20,9 @@ class ImportMultiTest(BitcoinTestFramework): self.extra_args = [["-addresstype=legacy"], ["-addresstype=legacy"]] self.setup_clean_chain = True + def skip_test_if_missing_module(self): + self.skip_if_no_wallet() + def setup_network(self): self.setup_nodes() diff --git a/test/functional/wallet_importprunedfunds.py b/test/functional/wallet_importprunedfunds.py index 57fc754d35..26b181db33 100755 --- a/test/functional/wallet_importprunedfunds.py +++ b/test/functional/wallet_importprunedfunds.py @@ -16,6 +16,9 @@ class ImportPrunedFundsTest(BitcoinTestFramework): self.setup_clean_chain = True self.num_nodes = 2 + def skip_test_if_missing_module(self): + self.skip_if_no_wallet() + def run_test(self): self.log.info("Mining blocks...") self.nodes[0].generate(101) diff --git a/test/functional/wallet_keypool.py b/test/functional/wallet_keypool.py index f52dce04dd..acc336e4d5 100755 --- a/test/functional/wallet_keypool.py +++ b/test/functional/wallet_keypool.py @@ -13,6 +13,9 @@ class KeyPoolTest(BitcoinTestFramework): def set_test_params(self): self.num_nodes = 1 + def skip_test_if_missing_module(self): + self.skip_if_no_wallet() + def run_test(self): nodes = self.nodes addr_before_encrypting = nodes[0].getnewaddress() diff --git a/test/functional/wallet_keypool_topup.py b/test/functional/wallet_keypool_topup.py index f6b88e6225..f1a441c399 100755 --- a/test/functional/wallet_keypool_topup.py +++ b/test/functional/wallet_keypool_topup.py @@ -27,6 +27,9 @@ class KeypoolRestoreTest(BitcoinTestFramework): self.num_nodes = 2 self.extra_args = [[], ['-keypool=100']] + def skip_test_if_missing_module(self): + self.skip_if_no_wallet() + def run_test(self): wallet_path = os.path.join(self.nodes[1].datadir, "regtest", "wallets", "wallet.dat") wallet_backup_path = os.path.join(self.nodes[1].datadir, "wallet.bak") diff --git a/test/functional/wallet_labels.py b/test/functional/wallet_labels.py index 01a73d9cef..8d7c77bb96 100755 --- a/test/functional/wallet_labels.py +++ b/test/functional/wallet_labels.py @@ -19,6 +19,9 @@ class WalletLabelsTest(BitcoinTestFramework): self.setup_clean_chain = True self.num_nodes = 1 + def skip_test_if_missing_module(self): + self.skip_if_no_wallet() + def run_test(self): # Check that there's no UTXO on the node node = self.nodes[0] diff --git a/test/functional/wallet_listreceivedby.py b/test/functional/wallet_listreceivedby.py index 09a7c72347..3485c4470f 100755 --- a/test/functional/wallet_listreceivedby.py +++ b/test/functional/wallet_listreceivedby.py @@ -18,6 +18,14 @@ class ReceivedByTest(BitcoinTestFramework): def set_test_params(self): self.num_nodes = 2 + def import_deterministic_coinbase_privkeys(self): + assert_equal(0, len(self.nodes[1].listreceivedbyaddress(minconf=0, include_empty=True, include_watchonly=True))) + super().import_deterministic_coinbase_privkeys() + self.num_cb_reward_addresses = len(self.nodes[1].listreceivedbyaddress(minconf=0, include_empty=True, include_watchonly=True)) + + def skip_test_if_missing_module(self): + self.skip_if_no_wallet() + def run_test(self): # Generate block to get out of IBD self.nodes[0].generate(1) @@ -64,7 +72,7 @@ class ReceivedByTest(BitcoinTestFramework): assert_raises_rpc_error(-4, "address_filter parameter was invalid", self.nodes[1].listreceivedbyaddress, minconf=0, include_empty=True, include_watchonly=True, address_filter="bamboozling") # Another address receive money res = self.nodes[1].listreceivedbyaddress(0, True, True) - assert_equal(len(res), 2) # Right now 2 entries + assert_equal(len(res), 2 + self.num_cb_reward_addresses) # Right now 2 entries other_addr = self.nodes[1].getnewaddress() txid2 = self.nodes[0].sendtoaddress(other_addr, 0.1) self.nodes[0].generate(1) @@ -81,7 +89,7 @@ class ReceivedByTest(BitcoinTestFramework): assert_equal(len(res), 1) # Should be two entries though without filter res = self.nodes[1].listreceivedbyaddress(0, True, True) - assert_equal(len(res), 3) # Became 3 entries + assert_equal(len(res), 3 + self.num_cb_reward_addresses) # Became 3 entries # Not on random addr other_addr = self.nodes[0].getnewaddress() # note on node[0]! just a random addr diff --git a/test/functional/wallet_listsinceblock.py b/test/functional/wallet_listsinceblock.py index 847b48aa89..53e671cd3b 100755 --- a/test/functional/wallet_listsinceblock.py +++ b/test/functional/wallet_listsinceblock.py @@ -12,6 +12,9 @@ class ListSinceBlockTest (BitcoinTestFramework): self.num_nodes = 4 self.setup_clean_chain = True + def skip_test_if_missing_module(self): + self.skip_if_no_wallet() + def run_test(self): self.nodes[2].generate(101) self.sync_all() diff --git a/test/functional/wallet_listtransactions.py b/test/functional/wallet_listtransactions.py index 4dc3ff4b26..5a17395abd 100755 --- a/test/functional/wallet_listtransactions.py +++ b/test/functional/wallet_listtransactions.py @@ -27,6 +27,9 @@ class ListTransactionsTest(BitcoinTestFramework): self.num_nodes = 2 self.enable_mocktime() + def skip_test_if_missing_module(self): + self.skip_if_no_wallet() + def run_test(self): # Simple send, 0 to 1: txid = self.nodes[0].sendtoaddress(self.nodes[1].getnewaddress(), 0.1) diff --git a/test/functional/wallet_multiwallet.py b/test/functional/wallet_multiwallet.py index 0690dcf92d..435821ec48 100755 --- a/test/functional/wallet_multiwallet.py +++ b/test/functional/wallet_multiwallet.py @@ -23,6 +23,9 @@ class MultiWalletTest(BitcoinTestFramework): self.num_nodes = 2 self.supports_cli = True + def skip_test_if_missing_module(self): + self.skip_if_no_wallet() + def run_test(self): node = self.nodes[0] diff --git a/test/functional/wallet_resendwallettransactions.py b/test/functional/wallet_resendwallettransactions.py index 8995aa743f..00bf58d709 100755 --- a/test/functional/wallet_resendwallettransactions.py +++ b/test/functional/wallet_resendwallettransactions.py @@ -12,6 +12,9 @@ class ResendWalletTransactionsTest(BitcoinTestFramework): self.num_nodes = 1 self.extra_args = [['--walletbroadcast=false']] + def skip_test_if_missing_module(self): + self.skip_if_no_wallet() + def run_test(self): # Should raise RPC_WALLET_ERROR (-4) if walletbroadcast is disabled. assert_raises_rpc_error(-4, "Error: Wallet transaction broadcasting is disabled with -walletbroadcast", self.nodes[0].resendwallettransactions) diff --git a/test/functional/wallet_txn_clone.py b/test/functional/wallet_txn_clone.py index 4ca4ee14e9..d78c105c17 100755 --- a/test/functional/wallet_txn_clone.py +++ b/test/functional/wallet_txn_clone.py @@ -16,6 +16,9 @@ class TxnMallTest(BitcoinTestFramework): def set_test_params(self): self.num_nodes = 4 + def skip_test_if_missing_module(self): + self.skip_if_no_wallet() + def add_options(self, parser): parser.add_argument("--mineblock", dest="mine_block", default=False, action="store_true", help="Test double-spend of 1-confirmed transaction") diff --git a/test/functional/wallet_txn_doublespend.py b/test/functional/wallet_txn_doublespend.py index 6811f6ab73..f114d5ab68 100755 --- a/test/functional/wallet_txn_doublespend.py +++ b/test/functional/wallet_txn_doublespend.py @@ -18,6 +18,9 @@ class TxnMallTest(BitcoinTestFramework): def set_test_params(self): self.num_nodes = 4 + def skip_test_if_missing_module(self): + self.skip_if_no_wallet() + def add_options(self, parser): parser.add_argument("--mineblock", dest="mine_block", default=False, action="store_true", help="Test double-spend of 1-confirmed transaction") diff --git a/test/functional/wallet_zapwallettxes.py b/test/functional/wallet_zapwallettxes.py index cbd142d1ee..adebff360a 100755 --- a/test/functional/wallet_zapwallettxes.py +++ b/test/functional/wallet_zapwallettxes.py @@ -26,6 +26,9 @@ class ZapWalletTXesTest (BitcoinTestFramework): self.setup_clean_chain = True self.num_nodes = 2 + def skip_test_if_missing_module(self): + self.skip_if_no_wallet() + def run_test(self): self.log.info("Mining blocks...") self.nodes[0].generate(1) diff --git a/test/lint/lint-format-strings.py b/test/lint/lint-format-strings.py index 60389176c9..2fb35fd8ca 100755 --- a/test/lint/lint-format-strings.py +++ b/test/lint/lint-format-strings.py @@ -20,6 +20,7 @@ FALSE_POSITIVES = [ ("src/util.cpp", "strprintf(COPYRIGHT_HOLDERS, COPYRIGHT_HOLDERS_SUBSTITUTION)"), ("src/wallet/wallet.h", "WalletLogPrintf(std::string fmt, Params... parameters)"), ("src/wallet/wallet.h", "LogPrintf((\"%s \" + fmt).c_str(), GetDisplayName(), parameters...)"), + ("src/logging.h", "LogPrintf(const char* fmt, const Args&... args)"), ] |