1
0
mirror of https://github.com/trezor/trezor-firmware.git synced 2024-12-29 01:28:10 +00:00

core/tezos: support the new protocol update (005-BABYLON)

This commit is contained in:
Adrian Nagy 2019-09-16 06:35:26 +02:00 committed by Pavol Rusnak
parent 09c3fd1981
commit 384275ac73
No known key found for this signature in database
GPG Key ID: 91F3B339B9A02A3D
19 changed files with 712 additions and 205 deletions

View File

@ -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;

View File

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

View File

@ -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)

View File

@ -21,6 +21,35 @@ async def sign_tx(ctx, msg, keychain):
node = keychain.derive(msg.address_n, CURVE)
if msg.transaction is not None:
# 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(
@ -28,7 +57,7 @@ async def sign_tx(ctx, msg, keychain):
)
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)
# 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"]))

View File

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

View File

@ -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),
}

View File

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

View File

@ -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),
}

View File

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

View File

@ -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),
}

View File

@ -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()

View File

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

View File

@ -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),
}

View File

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

View File

@ -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),
}

View File

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

View File

@ -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),
}

View File

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

View File

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