diff --git a/src/apps/common/confirm.py b/src/apps/common/confirm.py index 9ce8d06db0..07d4ae56ca 100644 --- a/src/apps/common/confirm.py +++ b/src/apps/common/confirm.py @@ -19,7 +19,7 @@ async def confirm(session_id, content=None, code=None, *args, **kwargs): if code is None: code = Other - await wire.reply_message(session_id, ButtonRequest(code=code), ButtonAck) + await wire.call(session_id, ButtonRequest(code=code), ButtonAck) return await loop.Wait((signal, dialog)) == CONFIRMED @@ -39,7 +39,7 @@ async def hold_to_confirm(session_id, content=None, code=None, *args, **kwargs): if code is None: code = Other - await wire.reply_message(session_id, ButtonRequest(code=code), ButtonAck) + await wire.call(session_id, ButtonRequest(code=code), ButtonAck) return await loop.Wait((signal, dialog)) == CONFIRMED diff --git a/src/apps/common/request_passphrase.py b/src/apps/common/request_passphrase.py index 6855af622f..8e60f45920 100644 --- a/src/apps/common/request_passphrase.py +++ b/src/apps/common/request_passphrase.py @@ -11,5 +11,5 @@ async def request_passphrase(session_id): 'Please enter passphrase', 'on your computer.') text.render() - ack = await wire.reply_message(session_id, PassphraseRequest(), PassphraseAck) + ack = await wire.call(session_id, PassphraseRequest(), PassphraseAck) return ack.passphrase diff --git a/src/apps/common/request_pin.py b/src/apps/common/request_pin.py index c1285b80a9..130b6b01c1 100644 --- a/src/apps/common/request_pin.py +++ b/src/apps/common/request_pin.py @@ -20,9 +20,9 @@ async def request_pin_on_display(session_id: int, code: int=None) -> str: _, label = _get_code_and_label(code) - await wire.reply_message(session_id, - ButtonRequest(code=ProtectCall), - ButtonAck) + await wire.call(session_id, + ButtonRequest(code=ProtectCall), + ButtonAck) ui.display.clear() matrix = PinMatrix(label) @@ -51,9 +51,9 @@ async def request_pin_on_client(session_id: int, code: int=None) -> str: matrix = PinMatrix(label) matrix.render() - ack = await wire.reply_message(session_id, - PinMatrixRequest(code=code), - PinMatrixAck, Cancel) + ack = await wire.call(session_id, + PinMatrixRequest(code=code), + PinMatrixAck, Cancel) digits = matrix.digits matrix = None diff --git a/src/apps/debug/__init__.py b/src/apps/debug/__init__.py index d46ce1d86c..14fca7d5b1 100644 --- a/src/apps/debug/__init__.py +++ b/src/apps/debug/__init__.py @@ -1,16 +1,16 @@ -from trezor.wire import register_type, protobuf_handler +from trezor.wire import register, protobuf_workflow from trezor.messages.wire_types import \ DebugLinkDecision, DebugLinkGetState, DebugLinkStop, \ DebugLinkMemoryRead, DebugLinkMemoryWrite, DebugLinkFlashErase -async def dispatch_DebugLinkDecision(msg, session_id): +async def dispatch_DebugLinkDecision(session_id, msg): from trezor.ui.confirm import CONFIRMED, CANCELLED from ..common.confirm import signal signal.send(CONFIRMED if msg.yes_no else CANCELLED) -async def dispatch_DebugLinkGetState(msg, session_id): +async def dispatch_DebugLinkGetState(session_id, msg): from trezor.messages.DebugLinkState import DebugLinkState from ..common import storage, request_pin @@ -35,11 +35,11 @@ async def dispatch_DebugLinkGetState(msg, session_id): return m -async def dispatch_DebugLinkStop(msg, session_id): +async def dispatch_DebugLinkStop(session_id, msg): pass -async def dispatch_DebugLinkMemoryRead(msg, session_id): +async def dispatch_DebugLinkMemoryRead(session_id, msg): from trezor.messages.DebugLinkMemory import DebugLinkMemory from trezor.debug import memaccess @@ -50,26 +50,20 @@ async def dispatch_DebugLinkMemoryRead(msg, session_id): return m -async def dispatch_DebugLinkMemoryWrite(msg, session_id): +async def dispatch_DebugLinkMemoryWrite(session_id, msg): # TODO: memcpy((void *)msg.address, msg.memory, len(msg.memory)) pass -async def dispatch_DebugLinkFlashErase(msg, session_id): +async def dispatch_DebugLinkFlashErase(session_id, msg): # TODO: erase(msg.sector) pass def boot(): - register_type( - DebugLinkDecision, protobuf_handler, dispatch_DebugLinkDecision) - register_type( - DebugLinkGetState, protobuf_handler, dispatch_DebugLinkGetState) - register_type( - DebugLinkStop, protobuf_handler, dispatch_DebugLinkStop) - register_type( - DebugLinkMemoryRead, protobuf_handler, dispatch_DebugLinkMemoryRead) - register_type( - DebugLinkMemoryWrite, protobuf_handler, dispatch_DebugLinkMemoryWrite) - register_type( - DebugLinkFlashErase, protobuf_handler, dispatch_DebugLinkFlashErase) + register(DebugLinkDecision, protobuf_workflow, dispatch_DebugLinkDecision) + register(DebugLinkGetState, protobuf_workflow, dispatch_DebugLinkGetState) + register(DebugLinkStop, protobuf_workflow, dispatch_DebugLinkStop) + register(DebugLinkMemoryRead, protobuf_workflow, dispatch_DebugLinkMemoryRead) + register(DebugLinkMemoryWrite, protobuf_workflow, dispatch_DebugLinkMemoryWrite) + register(DebugLinkFlashErase, protobuf_workflow, dispatch_DebugLinkFlashErase) diff --git a/src/apps/ethereum/__init__.py b/src/apps/ethereum/__init__.py index 5570a61d8e..972d66d68d 100644 --- a/src/apps/ethereum/__init__.py +++ b/src/apps/ethereum/__init__.py @@ -1,4 +1,4 @@ -from trezor.wire import register_type, protobuf_handler +from trezor.wire import register, protobuf_workflow from trezor.utils import unimport from trezor.messages.wire_types import \ EthereumGetAddress @@ -6,8 +6,8 @@ from trezor.messages.wire_types import \ @unimport def dispatch_EthereumGetAddress(*args, **kwargs): - from .layout_ethereum_get_address import layout_ethereum_get_address + from .ethereum_get_address import layout_ethereum_get_address return layout_ethereum_get_address(*args, **kwargs) def boot(): - register_type(EthereumGetAddress, protobuf_handler, dispatch_EthereumGetAddress) + register(EthereumGetAddress, protobuf_workflow, dispatch_EthereumGetAddress) diff --git a/src/apps/ethereum/layout_ethereum_get_address.py b/src/apps/ethereum/ethereum_get_address.py similarity index 95% rename from src/apps/ethereum/layout_ethereum_get_address.py rename to src/apps/ethereum/ethereum_get_address.py index 9f4d774923..c0e0f13258 100644 --- a/src/apps/ethereum/layout_ethereum_get_address.py +++ b/src/apps/ethereum/ethereum_get_address.py @@ -3,7 +3,7 @@ from trezor.utils import unimport @unimport -async def layout_ethereum_get_address(msg, session_id): +async def layout_ethereum_get_address(session_id, msg): from trezor.messages.EthereumAddress import EthereumAddress from trezor.crypto.curve import secp256k1 from trezor.crypto.hashlib import sha3_256 diff --git a/src/apps/fido_u2f/layout_u2f.py b/src/apps/fido_u2f/u2f.py similarity index 100% rename from src/apps/fido_u2f/layout_u2f.py rename to src/apps/fido_u2f/u2f.py diff --git a/src/apps/homescreen/__init__.py b/src/apps/homescreen/__init__.py index e03366e828..344a895d88 100644 --- a/src/apps/homescreen/__init__.py +++ b/src/apps/homescreen/__init__.py @@ -1,9 +1,9 @@ -from trezor.wire import register_type, protobuf_handler, write_message +from trezor.wire import register, protobuf_workflow from trezor.utils import unimport from trezor.messages.wire_types import Initialize, GetFeatures, Ping -async def respond_Features(msg, session_id): +async def respond_Features(session_id, msg): from ..common import storage, coins from trezor.messages.Features import Features @@ -25,7 +25,7 @@ async def respond_Features(msg, session_id): return f -async def respond_Pong(msg, session_id): +async def respond_Pong(session_id, msg): from trezor.messages.Success import Success s = Success() s.message = msg.message @@ -37,6 +37,6 @@ async def respond_Pong(msg, session_id): def boot(): - register_type(Initialize, protobuf_handler, respond_Features) - register_type(GetFeatures, protobuf_handler, respond_Features) - register_type(Ping, protobuf_handler, respond_Pong) + register(Initialize, protobuf_workflow, respond_Features) + register(GetFeatures, protobuf_workflow, respond_Features) + register(Ping, protobuf_workflow, respond_Pong) diff --git a/src/apps/homescreen/layout_homescreen.py b/src/apps/homescreen/homescreen.py similarity index 100% rename from src/apps/homescreen/layout_homescreen.py rename to src/apps/homescreen/homescreen.py diff --git a/src/apps/management/__init__.py b/src/apps/management/__init__.py index 5718f9cafa..3bc27cd0fb 100644 --- a/src/apps/management/__init__.py +++ b/src/apps/management/__init__.py @@ -1,4 +1,4 @@ -from trezor.wire import register_type, protobuf_handler +from trezor.wire import register, protobuf_workflow from trezor.utils import unimport from trezor.messages.wire_types import \ LoadDevice, ResetDevice, WipeDevice, RecoveryDevice, ApplySettings @@ -6,37 +6,37 @@ from trezor.messages.wire_types import \ @unimport def dispatch_LoadDevice(*args, **kwargs): - from .layout_load_device import layout_load_device + from .load_device import layout_load_device return layout_load_device(*args, **kwargs) @unimport def dispatch_ResetDevice(*args, **kwargs): - from .layout_reset_device import layout_reset_device + from .reset_device import layout_reset_device return layout_reset_device(*args, **kwargs) @unimport def dispatch_WipeDevice(*args, **kwargs): - from .layout_wipe_device import layout_wipe_device + from .wipe_device import layout_wipe_device return layout_wipe_device(*args, **kwargs) @unimport def dispatch_RecoveryDevice(*args, **kwargs): - from .layout_recovery_device import layout_recovery_device + from .recovery_device import layout_recovery_device return layout_recovery_device(*args, **kwargs) @unimport def dispatch_ApplySettings(*args, **kwargs): - from .layout_apply_settings import layout_apply_settings + from .apply_settings import layout_apply_settings return layout_apply_settings(*args, **kwargs) def boot(): - register_type(LoadDevice, protobuf_handler, dispatch_LoadDevice) - register_type(ResetDevice, protobuf_handler, dispatch_ResetDevice) - register_type(WipeDevice, protobuf_handler, dispatch_WipeDevice) - register_type(RecoveryDevice, protobuf_handler, dispatch_RecoveryDevice) - register_type(ApplySettings, protobuf_handler, dispatch_ApplySettings) + register(LoadDevice, protobuf_workflow, dispatch_LoadDevice) + register(ResetDevice, protobuf_workflow, dispatch_ResetDevice) + register(WipeDevice, protobuf_workflow, dispatch_WipeDevice) + register(RecoveryDevice, protobuf_workflow, dispatch_RecoveryDevice) + register(ApplySettings, protobuf_workflow, dispatch_ApplySettings) diff --git a/src/apps/management/layout_apply_settings.py b/src/apps/management/apply_settings.py similarity index 97% rename from src/apps/management/layout_apply_settings.py rename to src/apps/management/apply_settings.py index 7f7cb73c3e..7dc8464281 100644 --- a/src/apps/management/layout_apply_settings.py +++ b/src/apps/management/apply_settings.py @@ -3,7 +3,7 @@ from trezor.utils import unimport @unimport -async def layout_apply_settings(msg, session_id): +async def layout_apply_settings(session_id, msg): from trezor.messages.Success import Success from trezor.messages.FailureType import Other from trezor.ui.text import Text diff --git a/src/apps/management/layout_load_device.py b/src/apps/management/load_device.py similarity index 96% rename from src/apps/management/layout_load_device.py rename to src/apps/management/load_device.py index 015a324580..f8e802089d 100644 --- a/src/apps/management/layout_load_device.py +++ b/src/apps/management/load_device.py @@ -3,7 +3,7 @@ from trezor.utils import unimport @unimport -async def layout_load_device(msg, session_id): +async def layout_load_device(session_id, msg): from trezor.crypto import bip39 from trezor.messages.Success import Success from trezor.messages.FailureType import UnexpectedMessage, Other diff --git a/src/apps/management/layout_recovery_device.py b/src/apps/management/recovery_device.py similarity index 100% rename from src/apps/management/layout_recovery_device.py rename to src/apps/management/recovery_device.py diff --git a/src/apps/management/layout_reset_device.py b/src/apps/management/reset_device.py similarity index 92% rename from src/apps/management/layout_reset_device.py rename to src/apps/management/reset_device.py index 86d3e8aea9..3467e6cdd4 100644 --- a/src/apps/management/layout_reset_device.py +++ b/src/apps/management/reset_device.py @@ -4,7 +4,7 @@ from trezor.utils import unimport, chunks @unimport -async def layout_reset_device(msg, session_id): +async def layout_reset_device(session_id, msg): from trezor.messages.Success import Success from trezor.messages.FailureType import UnexpectedMessage from ..common.request_pin import request_pin_twice @@ -14,7 +14,7 @@ async def layout_reset_device(msg, session_id): raise wire.FailureError(UnexpectedMessage, 'Already initialized') mnemonic = await generate_mnemonic( - msg.strength, msg.display_random, session_id) + session_id, msg.strength, msg.display_random) await show_mnemonic(mnemonic) @@ -33,7 +33,7 @@ async def layout_reset_device(msg, session_id): @unimport -async def generate_mnemonic(strength, display_random, session_id): +async def generate_mnemonic(session_id, strength, display_random): from trezor.crypto import hashlib, random, bip39 from trezor.messages.EntropyRequest import EntropyRequest from trezor.messages.FailureType import Other @@ -46,7 +46,7 @@ async def generate_mnemonic(strength, display_random, session_id): # if display_random: # raise wire.FailureError(Other, 'Entropy display not implemented') - ack = await wire.reply_message(session_id, EntropyRequest(), EntropyAck) + ack = await wire.call(session_id, EntropyRequest(), EntropyAck) if len(ack.entropy) != 32: raise wire.FailureError(Other, 'Invalid entropy (has to be 32 bytes)') diff --git a/src/apps/management/layout_wipe_device.py b/src/apps/management/wipe_device.py similarity index 91% rename from src/apps/management/layout_wipe_device.py rename to src/apps/management/wipe_device.py index 75f7e4abd6..98adca29a7 100644 --- a/src/apps/management/layout_wipe_device.py +++ b/src/apps/management/wipe_device.py @@ -3,7 +3,7 @@ from trezor.utils import unimport @unimport -async def layout_wipe_device(_, session_id): +async def layout_wipe_device(session_id, msg): from trezor.messages.Success import Success from trezor.ui.text import Text from ..common.confirm import hold_to_confirm diff --git a/src/apps/wallet/__init__.py b/src/apps/wallet/__init__.py index 9cdacec8e8..6a25612556 100644 --- a/src/apps/wallet/__init__.py +++ b/src/apps/wallet/__init__.py @@ -1,4 +1,4 @@ -from trezor.wire import register_type, protobuf_handler +from trezor.wire import register, protobuf_workflow from trezor.utils import unimport from trezor.messages.wire_types import \ GetPublicKey, GetAddress, SignTx, EstimateTxSize, \ @@ -9,26 +9,26 @@ from trezor.messages.wire_types import \ @unimport def dispatch_GetPublicKey(*args, **kwargs): - from .layout_get_public_key import layout_get_public_key + from .get_public_key import layout_get_public_key return layout_get_public_key(*args, **kwargs) @unimport def dispatch_GetAddress(*args, **kwargs): - from .layout_get_address import layout_get_address + from .get_address import layout_get_address return layout_get_address(*args, **kwargs) @unimport def dispatch_SignTx(*args, **kwargs): - from .layout_sign_tx import layout_sign_tx - return layout_sign_tx(*args, **kwargs) + from .sign_tx.workflow import sign_tx + return sign_tx(*args, **kwargs) @unimport -async def dispatch_EstimateTxSize(msg, session_id): +async def dispatch_EstimateTxSize(session_id, msg): from trezor.messages.TxSize import TxSize - from ..common.signtx import estimate_tx_size + from .sign_tx.signing import estimate_tx_size m = TxSize() m.tx_size = estimate_tx_size(msg.inputs_count, msg.outputs_count) return m @@ -36,34 +36,34 @@ async def dispatch_EstimateTxSize(msg, session_id): @unimport def dispatch_SignMessage(*args, **kwargs): - from .layout_sign_message import layout_sign_message + from .sign_message import layout_sign_message return layout_sign_message(*args, **kwargs) @unimport def dispatch_VerifyMessage(*args, **kwargs): - from .layout_verify_message import layout_verify_message + from .verify_message import layout_verify_message return layout_verify_message(*args, **kwargs) @unimport def dispatch_SignIdentity(*args, **kwargs): - from .layout_sign_identity import layout_sign_identity + from .sign_identity import layout_sign_identity return layout_sign_identity(*args, **kwargs) @unimport def dispatch_CipherKeyValue(*args, **kwargs): - from .layout_cipherkeyvalue import layout_cipherkeyvalue + from .cipherkeyvalue import layout_cipherkeyvalue return layout_cipherkeyvalue(*args, **kwargs) def boot(): - register_type(GetPublicKey, protobuf_handler, dispatch_GetPublicKey) - register_type(GetAddress, protobuf_handler, dispatch_GetAddress) - register_type(SignTx, protobuf_handler, dispatch_SignTx) - register_type(EstimateTxSize, protobuf_handler, dispatch_EstimateTxSize) - register_type(SignMessage, protobuf_handler, dispatch_SignMessage) - register_type(VerifyMessage, protobuf_handler, dispatch_VerifyMessage) - register_type(SignIdentity, protobuf_handler, dispatch_SignIdentity) - register_type(CipherKeyValue, protobuf_handler, dispatch_CipherKeyValue) + register(GetPublicKey, protobuf_workflow, dispatch_GetPublicKey) + register(GetAddress, protobuf_workflow, dispatch_GetAddress) + register(SignTx, protobuf_workflow, dispatch_SignTx) + register(EstimateTxSize, protobuf_workflow, dispatch_EstimateTxSize) + register(SignMessage, protobuf_workflow, dispatch_SignMessage) + register(VerifyMessage, protobuf_workflow, dispatch_VerifyMessage) + register(SignIdentity, protobuf_workflow, dispatch_SignIdentity) + register(CipherKeyValue, protobuf_workflow, dispatch_CipherKeyValue) diff --git a/src/apps/wallet/layout_cipherkeyvalue.py b/src/apps/wallet/cipher_key_value.py similarity index 86% rename from src/apps/wallet/layout_cipherkeyvalue.py rename to src/apps/wallet/cipher_key_value.py index 771fd33de8..d5b9acfa3f 100644 --- a/src/apps/wallet/layout_cipherkeyvalue.py +++ b/src/apps/wallet/cipher_key_value.py @@ -1,11 +1,11 @@ -from trezor import wire, ui +from trezor import ui from trezor.utils import unimport @unimport -async def layout_cipherkeyvalue(msg, session_id): +async def layout_cipher_key_value(session_id, msg): from trezor.messages.CipheredKeyValue import CipheredKeyValue - from ..common.seed import get_node + from ..common import seed from trezor.crypto.hashlib import sha512 from trezor.crypto import hmac from trezor.crypto.aes import AES_CBC_Encrypt, AES_CBC_Decrypt @@ -18,7 +18,7 @@ async def layout_cipherkeyvalue(msg, session_id): ui.BOLD, ui.LIGHT_GREEN, ui.BLACK) ui.display.text(10, 60, msg.key, ui.MONO, ui.WHITE, ui.BLACK) - node = await get_node(session_id, msg.address_n) + node = await seed.get_node(session_id, msg.address_n) seckey = node.private_key() data = msg.key diff --git a/src/apps/wallet/layout_get_address.py b/src/apps/wallet/get_address.py similarity index 88% rename from src/apps/wallet/layout_get_address.py rename to src/apps/wallet/get_address.py index 73301be054..c06a2108fd 100644 --- a/src/apps/wallet/layout_get_address.py +++ b/src/apps/wallet/get_address.py @@ -3,18 +3,18 @@ from trezor.utils import unimport @unimport -async def layout_get_address(msg, session_id): +async def layout_get_address(session_id, msg): from trezor.messages.Address import Address from trezor.messages.FailureType import Other - from ..common.seed import get_node from ..common import coins + from ..common import seed if msg.multisig: raise wire.FailureError(Other, 'GetAddress.multisig is unsupported') address_n = msg.address_n or () coin_name = msg.coin_name or 'Bitcoin' - node = await get_node(session_id, address_n) + node = await seed.get_node(session_id, address_n) coin = coins.by_name(coin_name) address = node.address(coin.address_type) diff --git a/src/apps/wallet/layout_get_public_key.py b/src/apps/wallet/get_public_key.py similarity index 87% rename from src/apps/wallet/layout_get_public_key.py rename to src/apps/wallet/get_public_key.py index ce1062f0f8..2de9f66d5b 100644 --- a/src/apps/wallet/layout_get_public_key.py +++ b/src/apps/wallet/get_public_key.py @@ -1,11 +1,11 @@ from trezor.utils import unimport -from ..common import seed @unimport -async def layout_get_public_key(msg, session_id): +async def layout_get_public_key(session_id, msg): from trezor.messages.HDNodeType import HDNodeType from trezor.messages.PublicKey import PublicKey + from ..common import seed address_n = msg.address_n or () node = await seed.get_node(session_id, address_n) diff --git a/src/apps/wallet/layout_sign_tx.py b/src/apps/wallet/layout_sign_tx.py deleted file mode 100644 index a5556274e5..0000000000 --- a/src/apps/wallet/layout_sign_tx.py +++ /dev/null @@ -1,79 +0,0 @@ -from trezor.utils import unimport -from trezor import wire - - -def format_amount(amount, coin): - return '%s %s' % (amount / 1e8, coin.coin_shortcut) - - -def split_address(address): - from trezor.utils import chunks - return chunks(address, 17) - - -async def confirm_output(session_id, output, coin): - from trezor import ui - from trezor.ui.text import Text - from trezor.messages.ButtonRequestType import ConfirmOutput - from ..common.confirm import confirm - - content = Text('Confirm output', ui.ICON_RESET, - ui.BOLD, format_amount(output.amount, coin), - ui.NORMAL, 'to', - ui.MONO, *split_address(output.address)) - return await confirm(session_id, content, ConfirmOutput) - - -async def confirm_total(session_id, spending, fee, coin): - from trezor import ui - from trezor.ui.text import Text - from trezor.messages.ButtonRequestType import SignTx - from ..common.confirm import hold_to_confirm - - content = Text('Confirm transaction', ui.ICON_RESET, - 'Sending: %s' % format_amount(spending, coin), - 'Fee: %s' % format_amount(fee, coin)) - return await hold_to_confirm(session_id, content, SignTx) - - -async def confirm_feeoverthreshold(session_id, fee, coin): - from trezor import ui - from trezor.ui.text import Text - from trezor.messages.ButtonRequestType import FeeOverThreshold - from ..common.confirm import confirm - - content = Text('Confirm high fee:', ui.ICON_RESET, - ui.BOLD, format_amount(fee, coin)) - return await confirm(session_id, content, FeeOverThreshold) - - -@unimport -async def layout_sign_tx(msg, session_id): - from ..common.seed import get_root_node - from ..common import signtx - - from trezor.messages.RequestType import TXFINISHED - from trezor.messages.wire_types import TxAck - - root = await get_root_node(session_id) - - signer = signtx.sign_tx(msg, root) - res = None - while True: - try: - req = signer.send(res) - except signtx.SigningError as e: - raise wire.FailureError(*e.args) - if req.__qualname__ == 'TxRequest': - if req.request_type == TXFINISHED: - break - res = await wire.reply_message(session_id, req, TxAck) - elif req.__qualname__ == 'UiConfirmOutput': - res = await confirm_output(session_id, req.output, req.coin) - elif req.__qualname__ == 'UiConfirmTotal': - res = await confirm_total(session_id, req.spending, req.fee, req.coin) - elif req.__qualname__ == 'UiConfirmFeeOverThreshold': - res = await confirm_feeoverthreshold(session_id, req.fee, req.coin) - else: - raise TypeError('Invalid signing instruction') - return req diff --git a/src/apps/wallet/layout_sign_identity.py b/src/apps/wallet/sign_identity.py similarity index 92% rename from src/apps/wallet/layout_sign_identity.py rename to src/apps/wallet/sign_identity.py index a46a48d62b..c1422472c3 100644 --- a/src/apps/wallet/layout_sign_identity.py +++ b/src/apps/wallet/sign_identity.py @@ -2,13 +2,13 @@ from trezor import ui from trezor.utils import unimport @unimport -async def layout_sign_identity(msg, session_id): +async def layout_sign_identity(session_id, msg): from trezor.messages.SignedIdentity import SignedIdentity from trezor.crypto.curve import secp256k1 from trezor.crypto.hashlib import sha256 from ustruct import pack, unpack - from ..common.seed import get_node from ..common import coins + from ..common import seed from ..common.signverify import message_digest identity = '' @@ -38,7 +38,7 @@ async def layout_sign_identity(msg, session_id): ui.display.text(10, 60, msg.challenge_visual, ui.MONO, ui.WHITE, ui.BLACK) ui.display.text(10, 80, identity, ui.MONO, ui.WHITE, ui.BLACK) - node = await get_node(session_id, address_n) + node = await seed.get_node(session_id, address_n) coin = coins.by_name('Bitcoin') address = node.address(coin.address_type) # hardcoded Bitcoin address type diff --git a/src/apps/wallet/layout_sign_message.py b/src/apps/wallet/sign_message.py similarity index 84% rename from src/apps/wallet/layout_sign_message.py rename to src/apps/wallet/sign_message.py index 3ac3426cc3..c725424c9d 100644 --- a/src/apps/wallet/layout_sign_message.py +++ b/src/apps/wallet/sign_message.py @@ -3,11 +3,11 @@ from trezor.utils import unimport @unimport -async def layout_sign_message(msg, session_id): +async def layout_sign_message(session_id, msg): from trezor.messages.MessageSignature import MessageSignature from trezor.crypto.curve import secp256k1 - from ..common.seed import get_node from ..common import coins + from ..common import seed from ..common.signverify import message_digest ui.display.clear() @@ -18,7 +18,7 @@ async def layout_sign_message(msg, session_id): coin_name = msg.coin_name or 'Bitcoin' coin = coins.by_name(coin_name) - node = await get_node(session_id, msg.address_n) + node = await seed.get_node(session_id, msg.address_n) seckey = node.private_key() address = node.address(coin.address_type) diff --git a/src/apps/wallet/sign_tx/__init__.py b/src/apps/wallet/sign_tx/__init__.py new file mode 100644 index 0000000000..e69de29bb2 diff --git a/src/apps/wallet/sign_tx/layout.py b/src/apps/wallet/sign_tx/layout.py new file mode 100644 index 0000000000..4d36bb34d0 --- /dev/null +++ b/src/apps/wallet/sign_tx/layout.py @@ -0,0 +1,35 @@ +from trezor import ui +from trezor.utils import chunks +from trezor.ui.text import Text +from trezor.messages import ButtonRequestType +from apps.common.confirm import confirm +from apps.common.confirm import hold_to_confirm + + +def format_amount(amount, coin): + return '%s %s' % (amount / 1e8, coin.coin_shortcut) + + +def split_address(address): + return chunks(address, 17) + + +async def confirm_output(session_id, output, coin): + content = Text('Confirm output', ui.ICON_RESET, + ui.BOLD, format_amount(output.amount, coin), + ui.NORMAL, 'to', + ui.MONO, *split_address(output.address)) + return await confirm(session_id, content, ButtonRequestType.ConfirmOutput) + + +async def confirm_total(session_id, spending, fee, coin): + content = Text('Confirm transaction', ui.ICON_RESET, + 'Sending: %s' % format_amount(spending, coin), + 'Fee: %s' % format_amount(fee, coin)) + return await hold_to_confirm(session_id, content, ButtonRequestType.SignTx) + + +async def confirm_feeoverthreshold(session_id, fee, coin): + content = Text('Confirm high fee:', ui.ICON_RESET, + ui.BOLD, format_amount(fee, coin)) + return await confirm(session_id, content, ButtonRequestType.FeeOverThreshold) diff --git a/src/apps/common/signtx.py b/src/apps/wallet/sign_tx/signing.py similarity index 92% rename from src/apps/common/signtx.py rename to src/apps/wallet/sign_tx/signing.py index 6739cec03e..cdd13bc9db 100644 --- a/src/apps/common/signtx.py +++ b/src/apps/wallet/sign_tx/signing.py @@ -1,9 +1,7 @@ from trezor.crypto.hashlib import sha256, ripemd160 from trezor.crypto.curve import secp256k1 from trezor.crypto import base58, der - -from . import address_type -from . import coins +from trezor.utils import ensure from trezor.messages.CoinType import CoinType from trezor.messages.SignTx import SignTx @@ -17,6 +15,9 @@ from trezor.messages.TxRequestSerializedType import TxRequestSerializedType from trezor.messages.TxRequestDetailsType import TxRequestDetailsType from trezor.messages import OutputScriptType, InputScriptType, FailureType +from apps.common import address_type +from apps.common import coins + # Machine instructions # === @@ -412,11 +413,11 @@ def node_derive(root, address_n: list): def ecdsa_hash_pubkey(pubkey: bytes) -> bytes: if pubkey[0] == 0x04: - assert len(pubkey) == 65 # uncompressed format + ensure(len(pubkey) == 65) # uncompressed format elif pubkey[0] == 0x00: - assert len(pubkey) == 1 # point at infinity + ensure(len(pubkey) == 1) # point at infinity else: - assert len(pubkey) == 33 # compresssed format + ensure(len(pubkey) == 33) # compresssed format h = sha256(pubkey).digest() h = ripemd160(h).digest() return h @@ -473,9 +474,11 @@ def script_spendaddress_new(pubkey: bytes, signature: bytes) -> bytearray: # TX Serialization # === +_DEFAULT_SEQUENCE = 4294967295 + def write_tx_input(w, i: TxInputType): - i_sequence = i.sequence if i.sequence is not None else 4294967295 + i_sequence = i.sequence if i.sequence is not None else _DEFAULT_SEQUENCE write_bytes_rev(w, i.prev_hash) write_uint32(w, i.prev_index) write_varint(w, len(i.script_sig)) @@ -484,7 +487,7 @@ def write_tx_input(w, i: TxInputType): def write_tx_input_check(w, i: TxInputType): - i_sequence = i.sequence if i.sequence is not None else 4294967295 + i_sequence = i.sequence if i.sequence is not None else _DEFAULT_SEQUENCE write_bytes(w, i.prev_hash) write_uint32(w, i.prev_index) write_uint32(w, len(i.address_n)) @@ -500,22 +503,21 @@ def write_tx_output(w, o: TxOutputBinType): def write_op_push(w, n: int): - wb = w.append if n < 0x4C: - wb(n & 0xFF) + w.append(n & 0xFF) elif n < 0xFF: - wb(0x4C) - wb(n & 0xFF) + w.append(0x4C) + w.append(n & 0xFF) elif n < 0xFFFF: - wb(0x4D) - wb(n & 0xFF) - wb((n >> 8) & 0xFF) + w.append(0x4D) + w.append(n & 0xFF) + w.append((n >> 8) & 0xFF) else: - wb(0x4E) - wb(n & 0xFF) - wb((n >> 8) & 0xFF) - wb((n >> 16) & 0xFF) - wb((n >> 24) & 0xFF) + w.append(0x4E) + w.append(n & 0xFF) + w.append((n >> 8) & 0xFF) + w.append((n >> 16) & 0xFF) + w.append((n >> 24) & 0xFF) # Buffer IO & Serialization @@ -523,39 +525,36 @@ def write_op_push(w, n: int): def write_varint(w, n: int): - wb = w.append if n < 253: - wb(n & 0xFF) + w.append(n & 0xFF) elif n < 65536: - wb(253) - wb(n & 0xFF) - wb((n >> 8) & 0xFF) + w.append(253) + w.append(n & 0xFF) + w.append((n >> 8) & 0xFF) else: - wb(254) - wb(n & 0xFF) - wb((n >> 8) & 0xFF) - wb((n >> 16) & 0xFF) - wb((n >> 24) & 0xFF) + w.append(254) + w.append(n & 0xFF) + w.append((n >> 8) & 0xFF) + w.append((n >> 16) & 0xFF) + w.append((n >> 24) & 0xFF) def write_uint32(w, n: int): - wb = w.append - wb(n & 0xFF) - wb((n >> 8) & 0xFF) - wb((n >> 16) & 0xFF) - wb((n >> 24) & 0xFF) + w.append(n & 0xFF) + w.append((n >> 8) & 0xFF) + w.append((n >> 16) & 0xFF) + w.append((n >> 24) & 0xFF) def write_uint64(w, n: int): - wb = w.append - wb(n & 0xFF) - wb((n >> 8) & 0xFF) - wb((n >> 16) & 0xFF) - wb((n >> 24) & 0xFF) - wb((n >> 32) & 0xFF) - wb((n >> 40) & 0xFF) - wb((n >> 48) & 0xFF) - wb((n >> 56) & 0xFF) + w.append(n & 0xFF) + w.append((n >> 8) & 0xFF) + w.append((n >> 16) & 0xFF) + w.append((n >> 24) & 0xFF) + w.append((n >> 32) & 0xFF) + w.append((n >> 40) & 0xFF) + w.append((n >> 48) & 0xFF) + w.append((n >> 56) & 0xFF) def write_bytes(w, buf: bytearray): diff --git a/src/apps/wallet/sign_tx/workflow.py b/src/apps/wallet/sign_tx/workflow.py new file mode 100644 index 0000000000..4951c6d2a1 --- /dev/null +++ b/src/apps/wallet/sign_tx/workflow.py @@ -0,0 +1,35 @@ +from trezor.utils import unimport +from trezor import wire + + +@unimport +async def sign_tx(session_id, msg): + from trezor.messages.RequestType import TXFINISHED + from trezor.messages.wire_types import TxAck + + from apps.common import seed + from . import signing + from . import layout + + root = await seed.get_root_node(session_id) + + signer = signing.sign_tx(msg, root) + res = None + while True: + try: + req = signer.send(res) + except signing.SigningError as e: + raise wire.FailureError(*e.args) + if req.__qualname__ == 'TxRequest': + if req.request_type == TXFINISHED: + break + res = await wire.call(session_id, req, TxAck) + elif req.__qualname__ == 'UiConfirmOutput': + res = await layout.confirm_output(session_id, req.output, req.coin) + elif req.__qualname__ == 'UiConfirmTotal': + res = await layout.confirm_total(session_id, req.spending, req.fee, req.coin) + elif req.__qualname__ == 'UiConfirmFeeOverThreshold': + res = await layout.confirm_feeoverthreshold(session_id, req.fee, req.coin) + else: + raise TypeError('Invalid signing instruction') + return req diff --git a/src/apps/wallet/layout_verify_message.py b/src/apps/wallet/verify_message.py similarity index 95% rename from src/apps/wallet/layout_verify_message.py rename to src/apps/wallet/verify_message.py index 629c9ab9aa..f6cc905cff 100644 --- a/src/apps/wallet/layout_verify_message.py +++ b/src/apps/wallet/verify_message.py @@ -3,7 +3,7 @@ from trezor.utils import unimport @unimport -async def layout_verify_message(msg, session_id): +async def layout_verify_message(session_id, msg): from trezor.messages.Success import Success from trezor.crypto.curve import secp256k1 from trezor.crypto.hashlib import ripemd160, sha256 diff --git a/tests/test_apps.common.signtx.py b/tests/test_apps.common.signtx.py deleted file mode 100644 index 71b6d419fa..0000000000 --- a/tests/test_apps.common.signtx.py +++ /dev/null @@ -1,111 +0,0 @@ -from common import * - -from trezor.utils import chunks -from trezor.crypto import bip32, bip39 -from trezor.messages.SignTx import SignTx -from trezor.messages.TxInputType import TxInputType -from trezor.messages.TxOutputType import TxOutputType -from trezor.messages.TxOutputBinType import TxOutputBinType -from trezor.messages.TxRequest import TxRequest -from trezor.messages.TxAck import TxAck -from trezor.messages.TransactionType import TransactionType -from trezor.messages.RequestType import TXINPUT, TXOUTPUT, TXMETA, TXFINISHED -from trezor.messages.TxRequestDetailsType import TxRequestDetailsType -from trezor.messages.TxRequestSerializedType import TxRequestSerializedType -from trezor.messages import OutputScriptType - -from apps.common import coins -from apps.common import signtx - -class TestSignTx(unittest.TestCase): - # pylint: disable=C0301 - - def test_one_one_fee(self): - # tx: d5f65ee80147b4bcc70b75e4bbf2d7382021b871bd8867ef8fa525ef50864882 - # input 0: 0.0039 BTC - - coin_bitcoin = coins.by_name('Bitcoin') - - ptx1 = TransactionType(version=1, lock_time=0, inputs_cnt=2, outputs_cnt=1) - pinp1 = TxInputType(script_sig=unhexlify('483045022072ba61305fe7cb542d142b8f3299a7b10f9ea61f6ffaab5dca8142601869d53c0221009a8027ed79eb3b9bc13577ac2853269323434558528c6b6a7e542be46e7e9a820141047a2d177c0f3626fc68c53610b0270fa6156181f46586c679ba6a88b34c6f4874686390b4d92e5769fbb89c8050b984f4ec0b257a0e5c4ff8bd3b035a51709503'), - prev_hash=unhexlify('c16a03f1cf8f99f6b5297ab614586cacec784c2d259af245909dedb0e39eddcf'), - prev_index=1, - script_type=None, - sequence=None) - pinp2 = TxInputType(script_sig=unhexlify('48304502200fd63adc8f6cb34359dc6cca9e5458d7ea50376cbd0a74514880735e6d1b8a4c0221008b6ead7fe5fbdab7319d6dfede3a0bc8e2a7c5b5a9301636d1de4aa31a3ee9b101410486ad608470d796236b003635718dfc07c0cac0cfc3bfc3079e4f491b0426f0676e6643a39198e8e7bdaffb94f4b49ea21baa107ec2e237368872836073668214'), - prev_hash=unhexlify('1ae39a2f8d59670c8fc61179148a8e61e039d0d9e8ab08610cb69b4a19453eaf'), - prev_index=1, - script_type=None, - sequence=None) - pout1 = TxOutputBinType(script_pubkey=unhexlify('76a91424a56db43cf6f2b02e838ea493f95d8d6047423188ac'), - amount=390000, - address_n=None) - - inp1 = TxInputType(address_n=[0], # 14LmW5k4ssUrtbAB4255zdqv3b4w1TuX9e - # amount=390000, - prev_hash=unhexlify('d5f65ee80147b4bcc70b75e4bbf2d7382021b871bd8867ef8fa525ef50864882'), - prev_index=0, - script_type=None, - sequence=None) - out1 = TxOutputType(address='1MJ2tj2ThBE62zXbBYA5ZaN3fdve5CPAz1', - amount=390000 - 10000, - script_type=OutputScriptType.PAYTOADDRESS, - address_n=None) - tx = SignTx(coin_name=None, version=None, lock_time=None, inputs_count=1, outputs_count=1) - - messages = [ - None, - TxRequest(request_type=TXINPUT, details=TxRequestDetailsType(request_index=0, tx_hash=None)), - TxAck(tx=TransactionType(inputs=[inp1])), - TxRequest(request_type=TXMETA, details=TxRequestDetailsType(request_index=None, tx_hash=unhexlify('d5f65ee80147b4bcc70b75e4bbf2d7382021b871bd8867ef8fa525ef50864882')), serialized=None), - TxAck(tx=ptx1), - TxRequest(request_type=TXINPUT, details=TxRequestDetailsType(request_index=0, tx_hash=unhexlify('d5f65ee80147b4bcc70b75e4bbf2d7382021b871bd8867ef8fa525ef50864882')), serialized=None), - TxAck(tx=TransactionType(inputs=[pinp1])), - TxRequest(request_type=TXINPUT, details=TxRequestDetailsType(request_index=1, tx_hash=unhexlify('d5f65ee80147b4bcc70b75e4bbf2d7382021b871bd8867ef8fa525ef50864882')), serialized=None), - TxAck(tx=TransactionType(inputs=[pinp2])), - TxRequest(request_type=TXOUTPUT, details=TxRequestDetailsType(request_index=0, tx_hash=unhexlify('d5f65ee80147b4bcc70b75e4bbf2d7382021b871bd8867ef8fa525ef50864882')), serialized=None), - TxAck(tx=TransactionType(bin_outputs=[pout1])), - TxRequest(request_type=TXOUTPUT, details=TxRequestDetailsType(request_index=0, tx_hash=None), serialized=None), - TxAck(tx=TransactionType(outputs=[out1])), - signtx.UiConfirmOutput(out1, coin_bitcoin), - True, - signtx.UiConfirmTotal(380000, 10000, coin_bitcoin), - True, - # ButtonRequest(code=ButtonRequest_ConfirmOutput), - # ButtonRequest(code=ButtonRequest_SignTx), - TxRequest(request_type=TXINPUT, details=TxRequestDetailsType(request_index=0, tx_hash=None), serialized=None), - TxAck(tx=TransactionType(inputs=[inp1])), - TxRequest(request_type=TXOUTPUT, details=TxRequestDetailsType(request_index=0, tx_hash=None), serialized=None), - TxAck(tx=TransactionType(outputs=[out1])), - TxRequest(request_type=TXOUTPUT, details=TxRequestDetailsType(request_index=0, tx_hash=None), serialized=TxRequestSerializedType( - signature_index=0, - signature=unhexlify('30450221009a0b7be0d4ed3146ee262b42202841834698bb3ee39c24e7437df208b8b7077102202b79ab1e7736219387dffe8d615bbdba87e11477104b867ef47afed1a5ede781'), - serialized_tx=unhexlify('010000000182488650ef25a58fef6788bd71b8212038d7f2bbe4750bc7bcb44701e85ef6d5000000006b4830450221009a0b7be0d4ed3146ee262b42202841834698bb3ee39c24e7437df208b8b7077102202b79ab1e7736219387dffe8d615bbdba87e11477104b867ef47afed1a5ede7810121023230848585885f63803a0a8aecdd6538792d5c539215c91698e315bf0253b43dffffffff'))), - TxAck(tx=TransactionType(outputs=[out1])), - TxRequest(request_type=TXFINISHED, details=None, serialized=TxRequestSerializedType( - signature_index=None, - signature=None, - serialized_tx=unhexlify('0160cc0500000000001976a914de9b2a8da088824e8fe51debea566617d851537888ac00000000'), - )), - ] - - seed = bip39.seed('alcohol woman abuse must during monitor noble actual mixed trade anger aisle', '') - root = bip32.from_seed(seed, 'secp256k1') - - signer = signtx.sign_tx(tx, root) - for request, response in chunks(messages, 2): - self.assertEqualEx(signer.send(request), response) - with self.assertRaises(StopIteration): - signer.send(None) - - def assertEqualEx(self, a, b): - # hack to avoid adding __eq__ to signtx.Ui* classes - if ((isinstance(a, signtx.UiConfirmOutput) and isinstance(b, signtx.UiConfirmOutput)) or - (isinstance(a, signtx.UiConfirmTotal) and isinstance(b, signtx.UiConfirmTotal))): - return self.assertEqual(a.__dict__, b.__dict__) - else: - return self.assertEqual(a, b) - - -if __name__ == '__main__': - unittest.main()