mirror of
https://github.com/trezor/trezor-firmware.git
synced 2024-11-18 13:38:12 +00:00
feat(core): Show path for internal outputs in BTC signing.
This commit is contained in:
parent
4622aec0f1
commit
d4ddc78dbb
1
core/.changelog.d/2152.added
Normal file
1
core/.changelog.d/2152.added
Normal file
@ -0,0 +1 @@
|
||||
Show path for internal outputs in BTC signing.
|
@ -1,9 +1,10 @@
|
||||
from micropython import const
|
||||
from typing import TYPE_CHECKING
|
||||
|
||||
from trezor.enums import InputScriptType
|
||||
from trezor.messages import AuthorizeCoinJoin, SignMessage
|
||||
|
||||
from apps.common.paths import PATTERN_BIP44, PATTERN_CASA, PathSchema
|
||||
from apps.common.paths import PATTERN_BIP44, PATTERN_CASA, PathSchema, unharden
|
||||
|
||||
from . import authorization
|
||||
from .common import BITCOIN_NAMES
|
||||
@ -15,7 +16,6 @@ if TYPE_CHECKING:
|
||||
from trezor.protobuf import MessageType
|
||||
from trezor.wire import Context
|
||||
|
||||
from trezor.enums import InputScriptType
|
||||
from trezor.messages import (
|
||||
GetAddress,
|
||||
GetOwnershipId,
|
||||
@ -333,3 +333,109 @@ def with_keychain(func: HandlerWithCoinInfo[MsgOut]) -> Handler[MsgIn, MsgOut]:
|
||||
return await func(ctx, msg, keychain, coin)
|
||||
|
||||
return wrapper
|
||||
|
||||
|
||||
class AccountType:
|
||||
def __init__(
|
||||
self,
|
||||
account_name: str,
|
||||
pattern: str,
|
||||
script_type: InputScriptType,
|
||||
require_segwit: bool,
|
||||
require_bech32: bool,
|
||||
require_taproot: bool,
|
||||
):
|
||||
self.account_name = account_name
|
||||
self.pattern = pattern
|
||||
self.script_type = script_type
|
||||
self.require_segwit = require_segwit
|
||||
self.require_bech32 = require_bech32
|
||||
self.require_taproot = require_taproot
|
||||
|
||||
def get_name(
|
||||
self,
|
||||
coin: coininfo.CoinInfo,
|
||||
address_n: Bip32Path,
|
||||
script_type: InputScriptType | None,
|
||||
) -> str | None:
|
||||
if (
|
||||
(script_type is not None and script_type != self.script_type)
|
||||
or not PathSchema.parse(self.pattern, coin.slip44).match(address_n)
|
||||
or (not coin.segwit and self.require_segwit)
|
||||
or (not coin.bech32_prefix and self.require_bech32)
|
||||
or (not coin.taproot and self.require_taproot)
|
||||
):
|
||||
return None
|
||||
|
||||
name = self.account_name
|
||||
account_pos = self.pattern.find("/account'")
|
||||
if account_pos >= 0:
|
||||
i = self.pattern.count("/", 0, account_pos)
|
||||
account_number = unharden(address_n[i]) + 1
|
||||
name += f" #{account_number}"
|
||||
|
||||
return name
|
||||
|
||||
|
||||
def address_n_to_name(
|
||||
coin: coininfo.CoinInfo,
|
||||
address_n: Bip32Path,
|
||||
script_type: InputScriptType | None = None,
|
||||
) -> str | None:
|
||||
ACCOUNT_TYPES = (
|
||||
AccountType(
|
||||
"Legacy account",
|
||||
PATTERN_BIP44,
|
||||
InputScriptType.SPENDADDRESS,
|
||||
require_segwit=True,
|
||||
require_bech32=False,
|
||||
require_taproot=False,
|
||||
),
|
||||
AccountType(
|
||||
"Account",
|
||||
PATTERN_BIP44,
|
||||
InputScriptType.SPENDADDRESS,
|
||||
require_segwit=False,
|
||||
require_bech32=False,
|
||||
require_taproot=False,
|
||||
),
|
||||
AccountType(
|
||||
"Legacy SegWit account",
|
||||
PATTERN_BIP49,
|
||||
InputScriptType.SPENDP2SHWITNESS,
|
||||
require_segwit=True,
|
||||
require_bech32=False,
|
||||
require_taproot=False,
|
||||
),
|
||||
AccountType(
|
||||
"SegWit account",
|
||||
PATTERN_BIP84,
|
||||
InputScriptType.SPENDWITNESS,
|
||||
require_segwit=True,
|
||||
require_bech32=True,
|
||||
require_taproot=False,
|
||||
),
|
||||
AccountType(
|
||||
"Taproot account",
|
||||
PATTERN_BIP86,
|
||||
InputScriptType.SPENDTAPROOT,
|
||||
require_segwit=False,
|
||||
require_bech32=True,
|
||||
require_taproot=True,
|
||||
),
|
||||
AccountType(
|
||||
"Coinjoin account",
|
||||
PATTERN_SLIP25_TAPROOT,
|
||||
InputScriptType.SPENDTAPROOT,
|
||||
require_segwit=False,
|
||||
require_bech32=True,
|
||||
require_taproot=True,
|
||||
),
|
||||
)
|
||||
|
||||
for account in ACCOUNT_TYPES:
|
||||
name = account.get_name(coin, address_n, script_type)
|
||||
if name:
|
||||
return name
|
||||
|
||||
return None
|
||||
|
@ -6,8 +6,11 @@ from trezor.strings import format_amount
|
||||
from trezor.ui import layouts
|
||||
from trezor.ui.layouts import confirm_metadata
|
||||
|
||||
from apps.common.paths import address_n_to_str
|
||||
|
||||
from .. import addresses
|
||||
from ..common import format_fee_rate
|
||||
from ..common import CHANGE_OUTPUT_TO_INPUT_SCRIPT_TYPES, format_fee_rate
|
||||
from ..keychain import address_n_to_name
|
||||
|
||||
if TYPE_CHECKING:
|
||||
from typing import Any
|
||||
@ -76,11 +79,20 @@ async def confirm_output(
|
||||
else:
|
||||
title = "Confirm sending"
|
||||
|
||||
address_label = None
|
||||
if output.address_n and not output.multisig:
|
||||
script_type = CHANGE_OUTPUT_TO_INPUT_SCRIPT_TYPES[output.script_type]
|
||||
address_label = (
|
||||
address_n_to_name(coin, output.address_n, script_type)
|
||||
or f"address path {address_n_to_str(output.address_n)}"
|
||||
)
|
||||
|
||||
layout = layouts.confirm_output(
|
||||
ctx,
|
||||
address_short,
|
||||
format_coin_amount(output.amount, coin, amount_unit),
|
||||
title=title,
|
||||
address_label=address_label,
|
||||
)
|
||||
|
||||
await layout
|
||||
|
@ -189,13 +189,15 @@ async def confirm_output(
|
||||
amount: str,
|
||||
title: str = "Confirm sending",
|
||||
br_code: ButtonRequestType = ButtonRequestType.ConfirmOutput,
|
||||
address_label: str | None = None,
|
||||
) -> None:
|
||||
label = f" ({address_label})" if address_label else ""
|
||||
result = await interact(
|
||||
ctx,
|
||||
RustLayout(
|
||||
trezorui2.confirm_text(
|
||||
title=title,
|
||||
data=f"Send {amount} to {address}?",
|
||||
data=f"Send {amount} to {address}{label}?",
|
||||
description="Confirm Output",
|
||||
)
|
||||
),
|
||||
|
@ -532,16 +532,18 @@ async def confirm_output(
|
||||
title: str = "SENDING",
|
||||
hold: bool = False,
|
||||
br_code: ButtonRequestType = ButtonRequestType.ConfirmOutput,
|
||||
address_label: str | None = None,
|
||||
) -> None:
|
||||
title = title.upper()
|
||||
if title.startswith("CONFIRM "):
|
||||
title = title[len("CONFIRM ") :]
|
||||
|
||||
description = f"To your {address_label}:" if address_label else "To:"
|
||||
await confirm_value(
|
||||
ctx,
|
||||
title,
|
||||
address,
|
||||
"To:",
|
||||
description,
|
||||
"confirm_output",
|
||||
br_code,
|
||||
verb="NEXT",
|
||||
|
Loading…
Reference in New Issue
Block a user