diff --git a/src/apps/management/__init__.py b/src/apps/management/__init__.py index df1d776fba..88ff912d81 100644 --- a/src/apps/management/__init__.py +++ b/src/apps/management/__init__.py @@ -12,8 +12,8 @@ def dispatch_LoadDevice(*args, **kwargs): @unimport def dispatch_ResetDevice(*args, **kwargs): - from .reset_device import layout_reset_device - return layout_reset_device(*args, **kwargs) + from .reset_device import reset_device + return reset_device(*args, **kwargs) @unimport diff --git a/src/apps/management/reset_device.py b/src/apps/management/reset_device.py index 5b6c5d348e..77fdb7d210 100644 --- a/src/apps/management/reset_device.py +++ b/src/apps/management/reset_device.py @@ -1,6 +1,5 @@ from micropython import const -from trezor import wire, ui -from trezor.ui.container import Container +from trezor import config, ui, wire from trezor.utils import unimport, chunks from ubinascii import hexlify @@ -8,11 +7,11 @@ if __debug__: internal_entropy = None current_word = None + @unimport -async def layout_reset_device(ctx, msg): - from trezor import config +async def reset_device(ctx, msg): from trezor.ui.text import Text - from trezor.crypto import hashlib, random, bip39, random + from trezor.crypto import hashlib, random, bip39 from trezor.ui.keyboard import MnemonicKeyboard from trezor.messages.EntropyRequest import EntropyRequest from trezor.messages.Success import Success @@ -36,11 +35,13 @@ async def layout_reset_device(ctx, msg): internal_entropy = random.bytes(32) + # display internal entropy if msg.display_random: entropy_lines = chunks(hexlify(internal_entropy).decode(), 16) entropy_content = Text('Internal entropy', ui.ICON_RESET, ui.MONO, *entropy_lines) await require_confirm(ctx, entropy_content, ButtonRequestType.ResetDevice) + # request new PIN if msg.pin_protection: curpin = '' newpin = await request_pin_confirm(ctx) @@ -48,6 +49,7 @@ async def layout_reset_device(ctx, msg): curpin = '' newpin = '' + # request external entropy and compute mnemonic external_entropy_ack = await ctx.call(EntropyRequest(), EntropyAck) ehash = hashlib.sha256() ehash.update(internal_entropy) @@ -55,79 +57,62 @@ async def layout_reset_device(ctx, msg): entropy = ehash.digest() mnemonic = bip39.from_data(entropy[:msg.strength // 8]) - # seed-copy warning - warning_content = Text('Backup your seed', ui.ICON_NOCOPY, ui.NORMAL, - 'Never make a digital', - 'copy of your recovery', - 'seed and never upload', - 'it online!') - await require_confirm(ctx, warning_content, ButtonRequestType.ResetDevice) + # mnemonic safety warning + warning_content = Text( + 'Backup your seed', ui.ICON_NOCOPY, ui.NORMAL, + 'Never make a digital', + 'copy of your recovery', + 'seed and never upload', + 'it online!') + await require_confirm( + ctx, + warning_content, + ButtonRequestType.ResetDevice, + confirm='I understand', + cancel=None) # ask to write down mnemonic await show_mnemonic(mnemonic) - # ask for random number to check correctness - words = list(enumerate(mnemonic.split())) + # ask for random word to check correctness + words = mnemonic.split() index = random.uniform(len(words)) - word = words[index][1] - board = MnemonicKeyboard() - board.prompt = ('Type %s. word' % (index + 1)) - res = await board - if res != word: - fail_content = Text('Wrong entry!', ui.ICON_CLEAR, ui.NORMAL, - 'You have entered', - 'wrong seed word.', - 'Please, reconnect', - 'device and try again.', icon_color=ui.RED) - # todo redesign dialog to single cancel button with text 'Reconnect' or something else (no icon) - await require_confirm(ctx, fail_content, ButtonRequestType.ResetDevice) + res = await MnemonicKeyboard('Type %s. word' % (index + 1)) + if res != words[index]: + content = Text( + 'Wrong entry!', ui.ICON_CLEAR, + 'You have entered', + 'wrong seed word.', + 'Please, reconnect', + 'the device and try again.', icon_color=ui.RED) + ui.display.clear() + await content + raise wire.FailureError(FailureType.DataError, 'Wrong entry') + # write into storage if curpin != newpin: config.change_pin(curpin, newpin) - storage.load_settings(label=msg.label, - use_passphrase=msg.passphrase_protection) + storage.load_settings( + label=msg.label, use_passphrase=msg.passphrase_protection) storage.load_mnemonic(mnemonic) - fail_content = Text('Backup is done!', ui.ICON_CONFIRM, ui.NORMAL, - 'Never make a digital', - 'copy of your recovery', - 'seed and never upload', - 'it online!', icon_color=ui.GREEN) - # todo redesign dialog to single cancel button with text 'Finish?' or something else (no icon) - await require_confirm(ctx, fail_content, ButtonRequestType.ResetDevice) + # show success message + content = Text( + 'Backup is done!', ui.ICON_CONFIRM, + 'Never make a digital', + 'copy of your recovery', + 'seed and never upload', + 'it online!', icon_color=ui.GREEN) + await require_confirm( + ctx, + content, + ButtonRequestType.ResetDevice, + confirm='Finish setup', + cancel=None) return Success(message='Initialized') -async def show_mnemonic_by_word(ctx, mnemonic): - from trezor.ui.text import Text - from trezor.messages.ButtonRequestType import ConfirmWord - from apps.common.confirm import confirm - - words = mnemonic.split() - - if __debug__: - global current_word - - for index, word in enumerate(words): - if __debug__: - current_word = word - await confirm(ctx, - Text('Recovery seed setup', ui.ICON_RESET, - ui.NORMAL, 'Write down seed word', '', - ui.BOLD, '%d. %s' % (index + 1, word)), - ConfirmWord, confirm='Next', cancel=None) - - for index, word in enumerate(words): - if __debug__: - current_word = word - await confirm(ctx, - Text('Recovery seed setup', ui.ICON_RESET, - ui.NORMAL, 'Confirm seed word', '', - ui.BOLD, '%d. %s' % (index + 1, word)), - ConfirmWord, confirm='Next', cancel=None) - - async def show_mnemonic(mnemonic): from trezor.ui.scroll import paginate @@ -143,17 +128,18 @@ async def show_mnemonic_page(page, page_count, mnemonic): from trezor.ui.text import Text from trezor.ui.scroll import Scrollpage, animate_swipe - lines = [] - for pi, (wi, word) in enumerate(mnemonic[page]): - pos = wi + 1 - lines.append(str('%d. %s' % (pos, word))) + lines = ['%d. %s' % (wi + 1, word) for wi, word in mnemonic[page]] + scroll_page = Scrollpage( + Text('Recovery seed setup', ui.ICON_RESET, ui.MONO, lines), + page, + page_count) ui.display.clear() - scroll_page = Scrollpage(Text('Recovery seed setup', ui.ICON_RESET, ui.MONO, lines), page, page_count) scroll_page.render() + if page + 1 == page_count: await Button( - (0, 240 - 48, 240, 48), - 'Finalize', + ui.grid(4, n_x=1), + "I'm done", normal_style=ui.BTN_CONFIRM, active_style=ui.BTN_CONFIRM_ACTIVE) ui.display.clear()