From ca61e0d8f763fe10d370f2cac60a029656b1a2fa Mon Sep 17 00:00:00 2001 From: Jean Do Date: Sun, 21 Jul 2024 08:02:37 -0400 Subject: [PATCH 1/2] also tries to get descriptor from qr:urtype.Account --- src/krux/wallet.py | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/src/krux/wallet.py b/src/krux/wallet.py index 7b1fe74e3..367c7d20b 100644 --- a/src/krux/wallet.py +++ b/src/krux/wallet.py @@ -207,6 +207,15 @@ def parse_wallet(wallet_data, allow_assumption=None): except: pass + # Try to parse as a Crypto-Account type + try: + account = urtypes.crypto.Account.from_cbor( + wallet_data.cbor + ).output_descriptors[0] + return Descriptor.from_string(account.descriptor()), None + except: + pass + # Treat the UR as a generic UR bytes object and extract the data for further processing wallet_data = urtypes.Bytes.from_cbor(wallet_data.cbor).data From 16b6d28e8a177f5b2c7056d5ff0b5444d8d72928 Mon Sep 17 00:00:00 2001 From: Jean Do Date: Tue, 23 Jul 2024 16:36:11 -0400 Subject: [PATCH 2/2] tests for wallet descriptor via UR:Account/Output --- tests/test_wallet.py | 57 ++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 57 insertions(+) diff --git a/tests/test_wallet.py b/tests/test_wallet.py index 25389cad4..c5b0c1358 100644 --- a/tests/test_wallet.py +++ b/tests/test_wallet.py @@ -1,4 +1,5 @@ import pytest +from ur.ur_decoder import URDecoder @pytest.fixture @@ -979,3 +980,59 @@ def test_derivation_to_script_wrapper(): for _case in cases: assert derivation_to_script_wrapper(_case[0]) == _case[1] + + +def test_parse_wallet_via_ur_output(mocker, m5stickv): + from krux.wallet import parse_wallet + + # sparrow uses this ur format + QRDATA = [ + # testnet legacy p2pkh + "UR:CRYPTO-OUTPUT/TAADMUTAADDLOSAOWKAXHDCLAXJPDPECBNTOVEKOVOADIHWDDIBKHTHYAECWBSWPDEYTMSLEDRBSPMAMDEVAURWFDWAAHDCXKKSGMELBWMKOFRDMOEDAUEMUQDVDVANEBGVOMYGLKOVSFDSKDEJYKOGDGTINETTOAHTAADEHOEADAEAOADAMTAADDYOTADLNCSDWYKADYKAEYKAOCYTBFSSSOSAXAXAYCYLBZMISPFASIMGUIHIHIEGUINIOJTIHJPMEZMDWFY", + # testnet nested segwit + "UR:CRYPTO-OUTPUT/TAADMHTAADMWTAADDLOSAOWKAXHDCLAXPKGWJSLTINFRRELGGHECCMJLLKADKSHDRLDNDARLBZBACHSNAHHGNLDLLBGSTICFAAHDCXRPEETDCMQDWKBDPSBYJETBLGKTDNDRMSHHRFDIBEDREOLEKTBGMTBBOTKPFPWFWNAHTAADEHOEADAEAOADAMTAADDYOTADLNCSEHYKADYKAEYKAOCYTBFSSSOSAXAXAYCYINOTTORLASIEGRJPKPKSRYCEWNPF", + # testnet native segwit + "UR:CRYPTO-OUTPUT/TAADMWTAADDLOSAOWKAXHDCLAXRFBBVARYHNRLIMTLFEASUEOSGSRYOLBTCTSAHTIHKIDAMNPKLKFZTBHHMKKGKKGUAAHDCXHKMEMSKTVLNLSWDLUOGRDYBSFYIYIEJLCYVSJLNLMDLPJPNNGSSFMEIHHYCHLGENAHTAADEHOEADAEAOADAMTAADDYOTADLNCSGHYKADYKAEYKAOCYTBFSSSOSAXAXAYCYIDWEJPPKASIHFWGAGDEOESYKNYPEOT", + # testnet taproot + "UR:CRYPTO-OUTPUT/TAADNLTAADDLOSAOWKAXHDCLAOUYWTLNPRWYDIBNZCWEMHVWSTJYLGCNISEOPSEETEDMZTBSYTATJLAEZMNYDEEHCAAAHDCXHTRLUYDIRDNLDSYAZEKESWDYMTWNGSVAKTVWFGFEGUCSDNPDDTFRZMRTUTNSBSGTAHTAADEHOEADAEAOADAMTAADDYOTADLNCSHFYKADYKADYKAOCYTBFSSSOSAXAXAYCYOEWNPFHKASIMGUIHIHIEGUINIOJTIHJPDKZSVSIS", + ] + DESCRIPTORS = [ + "pkh([d63dc4a7/44h/1h/0h]tpubDCxxwY2QwiUCq8ievg9BurvmxfSa8LStd6XLh6meDBjK2BWynxq8M7d99P9yNBaCxSkUcxZrvnwgUsXbqP8SyJZY21C7Cm1R7M36xxSeiS6)", + "sh(wpkh([d63dc4a7/49h/1h/0h]tpubDCoS7zq26q1CC75oB7zcNRvbXbQwAUf9gnhaS5vDYEZA2F8Maz7taNiKGbEWGY1fxEyWQgvCCQRGNBz87qej9XuyMXpTCtDbbKP6fXGtio1))", + "wpkh([d63dc4a7/84h/1h/0h]tpubDCka9mfAaAN3cit16QqK2RCRVBpA2B7b8RFWUCLdyKR8eA48pjX7kZ5RAM6bSdwD9ivwh33KES7Q4DcqzNwkNUyyadZTTLf36Xp955vUBdf)", + "tr([d63dc4a7/86h/1h/1h]tpubDDDs2UVFbhXBRTW4EJEH74qDcdVetqn5pF2AMcpMCfwvU561GJiY4BZoLPSpw4d6cb7wVHyu1JNa3dVjhKgmTKZ6m8M4L6wv763gHjhYAfd)", + ] + + for i, QRDATUM in enumerate(QRDATA): + wallet_data = URDecoder().decode(QRDATUM) + descriptor, label = parse_wallet(wallet_data) + assert str(descriptor) == DESCRIPTORS[i] + print(DESCRIPTORS[i]) + + +def test_parse_wallet_via_ur_account(mocker, m5stickv): + from krux.wallet import parse_wallet + + # seedsigner uses this ur format when exporting for sparrow + QRDATA = [ + # mainnet legacy p2pkh + "UR:CRYPTO-ACCOUNT/OEADCYTBFSSSOSAOLYTAADMUTAADDLOXAXHDCLAODNLFAHCFGUJOYLESGDYNVANSDRGYTISWRTMWTTIAGUADAMPLONLAAEKPZOLGHSPMAAHDCXOLEOFRMSGELTHFPRJNVEECBBHDGOONEHMHBBTDVDAMCXVDMDROBZCWUYLDRERNHSAMTAADDYOTADLNCSDWYKAEYKAEYKAOCYTBFSSSOSAXAXAYCYBTWMBGPTAXUOCEVY", + # mainnet nested segwit + "UR:CRYPTO-ACCOUNT/OEADCYTBFSSSOSAOLYTAADMHTAADMWTAADDLOXAXHDCLAOFNVAJKFZAXCPCMJSAYYNYLCHEYESNLWDISVTVODAVTFZVEWLAMWYLDBNNTBEKECTAAHDCXSPYLEYCFMSHKJLGOMTTTEHCMNEPYSEIADTKPNBPMPKONIEWYAHPRADWDONYNGMSKAMTAADDYOTADLNCSEHYKAEYKAEYKAOCYTBFSSSOSAXAXAYCYVEZSGMCXTKYTCMKN", + # mainnet native segwit + "UR:CRYPTO-ACCOUNT/OEADCYTBFSSSOSAOLYTAADMWTAADDLOXAXHDCLAXZOCTGEIDHKEHSBHSDEZTJZWZJLFLMYAARSRFBWCLIDNELEVDDTWEDAMYURAECKSAAAHDCXGOSKCMDTKPFZJZSRJZHFHDQZJYLTIAZTQZMTZOCAIOCEECUESKAYECWFKPJZGOSPAMTAADDYOTADLNCSGHYKAEYKAEYKAOCYTBFSSSOSAXAXAYCYTBTEAXAODTCFGMBK", + # mainnet taproot + "UR:CRYPTO-ACCOUNT/OEADCYTBFSSSOSAOLYTAADNLTAADDLOXAXHDCLAXLKOENLDTDIFXOYDYUYHGOLFXSESOQZOXWSRTMHINPMSGKPNSHYIEBZVYVYRODKCEAAHDCXFTIDJNMSDWWPFDZSBNLSAORSKGGHTPGYFERSQDSFVSFWFYCYAOINCLWFLKSPMHFYAMTAADDYOTADLNCSHFYKAEYKAEYKAOCYTBFSSSOSAXAXAYCYKIWKJKVDYKTDJNUY", + ] + DESCRIPTORS = [ + "pkh([d63dc4a7/44h/0h/0h]xpub6Bkhh15pTDsqX2kEBaqLL9YTNwMBNkn8eL4vPEzPkKPG3dU1CtgNEfz6qMRH7ek8gonFWUe73Jg6Z2zVpYZMMgoXKsAnsuyFF6B3kZX81ed)", + "sh(wpkh([d63dc4a7/49h/0h/0h]xpub6DLPFknTv1YuRkTAmXXkrdcMVtsWjwMG1WkCKgQqP2LbEfhbn4EyYGo8gxgqF6jozRfQEVafJRnt57Ua2gXXBqyPvKPzuQRQpfYbyEUh8Z1))", + "wpkh([d63dc4a7/84h/0h/0h]xpub6DEMJ2Yce8xR9qAD4ZNfV4HuhhYCgNYbjDoZnuJprRQBtZCE7fgTLfLYdao26s3Pva1PBySwnSx9AtRtpSC3AsJ6LYuhKy1brMoc3Qe16t7)", + "tr([d63dc4a7/86h/0h/0h]xpub6CaTuhnAha3kjK1bZQxYbmyw8PcM6UypdK9MTdJY41Xxyg2dVws9LwuB5bL1fFPqJiAkBAoSwpcfEjEwwJ2byNeM4xxXKSa45TcHxLhQKPh)", + ] + + for i, QRDATUM in enumerate(QRDATA): + wallet_data = URDecoder().decode(QRDATUM) + descriptor, label = parse_wallet(wallet_data) + assert str(descriptor) == DESCRIPTORS[i] + print(DESCRIPTORS[i])