|
|
@ -56,6 +56,7 @@ from .certificates import (
|
|
|
|
validate_pool_relay,
|
|
|
|
validate_pool_relay,
|
|
|
|
)
|
|
|
|
)
|
|
|
|
from .helpers import (
|
|
|
|
from .helpers import (
|
|
|
|
|
|
|
|
INVALID_OUTPUT,
|
|
|
|
INVALID_STAKE_POOL_REGISTRATION_TX_STRUCTURE,
|
|
|
|
INVALID_STAKE_POOL_REGISTRATION_TX_STRUCTURE,
|
|
|
|
INVALID_STAKEPOOL_REGISTRATION_TX_WITNESSES,
|
|
|
|
INVALID_STAKEPOOL_REGISTRATION_TX_WITNESSES,
|
|
|
|
INVALID_TOKEN_BUNDLE_OUTPUT,
|
|
|
|
INVALID_TOKEN_BUNDLE_OUTPUT,
|
|
|
@ -65,17 +66,14 @@ from .helpers import (
|
|
|
|
protocol_magics,
|
|
|
|
protocol_magics,
|
|
|
|
staking_use_cases,
|
|
|
|
staking_use_cases,
|
|
|
|
)
|
|
|
|
)
|
|
|
|
|
|
|
|
from .helpers.account_path_check import AccountPathChecker
|
|
|
|
from .helpers.hash_builder_collection import HashBuilderDict, HashBuilderList
|
|
|
|
from .helpers.hash_builder_collection import HashBuilderDict, HashBuilderList
|
|
|
|
from .helpers.paths import (
|
|
|
|
from .helpers.paths import (
|
|
|
|
ACCOUNT_PATH_INDEX,
|
|
|
|
|
|
|
|
BIP_PATH_LENGTH,
|
|
|
|
|
|
|
|
CERTIFICATE_PATH_NAME,
|
|
|
|
CERTIFICATE_PATH_NAME,
|
|
|
|
CHANGE_OUTPUT_PATH_NAME,
|
|
|
|
CHANGE_OUTPUT_PATH_NAME,
|
|
|
|
CHANGE_OUTPUT_STAKING_PATH_NAME,
|
|
|
|
CHANGE_OUTPUT_STAKING_PATH_NAME,
|
|
|
|
MAX_SAFE_ACCOUNT_INDEX,
|
|
|
|
|
|
|
|
MAX_SAFE_CHANGE_ADDRESS_INDEX,
|
|
|
|
|
|
|
|
POOL_OWNER_STAKING_PATH_NAME,
|
|
|
|
POOL_OWNER_STAKING_PATH_NAME,
|
|
|
|
SCHEMA_ADDRESS,
|
|
|
|
SCHEMA_PAYMENT,
|
|
|
|
SCHEMA_STAKING,
|
|
|
|
SCHEMA_STAKING,
|
|
|
|
SCHEMA_STAKING_ANY_ACCOUNT,
|
|
|
|
SCHEMA_STAKING_ANY_ACCOUNT,
|
|
|
|
WITNESS_PATH_NAME,
|
|
|
|
WITNESS_PATH_NAME,
|
|
|
@ -139,18 +137,25 @@ async def sign_tx(
|
|
|
|
)
|
|
|
|
)
|
|
|
|
)
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
account_path_checker = AccountPathChecker()
|
|
|
|
|
|
|
|
|
|
|
|
hash_fn = hashlib.blake2b(outlen=32)
|
|
|
|
hash_fn = hashlib.blake2b(outlen=32)
|
|
|
|
tx_dict: HashBuilderDict[int, Any] = HashBuilderDict(tx_body_map_item_count)
|
|
|
|
tx_dict: HashBuilderDict[int, Any] = HashBuilderDict(tx_body_map_item_count)
|
|
|
|
tx_dict.start(hash_fn)
|
|
|
|
tx_dict.start(hash_fn)
|
|
|
|
with tx_dict:
|
|
|
|
with tx_dict:
|
|
|
|
await _process_transaction(ctx, msg, keychain, tx_dict)
|
|
|
|
await _process_transaction(ctx, msg, keychain, tx_dict, account_path_checker)
|
|
|
|
|
|
|
|
|
|
|
|
await _confirm_transaction(ctx, msg, is_network_id_verifiable)
|
|
|
|
await _confirm_transaction(ctx, msg, is_network_id_verifiable)
|
|
|
|
|
|
|
|
|
|
|
|
try:
|
|
|
|
try:
|
|
|
|
tx_hash = hash_fn.digest()
|
|
|
|
tx_hash = hash_fn.digest()
|
|
|
|
response_after_witness_requests = await _process_witness_requests(
|
|
|
|
response_after_witness_requests = await _process_witness_requests(
|
|
|
|
ctx, keychain, tx_hash, msg.witness_requests_count, msg.signing_mode
|
|
|
|
ctx,
|
|
|
|
|
|
|
|
keychain,
|
|
|
|
|
|
|
|
tx_hash,
|
|
|
|
|
|
|
|
msg.witness_requests_count,
|
|
|
|
|
|
|
|
msg.signing_mode,
|
|
|
|
|
|
|
|
account_path_checker,
|
|
|
|
)
|
|
|
|
)
|
|
|
|
await ctx.call(response_after_witness_requests, CardanoTxHostAck)
|
|
|
|
await ctx.call(response_after_witness_requests, CardanoTxHostAck)
|
|
|
|
|
|
|
|
|
|
|
@ -186,6 +191,7 @@ async def _process_transaction(
|
|
|
|
msg: CardanoSignTxInit,
|
|
|
|
msg: CardanoSignTxInit,
|
|
|
|
keychain: seed.Keychain,
|
|
|
|
keychain: seed.Keychain,
|
|
|
|
tx_dict: HashBuilderDict,
|
|
|
|
tx_dict: HashBuilderDict,
|
|
|
|
|
|
|
|
account_path_checker: AccountPathChecker,
|
|
|
|
) -> None:
|
|
|
|
) -> None:
|
|
|
|
inputs_list: HashBuilderList[tuple[bytes, int]] = HashBuilderList(msg.inputs_count)
|
|
|
|
inputs_list: HashBuilderList[tuple[bytes, int]] = HashBuilderList(msg.inputs_count)
|
|
|
|
with tx_dict.add(TX_BODY_KEY_INPUTS, inputs_list):
|
|
|
|
with tx_dict.add(TX_BODY_KEY_INPUTS, inputs_list):
|
|
|
@ -201,6 +207,7 @@ async def _process_transaction(
|
|
|
|
msg.signing_mode,
|
|
|
|
msg.signing_mode,
|
|
|
|
msg.protocol_magic,
|
|
|
|
msg.protocol_magic,
|
|
|
|
msg.network_id,
|
|
|
|
msg.network_id,
|
|
|
|
|
|
|
|
account_path_checker,
|
|
|
|
)
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
|
|
tx_dict.add(TX_BODY_KEY_FEE, msg.fee)
|
|
|
|
tx_dict.add(TX_BODY_KEY_FEE, msg.fee)
|
|
|
@ -219,6 +226,7 @@ async def _process_transaction(
|
|
|
|
msg.signing_mode,
|
|
|
|
msg.signing_mode,
|
|
|
|
msg.protocol_magic,
|
|
|
|
msg.protocol_magic,
|
|
|
|
msg.network_id,
|
|
|
|
msg.network_id,
|
|
|
|
|
|
|
|
account_path_checker,
|
|
|
|
)
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
|
|
if msg.withdrawals_count > 0:
|
|
|
|
if msg.withdrawals_count > 0:
|
|
|
@ -233,6 +241,7 @@ async def _process_transaction(
|
|
|
|
msg.withdrawals_count,
|
|
|
|
msg.withdrawals_count,
|
|
|
|
msg.protocol_magic,
|
|
|
|
msg.protocol_magic,
|
|
|
|
msg.network_id,
|
|
|
|
msg.network_id,
|
|
|
|
|
|
|
|
account_path_checker,
|
|
|
|
)
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
|
|
if msg.has_auxiliary_data:
|
|
|
|
if msg.has_auxiliary_data:
|
|
|
@ -287,12 +296,13 @@ async def _process_outputs(
|
|
|
|
signing_mode: CardanoTxSigningMode,
|
|
|
|
signing_mode: CardanoTxSigningMode,
|
|
|
|
protocol_magic: int,
|
|
|
|
protocol_magic: int,
|
|
|
|
network_id: int,
|
|
|
|
network_id: int,
|
|
|
|
|
|
|
|
account_path_checker: AccountPathChecker,
|
|
|
|
) -> None:
|
|
|
|
) -> None:
|
|
|
|
"""Read, validate, confirm and serialize the outputs, return the total non-change output amount."""
|
|
|
|
"""Read, validate, confirm and serialize the outputs, return the total non-change output amount."""
|
|
|
|
total_amount = 0
|
|
|
|
total_amount = 0
|
|
|
|
for _ in range(outputs_count):
|
|
|
|
for _ in range(outputs_count):
|
|
|
|
output: CardanoTxOutput = await ctx.call(CardanoTxItemAck(), CardanoTxOutput)
|
|
|
|
output: CardanoTxOutput = await ctx.call(CardanoTxItemAck(), CardanoTxOutput)
|
|
|
|
_validate_output(output, protocol_magic, network_id)
|
|
|
|
_validate_output(output, protocol_magic, network_id, account_path_checker)
|
|
|
|
if signing_mode == CardanoTxSigningMode.ORDINARY_TRANSACTION:
|
|
|
|
if signing_mode == CardanoTxSigningMode.ORDINARY_TRANSACTION:
|
|
|
|
await _show_output(
|
|
|
|
await _show_output(
|
|
|
|
ctx,
|
|
|
|
ctx,
|
|
|
@ -393,6 +403,7 @@ async def _process_certificates(
|
|
|
|
signing_mode: CardanoTxSigningMode,
|
|
|
|
signing_mode: CardanoTxSigningMode,
|
|
|
|
protocol_magic: int,
|
|
|
|
protocol_magic: int,
|
|
|
|
network_id: int,
|
|
|
|
network_id: int,
|
|
|
|
|
|
|
|
account_path_checker: AccountPathChecker,
|
|
|
|
) -> None:
|
|
|
|
) -> None:
|
|
|
|
"""Read, validate, confirm and serialize the certificates."""
|
|
|
|
"""Read, validate, confirm and serialize the certificates."""
|
|
|
|
if certificates_count == 0:
|
|
|
|
if certificates_count == 0:
|
|
|
@ -402,7 +413,9 @@ async def _process_certificates(
|
|
|
|
certificate: CardanoTxCertificate = await ctx.call(
|
|
|
|
certificate: CardanoTxCertificate = await ctx.call(
|
|
|
|
CardanoTxItemAck(), CardanoTxCertificate
|
|
|
|
CardanoTxItemAck(), CardanoTxCertificate
|
|
|
|
)
|
|
|
|
)
|
|
|
|
validate_certificate(certificate, signing_mode, protocol_magic, network_id)
|
|
|
|
validate_certificate(
|
|
|
|
|
|
|
|
certificate, signing_mode, protocol_magic, network_id, account_path_checker
|
|
|
|
|
|
|
|
)
|
|
|
|
await _show_certificate(ctx, certificate, signing_mode)
|
|
|
|
await _show_certificate(ctx, certificate, signing_mode)
|
|
|
|
|
|
|
|
|
|
|
|
if certificate.type == CardanoCertificateType.STAKE_POOL_REGISTRATION:
|
|
|
|
if certificate.type == CardanoCertificateType.STAKE_POOL_REGISTRATION:
|
|
|
@ -428,6 +441,7 @@ async def _process_certificates(
|
|
|
|
pool_owners_list,
|
|
|
|
pool_owners_list,
|
|
|
|
pool_parameters.owners_count,
|
|
|
|
pool_parameters.owners_count,
|
|
|
|
network_id,
|
|
|
|
network_id,
|
|
|
|
|
|
|
|
account_path_checker,
|
|
|
|
)
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
|
|
relays_list: HashBuilderList[cbor.CborSequence] = HashBuilderList(
|
|
|
|
relays_list: HashBuilderList[cbor.CborSequence] = HashBuilderList(
|
|
|
@ -449,11 +463,12 @@ async def _process_pool_owners(
|
|
|
|
pool_owners_list: HashBuilderList[bytes],
|
|
|
|
pool_owners_list: HashBuilderList[bytes],
|
|
|
|
owners_count: int,
|
|
|
|
owners_count: int,
|
|
|
|
network_id: int,
|
|
|
|
network_id: int,
|
|
|
|
|
|
|
|
account_path_checker: AccountPathChecker,
|
|
|
|
) -> None:
|
|
|
|
) -> None:
|
|
|
|
owners_as_path_count = 0
|
|
|
|
owners_as_path_count = 0
|
|
|
|
for _ in range(owners_count):
|
|
|
|
for _ in range(owners_count):
|
|
|
|
owner: CardanoPoolOwner = await ctx.call(CardanoTxItemAck(), CardanoPoolOwner)
|
|
|
|
owner: CardanoPoolOwner = await ctx.call(CardanoTxItemAck(), CardanoPoolOwner)
|
|
|
|
validate_pool_owner(owner)
|
|
|
|
validate_pool_owner(owner, account_path_checker)
|
|
|
|
await _show_pool_owner(ctx, keychain, owner, network_id)
|
|
|
|
await _show_pool_owner(ctx, keychain, owner, network_id)
|
|
|
|
|
|
|
|
|
|
|
|
pool_owners_list.append(cborize_pool_owner(keychain, owner))
|
|
|
|
pool_owners_list.append(cborize_pool_owner(keychain, owner))
|
|
|
@ -484,6 +499,7 @@ async def _process_withdrawals(
|
|
|
|
withdrawals_count: int,
|
|
|
|
withdrawals_count: int,
|
|
|
|
protocol_magic: int,
|
|
|
|
protocol_magic: int,
|
|
|
|
network_id: int,
|
|
|
|
network_id: int,
|
|
|
|
|
|
|
|
account_path_checker: AccountPathChecker,
|
|
|
|
) -> None:
|
|
|
|
) -> None:
|
|
|
|
"""Read, validate, confirm and serialize the withdrawals."""
|
|
|
|
"""Read, validate, confirm and serialize the withdrawals."""
|
|
|
|
if withdrawals_count == 0:
|
|
|
|
if withdrawals_count == 0:
|
|
|
@ -496,7 +512,7 @@ async def _process_withdrawals(
|
|
|
|
withdrawal: CardanoTxWithdrawal = await ctx.call(
|
|
|
|
withdrawal: CardanoTxWithdrawal = await ctx.call(
|
|
|
|
CardanoTxItemAck(), CardanoTxWithdrawal
|
|
|
|
CardanoTxItemAck(), CardanoTxWithdrawal
|
|
|
|
)
|
|
|
|
)
|
|
|
|
_validate_withdrawal(withdrawal, seen_withdrawals)
|
|
|
|
_validate_withdrawal(withdrawal, seen_withdrawals, account_path_checker)
|
|
|
|
await confirm_withdrawal(ctx, withdrawal)
|
|
|
|
await confirm_withdrawal(ctx, withdrawal)
|
|
|
|
reward_address = derive_address_bytes(
|
|
|
|
reward_address = derive_address_bytes(
|
|
|
|
keychain,
|
|
|
|
keychain,
|
|
|
@ -551,11 +567,12 @@ async def _process_witness_requests(
|
|
|
|
tx_hash: bytes,
|
|
|
|
tx_hash: bytes,
|
|
|
|
witness_requests_count: int,
|
|
|
|
witness_requests_count: int,
|
|
|
|
signing_mode: CardanoTxSigningMode,
|
|
|
|
signing_mode: CardanoTxSigningMode,
|
|
|
|
|
|
|
|
account_path_checker: AccountPathChecker,
|
|
|
|
) -> CardanoTxResponseType:
|
|
|
|
) -> CardanoTxResponseType:
|
|
|
|
response: CardanoTxResponseType = CardanoTxItemAck()
|
|
|
|
response: CardanoTxResponseType = CardanoTxItemAck()
|
|
|
|
for _ in range(witness_requests_count):
|
|
|
|
for _ in range(witness_requests_count):
|
|
|
|
witness_request = await ctx.call(response, CardanoTxWitnessRequest)
|
|
|
|
witness_request = await ctx.call(response, CardanoTxWitnessRequest)
|
|
|
|
_validate_witness(signing_mode, witness_request)
|
|
|
|
_validate_witness_request(witness_request, signing_mode, account_path_checker)
|
|
|
|
await _show_witness(ctx, witness_request.path)
|
|
|
|
await _show_witness(ctx, witness_request.path)
|
|
|
|
|
|
|
|
|
|
|
|
response = (
|
|
|
|
response = (
|
|
|
@ -616,21 +633,22 @@ def _validate_stake_pool_registration_tx_structure(msg: CardanoSignTxInit) -> No
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def _validate_output(
|
|
|
|
def _validate_output(
|
|
|
|
output: CardanoTxOutput, protocol_magic: int, network_id: int
|
|
|
|
output: CardanoTxOutput,
|
|
|
|
|
|
|
|
protocol_magic: int,
|
|
|
|
|
|
|
|
network_id: int,
|
|
|
|
|
|
|
|
account_path_checker: AccountPathChecker,
|
|
|
|
) -> None:
|
|
|
|
) -> None:
|
|
|
|
if output.address_parameters and output.address is not None:
|
|
|
|
if output.address_parameters and output.address is not None:
|
|
|
|
raise wire.ProcessError(
|
|
|
|
raise INVALID_OUTPUT
|
|
|
|
"Outputs can not contain both address and address_parameters fields!"
|
|
|
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if output.address_parameters:
|
|
|
|
if output.address_parameters:
|
|
|
|
validate_address_parameters(output.address_parameters)
|
|
|
|
validate_address_parameters(output.address_parameters)
|
|
|
|
elif output.address is not None:
|
|
|
|
elif output.address is not None:
|
|
|
|
validate_output_address(output.address, protocol_magic, network_id)
|
|
|
|
validate_output_address(output.address, protocol_magic, network_id)
|
|
|
|
else:
|
|
|
|
else:
|
|
|
|
raise wire.ProcessError(
|
|
|
|
raise INVALID_OUTPUT
|
|
|
|
"Each output must have an address field or address_parameters!"
|
|
|
|
|
|
|
|
)
|
|
|
|
account_path_checker.add_output(output)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
async def _show_output(
|
|
|
|
async def _show_output(
|
|
|
@ -644,7 +662,7 @@ async def _show_output(
|
|
|
|
if output.address_parameters:
|
|
|
|
if output.address_parameters:
|
|
|
|
await _fail_or_warn_if_invalid_path(
|
|
|
|
await _fail_or_warn_if_invalid_path(
|
|
|
|
ctx,
|
|
|
|
ctx,
|
|
|
|
SCHEMA_ADDRESS,
|
|
|
|
SCHEMA_PAYMENT,
|
|
|
|
output.address_parameters.address_n,
|
|
|
|
output.address_parameters.address_n,
|
|
|
|
CHANGE_OUTPUT_PATH_NAME,
|
|
|
|
CHANGE_OUTPUT_PATH_NAME,
|
|
|
|
)
|
|
|
|
)
|
|
|
@ -703,7 +721,9 @@ async def _show_certificate(
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def _validate_withdrawal(
|
|
|
|
def _validate_withdrawal(
|
|
|
|
withdrawal: CardanoTxWithdrawal, seen_withdrawals: set[tuple[int, ...]]
|
|
|
|
withdrawal: CardanoTxWithdrawal,
|
|
|
|
|
|
|
|
seen_withdrawals: set[tuple[int, ...]],
|
|
|
|
|
|
|
|
account_path_checker: AccountPathChecker,
|
|
|
|
) -> None:
|
|
|
|
) -> None:
|
|
|
|
if not SCHEMA_STAKING_ANY_ACCOUNT.match(withdrawal.path):
|
|
|
|
if not SCHEMA_STAKING_ANY_ACCOUNT.match(withdrawal.path):
|
|
|
|
raise INVALID_WITHDRAWAL
|
|
|
|
raise INVALID_WITHDRAWAL
|
|
|
@ -717,6 +737,8 @@ def _validate_withdrawal(
|
|
|
|
else:
|
|
|
|
else:
|
|
|
|
seen_withdrawals.add(path_tuple)
|
|
|
|
seen_withdrawals.add(path_tuple)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
account_path_checker.add_withdrawal(withdrawal)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def _get_output_address(
|
|
|
|
def _get_output_address(
|
|
|
|
keychain: seed.Keychain,
|
|
|
|
keychain: seed.Keychain,
|
|
|
@ -768,14 +790,17 @@ async def _show_pool_owner(
|
|
|
|
await confirm_stake_pool_owner(ctx, keychain, owner, network_id)
|
|
|
|
await confirm_stake_pool_owner(ctx, keychain, owner, network_id)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def _validate_witness(
|
|
|
|
def _validate_witness_request(
|
|
|
|
|
|
|
|
witness_request: CardanoTxWitnessRequest,
|
|
|
|
signing_mode: CardanoTxSigningMode,
|
|
|
|
signing_mode: CardanoTxSigningMode,
|
|
|
|
witness: CardanoTxWitnessRequest,
|
|
|
|
account_path_checker: AccountPathChecker,
|
|
|
|
) -> None:
|
|
|
|
) -> None:
|
|
|
|
# witness path validation happens in _show_witness
|
|
|
|
# witness path validation happens in _show_witness
|
|
|
|
|
|
|
|
|
|
|
|
if signing_mode == CardanoTxSigningMode.POOL_REGISTRATION_AS_OWNER:
|
|
|
|
if signing_mode == CardanoTxSigningMode.POOL_REGISTRATION_AS_OWNER:
|
|
|
|
_ensure_no_payment_witness(witness)
|
|
|
|
_ensure_no_payment_witness(witness_request)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
account_path_checker.add_witness_request(witness_request)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def _ensure_no_payment_witness(witness: CardanoTxWitnessRequest) -> None:
|
|
|
|
def _ensure_no_payment_witness(witness: CardanoTxWitnessRequest) -> None:
|
|
|
@ -799,12 +824,14 @@ async def _show_witness(
|
|
|
|
ctx: wire.Context,
|
|
|
|
ctx: wire.Context,
|
|
|
|
witness_path: list[int],
|
|
|
|
witness_path: list[int],
|
|
|
|
) -> None:
|
|
|
|
) -> None:
|
|
|
|
await _fail_or_warn_if_invalid_path(
|
|
|
|
if not SCHEMA_PAYMENT.match(witness_path) and not SCHEMA_STAKING.match(
|
|
|
|
ctx,
|
|
|
|
witness_path
|
|
|
|
SCHEMA_ADDRESS,
|
|
|
|
):
|
|
|
|
witness_path,
|
|
|
|
await _fail_or_warn_path(
|
|
|
|
WITNESS_PATH_NAME,
|
|
|
|
ctx,
|
|
|
|
)
|
|
|
|
witness_path,
|
|
|
|
|
|
|
|
WITNESS_PATH_NAME,
|
|
|
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
async def _show_change_output_staking_warnings(
|
|
|
|
async def _show_change_output_staking_warnings(
|
|
|
@ -856,19 +883,14 @@ async def _show_change_output_staking_warnings(
|
|
|
|
|
|
|
|
|
|
|
|
def _should_hide_output(path: list[int]) -> bool:
|
|
|
|
def _should_hide_output(path: list[int]) -> bool:
|
|
|
|
"""Return whether the output address is from a safe path, so it could be hidden."""
|
|
|
|
"""Return whether the output address is from a safe path, so it could be hidden."""
|
|
|
|
return (
|
|
|
|
return SCHEMA_PAYMENT.match(path)
|
|
|
|
len(path) == BIP_PATH_LENGTH
|
|
|
|
|
|
|
|
and path[ACCOUNT_PATH_INDEX] <= MAX_SAFE_ACCOUNT_INDEX
|
|
|
|
|
|
|
|
and path[-2] < 2
|
|
|
|
|
|
|
|
and path[-1] < MAX_SAFE_CHANGE_ADDRESS_INDEX
|
|
|
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def _should_show_tokens(
|
|
|
|
def _should_show_tokens(
|
|
|
|
output: CardanoTxOutput, signing_mode: CardanoTxSigningMode
|
|
|
|
output: CardanoTxOutput, signing_mode: CardanoTxSigningMode
|
|
|
|
) -> bool:
|
|
|
|
) -> bool:
|
|
|
|
if signing_mode != CardanoTxSigningMode.ORDINARY_TRANSACTION:
|
|
|
|
if signing_mode != CardanoTxSigningMode.ORDINARY_TRANSACTION:
|
|
|
|
return True
|
|
|
|
return False
|
|
|
|
|
|
|
|
|
|
|
|
if output.address_parameters:
|
|
|
|
if output.address_parameters:
|
|
|
|
return not _should_hide_output(output.address_parameters.address_n)
|
|
|
|
return not _should_hide_output(output.address_parameters.address_n)
|
|
|
@ -893,7 +915,13 @@ async def _fail_or_warn_if_invalid_path(
|
|
|
|
ctx: wire.Context, schema: PathSchema, path: list[int], path_name: str
|
|
|
|
ctx: wire.Context, schema: PathSchema, path: list[int], path_name: str
|
|
|
|
) -> None:
|
|
|
|
) -> None:
|
|
|
|
if not schema.match(path):
|
|
|
|
if not schema.match(path):
|
|
|
|
if safety_checks.is_strict():
|
|
|
|
await _fail_or_warn_path(ctx, path, path_name)
|
|
|
|
raise wire.DataError("Invalid %s" % path_name.lower())
|
|
|
|
|
|
|
|
else:
|
|
|
|
|
|
|
|
await show_warning_path(ctx, path, path_name)
|
|
|
|
async def _fail_or_warn_path(
|
|
|
|
|
|
|
|
ctx: wire.Context, path: list[int], path_name: str
|
|
|
|
|
|
|
|
) -> None:
|
|
|
|
|
|
|
|
if safety_checks.is_strict():
|
|
|
|
|
|
|
|
raise wire.DataError("Invalid %s" % path_name.lower())
|
|
|
|
|
|
|
|
else:
|
|
|
|
|
|
|
|
await show_warning_path(ctx, path, path_name)
|
|
|
|