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

pull/1531/head
Rafael Korbas 3 years ago committed by matejcik
parent bd4512b53a
commit 74ed5b7018

@ -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",
@ -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",

@ -1,3 +1,5 @@
from trezor.crypto import hashlib
from apps.cardano.helpers.paths import ACCOUNT_PATH_INDEX, unharden
from . import bech32
@ -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)

@ -25,6 +25,7 @@ from .address import (
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,
@ -42,7 +43,6 @@ if False:
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
@ -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:")
@ -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:

@ -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")
@ -28,6 +28,18 @@ class TestCardanoUtils(unittest.TestCase):
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__':
unittest.main()

@ -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",

Loading…
Cancel
Save