diff --git a/src/apps/tezos/get_address.py b/src/apps/tezos/get_address.py index 927fec202b..77049fe419 100644 --- a/src/apps/tezos/get_address.py +++ b/src/apps/tezos/get_address.py @@ -1,20 +1,22 @@ from trezor.crypto import hashlib -from trezor.crypto.curve import ed25519 from trezor.messages.TezosAddress import TezosAddress from apps.common import seed from apps.common.layout import show_address, show_qr -from apps.tezos.helpers import TEZOS_CURVE, b58cencode, tezos_get_address_prefix +from apps.tezos.helpers import ( + TEZOS_CURVE, + TEZOS_ED25519_ADDRESS_PREFIX, + base58_encode_check, +) async def get_address(ctx, msg): address_n = msg.address_n or () node = await seed.derive_node(ctx, address_n, TEZOS_CURVE) - sk = node.private_key() - pk = ed25519.publickey(sk) + pk = seed.remove_ed25519_prefix(node.public_key()) pkh = hashlib.blake2b(pk, outlen=20).digest() - address = b58cencode(pkh, prefix=tezos_get_address_prefix(0)) + address = base58_encode_check(pkh, prefix=TEZOS_ED25519_ADDRESS_PREFIX) if msg.show_display: while True: diff --git a/src/apps/tezos/get_public_key.py b/src/apps/tezos/get_public_key.py index dd8759be82..964944ce01 100644 --- a/src/apps/tezos/get_public_key.py +++ b/src/apps/tezos/get_public_key.py @@ -1,5 +1,4 @@ from trezor import ui -from trezor.crypto.curve import ed25519 from trezor.messages import ButtonRequestType from trezor.messages.TezosPublicKey import TezosPublicKey from trezor.ui.text import Text @@ -7,16 +6,15 @@ from trezor.utils import chunks from apps.common import seed from apps.common.confirm import require_confirm -from apps.tezos.helpers import TEZOS_CURVE, TEZOS_PUBLICKEY_PREFIX, b58cencode +from apps.tezos.helpers import TEZOS_CURVE, TEZOS_PUBLICKEY_PREFIX, base58_encode_check async def get_public_key(ctx, msg): address_n = msg.address_n or () node = await seed.derive_node(ctx, address_n, TEZOS_CURVE) - sk = node.private_key() - pk = ed25519.publickey(sk) - pk_prefixed = b58cencode(pk, prefix=TEZOS_PUBLICKEY_PREFIX) + pk = seed.remove_ed25519_prefix(node.public_key()) + pk_prefixed = base58_encode_check(pk, prefix=TEZOS_PUBLICKEY_PREFIX) if msg.show_display: await _show_tezos_pubkey(ctx, pk_prefixed) diff --git a/src/apps/tezos/helpers.py b/src/apps/tezos/helpers.py index 8ad0cd2280..4a82a6aa1b 100644 --- a/src/apps/tezos/helpers.py +++ b/src/apps/tezos/helpers.py @@ -1,10 +1,10 @@ from micropython import const -from trezor import wire from trezor.crypto import base58 TEZOS_CURVE = "ed25519" TEZOS_AMOUNT_DIVISIBILITY = const(6) +TEZOS_ED25519_ADDRESS_PREFIX = "tz1" TEZOS_ORIGINATED_ADDRESS_PREFIX = "KT1" TEZOS_PUBLICKEY_PREFIX = "edpk" TEZOS_SIGNATURE_PREFIX = "edsig" @@ -23,21 +23,14 @@ TEZOS_PREFIX_BYTES = { } -def tezos_get_address_prefix(tag): - prefixes = ["tz1", "tz2", "tz3"] - if 0 <= tag < len(prefixes): - return prefixes[tag] - raise wire.DataError("Invalid tag in address hash") - - -def b58cencode(payload, prefix=None): +def base58_encode_check(payload, prefix=None): result = payload if prefix is not None: result = bytes(TEZOS_PREFIX_BYTES[prefix]) + payload return base58.encode_check(result) -def b58cdecode(enc, prefix=None): +def base58_decode_check(enc, prefix=None): decoded = base58.decode_check(enc) if prefix is not None: decoded = decoded[len(TEZOS_PREFIX_BYTES[prefix]) :] diff --git a/src/apps/tezos/sign_tx.py b/src/apps/tezos/sign_tx.py index b1f4c51d5c..134dffb033 100644 --- a/src/apps/tezos/sign_tx.py +++ b/src/apps/tezos/sign_tx.py @@ -1,5 +1,3 @@ -import ustruct - from trezor import wire from trezor.crypto import hashlib from trezor.crypto.curve import ed25519 @@ -7,12 +5,12 @@ from trezor.messages import TezosContractType from trezor.messages.TezosSignedTx import TezosSignedTx from apps.common import seed +from apps.common.writers import write_bytes, write_uint8 from apps.tezos.helpers import ( TEZOS_CURVE, TEZOS_ORIGINATED_ADDRESS_PREFIX, TEZOS_SIGNATURE_PREFIX, - b58cencode, - tezos_get_address_prefix, + base58_encode_check, ) from apps.tezos.layout import * @@ -50,8 +48,12 @@ async def sign_tx(ctx, msg): else: raise wire.DataError("Invalid operation") - opbytes = _get_operation_bytes(msg) + w = bytearray() + _get_operation_bytes(w, msg) + opbytes = bytes(w) + + # watermark 0x03 is prefix for transactions, delegations, originations, reveals... watermark = bytes([3]) wm_opbytes = watermark + opbytes wm_opbytes_hash = hashlib.blake2b(wm_opbytes, outlen=32).digest() @@ -60,9 +62,9 @@ async def sign_tx(ctx, msg): sig_op_contents = opbytes + signature sig_op_contents_hash = hashlib.blake2b(sig_op_contents, outlen=32).digest() - ophash = b58cencode(sig_op_contents_hash, prefix="o") + ophash = base58_encode_check(sig_op_contents_hash, prefix="o") - sig_prefixed = b58cencode(signature, prefix=TEZOS_SIGNATURE_PREFIX) + sig_prefixed = base58_encode_check(signature, prefix=TEZOS_SIGNATURE_PREFIX) return TezosSignedTx( signature=sig_prefixed, sig_op_contents=sig_op_contents, operation_hash=ophash @@ -70,8 +72,12 @@ async def sign_tx(ctx, msg): def _get_address_by_tag(address_hash): + prefixes = ["tz1", "tz2", "tz3"] tag = int(address_hash[0]) - return b58cencode(address_hash[1:], prefix=tezos_get_address_prefix(tag)) + + if 0 <= tag < len(prefixes): + return base58_encode_check(address_hash[1:], prefix=prefixes[tag]) + raise wire.DataError("Invalid tag in address hash") def _get_address_from_contract(address): @@ -79,77 +85,80 @@ def _get_address_from_contract(address): return _get_address_by_tag(address.hash) elif address.tag == TezosContractType.Originated: - return b58cencode(address.hash[:-1], prefix=TEZOS_ORIGINATED_ADDRESS_PREFIX) + return base58_encode_check( + address.hash[:-1], prefix=TEZOS_ORIGINATED_ADDRESS_PREFIX + ) raise wire.DataError("Invalid contract type") -def _get_operation_bytes(msg): - result = msg.branch +def _get_operation_bytes(w: bytearray, msg): + write_bytes(w, msg.branch) # when the account sends first operation in lifetime, # we need to reveal its publickey if msg.reveal is not None: - result += _encode_common(msg.reveal, "reveal") - result += msg.reveal.public_key + _encode_common(w, msg.reveal, "reveal") + write_bytes(w, msg.reveal.public_key) # transaction operation if msg.transaction is not None: - result += _encode_common(msg.transaction, "transaction") - result += _encode_zarith(msg.transaction.amount) - result += _encode_contract_id(msg.transaction.destination) - result += _encode_data_with_bool_prefix(msg.transaction.parameters) + _encode_common(w, msg.transaction, "transaction") + _encode_zarith(w, msg.transaction.amount) + _encode_contract_id(w, msg.transaction.destination) + _encode_data_with_bool_prefix(w, msg.transaction.parameters) # origination operation elif msg.origination is not None: - result += _encode_common(msg.origination, "origination") - result += msg.origination.manager_pubkey - result += _encode_zarith(msg.origination.balance) - result += _encode_bool(msg.origination.spendable) - result += _encode_bool(msg.origination.delegatable) - result += _encode_data_with_bool_prefix(msg.origination.delegate) - result += _encode_data_with_bool_prefix(msg.origination.script) + _encode_common(w, msg.origination, "origination") + write_bytes(w, msg.origination.manager_pubkey) + _encode_zarith(w, msg.origination.balance) + _encode_bool(w, msg.origination.spendable) + _encode_bool(w, msg.origination.delegatable) + _encode_data_with_bool_prefix(w, msg.origination.delegate) + _encode_data_with_bool_prefix(w, msg.origination.script) # delegation operation elif msg.delegation is not None: - result += _encode_common(msg.delegation, "delegation") - result += _encode_data_with_bool_prefix(msg.delegation.delegate) - - return bytes(result) + _encode_common(w, msg.delegation, "delegation") + _encode_data_with_bool_prefix(w, msg.delegation.delegate) -def _encode_common(operation, str_operation): +def _encode_common(w: bytearray, operation, str_operation): operation_tags = {"reveal": 7, "transaction": 8, "origination": 9, "delegation": 10} - result = ustruct.pack("> 7 if num == 0: - result += ustruct.pack("