core/bitcoin: finalize bitcoin refactor

- core/bitcoin: move common files to the app's root
- core/bitcoin: use require_confirm instead of confirm
- core: move bitcoin unrelated functions from 'bitcoin' to a new 'misc' app
- core/bitcoin: use relative imports inside the app
- core: rename wallet app to bitcoin
- core/wallet: replace SigningErrors and the other exception classes with wire.Errors
pull/1002/head
Tomas Susanka 4 years ago
parent aa52fc3903
commit 445f56d387

@ -492,11 +492,13 @@ if FROZEN:
SOURCE_PY.extend(Glob(SOURCE_PY_DIR + 'apps/homescreen/*.py')) SOURCE_PY.extend(Glob(SOURCE_PY_DIR + 'apps/homescreen/*.py'))
SOURCE_PY.extend(Glob(SOURCE_PY_DIR + 'apps/management/*.py')) SOURCE_PY.extend(Glob(SOURCE_PY_DIR + 'apps/management/*.py'))
SOURCE_PY.extend(Glob(SOURCE_PY_DIR + 'apps/management/*/*.py')) SOURCE_PY.extend(Glob(SOURCE_PY_DIR + 'apps/management/*/*.py'))
SOURCE_PY.extend(Glob(SOURCE_PY_DIR + 'apps/wallet/*.py')) SOURCE_PY.extend(Glob(SOURCE_PY_DIR + 'apps/misc/*.py'))
SOURCE_PY.extend(Glob(SOURCE_PY_DIR + 'apps/wallet/*/*.py', SOURCE_PY.extend(Glob(SOURCE_PY_DIR + 'apps/bitcoin/*.py'))
SOURCE_PY.extend(Glob(SOURCE_PY_DIR + 'apps/bitcoin/*/*.py',
exclude=[ exclude=[
SOURCE_PY_DIR + 'apps/wallet/sign_tx/decred.py', SOURCE_PY_DIR + 'apps/bitcoin/sign_tx/decred.py',
SOURCE_PY_DIR + 'apps/wallet/sign_tx/zcash.py', SOURCE_PY_DIR + 'apps/bitcoin/sign_tx/bitcoinlike.py',
SOURCE_PY_DIR + 'apps/bitcoin/sign_tx/zcash.py',
]) ])
) )
@ -540,8 +542,9 @@ if FROZEN:
SOURCE_PY.extend(Glob(SOURCE_PY_DIR + 'apps/webauthn/*.py')) SOURCE_PY.extend(Glob(SOURCE_PY_DIR + 'apps/webauthn/*.py'))
SOURCE_PY.extend(Glob(SOURCE_PY_DIR + 'apps/wallet/sign_tx/decred.py')) SOURCE_PY.extend(Glob(SOURCE_PY_DIR + 'apps/bitcoin/sign_tx/decred.py'))
SOURCE_PY.extend(Glob(SOURCE_PY_DIR + 'apps/wallet/sign_tx/zcash.py')) SOURCE_PY.extend(Glob(SOURCE_PY_DIR + 'apps/bitcoin/sign_tx/bitcoinlike.py'))
SOURCE_PY.extend(Glob(SOURCE_PY_DIR + 'apps/bitcoin/sign_tx/zcash.py'))
source_mpy = env.FrozenModule(source=SOURCE_PY, source_dir=SOURCE_PY_DIR, bitcoin_only=BITCOIN_ONLY) source_mpy = env.FrozenModule(source=SOURCE_PY, source_dir=SOURCE_PY_DIR, bitcoin_only=BITCOIN_ONLY)

@ -460,11 +460,13 @@ if FROZEN:
SOURCE_PY.extend(Glob(SOURCE_PY_DIR + 'apps/homescreen/*.py')) SOURCE_PY.extend(Glob(SOURCE_PY_DIR + 'apps/homescreen/*.py'))
SOURCE_PY.extend(Glob(SOURCE_PY_DIR + 'apps/management/*.py')) SOURCE_PY.extend(Glob(SOURCE_PY_DIR + 'apps/management/*.py'))
SOURCE_PY.extend(Glob(SOURCE_PY_DIR + 'apps/management/*/*.py')) SOURCE_PY.extend(Glob(SOURCE_PY_DIR + 'apps/management/*/*.py'))
SOURCE_PY.extend(Glob(SOURCE_PY_DIR + 'apps/wallet/*.py')) SOURCE_PY.extend(Glob(SOURCE_PY_DIR + 'apps/misc/*.py'))
SOURCE_PY.extend(Glob(SOURCE_PY_DIR + 'apps/wallet/*/*.py', SOURCE_PY.extend(Glob(SOURCE_PY_DIR + 'apps/bitcoin/*.py'))
SOURCE_PY.extend(Glob(SOURCE_PY_DIR + 'apps/bitcoin/*/*.py',
exclude=[ exclude=[
SOURCE_PY_DIR + 'apps/wallet/sign_tx/decred.py', SOURCE_PY_DIR + 'apps/bitcoin/sign_tx/decred.py',
SOURCE_PY_DIR + 'apps/wallet/sign_tx/zcash.py', SOURCE_PY_DIR + 'apps/bitcoin/sign_tx/bitcoinlike.py',
SOURCE_PY_DIR + 'apps/bitcoin/sign_tx/zcash.py',
]) ])
) )
@ -508,8 +510,9 @@ if FROZEN:
SOURCE_PY.extend(Glob(SOURCE_PY_DIR + 'apps/webauthn/*.py')) SOURCE_PY.extend(Glob(SOURCE_PY_DIR + 'apps/webauthn/*.py'))
SOURCE_PY.extend(Glob(SOURCE_PY_DIR + 'apps/wallet/sign_tx/decred.py')) SOURCE_PY.extend(Glob(SOURCE_PY_DIR + 'apps/bitcoin/sign_tx/decred.py'))
SOURCE_PY.extend(Glob(SOURCE_PY_DIR + 'apps/wallet/sign_tx/zcash.py')) SOURCE_PY.extend(Glob(SOURCE_PY_DIR + 'apps/bitcoin/sign_tx/bitcoinlike.py'))
SOURCE_PY.extend(Glob(SOURCE_PY_DIR + 'apps/bitcoin/sign_tx/zcash.py'))
source_mpy = env.FrozenModule(source=SOURCE_PY, source_dir=SOURCE_PY_DIR, bitcoin_only=BITCOIN_ONLY) source_mpy = env.FrozenModule(source=SOURCE_PY, source_dir=SOURCE_PY_DIR, bitcoin_only=BITCOIN_ONLY)

@ -5,10 +5,6 @@ from trezor.messages import MessageType
def boot() -> None: def boot() -> None:
wire.add(MessageType.GetPublicKey, __name__, "get_public_key") wire.add(MessageType.GetPublicKey, __name__, "get_public_key")
wire.add(MessageType.GetAddress, __name__, "get_address") wire.add(MessageType.GetAddress, __name__, "get_address")
wire.add(MessageType.GetEntropy, __name__, "get_entropy")
wire.add(MessageType.SignTx, __name__, "sign_tx") wire.add(MessageType.SignTx, __name__, "sign_tx")
wire.add(MessageType.SignMessage, __name__, "sign_message") wire.add(MessageType.SignMessage, __name__, "sign_message")
wire.add(MessageType.VerifyMessage, __name__, "verify_message") wire.add(MessageType.VerifyMessage, __name__, "verify_message")
wire.add(MessageType.SignIdentity, __name__, "sign_identity")
wire.add(MessageType.GetECDHSessionKey, __name__, "get_ecdh_session_key")
wire.add(MessageType.CipherKeyValue, __name__, "cipher_key_value")

@ -1,31 +1,21 @@
from micropython import const from trezor import wire
from trezor.crypto import base58, cashaddr
from trezor.crypto import base58, bech32, cashaddr
from trezor.crypto.hashlib import sha256 from trezor.crypto.hashlib import sha256
from trezor.messages import FailureType, InputScriptType from trezor.messages import InputScriptType
from trezor.messages.MultisigRedeemScriptType import MultisigRedeemScriptType from trezor.messages.MultisigRedeemScriptType import MultisigRedeemScriptType
from trezor.utils import ensure
from .common import ecdsa_hash_pubkey, encode_bech32_address
from .multisig import multisig_get_pubkeys, multisig_pubkey_index
from .scripts import output_script_multisig, output_script_native_p2wpkh_or_p2wsh
from apps.common import HARDENED, address_type, paths from apps.common import HARDENED, address_type, paths
from apps.common.coininfo import CoinInfo from apps.common.coininfo import CoinInfo
from apps.wallet.sign_tx.multisig import multisig_get_pubkeys, multisig_pubkey_index
from apps.wallet.sign_tx.scripts import (
output_script_multisig,
output_script_native_p2wpkh_or_p2wsh,
)
if False: if False:
from typing import List from typing import List
from trezor.crypto import bip32 from trezor.crypto import bip32
from trezor.messages.TxInputType import EnumTypeInputScriptType from trezor.messages.TxInputType import EnumTypeInputScriptType
# supported witness version for bech32 addresses
_BECH32_WITVER = const(0x00)
class AddressError(Exception):
pass
def get_address( def get_address(
script_type: EnumTypeInputScriptType, script_type: EnumTypeInputScriptType,
@ -42,11 +32,9 @@ def get_address(
pubkey = node.public_key() pubkey = node.public_key()
index = multisig_pubkey_index(multisig, pubkey) index = multisig_pubkey_index(multisig, pubkey)
if index is None: if index is None:
raise AddressError(FailureType.ProcessError, "Public key not found") raise wire.ProcessError("Public key not found")
if coin.address_type_p2sh is None: if coin.address_type_p2sh is None:
raise AddressError( raise wire.ProcessError("Multisig not enabled on this coin")
FailureType.ProcessError, "Multisig not enabled on this coin"
)
pubkeys = multisig_get_pubkeys(multisig) pubkeys = multisig_get_pubkeys(multisig)
address = address_multisig_p2sh(pubkeys, multisig.m, coin) address = address_multisig_p2sh(pubkeys, multisig.m, coin)
@ -54,7 +42,7 @@ def get_address(
address = address_to_cashaddr(address, coin) address = address_to_cashaddr(address, coin)
return address return address
if script_type == InputScriptType.SPENDMULTISIG: if script_type == InputScriptType.SPENDMULTISIG:
raise AddressError(FailureType.ProcessError, "Multisig details required") raise wire.ProcessError("Multisig details required")
# p2pkh # p2pkh
address = node.address(coin.address_type) address = node.address(coin.address_type)
@ -64,9 +52,7 @@ def get_address(
elif script_type == InputScriptType.SPENDWITNESS: # native p2wpkh or native p2wsh elif script_type == InputScriptType.SPENDWITNESS: # native p2wpkh or native p2wsh
if not coin.segwit or not coin.bech32_prefix: if not coin.segwit or not coin.bech32_prefix:
raise AddressError( raise wire.ProcessError("Segwit not enabled on this coin")
FailureType.ProcessError, "Segwit not enabled on this coin"
)
# native p2wsh multisig # native p2wsh multisig
if multisig is not None: if multisig is not None:
pubkeys = multisig_get_pubkeys(multisig) pubkeys = multisig_get_pubkeys(multisig)
@ -79,9 +65,7 @@ def get_address(
script_type == InputScriptType.SPENDP2SHWITNESS script_type == InputScriptType.SPENDP2SHWITNESS
): # p2wpkh or p2wsh nested in p2sh ): # p2wpkh or p2wsh nested in p2sh
if not coin.segwit or coin.address_type_p2sh is None: if not coin.segwit or coin.address_type_p2sh is None:
raise AddressError( raise wire.ProcessError("Segwit not enabled on this coin")
FailureType.ProcessError, "Segwit not enabled on this coin"
)
# p2wsh multisig nested in p2sh # p2wsh multisig nested in p2sh
if multisig is not None: if multisig is not None:
pubkeys = multisig_get_pubkeys(multisig) pubkeys = multisig_get_pubkeys(multisig)
@ -91,14 +75,12 @@ def get_address(
return address_p2wpkh_in_p2sh(node.public_key(), coin) return address_p2wpkh_in_p2sh(node.public_key(), coin)
else: else:
raise AddressError(FailureType.ProcessError, "Invalid script type") raise wire.ProcessError("Invalid script type")
def address_multisig_p2sh(pubkeys: List[bytes], m: int, coin: CoinInfo) -> str: def address_multisig_p2sh(pubkeys: List[bytes], m: int, coin: CoinInfo) -> str:
if coin.address_type_p2sh is None: if coin.address_type_p2sh is None:
raise AddressError( raise wire.ProcessError("Multisig not enabled on this coin")
FailureType.ProcessError, "Multisig not enabled on this coin"
)
redeem_script = output_script_multisig(pubkeys, m) redeem_script = output_script_multisig(pubkeys, m)
redeem_script_hash = coin.script_hash(redeem_script) redeem_script_hash = coin.script_hash(redeem_script)
return address_p2sh(redeem_script_hash, coin) return address_p2sh(redeem_script_hash, coin)
@ -106,9 +88,7 @@ def address_multisig_p2sh(pubkeys: List[bytes], m: int, coin: CoinInfo) -> str:
def address_multisig_p2wsh_in_p2sh(pubkeys: List[bytes], m: int, coin: CoinInfo) -> str: def address_multisig_p2wsh_in_p2sh(pubkeys: List[bytes], m: int, coin: CoinInfo) -> str:
if coin.address_type_p2sh is None: if coin.address_type_p2sh is None:
raise AddressError( raise wire.ProcessError("Multisig not enabled on this coin")
FailureType.ProcessError, "Multisig not enabled on this coin"
)
witness_script = output_script_multisig(pubkeys, m) witness_script = output_script_multisig(pubkeys, m)
witness_script_hash = sha256(witness_script).digest() witness_script_hash = sha256(witness_script).digest()
return address_p2wsh_in_p2sh(witness_script_hash, coin) return address_p2wsh_in_p2sh(witness_script_hash, coin)
@ -116,9 +96,7 @@ def address_multisig_p2wsh_in_p2sh(pubkeys: List[bytes], m: int, coin: CoinInfo)
def address_multisig_p2wsh(pubkeys: List[bytes], m: int, hrp: str) -> str: def address_multisig_p2wsh(pubkeys: List[bytes], m: int, hrp: str) -> str:
if not hrp: if not hrp:
raise AddressError( raise wire.ProcessError("Multisig not enabled on this coin")
FailureType.ProcessError, "Multisig not enabled on this coin"
)
witness_script = output_script_multisig(pubkeys, m) witness_script = output_script_multisig(pubkeys, m)
witness_script_hash = sha256(witness_script).digest() witness_script_hash = sha256(witness_script).digest()
return address_p2wsh(witness_script_hash, hrp) return address_p2wsh(witness_script_hash, hrp)
@ -149,24 +127,11 @@ def address_p2wsh_in_p2sh(witness_script_hash: bytes, coin: CoinInfo) -> str:
def address_p2wpkh(pubkey: bytes, coin: CoinInfo) -> str: def address_p2wpkh(pubkey: bytes, coin: CoinInfo) -> str:
pubkeyhash = ecdsa_hash_pubkey(pubkey, coin) pubkeyhash = ecdsa_hash_pubkey(pubkey, coin)
address = bech32.encode(coin.bech32_prefix, _BECH32_WITVER, pubkeyhash) return encode_bech32_address(coin.bech32_prefix, pubkeyhash)
if address is None:
raise AddressError(FailureType.ProcessError, "Invalid address")
return address
def address_p2wsh(witness_script_hash: bytes, hrp: str) -> str: def address_p2wsh(witness_script_hash: bytes, hrp: str) -> str:
address = bech32.encode(hrp, _BECH32_WITVER, witness_script_hash) return encode_bech32_address(hrp, witness_script_hash)
if address is None:
raise AddressError(FailureType.ProcessError, "Invalid address")
return address
def decode_bech32_address(prefix: str, address: str) -> bytes:
witver, raw = bech32.decode(prefix, address)
if witver != _BECH32_WITVER:
raise AddressError(FailureType.ProcessError, "Invalid address witness program")
return bytes(raw)
def address_to_cashaddr(address: str, coin: CoinInfo) -> str: def address_to_cashaddr(address: str, coin: CoinInfo) -> str:
@ -181,17 +146,6 @@ def address_to_cashaddr(address: str, coin: CoinInfo) -> str:
return cashaddr.encode(coin.cashaddr_prefix, version, data) return cashaddr.encode(coin.cashaddr_prefix, version, data)
def ecdsa_hash_pubkey(pubkey: bytes, coin: CoinInfo) -> bytes:
if pubkey[0] == 0x04:
ensure(len(pubkey) == 65) # uncompressed format
elif pubkey[0] == 0x00:
ensure(len(pubkey) == 1) # point at infinity
else:
ensure(len(pubkey) == 33) # compresssed format
return coin.script_hash(pubkey)
def address_short(coin: CoinInfo, address: str) -> str: def address_short(coin: CoinInfo, address: str) -> str:
if coin.cashaddr_prefix is not None and address.startswith( if coin.cashaddr_prefix is not None and address.startswith(
coin.cashaddr_prefix + ":" coin.cashaddr_prefix + ":"

@ -0,0 +1,42 @@
from micropython import const
from trezor import wire
from trezor.crypto import bech32, bip32, der
from trezor.crypto.curve import secp256k1
from trezor.utils import ensure
from apps.common.coininfo import CoinInfo
# supported witness version for bech32 addresses
_BECH32_WITVER = const(0x00)
def ecdsa_sign(node: bip32.HDNode, digest: bytes) -> bytes:
sig = secp256k1.sign(node.private_key(), digest)
sigder = der.encode_seq((sig[1:33], sig[33:65]))
return sigder
def ecdsa_hash_pubkey(pubkey: bytes, coin: CoinInfo) -> bytes:
if pubkey[0] == 0x04:
ensure(len(pubkey) == 65) # uncompressed format
elif pubkey[0] == 0x00:
ensure(len(pubkey) == 1) # point at infinity
else:
ensure(len(pubkey) == 33) # compresssed format
return coin.script_hash(pubkey)
def encode_bech32_address(prefix: str, script: bytes) -> bytes:
address = bech32.encode(prefix, _BECH32_WITVER, script)
if address is None:
raise wire.ProcessError("Invalid address")
return address
def decode_bech32_address(prefix: str, address: str) -> bytes:
witver, raw = bech32.decode(prefix, address)
if witver != _BECH32_WITVER:
raise wire.ProcessError("Invalid address witness program")
return bytes(raw)

@ -2,9 +2,9 @@ from trezor.crypto import bip32
from trezor.messages import InputScriptType from trezor.messages import InputScriptType
from trezor.messages.Address import Address from trezor.messages.Address import Address
from . import addresses
from .keychain import with_keychain from .keychain import with_keychain
from .sign_tx import addresses from .multisig import multisig_pubkey_index
from .sign_tx.multisig import multisig_pubkey_index
from apps.common.layout import address_n_to_str, show_address, show_qr, show_xpub from apps.common.layout import address_n_to_str, show_address, show_qr, show_xpub
from apps.common.paths import validate_path from apps.common.paths import validate_path

@ -1,20 +1,16 @@
from trezor import wire
from trezor.crypto import bip32 from trezor.crypto import bip32
from trezor.crypto.hashlib import sha256 from trezor.crypto.hashlib import sha256
from trezor.messages import FailureType
from trezor.messages.HDNodeType import HDNodeType from trezor.messages.HDNodeType import HDNodeType
from trezor.messages.MultisigRedeemScriptType import MultisigRedeemScriptType from trezor.messages.MultisigRedeemScriptType import MultisigRedeemScriptType
from trezor.utils import HashWriter from trezor.utils import HashWriter
from apps.wallet.sign_tx.writers import write_bytes_fixed, write_uint32 from .writers import write_bytes_fixed, write_uint32
if False: if False:
from typing import List from typing import List
class MultisigError(ValueError):
pass
def multisig_fingerprint(multisig: MultisigRedeemScriptType) -> bytes: def multisig_fingerprint(multisig: MultisigRedeemScriptType) -> bytes:
if multisig.nodes: if multisig.nodes:
pubnodes = multisig.nodes pubnodes = multisig.nodes
@ -24,11 +20,11 @@ def multisig_fingerprint(multisig: MultisigRedeemScriptType) -> bytes:
n = len(pubnodes) n = len(pubnodes)
if n < 1 or n > 15 or m < 1 or m > 15: if n < 1 or n > 15 or m < 1 or m > 15:
raise MultisigError(FailureType.DataError, "Invalid multisig parameters") raise wire.DataError("Invalid multisig parameters")
for d in pubnodes: for d in pubnodes:
if len(d.public_key) != 33 or len(d.chain_code) != 32: if len(d.public_key) != 33 or len(d.chain_code) != 32:
raise MultisigError(FailureType.DataError, "Invalid multisig parameters") raise wire.DataError("Invalid multisig parameters")
# casting to bytes(), sorting on bytearray() is not supported in MicroPython # casting to bytes(), sorting on bytearray() is not supported in MicroPython
pubnodes = sorted(pubnodes, key=lambda n: bytes(n.public_key)) pubnodes = sorted(pubnodes, key=lambda n: bytes(n.public_key))
@ -55,7 +51,7 @@ def multisig_pubkey_index(multisig: MultisigRedeemScriptType, pubkey: bytes) ->
for i, hd in enumerate(multisig.pubkeys): for i, hd in enumerate(multisig.pubkeys):
if multisig_get_pubkey(hd.node, hd.address_n) == pubkey: if multisig_get_pubkey(hd.node, hd.address_n) == pubkey:
return i return i
raise MultisigError(FailureType.DataError, "Pubkey not found in multisig script") raise wire.DataError("Pubkey not found in multisig script")
def multisig_get_pubkey(n: HDNodeType, p: list) -> bytes: def multisig_get_pubkey(n: HDNodeType, p: list) -> bytes:

@ -1,34 +1,30 @@
from trezor import utils from trezor import utils, wire
from trezor.crypto import base58, cashaddr from trezor.crypto import base58, cashaddr
from trezor.crypto.hashlib import sha256 from trezor.crypto.hashlib import sha256
from trezor.messages import FailureType, InputScriptType, OutputScriptType from trezor.messages import InputScriptType, OutputScriptType
from trezor.messages.MultisigRedeemScriptType import MultisigRedeemScriptType from trezor.messages.MultisigRedeemScriptType import MultisigRedeemScriptType
from trezor.messages.TxInputType import TxInputType from trezor.messages.TxInputType import TxInputType
from trezor.messages.TxOutputType import TxOutputType from trezor.messages.TxOutputType import TxOutputType
from apps.common import address_type from apps.common import address_type
from apps.common.coininfo import CoinInfo from apps.common.coininfo import CoinInfo
from apps.common.writers import empty_bytearray from apps.common.writers import empty_bytearray, write_bitcoin_varint
from apps.wallet.sign_tx import addresses
from apps.wallet.sign_tx.multisig import ( from . import common
from .multisig import (
multisig_get_pubkey_count, multisig_get_pubkey_count,
multisig_get_pubkeys, multisig_get_pubkeys,
multisig_pubkey_index, multisig_pubkey_index,
) )
from apps.wallet.sign_tx.writers import ( from .writers import (
write_bytes_fixed, write_bytes_fixed,
write_bytes_unchecked, write_bytes_unchecked,
write_op_push, write_op_push,
write_varint,
) )
if False: if False:
from typing import List, Optional from typing import List, Optional
from apps.wallet.sign_tx.writers import Writer from .writers import Writer
class ScriptsError(ValueError):
pass
def input_derive_script( def input_derive_script(
@ -54,7 +50,7 @@ def input_derive_script(
return input_script_p2wsh_in_p2sh(witness_script_hash) return input_script_p2wsh_in_p2sh(witness_script_hash)
# p2wpkh in p2sh # p2wpkh in p2sh
return input_script_p2wpkh_in_p2sh(addresses.ecdsa_hash_pubkey(pubkey, coin)) return input_script_p2wpkh_in_p2sh(common.ecdsa_hash_pubkey(pubkey, coin))
elif txi.script_type == InputScriptType.SPENDWITNESS: elif txi.script_type == InputScriptType.SPENDWITNESS:
# native p2wpkh or p2wsh # native p2wpkh or p2wsh
return input_script_native_p2wpkh_or_p2wsh() return input_script_native_p2wpkh_or_p2wsh()
@ -65,7 +61,7 @@ def input_derive_script(
txi.multisig, signature, signature_index, hash_type, coin txi.multisig, signature, signature_index, hash_type, coin
) )
else: else:
raise ScriptsError(FailureType.ProcessError, "Invalid script type") raise wire.ProcessError("Invalid script type")
def output_derive_script(txo: TxOutputType, coin: CoinInfo) -> bytes: def output_derive_script(txo: TxOutputType, coin: CoinInfo) -> bytes:
@ -74,7 +70,7 @@ def output_derive_script(txo: TxOutputType, coin: CoinInfo) -> bytes:
if coin.bech32_prefix and txo.address.startswith(coin.bech32_prefix): if coin.bech32_prefix and txo.address.startswith(coin.bech32_prefix):
# p2wpkh or p2wsh # p2wpkh or p2wsh
witprog = addresses.decode_bech32_address(coin.bech32_prefix, txo.address) witprog = common.decode_bech32_address(coin.bech32_prefix, txo.address)
return output_script_native_p2wpkh_or_p2wsh(witprog) return output_script_native_p2wpkh_or_p2wsh(witprog)
if ( if (
@ -89,13 +85,13 @@ def output_derive_script(txo: TxOutputType, coin: CoinInfo) -> bytes:
elif version == cashaddr.ADDRESS_TYPE_P2SH: elif version == cashaddr.ADDRESS_TYPE_P2SH:
version = coin.address_type_p2sh version = coin.address_type_p2sh
else: else:
raise ScriptsError("Unknown cashaddr address type") raise wire.DataError("Unknown cashaddr address type")
raw_address = bytes([version]) + data raw_address = bytes([version]) + data
else: else:
try: try:
raw_address = base58.decode_check(txo.address, coin.b58_hash) raw_address = base58.decode_check(txo.address, coin.b58_hash)
except ValueError: except ValueError:
raise ScriptsError(FailureType.DataError, "Invalid address") raise wire.DataError("Invalid address")
if address_type.check(coin.address_type, raw_address): if address_type.check(coin.address_type, raw_address):
# p2pkh # p2pkh
@ -108,7 +104,7 @@ def output_derive_script(txo: TxOutputType, coin: CoinInfo) -> bytes:
script = output_script_p2sh(scripthash) script = output_script_p2sh(scripthash)
return script return script
raise ScriptsError(FailureType.DataError, "Invalid address type") raise wire.DataError("Invalid address type")
# see https://github.com/bitcoin/bips/blob/master/bip-0143.mediawiki#specification # see https://github.com/bitcoin/bips/blob/master/bip-0143.mediawiki#specification
@ -131,9 +127,7 @@ def bip143_derive_script_code(txi: TxInputType, pubkeyhash: bytes) -> bytearray:
return output_script_p2pkh(pubkeyhash) return output_script_p2pkh(pubkeyhash)
else: else:
raise ScriptsError( raise wire.DataError("Unknown input script type for bip143 script code")
FailureType.DataError, "Unknown input script type for bip143 script code",
)
# P2PKH, P2SH # P2PKH, P2SH
@ -238,7 +232,7 @@ def input_script_p2wsh_in_p2sh(script_hash: bytes) -> bytearray:
# Signature is moved to the witness. # Signature is moved to the witness.
if len(script_hash) != 32: if len(script_hash) != 32:
raise ScriptsError("Redeem script hash should be 32 bytes long") raise wire.DataError("Redeem script hash should be 32 bytes long")
w = empty_bytearray(3 + len(script_hash)) w = empty_bytearray(3 + len(script_hash))
w.append(0x22) # length of the data w.append(0x22) # length of the data
@ -272,7 +266,7 @@ def witness_p2wsh(
) )
# fill in our signature # fill in our signature
if signatures[signature_index]: if signatures[signature_index]:
raise ScriptsError("Invalid multisig parameters") raise wire.DataError("Invalid multisig parameters")
signatures[signature_index] = signature signatures[signature_index] = signature
# filter empty # filter empty
@ -324,7 +318,7 @@ def input_script_multisig(
) -> bytearray: ) -> bytearray:
signatures = multisig.signatures # other signatures signatures = multisig.signatures # other signatures
if len(signatures[signature_index]) > 0: if len(signatures[signature_index]) > 0:
raise ScriptsError("Invalid multisig parameters") raise wire.DataError("Invalid multisig parameters")
signatures[signature_index] = signature # our signature signatures[signature_index] = signature # our signature
# length of the redeem script # length of the redeem script
@ -367,10 +361,10 @@ def output_script_multisig(pubkeys: List[bytes], m: int) -> bytearray:
def write_output_script_multisig(w: Writer, pubkeys: List[bytes], m: int) -> None: def write_output_script_multisig(w: Writer, pubkeys: List[bytes], m: int) -> None:
n = len(pubkeys) n = len(pubkeys)
if n < 1 or n > 15 or m < 1 or m > 15 or m > n: if n < 1 or n > 15 or m < 1 or m > 15 or m > n:
raise ScriptsError("Invalid multisig parameters") raise wire.DataError("Invalid multisig parameters")
for pubkey in pubkeys: for pubkey in pubkeys:
if len(pubkey) != 33: if len(pubkey) != 33:
raise ScriptsError("Invalid multisig parameters") raise wire.DataError("Invalid multisig parameters")
w.append(0x50 + m) # numbers 1 to 16 are pushed as 0x50 + value w.append(0x50 + m) # numbers 1 to 16 are pushed as 0x50 + value
for p in pubkeys: for p in pubkeys:

@ -3,8 +3,8 @@ from trezor.crypto.curve import secp256k1
from trezor.messages.InputScriptType import SPENDADDRESS, SPENDP2SHWITNESS, SPENDWITNESS from trezor.messages.InputScriptType import SPENDADDRESS, SPENDP2SHWITNESS, SPENDWITNESS
from trezor.messages.MessageSignature import MessageSignature from trezor.messages.MessageSignature import MessageSignature
from .addresses import get_address, validate_full_path
from .keychain import with_keychain from .keychain import with_keychain
from .sign_tx.addresses import get_address, validate_full_path
from apps.common.paths import validate_path from apps.common.paths import validate_path
from apps.common.signverify import message_digest, require_confirm_sign_message from apps.common.signverify import message_digest, require_confirm_sign_message

@ -5,12 +5,12 @@ from trezor.messages.TxAck import TxAck
from trezor.messages.TxRequest import TxRequest from trezor.messages.TxRequest import TxRequest
from ..keychain import with_keychain from ..keychain import with_keychain
from . import addresses, bitcoin, common, helpers, layout, multisig, progress, scripts from . import bitcoin, helpers, layout, progress
from apps.common import coininfo, paths, seed from apps.common import coininfo, paths, seed
if not utils.BITCOIN_ONLY: if not utils.BITCOIN_ONLY:
from apps.wallet.sign_tx import bitcoinlike, decred, zcash from . import bitcoinlike, decred, zcash
if False: if False:
from typing import Type, Union from typing import Type, Union
@ -36,22 +36,11 @@ async def sign_tx(
else: else:
signer_class = bitcoin.Bitcoin signer_class = bitcoin.Bitcoin
try: signer = signer_class(msg, keychain, coin).signer()
signer = signer_class(msg, keychain, coin).signer()
except common.SigningError as e:
raise wire.Error(*e.args)
res = None # type: Union[TxAck, bool, None] res = None # type: Union[TxAck, bool, None]
while True: while True:
try: req = signer.send(res)
req = signer.send(res)
except (
common.SigningError,
multisig.MultisigError,
addresses.AddressError,
scripts.ScriptsError,
) as e:
raise wire.Error(*e.args)
if isinstance(req, TxRequest): if isinstance(req, TxRequest):
if req.request_type == TXFINISHED: if req.request_type == TXFINISHED:
break break

@ -1,8 +1,9 @@
import gc import gc
from micropython import const from micropython import const
from trezor import wire
from trezor.crypto.hashlib import sha256 from trezor.crypto.hashlib import sha256
from trezor.messages import FailureType, InputScriptType from trezor.messages import InputScriptType
from trezor.messages.SignTx import SignTx from trezor.messages.SignTx import SignTx
from trezor.messages.TransactionType import TransactionType from trezor.messages.TransactionType import TransactionType
from trezor.messages.TxInputType import TxInputType from trezor.messages.TxInputType import TxInputType
@ -14,17 +15,12 @@ from trezor.messages.TxRequestSerializedType import TxRequestSerializedType
from trezor.utils import HashWriter, ensure from trezor.utils import HashWriter, ensure
from apps.common import coininfo, seed from apps.common import coininfo, seed
from apps.wallet.sign_tx import ( from apps.common.writers import write_bitcoin_varint
addresses,
helpers, from .. import addresses, multisig, scripts, writers
multisig, from ..common import ecdsa_hash_pubkey, ecdsa_sign
progress, from . import helpers, progress, tx_weight
scripts, from .matchcheck import MultisigFingerprintChecker, WalletPathChecker
tx_weight,
writers,
)
from apps.wallet.sign_tx.common import SigningError, ecdsa_sign
from apps.wallet.sign_tx.matchcheck import MultisigFingerprintChecker, WalletPathChecker
if False: if False:
from typing import Set, Tuple, Union from typing import Set, Tuple, Union
@ -136,17 +132,10 @@ class Bitcoin:
# fee > (coin.maxfee per byte * tx size) # fee > (coin.maxfee per byte * tx size)
if fee > (self.coin.maxfee_kb / 1000) * (self.weight.get_total() / 4): if fee > (self.coin.maxfee_kb / 1000) * (self.weight.get_total() / 4):
if not await helpers.confirm_feeoverthreshold(fee, self.coin): await helpers.confirm_feeoverthreshold(fee, self.coin)
raise SigningError(FailureType.ActionCancelled, "Signing cancelled")
if self.tx.lock_time > 0: if self.tx.lock_time > 0:
if not await helpers.confirm_nondefault_locktime(self.tx.lock_time): await helpers.confirm_nondefault_locktime(self.tx.lock_time)
raise SigningError(FailureType.ActionCancelled, "Locktime cancelled") await helpers.confirm_total(self.total_in - self.change_out, fee, self.coin)
if not await helpers.confirm_total(
self.total_in - self.change_out, fee, self.coin
):
raise SigningError(FailureType.ActionCancelled, "Total cancelled")
async def step4_serialize_inputs(self) -> None: async def step4_serialize_inputs(self) -> None:
self.write_tx_header(self.serialized_tx, self.tx, bool(self.segwit)) self.write_tx_header(self.serialized_tx, self.tx, bool(self.segwit))
@ -193,7 +182,7 @@ class Bitcoin:
elif input_is_nonsegwit(txi): elif input_is_nonsegwit(txi):
await self.process_nonsegwit_input(txi) await self.process_nonsegwit_input(txi)
else: else:
raise SigningError(FailureType.DataError, "Wrong input script type") raise wire.DataError("Wrong input script type")
async def process_segwit_input(self, txi: TxInputType) -> None: async def process_segwit_input(self, txi: TxInputType) -> None:
await self.process_bip143_input(txi) await self.process_bip143_input(txi)
@ -205,7 +194,7 @@ class Bitcoin:
async def process_bip143_input(self, txi: TxInputType) -> None: async def process_bip143_input(self, txi: TxInputType) -> None:
if not txi.amount: if not txi.amount:
raise SigningError(FailureType.DataError, "Expected input with amount") raise wire.DataError("Expected input with amount")
self.bip143_in += txi.amount self.bip143_in += txi.amount
self.total_in += txi.amount self.total_in += txi.amount
@ -213,24 +202,22 @@ class Bitcoin:
if self.change_out == 0 and self.output_is_change(txo): if self.change_out == 0 and self.output_is_change(txo):
# output is change and does not need confirmation # output is change and does not need confirmation
self.change_out = txo.amount self.change_out = txo.amount
elif not await helpers.confirm_output(txo, self.coin): else:
raise SigningError(FailureType.ActionCancelled, "Output cancelled") await helpers.confirm_output(txo, self.coin)
self.write_tx_output(self.h_confirmed, txo, script_pubkey) self.write_tx_output(self.h_confirmed, txo, script_pubkey)
self.hash143_add_output(txo, script_pubkey) self.hash143_add_output(txo, script_pubkey)
self.total_out += txo.amount self.total_out += txo.amount
def on_negative_fee(self) -> None: def on_negative_fee(self) -> None:
raise SigningError(FailureType.NotEnoughFunds, "Not enough funds") raise wire.NotEnoughFunds("Not enough funds")
async def serialize_segwit_input(self, i: int) -> None: async def serialize_segwit_input(self, i: int) -> None:
# STAGE_REQUEST_SEGWIT_INPUT in legacy # STAGE_REQUEST_SEGWIT_INPUT in legacy
txi = await helpers.request_tx_input(self.tx_req, i, self.coin) txi = await helpers.request_tx_input(self.tx_req, i, self.coin)
if not input_is_segwit(txi): if not input_is_segwit(txi):
raise SigningError( raise wire.ProcessError("Transaction has changed during signing")
FailureType.ProcessError, "Transaction has changed during signing"
)
self.wallet_path.check_input(txi) self.wallet_path.check_input(txi)
# NOTE: No need to check the multisig fingerprint, because we won't be signing # NOTE: No need to check the multisig fingerprint, because we won't be signing
# the script here. Signatures are produced in STAGE_REQUEST_SEGWIT_WITNESS. # the script here. Signatures are produced in STAGE_REQUEST_SEGWIT_WITNESS.
@ -245,15 +232,13 @@ class Bitcoin:
self.multisig_fingerprint.check_input(txi) self.multisig_fingerprint.check_input(txi)
if txi.amount > self.bip143_in: if txi.amount > self.bip143_in:
raise SigningError( raise wire.ProcessError("Transaction has changed during signing")
FailureType.ProcessError, "Transaction has changed during signing"
)
self.bip143_in -= txi.amount self.bip143_in -= txi.amount
node = self.keychain.derive(txi.address_n) node = self.keychain.derive(txi.address_n)
public_key = node.public_key() public_key = node.public_key()
hash143_hash = self.hash143_preimage_hash( hash143_hash = self.hash143_preimage_hash(
txi, addresses.ecdsa_hash_pubkey(public_key, self.coin) txi, ecdsa_hash_pubkey(public_key, self.coin)
) )
signature = ecdsa_sign(node, hash143_hash) signature = ecdsa_sign(node, hash143_hash)
@ -265,9 +250,7 @@ class Bitcoin:
txi = await helpers.request_tx_input(self.tx_req, i, self.coin) txi = await helpers.request_tx_input(self.tx_req, i, self.coin)
if not input_is_segwit(txi): if not input_is_segwit(txi):
raise SigningError( raise wire.ProcessError("Transaction has changed during signing")
FailureType.ProcessError, "Transaction has changed during signing"
)
public_key, signature = self.sign_bip143_input(txi) public_key, signature = self.sign_bip143_input(txi)
@ -318,9 +301,7 @@ class Bitcoin:
addresses.ecdsa_hash_pubkey(key_sign_pub, self.coin) addresses.ecdsa_hash_pubkey(key_sign_pub, self.coin)
) )
else: else:
raise SigningError( raise wire.ProcessError("Unknown transaction type")
FailureType.ProcessError, "Unknown transaction type"
)
txi_sign = txi txi_sign = txi
else: else:
script_pubkey = bytes() script_pubkey = bytes()
@ -340,9 +321,7 @@ class Bitcoin:
# check the control digests # check the control digests
if self.h_confirmed.get_digest() != h_check.get_digest(): if self.h_confirmed.get_digest() != h_check.get_digest():
raise SigningError( raise wire.ProcessError("Transaction has changed during signing")
FailureType.ProcessError, "Transaction has changed during signing"
)
# compute the signature from the tx digest # compute the signature from the tx digest
signature = ecdsa_sign( signature = ecdsa_sign(
@ -368,9 +347,7 @@ class Bitcoin:
tx = await helpers.request_tx_meta(self.tx_req, self.coin, prev_hash) tx = await helpers.request_tx_meta(self.tx_req, self.coin, prev_hash)
if tx.outputs_cnt <= prev_index: if tx.outputs_cnt <= prev_index:
raise SigningError( raise wire.ProcessError("Not enough outputs in previous transaction.")
FailureType.ProcessError, "Not enough outputs in previous transaction."
)
txh = self.create_hash_writer() txh = self.create_hash_writer()
@ -401,9 +378,7 @@ class Bitcoin:
writers.get_tx_hash(txh, double=self.coin.sign_hash_double, reverse=True) writers.get_tx_hash(txh, double=self.coin.sign_hash_double, reverse=True)
!= prev_hash != prev_hash
): ):
raise SigningError( raise wire.ProcessError("Encountered invalid prev_hash")
FailureType.ProcessError, "Encountered invalid prev_hash"
)
return amount_out return amount_out
@ -469,7 +444,7 @@ class Bitcoin:
txo.script_type txo.script_type
] ]
except KeyError: except KeyError:
raise SigningError(FailureType.DataError, "Invalid script type") raise wire.DataError("Invalid script type")
node = self.keychain.derive(txo.address_n) node = self.keychain.derive(txo.address_n)
txo.address = addresses.get_address( txo.address = addresses.get_address(
input_script_type, self.coin, node, txo.multisig input_script_type, self.coin, node, txo.multisig

@ -1,14 +1,16 @@
import gc import gc
from micropython import const from micropython import const
from trezor.messages import FailureType from trezor import wire
from trezor.messages.SignTx import SignTx from trezor.messages.SignTx import SignTx
from trezor.messages.TransactionType import TransactionType from trezor.messages.TransactionType import TransactionType
from trezor.messages.TxInputType import TxInputType from trezor.messages.TxInputType import TxInputType
from apps.wallet.sign_tx import helpers, multisig, writers from .. import multisig, writers
from apps.wallet.sign_tx.bitcoin import Bitcoin, input_is_nonsegwit from . import helpers
from apps.wallet.sign_tx.common import SigningError from .bitcoin import Bitcoin, input_is_nonsegwit
from apps.common.writers import write_bitcoin_varint
if False: if False:
from typing import Union from typing import Union
@ -19,7 +21,7 @@ _SIGHASH_FORKID = const(0x40)
class Bitcoinlike(Bitcoin): class Bitcoinlike(Bitcoin):
async def process_segwit_input(self, txi: TxInputType) -> None: async def process_segwit_input(self, txi: TxInputType) -> None:
if not self.coin.segwit: if not self.coin.segwit:
raise SigningError(FailureType.DataError, "Segwit not enabled on this coin") raise wire.DataError("Segwit not enabled on this coin")
await super().process_segwit_input(txi) await super().process_segwit_input(txi)
async def process_nonsegwit_input(self, txi: TxInputType) -> None: async def process_nonsegwit_input(self, txi: TxInputType) -> None:
@ -32,9 +34,7 @@ class Bitcoinlike(Bitcoin):
txi = await helpers.request_tx_input(self.tx_req, i_sign, self.coin) txi = await helpers.request_tx_input(self.tx_req, i_sign, self.coin)
if not input_is_nonsegwit(txi): if not input_is_nonsegwit(txi):
raise SigningError( raise wire.ProcessError("Transaction has changed during signing")
FailureType.ProcessError, "Transaction has changed during signing"
)
public_key, signature = self.sign_bip143_input(txi) public_key, signature = self.sign_bip143_input(txi)
# if multisig, do a sanity check to ensure we are signing with a key that is included in the multisig # if multisig, do a sanity check to ensure we are signing with a key that is included in the multisig

@ -1,8 +1,9 @@
import gc import gc
from micropython import const from micropython import const
from trezor import wire
from trezor.crypto.hashlib import blake256 from trezor.crypto.hashlib import blake256
from trezor.messages import FailureType, InputScriptType from trezor.messages import InputScriptType
from trezor.messages.SignTx import SignTx from trezor.messages.SignTx import SignTx
from trezor.messages.TransactionType import TransactionType from trezor.messages.TransactionType import TransactionType
from trezor.messages.TxInputType import TxInputType from trezor.messages.TxInputType import TxInputType
@ -11,9 +12,11 @@ from trezor.messages.TxOutputType import TxOutputType
from trezor.utils import HashWriter, ensure from trezor.utils import HashWriter, ensure
from apps.common import coininfo, seed from apps.common import coininfo, seed
from apps.wallet.sign_tx import addresses, helpers, multisig, progress, scripts, writers
from apps.wallet.sign_tx.bitcoin import Bitcoin from .. import multisig, scripts, writers
from apps.wallet.sign_tx.common import SigningError, ecdsa_sign from ..common import ecdsa_hash_pubkey, ecdsa_sign
from . import helpers, progress
from .bitcoin import Bitcoin
DECRED_SERIALIZE_FULL = const(0 << 16) DECRED_SERIALIZE_FULL = const(0 << 16)
DECRED_SERIALIZE_NO_WITNESS = const(1 << 16) DECRED_SERIALIZE_NO_WITNESS = const(1 << 16)
@ -60,10 +63,7 @@ class Decred(Bitcoin):
async def confirm_output(self, txo: TxOutputType, script_pubkey: bytes) -> None: async def confirm_output(self, txo: TxOutputType, script_pubkey: bytes) -> None:
if txo.decred_script_version != 0: if txo.decred_script_version != 0:
raise SigningError( raise wire.ActionCancelled("Cannot send to output with script version != 0")
FailureType.ActionCancelled,
"Cannot send to output with script version != 0",
)
await super().confirm_output(txo, script_pubkey) await super().confirm_output(txo, script_pubkey)
self.write_tx_output(self.serialized_tx, txo, script_pubkey) self.write_tx_output(self.serialized_tx, txo, script_pubkey)
@ -90,10 +90,10 @@ class Decred(Bitcoin):
) )
elif txi_sign.script_type == InputScriptType.SPENDADDRESS: elif txi_sign.script_type == InputScriptType.SPENDADDRESS:
prev_pkscript = scripts.output_script_p2pkh( prev_pkscript = scripts.output_script_p2pkh(
addresses.ecdsa_hash_pubkey(key_sign_pub, self.coin) ecdsa_hash_pubkey(key_sign_pub, self.coin)
) )
else: else:
raise SigningError("Unsupported input script type") raise wire.DataError("Unsupported input script type")
h_witness = self.create_hash_writer() h_witness = self.create_hash_writer()
writers.write_uint32( writers.write_uint32(
@ -138,10 +138,7 @@ class Decred(Bitcoin):
def check_prevtx_output(self, txo_bin: TxOutputBinType) -> None: def check_prevtx_output(self, txo_bin: TxOutputBinType) -> None:
if txo_bin.decred_script_version != 0: if txo_bin.decred_script_version != 0:
raise SigningError( raise wire.ProcessError("Cannot use utxo that has script_version != 0")
FailureType.ProcessError,
"Cannot use utxo that has script_version != 0",
)
def hash143_add_input(self, txi: TxInputType) -> None: def hash143_add_input(self, txi: TxInputType) -> None:
writers.write_tx_input_decred(self.h_prefix, txi) writers.write_tx_input_decred(self.h_prefix, txi)

@ -1,7 +1,7 @@
import gc import gc
from trezor import utils from trezor import utils, wire
from trezor.messages import FailureType, InputScriptType, OutputScriptType from trezor.messages import InputScriptType, OutputScriptType
from trezor.messages.RequestType import ( from trezor.messages.RequestType import (
TXEXTRADATA, TXEXTRADATA,
TXFINISHED, TXFINISHED,
@ -16,8 +16,7 @@ from trezor.messages.TxOutputBinType import TxOutputBinType
from trezor.messages.TxOutputType import TxOutputType from trezor.messages.TxOutputType import TxOutputType
from trezor.messages.TxRequest import TxRequest from trezor.messages.TxRequest import TxRequest
from .common import SigningError from ..writers import TX_HASH_SIZE
from .writers import TX_HASH_SIZE
from apps.common.coininfo import CoinInfo from apps.common.coininfo import CoinInfo
@ -195,11 +194,11 @@ def sanitize_sign_tx(tx: SignTx, coin: CoinInfo) -> SignTx:
if coin.decred or coin.overwintered: if coin.decred or coin.overwintered:
tx.expiry = tx.expiry if tx.expiry is not None else 0 tx.expiry = tx.expiry if tx.expiry is not None else 0
elif tx.expiry: elif tx.expiry:
raise SigningError(FailureType.DataError, "Expiry not enabled on this coin.") raise wire.DataError("Expiry not enabled on this coin.")
if coin.timestamp and not tx.timestamp: if coin.timestamp and not tx.timestamp:
raise SigningError(FailureType.DataError, "Timestamp must be set.") raise wire.DataError("Timestamp must be set.")
elif not coin.timestamp and tx.timestamp: elif not coin.timestamp and tx.timestamp:
raise SigningError(FailureType.DataError, "Timestamp not enabled on this coin.") raise wire.DataError("Timestamp not enabled on this coin.")
return tx return tx
@ -211,17 +210,15 @@ def sanitize_tx_meta(tx: TransactionType, coin: CoinInfo) -> TransactionType:
if coin.extra_data: if coin.extra_data:
tx.extra_data_len = tx.extra_data_len if tx.extra_data_len is not None else 0 tx.extra_data_len = tx.extra_data_len if tx.extra_data_len is not None else 0
elif tx.extra_data_len: elif tx.extra_data_len:
raise SigningError( raise wire.DataError("Extra data not enabled on this coin.")
FailureType.DataError, "Extra data not enabled on this coin."
)
if coin.decred or coin.overwintered: if coin.decred or coin.overwintered:
tx.expiry = tx.expiry if tx.expiry is not None else 0 tx.expiry = tx.expiry if tx.expiry is not None else 0
elif tx.expiry: elif tx.expiry:
raise SigningError(FailureType.DataError, "Expiry not enabled on this coin.") raise wire.DataError("Expiry not enabled on this coin.")
if coin.timestamp and not tx.timestamp: if coin.timestamp and not tx.timestamp:
raise SigningError(FailureType.DataError, "Timestamp must be set.") raise wire.DataError("Timestamp must be set.")
elif not coin.timestamp and tx.timestamp: elif not coin.timestamp and tx.timestamp:
raise SigningError(FailureType.DataError, "Timestamp not enabled on this coin.") raise wire.DataError("Timestamp not enabled on this coin.")
return tx return tx
@ -232,29 +229,18 @@ def sanitize_tx_input(tx: TransactionType, coin: CoinInfo) -> TxInputType:
if txi.sequence is None: if txi.sequence is None:
txi.sequence = 0xFFFFFFFF txi.sequence = 0xFFFFFFFF
if txi.prev_hash is None or len(txi.prev_hash) != TX_HASH_SIZE: if txi.prev_hash is None or len(txi.prev_hash) != TX_HASH_SIZE:
raise SigningError(FailureType.DataError, "Provided prev_hash is invalid.") raise wire.DataError("Provided prev_hash is invalid.")
if txi.multisig and txi.script_type not in MULTISIG_INPUT_SCRIPT_TYPES: if txi.multisig and txi.script_type not in MULTISIG_INPUT_SCRIPT_TYPES:
raise SigningError( raise wire.DataError("Multisig field provided but not expected.")
FailureType.DataError, "Multisig field provided but not expected.",
)
if txi.address_n and txi.script_type not in INTERNAL_INPUT_SCRIPT_TYPES: if txi.address_n and txi.script_type not in INTERNAL_INPUT_SCRIPT_TYPES:
raise SigningError( raise wire.DataError("Input's address_n provided but not expected.")
FailureType.DataError, "Input's address_n provided but not expected.",
)
if not coin.decred and txi.decred_tree is not None: if not coin.decred and txi.decred_tree is not None:
raise SigningError( raise wire.DataError("Decred details provided but Decred coin not specified.")
FailureType.DataError,
"Decred details provided but Decred coin not specified.",
)
if txi.script_type in SEGWIT_INPUT_SCRIPT_TYPES: if txi.script_type in SEGWIT_INPUT_SCRIPT_TYPES:
if not coin.segwit: if not coin.segwit:
raise SigningError( raise wire.DataError("Segwit not enabled on this coin")
FailureType.DataError, "Segwit not enabled on this coin",
)
if txi.amount is None: if txi.amount is None:
raise SigningError( raise wire.DataError("Segwit input without amount")
FailureType.DataError, "Segwit input without amount",
)
_sanitize_decred(txi, coin) _sanitize_decred(txi, coin)
return txi return txi
@ -263,35 +249,24 @@ def sanitize_tx_input(tx: TransactionType, coin: CoinInfo) -> TxInputType:
def sanitize_tx_output(tx: TransactionType, coin: CoinInfo) -> TxOutputType: def sanitize_tx_output(tx: TransactionType, coin: CoinInfo) -> TxOutputType:
txo = tx.outputs[0] txo = tx.outputs[0]
if txo.multisig and txo.script_type not in MULTISIG_OUTPUT_SCRIPT_TYPES: if txo.multisig and txo.script_type not in MULTISIG_OUTPUT_SCRIPT_TYPES:
raise SigningError( raise wire.DataError("Multisig field provided but not expected.")
FailureType.DataError, "Multisig field provided but not expected.",
)
if txo.address_n and txo.script_type not in CHANGE_OUTPUT_SCRIPT_TYPES: if txo.address_n and txo.script_type not in CHANGE_OUTPUT_SCRIPT_TYPES:
raise SigningError( raise wire.DataError("Output's address_n provided but not expected.")
FailureType.DataError, "Output's address_n provided but not expected.",
)
if txo.script_type == OutputScriptType.PAYTOOPRETURN: if txo.script_type == OutputScriptType.PAYTOOPRETURN:
# op_return output # op_return output
if txo.amount != 0: if txo.amount != 0:
raise SigningError( raise wire.DataError("OP_RETURN output with non-zero amount")
FailureType.DataError, "OP_RETURN output with non-zero amount"
)
if txo.address or txo.address_n or txo.multisig: if txo.address or txo.address_n or txo.multisig:
raise SigningError( raise wire.DataError("OP_RETURN output with address or multisig")
FailureType.DataError, "OP_RETURN output with address or multisig"
)
else: else:
if txo.op_return_data: if txo.op_return_data:
raise SigningError( raise wire.DataError(
FailureType.DataError, "OP RETURN data provided but not OP RETURN script type."
"OP RETURN data provided but not OP RETURN script type.",
) )
if txo.address_n and txo.address: if txo.address_n and txo.address:
raise SigningError( raise wire.DataError("Both address and address_n provided.")
FailureType.DataError, "Both address and address_n provided."
)
if not txo.address_n and not txo.address: if not txo.address_n and not txo.address:
raise SigningError(FailureType.DataError, "Missing address") raise wire.DataError("Missing address")
_sanitize_decred(txo, coin) _sanitize_decred(txo, coin)
@ -312,7 +287,6 @@ def _sanitize_decred(
tx.decred_script_version = 0 tx.decred_script_version = 0
else: else:
if tx.decred_script_version is not None: if tx.decred_script_version is not None:
raise SigningError( raise wire.DataError(
FailureType.DataError, "Decred details provided but Decred coin not specified."
"Decred details provided but Decred coin not specified.",
) )

@ -10,7 +10,7 @@ from trezor.utils import chunks
from apps.common import coininfo from apps.common import coininfo
if False: if False:
from typing import Iterator, List from typing import Iterator
from trezor import wire from trezor import wire
_LOCKTIME_TIMESTAMP_MIN_VALUE = const(500000000) _LOCKTIME_TIMESTAMP_MIN_VALUE = const(500000000)
@ -30,10 +30,11 @@ def split_op_return(data: str) -> Iterator[str]:
async def confirm_output( async def confirm_output(
ctx: wire.Context, output: TxOutputType, coin: coininfo.CoinInfo ctx: wire.Context, output: TxOutputType, coin: coininfo.CoinInfo
) -> bool: ) -> None:
from trezor.ui.text import Text from trezor.ui.text import Text
from apps.common.confirm import confirm from apps.common.confirm import require_confirm
from apps.wallet.sign_tx import addresses, omni from . import omni
from .. import addresses
if output.script_type == OutputScriptType.PAYTOOPRETURN: if output.script_type == OutputScriptType.PAYTOOPRETURN:
data = output.op_return_data data = output.op_return_data
@ -54,50 +55,39 @@ async def confirm_output(
text = Text("Confirm sending", ui.ICON_SEND, ui.GREEN) text = Text("Confirm sending", ui.ICON_SEND, ui.GREEN)
text.normal(format_coin_amount(output.amount, coin) + " to") text.normal(format_coin_amount(output.amount, coin) + " to")
text.mono(*split_address(address_short)) text.mono(*split_address(address_short))
return await confirm(ctx, text, ButtonRequestType.ConfirmOutput) await require_confirm(ctx, text, ButtonRequestType.ConfirmOutput)
async def confirm_total( async def confirm_total(
ctx: wire.Context, spending: int, fee: int, coin: coininfo.CoinInfo ctx: wire.Context, spending: int, fee: int, coin: coininfo.CoinInfo
) -> bool: ) -> None:
from trezor.ui.text import Text from trezor.ui.text import Text
from apps.common.confirm import hold_to_confirm from apps.common.confirm import require_hold_to_confirm
text = Text("Confirm transaction", ui.ICON_SEND, ui.GREEN) text = Text("Confirm transaction", ui.ICON_SEND, ui.GREEN)
text.normal("Total amount:") text.normal("Total amount:")
text.bold(format_coin_amount(spending, coin)) text.bold(format_coin_amount(spending, coin))
text.normal("including fee:") text.normal("including fee:")
text.bold(format_coin_amount(fee, coin)) text.bold(format_coin_amount(fee, coin))
return await hold_to_confirm(ctx, text, ButtonRequestType.SignTx) await require_hold_to_confirm(ctx, text, ButtonRequestType.SignTx)
async def confirm_feeoverthreshold( async def confirm_feeoverthreshold(
ctx: wire.Context, fee: int, coin: coininfo.CoinInfo ctx: wire.Context, fee: int, coin: coininfo.CoinInfo
) -> bool: ) -> None:
from trezor.ui.text import Text from trezor.ui.text import Text
from apps.common.confirm import confirm from apps.common.confirm import require_confirm
text = Text("High fee", ui.ICON_SEND, ui.GREEN) text = Text("High fee", ui.ICON_SEND, ui.GREEN)
text.normal("The fee of") text.normal("The fee of")
text.bold(format_coin_amount(fee, coin)) text.bold(format_coin_amount(fee, coin))
text.normal("is unexpectedly high.", "Continue?") text.normal("is unexpectedly high.", "Continue?")
return await confirm(ctx, text, ButtonRequestType.FeeOverThreshold) await require_confirm(ctx, text, ButtonRequestType.FeeOverThreshold)
async def confirm_foreign_address( async def confirm_nondefault_locktime(ctx: wire.Context, lock_time: int) -> None:
ctx: wire.Context, address_n: List[int], coin: coininfo.CoinInfo
) -> bool:
from trezor.ui.text import Text from trezor.ui.text import Text
from apps.common.confirm import confirm from apps.common.confirm import require_confirm
text = Text("Confirm sending", ui.ICON_SEND, ui.RED)
text.normal("Trying to spend", "coins from another chain.", "Continue?")
return await confirm(ctx, text, ButtonRequestType.SignTx)
async def confirm_nondefault_locktime(ctx: wire.Context, lock_time: int) -> bool:
from trezor.ui.text import Text
from apps.common.confirm import confirm
text = Text("Confirm locktime", ui.ICON_SEND, ui.GREEN) text = Text("Confirm locktime", ui.ICON_SEND, ui.GREEN)
text.normal("Locktime for this transaction is set to") text.normal("Locktime for this transaction is set to")
@ -107,4 +97,4 @@ async def confirm_nondefault_locktime(ctx: wire.Context, lock_time: int) -> bool
text.normal("timestamp:") text.normal("timestamp:")
text.bold(str(lock_time)) text.bold(str(lock_time))
text.normal("Continue?") text.normal("Continue?")
return await confirm(ctx, text, ButtonRequestType.SignTx) await require_confirm(ctx, text, ButtonRequestType.SignTx)

@ -1,12 +1,11 @@
from micropython import const from micropython import const
from trezor.messages import FailureType from trezor import wire
from trezor.messages.TxInputType import TxInputType from trezor.messages.TxInputType import TxInputType
from trezor.messages.TxOutputType import TxOutputType from trezor.messages.TxOutputType import TxOutputType
from trezor.utils import ensure from trezor.utils import ensure
from apps.wallet.sign_tx import multisig from .. import multisig
from apps.wallet.sign_tx.common import SigningError
if False: if False:
from typing import Any, Union from typing import Any, Union
@ -71,9 +70,7 @@ class MatchChecker:
# All added inputs had a matching attribute, allowing a change-output. # All added inputs had a matching attribute, allowing a change-output.
# Ensure that this input still has the same attribute. # Ensure that this input still has the same attribute.
if self.attribute != self.attribute_from_tx(txi): if self.attribute != self.attribute_from_tx(txi):
raise SigningError( raise wire.ProcessError("Transaction has changed during signing")
FailureType.ProcessError, "Transaction has changed during signing"
)
def output_matches(self, txo: TxOutputType) -> bool: def output_matches(self, txo: TxOutputType) -> bool:
self.read_only = True self.read_only = True

@ -1,8 +1,9 @@
import ustruct as struct import ustruct as struct
from micropython import const from micropython import const
from trezor import wire
from trezor.crypto.hashlib import blake2b from trezor.crypto.hashlib import blake2b
from trezor.messages import FailureType, InputScriptType from trezor.messages import InputScriptType
from trezor.messages.SignTx import SignTx from trezor.messages.SignTx import SignTx
from trezor.messages.TransactionType import TransactionType from trezor.messages.TransactionType import TransactionType
from trezor.messages.TxInputType import TxInputType from trezor.messages.TxInputType import TxInputType
@ -10,12 +11,10 @@ from trezor.utils import HashWriter, ensure
from apps.common.coininfo import CoinInfo from apps.common.coininfo import CoinInfo
from apps.common.seed import Keychain from apps.common.seed import Keychain
from apps.wallet.sign_tx import helpers
from apps.wallet.sign_tx.bitcoinlike import Bitcoinlike from ..multisig import multisig_get_pubkeys
from apps.wallet.sign_tx.common import SigningError from ..scripts import output_script_multisig, output_script_p2pkh
from apps.wallet.sign_tx.multisig import multisig_get_pubkeys from ..writers import (
from apps.wallet.sign_tx.scripts import output_script_multisig, output_script_p2pkh
from apps.wallet.sign_tx.writers import (
TX_HASH_SIZE, TX_HASH_SIZE,
get_tx_hash, get_tx_hash,
write_bytes_fixed, write_bytes_fixed,
@ -25,10 +24,12 @@ from apps.wallet.sign_tx.writers import (
write_uint64, write_uint64,
write_varint, write_varint,
) )
from . import helpers
from .bitcoinlike import Bitcoinlike
if False: if False:
from typing import Union from typing import Union
from apps.wallet.sign_tx.writers import Writer from .writers import Writer
OVERWINTERED = const(0x80000000) OVERWINTERED = const(0x80000000)
@ -45,10 +46,7 @@ class Overwintered(Bitcoinlike):
if not self.tx.branch_id: if not self.tx.branch_id:
self.tx.branch_id = 0x76B809BB # Sapling self.tx.branch_id = 0x76B809BB # Sapling
else: else:
raise SigningError( raise wire.DataError("Unsupported version for overwintered transaction")
FailureType.DataError,
"Unsupported version for overwintered transaction",
)
async def step7_finish(self) -> None: async def step7_finish(self) -> None:
self.write_tx_footer(self.serialized_tx, self.tx) self.write_tx_footer(self.serialized_tx, self.tx)
@ -63,10 +61,7 @@ class Overwintered(Bitcoinlike):
write_varint(self.serialized_tx, 0) # nShieldedOutput write_varint(self.serialized_tx, 0) # nShieldedOutput
write_varint(self.serialized_tx, 0) # nJoinSplit write_varint(self.serialized_tx, 0) # nJoinSplit
else: else:
raise SigningError( raise wire.DataError("Unsupported version for overwintered transaction")
FailureType.DataError,
"Unsupported version for overwintered transaction",
)
await helpers.request_tx_finish(self.tx_req) await helpers.request_tx_finish(self.tx_req)
@ -136,10 +131,7 @@ class Overwintered(Bitcoinlike):
# 12. nHashType # 12. nHashType
write_uint32(h_preimage, self.get_hash_type()) write_uint32(h_preimage, self.get_hash_type())
else: else:
raise SigningError( raise wire.DataError("Unsupported version for overwintered transaction")
FailureType.DataError,
"Unsupported version for overwintered transaction",
)
# 10a /13a. outpoint # 10a /13a. outpoint
write_bytes_reversed(h_preimage, txi.prev_hash, TX_HASH_SIZE) write_bytes_reversed(h_preimage, txi.prev_hash, TX_HASH_SIZE)
@ -170,6 +162,4 @@ def derive_script_code(txi: TxInputType, pubkeyhash: bytes) -> bytearray:
return output_script_p2pkh(pubkeyhash) return output_script_p2pkh(pubkeyhash)
else: else:
raise SigningError( raise wire.DataError("Unknown input script type for zip143 script code")
FailureType.DataError, "Unknown input script type for zip143 script code"
)

@ -3,9 +3,7 @@ from trezor.crypto.curve import secp256k1
from trezor.messages.InputScriptType import SPENDADDRESS, SPENDP2SHWITNESS, SPENDWITNESS from trezor.messages.InputScriptType import SPENDADDRESS, SPENDP2SHWITNESS, SPENDWITNESS
from trezor.messages.Success import Success from trezor.messages.Success import Success
from apps.common import coins from .addresses import (
from apps.common.signverify import message_digest, require_confirm_verify_message
from apps.wallet.sign_tx.addresses import (
address_p2wpkh, address_p2wpkh,
address_p2wpkh_in_p2sh, address_p2wpkh_in_p2sh,
address_pkh, address_pkh,
@ -13,6 +11,9 @@ from apps.wallet.sign_tx.addresses import (
address_to_cashaddr, address_to_cashaddr,
) )
from apps.common import coins
from apps.common.signverify import message_digest, require_confirm_verify_message
async def verify_message(ctx, msg): async def verify_message(ctx, msg):
message = msg.message message = msg.message

@ -4,9 +4,9 @@ from trezor import utils, wire
from trezor.crypto.hashlib import blake256, sha256 from trezor.crypto.hashlib import blake256, sha256
from trezor.ui.text import Text from trezor.ui.text import Text
from apps.bitcoin.writers import write_varint
from apps.common.confirm import require_confirm from apps.common.confirm import require_confirm
from apps.common.layout import split_address from apps.common.layout import split_address
from apps.wallet.sign_tx.writers import write_varint
if False: if False:
from typing import List from typing import List

@ -3,12 +3,12 @@ from trezor.crypto.hashlib import sha256
from trezor.messages.LiskMessageSignature import LiskMessageSignature from trezor.messages.LiskMessageSignature import LiskMessageSignature
from trezor.utils import HashWriter from trezor.utils import HashWriter
from apps.bitcoin.sign_tx.writers import write_varint
from apps.common import paths from apps.common import paths
from apps.common.seed import with_slip44_keychain from apps.common.seed import with_slip44_keychain
from apps.common.signverify import require_confirm_sign_message from apps.common.signverify import require_confirm_sign_message
from apps.lisk import CURVE, SLIP44_ID from apps.lisk import CURVE, SLIP44_ID
from apps.lisk.helpers import validate_full_path from apps.lisk.helpers import validate_full_path
from apps.wallet.sign_tx.writers import write_varint
def message_digest(message): def message_digest(message):

@ -0,0 +1,9 @@
from trezor import wire
from trezor.messages import MessageType
def boot() -> None:
wire.add(MessageType.GetEntropy, __name__, "get_entropy")
wire.add(MessageType.SignIdentity, __name__, "sign_identity")
wire.add(MessageType.GetECDHSessionKey, __name__, "get_ecdh_session_key")
wire.add(MessageType.CipherKeyValue, __name__, "cipher_key_value")

@ -6,13 +6,11 @@ from trezor.messages.ECDHSessionKey import ECDHSessionKey
from trezor.ui.text import Text from trezor.ui.text import Text
from trezor.utils import chunks from trezor.utils import chunks
from .sign_identity import serialize_identity, serialize_identity_without_proto
from apps.common import HARDENED from apps.common import HARDENED
from apps.common.confirm import require_confirm from apps.common.confirm import require_confirm
from apps.common.seed import get_keychain from apps.common.seed import get_keychain
from apps.wallet.sign_identity import (
serialize_identity,
serialize_identity_without_proto,
)
async def get_ecdh_session_key(ctx, msg): async def get_ecdh_session_key(ctx, msg):

@ -1,12 +0,0 @@
from trezor.crypto import bip32, der
from trezor.crypto.curve import secp256k1
class SigningError(ValueError):
pass
def ecdsa_sign(node: bip32.HDNode, digest: bytes) -> bytes:
sig = secp256k1.sign(node.private_key(), digest)
sigder = der.encode_seq((sig[1:33], sig[33:65]))
return sigder

@ -17,7 +17,8 @@ def _boot_apps() -> None:
# load applications # load applications
import apps.homescreen import apps.homescreen
import apps.management import apps.management
import apps.wallet import apps.bitcoin
import apps.misc
if not utils.BITCOIN_ONLY: if not utils.BITCOIN_ONLY:
import apps.ethereum import apps.ethereum
@ -38,7 +39,8 @@ def _boot_apps() -> None:
# boot applications # boot applications
apps.homescreen.boot() apps.homescreen.boot()
apps.management.boot() apps.management.boot()
apps.wallet.boot() apps.bitcoin.boot()
apps.misc.boot()
if not utils.BITCOIN_ONLY: if not utils.BITCOIN_ONLY:
apps.ethereum.boot() apps.ethereum.boot()
apps.lisk.boot() apps.lisk.boot()

@ -2,12 +2,12 @@ from common import *
from trezor.crypto import bip32, bip39 from trezor.crypto import bip32, bip39
from trezor.utils import HashWriter from trezor.utils import HashWriter
from apps.wallet.sign_tx.addresses import validate_full_path, validate_path_for_bitcoin_public_key from apps.bitcoin.addresses import validate_full_path, validate_path_for_bitcoin_public_key
from apps.common.paths import HARDENED from apps.common.paths import HARDENED
from apps.common import coins from apps.common import coins
from apps.wallet.sign_tx import scripts from apps.bitcoin import scripts
from apps.wallet.sign_tx.addresses import * from apps.bitcoin.addresses import *
from apps.wallet.sign_tx.writers import * from apps.bitcoin.writers import *
def node_derive(root, path): def node_derive(root, path):
@ -111,7 +111,7 @@ class TestAddress(unittest.TestCase):
self.assertEqual(address, '39bgKC7RFbpoCRbtD5KEdkYKtNyhpsNa3Z') self.assertEqual(address, '39bgKC7RFbpoCRbtD5KEdkYKtNyhpsNa3Z')
for invalid_m in (-1, 0, len(pubkeys) + 1, 16): for invalid_m in (-1, 0, len(pubkeys) + 1, 16):
with self.assertRaises(scripts.ScriptsError): with self.assertRaises(wire.DataError):
address_multisig_p2sh(pubkeys, invalid_m, coin) address_multisig_p2sh(pubkeys, invalid_m, coin)
def test_multisig_address_p2wsh_in_p2sh(self): def test_multisig_address_p2wsh_in_p2sh(self):

@ -1,7 +1,7 @@
from common import * from common import *
from apps.wallet.sign_tx.common import * from apps.bitcoin.common import *
from apps.wallet.sign_tx.addresses import * from apps.bitcoin.addresses import *
from apps.common import coins from apps.common import coins
from trezor.crypto import bip32, bip39 from trezor.crypto import bip32, bip39

@ -1,8 +1,8 @@
from common import * from common import *
from apps.wallet.sign_tx.scripts import output_derive_script from apps.bitcoin.scripts import output_derive_script
from apps.wallet.sign_tx.bitcoin import Bitcoin from apps.bitcoin.sign_tx.bitcoin import Bitcoin
from apps.wallet.sign_tx.writers import get_tx_hash from apps.bitcoin.writers import get_tx_hash
from apps.common import coins from apps.common import coins
from trezor.messages.SignTx import SignTx from trezor.messages.SignTx import SignTx
from trezor.messages.TxInputType import TxInputType from trezor.messages.TxInputType import TxInputType

@ -1,8 +1,8 @@
from common import * from common import *
from apps.wallet.sign_tx.scripts import output_derive_script from apps.bitcoin.scripts import output_derive_script
from apps.wallet.sign_tx.bitcoin import Bitcoin from apps.bitcoin.sign_tx.bitcoin import Bitcoin
from apps.wallet.sign_tx.writers import get_tx_hash from apps.bitcoin.writers import get_tx_hash
from apps.common import coins from apps.common import coins
from trezor.messages.SignTx import SignTx from trezor.messages.SignTx import SignTx
from trezor.messages.TxInputType import TxInputType from trezor.messages.TxInputType import TxInputType

@ -13,12 +13,12 @@ from trezor.messages.TxRequestDetailsType import TxRequestDetailsType
from trezor.messages.TxRequestSerializedType import TxRequestSerializedType from trezor.messages.TxRequestSerializedType import TxRequestSerializedType
from trezor.messages import InputScriptType from trezor.messages import InputScriptType
from trezor.messages import OutputScriptType from trezor.messages import OutputScriptType
from trezor import wire
from apps.common import coins from apps.common import coins
from apps.common.seed import Keychain from apps.common.seed import Keychain
from apps.wallet.keychain import get_namespaces_for_coin from apps.bitcoin.keychain import get_namespaces_for_coin
from apps.wallet.sign_tx import helpers, bitcoin from apps.bitcoin.sign_tx import helpers, bitcoin
from apps.wallet.sign_tx.scripts import ScriptsError
EMPTY_SERIALIZED = TxRequestSerializedType(serialized_tx=bytearray()) EMPTY_SERIALIZED = TxRequestSerializedType(serialized_tx=bytearray())
@ -272,7 +272,7 @@ class TestSignSegwitTxNativeP2WPKH(unittest.TestCase):
signer = bitcoin.Bitcoin(tx, keychain, coin).signer() signer = bitcoin.Bitcoin(tx, keychain, coin).signer()
for request, response in chunks(messages, 2): for request, response in chunks(messages, 2):
if response is None: if response is None:
with self.assertRaises(ScriptsError): with self.assertRaises(wire.DataError):
signer.send(request) signer.send(request)
else: else:
self.assertEqual(signer.send(request), response) self.assertEqual(signer.send(request), response)

@ -16,8 +16,8 @@ from trezor.messages import OutputScriptType
from apps.common import coins from apps.common import coins
from apps.common.seed import Keychain from apps.common.seed import Keychain
from apps.wallet.keychain import get_namespaces_for_coin from apps.bitcoin.keychain import get_namespaces_for_coin
from apps.wallet.sign_tx import bitcoinlike, helpers from apps.bitcoin.sign_tx import bitcoinlike, helpers
EMPTY_SERIALIZED = TxRequestSerializedType(serialized_tx=bytearray()) EMPTY_SERIALIZED = TxRequestSerializedType(serialized_tx=bytearray())

@ -13,11 +13,12 @@ from trezor.messages.TxRequestDetailsType import TxRequestDetailsType
from trezor.messages.TxRequestSerializedType import TxRequestSerializedType from trezor.messages.TxRequestSerializedType import TxRequestSerializedType
from trezor.messages import InputScriptType from trezor.messages import InputScriptType
from trezor.messages import OutputScriptType from trezor.messages import OutputScriptType
from trezor import wire
from apps.common import coins from apps.common import coins
from apps.common.seed import Keychain from apps.common.seed import Keychain
from apps.wallet.keychain import get_namespaces_for_coin from apps.bitcoin.keychain import get_namespaces_for_coin
from apps.wallet.sign_tx import bitcoin, common, helpers from apps.bitcoin.sign_tx import bitcoin, helpers
EMPTY_SERIALIZED = TxRequestSerializedType(serialized_tx=bytearray()) EMPTY_SERIALIZED = TxRequestSerializedType(serialized_tx=bytearray())
@ -341,8 +342,8 @@ class TestSignSegwitTxP2WPKHInP2SH(unittest.TestCase):
i = 0 i = 0
messages_count = int(len(messages) / 2) messages_count = int(len(messages) / 2)
for request, response in chunks(messages, 2): for request, response in chunks(messages, 2):
if i == messages_count - 1: # last message should throw SigningError if i == messages_count - 1: # last message should throw wire.Error
self.assertRaises(common.SigningError, signer.send, request) self.assertRaises(wire.ProcessError, signer.send, request)
else: else:
self.assertEqual(signer.send(request), response) self.assertEqual(signer.send(request), response)
i += 1 i += 1

@ -16,8 +16,8 @@ from trezor.messages import OutputScriptType
from apps.common import coins from apps.common import coins
from apps.common.seed import Keychain from apps.common.seed import Keychain
from apps.wallet.keychain import get_namespaces_for_coin from apps.bitcoin.keychain import get_namespaces_for_coin
from apps.wallet.sign_tx import bitcoinlike, helpers from apps.bitcoin.sign_tx import bitcoinlike, helpers
EMPTY_SERIALIZED = TxRequestSerializedType(serialized_tx=bytearray()) EMPTY_SERIALIZED = TxRequestSerializedType(serialized_tx=bytearray())

@ -3,8 +3,7 @@ from common import *
from trezor.messages.TxInputType import TxInputType from trezor.messages.TxInputType import TxInputType
from trezor.messages import InputScriptType from trezor.messages import InputScriptType
from apps.common import coins from apps.bitcoin import writers
from apps.wallet.sign_tx import writers
class TestWriters(unittest.TestCase): class TestWriters(unittest.TestCase):

@ -16,7 +16,7 @@ from trezor.messages import OutputScriptType
from apps.common import coins from apps.common import coins
from apps.common.seed import Keychain from apps.common.seed import Keychain
from apps.wallet.sign_tx import bitcoin, helpers from apps.bitcoin.sign_tx import bitcoin, helpers
EMPTY_SERIALIZED = TxRequestSerializedType(serialized_tx=bytearray()) EMPTY_SERIALIZED = TxRequestSerializedType(serialized_tx=bytearray())

@ -1,6 +1,6 @@
from common import * from common import *
from apps.wallet.sign_tx.omni import is_valid, parse from apps.bitcoin.sign_tx.omni import is_valid, parse
class TestSignTxOmni(unittest.TestCase): class TestSignTxOmni(unittest.TestCase):

@ -16,8 +16,8 @@ from trezor.messages import OutputScriptType
from apps.common import coins from apps.common import coins
from apps.common.seed import Keychain from apps.common.seed import Keychain
from apps.wallet.keychain import get_namespaces_for_coin from apps.bitcoin.keychain import get_namespaces_for_coin
from apps.wallet.sign_tx import bitcoin, helpers from apps.bitcoin.sign_tx import bitcoin, helpers
EMPTY_SERIALIZED = TxRequestSerializedType(serialized_tx=bytearray()) EMPTY_SERIALIZED = TxRequestSerializedType(serialized_tx=bytearray())

@ -16,8 +16,8 @@ from trezor.messages import OutputScriptType
from apps.common import coins from apps.common import coins
from apps.common.seed import Keychain from apps.common.seed import Keychain
from apps.wallet.keychain import get_namespaces_for_coin from apps.bitcoin.keychain import get_namespaces_for_coin
from apps.wallet.sign_tx import bitcoinlike, helpers from apps.bitcoin.sign_tx import bitcoinlike, helpers
EMPTY_SERIALIZED = TxRequestSerializedType(serialized_tx=bytearray()) EMPTY_SERIALIZED = TxRequestSerializedType(serialized_tx=bytearray())

@ -6,8 +6,8 @@ from trezor.messages import OutputScriptType
from trezor.crypto import bip32, bip39 from trezor.crypto import bip32, bip39
from apps.common import coins from apps.common import coins
from apps.wallet.sign_tx.tx_weight import * from apps.bitcoin.sign_tx.tx_weight import *
from apps.wallet.sign_tx.scripts import output_derive_script from apps.bitcoin.scripts import output_derive_script
class TestCalculateTxWeight(unittest.TestCase): class TestCalculateTxWeight(unittest.TestCase):

@ -5,10 +5,10 @@ from trezor.messages.TxInputType import TxInputType
from trezor.messages.TxOutputBinType import TxOutputBinType from trezor.messages.TxOutputBinType import TxOutputBinType
from apps.common import coins from apps.common import coins
from apps.wallet.sign_tx.writers import get_tx_hash from apps.bitcoin.writers import get_tx_hash
if not utils.BITCOIN_ONLY: if not utils.BITCOIN_ONLY:
from apps.wallet.sign_tx.zcash import Overwintered from apps.bitcoin.sign_tx.zcash import Overwintered
# test vectors inspired from https://github.com/zcash-hackworks/zcash-test-vectors/blob/master/zip_0143.py # test vectors inspired from https://github.com/zcash-hackworks/zcash-test-vectors/blob/master/zip_0143.py

@ -5,10 +5,10 @@ from trezor.messages.TxInputType import TxInputType
from trezor.messages.TxOutputBinType import TxOutputBinType from trezor.messages.TxOutputBinType import TxOutputBinType
from apps.common import coins from apps.common import coins
from apps.wallet.sign_tx.writers import get_tx_hash from apps.bitcoin.writers import get_tx_hash
if not utils.BITCOIN_ONLY: if not utils.BITCOIN_ONLY:
from apps.wallet.sign_tx.zcash import Overwintered from apps.bitcoin.sign_tx.zcash import Overwintered
# test vectors inspired from https://github.com/zcash-hackworks/zcash-test-vectors/blob/master/zip_0243.py # test vectors inspired from https://github.com/zcash-hackworks/zcash-test-vectors/blob/master/zip_0243.py

@ -1,12 +1,10 @@
from common import * from common import *
from storage import cache from storage import cache
from apps.common import HARDENED, coins from apps.common import HARDENED
from apps.common.seed import Keychain, Slip21Node, _path_hardened, get_keychain, with_slip44_keychain from apps.common.seed import Keychain, Slip21Node, _path_hardened, get_keychain, with_slip44_keychain
from apps.wallet.sign_tx import scripts, addresses
from trezor import wire from trezor import wire
from trezor.crypto import bip39 from trezor.crypto import bip39
from trezor.crypto.curve import secp256k1
class TestKeychain(unittest.TestCase): class TestKeychain(unittest.TestCase):

@ -4,7 +4,7 @@ from trezor import wire
from trezor.crypto import bip39 from trezor.crypto import bip39
from apps.common.paths import HARDENED from apps.common.paths import HARDENED
from apps.wallet.keychain import get_keychain_for_coin from apps.bitcoin.keychain import get_keychain_for_coin
class TestBitcoinKeychain(unittest.TestCase): class TestBitcoinKeychain(unittest.TestCase):

@ -6,11 +6,11 @@ Each app has a `boot()` function in the module's \_\_init\_\_ file. This functio
## Example ## Example
This binds the message GetAddress to function `get_address` inside the `apps.wallet` module. This binds the message GetAddress to function `get_address` inside the `apps.bitcoin` module.
```python ```python
from trezor import wire from trezor import wire
from trezor.messages import MessageType from trezor.messages import MessageType
wire.add(MessageType.GetAddress, apps.wallet, "get_address") wire.add(MessageType.GetAddress, apps.bitcoin, "get_address")
``` ```

Loading…
Cancel
Save