1
0
mirror of https://github.com/trezor/trezor-firmware.git synced 2025-04-20 09:09:02 +00:00

feat(core): Set mac field in altcoin Address response messages.

This commit is contained in:
Andrew Kozlik 2025-04-17 15:59:09 +02:00
parent f7a74268e0
commit a1686b2377
12 changed files with 92 additions and 46 deletions

View File

@ -15,8 +15,11 @@ async def get_address(
from trezor import log, wire
from trezor.messages import CardanoAddress
from apps.common.address_mac import get_address_mac
from . import addresses
from .helpers.credential import Credential, should_show_credentials
from .helpers.paths import SLIP44_ID
from .helpers.utils import validate_network_info
from .layout import show_cardano_address, show_credentials
@ -34,6 +37,9 @@ async def get_address(
log.exception(__name__, e)
raise wire.ProcessError("Deriving address failed")
mac = get_address_mac(
address, SLIP44_ID, address_parameters.address_n, slip21_keychain
)
if msg.show_display:
# _display_address
if should_show_credentials(address_parameters):
@ -45,4 +51,4 @@ async def get_address(
address_parameters, address, msg.protocol_magic, chunkify=bool(msg.chunkify)
)
return CardanoAddress(address=address)
return CardanoAddress(address=address, mac=mac)

View File

@ -2,21 +2,21 @@ from micropython import const
from apps.common.paths import HARDENED, PathSchema, unharden # noqa: F401
_SLIP44_ID = const(1815)
SLIP44_ID = const(1815)
BYRON_ROOT = [44 | HARDENED, _SLIP44_ID | HARDENED]
SHELLEY_ROOT = [1852 | HARDENED, _SLIP44_ID | HARDENED]
MULTISIG_ROOT = [1854 | HARDENED, _SLIP44_ID | HARDENED]
MINTING_ROOT = [1855 | HARDENED, _SLIP44_ID | HARDENED]
BYRON_ROOT = [44 | HARDENED, SLIP44_ID | HARDENED]
SHELLEY_ROOT = [1852 | HARDENED, SLIP44_ID | HARDENED]
MULTISIG_ROOT = [1854 | HARDENED, SLIP44_ID | HARDENED]
MINTING_ROOT = [1855 | HARDENED, SLIP44_ID | HARDENED]
# fmt: off
SCHEMA_PUBKEY = PathSchema.parse("m/[44,1852,1854]'/coin_type'/account'/*", _SLIP44_ID)
SCHEMA_PUBKEY = PathSchema.parse("m/[44,1852,1854]'/coin_type'/account'/*", SLIP44_ID)
# minting has a specific schema for key derivation - see CIP-1855
SCHEMA_MINT = PathSchema.parse(f"m/1855'/coin_type'/[0-{HARDENED - 1}]'", _SLIP44_ID)
SCHEMA_PAYMENT = PathSchema.parse("m/[44,1852]'/coin_type'/account'/[0,1]/address_index", _SLIP44_ID)
SCHEMA_MINT = PathSchema.parse(f"m/1855'/coin_type'/[0-{HARDENED - 1}]'", SLIP44_ID)
SCHEMA_PAYMENT = PathSchema.parse("m/[44,1852]'/coin_type'/account'/[0,1]/address_index", SLIP44_ID)
# staking is only allowed on Shelley paths with suffix /2/0
SCHEMA_STAKING = PathSchema.parse("m/1852'/coin_type'/account'/2/address_index", _SLIP44_ID)
SCHEMA_STAKING_ANY_ACCOUNT = PathSchema.parse(f"m/1852'/coin_type'/[0-{HARDENED - 1}]'/2/address_index", _SLIP44_ID)
SCHEMA_STAKING = PathSchema.parse("m/1852'/coin_type'/account'/2/address_index", SLIP44_ID)
SCHEMA_STAKING_ANY_ACCOUNT = PathSchema.parse(f"m/1852'/coin_type'/[0-{HARDENED - 1}]'/2/address_index", SLIP44_ID)
# fmt: on
ACCOUNT_PATH_INDEX = const(2)

View File

@ -182,6 +182,7 @@ def with_slip44_keychain(
slip44_id: int,
curve: str = "secp256k1",
allow_testnet: bool = True,
slip21_namespaces: Iterable[paths.Slip21Path] = (),
) -> Callable[[HandlerWithKeychain[MsgIn, MsgOut]], Handler[MsgIn, MsgOut]]:
if not patterns:
raise ValueError # specify a pattern
@ -195,7 +196,7 @@ def with_slip44_keychain(
def decorator(func: HandlerWithKeychain[MsgIn, MsgOut]) -> Handler[MsgIn, MsgOut]:
async def wrapper(msg: MsgIn) -> MsgOut:
keychain = await get_keychain(curve, schemas)
keychain = await get_keychain(curve, schemas, slip21_namespaces)
with keychain:
return await func(msg, keychain)
@ -205,7 +206,9 @@ def with_slip44_keychain(
def auto_keychain(
modname: str, allow_testnet: bool = True
modname: str,
allow_testnet: bool = True,
slip21_namespaces: Iterable[paths.Slip21Path] = (),
) -> Callable[[HandlerWithKeychain[MsgIn, MsgOut]], Handler[MsgIn, MsgOut]]:
import sys
@ -217,5 +220,9 @@ def auto_keychain(
curve = getattr(parent_module, "CURVE")
slip44_id = getattr(parent_module, "SLIP44_ID")
return with_slip44_keychain(
pattern, slip44_id=slip44_id, curve=curve, allow_testnet=allow_testnet
pattern,
slip44_id=slip44_id,
curve=curve,
allow_testnet=allow_testnet,
slip21_namespaces=slip21_namespaces,
)

View File

@ -8,14 +8,16 @@ if TYPE_CHECKING:
from apps.common.keychain import Keychain
@auto_keychain(__name__)
@auto_keychain(__name__, slip21_namespaces=[[b"SLIP-0024"]])
async def get_address(msg: RippleGetAddress, keychain: Keychain) -> RippleAddress:
# NOTE: local imports here saves 20 bytes
from trezor.messages import RippleAddress
from trezor.ui.layouts import show_address
from apps.common import paths
from apps.common.address_mac import get_address_mac
from . import SLIP44_ID
from .helpers import address_from_public_key
address_n = msg.address_n # local_cache_attribute
@ -25,9 +27,10 @@ async def get_address(msg: RippleGetAddress, keychain: Keychain) -> RippleAddres
node = keychain.derive(address_n)
pubkey = node.public_key()
address = address_from_public_key(pubkey)
mac = get_address_mac(address, SLIP44_ID, address_n, keychain)
if msg.show_display:
from . import PATTERN, SLIP44_ID
from . import PATTERN
await show_address(
address,
@ -36,4 +39,4 @@ async def get_address(msg: RippleGetAddress, keychain: Keychain) -> RippleAddres
chunkify=bool(msg.chunkify),
)
return RippleAddress(address=address)
return RippleAddress(address=address, mac=mac)

View File

@ -12,7 +12,9 @@ if TYPE_CHECKING:
from apps.common.keychain import Keychain
@with_slip44_keychain(*PATTERNS, slip44_id=SLIP44_ID, curve=CURVE)
@with_slip44_keychain(
*PATTERNS, slip44_id=SLIP44_ID, curve=CURVE, slip21_namespaces=[[b"SLIP-0024"]]
)
async def get_address(
msg: SolanaGetAddress,
keychain: Keychain,
@ -21,11 +23,13 @@ async def get_address(
from trezor.ui.layouts import show_address
from apps.common import paths
from apps.common.address_mac import get_address_mac
from .get_public_key import derive_public_key
public_key = derive_public_key(keychain, msg.address_n)
address = base58.encode(public_key)
mac = get_address_mac(address, SLIP44_ID, msg.address_n, keychain)
if msg.show_display:
await show_address(
@ -34,4 +38,4 @@ async def get_address(
chunkify=bool(msg.chunkify),
)
return SolanaAddress(address=address)
return SolanaAddress(address=address, mac=mac)

View File

@ -8,14 +8,15 @@ if TYPE_CHECKING:
from apps.common.keychain import Keychain
@auto_keychain(__name__)
@auto_keychain(__name__, slip21_namespaces=[[b"SLIP-0024"]])
async def get_address(msg: StellarGetAddress, keychain: Keychain) -> StellarAddress:
from trezor.messages import StellarAddress
from trezor.ui.layouts import show_address
from apps.common import paths, seed
from apps.common.address_mac import get_address_mac
from . import helpers
from . import SLIP44_ID, helpers
address_n = msg.address_n # local_cache_attribute
@ -24,9 +25,10 @@ async def get_address(msg: StellarGetAddress, keychain: Keychain) -> StellarAddr
node = keychain.derive(address_n)
pubkey = seed.remove_ed25519_prefix(node.public_key())
address = helpers.address_from_public_key(pubkey)
mac = get_address_mac(address, SLIP44_ID, address_n, keychain)
if msg.show_display:
from . import PATTERN, SLIP44_ID
from . import PATTERN
await show_address(
address,
@ -36,4 +38,4 @@ async def get_address(msg: StellarGetAddress, keychain: Keychain) -> StellarAddr
chunkify=bool(msg.chunkify),
)
return StellarAddress(address=address)
return StellarAddress(address=address, mac=mac)

View File

@ -10,15 +10,18 @@ if TYPE_CHECKING:
from apps.common.keychain import Keychain
@with_slip44_keychain(*PATTERNS, slip44_id=SLIP44_ID, curve=CURVE)
@with_slip44_keychain(
*PATTERNS, slip44_id=SLIP44_ID, curve=CURVE, slip21_namespaces=[[b"SLIP-0024"]]
)
async def get_address(msg: TezosGetAddress, keychain: Keychain) -> TezosAddress:
from trezor.crypto import hashlib
from trezor.messages import TezosAddress
from trezor.ui.layouts import show_address
from apps.common import paths, seed
from apps.common.address_mac import get_address_mac
from . import helpers
from . import SLIP44_ID, helpers
address_n = msg.address_n # local_cache_attribute
@ -29,9 +32,10 @@ async def get_address(msg: TezosGetAddress, keychain: Keychain) -> TezosAddress:
pk = seed.remove_ed25519_prefix(node.public_key())
pkh = hashlib.blake2b(pk, outlen=helpers.PUBLIC_KEY_HASH_SIZE).digest()
address = helpers.base58_encode_check(pkh, helpers.TEZOS_ED25519_ADDRESS_PREFIX)
mac = get_address_mac(address, SLIP44_ID, address_n, keychain)
if msg.show_display:
from . import PATTERNS, SLIP44_ID
from . import PATTERNS
await show_address(
address,
@ -40,4 +44,4 @@ async def get_address(msg: TezosGetAddress, keychain: Keychain) -> TezosAddress:
chunkify=bool(msg.chunkify),
)
return TezosAddress(address=address)
return TezosAddress(address=address, mac=mac)

View File

@ -817,7 +817,11 @@ def _get_collateral_inputs_items(
# ====== Client functions ====== #
def get_address(
def get_address(*args: Any, **kwargs: Any) -> str:
return get_authenticated_address(*args, **kwargs).address
def get_authenticated_address(
client: "TrezorClient",
address_parameters: m.CardanoAddressParametersType,
protocol_magic: int = PROTOCOL_MAGICS["mainnet"],
@ -825,7 +829,7 @@ def get_address(
show_display: bool = False,
derivation_type: m.CardanoDerivationType = m.CardanoDerivationType.ICARUS,
chunkify: bool = False,
) -> str:
) -> m.CardanoAddress:
return client.call(
m.CardanoGetAddress(
address_parameters=address_parameters,
@ -836,7 +840,7 @@ def get_address(
chunkify=chunkify,
),
expect=m.CardanoAddress,
).address
)
def get_public_key(

View File

@ -14,7 +14,7 @@
# You should have received a copy of the License along with this library.
# If not, see <https://www.gnu.org/licenses/lgpl-3.0.html>.
from typing import TYPE_CHECKING
from typing import TYPE_CHECKING, Any
from . import messages
from .protobuf import dict_to_proto
@ -28,18 +28,22 @@ REQUIRED_FIELDS = ("Fee", "Sequence", "TransactionType", "Payment")
REQUIRED_PAYMENT_FIELDS = ("Amount", "Destination")
def get_address(
def get_address(*args: Any, **kwargs: Any) -> str:
return get_authenticated_address(*args, **kwargs).address
def get_authenticated_address(
client: "TrezorClient",
address_n: "Address",
show_display: bool = False,
chunkify: bool = False,
) -> str:
) -> messages.RippleAddress:
return client.call(
messages.RippleGetAddress(
address_n=address_n, show_display=show_display, chunkify=chunkify
),
expect=messages.RippleAddress,
).address
)
def sign_tx(

View File

@ -1,4 +1,4 @@
from typing import TYPE_CHECKING, List, Optional
from typing import TYPE_CHECKING, Any, List, Optional
from . import messages
@ -17,12 +17,16 @@ def get_public_key(
).public_key
def get_address(
def get_address(*args: Any, **kwargs: Any) -> str:
return get_authenticated_address(*args, **kwargs).address
def get_authenticated_address(
client: "TrezorClient",
address_n: List[int],
show_display: bool,
chunkify: bool = False,
) -> str:
) -> messages.SolanaAddress:
return client.call(
messages.SolanaGetAddress(
address_n=address_n,
@ -30,7 +34,7 @@ def get_address(
chunkify=chunkify,
),
expect=messages.SolanaAddress,
).address
)
def sign_tx(

View File

@ -15,7 +15,7 @@
# If not, see <https://www.gnu.org/licenses/lgpl-3.0.html>.
from decimal import Decimal
from typing import TYPE_CHECKING, List, Tuple, Union
from typing import TYPE_CHECKING, Any, List, Tuple, Union
from . import exceptions, messages
@ -321,18 +321,22 @@ def _read_asset(asset: "Asset") -> messages.StellarAsset:
# ====== Client functions ====== #
def get_address(
def get_address(*args: Any, **kwargs: Any) -> str:
return get_authenticated_address(*args, **kwargs).address
def get_authenticated_address(
client: "TrezorClient",
address_n: "Address",
show_display: bool = False,
chunkify: bool = False,
) -> str:
) -> messages.StellarAddress:
return client.call(
messages.StellarGetAddress(
address_n=address_n, show_display=show_display, chunkify=chunkify
),
expect=messages.StellarAddress,
).address
)
def sign_tx(

View File

@ -14,7 +14,7 @@
# You should have received a copy of the License along with this library.
# If not, see <https://www.gnu.org/licenses/lgpl-3.0.html>.
from typing import TYPE_CHECKING
from typing import TYPE_CHECKING, Any
from . import messages
@ -23,18 +23,22 @@ if TYPE_CHECKING:
from .tools import Address
def get_address(
def get_address(*args: Any, **kwargs: Any) -> str:
return get_authenticated_address(*args, **kwargs).address
def get_authenticated_address(
client: "TrezorClient",
address_n: "Address",
show_display: bool = False,
chunkify: bool = False,
) -> str:
) -> messages.TezosAddress:
return client.call(
messages.TezosGetAddress(
address_n=address_n, show_display=show_display, chunkify=chunkify
),
expect=messages.TezosAddress,
).address
)
def get_public_key(