Skip to content

Commit

Permalink
test: Test migration of taproot output scripts
Browse files Browse the repository at this point in the history
  • Loading branch information
achow101 committed Dec 13, 2024
1 parent 7018e1a commit ef20f9f
Showing 1 changed file with 58 additions and 0 deletions.
58 changes: 58 additions & 0 deletions test/functional/wallet_migration.py
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@
from test_framework.util import (
assert_equal,
assert_raises_rpc_error,
find_vout_for_address,
sha256sum_file,
)
from test_framework.wallet_util import (
Expand Down Expand Up @@ -1117,6 +1118,62 @@ def test_miniscript(self):
assert_equal(watchonly.getaddressinfo(some_keys_addr)["ismine"], True)
assert_equal(watchonly.getaddressinfo(all_keys_addr)["ismine"], False)

def test_taproot(self):
# It turns out that due to how signing logic works, legacy wallets that have the private key for a Taproot
# output key will be able to sign and spend those scripts, even though they would not be detected as ISMINE_SPENDABLE.
self.log.info("Test migration of Taproot scripts")
def_wallet = self.master_node.get_wallet_rpc(self.default_wallet_name)
wallet = self.create_legacy_wallet("taproot")

privkey, _ = generate_keypair(compressed=True, wif=True)

rawtr_desc = descsum_create(f"rawtr({privkey})")
rawtr_addr = self.master_node.deriveaddresses(rawtr_desc)[0]
rawtr_spk = self.master_node.validateaddress(rawtr_addr)["scriptPubKey"]
tr_desc = descsum_create(f"tr({privkey})")
tr_addr = self.master_node.deriveaddresses(tr_desc)[0]
tr_spk = self.master_node.validateaddress(tr_addr)["scriptPubKey"]
tr_script_desc = descsum_create(f"tr(9ffbe722b147f3035c87cb1c60b9a5947dd49c774cc31e94773478711a929ac0,pk({privkey}))")
tr_script_addr = self.master_node.deriveaddresses(tr_script_desc)[0]
tr_script_spk = self.master_node.validateaddress(tr_script_addr)["scriptPubKey"]

wallet.importaddress(rawtr_spk)
wallet.importaddress(tr_spk)
wallet.importaddress(tr_script_spk)
wallet.importprivkey(privkey)

txid = def_wallet.send([{rawtr_addr: 1},{tr_addr: 2}, {tr_script_addr: 3}])["txid"]
rawtr_vout = find_vout_for_address(self.master_node, txid, rawtr_addr)
tr_vout = find_vout_for_address(self.master_node, txid, tr_addr)
tr_script_vout = find_vout_for_address(self.master_node, txid, tr_script_addr)
self.generate(self.master_node, 6)

# Double check that the rawtr can be spent by the legacy wallet
send_res = wallet.send(outputs=[{rawtr_addr: 0.5}], include_watching=True, change_address=def_wallet.getnewaddress(), inputs=[{"txid": txid, "vout": rawtr_vout}])
assert_equal(send_res["complete"], True)
self.generate(self.old_node, 6)
assert_equal(wallet.getbalances()["watchonly"]["trusted"], 5.5)

# Check that the tr() cannot be spent by the legacy wallet
send_res = wallet.send(outputs=[{def_wallet.getnewaddress(): 4}], include_watching=True, inputs=[{"txid": txid, "vout": tr_vout}, {"txid": txid, "vout": tr_script_vout}])
assert_equal(send_res["complete"], False)

res, wallet = self.migrate_and_get_rpc("taproot")

# The rawtr should be migrated
assert_equal(wallet.getbalances()["mine"], {"trusted": 0.5, "untrusted_pending": 0, "immature": 0})
assert_equal(wallet.getaddressinfo(rawtr_addr)["ismine"], True)
assert_equal(wallet.getaddressinfo(tr_addr)["ismine"], False)
assert_equal(wallet.getaddressinfo(tr_script_addr)["ismine"], False)

# The miniscript with some keys should be in the watchonly wallet
assert "taproot_watchonly" in self.master_node.listwallets()
watchonly = self.master_node.get_wallet_rpc("taproot_watchonly")
assert_equal(watchonly.getbalances()["mine"], {"trusted": 5, "untrusted_pending": 0, "immature": 0})
assert_equal(watchonly.getaddressinfo(rawtr_addr)["ismine"], False)
assert_equal(watchonly.getaddressinfo(tr_addr)["ismine"], True)
assert_equal(watchonly.getaddressinfo(tr_script_addr)["ismine"], True)

def run_test(self):
self.master_node = self.nodes[0]
self.old_node = self.nodes[1]
Expand Down Expand Up @@ -1145,6 +1202,7 @@ def run_test(self):
self.test_migrate_simple_watch_only()
self.test_manual_keys_import()
self.test_miniscript()
self.test_taproot()


if __name__ == '__main__':
Expand Down

0 comments on commit ef20f9f

Please sign in to comment.