mirror of
https://github.com/bitcoin/bitcoin.git
synced 2026-04-24 05:52:08 +02:00
Add a --descriptors option to various tests
Adds a --descriptors option globally to the test framework. This will make the test create and use descriptor wallets. However some tests may not work with this. Some tests are modified to work with --descriptors and run with that option in test_runer: * wallet_basic.py * wallet_encryption.py * wallet_keypool.py * wallet_keypool_topup.py * wallet_labels.py * wallet_avoidreuse.py
This commit is contained in:
@@ -8,6 +8,8 @@ keys, and is trivially vulnerable to side channel attacks. Do not use for
|
||||
anything but tests."""
|
||||
import random
|
||||
|
||||
from .address import byte_to_base58
|
||||
|
||||
def modinv(a, n):
|
||||
"""Compute the modular inverse of a modulo n
|
||||
|
||||
@@ -384,3 +386,14 @@ class ECKey():
|
||||
rb = r.to_bytes((r.bit_length() + 8) // 8, 'big')
|
||||
sb = s.to_bytes((s.bit_length() + 8) // 8, 'big')
|
||||
return b'\x30' + bytes([4 + len(rb) + len(sb), 2, len(rb)]) + rb + bytes([2, len(sb)]) + sb
|
||||
|
||||
def bytes_to_wif(b, compressed=True):
|
||||
if compressed:
|
||||
b += b'\x01'
|
||||
return byte_to_base58(b, 239)
|
||||
|
||||
def generate_wif_key():
|
||||
# Makes a WIF privkey for imports
|
||||
k = ECKey()
|
||||
k.generate()
|
||||
return bytes_to_wif(k.get_bytes(), k.is_compressed)
|
||||
|
||||
@@ -165,6 +165,8 @@ class BitcoinTestFramework(metaclass=BitcoinTestMetaClass):
|
||||
help="run nodes under the valgrind memory error detector: expect at least a ~10x slowdown, valgrind 3.14 or later required")
|
||||
parser.add_argument("--randomseed", type=int,
|
||||
help="set a random seed for deterministically reproducing a previous test run")
|
||||
parser.add_argument("--descriptors", default=False, action="store_true",
|
||||
help="Run test using a descriptor wallet")
|
||||
self.add_options(parser)
|
||||
self.options = parser.parse_args()
|
||||
|
||||
@@ -333,11 +335,23 @@ class BitcoinTestFramework(metaclass=BitcoinTestMetaClass):
|
||||
|
||||
def setup_nodes(self):
|
||||
"""Override this method to customize test node setup"""
|
||||
extra_args = None
|
||||
extra_args = [[]] * self.num_nodes
|
||||
wallets = [[]] * self.num_nodes
|
||||
if hasattr(self, "extra_args"):
|
||||
extra_args = self.extra_args
|
||||
wallets = [[x for x in eargs if x.startswith('-wallet=')] for eargs in extra_args]
|
||||
extra_args = [x + ['-nowallet'] for x in extra_args]
|
||||
self.add_nodes(self.num_nodes, extra_args)
|
||||
self.start_nodes()
|
||||
for i, n in enumerate(self.nodes):
|
||||
n.extra_args.pop()
|
||||
if '-wallet=0' in n.extra_args or '-nowallet' in n.extra_args or '-disablewallet' in n.extra_args or not self.is_wallet_compiled():
|
||||
continue
|
||||
if '-wallet=' not in wallets[i] and not any([x.startswith('-wallet=') for x in wallets[i]]):
|
||||
wallets[i].append('-wallet=')
|
||||
for w in wallets[i]:
|
||||
wallet_name = w.split('=', 1)[1]
|
||||
n.createwallet(wallet_name=wallet_name, descriptors=self.options.descriptors)
|
||||
self.import_deterministic_coinbase_privkeys()
|
||||
if not self.setup_clean_chain:
|
||||
for n in self.nodes:
|
||||
@@ -408,6 +422,7 @@ class BitcoinTestFramework(metaclass=BitcoinTestMetaClass):
|
||||
use_cli=self.options.usecli,
|
||||
start_perf=self.options.perf,
|
||||
use_valgrind=self.options.valgrind,
|
||||
descriptors=self.options.descriptors,
|
||||
))
|
||||
|
||||
def start_node(self, i, *args, **kwargs):
|
||||
@@ -547,6 +562,7 @@ class BitcoinTestFramework(metaclass=BitcoinTestMetaClass):
|
||||
bitcoin_cli=self.options.bitcoincli,
|
||||
coverage_dir=None,
|
||||
cwd=self.options.tmpdir,
|
||||
descriptors=self.options.descriptors,
|
||||
))
|
||||
self.start_node(CACHE_NODE_ID)
|
||||
cache_node = self.nodes[CACHE_NODE_ID]
|
||||
|
||||
@@ -62,7 +62,7 @@ class TestNode():
|
||||
To make things easier for the test writer, any unrecognised messages will
|
||||
be dispatched to the RPC connection."""
|
||||
|
||||
def __init__(self, i, datadir, *, chain, rpchost, timewait, bitcoind, bitcoin_cli, coverage_dir, cwd, extra_conf=None, extra_args=None, use_cli=False, start_perf=False, use_valgrind=False, version=None):
|
||||
def __init__(self, i, datadir, *, chain, rpchost, timewait, bitcoind, bitcoin_cli, coverage_dir, cwd, extra_conf=None, extra_args=None, use_cli=False, start_perf=False, use_valgrind=False, version=None, descriptors=False):
|
||||
"""
|
||||
Kwargs:
|
||||
start_perf (bool): If True, begin profiling the node with `perf` as soon as
|
||||
@@ -80,6 +80,7 @@ class TestNode():
|
||||
self.binary = bitcoind
|
||||
self.coverage_dir = coverage_dir
|
||||
self.cwd = cwd
|
||||
self.descriptors = descriptors
|
||||
if extra_conf is not None:
|
||||
append_config(datadir, extra_conf)
|
||||
# Most callers will just need to add extra args to the standard list below.
|
||||
@@ -171,10 +172,10 @@ class TestNode():
|
||||
def __getattr__(self, name):
|
||||
"""Dispatches any unrecognised messages to the RPC connection or a CLI instance."""
|
||||
if self.use_cli:
|
||||
return getattr(RPCOverloadWrapper(self.cli, True), name)
|
||||
return getattr(RPCOverloadWrapper(self.cli, True, self.descriptors), name)
|
||||
else:
|
||||
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(RPCOverloadWrapper(self.rpc, descriptors=self.descriptors), name)
|
||||
|
||||
def start(self, extra_args=None, *, cwd=None, stdout=None, stderr=None, **kwargs):
|
||||
"""Start the node."""
|
||||
@@ -266,11 +267,11 @@ class TestNode():
|
||||
|
||||
def get_wallet_rpc(self, wallet_name):
|
||||
if self.use_cli:
|
||||
return RPCOverloadWrapper(self.cli("-rpcwallet={}".format(wallet_name)), True)
|
||||
return RPCOverloadWrapper(self.cli("-rpcwallet={}".format(wallet_name)), True, self.descriptors)
|
||||
else:
|
||||
assert self.rpc_connected and self.rpc, self._node_msg("RPC not connected")
|
||||
wallet_path = "wallet/{}".format(urllib.parse.quote(wallet_name))
|
||||
return RPCOverloadWrapper(self.rpc / wallet_path)
|
||||
return RPCOverloadWrapper(self.rpc / wallet_path, descriptors=self.descriptors)
|
||||
|
||||
def stop_node(self, expected_stderr='', wait=0):
|
||||
"""Stop the node."""
|
||||
@@ -598,13 +599,28 @@ class TestNodeCLI():
|
||||
return cli_stdout.rstrip("\n")
|
||||
|
||||
class RPCOverloadWrapper():
|
||||
def __init__(self, rpc, cli=False):
|
||||
def __init__(self, rpc, cli=False, descriptors=False):
|
||||
self.rpc = rpc
|
||||
self.is_cli = cli
|
||||
self.descriptors = descriptors
|
||||
|
||||
def __getattr__(self, name):
|
||||
return getattr(self.rpc, name)
|
||||
|
||||
def createwallet(self, wallet_name, disable_private_keys=None, blank=None, passphrase=None, avoid_reuse=None, descriptors=None):
|
||||
if self.is_cli:
|
||||
if disable_private_keys is None:
|
||||
disable_private_keys = 'null'
|
||||
if blank is None:
|
||||
blank = 'null'
|
||||
if passphrase is None:
|
||||
passphrase = ''
|
||||
if avoid_reuse is None:
|
||||
avoid_reuse = 'null'
|
||||
if descriptors is None:
|
||||
descriptors = self.descriptors
|
||||
return self.__getattr__('createwallet')(wallet_name, disable_private_keys, blank, passphrase, avoid_reuse, descriptors)
|
||||
|
||||
def importprivkey(self, privkey, label=None, rescan=None):
|
||||
wallet_info = self.getwalletinfo()
|
||||
if self.is_cli:
|
||||
|
||||
Reference in New Issue
Block a user