6
6
7
7
import os
8
8
import platform
9
+ import random
9
10
import stat
11
+ import string
10
12
import subprocess
11
13
import textwrap
12
14
13
15
from collections import OrderedDict
14
16
17
+ from test_framework .bdb import dump_bdb_kv
18
+ from test_framework .messages import ser_string
15
19
from test_framework .test_framework import BitcoinTestFramework
16
20
from test_framework .util import (
17
21
assert_equal ,
18
22
assert_greater_than ,
19
23
sha256sum_file ,
20
24
)
25
+ from test_framework .wallet import getnewdestination
21
26
22
27
23
28
class ToolWalletTest (BitcoinTestFramework ):
@@ -545,6 +550,44 @@ def test_dump_unclean_lsns(self):
545
550
self .stop_node (0 )
546
551
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" )
547
552
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'\x04 name' + 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
+
548
591
def run_test (self ):
549
592
self .wallet_path = self .nodes [0 ].wallets_path / self .default_wallet_name / self .wallet_data_filename
550
593
self .test_invalid_tool_commands_and_args ()
@@ -561,6 +604,9 @@ def run_test(self):
561
604
self .test_dump_createfromdump ()
562
605
self .test_chainless_conflicts ()
563
606
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
+
564
610
565
611
if __name__ == '__main__' :
566
612
ToolWalletTest (__file__ ).main ()
0 commit comments