1
0
mirror of https://github.com/trezor/trezor-firmware.git synced 2025-02-15 17:12:04 +00:00

app.lisk: code style

This commit is contained in:
Jan Pochyla 2018-05-21 15:09:06 +02:00
parent 04c652c120
commit 523e57ea52
5 changed files with 124 additions and 112 deletions

View File

@ -1,11 +1,11 @@
from apps.common import seed
from apps.wallet.get_address import _show_address, _show_qr from apps.wallet.get_address import _show_address, _show_qr
from trezor.messages.LiskAddress import LiskAddress
from .helpers import LISK_CURVE, get_address_from_public_key from .helpers import LISK_CURVE, get_address_from_public_key
async def layout_lisk_get_address(ctx, msg): async def layout_lisk_get_address(ctx, msg):
from trezor.messages.LiskAddress import LiskAddress
from ..common import seed
address_n = msg.address_n or () address_n = msg.address_n or ()
node = await seed.derive_node(ctx, address_n, LISK_CURVE) node = await seed.derive_node(ctx, address_n, LISK_CURVE)

View File

@ -1,11 +1,11 @@
from apps.common import seed
from apps.wallet.get_public_key import _show_pubkey from apps.wallet.get_public_key import _show_pubkey
from trezor.messages.LiskPublicKey import LiskPublicKey
from .helpers import LISK_CURVE from .helpers import LISK_CURVE
async def lisk_get_public_key(ctx, msg): async def lisk_get_public_key(ctx, msg):
from trezor.messages.LiskPublicKey import LiskPublicKey
from ..common import seed
address_n = msg.address_n or () address_n = msg.address_n or ()
node = await seed.derive_node(ctx, address_n, LISK_CURVE) node = await seed.derive_node(ctx, address_n, LISK_CURVE)

View File

@ -1,12 +1,13 @@
from trezor.crypto.hashlib import sha256
LISK_CURVE = 'ed25519' LISK_CURVE = 'ed25519'
def get_address_from_public_key(public_key):
from trezor.crypto.hashlib import sha256
public_key_hash = sha256(public_key).digest() def get_address_from_public_key(pubkey):
address = int.from_bytes(public_key_hash[:8], 'little') pubkeyhash = sha256(pubkey).digest()
return str(address) + "L" address = int.from_bytes(pubkeyhash[:8], 'little')
return str(address) + 'L'
def get_votes_count(votes): def get_votes_count(votes):
plus, minus = 0, 0 plus, minus = 0, 0
@ -17,6 +18,7 @@ def get_votes_count(votes):
minus += 1 minus += 1
return plus, minus return plus, minus
def get_vote_tx_text(votes): def get_vote_tx_text(votes):
plus, minus = get_votes_count(votes) plus, minus = get_votes_count(votes)
text = [] text = []
@ -26,5 +28,6 @@ def get_vote_tx_text(votes):
text.append(_text_with_plural('Remove', minus)) text.append(_text_with_plural('Remove', minus))
return text return text
def _text_with_plural(txt, value): def _text_with_plural(txt, value):
return '%s %s %s' % (txt, value, ('votes' if value != 1 else 'vote')) return '%s %s %s' % (txt, value, ('votes' if value != 1 else 'vote'))

View File

@ -1,8 +1,10 @@
from apps.common.confirm import * from apps.common.confirm import require_confirm, require_hold_to_confirm
from apps.wallet.get_public_key import _show_pubkey
from trezor import ui from trezor import ui
from trezor.utils import chunks
from trezor.messages import ButtonRequestType from trezor.messages import ButtonRequestType
from trezor.ui.text import Text from trezor.ui.text import Text
from trezor.utils import chunks
from .helpers import get_vote_tx_text from .helpers import get_vote_tx_text
@ -14,6 +16,7 @@ async def require_confirm_tx(ctx, to, value):
icon_color=ui.GREEN) icon_color=ui.GREEN)
return await require_confirm(ctx, content, ButtonRequestType.SignTx) return await require_confirm(ctx, content, ButtonRequestType.SignTx)
async def require_confirm_delegate_registration(ctx, delegate_name): async def require_confirm_delegate_registration(ctx, delegate_name):
content = Text('Confirm transaction', ui.ICON_SEND, content = Text('Confirm transaction', ui.ICON_SEND,
'Do you really want to', 'Do you really want to',
@ -22,26 +25,27 @@ async def require_confirm_delegate_registration(ctx, delegate_name):
icon_color=ui.GREEN) icon_color=ui.GREEN)
return await require_confirm(ctx, content, ButtonRequestType.SignTx) return await require_confirm(ctx, content, ButtonRequestType.SignTx)
async def require_confirm_vote_tx(ctx, votes): async def require_confirm_vote_tx(ctx, votes):
content = Text('Confirm transaction', ui.ICON_SEND, content = Text('Confirm transaction', ui.ICON_SEND,
*get_vote_tx_text(votes), *get_vote_tx_text(votes),
icon_color=ui.GREEN) icon_color=ui.GREEN)
return await require_confirm(ctx, content, ButtonRequestType.SignTx) return await require_confirm(ctx, content, ButtonRequestType.SignTx)
async def require_confirm_public_key(ctx, public_key): async def require_confirm_public_key(ctx, public_key):
from apps.wallet.get_public_key import _show_pubkey
return await _show_pubkey(ctx, public_key) return await _show_pubkey(ctx, public_key)
async def require_confirm_multisig(ctx, multisignature): async def require_confirm_multisig(ctx, multisignature):
content = Text('Confirm transaction', ui.ICON_SEND, content = Text('Confirm transaction', ui.ICON_SEND,
('Keys group length: %s' % len(multisignature.keys_group)), ('Keys group length: %s' % len(multisignature.keys_group)),
('Life time: %s' % multisignature.life_time), ('Life time: %s' % multisignature.life_time),
('Min: %s' % multisignature.min), ('Min: %s' % multisignature.min),
icon_color=ui.GREEN) icon_color=ui.GREEN)
return await require_confirm(ctx, content, ButtonRequestType.SignTx) return await require_confirm(ctx, content, ButtonRequestType.SignTx)
async def require_confirm_fee(ctx, value, fee): async def require_confirm_fee(ctx, value, fee):
content = Text('Confirm transaction', ui.ICON_SEND, content = Text('Confirm transaction', ui.ICON_SEND,
ui.BOLD, format_amount(value), ui.BOLD, format_amount(value),
@ -50,8 +54,10 @@ async def require_confirm_fee(ctx, value, fee):
icon_color=ui.GREEN) icon_color=ui.GREEN)
await require_hold_to_confirm(ctx, content, ButtonRequestType.ConfirmOutput) await require_hold_to_confirm(ctx, content, ButtonRequestType.ConfirmOutput)
def format_amount(value): def format_amount(value):
return '%s LSK' % (int(value) / 100000000) return '%s LSK' % (int(value) / 100000000)
def split_address(address): def split_address(address):
return chunks(address, 16) return chunks(address, 16)

View File

@ -1,112 +1,39 @@
from trezor import wire, ui import ustruct
from apps.common import seed
from trezor import wire
from trezor.crypto.curve import ed25519
from trezor.crypto.hashlib import sha256
from trezor.messages import LiskTransactionType
from trezor.messages.LiskSignedTx import LiskSignedTx from trezor.messages.LiskSignedTx import LiskSignedTx
from trezor.messages.LiskTransactionType import *
from trezor.messages import FailureType
from trezor.utils import HashWriter from trezor.utils import HashWriter
from apps.lisk.layout import *
from ubinascii import unhexlify, hexlify from . import layout
from .helpers import LISK_CURVE, get_address_from_public_key
async def lisk_sign_tx(ctx, msg): async def lisk_sign_tx(ctx, msg):
from trezor.crypto.hashlib import sha256
pubkey, seckey = await _get_keys(ctx, msg) pubkey, seckey = await _get_keys(ctx, msg)
transaction = update_raw_tx(msg.transaction, pubkey) transaction = _update_raw_tx(msg.transaction, pubkey)
# throw ValueError if transaction has not valid structure
try: try:
await require_confirm_by_type(ctx, transaction) await _require_confirm_by_type(ctx, transaction)
except AttributeError: except AttributeError:
raise ValueError(FailureType.DataError, 'The transaction has invalid asset data field') raise wire.DataError('The transaction has invalid asset data field')
await require_confirm_fee(ctx, transaction.amount, transaction.fee) await layout.require_confirm_fee(ctx, transaction.amount, transaction.fee)
sha = HashWriter(sha256) txbytes = _get_transaction_bytes(transaction)
transaction_bytes = _get_transaction_bytes(transaction) txhash = HashWriter(sha256)
for field in txbytes:
txhash.extend(field)
digest = txhash.get_digest()
for field in transaction_bytes: signature = ed25519.sign(seckey, digest)
sha.extend(field)
digest = sha.get_digest()
signature = await get_signature(seckey, digest)
return LiskSignedTx(signature=signature) return LiskSignedTx(signature=signature)
async def require_confirm_by_type(ctx, transaction):
if transaction.type == Transfer:
return await require_confirm_tx(ctx, transaction.recipient_id, transaction.amount)
if transaction.type == RegisterDelegate:
return await require_confirm_delegate_registration(ctx, transaction.asset.delegate.username)
if transaction.type == CastVotes:
return await require_confirm_vote_tx(ctx, transaction.asset.votes)
if transaction.type == RegisterSecondPassphrase:
return await require_confirm_public_key(ctx, transaction.asset.signature.public_key)
if transaction.type == RegisterMultisignatureAccount:
return await require_confirm_multisig(ctx, transaction.asset.multisignature)
raise ValueError(FailureType.DataError, 'Invalid transaction type')
async def get_signature(seckey, digest):
from trezor.crypto.curve import ed25519
signature = ed25519.sign(seckey, digest)
return signature
def _get_transaction_bytes(msg):
from ustruct import pack
# Required transaction parameters
t_type = pack('<b', msg.type)
t_timestamp = pack('<i', msg.timestamp)
t_amount = pack('<Q', msg.amount)
t_pubkey = msg.sender_public_key
t_requester_public_key = msg.requester_public_key or b''
# Value can be empty string
if not msg.recipient_id:
t_recipient_id = pack('>Q', 0)
else:
# Lisk use big-endian for recipient_id
# string -> int -> bytes
t_recipient_id = pack('>Q', int(msg.recipient_id[:-1]))
t_signature = msg.signature or b''
t_asset = _get_asset_data_bytes(msg)
return t_type, t_timestamp, t_pubkey, t_requester_public_key, t_recipient_id, t_amount, t_asset, t_signature
def _get_asset_data_bytes(msg):
from ustruct import pack
if msg.type == Transfer:
# Transfer transaction have optional data field
if msg.asset.data is not None:
return bytes(msg.asset.data, "utf8")
else:
return b''
if msg.type == RegisterDelegate:
return bytes(msg.asset.delegate.username, "utf8")
if msg.type == CastVotes:
return bytes("".join(msg.asset.votes), "utf8")
if msg.type == RegisterSecondPassphrase:
return msg.asset.signature.public_key
if msg.type == RegisterMultisignatureAccount:
data = b''
data += pack('<b', msg.asset.multisignature.min)
data += pack('<b', msg.asset.multisignature.life_time)
data += bytes("".join(msg.asset.multisignature.keys_group), "utf8")
return data
async def _get_keys(ctx, msg): async def _get_keys(ctx, msg):
from ..common import seed
from .helpers import LISK_CURVE
address_n = msg.address_n or () address_n = msg.address_n or ()
node = await seed.derive_node(ctx, address_n, LISK_CURVE) node = await seed.derive_node(ctx, address_n, LISK_CURVE)
@ -116,13 +43,89 @@ async def _get_keys(ctx, msg):
return pubkey, seckey return pubkey, seckey
def update_raw_tx(transaction, pubkey):
from .helpers import get_address_from_public_key
def _update_raw_tx(transaction, pubkey):
transaction.sender_public_key = pubkey transaction.sender_public_key = pubkey
# For this type of transactions, recipientId should be equal transaction creator address. # For CastVotes transactions, recipientId should be equal to transaction
if transaction.type == CastVotes: # creator address.
if transaction.type == LiskTransactionType.CastVotes:
transaction.recipient_id = get_address_from_public_key(pubkey) transaction.recipient_id = get_address_from_public_key(pubkey)
return transaction return transaction
async def _require_confirm_by_type(ctx, transaction):
if transaction.type == LiskTransactionType.Transfer:
return await layout.require_confirm_tx(
ctx, transaction.recipient_id, transaction.amount)
if transaction.type == LiskTransactionType.RegisterDelegate:
return await layout.require_confirm_delegate_registration(
ctx, transaction.asset.delegate.username)
if transaction.type == LiskTransactionType.CastVotes:
return await layout.require_confirm_vote_tx(
ctx, transaction.asset.votes)
if transaction.type == LiskTransactionType.RegisterSecondPassphrase:
return await layout.require_confirm_public_key(
ctx, transaction.asset.signature.public_key)
if transaction.type == LiskTransactionType.RegisterMultisignatureAccount:
return await layout.require_confirm_multisig(
ctx, transaction.asset.multisignature)
raise wire.DataError('Invalid transaction type')
def _get_transaction_bytes(tx):
# Required transaction parameters
t_type = ustruct.pack('<b', tx.type)
t_timestamp = ustruct.pack('<i', tx.timestamp)
t_sender_public_key = tx.sender_public_key
t_requester_public_key = tx.requester_public_key or b''
if not tx.recipient_id:
# Value can be empty string
t_recipient_id = ustruct.pack('>Q', 0)
else:
# Lisk uses big-endian for recipient_id, string -> int -> bytes
t_recipient_id = ustruct.pack('>Q', int(tx.recipient_id[:-1]))
t_amount = ustruct.pack('<Q', tx.amount)
t_asset = _get_asset_data_bytes(tx)
t_signature = tx.signature or b''
return (t_type, t_timestamp, t_sender_public_key, t_requester_public_key,
t_recipient_id, t_amount, t_asset, t_signature)
def _get_asset_data_bytes(msg):
if msg.type == LiskTransactionType.Transfer:
# Transfer transaction have optional data field
if msg.asset.data is not None:
return bytes(msg.asset.data, 'utf8')
else:
return b''
if msg.type == LiskTransactionType.RegisterDelegate:
return bytes(msg.asset.delegate.username, 'utf8')
if msg.type == LiskTransactionType.CastVotes:
return bytes(''.join(msg.asset.votes), 'utf8')
if msg.type == LiskTransactionType.RegisterSecondPassphrase:
return msg.asset.signature.public_key
if msg.type == LiskTransactionType.RegisterMultisignatureAccount:
data = b''
data += ustruct.pack('<b', msg.asset.multisignature.min)
data += ustruct.pack('<b', msg.asset.multisignature.life_time)
data += bytes(''.join(msg.asset.multisignature.keys_group), 'utf8')
return data
raise wire.DataError('Invalid transaction type')