@@ -67,6 +67,15 @@ def assert_list_txs_equal(self, received_list_txs, expected_list_txs):
6767 del d ["parent_descs" ]
6868 assert_equal (received_list_txs , expected_list_txs )
6969
70+ def check_address (self , wallet , addr , is_mine , is_change , label ):
71+ addr_info = wallet .getaddressinfo (addr )
72+ assert_equal (addr_info ['ismine' ], is_mine )
73+ assert_equal (addr_info ['ischange' ], is_change )
74+ if label is not None :
75+ assert_equal (addr_info ['labels' ], [label ]),
76+ else :
77+ assert_equal (addr_info ['labels' ], []),
78+
7079 def test_basic (self ):
7180 default = self .nodes [0 ].get_wallet_rpc (self .default_wallet_name )
7281
@@ -470,6 +479,132 @@ def test_unloaded_by_path(self):
470479
471480 assert_equal (bals , wallet .getbalances ())
472481
482+ def test_addressbook (self ):
483+ df_wallet = self .nodes [0 ].get_wallet_rpc (self .default_wallet_name )
484+
485+ self .log .info ("Test migration of address book data" )
486+ wallet = self .create_legacy_wallet ("legacy_addrbook" )
487+ df_wallet .sendtoaddress (wallet .getnewaddress (), 3 )
488+
489+ # Import watch-only script to create a watch-only wallet after migration
490+ watch_addr = df_wallet .getnewaddress ()
491+ wallet .importaddress (watch_addr )
492+ df_wallet .sendtoaddress (watch_addr , 2 )
493+
494+ # Import solvable script
495+ multi_addr1 = wallet .getnewaddress ()
496+ multi_addr2 = wallet .getnewaddress ()
497+ multi_addr3 = df_wallet .getnewaddress ()
498+ wallet .importpubkey (df_wallet .getaddressinfo (multi_addr3 )["pubkey" ])
499+ ms_addr_info = wallet .addmultisigaddress (2 , [multi_addr1 , multi_addr2 , multi_addr3 ])
500+
501+ self .generate (self .nodes [0 ], 1 )
502+
503+ # Test vectors
504+ addr_external = {
505+ "addr" : df_wallet .getnewaddress (),
506+ "is_mine" : False ,
507+ "is_change" : False ,
508+ "label" : ""
509+ }
510+ addr_external_with_label = {
511+ "addr" : df_wallet .getnewaddress (),
512+ "is_mine" : False ,
513+ "is_change" : False ,
514+ "label" : "external"
515+ }
516+ addr_internal = {
517+ "addr" : wallet .getnewaddress (),
518+ "is_mine" : True ,
519+ "is_change" : False ,
520+ "label" : ""
521+ }
522+ addr_internal_with_label = {
523+ "addr" : wallet .getnewaddress (),
524+ "is_mine" : True ,
525+ "is_change" : False ,
526+ "label" : "internal"
527+ }
528+ change_address = {
529+ "addr" : wallet .getrawchangeaddress (),
530+ "is_mine" : True ,
531+ "is_change" : True ,
532+ "label" : None
533+ }
534+ watch_only_addr = {
535+ "addr" : watch_addr ,
536+ "is_mine" : False ,
537+ "is_change" : False ,
538+ "label" : "imported"
539+ }
540+ ms_addr = {
541+ "addr" : ms_addr_info ['address' ],
542+ "is_mine" : False ,
543+ "is_change" : False ,
544+ "label" : "multisig"
545+ }
546+
547+ # To store the change address in the addressbook need to send coins to it
548+ wallet .send (outputs = [{wallet .getnewaddress (): 2 }], options = {"change_address" : change_address ['addr' ]})
549+ self .generate (self .nodes [0 ], 1 )
550+
551+ # Util wrapper func for 'addr_info'
552+ def check (info , node ):
553+ self .check_address (node , info ['addr' ], info ['is_mine' ], info ['is_change' ], info ["label" ])
554+
555+ # Pre-migration: set label and perform initial checks
556+ for addr_info in [addr_external , addr_external_with_label , addr_internal , addr_internal_with_label , change_address , watch_only_addr , ms_addr ]:
557+ if not addr_info ['is_change' ]:
558+ wallet .setlabel (addr_info ['addr' ], addr_info ["label" ])
559+ check (addr_info , wallet )
560+
561+ # Migrate wallet
562+ info_migration = wallet .migratewallet ()
563+ wallet_wo = self .nodes [0 ].get_wallet_rpc (info_migration ["watchonly_name" ])
564+ wallet_solvables = self .nodes [0 ].get_wallet_rpc (info_migration ["solvables_name" ])
565+
566+ #########################
567+ # Post migration checks #
568+ #########################
569+
570+ # First check the main wallet
571+ for addr_info in [addr_external , addr_external_with_label , addr_internal , addr_internal_with_label , change_address , ms_addr ]:
572+ check (addr_info , wallet )
573+
574+ # Watch-only wallet will contain the watch-only entry (with 'is_mine=True') and all external addresses ('send')
575+ self .check_address (wallet_wo , watch_only_addr ['addr' ], is_mine = True , is_change = watch_only_addr ['is_change' ], label = watch_only_addr ["label" ])
576+ for addr_info in [addr_external , addr_external_with_label , ms_addr ]:
577+ check (addr_info , wallet_wo )
578+
579+ # Solvables wallet will contain the multisig entry (with 'is_mine=True') and all external addresses ('send')
580+ self .check_address (wallet_solvables , ms_addr ['addr' ], is_mine = True , is_change = ms_addr ['is_change' ], label = ms_addr ["label" ])
581+ for addr_info in [addr_external , addr_external_with_label ]:
582+ check (addr_info , wallet_solvables )
583+
584+ ########################################################################################
585+ # Now restart migrated wallets and verify that the addressbook entries are still there #
586+ ########################################################################################
587+
588+ # First the main wallet
589+ self .nodes [0 ].unloadwallet ("legacy_addrbook" )
590+ self .nodes [0 ].loadwallet ("legacy_addrbook" )
591+ for addr_info in [addr_external , addr_external_with_label , addr_internal , addr_internal_with_label , change_address , ms_addr ]:
592+ check (addr_info , wallet )
593+
594+ # Watch-only wallet
595+ self .nodes [0 ].unloadwallet (info_migration ["watchonly_name" ])
596+ self .nodes [0 ].loadwallet (info_migration ["watchonly_name" ])
597+ self .check_address (wallet_wo , watch_only_addr ['addr' ], is_mine = True , is_change = watch_only_addr ['is_change' ], label = watch_only_addr ["label" ])
598+ for addr_info in [addr_external , addr_external_with_label , ms_addr ]:
599+ check (addr_info , wallet_wo )
600+
601+ # Solvables wallet
602+ self .nodes [0 ].unloadwallet (info_migration ["solvables_name" ])
603+ self .nodes [0 ].loadwallet (info_migration ["solvables_name" ])
604+ self .check_address (wallet_solvables , ms_addr ['addr' ], is_mine = True , is_change = ms_addr ['is_change' ], label = ms_addr ["label" ])
605+ for addr_info in [addr_external , addr_external_with_label ]:
606+ check (addr_info , wallet_solvables )
607+
473608 def run_test (self ):
474609 self .generate (self .nodes [0 ], 101 )
475610
@@ -482,6 +617,7 @@ def run_test(self):
482617 self .test_encrypted ()
483618 self .test_unloaded ()
484619 self .test_unloaded_by_path ()
620+ self .test_addressbook ()
485621
486622if __name__ == '__main__' :
487623 WalletMigrationTest ().main ()
0 commit comments