1
0
mirror of https://github.com/trezor/trezor-firmware.git synced 2024-11-26 01:18:28 +00:00

tezos: fixed nitpicks

Signed-off-by: Adrian Matejov <adrian.matejov@simplestaking.com>
This commit is contained in:
Adrian Matejov 2018-09-11 13:32:15 +02:00 committed by Tomas Susanka
parent d4987849ce
commit 8b252bff80
6 changed files with 134 additions and 110 deletions

View File

@ -1,20 +1,22 @@
from trezor.crypto import hashlib from trezor.crypto import hashlib
from trezor.crypto.curve import ed25519
from trezor.messages.TezosAddress import TezosAddress from trezor.messages.TezosAddress import TezosAddress
from apps.common import seed from apps.common import seed
from apps.common.layout import show_address, show_qr from apps.common.layout import show_address, show_qr
from apps.tezos.helpers import TEZOS_CURVE, b58cencode, tezos_get_address_prefix from apps.tezos.helpers import (
TEZOS_CURVE,
TEZOS_ED25519_ADDRESS_PREFIX,
base58_encode_check,
)
async def get_address(ctx, msg): async def get_address(ctx, msg):
address_n = msg.address_n or () address_n = msg.address_n or ()
node = await seed.derive_node(ctx, address_n, TEZOS_CURVE) node = await seed.derive_node(ctx, address_n, TEZOS_CURVE)
sk = node.private_key() pk = seed.remove_ed25519_prefix(node.public_key())
pk = ed25519.publickey(sk)
pkh = hashlib.blake2b(pk, outlen=20).digest() pkh = hashlib.blake2b(pk, outlen=20).digest()
address = b58cencode(pkh, prefix=tezos_get_address_prefix(0)) address = base58_encode_check(pkh, prefix=TEZOS_ED25519_ADDRESS_PREFIX)
if msg.show_display: if msg.show_display:
while True: while True:

View File

@ -1,5 +1,4 @@
from trezor import ui from trezor import ui
from trezor.crypto.curve import ed25519
from trezor.messages import ButtonRequestType from trezor.messages import ButtonRequestType
from trezor.messages.TezosPublicKey import TezosPublicKey from trezor.messages.TezosPublicKey import TezosPublicKey
from trezor.ui.text import Text from trezor.ui.text import Text
@ -7,16 +6,15 @@ from trezor.utils import chunks
from apps.common import seed from apps.common import seed
from apps.common.confirm import require_confirm from apps.common.confirm import require_confirm
from apps.tezos.helpers import TEZOS_CURVE, TEZOS_PUBLICKEY_PREFIX, b58cencode from apps.tezos.helpers import TEZOS_CURVE, TEZOS_PUBLICKEY_PREFIX, base58_encode_check
async def get_public_key(ctx, msg): async def get_public_key(ctx, msg):
address_n = msg.address_n or () address_n = msg.address_n or ()
node = await seed.derive_node(ctx, address_n, TEZOS_CURVE) node = await seed.derive_node(ctx, address_n, TEZOS_CURVE)
sk = node.private_key() pk = seed.remove_ed25519_prefix(node.public_key())
pk = ed25519.publickey(sk) pk_prefixed = base58_encode_check(pk, prefix=TEZOS_PUBLICKEY_PREFIX)
pk_prefixed = b58cencode(pk, prefix=TEZOS_PUBLICKEY_PREFIX)
if msg.show_display: if msg.show_display:
await _show_tezos_pubkey(ctx, pk_prefixed) await _show_tezos_pubkey(ctx, pk_prefixed)

View File

@ -1,10 +1,10 @@
from micropython import const from micropython import const
from trezor import wire
from trezor.crypto import base58 from trezor.crypto import base58
TEZOS_CURVE = "ed25519" TEZOS_CURVE = "ed25519"
TEZOS_AMOUNT_DIVISIBILITY = const(6) TEZOS_AMOUNT_DIVISIBILITY = const(6)
TEZOS_ED25519_ADDRESS_PREFIX = "tz1"
TEZOS_ORIGINATED_ADDRESS_PREFIX = "KT1" TEZOS_ORIGINATED_ADDRESS_PREFIX = "KT1"
TEZOS_PUBLICKEY_PREFIX = "edpk" TEZOS_PUBLICKEY_PREFIX = "edpk"
TEZOS_SIGNATURE_PREFIX = "edsig" TEZOS_SIGNATURE_PREFIX = "edsig"
@ -23,21 +23,14 @@ TEZOS_PREFIX_BYTES = {
} }
def tezos_get_address_prefix(tag): def base58_encode_check(payload, prefix=None):
prefixes = ["tz1", "tz2", "tz3"]
if 0 <= tag < len(prefixes):
return prefixes[tag]
raise wire.DataError("Invalid tag in address hash")
def b58cencode(payload, prefix=None):
result = payload result = payload
if prefix is not None: if prefix is not None:
result = bytes(TEZOS_PREFIX_BYTES[prefix]) + payload result = bytes(TEZOS_PREFIX_BYTES[prefix]) + payload
return base58.encode_check(result) return base58.encode_check(result)
def b58cdecode(enc, prefix=None): def base58_decode_check(enc, prefix=None):
decoded = base58.decode_check(enc) decoded = base58.decode_check(enc)
if prefix is not None: if prefix is not None:
decoded = decoded[len(TEZOS_PREFIX_BYTES[prefix]) :] decoded = decoded[len(TEZOS_PREFIX_BYTES[prefix]) :]

View File

@ -1,5 +1,3 @@
import ustruct
from trezor import wire from trezor import wire
from trezor.crypto import hashlib from trezor.crypto import hashlib
from trezor.crypto.curve import ed25519 from trezor.crypto.curve import ed25519
@ -7,12 +5,12 @@ from trezor.messages import TezosContractType
from trezor.messages.TezosSignedTx import TezosSignedTx from trezor.messages.TezosSignedTx import TezosSignedTx
from apps.common import seed from apps.common import seed
from apps.common.writers import write_bytes, write_uint8
from apps.tezos.helpers import ( from apps.tezos.helpers import (
TEZOS_CURVE, TEZOS_CURVE,
TEZOS_ORIGINATED_ADDRESS_PREFIX, TEZOS_ORIGINATED_ADDRESS_PREFIX,
TEZOS_SIGNATURE_PREFIX, TEZOS_SIGNATURE_PREFIX,
b58cencode, base58_encode_check,
tezos_get_address_prefix,
) )
from apps.tezos.layout import * from apps.tezos.layout import *
@ -50,8 +48,12 @@ async def sign_tx(ctx, msg):
else: else:
raise wire.DataError("Invalid operation") raise wire.DataError("Invalid operation")
opbytes = _get_operation_bytes(msg) w = bytearray()
_get_operation_bytes(w, msg)
opbytes = bytes(w)
# watermark 0x03 is prefix for transactions, delegations, originations, reveals...
watermark = bytes([3]) watermark = bytes([3])
wm_opbytes = watermark + opbytes wm_opbytes = watermark + opbytes
wm_opbytes_hash = hashlib.blake2b(wm_opbytes, outlen=32).digest() wm_opbytes_hash = hashlib.blake2b(wm_opbytes, outlen=32).digest()
@ -60,9 +62,9 @@ async def sign_tx(ctx, msg):
sig_op_contents = opbytes + signature sig_op_contents = 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 = b58cencode(sig_op_contents_hash, prefix="o") ophash = base58_encode_check(sig_op_contents_hash, prefix="o")
sig_prefixed = b58cencode(signature, prefix=TEZOS_SIGNATURE_PREFIX) sig_prefixed = base58_encode_check(signature, prefix=TEZOS_SIGNATURE_PREFIX)
return TezosSignedTx( 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
@ -70,8 +72,12 @@ async def sign_tx(ctx, msg):
def _get_address_by_tag(address_hash): def _get_address_by_tag(address_hash):
prefixes = ["tz1", "tz2", "tz3"]
tag = int(address_hash[0]) tag = int(address_hash[0])
return b58cencode(address_hash[1:], prefix=tezos_get_address_prefix(tag))
if 0 <= tag < len(prefixes):
return base58_encode_check(address_hash[1:], prefix=prefixes[tag])
raise wire.DataError("Invalid tag in address hash")
def _get_address_from_contract(address): def _get_address_from_contract(address):
@ -79,77 +85,80 @@ def _get_address_from_contract(address):
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 b58cencode(address.hash[:-1], prefix=TEZOS_ORIGINATED_ADDRESS_PREFIX) return base58_encode_check(
address.hash[:-1], prefix=TEZOS_ORIGINATED_ADDRESS_PREFIX
)
raise wire.DataError("Invalid contract type") raise wire.DataError("Invalid contract type")
def _get_operation_bytes(msg): def _get_operation_bytes(w: bytearray, msg):
result = msg.branch write_bytes(w, msg.branch)
# when the account sends first operation in lifetime, # when the account sends first operation in lifetime,
# we need to reveal its publickey # we need to reveal its publickey
if msg.reveal is not None: if msg.reveal is not None:
result += _encode_common(msg.reveal, "reveal") _encode_common(w, msg.reveal, "reveal")
result += msg.reveal.public_key write_bytes(w, msg.reveal.public_key)
# transaction operation # transaction operation
if msg.transaction is not None: if msg.transaction is not None:
result += _encode_common(msg.transaction, "transaction") _encode_common(w, msg.transaction, "transaction")
result += _encode_zarith(msg.transaction.amount) _encode_zarith(w, msg.transaction.amount)
result += _encode_contract_id(msg.transaction.destination) _encode_contract_id(w, msg.transaction.destination)
result += _encode_data_with_bool_prefix(msg.transaction.parameters) _encode_data_with_bool_prefix(w, msg.transaction.parameters)
# origination operation # origination operation
elif msg.origination is not None: elif msg.origination is not None:
result += _encode_common(msg.origination, "origination") _encode_common(w, msg.origination, "origination")
result += msg.origination.manager_pubkey write_bytes(w, msg.origination.manager_pubkey)
result += _encode_zarith(msg.origination.balance) _encode_zarith(w, msg.origination.balance)
result += _encode_bool(msg.origination.spendable) _encode_bool(w, msg.origination.spendable)
result += _encode_bool(msg.origination.delegatable) _encode_bool(w, msg.origination.delegatable)
result += _encode_data_with_bool_prefix(msg.origination.delegate) _encode_data_with_bool_prefix(w, msg.origination.delegate)
result += _encode_data_with_bool_prefix(msg.origination.script) _encode_data_with_bool_prefix(w, msg.origination.script)
# delegation operation # delegation operation
elif msg.delegation is not None: elif msg.delegation is not None:
result += _encode_common(msg.delegation, "delegation") _encode_common(w, msg.delegation, "delegation")
result += _encode_data_with_bool_prefix(msg.delegation.delegate) _encode_data_with_bool_prefix(w, msg.delegation.delegate)
return bytes(result)
def _encode_common(operation, str_operation): def _encode_common(w: bytearray, operation, str_operation):
operation_tags = {"reveal": 7, "transaction": 8, "origination": 9, "delegation": 10} operation_tags = {"reveal": 7, "transaction": 8, "origination": 9, "delegation": 10}
result = ustruct.pack("<b", operation_tags[str_operation]) write_uint8(w, operation_tags[str_operation])
result += _encode_contract_id(operation.source) _encode_contract_id(w, operation.source)
result += _encode_zarith(operation.fee) _encode_zarith(w, operation.fee)
result += _encode_zarith(operation.counter) _encode_zarith(w, operation.counter)
result += _encode_zarith(operation.gas_limit) _encode_zarith(w, operation.gas_limit)
result += _encode_zarith(operation.storage_limit) _encode_zarith(w, operation.storage_limit)
return result
def _encode_contract_id(contract_id): def _encode_contract_id(w: bytearray, contract_id):
return ustruct.pack("<b", contract_id.tag) + contract_id.hash write_uint8(w, contract_id.tag)
write_bytes(w, contract_id.hash)
def _encode_bool(boolean): def _encode_bool(w: bytearray, boolean):
return ustruct.pack("<b", 255) if boolean else ustruct.pack("<b", 0) if boolean:
write_uint8(w, 255)
else:
write_uint8(w, 0)
def _encode_data_with_bool_prefix(data): def _encode_data_with_bool_prefix(w: bytearray, data):
return _encode_bool(True) + data if data is not None else _encode_bool(False) if data:
_encode_bool(w, True)
write_bytes(w, data)
else:
_encode_bool(w, False)
def _encode_zarith(num): def _encode_zarith(w: bytearray, num):
result = bytes()
while True: while True:
byte = num & 127 byte = num & 127
num = num >> 7 num = num >> 7
if num == 0: if num == 0:
result += ustruct.pack("<b", byte) write_uint8(w, byte)
break break
result += ustruct.pack("<b", 128 | byte) write_uint8(w, 128 | byte)
return result

View File

@ -1,42 +1,43 @@
from common import *
from ubinascii import unhexlify from ubinascii import unhexlify
from common import *
from trezor.messages import TezosContractType from trezor.messages import TezosContractType
from trezor.messages.TezosContractID import TezosContractID from trezor.messages.TezosContractID import TezosContractID
from apps.tezos.sign_tx import _get_address_from_contract from apps.tezos.sign_tx import _get_address_from_contract
class TestTezosAddress(unittest.TestCase): class TestTezosAddress(unittest.TestCase):
def test_get_address_from_contract(self): def test_get_address_from_contract(self):
contracts = [ contracts = [
TezosContractID( TezosContractID(
tag=TezosContractType.Implicit, tag=TezosContractType.Implicit,
hash=unhexlify("0090ec585b4d5fa39b20213e46b232cc57a4cfab4b") hash=unhexlify("0090ec585b4d5fa39b20213e46b232cc57a4cfab4b"),
), ),
TezosContractID( TezosContractID(
tag=TezosContractType.Implicit, tag=TezosContractType.Implicit,
hash=unhexlify("017dfb3fef44082eca8cd3eccebd77db44633ffc9e") hash=unhexlify("017dfb3fef44082eca8cd3eccebd77db44633ffc9e"),
), ),
TezosContractID( TezosContractID(
tag=TezosContractType.Implicit, tag=TezosContractType.Implicit,
hash=unhexlify("02c1fc1b7e503825068ff4fe2f8916f98af981eab1") hash=unhexlify("02c1fc1b7e503825068ff4fe2f8916f98af981eab1"),
), ),
TezosContractID( TezosContractID(
tag=TezosContractType.Originated, tag=TezosContractType.Originated,
hash=unhexlify("65671dedc69669f066f45d586a2ecdeddacc95af00") hash=unhexlify("65671dedc69669f066f45d586a2ecdeddacc95af00"),
) ),
] ]
outputs = [ outputs = [
"tz1YrK8Hqt6GAPYRHAaeJmhETYyPSQCHTrkj", "tz1YrK8Hqt6GAPYRHAaeJmhETYyPSQCHTrkj",
"tz2KoN7TFjhp96V2XikqYSGyDmVVUHXvkzko", "tz2KoN7TFjhp96V2XikqYSGyDmVVUHXvkzko",
"tz3e1k3QzCwEbRZrfHCwT3Npvw1rezmMQArY", "tz3e1k3QzCwEbRZrfHCwT3Npvw1rezmMQArY",
"KT1HpwLq2AjZgEQspiSnYmdtaHy4NgXw6BDC" "KT1HpwLq2AjZgEQspiSnYmdtaHy4NgXw6BDC",
] ]
for i, contract in enumerate(contracts): for i, contract in enumerate(contracts):
self.assertEqual(_get_address_from_contract(contract), outputs[i]) self.assertEqual(_get_address_from_contract(contract), outputs[i])
if __name__ == '__main__': if __name__ == "__main__":
unittest.main() unittest.main()

View File

@ -1,79 +1,100 @@
from common import *
from ubinascii import unhexlify from ubinascii import unhexlify
from common import *
from trezor.messages import TezosContractType from trezor.messages import TezosContractType
from trezor.messages.TezosContractID import TezosContractID from trezor.messages.TezosContractID import TezosContractID
from apps.tezos.helpers import b58cencode, b58cdecode from apps.tezos.helpers import base58_decode_check, base58_encode_check
from apps.tezos.sign_tx import ( from apps.tezos.sign_tx import (
_encode_zarith,
_encode_data_with_bool_prefix,
_encode_bool, _encode_bool,
_encode_contract_id _encode_contract_id,
_encode_data_with_bool_prefix,
_encode_zarith,
) )
class TestTezosEncoding(unittest.TestCase): class TestTezosEncoding(unittest.TestCase):
def test_tezos_encode_zarith(self): def test_tezos_encode_zarith(self):
inputs = [2000000, 159066, 200, 60000, 157000000, 0] inputs = [2000000, 159066, 200, 60000, 157000000, 0]
outputs = ["80897a", "dada09", "c801", "e0d403", "c0c2ee4a", "00"] outputs = ["80897a", "dada09", "c801", "e0d403", "c0c2ee4a", "00"]
for i, o in zip(inputs, outputs): for i, o in zip(inputs, outputs):
self.assertEqual(_encode_zarith(i), unhexlify(o)) w = bytearray()
_encode_zarith(w, i)
self.assertEqual(bytes(w), unhexlify(o))
def test_tezos_encode_data_with_bool_prefix(self): def test_tezos_encode_data_with_bool_prefix(self):
self.assertEqual(_encode_data_with_bool_prefix(None), bytes([0])) w = bytearray()
_encode_data_with_bool_prefix(w, None)
self.assertEqual(bytes(w), bytes([0]))
data = "afffeb1dc3c0" data = "afffeb1dc3c0"
self.assertEqual(_encode_data_with_bool_prefix(unhexlify(data)), w = bytearray()
unhexlify("ff" + data)) _encode_data_with_bool_prefix(w, unhexlify(data))
self.assertEqual(bytes(w), unhexlify("ff" + data))
def test_tezos_encode_bool(self): def test_tezos_encode_bool(self):
self.assertEqual(_encode_bool(True), bytes([255])) w = bytearray()
self.assertEqual(_encode_bool(False), bytes([0])) _encode_bool(w, True)
self.assertEqual(bytes(w), bytes([255]))
w = bytearray()
_encode_bool(w, False)
self.assertEqual(bytes(w), bytes([0]))
def test_tezos_encode_contract_id(self): def test_tezos_encode_contract_id(self):
implicit = TezosContractID( implicit = TezosContractID(
tag=TezosContractType.Implicit, tag=TezosContractType.Implicit,
hash=unhexlify("00101368afffeb1dc3c089facbbe23f5c30b787ce9") hash=unhexlify("00101368afffeb1dc3c089facbbe23f5c30b787ce9"),
)
w = bytearray()
_encode_contract_id(w, implicit)
self.assertEqual(
bytes(w), unhexlify("0000101368afffeb1dc3c089facbbe23f5c30b787ce9")
) )
self.assertEqual(_encode_contract_id(implicit),
unhexlify("0000101368afffeb1dc3c089facbbe23f5c30b787ce9"))
originated = TezosContractID( originated = TezosContractID(
tag=TezosContractType.Originated, tag=TezosContractType.Originated,
hash=unhexlify("65671dedc69669f066f45d586a2ecdeddacc95af00") hash=unhexlify("65671dedc69669f066f45d586a2ecdeddacc95af00"),
)
w = bytearray()
_encode_contract_id(w, originated)
self.assertEqual(
bytes(w), unhexlify("0165671dedc69669f066f45d586a2ecdeddacc95af00")
) )
self.assertEqual(_encode_contract_id(originated),
unhexlify("0165671dedc69669f066f45d586a2ecdeddacc95af00"))
def test_tezos_b58cencode(self): def test_tezos_base58_encode_check(self):
pkh = unhexlify("101368afffeb1dc3c089facbbe23f5c30b787ce9") pkh = unhexlify("101368afffeb1dc3c089facbbe23f5c30b787ce9")
self.assertEqual(b58cencode(pkh, prefix="tz1"), self.assertEqual(
"tz1M72kkAJrntPtayM4yU4CCwQPLSdpEgRrn") base58_encode_check(pkh, prefix="tz1"),
self.assertEqual(b58cencode(pkh, prefix="tz2"), "tz1M72kkAJrntPtayM4yU4CCwQPLSdpEgRrn",
"tz29nEixktH9p9XTFX7p8hATUyeLxXEz96KR") )
self.assertEqual(b58cencode(pkh, prefix="tz3"), self.assertEqual(
"tz3Mo3gHekQhCmykfnC58ecqJLXrjMKzkF2Q") base58_encode_check(pkh, prefix="tz2"),
self.assertEqual(b58cencode(pkh), "2U14dJ6ED97bBHDZTQWA6umVL8SAVefXj") "tz29nEixktH9p9XTFX7p8hATUyeLxXEz96KR",
)
self.assertEqual(
base58_encode_check(pkh, prefix="tz3"),
"tz3Mo3gHekQhCmykfnC58ecqJLXrjMKzkF2Q",
)
self.assertEqual(base58_encode_check(pkh), "2U14dJ6ED97bBHDZTQWA6umVL8SAVefXj")
def test_tezos_b58cdecode(self): def test_tezos_base58_decode_check(self):
pkh = unhexlify("101368afffeb1dc3c089facbbe23f5c30b787ce9") pkh = unhexlify("101368afffeb1dc3c089facbbe23f5c30b787ce9")
address = "tz1M72kkAJrntPtayM4yU4CCwQPLSdpEgRrn" address = "tz1M72kkAJrntPtayM4yU4CCwQPLSdpEgRrn"
self.assertEqual(b58cdecode(address, prefix="tz1"), pkh) self.assertEqual(base58_decode_check(address, prefix="tz1"), pkh)
address = "tz29nEixktH9p9XTFX7p8hATUyeLxXEz96KR" address = "tz29nEixktH9p9XTFX7p8hATUyeLxXEz96KR"
self.assertEqual(b58cdecode(address, prefix="tz2"), pkh) self.assertEqual(base58_decode_check(address, prefix="tz2"), pkh)
address = "tz3Mo3gHekQhCmykfnC58ecqJLXrjMKzkF2Q" address = "tz3Mo3gHekQhCmykfnC58ecqJLXrjMKzkF2Q"
self.assertEqual(b58cdecode(address, prefix="tz3"), pkh) self.assertEqual(base58_decode_check(address, prefix="tz3"), pkh)
address = "2U14dJ6ED97bBHDZTQWA6umVL8SAVefXj" address = "2U14dJ6ED97bBHDZTQWA6umVL8SAVefXj"
self.assertEqual(b58cdecode(address), pkh) self.assertEqual(base58_decode_check(address), pkh)
if __name__ == '__main__': if __name__ == "__main__":
unittest.main() unittest.main()