def test_two_changes(self, client):
        # see 87be0736f202f7c2bff0781b42bad3e0cdcb54761939da69ea793a3735552c56

        # tx: e5040e1bc1ae7667ffb9e5248e90b2fb93cd9150234151ce90e14ab2f5933bcd
        # input 0: 0.31 BTC
        inp1 = messages.TxInputType(
            address_n=parse_path("44'/1'/0'/0/0"),
            amount=31000000,
            prev_hash=TXHASH_e5040e,
            prev_index=0,
        )

        out1 = messages.TxOutputType(
            address="msj42CCGruhRsFrGATiUuh25dtxYtnpbTx",
            amount=30090000,
            script_type=messages.OutputScriptType.PAYTOADDRESS,
        )

        out_change1 = messages.TxOutputType(
            address_n=parse_path("44'/1'/0'/1/0"),
            amount=900000,
            script_type=messages.OutputScriptType.PAYTOADDRESS,
        )

        out_change2 = messages.TxOutputType(
            address_n=parse_path("44'/1'/0'/1/1"),
            amount=10000,
            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(TXHASH_e5040e),
                    request_input(0, TXHASH_e5040e),
                    request_output(0, TXHASH_e5040e),
                    request_output(1, TXHASH_e5040e),
                    request_input(0),
                    request_output(0),
                    request_output(1),
                    request_output(2),
                    request_output(0),
                    request_output(1),
                    request_output(2),
                    request_finished(),
                ]
            )

            btc.sign_tx(
                client,
                "Testnet",
                [inp1],
                [out1, out_change1, out_change2],
                prev_txes=TX_CACHE_TESTNET,
            )
Example #2
0
    def test_pin_passphrase(self, client):
        mnemonic = MNEMONIC12.split(" ")
        ret = client.call_raw(
            proto.RecoveryDevice(
                passphrase_protection=True,
                pin_protection=True,
                label="label",
                enforce_wordlist=True,
            ))

        # Confirm Recovery
        assert isinstance(ret, proto.ButtonRequest)
        client.debug.press_yes()
        ret = client.call_raw(proto.ButtonAck())

        # Enter PIN for first time
        assert ret == proto.ButtonRequest(code=proto.ButtonRequestType.Other)
        client.debug.input("654")
        ret = client.call_raw(proto.ButtonAck())

        # Enter PIN for second time
        assert ret == proto.ButtonRequest(code=proto.ButtonRequestType.Other)
        client.debug.input("654")
        ret = client.call_raw(proto.ButtonAck())

        # Homescreen
        assert isinstance(ret, proto.ButtonRequest)
        client.debug.press_yes()
        ret = client.call_raw(proto.ButtonAck())

        # Enter word count
        assert ret == proto.ButtonRequest(
            code=proto.ButtonRequestType.MnemonicWordCount)
        client.debug.input(str(len(mnemonic)))
        ret = client.call_raw(proto.ButtonAck())

        # Homescreen
        assert isinstance(ret, proto.ButtonRequest)
        client.debug.press_yes()
        ret = client.call_raw(proto.ButtonAck())

        # Enter mnemonic words
        assert ret == proto.ButtonRequest(
            code=proto.ButtonRequestType.MnemonicInput)
        client.transport.write(proto.ButtonAck())
        for word in mnemonic:
            client.debug.input(word)
        ret = client.transport.read()

        # Confirm success
        assert isinstance(ret, proto.ButtonRequest)
        client.debug.press_yes()
        ret = client.call_raw(proto.ButtonAck())

        # Workflow succesfully ended
        assert ret == proto.Success(message="Device recovered")

        # Mnemonic is the same
        client.init_device()
        assert client.debug.read_mnemonic_secret() == MNEMONIC12.encode()

        assert client.features.pin_protection is True
        assert client.features.passphrase_protection is True
def test_send_multisig_1(client: Client):
    # input: 338e2d02e0eaf8848e38925904e51546cf22e58db5b1860c4a0e72b69c56afe5

    nodes = [
        btc.get_public_node(
            client, parse_path(f"m/49h/1h/{i}h"), coin_name="Testnet"
        ).node
        for i in range(1, 4)
    ]
    # address: 2MuqUo9axjz6FfHjSqNMu8kbF1tCjisMrbt
    multisig = messages.MultisigRedeemScriptType(
        nodes=nodes, address_n=[1, 0], signatures=[b"", b"", b""], m=2
    )

    inp1 = messages.TxInputType(
        address_n=parse_path("m/49h/1h/1h/1/0"),
        prev_hash=TXHASH_338e2d,
        prev_index=0,
        script_type=messages.InputScriptType.SPENDP2SHWITNESS,
        multisig=multisig,
        amount=100_000,
    )

    out1 = messages.TxOutputType(
        address="mu85iAHLpF16VyijB2wn5fcZrjT2bvrhnL",
        amount=100_000 - 10_000,
        script_type=messages.OutputScriptType.PAYTOADDRESS,
    )

    expected_responses = [
        request_input(0),
        request_output(0),
        messages.ButtonRequest(code=B.ConfirmOutput),
        messages.ButtonRequest(code=B.SignTx),
        request_input(0),
        request_meta(TXHASH_338e2d),
        request_input(0, TXHASH_338e2d),
        request_output(0, TXHASH_338e2d),
        request_output(1, TXHASH_338e2d),
        request_input(0),
        request_output(0),
        request_input(0),
        request_finished(),
    ]

    with client:
        client.set_expected_responses(expected_responses)
        signatures, _ = btc.sign_tx(
            client, "Testnet", [inp1], [out1], prev_txes=TX_API_TESTNET
        )

    # store signature
    inp1.multisig.signatures[0] = signatures[0]
    # sign with third key
    inp1.address_n[2] = H_(3)

    with client:
        client.set_expected_responses(expected_responses)
        _, serialized_tx = btc.sign_tx(
            client, "Testnet", [inp1], [out1], prev_txes=TX_API_TESTNET
        )

    assert_tx_matches(
        serialized_tx,
        hash_link="https://tbtc1.trezor.io/api/tx/0d5d04bffd49287d122f509bebd196b1ecba7cbc5f945c28bf8a26dea66e65de",
        tx_hex="01000000000101e5af569cb6720e4a0c86b1b58de522cf4615e5045992388e84f8eae0022d8e330000000023220020cf28684ff8a6dda1a7a9704dde113ddfcf236558da5ce35ad3f8477474dbdaf7ffffffff01905f0100000000001976a914953e62552a88c235c0691ec74b362a6803a7d93e88ac040047304402203aba48b0a98194a505420633eeca5acd8244061899e0a414f1b0d2de1d721b0f022001b32486e7c443e25cdfdfb14dc183ba31f5329d0078a25f7eb74f7209f347bb014830450221009cbdf84db2585abddf79165340cc0b54037f13bbe5318ec3619d0de680ebbf5d02206a2ef69e154700202ac72330e936c073f8a86cec9443273f4d8739db1019d55a0169522103d54ab3c8b81cb7f8f8088df4c62c105e8acaa2fb53b180f6bc6f922faecf3fdc21036aa47994f3f18f0976d6073ca79997003c3fa29c4f93907998fefc1151b4529b2102a092580f2828272517c402da9461425c5032860ab40180e041fbbb88ea2a520453ae00000000",
    )
 def test_ping(self, client):
     with client:
         client.set_expected_responses([proto.ButtonRequest(), proto.Success()])
         client.ping("msg", True)
 def test_get_entropy(self):
     with self.client:
         self.setup_mnemonic_pin_passphrase()
         self.client.set_expected_responses(
             [proto.ButtonRequest(), proto.Entropy()])
         self.client.get_entropy(10)
Example #6
0
    def test_reset_device(self, client):
        mnemonic = None
        strength = 128

        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
            btn_code = yield
            assert btn_code == B.ResetDevice
            mnemonic = read_and_confirm_mnemonic(client.debug, words=12)

            # confirm recovery seed check
            btn_code = yield
            assert btn_code == B.Success
            client.debug.press_yes()

            # confirm success
            btn_code = yield
            assert btn_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(
                [
                    proto.ButtonRequest(code=B.ResetDevice),
                    proto.EntropyRequest(),
                    proto.ButtonRequest(code=B.ResetDevice),
                    proto.ButtonRequest(code=B.ResetDevice),
                    proto.ButtonRequest(code=B.ResetDevice),
                    proto.ButtonRequest(code=B.Success),
                    proto.ButtonRequest(code=B.Success),
                    proto.Success(),
                    proto.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="english",
            )

        # generate mnemonic locally
        internal_entropy = client.debug.state().reset_entropy
        entropy = generate_entropy(strength, internal_entropy, EXTERNAL_ENTROPY)
        expected_mnemonic = Mnemonic("english").to_mnemonic(entropy)

        # Compare that device generated proper mnemonic for given entropies
        assert mnemonic == expected_mnemonic

        # Check if device is properly initialized
        resp = client.call_raw(proto.Initialize())
        assert resp.initialized is True
        assert resp.needs_backup is False
        assert resp.pin_protection is False
        assert resp.passphrase_protection is False
        assert resp.backup_type is proto.BackupType.Bip39

        # backup attempt fails because backup was done in reset
        with pytest.raises(TrezorFailure, match="ProcessError: Seed already backed up"):
            device.backup(client)
Example #7
0
 def btn(code):
     return proto.ButtonRequest(code=code)
Example #8
0
    def test_opreturn(self):
        self.setup_mnemonic_nopin_nopassphrase()

        # tx: d5f65ee80147b4bcc70b75e4bbf2d7382021b871bd8867ef8fa525ef50864882
        # input 0: 0.0039 BTC

        inp1 = proto.TxInputType(
            address_n=[0],  # 14LmW5k4ssUrtbAB4255zdqv3b4w1TuX9e
            # amount=390000,
            prev_hash=TXHASH_d5f65e,
            prev_index=0,
        )

        out1 = proto.TxOutputType(
            address="1MJ2tj2ThBE62zXbBYA5ZaN3fdve5CPAz1",
            amount=390000 - 10000,
            script_type=proto.OutputScriptType.PAYTOADDRESS,
        )

        out2 = proto.TxOutputType(
            op_return_data=b"test of the op_return data",
            amount=0,
            script_type=proto.OutputScriptType.PAYTOOPRETURN,
        )

        with self.client:
            self.client.set_expected_responses([
                proto.TxRequest(
                    request_type=proto.RequestType.TXINPUT,
                    details=proto.TxRequestDetailsType(request_index=0),
                ),
                proto.TxRequest(
                    request_type=proto.RequestType.TXMETA,
                    details=proto.TxRequestDetailsType(tx_hash=TXHASH_d5f65e),
                ),
                proto.TxRequest(
                    request_type=proto.RequestType.TXINPUT,
                    details=proto.TxRequestDetailsType(request_index=0,
                                                       tx_hash=TXHASH_d5f65e),
                ),
                proto.TxRequest(
                    request_type=proto.RequestType.TXINPUT,
                    details=proto.TxRequestDetailsType(request_index=1,
                                                       tx_hash=TXHASH_d5f65e),
                ),
                proto.TxRequest(
                    request_type=proto.RequestType.TXOUTPUT,
                    details=proto.TxRequestDetailsType(request_index=0,
                                                       tx_hash=TXHASH_d5f65e),
                ),
                proto.TxRequest(
                    request_type=proto.RequestType.TXOUTPUT,
                    details=proto.TxRequestDetailsType(request_index=0),
                ),
                proto.ButtonRequest(
                    code=proto.ButtonRequestType.ConfirmOutput),
                proto.TxRequest(
                    request_type=proto.RequestType.TXOUTPUT,
                    details=proto.TxRequestDetailsType(request_index=1),
                ),
                proto.ButtonRequest(
                    code=proto.ButtonRequestType.ConfirmOutput),
                proto.ButtonRequest(code=proto.ButtonRequestType.SignTx),
                proto.TxRequest(
                    request_type=proto.RequestType.TXINPUT,
                    details=proto.TxRequestDetailsType(request_index=0),
                ),
                proto.TxRequest(
                    request_type=proto.RequestType.TXOUTPUT,
                    details=proto.TxRequestDetailsType(request_index=0),
                ),
                proto.TxRequest(
                    request_type=proto.RequestType.TXOUTPUT,
                    details=proto.TxRequestDetailsType(request_index=1),
                ),
                proto.TxRequest(
                    request_type=proto.RequestType.TXOUTPUT,
                    details=proto.TxRequestDetailsType(request_index=0),
                ),
                proto.TxRequest(
                    request_type=proto.RequestType.TXOUTPUT,
                    details=proto.TxRequestDetailsType(request_index=1),
                ),
                proto.TxRequest(request_type=proto.RequestType.TXFINISHED),
            ])
            (signatures, serialized_tx) = btc.sign_tx(self.client, "Bitcoin",
                                                      [inp1], [out1, out2])

        assert (
            serialized_tx.hex() ==
            "010000000182488650ef25a58fef6788bd71b8212038d7f2bbe4750bc7bcb44701e85ef6d5000000006a4730440220187b7b9c340a32fc8445418ad11fb3827d2e8bac7d730e1c9ad800353e7ba62f02206c0c5820ba8882c82923a39aee8d36d6d32e13daed73f7a3d6199de5f8e7ddfd0121023230848585885f63803a0a8aecdd6538792d5c539215c91698e315bf0253b43dffffffff0260cc0500000000001976a914de9b2a8da088824e8fe51debea566617d851537888ac00000000000000001c6a1a74657374206f6620746865206f705f72657475726e206461746100000000"
        )
Example #9
0
    def test_send_both(self, client):
        inp1 = proto.TxInputType(
            address_n=parse_path("49'/1'/0'/1/0"),
            # 2N1LGaGg836mqSQqiuUBLfcyGBhyZbremDX
            amount=111145789,
            prev_hash=TXHASH_091446,
            prev_index=1,
            script_type=proto.InputScriptType.SPENDP2SHWITNESS,
        )
        inp2 = proto.TxInputType(
            address_n=parse_path("84'/1'/0'/1/0"),
            amount=7289000,
            prev_hash=TXHASH_65b811,
            prev_index=1,
            script_type=proto.InputScriptType.SPENDWITNESS,
        )
        out1 = proto.TxOutputType(
            address="tb1q54un3q39sf7e7tlfq99d6ezys7qgc62a6rxllc",
            amount=12300000,
            script_type=proto.OutputScriptType.PAYTOADDRESS,
        )
        out2 = proto.TxOutputType(
            # address_n=parse_path("44'/1'/0'/0/0"),
            # script_type=proto.OutputScriptType.PAYTOP2SHWITNESS,
            address="2N6UeBoqYEEnybg4cReFYDammpsyDw8R2Mc",
            script_type=proto.OutputScriptType.PAYTOADDRESS,
            amount=45600000,
        )
        out3 = proto.TxOutputType(
            address="mvbu1Gdy8SUjTenqerxUaZyYjmveZvt33q",
            amount=111145789 + 7289000 - 11000 - 12300000 - 45600000,
            script_type=proto.OutputScriptType.PAYTOADDRESS,
        )

        with client:
            client.set_expected_responses(
                [
                    request_input(0),
                    request_input(1),
                    request_output(0),
                    proto.ButtonRequest(code=B.ConfirmOutput),
                    request_output(1),
                    proto.ButtonRequest(code=B.ConfirmOutput),
                    request_output(2),
                    proto.ButtonRequest(code=B.ConfirmOutput),
                    proto.ButtonRequest(code=B.SignTx),
                    request_input(0),
                    request_input(1),
                    request_output(0),
                    request_output(1),
                    request_output(2),
                    request_input(0),
                    request_input(1),
                    request_finished(),
                ]
            )
            _, serialized_tx = btc.sign_tx(
                client, "Testnet", [inp1, inp2], [out1, out2, out3], prev_txes=TX_API
            )

        assert (
            serialized_tx.hex()
            == "010000000001028a44999c07bba32df1cacdc50987944e68e3205b4429438fdde35c76024614090100000017160014d16b8c0680c61fc6ed2e407455715055e41052f5ffffffff7b010c5faeb41cc5c253121b6bf69bf1a7c5867cd7f2d91569fea0ecd311b8650100000000ffffffff03e0aebb0000000000160014a579388225827d9f2fe9014add644487808c695d00cdb7020000000017a91491233e24a9bf8dbb19c1187ad876a9380c12e787870d859b03000000001976a914a579388225827d9f2fe9014add644487808c695d88ac02483045022100ead79ee134f25bb585b48aee6284a4bb14e07f03cc130253e83450d095515e5202201e161e9402c8b26b666f2b67e5b668a404ef7e57858ae9a6a68c3837e65fdc69012103e7bfe10708f715e8538c92d46ca50db6f657bbc455b7494e6a0303ccdb868b7902463043021f585c54a84dc7326fa60e22729accd41153c7dd4725bd4c8f751aa3a8cd8d6a0220631bfd83fc312cc6d5d129572a25178696d81eaf50c8c3f16c6121be4f4c029d012103505647c017ff2156eb6da20fae72173d3b681a1d0a629f95f49e884db300689f00000000"
        )
    def test_attack_change_input_address(self, client):
        inp1 = messages.TxInputType(
            address_n=parse_path("44'/1'/4'/0/0"),
            # moUJnmge8SRXuediK7bW6t4YfrPqbE6hD7
            prev_hash=TXHASH_d2dcda,
            amount=123400000,
            prev_index=1,
            script_type=messages.InputScriptType.SPENDADDRESS,
        )

        out1 = messages.TxOutputType(
            address="mwue7mokpBRAsJtHqEMcRPanYBmsSmYKvY",
            amount=100000,
            script_type=messages.OutputScriptType.PAYTOADDRESS,
        )

        out2 = messages.TxOutputType(
            address_n=parse_path("44'/1'/4'/1/0"),
            amount=123400000 - 5000 - 100000,
            script_type=messages.OutputScriptType.PAYTOADDRESS,
        )

        # Test if the transaction can be signed normally
        _, serialized_tx = btc.sign_tx(
            client, "Testnet", [inp1], [out1, out2], prev_txes=TX_CACHE_TESTNET
        )

        assert (
            serialized_tx.hex()
            == "0100000001243e15b53cc553d93ec4e27e16984adc3d885ef107c613a7577fea47f5dadcd2010000006b483045022100eedaadde3a771967beee39f1daa9e9450f72fccdec63488a96d71eeae4224b4002203a22be3c1677d3451c93a49550b69e8f8fc06328823c7e0f633dde13d67ef96b01210364430c9122948e525e2f1c6d88f00f47679274f0810fd8c63754954f310995c1ffffffff02a0860100000000001976a914b3cc67f3349974d0f1b50e9bb5dfdf226f888fa088ac18555907000000001976a914f80fb232a1e54b1fa732bc120cae72eabd7fcf6888ac00000000"
        )

        attack_count = 2

        def attack_processor(msg):
            nonlocal attack_count
            if msg.tx.inputs and msg.tx.inputs[0] == inp1:
                if attack_count > 0:
                    attack_count -= 1
                else:
                    msg.tx.inputs[0].address_n[2] = H_(12)

            return msg

        client.set_filter(messages.TxAck, attack_processor)
        # Now run the attack, must trigger the exception
        with client:
            client.set_expected_responses(
                [
                    request_input(0),
                    request_output(0),
                    messages.ButtonRequest(code=B.ConfirmOutput),
                    request_output(1),
                    messages.ButtonRequest(code=B.SignTx),
                    request_input(0),
                    request_meta(TXHASH_d2dcda),
                    request_input(0, TXHASH_d2dcda),
                    request_output(0, TXHASH_d2dcda),
                    request_output(1, TXHASH_d2dcda),
                    request_input(0),
                    messages.Failure(code=messages.FailureType.ProcessError),
                ]
            )
            # Now run the attack, must trigger the exception
            with pytest.raises(TrezorFailure) as exc:
                btc.sign_tx(
                    client,
                    "Testnet",
                    [inp1],
                    [out1, out2],
                    prev_txes=TX_CACHE_TESTNET,
                )

            assert exc.value.code == messages.FailureType.ProcessError
            if client.features.model == "1":
                assert exc.value.message.endswith("Failed to compile input")
            else:
                assert exc.value.message.endswith(
                    "Transaction has changed during signing"
                )
Example #11
0
def pin_request(client):
    return (messages.PinMatrixRequest()
            if client.features.model == "1" else messages.ButtonRequest())
    def test_lots_of_change(self, client):
        # Tests if device implements prompting for multiple change addresses correctly

        # tx: c63e24ed820c5851b60c54613fbc4bcb37df6cd49b4c96143e99580a472f79fb
        # index 1: 0.0010 BTC
        # tx: 39a29e954977662ab3879c66fb251ef753e0912223a83d1dcb009111d28265e5
        # index 1: 0.0254 BTC

        inp1 = messages.TxInputType(
            address_n=parse_path("44h/0h/1h/0/0"),
            amount=100000,
            prev_hash=TXHASH_c63e24,
            prev_index=1,
        )

        inp2 = messages.TxInputType(
            address_n=parse_path("44h/0h/1h/0/1"),
            amount=2540000,
            prev_hash=TXHASH_39a29e,
            prev_index=1,
        )

        outputs = [
            messages.TxOutputType(
                address="1NwN6UduuVkJi6sw3gSiKZaCY5rHgVXC2h",
                amount=500000,
                script_type=messages.OutputScriptType.PAYTOADDRESS,
            )
        ]

        cnt = 20
        for i in range(cnt):
            out = messages.TxOutputType(
                address_n=parse_path(f"44h/0h/1h/1/{i}"),
                amount=(100000 + 2540000 - 500000 - 39000) // cnt,
                script_type=messages.OutputScriptType.PAYTOADDRESS,
            )
            outputs.append(out)

        request_change_outputs = [request_output(i + 1) for i in range(cnt)]

        with client:
            client.set_expected_responses(
                [
                    request_input(0),
                    request_input(1),
                    request_output(0),
                    messages.ButtonRequest(code=B.ConfirmOutput),
                ]
                + request_change_outputs
                + [
                    messages.ButtonRequest(code=B.SignTx),
                    messages.ButtonRequest(code=B.SignTx),
                    request_input(0),
                    request_meta(TXHASH_c63e24),
                    request_input(0, TXHASH_c63e24),
                    request_input(1, TXHASH_c63e24),
                    request_output(0, TXHASH_c63e24),
                    request_output(1, TXHASH_c63e24),
                    request_input(1),
                    request_meta(TXHASH_39a29e),
                    request_input(0, TXHASH_39a29e),
                    request_output(0, TXHASH_39a29e),
                    request_output(1, TXHASH_39a29e),
                    request_input(0),
                    request_input(1),
                    request_output(0),
                ]
                + request_change_outputs
                + [request_input(0), request_input(1), request_output(0)]
                + request_change_outputs
                + [request_output(0)]
                + request_change_outputs
                + [request_finished()]
            )

            _, serialized_tx = btc.sign_tx(
                client, "Bitcoin", [inp1, inp2], outputs, prev_txes=TX_CACHE_MAINNET
            )

        assert (
            tx_hash(serialized_tx).hex()
            == "fae68e4a3a4b0540eb200e2218a6d8465eac469788ccb236e0d5822d105ddde9"
        )
    def test_two_two(self, client):
        # tx: c6be22d34946593bcad1d2b013e12f74159e69574ffea21581dad115572e031c
        # input 1: 0.0010 BTC
        # tx: 58497a7757224d1ff1941488d23087071103e5bf855f4c1c44e5c8d9d82ca46e
        # input 1: 0.0011 BTC

        inp1 = messages.TxInputType(
            address_n=parse_path("44h/0h/0h/0/0"),
            amount=100000,
            prev_hash=TXHASH_c6be22,
            prev_index=1,
        )

        inp2 = messages.TxInputType(
            address_n=parse_path("44h/0h/0h/0/1"),
            amount=110000,
            prev_hash=TXHASH_58497a,
            prev_index=1,
        )

        out1 = messages.TxOutputType(
            address="15Jvu3nZNP7u2ipw2533Q9VVgEu2Lu9F2B",
            amount=210000 - 100000 - 10000,
            script_type=messages.OutputScriptType.PAYTOADDRESS,
        )

        out2 = messages.TxOutputType(
            address_n=parse_path("44h/0h/0h/1/0"),
            amount=100000,
            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),
                    request_output(1),
                    messages.ButtonRequest(code=B.SignTx),
                    request_input(0),
                    request_meta(TXHASH_c6be22),
                    request_input(0, TXHASH_c6be22),
                    request_output(0, TXHASH_c6be22),
                    request_output(1, TXHASH_c6be22),
                    request_input(1),
                    request_meta(TXHASH_58497a),
                    request_input(0, TXHASH_58497a),
                    request_output(0, TXHASH_58497a),
                    request_output(1, TXHASH_58497a),
                    request_input(0),
                    request_input(1),
                    request_output(0),
                    request_output(1),
                    request_input(0),
                    request_input(1),
                    request_output(0),
                    request_output(1),
                    request_output(0),
                    request_output(1),
                    request_finished(),
                ]
            )
            _, serialized_tx = btc.sign_tx(
                client,
                "Bitcoin",
                [inp1, inp2],
                [out1, out2],
                prev_txes=TX_CACHE_MAINNET,
            )

        # Accepted by network: tx c63e24ed820c5851b60c54613fbc4bcb37df6cd49b4c96143e99580a472f79fb
        # The transaction was produced before Trezor implemented BIP-66, so the signature
        # is now different and txhash doesn't match what is on the blockchain.
        assert (
            tx_hash(serialized_tx).hex()
            == "6f9775545830731a316a4c2a39515b1890e9c8ab0f9e21e7c6a6ca2c1499116d"
        )
    def test_one_three_fee(self, client):
        # tx: d5f65ee80147b4bcc70b75e4bbf2d7382021b871bd8867ef8fa525ef50864882
        # input 0: 0.0039 BTC

        inp1 = messages.TxInputType(
            address_n=parse_path("44'/0'/0'/0/0"),
            amount=390000,
            prev_hash=TXHASH_d5f65e,
            prev_index=0,
        )

        out1 = messages.TxOutputType(
            address="1MJ2tj2ThBE62zXbBYA5ZaN3fdve5CPAz1",
            amount=390000 - 80000 - 12000 - 10000,
            script_type=messages.OutputScriptType.PAYTOADDRESS,
        )

        out2 = messages.TxOutputType(
            address="13uaUYn6XAooo88QvAqAVsiVvr2mAXutqP",
            amount=12000,
            script_type=messages.OutputScriptType.PAYTOADDRESS,
        )

        out3 = messages.TxOutputType(
            address_n=parse_path("44'/0'/0'/1/0"),
            amount=80000,
            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),
                    messages.ButtonRequest(code=B.ConfirmOutput),
                    request_output(2),
                    messages.ButtonRequest(code=B.SignTx),
                    request_input(0),
                    request_meta(TXHASH_d5f65e),
                    request_input(0, TXHASH_d5f65e),
                    request_input(1, TXHASH_d5f65e),
                    request_output(0, TXHASH_d5f65e),
                    request_input(0),
                    request_output(0),
                    request_output(1),
                    request_output(2),
                    request_output(0),
                    request_output(1),
                    request_output(2),
                    request_finished(),
                ]
            )
            _, serialized_tx = btc.sign_tx(
                client,
                "Bitcoin",
                [inp1],
                [out1, out2, out3],
                prev_txes=TX_CACHE_MAINNET,
            )

        assert (
            tx_hash(serialized_tx).hex()
            == "fedbba83b115725a713c2b1a13db09fd33de582132d520a3f6ff72503ca5da61"
        )
    def test_send_decred_change(self, client):
        inp1 = proto.TxInputType(
            # TscqTv1he8MZrV321SfRghw7LFBCJDKB3oz
            address_n=parse_path("m/44'/1'/0'/0/0"),
            prev_hash=TXHASH_5e6e35,
            prev_index=0,
            script_type=proto.InputScriptType.SPENDADDRESS,
            decred_tree=0,
        )

        inp2 = proto.TxInputType(
            # TscqTv1he8MZrV321SfRghw7LFBCJDKB3oz
            address_n=parse_path("m/44'/1'/0'/0/0"),
            prev_hash=TXHASH_ccf95b,
            prev_index=1,
            script_type=proto.InputScriptType.SPENDADDRESS,
            decred_tree=0,
        )

        inp3 = proto.TxInputType(
            # Tskt39YEvzoJ5KBDH4f1auNzG3jViVjZ2RV
            address_n=parse_path("m/44'/1'/0'/0/1"),
            prev_hash=TXHASH_f395ef,
            prev_index=0,
            script_type=proto.InputScriptType.SPENDADDRESS,
            decred_tree=0,
        )

        out1 = proto.TxOutputType(
            address="TsWjioPrP8E1TuTMmTrVMM2BA4iPrjQXBpR",
            amount=489975000,
            script_type=proto.OutputScriptType.PAYTOADDRESS,
            decred_script_version=0,
        )

        out2 = proto.TxOutputType(
            # TsaSFRwfN9muW5F6ZX36iSksc9hruiC5F97
            address_n=parse_path("m/44'/1'/0'/1/0"),
            amount=100000000,
            script_type=proto.OutputScriptType.PAYTOADDRESS,
            decred_script_version=0,
        )

        with client:
            client.set_expected_responses(
                [
                    request_input(0),
                    request_meta(TXHASH_5e6e35),
                    request_input(0, TXHASH_5e6e35),
                    request_output(0, TXHASH_5e6e35),
                    request_input(1),
                    request_meta(TXHASH_ccf95b),
                    request_input(0, TXHASH_ccf95b),
                    request_output(0, TXHASH_ccf95b),
                    request_output(1, TXHASH_ccf95b),
                    request_input(2),
                    request_meta(TXHASH_f395ef),
                    request_input(0, TXHASH_f395ef),
                    request_output(0, TXHASH_f395ef),
                    request_output(1, TXHASH_f395ef),
                    request_output(0),
                    proto.ButtonRequest(code=B.ConfirmOutput),
                    request_output(1),
                    proto.ButtonRequest(code=B.SignTx),
                    request_input(0),
                    request_input(1),
                    request_input(2),
                    request_finished(),
                ]
            )
            _, serialized_tx = btc.sign_tx(
                client,
                "Decred Testnet",
                [inp1, inp2, inp3],
                [out1, out2],
                prev_txes=TX_API,
            )

        assert (
            serialized_tx.hex()
            == "010000000370b95980a47b9bcb4ec2c2b450888a53179b1a5fdb23f5023cc533a300356e5e0000000000ffffffff74bc93bcfce18aff2e522d6822817522e2815a00175b2eae59ef20d20f5bf9cc0100000000ffffffff13317ab453832deabd684d2302eed42580c28ba3e715db66a731a8723eef95f30000000000ffffffff02d86c341d0000000000001976a9143eb656115197956125365348c542e37b6d3d259988ac00e1f5050000000000001976a9143ee6f9d662e7be18373d80e5eb44627014c2bf6688ac000000000000000003000000000000000000000000ffffffff6a47304402200e50a6d43c462045917792e7d03b4354900c3baccb7abef66f556a32b12f2ca6022031ae94fdf2a41dd6ed2e081faf0f8f1c64411a1b46eb26f7f35d94402b2bde110121030e669acac1f280d1ddf441cd2ba5e97417bf2689e4bbec86df4f831bf9f7ffd0000000000000000000000000ffffffff6a47304402204894c2f8e76c4645d2df600cdd01443aeb48807b72150c4bc10eebd126529532022054cd37462a3f0ddb85c75b4e874ab0c2aad7eebcff3e6c1ac20e1c16babe36720121030e669acac1f280d1ddf441cd2ba5e97417bf2689e4bbec86df4f831bf9f7ffd0000000000000000000000000ffffffff6b4830450221009f1ba584023da8aafd57374e83be68f1a097b906967ec9e50736f31bfc7989f102204a190fc2885e394572b5c2ced046657b1dd07abdb19144e21e78987968c7f17601210294e3e5e77e22eea0e4c0d30d89beb4db7f69b4bf1ae709e411d6a06618b8f852"
        )
Example #16
0
    def test_send_multisig_1(self, client):
        nodes = [
            btc.get_public_node(client, parse_path("49'/1'/%d'" % index))
            for index in range(1, 4)
        ]
        multisig = proto.MultisigRedeemScriptType(
            nodes=[deserialize(n.xpub) for n in nodes],
            address_n=[0, 0],
            signatures=[b"", b"", b""],
            m=2,
        )

        inp1 = proto.TxInputType(
            address_n=parse_path("49'/1'/1'/0/0"),
            prev_hash=TXHASH_9c3192,
            prev_index=1,
            script_type=proto.InputScriptType.SPENDP2SHWITNESS,
            multisig=multisig,
            amount=1610436,
        )

        out1 = proto.TxOutputType(
            address="tb1qch62pf820spe9mlq49ns5uexfnl6jzcezp7d328fw58lj0rhlhasge9hzy",
            amount=1605000,
            script_type=proto.OutputScriptType.PAYTOADDRESS,
        )

        with client:
            client.set_expected_responses(
                [
                    request_input(0),
                    request_output(0),
                    proto.ButtonRequest(code=B.ConfirmOutput),
                    proto.ButtonRequest(code=B.SignTx),
                    request_input(0),
                    request_output(0),
                    request_input(0),
                    request_finished(),
                ]
            )
            signatures, _ = btc.sign_tx(
                client, "Testnet", [inp1], [out1], prev_txes=TX_API
            )
            # store signature
            inp1.multisig.signatures[0] = signatures[0]
            # sign with third key
            inp1.address_n[2] = H_(3)
            client.set_expected_responses(
                [
                    request_input(0),
                    request_output(0),
                    proto.ButtonRequest(code=B.ConfirmOutput),
                    proto.ButtonRequest(code=B.SignTx),
                    request_input(0),
                    request_output(0),
                    request_input(0),
                    request_finished(),
                ]
            )
            _, serialized_tx = btc.sign_tx(
                client, "Testnet", [inp1], [out1], prev_txes=TX_API
            )

        assert (
            serialized_tx.hex()
            == "01000000000101be0210025c5be68a473f6a38bf53b53bc88d5c46567616026dc056e72b92319c01000000232200208d398cfb58a1d9cdb59ccbce81559c095e8c6f4a3e64966ca385078d9879f95effffffff01887d180000000000220020c5f4a0a4ea7c0392efe0a9670a73264cffa90b19107cd8a8e9750ff93c77fdfb0400483045022100dd6342c65197af27d7894d8b8b88b16b568ee3b5ebfdc55fdfb7caa9650e3b4c02200c7074a5bcb0068f63d9014c7cd2b0490aba75822d315d41aad444e9b86adf5201483045022100e7e6c2d21109512ba0609e93903e84bfb7731ac3962ee2c1cad54a7a30ff99a20220421497930226c39fc3834e8d6da3fc876516239518b0e82e2dc1e3c46271a17c01695221021630971f20fa349ba940a6ba3706884c41579cd760c89901374358db5dd545b92102f2ff4b353702d2bb03d4c494be19d77d0ab53d16161b53fbcaf1afeef4ad0cb52103e9b6b1c691a12ce448f1aedbbd588e064869c79fbd760eae3b8cd8a5f1a224db53ae00000000"
        )
Example #17
0
    def test_reset_device_pin(self, client):
        mnemonic = None
        strength = 128

        def input_flow():
            nonlocal mnemonic

            # Confirm Reset
            btn_code = yield
            assert btn_code == B.ResetDevice
            client.debug.press_yes()

            # Enter new PIN
            yield
            client.debug.input("654")

            # Confirm PIN
            yield
            client.debug.input("654")

            # Confirm entropy
            btn_code = yield
            assert btn_code == B.ResetDevice
            client.debug.press_yes()

            # Backup your seed
            btn_code = yield
            assert btn_code == B.ResetDevice
            client.debug.press_yes()

            # Confirm warning
            btn_code = yield
            assert btn_code == B.ResetDevice
            client.debug.press_yes()

            # mnemonic phrases
            btn_code = yield
            assert btn_code == B.ResetDevice
            mnemonic = read_and_confirm_mnemonic(client.debug, words=12)

            # confirm recovery seed check
            btn_code = yield
            assert btn_code == B.Success
            client.debug.press_yes()

            # confirm success
            btn_code = yield
            assert btn_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(
                [
                    proto.ButtonRequest(code=B.ResetDevice),
                    proto.ButtonRequest(code=B.Other),
                    proto.ButtonRequest(code=B.Other),
                    proto.ButtonRequest(code=B.ResetDevice),
                    proto.EntropyRequest(),
                    proto.ButtonRequest(code=B.ResetDevice),
                    proto.ButtonRequest(code=B.ResetDevice),
                    proto.ButtonRequest(code=B.ResetDevice),
                    proto.ButtonRequest(code=B.Success),
                    proto.ButtonRequest(code=B.Success),
                    proto.Success(),
                    proto.Features(),
                ]
            )
            client.set_input_flow(input_flow)

            # PIN, passphrase, display random
            device.reset(
                client,
                display_random=True,
                strength=strength,
                passphrase_protection=True,
                pin_protection=True,
                label="test",
                language="english",
            )

        # generate mnemonic locally
        internal_entropy = client.debug.state().reset_entropy
        entropy = generate_entropy(strength, internal_entropy, EXTERNAL_ENTROPY)
        expected_mnemonic = Mnemonic("english").to_mnemonic(entropy)

        # Compare that device generated proper mnemonic for given entropies
        assert mnemonic == expected_mnemonic

        # Check if device is properly initialized
        resp = client.call_raw(proto.Initialize())
        assert resp.initialized is True
        assert resp.needs_backup is False
        assert resp.pin_protection is True
        assert resp.passphrase_protection is True
Example #18
0
    def test_send_multisig_2(self, client):
        nodes = [
            btc.get_public_node(client, parse_path("84'/1'/%d'" % index))
            for index in range(1, 4)
        ]
        multisig = proto.MultisigRedeemScriptType(
            nodes=[deserialize(n.xpub) for n in nodes],
            address_n=[0, 1],
            signatures=[b"", b"", b""],
            m=2,
        )

        inp1 = proto.TxInputType(
            address_n=parse_path("84'/1'/2'/0/1"),
            prev_hash=TXHASH_f41cbe,
            prev_index=0,
            script_type=proto.InputScriptType.SPENDWITNESS,
            multisig=multisig,
            amount=1605000,
        )

        out1 = proto.TxOutputType(
            address="tb1qr6xa5v60zyt3ry9nmfew2fk5g9y3gerkjeu6xxdz7qga5kknz2ssld9z2z",
            amount=1604000,
            script_type=proto.OutputScriptType.PAYTOADDRESS,
        )

        with client:
            client.set_expected_responses(
                [
                    request_input(0),
                    request_output(0),
                    proto.ButtonRequest(code=B.ConfirmOutput),
                    proto.ButtonRequest(code=B.SignTx),
                    request_input(0),
                    request_output(0),
                    request_input(0),
                    request_finished(),
                ]
            )
            signatures, _ = btc.sign_tx(
                client, "Testnet", [inp1], [out1], prev_txes=TX_API
            )
            # store signature
            inp1.multisig.signatures[1] = signatures[0]
            # sign with first key
            inp1.address_n[2] = H_(1)
            client.set_expected_responses(
                [
                    request_input(0),
                    request_output(0),
                    proto.ButtonRequest(code=B.ConfirmOutput),
                    proto.ButtonRequest(code=B.SignTx),
                    request_input(0),
                    request_output(0),
                    request_input(0),
                    request_finished(),
                ]
            )
            _, serialized_tx = btc.sign_tx(
                client, "Testnet", [inp1], [out1], prev_txes=TX_API
            )

        assert (
            serialized_tx.hex()
            == "010000000001012812fe3916f228cda6c7b57d5464541265a63ad118f430a805eeec8bddbe1cf40000000000ffffffff01a0791800000000002200201e8dda334f11171190b3da72e526d441491464769679a319a2f011da5ad312a10400473044022001b7f4f21a8ddcd5e0faaaee3b95515bf8b84f2a7cbfdf66996c64123617a5cf02202fc6a776a7225420dbca759ad4ac83a61d15bf8d2883b6bf1aa31de7437f9b6e0147304402206c4125c1189a3b3e93a77cdf54c60c0538b80e5a03ec74e6ac776dfa77706ee4022035be14de76259b9d8a24863131a06a65b95df02f7d3ace90d52b37e8d94b167f0169522103bab8ecdd9ae2c51a0dc858f4c751b27533143bf6013ba1725ba8a4ecebe7de8c21027d5e55696c875308b03f2ca3d8637f51d3e35da9456a5187aa14b3de8a89534f2103b78eabaea8b3a4868be4f4bb96d6f66973f7081faa7f1cafba321444611c241e53ae00000000"
        )
Example #19
0
    def test_attack_change_input_address(self):
        # This unit test attempts to modify input address after the Trezor checked
        # that it matches the change output

        self.setup_mnemonic_allallall()
        self.client.set_tx_api(tx_api["Testnet"])

        inp1 = proto.TxInputType(
            address_n=parse_path("44'/1'/4'/0/0"),
            # moUJnmge8SRXuediK7bW6t4YfrPqbE6hD7
            prev_hash=TXHASH_d2dcda,
            prev_index=1,
            script_type=proto.InputScriptType.SPENDADDRESS,
        )

        out1 = proto.TxOutputType(
            address="mwue7mokpBRAsJtHqEMcRPanYBmsSmYKvY",
            amount=100000,
            script_type=proto.OutputScriptType.PAYTOADDRESS,
        )

        out2 = proto.TxOutputType(
            address_n=parse_path("44'/1'/12345'/1/0"),
            amount=123400000 - 5000 - 100000,
            script_type=proto.OutputScriptType.PAYTOADDRESS,
        )

        global run_attack
        run_attack = True

        def attack_processor(req, msg):
            global run_attack

            if req.details.tx_hash is not None:
                return msg

            if req.request_type != proto.RequestType.TXINPUT:
                return msg

            if req.details.request_index != 0:
                return msg

            if not run_attack:
                return msg

            msg.inputs[0].address_n[2] = H_(12345)
            run_attack = False
            return msg

        # Test if the transaction can be signed normally
        (_, serialized_tx) = btc.sign_tx(self.client, "Testnet", [inp1], [out1, out2])

        assert (
            serialized_tx.hex()
            == "0100000001243e15b53cc553d93ec4e27e16984adc3d885ef107c613a7577fea47f5dadcd2010000006a47304402207d517dcb6b823bba4d252da096795a7f914d0c477aee26e554ba61653c45608a02202cba1e805c586c830472f399510be5d42c2fcfd67b8a6b0690cbe8a3e6e475e801210364430c9122948e525e2f1c6d88f00f47679274f0810fd8c63754954f310995c1ffffffff02a0860100000000001976a914b3cc67f3349974d0f1b50e9bb5dfdf226f888fa088ac18555907000000001976a91485a3f5b0d23cdd61f5f8e1eb8c9ca0890dd15a9788ac00000000"
        )

        # Now run the attack, must trigger the exception
        with self.client:
            self.client.set_expected_responses(
                [
                    proto.TxRequest(
                        request_type=proto.RequestType.TXINPUT,
                        details=proto.TxRequestDetailsType(request_index=0),
                    ),
                    proto.TxRequest(
                        request_type=proto.RequestType.TXMETA,
                        details=proto.TxRequestDetailsType(tx_hash=TXHASH_d2dcda),
                    ),
                    proto.TxRequest(
                        request_type=proto.RequestType.TXINPUT,
                        details=proto.TxRequestDetailsType(
                            request_index=0, tx_hash=TXHASH_d2dcda
                        ),
                    ),
                    proto.TxRequest(
                        request_type=proto.RequestType.TXOUTPUT,
                        details=proto.TxRequestDetailsType(
                            request_index=0, tx_hash=TXHASH_d2dcda
                        ),
                    ),
                    proto.TxRequest(
                        request_type=proto.RequestType.TXOUTPUT,
                        details=proto.TxRequestDetailsType(
                            request_index=1, tx_hash=TXHASH_d2dcda
                        ),
                    ),
                    proto.TxRequest(
                        request_type=proto.RequestType.TXOUTPUT,
                        details=proto.TxRequestDetailsType(request_index=0),
                    ),
                    proto.ButtonRequest(code=proto.ButtonRequestType.ConfirmOutput),
                    proto.TxRequest(
                        request_type=proto.RequestType.TXOUTPUT,
                        details=proto.TxRequestDetailsType(request_index=1),
                    ),
                    proto.ButtonRequest(code=proto.ButtonRequestType.SignTx),
                    proto.TxRequest(
                        request_type=proto.RequestType.TXINPUT,
                        details=proto.TxRequestDetailsType(request_index=0),
                    ),
                    proto.Failure(code=proto.FailureType.ProcessError),
                ]
            )
            # Now run the attack, must trigger the exception
            with pytest.raises(CallException) as exc:
                btc.sign_tx(
                    self.client,
                    "Testnet",
                    [inp1],
                    [out1, out2],
                    debug_processor=attack_processor,
                )

            assert exc.value.args[0] == proto.FailureType.ProcessError
            if TREZOR_VERSION == 1:
                assert exc.value.args[1].endswith("Failed to compile input")
            else:
                assert exc.value.args[1].endswith(
                    "Transaction has changed during signing"
                )
Example #20
0
    def test_send_multisig_3_change(self, client):
        nodes = [
            btc.get_public_node(client, parse_path("84'/1'/%d'" % index))
            for index in range(1, 4)
        ]
        multisig = proto.MultisigRedeemScriptType(
            nodes=[deserialize(n.xpub) for n in nodes],
            address_n=[1, 0],
            signatures=[b"", b"", b""],
            m=2,
        )
        multisig2 = proto.MultisigRedeemScriptType(
            nodes=[deserialize(n.xpub) for n in nodes],
            address_n=[1, 1],
            signatures=[b"", b"", b""],
            m=2,
        )

        inp1 = proto.TxInputType(
            address_n=parse_path("84'/1'/1'/1/0"),
            prev_hash=TXHASH_c93480,
            prev_index=0,
            script_type=proto.InputScriptType.SPENDWITNESS,
            multisig=multisig,
            amount=1604000,
        )

        out1 = proto.TxOutputType(
            address_n=parse_path("84'/1'/1'/1/1"),
            amount=1603000,
            multisig=multisig2,
            script_type=proto.OutputScriptType.PAYTOP2SHWITNESS,
        )

        with client:
            client.set_expected_responses(
                [
                    request_input(0),
                    request_output(0),
                    proto.ButtonRequest(code=B.SignTx),
                    request_input(0),
                    request_output(0),
                    request_input(0),
                    request_finished(),
                ]
            )
            signatures, _ = btc.sign_tx(
                client, "Testnet", [inp1], [out1], prev_txes=TX_API
            )
            # store signature
            inp1.multisig.signatures[0] = signatures[0]
            # sign with third key
            inp1.address_n[2] = H_(3)
            out1.address_n[2] = H_(3)
            client.set_expected_responses(
                [
                    request_input(0),
                    request_output(0),
                    proto.ButtonRequest(code=B.SignTx),
                    request_input(0),
                    request_output(0),
                    request_input(0),
                    request_finished(),
                ]
            )
            _, serialized_tx = btc.sign_tx(
                client, "Testnet", [inp1], [out1], prev_txes=TX_API
            )

        assert (
            serialized_tx.hex()
            == "01000000000101fc7901dd033f8c02da14f3ac916b6498036b80b4a0b4dc124e02c2bb408034c90000000000ffffffff01b87518000000000017a914536250d41937e5b641082447580ff6a8e46c122a870400473044022003c26107a5a47f1f900ef8aa758977530cd13ea37a33971abae8d75cac2f9f34022039e2b8c2c1d0c24ff4fc026652e1f27ad8e3ed6c9bf485f61d9aa691cb57830801483045022100963b0dc0ab46e963a66ab6e69e5e41bac6c4fedc127cac12c560b029d54fe87402205b3bcdcf313dccd78e5dce0540e7d3c8cc1bf83f13c1f9f01811eb791fd35c8101695221039dba3a72f5dc3cad17aa924b5a03c34561465f997d0cb15993f2ca2c0be771c42103cd39f3f08bbd508dce4d307d57d0c70c258c285878bfda579fa260acc738c25d2102cd631ba95beca1d64766f5540885092d0bb384a3c13b6c3a5334d0ebacf51b9553ae00000000"
        )
 def test_wipe_device(self, client):
     with client:
         client.set_expected_responses(
             [proto.ButtonRequest(), proto.Success(), proto.Features()]
         )
         device.wipe(client)
Example #22
0
    def test_send_multisig_4_change(self, client):
        nodes = [
            btc.get_public_node(client, parse_path("49'/1'/%d'" % index))
            for index in range(1, 4)
        ]
        multisig = proto.MultisigRedeemScriptType(
            nodes=[deserialize(n.xpub) for n in nodes],
            address_n=[1, 1],
            signatures=[b"", b"", b""],
            m=2,
        )
        multisig2 = proto.MultisigRedeemScriptType(
            nodes=[deserialize(n.xpub) for n in nodes],
            address_n=[1, 2],
            signatures=[b"", b"", b""],
            m=2,
        )

        inp1 = proto.TxInputType(
            address_n=parse_path("49'/1'/1'/1/1"),
            prev_hash=TXHASH_31bc1c,
            prev_index=0,
            script_type=proto.InputScriptType.SPENDP2SHWITNESS,
            multisig=multisig,
            amount=1603000,
        )

        out1 = proto.TxOutputType(
            address_n=parse_path("49'/1'/1'/1/2"),
            amount=1602000,
            multisig=multisig2,
            script_type=proto.OutputScriptType.PAYTOWITNESS,
        )

        with client:
            client.set_expected_responses(
                [
                    request_input(0),
                    request_output(0),
                    proto.ButtonRequest(code=B.SignTx),
                    request_input(0),
                    request_output(0),
                    request_input(0),
                    request_finished(),
                ]
            )
            signatures, _ = btc.sign_tx(
                client, "Testnet", [inp1], [out1], prev_txes=TX_API
            )
            # store signature
            inp1.multisig.signatures[0] = signatures[0]
            # sign with third key
            inp1.address_n[2] = H_(3)
            out1.address_n[2] = H_(3)
            client.set_expected_responses(
                [
                    request_input(0),
                    request_output(0),
                    proto.ButtonRequest(code=B.SignTx),
                    request_input(0),
                    request_output(0),
                    request_input(0),
                    request_finished(),
                ]
            )
            _, serialized_tx = btc.sign_tx(
                client, "Testnet", [inp1], [out1], prev_txes=TX_API
            )

        assert (
            serialized_tx.hex()
            == "01000000000101e5918f661488bb7f0a7d04fc1dad61b5d0bad5167a05b3a637e36ace881cbc310000000023220020fa6c73de618ec134eeec0c16f6dd04d46d4347e9a4fd0a95fd7938403a4949f9ffffffff01d071180000000000220020bcea2324dacbcde5a9db90cc26b8df9cbc72010e05cb68cf034df6f0e05239a2040047304402206bbddb45f12e31e77610fd85b50a83bad4426433b1c4860b1c5ddc0a69f803720220087b0607daab14830f4b4941f16b953b38e606ad70029bac24af7267f93c4242014730440220551a0cb6b0d5b3fa0cfd0b07bb5d751494b827b1c6a08702186696cfbc18278302204f37c382876c4117cca656654599b508f2d55fc3b083dc938e3cd8491b29719601695221036a5ec3abd10501409092246fe59c6d7a15fff1a933479483c3ba98b866c5b9742103559be875179d44e438db2c74de26e0bc9842cbdefd16018eae8a2ed989e474722103067b56aad037cd8b5f569b21f9025b76470a72dc69457813d2b76e98dc0cd01a53ae00000000"
        )
 def test_get_entropy(self, client):
     with client:
         client.set_expected_responses([proto.ButtonRequest(), proto.Entropy()])
         misc.get_entropy(client, 10)
Example #24
0
    def test_multisig_mismatch_inputs_single(self, client):
        # m/84'/1'/0' for "alcohol woman abuse ..." seed.
        node_int = deserialize(
            "Vpub5kFDCYhiYuAzjk7TBQPNFffbexHF7iAd8AVVgHQKUany7e6NQvthgk86d7DfH57DY2dwBK4PyVTDDaS1r2gjkdyJyUYGoV9qNujGSrW9Dpe"
        )

        # m/84'/1'/0' for "all all ... all" seed.
        node_ext = deserialize(
            "Vpub5jR76XyyhBaQXPSRf3PBeY3gF914d9sf7DWFVhMESEQMCdNv35XiVvp8gZsFXAv222VPHLNnAEXxMPG8DPiSuhAXfEydBf55LTLBGHCDzH2"
        )

        # tb1qpzmgzpcumztvmpu3q27wwdggqav26j9dgks92pvnne2lz9ferxgssmhzlq
        multisig_in = proto.MultisigRedeemScriptType(
            nodes=[node_int, node_ext], address_n=[0, 0], signatures=[b"", b""], m=1
        )

        multisig_out = proto.MultisigRedeemScriptType(
            nodes=[node_int, node_ext], address_n=[1, 0], signatures=[b"", b""], m=1
        )

        inp1 = proto.TxInputType(
            address_n=parse_path("84'/1'/0'/0/0"),
            amount=12300000,
            prev_hash=TXHASH_091446,
            prev_index=0,
            script_type=proto.InputScriptType.SPENDWITNESS,
        )

        inp2 = proto.TxInputType(
            address_n=parse_path("84'/1'/0'/0/0"),
            prev_hash=TXHASH_a345b8,
            prev_index=0,
            script_type=proto.InputScriptType.SPENDWITNESS,
            multisig=multisig_in,
            amount=100,
        )

        out1 = proto.TxOutputType(
            address="2N4Q5FhU2497BryFfUgbqkAJE87aKHUhXMp",
            amount=5000000,
            script_type=proto.OutputScriptType.PAYTOADDRESS,
        )

        out2 = proto.TxOutputType(
            address_n=parse_path("84'/1'/0'/1/0"),
            script_type=proto.OutputScriptType.PAYTOWITNESS,
            multisig=multisig_out,
            amount=12300000 + 100 - 5000000 - 10000,
        )

        with client:
            client.set_expected_responses(
                [
                    request_input(0),
                    request_input(1),
                    request_output(0),
                    proto.ButtonRequest(code=B.ConfirmOutput),
                    request_output(1),
                    # Ensure that the multisig output is not identified as a change output.
                    proto.ButtonRequest(code=B.ConfirmOutput),
                    proto.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 (
            serialized_tx.hex()
            == "010000000001028a44999c07bba32df1cacdc50987944e68e3205b4429438fdde35c76024614090000000000ffffffff48e37c58a68ab4899400dc0950a661817ea7bac3e4556044c685b35957b845a30000000000ffffffff02404b4c000000000017a9147a55d61848e77ca266e79a39bfc85c580a6426c987f43c6f0000000000220020733ecfbbe7e47a74dde6c7645b60cdf627e90a585cde7733bc7fdaf9fe30b37402473044022037dc98b16be542a6e3e1ab32007a74192c43f2498170cc5e1dffb6847e3663e402206715102d0eb59e6461a97c78eb40a8679a04a8921fdafef25f0d3d16cc65de39012103adc58245cf28406af0ef5cc24b8afba7f1be6c72f279b642d85c48798685f8620300473044022070a24bcb00041cbed465f1f546bc59e1e353a6e182393932d5ba96e20bc32ef702202ddc76a97c01465692d5b0a0a61d653f64b9ea833af1810022110fd4d505ff950147512103505f0d82bbdd251511591b34f36ad5eea37d3220c2b81a1189084431ddb3aa3d2103adc58245cf28406af0ef5cc24b8afba7f1be6c72f279b642d85c48798685f86252ae00000000"
        )
Example #25
0
    def test_reset_device(self, client):
        words = []
        strength = 128

        def input_flow():
            # Confirm Reset
            btn_code = yield
            assert btn_code == B.ResetDevice
            client.debug.press_yes()

            # Backup your seed
            btn_code = yield
            assert btn_code == B.ResetDevice
            client.debug.press_yes()

            # Confirm warning
            btn_code = yield
            assert btn_code == B.ResetDevice
            client.debug.press_yes()

            # mnemonic phrases
            btn_code = yield
            assert btn_code == B.ResetDevice
            # 12 words, 3 pages
            for i in range(3):
                words.extend(client.debug.read_reset_word().split())
                if i < 2:
                    client.debug.swipe_down()
                else:
                    # last page is confirmation
                    client.debug.press_yes()

            # check backup words
            for _ in range(3):
                index = client.debug.read_reset_word_pos()
                client.debug.input(words[index])

            # confirm recovery seed check
            btn_code = yield
            assert btn_code == B.Success
            client.debug.press_yes()

            # confirm success
            btn_code = yield
            assert btn_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(
                [
                    proto.ButtonRequest(code=B.ResetDevice),
                    proto.EntropyRequest(),
                    proto.ButtonRequest(code=B.ResetDevice),
                    proto.ButtonRequest(code=B.ResetDevice),
                    proto.ButtonRequest(code=B.ResetDevice),
                    proto.ButtonRequest(code=B.Success),
                    proto.ButtonRequest(code=B.Success),
                    proto.Success(),
                    proto.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="english",
            )

        # generate mnemonic locally
        internal_entropy = client.debug.state().reset_entropy
        entropy = generate_entropy(strength, internal_entropy, EXTERNAL_ENTROPY)
        expected_mnemonic = Mnemonic("english").to_mnemonic(entropy)

        # Compare that device generated proper mnemonic for given entropies
        assert " ".join(words) == expected_mnemonic

        # Check if device is properly initialized
        resp = client.call_raw(proto.Initialize())
        assert resp.initialized is True
        assert resp.needs_backup is False
        assert resp.pin_protection is False
        assert resp.passphrase_protection is False
Example #26
0
    def test_2_of_3(self):
        self.setup_mnemonic_nopin_nopassphrase()

        # key1 = self.client.get_public_node([1])
        # key2 = self.client.get_public_node([2])
        # key3 = self.client.get_public_node([3])

        # xpub:
        # print(bip32.serialize(self.client.get_public_node([]).node))
        # xpub661MyMwAqRbcF1zGijBb2K6x9YiJPh58xpcCeLvTxMX6spkY3PcpJ4ABcCyWfskq5DDxM3e6Ez5ePCqG5bnPUXR4wL8TZWyoDaUdiWW7bKy

        # pubkeys:
        #    xpub/1: 0338d78612e990f2eea0c426b5e48a8db70b9d7ed66282b3b26511e0b1c75515a6
        #    xpub/2: 038caebd6f753bbbd2bb1f3346a43cd32140648583673a31d62f2dfb56ad0ab9e3
        #    xpub/3: 03477b9f0f34ae85434ce795f0c5e1e90c9420e5b5fad084d7cce9a487b94a7902

        # redeem script:
        # 52210338d78612e990f2eea0c426b5e48a8db70b9d7ed66282b3b26511e0b1c75515a621038caebd6f753bbbd2bb1f3346a43cd32140648583673a31d62f2dfb56ad0ab9e32103477b9f0f34ae85434ce795f0c5e1e90c9420e5b5fad084d7cce9a487b94a790253ae

        # multisig address: 3E7GDtuHqnqPmDgwH59pVC7AvySiSkbibz

        # tx: c6091adf4c0c23982a35899a6e58ae11e703eacd7954f588ed4b9cdefc4dba52
        # input 1: 0.001 BTC

        node = bip32.deserialize(
            'xpub661MyMwAqRbcF1zGijBb2K6x9YiJPh58xpcCeLvTxMX6spkY3PcpJ4ABcCyWfskq5DDxM3e6Ez5ePCqG5bnPUXR4wL8TZWyoDaUdiWW7bKy'
        )

        multisig = proto.MultisigRedeemScriptType(
            pubkeys=[
                proto.HDNodePathType(node=node, address_n=[1]),
                proto.HDNodePathType(node=node, address_n=[2]),
                proto.HDNodePathType(node=node, address_n=[3])
            ],
            signatures=[b'', b'', b''],
            m=2,
        )

        # Let's go to sign with key 1
        inp1 = proto.TxInputType(
            address_n=[1],
            prev_hash=TXHASH_c6091a,
            prev_index=1,
            script_type=proto.InputScriptType.SPENDMULTISIG,
            multisig=multisig,
        )

        out1 = proto.TxOutputType(
            address='12iyMbUb4R2K3gre4dHSrbu5azG5KaqVss',
            amount=100000,
            script_type=proto.OutputScriptType.PAYTOADDRESS)

        with self.client:
            self.client.set_expected_responses([
                proto.TxRequest(
                    request_type=proto.RequestType.TXINPUT,
                    details=proto.TxRequestDetailsType(request_index=0)),
                proto.TxRequest(
                    request_type=proto.RequestType.TXMETA,
                    details=proto.TxRequestDetailsType(tx_hash=TXHASH_c6091a)),
                proto.TxRequest(request_type=proto.RequestType.TXINPUT,
                                details=proto.TxRequestDetailsType(
                                    request_index=0, tx_hash=TXHASH_c6091a)),
                proto.TxRequest(request_type=proto.RequestType.TXOUTPUT,
                                details=proto.TxRequestDetailsType(
                                    request_index=0, tx_hash=TXHASH_c6091a)),
                proto.TxRequest(request_type=proto.RequestType.TXOUTPUT,
                                details=proto.TxRequestDetailsType(
                                    request_index=1, tx_hash=TXHASH_c6091a)),
                proto.TxRequest(
                    request_type=proto.RequestType.TXOUTPUT,
                    details=proto.TxRequestDetailsType(request_index=0)),
                proto.ButtonRequest(
                    code=proto.ButtonRequestType.ConfirmOutput),
                proto.ButtonRequest(code=proto.ButtonRequestType.SignTx),
                proto.TxRequest(
                    request_type=proto.RequestType.TXINPUT,
                    details=proto.TxRequestDetailsType(request_index=0)),
                proto.TxRequest(
                    request_type=proto.RequestType.TXOUTPUT,
                    details=proto.TxRequestDetailsType(request_index=0)),
                proto.TxRequest(
                    request_type=proto.RequestType.TXOUTPUT,
                    details=proto.TxRequestDetailsType(request_index=0)),
                proto.TxRequest(request_type=proto.RequestType.TXFINISHED),
            ])

            # Now we have first signature
            (signatures1, _) = self.client.sign_tx('Bitcoin', [
                inp1,
            ], [
                out1,
            ])

        assert hexlify(
            signatures1[0]
        ) == b'3045022100985cc1ba316d140eb4b2d4028d8cd1c451f87bff8ff679858732e516ad04cd3402207af6edda99972af0baa7702a3b7448517c8242e7bca669f6861771cdd16ee058'

        # ---------------------------------------
        # Let's do second signature using 3rd key

        multisig = proto.MultisigRedeemScriptType(
            pubkeys=[
                proto.HDNodePathType(node=node, address_n=[1]),
                proto.HDNodePathType(node=node, address_n=[2]),
                proto.HDNodePathType(node=node, address_n=[3])
            ],
            signatures=[signatures1[0], b'',
                        b''],  # Fill signature from previous signing process
            m=2,
        )

        # Let's do a second signature with key 3
        inp3 = proto.TxInputType(
            address_n=[3],
            prev_hash=TXHASH_c6091a,
            prev_index=1,
            script_type=proto.InputScriptType.SPENDMULTISIG,
            multisig=multisig,
        )

        with self.client:
            self.client.set_expected_responses([
                proto.TxRequest(
                    request_type=proto.RequestType.TXINPUT,
                    details=proto.TxRequestDetailsType(request_index=0)),
                proto.TxRequest(
                    request_type=proto.RequestType.TXMETA,
                    details=proto.TxRequestDetailsType(tx_hash=TXHASH_c6091a)),
                proto.TxRequest(request_type=proto.RequestType.TXINPUT,
                                details=proto.TxRequestDetailsType(
                                    request_index=0, tx_hash=TXHASH_c6091a)),
                proto.TxRequest(request_type=proto.RequestType.TXOUTPUT,
                                details=proto.TxRequestDetailsType(
                                    request_index=0, tx_hash=TXHASH_c6091a)),
                proto.TxRequest(request_type=proto.RequestType.TXOUTPUT,
                                details=proto.TxRequestDetailsType(
                                    request_index=1, tx_hash=TXHASH_c6091a)),
                proto.TxRequest(
                    request_type=proto.RequestType.TXOUTPUT,
                    details=proto.TxRequestDetailsType(request_index=0)),
                proto.ButtonRequest(
                    code=proto.ButtonRequestType.ConfirmOutput),
                proto.ButtonRequest(code=proto.ButtonRequestType.SignTx),
                proto.TxRequest(
                    request_type=proto.RequestType.TXINPUT,
                    details=proto.TxRequestDetailsType(request_index=0)),
                proto.TxRequest(
                    request_type=proto.RequestType.TXOUTPUT,
                    details=proto.TxRequestDetailsType(request_index=0)),
                proto.TxRequest(
                    request_type=proto.RequestType.TXOUTPUT,
                    details=proto.TxRequestDetailsType(request_index=0)),
                proto.TxRequest(request_type=proto.RequestType.TXFINISHED),
            ])
            (signatures2,
             serialized_tx) = self.client.sign_tx('Bitcoin', [
                 inp3,
             ], [
                 out1,
             ])

        assert hexlify(
            signatures2[0]
        ) == b'3045022100f5428fe0531b3095675b40d87cab607ee036fac823b22e8dcec35b65aff6e52b022032129b4577ff923d321a1c70db5a6cec5bcc142cb2c51901af8b989cced23e0d'

        # Accepted by network: tx 8382a2b2e3ec8788800c1d46d285dfa9dd4051edddd75982fad166b9273e5ac6
        assert hexlify(
            serialized_tx
        ) == b'010000000152ba4dfcde9c4bed88f55479cdea03e711ae586e9a89352a98230c4cdf1a09c601000000fdfe0000483045022100985cc1ba316d140eb4b2d4028d8cd1c451f87bff8ff679858732e516ad04cd3402207af6edda99972af0baa7702a3b7448517c8242e7bca669f6861771cdd16ee05801483045022100f5428fe0531b3095675b40d87cab607ee036fac823b22e8dcec35b65aff6e52b022032129b4577ff923d321a1c70db5a6cec5bcc142cb2c51901af8b989cced23e0d014c6952210338d78612e990f2eea0c426b5e48a8db70b9d7ed66282b3b26511e0b1c75515a621038caebd6f753bbbd2bb1f3346a43cd32140648583673a31d62f2dfb56ad0ab9e32103477b9f0f34ae85434ce795f0c5e1e90c9420e5b5fad084d7cce9a487b94a790253aeffffffff01a0860100000000001976a91412e8391ad256dcdc023365978418d658dfecba1c88ac00000000'
Example #27
0
    def test_2_of_3(self):
        self.setup_mnemonic_allallall()
        nodes = [
            btc.get_public_node(self.client,
                                parse_path("48'/0'/%d'" % index)).node
            for index in range(1, 4)
        ]

        multisig = proto.MultisigRedeemScriptType(nodes=nodes,
                                                  address_n=[0, 0],
                                                  signatures=[b"", b"", b""],
                                                  m=2)
        # Let's go to sign with key 1
        inp1 = proto.TxInputType(
            address_n=parse_path("48'/0'/1'/0/0"),
            prev_hash=TXHASH_c6091a,
            prev_index=1,
            script_type=proto.InputScriptType.SPENDMULTISIG,
            multisig=multisig,
        )

        out1 = proto.TxOutputType(
            address="12iyMbUb4R2K3gre4dHSrbu5azG5KaqVss",
            amount=100000,
            script_type=proto.OutputScriptType.PAYTOADDRESS,
        )

        with self.client:
            self.client.set_expected_responses([
                proto.TxRequest(
                    request_type=proto.RequestType.TXINPUT,
                    details=proto.TxRequestDetailsType(request_index=0),
                ),
                proto.TxRequest(
                    request_type=proto.RequestType.TXMETA,
                    details=proto.TxRequestDetailsType(tx_hash=TXHASH_c6091a),
                ),
                proto.TxRequest(
                    request_type=proto.RequestType.TXINPUT,
                    details=proto.TxRequestDetailsType(request_index=0,
                                                       tx_hash=TXHASH_c6091a),
                ),
                proto.TxRequest(
                    request_type=proto.RequestType.TXOUTPUT,
                    details=proto.TxRequestDetailsType(request_index=0,
                                                       tx_hash=TXHASH_c6091a),
                ),
                proto.TxRequest(
                    request_type=proto.RequestType.TXOUTPUT,
                    details=proto.TxRequestDetailsType(request_index=1,
                                                       tx_hash=TXHASH_c6091a),
                ),
                proto.TxRequest(
                    request_type=proto.RequestType.TXOUTPUT,
                    details=proto.TxRequestDetailsType(request_index=0),
                ),
                proto.ButtonRequest(
                    code=proto.ButtonRequestType.ConfirmOutput),
                proto.ButtonRequest(code=proto.ButtonRequestType.SignTx),
                proto.TxRequest(
                    request_type=proto.RequestType.TXINPUT,
                    details=proto.TxRequestDetailsType(request_index=0),
                ),
                proto.TxRequest(
                    request_type=proto.RequestType.TXOUTPUT,
                    details=proto.TxRequestDetailsType(request_index=0),
                ),
                proto.TxRequest(
                    request_type=proto.RequestType.TXOUTPUT,
                    details=proto.TxRequestDetailsType(request_index=0),
                ),
                proto.TxRequest(request_type=proto.RequestType.TXFINISHED),
            ])

            # Now we have first signature
            signatures1, _ = btc.sign_tx(self.client,
                                         "Bitcoin", [inp1], [out1],
                                         prev_txes=TX_API)

        assert (
            signatures1[0].hex() ==
            "3044022052f4a3dc5ca3e86ed66abb1e2b4d9b9ace7d96f5615944beea19e58280847c2902201bd3ff32a38366a4eed0373e27da26ebc0d2a4c2bbeffd83e8a60e313d95b9e3"
        )

        # ---------------------------------------
        # Let's do second signature using 3rd key

        multisig = proto.MultisigRedeemScriptType(
            nodes=nodes,
            address_n=[0, 0],
            signatures=[
                signatures1[0],
                b"",
                b"",
            ],  # Fill signature from previous signing process
            m=2,
        )

        # Let's do a second signature with key 3
        inp3 = proto.TxInputType(
            address_n=parse_path("48'/0'/3'/0/0"),
            prev_hash=TXHASH_c6091a,
            prev_index=1,
            script_type=proto.InputScriptType.SPENDMULTISIG,
            multisig=multisig,
        )

        with self.client:
            self.client.set_expected_responses([
                proto.TxRequest(
                    request_type=proto.RequestType.TXINPUT,
                    details=proto.TxRequestDetailsType(request_index=0),
                ),
                proto.TxRequest(
                    request_type=proto.RequestType.TXMETA,
                    details=proto.TxRequestDetailsType(tx_hash=TXHASH_c6091a),
                ),
                proto.TxRequest(
                    request_type=proto.RequestType.TXINPUT,
                    details=proto.TxRequestDetailsType(request_index=0,
                                                       tx_hash=TXHASH_c6091a),
                ),
                proto.TxRequest(
                    request_type=proto.RequestType.TXOUTPUT,
                    details=proto.TxRequestDetailsType(request_index=0,
                                                       tx_hash=TXHASH_c6091a),
                ),
                proto.TxRequest(
                    request_type=proto.RequestType.TXOUTPUT,
                    details=proto.TxRequestDetailsType(request_index=1,
                                                       tx_hash=TXHASH_c6091a),
                ),
                proto.TxRequest(
                    request_type=proto.RequestType.TXOUTPUT,
                    details=proto.TxRequestDetailsType(request_index=0),
                ),
                proto.ButtonRequest(
                    code=proto.ButtonRequestType.ConfirmOutput),
                proto.ButtonRequest(code=proto.ButtonRequestType.SignTx),
                proto.TxRequest(
                    request_type=proto.RequestType.TXINPUT,
                    details=proto.TxRequestDetailsType(request_index=0),
                ),
                proto.TxRequest(
                    request_type=proto.RequestType.TXOUTPUT,
                    details=proto.TxRequestDetailsType(request_index=0),
                ),
                proto.TxRequest(
                    request_type=proto.RequestType.TXOUTPUT,
                    details=proto.TxRequestDetailsType(request_index=0),
                ),
                proto.TxRequest(request_type=proto.RequestType.TXFINISHED),
            ])
            signatures2, serialized_tx = btc.sign_tx(self.client,
                                                     "Bitcoin", [inp3], [out1],
                                                     prev_txes=TX_API)

        assert (
            signatures2[0].hex() ==
            "304402203828fd48540811be6a1b12967e7012587c46e6f05c78d42471e7b25c06bc7afc0220749274bc1aa698335b00400c5ba946a70b6b46c711324fbc4989279737a57f49"
        )

        assert (
            serialized_tx.hex() ==
            "010000000152ba4dfcde9c4bed88f55479cdea03e711ae586e9a89352a98230c4cdf1a09c601000000fc00473044022052f4a3dc5ca3e86ed66abb1e2b4d9b9ace7d96f5615944beea19e58280847c2902201bd3ff32a38366a4eed0373e27da26ebc0d2a4c2bbeffd83e8a60e313d95b9e30147304402203828fd48540811be6a1b12967e7012587c46e6f05c78d42471e7b25c06bc7afc0220749274bc1aa698335b00400c5ba946a70b6b46c711324fbc4989279737a57f49014c6952210203ed6187880ae932660086e55d4561a57952dd200aa3ed2aa66b73e5723a0ce7210360e7f32fd3c8dee27a166f6614c598929699ee66acdcbda5fb24571bf2ae1ca021037c4c7e5d3293ab0f97771dcfdf83caadab341f427f54713da8b2c590a834f03b53aeffffffff01a0860100000000001976a91412e8391ad256dcdc023365978418d658dfecba1c88ac00000000"
        )
        def test_multisig(index):
            address_n, multisig = create_multisig(index, "m/0/0", signatures[0])
            inp1 = proto.TxInputType(
                address_n=address_n,
                # TchpthUkRys1VQWgnQyLJNaA4MLBjVmRL2c
                multisig=multisig,
                prev_hash=TXHASH_3f7c39,
                prev_index=1,
                script_type=proto.InputScriptType.SPENDMULTISIG,
                decred_tree=0,
            )

            address_n, multisig = create_multisig(index, "m/0/1", signatures[1])
            inp2 = proto.TxInputType(
                address_n=address_n,
                # TcnfDEfMhkM3oLWqiq9v9GmYgLK7qfjitKG
                multisig=multisig,
                prev_hash=TXHASH_16da18,
                prev_index=0,
                script_type=proto.InputScriptType.SPENDMULTISIG,
                decred_tree=0,
            )

            address_n, multisig = create_multisig(index, "m/1/0")
            out1 = proto.TxOutputType(
                address_n=address_n,
                # TcrrURA3Bzj4isGU48PdSP9SDoU5oCpjEcb
                multisig=multisig,
                amount=99900000,
                script_type=proto.OutputScriptType.PAYTOMULTISIG,
                decred_script_version=0,
            )

            out2 = proto.TxOutputType(
                address="TsWjioPrP8E1TuTMmTrVMM2BA4iPrjQXBpR",
                amount=300000000,
                script_type=proto.OutputScriptType.PAYTOADDRESS,
                decred_script_version=0,
            )

            with client:
                client.set_expected_responses(
                    [
                        request_input(0),
                        request_meta(TXHASH_3f7c39),
                        request_input(0, TXHASH_3f7c39),
                        request_output(0, TXHASH_3f7c39),
                        request_output(1, TXHASH_3f7c39),
                        request_input(1),
                        request_meta(TXHASH_16da18),
                        request_input(0, TXHASH_16da18),
                        request_output(0, TXHASH_16da18),
                        request_output(1, TXHASH_16da18),
                        request_output(0),
                        request_output(1),
                        proto.ButtonRequest(code=B.ConfirmOutput),
                        proto.ButtonRequest(code=B.SignTx),
                        request_input(0),
                        request_input(1),
                        request_finished(),
                    ]
                )
                signature, serialized_tx = btc.sign_tx(
                    client,
                    "Decred Testnet",
                    [inp1, inp2],
                    [out1, out2],
                    prev_txes=TX_API,
                )

            signatures[0][index] = signature[0]
            signatures[1][index] = signature[1]
            return serialized_tx
def test_attack_change_input_address(client: Client):
    # Simulates an attack where the user is coerced into unknowingly
    # transferring funds from one account to another one of their accounts,
    # potentially resulting in privacy issues.

    inp1 = messages.TxInputType(
        address_n=parse_path("m/49h/1h/0h/1/0"),
        # 2N1LGaGg836mqSQqiuUBLfcyGBhyZbremDX
        amount=123_456_789,
        prev_hash=TXHASH_20912f,
        prev_index=0,
        script_type=messages.InputScriptType.SPENDP2SHWITNESS,
    )
    out1 = messages.TxOutputType(
        address="mhRx1CeVfaayqRwq5zgRQmD7W5aWBfD5mC",
        amount=12_300_000,
        script_type=messages.OutputScriptType.PAYTOADDRESS,
    )
    out2 = messages.TxOutputType(
        address_n=parse_path("m/49h/1h/12h/1/0"),
        script_type=messages.OutputScriptType.PAYTOP2SHWITNESS,
        amount=123_456_789 - 11_000 - 12_300_000,
    )

    # Test if the transaction can be signed normally.
    with client:
        client.set_expected_responses(
            [
                request_input(0),
                request_output(0),
                # The user is required to confirm transfer to another account.
                messages.ButtonRequest(code=B.ConfirmOutput),
                request_output(1),
                messages.ButtonRequest(code=B.ConfirmOutput),
                messages.ButtonRequest(code=B.SignTx),
                request_input(0),
                request_meta(TXHASH_20912f),
                request_input(0, TXHASH_20912f),
                request_output(0, TXHASH_20912f),
                request_output(1, TXHASH_20912f),
                request_input(0),
                request_output(0),
                request_output(1),
                request_input(0),
                request_finished(),
            ]
        )
        _, serialized_tx = btc.sign_tx(
            client, "Testnet", [inp1], [out1, out2], prev_txes=TX_API_TESTNET
        )

    # Transaction does not exist on the blockchain, not using assert_tx_matches()
    assert (
        serialized_tx.hex()
        == "0100000000010137c361fb8f2d9056ba8c98c5611930fcb48cacfdd0fe2e0449d83eea982f91200000000017160014d16b8c0680c61fc6ed2e407455715055e41052f5ffffffff02e0aebb00000000001976a91414fdede0ddc3be652a0ce1afbc1b509a55b6b94888ac3df39f060000000017a9142f98413cb83ff8b3eaf1926192e68973cbd68a3a8702473044022013cbce7c575337ca05dbe03b5920a0805b510cd8dfd3180bd7c5d01cec6439cd0220050001be4bcefb585caf973caae0ffec682347f2127cc22f26efd93ee54fd852012103e7bfe10708f715e8538c92d46ca50db6f657bbc455b7494e6a0303ccdb868b7900000000"
    )

    attack_count = 2

    def attack_processor(msg):
        nonlocal attack_count

        if attack_count > 0 and msg.tx.inputs and msg.tx.inputs[0] == inp1:
            attack_count -= 1
            msg.tx.inputs[0].address_n[2] = H_(12)

        return msg

    # Now run the attack, must trigger the exception
    with client:
        client.set_filter(messages.TxAck, attack_processor)
        with pytest.raises(TrezorFailure):
            btc.sign_tx(
                client, "Testnet", [inp1], [out1, out2], prev_txes=TX_API_TESTNET
            )
    def test_reset_device_shamir(self):
        strength = 128

        # TODO: uncomment when python_shamir_mnemonic is uploaded to pypi
        # member_threshold = 2

        def input_flow():
            # Confirm Reset
            btn_code = yield
            assert btn_code == B.ResetDevice
            self.client.debug.press_yes()

            # Backup your seed
            btn_code = yield
            assert btn_code == B.ResetDevice
            self.client.debug.press_yes()

            # Confirm warning
            btn_code = yield
            assert btn_code == B.ResetDevice
            self.client.debug.press_yes()

            # shares info
            btn_code = yield
            assert btn_code == B.ResetDevice
            self.client.debug.press_yes()

            # Set & Confirm number of shares
            btn_code = yield
            assert btn_code == B.ResetDevice
            self.client.debug.press_yes()

            # threshold info
            btn_code = yield
            assert btn_code == B.ResetDevice
            self.client.debug.press_yes()

            # Set & confirm threshold value
            btn_code = yield
            assert btn_code == B.ResetDevice
            self.client.debug.press_yes()

            # Confirm show seeds
            btn_code = yield
            assert btn_code == B.ResetDevice
            self.client.debug.press_yes()

            # show & confirm shares
            all_mnemonics = []
            for h in range(5):
                words = []
                btn_code = yield
                assert btn_code == B.Other

                # mnemonic phrases
                # 20 word over 6 pages for strength 128, 33 words over 9 pages for strength 256
                for i in range(6):
                    time.sleep(1)
                    words.extend(self.client.debug.state().reset_word.split())
                    if i < 5:
                        self.client.debug.swipe_down()
                    else:
                        # last page is confirmation
                        self.client.debug.press_yes()

                # check share
                for _ in range(3):
                    time.sleep(1)
                    index = self.client.debug.state().reset_word_pos
                    self.client.debug.input(words[index])

                all_mnemonics.extend([" ".join(words)])

                # Confirm continue to next share
                btn_code = yield
                assert btn_code == B.ResetDevice
                self.client.debug.press_yes()

            # generate secret locally
            # internal_entropy = self.client.debug.state().reset_entropy
            # secret = generate_entropy(strength, internal_entropy, EXTERNAL_ENTROPY)

            # validate that all combinations will result in the correct master secret
            # validate_mnemonics(all_mnemonics, member_threshold, secret)

            # safety warning
            btn_code = yield
            assert btn_code == B.ResetDevice
            self.client.debug.press_yes()

        os_urandom = mock.Mock(return_value=EXTERNAL_ENTROPY)
        with mock.patch("os.urandom", os_urandom), self.client:
            self.client.set_expected_responses([
                proto.ButtonRequest(code=B.ResetDevice),
                proto.EntropyRequest(),
                proto.ButtonRequest(code=B.ResetDevice),
                proto.ButtonRequest(code=B.ResetDevice),
                proto.ButtonRequest(code=B.ResetDevice),
                proto.ButtonRequest(code=B.ResetDevice),
                proto.ButtonRequest(code=B.ResetDevice),
                proto.ButtonRequest(code=B.ResetDevice),
                proto.ButtonRequest(code=B.ResetDevice),
                proto.ButtonRequest(code=B.Other),
                proto.ButtonRequest(code=B.ResetDevice),
                proto.ButtonRequest(code=B.Other),
                proto.ButtonRequest(code=B.ResetDevice),
                proto.ButtonRequest(code=B.Other),
                proto.ButtonRequest(code=B.ResetDevice),
                proto.ButtonRequest(code=B.Other),
                proto.ButtonRequest(code=B.ResetDevice),
                proto.ButtonRequest(code=B.Other),
                proto.ButtonRequest(code=B.ResetDevice),
                proto.ButtonRequest(code=B.ResetDevice),
                proto.Success(),
                proto.Features(),
            ])
            self.client.set_input_flow(input_flow)

            # No PIN, no passphrase, don't display random
            device.reset(
                self.client,
                display_random=False,
                strength=strength,
                passphrase_protection=False,
                pin_protection=False,
                label="test",
                language="english",
                slip39=True,
            )

        # Check if device is properly initialized
        resp = self.client.call_raw(proto.Initialize())
        assert resp.initialized is True
        assert resp.needs_backup is False
        assert resp.pin_protection is False
        assert resp.passphrase_protection is False