From 3bf00e13609eefa6ddb11353519bb1aec2342513 Mon Sep 17 00:00:00 2001 From: Marnix <93143998+MarnixCroes@users.noreply.github.com> Date: Wed, 17 Jan 2024 08:48:03 +0100 Subject: [PATCH 01/46] gui: debugwindow: update session ID tooltip remove "if any" --- src/qt/forms/debugwindow.ui | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/qt/forms/debugwindow.ui b/src/qt/forms/debugwindow.ui index 60e9bcde33..eeea53864a 100644 --- a/src/qt/forms/debugwindow.ui +++ b/src/qt/forms/debugwindow.ui @@ -1113,7 +1113,7 @@ - The BIP324 session ID string in hex, if any. + The BIP324 session ID string in hex. Session ID From 100e8a75bf5d8196c005331bd8f2ed42ada6d8d0 Mon Sep 17 00:00:00 2001 From: Sebastian Falbesoner Date: Thu, 24 Aug 2023 15:20:55 +0200 Subject: [PATCH 02/46] rpc: check and throw specific pubkey parsing errors in `HexToPubKey` In the helper `HexToPubKey`, check for three different causes of legacy public key parsing errors (in this order): - pubkey is not a hex string - pubkey doesn't have a valid length (33 or 65 bytes) [NEW] - pubkey is cryptographically invalid, i.e. not on curve (`IsFullyValid` check) and throw a specific error message for each one. Note that the error code is identical for all of them (-5), so this doesn't break RPC API compatibility. The helper is currently used for the RPCs `createmultisig` and `addmultisigaddress`. The length checks can be removed from the call-sites and error message checks in the functional tests are adapted. --- src/rpc/output_script.cpp | 6 +----- src/rpc/util.cpp | 7 +++++-- test/functional/rpc_rawtransaction.py | 4 ++-- 3 files changed, 8 insertions(+), 9 deletions(-) diff --git a/src/rpc/output_script.cpp b/src/rpc/output_script.cpp index f9343f48a8..474d9076be 100644 --- a/src/rpc/output_script.cpp +++ b/src/rpc/output_script.cpp @@ -124,11 +124,7 @@ static RPCHelpMan createmultisig() const UniValue& keys = request.params[1].get_array(); std::vector pubkeys; for (unsigned int i = 0; i < keys.size(); ++i) { - if (IsHex(keys[i].get_str()) && (keys[i].get_str().length() == 66 || keys[i].get_str().length() == 130)) { - pubkeys.push_back(HexToPubKey(keys[i].get_str())); - } else { - throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, strprintf("Invalid public key: %s\n.", keys[i].get_str())); - } + pubkeys.push_back(HexToPubKey(keys[i].get_str())); } // Get the output type diff --git a/src/rpc/util.cpp b/src/rpc/util.cpp index cf48ee11e7..cc11dc4a46 100644 --- a/src/rpc/util.cpp +++ b/src/rpc/util.cpp @@ -180,11 +180,14 @@ std::string HelpExampleRpcNamed(const std::string& methodname, const RPCArgList& CPubKey HexToPubKey(const std::string& hex_in) { if (!IsHex(hex_in)) { - throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Invalid public key: " + hex_in); + throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Pubkey \"" + hex_in + "\" must be a hex string"); + } + if (hex_in.length() != 66 && hex_in.length() != 130) { + throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Pubkey \"" + hex_in + "\" must have a length of either 33 or 65 bytes"); } CPubKey vchPubKey(ParseHex(hex_in)); if (!vchPubKey.IsFullyValid()) { - throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Invalid public key: " + hex_in); + throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Pubkey \"" + hex_in + "\" must be cryptographically valid."); } return vchPubKey; } diff --git a/test/functional/rpc_rawtransaction.py b/test/functional/rpc_rawtransaction.py index c12865b5e3..e5d7cea135 100755 --- a/test/functional/rpc_rawtransaction.py +++ b/test/functional/rpc_rawtransaction.py @@ -491,11 +491,11 @@ def raw_multisig_transaction_legacy_tests(self): addr2Obj = self.nodes[2].getaddressinfo(addr2) # Tests for createmultisig and addmultisigaddress - assert_raises_rpc_error(-5, "Invalid public key", self.nodes[0].createmultisig, 1, ["01020304"]) + assert_raises_rpc_error(-5, 'Pubkey "01020304" must have a length of either 33 or 65 bytes', self.nodes[0].createmultisig, 1, ["01020304"]) # createmultisig can only take public keys self.nodes[0].createmultisig(2, [addr1Obj['pubkey'], addr2Obj['pubkey']]) # addmultisigaddress can take both pubkeys and addresses so long as they are in the wallet, which is tested here - assert_raises_rpc_error(-5, "Invalid public key", self.nodes[0].createmultisig, 2, [addr1Obj['pubkey'], addr1]) + assert_raises_rpc_error(-5, f'Pubkey "{addr1}" must be a hex string', self.nodes[0].createmultisig, 2, [addr1Obj['pubkey'], addr1]) mSigObj = self.nodes[2].addmultisigaddress(2, [addr1Obj['pubkey'], addr1])['address'] From c740b154d193b91ca42f18759098d3fef6eaab05 Mon Sep 17 00:00:00 2001 From: Sebastian Falbesoner Date: Thu, 24 Aug 2023 16:05:44 +0200 Subject: [PATCH 03/46] rpc: use `HexToPubKey` helper for all legacy pubkey-parsing RPCs This deduplicates code and leads to more consistent and detailed error messages. Affected are legacy import RPCs (`importpubkey`, `importmulti`) and other ones where solving data can be provided (`fundrawtransaction`, `walletcreatefundedpsbt`, `send`, `sendall`). --- src/wallet/rpc/backup.cpp | 17 ++--------------- src/wallet/rpc/spend.cpp | 10 +--------- test/functional/wallet_basic.py | 7 ++++--- test/functional/wallet_fundrawtransaction.py | 4 ++-- 4 files changed, 9 insertions(+), 29 deletions(-) diff --git a/src/wallet/rpc/backup.cpp b/src/wallet/rpc/backup.cpp index 99c548bf1d..d17a220603 100644 --- a/src/wallet/rpc/backup.cpp +++ b/src/wallet/rpc/backup.cpp @@ -460,12 +460,7 @@ RPCHelpMan importpubkey() throw JSONRPCError(RPC_WALLET_ERROR, "Wallet is currently rescanning. Abort existing rescan or wait."); } - if (!IsHex(request.params[0].get_str())) - throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Pubkey must be a hex string"); - std::vector data(ParseHex(request.params[0].get_str())); - CPubKey pubKey(data); - if (!pubKey.IsFullyValid()) - throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Pubkey is not a valid public key"); + CPubKey pubKey = HexToPubKey(request.params[0].get_str()); { LOCK(pwallet->cs_wallet); @@ -986,15 +981,7 @@ static UniValue ProcessImportLegacy(ImportData& import_data, std::map(parsed_witnessscript.begin(), parsed_witnessscript.end()); } for (size_t i = 0; i < pubKeys.size(); ++i) { - const auto& str = pubKeys[i].get_str(); - if (!IsHex(str)) { - throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Pubkey \"" + str + "\" must be a hex string"); - } - auto parsed_pubkey = ParseHex(str); - CPubKey pubkey(parsed_pubkey); - if (!pubkey.IsFullyValid()) { - throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Pubkey \"" + str + "\" is not a valid public key"); - } + CPubKey pubkey = HexToPubKey(pubKeys[i].get_str()); pubkey_map.emplace(pubkey.GetID(), pubkey); ordered_pubkeys.push_back(pubkey.GetID()); } diff --git a/src/wallet/rpc/spend.cpp b/src/wallet/rpc/spend.cpp index 6060f017ce..1a364a75ed 100644 --- a/src/wallet/rpc/spend.cpp +++ b/src/wallet/rpc/spend.cpp @@ -627,15 +627,7 @@ CreatedTransactionResult FundTransaction(CWallet& wallet, const CMutableTransact const UniValue solving_data = options["solving_data"].get_obj(); if (solving_data.exists("pubkeys")) { for (const UniValue& pk_univ : solving_data["pubkeys"].get_array().getValues()) { - const std::string& pk_str = pk_univ.get_str(); - if (!IsHex(pk_str)) { - throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, strprintf("'%s' is not hex", pk_str)); - } - const std::vector data(ParseHex(pk_str)); - const CPubKey pubkey(data.begin(), data.end()); - if (!pubkey.IsFullyValid()) { - throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, strprintf("'%s' is not a valid public key", pk_str)); - } + const CPubKey pubkey = HexToPubKey(pk_univ.get_str()); coinControl.m_external_provider.pubkeys.emplace(pubkey.GetID(), pubkey); // Add witness script for pubkeys const CScript wit_script = GetScriptForDestination(WitnessV0KeyHash(pubkey)); diff --git a/test/functional/wallet_basic.py b/test/functional/wallet_basic.py index f798eee365..dbb78e8d35 100755 --- a/test/functional/wallet_basic.py +++ b/test/functional/wallet_basic.py @@ -459,10 +459,11 @@ def run_test(self): assert_raises_rpc_error(-5, "Invalid Bitcoin address or script", self.nodes[0].importaddress, "invalid") # This will raise an exception for attempting to import a pubkey that isn't in hex - assert_raises_rpc_error(-5, "Pubkey must be a hex string", self.nodes[0].importpubkey, "not hex") + assert_raises_rpc_error(-5, 'Pubkey "not hex" must be a hex string', self.nodes[0].importpubkey, "not hex") - # This will raise an exception for importing an invalid pubkey - assert_raises_rpc_error(-5, "Pubkey is not a valid public key", self.nodes[0].importpubkey, "5361746f736869204e616b616d6f746f") + # This will raise an exception for importing a pubkey with invalid length + too_short_pubkey = "5361746f736869204e616b616d6f746f" + assert_raises_rpc_error(-5, f'Pubkey "{too_short_pubkey}" must have a length of either 33 or 65 bytes', self.nodes[0].importpubkey, too_short_pubkey) # Bech32m addresses cannot be imported into a legacy wallet assert_raises_rpc_error(-5, "Bech32m addresses cannot be imported into legacy wallets", self.nodes[0].importaddress, "bcrt1p0xlxvlhemja6c4dqv22uapctqupfhlxm9h8z3k2e72q4k9hcz7vqc8gma6") diff --git a/test/functional/wallet_fundrawtransaction.py b/test/functional/wallet_fundrawtransaction.py index d886a59ac1..083da3d0b7 100755 --- a/test/functional/wallet_fundrawtransaction.py +++ b/test/functional/wallet_fundrawtransaction.py @@ -1055,8 +1055,8 @@ def test_external_inputs(self): assert_raises_rpc_error(-4, "Not solvable pre-selected input COutPoint(%s, %s)" % (ext_utxo["txid"][0:10], ext_utxo["vout"]), wallet.fundrawtransaction, raw_tx) # Error conditions - assert_raises_rpc_error(-5, "'not a pubkey' is not hex", wallet.fundrawtransaction, raw_tx, solving_data={"pubkeys":["not a pubkey"]}) - assert_raises_rpc_error(-5, "'01234567890a0b0c0d0e0f' is not a valid public key", wallet.fundrawtransaction, raw_tx, solving_data={"pubkeys":["01234567890a0b0c0d0e0f"]}) + assert_raises_rpc_error(-5, 'Pubkey "not a pubkey" must be a hex string', wallet.fundrawtransaction, raw_tx, solving_data={"pubkeys":["not a pubkey"]}) + assert_raises_rpc_error(-5, 'Pubkey "01234567890a0b0c0d0e0f" must have a length of either 33 or 65 bytes', wallet.fundrawtransaction, raw_tx, solving_data={"pubkeys":["01234567890a0b0c0d0e0f"]}) assert_raises_rpc_error(-5, "'not a script' is not hex", wallet.fundrawtransaction, raw_tx, solving_data={"scripts":["not a script"]}) assert_raises_rpc_error(-8, "Unable to parse descriptor 'not a descriptor'", wallet.fundrawtransaction, raw_tx, solving_data={"descriptors":["not a descriptor"]}) assert_raises_rpc_error(-8, "Invalid parameter, missing vout key", wallet.fundrawtransaction, raw_tx, input_weights=[{"txid": ext_utxo["txid"]}]) From 98570fe29bb08d7edc48011aa6b9731c6ab4ed2e Mon Sep 17 00:00:00 2001 From: Sebastian Falbesoner Date: Thu, 24 Aug 2023 16:46:36 +0200 Subject: [PATCH 04/46] test: add coverage for parsing cryptographically invalid pubkeys --- test/functional/wallet_basic.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/test/functional/wallet_basic.py b/test/functional/wallet_basic.py index dbb78e8d35..3daec4dbd1 100755 --- a/test/functional/wallet_basic.py +++ b/test/functional/wallet_basic.py @@ -461,9 +461,11 @@ def run_test(self): # This will raise an exception for attempting to import a pubkey that isn't in hex assert_raises_rpc_error(-5, 'Pubkey "not hex" must be a hex string', self.nodes[0].importpubkey, "not hex") - # This will raise an exception for importing a pubkey with invalid length + # This will raise exceptions for importing a pubkeys with invalid length / invalid coordinates too_short_pubkey = "5361746f736869204e616b616d6f746f" assert_raises_rpc_error(-5, f'Pubkey "{too_short_pubkey}" must have a length of either 33 or 65 bytes', self.nodes[0].importpubkey, too_short_pubkey) + not_on_curve_pubkey = bytes([4] + [0]*64).hex() # pubkey with coordinates (0,0) is not on curve + assert_raises_rpc_error(-5, f'Pubkey "{not_on_curve_pubkey}" must be cryptographically valid', self.nodes[0].importpubkey, not_on_curve_pubkey) # Bech32m addresses cannot be imported into a legacy wallet assert_raises_rpc_error(-5, "Bech32m addresses cannot be imported into legacy wallets", self.nodes[0].importaddress, "bcrt1p0xlxvlhemja6c4dqv22uapctqupfhlxm9h8z3k2e72q4k9hcz7vqc8gma6") From d1ed09a7643b567e021b2ecb756bc925c48fc708 Mon Sep 17 00:00:00 2001 From: Luke Dashjr Date: Thu, 14 Mar 2024 23:56:48 +0000 Subject: [PATCH 05/46] Bugfix: GUI: Help messages already have a trailing newline, so don't add an extra one --- src/qt/utilitydialog.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/qt/utilitydialog.cpp b/src/qt/utilitydialog.cpp index 6509a701f3..bdaef47406 100644 --- a/src/qt/utilitydialog.cpp +++ b/src/qt/utilitydialog.cpp @@ -124,7 +124,7 @@ HelpMessageDialog::~HelpMessageDialog() void HelpMessageDialog::printToConsole() { // On other operating systems, the expected action is to print the message to the console. - tfm::format(std::cout, "%s\n", qPrintable(text)); + tfm::format(std::cout, "%s", qPrintable(text)); } void HelpMessageDialog::showOrPrint() From 671b7a32516d62e1e79393ded4b45910bd08010a Mon Sep 17 00:00:00 2001 From: furszy Date: Fri, 29 Mar 2024 11:40:38 -0300 Subject: [PATCH 06/46] gui: fix create unsigned transaction fee bump --- src/qt/walletmodel.cpp | 13 ++++++------- 1 file changed, 6 insertions(+), 7 deletions(-) diff --git a/src/qt/walletmodel.cpp b/src/qt/walletmodel.cpp index 1bdf94d3b5..a481092327 100644 --- a/src/qt/walletmodel.cpp +++ b/src/qt/walletmodel.cpp @@ -529,12 +529,6 @@ bool WalletModel::bumpFee(uint256 hash, uint256& new_hash) return false; } - WalletModel::UnlockContext ctx(requestUnlock()); - if(!ctx.isValid()) - { - return false; - } - // Short-circuit if we are returning a bumped transaction PSBT to clipboard if (retval == QMessageBox::Save) { // "Create Unsigned" clicked @@ -549,10 +543,15 @@ bool WalletModel::bumpFee(uint256 hash, uint256& new_hash) DataStream ssTx{}; ssTx << psbtx; GUIUtil::setClipboard(EncodeBase64(ssTx.str()).c_str()); - Q_EMIT message(tr("PSBT copied"), tr("Copied to clipboard", "Fee-bump PSBT saved"), CClientUIInterface::MSG_INFORMATION); + Q_EMIT message(tr("PSBT copied"), tr("Fee-bump PSBT copied to clipboard"), CClientUIInterface::MSG_INFORMATION | CClientUIInterface::MODAL); return true; } + WalletModel::UnlockContext ctx(requestUnlock()); + if (!ctx.isValid()) { + return false; + } + assert(!m_wallet->privateKeysDisabled() || wallet().hasExternalSigner()); // sign bumped transaction From 23dc0c19acd54cad1bed2f14df024b6b533f2330 Mon Sep 17 00:00:00 2001 From: Hennadii Stepanov <32963518+hebasto@users.noreply.github.com> Date: Sat, 30 Mar 2024 09:34:20 +0000 Subject: [PATCH 07/46] msvc, bench: Add missing source files to bench_bitcoin project --- build_msvc/bench_bitcoin/bench_bitcoin.vcxproj.in | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/build_msvc/bench_bitcoin/bench_bitcoin.vcxproj.in b/build_msvc/bench_bitcoin/bench_bitcoin.vcxproj.in index a5702a83ba..972d6d05d7 100644 --- a/build_msvc/bench_bitcoin/bench_bitcoin.vcxproj.in +++ b/build_msvc/bench_bitcoin/bench_bitcoin.vcxproj.in @@ -10,6 +10,12 @@ @SOURCE_FILES@ + + + + + + From 31a15f0aff79d2b34a9640909b9e6fb39a647b60 Mon Sep 17 00:00:00 2001 From: Hennadii Stepanov <32963518+hebasto@users.noreply.github.com> Date: Sun, 31 Mar 2024 10:24:20 +0100 Subject: [PATCH 08/46] bench: Disable WalletCreate* benchmarks when building with MSVC --- src/bench/wallet_create.cpp | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/bench/wallet_create.cpp b/src/bench/wallet_create.cpp index 32f55f51e1..d7e772ac82 100644 --- a/src/bench/wallet_create.cpp +++ b/src/bench/wallet_create.cpp @@ -51,9 +51,14 @@ static void WalletCreate(benchmark::Bench& bench, bool encrypted) static void WalletCreatePlain(benchmark::Bench& bench) { WalletCreate(bench, /*encrypted=*/false); } static void WalletCreateEncrypted(benchmark::Bench& bench) { WalletCreate(bench, /*encrypted=*/true); } +#ifndef _MSC_VER +// TODO: Being built with MSVC, the fs::remove_all() call in +// the WalletCreate() fails with the error "The process cannot +// access the file because it is being used by another process." #ifdef USE_SQLITE BENCHMARK(WalletCreatePlain, benchmark::PriorityLevel::LOW); BENCHMARK(WalletCreateEncrypted, benchmark::PriorityLevel::LOW); #endif +#endif } // namespace wallet From 10c5275ba4532fb1bf54057d2f61fc35b51f1e85 Mon Sep 17 00:00:00 2001 From: willcl-ark Date: Thu, 4 Apr 2024 21:08:38 +0100 Subject: [PATCH 09/46] gui: don't permit port in proxy IP option Fixes: #809 Previously it was possible through the GUI to enter an IP address:port into the "Proxy IP" configuration box. After the node was restarted the errant setting would prevent the node starting back up until manually removed from settings.json. --- src/qt/optionsdialog.cpp | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/qt/optionsdialog.cpp b/src/qt/optionsdialog.cpp index dd654a7abe..6d0904adb8 100644 --- a/src/qt/optionsdialog.cpp +++ b/src/qt/optionsdialog.cpp @@ -20,6 +20,7 @@ #include #include #include +#include #include @@ -482,7 +483,10 @@ QValidator(parent) QValidator::State ProxyAddressValidator::validate(QString &input, int &pos) const { Q_UNUSED(pos); - // Validate the proxy + uint16_t port{0}; + std::string hostname; + if (!SplitHostPort(input.toStdString(), port, hostname) || port != 0) return QValidator::Invalid; + CService serv(LookupNumeric(input.toStdString(), DEFAULT_GUI_PROXY_PORT)); Proxy addrProxy = Proxy(serv, true); if (addrProxy.IsValid()) From e912717ff63f111d8f1cd7ed1fcf054e28f36409 Mon Sep 17 00:00:00 2001 From: umiumi <9@umi.cat> Date: Wed, 24 Apr 2024 09:51:01 +0800 Subject: [PATCH 10/46] test: add missing comparison of node1's mempool in MempoolPackagesTest --- test/functional/mempool_packages.py | 26 +++++++++++++++----------- 1 file changed, 15 insertions(+), 11 deletions(-) diff --git a/test/functional/mempool_packages.py b/test/functional/mempool_packages.py index dcb66b2ca1..e83c62915e 100755 --- a/test/functional/mempool_packages.py +++ b/test/functional/mempool_packages.py @@ -199,13 +199,13 @@ def run_test(self): assert set(mempool1).issubset(set(mempool0)) for tx in chain[:CUSTOM_ANCESTOR_LIMIT]: assert tx in mempool1 - # TODO: more detailed check of node1's mempool (fees etc.) - # check transaction unbroadcast info (should be false if in both mempools) - mempool = self.nodes[0].getrawmempool(True) - for tx in mempool: - assert_equal(mempool[tx]['unbroadcast'], False) - - # TODO: test ancestor size limits + entry0 = self.nodes[0].getmempoolentry(tx) + entry1 = self.nodes[1].getmempoolentry(tx) + assert not entry0['unbroadcast'] + assert not entry1['unbroadcast'] + assert_equal(entry1['fees']['base'], entry0['fees']['base']) + assert_equal(entry1['vsize'], entry0['vsize']) + assert_equal(entry1['depends'], entry0['depends']) # Now test descendant chain limits @@ -251,10 +251,14 @@ def run_test(self): assert tx in mempool1 for tx in chain[CUSTOM_DESCENDANT_LIMIT:]: assert tx not in mempool1 - # TODO: more detailed check of node1's mempool (fees etc.) - - # TODO: test descendant size limits - + for tx in mempool1: + entry0 = self.nodes[0].getmempoolentry(tx) + entry1 = self.nodes[1].getmempoolentry(tx) + assert not entry0['unbroadcast'] + assert not entry1['unbroadcast'] + assert_equal(entry1['fees']['base'], entry0['fees']['base']) + assert_equal(entry1['vsize'], entry0['vsize']) + assert_equal(entry1['depends'], entry0['depends']) # Test reorg handling # First, the basics: self.generate(self.nodes[0], 1) From 6abe772a17e09fe96e68cd3311280d5a30f6378b Mon Sep 17 00:00:00 2001 From: Fabian Jahr Date: Wed, 1 Nov 2023 20:05:18 +0100 Subject: [PATCH 11/46] contrib: Add asmap-tool Co-authored-by: Pieter Wuille --- contrib/asmap/README.md | 12 +++ contrib/asmap/asmap-tool.py | 156 ++++++++++++++++++++++++++++++ contrib/{seeds => asmap}/asmap.py | 6 +- contrib/seeds/makeseeds.py | 5 +- 4 files changed, 176 insertions(+), 3 deletions(-) create mode 100644 contrib/asmap/README.md create mode 100755 contrib/asmap/asmap-tool.py rename contrib/{seeds => asmap}/asmap.py (99%) diff --git a/contrib/asmap/README.md b/contrib/asmap/README.md new file mode 100644 index 0000000000..5fab4b285e --- /dev/null +++ b/contrib/asmap/README.md @@ -0,0 +1,12 @@ +# ASMap Tool + +Tool for performing various operations on textual and binary asmap files, +particularly encoding/compressing the raw data to the binary format that can +be used in Bitcoin Core with the `-asmap` option. + +Example usage: +``` +python3 asmap-tool.py encode /path/to/input.file /path/to/output.file +python3 asmap-tool.py decode /path/to/input.file /path/to/output.file +python3 asmap-tool.py diff /path/to/first.file /path/to/second.file +``` diff --git a/contrib/asmap/asmap-tool.py b/contrib/asmap/asmap-tool.py new file mode 100755 index 0000000000..09c28725e4 --- /dev/null +++ b/contrib/asmap/asmap-tool.py @@ -0,0 +1,156 @@ +#!/usr/bin/env python3 +# Copyright (c) 2022 Pieter Wuille +# Distributed under the MIT software license, see the accompanying +# file LICENSE or http://www.opensource.org/licenses/mit-license.php. + +import argparse +import sys +import ipaddress +import math + +import asmap + +def load_file(input_file): + try: + contents = input_file.read() + except OSError as err: + sys.exit(f"Input file '{input_file.name}' cannot be read: {err.strerror}.") + try: + bin_asmap = asmap.ASMap.from_binary(contents) + except ValueError: + bin_asmap = None + txt_error = None + entries = None + try: + txt_contents = str(contents, encoding="utf-8") + except UnicodeError: + txt_error = "invalid UTF-8" + txt_contents = None + if txt_contents is not None: + entries = [] + for line in txt_contents.split("\n"): + idx = line.find('#') + if idx >= 0: + line = line[:idx] + line = line.lstrip(' ').rstrip(' \t\r\n') + if len(line) == 0: + continue + fields = line.split(' ') + if len(fields) != 2: + txt_error = f"unparseable line '{line}'" + entries = None + break + prefix, asn = fields + if len(asn) <= 2 or asn[:2] != "AS" or any(c < '0' or c > '9' for c in asn[2:]): + txt_error = f"invalid ASN '{asn}'" + entries = None + break + try: + net = ipaddress.ip_network(prefix) + except ValueError: + txt_error = f"invalid network '{prefix}'" + entries = None + break + entries.append((asmap.net_to_prefix(net), int(asn[2:]))) + if entries is not None and bin_asmap is not None and len(contents) > 0: + sys.exit(f"Input file '{input_file.name}' is ambiguous.") + if entries is not None: + state = asmap.ASMap() + state.update_multi(entries) + return state + if bin_asmap is not None: + return bin_asmap + sys.exit(f"Input file '{input_file.name}' is neither a valid binary asmap file nor valid text input ({txt_error}).") + + +def save_binary(output_file, state, fill): + contents = state.to_binary(fill=fill) + try: + output_file.write(contents) + output_file.close() + except OSError as err: + sys.exit(f"Output file '{output_file.name}' cannot be written to: {err.strerror}.") + +def save_text(output_file, state, fill, overlapping): + for prefix, asn in state.to_entries(fill=fill, overlapping=overlapping): + net = asmap.prefix_to_net(prefix) + try: + print(f"{net} AS{asn}", file=output_file) + except OSError as err: + sys.exit(f"Output file '{output_file.name}' cannot be written to: {err.strerror}.") + try: + output_file.close() + except OSError as err: + sys.exit(f"Output file '{output_file.name}' cannot be written to: {err.strerror}.") + +def main(): + parser = argparse.ArgumentParser(description="Tool for performing various operations on textual and binary asmap files.") + subparsers = parser.add_subparsers(title="valid subcommands", dest="subcommand") + + parser_encode = subparsers.add_parser("encode", help="convert asmap data to binary format") + parser_encode.add_argument('-f', '--fill', dest="fill", default=False, action="store_true", + help="permit reassigning undefined network ranges arbitrarily to reduce size") + parser_encode.add_argument('infile', nargs='?', type=argparse.FileType('rb'), default=sys.stdin.buffer, + help="input asmap file (text or binary); default is stdin") + parser_encode.add_argument('outfile', nargs='?', type=argparse.FileType('wb'), default=sys.stdout.buffer, + help="output binary asmap file; default is stdout") + + parser_decode = subparsers.add_parser("decode", help="convert asmap data to text format") + parser_decode.add_argument('-f', '--fill', dest="fill", default=False, action="store_true", + help="permit reassigning undefined network ranges arbitrarily to reduce length") + parser_decode.add_argument('-n', '--nonoverlapping', dest="overlapping", default=True, action="store_false", + help="output strictly non-overall ping network ranges (increases output size)") + parser_decode.add_argument('infile', nargs='?', type=argparse.FileType('rb'), default=sys.stdin.buffer, + help="input asmap file (text or binary); default is stdin") + parser_decode.add_argument('outfile', nargs='?', type=argparse.FileType('w'), default=sys.stdout, + help="output text file; default is stdout") + + parser_diff = subparsers.add_parser("diff", help="compute the difference between two asmap files") + parser_diff.add_argument('-i', '--ignore-unassigned', dest="ignore_unassigned", default=False, action="store_true", + help="ignore unassigned ranges in the first input (useful when second input is filled)") + parser_diff.add_argument('infile1', type=argparse.FileType('rb'), + help="first file to compare (text or binary)") + parser_diff.add_argument('infile2', type=argparse.FileType('rb'), + help="second file to compare (text or binary)") + + args = parser.parse_args() + if args.subcommand is None: + parser.print_help() + elif args.subcommand == "encode": + state = load_file(args.infile) + save_binary(args.outfile, state, fill=args.fill) + elif args.subcommand == "decode": + state = load_file(args.infile) + save_text(args.outfile, state, fill=args.fill, overlapping=args.overlapping) + elif args.subcommand == "diff": + state1 = load_file(args.infile1) + state2 = load_file(args.infile2) + ipv4_changed = 0 + ipv6_changed = 0 + for prefix, old_asn, new_asn in state1.diff(state2): + if args.ignore_unassigned and old_asn == 0: + continue + net = asmap.prefix_to_net(prefix) + if isinstance(net, ipaddress.IPv4Network): + ipv4_changed += 1 << (32 - net.prefixlen) + elif isinstance(net, ipaddress.IPv6Network): + ipv6_changed += 1 << (128 - net.prefixlen) + if new_asn == 0: + print(f"# {net} was AS{old_asn}") + elif old_asn == 0: + print(f"{net} AS{new_asn} # was unassigned") + else: + print(f"{net} AS{new_asn} # was AS{old_asn}") + ipv4_change_str = "" if ipv4_changed == 0 else f" (2^{math.log2(ipv4_changed):.2f})" + ipv6_change_str = "" if ipv6_changed == 0 else f" (2^{math.log2(ipv6_changed):.2f})" + + print( + f"# {ipv4_changed}{ipv4_change_str} IPv4 addresses changed; " + f"{ipv6_changed}{ipv6_change_str} IPv6 addresses changed" + ) + else: + parser.print_help() + sys.exit("No command provided.") + +if __name__ == '__main__': + main() diff --git a/contrib/seeds/asmap.py b/contrib/asmap/asmap.py similarity index 99% rename from contrib/seeds/asmap.py rename to contrib/asmap/asmap.py index 214805b5a5..2ae84a3f31 100644 --- a/contrib/seeds/asmap.py +++ b/contrib/asmap/asmap.py @@ -489,12 +489,14 @@ def candidate(ctx: Optional[int], arg1, arg2, func: Callable): if ctx not in ret or cand.size < ret[ctx].size: ret[ctx] = cand - for ctx in set(left) | set(right): + union = set(left) | set(right) + sorted_union = sorted(union, key=lambda x: (x is None, x)) + for ctx in sorted_union: candidate(ctx, left.get(ctx), right.get(ctx), _BinNode.make_branch) candidate(ctx, left.get(None), right.get(ctx), _BinNode.make_branch) candidate(ctx, left.get(ctx), right.get(None), _BinNode.make_branch) if not hole: - for ctx in set(ret) - set([None]): + for ctx in sorted(set(ret) - set([None])): candidate(None, ctx, ret[ctx], _BinNode.make_default) if None in ret: ret = {ctx:enc for ctx, enc in ret.items() diff --git a/contrib/seeds/makeseeds.py b/contrib/seeds/makeseeds.py index f03c2ab5e8..fd8c7511d0 100755 --- a/contrib/seeds/makeseeds.py +++ b/contrib/seeds/makeseeds.py @@ -9,11 +9,14 @@ import argparse import collections import ipaddress +from pathlib import Path import re import sys from typing import Union -from asmap import ASMap, net_to_prefix +asmap_dir = Path(__file__).parent.parent / "asmap" +sys.path.append(str(asmap_dir)) +from asmap import ASMap, net_to_prefix # noqa: E402 NSEEDS=512 From b259b0e8d360726b062c4b0453d1cf5a68e1933f Mon Sep 17 00:00:00 2001 From: Alfonso Roman Zubeldia Date: Fri, 26 Apr 2024 10:50:00 -0300 Subject: [PATCH 12/46] [Test] Assumeutxo: ensure failure when importing a snapshot twice --- test/functional/feature_assumeutxo.py | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/test/functional/feature_assumeutxo.py b/test/functional/feature_assumeutxo.py index 19cbbcffdb..ffbbfc8949 100755 --- a/test/functional/feature_assumeutxo.py +++ b/test/functional/feature_assumeutxo.py @@ -395,6 +395,10 @@ def check_tx_counts(final: bool) -> None: assert_equal(snapshot['snapshot_blockhash'], dump_output['base_hash']) assert_equal(snapshot['validated'], False) + self.log.info("Check that loading the snapshot again will fail because there is already an active snapshot.") + with n2.assert_debug_log(expected_msgs=["[snapshot] can't activate a snapshot-based chainstate more than once"]): + assert_raises_rpc_error(-32603, "Unable to load UTXO snapshot", n2.loadtxoutset, dump_output['path']) + self.connect_nodes(0, 2) self.wait_until(lambda: n2.getchainstates()['chainstates'][-1]['blocks'] == FINAL_HEIGHT) self.sync_blocks() From a8d9a0edc7cef2c31a557ef53eb45520976b0d65 Mon Sep 17 00:00:00 2001 From: Sergi Delgado Segura Date: Wed, 20 Dec 2023 10:53:49 -0500 Subject: [PATCH 13/46] test: adds outbound eviction functional tests, updates comment in ConsiderEviction --- src/net_processing.cpp | 11 +- test/functional/p2p_outbound_eviction.py | 224 +++++++++++++++++++++++ test/functional/test_runner.py | 1 + 3 files changed, 232 insertions(+), 4 deletions(-) create mode 100755 test/functional/p2p_outbound_eviction.py diff --git a/src/net_processing.cpp b/src/net_processing.cpp index 39ffff97d2..f936f1b666 100644 --- a/src/net_processing.cpp +++ b/src/net_processing.cpp @@ -5165,16 +5165,19 @@ void PeerManagerImpl::ConsiderEviction(CNode& pto, Peer& peer, std::chrono::seco // unless it's invalid, in which case we should find that out and // disconnect from them elsewhere). if (state.pindexBestKnownBlock != nullptr && state.pindexBestKnownBlock->nChainWork >= m_chainman.ActiveChain().Tip()->nChainWork) { + // The outbound peer has sent us a block with at least as much work as our current tip, so reset the timeout if it was set if (state.m_chain_sync.m_timeout != 0s) { state.m_chain_sync.m_timeout = 0s; state.m_chain_sync.m_work_header = nullptr; state.m_chain_sync.m_sent_getheaders = false; } } else if (state.m_chain_sync.m_timeout == 0s || (state.m_chain_sync.m_work_header != nullptr && state.pindexBestKnownBlock != nullptr && state.pindexBestKnownBlock->nChainWork >= state.m_chain_sync.m_work_header->nChainWork)) { - // Our best block known by this peer is behind our tip, and we're either noticing - // that for the first time, OR this peer was able to catch up to some earlier point - // where we checked against our tip. - // Either way, set a new timeout based on current tip. + // At this point we know that the outbound peer has either never sent us a block/header or they have, but its tip is behind ours + // AND + // we are noticing this for the first time (m_timeout is 0) + // OR we noticed this at some point within the last CHAIN_SYNC_TIMEOUT + HEADERS_RESPONSE_TIME seconds and set a timeout + // for them, they caught up to our tip at the time of setting the timer but not to our current one (we've also advanced). + // Either way, set a new timeout based on our current tip. state.m_chain_sync.m_timeout = time_in_seconds + CHAIN_SYNC_TIMEOUT; state.m_chain_sync.m_work_header = m_chainman.ActiveChain().Tip(); state.m_chain_sync.m_sent_getheaders = false; diff --git a/test/functional/p2p_outbound_eviction.py b/test/functional/p2p_outbound_eviction.py new file mode 100755 index 0000000000..43dec4df83 --- /dev/null +++ b/test/functional/p2p_outbound_eviction.py @@ -0,0 +1,224 @@ +#!/usr/bin/env python3 +# Copyright (c) 2019-2021 The Bitcoin Core developers +# Distributed under the MIT software license, see the accompanying +# file COPYING or http://www.opensource.org/licenses/mit-license.php. + +""" Test node outbound peer eviction logic + +A subset of our outbound peers are subject to eviction logic if they cannot keep up +with our vision of the best chain. This criteria applies only to non-protected peers, +and can be triggered by either not learning about any blocks from an outbound peer after +a certain deadline, or by them not being able to catch up fast enough (under the same deadline). + +This tests the different eviction paths based on the peer's behavior and on whether they are protected +or not. +""" +import time + +from test_framework.messages import ( + from_hex, + msg_headers, + CBlockHeader, +) +from test_framework.p2p import P2PInterface +from test_framework.test_framework import BitcoinTestFramework + +# Timeouts (in seconds) +CHAIN_SYNC_TIMEOUT = 20 * 60 +HEADERS_RESPONSE_TIME = 2 * 60 + + +class P2POutEvict(BitcoinTestFramework): + def set_test_params(self): + self.num_nodes = 1 + + def test_outbound_eviction_unprotected(self): + # This tests the eviction logic for **unprotected** outbound peers (that is, PeerManagerImpl::ConsiderEviction) + node = self.nodes[0] + cur_mock_time = node.mocktime + + # Get our tip header and its parent + tip_header = from_hex(CBlockHeader(), node.getblockheader(node.getbestblockhash(), False)) + prev_header = from_hex(CBlockHeader(), node.getblockheader(f"{tip_header.hashPrevBlock:064x}", False)) + + self.log.info("Create an outbound connection and don't send any headers") + # Test disconnect due to no block being announced in 22+ minutes (headers are not even exchanged) + peer = node.add_outbound_p2p_connection(P2PInterface(), p2p_idx=0, connection_type="outbound-full-relay") + # Wait for over 20 min to trigger the first eviction timeout. This sets the last call past 2 min in the future. + cur_mock_time += (CHAIN_SYNC_TIMEOUT + 1) + node.setmocktime(cur_mock_time) + peer.sync_with_ping() + # Wait for over 2 more min to trigger the disconnection + peer.wait_for_getheaders(block_hash=tip_header.hashPrevBlock) + cur_mock_time += (HEADERS_RESPONSE_TIME + 1) + node.setmocktime(cur_mock_time) + self.log.info("Test that the peer gets evicted") + peer.wait_for_disconnect() + + self.log.info("Create an outbound connection and send header but never catch up") + # Mimic a node that just falls behind for long enough + # This should also apply for a node doing IBD that does not catch up in time + # Connect a peer and make it send us headers ending in our tip's parent + peer = node.add_outbound_p2p_connection(P2PInterface(), p2p_idx=0, connection_type="outbound-full-relay") + peer.send_and_ping(msg_headers([prev_header])) + + # Trigger the timeouts + cur_mock_time += (CHAIN_SYNC_TIMEOUT + 1) + node.setmocktime(cur_mock_time) + peer.sync_with_ping() + peer.wait_for_getheaders(block_hash=tip_header.hashPrevBlock) + cur_mock_time += (HEADERS_RESPONSE_TIME + 1) + node.setmocktime(cur_mock_time) + self.log.info("Test that the peer gets evicted") + peer.wait_for_disconnect() + + self.log.info("Create an outbound connection and keep lagging behind, but not too much") + # Test that if the peer never catches up with our current tip, but it does with the + # expected work that we set when setting the timer (that is, our tip at the time) + # we do not disconnect the peer + peer = node.add_outbound_p2p_connection(P2PInterface(), p2p_idx=0, connection_type="outbound-full-relay") + + self.log.info("Mine a block so our peer starts lagging") + prev_prev_hash = tip_header.hashPrevBlock + best_block_hash = self.generateblock(node, output="raw(42)", transactions=[])["hash"] + peer.sync_with_ping() + + self.log.info("Keep catching up with the old tip and check that we are not evicted") + for i in range(10): + # Generate an additional block so the peers is 2 blocks behind + prev_header = from_hex(CBlockHeader(), node.getblockheader(best_block_hash, False)) + best_block_hash = self.generateblock(node, output="raw(42)", transactions=[])["hash"] + peer.sync_with_ping() + + # Advance time but not enough to evict the peer + cur_mock_time += (CHAIN_SYNC_TIMEOUT + 1) + node.setmocktime(cur_mock_time) + peer.sync_with_ping() + + # Wait until we get out last call (by receiving a getheaders) + peer.wait_for_getheaders(block_hash=prev_prev_hash) + + # Send a header with the previous tip (so we go back to 1 block behind) + peer.send_and_ping(msg_headers([prev_header])) + prev_prev_hash = tip_header.hash + + self.log.info("Create an outbound connection and take some time to catch up, but do it in time") + # Check that if the peer manages to catch up within time, the timeouts are removed (and the peer is not disconnected) + # We are reusing the peer from the previous case which already sent us a valid (but old) block and whose timer is ticking + + # Send an updated headers message matching our tip + peer.send_and_ping(msg_headers([from_hex(CBlockHeader(), node.getblockheader(best_block_hash, False))])) + + # Wait for long enough for the timeouts to have triggered and check that we are still connected + cur_mock_time += (CHAIN_SYNC_TIMEOUT + 1) + node.setmocktime(cur_mock_time) + peer.sync_with_ping() + cur_mock_time += (HEADERS_RESPONSE_TIME + 1) + node.setmocktime(cur_mock_time) + self.log.info("Test that the peer does not get evicted") + peer.sync_with_ping() + + node.disconnect_p2ps() + + def test_outbound_eviction_protected(self): + # This tests the eviction logic for **protected** outbound peers (that is, PeerManagerImpl::ConsiderEviction) + # Outbound connections are flagged as protected as long as they have sent us a connecting block with at least as + # much work as our current tip and we have enough empty protected_peers slots. + node = self.nodes[0] + cur_mock_time = node.mocktime + tip_header = from_hex(CBlockHeader(), node.getblockheader(node.getbestblockhash(), False)) + + self.log.info("Create an outbound connection to a peer that shares our tip so it gets granted protection") + peer = node.add_outbound_p2p_connection(P2PInterface(), p2p_idx=0, connection_type="outbound-full-relay") + peer.send_and_ping(msg_headers([tip_header])) + + self.log.info("Mine a new block and sync with our peer") + self.generateblock(node, output="raw(42)", transactions=[]) + peer.sync_with_ping() + + self.log.info("Let enough time pass for the timeouts to go off") + # Trigger the timeouts and check how we are still connected + cur_mock_time += (CHAIN_SYNC_TIMEOUT + 1) + node.setmocktime(cur_mock_time) + peer.sync_with_ping() + peer.wait_for_getheaders(block_hash=tip_header.hashPrevBlock) + cur_mock_time += (HEADERS_RESPONSE_TIME + 1) + node.setmocktime(cur_mock_time) + self.log.info("Test that the node does not get evicted") + peer.sync_with_ping() + + node.disconnect_p2ps() + + def test_outbound_eviction_mixed(self): + # This tests the outbound eviction logic for a mix of protected and unprotected peers. + node = self.nodes[0] + cur_mock_time = node.mocktime + + self.log.info("Create a mix of protected and unprotected outbound connections to check against eviction") + + # Let's try this logic having multiple peers, some protected and some unprotected + # We protect up to 4 peers as long as they have provided a block with the same amount of work as our tip + self.log.info("The first 4 peers are protected by sending us a valid block with enough work") + tip_header = from_hex(CBlockHeader(), node.getblockheader(node.getbestblockhash(), False)) + headers_message = msg_headers([tip_header]) + protected_peers = [] + for i in range(4): + peer = node.add_outbound_p2p_connection(P2PInterface(), p2p_idx=i, connection_type="outbound-full-relay") + peer.send_and_ping(headers_message) + protected_peers.append(peer) + + # We can create 4 additional outbound connections to peers that are unprotected. 2 of them will be well behaved, + # whereas the other 2 will misbehave (1 sending no headers, 1 sending old ones) + self.log.info("The remaining 4 peers will be mixed between honest (2) and misbehaving peers (2)") + prev_header = from_hex(CBlockHeader(), node.getblockheader(f"{tip_header.hashPrevBlock:064x}", False)) + headers_message = msg_headers([prev_header]) + honest_unprotected_peers = [] + for i in range(2): + peer = node.add_outbound_p2p_connection(P2PInterface(), p2p_idx=4+i, connection_type="outbound-full-relay") + peer.send_and_ping(headers_message) + honest_unprotected_peers.append(peer) + + misbehaving_unprotected_peers = [] + for i in range(2): + peer = node.add_outbound_p2p_connection(P2PInterface(), p2p_idx=6+i, connection_type="outbound-full-relay") + if i%2==0: + peer.send_and_ping(headers_message) + misbehaving_unprotected_peers.append(peer) + + self.log.info("Mine a new block and keep the unprotected honest peer on sync, all the rest off-sync") + # Mine a block so all peers become outdated + target_hash = prev_header.rehash() + tip_hash = self.generateblock(node, output="raw(42)", transactions=[])["hash"] + tip_header = from_hex(CBlockHeader(), node.getblockheader(tip_hash, False)) + tip_headers_message = msg_headers([tip_header]) + + # Let the timeouts hit and check back + cur_mock_time += (CHAIN_SYNC_TIMEOUT + 1) + node.setmocktime(cur_mock_time) + for peer in protected_peers + misbehaving_unprotected_peers: + peer.sync_with_ping() + peer.wait_for_getheaders(block_hash=target_hash) + for peer in honest_unprotected_peers: + peer.send_and_ping(tip_headers_message) + peer.wait_for_getheaders(block_hash=target_hash) + + cur_mock_time += (HEADERS_RESPONSE_TIME + 1) + node.setmocktime(cur_mock_time) + self.log.info("Check how none of the honest nor protected peers was evicted but all the misbehaving unprotected were") + for peer in protected_peers + honest_unprotected_peers: + peer.sync_with_ping() + for peer in misbehaving_unprotected_peers: + peer.wait_for_disconnect() + + node.disconnect_p2ps() + + + def run_test(self): + self.nodes[0].setmocktime(int(time.time())) + self.test_outbound_eviction_unprotected() + self.test_outbound_eviction_protected() + self.test_outbound_eviction_mixed() + + +if __name__ == '__main__': + P2POutEvict().main() diff --git a/test/functional/test_runner.py b/test/functional/test_runner.py index 32b55813a8..ec9096f929 100755 --- a/test/functional/test_runner.py +++ b/test/functional/test_runner.py @@ -292,6 +292,7 @@ 'p2p_leak_tx.py --v1transport', 'p2p_leak_tx.py --v2transport', 'p2p_eviction.py', + 'p2p_outbound_eviction.py', 'p2p_ibd_stalling.py --v1transport', 'p2p_ibd_stalling.py --v2transport', 'p2p_net_deadlock.py --v1transport', From d53d84834747c37f4060a9ef379e0a6b50155246 Mon Sep 17 00:00:00 2001 From: Sergi Delgado Segura Date: Fri, 1 Mar 2024 11:08:39 -0500 Subject: [PATCH 14/46] test: adds outbound eviction tests for non outbound-full-relay peers Peer protection is only given to outbound-full-relay peers. Add a negative test to check that other type of outbound peers are not given protection under the circumstances that outbound-full-relay would --- test/functional/p2p_outbound_eviction.py | 29 ++++++++++++++++++++++++ 1 file changed, 29 insertions(+) diff --git a/test/functional/p2p_outbound_eviction.py b/test/functional/p2p_outbound_eviction.py index 43dec4df83..8d89688999 100755 --- a/test/functional/p2p_outbound_eviction.py +++ b/test/functional/p2p_outbound_eviction.py @@ -212,12 +212,41 @@ def test_outbound_eviction_mixed(self): node.disconnect_p2ps() + def test_outbound_eviction_blocks_relay_only(self): + # The logic for outbound eviction protection only applies to outbound-full-relay peers + # This tests that other types of peers (blocks-relay-only for instance) are not granted protection + node = self.nodes[0] + cur_mock_time = node.mocktime + tip_header = from_hex(CBlockHeader(), node.getblockheader(node.getbestblockhash(), False)) + + self.log.info("Create an blocks-only outbound connection to a peer that shares our tip. This would usually grant protection") + peer = node.add_outbound_p2p_connection(P2PInterface(), p2p_idx=0, connection_type="block-relay-only") + peer.send_and_ping(msg_headers([tip_header])) + + self.log.info("Mine a new block and sync with our peer") + self.generateblock(node, output="raw(42)", transactions=[]) + peer.sync_with_ping() + + self.log.info("Let enough time pass for the timeouts to go off") + # Trigger the timeouts and check how the peer gets evicted, since protection is only given to outbound-full-relay peers + cur_mock_time += (CHAIN_SYNC_TIMEOUT + 1) + node.setmocktime(cur_mock_time) + peer.sync_with_ping() + peer.wait_for_getheaders(block_hash=tip_header.hash) + cur_mock_time += (HEADERS_RESPONSE_TIME + 1) + node.setmocktime(cur_mock_time) + self.log.info("Test that the peer gets evicted") + peer.wait_for_disconnect() + + node.disconnect_p2ps() + def run_test(self): self.nodes[0].setmocktime(int(time.time())) self.test_outbound_eviction_unprotected() self.test_outbound_eviction_protected() self.test_outbound_eviction_mixed() + self.test_outbound_eviction_blocks_relay_only() if __name__ == '__main__': From 7766dd280d9a4a7ffdfcec58224d0985cfd4169b Mon Sep 17 00:00:00 2001 From: laanwj <126646+laanwj@users.noreply.github.com> Date: Sun, 28 Apr 2024 11:35:27 +0200 Subject: [PATCH 15/46] net: Replace ifname check with IFF_LOOPBACK in Discover Checking the interface name is kind of brittle. In the age of network namespaces and containers, there is no reason a loopback interface can't be called differently. Check for the `IFF_LOOPBACK` flag to detect loopback interface instead. --- src/net.cpp | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/net.cpp b/src/net.cpp index 4801f5c1f9..7e60ef6df5 100644 --- a/src/net.cpp +++ b/src/net.cpp @@ -3077,8 +3077,7 @@ void Discover() { if (ifa->ifa_addr == nullptr) continue; if ((ifa->ifa_flags & IFF_UP) == 0) continue; - if (strcmp(ifa->ifa_name, "lo") == 0) continue; - if (strcmp(ifa->ifa_name, "lo0") == 0) continue; + if ((ifa->ifa_flags & IFF_LOOPBACK) != 0) continue; if (ifa->ifa_addr->sa_family == AF_INET) { struct sockaddr_in* s4 = (struct sockaddr_in*)(ifa->ifa_addr); From a68fed111be393ddbbcd7451f78bc63601253ee0 Mon Sep 17 00:00:00 2001 From: laanwj <126646+laanwj@users.noreply.github.com> Date: Sun, 28 Apr 2024 11:40:19 +0200 Subject: [PATCH 16/46] net: Fix misleading comment for Discover All network addresses are being iterated over and added, not just the first one per interface. --- src/net.h | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/net.h b/src/net.h index 46d9422695..55209324b1 100644 --- a/src/net.h +++ b/src/net.h @@ -137,8 +137,7 @@ struct CSerializedNetMsg { /** * Look up IP addresses from all interfaces on the machine and add them to the * list of local addresses to self-advertise. - * The loopback interface is skipped and only the first address from each - * interface is used. + * The loopback interface is skipped. */ void Discover(); From 357ad110548d726021547d85b5b2bfcf3191d7e3 Mon Sep 17 00:00:00 2001 From: Brandon Odiwuor Date: Sun, 28 Jan 2024 11:33:17 +0300 Subject: [PATCH 17/46] test: Handle functional test disk-full error --- test/functional/test_runner.py | 26 ++++++++++++++++++++++++++ 1 file changed, 26 insertions(+) diff --git a/test/functional/test_runner.py b/test/functional/test_runner.py index f6eccab2b3..2b9faa6368 100755 --- a/test/functional/test_runner.py +++ b/test/functional/test_runner.py @@ -29,6 +29,13 @@ os.environ["REQUIRE_WALLET_TYPE_SET"] = "1" +# Minimum amount of space to run the tests. +MIN_FREE_SPACE = 1.1 * 1024 * 1024 * 1024 +# Additional space to run an extra job. +ADDITIONAL_SPACE_PER_JOB = 100 * 1024 * 1024 +# Minimum amount of space required for --nocleanup +MIN_NO_CLEANUP_SPACE = 12 * 1024 * 1024 * 1024 + # Formatting. Default colors to empty strings. DEFAULT, BOLD, GREEN, RED = ("", ""), ("", ""), ("", ""), ("", "") try: @@ -424,6 +431,8 @@ def main(): parser.add_argument('--tmpdirprefix', '-t', default=tempfile.gettempdir(), help="Root directory for datadirs") parser.add_argument('--failfast', '-F', action='store_true', help='stop execution after the first test failure') parser.add_argument('--filter', help='filter scripts to run by regular expression') + parser.add_argument("--nocleanup", dest="nocleanup", default=False, action="store_true", + help="Leave bitcoinds and test.* datadir on exit or error") args, unknown_args = parser.parse_known_args() @@ -518,6 +527,13 @@ def main(): subprocess.check_call([sys.executable, os.path.join(config["environment"]["SRCDIR"], 'test', 'functional', test_list[0].split()[0]), '-h']) sys.exit(0) + # Warn if there is not enough space on tmpdir to run the tests with --nocleanup + if args.nocleanup: + if shutil.disk_usage(tmpdir).free < MIN_NO_CLEANUP_SPACE: + print(f"{BOLD[1]}WARNING!{BOLD[0]} There may be insufficient free space in {tmpdir} to run the functional test suite with --nocleanup. " + f"A minimum of {MIN_NO_CLEANUP_SPACE // (1024 * 1024 * 1024)} GB of free space is required.") + passon_args.append("--nocleanup") + check_script_list(src_dir=config["environment"]["SRCDIR"], fail_on_warn=args.ci) check_script_prefixes() @@ -554,6 +570,11 @@ def run_tests(*, test_list, src_dir, build_dir, tmpdir, jobs=1, enable_coverage= if os.path.isdir(cache_dir): print("%sWARNING!%s There is a cache directory here: %s. If tests fail unexpectedly, try deleting the cache directory." % (BOLD[1], BOLD[0], cache_dir)) + # Warn if there is not enough space on the testing dir + min_space = MIN_FREE_SPACE + (jobs - 1) * ADDITIONAL_SPACE_PER_JOB + if shutil.disk_usage(tmpdir).free < min_space: + print(f"{BOLD[1]}WARNING!{BOLD[0]} There may be insufficient free space in {tmpdir} to run the Bitcoin functional test suite. " + f"Running the test suite with fewer than {min_space // (1024 * 1024)} MB of free space might cause tests to fail.") tests_dir = src_dir + '/test/functional/' # This allows `test_runner.py` to work from an out-of-source build directory using a symlink, @@ -623,6 +644,11 @@ def run_tests(*, test_list, src_dir, build_dir, tmpdir, jobs=1, enable_coverage= logging.debug("Early exiting after test failure") break + if "[Errno 28] No space left on device" in stdout: + sys.exit(f"Early exiting after test failure due to insuffient free space in {tmpdir}\n" + f"Test execution data left in {tmpdir}.\n" + f"Additional storage is needed to execute testing.") + print_results(test_results, max_len_name, (int(time.time() - start_time))) if coverage: From fd6a7d3a13d89d74e161095b0e9bd3570210a40c Mon Sep 17 00:00:00 2001 From: Matthew Zipkin Date: Tue, 30 Apr 2024 14:03:41 -0400 Subject: [PATCH 18/46] test: use sleepy wait-for-log in reindex readonly Also rename the busy wait-for-log method to prevent recurrence --- test/functional/feature_init.py | 2 +- test/functional/feature_reindex_readonly.py | 2 +- test/functional/test_framework/test_node.py | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/test/functional/feature_init.py b/test/functional/feature_init.py index 268009b0f4..22ae0c307b 100755 --- a/test/functional/feature_init.py +++ b/test/functional/feature_init.py @@ -85,7 +85,7 @@ def check_clean_start(): for terminate_line in lines_to_terminate_after: self.log.info(f"Starting node and will exit after line {terminate_line}") - with node.wait_for_debug_log([terminate_line]): + with node.busy_wait_for_debug_log([terminate_line]): node.start(extra_args=['-txindex=1', '-blockfilterindex=1', '-coinstatsindex=1']) self.log.debug("Terminating node after terminate line was found") sigterm_node() diff --git a/test/functional/feature_reindex_readonly.py b/test/functional/feature_reindex_readonly.py index 25cff87a3b..52c0bb26a6 100755 --- a/test/functional/feature_reindex_readonly.py +++ b/test/functional/feature_reindex_readonly.py @@ -75,7 +75,7 @@ def reindex_readonly(self): if undo_immutable: self.log.debug("Attempt to restart and reindex the node with the unwritable block file") - with self.nodes[0].wait_for_debug_log([b"Reindexing finished"]): + with self.nodes[0].assert_debug_log(["Reindexing finished"], timeout=60): self.start_node(0, extra_args=['-reindex', '-fastprune']) assert block_count == self.nodes[0].getblockcount() undo_immutable() diff --git a/test/functional/test_framework/test_node.py b/test/functional/test_framework/test_node.py index 67e0be5280..d228bd8991 100755 --- a/test/functional/test_framework/test_node.py +++ b/test/functional/test_framework/test_node.py @@ -490,7 +490,7 @@ def assert_debug_log(self, expected_msgs, unexpected_msgs=None, timeout=2): self._raise_assertion_error('Expected messages "{}" does not partially match log:\n\n{}\n\n'.format(str(expected_msgs), print_log)) @contextlib.contextmanager - def wait_for_debug_log(self, expected_msgs, timeout=60): + def busy_wait_for_debug_log(self, expected_msgs, timeout=60): """ Block until we see a particular debug log message fragment or until we exceed the timeout. Return: From dddd40ba8267dea11a3eb03d5cf8b51dbb99be5d Mon Sep 17 00:00:00 2001 From: MarcoFalke <*~=`'#}+{/-|&$^_@721217.xyz> Date: Mon, 26 Feb 2024 13:36:30 +0100 Subject: [PATCH 19/46] scripted-diff: Add IWYU pragma keep to bitcoin-config.h includes -BEGIN VERIFY SCRIPT- perl -0777 -pi -e 's/#if defined\(HAVE_CONFIG_H\)\n#include .*\n#endif.*\n/#include \/\/ IWYU pragma: keep\n/g' $( git grep -l '#include ' ) -END VERIFY SCRIPT- --- src/addrdb.cpp | 4 +--- src/addrman.cpp | 4 +--- src/bench/wallet_create.cpp | 4 +--- src/bench/wallet_ismine.cpp | 4 +--- src/bench/wallet_loading.cpp | 4 +--- src/bitcoin-cli.cpp | 4 +--- src/bitcoin-tx.cpp | 4 +--- src/bitcoin-util.cpp | 4 +--- src/bitcoin-wallet.cpp | 4 +--- src/bitcoind.cpp | 4 +--- src/clientversion.cpp | 4 +--- src/clientversion.h | 4 +--- src/common/run_command.cpp | 4 +--- src/common/settings.cpp | 4 +--- src/common/system.cpp | 4 +--- src/common/system.h | 4 +--- src/crypto/sha256.cpp | 4 +--- src/httpserver.cpp | 4 +--- src/init.cpp | 4 +--- src/init/common.cpp | 4 +--- src/mapport.cpp | 4 +--- src/net.cpp | 4 +--- src/netbase.cpp | 4 +--- src/node/interfaces.cpp | 4 +--- src/node/kernel_notifications.cpp | 4 +--- src/qt/bitcoin.cpp | 4 +--- src/qt/bitcoin.h | 4 +--- src/qt/bitcoingui.cpp | 4 +--- src/qt/bitcoingui.h | 4 +--- src/qt/clientmodel.cpp | 4 +--- src/qt/createwalletdialog.cpp | 4 +--- src/qt/guiutil.cpp | 4 +--- src/qt/intro.cpp | 4 +--- src/qt/modaloverlay.cpp | 4 +--- src/qt/notificator.cpp | 4 +--- src/qt/notificator.h | 4 +--- src/qt/optionsdialog.cpp | 4 +--- src/qt/optionsmodel.cpp | 4 +--- src/qt/qrimagewidget.cpp | 4 +--- src/qt/receiverequestdialog.cpp | 4 +--- src/qt/rpcconsole.cpp | 4 +--- src/qt/rpcconsole.h | 4 +--- src/qt/sendcoinsdialog.cpp | 4 +--- src/qt/splashscreen.cpp | 4 +--- src/qt/test/optiontests.cpp | 4 +--- src/qt/test/test_main.cpp | 4 +--- src/qt/utilitydialog.cpp | 4 +--- src/random.cpp | 4 +--- src/randomenv.cpp | 4 +--- src/rest.cpp | 4 +--- src/rpc/external_signer.cpp | 4 +--- src/rpc/mining.cpp | 4 +--- src/rpc/node.cpp | 4 +--- src/rpc/register.h | 4 +--- src/rpc/server.cpp | 4 +--- src/rpc/util.cpp | 4 +--- src/test/system_tests.cpp | 4 +--- src/test/util/setup_common.cpp | 4 +--- src/test/util_threadnames_tests.cpp | 4 +--- src/util/check.cpp | 4 +--- src/util/fs_helpers.cpp | 4 +--- src/util/syserror.cpp | 4 +--- src/util/threadnames.cpp | 4 +--- src/util/tokenpipe.cpp | 4 +--- src/util/trace.h | 4 +--- src/validation.cpp | 4 +--- src/wallet/init.cpp | 4 +--- src/wallet/rpc/addresses.cpp | 4 +--- src/wallet/rpc/backup.cpp | 4 +--- src/wallet/rpc/wallet.cpp | 4 +--- src/wallet/sqlite.cpp | 4 +--- src/wallet/test/db_tests.cpp | 4 +--- src/wallet/test/util.h | 4 +--- src/wallet/wallet.cpp | 4 +--- src/wallet/walletdb.cpp | 4 +--- src/wallet/wallettool.cpp | 4 +--- src/warnings.cpp | 4 +--- 77 files changed, 77 insertions(+), 231 deletions(-) diff --git a/src/addrdb.cpp b/src/addrdb.cpp index 14dc314c36..4d34c24ba9 100644 --- a/src/addrdb.cpp +++ b/src/addrdb.cpp @@ -3,9 +3,7 @@ // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. -#if defined(HAVE_CONFIG_H) -#include -#endif +#include // IWYU pragma: keep #include diff --git a/src/addrman.cpp b/src/addrman.cpp index ef8ed92bb5..eb9c372550 100644 --- a/src/addrman.cpp +++ b/src/addrman.cpp @@ -3,9 +3,7 @@ // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. -#if defined(HAVE_CONFIG_H) -#include -#endif +#include // IWYU pragma: keep #include #include diff --git a/src/bench/wallet_create.cpp b/src/bench/wallet_create.cpp index 32f55f51e1..85280e5835 100644 --- a/src/bench/wallet_create.cpp +++ b/src/bench/wallet_create.cpp @@ -2,9 +2,7 @@ // Distributed under the MIT software license, see the accompanying // file COPYING or https://www.opensource.org/licenses/mit-license.php. -#if defined(HAVE_CONFIG_H) -#include -#endif +#include // IWYU pragma: keep #include #include diff --git a/src/bench/wallet_ismine.cpp b/src/bench/wallet_ismine.cpp index 3f922e18a5..753404b526 100644 --- a/src/bench/wallet_ismine.cpp +++ b/src/bench/wallet_ismine.cpp @@ -2,9 +2,7 @@ // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. -#if defined(HAVE_CONFIG_H) -#include -#endif // HAVE_CONFIG_H +#include // IWYU pragma: keep #include #include #include diff --git a/src/bench/wallet_loading.cpp b/src/bench/wallet_loading.cpp index 6305126c7d..02582deda4 100644 --- a/src/bench/wallet_loading.cpp +++ b/src/bench/wallet_loading.cpp @@ -2,9 +2,7 @@ // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. -#if defined(HAVE_CONFIG_H) -#include -#endif +#include // IWYU pragma: keep #include #include diff --git a/src/bitcoin-cli.cpp b/src/bitcoin-cli.cpp index 8901d10ef6..c7ba2204c3 100644 --- a/src/bitcoin-cli.cpp +++ b/src/bitcoin-cli.cpp @@ -3,9 +3,7 @@ // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. -#if defined(HAVE_CONFIG_H) -#include -#endif +#include // IWYU pragma: keep #include #include diff --git a/src/bitcoin-tx.cpp b/src/bitcoin-tx.cpp index 320624c419..1c5b0c074c 100644 --- a/src/bitcoin-tx.cpp +++ b/src/bitcoin-tx.cpp @@ -2,9 +2,7 @@ // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. -#if defined(HAVE_CONFIG_H) -#include -#endif +#include // IWYU pragma: keep #include #include diff --git a/src/bitcoin-util.cpp b/src/bitcoin-util.cpp index 96387e8c71..c8f5bc5026 100644 --- a/src/bitcoin-util.cpp +++ b/src/bitcoin-util.cpp @@ -2,9 +2,7 @@ // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. -#if defined(HAVE_CONFIG_H) -#include -#endif +#include // IWYU pragma: keep #include #include diff --git a/src/bitcoin-wallet.cpp b/src/bitcoin-wallet.cpp index fe90958a5f..bee052bc46 100644 --- a/src/bitcoin-wallet.cpp +++ b/src/bitcoin-wallet.cpp @@ -2,9 +2,7 @@ // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. -#if defined(HAVE_CONFIG_H) -#include -#endif +#include // IWYU pragma: keep #include #include diff --git a/src/bitcoind.cpp b/src/bitcoind.cpp index 54796c5abb..7685bdea79 100644 --- a/src/bitcoind.cpp +++ b/src/bitcoind.cpp @@ -3,9 +3,7 @@ // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. -#if defined(HAVE_CONFIG_H) -#include -#endif +#include // IWYU pragma: keep #include #include diff --git a/src/clientversion.cpp b/src/clientversion.cpp index bf5579ee69..3a5e060a39 100644 --- a/src/clientversion.cpp +++ b/src/clientversion.cpp @@ -2,9 +2,7 @@ // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. -#if defined(HAVE_CONFIG_H) -#include -#endif +#include // IWYU pragma: keep #include #include diff --git a/src/clientversion.h b/src/clientversion.h index 9da0cd0b39..73aaf868e4 100644 --- a/src/clientversion.h +++ b/src/clientversion.h @@ -7,9 +7,7 @@ #include -#if defined(HAVE_CONFIG_H) -#include -#endif //HAVE_CONFIG_H +#include // IWYU pragma: keep // Check that required client information is defined #if !defined(CLIENT_VERSION_MAJOR) || !defined(CLIENT_VERSION_MINOR) || !defined(CLIENT_VERSION_BUILD) || !defined(CLIENT_VERSION_IS_RELEASE) || !defined(COPYRIGHT_YEAR) diff --git a/src/common/run_command.cpp b/src/common/run_command.cpp index 347b486095..67608b985f 100644 --- a/src/common/run_command.cpp +++ b/src/common/run_command.cpp @@ -2,9 +2,7 @@ // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. -#if defined(HAVE_CONFIG_H) -#include -#endif +#include // IWYU pragma: keep #include diff --git a/src/common/settings.cpp b/src/common/settings.cpp index db1001111a..c1520dacd2 100644 --- a/src/common/settings.cpp +++ b/src/common/settings.cpp @@ -4,9 +4,7 @@ #include -#if defined(HAVE_CONFIG_H) -#include -#endif +#include // IWYU pragma: keep #include #include diff --git a/src/common/system.cpp b/src/common/system.cpp index 1fa53a5f34..ddd0feda3b 100644 --- a/src/common/system.cpp +++ b/src/common/system.cpp @@ -3,9 +3,7 @@ // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. -#if defined(HAVE_CONFIG_H) -#include -#endif +#include // IWYU pragma: keep #include diff --git a/src/common/system.h b/src/common/system.h index 83280d46ee..d9115d3b33 100644 --- a/src/common/system.h +++ b/src/common/system.h @@ -6,9 +6,7 @@ #ifndef BITCOIN_COMMON_SYSTEM_H #define BITCOIN_COMMON_SYSTEM_H -#if defined(HAVE_CONFIG_H) -#include -#endif +#include // IWYU pragma: keep #include #include diff --git a/src/crypto/sha256.cpp b/src/crypto/sha256.cpp index 301f22a248..c883bd2f03 100644 --- a/src/crypto/sha256.cpp +++ b/src/crypto/sha256.cpp @@ -2,9 +2,7 @@ // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. -#if defined(HAVE_CONFIG_H) -#include -#endif +#include // IWYU pragma: keep #include #include diff --git a/src/httpserver.cpp b/src/httpserver.cpp index 71134d442f..b1d4dc9234 100644 --- a/src/httpserver.cpp +++ b/src/httpserver.cpp @@ -2,9 +2,7 @@ // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. -#if defined(HAVE_CONFIG_H) -#include -#endif +#include // IWYU pragma: keep #include diff --git a/src/init.cpp b/src/init.cpp index 4d7638cd6e..1637d8369c 100644 --- a/src/init.cpp +++ b/src/init.cpp @@ -3,9 +3,7 @@ // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. -#if defined(HAVE_CONFIG_H) -#include -#endif +#include // IWYU pragma: keep #include diff --git a/src/init/common.cpp b/src/init/common.cpp index 0800cd93d8..3a6df3e8bd 100644 --- a/src/init/common.cpp +++ b/src/init/common.cpp @@ -2,9 +2,7 @@ // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. -#if defined(HAVE_CONFIG_H) -#include -#endif +#include // IWYU pragma: keep #include #include diff --git a/src/mapport.cpp b/src/mapport.cpp index 08b365db4b..80670230c7 100644 --- a/src/mapport.cpp +++ b/src/mapport.cpp @@ -2,9 +2,7 @@ // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. -#if defined(HAVE_CONFIG_H) -#include -#endif +#include // IWYU pragma: keep #include diff --git a/src/net.cpp b/src/net.cpp index 1eda98253a..4a42ddec2c 100644 --- a/src/net.cpp +++ b/src/net.cpp @@ -3,9 +3,7 @@ // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. -#if defined(HAVE_CONFIG_H) -#include -#endif +#include // IWYU pragma: keep #include diff --git a/src/netbase.cpp b/src/netbase.cpp index f0fa298378..e231766487 100644 --- a/src/netbase.cpp +++ b/src/netbase.cpp @@ -3,9 +3,7 @@ // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. -#if defined(HAVE_CONFIG_H) -#include -#endif +#include // IWYU pragma: keep #include diff --git a/src/node/interfaces.cpp b/src/node/interfaces.cpp index 4d2d83812e..40927c990a 100644 --- a/src/node/interfaces.cpp +++ b/src/node/interfaces.cpp @@ -52,9 +52,7 @@ #include #include -#if defined(HAVE_CONFIG_H) -#include -#endif +#include // IWYU pragma: keep #include #include diff --git a/src/node/kernel_notifications.cpp b/src/node/kernel_notifications.cpp index 99f909ff75..6578b383f7 100644 --- a/src/node/kernel_notifications.cpp +++ b/src/node/kernel_notifications.cpp @@ -4,9 +4,7 @@ #include -#if defined(HAVE_CONFIG_H) -#include -#endif +#include // IWYU pragma: keep #include #include diff --git a/src/qt/bitcoin.cpp b/src/qt/bitcoin.cpp index b1a8461d02..44a858c16b 100644 --- a/src/qt/bitcoin.cpp +++ b/src/qt/bitcoin.cpp @@ -2,9 +2,7 @@ // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. -#if defined(HAVE_CONFIG_H) -#include -#endif +#include // IWYU pragma: keep #include diff --git a/src/qt/bitcoin.h b/src/qt/bitcoin.h index 9622c9d57d..1423a8bbc6 100644 --- a/src/qt/bitcoin.h +++ b/src/qt/bitcoin.h @@ -5,9 +5,7 @@ #ifndef BITCOIN_QT_BITCOIN_H #define BITCOIN_QT_BITCOIN_H -#if defined(HAVE_CONFIG_H) -#include -#endif +#include // IWYU pragma: keep #include #include diff --git a/src/qt/bitcoingui.cpp b/src/qt/bitcoingui.cpp index 5f132b817e..a43009d954 100644 --- a/src/qt/bitcoingui.cpp +++ b/src/qt/bitcoingui.cpp @@ -2,9 +2,7 @@ // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. -#if defined(HAVE_CONFIG_H) -#include -#endif +#include // IWYU pragma: keep #include diff --git a/src/qt/bitcoingui.h b/src/qt/bitcoingui.h index ba91eeb1ff..73adbda5a5 100644 --- a/src/qt/bitcoingui.h +++ b/src/qt/bitcoingui.h @@ -5,9 +5,7 @@ #ifndef BITCOIN_QT_BITCOINGUI_H #define BITCOIN_QT_BITCOINGUI_H -#if defined(HAVE_CONFIG_H) -#include -#endif +#include // IWYU pragma: keep #include #include diff --git a/src/qt/clientmodel.cpp b/src/qt/clientmodel.cpp index 05172cfbd2..2f3bad37e6 100644 --- a/src/qt/clientmodel.cpp +++ b/src/qt/clientmodel.cpp @@ -2,9 +2,7 @@ // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. -#if defined(HAVE_CONFIG_H) -#include -#endif +#include // IWYU pragma: keep #include diff --git a/src/qt/createwalletdialog.cpp b/src/qt/createwalletdialog.cpp index 6557280d89..3e8d1461e5 100644 --- a/src/qt/createwalletdialog.cpp +++ b/src/qt/createwalletdialog.cpp @@ -2,9 +2,7 @@ // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. -#if defined(HAVE_CONFIG_H) -#include -#endif +#include // IWYU pragma: keep #include #include diff --git a/src/qt/guiutil.cpp b/src/qt/guiutil.cpp index e094b686d4..ee841ce626 100644 --- a/src/qt/guiutil.cpp +++ b/src/qt/guiutil.cpp @@ -2,9 +2,7 @@ // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. -#if defined(HAVE_CONFIG_H) -#include -#endif +#include // IWYU pragma: keep #include diff --git a/src/qt/intro.cpp b/src/qt/intro.cpp index 5371dbaa30..26b42deb64 100644 --- a/src/qt/intro.cpp +++ b/src/qt/intro.cpp @@ -2,9 +2,7 @@ // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. -#if defined(HAVE_CONFIG_H) -#include -#endif +#include // IWYU pragma: keep #include #include diff --git a/src/qt/modaloverlay.cpp b/src/qt/modaloverlay.cpp index 667db06574..7bc6ccdc49 100644 --- a/src/qt/modaloverlay.cpp +++ b/src/qt/modaloverlay.cpp @@ -2,9 +2,7 @@ // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. -#if defined(HAVE_CONFIG_H) -#include -#endif +#include // IWYU pragma: keep #include #include diff --git a/src/qt/notificator.cpp b/src/qt/notificator.cpp index 551c0ffd13..85bdeee49a 100644 --- a/src/qt/notificator.cpp +++ b/src/qt/notificator.cpp @@ -2,9 +2,7 @@ // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. -#if defined(HAVE_CONFIG_H) -#include -#endif +#include // IWYU pragma: keep #include diff --git a/src/qt/notificator.h b/src/qt/notificator.h index 1fd8181a22..8808716aa4 100644 --- a/src/qt/notificator.h +++ b/src/qt/notificator.h @@ -5,9 +5,7 @@ #ifndef BITCOIN_QT_NOTIFICATOR_H #define BITCOIN_QT_NOTIFICATOR_H -#if defined(HAVE_CONFIG_H) -#include -#endif +#include // IWYU pragma: keep #include #include diff --git a/src/qt/optionsdialog.cpp b/src/qt/optionsdialog.cpp index dd654a7abe..15103baf59 100644 --- a/src/qt/optionsdialog.cpp +++ b/src/qt/optionsdialog.cpp @@ -2,9 +2,7 @@ // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. -#if defined(HAVE_CONFIG_H) -#include -#endif +#include // IWYU pragma: keep #include #include diff --git a/src/qt/optionsmodel.cpp b/src/qt/optionsmodel.cpp index d0f7c64357..0c21c6748d 100644 --- a/src/qt/optionsmodel.cpp +++ b/src/qt/optionsmodel.cpp @@ -2,9 +2,7 @@ // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. -#if defined(HAVE_CONFIG_H) -#include -#endif +#include // IWYU pragma: keep #include diff --git a/src/qt/qrimagewidget.cpp b/src/qt/qrimagewidget.cpp index 00f928b355..f6e712a047 100644 --- a/src/qt/qrimagewidget.cpp +++ b/src/qt/qrimagewidget.cpp @@ -15,9 +15,7 @@ #include #include -#if defined(HAVE_CONFIG_H) -#include /* for USE_QRCODE */ -#endif +#include // IWYU pragma: keep #ifdef USE_QRCODE #include diff --git a/src/qt/receiverequestdialog.cpp b/src/qt/receiverequestdialog.cpp index 3453857f98..b4322ddc0f 100644 --- a/src/qt/receiverequestdialog.cpp +++ b/src/qt/receiverequestdialog.cpp @@ -14,9 +14,7 @@ #include #include -#if defined(HAVE_CONFIG_H) -#include /* for USE_QRCODE */ -#endif +#include // IWYU pragma: keep ReceiveRequestDialog::ReceiveRequestDialog(QWidget* parent) : QDialog(parent, GUIUtil::dialog_flags), diff --git a/src/qt/rpcconsole.cpp b/src/qt/rpcconsole.cpp index bafef62945..702ca44395 100644 --- a/src/qt/rpcconsole.cpp +++ b/src/qt/rpcconsole.cpp @@ -2,9 +2,7 @@ // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. -#if defined(HAVE_CONFIG_H) -#include -#endif +#include // IWYU pragma: keep #include #include diff --git a/src/qt/rpcconsole.h b/src/qt/rpcconsole.h index 358f68c3c8..d6a5035c33 100644 --- a/src/qt/rpcconsole.h +++ b/src/qt/rpcconsole.h @@ -5,9 +5,7 @@ #ifndef BITCOIN_QT_RPCCONSOLE_H #define BITCOIN_QT_RPCCONSOLE_H -#if defined(HAVE_CONFIG_H) -#include -#endif +#include // IWYU pragma: keep #include #include diff --git a/src/qt/sendcoinsdialog.cpp b/src/qt/sendcoinsdialog.cpp index 89bd35eb1b..0d8c0f7a63 100644 --- a/src/qt/sendcoinsdialog.cpp +++ b/src/qt/sendcoinsdialog.cpp @@ -2,9 +2,7 @@ // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. -#if defined(HAVE_CONFIG_H) -#include -#endif +#include // IWYU pragma: keep #include #include diff --git a/src/qt/splashscreen.cpp b/src/qt/splashscreen.cpp index 8872f8be32..ffd6689910 100644 --- a/src/qt/splashscreen.cpp +++ b/src/qt/splashscreen.cpp @@ -2,9 +2,7 @@ // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. -#if defined(HAVE_CONFIG_H) -#include -#endif +#include // IWYU pragma: keep #include diff --git a/src/qt/test/optiontests.cpp b/src/qt/test/optiontests.cpp index 5f9f2cb449..0f82f65f3e 100644 --- a/src/qt/test/optiontests.cpp +++ b/src/qt/test/optiontests.cpp @@ -2,9 +2,7 @@ // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. -#if defined(HAVE_CONFIG_H) -#include -#endif +#include // IWYU pragma: keep #include #include diff --git a/src/qt/test/test_main.cpp b/src/qt/test/test_main.cpp index c5405cca98..f310d0a02b 100644 --- a/src/qt/test/test_main.cpp +++ b/src/qt/test/test_main.cpp @@ -2,9 +2,7 @@ // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. -#if defined(HAVE_CONFIG_H) -#include -#endif +#include // IWYU pragma: keep #include #include diff --git a/src/qt/utilitydialog.cpp b/src/qt/utilitydialog.cpp index 22fe219def..b55b4cbe64 100644 --- a/src/qt/utilitydialog.cpp +++ b/src/qt/utilitydialog.cpp @@ -2,9 +2,7 @@ // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. -#if defined(HAVE_CONFIG_H) -#include -#endif +#include // IWYU pragma: keep #include diff --git a/src/random.cpp b/src/random.cpp index 4fc9099704..239d5bc6fe 100644 --- a/src/random.cpp +++ b/src/random.cpp @@ -3,9 +3,7 @@ // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. -#if defined(HAVE_CONFIG_H) -#include -#endif +#include // IWYU pragma: keep #include diff --git a/src/randomenv.cpp b/src/randomenv.cpp index 123b5cc06c..aeec959c28 100644 --- a/src/randomenv.cpp +++ b/src/randomenv.cpp @@ -3,9 +3,7 @@ // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. -#if defined(HAVE_CONFIG_H) -#include -#endif +#include // IWYU pragma: keep #include diff --git a/src/rest.cpp b/src/rest.cpp index 89c033b8a3..9fc5d4af04 100644 --- a/src/rest.cpp +++ b/src/rest.cpp @@ -3,9 +3,7 @@ // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. -#if defined(HAVE_CONFIG_H) -#include -#endif +#include // IWYU pragma: keep #include diff --git a/src/rpc/external_signer.cpp b/src/rpc/external_signer.cpp index 8d06ae4258..27c7394909 100644 --- a/src/rpc/external_signer.cpp +++ b/src/rpc/external_signer.cpp @@ -2,9 +2,7 @@ // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. -#if defined(HAVE_CONFIG_H) -#include -#endif +#include // IWYU pragma: keep #include #include diff --git a/src/rpc/mining.cpp b/src/rpc/mining.cpp index 454c262803..b908265c4b 100644 --- a/src/rpc/mining.cpp +++ b/src/rpc/mining.cpp @@ -3,9 +3,7 @@ // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. -#if defined(HAVE_CONFIG_H) -#include -#endif +#include // IWYU pragma: keep #include #include diff --git a/src/rpc/node.cpp b/src/rpc/node.cpp index ffc2ee5ab0..447be2cf64 100644 --- a/src/rpc/node.cpp +++ b/src/rpc/node.cpp @@ -3,9 +3,7 @@ // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. -#if defined(HAVE_CONFIG_H) -#include -#endif +#include // IWYU pragma: keep #include #include diff --git a/src/rpc/register.h b/src/rpc/register.h index fd23dde75b..65fd29ff08 100644 --- a/src/rpc/register.h +++ b/src/rpc/register.h @@ -5,9 +5,7 @@ #ifndef BITCOIN_RPC_REGISTER_H #define BITCOIN_RPC_REGISTER_H -#if defined(HAVE_CONFIG_H) -#include -#endif +#include // IWYU pragma: keep /** These are in one header file to avoid creating tons of single-function * headers for everything under src/rpc/ */ diff --git a/src/rpc/server.cpp b/src/rpc/server.cpp index e7d1e3db4e..a800451f4a 100644 --- a/src/rpc/server.cpp +++ b/src/rpc/server.cpp @@ -3,9 +3,7 @@ // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. -#if defined(HAVE_CONFIG_H) -#include -#endif +#include // IWYU pragma: keep #include diff --git a/src/rpc/util.cpp b/src/rpc/util.cpp index f683878054..a81300e3bf 100644 --- a/src/rpc/util.cpp +++ b/src/rpc/util.cpp @@ -2,9 +2,7 @@ // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. -#if defined(HAVE_CONFIG_H) -#include -#endif +#include // IWYU pragma: keep #include #include diff --git a/src/test/system_tests.cpp b/src/test/system_tests.cpp index 2de147deea..baa759e42c 100644 --- a/src/test/system_tests.cpp +++ b/src/test/system_tests.cpp @@ -3,9 +3,7 @@ // file COPYING or http://www.opensource.org/licenses/mit-license.php. // -#if defined(HAVE_CONFIG_H) -#include -#endif +#include // IWYU pragma: keep #include #include #include diff --git a/src/test/util/setup_common.cpp b/src/test/util/setup_common.cpp index 38350b33cc..0fb5e4eb45 100644 --- a/src/test/util/setup_common.cpp +++ b/src/test/util/setup_common.cpp @@ -2,9 +2,7 @@ // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. -#if defined(HAVE_CONFIG_H) -#include -#endif +#include // IWYU pragma: keep #include diff --git a/src/test/util_threadnames_tests.cpp b/src/test/util_threadnames_tests.cpp index 45d3a58fd3..df5b1a4461 100644 --- a/src/test/util_threadnames_tests.cpp +++ b/src/test/util_threadnames_tests.cpp @@ -11,9 +11,7 @@ #include #include -#if defined(HAVE_CONFIG_H) -#include -#endif +#include // IWYU pragma: keep #include diff --git a/src/util/check.cpp b/src/util/check.cpp index c4d4b0cc28..eb3885832b 100644 --- a/src/util/check.cpp +++ b/src/util/check.cpp @@ -4,9 +4,7 @@ #include -#if defined(HAVE_CONFIG_H) -#include -#endif +#include // IWYU pragma: keep #include #include diff --git a/src/util/fs_helpers.cpp b/src/util/fs_helpers.cpp index bce5602462..8952f20f79 100644 --- a/src/util/fs_helpers.cpp +++ b/src/util/fs_helpers.cpp @@ -5,9 +5,7 @@ #include -#if defined(HAVE_CONFIG_H) -#include -#endif +#include // IWYU pragma: keep #include #include diff --git a/src/util/syserror.cpp b/src/util/syserror.cpp index bac498a23d..6f3a724483 100644 --- a/src/util/syserror.cpp +++ b/src/util/syserror.cpp @@ -2,9 +2,7 @@ // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. -#if defined(HAVE_CONFIG_H) -#include -#endif +#include // IWYU pragma: keep #include #include diff --git a/src/util/threadnames.cpp b/src/util/threadnames.cpp index 91883fe4ff..ea597dd05a 100644 --- a/src/util/threadnames.cpp +++ b/src/util/threadnames.cpp @@ -2,9 +2,7 @@ // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. -#if defined(HAVE_CONFIG_H) -#include -#endif +#include // IWYU pragma: keep #include #include diff --git a/src/util/tokenpipe.cpp b/src/util/tokenpipe.cpp index 3c27d5e523..16fbb664ea 100644 --- a/src/util/tokenpipe.cpp +++ b/src/util/tokenpipe.cpp @@ -3,9 +3,7 @@ // file COPYING or http://www.opensource.org/licenses/mit-license.php. #include -#if defined(HAVE_CONFIG_H) -#include -#endif +#include // IWYU pragma: keep #ifndef WIN32 diff --git a/src/util/trace.h b/src/util/trace.h index b7c275f19b..d9ed65e3aa 100644 --- a/src/util/trace.h +++ b/src/util/trace.h @@ -5,9 +5,7 @@ #ifndef BITCOIN_UTIL_TRACE_H #define BITCOIN_UTIL_TRACE_H -#if defined(HAVE_CONFIG_H) -#include -#endif +#include // IWYU pragma: keep #ifdef ENABLE_TRACING diff --git a/src/validation.cpp b/src/validation.cpp index f57851b4f7..c2b56555a2 100644 --- a/src/validation.cpp +++ b/src/validation.cpp @@ -3,9 +3,7 @@ // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. -#if defined(HAVE_CONFIG_H) -#include -#endif +#include // IWYU pragma: keep #include diff --git a/src/wallet/init.cpp b/src/wallet/init.cpp index f151fad740..14e988ec1a 100644 --- a/src/wallet/init.cpp +++ b/src/wallet/init.cpp @@ -3,9 +3,7 @@ // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. -#if defined(HAVE_CONFIG_H) -#include -#endif +#include // IWYU pragma: keep #include #include diff --git a/src/wallet/rpc/addresses.cpp b/src/wallet/rpc/addresses.cpp index bed9ec029a..65587f0b18 100644 --- a/src/wallet/rpc/addresses.cpp +++ b/src/wallet/rpc/addresses.cpp @@ -2,9 +2,7 @@ // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. -#if defined(HAVE_CONFIG_H) -#include -#endif +#include // IWYU pragma: keep #include #include diff --git a/src/wallet/rpc/backup.cpp b/src/wallet/rpc/backup.cpp index ae2dfe5795..c05600484e 100644 --- a/src/wallet/rpc/backup.cpp +++ b/src/wallet/rpc/backup.cpp @@ -2,9 +2,7 @@ // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. -#if defined(HAVE_CONFIG_H) -#include -#endif +#include // IWYU pragma: keep #include #include diff --git a/src/wallet/rpc/wallet.cpp b/src/wallet/rpc/wallet.cpp index a684d4e191..f1cb595271 100644 --- a/src/wallet/rpc/wallet.cpp +++ b/src/wallet/rpc/wallet.cpp @@ -3,9 +3,7 @@ // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. -#if defined(HAVE_CONFIG_H) -#include -#endif +#include // IWYU pragma: keep #include #include diff --git a/src/wallet/sqlite.cpp b/src/wallet/sqlite.cpp index 34f18bf0b1..5e3a8179a2 100644 --- a/src/wallet/sqlite.cpp +++ b/src/wallet/sqlite.cpp @@ -2,9 +2,7 @@ // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. -#if defined(HAVE_CONFIG_H) -#include -#endif +#include // IWYU pragma: keep #include diff --git a/src/wallet/test/db_tests.cpp b/src/wallet/test/db_tests.cpp index f783424df8..438dfceb7f 100644 --- a/src/wallet/test/db_tests.cpp +++ b/src/wallet/test/db_tests.cpp @@ -2,9 +2,7 @@ // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. -#if defined(HAVE_CONFIG_H) -#include -#endif +#include // IWYU pragma: keep #include diff --git a/src/wallet/test/util.h b/src/wallet/test/util.h index 9f2974ece6..a3e6ede81e 100644 --- a/src/wallet/test/util.h +++ b/src/wallet/test/util.h @@ -5,9 +5,7 @@ #ifndef BITCOIN_WALLET_TEST_UTIL_H #define BITCOIN_WALLET_TEST_UTIL_H -#if defined(HAVE_CONFIG_H) -#include -#endif +#include // IWYU pragma: keep #include #include diff --git a/src/wallet/wallet.cpp b/src/wallet/wallet.cpp index 8f4171eb15..45f69f52d1 100644 --- a/src/wallet/wallet.cpp +++ b/src/wallet/wallet.cpp @@ -5,9 +5,7 @@ #include -#if defined(HAVE_CONFIG_H) -#include -#endif +#include // IWYU pragma: keep #include #include #include diff --git a/src/wallet/walletdb.cpp b/src/wallet/walletdb.cpp index b1ce7ee4e7..3ba43cdb73 100644 --- a/src/wallet/walletdb.cpp +++ b/src/wallet/walletdb.cpp @@ -3,9 +3,7 @@ // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. -#if defined(HAVE_CONFIG_H) -#include -#endif +#include // IWYU pragma: keep #include diff --git a/src/wallet/wallettool.cpp b/src/wallet/wallettool.cpp index cda344ab19..7a1930fd31 100644 --- a/src/wallet/wallettool.cpp +++ b/src/wallet/wallettool.cpp @@ -2,9 +2,7 @@ // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. -#if defined(HAVE_CONFIG_H) -#include -#endif +#include // IWYU pragma: keep #include diff --git a/src/warnings.cpp b/src/warnings.cpp index d55eecc48d..da41b02b27 100644 --- a/src/warnings.cpp +++ b/src/warnings.cpp @@ -3,9 +3,7 @@ // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. -#if defined(HAVE_CONFIG_H) -#include -#endif +#include // IWYU pragma: keep #include From fa09451f8e6799682d7e7c863f25334fd1c7dce3 Mon Sep 17 00:00:00 2001 From: MarcoFalke <*~=`'#}+{/-|&$^_@721217.xyz> Date: Mon, 26 Feb 2024 14:25:51 +0100 Subject: [PATCH 20/46] Add lint check for bitcoin-config.h include IWYU pragma Also, remove the no longer needed, remaining definitions and checks of HAVE_CONFIG_H. --- build-aux/m4/bitcoin_qt.m4 | 2 +- build_msvc/bitcoin-qt/bitcoin-qt.vcxproj | 4 ++-- build_msvc/common.init.vcxproj.in | 2 +- test/lint/test_runner/src/main.rs | 12 ++++++++++-- 4 files changed, 14 insertions(+), 6 deletions(-) diff --git a/build-aux/m4/bitcoin_qt.m4 b/build-aux/m4/bitcoin_qt.m4 index a716cd9a27..337e2208a9 100644 --- a/build-aux/m4/bitcoin_qt.m4 +++ b/build-aux/m4/bitcoin_qt.m4 @@ -227,7 +227,7 @@ AC_DEFUN([BITCOIN_QT_CONFIGURE],[ BITCOIN_QT_PATH_PROGS([LUPDATE], [lupdate-qt5 lupdate5 lupdate],$qt_bin_path, yes) BITCOIN_QT_PATH_PROGS([LCONVERT], [lconvert-qt5 lconvert5 lconvert], $qt_bin_path, yes) - MOC_DEFS='-DHAVE_CONFIG_H -I$(srcdir)' + MOC_DEFS='-I$(srcdir)' case $host in *darwin*) BITCOIN_QT_CHECK([ diff --git a/build_msvc/bitcoin-qt/bitcoin-qt.vcxproj b/build_msvc/bitcoin-qt/bitcoin-qt.vcxproj index fe01da28c8..ff98d37cf8 100644 --- a/build_msvc/bitcoin-qt/bitcoin-qt.vcxproj +++ b/build_msvc/bitcoin-qt/bitcoin-qt.vcxproj @@ -62,7 +62,7 @@ ..\..\src; - HAVE_CONFIG_H;_UNICODE;UNICODE;%(PreprocessorDefinitions) + _UNICODE;UNICODE;%(PreprocessorDefinitions) @@ -75,7 +75,7 @@ ..\..\src; - HAVE_CONFIG_H;_UNICODE;UNICODE;%(PreprocessorDefinitions) + _UNICODE;UNICODE;%(PreprocessorDefinitions) diff --git a/build_msvc/common.init.vcxproj.in b/build_msvc/common.init.vcxproj.in index 71fceb6c66..6468abcd06 100644 --- a/build_msvc/common.init.vcxproj.in +++ b/build_msvc/common.init.vcxproj.in @@ -90,7 +90,7 @@ /utf-8 /Zc:preprocessor /Zc:__cplusplus /std:c++20 %(AdditionalOptions) 4018;4244;4267;4715;4805 true - _SILENCE_CXX17_CODECVT_HEADER_DEPRECATION_WARNING;SECP256K1_STATIC;ZMQ_STATIC;NOMINMAX;WIN32;HAVE_CONFIG_H;_CRT_SECURE_NO_WARNINGS;_CONSOLE;_WIN32_WINNT=0x0601;_WIN32_IE=0x0501;WIN32_LEAN_AND_MEAN;PROVIDE_FUZZ_MAIN_FUNCTION;%(PreprocessorDefinitions) + _SILENCE_CXX17_CODECVT_HEADER_DEPRECATION_WARNING;SECP256K1_STATIC;ZMQ_STATIC;NOMINMAX;WIN32;_CRT_SECURE_NO_WARNINGS;_CONSOLE;_WIN32_WINNT=0x0601;_WIN32_IE=0x0501;WIN32_LEAN_AND_MEAN;PROVIDE_FUZZ_MAIN_FUNCTION;%(PreprocessorDefinitions) ..\..\src;..\..\src\minisketch\include;..\..\src\univalue\include;..\..\src\secp256k1\include;..\..\src\leveldb\include;..\..\src\leveldb\helpers\memenv;%(AdditionalIncludeDirectories) diff --git a/test/lint/test_runner/src/main.rs b/test/lint/test_runner/src/main.rs index e22e047e4b..9795f9ca34 100644 --- a/test/lint/test_runner/src/main.rs +++ b/test/lint/test_runner/src/main.rs @@ -178,7 +178,6 @@ Please add any false positives, such as subtrees, or externally sourced files to fn lint_includes_build_config() -> LintResult { let config_path = "./src/config/bitcoin-config.h.in"; - let include_directive = "#include "; if !Path::new(config_path).is_file() { assert!(Command::new("./autogen.sh") .status() @@ -235,7 +234,11 @@ fn lint_includes_build_config() -> LintResult { } else { "--files-with-matches" }, - include_directive, + if mode { + "^#include // IWYU pragma: keep$" + } else { + "#include " // Catch redundant includes with and without the IWYU pragma + }, "--", ]) .args(defines_files.lines()) @@ -256,6 +259,11 @@ even though bitcoin-config.h indicates that a faster feature is available and sh If you are unsure which symbol is used, you can find it with this command: git grep --perl-regexp '{}' -- file_name + +Make sure to include it with the IWYU pragma. Otherwise, IWYU may falsely instruct to remove the +include again. + +#include // IWYU pragma: keep "#, defines_regex )); From 42fb5311b19582361409d65c6fddeadbee14bb97 Mon Sep 17 00:00:00 2001 From: stickies-v Date: Wed, 10 Apr 2024 12:16:21 +0200 Subject: [PATCH 21/46] rpc: return warnings as an array instead of just a single one The RPC documentation for `getblockchaininfo`, `getmininginfo` and `getnetworkinfo` states that "warnings" returns "any network and blockchain warnings". In practice, only a single warning is returned. Fix that by returning all warnings as an array. As a side benefit, cleans up the GetWarnings() logic. --- doc/release-notes-29845.md | 8 +++++++ src/node/interfaces.cpp | 3 ++- src/rpc/blockchain.cpp | 12 +++++++--- src/rpc/mining.cpp | 12 +++++++--- src/rpc/net.cpp | 12 +++++++--- src/rpc/util.cpp | 17 +++++++++++++ src/rpc/util.h | 2 ++ src/warnings.cpp | 24 +++++++------------ src/warnings.h | 10 +++----- .../functional/feature_versionbits_warning.py | 8 +++---- 10 files changed, 71 insertions(+), 37 deletions(-) create mode 100644 doc/release-notes-29845.md diff --git a/doc/release-notes-29845.md b/doc/release-notes-29845.md new file mode 100644 index 0000000000..4994d0a34d --- /dev/null +++ b/doc/release-notes-29845.md @@ -0,0 +1,8 @@ +RPC +--- + +- the `warnings` field in `getblockchaininfo`, `getmininginfo` and + `getnetworkinfo` now returns all the active node warnings as an array + of strings, instead of just a single warning. The current behaviour + can temporarily be restored by running bitcoind with configuration + option `-deprecatedrpc=warnings`. \ No newline at end of file diff --git a/src/node/interfaces.cpp b/src/node/interfaces.cpp index 4d2d83812e..bb13e53738 100644 --- a/src/node/interfaces.cpp +++ b/src/node/interfaces.cpp @@ -47,6 +47,7 @@ #include #include #include +#include #include #include #include @@ -91,7 +92,7 @@ class NodeImpl : public Node explicit NodeImpl(NodeContext& context) { setContext(&context); } void initLogging() override { InitLogging(args()); } void initParameterInteraction() override { InitParameterInteraction(args()); } - bilingual_str getWarnings() override { return GetWarnings(true); } + bilingual_str getWarnings() override { return Join(GetWarnings(), Untranslated("
")); } int getExitStatus() override { return Assert(m_context)->exit_status.load(); } uint32_t getLogCategories() override { return LogInstance().GetCategoryMask(); } bool baseInitialize() override diff --git a/src/rpc/blockchain.cpp b/src/rpc/blockchain.cpp index eed004806a..c9997ae063 100644 --- a/src/rpc/blockchain.cpp +++ b/src/rpc/blockchain.cpp @@ -47,7 +47,6 @@ #include #include #include -#include #include @@ -1260,7 +1259,14 @@ RPCHelpMan getblockchaininfo() {RPCResult::Type::NUM, "pruneheight", /*optional=*/true, "height of the last block pruned, plus one (only present if pruning is enabled)"}, {RPCResult::Type::BOOL, "automatic_pruning", /*optional=*/true, "whether automatic pruning is enabled (only present if pruning is enabled)"}, {RPCResult::Type::NUM, "prune_target_size", /*optional=*/true, "the target size used by pruning (only present if automatic pruning is enabled)"}, - {RPCResult::Type::STR, "warnings", "any network and blockchain warnings"}, + (IsDeprecatedRPCEnabled("warnings") ? + RPCResult{RPCResult::Type::STR, "warnings", "any network and blockchain warnings (DEPRECATED)"} : + RPCResult{RPCResult::Type::ARR, "warnings", "any network and blockchain warnings (run with `-deprecatedrpc=warnings` to return the latest warning as a single string)", + { + {RPCResult::Type::STR, "", "warning"}, + } + } + ), }}, RPCExamples{ HelpExampleCli("getblockchaininfo", "") @@ -1298,7 +1304,7 @@ RPCHelpMan getblockchaininfo() } } - obj.pushKV("warnings", GetWarnings(false).original); + obj.pushKV("warnings", GetNodeWarnings(IsDeprecatedRPCEnabled("warnings"))); return obj; }, }; diff --git a/src/rpc/mining.cpp b/src/rpc/mining.cpp index 454c262803..f36665a819 100644 --- a/src/rpc/mining.cpp +++ b/src/rpc/mining.cpp @@ -39,7 +39,6 @@ #include #include #include -#include #include #include @@ -426,7 +425,14 @@ static RPCHelpMan getmininginfo() {RPCResult::Type::NUM, "networkhashps", "The network hashes per second"}, {RPCResult::Type::NUM, "pooledtx", "The size of the mempool"}, {RPCResult::Type::STR, "chain", "current network name (main, test, signet, regtest)"}, - {RPCResult::Type::STR, "warnings", "any network and blockchain warnings"}, + (IsDeprecatedRPCEnabled("warnings") ? + RPCResult{RPCResult::Type::STR, "warnings", "any network and blockchain warnings (DEPRECATED)"} : + RPCResult{RPCResult::Type::ARR, "warnings", "any network and blockchain warnings (run with `-deprecatedrpc=warnings` to return the latest warning as a single string)", + { + {RPCResult::Type::STR, "", "warning"}, + } + } + ), }}, RPCExamples{ HelpExampleCli("getmininginfo", "") @@ -448,7 +454,7 @@ static RPCHelpMan getmininginfo() obj.pushKV("networkhashps", getnetworkhashps().HandleRequest(request)); obj.pushKV("pooledtx", (uint64_t)mempool.size()); obj.pushKV("chain", chainman.GetParams().GetChainTypeString()); - obj.pushKV("warnings", GetWarnings(false).original); + obj.pushKV("warnings", GetNodeWarnings(IsDeprecatedRPCEnabled("warnings"))); return obj; }, }; diff --git a/src/rpc/net.cpp b/src/rpc/net.cpp index 739ff1a48e..04f9410b32 100644 --- a/src/rpc/net.cpp +++ b/src/rpc/net.cpp @@ -29,7 +29,6 @@ #include #include #include -#include #include @@ -657,7 +656,14 @@ static RPCHelpMan getnetworkinfo() {RPCResult::Type::NUM, "score", "relative score"}, }}, }}, - {RPCResult::Type::STR, "warnings", "any network and blockchain warnings"}, + (IsDeprecatedRPCEnabled("warnings") ? + RPCResult{RPCResult::Type::STR, "warnings", "any network and blockchain warnings (DEPRECATED)"} : + RPCResult{RPCResult::Type::ARR, "warnings", "any network and blockchain warnings (run with `-deprecatedrpc=warnings` to return the latest warning as a single string)", + { + {RPCResult::Type::STR, "", "warning"}, + } + } + ), } }, RPCExamples{ @@ -707,7 +713,7 @@ static RPCHelpMan getnetworkinfo() } } obj.pushKV("localaddresses", localAddresses); - obj.pushKV("warnings", GetWarnings(false).original); + obj.pushKV("warnings", GetNodeWarnings(IsDeprecatedRPCEnabled("warnings"))); return obj; }, }; diff --git a/src/rpc/util.cpp b/src/rpc/util.cpp index f683878054..0ac2c4e7b0 100644 --- a/src/rpc/util.cpp +++ b/src/rpc/util.cpp @@ -18,16 +18,19 @@ #include