6
6
7
7
import random
8
8
import shutil
9
- from test_framework .address import script_to_p2sh
9
+ from test_framework .address import (
10
+ script_to_p2sh ,
11
+ key_to_p2pkh ,
12
+ key_to_p2wpkh ,
13
+ )
10
14
from test_framework .descriptors import descsum_create
15
+ from test_framework .key import ECPubKey
11
16
from test_framework .test_framework import BitcoinTestFramework
12
17
from test_framework .messages import COIN , CTransaction , CTxOut
13
18
from test_framework .script_util import key_to_p2pkh_script , script_to_p2sh_script , script_to_p2wsh_script
@@ -770,6 +775,58 @@ def test_conflict_txs(self):
770
775
771
776
wallet .unloadwallet ()
772
777
778
+ def test_hybrid_pubkey (self ):
779
+ self .log .info ("Test migration when wallet contains a hybrid pubkey" )
780
+
781
+ wallet = self .create_legacy_wallet ("hybrid_keys" )
782
+
783
+ # Get the hybrid pubkey for one of the keys in the wallet
784
+ normal_pubkey = wallet .getaddressinfo (wallet .getnewaddress ())["pubkey" ]
785
+ first_byte = bytes .fromhex (normal_pubkey )[0 ] + 4 # Get the hybrid pubkey first byte
786
+ parsed_pubkey = ECPubKey ()
787
+ parsed_pubkey .set (bytes .fromhex (normal_pubkey ))
788
+ parsed_pubkey .compressed = False
789
+ hybrid_pubkey_bytes = bytearray (parsed_pubkey .get_bytes ())
790
+ hybrid_pubkey_bytes [0 ] = first_byte # Make it hybrid
791
+ hybrid_pubkey = hybrid_pubkey_bytes .hex ()
792
+
793
+ # Import the hybrid pubkey
794
+ wallet .importpubkey (hybrid_pubkey )
795
+ p2pkh_addr = key_to_p2pkh (hybrid_pubkey )
796
+ p2pkh_addr_info = wallet .getaddressinfo (p2pkh_addr )
797
+ assert_equal (p2pkh_addr_info ["iswatchonly" ], True )
798
+ assert_equal (p2pkh_addr_info ["ismine" ], False ) # Things involving hybrid pubkeys are not spendable
799
+
800
+ # Also import the p2wpkh for the pubkey to make sure we don't migrate it
801
+ p2wpkh_addr = key_to_p2wpkh (hybrid_pubkey )
802
+ wallet .importaddress (p2wpkh_addr )
803
+
804
+ migrate_info = wallet .migratewallet ()
805
+
806
+ # Both addresses should only appear in the watchonly wallet
807
+ p2pkh_addr_info = wallet .getaddressinfo (p2pkh_addr )
808
+ assert_equal (p2pkh_addr_info ["iswatchonly" ], False )
809
+ assert_equal (p2pkh_addr_info ["ismine" ], False )
810
+ p2wpkh_addr_info = wallet .getaddressinfo (p2wpkh_addr )
811
+ assert_equal (p2wpkh_addr_info ["iswatchonly" ], False )
812
+ assert_equal (p2wpkh_addr_info ["ismine" ], False )
813
+
814
+ watchonly_wallet = self .nodes [0 ].get_wallet_rpc (migrate_info ["watchonly_name" ])
815
+ watchonly_p2pkh_addr_info = watchonly_wallet .getaddressinfo (p2pkh_addr )
816
+ assert_equal (watchonly_p2pkh_addr_info ["iswatchonly" ], False )
817
+ assert_equal (watchonly_p2pkh_addr_info ["ismine" ], True )
818
+ watchonly_p2wpkh_addr_info = watchonly_wallet .getaddressinfo (p2wpkh_addr )
819
+ assert_equal (watchonly_p2wpkh_addr_info ["iswatchonly" ], False )
820
+ assert_equal (watchonly_p2wpkh_addr_info ["ismine" ], True )
821
+
822
+ # There should only be raw or addr descriptors
823
+ for desc in watchonly_wallet .listdescriptors ()["descriptors" ]:
824
+ if desc ["desc" ].startswith ("raw(" ) or desc ["desc" ].startswith ("addr(" ):
825
+ continue
826
+ assert False , "Hybrid pubkey watchonly wallet has more than just raw() and addr()"
827
+
828
+ wallet .unloadwallet ()
829
+
773
830
def run_test (self ):
774
831
self .generate (self .nodes [0 ], 101 )
775
832
@@ -787,6 +844,7 @@ def run_test(self):
787
844
self .test_addressbook ()
788
845
self .test_migrate_raw_p2sh ()
789
846
self .test_conflict_txs ()
847
+ self .test_hybrid_pubkey ()
790
848
791
849
if __name__ == '__main__' :
792
850
WalletMigrationTest ().main ()
0 commit comments