mirror of
https://github.com/trezor/trezor-firmware.git
synced 2025-08-01 19:38:33 +00:00
feat(core): join active workflows before restart
It should support asynchronous "success" confirmation layouts for address, public key and signature confirmation flows. [no changelog]
This commit is contained in:
parent
23cde4ed72
commit
f331b133e3
1
core/.changelog.d/3666.fixed
Normal file
1
core/.changelog.d/3666.fixed
Normal file
@ -0,0 +1 @@
|
|||||||
|
[T3T1] Show confirmation layout after sending address, public key or signature to host.
|
@ -757,7 +757,6 @@ static void _librust_qstrs(void) {
|
|||||||
MP_QSTR_time_ms;
|
MP_QSTR_time_ms;
|
||||||
MP_QSTR_timer;
|
MP_QSTR_timer;
|
||||||
MP_QSTR_title;
|
MP_QSTR_title;
|
||||||
MP_QSTR_title_success;
|
|
||||||
MP_QSTR_total_fee_new;
|
MP_QSTR_total_fee_new;
|
||||||
MP_QSTR_total_len;
|
MP_QSTR_total_len;
|
||||||
MP_QSTR_touch_event;
|
MP_QSTR_touch_event;
|
||||||
|
@ -553,7 +553,6 @@ extern "C" fn new_flow_get_address(n_args: usize, args: *const Obj, kwargs: *mut
|
|||||||
let account: Option<TString> = kwargs.get(Qstr::MP_QSTR_account)?.try_into_option()?;
|
let account: Option<TString> = kwargs.get(Qstr::MP_QSTR_account)?.try_into_option()?;
|
||||||
let path: Option<TString> = kwargs.get(Qstr::MP_QSTR_path)?.try_into_option()?;
|
let path: Option<TString> = kwargs.get(Qstr::MP_QSTR_path)?.try_into_option()?;
|
||||||
let xpubs: Obj = kwargs.get(Qstr::MP_QSTR_xpubs)?;
|
let xpubs: Obj = kwargs.get(Qstr::MP_QSTR_xpubs)?;
|
||||||
let title_success: TString = kwargs.get(Qstr::MP_QSTR_title_success)?.try_into()?;
|
|
||||||
let br_code: u16 = kwargs.get(Qstr::MP_QSTR_br_code)?.try_into()?;
|
let br_code: u16 = kwargs.get(Qstr::MP_QSTR_br_code)?.try_into()?;
|
||||||
let br_name: TString = kwargs.get(Qstr::MP_QSTR_br_name)?.try_into()?;
|
let br_name: TString = kwargs.get(Qstr::MP_QSTR_br_name)?.try_into()?;
|
||||||
|
|
||||||
@ -568,7 +567,6 @@ extern "C" fn new_flow_get_address(n_args: usize, args: *const Obj, kwargs: *mut
|
|||||||
account,
|
account,
|
||||||
path,
|
path,
|
||||||
xpubs,
|
xpubs,
|
||||||
title_success,
|
|
||||||
br_code,
|
br_code,
|
||||||
br_name,
|
br_name,
|
||||||
)?;
|
)?;
|
||||||
@ -1507,7 +1505,6 @@ pub static mp_module_trezorui_api: Module = obj_module! {
|
|||||||
/// account: str | None,
|
/// account: str | None,
|
||||||
/// path: str | None,
|
/// path: str | None,
|
||||||
/// xpubs: list[tuple[str, str]],
|
/// xpubs: list[tuple[str, str]],
|
||||||
/// title_success: str,
|
|
||||||
/// br_code: ButtonRequestType,
|
/// br_code: ButtonRequestType,
|
||||||
/// br_name: str,
|
/// br_name: str,
|
||||||
/// ) -> LayoutObj[UiResult]:
|
/// ) -> LayoutObj[UiResult]:
|
||||||
|
@ -599,7 +599,6 @@ impl FirmwareUI for UIBolt {
|
|||||||
_account: Option<TString<'static>>,
|
_account: Option<TString<'static>>,
|
||||||
_path: Option<TString<'static>>,
|
_path: Option<TString<'static>>,
|
||||||
_xpubs: Obj,
|
_xpubs: Obj,
|
||||||
_title_success: TString<'static>,
|
|
||||||
_br_code: u16,
|
_br_code: u16,
|
||||||
_br_name: TString<'static>,
|
_br_name: TString<'static>,
|
||||||
) -> Result<impl LayoutMaybeTrace, Error> {
|
) -> Result<impl LayoutMaybeTrace, Error> {
|
||||||
|
@ -735,7 +735,6 @@ impl FirmwareUI for UICaesar {
|
|||||||
_account: Option<TString<'static>>,
|
_account: Option<TString<'static>>,
|
||||||
_path: Option<TString<'static>>,
|
_path: Option<TString<'static>>,
|
||||||
_xpubs: Obj,
|
_xpubs: Obj,
|
||||||
_title_success: TString<'static>,
|
|
||||||
_br_code: u16,
|
_br_code: u16,
|
||||||
_br_name: TString<'static>,
|
_br_name: TString<'static>,
|
||||||
) -> Result<impl LayoutMaybeTrace, Error> {
|
) -> Result<impl LayoutMaybeTrace, Error> {
|
||||||
|
@ -172,12 +172,12 @@ impl StatusScreen {
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn new_success_timeout(msg: TString<'static>) -> Self {
|
pub fn new_success_timeout(msg: TString<'static>, time_ms: u32) -> Self {
|
||||||
Self::new(
|
Self::new(
|
||||||
theme::ICON_SIMPLE_CHECKMARK30,
|
theme::ICON_SIMPLE_CHECKMARK30,
|
||||||
theme::GREEN_LIME,
|
theme::GREEN_LIME,
|
||||||
theme::GREEN_LIGHT,
|
theme::GREEN_LIGHT,
|
||||||
DismissType::Timeout(Timeout::new(TIMEOUT_MS)),
|
DismissType::Timeout(Timeout::new(time_ms)),
|
||||||
msg,
|
msg,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
@ -20,7 +20,7 @@ use crate::{
|
|||||||
};
|
};
|
||||||
|
|
||||||
use super::super::{
|
use super::super::{
|
||||||
component::{AddressDetails, Frame, PromptScreen, StatusScreen, SwipeContent, VerticalMenu},
|
component::{AddressDetails, Frame, PromptScreen, SwipeContent, VerticalMenu},
|
||||||
theme,
|
theme,
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -30,7 +30,6 @@ const QR_BORDER: i16 = 4;
|
|||||||
pub enum GetAddress {
|
pub enum GetAddress {
|
||||||
Address,
|
Address,
|
||||||
Tap,
|
Tap,
|
||||||
Confirmed,
|
|
||||||
Menu,
|
Menu,
|
||||||
QrCode,
|
QrCode,
|
||||||
AccountInfo,
|
AccountInfo,
|
||||||
@ -57,9 +56,8 @@ impl FlowController for GetAddress {
|
|||||||
fn handle_event(&'static self, msg: FlowMsg) -> Decision {
|
fn handle_event(&'static self, msg: FlowMsg) -> Decision {
|
||||||
match (self, msg) {
|
match (self, msg) {
|
||||||
(Self::Address, FlowMsg::Info) => Self::Menu.goto(),
|
(Self::Address, FlowMsg::Info) => Self::Menu.goto(),
|
||||||
(Self::Tap, FlowMsg::Confirmed) => Self::Confirmed.swipe_up(),
|
(Self::Tap, FlowMsg::Confirmed) => self.return_msg(FlowMsg::Confirmed),
|
||||||
(Self::Tap, FlowMsg::Info) => Self::Menu.swipe_left(),
|
(Self::Tap, FlowMsg::Info) => Self::Menu.swipe_left(),
|
||||||
(Self::Confirmed, _) => self.return_msg(FlowMsg::Confirmed),
|
|
||||||
(Self::Menu, FlowMsg::Choice(0)) => Self::QrCode.swipe_left(),
|
(Self::Menu, FlowMsg::Choice(0)) => Self::QrCode.swipe_left(),
|
||||||
(Self::Menu, FlowMsg::Choice(1)) => Self::AccountInfo.swipe_left(),
|
(Self::Menu, FlowMsg::Choice(1)) => Self::AccountInfo.swipe_left(),
|
||||||
(Self::Menu, FlowMsg::Choice(2)) => Self::Cancel.swipe_left(),
|
(Self::Menu, FlowMsg::Choice(2)) => Self::Cancel.swipe_left(),
|
||||||
@ -86,7 +84,6 @@ pub fn new_get_address(
|
|||||||
account: Option<TString<'static>>,
|
account: Option<TString<'static>>,
|
||||||
path: Option<TString<'static>>,
|
path: Option<TString<'static>>,
|
||||||
xpubs: Obj, // TODO: get rid of Obj
|
xpubs: Obj, // TODO: get rid of Obj
|
||||||
title_success: TString<'static>,
|
|
||||||
br_code: u16,
|
br_code: u16,
|
||||||
br_name: TString<'static>,
|
br_name: TString<'static>,
|
||||||
) -> Result<SwipeFlow, error::Error> {
|
) -> Result<SwipeFlow, error::Error> {
|
||||||
@ -122,14 +119,6 @@ pub fn new_get_address(
|
|||||||
.with_swipe(Direction::Down, SwipeSettings::default())
|
.with_swipe(Direction::Down, SwipeSettings::default())
|
||||||
.map(super::util::map_to_confirm);
|
.map(super::util::map_to_confirm);
|
||||||
|
|
||||||
let content_confirmed = Frame::left_aligned(
|
|
||||||
TR::words__title_success.into(),
|
|
||||||
StatusScreen::new_success_timeout(title_success),
|
|
||||||
)
|
|
||||||
.with_footer(TR::instructions__continue_in_app.into(), None)
|
|
||||||
.with_result_icon(theme::ICON_BULLET_CHECKMARK, theme::GREEN_LIGHT)
|
|
||||||
.map(|_| Some(FlowMsg::Confirmed));
|
|
||||||
|
|
||||||
// Menu
|
// Menu
|
||||||
let content_menu = Frame::left_aligned(
|
let content_menu = Frame::left_aligned(
|
||||||
"".into(),
|
"".into(),
|
||||||
@ -187,7 +176,6 @@ pub fn new_get_address(
|
|||||||
let mut res = SwipeFlow::new(&GetAddress::Address)?;
|
let mut res = SwipeFlow::new(&GetAddress::Address)?;
|
||||||
res.add_page(&GetAddress::Address, content_address)?
|
res.add_page(&GetAddress::Address, content_address)?
|
||||||
.add_page(&GetAddress::Tap, content_tap)?
|
.add_page(&GetAddress::Tap, content_tap)?
|
||||||
.add_page(&GetAddress::Confirmed, content_confirmed)?
|
|
||||||
.add_page(&GetAddress::Menu, content_menu)?
|
.add_page(&GetAddress::Menu, content_menu)?
|
||||||
.add_page(&GetAddress::QrCode, content_qr)?
|
.add_page(&GetAddress::QrCode, content_qr)?
|
||||||
.add_page(&GetAddress::AccountInfo, content_account)?
|
.add_page(&GetAddress::AccountInfo, content_account)?
|
||||||
|
@ -9,6 +9,7 @@ use crate::{
|
|||||||
ui::{
|
ui::{
|
||||||
component::{
|
component::{
|
||||||
connect::Connect,
|
connect::Connect,
|
||||||
|
swipe_detect::SwipeSettings,
|
||||||
text::{
|
text::{
|
||||||
op::OpTextLayout,
|
op::OpTextLayout,
|
||||||
paragraphs::{
|
paragraphs::{
|
||||||
@ -19,7 +20,7 @@ use crate::{
|
|||||||
},
|
},
|
||||||
Border, CachedJpeg, ComponentExt, Empty, FormattedText, Never, Timeout,
|
Border, CachedJpeg, ComponentExt, Empty, FormattedText, Never, Timeout,
|
||||||
},
|
},
|
||||||
geometry::{self, Offset},
|
geometry::{self, Direction, Offset},
|
||||||
layout::{
|
layout::{
|
||||||
obj::{LayoutMaybeTrace, LayoutObj, RootComponent},
|
obj::{LayoutMaybeTrace, LayoutObj, RootComponent},
|
||||||
util::{PropsList, RecoveryType},
|
util::{PropsList, RecoveryType},
|
||||||
@ -628,7 +629,6 @@ impl FirmwareUI for UIDelizia {
|
|||||||
account: Option<TString<'static>>,
|
account: Option<TString<'static>>,
|
||||||
path: Option<TString<'static>>,
|
path: Option<TString<'static>>,
|
||||||
xpubs: Obj,
|
xpubs: Obj,
|
||||||
title_success: TString<'static>,
|
|
||||||
br_code: u16,
|
br_code: u16,
|
||||||
br_name: TString<'static>,
|
br_name: TString<'static>,
|
||||||
) -> Result<impl LayoutMaybeTrace, Error> {
|
) -> Result<impl LayoutMaybeTrace, Error> {
|
||||||
@ -643,7 +643,6 @@ impl FirmwareUI for UIDelizia {
|
|||||||
account,
|
account,
|
||||||
path,
|
path,
|
||||||
xpubs,
|
xpubs,
|
||||||
title_success,
|
|
||||||
br_code,
|
br_code,
|
||||||
br_name,
|
br_name,
|
||||||
)?;
|
)?;
|
||||||
@ -1088,24 +1087,34 @@ impl FirmwareUI for UIDelizia {
|
|||||||
|
|
||||||
fn show_success(
|
fn show_success(
|
||||||
title: TString<'static>,
|
title: TString<'static>,
|
||||||
_button: TString<'static>,
|
button: TString<'static>,
|
||||||
description: TString<'static>,
|
description: TString<'static>,
|
||||||
_allow_cancel: bool,
|
_allow_cancel: bool,
|
||||||
_time_ms: u32,
|
time_ms: u32,
|
||||||
) -> Result<Gc<LayoutObj>, Error> {
|
) -> Result<Gc<LayoutObj>, Error> {
|
||||||
|
let instruction = if button.is_empty() {
|
||||||
|
TR::instructions__tap_to_continue.into()
|
||||||
|
} else {
|
||||||
|
button
|
||||||
|
};
|
||||||
// description used in the Footer
|
// description used in the Footer
|
||||||
let description = if description.is_empty() {
|
let description = if description.is_empty() {
|
||||||
None
|
None
|
||||||
} else {
|
} else {
|
||||||
Some(description)
|
Some(description)
|
||||||
};
|
};
|
||||||
let content = StatusScreen::new_success(title);
|
let content = if time_ms > 0 {
|
||||||
|
StatusScreen::new_success_timeout(title, time_ms)
|
||||||
|
} else {
|
||||||
|
StatusScreen::new_success(title)
|
||||||
|
};
|
||||||
let layout = LayoutObj::new(SwipeUpScreen::new(
|
let layout = LayoutObj::new(SwipeUpScreen::new(
|
||||||
Frame::left_aligned(
|
Frame::left_aligned(
|
||||||
TR::words__title_success.into(),
|
TR::words__title_success.into(),
|
||||||
SwipeContent::new(content).with_no_attach_anim(),
|
SwipeContent::new(content).with_no_attach_anim(),
|
||||||
)
|
)
|
||||||
.with_swipeup_footer(description)
|
.with_footer(instruction, description)
|
||||||
|
.with_swipe(Direction::Up, SwipeSettings::default())
|
||||||
.with_result_icon(theme::ICON_BULLET_CHECKMARK, theme::GREEN_LIGHT),
|
.with_result_icon(theme::ICON_BULLET_CHECKMARK, theme::GREEN_LIGHT),
|
||||||
))?;
|
))?;
|
||||||
Ok(layout)
|
Ok(layout)
|
||||||
|
@ -205,7 +205,6 @@ pub trait FirmwareUI {
|
|||||||
account: Option<TString<'static>>,
|
account: Option<TString<'static>>,
|
||||||
path: Option<TString<'static>>,
|
path: Option<TString<'static>>,
|
||||||
xpubs: Obj, // TODO: replace Obj
|
xpubs: Obj, // TODO: replace Obj
|
||||||
title_success: TString<'static>,
|
|
||||||
br_code: u16,
|
br_code: u16,
|
||||||
br_name: TString<'static>,
|
br_name: TString<'static>,
|
||||||
) -> Result<impl LayoutMaybeTrace, Error>;
|
) -> Result<impl LayoutMaybeTrace, Error>;
|
||||||
|
@ -367,7 +367,6 @@ def flow_get_address(
|
|||||||
account: str | None,
|
account: str | None,
|
||||||
path: str | None,
|
path: str | None,
|
||||||
xpubs: list[tuple[str, str]],
|
xpubs: list[tuple[str, str]],
|
||||||
title_success: str,
|
|
||||||
br_code: ButtonRequestType,
|
br_code: ButtonRequestType,
|
||||||
br_name: str,
|
br_name: str,
|
||||||
) -> LayoutObj[UiResult]:
|
) -> LayoutObj[UiResult]:
|
||||||
|
@ -52,8 +52,10 @@ async def sign_tx(
|
|||||||
coin: CoinInfo,
|
coin: CoinInfo,
|
||||||
authorization: CoinJoinAuthorization | None = None,
|
authorization: CoinJoinAuthorization | None = None,
|
||||||
) -> TxRequest:
|
) -> TxRequest:
|
||||||
|
from trezor import TR
|
||||||
from trezor.enums import RequestType
|
from trezor.enums import RequestType
|
||||||
from trezor.messages import TxRequest
|
from trezor.messages import TxRequest
|
||||||
|
from trezor.ui.layouts import show_continue_in_app
|
||||||
from trezor.wire.context import call
|
from trezor.wire.context import call
|
||||||
|
|
||||||
from ..common import BITCOIN_NAMES
|
from ..common import BITCOIN_NAMES
|
||||||
@ -93,6 +95,7 @@ async def sign_tx(
|
|||||||
request_class, req = req
|
request_class, req = req
|
||||||
assert TxRequest.is_type_of(req)
|
assert TxRequest.is_type_of(req)
|
||||||
if req.request_type == RequestType.TXFINISHED:
|
if req.request_type == RequestType.TXFINISHED:
|
||||||
|
show_continue_in_app(TR.send__transaction_signed)
|
||||||
return req
|
return req
|
||||||
res = await call(req, request_class)
|
res = await call(req, request_class)
|
||||||
elif isinstance(req, helpers.UiConfirm):
|
elif isinstance(req, helpers.UiConfirm):
|
||||||
|
@ -12,9 +12,10 @@ if TYPE_CHECKING:
|
|||||||
async def sign_tx(
|
async def sign_tx(
|
||||||
msg: CardanoSignTxInit, keychain: seed.Keychain
|
msg: CardanoSignTxInit, keychain: seed.Keychain
|
||||||
) -> CardanoSignTxFinished:
|
) -> CardanoSignTxFinished:
|
||||||
from trezor import log, wire
|
from trezor import TR, log, wire
|
||||||
from trezor.enums import CardanoTxSigningMode
|
from trezor.enums import CardanoTxSigningMode
|
||||||
from trezor.messages import CardanoSignTxFinished
|
from trezor.messages import CardanoSignTxFinished
|
||||||
|
from trezor.ui.layouts import show_continue_in_app
|
||||||
|
|
||||||
from .signer import Signer
|
from .signer import Signer
|
||||||
|
|
||||||
@ -49,4 +50,5 @@ async def sign_tx(
|
|||||||
log.exception(__name__, e)
|
log.exception(__name__, e)
|
||||||
raise wire.ProcessError("Signing failed")
|
raise wire.ProcessError("Signing failed")
|
||||||
|
|
||||||
|
show_continue_in_app(TR.send__transaction_signed)
|
||||||
return CardanoSignTxFinished()
|
return CardanoSignTxFinished()
|
||||||
|
@ -10,9 +10,11 @@ if TYPE_CHECKING:
|
|||||||
|
|
||||||
@auto_keychain(__name__)
|
@auto_keychain(__name__)
|
||||||
async def sign_tx(msg: EosSignTx, keychain: Keychain) -> EosSignedTx:
|
async def sign_tx(msg: EosSignTx, keychain: Keychain) -> EosSignedTx:
|
||||||
|
from trezor import TR
|
||||||
from trezor.crypto.curve import secp256k1
|
from trezor.crypto.curve import secp256k1
|
||||||
from trezor.crypto.hashlib import sha256
|
from trezor.crypto.hashlib import sha256
|
||||||
from trezor.messages import EosSignedTx, EosTxActionAck, EosTxActionRequest
|
from trezor.messages import EosSignedTx, EosTxActionAck, EosTxActionRequest
|
||||||
|
from trezor.ui.layouts import show_continue_in_app
|
||||||
from trezor.utils import HashWriter
|
from trezor.utils import HashWriter
|
||||||
from trezor.wire import DataError
|
from trezor.wire import DataError
|
||||||
from trezor.wire.context import call
|
from trezor.wire.context import call
|
||||||
@ -55,4 +57,5 @@ async def sign_tx(msg: EosSignTx, keychain: Keychain) -> EosSignedTx:
|
|||||||
node.private_key(), digest, True, secp256k1.CANONICAL_SIG_EOS
|
node.private_key(), digest, True, secp256k1.CANONICAL_SIG_EOS
|
||||||
)
|
)
|
||||||
|
|
||||||
|
show_continue_in_app(TR.send__transaction_signed)
|
||||||
return EosSignedTx(signature=base58_encode("SIG_", "K1", signature))
|
return EosSignedTx(signature=base58_encode("SIG_", "K1", signature))
|
||||||
|
@ -40,6 +40,7 @@ async def sign_tx(
|
|||||||
) -> EthereumTxRequest:
|
) -> EthereumTxRequest:
|
||||||
from trezor import TR
|
from trezor import TR
|
||||||
from trezor.crypto.hashlib import sha3_256
|
from trezor.crypto.hashlib import sha3_256
|
||||||
|
from trezor.ui.layouts import show_continue_in_app
|
||||||
from trezor.ui.layouts.progress import progress
|
from trezor.ui.layouts.progress import progress
|
||||||
from trezor.utils import HashWriter
|
from trezor.utils import HashWriter
|
||||||
|
|
||||||
@ -111,6 +112,7 @@ async def sign_tx(
|
|||||||
|
|
||||||
progress_obj.stop()
|
progress_obj.stop()
|
||||||
|
|
||||||
|
show_continue_in_app(TR.send__transaction_signed)
|
||||||
return result
|
return result
|
||||||
|
|
||||||
|
|
||||||
|
@ -35,9 +35,10 @@ async def sign_tx_eip1559(
|
|||||||
keychain: Keychain,
|
keychain: Keychain,
|
||||||
defs: Definitions,
|
defs: Definitions,
|
||||||
) -> EthereumTxRequest:
|
) -> EthereumTxRequest:
|
||||||
from trezor import wire
|
from trezor import TR, wire
|
||||||
from trezor.crypto import rlp # local_cache_global
|
from trezor.crypto import rlp # local_cache_global
|
||||||
from trezor.crypto.hashlib import sha3_256
|
from trezor.crypto.hashlib import sha3_256
|
||||||
|
from trezor.ui.layouts import show_continue_in_app
|
||||||
from trezor.utils import HashWriter
|
from trezor.utils import HashWriter
|
||||||
|
|
||||||
from apps.common import paths
|
from apps.common import paths
|
||||||
@ -121,6 +122,7 @@ async def sign_tx_eip1559(
|
|||||||
digest = sha.get_digest()
|
digest = sha.get_digest()
|
||||||
result = _sign_digest(msg, keychain, digest)
|
result = _sign_digest(msg, keychain, digest)
|
||||||
|
|
||||||
|
show_continue_in_app(TR.send__transaction_signed)
|
||||||
return result
|
return result
|
||||||
|
|
||||||
|
|
||||||
|
@ -14,7 +14,8 @@ if TYPE_CHECKING:
|
|||||||
async def sign_tx(received_msg, keychain: Keychain) -> MoneroTransactionFinalAck:
|
async def sign_tx(received_msg, keychain: Keychain) -> MoneroTransactionFinalAck:
|
||||||
import gc
|
import gc
|
||||||
|
|
||||||
from trezor import log, utils
|
from trezor import TR, log, utils
|
||||||
|
from trezor.ui.layouts import show_continue_in_app
|
||||||
from trezor.wire.context import get_context
|
from trezor.wire.context import get_context
|
||||||
|
|
||||||
from apps.monero.signing.state import State
|
from apps.monero.signing.state import State
|
||||||
@ -45,6 +46,7 @@ async def sign_tx(received_msg, keychain: Keychain) -> MoneroTransactionFinalAck
|
|||||||
received_msg = await ctx.read(accept_msgs)
|
received_msg = await ctx.read(accept_msgs)
|
||||||
|
|
||||||
utils.unimport_end(mods)
|
utils.unimport_end(mods)
|
||||||
|
show_continue_in_app(TR.send__transaction_signed)
|
||||||
return result_msg
|
return result_msg
|
||||||
|
|
||||||
|
|
||||||
|
@ -11,10 +11,12 @@ if TYPE_CHECKING:
|
|||||||
# NOTE: it is one big function because that way it is the most flash-space-efficient
|
# NOTE: it is one big function because that way it is the most flash-space-efficient
|
||||||
@auto_keychain(__name__)
|
@auto_keychain(__name__)
|
||||||
async def sign_tx(msg: RippleSignTx, keychain: Keychain) -> RippleSignedTx:
|
async def sign_tx(msg: RippleSignTx, keychain: Keychain) -> RippleSignedTx:
|
||||||
|
from trezor import TR
|
||||||
from trezor.crypto import der
|
from trezor.crypto import der
|
||||||
from trezor.crypto.curve import secp256k1
|
from trezor.crypto.curve import secp256k1
|
||||||
from trezor.crypto.hashlib import sha512
|
from trezor.crypto.hashlib import sha512
|
||||||
from trezor.messages import RippleSignedTx
|
from trezor.messages import RippleSignedTx
|
||||||
|
from trezor.ui.layouts import show_continue_in_app
|
||||||
from trezor.wire import ProcessError
|
from trezor.wire import ProcessError
|
||||||
|
|
||||||
from apps.common import paths
|
from apps.common import paths
|
||||||
@ -58,4 +60,5 @@ async def sign_tx(msg: RippleSignTx, keychain: Keychain) -> RippleSignedTx:
|
|||||||
sig_encoded = der.encode_seq((sig[1:33], sig[33:65]))
|
sig_encoded = der.encode_seq((sig[1:33], sig[33:65]))
|
||||||
|
|
||||||
tx = serialize(msg, source_address, node.public_key(), sig_encoded)
|
tx = serialize(msg, source_address, node.public_key(), sig_encoded)
|
||||||
|
show_continue_in_app(TR.send__transaction_signed)
|
||||||
return RippleSignedTx(signature=sig_encoded, serialized_tx=tx)
|
return RippleSignedTx(signature=sig_encoded, serialized_tx=tx)
|
||||||
|
@ -23,7 +23,7 @@ async def sign_tx(
|
|||||||
from trezor.crypto.curve import ed25519
|
from trezor.crypto.curve import ed25519
|
||||||
from trezor.enums import ButtonRequestType
|
from trezor.enums import ButtonRequestType
|
||||||
from trezor.messages import SolanaTxSignature
|
from trezor.messages import SolanaTxSignature
|
||||||
from trezor.ui.layouts import confirm_metadata, show_warning
|
from trezor.ui.layouts import confirm_metadata, show_continue_in_app, show_warning
|
||||||
|
|
||||||
from apps.common import seed
|
from apps.common import seed
|
||||||
|
|
||||||
@ -79,7 +79,7 @@ async def sign_tx(
|
|||||||
)
|
)
|
||||||
|
|
||||||
signature = ed25519.sign(node.private_key(), serialized_tx)
|
signature = ed25519.sign(node.private_key(), serialized_tx)
|
||||||
|
show_continue_in_app(TR.send__transaction_signed)
|
||||||
return SolanaTxSignature(signature=signature)
|
return SolanaTxSignature(signature=signature)
|
||||||
|
|
||||||
|
|
||||||
|
@ -12,10 +12,12 @@ if TYPE_CHECKING:
|
|||||||
async def sign_tx(msg: StellarSignTx, keychain: Keychain) -> StellarSignedTx:
|
async def sign_tx(msg: StellarSignTx, keychain: Keychain) -> StellarSignedTx:
|
||||||
from ubinascii import hexlify
|
from ubinascii import hexlify
|
||||||
|
|
||||||
|
from trezor import TR
|
||||||
from trezor.crypto.curve import ed25519
|
from trezor.crypto.curve import ed25519
|
||||||
from trezor.crypto.hashlib import sha256
|
from trezor.crypto.hashlib import sha256
|
||||||
from trezor.enums import StellarMemoType
|
from trezor.enums import StellarMemoType
|
||||||
from trezor.messages import StellarSignedTx, StellarTxOpRequest
|
from trezor.messages import StellarSignedTx, StellarTxOpRequest
|
||||||
|
from trezor.ui.layouts import show_continue_in_app
|
||||||
from trezor.wire import DataError, ProcessError
|
from trezor.wire import DataError, ProcessError
|
||||||
from trezor.wire.context import call_any
|
from trezor.wire.context import call_any
|
||||||
|
|
||||||
@ -114,6 +116,7 @@ async def sign_tx(msg: StellarSignTx, keychain: Keychain) -> StellarSignedTx:
|
|||||||
# sign
|
# sign
|
||||||
digest = sha256(w).digest()
|
digest = sha256(w).digest()
|
||||||
signature = ed25519.sign(node.private_key(), digest)
|
signature = ed25519.sign(node.private_key(), digest)
|
||||||
|
show_continue_in_app(TR.send__transaction_signed)
|
||||||
|
|
||||||
# Add the public key for verification that the right account was used for signing
|
# Add the public key for verification that the right account was used for signing
|
||||||
return StellarSignedTx(public_key=pubkey, signature=signature)
|
return StellarSignedTx(public_key=pubkey, signature=signature)
|
||||||
|
@ -32,10 +32,12 @@ if TYPE_CHECKING:
|
|||||||
|
|
||||||
@with_slip44_keychain(*PATTERNS, slip44_id=SLIP44_ID, curve=CURVE)
|
@with_slip44_keychain(*PATTERNS, slip44_id=SLIP44_ID, curve=CURVE)
|
||||||
async def sign_tx(msg: TezosSignTx, keychain: Keychain) -> TezosSignedTx:
|
async def sign_tx(msg: TezosSignTx, keychain: Keychain) -> TezosSignedTx:
|
||||||
|
from trezor import TR
|
||||||
from trezor.crypto import hashlib
|
from trezor.crypto import hashlib
|
||||||
from trezor.crypto.curve import ed25519
|
from trezor.crypto.curve import ed25519
|
||||||
from trezor.enums import TezosBallotType
|
from trezor.enums import TezosBallotType
|
||||||
from trezor.messages import TezosSignedTx
|
from trezor.messages import TezosSignedTx
|
||||||
|
from trezor.ui.layouts import show_continue_in_app
|
||||||
|
|
||||||
from apps.common.paths import validate_path
|
from apps.common.paths import validate_path
|
||||||
|
|
||||||
@ -155,6 +157,7 @@ async def sign_tx(msg: TezosSignTx, keychain: Keychain) -> TezosSignedTx:
|
|||||||
|
|
||||||
sig_prefixed = base58_encode_check(signature, helpers.TEZOS_SIGNATURE_PREFIX)
|
sig_prefixed = base58_encode_check(signature, helpers.TEZOS_SIGNATURE_PREFIX)
|
||||||
|
|
||||||
|
show_continue_in_app(TR.send__transaction_signed)
|
||||||
return TezosSignedTx(
|
return TezosSignedTx(
|
||||||
signature=sig_prefixed, sig_op_contents=sig_op_contents, operation_hash=ophash
|
signature=sig_prefixed, sig_op_contents=sig_op_contents, operation_hash=ophash
|
||||||
)
|
)
|
||||||
|
@ -443,6 +443,10 @@ def show_success(
|
|||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
|
def show_continue_in_app(content: str) -> None:
|
||||||
|
return
|
||||||
|
|
||||||
|
|
||||||
async def confirm_output(
|
async def confirm_output(
|
||||||
address: str,
|
address: str,
|
||||||
amount: str,
|
amount: str,
|
||||||
|
@ -507,6 +507,10 @@ def show_success(
|
|||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
|
def show_continue_in_app(content: str) -> None:
|
||||||
|
return
|
||||||
|
|
||||||
|
|
||||||
async def confirm_output(
|
async def confirm_output(
|
||||||
address: str,
|
address: str,
|
||||||
amount: str,
|
amount: str,
|
||||||
|
@ -10,7 +10,7 @@ if __debug__:
|
|||||||
from trezor import log
|
from trezor import log
|
||||||
|
|
||||||
if TYPE_CHECKING:
|
if TYPE_CHECKING:
|
||||||
from typing import Any, Awaitable, Callable, TypeVar
|
from typing import Any, Awaitable, Callable, Coroutine, TypeVar
|
||||||
|
|
||||||
PropertyType = tuple[str | None, str | bytes | None]
|
PropertyType = tuple[str | None, str | bytes | None]
|
||||||
ExceptionType = BaseException | type[BaseException]
|
ExceptionType = BaseException | type[BaseException]
|
||||||
@ -62,7 +62,7 @@ def raise_if_not_confirmed(
|
|||||||
br_name: str | None,
|
br_name: str | None,
|
||||||
br_code: ButtonRequestType = ButtonRequestType.Other,
|
br_code: ButtonRequestType = ButtonRequestType.Other,
|
||||||
exc: ExceptionType = ActionCancelled,
|
exc: ExceptionType = ActionCancelled,
|
||||||
) -> Awaitable[None]:
|
) -> Coroutine[Any, Any, None]:
|
||||||
action = interact(layout_obj, br_name, br_code, exc)
|
action = interact(layout_obj, br_name, br_code, exc)
|
||||||
return action # type: ignore ["UiResult" is incompatible with "None"]
|
return action # type: ignore ["UiResult" is incompatible with "None"]
|
||||||
|
|
||||||
|
@ -1,14 +1,14 @@
|
|||||||
from typing import TYPE_CHECKING
|
from typing import TYPE_CHECKING
|
||||||
|
|
||||||
import trezorui_api
|
import trezorui_api
|
||||||
from trezor import TR, ui, utils
|
from trezor import TR, ui, utils, workflow
|
||||||
from trezor.enums import ButtonRequestType, RecoveryType
|
from trezor.enums import ButtonRequestType, RecoveryType
|
||||||
from trezor.wire import ActionCancelled
|
from trezor.wire import ActionCancelled
|
||||||
|
|
||||||
from ..common import draw_simple, interact, raise_if_not_confirmed, with_info
|
from ..common import draw_simple, interact, raise_if_not_confirmed, with_info
|
||||||
|
|
||||||
if TYPE_CHECKING:
|
if TYPE_CHECKING:
|
||||||
from typing import Awaitable, Iterable, NoReturn, Sequence, TypeVar
|
from typing import Any, Awaitable, Coroutine, Iterable, NoReturn, Sequence, TypeVar
|
||||||
|
|
||||||
from ..common import ExceptionType, PropertyType
|
from ..common import ExceptionType, PropertyType
|
||||||
|
|
||||||
@ -279,12 +279,6 @@ async def show_address(
|
|||||||
)
|
)
|
||||||
return result
|
return result
|
||||||
|
|
||||||
title_success = (
|
|
||||||
TR.address__public_key_confirmed
|
|
||||||
if title in ("XPUB", TR.address__public_key)
|
|
||||||
else TR.address__confirmed
|
|
||||||
)
|
|
||||||
|
|
||||||
await raise_if_not_confirmed(
|
await raise_if_not_confirmed(
|
||||||
trezorui_api.flow_get_address(
|
trezorui_api.flow_get_address(
|
||||||
address=address,
|
address=address,
|
||||||
@ -297,13 +291,18 @@ async def show_address(
|
|||||||
account=account,
|
account=account,
|
||||||
path=path,
|
path=path,
|
||||||
xpubs=[(xpub_title(i), xpub) for i, xpub in enumerate(xpubs)],
|
xpubs=[(xpub_title(i), xpub) for i, xpub in enumerate(xpubs)],
|
||||||
title_success=title_success,
|
|
||||||
br_name=br_name,
|
br_name=br_name,
|
||||||
br_code=br_code,
|
br_code=br_code,
|
||||||
),
|
),
|
||||||
None,
|
None,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
show_continue_in_app(
|
||||||
|
TR.address__public_key_confirmed
|
||||||
|
if title in ("XPUB", TR.address__public_key)
|
||||||
|
else TR.address__confirmed
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
def show_pubkey(
|
def show_pubkey(
|
||||||
pubkey: str,
|
pubkey: str,
|
||||||
@ -393,22 +392,34 @@ def show_danger(
|
|||||||
|
|
||||||
|
|
||||||
def show_success(
|
def show_success(
|
||||||
br_name: str,
|
br_name: str | None,
|
||||||
content: str,
|
content: str,
|
||||||
subheader: str | None = None,
|
subheader: str | None = None,
|
||||||
button: str | None = None,
|
button: str | None = None,
|
||||||
) -> Awaitable[None]:
|
time_ms: int = 0,
|
||||||
|
) -> Coroutine[Any, Any, None]:
|
||||||
return raise_if_not_confirmed(
|
return raise_if_not_confirmed(
|
||||||
trezorui_api.show_success(
|
trezorui_api.show_success(
|
||||||
title=content,
|
title=content,
|
||||||
button="",
|
button=button or "",
|
||||||
description=subheader if subheader else "",
|
description=subheader or "",
|
||||||
|
time_ms=time_ms,
|
||||||
),
|
),
|
||||||
br_name,
|
br_name,
|
||||||
ButtonRequestType.Success,
|
ButtonRequestType.Success,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
|
def show_continue_in_app(content: str) -> None:
|
||||||
|
task = show_success(
|
||||||
|
content=content,
|
||||||
|
button=TR.instructions__continue_in_app,
|
||||||
|
time_ms=3200,
|
||||||
|
br_name=None,
|
||||||
|
)
|
||||||
|
workflow.spawn(task)
|
||||||
|
|
||||||
|
|
||||||
async def confirm_output(
|
async def confirm_output(
|
||||||
address: str,
|
address: str,
|
||||||
amount: str | None = None,
|
amount: str | None = None,
|
||||||
|
@ -1,14 +1,14 @@
|
|||||||
from typing import TYPE_CHECKING
|
from typing import TYPE_CHECKING
|
||||||
|
|
||||||
import trezorui_api
|
import trezorui_api
|
||||||
from trezor import TR, ui, utils
|
from trezor import TR, ui, utils, workflow
|
||||||
from trezor.enums import ButtonRequestType, RecoveryType
|
from trezor.enums import ButtonRequestType, RecoveryType
|
||||||
from trezor.wire import ActionCancelled
|
from trezor.wire import ActionCancelled
|
||||||
|
|
||||||
from ..common import draw_simple, interact, raise_if_not_confirmed, with_info
|
from ..common import draw_simple, interact, raise_if_not_confirmed, with_info
|
||||||
|
|
||||||
if TYPE_CHECKING:
|
if TYPE_CHECKING:
|
||||||
from typing import Awaitable, Iterable, NoReturn, Sequence, TypeVar
|
from typing import Any, Awaitable, Coroutine, Iterable, NoReturn, Sequence, TypeVar
|
||||||
|
|
||||||
from ..common import ExceptionType, PropertyType
|
from ..common import ExceptionType, PropertyType
|
||||||
|
|
||||||
@ -297,6 +297,12 @@ async def show_address(
|
|||||||
None,
|
None,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
show_continue_in_app(
|
||||||
|
TR.address__public_key_confirmed
|
||||||
|
if title in ("XPUB", TR.address__public_key)
|
||||||
|
else TR.address__confirmed
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
def show_pubkey(
|
def show_pubkey(
|
||||||
pubkey: str,
|
pubkey: str,
|
||||||
@ -393,7 +399,7 @@ def show_success(
|
|||||||
subheader: str | None = None,
|
subheader: str | None = None,
|
||||||
button: str | None = None,
|
button: str | None = None,
|
||||||
time_ms: int = 0,
|
time_ms: int = 0,
|
||||||
) -> Awaitable[None]:
|
) -> Coroutine[Any, Any, None]:
|
||||||
button = button or TR.buttons__continue # def_arg
|
button = button or TR.buttons__continue # def_arg
|
||||||
return raise_if_not_confirmed(
|
return raise_if_not_confirmed(
|
||||||
trezorui_api.show_success(
|
trezorui_api.show_success(
|
||||||
@ -408,13 +414,14 @@ def show_success(
|
|||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
def show_continue_in_app(content: str) -> Awaitable[None]:
|
def show_continue_in_app(content: str) -> None:
|
||||||
return show_success(
|
task = show_success(
|
||||||
content=content,
|
content=content,
|
||||||
button=TR.instructions__continue_in_app,
|
button=TR.instructions__continue_in_app,
|
||||||
time_ms=3200,
|
time_ms=3200,
|
||||||
br_name=None,
|
br_name=None,
|
||||||
)
|
)
|
||||||
|
workflow.spawn(task)
|
||||||
|
|
||||||
|
|
||||||
async def confirm_output(
|
async def confirm_output(
|
||||||
|
@ -27,6 +27,7 @@ from typing import TYPE_CHECKING
|
|||||||
|
|
||||||
from trezor import loop, protobuf, utils
|
from trezor import loop, protobuf, utils
|
||||||
|
|
||||||
|
from .. import workflow
|
||||||
from . import message_handler, protocol_common
|
from . import message_handler, protocol_common
|
||||||
from .codec.codec_context import CodecContext
|
from .codec.codec_context import CodecContext
|
||||||
from .context import UnexpectedMessageException
|
from .context import UnexpectedMessageException
|
||||||
@ -118,6 +119,8 @@ async def handle_session(iface: WireInterface) -> None:
|
|||||||
utils.unimport_end(modules)
|
utils.unimport_end(modules)
|
||||||
|
|
||||||
if not do_not_restart:
|
if not do_not_restart:
|
||||||
|
# Wait for all active workflows to finish.
|
||||||
|
await workflow.join_all()
|
||||||
# Let the session be restarted from `main`.
|
# Let the session be restarted from `main`.
|
||||||
loop.clear()
|
loop.clear()
|
||||||
return # pylint: disable=lost-exception
|
return # pylint: disable=lost-exception
|
||||||
|
@ -84,6 +84,16 @@ def spawn(workflow: loop.Task) -> loop.spawn:
|
|||||||
return task
|
return task
|
||||||
|
|
||||||
|
|
||||||
|
async def join_all() -> None:
|
||||||
|
"""Block until all workflows are over."""
|
||||||
|
if __debug__:
|
||||||
|
log.debug(__name__, "joining %d workflows", len(tasks))
|
||||||
|
|
||||||
|
# Don't iterate over `tasks` since it will be modified by its finalizers
|
||||||
|
while tasks:
|
||||||
|
await next(iter(tasks))
|
||||||
|
|
||||||
|
|
||||||
def start_default() -> None:
|
def start_default() -> None:
|
||||||
"""Start a default workflow.
|
"""Start a default workflow.
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user