1
0
mirror of https://github.com/trezor/trezor-firmware.git synced 2024-11-18 13:38:12 +00:00

nem: first signed transaction

This commit is contained in:
Tomas Susanka 2018-03-19 14:50:10 +01:00 committed by Jan Pochyla
parent fb15e993f1
commit d28a3ca5cf
4 changed files with 80 additions and 87 deletions

View File

@ -1,6 +1,6 @@
from trezor.wire import register, protobuf_workflow from trezor.wire import register, protobuf_workflow
from trezor.utils import unimport from trezor.utils import unimport
from trezor.messages.wire_types import NEMGetAddress from trezor.messages.wire_types import NEMGetAddress, NEMSignTx
@unimport @unimport
@ -9,5 +9,12 @@ def dispatch_NemGetAddress(*args, **kwargs):
return nem_get_address(*args, **kwargs) return nem_get_address(*args, **kwargs)
@unimport
def dispatch_NemSignTx(*args, **kwargs):
from .signing import nem_sign_tx
return nem_sign_tx(*args, **kwargs)
def boot(): def boot():
register(NEMGetAddress, protobuf_workflow, dispatch_NemGetAddress) register(NEMGetAddress, protobuf_workflow, dispatch_NemGetAddress)
register(NEMSignTx, protobuf_workflow, dispatch_NemSignTx)

29
src/apps/nem/layout.py Normal file
View File

@ -0,0 +1,29 @@
from apps.common.confirm import *
from trezor import ui
from trezor.messages import ButtonRequestType
from trezor.ui.text import Text
# todo wording, ui
async def require_confirm_tx(ctx, recipient, value):
content = Text('Confirm sending', ui.ICON_SEND,
ui.BOLD, value,
ui.NORMAL, 'to',
ui.MONO, recipient,
icon_color=ui.GREEN)
await require_hold_to_confirm(ctx, content, ButtonRequestType.SignTx) # we use SignTx, not ConfirmOutput, for compatibility with T1
async def require_confirm_fee(ctx, value, fee):
content = Text('Confirm transaction', ui.ICON_SEND,
ui.BOLD, value,
ui.NORMAL, 'fee:',
ui.BOLD, fee,
icon_color=ui.GREEN)
await require_confirm(ctx, content, ButtonRequestType.ConfirmOutput)
async def require_confirm_action(ctx):
content = Text('Send unencrypted transaction?', ui.ICON_SEND)
await require_confirm(ctx, content, ButtonRequestType.ConfirmOutput)

View File

@ -1,86 +0,0 @@
from .helpers import *
from .writers import *
def nem_transaction_create_transfer(network: int, timestamp: int, signer_public_key: bytes, fee: int, deadline: int,
recipient: str, amount: int, payload: bytearray = None, encrypted: bool = False,
mosaics: int = 0) -> bytearray:
tx = _nem_transaction_write_common(NEM_TRANSACTION_TYPE_TRANSFER,
_nem_get_version(network, mosaics),
timestamp,
signer_public_key,
fee,
deadline)
write_bytes_with_length(tx, bytearray(recipient))
write_uint64(tx, amount)
if payload:
# payload + payload size (u32) + encryption flag (u32)
write_uint32(tx, len(payload) + 2 * 4)
if encrypted:
write_uint32(tx, 0x02)
else:
write_uint32(tx, 0x01)
write_bytes_with_length(tx, payload)
else:
write_uint32(tx, 0)
if mosaics:
write_uint32(tx, mosaics)
return tx
def nem_transaction_create_provision_namespace(network: int, timestamp: int, signer_public_key: bytes, fee: int,
deadline: int, namespace: str, parent: str, rental_sink: str,
rental_fee: int) -> bytearray:
tx = _nem_transaction_write_common(NEM_TRANSACTION_TYPE_PROVISION_NAMESPACE,
_nem_get_version(network),
timestamp,
signer_public_key,
fee,
deadline)
write_bytes_with_length(tx, bytearray(rental_sink))
write_uint64(tx, rental_fee)
write_bytes_with_length(tx, bytearray(namespace))
if parent:
write_bytes_with_length(tx, bytearray(parent))
else:
write_uint32(tx, 0xffffffff)
return tx
def nem_transaction_write_mosaic(w: bytearray, namespace: str, mosaic: str, quantity: int):
identifier_length = 4 + len(namespace) + 4 + len(mosaic)
# indentifier length (u32) + quantity (u64) + identifier size
write_uint32(w, 4 + 8 + identifier_length)
write_uint32(w, identifier_length)
write_bytes_with_length(w, bytearray(namespace))
write_bytes_with_length(w, bytearray(mosaic))
write_uint64(w, quantity)
def _nem_transaction_write_common(tx_type: int, version: int, timestamp: int, signer: bytes, fee: int, deadline: int)\
-> bytearray:
ret = bytearray()
write_uint32(ret, tx_type)
write_uint32(ret, version)
write_uint32(ret, timestamp)
write_bytes_with_length(ret, bytearray(signer))
write_uint64(ret, fee)
write_uint32(ret, deadline)
return ret
def _nem_get_version(network, mosaics=None) -> int:
if mosaics:
return network << 24 | 2
return network << 24 | 1

43
src/apps/nem/signing.py Normal file
View File

@ -0,0 +1,43 @@
from apps.nem.transaction import *
from apps.nem.layout import *
from trezor.messages.NEMSignTx import NEMSignTx
from trezor.messages.NEMSignedTx import NEMSignedTx
async def nem_sign_tx(ctx, msg: NEMSignTx):
from ..common import seed
from trezor.crypto.curve import ed25519
# if len(msg.transfer.public_key):
# todo encrypt
node = await seed.derive_node(ctx, msg.transaction.address_n, NEM_CURVE)
# 0x01 prefix is not part of the actual public key, hence removed
public_key = node.public_key()[1:]
tx = nem_transaction_create_transfer(
msg.transaction.network,
msg.transaction.timestamp,
public_key,
msg.transaction.fee,
msg.transaction.deadline,
msg.transfer.recipient,
msg.transfer.amount,
msg.transfer.payload, # todo might require encryption
msg.transfer.public_key is not None,
len(msg.transfer.mosaics)
)
for mosaic in msg.transfer.mosaics:
nem_transaction_write_mosaic(tx, mosaic.namespace, mosaic.mosaic, mosaic.quantity)
await require_confirm_action(ctx)
await require_confirm_fee(ctx, msg.transfer.amount, msg.transaction.fee)
await require_confirm_tx(ctx, msg.transfer.recipient, msg.transfer.amount)
signature = ed25519.sign(node.private_key(), tx, 'keccak')
resp = NEMSignedTx()
resp.data = tx
resp.signature = signature
return resp