fixup! feat(core): implement repeated backup

ibz/20240423-repeated-backup-rebased
Ioan Bizău 3 weeks ago
parent 878186a4f5
commit eb0fb9aac5

@ -88,7 +88,13 @@ message Features {
// optional bytes fw_vendor_keys = 26; // obsoleted, use fw_vendor
optional bool unfinished_backup = 27; // report unfinished backup (equals to Storage.unfinished_backup)
optional bool no_backup = 28; // report no backup (equals to Storage.no_backup)
optional bool recovery_mode = 29; // is recovery mode in progress
optional RecoveryStatus recovery_status = 29; // whether or not we are in recovery mode and of what kind
enum RecoveryStatus {
NoRecovery = 0;
InNormalRecovery = 1;
InDryRunRecovery = 2;
InUnlockRepeatedBackupRecovery = 3;
}
repeated Capability capabilities = 30; // list of supported capabilities
enum Capability {
option (has_bitcoin_only_values) = true;
@ -427,16 +433,16 @@ message EntropyAck {
* @next WordRequest
*/
message RecoveryDevice {
optional uint32 word_count = 1; // number of words in BIP-39 mnemonic (T1 only)
optional bool passphrase_protection = 2; // enable master node encryption using passphrase
optional bool pin_protection = 3; // enable PIN protection
optional string language = 4 [deprecated=true]; // deprecated (use ChangeLanguage)
optional string label = 5; // device label
optional bool enforce_wordlist = 6; // enforce BIP-39 wordlist during the process (T1 only)
optional uint32 word_count = 1; // number of words in BIP-39 mnemonic (T1 only)
optional bool passphrase_protection = 2; // enable master node encryption using passphrase
optional bool pin_protection = 3; // enable PIN protection
optional string language = 4 [deprecated=true]; // deprecated (use ChangeLanguage)
optional string label = 5; // device label
optional bool enforce_wordlist = 6; // enforce BIP-39 wordlist during the process (T1 only)
// 7 reserved for unused recovery method
optional RecoveryDeviceType type = 8; // supported recovery type (T1 only)
optional uint32 u2f_counter = 9; // U2F counter
optional RecoveryKind kind = 10; // the kind of recovery to perform
optional RecoveryDeviceType type = 8; // supported recovery type (T1 only)
optional uint32 u2f_counter = 9; // U2F counter
optional RecoveryKind kind = 10 [default=NormalRecovery]; // the kind of recovery to perform
/**
* Type of recovery procedure. These should be used as bitmask, e.g.,
* `RecoveryDeviceType_ScrambledWords | RecoveryDeviceType_Matrix`
@ -452,9 +458,9 @@ message RecoveryDevice {
}
enum RecoveryKind {
RecoveryKind_NormalRecovery = 0; // recovery from seedphrase on an uninitialized device
RecoveryKind_DryRun = 1; // mnemonic validation
RecoveryKind_UnlockRepeatedBackup = 2; // unlock SLIP-39 repeated backup
NormalRecovery = 0; // recovery from seedphrase on an uninitialized device
DryRun = 1; // mnemonic validation
UnlockRepeatedBackup = 2; // unlock SLIP-39 repeated backup
}
}

@ -1237,11 +1237,11 @@ pub enum TranslatedString {
storage_msg__starting = 842, // "Starting up"
storage_msg__verifying_pin = 843, // "Verifying PIN"
storage_msg__wrong_pin = 844, // "Wrong PIN"
recovery__title_unlock_repeated_backup = 845, // "Unlock backup"
recovery__unlock_repeated_backup = 846, // "Do you want to unlock the backup?"
recovery__unlock_repeated_backup_verb = 847, // "Unlock backup"
reset__create_x_of_y_shamir_backup_template = 848, // "Do you want to create a {0} of {1} Shamir backup?"
reset__title_shamir_backup = 849, // "Shamir backup"
reset__create_x_of_y_shamir_backup_template = 845, // "Do you want to create a {0} of {1} Shamir backup?"
reset__title_shamir_backup = 846, // "Shamir backup"
recovery__title_unlock_repeated_backup = 847, // "Unlock backup"
recovery__unlock_repeated_backup = 848, // "Do you want to unlock the backup?"
recovery__unlock_repeated_backup_verb = 849, // "Unlock backup"
}
impl TranslatedString {
@ -2474,11 +2474,11 @@ impl TranslatedString {
Self::storage_msg__starting => "Starting up",
Self::storage_msg__verifying_pin => "Verifying PIN",
Self::storage_msg__wrong_pin => "Wrong PIN",
Self::reset__create_x_of_y_shamir_backup_template => "Do you want to create a {0} of {1} Shamir backup?",
Self::reset__title_shamir_backup => "Shamir backup",
Self::recovery__title_unlock_repeated_backup => "Unlock backup",
Self::recovery__unlock_repeated_backup => "Do you want to unlock the backup?",
Self::recovery__unlock_repeated_backup_verb => "Unlock backup",
Self::reset__create_x_of_y_shamir_backup_template => "Do you want to create a {0} of {1} Shamir backup?",
Self::reset__title_shamir_backup => "Shamir backup",
}
}
@ -3712,11 +3712,11 @@ impl TranslatedString {
Qstr::MP_QSTR_storage_msg__starting => Some(Self::storage_msg__starting),
Qstr::MP_QSTR_storage_msg__verifying_pin => Some(Self::storage_msg__verifying_pin),
Qstr::MP_QSTR_storage_msg__wrong_pin => Some(Self::storage_msg__wrong_pin),
Qstr::MP_QSTR_reset__create_x_of_y_shamir_backup_template => Some(Self::reset__create_x_of_y_shamir_backup_template),
Qstr::MP_QSTR_reset__title_shamir_backup => Some(Self::reset__title_shamir_backup),
Qstr::MP_QSTR_recovery__title_unlock_repeated_backup => Some(Self::recovery__title_unlock_repeated_backup),
Qstr::MP_QSTR_recovery__unlock_repeated_backup => Some(Self::recovery__unlock_repeated_backup),
Qstr::MP_QSTR_recovery__unlock_repeated_backup_verb => Some(Self::recovery__unlock_repeated_backup_verb),
Qstr::MP_QSTR_reset__create_x_of_y_shamir_backup_template => Some(Self::reset__create_x_of_y_shamir_backup_template),
Qstr::MP_QSTR_reset__title_shamir_backup => Some(Self::reset__title_shamir_backup),
_ => None,
}
}

@ -123,6 +123,8 @@ trezor.enums.RecoveryDeviceType
import trezor.enums.RecoveryDeviceType
trezor.enums.RecoveryKind
import trezor.enums.RecoveryKind
trezor.enums.RecoveryStatus
import trezor.enums.RecoveryStatus
trezor.enums.RequestType
import trezor.enums.RequestType
trezor.enums.SafetyCheckLevel

@ -60,7 +60,7 @@ 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
from trezor.enums import Capability, RecoveryKind, RecoveryStatus
from trezor.messages import Features
from trezor.ui import HEIGHT, WIDTH
@ -153,7 +153,18 @@ def get_features() -> Features:
f.unfinished_backup = storage_device.unfinished_backup()
f.no_backup = storage_device.no_backup()
f.flags = storage_device.get_flags()
f.recovery_mode = storage_recovery.is_in_progress()
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
else:
raise wire.ProcessError("Unknown recovery kind")
else:
f.recovery_status = RecoveryStatus.NoRecovery
f.backup_type = mnemonic.get_type()
# Only some models are capable of SD card

@ -47,7 +47,7 @@ async def recovery_device(msg: RecoveryDevice) -> Success:
for key, value in msg.__dict__.items():
if key not in DRY_RUN_ALLOWED_FIELDS and value is not None:
raise wire.ProcessError(
f"Forbidden field set in DryRun or UnlockRepeatedBackup: {key}"
f"Forbidden field set in dry-run: {key}"
)
else:
raise ValueError("Unknown RecoveryKind")

@ -19,24 +19,24 @@ async def recovery_homescreen() -> None:
from apps.homescreen import homescreen
if not storage_recovery.is_in_progress():
workflow.set_default(homescreen)
return
elif (
if (
storage_cache.get(storage_cache.APP_RECOVERY_REPEATED_BACKUP_UNLOCKED)
== b"\x01"
):
await _continue_repeated_backup()
elif not storage_recovery.is_in_progress():
workflow.set_default(homescreen)
else:
await recovery_process()
async def recovery_process() -> Success:
import storage
from trezor.enums import MessageType
from trezor.enums import MessageType, RecoveryKind
is_special_kind = (
storage_recovery.is_dry_run() or storage_recovery.is_unlock_repeated_backup()
is_special_kind = storage_recovery.get_kind() in (
RecoveryKind.DryRun,
RecoveryKind.UnlockRepeatedBackup,
)
wire.AVOID_RESTARTING_FOR = (
@ -93,11 +93,11 @@ async def _continue_repeated_backup() -> None:
async def _continue_recovery_process() -> Success:
from trezor import utils
from trezor.enums import RecoveryKind
from trezor.errors import MnemonicError
# gather the current recovery state from storage
dry_run = storage_recovery.is_dry_run()
unlock_repeated_backup = storage_recovery.is_unlock_repeated_backup()
kind = storage_recovery.get_kind()
word_count, backup_type = recover.load_slip39_state()
# Both word_count and backup_type are derived from the same data. Both will be
@ -122,7 +122,7 @@ 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(dry_run)
word_count = await layout.request_word_count(kind == RecoveryKind.DryRun)
# ...and only then show the starting screen with word count.
await _request_share_first_screen(word_count)
assert word_count is not None
@ -144,9 +144,9 @@ async def _continue_recovery_process() -> Success:
await layout.show_invalid_mnemonic(word_count)
assert backup_type is not None
if dry_run:
if kind == RecoveryKind.DryRun:
result = await _finish_recovery_dry_run(secret, backup_type)
elif unlock_repeated_backup:
elif kind == RecoveryKind.UnlockRepeatedBackup:
result = await _finish_recovery_unlock_repeated_backup(secret, backup_type)
else:
result = await _finish_recovery(secret, backup_type)

@ -148,13 +148,14 @@ async def homescreen_dialog(
show_info: bool = False,
) -> None:
import storage.recovery as storage_recovery
from trezor.enums import RecoveryKind
from trezor.ui.layouts.recovery import continue_recovery
from trezor.wire import ActionCancelled
from .recover import RecoveryAborted
while True:
dry_run = storage_recovery.is_dry_run()
dry_run = storage_recovery.get_kind() == RecoveryKind.DryRun
if await continue_recovery(
button_label, text, subtext, info_func, dry_run, show_info
):

@ -1,7 +1,10 @@
from micropython import const
from typing import TYPE_CHECKING
from storage import common
from trezor.enums import RecoveryKind
if TYPE_CHECKING:
from trezor.enums import RecoveryKind
# Namespace:
_NAMESPACE = common.APP_RECOVERY
@ -16,7 +19,6 @@ _SLIP39_ITERATION_EXPONENT = const(0x06) # int
_SLIP39_GROUP_COUNT = const(0x07) # int
# Deprecated Keys:
# _DRY_RUN = const(0x01) # bool (got upgraded to int)
# _WORD_COUNT = const(0x02) # int
# _SLIP39_THRESHOLD = const(0x04) # int
# fmt: on
@ -43,14 +45,22 @@ def set_kind(val: int) -> None:
common.set_uint8(_NAMESPACE, _KIND, val)
def is_dry_run() -> bool:
_require_progress()
return common.get_uint8(_NAMESPACE, _KIND) == RecoveryKind.DryRun
def get_kind() -> RecoveryKind:
from trezor.enums import RecoveryKind
def is_unlock_repeated_backup() -> bool:
_require_progress()
return common.get_uint8(_NAMESPACE, _KIND) == RecoveryKind.UnlockRepeatedBackup
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,
):
# Invalid recovery kind
raise RuntimeError
return recovery_kind # type: ignore [int-into-enum]
def set_slip39_identifier(identifier: int) -> None:

@ -0,0 +1,8 @@
# Automatically generated by pb2py
# fmt: off
# isort:skip_file
NoRecovery = 0
InNormalRecovery = 1
InDryRunRecovery = 2
InUnlockRepeatedBackupRecovery = 3

@ -427,6 +427,12 @@ if TYPE_CHECKING:
Jpeg = 2
ToiG = 3
class RecoveryStatus(IntEnum):
NoRecovery = 0
InNormalRecovery = 1
InDryRunRecovery = 2
InUnlockRepeatedBackupRecovery = 3
class Capability(IntEnum):
Bitcoin = 1
Bitcoin_like = 2

@ -54,6 +54,7 @@ if TYPE_CHECKING:
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 RecoveryStatus # noqa: F401
from trezor.enums import RequestType # noqa: F401
from trezor.enums import SafetyCheckLevel # noqa: F401
from trezor.enums import SdProtectOperationType # noqa: F401
@ -2116,7 +2117,7 @@ if TYPE_CHECKING:
fw_vendor: "str | None"
unfinished_backup: "bool | None"
no_backup: "bool | None"
recovery_mode: "bool | None"
recovery_status: "RecoveryStatus | None"
capabilities: "list[Capability]"
backup_type: "BackupType | None"
sd_card_present: "bool | None"
@ -2169,7 +2170,7 @@ if TYPE_CHECKING:
fw_vendor: "str | None" = None,
unfinished_backup: "bool | None" = None,
no_backup: "bool | None" = None,
recovery_mode: "bool | None" = None,
recovery_status: "RecoveryStatus | None" = None,
backup_type: "BackupType | None" = None,
sd_card_present: "bool | None" = None,
sd_protection: "bool | None" = None,
@ -2572,7 +2573,7 @@ if TYPE_CHECKING:
enforce_wordlist: "bool | None"
type: "RecoveryDeviceType | None"
u2f_counter: "int | None"
kind: "RecoveryKind | None"
kind: "RecoveryKind"
def __init__(
self,

@ -844,9 +844,9 @@
"842": "storage_msg__starting",
"843": "storage_msg__verifying_pin",
"844": "storage_msg__wrong_pin",
"845": "recovery__title_unlock_repeated_backup",
"846": "recovery__unlock_repeated_backup",
"847": "recovery__unlock_repeated_backup_verb",
"848": "reset__create_x_of_y_shamir_backup_template",
"849": "reset__title_shamir_backup"
"845": "reset__create_x_of_y_shamir_backup_template",
"846": "reset__title_shamir_backup",
"847": "recovery__title_unlock_repeated_backup",
"848": "recovery__unlock_repeated_backup",
"849": "recovery__unlock_repeated_backup_verb"
}

@ -1,8 +1,8 @@
{
"current": {
"merkle_root": "a430420d520b093456246183c929614ebe7e26ece5e5502d7988af8d5de542d5",
"datetime": "2024-05-13T13:46:30.042272",
"commit": "82e62cf41c1e0134d2d2ed824c3ad74ead01f10e"
"merkle_root": "96d8a11fd694032494d8fcf141653c6fb1b6c7384f9a34363e5a9f6b530c678f",
"datetime": "2024-05-13T13:48:32.161992",
"commit": "878186a4f5d8dab52197759a036f1b00918e8d8c"
},
"history": [
{

@ -499,7 +499,7 @@ void fsm_msgRecoveryDevice(const RecoveryDevice *msg) {
CHECK_PARAM(!msg->has_passphrase_protection && !msg->has_pin_protection &&
!msg->has_language && !msg->has_label &&
!msg->has_u2f_counter,
_("Forbidden field set in DryRun or UnlockRepeatedBackup"))
_("Forbidden field set in dry-run"))
}
CHECK_PARAM(!msg->has_word_count || msg->word_count == 12 ||

@ -172,6 +172,15 @@ def recover(
input_callback = ui.matrix_words
click.echo(ui.RECOVERY_MATRIX_DESCRIPTION)
if dry_run and unlock_repeated_backup:
raise click.ClickException("Cannot use -d and -b together.")
recovery_kind = None
if dry_run:
recovery_kind = messages.RecoveryKind.DryRun
if unlock_repeated_backup:
recovery_kind = messages.RecoveryKind.UnlockRepeatedBackup
return device.recover(
client,
word_count=int(words),
@ -181,8 +190,7 @@ def recover(
u2f_counter=u2f_counter,
input_callback=input_callback,
type=rec_type,
dry_run=dry_run,
unlock_repeated_backup=unlock_repeated_backup,
recovery_kind=recovery_kind,
)

@ -158,9 +158,10 @@ def recover(
language: Optional[str] = None,
input_callback: Optional[Callable] = None,
type: messages.RecoveryDeviceType = messages.RecoveryDeviceType.ScrambledWords,
dry_run: bool = False,
unlock_repeated_backup: bool = False,
dry_run: Optional[bool] = None,
u2f_counter: Optional[int] = None,
*,
recovery_kind: Optional[messages.RecoveryKind] = None,
) -> "MessageType":
if language is not None:
warnings.warn(
@ -168,13 +169,29 @@ def recover(
DeprecationWarning,
)
if dry_run is not None:
warnings.warn(
"Use recovery_kind=RecoveryKind.DryRun instead!",
DeprecationWarning,
)
if recovery_kind is not None:
raise ValueError(
"Cannot use both dry_run and recovery_kind simultaneously."
)
if client.features.model == "1" and input_callback is None:
raise RuntimeError("Input callback required for Trezor One")
if word_count not in (12, 18, 24):
raise ValueError("Invalid word count. Use 12/18/24")
if client.features.initialized and not (dry_run or unlock_repeated_backup):
is_special_recovery = dry_run or recovery_kind in (
messages.RecoveryKind.DryRun,
messages.RecoveryKind.UnlockRepeatedBackup,
)
if client.features.initialized and not is_special_recovery:
raise RuntimeError(
"Device already initialized. Call device.wipe() and try again."
)
@ -182,22 +199,11 @@ def recover(
if u2f_counter is None:
u2f_counter = int(time.time())
if not dry_run and not unlock_repeated_backup:
kind = messages.RecoveryKind.NormalRecovery
elif dry_run and not unlock_repeated_backup:
kind = messages.RecoveryKind.DryRun
elif unlock_repeated_backup and not dry_run:
kind = messages.RecoveryKind.UnlockRepeatedBackup
else:
raise RuntimeError(
"Only one of dry_run and unlock_repeated_backup can be requested at the same time."
)
msg = messages.RecoveryDevice(
word_count=word_count, enforce_wordlist=True, type=type, kind=kind
word_count=word_count, enforce_wordlist=True, type=type, kind=recovery_kind
)
if kind == messages.RecoveryKind.NormalRecovery:
if recovery_kind == messages.RecoveryKind.NormalRecovery:
# set additional parameters
msg.passphrase_protection = passphrase_protection
msg.pin_protection = pin_protection

@ -458,6 +458,13 @@ class HomescreenFormat(IntEnum):
ToiG = 3
class RecoveryStatus(IntEnum):
NoRecovery = 0
InNormalRecovery = 1
InDryRunRecovery = 2
InUnlockRepeatedBackupRecovery = 3
class Capability(IntEnum):
Bitcoin = 1
Bitcoin_like = 2
@ -3202,7 +3209,7 @@ class Features(protobuf.MessageType):
25: protobuf.Field("fw_vendor", "string", repeated=False, required=False, default=None),
27: protobuf.Field("unfinished_backup", "bool", repeated=False, required=False, default=None),
28: protobuf.Field("no_backup", "bool", repeated=False, required=False, default=None),
29: protobuf.Field("recovery_mode", "bool", repeated=False, required=False, default=None),
29: protobuf.Field("recovery_status", "RecoveryStatus", repeated=False, required=False, default=None),
30: protobuf.Field("capabilities", "Capability", repeated=True, required=False, default=None),
31: protobuf.Field("backup_type", "BackupType", repeated=False, required=False, default=None),
32: protobuf.Field("sd_card_present", "bool", repeated=False, required=False, default=None),
@ -3257,7 +3264,7 @@ class Features(protobuf.MessageType):
fw_vendor: Optional["str"] = None,
unfinished_backup: Optional["bool"] = None,
no_backup: Optional["bool"] = None,
recovery_mode: Optional["bool"] = None,
recovery_status: Optional["RecoveryStatus"] = None,
backup_type: Optional["BackupType"] = None,
sd_card_present: Optional["bool"] = None,
sd_protection: Optional["bool"] = None,
@ -3307,7 +3314,7 @@ class Features(protobuf.MessageType):
self.fw_vendor = fw_vendor
self.unfinished_backup = unfinished_backup
self.no_backup = no_backup
self.recovery_mode = recovery_mode
self.recovery_status = recovery_status
self.backup_type = backup_type
self.sd_card_present = sd_card_present
self.sd_protection = sd_protection
@ -3738,7 +3745,7 @@ class RecoveryDevice(protobuf.MessageType):
6: protobuf.Field("enforce_wordlist", "bool", repeated=False, required=False, default=None),
8: protobuf.Field("type", "RecoveryDeviceType", 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=None),
10: protobuf.Field("kind", "RecoveryKind", repeated=False, required=False, default=RecoveryKind.NormalRecovery),
}
def __init__(
@ -3752,7 +3759,7 @@ class RecoveryDevice(protobuf.MessageType):
enforce_wordlist: Optional["bool"] = None,
type: Optional["RecoveryDeviceType"] = None,
u2f_counter: Optional["int"] = None,
kind: Optional["RecoveryKind"] = None,
kind: Optional["RecoveryKind"] = RecoveryKind.NormalRecovery,
) -> None:
self.word_count = word_count
self.passphrase_protection = passphrase_protection

@ -416,8 +416,8 @@ pub struct Features {
pub unfinished_backup: ::std::option::Option<bool>,
// @@protoc_insertion_point(field:hw.trezor.messages.management.Features.no_backup)
pub no_backup: ::std::option::Option<bool>,
// @@protoc_insertion_point(field:hw.trezor.messages.management.Features.recovery_mode)
pub recovery_mode: ::std::option::Option<bool>,
// @@protoc_insertion_point(field:hw.trezor.messages.management.Features.recovery_status)
pub recovery_status: ::std::option::Option<::protobuf::EnumOrUnknown<features::RecoveryStatus>>,
// @@protoc_insertion_point(field:hw.trezor.messages.management.Features.capabilities)
pub capabilities: ::std::vec::Vec<::protobuf::EnumOrUnknown<features::Capability>>,
// @@protoc_insertion_point(field:hw.trezor.messages.management.Features.backup_type)
@ -1108,23 +1108,26 @@ impl Features {
self.no_backup = ::std::option::Option::Some(v);
}
// optional bool recovery_mode = 29;
// optional .hw.trezor.messages.management.Features.RecoveryStatus recovery_status = 29;
pub fn recovery_mode(&self) -> bool {
self.recovery_mode.unwrap_or(false)
pub fn recovery_status(&self) -> features::RecoveryStatus {
match self.recovery_status {
Some(e) => e.enum_value_or(features::RecoveryStatus::NoRecovery),
None => features::RecoveryStatus::NoRecovery,
}
}
pub fn clear_recovery_mode(&mut self) {
self.recovery_mode = ::std::option::Option::None;
pub fn clear_recovery_status(&mut self) {
self.recovery_status = ::std::option::Option::None;
}
pub fn has_recovery_mode(&self) -> bool {
self.recovery_mode.is_some()
pub fn has_recovery_status(&self) -> bool {
self.recovery_status.is_some()
}
// Param is passed by value, moved
pub fn set_recovery_mode(&mut self, v: bool) {
self.recovery_mode = ::std::option::Option::Some(v);
pub fn set_recovery_status(&mut self, v: features::RecoveryStatus) {
self.recovery_status = ::std::option::Option::Some(::protobuf::EnumOrUnknown::new(v));
}
// optional .hw.trezor.messages.management.BackupType backup_type = 31;
@ -1703,9 +1706,9 @@ impl Features {
|m: &mut Features| { &mut m.no_backup },
));
fields.push(::protobuf::reflect::rt::v2::make_option_accessor::<_, _>(
"recovery_mode",
|m: &Features| { &m.recovery_mode },
|m: &mut Features| { &mut m.recovery_mode },
"recovery_status",
|m: &Features| { &m.recovery_status },
|m: &mut Features| { &mut m.recovery_status },
));
fields.push(::protobuf::reflect::rt::v2::make_vec_simpler_accessor::<_, _>(
"capabilities",
@ -1923,7 +1926,7 @@ impl ::protobuf::Message for Features {
self.no_backup = ::std::option::Option::Some(is.read_bool()?);
},
232 => {
self.recovery_mode = ::std::option::Option::Some(is.read_bool()?);
self.recovery_status = ::std::option::Option::Some(is.read_enum_or_unknown()?);
},
240 => {
self.capabilities.push(is.read_enum_or_unknown()?);
@ -2084,8 +2087,8 @@ impl ::protobuf::Message for Features {
if let Some(v) = self.no_backup {
my_size += 2 + 1;
}
if let Some(v) = self.recovery_mode {
my_size += 2 + 1;
if let Some(v) = self.recovery_status {
my_size += ::protobuf::rt::int32_size(29, v.value());
}
for value in &self.capabilities {
my_size += ::protobuf::rt::int32_size(30, value.value());
@ -2237,8 +2240,8 @@ impl ::protobuf::Message for Features {
if let Some(v) = self.no_backup {
os.write_bool(28, v)?;
}
if let Some(v) = self.recovery_mode {
os.write_bool(29, v)?;
if let Some(v) = self.recovery_status {
os.write_enum(29, ::protobuf::EnumOrUnknown::value(&v))?;
}
for v in &self.capabilities {
os.write_enum(30, ::protobuf::EnumOrUnknown::value(v))?;
@ -2349,7 +2352,7 @@ impl ::protobuf::Message for Features {
self.fw_vendor = ::std::option::Option::None;
self.unfinished_backup = ::std::option::Option::None;
self.no_backup = ::std::option::Option::None;
self.recovery_mode = ::std::option::Option::None;
self.recovery_status = ::std::option::Option::None;
self.capabilities.clear();
self.backup_type = ::std::option::Option::None;
self.sd_card_present = ::std::option::Option::None;
@ -2403,7 +2406,7 @@ impl ::protobuf::Message for Features {
fw_vendor: ::std::option::Option::None,
unfinished_backup: ::std::option::Option::None,
no_backup: ::std::option::Option::None,
recovery_mode: ::std::option::Option::None,
recovery_status: ::std::option::Option::None,
capabilities: ::std::vec::Vec::new(),
backup_type: ::std::option::Option::None,
sd_card_present: ::std::option::Option::None,
@ -2451,6 +2454,78 @@ 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.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,
}
impl ::protobuf::Enum for RecoveryStatus {
const NAME: &'static str = "RecoveryStatus";
fn value(&self) -> i32 {
*self as i32
}
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),
_ => ::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),
_ => ::std::option::Option::None
}
}
const VALUES: &'static [RecoveryStatus] = &[
RecoveryStatus::NoRecovery,
RecoveryStatus::InNormalRecovery,
RecoveryStatus::InDryRunRecovery,
RecoveryStatus::InUnlockRepeatedBackupRecovery,
];
}
impl ::protobuf::EnumFull for RecoveryStatus {
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.RecoveryStatus").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 RecoveryStatus {
fn default() -> Self {
RecoveryStatus::NoRecovery
}
}
impl RecoveryStatus {
pub(in super) fn generated_enum_descriptor_data() -> ::protobuf::reflect::GeneratedEnumDescriptorData {
::protobuf::reflect::GeneratedEnumDescriptorData::new::<RecoveryStatus>("Features.RecoveryStatus")
}
}
#[derive(Clone,Copy,PartialEq,Eq,Debug,Hash)]
// @@protoc_insertion_point(enum:hw.trezor.messages.management.Features.Capability)
pub enum Capability {
@ -7893,8 +7968,8 @@ impl RecoveryDevice {
pub fn kind(&self) -> recovery_device::RecoveryKind {
match self.kind {
Some(e) => e.enum_value_or(recovery_device::RecoveryKind::RecoveryKind_NormalRecovery),
None => recovery_device::RecoveryKind::RecoveryKind_NormalRecovery,
Some(e) => e.enum_value_or(recovery_device::RecoveryKind::NormalRecovery),
None => recovery_device::RecoveryKind::NormalRecovery,
}
}
@ -8206,12 +8281,12 @@ pub mod recovery_device {
#[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.RecoveryKind_NormalRecovery)
RecoveryKind_NormalRecovery = 0,
// @@protoc_insertion_point(enum_value:hw.trezor.messages.management.RecoveryDevice.RecoveryKind.RecoveryKind_DryRun)
RecoveryKind_DryRun = 1,
// @@protoc_insertion_point(enum_value:hw.trezor.messages.management.RecoveryDevice.RecoveryKind.RecoveryKind_UnlockRepeatedBackup)
RecoveryKind_UnlockRepeatedBackup = 2,
// @@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,
}
impl ::protobuf::Enum for RecoveryKind {
@ -8223,26 +8298,26 @@ pub mod recovery_device {
fn from_i32(value: i32) -> ::std::option::Option<RecoveryKind> {
match value {
0 => ::std::option::Option::Some(RecoveryKind::RecoveryKind_NormalRecovery),
1 => ::std::option::Option::Some(RecoveryKind::RecoveryKind_DryRun),
2 => ::std::option::Option::Some(RecoveryKind::RecoveryKind_UnlockRepeatedBackup),
0 => ::std::option::Option::Some(RecoveryKind::NormalRecovery),
1 => ::std::option::Option::Some(RecoveryKind::DryRun),
2 => ::std::option::Option::Some(RecoveryKind::UnlockRepeatedBackup),
_ => ::std::option::Option::None
}
}
fn from_str(str: &str) -> ::std::option::Option<RecoveryKind> {
match str {
"RecoveryKind_NormalRecovery" => ::std::option::Option::Some(RecoveryKind::RecoveryKind_NormalRecovery),
"RecoveryKind_DryRun" => ::std::option::Option::Some(RecoveryKind::RecoveryKind_DryRun),
"RecoveryKind_UnlockRepeatedBackup" => ::std::option::Option::Some(RecoveryKind::RecoveryKind_UnlockRepeatedBackup),
"NormalRecovery" => ::std::option::Option::Some(RecoveryKind::NormalRecovery),
"DryRun" => ::std::option::Option::Some(RecoveryKind::DryRun),
"UnlockRepeatedBackup" => ::std::option::Option::Some(RecoveryKind::UnlockRepeatedBackup),
_ => ::std::option::Option::None
}
}
const VALUES: &'static [RecoveryKind] = &[
RecoveryKind::RecoveryKind_NormalRecovery,
RecoveryKind::RecoveryKind_DryRun,
RecoveryKind::RecoveryKind_UnlockRepeatedBackup,
RecoveryKind::NormalRecovery,
RecoveryKind::DryRun,
RecoveryKind::UnlockRepeatedBackup,
];
}
@ -8260,7 +8335,7 @@ pub mod recovery_device {
impl ::std::default::Default for RecoveryKind {
fn default() -> Self {
RecoveryKind::RecoveryKind_NormalRecovery
RecoveryKind::NormalRecovery
}
}
@ -10667,7 +10742,7 @@ static file_descriptor_proto_data: &'static [u8] = b"\
\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\"\xfa\x13\n\x08Featur\
\x20\x01(\x08R\rderiveCardano\"\r\n\x0bGetFeatures\"\xa8\x15\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\
@ -10689,22 +10764,23 @@ static file_descriptor_proto_data: &'static [u8] = b"\
\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\rrecovery_mode\x18\x1d\x20\x01(\x08R\
\x0crecoveryMode\x12V\n\x0ccapabilities\x18\x1e\x20\x03(\x0e22.hw.trezor\
.messages.management.Features.CapabilityR\x0ccapabilities\x12J\n\x0bback\
up_type\x18\x1f\x20\x01(\x0e2).hw.trezor.messages.management.BackupTypeR\
\nbackupType\x12&\n\x0fsd_card_present\x18\x20\x20\x01(\x08R\rsdCardPres\
ent\x12#\n\rsd_protection\x18!\x20\x01(\x08R\x0csdProtection\x120\n\x14w\
ipe_code_protection\x18\"\x20\x01(\x08R\x12wipeCodeProtection\x12\x1d\n\
\nsession_id\x18#\x20\x01(\x0cR\tsessionId\x12=\n\x1bpassphrase_always_o\
n_device\x18$\x20\x01(\x08R\x18passphraseAlwaysOnDevice\x12T\n\rsafety_c\
hecks\x18%\x20\x01(\x0e2/.hw.trezor.messages.management.SafetyCheckLevel\
R\x0csafetyChecks\x12+\n\x12auto_lock_delay_ms\x18&\x20\x01(\rR\x0fautoL\
ockDelayMs\x12)\n\x10display_rotation\x18'\x20\x01(\rR\x0fdisplayRotatio\
n\x123\n\x15experimental_features\x18(\x20\x01(\x08R\x14experimentalFeat\
ures\x12\x12\n\x04busy\x18)\x20\x01(\x08R\x04busy\x12\\\n\x11homescreen_\
format\x18*\x20\x01(\x0e2/.hw.trezor.messages.management.HomescreenForma\
tR\x10homescreenFormat\x129\n\x19hide_passphrase_from_host\x18+\x20\x01(\
\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\
\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\
e_protection\x18\"\x20\x01(\x08R\x12wipeCodeProtection\x12\x1d\n\nsessio\
n_id\x18#\x20\x01(\x0cR\tsessionId\x12=\n\x1bpassphrase_always_on_device\
\x18$\x20\x01(\x08R\x18passphraseAlwaysOnDevice\x12T\n\rsafety_checks\
\x18%\x20\x01(\x0e2/.hw.trezor.messages.management.SafetyCheckLevelR\x0c\
safetyChecks\x12+\n\x12auto_lock_delay_ms\x18&\x20\x01(\rR\x0fautoLockDe\
layMs\x12)\n\x10display_rotation\x18'\x20\x01(\rR\x0fdisplayRotation\x12\
3\n\x15experimental_features\x18(\x20\x01(\x08R\x14experimentalFeatures\
\x12\x12\n\x04busy\x18)\x20\x01(\x08R\x04busy\x12\\\n\x11homescreen_form\
at\x18*\x20\x01(\x0e2/.hw.trezor.messages.management.HomescreenFormatR\
\x10homescreenFormat\x129\n\x19hide_passphrase_from_host\x18+\x20\x01(\
\x08R\x16hidePassphraseFromHost\x12%\n\x0einternal_model\x18,\x20\x01(\t\
R\rinternalModel\x12\x1d\n\nunit_color\x18-\x20\x01(\rR\tunitColor\x12!\
\n\x0cunit_btconly\x18.\x20\x01(\x08R\x0bunitBtconly\x12)\n\x10homescree\
@ -10712,92 +10788,94 @@ static file_descriptor_proto_data: &'static [u8] = b"\
\x180\x20\x01(\rR\x10homescreenHeight\x12+\n\x11bootloader_locked\x181\
\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\"\x84\x04\n\nCapability\x12\x1c\
\n\x12Capability_Bitcoin\x10\x01\x1a\x04\x80\xa6\x1d\x01\x12\x1b\n\x17Ca\
pability_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\x11Capability_Monero\x10\t\x12\x12\n\x0eC\
apability_NEM\x10\n\x12\x15\n\x11Capability_Ripple\x10\x0b\x12\x16\n\x12\
Capability_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\x17Capability_ShamirGroups\x10\x10\x1a\x04\
\x80\xa6\x1d\x01\x12$\n\x1aCapability_PassphraseEntry\x10\x11\x1a\x04\
\x80\xa6\x1d\x01\x12\x15\n\x11Capability_Solana\x10\x12\x12!\n\x17Capabi\
lity_Translations\x10\x13\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\"\x9b\x04\n\rApplySettings\
\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_passphrase\
\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\x0csaf\
etyChecks\x123\n\x15experimental_features\x18\n\x20\x01(\x08R\x14experim\
entalFeatures\x129\n\x19hide_passphrase_from_host\x18\x0b\x20\x01(\x08R\
\x16hidePassphraseFromHost\"T\n\x0eChangeLanguage\x12\x1f\n\x0bdata_leng\
th\x18\x01\x20\x02(\rR\ndataLength\x12!\n\x0cshow_display\x18\x02\x20\
\x01(\x08R\x0bshowDisplay\"Z\n\x16TranslationDataRequest\x12\x1f\n\x0bda\
ta_length\x18\x01\x20\x02(\rR\ndataLength\x12\x1f\n\x0bdata_offset\x18\
\x02\x20\x02(\rR\ndataOffset\"3\n\x12TranslationDataAck\x12\x1d\n\ndata_\
chunk\x18\x01\x20\x02(\x0cR\tdataChunk\"\"\n\nApplyFlags\x12\x14\n\x05fl\
ags\x18\x01\x20\x02(\rR\x05flags\"#\n\tChangePin\x12\x16\n\x06remove\x18\
\x01\x20\x01(\x08R\x06remove\"(\n\x0eChangeWipeCode\x12\x16\n\x06remove\
\x18\x01\x20\x01(\x08R\x06remove\"\xaa\x01\n\tSdProtect\x12]\n\toperatio\
n\x18\x01\x20\x02(\x0e2?.hw.trezor.messages.management.SdProtect.SdProte\
ctOperationTypeR\toperation\">\n\x16SdProtectOperationType\x12\x0b\n\x07\
DISABLE\x10\0\x12\n\n\x06ENABLE\x10\x01\x12\x0b\n\x07REFRESH\x10\x02\"O\
\n\x04Ping\x12\x1a\n\x07message\x18\x01\x20\x01(\t:\0R\x07message\x12+\n\
\x11button_protection\x18\x02\x20\x01(\x08R\x10buttonProtection\"\x08\n\
\x06Cancel\"\x20\n\nGetEntropy\x12\x12\n\x04size\x18\x01\x20\x02(\rR\x04\
size\"#\n\x07Entropy\x12\x18\n\x07entropy\x18\x01\x20\x02(\x0cR\x07entro\
py\"/\n\x0fGetFirmwareHash\x12\x1c\n\tchallenge\x18\x01\x20\x01(\x0cR\tc\
hallenge\"\"\n\x0cFirmwareHash\x12\x12\n\x04hash\x18\x01\x20\x02(\x0cR\
\x04hash\"2\n\x12AuthenticateDevice\x12\x1c\n\tchallenge\x18\x01\x20\x02\
(\x0cR\tchallenge\"U\n\x11AuthenticityProof\x12\"\n\x0ccertificates\x18\
\x01\x20\x03(\x0cR\x0ccertificates\x12\x1c\n\tsignature\x18\x02\x20\x02(\
\x0cR\tsignature\"\x0c\n\nWipeDevice\"\xad\x02\n\nLoadDevice\x12\x1c\n\t\
mnemonics\x18\x01\x20\x03(\tR\tmnemonics\x12\x10\n\x03pin\x18\x03\x20\
\x01(\tR\x03pin\x123\n\x15passphrase_protection\x18\x04\x20\x01(\x08R\
\x14passphraseProtection\x12\x1e\n\x08language\x18\x05\x20\x01(\tR\x08la\
nguageB\x02\x18\x01\x12\x14\n\x05label\x18\x06\x20\x01(\tR\x05label\x12#\
\n\rskip_checksum\x18\x07\x20\x01(\x08R\x0cskipChecksum\x12\x1f\n\x0bu2f\
_counter\x18\x08\x20\x01(\rR\nu2fCounter\x12!\n\x0cneeds_backup\x18\t\
\x20\x01(\x08R\x0bneedsBackup\x12\x1b\n\tno_backup\x18\n\x20\x01(\x08R\
\x08noBackup\"\x99\x03\n\x0bResetDevice\x12%\n\x0edisplay_random\x18\x01\
\x20\x01(\x08R\rdisplayRandom\x12\x1f\n\x08strength\x18\x02\x20\x01(\r:\
\x03256R\x08strength\x123\n\x15passphrase_protection\x18\x03\x20\x01(\
\x08R\x14passphraseProtection\x12%\n\x0epin_protection\x18\x04\x20\x01(\
\x08R\rpinProtection\x12\x1e\n\x08language\x18\x05\x20\x01(\tR\x08langua\
geB\x02\x18\x01\x12\x14\n\x05label\x18\x06\x20\x01(\tR\x05label\x12\x1f\
\n\x0bu2f_counter\x18\x07\x20\x01(\rR\nu2fCounter\x12\x1f\n\x0bskip_back\
up\x18\x08\x20\x01(\x08R\nskipBackup\x12\x1b\n\tno_backup\x18\t\x20\x01(\
\x08R\x08noBackup\x12Q\n\x0bbackup_type\x18\n\x20\x01(\x0e2).hw.trezor.m\
essages.management.BackupType:\x05Bip39R\nbackupType\"\xe5\x01\n\x0cBack\
upDevice\x12'\n\x0fgroup_threshold\x18\x01\x20\x01(\rR\x0egroupThreshold\
\x12O\n\x06groups\x18\x02\x20\x03(\x0b27.hw.trezor.messages.management.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\"\x80\x05\
\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\x12N\n\
\x04kind\x18\n\x20\x01(\x0e2:.hw.trezor.messages.management.RecoveryDevi\
ce.RecoveryKindR\x04kind\"Z\n\x12RecoveryDeviceType\x12%\n!RecoveryDevic\
eType_ScrambledWords\x10\0\x12\x1d\n\x19RecoveryDeviceType_Matrix\x10\
\x01\"o\n\x0cRecoveryKind\x12\x1f\n\x1bRecoveryKind_NormalRecovery\x10\0\
\x12\x17\n\x13RecoveryKind_DryRun\x10\x01\x12%\n!RecoveryKind_UnlockRepe\
atedBackup\x10\x02\"\xc5\x01\n\x0bWordRequest\x12N\n\x04type\x18\x01\x20\
ckaging\x183\x20\x01(\rR\runitPackaging\"p\n\x0eRecoveryStatus\x12\x0e\n\
\nNoRecovery\x10\0\x12\x14\n\x10InNormalRecovery\x10\x01\x12\x14\n\x10In\
DryRunRecovery\x10\x02\x12\"\n\x1eInUnlockRepeatedBackupRecovery\x10\x03\
\"\x84\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\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\"\
\x9b\x04\n\rApplySettings\x12\x1e\n\x08language\x18\x01\x20\x01(\tR\x08l\
anguageB\x02\x18\x01\x12\x14\n\x05label\x18\x02\x20\x01(\tR\x05label\x12\
%\n\x0euse_passphrase\x18\x03\x20\x01(\x08R\rusePassphrase\x12\x1e\n\nho\
mescreen\x18\x04\x20\x01(\x0cR\nhomescreen\x120\n\x12_passphrase_source\
\x18\x05\x20\x01(\rR\x10PassphraseSourceB\x02\x18\x01\x12+\n\x12auto_loc\
k_delay_ms\x18\x06\x20\x01(\rR\x0fautoLockDelayMs\x12)\n\x10display_rota\
tion\x18\x07\x20\x01(\rR\x0fdisplayRotation\x12=\n\x1bpassphrase_always_\
on_device\x18\x08\x20\x01(\x08R\x18passphraseAlwaysOnDevice\x12T\n\rsafe\
ty_checks\x18\t\x20\x01(\x0e2/.hw.trezor.messages.management.SafetyCheck\
LevelR\x0csafetyChecks\x123\n\x15experimental_features\x18\n\x20\x01(\
\x08R\x14experimentalFeatures\x129\n\x19hide_passphrase_from_host\x18\
\x0b\x20\x01(\x08R\x16hidePassphraseFromHost\"T\n\x0eChangeLanguage\x12\
\x1f\n\x0bdata_length\x18\x01\x20\x02(\rR\ndataLength\x12!\n\x0cshow_dis\
play\x18\x02\x20\x01(\x08R\x0bshowDisplay\"Z\n\x16TranslationDataRequest\
\x12\x1f\n\x0bdata_length\x18\x01\x20\x02(\rR\ndataLength\x12\x1f\n\x0bd\
ata_offset\x18\x02\x20\x02(\rR\ndataOffset\"3\n\x12TranslationDataAck\
\x12\x1d\n\ndata_chunk\x18\x01\x20\x02(\x0cR\tdataChunk\"\"\n\nApplyFlag\
s\x12\x14\n\x05flags\x18\x01\x20\x02(\rR\x05flags\"#\n\tChangePin\x12\
\x16\n\x06remove\x18\x01\x20\x01(\x08R\x06remove\"(\n\x0eChangeWipeCode\
\x12\x16\n\x06remove\x18\x01\x20\x01(\x08R\x06remove\"\xaa\x01\n\tSdProt\
ect\x12]\n\toperation\x18\x01\x20\x02(\x0e2?.hw.trezor.messages.manageme\
nt.SdProtect.SdProtectOperationTypeR\toperation\">\n\x16SdProtectOperati\
onType\x12\x0b\n\x07DISABLE\x10\0\x12\n\n\x06ENABLE\x10\x01\x12\x0b\n\
\x07REFRESH\x10\x02\"O\n\x04Ping\x12\x1a\n\x07message\x18\x01\x20\x01(\t\
:\0R\x07message\x12+\n\x11button_protection\x18\x02\x20\x01(\x08R\x10but\
tonProtection\"\x08\n\x06Cancel\"\x20\n\nGetEntropy\x12\x12\n\x04size\
\x18\x01\x20\x02(\rR\x04size\"#\n\x07Entropy\x12\x18\n\x07entropy\x18\
\x01\x20\x02(\x0cR\x07entropy\"/\n\x0fGetFirmwareHash\x12\x1c\n\tchallen\
ge\x18\x01\x20\x01(\x0cR\tchallenge\"\"\n\x0cFirmwareHash\x12\x12\n\x04h\
ash\x18\x01\x20\x02(\x0cR\x04hash\"2\n\x12AuthenticateDevice\x12\x1c\n\t\
challenge\x18\x01\x20\x02(\x0cR\tchallenge\"U\n\x11AuthenticityProof\x12\
\"\n\x0ccertificates\x18\x01\x20\x03(\x0cR\x0ccertificates\x12\x1c\n\tsi\
gnature\x18\x02\x20\x02(\x0cR\tsignature\"\x0c\n\nWipeDevice\"\xad\x02\n\
\nLoadDevice\x12\x1c\n\tmnemonics\x18\x01\x20\x03(\tR\tmnemonics\x12\x10\
\n\x03pin\x18\x03\x20\x01(\tR\x03pin\x123\n\x15passphrase_protection\x18\
\x04\x20\x01(\x08R\x14passphraseProtection\x12\x1e\n\x08language\x18\x05\
\x20\x01(\tR\x08languageB\x02\x18\x01\x12\x14\n\x05label\x18\x06\x20\x01\
(\tR\x05label\x12#\n\rskip_checksum\x18\x07\x20\x01(\x08R\x0cskipChecksu\
m\x12\x1f\n\x0bu2f_counter\x18\x08\x20\x01(\rR\nu2fCounter\x12!\n\x0cnee\
ds_backup\x18\t\x20\x01(\x08R\x0bneedsBackup\x12\x1b\n\tno_backup\x18\n\
\x20\x01(\x08R\x08noBackup\"\x99\x03\n\x0bResetDevice\x12%\n\x0edisplay_\
random\x18\x01\x20\x01(\x08R\rdisplayRandom\x12\x1f\n\x08strength\x18\
\x02\x20\x01(\r:\x03256R\x08strength\x123\n\x15passphrase_protection\x18\
\x03\x20\x01(\x08R\x14passphraseProtection\x12%\n\x0epin_protection\x18\
\x04\x20\x01(\x08R\rpinProtection\x12\x1e\n\x08language\x18\x05\x20\x01(\
\tR\x08languageB\x02\x18\x01\x12\x14\n\x05label\x18\x06\x20\x01(\tR\x05l\
abel\x12\x1f\n\x0bu2f_counter\x18\x07\x20\x01(\rR\nu2fCounter\x12\x1f\n\
\x0bskip_backup\x18\x08\x20\x01(\x08R\nskipBackup\x12\x1b\n\tno_backup\
\x18\t\x20\x01(\x08R\x08noBackup\x12Q\n\x0bbackup_type\x18\n\x20\x01(\
\x0e2).hw.trezor.messages.management.BackupType:\x05Bip39R\nbackupType\"\
\xe5\x01\n\x0cBackupDevice\x12'\n\x0fgroup_threshold\x18\x01\x20\x01(\rR\
\x0egroupThreshold\x12O\n\x06groups\x18\x02\x20\x03(\x0b27.hw.trezor.mes\
sages.management.BackupDevice.Slip39GroupR\x06groups\x1a[\n\x0bSlip39Gro\
up\x12)\n\x10member_threshold\x18\x01\x20\x02(\rR\x0fmemberThreshold\x12\
!\n\x0cmember_count\x18\x02\x20\x02(\rR\x0bmemberCount\"\x10\n\x0eEntrop\
yRequest\"&\n\nEntropyAck\x12\x18\n\x07entropy\x18\x01\x20\x02(\x0cR\x07\
entropy\"\xe9\x04\n\x0eRecoveryDevice\x12\x1d\n\nword_count\x18\x01\x20\
\x01(\rR\twordCount\x123\n\x15passphrase_protection\x18\x02\x20\x01(\x08\
R\x14passphraseProtection\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\x10e\
nforce_wordlist\x18\x06\x20\x01(\x08R\x0fenforceWordlist\x12T\n\x04type\
\x18\x08\x20\x01(\x0e2@.hw.trezor.messages.management.RecoveryDevice.Rec\
overyDeviceTypeR\x04type\x12\x1f\n\x0bu2f_counter\x18\t\x20\x01(\rR\nu2f\
Counter\x12^\n\x04kind\x18\n\x20\x01(\x0e2:.hw.trezor.messages.managemen\
t.RecoveryDevice.RecoveryKind:\x0eNormalRecoveryR\x04kind\"Z\n\x12Recove\
ryDeviceType\x12%\n!RecoveryDeviceType_ScrambledWords\x10\0\x12\x1d\n\
\x19RecoveryDeviceType_Matrix\x10\x01\"H\n\x0cRecoveryKind\x12\x12\n\x0e\
NormalRecovery\x10\0\x12\n\n\x06DryRun\x10\x01\x12\x18\n\x14UnlockRepeat\
edBackup\x10\x02\"\xc5\x01\n\x0bWordRequest\x12N\n\x04type\x18\x01\x20\
\x02(\x0e2:.hw.trezor.messages.management.WordRequest.WordRequestTypeR\
\x04type\"f\n\x0fWordRequestType\x12\x19\n\x15WordRequestType_Plain\x10\
\0\x12\x1b\n\x17WordRequestType_Matrix9\x10\x01\x12\x1b\n\x17WordRequest\
@ -10887,10 +10965,11 @@ pub fn file_descriptor() -> &'static ::protobuf::reflect::FileDescriptor {
messages.push(ShowDeviceTutorial::generated_message_descriptor_data());
messages.push(UnlockBootloader::generated_message_descriptor_data());
messages.push(backup_device::Slip39Group::generated_message_descriptor_data());
let mut enums = ::std::vec::Vec::with_capacity(9);
let mut enums = ::std::vec::Vec::with_capacity(10);
enums.push(BackupType::generated_enum_descriptor_data());
enums.push(SafetyCheckLevel::generated_enum_descriptor_data());
enums.push(HomescreenFormat::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());

@ -46,7 +46,7 @@ def enter_word(
raise ValueError("Unknown model")
def confirm_recovery(debug: "DebugLink", title="recovery__title") -> None:
def confirm_recovery(debug: "DebugLink", title: str = "recovery__title") -> None:
layout = debug.wait_layout()
TR.assert_equals(layout.title(), title)
if debug.model in (models.T2T1, models.T3T1):
@ -112,7 +112,7 @@ def enter_share(
def enter_shares(
debug: "DebugLink",
shares: list[str],
after_layout_text="recovery__wallet_recovered",
after_layout_text: str = "recovery__wallet_recovered",
) -> None:
TR.assert_in(debug.read_layout().text_content(), "recovery__enter_any_share")
for index, share in enumerate(shares):
@ -131,8 +131,8 @@ def enter_seed(
debug: "DebugLink",
seed_words: list[str],
is_slip39=False,
prepare_layout_text="recovery__enter_backup",
after_layout_text="recovery__wallet_recovered",
prepare_layout_text: str = "recovery__enter_backup",
after_layout_text: str = "recovery__wallet_recovered",
) -> None:
prepare_enter_seed(debug, prepare_layout_text)
@ -188,7 +188,7 @@ def enter_seed_previous_correct(
def prepare_enter_seed(
debug: "DebugLink", layout_text="recovery__enter_backup"
debug: "DebugLink", layout_text: str = "recovery__enter_backup"
) -> None:
TR.assert_in(debug.read_layout().text_content(), layout_text)
if debug.model in (models.T2T1, models.T3T1):

@ -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_mode is False
assert features.recovery_status == messages.RecoveryStatus.NoRecovery
@pytest.mark.setup_client(uninitialized=True)

@ -97,12 +97,12 @@ def test_repeated_backup(
assert features.initialized is True
assert features.needs_backup is False
assert features.no_backup is False
assert features.recovery_mode is False
assert features.recovery_status == messages.RecoveryStatus.NoRecovery
# run recovery to unlock backup
device_handler.run(
device.recover,
unlock_repeated_backup=True,
recovery_kind=messages.RecoveryKind.UnlockRepeatedBackup,
)
recovery.confirm_recovery(debug, "recovery__title_unlock_repeated_backup")
@ -127,7 +127,7 @@ def test_repeated_backup(
assert features.initialized is True
assert features.needs_backup is False
assert features.no_backup is False
assert features.recovery_mode is True
assert features.recovery_status == messages.RecoveryStatus.InUnlockRepeatedBackupRecovery
# at this point, the backup is unlocked...
@ -170,12 +170,12 @@ def test_repeated_backup(
assert features.initialized is True
assert features.needs_backup is False
assert features.no_backup is False
assert features.recovery_mode is False
assert features.recovery_status == messages.RecoveryStatus.NoRecovery
# try to unlock backup again...
device_handler.run(
device.recover,
unlock_repeated_backup=True,
recovery_kind=messages.RecoveryKind.UnlockRepeatedBackup,
)
recovery.confirm_recovery(debug, "recovery__title_unlock_repeated_backup")
@ -194,7 +194,7 @@ def test_repeated_backup(
assert features.initialized is True
assert features.needs_backup is False
assert features.no_backup is False
assert features.recovery_mode is True
assert features.recovery_status == messages.RecoveryStatus.InUnlockRepeatedBackupRecovery
# but if we cancel the backup at this point...
reset.cancel_backup(debug)
@ -205,4 +205,4 @@ def test_repeated_backup(
assert features.initialized is True
assert features.needs_backup is False
assert features.no_backup is False
assert features.recovery_mode is False
assert features.recovery_status == messages.RecoveryStatus.NoRecovery

@ -150,6 +150,6 @@ def test_bad_parameters(client: Client, field_name: str, field_value: Any):
setattr(msg, field_name, field_value)
with pytest.raises(
exceptions.TrezorFailure,
match="Forbidden field set in DryRun or UnlockRepeatedBackup",
match="Forbidden field set in dry-run",
):
client.call(msg)

@ -49,7 +49,7 @@ def test_repeated_backup(client: Client):
with client:
IF = InputFlowSlip39BasicRecoveryDryRun(client, mnemonics[:3])
client.set_input_flow(IF.get())
ret = device.recover(client, unlock_repeated_backup=True)
ret = device.recover(client, recovery_kind=messages.RecoveryKind.UnlockRepeatedBackup)
assert ret == messages.Success(message="Backup unlocked")
# we can now perform another backup

@ -15,6 +15,7 @@
# If not, see <https://www.gnu.org/licenses/lgpl-3.0.html>.
from trezorlib import device
from trezorlib.messages import RecoveryStatus
from trezorlib.debuglink import DebugLink
from .. import buttons
@ -38,7 +39,7 @@ def test_abort(core_emulator: Emulator):
debug = device_handler.debuglink()
features = device_handler.features()
assert features.recovery_mode is False
assert features.recovery_status == RecoveryStatus.NoRecovery
device_handler.run(device.recover, pin_protection=False)
@ -50,7 +51,7 @@ def test_abort(core_emulator: Emulator):
debug = _restart(device_handler, core_emulator)
features = device_handler.features()
assert features.recovery_mode is True
assert features.recovery_status == RecoveryStatus.InNormalRecovery
# no waiting for layout because layout doesn't change
assert "number of words" in debug.read_layout().text_content()
@ -66,7 +67,7 @@ def test_abort(core_emulator: Emulator):
assert layout.main_component() == "Homescreen"
features = device_handler.features()
assert features.recovery_mode is False
assert features.recovery_status == RecoveryStatus.NoRecovery
@core_only
@ -76,7 +77,7 @@ def test_recovery_single_reset(core_emulator: Emulator):
features = device_handler.features()
assert features.initialized is False
assert features.recovery_mode is False
assert features.recovery_status == RecoveryStatus.NoRecovery
device_handler.run(device.recover, pin_protection=False)
@ -86,7 +87,7 @@ def test_recovery_single_reset(core_emulator: Emulator):
debug = _restart(device_handler, core_emulator)
features = device_handler.features()
assert features.recovery_mode is True
assert features.recovery_status == RecoveryStatus.InNormalRecovery
# we need to enter the number of words again, that's a feature
recovery.select_number_of_words(debug, wait=False)
@ -95,7 +96,7 @@ def test_recovery_single_reset(core_emulator: Emulator):
features = device_handler.features()
assert features.initialized is True
assert features.recovery_mode is False
assert features.recovery_status == RecoveryStatus.NoRecovery
@core_only
@ -113,7 +114,7 @@ def test_recovery_on_old_wallet(core_emulator: Emulator):
features = device_handler.features()
assert features.initialized is False
assert features.recovery_mode is False
assert features.recovery_status == RecoveryStatus.NoRecovery
# enter recovery mode
device_handler.run(device.recover, pin_protection=False)
@ -123,7 +124,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_mode is True
assert features.recovery_status == RecoveryStatus.InNormalRecovery
# enter number of words
recovery.select_number_of_words(debug, wait=False)
@ -162,7 +163,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_mode is False
assert features.recovery_status == RecoveryStatus.NoRecovery
@core_only
@ -186,7 +187,7 @@ def test_recovery_multiple_resets(core_emulator: Emulator):
features = device_handler.features()
assert features.initialized is False
assert features.recovery_mode is False
assert features.recovery_status == RecoveryStatus.NoRecovery
# start device and recovery
device_handler.run(device.recover, pin_protection=False)
@ -199,7 +200,7 @@ def test_recovery_multiple_resets(core_emulator: Emulator):
# restart
debug = _restart(device_handler, core_emulator)
features = device_handler.features()
assert features.recovery_mode is True
assert features.recovery_status == RecoveryStatus.InNormalRecovery
# enter the number of words again, that's a feature!
recovery.select_number_of_words(debug, wait=False)
@ -211,4 +212,4 @@ def test_recovery_multiple_resets(core_emulator: Emulator):
features = device_handler.features()
assert features.initialized is True
assert features.recovery_mode is False
assert features.recovery_status == RecoveryStatus.NoRecovery

@ -20,7 +20,7 @@ from typing import TYPE_CHECKING, List, Optional
import pytest
from trezorlib import btc, debuglink, device, exceptions, fido, models
from trezorlib.messages import BackupType
from trezorlib.messages import BackupType, RecoveryStatus
from trezorlib.tools import H_
from ..common import MNEMONIC_SLIP39_BASIC_20_3of6, MNEMONIC_SLIP39_BASIC_20_3of6_SECRET
@ -287,7 +287,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_mode is False
assert emu.client.features.recovery_status == RecoveryStatus.NoRecovery
emu.client.watch_layout(True)
debug = device_handler.debuglink()
@ -308,7 +308,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_mode
assert emu.client.features.recovery_status == RecoveryStatus.InNormalRecovery
debug = emu.client.debug
emu.client.watch_layout(True)

Loading…
Cancel
Save