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 trezor.messages.LiskAddress import LiskAddress
from .helpers import LISK_CURVE, get_address_from_public_key
async def layout_lisk_get_address(ctx, msg):
from trezor.messages.LiskAddress import LiskAddress
from ..common import seed
address_n = msg.address_n or ()
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 trezor.messages.LiskPublicKey import LiskPublicKey
from .helpers import LISK_CURVE
async def lisk_get_public_key(ctx, msg):
from trezor.messages.LiskPublicKey import LiskPublicKey
from ..common import seed
address_n = msg.address_n or ()
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'
def get_address_from_public_key(public_key):
from trezor.crypto.hashlib import sha256
public_key_hash = sha256(public_key).digest()
address = int.from_bytes(public_key_hash[:8], 'little')
return str(address) + "L"
def get_address_from_public_key(pubkey):
pubkeyhash = sha256(pubkey).digest()
address = int.from_bytes(pubkeyhash[:8], 'little')
return str(address) + 'L'
def get_votes_count(votes):
plus, minus = 0, 0
@ -17,6 +18,7 @@ def get_votes_count(votes):
minus += 1
return plus, minus
def get_vote_tx_text(votes):
plus, minus = get_votes_count(votes)
text = []
@ -26,5 +28,6 @@ def get_vote_tx_text(votes):
text.append(_text_with_plural('Remove', minus))
return text
def _text_with_plural(txt, value):
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.utils import chunks
from trezor.messages import ButtonRequestType
from trezor.ui.text import Text
from trezor.utils import chunks
from .helpers import get_vote_tx_text
@ -14,6 +16,7 @@ async def require_confirm_tx(ctx, to, value):
icon_color=ui.GREEN)
return await require_confirm(ctx, content, ButtonRequestType.SignTx)
async def require_confirm_delegate_registration(ctx, delegate_name):
content = Text('Confirm transaction', ui.ICON_SEND,
'Do you really want to',
@ -22,26 +25,27 @@ async def require_confirm_delegate_registration(ctx, delegate_name):
icon_color=ui.GREEN)
return await require_confirm(ctx, content, ButtonRequestType.SignTx)
async def require_confirm_vote_tx(ctx, votes):
content = Text('Confirm transaction', ui.ICON_SEND,
*get_vote_tx_text(votes),
icon_color=ui.GREEN)
return await require_confirm(ctx, content, ButtonRequestType.SignTx)
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)
async def require_confirm_multisig(ctx, multisignature):
content = Text('Confirm transaction', ui.ICON_SEND,
('Keys group length: %s' % len(multisignature.keys_group)),
('Life time: %s' % multisignature.life_time),
('Min: %s' % multisignature.min),
icon_color=ui.GREEN)
return await require_confirm(ctx, content, ButtonRequestType.SignTx)
async def require_confirm_fee(ctx, value, fee):
content = Text('Confirm transaction', ui.ICON_SEND,
ui.BOLD, format_amount(value),
@ -50,8 +54,10 @@ async def require_confirm_fee(ctx, value, fee):
icon_color=ui.GREEN)
await require_hold_to_confirm(ctx, content, ButtonRequestType.ConfirmOutput)
def format_amount(value):
return '%s LSK' % (int(value) / 100000000)
def split_address(address):
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.LiskTransactionType import *
from trezor.messages import FailureType
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):
from trezor.crypto.hashlib import sha256
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:
await require_confirm_by_type(ctx, transaction)
await _require_confirm_by_type(ctx, transaction)
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)
transaction_bytes = _get_transaction_bytes(transaction)
txbytes = _get_transaction_bytes(transaction)
txhash = HashWriter(sha256)
for field in txbytes:
txhash.extend(field)
digest = txhash.get_digest()
for field in transaction_bytes:
sha.extend(field)
digest = sha.get_digest()
signature = await get_signature(seckey, digest)
signature = ed25519.sign(seckey, digest)
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):
from ..common import seed
from .helpers import LISK_CURVE
address_n = msg.address_n or ()
node = await seed.derive_node(ctx, address_n, LISK_CURVE)
@ -116,13 +43,89 @@ async def _get_keys(ctx, msg):
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
# For this type of transactions, recipientId should be equal transaction creator address.
if transaction.type == CastVotes:
# For CastVotes transactions, recipientId should be equal to transaction
# creator address.
if transaction.type == LiskTransactionType.CastVotes:
transaction.recipient_id = get_address_from_public_key(pubkey)
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')