diff --git a/tests/test_sign_psbt_v1.py b/tests/test_sign_psbt_v1.py index aa3afce0..bfe5420a 100644 --- a/tests/test_sign_psbt_v1.py +++ b/tests/test_sign_psbt_v1.py @@ -1,34 +1,19 @@ # Tests using the V1 version of the wallet policy language, used before version 2.1.0 of the app # Make sure we remain compatible for some time. -import pytest - -import threading - -from decimal import Decimal - -from typing import List - from pathlib import Path from ledger_bitcoin import WalletPolicy, MultisigWallet, AddressType, WalletType, PartialSignature -from ledger_bitcoin.exception.errors import IncorrectDataError, NotSupportedError -from ledger_bitcoin.exception.device_exception import DeviceException from ledger_bitcoin.psbt import PSBT from ledger_bitcoin.wallet import AddressType -from test_utils import bip0340, txmaker +from test_utils import bip0340 -from embit.script import Script from embit.networks import NETWORKS -from ragger.navigator import Navigator, NavInsID -from ragger.error import ExceptionRAPDU +from ragger.navigator import Navigator from ragger.firmware import Firmware -import requests -import json - from ragger_bitcoin import RaggerClient from .instructions import * @@ -63,13 +48,15 @@ def test_sign_psbt_singlesig_pkh_1to1_v1(navigator: Navigator, firmware: Firmwar # "pubkey" : "02ee8608207e21028426f69e76447d7e3d5e077049f5e683c3136c2314762a4718", # "signature" : "3045022100e55b3ca788721aae8def2eadff710e524ffe8c9dec1764fdaa89584f9726e196022012a30fbcf9e1a24df31a1010356b794ab8de438b4250684757ed5772402540f401" result = client.sign_psbt(psbt, wallet, None, navigator, - instructions=sign_psbt_instruction_approve(firmware), + instructions=sign_psbt_instruction_approve( + firmware), testname=test_name) assert result == [( 0, PartialSignature( - pubkey=bytes.fromhex("02ee8608207e21028426f69e76447d7e3d5e077049f5e683c3136c2314762a4718"), + pubkey=bytes.fromhex( + "02ee8608207e21028426f69e76447d7e3d5e077049f5e683c3136c2314762a4718"), signature=bytes.fromhex( "3045022100e55b3ca788721aae8def2eadff710e524ffe8c9dec1764fdaa89584f9726e196022012a30fbcf9e1a24df31a1010356b794ab8de438b4250684757ed5772402540f401" ) @@ -80,7 +67,8 @@ def test_sign_psbt_singlesig_pkh_1to1_v1(navigator: Navigator, firmware: Firmwar def test_sign_psbt_singlesig_sh_wpkh_1to2_v1(navigator: Navigator, firmware: Firmware, client: RaggerClient, test_name: str): # PSBT for a wrapped segwit 1-input 2-output spend (1 change address) - psbt = open_psbt_from_file(f"{tests_root}/psbt/singlesig/sh-wpkh-1to2.psbt") + psbt = open_psbt_from_file( + f"{tests_root}/psbt/singlesig/sh-wpkh-1to2.psbt") wallet = WalletPolicy( "", @@ -96,13 +84,15 @@ def test_sign_psbt_singlesig_sh_wpkh_1to2_v1(navigator: Navigator, firmware: Fir # "pubkey" : "024ba3b77d933de9fa3f9583348c40f3caaf2effad5b6e244ece8abbfcc7244f67", # "signature" : "30440220720722b08489c2a50d10edea8e21880086c8e8f22889a16815e306daeea4665b02203fcf453fa490b76cf4f929714065fc90a519b7b97ab18914f9451b5a4b45241201" result = client.sign_psbt(psbt, wallet, None, navigator, - instructions=sign_psbt_instruction_approve_2(firmware), + instructions=sign_psbt_instruction_approve_2( + firmware), testname=test_name) assert result == [( 0, PartialSignature( - pubkey=bytes.fromhex("024ba3b77d933de9fa3f9583348c40f3caaf2effad5b6e244ece8abbfcc7244f67"), + pubkey=bytes.fromhex( + "024ba3b77d933de9fa3f9583348c40f3caaf2effad5b6e244ece8abbfcc7244f67"), signature=bytes.fromhex( "30440220720722b08489c2a50d10edea8e21880086c8e8f22889a16815e306daeea4665b02203fcf453fa490b76cf4f929714065fc90a519b7b97ab18914f9451b5a4b45241201" ) @@ -125,7 +115,8 @@ def test_sign_psbt_singlesig_wpkh_1to2_v1(navigator: Navigator, firmware: Firmwa ) result = client.sign_psbt(psbt, wallet, None, navigator, - instructions=sign_psbt_instruction_approve_2(firmware), + instructions=sign_psbt_instruction_approve_2( + firmware), testname=test_name) # expected sigs @@ -136,7 +127,8 @@ def test_sign_psbt_singlesig_wpkh_1to2_v1(navigator: Navigator, firmware: Firmwa assert result == [( 0, PartialSignature( - pubkey=bytes.fromhex("03ee2c3d98eb1f93c0a1aa8e5a4009b70eb7b44ead15f1666f136b012ad58d3068"), + pubkey=bytes.fromhex( + "03ee2c3d98eb1f93c0a1aa8e5a4009b70eb7b44ead15f1666f136b012ad58d3068"), signature=bytes.fromhex( "3045022100ab44f34dd7e87c9054591297a101e8500a0641d1d591878d0d23cf8096fa79e802205d12d1062d925e27b57bdcf994ecf332ad0a8e67b8fe407bab2101255da632aa01" ) @@ -160,7 +152,8 @@ def test_sign_psbt_singlesig_wpkh_2to2_v1(navigator: Navigator, firmware: Firmwa ) result = client.sign_psbt(psbt, wallet, None, navigator, - instructions=sign_psbt_instruction_approve(firmware), + instructions=sign_psbt_instruction_approve( + firmware), testname=test_name) # expected sigs @@ -174,7 +167,8 @@ def test_sign_psbt_singlesig_wpkh_2to2_v1(navigator: Navigator, firmware: Firmwa assert result == [( 0, PartialSignature( - pubkey=bytes.fromhex("03455ee7cedc97b0ba435b80066fc92c963a34c600317981d135330c4ee43ac7a3"), + pubkey=bytes.fromhex( + "03455ee7cedc97b0ba435b80066fc92c963a34c600317981d135330c4ee43ac7a3"), signature=bytes.fromhex( "304402206b3e877655f08c6e7b1b74d6d893a82cdf799f68a5ae7cecae63a71b0339e5ce022019b94aa3fb6635956e109f3d89c996b1bfbbaf3c619134b5a302badfaf52180e01" ) @@ -182,7 +176,8 @@ def test_sign_psbt_singlesig_wpkh_2to2_v1(navigator: Navigator, firmware: Firmwa ), ( 1, PartialSignature( - pubkey=bytes.fromhex("0271b5b779ad870838587797bcf6f0c7aec5abe76a709d724f48d2e26cf874f0a0"), + pubkey=bytes.fromhex( + "0271b5b779ad870838587797bcf6f0c7aec5abe76a709d724f48d2e26cf874f0a0"), signature=bytes.fromhex( "3045022100e2e98e4f8c70274f10145c89a5d86e216d0376bdf9f42f829e4315ea67d79d210220743589fd4f55e540540a976a5af58acd610fa5e188a5096dfe7d36baf3afb94001" ) @@ -209,13 +204,15 @@ def test_sign_psbt_multisig_wsh_v1(navigator: Navigator, firmware: Firmware, cli psbt = open_psbt_from_file(f"{tests_root}/psbt/multisig/wsh-2of2.psbt") result = client.sign_psbt(psbt, wallet, wallet_hmac, navigator, - instructions=sign_psbt_instruction_approve_6(firmware), + instructions=sign_psbt_instruction_approve_6( + firmware), testname=test_name) assert result == [( 0, PartialSignature( - pubkey=bytes.fromhex("036b16e8c1f979fa4cc0f05b6a300affff941459b6f20de77de55b0160ef8e4cac"), + pubkey=bytes.fromhex( + "036b16e8c1f979fa4cc0f05b6a300affff941459b6f20de77de55b0160ef8e4cac"), signature=bytes.fromhex( "304402206ab297c83ab66e573723892061d827c5ac0150e2044fed7ed34742fedbcfb26e0220319cdf4eaddff63fc308cdf53e225ea034024ef96de03fd0939b6deeea1e8bd301" ) @@ -226,7 +223,8 @@ def test_sign_psbt_multisig_wsh_v1(navigator: Navigator, firmware: Firmware, cli def test_sign_psbt_taproot_1to2_v1(navigator: Navigator, firmware: Firmware, client: RaggerClient, test_name: str): # PSBT for a p2tr 1-input 2-output spend (1 change address) - psbt = open_psbt_from_file(f"{tests_root}/psbt/singlesig/tr-1to2-sighash-all.psbt") + psbt = open_psbt_from_file( + f"{tests_root}/psbt/singlesig/tr-1to2-sighash-all.psbt") wallet = WalletPolicy( "", @@ -238,7 +236,8 @@ def test_sign_psbt_taproot_1to2_v1(navigator: Navigator, firmware: Firmware, cli ) result = client.sign_psbt(psbt, wallet, None, navigator, - instructions=sign_psbt_instruction_approve(firmware), + instructions=sign_psbt_instruction_approve( + firmware), testname=test_name) assert len(result) == 1 @@ -247,7 +246,8 @@ def test_sign_psbt_taproot_1to2_v1(navigator: Navigator, firmware: Firmware, cli # transaction was sent), and we verify the produced Schnorr signature with the reference bip340 implementation. # sighash verified with bitcoin-core - sighash0 = bytes.fromhex("7A999E5AD6F53EA6448E7026061D3B4523F957999C430A5A492DFACE74AE31B6") + sighash0 = bytes.fromhex( + "7A999E5AD6F53EA6448E7026061D3B4523F957999C430A5A492DFACE74AE31B6") # get the (tweaked) pubkey from the scriptPubKey pubkey0_psbt = psbt.inputs[0].witness_utxo.scriptPubKey[2:] @@ -260,177 +260,8 @@ def test_sign_psbt_taproot_1to2_v1(navigator: Navigator, firmware: Firmware, cli assert len(partial_sig0.signature) == 64+1 assert partial_sig0.signature[-1] == 0x01 - assert bip0340.schnorr_verify(sighash0, pubkey0_psbt, partial_sig0.signature[:-1]) - - -def test_sign_psbt_singlesig_wpkh_4to3_v1(navigator: Navigator, firmware: Firmware, client: - RaggerClient, test_name: str): - # PSBT for a segwit 4-input 3-output spend (1 change address) - # this test also checks that addresses, amounts and fees shown on screen are correct - - wallet = WalletPolicy( - "", - "wpkh(@0)", - [ - "[f5acc2fd/84'/1'/0']tpubDCtKfsNyRhULjZ9XMS4VKKtVcPdVDi8MKUbcSD9MJDyjRu1A2ND5MiipozyyspBT9bg8upEp7a8EAgFxNxXn1d7QkdbL52Ty5jiSLcxPt1P/**" - ], - version=WalletType.WALLET_POLICY_V1 - ) - - n_ins = 4 - n_outs = 3 - - in_amounts = [10000 + 10000 * i for i in range(n_ins)] - sum_in = sum(in_amounts) - out_amounts = [sum_in // n_outs - i for i in range(n_outs)] - - change_index = 1 - - psbt = txmaker.createPsbt( - wallet, - in_amounts, - out_amounts, - [i == change_index for i in range(n_outs)] - ) - - sum_out = sum(out_amounts) - - assert sum_out < sum_in - - result = client.sign_psbt(psbt, wallet, None, navigator, - instructions=sign_psbt_instruction_approve_9(firmware), - testname=test_name) - - assert len(result) == n_ins - - -def test_sign_psbt_singlesig_large_amount_v1(navigator: Navigator, firmware: Firmware, client: - RaggerClient, test_name: str): - # Test with a transaction with an extremely large amount - - wallet = WalletPolicy( - "", - "wpkh(@0)", - [ - "[f5acc2fd/84'/1'/0']tpubDCtKfsNyRhULjZ9XMS4VKKtVcPdVDi8MKUbcSD9MJDyjRu1A2ND5MiipozyyspBT9bg8upEp7a8EAgFxNxXn1d7QkdbL52Ty5jiSLcxPt1P/**" - ], - version=WalletType.WALLET_POLICY_V1 - ) - - in_amounts = [21_000_000*100_000_000] - out_amounts = [21_000_000*100_000_000 - 100_000] - - psbt = txmaker.createPsbt(wallet, in_amounts, out_amounts, [False]) - - sum_in = sum(in_amounts) - sum_out = sum(out_amounts) - - assert sum_out < sum_in - - result = client.sign_psbt(psbt, wallet, None, navigator, - instructions=sign_psbt_instruction_approve(firmware), - testname=test_name) - - assert len(result) == 1 - - -def test_sign_psbt_singlesig_wpkh_512to256_v1(navigator: Navigator, firmware: Firmware, client: - RaggerClient, test_name: str, enable_slow_tests: bool): - # PSBT for a transaction with 512 inputs and 256 outputs (maximum currently supported in the app) - # Very slow test (esp. with DEBUG enabled), so disabled unless the --enableslowtests option is used - - if not enable_slow_tests: - pytest.skip() - - n_inputs = 512 - n_outputs = 256 - - wallet = WalletPolicy( - "", - "tr(@0)", - [ - "[f5acc2fd/86'/1'/0']tpubDDKYE6BREvDsSWMazgHoyQWiJwYaDDYPbCFjYxN3HFXJP5fokeiK4hwK5tTLBNEDBwrDXn8cQ4v9b2xdW62Xr5yxoQdMu1v6c7UDXYVH27U/**" - ], - version=WalletType.WALLET_POLICY_V1 - ) - - psbt = txmaker.createPsbt( - wallet, - [10000 + 10000 * i for i in range(n_inputs)], - [999 + 99 * i for i in range(n_outputs)], - [i == 42 for i in range(n_outputs)] - ) - - result = client.sign_psbt(psbt, wallet, None, None) - - assert len(result) == n_inputs - - -def test_sign_psbt_fail_11_changes_v1(navigator: Navigator, firmware: Firmware, client: - RaggerClient, test_name: str): - # PSBT for transaction with 11 change addresses; the limit is 10, so it must fail with NotSupportedError - # before any user interaction - - wallet = WalletPolicy( - "", - "wpkh(@0)", - [ - "[f5acc2fd/84'/1'/0']tpubDCtKfsNyRhULjZ9XMS4VKKtVcPdVDi8MKUbcSD9MJDyjRu1A2ND5MiipozyyspBT9bg8upEp7a8EAgFxNxXn1d7QkdbL52Ty5jiSLcxPt1P/**" - ], - version=WalletType.WALLET_POLICY_V1 - ) - - psbt = txmaker.createPsbt( - wallet, - [11 * 100_000_000 + 1234], - [100_000_000] * 11, - [True] * 11, - ) - - with pytest.raises(ExceptionRAPDU) as e: - client.sign_psbt(psbt, wallet, None, navigator, - instructions=sign_psbt_instruction_tap(firmware), - testname=test_name) - - assert DeviceException.exc.get(e.value.status) == NotSupportedError - assert len(e.value.data) == 0 - - -def test_sign_psbt_fail_wrong_non_witness_utxo_v1(navigator: Navigator, firmware: Firmware, client: - RaggerClient, test_name: str): - # PSBT for transaction with the wrong non-witness utxo for an input. - # It must fail with IncorrectDataError before any user interaction. - - wallet = WalletPolicy( - "", - "wpkh(@0)", - [ - "[f5acc2fd/84'/1'/0']tpubDCtKfsNyRhULjZ9XMS4VKKtVcPdVDi8MKUbcSD9MJDyjRu1A2ND5MiipozyyspBT9bg8upEp7a8EAgFxNxXn1d7QkdbL52Ty5jiSLcxPt1P/**" - ], - version=WalletType.WALLET_POLICY_V1 - ) - - psbt = txmaker.createPsbt( - wallet, - [3 * 100_000_000], - [1 * 100_000_000, 2 * 100_000_000], - [False, True] - ) - - # Modify the non_witness_utxo so that the txid does not matches - wit = psbt.inputs[0].non_witness_utxo - wit.nLockTime = wit.nLockTime ^ 1 # change one bit of nLockTime arbitrarily to change the txid - wit.rehash() - psbt.inputs[0].non_witness_utxo = wit - - client._no_clone_psbt = True - with pytest.raises(ExceptionRAPDU) as e: - client.sign_psbt(psbt, wallet, None, navigator, - instructions=sign_psbt_instruction_approve(firmware), - testname=test_name) - assert DeviceException.exc.get(e.value.status) == IncorrectDataError - assert len(e.value.data) == 0 - client._no_clone_psbt = False + assert bip0340.schnorr_verify( + sighash0, pubkey0_psbt, partial_sig0.signature[:-1]) def test_sign_psbt_with_opreturn_v1(navigator: Navigator, firmware: Firmware, client: RaggerClient, test_name: str): @@ -448,7 +279,8 @@ def test_sign_psbt_with_opreturn_v1(navigator: Navigator, firmware: Firmware, cl psbt.deserialize(psbt_b64) hww_sigs = client.sign_psbt(psbt, wallet, None, navigator, - instructions=sign_psbt_instruction_approve_opreturn(firmware), + instructions=sign_psbt_instruction_approve_opreturn( + firmware), testname=test_name) assert len(hww_sigs) == 1 @@ -474,7 +306,8 @@ def test_sign_psbt_with_segwit_v16_v1(navigator: Navigator, firmware: Firmware, ) hww_sigs = client.sign_psbt(psbt, wallet, None, navigator, - instructions=sign_psbt_instruction_approve(firmware), + instructions=sign_psbt_instruction_approve( + firmware), testname=test_name) assert len(hww_sigs) == 1