예제 #1
0
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)
예제 #3
0
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)
예제 #5
0
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",
    )
예제 #6
0
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
예제 #11
0
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)
예제 #12
0
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"
    )
예제 #13
0
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)
예제 #14
0
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",
            )
        )
예제 #17
0
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)
예제 #19
0
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,
            )
예제 #20
0
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
예제 #22
0
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
예제 #24
0
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)
예제 #26
0
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)
예제 #27
0
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"
    )
예제 #28
0
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",
    )
예제 #29
0
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)
예제 #30
0
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)