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/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/wallet/*/*.py',
SOURCE_PY.extend(Glob(SOURCE_PY_DIR + 'apps/misc/*.py'))
SOURCE_PY.extend(Glob(SOURCE_PY_DIR + 'apps/bitcoin/*.py'))
SOURCE_PY.extend(Glob(SOURCE_PY_DIR + 'apps/bitcoin/*/*.py',
exclude=[
SOURCE_PY_DIR + 'apps/wallet/sign_tx/decred.py',
SOURCE_PY_DIR + 'apps/wallet/sign_tx/zcash.py',
SOURCE_PY_DIR + 'apps/bitcoin/sign_tx/decred.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/wallet/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/decred.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)

@ -460,11 +460,13 @@ if FROZEN:
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/wallet/*.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/bitcoin/*.py'))
SOURCE_PY.extend(Glob(SOURCE_PY_DIR + 'apps/bitcoin/*/*.py',
exclude=[
SOURCE_PY_DIR + 'apps/wallet/sign_tx/decred.py',
SOURCE_PY_DIR + 'apps/wallet/sign_tx/zcash.py',
SOURCE_PY_DIR + 'apps/bitcoin/sign_tx/decred.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/wallet/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/decred.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)

@ -5,10 +5,6 @@ from trezor.messages import MessageType
def boot() -> None:
wire.add(MessageType.GetPublicKey, __name__, "get_public_key")
wire.add(MessageType.GetAddress, __name__, "get_address")
wire.add(MessageType.GetEntropy, __name__, "get_entropy")
wire.add(MessageType.SignTx, __name__, "sign_tx")
wire.add(MessageType.SignMessage, __name__, "sign_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.crypto import base58, bech32, cashaddr
from trezor import wire
from trezor.crypto import base58, cashaddr
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.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.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:
from typing import List
from trezor.crypto import bip32
from trezor.messages.TxInputType import EnumTypeInputScriptType
# supported witness version for bech32 addresses
_BECH32_WITVER = const(0x00)
class AddressError(Exception):
pass
def get_address(
script_type: EnumTypeInputScriptType,
@ -42,11 +32,9 @@ def get_address(
pubkey = node.public_key()
index = multisig_pubkey_index(multisig, pubkey)
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:
raise AddressError(
FailureType.ProcessError, "Multisig not enabled on this coin"
)
raise wire.ProcessError("Multisig not enabled on this coin")
pubkeys = multisig_get_pubkeys(multisig)
address = address_multisig_p2sh(pubkeys, multisig.m, coin)
@ -54,7 +42,7 @@ def get_address(
address = address_to_cashaddr(address, coin)
return address
if script_type == InputScriptType.SPENDMULTISIG:
raise AddressError(FailureType.ProcessError, "Multisig details required")
raise wire.ProcessError("Multisig details required")
# p2pkh
address = node.address(coin.address_type)
@ -64,9 +52,7 @@ def get_address(
elif script_type == InputScriptType.SPENDWITNESS: # native p2wpkh or native p2wsh
if not coin.segwit or not coin.bech32_prefix:
raise AddressError(
FailureType.ProcessError, "Segwit not enabled on this coin"
)
raise wire.ProcessError("Segwit not enabled on this coin")
# native p2wsh multisig
if multisig is not None:
pubkeys = multisig_get_pubkeys(multisig)
@ -79,9 +65,7 @@ def get_address(
script_type == InputScriptType.SPENDP2SHWITNESS
): # p2wpkh or p2wsh nested in p2sh
if not coin.segwit or coin.address_type_p2sh is None:
raise AddressError(
FailureType.ProcessError, "Segwit not enabled on this coin"
)
raise wire.ProcessError("Segwit not enabled on this coin")
# p2wsh multisig nested in p2sh
if multisig is not None:
pubkeys = multisig_get_pubkeys(multisig)
@ -91,14 +75,12 @@ def get_address(
return address_p2wpkh_in_p2sh(node.public_key(), coin)
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:
if coin.address_type_p2sh is None:
raise AddressError(
FailureType.ProcessError, "Multisig not enabled on this coin"
)
raise wire.ProcessError("Multisig not enabled on this coin")
redeem_script = output_script_multisig(pubkeys, m)
redeem_script_hash = coin.script_hash(redeem_script)
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:
if coin.address_type_p2sh is None:
raise AddressError(
FailureType.ProcessError, "Multisig not enabled on this coin"
)
raise wire.ProcessError("Multisig not enabled on this coin")
witness_script = output_script_multisig(pubkeys, m)
witness_script_hash = sha256(witness_script).digest()
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:
if not hrp:
raise AddressError(
FailureType.ProcessError, "Multisig not enabled on this coin"
)
raise wire.ProcessError("Multisig not enabled on this coin")
witness_script = output_script_multisig(pubkeys, m)
witness_script_hash = sha256(witness_script).digest()
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:
pubkeyhash = ecdsa_hash_pubkey(pubkey, coin)
address = bech32.encode(coin.bech32_prefix, _BECH32_WITVER, pubkeyhash)
if address is None:
raise AddressError(FailureType.ProcessError, "Invalid address")
return address
return encode_bech32_address(coin.bech32_prefix, pubkeyhash)
def address_p2wsh(witness_script_hash: bytes, hrp: str) -> str:
address = bech32.encode(hrp, _BECH32_WITVER, 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)
return encode_bech32_address(hrp, witness_script_hash)
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)
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:
if coin.cashaddr_prefix is not None and address.startswith(
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.Address import Address
from . import addresses
from .keychain import with_keychain
from .sign_tx import addresses
from .sign_tx.multisig import multisig_pubkey_index
from .multisig import multisig_pubkey_index
from apps.common.layout import address_n_to_str, show_address, show_qr, show_xpub
from apps.common.paths import validate_path

@ -1,20 +1,16 @@
from trezor import wire
from trezor.crypto import bip32
from trezor.crypto.hashlib import sha256
from trezor.messages import FailureType
from trezor.messages.HDNodeType import HDNodeType
from trezor.messages.MultisigRedeemScriptType import MultisigRedeemScriptType
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:
from typing import List
class MultisigError(ValueError):
pass
def multisig_fingerprint(multisig: MultisigRedeemScriptType) -> bytes:
if multisig.nodes:
pubnodes = multisig.nodes
@ -24,11 +20,11 @@ def multisig_fingerprint(multisig: MultisigRedeemScriptType) -> bytes:
n = len(pubnodes)
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:
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
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):
if multisig_get_pubkey(hd.node, hd.address_n) == pubkey:
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:

@ -1,34 +1,30 @@
from trezor import utils
from trezor import utils, wire
from trezor.crypto import base58, cashaddr
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.TxInputType import TxInputType
from trezor.messages.TxOutputType import TxOutputType
from apps.common import address_type
from apps.common.coininfo import CoinInfo
from apps.common.writers import empty_bytearray
from apps.wallet.sign_tx import addresses
from apps.wallet.sign_tx.multisig import (
from apps.common.writers import empty_bytearray, write_bitcoin_varint
from . import common
from .multisig import (
multisig_get_pubkey_count,
multisig_get_pubkeys,
multisig_pubkey_index,
)
from apps.wallet.sign_tx.writers import (
from .writers import (
write_bytes_fixed,
write_bytes_unchecked,
write_op_push,
write_varint,
)
if False:
from typing import List, Optional
from apps.wallet.sign_tx.writers import Writer
class ScriptsError(ValueError):
pass
from .writers import Writer
def input_derive_script(
@ -54,7 +50,7 @@ def input_derive_script(
return input_script_p2wsh_in_p2sh(witness_script_hash)
# 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:
# 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
)
else:
raise ScriptsError(FailureType.ProcessError, "Invalid script type")
raise wire.ProcessError("Invalid script type")
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):
# 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)
if (
@ -89,13 +85,13 @@ def output_derive_script(txo: TxOutputType, coin: CoinInfo) -> bytes:
elif version == cashaddr.ADDRESS_TYPE_P2SH:
version = coin.address_type_p2sh
else:
raise ScriptsError("Unknown cashaddr address type")
raise wire.DataError("Unknown cashaddr address type")
raw_address = bytes([version]) + data
else:
try:
raw_address = base58.decode_check(txo.address, coin.b58_hash)
except ValueError:
raise ScriptsError(FailureType.DataError, "Invalid address")
raise wire.DataError("Invalid address")
if address_type.check(coin.address_type, raw_address):
# p2pkh
@ -108,7 +104,7 @@ def output_derive_script(txo: TxOutputType, coin: CoinInfo) -> bytes:
script = output_script_p2sh(scripthash)
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
@ -131,9 +127,7 @@ def bip143_derive_script_code(txi: TxInputType, pubkeyhash: bytes) -> bytearray:
return output_script_p2pkh(pubkeyhash)
else:
raise ScriptsError(
FailureType.DataError, "Unknown input script type for bip143 script code",
)
raise wire.DataError("Unknown input script type for bip143 script code")
# P2PKH, P2SH
@ -238,7 +232,7 @@ def input_script_p2wsh_in_p2sh(script_hash: bytes) -> bytearray:
# Signature is moved to the witness.
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.append(0x22) # length of the data
@ -272,7 +266,7 @@ def witness_p2wsh(
)
# fill in our signature
if signatures[signature_index]:
raise ScriptsError("Invalid multisig parameters")
raise wire.DataError("Invalid multisig parameters")
signatures[signature_index] = signature
# filter empty
@ -324,7 +318,7 @@ def input_script_multisig(
) -> bytearray:
signatures = multisig.signatures # other signatures
if len(signatures[signature_index]) > 0:
raise ScriptsError("Invalid multisig parameters")
raise wire.DataError("Invalid multisig parameters")
signatures[signature_index] = signature # our signature
# 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:
n = len(pubkeys)
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:
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
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.MessageSignature import MessageSignature
from .addresses import get_address, validate_full_path
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.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 ..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
if not utils.BITCOIN_ONLY:
from apps.wallet.sign_tx import bitcoinlike, decred, zcash
from . import bitcoinlike, decred, zcash
if False:
from typing import Type, Union
@ -36,22 +36,11 @@ async def sign_tx(
else:
signer_class = bitcoin.Bitcoin
try:
signer = signer_class(msg, keychain, coin).signer()
except common.SigningError as e:
raise wire.Error(*e.args)
signer = signer_class(msg, keychain, coin).signer()
res = None # type: Union[TxAck, bool, None]
while True:
try:
req = signer.send(res)
except (
common.SigningError,
multisig.MultisigError,
addresses.AddressError,
scripts.ScriptsError,
) as e:
raise wire.Error(*e.args)
req = signer.send(res)
if isinstance(req, TxRequest):
if req.request_type == TXFINISHED:
break

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

@ -1,14 +1,16 @@
import gc
from micropython import const
from trezor.messages import FailureType
from trezor import wire
from trezor.messages.SignTx import SignTx
from trezor.messages.TransactionType import TransactionType
from trezor.messages.TxInputType import TxInputType
from apps.wallet.sign_tx import helpers, multisig, writers
from apps.wallet.sign_tx.bitcoin import Bitcoin, input_is_nonsegwit
from apps.wallet.sign_tx.common import SigningError
from .. import multisig, writers
from . import helpers
from .bitcoin import Bitcoin, input_is_nonsegwit
from apps.common.writers import write_bitcoin_varint
if False:
from typing import Union
@ -19,7 +21,7 @@ _SIGHASH_FORKID = const(0x40)
class Bitcoinlike(Bitcoin):
async def process_segwit_input(self, txi: TxInputType) -> None:
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)
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)
if not input_is_nonsegwit(txi):
raise SigningError(
FailureType.ProcessError, "Transaction has changed during signing"
)
raise wire.ProcessError("Transaction has changed during signing")
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

@ -1,8 +1,9 @@
import gc
from micropython import const
from trezor import wire
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.TransactionType import TransactionType
from trezor.messages.TxInputType import TxInputType
@ -11,9 +12,11 @@ from trezor.messages.TxOutputType import TxOutputType
from trezor.utils import HashWriter, ensure
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 apps.wallet.sign_tx.common import SigningError, ecdsa_sign
from .. import multisig, scripts, writers
from ..common import ecdsa_hash_pubkey, ecdsa_sign
from . import helpers, progress
from .bitcoin import Bitcoin
DECRED_SERIALIZE_FULL = const(0 << 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:
if txo.decred_script_version != 0:
raise SigningError(
FailureType.ActionCancelled,
"Cannot send to output with script version != 0",
)
raise wire.ActionCancelled("Cannot send to output with script version != 0")
await super().confirm_output(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:
prev_pkscript = scripts.output_script_p2pkh(
addresses.ecdsa_hash_pubkey(key_sign_pub, self.coin)
ecdsa_hash_pubkey(key_sign_pub, self.coin)
)
else:
raise SigningError("Unsupported input script type")
raise wire.DataError("Unsupported input script type")
h_witness = self.create_hash_writer()
writers.write_uint32(
@ -138,10 +138,7 @@ class Decred(Bitcoin):
def check_prevtx_output(self, txo_bin: TxOutputBinType) -> None:
if txo_bin.decred_script_version != 0:
raise SigningError(
FailureType.ProcessError,
"Cannot use utxo that has script_version != 0",
)
raise wire.ProcessError("Cannot use utxo that has script_version != 0")
def hash143_add_input(self, txi: TxInputType) -> None:
writers.write_tx_input_decred(self.h_prefix, txi)

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

@ -10,7 +10,7 @@ from trezor.utils import chunks
from apps.common import coininfo
if False:
from typing import Iterator, List
from typing import Iterator
from trezor import wire
_LOCKTIME_TIMESTAMP_MIN_VALUE = const(500000000)
@ -30,10 +30,11 @@ def split_op_return(data: str) -> Iterator[str]:
async def confirm_output(
ctx: wire.Context, output: TxOutputType, coin: coininfo.CoinInfo
) -> bool:
) -> None:
from trezor.ui.text import Text
from apps.common.confirm import confirm
from apps.wallet.sign_tx import addresses, omni
from apps.common.confirm import require_confirm
from . import omni
from .. import addresses
if output.script_type == OutputScriptType.PAYTOOPRETURN:
data = output.op_return_data
@ -54,50 +55,39 @@ async def confirm_output(
text = Text("Confirm sending", ui.ICON_SEND, ui.GREEN)
text.normal(format_coin_amount(output.amount, coin) + " to")
text.mono(*split_address(address_short))
return await confirm(ctx, text, ButtonRequestType.ConfirmOutput)
await require_confirm(ctx, text, ButtonRequestType.ConfirmOutput)
async def confirm_total(
ctx: wire.Context, spending: int, fee: int, coin: coininfo.CoinInfo
) -> bool:
) -> None:
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.normal("Total amount:")
text.bold(format_coin_amount(spending, coin))
text.normal("including fee:")
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(
ctx: wire.Context, fee: int, coin: coininfo.CoinInfo
) -> bool:
) -> None:
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.normal("The fee of")
text.bold(format_coin_amount(fee, coin))
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(
ctx: wire.Context, address_n: List[int], coin: coininfo.CoinInfo
) -> bool:
async def confirm_nondefault_locktime(ctx: wire.Context, lock_time: int) -> None:
from trezor.ui.text import Text
from apps.common.confirm import 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
from apps.common.confirm import require_confirm
text = Text("Confirm locktime", ui.ICON_SEND, ui.GREEN)
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.bold(str(lock_time))
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 trezor.messages import FailureType
from trezor import wire
from trezor.messages.TxInputType import TxInputType
from trezor.messages.TxOutputType import TxOutputType
from trezor.utils import ensure
from apps.wallet.sign_tx import multisig
from apps.wallet.sign_tx.common import SigningError
from .. import multisig
if False:
from typing import Any, Union
@ -71,9 +70,7 @@ class MatchChecker:
# All added inputs had a matching attribute, allowing a change-output.
# Ensure that this input still has the same attribute.
if self.attribute != self.attribute_from_tx(txi):
raise SigningError(
FailureType.ProcessError, "Transaction has changed during signing"
)
raise wire.ProcessError("Transaction has changed during signing")
def output_matches(self, txo: TxOutputType) -> bool:
self.read_only = True

@ -1,8 +1,9 @@
import ustruct as struct
from micropython import const
from trezor import wire
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.TransactionType import TransactionType
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.seed import Keychain
from apps.wallet.sign_tx import helpers
from apps.wallet.sign_tx.bitcoinlike import Bitcoinlike
from apps.wallet.sign_tx.common import SigningError
from apps.wallet.sign_tx.multisig import multisig_get_pubkeys
from apps.wallet.sign_tx.scripts import output_script_multisig, output_script_p2pkh
from apps.wallet.sign_tx.writers import (
from ..multisig import multisig_get_pubkeys
from ..scripts import output_script_multisig, output_script_p2pkh
from ..writers import (
TX_HASH_SIZE,
get_tx_hash,
write_bytes_fixed,
@ -25,10 +24,12 @@ from apps.wallet.sign_tx.writers import (
write_uint64,
write_varint,
)
from . import helpers
from .bitcoinlike import Bitcoinlike
if False:
from typing import Union
from apps.wallet.sign_tx.writers import Writer
from .writers import Writer
OVERWINTERED = const(0x80000000)
@ -45,10 +46,7 @@ class Overwintered(Bitcoinlike):
if not self.tx.branch_id:
self.tx.branch_id = 0x76B809BB # Sapling
else:
raise SigningError(
FailureType.DataError,
"Unsupported version for overwintered transaction",
)
raise wire.DataError("Unsupported version for overwintered transaction")
async def step7_finish(self) -> None:
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) # nJoinSplit
else:
raise SigningError(
FailureType.DataError,
"Unsupported version for overwintered transaction",
)
raise wire.DataError("Unsupported version for overwintered transaction")
await helpers.request_tx_finish(self.tx_req)
@ -136,10 +131,7 @@ class Overwintered(Bitcoinlike):
# 12. nHashType
write_uint32(h_preimage, self.get_hash_type())
else:
raise SigningError(
FailureType.DataError,
"Unsupported version for overwintered transaction",
)
raise wire.DataError("Unsupported version for overwintered transaction")
# 10a /13a. outpoint
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)
else:
raise SigningError(
FailureType.DataError, "Unknown input script type for zip143 script code"
)
raise wire.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.Success import Success
from apps.common import coins
from apps.common.signverify import message_digest, require_confirm_verify_message
from apps.wallet.sign_tx.addresses import (
from .addresses import (
address_p2wpkh,
address_p2wpkh_in_p2sh,
address_pkh,
@ -13,6 +11,9 @@ from apps.wallet.sign_tx.addresses import (
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):
message = msg.message

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

@ -3,12 +3,12 @@ from trezor.crypto.hashlib import sha256
from trezor.messages.LiskMessageSignature import LiskMessageSignature
from trezor.utils import HashWriter
from apps.bitcoin.sign_tx.writers import write_varint
from apps.common import paths
from apps.common.seed import with_slip44_keychain
from apps.common.signverify import require_confirm_sign_message
from apps.lisk import CURVE, SLIP44_ID
from apps.lisk.helpers import validate_full_path
from apps.wallet.sign_tx.writers import write_varint
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.utils import chunks
from .sign_identity import serialize_identity, serialize_identity_without_proto
from apps.common import HARDENED
from apps.common.confirm import require_confirm
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):

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

@ -2,12 +2,12 @@ from common import *
from trezor.crypto import bip32, bip39
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 import coins
from apps.wallet.sign_tx import scripts
from apps.wallet.sign_tx.addresses import *
from apps.wallet.sign_tx.writers import *
from apps.bitcoin import scripts
from apps.bitcoin.addresses import *
from apps.bitcoin.writers import *
def node_derive(root, path):
@ -111,7 +111,7 @@ class TestAddress(unittest.TestCase):
self.assertEqual(address, '39bgKC7RFbpoCRbtD5KEdkYKtNyhpsNa3Z')
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)
def test_multisig_address_p2wsh_in_p2sh(self):

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

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

@ -1,8 +1,8 @@
from common import *
from apps.wallet.sign_tx.scripts import output_derive_script
from apps.wallet.sign_tx.bitcoin import Bitcoin
from apps.wallet.sign_tx.writers import get_tx_hash
from apps.bitcoin.scripts import output_derive_script
from apps.bitcoin.sign_tx.bitcoin import Bitcoin
from apps.bitcoin.writers import get_tx_hash
from apps.common import coins
from trezor.messages.SignTx import SignTx
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 import InputScriptType
from trezor.messages import OutputScriptType
from trezor import wire
from apps.common import coins
from apps.common.seed import Keychain
from apps.wallet.keychain import get_namespaces_for_coin
from apps.wallet.sign_tx import helpers, bitcoin
from apps.wallet.sign_tx.scripts import ScriptsError
from apps.bitcoin.keychain import get_namespaces_for_coin
from apps.bitcoin.sign_tx import helpers, bitcoin
EMPTY_SERIALIZED = TxRequestSerializedType(serialized_tx=bytearray())
@ -272,7 +272,7 @@ class TestSignSegwitTxNativeP2WPKH(unittest.TestCase):
signer = bitcoin.Bitcoin(tx, keychain, coin).signer()
for request, response in chunks(messages, 2):
if response is None:
with self.assertRaises(ScriptsError):
with self.assertRaises(wire.DataError):
signer.send(request)
else:
self.assertEqual(signer.send(request), response)

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

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

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

@ -16,7 +16,7 @@ from trezor.messages import OutputScriptType
from apps.common import coins
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())

@ -1,6 +1,6 @@
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):

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

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

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

@ -5,10 +5,10 @@ from trezor.messages.TxInputType import TxInputType
from trezor.messages.TxOutputBinType import TxOutputBinType
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:
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

@ -5,10 +5,10 @@ from trezor.messages.TxInputType import TxInputType
from trezor.messages.TxOutputBinType import TxOutputBinType
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:
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

@ -1,12 +1,10 @@
from common import *
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.wallet.sign_tx import scripts, addresses
from trezor import wire
from trezor.crypto import bip39
from trezor.crypto.curve import secp256k1
class TestKeychain(unittest.TestCase):

@ -4,7 +4,7 @@ from trezor import wire
from trezor.crypto import bip39
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):

@ -6,11 +6,11 @@ Each app has a `boot()` function in the module's \_\_init\_\_ file. This functio
## 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
from trezor import wire
from trezor.messages import MessageType
wire.add(MessageType.GetAddress, apps.wallet, "get_address")
wire.add(MessageType.GetAddress, apps.bitcoin, "get_address")
```

Loading…
Cancel
Save