diff options
Diffstat (limited to 'test')
-rwxr-xr-x | test/functional/interface_zmq.py | 4 | ||||
-rwxr-xr-x | test/functional/rpc_getaddressinfo_labels_purpose_deprecation.py | 48 | ||||
-rwxr-xr-x | test/functional/test_framework/wallet_util.py | 5 | ||||
-rwxr-xr-x | test/functional/test_runner.py | 1 | ||||
-rwxr-xr-x | test/functional/wallet_avoidreuse.py | 25 | ||||
-rwxr-xr-x | test/functional/wallet_basic.py | 7 | ||||
-rwxr-xr-x | test/functional/wallet_bumpfee.py | 82 | ||||
-rwxr-xr-x | test/functional/wallet_import_with_label.py | 39 | ||||
-rwxr-xr-x | test/functional/wallet_importmulti.py | 5 | ||||
-rwxr-xr-x | test/functional/wallet_labels.py | 13 | ||||
-rwxr-xr-x | test/functional/wallet_listreceivedby.py | 7 | ||||
-rwxr-xr-x | test/lint/lint-format-strings.py | 1 | ||||
-rw-r--r-- | test/sanitizer_suppressions/tsan | 8 |
13 files changed, 184 insertions, 61 deletions
diff --git a/test/functional/interface_zmq.py b/test/functional/interface_zmq.py index 5aea10fbce..89c55f31f3 100755 --- a/test/functional/interface_zmq.py +++ b/test/functional/interface_zmq.py @@ -59,6 +59,10 @@ class ZMQTest (BitcoinTestFramework): # Note that the publishing order is not defined in the documentation and # is subject to change. import zmq + + # Invalid zmq arguments don't take down the node, see #17185. + self.restart_node(0, ["-zmqpubrawtx=foo", "-zmqpubhashtx=bar"]) + address = 'tcp://127.0.0.1:28332' socket = self.ctx.socket(zmq.SUB) socket.set(zmq.RCVTIMEO, 60000) diff --git a/test/functional/rpc_getaddressinfo_labels_purpose_deprecation.py b/test/functional/rpc_getaddressinfo_labels_purpose_deprecation.py new file mode 100755 index 0000000000..1049440d49 --- /dev/null +++ b/test/functional/rpc_getaddressinfo_labels_purpose_deprecation.py @@ -0,0 +1,48 @@ +#!/usr/bin/env python3 +# Copyright (c) 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. +""" +Test deprecation of RPC getaddressinfo `labels` returning an array +containing a JSON hash of `name` and purpose` key-value pairs. It now +returns an array of label names. + +""" +from test_framework.test_framework import BitcoinTestFramework +from test_framework.util import assert_equal + +LABELS_TO_TEST = frozenset({"" , "New 𝅘𝅥𝅯 $<#>&!рыба Label"}) + +class GetAddressInfoLabelsPurposeDeprecationTest(BitcoinTestFramework): + def set_test_params(self): + self.num_nodes = 2 + self.setup_clean_chain = False + # Start node[0] with -deprecatedrpc=labelspurpose and node[1] without. + self.extra_args = [["-deprecatedrpc=labelspurpose"], []] + + def skip_test_if_missing_module(self): + self.skip_if_no_wallet() + + def test_labels(self, node_num, label_name, expected_value): + node = self.nodes[node_num] + address = node.getnewaddress() + if label_name != "": + node.setlabel(address, label_name) + self.log.info(" set label to {}".format(label_name)) + labels = node.getaddressinfo(address)["labels"] + self.log.info(" labels = {}".format(labels)) + assert_equal(labels, expected_value) + + def run_test(self): + """Test getaddressinfo labels with and without -deprecatedrpc flag.""" + self.log.info("Test getaddressinfo labels with -deprecatedrpc flag") + for label in LABELS_TO_TEST: + self.test_labels(node_num=0, label_name=label, expected_value=[{"name": label, "purpose": "receive"}]) + + self.log.info("Test getaddressinfo labels without -deprecatedrpc flag") + for label in LABELS_TO_TEST: + self.test_labels(node_num=1, label_name=label, expected_value=[label]) + + +if __name__ == '__main__': + GetAddressInfoLabelsPurposeDeprecationTest().main() diff --git a/test/functional/test_framework/wallet_util.py b/test/functional/test_framework/wallet_util.py index 881df80f64..487acd75d9 100755 --- a/test/functional/test_framework/wallet_util.py +++ b/test/functional/test_framework/wallet_util.py @@ -88,11 +88,6 @@ def get_multisig(node): p2sh_p2wsh_script=CScript([OP_HASH160, witness_script, OP_EQUAL]).hex(), p2sh_p2wsh_addr=script_to_p2sh_p2wsh(script_code)) -def labels_value(name="", purpose="receive"): - """Generate a getaddressinfo labels array from a name and purpose. - Often used as the value of a labels kwarg for calling test_address below.""" - return [{"name": name, "purpose": purpose}] - def test_address(node, address, **kwargs): """Get address info for `address` and test whether the returned values are as expected.""" addr_info = node.getaddressinfo(address) diff --git a/test/functional/test_runner.py b/test/functional/test_runner.py index 110733c529..acb559911b 100755 --- a/test/functional/test_runner.py +++ b/test/functional/test_runner.py @@ -212,6 +212,7 @@ BASE_SCRIPTS = [ 'p2p_permissions.py', 'feature_blocksdir.py', 'feature_config_args.py', + 'rpc_getaddressinfo_labels_purpose_deprecation.py', 'rpc_help.py', 'feature_help.py', 'feature_shutdown.py', diff --git a/test/functional/wallet_avoidreuse.py b/test/functional/wallet_avoidreuse.py index 3cfb5a648b..0ca8c80956 100755 --- a/test/functional/wallet_avoidreuse.py +++ b/test/functional/wallet_avoidreuse.py @@ -86,7 +86,12 @@ class AvoidReuseTest(BitcoinTestFramework): reset_balance(self.nodes[1], self.nodes[0].getnewaddress()) self.test_fund_send_fund_senddirty() reset_balance(self.nodes[1], self.nodes[0].getnewaddress()) - self.test_fund_send_fund_send() + self.test_fund_send_fund_send("legacy") + reset_balance(self.nodes[1], self.nodes[0].getnewaddress()) + self.test_fund_send_fund_send("p2sh-segwit") + reset_balance(self.nodes[1], self.nodes[0].getnewaddress()) + self.test_fund_send_fund_send("bech32") + def test_persistence(self): '''Test that wallet files persist the avoid_reuse flag.''' @@ -182,7 +187,7 @@ class AvoidReuseTest(BitcoinTestFramework): assert_approx(self.nodes[1].getbalance(), 5, 0.001) assert_approx(self.nodes[1].getbalance(avoid_reuse=False), 5, 0.001) - def test_fund_send_fund_send(self): + def test_fund_send_fund_send(self, second_addr_type): ''' Test the simple case where [1] generates a new address A, then [0] sends 10 BTC to A. @@ -193,7 +198,7 @@ class AvoidReuseTest(BitcoinTestFramework): ''' self.log.info("Test fund send fund send") - fundaddr = self.nodes[1].getnewaddress() + fundaddr = self.nodes[1].getnewaddress(label="", address_type="legacy") retaddr = self.nodes[0].getnewaddress() self.nodes[0].sendtoaddress(fundaddr, 10) @@ -214,7 +219,19 @@ class AvoidReuseTest(BitcoinTestFramework): # getbalances should show no used, 5 btc trusted assert_balances(self.nodes[1], mine={"used": 0, "trusted": 5}) - self.nodes[0].sendtoaddress(fundaddr, 10) + # For the second send, we transmute it to a related single-key address + # to make sure it's also detected as re-use + fund_spk = self.nodes[0].getaddressinfo(fundaddr)["scriptPubKey"] + fund_decoded = self.nodes[0].decodescript(fund_spk) + if second_addr_type == "p2sh-segwit": + new_fundaddr = fund_decoded["segwit"]["p2sh-segwit"] + elif second_addr_type == "bech32": + new_fundaddr = fund_decoded["segwit"]["addresses"][0] + else: + new_fundaddr = fundaddr + assert_equal(second_addr_type, "legacy") + + self.nodes[0].sendtoaddress(new_fundaddr, 10) self.nodes[0].generate(1) self.sync_all() diff --git a/test/functional/wallet_basic.py b/test/functional/wallet_basic.py index 2606afa0e4..4780e9263e 100755 --- a/test/functional/wallet_basic.py +++ b/test/functional/wallet_basic.py @@ -15,10 +15,7 @@ from test_framework.util import ( connect_nodes, wait_until, ) -from test_framework.wallet_util import ( - labels_value, - test_address, -) +from test_framework.wallet_util import test_address class WalletTest(BitcoinTestFramework): @@ -395,7 +392,7 @@ class WalletTest(BitcoinTestFramework): for label in [u'рыба', u'𝅘𝅥𝅯']: addr = self.nodes[0].getnewaddress() self.nodes[0].setlabel(addr, label) - test_address(self.nodes[0], addr, label=label, labels=labels_value(name=label)) + test_address(self.nodes[0], addr, label=label, labels=[label]) assert label in self.nodes[0].listlabels() self.nodes[0].rpc.ensure_ascii = True # restore to default diff --git a/test/functional/wallet_bumpfee.py b/test/functional/wallet_bumpfee.py index 0c08655833..4eb0d19a4f 100755 --- a/test/functional/wallet_bumpfee.py +++ b/test/functional/wallet_bumpfee.py @@ -78,6 +78,7 @@ class BumpFeeTest(BitcoinTestFramework): test_small_output_fails(rbf_node, dest_address) test_dust_to_fee(rbf_node, dest_address) test_settxfee(rbf_node, dest_address) + test_watchonly_psbt(self, peer_node, rbf_node, dest_address) test_rebumping(rbf_node, dest_address) test_rebumping_not_replaceable(rbf_node, dest_address) test_unconfirmed_not_spendable(rbf_node, rbf_node_address) @@ -103,6 +104,7 @@ def test_simple_bumpfee_succeeds(self, mode, rbf_node, peer_node, dest_address): assert_equal(bumped_tx["errors"], []) assert bumped_tx["fee"] > -rbftx["fee"] assert_equal(bumped_tx["origfee"], -rbftx["fee"]) + assert "psbt" not in bumped_tx # check that bumped_tx propagates, original tx was evicted and has a wallet conflict self.sync_mempools((rbf_node, peer_node)) assert bumped_tx["txid"] in rbf_node.getrawmempool() @@ -280,6 +282,86 @@ def test_maxtxfee_fails(test, rbf_node, dest_address): test.restart_node(1, test.extra_args[1]) rbf_node.walletpassphrase(WALLET_PASSPHRASE, WALLET_PASSPHRASE_TIMEOUT) +def test_watchonly_psbt(test, peer_node, rbf_node, dest_address): + priv_rec_desc = "wpkh([00000001/84'/1'/0']tprv8ZgxMBicQKsPd7Uf69XL1XwhmjHopUGep8GuEiJDZmbQz6o58LninorQAfcKZWARbtRtfnLcJ5MQ2AtHcQJCCRUcMRvmDUjyEmNUWwx8UbK/0/*)#rweraev0" + pub_rec_desc = rbf_node.getdescriptorinfo(priv_rec_desc)["descriptor"] + priv_change_desc = "wpkh([00000001/84'/1'/0']tprv8ZgxMBicQKsPd7Uf69XL1XwhmjHopUGep8GuEiJDZmbQz6o58LninorQAfcKZWARbtRtfnLcJ5MQ2AtHcQJCCRUcMRvmDUjyEmNUWwx8UbK/1/*)#j6uzqvuh" + pub_change_desc = rbf_node.getdescriptorinfo(priv_change_desc)["descriptor"] + # Create a wallet with private keys that can sign PSBTs + rbf_node.createwallet(wallet_name="signer", disable_private_keys=False, blank=True) + signer = rbf_node.get_wallet_rpc("signer") + assert signer.getwalletinfo()['private_keys_enabled'] + result = signer.importmulti([{ + "desc": priv_rec_desc, + "timestamp": 0, + "range": [0,1], + "internal": False, + "keypool": False # Keys can only be imported to the keypool when private keys are disabled + }, + { + "desc": priv_change_desc, + "timestamp": 0, + "range": [0, 0], + "internal": True, + "keypool": False + }]) + assert_equal(result, [{'success': True}, {'success': True}]) + + # Create another wallet with just the public keys, which creates PSBTs + rbf_node.createwallet(wallet_name="watcher", disable_private_keys=True, blank=True) + watcher = rbf_node.get_wallet_rpc("watcher") + assert not watcher.getwalletinfo()['private_keys_enabled'] + + result = watcher.importmulti([{ + "desc": pub_rec_desc, + "timestamp": 0, + "range": [0,10], + "internal": False, + "keypool": True, + "watchonly": True + }, + { + "desc": pub_change_desc, + "timestamp": 0, + "range": [0, 10], + "internal": True, + "keypool": True, + "watchonly": True + }]) + assert_equal(result, [{'success': True}, {'success': True}]) + + funding_address1 = watcher.getnewaddress(address_type='bech32') + funding_address2 = watcher.getnewaddress(address_type='bech32') + peer_node.sendmany("", {funding_address1: 0.001, funding_address2: 0.001}) + peer_node.generate(1) + test.sync_all() + + # Create single-input PSBT for transaction to be bumped + psbt = watcher.walletcreatefundedpsbt([], {dest_address:0.0005}, 0, {"feeRate": 0.00001}, True)['psbt'] + psbt_signed = signer.walletprocesspsbt(psbt=psbt, sign=True, sighashtype="ALL", bip32derivs=True) + psbt_final = watcher.finalizepsbt(psbt_signed["psbt"]) + original_txid = watcher.sendrawtransaction(psbt_final["hex"]) + assert_equal(len(watcher.decodepsbt(psbt)["tx"]["vin"]), 1) + + # Bump fee, obnoxiously high to add additional watchonly input + bumped_psbt = watcher.bumpfee(original_txid, {"fee_rate":0.005}) + assert_greater_than(len(watcher.decodepsbt(bumped_psbt['psbt'])["tx"]["vin"]), 1) + assert "txid" not in bumped_psbt + assert_equal(bumped_psbt["origfee"], -watcher.gettransaction(original_txid)["fee"]) + assert not watcher.finalizepsbt(bumped_psbt["psbt"])["complete"] + + # Sign bumped transaction + bumped_psbt_signed = signer.walletprocesspsbt(psbt=bumped_psbt["psbt"], sign=True, sighashtype="ALL", bip32derivs=True) + bumped_psbt_final = watcher.finalizepsbt(bumped_psbt_signed["psbt"]) + assert bumped_psbt_final["complete"] + + # Broadcast bumped transaction + bumped_txid = watcher.sendrawtransaction(bumped_psbt_final["hex"]) + assert bumped_txid in rbf_node.getrawmempool() + assert original_txid not in rbf_node.getrawmempool() + + rbf_node.unloadwallet("watcher") + rbf_node.unloadwallet("signer") def test_rebumping(rbf_node, dest_address): # check that re-bumping the original tx fails, but bumping the bumper succeeds diff --git a/test/functional/wallet_import_with_label.py b/test/functional/wallet_import_with_label.py index 651ecd18b2..64d227b30f 100755 --- a/test/functional/wallet_import_with_label.py +++ b/test/functional/wallet_import_with_label.py @@ -11,10 +11,7 @@ with and without a label. """ from test_framework.test_framework import BitcoinTestFramework -from test_framework.wallet_util import ( - labels_value, - test_address, -) +from test_framework.wallet_util import test_address class ImportWithLabel(BitcoinTestFramework): @@ -40,7 +37,7 @@ class ImportWithLabel(BitcoinTestFramework): iswatchonly=True, ismine=False, label=label, - labels=labels_value(name=label)) + labels=[label]) self.log.info( "Import the watch-only address's private key without a " @@ -48,11 +45,7 @@ class ImportWithLabel(BitcoinTestFramework): ) priv_key = self.nodes[0].dumpprivkey(address) self.nodes[1].importprivkey(priv_key) - - test_address(self.nodes[1], - address, - label=label, - labels=labels_value(name=label)) + test_address(self.nodes[1], address, label=label, labels=[label]) self.log.info( "Test importaddress without label and importprivkey with label." @@ -65,7 +58,7 @@ class ImportWithLabel(BitcoinTestFramework): iswatchonly=True, ismine=False, label="", - labels=labels_value()) + labels=[""]) self.log.info( "Import the watch-only address's private key with a " @@ -75,10 +68,7 @@ class ImportWithLabel(BitcoinTestFramework): label2 = "Test Label 2" self.nodes[1].importprivkey(priv_key2, label2) - test_address(self.nodes[1], - address2, - label=label2, - labels=labels_value(name=label2)) + test_address(self.nodes[1], address2, label=label2, labels=[label2]) self.log.info("Test importaddress with label and importprivkey with label.") self.log.info("Import a watch-only address with a label.") @@ -90,7 +80,7 @@ class ImportWithLabel(BitcoinTestFramework): iswatchonly=True, ismine=False, label=label3_addr, - labels=labels_value(name=label3_addr)) + labels=[label3_addr]) self.log.info( "Import the watch-only address's private key with a " @@ -100,10 +90,7 @@ class ImportWithLabel(BitcoinTestFramework): label3_priv = "Test Label 3 for importprivkey" self.nodes[1].importprivkey(priv_key3, label3_priv) - test_address(self.nodes[1], - address3, - label=label3_priv, - labels=labels_value(name=label3_priv)) + test_address(self.nodes[1], address3, label=label3_priv, labels=[label3_priv]) self.log.info( "Test importprivkey won't label new dests with the same " @@ -118,7 +105,7 @@ class ImportWithLabel(BitcoinTestFramework): iswatchonly=True, ismine=False, label=label4_addr, - labels=labels_value(name=label4_addr), + labels=[label4_addr], embedded=None) self.log.info( @@ -131,15 +118,9 @@ class ImportWithLabel(BitcoinTestFramework): self.nodes[1].importprivkey(priv_key4) embedded_addr = self.nodes[1].getaddressinfo(address4)['embedded']['address'] - test_address(self.nodes[1], - embedded_addr, - label="", - labels=labels_value()) + test_address(self.nodes[1], embedded_addr, label="", labels=[""]) - test_address(self.nodes[1], - address4, - label=label4_addr, - labels=labels_value(name=label4_addr)) + test_address(self.nodes[1], address4, label=label4_addr, labels=[label4_addr]) self.stop_nodes() diff --git a/test/functional/wallet_importmulti.py b/test/functional/wallet_importmulti.py index 5febac5998..eb55578bfd 100755 --- a/test/functional/wallet_importmulti.py +++ b/test/functional/wallet_importmulti.py @@ -29,7 +29,6 @@ from test_framework.util import ( from test_framework.wallet_util import ( get_key, get_multisig, - labels_value, test_address, ) @@ -571,7 +570,7 @@ class ImportMultiTest(BitcoinTestFramework): solvable=True, ismine=True, label=p2sh_p2wpkh_label, - labels=labels_value(name=p2sh_p2wpkh_label)) + labels=[p2sh_p2wpkh_label]) # Test ranged descriptor fails if range is not specified xpriv = "tprv8ZgxMBicQKsPeuVhWwi6wuMQGfPKi9Li5GtX35jVNknACgqe3CY4g5xgkfDDJcmtF7o1QnxWDRYw4H5P26PXq7sbcUkEqeR4fg3Kxp2tigg" @@ -643,7 +642,7 @@ class ImportMultiTest(BitcoinTestFramework): solvable=True, ismine=False, label=p2pkh_label, - labels=labels_value(name=p2pkh_label)) + labels=[p2pkh_label]) # Test import fails if both desc and scriptPubKey are provided key = get_key(self.nodes[0]) diff --git a/test/functional/wallet_labels.py b/test/functional/wallet_labels.py index 33e067601e..f795202d72 100755 --- a/test/functional/wallet_labels.py +++ b/test/functional/wallet_labels.py @@ -13,10 +13,8 @@ from collections import defaultdict from test_framework.test_framework import BitcoinTestFramework from test_framework.util import assert_equal, assert_raises_rpc_error -from test_framework.wallet_util import ( - labels_value, - test_address, -) +from test_framework.wallet_util import test_address + class WalletLabelsTest(BitcoinTestFramework): def set_test_params(self): @@ -157,12 +155,7 @@ class Label: if self.receive_address is not None: assert self.receive_address in self.addresses for address in self.addresses: - test_address( - node, - address, - label=self.name, - labels=labels_value(name=self.name, purpose=self.purpose[address]) - ) + test_address(node, address, label=self.name, labels=[self.name]) assert self.name in node.listlabels() assert_equal( node.getaddressesbylabel(self.name), diff --git a/test/functional/wallet_listreceivedby.py b/test/functional/wallet_listreceivedby.py index afd473306d..4b83e1613f 100755 --- a/test/functional/wallet_listreceivedby.py +++ b/test/functional/wallet_listreceivedby.py @@ -11,10 +11,7 @@ from test_framework.util import ( assert_equal, assert_raises_rpc_error, ) -from test_framework.wallet_util import ( - labels_value, - test_address, -) +from test_framework.wallet_util import test_address class ReceivedByTest(BitcoinTestFramework): @@ -131,7 +128,7 @@ class ReceivedByTest(BitcoinTestFramework): # set pre-state label = '' address = self.nodes[1].getnewaddress() - test_address(self.nodes[1], address, label=label, labels=labels_value(name=label)) + test_address(self.nodes[1], address, label=label, labels=[label]) received_by_label_json = [r for r in self.nodes[1].listreceivedbylabel() if r["label"] == label][0] balance_by_label = self.nodes[1].getreceivedbylabel(label) diff --git a/test/lint/lint-format-strings.py b/test/lint/lint-format-strings.py index 99127e01f8..cc24a0b609 100755 --- a/test/lint/lint-format-strings.py +++ b/test/lint/lint-format-strings.py @@ -17,6 +17,7 @@ FALSE_POSITIVES = [ ("src/index/base.cpp", "FatalError(const char* fmt, const Args&... args)"), ("src/netbase.cpp", "LogConnectFailure(bool manual_connection, const char* fmt, const Args&... args)"), ("src/util/system.cpp", "strprintf(_(COPYRIGHT_HOLDERS).translated, COPYRIGHT_HOLDERS_SUBSTITUTION)"), + ("src/validationinterface.cpp", "LogPrint(BCLog::VALIDATION, fmt \"\\n\", __VA_ARGS__)"), ("src/wallet/wallet.h", "WalletLogPrintf(std::string fmt, Params... parameters)"), ("src/wallet/wallet.h", "LogPrintf((\"%s \" + fmt).c_str(), GetDisplayName(), parameters...)"), ("src/logging.h", "LogPrintf(const char* fmt, const Args&... args)"), diff --git a/test/sanitizer_suppressions/tsan b/test/sanitizer_suppressions/tsan index 70eea34363..b9c5c038d0 100644 --- a/test/sanitizer_suppressions/tsan +++ b/test/sanitizer_suppressions/tsan @@ -7,6 +7,14 @@ deadlock:WalletBatch # Intentional deadlock in tests deadlock:TestPotentialDeadLockDetected +# Race due to unprotected calls to thread-unsafe BOOST_TEST_MESSAGE from different threads: +# * G_TEST_LOG_FUN in the index thread +# * boost test case invoker (entering a test case) in the main thread +# TODO: get rid of BOOST_ macros, see also https://github.com/bitcoin/bitcoin/issues/8670 +race:blockfilter_index_initial_sync_invoker +race:txindex_initial_sync_invoker +race:validation_block_tests::TestSubscriber + # Wildcard for all gui tests, should be replaced with non-wildcard suppressions race:src/qt/test/* deadlock:src/qt/test/* |