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:
parent
04c652c120
commit
523e57ea52
@ -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)
|
||||||
|
@ -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)
|
||||||
|
@ -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'))
|
||||||
|
@ -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)
|
||||||
|
@ -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')
|
||||||
|
Loading…
Reference in New Issue
Block a user