Skip to content

Commit 8e7e3e6

Browse files
committed
test: wallet, verify migration doesn't crash for an invalid script
The migration process must skip any invalid script inside the legacy spkm and all the addressbook records linked to them. These scripts are not being watched by the current wallet, nor should be watched by the migrated one. IsMine() returns ISMINE_NO for them.
1 parent 1de8a23 commit 8e7e3e6

File tree

1 file changed

+30
-0
lines changed

1 file changed

+30
-0
lines changed

test/functional/wallet_migration.py

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66

77
import random
88
import shutil
9+
from test_framework.address import script_to_p2sh
910
from test_framework.descriptors import descsum_create
1011
from test_framework.test_framework import BitcoinTestFramework
1112
from test_framework.messages import COIN, CTransaction, CTxOut
@@ -674,6 +675,21 @@ def send_to_script(script, amount):
674675
wallet.rpc.importaddress(address=script_wsh_pkh.hex(), label="raw_spk2", rescan=True, p2sh=False)
675676
assert_equal(wallet.getbalances()['watchonly']['trusted'], 5)
676677

678+
# Import sh(pkh()) script, by using importaddress(), with the p2sh flag enabled.
679+
# This will wrap the script under another sh level, which is invalid!, and store it inside the wallet.
680+
# The migration process must skip the invalid scripts and the addressbook records linked to them.
681+
# They are not being watched by the current wallet, nor should be watched by the migrated one.
682+
label_sh_pkh = "raw_sh_pkh"
683+
script_pkh = key_to_p2pkh_script(df_wallet.getaddressinfo(df_wallet.getnewaddress())["pubkey"])
684+
script_sh_pkh = script_to_p2sh_script(script_pkh)
685+
addy_script_sh_pkh = script_to_p2sh(script_pkh) # valid script address
686+
addy_script_double_sh_pkh = script_to_p2sh(script_sh_pkh) # invalid script address
687+
688+
# Note: 'importaddress()' will add two scripts, a valid one sh(pkh()) and an invalid one 'sh(sh(pkh()))'.
689+
# Both of them will be stored with the same addressbook label. And only the latter one should
690+
# be discarded during migration. The first one must be migrated.
691+
wallet.rpc.importaddress(address=script_sh_pkh.hex(), label=label_sh_pkh, rescan=False, p2sh=True)
692+
677693
# Migrate wallet and re-check balance
678694
info_migration = wallet.migratewallet()
679695
wallet_wo = self.nodes[0].get_wallet_rpc(info_migration["watchonly_name"])
@@ -683,6 +699,20 @@ def send_to_script(script, amount):
683699
# The watch-only scripts are no longer part of the main wallet
684700
assert_equal(wallet.getbalances()['mine']['trusted'], 0)
685701

702+
# The invalid sh(sh(pk())) script label must not be part of the main wallet anymore
703+
assert label_sh_pkh not in wallet.listlabels()
704+
# But, the standard sh(pkh()) script should be part of the watch-only wallet.
705+
addrs_by_label = wallet_wo.getaddressesbylabel(label_sh_pkh)
706+
assert addy_script_sh_pkh in addrs_by_label
707+
assert addy_script_double_sh_pkh not in addrs_by_label
708+
709+
# Also, the watch-only wallet should have the descriptor for the standard sh(pkh())
710+
desc = descsum_create(f"addr({addy_script_sh_pkh})")
711+
assert next(it['desc'] for it in wallet_wo.listdescriptors()['descriptors'] if it['desc'] == desc)
712+
# And doesn't have a descriptor for the invalid one
713+
desc_invalid = descsum_create(f"addr({addy_script_double_sh_pkh})")
714+
assert_equal(next((it['desc'] for it in wallet_wo.listdescriptors()['descriptors'] if it['desc'] == desc_invalid), None), None)
715+
686716
# Just in case, also verify wallet restart
687717
self.nodes[0].unloadwallet(info_migration["watchonly_name"])
688718
self.nodes[0].loadwallet(info_migration["watchonly_name"])

0 commit comments

Comments
 (0)