Merge bitcoin/bitcoin#32452: test: Remove legacy wallet RPC overloads

b104d44227 test: Remove RPCOverloadWrapper (Ava Chow)
4d32c19516 test: Replace importpubkey (Ava Chow)
fe838dd391 test: Replace usage of addmultisigaddress (Ava Chow)
d314207779 test: Replace usage of importaddress (Ava Chow)
fcc457573f test: Replace importprivkey with wallet_importprivkey (Ava Chow)
94c87bbbd0 test: Remove unnecessary importprivkey from wallet_createwallet (Ava Chow)

Pull request description:

  `RPCOverloadWrapper` implemented overloads for legacy wallet only RPCs so that the same function call could be used within tests for both legacy wallets and descriptor wallets. With legacy wallets now removed, there is no need to continue to have these overloads.

  For `importaddress`, `addmultisigaddress`, and `importpubkey`, the uses of these are converted to `importdescriptors`.

  For `importprivkey`, a new helper function `wallet_imporprivkey` is introduced that does what the overload did. This is mainly to reduce verbosity as `importprivkey` was more widely used throughout the tests.

  Some tests that used these RPCs are now also no longer relevant and have been removed.

ACKs for top commit:
  Sjors:
    ACK b104d44227
  pablomartin4btc:
    cr ACK b104d44227
  rkrux:
    ACK b104d44227
  w0xlt:
    ACK https://github.com/bitcoin/bitcoin/pull/32452/commits/b104d442277090337ce405d92f1398b7cc9bcdb7

Tree-SHA512: ded2f73829e2ce28466d4a9738eb382783ad990daee5d1859dbc4d354e6f8eec0c483ed5ecb1287fe0dd24ac332065b733a30d71b126b841bd7cd49e9a094b6d
This commit is contained in:
merge-script committed 2025-05-17 10:19:35 +01:00
commit 7710a31f0c
18 files changed
+106 -136

No files matched your search

+2 -1
View File
@@ -12,6 +12,7 @@ from test_framework.test_framework import BitcoinTestFramework
from test_framework.util import ( from test_framework.util import (
assert_equal, assert_equal,
assert_raises_rpc_error, assert_raises_rpc_error,
wallet_importprivkey,
) )
import json import json
import os import os
@@ -45,7 +46,7 @@ class GetblockstatsTest(BitcoinTestFramework):
self.nodes[0].setmocktime(mocktime) self.nodes[0].setmocktime(mocktime)
self.nodes[0].createwallet(wallet_name='test') self.nodes[0].createwallet(wallet_name='test')
privkey = self.nodes[0].get_deterministic_priv_key().key privkey = self.nodes[0].get_deterministic_priv_key().key
self.nodes[0].importprivkey(privkey) wallet_importprivkey(self.nodes[0], privkey, 0)
self.generate(self.nodes[0], COINBASE_MATURITY + 1) self.generate(self.nodes[0], COINBASE_MATURITY + 1)
+18 -6
View File
@@ -48,6 +48,7 @@ from test_framework.util import (
assert_greater_than_or_equal, assert_greater_than_or_equal,
assert_raises_rpc_error, assert_raises_rpc_error,
find_vout_for_address, find_vout_for_address,
wallet_importprivkey,
) )
from test_framework.wallet_util import ( from test_framework.wallet_util import (
calculate_input_weight, calculate_input_weight,
@@ -115,7 +116,8 @@ class PSBTTest(BitcoinTestFramework):
# Mine a transaction that credits the offline address # Mine a transaction that credits the offline address
offline_addr = offline_node.getnewaddress(address_type="bech32m") offline_addr = offline_node.getnewaddress(address_type="bech32m")
online_addr = w2.getnewaddress(address_type="bech32m") online_addr = w2.getnewaddress(address_type="bech32m")
wonline.importaddress(offline_addr, label="", rescan=False) import_res = wonline.importdescriptors([{"desc": offline_node.getaddressinfo(offline_addr)["desc"], "timestamp": "now"}])
assert_equal(import_res[0]["success"], True)
mining_wallet = mining_node.get_wallet_rpc(self.default_wallet_name) mining_wallet = mining_node.get_wallet_rpc(self.default_wallet_name)
mining_wallet.sendtoaddress(address=offline_addr, amount=1.0) mining_wallet.sendtoaddress(address=offline_addr, amount=1.0)
self.generate(mining_node, nblocks=1, sync_fun=lambda: self.sync_all([online_node, mining_node])) self.generate(mining_node, nblocks=1, sync_fun=lambda: self.sync_all([online_node, mining_node]))
@@ -385,9 +387,19 @@ class PSBTTest(BitcoinTestFramework):
wmulti = self.nodes[2].get_wallet_rpc('wmulti') wmulti = self.nodes[2].get_wallet_rpc('wmulti')
# Create all the addresses # Create all the addresses
p2sh = wmulti.addmultisigaddress(2, [pubkey0, pubkey1, pubkey2], label="", address_type="legacy")["address"] p2sh_ms = wmulti.createmultisig(2, [pubkey0, pubkey1, pubkey2], address_type="legacy")
p2wsh = wmulti.addmultisigaddress(2, [pubkey0, pubkey1, pubkey2], label="", address_type="bech32")["address"] p2sh = p2sh_ms["address"]
p2sh_p2wsh = wmulti.addmultisigaddress(2, [pubkey0, pubkey1, pubkey2], label="", address_type="p2sh-segwit")["address"] p2wsh_ms = wmulti.createmultisig(2, [pubkey0, pubkey1, pubkey2], address_type="bech32")
p2wsh = p2wsh_ms["address"]
p2sh_p2wsh_ms = wmulti.createmultisig(2, [pubkey0, pubkey1, pubkey2], address_type="p2sh-segwit")
p2sh_p2wsh = p2sh_p2wsh_ms["address"]
import_res = wmulti.importdescriptors(
[
{"desc": p2sh_ms["descriptor"], "timestamp": "now"},
{"desc": p2wsh_ms["descriptor"], "timestamp": "now"},
{"desc": p2sh_p2wsh_ms["descriptor"], "timestamp": "now"},
])
assert_equal(all([r["success"] for r in import_res]), True)
p2wpkh = self.nodes[1].getnewaddress("", "bech32") p2wpkh = self.nodes[1].getnewaddress("", "bech32")
p2pkh = self.nodes[1].getnewaddress("", "legacy") p2pkh = self.nodes[1].getnewaddress("", "legacy")
p2sh_p2wpkh = self.nodes[1].getnewaddress("", "p2sh-segwit") p2sh_p2wpkh = self.nodes[1].getnewaddress("", "p2sh-segwit")
@@ -695,7 +707,7 @@ class PSBTTest(BitcoinTestFramework):
self.nodes[2].createwallet(wallet_name="wallet{}".format(i)) self.nodes[2].createwallet(wallet_name="wallet{}".format(i))
wrpc = self.nodes[2].get_wallet_rpc("wallet{}".format(i)) wrpc = self.nodes[2].get_wallet_rpc("wallet{}".format(i))
for key in signer['privkeys']: for key in signer['privkeys']:
wrpc.importprivkey(key) wallet_importprivkey(wrpc, key, "now")
signed_tx = wrpc.walletprocesspsbt(signer['psbt'], True, "ALL")['psbt'] signed_tx = wrpc.walletprocesspsbt(signer['psbt'], True, "ALL")['psbt']
assert_equal(signed_tx, signer['result']) assert_equal(signed_tx, signer['result'])
@@ -951,7 +963,7 @@ class PSBTTest(BitcoinTestFramework):
addr = self.nodes[0].deriveaddresses(desc)[0] addr = self.nodes[0].deriveaddresses(desc)[0]
self.nodes[0].sendtoaddress(addr, 10) self.nodes[0].sendtoaddress(addr, 10)
self.generate(self.nodes[0], 1) self.generate(self.nodes[0], 1)
self.nodes[0].importprivkey(privkey) wallet_importprivkey(self.nodes[0], privkey, "now")
psbt = watchonly.sendall([wallet.getnewaddress()])["psbt"] psbt = watchonly.sendall([wallet.getnewaddress()])["psbt"]
signed_tx = self.nodes[0].walletprocesspsbt(psbt) signed_tx = self.nodes[0].walletprocesspsbt(psbt)
@@ -35,6 +35,7 @@ from .util import (
initialize_datadir, initialize_datadir,
p2p_port, p2p_port,
wait_until_helper_internal, wait_until_helper_internal,
wallet_importprivkey,
) )
@@ -485,7 +486,7 @@ class BitcoinTestFramework(metaclass=BitcoinTestMetaClass):
n = self.nodes[node] n = self.nodes[node]
if wallet_name is not None: if wallet_name is not None:
n.createwallet(wallet_name=wallet_name, load_on_startup=True) n.createwallet(wallet_name=wallet_name, load_on_startup=True)
n.importprivkey(privkey=n.get_deterministic_priv_key().key, label='coinbase', rescan=True) wallet_importprivkey(n.get_wallet_rpc(wallet_name), n.get_deterministic_priv_key().key, 0, label="coinbase")
def run_test(self): def run_test(self):
"""Tests must override this method to define test logic""" """Tests must override this method to define test logic"""
+4 -82
View File
@@ -26,7 +26,6 @@ from .authproxy import (
JSONRPCException, JSONRPCException,
serialization_fallback, serialization_fallback,
) )
from .descriptors import descsum_create
from .messages import NODE_P2P_V2 from .messages import NODE_P2P_V2
from .p2p import P2P_SERVICES, P2P_SUBVERSION from .p2p import P2P_SERVICES, P2P_SUBVERSION
from .util import ( from .util import (
@@ -208,10 +207,10 @@ class TestNode():
def __getattr__(self, name): def __getattr__(self, name):
"""Dispatches any unrecognised messages to the RPC connection or a CLI instance.""" """Dispatches any unrecognised messages to the RPC connection or a CLI instance."""
if self.use_cli: if self.use_cli:
return getattr(RPCOverloadWrapper(self.cli), name) return getattr(self.cli, name)
else: else:
assert self.rpc_connected and self.rpc is not None, self._node_msg("Error: no RPC connection") assert self.rpc_connected and self.rpc is not None, self._node_msg("Error: no RPC connection")
return getattr(RPCOverloadWrapper(self.rpc), name) return getattr(self.rpc, name)
def start(self, extra_args=None, *, cwd=None, stdout=None, stderr=None, env=None, **kwargs): def start(self, extra_args=None, *, cwd=None, stdout=None, stderr=None, env=None, **kwargs):
"""Start the node.""" """Start the node."""
@@ -388,11 +387,11 @@ class TestNode():
def get_wallet_rpc(self, wallet_name): def get_wallet_rpc(self, wallet_name):
if self.use_cli: if self.use_cli:
return RPCOverloadWrapper(self.cli("-rpcwallet={}".format(wallet_name))) return self.cli("-rpcwallet={}".format(wallet_name))
else: else:
assert self.rpc_connected and self.rpc, self._node_msg("RPC not connected") assert self.rpc_connected and self.rpc, self._node_msg("RPC not connected")
wallet_path = "wallet/{}".format(urllib.parse.quote(wallet_name)) wallet_path = "wallet/{}".format(urllib.parse.quote(wallet_name))
return RPCOverloadWrapper(self.rpc / wallet_path) return self.rpc / wallet_path
def version_is_at_least(self, ver): def version_is_at_least(self, ver):
return self.version is None or self.version >= ver return self.version is None or self.version >= ver
@@ -937,80 +936,3 @@ class TestNodeCLI():
return json.loads(cli_stdout, parse_float=decimal.Decimal) return json.loads(cli_stdout, parse_float=decimal.Decimal)
except (json.JSONDecodeError, decimal.InvalidOperation): except (json.JSONDecodeError, decimal.InvalidOperation):
return cli_stdout.rstrip("\n") return cli_stdout.rstrip("\n")
class RPCOverloadWrapper():
def __init__(self, rpc):
self.rpc = rpc
def __getattr__(self, name):
return getattr(self.rpc, name)
def importprivkey(self, privkey, *, label=None, rescan=None):
wallet_info = self.getwalletinfo()
if 'descriptors' not in wallet_info or ('descriptors' in wallet_info and not wallet_info['descriptors']):
return self.__getattr__('importprivkey')(privkey, label, rescan)
desc = descsum_create('combo(' + privkey + ')')
req = [{
'desc': desc,
'timestamp': 0 if rescan else 'now',
'label': label if label else '',
}]
import_res = self.importdescriptors(req)
if not import_res[0]['success']:
raise JSONRPCException(import_res[0]['error'])
def addmultisigaddress(self, nrequired, keys, *, label=None, address_type=None):
wallet_info = self.getwalletinfo()
if 'descriptors' not in wallet_info or ('descriptors' in wallet_info and not wallet_info['descriptors']):
return self.__getattr__('addmultisigaddress')(nrequired, keys, label, address_type)
cms = self.createmultisig(nrequired, keys, address_type)
req = [{
'desc': cms['descriptor'],
'timestamp': 0,
'label': label if label else '',
}]
import_res = self.importdescriptors(req)
if not import_res[0]['success']:
raise JSONRPCException(import_res[0]['error'])
return cms
def importpubkey(self, pubkey, *, label=None, rescan=None):
wallet_info = self.getwalletinfo()
if 'descriptors' not in wallet_info or ('descriptors' in wallet_info and not wallet_info['descriptors']):
return self.__getattr__('importpubkey')(pubkey, label, rescan)
desc = descsum_create('combo(' + pubkey + ')')
req = [{
'desc': desc,
'timestamp': 0 if rescan else 'now',
'label': label if label else '',
}]
import_res = self.importdescriptors(req)
if not import_res[0]['success']:
raise JSONRPCException(import_res[0]['error'])
def importaddress(self, address, *, label=None, rescan=None, p2sh=None):
wallet_info = self.getwalletinfo()
if 'descriptors' not in wallet_info or ('descriptors' in wallet_info and not wallet_info['descriptors']):
return self.__getattr__('importaddress')(address, label, rescan, p2sh)
is_hex = False
try:
int(address ,16)
is_hex = True
desc = descsum_create('raw(' + address + ')')
except Exception:
desc = descsum_create('addr(' + address + ')')
reqs = [{
'desc': desc,
'timestamp': 0 if rescan else 'now',
'label': label if label else '',
}]
if is_hex and p2sh:
reqs.append({
'desc': descsum_create('p2sh(raw(' + address + '))'),
'timestamp': 0 if rescan else 'now',
'label': label if label else '',
})
import_res = self.importdescriptors(reqs)
for res in import_res:
if not res['success']:
raise JSONRPCException(res['error'])
+11
View File
@@ -20,6 +20,7 @@ import time
from . import coverage from . import coverage
from .authproxy import AuthServiceProxy, JSONRPCException from .authproxy import AuthServiceProxy, JSONRPCException
from .descriptors import descsum_create
from collections.abc import Callable from collections.abc import Callable
from typing import Optional, Union from typing import Optional, Union
@@ -608,3 +609,13 @@ def sync_txindex(test_framework, node):
sync_start = int(time.time()) sync_start = int(time.time())
test_framework.wait_until(lambda: node.getindexinfo("txindex")["txindex"]["synced"]) test_framework.wait_until(lambda: node.getindexinfo("txindex")["txindex"]["synced"])
test_framework.log.debug(f"Synced in {time.time() - sync_start} seconds") test_framework.log.debug(f"Synced in {time.time() - sync_start} seconds")
def wallet_importprivkey(wallet_rpc, privkey, timestamp, *, label=""):
desc = descsum_create("combo(" + privkey + ")")
req = [{
"desc": desc,
"timestamp": timestamp,
"label": label,
}]
import_res = wallet_rpc.importdescriptors(req)
assert_equal(import_res[0]["success"], True)
+5 -2
View File
@@ -14,7 +14,10 @@ from test_framework.blocktools import DIFF_1_N_BITS
from test_framework.key import ECKey from test_framework.key import ECKey
from test_framework.script_util import key_to_p2wpkh_script from test_framework.script_util import key_to_p2wpkh_script
from test_framework.test_framework import BitcoinTestFramework from test_framework.test_framework import BitcoinTestFramework
from test_framework.util import assert_equal from test_framework.util import (
assert_equal,
wallet_importprivkey,
)
from test_framework.wallet_util import bytes_to_wif from test_framework.wallet_util import bytes_to_wif
@@ -42,7 +45,7 @@ class SignetMinerTest(BitcoinTestFramework):
def run_test(self): def run_test(self):
node = self.nodes[0] node = self.nodes[0]
# import private key needed for signing block # import private key needed for signing block
node.importprivkey(bytes_to_wif(CHALLENGE_PRIVATE_KEY)) wallet_importprivkey(node, bytes_to_wif(CHALLENGE_PRIVATE_KEY), "now")
# generate block with signet miner tool # generate block with signet miner tool
base_dir = self.config["environment"]["SRCDIR"] base_dir = self.config["environment"]["SRCDIR"]
+6 -4
View File
@@ -260,9 +260,11 @@ class AddressTypeTest(BitcoinTestFramework):
else: else:
address = self.nodes[to_node].getnewaddress(address_type=address_type) address = self.nodes[to_node].getnewaddress(address_type=address_type)
else: else:
addr1 = self.nodes[to_node].getnewaddress() pubkey1 = self.nodes[to_node].getaddressinfo(self.nodes[to_node].getnewaddress())["pubkey"]
addr2 = self.nodes[to_node].getnewaddress() pubkey2 = self.nodes[to_node].getaddressinfo(self.nodes[to_node].getnewaddress())["pubkey"]
address = self.nodes[to_node].addmultisigaddress(2, [addr1, addr2])['address'] ms = self.nodes[to_node].createmultisig(2, [pubkey1, pubkey2])
import_res = self.nodes[to_node].importdescriptors([{"desc": ms["descriptor"], "timestamp": 0}])
assert_equal(import_res[0]["success"], True)
# Do some sanity checking on the created address # Do some sanity checking on the created address
if address_type is not None: if address_type is not None:
@@ -344,7 +346,7 @@ class AddressTypeTest(BitcoinTestFramework):
self.test_address(3, self.nodes[3].getrawchangeaddress(), multisig=False, typ='bech32') self.test_address(3, self.nodes[3].getrawchangeaddress(), multisig=False, typ='bech32')
self.log.info('test invalid address type arguments') self.log.info('test invalid address type arguments')
assert_raises_rpc_error(-5, "Unknown address type ''", self.nodes[3].addmultisigaddress, 2, [compressed_1, compressed_2], address_type="") assert_raises_rpc_error(-5, "Unknown address type ''", self.nodes[3].createmultisig, 2, [compressed_1, compressed_2], address_type="")
assert_raises_rpc_error(-5, "Unknown address type ''", self.nodes[3].getnewaddress, None, '') assert_raises_rpc_error(-5, "Unknown address type ''", self.nodes[3].getnewaddress, None, '')
assert_raises_rpc_error(-5, "Unknown address type ''", self.nodes[3].getrawchangeaddress, '') assert_raises_rpc_error(-5, "Unknown address type ''", self.nodes[3].getrawchangeaddress, '')
assert_raises_rpc_error(-5, "Unknown address type 'bech23'", self.nodes[3].getrawchangeaddress, 'bech23') assert_raises_rpc_error(-5, "Unknown address type 'bech23'", self.nodes[3].getrawchangeaddress, 'bech23')
+2 -1
View File
@@ -678,7 +678,8 @@ class WalletTest(BitcoinTestFramework):
self.generate(self.wallet, 1, sync_fun=self.no_op) self.generate(self.wallet, 1, sync_fun=self.no_op)
self.nodes[0].createwallet("watch_wallet", disable_private_keys=True) self.nodes[0].createwallet("watch_wallet", disable_private_keys=True)
watch_wallet = self.nodes[0].get_wallet_rpc("watch_wallet") watch_wallet = self.nodes[0].get_wallet_rpc("watch_wallet")
watch_wallet.importaddress(self.wallet.get_address()) import_res = watch_wallet.importdescriptors([{"desc": self.wallet.get_descriptor(), "timestamp": "now"}])
assert_equal(import_res[0]["success"], True)
# DEFAULT_ANCESTOR_LIMIT transactions off a confirmed tx should be fine # DEFAULT_ANCESTOR_LIMIT transactions off a confirmed tx should be fine
chain = self.wallet.create_self_transfer_chain(chain_length=DEFAULT_ANCESTOR_LIMIT) chain = self.wallet.create_self_transfer_chain(chain_length=DEFAULT_ANCESTOR_LIMIT)
+6 -4
View File
@@ -10,6 +10,7 @@ from test_framework.test_framework import BitcoinTestFramework
from test_framework.util import ( from test_framework.util import (
assert_equal, assert_equal,
assert_raises_rpc_error, assert_raises_rpc_error,
wallet_importprivkey,
) )
from test_framework.wallet_util import generate_keypair, WalletUnlock from test_framework.wallet_util import generate_keypair, WalletUnlock
@@ -41,11 +42,11 @@ class CreateWalletTest(BitcoinTestFramework):
w1 = node.get_wallet_rpc('w1') w1 = node.get_wallet_rpc('w1')
assert_raises_rpc_error(-4, "Error: This wallet has no available keys", w1.getnewaddress) assert_raises_rpc_error(-4, "Error: This wallet has no available keys", w1.getnewaddress)
assert_raises_rpc_error(-4, "Error: This wallet has no available keys", w1.getrawchangeaddress) assert_raises_rpc_error(-4, "Error: This wallet has no available keys", w1.getrawchangeaddress)
w1.importpubkey(w0.getaddressinfo(address1)['pubkey']) import_res = w1.importdescriptors([{"desc": w0.getaddressinfo(address1)['desc'], "timestamp": "now"}])
assert_equal(import_res[0]["success"], True)
self.log.info('Test that private keys cannot be imported') self.log.info('Test that private keys cannot be imported')
privkey, pubkey = generate_keypair(wif=True) privkey, pubkey = generate_keypair(wif=True)
assert_raises_rpc_error(-4, 'Cannot import private keys to a wallet with private keys disabled', w1.importprivkey, privkey)
result = w1.importdescriptors([{'desc': descsum_create('wpkh(' + privkey + ')'), 'timestamp': 'now'}]) result = w1.importdescriptors([{'desc': descsum_create('wpkh(' + privkey + ')'), 'timestamp': 'now'}])
assert not result[0]['success'] assert not result[0]['success']
assert 'warnings' not in result[0] assert 'warnings' not in result[0]
@@ -57,7 +58,8 @@ class CreateWalletTest(BitcoinTestFramework):
w2 = node.get_wallet_rpc('w2') w2 = node.get_wallet_rpc('w2')
assert_raises_rpc_error(-4, "Error: This wallet has no available keys", w2.getnewaddress) assert_raises_rpc_error(-4, "Error: This wallet has no available keys", w2.getnewaddress)
assert_raises_rpc_error(-4, "Error: This wallet has no available keys", w2.getrawchangeaddress) assert_raises_rpc_error(-4, "Error: This wallet has no available keys", w2.getrawchangeaddress)
w2.importpubkey(w0.getaddressinfo(address1)['pubkey']) import_res = w2.importdescriptors([{"desc": w0.getaddressinfo(address1)['desc'], "timestamp": "now"}])
assert_equal(import_res[0]["success"], True)
self.log.info("Test blank creation with private keys enabled.") self.log.info("Test blank creation with private keys enabled.")
self.nodes[0].createwallet(wallet_name='w3', disable_private_keys=False, blank=True) self.nodes[0].createwallet(wallet_name='w3', disable_private_keys=False, blank=True)
@@ -66,7 +68,7 @@ class CreateWalletTest(BitcoinTestFramework):
assert_raises_rpc_error(-4, "Error: This wallet has no available keys", w3.getnewaddress) assert_raises_rpc_error(-4, "Error: This wallet has no available keys", w3.getnewaddress)
assert_raises_rpc_error(-4, "Error: This wallet has no available keys", w3.getrawchangeaddress) assert_raises_rpc_error(-4, "Error: This wallet has no available keys", w3.getrawchangeaddress)
# Import private key # Import private key
w3.importprivkey(generate_keypair(wif=True)[0]) wallet_importprivkey(w3, generate_keypair(wif=True)[0], "now")
# Imported private keys are currently ignored by the keypool # Imported private keys are currently ignored by the keypool
assert_equal(w3.getwalletinfo()['keypoolsize'], 0) assert_equal(w3.getwalletinfo()['keypoolsize'], 0)
assert_raises_rpc_error(-4, "Error: This wallet has no available keys", w3.getnewaddress) assert_raises_rpc_error(-4, "Error: This wallet has no available keys", w3.getnewaddress)
+7 -5
View File
@@ -190,9 +190,9 @@ class RawTransactionsTest(BitcoinTestFramework):
self.nodes[3].createwallet(wallet_name="wwatch", disable_private_keys=True) self.nodes[3].createwallet(wallet_name="wwatch", disable_private_keys=True)
wwatch = self.nodes[3].get_wallet_rpc('wwatch') wwatch = self.nodes[3].get_wallet_rpc('wwatch')
watchonly_address = self.nodes[0].getnewaddress() watchonly_address = self.nodes[0].getnewaddress()
watchonly_pubkey = self.nodes[0].getaddressinfo(watchonly_address)["pubkey"]
self.watchonly_amount = Decimal(200) self.watchonly_amount = Decimal(200)
wwatch.importpubkey(watchonly_pubkey, label="", rescan=True) import_res = wwatch.importdescriptors([{"desc": self.nodes[0].getaddressinfo(watchonly_address)["desc"], "timestamp": "now"}])
assert_equal(import_res[0]["success"], True)
self.watchonly_utxo = self.create_outpoints(self.nodes[0], outputs=[{watchonly_address: self.watchonly_amount}])[0] self.watchonly_utxo = self.create_outpoints(self.nodes[0], outputs=[{watchonly_address: self.watchonly_amount}])[0]
# Lock UTXO so nodes[0] doesn't accidentally spend it # Lock UTXO so nodes[0] doesn't accidentally spend it
@@ -565,16 +565,18 @@ class RawTransactionsTest(BitcoinTestFramework):
self.nodes[2].createwallet(wallet_name='wmulti', disable_private_keys=True) self.nodes[2].createwallet(wallet_name='wmulti', disable_private_keys=True)
wmulti = self.nodes[2].get_wallet_rpc('wmulti') wmulti = self.nodes[2].get_wallet_rpc('wmulti')
w2 = self.nodes[2].get_wallet_rpc(self.default_wallet_name) w2 = self.nodes[2].get_wallet_rpc(self.default_wallet_name)
mSigObj = wmulti.addmultisigaddress( mSigObj = self.nodes[2].createmultisig(
2, 2,
[ [
addr1Obj['pubkey'], addr1Obj['pubkey'],
addr2Obj['pubkey'], addr2Obj['pubkey'],
] ]
)['address'] )
import_res = wmulti.importdescriptors([{"desc": mSigObj["descriptor"], "timestamp": "now"}])
assert_equal(import_res[0]["success"], True)
# Send 1.2 BTC to msig addr. # Send 1.2 BTC to msig addr.
self.nodes[0].sendtoaddress(mSigObj, 1.2) self.nodes[0].sendtoaddress(mSigObj["address"], 1.2)
self.generate(self.nodes[0], 1) self.generate(self.nodes[0], 1)
oldBalance = self.nodes[1].getbalance() oldBalance = self.nodes[1].getbalance()
+2 -1
View File
@@ -10,6 +10,7 @@ from test_framework.blocktools import COINBASE_MATURITY
from test_framework.test_framework import BitcoinTestFramework from test_framework.test_framework import BitcoinTestFramework
from test_framework.util import ( from test_framework.util import (
assert_equal, assert_equal,
wallet_importprivkey,
) )
@@ -39,7 +40,7 @@ class WalletHDTest(BitcoinTestFramework):
# Import a non-HD private key in the HD wallet # Import a non-HD private key in the HD wallet
non_hd_add = 'bcrt1qmevj8zfx0wdvp05cqwkmr6mxkfx60yezwjksmt' non_hd_add = 'bcrt1qmevj8zfx0wdvp05cqwkmr6mxkfx60yezwjksmt'
non_hd_key = 'cS9umN9w6cDMuRVYdbkfE4c7YUFLJRoXMfhQ569uY4odiQbVN8Rt' non_hd_key = 'cS9umN9w6cDMuRVYdbkfE4c7YUFLJRoXMfhQ569uY4odiQbVN8Rt'
self.nodes[1].importprivkey(non_hd_key) wallet_importprivkey(self.nodes[1], non_hd_key, "now")
# This should be enough to keep the master key and the non-HD key # This should be enough to keep the master key and the non-HD key
self.nodes[1].backupwallet(self.nodes[1].datadir_path / "hd.bak") self.nodes[1].backupwallet(self.nodes[1].datadir_path / "hd.bak")
+4 -3
View File
@@ -15,6 +15,7 @@ from test_framework.test_framework import BitcoinTestFramework
from test_framework.util import ( from test_framework.util import (
assert_equal, assert_equal,
assert_raises_rpc_error, assert_raises_rpc_error,
wallet_importprivkey,
) )
from test_framework.wallet_util import generate_keypair from test_framework.wallet_util import generate_keypair
@@ -38,7 +39,7 @@ class ImportPrunedFundsTest(BitcoinTestFramework):
# privkey # privkey
address3_privkey, address3_pubkey = generate_keypair(wif=True) address3_privkey, address3_pubkey = generate_keypair(wif=True)
address3 = key_to_p2wpkh(address3_pubkey) address3 = key_to_p2wpkh(address3_pubkey)
self.nodes[0].importprivkey(address3_privkey) wallet_importprivkey(self.nodes[0], address3_privkey, "now")
# Check only one address # Check only one address
address_info = self.nodes[0].getaddressinfo(address1) address_info = self.nodes[0].getaddressinfo(address1)
@@ -89,13 +90,13 @@ class ImportPrunedFundsTest(BitcoinTestFramework):
# Import with affiliated address with no rescan # Import with affiliated address with no rescan
self.nodes[1].createwallet('wwatch', disable_private_keys=True) self.nodes[1].createwallet('wwatch', disable_private_keys=True)
wwatch = self.nodes[1].get_wallet_rpc('wwatch') wwatch = self.nodes[1].get_wallet_rpc('wwatch')
wwatch.importaddress(address=address2, rescan=False) wwatch.importdescriptors([{"desc": self.nodes[0].getaddressinfo(address2)["desc"], "timestamp": "now"}])
wwatch.importprunedfunds(rawtransaction=rawtxn2, txoutproof=proof2) wwatch.importprunedfunds(rawtransaction=rawtxn2, txoutproof=proof2)
assert [tx for tx in wwatch.listtransactions(include_watchonly=True) if tx['txid'] == txnid2] assert [tx for tx in wwatch.listtransactions(include_watchonly=True) if tx['txid'] == txnid2]
# Import with private key with no rescan # Import with private key with no rescan
w1 = self.nodes[1].get_wallet_rpc(self.default_wallet_name) w1 = self.nodes[1].get_wallet_rpc(self.default_wallet_name)
w1.importprivkey(privkey=address3_privkey, rescan=False) wallet_importprivkey(w1, address3_privkey, "now")
w1.importprunedfunds(rawtxn3, proof3) w1.importprunedfunds(rawtxn3, proof3)
assert [tx for tx in w1.listtransactions() if tx['txid'] == txnid3] assert [tx for tx in w1.listtransactions() if tx['txid'] == txnid3]
balance3 = w1.getbalance() balance3 = w1.getbalance()
+7 -8
View File
@@ -12,6 +12,7 @@ RPCs tested are:
from collections import defaultdict from collections import defaultdict
from test_framework.blocktools import COINBASE_MATURITY from test_framework.blocktools import COINBASE_MATURITY
from test_framework.descriptors import descsum_create
from test_framework.test_framework import BitcoinTestFramework from test_framework.test_framework import BitcoinTestFramework
from test_framework.util import assert_equal, assert_raises_rpc_error from test_framework.util import assert_equal, assert_raises_rpc_error
from test_framework.wallet_util import test_address from test_framework.wallet_util import test_address
@@ -33,8 +34,6 @@ class WalletLabelsTest(BitcoinTestFramework):
[node.getnewaddress], [node.getnewaddress],
[node.setlabel, address], [node.setlabel, address],
[node.getaddressesbylabel], [node.getaddressesbylabel],
[node.importpubkey, pubkey],
[node.addmultisigaddress, 1, [pubkey]],
[node.getreceivedbylabel], [node.getreceivedbylabel],
[node.listsinceblock, node.getblockhash(0), 1, False, True, False], [node.listsinceblock, node.getblockhash(0), 1, False, True, False],
] ]
@@ -176,17 +175,17 @@ class WalletLabelsTest(BitcoinTestFramework):
} }
for l in BECH32_VALID: for l in BECH32_VALID:
ad = BECH32_VALID[l] ad = BECH32_VALID[l]
wallet_watch_only.importaddress(label=l, rescan=False, address=ad) import_res = wallet_watch_only.importdescriptors([{"desc": descsum_create(f"addr({ad})"), "timestamp": "now", "label": l}])
assert_equal(import_res[0]["success"], True)
self.generatetoaddress(node, 1, ad) self.generatetoaddress(node, 1, ad)
assert_equal(wallet_watch_only.getaddressesbylabel(label=l), {ad: {'purpose': 'receive'}}) assert_equal(wallet_watch_only.getaddressesbylabel(label=l), {ad: {'purpose': 'receive'}})
assert_equal(wallet_watch_only.getreceivedbylabel(label=l), 0) assert_equal(wallet_watch_only.getreceivedbylabel(label=l), 0)
for l in BECH32_INVALID: for l in BECH32_INVALID:
ad = BECH32_INVALID[l] ad = BECH32_INVALID[l]
assert_raises_rpc_error( import_res = wallet_watch_only.importdescriptors([{"desc": descsum_create(f"addr({ad})"), "timestamp": "now", "label": l}])
-5, assert_equal(import_res[0]["success"], False)
"Address is not valid", assert_equal(import_res[0]["error"]["code"], -5)
lambda: wallet_watch_only.importaddress(label=l, rescan=False, address=ad), assert_equal(import_res[0]["error"]["message"], "Address is not valid")
)
class Label: class Label:
+3 -2
View File
@@ -13,6 +13,7 @@ from test_framework.util import (
assert_array_result, assert_array_result,
assert_equal, assert_equal,
assert_raises_rpc_error, assert_raises_rpc_error,
wallet_importprivkey,
) )
from test_framework.wallet_util import generate_keypair from test_framework.wallet_util import generate_keypair
@@ -227,10 +228,10 @@ class ListSinceBlockTest(BitcoinTestFramework):
address = key_to_p2wpkh(pubkey) address = key_to_p2wpkh(pubkey)
self.nodes[2].sendtoaddress(address, 10) self.nodes[2].sendtoaddress(address, 10)
self.generate(self.nodes[2], 6) self.generate(self.nodes[2], 6)
self.nodes[2].importprivkey(privkey) wallet_importprivkey(self.nodes[2], privkey, "now")
utxos = self.nodes[2].listunspent() utxos = self.nodes[2].listunspent()
utxo = [u for u in utxos if u["address"] == address][0] utxo = [u for u in utxos if u["address"] == address][0]
self.nodes[1].importprivkey(privkey) wallet_importprivkey(self.nodes[1], privkey, "now")
# Split network into two # Split network into two
self.split_network() self.split_network()
+3 -3
View File
@@ -726,7 +726,7 @@ class WalletMigrationTest(BitcoinTestFramework):
send_to_script(script=script_sh_pkh, amount=2) send_to_script(script=script_sh_pkh, amount=2)
# Import script and check balance # Import script and check balance
wallet.rpc.importaddress(address=script_pkh.hex(), label="raw_spk", rescan=True, p2sh=True) wallet.importaddress(address=script_pkh.hex(), label="raw_spk", rescan=True, p2sh=True)
assert_equal(wallet.getbalances()['watchonly']['trusted'], 2) assert_equal(wallet.getbalances()['watchonly']['trusted'], 2)
# Craft wsh(pkh(key)) and send coins to it # Craft wsh(pkh(key)) and send coins to it
@@ -735,7 +735,7 @@ class WalletMigrationTest(BitcoinTestFramework):
send_to_script(script=script_wsh_pkh, amount=3) send_to_script(script=script_wsh_pkh, amount=3)
# Import script and check balance # Import script and check balance
wallet.rpc.importaddress(address=script_wsh_pkh.hex(), label="raw_spk2", rescan=True, p2sh=False) wallet.importaddress(address=script_wsh_pkh.hex(), label="raw_spk2", rescan=True, p2sh=False)
assert_equal(wallet.getbalances()['watchonly']['trusted'], 5) assert_equal(wallet.getbalances()['watchonly']['trusted'], 5)
# Import sh(pkh()) script, by using importaddress(), with the p2sh flag enabled. # Import sh(pkh()) script, by using importaddress(), with the p2sh flag enabled.
@@ -751,7 +751,7 @@ class WalletMigrationTest(BitcoinTestFramework):
# Note: 'importaddress()' will add two scripts, a valid one sh(pkh()) and an invalid one 'sh(sh(pkh()))'. # Note: 'importaddress()' will add two scripts, a valid one sh(pkh()) and an invalid one 'sh(sh(pkh()))'.
# Both of them will be stored with the same addressbook label. And only the latter one should # Both of them will be stored with the same addressbook label. And only the latter one should
# be discarded during migration. The first one must be migrated. # be discarded during migration. The first one must be migrated.
wallet.rpc.importaddress(address=script_sh_pkh.hex(), label=label_sh_pkh, rescan=False, p2sh=True) wallet.importaddress(address=script_sh_pkh.hex(), label=label_sh_pkh, rescan=False, p2sh=True)
# Migrate wallet and re-check balance # Migrate wallet and re-check balance
info_migration, wallet = self.migrate_and_get_rpc("raw_p2sh") info_migration, wallet = self.migrate_and_get_rpc("raw_p2sh")
+2 -4
View File
@@ -46,10 +46,8 @@ class WalletReindexTest(BitcoinTestFramework):
# Blank wallets don't have a birth time # Blank wallets don't have a birth time
assert 'birthtime' not in wallet_watch_only.getwalletinfo() assert 'birthtime' not in wallet_watch_only.getwalletinfo()
# For a descriptors wallet: Import address with timestamp=now. # Import address with timestamp=now.
# For legacy wallet: There is no way of importing a script/address with a custom time. The wallet always imports it with birthtime=1. wallet_watch_only.importdescriptors([{"desc": miner_wallet.getaddressinfo(wallet_addr)["desc"], "timestamp": "now"}])
# In both cases, disable rescan to not detect the transaction.
wallet_watch_only.importaddress(wallet_addr, rescan=False)
assert_equal(len(wallet_watch_only.listtransactions()), 0) assert_equal(len(wallet_watch_only.listtransactions()), 0)
# Depending on the wallet type, the birth time changes. # Depending on the wallet type, the birth time changes.
+2 -1
View File
@@ -45,7 +45,8 @@ class SimulateTxTest(BitcoinTestFramework):
address2 = w1.getnewaddress() address2 = w1.getnewaddress()
# Add address1 as watch-only to w2 # Add address1 as watch-only to w2
w2.importpubkey(pubkey=w1.getaddressinfo(address1)["pubkey"]) import_res = w2.importdescriptors([{"desc": w1.getaddressinfo(address1)["desc"], "timestamp": "now"}])
assert_equal(import_res[0]["success"], True)
tx1 = node.createrawtransaction([], [{address1: 5.0}]) tx1 = node.createrawtransaction([], [{address1: 5.0}])
tx2 = node.createrawtransaction([], [{address2: 10.0}]) tx2 = node.createrawtransaction([], [{address2: 10.0}])
@@ -50,15 +50,23 @@ class TransactionTimeRescanTest(BitcoinTestFramework):
# prepare the user wallet with 3 watch only addresses # prepare the user wallet with 3 watch only addresses
wo1 = usernode.getnewaddress() wo1 = usernode.getnewaddress()
wo1_desc = usernode.getaddressinfo(wo1)["desc"]
wo2 = usernode.getnewaddress() wo2 = usernode.getnewaddress()
wo2_desc = usernode.getaddressinfo(wo2)["desc"]
wo3 = usernode.getnewaddress() wo3 = usernode.getnewaddress()
wo3_desc = usernode.getaddressinfo(wo3)["desc"]
usernode.createwallet(wallet_name='wo', disable_private_keys=True) usernode.createwallet(wallet_name='wo', disable_private_keys=True)
wo_wallet = usernode.get_wallet_rpc('wo') wo_wallet = usernode.get_wallet_rpc('wo')
wo_wallet.importaddress(wo1) import_res = wo_wallet.importdescriptors(
wo_wallet.importaddress(wo2) [
wo_wallet.importaddress(wo3) {"desc": wo1_desc, "timestamp": "now"},
{"desc": wo2_desc, "timestamp": "now"},
{"desc": wo3_desc, "timestamp": "now"},
]
)
assert_equal(all([r["success"] for r in import_res]), True)
self.log.info('Start transactions') self.log.info('Start transactions')
@@ -124,16 +132,20 @@ class TransactionTimeRescanTest(BitcoinTestFramework):
restorenode.createwallet(wallet_name='wo', disable_private_keys=True) restorenode.createwallet(wallet_name='wo', disable_private_keys=True)
restorewo_wallet = restorenode.get_wallet_rpc('wo') restorewo_wallet = restorenode.get_wallet_rpc('wo')
# for descriptor wallets, the test framework maps the importaddress RPC to the # importdescriptors with "timestamp": "now" always rescans
# importdescriptors RPC (with argument 'timestamp'='now'), which always rescans
# blocks of the past 2 hours, based on the current MTP timestamp; in order to avoid # blocks of the past 2 hours, based on the current MTP timestamp; in order to avoid
# importing the last address (wo3), we advance the time further and generate 10 blocks # importing the last address (wo3), we advance the time further and generate 10 blocks
set_node_times(self.nodes, cur_time + ten_days + ten_days + ten_days + ten_days) set_node_times(self.nodes, cur_time + ten_days + ten_days + ten_days + ten_days)
self.generatetoaddress(minernode, 10, m1) self.generatetoaddress(minernode, 10, m1)
restorewo_wallet.importaddress(wo1, rescan=False) import_res = restorewo_wallet.importdescriptors(
restorewo_wallet.importaddress(wo2, rescan=False) [
restorewo_wallet.importaddress(wo3, rescan=False) {"desc": wo1_desc, "timestamp": "now"},
{"desc": wo2_desc, "timestamp": "now"},
{"desc": wo3_desc, "timestamp": "now"},
]
)
assert_equal(all([r["success"] for r in import_res]), True)
# check user has 0 balance and no transactions # check user has 0 balance and no transactions
assert_equal(restorewo_wallet.getbalance(), 0) assert_equal(restorewo_wallet.getbalance(), 0)