Skip to content

Commit a6b1bf6

Browse files
committed
Merge bitcoin#20267: Disable and fix tests for when BDB is not compiled
49797c3 tests: Disable bdb dump test when no bdb (Andrew Chow) 1194cf9 Fix wallet_send.py wallet setup to work with descriptors (Andrew Chow) fbaea7b Require legacy wallet for wallet_upgradewallet.py (Andrew Chow) b1b679e Explicitly mark legacy wallet tests as such (Andrew Chow) 09514e1 Setup wallets for interface_zmq.py (Andrew Chow) 4d03ef9 Use MiniWallet in rpc_net.py (Andrew Chow) 4de2382 Setup wallets for interface_bitcoin_cli.py (Andrew Chow) 7c71c62 Setup wallets with descriptors for feature_notifications (Andrew Chow) 1f1bef8 Have feature_filelock.py test both bdb and sqlite, depending on compiled (Andrew Chow) c77975a Disable upgrades tests that require BDB if BDB is not compiled (Andrew Chow) 1f20cac Disable wallet_descriptor.py bdb format check if BDB is not compiled (Andrew Chow) 3641597 tests: Don't make any wallets unless wallet is required (Andrew Chow) b9b88f5 Skip legacy wallet reliant tests if BDB is not compiled (Andrew Chow) 6f36242 tests: Set descriptors default based on compilation (Andrew Chow) Pull request description: This PR fixes tests for when BDB is not compiled. Tests which rely on or test legacy wallet behavior are disabled and skipped when BDB is not compiled. For the components of some tests that are for legacy wallet things, those parts of the tests are skipped. For the majority of tests, changes are made so that they can be run with either legacy wallets or descriptor wallets without materially effecting the test. Most tests only need the wallet for balance and transactions, so the type of wallet is not an important part of those tests. Additionally, some tests are wallet agnostic and modified to instead use the test framework's MiniWallet. ACKs for top commit: laanwj: ACK 49797c3 ryanofsky: Code review ACK 49797c3. Only change since last review is dropping last commit. Previous review w/ suggestions for future followup is bitcoin#20267 (review) Tree-SHA512: 69659f8a81fb437ecbca962f4082c12835282dbf1fba7d9952f727a49e01981d749af9b09feda1c8ca737516c7d7a08ef17e782795df3fa69892d5021b41c1ed
2 parents 3931732 + 49797c3 commit a6b1bf6

12 files changed

+270
-152
lines changed

test/functional/feature_backwards_compatibility.py

+68-66
Original file line numberDiff line numberDiff line change
@@ -354,73 +354,75 @@ def run_test(self):
354354
hdkeypath = v17_info["hdkeypath"]
355355
pubkey = v17_info["pubkey"]
356356

357-
# Copy the 0.16 wallet to the last Bitcoin Core version and open it:
358-
shutil.copyfile(
359-
os.path.join(node_v16_wallets_dir, "wallets/u1_v16"),
360-
os.path.join(node_master_wallets_dir, "u1_v16")
361-
)
362-
load_res = node_master.loadwallet("u1_v16")
363-
# Make sure this wallet opens without warnings. See https://github.com/bitcoin/bitcoin/pull/19054
364-
assert_equal(load_res['warning'], '')
365-
wallet = node_master.get_wallet_rpc("u1_v16")
366-
info = wallet.getaddressinfo(v16_addr)
367-
descriptor = "wpkh([" + info["hdmasterfingerprint"] + hdkeypath[1:] + "]" + v16_pubkey + ")"
368-
assert_equal(info["desc"], descsum_create(descriptor))
369-
370-
# Now copy that same wallet back to 0.16 to make sure no automatic upgrade breaks it
371-
os.remove(os.path.join(node_v16_wallets_dir, "wallets/u1_v16"))
372-
shutil.copyfile(
373-
os.path.join(node_master_wallets_dir, "u1_v16"),
374-
os.path.join(node_v16_wallets_dir, "wallets/u1_v16")
375-
)
376-
self.start_node(-1, extra_args=["-wallet=u1_v16"])
377-
wallet = node_v16.get_wallet_rpc("u1_v16")
378-
info = wallet.validateaddress(v16_addr)
379-
assert_equal(info, v16_info)
380-
381-
# Copy the 0.17 wallet to the last Bitcoin Core version and open it:
382-
node_v17.unloadwallet("u1_v17")
383-
shutil.copytree(
384-
os.path.join(node_v17_wallets_dir, "u1_v17"),
385-
os.path.join(node_master_wallets_dir, "u1_v17")
386-
)
387-
node_master.loadwallet("u1_v17")
388-
wallet = node_master.get_wallet_rpc("u1_v17")
389-
info = wallet.getaddressinfo(address)
390-
descriptor = "wpkh([" + info["hdmasterfingerprint"] + hdkeypath[1:] + "]" + pubkey + ")"
391-
assert_equal(info["desc"], descsum_create(descriptor))
392-
393-
# Now copy that same wallet back to 0.17 to make sure no automatic upgrade breaks it
394-
node_master.unloadwallet("u1_v17")
395-
shutil.rmtree(os.path.join(node_v17_wallets_dir, "u1_v17"))
396-
shutil.copytree(
397-
os.path.join(node_master_wallets_dir, "u1_v17"),
398-
os.path.join(node_v17_wallets_dir, "u1_v17")
399-
)
400-
node_v17.loadwallet("u1_v17")
401-
wallet = node_v17.get_wallet_rpc("u1_v17")
402-
info = wallet.getaddressinfo(address)
403-
assert_equal(info, v17_info)
404-
405-
# Copy the 0.19 wallet to the last Bitcoin Core version and open it:
406-
shutil.copytree(
407-
os.path.join(node_v19_wallets_dir, "w1_v19"),
408-
os.path.join(node_master_wallets_dir, "w1_v19")
409-
)
410-
node_master.loadwallet("w1_v19")
411-
wallet = node_master.get_wallet_rpc("w1_v19")
412-
assert wallet.getaddressinfo(address_18075)["solvable"]
357+
if self.is_bdb_compiled():
358+
# Old wallets are BDB and will only work if BDB is compiled
359+
# Copy the 0.16 wallet to the last Bitcoin Core version and open it:
360+
shutil.copyfile(
361+
os.path.join(node_v16_wallets_dir, "wallets/u1_v16"),
362+
os.path.join(node_master_wallets_dir, "u1_v16")
363+
)
364+
load_res = node_master.loadwallet("u1_v16")
365+
# Make sure this wallet opens without warnings. See https://github.com/bitcoin/bitcoin/pull/19054
366+
assert_equal(load_res['warning'], '')
367+
wallet = node_master.get_wallet_rpc("u1_v16")
368+
info = wallet.getaddressinfo(v16_addr)
369+
descriptor = "wpkh([" + info["hdmasterfingerprint"] + hdkeypath[1:] + "]" + v16_pubkey + ")"
370+
assert_equal(info["desc"], descsum_create(descriptor))
371+
372+
# Now copy that same wallet back to 0.16 to make sure no automatic upgrade breaks it
373+
os.remove(os.path.join(node_v16_wallets_dir, "wallets/u1_v16"))
374+
shutil.copyfile(
375+
os.path.join(node_master_wallets_dir, "u1_v16"),
376+
os.path.join(node_v16_wallets_dir, "wallets/u1_v16")
377+
)
378+
self.start_node(-1, extra_args=["-wallet=u1_v16"])
379+
wallet = node_v16.get_wallet_rpc("u1_v16")
380+
info = wallet.validateaddress(v16_addr)
381+
assert_equal(info, v16_info)
413382

414-
# Now copy that same wallet back to 0.19 to make sure no automatic upgrade breaks it
415-
node_master.unloadwallet("w1_v19")
416-
shutil.rmtree(os.path.join(node_v19_wallets_dir, "w1_v19"))
417-
shutil.copytree(
418-
os.path.join(node_master_wallets_dir, "w1_v19"),
419-
os.path.join(node_v19_wallets_dir, "w1_v19")
420-
)
421-
node_v19.loadwallet("w1_v19")
422-
wallet = node_v19.get_wallet_rpc("w1_v19")
423-
assert wallet.getaddressinfo(address_18075)["solvable"]
383+
# Copy the 0.17 wallet to the last Bitcoin Core version and open it:
384+
node_v17.unloadwallet("u1_v17")
385+
shutil.copytree(
386+
os.path.join(node_v17_wallets_dir, "u1_v17"),
387+
os.path.join(node_master_wallets_dir, "u1_v17")
388+
)
389+
node_master.loadwallet("u1_v17")
390+
wallet = node_master.get_wallet_rpc("u1_v17")
391+
info = wallet.getaddressinfo(address)
392+
descriptor = "wpkh([" + info["hdmasterfingerprint"] + hdkeypath[1:] + "]" + pubkey + ")"
393+
assert_equal(info["desc"], descsum_create(descriptor))
394+
395+
# Now copy that same wallet back to 0.17 to make sure no automatic upgrade breaks it
396+
node_master.unloadwallet("u1_v17")
397+
shutil.rmtree(os.path.join(node_v17_wallets_dir, "u1_v17"))
398+
shutil.copytree(
399+
os.path.join(node_master_wallets_dir, "u1_v17"),
400+
os.path.join(node_v17_wallets_dir, "u1_v17")
401+
)
402+
node_v17.loadwallet("u1_v17")
403+
wallet = node_v17.get_wallet_rpc("u1_v17")
404+
info = wallet.getaddressinfo(address)
405+
assert_equal(info, v17_info)
406+
407+
# Copy the 0.19 wallet to the last Bitcoin Core version and open it:
408+
shutil.copytree(
409+
os.path.join(node_v19_wallets_dir, "w1_v19"),
410+
os.path.join(node_master_wallets_dir, "w1_v19")
411+
)
412+
node_master.loadwallet("w1_v19")
413+
wallet = node_master.get_wallet_rpc("w1_v19")
414+
assert wallet.getaddressinfo(address_18075)["solvable"]
415+
416+
# Now copy that same wallet back to 0.19 to make sure no automatic upgrade breaks it
417+
node_master.unloadwallet("w1_v19")
418+
shutil.rmtree(os.path.join(node_v19_wallets_dir, "w1_v19"))
419+
shutil.copytree(
420+
os.path.join(node_master_wallets_dir, "w1_v19"),
421+
os.path.join(node_v19_wallets_dir, "w1_v19")
422+
)
423+
node_v19.loadwallet("w1_v19")
424+
wallet = node_v19.get_wallet_rpc("w1_v19")
425+
assert wallet.getaddressinfo(address_18075)["solvable"]
424426

425427
if __name__ == '__main__':
426428
BackwardsCompatibilityTest().main()

test/functional/feature_filelock.py

+17-5
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,8 @@
44
# file COPYING or http://www.opensource.org/licenses/mit-license.php.
55
"""Check that it's not possible to start a second bitcoind instance using the same datadir or wallet."""
66
import os
7+
import random
8+
import string
79

810
from test_framework.test_framework import BitcoinTestFramework
911
from test_framework.test_node import ErrorMatch
@@ -27,11 +29,21 @@ def run_test(self):
2729
self.nodes[1].assert_start_raises_init_error(extra_args=['-datadir={}'.format(self.nodes[0].datadir), '-noserver'], expected_msg=expected_msg)
2830

2931
if self.is_wallet_compiled():
30-
self.nodes[0].createwallet(self.default_wallet_name)
31-
wallet_dir = os.path.join(datadir, 'wallets')
32-
self.log.info("Check that we can't start a second bitcoind instance using the same wallet")
33-
expected_msg = "Error: Error initializing wallet database environment"
34-
self.nodes[1].assert_start_raises_init_error(extra_args=['-walletdir={}'.format(wallet_dir), '-wallet=' + self.default_wallet_name, '-noserver'], expected_msg=expected_msg, match=ErrorMatch.PARTIAL_REGEX)
32+
def check_wallet_filelock(descriptors):
33+
wallet_name = ''.join([random.choice(string.ascii_lowercase) for _ in range(6)])
34+
self.nodes[0].createwallet(wallet_name=wallet_name, descriptors=descriptors)
35+
wallet_dir = os.path.join(datadir, 'wallets')
36+
self.log.info("Check that we can't start a second bitcoind instance using the same wallet")
37+
if descriptors:
38+
expected_msg = "Error: SQLiteDatabase: Unable to obtain an exclusive lock on the database, is it being used by another bitcoind?"
39+
else:
40+
expected_msg = "Error: Error initializing wallet database environment"
41+
self.nodes[1].assert_start_raises_init_error(extra_args=['-walletdir={}'.format(wallet_dir), '-wallet=' + wallet_name, '-noserver'], expected_msg=expected_msg, match=ErrorMatch.PARTIAL_REGEX)
42+
43+
if self.is_bdb_compiled():
44+
check_wallet_filelock(False)
45+
if self.is_sqlite_compiled():
46+
check_wallet_filelock(True)
3547

3648
if __name__ == '__main__':
3749
FilelockTest().main()

test/functional/feature_notifications.py

+29-5
Original file line numberDiff line numberDiff line change
@@ -5,11 +5,11 @@
55
"""Test the -alertnotify, -blocknotify and -walletnotify options."""
66
import os
77

8-
from test_framework.address import ADDRESS_BCRT1_UNSPENDABLE, keyhash_to_p2pkh
8+
from test_framework.address import ADDRESS_BCRT1_UNSPENDABLE
9+
from test_framework.descriptors import descsum_create
910
from test_framework.test_framework import BitcoinTestFramework
1011
from test_framework.util import (
1112
assert_equal,
12-
hex_str_to_bytes,
1313
)
1414

1515
# Linux allow all characters other than \x00
@@ -49,6 +49,31 @@ def setup_network(self):
4949
super().setup_network()
5050

5151
def run_test(self):
52+
if self.is_wallet_compiled():
53+
# Setup the descriptors to be imported to the wallet
54+
seed = "cTdGmKFWpbvpKQ7ejrdzqYT2hhjyb3GPHnLAK7wdi5Em67YLwSm9"
55+
xpriv = "tprv8ZgxMBicQKsPfHCsTwkiM1KT56RXbGGTqvc2hgqzycpwbHqqpcajQeMRZoBD35kW4RtyCemu6j34Ku5DEspmgjKdt2qe4SvRch5Kk8B8A2v"
56+
desc_imports = [{
57+
"desc": descsum_create("wpkh(" + xpriv + "/0/*)"),
58+
"timestamp": 0,
59+
"active": True,
60+
"keypool": True,
61+
},{
62+
"desc": descsum_create("wpkh(" + xpriv + "/1/*)"),
63+
"timestamp": 0,
64+
"active": True,
65+
"keypool": True,
66+
"internal": True,
67+
}]
68+
# Make the wallets and import the descriptors
69+
# Ensures that node 0 and node 1 share the same wallet for the conflicting transaction tests below.
70+
for i, name in enumerate(self.wallet_names):
71+
self.nodes[i].createwallet(wallet_name=name, descriptors=self.options.descriptors, blank=True, load_on_startup=True)
72+
if self.options.descriptors:
73+
self.nodes[i].importdescriptors(desc_imports)
74+
else:
75+
self.nodes[i].sethdseed(True, seed)
76+
5277
self.log.info("test -blocknotify")
5378
block_count = 10
5479
blocks = self.nodes[1].generatetoaddress(block_count, self.nodes[1].getnewaddress() if self.is_wallet_compiled() else ADDRESS_BCRT1_UNSPENDABLE)
@@ -84,11 +109,10 @@ def run_test(self):
84109
for tx_file in os.listdir(self.walletnotify_dir):
85110
os.remove(os.path.join(self.walletnotify_dir, tx_file))
86111

87-
# Conflicting transactions tests. Give node 0 same wallet seed as
88-
# node 1, generate spends from node 0, and check notifications
112+
# Conflicting transactions tests.
113+
# Generate spends from node 0, and check notifications
89114
# triggered by node 1
90115
self.log.info("test -walletnotify with conflicting transactions")
91-
self.nodes[0].sethdseed(seed=self.nodes[1].dumpprivkey(keyhash_to_p2pkh(hex_str_to_bytes(self.nodes[1].getwalletinfo()['hdseedid'])[::-1])))
92116
self.nodes[0].rescanblockchain()
93117
self.nodes[0].generatetoaddress(100, ADDRESS_BCRT1_UNSPENDABLE)
94118
self.sync_blocks()

test/functional/interface_bitcoin_cli.py

+2
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,8 @@ class TestBitcoinCli(BitcoinTestFramework):
2929
def set_test_params(self):
3030
self.setup_clean_chain = True
3131
self.num_nodes = 1
32+
if self.is_wallet_compiled():
33+
self.requires_wallet = True
3234

3335
def skip_test_if_missing_module(self):
3436
self.skip_if_no_cli()

test/functional/interface_zmq.py

+2
Original file line numberDiff line numberDiff line change
@@ -62,6 +62,8 @@ def receive_sequence(self):
6262
class ZMQTest (BitcoinTestFramework):
6363
def set_test_params(self):
6464
self.num_nodes = 2
65+
if self.is_wallet_compiled():
66+
self.requires_wallet = True
6567

6668
def skip_test_if_missing_module(self):
6769
self.skip_if_no_py3_zmq()

test/functional/rpc_net.py

+5-2
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@
2525
assert_raises_rpc_error,
2626
p2p_port,
2727
)
28+
from test_framework.wallet import MiniWallet
2829

2930

3031
def assert_net_servicesnames(servicesflag, servicenames):
@@ -48,6 +49,9 @@ def set_test_params(self):
4849
self.supports_cli = False
4950

5051
def run_test(self):
52+
# We need miniwallet to make a transaction
53+
self.wallet = MiniWallet(self.nodes[0])
54+
self.wallet.generate(1)
5155
# Get out of IBD for the minfeefilter and getpeerinfo tests.
5256
self.nodes[0].generate(101)
5357

@@ -74,8 +78,7 @@ def test_connection_count(self):
7478
def test_getpeerinfo(self):
7579
self.log.info("Test getpeerinfo")
7680
# Create a few getpeerinfo last_block/last_transaction values.
77-
if self.is_wallet_compiled():
78-
self.nodes[0].sendtoaddress(self.nodes[1].getnewaddress(), 1)
81+
self.wallet.send_self_transfer(from_node=self.nodes[0]) # Make a transaction so we can see it in the getpeerinfo results
7982
self.nodes[1].generate(1)
8083
self.sync_all()
8184
time_now = int(time.time())

test/functional/test_framework/test_framework.py

+26-6
Original file line numberDiff line numberDiff line change
@@ -108,6 +108,9 @@ def __init__(self):
108108
# skipped. If list is truncated, wallet creation is skipped and keys
109109
# are not imported.
110110
self.wallet_names = None
111+
# By default the wallet is not required. Set to true by skip_if_no_wallet().
112+
# When False, we ignore wallet_names regardless of what it is.
113+
self.requires_wallet = False
111114
self.set_test_params()
112115
assert self.wallet_names is None or len(self.wallet_names) <= self.num_nodes
113116
if self.options.timeout_factor == 0 :
@@ -184,15 +187,30 @@ def parse_args(self):
184187
parser.add_argument('--timeout-factor', dest="timeout_factor", type=float, default=1.0, help='adjust test timeouts by a factor. Setting it to 0 disables all timeouts')
185188

186189
group = parser.add_mutually_exclusive_group()
187-
group.add_argument("--descriptors", default=False, action="store_true",
190+
group.add_argument("--descriptors", action='store_const', const=True,
188191
help="Run test using a descriptor wallet", dest='descriptors')
189-
group.add_argument("--legacy-wallet", default=False, action="store_false",
192+
group.add_argument("--legacy-wallet", action='store_const', const=False,
190193
help="Run test using legacy wallets", dest='descriptors')
191194

192195
self.add_options(parser)
193196
self.options = parser.parse_args()
194197
self.options.previous_releases_path = previous_releases_path
195198

199+
config = configparser.ConfigParser()
200+
config.read_file(open(self.options.configfile))
201+
self.config = config
202+
203+
if self.options.descriptors is None:
204+
# Prefer BDB unless it isn't available
205+
if self.is_bdb_compiled():
206+
self.options.descriptors = False
207+
elif self.is_sqlite_compiled():
208+
self.options.descriptors = True
209+
else:
210+
# If neither are compiled, tests requiring a wallet will be skipped and the value of self.options.descriptors won't matter
211+
# It still needs to exist and be None in order for tests to work however.
212+
self.options.descriptors = None
213+
196214
def setup(self):
197215
"""Call this method to start up the test framework object with options set."""
198216

@@ -202,9 +220,8 @@ def setup(self):
202220

203221
self.options.cachedir = os.path.abspath(self.options.cachedir)
204222

205-
config = configparser.ConfigParser()
206-
config.read_file(open(self.options.configfile))
207-
self.config = config
223+
config = self.config
224+
208225
fname_bitcoind = os.path.join(
209226
config["environment"]["BUILDDIR"],
210227
"src",
@@ -377,7 +394,7 @@ def setup_nodes(self):
377394
extra_args = self.extra_args
378395
self.add_nodes(self.num_nodes, extra_args)
379396
self.start_nodes()
380-
if self.is_wallet_compiled():
397+
if self.requires_wallet:
381398
self.import_deterministic_coinbase_privkeys()
382399
if not self.setup_clean_chain:
383400
for n in self.nodes:
@@ -769,10 +786,13 @@ def skip_if_no_bitcoind_zmq(self):
769786

770787
def skip_if_no_wallet(self):
771788
"""Skip the running test if wallet has not been compiled."""
789+
self.requires_wallet = True
772790
if not self.is_wallet_compiled():
773791
raise SkipTest("wallet has not been compiled.")
774792
if self.options.descriptors:
775793
self.skip_if_no_sqlite()
794+
else:
795+
self.skip_if_no_bdb()
776796

777797
def skip_if_no_sqlite(self):
778798
"""Skip the running test if sqlite has not been compiled."""

0 commit comments

Comments
 (0)