mirror of
https://github.com/trezor/trezor-firmware.git
synced 2025-01-03 12:00:59 +00:00
feat(cardano): show governance registration reward address credentials
This commit is contained in:
parent
a94cfa1a13
commit
ac58c1c25b
@ -44,6 +44,8 @@ ADDRESS_TYPES_PAYMENT_SCRIPT = (
|
||||
CardanoAddressType.ENTERPRISE_SCRIPT,
|
||||
)
|
||||
|
||||
ADDRESS_TYPES_PAYMENT = ADDRESS_TYPES_PAYMENT_KEY + ADDRESS_TYPES_PAYMENT_SCRIPT
|
||||
|
||||
_MIN_ADDRESS_BYTES_LENGTH = const(29)
|
||||
_MAX_ADDRESS_BYTES_LENGTH = const(65)
|
||||
|
||||
|
@ -2,7 +2,7 @@ from micropython import const
|
||||
from typing import TYPE_CHECKING
|
||||
|
||||
from trezor.crypto import hashlib
|
||||
from trezor.enums import CardanoGovernanceRegistrationFormat
|
||||
from trezor.enums import CardanoAddressType, CardanoGovernanceRegistrationFormat
|
||||
|
||||
from apps.common import cbor
|
||||
|
||||
@ -137,6 +137,14 @@ async def show(
|
||||
await layout.show_auxiliary_data_hash(ctx, auxiliary_data_hash)
|
||||
|
||||
|
||||
def _should_show_payment_warning(address_type: CardanoAddressType) -> bool:
|
||||
# For non-payment governance reward addresses, we show a warning that the address is not
|
||||
# actually eligible for rewards. https://github.com/cardano-foundation/CIPs/pull/373
|
||||
# However, the registration is otherwise valid, so we allow such addresses since we don't
|
||||
# want to prevent the user from voting just because they use an outdated SW wallet.
|
||||
return address_type not in addresses.ADDRESS_TYPES_PAYMENT
|
||||
|
||||
|
||||
async def _show_governance_registration(
|
||||
ctx: Context,
|
||||
keychain: seed.Keychain,
|
||||
@ -146,6 +154,7 @@ async def _show_governance_registration(
|
||||
should_show_details: bool,
|
||||
) -> None:
|
||||
from .helpers import bech32
|
||||
from .helpers.credential import Credential, should_show_credentials
|
||||
|
||||
for delegation in parameters.delegations:
|
||||
encoded_public_key = bech32.encode(
|
||||
@ -155,25 +164,34 @@ async def _show_governance_registration(
|
||||
ctx, encoded_public_key, delegation.weight
|
||||
)
|
||||
|
||||
if parameters.reward_address:
|
||||
show_payment_warning = _should_show_payment_warning(
|
||||
addresses.get_type(addresses.get_bytes_unsafe(parameters.reward_address))
|
||||
)
|
||||
await layout.confirm_governance_registration_reward_address(
|
||||
ctx, parameters.reward_address, show_payment_warning
|
||||
)
|
||||
else:
|
||||
address_parameters = parameters.reward_address_parameters
|
||||
assert address_parameters # _validate_governance_registration_parameters
|
||||
show_both_credentials = should_show_credentials(address_parameters)
|
||||
show_payment_warning = _should_show_payment_warning(
|
||||
address_parameters.address_type
|
||||
)
|
||||
await layout.show_governance_registration_reward_credentials(
|
||||
ctx,
|
||||
Credential.payment_credential(address_parameters),
|
||||
Credential.stake_credential(address_parameters),
|
||||
show_both_credentials,
|
||||
show_payment_warning,
|
||||
)
|
||||
|
||||
encoded_public_key: str | None = None
|
||||
if parameters.voting_public_key:
|
||||
encoded_public_key = bech32.encode(
|
||||
bech32.HRP_GOVERNANCE_PUBLIC_KEY, parameters.voting_public_key
|
||||
)
|
||||
|
||||
if parameters.reward_address:
|
||||
reward_address = parameters.reward_address
|
||||
else:
|
||||
assert (
|
||||
parameters.reward_address_parameters
|
||||
) # _validate_governance_registration_parameters
|
||||
reward_address = addresses.derive_human_readable(
|
||||
keychain,
|
||||
parameters.reward_address_parameters,
|
||||
protocol_magic,
|
||||
network_id,
|
||||
)
|
||||
|
||||
voting_purpose: int | None = (
|
||||
_get_voting_purpose_to_serialize(parameters) if should_show_details else None
|
||||
)
|
||||
@ -182,7 +200,6 @@ async def _show_governance_registration(
|
||||
ctx,
|
||||
encoded_public_key,
|
||||
parameters.staking_path,
|
||||
reward_address,
|
||||
parameters.nonce,
|
||||
voting_purpose,
|
||||
)
|
||||
|
@ -68,6 +68,10 @@ CERTIFICATE_TYPE_NAMES = {
|
||||
|
||||
BRT_Other = ButtonRequestType.Other # global_import_cache
|
||||
|
||||
GOVERNANCE_REWARD_ELIGIBILITY_WARNING = (
|
||||
"Warning: The address is not a payment address, it is not eligible for rewards."
|
||||
)
|
||||
|
||||
|
||||
def format_coin_amount(amount: int, network_id: int) -> str:
|
||||
from .helpers import network_ids
|
||||
@ -327,8 +331,8 @@ async def show_credentials(
|
||||
stake_credential: Credential,
|
||||
) -> None:
|
||||
intro_text = "Address"
|
||||
await _show_credential(ctx, payment_credential, intro_text, is_output=False)
|
||||
await _show_credential(ctx, stake_credential, intro_text, is_output=False)
|
||||
await _show_credential(ctx, payment_credential, intro_text, purpose="address")
|
||||
await _show_credential(ctx, stake_credential, intro_text, purpose="address")
|
||||
|
||||
|
||||
async def show_change_output_credentials(
|
||||
@ -337,8 +341,8 @@ async def show_change_output_credentials(
|
||||
stake_credential: Credential,
|
||||
) -> None:
|
||||
intro_text = "The following address is a change address. Its"
|
||||
await _show_credential(ctx, payment_credential, intro_text, is_output=True)
|
||||
await _show_credential(ctx, stake_credential, intro_text, is_output=True)
|
||||
await _show_credential(ctx, payment_credential, intro_text, purpose="output")
|
||||
await _show_credential(ctx, stake_credential, intro_text, purpose="output")
|
||||
|
||||
|
||||
async def show_device_owned_output_credentials(
|
||||
@ -348,22 +352,47 @@ async def show_device_owned_output_credentials(
|
||||
show_both_credentials: bool,
|
||||
) -> None:
|
||||
intro_text = "The following address is owned by this device. Its"
|
||||
await _show_credential(ctx, payment_credential, intro_text, is_output=True)
|
||||
await _show_credential(ctx, payment_credential, intro_text, purpose="output")
|
||||
if show_both_credentials:
|
||||
await _show_credential(ctx, stake_credential, intro_text, is_output=True)
|
||||
await _show_credential(ctx, stake_credential, intro_text, purpose="output")
|
||||
|
||||
|
||||
async def show_governance_registration_reward_credentials(
|
||||
ctx: Context,
|
||||
payment_credential: Credential,
|
||||
stake_credential: Credential,
|
||||
show_both_credentials: bool,
|
||||
show_payment_warning: bool,
|
||||
) -> None:
|
||||
intro_text = "The governance registration reward address is owned by this device. Its"
|
||||
await _show_credential(
|
||||
ctx, payment_credential, intro_text, purpose="gov_reg_reward_address"
|
||||
)
|
||||
if show_both_credentials or show_payment_warning:
|
||||
extra_text = (
|
||||
GOVERNANCE_REWARD_ELIGIBILITY_WARNING if show_payment_warning else None
|
||||
)
|
||||
await _show_credential(
|
||||
ctx,
|
||||
stake_credential,
|
||||
intro_text,
|
||||
purpose="gov_reg_reward_address",
|
||||
extra_text=extra_text,
|
||||
)
|
||||
|
||||
|
||||
async def _show_credential(
|
||||
ctx: Context,
|
||||
credential: Credential,
|
||||
intro_text: str,
|
||||
is_output: bool,
|
||||
purpose: Literal["address", "output", "gov_reg_reward_address"],
|
||||
extra_text: str | None = None,
|
||||
) -> None:
|
||||
title = (
|
||||
"Confirm transaction"
|
||||
if is_output
|
||||
else f"{ADDRESS_TYPE_NAMES[credential.address_type]} address"
|
||||
)
|
||||
title = {
|
||||
"address": f"{ADDRESS_TYPE_NAMES[credential.address_type]} address",
|
||||
"output": "Confirm transaction",
|
||||
"gov_reg_reward_address": "Confirm transaction",
|
||||
}[purpose]
|
||||
|
||||
props: list[PropertyType] = []
|
||||
append = props.append # local_cache_attribute
|
||||
@ -385,7 +414,8 @@ async def _show_credential(
|
||||
append((None, "Path is unusual."))
|
||||
if credential.is_mismatch:
|
||||
append((None, "Credential doesn't match payment credential."))
|
||||
if credential.is_reward:
|
||||
if credential.is_reward and purpose != "gov_reg_reward_address":
|
||||
# for governance registrations, this is handled by extra_text at the end
|
||||
append(("Address is a reward address.", None))
|
||||
if credential.is_no_staking:
|
||||
append(
|
||||
@ -395,13 +425,17 @@ async def _show_credential(
|
||||
)
|
||||
)
|
||||
|
||||
await confirm_properties(
|
||||
ctx,
|
||||
"confirm_credential",
|
||||
title,
|
||||
props,
|
||||
br_code=BRT_Other,
|
||||
)
|
||||
if extra_text:
|
||||
append((extra_text, None))
|
||||
|
||||
if len(props) > 0:
|
||||
await confirm_properties(
|
||||
ctx,
|
||||
"confirm_credential",
|
||||
title,
|
||||
props,
|
||||
br_code=BRT_Other,
|
||||
)
|
||||
|
||||
|
||||
async def warn_path(ctx: Context, path: list[int], title: str) -> None:
|
||||
@ -762,11 +796,30 @@ async def confirm_governance_registration_delegation(
|
||||
)
|
||||
|
||||
|
||||
async def confirm_governance_registration_reward_address(
|
||||
ctx: Context,
|
||||
reward_address: str,
|
||||
should_show_payment_warning: bool,
|
||||
) -> None:
|
||||
props = [
|
||||
("Governance voting key registration", None),
|
||||
("Rewards go to:", reward_address),
|
||||
]
|
||||
if should_show_payment_warning:
|
||||
props.append((GOVERNANCE_REWARD_ELIGIBILITY_WARNING, None))
|
||||
await confirm_properties(
|
||||
ctx,
|
||||
"confirm_governance_registration_reward_address",
|
||||
title="Confirm transaction",
|
||||
props=props,
|
||||
br_code=ButtonRequestType.Other,
|
||||
)
|
||||
|
||||
|
||||
async def confirm_governance_registration(
|
||||
ctx: Context,
|
||||
public_key: str | None,
|
||||
staking_path: list[int],
|
||||
reward_address: str,
|
||||
nonce: int,
|
||||
voting_purpose: int | None,
|
||||
) -> None:
|
||||
@ -779,7 +832,6 @@ async def confirm_governance_registration(
|
||||
f"Staking key for account {format_account_number(staking_path)}:",
|
||||
address_n_to_str(staking_path),
|
||||
),
|
||||
("Rewards go to:", reward_address),
|
||||
("Nonce:", str(nonce)),
|
||||
]
|
||||
)
|
||||
|
Loading…
Reference in New Issue
Block a user