feat(cardano): add support for hiding some details during tx signing

pull/2374/head
gabrielkerekes 2 years ago committed by matejcik
parent 2f9435570d
commit 1a68650c43

@ -313,6 +313,10 @@ Note that including `inline_datum` and/or `reference_script` requires using the
When one wants to spend funds from a Plutus script address (which is possible only in the Plutus signing mode), they have to attach the Plutus script body as well as the datum referenced in the UTXO (if they did not utilize `inline_datum` and `reference_script` with `reference_inputs`). A redeemer must be provided too. These items are outside the transaction body which is signed by Trezor, so their hash is included in the transaction body as `script_data_hash`.
### Level of details ("Show All"/"Show Simple")
With the introduction of Plutus scripts the transaction signing UI has become a pain for the users. There are many elements which an ordinary user has no chance to verify and they might only confuse and bother him during the transaction signing process. This is why we have introduced the option to hide some transaction elements by letting the user choose the level of details for the transaction signing. This is done by adding an initial screen to the transaction signing flow on which two buttons are displayed: "Show All" button to display all transaction details and a "Show Simple" button to only show the critical transaction details.
### Transaction Explorer
[Cardano explorer](https://explorer.cardano.org/en.html), [Cardanoscan](https://cardanoscan.io/).

@ -80,6 +80,7 @@ async def show(
| None,
protocol_magic: int,
network_id: int,
should_show_details: bool,
) -> None:
if catalyst_registration_parameters:
await _show_catalyst_registration(
@ -90,7 +91,8 @@ async def show(
network_id,
)
await show_auxiliary_data_hash(ctx, auxiliary_data_hash)
if should_show_details:
await show_auxiliary_data_hash(ctx, auxiliary_data_hash)
async def _show_catalyst_registration(

@ -81,3 +81,7 @@ class OrdinarySigner(Signer):
await layout.confirm_witness_request(self.ctx, witness_path)
elif not is_payment and not is_staking:
await self._fail_or_warn_path(witness_path, WITNESS_PATH_NAME)
else:
await self._show_if_showing_details(
layout.confirm_witness_request(self.ctx, witness_path)
)

@ -54,7 +54,7 @@ class PlutusSigner(Signer):
async def _show_input(self, input: messages.CardanoTxInput) -> None:
# super() omitted intentionally
# The inputs are not interchangeable (because of datums), so we must show them.
await layout.confirm_input(self.ctx, input)
await self._show_if_showing_details(layout.confirm_input(self.ctx, input))
async def _show_output_credentials(
self, address_parameters: messages.CardanoAddressParametersType
@ -74,6 +74,10 @@ class PlutusSigner(Signer):
# super() omitted intentionally
# All outputs need to be shown (even device-owned), because they might influence
# the script evaluation.
if self._is_simple_change_output(output):
# only display simple change outputs if showing details
return self.should_show_details
return True
def _is_change_output(self, output: messages.CardanoTxOutput) -> bool:

@ -104,11 +104,6 @@ class Signer:
self.msg = msg
self.keychain = keychain
# Some data (e.g. output inline datum) are too long to verify manually.
# We track their presence and eventually display the tx hash when
# confirming the tx.
self.has_hidden_data = False
self.account_path_checker = AccountPathChecker()
# Inputs, outputs and fee are mandatory, count the number of optional fields present.
@ -259,8 +254,8 @@ class Signer:
raise NotImplementedError
def _should_show_tx_hash(self) -> bool:
# By default, we display tx hash only if some data wasn't shown.
return self.has_hidden_data
# By default we display tx hash only if showing details
return self.should_show_details
# inputs
@ -407,12 +402,6 @@ class Signer:
Determines whether the output should be shown. Extracted from _show_output
because of readability.
"""
if (
output.datum_hash is not None
or output.inline_datum_size > 0
or output.reference_script_size > 0
):
return True
address_type = self._get_output_address_type(output)
if (
@ -424,8 +413,13 @@ class Signer:
return True
if self._is_simple_change_output(output):
# We don't need to display simple address outputs.
return False
# Show change output only if showing details and if it contains plutus data
has_plutus_data = (
output.datum_hash is not None
or output.inline_datum_size > 0
or output.reference_script_size > 0
)
return self.should_show_details and has_plutus_data
return True
@ -459,7 +453,9 @@ class Signer:
if output.datum_hash is not None:
if should_show:
await layout.confirm_datum_hash(self.ctx, output.datum_hash)
await self._show_if_showing_details(
layout.confirm_datum_hash(self.ctx, output.datum_hash)
)
output_list.append(output.datum_hash)
async def _process_babbage_output(
@ -486,7 +482,9 @@ class Signer:
if output.datum_hash is not None:
if should_show:
await layout.confirm_datum_hash(self.ctx, output.datum_hash)
await self._show_if_showing_details(
layout.confirm_datum_hash(self.ctx, output.datum_hash)
)
output_dict.add(
BABBAGE_OUTPUT_KEY_DATUM_OPTION,
(DATUM_OPTION_KEY_HASH, output.datum_hash),
@ -626,7 +624,6 @@ class Signer:
should_show: bool,
) -> None:
assert inline_datum_size > 0
self.has_hidden_data = True
chunks_count = self._get_chunks_count(inline_datum_size)
for chunk_number in range(chunks_count):
@ -640,8 +637,8 @@ class Signer:
wire.ProcessError("Invalid inline datum chunk"),
)
if chunk_number == 0 and should_show:
await layout.confirm_inline_datum(
self.ctx, chunk.data, inline_datum_size
await self._show_if_showing_details(
layout.confirm_inline_datum(self.ctx, chunk.data, inline_datum_size)
)
inline_datum_cbor.add(chunk.data)
@ -654,7 +651,6 @@ class Signer:
should_show: bool,
) -> None:
assert reference_script_size > 0
self.has_hidden_data = True
chunks_count = self._get_chunks_count(reference_script_size)
for chunk_number in range(chunks_count):
@ -668,8 +664,10 @@ class Signer:
wire.ProcessError("Invalid reference script chunk"),
)
if chunk_number == 0 and should_show:
await layout.confirm_reference_script(
self.ctx, chunk.data, reference_script_size
await self._show_if_showing_details(
layout.confirm_reference_script(
self.ctx, chunk.data, reference_script_size
)
)
reference_script_cbor.add(chunk.data)
@ -803,8 +801,10 @@ class Signer:
)
self._validate_withdrawal(withdrawal)
address_bytes = self._derive_withdrawal_address_bytes(withdrawal)
await layout.confirm_withdrawal(
self.ctx, withdrawal, address_bytes, self.msg.network_id
await self._show_if_showing_details(
layout.confirm_withdrawal(
self.ctx, withdrawal, address_bytes, self.msg.network_id
)
)
withdrawals_dict.add(address_bytes, withdrawal.amount)
@ -842,6 +842,7 @@ class Signer:
data.catalyst_registration_parameters,
self.msg.protocol_magic,
self.msg.network_id,
self.should_show_details,
)
self.tx_dict.add(TX_BODY_KEY_AUXILIARY_DATA, auxiliary_data_hash)
@ -897,7 +898,9 @@ class Signer:
async def _process_script_data_hash(self) -> None:
assert self.msg.script_data_hash is not None
self._validate_script_data_hash()
await layout.confirm_script_data_hash(self.ctx, self.msg.script_data_hash)
await self._show_if_showing_details(
layout.confirm_script_data_hash(self.ctx, self.msg.script_data_hash)
)
self.tx_dict.add(TX_BODY_KEY_SCRIPT_DATA_HASH, self.msg.script_data_hash)
def _validate_script_data_hash(self) -> None:
@ -930,7 +933,9 @@ class Signer:
self, collateral_input: messages.CardanoTxCollateralInput
) -> None:
if self.msg.total_collateral is None:
await layout.confirm_collateral_input(self.ctx, collateral_input)
await self._show_if_showing_details(
layout.confirm_collateral_input(self.ctx, collateral_input)
)
# required signers
@ -942,7 +947,9 @@ class Signer:
messages.CardanoTxItemAck(), messages.CardanoTxRequiredSigner
)
self._validate_required_signer(required_signer)
await layout.confirm_required_signer(self.ctx, required_signer)
await self._show_if_showing_details(
layout.confirm_required_signer(self.ctx, required_signer)
)
key_hash = required_signer.key_hash or get_public_key_hash(
self.keychain, required_signer.key_path
@ -1064,7 +1071,7 @@ class Signer:
if self._is_simple_change_output(output):
return False
return True
return self.should_show_details
# reference inputs
@ -1076,7 +1083,9 @@ class Signer:
messages.CardanoTxItemAck(), messages.CardanoTxReferenceInput
)
self._validate_reference_input(reference_input)
await layout.confirm_reference_input(self.ctx, reference_input)
await self._show_if_showing_details(
layout.confirm_reference_input(self.ctx, reference_input)
)
reference_inputs_list.append(
(reference_input.prev_hash, reference_input.prev_index)
)
@ -1244,3 +1253,7 @@ class Signer:
if Credential.stake_credential(address_parameters).is_unusual_path:
raise wire.DataError(f"Invalid {CHANGE_OUTPUT_STAKING_PATH_NAME.lower()}")
async def _show_if_showing_details(self, layout_fn: Awaitable) -> None:
if self.should_show_details:
await layout_fn

Loading…
Cancel
Save