1
0
mirror of https://github.com/trezor/trezor-firmware.git synced 2024-12-27 16:48:09 +00:00

Merge branch 'matejcik/refactor'

This commit is contained in:
matejcik 2018-05-28 17:46:26 +02:00
commit 279da34864
86 changed files with 942 additions and 639 deletions

View File

@ -10,18 +10,12 @@ exclude =
ignore =
# F401: module imported but unused
F401,
# F403: used import *
F403,
# F405 'foo' may be undefined, or defined from star imports
F405,
# E241: multiple spaces after ':'
E241,
# E402: module level import not at top of file
E402,
# E501: line too long
E501,
# E721: do not compare types, use 'isinstance()'
E721,
# E722: do not use bare except
E722,
# E741: ambiguous variable name

View File

@ -1,6 +1,7 @@
#!/usr/bin/env python3
from trezorlib.client import TrezorClient
from trezorlib.transport import get_transport
from trezorlib.tools import parse_path
def main():
@ -15,7 +16,7 @@ def main():
# Get the first address of first BIP44 account
# (should be the same address as shown in wallet.trezor.io)
bip32_path = client.expand_path("44'/0'/0'/0/0")
bip32_path = parse_path("44'/0'/0'/0/0")
address = client.get_address('Bitcoin', bip32_path)
print('Bitcoin address:', address)

View File

@ -10,16 +10,16 @@ from urllib.parse import urlparse
from trezorlib.client import TrezorClient
from trezorlib.transport import get_transport
from trezorlib.tools import parse_path
# Return path by BIP-32
def getPath(client):
return client.expand_path("10016'/0")
BIP32_PATH = parse_path("10016h/0")
# Deriving master key
def getMasterKey(client):
bip32_path = getPath(client)
bip32_path = BIP32_PATH
ENC_KEY = 'Activate TREZOR Password Manager?'
ENC_VALUE = unhexlify('2d650551248d792eabf628f451200d7f51cb63e46aadcbb1038aacb05e8c8aee2d650551248d792eabf628f451200d7f51cb63e46aadcbb1038aacb05e8c8aee')
key = hexlify(client.encrypt_keyvalue(
@ -99,7 +99,7 @@ def getDecryptedNonce(client, entry):
ENC_KEY = 'Unlock %s for user %s?' % (item, entry['username'])
ENC_VALUE = entry['nonce']
decrypted_nonce = hexlify(client.decrypt_keyvalue(
getPath(client),
BIP32_PATH,
ENC_KEY,
unhexlify(ENC_VALUE),
False,

View File

@ -14,6 +14,13 @@ from trezorlib.tx_api import TxApiBitcoin
from trezorlib.transport import get_transport
# This script has survived unmodified through several significant changes
# of the trezorlib library. While we want to have something like this,
# we're waiting on a couple more changes in order to implement this a little more cleanly.
# Wait for trezorlib v1.0.
raise Exception("This code is too old to run. Sorry.")
def hash160(x):
h = hashlib.new("ripemd160")
h.update(hashlib.sha256(x).digest())
@ -110,7 +117,7 @@ class MyTxApiBitcoin(object):
o.script_pubkey = b'\x76\xa9\x14' + pubkey + b'\x88\xac'
txser = self.serialize_tx(t)
txhash = tools.Hash(txser)[::-1]
txhash = tools.btc_hash(txser)[::-1]
self.inputs.append(
proto_types.TxInputType(
address_n=self.client.expand_path("44'/0'/0'/0/%d" % idx),

View File

@ -23,18 +23,19 @@
import base64
import binascii
import click
import functools
import json
import logging
import os
import sys
from trezorlib.client import TrezorClient, TrezorClientVerbose, CallException, format_protobuf
from trezorlib.transport import get_transport, enumerate_devices, TransportException
from trezorlib.client import TrezorClient, CallException
from trezorlib.transport import get_transport, enumerate_devices
from trezorlib import coins
from trezorlib import log
from trezorlib import messages as proto
from trezorlib import protobuf
from trezorlib.ckd_public import PRIME_DERIVATION_FLAG
from trezorlib import stellar
from trezorlib import tools
class ChoiceType(click.Choice):
@ -65,32 +66,34 @@ CHOICE_OUTPUT_SCRIPT_TYPE = ChoiceType({
})
def enable_logging():
log.enable_debug_output()
log.OMITTED_MESSAGES.add(proto.Features)
@click.group(context_settings={'max_content_width': 400})
@click.option('-p', '--path', help='Select device by specific path.', default=os.environ.get('TREZOR_PATH'))
@click.option('-v', '--verbose', is_flag=True, help='Show communication messages.')
@click.option('-j', '--json', 'is_json', is_flag=True, help='Print result as JSON object')
@click.pass_context
def cli(ctx, path, verbose, is_json):
if ctx.invoked_subcommand != 'list':
if verbose:
cls = TrezorClientVerbose
else:
cls = TrezorClient
if verbose:
enable_logging()
def get_device():
def get_device():
try:
device = get_transport(path, prefix_search=False)
except:
try:
device = get_transport(path, prefix_search=False)
device = get_transport(path, prefix_search=True)
except:
try:
device = get_transport(path, prefix_search=True)
except:
click.echo("Failed to find a TREZOR device.")
if path is not None:
click.echo("Using path: {}".format(path))
sys.exit(1)
return cls(transport=device)
click.echo("Failed to find a TREZOR device.")
if path is not None:
click.echo("Using path: {}".format(path))
sys.exit(1)
return TrezorClient(transport=device)
ctx.obj = get_device
ctx.obj = get_device
@cli.resultcallback()
@ -112,7 +115,7 @@ def print_result(res, path, verbose, is_json):
else:
click.echo('%s: %s' % (k, v))
elif isinstance(res, protobuf.MessageType):
click.echo(format_protobuf(res))
click.echo(protobuf.format_message(res))
else:
click.echo(res)
@ -449,7 +452,7 @@ def self_test(connect):
@click.pass_obj
def get_address(connect, coin, address, script_type, show_display):
client = connect()
address_n = client.expand_path(address)
address_n = tools.parse_path(address)
return client.get_address(coin, address_n, show_display, script_type=script_type)
@ -461,7 +464,7 @@ def get_address(connect, coin, address, script_type, show_display):
@click.pass_obj
def get_public_node(connect, coin, address, curve, show_display):
client = connect()
address_n = client.expand_path(address)
address_n = tools.parse_path(address)
result = client.get_public_node(address_n, ecdsa_curve_name=curve, show_display=show_display, coin_name=coin)
return {
'node': {
@ -502,7 +505,7 @@ def sign_tx(connect, coin):
if address_n is None:
pass
elif address_n[0] == (49 | PRIME_DERIVATION_FLAG):
elif address_n[0] == tools.H_(49):
script_type = 'p2shsegwit'
return script_type
@ -518,7 +521,7 @@ def sign_tx(connect, coin):
if not prev:
break
prev_hash, prev_index = prev
address_n = click.prompt('BIP-32 path to derive the key', type=client.expand_path)
address_n = click.prompt('BIP-32 path to derive the key', type=tools.parse_path)
amount = click.prompt('Input amount (satoshis)', type=int, default=0)
sequence = click.prompt('Sequence Number to use (RBF opt-in enabled by default)', type=int, default=0xfffffffd)
script_type = click.prompt('Input type', type=CHOICE_INPUT_SCRIPT_TYPE, default=default_script_type(address_n))
@ -540,7 +543,7 @@ def sign_tx(connect, coin):
address_n = None
else:
address = None
address_n = click.prompt('BIP-32 path (for change output)', type=client.expand_path, default='')
address_n = click.prompt('BIP-32 path (for change output)', type=tools.parse_path, default='')
if not address_n:
break
amount = click.prompt('Amount to spend (satoshis)', type=int)
@ -581,7 +584,7 @@ def sign_tx(connect, coin):
@click.pass_obj
def sign_message(connect, coin, address, message, script_type):
client = connect()
address_n = client.expand_path(address)
address_n = tools.parse_path(address)
typemap = {
'address': proto.InputScriptType.SPENDADDRESS,
'segwit': proto.InputScriptType.SPENDWITNESS,
@ -613,7 +616,7 @@ def verify_message(connect, coin, address, signature, message):
@click.pass_obj
def ethereum_sign_message(connect, address, message):
client = connect()
address_n = client.expand_path(address)
address_n = tools.parse_path(address)
ret = client.ethereum_sign_message(address_n, message)
output = {
'message': message,
@ -648,7 +651,7 @@ def ethereum_verify_message(connect, address, signature, message):
@click.pass_obj
def encrypt_keyvalue(connect, address, key, value):
client = connect()
address_n = client.expand_path(address)
address_n = tools.parse_path(address)
res = client.encrypt_keyvalue(address_n, key, value.encode())
return binascii.hexlify(res)
@ -660,7 +663,7 @@ def encrypt_keyvalue(connect, address, key, value):
@click.pass_obj
def decrypt_keyvalue(connect, address, key, value):
client = connect()
address_n = client.expand_path(address)
address_n = tools.parse_path(address)
return client.decrypt_keyvalue(address_n, key, binascii.unhexlify(value))
@ -674,7 +677,7 @@ def decrypt_keyvalue(connect, address, key, value):
def encrypt_message(connect, coin, display_only, address, pubkey, message):
client = connect()
pubkey = binascii.unhexlify(pubkey)
address_n = client.expand_path(address)
address_n = tools.parse_path(address)
res = client.encrypt_message(pubkey, message, display_only, coin, address_n)
return {
'nonce': binascii.hexlify(res.nonce),
@ -690,7 +693,7 @@ def encrypt_message(connect, coin, display_only, address, pubkey, message):
@click.pass_obj
def decrypt_message(connect, address, payload):
client = connect()
address_n = client.expand_path(address)
address_n = tools.parse_path(address)
payload = base64.b64decode(payload)
nonce, message, msg_hmac = payload[:33], payload[33:-8], payload[-8:]
return client.decrypt_message(address_n, nonce, message, msg_hmac)
@ -707,7 +710,7 @@ def decrypt_message(connect, address, payload):
@click.pass_obj
def ethereum_get_address(connect, address, show_display):
client = connect()
address_n = client.expand_path(address)
address_n = tools.parse_path(address)
address = client.ethereum_get_address(address_n, show_display)
return '0x%s' % binascii.hexlify(address).decode()
@ -774,7 +777,7 @@ def ethereum_sign_tx(connect, host, chain_id, address, value, gas_limit, gas_pri
to_address = ethereum_decode_hex(to)
client = connect()
address_n = client.expand_path(address)
address_n = tools.parse_path(address)
address = '0x%s' % (binascii.hexlify(client.ethereum_get_address(address_n)).decode())
if gas_price is None or gas_limit is None or nonce is None or publish:
@ -836,7 +839,7 @@ def ethereum_sign_tx(connect, host, chain_id, address, value, gas_limit, gas_pri
@click.pass_obj
def nem_get_address(connect, address, network, show_display):
client = connect()
address_n = client.expand_path(address)
address_n = tools.parse_path(address)
return client.nem_get_address(address_n, network, show_display)
@ -847,7 +850,7 @@ def nem_get_address(connect, address, network, show_display):
@click.pass_obj
def nem_sign_tx(connect, address, file, broadcast):
client = connect()
address_n = client.expand_path(address)
address_n = tools.parse_path(address)
transaction = client.nem_sign_tx(address_n, json.load(file))
payload = {
@ -873,7 +876,7 @@ def nem_sign_tx(connect, address, file, broadcast):
@click.pass_obj
def lisk_get_address(connect, address, show_display):
client = connect()
address_n = client.expand_path(address)
address_n = tools.parse_path(address)
return client.lisk_get_address(address_n, show_display)
@ -883,7 +886,7 @@ def lisk_get_address(connect, address, show_display):
@click.pass_obj
def lisk_get_public_key(connect, address, show_display):
client = connect()
address_n = client.expand_path(address)
address_n = tools.parse_path(address)
res = client.lisk_get_public_key(address_n, show_display)
output = {
"public_key": binascii.hexlify(res.public_key).decode()
@ -898,7 +901,7 @@ def lisk_get_public_key(connect, address, show_display):
@click.pass_obj
def lisk_sign_tx(connect, address, file):
client = connect()
address_n = client.expand_path(address)
address_n = tools.parse_path(address)
transaction = client.lisk_sign_tx(address_n, json.load(file))
payload = {
@ -919,7 +922,7 @@ def lisk_sign_tx(connect, address, file):
@click.pass_obj
def cosi_commit(connect, address, data):
client = connect()
address_n = client.expand_path(address)
address_n = tools.parse_path(address)
return client.cosi_commit(address_n, binascii.unhexlify(data))
@ -931,7 +934,7 @@ def cosi_commit(connect, address, data):
@click.pass_obj
def cosi_sign(connect, address, data, global_commitment, global_pubkey):
client = connect()
address_n = client.expand_path(address)
address_n = tools.parse_path(address)
return client.cosi_sign(address_n, binascii.unhexlify(data), binascii.unhexlify(global_commitment), binascii.unhexlify(global_pubkey))
@ -939,25 +942,24 @@ def cosi_sign(connect, address, data, global_commitment, global_pubkey):
# Stellar functions
#
@cli.command(help='Get Stellar public address')
@click.option('-n', '--address', required=False, help="BIP32 path. Default primary account is m/44'/148'/0'. Always use hardened paths and the m/44'/148'/ prefix")
@click.option('-n', '--address', required=False, help="BIP32 path. Always use hardened paths and the m/44'/148'/ prefix", default=stellar.DEFAULT_BIP32_PATH)
@click.pass_obj
def stellar_get_address(connect, address):
client = connect()
address_n = stellar.expand_path_or_default(client, address)
address_n = tools.parse_path(address)
# StellarPublicKey response
response = client.stellar_get_public_key(address_n)
return stellar.address_from_public_key(response.public_key)
@cli.command(help='Sign a base64-encoded transaction envelope')
@click.option('-n', '--address', required=False, help="BIP32 path. Default primary account is m/44'/148'/0'. Always use hardened paths and the m/44'/148'/ prefix")
@click.option('-n', '--address', required=False, help="BIP32 path. Always use hardened paths and the m/44'/148'/ prefix", default=stellar.DEFAULT_BIP32_PATH)
@click.option('-n', '--network-passphrase', default='Public Global Stellar Network ; September 2015', required=False, help="Network passphrase (blank for public network). Testnet is: 'Test SDF Network ; September 2015'")
@click.argument('b64envelope')
@click.pass_obj
def stellar_sign_transaction(connect, b64envelope, address, network_passphrase):
client = connect()
address_n = stellar.expand_path_or_default(client, address)
address_n = tools.parse_path(address)
tx, operations = stellar.parse_transaction_bytes(base64.b64decode(b64envelope))
resp = client.stellar_sign_transaction(tx, operations, address_n, network_passphrase)

View File

@ -1,19 +1,21 @@
# orignal version downloaded from https://ed25519.cr.yp.to/python/ed25519.py
# modified for Python 3 by Jochen Hoenicke <hoenicke@gmail.com>
import sys
import hashlib
from typing import Tuple, NewType
Point = NewType("Point", Tuple[int, int])
b = 256
q = 2 ** 255 - 19
l = 2 ** 252 + 27742317777372353535851937790883648493
def H(m):
def H(m: bytes) -> bytes:
return hashlib.sha512(m).digest()
def expmod(b, e, m):
def expmod(b: int, e: int, m: int) -> int:
if e < 0:
raise ValueError('negative exponent')
if e == 0:
@ -24,7 +26,7 @@ def expmod(b, e, m):
return t
def inv(x):
def inv(x: int) -> int:
return expmod(x, q - 2, q)
@ -32,7 +34,7 @@ d = -121665 * inv(121666)
I = expmod(2, (q - 1) >> 2, q)
def xrecover(y):
def xrecover(y: int) -> int:
xx = (y * y - 1) * inv(d * y * y + 1)
x = expmod(xx, (q + 3) >> 3, q)
if (x * x - xx) % q != 0:
@ -44,22 +46,22 @@ def xrecover(y):
By = 4 * inv(5)
Bx = xrecover(By)
B = [Bx % q, By % q]
B = Point((Bx % q, By % q))
def edwards(P, Q):
def edwards(P: Point, Q: Point) -> Point:
x1 = P[0]
y1 = P[1]
x2 = Q[0]
y2 = Q[1]
x3 = (x1 * y2 + x2 * y1) * inv(1 + d * x1 * x2 * y1 * y2)
y3 = (y1 * y2 + x1 * x2) * inv(1 - d * x1 * x2 * y1 * y2)
return [x3 % q, y3 % q]
return Point((x3 % q, y3 % q))
def scalarmult(P, e):
def scalarmult(P: Point, e: int) -> Point:
if e == 0:
return [0, 1]
return Point((0, 1))
Q = scalarmult(P, e >> 1)
Q = edwards(Q, Q)
if e & 1:
@ -67,35 +69,35 @@ def scalarmult(P, e):
return Q
def encodeint(y):
def encodeint(y: int) -> bytes:
bits = [(y >> i) & 1 for i in range(b)]
return bytes([sum([bits[i * 8 + j] << j for j in range(8)]) for i in range(b >> 3)])
def encodepoint(P):
def encodepoint(P: Point) -> bytes:
x = P[0]
y = P[1]
bits = [(y >> i) & 1 for i in range(b - 1)] + [x & 1]
return bytes([sum([bits[i * 8 + j] << j for j in range(8)]) for i in range(b >> 3)])
def bit(h, i):
def bit(h: bytes, i: int) -> int:
return (h[i >> 3] >> (i & 7)) & 1
def publickey(sk):
def publickey(sk: bytes) -> bytes:
h = H(sk)
a = 2 ** (b - 2) + sum(2 ** i * bit(h, i) for i in range(3, b - 2))
A = scalarmult(B, a)
return encodepoint(A)
def Hint(m):
def Hint(m: bytes) -> int:
h = H(m)
return sum(2 ** i * bit(h, i) for i in range(2 * b))
def signature(m, sk, pk):
def signature(m: bytes, sk: bytes, pk: bytes) -> bytes:
h = H(sk)
a = 2 ** (b - 2) + sum(2 ** i * bit(h, i) for i in range(3, b - 2))
r = Hint(bytes([h[i] for i in range(b >> 3, b >> 2)]) + m)
@ -104,28 +106,28 @@ def signature(m, sk, pk):
return encodepoint(R) + encodeint(S)
def isoncurve(P):
def isoncurve(P: Point) -> bool:
x = P[0]
y = P[1]
return (-x * x + y * y - 1 - d * x * x * y * y) % q == 0
def decodeint(s):
def decodeint(s: bytes) -> int:
return sum(2 ** i * bit(s, i) for i in range(0, b))
def decodepoint(s):
def decodepoint(s: bytes) -> Point:
y = sum(2 ** i * bit(s, i) for i in range(0, b - 1))
x = xrecover(y)
if x & 1 != bit(s, b - 1):
x = q - x
P = [x, y]
P = Point((x, y))
if not isoncurve(P):
raise ValueError('decoding point that is not on curve')
return P
def checkvalid(s, m, pk):
def checkvalid(s: bytes, m: bytes, pk: bytes) -> None:
if len(s) != b >> 2:
raise ValueError('signature length is wrong')
if len(pk) != b >> 3:

View File

@ -17,8 +17,8 @@
# You should have received a copy of the GNU Lesser General Public License
# along with this library. If not, see <http://www.gnu.org/licenses/>.
from __future__ import print_function, absolute_import
import functools
import logging
import os
import sys
import time
@ -34,18 +34,16 @@ from . import messages as proto
from . import tools
from . import mapping
from . import nem
from .coins import slip44
from . import protobuf
from . import stellar
from .debuglink import DebugLink
from .protobuf import MessageType
if sys.version_info.major < 3:
raise Exception("Trezorlib does not support Python 2 anymore.")
SCREENSHOT = False
LOG = logging.getLogger(__name__)
# make a getch function
try:
@ -84,70 +82,15 @@ def get_buttonrequest_value(code):
return [k for k in dir(proto.ButtonRequestType) if getattr(proto.ButtonRequestType, k) == code][0]
def format_protobuf(pb, indent=0, sep=' ' * 4):
def pformat_value(value, indent):
level = sep * indent
leadin = sep * (indent + 1)
if isinstance(value, MessageType):
return format_protobuf(value, indent, sep)
if isinstance(value, list):
lines = []
lines.append('[')
lines += [leadin + pformat_value(x, indent + 1) + ',' for x in value]
lines.append(level + ']')
return '\n'.join(lines)
if isinstance(value, dict):
lines = []
lines.append('{')
for key, val in sorted(value.items()):
if val is None or val == []:
continue
if key == 'address_n' and isinstance(val, list):
lines.append(leadin + key + ': ' + repr(val) + ',')
else:
lines.append(leadin + key + ': ' + pformat_value(val, indent + 1) + ',')
lines.append(level + '}')
return '\n'.join(lines)
if isinstance(value, bytearray):
return 'bytearray(0x{})'.format(binascii.hexlify(value).decode('ascii'))
return repr(value)
return pb.__class__.__name__ + ' ' + pformat_value(pb.__dict__, indent)
def pprint(msg):
msg_class = msg.__class__.__name__
msg_size = msg.ByteSize()
if isinstance(msg, proto.FirmwareUpload) or isinstance(msg, proto.SelfTest) \
or isinstance(msg, proto.Features):
return "<%s> (%d bytes)" % (msg_class, msg_size)
else:
return "<%s> (%d bytes):\n%s" % (msg_class, msg_size, format_protobuf(msg))
def log(msg):
sys.stderr.write(msg)
sys.stderr.write('\n')
sys.stderr.flush()
class CallException(Exception):
def __init__(self, code, message):
super(CallException, self).__init__()
self.args = [code, message]
class AssertionException(Exception):
def __init__(self, code, message):
self.args = [code, message]
pass
class PinException(CallException):
pass
class field(object):
class field:
# Decorator extracts single value from
# protobuf object. If the field is not
# present, raises an exception.
@ -155,13 +98,14 @@ class field(object):
self.field = field
def __call__(self, f):
@functools.wraps(f)
def wrapped_f(*args, **kwargs):
ret = f(*args, **kwargs)
return getattr(ret, self.field)
return wrapped_f
class expect(object):
class expect:
# Decorator checks if the method
# returned one of expected protobuf messages
# or raises an exception
@ -169,6 +113,7 @@ class expect(object):
self.expected = expected
def __call__(self, f):
@functools.wraps(f)
def wrapped_f(*args, **kwargs):
ret = f(*args, **kwargs)
if not isinstance(ret, self.expected):
@ -180,7 +125,9 @@ class expect(object):
def session(f):
# Decorator wraps a BaseClient method
# with session activation / deactivation
@functools.wraps(f)
def wrapped_f(*args, **kwargs):
__tracebackhide__ = True # pytest traceback hiding - this function won't appear in tracebacks
client = args[0]
client.transport.session_begin()
try:
@ -204,6 +151,7 @@ class BaseClient(object):
# Implements very basic layer of sending raw protobuf
# messages to device and getting its response back.
def __init__(self, transport, **kwargs):
LOG.info("creating client instance for device: {}".format(transport.get_path()))
self.transport = transport
super(BaseClient, self).__init__() # *args, **kwargs)
@ -215,6 +163,7 @@ class BaseClient(object):
@session
def call_raw(self, msg):
__tracebackhide__ = True # pytest traceback hiding - this function won't appear in tracebacks
self.transport.write(msg)
return self.transport.read()
@ -244,14 +193,6 @@ class BaseClient(object):
mapping.register_message(msg)
class VerboseWireMixin(object):
def call_raw(self, msg):
log("SENDING " + pprint(msg))
resp = super(VerboseWireMixin, self).call_raw(msg)
log("RECEIVED " + pprint(resp))
return resp
class TextUIMixin(object):
# This class demonstrates easy test-based UI
# integration between the device and wallet.
@ -262,6 +203,10 @@ class TextUIMixin(object):
def __init__(self, *args, **kwargs):
super(TextUIMixin, self).__init__(*args, **kwargs)
@staticmethod
def print(text):
print(text, file=sys.stderr)
def callback_ButtonRequest(self, msg):
# log("Sending ButtonAck for %s " % get_buttonrequest_value(msg.code))
return proto.ButtonAck()
@ -269,11 +214,11 @@ class TextUIMixin(object):
def callback_RecoveryMatrix(self, msg):
if self.recovery_matrix_first_pass:
self.recovery_matrix_first_pass = False
log("Use the numeric keypad to describe positions. For the word list use only left and right keys.")
log("Use backspace to correct an entry. The keypad layout is:")
log(" 7 8 9 7 | 9")
log(" 4 5 6 4 | 6")
log(" 1 2 3 1 | 3")
self.print("Use the numeric keypad to describe positions. For the word list use only left and right keys.")
self.print("Use backspace to correct an entry. The keypad layout is:")
self.print(" 7 8 9 7 | 9")
self.print(" 4 5 6 4 | 6")
self.print(" 1 2 3 1 | 3")
while True:
character = getch()
if character in ('\x03', '\x04'):
@ -299,11 +244,11 @@ class TextUIMixin(object):
else:
desc = 'PIN'
log("Use the numeric keypad to describe number positions. The layout is:")
log(" 7 8 9")
log(" 4 5 6")
log(" 1 2 3")
log("Please enter %s: " % desc)
self.print("Use the numeric keypad to describe number positions. The layout is:")
self.print(" 7 8 9")
self.print(" 4 5 6")
self.print(" 1 2 3")
self.print("Please enter %s: " % desc)
pin = getpass.getpass('')
if not pin.isdigit():
raise ValueError('Non-numerical PIN provided')
@ -314,18 +259,18 @@ class TextUIMixin(object):
return proto.PassphraseAck()
if os.getenv("PASSPHRASE") is not None:
log("Passphrase required. Using PASSPHRASE environment variable.")
self.print("Passphrase required. Using PASSPHRASE environment variable.")
passphrase = Mnemonic.normalize_string(os.getenv("PASSPHRASE"))
return proto.PassphraseAck(passphrase=passphrase)
log("Passphrase required: ")
self.print("Passphrase required: ")
passphrase = getpass.getpass('')
log("Confirm your Passphrase: ")
self.print("Confirm your Passphrase: ")
if passphrase == getpass.getpass(''):
passphrase = Mnemonic.normalize_string(passphrase)
return proto.PassphraseAck(passphrase=passphrase)
else:
log("Passphrase did not match! ")
self.print("Passphrase did not match! ")
exit()
def callback_PassphraseStateRequest(self, msg):
@ -335,7 +280,7 @@ class TextUIMixin(object):
if msg.type in (proto.WordRequestType.Matrix9,
proto.WordRequestType.Matrix6):
return self.callback_RecoveryMatrix(msg)
log("Enter one word of mnemonic: ")
self.print("Enter one word of mnemonic: ")
word = input()
if self.expand:
word = self.mnemonic_wordlist.expand_word(word)
@ -352,6 +297,7 @@ class DebugLinkMixin(object):
# of unit testing, because it will fail to work
# without special DebugLink interface provided
# by the device.
DEBUG = LOG.getChild('debug_link').debug
def __init__(self, *args, **kwargs):
super(DebugLinkMixin, self).__init__(*args, **kwargs)
@ -396,7 +342,7 @@ class DebugLinkMixin(object):
# Evaluate missed responses in 'with' statement
if self.expected_responses is not None and len(self.expected_responses):
raise RuntimeError("Some of expected responses didn't come from device: %s" %
[pprint(x) for x in self.expected_responses])
[repr(x) for x in self.expected_responses])
# Cleanup
self.expected_responses = None
@ -418,6 +364,7 @@ class DebugLinkMixin(object):
self.mnemonic = Mnemonic.normalize_string(mnemonic).split(' ')
def call_raw(self, msg):
__tracebackhide__ = True # pytest traceback hiding - this function won't appear in tracebacks
if SCREENSHOT and self.debug:
from PIL import Image
@ -437,30 +384,32 @@ class DebugLinkMixin(object):
return resp
def _check_request(self, msg):
__tracebackhide__ = True # pytest traceback hiding - this function won't appear in tracebacks
if self.expected_responses is not None:
try:
expected = self.expected_responses.pop(0)
except IndexError:
raise AssertionException(proto.FailureType.UnexpectedMessage,
"Got %s, but no message has been expected" % pprint(msg))
raise AssertionError(proto.FailureType.UnexpectedMessage,
"Got %s, but no message has been expected" % repr(msg))
if msg.__class__ != expected.__class__:
raise AssertionException(proto.FailureType.UnexpectedMessage,
"Expected %s, got %s" % (pprint(expected), pprint(msg)))
raise AssertionError(proto.FailureType.UnexpectedMessage,
"Expected %s, got %s" % (repr(expected), repr(msg)))
for field, value in expected.__dict__.items():
if value is None or value == []:
continue
if getattr(msg, field) != value:
raise AssertionException(proto.FailureType.UnexpectedMessage,
"Expected %s, got %s" % (pprint(expected), pprint(msg)))
raise AssertionError(proto.FailureType.UnexpectedMessage,
"Expected %s, got %s" % (repr(expected), repr(msg)))
def callback_ButtonRequest(self, msg):
log("ButtonRequest code: " + get_buttonrequest_value(msg.code))
self.DEBUG("ButtonRequest code: " + get_buttonrequest_value(msg.code))
log("Pressing button " + str(self.button))
self.DEBUG("Pressing button " + str(self.button))
if self.button_wait:
log("Waiting %d seconds " % self.button_wait)
self.DEBUG("Waiting %d seconds " % self.button_wait)
time.sleep(self.button_wait)
self.debug.press_button(self.button)
return proto.ButtonAck()
@ -473,7 +422,7 @@ class DebugLinkMixin(object):
return proto.PinMatrixAck(pin=pin)
def callback_PassphraseRequest(self, msg):
log("Provided passphrase: '%s'" % self.passphrase)
self.DEBUG("Provided passphrase: '%s'" % self.passphrase)
return proto.PassphraseAck(passphrase=self.passphrase)
def callback_PassphraseStateRequest(self, msg):
@ -490,7 +439,6 @@ class DebugLinkMixin(object):
class ProtocolMixin(object):
PRIME_DERIVATION_FLAG = 0x80000000
VENDORS = ('bitcointrezor.com', 'trezor.io')
def __init__(self, state=None, *args, **kwargs):
@ -513,44 +461,15 @@ class ProtocolMixin(object):
def _get_local_entropy(self):
return os.urandom(32)
def _convert_prime(self, n):
@staticmethod
def _convert_prime(n: tools.Address) -> tools.Address:
# Convert minus signs to uint32 with flag
return [int(abs(x) | self.PRIME_DERIVATION_FLAG) if x < 0 else x for x in n]
return [tools.H_(int(abs(x))) if x < 0 else x for x in n]
@staticmethod
def expand_path(n):
# Convert string of bip32 path to list of uint32 integers with prime flags
# 0/-1/1' -> [0, 0x80000001, 0x80000001]
if not n:
return []
n = n.split('/')
# m/a/b/c => a/b/c
if n[0] == 'm':
n = n[1:]
# coin_name/a/b/c => 44'/SLIP44_constant'/a/b/c
if n[0] in slip44:
n = ["44'", "%d'" % slip44[n[0]]] + n[1:]
path = []
for x in n:
prime = False
if x.endswith("'"):
x = x.replace('\'', '')
prime = True
if x.startswith('-'):
prime = True
x = abs(int(x))
if prime:
x |= ProtocolMixin.PRIME_DERIVATION_FLAG
path.append(x)
return path
warnings.warn('expand_path is deprecated, use tools.parse_path', DeprecationWarning)
return tools.parse_path(n)
@expect(proto.PublicKey)
def get_public_node(self, n, ecdsa_curve_name=None, show_display=False, coin_name=None):
@ -1031,7 +950,7 @@ class ProtocolMixin(object):
raise RuntimeError("Invalid response, expected EntropyRequest")
external_entropy = self._get_local_entropy()
log("Computer generated entropy: " + binascii.hexlify(external_entropy).decode())
LOG.debug("Computer generated entropy: " + binascii.hexlify(external_entropy).decode())
ret = self.call(proto.EntropyAck(entropy=external_entropy))
self.init_device()
return ret
@ -1079,7 +998,7 @@ class ProtocolMixin(object):
if xprv[0:4] not in ('xprv', 'tprv'):
raise ValueError("Unknown type of xprv")
if len(xprv) < 100 and len(xprv) > 112:
if not 100 < len(xprv) < 112: # yes this is correct in Python
raise ValueError("Invalid length of xprv")
node = proto.HDNodeType()
@ -1088,7 +1007,7 @@ class ProtocolMixin(object):
if data[90:92] != b'00':
raise ValueError("Contain invalid private key")
checksum = binascii.hexlify(hashlib.sha256(hashlib.sha256(binascii.unhexlify(data[:156])).digest()).digest()[:4])
checksum = binascii.hexlify(tools.btc_hash(binascii.unhexlify(data[:156]))[:4])
if checksum != data[156:]:
raise ValueError("Checksum doesn't match")
@ -1128,7 +1047,7 @@ class ProtocolMixin(object):
# TREZORv1 method
if isinstance(resp, proto.Success):
fingerprint = hashlib.sha256(data[256:]).hexdigest()
log("Firmware fingerprint: " + fingerprint)
LOG.debug("Firmware fingerprint: " + fingerprint)
resp = self.call(proto.FirmwareUpload(payload=data))
if isinstance(resp, proto.Success):
return True
@ -1204,11 +1123,6 @@ class TrezorClient(ProtocolMixin, TextUIMixin, BaseClient):
super().__init__(transport=transport, *args, **kwargs)
class TrezorClientVerbose(ProtocolMixin, TextUIMixin, VerboseWireMixin, BaseClient):
def __init__(self, transport, *args, **kwargs):
super().__init__(transport=transport, *args, **kwargs)
class TrezorClientDebugLink(ProtocolMixin, DebugLinkMixin, VerboseWireMixin, BaseClient):
class TrezorClientDebugLink(ProtocolMixin, DebugLinkMixin, BaseClient):
def __init__(self, transport, *args, **kwargs):
super().__init__(transport=transport, *args, **kwargs)

72
trezorlib/cosi.py Normal file
View File

@ -0,0 +1,72 @@
import sys
from functools import reduce
import binascii
from typing import Iterable, Tuple
from trezorlib import _ed25519
# XXX, these could be NewType's, but that would infect users of the cosi module with these types as well.
# Unsure if we want that.
Ed25519PrivateKey = bytes
Ed25519PublicPoint = bytes
Ed25519Signature = bytes
def combine_keys(pks: Iterable[Ed25519PublicPoint]) -> Ed25519PublicPoint:
"""Combine a list of Ed25519 points into a "global" CoSi key."""
P = [_ed25519.decodepoint(pk) for pk in pks]
combine = reduce(_ed25519.edwards, P)
return Ed25519PublicPoint(_ed25519.encodepoint(combine))
def combine_sig(global_R: Ed25519PublicPoint, sigs: Iterable[Ed25519Signature]) -> Ed25519Signature:
"""Combine a list of signatures into a single CoSi signature."""
S = [_ed25519.decodeint(si) for si in sigs]
s = sum(S) % _ed25519.l
sig = global_R + _ed25519.encodeint(s)
return Ed25519Signature(sig)
def get_nonce(sk: Ed25519PrivateKey, data: bytes, ctr: int = 0) -> Tuple[int, Ed25519PublicPoint]:
"""Calculate CoSi nonces for given data.
These differ from Ed25519 deterministic nonces in that there is a counter appended at end.
Returns both the private point `r` and the partial signature `R`.
`r` is returned for performance reasons: :func:`sign_with_privkey`
takes it as its `nonce` argument so that it doesn't repeat the `get_nonce` call.
`R` should be combined with other partial signatures through :func:`combine_keys`
to obtain a "global commitment".
"""
h = _ed25519.H(sk)
b = _ed25519.b
r = _ed25519.Hint(bytes([h[i] for i in range(b >> 3, b >> 2)]) + data + binascii.unhexlify('%08x' % ctr))
R = _ed25519.scalarmult(_ed25519.B, r)
return r, Ed25519PublicPoint(_ed25519.encodepoint(R))
def verify(signature: Ed25519Signature, digest: bytes, pub_key: Ed25519PublicPoint) -> None:
"""Verify Ed25519 signature. Raise exception if the signature is invalid."""
# XXX this *might* change to bool function
_ed25519.checkvalid(signature, digest, pub_key)
def pubkey_from_privkey(privkey: Ed25519PrivateKey) -> Ed25519PublicPoint:
"""Interpret 32 bytes of data as an Ed25519 private key.
Calculate and return the corresponding public key.
"""
return Ed25519PublicPoint(_ed25519.publickey(privkey))
def sign_with_privkey(digest: bytes, privkey: Ed25519PrivateKey,
global_pubkey: Ed25519PublicPoint,
nonce: int,
global_commit: Ed25519PublicPoint) -> Ed25519Signature:
"""Create a CoSi signature of `digest` with the supplied private key.
This function needs to know the global public key and global commitment.
"""
h = _ed25519.H(privkey)
b = _ed25519.b
a = 2 ** (b - 2) + sum(2 ** i * _ed25519.bit(h, i) for i in range(3, b - 2))
S = (nonce + _ed25519.Hint(global_commit + global_pubkey + digest) * a) % _ed25519.l
return Ed25519Signature(_ed25519.encodeint(S))

View File

@ -29,10 +29,6 @@ def button_press(yes_no):
print("User pressed", '"y"' if yes_no else '"n"')
def pprint(msg):
return "<%s> (%d bytes):\n%s" % (msg.__class__.__name__, msg.ByteSize(), msg)
class DebugLink(object):
def __init__(self, transport, pin_func=pin_info, button_func=button_press):
self.transport = transport
@ -45,12 +41,10 @@ class DebugLink(object):
self.transport.session_end()
def _call(self, msg, nowait=False):
print("DEBUGLINK SEND", pprint(msg))
self.transport.write(msg)
if nowait:
return
return None
ret = self.transport.read()
print("DEBUGLINK RECV", pprint(ret))
return ret
def read_pin(self):

View File

@ -1,89 +0,0 @@
import sys
from functools import reduce
import binascii
from . import ed25519raw
def combine_keys(pks):
P = [ed25519raw.decodepoint(pk) for pk in pks]
combine = reduce(ed25519raw.edwards, P)
return ed25519raw.encodepoint(combine)
def combine_sig(R, sigs):
S = [ed25519raw.decodeint(si) for si in sigs]
s = sum(S) % ed25519raw.l
sig = R + ed25519raw.encodeint(s)
return sig
def get_nonce(sk, data, ctr):
h = ed25519raw.H(sk)
b = ed25519raw.b
r = ed25519raw.Hint(bytes([h[i] for i in range(b >> 3, b >> 2)]) + data + binascii.unhexlify('%08x' % ctr))
R = ed25519raw.scalarmult(ed25519raw.B, r)
return r, ed25519raw.encodepoint(R)
def self_test(digest):
def to_hex(by):
return binascii.hexlify(by).decode()
N = 3
keyset = [0, 2]
digest = binascii.unhexlify(digest)
print('Digest: %s' % to_hex(digest))
sks = []
pks = []
nonces = []
commits = []
sigs = []
for i in range(0, N):
print('----- Key %d ------' % (i + 1))
seckey = (chr(0x41 + i) * 32).encode()
pubkey = ed25519raw.publickey(seckey)
print('Secret Key: %s' % to_hex(seckey))
print('Public Key: %s' % to_hex(pubkey))
sks.append(seckey)
pks.append(pubkey)
ctr = 0
r, R = get_nonce(seckey, digest, ctr)
print('Local nonce: %s' % to_hex(ed25519raw.encodeint(r)))
print('Local commit: %s' % to_hex(R))
nonces.append(r)
commits.append(R)
global_pk = combine_keys([pks[i] for i in keyset])
global_R = combine_keys([commits[i] for i in keyset])
print('-----------------')
print('Global pubkey: %s' % to_hex(global_pk))
print('Global commit: %s' % to_hex(global_R))
print('-----------------')
for i in range(0, N):
seckey = sks[i]
pubkey = pks[i]
r = nonces[i]
R = commits[i]
h = ed25519raw.H(seckey)
b = ed25519raw.b
a = 2**(b - 2) + sum(2**i * ed25519raw.bit(h, i) for i in range(3, b - 2))
S = (r + ed25519raw.Hint(global_R + global_pk + digest) * a) % ed25519raw.l
print('Local sig %d: %s' % (i + 1, to_hex(ed25519raw.encodeint(S))))
sigs.append(ed25519raw.encodeint(S))
print('-----------------')
sig = combine_sig(global_R, [sigs[i] for i in keyset])
print('Global sig: %s' % to_hex(sig))
ed25519raw.checkvalid(sig, digest, global_pk)
print('Valid Signature!')
if __name__ == '__main__':
if len(sys.argv) > 1:
self_test(digest=sys.argv[1])
else:
self_test(digest='4a5e1e4baab89f3a32518a88c31bc87f618f76673e2cc77ab2127b7afdeda33b')

34
trezorlib/log.py Normal file
View File

@ -0,0 +1,34 @@
import logging
from typing import Set, Type, Optional
from . import protobuf
OMITTED_MESSAGES = set() # type: Set[Type[protobuf.MessageType]]
class PrettyProtobufFormatter(logging.Formatter):
def format(self, record: logging.LogRecord) -> str:
time = self.formatTime(record)
message = '[{time}] {source} {level}: {msg}'.format(
time=time, level=record.levelname.upper(),
source=record.name,
msg=super().format(record))
if hasattr(record, 'protobuf'):
if type(record.protobuf) in OMITTED_MESSAGES:
message += " ({} bytes)".format(record.protobuf.ByteSize())
else:
message += "\n" + protobuf.format_message(record.protobuf)
return message
def enable_debug_output(handler: Optional[logging.Handler] = None):
if handler is None:
handler = logging.StreamHandler()
formatter = PrettyProtobufFormatter()
handler.setFormatter(formatter)
logger = logging.getLogger('trezorlib')
logger.setLevel(logging.DEBUG)
logger.addHandler(handler)

View File

@ -39,7 +39,9 @@ required:
>>> """
'''
import binascii
from io import BytesIO
from typing import Any, Optional
_UVARINT_BUFFER = bytearray(1)
@ -344,3 +346,58 @@ def dump_message(writer, msg):
else:
raise TypeError
def format_message(pb: MessageType,
indent: int = 0,
sep: str = ' ' * 4,
truncate_after: Optional[int] = 256,
truncate_to: Optional[int] = 64) -> str:
def mostly_printable(bytes):
if not bytes:
return True
printable = sum(1 for byte in bytes if 0x20 <= byte <= 0x7e)
return printable / len(bytes) > 0.8
def pformat_value(value: Any, indent: int) -> str:
level = sep * indent
leadin = sep * (indent + 1)
if isinstance(value, MessageType):
return format_message(value, indent, sep)
if isinstance(value, list):
# short list of simple values
if not value or not isinstance(value[0], MessageType):
return repr(value)
# long list, one line per entry
lines = ['[', level + ']']
lines[1:1] = [leadin + pformat_value(x, indent + 1) + ',' for x in value]
return '\n'.join(lines)
if isinstance(value, dict):
lines = ['{']
for key, val in sorted(value.items()):
if val is None or val == []:
continue
lines.append(leadin + key + ': ' + pformat_value(val, indent + 1) + ',')
lines.append(level + '}')
return '\n'.join(lines)
if isinstance(value, (bytes, bytearray)):
length = len(value)
suffix = ''
if truncate_after and length > truncate_after:
suffix = '...'
value = value[:truncate_to or 0]
if mostly_printable(value):
output = repr(value)
else:
output = '0x' + binascii.hexlify(value).decode('ascii')
return '{} bytes {}{}'.format(length, output, suffix)
return repr(value)
return '{name} ({size} bytes) {content}'.format(
name=pb.__class__.__name__,
size=pb.ByteSize(),
content=pformat_value(pb.__dict__, indent)
)

View File

@ -19,22 +19,30 @@
from __future__ import absolute_import
from io import BytesIO
import logging
import struct
from typing import Tuple, Type
from . import mapping
from . import protobuf
from .transport import Transport
REPLEN = 64
LOG = logging.getLogger(__name__)
class ProtocolV1(object):
def session_begin(self, transport):
class ProtocolV1:
def session_begin(self, transport: Transport) -> None:
pass
def session_end(self, transport):
def session_end(self, transport: Transport) -> None:
pass
def write(self, transport, msg):
def write(self, transport: Transport, msg: protobuf.MessageType) -> None:
LOG.debug("sending message: {}".format(msg.__class__.__name__),
extra={'protobuf': msg})
data = BytesIO()
protobuf.dump_message(data, msg)
ser = data.getvalue()
@ -48,10 +56,10 @@ class ProtocolV1(object):
transport.write_chunk(chunk)
data = data[63:]
def read(self, transport):
def read(self, transport: Transport) -> protobuf.MessageType:
# Read header with first part of message data
chunk = transport.read_chunk()
(msg_type, datalen, data) = self.parse_first(chunk)
msg_type, datalen, data = self.parse_first(chunk)
# Read the rest of the message
while len(data) < datalen:
@ -63,21 +71,23 @@ class ProtocolV1(object):
# Parse to protobuf
msg = protobuf.load_message(data, mapping.get_class(msg_type))
LOG.debug("received message: {}".format(msg.__class__.__name__),
extra={'protobuf': msg})
return msg
def parse_first(self, chunk):
def parse_first(self, chunk: bytes) -> Tuple[int, int, bytes]:
if chunk[:3] != b'?##':
raise RuntimeError('Unexpected magic characters')
try:
headerlen = struct.calcsize('>HL')
(msg_type, datalen) = struct.unpack('>HL', chunk[3:3 + headerlen])
msg_type, datalen = struct.unpack('>HL', chunk[3:3 + headerlen])
except:
raise RuntimeError('Cannot parse header')
data = chunk[3 + headerlen:]
return (msg_type, datalen, data)
return msg_type, datalen, data
def parse_next(self, chunk):
def parse_next(self, chunk: bytes) -> bytes:
if chunk[:1] != b'?':
raise RuntimeError('Unexpected magic characters')
return chunk[1:]

View File

@ -18,28 +18,34 @@
from __future__ import absolute_import
import struct
from io import BytesIO
from . import messages as proto
import logging
import struct
from typing import Tuple
from . import mapping
from . import protobuf
from .transport import Transport
REPLEN = 64
LOG = logging.getLogger(__name__)
class ProtocolV2(object):
def __init__(self):
class ProtocolV2:
def __init__(self) -> None:
self.session = None
def session_begin(self, transport):
def session_begin(self, transport: Transport) -> None:
chunk = struct.pack('>B', 0x03)
chunk = chunk.ljust(REPLEN, b'\x00')
transport.write_chunk(chunk)
resp = transport.read_chunk()
self.session = self.parse_session_open(resp)
LOG.debug("[session {}] session started".format(self.session))
def session_end(self, transport):
def session_end(self, transport: Transport) -> None:
if not self.session:
return
chunk = struct.pack('>BL', 0x04, self.session)
@ -49,12 +55,15 @@ class ProtocolV2(object):
(magic, ) = struct.unpack('>B', resp[:1])
if magic != 0x04:
raise RuntimeError('Expected session close')
LOG.debug("[session {}] session ended".format(self.session))
self.session = None
def write(self, transport, msg):
def write(self, transport: Transport, msg: protobuf.MessageType) -> None:
if not self.session:
raise RuntimeError('Missing session for v2 protocol')
LOG.debug("[session {}] sending message: {}".format(self.session, msg.__class__.__name__),
extra={'protobuf': msg})
# Serialize whole message
data = BytesIO()
protobuf.dump_message(data, msg)
@ -76,7 +85,7 @@ class ProtocolV2(object):
data = data[datalen:]
seq += 1
def read(self, transport):
def read(self, transport: Transport) -> protobuf.MessageType:
if not self.session:
raise RuntimeError('Missing session for v2 protocol')
@ -95,12 +104,14 @@ class ProtocolV2(object):
# Parse to protobuf
msg = protobuf.load_message(data, mapping.get_class(msg_type))
LOG.debug("[session {}] received message: {}".format(self.session, msg.__class__.__name__),
extra={'protobuf': msg})
return msg
def parse_first(self, chunk):
def parse_first(self, chunk: bytes) -> Tuple[int, int, bytes]:
try:
headerlen = struct.calcsize('>BLLL')
(magic, session, msg_type, datalen) = struct.unpack('>BLLL', chunk[:headerlen])
magic, session, msg_type, datalen = struct.unpack('>BLLL', chunk[:headerlen])
except:
raise RuntimeError('Cannot parse header')
if magic != 0x01:
@ -109,10 +120,10 @@ class ProtocolV2(object):
raise RuntimeError('Session id mismatch')
return msg_type, datalen, chunk[headerlen:]
def parse_next(self, chunk):
def parse_next(self, chunk: bytes) -> bytes:
try:
headerlen = struct.calcsize('>BLL')
(magic, session, sequence) = struct.unpack('>BLL', chunk[:headerlen])
magic, session, sequence = struct.unpack('>BLL', chunk[:headerlen])
except:
raise RuntimeError('Cannot parse header')
if magic != 0x02:
@ -121,10 +132,10 @@ class ProtocolV2(object):
raise RuntimeError('Session id mismatch')
return chunk[headerlen:]
def parse_session_open(self, chunk):
def parse_session_open(self, chunk: bytes) -> int:
try:
headerlen = struct.calcsize('>BL')
(magic, session) = struct.unpack('>BL', chunk[:headerlen])
magic, session = struct.unpack('>BL', chunk[:headerlen])
except:
raise RuntimeError('Cannot parse header')
if magic != 0x03:

View File

@ -30,14 +30,7 @@ OP_MANAGE_DATA = 10
OP_BUMP_SEQUENCE = 11
def expand_path_or_default(client, address):
"""Uses client to parse address and returns an array of integers
If no address is specified, the default of m/44'/148'/0' is used
"""
if address:
return client.expand_path(address)
else:
return client.expand_path("m/44'/148'/0'")
DEFAULT_BIP32_PATH = "m/44h/148h/0h"
def address_from_public_key(pk_bytes):

View File

@ -18,13 +18,11 @@
from __future__ import print_function
from binascii import hexlify, unhexlify
import pytest
import os
from trezorlib import coins
from trezorlib import tx_api
from trezorlib.client import TrezorClient, TrezorClientDebugLink
from trezorlib.client import TrezorClientDebugLink
from trezorlib.transport import get_transport
tests_dir = os.path.dirname(os.path.abspath(__file__))

View File

@ -2,6 +2,7 @@ import pytest
from . import common
from trezorlib.client import TrezorClient
from trezorlib import log
def device_version():
@ -22,6 +23,11 @@ except:
TREZOR_VERSION = None
def pytest_configure(config):
if config.getoption('verbose'):
log.enable_debug_output()
def pytest_addoption(parser):
parser.addini("run_xfail", "List of markers that will run even if marked as xfail", "args", [])

View File

@ -16,7 +16,7 @@
# You should have received a copy of the GNU Lesser General Public License
# along with this library. If not, see <http://www.gnu.org/licenses/>.
from .common import *
from .common import TrezorTest
from trezorlib import messages

View File

@ -15,11 +15,10 @@
#
# You should have received a copy of the GNU Lesser General Public License
# along with this library. If not, see <http://www.gnu.org/licenses/>.
from __future__ import print_function
from .common import *
import time
import pytest
from .common import TrezorTest
class TestBip32Speed(TrezorTest):

View File

@ -16,10 +16,13 @@
# You should have received a copy of the GNU Lesser General Public License
# along with this library. If not, see <http://www.gnu.org/licenses/>.
from .common import *
import pytest
from hashlib import sha256
from trezorlib import ed25519raw, ed25519cosi
from .common import TrezorTest
from trezorlib import cosi
from trezorlib.tools import parse_path
@pytest.mark.skip_t2
@ -30,9 +33,9 @@ class TestCosi(TrezorTest):
digest = sha256(b'this is a message').digest()
c0 = self.client.cosi_commit(self.client.expand_path("10018'/0'"), digest)
c1 = self.client.cosi_commit(self.client.expand_path("10018'/1'"), digest)
c2 = self.client.cosi_commit(self.client.expand_path("10018'/2'"), digest)
c0 = self.client.cosi_commit(parse_path("10018'/0'"), digest)
c1 = self.client.cosi_commit(parse_path("10018'/1'"), digest)
c2 = self.client.cosi_commit(parse_path("10018'/2'"), digest)
assert c0.pubkey != c1.pubkey
assert c0.pubkey != c2.pubkey
@ -44,9 +47,9 @@ class TestCosi(TrezorTest):
digestb = sha256(b'this is a different message').digest()
c0b = self.client.cosi_commit(self.client.expand_path("10018'/0'"), digestb)
c1b = self.client.cosi_commit(self.client.expand_path("10018'/1'"), digestb)
c2b = self.client.cosi_commit(self.client.expand_path("10018'/2'"), digestb)
c0b = self.client.cosi_commit(parse_path("10018'/0'"), digestb)
c1b = self.client.cosi_commit(parse_path("10018'/1'"), digestb)
c2b = self.client.cosi_commit(parse_path("10018'/2'"), digestb)
assert c0.pubkey == c0b.pubkey
assert c1.pubkey == c1b.pubkey
@ -61,17 +64,36 @@ class TestCosi(TrezorTest):
digest = sha256(b'this is a message').digest()
c0 = self.client.cosi_commit(self.client.expand_path("10018'/0'"), digest)
c1 = self.client.cosi_commit(self.client.expand_path("10018'/1'"), digest)
c2 = self.client.cosi_commit(self.client.expand_path("10018'/2'"), digest)
c0 = self.client.cosi_commit(parse_path("10018'/0'"), digest)
c1 = self.client.cosi_commit(parse_path("10018'/1'"), digest)
c2 = self.client.cosi_commit(parse_path("10018'/2'"), digest)
global_pk = ed25519cosi.combine_keys([c0.pubkey, c1.pubkey, c2.pubkey])
global_R = ed25519cosi.combine_keys([c0.commitment, c1.commitment, c2.commitment])
global_pk = cosi.combine_keys([c0.pubkey, c1.pubkey, c2.pubkey])
global_R = cosi.combine_keys([c0.commitment, c1.commitment, c2.commitment])
sig0 = self.client.cosi_sign(self.client.expand_path("10018'/0'"), digest, global_R, global_pk)
sig1 = self.client.cosi_sign(self.client.expand_path("10018'/1'"), digest, global_R, global_pk)
sig2 = self.client.cosi_sign(self.client.expand_path("10018'/2'"), digest, global_R, global_pk)
sig0 = self.client.cosi_sign(parse_path("10018'/0'"), digest, global_R, global_pk)
sig1 = self.client.cosi_sign(parse_path("10018'/1'"), digest, global_R, global_pk)
sig2 = self.client.cosi_sign(parse_path("10018'/2'"), digest, global_R, global_pk)
sig = ed25519cosi.combine_sig(global_R, [sig0.signature, sig1.signature, sig2.signature])
sig = cosi.combine_sig(global_R, [sig0.signature, sig1.signature, sig2.signature])
ed25519raw.checkvalid(sig, digest, global_pk)
cosi.verify(sig, digest, global_pk)
def test_cosi_compat(self):
self.setup_mnemonic_pin_passphrase()
digest = sha256(b'this is not a pipe').digest()
remote_commit = self.client.cosi_commit(parse_path("10018'/0'"), digest)
local_privkey = sha256(b'private key').digest()[:32]
local_pubkey = cosi.pubkey_from_privkey(local_privkey)
local_nonce, local_commitment = cosi.get_nonce(local_privkey, digest, 42)
global_pk = cosi.combine_keys([remote_commit.pubkey, local_pubkey])
global_R = cosi.combine_keys([remote_commit.commitment, local_commitment])
remote_sig = self.client.cosi_sign(parse_path("10018'/0'"), digest, global_R, global_pk)
local_sig = cosi.sign_with_privkey(digest, local_privkey, global_pk, local_nonce, global_R)
sig = cosi.combine_sig(global_R, [remote_sig.signature, local_sig])
cosi.verify(sig, digest, global_pk)

View File

@ -15,9 +15,9 @@
#
# You should have received a copy of the GNU Lesser General Public License
# along with this library. If not, see <http://www.gnu.org/licenses/>.
import pytest
from .common import *
from .common import TrezorTest
from trezorlib import messages as proto

View File

@ -15,8 +15,9 @@
#
# You should have received a copy of the GNU Lesser General Public License
# along with this library. If not, see <http://www.gnu.org/licenses/>.
import pytest
from .common import *
from .common import TrezorTest
import time
from trezorlib import messages as proto

View File

@ -15,8 +15,9 @@
#
# You should have received a copy of the GNU Lesser General Public License
# along with this library. If not, see <http://www.gnu.org/licenses/>.
import pytest
from .common import *
from .common import TrezorTest
from trezorlib import messages as proto

View File

@ -15,8 +15,10 @@
#
# You should have received a copy of the GNU Lesser General Public License
# along with this library. If not, see <http://www.gnu.org/licenses/>.
from binascii import hexlify, unhexlify
import pytest
from .common import *
from .common import TrezorTest
class TestMsgCipherkeyvalue(TrezorTest):

View File

@ -15,8 +15,9 @@
#
# You should have received a copy of the GNU Lesser General Public License
# along with this library. If not, see <http://www.gnu.org/licenses/>.
import pytest
from .common import *
from .common import TrezorTest
from trezorlib import messages as proto

View File

@ -15,9 +15,10 @@
#
# You should have received a copy of the GNU Lesser General Public License
# along with this library. If not, see <http://www.gnu.org/licenses/>.
from binascii import hexlify
import pytest
from .common import *
from .common import TrezorTest
@pytest.mark.ethereum

View File

@ -14,8 +14,10 @@
#
# You should have received a copy of the GNU Lesser General Public License
# along with this library. If not, see <http://www.gnu.org/licenses/>.
from binascii import hexlify
import pytest
from .common import *
from .common import TrezorTest
@pytest.mark.ethereum

View File

@ -15,9 +15,10 @@
#
# You should have received a copy of the GNU Lesser General Public License
# along with this library. If not, see <http://www.gnu.org/licenses/>.
from binascii import unhexlify, hexlify
import pytest
from .common import *
from .common import TrezorTest
from trezorlib import messages as proto

View File

@ -14,8 +14,11 @@
#
# You should have received a copy of the GNU Lesser General Public License
# along with this library. If not, see <http://www.gnu.org/licenses/>.
from binascii import unhexlify
from .common import *
import pytest
from .common import TrezorTest
@pytest.mark.ethereum

View File

@ -16,9 +16,13 @@
# You should have received a copy of the GNU Lesser General Public License
# along with this library. If not, see <http://www.gnu.org/licenses/>.
from .common import *
import pytest
from .common import TrezorTest
from ..support import ckd_public as bip32
from trezorlib import messages as proto
import trezorlib.ckd_public as bip32
from trezorlib.tools import parse_path
class TestMsgGetaddress(TrezorTest):
@ -45,14 +49,14 @@ class TestMsgGetaddress(TrezorTest):
def test_bch(self):
self.setup_mnemonic_allallall()
assert self.client.get_address('Bcash', self.client.expand_path("44'/145'/0'/0/0")) == 'bitcoincash:qr08q88p9etk89wgv05nwlrkm4l0urz4cyl36hh9sv'
assert self.client.get_address('Bcash', self.client.expand_path("44'/145'/0'/0/1")) == 'bitcoincash:qr23ajjfd9wd73l87j642puf8cad20lfmqdgwvpat4'
assert self.client.get_address('Bcash', self.client.expand_path("44'/145'/0'/1/0")) == 'bitcoincash:qzc5q87w069lzg7g3gzx0c8dz83mn7l02scej5aluw'
assert self.client.get_address('Bcash', parse_path("44'/145'/0'/0/0")) == 'bitcoincash:qr08q88p9etk89wgv05nwlrkm4l0urz4cyl36hh9sv'
assert self.client.get_address('Bcash', parse_path("44'/145'/0'/0/1")) == 'bitcoincash:qr23ajjfd9wd73l87j642puf8cad20lfmqdgwvpat4'
assert self.client.get_address('Bcash', parse_path("44'/145'/0'/1/0")) == 'bitcoincash:qzc5q87w069lzg7g3gzx0c8dz83mn7l02scej5aluw'
def test_bch_multisig(self):
self.setup_mnemonic_allallall()
xpubs = []
for n in map(lambda index: self.client.get_public_node(self.client.expand_path("44'/145'/" + str(index) + "'")), range(1, 4)):
for n in map(lambda index: self.client.get_public_node(parse_path("44'/145'/" + str(index) + "'")), range(1, 4)):
xpubs.append(n.xpub)
def getmultisig(chain, nr, signatures=[b'', b'', b''], xpubs=xpubs):
@ -62,8 +66,8 @@ class TestMsgGetaddress(TrezorTest):
m=2,
)
for nr in range(1, 4):
assert self.client.get_address('Bcash', self.client.expand_path("44'/145'/" + str(nr) + "'/0/0"), show_display=(nr == 1), multisig=getmultisig(0, 0)) == 'bitcoincash:pqguz4nqq64jhr5v3kvpq4dsjrkda75hwy86gq0qzw'
assert self.client.get_address('Bcash', self.client.expand_path("44'/145'/" + str(nr) + "'/1/0"), show_display=(nr == 1), multisig=getmultisig(1, 0)) == 'bitcoincash:pp6kcpkhua7789g2vyj0qfkcux3yvje7euhyhltn0a'
assert self.client.get_address('Bcash', parse_path("44'/145'/" + str(nr) + "'/0/0"), show_display=(nr == 1), multisig=getmultisig(0, 0)) == 'bitcoincash:pqguz4nqq64jhr5v3kvpq4dsjrkda75hwy86gq0qzw'
assert self.client.get_address('Bcash', parse_path("44'/145'/" + str(nr) + "'/1/0"), show_display=(nr == 1), multisig=getmultisig(1, 0)) == 'bitcoincash:pp6kcpkhua7789g2vyj0qfkcux3yvje7euhyhltn0a'
def test_public_ckd(self):
self.setup_mnemonic_nopin_nopassphrase()

View File

@ -15,23 +15,24 @@
# You should have received a copy of the GNU Lesser General Public License
# along with this library. If not, see <http://www.gnu.org/licenses/>.
from .common import *
import trezorlib.ckd_public as bip32
from .common import TrezorTest
from ..support import ckd_public as bip32
from trezorlib import messages as proto
from trezorlib.tools import parse_path
class TestMsgGetaddressSegwit(TrezorTest):
def test_show_segwit(self):
self.setup_mnemonic_allallall()
assert self.client.get_address("Testnet", self.client.expand_path("49'/1'/0'/1/0"), True, None, script_type=proto.InputScriptType.SPENDP2SHWITNESS) == '2N1LGaGg836mqSQqiuUBLfcyGBhyZbremDX'
assert self.client.get_address("Testnet", self.client.expand_path("49'/1'/0'/0/0"), False, None, script_type=proto.InputScriptType.SPENDP2SHWITNESS) == '2N4Q5FhU2497BryFfUgbqkAJE87aKHUhXMp'
assert self.client.get_address("Testnet", self.client.expand_path("44'/1'/0'/0/0"), False, None, script_type=proto.InputScriptType.SPENDP2SHWITNESS) == '2N6UeBoqYEEnybg4cReFYDammpsyDw8R2Mc'
assert self.client.get_address("Testnet", self.client.expand_path("44'/1'/0'/0/0"), False, None, script_type=proto.InputScriptType.SPENDADDRESS) == 'mvbu1Gdy8SUjTenqerxUaZyYjmveZvt33q'
assert self.client.get_address("Testnet", parse_path("49'/1'/0'/1/0"), True, None, script_type=proto.InputScriptType.SPENDP2SHWITNESS) == '2N1LGaGg836mqSQqiuUBLfcyGBhyZbremDX'
assert self.client.get_address("Testnet", parse_path("49'/1'/0'/0/0"), False, None, script_type=proto.InputScriptType.SPENDP2SHWITNESS) == '2N4Q5FhU2497BryFfUgbqkAJE87aKHUhXMp'
assert self.client.get_address("Testnet", parse_path("44'/1'/0'/0/0"), False, None, script_type=proto.InputScriptType.SPENDP2SHWITNESS) == '2N6UeBoqYEEnybg4cReFYDammpsyDw8R2Mc'
assert self.client.get_address("Testnet", parse_path("44'/1'/0'/0/0"), False, None, script_type=proto.InputScriptType.SPENDADDRESS) == 'mvbu1Gdy8SUjTenqerxUaZyYjmveZvt33q'
def test_show_multisig_3(self):
self.setup_mnemonic_allallall()
nodes = map(lambda index: self.client.get_public_node(self.client.expand_path("999'/1'/%d'" % index)), range(1, 4))
nodes = map(lambda index: self.client.get_public_node(parse_path("999'/1'/%d'" % index)), range(1, 4))
multisig1 = proto.MultisigRedeemScriptType(
pubkeys=list(map(lambda n: proto.HDNodePathType(node=bip32.deserialize(n.xpub), address_n=[2, 0]), nodes)),
signatures=[b'', b'', b''],
@ -43,4 +44,4 @@ class TestMsgGetaddressSegwit(TrezorTest):
# m=2,
# )
for i in [1, 2, 3]:
assert self.client.get_address("Testnet", self.client.expand_path("999'/1'/%d'/2/0" % i), False, multisig1, script_type=proto.InputScriptType.SPENDP2SHWITNESS) == '2N2MxyAfifVhb3AMagisxaj3uij8bfXqf4Y'
assert self.client.get_address("Testnet", parse_path("999'/1'/%d'/2/0" % i), False, multisig1, script_type=proto.InputScriptType.SPENDP2SHWITNESS) == '2N2MxyAfifVhb3AMagisxaj3uij8bfXqf4Y'

View File

@ -15,23 +15,24 @@
# You should have received a copy of the GNU Lesser General Public License
# along with this library. If not, see <http://www.gnu.org/licenses/>.
from .common import *
import trezorlib.ckd_public as bip32
from .common import TrezorTest
from ..support import ckd_public as bip32
from trezorlib import messages as proto
from trezorlib.tools import parse_path
class TestMsgGetaddressSegwitNative(TrezorTest):
def test_show_segwit(self):
self.setup_mnemonic_allallall()
assert self.client.get_address("Testnet", self.client.expand_path("49'/1'/0'/0/0"), True, None, script_type=proto.InputScriptType.SPENDWITNESS) == 'tb1qqzv60m9ajw8drqulta4ld4gfx0rdh82un5s65s'
assert self.client.get_address("Testnet", self.client.expand_path("49'/1'/0'/1/0"), False, None, script_type=proto.InputScriptType.SPENDWITNESS) == 'tb1q694ccp5qcc0udmfwgp692u2s2hjpq5h407urtu'
assert self.client.get_address("Testnet", self.client.expand_path("44'/1'/0'/0/0"), False, None, script_type=proto.InputScriptType.SPENDWITNESS) == 'tb1q54un3q39sf7e7tlfq99d6ezys7qgc62a6rxllc'
assert self.client.get_address("Testnet", self.client.expand_path("44'/1'/0'/0/0"), False, None, script_type=proto.InputScriptType.SPENDADDRESS) == 'mvbu1Gdy8SUjTenqerxUaZyYjmveZvt33q'
assert self.client.get_address("Testnet", parse_path("49'/1'/0'/0/0"), True, None, script_type=proto.InputScriptType.SPENDWITNESS) == 'tb1qqzv60m9ajw8drqulta4ld4gfx0rdh82un5s65s'
assert self.client.get_address("Testnet", parse_path("49'/1'/0'/1/0"), False, None, script_type=proto.InputScriptType.SPENDWITNESS) == 'tb1q694ccp5qcc0udmfwgp692u2s2hjpq5h407urtu'
assert self.client.get_address("Testnet", parse_path("44'/1'/0'/0/0"), False, None, script_type=proto.InputScriptType.SPENDWITNESS) == 'tb1q54un3q39sf7e7tlfq99d6ezys7qgc62a6rxllc'
assert self.client.get_address("Testnet", parse_path("44'/1'/0'/0/0"), False, None, script_type=proto.InputScriptType.SPENDADDRESS) == 'mvbu1Gdy8SUjTenqerxUaZyYjmveZvt33q'
def test_show_multisig_3(self):
self.setup_mnemonic_allallall()
nodes = [self.client.get_public_node(self.client.expand_path("999'/1'/%d'" % index)) for index in range(1, 4)]
nodes = [self.client.get_public_node(parse_path("999'/1'/%d'" % index)) for index in range(1, 4)]
multisig1 = proto.MultisigRedeemScriptType(
pubkeys=list(map(lambda n: proto.HDNodePathType(node=bip32.deserialize(n.xpub), address_n=[2, 0]), nodes)),
signatures=[b'', b'', b''],
@ -43,5 +44,5 @@ class TestMsgGetaddressSegwitNative(TrezorTest):
m=2,
)
for i in [1, 2, 3]:
assert self.client.get_address("Testnet", self.client.expand_path("999'/1'/%d'/2/1" % i), False, multisig2, script_type=proto.InputScriptType.SPENDWITNESS) == 'tb1qch62pf820spe9mlq49ns5uexfnl6jzcezp7d328fw58lj0rhlhasge9hzy'
assert self.client.get_address("Testnet", self.client.expand_path("999'/1'/%d'/2/0" % i), False, multisig1, script_type=proto.InputScriptType.SPENDWITNESS) == 'tb1qr6xa5v60zyt3ry9nmfew2fk5g9y3gerkjeu6xxdz7qga5kknz2ssld9z2z'
assert self.client.get_address("Testnet", parse_path("999'/1'/%d'/2/1" % i), False, multisig2, script_type=proto.InputScriptType.SPENDWITNESS) == 'tb1qch62pf820spe9mlq49ns5uexfnl6jzcezp7d328fw58lj0rhlhasge9hzy'
assert self.client.get_address("Testnet", parse_path("999'/1'/%d'/2/0" % i), False, multisig1, script_type=proto.InputScriptType.SPENDWITNESS) == 'tb1qr6xa5v60zyt3ry9nmfew2fk5g9y3gerkjeu6xxdz7qga5kknz2ssld9z2z'

View File

@ -16,8 +16,8 @@
# You should have received a copy of the GNU Lesser General Public License
# along with this library. If not, see <http://www.gnu.org/licenses/>.
from .common import *
import trezorlib.ckd_public as bip32
from .common import TrezorTest
from ..support import ckd_public as bip32
from trezorlib import messages as proto

View File

@ -15,8 +15,9 @@
#
# You should have received a copy of the GNU Lesser General Public License
# along with this library. If not, see <http://www.gnu.org/licenses/>.
from binascii import unhexlify
from .common import *
from .common import TrezorTest
from trezorlib import messages as proto

View File

@ -16,10 +16,9 @@
# You should have received a copy of the GNU Lesser General Public License
# along with this library. If not, see <http://www.gnu.org/licenses/>.
from __future__ import print_function
import math
from .common import *
from .common import TrezorTest
import trezorlib.messages as proto

View File

@ -16,8 +16,8 @@
# You should have received a copy of the GNU Lesser General Public License
# along with this library. If not, see <http://www.gnu.org/licenses/>.
from .common import *
import trezorlib.ckd_public as bip32
from .common import TrezorTest
from ..support import ckd_public as bip32
class TestMsgGetpublickey(TrezorTest):

View File

@ -16,8 +16,10 @@
# You should have received a copy of the GNU Lesser General Public License
# along with this library. If not, see <http://www.gnu.org/licenses/>.
from .common import *
import trezorlib.ckd_public as bip32
from binascii import hexlify
import pytest
from .common import TrezorTest
from trezorlib.client import CallException

View File

@ -21,6 +21,7 @@ import pytest
from .common import TrezorTest
from trezorlib import messages as proto
from trezorlib.tools import parse_path
PUBLIC_KEY = unhexlify('eb56d7bbb5e8ea9269405f7a8527fe126023d1db2c973cfac6f760b60ae27294')
@ -41,7 +42,7 @@ class TestMsgLiskSignTx(TrezorTest):
)
])
self.client.lisk_sign_tx(self.client.expand_path("m/44'/134'/0'/0'"), {
self.client.lisk_sign_tx(parse_path("m/44'/134'/0'/0'"), {
"amount": "10000000",
"recipientId": "9971262264659915921L",
"timestamp": 57525937,
@ -62,7 +63,7 @@ class TestMsgLiskSignTx(TrezorTest):
)
])
self.client.lisk_sign_tx(self.client.expand_path("m/44'/134'/0'/0'"), {
self.client.lisk_sign_tx(parse_path("m/44'/134'/0'/0'"), {
"amount": "10000000",
"recipientId": "9971262264659915921L",
"timestamp": 57525937,
@ -85,7 +86,7 @@ class TestMsgLiskSignTx(TrezorTest):
)
])
self.client.lisk_sign_tx(self.client.expand_path("m/44'/134'/0'/0'"), {
self.client.lisk_sign_tx(parse_path("m/44'/134'/0'/0'"), {
"amount": "0",
"timestamp": 57525937,
"type": 1,
@ -109,7 +110,7 @@ class TestMsgLiskSignTx(TrezorTest):
)
])
self.client.lisk_sign_tx(self.client.expand_path("m/44'/134'/0'/0'"), {
self.client.lisk_sign_tx(parse_path("m/44'/134'/0'/0'"), {
"amount": "0",
"timestamp": 57525937,
"type": 2,
@ -133,7 +134,7 @@ class TestMsgLiskSignTx(TrezorTest):
)
])
self.client.lisk_sign_tx(self.client.expand_path("m/44'/134'/0'/0'"), {
self.client.lisk_sign_tx(parse_path("m/44'/134'/0'/0'"), {
"amount": "0",
"timestamp": 57525937,
"type": 3,
@ -158,7 +159,7 @@ class TestMsgLiskSignTx(TrezorTest):
)
])
self.client.lisk_sign_tx(self.client.expand_path("m/44'/134'/0'/0'"), {
self.client.lisk_sign_tx(parse_path("m/44'/134'/0'/0'"), {
"amount": "0",
"timestamp": 57525937,
"type": 4,

View File

@ -15,8 +15,9 @@
#
# You should have received a copy of the GNU Lesser General Public License
# along with this library. If not, see <http://www.gnu.org/licenses/>.
import pytest
from .common import *
from .common import TrezorTest
@pytest.mark.skip_t2

View File

@ -15,8 +15,9 @@
#
# You should have received a copy of the GNU Lesser General Public License
# along with this library. If not, see <http://www.gnu.org/licenses/>.
import pytest
from .common import *
from .common import TrezorTest
@pytest.mark.skip_t2

View File

@ -15,7 +15,10 @@
# You should have received a copy of the GNU Lesser General Public License
# along with this library. If not, see <http://www.gnu.org/licenses/>.
from .common import *
import pytest
from .common import TrezorTest
from trezorlib.tools import parse_path
@pytest.mark.nem
@ -24,5 +27,5 @@ class TestMsgNEMGetaddress(TrezorTest):
def test_nem_getaddress(self):
self.setup_mnemonic_nopin_nopassphrase()
assert self.client.nem_get_address(self.client.expand_path("m/44'/1'/0'/0'/0'"), 0x68) == "NB3JCHVARQNGDS3UVGAJPTFE22UQFGMCQGHUBWQN"
assert self.client.nem_get_address(self.client.expand_path("m/44'/1'/0'/0'/0'"), 0x98) == "TB3JCHVARQNGDS3UVGAJPTFE22UQFGMCQHSBNBMF"
assert self.client.nem_get_address(parse_path("m/44'/1'/0'/0'/0'"), 0x68) == "NB3JCHVARQNGDS3UVGAJPTFE22UQFGMCQGHUBWQN"
assert self.client.nem_get_address(parse_path("m/44'/1'/0'/0'/0'"), 0x98) == "TB3JCHVARQNGDS3UVGAJPTFE22UQFGMCQHSBNBMF"

View File

@ -15,8 +15,12 @@
# You should have received a copy of the GNU Lesser General Public License
# along with this library. If not, see <http://www.gnu.org/licenses/>.
from .common import *
import pytest
from binascii import hexlify
from .common import TrezorTest
from trezorlib import nem
from trezorlib.tools import parse_path
# assertion data from T1
@ -27,7 +31,7 @@ class TestMsgNEMSignTxMosaics(TrezorTest):
def test_nem_signtx_mosaic_supply_change(self):
self.setup_mnemonic_nopin_nopassphrase()
tx = self.client.nem_sign_tx(self.client.expand_path("m/44'/1'/0'/0'/0'"), {
tx = self.client.nem_sign_tx(parse_path("m/44'/1'/0'/0'/0'"), {
"timeStamp": 74649215,
"fee": 2000000,
"type": nem.TYPE_MOSAIC_SUPPLY_CHANGE,
@ -51,7 +55,7 @@ class TestMsgNEMSignTxMosaics(TrezorTest):
def test_nem_signtx_mosaic_creation(self):
self.setup_mnemonic_nopin_nopassphrase()
tx = self.client.nem_sign_tx(self.client.expand_path("m/44'/1'/0'/0'/0'"), {
tx = self.client.nem_sign_tx(parse_path("m/44'/1'/0'/0'/0'"), {
"timeStamp": 74649215,
"fee": 2000000,
"type": nem.TYPE_MOSAIC_CREATION,
@ -78,7 +82,7 @@ class TestMsgNEMSignTxMosaics(TrezorTest):
def test_nem_signtx_mosaic_creation_properties(self):
self.setup_mnemonic_nopin_nopassphrase()
tx = self.client.nem_sign_tx(self.client.expand_path("m/44'/1'/0'/0'/0'"), {
tx = self.client.nem_sign_tx(parse_path("m/44'/1'/0'/0'/0'"), {
"timeStamp": 74649215,
"fee": 2000000,
"type": nem.TYPE_MOSAIC_CREATION,
@ -122,7 +126,7 @@ class TestMsgNEMSignTxMosaics(TrezorTest):
def test_nem_signtx_mosaic_creation_levy(self):
self.setup_mnemonic_nopin_nopassphrase()
tx = self.client.nem_sign_tx(self.client.expand_path("m/44'/1'/0'/0'/0'"), {
tx = self.client.nem_sign_tx(parse_path("m/44'/1'/0'/0'/0'"), {
"timeStamp": 74649215,
"fee": 2000000,
"type": nem.TYPE_MOSAIC_CREATION,

View File

@ -15,11 +15,14 @@
# You should have received a copy of the GNU Lesser General Public License
# along with this library. If not, see <http://www.gnu.org/licenses/>.
from .common import *
from binascii import hexlify
import pytest
import time
from .common import TrezorTest
from trezorlib import messages as proto
from trezorlib import nem
import time
from trezorlib.tools import parse_path
# assertion data from T1
@ -32,7 +35,7 @@ class TestMsgNEMSignTxMosaics(TrezorTest):
self.setup_mnemonic_nopin_nopassphrase()
with self.client:
tx = self.client.nem_sign_tx(self.client.expand_path("m/44'/1'/0'/0'/0'"), {
tx = self.client.nem_sign_tx(parse_path("m/44'/1'/0'/0'/0'"), {
"timeStamp": 74649215,
"fee": 2000000,
"type": nem.TYPE_MOSAIC_SUPPLY_CHANGE,
@ -182,7 +185,7 @@ class TestMsgNEMSignTxMosaics(TrezorTest):
assert hexlify(tx.signature) == b'b87aac1ddf146d35e6a7f3451f57e2fe504ac559031e010a51261257c37bd50fcfa7b2939dd7a3203b54c4807d458475182f5d3dc135ec0d1d4a9cd42159fd0a'
def _nem_sign(self, num_of_swipes, test_suite):
n = self.client.expand_path("m/44'/1'/0'/0'/0'")
n = parse_path("m/44'/1'/0'/0'/0'")
n = self.client._convert_prime(n)
msg = nem.create_sign_tx(test_suite)
assert msg.transaction is not None

View File

@ -15,7 +15,11 @@
# You should have received a copy of the GNU Lesser General Public License
# along with this library. If not, see <http://www.gnu.org/licenses/>.
from .common import *
from binascii import hexlify
import pytest
from .common import TrezorTest
from trezorlib.tools import parse_path
from trezorlib import nem
@ -28,7 +32,7 @@ class TestMsgNEMSignTxMultisig(TrezorTest):
def test_nem_signtx_aggregate_modification(self):
self.setup_mnemonic_nopin_nopassphrase()
tx = self.client.nem_sign_tx(self.client.expand_path("m/44'/1'/0'/0'/0'"), {
tx = self.client.nem_sign_tx(parse_path("m/44'/1'/0'/0'/0'"), {
"timeStamp": 74649215,
"fee": 2000000,
"type": nem.TYPE_AGGREGATE_MODIFICATION,
@ -52,7 +56,7 @@ class TestMsgNEMSignTxMultisig(TrezorTest):
def test_nem_signtx_multisig(self):
self.setup_mnemonic_nopin_nopassphrase()
tx = self.client.nem_sign_tx(self.client.expand_path("m/44'/1'/0'/0'/0'"), {
tx = self.client.nem_sign_tx(parse_path("m/44'/1'/0'/0'/0'"), {
"timeStamp": 1,
"fee": 10000,
"type": nem.TYPE_MULTISIG,
@ -77,7 +81,7 @@ class TestMsgNEMSignTxMultisig(TrezorTest):
assert hexlify(tx.data) == b'04100000010000980100000020000000edfd32f6e760648c032f9acb4b30d514265f6a5b5f8a7154f2618922b40620841027000000000000ff5f74049900000001010000010000980200000020000000c5f54ba980fcbb657dbaaa42700539b207873e134d2375efeab5f1ab52f87844983a000000000000320901002800000054414c49434532474d4133344358484437584c4a513533364e4d35554e4b5148544f524e4e54324a80841e000000000025000000010000001d000000746573745f6e656d5f7472616e73616374696f6e5f7472616e73666572'
assert hexlify(tx.signature) == b'0cab2fddf2f02b5d7201675b9a71869292fe25ed33a366c7d2cbea7676fed491faaa03310079b7e17884b6ba2e3ea21c4f728d1cca8f190b8288207f6514820a'
tx = self.client.nem_sign_tx(self.client.expand_path("m/44'/1'/0'/0'/0'"), {
tx = self.client.nem_sign_tx(parse_path("m/44'/1'/0'/0'/0'"), {
"timeStamp": 74649215,
"fee": 150,
"type": nem.TYPE_MULTISIG,
@ -105,7 +109,7 @@ class TestMsgNEMSignTxMultisig(TrezorTest):
def test_nem_signtx_multisig_signer(self):
self.setup_mnemonic_nopin_nopassphrase()
tx = self.client.nem_sign_tx(self.client.expand_path("m/44'/1'/0'/0'/0'"), {
tx = self.client.nem_sign_tx(parse_path("m/44'/1'/0'/0'/0'"), {
"timeStamp": 333,
"fee": 200,
"type": nem.TYPE_MULTISIG_SIGNATURE,
@ -130,7 +134,7 @@ class TestMsgNEMSignTxMultisig(TrezorTest):
assert hexlify(tx.data) == b'02100000010000984d01000020000000edfd32f6e760648c032f9acb4b30d514265f6a5b5f8a7154f2618922b4062084c800000000000000bc010000240000002000000087923cd4805f3babe6b5af9cbb2b08be4458e39531618aed73c911f160c8e38528000000544444324354364c514c49595135364b49584933454e544d36454b3344343450354b5a50464d4b32'
assert hexlify(tx.signature) == b'286358a16ae545bff798feab93a713440c7c2f236d52ac0e995669d17a1915b0903667c97fa04418eccb42333cba95b19bccc8ac1faa8224dcfaeb41890ae807'
tx = self.client.nem_sign_tx(self.client.expand_path("m/44'/1'/0'/0'/0'"), {
tx = self.client.nem_sign_tx(parse_path("m/44'/1'/0'/0'/0'"), {
"timeStamp": 900000,
"fee": 200000,
"type": nem.TYPE_MULTISIG_SIGNATURE,

View File

@ -15,9 +15,13 @@
# You should have received a copy of the GNU Lesser General Public License
# along with this library. If not, see <http://www.gnu.org/licenses/>.
from .common import *
from binascii import hexlify
import pytest
from .common import TrezorTest
from trezorlib import nem
from trezorlib.tools import parse_path
# assertion data from T1
@ -29,7 +33,7 @@ class TestMsgNEMSignTxOther(TrezorTest):
self.setup_mnemonic_nopin_nopassphrase()
with self.client:
tx = self.client.nem_sign_tx(self.client.expand_path("m/44'/1'/0'/0'/0'"), {
tx = self.client.nem_sign_tx(parse_path("m/44'/1'/0'/0'/0'"), {
"timeStamp": 12349215,
"fee": 9900,
"type": nem.TYPE_IMPORTANCE_TRANSFER,
@ -50,7 +54,7 @@ class TestMsgNEMSignTxOther(TrezorTest):
self.setup_mnemonic_nopin_nopassphrase()
tx = self.client.nem_sign_tx(self.client.expand_path("m/44'/1'/0'/0'/0'"), {
tx = self.client.nem_sign_tx(parse_path("m/44'/1'/0'/0'/0'"), {
"timeStamp": 74649215,
"fee": 2000000,
"type": nem.TYPE_PROVISION_NAMESPACE,

View File

@ -15,10 +15,14 @@
# You should have received a copy of the GNU Lesser General Public License
# along with this library. If not, see <http://www.gnu.org/licenses/>.
from .common import *
from binascii import hexlify, unhexlify
import pytest
from .common import TrezorTest
from trezorlib import messages as proto
from trezorlib import nem
from trezorlib.tools import parse_path
# assertion data from T1
@ -44,7 +48,7 @@ class TestMsgNEMSignTx(TrezorTest):
proto.NEMSignedTx(),
])
tx = self.client.nem_sign_tx(self.client.expand_path("m/44'/1'/0'/0'/0'"), {
tx = self.client.nem_sign_tx(parse_path("m/44'/1'/0'/0'/0'"), {
"timeStamp": 74649215,
"amount": 2000000,
"fee": 2000000,
@ -75,7 +79,7 @@ class TestMsgNEMSignTx(TrezorTest):
proto.NEMSignedTx(),
])
tx = self.client.nem_sign_tx(self.client.expand_path("m/44'/1'/0'/0'/0'"), {
tx = self.client.nem_sign_tx(parse_path("m/44'/1'/0'/0'/0'"), {
"timeStamp": 74649215,
"amount": 2000000,
"fee": 2000000,
@ -101,7 +105,7 @@ class TestMsgNEMSignTx(TrezorTest):
def test_nem_signtx_xem_as_mosaic(self):
self.setup_mnemonic_nopin_nopassphrase()
tx = self.client.nem_sign_tx(self.client.expand_path("m/44'/1'/0'/0'/0'"), {
tx = self.client.nem_sign_tx(parse_path("m/44'/1'/0'/0'/0'"), {
"timeStamp": 76809215,
"amount": 5000000,
"fee": 1000000,
@ -129,7 +133,7 @@ class TestMsgNEMSignTx(TrezorTest):
def test_nem_signtx_unknown_mosaic(self):
self.setup_mnemonic_nopin_nopassphrase()
tx = self.client.nem_sign_tx(self.client.expand_path("m/44'/1'/0'/0'/0'"), {
tx = self.client.nem_sign_tx(parse_path("m/44'/1'/0'/0'/0'"), {
"timeStamp": 76809215,
"amount": 2000000,
"fee": 1000000,
@ -158,7 +162,7 @@ class TestMsgNEMSignTx(TrezorTest):
self.setup_mnemonic_nopin_nopassphrase()
tx = self.client.nem_sign_tx(self.client.expand_path("m/44'/1'/0'/0'/0'"), {
tx = self.client.nem_sign_tx(parse_path("m/44'/1'/0'/0'/0'"), {
"timeStamp": 76809215,
"amount": 3000000,
"fee": 1000000,
@ -187,7 +191,7 @@ class TestMsgNEMSignTx(TrezorTest):
self.setup_mnemonic_nopin_nopassphrase()
tx = self.client.nem_sign_tx(self.client.expand_path("m/44'/1'/0'/0'/0'"), {
tx = self.client.nem_sign_tx(parse_path("m/44'/1'/0'/0'/0'"), {
"timeStamp": 76809215,
"amount": 2000000,
"fee": 1000000,
@ -215,7 +219,7 @@ class TestMsgNEMSignTx(TrezorTest):
def test_nem_signtx_multiple_mosaics(self):
self.setup_mnemonic_nopin_nopassphrase()
tx = self.client.nem_sign_tx(self.client.expand_path("m/44'/1'/0'/0'/0'"), {
tx = self.client.nem_sign_tx(parse_path("m/44'/1'/0'/0'/0'"), {
"timeStamp": 76809215,
"amount": 2000000,
"fee": 1000000,

View File

@ -15,8 +15,9 @@
#
# You should have received a copy of the GNU Lesser General Public License
# along with this library. If not, see <http://www.gnu.org/licenses/>.
import pytest
from .common import *
from .common import TrezorTest
from trezorlib import messages as proto

View File

@ -16,9 +16,9 @@
# You should have received a copy of the GNU Lesser General Public License
# along with this library. If not, see <http://www.gnu.org/licenses/>.
from __future__ import print_function
import pytest
from .common import *
from .common import TrezorTest
from trezorlib import messages as proto

View File

@ -16,11 +16,12 @@
# You should have received a copy of the GNU Lesser General Public License
# along with this library. If not, see <http://www.gnu.org/licenses/>.
from __future__ import print_function
import time
from .common import *
import pytest
from .common import TrezorTest
from trezorlib import messages as proto

View File

@ -15,8 +15,9 @@
#
# You should have received a copy of the GNU Lesser General Public License
# along with this library. If not, see <http://www.gnu.org/licenses/>.
import pytest
from .common import *
from .common import TrezorTest, generate_entropy
from trezorlib import messages as proto
from mnemonic import Mnemonic

View File

@ -15,8 +15,9 @@
#
# You should have received a copy of the GNU Lesser General Public License
# along with this library. If not, see <http://www.gnu.org/licenses/>.
import pytest
from .common import *
from .common import TrezorTest, generate_entropy
from trezorlib import messages as proto
from mnemonic import Mnemonic

View File

@ -17,8 +17,9 @@
# along with this library. If not, see <http://www.gnu.org/licenses/>.
import time
import pytest
from .common import *
from .common import TrezorTest, generate_entropy
from trezorlib import messages as proto
from mnemonic import Mnemonic

View File

@ -16,10 +16,11 @@
# You should have received a copy of the GNU Lesser General Public License
# along with this library. If not, see <http://www.gnu.org/licenses/>.
from __future__ import print_function
import struct
from .common import *
from binascii import hexlify, unhexlify
from .common import TrezorTest
from trezorlib import messages as proto

View File

@ -15,8 +15,9 @@
#
# You should have received a copy of the GNU Lesser General Public License
# along with this library. If not, see <http://www.gnu.org/licenses/>.
from binascii import hexlify
from .common import *
from .common import TrezorTest
class TestMsgSignmessage(TrezorTest):

View File

@ -15,8 +15,9 @@
#
# You should have received a copy of the GNU Lesser General Public License
# along with this library. If not, see <http://www.gnu.org/licenses/>.
from binascii import hexlify
from .common import *
from .common import TrezorTest
from trezorlib import messages as proto

View File

@ -15,8 +15,9 @@
#
# You should have received a copy of the GNU Lesser General Public License
# along with this library. If not, see <http://www.gnu.org/licenses/>.
from binascii import hexlify
from .common import *
from .common import TrezorTest
from trezorlib import messages as proto

View File

@ -25,6 +25,7 @@ from .conftest import TREZOR_VERSION
from trezorlib import coins
from trezorlib import messages as proto
from trezorlib.client import CallException
from trezorlib.tools import parse_path
TxApiTestnet = coins.tx_api['Testnet']
@ -92,7 +93,7 @@ class TestMsgSigntx(TrezorTest):
# tx: e5040e1bc1ae7667ffb9e5248e90b2fb93cd9150234151ce90e14ab2f5933bcd
# input 0: 0.31 BTC
inp1 = proto.TxInputType(
address_n=self.client.expand_path("44'/1'/0'/0/0"),
address_n=parse_path("44'/1'/0'/0/0"),
# amount=31000000,
prev_hash=TXHASH_e5040e,
prev_index=0,
@ -105,7 +106,7 @@ class TestMsgSigntx(TrezorTest):
)
out2 = proto.TxOutputType(
address_n=self.client.expand_path("44'/1'/0'/1/0"),
address_n=parse_path("44'/1'/0'/1/0"),
amount=900000,
script_type=proto.OutputScriptType.PAYTOADDRESS,
)
@ -189,14 +190,14 @@ class TestMsgSigntx(TrezorTest):
# tx: c275c333fd1b36bef4af316226c66a8b3693fbfcc081a5e16a2ae5fcb09e92bf
inp1 = proto.TxInputType(
address_n=self.client.expand_path("m/44'/0'/0'/0/5"), # 1GA9u9TfCG7SWmKCveBumdA1TZpfom6ZdJ
address_n=parse_path("m/44'/0'/0'/0/5"), # 1GA9u9TfCG7SWmKCveBumdA1TZpfom6ZdJ
# amount=50000,
prev_hash=TXHASH_50f6f1,
prev_index=1,
)
out1 = proto.TxOutputType(
address_n=self.client.expand_path("m/44'/0'/0'/1/3"), # 1EcL6AyfQTyWKGvXwNSfsWoYnD3whzVFdu
address_n=parse_path("m/44'/0'/0'/1/3"), # 1EcL6AyfQTyWKGvXwNSfsWoYnD3whzVFdu
amount=30000,
script_type=proto.OutputScriptType.PAYTOADDRESS,
)
@ -637,7 +638,7 @@ class TestMsgSigntx(TrezorTest):
self.client.set_tx_api(TxApiTestnet)
inp1 = proto.TxInputType(
address_n=self.client.expand_path("44'/1'/4'/0/0"),
address_n=parse_path("44'/1'/4'/0/0"),
# moUJnmge8SRXuediK7bW6t4YfrPqbE6hD7
prev_hash=TXHASH_d2dcda,
prev_index=1,
@ -651,7 +652,7 @@ class TestMsgSigntx(TrezorTest):
)
out2 = proto.TxOutputType(
address_n=self.client.expand_path("44'/1'/12345'/1/0"),
address_n=parse_path("44'/1'/12345'/1/0"),
amount=123400000 - 5000 - 100000,
script_type=proto.OutputScriptType.PAYTOADDRESS,
)
@ -755,7 +756,7 @@ class TestMsgSigntx(TrezorTest):
# tx: e5040e1bc1ae7667ffb9e5248e90b2fb93cd9150234151ce90e14ab2f5933bcd
# input 0: 0.31 BTC
inp1 = proto.TxInputType(
address_n=self.client.expand_path("44'/1'/0'/0/0"),
address_n=parse_path("44'/1'/0'/0/0"),
# amount=31000000,
prev_hash=TXHASH_e5040e,
prev_index=0,
@ -768,13 +769,13 @@ class TestMsgSigntx(TrezorTest):
)
out_change1 = proto.TxOutputType(
address_n=self.client.expand_path("44'/1'/0'/1/0"),
address_n=parse_path("44'/1'/0'/1/0"),
amount=900000,
script_type=proto.OutputScriptType.PAYTOADDRESS,
)
out_change2 = proto.TxOutputType(
address_n=self.client.expand_path("44'/1'/0'/1/1"),
address_n=parse_path("44'/1'/0'/1/1"),
amount=10000,
script_type=proto.OutputScriptType.PAYTOADDRESS,
)
@ -814,7 +815,7 @@ class TestMsgSigntx(TrezorTest):
# tx: e5040e1bc1ae7667ffb9e5248e90b2fb93cd9150234151ce90e14ab2f5933bcd
# input 0: 0.31 BTC
inp1 = proto.TxInputType(
address_n=self.client.expand_path("44'/1'/0'/0/0"),
address_n=parse_path("44'/1'/0'/0/0"),
# amount=31000000,
prev_hash=TXHASH_e5040e,
prev_index=0,
@ -828,7 +829,7 @@ class TestMsgSigntx(TrezorTest):
# change on main chain is allowed => treated as a change
out_change = proto.TxOutputType(
address_n=self.client.expand_path("44'/1'/0'/0/0"),
address_n=parse_path("44'/1'/0'/0/0"),
amount=900000,
script_type=proto.OutputScriptType.PAYTOADDRESS,
)

View File

@ -15,11 +15,16 @@
# You should have received a copy of the GNU Lesser General Public License
# along with this library. If not, see <http://www.gnu.org/licenses/>.
from .common import *
import pytest
from binascii import hexlify, unhexlify
from .common import TrezorTest
from ..support.ckd_public import deserialize
from trezorlib import coins
from trezorlib import messages as proto
from trezorlib.ckd_public import deserialize
from trezorlib.client import CallException
from trezorlib.tools import parse_path
TxApiBcash = coins.tx_api['Bcash']
@ -30,7 +35,7 @@ class TestMsgSigntxBch(TrezorTest):
self.setup_mnemonic_allallall()
self.client.set_tx_api(TxApiBcash)
inp1 = proto.TxInputType(
address_n=self.client.expand_path("44'/145'/0'/0/0"),
address_n=parse_path("44'/145'/0'/0/0"),
# bitcoincash:qr08q88p9etk89wgv05nwlrkm4l0urz4cyl36hh9sv
amount=1995344,
prev_hash=unhexlify('bc37c28dfb467d2ecb50261387bf752a3977d7e5337915071bb4151e6b711a78'),
@ -38,7 +43,7 @@ class TestMsgSigntxBch(TrezorTest):
script_type=proto.InputScriptType.SPENDADDRESS,
)
out1 = proto.TxOutputType(
address_n=self.client.expand_path("44'/145'/0'/1/0"),
address_n=parse_path("44'/145'/0'/1/0"),
amount=1896050,
script_type=proto.OutputScriptType.PAYTOADDRESS,
)
@ -67,7 +72,7 @@ class TestMsgSigntxBch(TrezorTest):
self.setup_mnemonic_allallall()
self.client.set_tx_api(TxApiBcash)
inp1 = proto.TxInputType(
address_n=self.client.expand_path("44'/145'/0'/1/0"),
address_n=parse_path("44'/145'/0'/1/0"),
# bitcoincash:qzc5q87w069lzg7g3gzx0c8dz83mn7l02scej5aluw
amount=1896050,
prev_hash=unhexlify('502e8577b237b0152843a416f8f1ab0c63321b1be7a8cad7bf5c5c216fcf062c'),
@ -75,7 +80,7 @@ class TestMsgSigntxBch(TrezorTest):
script_type=proto.InputScriptType.SPENDADDRESS,
)
inp2 = proto.TxInputType(
address_n=self.client.expand_path("44'/145'/0'/0/1"),
address_n=parse_path("44'/145'/0'/0/1"),
# bitcoincash:qr23ajjfd9wd73l87j642puf8cad20lfmqdgwvpat4
amount=73452,
prev_hash=unhexlify('502e8577b237b0152843a416f8f1ab0c63321b1be7a8cad7bf5c5c216fcf062c'),
@ -107,7 +112,7 @@ class TestMsgSigntxBch(TrezorTest):
self.setup_mnemonic_allallall()
self.client.set_tx_api(TxApiBcash)
inp1 = proto.TxInputType(
address_n=self.client.expand_path("44'/145'/0'/1/0"),
address_n=parse_path("44'/145'/0'/1/0"),
# bitcoincash:qzc5q87w069lzg7g3gzx0c8dz83mn7l02scej5aluw
amount=1896050,
prev_hash=unhexlify('502e8577b237b0152843a416f8f1ab0c63321b1be7a8cad7bf5c5c216fcf062c'),
@ -115,7 +120,7 @@ class TestMsgSigntxBch(TrezorTest):
script_type=proto.InputScriptType.SPENDADDRESS,
)
inp2 = proto.TxInputType(
address_n=self.client.expand_path("44'/145'/0'/0/1"),
address_n=parse_path("44'/145'/0'/0/1"),
# bitcoincash:qr23ajjfd9wd73l87j642puf8cad20lfmqdgwvpat4
amount=73452,
prev_hash=unhexlify('502e8577b237b0152843a416f8f1ab0c63321b1be7a8cad7bf5c5c216fcf062c'),
@ -147,7 +152,7 @@ class TestMsgSigntxBch(TrezorTest):
self.setup_mnemonic_allallall()
self.client.set_tx_api(TxApiBcash)
inp1 = proto.TxInputType(
address_n=self.client.expand_path("44'/145'/0'/1/0"),
address_n=parse_path("44'/145'/0'/1/0"),
# bitcoincash:qzc5q87w069lzg7g3gzx0c8dz83mn7l02scej5aluw
amount=300,
prev_hash=unhexlify('502e8577b237b0152843a416f8f1ab0c63321b1be7a8cad7bf5c5c216fcf062c'),
@ -155,7 +160,7 @@ class TestMsgSigntxBch(TrezorTest):
script_type=proto.InputScriptType.SPENDADDRESS,
)
inp2 = proto.TxInputType(
address_n=self.client.expand_path("44'/145'/0'/0/1"),
address_n=parse_path("44'/145'/0'/0/1"),
# bitcoincash:qr23ajjfd9wd73l87j642puf8cad20lfmqdgwvpat4
amount=70,
prev_hash=unhexlify('502e8577b237b0152843a416f8f1ab0c63321b1be7a8cad7bf5c5c216fcf062c'),
@ -231,7 +236,7 @@ class TestMsgSigntxBch(TrezorTest):
self.setup_mnemonic_allallall()
self.client.set_tx_api(TxApiBcash)
inp1 = proto.TxInputType(
address_n=self.client.expand_path("44'/145'/1000'/0/0"),
address_n=parse_path("44'/145'/1000'/0/0"),
# bitcoincash:qr08q88p9etk89wgv05nwlrkm4l0urz4cyl36hh9sv
amount=1995344,
prev_hash=unhexlify('bc37c28dfb467d2ecb50261387bf752a3977d7e5337915071bb4151e6b711a78'),
@ -239,7 +244,7 @@ class TestMsgSigntxBch(TrezorTest):
script_type=proto.InputScriptType.SPENDADDRESS,
)
out1 = proto.TxOutputType(
address_n=self.client.expand_path("44'/145'/1000'/1/0"),
address_n=parse_path("44'/145'/1000'/1/0"),
amount=1896050,
script_type=proto.OutputScriptType.PAYTOADDRESS,
)
@ -253,7 +258,6 @@ class TestMsgSigntxBch(TrezorTest):
attack_ctr = 0
def attack_processor(req, msg):
import sys
global attack_ctr
if req.details.tx_hash is not None:
@ -286,7 +290,7 @@ class TestMsgSigntxBch(TrezorTest):
self.setup_mnemonic_allallall()
self.client.set_tx_api(TxApiBcash)
xpubs = []
for n in map(lambda index: self.client.get_public_node(self.client.expand_path("44'/145'/" + str(index) + "'")), range(1, 4)):
for n in map(lambda index: self.client.get_public_node(parse_path("44'/145'/" + str(index) + "'")), range(1, 4)):
xpubs.append(n.xpub)
def getmultisig(chain, nr, signatures=[b'', b'', b''], xpubs=xpubs):
@ -301,7 +305,7 @@ class TestMsgSigntxBch(TrezorTest):
public_key=unhexlify('0378d430274f8c5ec1321338151e9f27f4c676a008bdf8638d07c0b6be9ab35c71'))
sig = unhexlify(b'304402207274b5a4d15e75f3df7319a375557b0efba9b27bc63f9f183a17da95a6125c94022000efac57629f1522e2d3958430e2ef073b0706cfac06cce492651b79858f09ae')
inp1 = proto.TxInputType(
address_n=self.client.expand_path("44'/145'/1'/1/0"),
address_n=parse_path("44'/145'/1'/1/0"),
multisig=getmultisig(1, 0, [b'', sig, b'']),
# bitcoincash:pp6kcpkhua7789g2vyj0qfkcux3yvje7euhyhltn0a
amount=24000,
@ -310,7 +314,7 @@ class TestMsgSigntxBch(TrezorTest):
script_type=proto.InputScriptType.SPENDMULTISIG,
)
out1 = proto.TxOutputType(
address_n=self.client.expand_path("44'/145'/1'/1/1"),
address_n=parse_path("44'/145'/1'/1/1"),
multisig=proto.MultisigRedeemScriptType(
pubkeys=[proto.HDNodePathType(node=deserialize(xpubs[0]), address_n=[1, 1]),
proto.HDNodePathType(node=correcthorse, address_n=[]),
@ -339,7 +343,7 @@ class TestMsgSigntxBch(TrezorTest):
self.setup_mnemonic_allallall()
self.client.set_tx_api(TxApiBcash)
xpubs = []
for n in map(lambda index: self.client.get_public_node(self.client.expand_path("44'/145'/" + str(index) + "'")), range(1, 4)):
for n in map(lambda index: self.client.get_public_node(parse_path("44'/145'/" + str(index) + "'")), range(1, 4)):
xpubs.append(n.xpub)
def getmultisig(chain, nr, signatures=[b'', b'', b''], xpubs=xpubs):
@ -349,7 +353,7 @@ class TestMsgSigntxBch(TrezorTest):
m=2,
)
inp1 = proto.TxInputType(
address_n=self.client.expand_path("44'/145'/3'/0/0"),
address_n=parse_path("44'/145'/3'/0/0"),
multisig=getmultisig(0, 0),
# bitcoincash:pqguz4nqq64jhr5v3kvpq4dsjrkda75hwy86gq0qzw
amount=48490,
@ -363,7 +367,7 @@ class TestMsgSigntxBch(TrezorTest):
script_type=proto.OutputScriptType.PAYTOADDRESS,
)
out2 = proto.TxOutputType(
address_n=self.client.expand_path("44'/145'/3'/1/0"),
address_n=parse_path("44'/145'/3'/1/0"),
multisig=getmultisig(1, 0),
script_type=proto.OutputScriptType.PAYTOMULTISIG,
amount=24000
@ -385,7 +389,7 @@ class TestMsgSigntxBch(TrezorTest):
assert hexlify(signatures1[0]) == b'3045022100bcb1a7134a13025a06052546ee1c6ac3640a0abd2d130190ed13ed7fcb43e9cd02207c381478e2ee123c850425bfbf6d3c691230eb37e333832cb32a1ed3f2cd9e85'
inp1 = proto.TxInputType(
address_n=self.client.expand_path("44'/145'/1'/0/0"),
address_n=parse_path("44'/145'/1'/0/0"),
multisig=getmultisig(0, 0, [b'', b'', signatures1[0]]),
# bitcoincash:pqguz4nqq64jhr5v3kvpq4dsjrkda75hwy86gq0qzw
amount=48490,

View File

@ -16,11 +16,15 @@
# You should have received a copy of the GNU Lesser General Public License
# along with this library. If not, see <http://www.gnu.org/licenses/>.
from .common import *
import pytest
from binascii import hexlify, unhexlify
from .common import TrezorTest
from ..support.ckd_public import deserialize
from trezorlib import coins
from trezorlib import messages as proto
from trezorlib.ckd_public import deserialize
from trezorlib.client import CallException
from trezorlib.tools import parse_path
TxApiBitcoinGold = coins.tx_api["Bitcoin Gold"]
@ -32,14 +36,14 @@ class TestMsgSigntxBitcoinGold(TrezorTest):
self.setup_mnemonic_allallall()
self.client.set_tx_api(TxApiBitcoinGold)
inp1 = proto.TxInputType(
address_n=self.client.expand_path("44'/156'/0'/0/0"),
address_n=parse_path("44'/156'/0'/0/0"),
amount=1995344,
prev_hash=unhexlify('25526bf06c76ad3082bba930cf627cdd5f1b3cd0b9907dd7ff1a07e14addc985'),
prev_index=0,
script_type=proto.InputScriptType.SPENDADDRESS,
)
out1 = proto.TxOutputType(
address_n=self.client.expand_path("44'/156'/0'/1/0"),
address_n=parse_path("44'/156'/0'/1/0"),
amount=1896050,
script_type=proto.OutputScriptType.PAYTOADDRESS,
)
@ -68,14 +72,14 @@ class TestMsgSigntxBitcoinGold(TrezorTest):
self.setup_mnemonic_allallall()
self.client.set_tx_api(TxApiBitcoinGold)
inp1 = proto.TxInputType(
address_n=self.client.expand_path("44'/156'/0'/1/0"),
address_n=parse_path("44'/156'/0'/1/0"),
amount=1896050,
prev_hash=unhexlify('25526bf06c76ad3082bba930cf627cdd5f1b3cd0b9907dd7ff1a07e14addc985'),
prev_index=0,
script_type=proto.InputScriptType.SPENDADDRESS,
)
inp2 = proto.TxInputType(
address_n=self.client.expand_path("44'/156'/0'/0/1"),
address_n=parse_path("44'/156'/0'/0/1"),
# 1LRspCZNFJcbuNKQkXgHMDucctFRQya5a3
amount=73452,
prev_hash=unhexlify('db77c2461b840e6edbe7f9280043184a98e020d9795c1b65cb7cef2551a8fb18'),
@ -107,7 +111,7 @@ class TestMsgSigntxBitcoinGold(TrezorTest):
self.setup_mnemonic_allallall()
self.client.set_tx_api(TxApiBitcoinGold)
inp1 = proto.TxInputType(
address_n=self.client.expand_path("44'/156'/1000'/0/0"),
address_n=parse_path("44'/156'/1000'/0/0"),
# 1MH9KKcvdCTY44xVDC2k3fjBbX5Cz29N1q
amount=1995344,
prev_hash=unhexlify('25526bf06c76ad3082bba930cf627cdd5f1b3cd0b9907dd7ff1a07e14addc985'),
@ -115,7 +119,7 @@ class TestMsgSigntxBitcoinGold(TrezorTest):
script_type=proto.InputScriptType.SPENDADDRESS,
)
out1 = proto.TxOutputType(
address_n=self.client.expand_path("44'/156'/1000'/1/0"),
address_n=parse_path("44'/156'/1000'/1/0"),
amount=1896050,
script_type=proto.OutputScriptType.PAYTOADDRESS,
)
@ -129,7 +133,6 @@ class TestMsgSigntxBitcoinGold(TrezorTest):
attack_ctr = 0
def attack_processor(req, msg):
import sys
global attack_ctr
if req.details.tx_hash is not None:
@ -162,7 +165,7 @@ class TestMsgSigntxBitcoinGold(TrezorTest):
self.setup_mnemonic_allallall()
self.client.set_tx_api(TxApiBitcoinGold)
xpubs = []
for n in map(lambda index: self.client.get_public_node(self.client.expand_path("44'/156'/" + str(index) + "'")), range(1, 4)):
for n in map(lambda index: self.client.get_public_node(parse_path("44'/156'/" + str(index) + "'")), range(1, 4)):
xpubs.append(n.xpub)
def getmultisig(chain, nr, signatures=[b'', b'', b''], xpubs=xpubs):
@ -172,7 +175,7 @@ class TestMsgSigntxBitcoinGold(TrezorTest):
m=2,
)
inp1 = proto.TxInputType(
address_n=self.client.expand_path("44'/156'/3'/0/0"),
address_n=parse_path("44'/156'/3'/0/0"),
multisig=getmultisig(0, 0),
# 33Ju286QvonBz5N1V754ZekQv4GLJqcc5R
amount=48490,
@ -186,7 +189,7 @@ class TestMsgSigntxBitcoinGold(TrezorTest):
script_type=proto.OutputScriptType.PAYTOADDRESS,
)
out2 = proto.TxOutputType(
address_n=self.client.expand_path("44'/156'/3'/1/0"),
address_n=parse_path("44'/156'/3'/1/0"),
multisig=getmultisig(1, 0),
script_type=proto.OutputScriptType.PAYTOMULTISIG,
amount=24000
@ -208,7 +211,7 @@ class TestMsgSigntxBitcoinGold(TrezorTest):
assert hexlify(signatures1[0]) == b'3045022100b1594f3b186d0dedbf61e53a1c407b1e0747098b7375941df85af045040f578e022013ba1893eb9e2fd854dd07073a83b261cf4beba76f66b07742e462b4088a7e4a'
inp1 = proto.TxInputType(
address_n=self.client.expand_path("44'/156'/1'/0/0"),
address_n=parse_path("44'/156'/1'/0/0"),
multisig=getmultisig(0, 0, [b'', b'', signatures1[0]]),
# 33Ju286QvonBz5N1V754ZekQv4GLJqcc5R
amount=48490,
@ -239,7 +242,7 @@ class TestMsgSigntxBitcoinGold(TrezorTest):
self.setup_mnemonic_allallall()
self.client.set_tx_api(TxApiBitcoinGold)
inp1 = proto.TxInputType(
address_n=self.client.expand_path("49'/156'/0'/1/0"),
address_n=parse_path("49'/156'/0'/1/0"),
amount=123456789,
prev_hash=unhexlify('25526bf06c76ad3082bba930cf627cdd5f1b3cd0b9907dd7ff1a07e14addc985'),
prev_index=0,
@ -277,7 +280,7 @@ class TestMsgSigntxBitcoinGold(TrezorTest):
self.setup_mnemonic_allallall()
self.client.set_tx_api(TxApiBitcoinGold)
inp1 = proto.TxInputType(
address_n=self.client.expand_path("49'/156'/0'/1/0"),
address_n=parse_path("49'/156'/0'/1/0"),
amount=123456789,
prev_hash=unhexlify('25526bf06c76ad3082bba930cf627cdd5f1b3cd0b9907dd7ff1a07e14addc985'),
prev_index=0,
@ -289,7 +292,7 @@ class TestMsgSigntxBitcoinGold(TrezorTest):
script_type=proto.OutputScriptType.PAYTOADDRESS,
)
out2 = proto.TxOutputType(
address_n=self.client.expand_path("49'/156'/0'/1/0"),
address_n=parse_path("49'/156'/0'/1/0"),
script_type=proto.OutputScriptType.PAYTOP2SHWITNESS,
amount=123456789 - 11000 - 12300000,
)
@ -315,7 +318,7 @@ class TestMsgSigntxBitcoinGold(TrezorTest):
def test_send_multisig_1(self):
self.setup_mnemonic_allallall()
self.client.set_tx_api(TxApiBitcoinGold)
nodes = map(lambda index: self.client.get_public_node(self.client.expand_path("999'/1'/%d'" % index)), range(1, 4))
nodes = map(lambda index: self.client.get_public_node(parse_path("999'/1'/%d'" % index)), range(1, 4))
multisig = proto.MultisigRedeemScriptType(
pubkeys=list(map(lambda n: proto.HDNodePathType(node=deserialize(n.xpub), address_n=[2, 0]), nodes)),
signatures=[b'', b'', b''],
@ -323,7 +326,7 @@ class TestMsgSigntxBitcoinGold(TrezorTest):
)
inp1 = proto.TxInputType(
address_n=self.client.expand_path("999'/1'/1'/2/0"),
address_n=parse_path("999'/1'/1'/2/0"),
prev_hash=unhexlify('25526bf06c76ad3082bba930cf627cdd5f1b3cd0b9907dd7ff1a07e14addc985'),
prev_index=1,
script_type=proto.InputScriptType.SPENDP2SHWITNESS,

View File

@ -15,10 +15,14 @@
# You should have received a copy of the GNU Lesser General Public License
# along with this library. If not, see <http://www.gnu.org/licenses/>.
from .common import *
from binascii import unhexlify
import pytest
from .common import TrezorTest
from trezorlib import coins
from trezorlib import messages as proto
from trezorlib.tools import parse_path
TxApiDecredTestnet = coins.tx_api['Decred Testnet']
@ -41,7 +45,7 @@ class TestMsgSigntxDecred(TrezorTest):
inp1 = proto.TxInputType(
# TscqTv1he8MZrV321SfRghw7LFBCJDKB3oz
address_n=self.client.expand_path("m/44'/1'/0'/0/0"),
address_n=parse_path("m/44'/1'/0'/0/0"),
prev_hash=TXHASH_e16248,
prev_index=1,
script_type=proto.InputScriptType.SPENDADDRESS,
@ -80,7 +84,7 @@ class TestMsgSigntxDecred(TrezorTest):
inp1 = proto.TxInputType(
# TscqTv1he8MZrV321SfRghw7LFBCJDKB3oz
address_n=self.client.expand_path("m/44'/1'/0'/0/0"),
address_n=parse_path("m/44'/1'/0'/0/0"),
prev_hash=TXHASH_5e6e35,
prev_index=0,
script_type=proto.InputScriptType.SPENDADDRESS,
@ -89,7 +93,7 @@ class TestMsgSigntxDecred(TrezorTest):
inp2 = proto.TxInputType(
# TscqTv1he8MZrV321SfRghw7LFBCJDKB3oz
address_n=self.client.expand_path("m/44'/1'/0'/0/0"),
address_n=parse_path("m/44'/1'/0'/0/0"),
prev_hash=TXHASH_ccf95b,
prev_index=1,
script_type=proto.InputScriptType.SPENDADDRESS,
@ -98,7 +102,7 @@ class TestMsgSigntxDecred(TrezorTest):
inp3 = proto.TxInputType(
# Tskt39YEvzoJ5KBDH4f1auNzG3jViVjZ2RV
address_n=self.client.expand_path("m/44'/1'/0'/0/1"),
address_n=parse_path("m/44'/1'/0'/0/1"),
prev_hash=TXHASH_f395ef,
prev_index=0,
script_type=proto.InputScriptType.SPENDADDRESS,
@ -114,7 +118,7 @@ class TestMsgSigntxDecred(TrezorTest):
out2 = proto.TxOutputType(
# TsaSFRwfN9muW5F6ZX36iSksc9hruiC5F97
address_n=self.client.expand_path("m/44'/1'/0'/1/0"),
address_n=parse_path("m/44'/1'/0'/1/0"),
amount=100000000,
script_type=proto.OutputScriptType.PAYTOADDRESS,
decred_script_version=0,
@ -154,7 +158,7 @@ class TestMsgSigntxDecred(TrezorTest):
self.setup_mnemonic_allallall()
self.client.set_tx_api(TxApiDecredTestnet)
paths = [self.client.expand_path("m/48'/1'/%d'" % index) for index in range(3)]
paths = [parse_path("m/48'/1'/%d'" % index) for index in range(3)]
nodes = [self.client.get_public_node(address_n, coin_name="Decred Testnet").node for address_n in paths]
signatures = [
@ -163,7 +167,7 @@ class TestMsgSigntxDecred(TrezorTest):
]
def create_multisig(index, address, signatures=None):
address_n = self.client.expand_path(address)
address_n = parse_path(address)
multisig = proto.MultisigRedeemScriptType(
pubkeys=[proto.HDNodePathType(node=node, address_n=address_n) for node in nodes],
signatures=signatures,

View File

@ -18,12 +18,14 @@
from binascii import hexlify, unhexlify
import pytest
from ..support.ckd_public import deserialize
from .conftest import TREZOR_VERSION
from .common import TrezorTest
from trezorlib import coins
from trezorlib import messages as proto
from trezorlib.ckd_public import deserialize
from trezorlib.client import CallException
from trezorlib.tools import parse_path
TxApiTestnet = coins.tx_api["Testnet"]
@ -34,7 +36,7 @@ class TestMsgSigntxSegwit(TrezorTest):
self.setup_mnemonic_allallall()
self.client.set_tx_api(TxApiTestnet)
inp1 = proto.TxInputType(
address_n=self.client.expand_path("49'/1'/0'/1/0"),
address_n=parse_path("49'/1'/0'/1/0"),
# 2N1LGaGg836mqSQqiuUBLfcyGBhyZbremDX
amount=123456789,
prev_hash=unhexlify('20912f98ea3ed849042efed0fdac8cb4fc301961c5988cba56902d8ffb61c337'),
@ -73,7 +75,7 @@ class TestMsgSigntxSegwit(TrezorTest):
self.setup_mnemonic_allallall()
self.client.set_tx_api(TxApiTestnet)
inp1 = proto.TxInputType(
address_n=self.client.expand_path("49'/1'/0'/1/0"),
address_n=parse_path("49'/1'/0'/1/0"),
# 2N1LGaGg836mqSQqiuUBLfcyGBhyZbremDX
amount=123456789,
prev_hash=unhexlify('20912f98ea3ed849042efed0fdac8cb4fc301961c5988cba56902d8ffb61c337'),
@ -86,7 +88,7 @@ class TestMsgSigntxSegwit(TrezorTest):
script_type=proto.OutputScriptType.PAYTOADDRESS,
)
out2 = proto.TxOutputType(
address_n=self.client.expand_path("49'/1'/0'/1/0"),
address_n=parse_path("49'/1'/0'/1/0"),
script_type=proto.OutputScriptType.PAYTOP2SHWITNESS,
amount=123456789 - 11000 - 12300000,
)
@ -110,7 +112,7 @@ class TestMsgSigntxSegwit(TrezorTest):
def test_send_multisig_1(self):
self.setup_mnemonic_allallall()
self.client.set_tx_api(TxApiTestnet)
nodes = map(lambda index: self.client.get_public_node(self.client.expand_path("999'/1'/%d'" % index)), range(1, 4))
nodes = map(lambda index: self.client.get_public_node(parse_path("999'/1'/%d'" % index)), range(1, 4))
multisig = proto.MultisigRedeemScriptType(
pubkeys=list(map(lambda n: proto.HDNodePathType(node=deserialize(n.xpub), address_n=[2, 0]), nodes)),
signatures=[b'', b'', b''],
@ -118,7 +120,7 @@ class TestMsgSigntxSegwit(TrezorTest):
)
inp1 = proto.TxInputType(
address_n=self.client.expand_path("999'/1'/1'/2/0"),
address_n=parse_path("999'/1'/1'/2/0"),
prev_hash=unhexlify('9c31922be756c06d02167656465c8dc83bb553bf386a3f478ae65b5c021002be'),
prev_index=1,
script_type=proto.InputScriptType.SPENDP2SHWITNESS,
@ -167,7 +169,7 @@ class TestMsgSigntxSegwit(TrezorTest):
self.setup_mnemonic_allallall()
self.client.set_tx_api(TxApiTestnet)
inp1 = proto.TxInputType(
address_n=self.client.expand_path("49'/1'/0'/1/0"),
address_n=parse_path("49'/1'/0'/1/0"),
# 2N1LGaGg836mqSQqiuUBLfcyGBhyZbremDX
amount=123456789,
prev_hash=unhexlify('20912f98ea3ed849042efed0fdac8cb4fc301961c5988cba56902d8ffb61c337'),
@ -180,7 +182,7 @@ class TestMsgSigntxSegwit(TrezorTest):
script_type=proto.OutputScriptType.PAYTOADDRESS,
)
out2 = proto.TxOutputType(
address_n=self.client.expand_path("49'/1'/12345'/1/0"),
address_n=parse_path("49'/1'/12345'/1/0"),
script_type=proto.OutputScriptType.PAYTOP2SHWITNESS,
amount=123456789 - 11000 - 12300000,
)
@ -189,7 +191,6 @@ class TestMsgSigntxSegwit(TrezorTest):
run_attack = True
def attack_processor(req, msg):
import sys
global run_attack
if req.details.tx_hash is not None:

View File

@ -15,11 +15,13 @@
# You should have received a copy of the GNU Lesser General Public License
# along with this library. If not, see <http://www.gnu.org/licenses/>.
from .common import *
from binascii import hexlify, unhexlify
from .common import TrezorTest
from ..support.ckd_public import deserialize
from trezorlib import coins
from trezorlib import messages as proto
from trezorlib.ckd_public import deserialize
from trezorlib.tools import parse_path
TxApiTestnet = coins.tx_api['Testnet']
@ -30,7 +32,7 @@ class TestMsgSigntxSegwitNative(TrezorTest):
self.setup_mnemonic_allallall()
self.client.set_tx_api(TxApiTestnet)
inp1 = proto.TxInputType(
address_n=self.client.expand_path("49'/1'/0'/1/0"),
address_n=parse_path("49'/1'/0'/1/0"),
# 2N1LGaGg836mqSQqiuUBLfcyGBhyZbremDX
amount=123456789,
prev_hash=unhexlify('20912f98ea3ed849042efed0fdac8cb4fc301961c5988cba56902d8ffb61c337'),
@ -69,7 +71,7 @@ class TestMsgSigntxSegwitNative(TrezorTest):
self.setup_mnemonic_allallall()
self.client.set_tx_api(TxApiTestnet)
inp1 = proto.TxInputType(
address_n=self.client.expand_path("49'/1'/0'/1/0"),
address_n=parse_path("49'/1'/0'/1/0"),
# 2N1LGaGg836mqSQqiuUBLfcyGBhyZbremDX
amount=123456789,
prev_hash=unhexlify('20912f98ea3ed849042efed0fdac8cb4fc301961c5988cba56902d8ffb61c337'),
@ -82,7 +84,7 @@ class TestMsgSigntxSegwitNative(TrezorTest):
script_type=proto.OutputScriptType.PAYTOADDRESS,
)
out2 = proto.TxOutputType(
address_n=self.client.expand_path("49'/1'/0'/1/0"),
address_n=parse_path("49'/1'/0'/1/0"),
script_type=proto.OutputScriptType.PAYTOP2SHWITNESS,
amount=123456789 - 11000 - 12300000,
)
@ -107,7 +109,7 @@ class TestMsgSigntxSegwitNative(TrezorTest):
self.setup_mnemonic_allallall()
self.client.set_tx_api(TxApiTestnet)
inp1 = proto.TxInputType(
address_n=self.client.expand_path("49'/1'/0'/0/0"),
address_n=parse_path("49'/1'/0'/0/0"),
# tb1qqzv60m9ajw8drqulta4ld4gfx0rdh82un5s65s
amount=12300000,
prev_hash=unhexlify('09144602765ce3dd8f4329445b20e3684e948709c5cdcaf12da3bb079c99448a'),
@ -146,7 +148,7 @@ class TestMsgSigntxSegwitNative(TrezorTest):
self.setup_mnemonic_allallall()
self.client.set_tx_api(TxApiTestnet)
inp1 = proto.TxInputType(
address_n=self.client.expand_path("49'/1'/0'/0/0"),
address_n=parse_path("49'/1'/0'/0/0"),
# tb1qqzv60m9ajw8drqulta4ld4gfx0rdh82un5s65s
amount=12300000,
prev_hash=unhexlify('09144602765ce3dd8f4329445b20e3684e948709c5cdcaf12da3bb079c99448a'),
@ -159,7 +161,7 @@ class TestMsgSigntxSegwitNative(TrezorTest):
script_type=proto.OutputScriptType.PAYTOADDRESS,
)
out2 = proto.TxOutputType(
address_n=self.client.expand_path("49'/1'/0'/1/0"),
address_n=parse_path("49'/1'/0'/1/0"),
script_type=proto.OutputScriptType.PAYTOWITNESS,
amount=12300000 - 11000 - 5000000,
)
@ -184,7 +186,7 @@ class TestMsgSigntxSegwitNative(TrezorTest):
self.setup_mnemonic_allallall()
self.client.set_tx_api(TxApiTestnet)
inp1 = proto.TxInputType(
address_n=self.client.expand_path("49'/1'/0'/1/0"),
address_n=parse_path("49'/1'/0'/1/0"),
# 2N1LGaGg836mqSQqiuUBLfcyGBhyZbremDX
amount=111145789,
prev_hash=unhexlify('09144602765ce3dd8f4329445b20e3684e948709c5cdcaf12da3bb079c99448a'),
@ -192,7 +194,7 @@ class TestMsgSigntxSegwitNative(TrezorTest):
script_type=proto.InputScriptType.SPENDP2SHWITNESS,
)
inp2 = proto.TxInputType(
address_n=self.client.expand_path("49'/1'/0'/1/0"),
address_n=parse_path("49'/1'/0'/1/0"),
# tb1q694ccp5qcc0udmfwgp692u2s2hjpq5h407urtu
amount=7289000,
prev_hash=unhexlify('65b811d3eca0fe6915d9f2d77c86c5a7f19bf66b1b1253c2c51cb4ae5f0c017b'),
@ -205,7 +207,7 @@ class TestMsgSigntxSegwitNative(TrezorTest):
script_type=proto.OutputScriptType.PAYTOADDRESS,
)
out2 = proto.TxOutputType(
# address_n=self.client.expand_path("44'/1'/0'/0/0"),
# address_n=parse_path("44'/1'/0'/0/0"),
# script_type=proto.OutputScriptType.PAYTOP2SHWITNESS,
address='2N6UeBoqYEEnybg4cReFYDammpsyDw8R2Mc',
script_type=proto.OutputScriptType.PAYTOADDRESS,
@ -245,7 +247,7 @@ class TestMsgSigntxSegwitNative(TrezorTest):
def test_send_multisig_1(self):
self.setup_mnemonic_allallall()
self.client.set_tx_api(TxApiTestnet)
nodes = [self.client.get_public_node(self.client.expand_path("999'/1'/%d'" % index)) for index in range(1, 4)]
nodes = [self.client.get_public_node(parse_path("999'/1'/%d'" % index)) for index in range(1, 4)]
multisig = proto.MultisigRedeemScriptType(
pubkeys=list(map(lambda n: proto.HDNodePathType(node=deserialize(n.xpub), address_n=[2, 0]), nodes)),
signatures=[b'', b'', b''],
@ -253,7 +255,7 @@ class TestMsgSigntxSegwitNative(TrezorTest):
)
inp1 = proto.TxInputType(
address_n=self.client.expand_path("999'/1'/1'/2/0"),
address_n=parse_path("999'/1'/1'/2/0"),
prev_hash=unhexlify('9c31922be756c06d02167656465c8dc83bb553bf386a3f478ae65b5c021002be'),
prev_index=1,
script_type=proto.InputScriptType.SPENDP2SHWITNESS,
@ -301,7 +303,7 @@ class TestMsgSigntxSegwitNative(TrezorTest):
def test_send_multisig_2(self):
self.setup_mnemonic_allallall()
self.client.set_tx_api(TxApiTestnet)
nodes = [self.client.get_public_node(self.client.expand_path("999'/1'/%d'" % index)) for index in range(1, 4)]
nodes = [self.client.get_public_node(parse_path("999'/1'/%d'" % index)) for index in range(1, 4)]
multisig = proto.MultisigRedeemScriptType(
pubkeys=list(map(lambda n: proto.HDNodePathType(node=deserialize(n.xpub), address_n=[2, 1]), nodes)),
signatures=[b'', b'', b''],
@ -309,7 +311,7 @@ class TestMsgSigntxSegwitNative(TrezorTest):
)
inp1 = proto.TxInputType(
address_n=self.client.expand_path("999'/1'/2'/2/1"),
address_n=parse_path("999'/1'/2'/2/1"),
prev_hash=unhexlify('f41cbedd8becee05a830f418d13aa665125464547db5c7a6cd28f21639fe1228'),
prev_index=0,
script_type=proto.InputScriptType.SPENDWITNESS,
@ -357,7 +359,7 @@ class TestMsgSigntxSegwitNative(TrezorTest):
def test_send_multisig_3_change(self):
self.setup_mnemonic_allallall()
self.client.set_tx_api(TxApiTestnet)
nodes = [self.client.get_public_node(self.client.expand_path("999'/1'/%d'" % index)) for index in range(1, 4)]
nodes = [self.client.get_public_node(parse_path("999'/1'/%d'" % index)) for index in range(1, 4)]
multisig = proto.MultisigRedeemScriptType(
pubkeys=list(map(lambda n: proto.HDNodePathType(node=deserialize(n.xpub), address_n=[2, 0]), nodes)),
signatures=[b'', b'', b''],
@ -370,7 +372,7 @@ class TestMsgSigntxSegwitNative(TrezorTest):
)
inp1 = proto.TxInputType(
address_n=self.client.expand_path("999'/1'/1'/2/0"),
address_n=parse_path("999'/1'/1'/2/0"),
prev_hash=unhexlify('c9348040bbc2024e12dcb4a0b4806b0398646b91acf314da028c3f03dd0179fc'),
prev_index=0,
script_type=proto.InputScriptType.SPENDWITNESS,
@ -379,7 +381,7 @@ class TestMsgSigntxSegwitNative(TrezorTest):
)
out1 = proto.TxOutputType(
address_n=self.client.expand_path("999'/1'/1'/1/1"),
address_n=parse_path("999'/1'/1'/1/1"),
amount=1603000,
multisig=multisig2,
script_type=proto.OutputScriptType.PAYTOP2SHWITNESS
@ -418,7 +420,7 @@ class TestMsgSigntxSegwitNative(TrezorTest):
def test_send_multisig_4_change(self):
self.setup_mnemonic_allallall()
self.client.set_tx_api(TxApiTestnet)
nodes = [self.client.get_public_node(self.client.expand_path("999'/1'/%d'" % index)) for index in range(1, 4)]
nodes = [self.client.get_public_node(parse_path("999'/1'/%d'" % index)) for index in range(1, 4)]
multisig = proto.MultisigRedeemScriptType(
pubkeys=list(map(lambda n: proto.HDNodePathType(node=deserialize(n.xpub), address_n=[1, 1]), nodes)),
signatures=[b'', b'', b''],
@ -431,7 +433,7 @@ class TestMsgSigntxSegwitNative(TrezorTest):
)
inp1 = proto.TxInputType(
address_n=self.client.expand_path("999'/1'/1'/1/1"),
address_n=parse_path("999'/1'/1'/1/1"),
prev_hash=unhexlify('31bc1c88ce6ae337a6b3057a16d5bad0b561ad1dfc047d0a7fbb8814668f91e5'),
prev_index=0,
script_type=proto.InputScriptType.SPENDP2SHWITNESS,
@ -440,7 +442,7 @@ class TestMsgSigntxSegwitNative(TrezorTest):
)
out1 = proto.TxOutputType(
address_n=self.client.expand_path("999'/1'/1'/1/2"),
address_n=parse_path("999'/1'/1'/1/2"),
amount=1602000,
multisig=multisig2,
script_type=proto.OutputScriptType.PAYTOWITNESS

View File

@ -15,12 +15,14 @@
#
# You should have received a copy of the GNU Lesser General Public License
# along with this library. If not, see <http://www.gnu.org/licenses/>.
from binascii import unhexlify, hexlify
import pytest
from .common import *
from .common import TrezorTest
from trezorlib import coins
from trezorlib import messages as proto
from trezorlib.tools import parse_path
TxApiZcash = coins.tx_api["Zcash"]
@ -42,7 +44,7 @@ class TestMsgSigntxZcash(TrezorTest):
# input 0: 1.234567 TAZ
inp1 = proto.TxInputType(
address_n=[2147483692, 2147483649, 2147483648, 0, 0], # tmQoJ3PTXgQLaRRZZYT6xk8XtjRbr2kCqwu
address_n=parse_path("m/Zcash Testnet/0h/0/0"), # tmQoJ3PTXgQLaRRZZYT6xk8XtjRbr2kCqwu
# amount=123456700,
prev_hash=TXHASH_93373e,
prev_index=0,

View File

@ -12,11 +12,12 @@
#
# You should have received a copy of the GNU Lesser General Public License
# along with this library. If not, see <http://www.gnu.org/licenses/>.
import pytest
from .common import TrezorTest
from .conftest import TREZOR_VERSION
from trezorlib import stellar
import pytest
from trezorlib.tools import parse_path
@pytest.mark.stellar
@ -27,5 +28,5 @@ class TestMsgStellarGetPublicKey(TrezorTest):
self.setup_mnemonic_nopin_nopassphrase()
# GAK5MSF74TJW6GLM7NLTL76YZJKM2S4CGP3UH4REJHPHZ4YBZW2GSBPW
response = self.client.stellar_get_public_key(self.client.expand_path("m/44'/148'/0'"))
response = self.client.stellar_get_public_key(parse_path(stellar.DEFAULT_BIP32_PATH))
assert stellar.address_from_public_key(response.public_key) == b'GAK5MSF74TJW6GLM7NLTL76YZJKM2S4CGP3UH4REJHPHZ4YBZW2GSBPW'

View File

@ -22,6 +22,8 @@ from .common import TrezorTest
from .conftest import TREZOR_VERSION
from binascii import hexlify, unhexlify
from trezorlib import messages as proto
from trezorlib import stellar
from trezorlib.tools import parse_path
import pytest
@ -29,14 +31,12 @@ import pytest
@pytest.mark.xfail(TREZOR_VERSION == 2, reason="T2 support is not yet finished")
class TestMsgStellarSignTransaction(TrezorTest):
ADDRESS_N = parse_path(stellar.DEFAULT_BIP32_PATH)
def get_network_passphrase(self):
"""Use the same passphrase as the network that generated the test XDR/signatures"""
return "Integration Test Network ; zulucrypto"
def get_address_n(self):
"""BIP32 path of the default account"""
return self.client.expand_path("m/44'/148'/0'")
def test_sign_tx_bump_sequence_op(self):
self.setup_mnemonic_nopin_nopassphrase()
@ -44,7 +44,7 @@ class TestMsgStellarSignTransaction(TrezorTest):
op.bump_to = 0x7fffffffffffffff
tx = self._create_msg()
response = self.client.stellar_sign_transaction(tx, [op], self.get_address_n(), self.get_network_passphrase())
response = self.client.stellar_sign_transaction(tx, [op], self.ADDRESS_N, self.get_network_passphrase())
assert b64encode(response.signature) == b'UAOL4ZPYIOzEgM66kBrhyNjLR66dNXtuNrmvd3m0/pc8qCSoLmYY4TybS0lHiMtb+LFZESTaxrpErMHz1sZ6DQ=='
def test_sign_tx_account_merge_op(self):
@ -56,7 +56,7 @@ class TestMsgStellarSignTransaction(TrezorTest):
tx = self._create_msg()
response = self.client.stellar_sign_transaction(tx, [op], self.get_address_n(), self.get_network_passphrase())
response = self.client.stellar_sign_transaction(tx, [op], self.ADDRESS_N, self.get_network_passphrase())
assert hexlify(response.public_key) == b'15d648bfe4d36f196cfb5735ffd8ca54cd4b8233f743f22449de7cf301cdb469'
assert b64encode(response.signature) == b'gjoPRj4sW5o7NAXzYOqPK0uxfPbeKb4Qw48LJiCH/XUZ6YVCiZogePC0Z5ISUlozMh6YO6HoYtuLPbm7jq+eCA=='

View File

@ -15,9 +15,9 @@
#
# You should have received a copy of the GNU Lesser General Public License
# along with this library. If not, see <http://www.gnu.org/licenses/>.
from binascii import unhexlify
from .common import *
import base64
from .common import TrezorTest
class TestMsgVerifymessage(TrezorTest):

View File

@ -15,9 +15,9 @@
#
# You should have received a copy of the GNU Lesser General Public License
# along with this library. If not, see <http://www.gnu.org/licenses/>.
from binascii import unhexlify
from .common import *
import base64
from .common import TrezorTest
class TestMsgVerifymessageSegwit(TrezorTest):

View File

@ -15,9 +15,9 @@
#
# You should have received a copy of the GNU Lesser General Public License
# along with this library. If not, see <http://www.gnu.org/licenses/>.
from binascii import unhexlify
from .common import *
import base64
from .common import TrezorTest
class TestMsgVerifymessageSegwitNative(TrezorTest):

View File

@ -16,7 +16,7 @@
# You should have received a copy of the GNU Lesser General Public License
# along with this library. If not, see <http://www.gnu.org/licenses/>.
from .common import *
from .common import TrezorTest
from trezorlib import messages as proto

View File

@ -20,11 +20,10 @@ from binascii import hexlify, unhexlify
import pytest
from .common import TrezorTest
from ..support import ckd_public as bip32
from trezorlib import messages as proto
import trezorlib.ckd_public as bip32
from trezorlib.client import CallException
TXHASH_c6091a = unhexlify('c6091adf4c0c23982a35899a6e58ae11e703eacd7954f588ed4b9cdefc4dba52')

View File

@ -16,10 +16,13 @@
# You should have received a copy of the GNU Lesser General Public License
# along with this library. If not, see <http://www.gnu.org/licenses/>.
from .common import *
from binascii import hexlify, unhexlify
from .common import TrezorTest
from ..support import ckd_public as bip32
from trezorlib import messages as proto
import trezorlib.ckd_public as bip32
from trezorlib.coins import tx_api
from trezorlib.tools import parse_path
class TestMultisigChange(TrezorTest):
@ -193,7 +196,7 @@ class TestMultisigChange(TrezorTest):
)
out2 = proto.TxOutputType(
address_n=self.client.expand_path("45'/0/1/1"),
address_n=parse_path("45'/0/1/1"),
amount=44000000,
script_type=proto.OutputScriptType.PAYTOADDRESS
)
@ -209,7 +212,7 @@ class TestMultisigChange(TrezorTest):
self.setup_mnemonic_nopin_nopassphrase()
out1 = proto.TxOutputType(
address_n=self.client.expand_path("45'/0/1/0"),
address_n=parse_path("45'/0/1/0"),
amount=40000000,
script_type=proto.OutputScriptType.PAYTOADDRESS
)

View File

@ -20,7 +20,6 @@ import pytest
from .common import TrezorTest
from .conftest import TREZOR_VERSION
from trezorlib import messages as proto
from trezorlib.client import CallException

View File

@ -16,10 +16,10 @@
# You should have received a copy of the GNU Lesser General Public License
# along with this library. If not, see <http://www.gnu.org/licenses/>.
from __future__ import print_function
import time
from .common import *
import pytest
from .common import TrezorTest
from trezorlib import messages as proto
from trezorlib.client import PinException, CallException

View File

@ -15,8 +15,10 @@
#
# You should have received a copy of the GNU Lesser General Public License
# along with this library. If not, see <http://www.gnu.org/licenses/>.
from binascii import unhexlify
import pytest
from .common import *
from .common import TrezorTest
from trezorlib import messages as proto

View File

@ -15,12 +15,9 @@
#
# You should have received a copy of the GNU Lesser General Public License
# along with this library. If not, see <http://www.gnu.org/licenses/>.
from binascii import unhexlify
from __future__ import print_function
import sys
from .common import *
from .common import TrezorTest
from trezorlib import messages as proto

View File

View File

@ -27,10 +27,8 @@ from ecdsa.util import string_to_number, number_to_string
from ecdsa.curves import SECP256k1
from ecdsa.ellipticcurve import Point, INFINITY
from . import tools
from . import messages as proto
PRIME_DERIVATION_FLAG = 0x80000000
from trezorlib import tools
from trezorlib import messages
def point_to_pubkey(point):
@ -61,7 +59,7 @@ def sec_to_public_pair(pubkey):
def is_prime(n):
return (bool)(n & PRIME_DERIVATION_FLAG)
return bool(n & tools.HARDENED_FLAG)
def fingerprint(pubkey):
@ -76,7 +74,7 @@ def public_ckd(public_node, n):
if not isinstance(n, list):
raise ValueError('Parameter must be a list')
node = proto.HDNodeType()
node = messages.HDNodeType()
node.CopyFrom(public_node)
for i in n:
@ -98,7 +96,7 @@ def get_subnode(node, i):
I64 = hmac.HMAC(key=node.chain_code, msg=data, digestmod=hashlib.sha512).digest()
I_left_as_exponent = string_to_number(I64[:32])
node_out = proto.HDNodeType()
node_out = messages.HDNodeType()
node_out.depth = node.depth + 1
node_out.child_num = i
node_out.chain_code = I64[32:]
@ -128,17 +126,17 @@ def serialize(node, version=0x0488B21E):
s += b'\x00' + node.private_key
else:
s += node.public_key
s += tools.Hash(s)[:4]
s += tools.btc_hash(s)[:4]
return tools.b58encode(s)
def deserialize(xpub):
data = tools.b58decode(xpub, None)
if tools.Hash(data[:-4])[:4] != data[-4:]:
if tools.btc_hash(data[:-4])[:4] != data[-4:]:
raise ValueError("Checksum failed")
node = proto.HDNodeType()
node = messages.HDNodeType()
node.depth = struct.unpack('>B', data[4:5])[0]
node.fingerprint = struct.unpack('>I', data[5:9])[0]
node.child_num = struct.unpack('>I', data[9:13])[0]

View File

@ -16,7 +16,7 @@
# You should have received a copy of the GNU Lesser General Public License
# along with this library. If not, see <http://www.gnu.org/licenses/>.
from trezorlib import ckd_public
from ..support import ckd_public
def test_ckd_public():

View File

@ -0,0 +1,124 @@
import binascii
import hashlib
import pytest
from trezorlib import cosi
# These tests calculate Ed25519 signatures in pure Python.
# In addition to being Python, this is also DJB's proof-of-concept, unoptimized code.
# As a result, it is actually very noticeably slow. On a gen8 Core i5, this takes around 40 seconds.
# To skip the test, run `pytest -m "not slow_cosi"`.
# Therefore, the tests are skipped by default.
# Run `pytest -m slow_cosi` to explicitly enable.
pytestmark = pytest.mark.slow_cosi
if "slow_cosi" not in pytest.config.getoption("-m"):
pytestmark = pytest.mark.skip("Skipping slow CoSi tests. 'pytest -m slow_cosi' to run.")
RFC8032_VECTORS = (
( # test 1
# privkey
binascii.unhexlify("9d61b19deffd5a60ba844af492ec2cc44449c5697b326919703bac031cae7f60"),
# pubkey
binascii.unhexlify("d75a980182b10ab7d54bfed3c964073a0ee172f3daa62325af021a68f707511a"),
# message
binascii.unhexlify(""),
# signature
binascii.unhexlify("e5564300c360ac729086e2cc806e828a84877f1eb8e5d974d873e06522490155"
"5fb8821590a33bacc61e39701cf9b46bd25bf5f0595bbe24655141438e7a100b"),
),
( # test 2
# privkey
binascii.unhexlify("4ccd089b28ff96da9db6c346ec114e0f5b8a319f35aba624da8cf6ed4fb8a6fb"),
# pubkey
binascii.unhexlify("3d4017c3e843895a92b70aa74d1b7ebc9c982ccf2ec4968cc0cd55f12af4660c"),
# message
binascii.unhexlify("72"),
# signature
binascii.unhexlify("92a009a9f0d4cab8720e820b5f642540a2b27b5416503f8fb3762223ebdb69da"
"085ac1e43e15996e458f3613d0f11d8c387b2eaeb4302aeeb00d291612bb0c00"),
),
( # test 3
# privkey
binascii.unhexlify("c5aa8df43f9f837bedb7442f31dcb7b166d38535076f094b85ce3a2e0b4458f7"),
# pubkey
binascii.unhexlify("fc51cd8e6218a1a38da47ed00230f0580816ed13ba3303ac5deb911548908025"),
# message
binascii.unhexlify("af82"),
# signature
binascii.unhexlify("6291d657deec24024827e69c3abe01a30ce548a284743a445e3680d7db5ac3ac"
"18ff9b538d16f290ae67f760984dc6594a7c15e9716ed28dc027beceea1ec40a"),
),
( # test SHA(abc)
# privkey
binascii.unhexlify("833fe62409237b9d62ec77587520911e9a759cec1d19755b7da901b96dca3d42"),
# pubkey
binascii.unhexlify("ec172b93ad5e563bf4932c70e1245034c35467ef2efd4d64ebf819683467e2bf"),
# message
hashlib.sha512(b"abc").digest(),
# signature
binascii.unhexlify("dc2a4459e7369633a52b1bf277839a00201009a3efbf3ecb69bea2186c26b589"
"09351fc9ac90b3ecfdfbc7c66431e0303dca179c138ac17ad9bef1177331a704"),
),
)
COMBINED_KEY = binascii.unhexlify("283967b1c19ff93d2924cdcba95e586547cafef509ea402963ceefe96ccb44f2")
GLOBAL_COMMIT = binascii.unhexlify("75bd5806c6366e0374a1c6e020c53feb0791d6cc07560d27d8c158f886ecf389")
@pytest.mark.parametrize("privkey, pubkey, message, signature",
RFC8032_VECTORS)
def test_single_eddsa_vector(privkey, pubkey, message, signature):
my_pubkey = cosi.pubkey_from_privkey(privkey)
assert my_pubkey == pubkey
try:
cosi.verify(signature, message, pubkey)
except ValueError:
pytest.fail("Signature does not verify.")
fake_signature = b'\xf1' + signature[1:]
with pytest.raises(ValueError):
cosi.verify(fake_signature, message, pubkey)
def test_combine_keys():
pubkeys = [pubkey for _, pubkey, _, _ in RFC8032_VECTORS]
assert cosi.combine_keys(pubkeys) == COMBINED_KEY
Rs = [cosi.get_nonce(privkey, message)[1] for privkey, _, message, _ in RFC8032_VECTORS]
assert cosi.combine_keys(Rs) == GLOBAL_COMMIT
@pytest.mark.parametrize("keyset", [
(0,),
(0, 1),
(0, 1, 2),
(0, 1, 2, 3),
(1, 3),
])
def test_cosi_combination(keyset):
message = hashlib.sha512(b"You all have to sign this.").digest()
selection = [RFC8032_VECTORS[i] for i in keyset]
# zip(*iterable) turns a list of tuples to a tuple of lists
privkeys, pubkeys, _, _ = zip(*selection)
nonce_pairs = [cosi.get_nonce(pk, message) for pk in privkeys]
nonces, commits = zip(*nonce_pairs)
# calculate global pubkey and commitment
global_pk = cosi.combine_keys(pubkeys)
global_commit = cosi.combine_keys(commits)
# generate individual signatures
signatures = [cosi.sign_with_privkey(message, privkey, global_pk, nonce, global_commit)
for privkey, nonce in zip(privkeys, nonces)]
# combine signatures
global_sig = cosi.combine_sig(global_commit, signatures)
try:
cosi.verify(global_sig, message, global_pk)
except ValueError:
pytest.fail("Failed to validate global signature")

View File

@ -18,12 +18,27 @@
# along with this library. If not, see <http://www.gnu.org/licenses/>.
import hashlib
import binascii
import struct
import sys
from typing import NewType, List
from .coins import slip44
HARDENED_FLAG = 1 << 31
Address = NewType('Address', List[int])
def Hash(data):
def H_(x: int) -> int:
"""
Shortcut function that "hardens" a number in a BIP44 path.
"""
return x | HARDENED_FLAG
def btc_hash(data):
"""
Double-SHA256 hash as used in BTC
"""
return hashlib.sha256(hashlib.sha256(data).digest()).digest()
@ -35,7 +50,7 @@ def hash_160(public_key):
def hash_160_to_bc_address(h160, address_type):
vh160 = struct.pack('<B', address_type) + h160
h = Hash(vh160)
h = btc_hash(vh160)
addr = vh160 + h[0:4]
return b58encode(addr)
@ -109,3 +124,41 @@ def b58decode(v, length):
return None
return result
def parse_path(nstr: str) -> Address:
"""
Convert BIP32 path string to list of uint32 integers with hardened flags.
Several conventions are supported to set the hardened flag: -1, 1', 1h
e.g.: "0/1h/1" -> [0, 0x80000001, 1]
:param nstr: path string
:return: list of integers
"""
if not nstr:
return []
n = nstr.split('/')
# m/a/b/c => a/b/c
if n[0] == 'm':
n = n[1:]
# coin_name/a/b/c => 44'/SLIP44_constant'/a/b/c
if n[0] in slip44:
coin_id = slip44[n[0]]
n[0:1] = ['44h', '{}h'.format(coin_id)]
def str_to_harden(x: str) -> int:
if x.startswith('-'):
return H_(abs(int(x)))
elif x.endswith(('h', "'")):
return H_(int(x[:-1]))
else:
return int(x)
try:
return list(str_to_harden(x) for x in n)
except Exception:
raise ValueError('Invalid BIP32 path', nstr)

View File

@ -17,6 +17,13 @@
# You should have received a copy of the GNU Lesser General Public License
# along with this library. If not, see <http://www.gnu.org/licenses/>.
import importlib
import logging
from typing import Iterable, Type, List, Set
LOG = logging.getLogger(__name__)
class TransportException(Exception):
pass
@ -63,54 +70,52 @@ class Transport(object):
raise TransportException('{} device not found: {}'.format(cls.PATH_PREFIX, path))
def all_transports():
transports = []
try:
from .bridge import BridgeTransport
transports.append(BridgeTransport)
except:
pass
try:
from .hid import HidTransport
transports.append(HidTransport)
except:
pass
try:
from .udp import UdpTransport
transports.append(UdpTransport)
except:
pass
try:
from .webusb import WebUsbTransport
transports.append(WebUsbTransport)
except:
pass
def all_transports() -> Iterable[Type[Transport]]:
transports = set() # type: Set[Type[Transport]]
for modname in ("bridge", "hid", "udp", "webusb"):
try:
# Import the module and find the Transport class.
# To avoid iterating over every item, the module should assign its Transport class
# to a constant named TRANSPORT.
module = importlib.import_module("." + modname, __name__)
try:
transports.add(getattr(module, "TRANSPORT"))
except AttributeError:
LOG.warning("Skipping broken module {}".format(modname))
except ImportError as e:
LOG.info("Failed to import module {}: {}".format(modname, e))
return transports
def enumerate_devices():
return [device
for transport in all_transports()
for device in transport.enumerate()]
def enumerate_devices() -> Iterable[Transport]:
devices = [] # type: List[Transport]
for transport in all_transports():
try:
found = transport.enumerate()
LOG.info("Enumerating {}: found {} devices".format(transport.__name__, len(found)))
devices.extend(found)
except NotImplementedError:
LOG.error("{} does not implement device enumeration".format(transport.__name__))
except Exception as e:
LOG.error("Failed to enumerate {}. {}: {}".format(transport.__name__, e.__class__.__name__, e))
return devices
def get_transport(path=None, prefix_search=False):
def get_transport(path: str = None, prefix_search: bool = False) -> Transport:
if path is None:
try:
return enumerate_devices()[0]
return next(iter(enumerate_devices()))
except IndexError:
raise Exception("No TREZOR device found") from None
# Find whether B is prefix of A (transport name is part of the path)
# or A is prefix of B (path is a prefix, or a name, of transport).
# This naively expects that no two transports have a common prefix.
def match_prefix(a, b):
def match_prefix(a: str, b: str) -> bool:
return a.startswith(b) or b.startswith(a)
LOG.info("looking for device by {}: {}".format("prefix" if prefix_search else "full path", path))
transports = [t for t in all_transports() if match_prefix(path, t.PATH_PREFIX)]
if transports:
return transports[0].find_by_path(path, prefix_search=prefix_search)

View File

@ -17,6 +17,7 @@
# You should have received a copy of the GNU Lesser General Public License
# along with this library. If not, see <http://www.gnu.org/licenses/>.
import logging
import requests
import binascii
from io import BytesIO
@ -27,6 +28,8 @@ from .. import messages
from .. import protobuf
from . import Transport, TransportException
LOG = logging.getLogger(__name__)
TREZORD_HOST = 'http://127.0.0.1:21325'
@ -78,6 +81,8 @@ class BridgeTransport(Transport):
self.session = None
def write(self, msg):
LOG.debug("sending message: {}".format(msg.__class__.__name__),
extra={'protobuf': msg})
data = BytesIO()
protobuf.dump_message(data, msg)
ser = data.getvalue()
@ -97,5 +102,10 @@ class BridgeTransport(Transport):
(msg_type, datalen) = struct.unpack('>HL', data[:headerlen])
data = BytesIO(data[headerlen:headerlen + datalen])
msg = protobuf.load_message(data, mapping.get_class(msg_type))
LOG.debug("received message: {}".format(msg.__class__.__name__),
extra={'protobuf': msg})
self.response = None
return msg
TRANSPORT = BridgeTransport

View File

@ -180,3 +180,6 @@ def is_wirelink(dev):
def is_debuglink(dev):
return (dev['usage_page'] == 0xFF01 or dev['interface_number'] == 1)
TRANSPORT = HidTransport

View File

@ -124,3 +124,6 @@ class UdpTransport(Transport):
if len(chunk) != 64:
raise TransportException('Unexpected chunk size: %d' % len(chunk))
return bytearray(chunk)
TRANSPORT = UdpTransport

View File

@ -188,3 +188,6 @@ def is_vendor_class(dev):
def dev_to_str(dev):
return ':'.join(str(x) for x in ['%03i' % (dev.getBusNumber(), )] + dev.getPortNumberList())
TRANSPORT = WebUsbTransport

View File

@ -9,6 +9,11 @@ if [ "$TRAVIS_REPO_SLUG" != "$SOURCE" ]; then
exit 0;
fi
if [ "$TRAVIS_BRANCH" != "master" ]; then
echo "not triggering from non-master branch"
exit 0;
fi
if [ "$TRAVIS_PULL_REQUEST" != "false" ]; then
echo "not triggering from pull requests"
exit 0;