diff --git a/common/protob/messages-tezos.proto b/common/protob/messages-tezos.proto index d6fbfea65a..474f18628f 100644 --- a/common/protob/messages-tezos.proto +++ b/common/protob/messages-tezos.proto @@ -75,7 +75,7 @@ message TezosSignTx { * Structure representing information for reveal */ message TezosRevealOp { - optional TezosContractID source = 1; + optional bytes source = 7; optional uint64 fee = 2; optional uint64 counter = 3; optional uint64 gas_limit = 4; @@ -86,7 +86,7 @@ message TezosSignTx { * Structure representing information for transaction */ message TezosTransactionOp { - optional TezosContractID source = 1; + optional bytes source = 9; optional uint64 fee = 2; optional uint64 counter = 3; optional uint64 gas_limit = 4; @@ -94,12 +94,24 @@ message TezosSignTx { optional uint64 amount = 6; optional TezosContractID destination = 7; optional bytes parameters = 8; + optional TezosParametersManager parameters_manager = 10; + + message TezosParametersManager { + optional bytes set_delegate = 1; + optional bool cancel_delegate = 2; + optional TezosManagerTransfer transfer = 3; + + message TezosManagerTransfer { + optional TezosContractID destination = 1; + optional uint64 amount = 2; + } + } } /** * Structure representing information for origination */ message TezosOriginationOp { - optional TezosContractID source = 1; + optional bytes source = 12; optional uint64 fee = 2; optional uint64 counter = 3; optional uint64 gas_limit = 4; @@ -115,7 +127,7 @@ message TezosSignTx { * Structure representing information for delegation */ message TezosDelegationOp { - optional TezosContractID source = 1; + optional bytes source = 7; optional uint64 fee = 2; optional uint64 counter = 3; optional uint64 gas_limit = 4; diff --git a/core/src/apps/tezos/helpers.py b/core/src/apps/tezos/helpers.py index 73bd02d1f8..5e1f50c6a8 100644 --- a/core/src/apps/tezos/helpers.py +++ b/core/src/apps/tezos/helpers.py @@ -26,6 +26,58 @@ TEZOS_PREFIX_BYTES = { "P": [2, 170], } +# MICHELSON instruction bytes +MICHELSON_INSTRUCTION_BYTES = { + "DROP": [3, 32], # '0320' + "NIL": [5, 61], # '053d' + "operation": [3, 109], # '036d' + "NONE": [5, 62], # '053e' + "key_hash": [3, 93], # '035d' + "SET_DELEGATE": [3, 78], # '034e' + "CONS": [3, 27], # '031b' + "IMPLICIT_ACCOUNT": [3, 30], # '031e' + "PUSH": [7, 67], # '0743' + "mutez": [3, 106], # '036a' + "UNIT": [3, 79], # '034f' + "TRANSFER_TOKENS": [3, 77], # '034d' + "SOME": [3, 70], # '0346' + "address": [3, 110], # '036e' + "CONTRACT": [5, 85], # '0555' + "unit": [3, 108], # '036c' + # ASSERT_SOME unfolded as { IF_NONE { { UNIT ; FAILWITH } } {} } + "ASSERT_SOME": [ + 2, + 0, + 0, + 0, + 21, + 7, + 47, + 2, + 0, + 0, + 0, + 9, + 2, + 0, + 0, + 0, + 4, + 3, + 79, + 3, + 39, + 2, + 0, + 0, + 0, + 0, + ], +} + +DO_ENTRYPOINT_TAG = const(2) +MICHELSON_SEQUENCE_TAG = const(2) + def base58_encode_check(payload, prefix=None): result = payload diff --git a/core/src/apps/tezos/layout.py b/core/src/apps/tezos/layout.py index 672de53857..e7cd4793fb 100644 --- a/core/src/apps/tezos/layout.py +++ b/core/src/apps/tezos/layout.py @@ -99,3 +99,17 @@ async def require_confirm_proposals(ctx, proposals): paginated = Paginated(pages) await require_confirm(ctx, paginated, ButtonRequestType.SignTx) + + +async def require_confirm_delegation_manager_withdraw(ctx, address): + text = Text("Cancel delegation", ui.ICON_RECEIVE, icon_color=ui.RED) + text.bold("Delegator:") + text.mono(*split_address(address)) + await require_confirm(ctx, text, ButtonRequestType.SignTx) + + +async def require_confirm_manager_remove_delegate(ctx, fee): + text = Text("Cancel delegation", ui.ICON_RECEIVE, ui.RED) + text.normal("Fee:") + text.bold(format_tezos_amount(fee)) + await require_hold_to_confirm(ctx, text, ButtonRequestType.SignTx) diff --git a/core/src/apps/tezos/sign_tx.py b/core/src/apps/tezos/sign_tx.py index a15f96853b..91281d8d0f 100644 --- a/core/src/apps/tezos/sign_tx.py +++ b/core/src/apps/tezos/sign_tx.py @@ -21,14 +21,43 @@ async def sign_tx(ctx, msg, keychain): node = keychain.derive(msg.address_n, CURVE) if msg.transaction is not None: - to = _get_address_from_contract(msg.transaction.destination) - await layout.require_confirm_tx(ctx, to, msg.transaction.amount) - await layout.require_confirm_fee( - ctx, msg.transaction.amount, msg.transaction.fee - ) + # if the tranasction oprtation is used to execute code on a smart contract + if msg.transaction.parameters_manager is not None: + parameters_manager = msg.transaction.parameters_manager + + # operation to delegate from a smart contract with manager.tz + if parameters_manager.set_delegate is not None: + delegate = _get_address_by_tag(parameters_manager.set_delegate) + await layout.require_confirm_delegation_baker(ctx, delegate) + await layout.require_confirm_set_delegate(ctx, msg.transaction.fee) + + # operation to remove delegate from the smart contract with manager.tz + elif parameters_manager.cancel_delegate is not None: + address = _get_address_from_contract(msg.transaction.destination) + await layout.require_confirm_delegation_manager_withdraw(ctx, address) + await layout.require_confirm_manager_remove_delegate( + ctx, msg.transaction.fee + ) + + # operation to transfer tokens from a smart contract to an implicit account or a smart contract + elif parameters_manager.transfer is not None: + to = _get_address_from_contract(parameters_manager.transfer.destination) + await layout.require_confirm_tx( + ctx, to, parameters_manager.transfer.amount + ) + await layout.require_confirm_fee( + ctx, parameters_manager.transfer.amount, msg.transaction.fee + ) + else: + # transactions from an implicit account + to = _get_address_from_contract(msg.transaction.destination) + await layout.require_confirm_tx(ctx, to, msg.transaction.amount) + await layout.require_confirm_fee( + ctx, msg.transaction.amount, msg.transaction.fee + ) elif msg.origination is not None: - source = _get_address_from_contract(msg.origination.source) + source = _get_address_by_tag(msg.origination.source) await layout.require_confirm_origination(ctx, source) # if we are immediately delegating contract @@ -41,7 +70,7 @@ async def sign_tx(ctx, msg, keychain): ) elif msg.delegation is not None: - source = _get_address_from_contract(msg.delegation.source) + source = _get_address_by_tag(msg.delegation.source) delegate = None if msg.delegation.delegate is not None: @@ -141,16 +170,32 @@ def _get_operation_bytes(w: bytearray, msg): _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) + + # support delegation and transfer from the old scriptless contracts (now with manager.tz script) + if msg.transaction.parameters_manager is not None: + parameters_manager = msg.transaction.parameters_manager + + if parameters_manager.set_delegate is not None: + _encode_manager_delegation(w, parameters_manager.set_delegate) + elif parameters_manager.cancel_delegate is not None: + _encode_manager_delegation_remove(w) + elif parameters_manager.transfer is not None: + if ( + parameters_manager.transfer.destination.tag + == TezosContractType.Implicit + ): + _encode_manager_to_implicit_transfer(w, parameters_manager.transfer) + else: + _encode_manager_to_manager_transfer(w, parameters_manager.transfer) + else: + _encode_data_with_bool_prefix(w, msg.transaction.parameters) # origination operation elif msg.origination is not None: _encode_common(w, msg.origination, "origination") - write_bytes(w, msg.origination.manager_pubkey) _encode_zarith(w, msg.origination.balance) - helpers.write_bool(w, msg.origination.spendable) - helpers.write_bool(w, msg.origination.delegatable) _encode_data_with_bool_prefix(w, msg.origination.delegate) - _encode_data_with_bool_prefix(w, msg.origination.script) + write_bytes(w, msg.origination.script) + # delegation operation elif msg.delegation is not None: _encode_common(w, msg.delegation, "delegation") @@ -162,9 +207,14 @@ def _get_operation_bytes(w: bytearray, msg): def _encode_common(w: bytearray, operation, str_operation): - operation_tags = {"reveal": 7, "transaction": 8, "origination": 9, "delegation": 10} + operation_tags = { + "reveal": 107, + "transaction": 108, + "origination": 109, + "delegation": 110, + } write_uint8(w, operation_tags[str_operation]) - _encode_contract_id(w, operation.source) + write_bytes(w, operation.source) _encode_zarith(w, operation.fee) _encode_zarith(w, operation.counter) _encode_zarith(w, operation.gas_limit) @@ -215,3 +265,103 @@ def _encode_ballot(w: bytearray, ballot): write_uint32_be(w, ballot.period) write_bytes(w, ballot.proposal) write_uint8(w, ballot.ballot) + + +def _encode_natural(w: bytearray, num): + # 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 + natural_tag = 0 + write_uint8(w, natural_tag) + + byte = num & 63 + modified = num >> 6 + + if modified == 0: + write_uint8(w, byte) + else: + write_uint8(w, 128 | byte) + _encode_zarith(w, modified) + + +def _encode_manager_common(w: bytearray, sequence_length, operation, to_contract=False): + IMPLICIT_ADDRESS_LENGTH = 21 + SMART_CONTRACT_ADDRESS_LENGTH = 22 + + # 5 = tag and sequence_length (1 byte + 4 bytes) + argument_length = sequence_length + 5 + + helpers.write_bool(w, True) + write_uint8(w, helpers.DO_ENTRYPOINT_TAG) + write_uint32_be(w, argument_length) + write_uint8(w, helpers.MICHELSON_SEQUENCE_TAG) + write_uint32_be(w, sequence_length) + write_bytes(w, bytes(helpers.MICHELSON_INSTRUCTION_BYTES["DROP"])) + write_bytes(w, bytes(helpers.MICHELSON_INSTRUCTION_BYTES["NIL"])) + write_bytes(w, bytes(helpers.MICHELSON_INSTRUCTION_BYTES["operation"])) + write_bytes(w, bytes(helpers.MICHELSON_INSTRUCTION_BYTES[operation])) + if to_contract is True: + write_bytes(w, bytes(helpers.MICHELSON_INSTRUCTION_BYTES["address"])) + else: + write_bytes(w, bytes(helpers.MICHELSON_INSTRUCTION_BYTES["key_hash"])) + if operation == "PUSH": + write_bytes(w, bytes([10])) # byte sequence + if to_contract is True: + write_uint32_be(w, SMART_CONTRACT_ADDRESS_LENGTH) + else: + write_uint32_be(w, IMPLICIT_ADDRESS_LENGTH) + + +def _encode_manager_to_implicit_transfer(w: bytearray, manager_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(w, manager_transfer.destination.hash) + write_bytes(w, bytes(helpers.MICHELSON_INSTRUCTION_BYTES["IMPLICIT_ACCOUNT"])) + write_bytes(w, bytes(helpers.MICHELSON_INSTRUCTION_BYTES["PUSH"])) + write_bytes(w, bytes(helpers.MICHELSON_INSTRUCTION_BYTES["mutez"])) + _encode_natural(w, manager_transfer.amount) + write_bytes(w, bytes(helpers.MICHELSON_INSTRUCTION_BYTES["UNIT"])) + write_bytes(w, bytes(helpers.MICHELSON_INSTRUCTION_BYTES["TRANSFER_TOKENS"])) + write_bytes(w, bytes(helpers.MICHELSON_INSTRUCTION_BYTES["CONS"])) + + +# smart_contract_delegation +def _encode_manager_delegation(w: bytearray, delegate): + MICHELSON_LENGTH = 42 # length is fixed this time(no variable length fields) + + _encode_manager_common(w, MICHELSON_LENGTH, "PUSH") + write_bytes(w, delegate) + write_bytes(w, bytes(helpers.MICHELSON_INSTRUCTION_BYTES["SOME"])) + write_bytes(w, bytes(helpers.MICHELSON_INSTRUCTION_BYTES["SET_DELEGATE"])) + write_bytes(w, bytes(helpers.MICHELSON_INSTRUCTION_BYTES["CONS"])) + + +def _encode_manager_delegation_remove(w: bytearray): + MICHELSON_LENGTH = 14 # length is fixed this time(no variable length fields) + _encode_manager_common(w, MICHELSON_LENGTH, "NONE") + write_bytes(w, bytes(helpers.MICHELSON_INSTRUCTION_BYTES["SET_DELEGATE"])) + write_bytes(w, bytes(helpers.MICHELSON_INSTRUCTION_BYTES["CONS"])) + + +def _encode_manager_to_manager_transfer(w: bytearray, manager_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(w, manager_transfer.destination) + write_bytes(w, bytes(helpers.MICHELSON_INSTRUCTION_BYTES["CONTRACT"])) + write_bytes(w, bytes(helpers.MICHELSON_INSTRUCTION_BYTES["unit"])) + write_bytes(w, bytes(helpers.MICHELSON_INSTRUCTION_BYTES["ASSERT_SOME"])) + write_bytes(w, bytes(helpers.MICHELSON_INSTRUCTION_BYTES["PUSH"])) + write_bytes(w, bytes(helpers.MICHELSON_INSTRUCTION_BYTES["mutez"])) + _encode_natural(w, manager_transfer.amount) + write_bytes(w, bytes(helpers.MICHELSON_INSTRUCTION_BYTES["UNIT"])) + write_bytes(w, bytes(helpers.MICHELSON_INSTRUCTION_BYTES["TRANSFER_TOKENS"])) + write_bytes(w, bytes(helpers.MICHELSON_INSTRUCTION_BYTES["CONS"])) diff --git a/core/src/trezor/messages/TezosDelegationOp.py b/core/src/trezor/messages/TezosDelegationOp.py index dea07f62b5..a15f6ecfd7 100644 --- a/core/src/trezor/messages/TezosDelegationOp.py +++ b/core/src/trezor/messages/TezosDelegationOp.py @@ -2,8 +2,6 @@ # fmt: off import protobuf as p -from .TezosContractID import TezosContractID - if __debug__: try: from typing import Dict, List # noqa: F401 @@ -16,7 +14,7 @@ class TezosDelegationOp(p.MessageType): def __init__( self, - source: TezosContractID = None, + source: bytes = None, fee: int = None, counter: int = None, gas_limit: int = None, @@ -33,7 +31,7 @@ class TezosDelegationOp(p.MessageType): @classmethod def get_fields(cls) -> Dict: return { - 1: ('source', TezosContractID, 0), + 7: ('source', p.BytesType, 0), 2: ('fee', p.UVarintType, 0), 3: ('counter', p.UVarintType, 0), 4: ('gas_limit', p.UVarintType, 0), diff --git a/core/src/trezor/messages/TezosManagerTransfer.py b/core/src/trezor/messages/TezosManagerTransfer.py new file mode 100644 index 0000000000..40b2fabb9b --- /dev/null +++ b/core/src/trezor/messages/TezosManagerTransfer.py @@ -0,0 +1,30 @@ +# Automatically generated by pb2py +# fmt: off +import protobuf as p + +from .TezosContractID import TezosContractID + +if __debug__: + try: + from typing import Dict, List # noqa: F401 + from typing_extensions import Literal # noqa: F401 + except ImportError: + pass + + +class TezosManagerTransfer(p.MessageType): + + def __init__( + self, + destination: TezosContractID = None, + amount: int = None, + ) -> None: + self.destination = destination + self.amount = amount + + @classmethod + def get_fields(cls) -> Dict: + return { + 1: ('destination', TezosContractID, 0), + 2: ('amount', p.UVarintType, 0), + } diff --git a/core/src/trezor/messages/TezosOriginationOp.py b/core/src/trezor/messages/TezosOriginationOp.py index 3d9561c458..7f0f7c4f7f 100644 --- a/core/src/trezor/messages/TezosOriginationOp.py +++ b/core/src/trezor/messages/TezosOriginationOp.py @@ -2,8 +2,6 @@ # fmt: off import protobuf as p -from .TezosContractID import TezosContractID - if __debug__: try: from typing import Dict, List # noqa: F401 @@ -16,7 +14,7 @@ class TezosOriginationOp(p.MessageType): def __init__( self, - source: TezosContractID = None, + source: bytes = None, fee: int = None, counter: int = None, gas_limit: int = None, @@ -43,7 +41,7 @@ class TezosOriginationOp(p.MessageType): @classmethod def get_fields(cls) -> Dict: return { - 1: ('source', TezosContractID, 0), + 12: ('source', p.BytesType, 0), 2: ('fee', p.UVarintType, 0), 3: ('counter', p.UVarintType, 0), 4: ('gas_limit', p.UVarintType, 0), diff --git a/core/src/trezor/messages/TezosParametersManager.py b/core/src/trezor/messages/TezosParametersManager.py new file mode 100644 index 0000000000..c50b52a7c6 --- /dev/null +++ b/core/src/trezor/messages/TezosParametersManager.py @@ -0,0 +1,33 @@ +# Automatically generated by pb2py +# fmt: off +import protobuf as p + +from .TezosManagerTransfer import TezosManagerTransfer + +if __debug__: + try: + from typing import Dict, List # noqa: F401 + from typing_extensions import Literal # noqa: F401 + except ImportError: + pass + + +class TezosParametersManager(p.MessageType): + + def __init__( + self, + set_delegate: bytes = None, + cancel_delegate: bool = None, + transfer: TezosManagerTransfer = None, + ) -> None: + self.set_delegate = set_delegate + self.cancel_delegate = cancel_delegate + self.transfer = transfer + + @classmethod + def get_fields(cls) -> Dict: + return { + 1: ('set_delegate', p.BytesType, 0), + 2: ('cancel_delegate', p.BoolType, 0), + 3: ('transfer', TezosManagerTransfer, 0), + } diff --git a/core/src/trezor/messages/TezosRevealOp.py b/core/src/trezor/messages/TezosRevealOp.py index dda5f8b86a..2abf3f52e2 100644 --- a/core/src/trezor/messages/TezosRevealOp.py +++ b/core/src/trezor/messages/TezosRevealOp.py @@ -2,8 +2,6 @@ # fmt: off import protobuf as p -from .TezosContractID import TezosContractID - if __debug__: try: from typing import Dict, List # noqa: F401 @@ -16,7 +14,7 @@ class TezosRevealOp(p.MessageType): def __init__( self, - source: TezosContractID = None, + source: bytes = None, fee: int = None, counter: int = None, gas_limit: int = None, @@ -33,7 +31,7 @@ class TezosRevealOp(p.MessageType): @classmethod def get_fields(cls) -> Dict: return { - 1: ('source', TezosContractID, 0), + 7: ('source', p.BytesType, 0), 2: ('fee', p.UVarintType, 0), 3: ('counter', p.UVarintType, 0), 4: ('gas_limit', p.UVarintType, 0), diff --git a/core/src/trezor/messages/TezosTransactionOp.py b/core/src/trezor/messages/TezosTransactionOp.py index 308e7961f8..6e4d8b361c 100644 --- a/core/src/trezor/messages/TezosTransactionOp.py +++ b/core/src/trezor/messages/TezosTransactionOp.py @@ -3,6 +3,7 @@ import protobuf as p from .TezosContractID import TezosContractID +from .TezosParametersManager import TezosParametersManager if __debug__: try: @@ -16,7 +17,7 @@ class TezosTransactionOp(p.MessageType): def __init__( self, - source: TezosContractID = None, + source: bytes = None, fee: int = None, counter: int = None, gas_limit: int = None, @@ -24,6 +25,7 @@ class TezosTransactionOp(p.MessageType): amount: int = None, destination: TezosContractID = None, parameters: bytes = None, + parameters_manager: TezosParametersManager = None, ) -> None: self.source = source self.fee = fee @@ -33,11 +35,12 @@ class TezosTransactionOp(p.MessageType): self.amount = amount self.destination = destination self.parameters = parameters + self.parameters_manager = parameters_manager @classmethod def get_fields(cls) -> Dict: return { - 1: ('source', TezosContractID, 0), + 9: ('source', p.BytesType, 0), 2: ('fee', p.UVarintType, 0), 3: ('counter', p.UVarintType, 0), 4: ('gas_limit', p.UVarintType, 0), @@ -45,4 +48,5 @@ class TezosTransactionOp(p.MessageType): 6: ('amount', p.UVarintType, 0), 7: ('destination', TezosContractID, 0), 8: ('parameters', p.BytesType, 0), + 10: ('parameters_manager', TezosParametersManager, 0), } diff --git a/core/tests/test_apps.tezos.encode.py b/core/tests/test_apps.tezos.encode.py index 7a67395a51..48dc2cf7c6 100644 --- a/core/tests/test_apps.tezos.encode.py +++ b/core/tests/test_apps.tezos.encode.py @@ -8,6 +8,7 @@ if not utils.BITCOIN_ONLY: _encode_contract_id, _encode_data_with_bool_prefix, _encode_zarith, + _encode_natural, ) @@ -94,6 +95,15 @@ class TestTezosEncoding(unittest.TestCase): address = "2U14dJ6ED97bBHDZTQWA6umVL8SAVefXj" self.assertEqual(base58_decode_check(address), pkh) + def test_tezos_encode_natural(self): + inputs = [200000000000, 2000000, 159066, 200, 60000, 157000000, 0] + outputs = ["0080c0ee8ed20b", "008092f401", "009ab513", "008803", "00a0a907", "008085dd9501", "0000"] + + for i, o in zip(inputs, outputs): + w = bytearray() + _encode_natural(w, i) + self.assertEqual(bytes(w), unhexlify(o)) + if __name__ == "__main__": unittest.main() diff --git a/python/src/trezorlib/messages/TezosDelegationOp.py b/python/src/trezorlib/messages/TezosDelegationOp.py index 08d47e594b..69013af0d5 100644 --- a/python/src/trezorlib/messages/TezosDelegationOp.py +++ b/python/src/trezorlib/messages/TezosDelegationOp.py @@ -2,8 +2,6 @@ # fmt: off from .. import protobuf as p -from .TezosContractID import TezosContractID - if __debug__: try: from typing import Dict, List # noqa: F401 @@ -16,7 +14,7 @@ class TezosDelegationOp(p.MessageType): def __init__( self, - source: TezosContractID = None, + source: bytes = None, fee: int = None, counter: int = None, gas_limit: int = None, @@ -33,7 +31,7 @@ class TezosDelegationOp(p.MessageType): @classmethod def get_fields(cls) -> Dict: return { - 1: ('source', TezosContractID, 0), + 7: ('source', p.BytesType, 0), 2: ('fee', p.UVarintType, 0), 3: ('counter', p.UVarintType, 0), 4: ('gas_limit', p.UVarintType, 0), diff --git a/python/src/trezorlib/messages/TezosManagerTransfer.py b/python/src/trezorlib/messages/TezosManagerTransfer.py new file mode 100644 index 0000000000..96af07ea10 --- /dev/null +++ b/python/src/trezorlib/messages/TezosManagerTransfer.py @@ -0,0 +1,30 @@ +# Automatically generated by pb2py +# fmt: off +from .. import protobuf as p + +from .TezosContractID import TezosContractID + +if __debug__: + try: + from typing import Dict, List # noqa: F401 + from typing_extensions import Literal # noqa: F401 + except ImportError: + pass + + +class TezosManagerTransfer(p.MessageType): + + def __init__( + self, + destination: TezosContractID = None, + amount: int = None, + ) -> None: + self.destination = destination + self.amount = amount + + @classmethod + def get_fields(cls) -> Dict: + return { + 1: ('destination', TezosContractID, 0), + 2: ('amount', p.UVarintType, 0), + } diff --git a/python/src/trezorlib/messages/TezosOriginationOp.py b/python/src/trezorlib/messages/TezosOriginationOp.py index 63b607c8ab..f31bafd10c 100644 --- a/python/src/trezorlib/messages/TezosOriginationOp.py +++ b/python/src/trezorlib/messages/TezosOriginationOp.py @@ -2,8 +2,6 @@ # fmt: off from .. import protobuf as p -from .TezosContractID import TezosContractID - if __debug__: try: from typing import Dict, List # noqa: F401 @@ -16,7 +14,7 @@ class TezosOriginationOp(p.MessageType): def __init__( self, - source: TezosContractID = None, + source: bytes = None, fee: int = None, counter: int = None, gas_limit: int = None, @@ -43,7 +41,7 @@ class TezosOriginationOp(p.MessageType): @classmethod def get_fields(cls) -> Dict: return { - 1: ('source', TezosContractID, 0), + 12: ('source', p.BytesType, 0), 2: ('fee', p.UVarintType, 0), 3: ('counter', p.UVarintType, 0), 4: ('gas_limit', p.UVarintType, 0), diff --git a/python/src/trezorlib/messages/TezosParametersManager.py b/python/src/trezorlib/messages/TezosParametersManager.py new file mode 100644 index 0000000000..9eb13474ad --- /dev/null +++ b/python/src/trezorlib/messages/TezosParametersManager.py @@ -0,0 +1,33 @@ +# Automatically generated by pb2py +# fmt: off +from .. import protobuf as p + +from .TezosManagerTransfer import TezosManagerTransfer + +if __debug__: + try: + from typing import Dict, List # noqa: F401 + from typing_extensions import Literal # noqa: F401 + except ImportError: + pass + + +class TezosParametersManager(p.MessageType): + + def __init__( + self, + set_delegate: bytes = None, + cancel_delegate: bool = None, + transfer: TezosManagerTransfer = None, + ) -> None: + self.set_delegate = set_delegate + self.cancel_delegate = cancel_delegate + self.transfer = transfer + + @classmethod + def get_fields(cls) -> Dict: + return { + 1: ('set_delegate', p.BytesType, 0), + 2: ('cancel_delegate', p.BoolType, 0), + 3: ('transfer', TezosManagerTransfer, 0), + } diff --git a/python/src/trezorlib/messages/TezosRevealOp.py b/python/src/trezorlib/messages/TezosRevealOp.py index ae7728ea88..08a700afa9 100644 --- a/python/src/trezorlib/messages/TezosRevealOp.py +++ b/python/src/trezorlib/messages/TezosRevealOp.py @@ -2,8 +2,6 @@ # fmt: off from .. import protobuf as p -from .TezosContractID import TezosContractID - if __debug__: try: from typing import Dict, List # noqa: F401 @@ -16,7 +14,7 @@ class TezosRevealOp(p.MessageType): def __init__( self, - source: TezosContractID = None, + source: bytes = None, fee: int = None, counter: int = None, gas_limit: int = None, @@ -33,7 +31,7 @@ class TezosRevealOp(p.MessageType): @classmethod def get_fields(cls) -> Dict: return { - 1: ('source', TezosContractID, 0), + 7: ('source', p.BytesType, 0), 2: ('fee', p.UVarintType, 0), 3: ('counter', p.UVarintType, 0), 4: ('gas_limit', p.UVarintType, 0), diff --git a/python/src/trezorlib/messages/TezosTransactionOp.py b/python/src/trezorlib/messages/TezosTransactionOp.py index 775f961b73..97690bd91f 100644 --- a/python/src/trezorlib/messages/TezosTransactionOp.py +++ b/python/src/trezorlib/messages/TezosTransactionOp.py @@ -3,6 +3,7 @@ from .. import protobuf as p from .TezosContractID import TezosContractID +from .TezosParametersManager import TezosParametersManager if __debug__: try: @@ -16,7 +17,7 @@ class TezosTransactionOp(p.MessageType): def __init__( self, - source: TezosContractID = None, + source: bytes = None, fee: int = None, counter: int = None, gas_limit: int = None, @@ -24,6 +25,7 @@ class TezosTransactionOp(p.MessageType): amount: int = None, destination: TezosContractID = None, parameters: bytes = None, + parameters_manager: TezosParametersManager = None, ) -> None: self.source = source self.fee = fee @@ -33,11 +35,12 @@ class TezosTransactionOp(p.MessageType): self.amount = amount self.destination = destination self.parameters = parameters + self.parameters_manager = parameters_manager @classmethod def get_fields(cls) -> Dict: return { - 1: ('source', TezosContractID, 0), + 9: ('source', p.BytesType, 0), 2: ('fee', p.UVarintType, 0), 3: ('counter', p.UVarintType, 0), 4: ('gas_limit', p.UVarintType, 0), @@ -45,4 +48,5 @@ class TezosTransactionOp(p.MessageType): 6: ('amount', p.UVarintType, 0), 7: ('destination', TezosContractID, 0), 8: ('parameters', p.BytesType, 0), + 10: ('parameters_manager', TezosParametersManager, 0), } diff --git a/python/src/trezorlib/messages/__init__.py b/python/src/trezorlib/messages/__init__.py index 8aa242e525..b8e9cec649 100644 --- a/python/src/trezorlib/messages/__init__.py +++ b/python/src/trezorlib/messages/__init__.py @@ -233,7 +233,9 @@ from .TezosContractID import TezosContractID from .TezosDelegationOp import TezosDelegationOp from .TezosGetAddress import TezosGetAddress from .TezosGetPublicKey import TezosGetPublicKey +from .TezosManagerTransfer import TezosManagerTransfer from .TezosOriginationOp import TezosOriginationOp +from .TezosParametersManager import TezosParametersManager from .TezosProposalOp import TezosProposalOp from .TezosPublicKey import TezosPublicKey from .TezosRevealOp import TezosRevealOp diff --git a/tests/device_tests/test_msg_tezos_sign_tx.py b/tests/device_tests/test_msg_tezos_sign_tx.py index 610986434a..da847510da 100644 --- a/tests/device_tests/test_msg_tezos_sign_tx.py +++ b/tests/device_tests/test_msg_tezos_sign_tx.py @@ -22,171 +22,13 @@ from trezorlib.tools import parse_path TEZOS_PATH = parse_path("m/44'/1729'/0'") TEZOS_PATH_10 = parse_path("m/44'/1729'/10'") +TEZOS_PATH_15 = parse_path("m/44'/1729'/15'") @pytest.mark.altcoin @pytest.mark.tezos @pytest.mark.skip_t1 class TestMsgTezosSignTx: - def test_tezos_sign_tx_transaction(self, client): - resp = tezos.sign_tx( - client, - TEZOS_PATH, - dict_to_proto( - messages.TezosSignTx, - { - "branch": "f2ae0c72fdd41d7a89bebfe8d6dd6d38e0fcd0782adb8194717176eb70366f64", - "transaction": { - "source": { - "tag": 0, - "hash": "00001e65c88ae6317cd62a638c8abd1e71c83c8475", - }, - "fee": 0, - "counter": 108925, - "gas_limit": 200, - "storage_limit": 0, - "amount": 10000, - "destination": { - "tag": 0, - "hash": "0004115bce5af2f977acbb900f449c14c53e1d89cf", - }, - }, - }, - ), - ) - assert ( - resp.signature - == "edsigtfmAbUJtZMAJRGMppvDzPtiWBBQiZKf7G15dV9tgkHQefwiV4JeSw5Rj57ZK54FHEthpyzCpfGvAjU8YqhHxMwZP9Z2Jmt" - ) - assert ( - resp.sig_op_contents.hex() - == "f2ae0c72fdd41d7a89bebfe8d6dd6d38e0fcd0782adb8194717176eb70366f64080000001e65c88ae6317cd62a638c8abd1e71c83c847500fdd206c80100904e000004115bce5af2f977acbb900f449c14c53e1d89cf003cce7e6dfe3f79a8bd39f77d738fd79140da1a9e762b7d156eca2cf945aae978436cf68c1ec11889e4f2cf074c9642e05b3d65cc2896809af1fbdab0b126f90c" - ) - assert ( - resp.operation_hash == "opNeGBdgbM5jN2ykz4o8NdsCuJfqNZ6WBEFVbBUmYH8gp45CJvH" - ) - - def test_tezos_sign_reveal_transaction(self, client): - resp = tezos.sign_tx( - client, - TEZOS_PATH, - dict_to_proto( - messages.TezosSignTx, - { - "branch": "03cbce9a5ea1fae2566f7f244a01edc5869f5ada9d0bf21c1098017c59be98e0", - "reveal": { - "source": { - "tag": 0, - "hash": "00001e65c88ae6317cd62a638c8abd1e71c83c8475", - }, - "fee": 0, - "counter": 108923, - "gas_limit": 200, - "storage_limit": 0, - "public_key": "00200da2c0200927dd8168b2b62e1322637521fcefb3184e61c1c3123c7c00bb95", - }, - "transaction": { - "source": { - "tag": 0, - "hash": "00001e65c88ae6317cd62a638c8abd1e71c83c8475", - }, - "fee": 0, - "counter": 108924, - "gas_limit": 200, - "storage_limit": 0, - "amount": 10000, - "destination": { - "tag": 0, - "hash": "0004115bce5af2f977acbb900f449c14c53e1d89cf", - }, - }, - }, - ), - ) - assert ( - resp.signature - == "edsigtheQQ78dZM9Sir78T3TNdfnyHrbFw8w3hiGMaLD5mPbGrUiD1jvy5fpsNJW9T5o7qrWBe7y7bai6vZ5KhwJ5HKZ8UnoCbh" - ) - assert ( - resp.sig_op_contents.hex() - == "03cbce9a5ea1fae2566f7f244a01edc5869f5ada9d0bf21c1098017c59be98e0070000001e65c88ae6317cd62a638c8abd1e71c83c847500fbd206c8010000200da2c0200927dd8168b2b62e1322637521fcefb3184e61c1c3123c7c00bb95080000001e65c88ae6317cd62a638c8abd1e71c83c847500fcd206c80100904e000004115bce5af2f977acbb900f449c14c53e1d89cf004b33e241c90b828c31cf44a28c123aee3f161049c3cb4c42ec71dd96fbbf8dae9963bdadb33f51d7c6f11ff0e74f0baad742352d980a1899f69c3c65c70fe40f" - ) - assert ( - resp.operation_hash == "opQHu93L8juNm2VjmsMKioFowWNyMvGzopcuoVcuzFV1bJMhJef" - ) - - def test_tezos_sign_tx_origination(self, client): - resp = tezos.sign_tx( - client, - TEZOS_PATH, - dict_to_proto( - messages.TezosSignTx, - { - "branch": "5e556181029c4ce5e54c9ffcbba2fc0966ed4d880ddeb0849bf6387438a7a877", - "origination": { - "source": { - "tag": 0, - "hash": "00001e65c88ae6317cd62a638c8abd1e71c83c8475", - }, - "fee": 0, - "counter": 108929, - "gas_limit": 10000, - "storage_limit": 100, - "manager_pubkey": "00001e65c88ae6317cd62a638c8abd1e71c83c8475", - "balance": 2000000, - "spendable": True, - "delegatable": True, - "delegate": "0049a35041e4be130977d51419208ca1d487cfb2e7", - }, - }, - ), - ) - assert ( - resp.signature - == "edsigu46YtcVthQQQ2FTcuayNwTcYY1Mpo6BmwCu83qGovi4kHM9CL5h4NaV4NQw8RTEP1VgraR6Kiv5J6RQsDLMzG17V6fcYwp" - ) - assert ( - resp.sig_op_contents.hex() - == "5e556181029c4ce5e54c9ffcbba2fc0966ed4d880ddeb0849bf6387438a7a877090000001e65c88ae6317cd62a638c8abd1e71c83c84750081d306904e6400001e65c88ae6317cd62a638c8abd1e71c83c847580897affffff0049a35041e4be130977d51419208ca1d487cfb2e700e785342fd2258277741f93c17c5022ea1be059f47f3e343600e83c50ca191e8318da9e5ec237be9657d0fc6aba654f476c945430239a3c6dfeca21e06be98706" - ) - assert ( - resp.operation_hash == "onuKkBtP4K2JMGg7YMv7qs869B8aHCEUQecvuiL71aKkY8iPCb6" - ) - - def test_tezos_sign_tx_delegation(self, client): - resp = tezos.sign_tx( - client, - TEZOS_PATH, - dict_to_proto( - messages.TezosSignTx, - { - "branch": "9b8b8bc45d611a3ada20ad0f4b6f0bfd72ab395cc52213a57b14d1fb75b37fd0", - "delegation": { - "source": { - "tag": 0, - "hash": "00001e65c88ae6317cd62a638c8abd1e71c83c8475", - }, - "fee": 0, - "counter": 108927, - "gas_limit": 200, - "storage_limit": 0, - "delegate": "0049a35041e4be130977d51419208ca1d487cfb2e7", - }, - }, - ), - ) - assert ( - resp.signature - == "edsigu3qGseaB2MghcGQWNWUhPtWgM9rC62FTEVrYWGtzFTHShDxGGmLFfEpJyToRCeRqcgGm3pyXY3NdyATkjmFTtUvJKvb3rX" - ) - assert ( - resp.sig_op_contents.hex() - == "9b8b8bc45d611a3ada20ad0f4b6f0bfd72ab395cc52213a57b14d1fb75b37fd00a0000001e65c88ae6317cd62a638c8abd1e71c83c847500ffd206c80100ff0049a35041e4be130977d51419208ca1d487cfb2e7e581d41daf8cab833d5b99151a0303fd04472eb990f7338d7be57afe21c26e779ff4341511694aebd901a0d74d183bbcb726a9be4b873d3b47298f99f2b7e80c" - ) - assert ( - resp.operation_hash == "oocgc3hyKsGHPsw6WFWJpWT8jBwQLtebQAXF27KNisThkzoj635" - ) - def input_flow(self, debug, num_pages): yield for _ in range(num_pages - 1): @@ -327,3 +169,306 @@ class TestMsgTezosSignTx: resp.signature == "edsigu6YX7EegPwrpcEbdNQsNhrRiEagBNGJBmFamP4mixZZw1UynhahGQ8RNiZLSUVLERUZwygrsSVenBqXGt9VnknTxtzjKzv" ) + + def test_tezos_sign_tx_tranasaction(self, client): + resp = tezos.sign_tx( + client, + TEZOS_PATH_10, + dict_to_proto( + messages.TezosSignTx, + { + "branch": "3b85532b5a468cd26b6d3c7e762ae53b795d19c6db4838ed2750df8e063aedb8", + "transaction": { + "source": "005f450441f41ee11eee78a31d1e1e55627c783bd6", + "fee": 10000, + "counter": 274, + "gas_limit": 20000, + "storage_limit": 0, + "amount": 100000, + "destination": { + "tag": 0, + "hash": "003325df8851047421605ae7d6b09b49f70c8ce460", + }, + }, + }, + ), + ) + assert ( + resp.signature + == "edsigtvRTDegGy83x5AHQwhzPAbKteJ7MsLukhLRS9RLMRX5UdmtV1xiHEhQCUrGNv6h9CbV1cvuUVzRgLd6Af4XfVQgGkkYUuY" + ) + assert ( + resp.sig_op_contents.hex() + == "3b85532b5a468cd26b6d3c7e762ae53b795d19c6db4838ed2750df8e063aedb86c005f450441f41ee11eee78a31d1e1e55627c783bd6904e9202a09c0100a08d0600003325df8851047421605ae7d6b09b49f70c8ce46000acdcd3df9daaa79c7345c068ffddc2113047fc00c1eed3503838d15fc6690821ee6eaa1e67b4a8d40dcf30a9ec456bbbda18ef2bcc021053d7d8c3f1473df809" + ) + assert ( + resp.operation_hash == "oon8PNUsPETGKzfESv1Epv4535rviGS7RdCfAEKcPvzojrcuufb" + ) + + def test_tezos_sign_tx_delegation(self, client): + resp = tezos.sign_tx( + client, + TEZOS_PATH_15, + dict_to_proto( + messages.TezosSignTx, + { + "branch": "447d51450749763989c1aa5e1939aae623abb5a050f9cf1c04c247d91ca67593", + "delegation": { + "source": "0002eca091abc1e0f5c38a155c1313c410b47e1549", + "fee": 20000, + "counter": 458069, + "gas_limit": 20000, + "storage_limit": 0, + "delegate": "005f450441f41ee11eee78a31d1e1e55627c783bd6", + }, + }, + ), + ) + assert ( + resp.signature + == "edsigu2ZsDXXm7RzMF2oSKHK54ZfSUPvU2jekJBQmAprMe8ksnofMScKd3Kc3RTTExwzaJGENzoe94ZDiW86eWWnWBTPNw2xu5m" + ) + assert ( + resp.sig_op_contents.hex() + == "447d51450749763989c1aa5e1939aae623abb5a050f9cf1c04c247d91ca675936e0002eca091abc1e0f5c38a155c1313c410b47e1549a09c01d5fa1ba09c0100ff005f450441f41ee11eee78a31d1e1e55627c783bd6dbd53f9129387e82548e5d20b1479a46a876ac7516001fae01488dfbe9dcfc732cb8664d52fd7e1bc25a9845714131fd498ef65ea91f84e180688a41e06fe700" + ) + assert ( + resp.operation_hash == "op79C1tR7wkUgYNid2zC1WNXmGorS38mTXZwtAjmCQm2kG7XG59" + ) + + def test_tezos_sign_tx_origination(self, client): + resp = tezos.sign_tx( + client, + TEZOS_PATH_10, + dict_to_proto( + messages.TezosSignTx, + { + "branch": "927ac7cd7969bde606e7537712584eb0d34fc52d9f5a88cc908994d817170a16", + "origination": { + "source": "005f450441f41ee11eee78a31d1e1e55627c783bd6", + "fee": 20000, + "counter": 276, + "gas_limit": 20000, + "storage_limit": 10000, + "balance": 100000, + "script": "0000001c02000000170500036805010368050202000000080316053d036d03420000000a010000000568656c6c6f", + }, + }, + ), + ) + assert ( + resp.signature + == "edsigtcAamBz7cL8whbLvaeMNYUdsQieh6RADrzWLCPhDjzqn7JtdX9Yy4vYWKcpMnycY6YTMWCAYMegPaKMNJVM4zbxypALAyN" + ) + assert ( + resp.sig_op_contents.hex() + == "927ac7cd7969bde606e7537712584eb0d34fc52d9f5a88cc908994d817170a166d005f450441f41ee11eee78a31d1e1e55627c783bd6a09c019402a09c01904ea08d06000000001c02000000170500036805010368050202000000080316053d036d03420000000a010000000568656c6c6f2151774735e1659a7d0f54659e98fbcbd86a667717a9a2a9961292a170e5e8d1608a1dbf805a03981be2f7389ba1738841ac8b1069fe5978a72d441a97de3505" + ) + assert ( + resp.operation_hash == "onmq9FFZzvG2zghNdr1bgv9jzdbzNycXjSSNmCVhXCGSnV3WA9g" + ) + + def test_tezos_sign_tx_reveal(self, client): + resp = tezos.sign_tx( + client, + TEZOS_PATH, + dict_to_proto( + messages.TezosSignTx, + { + "branch": "f26502c204619c4bdab2e59efc50c79bc0136d781304b8f7fad389263550300e", + "reveal": { + "source": "00001e65c88ae6317cd62a638c8abd1e71c83c8475", + "fee": 20000, + "counter": 564560, + "gas_limit": 20000, + "storage_limit": 0, + "public_key": "00200da2c0200927dd8168b2b62e1322637521fcefb3184e61c1c3123c7c00bb95", + }, + "transaction": { + "source": "00001e65c88ae6317cd62a638c8abd1e71c83c8475", + "fee": 50000, + "counter": 564561, + "gas_limit": 20000, + "storage_limit": 0, + "amount": 100000, + "destination": { + "tag": 0, + "hash": "005f450441f41ee11eee78a31d1e1e55627c783bd6", + }, + }, + }, + ), + ) + assert ( + resp.signature + == "edsigtcqDr47paEVgr8X8gmvFt9UnNWACkMVCGdVFZ2yUq849oxmTbx2FqjToveUNwNujC9qmoi5kXWy78qZY2d5Qeryx6kCbGs" + ) + assert ( + resp.sig_op_contents.hex() + == "f26502c204619c4bdab2e59efc50c79bc0136d781304b8f7fad389263550300e6b00001e65c88ae6317cd62a638c8abd1e71c83c8475a09c01d0ba22a09c010000200da2c0200927dd8168b2b62e1322637521fcefb3184e61c1c3123c7c00bb956c00001e65c88ae6317cd62a638c8abd1e71c83c8475d08603d1ba22a09c0100a08d0600005f450441f41ee11eee78a31d1e1e55627c783bd60026690d65407d6cda03cde8e3c17a22ffd0351f78c18c500f3997cbe311e12e6cc4b5ff40b339c7fba8b4c7d62329ea45da662340113a6da98b7510b40042f204" + ) + assert ( + resp.operation_hash == "oo9JFiWTnTSvUZfajMNwQe1VyFN2pqwiJzZPkpSAGfGD57Z6mZJ" + ) + + def test_tezos_smart_contract_delegation(self, client): + resp = tezos.sign_tx( + client, + TEZOS_PATH_10, + dict_to_proto( + messages.TezosSignTx, + { + "branch": "49eead995833934ee2571c6cd6439897ee71b72a9e4d22f127e0c3d4ca69ba15", + "transaction": { + "source": "005f450441f41ee11eee78a31d1e1e55627c783bd6", + "fee": 10000, + "counter": 278, + "gas_limit": 25822, + "storage_limit": 0, + "amount": 0, + "destination": { + "tag": 1, + "hash": "c116a6c74bf00a5839b593838215fe1fcf2db59c00", + }, + "parameters_manager": { + "set_delegate": "005f450441f41ee11eee78a31d1e1e55627c783bd6" + }, + }, + }, + ), + ) + assert ( + resp.signature + == "edsigtw8uSW99pT4GUd1mS14DbczxVfTCJrKBy6bMckBknwAxwAF53yBXnQAZwZ9WWMKyGmbta8RgPs262b7hGGNxFyTM8zdPBd" + ) + assert ( + resp.sig_op_contents.hex() + == "49eead995833934ee2571c6cd6439897ee71b72a9e4d22f127e0c3d4ca69ba156c005f450441f41ee11eee78a31d1e1e55627c783bd6904e9602dec901000001c116a6c74bf00a5839b593838215fe1fcf2db59c00ff020000002f020000002a0320053d036d0743035d0a00000015005f450441f41ee11eee78a31d1e1e55627c783bd60346034e031bb2534eb5478c31d5ffbc13b4692a7f2b73aad16e2d8e0f7068110955aa9480a6432775ba301f24bc20e4c12cffc9fd1f27b44204f830ea7f4dec23a18e25450d" + ) + assert ( + resp.operation_hash == "oo75gfQGGPEPChXZzcPPAGtYqCpsg2BS5q9gmhrU3NQP7CEffpU" + ) + + def test_tezos_kt_remove_delegation(self, client): + resp = tezos.sign_tx( + client, + TEZOS_PATH_10, + dict_to_proto( + messages.TezosSignTx, + { + "branch": "77a1800dd37b54f61755bd97b2a6759627c53a5f8afb00bdcf8255b5d23eff44", + "transaction": { + "source": "005f450441f41ee11eee78a31d1e1e55627c783bd6", + "fee": 10000, + "counter": 279, + "gas_limit": 25822, + "storage_limit": 0, + "amount": 0, + "destination": { + "tag": 1, + "hash": "c116a6c74bf00a5839b593838215fe1fcf2db59c00", + }, + "parameters_manager": {"cancel_delegate": True}, + }, + }, + ), + ) + assert ( + resp.signature + == "edsigtqZZd8r2cww5GvTpaJANizYyAAB8n2sByKJWYwgEQQu6gjzSi7mQ7NAxbwsCaHGUS3F87oDJ1J5mz8SM8KYVidQj1NUz8E" + ) + assert ( + resp.sig_op_contents.hex() + == "77a1800dd37b54f61755bd97b2a6759627c53a5f8afb00bdcf8255b5d23eff446c005f450441f41ee11eee78a31d1e1e55627c783bd6904e9702dec901000001c116a6c74bf00a5839b593838215fe1fcf2db59c00ff0200000013020000000e0320053d036d053e035d034e031b87b6a5f01c0689f8f453f2b23582a2891792087197e01276648eec734850999e54e9edd687efb9297e24a96d126dc1e6636e772aeab80d5bc6b3f9b55aa3a701" + ) + assert ( + resp.operation_hash == "ootMi1tXbfoVgFyzJa8iXyR4mnHd5TxLm9hmxVzMVRkbyVjKaHt" + ) + + def test_tezos_smart_contract_transfer(self, client): + resp = tezos.sign_tx( + client, + TEZOS_PATH_10, + dict_to_proto( + messages.TezosSignTx, + { + "branch": "442b86e27a7b79d893262b4daee229818f71073827570c74fa3aa1da7929d16d", + "transaction": { + "source": "005f450441f41ee11eee78a31d1e1e55627c783bd6", + "fee": 10000, + "counter": 280, + "gas_limit": 36000, + "storage_limit": 0, + "amount": 0, + "destination": { + "tag": 1, + "hash": "c116a6c74bf00a5839b593838215fe1fcf2db59c00", + }, + "parameters_manager": { + "transfer": { + "amount": 20000, + "destination": { + "tag": 0, + "hash": "005f450441f41ee11eee78a31d1e1e55627c783bd6", + }, + } + }, + }, + }, + ), + ) + assert ( + resp.signature + == "edsigtaY4HzLQ2oVDqnUAzbkSjGMQVBNHnBLq5t4TmVnsdAG8W4FWzeEnWbJXRQSTUKme3sXijve9vmDyAtim7HXeu9XhFJDrMo" + ) + assert ( + resp.sig_op_contents.hex() + == "442b86e27a7b79d893262b4daee229818f71073827570c74fa3aa1da7929d16d6c005f450441f41ee11eee78a31d1e1e55627c783bd6904e9802a09902000001c116a6c74bf00a5839b593838215fe1fcf2db59c00ff020000003902000000340320053d036d0743035d0a00000015005f450441f41ee11eee78a31d1e1e55627c783bd6031e0743036a00a0b802034f034d031b14dc70ef8db46c4b8f53e387ff3d642644af458f757ab85f9291727dc18bb09d7ec5790136b8cc428b165aec9cf628eeefc90aad526dc75e2aab203e57b8920f" + ) + assert ( + resp.operation_hash == "ooRGGtCmoQDgB36XvQqmM7govc3yb77YDUoa7p2QS7on27wGRns" + ) + + def test_tezos_smart_contract_transfer_to_contract(self, client): + resp = tezos.sign_tx( + client, + TEZOS_PATH_10, + dict_to_proto( + messages.TezosSignTx, + { + "branch": "8c696f9eb98cd641e33b680f424f7334b903d2b0108f0f896e73e921c44bf4c9", + "transaction": { + "source": "005f450441f41ee11eee78a31d1e1e55627c783bd6", + "fee": 4813, + "counter": 272, + "gas_limit": 44725, + "storage_limit": 0, + "amount": 0, + "destination": { + "tag": 1, + "hash": "c116a6c74bf00a5839b593838215fe1fcf2db59c00", + }, + "parameters_manager": { + "transfer": { + "amount": 200, + "destination": { + "tag": 1, + "hash": "8b83360512c6045c1185f8000de41302e23a220c00", + }, + } + }, + }, + }, + ), + ) + assert ( + resp.sig_op_contents.hex() + == "8c696f9eb98cd641e33b680f424f7334b903d2b0108f0f896e73e921c44bf4c96c005f450441f41ee11eee78a31d1e1e55627c783bd6cd259002b5dd02000001c116a6c74bf00a5839b593838215fe1fcf2db59c00ff020000005502000000500320053d036d0743036e0a00000016018b83360512c6045c1185f8000de41302e23a220c000555036c0200000015072f02000000090200000004034f032702000000000743036a008803034f034d031b911b8e7f22acdacc78e6d40566636a7029773c9ebfa741bb94bb58fb9e705d3ad695ac24fd1a58943c3070e9c38b0660671adb478233ae31005cd9139c84a80b" + ) + assert ( + resp.signature + == "edsigtrnr4jXpPZK1yFVGtsapR4VHKp9Gnz1Uj7G4AdAXVn8ug16tgUx5u3TsyYJFp9MzENKuVqotaEwco3JhAhKpbjxbBQhEsT" + ) + assert ( + resp.operation_hash == "opUE4xNkiUyYmJwUUgAab9xqHE66FXEc6VNZq4ZXDiBJcYwqNJX" + )