aboutsummaryrefslogtreecommitdiff
path: root/test/functional
diff options
context:
space:
mode:
Diffstat (limited to 'test/functional')
-rwxr-xr-xtest/functional/interface_zmq.py4
-rwxr-xr-xtest/functional/rpc_getaddressinfo_labels_purpose_deprecation.py48
-rwxr-xr-xtest/functional/test_framework/wallet_util.py5
-rwxr-xr-xtest/functional/test_runner.py1
-rwxr-xr-xtest/functional/wallet_avoidreuse.py25
-rwxr-xr-xtest/functional/wallet_basic.py7
-rwxr-xr-xtest/functional/wallet_bumpfee.py82
-rwxr-xr-xtest/functional/wallet_import_with_label.py39
-rwxr-xr-xtest/functional/wallet_importmulti.py5
-rwxr-xr-xtest/functional/wallet_labels.py13
-rwxr-xr-xtest/functional/wallet_listreceivedby.py7
11 files changed, 175 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)