From 4303fa500d4ff2978cb9b8870139cfd9ae098c42 Mon Sep 17 00:00:00 2001 From: Byron Hambly Date: Tue, 14 Jan 2025 15:03:48 +0200 Subject: [PATCH 01/16] test: add functional test for issue --- test/functional/test_runner.py | 1 + test/functional/wallet_elements_21million.py | 94 ++++++++++++++++++++ 2 files changed, 95 insertions(+) create mode 100755 test/functional/wallet_elements_21million.py diff --git a/test/functional/test_runner.py b/test/functional/test_runner.py index b9efe9b8d8..710e372752 100755 --- a/test/functional/test_runner.py +++ b/test/functional/test_runner.py @@ -112,6 +112,7 @@ 'rpc_getnewblockhex.py', 'wallet_elements_regression_1172.py --legacy-wallet', 'wallet_elements_regression_1259.py --legacy-wallet', + 'wallet_elements_21million.py', 'feature_trim_headers.py', # Longest test should go first, to favor running tests in parallel 'wallet_hd.py --legacy-wallet', diff --git a/test/functional/wallet_elements_21million.py b/test/functional/wallet_elements_21million.py new file mode 100755 index 0000000000..f9faafdbea --- /dev/null +++ b/test/functional/wallet_elements_21million.py @@ -0,0 +1,94 @@ +#!/usr/bin/env python3 +# Copyright (c) 2017-2020 The Bitcoin Core developers +# Distributed under the MIT software license, see the accompanying +# file COPYING or http://www.opensource.org/licenses/mit-license.php. + +from test_framework.blocktools import COINBASE_MATURITY +from test_framework.test_framework import BitcoinTestFramework +from test_framework.util import ( + assert_equal, +) + +class WalletTest(BitcoinTestFramework): + def set_test_params(self): + self.setup_clean_chain = True + self.num_nodes = 3 + self.extra_args = [['-blindedaddresses=1']] * self.num_nodes + + def setup_network(self, split=False): + self.setup_nodes() + self.connect_nodes(0, 1) + self.connect_nodes(1, 2) + self.connect_nodes(0, 2) + self.sync_all() + + def skip_test_if_missing_module(self): + self.skip_if_no_wallet() + + def run_test(self): + self.generate(self.nodes[0], COINBASE_MATURITY + 1) + + assert_equal(self.nodes[0].getbalance(), {'bitcoin': 50}) + assert_equal(self.nodes[1].getbalance(), {'bitcoin': 0}) + + self.log.info("Issue more than 21 million of a non-policy asset") + issuance = self.nodes[0].issueasset(100_000_000, 100) + asset = issuance['asset'] + self.generate(self.nodes[0], 1) + assert_equal(self.nodes[0].getbalance()[asset], 100_000_000) + + self.log.info("Reissue more than 21 million of a non-policy asset") + self.nodes[0].reissueasset(asset, 100_000_000) + self.generate(self.nodes[0], 1) + assert_equal(self.nodes[0].getbalance()[asset], 200_000_000) + + # send more than 21 million of that asset + addr = self.nodes[1].getnewaddress() + self.nodes[0].sendtoaddress(address=addr, amount=22_000_000, assetlabel=asset) + self.generate(self.nodes[0], 1) + assert_equal(self.nodes[0].getbalance()[asset], 178_000_000) + assert_equal(self.nodes[1].getbalance()[asset], 22_000_000) + + # unload/load wallet + self.nodes[1].unloadwallet("") + self.nodes[1].loadwallet("") + assert_equal(self.nodes[1].getbalance()[asset], 22_000_000) + + # send more than 45 million of that asset + addr = self.nodes[2].getnewaddress() + self.nodes[0].sendtoaddress(address=addr, amount=46_000_000, assetlabel=asset) + self.generate(self.nodes[0], 1) + assert_equal(self.nodes[0].getbalance()[asset], 132_000_000) + assert_equal(self.nodes[2].getbalance()[asset], 46_000_000) + + # unload/load wallet + self.nodes[2].unloadwallet("") + self.nodes[2].loadwallet("") + assert_equal(self.nodes[2].getbalance()[asset], 46_000_000) + + # send some policy asset to node 1 for fees + addr = self.nodes[1].getnewaddress() + self.nodes[0].sendtoaddress(address=addr, amount=1) + self.generate(self.nodes[0], 1) + assert_equal(self.nodes[1].getbalance()['bitcoin'], 1) + assert_equal(self.nodes[1].getbalance()[asset], 22_000_000) + + # send the remainders + addr = self.nodes[2].getnewaddress() + self.nodes[0].sendtoaddress(address=addr, amount=132_000_000, assetlabel=asset) + addr = self.nodes[2].getnewaddress() + self.nodes[1].sendtoaddress(address=addr, amount=22_000_000, assetlabel=asset) + self.sync_mempools() + self.generate(self.nodes[0], 1) + + assert asset not in self.nodes[0].getbalance() + assert asset not in self.nodes[1].getbalance() + assert_equal(self.nodes[2].getbalance()[asset], 200_000_000) + + # unload/load wallet + self.nodes[2].unloadwallet("") + self.nodes[2].loadwallet("") + assert_equal(self.nodes[2].getbalance()[asset], 200_000_000) + +if __name__ == '__main__': + WalletTest().main() From a3e0ce2e8c2e1614acf4fd70bc023c0b52484701 Mon Sep 17 00:00:00 2001 From: Byron Hambly Date: Tue, 14 Jan 2025 15:21:53 +0200 Subject: [PATCH 02/16] amountfromvalue: add arg to check moneyrange --- src/rpc/rawtransaction.cpp | 6 +++--- src/rpc/util.cpp | 4 ++-- src/rpc/util.h | 2 +- src/wallet/rpc/elements.cpp | 6 +++--- src/wallet/rpc/spend.cpp | 4 ++-- 5 files changed, 11 insertions(+), 11 deletions(-) diff --git a/src/rpc/rawtransaction.cpp b/src/rpc/rawtransaction.cpp index 1881bb12f7..8b0f7e5d7e 100644 --- a/src/rpc/rawtransaction.cpp +++ b/src/rpc/rawtransaction.cpp @@ -3049,7 +3049,7 @@ static RPCHelpMan rawissueasset() CAmount asset_amount = 0; const UniValue& asset_amount_uni = issuance_o["asset_amount"]; if (asset_amount_uni.isNum()) { - asset_amount = AmountFromValue(asset_amount_uni); + asset_amount = AmountFromValue(asset_amount_uni, false); if (asset_amount <= 0) { throw JSONRPCError(RPC_INVALID_PARAMETER, "Invalid parameter, asset_amount must be positive"); } @@ -3066,7 +3066,7 @@ static RPCHelpMan rawissueasset() CAmount token_amount = 0; const UniValue& token_amount_uni = issuance_o["token_amount"]; if (token_amount_uni.isNum()) { - token_amount = AmountFromValue(token_amount_uni); + token_amount = AmountFromValue(token_amount_uni, false); if (token_amount <= 0) { throw JSONRPCError(RPC_INVALID_PARAMETER, "Invalid parameter, token_amount must be positive"); } @@ -3177,7 +3177,7 @@ static RPCHelpMan rawreissueasset() CAmount asset_amount = 0; const UniValue& asset_amount_uni = issuance_o["asset_amount"]; if (asset_amount_uni.isNum()) { - asset_amount = AmountFromValue(asset_amount_uni); + asset_amount = AmountFromValue(asset_amount_uni, false); if (asset_amount <= 0) { throw JSONRPCError(RPC_INVALID_PARAMETER, "Invalid parameter, asset_amount must be positive"); } diff --git a/src/rpc/util.cpp b/src/rpc/util.cpp index 6b70ca695b..1a65c07ab7 100644 --- a/src/rpc/util.cpp +++ b/src/rpc/util.cpp @@ -90,14 +90,14 @@ void RPCTypeCheckObj(const UniValue& o, } } -CAmount AmountFromValue(const UniValue& value, int decimals) +CAmount AmountFromValue(const UniValue& value, bool check_range, int decimals) { if (!value.isNum() && !value.isStr()) throw JSONRPCError(RPC_TYPE_ERROR, "Amount is not a number or string"); CAmount amount; if (!ParseFixedPoint(value.getValStr(), decimals, &amount)) throw JSONRPCError(RPC_TYPE_ERROR, "Invalid amount"); - if (!MoneyRange(amount)) + if (amount < 0 || (check_range && !MoneyRange(amount))) throw JSONRPCError(RPC_TYPE_ERROR, "Amount out of range"); return amount; } diff --git a/src/rpc/util.h b/src/rpc/util.h index 898db3cd39..4a55dddf61 100644 --- a/src/rpc/util.h +++ b/src/rpc/util.h @@ -91,7 +91,7 @@ std::vector ParseHexO(const UniValue& o, std::string strKey); * @param[in] decimals Number of significant digits (default: 8). * @returns a CAmount if the various checks pass. */ -CAmount AmountFromValue(const UniValue& value, int decimals = 8); +CAmount AmountFromValue(const UniValue& value, bool check_range = true, int decimals = 8); using RPCArgList = std::vector>; std::string HelpExampleCli(const std::string& methodname, const std::string& args); diff --git a/src/wallet/rpc/elements.cpp b/src/wallet/rpc/elements.cpp index d51274360c..798c218249 100644 --- a/src/wallet/rpc/elements.cpp +++ b/src/wallet/rpc/elements.cpp @@ -1426,8 +1426,8 @@ RPCHelpMan issueasset() throw JSONRPCError(RPC_TYPE_ERROR, "Issuance can only be done on elements-style chains. Note: `-regtest` is Bitcoin's regtest mode, instead try `-chain=`"); } - CAmount nAmount = AmountFromValue(request.params[0]); - CAmount nTokens = AmountFromValue(request.params[1]); + CAmount nAmount = AmountFromValue(request.params[0], false); + CAmount nTokens = AmountFromValue(request.params[1], false); if (nAmount == 0 && nTokens == 0) { throw JSONRPCError(RPC_TYPE_ERROR, "Issuance must have one non-zero component"); } @@ -1524,7 +1524,7 @@ RPCHelpMan reissueasset() std::string assetstr = request.params[0].get_str(); CAsset asset = GetAssetFromString(assetstr); - CAmount nAmount = AmountFromValue(request.params[1]); + CAmount nAmount = AmountFromValue(request.params[1], false); if (nAmount <= 0) { throw JSONRPCError(RPC_TYPE_ERROR, "Reissuance must create a non-zero amount."); } diff --git a/src/wallet/rpc/spend.cpp b/src/wallet/rpc/spend.cpp index 903b248144..0ead021dbb 100644 --- a/src/wallet/rpc/spend.cpp +++ b/src/wallet/rpc/spend.cpp @@ -50,7 +50,7 @@ static void ParseRecipients(const UniValue& address_amounts, const UniValue& add destinations.insert(dest); CScript script_pub_key = GetScriptForDestination(dest); - CAmount amount = AmountFromValue(address_amounts[i++]); + CAmount amount = AmountFromValue(address_amounts[i++], asset == Params().GetConsensus().pegged_asset); bool subtract_fee = false; for (unsigned int idx = 0; idx < subtract_fee_outputs.size(); idx++) { @@ -124,7 +124,7 @@ static void SetFeeEstimateMode(const CWallet& wallet, CCoinControl& cc, const Un throw JSONRPCError(RPC_INVALID_PARAMETER, "Cannot specify both estimate_mode and fee_rate"); } // Fee rates in sat/vB cannot represent more than 3 significant digits. - cc.m_feerate = CFeeRate{AmountFromValue(fee_rate, /* decimals */ 3)}; + cc.m_feerate = CFeeRate{AmountFromValue(fee_rate, /*check_range=*/true, /*decimals=*/3)}; if (override_min_fee) cc.fOverrideFeeRate = true; // Default RBF to true for explicit fee_rate, if unset. if (!cc.m_signal_bip125_rbf) cc.m_signal_bip125_rbf = true; From 8dabb73663164b200b3f0cb94af92ad59de2324a Mon Sep 17 00:00:00 2001 From: Byron Hambly Date: Tue, 14 Jan 2025 15:22:55 +0200 Subject: [PATCH 03/16] moneyrange: check asset type --- src/asset.h | 8 ++++++-- src/wallet/receive.cpp | 15 ++++++++++----- src/wallet/spend.cpp | 3 ++- src/wallet/wallet.cpp | 2 +- 4 files changed, 19 insertions(+), 9 deletions(-) diff --git a/src/asset.h b/src/asset.h index ceb1621625..a15861d8f8 100644 --- a/src/asset.h +++ b/src/asset.h @@ -90,15 +90,19 @@ bool operator==(const CAmountMap& a, const CAmountMap& b); bool operator!=(const CAmountMap& a, const CAmountMap& b); bool operator!(const CAmountMap& a); // Check if all values are 0 -inline bool MoneyRange(const CAmountMap& mapValue) { +inline bool MoneyRange(const CAmountMap& mapValue, const CAsset& pegged_asset) { for(CAmountMap::const_iterator it = mapValue.begin(); it != mapValue.end(); it++) { - if (it->second < 0 || it->second > MAX_MONEY) { + if (it->second < 0 || ((pegged_asset.IsNull() || it->first == pegged_asset) && it->second > MAX_MONEY)) { return false; } } return true; } +inline bool MoneyRange(const CAmountMap& mapValue) { + return MoneyRange(mapValue, CAsset()); +} + CAmount valueFor(const CAmountMap& mapValue, const CAsset& asset); std::ostream& operator<<(std::ostream& out, const CAmountMap& map); diff --git a/src/wallet/receive.cpp b/src/wallet/receive.cpp index 20a8c61376..cf988926b8 100644 --- a/src/wallet/receive.cpp +++ b/src/wallet/receive.cpp @@ -70,14 +70,17 @@ CAmountMap TxGetCredit(const CWallet& wallet, const CWalletTx& wtx, const ismine { LOCK(wallet.cs_wallet); + CAsset pegged_asset{Params().GetConsensus().pegged_asset}; for (unsigned int i = 0; i < wtx.tx->vout.size(); ++i) { if (wallet.IsMine(wtx.tx->vout[i]) & filter) { + CAsset asset{wtx.GetOutputAsset(wallet, i)}; CAmount credit = std::max(0, wtx.GetOutputValueOut(wallet, i)); - if (!MoneyRange(credit)) + if (asset == pegged_asset && !MoneyRange(credit)) { throw std::runtime_error(std::string(__func__) + ": value out of range"); + } - nCredit[wtx.GetOutputAsset(wallet, i)] += credit; - if (!MoneyRange(nCredit)) + nCredit[asset] += credit; + if (!MoneyRange(nCredit, pegged_asset)) throw std::runtime_error(std::string(__func__) + ": value out of range"); } } @@ -226,16 +229,18 @@ CAmountMap CachedTxGetAvailableCredit(const CWallet& wallet, const CWalletTx& wt bool allow_used_addresses = (filter & ISMINE_USED) || !wallet.IsWalletFlagSet(WALLET_FLAG_AVOID_REUSE); CAmountMap nCredit; uint256 hashTx = wtx.GetHash(); + CAsset pegged_asset{Params().GetConsensus().pegged_asset}; for (unsigned int i = 0; i < wtx.tx->vout.size(); i++) { if (!wallet.IsSpent(hashTx, i) && (allow_used_addresses || !wallet.IsSpentKey(hashTx, i))) { if (wallet.IsMine(wtx.tx->vout[i]) & filter) { + CAsset asset = wtx.GetOutputAsset(wallet, i); CAmount credit = std::max(0, wtx.GetOutputValueOut(wallet, i)); - if (!MoneyRange(credit)) + if (asset == pegged_asset && !MoneyRange(credit)) throw std::runtime_error(std::string(__func__) + ": value out of range"); nCredit[wtx.GetOutputAsset(wallet, i)] += std::max(0, wtx.GetOutputValueOut(wallet, i)); - if (!MoneyRange(nCredit)) + if (!MoneyRange(nCredit, pegged_asset)) throw std::runtime_error(std::string(__func__) + ": value out of range"); } } diff --git a/src/wallet/spend.cpp b/src/wallet/spend.cpp index f7bd721cef..9a82b63b2d 100644 --- a/src/wallet/spend.cpp +++ b/src/wallet/spend.cpp @@ -265,8 +265,9 @@ void AvailableCoins(const CWallet& wallet, std::vector &vCoins, const C if (asset_filter && asset != *asset_filter) { continue; } - if (outValue < nMinimumAmount || outValue > nMaximumAmount) + if (outValue < nMinimumAmount || (asset == Params().GetConsensus().pegged_asset && outValue > nMaximumAmount)) { continue; + } if (coinControl && coinControl->HasSelected() && !coinControl->fAllowOtherInputs && !coinControl->IsSelected(COutPoint(entry.first, i))) continue; diff --git a/src/wallet/wallet.cpp b/src/wallet/wallet.cpp index e7444556ea..ad9fe6d123 100644 --- a/src/wallet/wallet.cpp +++ b/src/wallet/wallet.cpp @@ -1418,7 +1418,7 @@ CAmountMap CWallet::GetDebit(const CTransaction& tx, const isminefilter& filter) for (const CTxIn& txin : tx.vin) { nDebit += GetDebit(txin, filter); - if (!MoneyRange(nDebit)) + if (!MoneyRange(nDebit, Params().GetConsensus().pegged_asset)) throw std::runtime_error(std::string(__func__) + ": value out of range"); } return nDebit; From e7f32aac75dadedf6e49068fede108ac6c8f4672 Mon Sep 17 00:00:00 2001 From: Byron Hambly Date: Tue, 14 Jan 2025 15:24:33 +0200 Subject: [PATCH 04/16] unblindconfidentialpair: update moneyrange check with asset --- src/blind.cpp | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) diff --git a/src/blind.cpp b/src/blind.cpp index e1a15ab05a..9cb9ea7a7d 100644 --- a/src/blind.cpp +++ b/src/blind.cpp @@ -3,6 +3,7 @@ // file COPYING or http://www.opensource.org/licenses/mit-license.php. #include +#include #include #include @@ -157,11 +158,6 @@ bool UnblindConfidentialPair(const CKey& blinding_key, const CConfidentialValue& return false; } - // Value sidechannel must be a transaction-valid amount (should be belt-and-suspenders check) - if (amount > (uint64_t)MAX_MONEY || !MoneyRange((CAmount)amount)) { - return false; - } - // Convenience pointers to starting point of each recovered 32 byte message unsigned char *asset_type = msg; unsigned char *asset_blinder = msg+32; @@ -172,6 +168,13 @@ bool UnblindConfidentialPair(const CKey& blinding_key, const CConfidentialValue& return false; } + CAsset asset{std::vector{asset_type, asset_type + 32}}; + + // Value sidechannel must be a transaction-valid amount (should be belt-and-suspenders check) + if ((!committedScript.IsUnspendable() && amount == 0) || (asset == Params().GetConsensus().pegged_asset && (amount > (uint64_t)MAX_MONEY || !MoneyRange((CAmount)amount)))) { + return false; + } + // Serialize both generators then compare unsigned char observed_generator[33]; unsigned char derived_generator[33]; @@ -182,7 +185,7 @@ bool UnblindConfidentialPair(const CKey& blinding_key, const CConfidentialValue& } amount_out = (CAmount)amount; - asset_out = CAsset(std::vector(asset_type, asset_type+32)); + asset_out = asset; asset_blinding_factor_out = uint256(std::vector(asset_blinder, asset_blinder+32)); return true; } From 3a3d77e3b6218895473c8b4a0d2a5a2c00963a2f Mon Sep 17 00:00:00 2001 From: Pablo Greco Date: Thu, 23 Jan 2025 05:49:16 -0800 Subject: [PATCH 05/16] Bump version to 23.3.0-rc2 --- configure.ac | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/configure.ac b/configure.ac index 379ebbe695..55e57c5847 100644 --- a/configure.ac +++ b/configure.ac @@ -2,7 +2,7 @@ AC_PREREQ([2.69]) define(_CLIENT_VERSION_MAJOR, 23) define(_CLIENT_VERSION_MINOR, 3) define(_CLIENT_VERSION_BUILD, 0) -define(_CLIENT_VERSION_RC, 1) +define(_CLIENT_VERSION_RC, 2) define(_CLIENT_VERSION_IS_RELEASE, true) define(_COPYRIGHT_YEAR, 2024) define(_COPYRIGHT_HOLDERS,[The %s developers]) From bc05a7aa308e6d1bc2d4b5a421e386f8a0a950ed Mon Sep 17 00:00:00 2001 From: Pablo Greco Date: Mon, 27 Jan 2025 11:54:40 -0800 Subject: [PATCH 06/16] Manually pick acc06bc91f80ddf4e015dcdf0b984bbdbfcb5ca3 from bitcoin --- ci/test/00_setup_env_mac_native_arm64.sh | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/ci/test/00_setup_env_mac_native_arm64.sh b/ci/test/00_setup_env_mac_native_arm64.sh index 1a7be56d5b..ade2d2787c 100755 --- a/ci/test/00_setup_env_mac_native_arm64.sh +++ b/ci/test/00_setup_env_mac_native_arm64.sh @@ -7,7 +7,9 @@ export LC_ALL=C.UTF-8 export HOST=arm64-apple-darwin -export PIP_PACKAGES="zmq" +# Homebrew's python@3.12 is marked as externally managed (PEP 668). +# Therefore, `--break-system-packages` is needed. +export PIP_PACKAGES="--break-system-packages zmq" export GOAL="install" # ELEMENTS: add -fno-stack-check to work around clang bug on macos export BITCOIN_CONFIG="--with-gui --with-miniupnpc --with-natpmp --enable-reduce-exports CXXFLAGS=-fno-stack-check" From 842a5a9608694348c2ee7e52b59ffffbf0a4d927 Mon Sep 17 00:00:00 2001 From: Cory Fields Date: Thu, 13 Jun 2024 13:25:37 +0000 Subject: [PATCH 07/16] upnp: add compatibility for miniupnpc 2.2.8 See: https://github.com/miniupnp/miniupnp/commit/c0a50ce33e3b99ce8a96fd43049bb5b53ffac62f The return value of 2 now indicates: "A valid connected IGD has been found but its IP address is reserved (non routable)" We continue to ignore any return value other than 1. (cherry picked from commit 8acdf66540834b9f9cf28f16d389e8b6a48516d5) --- src/mapport.cpp | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/mapport.cpp b/src/mapport.cpp index 42ca366089..af983a2c5b 100644 --- a/src/mapport.cpp +++ b/src/mapport.cpp @@ -168,8 +168,11 @@ static bool ProcessUpnp() struct UPNPUrls urls; struct IGDdatas data; int r; - +#if MINIUPNPC_API_VERSION <= 17 r = UPNP_GetValidIGD(devlist, &urls, &data, lanaddr, sizeof(lanaddr)); +#else + r = UPNP_GetValidIGD(devlist, &urls, &data, lanaddr, sizeof(lanaddr), nullptr, 0); +#endif if (r == 1) { if (fDiscover) { From eeeed9c3f98a051b06d0fe3dc5fcc925423e0e09 Mon Sep 17 00:00:00 2001 From: Pablo Greco Date: Mon, 27 Jan 2025 09:47:35 -0800 Subject: [PATCH 08/16] CI: Use RockyLinux 8 instead of CentOS Stream 8 --- .cirrus.yml | 4 ++-- ci/test/00_setup_env_i686_centos.sh | 2 +- ci/test/04_install.sh | 2 +- ci/test/05_before_script.sh | 2 +- 4 files changed, 5 insertions(+), 5 deletions(-) diff --git a/.cirrus.yml b/.cirrus.yml index e1102be446..c2b3c50059 100644 --- a/.cirrus.yml +++ b/.cirrus.yml @@ -194,10 +194,10 @@ task: FILE_ENV: "./ci/test/00_setup_env_win64.sh" task: - name: '32-bit + dash [gui] [CentOS 8]' + name: '32-bit + dash [gui] [Rocky 8]' << : *GLOBAL_TASK_TEMPLATE container: - image: quay.io/centos/centos:stream8 + image: quay.io/rockylinux/rockylinux:8 env: << : *CIRRUS_EPHEMERAL_WORKER_TEMPLATE_ENV PACKAGE_MANAGER_INSTALL: "yum install -y" diff --git a/ci/test/00_setup_env_i686_centos.sh b/ci/test/00_setup_env_i686_centos.sh index 8f1cc8af29..28583c6e63 100755 --- a/ci/test/00_setup_env_i686_centos.sh +++ b/ci/test/00_setup_env_i686_centos.sh @@ -8,7 +8,7 @@ export LC_ALL=C.UTF-8 export HOST=i686-pc-linux-gnu export CONTAINER_NAME=ci_i686_centos -export DOCKER_NAME_TAG=quay.io/centos/centos:stream8 +export DOCKER_NAME_TAG=quay.io/rockylinux/rockylinux:8 export DOCKER_PACKAGES="gcc-c++ glibc-devel.x86_64 libstdc++-devel.x86_64 glibc-devel.i686 libstdc++-devel.i686 ccache libtool make git python3 python3-zmq which patch lbzip2 xz procps-ng dash rsync coreutils bison" export GOAL="install" export BITCOIN_CONFIG="--enable-zmq --with-gui=qt5 --enable-reduce-exports" diff --git a/ci/test/04_install.sh b/ci/test/04_install.sh index eaeecec60a..1e8ec18840 100755 --- a/ci/test/04_install.sh +++ b/ci/test/04_install.sh @@ -64,7 +64,7 @@ if [ -n "$DPKG_ADD_ARCH" ]; then CI_EXEC dpkg --add-architecture "$DPKG_ADD_ARCH" fi -if [[ $DOCKER_NAME_TAG == *centos* ]]; then +if [[ $DOCKER_NAME_TAG == *centos* ]] || [[ $DOCKER_NAME_TAG == *rocky* ]]; then ${CI_RETRY_EXE} CI_EXEC dnf -y install epel-release ${CI_RETRY_EXE} CI_EXEC dnf -y --allowerasing install "$DOCKER_PACKAGES" "$PACKAGES" elif [ "$CI_USE_APT_INSTALL" != "no" ]; then diff --git a/ci/test/05_before_script.sh b/ci/test/05_before_script.sh index 8f75fbd1fa..b1cb1e300f 100755 --- a/ci/test/05_before_script.sh +++ b/ci/test/05_before_script.sh @@ -44,7 +44,7 @@ if [[ ${USE_MEMORY_SANITIZER} == "true" ]]; then fi if [ -z "$NO_DEPENDS" ]; then - if [[ $DOCKER_NAME_TAG == *centos* ]]; then + if [[ $DOCKER_NAME_TAG == *centos* ]] || [[ $DOCKER_NAME_TAG == *rocky* ]]; then # CentOS has problems building the depends if the config shell is not explicitly set # (i.e. for libevent a Makefile with an empty SHELL variable is generated, leading to # an error as the first command is executed) From df4d00f1a34f60415f46c6bb18ab8a7b54aca42a Mon Sep 17 00:00:00 2001 From: Pablo Greco Date: Mon, 27 Jan 2025 11:17:44 -0800 Subject: [PATCH 09/16] debug --- ci/test/04_install.sh | 4 +++- ci/test_run_all.sh | 1 + 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/ci/test/04_install.sh b/ci/test/04_install.sh index 1e8ec18840..ff4293009b 100755 --- a/ci/test/04_install.sh +++ b/ci/test/04_install.sh @@ -6,12 +6,14 @@ export LC_ALL=C.UTF-8 +set -x + if [[ $QEMU_USER_CMD == qemu-s390* ]]; then export LC_ALL=C fi if [ "$CI_OS_NAME" == "macos" ]; then - sudo -H pip3 install --upgrade pip + sudo -H pip3 install --upgrade pip || true # shellcheck disable=SC2086 IN_GETOPT_BIN="$(brew --prefix gnu-getopt)/bin/getopt" ${CI_RETRY_EXE} pip3 install --user $PIP_PACKAGES fi diff --git a/ci/test_run_all.sh b/ci/test_run_all.sh index 93b07aab1e..1aec490962 100755 --- a/ci/test_run_all.sh +++ b/ci/test_run_all.sh @@ -6,6 +6,7 @@ export LC_ALL=C.UTF-8 +set -x set -o errexit; source ./ci/test/00_setup_env.sh set -o errexit; source ./ci/test/04_install.sh set -o errexit; source ./ci/test/05_before_script.sh From 0f7383b5cbc104f64b9570f66b3e4085481250ae Mon Sep 17 00:00:00 2001 From: Pablo Greco Date: Mon, 27 Jan 2025 17:29:44 -0800 Subject: [PATCH 10/16] CI: use default wallet name in wallet_elements_21million --- test/functional/wallet_elements_21million.py | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/test/functional/wallet_elements_21million.py b/test/functional/wallet_elements_21million.py index f9faafdbea..ea6b34dd6f 100755 --- a/test/functional/wallet_elements_21million.py +++ b/test/functional/wallet_elements_21million.py @@ -50,8 +50,8 @@ def run_test(self): assert_equal(self.nodes[1].getbalance()[asset], 22_000_000) # unload/load wallet - self.nodes[1].unloadwallet("") - self.nodes[1].loadwallet("") + self.nodes[1].unloadwallet(self.default_wallet_name) + self.nodes[1].loadwallet(self.default_wallet_name) assert_equal(self.nodes[1].getbalance()[asset], 22_000_000) # send more than 45 million of that asset @@ -62,8 +62,8 @@ def run_test(self): assert_equal(self.nodes[2].getbalance()[asset], 46_000_000) # unload/load wallet - self.nodes[2].unloadwallet("") - self.nodes[2].loadwallet("") + self.nodes[2].unloadwallet(self.default_wallet_name) + self.nodes[2].loadwallet(self.default_wallet_name) assert_equal(self.nodes[2].getbalance()[asset], 46_000_000) # send some policy asset to node 1 for fees @@ -86,8 +86,8 @@ def run_test(self): assert_equal(self.nodes[2].getbalance()[asset], 200_000_000) # unload/load wallet - self.nodes[2].unloadwallet("") - self.nodes[2].loadwallet("") + self.nodes[2].unloadwallet(self.default_wallet_name) + self.nodes[2].loadwallet(self.default_wallet_name) assert_equal(self.nodes[2].getbalance()[asset], 200_000_000) if __name__ == '__main__': From fd09b79f9871f2df47e9bf69f14e0d90441e128b Mon Sep 17 00:00:00 2001 From: Pablo Greco Date: Mon, 27 Jan 2025 17:29:19 -0800 Subject: [PATCH 11/16] CI: wallet_elements_regression_1263 uses getpeginaddress, disable for descriptor wallets --- test/functional/wallet_elements_regression_1263.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/functional/wallet_elements_regression_1263.py b/test/functional/wallet_elements_regression_1263.py index c4f713c8e3..e13c8a6f8e 100755 --- a/test/functional/wallet_elements_regression_1263.py +++ b/test/functional/wallet_elements_regression_1263.py @@ -18,7 +18,7 @@ def set_test_params(self): self.chain = "regtest" def skip_test_if_missing_module(self): - self.skip_if_no_wallet() + self.skip_if_no_bdb() def run_test(self): self.log.info("Start in Bitcoin regtest mode") From a582dfaa3e2b2750122273e4bc096b60a3d0460d Mon Sep 17 00:00:00 2001 From: Pablo Greco Date: Mon, 27 Jan 2025 17:27:53 -0800 Subject: [PATCH 12/16] CI: trim_headers test uses combineblocksigs, disable for descriptor wallets --- test/functional/feature_trim_headers.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/functional/feature_trim_headers.py b/test/functional/feature_trim_headers.py index 8d44ee92a9..0ed204ffa9 100755 --- a/test/functional/feature_trim_headers.py +++ b/test/functional/feature_trim_headers.py @@ -38,7 +38,7 @@ def make_signblockscript(num_nodes, required_signers, keys): class TrimHeadersTest(BitcoinTestFramework): def skip_test_if_missing_module(self): - self.skip_if_no_wallet() + self.skip_if_no_bdb() # Dynamically generate N keys to be used for block signing. def init_keys(self, num_keys): From 4c2bb8cc2cfb4e155d5918019fb6b235423ef285 Mon Sep 17 00:00:00 2001 From: Pablo Greco Date: Mon, 27 Jan 2025 17:24:35 -0800 Subject: [PATCH 13/16] CI: discounttests use initialfreecoins, disable for descriptor wallets --- test/functional/feature_discount_ct.py | 2 +- test/functional/feature_discount_ct_ordering.py | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/test/functional/feature_discount_ct.py b/test/functional/feature_discount_ct.py index 84e2c096b1..8b4cdd658e 100755 --- a/test/functional/feature_discount_ct.py +++ b/test/functional/feature_discount_ct.py @@ -35,7 +35,7 @@ def set_test_params(self): ] def skip_test_if_missing_module(self): - self.skip_if_no_wallet() + self.skip_if_no_bdb() def run_test(self): feerate = 1.0 diff --git a/test/functional/feature_discount_ct_ordering.py b/test/functional/feature_discount_ct_ordering.py index aed8a1f0db..0dd2d9d54c 100755 --- a/test/functional/feature_discount_ct_ordering.py +++ b/test/functional/feature_discount_ct_ordering.py @@ -32,7 +32,7 @@ def set_test_params(self): ] def skip_test_if_missing_module(self): - self.skip_if_no_wallet() + self.skip_if_no_bdb() def run_test(self): From ef1da6ae51c53621631c78890ab47b31e8fb8869 Mon Sep 17 00:00:00 2001 From: Pablo Greco Date: Mon, 27 Jan 2025 17:25:29 -0800 Subject: [PATCH 14/16] CI: feature_taphash_pegins_issuances test uses initialfreecoins, disable for descriptor wallets --- test/functional/feature_taphash_pegins_issuances.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/functional/feature_taphash_pegins_issuances.py b/test/functional/feature_taphash_pegins_issuances.py index e4716e8ebc..ec2ee8d99f 100755 --- a/test/functional/feature_taphash_pegins_issuances.py +++ b/test/functional/feature_taphash_pegins_issuances.py @@ -40,7 +40,7 @@ def set_test_params(self): ]] def skip_test_if_missing_module(self): - self.skip_if_no_wallet() + self.skip_if_no_bdb() def setup_network(self, split=False): self.setup_nodes() From 45c5a3509a02668681edc38295c061a9215a4b1a Mon Sep 17 00:00:00 2001 From: Pablo Greco Date: Mon, 27 Jan 2025 17:26:12 -0800 Subject: [PATCH 15/16] CI: feature_tapscript_opcodes test uses initialfreecoins, disable for descriptor wallets --- test/functional/feature_tapscript_opcodes.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/functional/feature_tapscript_opcodes.py b/test/functional/feature_tapscript_opcodes.py index 8772a08d72..6174e18e30 100755 --- a/test/functional/feature_tapscript_opcodes.py +++ b/test/functional/feature_tapscript_opcodes.py @@ -44,7 +44,7 @@ def set_test_params(self): ]] def skip_test_if_missing_module(self): - self.skip_if_no_wallet() + self.skip_if_no_bdb() def setup_network(self, split=False): self.setup_nodes() From 2f27b97cf0a99b59577782d309068a5386f36997 Mon Sep 17 00:00:00 2001 From: Pablo Greco Date: Mon, 27 Jan 2025 16:39:17 -0800 Subject: [PATCH 16/16] CI: example_elements_code_tutorial test test uses initialfreecoins, disable for descriptor wallets --- test/functional/example_elements_code_tutorial.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/functional/example_elements_code_tutorial.py b/test/functional/example_elements_code_tutorial.py index feb645f1f1..62a24ea76a 100755 --- a/test/functional/example_elements_code_tutorial.py +++ b/test/functional/example_elements_code_tutorial.py @@ -24,7 +24,7 @@ def set_test_params(self): self.extra_args[0].append("-anyonecanspendaremine=1") def skip_test_if_missing_module(self): - self.skip_if_no_wallet() + self.skip_if_no_bdb() def run_test(self): self.generate(self.nodes[0], COINBASE_MATURITY + 1)