chore(core): change string tuple to propertytype
What changed, and why it matters
This is a large internal refactoring of how Trezor's user-interface passes key-value display data from Python apps to the Rust firmware. It replaces two-element string tuples with a new three-element 'PropertyType' that adds a flag indicating whether a value is raw data. The change touches many coin apps and UI layouts but is described by the vendor as a routine chore with no changelog entry. There is no direct evidence in the commit of a security vulnerability or fix.
Treat as a routine refactor. If monitoring this project, verify that follow-up commits add or update UI tests and that the new PropertyType flag is consistently honored by all layouts to avoid display bugs. No immediate security response is indicated by this commit alone.
Security signals we found
Large cross-cutting UI API change with no changelog or security framing
Type narrowing from raw Obj to TString/StrOrBytes in Rust UI boundary
Addition of a third 'is_data' boolean to property tuples across many coin apps
No explicit bounds checks or validation changes visible in the diff
No vendor disclosure or advisory references present
Evidence from the diff
The commit refactors UI property lists across the firmware from tuple[str, str] to PropertyType = tuple[str | None, str | bytes | None, bool | None]. Rust UI code is updated to destructure three-element tuples ([key, value, _is_data]) and to use typed TString/StrOrBytes instead of raw Obj for message/amount fields. Layout-specific code (Bolt, Caesar, Delizia, Eckhart) is adjusted to consume the new type, and a shared content_menu_info helper is introduced for the Eckhart layout. Python callers in Bitcoin, Cardano, Ethereum, Nostr, Ripple, and Solana apps add the third boolean flag to property items. The commit title is ‘chore(core): change string tuple to propertytype’ and includes ‘[no changelog]’.
Changed components
core/embed/rust/src/ui/api/firmware_micropython.rscore/embed/rust/src/ui/layout/util.rscore/embed/rust/src/ui/layout_bolt/ui_firmware.rscore/embed/rust/src/ui/layout_caesar/ui_firmware.rscore/embed/rust/src/ui/layout_delizia/ui_firmware.rscore/embed/rust/src/ui/layout_delizia/flow/util.rscore/embed/rust/src/ui/layout_eckhart/ui_firmware.rscore/embed/rust/src/ui/layout_eckhart/flow/confirm_output.rscore/embed/rust/src/ui/layout_eckhart/flow/confirm_summary.rscore/embed/rust/src/ui/layout_eckhart/flow/util.rscore/embed/rust/src/ui/ui_firmware.rscore/mocks/generated/trezorui_api.pyicore/src/apps/bitcoin/sign_tx/layout.pycore/src/apps/cardano/layout.pycore/src/apps/ethereum/helpers.pycore/src/apps/ethereum/layout.pycore/src/apps/ethereum/sign_tx.pycore/src/apps/nostr/sign_event.pycore/src/apps/ripple/layout.pycore/src/apps/solana/layout.pycore/src/trezor/ui/layouts/bolt/__init__.pycore/src/trezor/ui/layouts/caesar/__init__.pycore/src/trezor/ui/layouts/delizia/__init__.pycore/src/trezor/ui/layouts/eckhart/__init__.pytests/ui_tests/fixtures.jsonInspect captured patch +5021 / −4839
diff --git a/core/embed/rust/src/ui/api/firmware_micropython.rs b/core/embed/rust/src/ui/api/firmware_micropython.rs
index f097adf6..72afe59c 100644
--- a/core/embed/rust/src/ui/api/firmware_micropython.rs
+++ b/core/embed/rust/src/ui/api/firmware_micropython.rs
@@ -513,8 +513,8 @@ extern "C" fn new_flow_confirm_output(n_args: usize, args: *const Obj, kwargs: *
let extra: Option<TString> = kwargs.get(Qstr::MP_QSTR_extra)?.try_into_option()?;
let description: Option<TString> =
kwargs.get(Qstr::MP_QSTR_description)?.try_into_option()?;
- let message: Obj = kwargs.get(Qstr::MP_QSTR_message)?;
- let amount: Option<Obj> = kwargs.get(Qstr::MP_QSTR_amount)?.try_into_option()?;
+ let message: TString = kwargs.get(Qstr::MP_QSTR_message)?.try_into()?;
+ let amount: Option<TString> = kwargs.get(Qstr::MP_QSTR_amount)?.try_into_option()?;
let chunkify: bool = kwargs.get_or(Qstr::MP_QSTR_chunkify, false)?;
let text_mono: bool = kwargs.get_or(Qstr::MP_QSTR_text_mono, true)?;
let account_title: TString = kwargs.get(Qstr::MP_QSTR_account_title)?.try_into()?;
@@ -524,22 +524,9 @@ extern "C" fn new_flow_confirm_output(n_args: usize, args: *const Obj, kwargs: *
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 address_item = kwargs
- .get(Qstr::MP_QSTR_address_item)?
- .try_into_option()?
- .map(|item| -> Result<(TString, Obj), crate::error::Error> {
- let pair: [Obj; 2] = util::iter_into_array(item)?;
- Ok((pair[0].try_into()?, pair[1]))
- })
- .transpose()?;
- let extra_item = kwargs
- .get(Qstr::MP_QSTR_extra_item)?
- .try_into_option()?
- .map(|item| -> Result<(TString, Obj), crate::error::Error> {
- let pair: [Obj; 2] = util::iter_into_array(item)?;
- Ok((pair[0].try_into()?, pair[1]))
- })
- .transpose()?;
+ let address_item: Option<Obj> =
+ kwargs.get(Qstr::MP_QSTR_address_item)?.try_into_option()?;
+ let extra_item: Option<Obj> = kwargs.get(Qstr::MP_QSTR_extra_item)?.try_into_option()?;
let summary_items: Option<Obj> =
kwargs.get(Qstr::MP_QSTR_summary_items)?.try_into_option()?;
let fee_items: Option<Obj> = kwargs.get(Qstr::MP_QSTR_fee_items)?.try_into_option()?;
@@ -1269,6 +1256,7 @@ pub extern "C" fn upy_backlight_fade(_level: Obj) -> Obj {
pub static mp_module_trezorui_api: Module = obj_module! {
/// from trezor import utils
///
+ /// PropertyType = tuple[str | None, str | bytes | None, bool | None]
/// T = TypeVar("T")
///
/// class LayoutObj(Generic[T]):
@@ -1561,7 +1549,7 @@ pub static mp_module_trezorui_api: Module = obj_module! {
/// *,
/// title: str,
/// subtitle: str | None = None,
- /// items: list[tuple[str | None, str | bytes | None, bool | None]],
+ /// items: list[PropertyType],
/// hold: bool = False,
/// verb: str | None = None,
/// external_menu: bool = False,
@@ -1581,9 +1569,9 @@ pub static mp_module_trezorui_api: Module = obj_module! {
/// fee: str,
/// fee_label: str,
/// title: str | None = None,
- /// account_items: Iterable[tuple[str, str]] | None = None,
+ /// account_items: list[PropertyType] | None = None,
/// account_title: str | None = None,
- /// extra_items: Iterable[tuple[str, str]] | None = None,
+ /// extra_items: list[PropertyType] | None = None,
/// extra_title: str | None = None,
/// verb_cancel: str | None = None,
/// back_button: bool = False,
@@ -1634,10 +1622,10 @@ pub static mp_module_trezorui_api: Module = obj_module! {
/// account_path: str | None,
/// br_code: ButtonRequestType,
/// br_name: str,
- /// address_item: (str, str) | None,
- /// extra_item: (str, str) | None,
- /// summary_items: Iterable[tuple[str, str]] | None = None,
- /// fee_items: Iterable[tuple[str, str]] | None = None,
+ /// address_item: PropertyType | None,
+ /// extra_item: PropertyType | None,
+ /// summary_items: list[PropertyType] | None = None,
+ /// fee_items: list[PropertyType] | None = None,
/// summary_title: str | None = None,
/// summary_br_code: ButtonRequestType | None = None,
/// summary_br_name: str | None = None,
@@ -1912,7 +1900,7 @@ pub static mp_module_trezorui_api: Module = obj_module! {
/// def show_info_with_cancel(
/// *,
/// title: str,
- /// items: Iterable[tuple[str, str]],
+ /// items: list[PropertyType],
/// horizontal: bool = False,
/// chunkify: bool = False,
/// ) -> LayoutObj[UiResult]:
@@ -1959,7 +1947,7 @@ pub static mp_module_trezorui_api: Module = obj_module! {
/// def show_properties(
/// *,
/// title: str,
- /// value: list[tuple[str, str]] | str,
+ /// value: list[PropertyType] | str,
/// ) -> LayoutObj[None]:
/// """Show a list of key-value pairs, or a monospace string."""
Qstr::MP_QSTR_show_properties => obj_fn_kw!(0, new_show_properties).as_obj(),
diff --git a/core/embed/rust/src/ui/layout/util.rs b/core/embed/rust/src/ui/layout/util.rs
index 51cfa967..d90a6111 100644
--- a/core/embed/rust/src/ui/layout/util.rs
+++ b/core/embed/rust/src/ui/layout/util.rs
@@ -114,6 +114,24 @@ impl PropsList {
props_padding,
})
}
+
+ pub fn empty(
+ key_font: &'static TextStyle,
+ value_font: &'static TextStyle,
+ value_mono_font: &'static TextStyle,
+ key_value_padding: i16,
+ props_padding: i16,
+ ) -> Result<Self, Error> {
+ let empty_list = List::alloc(&[])?; // Create an empty GC list
+ Ok(Self {
+ items: empty_list,
+ key_font,
+ value_font,
+ value_mono_font,
+ key_value_padding,
+ props_padding,
+ })
+ }
}
impl ParagraphSource<'static> for PropsList {
diff --git a/core/embed/rust/src/ui/layout_bolt/ui_firmware.rs b/core/embed/rust/src/ui/layout_bolt/ui_firmware.rs
index b8263d4b..4c5c019b 100644
--- a/core/embed/rust/src/ui/layout_bolt/ui_firmware.rs
+++ b/core/embed/rust/src/ui/layout_bolt/ui_firmware.rs
@@ -581,8 +581,8 @@ impl FirmwareUI for UIBolt {
_subtitle: Option<TString<'static>>,
_description: Option<TString<'static>>,
_extra: Option<TString<'static>>,
- _message: Obj,
- _amount: Option<Obj>,
+ _message: TString<'static>,
+ _amount: Option<TString<'static>>,
_chunkify: bool,
_text_mono: bool,
_account_title: TString<'static>,
@@ -590,8 +590,8 @@ impl FirmwareUI for UIBolt {
_account_path: Option<TString<'static>>,
_br_code: u16,
_br_name: TString<'static>,
- _address_item: Option<(TString<'static>, Obj)>,
- _extra_item: Option<(TString<'static>, Obj)>,
+ _address_item: Option<Obj>,
+ _extra_item: Option<Obj>,
_summary_items: Option<Obj>,
_fee_items: Option<Obj>,
_summary_title: Option<TString<'static>>,
@@ -1014,7 +1014,7 @@ impl FirmwareUI for UIBolt {
let mut paragraphs = ParagraphVecShort::new();
for para in IterBuf::new().try_iterate(items)? {
- let [key, value]: [Obj; 2] = util::iter_into_array(para)?;
+ let [key, value, _]: [Obj; 3] = util::iter_into_array(para)?;
let key: TString = key.try_into()?;
let value: TString = value.try_into()?;
paragraphs.add(Paragraph::new(&theme::TEXT_NORMAL, key).no_break());
diff --git a/core/embed/rust/src/ui/layout_caesar/ui_firmware.rs b/core/embed/rust/src/ui/layout_caesar/ui_firmware.rs
index 96c5df99..0e966209 100644
--- a/core/embed/rust/src/ui/layout_caesar/ui_firmware.rs
+++ b/core/embed/rust/src/ui/layout_caesar/ui_firmware.rs
@@ -592,7 +592,7 @@ impl FirmwareUI for UICaesar {
let mut ops = OpTextLayout::new(theme::TEXT_MONO);
for item in unwrap!(IterBuf::new().try_iterate(*info_obj)) {
- let [key, value]: [Obj; 2] = unwrap!(util::iter_into_array(item));
+ let [key, value, _is_data]: [Obj; 3] = unwrap!(util::iter_into_array(item));
if !ops.is_empty() {
// Each key-value pair is on its own page
ops.add_next_page();
@@ -706,8 +706,8 @@ impl FirmwareUI for UICaesar {
_subtitle: Option<TString<'static>>,
_description: Option<TString<'static>>,
_extra: Option<TString<'static>>,
- _message: Obj,
- _amount: Option<Obj>,
+ _message: TString<'static>,
+ _amount: Option<TString<'static>>,
_chunkify: bool,
_text_mono: bool,
_account_title: TString<'static>,
@@ -715,8 +715,8 @@ impl FirmwareUI for UICaesar {
_account_path: Option<TString<'static>>,
_br_code: u16,
_br_name: TString<'static>,
- _address_item: Option<(TString<'static>, Obj)>,
- _extra_item: Option<(TString<'static>, Obj)>,
+ _address_item: Option<Obj>,
+ _extra_item: Option<Obj>,
_summary_items: Option<Obj>,
_fee_items: Option<Obj>,
_summary_title: Option<TString<'static>>,
@@ -1273,7 +1273,7 @@ impl FirmwareUI for UICaesar {
add_paragraphs(&mut paragraphs, None, Some(value.try_into()?), true);
} else {
for para in IterBuf::new().try_iterate(value)? {
- let [key, value]: [Obj; 2] = util::iter_into_array(para)?;
+ let [key, value, _is_data]: [Obj; 3] = util::iter_into_array(para)?;
add_paragraphs(
&mut paragraphs,
key.try_into_option()?,
diff --git a/core/embed/rust/src/ui/layout_delizia/flow/util.rs b/core/embed/rust/src/ui/layout_delizia/flow/util.rs
index d2539d5f..f3999969 100644
--- a/core/embed/rust/src/ui/layout_delizia/flow/util.rs
+++ b/core/embed/rust/src/ui/layout_delizia/flow/util.rs
@@ -1,7 +1,6 @@
use crate::{
error::Error,
maybe_trace::MaybeTrace,
- micropython::obj::Obj,
strutil::TString,
translations::TR,
ui::{
@@ -36,7 +35,7 @@ pub struct ConfirmValue {
subtitle: Option<TString<'static>>,
footer_instruction: Option<TString<'static>>,
footer_description: Option<TString<'static>>,
- value: Obj,
+ value: StrOrBytes,
description: Option<TString<'static>>,
description_font: &'static TextStyle,
extra: Option<TString<'static>>,
@@ -62,7 +61,11 @@ pub struct ConfirmValue {
}
impl ConfirmValue {
- pub fn new(title: TString<'static>, value: Obj, description: Option<TString<'static>>) -> Self {
+ pub fn new(
+ title: TString<'static>,
+ value: StrOrBytes,
+ description: Option<TString<'static>>,
+ ) -> Self {
Self {
title,
subtitle: None,
@@ -228,17 +231,13 @@ impl ConfirmValue {
pub fn into_layout(
self,
) -> Result<impl Component<Msg = FlowMsg> + Swipable + MaybeTrace, Error> {
+ let value_len = self.value.as_str_offset(0).len();
let paragraphs = ConfirmValueParams {
description: self.description.unwrap_or("".into()),
extra: self.extra.unwrap_or("".into()),
- value: if self.value != Obj::const_none() {
- self.value.try_into()?
- } else {
- StrOrBytes::Str("".into())
- },
+ value: self.value,
font: if self.chunkify {
- let value: TString = self.value.try_into()?;
- theme::get_chunkified_text_style(value.len())
+ theme::get_chunkified_text_style(value_len)
} else if self.text_mono {
if self.classic_ellipsis {
&theme::TEXT_MONO_WITH_CLASSIC_ELLIPSIS
@@ -286,13 +285,13 @@ impl ConfirmValue {
}
pub fn into_flow(self) -> Result<SwipeFlow, Error> {
+ let value_len = self.value.as_str_offset(0).len();
let paragraphs = ConfirmValueParams {
description: self.description.unwrap_or("".into()),
extra: self.extra.unwrap_or("".into()),
- value: self.value.try_into()?,
+ value: self.value,
font: if self.chunkify {
- let value: TString = self.value.try_into()?;
- theme::get_chunkified_text_style(value.len())
+ theme::get_chunkified_text_style(value_len)
} else if self.text_mono {
if self.classic_ellipsis {
&theme::TEXT_MONO_WITH_CLASSIC_ELLIPSIS
diff --git a/core/embed/rust/src/ui/layout_delizia/ui_firmware.rs b/core/embed/rust/src/ui/layout_delizia/ui_firmware.rs
index dae42075..33fadd88 100644
--- a/core/embed/rust/src/ui/layout_delizia/ui_firmware.rs
+++ b/core/embed/rust/src/ui/layout_delizia/ui_firmware.rs
@@ -25,7 +25,7 @@ use crate::{
geometry::{self, Direction, Offset},
layout::{
obj::{LayoutMaybeTrace, LayoutObj, RootComponent},
- util::{ContentType, PropsList, RecoveryType},
+ util::{ContentType, PropsList, RecoveryType, StrOrBytes},
},
ui_firmware::{
FirmwareUI, ERROR_NOT_IMPLEMENTED, MAX_CHECKLIST_ITEMS, MAX_GROUP_SHARE_LINES,
@@ -127,7 +127,7 @@ impl FirmwareUI for UIDelizia {
_warning_footer: Option<TString<'static>>,
external_menu: bool,
) -> Result<Gc<LayoutObj>, Error> {
- ConfirmValue::new(title, value, description)
+ ConfirmValue::new(title, value.try_into()?, description)
.with_description_font(&theme::TEXT_SUB_GREY)
.with_text_mono(is_data)
.with_subtitle(subtitle)
@@ -159,20 +159,24 @@ impl FirmwareUI for UIDelizia {
chunkify: bool,
) -> Result<Gc<LayoutObj>, Error> {
const CONFIRM_VALUE_INTRO_MARGIN: usize = 24;
- ConfirmValue::new(title, value, Some(TR::instructions__view_all_data.into()))
- .with_verb(verb)
- .with_verb_info(Some(TR::buttons__view_all_data.into()))
- .with_description_font(&theme::TEXT_SUB_GREEN_LIME)
- .with_subtitle(subtitle)
- .with_verb_cancel(verb_cancel)
- .with_footer_description(verb)
- .with_chunkify(chunkify)
- .with_page_limit(Some(1))
- .with_classic_ellipsis(true)
- .with_frame_margin(CONFIRM_VALUE_INTRO_MARGIN)
- .with_hold(hold)
- .into_flow()
- .and_then(LayoutObj::new_root)
+ ConfirmValue::new(
+ title,
+ value.try_into()?,
+ Some(TR::instructions__view_all_data.into()),
+ )
+ .with_verb(verb)
+ .with_verb_info(Some(TR::buttons__view_all_data.into()))
+ .with_description_font(&theme::TEXT_SUB_GREEN_LIME)
+ .with_subtitle(subtitle)
+ .with_verb_cancel(verb_cancel)
+ .with_footer_description(verb)
+ .with_chunkify(chunkify)
+ .with_page_limit(Some(1))
+ .with_classic_ellipsis(true)
+ .with_frame_margin(CONFIRM_VALUE_INTRO_MARGIN)
+ .with_hold(hold)
+ .into_flow()
+ .and_then(LayoutObj::new_root)
}
fn confirm_homescreen(
@@ -411,8 +415,8 @@ impl FirmwareUI for UIDelizia {
let account_title = account_title.unwrap_or(TR::send__send_from.into());
let mut account_params = ShowInfoParams::new(account_title).with_cancel_button();
for pair in IterBuf::new().try_iterate(items)? {
- let [label, value]: [TString; 2] = util::iter_into_array(pair)?;
- account_params = unwrap!(account_params.add(label, value));
+ let [key, value, _is_data]: [Obj; 3] = util::iter_into_array(pair)?;
+ account_params = unwrap!(account_params.add(key.try_into()?, value.try_into()?));
}
Some(account_params)
} else {
@@ -422,8 +426,8 @@ impl FirmwareUI for UIDelizia {
let extra_title = extra_title.unwrap_or(TR::buttons__more_info.into());
let mut extra_params = ShowInfoParams::new(extra_title).with_cancel_button();
for pair in IterBuf::new().try_iterate(items)? {
- let [label, value]: [TString; 2] = util::iter_into_array(pair)?;
- extra_params = unwrap!(extra_params.add(label, value));
+ let [label, value, _is_data]: [Obj; 3] = util::iter_into_array(pair)?;
+ extra_params = unwrap!(extra_params.add(label.try_into()?, value.try_into()?));
}
Some(extra_params)
} else {
@@ -548,8 +552,8 @@ impl FirmwareUI for UIDelizia {
subtitle: Option<TString<'static>>,
description: Option<TString<'static>>,
extra: Option<TString<'static>>,
- message: Obj,
- amount: Option<Obj>,
+ message: TString<'static>,
+ amount: Option<TString<'static>>,
chunkify: bool,
text_mono: bool,
account_title: TString<'static>,
@@ -557,8 +561,8 @@ impl FirmwareUI for UIDelizia {
account_path: Option<TString<'static>>,
br_code: u16,
br_name: TString<'static>,
- address_item: Option<(TString<'static>, Obj)>,
- extra_item: Option<(TString<'static>, Obj)>,
+ address_item: Option<Obj>,
+ extra_item: Option<Obj>,
summary_items: Option<Obj>,
fee_items: Option<Obj>,
summary_title: Option<TString<'static>>,
@@ -566,19 +570,22 @@ impl FirmwareUI for UIDelizia {
summary_br_name: Option<TString<'static>>,
cancel_text: Option<TString<'static>>,
) -> Result<impl LayoutMaybeTrace, Error> {
- let confirm_main =
- ConfirmValue::new(title.unwrap_or(TString::empty()), message, description)
- .with_description_font(&theme::TEXT_MAIN_GREY_LIGHT)
- .with_subtitle(subtitle)
- .with_extra(extra)
- .with_extra_font(&theme::TEXT_SUB_GREY)
- .with_menu_button()
- .with_swipeup_footer(None)
- .with_chunkify(chunkify)
- .with_text_mono(text_mono);
+ let confirm_main = ConfirmValue::new(
+ title.unwrap_or(TString::empty()),
+ message.into(),
+ description,
+ )
+ .with_description_font(&theme::TEXT_MAIN_GREY_LIGHT)
+ .with_subtitle(subtitle)
+ .with_extra(extra)
+ .with_extra_font(&theme::TEXT_SUB_GREY)
+ .with_menu_button()
+ .with_swipeup_footer(None)
+ .with_chunkify(chunkify)
+ .with_text_mono(text_mono);
let confirm_amount = amount.map(|amount| {
- ConfirmValue::new(TR::words__amount.into(), amount, None)
+ ConfirmValue::new(TR::words__amount.into(), amount.into(), None)
.with_subtitle(subtitle)
.with_menu_button()
.with_swipeup_footer(None)
@@ -586,26 +593,37 @@ impl FirmwareUI for UIDelizia {
.with_swipe_down()
});
- let confirm_address = address_item.map(|(address_title, address)| {
- ConfirmValue::new(address_title, address, None)
- .with_cancel_button()
- .with_chunkify(true)
- .with_text_mono(true)
+ let confirm_address = address_item.map(|address_item| {
+ let [key, value, _is_data]: [Obj; 3] = unwrap!(util::iter_into_array(address_item));
+ ConfirmValue::new(
+ key.try_into().unwrap_or(TString::empty()),
+ value.try_into().unwrap_or(StrOrBytes::Str("".into())),
+ None,
+ )
+ .with_cancel_button()
+ .with_chunkify(true)
+ .with_text_mono(true)
});
- let confirm_extra = extra_item.map(|(extra_title, extra)| {
- ConfirmValue::new(extra_title, extra, None)
- .with_cancel_button()
- .with_chunkify(true)
- .with_text_mono(true)
+ let confirm_extra = extra_item.map(|extra_item| {
+ let [key, value, _is_data]: [Obj; 3] = unwrap!(util::iter_into_array(extra_item));
+ ConfirmValue::new(
+ key.try_into().unwrap_or(TString::empty()),
+ value.try_into().unwrap_or(StrOrBytes::Str("".into())),
+ None,
+ )
+ .with_cancel_button()
+ .with_chunkify(true)
+ .with_text_mono(true)
});
let mut fee_items_params =
ShowInfoParams::new(TR::confirm_total__title_fee.into()).with_cancel_button();
if fee_items.is_some() {
for pair in IterBuf::new().try_iterate(fee_items.unwrap())? {
- let [label, value]: [TString; 2] = util::iter_into_array(pair)?;
- fee_items_params = unwrap!(fee_items_params.add(label, value));
+ let [key, value, _is_data]: [Obj; 3] = util::iter_into_array(pair)?;
+ fee_items_params =
+ unwrap!(fee_items_params.add(key.try_into()?, value.try_into()?));
}
}
@@ -615,9 +633,9 @@ impl FirmwareUI for UIDelizia {
.with_menu_button()
.with_swipeup_footer(None)
.with_swipe_down();
- for pair in IterBuf::new().try_iterate(summary_items.unwrap())? {
- let [label, value]: [TString; 2] = util::iter_into_array(pair)?;
- summary = unwrap!(summary.add(label, value));
+ for property in IterBuf::new().try_iterate(summary_items.unwrap())? {
+ let [key, value, _is_data]: [Obj; 3] = util::iter_into_array(property)?;
+ summary = unwrap!(summary.add(key.try_into()?, value.try_into()?));
}
Some(summary)
} else {
@@ -1069,7 +1087,7 @@ impl FirmwareUI for UIDelizia {
let mut paragraphs = ParagraphVecShort::new();
for para in IterBuf::new().try_iterate(items)? {
- let [key, value]: [Obj; 2] = util::iter_into_array(para)?;
+ let [key, value, _]: [Obj; 3] = util::iter_into_array(para)?;
let key: TString = key.try_into()?;
let value: TString = value.try_into()?;
paragraphs.add(Paragraph::new(&theme::TEXT_SUB_GREY, key).no_break());
@@ -1159,7 +1177,7 @@ impl FirmwareUI for UIDelizia {
value: Obj,
) -> Result<impl LayoutMaybeTrace, Error> {
if Obj::is_str(value) {
- let confirm = ConfirmValue::new(title, value, None)
+ let confirm = ConfirmValue::new(title, value.try_into()?, None)
.with_cancel_button()
.with_text_mono(true);
let layout = confirm.into_layout()?;
@@ -1168,7 +1186,7 @@ impl FirmwareUI for UIDelizia {
let mut params = ShowInfoParams::new(title).with_cancel_button();
for property in IterBuf::new().try_iterate(value)? {
- let [header, text]: [Obj; 2] = util::iter_into_array(property)?;
+ let [header, text, _is_data]: [Obj; 3] = util::iter_into_array(property)?;
let header = header
.try_into_option::<TString>()?
.unwrap_or_else(TString::empty);
diff --git a/core/embed/rust/src/ui/layout_eckhart/flow/confirm_output.rs b/core/embed/rust/src/ui/layout_eckhart/flow/confirm_output.rs
index 32912e77..9dad52b3 100644
--- a/core/embed/rust/src/ui/layout_eckhart/flow/confirm_output.rs
+++ b/core/embed/rust/src/ui/layout_eckhart/flow/confirm_output.rs
@@ -2,7 +2,6 @@ use heapless::Vec;
use crate::{
error,
- micropython::obj::Obj,
strutil::TString,
time::Duration,
translations::TR,
@@ -17,7 +16,7 @@ use crate::{
FlowController, FlowMsg, SwipeFlow,
},
geometry::{Direction, LinearPlacement},
- layout::util::StrOrBytes,
+ layout::util::PropsList,
},
};
@@ -27,6 +26,7 @@ use super::super::{
ActionBar, Header, ShortMenuVec, TextScreen, TextScreenMsg, VerticalMenu,
VerticalMenuScreen, VerticalMenuScreenMsg,
},
+ flow::util::content_menu_info,
theme::{self, gradient::Gradient},
};
@@ -252,31 +252,12 @@ fn content_main_menu(
})
}
-fn content_menu_info(
- title: TString<'static>,
- subtitle: Option<TString<'static>>,
- paragraphs: Option<ParagraphVecShort<'static>>,
-) -> MsgMap<
- TextScreen<Paragraphs<ParagraphVecShort<'static>>>,
- impl Fn(TextScreenMsg) -> Option<FlowMsg>,
-> {
- TextScreen::new(
- paragraphs
- .map_or_else(ParagraphVecShort::new, |p| p)
- .into_paragraphs()
- .with_placement(LinearPlacement::vertical().with_spacing(theme::PROP_INNER_SPACING)),
- )
- .with_header(Header::new(title).with_close_button())
- .with_subtitle(subtitle.unwrap_or(TString::empty()))
- .map(|_| Some(FlowMsg::Cancelled))
-}
-
#[allow(clippy::too_many_arguments)]
pub fn new_confirm_output(
title: Option<TString<'static>>,
subtitle: Option<TString<'static>>,
main_paragraphs: ParagraphVecShort<'static>,
- amount: Option<Obj>,
+ amount: Option<TString<'static>>,
br_name: TString<'static>,
br_code: u16,
account_title: TString<'static>,
@@ -284,12 +265,12 @@ pub fn new_confirm_output(
address_title: Option<TString<'static>>,
address_paragraph: Option<Paragraph<'static>>,
summary_title: Option<TString<'static>>,
- summary_paragraphs: Option<ParagraphVecShort<'static>>,
+ summary_paragraphs: Option<PropsList>,
summary_br_code: Option<u16>,
summary_br_name: Option<TString<'static>>,
extra_title: Option<TString<'static>>,
extra_paragraph: Option<Paragraph<'static>>,
- fee_paragraphs: Option<ParagraphVecShort<'static>>,
+ fee_paragraphs: Option<PropsList>,
cancel_menu_label: Option<TString<'static>>,
) -> Result<SwipeFlow, error::Error> {
let cancel_menu_label = cancel_menu_label.unwrap_or(TR::buttons__cancel.into());
@@ -301,22 +282,21 @@ pub fn new_confirm_output(
let account_subtitle = Some(TR::send__send_from.into());
// Main
- let content_main = TextScreen::new(
- main_paragraphs
- .into_paragraphs()
- .with_placement(LinearPlacement::vertical().with_spacing(theme::PROP_INNER_SPACING)),
- )
- .with_header(Header::new(title.unwrap_or(TString::empty())).with_menu_button())
- .with_action_bar(ActionBar::new_single(Button::with_text(
- TR::buttons__continue.into(),
- )))
- .with_subtitle(subtitle.unwrap_or(TString::empty()))
- .map(|msg| match msg {
- TextScreenMsg::Confirmed => Some(FlowMsg::Confirmed),
- TextScreenMsg::Cancelled => Some(FlowMsg::Cancelled),
- TextScreenMsg::Menu => Some(FlowMsg::Info),
- })
- .one_button_request(ButtonRequest::from_num(br_code, br_name));
+ let content_main =
+ TextScreen::new(main_paragraphs.into_paragraphs().with_placement(
+ LinearPlacement::vertical().with_spacing(theme::TEXT_VERTICAL_SPACING),
+ ))
+ .with_header(Header::new(title.unwrap_or(TString::empty())).with_menu_button())
+ .with_action_bar(ActionBar::new_single(Button::with_text(
+ TR::buttons__continue.into(),
+ )))
+ .with_subtitle(subtitle.unwrap_or(TString::empty()))
+ .map(|msg| match msg {
+ TextScreenMsg::Confirmed => Some(FlowMsg::Confirmed),
+ TextScreenMsg::Cancelled => Some(FlowMsg::Cancelled),
+ TextScreenMsg::Menu => Some(FlowMsg::Info),
+ })
+ .one_button_request(ButtonRequest::from_num(br_code, br_name));
// Cancelled
let content_cancelled = TextScreen::new(
@@ -334,13 +314,7 @@ pub fn new_confirm_output(
let res = if let Some(amount) = amount {
let amount_paragraphs = ParagraphVecShort::from_iter([
Paragraph::new(&theme::TEXT_SMALL_LIGHT, TR::words__amount).no_break(),
- Paragraph::new(
- &theme::TEXT_MONO_MEDIUM_LIGHT,
- amount
- .try_into()
- .unwrap_or(StrOrBytes::Str("".into()))
- .as_str_offset(0),
- ),
+ Paragraph::new(&theme::TEXT_MONO_MEDIUM_LIGHT, amount),
]);
let content_amount = TextScreen::new(
@@ -377,7 +351,9 @@ pub fn new_confirm_output(
content_menu_info(
TR::address_details__account_info.into(),
account_subtitle,
- account_paragraphs.clone(),
+ account_paragraphs
+ .clone()
+ .map_or_else(ParagraphVecShort::new, |p| p),
),
)?
.add_page(&ConfirmOutputWithAmount::AddressCancel, content_cancel())?
@@ -393,37 +369,44 @@ pub fn new_confirm_output(
)?
.add_page(
&ConfirmOutputWithAmount::AmountAccountInfo,
- content_menu_info(account_title, account_subtitle, account_paragraphs.clone()),
+ content_menu_info(
+ account_title,
+ account_subtitle,
+ account_paragraphs
+ .clone()
+ .map_or_else(ParagraphVecShort::new, |p| p),
+ ),
)?
.add_page(&ConfirmOutputWithAmount::AmountCancel, content_cancel())?
.add_page(&ConfirmOutputWithAmount::Cancelled, content_cancelled)?;
flow
} else if let Some(summary_paragraphs) = summary_paragraphs {
// Summary
- let content_summary =
- TextScreen::new(summary_paragraphs.into_paragraphs().with_placement(
- LinearPlacement::vertical().with_spacing(theme::PROP_INNER_SPACING),
- ))
- .with_header(
- Header::new(summary_title.unwrap_or(TR::words__title_summary.into()))
- .with_menu_button(),
- )
- .with_action_bar(ActionBar::new_double(
- Button::with_icon(theme::ICON_CHEVRON_UP),
- Button::with_text(TR::instructions__hold_to_sign.into())
- .with_long_press(theme::CONFIRM_HOLD_DURATION)
- .styled(theme::button_confirm())
- .with_gradient(Gradient::SignGreen),
- ))
- .map(|msg| match msg {
- TextScreenMsg::Confirmed => Some(FlowMsg::Confirmed),
- TextScreenMsg::Cancelled => Some(FlowMsg::Cancelled),
- TextScreenMsg::Menu => Some(FlowMsg::Info),
- })
- .one_button_request(ButtonRequest::from_num(
- summary_br_code.unwrap(),
- summary_br_name.unwrap(),
- ));
+ let content_summary = TextScreen::new(
+ summary_paragraphs
+ .into_paragraphs()
+ .with_placement(LinearPlacement::vertical()),
+ )
+ .with_header(
+ Header::new(summary_title.unwrap_or(TR::words__title_summary.into()))
+ .with_menu_button(),
+ )
+ .with_action_bar(ActionBar::new_double(
+ Button::with_icon(theme::ICON_CHEVRON_UP),
+ Button::with_text(TR::instructions__hold_to_sign.into())
+ .with_long_press(theme::CONFIRM_HOLD_DURATION)
+ .styled(theme::button_confirm())
+ .with_gradient(Gradient::SignGreen),
+ ))
+ .map(|msg| match msg {
+ TextScreenMsg::Confirmed => Some(FlowMsg::Confirmed),
+ TextScreenMsg::Cancelled => Some(FlowMsg::Cancelled),
+ TextScreenMsg::Menu => Some(FlowMsg::Info),
+ })
+ .one_button_request(ButtonRequest::from_num(
+ summary_br_code.unwrap(),
+ summary_br_name.unwrap(),
+ ));
// SummaryMenu
let mut summary_menu = VerticalMenu::<ShortMenuVec>::empty();
@@ -477,12 +460,19 @@ pub fn new_confirm_output(
address_title,
None,
address_paragraph
- .map(|address_paragraph| ParagraphVecShort::from_iter([address_paragraph])),
+ .map(|address_paragraph| ParagraphVecShort::from_iter([address_paragraph]))
+ .map_or_else(ParagraphVecShort::new, |p| p),
),
)?
.add_page(
&ConfirmOutputWithSummary::MainMenuAccountInfo,
- content_menu_info(account_title, account_subtitle, account_paragraphs.clone()),
+ content_menu_info(
+ account_title,
+ account_subtitle,
+ account_paragraphs
+ .clone()
+ .map_or_else(ParagraphVecShort::new, |p| p),
+ ),
)?
.add_page(&ConfirmOutputWithSummary::Summary, content_summary)?
.add_page(&ConfirmOutputWithSummary::SummaryMenu, content_summary_menu)?
@@ -492,7 +482,19 @@ pub fn new_confirm_output(
)?
.add_page(
&ConfirmOutputWithSummary::SummaryMenuFeeInfo,
- content_menu_info(TR::confirm_total__title_fee.into(), None, fee_paragraphs),
+ content_menu_info(
+ TR::confirm_total__title_fee.into(),
+ None,
+ fee_paragraphs.unwrap_or_else(|| {
+ unwrap!(PropsList::empty(
+ &theme::TEXT_SMALL_LIGHT,
+ &theme::TEXT_MONO_MEDIUM_LIGHT,
+ &theme::TEXT_MONO_MEDIUM_LIGHT,
+ theme::PROP_INNER_SPACING,
+ theme::PROPS_SPACING,
+ ))
+ }),
+ ),
)?
.add_page(
&ConfirmOutputWithSummary::SummaryMenuExtraInfo,
@@ -500,7 +502,8 @@ pub fn new_confirm_output(
extra_title.unwrap_or(TString::empty()),
None,
extra_paragraph
- .map(|extra_paragraph| ParagraphVecShort::from_iter([extra_paragraph])),
+ .map(|extra_paragraph| ParagraphVecShort::from_iter([extra_paragraph]))
+ .map_or_else(ParagraphVecShort::new, |p| p),
),
)?
.add_page(&ConfirmOutputWithSummary::Cancelled, content_cancelled)?;
@@ -519,7 +522,11 @@ pub fn new_confirm_output(
)?
.add_page(
&ConfirmOutput::AccountInfo,
- content_menu_info(account_title, account_subtitle, account_paragraphs),
+ content_menu_info(
+ account_title,
+ account_subtitle,
+ account_paragraphs.map_or_else(ParagraphVecShort::new, |p| p),
+ ),
)?
.add_page(&ConfirmOutput::Cancel, content_cancel())?
.add_page(&ConfirmOutput::Cancelled, content_cancelled)?;
diff --git a/core/embed/rust/src/ui/layout_eckhart/flow/confirm_set_new_pin.rs b/core/embed/rust/src/ui/layout_eckhart/flow/confirm_set_new_pin.rs
index c7ab4db3..2e015820 100644
--- a/core/embed/rust/src/ui/layout_eckhart/flow/confirm_set_new_pin.rs
+++ b/core/embed/rust/src/ui/layout_eckhart/flow/confirm_set_new_pin.rs
@@ -88,7 +88,7 @@ pub fn new_set_new_pin(
])
.into_paragraphs()
.with_placement(LinearPlacement::vertical())
- .with_spacing(24);
+ .with_spacing(theme::TEXT_VERTICAL_SPACING);
let content_cancel = TextScreen::new(paragraphs_cancel_intro)
.with_header(
diff --git a/core/embed/rust/src/ui/layout_eckhart/flow/confirm_summary.rs b/core/embed/rust/src/ui/layout_eckhart/flow/confirm_summary.rs
index c3bdddac..47f10d57 100644
--- a/core/embed/rust/src/ui/layout_eckhart/flow/confirm_summary.rs
+++ b/core/embed/rust/src/ui/layout_eckhart/flow/confirm_summary.rs
@@ -7,14 +7,15 @@ use crate::{
translations::TR,
ui::{
component::{
- text::paragraphs::{Paragraph, ParagraphSource, ParagraphVecShort, Paragraphs, VecExt},
- ComponentExt, MsgMap,
+ text::paragraphs::{Paragraph, ParagraphSource, ParagraphVecShort, VecExt},
+ ComponentExt,
},
flow::{
base::{Decision, DecisionBuilder as _},
FlowController, FlowMsg, SwipeFlow,
},
geometry::{Direction, LinearPlacement},
+ layout::util::PropsList,
},
};
@@ -24,6 +25,7 @@ use super::super::{
ActionBar, Header, Hint, ShortMenuVec, TextScreen, TextScreenMsg, VerticalMenu,
VerticalMenuScreen, VerticalMenuScreenMsg,
},
+ flow::util::content_menu_info,
theme::{self, gradient::Gradient},
};
@@ -70,25 +72,6 @@ impl FlowController for ConfirmSummary {
}
}
-fn content_menu_info(
- title: TString<'static>,
- subtitle: Option<TString<'static>>,
- paragraphs: Option<ParagraphVecShort<'static>>,
-) -> MsgMap<
- TextScreen<Paragraphs<ParagraphVecShort<'static>>>,
- impl Fn(TextScreenMsg) -> Option<FlowMsg>,
-> {
- TextScreen::new(
- paragraphs
- .map_or_else(ParagraphVecShort::new, |p| p)
- .into_paragraphs()
- .with_placement(LinearPlacement::vertical().with_spacing(theme::PROP_INNER_SPACING)),
- )
- .with_header(Header::new(title).with_close_button())
- .with_subtitle(subtitle.unwrap_or(TString::empty()))
- .map(|_| Some(FlowMsg::Cancelled))
-}
-
#[allow(clippy::too_many_arguments)]
pub fn new_confirm_summary(
title: TString<'static>,
@@ -97,22 +80,37 @@ pub fn new_confirm_summary(
fee: TString<'static>,
fee_label: TString<'static>,
account_title: Option<TString<'static>>,
- account_paragraphs: Option<ParagraphVecShort<'static>>,
+ account_paragraphs: Option<PropsList>,
extra_title: Option<TString<'static>>,
- extra_paragraphs: Option<ParagraphVecShort<'static>>,
+ extra_paragraphs: Option<PropsList>,
verb_cancel: Option<TString<'static>>,
back_button: bool,
) -> Result<SwipeFlow, error::Error> {
// Summary
let mut summary_paragraphs = ParagraphVecShort::new();
if let Some(amount_label) = amount_label {
- summary_paragraphs.add(Paragraph::new(&theme::TEXT_SMALL_LIGHT, amount_label));
+ let para = Paragraph::new(&theme::TEXT_SMALL_LIGHT, amount_label);
+ if amount.is_some() {
+ summary_paragraphs.add(
+ para.with_bottom_padding(theme::PROP_INNER_SPACING)
+ .no_break(),
+ );
+ } else {
+ summary_paragraphs.add(para.with_bottom_padding(theme::PROPS_SPACING));
+ }
}
if let Some(amount) = amount {
- summary_paragraphs.add(Paragraph::new(&theme::TEXT_MONO_MEDIUM_LIGHT, amount));
+ summary_paragraphs.add(
+ Paragraph::new(&theme::TEXT_MONO_MEDIUM_LIGHT, amount)
+ .with_bottom_padding(theme::PROPS_SPACING),
+ );
}
summary_paragraphs
- .add(Paragraph::new(&theme::TEXT_SMALL_LIGHT, fee_label))
+ .add(
+ Paragraph::new(&theme::TEXT_SMALL_LIGHT, fee_label)
+ .with_bottom_padding(theme::PROP_INNER_SPACING)
+ .no_break(),
+ )
.add(Paragraph::new(&theme::TEXT_MONO_MEDIUM_LIGHT, fee));
let confirm_button = Button::with_text(TR::instructions__hold_to_sign.into())
@@ -122,7 +120,7 @@ pub fn new_confirm_summary(
let content_summary = TextScreen::new(
summary_paragraphs
.into_paragraphs()
- .with_placement(LinearPlacement::vertical().with_spacing(theme::PROP_INNER_SPACING)),
+ .with_placement(LinearPlacement::vertical()),
)
.with_header(Header::new(title).with_menu_button())
.with_action_bar(if back_button {
@@ -182,14 +180,30 @@ pub fn new_confirm_summary(
let content_extra = content_menu_info(
extra_title.unwrap_or(TR::buttons__more_info.into()),
None,
- extra_paragraphs,
+ extra_paragraphs.unwrap_or_else(|| {
+ unwrap!(PropsList::empty(
+ &theme::TEXT_SMALL_LIGHT,
+ &theme::TEXT_MONO_LIGHT,
+ &theme::TEXT_MONO_LIGHT,
+ theme::PROP_INNER_SPACING,
+ theme::PROPS_SPACING,
+ ))
+ }),
);
// AccountInfo
let content_account = content_menu_info(
account_title.unwrap_or(TR::address_details__account_info.into()),
Some(TR::send__send_from.into()),
- account_paragraphs,
+ account_paragraphs.unwrap_or_else(|| {
+ unwrap!(PropsList::empty(
+ &theme::TEXT_SMALL_LIGHT,
+ &theme::TEXT_MONO_LIGHT,
+ &theme::TEXT_MONO_LIGHT,
+ theme::PROP_INNER_SPACING,
+ theme::PROPS_SPACING,
+ ))
+ }),
);
// Cancel
diff --git a/core/embed/rust/src/ui/layout_eckhart/flow/util.rs b/core/embed/rust/src/ui/layout_eckhart/flow/util.rs
index 0bd90f03..609d396b 100644
--- a/core/embed/rust/src/ui/layout_eckhart/flow/util.rs
+++ b/core/embed/rust/src/ui/layout_eckhart/flow/util.rs
@@ -1,16 +1,22 @@
use crate::{
error::Error,
maybe_trace::MaybeTrace,
+ strutil::TString,
ui::{
- component::Component,
+ component::{
+ text::paragraphs::{ParagraphSource, Paragraphs},
+ Component, ComponentExt, MsgMap,
+ },
flow::{
base::{Decision, DecisionBuilder},
FlowController, FlowMsg, Swipable, SwipeFlow,
},
- geometry::Direction,
+ geometry::{Direction, LinearPlacement},
},
};
+use super::super::firmware::{Header, TextScreen, TextScreenMsg};
+
enum SinglePage {
Show,
}
@@ -38,3 +44,21 @@ where
flow.add_page(&SinglePage::Show, layout)?;
Ok(flow)
}
+
+pub fn content_menu_info<'a, P>(
+ title: TString<'static>,
+ subtitle: Option<TString<'static>>,
+ paragraphs: P,
+) -> MsgMap<TextScreen<Paragraphs<P>>, impl Fn(TextScreenMsg) -> Option<FlowMsg>>
+where
+ P: ParagraphSource<'a> + 'a,
+{
+ TextScreen::new(
+ paragraphs
+ .into_paragraphs()
+ .with_placement(LinearPlacement::vertical()),
+ )
+ .with_header(Header::new(title).with_close_button())
+ .with_subtitle(subtitle.unwrap_or(TString::empty()))
+ .map(|_| Some(FlowMsg::Cancelled))
+}
diff --git a/core/embed/rust/src/ui/layout_eckhart/ui_firmware.rs b/core/embed/rust/src/ui/layout_eckhart/ui_firmware.rs
index e799bc16..198dcef1 100644
--- a/core/embed/rust/src/ui/layout_eckhart/ui_firmware.rs
+++ b/core/embed/rust/src/ui/layout_eckhart/ui_firmware.rs
@@ -143,13 +143,17 @@ impl FirmwareUI for UIEckhart {
max_rounds: TString<'static>,
max_feerate: TString<'static>,
) -> Result<impl LayoutMaybeTrace, Error> {
- let paragraphs = ParagraphVecShort::from_iter([
- Paragraph::new(&theme::TEXT_REGULAR, TR::coinjoin__max_rounds),
- Paragraph::new(&theme::TEXT_MONO_LIGHT, max_rounds),
- Paragraph::new(&theme::TEXT_REGULAR, TR::coinjoin__max_mining_fee),
+ let paragraphs = Paragraphs::new([
+ Paragraph::new(&theme::TEXT_REGULAR, TR::coinjoin__max_rounds)
+ .with_bottom_padding(theme::PROP_INNER_SPACING)
+ .no_break(),
+ Paragraph::new(&theme::TEXT_MONO_LIGHT, max_rounds)
+ .with_bottom_padding(theme::PROPS_SPACING),
+ Paragraph::new(&theme::TEXT_REGULAR, TR::coinjoin__max_mining_fee)
+ .with_bottom_padding(theme::PROP_INNER_SPACING)
+ .no_break(),
Paragraph::new(&theme::TEXT_MONO_LIGHT, max_feerate),
])
- .into_paragraphs()
.with_placement(LinearPlacement::vertical());
let screen = TextScreen::new(paragraphs)
@@ -253,7 +257,10 @@ impl FirmwareUI for UIEckhart {
Paragraph::new(&theme::TEXT_SMALL_LIGHT, description)
.with_bottom_padding(theme::PROP_INNER_SPACING),
)
- .add(Paragraph::new(&theme::TEXT_MONO_EXTRA_LIGHT, change).with_bottom_padding(16));
+ .add(
+ Paragraph::new(&theme::TEXT_MONO_EXTRA_LIGHT, change)
+ .with_bottom_padding(theme::PROPS_SPACING),
+ );
}
paragraphs
.add(
@@ -288,19 +295,23 @@ impl FirmwareUI for UIEckhart {
TR::modify_amount__increase_amount
};
- let paragraphs = ParagraphVecShort::from_iter([
- Paragraph::new(&theme::TEXT_SMALL_LIGHT, description),
- Paragraph::new(&theme::TEXT_MONO_EXTRA_LIGHT, amount_change),
- Paragraph::new(&theme::TEXT_SMALL_LIGHT, TR::modify_amount__new_amount),
+ let paragraphs = Paragraphs::new([
+ Paragraph::new(&theme::TEXT_SMALL_LIGHT, description)
+ .with_bottom_padding(theme::PROP_INNER_SPACING)
+ .no_break(),
+ Paragraph::new(&theme::TEXT_MONO_EXTRA_LIGHT, amount_change)
+ .with_bottom_padding(theme::PROPS_SPACING),
+ Paragraph::new(&theme::TEXT_SMALL_LIGHT, TR::modify_amount__new_amount)
+ .with_bottom_padding(theme::PROP_INNER_SPACING)
+ .no_break(),
Paragraph::new(&theme::TEXT_MONO_EXTRA_LIGHT, amount_new),
- ]);
+ ])
+ .with_placement(LinearPlacement::vertical());
let layout = RootComponent::new(
- TextScreen::new(paragraphs.into_paragraphs().with_placement(
- LinearPlacement::vertical().with_spacing(theme::PROP_INNER_SPACING),
- ))
- .with_header(Header::new(TR::modify_amount__title.into()))
- .with_action_bar(ActionBar::new_cancel_confirm()),
+ TextScreen::new(paragraphs)
+ .with_header(Header::new(TR::modify_amount__title.into()))
+ .with_action_bar(ActionBar::new_cancel_confirm()),
);
Ok(layout)
}
@@ -336,26 +347,26 @@ impl FirmwareUI for UIEckhart {
) -> Result<impl LayoutMaybeTrace, Error> {
// collect available info
let account_paragraphs = if let Some(items) = account_items {
- let mut paragraphs = ParagraphVecShort::new();
- for pair in IterBuf::new().try_iterate(items)? {
- let [label, value]: [TString; 2] = util::iter_into_array(pair)?;
- paragraphs
- .add(Paragraph::new(&theme::TEXT_SMALL_LIGHT, label).no_break())
- .add(Paragraph::new(&theme::TEXT_MONO_LIGHT, value));
- }
- Some(paragraphs)
+ Some(PropsList::new(
+ items,
+ &theme::TEXT_SMALL_LIGHT,
+ &theme::TEXT_MONO_LIGHT,
+ &theme::TEXT_MONO_LIGHT,
+ theme::PROP_INNER_SPACING,
+ theme::PROPS_SPACING,
+ )?)
} else {
None
};
let extra_paragraphs = if let Some(items) = extra_items {
- let mut paragraphs = ParagraphVecShort::new();
- for pair in IterBuf::new().try_iterate(items)? {
- let [label, value]: [TString; 2] = util::iter_into_array(pair)?;
- paragraphs
- .add(Paragraph::new(&theme::TEXT_SMALL_LIGHT, label).no_break())
- .add(Paragraph::new(&theme::TEXT_MONO_LIGHT, value));
- }
- Some(paragraphs)
+ Some(PropsList::new(
+ items,
+ &theme::TEXT_SMALL_LIGHT,
+ &theme::TEXT_MONO_LIGHT,
+ &theme::TEXT_MONO_LIGHT,
+ theme::PROP_INNER_SPACING,
+ theme::PROPS_SPACING,
+ )?)
} else {
None
};
@@ -391,20 +402,12 @@ impl FirmwareUI for UIEckhart {
&theme::TEXT_MONO_MEDIUM_LIGHT_DATA,
theme::PROP_INNER_SPACING,
theme::PROPS_SPACING,
- )?;
+ )?
+ .into_paragraphs()
+ .with_placement(LinearPlacement::vertical());
- let flow = flow::new_confirm_with_menu(
- title,
- None,
- paragraphs.into_paragraphs().with_placement(
- LinearPlacement::vertical().with_spacing(theme::PROP_INNER_SPACING),
- ),
- None,
- verb,
- hold,
- None,
- None,
- )?;
+ let flow =
+ flow::new_confirm_with_menu(title, None, paragraphs, None, verb, hold, None, None)?;
Ok(flow)
}
@@ -588,7 +591,7 @@ impl FirmwareUI for UIEckhart {
paragraphs
.into_paragraphs()
.with_placement(LinearPlacement::vertical())
- .with_spacing(12),
+ .with_spacing(theme::TEXT_VERTICAL_SPACING),
None,
Some(verb),
false,
@@ -651,8 +654,8 @@ impl FirmwareUI for UIEckhart {
subtitle: Option<TString<'static>>,
description: Option<TString<'static>>,
extra: Option<TString<'static>>,
- message: Obj,
- amount: Option<Obj>,
+ message: TString<'static>,
+ amount: Option<TString<'static>>,
chunkify: bool,
text_mono: bool,
account_title: TString<'static>,
@@ -660,8 +663,8 @@ impl FirmwareUI for UIEckhart {
account_path: Option<TString<'static>>,
br_code: u16,
br_name: TString<'static>,
- address_item: Option<(TString<'static>, Obj)>,
- extra_item: Option<(TString<'static>, Obj)>,
+ address_item: Option<Obj>,
+ extra_item: Option<Obj>,
summary_items: Option<Obj>,
fee_items: Option<Obj>,
summary_title: Option<TString<'static>>,
@@ -671,10 +674,15 @@ impl FirmwareUI for UIEckhart {
) -> Result<impl LayoutMaybeTrace, Error> {
let mut main_paragraphs = ParagraphVecShort::new();
if let Some(description) = description {
- main_paragraphs.add(Paragraph::new(&theme::TEXT_REGULAR, description));
+ main_paragraphs.add(
+ Paragraph::new(&theme::TEXT_REGULAR, description)
+ .with_bottom_padding(theme::PROPS_SPACING),
+ );
}
if let Some(extra) = extra {
- main_paragraphs.add(Paragraph::new(&theme::TEXT_SMALL, extra));
+ main_paragraphs.add(
+ Paragraph::new(&theme::TEXT_SMALL, extra).with_bottom_padding(theme::PROPS_SPACING),
+ );
}
let font = if chunkify {
&theme::TEXT_MONO_ADDRESS_CHUNKS
@@ -683,17 +691,18 @@ impl FirmwareUI for UIEckhart {
} else {
&theme::TEXT_REGULAR
};
- main_paragraphs.add(Paragraph::new(
- font,
- message.try_into().unwrap_or(TString::empty()),
- ));
+ main_paragraphs.add(Paragraph::new(font, message));
- let (address_title, address_paragraph) = if let Some((title, item)) = address_item {
+ let (address_title, address_paragraph) = if let Some(address_item) = address_item {
+ let [key, value, _is_data]: [Obj; 3] = util::iter_into_array(address_item)?;
let paragraph = Paragraph::new(
&theme::TEXT_MONO_ADDRESS_CHUNKS,
- item.try_into().unwrap_or(TString::empty()),
+ value.try_into().unwrap_or(TString::empty()),
);
- (Some(title), Some(paragraph))
+ (
+ Some(key.try_into().unwrap_or(TString::empty())),
+ Some(paragraph),
+ )
} else {
(None, None)
};
@@ -702,15 +711,17 @@ impl FirmwareUI for UIEckhart {
let account_paragraphs = {
let mut paragraphs = ParagraphVecShort::new();
if let Some(account) = account {
+ let mut para = Paragraph::new(&theme::TEXT_MONO_LIGHT, account);
+ if account_path.is_some() {
+ para = para.with_bottom_padding(theme::PROPS_SPACING);
+ }
paragraphs
.add(
- Paragraph::new(
- &theme::TEXT_SMALL_LIGHT,
- TString::from_translation(TR::words__wallet),
- )
- .no_break(),
+ Paragraph::new(&theme::TEXT_SMALL_LIGHT, TR::words__wallet)
+ .with_bottom_padding(theme::PROP_INNER_SPACING)
+ .no_break(),
)
- .add(Paragraph::new(&theme::TEXT_MONO_LIGHT, account));
+ .add(para);
}
if let Some(path) = account_path {
paragraphs
@@ -719,6 +730,7 @@ impl FirmwareUI for UIEckhart {
&theme::TEXT_SMALL_LIGHT,
TString::from_translation(TR::address_details__derivation_path),
)
+ .with_bottom_padding(theme::PROP_INNER_SPACING)
.no_break(),
)
.add(Paragraph::new(&theme::TEXT_MONO_LIGHT, path));
@@ -731,37 +743,41 @@ impl FirmwareUI for UIEckhart {
};
let summary_paragraphs = if let Some(items) = summary_items {
- let mut paragraphs = ParagraphVecShort::new();
- for pair in IterBuf::new().try_iterate(items)? {
- let [label, value]: [TString; 2] = util::iter_into_array(pair)?;
- paragraphs
- .add(Paragraph::new(&theme::TEXT_SMALL_LIGHT, label).no_break())
- .add(Paragraph::new(&theme::TEXT_MONO_MEDIUM_LIGHT, value));
- }
- Some(paragraphs)
+ Some(PropsList::new(
+ items,
+ &theme::TEXT_SMALL_LIGHT,
+ &theme::TEXT_MONO_MEDIUM_LIGHT,
+ &theme::TEXT_MONO_MEDIUM_LIGHT,
+ theme::PROP_INNER_SPACING,
+ theme::PROPS_SPACING,
+ )?)
} else {
None
};
let fee_paragraphs = if let Some(items) = fee_items {
- let mut paragraphs = ParagraphVecShort::new();
- for pair in IterBuf::new().try_iterate(items)? {
- let [label, value]: [TString; 2] = util::iter_into_array(pair)?;
- paragraphs
- .add(Paragraph::new(&theme::TEXT_SMALL_LIGHT, label).no_break())
- .add(Paragraph::new(&theme::TEXT_MONO_MEDIUM_LIGHT, value));
- }
- Some(paragraphs)
+ Some(PropsList::new(
+ items,
+ &theme::TEXT_SMALL_LIGHT,
+ &theme::TEXT_MONO_MEDIUM_LIGHT,
+ &theme::TEXT_MONO_MEDIUM_LIGHT_DATA,
+ theme::PROP_INNER_SPACING,
+ theme::PROPS_SPACING,
+ )?)
} else {
None
};
- let (extra_title, extra_paragraph) = if let Some((title, item)) = extra_item {
+ let (extra_title, extra_paragraph) = if let Some(extra_item) = extra_item {
+ let [key, value, _is_data]: [Obj; 3] = util::iter_into_array(extra_item)?;
let paragraph = Paragraph::new(
&theme::TEXT_MONO_ADDRESS,
- item.try_into().unwrap_or(TString::empty()),
+ value.try_into().unwrap_or(TString::empty()),
);
- (Some(title), Some(paragraph))
+ (
+ Some(key.try_into().unwrap_or(TString::empty())),
+ Some(paragraph),
+ )
} else {
(None, None)
};
@@ -1272,27 +1288,25 @@ impl FirmwareUI for UIEckhart {
_horizontal: bool,
chunkify: bool,
) -> Result<impl LayoutMaybeTrace, Error> {
- let mut paragraphs = ParagraphVecShort::new();
- for para in IterBuf::new().try_iterate(items)? {
- let [key, value]: [Obj; 2] = util::iter_into_array(para)?;
- let key: TString = key.try_into()?;
- let value: TString = value.try_into()?;
- paragraphs.add(Paragraph::new(&theme::TEXT_SMALL_LIGHT, key).no_break());
- if chunkify {
- paragraphs.add(Paragraph::new(
- theme::get_chunkified_text_style(value.len()),
- value,
- ));
- } else {
- paragraphs.add(Paragraph::new(&theme::TEXT_MONO_LIGHT, value));
- }
- }
+ let value_mono_font = if chunkify {
+ &theme::TEXT_MONO_ADDRESS_CHUNKS
+ } else {
+ &theme::TEXT_MONO_LIGHT
+ };
+
+ let paragraphs = PropsList::new(
+ items,
+ &theme::TEXT_SMALL_LIGHT,
+ &theme::TEXT_MONO_MEDIUM_LIGHT,
+ value_mono_font,
+ theme::PROP_INNER_SPACING,
+ theme::PROPS_SPACING,
+ )?
+ .into_paragraphs()
+ .with_placement(LinearPlacement::vertical());
let screen =
- TextScreen::new(paragraphs.into_paragraphs().with_placement(
- LinearPlacement::vertical().with_spacing(theme::PROP_INNER_SPACING),
- ))
- .with_header(Header::new(title).with_close_button());
+ TextScreen::new(paragraphs).with_header(Header::new(title).with_close_button());
let layout = RootComponent::new(screen);
Ok(layout)
}
@@ -1391,7 +1405,7 @@ impl FirmwareUI for UIEckhart {
unwrap!(vec.push(Paragraph::new(&theme::TEXT_MONO_ADDRESS_CHUNKS, text)));
} else {
for property in IterBuf::new().try_iterate(value)? {
- let [header, text]: [Obj; 2] = util::iter_into_array(property)?;
+ let [header, text, _is_data]: [Obj; 3] = util::iter_into_array(property)?;
let header = header
.try_into_option::<TString>()?
.unwrap_or_else(TString::empty);
@@ -1537,11 +1551,10 @@ impl FirmwareUI for UIEckhart {
allow_cancel: bool,
danger: bool,
) -> Result<Gc<LayoutObj>, Error> {
- let paragraphs = ParagraphVecShort::from_iter([
+ let paragraphs = Paragraphs::new([
Paragraph::new(&theme::TEXT_REGULAR, description),
Paragraph::new(&theme::TEXT_REGULAR, value),
])
- .into_paragraphs()
.with_placement(LinearPlacement::vertical())
.with_spacing(theme::TEXT_VERTICAL_SPACING);
diff --git a/core/embed/rust/src/ui/ui_firmware.rs b/core/embed/rust/src/ui/ui_firmware.rs
index a747c022..3ebc9d32 100644
--- a/core/embed/rust/src/ui/ui_firmware.rs
+++ b/core/embed/rust/src/ui/ui_firmware.rs
@@ -186,8 +186,8 @@ pub trait FirmwareUI {
subtitle: Option<TString<'static>>,
description: Option<TString<'static>>,
extra: Option<TString<'static>>,
- message: Obj, // TODO: replace Obj
- amount: Option<Obj>, // TODO: replace Obj
+ message: TString<'static>,
+ amount: Option<TString<'static>>,
chunkify: bool,
text_mono: bool,
account_title: TString<'static>,
@@ -195,8 +195,8 @@ pub trait FirmwareUI {
account_path: Option<TString<'static>>,
br_code: u16,
br_name: TString<'static>,
- address_item: Option<(TString<'static>, Obj)>,
- extra_item: Option<(TString<'static>, Obj)>,
+ address_item: Option<Obj>,
+ extra_item: Option<Obj>,
summary_items: Option<Obj>, // TODO: replace Obj
fee_items: Option<Obj>, // TODO: replace Obj
summary_title: Option<TString<'static>>,
diff --git a/core/mocks/generated/trezorui_api.pyi b/core/mocks/generated/trezorui_api.pyi
index bcc8912b..d2888dec 100644
--- a/core/mocks/generated/trezorui_api.pyi
+++ b/core/mocks/generated/trezorui_api.pyi
@@ -1,5 +1,6 @@
from typing import *
from trezor import utils
+PropertyType = tuple[str | None, str | bytes | None, bool | None]
T = TypeVar("T")
@@ -282,7 +283,7 @@ def confirm_properties(
*,
title: str,
subtitle: str | None = None,
- items: list[tuple[str | None, str | bytes | None, bool | None]],
+ items: list[PropertyType],
hold: bool = False,
verb: str | None = None,
external_menu: bool = False,
@@ -304,9 +305,9 @@ def confirm_summary(
fee: str,
fee_label: str,
title: str | None = None,
- account_items: Iterable[tuple[str, str]] | None = None,
+ account_items: list[PropertyType] | None = None,
account_title: str | None = None,
- extra_items: Iterable[tuple[str, str]] | None = None,
+ extra_items: list[PropertyType] | None = None,
extra_title: str | None = None,
verb_cancel: str | None = None,
back_button: bool = False,
@@ -360,10 +361,10 @@ def flow_confirm_output(
account_path: str | None,
br_code: ButtonRequestType,
br_name: str,
- address_item: (str, str) | None,
- extra_item: (str, str) | None,
- summary_items: Iterable[tuple[str, str]] | None = None,
- fee_items: Iterable[tuple[str, str]] | None = None,
+ address_item: PropertyType | None,
+ extra_item: PropertyType | None,
+ summary_items: list[PropertyType] | None = None,
+ fee_items: list[PropertyType] | None = None,
summary_title: str | None = None,
summary_br_code: ButtonRequestType | None = None,
summary_br_name: str | None = None,
@@ -663,7 +664,7 @@ def show_info(
def show_info_with_cancel(
*,
title: str,
- items: Iterable[tuple[str, str]],
+ items: list[PropertyType],
horizontal: bool = False,
chunkify: bool = False,
) -> LayoutObj[UiResult]:
@@ -715,7 +716,7 @@ def show_progress_coinjoin(
def show_properties(
*,
title: str,
- value: list[tuple[str, str]] | str,
+ value: list[PropertyType] | str,
) -> LayoutObj[None]:
"""Show a list of key-value pairs, or a monospace string."""
diff --git a/core/src/apps/bitcoin/sign_tx/layout.py b/core/src/apps/bitcoin/sign_tx/layout.py
index 778d3a69..3f3dcb19 100644
--- a/core/src/apps/bitcoin/sign_tx/layout.py
+++ b/core/src/apps/bitcoin/sign_tx/layout.py
@@ -20,6 +20,7 @@ from ..keychain import address_n_to_name
if TYPE_CHECKING:
from trezor.enums import AmountUnit
from trezor.messages import PaymentRequest, TxOutput
+ from trezor.ui.layouts import PropertyType
from apps.common.coininfo import CoinInfo
from apps.common.paths import Bip32Path
@@ -202,11 +203,11 @@ async def show_payment_request_details(
account = account_label(coin, address_n)
account_path = address_n_to_str(address_n) if address_n else None
- account_items = []
+ account_items: list[PropertyType] = []
if account:
- account_items.append((TR.words__account, account))
+ account_items.append((TR.words__account, account, True))
if account_path:
- account_items.append((TR.address_details__derivation_path, account_path))
+ account_items.append((TR.address_details__derivation_path, account_path, True))
await layouts.confirm_payment_request(
payment_request.recipient_name,
diff --git a/core/src/apps/cardano/layout.py b/core/src/apps/cardano/layout.py
index 14a4a1a8..5aea73ea 100644
--- a/core/src/apps/cardano/layout.py
+++ b/core/src/apps/cardano/layout.py
@@ -324,7 +324,7 @@ async def _confirm_data_chunk(
MAX_DISPLAYED_SIZE = 56
displayed_bytes = first_chunk[:MAX_DISPLAYED_SIZE]
bytes_optional_plural = "byte" if data_size == 1 else "bytes"
- props: list[tuple[str, bytes | None, bool | None]] = [
+ props: list[PropertyType] = [
(
f"{title} ({data_size} {bytes_optional_plural}):",
displayed_bytes,
@@ -543,11 +543,15 @@ async def confirm_tx(
) -> None:
total_amount = format_coin_amount(spending, network_id)
fee_amount = format_coin_amount(fee, network_id)
- items = (
- (TR.cardano__network, f"{protocol_magics.to_ui_string(protocol_magic)}"),
- (TR.cardano__valid_since, f"{format_optional_int(validity_interval_start)}"),
- (TR.cardano__ttl, f"{format_optional_int(ttl)}"),
- )
+ items: list[PropertyType] = [
+ (TR.cardano__network, f"{protocol_magics.to_ui_string(protocol_magic)}", True),
+ (
+ TR.cardano__valid_since,
+ f"{format_optional_int(validity_interval_start)}",
+ True,
+ ),
+ (TR.cardano__ttl, f"{format_optional_int(ttl)}", True),
+ ]
await layouts.confirm_cardano_tx(
total_amount,
@@ -701,7 +705,7 @@ async def confirm_stake_pool_owner(
) -> None:
from trezor import messages
- props: list[tuple[str, str | None, bool | None]] = []
+ props: list[PropertyType] = []
if owner.staking_key_path:
props.append(
(TR.cardano__pool_owner, address_n_to_str(owner.staking_key_path), True)
@@ -871,7 +875,7 @@ def _format_stake_credential(
raise ValueError
-def _format_drep(drep: messages.CardanoDRep) -> tuple[str, str, bool]:
+def _format_drep(drep: messages.CardanoDRep) -> PropertyType:
if drep.type == CardanoDRepType.KEY_HASH:
assert drep.key_hash is not None # validate_drep
return (
@@ -1161,9 +1165,9 @@ async def require_confirm_payment_request(
raise wire.DataError("Unrecognized memo type in payment request memo.")
account_path = address_n_to_str(address_n) if address_n else None
- account_items = []
+ account_items: list[PropertyType] = []
if account_path:
- account_items.append((TR.address_details__derivation_path, account_path))
+ account_items.append((TR.address_details__derivation_path, account_path, True))
await confirm_payment_request(
verified_payment_request.recipient_name,
diff --git a/core/src/apps/ethereum/helpers.py b/core/src/apps/ethereum/helpers.py
index 09a93436..6e7397be 100644
--- a/core/src/apps/ethereum/helpers.py
+++ b/core/src/apps/ethereum/helpers.py
@@ -9,6 +9,7 @@ if TYPE_CHECKING:
from typing import Iterable
from trezor.messages import EthereumFieldType, EthereumTokenInfo
+ from trezor.ui.layouts import PropertyType
from .networks import EthereumNetworkInfo
@@ -131,7 +132,7 @@ def decode_typed_data(data: bytes, type_name: str) -> str:
def get_fee_items_regular(
gas_price: int, gas_limit: int, network: EthereumNetworkInfo
-) -> Iterable[tuple[str, str]]:
+) -> Iterable[PropertyType]:
# regular
gas_limit_str = TR.ethereum__units_template.format(gas_limit)
gas_price_str = format_ethereum_amount(
@@ -139,8 +140,8 @@ def get_fee_items_regular(
)
return (
- (TR.ethereum__gas_limit, gas_limit_str),
- (TR.ethereum__gas_price, gas_price_str),
+ (TR.ethereum__gas_limit, gas_limit_str, False),
+ (TR.ethereum__gas_price, gas_price_str, False),
)
@@ -149,7 +150,7 @@ def get_fee_items_eip1559(
max_priority_fee: int,
gas_limit: int,
network: EthereumNetworkInfo,
-) -> Iterable[tuple[str, str]]:
+) -> Iterable[PropertyType]:
# EIP-1559
gas_limit_str = TR.ethereum__units_template.format(gas_limit)
max_gas_fee_str = format_ethereum_amount(
@@ -160,9 +161,9 @@ def get_fee_items_eip1559(
)
return (
- (TR.ethereum__gas_limit, gas_limit_str),
- (TR.ethereum__max_gas_price, max_gas_fee_str),
- (TR.ethereum__priority_fee, max_priority_fee_str),
+ (TR.ethereum__gas_limit, gas_limit_str, False),
+ (TR.ethereum__max_gas_price, max_gas_fee_str, False),
+ (TR.ethereum__priority_fee, max_priority_fee_str, False),
)
diff --git a/core/src/apps/ethereum/layout.py b/core/src/apps/ethereum/layout.py
index f74405b8..4eb0b180 100644
--- a/core/src/apps/ethereum/layout.py
+++ b/core/src/apps/ethereum/layout.py
@@ -26,6 +26,7 @@ if TYPE_CHECKING:
EthereumTokenInfo,
PaymentRequest,
)
+ from trezor.ui.layouts import PropertyType
async def require_confirm_approve(
@@ -33,7 +34,7 @@ async def require_confirm_approve(
value: int | None,
address_n: list[int],
maximum_fee: str,
- fee_info_items: Iterable[tuple[str, str]],
+ fee_info_items: Iterable[PropertyType],
chain_id: int,
network: EthereumNetworkInfo,
token: EthereumTokenInfo,
@@ -85,7 +86,7 @@ async def require_confirm_tx(
value: int,
address_n: list[int],
maximum_fee: str,
- fee_info_items: Iterable[tuple[str, str]],
+ fee_info_items: Iterable[PropertyType],
network: EthereumNetworkInfo,
token: EthereumTokenInfo | None,
is_contract_interaction: bool,
@@ -113,7 +114,7 @@ async def require_confirm_payment_request(
verified_payment_req: PaymentRequest,
address_n: list[int],
maximum_fee: str,
- fee_info_items: Iterable[tuple[str, str]],
+ fee_info_items: Iterable[PropertyType],
chain_id: int,
network: EthereumNetworkInfo,
token: EthereumTokenInfo | None,
@@ -159,14 +160,14 @@ async def require_confirm_payment_request(
raise wire.DataError("Unrecognized memo type in payment request memo.")
account, account_path = get_account_and_path(address_n)
- account_items = []
+ account_items: list[PropertyType] = []
if account:
- account_items.append((TR.words__account, account))
+ account_items.append((TR.words__account, account, True))
if account_path:
- account_items.append((TR.address_details__derivation_path, account_path))
+ account_items.append((TR.address_details__derivation_path, account_path, True))
if chain_id:
account_items.append(
- (TR.ethereum__approve_chain_id, f"{network.name} ({chain_id})")
+ (TR.ethereum__approve_chain_id, f"{network.name} ({chain_id})", True)
)
await confirm_payment_request(
@@ -187,7 +188,7 @@ async def require_confirm_stake(
value: int,
address_n: list[int],
maximum_fee: str,
- fee_info_items: Iterable[tuple[str, str]],
+ fee_info_items: Iterable[PropertyType],
network: EthereumNetworkInfo,
chunkify: bool,
) -> None:
@@ -216,7 +217,7 @@ async def require_confirm_unstake(
value: int,
address_n: list[int],
maximum_fee: str,
- fee_info_items: Iterable[tuple[str, str]],
+ fee_info_items: Iterable[PropertyType],
network: EthereumNetworkInfo,
chunkify: bool,
) -> None:
@@ -244,7 +245,7 @@ async def require_confirm_claim(
addr_bytes: bytes,
address_n: list[int],
maximum_fee: str,
- fee_info_items: Iterable[tuple[str, str]],
+ fee_info_items: Iterable[PropertyType],
network: EthereumNetworkInfo,
chunkify: bool,
) -> None:
diff --git a/core/src/apps/ethereum/sign_tx.py b/core/src/apps/ethereum/sign_tx.py
index f589f0be..da19da6f 100644
--- a/core/src/apps/ethereum/sign_tx.py
+++ b/core/src/apps/ethereum/sign_tx.py
@@ -19,6 +19,7 @@ if TYPE_CHECKING:
EthereumTokenInfo,
EthereumTxAck,
)
+ from trezor.ui.layouts import PropertyType
from apps.common.keychain import Keychain
from apps.common.payment_request import PaymentRequestVerifier
@@ -140,7 +141,7 @@ async def confirm_tx_data(
defs: Definitions,
address_bytes: bytes,
maximum_fee: str,
- fee_items: Iterable[tuple[str, str]],
+ fee_items: Iterable[PropertyType],
data_total_len: int,
payment_req_verifier: PaymentRequestVerifier | None,
) -> None:
@@ -263,7 +264,7 @@ async def handle_staking(
network: EthereumNetworkInfo,
address_bytes: bytes,
maximum_fee: str,
- fee_items: Iterable[tuple[str, str]],
+ fee_items: Iterable[PropertyType],
) -> bool:
data_reader = BufferReader(msg.data_initial_chunk)
@@ -445,7 +446,7 @@ async def _handle_staking_tx_stake(
network: EthereumNetworkInfo,
address_bytes: bytes,
maximum_fee: str,
- fee_items: Iterable[tuple[str, str]],
+ fee_items: Iterable[PropertyType],
) -> None:
from .layout import require_confirm_stake
@@ -479,7 +480,7 @@ async def _handle_staking_tx_unstake(
network: EthereumNetworkInfo,
address_bytes: bytes,
maximum_fee: str,
- fee_items: Iterable[tuple[str, str]],
+ fee_items: Iterable[PropertyType],
) -> None:
from .layout import require_confirm_unstake
@@ -518,7 +519,7 @@ async def _handle_staking_tx_claim(
msg: MsgInSignTx,
staking_addr: bytes,
maximum_fee: str,
- fee_items: Iterable[tuple[str, str]],
+ fee_items: Iterable[PropertyType],
network: EthereumNetworkInfo,
chunkify: bool,
) -> None:
diff --git a/core/src/apps/nostr/sign_event.py b/core/src/apps/nostr/sign_event.py
index c9ba2a13..edfa8be4 100644
--- a/core/src/apps/nostr/sign_event.py
+++ b/core/src/apps/nostr/sign_event.py
@@ -4,6 +4,7 @@ from apps.common.keychain import auto_keychain
if TYPE_CHECKING:
from trezor.messages import NostrEventSignature, NostrSignEvent
+ from trezor.ui.layouts import PropertyType
from apps.common.keychain import Keychain
@@ -40,7 +41,10 @@ async def sign_event(msg: NostrSignEvent, keychain: Keychain) -> NostrEventSigna
["[" + ",".join(f'"{t}"' for t in tag) + "]" for tag in tags]
)
- info_items = [("Created", str(created_at)), ("Tags", serialized_tags)]
+ info_items: list[PropertyType] = [
+ ("Created", str(created_at), True),
+ ("Tags", serialized_tags, True),
+ ]
await confirm_value(title, content, "", "nostr_sign_event", info_items=info_items)
serialized_event = f'[0,"{hexlify(pk).decode()}",{created_at},{kind},[{serialized_tags}],"{content}"]'
diff --git a/core/src/apps/ripple/layout.py b/core/src/apps/ripple/layout.py
index ccd4db77..d5b2cda1 100644
--- a/core/src/apps/ripple/layout.py
+++ b/core/src/apps/ripple/layout.py
@@ -9,6 +9,7 @@ from .helpers import DECIMALS
if TYPE_CHECKING:
from trezor.messages import PaymentRequest
+ from trezor.ui.layouts import PropertyType
from apps.common.paths import Bip32Path
@@ -71,8 +72,8 @@ async def require_confirm_payment_request(
)
trades.append(
(
- f"-\u00A0{total_amount}",
- f"+\u00A0{memo.coin_purchase_memo.amount}",
+ f"-\u00a0{total_amount}",
+ f"+\u00a0{memo.coin_purchase_memo.amount}",
memo.coin_purchase_memo.address,
None,
coin_purchase_account_path,
@@ -82,9 +83,9 @@ async def require_confirm_payment_request(
raise wire.DataError("Unrecognized memo type in payment request memo.")
account_path = address_n_to_str(address_n) if address_n else None
- account_items = []
+ account_items: list[PropertyType] = []
if account_path:
- account_items.append((TR.address_details__derivation_path, account_path))
+ account_items.append((TR.address_details__derivation_path, account_path, True))
await confirm_payment_request(
verified_payment_request.recipient_name,
diff --git a/core/src/apps/solana/layout.py b/core/src/apps/solana/layout.py
index a1637297..58fd2810 100644
--- a/core/src/apps/solana/layout.py
+++ b/core/src/apps/solana/layout.py
@@ -171,7 +171,7 @@ async def confirm_instruction(
raise ValueError # Invalid ui property
if instruction.multisig_signers:
- signers: list[tuple[str, str, bool]] = []
+ signers: list[PropertyType] = []
for i, multisig_signer in enumerate(instruction.multisig_signers, 1):
multisig_signer_public_key = multisig_signer[0]
@@ -313,7 +313,7 @@ async def confirm_system_transfer(
await confirm_solana_recipient(
recipient=base58.encode(transfer_instruction.recipient_account[0]),
title=TR.words__recipient,
- items=[(TR.words__blockhash, base58.encode(blockhash))],
+ items=[(TR.words__blockhash, base58.encode(blockhash), True)],
)
await confirm_custom_transaction(transfer_instruction.lamports, 9, "SOL", fee)
@@ -329,12 +329,12 @@ async def confirm_token_transfer(
fee: Fee,
blockhash: bytes,
) -> None:
- items = []
+ items: list[PropertyType] = []
if token_account != destination_account:
items.append(
- (TR.solana__associated_token_account, base58.encode(token_account))
+ (TR.solana__associated_token_account, base58.encode(token_account), True)
)
- items.append((TR.words__blockhash, base58.encode(blockhash)))
+ items.append((TR.words__blockhash, base58.encode(blockhash), True))
await confirm_solana_recipient(
recipient=base58.encode(destination_account),
@@ -358,22 +358,22 @@ async def confirm_token_transfer(
await confirm_custom_transaction(amount, decimals, token.symbol, fee)
-def _fee_ui_info(fee: Fee | None) -> tuple[str, str, list[tuple[str, str]]]:
- fee_items: list[tuple[str, str]] = []
+def _fee_ui_info(fee: Fee | None) -> tuple[str, str, list[PropertyType]]:
+ fee_items: list[PropertyType] = []
if fee is None:
fee_title = f"{TR.solana__max_fees_rent}:"
fee_str = TR.words__unknown
else:
fee_str = format_amount_unit(format_amount(fee.total, 9), "SOL")
base_fee_str = format_amount_unit(format_amount(fee.base, 9), "SOL")
- fee_items.append((TR.solana__base_fee, base_fee_str))
+ fee_items.append((TR.solana__base_fee, base_fee_str, True))
if fee.priority:
priority_fee_str = format_amount_unit(format_amount(fee.priority, 9), "SOL")
- fee_items.append((TR.solana__priority_fee, priority_fee_str))
+ fee_items.append((TR.solana__priority_fee, priority_fee_str, True))
if fee.rent:
fee_title = f"{TR.solana__max_fees_rent}:"
rent_str = format_amount_unit(format_amount(fee.rent, 9), "SOL")
- fee_items.append((TR.solana__max_rent_fee, rent_str))
+ fee_items.append((TR.solana__max_rent_fee, rent_str, True))
else:
fee_title = f"{TR.words__transaction_fee}:"
return fee_title, fee_str, fee_items
@@ -452,14 +452,16 @@ async def confirm_stake_transaction(
stake_item=(
TR.solana__stake_account,
base58.encode(delegate.initialized_stake_account[0]),
+ True,
),
amount_item=(
f"{TR.words__amount}:",
format_amount_unit(format_amount(create.lamports, 9), "SOL"),
+ True,
),
- fee_item=(fee_title, fee_str),
+ fee_item=(fee_title, fee_str, True),
fee_details=fee_items,
- blockhash_item=(TR.words__blockhash, base58.encode(blockhash)),
+ blockhash_item=(TR.words__blockhash, base58.encode(blockhash), True),
)
@@ -480,9 +482,9 @@ async def confirm_unstake_transaction(
vote_account="",
stake_item=None,
amount_item=None,
- fee_item=(fee_title, fee_str),
+ fee_item=(fee_title, fee_str, True),
fee_details=fee_items,
- blockhash_item=(TR.words__blockhash, base58.encode(blockhash)),
+ blockhash_item=(TR.words__blockhash, base58.encode(blockhash), True),
)
@@ -505,10 +507,11 @@ async def confirm_claim_transaction(
amount_item=(
f"{TR.words__amount}:",
format_amount_unit(format_amount(total_amount, 9), "SOL"),
+ True,
),
- fee_item=(fee_title, fee_str),
+ fee_item=(fee_title, fee_str, True),
fee_details=fee_items,
- blockhash_item=(TR.words__blockhash, base58.encode(blockhash)),
+ blockhash_item=(TR.words__blockhash, base58.encode(blockhash), True),
)
@@ -517,7 +520,7 @@ async def confirm_transaction(
fee: Fee | None,
) -> None:
fee_title, fee_str, fee_items = _fee_ui_info(fee)
- fee_items.append((TR.words__blockhash, base58.encode(blockhash)))
+ fee_items.append((TR.words__blockhash, base58.encode(blockhash), True))
await confirm_solana_tx(
amount="",
amount_title="",
@@ -568,9 +571,9 @@ async def confirm_payment_request(
raise wire.DataError("Unrecognized memo type in payment request memo.")
account_path = address_n_to_str(address_n) if address_n else None
- account_items = []
+ account_items: list[PropertyType] = []
if account_path:
- account_items.append((TR.address_details__derivation_path, account_path))
+ account_items.append((TR.address_details__derivation_path, account_path, True))
_, fee_str, fee_items = _fee_ui_info(fee)
diff --git a/core/src/trezor/ui/layouts/bolt/__init__.py b/core/src/trezor/ui/layouts/bolt/__init__.py
index a7226eb5..f5b0bf96 100644
--- a/core/src/trezor/ui/layouts/bolt/__init__.py
+++ b/core/src/trezor/ui/layouts/bolt/__init__.py
@@ -736,7 +736,7 @@ def confirm_value(
subtitle: str | None = None,
hold: bool = False,
is_data: bool = True,
- info_items: Iterable[tuple[str, str]] | None = None,
+ info_items: Iterable[PropertyType] | None = None,
info_title: str | None = None,
chunkify: bool = False,
chunkify_info: bool = False,
@@ -747,10 +747,9 @@ def confirm_value(
if description and value:
description += ":"
- info_items = info_items or []
info_layout = trezorui_api.show_info_with_cancel(
title=info_title if info_title else TR.words__title_information,
- items=info_items,
+ items=list(info_items) if info_items else [],
chunkify=chunkify_info,
)
@@ -814,14 +813,16 @@ def confirm_total(
total_label = total_label or f"{TR.send__total_amount}:" # def_arg
fee_label = fee_label or TR.send__including_fee # def_arg
- account_info_items = []
- extra_info_items = []
- if source_account:
- account_info_items.append(
- (TR.confirm_total__sending_from_account, source_account)
- )
- if fee_rate_amount:
- extra_info_items.append((f"{TR.confirm_total__fee_rate}:", fee_rate_amount))
+ account_info_items: list[PropertyType] | None = (
+ [(TR.confirm_total__sending_from_account, source_account, None)]
+ if source_account
+ else None
+ )
+ extra_info_items: list[PropertyType] | None = (
+ [(f"{TR.confirm_total__fee_rate}:", fee_rate_amount, None)]
+ if fee_rate_amount
+ else None
+ )
return _confirm_summary(
total_amount,
@@ -843,33 +844,36 @@ def _confirm_summary(
fee: str,
fee_label: str,
title: str | None = None,
- account_items: Iterable[tuple[str, str]] | None = None,
- extra_items: Iterable[tuple[str, str]] | None = None,
+ account_items: Iterable[PropertyType] | None = None,
+ extra_items: Iterable[PropertyType] | None = None,
extra_title: str | None = None,
br_name: str = "confirm_total",
br_code: ButtonRequestType = ButtonRequestType.SignTx,
) -> Awaitable[None]:
title = title or TR.words__title_summary # def_arg
-
+ account_props: list[PropertyType] | None = (
+ list(account_items) if account_items else None
+ )
+ extra_props: list[PropertyType] | None = list(extra_items) if extra_items else None
total_layout = trezorui_api.confirm_summary(
amount=amount,
amount_label=amount_label,
fee=fee,
fee_label=fee_label,
title=title,
- account_items=account_items or None,
- extra_items=extra_items or None,
+ account_items=account_props,
+ extra_items=extra_props,
)
# TODO: use `_info` params directly in this^ layout instead of using `with_info`
- info_items = []
- if account_items:
- info_items.extend(account_items)
- if extra_items:
- info_items.extend(extra_items)
+ info_props: list[PropertyType] = []
+ if account_props:
+ info_props.extend(account_props)
+ if extra_props:
+ info_props.extend(extra_props)
info_layout = trezorui_api.show_info_with_cancel(
title=extra_title if extra_title else TR.words__title_information,
- items=info_items,
+ items=info_props,
)
return with_info(total_layout, info_layout, br_name, br_code)
@@ -889,7 +893,7 @@ if not utils.BITCOIN_ONLY:
account: str | None,
account_path: str | None,
maximum_fee: str,
- fee_info_items: Iterable[tuple[str, str]],
+ fee_info_items: Iterable[PropertyType],
is_contract_interaction: bool,
br_name: str = "confirm_ethereum_tx",
br_code: ButtonRequestType = ButtonRequestType.SignTx,
@@ -910,28 +914,34 @@ if not utils.BITCOIN_ONLY:
chunkify=(chunkify if recipient else False),
)
+ items: list[PropertyType] = [
+ (f"{TR.words__account}:", account or "", None),
+ (TR.address_details__derivation_path_colon, account_path or "", None),
+ ]
account_info_layout = trezorui_api.show_info_with_cancel(
title=TR.send__send_from,
- items=[
- (f"{TR.words__account}:", account or ""),
- (TR.address_details__derivation_path_colon, account_path or ""),
- ],
+ items=items,
)
+ extra_items: list[PropertyType] | None = (
+ [(f"{k}:", v, is_data) for (k, v, is_data) in fee_info_items]
+ if fee_info_items
+ else None
+ )
total_layout = trezorui_api.confirm_summary(
amount=total_amount,
amount_label=f"{TR.words__amount}:",
fee=maximum_fee,
fee_label=f"{TR.send__maximum_fee}:",
title=TR.words__title_summary,
- extra_items=fee_info_items, # used so that info button is shown
+ extra_items=extra_items, # used so that info button is shown
extra_title=TR.confirm_total__title_fee,
verb_cancel="^",
)
fee_info_layout = trezorui_api.show_info_with_cancel(
title=TR.confirm_total__title_fee,
- items=[(f"{k}:", v) for (k, v) in fee_info_items],
+ items=extra_items or [],
)
while True:
@@ -963,7 +973,7 @@ if not utils.BITCOIN_ONLY:
account: str | None,
account_path: str | None,
maximum_fee: str,
- fee_info_items: Iterable[tuple[str, str]],
+ fee_info_items: Iterable[PropertyType],
chunkify: bool = False,
) -> None:
await confirm_value(
@@ -1040,9 +1050,11 @@ if not utils.BITCOIN_ONLY:
False,
)
- account_items = []
- if account_path:
- account_items.append((TR.address_details__derivation_path, account_path))
+ account_items: list[PropertyType] | None = (
+ [(TR.address_details__derivation_path, account_path, None)]
+ if account_path
+ else None
+ )
await _confirm_summary(
None,
@@ -1065,13 +1077,13 @@ if not utils.BITCOIN_ONLY:
maximum_fee: str,
address: str,
address_title: str,
- info_items: Iterable[tuple[str, str]],
+ info_items: Iterable[PropertyType],
chunkify: bool = False,
br_name: str = "confirm_ethereum_staking_tx",
br_code: ButtonRequestType = ButtonRequestType.SignTx,
) -> None:
# intro
-
+ items: list[PropertyType] = [("", address, None)]
await confirm_value(
title,
intro_question,
@@ -1080,7 +1092,7 @@ if not utils.BITCOIN_ONLY:
br_code,
verb=verb,
is_data=False,
- info_items=(("", address),),
+ info_items=items,
info_title=address_title,
chunkify_info=chunkify,
)
@@ -1102,7 +1114,11 @@ if not utils.BITCOIN_ONLY:
fee,
fee_label,
title=title,
- extra_items=[(f"{k}:", v) for (k, v) in info_items],
+ extra_items=(
+ [(f"{k}:", v, is_data) for (k, v, is_data) in info_items]
+ if info_items
+ else None
+ ),
extra_title=TR.confirm_total__title_fee,
br_name=br_name,
br_code=br_code,
@@ -1116,7 +1132,7 @@ if not utils.BITCOIN_ONLY:
def confirm_solana_recipient(
recipient: str,
title: str,
- items: Iterable[tuple[str, str]] = (),
+ items: Iterable[PropertyType] = (),
br_name: str = "confirm_solana_recipient",
br_code: ButtonRequestType = ButtonRequestType.ConfirmOutput,
) -> Awaitable[None]:
@@ -1133,7 +1149,7 @@ if not utils.BITCOIN_ONLY:
def confirm_solana_tx(
amount: str,
fee: str,
- items: Iterable[tuple[str, str]],
+ items: Iterable[PropertyType],
amount_title: str | None = None,
fee_title: str | None = None,
br_name: str = "confirm_solana_tx",
@@ -1149,7 +1165,7 @@ if not utils.BITCOIN_ONLY:
amount_title,
fee,
fee_title,
- extra_items=items,
+ extra_items=list(items) if items else None,
extra_title=info_title,
br_name=br_name,
br_code=br_code,
@@ -1161,16 +1177,16 @@ if not utils.BITCOIN_ONLY:
account: str,
account_path: str,
vote_account: str,
- stake_item: tuple[str, str] | None,
- amount_item: tuple[str, str] | None,
- fee_item: tuple[str, str],
- fee_details: Iterable[tuple[str, str]],
- blockhash_item: tuple[str, str],
+ stake_item: PropertyType | None,
+ amount_item: PropertyType | None,
+ fee_item: PropertyType,
+ fee_details: Iterable[PropertyType],
+ blockhash_item: PropertyType,
br_name: str = "confirm_solana_staking_tx",
br_code: ButtonRequestType = ButtonRequestType.SignTx,
) -> None:
- (amount_label, amount) = amount_item or ("", "")
- (fee_label, fee) = fee_item
+ (amount_label, amount, _is_data) = amount_item or ("", "", None)
+ (fee_label, fee, _is_data) = fee_item
confirm_layout = trezorui_api.confirm_value(
title=title,
@@ -1181,13 +1197,19 @@ if not utils.BITCOIN_ONLY:
info=True,
)
- items = [
- (f"{TR.words__account}:", account),
- (TR.address_details__derivation_path_colon, account_path),
+ items: list[PropertyType] = [
+ (f"{TR.words__account}:", account, None),
+ (TR.address_details__derivation_path_colon, account_path, None),
]
if stake_item is not None:
- items.append(stake_item)
- items.append(blockhash_item)
+ stake_property: PropertyType = (stake_item[0], stake_item[1], None)
+ items.append(stake_property)
+ blockhash_property: PropertyType = (
+ blockhash_item[0],
+ blockhash_item[1],
+ None,
+ )
+ items.append(blockhash_property)
info_layout = trezorui_api.show_info_with_cancel(
title=title,
@@ -1198,10 +1220,10 @@ if not utils.BITCOIN_ONLY:
await with_info(confirm_layout, info_layout, br_name, br_code)
await _confirm_summary(
- amount=amount,
+ amount=str(amount),
amount_label=amount_label,
- fee=fee,
- fee_label=fee_label,
+ fee=str(fee),
+ fee_label=str(fee_label),
account_items=None,
title=title,
extra_title=TR.confirm_total__title_fee,
@@ -1213,7 +1235,7 @@ if not utils.BITCOIN_ONLY:
def confirm_cardano_tx(
amount: str,
fee: str,
- items: Iterable[tuple[str, str]],
+ items: Iterable[PropertyType],
) -> Awaitable[None]:
amount_title = f"{TR.send__total_amount}:"
fee_title = TR.send__including_fee
@@ -1329,9 +1351,9 @@ def confirm_modify_fee(
total_fee_new=total_fee_new,
fee_rate_amount=fee_rate_amount,
)
- items: list[tuple[str, str]] = []
+ items: list[PropertyType] = []
if fee_rate_amount:
- items.append((TR.bitcoin__new_fee_rate, fee_rate_amount))
+ items.append((TR.bitcoin__new_fee_rate, fee_rate_amount, None))
info_layout = trezorui_api.show_info_with_cancel(
title=TR.confirm_total__title_fee,
items=items,
@@ -1390,15 +1412,16 @@ async def confirm_signverify(
chunkify=chunkify,
)
- items: list[tuple[str, str]] = []
+ items: list[PropertyType] = []
if account is not None:
- items.append((f"{TR.words__account}:", account))
+ items.append((f"{TR.words__account}:", account, None))
if path is not None:
- items.append((TR.address_details__derivation_path_colon, path))
+ items.append((TR.address_details__derivation_path_colon, path, None))
items.append(
(
f"{TR.sign_message__message_size}:",
TR.sign_message__bytes_template.format(len(message)),
+ None,
)
)
@@ -1634,9 +1657,12 @@ async def confirm_firmware_update(description: str, fingerprint: str) -> None:
verb=TR.buttons__install,
info=True,
)
+ items: list[PropertyType] = [
+ ("", fingerprint, None),
+ ]
info = trezorui_api.show_info_with_cancel(
title=TR.firmware_update__title_fingerprint,
- items=(("", fingerprint),),
+ items=items,
chunkify=True,
)
await with_info(
diff --git a/core/src/trezor/ui/layouts/caesar/__init__.py b/core/src/trezor/ui/layouts/caesar/__init__.py
index 98188893..5ed71baa 100644
--- a/core/src/trezor/ui/layouts/caesar/__init__.py
+++ b/core/src/trezor/ui/layouts/caesar/__init__.py
@@ -541,9 +541,9 @@ async def confirm_payment_request(
texts: Iterable[tuple[str | None, str]],
refunds: Iterable[tuple[str, str | None, str | None]],
trades: List[tuple[str, str, str, str | None, str | None]],
- account_items: List[tuple[str, str]],
+ account_items: List[PropertyType],
transaction_fee: str | None,
- fee_info_items: Iterable[tuple[str, str]] | None,
+ fee_info_items: Iterable[PropertyType] | None,
token_address: str | None,
) -> None:
from trezor.ui.layouts.menu import Menu, confirm_with_menu
@@ -572,12 +572,12 @@ async def confirm_payment_request(
menu_items = [create_details(TR.address__title_provider_address, recipient)]
for r_address, r_account, r_account_path in refunds:
- refund_account_items: list[tuple[str, str]] = [("", r_address)]
+ refund_account_items: list[PropertyType] = [("", r_address, None)]
if r_account:
- refund_account_items.append((TR.words__account, r_account))
+ refund_account_items.append((TR.words__account, r_account, None))
if r_account_path:
refund_account_items.append(
- (TR.address_details__derivation_path, r_account_path)
+ (TR.address_details__derivation_path, r_account_path, None)
)
menu_items.append(
create_details(
@@ -908,7 +908,7 @@ async def confirm_value(
verb_cancel: str | None = None,
hold: bool = False,
is_data: bool = True,
- info_items: Iterable[tuple[str, str]] | None = None,
+ info_items: Iterable[PropertyType] | None = None,
chunkify: bool = False,
chunkify_info: bool = False,
cancel: bool = False,
@@ -960,8 +960,8 @@ async def confirm_value(
)
menu = Menu.root(
- Details.from_layout(name, item_factory(name, value))
- for name, value in info_items
+ Details.from_layout(str(name), item_factory(str(name), str(value)))
+ for name, value, _is_data in info_items
)
await confirm_with_menu(main, menu, br_name, br_code)
@@ -981,12 +981,16 @@ def confirm_total(
total_label = total_label or f"{TR.send__total_amount}:" # def_arg
fee_label = fee_label or TR.send__including_fee # def_arg
- fee_info_items = []
- if fee_rate_amount:
- fee_info_items.append((TR.confirm_total__fee_rate_colon, fee_rate_amount))
- account_info_items = []
- if source_account:
- account_info_items.append((TR.words__account_colon, source_account))
+ fee_info_items: list[PropertyType] | None = (
+ [(TR.confirm_total__fee_rate_colon, fee_rate_amount, None)]
+ if fee_rate_amount is not None
+ else None
+ )
+ account_info_items: list[PropertyType] | None = (
+ [(TR.words__account_colon, source_account, None)]
+ if source_account is not None
+ else None
+ )
return raise_if_cancelled(
trezorui_api.confirm_summary(
@@ -994,8 +998,8 @@ def confirm_total(
amount_label=total_label,
fee=fee_amount,
fee_label=fee_label,
- account_items=account_info_items or None,
- extra_items=fee_info_items or None,
+ account_items=account_info_items,
+ extra_items=fee_info_items,
extra_title=TR.confirm_total__title_fee,
),
br_name,
@@ -1032,7 +1036,7 @@ if not utils.BITCOIN_ONLY:
account: str | None,
account_path: str | None,
maximum_fee: str,
- fee_info_items: Iterable[tuple[str, str]],
+ fee_info_items: Iterable[PropertyType],
chunkify: bool = False,
) -> None:
await confirm_value(
@@ -1113,10 +1117,11 @@ if not utils.BITCOIN_ONLY:
False,
)
- account_items = []
- if account_path:
- account_items.append((TR.address_details__derivation_path, account_path))
-
+ account_items: list[PropertyType] | None = (
+ [(f"{TR.address_details__derivation_path}:", account_path, None)]
+ if account_path
+ else None
+ )
await raise_if_cancelled(
trezorui_api.confirm_summary(
amount=None,
@@ -1124,9 +1129,9 @@ if not utils.BITCOIN_ONLY:
fee=maximum_fee,
fee_label=f"{TR.send__maximum_fee}:",
title=TR.words__title_summary,
- account_items=[(f"{k}:", v) for (k, v) in account_items],
+ account_items=account_items,
account_title=TR.address_details__account_info,
- extra_items=fee_info_items,
+ extra_items=list(fee_info_items) if fee_info_items else None,
extra_title=TR.confirm_total__title_fee,
),
br_name="confirm_ethereum_approve",
@@ -1150,11 +1155,13 @@ if not utils.BITCOIN_ONLY:
external_menu=True,
)
- account_items: list[tuple[str, str]] = [("", address)]
+ account_items: list[PropertyType] = [("", address, None)]
if account:
- account_items.append((TR.words__account, account))
+ account_items.append((TR.words__account, account, None))
if account_path:
- account_items.append((TR.address_details__derivation_path, account_path))
+ account_items.append(
+ (TR.address_details__derivation_path, account_path, None)
+ )
menu_items = [create_details(TR.address__title_receive_address, account_items)]
if token_address is not None:
menu_items.append(
@@ -1174,12 +1181,13 @@ if not utils.BITCOIN_ONLY:
maximum_fee: str,
address: str,
address_title: str,
- info_items: Iterable[tuple[str, str]],
+ info_items: Iterable[PropertyType],
chunkify: bool = False,
br_name: str = "confirm_ethereum_staking_tx",
br_code: ButtonRequestType = ButtonRequestType.SignTx,
) -> None:
# intro
+ items: list[PropertyType] = [(address_title, address, None)]
await confirm_value(
title,
intro_question,
@@ -1187,7 +1195,7 @@ if not utils.BITCOIN_ONLY:
br_name,
br_code,
verb=verb,
- info_items=((address_title, address),),
+ info_items=items,
chunkify_info=chunkify,
)
@@ -1204,7 +1212,11 @@ if not utils.BITCOIN_ONLY:
amount_label=amount_title,
fee=maximum_fee,
fee_label=f"{TR.send__maximum_fee}:",
- extra_items=[(f"{k}:", v) for (k, v) in info_items],
+ extra_items=(
+ [(f"{k}:", v, is_data) for (k, v, is_data) in info_items]
+ if info_items
+ else None
+ ),
extra_title=TR.confirm_total__title_fee,
),
br_name=br_name,
@@ -1221,7 +1233,7 @@ if not utils.BITCOIN_ONLY:
def confirm_solana_recipient(
recipient: str,
title: str,
- items: Iterable[tuple[str, str]] = (),
+ items: Iterable[PropertyType] = (),
br_name: str = "confirm_solana_recipient",
br_code: ButtonRequestType = ButtonRequestType.ConfirmOutput,
) -> Awaitable[None]:
@@ -1238,7 +1250,7 @@ if not utils.BITCOIN_ONLY:
def confirm_solana_tx(
amount: str,
fee: str,
- items: Iterable[tuple[str, str]],
+ items: Iterable[PropertyType],
amount_title: str | None = None,
fee_title: str | None = None,
br_name: str = "confirm_solana_tx",
@@ -1254,7 +1266,7 @@ if not utils.BITCOIN_ONLY:
amount_label=amount_title,
fee=fee,
fee_label=fee_title,
- extra_items=items, # TODO: extra_title here?
+ extra_items=list(items) if items else None, # TODO: extra_title here?
extra_title=TR.words__title_information,
),
br_name=br_name,
@@ -1267,26 +1279,26 @@ if not utils.BITCOIN_ONLY:
account: str,
account_path: str,
vote_account: str,
- stake_item: tuple[str, str] | None,
- amount_item: tuple[str, str] | None,
- fee_item: tuple[str, str],
- fee_details: list[tuple[str, str]],
- blockhash_item: tuple[str, str],
+ stake_item: PropertyType | None,
+ amount_item: PropertyType | None,
+ fee_item: PropertyType,
+ fee_details: list[PropertyType],
+ blockhash_item: PropertyType,
br_name: str = "confirm_solana_staking_tx",
br_code: ButtonRequestType = ButtonRequestType.SignTx,
) -> None:
from trezor.ui.layouts.menu import Menu, confirm_with_menu
if not amount_item:
- amount_label, amount = fee_item
+ amount_label, amount, _is_data = fee_item
amount_label = f"\n\n{amount_label}"
fee_label = ""
fee = ""
else:
- amount_label, amount = amount_item
- fee_label, fee = fee_item
+ amount_label, amount, _is_data = amount_item
+ fee_label, fee, _is_data = fee_item
- items = []
+ items: list[PropertyType] = []
if stake_item is not None:
items.append(stake_item)
items.append(blockhash_item)
@@ -1305,44 +1317,45 @@ if not utils.BITCOIN_ONLY:
fee_label="",
external_menu=True,
)
- menu = Menu.root(create_details(name, value) for name, value in items)
+ menu = Menu.root(
+ create_details(str(name), str(value)) for name, value, _is_data in items
+ )
await confirm_with_menu(main, menu, br_name, br_code)
main = trezorui_api.confirm_summary(
- amount=amount,
+ amount=str(amount),
amount_label=amount_label,
- fee=fee,
- fee_label=fee_label,
+ fee=str(fee),
+ fee_label=str(fee_label),
external_menu=True,
)
- account_details = [
- (f"{TR.words__account}:", account),
- (TR.address_details__derivation_path_colon, account_path),
+ account_details: list[PropertyType] = [
+ (f"{TR.words__account}:", account, None),
+ (TR.address_details__derivation_path_colon, account_path, None),
]
- items = [
+ iter = [
(TR.confirm_total__title_fee, fee_details),
(TR.address_details__account_info, account_details),
]
- menu = Menu.root(create_details(name, value) for name, value in items)
+ menu = Menu.root(create_details(str(name), props) for name, props in iter)
await confirm_with_menu(main, menu, br_name, br_code)
def confirm_cardano_tx(
amount: str,
fee: str,
- items: Iterable[tuple[str, str]],
+ items: Iterable[PropertyType],
amount_title: str | None = None,
fee_title: str | None = None,
) -> Awaitable[None]:
amount_title = f"{TR.send__total_amount}:"
fee_title = TR.send__including_fee
-
return raise_if_cancelled(
trezorui_api.confirm_summary(
amount=amount,
amount_label=amount_title,
fee=fee,
fee_label=fee_title,
- extra_items=items,
+ extra_items=list(items) if items else None,
),
br_name="confirm_cardano_tx",
br_code=ButtonRequestType.SignTx,
@@ -1354,7 +1367,7 @@ if not utils.BITCOIN_ONLY:
_account: str | None,
_account_path: str | None,
maximum_fee: str,
- fee_info_items: Iterable[tuple[str, str]],
+ fee_info_items: Iterable[PropertyType],
is_contract_interaction: bool,
br_name: str = "confirm_ethereum_tx",
br_code: ButtonRequestType = ButtonRequestType.SignTx,
@@ -1365,7 +1378,11 @@ if not utils.BITCOIN_ONLY:
amount_label=f"{TR.words__amount}:",
fee=maximum_fee,
fee_label=f"{TR.send__maximum_fee}:",
- extra_items=[(f"{k}:", v) for (k, v) in fee_info_items],
+ extra_items=(
+ [(f"{k}:", v, is_data) for (k, v, is_data) in fee_info_items]
+ if fee_info_items
+ else None
+ ),
extra_title=TR.confirm_total__title_fee,
verb_cancel="^",
)
@@ -1801,7 +1818,7 @@ def confirm_firmware_update(description: str, fingerprint: str) -> Awaitable[Non
)
-def create_details(name: str, value: list[tuple[str, str]] | str) -> Details:
+def create_details(name: str, value: list[PropertyType] | str) -> Details:
from trezor.ui.layouts.menu import Details
return Details.from_layout(
diff --git a/core/src/trezor/ui/layouts/delizia/__init__.py b/core/src/trezor/ui/layouts/delizia/__init__.py
index 2b3dc4bd..e80645c0 100644
--- a/core/src/trezor/ui/layouts/delizia/__init__.py
+++ b/core/src/trezor/ui/layouts/delizia/__init__.py
@@ -483,9 +483,9 @@ async def confirm_payment_request(
texts: Iterable[tuple[str | None, str]],
refunds: Iterable[tuple[str, str | None, str | None]],
trades: List[tuple[str, str, str, str | None, str | None]],
- account_items: List[tuple[str, str]],
+ account_items: List[PropertyType] | None,
transaction_fee: str | None,
- fee_info_items: Iterable[tuple[str, str]] | None,
+ fee_info_items: Iterable[PropertyType] | None,
token_address: str | None,
) -> None:
from trezor.ui.layouts.menu import Menu, confirm_with_menu
@@ -518,12 +518,12 @@ async def confirm_payment_request(
menu_items = [create_details(TR.address__title_provider_address, recipient)]
for r_address, r_account, r_account_path in refunds:
- refund_account_items: list[tuple[str, str]] = [("", r_address)]
+ refund_account_items: list[PropertyType] = [("", r_address, None)]
if r_account:
- refund_account_items.append((TR.words__account, r_account))
+ refund_account_items.append((TR.words__account, r_account, None))
if r_account_path:
refund_account_items.append(
- (TR.address_details__derivation_path, r_account_path)
+ (TR.address_details__derivation_path, r_account_path, None)
)
menu_items.append(
create_details(
@@ -786,7 +786,7 @@ def confirm_value(
hold: bool = False,
is_data: bool = True,
chunkify: bool = False,
- info_items: Iterable[tuple[str, str]] | None = None,
+ info_items: Iterable[PropertyType] | None = None,
cancel: bool = False,
) -> Awaitable[ui.UiResult]:
"""General confirmation dialog, used by many other confirm_* functions."""
@@ -809,7 +809,7 @@ def confirm_value(
info_items = info_items or []
menu = Menu.root(
- (create_details(name, value) for name, value in info_items),
+ (create_details(str(name), str(value)) for name, value, _is_data in info_items),
cancel=TR.buttons__cancel,
)
return interact_with_menu(main, menu, br_name, br_code)
@@ -853,14 +853,18 @@ def confirm_total(
total_label = total_label or TR.send__total_amount # def_arg
fee_label = fee_label or TR.send__incl_transaction_fee # def_arg
- fee_items = []
- account_items = []
+ fee_items: list[PropertyType] = []
+ account_items: list[PropertyType] = []
if source_account:
- account_items.append((TR.confirm_total__sending_from_account, source_account))
+ account_items.append(
+ (TR.confirm_total__sending_from_account, source_account, None)
+ )
if source_account_path:
- account_items.append((TR.address_details__derivation_path, source_account_path))
+ account_items.append(
+ (TR.address_details__derivation_path, source_account_path, None)
+ )
if fee_rate_amount:
- fee_items.append((TR.confirm_total__fee_rate, fee_rate_amount))
+ fee_items.append((TR.confirm_total__fee_rate, fee_rate_amount, None))
return raise_if_cancelled(
trezorui_api.confirm_summary(
@@ -884,14 +888,17 @@ def _confirm_summary(
fee: str,
fee_label: str,
title: str | None = None,
- account_items: Iterable[tuple[str, str]] | None = None,
- extra_items: Iterable[tuple[str, str]] | None = None,
+ account_items: Iterable[PropertyType] | None = None,
+ extra_items: Iterable[PropertyType] | None = None,
extra_title: str | None = None,
br_name: str = "confirm_total",
br_code: ButtonRequestType = ButtonRequestType.SignTx,
) -> Awaitable[None]:
title = title or TR.words__title_summary # def_arg
-
+ account_props: list[PropertyType] | None = (
+ list(account_items) if account_items else None
+ )
+ extra_props: list[PropertyType] | None = list(extra_items) if extra_items else None
return raise_if_cancelled(
trezorui_api.confirm_summary(
amount=amount,
@@ -899,8 +906,8 @@ def _confirm_summary(
fee=fee,
fee_label=fee_label,
title=title,
- account_items=account_items or None,
- extra_items=extra_items or None,
+ account_items=account_props,
+ extra_items=extra_props,
extra_title=extra_title or None,
),
br_name,
@@ -925,12 +932,19 @@ if not utils.BITCOIN_ONLY:
account: str | None,
account_path: str | None,
maximum_fee: str,
- fee_info_items: Iterable[tuple[str, str]],
+ fee_info_items: Iterable[PropertyType],
is_contract_interaction: bool,
br_name: str = "confirm_ethereum_tx",
br_code: ButtonRequestType = ButtonRequestType.SignTx,
chunkify: bool = False,
) -> None:
+ fee_items: list[PropertyType] | None = (
+ list(fee_info_items) if fee_info_items else None
+ )
+ summary_items: list[PropertyType] | None = [
+ (TR.words__amount, total_amount, None),
+ (TR.send__maximum_fee, maximum_fee, None),
+ ]
await raise_if_cancelled(
trezorui_api.flow_confirm_output(
title=TR.words__address,
@@ -952,11 +966,8 @@ if not utils.BITCOIN_ONLY:
extra_item=None,
br_code=ButtonRequestType.SignTx,
br_name="confirm_output",
- summary_items=(
- (TR.words__amount, total_amount),
- (TR.send__maximum_fee, maximum_fee),
- ),
- fee_items=fee_info_items,
+ summary_items=summary_items,
+ fee_items=fee_items,
summary_title=TR.words__title_summary,
summary_br_name="confirm_total",
summary_br_code=ButtonRequestType.SignTx,
@@ -983,7 +994,7 @@ if not utils.BITCOIN_ONLY:
account: str | None,
account_path: str | None,
maximum_fee: str,
- fee_info_items: Iterable[tuple[str, str]],
+ fee_info_items: Iterable[PropertyType],
chunkify: bool = False,
) -> None:
br_name = "confirm_ethereum_approve"
@@ -1023,9 +1034,10 @@ if not utils.BITCOIN_ONLY:
verb="",
verb_info=TR.ethereum__contract_address,
)
+ items: list[PropertyType] = [("", recipient_addr, True)]
info_layout = trezorui_api.show_info_with_cancel(
title=TR.ethereum__contract_address,
- items=[("", recipient_addr)],
+ items=items,
chunkify=chunkify,
)
await with_info(main_layout, info_layout, br_name, br_code)
@@ -1076,9 +1088,11 @@ if not utils.BITCOIN_ONLY:
False,
)
- account_items = []
- if account_path:
- account_items.append((TR.address_details__derivation_path, account_path))
+ account_items: list[PropertyType] | None = (
+ [(TR.address_details__derivation_path, account_path, None)]
+ if account_path
+ else None
+ )
await _confirm_summary(
None,
@@ -1110,11 +1124,13 @@ if not utils.BITCOIN_ONLY:
buy_amount=buy_amount,
)
- account_items: list[tuple[str, str]] = [("", address)]
+ account_items: list[PropertyType] = [("", address, None)]
if account:
- account_items.append((TR.words__account, account))
+ account_items.append((TR.words__account, account, None))
if account_path:
- account_items.append((TR.address_details__derivation_path, account_path))
+ account_items.append(
+ (TR.address_details__derivation_path, account_path, None)
+ )
menu_items = [create_details(TR.address__title_receive_address, account_items)]
if token_address is not None:
menu_items.append(
@@ -1134,17 +1150,20 @@ if not utils.BITCOIN_ONLY:
maximum_fee: str,
address: str,
address_title: str,
- info_items: Iterable[tuple[str, str]],
+ info_items: Iterable[PropertyType],
chunkify: bool = False,
br_name: str = "confirm_ethereum_staking_tx",
br_code: ButtonRequestType = ButtonRequestType.SignTx,
) -> None:
+ summary_items: list[PropertyType] = []
if verb == TR.ethereum__staking_claim:
- summary_items = ((TR.send__maximum_fee, maximum_fee),)
+ summary_items.extend([(TR.send__maximum_fee, maximum_fee, None)])
else:
- summary_items = (
- (TR.words__amount, total_amount),
- (TR.send__maximum_fee, maximum_fee),
+ summary_items.extend(
+ [
+ (TR.words__amount, total_amount, None),
+ (TR.send__maximum_fee, maximum_fee, None),
+ ]
)
await raise_if_cancelled(
trezorui_api.flow_confirm_output(
@@ -1161,10 +1180,10 @@ if not utils.BITCOIN_ONLY:
account_path=account_path,
br_code=br_code,
br_name=br_name,
- address_item=(address_title, address),
+ address_item=(address_title, address, None),
extra_item=None,
summary_items=summary_items,
- fee_items=info_items,
+ fee_items=list(info_items) if info_items else None,
summary_title=verb,
summary_br_name="confirm_total",
summary_br_code=ButtonRequestType.SignTx,
@@ -1183,7 +1202,7 @@ if not utils.BITCOIN_ONLY:
def confirm_solana_recipient(
recipient: str,
title: str,
- items: Iterable[tuple[str, str]] = (),
+ items: Iterable[PropertyType] = (),
br_name: str = "confirm_solana_recipient",
br_code: ButtonRequestType = ButtonRequestType.ConfirmOutput,
) -> Awaitable[ui.UiResult]:
@@ -1200,7 +1219,7 @@ if not utils.BITCOIN_ONLY:
def confirm_solana_tx(
amount: str,
fee: str,
- items: Iterable[tuple[str, str]],
+ items: Iterable[PropertyType],
amount_title: str | None = None,
fee_title: str | None = None,
br_name: str = "confirm_solana_tx",
@@ -1216,7 +1235,7 @@ if not utils.BITCOIN_ONLY:
fee,
fee_title,
extra_title=TR.confirm_total__title_fee,
- extra_items=items,
+ extra_items=list(items) if items else None,
br_name=br_name,
br_code=br_code,
)
@@ -1227,14 +1246,18 @@ if not utils.BITCOIN_ONLY:
account: str,
account_path: str,
vote_account: str,
- stake_item: tuple[str, str] | None,
- amount_item: tuple[str, str] | None,
- fee_item: tuple[str, str],
- fee_details: Iterable[tuple[str, str]],
- blockhash_item: tuple[str, str],
+ stake_item: PropertyType | None,
+ amount_item: PropertyType | None,
+ fee_item: PropertyType,
+ fee_details: Iterable[PropertyType],
+ blockhash_item: PropertyType,
br_name: str = "confirm_solana_staking_tx",
br_code: ButtonRequestType = ButtonRequestType.SignTx,
) -> None:
+ summary_items: list[PropertyType] = []
+ if amount_item:
+ summary_items.append(amount_item)
+ summary_items.append(fee_item)
await raise_if_cancelled(
trezorui_api.flow_confirm_output(
title=title,
@@ -1252,9 +1275,9 @@ if not utils.BITCOIN_ONLY:
br_name=br_name,
address_item=stake_item,
extra_item=blockhash_item,
- fee_items=fee_details,
+ fee_items=list(fee_details) if fee_details else None,
summary_title=title,
- summary_items=(amount_item, fee_item) if amount_item else (fee_item,),
+ summary_items=summary_items,
summary_br_name="confirm_total",
summary_br_code=ButtonRequestType.SignTx,
cancel_text=TR.buttons__cancel,
@@ -1265,11 +1288,10 @@ if not utils.BITCOIN_ONLY:
def confirm_cardano_tx(
amount: str,
fee: str,
- items: Iterable[tuple[str, str]],
+ items: Iterable[PropertyType],
) -> Awaitable[None]:
amount_title = TR.send__total_amount
fee_title = TR.send__incl_transaction_fee
-
return _confirm_summary(
amount,
amount_title,
@@ -1380,9 +1402,9 @@ def confirm_modify_fee(
total_fee_new=total_fee_new,
fee_rate_amount=fee_rate_amount,
)
- items: list[tuple[str, str]] = []
+ items: list[PropertyType] = []
if fee_rate_amount:
- items.append((TR.bitcoin__new_fee_rate, fee_rate_amount))
+ items.append((TR.bitcoin__new_fee_rate, fee_rate_amount, None))
info_layout = trezorui_api.show_info_with_cancel(
title=TR.confirm_total__title_fee,
items=items,
@@ -1687,7 +1709,7 @@ def tutorial(br_code: ButtonRequestType = BR_CODE_OTHER) -> Awaitable[None]:
)
-def create_details(name: str, value: list[tuple[str, str]] | str) -> Details:
+def create_details(name: str, value: list[PropertyType] | str) -> Details:
from trezor.ui.layouts.menu import Details
return Details.from_layout(
diff --git a/core/src/trezor/ui/layouts/eckhart/__init__.py b/core/src/trezor/ui/layouts/eckhart/__init__.py
index f29edb4b..d4fc6f7c 100644
--- a/core/src/trezor/ui/layouts/eckhart/__init__.py
+++ b/core/src/trezor/ui/layouts/eckhart/__init__.py
@@ -470,9 +470,9 @@ async def confirm_payment_request(
texts: Iterable[tuple[str | None, str]],
refunds: Iterable[tuple[str, str | None, str | None]],
trades: List[tuple[str, str, str, str | None, str | None]],
- account_items: List[tuple[str, str]],
+ account_items: List[PropertyType],
transaction_fee: str | None,
- fee_info_items: Iterable[tuple[str, str]] | None,
+ fee_info_items: Iterable[PropertyType] | None,
token_address: str | None,
) -> None:
from trezor.ui.layouts.menu import Menu, confirm_with_menu
@@ -505,12 +505,12 @@ async def confirm_payment_request(
menu_items = [create_details(TR.address__title_provider_address, recipient)]
for r_address, r_account, r_account_path in refunds:
- refund_account_info = [(str(""), r_address)]
+ refund_account_info: list[PropertyType] = [(str(""), r_address, True)]
if r_account:
- refund_account_info.append((TR.words__account, r_account))
+ refund_account_info.append((TR.words__account, r_account, True))
if r_account_path:
refund_account_info.append(
- (TR.address_details__derivation_path, r_account_path)
+ (TR.address_details__derivation_path, r_account_path, True)
)
menu_items.append(
create_details(
@@ -806,7 +806,7 @@ def confirm_value(
hold: bool = False,
is_data: bool = True,
chunkify: bool = False,
- info_items: Iterable[tuple[str, str]] | None = None,
+ info_items: Iterable[PropertyType] | None = None,
info_title: str | None = None,
chunkify_info: bool = False,
warning_footer: str | None = None,
@@ -814,10 +814,10 @@ def confirm_value(
) -> Awaitable[None]:
"""General confirmation dialog, used by many other confirm_* functions."""
- info_items = info_items or []
+ items: list[PropertyType] = list(info_items) if info_items else []
info_layout = trezorui_api.show_info_with_cancel(
title=info_title if info_title else TR.words__title_information,
- items=info_items,
+ items=items,
chunkify=chunkify_info,
)
@@ -882,14 +882,16 @@ def confirm_total(
total_label = total_label or TR.send__total_amount # def_arg
fee_label = fee_label or TR.send__incl_transaction_fee # def_arg
- fee_items = []
- account_items = []
+ fee_items: list[PropertyType] = []
+ account_items: list[PropertyType] = []
if source_account:
- account_items.append((TR.words__account, source_account))
+ account_items.append((TR.words__account, source_account, True))
if source_account_path:
- account_items.append((TR.address_details__derivation_path, source_account_path))
+ account_items.append(
+ (TR.address_details__derivation_path, source_account_path, True)
+ )
if fee_rate_amount:
- fee_items.append((TR.confirm_total__fee_rate, fee_rate_amount))
+ fee_items.append((TR.confirm_total__fee_rate, fee_rate_amount, True))
return raise_if_cancelled(
trezorui_api.confirm_summary(
@@ -913,15 +915,18 @@ def _confirm_summary(
fee: str,
fee_label: str,
title: str | None = None,
- account_items: Iterable[tuple[str, str]] | None = None,
- extra_items: Iterable[tuple[str, str]] | None = None,
+ account_items: Iterable[PropertyType] | None = None,
+ extra_items: Iterable[PropertyType] | None = None,
extra_title: str | None = None,
back_button: bool = False,
br_name: str = "confirm_total",
br_code: ButtonRequestType = ButtonRequestType.SignTx,
) -> Awaitable[None]:
title = title or TR.words__send # def_arg
-
+ account_props: list[PropertyType] | None = (
+ list(account_items) if account_items else None
+ )
+ extra_props: list[PropertyType] | None = list(extra_items) if extra_items else None
return raise_if_cancelled(
trezorui_api.confirm_summary(
amount=amount,
@@ -929,8 +934,8 @@ def _confirm_summary(
fee=fee,
fee_label=fee_label,
title=title,
- account_items=account_items or None,
- extra_items=extra_items or None,
+ account_items=account_props,
+ extra_items=extra_props,
extra_title=extra_title or None,
back_button=back_button,
),
@@ -963,7 +968,7 @@ if not utils.BITCOIN_ONLY:
account: str | None,
account_path: str | None,
maximum_fee: str,
- fee_info_items: Iterable[tuple[str, str]],
+ fee_info_items: Iterable[PropertyType],
is_contract_interaction: bool,
br_name: str = "confirm_total",
br_code: ButtonRequestType = ButtonRequestType.SignTx,
@@ -979,7 +984,9 @@ if not utils.BITCOIN_ONLY:
)
)
title = TR.words__send
-
+ fee_items: list[PropertyType] | None = (
+ list(fee_info_items) if fee_info_items else None
+ )
await raise_if_cancelled(
trezorui_api.flow_confirm_output(
title=title,
@@ -997,11 +1004,11 @@ if not utils.BITCOIN_ONLY:
extra_item=None,
br_code=br_code,
br_name="confirm_output",
- summary_items=(
- (TR.words__amount, total_amount),
- (TR.send__maximum_fee, maximum_fee),
- ),
- fee_items=fee_info_items,
+ summary_items=[
+ (TR.words__amount, total_amount, True),
+ (TR.send__maximum_fee, maximum_fee, True),
+ ],
+ fee_items=fee_items,
summary_title=title,
summary_br_name=br_name,
summary_br_code=br_code,
@@ -1028,7 +1035,7 @@ if not utils.BITCOIN_ONLY:
account: str | None,
account_path: str | None,
maximum_fee: str,
- fee_info_items: Iterable[tuple[str, str]],
+ fee_info_items: Iterable[PropertyType],
chunkify: bool = False,
) -> None:
@@ -1078,9 +1085,10 @@ if not utils.BITCOIN_ONLY:
verb=TR.buttons__continue,
verb_info=TR.ethereum__contract_address,
)
+ items: list[PropertyType] = [("", recipient_addr, True)]
info_layout = trezorui_api.show_info_with_cancel(
title=title,
- items=[("", recipient_addr)],
+ items=items,
chunkify=chunkify,
)
await with_info(main_layout, info_layout, br_name, br_code)
@@ -1134,9 +1142,11 @@ if not utils.BITCOIN_ONLY:
verb=TR.buttons__continue,
)
- account_items = []
- if account_path:
- account_items.append((TR.address_details__derivation_path, account_path))
+ account_items: list[PropertyType] | None = (
+ [(TR.address_details__derivation_path, account_path, True)]
+ if account_path
+ else None
+ )
await _confirm_summary(
None,
@@ -1170,11 +1180,13 @@ if not utils.BITCOIN_ONLY:
back_button=back_button,
)
- account_info: list[tuple[str, str]] = [("", address)]
+ account_info: list[PropertyType] = [("", address, True)]
if account:
- account_info.append((TR.words__account, account))
+ account_info.append((TR.words__account, account, True))
if account_path:
- account_info.append((TR.address_details__derivation_path, account_path))
+ account_info.append(
+ (TR.address_details__derivation_path, account_path, True)
+ )
menu_items = [create_details(TR.address__title_receive_address, account_info)]
if token_address is not None:
menu_items.append(
@@ -1194,18 +1206,22 @@ if not utils.BITCOIN_ONLY:
maximum_fee: str,
address: str,
address_title: str,
- info_items: Iterable[tuple[str, str]],
+ info_items: Iterable[PropertyType],
chunkify: bool = False,
br_name: str = "confirm_ethereum_staking_tx",
br_code: ButtonRequestType = ButtonRequestType.SignTx,
) -> None:
+ summary_items: list[PropertyType] = []
if verb == TR.ethereum__staking_claim:
- summary_items = ((TR.send__maximum_fee, maximum_fee),)
+ summary_items.extend([(TR.send__maximum_fee, maximum_fee, True)])
else:
- summary_items = (
- (TR.words__amount, total_amount),
- (TR.send__maximum_fee, maximum_fee),
+ summary_items.extend(
+ [
+ (TR.words__amount, total_amount, True),
+ (TR.send__maximum_fee, maximum_fee, True),
+ ]
)
+ fee_items: list[PropertyType] | None = list(info_items) if info_items else None
await raise_if_cancelled(
trezorui_api.flow_confirm_output(
title=verb,
@@ -1221,10 +1237,10 @@ if not utils.BITCOIN_ONLY:
account_path=account_path,
br_code=br_code,
br_name=br_name,
- address_item=(address_title, address),
+ address_item=(address_title, address, True),
extra_item=None,
summary_items=summary_items,
- fee_items=info_items,
+ fee_items=fee_items,
summary_title=verb,
summary_br_name="confirm_total",
summary_br_code=ButtonRequestType.SignTx,
@@ -1236,7 +1252,7 @@ if not utils.BITCOIN_ONLY:
def confirm_solana_recipient(
recipient: str,
title: str,
- items: Iterable[tuple[str, str]] = (),
+ items: Iterable[PropertyType] = (),
br_name: str = "confirm_solana_recipient",
br_code: ButtonRequestType = ButtonRequestType.ConfirmOutput,
) -> Awaitable[None]:
@@ -1253,7 +1269,7 @@ if not utils.BITCOIN_ONLY:
def confirm_solana_tx(
amount: str,
fee: str,
- items: Iterable[tuple[str, str]],
+ items: Iterable[PropertyType],
amount_title: str | None = None,
fee_title: str | None = None,
br_name: str = "confirm_solana_tx",
@@ -1268,7 +1284,7 @@ if not utils.BITCOIN_ONLY:
amount_title,
fee,
fee_title,
- extra_items=items,
+ extra_items=list(items) if items else None,
br_name=br_name,
br_code=br_code,
)
@@ -1279,14 +1295,17 @@ if not utils.BITCOIN_ONLY:
account: str,
account_path: str,
vote_account: str,
- stake_item: tuple[str, str] | None,
- amount_item: tuple[str, str] | None,
- fee_item: tuple[str, str],
- fee_details: Iterable[tuple[str, str]],
- blockhash_item: tuple[str, str],
+ stake_item: PropertyType | None,
+ amount_item: PropertyType | None,
+ fee_item: PropertyType,
+ fee_details: Iterable[PropertyType],
+ blockhash_item: PropertyType,
br_name: str = "confirm_solana_staking_tx",
br_code: ButtonRequestType = ButtonRequestType.SignTx,
) -> None:
+ summary_items: list[PropertyType] = [fee_item]
+ if amount_item:
+ summary_items.append(amount_item)
await raise_if_cancelled(
trezorui_api.flow_confirm_output(
title=title,
@@ -1304,9 +1323,9 @@ if not utils.BITCOIN_ONLY:
br_name=br_name,
address_item=stake_item,
extra_item=blockhash_item,
- fee_items=fee_details,
+ fee_items=list(fee_details) if fee_details else None,
summary_title=title,
- summary_items=(amount_item, fee_item) if amount_item else (fee_item,),
+ summary_items=summary_items,
summary_br_name="confirm_total",
summary_br_code=ButtonRequestType.SignTx,
cancel_text=TR.buttons__cancel,
@@ -1317,11 +1336,10 @@ if not utils.BITCOIN_ONLY:
def confirm_cardano_tx(
amount: str,
fee: str,
- items: Iterable[tuple[str, str]],
+ items: Iterable[PropertyType],
) -> Awaitable[None]:
amount_title = TR.send__total_amount
fee_title = TR.send__incl_transaction_fee
-
return _confirm_summary(
amount,
amount_title,
@@ -1433,9 +1451,9 @@ def confirm_modify_fee(
total_fee_new=total_fee_new,
fee_rate_amount=fee_rate_amount,
)
- items: list[tuple[str, str]] = []
+ items: list[PropertyType] = []
if fee_rate_amount:
- items.append((TR.bitcoin__new_fee_rate, fee_rate_amount))
+ items.append((TR.bitcoin__new_fee_rate, fee_rate_amount, True))
info_layout = trezorui_api.show_info_with_cancel(
title=TR.confirm_total__title_fee,
items=items,
@@ -1496,15 +1514,16 @@ async def confirm_signverify(
cancel=True,
)
- items: list[tuple[str, str]] = []
+ items: list[PropertyType] = []
if account is not None:
- items.append((TR.words__account, account))
+ items.append((TR.words__account, account, True))
if path is not None:
- items.append((TR.address_details__derivation_path, path))
+ items.append((TR.address_details__derivation_path, path, True))
items.append(
(
TR.sign_message__message_size,
TR.sign_message__bytes_template.format(len(message)),
+ True,
)
)
@@ -1745,7 +1764,7 @@ def tutorial(br_code: ButtonRequestType = BR_CODE_OTHER) -> Awaitable[None]:
)
-def create_details(name: str, value: list[tuple[str, str]] | str) -> Details:
+def create_details(name: str, value: list[PropertyType] | str) -> Details:
from trezor.ui.layouts.menu import Details
return Details.from_layout(
diff --git a/tests/ui_tests/fixtures.json b/tests/ui_tests/fixtures.json
index 447105e1..3c66db28 100644
--- a/tests/ui_tests/fixtures.json
+++ b/tests/ui_tests/fixtures.json
@@ -28211,9 +28211,9 @@
},
"T3W1": {
"click_tests": {
-"T3W1_cs_test_autolock.py::test_autolock_does_not_interrupt_signing": "cdf929a8d01ef8fdba5b3f3fca250292b53c70d1f9151bbe214cbaf99e956663",
+"T3W1_cs_test_autolock.py::test_autolock_does_not_interrupt_signing": "ecd7474e289059fcbea2fc684df03373560d032a1e37d9d121e9ad7fbf427ef3",
"T3W1_cs_test_autolock.py::test_autolock_interrupts_passphrase": "56af73980e1469c37432ac48222c75b6ef71eda0a07db5dcf174a1e689356a7f",
-"T3W1_cs_test_autolock.py::test_autolock_interrupts_signing": "3c19772a72147eea0099fc6b365e7ccb2a25debb51272c40eadf00fbe26aed72",
+"T3W1_cs_test_autolock.py::test_autolock_interrupts_signing": "034d474ee2d3286e14b9cb51d820e0d62813de1d14ef3ad2117461ae2184bb48",
"T3W1_cs_test_autolock.py::test_autolock_passphrase_keyboard": "2e2a0fa3b7df8f1d0bd36603eecae3becd9738331a6e34982e223f8d76979d0f",
"T3W1_cs_test_autolock.py::test_dryrun_enter_word_slowly": "c3f12adc23be3f9fa9cd72993bd44a16c860d29e7e119e91d0382fee8c58a114",
"T3W1_cs_test_autolock.py::test_dryrun_locks_at_number_of_words": "7f3d3c84bb9a721e603f917f926005ee1b0237d3ac9d795f3659ea69687c4159",
@@ -28269,9 +28269,9 @@
"T3W1_cs_test_tutorial_eckhart.py::test_tutorial_menu_close": "c36f6fd1849795ff7b005b90885e9d1a7fcfd6bd185429b27c1735591d264b9b",
"T3W1_cs_test_tutorial_eckhart.py::test_tutorial_menu_tropic": "a5d2959fe021cef597f3c7acfeb4e2ae79f5939ea3702d81f5dc881c62bd6e38",
"T3W1_cs_test_tutorial_eckhart.py::test_tutorial_restart": "a8a7392b10cf2198f1a82a38ce7f229041ca24f7ed3f8a0fbbb707f8826b0f4b",
-"T3W1_de_test_autolock.py::test_autolock_does_not_interrupt_signing": "2618da349b727e25fbe17ac6471a2a31707223159bfb102989ba2a362a23e2bf",
+"T3W1_de_test_autolock.py::test_autolock_does_not_interrupt_signing": "f6ec7857738d46357863af87f2bd3bacba5b20989d389d88934f638a9197cc51",
"T3W1_de_test_autolock.py::test_autolock_interrupts_passphrase": "2bf88cb474ceece4441a51277297fc3d0e9c8c04d4083b2acb0d2848d1237c18",
-"T3W1_de_test_autolock.py::test_autolock_interrupts_signing": "9a217fcd034d0dca98c876d36f856a1b79e95837aece0f98e4da8c768a168d41",
+"T3W1_de_test_autolock.py::test_autolock_interrupts_signing": "d3f21164e70220842a2a6c9f31a433558b7893b8b2d27f26475eeedea5001462",
"T3W1_de_test_autolock.py::test_autolock_passphrase_keyboard": "175fec0c0520d5a01fa72520f351b72d1f1bd06a86a9259a2474b2b0d66203ad",
"T3W1_de_test_autolock.py::test_dryrun_enter_word_slowly": "a3be03e5ae30453c98e84de04d571312bfe97e82e2c84524f407c168969c0337",
"T3W1_de_test_autolock.py::test_dryrun_locks_at_number_of_words": "caf1c62593fe72f908f67fb2db74b112e15e608b16bf23bfbb220d8a0ac00c9a",
@@ -28327,9 +28327,9 @@
"T3W1_de_test_tutorial_eckhart.py::test_tutorial_menu_close": "c95e630b55a5cd334ece1062c6de2eaefd4ea350d4bb06a110ad2bfbbdfd419f",
"T3W1_de_test_tutorial_eckhart.py::test_tutorial_menu_tropic": "a8662ddcc52241c96d68b5e62f74276be392243024199795ca009b3d87839198",
"T3W1_de_test_tutorial_eckhart.py::test_tutorial_restart": "1aec6158bef0c24f8f4e493017bb9415a28179126554cd042655d8686045ae69",
-"T3W1_en_test_autolock.py::test_autolock_does_not_interrupt_signing": "c73547a985503889f034d0cda32c9b98dff894347ebad07f476fea9b05afd516",
+"T3W1_en_test_autolock.py::test_autolock_does_not_interrupt_signing": "36477085887f2d9cc83d11680f03de8622ead10fbc3de2e08c27e3b3b0fb08ce",
"T3W1_en_test_autolock.py::test_autolock_interrupts_passphrase": "18194e4cc069c1d5c27cd71cbcb0230b6c724cf837633f043f1bee881304e99c",
-"T3W1_en_test_autolock.py::test_autolock_interrupts_signing": "9efa28426fcbd8c9919a1b7fbd40a7ddf90229ceca464a364b5cece28f9c76c2",
+"T3W1_en_test_autolock.py::test_autolock_interrupts_signing": "41e756aeba0854e36eb58fad71c24714bea073eb8e8991785dd320cc699b4ac0",
"T3W1_en_test_autolock.py::test_autolock_passphrase_keyboard": "4f57edd52b6af423c871ff49d81699f80c77d309c8154abd0e17b91785b3099a",
"T3W1_en_test_autolock.py::test_dryrun_enter_word_slowly": "73c85892e4213b615c84016ba7128a60ab50392e39e27400cefbec4baf8d8be3",
"T3W1_en_test_autolock.py::test_dryrun_locks_at_number_of_words": "3f78341e43b310e026a56d1d94d2964d299df425c4b09972b11714ad628c0a4c",
@@ -28385,9 +28385,9 @@
"T3W1_en_test_tutorial_eckhart.py::test_tutorial_menu_close": "633526d9cbee02419c701fdde3326ed5ad7f5331e43c2680c91dea71c714e4e8",
"T3W1_en_test_tutorial_eckhart.py::test_tutorial_menu_tropic": "625c22431dc74b8ab6d5f87efe31a7df6fed7eac7c5cf81fdf0c7ee378479195",
"T3W1_en_test_tutorial_eckhart.py::test_tutorial_restart": "1525486a578f0a98bfb4ef4e0744868b672d29e49ff7fe58f214f534756e9c72",
-"T3W1_es_test_autolock.py::test_autolock_does_not_interrupt_signing": "c9c2d4dd4b997b7f82f46320c3f8e6142177ddf104b1fff43a72e5b9da2f5cd4",
+"T3W1_es_test_autolock.py::test_autolock_does_not_interrupt_signing": "ececf550d827f511b824619a62d25224293e25915e5b24c788331a5b2900f33d",
"T3W1_es_test_autolock.py::test_autolock_interrupts_passphrase": "a8c17fe88d988af14db8bf2a8b658955e69a4668e7584f2ac72df7031dc7c2e1",
-"T3W1_es_test_autolock.py::test_autolock_interrupts_signing": "00a969d40620edb68a76dbbe100fffe2f381343e946eee7841f4abdff9eec294",
+"T3W1_es_test_autolock.py::test_autolock_interrupts_signing": "9e44a20e1a069f5d051ea4f1a0149ebf661fa550eee652867ceb5ff58e30f9f6",
"T3W1_es_test_autolock.py::test_autolock_passphrase_keyboard": "f22ed6f79805a94f9c119fadf83227ae480abc4b4fb1297b98eff3c63c1ddb5a",
"T3W1_es_test_autolock.py::test_dryrun_enter_word_slowly": "3a5eab671fc53201e18c535e7e641d49541530a532df8ce3278b7c332f00dedb",
"T3W1_es_test_autolock.py::test_dryrun_locks_at_number_of_words": "54d0d41f51f6d520d54d5f0952582aa7278a6f9f4b147fff98a5097dc9037170",
@@ -28443,9 +28443,9 @@
"T3W1_es_test_tutorial_eckhart.py::test_tutorial_menu_close": "d38b5a9e6f568990bf3ba07dc8b7147a9c407087279ba6cab7b9d287f9a1aaba",
"T3W1_es_test_tutorial_eckhart.py::test_tutorial_menu_tropic": "c515b73ba5dadb6a59ba1308ae067af8e1efdd1295525a78e353d6abbcfe8cb9",
"T3W1_es_test_tutorial_eckhart.py::test_tutorial_restart": "9c13dfcdacca73f9896e0f5e73f28c768b6f4840c661ae33303da870ce4174bf",
-"T3W1_fr_test_autolock.py::test_autolock_does_not_interrupt_signing": "f412ecf53c5cc3f8582b33b17c1f9a47f4a672398a1f7e68527a29defdb0b81d",
+"T3W1_fr_test_autolock.py::test_autolock_does_not_interrupt_signing": "68e256ec382479c5e56e76ab26c51a60ee045fc580c4108e4e595828b191f229",
"T3W1_fr_test_autolock.py::test_autolock_interrupts_passphrase": "82077d2931ddb9c1282a6e8bb4e72dd46c97faaf86a70e049fba373d82b97a4e",
-"T3W1_fr_test_autolock.py::test_autolock_interrupts_signing": "0eb1da5e165993be957031d9acbb3e3493dcdb7b32a4b2466840b2b6565f39e3",
+"T3W1_fr_test_autolock.py::test_autolock_interrupts_signing": "d9ecd06d3e3e9b219a92d22ace6e1af3e86060359cd076c022112d68351db8b4",
"T3W1_fr_test_autolock.py::test_autolock_passphrase_keyboard": "eabbc9e67718c92e71e7ecaaa577fe309d5a1f8e2d79563a7d72c90d0b0db008",
"T3W1_fr_test_autolock.py::test_dryrun_enter_word_slowly": "7d3c5d19ee2ef49d0382d74e528f08e5905f8e39a51225379aa543fa31b0b039",
"T3W1_fr_test_autolock.py::test_dryrun_locks_at_number_of_words": "b6b0ac128d7f167b5b1463b4190f069098666848f92b2ac0702e5a337d06eaf9",
@@ -28501,9 +28501,9 @@
"T3W1_fr_test_tutorial_eckhart.py::test_tutorial_menu_close": "8f7e0d38805d0bfde1772b83f341cb0237a4b43c07a0a0069e7f2bbfb3b8f532",
"T3W1_fr_test_tutorial_eckhart.py::test_tutorial_menu_tropic": "52e8cab07b25117328c6f779da34883509404ad04dcf2c221a529ad4f47aa581",
"T3W1_fr_test_tutorial_eckhart.py::test_tutorial_restart": "41dcfdb0126e43a331793e81e8f14333b561d462b730474325cd8593130cb723",
-"T3W1_pt_test_autolock.py::test_autolock_does_not_interrupt_signing": "6c1706657849538126ed3a09e5e7a729423b6d056b8e6deadea175a877389a93",
+"T3W1_pt_test_autolock.py::test_autolock_does_not_interrupt_signing": "185ec5833f9a4f8265dff4840fa82ef95d47c2ad33e335b732018a6bcd36c410",
"T3W1_pt_test_autolock.py::test_autolock_interrupts_passphrase": "a559c9e4a5f11a6b60cba2e22ef2ef20b3cb3cd78d1d08c6d1031f9b4a620dab",
-"T3W1_pt_test_autolock.py::test_autolock_interrupts_signing": "bebeba9d15412e8206c3645a8fa780e6834ea6c6286094092c8ff29e0d152be0",
+"T3W1_pt_test_autolock.py::test_autolock_interrupts_signing": "c4940d6b2371fb972b3d697edda0f9d08e79375b5bb9f98966ee0c0086cb9bcd",
"T3W1_pt_test_autolock.py::test_autolock_passphrase_keyboard": "676481a9def44e22614ae2696934dc5ed38f0f63ee27d301f3dcc7b8a1908cc6",
"T3W1_pt_test_autolock.py::test_dryrun_enter_word_slowly": "e9a99e802a5f4b8a33603d4e59d85b4d5b3706aa1dbfe7c93a23912c3a204440",
"T3W1_pt_test_autolock.py::test_dryrun_locks_at_number_of_words": "ed6c8bee10effb47107bbe84db1618e232b7b3f65bec26eb5125c75f0d847373",
@@ -28561,24 +28561,24 @@
"T3W1_pt_test_tutorial_eckhart.py::test_tutorial_restart": "41a22acb3cf0b285d46dee8725baca8d7bc6a89b87506cd618dcdfc987698807"
},
"device_tests": {
-"T3W1_cs_bitcoin-test_authorize_coinjoin.py::test_cancel_authorization": "81622562877598a2113092887f68a727b7780dcaa30e5250e6761311c5f59a2c",
+"T3W1_cs_bitcoin-test_authorize_coinjoin.py::test_cancel_authorization": "7cc88d9cc65b0b903d9e87fa088074fb1b7e8e8822e73927d4b09fb143e82002",
"T3W1_cs_bitcoin-test_authorize_coinjoin.py::test_get_address": "8b7cc66240dd21cc7a720f624e22b2f677f0e2d810f0eca8cf9bcb548726b4cf",
"T3W1_cs_bitcoin-test_authorize_coinjoin.py::test_get_public_key": "6ecf2a50e67e37aec41a5a4dece4337b8ba73862414aea28a3a51dbf3094c0fd",
-"T3W1_cs_bitcoin-test_authorize_coinjoin.py::test_multisession_authorization": "9a745089b9d781a950c59e173a086d8562a06161ad99208dea44941d0720116b",
-"T3W1_cs_bitcoin-test_authorize_coinjoin.py::test_sign_tx[False]": "2c964c3666df2a0d351d29708fc0732abdd800511c5471f9536a88e950dedb82",
-"T3W1_cs_bitcoin-test_authorize_coinjoin.py::test_sign_tx[True]": "2c964c3666df2a0d351d29708fc0732abdd800511c5471f9536a88e950dedb82",
-"T3W1_cs_bitcoin-test_authorize_coinjoin.py::test_sign_tx_large": "296b2e30e480d6edb008b00a0c99abbccf33e5ed70d0d80936ef1256dc989522",
-"T3W1_cs_bitcoin-test_authorize_coinjoin.py::test_sign_tx_migration": "5ed605ae9b677123a62591dac4f47b8cf7acb0233823e0cdb7b062a73193a6ad",
-"T3W1_cs_bitcoin-test_authorize_coinjoin.py::test_sign_tx_spend": "f4374640416ece30dc950a67ecc00fce6b04adec7e40c51a81222dba5068b490",
-"T3W1_cs_bitcoin-test_authorize_coinjoin.py::test_wrong_account_type": "09dd14a0b835e47968446b053643226577a57309e3a7416ea22c9ff0f81f1a8b",
-"T3W1_cs_bitcoin-test_authorize_coinjoin.py::test_wrong_coordinator": "09dd14a0b835e47968446b053643226577a57309e3a7416ea22c9ff0f81f1a8b",
-"T3W1_cs_bitcoin-test_bcash.py::test_attack_change_input": "7b0c9983afd7d165e45ee7cc9136333b4579c2e75f5f5fca035c35517c915cb2",
-"T3W1_cs_bitcoin-test_bcash.py::test_send_bch_change": "184eeafc86ca870bd350593bcc8c060c8216f3fa0cd78cb1eb3969d597cdbbda",
-"T3W1_cs_bitcoin-test_bcash.py::test_send_bch_external_presigned": "e3ad36a40ddf468c713a2ee7d2562c21f547e98dea15e52a2109ae3550562b70",
-"T3W1_cs_bitcoin-test_bcash.py::test_send_bch_multisig_change": "ecc7b3508a12af9f769c373b346c233abf225f5fad62bda5bef56ad01068daa8",
-"T3W1_cs_bitcoin-test_bcash.py::test_send_bch_multisig_wrongchange": "fbadf24e23da76655850eef4884dd1434f4102e41a7cc1e7e59e438ca09229e2",
-"T3W1_cs_bitcoin-test_bcash.py::test_send_bch_nochange": "de9ba8e8a68c811e59e051d57c2588306f836f21984a0f9ed3b0d471d247e106",
-"T3W1_cs_bitcoin-test_bcash.py::test_send_bch_oldaddr": "f6079f4a36a321b7b732c568fea6b7767cafbea65a4ba0e5d1deda83c170a340",
+"T3W1_cs_bitcoin-test_authorize_coinjoin.py::test_multisession_authorization": "c6aa7813443ff643ee7337aa65ea2e0fb014bec5062e75182e756ace94f17574",
+"T3W1_cs_bitcoin-test_authorize_coinjoin.py::test_sign_tx[False]": "19c8e7453713601c840ff024a5bc73964dd0e86f5afb79e26db62788e8a891d3",
+"T3W1_cs_bitcoin-test_authorize_coinjoin.py::test_sign_tx[True]": "19c8e7453713601c840ff024a5bc73964dd0e86f5afb79e26db62788e8a891d3",
+"T3W1_cs_bitcoin-test_authorize_coinjoin.py::test_sign_tx_large": "74bd2494c1c38e652eb871f2790a1df8b940ff157f54acb7cac40e7ecd3da7f4",
+"T3W1_cs_bitcoin-test_authorize_coinjoin.py::test_sign_tx_migration": "067d1319ece97076a138e1356575b73931dcdacc437c336cd422c84549e45b14",
+"T3W1_cs_bitcoin-test_authorize_coinjoin.py::test_sign_tx_spend": "60e89da69895d3dd7586c3e3a3a19a3ec5a737247537f4fa2b5c5ec8682dade7",
+"T3W1_cs_bitcoin-test_authorize_coinjoin.py::test_wrong_account_type": "b70bed5f468dca75fbe02d8d0146d5ef295c8055d1a963394e244a52c449ed00",
+"T3W1_cs_bitcoin-test_authorize_coinjoin.py::test_wrong_coordinator": "b70bed5f468dca75fbe02d8d0146d5ef295c8055d1a963394e244a52c449ed00",
+"T3W1_cs_bitcoin-test_bcash.py::test_attack_change_input": "becf8f83c17caddad00af5fe92d68a16f5ae23e07a7c19adbe97bacba644e617",
+"T3W1_cs_bitcoin-test_bcash.py::test_send_bch_change": "f8f9e99fdad1bdf4512dea66e1654ad32f74e0257a003ddcac466cd3b999a6a1",
+"T3W1_cs_bitcoin-test_bcash.py::test_send_bch_external_presigned": "ee161f7a1e9bc4f64bd58d5eb8802f6ebbe7c72308fb62a845de1d20fe6dbf64",
+"T3W1_cs_bitcoin-test_bcash.py::test_send_bch_multisig_change": "2d2a8b1c8dde1efdb4344242c796270fd061b85ec59490cfff6a56f075e89b4f",
+"T3W1_cs_bitcoin-test_bcash.py::test_send_bch_multisig_wrongchange": "bc258ec29f85f91aa3cd573ebaa63dd9b5692d5702603d0a7d47f042ec83f823",
+"T3W1_cs_bitcoin-test_bcash.py::test_send_bch_nochange": "d4635f8136b6384146f063c6f7432648a20e60f654e3c66c4a1d168e1cb302d0",
+"T3W1_cs_bitcoin-test_bcash.py::test_send_bch_oldaddr": "eac61acce78a003e190e76a741af7eca055ab519b648af45aba7da54d17f952e",
"T3W1_cs_bitcoin-test_descriptors.py::test_descriptors[Bitcoin-0-10025-InputScriptType.SPENDTAPROOT--301d7568": "119dde736c510362c58f1c23ef3cf9503ac15c1f8fb029a89dc617b28ae5ead2",
"T3W1_cs_bitcoin-test_descriptors.py::test_descriptors[Bitcoin-0-44-InputScriptType.SPENDADDRESS-pkh-a1b0211f": "9fee25f9399650fa700ea3ce4acea66521dca2e2ba18397d5e3eb46597e62f44",
"T3W1_cs_bitcoin-test_descriptors.py::test_descriptors[Bitcoin-0-49-InputScriptType.SPENDP2SHWITNESS-75f8d49f": "59881e377b9e11db1cc96f361e17e3f0ceb6a51e7a643e72eb3e6c39e0817775",
@@ -28615,8 +28615,8 @@
"T3W1_cs_bitcoin-test_descriptors.py::test_descriptors_trezorlib[Testnet-1-49-InputScriptType.SPENDP-2341fa5a": "2734e4aec8bdc23dfce2c772613c5f706847915afd1d820b399f38e34e7bbd5f",
"T3W1_cs_bitcoin-test_descriptors.py::test_descriptors_trezorlib[Testnet-1-84-InputScriptType.SPENDW-59aa0a79": "7f7ba477e25c5eb55c548f55922de630c6988afcf29d1b4c2d04ed936a146cff",
"T3W1_cs_bitcoin-test_descriptors.py::test_descriptors_trezorlib[Testnet-1-86-InputScriptType.SPENDT-af95048b": "53cd9333c4ff4d11873a15f67135ef4478d9eff5f6d97ba9383c845fcf3256e7",
-"T3W1_cs_bitcoin-test_firo.py::test_spend_lelantus": "25f4fdffccce8710a49c14da7673e85319f194de506af082fdcf6b856d30fb92",
-"T3W1_cs_bitcoin-test_fujicoin.py::test_send_p2tr": "a91af294962c3e355d8b4a8abeabe6eca8c858c023218e1663a201e34777e928",
+"T3W1_cs_bitcoin-test_firo.py::test_spend_lelantus": "7b67a52777d8baf68ec8070005fb484abeec28df808f16f93e620907293df69e",
+"T3W1_cs_bitcoin-test_fujicoin.py::test_send_p2tr": "6ba4e505de33b40ebf0e3831ab96085fff0265a9b6ff13b11ed90711333fe65f",
"T3W1_cs_bitcoin-test_getaddress.py::test_address_mac": "535037bfe5f1459cfdf305915835d8bf2a9a427c3f60264a8cc3ca6f306a61b1",
"T3W1_cs_bitcoin-test_getaddress.py::test_altcoin_address_mac": "535037bfe5f1459cfdf305915835d8bf2a9a427c3f60264a8cc3ca6f306a61b1",
"T3W1_cs_bitcoin-test_getaddress.py::test_bch": "535037bfe5f1459cfdf305915835d8bf2a9a427c3f60264a8cc3ca6f306a61b1",
@@ -28757,33 +28757,33 @@
"T3W1_cs_bitcoin-test_getpublickey_curve.py::test_publickey_curve[nist256p1-path3-03b93f7e6c777143ad-2d6b178b": "535037bfe5f1459cfdf305915835d8bf2a9a427c3f60264a8cc3ca6f306a61b1",
"T3W1_cs_bitcoin-test_getpublickey_curve.py::test_publickey_curve[secp256k1-path0-02f65ce170451f66f4-9c982c22": "535037bfe5f1459cfdf305915835d8bf2a9a427c3f60264a8cc3ca6f306a61b1",
"T3W1_cs_bitcoin-test_getpublickey_curve.py::test_publickey_curve[secp256k1-path1-0212f4629f4f224db0-0209bb73": "535037bfe5f1459cfdf305915835d8bf2a9a427c3f60264a8cc3ca6f306a61b1",
-"T3W1_cs_bitcoin-test_grs.py::test_legacy": "45ea24642818d47d68cc02a9858bc33060872aa49d9fc2f0ed0032d9230e2a6f",
-"T3W1_cs_bitcoin-test_grs.py::test_legacy_change": "52ee936cc4c646277b7a6bdc1969fd811548cd5b35622c200d48cacf003a09d6",
-"T3W1_cs_bitcoin-test_grs.py::test_send_p2tr": "e407330b1acd99d666d1d0e5e998d5082b2c03abf2e0b22959a3c8376fba9b1a",
-"T3W1_cs_bitcoin-test_grs.py::test_send_segwit_native": "f82a6a1bc5fa515b9f3bfa7397463f02308897d97688ec9305f98a21cdcc6a7d",
-"T3W1_cs_bitcoin-test_grs.py::test_send_segwit_native_change": "d5535f4f4dbf4a5af9a03ed785bf88b8efb0ef35b7e531a6756be785a4369ecd",
-"T3W1_cs_bitcoin-test_grs.py::test_send_segwit_p2sh": "45d07be61a477110704f146451c437b104576b0aadb6ea9a944ee9c3c33a30cf",
-"T3W1_cs_bitcoin-test_grs.py::test_send_segwit_p2sh_change": "9a7a2768dd96adfa8dafc4dd7ab44c2cb1b581b3ca63a029d0c07d7d8777df19",
-"T3W1_cs_bitcoin-test_komodo.py::test_one_one_fee_sapling": "9f747dcfe2377eedc06c64c8906162e6599481a68da06ce5c3f547926890463c",
-"T3W1_cs_bitcoin-test_komodo.py::test_one_one_rewards_claim": "8dc003aae65ccb75e3aef5eb11f61d9a0d5f8772a5c3663d22e9d5f763baee10",
-"T3W1_cs_bitcoin-test_multisig.py::test_15_of_15": "c65cfb4e28944574d8732ba2919696c368014c5cf0b861eb1fe636b9b851d2d5",
-"T3W1_cs_bitcoin-test_multisig.py::test_2_of_3[False]": "2dd5c48476cb3b000892d918bb0ec1cdc685e7cf249aa9508b27de6e6063e203",
-"T3W1_cs_bitcoin-test_multisig.py::test_2_of_3[True]": "9fd4e81ef77b6ad123a6b2de1c60db01e0f665038cbdb882978f2f942676afad",
-"T3W1_cs_bitcoin-test_multisig.py::test_attack_change_input": "4c9f6a3c177b3cb138b389b05d88442355d27f4262564f471fb705839d281650",
+"T3W1_cs_bitcoin-test_grs.py::test_legacy": "ce7fee2745bc881741a49960ac54c0b5e7ab1400d259555c35bc5d92da8188b5",
+"T3W1_cs_bitcoin-test_grs.py::test_legacy_change": "04cdcc29d93425ff4f4626cc7e77cf4fdb7f933227af9fbae446035b499c935e",
+"T3W1_cs_bitcoin-test_grs.py::test_send_p2tr": "cd09b34255190315c7638b0d7a0cc512c4fe925819a4d253a327ee9a84c4f0c6",
+"T3W1_cs_bitcoin-test_grs.py::test_send_segwit_native": "4a05314fd203736207f56efd6b528d3bd94bd3dc69be86c0c674ba49bf63ba12",
+"T3W1_cs_bitcoin-test_grs.py::test_send_segwit_native_change": "079dd9f1a5740084751bb702c278225b83a9474d72a50f8dcd9b2c6a8e1fd476",
+"T3W1_cs_bitcoin-test_grs.py::test_send_segwit_p2sh": "3d72a9f4b44eb1396a8a1f3546e5c7dc6e72cec2cf77ef9b0d3329b935541ed1",
+"T3W1_cs_bitcoin-test_grs.py::test_send_segwit_p2sh_change": "07da8841aa5e1706ce65597a599d8cf59dcdf50f33ae5a125fdd54f36acad28b",
+"T3W1_cs_bitcoin-test_komodo.py::test_one_one_fee_sapling": "0cc7296f7ccfc44481a762726515fcbc965eb1cab8bea626b79f4dcad804e533",
+"T3W1_cs_bitcoin-test_komodo.py::test_one_one_rewards_claim": "36677db147cbc373f01573fe8f6174a71359653450d307d14ab08eea33cb1dc8",
+"T3W1_cs_bitcoin-test_multisig.py::test_15_of_15": "bd146bd85caa11793cb10742270a7a6ba07caaf8f83ad42a336137062377ba11",
+"T3W1_cs_bitcoin-test_multisig.py::test_2_of_3[False]": "cfd29897fa54a6b48d377dc2a7da56dd8583362ebc7dac1d71cd4be46ca28ea7",
+"T3W1_cs_bitcoin-test_multisig.py::test_2_of_3[True]": "d5e8596ae1605597e9211d5f181ba30a898714757fce6976d5f3259e900afda2",
+"T3W1_cs_bitcoin-test_multisig.py::test_attack_change_input": "ae5ac0482daf5378fe86b5857892416d3bc6e6a7f199650ac8c2f7ae72a66e32",
"T3W1_cs_bitcoin-test_multisig.py::test_missing_pubkey": "4b3bd3170e11f2a10db73a704c809c23da90ca9c5bca95e2384abe499a44f002",
-"T3W1_cs_bitcoin-test_multisig.py::test_pubkeys_order": "9d1ca545a1670d65d93ea403ef33430b0db8c8591bd54a35296b9260be546cd3",
-"T3W1_cs_bitcoin-test_multisig_change.py::test_external_external": "65ce8eae0d85c8628eb151bba3397ad3f56ad66d60154d57e6853a3276f7ad6f",
-"T3W1_cs_bitcoin-test_multisig_change.py::test_external_internal": "729b5a75f2dc1b06d265a79d804448524d16391ed269b35cb99b9a7bb152fe00",
-"T3W1_cs_bitcoin-test_multisig_change.py::test_internal_external": "693335013326de7d043b15204ead8c176d3a089811bcd0b6ebe956a50d37e084",
-"T3W1_cs_bitcoin-test_multisig_change.py::test_multisig_change_match_first": "3945789575536dd8de1dbd2ea9a5e28c3347172018fb27a222c9b4d9f3314b1b",
-"T3W1_cs_bitcoin-test_multisig_change.py::test_multisig_change_match_second": "1dc4adad7d5a69b66836bfaede3b848eaed58c4195e200c13e3c197862eb4d2e",
-"T3W1_cs_bitcoin-test_multisig_change.py::test_multisig_external_external": "9268d966d5b64ffffc22d6d7559d13e992d575d684c6510670e7d43363824ad1",
-"T3W1_cs_bitcoin-test_multisig_change.py::test_multisig_mismatch_inputs": "0cfcb80c6634dce77769a380467772c44618d41276aa25b0b859965557c5e922",
-"T3W1_cs_bitcoin-test_multisig_change.py::test_multisig_mismatch_multisig_change": "f338eff0166132b2e77e31882a3a2243dcb69f4c37f13b34bf453fc5c8ea5360",
-"T3W1_cs_bitcoin-test_multisig_change.py::test_multisig_mismatch_multisig_change_different_paths": "6ecb5972d9fea1167fd4736d0eb1456accadf26562736f52394008833a509f08",
-"T3W1_cs_bitcoin-test_multisig_change.py::test_sorted_multisig_change_match_first": "3945789575536dd8de1dbd2ea9a5e28c3347172018fb27a222c9b4d9f3314b1b",
-"T3W1_cs_bitcoin-test_multisig_change.py::test_sorted_multisig_mismatch_inputs": "7900ba448ea1296a227afa70f0e615d4fbe8b60d274af0f9068b092ec5fb5853",
-"T3W1_cs_bitcoin-test_multisig_change.py::test_sorted_multisig_mismatch_multisig_change": "e2661d979487cda91cffb16f0c5a667a16a43b6401946b6fbc8d7210731737fb",
+"T3W1_cs_bitcoin-test_multisig.py::test_pubkeys_order": "db5edfe912c2c2e13f1e1102d451e2d276d3dceaff708d2969166397c0ab24d8",
+"T3W1_cs_bitcoin-test_multisig_change.py::test_external_external": "65bd4080cb350053f53db9c0834714040316955b8a764f25dcc294bcb8e37241",
+"T3W1_cs_bitcoin-test_multisig_change.py::test_external_internal": "e57461714df2280d70937018e5714d224eb10fcd3cd8a4f1f31463d20dac85c6",
+"T3W1_cs_bitcoin-test_multisig_change.py::test_internal_external": "ebab3a063633c10f921e8c2455c5768f6142fc77e6095db0c44be04e653a897d",
+"T3W1_cs_bitcoin-test_multisig_change.py::test_multisig_change_match_first": "910e8e05163d09a4deb6afb8abf111ff8fe3c18899a11474b516758b172f9b87",
+"T3W1_cs_bitcoin-test_multisig_change.py::test_multisig_change_match_second": "fed465069697367256faac668105422713adaf79a42bd5a8793c6d65e35f029a",
+"T3W1_cs_bitcoin-test_multisig_change.py::test_multisig_external_external": "e8f63ea2315ba4b3906487b18d0c7d4ce90e092927b99c2e4e68235cbf0a719a",
+"T3W1_cs_bitcoin-test_multisig_change.py::test_multisig_mismatch_inputs": "02ed550d45df53bf46c34cd9cdaa5a65ee4c7264650aa1bd5711b306c4ab8458",
+"T3W1_cs_bitcoin-test_multisig_change.py::test_multisig_mismatch_multisig_change": "d9b3a7b9d4434ddc4b56836f974ffab06b4dfad4550960b7e747f0d6cf7142c4",
+"T3W1_cs_bitcoin-test_multisig_change.py::test_multisig_mismatch_multisig_change_different_paths": "ef26acb9d23577f49475c52b4d0ad7bc6c8d3961ae3e502be6e144f0573be1cd",
+"T3W1_cs_bitcoin-test_multisig_change.py::test_sorted_multisig_change_match_first": "910e8e05163d09a4deb6afb8abf111ff8fe3c18899a11474b516758b172f9b87",
+"T3W1_cs_bitcoin-test_multisig_change.py::test_sorted_multisig_mismatch_inputs": "a577555a49c0778a6e699ac48f41af05b00a1166ec8af51c5ec84bec5ffce6c6",
+"T3W1_cs_bitcoin-test_multisig_change.py::test_sorted_multisig_mismatch_multisig_change": "f859b34fa4e770bd16c7d159eb246cfdb763c046501180b2fa66026f2d215248",
"T3W1_cs_bitcoin-test_nonstandard_paths.py::test_getaddress[m-1195487518-6-255-script_types3-False]": "da9392ae736ae0eb80b299ed64af0b4e813ad7999bdd635f0cb6601759e4cf7c",
"T3W1_cs_bitcoin-test_nonstandard_paths.py::test_getaddress[m-1195487518-6-255-script_types3-True]": "a98ecd471dface3214cce0801a3d23825223705222d276ae831bcd2e5766716e",
"T3W1_cs_bitcoin-test_nonstandard_paths.py::test_getaddress[m-1195487518-script_types2-False]": "324738ec62c71968937e83c099a48327619add6bb78ced763c43d7bd144fc52d",
@@ -28811,24 +28811,24 @@
"T3W1_cs_bitcoin-test_nonstandard_paths.py::test_signmessage[m-3h-100h-4-255-script_types1]": "d82c3aadeb743e4d65a65981d1718213fc4c0139ee145cb5bbadd32cc2b271f0",
"T3W1_cs_bitcoin-test_nonstandard_paths.py::test_signmessage[m-4-255-script_types0]": "79aa4392c83354c5ff7959e56603753dcd04f1a17f4cac3bbef3103e1ebfe7af",
"T3W1_cs_bitcoin-test_nonstandard_paths.py::test_signmessage[m-49-0-63-0-255-script_types4]": "4847b8d1530d1c6c791cf68172e07ad02768d16ce2fe836c9cd924116740aa14",
-"T3W1_cs_bitcoin-test_nonstandard_paths.py::test_signtx[m-1195487518-6-255-script_types3]": "0b99f5cac024d16e9be08924f6af2c4024217c40703ea1b028dad6c53becbee6",
-"T3W1_cs_bitcoin-test_nonstandard_paths.py::test_signtx[m-1195487518-script_types2]": "9e011c210457b68fe5d5b4c48fd820d922bf84f0fb31e63df378a905ca852a80",
-"T3W1_cs_bitcoin-test_nonstandard_paths.py::test_signtx[m-3h-100h-4-255-script_types1]": "46022922f18f141da920182c51a576c85cf8115291fdbab5322064fcff8f1821",
-"T3W1_cs_bitcoin-test_nonstandard_paths.py::test_signtx[m-4-255-script_types0]": "daf88341aec54aabf702b6cfa1654a4312ea60344e761d33fb36a455c9d96c67",
-"T3W1_cs_bitcoin-test_nonstandard_paths.py::test_signtx[m-49-0-63-0-255-script_types4]": "ce91d7079534899f2dfd9fc837fc8b9f0ba7c942d08f966ca5028f17e23dc25e",
-"T3W1_cs_bitcoin-test_nonstandard_paths.py::test_signtx_multisig[paths0-address_index0]": "cb66f6bae105e90085a2a125dc8e2e1f637809358e6594733d424e9113adb949",
-"T3W1_cs_bitcoin-test_nonstandard_paths.py::test_signtx_multisig[paths1-address_index1]": "4ec30ccccff8ca5e13409040d5a3982ab67aeb35cafd4d943747b3c995d52635",
-"T3W1_cs_bitcoin-test_nonstandard_paths.py::test_signtx_multisig[paths2-address_index2]": "67ec0e8091fb3d220f9579d37207d4990ae86881663cf4e912e4a696b3de5e46",
-"T3W1_cs_bitcoin-test_nonstandard_paths.py::test_signtx_multisig[paths3-address_index3]": "e2367a0ef730fdf94968836ee656a02b14fe50a3f5f6a4e67f6a38963e731640",
-"T3W1_cs_bitcoin-test_nonstandard_paths.py::test_signtx_multisig[paths4-address_index4]": "4ec30ccccff8ca5e13409040d5a3982ab67aeb35cafd4d943747b3c995d52635",
-"T3W1_cs_bitcoin-test_nonstandard_paths.py::test_signtx_multisig[paths5-address_index5]": "4ec30ccccff8ca5e13409040d5a3982ab67aeb35cafd4d943747b3c995d52635",
-"T3W1_cs_bitcoin-test_nonstandard_paths.py::test_signtx_multisig[paths6-address_index6]": "3c1d909a5434ecc8f8fa88c0aaf4d1e5042cc810e8ad55886bac16e8b1abb2c2",
+"T3W1_cs_bitcoin-test_nonstandard_paths.py::test_signtx[m-1195487518-6-255-script_types3]": "6c048343b4092372392590ebf005cff6681071ecc05adea032bb12111935c27d",
+"T3W1_cs_bitcoin-test_nonstandard_paths.py::test_signtx[m-1195487518-script_types2]": "9b4d06133167a123e13450e818faeba43329af4d6e5815dc62272e3935438404",
+"T3W1_cs_bitcoin-test_nonstandard_paths.py::test_signtx[m-3h-100h-4-255-script_types1]": "172d5fa096700507857f5d6c194ca82543f01be2b6137b44d7c0b67fd378772d",
+"T3W1_cs_bitcoin-test_nonstandard_paths.py::test_signtx[m-4-255-script_types0]": "029905e55fb27a689e0b173ab197ca36e605972d1207e0327df5447163777929",
+"T3W1_cs_bitcoin-test_nonstandard_paths.py::test_signtx[m-49-0-63-0-255-script_types4]": "1c1da82c1118a4a5ec5b73e3ad1dd49406fa6b74e659bd204865b51ad8ce19b1",
+"T3W1_cs_bitcoin-test_nonstandard_paths.py::test_signtx_multisig[paths0-address_index0]": "8c00345fbbc97d1247a3508de66b1f7fe08abb5c8a3f0aae6f934aed9bb82714",
+"T3W1_cs_bitcoin-test_nonstandard_paths.py::test_signtx_multisig[paths1-address_index1]": "fc554f55a515c51b30d33bab62753b4330e03af73b9a27f1bfc2aceb0e35f9ec",
+"T3W1_cs_bitcoin-test_nonstandard_paths.py::test_signtx_multisig[paths2-address_index2]": "7801894caa5c679beab2aa09e20ff8a57e8e30703945461260ba833acc57ad32",
+"T3W1_cs_bitcoin-test_nonstandard_paths.py::test_signtx_multisig[paths3-address_index3]": "aa0abd114ef648997d211e85cddd5e9570095a53bf572e60494fecec29b8d5b0",
+"T3W1_cs_bitcoin-test_nonstandard_paths.py::test_signtx_multisig[paths4-address_index4]": "fc554f55a515c51b30d33bab62753b4330e03af73b9a27f1bfc2aceb0e35f9ec",
+"T3W1_cs_bitcoin-test_nonstandard_paths.py::test_signtx_multisig[paths5-address_index5]": "fc554f55a515c51b30d33bab62753b4330e03af73b9a27f1bfc2aceb0e35f9ec",
+"T3W1_cs_bitcoin-test_nonstandard_paths.py::test_signtx_multisig[paths6-address_index6]": "8ce9922e1cc6a6208fd4c5b89b442b2ccc5b4bcb075cceb5356d3b7f60d65ec0",
"T3W1_cs_bitcoin-test_op_return.py::test_nonzero_opreturn": "4b3bd3170e11f2a10db73a704c809c23da90ca9c5bca95e2384abe499a44f002",
-"T3W1_cs_bitcoin-test_op_return.py::test_opreturn": "3e129d48baf78a706cf272d889d0573ec40823b084dcdb89c80ca11e0f42d483",
+"T3W1_cs_bitcoin-test_op_return.py::test_opreturn": "c925b612aa26d07219f3494e766a621a0877b115e16c21b8b0e8b38b0245e534",
"T3W1_cs_bitcoin-test_op_return.py::test_opreturn_address": "4b3bd3170e11f2a10db73a704c809c23da90ca9c5bca95e2384abe499a44f002",
-"T3W1_cs_bitcoin-test_peercoin.py::test_timestamp_included": "3af6d9ff97b914dd26b3c360942371cf6e810400ed6bc6a996767e9df47a6796",
+"T3W1_cs_bitcoin-test_peercoin.py::test_timestamp_included": "4fcde379722f8df237c8bc21c7e916753540b8699a7646d5e01753c6baaf5c56",
"T3W1_cs_bitcoin-test_peercoin.py::test_timestamp_missing": "535037bfe5f1459cfdf305915835d8bf2a9a427c3f60264a8cc3ca6f306a61b1",
-"T3W1_cs_bitcoin-test_peercoin.py::test_timestamp_missing_prevtx": "f46475c671618d3e6c6a2f5220ae09ad2b585df4a158e7ddc4326ba7776144e0",
+"T3W1_cs_bitcoin-test_peercoin.py::test_timestamp_missing_prevtx": "2c2dfd957d19cd48dc00118cc52c06b99519d1275a5bca2bb8a68ccaeb86d7e1",
"T3W1_cs_bitcoin-test_signmessage.py::test_signmessage[NFC message]": "04165edda84fe3d05f2031e638ee24b61548e70cbffd965cdbfaa5b8f46a2684",
"T3W1_cs_bitcoin-test_signmessage.py::test_signmessage[NFKD message]": "04165edda84fe3d05f2031e638ee24b61548e70cbffd965cdbfaa5b8f46a2684",
"T3W1_cs_bitcoin-test_signmessage.py::test_signmessage[bcash]": "f4189a441f622ff1a8bfaf6d5606b169dba63a41bade0cfe39c8dc48cc02eac1",
@@ -28845,22 +28845,22 @@
"T3W1_cs_bitcoin-test_signmessage.py::test_signmessage[segwit-p2sh1]": "4f50f0102de0aaf169b05037c566b2efa761fa555c248f7697c57b8638bf9f9a",
"T3W1_cs_bitcoin-test_signmessage.py::test_signmessage[segwit-p2sh2]": "40666d5c5cd8bf0097364a6f2d0b9b4511a179b06715d3a9f44ba4f0122af8e5",
"T3W1_cs_bitcoin-test_signmessage.py::test_signmessage[t1 firmware path]": "f54ce14ad3209866926344cd91bbf413df0866d279fd1ff700fabda90d1b6085",
-"T3W1_cs_bitcoin-test_signmessage.py::test_signmessage_info[NFC message]": "bfd19139b87aac6e0c47835d616e7370261885fbb955e85a73e2c28c9262eeb8",
-"T3W1_cs_bitcoin-test_signmessage.py::test_signmessage_info[NFKD message]": "bfd19139b87aac6e0c47835d616e7370261885fbb955e85a73e2c28c9262eeb8",
-"T3W1_cs_bitcoin-test_signmessage.py::test_signmessage_info[bcash]": "1b4edb679228fce1afb3bff352a9ca994b855a3f0868fd8ce8e1dc3ed6060966",
-"T3W1_cs_bitcoin-test_signmessage.py::test_signmessage_info[grs-p2pkh]": "e7ae810d5e1b63f407989b34efe0d2a7a0afa810936ad11feff3f92155b72e76",
-"T3W1_cs_bitcoin-test_signmessage.py::test_signmessage_info[grs-segwit-native]": "080aac1709f1d46a14071014d4a2632e2a91c0ffcda3062a2911b8d515e2546d",
-"T3W1_cs_bitcoin-test_signmessage.py::test_signmessage_info[grs-segwit-p2sh]": "0ad2127c6daa23c08eb16d2611e9285b186dd2c9de028002c00b48f774ac5acc",
-"T3W1_cs_bitcoin-test_signmessage.py::test_signmessage_info[p2pkh0]": "07ce5a76106d8f4f5ab84c476ece16515df041fd3361e10d088189a3065cdae6",
-"T3W1_cs_bitcoin-test_signmessage.py::test_signmessage_info[p2pkh1]": "07ce5a76106d8f4f5ab84c476ece16515df041fd3361e10d088189a3065cdae6",
-"T3W1_cs_bitcoin-test_signmessage.py::test_signmessage_info[p2pkh2]": "3fda54dcf64fcd0f88ffda93b00bc363f3c4f12e4f2a15e2b26e6d209bb8f846",
-"T3W1_cs_bitcoin-test_signmessage.py::test_signmessage_info[segwit-native0]": "345648bd0f7d60f9c55e6609760954540f92221442f53d22278da16660ab4175",
-"T3W1_cs_bitcoin-test_signmessage.py::test_signmessage_info[segwit-native1]": "345648bd0f7d60f9c55e6609760954540f92221442f53d22278da16660ab4175",
-"T3W1_cs_bitcoin-test_signmessage.py::test_signmessage_info[segwit-native2]": "59ef41e0bd1f7c13add2a3f571bba9c9d96b427fa2de6881ec6f761884d586d4",
-"T3W1_cs_bitcoin-test_signmessage.py::test_signmessage_info[segwit-p2sh0]": "4c87c7b1ff8eaef9a97abb3003b29439d4984addcd525fae89c7169644c39c5d",
-"T3W1_cs_bitcoin-test_signmessage.py::test_signmessage_info[segwit-p2sh1]": "4c87c7b1ff8eaef9a97abb3003b29439d4984addcd525fae89c7169644c39c5d",
-"T3W1_cs_bitcoin-test_signmessage.py::test_signmessage_info[segwit-p2sh2]": "b08de68efa40b429d6cb533995c3e0126f69299c47e3a37190dda0a61728736d",
-"T3W1_cs_bitcoin-test_signmessage.py::test_signmessage_info[t1 firmware path]": "d7bf569812990533cbd0ce4482ec12c5840cd420be3d7b26a2e1a172d97f3dcc",
+"T3W1_cs_bitcoin-test_signmessage.py::test_signmessage_info[NFC message]": "a5bd5e8b257be562f27d868b927f1e22069985bc851de25872c8a2c50c9cb0a3",
+"T3W1_cs_bitcoin-test_signmessage.py::test_signmessage_info[NFKD message]": "a5bd5e8b257be562f27d868b927f1e22069985bc851de25872c8a2c50c9cb0a3",
+"T3W1_cs_bitcoin-test_signmessage.py::test_signmessage_info[bcash]": "d34936ba89befd3480aac38b06f9af428a2d6f746dfe9c388e88b83223d4a16c",
+"T3W1_cs_bitcoin-test_signmessage.py::test_signmessage_info[grs-p2pkh]": "8c724415d3fe39c9c717d277a9adf491232036d4798b393c532b85a0e4b856a5",
+"T3W1_cs_bitcoin-test_signmessage.py::test_signmessage_info[grs-segwit-native]": "87a7c263b2291b07a9e4ffa1a6cf8e23f5c70123be15a8e8cb3a171a8473d145",
+"T3W1_cs_bitcoin-test_signmessage.py::test_signmessage_info[grs-segwit-p2sh]": "19cd341ae5dd56088afe89d097dd2b84ffec313b4361fb3d74ebed3480d98028",
+"T3W1_cs_bitcoin-test_signmessage.py::test_signmessage_info[p2pkh0]": "2b64e896ceda0bb19fdf068ecd32e5c3a05e1210b66697de39f19de5684e332c",
+"T3W1_cs_bitcoin-test_signmessage.py::test_signmessage_info[p2pkh1]": "2b64e896ceda0bb19fdf068ecd32e5c3a05e1210b66697de39f19de5684e332c",
+"T3W1_cs_bitcoin-test_signmessage.py::test_signmessage_info[p2pkh2]": "0019fbae72ecba7cba592bc58a9aa1b6f111c689db470a9ff8c81e6a8c61cb14",
+"T3W1_cs_bitcoin-test_signmessage.py::test_signmessage_info[segwit-native0]": "c4f40c45a169e8099bec852d0218b04a28378bf69309b61fcc87948ad11f4a21",
+"T3W1_cs_bitcoin-test_signmessage.py::test_signmessage_info[segwit-native1]": "c4f40c45a169e8099bec852d0218b04a28378bf69309b61fcc87948ad11f4a21",
+"T3W1_cs_bitcoin-test_signmessage.py::test_signmessage_info[segwit-native2]": "d031dfc296144fc858b94983f3ae45e4e527870a2a154da5916222153bcac7e3",
+"T3W1_cs_bitcoin-test_signmessage.py::test_signmessage_info[segwit-p2sh0]": "e39fd5939b4f26e7867840f30522aa85f7b235fd37f0ecf97708b3a64acd4c47",
+"T3W1_cs_bitcoin-test_signmessage.py::test_signmessage_info[segwit-p2sh1]": "e39fd5939b4f26e7867840f30522aa85f7b235fd37f0ecf97708b3a64acd4c47",
+"T3W1_cs_bitcoin-test_signmessage.py::test_signmessage_info[segwit-p2sh2]": "849c808a174cace21a03f0705da5695f4672a6fa4a1ac48e882dfb63dcdd0ff5",
+"T3W1_cs_bitcoin-test_signmessage.py::test_signmessage_info[t1 firmware path]": "a9bcb81035c9659c599933345069ffb8f752736ae5ae7ba8739ac2b83e7fbb0d",
"T3W1_cs_bitcoin-test_signmessage.py::test_signmessage_long[p2pkh long message]": "17deace81216fed4340096b64d76a141955a8662965cd7b86c94bdc062695432",
"T3W1_cs_bitcoin-test_signmessage.py::test_signmessage_long[segwit-native long message]": "5db999e39b85ec9762d154f6004f5a49e9c775b52d3507e3c4a1ddcd57201929",
"T3W1_cs_bitcoin-test_signmessage.py::test_signmessage_long[segwit-p2sh long message]": "04d08be36a70baab7bca1219877234796f4a76d5ec1d72d7977222440e61e2ed",
@@ -28872,109 +28872,109 @@
"T3W1_cs_bitcoin-test_signmessage.py::test_signmessage_pagination_eckhart[utf_nospace]": "d8839ee667e1e23dde4c296a01abc1100a8756a62ae3d52ba73a44a34cd915a3",
"T3W1_cs_bitcoin-test_signmessage.py::test_signmessage_pagination_eckhart[utf_text]": "4e8da72b6d81b4ef7e251e535fadf801152f0df8cc4a41410a0f341c972e1ca1",
"T3W1_cs_bitcoin-test_signmessage.py::test_signmessage_path_warning": "3a4d142a2fbfdcde6f40ec4a9204249fac9b16d8269e2235fc84fa2043dadfbb",
-"T3W1_cs_bitcoin-test_signtx.py::test_attack_change_input_address": "9c42cc1095ab57c7ecc95d9311bc9da79d336bcfeb8a929005ce5f385bf5c7c3",
-"T3W1_cs_bitcoin-test_signtx.py::test_attack_change_outputs": "a8a71eb54f84b79a4d3695d835261f3b0d1b2d07128ad9a77c4712060ff7cf42",
-"T3W1_cs_bitcoin-test_signtx.py::test_attack_modify_change_address": "86b4a652e59523c76e5a318d57eec28b33a176c45788fe850b94769514eabf47",
-"T3W1_cs_bitcoin-test_signtx.py::test_change_on_main_chain_allowed": "23fbc1e721576d9c82a55e5ae9ce0aba043bd7437e8f02e7c2e1602f0c8beef3",
-"T3W1_cs_bitcoin-test_signtx.py::test_fee_high_hardfail": "6a1df6936cc354986b329d336e876341df9c9aa2600625753d17220cc1c75ad6",
-"T3W1_cs_bitcoin-test_signtx.py::test_fee_high_warning": "8d1e9c7c5ddd4ad8324f3cb12740413af6f0459b646bff6783587d3eaa217837",
+"T3W1_cs_bitcoin-test_signtx.py::test_attack_change_input_address": "e571274c0cc0238bb1328694fa22dd50deeb87119e3546e0f117ec19cf2c0438",
+"T3W1_cs_bitcoin-test_signtx.py::test_attack_change_outputs": "f1e326ea03eaa9782c15da469e499fab129aec0dd6e2b6636304766801e1eeb3",
+"T3W1_cs_bitcoin-test_signtx.py::test_attack_modify_change_address": "2c01b2e2110a9011c3437c32cbbdf8078994f6e08cf218a6cee20855d0e1de71",
+"T3W1_cs_bitcoin-test_signtx.py::test_change_on_main_chain_allowed": "c702df46a6f88a5b0ae9d3501413e9c6c7413f16cd80982177edfba71d5a82d5",
+"T3W1_cs_bitcoin-test_signtx.py::test_fee_high_hardfail": "522cd3630c3020a534d89c054a237a012677f8726a992ae9acbe2cafb4dfe695",
+"T3W1_cs_bitcoin-test_signtx.py::test_fee_high_warning": "a0f4d0f8cb33a972f4bea5e765cf9da97e49dc17b5e6546c3924d96480b514bb",
"T3W1_cs_bitcoin-test_signtx.py::test_incorrect_input_script_type[InputScriptType.EXTERNAL]": "4b3bd3170e11f2a10db73a704c809c23da90ca9c5bca95e2384abe499a44f002",
"T3W1_cs_bitcoin-test_signtx.py::test_incorrect_input_script_type[InputScriptType.SPENDADDRESS]": "4b3bd3170e11f2a10db73a704c809c23da90ca9c5bca95e2384abe499a44f002",
"T3W1_cs_bitcoin-test_signtx.py::test_incorrect_output_script_type[OutputScriptType.PAYTOADDRESS]": "4b3bd3170e11f2a10db73a704c809c23da90ca9c5bca95e2384abe499a44f002",
"T3W1_cs_bitcoin-test_signtx.py::test_incorrect_output_script_type[OutputScriptType.PAYTOSCRIPTHASH]": "4b3bd3170e11f2a10db73a704c809c23da90ca9c5bca95e2384abe499a44f002",
-"T3W1_cs_bitcoin-test_signtx.py::test_information": "ad1c17371e4b32118f44fecc1742bf7de2589dd8487b4d67247ab821bdc6c2d2",
-"T3W1_cs_bitcoin-test_signtx.py::test_information_cancel": "2b5628497d873b52382e7f335ae7d3ce007c1e835e86f8c4417383151371e9ad",
-"T3W1_cs_bitcoin-test_signtx.py::test_information_mixed": "106b78cf818b2ed5ec81714027ddf08cf91991334351195d3afa2118b49b2439",
-"T3W1_cs_bitcoin-test_signtx.py::test_information_replacement": "cef8a50ce7a52a0dfd5b81b499d3d423039bce91ae0dd9ccc82bd9b413ff5e10",
-"T3W1_cs_bitcoin-test_signtx.py::test_lock_time[1-4294967295]": "8e74cadb5e49784f0e6dca66d8280dcf1cfc074b56fba7863bcaa3a8b72d7ac4",
-"T3W1_cs_bitcoin-test_signtx.py::test_lock_time[499999999-4294967294]": "57baf8e28130ab535f19daf6b0f0764208520937dbc5d8dd749eb257730e106b",
-"T3W1_cs_bitcoin-test_signtx.py::test_lock_time[500000000-4294967294]": "13678a1d92bdce7d2dd10965c9459b8bd44e73091081e09cd73ce88b6d43241c",
-"T3W1_cs_bitcoin-test_signtx.py::test_lock_time_blockheight": "bed3ce01276516b6a0762a8633b239b9d7f35eb67bfd95f5fcf63fd75a1d716b",
-"T3W1_cs_bitcoin-test_signtx.py::test_lock_time_datetime[1985-11-05 00:53:20]": "e439988f0e3caeb7448f82fc0587e2f569a7530dd9b93fa2a92a860d9a65d635",
-"T3W1_cs_bitcoin-test_signtx.py::test_lock_time_datetime[2048-08-16 22:14:00]": "289025a51df5395ea78102425f2c399b33d38e01c2ad94e42a6c64d27c1e0504",
-"T3W1_cs_bitcoin-test_signtx.py::test_lots_of_change": "8720b55bd4ed033cec34095a7fd94134887fb7f872dd9949d2d3eb96a9162c79",
-"T3W1_cs_bitcoin-test_signtx.py::test_lots_of_inputs": "47bb6a267a81f9cd5751b1ff19cb17945a62e538183bf0fe6c17728675063db5",
-"T3W1_cs_bitcoin-test_signtx.py::test_lots_of_outputs": "fbb736fe19b0e3d29dbb89b11a11221ebb8af51bce64e9fd83d9049c96b88d64",
+"T3W1_cs_bitcoin-test_signtx.py::test_information": "b2a6c5e311fe972e2065ea8f82032147cc3f0dec7c13b8316aa1134760656f63",
+"T3W1_cs_bitcoin-test_signtx.py::test_information_cancel": "e2c0a6ad8ebd6b690c2ae3d3e417d237521008a48b09f409fc2afd57dbd1db9d",
+"T3W1_cs_bitcoin-test_signtx.py::test_information_mixed": "0603cae554d1089ff58cf264d44ab0c95b4f536c72a449e337de51e80027459b",
+"T3W1_cs_bitcoin-test_signtx.py::test_information_replacement": "61088dba9b7798463b54159e7a1124ea821553f81cfab3de2be2adde84c94373",
+"T3W1_cs_bitcoin-test_signtx.py::test_lock_time[1-4294967295]": "4e35729b3033f36ecac00bf134ee0b8015761a0b0b9d3e9d8c84e50bd65706cd",
+"T3W1_cs_bitcoin-test_signtx.py::test_lock_time[499999999-4294967294]": "11745371fffc28a409fe900a4ef0624df94e75bceadf271d13868347b2e86e88",
+"T3W1_cs_bitcoin-test_signtx.py::test_lock_time[500000000-4294967294]": "375c13081b5667988eea136b081cef79e0312e8a458ceb94a9eada434d3cc8d5",
+"T3W1_cs_bitcoin-test_signtx.py::test_lock_time_blockheight": "6b2a1fbbcf84e0f64d525516fd549a72745fc10d174b3fa485140b9ab8821f9e",
+"T3W1_cs_bitcoin-test_signtx.py::test_lock_time_datetime[1985-11-05 00:53:20]": "3e6fbd60eaafa77c03557990ac6b1fd3bfd4fd4a245021f9306ef404eff69cfb",
+"T3W1_cs_bitcoin-test_signtx.py::test_lock_time_datetime[2048-08-16 22:14:00]": "b074f423ce6a6d7312e0bd353fe2f5c76e59f0ac2ed186216506d58af98a2e25",
+"T3W1_cs_bitcoin-test_signtx.py::test_lots_of_change": "7e04c63360e7245041890c919d2970d6b2944948fa84b385f21c1ba8f3223f7e",
+"T3W1_cs_bitcoin-test_signtx.py::test_lots_of_inputs": "1945818c284d2ef94bad820e3597d2532922117dec621d6077b317de9d993903",
+"T3W1_cs_bitcoin-test_signtx.py::test_lots_of_outputs": "ae12f16b912805df50a06fd62127dd733d797d3438f4f941cba99f504f4b3092",
"T3W1_cs_bitcoin-test_signtx.py::test_not_enough_funds": "2a960ad228bc91595d96414ce4032a1fc7b930d4353e3c3f209cd587acd5f88c",
-"T3W1_cs_bitcoin-test_signtx.py::test_not_enough_vouts": "156d1183894bb354e18460abfe890886cf297f3e138e31dab06048062d54172d",
-"T3W1_cs_bitcoin-test_signtx.py::test_one_one_fee": "6e7f6c1c04d745f37e11ca0307c988bd4b95eb354d0b9e916a724c47d62dcd51",
-"T3W1_cs_bitcoin-test_signtx.py::test_one_three_fee[False]": "f9e8c3bc9df2f55cfbc08d3a5326f47ee03553eddec8d33b0910faca47e76012",
-"T3W1_cs_bitcoin-test_signtx.py::test_one_three_fee[True]": "fc9b8aaeff307a876d8dbea97c9a41f24200205b0417e3e758a082ecf93d84ea",
-"T3W1_cs_bitcoin-test_signtx.py::test_one_two_fee": "e2dcc9c0ad5f8fc4e3c68d4f9c75b49c3a865ee90edd45cf9fb89432ece256c8",
-"T3W1_cs_bitcoin-test_signtx.py::test_p2sh": "bc265c1a59edab031730351f98f88d2d8f98e3a143789e2df80679475eb374c2",
-"T3W1_cs_bitcoin-test_signtx.py::test_prevtx_forbidden_fields[branch_id-13]": "3e84480492bd91cab38c6eedded675a2adfc8b4efd853b1a7ecf151aa93ab04c",
-"T3W1_cs_bitcoin-test_signtx.py::test_prevtx_forbidden_fields[expiry-9]": "3e84480492bd91cab38c6eedded675a2adfc8b4efd853b1a7ecf151aa93ab04c",
-"T3W1_cs_bitcoin-test_signtx.py::test_prevtx_forbidden_fields[extra_data-hello world]": "3e84480492bd91cab38c6eedded675a2adfc8b4efd853b1a7ecf151aa93ab04c",
-"T3W1_cs_bitcoin-test_signtx.py::test_prevtx_forbidden_fields[timestamp-42]": "3e84480492bd91cab38c6eedded675a2adfc8b4efd853b1a7ecf151aa93ab04c",
-"T3W1_cs_bitcoin-test_signtx.py::test_prevtx_forbidden_fields[version_group_id-69]": "3e84480492bd91cab38c6eedded675a2adfc8b4efd853b1a7ecf151aa93ab04c",
+"T3W1_cs_bitcoin-test_signtx.py::test_not_enough_vouts": "e6dceceba078b3129a7a75d1550783bf7e6d540e35372777e4631d9bee9b8faa",
+"T3W1_cs_bitcoin-test_signtx.py::test_one_one_fee": "6e347566916667302b2041c35398c05edb34327225b10767d9f895c81e25e462",
+"T3W1_cs_bitcoin-test_signtx.py::test_one_three_fee[False]": "470566e02ed654db0c99a9591874d40836e6c4b354cf000586c55e691e4c9bd1",
+"T3W1_cs_bitcoin-test_signtx.py::test_one_three_fee[True]": "2f9ecc90bc220d8a7b2937debec32df9493fbe46d570c5c3db56b4df96e22c0f",
+"T3W1_cs_bitcoin-test_signtx.py::test_one_two_fee": "cdb4cc7a24021525001dd155fac3def0d38587531efb192a15b99ad56575bb05",
+"T3W1_cs_bitcoin-test_signtx.py::test_p2sh": "c0e563e49e04a8f2fc066a0c8c2fcb07b6a70020b7ca78743e8595e28ae1d82e",
+"T3W1_cs_bitcoin-test_signtx.py::test_prevtx_forbidden_fields[branch_id-13]": "308c6532318469635ffa22ac9fb73110318b10c2fdb5f041097e5c1cb8a23bb5",
+"T3W1_cs_bitcoin-test_signtx.py::test_prevtx_forbidden_fields[expiry-9]": "308c6532318469635ffa22ac9fb73110318b10c2fdb5f041097e5c1cb8a23bb5",
+"T3W1_cs_bitcoin-test_signtx.py::test_prevtx_forbidden_fields[extra_data-hello world]": "308c6532318469635ffa22ac9fb73110318b10c2fdb5f041097e5c1cb8a23bb5",
+"T3W1_cs_bitcoin-test_signtx.py::test_prevtx_forbidden_fields[timestamp-42]": "308c6532318469635ffa22ac9fb73110318b10c2fdb5f041097e5c1cb8a23bb5",
+"T3W1_cs_bitcoin-test_signtx.py::test_prevtx_forbidden_fields[version_group_id-69]": "308c6532318469635ffa22ac9fb73110318b10c2fdb5f041097e5c1cb8a23bb5",
"T3W1_cs_bitcoin-test_signtx.py::test_signtx_forbidden_fields[branch_id-13]": "535037bfe5f1459cfdf305915835d8bf2a9a427c3f60264a8cc3ca6f306a61b1",
"T3W1_cs_bitcoin-test_signtx.py::test_signtx_forbidden_fields[expiry-9]": "535037bfe5f1459cfdf305915835d8bf2a9a427c3f60264a8cc3ca6f306a61b1",
"T3W1_cs_bitcoin-test_signtx.py::test_signtx_forbidden_fields[timestamp-42]": "535037bfe5f1459cfdf305915835d8bf2a9a427c3f60264a8cc3ca6f306a61b1",
"T3W1_cs_bitcoin-test_signtx.py::test_signtx_forbidden_fields[version_group_id-69]": "535037bfe5f1459cfdf305915835d8bf2a9a427c3f60264a8cc3ca6f306a61b1",
-"T3W1_cs_bitcoin-test_signtx.py::test_spend_coinbase": "a1405842ee94773d00dd985cfc6f59d1706592029d69d360195bdccecc6cb1ee",
-"T3W1_cs_bitcoin-test_signtx.py::test_testnet_big_amount": "2209f0279da73f329507e7dd5036afea8ca338fbce2dfd690f48a3d27619d010",
-"T3W1_cs_bitcoin-test_signtx.py::test_testnet_fee_high_warning": "971db6ac60aef09aa51ae6e88682b6855420e49a4fbe2c06db2f8be32b6626e0",
-"T3W1_cs_bitcoin-test_signtx.py::test_testnet_one_two_fee": "23fbc1e721576d9c82a55e5ae9ce0aba043bd7437e8f02e7c2e1602f0c8beef3",
-"T3W1_cs_bitcoin-test_signtx.py::test_two_changes": "065ea17384b72e4b65a903a91b8852419e7b012213d919f8ef875d6683ff2058",
-"T3W1_cs_bitcoin-test_signtx.py::test_two_two": "20850fce6bff788a61acd27124bb8b68a5c0fa4350a1caea805ee868d3cc37b1",
-"T3W1_cs_bitcoin-test_signtx_amount_unit.py::test_signtx_btc[AmountUnit.BITCOIN]": "6e7f6c1c04d745f37e11ca0307c988bd4b95eb354d0b9e916a724c47d62dcd51",
-"T3W1_cs_bitcoin-test_signtx_amount_unit.py::test_signtx_btc[AmountUnit.MICROBITCOIN]": "6aeb4ccd3421aae8b550a01b196ba18e9a4d47a50b59201744916a5cc21e2b13",
-"T3W1_cs_bitcoin-test_signtx_amount_unit.py::test_signtx_btc[AmountUnit.MILLIBITCOIN]": "bc50adf7995b3e429e3f260877023e1a44366bc26505cb96632dc503ccbf6728",
-"T3W1_cs_bitcoin-test_signtx_amount_unit.py::test_signtx_btc[AmountUnit.SATOSHI]": "3209f100f1b13e0fb0075a95d83743fdd3520aa29441ffaeda20f4134c5774ff",
-"T3W1_cs_bitcoin-test_signtx_amount_unit.py::test_signtx_btc[None]": "6e7f6c1c04d745f37e11ca0307c988bd4b95eb354d0b9e916a724c47d62dcd51",
-"T3W1_cs_bitcoin-test_signtx_amount_unit.py::test_signtx_testnet[AmountUnit.BITCOIN]": "3b8d243921c7afc3d404e2ef185f2ee6a1d50c02c0ee2a22acede697ea0742e7",
-"T3W1_cs_bitcoin-test_signtx_amount_unit.py::test_signtx_testnet[AmountUnit.MICROBITCOIN]": "64eef3890f029c5f27ffc422004f2fd0195a2646deec85b0947a49d66cff7a04",
-"T3W1_cs_bitcoin-test_signtx_amount_unit.py::test_signtx_testnet[AmountUnit.MILLIBITCOIN]": "70eb9ea69936664aca235d892b0531e0e4d1981cae8b91973828a85f455a4d08",
-"T3W1_cs_bitcoin-test_signtx_amount_unit.py::test_signtx_testnet[AmountUnit.SATOSHI]": "607bb6dfe4a85c0653c886c1b389a5117e719870f3e6b6a17612a3b564090c0e",
-"T3W1_cs_bitcoin-test_signtx_amount_unit.py::test_signtx_testnet[None]": "3b8d243921c7afc3d404e2ef185f2ee6a1d50c02c0ee2a22acede697ea0742e7",
-"T3W1_cs_bitcoin-test_signtx_external.py::test_p2pkh_presigned": "e1aed4d98fb33af68165f67bd741faa8f664d533658791c3af074a8ea9f7bcff",
+"T3W1_cs_bitcoin-test_signtx.py::test_spend_coinbase": "f8baba4380382a416e1d6be15635e36d89e336b7c428f28848a941d21f31ed20",
+"T3W1_cs_bitcoin-test_signtx.py::test_testnet_big_amount": "88481888ab2c052330294085cbd21e639db133087203328b7e11205109424fb4",
+"T3W1_cs_bitcoin-test_signtx.py::test_testnet_fee_high_warning": "ae48b8b15e30fc8941ca280085a09cd17e58226ae45ce2acd180adc420a26c2e",
+"T3W1_cs_bitcoin-test_signtx.py::test_testnet_one_two_fee": "c702df46a6f88a5b0ae9d3501413e9c6c7413f16cd80982177edfba71d5a82d5",
+"T3W1_cs_bitcoin-test_signtx.py::test_two_changes": "fd8d5ff8515d2a5403e4247b33a9b4de72b613320b83fb644ab32792bae32395",
+"T3W1_cs_bitcoin-test_signtx.py::test_two_two": "38b8214a9549a011ea944d8b894e5ff316066282ac46691d7e286074d44b975d",
+"T3W1_cs_bitcoin-test_signtx_amount_unit.py::test_signtx_btc[AmountUnit.BITCOIN]": "6e347566916667302b2041c35398c05edb34327225b10767d9f895c81e25e462",
+"T3W1_cs_bitcoin-test_signtx_amount_unit.py::test_signtx_btc[AmountUnit.MICROBITCOIN]": "4b870cd625d47ddbb60f99662a69c6b22117684e1dee93f0e66ffcce1b2c90ce",
+"T3W1_cs_bitcoin-test_signtx_amount_unit.py::test_signtx_btc[AmountUnit.MILLIBITCOIN]": "0692a9dde5a34e72129de49884d5373b022768d50d418e05894a20df3d7ac97c",
+"T3W1_cs_bitcoin-test_signtx_amount_unit.py::test_signtx_btc[AmountUnit.SATOSHI]": "db423188c327d647f2fd10240caa28b573a1cd6f96a76810eb3bcaeb232669b9",
+"T3W1_cs_bitcoin-test_signtx_amount_unit.py::test_signtx_btc[None]": "6e347566916667302b2041c35398c05edb34327225b10767d9f895c81e25e462",
+"T3W1_cs_bitcoin-test_signtx_amount_unit.py::test_signtx_testnet[AmountUnit.BITCOIN]": "862ca46cd89222597f6858747dec8f4e5fb1612c8bc3e920f4c87f5b3a873411",
+"T3W1_cs_bitcoin-test_signtx_amount_unit.py::test_signtx_testnet[AmountUnit.MICROBITCOIN]": "ae00ecba15fa24c8642c2f81723b854d6f589c6d986c36fb7b6651478972df5d",
+"T3W1_cs_bitcoin-test_signtx_amount_unit.py::test_signtx_testnet[AmountUnit.MILLIBITCOIN]": "96942b4638323af66c9ba58b9a7a2fbf586836a12b09bf804f3d89cc1371f746",
+"T3W1_cs_bitcoin-test_signtx_amount_unit.py::test_signtx_testnet[AmountUnit.SATOSHI]": "70d808e61e8d02c4992561a2160fe05ed89d8fed6744b64bb8190bfc650bc0a1",
+"T3W1_cs_bitcoin-test_signtx_amount_unit.py::test_signtx_testnet[None]": "862ca46cd89222597f6858747dec8f4e5fb1612c8bc3e920f4c87f5b3a873411",
+"T3W1_cs_bitcoin-test_signtx_external.py::test_p2pkh_presigned": "1a082783c676006a3c927d975198fb2eea1dd56d7db281922bbe3b70444eef46",
"T3W1_cs_bitcoin-test_signtx_external.py::test_p2pkh_with_proof": "535037bfe5f1459cfdf305915835d8bf2a9a427c3f60264a8cc3ca6f306a61b1",
-"T3W1_cs_bitcoin-test_signtx_external.py::test_p2tr_external_presigned": "8466f1d229e4c623b869079c36ddebd4295dea81603ca988897ca2c0a52c1627",
-"T3W1_cs_bitcoin-test_signtx_external.py::test_p2tr_external_unverified": "89782194587d942a08801e64023250e02de6555109d40d1cbad8b58e891467d3",
-"T3W1_cs_bitcoin-test_signtx_external.py::test_p2tr_with_proof": "524fe8281f8eef1c95d0afddc035c95224bb74289b8f704d233bb1d45432754a",
-"T3W1_cs_bitcoin-test_signtx_external.py::test_p2wpkh_external_unverified": "9e0a876ac7347cbe3460917887cda9b58231eb55ffbd7653051ece31f52de219",
-"T3W1_cs_bitcoin-test_signtx_external.py::test_p2wpkh_in_p2sh_presigned": "b9016a0a70c20ed76b10dd0d913bc8e4510d25d9762dc182cc40bff5229b0c4e",
+"T3W1_cs_bitcoin-test_signtx_external.py::test_p2tr_external_presigned": "90a79783f128f221ec98ac43d579d205ea01d173cbfdc43f4463f756bdcb9a5f",
+"T3W1_cs_bitcoin-test_signtx_external.py::test_p2tr_external_unverified": "09512f2f638dc16e361f255aa05a2d6d31303c6c0e8425faa97972e326d65e53",
+"T3W1_cs_bitcoin-test_signtx_external.py::test_p2tr_with_proof": "4f480e915dc8179e812b0319cafa62177355686ea9efe9c901f19e0d3ad787dc",
+"T3W1_cs_bitcoin-test_signtx_external.py::test_p2wpkh_external_unverified": "522f5b9b6086e01818ce4f0e3bb190bb69be5d60fb774c75d22beeec4c46aee2",
+"T3W1_cs_bitcoin-test_signtx_external.py::test_p2wpkh_in_p2sh_presigned": "3e3ee92472976293978bb28fa7bc3047579d30d055f9d765e372792e379fbcfb",
"T3W1_cs_bitcoin-test_signtx_external.py::test_p2wpkh_in_p2sh_with_proof": "535037bfe5f1459cfdf305915835d8bf2a9a427c3f60264a8cc3ca6f306a61b1",
-"T3W1_cs_bitcoin-test_signtx_external.py::test_p2wpkh_presigned": "ce19bbf9f9c5e9487e51ea9103167f8f10e2ae3b5b757ad062993bee0b0b1179",
+"T3W1_cs_bitcoin-test_signtx_external.py::test_p2wpkh_presigned": "4634b6825d663ad1672989f414b50aa007b1d48272ae7dab25bcde89800edc2b",
"T3W1_cs_bitcoin-test_signtx_external.py::test_p2wpkh_with_false_proof": "4b3bd3170e11f2a10db73a704c809c23da90ca9c5bca95e2384abe499a44f002",
-"T3W1_cs_bitcoin-test_signtx_external.py::test_p2wpkh_with_proof": "0ed030f2b07f8477cd25496127c1c1e21c0c2166d0c8c8fd92ca9c8d5ac35676",
-"T3W1_cs_bitcoin-test_signtx_external.py::test_p2wsh_external_presigned": "77564eb933464754f8afe73173f3529ff0814b735a038f690e183e79db74743c",
-"T3W1_cs_bitcoin-test_signtx_invalid_path.py::test_attack_path_segwit": "ca3762434a0be4b9d8a5da4311761a31237734e3840608c5a9704363b3b5334c",
+"T3W1_cs_bitcoin-test_signtx_external.py::test_p2wpkh_with_proof": "0e7deaf1c8e671c5fc17fb51c47f0876fbeb34f5ce68977dc7673c40cc88d86c",
+"T3W1_cs_bitcoin-test_signtx_external.py::test_p2wsh_external_presigned": "03d5d5438de20e7afa8fc89c747d5c6dfde2521df329d504342f107097489e17",
+"T3W1_cs_bitcoin-test_signtx_invalid_path.py::test_attack_path_segwit": "6ea1ffc19c3cd77241b587451db22b63c866857410198fec61b7bdb6d160b792",
"T3W1_cs_bitcoin-test_signtx_invalid_path.py::test_invalid_path_fail": "4b3bd3170e11f2a10db73a704c809c23da90ca9c5bca95e2384abe499a44f002",
"T3W1_cs_bitcoin-test_signtx_invalid_path.py::test_invalid_path_fail_asap": "4b3bd3170e11f2a10db73a704c809c23da90ca9c5bca95e2384abe499a44f002",
-"T3W1_cs_bitcoin-test_signtx_invalid_path.py::test_invalid_path_pass_forkid": "d4728148f6d87e3f9ee515564d1150f985f8f913f9820303fdc815dc6cfcaa3f",
-"T3W1_cs_bitcoin-test_signtx_invalid_path.py::test_invalid_path_prompt": "127f527110845b4f45f2ee6703ca55af3ca2fc337d6f82fa54e9676d07eca61a",
-"T3W1_cs_bitcoin-test_signtx_mixed_inputs.py::test_non_segwit_segwit_inputs": "75da728664c1a84df6a1cc9f25775e2d276c91565d34cc8e1fc694f3674afaba",
-"T3W1_cs_bitcoin-test_signtx_mixed_inputs.py::test_non_segwit_segwit_non_segwit_inputs": "253912a080ccd7c88a9b4b1fce279d1b0eceb1b742ce1b6ce08d333bc4ca2023",
-"T3W1_cs_bitcoin-test_signtx_mixed_inputs.py::test_segwit_non_segwit_inputs": "75da728664c1a84df6a1cc9f25775e2d276c91565d34cc8e1fc694f3674afaba",
-"T3W1_cs_bitcoin-test_signtx_mixed_inputs.py::test_segwit_non_segwit_segwit_inputs": "253912a080ccd7c88a9b4b1fce279d1b0eceb1b742ce1b6ce08d333bc4ca2023",
+"T3W1_cs_bitcoin-test_signtx_invalid_path.py::test_invalid_path_pass_forkid": "a820e3c85b895a4fbdbc6928f3cf09464f8595f46d1b9a9e351f345cef01bb34",
+"T3W1_cs_bitcoin-test_signtx_invalid_path.py::test_invalid_path_prompt": "67e2582332370f9eedc6b16a9c0cdfb6051078514da950c7ebc8674ce1ebdfc0",
+"T3W1_cs_bitcoin-test_signtx_mixed_inputs.py::test_non_segwit_segwit_inputs": "696d94de3bb22ade0f7f1e0c58a7908abcaa81c758500e47d5801cc6818b41c8",
+"T3W1_cs_bitcoin-test_signtx_mixed_inputs.py::test_non_segwit_segwit_non_segwit_inputs": "6dc02a8d3ca2b0d47740f9ee0b96c9aebd51a77474a9fc7fd341445cf20d8c69",
+"T3W1_cs_bitcoin-test_signtx_mixed_inputs.py::test_segwit_non_segwit_inputs": "696d94de3bb22ade0f7f1e0c58a7908abcaa81c758500e47d5801cc6818b41c8",
+"T3W1_cs_bitcoin-test_signtx_mixed_inputs.py::test_segwit_non_segwit_segwit_inputs": "6dc02a8d3ca2b0d47740f9ee0b96c9aebd51a77474a9fc7fd341445cf20d8c69",
"T3W1_cs_bitcoin-test_signtx_payreq.py::test_payment_req_wrong_amount": "2565d54594c1ad333a3c84abc6f96072f59f65cbc2c695036ff4727cae5138f3",
"T3W1_cs_bitcoin-test_signtx_payreq.py::test_payment_req_wrong_mac_purchase": "4b3bd3170e11f2a10db73a704c809c23da90ca9c5bca95e2384abe499a44f002",
"T3W1_cs_bitcoin-test_signtx_payreq.py::test_payment_req_wrong_mac_refund": "4b3bd3170e11f2a10db73a704c809c23da90ca9c5bca95e2384abe499a44f002",
"T3W1_cs_bitcoin-test_signtx_payreq.py::test_payment_req_wrong_output": "2565d54594c1ad333a3c84abc6f96072f59f65cbc2c695036ff4727cae5138f3",
-"T3W1_cs_bitcoin-test_signtx_payreq.py::test_payment_request[out0+out1]": "bc16844928bd982f286295e2615fb3f3084220437c06042538a6355ab531d879",
-"T3W1_cs_bitcoin-test_signtx_payreq.py::test_payment_request[out012]": "dd983a8b3e55ea0de4cb36bfc8506bf5fe74fb505c00232af197a2ec556cc036",
-"T3W1_cs_bitcoin-test_signtx_payreq.py::test_payment_request[out01]": "6b30f33a2bb6ae7c93161eae1901b659fd2d81ecd189a28f376d5d233dd5e415",
-"T3W1_cs_bitcoin-test_signtx_payreq.py::test_payment_request[out0]": "e45417c1948c40ac15fc494c502c82bb712c8c45b65a9e3fd4dee3cd34e8a96e",
-"T3W1_cs_bitcoin-test_signtx_payreq.py::test_payment_request[out12]": "4003c2561b54eb06cee4437c71fb9571d32e3432495bbd49fcb946eb1669aec2",
-"T3W1_cs_bitcoin-test_signtx_payreq.py::test_payment_request[out1]": "827a85ecbd943436ba91260533b622217d85dc99d28e5688f699662d91902036",
-"T3W1_cs_bitcoin-test_signtx_payreq.py::test_payment_request[out2]": "33b881520571a00007910bc6b69871d986c410a1e55c33d3ed0bb10e3ebbbdc1",
-"T3W1_cs_bitcoin-test_signtx_payreq.py::test_signtx_payment_req_swap_with_text_and_refund[False-False]": "201822eaec922d3de714b5de1130cb0e24b7c02579a3ae62e8cffdda8e163f58",
-"T3W1_cs_bitcoin-test_signtx_payreq.py::test_signtx_payment_req_swap_with_text_and_refund[False-True]": "201822eaec922d3de714b5de1130cb0e24b7c02579a3ae62e8cffdda8e163f58",
-"T3W1_cs_bitcoin-test_signtx_payreq.py::test_signtx_payment_req_swap_with_text_and_refund[True-False]": "52485f4e4b76144b68d591ebab21c8e3dd0e8741c607f30d1de6db77a896cc45",
-"T3W1_cs_bitcoin-test_signtx_payreq.py::test_signtx_payment_req_swap_with_text_and_refund[True-True]": "52485f4e4b76144b68d591ebab21c8e3dd0e8741c607f30d1de6db77a896cc45",
+"T3W1_cs_bitcoin-test_signtx_payreq.py::test_payment_request[out0+out1]": "56b78d113a19e9c090cc38f04124f38c01143718af498c8221951aa30dc7cc15",
+"T3W1_cs_bitcoin-test_signtx_payreq.py::test_payment_request[out012]": "efff4a8575d1a1f6c73011c305827bdd584d46144e658bb19cc59e3cf5cf5f13",
+"T3W1_cs_bitcoin-test_signtx_payreq.py::test_payment_request[out01]": "f4416d00c97b19ee3b2b519f08d35d21efce933656fceda8eb50a40f2e64f10e",
+"T3W1_cs_bitcoin-test_signtx_payreq.py::test_payment_request[out0]": "9fc814c246b15a94f66a7bb82de1d5fd1fd3ec9f6357829eed342c1545dce1cc",
+"T3W1_cs_bitcoin-test_signtx_payreq.py::test_payment_request[out12]": "6496c43e85b8a881e9c3108ff1730107fb16bfbb990695b83d8d63fb08e3bfc7",
+"T3W1_cs_bitcoin-test_signtx_payreq.py::test_payment_request[out1]": "71125cf7ab98a44e8e71c2e70e3d155a3398460a0894d69f585a5e53ca630f40",
+"T3W1_cs_bitcoin-test_signtx_payreq.py::test_payment_request[out2]": "d91a59b14a8802d3c73814bae1681cd6aab2d7f5cc141fcbb99b623342e70b0c",
+"T3W1_cs_bitcoin-test_signtx_payreq.py::test_signtx_payment_req_swap_with_text_and_refund[False-False]": "76be01c761e0edc3f83d8e01f84024abdf88c1b3ad013096e9133951f34f5da0",
+"T3W1_cs_bitcoin-test_signtx_payreq.py::test_signtx_payment_req_swap_with_text_and_refund[False-True]": "76be01c761e0edc3f83d8e01f84024abdf88c1b3ad013096e9133951f34f5da0",
+"T3W1_cs_bitcoin-test_signtx_payreq.py::test_signtx_payment_req_swap_with_text_and_refund[True-False]": "1d58ecf5e85b62003dd162d25008562029fcffcd96a70fbb86c0b3ba7038d25f",
+"T3W1_cs_bitcoin-test_signtx_payreq.py::test_signtx_payment_req_swap_with_text_and_refund[True-True]": "1d58ecf5e85b62003dd162d25008562029fcffcd96a70fbb86c0b3ba7038d25f",
"T3W1_cs_bitcoin-test_signtx_prevhash.py::test_invalid_prev_hash[]": "4b3bd3170e11f2a10db73a704c809c23da90ca9c5bca95e2384abe499a44f002",
"T3W1_cs_bitcoin-test_signtx_prevhash.py::test_invalid_prev_hash[hello world]": "4b3bd3170e11f2a10db73a704c809c23da90ca9c5bca95e2384abe499a44f002",
"T3W1_cs_bitcoin-test_signtx_prevhash.py::test_invalid_prev_hash[x]": "4b3bd3170e11f2a10db73a704c809c23da90ca9c5bca95e2384abe499a44f002",
"T3W1_cs_bitcoin-test_signtx_prevhash.py::test_invalid_prev_hash[xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx]": "4b3bd3170e11f2a10db73a704c809c23da90ca9c5bca95e2384abe499a44f002",
-"T3W1_cs_bitcoin-test_signtx_prevhash.py::test_invalid_prev_hash_attack[]": "fe3e910d09e739dcd079aeb8352315427f76d3d7ba5280dbb404aa050fcac461",
-"T3W1_cs_bitcoin-test_signtx_prevhash.py::test_invalid_prev_hash_attack[hello world]": "fe3e910d09e739dcd079aeb8352315427f76d3d7ba5280dbb404aa050fcac461",
-"T3W1_cs_bitcoin-test_signtx_prevhash.py::test_invalid_prev_hash_attack[x]": "fe3e910d09e739dcd079aeb8352315427f76d3d7ba5280dbb404aa050fcac461",
-"T3W1_cs_bitcoin-test_signtx_prevhash.py::test_invalid_prev_hash_attack[xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx]": "fe3e910d09e739dcd079aeb8352315427f76d3d7ba5280dbb404aa050fcac461",
-"T3W1_cs_bitcoin-test_signtx_prevhash.py::test_invalid_prev_hash_in_prevtx[]": "68c6d1fb0ab4bcdc0fe7205a4749e16c136f9f6072c830cb4a9d4b2bf0c8ff58",
-"T3W1_cs_bitcoin-test_signtx_prevhash.py::test_invalid_prev_hash_in_prevtx[hello world]": "68c6d1fb0ab4bcdc0fe7205a4749e16c136f9f6072c830cb4a9d4b2bf0c8ff58",
-"T3W1_cs_bitcoin-test_signtx_prevhash.py::test_invalid_prev_hash_in_prevtx[x]": "68c6d1fb0ab4bcdc0fe7205a4749e16c136f9f6072c830cb4a9d4b2bf0c8ff58",
-"T3W1_cs_bitcoin-test_signtx_prevhash.py::test_invalid_prev_hash_in_prevtx[xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx]": "68c6d1fb0ab4bcdc0fe7205a4749e16c136f9f6072c830cb4a9d4b2bf0c8ff58",
+"T3W1_cs_bitcoin-test_signtx_prevhash.py::test_invalid_prev_hash_attack[]": "eda33c02c64c3c99ce7841eb2be8ad8771662146a1d48c301dc2108bb78cc7dc",
+"T3W1_cs_bitcoin-test_signtx_prevhash.py::test_invalid_prev_hash_attack[hello world]": "eda33c02c64c3c99ce7841eb2be8ad8771662146a1d48c301dc2108bb78cc7dc",
+"T3W1_cs_bitcoin-test_signtx_prevhash.py::test_invalid_prev_hash_attack[x]": "eda33c02c64c3c99ce7841eb2be8ad8771662146a1d48c301dc2108bb78cc7dc",
+"T3W1_cs_bitcoin-test_signtx_prevhash.py::test_invalid_prev_hash_attack[xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx]": "eda33c02c64c3c99ce7841eb2be8ad8771662146a1d48c301dc2108bb78cc7dc",
+"T3W1_cs_bitcoin-test_signtx_prevhash.py::test_invalid_prev_hash_in_prevtx[]": "30cfb17c709ce79d564ebff8574b38461551814f0c81cd544f717bb27f1bf374",
+"T3W1_cs_bitcoin-test_signtx_prevhash.py::test_invalid_prev_hash_in_prevtx[hello world]": "30cfb17c709ce79d564ebff8574b38461551814f0c81cd544f717bb27f1bf374",
+"T3W1_cs_bitcoin-test_signtx_prevhash.py::test_invalid_prev_hash_in_prevtx[x]": "30cfb17c709ce79d564ebff8574b38461551814f0c81cd544f717bb27f1bf374",
+"T3W1_cs_bitcoin-test_signtx_prevhash.py::test_invalid_prev_hash_in_prevtx[xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx]": "30cfb17c709ce79d564ebff8574b38461551814f0c81cd544f717bb27f1bf374",
"T3W1_cs_bitcoin-test_signtx_replacement.py::test_attack_fake_ext_input_amount": "4b3bd3170e11f2a10db73a704c809c23da90ca9c5bca95e2384abe499a44f002",
"T3W1_cs_bitcoin-test_signtx_replacement.py::test_attack_fake_int_input_amount": "4b3bd3170e11f2a10db73a704c809c23da90ca9c5bca95e2384abe499a44f002",
"T3W1_cs_bitcoin-test_signtx_replacement.py::test_attack_false_internal": "4b3bd3170e11f2a10db73a704c809c23da90ca9c5bca95e2384abe499a44f002",
@@ -28983,7 +28983,7 @@
"T3W1_cs_bitcoin-test_signtx_replacement.py::test_p2tr_fee_bump": "82ca8d393691144dead83f5ac00375d4224bb912bc7041e91e49c12f60f0b15f",
"T3W1_cs_bitcoin-test_signtx_replacement.py::test_p2tr_invalid_signature": "04f02a88e8bfa9f1ec8b5964ef838e515b6ccaa7d8f475e4a0a937cab2389b7a",
"T3W1_cs_bitcoin-test_signtx_replacement.py::test_p2wpkh_finalize": "ada519cbe8a04957b9df9b5a00b6cecc67e0dcddce72408e3eb69a5cb16e2fd4",
-"T3W1_cs_bitcoin-test_signtx_replacement.py::test_p2wpkh_in_p2sh_fee_bump_from_external": "f2baf4cf2c4f7ea195b2777ab4adaa58b8e8092b8c03a6324cefdf6241b98d45",
+"T3W1_cs_bitcoin-test_signtx_replacement.py::test_p2wpkh_in_p2sh_fee_bump_from_external": "657e800b133085c78f16ccc7464a3f7f2cd68afd5785cdd8e3d443e6e46db797",
"T3W1_cs_bitcoin-test_signtx_replacement.py::test_p2wpkh_in_p2sh_remove_change": "bd6ac66b7246139a496d27c7ad31d27181c52bb8932ef34b45db2b350b3f55e2",
"T3W1_cs_bitcoin-test_signtx_replacement.py::test_p2wpkh_invalid_signature": "b3b4b7fe081e1af77e04dd4709ed469fa18a3b6d5688175b43491ab5f0c53fc8",
"T3W1_cs_bitcoin-test_signtx_replacement.py::test_p2wpkh_op_return_fee_bump": "8f7b9a3a815ec34dd72e9028366aff32eae307ea5c798828f50f7976cc5a7cd1",
@@ -28993,33 +28993,33 @@
"T3W1_cs_bitcoin-test_signtx_replacement.py::test_p2wpkh_payjoin[19909859-89800-02483045022100af3a87-80428fad": "7a0c23561bd6e39db2f068e071a5542651479e68a25f6ee873d00d7d6710037b",
"T3W1_cs_bitcoin-test_signtx_replacement.py::test_p2wpkh_payjoin[19909859-89859-02483045022100eb74ab-881c7bef": "80c7126c8810f2d040fcb813f410518dd04560d45bb42fe329cc79b0b6ee9ec3",
"T3W1_cs_bitcoin-test_signtx_replacement.py::test_tx_meld": "76f5b3a455323434f415345b64803bad72dfe7e8ccdf8866c729694e53357ddf",
-"T3W1_cs_bitcoin-test_signtx_segwit.py::test_attack_change_input_address": "624e6b3a7c86a02797fc9529b6fffeee494652f01d16efe14a68e8593676bb13",
-"T3W1_cs_bitcoin-test_signtx_segwit.py::test_attack_mixed_inputs": "3f8378cdbf2214544854e58748e1d1e1468073cda2ee1ebb7e158f7171626eec",
-"T3W1_cs_bitcoin-test_signtx_segwit.py::test_send_multisig_1": "52c8d2d9de7d3d05311677a2574f02e900a254cf62535265d305b836ef2fdf2d",
-"T3W1_cs_bitcoin-test_signtx_segwit.py::test_send_p2sh[False]": "f478437a97ebabcf9f52c0bd64df0ff80d29aa38d1b94921135f762a6ffd8fb0",
-"T3W1_cs_bitcoin-test_signtx_segwit.py::test_send_p2sh[True]": "49a16a6375a1a741ebe4bb327e1edc13db0016cb74baff62c9c49b1b1f556ab1",
-"T3W1_cs_bitcoin-test_signtx_segwit.py::test_send_p2sh_change": "50b83a4e583b503b594c89a4c91f6f6f03b64eb7c96ad8d09f0a38094ca49149",
-"T3W1_cs_bitcoin-test_signtx_segwit.py::test_testnet_segwit_big_amount": "c18a0594d567e959972b210027d7cae05e64d5fc2508e72a92c492aabb521be9",
-"T3W1_cs_bitcoin-test_signtx_segwit_native.py::test_multisig_mismatch_inputs_single": "ccee3e9047b968dda88e39dbdfa6ae34133a530202882f36e878c06ea9030e78",
-"T3W1_cs_bitcoin-test_signtx_segwit_native.py::test_send_both": "b374879ac8ceaaaf88f22ec98e9f29e0fad22e9ae59e955728f9b5027d0649e1",
-"T3W1_cs_bitcoin-test_signtx_segwit_native.py::test_send_multisig_1": "4d22f6c4c2b5a8c36a3f0821070947e2ce8fffbf3f0ef863e1f3ca32b50e6d69",
-"T3W1_cs_bitcoin-test_signtx_segwit_native.py::test_send_multisig_2": "f3fce042327075afe889fd56f311f8efa3b9e0d3e89faf054fbb3b10e2bc32a8",
-"T3W1_cs_bitcoin-test_signtx_segwit_native.py::test_send_multisig_3_change": "bc467b871e29837d11a06477a656389181b02111d9d509f33e4dd266d352b19b",
-"T3W1_cs_bitcoin-test_signtx_segwit_native.py::test_send_multisig_4_change": "250f2f152c6d6ebe8782cb2c9ef684e189326e27c10e0e2b23491977cf09272e",
-"T3W1_cs_bitcoin-test_signtx_segwit_native.py::test_send_native": "3b8d243921c7afc3d404e2ef185f2ee6a1d50c02c0ee2a22acede697ea0742e7",
-"T3W1_cs_bitcoin-test_signtx_segwit_native.py::test_send_native_change": "edf0ac906d1706b055938df1c3555d7f49457a4cbff8997113a698aa550a2790",
-"T3W1_cs_bitcoin-test_signtx_segwit_native.py::test_send_p2sh": "d5dadabdd0fcda1a738885ff4c34c91daa44e47a38b090d6ee0ba1d2bd3a160b",
-"T3W1_cs_bitcoin-test_signtx_segwit_native.py::test_send_p2sh_change": "b4f1b11e118bccb290d08a6bebaadbce68c9edc837e4bc7df5c848b0bfa8d198",
-"T3W1_cs_bitcoin-test_signtx_segwit_native.py::test_send_to_taproot": "a49d6bfc0fbba48b62e402b9292e76f4b306baf26ca836b03bfe71830a126ec7",
-"T3W1_cs_bitcoin-test_signtx_taproot.py::test_attack_script_type": "dece81136b9881e166468d432971db80e95817406e701bd3ce0adfbe2a6c1492",
+"T3W1_cs_bitcoin-test_signtx_segwit.py::test_attack_change_input_address": "eec6b80e8a0b8c14de8bc2487e2265e135f1d586a915b67144e9408992a00a0c",
+"T3W1_cs_bitcoin-test_signtx_segwit.py::test_attack_mixed_inputs": "d0548559339a084840787bfdc53c4709547a1f170f3224efab1f12aa41246d97",
+"T3W1_cs_bitcoin-test_signtx_segwit.py::test_send_multisig_1": "db3ab9b3db04b9129e8d1bbce96180596b158ed4e72b03c38385cd60e2823926",
+"T3W1_cs_bitcoin-test_signtx_segwit.py::test_send_p2sh[False]": "ee1f5c596e94f83bee4e856be4a0b2eb8c88fe1cbc581e16fbfe1da2b123e4ce",
+"T3W1_cs_bitcoin-test_signtx_segwit.py::test_send_p2sh[True]": "4f06df91e7abd449de0d1500d365d608cebdee2431f8dc22d201a3bca81c20ff",
+"T3W1_cs_bitcoin-test_signtx_segwit.py::test_send_p2sh_change": "e31c2e731e10e434522a668a55d55b8d8658f04d43758b922260aec80683b06c",
+"T3W1_cs_bitcoin-test_signtx_segwit.py::test_testnet_segwit_big_amount": "5d24614b20e71c6779d3d68134bf45e7c3e0a0ca921193baa581455227f53925",
+"T3W1_cs_bitcoin-test_signtx_segwit_native.py::test_multisig_mismatch_inputs_single": "c849e00b483f6a951e5984019721f668afd0a4c00662e2475d9ca86915a8e9a6",
+"T3W1_cs_bitcoin-test_signtx_segwit_native.py::test_send_both": "3c18afa8c48df566dcc7843f47cbcc12562e1a3d09c823116970f1765a6024ff",
+"T3W1_cs_bitcoin-test_signtx_segwit_native.py::test_send_multisig_1": "92b5275c49cb4a6ee43bfb10719fefcdcec111a1c07f28c2c87d7d16d005cefc",
+"T3W1_cs_bitcoin-test_signtx_segwit_native.py::test_send_multisig_2": "b712f84d5f29ace4ec5697d6133956619f126ae6d879ddc17b335b5765674230",
+"T3W1_cs_bitcoin-test_signtx_segwit_native.py::test_send_multisig_3_change": "1fe3812b4733fe03310936ce5aab6249f520af1c5aa147ef150219dca2cc1465",
+"T3W1_cs_bitcoin-test_signtx_segwit_native.py::test_send_multisig_4_change": "ed68db43ef57532df77b009b9558e5764e62140893bd9aa4f99f3b40e387a823",
+"T3W1_cs_bitcoin-test_signtx_segwit_native.py::test_send_native": "862ca46cd89222597f6858747dec8f4e5fb1612c8bc3e920f4c87f5b3a873411",
+"T3W1_cs_bitcoin-test_signtx_segwit_native.py::test_send_native_change": "aea5b144317a1e4f2abe39697b9543893c2e5f463d9d61d7141f3c6cb79ca746",
+"T3W1_cs_bitcoin-test_signtx_segwit_native.py::test_send_p2sh": "3d53dab7ad9c8afa3eb2bbe143c56aeeb4ffc08dd445e9e0442645c94643c5c4",
+"T3W1_cs_bitcoin-test_signtx_segwit_native.py::test_send_p2sh_change": "de853c1a5a72f8c6bb74d572f73f2f4eb9ec560664351aaa6bd3ec8d2c3eecfa",
+"T3W1_cs_bitcoin-test_signtx_segwit_native.py::test_send_to_taproot": "a6891041730a217166212782a55566032ec5ae61b642f5e6863ce2da63176eb2",
+"T3W1_cs_bitcoin-test_signtx_taproot.py::test_attack_script_type": "2b4d7f88c4405d484578cb0c42983b7f0bedf91b2d7ac6b998d814965e569e20",
"T3W1_cs_bitcoin-test_signtx_taproot.py::test_send_invalid_address[tb1pam775nxmvam4pfpqlm5q06k0y84e3-a257be51": "4b3bd3170e11f2a10db73a704c809c23da90ca9c5bca95e2384abe499a44f002",
"T3W1_cs_bitcoin-test_signtx_taproot.py::test_send_invalid_address[tb1plllllllllllllllllllllllllllll-aaa668e3": "4b3bd3170e11f2a10db73a704c809c23da90ca9c5bca95e2384abe499a44f002",
"T3W1_cs_bitcoin-test_signtx_taproot.py::test_send_invalid_address[tb1plycg5qvjtrp3qjf5f7zl382j9x6nr-5447628e": "4b3bd3170e11f2a10db73a704c809c23da90ca9c5bca95e2384abe499a44f002",
"T3W1_cs_bitcoin-test_signtx_taproot.py::test_send_invalid_address[tb1zlycg5qvjtrp3qjf5f7zl382j9x6nr-880d4a6b": "4b3bd3170e11f2a10db73a704c809c23da90ca9c5bca95e2384abe499a44f002",
-"T3W1_cs_bitcoin-test_signtx_taproot.py::test_send_mixed": "92a291df53658e944a00cb687fc7141af5715e8c7ad85a2c0fa1d25cc52b66ff",
-"T3W1_cs_bitcoin-test_signtx_taproot.py::test_send_p2tr[False]": "56944e3019bf23ac593234fb0c02cc78c8197312e67f291f88ea4567901e2718",
-"T3W1_cs_bitcoin-test_signtx_taproot.py::test_send_p2tr[True]": "f3d042941c46f51f0fe4b4c60838c1b7e0b1342f2d207b22e4bcb585a3627642",
-"T3W1_cs_bitcoin-test_signtx_taproot.py::test_send_two_with_change": "f6a8fcf4bc5b0981fef906cfa029765dac9df2bf506a6b3f16b41894beb1c7da",
+"T3W1_cs_bitcoin-test_signtx_taproot.py::test_send_mixed": "c8451b4d1cb7499312c6c58cac7acfc5f937effbc94c4f4dab8eb1375f566d93",
+"T3W1_cs_bitcoin-test_signtx_taproot.py::test_send_p2tr[False]": "3e6c50a92ca4e18cc9d2ffd489c8bd637a68256703ff8145d07033b8ff407adb",
+"T3W1_cs_bitcoin-test_signtx_taproot.py::test_send_p2tr[True]": "018bfc47b7bc316162f4c3c9ff3b96edba48102d027be78c1ac12cdc8d8c1811",
+"T3W1_cs_bitcoin-test_signtx_taproot.py::test_send_two_with_change": "1bc97f6eab37adaad26faa19298ed10e281514c8a804335c34891272afa6b5fc",
"T3W1_cs_bitcoin-test_verifymessage.py::test_message_grs": "54623cc6f39c2cae2f44fffe5ec22ff3ff6073ffb2e96df8a3fa557c16a8c229",
"T3W1_cs_bitcoin-test_verifymessage.py::test_message_long_core": "0e1628f0112136307193bb8d06596d148771247ad210f1f9450972b2144c9d95",
"T3W1_cs_bitcoin-test_verifymessage.py::test_message_testnet": "1001ba1b6b98d26cd703d2d5d4273ef78277dff5e70da858d8f25ef3a46d6fe5",
@@ -29035,91 +29035,91 @@
"T3W1_cs_bitcoin-test_verifymessage_segwit_native.py::test_message_testnet": "7d2016131de41879fded1f5339aac041c03cb11b89429c18556b706b8efad2c5",
"T3W1_cs_bitcoin-test_verifymessage_segwit_native.py::test_message_verify": "aa5adb78d07cf901b74e4d078e014c8218f2fa0fc5b861db4db9059d4724c1c7",
"T3W1_cs_bitcoin-test_verifymessage_segwit_native.py::test_verify_utf": "9e74f5c98ee38273b1d0efed4b666d39b2bff62c9ff57216c274f6fbee5a7943",
-"T3W1_cs_bitcoin-test_zcash.py::test_external_presigned": "2d2556bd5508a18b1c7d9f36fe07c8c437248a9e660e292fdb7a23c9fc62aa96",
-"T3W1_cs_bitcoin-test_zcash.py::test_one_one_fee_sapling": "c91e3d88a5cf2b9dd6d36ce67919b115b30728a9a8d7e6fb47e7693bf4b41741",
-"T3W1_cs_bitcoin-test_zcash.py::test_spend_old_versions": "66bd90fb340427849641d501439f377564466cb90b3a4b97bf9a2b17128e718b",
+"T3W1_cs_bitcoin-test_zcash.py::test_external_presigned": "cb0b0420447e89ad9af7d4a9623755c65327b3170a200f627a0bdc35c1f8a808",
+"T3W1_cs_bitcoin-test_zcash.py::test_one_one_fee_sapling": "dbe9f53bee000a2165f9c62af961860e92681ae55353022dfa4d0ae7a131fe2e",
+"T3W1_cs_bitcoin-test_zcash.py::test_spend_old_versions": "427512df5d1669b85ea6402221eb3c0fd834ce2da9aa01352fb17f45a68234db",
"T3W1_cs_bitcoin-test_zcash.py::test_v3_not_supported": "535037bfe5f1459cfdf305915835d8bf2a9a427c3f60264a8cc3ca6f306a61b1",
"T3W1_cs_bitcoin-test_zcash.py::test_version_group_id_missing": "535037bfe5f1459cfdf305915835d8bf2a9a427c3f60264a8cc3ca6f306a61b1",
"T3W1_cs_cardano-test_address_public_key.py::test_cardano_get_address[False-icarus-derivation]": "bfac0b96f15a78e3016ca81ec1b7e8c08c0fb3a8c75495e753243765ff75243d",
"T3W1_cs_cardano-test_address_public_key.py::test_cardano_get_address[False-icarus-trezor-derivation]": "ce8c8b6a4b01928b7b5e67f260cfe1505b704a2692918b02d0e086c1f42efe2a",
"T3W1_cs_cardano-test_address_public_key.py::test_cardano_get_address[False-ledger-derivation]": "c737501b45c416bccb369b5c03be728225911a2b0c84835d28cafc925abe8fd8",
-"T3W1_cs_cardano-test_address_public_key.py::test_cardano_get_address[False-parameters0-result0]": "427398b43a18cde99c88d5efce78da7e0a7540d513911e012abc863d664f771d",
-"T3W1_cs_cardano-test_address_public_key.py::test_cardano_get_address[False-parameters1-result1]": "280368c37bbe24cecf0eb28c0842c3de8fb7ebe18a14bb87a8a4af76896699d7",
-"T3W1_cs_cardano-test_address_public_key.py::test_cardano_get_address[False-parameters10-result10]": "c59aa7914a406f4e97f4ae1090f7953acbbadf380c64566f86bca3b73935495b",
-"T3W1_cs_cardano-test_address_public_key.py::test_cardano_get_address[False-parameters11-result11]": "e0830252a2a14369f30f556b92916f48b925c2adfc0ae4a0d4769d96131124f1",
+"T3W1_cs_cardano-test_address_public_key.py::test_cardano_get_address[False-parameters0-result0]": "24a817b6d329e2cea082324cd2d8b821589ec2c5189b286091ab9a3294e2314b",
+"T3W1_cs_cardano-test_address_public_key.py::test_cardano_get_address[False-parameters1-result1]": "847a120833a0a3f4fe44af008cdd46788ce4d378273954f0045688d155fe8c8a",
+"T3W1_cs_cardano-test_address_public_key.py::test_cardano_get_address[False-parameters10-result10]": "7de7ff25beeae08b8a0c80cc1a67fc3a2a7748a16d00d8bed28c59d399dbb237",
+"T3W1_cs_cardano-test_address_public_key.py::test_cardano_get_address[False-parameters11-result11]": "c966de2e5ad3b710f32209b93592fce54aef89d739b53c635d8d46feec87bd7a",
"T3W1_cs_cardano-test_address_public_key.py::test_cardano_get_address[False-parameters12-result12]": "e7a80c506c49fe95076c2db73b3f8b2e02c4384dc6c2a56a270e036a232a7f69",
"T3W1_cs_cardano-test_address_public_key.py::test_cardano_get_address[False-parameters13-result13]": "2af9bc4700d10beba6823f8af1993c8f21eea06e7a460532b0bb41fbae6a4d87",
-"T3W1_cs_cardano-test_address_public_key.py::test_cardano_get_address[False-parameters14-result14]": "09f25858d9bb91b0e037d94bab0b99dbe2701f6f389ba25a113f702c093da95d",
-"T3W1_cs_cardano-test_address_public_key.py::test_cardano_get_address[False-parameters15-result15]": "216956add199bfd262e01ce9287766bb2538db0c7294fa029db091f8693fbfab",
-"T3W1_cs_cardano-test_address_public_key.py::test_cardano_get_address[False-parameters16-result16]": "80a57b2a5f05a4c017ae6fcc09dc4f50f2992e04b9fb3643e20eae7438ab8f42",
-"T3W1_cs_cardano-test_address_public_key.py::test_cardano_get_address[False-parameters17-result17]": "08ee150022fd305c92a373e616772f73b10a80e873b3a37895236eff0af1ae36",
-"T3W1_cs_cardano-test_address_public_key.py::test_cardano_get_address[False-parameters18-result18]": "59b6fcb936a0a512a29b85d003034fd58d6b442bbce16d7c008624c5baecc834",
-"T3W1_cs_cardano-test_address_public_key.py::test_cardano_get_address[False-parameters19-result19]": "1f1106533ce9a1460b7faece7d7f5837049ac9220c79ed2928f9d09721af63c8",
-"T3W1_cs_cardano-test_address_public_key.py::test_cardano_get_address[False-parameters2-result2]": "76ba64b43cf032ee900e0e0dadee487f3b9a65c8de8e940ddd6d48c293083700",
-"T3W1_cs_cardano-test_address_public_key.py::test_cardano_get_address[False-parameters20-result20]": "f12349325d5981be8aac8b0104f1fdf465b23622719eed22b65731f104844230",
-"T3W1_cs_cardano-test_address_public_key.py::test_cardano_get_address[False-parameters21-result21]": "575f6c604a4ee3a05fff919add663fd182b31a07493cff1f81d6c5d6e9cd7f6e",
-"T3W1_cs_cardano-test_address_public_key.py::test_cardano_get_address[False-parameters22-result22]": "7053e5f6b47b808654161ab20b5c1ce72d0defc60b40e4addf814b646576770a",
-"T3W1_cs_cardano-test_address_public_key.py::test_cardano_get_address[False-parameters23-result23]": "90492ddc4e14b027eefd6f18dce7918000d38dcdb5c81907d0d0351dce8361fa",
-"T3W1_cs_cardano-test_address_public_key.py::test_cardano_get_address[False-parameters24-result24]": "b0dd2909408c3278fc1c24b6b0770b30241c421a7e1f6d5ba280f1f3b90adf2b",
-"T3W1_cs_cardano-test_address_public_key.py::test_cardano_get_address[False-parameters25-result25]": "fec9db615dafd48a97c2f8b57b84d0156ad2342ca9c59b9a64746078040b48d9",
-"T3W1_cs_cardano-test_address_public_key.py::test_cardano_get_address[False-parameters26-result26]": "d2e807a4c73c8e78c411584e9d9bc9b7f9b0de85015807aaad4214997dd3c031",
-"T3W1_cs_cardano-test_address_public_key.py::test_cardano_get_address[False-parameters27-result27]": "1de3b19af14fa6d60a73994090ac129ba89f8842e08f777c7a8667febabb4c31",
-"T3W1_cs_cardano-test_address_public_key.py::test_cardano_get_address[False-parameters28-result28]": "70a59d18d6342a746eb9a4a5875e0a1d83bf06301e43f5563f84e9b9a8c2330a",
-"T3W1_cs_cardano-test_address_public_key.py::test_cardano_get_address[False-parameters29-result29]": "1deb5f6db1f0b59deb2438b78a9f66f3a41e8b34a6372df897f27302023353b4",
-"T3W1_cs_cardano-test_address_public_key.py::test_cardano_get_address[False-parameters3-result3]": "1e61e535c8b8ca932119cda4516d4097a8b0a7491fb63108a6885cdf097c5da3",
-"T3W1_cs_cardano-test_address_public_key.py::test_cardano_get_address[False-parameters30-result30]": "35e56ed088544da29efb8c5519e3a3b50c6dc25da6f44eb5cc4807ae26cf94b4",
-"T3W1_cs_cardano-test_address_public_key.py::test_cardano_get_address[False-parameters31-result31]": "ded6ae5cb7f90d6166a6b571fd9d7141868e8078b05fa968db1bf7ea7a5c5134",
-"T3W1_cs_cardano-test_address_public_key.py::test_cardano_get_address[False-parameters32-result32]": "e5569543af5fc3f83a51cfa0b6c2364daf52074fb916004f18fb3e401f973a04",
-"T3W1_cs_cardano-test_address_public_key.py::test_cardano_get_address[False-parameters33-result33]": "5a61df02fa3484d5c41c49dd661e7af6ad8a4f1b240df4ab545d99fc65238778",
-"T3W1_cs_cardano-test_address_public_key.py::test_cardano_get_address[False-parameters34-result34]": "f501b4cfb75f04eadcbdf1997edfbfeb015f9479a3094d2e53255d4111f26d85",
-"T3W1_cs_cardano-test_address_public_key.py::test_cardano_get_address[False-parameters35-result35]": "5a54d9005728e51e0046daeb4ca04f84dd1aad49850f6651ff1a0d42b4e1e504",
-"T3W1_cs_cardano-test_address_public_key.py::test_cardano_get_address[False-parameters36-result36]": "796830d142289924bc069aa7ebe87fd768a05e6046f43855150879a868ee24ad",
-"T3W1_cs_cardano-test_address_public_key.py::test_cardano_get_address[False-parameters4-result4]": "3a17168b1dfb5c46574b0bc897e246dea15d6e12182b3179bd8bd17ba6a240bb",
-"T3W1_cs_cardano-test_address_public_key.py::test_cardano_get_address[False-parameters5-result5]": "014301d26e707d24aabfbd733fca66946e70ba8af230aa20061aecaaea32f87f",
-"T3W1_cs_cardano-test_address_public_key.py::test_cardano_get_address[False-parameters6-result6]": "1a2e6c6b0e02bcdc362f22c2b2d634a55bb881f9f6c6b2b90e707d8819c2f054",
-"T3W1_cs_cardano-test_address_public_key.py::test_cardano_get_address[False-parameters7-result7]": "de575f871aef63733aed29d5f3b143f5a1e1b227d6c02cf409cde34700318064",
-"T3W1_cs_cardano-test_address_public_key.py::test_cardano_get_address[False-parameters8-result8]": "620a997b2894e1d3d7b650937765f874adf1b30be53a65bf552e9045ca2a9380",
-"T3W1_cs_cardano-test_address_public_key.py::test_cardano_get_address[False-parameters9-result9]": "4c1c14716b2030e7c88f4f61104013818ae69965516c56e974777fa42c0fa354",
+"T3W1_cs_cardano-test_address_public_key.py::test_cardano_get_address[False-parameters14-result14]": "86d1e481eb1ac9198778badc89f7ab29ac46dae964076caf87c6ac1e48fa8344",
+"T3W1_cs_cardano-test_address_public_key.py::test_cardano_get_address[False-parameters15-result15]": "75447be648aae228c091b316a70c9f1229d795679b63aa1c46954ea4b4c1084f",
+"T3W1_cs_cardano-test_address_public_key.py::test_cardano_get_address[False-parameters16-result16]": "452b6a131cf97c1da34c781f6d606f9a54574a2b485cdb062726696f46547197",
+"T3W1_cs_cardano-test_address_public_key.py::test_cardano_get_address[False-parameters17-result17]": "a0f552c5275cf4036517323bc0f611881c83cdfb6c69473342e1ebf1fddf9ab0",
+"T3W1_cs_cardano-test_address_public_key.py::test_cardano_get_address[False-parameters18-result18]": "41df1f1b448e9d6d7411df3c754e655a0da3478804d27c63cea141e35db473b6",
+"T3W1_cs_cardano-test_address_public_key.py::test_cardano_get_address[False-parameters19-result19]": "267a8d925141b4646275ed1425c8ff207dcf4bfc97a9ae6e287f598bdd547907",
+"T3W1_cs_cardano-test_address_public_key.py::test_cardano_get_address[False-parameters2-result2]": "a97bed737ed58580121e3cb078710085fe6c9bfa40a10a2fe38c99c3047b7a82",
+"T3W1_cs_cardano-test_address_public_key.py::test_cardano_get_address[False-parameters20-result20]": "ebb275760830a09fa0a1df41e2651fd1064ee5fc50e6fcb088a9341d23fb1cf6",
+"T3W1_cs_cardano-test_address_public_key.py::test_cardano_get_address[False-parameters21-result21]": "f5198fe39ba12c390a9bd26cd495342bf0dc91317b350241b5a3ee5366c9ffc8",
+"T3W1_cs_cardano-test_address_public_key.py::test_cardano_get_address[False-parameters22-result22]": "319fef870dee4667b5ae346be74290bcfa245884523446c751820d9133a74d18",
+"T3W1_cs_cardano-test_address_public_key.py::test_cardano_get_address[False-parameters23-result23]": "1b8bb6ecd02e3f53bdfebe97f68b16b5eaf035a10644895adffcc576cfdf6a8c",
+"T3W1_cs_cardano-test_address_public_key.py::test_cardano_get_address[False-parameters24-result24]": "cd1810bad7b235abba7e6b80363069fbc33f9cdb516e06033757d6db13d80220",
+"T3W1_cs_cardano-test_address_public_key.py::test_cardano_get_address[False-parameters25-result25]": "d300b484865bdf122370e66077377911c3aea5157d6db863948c266ddd6705af",
+"T3W1_cs_cardano-test_address_public_key.py::test_cardano_get_address[False-parameters26-result26]": "0e0bfd33527077a9380e9f39ff06a9e7a5cbf5448bf26bb5b1602f3670cfd8aa",
+"T3W1_cs_cardano-test_address_public_key.py::test_cardano_get_address[False-parameters27-result27]": "ec3e5c9a50e9f74bfc0f1cd7d0b01a104c0e773638e3b65659ac355f3adbf44c",
+"T3W1_cs_cardano-test_address_public_key.py::test_cardano_get_address[False-parameters28-result28]": "a3ced200fae128148312b1b3e7b62ede170afcc5041e27cb9a37455a87efbd4e",
+"T3W1_cs_cardano-test_address_public_key.py::test_cardano_get_address[False-parameters29-result29]": "d1471c3a7fda4f4fd3d14d4b73ab7079af75bdf3f51a6389ec6fe621a7505a35",
+"T3W1_cs_cardano-test_address_public_key.py::test_cardano_get_address[False-parameters3-result3]": "2772d5483976a5511d125059932b4f8b8fd8904a25dc67bd1aa2968364cb0cc7",
+"T3W1_cs_cardano-test_address_public_key.py::test_cardano_get_address[False-parameters30-result30]": "5e0a5072b88e9f86531c53d19207a80c3c17b0a9e335c62d78e0f033f26c87ec",
+"T3W1_cs_cardano-test_address_public_key.py::test_cardano_get_address[False-parameters31-result31]": "f6a10eb505a13b8a7928295bb19f919a0e548b53aa0f833bcd9380aed75e7a1f",
+"T3W1_cs_cardano-test_address_public_key.py::test_cardano_get_address[False-parameters32-result32]": "88862e660613153534592952ed74974bfd3837d599fc0a5c50c073c68361bf45",
+"T3W1_cs_cardano-test_address_public_key.py::test_cardano_get_address[False-parameters33-result33]": "558b28bbe935dc054ec506f7ee1d1cf11ec832c7b12d8c9df9ba5cbdc8dd1e58",
+"T3W1_cs_cardano-test_address_public_key.py::test_cardano_get_address[False-parameters34-result34]": "8d53ffc56dfdc7dffb8f8d94efcb94b40dc01ecff53817891fec9f6d07303993",
+"T3W1_cs_cardano-test_address_public_key.py::test_cardano_get_address[False-parameters35-result35]": "649e0f4eef6a14909044352e615a2585d1b434d63babad33db2d375eafadc05e",
+"T3W1_cs_cardano-test_address_public_key.py::test_cardano_get_address[False-parameters36-result36]": "c59b87bfc00cdd24f4d8887ad18417244a65e5e20e29a0c335bf9472ed7d213d",
+"T3W1_cs_cardano-test_address_public_key.py::test_cardano_get_address[False-parameters4-result4]": "9c4946495eac88b26f09f82406b13b07aed604769aae10a7d0f75154d45fc81d",
+"T3W1_cs_cardano-test_address_public_key.py::test_cardano_get_address[False-parameters5-result5]": "833a7708672f3515e7c8930292ca37bf6cce32532fe6b838258c1c3afa4dbf07",
+"T3W1_cs_cardano-test_address_public_key.py::test_cardano_get_address[False-parameters6-result6]": "29d74891ec3736701e03939d4b0398622b1df0c8963872f0a7573002984a768a",
+"T3W1_cs_cardano-test_address_public_key.py::test_cardano_get_address[False-parameters7-result7]": "fff3aa2869d3093e2cbcecd4623369c983c0260d7946cc47b133e9f730b34424",
+"T3W1_cs_cardano-test_address_public_key.py::test_cardano_get_address[False-parameters8-result8]": "13819d0bb1c7f352ac606824cde5d92fb9bf75274125ebf6b172c17acefe4725",
+"T3W1_cs_cardano-test_address_public_key.py::test_cardano_get_address[False-parameters9-result9]": "a836223f3682389cb2a0543698bc45fb56b58fe3336b8a12179e4a02845d1806",
"T3W1_cs_cardano-test_address_public_key.py::test_cardano_get_address[True-icarus-derivation]": "3c73413e21e09617095f3e26b337f3b50092b33c5f07ccfce0fcdfecc17ec07e",
"T3W1_cs_cardano-test_address_public_key.py::test_cardano_get_address[True-icarus-trezor-derivation]": "802a5241264370f6f6e2233a1339f7c2380c749d8a6a20224e6880615b3ff71b",
"T3W1_cs_cardano-test_address_public_key.py::test_cardano_get_address[True-ledger-derivation]": "a20815b196b9d7dbd1780004878549c3b592a92957a9c636c06ea8088469cc39",
-"T3W1_cs_cardano-test_address_public_key.py::test_cardano_get_address[True-parameters0-result0]": "cc677e9ed9bab2191880dca8993489bfa9f2e4ceb9f1e59bbe81ec560220f5a1",
-"T3W1_cs_cardano-test_address_public_key.py::test_cardano_get_address[True-parameters1-result1]": "df7b1747caad642d04998f49d0d68e16053215a83ed5bf3b3b521b38639cb41f",
-"T3W1_cs_cardano-test_address_public_key.py::test_cardano_get_address[True-parameters10-result10]": "31b6cac7d77fa86b6d64d8bbf29062e1972caec61bbd3e4cfbc35b6f38e5e685",
-"T3W1_cs_cardano-test_address_public_key.py::test_cardano_get_address[True-parameters11-result11]": "ab36aba860b7e62354a738123d6ab82c04f97c73140c6ebb9644c592c7cda27c",
+"T3W1_cs_cardano-test_address_public_key.py::test_cardano_get_address[True-parameters0-result0]": "820d6dc94bc2931eb78c4987586ce2a45e61941180752898cdffc445e726a3e3",
+"T3W1_cs_cardano-test_address_public_key.py::test_cardano_get_address[True-parameters1-result1]": "53371ee30d10be955e5d3db40dc78f0dc20ae94ec4a47fbd368ec6b81b7b29a3",
+"T3W1_cs_cardano-test_address_public_key.py::test_cardano_get_address[True-parameters10-result10]": "d0e3ea0487035f0a6bcd04a71f5f7e84a50cba0fd2b77d6d4cc8371ea218c77f",
+"T3W1_cs_cardano-test_address_public_key.py::test_cardano_get_address[True-parameters11-result11]": "4e540254b51edd3b4ccbe137642fcbb64ac38b59c0f9fb0ec5f440eaf5601072",
"T3W1_cs_cardano-test_address_public_key.py::test_cardano_get_address[True-parameters12-result12]": "cc622866dbf31782558306bf5d82d3db4e54a0099b150daa20371d759eddd0bf",
"T3W1_cs_cardano-test_address_public_key.py::test_cardano_get_address[True-parameters13-result13]": "c233199a417ffef2bd026f16753c3189c4de00d26b4106af3e064b2645ff137d",
-"T3W1_cs_cardano-test_address_public_key.py::test_cardano_get_address[True-parameters14-result14]": "ac5d6119d9ca04736743c51850a72136f6a551a2fed30a4eded805de476b44c7",
-"T3W1_cs_cardano-test_address_public_key.py::test_cardano_get_address[True-parameters15-result15]": "1d8184bd506f626a756430db616dc839adce25e97f05441b395a30e2578ed07d",
-"T3W1_cs_cardano-test_address_public_key.py::test_cardano_get_address[True-parameters16-result16]": "2a94638447976e8f511ca0fd1f2234070877d3e4372688703b8aca4c39deaeb7",
-"T3W1_cs_cardano-test_address_public_key.py::test_cardano_get_address[True-parameters17-result17]": "3cb66df0ea11a8befcaac5c1658d2776dd068d6f7e9a116a6069c9a76a2feb84",
-"T3W1_cs_cardano-test_address_public_key.py::test_cardano_get_address[True-parameters18-result18]": "91335b687ad818a9fd82798f600a929dcd1ba455568143465bb864e9e3919400",
-"T3W1_cs_cardano-test_address_public_key.py::test_cardano_get_address[True-parameters19-result19]": "a471658affa3cc576a4d93c0dd10aa5dce7ced4d0da0dc8cd67f97cad1585aa0",
-"T3W1_cs_cardano-test_address_public_key.py::test_cardano_get_address[True-parameters2-result2]": "1e67399868f1c0f9e32ad0a0747e05c34c82310360ba5d55a7b5126a08147cee",
-"T3W1_cs_cardano-test_address_public_key.py::test_cardano_get_address[True-parameters20-result20]": "b48de380c3a540da2bc564e11713172d37a047c58aeb382a28cfb97e02b514c0",
-"T3W1_cs_cardano-test_address_public_key.py::test_cardano_get_address[True-parameters21-result21]": "a585d87951c8dfb08fdfa60d4acc92db0898dbc0196fa5397ab8fda82b85b15a",
-"T3W1_cs_cardano-test_address_public_key.py::test_cardano_get_address[True-parameters22-result22]": "00744e0c3046ee3abe1d224f076f39e53348493759f329511876e1409482ae46",
-"T3W1_cs_cardano-test_address_public_key.py::test_cardano_get_address[True-parameters23-result23]": "d34b02f7e9cd0c7f69d0e0417da739a33551d6c0895ee9b1dcd4a0aeb0b114b1",
-"T3W1_cs_cardano-test_address_public_key.py::test_cardano_get_address[True-parameters24-result24]": "8305648e5e399afe3e9a945248b42642c620d3d7430827c336171062dad90970",
-"T3W1_cs_cardano-test_address_public_key.py::test_cardano_get_address[True-parameters25-result25]": "e4e0d50daf8afa53e6e3c67e5e37c893691830dbf2c99396ee0706a7917aee2c",
-"T3W1_cs_cardano-test_address_public_key.py::test_cardano_get_address[True-parameters26-result26]": "57721df24d10f33a156011fd906037c605c4503b929cf9c7c00c04196e05461b",
-"T3W1_cs_cardano-test_address_public_key.py::test_cardano_get_address[True-parameters27-result27]": "a29932a3d6d98905249c776cef74435a77a8d2c3def5f6a6f74f79ecba566ecb",
-"T3W1_cs_cardano-test_address_public_key.py::test_cardano_get_address[True-parameters28-result28]": "9ddd72aea7da4ffe1f58ca95f9c558bb790df5c157a1452eaa3d79ea1e8073c1",
-"T3W1_cs_cardano-test_address_public_key.py::test_cardano_get_address[True-parameters29-result29]": "deed6d86d5be17d5a6af9e4e53885faa1ef505a2150acef269d257a213b9f7b8",
-"T3W1_cs_cardano-test_address_public_key.py::test_cardano_get_address[True-parameters3-result3]": "1d8dc3397bed3dec12f302477abf9091c9a36ed6a081db261f0c6079f538448d",
-"T3W1_cs_cardano-test_address_public_key.py::test_cardano_get_address[True-parameters30-result30]": "c3fc12af356f100be8226ac647ffa7e56cf483f015d98c2740d33c211650a035",
-"T3W1_cs_cardano-test_address_public_key.py::test_cardano_get_address[True-parameters31-result31]": "44fde4e45d8602a777e4a54a8053ead66b460b7067b0ca311e33d2933d9ebad1",
-"T3W1_cs_cardano-test_address_public_key.py::test_cardano_get_address[True-parameters32-result32]": "81eed35af1ff08a3aea2241d3b9f4479589c920582cb314479f4e02de8e91a24",
-"T3W1_cs_cardano-test_address_public_key.py::test_cardano_get_address[True-parameters33-result33]": "cd8e7a9562727dd28f7e727664a49e877c645d235312fc4b6ae94c066a3249d1",
-"T3W1_cs_cardano-test_address_public_key.py::test_cardano_get_address[True-parameters34-result34]": "b69a2c27b5319eaddefe0079cda63aa55a8690fec2994017ff6491dd246a08a7",
-"T3W1_cs_cardano-test_address_public_key.py::test_cardano_get_address[True-parameters35-result35]": "7c6e13cc1a8a76e243b269da2abad3e10801f1efe73654f0dd44f0d7e935bf1a",
-"T3W1_cs_cardano-test_address_public_key.py::test_cardano_get_address[True-parameters36-result36]": "a8062b6e6cf3571fb89148c770b3e6adf4dfb41b320fa27e91492d68bf280380",
-"T3W1_cs_cardano-test_address_public_key.py::test_cardano_get_address[True-parameters4-result4]": "d301aa9446415d3e6087b286eb13788753a4a073fba9829ef9a0c75f4141bbe6",
-"T3W1_cs_cardano-test_address_public_key.py::test_cardano_get_address[True-parameters5-result5]": "a7dae4e04aff934da887e93e82255ca2caa8e69adf2035ab9c8ecfe1af430e39",
-"T3W1_cs_cardano-test_address_public_key.py::test_cardano_get_address[True-parameters6-result6]": "ab11d83544fda95166794e11a75c649fbc2e4509a2f332cc029dec9a17d7b51e",
-"T3W1_cs_cardano-test_address_public_key.py::test_cardano_get_address[True-parameters7-result7]": "f9fe4d46ba758995b48a6a29f198063b4ced3d5a51511a88414309512c61513f",
-"T3W1_cs_cardano-test_address_public_key.py::test_cardano_get_address[True-parameters8-result8]": "c774f6af157e9e5bce59648665a9f969aa2b5286a84c7db1927c644f805ed48c",
-"T3W1_cs_cardano-test_address_public_key.py::test_cardano_get_address[True-parameters9-result9]": "b975e6a02d029db22ee2029f490801dd04e32e3d6b1c9276d8956f04ba776733",
+"T3W1_cs_cardano-test_address_public_key.py::test_cardano_get_address[True-parameters14-result14]": "32d0b967d6a5880f857f72bcb4a7f5da0ec15c1621d1935d26c4e08fbeb641aa",
+"T3W1_cs_cardano-test_address_public_key.py::test_cardano_get_address[True-parameters15-result15]": "6b469f654005a2f9f4586cb64a02776fc630b63e542bbdac09900c80bc6e33e0",
+"T3W1_cs_cardano-test_address_public_key.py::test_cardano_get_address[True-parameters16-result16]": "040fa666d92196eef3b3020b5f9f048dca40c5f32f4cc0503741d8038ddf0fad",
+"T3W1_cs_cardano-test_address_public_key.py::test_cardano_get_address[True-parameters17-result17]": "5ed4d405c0eb0ce9a8f18c03934d87cbd6cca4d1584cb71db1bc445f10651d0f",
+"T3W1_cs_cardano-test_address_public_key.py::test_cardano_get_address[True-parameters18-result18]": "79c72c8871a709edb099d668bc93435e0f32ab696b23abafa1260c1781752e0f",
+"T3W1_cs_cardano-test_address_public_key.py::test_cardano_get_address[True-parameters19-result19]": "daff56b4ccd082a147b21e5fd7b5603e7405a83aa5966af633fa5d616c095a15",
+"T3W1_cs_cardano-test_address_public_key.py::test_cardano_get_address[True-parameters2-result2]": "909466538a9b3a8f04d6fe1da45d7043583934ab2b11d1c41e0959f80d942345",
+"T3W1_cs_cardano-test_address_public_key.py::test_cardano_get_address[True-parameters20-result20]": "6b55ee29d1c8fab07949a42103dc83ad54d6550ea4d7def0dea6109f02407d15",
+"T3W1_cs_cardano-test_address_public_key.py::test_cardano_get_address[True-parameters21-result21]": "10e0831b95f1c1b2e68c1e461546779eac828fa37c1a48aa0d2d94d669da8464",
+"T3W1_cs_cardano-test_address_public_key.py::test_cardano_get_address[True-parameters22-result22]": "59ed316c596fceb5bde00d32fa960ccf89d90083f2a96cc55e25ac97dd4d7b4b",
+"T3W1_cs_cardano-test_address_public_key.py::test_cardano_get_address[True-parameters23-result23]": "b262347ff4676f15fbf5910997d83eef0b09e2f25b6d2b410f5dd8ef1657714f",
+"T3W1_cs_cardano-test_address_public_key.py::test_cardano_get_address[True-parameters24-result24]": "cc2867c9329931504a642146995e10e3bb35703df77c946e74962c8ba13c49c3",
+"T3W1_cs_cardano-test_address_public_key.py::test_cardano_get_address[True-parameters25-result25]": "8898c6519e73a45fc0033e38c2e49f81d7a3e0bfd15f33d24e46ec7262b627ea",
+"T3W1_cs_cardano-test_address_public_key.py::test_cardano_get_address[True-parameters26-result26]": "1d92fb0b4e3571e36883b71ba748d2b56627ca14a7f2231bdf200853a3555515",
+"T3W1_cs_cardano-test_address_public_key.py::test_cardano_get_address[True-parameters27-result27]": "c00e8d3afd823d0d5460ce97dcfdbaeca014c797a20f2624b8d03d0aaaf1c7b7",
+"T3W1_cs_cardano-test_address_public_key.py::test_cardano_get_address[True-parameters28-result28]": "0dc21dddd1b51f8c047921275d489ea08772ae2b0b93d8f7e0fba48d0c87522a",
+"T3W1_cs_cardano-test_address_public_key.py::test_cardano_get_address[True-parameters29-result29]": "35c12d77a48ddde50fe325d0ad4bf6e2641cde85f52cae2cd96462a4dea2738f",
+"T3W1_cs_cardano-test_address_public_key.py::test_cardano_get_address[True-parameters3-result3]": "b375b043676f5f6b9dcd17d80c5f1c5c3c4031b19412921cfe2ff66a6c0b7764",
+"T3W1_cs_cardano-test_address_public_key.py::test_cardano_get_address[True-parameters30-result30]": "88e8799749fbcab4f3e1edb2116c18b69b4be711d3ddb7cdcbbd32de0fd6808b",
+"T3W1_cs_cardano-test_address_public_key.py::test_cardano_get_address[True-parameters31-result31]": "f426ffff3f886b1d4cb416e37d7dc8ae3970006219749157eb8db09ddd1cf639",
+"T3W1_cs_cardano-test_address_public_key.py::test_cardano_get_address[True-parameters32-result32]": "bf203fd7d03c2d931294be966457b0c3f2e439cf42c92b0a95a2fad1fe30e654",
+"T3W1_cs_cardano-test_address_public_key.py::test_cardano_get_address[True-parameters33-result33]": "151446802166dde272f4db645ad9b37c7ccc6ff4669a547b11289a28f1d72f82",
+"T3W1_cs_cardano-test_address_public_key.py::test_cardano_get_address[True-parameters34-result34]": "020577bd6e98448bd0ea4be001ee441c3f8e1b6c2418fe60a2f76ffeddc11a0e",
+"T3W1_cs_cardano-test_address_public_key.py::test_cardano_get_address[True-parameters35-result35]": "c59df4fa523551dbd497530bf7c794aa843756f8b73e73da5312ca928932dea1",
+"T3W1_cs_cardano-test_address_public_key.py::test_cardano_get_address[True-parameters36-result36]": "4cd0c6ef96f16f8868d7927eececcee325d61a08b4f4229698abf743b40d9b7e",
+"T3W1_cs_cardano-test_address_public_key.py::test_cardano_get_address[True-parameters4-result4]": "5df4fd657e30b43519da01172cf8c8ce47648fce684160cbba9a6de12a6c3c10",
+"T3W1_cs_cardano-test_address_public_key.py::test_cardano_get_address[True-parameters5-result5]": "51e6247bf5dbb3b5a19c168ec8263b44bd825000cf5b408e616c4d4ffdcc107e",
+"T3W1_cs_cardano-test_address_public_key.py::test_cardano_get_address[True-parameters6-result6]": "a00742a38f9fd916a28f6576c7dc26ecff33a074c48abd14eedae435f528158a",
+"T3W1_cs_cardano-test_address_public_key.py::test_cardano_get_address[True-parameters7-result7]": "43afb8fd5683868ce4ea55eff747c8bc90ba72edfcfd28eea5294b263eb35084",
+"T3W1_cs_cardano-test_address_public_key.py::test_cardano_get_address[True-parameters8-result8]": "e0799427aa110452a295d66e49269784b1d817b030b0fac7090125c3c0cf9b6b",
+"T3W1_cs_cardano-test_address_public_key.py::test_cardano_get_address[True-parameters9-result9]": "954017ae621d8bfd0752cf520b032652a706c834bbf9a17d3f1a7810a54ee507",
"T3W1_cs_cardano-test_address_public_key.py::test_cardano_get_public_key[icarus-derivation]": "d51f1a2fa4262a0968a1490ca8f7376f717bbd12b7386a4d4c38986ce230bec4",
"T3W1_cs_cardano-test_address_public_key.py::test_cardano_get_public_key[icarus-trezor-derivation]": "192094b79a99be2d34ff8b2c6d73a3fce308cdcfd35a9b958515605edf9daa3c",
"T3W1_cs_cardano-test_address_public_key.py::test_cardano_get_public_key[ledger-derivation]": "21508fc7a4650c1624f5e415a9950287ea140227289fab1935918c26dcbb5a97",
@@ -29146,125 +29146,125 @@
"T3W1_cs_cardano-test_derivations.py::test_derivation_irrelevant_on_slip39[CardanoDerivationType.LEDGER]": "535037bfe5f1459cfdf305915835d8bf2a9a427c3f60264a8cc3ca6f306a61b1",
"T3W1_cs_cardano-test_derivations.py::test_ledger_available_with_cardano": "535037bfe5f1459cfdf305915835d8bf2a9a427c3f60264a8cc3ca6f306a61b1",
"T3W1_cs_cardano-test_derivations.py::test_ledger_available_without_cardano": "535037bfe5f1459cfdf305915835d8bf2a9a427c3f60264a8cc3ca6f306a61b1",
-"T3W1_cs_cardano-test_get_native_script_hash.py::test_cardano_get_native_script_hash[all_script]": "f96285f4139794646c7d0d7b66590701eb5ea4d0ed31fcca628ac50c58431d0c",
-"T3W1_cs_cardano-test_get_native_script_hash.py::test_cardano_get_native_script_hash[all_script_cont-aae1e6c3": "b78eb6c26d738bbc3cebdfc2f3631ad4a701d858ee55431b5cc52c2563482891",
-"T3W1_cs_cardano-test_get_native_script_hash.py::test_cardano_get_native_script_hash[all_script_cont-e4ca0ea5": "17c1d41864c49376dd6cee5b966080a569edc4d64c1950913c474f4e99597a3c",
-"T3W1_cs_cardano-test_get_native_script_hash.py::test_cardano_get_native_script_hash[any_script]": "d73c53a57eb7512d26564a2c10e9ce2cc04fe448474b3a6936e5f4ff389975e5",
-"T3W1_cs_cardano-test_get_native_script_hash.py::test_cardano_get_native_script_hash[any_script_with-f2466a2e": "37d3448bb806024cba76234314e457e373beafcb6fb98bfb15ec73235a62ce0d",
-"T3W1_cs_cardano-test_get_native_script_hash.py::test_cardano_get_native_script_hash[invalid_before_script]": "3f1f845026ad2e2661f6b4b0623d4d1ba732a8918ce2fd684487b07cc37b37ab",
-"T3W1_cs_cardano-test_get_native_script_hash.py::test_cardano_get_native_script_hash[invalid_hereaft-d01d7292": "6dc30aca32dc584cddbe1746b59f7c1e64f2564ae85f845ddd6b1cda7805927e",
-"T3W1_cs_cardano-test_get_native_script_hash.py::test_cardano_get_native_script_hash[n_of_k_script]": "421fffb636dae303a258baa45f804632deedf0e8326fd3aa5870b46d6e717a09",
-"T3W1_cs_cardano-test_get_native_script_hash.py::test_cardano_get_native_script_hash[n_of_k_script_c-d93f5fb0": "bef73080d95e9d6152929c01ee57ae9aa551d22b5ec3b2734256340da4d16a25",
-"T3W1_cs_cardano-test_get_native_script_hash.py::test_cardano_get_native_script_hash[nested_script]": "7e9ded6738491658f556202951bd311e5afacea75f164cad12d418e2da5c2a22",
-"T3W1_cs_cardano-test_get_native_script_hash.py::test_cardano_get_native_script_hash[nested_script_w-789238e6": "d4aab99d4c51af65a6b6d0e57366a339e0541ba5e7f7a12412e92779abd9c153",
-"T3W1_cs_cardano-test_get_native_script_hash.py::test_cardano_get_native_script_hash[pub_key_script]": "1f432749ebfd6ce6d1d62e88ef8c10dd229deb90c72116a8bb1868bca58fff21",
-"T3W1_cs_cardano-test_get_native_script_hash.py::test_cardano_get_native_script_hash[pub_key_script_-1579fe2a": "317b82cd154a5d6d0f7cd5f87cc57c42368dcb42b794d0e8450d791e1228fae2",
-"T3W1_cs_cardano-test_sign_tx.py::test_cardano_sign_tx[byron_to_shelley_transfer]": "61224d230b034cbe2c99e1d46c8c1dfcea311102849d11b9ad3772bc0a04de6d",
-"T3W1_cs_cardano-test_sign_tx.py::test_cardano_sign_tx[mainnet_transaction_with_change0]": "9fca094a88967ebf012479e100d684a1bdf75b64c94d21931dd471ddfa316f5a",
-"T3W1_cs_cardano-test_sign_tx.py::test_cardano_sign_tx[mainnet_transaction_with_change1]": "7eea54952f5273a3805bae01c987b198c1cccb81490ad00b6c86eabaa502c823",
-"T3W1_cs_cardano-test_sign_tx.py::test_cardano_sign_tx[mainnet_transaction_with_multiple_inputs]": "f448ea663847746511fbf8facad48a485ade7c384a42e82a83cee66b4e36d5f0",
-"T3W1_cs_cardano-test_sign_tx.py::test_cardano_sign_tx[mainnet_transaction_without_change0]": "f448ea663847746511fbf8facad48a485ade7c384a42e82a83cee66b4e36d5f0",
-"T3W1_cs_cardano-test_sign_tx.py::test_cardano_sign_tx[mainnet_transaction_without_change1]": "f448ea663847746511fbf8facad48a485ade7c384a42e82a83cee66b4e36d5f0",
-"T3W1_cs_cardano-test_sign_tx.py::test_cardano_sign_tx[mary_era_transaction_with_different_policies_-1dbb1bfb": "81bfe78b8f7319e7855fd6d0dc1cf3ef91b89567841d6b399658bea06f2a4b6e",
-"T3W1_cs_cardano-test_sign_tx.py::test_cardano_sign_tx[mary_era_transaction_with_multiasset_output]": "674be71148a713fad0830f0d39b4b778097131bf016d00b358820b913bc1e354",
-"T3W1_cs_cardano-test_sign_tx.py::test_cardano_sign_tx[mary_era_transaction_with_no_ttl-validity_start]": "44784a716527c76e0f6f6b05bf83ad445c6ea713b954e7049a710eeccb842dea",
-"T3W1_cs_cardano-test_sign_tx.py::test_cardano_sign_tx[multisig_transaction_with_a_required_signer]": "0ddee2684e1e2b81cc4348909879d34f48363007d89483a2307e5597136f26ef",
-"T3W1_cs_cardano-test_sign_tx.py::test_cardano_sign_tx[multisig_transaction_with_most_elements_fille-29691455": "5bb5b9403712397df0eaefe11b74babf310fa2100f5fe565175112920b856647",
-"T3W1_cs_cardano-test_sign_tx.py::test_cardano_sign_tx[multisig_transaction_with_output_datum_hash]": "b22ff69e3c0b8d050aa0a2d4fc4250f3e32d32c03d473e1a34168afbe6d3059d",
-"T3W1_cs_cardano-test_sign_tx.py::test_cardano_sign_tx[multisig_transaction_with_script_data_hash]": "982755217030070e1b8f5ccdfd621fb3be74ae1913a5577b563701d4cc85b7f1",
-"T3W1_cs_cardano-test_sign_tx.py::test_cardano_sign_tx[multisig_transaction_with_stake_deregistratio-1ab28f77": "fdce5cf2ffcd908c97d924fc9aa10f9462fa789223829d3486b15d5724ac677a",
-"T3W1_cs_cardano-test_sign_tx.py::test_cardano_sign_tx[multisig_transaction_with_stake_deregistration]": "fdce5cf2ffcd908c97d924fc9aa10f9462fa789223829d3486b15d5724ac677a",
-"T3W1_cs_cardano-test_sign_tx.py::test_cardano_sign_tx[multisig_transaction_with_stake_registration_-a144c34c": "ddcd8360ecc3f46e5366f21307af8f80056f7c4b12be9b44cecae0d8d2167682",
-"T3W1_cs_cardano-test_sign_tx.py::test_cardano_sign_tx[multisig_transaction_with_stake_registration_-bf5f9707": "16c8a31947ef5be5dfd784b37c2cf4fe580388023d7fae56194c205662709881",
-"T3W1_cs_cardano-test_sign_tx.py::test_cardano_sign_tx[multisig_transaction_with_token_minting]": "6dc92765d57382367f16d8278019c8afc1c3dd2fe4c2c8ba7cf39e136225ef52",
-"T3W1_cs_cardano-test_sign_tx.py::test_cardano_sign_tx[ordinary_transaction_with_a_required_signer]": "e95296e5851e670740a40f273b0ab7ba346b677bd960763774352943d5439887",
-"T3W1_cs_cardano-test_sign_tx.py::test_cardano_sign_tx[ordinary_transaction_with_both_output_formats]": "32866af2be22ad53d6827254a4fa2cbd5f67383f0fc381567dcbce16b90d4cdc",
-"T3W1_cs_cardano-test_sign_tx.py::test_cardano_sign_tx[ordinary_transaction_with_inline_datum,_refer-d1082570": "d6102a5c2118ff221cf3bb2314d57f9535ed27a23f01937e77dfd2a0835c26f0",
-"T3W1_cs_cardano-test_sign_tx.py::test_cardano_sign_tx[ordinary_transaction_with_long_inline_datum,_-1f681aaa": "44784a716527c76e0f6f6b05bf83ad445c6ea713b954e7049a710eeccb842dea",
-"T3W1_cs_cardano-test_sign_tx.py::test_cardano_sign_tx[ordinary_transaction_with_multiple_correctly_-6545455a": "bd19b8b4478045d9905481b18a8d64c9271b16f34c48bb3f51f2f8a1ae7c71d9",
-"T3W1_cs_cardano-test_sign_tx.py::test_cardano_sign_tx[ordinary_transaction_with_network_id_included-d9df16f9": "f448ea663847746511fbf8facad48a485ade7c384a42e82a83cee66b4e36d5f0",
-"T3W1_cs_cardano-test_sign_tx.py::test_cardano_sign_tx[ordinary_transaction_with_non-zero_address_in-57a740e6": "c64ca4cefff810cb544c4491febfa4f000d0c2a0c35e9606ea14e3d53496e6c2",
-"T3W1_cs_cardano-test_sign_tx.py::test_cardano_sign_tx[ordinary_transaction_with_non-zero_address_in-f709f55f": "287a6b07bdc8720fb861e8cf71433eb4389e44ebe2778073d30c5950340de886",
-"T3W1_cs_cardano-test_sign_tx.py::test_cardano_sign_tx[ordinary_transaction_with_non-zero_address_in-fab7e996": "c29d0ccc1e5435534445150493afb1835639ff7d75954f836d4449fbe8397be4",
-"T3W1_cs_cardano-test_sign_tx.py::test_cardano_sign_tx[ordinary_transaction_with_output_datum_hash]": "d6102a5c2118ff221cf3bb2314d57f9535ed27a23f01937e77dfd2a0835c26f0",
-"T3W1_cs_cardano-test_sign_tx.py::test_cardano_sign_tx[ordinary_transaction_with_output_datum_hash_a-84ad587a": "44784a716527c76e0f6f6b05bf83ad445c6ea713b954e7049a710eeccb842dea",
-"T3W1_cs_cardano-test_sign_tx.py::test_cardano_sign_tx[ordinary_transaction_with_script_address_but_-b0da7209": "a34911377a69a499708bf531634f2e36c0737985027f5431c8b45eb300c57ab6",
-"T3W1_cs_cardano-test_sign_tx.py::test_cardano_sign_tx[ordinary_transaction_with_script_data_hash]": "d7a12473e5c0499e0dc900936a4e898247104916ab9d82a1f3cdbfd980658ad7",
-"T3W1_cs_cardano-test_sign_tx.py::test_cardano_sign_tx[ordinary_transaction_with_token_minting]": "93da4d7cb447718c5a1aeef696efa8848a98cba984ffc3d412d6a6070858170e",
-"T3W1_cs_cardano-test_sign_tx.py::test_cardano_sign_tx[plutus_transaction_with_an_ordinary_input]": "0cc11748c9ff4abe265d6b699b2d6871b78b0bce402b40b061a1d09d440bb604",
-"T3W1_cs_cardano-test_sign_tx.py::test_cardano_sign_tx[plutus_transaction_with_base_address_device-o-a33e6741": "360e76839c727e8a2ff24e380425cede8ec9a0fa51c4906ed610093e77b0be04",
-"T3W1_cs_cardano-test_sign_tx.py::test_cardano_sign_tx[plutus_transaction_with_base_address_device-o-a6481374": "6adfb48afe7e4934ed71afec0993ebd1d66ea19c29077ce8ab9ae2d796e14e6d",
-"T3W1_cs_cardano-test_sign_tx.py::test_cardano_sign_tx[plutus_transaction_with_base_address_device-o-ae657c7a": "989811cb8af405c6bfdaac7756c47d52e1c5dfa50b0f0ed0a975541ec9e70dc8",
-"T3W1_cs_cardano-test_sign_tx.py::test_cardano_sign_tx[plutus_transaction_with_base_key_script_addre-d3366a63": "a93a7e24e7009c9b4a0e7d858d388566080c6ef09ef60ea1c688e556624fa7af",
-"T3W1_cs_cardano-test_sign_tx.py::test_cardano_sign_tx[plutus_transaction_with_device-owned_collater-8f38b4d7": "974716aa3aacd00e055757b054b1e8575f8a295978191062057b98a5df37c30f",
-"T3W1_cs_cardano-test_sign_tx.py::test_cardano_sign_tx[plutus_transaction_with_external_collateral_return]": "ad9ba0f78ced86faa20e422d80cb3a9b66525f028177d94c98d640526a81b47e",
-"T3W1_cs_cardano-test_sign_tx.py::test_cardano_sign_tx[plutus_transaction_with_output_datum_hash]": "7760e013b041afecee3d5648c4db24f869fb5d3af3bd3a93bc68dda3f9d1296f",
-"T3W1_cs_cardano-test_sign_tx.py::test_cardano_sign_tx[plutus_transaction_with_reference_input]": "cf27185f1ab1f2e94f6739207ecbe1b42e2bc417e0ad1ebd1a0b310b6921b8c4",
-"T3W1_cs_cardano-test_sign_tx.py::test_cardano_sign_tx[plutus_transaction_with_required_signers,_ref-b419b9e1": "17ba6d00d48454170b1f092dd618a6fdc2f846d8492cbc495dc6eaf0ef1ba0a0",
-"T3W1_cs_cardano-test_sign_tx.py::test_cardano_sign_tx[plutus_transaction_with_stake_credentials_giv-6a67c1eb": "10f2cd2ca90e55dce93f94a5a590167594a000902ebbebc605627dbd52784362",
-"T3W1_cs_cardano-test_sign_tx.py::test_cardano_sign_tx[plutus_transaction_with_stake_credentials_giv-72ef969e": "0bb36e64be10d2ac71f4df1c6a8f241e96ea6927d698b63f2f8dd434b4b4f505",
-"T3W1_cs_cardano-test_sign_tx.py::test_cardano_sign_tx[plutus_transaction_with_stake_deregistration]": "afa787622e9200ba527b2d1e205b0a60cef65bef6e8ecc1f8401519134b3adde",
-"T3W1_cs_cardano-test_sign_tx.py::test_cardano_sign_tx[plutus_transaction_with_stake_deregistration_-78f5c748": "4a2c9f02e9c38948a45735f2d02628911f5b1918f9fa4da141adcaff43e09a9d",
-"T3W1_cs_cardano-test_sign_tx.py::test_cardano_sign_tx[plutus_transaction_with_stake_registration_an-4da9385a": "1686c91847df7927ce886715361a5d26c98cd7296b42b70fff4610e94e91d689",
-"T3W1_cs_cardano-test_sign_tx.py::test_cardano_sign_tx[plutus_transaction_with_stake_registration_ce-46b0a250": "f58ee90511c83ed433a67d7598dd598521f4d8352ad0fb22bf1267af45f03cf0",
-"T3W1_cs_cardano-test_sign_tx.py::test_cardano_sign_tx[plutus_transaction_with_token_minting]": "47d4b32181604ec31a69ccc1693db3834d51bce2ca6f6207095a7e81949d9a6c",
-"T3W1_cs_cardano-test_sign_tx.py::test_cardano_sign_tx[plutus_transaction_with_total_collateral]": "3a85d882795abb618da5e5e3c4358b8abd0b5f3a84a4536a164c1d35905322e9",
-"T3W1_cs_cardano-test_sign_tx.py::test_cardano_sign_tx[plutus_transaction_with_total_collateral_and_-3f0b305a": "01cff06611c3bcde637ed54854116a9f5fb8ac56392f70c26bdad5122d7ee5e7",
-"T3W1_cs_cardano-test_sign_tx.py::test_cardano_sign_tx[plutus_transaction_with_total_collateral_and_-c92d773b": "e5fadb9da5e286ea6379e2b7788dfd66ec0fc50049ebe9c1a261a9acf77352ee",
-"T3W1_cs_cardano-test_sign_tx.py::test_cardano_sign_tx[plutus_transaction_without_script_data_hash_a-9590827f": "1ef5d427acd9187e11f761bdda33d6f340ef183176e8b8ae18326b067e74978e",
-"T3W1_cs_cardano-test_sign_tx.py::test_cardano_sign_tx[sample_stake_pool_registration_certificate]": "845275aba239cf08d59b19dd636021e29776ffc105ed962e0291cc0d6340e2d2",
-"T3W1_cs_cardano-test_sign_tx.py::test_cardano_sign_tx[sample_stake_pool_registration_certificate_wi-336f4a44": "845275aba239cf08d59b19dd636021e29776ffc105ed962e0291cc0d6340e2d2",
-"T3W1_cs_cardano-test_sign_tx.py::test_cardano_sign_tx[sample_stake_pool_registration_certificate_wi-d3427614": "e6af5517e8f9a69f5f068f18709765f3f706d8a1cc8e5ba60a44dcce9a46261e",
-"T3W1_cs_cardano-test_sign_tx.py::test_cardano_sign_tx[sample_stake_pool_registration_certificate_wi-e1e17a76": "c39790b7c3423bc8cd2bc130ee3b5e6e0335b18b8f9b60c88b2ceaf33c86baaa",
-"T3W1_cs_cardano-test_sign_tx.py::test_cardano_sign_tx[sample_stake_pool_registration_with_zero_margin]": "bb9a49f0e8134742878be2758ab9ad954537bc7a0fd133907c37817574175697",
-"T3W1_cs_cardano-test_sign_tx.py::test_cardano_sign_tx[simple_plutus_transaction]": "97eaf899fed89c19e64c6bfbc5a33f6b5be4e3c79c5ab977c218b3e9d51cf5cc",
-"T3W1_cs_cardano-test_sign_tx.py::test_cardano_sign_tx[simple_plutus_transaction_with_additional_wit-36ba8ce8": "161d962d971ae3b774b11d75b0ab9128c7ad3e5f505310c1766bc056bbcb3bca",
-"T3W1_cs_cardano-test_sign_tx.py::test_cardano_sign_tx[simple_plutus_transaction_with_required_signers]": "fc9612354938d611a5e7273b8b63068b9832e6deedd53be82536ce4937dd2af3",
-"T3W1_cs_cardano-test_sign_tx.py::test_cardano_sign_tx[simple_transaction_with_base_address_change_o-0c37e6dc": "31f6d88854d65845d1c863d26686be2ce6b3b2769e79cff31df0ac6799c6f307",
-"T3W1_cs_cardano-test_sign_tx.py::test_cardano_sign_tx[simple_transaction_with_base_address_change_o-7f1d12f6": "87ac4ec0faeef93009693387b05740fdf0fdc33f5ef5e89603987f69bbf77153",
-"T3W1_cs_cardano-test_sign_tx.py::test_cardano_sign_tx[simple_transaction_with_base_address_change_output]": "d7a12473e5c0499e0dc900936a4e898247104916ab9d82a1f3cdbfd980658ad7",
-"T3W1_cs_cardano-test_sign_tx.py::test_cardano_sign_tx[simple_transaction_with_base_script_address_a-56fc16f7": "a6a614b32186a331b363fe2064689b8ad5ef3a3c873af1a51d9cb9c3177bf64a",
-"T3W1_cs_cardano-test_sign_tx.py::test_cardano_sign_tx[simple_transaction_with_enterprise_address_ch-15518a4c": "0bbe9ebe69df91359057a1dc984706f115f9098aab519001a6ebb34473fc0213",
-"T3W1_cs_cardano-test_sign_tx.py::test_cardano_sign_tx[simple_transaction_with_pointer_address_change_output]": "8e2276f32af711de835cfb5c1b2978f9efc1c0b3f5b660440b3517fac6f05221",
-"T3W1_cs_cardano-test_sign_tx.py::test_cardano_sign_tx[stake_pool_registration_certificate_with_no_p-0bbad967": "374d4a033e91387ccf4b1a5ce011f4a2b7d449e00b874489cf54275e3b18918c",
-"T3W1_cs_cardano-test_sign_tx.py::test_cardano_sign_tx[stake_pool_registration_on_testnet]": "dd61fd6b7ad1d0ed6c59e6b37e43fb1f3b2b4d4c428c68bf6267812e790f7097",
-"T3W1_cs_cardano-test_sign_tx.py::test_cardano_sign_tx[testnetWhy this scored 19/100
Community notes
Notes can correct, qualify, or add evidence to the AI analysis. Every note shown here has been validated by a human moderator.
The AI analysis stands alone for now. Submit a note if you can add evidence or important context.