chore(core): rename recovery type & kind and tweak feature flags

pull/3890/head
Ioan Bizău 4 weeks ago committed by Ioan Bizău
parent 49daeaa746
commit 8870869f93

@ -81,7 +81,7 @@ message Features {
optional bool unlocked = 16; // is the device unlocked? called "pin_cached" previously
optional bool _passphrase_cached = 17 [deprecated=true]; // is passphrase already cached in session?
optional bool firmware_present = 18; // is valid firmware loaded?
optional bool needs_backup = 19; // does storage need backup? (equals to Storage.needs_backup)
optional BackupAvailability backup_availability = 19; // does storage need backup? is repeated backup unlocked?
optional uint32 flags = 20; // device flags (equals to Storage.flags)
optional string model = 21; // device hardware model
optional uint32 fw_major = 22; // reported firmware version if in bootloader mode
@ -107,20 +107,29 @@ message Features {
optional HomescreenFormat homescreen_format = 42; // format of the homescreen, 1 = TOIf, 2 = jpg, 3 = TOIG
optional bool hide_passphrase_from_host = 43; // should we hide the passphrase when it comes from host?
optional string internal_model = 44; // internal model name
optional uint32 unit_color = 45; // color of the unit/device
optional bool unit_btconly = 46; // unit/device is intended as bitcoin only
optional uint32 homescreen_width = 47; // homescreen width in pixels
optional uint32 homescreen_height = 48; // homescreen height in pixels
optional uint32 unit_color = 45; // color of the unit/device
optional bool unit_btconly = 46; // unit/device is intended as bitcoin only
optional uint32 homescreen_width = 47; // homescreen width in pixels
optional uint32 homescreen_height = 48; // homescreen height in pixels
optional bool bootloader_locked = 49; // bootloader is locked
optional bool language_version_matches = 50 [default=true]; // translation blob version matches firmware version
optional uint32 unit_packaging = 51; // unit/device packaging version
optional bool haptic_feedback = 52; // haptic feedback is enabled
optional RecoveryType recovery_type = 53; // what type of recovery we are in. NB: this works in conjunction with recovery_status
enum BackupAvailability {
/// Device is already backed up, or a previous backup has failed.
NotAvailable = 0;
/// Device is not backed up. Backup is required.
Required = 1;
/// Device is already backed up and can be backed up again.
Available = 2;
}
enum RecoveryStatus {
NoRecovery = 0;
InNormalRecovery = 1;
InDryRunRecovery = 2;
InUnlockRepeatedBackupRecovery = 3;
Nothing = 0; // we are not in recovery mode
Recovery = 1; // we are in "Normal" or "DryRun" recovery
Backup = 2; // we are in repeated backup mode
}
enum Capability {
@ -449,28 +458,28 @@ message RecoveryDevice {
optional string label = 5; // device label
optional bool enforce_wordlist = 6; // enforce BIP-39 wordlist during the process (T1 only)
reserved 7; // unused recovery method
optional RecoveryDeviceType type = 8; // supported recovery type (T1 only)
optional RecoveryDeviceInputMethod input_method = 8; // supported recovery input method (T1 only)
optional uint32 u2f_counter = 9; // U2F counter
optional RecoveryKind kind = 10 [default=NormalRecovery]; // the kind of recovery to perform
optional RecoveryType type = 10 [default=NormalRecovery]; // the type of recovery to perform
/**
* Type of recovery procedure. These should be used as bitmask, e.g.,
* `RecoveryDeviceType_ScrambledWords | RecoveryDeviceType_Matrix`
* `RecoveryDeviceInputMethod_ScrambledWords | RecoveryDeviceInputMethod_Matrix`
* listing every method supported by the host computer.
*
* Note that ScrambledWords must be supported by every implementation
* for backward compatibility; there is no way to not support it.
*/
enum RecoveryDeviceType {
enum RecoveryDeviceInputMethod {
// use powers of two when extending this field
RecoveryDeviceType_ScrambledWords = 0; // words in scrambled order
RecoveryDeviceType_Matrix = 1; // matrix recovery type
ScrambledWords = 0; // words in scrambled order
Matrix = 1; // matrix recovery type
}
}
enum RecoveryKind {
NormalRecovery = 0; // recovery from seedphrase on an uninitialized device
DryRun = 1; // mnemonic validation
UnlockRepeatedBackup = 2; // unlock SLIP-39 repeated backup
}
enum RecoveryType {
NormalRecovery = 0; // recovery from seedphrase on an uninitialized device
DryRun = 1; // mnemonic validation
UnlockRepeatedBackup = 2; // unlock SLIP-39 repeated backup
}
/**

@ -293,7 +293,6 @@ static void _librust_qstrs(void) {
MP_QSTR_joint__title;
MP_QSTR_joint__to_the_total_amount;
MP_QSTR_joint__you_are_contributing;
MP_QSTR_kind;
MP_QSTR_label;
MP_QSTR_language;
MP_QSTR_language__change_to_template;
@ -454,6 +453,7 @@ static void _librust_qstrs(void) {
MP_QSTR_recovery__x_more_shares_needed_template_plural;
MP_QSTR_recovery__x_of_y_entered_template;
MP_QSTR_recovery__you_have_entered;
MP_QSTR_recovery_type;
MP_QSTR_request_bip39;
MP_QSTR_request_complete_repaint;
MP_QSTR_request_number;

@ -1331,7 +1331,7 @@ pub enum TranslatedString {
reset__slip39_checklist_num_groups_x_template = 931, // "Number of groups: {0}"
brightness__title = 932, // "Set brightness"
recovery__title_unlock_repeated_backup = 933, // "Multi-share backup"
recovery__unlock_repeated_backup = 934, // "Do you want to unlock the seed for repeated backup?"
recovery__unlock_repeated_backup = 934, // "Create additional backup?"
recovery__unlock_repeated_backup_verb = 935, // "Unlock backup"
}
@ -2659,7 +2659,7 @@ impl TranslatedString {
Self::reset__slip39_checklist_num_groups_x_template => "Number of groups: {0}",
Self::brightness__title => "Set brightness",
Self::recovery__title_unlock_repeated_backup => "Multi-share backup",
Self::recovery__unlock_repeated_backup => "Do you want to unlock the seed for repeated backup?",
Self::recovery__unlock_repeated_backup => "Create additional backup?",
Self::recovery__unlock_repeated_backup_verb => "Unlock backup",
}
}

@ -228,8 +228,8 @@ impl ComponentMsgObj for super::component::bl_confirm::Confirm<'_> {
}
}
const RECOVERY_KIND_DRY_RUN: u32 = 1;
const RECOVERY_KIND_UNLOCK_REPEATED_BACKUP: u32 = 2;
const RECOVERY_TYPE_DRY_RUN: u32 = 1;
const RECOVERY_TYPE_UNLOCK_REPEATED_BACKUP: u32 = 2;
/// Function to create and call a `ButtonPage` dialog based on paginable content
/// (e.g. `Paragraphs` or `FormattedText`).
@ -1398,7 +1398,7 @@ extern "C" fn new_confirm_recovery(n_args: usize, args: *const Obj, kwargs: *mut
let block = move |_args: &[Obj], kwargs: &Map| {
let description: TString = kwargs.get(Qstr::MP_QSTR_description)?.try_into()?;
let button: TString<'static> = kwargs.get(Qstr::MP_QSTR_button)?.try_into()?;
let kind: u32 = kwargs.get(Qstr::MP_QSTR_kind)?.try_into()?;
let recovery_type: u32 = kwargs.get(Qstr::MP_QSTR_recovery_type)?.try_into()?;
let show_info: bool = kwargs.get(Qstr::MP_QSTR_show_info)?.try_into()?;
let mut paragraphs = ParagraphVecShort::new();
@ -1415,9 +1415,9 @@ extern "C" fn new_confirm_recovery(n_args: usize, args: *const Obj, kwargs: *mut
));
}
let title = match kind {
RECOVERY_KIND_DRY_RUN => TR::recovery__title_dry_run,
RECOVERY_KIND_UNLOCK_REPEATED_BACKUP => TR::recovery__title_unlock_repeated_backup,
let title = match recovery_type {
RECOVERY_TYPE_DRY_RUN => TR::recovery__title_dry_run,
RECOVERY_TYPE_UNLOCK_REPEATED_BACKUP => TR::recovery__title_dry_run,
_ => TR::recovery__title,
};
@ -1968,7 +1968,7 @@ pub static mp_module_trezorui2: Module = obj_module! {
/// title: str, # unused on TR
/// description: str,
/// button: str,
/// kind: int, # RecoveryKind enum, passed as an int
/// recovery_type: RecoveryType,
/// info_button: bool, # unused on TR
/// show_info: bool,
/// ) -> LayoutObj[UiResult]:
@ -1977,7 +1977,7 @@ pub static mp_module_trezorui2: Module = obj_module! {
/// def select_word_count(
/// *,
/// dry_run: bool, # unused on TR
/// recovery_type: RecoveryType, # unused on TR
/// ) -> LayoutObj[int | str]:
/// """Select mnemonic word count from (12, 18, 20, 24, 33)."""
Qstr::MP_QSTR_select_word_count => obj_fn_kw!(0, new_select_word_count).as_obj(),

@ -310,8 +310,8 @@ impl ComponentMsgObj for super::component::bl_confirm::Confirm<'_> {
}
}
const RECOVERY_KIND_DRY_RUN: u32 = 1;
const RECOVERY_KIND_UNLOCK_REPEATED_BACKUP: u32 = 2;
const RECOVERY_TYPE_DRY_RUN: u32 = 1;
const RECOVERY_TYPE_UNLOCK_REPEATED_BACKUP: u32 = 2;
extern "C" fn new_confirm_action(n_args: usize, args: *const Obj, kwargs: *mut Map) -> Obj {
let block = move |_args: &[Obj], kwargs: &Map| {
@ -1368,7 +1368,7 @@ extern "C" fn new_confirm_recovery(n_args: usize, args: *const Obj, kwargs: *mut
let title: TString = kwargs.get(Qstr::MP_QSTR_title)?.try_into()?;
let description: TString = kwargs.get(Qstr::MP_QSTR_description)?.try_into()?;
let button: TString = kwargs.get(Qstr::MP_QSTR_button)?.try_into()?;
let kind: u32 = kwargs.get(Qstr::MP_QSTR_kind)?.try_into()?;
let recovery_type: u32 = kwargs.get(Qstr::MP_QSTR_recovery_type)?.try_into()?;
let info_button: bool = kwargs.get_or(Qstr::MP_QSTR_info_button, false)?;
let paragraphs = Paragraphs::new([
@ -1377,11 +1377,9 @@ extern "C" fn new_confirm_recovery(n_args: usize, args: *const Obj, kwargs: *mut
])
.with_spacing(theme::RECOVERY_SPACING);
let notification = match kind {
RECOVERY_KIND_DRY_RUN => TR::recovery__title_dry_run.into(),
RECOVERY_KIND_UNLOCK_REPEATED_BACKUP => {
TR::recovery__title_unlock_repeated_backup.into()
}
let notification = match recovery_type {
RECOVERY_TYPE_DRY_RUN => TR::recovery__title_dry_run.into(),
RECOVERY_TYPE_UNLOCK_REPEATED_BACKUP => TR::recovery__title_dry_run.into(),
_ => TR::recovery__title.into(),
};
@ -1411,11 +1409,11 @@ extern "C" fn new_confirm_recovery(n_args: usize, args: *const Obj, kwargs: *mut
extern "C" fn new_select_word_count(n_args: usize, args: *const Obj, kwargs: *mut Map) -> Obj {
let block = move |_args: &[Obj], kwargs: &Map| {
let dry_run: bool = kwargs.get(Qstr::MP_QSTR_dry_run)?.try_into()?;
let title: TString = if dry_run {
TR::recovery__title_dry_run.into()
} else {
TR::recovery__title.into()
let recovery_type: u32 = kwargs.get(Qstr::MP_QSTR_recovery_type)?.try_into()?;
let title: TString = match recovery_type {
RECOVERY_TYPE_DRY_RUN => TR::recovery__title_dry_run.into(),
RECOVERY_TYPE_UNLOCK_REPEATED_BACKUP => TR::recovery__title_dry_run.into(),
_ => TR::recovery__title.into(),
};
let paragraphs = Paragraphs::new(Paragraph::new(
@ -2047,7 +2045,7 @@ pub static mp_module_trezorui2: Module = obj_module! {
/// title: str,
/// description: str,
/// button: str,
/// kind: int, # RecoveryKind enum, passed as an int
/// recovery_type: RecoveryType,
/// info_button: bool = False,
/// ) -> LayoutObj[UiResult]:
/// """Device recovery homescreen."""
@ -2055,7 +2053,7 @@ pub static mp_module_trezorui2: Module = obj_module! {
/// def select_word_count(
/// *,
/// dry_run: bool,
/// recovery_type: RecoveryType,
/// ) -> LayoutObj[int | str]: # TT returns int
/// """Select mnemonic word count from (12, 18, 20, 24, 33)."""
Qstr::MP_QSTR_select_word_count => obj_fn_kw!(0, new_select_word_count).as_obj(),

@ -980,7 +980,7 @@ def confirm_recovery(
title: str, # unused on TR
description: str,
button: str,
kind: int, # RecoveryKind enum, passed as an int
recovery_type: RecoveryType,
info_button: bool, # unused on TR
show_info: bool,
) -> LayoutObj[UiResult]:
@ -990,7 +990,7 @@ def confirm_recovery(
# rust/src/ui/model_tr/layout.rs
def select_word_count(
*,
dry_run: bool, # unused on TR
recovery_type: RecoveryType, # unused on TR
) -> LayoutObj[int | str]:
"""Select mnemonic word count from (12, 18, 20, 24, 33)."""
@ -1515,7 +1515,7 @@ def confirm_recovery(
title: str,
description: str,
button: str,
kind: int, # RecoveryKind enum, passed as an int
recovery_type: RecoveryType,
info_button: bool = False,
) -> LayoutObj[UiResult]:
"""Device recovery homescreen."""
@ -1524,7 +1524,7 @@ def confirm_recovery(
# rust/src/ui/model_tt/layout.rs
def select_word_count(
*,
dry_run: bool,
recovery_type: RecoveryType,
) -> LayoutObj[int | str]: # TT returns int
"""Select mnemonic word count from (12, 18, 20, 24, 33)."""

@ -585,7 +585,7 @@ class TR:
recovery__title_remaining_shares: str = "Remaining shares"
recovery__title_unlock_repeated_backup: str = "Multi-share backup"
recovery__type_word_x_of_y_template: str = "Type word {0} of {1}"
recovery__unlock_repeated_backup: str = "Do you want to unlock the seed for repeated backup?"
recovery__unlock_repeated_backup: str = "Create additional backup?"
recovery__unlock_repeated_backup_verb: str = "Unlock backup"
recovery__wallet_recovered: str = "Wallet recovery completed"
recovery__wanna_cancel_dry_run: str = "Are you sure you want to cancel the backup check?"

@ -91,6 +91,8 @@ trezor.crypto.slip39
import trezor.crypto.slip39
trezor.enums.AmountUnit
import trezor.enums.AmountUnit
trezor.enums.BackupAvailability
import trezor.enums.BackupAvailability
trezor.enums.BackupType
import trezor.enums.BackupType
trezor.enums.BootCommand
@ -119,12 +121,12 @@ trezor.enums.OutputScriptType
import trezor.enums.OutputScriptType
trezor.enums.PinMatrixRequestType
import trezor.enums.PinMatrixRequestType
trezor.enums.RecoveryDeviceType
import trezor.enums.RecoveryDeviceType
trezor.enums.RecoveryKind
import trezor.enums.RecoveryKind
trezor.enums.RecoveryDeviceInputMethod
import trezor.enums.RecoveryDeviceInputMethod
trezor.enums.RecoveryStatus
import trezor.enums.RecoveryStatus
trezor.enums.RecoveryType
import trezor.enums.RecoveryType
trezor.enums.RequestType
import trezor.enums.RequestType
trezor.enums.SafetyCheckLevel

@ -61,11 +61,11 @@ def _language_version_matches() -> bool | None:
def get_features() -> Features:
import storage.recovery as storage_recovery
from trezor import translations
from trezor.enums import Capability, RecoveryKind, RecoveryStatus
from trezor.enums import BackupAvailability, Capability, RecoveryStatus
from trezor.messages import Features
from trezor.ui import HEIGHT, WIDTH
from apps.common import mnemonic, safety_checks
from apps.common import backup, mnemonic, safety_checks
v_major, v_minor, v_patch, _v_build = utils.VERSION
@ -157,20 +157,22 @@ def get_features() -> Features:
if config.is_unlocked():
# passphrase_protection is private, see #1807
f.passphrase_protection = storage_device.is_passphrase_enabled()
f.needs_backup = storage_device.needs_backup()
if storage_device.needs_backup():
f.backup_availability = BackupAvailability.Required
elif backup.repeated_backup_enabled():
f.backup_availability = BackupAvailability.Available
else:
f.backup_availability = BackupAvailability.NotAvailable
f.unfinished_backup = storage_device.unfinished_backup()
f.no_backup = storage_device.no_backup()
f.flags = storage_device.get_flags()
if storage_recovery.is_in_progress():
kind = storage_recovery.get_kind()
if kind == RecoveryKind.NormalRecovery:
f.recovery_status = RecoveryStatus.InNormalRecovery
elif kind == RecoveryKind.DryRun:
f.recovery_status = RecoveryStatus.InDryRunRecovery
elif kind == RecoveryKind.UnlockRepeatedBackup:
f.recovery_status = RecoveryStatus.InUnlockRepeatedBackupRecovery
f.recovery_status = RecoveryStatus.Recovery
f.recovery_type = storage_recovery.get_type()
elif backup.repeated_backup_enabled():
f.recovery_status = RecoveryStatus.Backup
else:
f.recovery_status = RecoveryStatus.NoRecovery
f.recovery_status = RecoveryStatus.Nothing
f.backup_type = mnemonic.get_type()
# Only some models are capable of SD card
@ -417,7 +419,7 @@ async def unlock_device() -> None:
_SCREENSAVER_IS_ON = False
set_homescreen()
wire.filters.remove(_pinlock_filter)
wire.remove_filter(_pinlock_filter)
def _pinlock_filter(msg_type: int, prev_handler: Handler[Msg]) -> Handler[Msg]:
@ -431,30 +433,6 @@ def _pinlock_filter(msg_type: int, prev_handler: Handler[Msg]) -> Handler[Msg]:
return wrapper
_ALLOW_WHILE_REPEATED_BACKUP_UNLOCKED = (
MessageType.Initialize,
MessageType.GetFeatures,
MessageType.EndSession,
MessageType.BackupDevice,
MessageType.WipeDevice,
MessageType.Cancel,
)
def _repeated_backup_filter(msg_type: int, prev_handler: Handler[Msg]) -> Handler[Msg]:
if msg_type in _ALLOW_WHILE_REPEATED_BACKUP_UNLOCKED:
return prev_handler
else:
raise wire.ProcessError("Operation not allowed when in repeated backup state")
def remove_repeated_backup_filter():
try:
wire.filters.remove(_repeated_backup_filter)
except ValueError:
pass
# this function is also called when handling ApplySettings
def reload_settings_from_storage() -> None:
from trezor import ui
@ -469,6 +447,8 @@ def reload_settings_from_storage() -> None:
def boot() -> None:
from apps.common import backup
MT = MessageType # local_cache_global
# Register workflow handlers
@ -488,8 +468,8 @@ def boot() -> None:
reload_settings_from_storage()
if storage_cache.get_bool(storage_cache.APP_RECOVERY_REPEATED_BACKUP_UNLOCKED):
wire.filters.append(_repeated_backup_filter)
if backup.repeated_backup_enabled():
backup.activate_repeated_backup()
if not config.is_unlocked():
# pinlocked handler should always be the last one
wire.filters.append(_pinlock_filter)

@ -1,7 +1,39 @@
from typing import TYPE_CHECKING
def disable_repeated_backup():
import storage.cache as storage_cache
from apps import base
import storage.cache as storage_cache
from trezor import wire
from trezor.enums import MessageType
if TYPE_CHECKING:
from trezor.wire import Handler, Msg
def repeated_backup_enabled() -> bool:
return storage_cache.get_bool(storage_cache.APP_RECOVERY_REPEATED_BACKUP_UNLOCKED)
def activate_repeated_backup():
storage_cache.set_bool(storage_cache.APP_RECOVERY_REPEATED_BACKUP_UNLOCKED, True)
wire.filters.append(_repeated_backup_filter)
def deactivate_repeated_backup():
storage_cache.delete(storage_cache.APP_RECOVERY_REPEATED_BACKUP_UNLOCKED)
base.remove_repeated_backup_filter()
wire.remove_filter(_repeated_backup_filter)
_ALLOW_WHILE_REPEATED_BACKUP_UNLOCKED = (
MessageType.Initialize,
MessageType.GetFeatures,
MessageType.EndSession,
MessageType.BackupDevice,
MessageType.WipeDevice,
MessageType.Cancel,
)
def _repeated_backup_filter(msg_type: int, prev_handler: Handler[Msg]) -> Handler[Msg]:
if msg_type in _ALLOW_WHILE_REPEATED_BACKUP_UNLOCKED:
return prev_handler
else:
raise wire.ProcessError("Operation not allowed when in repeated backup state")

@ -10,7 +10,6 @@ BAK_T_BIP39 = BackupType.Bip39 # global_import_cache
async def backup_device(msg: BackupDevice) -> Success:
import storage.cache as storage_cache
import storage.device as storage_device
from trezor import wire
from trezor.messages import Success
@ -21,13 +20,11 @@ async def backup_device(msg: BackupDevice) -> Success:
# do this early before we show any UI
# the homescreen will clear the flag right after its own UI is gone
repeated_backup_unlocked = storage_cache.get_bool(
storage_cache.APP_RECOVERY_REPEATED_BACKUP_UNLOCKED
)
repeated_backup_enabled = backup.repeated_backup_enabled()
if not storage_device.is_initialized():
raise wire.NotInitialized("Device is not initialized")
if not storage_device.needs_backup() and not repeated_backup_unlocked:
if not storage_device.needs_backup() and not repeated_backup_enabled:
raise wire.ProcessError("Seed already backed up")
mnemonic_secret, backup_type = mnemonic.get()
@ -47,10 +44,10 @@ async def backup_device(msg: BackupDevice) -> Success:
elif len(groups) > 0:
raise wire.DataError("group_threshold is missing")
if not repeated_backup_unlocked:
if not repeated_backup_enabled:
storage_device.set_unfinished_backup(True)
backup.disable_repeated_backup()
backup.deactivate_repeated_backup()
storage_device.set_backed_up()
if group_threshold is not None:

@ -1,14 +1,14 @@
from typing import TYPE_CHECKING
from trezor.enums import RecoveryKind
from trezor.enums import RecoveryType
if TYPE_CHECKING:
from trezor.messages import RecoveryDevice, Success
# List of RecoveryDevice fields that can be set when doing dry-run recovery.
# All except `kind` are allowed for T1 compatibility, but their values are ignored.
# All except `type` are allowed for T1 compatibility, but their values are ignored.
# If set, `enforce_wordlist` must be True, because we do not support non-enforcing.
DRY_RUN_ALLOWED_FIELDS = ("kind", "word_count", "enforce_wordlist", "type")
DRY_RUN_ALLOWED_FIELDS = ("type", "word_count", "enforce_wordlist", "input_method")
async def recovery_device(msg: RecoveryDevice) -> Success:
@ -34,18 +34,18 @@ async def recovery_device(msg: RecoveryDevice) -> Success:
from .homescreen import recovery_homescreen, recovery_process
recovery_kind = msg.kind # local_cache_attribute
recovery_type = msg.type # local_cache_attribute
# --------------------------------------------------------
# validate
if recovery_kind == RecoveryKind.NormalRecovery:
if recovery_type == RecoveryType.NormalRecovery:
if storage_device.is_initialized():
raise wire.UnexpectedMessage("Already initialized")
elif recovery_kind in (RecoveryKind.DryRun, RecoveryKind.UnlockRepeatedBackup):
elif recovery_type in (RecoveryType.DryRun, RecoveryType.UnlockRepeatedBackup):
if not storage_device.is_initialized():
raise wire.NotInitialized("Device is not initialized")
if (
recovery_kind == RecoveryKind.UnlockRepeatedBackup
recovery_type == RecoveryType.UnlockRepeatedBackup
and mnemonic.get_type() == BackupType.Bip39
):
raise wire.ProcessError("Repeated Backup not available for BIP39 backups")
@ -54,7 +54,7 @@ async def recovery_device(msg: RecoveryDevice) -> Success:
if key not in DRY_RUN_ALLOWED_FIELDS and value is not None:
raise wire.ProcessError(f"Forbidden field set in dry-run: {key}")
else:
raise RuntimeError # Unknown RecoveryKind
raise RuntimeError # Unknown RecoveryType
if msg.enforce_wordlist is False:
raise wire.ProcessError(
@ -66,7 +66,7 @@ async def recovery_device(msg: RecoveryDevice) -> Success:
if storage_recovery.is_in_progress():
return await recovery_process()
if recovery_kind == RecoveryKind.NormalRecovery:
if recovery_type == RecoveryType.NormalRecovery:
await confirm_reset_device(TR.recovery__title_recover, recovery=True)
# wipe storage to make sure the device is in a clear state
@ -85,10 +85,10 @@ async def recovery_device(msg: RecoveryDevice) -> Success:
if msg.label is not None:
storage_device.set_label(msg.label)
elif recovery_kind in (RecoveryKind.DryRun, RecoveryKind.UnlockRepeatedBackup):
elif recovery_type in (RecoveryType.DryRun, RecoveryType.UnlockRepeatedBackup):
title = (
TR.recovery__title_dry_run
if recovery_kind == RecoveryKind.DryRun
if recovery_type == RecoveryType.DryRun
else TR.recovery__title_unlock_repeated_backup
)
await confirm_action(
@ -105,7 +105,7 @@ async def recovery_device(msg: RecoveryDevice) -> Success:
storage_recovery.set_in_progress(True)
storage_recovery.set_kind(int(recovery_kind))
storage_recovery.set_type(int(recovery_type))
workflow.set_default(recovery_homescreen)

@ -1,6 +1,5 @@
from typing import TYPE_CHECKING
import storage.cache as storage_cache
import storage.device as storage_device
import storage.recovery as storage_recovery
import storage.recovery_shares as storage_recovery_shares
@ -12,15 +11,17 @@ from apps.common import backup_types
from . import layout, recover
if TYPE_CHECKING:
from trezor.enums import BackupType, RecoveryKind
from trezor.enums import BackupType, RecoveryType
async def recovery_homescreen() -> None:
from trezor import workflow
from apps.common import backup
from apps.homescreen import homescreen
if storage_cache.get_bool(storage_cache.APP_RECOVERY_REPEATED_BACKUP_UNLOCKED):
if backup.repeated_backup_enabled():
storage_recovery.end_progress()
await _continue_repeated_backup()
elif not storage_recovery.is_in_progress():
workflow.set_default(homescreen)
@ -30,11 +31,11 @@ async def recovery_homescreen() -> None:
async def recovery_process() -> Success:
import storage
from trezor.enums import MessageType, RecoveryKind
from trezor.enums import MessageType, RecoveryType
from apps.common import backup
kind = storage_recovery.get_kind()
recovery_type = storage_recovery.get_type()
wire.AVOID_RESTARTING_FOR = (
MessageType.Initialize,
@ -44,24 +45,18 @@ async def recovery_process() -> Success:
try:
return await _continue_recovery_process()
except recover.RecoveryAborted:
if kind == RecoveryKind.DryRun:
storage_recovery.end_progress()
elif kind == RecoveryKind.UnlockRepeatedBackup:
backup.disable_repeated_backup()
storage_recovery.end_progress()
else:
storage_recovery.end_progress()
backup.deactivate_repeated_backup()
if recovery_type == RecoveryType.NormalRecovery:
storage.wipe()
raise wire.ActionCancelled
async def _continue_repeated_backup() -> None:
from trezor import workflow
from trezor.enums import ButtonRequestType, MessageType
from trezor.ui.layouts import confirm_action
from trezor.wire import ActionCancelled
from apps.common import backup, mnemonic
from apps.homescreen import homescreen
from apps.management.reset_device import backup_seed
wire.AVOID_RESTARTING_FOR = (
@ -84,20 +79,17 @@ async def _continue_repeated_backup() -> None:
raise RuntimeError
await backup_seed(backup_type, mnemonic_secret)
except ActionCancelled:
workflow.set_default(homescreen)
finally:
backup.disable_repeated_backup()
storage_recovery.end_progress()
backup.deactivate_repeated_backup()
async def _continue_recovery_process() -> Success:
from trezor import utils
from trezor.enums import RecoveryKind
from trezor.enums import RecoveryType
from trezor.errors import MnemonicError
# gather the current recovery state from storage
kind = storage_recovery.get_kind()
recovery_type = storage_recovery.get_type()
word_count, backup_type = recover.load_slip39_state()
# Both word_count and backup_type are derived from the same data. Both will be
@ -109,7 +101,7 @@ async def _continue_recovery_process() -> Success:
if not is_first_step:
assert word_count is not None
# If we continue recovery, show starting screen with word count immediately.
await _request_share_first_screen(word_count, kind)
await _request_share_first_screen(word_count, recovery_type)
secret = None
while secret is None:
@ -122,9 +114,9 @@ async def _continue_recovery_process() -> Success:
TR.buttons__continue, TR.recovery__num_of_words
)
# ask for the number of words
word_count = await layout.request_word_count(kind == RecoveryKind.DryRun)
word_count = await layout.request_word_count(recovery_type)
# ...and only then show the starting screen with word count.
await _request_share_first_screen(word_count, kind)
await _request_share_first_screen(word_count, recovery_type)
assert word_count is not None
# ask for mnemonic words one by one
@ -144,9 +136,9 @@ async def _continue_recovery_process() -> Success:
await layout.show_invalid_mnemonic(word_count)
assert backup_type is not None
if kind == RecoveryKind.DryRun:
if recovery_type == RecoveryType.DryRun:
result = await _finish_recovery_dry_run(secret, backup_type)
elif kind == RecoveryKind.UnlockRepeatedBackup:
elif recovery_type == RecoveryType.UnlockRepeatedBackup:
result = await _finish_recovery_unlock_repeated_backup(secret, backup_type)
else:
result = await _finish_recovery(secret, backup_type)
@ -154,7 +146,9 @@ async def _continue_recovery_process() -> Success:
return result
def _check_secret_against_stored_secret(secret: bytes, is_slip39: bool, backup_type: BackupType) -> bool:
def _check_secret_against_stored_secret(
secret: bytes, is_slip39: bool, backup_type: BackupType
) -> bool:
from trezor import utils
from trezor.crypto.hashlib import sha256
@ -205,7 +199,7 @@ async def _finish_recovery_dry_run(secret: bytes, backup_type: BackupType) -> Su
async def _finish_recovery_unlock_repeated_backup(
secret: bytes, backup_type: BackupType
) -> Success:
import storage.cache as storage_cache
from apps.common import backup
if backup_type is None:
raise RuntimeError
@ -215,9 +209,7 @@ async def _finish_recovery_unlock_repeated_backup(
result = _check_secret_against_stored_secret(secret, is_slip39, backup_type)
if result:
storage_cache.set_bool(
storage_cache.APP_RECOVERY_REPEATED_BACKUP_UNLOCKED, True
)
backup.activate_repeated_backup()
return Success(message="Backup unlocked")
else:
raise wire.ProcessError("The seed does not match the one in the device")
@ -272,15 +264,17 @@ async def _process_words(words: str) -> tuple[bytes | None, BackupType]:
return secret, backup_type
async def _request_share_first_screen(word_count: int, kind: RecoveryKind) -> None:
from trezor.enums import RecoveryKind
async def _request_share_first_screen(
word_count: int, recovery_type: RecoveryType
) -> None:
from trezor.enums import RecoveryType
if backup_types.is_slip39_word_count(word_count):
remaining = storage_recovery.fetch_slip39_remaining_shares()
if remaining:
await _request_share_next_screen()
else:
if kind == RecoveryKind.UnlockRepeatedBackup:
if recovery_type == RecoveryType.UnlockRepeatedBackup:
text = TR.recovery__enter_backup
button_label = TR.buttons__continue
else:

@ -149,23 +149,23 @@ async def homescreen_dialog(
show_info: bool = False,
) -> None:
import storage.recovery as storage_recovery
from trezor.enums import RecoveryKind
from trezor.enums import RecoveryType
from trezor.ui.layouts.recovery import continue_recovery
from trezor.wire import ActionCancelled
from .recover import RecoveryAborted
kind = storage_recovery.get_kind()
recovery_type = storage_recovery.get_type()
while True:
if await continue_recovery(
button_label, text, subtext, info_func, kind, show_info
button_label, text, subtext, info_func, recovery_type, show_info
):
# go forward in the recovery process
break
# user has chosen to abort, confirm the choice
try:
await _confirm_abort(kind != RecoveryKind.NormalRecovery)
await _confirm_abort(recovery_type != RecoveryType.NormalRecovery)
except ActionCancelled:
pass
else:

@ -4,7 +4,7 @@ from typing import TYPE_CHECKING
from storage import common
if TYPE_CHECKING:
from trezor.enums import RecoveryKind
from trezor.enums import RecoveryType
# Namespace:
_NAMESPACE = common.APP_RECOVERY
@ -12,7 +12,7 @@ _NAMESPACE = common.APP_RECOVERY
# fmt: off
# Keys:
_IN_PROGRESS = const(0x00) # bool
_KIND = const(0x01) # int
_TYPE = const(0x01) # int
_SLIP39_IDENTIFIER = const(0x03) # bytes
_REMAINING = const(0x05) # int
_SLIP39_ITERATION_EXPONENT = const(0x06) # int
@ -41,27 +41,27 @@ def is_in_progress() -> bool:
return common.get_bool(_NAMESPACE, _IN_PROGRESS)
def set_kind(val: int) -> None:
def set_type(val: int) -> None:
_require_progress()
common.set_uint8(_NAMESPACE, _KIND, val)
common.set_uint8(_NAMESPACE, _TYPE, val)
def get_kind() -> RecoveryKind:
from trezor.enums import RecoveryKind
def get_type() -> RecoveryType:
from trezor.enums import RecoveryType
_require_progress()
recovery_kind = common.get_uint8(_NAMESPACE, _KIND)
if recovery_kind is None:
recovery_kind = RecoveryKind.NormalRecovery
if recovery_kind not in (
RecoveryKind.NormalRecovery,
RecoveryKind.DryRun,
RecoveryKind.UnlockRepeatedBackup,
recovery_type = common.get_uint8(_NAMESPACE, _TYPE)
if recovery_type is None:
recovery_type = RecoveryType.NormalRecovery
if recovery_type not in (
RecoveryType.NormalRecovery,
RecoveryType.DryRun,
RecoveryType.UnlockRepeatedBackup,
):
# Invalid recovery kind
# Invalid recovery type
raise RuntimeError
return recovery_kind
return recovery_type
def set_slip39_identifier(identifier: int) -> None:
@ -146,7 +146,7 @@ def end_progress() -> None:
_require_progress()
for key in (
_IN_PROGRESS,
_KIND,
_TYPE,
_SLIP39_IDENTIFIER,
_REMAINING,
_SLIP39_ITERATION_EXPONENT,

@ -0,0 +1,7 @@
# Automatically generated by pb2py
# fmt: off
# isort:skip_file
NotAvailable = 0
Required = 1
Available = 2

@ -2,7 +2,6 @@
# fmt: off
# isort:skip_file
NoRecovery = 0
InNormalRecovery = 1
InDryRunRecovery = 2
InUnlockRepeatedBackupRecovery = 3
Nothing = 0
Recovery = 1
Backup = 2

@ -440,11 +440,20 @@ if TYPE_CHECKING:
Jpeg = 2
ToiG = 3
class RecoveryType(IntEnum):
NormalRecovery = 0
DryRun = 1
UnlockRepeatedBackup = 2
class BackupAvailability(IntEnum):
NotAvailable = 0
Required = 1
Available = 2
class RecoveryStatus(IntEnum):
NoRecovery = 0
InNormalRecovery = 1
InDryRunRecovery = 2
InUnlockRepeatedBackupRecovery = 3
Nothing = 0
Recovery = 1
Backup = 2
class Capability(IntEnum):
Bitcoin = 1
@ -474,15 +483,10 @@ if TYPE_CHECKING:
ENABLE = 1
REFRESH = 2
class RecoveryDeviceType(IntEnum):
class RecoveryDeviceInputMethod(IntEnum):
ScrambledWords = 0
Matrix = 1
class RecoveryKind(IntEnum):
NormalRecovery = 0
DryRun = 1
UnlockRepeatedBackup = 2
class WordRequestType(IntEnum):
Plain = 0
Matrix9 = 1

@ -17,6 +17,7 @@ def __getattr__(name: str) -> Any:
if TYPE_CHECKING:
from typing import TypeGuard
from trezor.enums import AmountUnit # noqa: F401
from trezor.enums import BackupAvailability # noqa: F401
from trezor.enums import BackupType # noqa: F401
from trezor.enums import BinanceOrderSide # noqa: F401
from trezor.enums import BinanceOrderType # noqa: F401
@ -53,9 +54,9 @@ if TYPE_CHECKING:
from trezor.enums import NEMSupplyChangeType # noqa: F401
from trezor.enums import OutputScriptType # noqa: F401
from trezor.enums import PinMatrixRequestType # noqa: F401
from trezor.enums import RecoveryDeviceType # noqa: F401
from trezor.enums import RecoveryKind # noqa: F401
from trezor.enums import RecoveryDeviceInputMethod # noqa: F401
from trezor.enums import RecoveryStatus # noqa: F401
from trezor.enums import RecoveryType # noqa: F401
from trezor.enums import RequestType # noqa: F401
from trezor.enums import SafetyCheckLevel # noqa: F401
from trezor.enums import SdProtectOperationType # noqa: F401
@ -2133,7 +2134,7 @@ if TYPE_CHECKING:
imported: "bool | None"
unlocked: "bool | None"
firmware_present: "bool | None"
needs_backup: "bool | None"
backup_availability: "BackupAvailability | None"
flags: "int | None"
model: "str | None"
fw_major: "int | None"
@ -2166,6 +2167,7 @@ if TYPE_CHECKING:
language_version_matches: "bool"
unit_packaging: "int | None"
haptic_feedback: "bool | None"
recovery_type: "RecoveryType | None"
def __init__(
self,
@ -2187,7 +2189,7 @@ if TYPE_CHECKING:
imported: "bool | None" = None,
unlocked: "bool | None" = None,
firmware_present: "bool | None" = None,
needs_backup: "bool | None" = None,
backup_availability: "BackupAvailability | None" = None,
flags: "int | None" = None,
model: "str | None" = None,
fw_major: "int | None" = None,
@ -2219,6 +2221,7 @@ if TYPE_CHECKING:
language_version_matches: "bool | None" = None,
unit_packaging: "int | None" = None,
haptic_feedback: "bool | None" = None,
recovery_type: "RecoveryType | None" = None,
) -> None:
pass
@ -2600,9 +2603,9 @@ if TYPE_CHECKING:
pin_protection: "bool | None"
label: "str | None"
enforce_wordlist: "bool | None"
type: "RecoveryDeviceType | None"
input_method: "RecoveryDeviceInputMethod | None"
u2f_counter: "int | None"
kind: "RecoveryKind"
type: "RecoveryType"
def __init__(
self,
@ -2612,9 +2615,9 @@ if TYPE_CHECKING:
pin_protection: "bool | None" = None,
label: "str | None" = None,
enforce_wordlist: "bool | None" = None,
type: "RecoveryDeviceType | None" = None,
input_method: "RecoveryDeviceInputMethod | None" = None,
u2f_counter: "int | None" = None,
kind: "RecoveryKind | None" = None,
type: "RecoveryType | None" = None,
) -> None:
pass

@ -2,15 +2,15 @@ from typing import Callable, Iterable
import trezorui2
from trezor import TR
from trezor.enums import ButtonRequestType, RecoveryKind
from trezor.enums import ButtonRequestType, RecoveryType
from ..common import interact
from . import RustLayout, raise_if_not_confirmed, show_warning
async def request_word_count(dry_run: bool) -> int:
async def request_word_count(recovery_type: RecoveryType) -> int:
count = await interact(
RustLayout(trezorui2.select_word_count(dry_run=dry_run)),
RustLayout(trezorui2.select_word_count(recovery_type=recovery_type)),
"word_count",
ButtonRequestType.MnemonicWordCount,
)
@ -76,7 +76,7 @@ async def continue_recovery(
text: str,
subtext: str | None,
info_func: Callable | None,
kind: RecoveryKind,
recovery_type: RecoveryType,
show_info: bool = False,
) -> bool:
# TODO: implement info_func?
@ -84,7 +84,7 @@ async def continue_recovery(
# (and having middle button would mean shortening the right button text)
# Never showing info for dry-run, user already saw it and it is disturbing
if kind in (RecoveryKind.DryRun, RecoveryKind.UnlockRepeatedBackup):
if recovery_type in (RecoveryType.DryRun, RecoveryType.UnlockRepeatedBackup):
show_info = False
if subtext:
@ -95,7 +95,7 @@ async def continue_recovery(
title="",
description=text,
button=button_label,
kind=kind,
recovery_type=recovery_type,
info_button=False,
show_info=show_info, # type: ignore [No parameter named "show_info"]
)

@ -2,7 +2,7 @@ from typing import Callable, Iterable
import trezorui2
from trezor import TR
from trezor.enums import ButtonRequestType, RecoveryKind
from trezor.enums import ButtonRequestType, RecoveryType
from ..common import interact
from . import RustLayout, raise_if_not_confirmed
@ -25,8 +25,8 @@ async def _is_confirmed_info(
return result is CONFIRMED
async def request_word_count(dry_run: bool) -> int:
selector = RustLayout(trezorui2.select_word_count(dry_run=dry_run))
async def request_word_count(recovery_type: RecoveryType) -> int:
selector = RustLayout(trezorui2.select_word_count(recovery_type=recovery_type))
count = await interact(selector, "word_count", ButtonRequestType.MnemonicWordCount)
return int(count)
@ -116,7 +116,7 @@ async def continue_recovery(
text: str,
subtext: str | None,
info_func: Callable | None,
kind: RecoveryKind,
recovery_type: RecoveryType,
show_info: bool = False, # unused on TT
) -> bool:
from ..common import button_request
@ -132,7 +132,7 @@ async def continue_recovery(
title=text,
description=description,
button=button_label,
kind=kind,
recovery_type=recovery_type,
info_button=info_func is not None,
)
)

@ -31,7 +31,7 @@ from trezor import log, loop, protobuf, utils, workflow
from trezor.enums import FailureType
from trezor.messages import Failure
from trezor.wire import codec_v1, context
from trezor.wire.errors import ActionCancelled, DataError, Error
from trezor.wire.errors import ActionCancelled, DataError, Error, UnexpectedMessage
# Import all errors into namespace, so that `wire.Error` is available from
# other packages.
@ -261,11 +261,12 @@ async def handle_session(
def find_handler(iface: WireInterface, msg_type: int) -> Handler:
import usb
from apps import workflow_handlers
handler = workflow_handlers.find_registered_handler(iface, msg_type)
if handler is None:
raise context.UnexpectedMessage(msg="Unexpected message")
raise UnexpectedMessage("Unexpected message")
if __debug__ and iface is usb.iface_debug:
# no filtering allowed for debuglink
@ -297,8 +298,21 @@ filter "wins" and the latest behavior triggers first.
Please note that this behavior is really unsuited to anything other than what we are
using it for now. It might be necessary to modify the semantics if we need more complex
usecases.
NB: `filters` is currently public so callers can have control over where they insert
new filters, but removal should be done using `remove_filter`!
We should, however, change it such that filters must be added using an `add_filter`
and `filters` becomes private!
"""
def remove_filter(filter):
try:
filters.remove(filter)
except ValueError:
pass
AVOID_RESTARTING_FOR: Container[int] = ()

@ -589,7 +589,7 @@
"recovery__title_remaining_shares": "Remaining shares",
"recovery__title_unlock_repeated_backup": "Multi-share backup",
"recovery__type_word_x_of_y_template": "Type word {0} of {1}",
"recovery__unlock_repeated_backup": "Do you want to unlock the seed for repeated backup?",
"recovery__unlock_repeated_backup": "Create additional backup?",
"recovery__unlock_repeated_backup_verb": "Unlock backup",
"recovery__wallet_recovered": "Wallet recovery completed",
"recovery__wanna_cancel_dry_run": "Are you sure you want to cancel the backup check?",

@ -60,8 +60,11 @@ bool get_features(Features *resp) {
resp->has_imported = config_getImported(&(resp->imported));
resp->has_unlocked = true;
resp->unlocked = session_isUnlocked();
resp->has_needs_backup = true;
config_getNeedsBackup(&(resp->needs_backup));
resp->has_backup_availability = true;
bool needs_backup = false;
config_getNeedsBackup(&needs_backup);
resp->backup_availability = needs_backup ? BackupAvailability_Required
: BackupAvailability_NotAvailable;
resp->has_unfinished_backup = true;
config_getUnfinishedBackup(&(resp->unfinished_backup));
resp->has_no_backup = true;
@ -491,11 +494,11 @@ void fsm_msgApplyFlags(const ApplyFlags *msg) {
void fsm_msgRecoveryDevice(const RecoveryDevice *msg) {
CHECK_PIN_UNCACHED
CHECK_PARAM(!msg->has_kind || msg->kind == RecoveryKind_NormalRecovery ||
msg->kind == RecoveryKind_DryRun,
CHECK_PARAM(msg->type == RecoveryType_NormalRecovery ||
msg->type == RecoveryType_DryRun,
_("UnlockRepeatedBackup not supported"))
const bool dry_run = msg->has_kind ? msg->kind == RecoveryKind_DryRun : false;
const bool dry_run = msg->has_type ? msg->type == RecoveryType_DryRun : false;
if (!dry_run) {
CHECK_NOT_INITIALIZED
} else {
@ -516,7 +519,7 @@ void fsm_msgRecoveryDevice(const RecoveryDevice *msg) {
msg->has_language ? msg->language : 0,
msg->has_label ? msg->label : 0,
msg->has_enforce_wordlist && msg->enforce_wordlist,
msg->has_type ? msg->type : 0,
msg->has_input_method ? msg->input_method : 0,
msg->has_u2f_counter ? msg->u2f_counter : 0, dry_run);
}

@ -474,8 +474,8 @@ void next_word(void) {
void recovery_init(uint32_t _word_count, bool passphrase_protection,
bool pin_protection, const char *language, const char *label,
bool _enforce_wordlist, uint32_t type, uint32_t u2f_counter,
bool _dry_run) {
bool _enforce_wordlist, uint32_t input_method,
uint32_t u2f_counter, bool _dry_run) {
if (_word_count != 12 && _word_count != 18 && _word_count != 24) return;
recovery_mode = RECOVERY_NONE;
@ -510,7 +510,7 @@ void recovery_init(uint32_t _word_count, bool passphrase_protection,
}
// Prefer matrix recovery if the host supports it.
if ((type & RecoveryDeviceType_RecoveryDeviceType_Matrix) != 0) {
if ((input_method & RecoveryDeviceInputMethod_Matrix) != 0) {
recovery_mode = RECOVERY_MATRIX;
next_matrix();
} else {

@ -25,8 +25,8 @@
void recovery_init(uint32_t _word_count, bool passphrase_protection,
bool pin_protection, const char *language, const char *label,
bool _enforce_wordlist, uint32_t type, uint32_t u2f_counter,
bool _dry_run);
bool _enforce_wordlist, uint32_t input_method,
uint32_t u2f_counter, bool _dry_run);
void recovery_word(const char *word);
void recovery_abort(void);
const char *recovery_get_fake_word(void);

@ -28,9 +28,9 @@ if TYPE_CHECKING:
from ..protobuf import MessageType
from . import TrezorConnection
RECOVERY_TYPE = {
"scrambled": messages.RecoveryDeviceType.ScrambledWords,
"matrix": messages.RecoveryDeviceType.Matrix,
RECOVERY_DEVICE_INPUT_METHOD = {
"scrambled": messages.RecoveryDeviceInputMethod.ScrambledWords,
"matrix": messages.RecoveryDeviceInputMethod.Matrix,
}
BACKUP_TYPE = {
@ -148,7 +148,12 @@ def load(
@click.option("-l", "--label")
@click.option("-u", "--u2f-counter", default=None, type=int)
@click.option(
"-t", "--type", "rec_type", type=ChoiceType(RECOVERY_TYPE), default="scrambled"
"-i",
"--input_method",
"-t",
"--type",
type=ChoiceType(RECOVERY_DEVICE_INPUT_METHOD),
default="scrambled",
)
@click.option("-d", "--dry-run", is_flag=True)
@click.option("-b", "--unlock-repeated-backup", is_flag=True)
@ -161,12 +166,12 @@ def recover(
passphrase_protection: bool,
label: Optional[str],
u2f_counter: int,
rec_type: messages.RecoveryDeviceType,
input_method: messages.RecoveryDeviceInputMethod,
dry_run: bool,
unlock_repeated_backup: bool,
) -> "MessageType":
"""Start safe recovery workflow."""
if rec_type == messages.RecoveryDeviceType.ScrambledWords:
if input_method == messages.RecoveryDeviceInputMethod.ScrambledWords:
input_callback = ui.mnemonic_words(expand)
else:
input_callback = ui.matrix_words
@ -175,11 +180,11 @@ def recover(
if dry_run and unlock_repeated_backup:
raise click.ClickException("Cannot use -d and -b together.")
recovery_kind = None
type = None
if dry_run:
recovery_kind = messages.RecoveryKind.DryRun
type = messages.RecoveryType.DryRun
if unlock_repeated_backup:
recovery_kind = messages.RecoveryKind.UnlockRepeatedBackup
type = messages.RecoveryType.UnlockRepeatedBackup
return device.recover(
client,
@ -189,8 +194,8 @@ def recover(
label=label,
u2f_counter=u2f_counter,
input_callback=input_callback,
type=rec_type,
recovery_kind=recovery_kind,
input_method=input_method,
type=type,
)

@ -159,11 +159,11 @@ def recover(
label: Optional[str] = None,
language: Optional[str] = None,
input_callback: Optional[Callable] = None,
type: messages.RecoveryDeviceType = messages.RecoveryDeviceType.ScrambledWords,
input_method: messages.RecoveryDeviceInputMethod = messages.RecoveryDeviceInputMethod.ScrambledWords,
dry_run: Optional[bool] = None,
u2f_counter: Optional[int] = None,
*,
recovery_kind: Optional[messages.RecoveryKind] = None,
type: Optional[messages.RecoveryType] = None,
) -> "MessageType":
if language is not None:
warnings.warn(
@ -173,21 +173,19 @@ def recover(
if dry_run is not None:
warnings.warn(
"Use recovery_kind=RecoveryKind.DryRun instead!",
"Use type=RecoveryType.DryRun instead!",
DeprecationWarning,
)
if recovery_kind is not None:
raise ValueError(
"Cannot use both dry_run and recovery_kind simultaneously."
)
if type is not None:
raise ValueError("Cannot use both dry_run and type simultaneously.")
elif dry_run:
recovery_kind = messages.RecoveryKind.DryRun
type = messages.RecoveryType.DryRun
else:
recovery_kind = messages.RecoveryKind.NormalRecovery
type = messages.RecoveryType.NormalRecovery
if recovery_kind is None:
recovery_kind = messages.RecoveryKind.NormalRecovery
if type is None:
type = messages.RecoveryType.NormalRecovery
if client.features.model == "1" and input_callback is None:
raise RuntimeError("Input callback required for Trezor One")
@ -195,10 +193,7 @@ def recover(
if word_count not in (12, 18, 24):
raise ValueError("Invalid word count. Use 12/18/24")
if (
client.features.initialized
and recovery_kind == messages.RecoveryKind.NormalRecovery
):
if client.features.initialized and type == messages.RecoveryType.NormalRecovery:
raise RuntimeError(
"Device already initialized. Call device.wipe() and try again."
)
@ -207,10 +202,13 @@ def recover(
u2f_counter = int(time.time())
msg = messages.RecoveryDevice(
word_count=word_count, enforce_wordlist=True, type=type, kind=recovery_kind
word_count=word_count,
enforce_wordlist=True,
input_method=input_method,
type=type,
)
if recovery_kind == messages.RecoveryKind.NormalRecovery:
if type == messages.RecoveryType.NormalRecovery:
# set additional parameters
msg.passphrase_protection = passphrase_protection
msg.pin_protection = pin_protection

@ -472,11 +472,22 @@ class HomescreenFormat(IntEnum):
ToiG = 3
class RecoveryType(IntEnum):
NormalRecovery = 0
DryRun = 1
UnlockRepeatedBackup = 2
class BackupAvailability(IntEnum):
NotAvailable = 0
Required = 1
Available = 2
class RecoveryStatus(IntEnum):
NoRecovery = 0
InNormalRecovery = 1
InDryRunRecovery = 2
InUnlockRepeatedBackupRecovery = 3
Nothing = 0
Recovery = 1
Backup = 2
class Capability(IntEnum):
@ -509,17 +520,11 @@ class SdProtectOperationType(IntEnum):
REFRESH = 2
class RecoveryDeviceType(IntEnum):
class RecoveryDeviceInputMethod(IntEnum):
ScrambledWords = 0
Matrix = 1
class RecoveryKind(IntEnum):
NormalRecovery = 0
DryRun = 1
UnlockRepeatedBackup = 2
class WordRequestType(IntEnum):
Plain = 0
Matrix9 = 1
@ -3245,7 +3250,7 @@ class Features(protobuf.MessageType):
16: protobuf.Field("unlocked", "bool", repeated=False, required=False, default=None),
17: protobuf.Field("_passphrase_cached", "bool", repeated=False, required=False, default=None),
18: protobuf.Field("firmware_present", "bool", repeated=False, required=False, default=None),
19: protobuf.Field("needs_backup", "bool", repeated=False, required=False, default=None),
19: protobuf.Field("backup_availability", "BackupAvailability", repeated=False, required=False, default=None),
20: protobuf.Field("flags", "uint32", repeated=False, required=False, default=None),
21: protobuf.Field("model", "string", repeated=False, required=False, default=None),
22: protobuf.Field("fw_major", "uint32", repeated=False, required=False, default=None),
@ -3278,6 +3283,7 @@ class Features(protobuf.MessageType):
50: protobuf.Field("language_version_matches", "bool", repeated=False, required=False, default=True),
51: protobuf.Field("unit_packaging", "uint32", repeated=False, required=False, default=None),
52: protobuf.Field("haptic_feedback", "bool", repeated=False, required=False, default=None),
53: protobuf.Field("recovery_type", "RecoveryType", repeated=False, required=False, default=None),
}
def __init__(
@ -3301,7 +3307,7 @@ class Features(protobuf.MessageType):
unlocked: Optional["bool"] = None,
_passphrase_cached: Optional["bool"] = None,
firmware_present: Optional["bool"] = None,
needs_backup: Optional["bool"] = None,
backup_availability: Optional["BackupAvailability"] = None,
flags: Optional["int"] = None,
model: Optional["str"] = None,
fw_major: Optional["int"] = None,
@ -3333,6 +3339,7 @@ class Features(protobuf.MessageType):
language_version_matches: Optional["bool"] = True,
unit_packaging: Optional["int"] = None,
haptic_feedback: Optional["bool"] = None,
recovery_type: Optional["RecoveryType"] = None,
) -> None:
self.capabilities: Sequence["Capability"] = capabilities if capabilities is not None else []
self.major_version = major_version
@ -3352,7 +3359,7 @@ class Features(protobuf.MessageType):
self.unlocked = unlocked
self._passphrase_cached = _passphrase_cached
self.firmware_present = firmware_present
self.needs_backup = needs_backup
self.backup_availability = backup_availability
self.flags = flags
self.model = model
self.fw_major = fw_major
@ -3384,6 +3391,7 @@ class Features(protobuf.MessageType):
self.language_version_matches = language_version_matches
self.unit_packaging = unit_packaging
self.haptic_feedback = haptic_feedback
self.recovery_type = recovery_type
class LockDevice(protobuf.MessageType):
@ -3794,9 +3802,9 @@ class RecoveryDevice(protobuf.MessageType):
4: protobuf.Field("language", "string", repeated=False, required=False, default=None),
5: protobuf.Field("label", "string", repeated=False, required=False, default=None),
6: protobuf.Field("enforce_wordlist", "bool", repeated=False, required=False, default=None),
8: protobuf.Field("type", "RecoveryDeviceType", repeated=False, required=False, default=None),
8: protobuf.Field("input_method", "RecoveryDeviceInputMethod", repeated=False, required=False, default=None),
9: protobuf.Field("u2f_counter", "uint32", repeated=False, required=False, default=None),
10: protobuf.Field("kind", "RecoveryKind", repeated=False, required=False, default=RecoveryKind.NormalRecovery),
10: protobuf.Field("type", "RecoveryType", repeated=False, required=False, default=RecoveryType.NormalRecovery),
}
def __init__(
@ -3808,9 +3816,9 @@ class RecoveryDevice(protobuf.MessageType):
language: Optional["str"] = None,
label: Optional["str"] = None,
enforce_wordlist: Optional["bool"] = None,
type: Optional["RecoveryDeviceType"] = None,
input_method: Optional["RecoveryDeviceInputMethod"] = None,
u2f_counter: Optional["int"] = None,
kind: Optional["RecoveryKind"] = RecoveryKind.NormalRecovery,
type: Optional["RecoveryType"] = RecoveryType.NormalRecovery,
) -> None:
self.word_count = word_count
self.passphrase_protection = passphrase_protection
@ -3818,9 +3826,9 @@ class RecoveryDevice(protobuf.MessageType):
self.language = language
self.label = label
self.enforce_wordlist = enforce_wordlist
self.type = type
self.input_method = input_method
self.u2f_counter = u2f_counter
self.kind = kind
self.type = type
class WordRequest(protobuf.MessageType):

@ -78,8 +78,7 @@ fn do_main() -> Result<(), trezor_client::Error> {
//optional bool pin_cached = 16; // is PIN already cached in session?
//optional bool passphrase_cached = 17; // is passphrase already cached in session?
//optional bool firmware_present = 18; // is valid firmware loaded?
//optional bool needs_backup = 19; // does storage need backup? (equals to
// Storage.needs_backup) optional uint32 flags = 20; // device flags (equals
//optional uint32 flags = 20; // device flags (equals
// to Storage.flags) optional string model = 21; // device hardware model
//optional uint32 fw_major = 22; // reported firmware version if in bootloader
// mode optional uint32 fw_minor = 23; // reported firmware version if in

@ -170,13 +170,11 @@ impl Trezor {
req.set_label(label);
req.set_enforce_wordlist(true);
if dry_run {
req.set_kind(protos::recovery_device::RecoveryKind::DryRun);
req.set_type(protos::RecoveryType::DryRun);
} else {
req.set_kind(protos::recovery_device::RecoveryKind::NormalRecovery);
req.set_type(protos::RecoveryType::NormalRecovery);
}
req.set_type(
protos::recovery_device::RecoveryDeviceType::RecoveryDeviceType_ScrambledWords,
);
req.set_input_method(protos::recovery_device::RecoveryDeviceInputMethod::ScrambledWords);
//TODO(stevenroose) support languages
req.set_language("english".to_owned());
self.call(req, Box::new(|_, _| Ok(())))

@ -398,8 +398,8 @@ pub struct Features {
pub _passphrase_cached: ::std::option::Option<bool>,
// @@protoc_insertion_point(field:hw.trezor.messages.management.Features.firmware_present)
pub firmware_present: ::std::option::Option<bool>,
// @@protoc_insertion_point(field:hw.trezor.messages.management.Features.needs_backup)
pub needs_backup: ::std::option::Option<bool>,
// @@protoc_insertion_point(field:hw.trezor.messages.management.Features.backup_availability)
pub backup_availability: ::std::option::Option<::protobuf::EnumOrUnknown<features::BackupAvailability>>,
// @@protoc_insertion_point(field:hw.trezor.messages.management.Features.flags)
pub flags: ::std::option::Option<u32>,
// @@protoc_insertion_point(field:hw.trezor.messages.management.Features.model)
@ -464,6 +464,8 @@ pub struct Features {
pub unit_packaging: ::std::option::Option<u32>,
// @@protoc_insertion_point(field:hw.trezor.messages.management.Features.haptic_feedback)
pub haptic_feedback: ::std::option::Option<bool>,
// @@protoc_insertion_point(field:hw.trezor.messages.management.Features.recovery_type)
pub recovery_type: ::std::option::Option<::protobuf::EnumOrUnknown<RecoveryType>>,
// special fields
// @@protoc_insertion_point(special_field:hw.trezor.messages.management.Features.special_fields)
pub special_fields: ::protobuf::SpecialFields,
@ -905,23 +907,26 @@ impl Features {
self.firmware_present = ::std::option::Option::Some(v);
}
// optional bool needs_backup = 19;
// optional .hw.trezor.messages.management.Features.BackupAvailability backup_availability = 19;
pub fn needs_backup(&self) -> bool {
self.needs_backup.unwrap_or(false)
pub fn backup_availability(&self) -> features::BackupAvailability {
match self.backup_availability {
Some(e) => e.enum_value_or(features::BackupAvailability::NotAvailable),
None => features::BackupAvailability::NotAvailable,
}
}
pub fn clear_needs_backup(&mut self) {
self.needs_backup = ::std::option::Option::None;
pub fn clear_backup_availability(&mut self) {
self.backup_availability = ::std::option::Option::None;
}
pub fn has_needs_backup(&self) -> bool {
self.needs_backup.is_some()
pub fn has_backup_availability(&self) -> bool {
self.backup_availability.is_some()
}
// Param is passed by value, moved
pub fn set_needs_backup(&mut self, v: bool) {
self.needs_backup = ::std::option::Option::Some(v);
pub fn set_backup_availability(&mut self, v: features::BackupAvailability) {
self.backup_availability = ::std::option::Option::Some(::protobuf::EnumOrUnknown::new(v));
}
// optional uint32 flags = 20;
@ -1114,8 +1119,8 @@ impl Features {
pub fn recovery_status(&self) -> features::RecoveryStatus {
match self.recovery_status {
Some(e) => e.enum_value_or(features::RecoveryStatus::NoRecovery),
None => features::RecoveryStatus::NoRecovery,
Some(e) => e.enum_value_or(features::RecoveryStatus::Nothing),
None => features::RecoveryStatus::Nothing,
}
}
@ -1593,8 +1598,30 @@ impl Features {
self.haptic_feedback = ::std::option::Option::Some(v);
}
// optional .hw.trezor.messages.management.RecoveryType recovery_type = 53;
pub fn recovery_type(&self) -> RecoveryType {
match self.recovery_type {
Some(e) => e.enum_value_or(RecoveryType::NormalRecovery),
None => RecoveryType::NormalRecovery,
}
}
pub fn clear_recovery_type(&mut self) {
self.recovery_type = ::std::option::Option::None;
}
pub fn has_recovery_type(&self) -> bool {
self.recovery_type.is_some()
}
// Param is passed by value, moved
pub fn set_recovery_type(&mut self, v: RecoveryType) {
self.recovery_type = ::std::option::Option::Some(::protobuf::EnumOrUnknown::new(v));
}
fn generated_message_descriptor_data() -> ::protobuf::reflect::GeneratedMessageDescriptorData {
let mut fields = ::std::vec::Vec::with_capacity(50);
let mut fields = ::std::vec::Vec::with_capacity(51);
let mut oneofs = ::std::vec::Vec::with_capacity(0);
fields.push(::protobuf::reflect::rt::v2::make_option_accessor::<_, _>(
"vendor",
@ -1682,9 +1709,9 @@ impl Features {
|m: &mut Features| { &mut m.firmware_present },
));
fields.push(::protobuf::reflect::rt::v2::make_option_accessor::<_, _>(
"needs_backup",
|m: &Features| { &m.needs_backup },
|m: &mut Features| { &mut m.needs_backup },
"backup_availability",
|m: &Features| { &m.backup_availability },
|m: &mut Features| { &mut m.backup_availability },
));
fields.push(::protobuf::reflect::rt::v2::make_option_accessor::<_, _>(
"flags",
@ -1846,6 +1873,11 @@ impl Features {
|m: &Features| { &m.haptic_feedback },
|m: &mut Features| { &mut m.haptic_feedback },
));
fields.push(::protobuf::reflect::rt::v2::make_option_accessor::<_, _>(
"recovery_type",
|m: &Features| { &m.recovery_type },
|m: &mut Features| { &mut m.recovery_type },
));
::protobuf::reflect::GeneratedMessageDescriptorData::new_2::<Features>(
"Features",
fields,
@ -1925,7 +1957,7 @@ impl ::protobuf::Message for Features {
self.firmware_present = ::std::option::Option::Some(is.read_bool()?);
},
152 => {
self.needs_backup = ::std::option::Option::Some(is.read_bool()?);
self.backup_availability = ::std::option::Option::Some(is.read_enum_or_unknown()?);
},
160 => {
self.flags = ::std::option::Option::Some(is.read_uint32()?);
@ -2026,6 +2058,9 @@ impl ::protobuf::Message for Features {
416 => {
self.haptic_feedback = ::std::option::Option::Some(is.read_bool()?);
},
424 => {
self.recovery_type = ::std::option::Option::Some(is.read_enum_or_unknown()?);
},
tag => {
::protobuf::rt::read_unknown_or_skip_group(tag, is, self.special_fields.mut_unknown_fields())?;
},
@ -2089,8 +2124,8 @@ impl ::protobuf::Message for Features {
if let Some(v) = self.firmware_present {
my_size += 2 + 1;
}
if let Some(v) = self.needs_backup {
my_size += 2 + 1;
if let Some(v) = self.backup_availability {
my_size += ::protobuf::rt::int32_size(19, v.value());
}
if let Some(v) = self.flags {
my_size += ::protobuf::rt::uint32_size(20, v);
@ -2188,6 +2223,9 @@ impl ::protobuf::Message for Features {
if let Some(v) = self.haptic_feedback {
my_size += 2 + 1;
}
if let Some(v) = self.recovery_type {
my_size += ::protobuf::rt::int32_size(53, v.value());
}
my_size += ::protobuf::rt::unknown_fields_size(self.special_fields.unknown_fields());
self.special_fields.cached_size().set(my_size as u32);
my_size
@ -2245,8 +2283,8 @@ impl ::protobuf::Message for Features {
if let Some(v) = self.firmware_present {
os.write_bool(18, v)?;
}
if let Some(v) = self.needs_backup {
os.write_bool(19, v)?;
if let Some(v) = self.backup_availability {
os.write_enum(19, ::protobuf::EnumOrUnknown::value(&v))?;
}
if let Some(v) = self.flags {
os.write_uint32(20, v)?;
@ -2344,6 +2382,9 @@ impl ::protobuf::Message for Features {
if let Some(v) = self.haptic_feedback {
os.write_bool(52, v)?;
}
if let Some(v) = self.recovery_type {
os.write_enum(53, ::protobuf::EnumOrUnknown::value(&v))?;
}
os.write_unknown_fields(self.special_fields.unknown_fields())?;
::std::result::Result::Ok(())
}
@ -2378,7 +2419,7 @@ impl ::protobuf::Message for Features {
self.unlocked = ::std::option::Option::None;
self._passphrase_cached = ::std::option::Option::None;
self.firmware_present = ::std::option::Option::None;
self.needs_backup = ::std::option::Option::None;
self.backup_availability = ::std::option::Option::None;
self.flags = ::std::option::Option::None;
self.model = ::std::option::Option::None;
self.fw_major = ::std::option::Option::None;
@ -2411,6 +2452,7 @@ impl ::protobuf::Message for Features {
self.language_version_matches = ::std::option::Option::None;
self.unit_packaging = ::std::option::Option::None;
self.haptic_feedback = ::std::option::Option::None;
self.recovery_type = ::std::option::Option::None;
self.special_fields.clear();
}
@ -2433,7 +2475,7 @@ impl ::protobuf::Message for Features {
unlocked: ::std::option::Option::None,
_passphrase_cached: ::std::option::Option::None,
firmware_present: ::std::option::Option::None,
needs_backup: ::std::option::Option::None,
backup_availability: ::std::option::Option::None,
flags: ::std::option::Option::None,
model: ::std::option::Option::None,
fw_major: ::std::option::Option::None,
@ -2466,6 +2508,7 @@ impl ::protobuf::Message for Features {
language_version_matches: ::std::option::Option::None,
unit_packaging: ::std::option::Option::None,
haptic_feedback: ::std::option::Option::None,
recovery_type: ::std::option::Option::None,
special_fields: ::protobuf::SpecialFields::new(),
};
&instance
@ -2491,17 +2534,82 @@ impl ::protobuf::reflect::ProtobufValue for Features {
/// Nested message and enums of message `Features`
pub mod features {
#[derive(Clone,Copy,PartialEq,Eq,Debug,Hash)]
// @@protoc_insertion_point(enum:hw.trezor.messages.management.Features.BackupAvailability)
pub enum BackupAvailability {
// @@protoc_insertion_point(enum_value:hw.trezor.messages.management.Features.BackupAvailability.NotAvailable)
NotAvailable = 0,
// @@protoc_insertion_point(enum_value:hw.trezor.messages.management.Features.BackupAvailability.Required)
Required = 1,
// @@protoc_insertion_point(enum_value:hw.trezor.messages.management.Features.BackupAvailability.Available)
Available = 2,
}
impl ::protobuf::Enum for BackupAvailability {
const NAME: &'static str = "BackupAvailability";
fn value(&self) -> i32 {
*self as i32
}
fn from_i32(value: i32) -> ::std::option::Option<BackupAvailability> {
match value {
0 => ::std::option::Option::Some(BackupAvailability::NotAvailable),
1 => ::std::option::Option::Some(BackupAvailability::Required),
2 => ::std::option::Option::Some(BackupAvailability::Available),
_ => ::std::option::Option::None
}
}
fn from_str(str: &str) -> ::std::option::Option<BackupAvailability> {
match str {
"NotAvailable" => ::std::option::Option::Some(BackupAvailability::NotAvailable),
"Required" => ::std::option::Option::Some(BackupAvailability::Required),
"Available" => ::std::option::Option::Some(BackupAvailability::Available),
_ => ::std::option::Option::None
}
}
const VALUES: &'static [BackupAvailability] = &[
BackupAvailability::NotAvailable,
BackupAvailability::Required,
BackupAvailability::Available,
];
}
impl ::protobuf::EnumFull for BackupAvailability {
fn enum_descriptor() -> ::protobuf::reflect::EnumDescriptor {
static descriptor: ::protobuf::rt::Lazy<::protobuf::reflect::EnumDescriptor> = ::protobuf::rt::Lazy::new();
descriptor.get(|| super::file_descriptor().enum_by_package_relative_name("Features.BackupAvailability").unwrap()).clone()
}
fn descriptor(&self) -> ::protobuf::reflect::EnumValueDescriptor {
let index = *self as usize;
Self::enum_descriptor().value_by_index(index)
}
}
impl ::std::default::Default for BackupAvailability {
fn default() -> Self {
BackupAvailability::NotAvailable
}
}
impl BackupAvailability {
pub(in super) fn generated_enum_descriptor_data() -> ::protobuf::reflect::GeneratedEnumDescriptorData {
::protobuf::reflect::GeneratedEnumDescriptorData::new::<BackupAvailability>("Features.BackupAvailability")
}
}
#[derive(Clone,Copy,PartialEq,Eq,Debug,Hash)]
// @@protoc_insertion_point(enum:hw.trezor.messages.management.Features.RecoveryStatus)
pub enum RecoveryStatus {
// @@protoc_insertion_point(enum_value:hw.trezor.messages.management.Features.RecoveryStatus.NoRecovery)
NoRecovery = 0,
// @@protoc_insertion_point(enum_value:hw.trezor.messages.management.Features.RecoveryStatus.InNormalRecovery)
InNormalRecovery = 1,
// @@protoc_insertion_point(enum_value:hw.trezor.messages.management.Features.RecoveryStatus.InDryRunRecovery)
InDryRunRecovery = 2,
// @@protoc_insertion_point(enum_value:hw.trezor.messages.management.Features.RecoveryStatus.InUnlockRepeatedBackupRecovery)
InUnlockRepeatedBackupRecovery = 3,
// @@protoc_insertion_point(enum_value:hw.trezor.messages.management.Features.RecoveryStatus.Nothing)
Nothing = 0,
// @@protoc_insertion_point(enum_value:hw.trezor.messages.management.Features.RecoveryStatus.Recovery)
Recovery = 1,
// @@protoc_insertion_point(enum_value:hw.trezor.messages.management.Features.RecoveryStatus.Backup)
Backup = 2,
}
impl ::protobuf::Enum for RecoveryStatus {
@ -2513,29 +2621,26 @@ pub mod features {
fn from_i32(value: i32) -> ::std::option::Option<RecoveryStatus> {
match value {
0 => ::std::option::Option::Some(RecoveryStatus::NoRecovery),
1 => ::std::option::Option::Some(RecoveryStatus::InNormalRecovery),
2 => ::std::option::Option::Some(RecoveryStatus::InDryRunRecovery),
3 => ::std::option::Option::Some(RecoveryStatus::InUnlockRepeatedBackupRecovery),
0 => ::std::option::Option::Some(RecoveryStatus::Nothing),
1 => ::std::option::Option::Some(RecoveryStatus::Recovery),
2 => ::std::option::Option::Some(RecoveryStatus::Backup),
_ => ::std::option::Option::None
}
}
fn from_str(str: &str) -> ::std::option::Option<RecoveryStatus> {
match str {
"NoRecovery" => ::std::option::Option::Some(RecoveryStatus::NoRecovery),
"InNormalRecovery" => ::std::option::Option::Some(RecoveryStatus::InNormalRecovery),
"InDryRunRecovery" => ::std::option::Option::Some(RecoveryStatus::InDryRunRecovery),
"InUnlockRepeatedBackupRecovery" => ::std::option::Option::Some(RecoveryStatus::InUnlockRepeatedBackupRecovery),
"Nothing" => ::std::option::Option::Some(RecoveryStatus::Nothing),
"Recovery" => ::std::option::Option::Some(RecoveryStatus::Recovery),
"Backup" => ::std::option::Option::Some(RecoveryStatus::Backup),
_ => ::std::option::Option::None
}
}
const VALUES: &'static [RecoveryStatus] = &[
RecoveryStatus::NoRecovery,
RecoveryStatus::InNormalRecovery,
RecoveryStatus::InDryRunRecovery,
RecoveryStatus::InUnlockRepeatedBackupRecovery,
RecoveryStatus::Nothing,
RecoveryStatus::Recovery,
RecoveryStatus::Backup,
];
}
@ -2553,7 +2658,7 @@ pub mod features {
impl ::std::default::Default for RecoveryStatus {
fn default() -> Self {
RecoveryStatus::NoRecovery
RecoveryStatus::Nothing
}
}
@ -7839,12 +7944,12 @@ pub struct RecoveryDevice {
pub label: ::std::option::Option<::std::string::String>,
// @@protoc_insertion_point(field:hw.trezor.messages.management.RecoveryDevice.enforce_wordlist)
pub enforce_wordlist: ::std::option::Option<bool>,
// @@protoc_insertion_point(field:hw.trezor.messages.management.RecoveryDevice.type)
pub type_: ::std::option::Option<::protobuf::EnumOrUnknown<recovery_device::RecoveryDeviceType>>,
// @@protoc_insertion_point(field:hw.trezor.messages.management.RecoveryDevice.input_method)
pub input_method: ::std::option::Option<::protobuf::EnumOrUnknown<recovery_device::RecoveryDeviceInputMethod>>,
// @@protoc_insertion_point(field:hw.trezor.messages.management.RecoveryDevice.u2f_counter)
pub u2f_counter: ::std::option::Option<u32>,
// @@protoc_insertion_point(field:hw.trezor.messages.management.RecoveryDevice.kind)
pub kind: ::std::option::Option<::protobuf::EnumOrUnknown<recovery_device::RecoveryKind>>,
// @@protoc_insertion_point(field:hw.trezor.messages.management.RecoveryDevice.type)
pub type_: ::std::option::Option<::protobuf::EnumOrUnknown<RecoveryType>>,
// special fields
// @@protoc_insertion_point(special_field:hw.trezor.messages.management.RecoveryDevice.special_fields)
pub special_fields: ::protobuf::SpecialFields,
@ -8009,26 +8114,26 @@ impl RecoveryDevice {
self.enforce_wordlist = ::std::option::Option::Some(v);
}
// optional .hw.trezor.messages.management.RecoveryDevice.RecoveryDeviceType type = 8;
// optional .hw.trezor.messages.management.RecoveryDevice.RecoveryDeviceInputMethod input_method = 8;
pub fn type_(&self) -> recovery_device::RecoveryDeviceType {
match self.type_ {
Some(e) => e.enum_value_or(recovery_device::RecoveryDeviceType::RecoveryDeviceType_ScrambledWords),
None => recovery_device::RecoveryDeviceType::RecoveryDeviceType_ScrambledWords,
pub fn input_method(&self) -> recovery_device::RecoveryDeviceInputMethod {
match self.input_method {
Some(e) => e.enum_value_or(recovery_device::RecoveryDeviceInputMethod::ScrambledWords),
None => recovery_device::RecoveryDeviceInputMethod::ScrambledWords,
}
}
pub fn clear_type_(&mut self) {
self.type_ = ::std::option::Option::None;
pub fn clear_input_method(&mut self) {
self.input_method = ::std::option::Option::None;
}
pub fn has_type(&self) -> bool {
self.type_.is_some()
pub fn has_input_method(&self) -> bool {
self.input_method.is_some()
}
// Param is passed by value, moved
pub fn set_type(&mut self, v: recovery_device::RecoveryDeviceType) {
self.type_ = ::std::option::Option::Some(::protobuf::EnumOrUnknown::new(v));
pub fn set_input_method(&mut self, v: recovery_device::RecoveryDeviceInputMethod) {
self.input_method = ::std::option::Option::Some(::protobuf::EnumOrUnknown::new(v));
}
// optional uint32 u2f_counter = 9;
@ -8050,26 +8155,26 @@ impl RecoveryDevice {
self.u2f_counter = ::std::option::Option::Some(v);
}
// optional .hw.trezor.messages.management.RecoveryDevice.RecoveryKind kind = 10;
// optional .hw.trezor.messages.management.RecoveryType type = 10;
pub fn kind(&self) -> recovery_device::RecoveryKind {
match self.kind {
Some(e) => e.enum_value_or(recovery_device::RecoveryKind::NormalRecovery),
None => recovery_device::RecoveryKind::NormalRecovery,
pub fn type_(&self) -> RecoveryType {
match self.type_ {
Some(e) => e.enum_value_or(RecoveryType::NormalRecovery),
None => RecoveryType::NormalRecovery,
}
}
pub fn clear_kind(&mut self) {
self.kind = ::std::option::Option::None;
pub fn clear_type_(&mut self) {
self.type_ = ::std::option::Option::None;
}
pub fn has_kind(&self) -> bool {
self.kind.is_some()
pub fn has_type(&self) -> bool {
self.type_.is_some()
}
// Param is passed by value, moved
pub fn set_kind(&mut self, v: recovery_device::RecoveryKind) {
self.kind = ::std::option::Option::Some(::protobuf::EnumOrUnknown::new(v));
pub fn set_type(&mut self, v: RecoveryType) {
self.type_ = ::std::option::Option::Some(::protobuf::EnumOrUnknown::new(v));
}
fn generated_message_descriptor_data() -> ::protobuf::reflect::GeneratedMessageDescriptorData {
@ -8106,9 +8211,9 @@ impl RecoveryDevice {
|m: &mut RecoveryDevice| { &mut m.enforce_wordlist },
));
fields.push(::protobuf::reflect::rt::v2::make_option_accessor::<_, _>(
"type",
|m: &RecoveryDevice| { &m.type_ },
|m: &mut RecoveryDevice| { &mut m.type_ },
"input_method",
|m: &RecoveryDevice| { &m.input_method },
|m: &mut RecoveryDevice| { &mut m.input_method },
));
fields.push(::protobuf::reflect::rt::v2::make_option_accessor::<_, _>(
"u2f_counter",
@ -8116,9 +8221,9 @@ impl RecoveryDevice {
|m: &mut RecoveryDevice| { &mut m.u2f_counter },
));
fields.push(::protobuf::reflect::rt::v2::make_option_accessor::<_, _>(
"kind",
|m: &RecoveryDevice| { &m.kind },
|m: &mut RecoveryDevice| { &mut m.kind },
"type",
|m: &RecoveryDevice| { &m.type_ },
|m: &mut RecoveryDevice| { &mut m.type_ },
));
::protobuf::reflect::GeneratedMessageDescriptorData::new_2::<RecoveryDevice>(
"RecoveryDevice",
@ -8157,13 +8262,13 @@ impl ::protobuf::Message for RecoveryDevice {
self.enforce_wordlist = ::std::option::Option::Some(is.read_bool()?);
},
64 => {
self.type_ = ::std::option::Option::Some(is.read_enum_or_unknown()?);
self.input_method = ::std::option::Option::Some(is.read_enum_or_unknown()?);
},
72 => {
self.u2f_counter = ::std::option::Option::Some(is.read_uint32()?);
},
80 => {
self.kind = ::std::option::Option::Some(is.read_enum_or_unknown()?);
self.type_ = ::std::option::Option::Some(is.read_enum_or_unknown()?);
},
tag => {
::protobuf::rt::read_unknown_or_skip_group(tag, is, self.special_fields.mut_unknown_fields())?;
@ -8195,13 +8300,13 @@ impl ::protobuf::Message for RecoveryDevice {
if let Some(v) = self.enforce_wordlist {
my_size += 1 + 1;
}
if let Some(v) = self.type_ {
if let Some(v) = self.input_method {
my_size += ::protobuf::rt::int32_size(8, v.value());
}
if let Some(v) = self.u2f_counter {
my_size += ::protobuf::rt::uint32_size(9, v);
}
if let Some(v) = self.kind {
if let Some(v) = self.type_ {
my_size += ::protobuf::rt::int32_size(10, v.value());
}
my_size += ::protobuf::rt::unknown_fields_size(self.special_fields.unknown_fields());
@ -8228,13 +8333,13 @@ impl ::protobuf::Message for RecoveryDevice {
if let Some(v) = self.enforce_wordlist {
os.write_bool(6, v)?;
}
if let Some(v) = self.type_ {
if let Some(v) = self.input_method {
os.write_enum(8, ::protobuf::EnumOrUnknown::value(&v))?;
}
if let Some(v) = self.u2f_counter {
os.write_uint32(9, v)?;
}
if let Some(v) = self.kind {
if let Some(v) = self.type_ {
os.write_enum(10, ::protobuf::EnumOrUnknown::value(&v))?;
}
os.write_unknown_fields(self.special_fields.unknown_fields())?;
@ -8260,9 +8365,9 @@ impl ::protobuf::Message for RecoveryDevice {
self.language = ::std::option::Option::None;
self.label = ::std::option::Option::None;
self.enforce_wordlist = ::std::option::Option::None;
self.type_ = ::std::option::Option::None;
self.input_method = ::std::option::Option::None;
self.u2f_counter = ::std::option::Option::None;
self.kind = ::std::option::Option::None;
self.type_ = ::std::option::Option::None;
self.special_fields.clear();
}
@ -8274,9 +8379,9 @@ impl ::protobuf::Message for RecoveryDevice {
language: ::std::option::Option::None,
label: ::std::option::Option::None,
enforce_wordlist: ::std::option::Option::None,
type_: ::std::option::Option::None,
input_method: ::std::option::Option::None,
u2f_counter: ::std::option::Option::None,
kind: ::std::option::Option::None,
type_: ::std::option::Option::None,
special_fields: ::protobuf::SpecialFields::new(),
};
&instance
@ -8303,114 +8408,47 @@ impl ::protobuf::reflect::ProtobufValue for RecoveryDevice {
/// Nested message and enums of message `RecoveryDevice`
pub mod recovery_device {
#[derive(Clone,Copy,PartialEq,Eq,Debug,Hash)]
// @@protoc_insertion_point(enum:hw.trezor.messages.management.RecoveryDevice.RecoveryDeviceType)
pub enum RecoveryDeviceType {
// @@protoc_insertion_point(enum_value:hw.trezor.messages.management.RecoveryDevice.RecoveryDeviceType.RecoveryDeviceType_ScrambledWords)
RecoveryDeviceType_ScrambledWords = 0,
// @@protoc_insertion_point(enum_value:hw.trezor.messages.management.RecoveryDevice.RecoveryDeviceType.RecoveryDeviceType_Matrix)
RecoveryDeviceType_Matrix = 1,
}
impl ::protobuf::Enum for RecoveryDeviceType {
const NAME: &'static str = "RecoveryDeviceType";
fn value(&self) -> i32 {
*self as i32
}
fn from_i32(value: i32) -> ::std::option::Option<RecoveryDeviceType> {
match value {
0 => ::std::option::Option::Some(RecoveryDeviceType::RecoveryDeviceType_ScrambledWords),
1 => ::std::option::Option::Some(RecoveryDeviceType::RecoveryDeviceType_Matrix),
_ => ::std::option::Option::None
}
}
fn from_str(str: &str) -> ::std::option::Option<RecoveryDeviceType> {
match str {
"RecoveryDeviceType_ScrambledWords" => ::std::option::Option::Some(RecoveryDeviceType::RecoveryDeviceType_ScrambledWords),
"RecoveryDeviceType_Matrix" => ::std::option::Option::Some(RecoveryDeviceType::RecoveryDeviceType_Matrix),
_ => ::std::option::Option::None
}
}
const VALUES: &'static [RecoveryDeviceType] = &[
RecoveryDeviceType::RecoveryDeviceType_ScrambledWords,
RecoveryDeviceType::RecoveryDeviceType_Matrix,
];
}
impl ::protobuf::EnumFull for RecoveryDeviceType {
fn enum_descriptor() -> ::protobuf::reflect::EnumDescriptor {
static descriptor: ::protobuf::rt::Lazy<::protobuf::reflect::EnumDescriptor> = ::protobuf::rt::Lazy::new();
descriptor.get(|| super::file_descriptor().enum_by_package_relative_name("RecoveryDevice.RecoveryDeviceType").unwrap()).clone()
}
fn descriptor(&self) -> ::protobuf::reflect::EnumValueDescriptor {
let index = *self as usize;
Self::enum_descriptor().value_by_index(index)
}
}
impl ::std::default::Default for RecoveryDeviceType {
fn default() -> Self {
RecoveryDeviceType::RecoveryDeviceType_ScrambledWords
}
}
impl RecoveryDeviceType {
pub(in super) fn generated_enum_descriptor_data() -> ::protobuf::reflect::GeneratedEnumDescriptorData {
::protobuf::reflect::GeneratedEnumDescriptorData::new::<RecoveryDeviceType>("RecoveryDevice.RecoveryDeviceType")
}
}
#[derive(Clone,Copy,PartialEq,Eq,Debug,Hash)]
// @@protoc_insertion_point(enum:hw.trezor.messages.management.RecoveryDevice.RecoveryKind)
pub enum RecoveryKind {
// @@protoc_insertion_point(enum_value:hw.trezor.messages.management.RecoveryDevice.RecoveryKind.NormalRecovery)
NormalRecovery = 0,
// @@protoc_insertion_point(enum_value:hw.trezor.messages.management.RecoveryDevice.RecoveryKind.DryRun)
DryRun = 1,
// @@protoc_insertion_point(enum_value:hw.trezor.messages.management.RecoveryDevice.RecoveryKind.UnlockRepeatedBackup)
UnlockRepeatedBackup = 2,
// @@protoc_insertion_point(enum:hw.trezor.messages.management.RecoveryDevice.RecoveryDeviceInputMethod)
pub enum RecoveryDeviceInputMethod {
// @@protoc_insertion_point(enum_value:hw.trezor.messages.management.RecoveryDevice.RecoveryDeviceInputMethod.ScrambledWords)
ScrambledWords = 0,
// @@protoc_insertion_point(enum_value:hw.trezor.messages.management.RecoveryDevice.RecoveryDeviceInputMethod.Matrix)
Matrix = 1,
}
impl ::protobuf::Enum for RecoveryKind {
const NAME: &'static str = "RecoveryKind";
impl ::protobuf::Enum for RecoveryDeviceInputMethod {
const NAME: &'static str = "RecoveryDeviceInputMethod";
fn value(&self) -> i32 {
*self as i32
}
fn from_i32(value: i32) -> ::std::option::Option<RecoveryKind> {
fn from_i32(value: i32) -> ::std::option::Option<RecoveryDeviceInputMethod> {
match value {
0 => ::std::option::Option::Some(RecoveryKind::NormalRecovery),
1 => ::std::option::Option::Some(RecoveryKind::DryRun),
2 => ::std::option::Option::Some(RecoveryKind::UnlockRepeatedBackup),
0 => ::std::option::Option::Some(RecoveryDeviceInputMethod::ScrambledWords),
1 => ::std::option::Option::Some(RecoveryDeviceInputMethod::Matrix),
_ => ::std::option::Option::None
}
}
fn from_str(str: &str) -> ::std::option::Option<RecoveryKind> {
fn from_str(str: &str) -> ::std::option::Option<RecoveryDeviceInputMethod> {
match str {
"NormalRecovery" => ::std::option::Option::Some(RecoveryKind::NormalRecovery),
"DryRun" => ::std::option::Option::Some(RecoveryKind::DryRun),
"UnlockRepeatedBackup" => ::std::option::Option::Some(RecoveryKind::UnlockRepeatedBackup),
"ScrambledWords" => ::std::option::Option::Some(RecoveryDeviceInputMethod::ScrambledWords),
"Matrix" => ::std::option::Option::Some(RecoveryDeviceInputMethod::Matrix),
_ => ::std::option::Option::None
}
}
const VALUES: &'static [RecoveryKind] = &[
RecoveryKind::NormalRecovery,
RecoveryKind::DryRun,
RecoveryKind::UnlockRepeatedBackup,
const VALUES: &'static [RecoveryDeviceInputMethod] = &[
RecoveryDeviceInputMethod::ScrambledWords,
RecoveryDeviceInputMethod::Matrix,
];
}
impl ::protobuf::EnumFull for RecoveryKind {
impl ::protobuf::EnumFull for RecoveryDeviceInputMethod {
fn enum_descriptor() -> ::protobuf::reflect::EnumDescriptor {
static descriptor: ::protobuf::rt::Lazy<::protobuf::reflect::EnumDescriptor> = ::protobuf::rt::Lazy::new();
descriptor.get(|| super::file_descriptor().enum_by_package_relative_name("RecoveryDevice.RecoveryKind").unwrap()).clone()
descriptor.get(|| super::file_descriptor().enum_by_package_relative_name("RecoveryDevice.RecoveryDeviceInputMethod").unwrap()).clone()
}
fn descriptor(&self) -> ::protobuf::reflect::EnumValueDescriptor {
@ -8419,15 +8457,15 @@ pub mod recovery_device {
}
}
impl ::std::default::Default for RecoveryKind {
impl ::std::default::Default for RecoveryDeviceInputMethod {
fn default() -> Self {
RecoveryKind::NormalRecovery
RecoveryDeviceInputMethod::ScrambledWords
}
}
impl RecoveryKind {
impl RecoveryDeviceInputMethod {
pub(in super) fn generated_enum_descriptor_data() -> ::protobuf::reflect::GeneratedEnumDescriptorData {
::protobuf::reflect::GeneratedEnumDescriptorData::new::<RecoveryKind>("RecoveryDevice.RecoveryKind")
::protobuf::reflect::GeneratedEnumDescriptorData::new::<RecoveryDeviceInputMethod>("RecoveryDevice.RecoveryDeviceInputMethod")
}
}
}
@ -10979,12 +11017,79 @@ impl HomescreenFormat {
}
}
#[derive(Clone,Copy,PartialEq,Eq,Debug,Hash)]
// @@protoc_insertion_point(enum:hw.trezor.messages.management.RecoveryType)
pub enum RecoveryType {
// @@protoc_insertion_point(enum_value:hw.trezor.messages.management.RecoveryType.NormalRecovery)
NormalRecovery = 0,
// @@protoc_insertion_point(enum_value:hw.trezor.messages.management.RecoveryType.DryRun)
DryRun = 1,
// @@protoc_insertion_point(enum_value:hw.trezor.messages.management.RecoveryType.UnlockRepeatedBackup)
UnlockRepeatedBackup = 2,
}
impl ::protobuf::Enum for RecoveryType {
const NAME: &'static str = "RecoveryType";
fn value(&self) -> i32 {
*self as i32
}
fn from_i32(value: i32) -> ::std::option::Option<RecoveryType> {
match value {
0 => ::std::option::Option::Some(RecoveryType::NormalRecovery),
1 => ::std::option::Option::Some(RecoveryType::DryRun),
2 => ::std::option::Option::Some(RecoveryType::UnlockRepeatedBackup),
_ => ::std::option::Option::None
}
}
fn from_str(str: &str) -> ::std::option::Option<RecoveryType> {
match str {
"NormalRecovery" => ::std::option::Option::Some(RecoveryType::NormalRecovery),
"DryRun" => ::std::option::Option::Some(RecoveryType::DryRun),
"UnlockRepeatedBackup" => ::std::option::Option::Some(RecoveryType::UnlockRepeatedBackup),
_ => ::std::option::Option::None
}
}
const VALUES: &'static [RecoveryType] = &[
RecoveryType::NormalRecovery,
RecoveryType::DryRun,
RecoveryType::UnlockRepeatedBackup,
];
}
impl ::protobuf::EnumFull for RecoveryType {
fn enum_descriptor() -> ::protobuf::reflect::EnumDescriptor {
static descriptor: ::protobuf::rt::Lazy<::protobuf::reflect::EnumDescriptor> = ::protobuf::rt::Lazy::new();
descriptor.get(|| file_descriptor().enum_by_package_relative_name("RecoveryType").unwrap()).clone()
}
fn descriptor(&self) -> ::protobuf::reflect::EnumValueDescriptor {
let index = *self as usize;
Self::enum_descriptor().value_by_index(index)
}
}
impl ::std::default::Default for RecoveryType {
fn default() -> Self {
RecoveryType::NormalRecovery
}
}
impl RecoveryType {
fn generated_enum_descriptor_data() -> ::protobuf::reflect::GeneratedEnumDescriptorData {
::protobuf::reflect::GeneratedEnumDescriptorData::new::<RecoveryType>("RecoveryType")
}
}
static file_descriptor_proto_data: &'static [u8] = b"\
\n\x19messages-management.proto\x12\x1dhw.trezor.messages.management\x1a\
\x0emessages.proto\"\x80\x01\n\nInitialize\x12\x1d\n\nsession_id\x18\x01\
\x20\x01(\x0cR\tsessionId\x12,\n\x10_skip_passphrase\x18\x02\x20\x01(\
\x08R\x0eSkipPassphraseB\x02\x18\x01\x12%\n\x0ederive_cardano\x18\x03\
\x20\x01(\x08R\rderiveCardano\"\r\n\x0bGetFeatures\"\x8f\x16\n\x08Featur\
\x20\x01(\x08R\rderiveCardano\"\r\n\x0bGetFeatures\"\xb7\x17\n\x08Featur\
es\x12\x16\n\x06vendor\x18\x01\x20\x01(\tR\x06vendor\x12#\n\rmajor_versi\
on\x18\x02\x20\x02(\rR\x0cmajorVersion\x12#\n\rminor_version\x18\x03\x20\
\x02(\rR\x0cminorVersion\x12#\n\rpatch_version\x18\x04\x20\x02(\rR\x0cpa\
@ -10999,17 +11104,18 @@ static file_descriptor_proto_data: &'static [u8] = b"\
\x18\x0f\x20\x01(\x08R\x08imported\x12\x1a\n\x08unlocked\x18\x10\x20\x01\
(\x08R\x08unlocked\x120\n\x12_passphrase_cached\x18\x11\x20\x01(\x08R\
\x10PassphraseCachedB\x02\x18\x01\x12)\n\x10firmware_present\x18\x12\x20\
\x01(\x08R\x0ffirmwarePresent\x12!\n\x0cneeds_backup\x18\x13\x20\x01(\
\x08R\x0bneedsBackup\x12\x14\n\x05flags\x18\x14\x20\x01(\rR\x05flags\x12\
\x14\n\x05model\x18\x15\x20\x01(\tR\x05model\x12\x19\n\x08fw_major\x18\
\x16\x20\x01(\rR\x07fwMajor\x12\x19\n\x08fw_minor\x18\x17\x20\x01(\rR\
\x07fwMinor\x12\x19\n\x08fw_patch\x18\x18\x20\x01(\rR\x07fwPatch\x12\x1b\
\n\tfw_vendor\x18\x19\x20\x01(\tR\x08fwVendor\x12+\n\x11unfinished_backu\
p\x18\x1b\x20\x01(\x08R\x10unfinishedBackup\x12\x1b\n\tno_backup\x18\x1c\
\x20\x01(\x08R\x08noBackup\x12_\n\x0frecovery_status\x18\x1d\x20\x01(\
\x0e26.hw.trezor.messages.management.Features.RecoveryStatusR\x0erecover\
yStatus\x12V\n\x0ccapabilities\x18\x1e\x20\x03(\x0e22.hw.trezor.messages\
.management.Features.CapabilityR\x0ccapabilities\x12J\n\x0bbackup_type\
\x01(\x08R\x0ffirmwarePresent\x12k\n\x13backup_availability\x18\x13\x20\
\x01(\x0e2:.hw.trezor.messages.management.Features.BackupAvailabilityR\
\x12backupAvailability\x12\x14\n\x05flags\x18\x14\x20\x01(\rR\x05flags\
\x12\x14\n\x05model\x18\x15\x20\x01(\tR\x05model\x12\x19\n\x08fw_major\
\x18\x16\x20\x01(\rR\x07fwMajor\x12\x19\n\x08fw_minor\x18\x17\x20\x01(\r\
R\x07fwMinor\x12\x19\n\x08fw_patch\x18\x18\x20\x01(\rR\x07fwPatch\x12\
\x1b\n\tfw_vendor\x18\x19\x20\x01(\tR\x08fwVendor\x12+\n\x11unfinished_b\
ackup\x18\x1b\x20\x01(\x08R\x10unfinishedBackup\x12\x1b\n\tno_backup\x18\
\x1c\x20\x01(\x08R\x08noBackup\x12_\n\x0frecovery_status\x18\x1d\x20\x01\
(\x0e26.hw.trezor.messages.management.Features.RecoveryStatusR\x0erecove\
ryStatus\x12V\n\x0ccapabilities\x18\x1e\x20\x03(\x0e22.hw.trezor.message\
s.management.Features.CapabilityR\x0ccapabilities\x12J\n\x0bbackup_type\
\x18\x1f\x20\x01(\x0e2).hw.trezor.messages.management.BackupTypeR\nbacku\
pType\x12&\n\x0fsd_card_present\x18\x20\x20\x01(\x08R\rsdCardPresent\x12\
#\n\rsd_protection\x18!\x20\x01(\x08R\x0csdProtection\x120\n\x14wipe_cod\
@ -11031,35 +11137,37 @@ static file_descriptor_proto_data: &'static [u8] = b"\
\x20\x01(\x08R\x10bootloaderLocked\x12>\n\x18language_version_matches\
\x182\x20\x01(\x08:\x04trueR\x16languageVersionMatches\x12%\n\x0eunit_pa\
ckaging\x183\x20\x01(\rR\runitPackaging\x12'\n\x0fhaptic_feedback\x184\
\x20\x01(\x08R\x0ehapticFeedback\"p\n\x0eRecoveryStatus\x12\x0e\n\nNoRec\
overy\x10\0\x12\x14\n\x10InNormalRecovery\x10\x01\x12\x14\n\x10InDryRunR\
ecovery\x10\x02\x12\"\n\x1eInUnlockRepeatedBackupRecovery\x10\x03\"\xc2\
\x04\n\nCapability\x12\x1c\n\x12Capability_Bitcoin\x10\x01\x1a\x04\x80\
\xa6\x1d\x01\x12\x1b\n\x17Capability_Bitcoin_like\x10\x02\x12\x16\n\x12C\
apability_Binance\x10\x03\x12\x16\n\x12Capability_Cardano\x10\x04\x12\
\x1b\n\x11Capability_Crypto\x10\x05\x1a\x04\x80\xa6\x1d\x01\x12\x12\n\
\x0eCapability_EOS\x10\x06\x12\x17\n\x13Capability_Ethereum\x10\x07\x12\
\x17\n\x0fCapability_Lisk\x10\x08\x1a\x02\x08\x01\x12\x15\n\x11Capabilit\
y_Monero\x10\t\x12\x12\n\x0eCapability_NEM\x10\n\x12\x15\n\x11Capability\
_Ripple\x10\x0b\x12\x16\n\x12Capability_Stellar\x10\x0c\x12\x14\n\x10Cap\
ability_Tezos\x10\r\x12\x12\n\x0eCapability_U2F\x10\x0e\x12\x1b\n\x11Cap\
ability_Shamir\x10\x0f\x1a\x04\x80\xa6\x1d\x01\x12!\n\x17Capability_Sham\
irGroups\x10\x10\x1a\x04\x80\xa6\x1d\x01\x12$\n\x1aCapability_Passphrase\
Entry\x10\x11\x1a\x04\x80\xa6\x1d\x01\x12\x15\n\x11Capability_Solana\x10\
\x12\x12!\n\x17Capability_Translations\x10\x13\x1a\x04\x80\xa6\x1d\x01\
\x12\x1f\n\x15Capability_Brightness\x10\x14\x1a\x04\x80\xa6\x1d\x01\x12\
\x1b\n\x11Capability_Haptic\x10\x15\x1a\x04\x80\xa6\x1d\x01\x1a\x04\xc8\
\xf3\x18\x01\"\x0c\n\nLockDevice\"&\n\x07SetBusy\x12\x1b\n\texpiry_ms\
\x18\x01\x20\x01(\rR\x08expiryMs\"\x0c\n\nEndSession\"\xc4\x04\n\rApplyS\
ettings\x12\x1e\n\x08language\x18\x01\x20\x01(\tR\x08languageB\x02\x18\
\x01\x12\x14\n\x05label\x18\x02\x20\x01(\tR\x05label\x12%\n\x0euse_passp\
hrase\x18\x03\x20\x01(\x08R\rusePassphrase\x12\x1e\n\nhomescreen\x18\x04\
\x20\x01(\x0cR\nhomescreen\x120\n\x12_passphrase_source\x18\x05\x20\x01(\
\rR\x10PassphraseSourceB\x02\x18\x01\x12+\n\x12auto_lock_delay_ms\x18\
\x06\x20\x01(\rR\x0fautoLockDelayMs\x12)\n\x10display_rotation\x18\x07\
\x20\x01(\rR\x0fdisplayRotation\x12=\n\x1bpassphrase_always_on_device\
\x18\x08\x20\x01(\x08R\x18passphraseAlwaysOnDevice\x12T\n\rsafety_checks\
\x18\t\x20\x01(\x0e2/.hw.trezor.messages.management.SafetyCheckLevelR\
\x20\x01(\x08R\x0ehapticFeedback\x12P\n\rrecovery_type\x185\x20\x01(\x0e\
2+.hw.trezor.messages.management.RecoveryTypeR\x0crecoveryType\"C\n\x12B\
ackupAvailability\x12\x10\n\x0cNotAvailable\x10\0\x12\x0c\n\x08Required\
\x10\x01\x12\r\n\tAvailable\x10\x02\"7\n\x0eRecoveryStatus\x12\x0b\n\x07\
Nothing\x10\0\x12\x0c\n\x08Recovery\x10\x01\x12\n\n\x06Backup\x10\x02\"\
\xc2\x04\n\nCapability\x12\x1c\n\x12Capability_Bitcoin\x10\x01\x1a\x04\
\x80\xa6\x1d\x01\x12\x1b\n\x17Capability_Bitcoin_like\x10\x02\x12\x16\n\
\x12Capability_Binance\x10\x03\x12\x16\n\x12Capability_Cardano\x10\x04\
\x12\x1b\n\x11Capability_Crypto\x10\x05\x1a\x04\x80\xa6\x1d\x01\x12\x12\
\n\x0eCapability_EOS\x10\x06\x12\x17\n\x13Capability_Ethereum\x10\x07\
\x12\x17\n\x0fCapability_Lisk\x10\x08\x1a\x02\x08\x01\x12\x15\n\x11Capab\
ility_Monero\x10\t\x12\x12\n\x0eCapability_NEM\x10\n\x12\x15\n\x11Capabi\
lity_Ripple\x10\x0b\x12\x16\n\x12Capability_Stellar\x10\x0c\x12\x14\n\
\x10Capability_Tezos\x10\r\x12\x12\n\x0eCapability_U2F\x10\x0e\x12\x1b\n\
\x11Capability_Shamir\x10\x0f\x1a\x04\x80\xa6\x1d\x01\x12!\n\x17Capabili\
ty_ShamirGroups\x10\x10\x1a\x04\x80\xa6\x1d\x01\x12$\n\x1aCapability_Pas\
sphraseEntry\x10\x11\x1a\x04\x80\xa6\x1d\x01\x12\x15\n\x11Capability_Sol\
ana\x10\x12\x12!\n\x17Capability_Translations\x10\x13\x1a\x04\x80\xa6\
\x1d\x01\x12\x1f\n\x15Capability_Brightness\x10\x14\x1a\x04\x80\xa6\x1d\
\x01\x12\x1b\n\x11Capability_Haptic\x10\x15\x1a\x04\x80\xa6\x1d\x01\x1a\
\x04\xc8\xf3\x18\x01\"\x0c\n\nLockDevice\"&\n\x07SetBusy\x12\x1b\n\texpi\
ry_ms\x18\x01\x20\x01(\rR\x08expiryMs\"\x0c\n\nEndSession\"\xc4\x04\n\rA\
pplySettings\x12\x1e\n\x08language\x18\x01\x20\x01(\tR\x08languageB\x02\
\x18\x01\x12\x14\n\x05label\x18\x02\x20\x01(\tR\x05label\x12%\n\x0euse_p\
assphrase\x18\x03\x20\x01(\x08R\rusePassphrase\x12\x1e\n\nhomescreen\x18\
\x04\x20\x01(\x0cR\nhomescreen\x120\n\x12_passphrase_source\x18\x05\x20\
\x01(\rR\x10PassphraseSourceB\x02\x18\x01\x12+\n\x12auto_lock_delay_ms\
\x18\x06\x20\x01(\rR\x0fautoLockDelayMs\x12)\n\x10display_rotation\x18\
\x07\x20\x01(\rR\x0fdisplayRotation\x12=\n\x1bpassphrase_always_on_devic\
e\x18\x08\x20\x01(\x08R\x18passphraseAlwaysOnDevice\x12T\n\rsafety_check\
s\x18\t\x20\x01(\x0e2/.hw.trezor.messages.management.SafetyCheckLevelR\
\x0csafetyChecks\x123\n\x15experimental_features\x18\n\x20\x01(\x08R\x14\
experimentalFeatures\x129\n\x19hide_passphrase_from_host\x18\x0b\x20\x01\
(\x08R\x16hidePassphraseFromHost\x12'\n\x0fhaptic_feedback\x18\r\x20\x01\
@ -11107,25 +11215,23 @@ static file_descriptor_proto_data: &'static [u8] = b"\
ackupDevice.Slip39GroupR\x06groups\x1a[\n\x0bSlip39Group\x12)\n\x10membe\
r_threshold\x18\x01\x20\x02(\rR\x0fmemberThreshold\x12!\n\x0cmember_coun\
t\x18\x02\x20\x02(\rR\x0bmemberCount\"\x10\n\x0eEntropyRequest\"&\n\nEnt\
ropyAck\x12\x18\n\x07entropy\x18\x01\x20\x02(\x0cR\x07entropy\"\xef\x04\
ropyAck\x12\x18\n\x07entropy\x18\x01\x20\x02(\x0cR\x07entropy\"\x8d\x04\
\n\x0eRecoveryDevice\x12\x1d\n\nword_count\x18\x01\x20\x01(\rR\twordCoun\
t\x123\n\x15passphrase_protection\x18\x02\x20\x01(\x08R\x14passphrasePro\
tection\x12%\n\x0epin_protection\x18\x03\x20\x01(\x08R\rpinProtection\
\x12\x1e\n\x08language\x18\x04\x20\x01(\tR\x08languageB\x02\x18\x01\x12\
\x14\n\x05label\x18\x05\x20\x01(\tR\x05label\x12)\n\x10enforce_wordlist\
\x18\x06\x20\x01(\x08R\x0fenforceWordlist\x12T\n\x04type\x18\x08\x20\x01\
(\x0e2@.hw.trezor.messages.management.RecoveryDevice.RecoveryDeviceTypeR\
\x04type\x12\x1f\n\x0bu2f_counter\x18\t\x20\x01(\rR\nu2fCounter\x12^\n\
\x04kind\x18\n\x20\x01(\x0e2:.hw.trezor.messages.management.RecoveryDevi\
ce.RecoveryKind:\x0eNormalRecoveryR\x04kind\"Z\n\x12RecoveryDeviceType\
\x12%\n!RecoveryDeviceType_ScrambledWords\x10\0\x12\x1d\n\x19RecoveryDev\
iceType_Matrix\x10\x01\"H\n\x0cRecoveryKind\x12\x12\n\x0eNormalRecovery\
\x10\0\x12\n\n\x06DryRun\x10\x01\x12\x18\n\x14UnlockRepeatedBackup\x10\
\x02J\x04\x08\x07\x10\x08\"\xc5\x01\n\x0bWordRequest\x12N\n\x04type\x18\
\x01\x20\x02(\x0e2:.hw.trezor.messages.management.WordRequest.WordReques\
tTypeR\x04type\"f\n\x0fWordRequestType\x12\x19\n\x15WordRequestType_Plai\
n\x10\0\x12\x1b\n\x17WordRequestType_Matrix9\x10\x01\x12\x1b\n\x17WordRe\
questType_Matrix6\x10\x02\"\x1d\n\x07WordAck\x12\x12\n\x04word\x18\x01\
\x18\x06\x20\x01(\x08R\x0fenforceWordlist\x12j\n\x0cinput_method\x18\x08\
\x20\x01(\x0e2G.hw.trezor.messages.management.RecoveryDevice.RecoveryDev\
iceInputMethodR\x0binputMethod\x12\x1f\n\x0bu2f_counter\x18\t\x20\x01(\r\
R\nu2fCounter\x12O\n\x04type\x18\n\x20\x01(\x0e2+.hw.trezor.messages.man\
agement.RecoveryType:\x0eNormalRecoveryR\x04type\";\n\x19RecoveryDeviceI\
nputMethod\x12\x12\n\x0eScrambledWords\x10\0\x12\n\n\x06Matrix\x10\x01J\
\x04\x08\x07\x10\x08\"\xc5\x01\n\x0bWordRequest\x12N\n\x04type\x18\x01\
\x20\x02(\x0e2:.hw.trezor.messages.management.WordRequest.WordRequestTyp\
eR\x04type\"f\n\x0fWordRequestType\x12\x19\n\x15WordRequestType_Plain\
\x10\0\x12\x1b\n\x17WordRequestType_Matrix9\x10\x01\x12\x1b\n\x17WordReq\
uestType_Matrix6\x10\x02\"\x1d\n\x07WordAck\x12\x12\n\x04word\x18\x01\
\x20\x02(\tR\x04word\"0\n\rSetU2FCounter\x12\x1f\n\x0bu2f_counter\x18\
\x01\x20\x02(\rR\nu2fCounter\"\x13\n\x11GetNextU2FCounter\"1\n\x0eNextU2\
FCounter\x12\x1f\n\x0bu2f_counter\x18\x01\x20\x02(\rR\nu2fCounter\"\x11\
@ -11148,8 +11254,10 @@ static file_descriptor_proto_data: &'static [u8] = b"\
\x04\x12\x1e\n\x1aSlip39_Advanced_Extendable\x10\x05*G\n\x10SafetyCheckL\
evel\x12\n\n\x06Strict\x10\0\x12\x10\n\x0cPromptAlways\x10\x01\x12\x15\n\
\x11PromptTemporarily\x10\x02*0\n\x10HomescreenFormat\x12\x08\n\x04Toif\
\x10\x01\x12\x08\n\x04Jpeg\x10\x02\x12\x08\n\x04ToiG\x10\x03BB\n#com.sat\
oshilabs.trezor.lib.protobufB\x17TrezorMessageManagement\x80\xa6\x1d\x01\
\x10\x01\x12\x08\n\x04Jpeg\x10\x02\x12\x08\n\x04ToiG\x10\x03*H\n\x0cReco\
veryType\x12\x12\n\x0eNormalRecovery\x10\0\x12\n\n\x06DryRun\x10\x01\x12\
\x18\n\x14UnlockRepeatedBackup\x10\x02BB\n#com.satoshilabs.trezor.lib.pr\
otobufB\x17TrezorMessageManagement\x80\xa6\x1d\x01\
";
/// `FileDescriptorProto` object which was a source for this generated file
@ -11215,15 +11323,16 @@ pub fn file_descriptor() -> &'static ::protobuf::reflect::FileDescriptor {
messages.push(UnlockBootloader::generated_message_descriptor_data());
messages.push(SetBrightness::generated_message_descriptor_data());
messages.push(backup_device::Slip39Group::generated_message_descriptor_data());
let mut enums = ::std::vec::Vec::with_capacity(10);
let mut enums = ::std::vec::Vec::with_capacity(11);
enums.push(BackupType::generated_enum_descriptor_data());
enums.push(SafetyCheckLevel::generated_enum_descriptor_data());
enums.push(HomescreenFormat::generated_enum_descriptor_data());
enums.push(RecoveryType::generated_enum_descriptor_data());
enums.push(features::BackupAvailability::generated_enum_descriptor_data());
enums.push(features::RecoveryStatus::generated_enum_descriptor_data());
enums.push(features::Capability::generated_enum_descriptor_data());
enums.push(sd_protect::SdProtectOperationType::generated_enum_descriptor_data());
enums.push(recovery_device::RecoveryDeviceType::generated_enum_descriptor_data());
enums.push(recovery_device::RecoveryKind::generated_enum_descriptor_data());
enums.push(recovery_device::RecoveryDeviceInputMethod::generated_enum_descriptor_data());
enums.push(word_request::WordRequestType::generated_enum_descriptor_data());
enums.push(reboot_to_bootloader::BootCommand::generated_enum_descriptor_data());
::protobuf::reflect::GeneratedFileDescriptor::new_generated(

@ -106,7 +106,7 @@ def test_backup_slip39_custom(
assert device_handler.result() == "Seed successfully backed up"
features = device_handler.features()
assert features.initialized is True
assert features.needs_backup is False
assert features.backup_availability == messages.BackupAvailability.NotAvailable
assert features.pin_protection is False
assert features.passphrase_protection is False
assert features.backup_type is messages.BackupType.Slip39_Basic_Extendable

@ -47,7 +47,7 @@ def prepare_recovery_and_evaluate(
assert isinstance(device_handler.result(), messages.Success)
features = device_handler.features()
assert features.initialized is True
assert features.recovery_status == messages.RecoveryStatus.NoRecovery
assert features.recovery_status == messages.RecoveryStatus.Nothing
@pytest.mark.setup_client(uninitialized=True)

@ -93,16 +93,16 @@ def test_repeated_backup(
# great ... device is initialized, backup done, and we are not in recovery mode!
assert device_handler.result() == "Initialized"
features = device_handler.features()
assert features.backup_type is messages.BackupType.Slip39_Basic
assert features.backup_type is messages.BackupType.Slip39_Basic_Extendable
assert features.initialized is True
assert features.needs_backup is False
assert features.backup_availability == messages.BackupAvailability.NotAvailable
assert features.no_backup is False
assert features.recovery_status == messages.RecoveryStatus.NoRecovery
assert features.recovery_status == messages.RecoveryStatus.Nothing
# run recovery to unlock backup
device_handler.run(
device.recover,
recovery_kind=messages.RecoveryKind.UnlockRepeatedBackup,
type=messages.RecoveryType.UnlockRepeatedBackup,
)
recovery.confirm_recovery(debug, "recovery__title_unlock_repeated_backup")
@ -123,14 +123,11 @@ def test_repeated_backup(
# we are now in recovery mode
features = device_handler.features()
assert features.backup_type is messages.BackupType.Slip39_Basic
assert features.backup_type is messages.BackupType.Slip39_Basic_Extendable
assert features.initialized is True
assert features.needs_backup is False
assert features.backup_availability == messages.BackupAvailability.Available
assert features.no_backup is False
assert (
features.recovery_status
== messages.RecoveryStatus.InUnlockRepeatedBackupRecovery
)
assert features.recovery_status == messages.RecoveryStatus.Backup
# at this point, the backup is unlocked...
@ -169,16 +166,16 @@ def test_repeated_backup(
# we are not in recovery mode anymore, because we finished the backup process!
features = device_handler.features()
assert features.backup_type is messages.BackupType.Slip39_Basic
assert features.backup_type is messages.BackupType.Slip39_Basic_Extendable
assert features.initialized is True
assert features.needs_backup is False
assert features.backup_availability == messages.BackupAvailability.NotAvailable
assert features.no_backup is False
assert features.recovery_status == messages.RecoveryStatus.NoRecovery
assert features.recovery_status == messages.RecoveryStatus.Nothing
# try to unlock backup again...
device_handler.run(
device.recover,
recovery_kind=messages.RecoveryKind.UnlockRepeatedBackup,
type=messages.RecoveryType.UnlockRepeatedBackup,
)
recovery.confirm_recovery(debug, "recovery__title_unlock_repeated_backup")
@ -188,7 +185,7 @@ def test_repeated_backup(
recovery.enter_shares(
debug,
second_backup_2_of_3[-2:],
"recovery__title_unlock_repeated_backup",
"recovery__title_dry_run",
"recovery__enter_backup",
"recovery__unlock_repeated_backup",
)
@ -197,22 +194,19 @@ def test_repeated_backup(
# we are now in recovery mode again!
features = device_handler.features()
assert features.backup_type is messages.BackupType.Slip39_Basic
assert features.backup_type is messages.BackupType.Slip39_Basic_Extendable
assert features.initialized is True
assert features.needs_backup is False
assert features.backup_availability == messages.BackupAvailability.Available
assert features.no_backup is False
assert (
features.recovery_status
== messages.RecoveryStatus.InUnlockRepeatedBackupRecovery
)
assert features.recovery_status == messages.RecoveryStatus.Backup
# but if we cancel the backup at this point...
reset.cancel_backup(debug)
# ...we are out of recovery mode!
features = device_handler.features()
assert features.backup_type is messages.BackupType.Slip39_Basic
assert features.backup_type is messages.BackupType.Slip39_Basic_Extendable
assert features.initialized is True
assert features.needs_backup is False
assert features.backup_availability == messages.BackupAvailability.NotAvailable
assert features.no_backup is False
assert features.recovery_status == messages.RecoveryStatus.NoRecovery
assert features.recovery_status == messages.RecoveryStatus.Nothing

@ -72,7 +72,7 @@ def test_reset_bip39(device_handler: "BackgroundDeviceHandler"):
assert device_handler.result() == "Initialized"
features = device_handler.features()
assert features.initialized is True
assert features.needs_backup is False
assert features.backup_availability == messages.BackupAvailability.NotAvailable
assert features.pin_protection is False
assert features.passphrase_protection is False
assert features.backup_type is messages.BackupType.Bip39

@ -139,7 +139,7 @@ def test_reset_slip39_advanced(
features = device_handler.features()
assert features.initialized is True
assert features.needs_backup is False
assert features.backup_availability == messages.BackupAvailability.NotAvailable
assert features.pin_protection is False
assert features.passphrase_protection is False
assert features.backup_type is messages.BackupType.Slip39_Advanced_Extendable

@ -117,7 +117,7 @@ def test_reset_slip39_basic(
assert device_handler.result() == "Initialized"
features = device_handler.features()
assert features.initialized is True
assert features.needs_backup is False
assert features.backup_availability == messages.BackupAvailability.NotAvailable
assert features.pin_protection is False
assert features.passphrase_protection is False
assert features.backup_type is messages.BackupType.Slip39_Basic_Extendable

@ -28,7 +28,7 @@ from ...input_flows import (
)
def do_recover_legacy(client: Client, mnemonic: list[str], **kwargs: Any):
def do_recover_legacy(client: Client, mnemonic: list[str]):
def input_callback(_):
word, pos = client.debug.read_recovery_word()
if pos != 0 and pos is not None:
@ -40,11 +40,10 @@ def do_recover_legacy(client: Client, mnemonic: list[str], **kwargs: Any):
ret = device.recover(
client,
recovery_kind=messages.RecoveryKind.DryRun,
type=messages.RecoveryType.DryRun,
word_count=len(mnemonic),
type=messages.RecoveryDeviceType.ScrambledWords,
input_method=messages.RecoveryDeviceInputMethod.ScrambledWords,
input_callback=input_callback,
**kwargs
)
# if the call succeeded, check that all words have been used
assert all(m is None for m in mnemonic)
@ -56,7 +55,7 @@ def do_recover_core(client: Client, mnemonic: list[str], mismatch: bool = False)
client.watch_layout()
IF = InputFlowBip39RecoveryDryRun(client, mnemonic, mismatch=mismatch)
client.set_input_flow(IF.get())
return device.recover(client, recovery_kind=messages.RecoveryKind.DryRun)
return device.recover(client, type=messages.RecoveryType.DryRun)
def do_recover(client: Client, mnemonic: list[str], mismatch: bool = False):
@ -105,10 +104,10 @@ def test_uninitialized(client: Client):
DRY_RUN_ALLOWED_FIELDS = (
"kind",
"type",
"word_count",
"enforce_wordlist",
"type",
"input_method",
"show_tutorial",
)
@ -131,7 +130,7 @@ def _make_bad_params():
yield field.name, True
elif field.type == "string":
yield field.name, "test"
elif field.type == "RecoveryKind":
elif field.type == "RecoveryType":
yield field.name, 1
else:
# Someone added a field to RecoveryDevice of a type that has no assigned
@ -142,10 +141,10 @@ def _make_bad_params():
@pytest.mark.parametrize("field_name, field_value", _make_bad_params())
def test_bad_parameters(client: Client, field_name: str, field_value: Any):
msg = messages.RecoveryDevice(
kind=messages.RecoveryKind.DryRun,
type=messages.RecoveryType.DryRun,
word_count=12,
enforce_wordlist=True,
type=messages.RecoveryDeviceType.ScrambledWords,
input_method=messages.RecoveryDeviceInputMethod.ScrambledWords,
)
setattr(msg, field_name, field_value)
with pytest.raises(

@ -211,7 +211,8 @@ def test_already_initialized(client: Client):
ret = client.call_raw(
messages.RecoveryDevice(
word_count=12, type=messages.RecoveryDeviceType.ScrambledWords
word_count=12,
input_method=messages.RecoveryDeviceInputMethod.ScrambledWords,
)
)
assert isinstance(ret, messages.Failure)

@ -20,7 +20,7 @@ from shamir_mnemonic import shamir
from trezorlib import device
from trezorlib.debuglink import TrezorClientDebugLink as Client
from trezorlib.messages import BackupType
from trezorlib.messages import BackupAvailability, BackupType
from ...common import WITH_MOCK_URANDOM
from ...input_flows import (
@ -85,7 +85,7 @@ def test_skip_backup_msg(client: Client, backup_type, backup_flow):
)
assert client.features.initialized is True
assert client.features.needs_backup is True
assert client.features.backup_availability == BackupAvailability.Required
assert client.features.unfinished_backup is False
assert client.features.no_backup is False
assert client.features.backup_type is backup_type
@ -94,7 +94,7 @@ def test_skip_backup_msg(client: Client, backup_type, backup_flow):
client.init_device()
assert client.features.initialized is True
assert client.features.needs_backup is False
assert client.features.backup_availability == BackupAvailability.NotAvailable
assert client.features.unfinished_backup is False
assert client.features.backup_type is backup_type
@ -119,7 +119,7 @@ def test_skip_backup_manual(client: Client, backup_type: BackupType, backup_flow
)
assert client.features.initialized is True
assert client.features.needs_backup is True
assert client.features.backup_availability == BackupAvailability.Required
assert client.features.unfinished_backup is False
assert client.features.no_backup is False
assert client.features.backup_type is backup_type
@ -128,7 +128,7 @@ def test_skip_backup_manual(client: Client, backup_type: BackupType, backup_flow
client.init_device()
assert client.features.initialized is True
assert client.features.needs_backup is False
assert client.features.backup_availability == BackupAvailability.NotAvailable
assert client.features.unfinished_backup is False
assert client.features.backup_type is backup_type

@ -53,7 +53,7 @@ def test_reset_device_skip_backup(client: Client):
# Check if device is properly initialized
ret = client.call_raw(messages.Initialize())
assert ret.initialized is True
assert ret.needs_backup is True
assert ret.backup_availability == messages.BackupAvailability.Required
assert ret.unfinished_backup is False
assert ret.no_backup is False
@ -120,7 +120,7 @@ def test_reset_device_skip_backup_break(client: Client):
# Check if device is properly initialized
ret = client.call_raw(messages.Initialize())
assert ret.initialized is True
assert ret.needs_backup is True
assert ret.backup_availability == messages.BackupAvailability.Required
assert ret.unfinished_backup is False
assert ret.no_backup is False
@ -131,7 +131,7 @@ def test_reset_device_skip_backup_break(client: Client):
ret = client.call_raw(messages.Initialize())
assert isinstance(ret, messages.Features)
assert ret.initialized is True
assert ret.needs_backup is False
assert ret.backup_availability == messages.BackupAvailability.NotAvailable
assert ret.unfinished_backup is True
assert ret.no_backup is False
@ -143,7 +143,7 @@ def test_reset_device_skip_backup_break(client: Client):
ret = client.call_raw(messages.Initialize())
assert isinstance(ret, messages.Features)
assert ret.initialized is True
assert ret.needs_backup is False
assert ret.backup_availability == messages.BackupAvailability.NotAvailable
assert ret.unfinished_backup is True
assert ret.no_backup is False

@ -80,7 +80,7 @@ def reset_device(client: Client, strength: int):
# Check if device is properly initialized
resp = client.call_raw(messages.Initialize())
assert resp.initialized is True
assert resp.needs_backup is False
assert resp.backup_availability == messages.BackupAvailability.NotAvailable
assert resp.pin_protection is False
assert resp.passphrase_protection is False
@ -177,7 +177,7 @@ def test_reset_device_256_pin(client: Client):
# Check if device is properly initialized
resp = client.call_raw(messages.Initialize())
assert resp.initialized is True
assert resp.needs_backup is False
assert resp.backup_availability == messages.BackupAvailability.NotAvailable
assert resp.pin_protection is True
assert resp.passphrase_protection is True

@ -57,7 +57,7 @@ def reset_device(client: Client, strength: int):
# Check if device is properly initialized
resp = client.call_raw(messages.Initialize())
assert resp.initialized is True
assert resp.needs_backup is False
assert resp.backup_availability == messages.BackupAvailability.NotAvailable
assert resp.pin_protection is False
assert resp.passphrase_protection is False
assert resp.backup_type is messages.BackupType.Bip39
@ -106,7 +106,7 @@ def test_reset_device_pin(client: Client):
# Check if device is properly initialized
resp = client.call_raw(messages.Initialize())
assert resp.initialized is True
assert resp.needs_backup is False
assert resp.backup_availability == messages.BackupAvailability.NotAvailable
assert resp.pin_protection is True
assert resp.passphrase_protection is True
@ -140,7 +140,7 @@ def test_reset_failed_check(client: Client):
# Check if device is properly initialized
resp = client.call_raw(messages.Initialize())
assert resp.initialized is True
assert resp.needs_backup is False
assert resp.backup_availability == messages.BackupAvailability.NotAvailable
assert resp.pin_protection is False
assert resp.passphrase_protection is False
assert resp.backup_type is messages.BackupType.Bip39

@ -55,7 +55,9 @@ def reset(client: Client, strength: int = 128, skip_backup: bool = False) -> str
# Check if device is properly initialized
assert client.features.initialized is True
assert client.features.needs_backup is False
assert (
client.features.backup_availability == messages.BackupAvailability.NotAvailable
)
assert client.features.pin_protection is False
assert client.features.passphrase_protection is False

@ -75,7 +75,9 @@ def reset(client: Client, strength: int = 128) -> list[str]:
# Check if device is properly initialized
assert client.features.initialized is True
assert client.features.needs_backup is False
assert (
client.features.backup_availability == messages.BackupAvailability.NotAvailable
)
assert client.features.pin_protection is False
assert client.features.passphrase_protection is False
assert client.features.backup_type is BackupType.Slip39_Advanced_Extendable

@ -65,7 +65,9 @@ def reset(client: Client, strength: int = 128) -> list[str]:
# Check if device is properly initialized
assert client.features.initialized is True
assert client.features.needs_backup is False
assert (
client.features.backup_availability == messages.BackupAvailability.NotAvailable
)
assert client.features.pin_protection is False
assert client.features.passphrase_protection is False
assert client.features.backup_type is BackupType.Slip39_Basic_Extendable

@ -20,7 +20,7 @@ from shamir_mnemonic import shamir
from trezorlib import device
from trezorlib.debuglink import TrezorClientDebugLink as Client
from trezorlib.exceptions import TrezorFailure
from trezorlib.messages import BackupType
from trezorlib.messages import BackupAvailability, BackupType
from ...common import EXTERNAL_ENTROPY, WITH_MOCK_URANDOM, generate_entropy
from ...input_flows import InputFlowSlip39AdvancedResetRecovery
@ -58,7 +58,7 @@ def test_reset_device_slip39_advanced(client: Client):
# Check if device is properly initialized
assert client.features.initialized is True
assert client.features.needs_backup is False
assert client.features.backup_availability == BackupAvailability.NotAvailable
assert client.features.pin_protection is False
assert client.features.passphrase_protection is False
assert client.features.backup_type is BackupType.Slip39_Advanced_Extendable

@ -22,7 +22,7 @@ from shamir_mnemonic import MnemonicError, shamir
from trezorlib import device
from trezorlib.debuglink import TrezorClientDebugLink as Client
from trezorlib.exceptions import TrezorFailure
from trezorlib.messages import BackupType
from trezorlib.messages import BackupAvailability, BackupType
from ...common import EXTERNAL_ENTROPY, WITH_MOCK_URANDOM, generate_entropy
from ...input_flows import InputFlowSlip39BasicResetRecovery
@ -57,7 +57,7 @@ def reset_device(client: Client, strength: int):
# Check if device is properly initialized
assert client.features.initialized is True
assert client.features.needs_backup is False
assert client.features.backup_availability == BackupAvailability.NotAvailable
assert client.features.pin_protection is False
assert client.features.passphrase_protection is False
assert client.features.backup_type is BackupType.Slip39_Basic_Extendable

@ -40,7 +40,7 @@ from ..input_flows import (
@pytest.mark.skip_t1b1 # TODO we want this for t1 too
@pytest.mark.setup_client(needs_backup=True, mnemonic=MNEMONIC12)
def test_backup_bip39(client: Client):
assert client.features.needs_backup is True
assert client.features.backup_availability == messages.BackupAvailability.Required
with client:
IF = InputFlowBip39Backup(client)
@ -50,7 +50,9 @@ def test_backup_bip39(client: Client):
assert IF.mnemonic == MNEMONIC12
client.init_device()
assert client.features.initialized is True
assert client.features.needs_backup is False
assert (
client.features.backup_availability == messages.BackupAvailability.NotAvailable
)
assert client.features.unfinished_backup is False
assert client.features.no_backup is False
assert client.features.backup_type is messages.BackupType.Bip39
@ -65,7 +67,7 @@ def test_backup_slip39_basic(client: Client, click_info: bool):
if click_info and client.model is models.T2B1:
pytest.skip("click_info not implemented on T2B1")
assert client.features.needs_backup is True
assert client.features.backup_availability == messages.BackupAvailability.Required
with client:
IF = InputFlowSlip39BasicBackup(client, click_info)
@ -74,7 +76,9 @@ def test_backup_slip39_basic(client: Client, click_info: bool):
client.init_device()
assert client.features.initialized is True
assert client.features.needs_backup is False
assert (
client.features.backup_availability == messages.BackupAvailability.NotAvailable
)
assert client.features.unfinished_backup is False
assert client.features.no_backup is False
assert client.features.backup_type is messages.BackupType.Slip39_Basic
@ -93,7 +97,7 @@ def test_backup_slip39_advanced(client: Client, click_info: bool):
if click_info and client.model is models.T2B1:
pytest.skip("click_info not implemented on T2B1")
assert client.features.needs_backup is True
assert client.features.backup_availability == messages.BackupAvailability.Required
with client:
IF = InputFlowSlip39AdvancedBackup(client, click_info)
@ -102,7 +106,9 @@ def test_backup_slip39_advanced(client: Client, click_info: bool):
client.init_device()
assert client.features.initialized is True
assert client.features.needs_backup is False
assert (
client.features.backup_availability == messages.BackupAvailability.NotAvailable
)
assert client.features.unfinished_backup is False
assert client.features.no_backup is False
assert client.features.backup_type is messages.BackupType.Slip39_Advanced
@ -122,7 +128,7 @@ def test_backup_slip39_advanced(client: Client, click_info: bool):
ids=["1_of_1", "2_of_2", "3_of_5"],
)
def test_backup_slip39_custom(client: Client, share_threshold, share_count):
assert client.features.needs_backup is True
assert client.features.backup_availability == messages.BackupAvailability.Required
with client:
IF = InputFlowSlip39CustomBackup(client, share_count)
@ -133,7 +139,9 @@ def test_backup_slip39_custom(client: Client, share_threshold, share_count):
client.init_device()
assert client.features.initialized is True
assert client.features.needs_backup is False
assert (
client.features.backup_availability == messages.BackupAvailability.NotAvailable
)
assert client.features.unfinished_backup is False
assert client.features.no_backup is False
@ -150,7 +158,9 @@ def test_no_backup_fails(client: Client):
client.ensure_unlocked()
assert client.features.initialized is True
assert client.features.no_backup is True
assert client.features.needs_backup is False
assert (
client.features.backup_availability == messages.BackupAvailability.NotAvailable
)
# backup attempt should fail because no_backup=True
with pytest.raises(TrezorFailure, match=r".*Seed already backed up"):
@ -162,7 +172,7 @@ def test_no_backup_fails(client: Client):
def test_interrupt_backup_fails(client: Client):
client.ensure_unlocked()
assert client.features.initialized is True
assert client.features.needs_backup is True
assert client.features.backup_availability == messages.BackupAvailability.Required
assert client.features.unfinished_backup is False
assert client.features.no_backup is False
@ -174,7 +184,9 @@ def test_interrupt_backup_fails(client: Client):
# check that device state is as expected
assert client.features.initialized is True
assert client.features.needs_backup is False
assert (
client.features.backup_availability == messages.BackupAvailability.NotAvailable
)
assert client.features.unfinished_backup is True
assert client.features.no_backup is False

@ -29,7 +29,7 @@ from ..input_flows import InputFlowSlip39BasicBackup, InputFlowSlip39BasicRecove
@pytest.mark.skip_t1b1
@WITH_MOCK_URANDOM
def test_repeated_backup(client: Client):
assert client.features.needs_backup is True
assert client.features.backup_availability == messages.BackupAvailability.Required
# initial device backup
mnemonics = []
@ -51,9 +51,7 @@ def test_repeated_backup(client: Client):
client, mnemonics[:3], unlock_repeated_backup=True
)
client.set_input_flow(IF.get())
ret = device.recover(
client, recovery_kind=messages.RecoveryKind.UnlockRepeatedBackup
)
ret = device.recover(client, type=messages.RecoveryType.UnlockRepeatedBackup)
assert ret == messages.Success(message="Backup unlocked")
# we can now perform another backup
@ -71,7 +69,7 @@ def test_repeated_backup(client: Client):
@pytest.mark.skip_t1b1
@WITH_MOCK_URANDOM
def test_repeated_backup_cancel(client: Client):
assert client.features.needs_backup is True
assert client.features.backup_availability == messages.BackupAvailability.Required
# initial device backup
mnemonics = []
@ -93,9 +91,7 @@ def test_repeated_backup_cancel(client: Client):
client, mnemonics[:3], unlock_repeated_backup=True
)
client.set_input_flow(IF.get())
ret = device.recover(
client, recovery_kind=messages.RecoveryKind.UnlockRepeatedBackup
)
ret = device.recover(client, type=messages.RecoveryType.UnlockRepeatedBackup)
assert ret == messages.Success(message="Backup unlocked")
client.debug.wait_layout()

@ -44,7 +44,7 @@ def test_abort(core_emulator: Emulator):
if debug.model is models.T3T1:
pytest.skip("abort not supported on T3T1")
assert features.recovery_status == RecoveryStatus.NoRecovery
assert features.recovery_status == RecoveryStatus.Nothing
device_handler.run(device.recover, pin_protection=False)
@ -56,7 +56,7 @@ def test_abort(core_emulator: Emulator):
debug = _restart(device_handler, core_emulator)
features = device_handler.features()
assert features.recovery_status == RecoveryStatus.InNormalRecovery
assert features.recovery_status == RecoveryStatus.Recovery
# no waiting for layout because layout doesn't change
assert "number of words" in debug.read_layout().text_content()
@ -72,7 +72,7 @@ def test_abort(core_emulator: Emulator):
assert layout.main_component() == "Homescreen"
features = device_handler.features()
assert features.recovery_status == RecoveryStatus.NoRecovery
assert features.recovery_status == RecoveryStatus.Nothing
@core_only
@ -82,7 +82,7 @@ def test_recovery_single_reset(core_emulator: Emulator):
features = device_handler.features()
assert features.initialized is False
assert features.recovery_status == RecoveryStatus.NoRecovery
assert features.recovery_status == RecoveryStatus.Nothing
device_handler.run(device.recover, pin_protection=False)
@ -92,7 +92,7 @@ def test_recovery_single_reset(core_emulator: Emulator):
debug = _restart(device_handler, core_emulator)
features = device_handler.features()
assert features.recovery_status == RecoveryStatus.InNormalRecovery
assert features.recovery_status == RecoveryStatus.Recovery
# we need to enter the number of words again, that's a feature
recovery.select_number_of_words(debug, wait=False)
@ -101,7 +101,7 @@ def test_recovery_single_reset(core_emulator: Emulator):
features = device_handler.features()
assert features.initialized is True
assert features.recovery_status == RecoveryStatus.NoRecovery
assert features.recovery_status == RecoveryStatus.Nothing
@core_only
@ -119,7 +119,7 @@ def test_recovery_on_old_wallet(core_emulator: Emulator):
features = device_handler.features()
assert features.initialized is False
assert features.recovery_status == RecoveryStatus.NoRecovery
assert features.recovery_status == RecoveryStatus.Nothing
# enter recovery mode
device_handler.run(device.recover, pin_protection=False)
@ -129,7 +129,7 @@ def test_recovery_on_old_wallet(core_emulator: Emulator):
# restart to get into stand-alone recovery
debug = _restart(device_handler, core_emulator)
features = device_handler.features()
assert features.recovery_status == RecoveryStatus.InNormalRecovery
assert features.recovery_status == RecoveryStatus.Recovery
# enter number of words
recovery.select_number_of_words(debug, wait=False)
@ -168,7 +168,7 @@ def test_recovery_on_old_wallet(core_emulator: Emulator):
# check that the recovery succeeded
features = device_handler.features()
assert features.initialized is True
assert features.recovery_status == RecoveryStatus.NoRecovery
assert features.recovery_status == RecoveryStatus.Nothing
@core_only
@ -192,7 +192,7 @@ def test_recovery_multiple_resets(core_emulator: Emulator):
features = device_handler.features()
assert features.initialized is False
assert features.recovery_status == RecoveryStatus.NoRecovery
assert features.recovery_status == RecoveryStatus.Nothing
# start device and recovery
device_handler.run(device.recover, pin_protection=False)
@ -205,7 +205,7 @@ def test_recovery_multiple_resets(core_emulator: Emulator):
# restart
debug = _restart(device_handler, core_emulator)
features = device_handler.features()
assert features.recovery_status == RecoveryStatus.InNormalRecovery
assert features.recovery_status == RecoveryStatus.Recovery
# enter the number of words again, that's a feature!
recovery.select_number_of_words(debug, wait=False)
@ -217,4 +217,4 @@ def test_recovery_multiple_resets(core_emulator: Emulator):
features = device_handler.features()
assert features.initialized is True
assert features.recovery_status == RecoveryStatus.NoRecovery
assert features.recovery_status == RecoveryStatus.Nothing

@ -21,7 +21,13 @@ import pytest
from shamir_mnemonic import shamir
from trezorlib import btc, debuglink, device, exceptions, fido, models
from trezorlib.messages import ApplySettings, BackupType, RecoveryStatus, Success
from trezorlib.messages import (
ApplySettings,
BackupAvailability,
BackupType,
RecoveryStatus,
Success,
)
from trezorlib.tools import H_
from ..common import MNEMONIC_SLIP39_BASIC_20_3of6, MNEMONIC_SLIP39_BASIC_20_3of6_SECRET
@ -197,7 +203,7 @@ def test_upgrade_reset(gen: str, tag: str):
assert not client.features.passphrase_protection
assert client.features.initialized
assert client.features.label == LABEL
assert not client.features.needs_backup
assert client.features.backup_availability == BackupAvailability.NotAvailable
assert not client.features.unfinished_backup
assert not client.features.no_backup
@ -228,7 +234,7 @@ def test_upgrade_reset_skip_backup(gen: str, tag: str):
assert not client.features.passphrase_protection
assert client.features.initialized
assert client.features.label == LABEL
assert client.features.needs_backup
assert client.features.backup_availability == BackupAvailability.Required
assert not client.features.unfinished_backup
assert not client.features.no_backup
@ -260,7 +266,7 @@ def test_upgrade_reset_no_backup(gen: str, tag: str):
assert not client.features.passphrase_protection
assert client.features.initialized
assert client.features.label == LABEL
assert not client.features.needs_backup
assert client.features.backup_availability == BackupAvailability.NotAvailable
assert not client.features.unfinished_backup
assert client.features.no_backup
@ -291,7 +297,7 @@ def test_upgrade_shamir_recovery(gen: str, tag: Optional[str]):
with EmulatorWrapper(gen, tag) as emu, BackgroundDeviceHandler(
emu.client
) as device_handler:
assert emu.client.features.recovery_status == RecoveryStatus.NoRecovery
assert emu.client.features.recovery_status == RecoveryStatus.Nothing
emu.client.watch_layout(True)
debug = device_handler.debuglink()
@ -312,7 +318,7 @@ def test_upgrade_shamir_recovery(gen: str, tag: Optional[str]):
with EmulatorWrapper(gen, storage=storage) as emu:
assert device_id == emu.client.features.device_id
assert emu.client.features.recovery_status == RecoveryStatus.InNormalRecovery
assert emu.client.features.recovery_status == RecoveryStatus.Recovery
debug = emu.client.debug
emu.client.watch_layout(True)
@ -361,19 +367,21 @@ def test_upgrade_shamir_backup(gen: str, tag: Optional[str]):
emu.client.use_passphrase("TREZOR")
address_passphrase = btc.get_address(emu.client, "Bitcoin", PATH)
assert emu.client.features.needs_backup
assert emu.client.features.backup_availability == BackupAvailability.Required
storage = emu.get_storage()
with EmulatorWrapper(gen, storage=storage) as emu:
assert emu.client.features.device_id == device_id
# Create a backup of the encrypted master secret.
assert emu.client.features.needs_backup
assert emu.client.features.backup_availability == BackupAvailability.Required
with emu.client:
IF = InputFlowSlip39BasicBackup(emu.client, False)
emu.client.set_input_flow(IF.get())
device.backup(emu.client)
assert not emu.client.features.needs_backup
assert (
emu.client.features.backup_availability == BackupAvailability.NotAvailable
)
# Check the backup type.
assert emu.client.features.backup_type == backup_type

Loading…
Cancel
Save