test: remove legacy wallet functional tests

Removes all legacy wallet specific functional tests.

Also removes the --descriptor and --legacy-wallet options as these are
no longer necessary with the legacy wallet removed.
This commit is contained in:
Ava Chow committed 2025-04-23 12:10:30 -07:00
1 parent 20a9173717
commit c847dee148
96 files changed
+389 -4669

No files matched your search

+20 -149
View File
@@ -5,28 +5,22 @@
"""Test bitcoin-wallet."""
import os
import random
import stat
import string
import subprocess
import textwrap
from collections import OrderedDict
from test_framework.bdb import dump_bdb_kv
from test_framework.messages import ser_string
from test_framework.test_framework import BitcoinTestFramework
from test_framework.util import (
assert_equal,
assert_greater_than,
sha256sum_file,
)
from test_framework.wallet import getnewdestination
class ToolWalletTest(BitcoinTestFramework):
def add_options(self, parser):
self.add_wallet_options(parser)
parser.add_argument("--bdbro", action="store_true", help="Use the BerkeleyRO internal parser when dumping a Berkeley DB wallet file")
parser.add_argument("--swap-bdb-endian", action="store_true",help="When making Legacy BDB wallets, always make then byte swapped internally")
@@ -43,8 +37,6 @@ class ToolWalletTest(BitcoinTestFramework):
def bitcoin_wallet_process(self, *args):
default_args = ['-datadir={}'.format(self.nodes[0].datadir_path), '-chain=%s' % self.chain]
if not self.options.descriptors and 'create' in args:
default_args.append('-legacy')
if "dump" in args and self.options.bdbro:
default_args.append("-withinternalbdb")
@@ -83,34 +75,19 @@ class ToolWalletTest(BitcoinTestFramework):
def get_expected_info_output(self, name="", transactions=0, keypool=2, address=0, imported_privs=0):
wallet_name = self.default_wallet_name if name == "" else name
if self.options.descriptors:
output_types = 4 # p2pkh, p2sh, segwit, bech32m
return textwrap.dedent('''\
Wallet info
===========
Name: %s
Format: sqlite
Descriptors: yes
Encrypted: no
HD (hd seed available): yes
Keypool Size: %d
Transactions: %d
Address Book: %d
''' % (wallet_name, keypool * output_types, transactions, imported_privs * 3 + address))
else:
output_types = 3 # p2pkh, p2sh, segwit. Legacy wallets do not support bech32m.
return textwrap.dedent('''\
Wallet info
===========
Name: %s
Format: bdb
Descriptors: no
Encrypted: no
HD (hd seed available): yes
Keypool Size: %d
Transactions: %d
Address Book: %d
''' % (wallet_name, keypool, transactions, (address + imported_privs) * output_types))
output_types = 4 # p2pkh, p2sh, segwit, bech32m
return textwrap.dedent('''\
Wallet info
===========
Name: %s
Format: sqlite
Descriptors: yes
Encrypted: no
HD (hd seed available): yes
Keypool Size: %d
Transactions: %d
Address Book: %d
''' % (wallet_name, keypool * output_types, transactions, imported_privs * 3 + address))
def read_dump(self, filename):
dump = OrderedDict()
@@ -204,10 +181,7 @@ class ToolWalletTest(BitcoinTestFramework):
self.assert_raises_tool_error('Error parsing command line arguments: Invalid parameter -foo', '-foo')
self.assert_raises_tool_error('No method provided. Run `bitcoin-wallet -help` for valid methods.')
self.assert_raises_tool_error('Wallet name must be provided when creating a new wallet.', 'create')
locked_dir = self.nodes[0].wallets_path
error = 'Error initializing wallet database environment "{}"!'.format(locked_dir)
if self.options.descriptors:
error = f"SQLiteDatabase: Unable to obtain an exclusive lock on the database, is it being used by another instance of {self.config['environment']['CLIENT_NAME']}?"
error = f"SQLiteDatabase: Unable to obtain an exclusive lock on the database, is it being used by another instance of {self.config['environment']['CLIENT_NAME']}?"
self.assert_raises_tool_error(
error,
'-wallet=' + self.default_wallet_name,
@@ -307,28 +281,14 @@ class ToolWalletTest(BitcoinTestFramework):
self.log.debug('Wallet file timestamp after calling getwalletinfo: {}'.format(timestamp_after))
assert_equal(0, out['txcount'])
if not self.options.descriptors:
assert_equal(1000, out['keypoolsize'])
assert_equal(1000, out['keypoolsize_hd_internal'])
assert_equal(True, 'hdseedid' in out)
else:
assert_equal(4000, out['keypoolsize'])
assert_equal(4000, out['keypoolsize_hd_internal'])
assert_equal(4000, out['keypoolsize'])
assert_equal(4000, out['keypoolsize_hd_internal'])
self.log_wallet_timestamp_comparison(timestamp_before, timestamp_after)
assert_equal(timestamp_before, timestamp_after)
assert_equal(shasum_after, shasum_before)
self.log.debug('Wallet file shasum unchanged\n')
def test_salvage(self):
# TODO: Check salvage actually salvages and doesn't break things. https://github.com/bitcoin/bitcoin/issues/7463
self.log.info('Check salvage')
self.start_node(0)
self.nodes[0].createwallet("salvage")
self.stop_node(0)
self.assert_tool_output('', '-wallet=salvage', 'salvage')
def test_dump_createfromdump(self):
self.start_node(0)
self.nodes[0].createwallet("todump")
@@ -452,39 +412,20 @@ class ToolWalletTest(BitcoinTestFramework):
self.stop_node(0)
# Wallet tool should successfully give info for this wallet
expected_output = textwrap.dedent(f'''\
expected_output = textwrap.dedent('''\
Wallet info
===========
Name: conflicts
Format: {"sqlite" if self.options.descriptors else "bdb"}
Descriptors: {"yes" if self.options.descriptors else "no"}
Format: sqlite
Descriptors: yes
Encrypted: no
HD (hd seed available): yes
Keypool Size: {"8" if self.options.descriptors else "1"}
Keypool Size: 8
Transactions: 4
Address Book: 4
''')
self.assert_tool_output(expected_output, "-wallet=conflicts", "info")
def test_dump_endianness(self):
self.log.info("Testing dumps of the same contents with different BDB endianness")
self.start_node(0)
self.nodes[0].createwallet("endian")
self.stop_node(0)
wallet_dump = self.nodes[0].datadir_path / "endian.dump"
self.assert_tool_output("The dumpfile may contain private keys. To ensure the safety of your Bitcoin, do not share the dumpfile.\n", "-wallet=endian", f"-dumpfile={wallet_dump}", "dump")
expected_dump = self.read_dump(wallet_dump)
self.do_tool_createfromdump("native_endian", "endian.dump", "bdb")
native_dump = self.read_dump(self.nodes[0].datadir_path / "rt-native_endian.dump")
self.assert_dump(expected_dump, native_dump)
self.do_tool_createfromdump("other_endian", "endian.dump", "bdb_swap")
other_dump = self.read_dump(self.nodes[0].datadir_path / "rt-other_endian.dump")
self.assert_dump(expected_dump, other_dump)
def test_dump_very_large_records(self):
self.log.info("Test that wallets with large records are successfully dumped")
@@ -521,69 +462,6 @@ class ToolWalletTest(BitcoinTestFramework):
else:
assert False, "Big transaction was not found in wallet dump"
def test_dump_unclean_lsns(self):
if not self.options.bdbro:
return
self.log.info("Test that a legacy wallet that has not been compacted is not dumped by bdbro")
self.start_node(0, extra_args=["-flushwallet=0"])
self.nodes[0].createwallet("unclean_lsn")
wallet = self.nodes[0].get_wallet_rpc("unclean_lsn")
# First unload and load normally to make sure everything is written
wallet.unloadwallet()
self.nodes[0].loadwallet("unclean_lsn")
# Next cause a bunch of writes by filling the keypool
wallet.keypoolrefill(wallet.getwalletinfo()["keypoolsize"] + 100)
# Lastly kill bitcoind so that the LSNs don't get reset
self.nodes[0].kill_process()
wallet_dump = self.nodes[0].datadir_path / "unclean_lsn.dump"
self.assert_raises_tool_error("LSNs are not reset, this database is not completely flushed. Please reopen then close the database with a version that has BDB support", "-wallet=unclean_lsn", f"-dumpfile={wallet_dump}", "dump")
# File can be dumped after reload it normally
self.start_node(0)
self.nodes[0].loadwallet("unclean_lsn")
self.stop_node(0)
self.assert_tool_output("The dumpfile may contain private keys. To ensure the safety of your Bitcoin, do not share the dumpfile.\n", "-wallet=unclean_lsn", f"-dumpfile={wallet_dump}", "dump")
def test_compare_legacy_dump_with_framework_bdb_parser(self):
self.log.info("Verify that legacy wallet database dump matches the one from the test framework's BDB parser")
wallet_name = "bdb_ro_test"
self.start_node(0)
# add some really large labels (above twice the largest valid page size) to create BDB overflow pages
self.nodes[0].createwallet(wallet_name)
wallet_rpc = self.nodes[0].get_wallet_rpc(wallet_name)
generated_labels = {}
for i in range(10):
address = getnewdestination()[2]
large_label = ''.join([random.choice(string.ascii_letters) for _ in range(150000)])
wallet_rpc.setlabel(address, large_label)
generated_labels[address] = large_label
# fill the keypool to create BDB internal pages
wallet_rpc.keypoolrefill(1000)
self.stop_node(0)
wallet_dumpfile = self.nodes[0].datadir_path / "bdb_ro_test.dump"
self.assert_tool_output("The dumpfile may contain private keys. To ensure the safety of your Bitcoin, do not share the dumpfile.\n", "-wallet={}".format(wallet_name), "-dumpfile={}".format(wallet_dumpfile), "dump")
expected_dump = self.read_dump(wallet_dumpfile)
# remove extra entries from wallet tool dump that are not actual key/value pairs from the database
del expected_dump['BITCOIN_CORE_WALLET_DUMP']
del expected_dump['format']
del expected_dump['checksum']
bdb_ro_parser_dump_raw = dump_bdb_kv(self.nodes[0].wallets_path / wallet_name / "wallet.dat")
bdb_ro_parser_dump = OrderedDict()
assert any([len(bytes.fromhex(value)) >= 150000 for value in expected_dump.values()])
for key, value in sorted(bdb_ro_parser_dump_raw.items()):
bdb_ro_parser_dump[key.hex()] = value.hex()
assert_equal(bdb_ro_parser_dump, expected_dump)
# check that all labels were created with the correct address
for address, label in generated_labels.items():
key_bytes = b'\x04name' + ser_string(address.encode())
assert key_bytes in bdb_ro_parser_dump_raw
assert_equal(bdb_ro_parser_dump_raw[key_bytes], ser_string(label.encode()))
def run_test(self):
self.wallet_path = self.nodes[0].wallets_path / self.default_wallet_name / self.wallet_data_filename
self.test_invalid_tool_commands_and_args()
@@ -592,16 +470,9 @@ class ToolWalletTest(BitcoinTestFramework):
self.test_tool_wallet_info_after_transaction()
self.test_tool_wallet_create_on_existing_wallet()
self.test_getwalletinfo_on_different_wallet()
if not self.options.descriptors:
# Salvage is a legacy wallet only thing
self.test_salvage()
self.test_dump_endianness()
self.test_dump_unclean_lsns()
self.test_dump_createfromdump()
self.test_chainless_conflicts()
self.test_dump_very_large_records()
if not self.options.descriptors and self.is_bdb_compiled() and not self.options.swap_bdb_endian:
self.test_compare_legacy_dump_with_framework_bdb_parser()
if __name__ == '__main__':