mirror of
https://github.com/trezor/trezor-firmware.git
synced 2025-03-03 08:46:05 +00:00
feat(core/mercury): impl flow_request_passphrase
This commit replaces request_passphrase with flow_request_passphrase. The added benefit is that the user is prompted for confirmation if they want to proceed with an empty passphrase.
This commit is contained in:
parent
60ad7219fe
commit
50dc265162
1
core/.changelog.d/4054.added
Normal file
1
core/.changelog.d/4054.added
Normal file
@ -0,0 +1 @@
|
||||
[T3T1] Added reassuring screen when entering empty passphrase
|
@ -248,6 +248,7 @@ static void _librust_qstrs(void) {
|
||||
MP_QSTR_flow_get_address;
|
||||
MP_QSTR_flow_prompt_backup;
|
||||
MP_QSTR_flow_request_number;
|
||||
MP_QSTR_flow_request_passphrase;
|
||||
MP_QSTR_flow_show_share_words;
|
||||
MP_QSTR_flow_warning_hi_prio;
|
||||
MP_QSTR_get_language;
|
||||
@ -346,6 +347,7 @@ static void _librust_qstrs(void) {
|
||||
MP_QSTR_paint;
|
||||
MP_QSTR_passphrase__access_wallet;
|
||||
MP_QSTR_passphrase__always_on_device;
|
||||
MP_QSTR_passphrase__continue_with_empty_passphrase;
|
||||
MP_QSTR_passphrase__from_host_not_shown;
|
||||
MP_QSTR_passphrase__hide;
|
||||
MP_QSTR_passphrase__next_screen_will_show_passphrase;
|
||||
|
@ -1357,6 +1357,7 @@ pub enum TranslatedString {
|
||||
words__title_done = 956, // "Done"
|
||||
reset__slip39_checklist_more_info_threshold = 957, // "The threshold sets the minumum number of shares needed to recover your wallet."
|
||||
reset__slip39_checklist_more_info_threshold_example_template = 958, // "If you set {0} out of {1} shares, you'll need {2} backup shares to recover your wallet."
|
||||
passphrase__continue_with_empty_passphrase = 959, // "Continue with empty passphrase?"
|
||||
}
|
||||
|
||||
impl TranslatedString {
|
||||
@ -2708,6 +2709,7 @@ impl TranslatedString {
|
||||
Self::words__title_done => "Done",
|
||||
Self::reset__slip39_checklist_more_info_threshold => "The threshold sets the minumum number of shares needed to recover your wallet.",
|
||||
Self::reset__slip39_checklist_more_info_threshold_example_template => "If you set {0} out of {1} shares, you'll need {2} backup shares to recover your wallet.",
|
||||
Self::passphrase__continue_with_empty_passphrase => "Continue with empty passphrase?",
|
||||
}
|
||||
}
|
||||
|
||||
@ -4060,6 +4062,7 @@ impl TranslatedString {
|
||||
Qstr::MP_QSTR_words__title_done => Some(Self::words__title_done),
|
||||
Qstr::MP_QSTR_reset__slip39_checklist_more_info_threshold => Some(Self::reset__slip39_checklist_more_info_threshold),
|
||||
Qstr::MP_QSTR_reset__slip39_checklist_more_info_threshold_example_template => Some(Self::reset__slip39_checklist_more_info_threshold_example_template),
|
||||
Qstr::MP_QSTR_passphrase__continue_with_empty_passphrase => Some(Self::passphrase__continue_with_empty_passphrase),
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
|
@ -1,5 +1,5 @@
|
||||
use crate::{
|
||||
strutil::TString,
|
||||
strutil::{ShortString, TString},
|
||||
translations::TR,
|
||||
ui::{
|
||||
component::{
|
||||
@ -26,7 +26,7 @@ use core::cell::Cell;
|
||||
use num_traits::ToPrimitive;
|
||||
|
||||
pub enum PassphraseKeyboardMsg {
|
||||
Confirmed,
|
||||
Confirmed(ShortString),
|
||||
Cancelled,
|
||||
}
|
||||
|
||||
|
@ -8,6 +8,7 @@ pub mod continue_recovery;
|
||||
pub mod get_address;
|
||||
pub mod prompt_backup;
|
||||
pub mod request_number;
|
||||
pub mod request_passphrase;
|
||||
pub mod set_brightness;
|
||||
pub mod show_share_words;
|
||||
pub mod show_tutorial;
|
||||
@ -25,6 +26,7 @@ pub use continue_recovery::new_continue_recovery;
|
||||
pub use get_address::GetAddress;
|
||||
pub use prompt_backup::PromptBackup;
|
||||
pub use request_number::RequestNumber;
|
||||
pub use request_passphrase::RequestPassphrase;
|
||||
pub use set_brightness::SetBrightness;
|
||||
pub use show_share_words::ShowShareWords;
|
||||
pub use show_tutorial::ShowTutorial;
|
||||
|
@ -4,10 +4,9 @@ use super::{
|
||||
component::{
|
||||
AddressDetails, Bip39Input, Button, CancelConfirmMsg, CancelInfoConfirmMsg,
|
||||
CoinJoinProgress, FidoConfirm, FidoMsg, Frame, FrameMsg, Homescreen, HomescreenMsg,
|
||||
Lockscreen, MnemonicInput, MnemonicKeyboard, MnemonicKeyboardMsg, PassphraseKeyboard,
|
||||
PassphraseKeyboardMsg, PinKeyboard, PinKeyboardMsg, Progress, PromptScreen,
|
||||
SelectWordCount, SelectWordCountMsg, Slip39Input, StatusScreen, SwipeUpScreen,
|
||||
SwipeUpScreenMsg, VerticalMenu, VerticalMenuChoiceMsg,
|
||||
Lockscreen, MnemonicInput, MnemonicKeyboard, MnemonicKeyboardMsg, PinKeyboard,
|
||||
PinKeyboardMsg, Progress, PromptScreen, SelectWordCount, SelectWordCountMsg, Slip39Input,
|
||||
StatusScreen, SwipeUpScreen, SwipeUpScreenMsg, VerticalMenu, VerticalMenuChoiceMsg,
|
||||
},
|
||||
flow, theme,
|
||||
};
|
||||
@ -124,15 +123,6 @@ impl ComponentMsgObj for PinKeyboard<'_> {
|
||||
}
|
||||
}
|
||||
|
||||
impl ComponentMsgObj for PassphraseKeyboard {
|
||||
fn msg_try_into_obj(&self, msg: Self::Msg) -> Result<Obj, Error> {
|
||||
match msg {
|
||||
PassphraseKeyboardMsg::Confirmed => self.passphrase().try_into(),
|
||||
PassphraseKeyboardMsg::Cancelled => Ok(CANCELLED.as_obj()),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<T> ComponentMsgObj for MnemonicKeyboard<T>
|
||||
where
|
||||
T: MnemonicInput,
|
||||
@ -954,16 +944,6 @@ extern "C" fn new_request_pin(n_args: usize, args: *const Obj, kwargs: *mut Map)
|
||||
unsafe { util::try_with_args_and_kwargs(n_args, args, kwargs, block) }
|
||||
}
|
||||
|
||||
extern "C" fn new_request_passphrase(n_args: usize, args: *const Obj, kwargs: *mut Map) -> Obj {
|
||||
let block = move |_args: &[Obj], kwargs: &Map| {
|
||||
let _prompt: TString = kwargs.get(Qstr::MP_QSTR_prompt)?.try_into()?;
|
||||
let _max_len: u32 = kwargs.get(Qstr::MP_QSTR_max_len)?.try_into()?;
|
||||
let obj = LayoutObj::new(PassphraseKeyboard::new())?;
|
||||
Ok(obj.into())
|
||||
};
|
||||
unsafe { util::try_with_args_and_kwargs(n_args, args, kwargs, block) }
|
||||
}
|
||||
|
||||
extern "C" fn new_request_bip39(n_args: usize, args: *const Obj, kwargs: *mut Map) -> Obj {
|
||||
let block = move |_args: &[Obj], kwargs: &Map| {
|
||||
let prompt: TString = kwargs.get(Qstr::MP_QSTR_prompt)?.try_into()?;
|
||||
@ -1570,13 +1550,13 @@ pub static mp_module_trezorui2: Module = obj_module! {
|
||||
/// """Request pin on device."""
|
||||
Qstr::MP_QSTR_request_pin => obj_fn_kw!(0, new_request_pin).as_obj(),
|
||||
|
||||
/// def request_passphrase(
|
||||
/// def flow_request_passphrase(
|
||||
/// *,
|
||||
/// prompt: str,
|
||||
/// max_len: int,
|
||||
/// ) -> LayoutObj[str | UiResult]:
|
||||
/// """Passphrase input keyboard."""
|
||||
Qstr::MP_QSTR_request_passphrase => obj_fn_kw!(0, new_request_passphrase).as_obj(),
|
||||
Qstr::MP_QSTR_flow_request_passphrase => obj_fn_kw!(0, flow::request_passphrase::new_request_passphrase).as_obj(),
|
||||
|
||||
/// def request_bip39(
|
||||
/// *,
|
||||
|
@ -349,7 +349,7 @@ def request_pin(
|
||||
|
||||
|
||||
# rust/src/ui/model_mercury/layout.rs
|
||||
def request_passphrase(
|
||||
def flow_request_passphrase(
|
||||
*,
|
||||
prompt: str,
|
||||
max_len: int,
|
||||
|
@ -487,6 +487,7 @@ class TR:
|
||||
nem__unknown_mosaic: str = "Unknown mosaic!"
|
||||
passphrase__access_wallet: str = "Access passphrase wallet?"
|
||||
passphrase__always_on_device: str = "Always enter your passphrase on Trezor?"
|
||||
passphrase__continue_with_empty_passphrase: str = "Continue with empty passphrase?"
|
||||
passphrase__from_host_not_shown: str = "Passphrase provided by host will be used but will not be displayed due to the device settings."
|
||||
passphrase__hide: str = "Hide passphrase coming from host?"
|
||||
passphrase__next_screen_will_show_passphrase: str = "The next screen shows your passphrase."
|
||||
|
@ -1374,7 +1374,7 @@ def show_wait_text(message: str) -> None:
|
||||
async def request_passphrase_on_device(max_len: int) -> str:
|
||||
result = await interact(
|
||||
RustLayout(
|
||||
trezorui2.request_passphrase(
|
||||
trezorui2.flow_request_passphrase(
|
||||
prompt=TR.passphrase__title_enter, max_len=max_len
|
||||
)
|
||||
),
|
||||
@ -1384,8 +1384,18 @@ async def request_passphrase_on_device(max_len: int) -> str:
|
||||
if result is CANCELLED:
|
||||
raise ActionCancelled("Passphrase entry cancelled")
|
||||
|
||||
assert isinstance(result, str)
|
||||
return result
|
||||
if __debug__:
|
||||
if not isinstance(result, tuple):
|
||||
# TODO: DebugLink problem, better comment or solution?
|
||||
result = (CONFIRMED, str(result))
|
||||
|
||||
status, value = result
|
||||
if status == CONFIRMED:
|
||||
assert isinstance(value, str)
|
||||
return value
|
||||
else:
|
||||
# flow_request_pin returns either CANCELLED or (CONFIRMED, str) so this branch shouldn't be taken
|
||||
raise ActionCancelled("Passphrase entry cancelled")
|
||||
|
||||
|
||||
async def request_pin_on_device(
|
||||
|
@ -489,6 +489,7 @@
|
||||
"nem__unknown_mosaic": "Unknown mosaic!",
|
||||
"passphrase__access_wallet": "Access passphrase wallet?",
|
||||
"passphrase__always_on_device": "Always enter your passphrase on Trezor?",
|
||||
"passphrase__continue_with_empty_passphrase": "Continue with empty passphrase?",
|
||||
"passphrase__from_host_not_shown": "Passphrase provided by host will be used but will not be displayed due to the device settings.",
|
||||
"passphrase__wallet": "Passphrase wallet",
|
||||
"passphrase__hide": "Hide passphrase coming from host?",
|
||||
|
@ -957,5 +957,6 @@
|
||||
"955": "brightness__change_title",
|
||||
"956": "words__title_done",
|
||||
"957": "reset__slip39_checklist_more_info_threshold",
|
||||
"958": "reset__slip39_checklist_more_info_threshold_example_template"
|
||||
"958": "reset__slip39_checklist_more_info_threshold_example_template",
|
||||
"959": "passphrase__continue_with_empty_passphrase"
|
||||
}
|
||||
|
@ -13,6 +13,20 @@ def grid(dim: int, grid_cells: int, cell: int) -> int:
|
||||
return cell * step + ofs
|
||||
|
||||
|
||||
def grid35(x: int, y: int) -> Coords:
|
||||
return grid(DISPLAY_WIDTH, 3, x), grid(DISPLAY_HEIGHT, 5, y)
|
||||
|
||||
|
||||
def grid34(x: int, y: int) -> Coords:
|
||||
return grid(DISPLAY_WIDTH, 3, x), grid(DISPLAY_HEIGHT, 4, y)
|
||||
|
||||
|
||||
def _grid34_from_index(idx: int) -> Coords:
|
||||
grid_x = idx % 3
|
||||
grid_y = idx // 3 + 1 # first line is empty
|
||||
return grid34(grid_x, grid_y)
|
||||
|
||||
|
||||
LEFT = grid(DISPLAY_WIDTH, 3, 0)
|
||||
MID = grid(DISPLAY_WIDTH, 3, 1)
|
||||
RIGHT = grid(DISPLAY_WIDTH, 3, 2)
|
||||
@ -31,6 +45,9 @@ CORNER_BUTTON = (215, 25)
|
||||
CONFIRM_WORD = (MID, TOP)
|
||||
TOP_ROW = (MID, TOP)
|
||||
|
||||
MERCURY_YES = grid34(2, 2)
|
||||
MERCURY_NO = grid34(0, 2)
|
||||
|
||||
|
||||
def reset_minus(model_internal_name: str) -> Coords:
|
||||
RESET_MINUS_T3T1 = (LEFT, grid(DISPLAY_HEIGHT, 5, 3))
|
||||
@ -109,20 +126,6 @@ def pin_passphrase_grid(idx: int) -> Coords:
|
||||
return grid35(grid_x, grid_y)
|
||||
|
||||
|
||||
def grid35(x: int, y: int) -> Coords:
|
||||
return grid(DISPLAY_WIDTH, 3, x), grid(DISPLAY_HEIGHT, 5, y)
|
||||
|
||||
|
||||
def grid34(x: int, y: int) -> Coords:
|
||||
return grid(DISPLAY_WIDTH, 3, x), grid(DISPLAY_HEIGHT, 4, y)
|
||||
|
||||
|
||||
def _grid34_from_index(idx: int) -> Coords:
|
||||
grid_x = idx % 3
|
||||
grid_y = idx // 3 + 1 # first line is empty
|
||||
return grid34(grid_x, grid_y)
|
||||
|
||||
|
||||
def type_word(word: str, is_slip39: bool = False) -> Iterator[Coords]:
|
||||
if is_slip39:
|
||||
yield from _type_word_slip39(word)
|
||||
|
@ -168,8 +168,11 @@ def input_passphrase(debug: "DebugLink", passphrase: str, check: bool = True) ->
|
||||
|
||||
def enter_passphrase(debug: "DebugLink") -> None:
|
||||
"""Enter a passphrase"""
|
||||
coords = buttons.grid35(2, 0) # top-right corner
|
||||
is_empty: bool = len(debug.read_layout().passphrase()) == 0
|
||||
coords = buttons.CORNER_BUTTON # top-right corner
|
||||
debug.click(coords, wait=True)
|
||||
if is_empty:
|
||||
debug.click(buttons.MERCURY_YES)
|
||||
|
||||
|
||||
def delete_char(debug: "DebugLink") -> None:
|
||||
|
@ -1597,7 +1597,7 @@ class InputFlowSlip39BasicResetRecovery(InputFlowBase):
|
||||
# Mnemonic phrases
|
||||
self.mnemonics = yield from load_N_shares(self.debug, 5)
|
||||
|
||||
br = yield # safety warning
|
||||
br = yield # success screen
|
||||
assert br.code == B.Success
|
||||
self.debug.press_yes()
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user