Пример #1
0
async def require_confirm_sign_identity(ctx, identity, challenge_visual):
    lines = []
    if challenge_visual:
        lines.append(challenge_visual)

    lines.append(ui.MONO)
    lines.extend(chunks(serialize_identity_without_proto(identity), 18))

    proto = identity.proto.upper() if identity.proto else "identity"
    text = Text("Sign %s" % proto)
    text.normal(*lines)
    await require_confirm(ctx, text)
Пример #2
0
async def _require_confirm_paginated(ctx: wire.Context, header: str,
                                     fields: List[str], per_page: int) -> None:
    pages = []
    for page in chunks(fields, per_page):
        if header == "Arbitrary data":
            text = Text(header, ui.ICON_WIPE, ui.RED)
        else:
            text = Text(header, ui.ICON_CONFIRM, ui.GREEN)
        text.mono(*page)
        pages.append(text)
    await require_confirm(ctx, Paginated(pages),
                          ButtonRequestType.ConfirmOutput)
Пример #3
0
async def layout_reset_device(session_id, msg):
    from trezor.ui.text import Text
    from trezor.crypto import hashlib, random, bip39
    from trezor.messages.EntropyRequest import EntropyRequest
    from trezor.messages.Success import Success
    from trezor.messages import FailureType
    from trezor.messages import ButtonRequestType
    from trezor.messages.wire_types import EntropyAck

    from apps.common.request_pin import request_pin_twice
    from apps.common.confirm import require_confirm
    from apps.common import storage

    if __debug__:
        global internal_entropy

    if msg.strength not in (128, 192, 256):
        raise wire.FailureError(
            FailureType.Other, 'Invalid strength (has to be 128, 192 or 256 bits)')

    if storage.is_initialized():
        raise wire.FailureError(
            FailureType.UnexpectedMessage, 'Already initialized')

    internal_entropy = random.bytes(32)

    if msg.display_random:
        entropy_lines = chunks(ubinascii.hexlify(internal_entropy), 16)
        entropy_content = Text('Internal entropy', ui.ICON_RESET, *entropy_lines)
        await require_confirm(session_id, entropy_content, ButtonRequestType.ResetDevice)

    if msg.pin_protection:
        pin = await request_pin_twice(session_id)
    else:
        pin = None

    external_entropy_ack = await wire.call(session_id, EntropyRequest(), EntropyAck)
    ctx = hashlib.sha256()
    ctx.update(internal_entropy)
    ctx.update(external_entropy_ack.entropy)
    entropy = ctx.digest()
    mnemonic = bip39.from_data(entropy[:msg.strength // 8])

    await show_mnemonic_by_word(session_id, mnemonic)

    storage.load_mnemonic(mnemonic)
    storage.load_settings(pin=pin,
                          passphrase_protection=msg.passphrase_protection,
                          language=msg.language,
                          label=msg.label)

    return Success(message='Initialized')
Пример #4
0
async def naive_pagination(
    ctx, lines, title, icon=ui.ICON_RESET, icon_color=ui.ORANGE, per_page=5
):
    from trezor.ui.confirm import CANCELLED, CONFIRMED, DEFAULT_CANCEL, DEFAULT_CONFIRM

    if isinstance(lines, (list, tuple)):
        lines = lines
    else:
        lines = list(chunks(lines, 16))

    pages = paginate_lines(lines, per_page)
    npages = len(pages)
    cur_step = 0
    code = ButtonRequestType.SignTx
    iback = res.load(ui.ICON_BACK)
    inext = res.load(ui.ICON_CLICK)

    while cur_step <= npages:
        text = pages[cur_step]
        fst_page = cur_step == 0
        lst_page = cur_step + 1 >= npages

        cancel_btn = DEFAULT_CANCEL if fst_page else iback
        cancel_style = ui.BTN_CANCEL if fst_page else ui.BTN_DEFAULT
        confirm_btn = DEFAULT_CONFIRM if lst_page else inext
        confirm_style = ui.BTN_CONFIRM if lst_page else ui.BTN_DEFAULT

        paging = ("%d/%d" % (cur_step + 1, npages)) if npages > 1 else ""
        content = Text("%s %s" % (title, paging), icon, icon_color=icon_color)
        content.normal(*text)

        reaction = await tx_dialog(
            ctx,
            code,
            content,
            cancel_btn,
            confirm_btn,
            cancel_style,
            confirm_style,
            (cur_step, npages),
        )

        if fst_page and reaction == CANCELLED:
            return False
        elif not lst_page and reaction == CONFIRMED:
            cur_step += 1
        elif lst_page and reaction == CONFIRMED:
            return True
        elif reaction == CANCELLED:
            cur_step -= 1
        elif reaction == CONFIRMED:
            cur_step += 1
Пример #5
0
def _truncate_hex(
    hex_data: str,
    lines: int = TEXT_MAX_LINES,
    width: int = MONO_HEX_PER_LINE,
    middle: bool = False,
) -> Iterator[str]:
    if len(hex_data) >= width * lines:
        if middle:
            hex_data = (hex_data[:lines * width // 2 - 1] + "..." +
                        hex_data[-lines * width // 2 + 2:])
        else:
            hex_data = hex_data[:(width * lines - 3)] + "..."
    return chunks(hex_data, width)
Пример #6
0
async def _confirm_share_words(ctx, share_index, share_words, group_index=None):
    # divide list into thirds, rounding up, so that chunking by `third` always yields
    # three parts (the last one might be shorter)
    third = (len(share_words) + 2) // 3

    offset = 0
    count = len(share_words)
    for part in utils.chunks(share_words, third):
        if not await _confirm_word(ctx, share_index, part, offset, count, group_index):
            return False
        offset += len(part)

    return True
Пример #7
0
async def confirm_sending(ctx: wire.Context, amount: int, to: str) -> None:
    page1 = Text("Confirm transaction", ui.ICON_SEND, ui.GREEN)
    page1.normal("Confirm sending:")
    page1.bold(format_coin_amount(amount))
    page1.normal("to")

    to_lines = list(chunks(to, 17))
    page1.bold(to_lines[0])

    pages = [page1] + _paginate_lines(to_lines, 1, "Confirm transaction",
                                      ui.ICON_SEND)

    await require_confirm(ctx, Paginated(pages))
Пример #8
0
def _paginate_lines(
    lines: List[str], offset: int, desc: str, icon: str, per_page: int = 4
) -> List[ui.Component]:
    pages = []
    if len(lines) > offset:
        to_pages = list(chunks(lines[offset:], per_page))
        for page in to_pages:
            t = Text(desc, icon, ui.GREEN)
            for line in page:
                t.bold(line)
            pages.append(t)

    return pages
Пример #9
0
async def show_address(
    ctx: wire.Context,
    address: str,
    address_type: EnumTypeCardanoAddressType,
    path: List[int],
    network: str = None,
) -> bool:
    """
    Custom show_address function is needed because cardano addresses don't
    fit on a single screen.
    """

    address_type_label = "%s address" % ADDRESS_TYPE_NAMES[address_type]
    page1 = Text(address_type_label, ui.ICON_RECEIVE, ui.GREEN)

    lines_per_page = 5
    lines_used_on_first_page = 0

    # assemble first page to be displayed (path + network + whatever part of the address fits)
    if network is not None:
        page1.normal("%s network" % network)
        lines_used_on_first_page += 1

    path_str = address_n_to_str(path)
    page1.mono(path_str)
    lines_used_on_first_page = min(
        lines_used_on_first_page + math.ceil(len(path_str) / _MAX_MONO_LINE),
        lines_per_page,
    )

    address_lines = list(chunks(address, 17))
    for address_line in address_lines[:lines_per_page -
                                      lines_used_on_first_page]:
        page1.bold(address_line)

    # append remaining pages containing the rest of the address
    pages = [page1] + _paginate_lines(
        address_lines,
        lines_per_page - lines_used_on_first_page,
        address_type_label,
        ui.ICON_RECEIVE,
        lines_per_page,
    )

    return await confirm(
        ctx,
        Paginated(pages),
        code=ButtonRequestType.Address,
        cancel="QR",
        cancel_style=ButtonDefault,
    )
Пример #10
0
async def require_confirm_sign_identity(
        ctx: wire.Context, identity: IdentityType,
        challenge_visual: Optional[str]) -> None:
    lines: List[TextContent] = []
    if challenge_visual:
        lines.append(challenge_visual)

    lines.append(ui.MONO)
    lines.extend(chunks(serialize_identity_without_proto(identity), 18))

    proto = identity.proto.upper() if identity.proto else "identity"
    text = Text("Sign %s" % proto)
    text.normal(*lines)
    await require_confirm(ctx, text)
Пример #11
0
async def confirm_sign_identity(ctx: wire.GenericContext, proto: str,
                                identity: str,
                                challenge_visual: str | None) -> None:
    lines: list[TextContent] = []
    if challenge_visual:
        lines.append(challenge_visual)

    lines.append(ui.MONO)
    lines.extend(chunks(identity, 18))

    text = Text("Sign %s" % proto)
    text.normal(*lines)
    await raise_if_cancelled(
        interact(ctx, Confirm(text), "sign_identity", ButtonRequestType.Other))
Пример #12
0
async def _confirm_share_words(ctx, share_index, share_words):
    numbered = list(enumerate(share_words))

    # check three words
    third = len(numbered) // 3
    # if the num of words is not dividable by 3 let's add 1
    # to have more words at the beggining and to check all of them
    if len(numbered) % 3:
        third += 1

    for part in utils.chunks(numbered, third):
        if not await _confirm_word(ctx, share_index, part, len(share_words)):
            return False

    return True
Пример #13
0
async def confirm_action_sellram(ctx, msg: EosActionSellRam):
    await ctx.call(ButtonRequest(code=ButtonRequestType.ConfirmOutput),
                   MessageType.ButtonAck)

    text = "Sell RAM"
    fields = []
    fields.append("Receiver:")
    fields.append(helpers.eos_name_to_string(msg.account))
    fields.append("Bytes:")
    fields.append(str(msg.bytes))

    pages = list(chunks(fields, _TWO_FIELDS_PER_PAGE))
    paginator = paginate(show_lines_page, len(pages), _FIRST_PAGE, pages, text)

    await ctx.wait(paginator)
    def test_send_native_invalid_address(self):

        coin = coins.by_name('Testnet')
        seed = bip39.seed(' '.join(['all'] * 12), '')

        inp1 = TxInputType(
            # 49'/1'/0'/0/0" - tb1qqzv60m9ajw8drqulta4ld4gfx0rdh82un5s65s
            address_n=[49 | 0x80000000, 1 | 0x80000000, 0 | 0x80000000, 0, 0],
            amount=12300000,
            prev_hash=unhexlify('09144602765ce3dd8f4329445b20e3684e948709c5cdcaf12da3bb079c99448a'),
            prev_index=0,
            script_type=InputScriptType.SPENDWITNESS,
            sequence=0xffffffff,
            multisig=None,
        )
        out1 = TxOutputType(
            address='TB1Q694CCP5QCC0UDMFWGP692U2S2HJPQ5H407URTU',  # Error: should be lower case
            script_type=OutputScriptType.PAYTOADDRESS,
            amount=12300000 - 11000 - 5000000,
            address_n=[],
            multisig=None,
        )
        tx = SignTx(coin_name='Testnet', version=None, lock_time=None, inputs_count=1, outputs_count=1)

        messages = [
            None,

            # check fee
            TxRequest(request_type=TXINPUT, details=TxRequestDetailsType(request_index=0, tx_hash=None), serialized=EMPTY_SERIALIZED),
            TxAck(tx=TransactionType(inputs=[inp1])),

            helpers.UiConfirmForeignAddress(address_n=inp1.address_n),
            True,

            TxRequest(request_type=TXOUTPUT, details=TxRequestDetailsType(request_index=0, tx_hash=None), serialized=EMPTY_SERIALIZED),
            TxAck(tx=TransactionType(outputs=[out1])),
            None
        ]

        ns = get_namespaces_for_coin(coin)
        keychain = Keychain(seed, ns)
        signer = bitcoin.Bitcoin(tx, keychain, coin).signer()
        for request, response in chunks(messages, 2):
            if response is None:
                with self.assertRaises(wire.DataError):
                    signer.send(request)
            else:
                self.assertEqual(signer.send(request), response)
Пример #15
0
def _split_share_into_pages(share_words):
    share = list(enumerate(share_words))  # we need to keep track of the word indices
    first = share[:2]  # two words on the first page
    length = len(share_words)
    if length == 12 or length == 20 or length == 24:
        middle = share[2:-2]
        last = share[-2:]  # two words on the last page
    elif length == 33:
        middle = share[2:]
        last = []  # no words at the last page, because it does not add up
    else:
        # Invalid number of shares. SLIP-39 allows 20 or 33 words, BIP-39 12 or 24
        raise RuntimeError

    chunks = utils.chunks(middle, 4)  # 4 words on the middle pages
    return first, list(chunks), last
Пример #16
0
def _show_xpub(xpub: str, title: str, cancel: str) -> Paginated:
    pages: list[ui.Component] = []
    for lines in chunks(list(chunks_intersperse(xpub, 16)), TEXT_MAX_LINES * 2):
        text = Text(title, ui.ICON_RECEIVE, ui.GREEN, new_lines=False)
        text.mono(*lines)
        pages.append(text)

    content = Paginated(pages)

    content.pages[-1] = Confirm(
        content.pages[-1],
        cancel=cancel,
        cancel_style=ButtonDefault,
    )

    return content
Пример #17
0
async def confirm_action_unknown(ctx, action, checksum):
    await ctx.call(ButtonRequest(code=ButtonRequestType.ConfirmOutput),
                   MessageType.ButtonAck)
    text = "Arbitrary data"
    fields = []
    fields.append("Contract:")
    fields.append(helpers.eos_name_to_string(action.account))
    fields.append("Action Name:")
    fields.append(helpers.eos_name_to_string(action.name))

    fields.append("Checksum: ")
    fields += split_data(hexlify(checksum).decode("ascii"))

    pages = list(chunks(fields, _FIVE_FIELDS_PER_PAGE))
    paginator = paginate(show_lines_page, len(pages), _FIRST_PAGE, pages, text)

    await ctx.wait(paginator)
Пример #18
0
async def confirm_action_newaccount(ctx, msg: EosActionNewAccount):
    await ctx.call(ButtonRequest(code=ButtonRequestType.ConfirmOutput),
                   MessageType.ButtonAck)

    text = "New Account"
    fields = []
    fields.append("Creator:")
    fields.append(helpers.eos_name_to_string(msg.creator))
    fields.append("Name:")
    fields.append(helpers.eos_name_to_string(msg.name))
    fields += authorization_fields(msg.owner)
    fields += authorization_fields(msg.active)

    pages = list(chunks(fields, _FOUR_FIELDS_PER_PAGE))
    paginator = paginate(show_lines_page, len(pages), _FIRST_PAGE, pages, text)

    await ctx.wait(paginator)
Пример #19
0
async def confirm_action_unlinkauth(ctx, msg: EosActionUnlinkAuth):
    await ctx.call(ButtonRequest(code=ButtonRequestType.ConfirmOutput),
                   MessageType.ButtonAck)

    text = "Unlink Auth"
    fields = []
    fields.append("Account:")
    fields.append(helpers.eos_name_to_string(msg.account))
    fields.append("Code:")
    fields.append(helpers.eos_name_to_string(msg.code))
    fields.append("Type:")
    fields.append(helpers.eos_name_to_string(msg.type))

    pages = list(chunks(fields, _FOUR_FIELDS_PER_PAGE))
    paginator = paginate(show_lines_page, len(pages), _FIRST_PAGE, pages, text)

    await ctx.wait(paginator)
Пример #20
0
async def confirm_action_buyrambytes(ctx, msg: EosActionBuyRamBytes):
    await ctx.call(ButtonRequest(code=ButtonRequestType.ConfirmOutput),
                   MessageType.ButtonAck)

    text = "Buy RAM"
    fields = []
    fields.append("Payer:")
    fields.append(helpers.eos_name_to_string(msg.payer))
    fields.append("Receiver:")
    fields.append(helpers.eos_name_to_string(msg.receiver))
    fields.append("Bytes:")
    fields.append(str(msg.bytes))

    pages = list(chunks(fields, _FOUR_FIELDS_PER_PAGE))
    paginator = paginate(show_lines_page, len(pages), _FIRST_PAGE, pages, text)

    await ctx.wait(paginator)
Пример #21
0
async def show_warning_tx_staking_key_hash(
    ctx: wire.Context, staking_key_hash: bytes, amount: int,
):
    t1 = Text("Confirm transaction", ui.ICON_SEND, ui.GREEN)
    t1.normal("Change address staking")
    t1.normal("rights do not match")
    t1.normal("the current account.")

    t2 = Text("Confirm transaction", ui.ICON_SEND, ui.GREEN)
    t2.normal("Staking key hash:")
    t2.mono(*chunks(hexlify(staking_key_hash), 17))

    t3 = Text("Confirm transaction", ui.ICON_SEND, ui.GREEN)
    t3.normal("Change amount:")
    t3.bold(format_coin_amount(amount))

    await require_confirm(ctx, Paginated([t1, t2, t3]))
Пример #22
0
async def confirm_action_updateauth(ctx, msg: EosActionUpdateAuth):
    await ctx.call(ButtonRequest(code=ButtonRequestType.ConfirmOutput),
                   MessageType.ButtonAck)

    text = "Update Auth"
    fields = []
    fields.append("Account:")
    fields.append(helpers.eos_name_to_string(msg.account))
    fields.append("Permission:")
    fields.append(helpers.eos_name_to_string(msg.permission))
    fields.append("Parent:")
    fields.append(helpers.eos_name_to_string(msg.parent))
    fields += authorization_fields(msg.auth)

    pages = list(chunks(fields, _FOUR_FIELDS_PER_PAGE))

    paginator = paginate(show_lines_page, len(pages), _FIRST_PAGE, pages, text)
    await ctx.wait(paginator)
Пример #23
0
async def confirm_action_undelegate(ctx, msg: EosActionUndelegate):
    await ctx.call(ButtonRequest(code=ButtonRequestType.ConfirmOutput),
                   MessageType.ButtonAck)

    text = "Undelegate"
    fields = []
    fields.append("Sender:")
    fields.append(helpers.eos_name_to_string(msg.sender))
    fields.append("Receiver:")
    fields.append(helpers.eos_name_to_string(msg.receiver))
    fields.append("CPU:")
    fields.append(helpers.eos_asset_to_string(msg.cpu_quantity))
    fields.append("NET:")
    fields.append(helpers.eos_asset_to_string(msg.net_quantity))

    pages = list(chunks(fields, _FOUR_FIELDS_PER_PAGE))
    paginator = paginate(show_lines_page, len(pages), _FIRST_PAGE, pages, text)

    await ctx.wait(paginator)
Пример #24
0
async def _confirm_share_words(
    ctx: wire.GenericContext,
    share_index: int | None,
    share_words: Sequence[str],
    group_index: int | None = None,
) -> bool:
    # divide list into thirds, rounding up, so that chunking by `third` always yields
    # three parts (the last one might be shorter)
    third = (len(share_words) + 2) // 3

    offset = 0
    count = len(share_words)
    for part in utils.chunks(share_words, third):
        if not await confirm_word(ctx, share_index, part, offset, count,
                                  group_index):
            return False
        offset += len(part)

    return True
Пример #25
0
def _show_address(
    address: str,
    title: str,
    network: str | None = None,
    extra: str | None = None,
) -> ui.Layout:
    para = [(ui.NORMAL, f"{network} network")] if network is not None else []
    if extra is not None:
        para.append((ui.BOLD, extra))
    para.extend((ui.MONO, address_line)
                for address_line in chunks(address, MONO_ADDR_PER_LINE))
    return paginate_paragraphs(
        para,
        header=title,
        header_icon=ui.ICON_RECEIVE,
        icon_color=ui.GREEN,
        confirm=lambda content: Confirm(
            content, cancel="QR", cancel_style=ButtonDefault),
    )
Пример #26
0
def _split_share_into_pages(
    share_words: Sequence[str],
) -> tuple[NumberedWords, list[NumberedWords], NumberedWords]:
    share = list(
        enumerate(share_words))  # we need to keep track of the word indices
    first = share[:2]  # two words on the first page
    length = len(share_words)
    if length in (12, 20, 24):
        middle = share[2:-2]
        last = share[-2:]  # two words on the last page
    elif length in (18, 33):
        middle = share[2:]
        last = []  # no words at the last page, because it does not add up
    else:
        # Invalid number of shares. SLIP-39 allows 20 or 33 words, BIP-39 12 or 24
        raise RuntimeError

    chunks = utils.chunks(middle, 4)  # 4 words on the middle pages
    return first, list(chunks), last
Пример #27
0
async def _bip39_show_mnemonic(ctx, words: list):
    # split mnemonic words into pages
    PER_PAGE = const(4)
    words = list(enumerate(words))
    words = list(utils.chunks(words, PER_PAGE))

    # display the pages, with a confirmation dialog on the last one
    pages = [_get_mnemonic_page(page) for page in words]
    paginated = Paginated(pages)

    if __debug__:

        def export_displayed_words():
            # export currently displayed mnemonic words into debuglink
            debug.reset_current_words = [w for _, w in words[paginated.page]]

        paginated.on_change = export_displayed_words
        export_displayed_words()

    await hold_to_confirm(ctx, paginated, ButtonRequestType.ResetDevice)
Пример #28
0
async def confirm_sending(
    ctx: wire.Context,
    ada_amount: int,
    token_bundle: List[CardanoAssetGroupType],
    to: str,
) -> None:
    await confirm_sending_token_bundle(ctx, token_bundle)

    page1 = Text("Confirm transaction", ui.ICON_SEND, ui.GREEN)
    page1.normal("Confirm sending:")
    page1.bold(format_coin_amount(ada_amount))
    page1.normal("to")

    to_lines = list(chunks(to, 17))
    page1.bold(to_lines[0])

    comp: ui.Component = page1  # otherwise `[page1]` is of the wrong type
    pages = [comp] + _paginate_lines(to_lines, 1, "Confirm transaction", ui.ICON_SEND)

    await require_confirm(ctx, Paginated(pages))
Пример #29
0
async def confirm_sending(
    ctx: wire.Context,
    ada_amount: int,
    token_bundle: List[CardanoAssetGroupType],
    to: str,
) -> None:
    for token_group in token_bundle:
        await confirm_sending_token_group(ctx, token_group)

    page1 = Text("Confirm transaction", ui.ICON_SEND, ui.GREEN)
    page1.normal("Confirm sending:")
    page1.bold(format_coin_amount(ada_amount))
    page1.normal("to")

    to_lines = list(chunks(to, 17))
    page1.bold(to_lines[0])

    pages = [page1] + _paginate_lines(to_lines, 1, "Confirm transaction",
                                      ui.ICON_SEND)

    await require_confirm(ctx, Paginated(pages))
Пример #30
0
async def confirm_action_transfer(ctx, msg: EosActionTransfer, account: str):
    await ctx.call(ButtonRequest(code=ButtonRequestType.ConfirmOutput),
                   MessageType.ButtonAck)

    text = "Transfer"
    fields = []
    fields.append("From:")
    fields.append(helpers.eos_name_to_string(msg.sender))
    fields.append("To:")
    fields.append(helpers.eos_name_to_string(msg.receiver))
    fields.append("Amount:")
    fields.append(helpers.eos_asset_to_string(msg.quantity))
    fields.append("Contract:")
    fields.append(account)

    if msg.memo is not None:
        fields.append("Memo:")
        fields += split_data(msg.memo[:512])

    pages = list(chunks(fields, _FOUR_FIELDS_PER_PAGE))

    paginator = paginate(show_lines_page, len(pages), _FIRST_PAGE, pages, text)
    await ctx.wait(paginator)