Skip to content

Commit d45eb39

Browse files
committed
test: compare BDB dumps of test framework parser and wallet tool
1 parent 01ddd9f commit d45eb39

File tree

1 file changed

+46
-0
lines changed

1 file changed

+46
-0
lines changed

test/functional/tool_wallet.py

Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,18 +6,23 @@
66

77
import os
88
import platform
9+
import random
910
import stat
11+
import string
1012
import subprocess
1113
import textwrap
1214

1315
from collections import OrderedDict
1416

17+
from test_framework.bdb import dump_bdb_kv
18+
from test_framework.messages import ser_string
1519
from test_framework.test_framework import BitcoinTestFramework
1620
from test_framework.util import (
1721
assert_equal,
1822
assert_greater_than,
1923
sha256sum_file,
2024
)
25+
from test_framework.wallet import getnewdestination
2126

2227

2328
class ToolWalletTest(BitcoinTestFramework):
@@ -545,6 +550,44 @@ def test_dump_unclean_lsns(self):
545550
self.stop_node(0)
546551
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")
547552

553+
def test_compare_legacy_dump_with_framework_bdb_parser(self):
554+
self.log.info("Verify that legacy wallet database dump matches the one from the test framework's BDB parser")
555+
wallet_name = "bdb_ro_test"
556+
self.start_node(0)
557+
# add some really large labels (above twice the largest valid page size) to create BDB overflow pages
558+
self.nodes[0].createwallet(wallet_name)
559+
wallet_rpc = self.nodes[0].get_wallet_rpc(wallet_name)
560+
generated_labels = {}
561+
for i in range(10):
562+
address = getnewdestination()[2]
563+
large_label = ''.join([random.choice(string.ascii_letters) for _ in range(150000)])
564+
wallet_rpc.setlabel(address, large_label)
565+
generated_labels[address] = large_label
566+
# fill the keypool to create BDB internal pages
567+
wallet_rpc.keypoolrefill(1000)
568+
self.stop_node(0)
569+
570+
wallet_dumpfile = self.nodes[0].datadir_path / "bdb_ro_test.dump"
571+
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")
572+
573+
expected_dump = self.read_dump(wallet_dumpfile)
574+
# remove extra entries from wallet tool dump that are not actual key/value pairs from the database
575+
del expected_dump['BITCOIN_CORE_WALLET_DUMP']
576+
del expected_dump['format']
577+
del expected_dump['checksum']
578+
bdb_ro_parser_dump_raw = dump_bdb_kv(self.nodes[0].wallets_path / wallet_name / "wallet.dat")
579+
bdb_ro_parser_dump = OrderedDict()
580+
assert any([len(bytes.fromhex(value)) >= 150000 for value in expected_dump.values()])
581+
for key, value in sorted(bdb_ro_parser_dump_raw.items()):
582+
bdb_ro_parser_dump[key.hex()] = value.hex()
583+
assert_equal(bdb_ro_parser_dump, expected_dump)
584+
585+
# check that all labels were created with the correct address
586+
for address, label in generated_labels.items():
587+
key_bytes = b'\x04name' + ser_string(address.encode())
588+
assert key_bytes in bdb_ro_parser_dump_raw
589+
assert_equal(bdb_ro_parser_dump_raw[key_bytes], ser_string(label.encode()))
590+
548591
def run_test(self):
549592
self.wallet_path = self.nodes[0].wallets_path / self.default_wallet_name / self.wallet_data_filename
550593
self.test_invalid_tool_commands_and_args()
@@ -561,6 +604,9 @@ def run_test(self):
561604
self.test_dump_createfromdump()
562605
self.test_chainless_conflicts()
563606
self.test_dump_very_large_records()
607+
if not self.options.descriptors and self.is_bdb_compiled() and not self.options.swap_bdb_endian:
608+
self.test_compare_legacy_dump_with_framework_bdb_parser()
609+
564610

565611
if __name__ == '__main__':
566612
ToolWalletTest(__file__).main()

0 commit comments

Comments
 (0)