From afdd3d1ffc544fb613383100d8c46d3c828fbecc Mon Sep 17 00:00:00 2001 From: Nick Klockenga Date: Sat, 18 Mar 2023 22:33:12 -0400 Subject: [PATCH 1/3] taproot_bip32_derivations won't be populated for non-change p2tr addresses and therefor my_pubkey will be None. The additional indendation of script.p2tr(my_pubkey) will make it so it's only called when my_pubkey is not None. --- src/seedsigner/models/psbt_parser.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/seedsigner/models/psbt_parser.py b/src/seedsigner/models/psbt_parser.py index a76785f81..3a1374bed 100644 --- a/src/seedsigner/models/psbt_parser.py +++ b/src/seedsigner/models/psbt_parser.py @@ -148,7 +148,7 @@ def _parse_outputs(self): leaf_hashes, derivation = list(out.taproot_bip32_derivations.values())[0] der = derivation.derivation my_pubkey = self.root.derive(der) - sc = script.p2tr(my_pubkey) + sc = script.p2tr(my_pubkey) if sc.data == self.psbt.tx.vout[i].script_pubkey.data: is_change = True From 27e64123814740fe0c3b67d5558901d2093cff76 Mon Sep 17 00:00:00 2001 From: Nick Klockenga Date: Sat, 18 Mar 2023 22:59:57 -0400 Subject: [PATCH 2/3] add unit test for p2tr spend with change for psbt_parser --- tests/test_psbt_parser.py | 33 +++++++++++++++++++++++++++++---- 1 file changed, 29 insertions(+), 4 deletions(-) diff --git a/tests/test_psbt_parser.py b/tests/test_psbt_parser.py index 7fb84c600..6afe3d008 100644 --- a/tests/test_psbt_parser.py +++ b/tests/test_psbt_parser.py @@ -1,8 +1,33 @@ import pytest from mock import MagicMock -from seedsigner.models import PSBTParser +from seedsigner.models import PSBTParser, Seed from embit import psbt +from embit import bip32 +from embit import bip39 +from binascii import a2b_base64, b2a_base64 +from seedsigner.models.settings_definition import SettingsConstants -def test_sig_count(): - print("test") - \ No newline at end of file +def test_p2tr_change_detection(): + psbt_base64 = "cHNidP8BAIkCAAAAAf8upuiIWF1VTgC/Q8ZWRrameRigaXpRcQcBe8ye+TK3AQAAAAAXCgAAAs7BJqsAAAAAIlEgGKqNQ7yF4+yFrrscHnjrbEHiJFExhR903ze43FtOH3BwTgQTAAAAACJRINBe93RcrOYO4UVLLE0y8pzvblOKQWcoQ0obCey8nA5GAAAAAE8BBDWHzwNMUx9OgAAAAJdr+WtwWfVa6IPbpKZ4KgRC0clbm11Gl155IPA27n2FAvQCrFGH6Ac2U0Gcy1IH5f5ltgUBDz2+fe8iqL6JzZdgEDlK7RRWAACAAQAAgAAAAIAAAQB9AgAAAAGAKOOUFIzw9pbRDaZ7F0DYhLImrdMn//OSm++ff5VNdAAAAAAAAQAAAAKsjLwAAAAAABYAFKEcuxvXmB3rWHSqSviP5mrKMZoL2RArvgAAAAAiUSBGU0Lg5fx/ECsB1Z4ZUqXQFSLFnlmpm0rm5R2l599h2AAAAAABASvZECu+AAAAACJRIEZTQuDl/H8QKwHVnhlSpdAVIsWeWambSublHaXn32HYAQMEAAAAACEWF7hZVn7pIDR429kAn/WDeQiWjZey1iGHztsL1H83QLMZADlK7RRWAACAAQAAgAAAAIABAAAAAAAAAAEXIBe4WVZ+6SA0eNvZAJ/1g3kIlo2XstYhh87bC9R/N0CzACEHbJdqWyMxF2eOPr6YRXUJmry04HUbgKyeM2IZeG+NI9AZADlK7RRWAACAAQAAgAAAAIABAAAAAQAAAAEFIGyXalsjMRdnjj6+mEV1CZq8tOB1G4CsnjNiGXhvjSPQAAA=" + + raw = a2b_base64(psbt_base64) + tx = psbt.PSBT.parse(raw) + + mnemonic = "goddess rough corn exclude cream trial fee trumpet million prevent gaze power".split() + pw = "" + seed = Seed(mnemonic, passphrase=pw) + + pp = PSBTParser(p=tx, seed=seed, network=SettingsConstants.REGTEST) + + assert pp.change_data == [ + { + 'output_index': 0, + 'address': 'bcrt1prz4g6saush37epdwhvwpu78td3q7yfz3xxz37axlx7udck6wracq3rwq30', + 'amount': 2871443918, + 'fingerprint': ['394aed14'], + 'derivation_path': ['m/86h/1h/0h/1/1']} + ] + assert pp.spend_amount == 319049328 + assert pp.change_amount == 2871443918 + assert pp.destination_addresses == ['bcrt1p6p00wazu4nnqac29fvky6vhjnnhku5u2g9njss62rvy7e0yuperq86f5ek'] + assert pp.destination_amounts == [319049328] \ No newline at end of file From 28a4999a091c76cf3d87a53eee4ec1a79003b29c Mon Sep 17 00:00:00 2001 From: Nick Klockenga Date: Thu, 29 Jun 2023 17:23:41 -0400 Subject: [PATCH 3/3] - remove unnecessary imports - add test doc string --- tests/test_psbt_parser.py | 20 +++++++++++++++++--- 1 file changed, 17 insertions(+), 3 deletions(-) diff --git a/tests/test_psbt_parser.py b/tests/test_psbt_parser.py index 6afe3d008..e0fb5a843 100644 --- a/tests/test_psbt_parser.py +++ b/tests/test_psbt_parser.py @@ -2,12 +2,26 @@ from mock import MagicMock from seedsigner.models import PSBTParser, Seed from embit import psbt -from embit import bip32 -from embit import bip39 -from binascii import a2b_base64, b2a_base64 +from binascii import a2b_base64 from seedsigner.models.settings_definition import SettingsConstants def test_p2tr_change_detection(): + """ Should successfully detect change in a p2tr to p2tr psbt spend + + PSBT Tx and Wallet Details + - Single Sig Wallet P2TR (Taproot) with no passphrase + - Regtest 394aed14 m/86'/1'/0' tpubDCawGrRg7YdHdFb9p4mmD8GBaZjJegL53FPFRrMkGoLcgLATJfksUs2y1Q7dVzixAkgecazsxEsUuyj3LyDw7eVVYHQyojwrc2hfesK4wXW + - 1 Inputs + - 3,190,493,401 sats + - 2 Outputs + - 1 Output spend to another wallet (bcrt1p6p00wazu4nnqac29fvky6vhjnnhku5u2g9njss62rvy7e0yuperq86f5ek) p2tr address + - 1 Output change + - addresss bcrt1prz4g6saush37epdwhvwpu78td3q7yfz3xxz37axlx7udck6wracq3rwq30) + - amount 2,871,443,918 sats + - Change addresses is index 1/1 + - Fee 155 sats + """ + psbt_base64 = "cHNidP8BAIkCAAAAAf8upuiIWF1VTgC/Q8ZWRrameRigaXpRcQcBe8ye+TK3AQAAAAAXCgAAAs7BJqsAAAAAIlEgGKqNQ7yF4+yFrrscHnjrbEHiJFExhR903ze43FtOH3BwTgQTAAAAACJRINBe93RcrOYO4UVLLE0y8pzvblOKQWcoQ0obCey8nA5GAAAAAE8BBDWHzwNMUx9OgAAAAJdr+WtwWfVa6IPbpKZ4KgRC0clbm11Gl155IPA27n2FAvQCrFGH6Ac2U0Gcy1IH5f5ltgUBDz2+fe8iqL6JzZdgEDlK7RRWAACAAQAAgAAAAIAAAQB9AgAAAAGAKOOUFIzw9pbRDaZ7F0DYhLImrdMn//OSm++ff5VNdAAAAAAAAQAAAAKsjLwAAAAAABYAFKEcuxvXmB3rWHSqSviP5mrKMZoL2RArvgAAAAAiUSBGU0Lg5fx/ECsB1Z4ZUqXQFSLFnlmpm0rm5R2l599h2AAAAAABASvZECu+AAAAACJRIEZTQuDl/H8QKwHVnhlSpdAVIsWeWambSublHaXn32HYAQMEAAAAACEWF7hZVn7pIDR429kAn/WDeQiWjZey1iGHztsL1H83QLMZADlK7RRWAACAAQAAgAAAAIABAAAAAAAAAAEXIBe4WVZ+6SA0eNvZAJ/1g3kIlo2XstYhh87bC9R/N0CzACEHbJdqWyMxF2eOPr6YRXUJmry04HUbgKyeM2IZeG+NI9AZADlK7RRWAACAAQAAgAAAAIABAAAAAQAAAAEFIGyXalsjMRdnjj6+mEV1CZq8tOB1G4CsnjNiGXhvjSPQAAA=" raw = a2b_base64(psbt_base64)