From ca484b2c061bb8f05a84c3d502c6b41c09babe17 Mon Sep 17 00:00:00 2001 From: Tomas Susanka Date: Thu, 31 Oct 2019 10:27:59 +0100 Subject: [PATCH] core: remove persistence boot and set recovery as a default workflow --- core/src/apps/homescreen/__init__.py | 9 +++-- .../management/recovery_device/__init__.py | 12 +++---- .../management/recovery_device/homescreen.py | 12 +++---- core/src/main.py | 34 ++++++------------- core/src/trezor/workflow.py | 18 ++++++++-- 5 files changed, 39 insertions(+), 46 deletions(-) diff --git a/core/src/apps/homescreen/__init__.py b/core/src/apps/homescreen/__init__.py index 8c8c44e28a..ce296c7608 100644 --- a/core/src/apps/homescreen/__init__.py +++ b/core/src/apps/homescreen/__init__.py @@ -104,10 +104,9 @@ async def handle_Ping(ctx: wire.Context, msg: Ping) -> Success: return Success(message=msg.message) -def boot(features_only: bool = False) -> None: +def boot() -> None: register(MessageType.Initialize, handle_Initialize) register(MessageType.GetFeatures, handle_GetFeatures) - if not features_only: - register(MessageType.Cancel, handle_Cancel) - register(MessageType.ClearSession, handle_ClearSession) - register(MessageType.Ping, handle_Ping) + register(MessageType.Cancel, handle_Cancel) + register(MessageType.ClearSession, handle_ClearSession) + register(MessageType.Ping, handle_Ping) diff --git a/core/src/apps/management/recovery_device/__init__.py b/core/src/apps/management/recovery_device/__init__.py index fc77769cdd..8b59c5972a 100644 --- a/core/src/apps/management/recovery_device/__init__.py +++ b/core/src/apps/management/recovery_device/__init__.py @@ -27,6 +27,9 @@ async def recovery_device(ctx: wire.Context, msg: RecoveryDevice) -> Success: """ _check_state(msg) + if storage_recovery.is_in_progress(): + return await recovery_process(ctx) + await _continue_dialog(ctx, msg) # for dry run pin needs to be entered @@ -52,9 +55,7 @@ async def recovery_device(ctx: wire.Context, msg: RecoveryDevice) -> Success: if msg.dry_run: storage_recovery.set_dry_run(msg.dry_run) - result = await recovery_process(ctx) - - return result + return await recovery_process(ctx) def _check_state(msg: RecoveryDevice) -> None: @@ -63,11 +64,6 @@ def _check_state(msg: RecoveryDevice) -> None: if msg.dry_run and not storage.is_initialized(): raise wire.NotInitialized("Device is not initialized") - if storage_recovery.is_in_progress(): - raise RuntimeError( - "Function recovery_device should not be invoked when recovery is already in progress" - ) - if msg.enforce_wordlist is False: raise wire.ProcessError( "Value enforce_wordlist must be True, Trezor Core enforces words automatically." diff --git a/core/src/apps/management/recovery_device/homescreen.py b/core/src/apps/management/recovery_device/homescreen.py index c48a9a4bd3..d5500dc12b 100644 --- a/core/src/apps/management/recovery_device/homescreen.py +++ b/core/src/apps/management/recovery_device/homescreen.py @@ -1,4 +1,4 @@ -from trezor import loop, utils, wire +from trezor import utils, wire, workflow from trezor.crypto import slip39 from trezor.crypto.hashlib import sha256 from trezor.errors import MnemonicError @@ -14,6 +14,7 @@ from apps.common.storage import ( recovery as storage_recovery, recovery_shares as storage_recovery_shares, ) +from apps.homescreen.homescreen import homescreen from apps.management import backup_types from apps.management.recovery_device import layout @@ -25,13 +26,7 @@ if False: async def recovery_homescreen() -> None: # recovery process does not communicate on the wire ctx = wire.DummyContext() - try: - await recovery_process(ctx) - finally: - # clear the loop state, so loop.run will exit - loop.clear() - # clear the registered wire handlers to avoid conflicts - wire.clear() + await recovery_process(ctx) async def recovery_process(ctx: wire.GenericContext) -> Success: @@ -43,6 +38,7 @@ async def recovery_process(ctx: wire.GenericContext) -> Success: storage_recovery.end_progress() else: storage.wipe() + workflow.replace_default(homescreen) raise wire.ActionCancelled("Cancelled") return result diff --git a/core/src/main.py b/core/src/main.py index 1f13f8ac89..55e312125e 100644 --- a/core/src/main.py +++ b/core/src/main.py @@ -15,21 +15,7 @@ usb.bus.open() utils.set_mode_unprivileged() -def _boot_recovery() -> None: - # load applications - import apps.homescreen - - # boot applications - apps.homescreen.boot(features_only=True) - if __debug__: - apps.debug.boot() - - from apps.management.recovery_device.homescreen import recovery_homescreen - - loop.schedule(recovery_homescreen()) - - -def _boot_default() -> None: +def _boot_apps() -> None: # load applications import apps.homescreen import apps.management @@ -71,13 +57,19 @@ def _boot_default() -> None: apps.debug.boot() # run main event loop and specify which screen is the default - from apps.homescreen.homescreen import homescreen + from apps.common.storage import recovery - workflow.start_default(homescreen) + if recovery.is_in_progress(): + from apps.management.recovery_device.homescreen import recovery_homescreen + + workflow.start_default(recovery_homescreen) + else: + from apps.homescreen.homescreen import homescreen + + workflow.start_default(homescreen) from trezor import loop, wire, workflow -from apps.common.storage import recovery while True: # initialize the wire codec @@ -85,11 +77,7 @@ while True: if __debug__: wire.setup(usb.iface_debug) - # boot either in recovery or default mode - if recovery.is_in_progress(): - _boot_recovery() - else: - _boot_default() + _boot_apps() loop.run() # loop is empty, reboot diff --git a/core/src/trezor/workflow.py b/core/src/trezor/workflow.py index df7d0e97d8..4cb28195f9 100644 --- a/core/src/trezor/workflow.py +++ b/core/src/trezor/workflow.py @@ -57,7 +57,7 @@ def start_default(constructor: Callable[[], loop.Task]) -> None: default_constructor = constructor default_task = constructor() if __debug__: - log.debug(__name__, "start default") + log.debug(__name__, "start default: %s", default_task) # Schedule the default task. Because the task can complete on its own, # we need to reset the `default_task` global in a finalizer. loop.schedule(default_task, None, None, _finalize_default) @@ -66,6 +66,20 @@ def start_default(constructor: Callable[[], loop.Task]) -> None: log.debug(__name__, "default already started") +def replace_default(constructor: Callable[[], loop.Task]) -> None: + global default_task + + if __debug__: + if default_task is None: + log.debug(__name__, "replacing default: default not running") + else: + log.debug(__name__, "replacing default: %s", default_task) + + if default_task is not None: + loop.finalize(default_task, None) # TODO: why not close_default() + start_default(constructor) + + def close_default() -> None: """Explicitly close the default workflow task.""" if default_task: @@ -80,7 +94,7 @@ def _finalize_default(task: loop.Task, value: Any) -> None: if default_task is task: if __debug__: - log.debug(__name__, "default closed") + log.debug(__name__, "default closed: %s", task) default_task = None else: if __debug__: