mirror of
https://github.com/trezor/trezor-firmware.git
synced 2024-11-18 05:28:40 +00:00
chore(core): decrease tezos size by 860 bytes
This commit is contained in:
parent
80ab7f1c29
commit
164be3ac8f
@ -1,16 +1,11 @@
|
|||||||
from typing import TYPE_CHECKING
|
from typing import TYPE_CHECKING
|
||||||
|
|
||||||
from trezor.crypto import hashlib
|
|
||||||
from trezor.messages import TezosAddress
|
|
||||||
from trezor.ui.layouts import show_address
|
|
||||||
|
|
||||||
from apps.common import paths, seed
|
|
||||||
from apps.common.keychain import with_slip44_keychain
|
from apps.common.keychain import with_slip44_keychain
|
||||||
|
|
||||||
from . import CURVE, PATTERNS, SLIP44_ID, helpers
|
from . import CURVE, PATTERNS, SLIP44_ID
|
||||||
|
|
||||||
if TYPE_CHECKING:
|
if TYPE_CHECKING:
|
||||||
from trezor.messages import TezosGetAddress
|
from trezor.messages import TezosGetAddress, TezosAddress
|
||||||
from apps.common.keychain import Keychain
|
from apps.common.keychain import Keychain
|
||||||
from trezor.wire import Context
|
from trezor.wire import Context
|
||||||
|
|
||||||
@ -19,18 +14,22 @@ if TYPE_CHECKING:
|
|||||||
async def get_address(
|
async def get_address(
|
||||||
ctx: Context, msg: TezosGetAddress, keychain: Keychain
|
ctx: Context, msg: TezosGetAddress, keychain: Keychain
|
||||||
) -> TezosAddress:
|
) -> TezosAddress:
|
||||||
|
from trezor.crypto import hashlib
|
||||||
|
from trezor.messages import TezosAddress
|
||||||
|
from trezor.ui.layouts import show_address
|
||||||
|
from apps.common import paths, seed
|
||||||
|
from . import helpers
|
||||||
|
|
||||||
await paths.validate_path(ctx, keychain, msg.address_n)
|
await paths.validate_path(ctx, keychain, msg.address_n)
|
||||||
|
|
||||||
node = keychain.derive(msg.address_n)
|
node = keychain.derive(msg.address_n)
|
||||||
|
|
||||||
pk = seed.remove_ed25519_prefix(node.public_key())
|
pk = seed.remove_ed25519_prefix(node.public_key())
|
||||||
pkh = hashlib.blake2b(pk, outlen=helpers.PUBLIC_KEY_HASH_SIZE).digest()
|
pkh = hashlib.blake2b(pk, outlen=helpers.PUBLIC_KEY_HASH_SIZE).digest()
|
||||||
address = helpers.base58_encode_check(
|
address = helpers.base58_encode_check(pkh, helpers.TEZOS_ED25519_ADDRESS_PREFIX)
|
||||||
pkh, prefix=helpers.TEZOS_ED25519_ADDRESS_PREFIX
|
|
||||||
)
|
|
||||||
|
|
||||||
if msg.show_display:
|
if msg.show_display:
|
||||||
title = paths.address_n_to_str(msg.address_n)
|
title = paths.address_n_to_str(msg.address_n)
|
||||||
await show_address(ctx, address=address, title=title)
|
await show_address(ctx, address, title=title)
|
||||||
|
|
||||||
return TezosAddress(address=address)
|
return TezosAddress(address=address)
|
||||||
|
@ -1,15 +1,11 @@
|
|||||||
from typing import TYPE_CHECKING
|
from typing import TYPE_CHECKING
|
||||||
|
|
||||||
from trezor.messages import TezosPublicKey
|
|
||||||
from trezor.ui.layouts import show_pubkey
|
|
||||||
|
|
||||||
from apps.common import paths, seed
|
|
||||||
from apps.common.keychain import with_slip44_keychain
|
from apps.common.keychain import with_slip44_keychain
|
||||||
|
|
||||||
from . import CURVE, PATTERNS, SLIP44_ID, helpers
|
from . import CURVE, PATTERNS, SLIP44_ID
|
||||||
|
|
||||||
if TYPE_CHECKING:
|
if TYPE_CHECKING:
|
||||||
from trezor.messages import TezosGetPublicKey
|
from trezor.messages import TezosGetPublicKey, TezosPublicKey
|
||||||
from apps.common.keychain import Keychain
|
from apps.common.keychain import Keychain
|
||||||
from trezor.wire import Context
|
from trezor.wire import Context
|
||||||
|
|
||||||
@ -18,11 +14,16 @@ if TYPE_CHECKING:
|
|||||||
async def get_public_key(
|
async def get_public_key(
|
||||||
ctx: Context, msg: TezosGetPublicKey, keychain: Keychain
|
ctx: Context, msg: TezosGetPublicKey, keychain: Keychain
|
||||||
) -> TezosPublicKey:
|
) -> TezosPublicKey:
|
||||||
|
from trezor.messages import TezosPublicKey
|
||||||
|
from trezor.ui.layouts import show_pubkey
|
||||||
|
from apps.common import paths, seed
|
||||||
|
from . import helpers
|
||||||
|
|
||||||
await paths.validate_path(ctx, keychain, msg.address_n)
|
await paths.validate_path(ctx, keychain, msg.address_n)
|
||||||
|
|
||||||
node = keychain.derive(msg.address_n)
|
node = keychain.derive(msg.address_n)
|
||||||
pk = seed.remove_ed25519_prefix(node.public_key())
|
pk = seed.remove_ed25519_prefix(node.public_key())
|
||||||
pk_prefixed = helpers.base58_encode_check(pk, prefix=helpers.TEZOS_PUBLICKEY_PREFIX)
|
pk_prefixed = helpers.base58_encode_check(pk, helpers.TEZOS_PUBLICKEY_PREFIX)
|
||||||
|
|
||||||
if msg.show_display:
|
if msg.show_display:
|
||||||
await show_pubkey(ctx, pk_prefixed)
|
await show_pubkey(ctx, pk_prefixed)
|
||||||
|
@ -1,12 +1,10 @@
|
|||||||
from micropython import const
|
from micropython import const
|
||||||
from typing import TYPE_CHECKING
|
from typing import TYPE_CHECKING
|
||||||
|
|
||||||
from trezor import wire
|
|
||||||
from trezor.crypto import base58
|
|
||||||
from trezor.utils import BufferReader, ensure
|
from trezor.utils import BufferReader, ensure
|
||||||
|
from trezor.wire import DataError
|
||||||
|
|
||||||
from apps.common.readers import read_uint32_be
|
from apps.common.readers import read_uint32_be
|
||||||
from apps.common.writers import write_bytes_unchecked, write_uint8
|
|
||||||
|
|
||||||
if TYPE_CHECKING:
|
if TYPE_CHECKING:
|
||||||
from trezor.utils import Writer
|
from trezor.utils import Writer
|
||||||
@ -83,6 +81,8 @@ _EP_TAG_NAMED = const(255)
|
|||||||
|
|
||||||
|
|
||||||
def base58_encode_check(payload: bytes, prefix: str | None = None) -> str:
|
def base58_encode_check(payload: bytes, prefix: str | None = None) -> str:
|
||||||
|
from trezor.crypto import base58
|
||||||
|
|
||||||
result = payload
|
result = payload
|
||||||
if prefix is not None:
|
if prefix is not None:
|
||||||
result = TEZOS_PREFIX_BYTES[prefix] + payload
|
result = TEZOS_PREFIX_BYTES[prefix] + payload
|
||||||
@ -90,13 +90,14 @@ def base58_encode_check(payload: bytes, prefix: str | None = None) -> str:
|
|||||||
|
|
||||||
|
|
||||||
def write_bool(w: Writer, boolean: bool) -> None:
|
def write_bool(w: Writer, boolean: bool) -> None:
|
||||||
if boolean:
|
from apps.common.writers import write_uint8
|
||||||
write_uint8(w, 255)
|
|
||||||
else:
|
write_uint8(w, 255 if boolean else 0)
|
||||||
write_uint8(w, 0)
|
|
||||||
|
|
||||||
|
|
||||||
def write_instruction(w: Writer, instruction: str) -> None:
|
def write_instruction(w: Writer, instruction: str) -> None:
|
||||||
|
from apps.common.writers import write_bytes_unchecked
|
||||||
|
|
||||||
write_bytes_unchecked(w, MICHELSON_INSTRUCTION_BYTES[instruction])
|
write_bytes_unchecked(w, MICHELSON_INSTRUCTION_BYTES[instruction])
|
||||||
|
|
||||||
|
|
||||||
@ -108,7 +109,7 @@ def check_script_size(script: bytes) -> None:
|
|||||||
n = read_uint32_be(r)
|
n = read_uint32_be(r)
|
||||||
ensure(r.remaining_count() == n)
|
ensure(r.remaining_count() == n)
|
||||||
except (AssertionError, EOFError):
|
except (AssertionError, EOFError):
|
||||||
raise wire.DataError("Invalid script")
|
raise DataError("Invalid script")
|
||||||
|
|
||||||
|
|
||||||
def check_tx_params_size(params: bytes) -> None:
|
def check_tx_params_size(params: bytes) -> None:
|
||||||
@ -119,8 +120,8 @@ def check_tx_params_size(params: bytes) -> None:
|
|||||||
n = r.get()
|
n = r.get()
|
||||||
r.read(n)
|
r.read(n)
|
||||||
elif tag > 4:
|
elif tag > 4:
|
||||||
raise wire.DataError("Unknown entrypoint tag")
|
raise DataError("Unknown entrypoint tag")
|
||||||
n = read_uint32_be(r)
|
n = read_uint32_be(r)
|
||||||
ensure(r.remaining_count() == n)
|
ensure(r.remaining_count() == n)
|
||||||
except (AssertionError, EOFError):
|
except (AssertionError, EOFError):
|
||||||
raise wire.DataError("Invalid transaction parameters")
|
raise DataError("Invalid transaction parameters")
|
||||||
|
@ -2,39 +2,38 @@ from typing import TYPE_CHECKING
|
|||||||
|
|
||||||
from trezor import ui
|
from trezor import ui
|
||||||
from trezor.enums import ButtonRequestType
|
from trezor.enums import ButtonRequestType
|
||||||
from trezor.strings import format_amount
|
from trezor.ui.layouts import confirm_address, confirm_metadata, confirm_properties
|
||||||
from trezor.ui.layouts import (
|
|
||||||
confirm_address,
|
|
||||||
confirm_metadata,
|
|
||||||
confirm_output,
|
|
||||||
confirm_properties,
|
|
||||||
confirm_total,
|
|
||||||
)
|
|
||||||
|
|
||||||
from .helpers import TEZOS_AMOUNT_DECIMALS
|
|
||||||
|
|
||||||
if TYPE_CHECKING:
|
if TYPE_CHECKING:
|
||||||
from trezor.wire import Context
|
from trezor.wire import Context
|
||||||
|
|
||||||
|
|
||||||
|
BR_SIGN_TX = ButtonRequestType.SignTx # global_import_cache
|
||||||
|
BLUE = ui.BLUE # global_import_cache
|
||||||
|
|
||||||
|
|
||||||
async def require_confirm_tx(ctx: Context, to: str, value: int) -> None:
|
async def require_confirm_tx(ctx: Context, to: str, value: int) -> None:
|
||||||
|
from trezor.ui.layouts import confirm_output
|
||||||
|
|
||||||
await confirm_output(
|
await confirm_output(
|
||||||
ctx,
|
ctx,
|
||||||
to,
|
to,
|
||||||
format_tezos_amount(value),
|
format_tezos_amount(value),
|
||||||
font_amount=ui.BOLD,
|
ui.BOLD,
|
||||||
to_str="\nto\n",
|
to_str="\nto\n",
|
||||||
width=18,
|
width=18,
|
||||||
br_code=ButtonRequestType.SignTx,
|
br_code=BR_SIGN_TX,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
async def require_confirm_fee(ctx: Context, value: int, fee: int) -> None:
|
async def require_confirm_fee(ctx: Context, value: int, fee: int) -> None:
|
||||||
|
from trezor.ui.layouts import confirm_total
|
||||||
|
|
||||||
await confirm_total(
|
await confirm_total(
|
||||||
ctx,
|
ctx,
|
||||||
total_amount=format_tezos_amount(value),
|
format_tezos_amount(value),
|
||||||
|
format_tezos_amount(fee),
|
||||||
total_label="Amount:\n",
|
total_label="Amount:\n",
|
||||||
fee_amount=format_tezos_amount(fee),
|
|
||||||
fee_label="\nFee:\n",
|
fee_label="\nFee:\n",
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -42,25 +41,25 @@ async def require_confirm_fee(ctx: Context, value: int, fee: int) -> None:
|
|||||||
async def require_confirm_origination(ctx: Context, address: str) -> None:
|
async def require_confirm_origination(ctx: Context, address: str) -> None:
|
||||||
await confirm_address(
|
await confirm_address(
|
||||||
ctx,
|
ctx,
|
||||||
title="Confirm origination",
|
"Confirm origination",
|
||||||
address=address,
|
address,
|
||||||
description="Address:",
|
"Address:",
|
||||||
br_type="confirm_origination",
|
"confirm_origination",
|
||||||
|
BR_SIGN_TX,
|
||||||
icon_color=ui.ORANGE,
|
icon_color=ui.ORANGE,
|
||||||
br_code=ButtonRequestType.SignTx,
|
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
async def require_confirm_origination_fee(ctx: Context, balance: int, fee: int) -> None:
|
async def require_confirm_origination_fee(ctx: Context, balance: int, fee: int) -> None:
|
||||||
await confirm_properties(
|
await confirm_properties(
|
||||||
ctx,
|
ctx,
|
||||||
title="Confirm origination",
|
"confirm_origination_final",
|
||||||
props=(
|
"Confirm origination",
|
||||||
|
(
|
||||||
("Balance:", format_tezos_amount(balance)),
|
("Balance:", format_tezos_amount(balance)),
|
||||||
("Fee:", format_tezos_amount(fee)),
|
("Fee:", format_tezos_amount(fee)),
|
||||||
),
|
),
|
||||||
icon_color=ui.ORANGE,
|
icon_color=ui.ORANGE,
|
||||||
br_type="confirm_origination_final",
|
|
||||||
hold=True,
|
hold=True,
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -68,12 +67,12 @@ async def require_confirm_origination_fee(ctx: Context, balance: int, fee: int)
|
|||||||
async def require_confirm_delegation_baker(ctx: Context, baker: str) -> None:
|
async def require_confirm_delegation_baker(ctx: Context, baker: str) -> None:
|
||||||
await confirm_address(
|
await confirm_address(
|
||||||
ctx,
|
ctx,
|
||||||
title="Confirm delegation",
|
"Confirm delegation",
|
||||||
address=baker,
|
baker,
|
||||||
description="Baker address:",
|
"Baker address:",
|
||||||
br_type="confirm_delegation",
|
"confirm_delegation",
|
||||||
icon_color=ui.BLUE,
|
BR_SIGN_TX,
|
||||||
br_code=ButtonRequestType.SignTx,
|
icon_color=BLUE,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
@ -81,13 +80,13 @@ async def require_confirm_set_delegate(ctx: Context, fee: int) -> None:
|
|||||||
await confirm_metadata(
|
await confirm_metadata(
|
||||||
ctx,
|
ctx,
|
||||||
"confirm_delegation_final",
|
"confirm_delegation_final",
|
||||||
title="Confirm delegation",
|
"Confirm delegation",
|
||||||
content="Fee:\n{}",
|
"Fee:\n{}",
|
||||||
param=format_tezos_amount(fee),
|
format_tezos_amount(fee),
|
||||||
hold=True,
|
BR_SIGN_TX,
|
||||||
hide_continue=True,
|
hide_continue=True,
|
||||||
icon_color=ui.BLUE,
|
hold=True,
|
||||||
br_code=ButtonRequestType.SignTx,
|
icon_color=BLUE,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
@ -97,17 +96,20 @@ async def require_confirm_register_delegate(
|
|||||||
await confirm_properties(
|
await confirm_properties(
|
||||||
ctx,
|
ctx,
|
||||||
"confirm_register_delegate",
|
"confirm_register_delegate",
|
||||||
title="Register delegate",
|
"Register delegate",
|
||||||
props=(
|
(
|
||||||
("Fee:", format_tezos_amount(fee)),
|
("Fee:", format_tezos_amount(fee)),
|
||||||
("Address:", address),
|
("Address:", address),
|
||||||
),
|
),
|
||||||
icon_color=ui.BLUE,
|
icon_color=BLUE,
|
||||||
br_code=ButtonRequestType.SignTx,
|
br_code=BR_SIGN_TX,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
def format_tezos_amount(value: int) -> str:
|
def format_tezos_amount(value: int) -> str:
|
||||||
|
from trezor.strings import format_amount
|
||||||
|
from .helpers import TEZOS_AMOUNT_DECIMALS
|
||||||
|
|
||||||
formatted_value = format_amount(value, TEZOS_AMOUNT_DECIMALS)
|
formatted_value = format_amount(value, TEZOS_AMOUNT_DECIMALS)
|
||||||
return formatted_value + " XTZ"
|
return formatted_value + " XTZ"
|
||||||
|
|
||||||
@ -116,31 +118,24 @@ async def require_confirm_ballot(ctx: Context, proposal: str, ballot: str) -> No
|
|||||||
await confirm_properties(
|
await confirm_properties(
|
||||||
ctx,
|
ctx,
|
||||||
"confirm_ballot",
|
"confirm_ballot",
|
||||||
title="Submit ballot",
|
"Submit ballot",
|
||||||
props=(
|
(
|
||||||
("Ballot:", ballot),
|
("Ballot:", ballot),
|
||||||
("Proposal:", proposal),
|
("Proposal:", proposal),
|
||||||
),
|
),
|
||||||
icon_color=ui.PURPLE,
|
icon_color=ui.PURPLE,
|
||||||
br_code=ButtonRequestType.SignTx,
|
br_code=BR_SIGN_TX,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
async def require_confirm_proposals(ctx: Context, proposals: list[str]) -> None:
|
async def require_confirm_proposals(ctx: Context, proposals: list[str]) -> None:
|
||||||
if len(proposals) > 1:
|
|
||||||
title = "Submit proposals"
|
|
||||||
else:
|
|
||||||
title = "Submit proposal"
|
|
||||||
|
|
||||||
await confirm_properties(
|
await confirm_properties(
|
||||||
ctx,
|
ctx,
|
||||||
"confirm_proposals",
|
"confirm_proposals",
|
||||||
title=title,
|
"Submit proposals" if len(proposals) > 1 else "Submit proposal",
|
||||||
props=[
|
[("Proposal " + str(i), proposal) for i, proposal in enumerate(proposals, 1)],
|
||||||
("Proposal " + str(i), proposal) for i, proposal in enumerate(proposals, 1)
|
|
||||||
],
|
|
||||||
icon_color=ui.PURPLE,
|
icon_color=ui.PURPLE,
|
||||||
br_code=ButtonRequestType.SignTx,
|
br_code=BR_SIGN_TX,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
@ -149,13 +144,13 @@ async def require_confirm_delegation_manager_withdraw(
|
|||||||
) -> None:
|
) -> None:
|
||||||
await confirm_address(
|
await confirm_address(
|
||||||
ctx,
|
ctx,
|
||||||
title="Remove delegation",
|
"Remove delegation",
|
||||||
address=address,
|
address,
|
||||||
description="Delegator:",
|
"Delegator:",
|
||||||
br_type="confirm_undelegation",
|
"confirm_undelegation",
|
||||||
|
BR_SIGN_TX,
|
||||||
icon=ui.ICON_RECEIVE,
|
icon=ui.ICON_RECEIVE,
|
||||||
icon_color=ui.RED,
|
icon_color=ui.RED,
|
||||||
br_code=ButtonRequestType.SignTx,
|
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
@ -163,12 +158,12 @@ async def require_confirm_manager_remove_delegate(ctx: Context, fee: int) -> Non
|
|||||||
await confirm_metadata(
|
await confirm_metadata(
|
||||||
ctx,
|
ctx,
|
||||||
"confirm_undelegation_final",
|
"confirm_undelegation_final",
|
||||||
title="Remove delegation",
|
"Remove delegation",
|
||||||
content="Fee:\n{}",
|
"Fee:\n{}",
|
||||||
param=format_tezos_amount(fee),
|
format_tezos_amount(fee),
|
||||||
hold=True,
|
BR_SIGN_TX,
|
||||||
hide_continue=True,
|
hide_continue=True,
|
||||||
|
hold=True,
|
||||||
icon=ui.ICON_RECEIVE,
|
icon=ui.ICON_RECEIVE,
|
||||||
icon_color=ui.RED,
|
icon_color=ui.RED,
|
||||||
br_code=ButtonRequestType.SignTx,
|
|
||||||
)
|
)
|
||||||
|
@ -1,21 +1,19 @@
|
|||||||
from typing import TYPE_CHECKING
|
from typing import TYPE_CHECKING
|
||||||
|
|
||||||
from trezor import wire
|
from trezor.enums import TezosContractType
|
||||||
from trezor.crypto import hashlib
|
from trezor.wire import DataError
|
||||||
from trezor.crypto.curve import ed25519
|
|
||||||
from trezor.enums import TezosBallotType, TezosContractType
|
|
||||||
from trezor.messages import TezosSignedTx
|
|
||||||
|
|
||||||
from apps.common import paths
|
|
||||||
from apps.common.keychain import with_slip44_keychain
|
from apps.common.keychain import with_slip44_keychain
|
||||||
from apps.common.writers import (
|
from apps.common.writers import write_bytes_fixed, write_uint8, write_uint32_be
|
||||||
write_bytes_fixed,
|
|
||||||
write_bytes_unchecked,
|
|
||||||
write_uint8,
|
|
||||||
write_uint32_be,
|
|
||||||
)
|
|
||||||
|
|
||||||
from . import CURVE, PATTERNS, SLIP44_ID, helpers, layout
|
from . import CURVE, PATTERNS, SLIP44_ID, helpers
|
||||||
|
from .helpers import ( # symbols used more than once
|
||||||
|
CONTRACT_ID_SIZE,
|
||||||
|
TAGGED_PUBKEY_HASH_SIZE,
|
||||||
|
base58_encode_check,
|
||||||
|
write_bool,
|
||||||
|
write_instruction,
|
||||||
|
)
|
||||||
|
|
||||||
if TYPE_CHECKING:
|
if TYPE_CHECKING:
|
||||||
from apps.common.keychain import Keychain
|
from apps.common.keychain import Keychain
|
||||||
@ -23,99 +21,115 @@ if TYPE_CHECKING:
|
|||||||
from trezor.messages import (
|
from trezor.messages import (
|
||||||
TezosSignTx,
|
TezosSignTx,
|
||||||
TezosContractID,
|
TezosContractID,
|
||||||
TezosManagerTransfer,
|
|
||||||
TezosBallotOp,
|
|
||||||
TezosProposalOp,
|
|
||||||
TezosRevealOp,
|
TezosRevealOp,
|
||||||
TezosDelegationOp,
|
TezosDelegationOp,
|
||||||
TezosTransactionOp,
|
TezosTransactionOp,
|
||||||
TezosOriginationOp,
|
TezosOriginationOp,
|
||||||
|
TezosSignedTx,
|
||||||
)
|
)
|
||||||
from trezor.utils import Writer
|
from trezor.utils import Writer
|
||||||
|
|
||||||
|
|
||||||
@with_slip44_keychain(*PATTERNS, slip44_id=SLIP44_ID, curve=CURVE)
|
@with_slip44_keychain(*PATTERNS, slip44_id=SLIP44_ID, curve=CURVE)
|
||||||
async def sign_tx(ctx: Context, msg: TezosSignTx, keychain: Keychain) -> TezosSignedTx:
|
async def sign_tx(ctx: Context, msg: TezosSignTx, keychain: Keychain) -> TezosSignedTx:
|
||||||
await paths.validate_path(ctx, keychain, msg.address_n)
|
from trezor.crypto import hashlib
|
||||||
|
from trezor.crypto.curve import ed25519
|
||||||
|
from apps.common.paths import validate_path
|
||||||
|
from trezor.messages import TezosSignedTx
|
||||||
|
from trezor.enums import TezosBallotType
|
||||||
|
from . import layout
|
||||||
|
|
||||||
|
await validate_path(ctx, keychain, msg.address_n)
|
||||||
|
|
||||||
node = keychain.derive(msg.address_n)
|
node = keychain.derive(msg.address_n)
|
||||||
|
transaction = msg.transaction # local_cache_attribute
|
||||||
|
origination = msg.origination # local_cache_attribute
|
||||||
|
delegation = msg.delegation # local_cache_attribute
|
||||||
|
|
||||||
|
if transaction is not None:
|
||||||
|
fee = transaction.fee # local_cache_attribute
|
||||||
|
parameters_manager = transaction.parameters_manager # local_cache_attribute
|
||||||
|
|
||||||
if msg.transaction is not None:
|
|
||||||
# if the transaction operation is used to execute code on a smart contract
|
# if the transaction operation is used to execute code on a smart contract
|
||||||
if msg.transaction.parameters_manager is not None:
|
if parameters_manager is not None:
|
||||||
parameters_manager = msg.transaction.parameters_manager
|
transfer = parameters_manager.transfer # local_cache_attribute
|
||||||
|
|
||||||
# operation to delegate from a smart contract with manager.tz
|
# operation to delegate from a smart contract with manager.tz
|
||||||
if parameters_manager.set_delegate is not None:
|
if parameters_manager.set_delegate is not None:
|
||||||
delegate = _get_address_by_tag(parameters_manager.set_delegate)
|
delegate = _get_address_by_tag(parameters_manager.set_delegate)
|
||||||
await layout.require_confirm_delegation_baker(ctx, delegate)
|
await layout.require_confirm_delegation_baker(ctx, delegate)
|
||||||
await layout.require_confirm_set_delegate(ctx, msg.transaction.fee)
|
await layout.require_confirm_set_delegate(ctx, fee)
|
||||||
|
|
||||||
# operation to remove delegate from the smart contract with manager.tz
|
# operation to remove delegate from the smart contract with manager.tz
|
||||||
elif parameters_manager.cancel_delegate is not None:
|
elif parameters_manager.cancel_delegate is not None:
|
||||||
address = _get_address_from_contract(msg.transaction.destination)
|
address = _get_address_from_contract(transaction.destination)
|
||||||
await layout.require_confirm_delegation_manager_withdraw(ctx, address)
|
await layout.require_confirm_delegation_manager_withdraw(ctx, address)
|
||||||
await layout.require_confirm_manager_remove_delegate(
|
await layout.require_confirm_manager_remove_delegate(ctx, fee)
|
||||||
ctx, msg.transaction.fee
|
|
||||||
)
|
|
||||||
|
|
||||||
# operation to transfer tokens from a smart contract to an implicit account or a smart contract
|
# operation to transfer tokens from a smart contract to an implicit account or a smart contract
|
||||||
elif parameters_manager.transfer is not None:
|
elif transfer is not None:
|
||||||
to = _get_address_from_contract(parameters_manager.transfer.destination)
|
to = _get_address_from_contract(transfer.destination)
|
||||||
await layout.require_confirm_tx(
|
await layout.require_confirm_tx(ctx, to, transfer.amount)
|
||||||
ctx, to, parameters_manager.transfer.amount
|
await layout.require_confirm_fee(ctx, transfer.amount, fee)
|
||||||
)
|
|
||||||
await layout.require_confirm_fee(
|
|
||||||
ctx, parameters_manager.transfer.amount, msg.transaction.fee
|
|
||||||
)
|
|
||||||
else:
|
else:
|
||||||
# transactions from an implicit account
|
# transactions from an implicit account
|
||||||
to = _get_address_from_contract(msg.transaction.destination)
|
to = _get_address_from_contract(transaction.destination)
|
||||||
await layout.require_confirm_tx(ctx, to, msg.transaction.amount)
|
await layout.require_confirm_tx(ctx, to, transaction.amount)
|
||||||
await layout.require_confirm_fee(
|
await layout.require_confirm_fee(ctx, transaction.amount, fee)
|
||||||
ctx, msg.transaction.amount, msg.transaction.fee
|
|
||||||
)
|
|
||||||
|
|
||||||
elif msg.origination is not None:
|
elif origination is not None:
|
||||||
source = _get_address_by_tag(msg.origination.source)
|
source = _get_address_by_tag(origination.source)
|
||||||
await layout.require_confirm_origination(ctx, source)
|
await layout.require_confirm_origination(ctx, source)
|
||||||
|
|
||||||
# if we are immediately delegating contract
|
# if we are immediately delegating contract
|
||||||
if msg.origination.delegate is not None:
|
if origination.delegate is not None:
|
||||||
delegate = _get_address_by_tag(msg.origination.delegate)
|
delegate = _get_address_by_tag(origination.delegate)
|
||||||
await layout.require_confirm_delegation_baker(ctx, delegate)
|
await layout.require_confirm_delegation_baker(ctx, delegate)
|
||||||
|
|
||||||
await layout.require_confirm_origination_fee(
|
await layout.require_confirm_origination_fee(
|
||||||
ctx, msg.origination.balance, msg.origination.fee
|
ctx, origination.balance, origination.fee
|
||||||
)
|
)
|
||||||
|
|
||||||
elif msg.delegation is not None:
|
elif delegation is not None:
|
||||||
source = _get_address_by_tag(msg.delegation.source)
|
source = _get_address_by_tag(delegation.source)
|
||||||
|
|
||||||
delegate_address: str | None = None
|
delegate_address: str | None = None
|
||||||
if msg.delegation.delegate is not None:
|
if delegation.delegate is not None:
|
||||||
delegate_address = _get_address_by_tag(msg.delegation.delegate)
|
delegate_address = _get_address_by_tag(delegation.delegate)
|
||||||
|
|
||||||
if delegate_address is not None and source != delegate_address:
|
if delegate_address is not None and source != delegate_address:
|
||||||
await layout.require_confirm_delegation_baker(ctx, delegate_address)
|
await layout.require_confirm_delegation_baker(ctx, delegate_address)
|
||||||
await layout.require_confirm_set_delegate(ctx, msg.delegation.fee)
|
await layout.require_confirm_set_delegate(ctx, delegation.fee)
|
||||||
# if account registers itself as a delegate
|
# if account registers itself as a delegate
|
||||||
else:
|
else:
|
||||||
await layout.require_confirm_register_delegate(
|
await layout.require_confirm_register_delegate(ctx, source, delegation.fee)
|
||||||
ctx, source, msg.delegation.fee
|
|
||||||
)
|
|
||||||
|
|
||||||
elif msg.proposal is not None:
|
elif msg.proposal is not None:
|
||||||
proposed_protocols = [_get_protocol_hash(p) for p in msg.proposal.proposals]
|
proposed_protocols = [
|
||||||
|
# _get_protocol_hash
|
||||||
|
base58_encode_check(p, "P")
|
||||||
|
for p in msg.proposal.proposals
|
||||||
|
]
|
||||||
await layout.require_confirm_proposals(ctx, proposed_protocols)
|
await layout.require_confirm_proposals(ctx, proposed_protocols)
|
||||||
|
|
||||||
elif msg.ballot is not None:
|
elif msg.ballot is not None:
|
||||||
proposed_protocol = _get_protocol_hash(msg.ballot.proposal)
|
# _get_protocol_hash
|
||||||
submitted_ballot = _get_ballot(msg.ballot.ballot)
|
proposed_protocol = base58_encode_check(msg.ballot.proposal, "P")
|
||||||
|
|
||||||
|
# _get_ballot
|
||||||
|
if msg.ballot.ballot == TezosBallotType.Yay:
|
||||||
|
submitted_ballot = "yay"
|
||||||
|
elif msg.ballot.ballot == TezosBallotType.Nay:
|
||||||
|
submitted_ballot = "nay"
|
||||||
|
elif msg.ballot.ballot == TezosBallotType.Pass:
|
||||||
|
submitted_ballot = "pass"
|
||||||
|
else:
|
||||||
|
raise RuntimeError # unrecognized enum value
|
||||||
|
|
||||||
await layout.require_confirm_ballot(ctx, proposed_protocol, submitted_ballot)
|
await layout.require_confirm_ballot(ctx, proposed_protocol, submitted_ballot)
|
||||||
|
|
||||||
else:
|
else:
|
||||||
raise wire.DataError("Invalid operation")
|
raise DataError("Invalid operation")
|
||||||
|
|
||||||
w = bytearray()
|
w = bytearray()
|
||||||
_get_operation_bytes(w, msg)
|
_get_operation_bytes(w, msg)
|
||||||
@ -131,11 +145,9 @@ async def sign_tx(ctx: Context, msg: TezosSignTx, keychain: Keychain) -> TezosSi
|
|||||||
|
|
||||||
sig_op_contents = opbytes + signature
|
sig_op_contents = opbytes + signature
|
||||||
sig_op_contents_hash = hashlib.blake2b(sig_op_contents, outlen=32).digest()
|
sig_op_contents_hash = hashlib.blake2b(sig_op_contents, outlen=32).digest()
|
||||||
ophash = helpers.base58_encode_check(sig_op_contents_hash, prefix="o")
|
ophash = base58_encode_check(sig_op_contents_hash, "o")
|
||||||
|
|
||||||
sig_prefixed = helpers.base58_encode_check(
|
sig_prefixed = base58_encode_check(signature, helpers.TEZOS_SIGNATURE_PREFIX)
|
||||||
signature, prefix=helpers.TEZOS_SIGNATURE_PREFIX
|
|
||||||
)
|
|
||||||
|
|
||||||
return TezosSignedTx(
|
return TezosSignedTx(
|
||||||
signature=sig_prefixed, sig_op_contents=sig_op_contents, operation_hash=ophash
|
signature=sig_prefixed, sig_op_contents=sig_op_contents, operation_hash=ophash
|
||||||
@ -147,8 +159,8 @@ def _get_address_by_tag(address_hash: bytes) -> str:
|
|||||||
tag = int(address_hash[0])
|
tag = int(address_hash[0])
|
||||||
|
|
||||||
if 0 <= tag < len(prefixes):
|
if 0 <= tag < len(prefixes):
|
||||||
return helpers.base58_encode_check(address_hash[1:], prefix=prefixes[tag])
|
return base58_encode_check(address_hash[1:], prefixes[tag])
|
||||||
raise wire.DataError("Invalid tag in address hash")
|
raise DataError("Invalid tag in address hash")
|
||||||
|
|
||||||
|
|
||||||
def _get_address_from_contract(address: TezosContractID) -> str:
|
def _get_address_from_contract(address: TezosContractID) -> str:
|
||||||
@ -156,94 +168,144 @@ def _get_address_from_contract(address: TezosContractID) -> str:
|
|||||||
return _get_address_by_tag(address.hash)
|
return _get_address_by_tag(address.hash)
|
||||||
|
|
||||||
elif address.tag == TezosContractType.Originated:
|
elif address.tag == TezosContractType.Originated:
|
||||||
return helpers.base58_encode_check(
|
return base58_encode_check(
|
||||||
address.hash[:-1], prefix=helpers.TEZOS_ORIGINATED_ADDRESS_PREFIX
|
address.hash[:-1], helpers.TEZOS_ORIGINATED_ADDRESS_PREFIX
|
||||||
)
|
)
|
||||||
|
|
||||||
raise wire.DataError("Invalid contract type")
|
raise DataError("Invalid contract type")
|
||||||
|
|
||||||
|
|
||||||
def _get_protocol_hash(proposal: bytes) -> str:
|
|
||||||
return helpers.base58_encode_check(proposal, prefix="P")
|
|
||||||
|
|
||||||
|
|
||||||
def _get_ballot(ballot: TezosBallotType) -> str:
|
|
||||||
if ballot == TezosBallotType.Yay:
|
|
||||||
return "yay"
|
|
||||||
elif ballot == TezosBallotType.Nay:
|
|
||||||
return "nay"
|
|
||||||
elif ballot == TezosBallotType.Pass:
|
|
||||||
return "pass"
|
|
||||||
|
|
||||||
raise RuntimeError # unrecognized enum value
|
|
||||||
|
|
||||||
|
|
||||||
def _get_operation_bytes(w: Writer, msg: TezosSignTx) -> None:
|
def _get_operation_bytes(w: Writer, msg: TezosSignTx) -> None:
|
||||||
|
from apps.common.writers import write_bytes_unchecked
|
||||||
|
from .helpers import PROPOSAL_HASH_SIZE
|
||||||
|
|
||||||
|
reveal = msg.reveal # local_cache_attribute
|
||||||
|
|
||||||
write_bytes_fixed(w, msg.branch, helpers.BRANCH_HASH_SIZE)
|
write_bytes_fixed(w, msg.branch, helpers.BRANCH_HASH_SIZE)
|
||||||
|
|
||||||
# when the account sends first operation in lifetime,
|
# when the account sends first operation in lifetime,
|
||||||
# we need to reveal its public key
|
# we need to reveal its public key
|
||||||
if msg.reveal is not None:
|
if reveal is not None:
|
||||||
_encode_common(w, msg.reveal, "reveal")
|
_encode_common(w, reveal, "reveal")
|
||||||
tag = int(msg.reveal.public_key[0])
|
tag = int(reveal.public_key[0])
|
||||||
|
|
||||||
try:
|
try:
|
||||||
public_key_size = helpers.PUBLIC_KEY_TAG_TO_SIZE[tag]
|
public_key_size = helpers.PUBLIC_KEY_TAG_TO_SIZE[tag]
|
||||||
except KeyError:
|
except KeyError:
|
||||||
raise wire.DataError("Invalid tag in public key")
|
raise DataError("Invalid tag in public key")
|
||||||
|
|
||||||
write_bytes_fixed(w, msg.reveal.public_key, 1 + public_key_size)
|
write_bytes_fixed(w, reveal.public_key, 1 + public_key_size)
|
||||||
|
|
||||||
# transaction operation
|
# transaction operation
|
||||||
if msg.transaction is not None:
|
if msg.transaction is not None:
|
||||||
_encode_common(w, msg.transaction, "transaction")
|
transaction = msg.transaction
|
||||||
_encode_zarith(w, msg.transaction.amount)
|
_encode_common(w, transaction, "transaction")
|
||||||
_encode_contract_id(w, msg.transaction.destination)
|
_encode_zarith(w, transaction.amount)
|
||||||
|
|
||||||
|
# _encode_contract_id
|
||||||
|
contract_id = transaction.destination
|
||||||
|
write_uint8(w, contract_id.tag)
|
||||||
|
write_bytes_fixed(w, contract_id.hash, CONTRACT_ID_SIZE - 1)
|
||||||
|
|
||||||
# support delegation and transfer from the old scriptless contracts (now with manager.tz script)
|
# support delegation and transfer from the old scriptless contracts (now with manager.tz script)
|
||||||
if msg.transaction.parameters_manager is not None:
|
if transaction.parameters_manager is not None:
|
||||||
parameters_manager = msg.transaction.parameters_manager
|
parameters_manager = transaction.parameters_manager # local_cache_attribute
|
||||||
|
transfer = parameters_manager.transfer # local_cache_attribute
|
||||||
|
|
||||||
if parameters_manager.set_delegate is not None:
|
if parameters_manager.set_delegate is not None:
|
||||||
_encode_manager_delegation(w, parameters_manager.set_delegate)
|
# _encode_manager_delegation
|
||||||
|
delegate = parameters_manager.set_delegate
|
||||||
|
michelson_length = 42
|
||||||
|
_encode_manager_common(w, michelson_length, "PUSH")
|
||||||
|
write_bytes_fixed(w, delegate, TAGGED_PUBKEY_HASH_SIZE)
|
||||||
|
for i in ("SOME", "SET_DELEGATE", "CONS"):
|
||||||
|
write_instruction(w, i)
|
||||||
elif parameters_manager.cancel_delegate is not None:
|
elif parameters_manager.cancel_delegate is not None:
|
||||||
_encode_manager_delegation_remove(w)
|
# _encode_manager_delegation_remove
|
||||||
elif parameters_manager.transfer is not None:
|
michelson_length = 14
|
||||||
assert parameters_manager.transfer.destination is not None
|
_encode_manager_common(w, michelson_length, "NONE")
|
||||||
if (
|
for i in ("SET_DELEGATE", "CONS"):
|
||||||
parameters_manager.transfer.destination.tag
|
write_instruction(w, i)
|
||||||
== TezosContractType.Implicit
|
elif transfer is not None:
|
||||||
):
|
assert transfer.destination is not None
|
||||||
_encode_manager_to_implicit_transfer(w, parameters_manager.transfer)
|
if transfer.destination.tag == TezosContractType.Implicit:
|
||||||
|
# _encode_manager_to_implicit_transfer
|
||||||
|
manager_transfer = transfer
|
||||||
|
michelson_length = 48
|
||||||
|
value_natural = bytearray()
|
||||||
|
_encode_natural(value_natural, manager_transfer.amount)
|
||||||
|
sequence_length = michelson_length + len(value_natural)
|
||||||
|
|
||||||
|
_encode_manager_common(w, sequence_length, "PUSH")
|
||||||
|
write_bytes_fixed(
|
||||||
|
w, manager_transfer.destination.hash, TAGGED_PUBKEY_HASH_SIZE
|
||||||
|
)
|
||||||
|
for i in ("IMPLICIT_ACCOUNT", "PUSH", "mutez"):
|
||||||
|
write_instruction(w, i)
|
||||||
|
_encode_natural(w, manager_transfer.amount)
|
||||||
|
for i in ("UNIT", "TRANSFER_TOKENS", "CONS"):
|
||||||
|
write_instruction(w, i)
|
||||||
else:
|
else:
|
||||||
_encode_manager_to_manager_transfer(w, parameters_manager.transfer)
|
# _encode_manager_to_manager_transfer
|
||||||
|
manager_transfer = transfer
|
||||||
|
michelson_length = 77
|
||||||
|
|
||||||
|
value_natural = bytearray()
|
||||||
|
_encode_natural(value_natural, manager_transfer.amount)
|
||||||
|
sequence_length = michelson_length + len(value_natural)
|
||||||
|
|
||||||
|
_encode_manager_common(w, sequence_length, "PUSH", to_contract=True)
|
||||||
|
|
||||||
|
# _encode_contract_id
|
||||||
|
contract_id = manager_transfer.destination
|
||||||
|
write_uint8(w, contract_id.tag)
|
||||||
|
write_bytes_fixed(w, contract_id.hash, CONTRACT_ID_SIZE - 1)
|
||||||
|
|
||||||
|
for i in ("CONTRACT", "unit", "ASSERT_SOME", "PUSH", "mutez"):
|
||||||
|
write_instruction(w, i)
|
||||||
|
_encode_natural(w, manager_transfer.amount)
|
||||||
|
for i in ("UNIT", "TRANSFER_TOKENS", "CONS"):
|
||||||
|
write_instruction(w, i)
|
||||||
else:
|
else:
|
||||||
if msg.transaction.parameters:
|
parameters = transaction.parameters # local_cache_attribute
|
||||||
helpers.write_bool(w, True)
|
if parameters:
|
||||||
helpers.check_tx_params_size(msg.transaction.parameters)
|
write_bool(w, True)
|
||||||
write_bytes_unchecked(w, msg.transaction.parameters)
|
helpers.check_tx_params_size(parameters)
|
||||||
|
write_bytes_unchecked(w, parameters)
|
||||||
else:
|
else:
|
||||||
helpers.write_bool(w, False)
|
write_bool(w, False)
|
||||||
# origination operation
|
# origination operation
|
||||||
elif msg.origination is not None:
|
elif msg.origination is not None:
|
||||||
_encode_common(w, msg.origination, "origination")
|
origination = msg.origination
|
||||||
_encode_zarith(w, msg.origination.balance)
|
_encode_common(w, origination, "origination")
|
||||||
_encode_data_with_bool_prefix(
|
_encode_zarith(w, origination.balance)
|
||||||
w, msg.origination.delegate, helpers.TAGGED_PUBKEY_HASH_SIZE
|
_encode_data_with_bool_prefix(w, origination.delegate, TAGGED_PUBKEY_HASH_SIZE)
|
||||||
)
|
helpers.check_script_size(origination.script)
|
||||||
helpers.check_script_size(msg.origination.script)
|
write_bytes_unchecked(w, origination.script)
|
||||||
write_bytes_unchecked(w, msg.origination.script)
|
|
||||||
|
|
||||||
# delegation operation
|
# delegation operation
|
||||||
elif msg.delegation is not None:
|
elif msg.delegation is not None:
|
||||||
_encode_common(w, msg.delegation, "delegation")
|
_encode_common(w, msg.delegation, "delegation")
|
||||||
_encode_data_with_bool_prefix(
|
_encode_data_with_bool_prefix(
|
||||||
w, msg.delegation.delegate, helpers.TAGGED_PUBKEY_HASH_SIZE
|
w, msg.delegation.delegate, TAGGED_PUBKEY_HASH_SIZE
|
||||||
)
|
)
|
||||||
elif msg.proposal is not None:
|
elif msg.proposal is not None:
|
||||||
_encode_proposal(w, msg.proposal)
|
# _encode_proposal
|
||||||
|
proposal = msg.proposal
|
||||||
|
write_uint8(w, helpers.OP_TAG_PROPOSALS)
|
||||||
|
write_bytes_fixed(w, proposal.source, TAGGED_PUBKEY_HASH_SIZE)
|
||||||
|
write_uint32_be(w, proposal.period)
|
||||||
|
write_uint32_be(w, len(proposal.proposals) * PROPOSAL_HASH_SIZE)
|
||||||
|
for proposal_hash in proposal.proposals:
|
||||||
|
write_bytes_fixed(w, proposal_hash, PROPOSAL_HASH_SIZE)
|
||||||
elif msg.ballot is not None:
|
elif msg.ballot is not None:
|
||||||
_encode_ballot(w, msg.ballot)
|
# _encode_ballot
|
||||||
|
ballot = msg.ballot
|
||||||
|
write_uint8(w, helpers.OP_TAG_BALLOT)
|
||||||
|
write_bytes_fixed(w, ballot.source, TAGGED_PUBKEY_HASH_SIZE)
|
||||||
|
write_uint32_be(w, ballot.period)
|
||||||
|
write_bytes_fixed(w, ballot.proposal, PROPOSAL_HASH_SIZE)
|
||||||
|
write_uint8(w, ballot.ballot)
|
||||||
|
|
||||||
|
|
||||||
def _encode_common(
|
def _encode_common(
|
||||||
@ -261,16 +323,14 @@ def _encode_common(
|
|||||||
"delegation": helpers.OP_TAG_DELEGATION,
|
"delegation": helpers.OP_TAG_DELEGATION,
|
||||||
}
|
}
|
||||||
write_uint8(w, operation_tags[str_operation])
|
write_uint8(w, operation_tags[str_operation])
|
||||||
write_bytes_fixed(w, operation.source, helpers.TAGGED_PUBKEY_HASH_SIZE)
|
write_bytes_fixed(w, operation.source, TAGGED_PUBKEY_HASH_SIZE)
|
||||||
_encode_zarith(w, operation.fee)
|
for num in (
|
||||||
_encode_zarith(w, operation.counter)
|
operation.fee,
|
||||||
_encode_zarith(w, operation.gas_limit)
|
operation.counter,
|
||||||
_encode_zarith(w, operation.storage_limit)
|
operation.gas_limit,
|
||||||
|
operation.storage_limit,
|
||||||
|
):
|
||||||
def _encode_contract_id(w: Writer, contract_id: TezosContractID) -> None:
|
_encode_zarith(w, num)
|
||||||
write_uint8(w, contract_id.tag)
|
|
||||||
write_bytes_fixed(w, contract_id.hash, helpers.CONTRACT_ID_SIZE - 1)
|
|
||||||
|
|
||||||
|
|
||||||
def _encode_data_with_bool_prefix(
|
def _encode_data_with_bool_prefix(
|
||||||
@ -295,23 +355,6 @@ def _encode_zarith(w: Writer, num: int) -> None:
|
|||||||
write_uint8(w, 128 | byte)
|
write_uint8(w, 128 | byte)
|
||||||
|
|
||||||
|
|
||||||
def _encode_proposal(w: Writer, proposal: TezosProposalOp) -> None:
|
|
||||||
write_uint8(w, helpers.OP_TAG_PROPOSALS)
|
|
||||||
write_bytes_fixed(w, proposal.source, helpers.TAGGED_PUBKEY_HASH_SIZE)
|
|
||||||
write_uint32_be(w, proposal.period)
|
|
||||||
write_uint32_be(w, len(proposal.proposals) * helpers.PROPOSAL_HASH_SIZE)
|
|
||||||
for proposal_hash in proposal.proposals:
|
|
||||||
write_bytes_fixed(w, proposal_hash, helpers.PROPOSAL_HASH_SIZE)
|
|
||||||
|
|
||||||
|
|
||||||
def _encode_ballot(w: Writer, ballot: TezosBallotOp) -> None:
|
|
||||||
write_uint8(w, helpers.OP_TAG_BALLOT)
|
|
||||||
write_bytes_fixed(w, ballot.source, helpers.TAGGED_PUBKEY_HASH_SIZE)
|
|
||||||
write_uint32_be(w, ballot.period)
|
|
||||||
write_bytes_fixed(w, ballot.proposal, helpers.PROPOSAL_HASH_SIZE)
|
|
||||||
write_uint8(w, ballot.ballot)
|
|
||||||
|
|
||||||
|
|
||||||
def _encode_natural(w: Writer, num: int) -> None:
|
def _encode_natural(w: Writer, num: int) -> None:
|
||||||
# encode a natural integer with its signed bit on position 7
|
# encode a natural integer with its signed bit on position 7
|
||||||
# as we do not expect negative numbers in a transfer operation the bit is never set
|
# as we do not expect negative numbers in a transfer operation the bit is never set
|
||||||
@ -334,84 +377,20 @@ def _encode_manager_common(
|
|||||||
# 5 = tag and sequence_length (1 byte + 4 bytes)
|
# 5 = tag and sequence_length (1 byte + 4 bytes)
|
||||||
argument_length = sequence_length + 5
|
argument_length = sequence_length + 5
|
||||||
|
|
||||||
helpers.write_bool(w, True)
|
write_bool(w, True)
|
||||||
write_uint8(w, helpers.DO_ENTRYPOINT_TAG)
|
write_uint8(w, helpers.DO_ENTRYPOINT_TAG)
|
||||||
write_uint32_be(w, argument_length)
|
write_uint32_be(w, argument_length)
|
||||||
write_uint8(w, helpers.MICHELSON_SEQUENCE_TAG)
|
write_uint8(w, helpers.MICHELSON_SEQUENCE_TAG)
|
||||||
write_uint32_be(w, sequence_length)
|
write_uint32_be(w, sequence_length)
|
||||||
helpers.write_instruction(w, "DROP")
|
for i in ("DROP", "NIL", "operation", operation):
|
||||||
helpers.write_instruction(w, "NIL")
|
write_instruction(w, i)
|
||||||
helpers.write_instruction(w, "operation")
|
|
||||||
helpers.write_instruction(w, operation)
|
|
||||||
if to_contract:
|
if to_contract:
|
||||||
helpers.write_instruction(w, "address")
|
write_instruction(w, "address")
|
||||||
else:
|
else:
|
||||||
helpers.write_instruction(w, "key_hash")
|
write_instruction(w, "key_hash")
|
||||||
if operation == "PUSH":
|
if operation == "PUSH":
|
||||||
write_uint8(w, 10) # byte sequence
|
write_uint8(w, 10) # byte sequence
|
||||||
if to_contract:
|
if to_contract:
|
||||||
write_uint32_be(w, helpers.CONTRACT_ID_SIZE)
|
write_uint32_be(w, CONTRACT_ID_SIZE)
|
||||||
else:
|
else:
|
||||||
write_uint32_be(w, helpers.TAGGED_PUBKEY_HASH_SIZE)
|
write_uint32_be(w, TAGGED_PUBKEY_HASH_SIZE)
|
||||||
|
|
||||||
|
|
||||||
def _encode_manager_to_implicit_transfer(
|
|
||||||
w: Writer, manager_transfer: TezosManagerTransfer
|
|
||||||
) -> None:
|
|
||||||
MICHELSON_LENGTH = 48
|
|
||||||
|
|
||||||
value_natural = bytearray()
|
|
||||||
_encode_natural(value_natural, manager_transfer.amount)
|
|
||||||
sequence_length = MICHELSON_LENGTH + len(value_natural)
|
|
||||||
|
|
||||||
_encode_manager_common(w, sequence_length, "PUSH")
|
|
||||||
write_bytes_fixed(
|
|
||||||
w, manager_transfer.destination.hash, helpers.TAGGED_PUBKEY_HASH_SIZE
|
|
||||||
)
|
|
||||||
helpers.write_instruction(w, "IMPLICIT_ACCOUNT")
|
|
||||||
helpers.write_instruction(w, "PUSH")
|
|
||||||
helpers.write_instruction(w, "mutez")
|
|
||||||
_encode_natural(w, manager_transfer.amount)
|
|
||||||
helpers.write_instruction(w, "UNIT")
|
|
||||||
helpers.write_instruction(w, "TRANSFER_TOKENS")
|
|
||||||
helpers.write_instruction(w, "CONS")
|
|
||||||
|
|
||||||
|
|
||||||
# smart_contract_delegation
|
|
||||||
def _encode_manager_delegation(w: Writer, delegate: bytes) -> None:
|
|
||||||
MICHELSON_LENGTH = 42 # length is fixed this time(no variable length fields)
|
|
||||||
|
|
||||||
_encode_manager_common(w, MICHELSON_LENGTH, "PUSH")
|
|
||||||
write_bytes_fixed(w, delegate, helpers.TAGGED_PUBKEY_HASH_SIZE)
|
|
||||||
helpers.write_instruction(w, "SOME")
|
|
||||||
helpers.write_instruction(w, "SET_DELEGATE")
|
|
||||||
helpers.write_instruction(w, "CONS")
|
|
||||||
|
|
||||||
|
|
||||||
def _encode_manager_delegation_remove(w: Writer) -> None:
|
|
||||||
MICHELSON_LENGTH = 14 # length is fixed this time(no variable length fields)
|
|
||||||
_encode_manager_common(w, MICHELSON_LENGTH, "NONE")
|
|
||||||
helpers.write_instruction(w, "SET_DELEGATE")
|
|
||||||
helpers.write_instruction(w, "CONS")
|
|
||||||
|
|
||||||
|
|
||||||
def _encode_manager_to_manager_transfer(
|
|
||||||
w: Writer, manager_transfer: TezosManagerTransfer
|
|
||||||
) -> None:
|
|
||||||
MICHELSON_LENGTH = 77
|
|
||||||
|
|
||||||
value_natural = bytearray()
|
|
||||||
_encode_natural(value_natural, manager_transfer.amount)
|
|
||||||
sequence_length = MICHELSON_LENGTH + len(value_natural)
|
|
||||||
|
|
||||||
_encode_manager_common(w, sequence_length, "PUSH", to_contract=True)
|
|
||||||
_encode_contract_id(w, manager_transfer.destination)
|
|
||||||
helpers.write_instruction(w, "CONTRACT")
|
|
||||||
helpers.write_instruction(w, "unit")
|
|
||||||
helpers.write_instruction(w, "ASSERT_SOME")
|
|
||||||
helpers.write_instruction(w, "PUSH")
|
|
||||||
helpers.write_instruction(w, "mutez")
|
|
||||||
_encode_natural(w, manager_transfer.amount)
|
|
||||||
helpers.write_instruction(w, "UNIT")
|
|
||||||
helpers.write_instruction(w, "TRANSFER_TOKENS")
|
|
||||||
helpers.write_instruction(w, "CONS")
|
|
||||||
|
@ -3,15 +3,22 @@ from common import *
|
|||||||
if not utils.BITCOIN_ONLY:
|
if not utils.BITCOIN_ONLY:
|
||||||
from trezor.enums import TezosContractType
|
from trezor.enums import TezosContractType
|
||||||
from trezor.messages import TezosContractID
|
from trezor.messages import TezosContractID
|
||||||
from apps.tezos.helpers import base58_encode_check, write_bool
|
from apps.tezos.helpers import base58_encode_check, write_bool, CONTRACT_ID_SIZE
|
||||||
from apps.tezos.sign_tx import (
|
from apps.tezos.sign_tx import (
|
||||||
_encode_contract_id,
|
write_uint8,
|
||||||
|
write_bytes_fixed,
|
||||||
_encode_data_with_bool_prefix,
|
_encode_data_with_bool_prefix,
|
||||||
_encode_zarith,
|
_encode_zarith,
|
||||||
_encode_natural,
|
_encode_natural,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
|
# NOTE: copy-pasted from apps.tezos.sign_tx
|
||||||
|
def _encode_contract_id(w: "Writer", contract_id: TezosContractID) -> None:
|
||||||
|
write_uint8(w, contract_id.tag)
|
||||||
|
write_bytes_fixed(w, contract_id.hash, CONTRACT_ID_SIZE - 1)
|
||||||
|
|
||||||
|
|
||||||
@unittest.skipUnless(not utils.BITCOIN_ONLY, "altcoin")
|
@unittest.skipUnless(not utils.BITCOIN_ONLY, "altcoin")
|
||||||
class TestTezosEncoding(unittest.TestCase):
|
class TestTezosEncoding(unittest.TestCase):
|
||||||
def test_tezos_encode_zarith(self):
|
def test_tezos_encode_zarith(self):
|
||||||
|
Loading…
Reference in New Issue
Block a user