1
0
mirror of https://github.com/trezor/trezor-firmware.git synced 2024-11-22 07:28:10 +00:00

Cardano: map account paths to account numbers

This commit is contained in:
Rafael Korbas 2020-12-17 22:25:28 +01:00 committed by matejcik
parent 33df274458
commit 44c7d23741
6 changed files with 59 additions and 54 deletions

View File

@ -1,3 +1,5 @@
from micropython import const
from apps.common import HARDENED from apps.common import HARDENED
from apps.common.paths import PathSchema from apps.common.paths import PathSchema
@ -12,3 +14,13 @@ SCHEMA_ADDRESS = PathSchema("m/[44,1852]'/coin_type'/account'/[0,1,2]/address_in
# staking is only allowed on Shelley paths with suffix /2/0 # staking is only allowed on Shelley paths with suffix /2/0
SCHEMA_STAKING = PathSchema("m/1852'/coin_type'/account'/2/0", SLIP44_ID) SCHEMA_STAKING = PathSchema("m/1852'/coin_type'/account'/2/0", SLIP44_ID)
# fmt: on # fmt: on
# the maximum allowed change address. this should be large enough for normal
# use and still allow to quickly brute-force the correct bip32 path
MAX_CHANGE_ADDRESS_INDEX = const(1_000_000)
ACCOUNT_PATH_INDEX = const(2)
BIP_PATH_LENGTH = const(5)
def unharden(item: int) -> int:
return item ^ (item & HARDENED)

View File

@ -1,4 +1,4 @@
from micropython import const from apps.cardano.helpers.paths import ACCOUNT_PATH_INDEX, unharden
if False: if False:
from typing import List from typing import List
@ -27,5 +27,11 @@ def variable_length_encode(number: int) -> bytes:
def to_account_path(path: List[int]) -> List[int]: def to_account_path(path: List[int]) -> List[int]:
ACCOUNT_PATH_LENGTH = const(3) return path[: ACCOUNT_PATH_INDEX + 1]
return path[:ACCOUNT_PATH_LENGTH]
def format_account_number(path: List[int]) -> str:
if len(path) <= ACCOUNT_PATH_INDEX:
raise ValueError("Path is too short.")
return "#%d" % (unharden(path[ACCOUNT_PATH_INDEX]) + 1)

View File

@ -16,7 +16,7 @@ from trezor.ui.text import Text
from trezor.utils import chunks from trezor.utils import chunks
from apps.common.confirm import confirm, require_confirm, require_hold_to_confirm from apps.common.confirm import confirm, require_confirm, require_hold_to_confirm
from apps.common.layout import address_n_to_str, show_warning from apps.common.layout import address_n_to_str
from . import seed from . import seed
from .address import ( from .address import (
@ -25,7 +25,7 @@ from .address import (
pack_reward_address_bytes, pack_reward_address_bytes,
) )
from .helpers import protocol_magics from .helpers import protocol_magics
from .helpers.utils import to_account_path from .helpers.utils import format_account_number, to_account_path
if False: if False:
from typing import List, Optional from typing import List, Optional
@ -122,7 +122,7 @@ async def show_warning_tx_different_staking_account(
page1.normal("the current account.") page1.normal("the current account.")
page2 = Text("Confirm transaction", ui.ICON_SEND, ui.GREEN) page2 = Text("Confirm transaction", ui.ICON_SEND, ui.GREEN)
page2.normal("Staking account:") page2.normal("Staking account %s:" % format_account_number(staking_account_path))
page2.bold(address_n_to_str(staking_account_path)) page2.bold(address_n_to_str(staking_account_path))
page2.normal("Change amount:") page2.normal("Change amount:")
page2.bold(format_coin_amount(amount)) page2.bold(format_coin_amount(amount))
@ -198,7 +198,7 @@ async def confirm_certificate(
page1 = Text("Confirm transaction", ui.ICON_SEND, ui.GREEN) page1 = Text("Confirm transaction", ui.ICON_SEND, ui.GREEN)
page1.normal("Confirm:") page1.normal("Confirm:")
page1.bold(CERTIFICATE_TYPE_NAMES[certificate.type]) page1.bold(CERTIFICATE_TYPE_NAMES[certificate.type])
page1.normal("for account:") page1.normal("for account %s:" % format_account_number(certificate.path))
page1.bold(address_n_to_str(to_account_path(certificate.path))) page1.bold(address_n_to_str(to_account_path(certificate.path)))
pages.append(page1) pages.append(page1)
@ -320,7 +320,7 @@ async def confirm_withdrawal(
) -> None: ) -> None:
page1 = Text("Confirm transaction", ui.ICON_SEND, ui.GREEN) page1 = Text("Confirm transaction", ui.ICON_SEND, ui.GREEN)
page1.normal("Confirm withdrawal") page1.normal("Confirm withdrawal")
page1.normal("for account:") page1.normal("for account %s:" % format_account_number(withdrawal.path))
page1.bold(address_n_to_str(to_account_path(withdrawal.path))) page1.bold(address_n_to_str(to_account_path(withdrawal.path)))
page1.normal("Amount:") page1.normal("Amount:")
page1.bold(format_coin_amount(withdrawal.amount)) page1.bold(format_coin_amount(withdrawal.amount))
@ -401,31 +401,24 @@ async def show_warning_address_foreign_staking_key(
staking_account_path: List[int], staking_account_path: List[int],
staking_key_hash: bytes, staking_key_hash: bytes,
) -> None: ) -> None:
await show_warning( page1 = Text("Warning", ui.ICON_WRONG, ui.RED)
ctx, page1.normal("Stake rights associated")
( page1.normal("with this address do")
"Stake rights associated", page1.normal("not match your")
"with this address do", page1.normal("account %s:" % format_account_number(account_path))
"not match your", page1.bold(address_n_to_str(account_path))
"account",
address_n_to_str(account_path),
),
button="Ok",
)
page2 = Text("Warning", ui.ICON_WRONG, ui.RED)
if staking_account_path: if staking_account_path:
staking_key_message = ( page2.normal("Stake account %s:" % format_account_number(staking_account_path))
"Stake account path:", page2.bold(address_n_to_str(staking_account_path))
address_n_to_str(staking_account_path), page2.br_half()
)
else: else:
staking_key_message = ("Staking key:", hexlify(staking_key_hash).decode()) page2.normal("Staking key:")
page2.bold(hexlify(staking_key_hash).decode())
page2.normal("Continue?")
await show_warning( await require_confirm(ctx, Paginated([page1, page2]))
ctx,
staking_key_message,
button="Ok",
)
async def show_warning_tx_network_unverifiable(ctx: wire.Context) -> None: async def show_warning_tx_network_unverifiable(ctx: wire.Context) -> None:
@ -440,13 +433,10 @@ async def show_warning_tx_network_unverifiable(ctx: wire.Context) -> None:
async def show_warning_address_pointer( async def show_warning_address_pointer(
ctx: wire.Context, pointer: CardanoBlockchainPointerType ctx: wire.Context, pointer: CardanoBlockchainPointerType
) -> None: ) -> None:
await show_warning( text = Text("Warning", ui.ICON_WRONG, ui.RED)
ctx, text.normal("Pointer address:")
( text.normal("Block: %s" % pointer.block_index)
"Pointer address:", text.normal("Transaction: %s" % pointer.tx_index)
"Block: %s" % pointer.block_index, text.normal("Certificate: %s" % pointer.certificate_index)
"Transaction: %s" % pointer.tx_index, text.normal("Continue?")
"Certificate: %s" % pointer.certificate_index, await require_confirm(ctx, text)
),
button="Ok",
)

View File

@ -1,5 +1,3 @@
from micropython import const
from trezor import log, wire from trezor import log, wire
from trezor.crypto import hashlib from trezor.crypto import hashlib
from trezor.crypto.curve import ed25519 from trezor.crypto.curve import ed25519
@ -30,7 +28,13 @@ from .helpers import (
protocol_magics, protocol_magics,
staking_use_cases, staking_use_cases,
) )
from .helpers.paths import SCHEMA_ADDRESS, SCHEMA_STAKING from .helpers.paths import (
ACCOUNT_PATH_INDEX,
BIP_PATH_LENGTH,
MAX_CHANGE_ADDRESS_INDEX,
SCHEMA_ADDRESS,
SCHEMA_STAKING,
)
from .helpers.utils import to_account_path from .helpers.utils import to_account_path
from .layout import ( from .layout import (
confirm_certificate, confirm_certificate,
@ -58,12 +62,6 @@ if False:
from trezor.messages.CardanoTxWithdrawalType import CardanoTxWithdrawalType from trezor.messages.CardanoTxWithdrawalType import CardanoTxWithdrawalType
from typing import Dict, List, Tuple from typing import Dict, List, Tuple
# the maximum allowed change address. this should be large enough for normal
# use and still allow to quickly brute-force the correct bip32 path
MAX_CHANGE_ADDRESS_INDEX = const(1_000_000)
ACCOUNT_PATH_INDEX = const(2)
BIP_PATH_LENGTH = const(5)
METADATA_HASH_SIZE = 32 METADATA_HASH_SIZE = 32
MAX_METADATA_LENGTH = 500 MAX_METADATA_LENGTH = 500

View File

@ -47,7 +47,6 @@ def cli():
@click.option("-t", "--testnet", is_flag=True) @click.option("-t", "--testnet", is_flag=True)
@with_client @with_client
def sign_tx(client, file, protocol_magic, network_id, testnet): def sign_tx(client, file, protocol_magic, network_id, testnet):
print("AAAAA")
"""Sign Cardano transaction.""" """Sign Cardano transaction."""
transaction = json.load(file) transaction = json.load(file)

View File

@ -15,11 +15,11 @@
"cardano-test_sign_tx.py::test_cardano_sign_tx[testnet_transaction0]": "994900bb0b0d52d0872dae1254fc8d5ed337e51be0e2ddd85b9d613bc9b11687", "cardano-test_sign_tx.py::test_cardano_sign_tx[testnet_transaction0]": "994900bb0b0d52d0872dae1254fc8d5ed337e51be0e2ddd85b9d613bc9b11687",
"cardano-test_sign_tx.py::test_cardano_sign_tx[testnet_transaction1]": "120eb04eae3bbcd492e4e0ab19e25bd2e718e4fa9620d5a0496eaee5704f1951", "cardano-test_sign_tx.py::test_cardano_sign_tx[testnet_transaction1]": "120eb04eae3bbcd492e4e0ab19e25bd2e718e4fa9620d5a0496eaee5704f1951",
"cardano-test_sign_tx.py::test_cardano_sign_tx[transaction_with_metadata]": "e0707009a202512da0e38ec536d24d0522f12453ca0bcf91ff074e7653b7958f", "cardano-test_sign_tx.py::test_cardano_sign_tx[transaction_with_metadata]": "e0707009a202512da0e38ec536d24d0522f12453ca0bcf91ff074e7653b7958f",
"cardano-test_sign_tx.py::test_cardano_sign_tx[transaction_with_stake_deregistration]": "c2f15e879c71ba93d5e56e043db4e0f9d3d16b459a21106eb4a4e2bd26b0a964", "cardano-test_sign_tx.py::test_cardano_sign_tx[transaction_with_stake_deregistration]": "3d2ae35075551db91aa24dedbc388a37f58f0b618e073a73aed6a094a352b306",
"cardano-test_sign_tx.py::test_cardano_sign_tx[transaction_with_stake_deregistration_and_withdrawal]": "02b11d9fae34da917ee80e4df75bdcd2e1a8bab7f273d2c0b49f0ba16d21ba85", "cardano-test_sign_tx.py::test_cardano_sign_tx[transaction_with_stake_deregistration_and_withdrawal]": "60f510ca75fc1288c92b50ac38ce2d413b608cc008a5ac519772936a98e60253",
"cardano-test_sign_tx.py::test_cardano_sign_tx[transaction_with_stake_registration_and_stake-3fdfc583": "a1ad5b29757c996c5d58f92dbd99ace6ef94d67abbb4ca4e2020464acf7cb21c", "cardano-test_sign_tx.py::test_cardano_sign_tx[transaction_with_stake_registration_and_stake-3fdfc583": "604b63443e2d554fd3173e748439c29a968597b4db82ad98f56176cda225128f",
"cardano-test_sign_tx.py::test_cardano_sign_tx[transaction_with_stake_registration_certifica-e7bd462a": "6f79fb024254f9eab2be91f4fb15b24926ec3270130eee60f7fe185a5a7f21e4", "cardano-test_sign_tx.py::test_cardano_sign_tx[transaction_with_stake_registration_certifica-e7bd462a": "ab4eb02c8769a90c0c5a643826d6affbab9cda1a55b5bfa1cc1066ac97a86368",
"cardano-test_sign_tx.py::test_cardano_sign_tx[transaction_with_stake_registration_certificate]": "985c5a87c7dc8f36f56aa339285deb5dfaf446b3ab1f3e15dfdbac6bf223b73d", "cardano-test_sign_tx.py::test_cardano_sign_tx[transaction_with_stake_registration_certificate]": "c804dd78f120d14ef2585f04a148df23ab6da539d35b2b20b5bfc6092a4a0da7",
"cardano-test_sign_tx.py::test_cardano_sign_tx_failed[all_tx_inputs_must_be_external_(without_path)]": "612dad8ab8762162a186ec9279d7de0bdfc589c52b4e4f4eba0545a00f21c3f0", "cardano-test_sign_tx.py::test_cardano_sign_tx_failed[all_tx_inputs_must_be_external_(without_path)]": "612dad8ab8762162a186ec9279d7de0bdfc589c52b4e4f4eba0545a00f21c3f0",
"cardano-test_sign_tx.py::test_cardano_sign_tx_failed[certificate_has_invalid_pool_size]": "612dad8ab8762162a186ec9279d7de0bdfc589c52b4e4f4eba0545a00f21c3f0", "cardano-test_sign_tx.py::test_cardano_sign_tx_failed[certificate_has_invalid_pool_size]": "612dad8ab8762162a186ec9279d7de0bdfc589c52b4e4f4eba0545a00f21c3f0",
"cardano-test_sign_tx.py::test_cardano_sign_tx_failed[certificate_has_non_staking_path]": "612dad8ab8762162a186ec9279d7de0bdfc589c52b4e4f4eba0545a00f21c3f0", "cardano-test_sign_tx.py::test_cardano_sign_tx_failed[certificate_has_non_staking_path]": "612dad8ab8762162a186ec9279d7de0bdfc589c52b4e4f4eba0545a00f21c3f0",