Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(core/cardano): Implement bech32 asset ids based on CIP-0014 #1510

Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions common/tests/fixtures/cardano/sign_tx.json
Original file line number Diff line number Diff line change
Expand Up @@ -663,7 +663,7 @@
"certificates": [],
"withdrawals": [],
"metadata": "",
"input_flow": [["YES"], ["YES"], ["YES"], ["SWIPE", "YES"], ["SWIPE", "YES"]],
"input_flow": [["YES"], ["SWIPE", "YES"], ["SWIPE", "SWIPE", "YES"], ["SWIPE", "YES"]],
"inputs": [
{
"path": "m/1852'/1815'/0'/0/0",
Expand Down Expand Up @@ -711,7 +711,7 @@
"certificates": [],
"withdrawals": [],
"metadata": "",
"input_flow": [["YES"], ["YES"], ["YES"], ["SWIPE", "YES"], ["YES"], ["SWIPE", "YES"], ["SWIPE", "SWIPE", "YES"], ["YES"]],
"input_flow": [["YES"], ["SWIPE", "YES"], ["SWIPE", "YES"], ["SWIPE", "YES"], ["SWIPE", "SWIPE", "YES"], ["SWIPE", "YES"]],
"inputs": [
{
"path": "m/1852'/1815'/0'/0/0",
Expand Down
13 changes: 13 additions & 0 deletions core/src/apps/cardano/helpers/utils.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
from trezor.crypto import hashlib

from apps.cardano.helpers.paths import ACCOUNT_PATH_INDEX, unharden

from . import bech32
Expand Down Expand Up @@ -48,3 +50,14 @@ def format_optional_int(number: Optional[int]) -> str:

def format_stake_pool_id(pool_id_bytes: bytes) -> str:
return bech32.encode("pool", pool_id_bytes)


def format_asset_fingerprint(policy_id: bytes, asset_name_bytes: bytes) -> str:
fingerprint = hashlib.blake2b(
# bytearrays are being promoted to bytes: https://github.com/python/mypy/issues/654
# but bytearrays are not concatenable, this casting works around this limitation
data=bytes(policy_id) + bytes(asset_name_bytes),
outlen=20,
).digest()

return bech32.encode("asset", fingerprint)
56 changes: 18 additions & 38 deletions core/src/apps/cardano/layout.py
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@
from .helpers import protocol_magics
from .helpers.utils import (
format_account_number,
format_asset_fingerprint,
format_optional_int,
format_stake_pool_id,
to_account_path,
Expand All @@ -42,7 +43,6 @@
from trezor.messages.CardanoPoolOwnerType import CardanoPoolOwnerType
from trezor.messages.CardanoPoolMetadataType import CardanoPoolMetadataType
from trezor.messages.CardanoAssetGroupType import CardanoAssetGroupType
from trezor.messages.CardanoTokenType import CardanoTokenType
from trezor.messages.CardanoAddressParametersType import EnumTypeCardanoAddressType


Expand Down Expand Up @@ -79,8 +79,7 @@ async def confirm_sending(
token_bundle: List[CardanoAssetGroupType],
to: str,
) -> None:
for token_group in token_bundle:
await confirm_sending_token_group(ctx, token_group)
await confirm_sending_token_bundle(ctx, token_bundle)

page1 = Text("Confirm transaction", ui.ICON_SEND, ui.GREEN)
page1.normal("Confirm sending:")
Expand All @@ -96,42 +95,23 @@ async def confirm_sending(
await require_confirm(ctx, Paginated(pages))


async def confirm_sending_token_group(
ctx: wire.Context, token_group: CardanoAssetGroupType
) -> None:
page1 = Text("Confirm transaction", ui.ICON_SEND, ui.GREEN)
page1.bold("Policy id: ")
page1.mono(hexlify(token_group.policy_id).decode())
await require_confirm(ctx, page1)

for token_number, token in enumerate(token_group.tokens, 1):
if is_printable_ascii_bytestring(token.asset_name_bytes):
await confirm_sending_token_ascii(ctx, token, token_number)
else:
await confirm_sending_token_hex(ctx, token, token_number)


async def confirm_sending_token_ascii(
ctx: wire.Context, token: CardanoTokenType, token_number: int
async def confirm_sending_token_bundle(
ctx: wire.Context, token_bundle: List[CardanoAssetGroupType]
) -> None:
page1 = Text("Confirm transaction", ui.ICON_SEND, ui.GREEN)
page1.normal("Asset #%s name (ASCII):" % (token_number))
page1.bold(token.asset_name_bytes.decode("ascii"))
page1.normal("Amount sent:")
page1.bold(format_amount(token.amount, 0))
await require_confirm(ctx, page1)


async def confirm_sending_token_hex(
ctx: wire.Context, token: CardanoTokenType, token_number: int
) -> None:
page1 = Text("Confirm transaction", ui.ICON_SEND, ui.GREEN)
page1.bold("Asset #%s name (hex):" % (token_number))
page1.mono(hexlify(token.asset_name_bytes).decode())
page2 = Text("Confirm transaction", ui.ICON_SEND, ui.GREEN)
page2.normal("Amount sent:")
page2.bold(format_amount(token.amount, 0))
await require_confirm(ctx, Paginated([page1, page2]))
for token_group in token_bundle:
for token in token_group.tokens:
page1 = Text("Confirm transaction", ui.ICON_SEND, ui.GREEN)
page1.normal("Asset fingerprint:")
page1.bold(
format_asset_fingerprint(
policy_id=token_group.policy_id,
asset_name_bytes=token.asset_name_bytes,
)
)
page2 = Text("Confirm transaction", ui.ICON_SEND, ui.GREEN)
page2.normal("Amount sent:")
page2.bold(format_amount(token.amount, 0))
await require_confirm(ctx, Paginated([page1, page2]))


async def show_warning_tx_output_contains_tokens(ctx: wire.Context) -> None:
Expand Down
14 changes: 13 additions & 1 deletion core/tests/test_apps.cardano.utils.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
from common import *

if not utils.BITCOIN_ONLY:
from apps.cardano.helpers.utils import variable_length_encode
from apps.cardano.helpers.utils import variable_length_encode, format_asset_fingerprint


@unittest.skipUnless(not utils.BITCOIN_ONLY, "altcoin")
Expand All @@ -27,6 +27,18 @@ def test_variable_length_encode(self):
def test_variable_length_encode_negative_number(self):
with self.assertRaises(ValueError):
variable_length_encode(-1)

def test_format_asset_fingerprint(self):
# source: https://github.com/cardano-foundation/CIPs/pull/64
test_vectors = [
(("7eae28af2208be856f7a119668ae52a49b73725e326dc16579dcc373", ""), "asset1rjklcrnsdzqp65wjgrg55sy9723kw09mlgvlc3"),
(("7eae28af2208be856f7a119668ae52a49b73725e326dc16579dcc373", "504154415445"), "asset13n25uv0yaf5kus35fm2k86cqy60z58d9xmde92"),
(("1e349c9bdea19fd6c147626a5260bc44b71635f398b67c59881df209", "7eae28af2208be856f7a119668ae52a49b73725e326dc16579dcc373"), "asset1aqrdypg669jgazruv5ah07nuyqe0wxjhe2el6f"),
]

for params, expected in test_vectors:
actual = format_asset_fingerprint(policy_id=unhexlify(params[0]), asset_name_bytes=unhexlify(params[1]))
self.assertEqual(actual, expected)


if __name__ == '__main__':
Expand Down
4 changes: 2 additions & 2 deletions tests/ui_tests/fixtures.json
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,8 @@
"cardano-test_sign_tx.py::test_cardano_sign_tx[mainnet_transaction_with_multiple_inputs]": "5ba2589aeda7cb2b707b5dd0d40ac26a5abe6eb0c3ec3d47d834701ef07a42bc",
"cardano-test_sign_tx.py::test_cardano_sign_tx[mainnet_transaction_without_change0]": "5ba2589aeda7cb2b707b5dd0d40ac26a5abe6eb0c3ec3d47d834701ef07a42bc",
"cardano-test_sign_tx.py::test_cardano_sign_tx[mainnet_transaction_without_change1]": "c57c4097446de48b1f79850854a83410816ac05c8a7476452771cdc71e0aeefa",
"cardano-test_sign_tx.py::test_cardano_sign_tx[mary_era_transaction_with_different_policies_-1dbb1bfb": "0f14d371c83adf4ceaa05530581df86eb653b9e8226be61fcd2bc1cc97e3581a",
"cardano-test_sign_tx.py::test_cardano_sign_tx[mary_era_transaction_with_multiasset_output]": "a24edeaaefca10b45235836264b8385148048a23bd34c56570c3de69de4f3d06",
"cardano-test_sign_tx.py::test_cardano_sign_tx[mary_era_transaction_with_different_policies_-1dbb1bfb": "02f8517926fe8d38d96606929df43372d8949e917299199d37e648672fed9256",
"cardano-test_sign_tx.py::test_cardano_sign_tx[mary_era_transaction_with_multiasset_output]": "d0a58ab8b68fcd9f1191f309de52efb6be9157383357f5f9c0e0d116fccc08e4",
"cardano-test_sign_tx.py::test_cardano_sign_tx[mary_era_transaction_with_no_ttl-validity_start]": "db76676358164a3b3dab5148f09ba5515d079212366b79c44f95e2ba613abc71",
"cardano-test_sign_tx.py::test_cardano_sign_tx[sample_stake_pool_registration_certificate]": "f56482d4a0f2c07fe04291a7d9c29ed4aedfd31e6a80fed1563d80e3a4c4005c",
"cardano-test_sign_tx.py::test_cardano_sign_tx[sample_stake_pool_registration_certificate_wi-d3427614": "629ccaa5b660247843b366582c1bc505831c1800e028474a784b0f8b35fc473a",
Expand Down