def test_multisig_mismatch_inputs(client: Client): multisig_out1 = messages.MultisigRedeemScriptType( nodes=[NODE_EXT2, NODE_EXT1, NODE_INT], address_n=[1, 0], signatures=[b"", b"", b""], m=2, ) out1 = messages.TxOutputType( address_n=[H_(45), 0, 1, 0], multisig=multisig_out1, amount=40_000_000, script_type=messages.OutputScriptType.PAYTOMULTISIG, ) out2 = messages.TxOutputType( address="3PkXLsY7AUZCrCKGvX8FfP2EawowUBMbcg", amount=65_000_000, script_type=messages.OutputScriptType.PAYTOADDRESS, ) with client: client.set_expected_responses(_responses(INP1, INP3)) _, serialized_tx = btc.sign_tx( client, "Bitcoin", [INP1, INP3], [out1, out2], prev_txes=TX_API, ) assert ( serialized_tx.hex() == "0100000002e53cf4e3fcd37f8c439286ce636476e1faeebf86bbb2f228a6b78d1b47c8c61601000000b500483045022100d907b9339951c96ef4515ef7aff8b3c28c4c8c5875d7421aa1de9f3a94e3508302205cdc311a6c91dfbb74f1a9a940a994a65dbfb0cf6dedcaaaeee839e0b8fd016d014c69522103dc07026aacb5918dac4e09f9da8290d0ae22161699636c22cace78082116a7792103e70db185fad69c2971f0107a42930e5d82a9ed3a11b922a96fdfc4124b63e54c2103f3fe007a1e34ac76c1a2528e9149f90f9f93739929797afab6a8e18d682fa71053aeffffffff39f756d82082b580b0d69ae8798ff10a981820ccfe1ab149a708a37bc26d94b000000000b500483045022100fdad4a47d15f47cc364fe0cbed11b1ced1f9ef210bc1bd413ec4384f630c63720220752e4f09ea4e5e6623f5ebe89b3983ec6e5702f63f9bce696f10b2d594d23532014c6952210297ad8a5df42f9e362ef37d9a4ddced89d8f7a143690649aa0d0ff049c7daca842103b6321a1194e5cc47b6b7edc3f67a096e6f71ccb72440f84f390b6e98df0ea8ec2103f91460d79e4e463d7d90cb75254bcd62b515a99a950574c721efdc5f711dff3553aeffffffff02005a62020000000017a91466528dd543f94d162c8111d2ec248d25ba9b90948740d2df030000000017a914f1fc92c0aed1712911c70a2e09ac15ff0922652f8700000000" )
def test_set_failed(client: Client): assert client.features.pin_protection is False # Check that there's no PIN protection _check_no_pin(client) # Let's set new PIN def input_flow(): yield # do you want to set pin? client.debug.press_yes() yield # enter new pin client.debug.input(PIN4) yield # enter new pin again (but different) client.debug.input(PIN60) # failed retry yield # enter new pin client.cancel() with client, pytest.raises(Cancelled): client.set_expected_responses([messages.ButtonRequest] * 4 + [messages.Failure]) client.set_input_flow(input_flow) device.change_pin(client) # Check that there's still no PIN protection now client.init_device() assert client.features.pin_protection is False _check_no_pin(client)
def backup_flow_bip39(client: Client): mnemonic = None def input_flow(): nonlocal mnemonic # 1. Confirm Reset yield from click_through(client.debug, screens=1, code=B.ResetDevice) # mnemonic phrases mnemonic = yield from read_and_confirm_mnemonic(client.debug) # confirm recovery seed check br = yield assert br.code == B.Success client.debug.press_yes() # confirm success br = yield assert br.code == B.Success client.debug.press_yes() with client: client.set_expected_responses([ messages.ButtonRequest(code=B.ResetDevice), messages.ButtonRequest(code=B.ResetDevice), messages.ButtonRequest(code=B.Success), messages.ButtonRequest(code=B.Success), messages.Success, messages.Features, ]) client.set_input_flow(input_flow) device.backup(client) return mnemonic.encode()
def test_change_failed(client: Client): assert client.features.pin_protection is True # Check current PIN value _check_pin(client, PIN4) # Let's set new PIN def input_flow(): yield # do you want to change pin? client.debug.press_yes() yield # enter current pin client.debug.input(PIN4) yield # enter new pin client.debug.input("457891") yield # enter new pin again (but different) client.debug.input("381847") # failed retry yield # enter current pin again client.cancel() with client, pytest.raises(Cancelled): client.set_expected_responses([messages.ButtonRequest] * 5 + [messages.Failure]) client.set_input_flow(input_flow) device.change_pin(client) # Check that there's still old PIN protection client.init_device() assert client.features.pin_protection is True _check_pin(client, PIN4)
def test_send_bch_external_presigned(client: Client): inp1 = messages.TxInputType( # address_n=parse_path("44'/145'/0'/1/0"), # bitcoincash:qzc5q87w069lzg7g3gzx0c8dz83mn7l02scej5aluw amount=1_896_050, prev_hash=TXHASH_502e85, prev_index=0, script_type=messages.InputScriptType.EXTERNAL, script_pubkey=bytes.fromhex( "76a914b1401fce7e8bf123c88a0467e0ed11e3b9fbef5488ac"), script_sig=bytes.fromhex( "47304402207a2a955f1cb3dc5f03f2c82934f55654882af4e852e5159639f6349e9386ec4002205fb8419dce4e648eae8f67bc4e369adfb130a87d2ea2d668f8144213b12bb457412103174c61e9c5362507e8061e28d2c0ce3d4df4e73f3535ae0b12f37809e0f92d2d" ), ) inp2 = messages.TxInputType( address_n=parse_path("m/44h/145h/0h/0/1"), # bitcoincash:qr23ajjfd9wd73l87j642puf8cad20lfmqdgwvpat4 amount=73_452, prev_hash=TXHASH_502e85, prev_index=1, script_type=messages.InputScriptType.SPENDADDRESS, ) out1 = messages.TxOutputType( address="bitcoincash:qq6wnnkrz7ykaqvxrx4hmjvayvzjzml54uyk76arx4", amount=1_934_960, script_type=messages.OutputScriptType.PAYTOADDRESS, ) with client: client.set_expected_responses([ request_input(0), request_input(1), request_output(0), messages.ButtonRequest(code=B.ConfirmOutput), messages.ButtonRequest(code=B.SignTx), request_input(0), request_meta(TXHASH_502e85), request_input(0, TXHASH_502e85), request_output(0, TXHASH_502e85), request_output(1, TXHASH_502e85), request_input(1), request_meta(TXHASH_502e85), request_input(0, TXHASH_502e85), request_output(0, TXHASH_502e85), request_output(1, TXHASH_502e85), request_input(0), request_input(1), request_output(0), request_finished(), ]) _, serialized_tx = btc.sign_tx(client, "Bcash", [inp1, inp2], [out1], prev_txes=TX_API) assert_tx_matches( serialized_tx, hash_link= "https://bch1.trezor.io/api/tx/5594fd9e5e26dcb4437cbbbba517401720849159bac4e2158e1e6401ffd5fdb7", tx_hex= "01000000022c06cf6f215c5cbfd7caa8e71b1b32630cabf1f816a4432815b037b277852e50000000006a47304402207a2a955f1cb3dc5f03f2c82934f55654882af4e852e5159639f6349e9386ec4002205fb8419dce4e648eae8f67bc4e369adfb130a87d2ea2d668f8144213b12bb457412103174c61e9c5362507e8061e28d2c0ce3d4df4e73f3535ae0b12f37809e0f92d2dffffffff2c06cf6f215c5cbfd7caa8e71b1b32630cabf1f816a4432815b037b277852e50010000006a473044022062151cf960b71823bbe68c7ed2c2a93ad1b9706a30255fddb02fcbe056d8c26102207bad1f0872bc5f0cfaf22e45c925c35d6c1466e303163b75cb7688038f1a5541412102595caf9aeb6ffdd0e82b150739a83297358b9a77564de382671056ad9e5b8c58ffffffff0170861d00000000001976a91434e9cec317896e818619ab7dc99d2305216ff4af88ac00000000", )
def test_multisig_mismatch_change(client: Client): multisig_out2 = messages.MultisigRedeemScriptType( nodes=[NODE_EXT1, NODE_INT, NODE_EXT3], address_n=[1, 0], signatures=[b"", b"", b""], m=2, ) out1 = messages.TxOutputType( address="3B23k4kFBRtu49zvpG3Z9xuFzfpHvxBcwt", amount=40_000_000, script_type=messages.OutputScriptType.PAYTOADDRESS, ) out2 = messages.TxOutputType( address_n=[H_(45), 0, 1, 0], multisig=multisig_out2, amount=44_000_000, script_type=messages.OutputScriptType.PAYTOMULTISIG, ) with client: client.set_expected_responses(_responses(INP1, INP2)) _, serialized_tx = btc.sign_tx( client, "Bitcoin", [INP1, INP2], [out1, out2], prev_txes=TX_API, ) assert ( serialized_tx.hex() == "0100000002e53cf4e3fcd37f8c439286ce636476e1faeebf86bbb2f228a6b78d1b47c8c61601000000b40047304402207f9992cc0230527faf54ec6bd233307db82bc8fac039dcee418bc6feb4e96a3a02206bb4cb157ad27c123277328a877572563a45d70b844d9ab07cc42238112f8c2a014c69522103dc07026aacb5918dac4e09f9da8290d0ae22161699636c22cace78082116a7792103e70db185fad69c2971f0107a42930e5d82a9ed3a11b922a96fdfc4124b63e54c2103f3fe007a1e34ac76c1a2528e9149f90f9f93739929797afab6a8e18d682fa71053aeffffffff185315ae8050e18efa70d6ca96378a1194f57e2b102511f68b3a1414ee340cd800000000b400473044022078a41bfa87d72d6ba810d84bf568b5a29acf8b851ba6c3a8dbff079b34a7feb0022037b770c776db0b6c883c38a684a121b90a59ed1958774cbf64de70e53e29639f014c6952210297ad8a5df42f9e362ef37d9a4ddced89d8f7a143690649aa0d0ff049c7daca842103ed1fd93989595d7ad4b488efd05a22c0239482c9a20923f2f214a38e54f6c41a2103f91460d79e4e463d7d90cb75254bcd62b515a99a950574c721efdc5f711dff3553aeffffffff02005a62020000000017a91466528dd543f94d162c8111d2ec248d25ba9b90948700639f020000000017a914e6a3e2fbadb7f559f8d20c46aceae78c96fcf1d18700000000" )
def test_internal_external(client: Client): out1 = messages.TxOutputType( address_n=parse_path("m/45h/0/1/0"), amount=40_000_000, script_type=messages.OutputScriptType.PAYTOADDRESS, ) out2 = messages.TxOutputType( address="1H7uXJQTVwXca2BXF2opTrvuZapk8Cm8zY", amount=44_000_000, script_type=messages.OutputScriptType.PAYTOADDRESS, ) with client: client.set_expected_responses(_responses(INP1, INP2, change=1)) _, serialized_tx = btc.sign_tx( client, "Bitcoin", [INP1, INP2], [out1, out2], prev_txes=TX_API, ) # Transaction does not exist on the blockchain, not using assert_tx_matches() assert ( serialized_tx.hex() == "0100000002e53cf4e3fcd37f8c439286ce636476e1faeebf86bbb2f228a6b78d1b47c8c61601000000b400473044022064f13801744a6c21b694f62cdb5d834e852f13ecf85ed4d0a56ba279571c24e3022010fab4cb05bdd7b24c8376dda4f62a418548eea6eb483e58675fa06e0d5c642c014c69522103dc07026aacb5918dac4e09f9da8290d0ae22161699636c22cace78082116a7792103e70db185fad69c2971f0107a42930e5d82a9ed3a11b922a96fdfc4124b63e54c2103f3fe007a1e34ac76c1a2528e9149f90f9f93739929797afab6a8e18d682fa71053aeffffffff185315ae8050e18efa70d6ca96378a1194f57e2b102511f68b3a1414ee340cd800000000b4004730440220727b2522268f913acd213c507d7801b146e5b6cef666ad44b769c26d6c762e4d022021c0c2e9e8298dee2a490d956f7ab1b2d3160c1e37a50cc6d19a5e62eb484fc9014c6952210297ad8a5df42f9e362ef37d9a4ddced89d8f7a143690649aa0d0ff049c7daca842103ed1fd93989595d7ad4b488efd05a22c0239482c9a20923f2f214a38e54f6c41a2103f91460d79e4e463d7d90cb75254bcd62b515a99a950574c721efdc5f711dff3553aeffffffff02005a6202000000001976a9149b139230e4fe91c05a37ec334dc8378f3dbe377088ac00639f02000000001976a914b0d05a10926a7925508febdbab9a5bd4cda8c8f688ac00000000" )
def _check_no_pin(client: Client): client.lock() assert client.features.pin_protection is False with client: client.set_expected_responses([messages.Address]) btc.get_address(client, "Testnet", PASSPHRASE_TEST_PATH)
def test_wipe_device(client: Client): _assert_protection(client) with client: client.set_expected_responses( [messages.ButtonRequest, messages.Success, messages.Features] ) device.wipe(client)
def test_backup_bip39(client: Client): assert client.features.needs_backup is True mnemonic = None def input_flow(): nonlocal mnemonic yield # Confirm Backup client.debug.press_yes() # Mnemonic phrases mnemonic = yield from read_and_confirm_mnemonic(client.debug) yield # Confirm success client.debug.press_yes() yield # Backup is done client.debug.press_yes() with client: client.set_input_flow(input_flow) client.set_expected_responses([ messages.ButtonRequest(code=B.ResetDevice), messages.ButtonRequest(code=B.ResetDevice), messages.ButtonRequest(code=B.Success), messages.ButtonRequest(code=B.Success), messages.Success, messages.Features, ]) device.backup(client) assert mnemonic == MNEMONIC12 client.init_device() assert client.features.initialized is True assert client.features.needs_backup is False assert client.features.unfinished_backup is False assert client.features.no_backup is False assert client.features.backup_type is messages.BackupType.Bip39
def _check_pin(client: Client, pin): client.lock() with client: client.use_pin_sequence([pin]) client.set_expected_responses( [messages.PinMatrixRequest, messages.Address]) get_test_address(client)
def test_multisig_external_external(client: Client): out1 = messages.TxOutputType( address="3B23k4kFBRtu49zvpG3Z9xuFzfpHvxBcwt", amount=40_000_000, script_type=messages.OutputScriptType.PAYTOADDRESS, ) out2 = messages.TxOutputType( address="3PkXLsY7AUZCrCKGvX8FfP2EawowUBMbcg", amount=44_000_000, script_type=messages.OutputScriptType.PAYTOADDRESS, ) with client: client.set_expected_responses(_responses(INP1, INP2)) _, serialized_tx = btc.sign_tx( client, "Bitcoin", [INP1, INP2], [out1, out2], prev_txes=TX_API, ) # Transaction does not exist on the blockchain, not using assert_tx_matches() assert ( serialized_tx.hex() == "0100000002e53cf4e3fcd37f8c439286ce636476e1faeebf86bbb2f228a6b78d1b47c8c61601000000b400473044022059394e0dfcb2d2f4a6108703f801545ca5a820c0ac6a1859d0a3854813de55fa02207b6a57d70b82932ff58163336c461653a2dc82c78ed8157159e5178ac7325390014c69522103dc07026aacb5918dac4e09f9da8290d0ae22161699636c22cace78082116a7792103e70db185fad69c2971f0107a42930e5d82a9ed3a11b922a96fdfc4124b63e54c2103f3fe007a1e34ac76c1a2528e9149f90f9f93739929797afab6a8e18d682fa71053aeffffffff185315ae8050e18efa70d6ca96378a1194f57e2b102511f68b3a1414ee340cd800000000b40047304402205a911685f5b974b2fc4a19d5ce056218773a4d20b5eaae2c2f9594929308182002201e03449f5a8813ec19f408bf1b6f4f334886d6fcf9920e300fd7678ef0724f81014c6952210297ad8a5df42f9e362ef37d9a4ddced89d8f7a143690649aa0d0ff049c7daca842103ed1fd93989595d7ad4b488efd05a22c0239482c9a20923f2f214a38e54f6c41a2103f91460d79e4e463d7d90cb75254bcd62b515a99a950574c721efdc5f711dff3553aeffffffff02005a62020000000017a91466528dd543f94d162c8111d2ec248d25ba9b90948700639f020000000017a914f1fc92c0aed1712911c70a2e09ac15ff0922652f8700000000" )
def setup_device_core(client: Client, pin: str, wipe_code: str) -> None: device.wipe(client) debuglink.load_device( client, MNEMONIC12, pin, passphrase_protection=False, label="WIPECODE" ) def input_flow(): yield # do you want to set/change the wipe_code? client.debug.press_yes() if pin is not None: yield # enter current pin client.debug.input(pin) yield # enter new wipe code client.debug.input(wipe_code) yield # enter new wipe code again client.debug.input(wipe_code) yield # success client.debug.press_yes() with client: client.set_expected_responses( [messages.ButtonRequest()] * 5 + [messages.Success, messages.Features] ) client.set_input_flow(input_flow) device.change_wipe_code(client)
def test_invalid_path_fail_asap(client: Client): inp1 = messages.TxInputType( address_n=parse_path("m/0"), amount=1_000_000, prev_hash=b"\x42" * 32, prev_index=0, script_type=messages.InputScriptType.SPENDWITNESS, sequence=4_294_967_293, ) out1 = messages.TxOutputType( address_n=parse_path("m/84h/0h/0h/1/0"), amount=1_000_000, script_type=messages.OutputScriptType.PAYTOWITNESS, ) with client: client.set_expected_responses([ request_input(0), messages.Failure(code=messages.FailureType.DataError), ]) try: btc.sign_tx(client, "Testnet", [inp1], [out1]) except TrezorFailure: pass
def test_recovery_device(client: Client): assert client.features.pin_protection is False assert client.features.passphrase_protection is False client.use_mnemonic(MNEMONIC12) with client: client.set_expected_responses( [messages.ButtonRequest] + [messages.WordRequest] * 24 + [messages.Success, messages.Features] ) device.recover( client, 12, False, False, "label", "en-US", client.mnemonic_callback ) with pytest.raises(TrezorFailure): # This must fail, because device is already initialized # Using direct call because `device.recover` has its own check client.call( messages.RecoveryDevice( word_count=12, passphrase_protection=False, pin_protection=False, label="label", language="en-US", ) )
def test_reset_device(client: Client): assert client.features.pin_protection is False assert client.features.passphrase_protection is False os_urandom = mock.Mock(return_value=EXTERNAL_ENTROPY) with mock.patch("os.urandom", os_urandom), client: client.set_expected_responses( [messages.ButtonRequest] + [messages.EntropyRequest] + [messages.ButtonRequest] * 24 + [messages.Success, messages.Features] ) device.reset(client, False, 128, True, False, "label", "en-US") with pytest.raises(TrezorFailure): # This must fail, because device is already initialized # Using direct call because `device.reset` has its own check client.call( messages.ResetDevice( display_random=False, strength=128, passphrase_protection=True, pin_protection=False, label="label", language="en-US", ) )
def test_entropy(client: Client, entropy_length): with client: client.set_expected_responses( [m.ButtonRequest(code=m.ButtonRequestType.ProtectCall), m.Entropy]) ent = misc.get_entropy(client, entropy_length) assert len(ent) == entropy_length print(f"{entropy_length} bytes: entropy = {entropy(ent)}")
def test_change_invalid_current(client: Client): assert client.features.pin_protection is True # Check current PIN value _check_pin(client, PIN4) # Let's set new PIN def input_flow(): yield # do you want to change pin? client.debug.press_yes() yield # enter wrong current pin client.debug.input(PIN60) yield client.debug.press_no() with client, pytest.raises(TrezorFailure): client.set_expected_responses([messages.ButtonRequest] * 3 + [messages.Failure]) client.set_input_flow(input_flow) device.change_pin(client) # Check that there's still old PIN protection client.init_device() assert client.features.pin_protection is True _check_pin(client, PIN4)
def test_p2wpkh_with_false_proof(client: Client): inp1 = messages.TxInputType( # tb1qkvwu9g3k2pdxewfqr7syz89r3gj557l3uuf9r9 address_n=parse_path("m/84h/1h/0h/0/0"), prev_hash=TXHASH_70f987, prev_index=0, amount=100_000, script_type=messages.InputScriptType.SPENDWITNESS, ) inp2 = messages.TxInputType( # tb1qldlynaqp0hy4zc2aag3pkenzvxy65saesxw3wd # address_n=parse_path("m/84h/1h/0h/0/1"), prev_hash=TXHASH_65b768, prev_index=0, amount=10_000, script_type=messages.InputScriptType.EXTERNAL, script_pubkey=bytes.fromhex("0014fb7e49f4017dc951615dea221b66626189aa43b9"), ownership_proof=bytes.fromhex( "534c00190001b0b66657a824e41c063299fb4435dc70a6fd2e9db4c87e3c26a7ab7c0283547b000247304402206e285291aa955cb60b16acd69332eaada67ec5192d361fe4e2b384553e7e80c6022023470cfcb9c3251a136c26eb1637142206785a3d91b98583e5a1d6ab64fa91ed012103dcf3bc936ecb2ec57b8f468050abce8c8756e75fd74273c9977744b1a0be7d03" ), ) out1 = messages.TxOutputType( address="tb1qnspxpr2xj9s2jt6qlhuvdnxw6q55jvygcf89r2", amount=50_000, script_type=messages.OutputScriptType.PAYTOWITNESS, ) with client: client.set_expected_responses( [ request_input(0), request_input(1), request_output(0), messages.ButtonRequest(code=B.ConfirmOutput), messages.ButtonRequest(code=B.SignTx), request_input(0), request_meta(TXHASH_70f987), request_input(0, TXHASH_70f987), request_output(0, TXHASH_70f987), request_output(1, TXHASH_70f987), request_input(1), request_meta(TXHASH_65b768), request_input(0, TXHASH_65b768), request_output(0, TXHASH_65b768), request_output(1, TXHASH_65b768), messages.Failure(code=messages.FailureType.DataError), ] ) with pytest.raises(TrezorFailure, match="Invalid external input"): btc.sign_tx( client, "Testnet", [inp1, inp2], [out1], prev_txes=TX_CACHE_TESTNET, )
def test_spend_from_stake_generation_and_revocation_decred(client: Client): # NOTE: fake input tx used inp1 = messages.TxInputType( address_n=parse_path("m/44h/1h/0h/0/0"), prev_hash=FAKE_TXHASH_f8e2f2, prev_index=2, amount=200_000_000, script_type=messages.InputScriptType.SPENDADDRESS, decred_staking_spend=messages.DecredStakingSpendType.SSGen, decred_tree=1, ) inp2 = messages.TxInputType( address_n=parse_path("m/44h/1h/0h/0/0"), prev_hash=FAKE_TXHASH_51bc9c, prev_index=0, amount=200_000_000, script_type=messages.InputScriptType.SPENDADDRESS, decred_staking_spend=messages.DecredStakingSpendType.SSRTX, decred_tree=1, ) out1 = messages.TxOutputType( address="TscqTv1he8MZrV321SfRghw7LFBCJDKB3oz", amount=399_900_000, script_type=messages.OutputScriptType.PAYTOADDRESS, ) with client: client.set_expected_responses([ request_input(0), request_input(1), request_output(0), messages.ButtonRequest(code=B.ConfirmOutput), messages.ButtonRequest(code=B.SignTx), request_input(0), request_meta(FAKE_TXHASH_f8e2f2), request_input(0, FAKE_TXHASH_f8e2f2), request_input(1, FAKE_TXHASH_f8e2f2), request_output(0, FAKE_TXHASH_f8e2f2), request_output(1, FAKE_TXHASH_f8e2f2), request_output(2, FAKE_TXHASH_f8e2f2), request_input(1), request_meta(FAKE_TXHASH_51bc9c), request_input(0, FAKE_TXHASH_51bc9c), request_output(0, FAKE_TXHASH_51bc9c), request_input(0), request_input(1), request_finished(), ]) _, serialized_tx = btc.sign_tx(client, "Decred Testnet", [inp1, inp2], [out1], prev_txes=TX_API) assert ( serialized_tx.hex() == "01000000027bfc02bff0fb90765c37ae169c4db8641f34db92ba3c74e3f672b7eab4f2e2f80200000001ffffffffe872c504dc8fe96f9102df8a99701f4beb623033b5edcaf3ee810af1719cbc510000000001ffffffff0160fdd5170000000000001976a914819d291a2f7fbf770e784bfd78b5ce92c58e95ea88ac00000000000000000200c2eb0b0000000000000000ffffffff6b483045022100f74f652a073bdaf2197ede47b4df0d90609bbfd0dc8a94199d36ebb1429de09b022040366292a8812135ec7572a94eb6e969fa1fa97a52c03f08a337f20bc4fb71de0121030e669acac1f280d1ddf441cd2ba5e97417bf2689e4bbec86df4f831bf9f7ffd000c2eb0b0000000000000000ffffffff6b483045022100ca385c05a008239c038e107989bbc30eec1ecd5a66e4973265eb21df034c77a9022070c3dceb24b39cb6e9f8c973572b955b37a4754e9caa704cdd37113c46e2b2970121030e669acac1f280d1ddf441cd2ba5e97417bf2689e4bbec86df4f831bf9f7ffd0" )
def test_backup_slip39_basic(client: Client, click_info: bool): assert client.features.needs_backup is True mnemonics = [] def input_flow(): yield # Checklist client.debug.press_yes() if click_info: yield from click_info_button(client.debug) yield # Number of shares (5) client.debug.press_yes() yield # Checklist client.debug.press_yes() if click_info: yield from click_info_button(client.debug) yield # Threshold (3) client.debug.press_yes() yield # Checklist client.debug.press_yes() yield # Confirm show seeds client.debug.press_yes() # Mnemonic phrases for _ in range(5): # Phrase screen mnemonic = yield from read_and_confirm_mnemonic(client.debug) mnemonics.append(mnemonic) yield # Confirm continue to next client.debug.press_yes() yield # Confirm backup client.debug.press_yes() with client: client.set_input_flow(input_flow) client.set_expected_responses( [messages.ButtonRequest(code=B.ResetDevice)] * (8 if click_info else 6) # intro screens (and optional info) + [ messages.ButtonRequest(code=B.ResetDevice), messages.ButtonRequest(code=B.Success), ] * 5 # individual shares + [ messages.ButtonRequest(code=B.Success), messages.Success, messages.Features, ]) device.backup(client) client.init_device() assert client.features.initialized is True assert client.features.needs_backup is False assert client.features.unfinished_backup is False assert client.features.no_backup is False assert client.features.backup_type is messages.BackupType.Slip39_Basic expected_ms = shamir.combine_mnemonics(MNEMONIC_SLIP39_BASIC_20_3of6) actual_ms = shamir.combine_mnemonics(mnemonics[:3]) assert expected_ms == actual_ms
def test_get_entropy_t1(client: Client): _assert_protection(client) with client: client.set_expected_responses([ messages.ButtonRequest(code=B.ProtectCall), messages.Entropy, ]) misc.get_entropy(client, 10)
def reset(client: Client, strength=128, skip_backup=False): mnemonic = None def input_flow(): nonlocal mnemonic # 1. Confirm Reset # 2. Backup your seed # 3. Confirm warning yield from click_through(client.debug, screens=3, code=B.ResetDevice) # mnemonic phrases mnemonic = yield from read_and_confirm_mnemonic(client.debug) # confirm recovery seed check br = yield assert br.code == B.Success client.debug.press_yes() # confirm success br = yield assert br.code == B.Success client.debug.press_yes() os_urandom = mock.Mock(return_value=EXTERNAL_ENTROPY) with mock.patch("os.urandom", os_urandom), client: client.set_expected_responses([ messages.ButtonRequest(code=B.ResetDevice), messages.EntropyRequest(), messages.ButtonRequest(code=B.ResetDevice), messages.ButtonRequest(code=B.ResetDevice), messages.ButtonRequest(code=B.ResetDevice), messages.ButtonRequest(code=B.Success), messages.ButtonRequest(code=B.Success), messages.Success, messages.Features, ]) client.set_input_flow(input_flow) # No PIN, no passphrase, don't display random device.reset( client, display_random=False, strength=strength, passphrase_protection=False, pin_protection=False, label="test", language="en-US", backup_type=BackupType.Bip39, ) # Check if device is properly initialized assert client.features.initialized is True assert client.features.needs_backup is False assert client.features.pin_protection is False assert client.features.passphrase_protection is False return mnemonic
def test_apply_homescreen_toif(client: Client): img = b"TOIf\x90\x00\x90\x00~\x00\x00\x00\xed\xd2\xcb\r\x83@\x10D\xc1^.\xde#!\xac31\x99\x10\x8aC%\x14~\x16\x92Y9\x02WI3\x01<\xf5cI2d\x1es(\xe1[\xdbn\xba\xca\xe8s7\xa4\xd5\xd4\xb3\x13\xbdw\xf6:\xf3\xd1\xe7%\xc7]\xdd_\xb3\x9e\x9f\x9e\x9fN\xed\xaaE\xef\xdc\xcf$D\xa7\xa4X\r\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xf0OV" with client: _set_expected_responses(client) device.apply_settings(client, homescreen=img) client.set_expected_responses(EXPECTED_RESPONSES_NOPIN) device.apply_settings(client, homescreen=b"")
def test_passphrase_cached(client: Client): _assert_protection(client, pin=False) with client: client.set_expected_responses([messages.PassphraseRequest, messages.Address]) get_test_address(client) with client: client.set_expected_responses([messages.Address]) get_test_address(client)
def test_cancel_message_via_cancel(client: Client, message): def input_flow(): yield client.cancel() with client, pytest.raises(Cancelled): client.set_expected_responses([m.ButtonRequest(), m.Failure()]) client.set_input_flow(input_flow) client.call(message)
def test_purchase_ticket_decred(client: Client): # NOTE: fake input tx used inp1 = messages.TxInputType( address_n=parse_path("m/44h/1h/0h/0/0"), prev_hash=FAKE_TXHASH_4d8acd, prev_index=1, amount=200_000_000, decred_tree=0, script_type=messages.InputScriptType.SPENDADDRESS, ) out1 = messages.TxOutputType( address="TscqTv1he8MZrV321SfRghw7LFBCJDKB3oz", script_type=messages.OutputScriptType.PAYTOADDRESS, amount=199_900_000, ) out2 = messages.TxOutputType( address_n=parse_path("m/44h/1h/0h/0/0"), amount=200_000_000, script_type=messages.OutputScriptType.PAYTOADDRESS, ) out3 = messages.TxOutputType( address="TsR28UZRprhgQQhzWns2M6cAwchrNVvbYq2", amount=0, script_type=messages.OutputScriptType.PAYTOADDRESS, ) with client: client.set_expected_responses([ request_input(0), request_output(0), messages.ButtonRequest(code=B.ConfirmOutput), request_output(1), request_output(2), messages.ButtonRequest(code=B.SignTx), request_input(0), request_meta(FAKE_TXHASH_4d8acd), request_input(0, FAKE_TXHASH_4d8acd), request_output(0, FAKE_TXHASH_4d8acd), request_output(1, FAKE_TXHASH_4d8acd), request_input(0), request_finished(), ]) _, serialized_tx = btc.sign_tx( client, "Decred Testnet", [inp1], [out1, out2, out3], prev_txes=TX_API, decred_staking_ticket=True, ) assert ( serialized_tx.hex() == "01000000011064cbf0f0889b919ce083c82065612710b1a6adcdb3f15d7ffc5e6de2cd8a4d0100000000ffffffff03603bea0b0000000000001aba76a914819d291a2f7fbf770e784bfd78b5ce92c58e95ea88ac00000000000000000000206a1edc1a98d791735eb9a8715a2a219c23680edcedad00c2eb0b000000000058000000000000000000001abd76a914000000000000000000000000000000000000000088ac00000000000000000100c2eb0b0000000000000000ffffffff6b483045022100b3a11ff4befcc035623de7665aaa76dacc9252e53aabf2a5d61238151e696532022004cbcc537c1d539e04c823140bac4524bdba09f528f5c4b76f3f1022b7dc0ad40121030e669acac1f280d1ddf441cd2ba5e97417bf2689e4bbec86df4f831bf9f7ffd0" )
def test_send_two_with_change(client: Client): inp1 = messages.TxInputType( # tb1pswrqtykue8r89t9u4rprjs0gt4qzkdfuursfnvqaa3f2yql07zmq8s8a5u address_n=parse_path("m/86h/1h/0h/0/0"), amount=6_800, prev_hash=TXHASH_c96621, prev_index=0, script_type=messages.InputScriptType.SPENDTAPROOT, ) inp2 = messages.TxInputType( # tb1p8tvmvsvhsee73rhym86wt435qrqm92psfsyhy6a3n5gw455znnpqm8wald address_n=parse_path("m/86h/1h/0h/0/1"), amount=13_000, prev_hash=TXHASH_c96621, prev_index=1, script_type=messages.InputScriptType.SPENDTAPROOT, ) out1 = messages.TxOutputType( # 84'/1'/1'/0/0 address="tb1q7r9yvcdgcl6wmtta58yxf29a8kc96jkyxl7y88", amount=15_000, script_type=messages.OutputScriptType.PAYTOADDRESS, ) out2 = messages.TxOutputType( # tb1pn2d0yjeedavnkd8z8lhm566p0f2utm3lgvxrsdehnl94y34txmts5s7t4c address_n=parse_path("m/86h/1h/0h/1/0"), script_type=messages.OutputScriptType.PAYTOTAPROOT, amount=6_800 + 13_000 - 200 - 15_000, ) with client: client.set_expected_responses([ request_input(0), request_input(1), request_output(0), messages.ButtonRequest(code=B.ConfirmOutput), request_output(1), messages.ButtonRequest(code=B.SignTx), request_input(0), request_input(1), request_output(0), request_output(1), request_input(0), request_input(1), request_finished(), ]) _, serialized_tx = btc.sign_tx(client, "Testnet", [inp1, inp2], [out1, out2], prev_txes=TX_API) assert_tx_matches( serialized_tx, hash_link= "https://tbtc1.trezor.io/api/tx/1054eb649110534518239bca2abebebee76d50addac27d0d582cef2b9b9d80c0", tx_hex= "010000000001021988ca0c649b0e56428288a4daa5038503b2e29eeb4d5c50ddf76866a92166c90000000000ffffffff1988ca0c649b0e56428288a4daa5038503b2e29eeb4d5c50ddf76866a92166c90100000000ffffffff02983a000000000000160014f0ca4661a8c7f4edad7da1c864a8bd3db05d4ac4f8110000000000002251209a9af24b396f593b34e23fefba6b417a55c5ee3f430c3837379fcb5246ab36d70140aad93b4abfdc18826a60d79dc648c58810d56c24273f02dde4ac614367395feec25e809c0fdb58fb31f5631ef798a95d82864efc2b0a48b1be83196193ece05401402624067d8ef3705b908956fa824d36998a1522b3f01f38272c11ad5488fb63cb6d7c68d82e8e2d052805610bce34048335ed9c15037ef36b6e2accc0d3f5893500000000", )
def test_incorrect_pin_t2(client: Client): with client: # After first incorrect attempt, TT will not raise an error, but instead ask for another attempt client.use_pin_sequence([BAD_PIN, PIN4]) client.set_expected_responses([ messages.ButtonRequest(code=messages.ButtonRequestType.PinEntry), messages.ButtonRequest(code=messages.ButtonRequestType.PinEntry), messages.Address, ]) get_test_address(client)
def test_get_address(client: Client): _assert_protection(client) with client: client.use_pin_sequence([PIN4]) client.set_expected_responses([ _pin_request(client), messages.PassphraseRequest, messages.Address, ]) get_test_address(client)