1
0
mirror of https://github.com/trezor/trezor-firmware.git synced 2024-12-28 09:08:07 +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 = ignore =
# F401: module imported but unused # F401: module imported but unused
F401, F401,
# F403: used import *
F403,
# F405 'foo' may be undefined, or defined from star imports
F405,
# E241: multiple spaces after ':' # E241: multiple spaces after ':'
E241, E241,
# E402: module level import not at top of file # E402: module level import not at top of file
E402, E402,
# E501: line too long # E501: line too long
E501, E501,
# E721: do not compare types, use 'isinstance()'
E721,
# E722: do not use bare except # E722: do not use bare except
E722, E722,
# E741: ambiguous variable name # E741: ambiguous variable name

View File

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

View File

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

View File

@ -14,6 +14,13 @@ from trezorlib.tx_api import TxApiBitcoin
from trezorlib.transport import get_transport 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): def hash160(x):
h = hashlib.new("ripemd160") h = hashlib.new("ripemd160")
h.update(hashlib.sha256(x).digest()) h.update(hashlib.sha256(x).digest())
@ -110,7 +117,7 @@ class MyTxApiBitcoin(object):
o.script_pubkey = b'\x76\xa9\x14' + pubkey + b'\x88\xac' o.script_pubkey = b'\x76\xa9\x14' + pubkey + b'\x88\xac'
txser = self.serialize_tx(t) txser = self.serialize_tx(t)
txhash = tools.Hash(txser)[::-1] txhash = tools.btc_hash(txser)[::-1]
self.inputs.append( self.inputs.append(
proto_types.TxInputType( proto_types.TxInputType(
address_n=self.client.expand_path("44'/0'/0'/0/%d" % idx), address_n=self.client.expand_path("44'/0'/0'/0/%d" % idx),

View File

@ -23,18 +23,19 @@
import base64 import base64
import binascii import binascii
import click import click
import functools
import json import json
import logging
import os import os
import sys import sys
from trezorlib.client import TrezorClient, TrezorClientVerbose, CallException, format_protobuf from trezorlib.client import TrezorClient, CallException
from trezorlib.transport import get_transport, enumerate_devices, TransportException from trezorlib.transport import get_transport, enumerate_devices
from trezorlib import coins from trezorlib import coins
from trezorlib import log
from trezorlib import messages as proto from trezorlib import messages as proto
from trezorlib import protobuf from trezorlib import protobuf
from trezorlib.ckd_public import PRIME_DERIVATION_FLAG
from trezorlib import stellar from trezorlib import stellar
from trezorlib import tools
class ChoiceType(click.Choice): 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.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('-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('-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.option('-j', '--json', 'is_json', is_flag=True, help='Print result as JSON object')
@click.pass_context @click.pass_context
def cli(ctx, path, verbose, is_json): def cli(ctx, path, verbose, is_json):
if ctx.invoked_subcommand != 'list': if verbose:
if verbose: enable_logging()
cls = TrezorClientVerbose
else:
cls = TrezorClient
def get_device(): def get_device():
try:
device = get_transport(path, prefix_search=False)
except:
try: try:
device = get_transport(path, prefix_search=False) device = get_transport(path, prefix_search=True)
except: except:
try: click.echo("Failed to find a TREZOR device.")
device = get_transport(path, prefix_search=True) if path is not None:
except: click.echo("Using path: {}".format(path))
click.echo("Failed to find a TREZOR device.") sys.exit(1)
if path is not None: return TrezorClient(transport=device)
click.echo("Using path: {}".format(path))
sys.exit(1)
return cls(transport=device)
ctx.obj = get_device ctx.obj = get_device
@cli.resultcallback() @cli.resultcallback()
@ -112,7 +115,7 @@ def print_result(res, path, verbose, is_json):
else: else:
click.echo('%s: %s' % (k, v)) click.echo('%s: %s' % (k, v))
elif isinstance(res, protobuf.MessageType): elif isinstance(res, protobuf.MessageType):
click.echo(format_protobuf(res)) click.echo(protobuf.format_message(res))
else: else:
click.echo(res) click.echo(res)
@ -449,7 +452,7 @@ def self_test(connect):
@click.pass_obj @click.pass_obj
def get_address(connect, coin, address, script_type, show_display): def get_address(connect, coin, address, script_type, show_display):
client = connect() 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) 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 @click.pass_obj
def get_public_node(connect, coin, address, curve, show_display): def get_public_node(connect, coin, address, curve, show_display):
client = connect() 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) result = client.get_public_node(address_n, ecdsa_curve_name=curve, show_display=show_display, coin_name=coin)
return { return {
'node': { 'node': {
@ -502,7 +505,7 @@ def sign_tx(connect, coin):
if address_n is None: if address_n is None:
pass pass
elif address_n[0] == (49 | PRIME_DERIVATION_FLAG): elif address_n[0] == tools.H_(49):
script_type = 'p2shsegwit' script_type = 'p2shsegwit'
return script_type return script_type
@ -518,7 +521,7 @@ def sign_tx(connect, coin):
if not prev: if not prev:
break break
prev_hash, prev_index = prev 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) 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) 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)) 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 address_n = None
else: else:
address = None 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: if not address_n:
break break
amount = click.prompt('Amount to spend (satoshis)', type=int) amount = click.prompt('Amount to spend (satoshis)', type=int)
@ -581,7 +584,7 @@ def sign_tx(connect, coin):
@click.pass_obj @click.pass_obj
def sign_message(connect, coin, address, message, script_type): def sign_message(connect, coin, address, message, script_type):
client = connect() client = connect()
address_n = client.expand_path(address) address_n = tools.parse_path(address)
typemap = { typemap = {
'address': proto.InputScriptType.SPENDADDRESS, 'address': proto.InputScriptType.SPENDADDRESS,
'segwit': proto.InputScriptType.SPENDWITNESS, 'segwit': proto.InputScriptType.SPENDWITNESS,
@ -613,7 +616,7 @@ def verify_message(connect, coin, address, signature, message):
@click.pass_obj @click.pass_obj
def ethereum_sign_message(connect, address, message): def ethereum_sign_message(connect, address, message):
client = connect() client = connect()
address_n = client.expand_path(address) address_n = tools.parse_path(address)
ret = client.ethereum_sign_message(address_n, message) ret = client.ethereum_sign_message(address_n, message)
output = { output = {
'message': message, 'message': message,
@ -648,7 +651,7 @@ def ethereum_verify_message(connect, address, signature, message):
@click.pass_obj @click.pass_obj
def encrypt_keyvalue(connect, address, key, value): def encrypt_keyvalue(connect, address, key, value):
client = connect() client = connect()
address_n = client.expand_path(address) address_n = tools.parse_path(address)
res = client.encrypt_keyvalue(address_n, key, value.encode()) res = client.encrypt_keyvalue(address_n, key, value.encode())
return binascii.hexlify(res) return binascii.hexlify(res)
@ -660,7 +663,7 @@ def encrypt_keyvalue(connect, address, key, value):
@click.pass_obj @click.pass_obj
def decrypt_keyvalue(connect, address, key, value): def decrypt_keyvalue(connect, address, key, value):
client = connect() client = connect()
address_n = client.expand_path(address) address_n = tools.parse_path(address)
return client.decrypt_keyvalue(address_n, key, binascii.unhexlify(value)) 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): def encrypt_message(connect, coin, display_only, address, pubkey, message):
client = connect() client = connect()
pubkey = binascii.unhexlify(pubkey) 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) res = client.encrypt_message(pubkey, message, display_only, coin, address_n)
return { return {
'nonce': binascii.hexlify(res.nonce), 'nonce': binascii.hexlify(res.nonce),
@ -690,7 +693,7 @@ def encrypt_message(connect, coin, display_only, address, pubkey, message):
@click.pass_obj @click.pass_obj
def decrypt_message(connect, address, payload): def decrypt_message(connect, address, payload):
client = connect() client = connect()
address_n = client.expand_path(address) address_n = tools.parse_path(address)
payload = base64.b64decode(payload) payload = base64.b64decode(payload)
nonce, message, msg_hmac = payload[:33], payload[33:-8], payload[-8:] nonce, message, msg_hmac = payload[:33], payload[33:-8], payload[-8:]
return client.decrypt_message(address_n, nonce, message, msg_hmac) return client.decrypt_message(address_n, nonce, message, msg_hmac)
@ -707,7 +710,7 @@ def decrypt_message(connect, address, payload):
@click.pass_obj @click.pass_obj
def ethereum_get_address(connect, address, show_display): def ethereum_get_address(connect, address, show_display):
client = connect() client = connect()
address_n = client.expand_path(address) address_n = tools.parse_path(address)
address = client.ethereum_get_address(address_n, show_display) address = client.ethereum_get_address(address_n, show_display)
return '0x%s' % binascii.hexlify(address).decode() 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) to_address = ethereum_decode_hex(to)
client = connect() 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()) 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: 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 @click.pass_obj
def nem_get_address(connect, address, network, show_display): def nem_get_address(connect, address, network, show_display):
client = connect() client = connect()
address_n = client.expand_path(address) address_n = tools.parse_path(address)
return client.nem_get_address(address_n, network, show_display) 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 @click.pass_obj
def nem_sign_tx(connect, address, file, broadcast): def nem_sign_tx(connect, address, file, broadcast):
client = connect() client = connect()
address_n = client.expand_path(address) address_n = tools.parse_path(address)
transaction = client.nem_sign_tx(address_n, json.load(file)) transaction = client.nem_sign_tx(address_n, json.load(file))
payload = { payload = {
@ -873,7 +876,7 @@ def nem_sign_tx(connect, address, file, broadcast):
@click.pass_obj @click.pass_obj
def lisk_get_address(connect, address, show_display): def lisk_get_address(connect, address, show_display):
client = connect() client = connect()
address_n = client.expand_path(address) address_n = tools.parse_path(address)
return client.lisk_get_address(address_n, show_display) return client.lisk_get_address(address_n, show_display)
@ -883,7 +886,7 @@ def lisk_get_address(connect, address, show_display):
@click.pass_obj @click.pass_obj
def lisk_get_public_key(connect, address, show_display): def lisk_get_public_key(connect, address, show_display):
client = connect() client = connect()
address_n = client.expand_path(address) address_n = tools.parse_path(address)
res = client.lisk_get_public_key(address_n, show_display) res = client.lisk_get_public_key(address_n, show_display)
output = { output = {
"public_key": binascii.hexlify(res.public_key).decode() "public_key": binascii.hexlify(res.public_key).decode()
@ -898,7 +901,7 @@ def lisk_get_public_key(connect, address, show_display):
@click.pass_obj @click.pass_obj
def lisk_sign_tx(connect, address, file): def lisk_sign_tx(connect, address, file):
client = connect() client = connect()
address_n = client.expand_path(address) address_n = tools.parse_path(address)
transaction = client.lisk_sign_tx(address_n, json.load(file)) transaction = client.lisk_sign_tx(address_n, json.load(file))
payload = { payload = {
@ -919,7 +922,7 @@ def lisk_sign_tx(connect, address, file):
@click.pass_obj @click.pass_obj
def cosi_commit(connect, address, data): def cosi_commit(connect, address, data):
client = connect() client = connect()
address_n = client.expand_path(address) address_n = tools.parse_path(address)
return client.cosi_commit(address_n, binascii.unhexlify(data)) return client.cosi_commit(address_n, binascii.unhexlify(data))
@ -931,7 +934,7 @@ def cosi_commit(connect, address, data):
@click.pass_obj @click.pass_obj
def cosi_sign(connect, address, data, global_commitment, global_pubkey): def cosi_sign(connect, address, data, global_commitment, global_pubkey):
client = connect() 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)) 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 # Stellar functions
# #
@cli.command(help='Get Stellar public address') @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 @click.pass_obj
def stellar_get_address(connect, address): def stellar_get_address(connect, address):
client = connect() client = connect()
address_n = stellar.expand_path_or_default(client, address) address_n = tools.parse_path(address)
# StellarPublicKey response # StellarPublicKey response
response = client.stellar_get_public_key(address_n) response = client.stellar_get_public_key(address_n)
return stellar.address_from_public_key(response.public_key) return stellar.address_from_public_key(response.public_key)
@cli.command(help='Sign a base64-encoded transaction envelope') @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.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.argument('b64envelope')
@click.pass_obj @click.pass_obj
def stellar_sign_transaction(connect, b64envelope, address, network_passphrase): def stellar_sign_transaction(connect, b64envelope, address, network_passphrase):
client = connect() client = connect()
address_n = tools.parse_path(address)
address_n = stellar.expand_path_or_default(client, address)
tx, operations = stellar.parse_transaction_bytes(base64.b64decode(b64envelope)) tx, operations = stellar.parse_transaction_bytes(base64.b64decode(b64envelope))
resp = client.stellar_sign_transaction(tx, operations, address_n, network_passphrase) 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 # orignal version downloaded from https://ed25519.cr.yp.to/python/ed25519.py
# modified for Python 3 by Jochen Hoenicke <hoenicke@gmail.com> # modified for Python 3 by Jochen Hoenicke <hoenicke@gmail.com>
import sys
import hashlib import hashlib
from typing import Tuple, NewType
Point = NewType("Point", Tuple[int, int])
b = 256 b = 256
q = 2 ** 255 - 19 q = 2 ** 255 - 19
l = 2 ** 252 + 27742317777372353535851937790883648493 l = 2 ** 252 + 27742317777372353535851937790883648493
def H(m): def H(m: bytes) -> bytes:
return hashlib.sha512(m).digest() return hashlib.sha512(m).digest()
def expmod(b, e, m): def expmod(b: int, e: int, m: int) -> int:
if e < 0: if e < 0:
raise ValueError('negative exponent') raise ValueError('negative exponent')
if e == 0: if e == 0:
@ -24,7 +26,7 @@ def expmod(b, e, m):
return t return t
def inv(x): def inv(x: int) -> int:
return expmod(x, q - 2, q) return expmod(x, q - 2, q)
@ -32,7 +34,7 @@ d = -121665 * inv(121666)
I = expmod(2, (q - 1) >> 2, q) I = expmod(2, (q - 1) >> 2, q)
def xrecover(y): def xrecover(y: int) -> int:
xx = (y * y - 1) * inv(d * y * y + 1) xx = (y * y - 1) * inv(d * y * y + 1)
x = expmod(xx, (q + 3) >> 3, q) x = expmod(xx, (q + 3) >> 3, q)
if (x * x - xx) % q != 0: if (x * x - xx) % q != 0:
@ -44,22 +46,22 @@ def xrecover(y):
By = 4 * inv(5) By = 4 * inv(5)
Bx = xrecover(By) 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] x1 = P[0]
y1 = P[1] y1 = P[1]
x2 = Q[0] x2 = Q[0]
y2 = Q[1] y2 = Q[1]
x3 = (x1 * y2 + x2 * y1) * inv(1 + d * x1 * x2 * y1 * y2) x3 = (x1 * y2 + x2 * y1) * inv(1 + d * x1 * x2 * y1 * y2)
y3 = (y1 * y2 + x1 * x2) * 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: if e == 0:
return [0, 1] return Point((0, 1))
Q = scalarmult(P, e >> 1) Q = scalarmult(P, e >> 1)
Q = edwards(Q, Q) Q = edwards(Q, Q)
if e & 1: if e & 1:
@ -67,35 +69,35 @@ def scalarmult(P, e):
return Q return Q
def encodeint(y): def encodeint(y: int) -> bytes:
bits = [(y >> i) & 1 for i in range(b)] 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)]) 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] x = P[0]
y = P[1] y = P[1]
bits = [(y >> i) & 1 for i in range(b - 1)] + [x & 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)]) 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 return (h[i >> 3] >> (i & 7)) & 1
def publickey(sk): def publickey(sk: bytes) -> bytes:
h = H(sk) h = H(sk)
a = 2 ** (b - 2) + sum(2 ** i * bit(h, i) for i in range(3, b - 2)) a = 2 ** (b - 2) + sum(2 ** i * bit(h, i) for i in range(3, b - 2))
A = scalarmult(B, a) A = scalarmult(B, a)
return encodepoint(A) return encodepoint(A)
def Hint(m): def Hint(m: bytes) -> int:
h = H(m) h = H(m)
return sum(2 ** i * bit(h, i) for i in range(2 * b)) 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) h = H(sk)
a = 2 ** (b - 2) + sum(2 ** i * bit(h, i) for i in range(3, b - 2)) 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) 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) return encodepoint(R) + encodeint(S)
def isoncurve(P): def isoncurve(P: Point) -> bool:
x = P[0] x = P[0]
y = P[1] y = P[1]
return (-x * x + y * y - 1 - d * x * x * y * y) % q == 0 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)) 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)) y = sum(2 ** i * bit(s, i) for i in range(0, b - 1))
x = xrecover(y) x = xrecover(y)
if x & 1 != bit(s, b - 1): if x & 1 != bit(s, b - 1):
x = q - x x = q - x
P = [x, y] P = Point((x, y))
if not isoncurve(P): if not isoncurve(P):
raise ValueError('decoding point that is not on curve') raise ValueError('decoding point that is not on curve')
return P return P
def checkvalid(s, m, pk): def checkvalid(s: bytes, m: bytes, pk: bytes) -> None:
if len(s) != b >> 2: if len(s) != b >> 2:
raise ValueError('signature length is wrong') raise ValueError('signature length is wrong')
if len(pk) != b >> 3: if len(pk) != b >> 3:

View File

@ -17,8 +17,8 @@
# You should have received a copy of the GNU Lesser General Public License # 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/>. # 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 os
import sys import sys
import time import time
@ -34,18 +34,16 @@ from . import messages as proto
from . import tools from . import tools
from . import mapping from . import mapping
from . import nem from . import nem
from .coins import slip44 from . import protobuf
from . import stellar from . import stellar
from .debuglink import DebugLink from .debuglink import DebugLink
from .protobuf import MessageType
if sys.version_info.major < 3: if sys.version_info.major < 3:
raise Exception("Trezorlib does not support Python 2 anymore.") raise Exception("Trezorlib does not support Python 2 anymore.")
SCREENSHOT = False SCREENSHOT = False
LOG = logging.getLogger(__name__)
# make a getch function # make a getch function
try: 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] 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): class CallException(Exception):
def __init__(self, code, message): pass
super(CallException, self).__init__()
self.args = [code, message]
class AssertionException(Exception):
def __init__(self, code, message):
self.args = [code, message]
class PinException(CallException): class PinException(CallException):
pass pass
class field(object): class field:
# Decorator extracts single value from # Decorator extracts single value from
# protobuf object. If the field is not # protobuf object. If the field is not
# present, raises an exception. # present, raises an exception.
@ -155,13 +98,14 @@ class field(object):
self.field = field self.field = field
def __call__(self, f): def __call__(self, f):
@functools.wraps(f)
def wrapped_f(*args, **kwargs): def wrapped_f(*args, **kwargs):
ret = f(*args, **kwargs) ret = f(*args, **kwargs)
return getattr(ret, self.field) return getattr(ret, self.field)
return wrapped_f return wrapped_f
class expect(object): class expect:
# Decorator checks if the method # Decorator checks if the method
# returned one of expected protobuf messages # returned one of expected protobuf messages
# or raises an exception # or raises an exception
@ -169,6 +113,7 @@ class expect(object):
self.expected = expected self.expected = expected
def __call__(self, f): def __call__(self, f):
@functools.wraps(f)
def wrapped_f(*args, **kwargs): def wrapped_f(*args, **kwargs):
ret = f(*args, **kwargs) ret = f(*args, **kwargs)
if not isinstance(ret, self.expected): if not isinstance(ret, self.expected):
@ -180,7 +125,9 @@ class expect(object):
def session(f): def session(f):
# Decorator wraps a BaseClient method # Decorator wraps a BaseClient method
# with session activation / deactivation # with session activation / deactivation
@functools.wraps(f)
def wrapped_f(*args, **kwargs): def wrapped_f(*args, **kwargs):
__tracebackhide__ = True # pytest traceback hiding - this function won't appear in tracebacks
client = args[0] client = args[0]
client.transport.session_begin() client.transport.session_begin()
try: try:
@ -204,6 +151,7 @@ class BaseClient(object):
# Implements very basic layer of sending raw protobuf # Implements very basic layer of sending raw protobuf
# messages to device and getting its response back. # messages to device and getting its response back.
def __init__(self, transport, **kwargs): def __init__(self, transport, **kwargs):
LOG.info("creating client instance for device: {}".format(transport.get_path()))
self.transport = transport self.transport = transport
super(BaseClient, self).__init__() # *args, **kwargs) super(BaseClient, self).__init__() # *args, **kwargs)
@ -215,6 +163,7 @@ class BaseClient(object):
@session @session
def call_raw(self, msg): def call_raw(self, msg):
__tracebackhide__ = True # pytest traceback hiding - this function won't appear in tracebacks
self.transport.write(msg) self.transport.write(msg)
return self.transport.read() return self.transport.read()
@ -244,14 +193,6 @@ class BaseClient(object):
mapping.register_message(msg) 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): class TextUIMixin(object):
# This class demonstrates easy test-based UI # This class demonstrates easy test-based UI
# integration between the device and wallet. # integration between the device and wallet.
@ -262,6 +203,10 @@ class TextUIMixin(object):
def __init__(self, *args, **kwargs): def __init__(self, *args, **kwargs):
super(TextUIMixin, self).__init__(*args, **kwargs) super(TextUIMixin, self).__init__(*args, **kwargs)
@staticmethod
def print(text):
print(text, file=sys.stderr)
def callback_ButtonRequest(self, msg): def callback_ButtonRequest(self, msg):
# log("Sending ButtonAck for %s " % get_buttonrequest_value(msg.code)) # log("Sending ButtonAck for %s " % get_buttonrequest_value(msg.code))
return proto.ButtonAck() return proto.ButtonAck()
@ -269,11 +214,11 @@ class TextUIMixin(object):
def callback_RecoveryMatrix(self, msg): def callback_RecoveryMatrix(self, msg):
if self.recovery_matrix_first_pass: if self.recovery_matrix_first_pass:
self.recovery_matrix_first_pass = False self.recovery_matrix_first_pass = False
log("Use the numeric keypad to describe positions. For the word list use only left and right keys.") self.print("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:") self.print("Use backspace to correct an entry. The keypad layout is:")
log(" 7 8 9 7 | 9") self.print(" 7 8 9 7 | 9")
log(" 4 5 6 4 | 6") self.print(" 4 5 6 4 | 6")
log(" 1 2 3 1 | 3") self.print(" 1 2 3 1 | 3")
while True: while True:
character = getch() character = getch()
if character in ('\x03', '\x04'): if character in ('\x03', '\x04'):
@ -299,11 +244,11 @@ class TextUIMixin(object):
else: else:
desc = 'PIN' desc = 'PIN'
log("Use the numeric keypad to describe number positions. The layout is:") self.print("Use the numeric keypad to describe number positions. The layout is:")
log(" 7 8 9") self.print(" 7 8 9")
log(" 4 5 6") self.print(" 4 5 6")
log(" 1 2 3") self.print(" 1 2 3")
log("Please enter %s: " % desc) self.print("Please enter %s: " % desc)
pin = getpass.getpass('') pin = getpass.getpass('')
if not pin.isdigit(): if not pin.isdigit():
raise ValueError('Non-numerical PIN provided') raise ValueError('Non-numerical PIN provided')
@ -314,18 +259,18 @@ class TextUIMixin(object):
return proto.PassphraseAck() return proto.PassphraseAck()
if os.getenv("PASSPHRASE") is not None: 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")) passphrase = Mnemonic.normalize_string(os.getenv("PASSPHRASE"))
return proto.PassphraseAck(passphrase=passphrase) return proto.PassphraseAck(passphrase=passphrase)
log("Passphrase required: ") self.print("Passphrase required: ")
passphrase = getpass.getpass('') passphrase = getpass.getpass('')
log("Confirm your Passphrase: ") self.print("Confirm your Passphrase: ")
if passphrase == getpass.getpass(''): if passphrase == getpass.getpass(''):
passphrase = Mnemonic.normalize_string(passphrase) passphrase = Mnemonic.normalize_string(passphrase)
return proto.PassphraseAck(passphrase=passphrase) return proto.PassphraseAck(passphrase=passphrase)
else: else:
log("Passphrase did not match! ") self.print("Passphrase did not match! ")
exit() exit()
def callback_PassphraseStateRequest(self, msg): def callback_PassphraseStateRequest(self, msg):
@ -335,7 +280,7 @@ class TextUIMixin(object):
if msg.type in (proto.WordRequestType.Matrix9, if msg.type in (proto.WordRequestType.Matrix9,
proto.WordRequestType.Matrix6): proto.WordRequestType.Matrix6):
return self.callback_RecoveryMatrix(msg) return self.callback_RecoveryMatrix(msg)
log("Enter one word of mnemonic: ") self.print("Enter one word of mnemonic: ")
word = input() word = input()
if self.expand: if self.expand:
word = self.mnemonic_wordlist.expand_word(word) word = self.mnemonic_wordlist.expand_word(word)
@ -352,6 +297,7 @@ class DebugLinkMixin(object):
# of unit testing, because it will fail to work # of unit testing, because it will fail to work
# without special DebugLink interface provided # without special DebugLink interface provided
# by the device. # by the device.
DEBUG = LOG.getChild('debug_link').debug
def __init__(self, *args, **kwargs): def __init__(self, *args, **kwargs):
super(DebugLinkMixin, self).__init__(*args, **kwargs) super(DebugLinkMixin, self).__init__(*args, **kwargs)
@ -396,7 +342,7 @@ class DebugLinkMixin(object):
# Evaluate missed responses in 'with' statement # Evaluate missed responses in 'with' statement
if self.expected_responses is not None and len(self.expected_responses): if self.expected_responses is not None and len(self.expected_responses):
raise RuntimeError("Some of expected responses didn't come from device: %s" % 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 # Cleanup
self.expected_responses = None self.expected_responses = None
@ -418,6 +364,7 @@ class DebugLinkMixin(object):
self.mnemonic = Mnemonic.normalize_string(mnemonic).split(' ') self.mnemonic = Mnemonic.normalize_string(mnemonic).split(' ')
def call_raw(self, msg): def call_raw(self, msg):
__tracebackhide__ = True # pytest traceback hiding - this function won't appear in tracebacks
if SCREENSHOT and self.debug: if SCREENSHOT and self.debug:
from PIL import Image from PIL import Image
@ -437,30 +384,32 @@ class DebugLinkMixin(object):
return resp return resp
def _check_request(self, msg): def _check_request(self, msg):
__tracebackhide__ = True # pytest traceback hiding - this function won't appear in tracebacks
if self.expected_responses is not None: if self.expected_responses is not None:
try: try:
expected = self.expected_responses.pop(0) expected = self.expected_responses.pop(0)
except IndexError: except IndexError:
raise AssertionException(proto.FailureType.UnexpectedMessage, raise AssertionError(proto.FailureType.UnexpectedMessage,
"Got %s, but no message has been expected" % pprint(msg)) "Got %s, but no message has been expected" % repr(msg))
if msg.__class__ != expected.__class__: if msg.__class__ != expected.__class__:
raise AssertionException(proto.FailureType.UnexpectedMessage, raise AssertionError(proto.FailureType.UnexpectedMessage,
"Expected %s, got %s" % (pprint(expected), pprint(msg))) "Expected %s, got %s" % (repr(expected), repr(msg)))
for field, value in expected.__dict__.items(): for field, value in expected.__dict__.items():
if value is None or value == []: if value is None or value == []:
continue continue
if getattr(msg, field) != value: if getattr(msg, field) != value:
raise AssertionException(proto.FailureType.UnexpectedMessage, raise AssertionError(proto.FailureType.UnexpectedMessage,
"Expected %s, got %s" % (pprint(expected), pprint(msg))) "Expected %s, got %s" % (repr(expected), repr(msg)))
def callback_ButtonRequest(self, 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: if self.button_wait:
log("Waiting %d seconds " % self.button_wait) self.DEBUG("Waiting %d seconds " % self.button_wait)
time.sleep(self.button_wait) time.sleep(self.button_wait)
self.debug.press_button(self.button) self.debug.press_button(self.button)
return proto.ButtonAck() return proto.ButtonAck()
@ -473,7 +422,7 @@ class DebugLinkMixin(object):
return proto.PinMatrixAck(pin=pin) return proto.PinMatrixAck(pin=pin)
def callback_PassphraseRequest(self, msg): def callback_PassphraseRequest(self, msg):
log("Provided passphrase: '%s'" % self.passphrase) self.DEBUG("Provided passphrase: '%s'" % self.passphrase)
return proto.PassphraseAck(passphrase=self.passphrase) return proto.PassphraseAck(passphrase=self.passphrase)
def callback_PassphraseStateRequest(self, msg): def callback_PassphraseStateRequest(self, msg):
@ -490,7 +439,6 @@ class DebugLinkMixin(object):
class ProtocolMixin(object): class ProtocolMixin(object):
PRIME_DERIVATION_FLAG = 0x80000000
VENDORS = ('bitcointrezor.com', 'trezor.io') VENDORS = ('bitcointrezor.com', 'trezor.io')
def __init__(self, state=None, *args, **kwargs): def __init__(self, state=None, *args, **kwargs):
@ -513,44 +461,15 @@ class ProtocolMixin(object):
def _get_local_entropy(self): def _get_local_entropy(self):
return os.urandom(32) 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 # 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 @staticmethod
def expand_path(n): def expand_path(n):
# Convert string of bip32 path to list of uint32 integers with prime flags warnings.warn('expand_path is deprecated, use tools.parse_path', DeprecationWarning)
# 0/-1/1' -> [0, 0x80000001, 0x80000001] return tools.parse_path(n)
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
@expect(proto.PublicKey) @expect(proto.PublicKey)
def get_public_node(self, n, ecdsa_curve_name=None, show_display=False, coin_name=None): 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") raise RuntimeError("Invalid response, expected EntropyRequest")
external_entropy = self._get_local_entropy() 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)) ret = self.call(proto.EntropyAck(entropy=external_entropy))
self.init_device() self.init_device()
return ret return ret
@ -1079,7 +998,7 @@ class ProtocolMixin(object):
if xprv[0:4] not in ('xprv', 'tprv'): if xprv[0:4] not in ('xprv', 'tprv'):
raise ValueError("Unknown type of xprv") 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") raise ValueError("Invalid length of xprv")
node = proto.HDNodeType() node = proto.HDNodeType()
@ -1088,7 +1007,7 @@ class ProtocolMixin(object):
if data[90:92] != b'00': if data[90:92] != b'00':
raise ValueError("Contain invalid private key") 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:]: if checksum != data[156:]:
raise ValueError("Checksum doesn't match") raise ValueError("Checksum doesn't match")
@ -1128,7 +1047,7 @@ class ProtocolMixin(object):
# TREZORv1 method # TREZORv1 method
if isinstance(resp, proto.Success): if isinstance(resp, proto.Success):
fingerprint = hashlib.sha256(data[256:]).hexdigest() fingerprint = hashlib.sha256(data[256:]).hexdigest()
log("Firmware fingerprint: " + fingerprint) LOG.debug("Firmware fingerprint: " + fingerprint)
resp = self.call(proto.FirmwareUpload(payload=data)) resp = self.call(proto.FirmwareUpload(payload=data))
if isinstance(resp, proto.Success): if isinstance(resp, proto.Success):
return True return True
@ -1204,11 +1123,6 @@ class TrezorClient(ProtocolMixin, TextUIMixin, BaseClient):
super().__init__(transport=transport, *args, **kwargs) super().__init__(transport=transport, *args, **kwargs)
class TrezorClientVerbose(ProtocolMixin, TextUIMixin, VerboseWireMixin, BaseClient): class TrezorClientDebugLink(ProtocolMixin, DebugLinkMixin, BaseClient):
def __init__(self, transport, *args, **kwargs):
super().__init__(transport=transport, *args, **kwargs)
class TrezorClientDebugLink(ProtocolMixin, DebugLinkMixin, VerboseWireMixin, BaseClient):
def __init__(self, transport, *args, **kwargs): def __init__(self, transport, *args, **kwargs):
super().__init__(transport=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"') 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): class DebugLink(object):
def __init__(self, transport, pin_func=pin_info, button_func=button_press): def __init__(self, transport, pin_func=pin_info, button_func=button_press):
self.transport = transport self.transport = transport
@ -45,12 +41,10 @@ class DebugLink(object):
self.transport.session_end() self.transport.session_end()
def _call(self, msg, nowait=False): def _call(self, msg, nowait=False):
print("DEBUGLINK SEND", pprint(msg))
self.transport.write(msg) self.transport.write(msg)
if nowait: if nowait:
return return None
ret = self.transport.read() ret = self.transport.read()
print("DEBUGLINK RECV", pprint(ret))
return ret return ret
def read_pin(self): 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 io import BytesIO
from typing import Any, Optional
_UVARINT_BUFFER = bytearray(1) _UVARINT_BUFFER = bytearray(1)
@ -344,3 +346,58 @@ def dump_message(writer, msg):
else: else:
raise TypeError 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 __future__ import absolute_import
from io import BytesIO from io import BytesIO
import logging
import struct import struct
from typing import Tuple, Type
from . import mapping from . import mapping
from . import protobuf from . import protobuf
from .transport import Transport
REPLEN = 64 REPLEN = 64
LOG = logging.getLogger(__name__)
class ProtocolV1(object):
def session_begin(self, transport): class ProtocolV1:
def session_begin(self, transport: Transport) -> None:
pass pass
def session_end(self, transport): def session_end(self, transport: Transport) -> None:
pass 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() data = BytesIO()
protobuf.dump_message(data, msg) protobuf.dump_message(data, msg)
ser = data.getvalue() ser = data.getvalue()
@ -48,10 +56,10 @@ class ProtocolV1(object):
transport.write_chunk(chunk) transport.write_chunk(chunk)
data = data[63:] data = data[63:]
def read(self, transport): def read(self, transport: Transport) -> protobuf.MessageType:
# Read header with first part of message data # Read header with first part of message data
chunk = transport.read_chunk() 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 # Read the rest of the message
while len(data) < datalen: while len(data) < datalen:
@ -63,21 +71,23 @@ class ProtocolV1(object):
# Parse to protobuf # Parse to protobuf
msg = protobuf.load_message(data, mapping.get_class(msg_type)) msg = protobuf.load_message(data, mapping.get_class(msg_type))
LOG.debug("received message: {}".format(msg.__class__.__name__),
extra={'protobuf': msg})
return msg return msg
def parse_first(self, chunk): def parse_first(self, chunk: bytes) -> Tuple[int, int, bytes]:
if chunk[:3] != b'?##': if chunk[:3] != b'?##':
raise RuntimeError('Unexpected magic characters') raise RuntimeError('Unexpected magic characters')
try: try:
headerlen = struct.calcsize('>HL') 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: except:
raise RuntimeError('Cannot parse header') raise RuntimeError('Cannot parse header')
data = chunk[3 + headerlen:] 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'?': if chunk[:1] != b'?':
raise RuntimeError('Unexpected magic characters') raise RuntimeError('Unexpected magic characters')
return chunk[1:] return chunk[1:]

View File

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

View File

@ -30,14 +30,7 @@ OP_MANAGE_DATA = 10
OP_BUMP_SEQUENCE = 11 OP_BUMP_SEQUENCE = 11
def expand_path_or_default(client, address): DEFAULT_BIP32_PATH = "m/44h/148h/0h"
"""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'")
def address_from_public_key(pk_bytes): def address_from_public_key(pk_bytes):

View File

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

View File

@ -2,6 +2,7 @@ import pytest
from . import common from . import common
from trezorlib.client import TrezorClient from trezorlib.client import TrezorClient
from trezorlib import log
def device_version(): def device_version():
@ -22,6 +23,11 @@ except:
TREZOR_VERSION = None TREZOR_VERSION = None
def pytest_configure(config):
if config.getoption('verbose'):
log.enable_debug_output()
def pytest_addoption(parser): def pytest_addoption(parser):
parser.addini("run_xfail", "List of markers that will run even if marked as xfail", "args", []) 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 # 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/>. # along with this library. If not, see <http://www.gnu.org/licenses/>.
from .common import * from .common import TrezorTest
from trezorlib import messages from trezorlib import messages

View File

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

View File

@ -16,10 +16,13 @@
# You should have received a copy of the GNU Lesser General Public License # 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/>. # along with this library. If not, see <http://www.gnu.org/licenses/>.
from .common import * import pytest
from hashlib import sha256 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 @pytest.mark.skip_t2
@ -30,9 +33,9 @@ class TestCosi(TrezorTest):
digest = sha256(b'this is a message').digest() digest = sha256(b'this is a message').digest()
c0 = self.client.cosi_commit(self.client.expand_path("10018'/0'"), digest) c0 = self.client.cosi_commit(parse_path("10018'/0'"), digest)
c1 = self.client.cosi_commit(self.client.expand_path("10018'/1'"), digest) c1 = self.client.cosi_commit(parse_path("10018'/1'"), digest)
c2 = self.client.cosi_commit(self.client.expand_path("10018'/2'"), digest) c2 = self.client.cosi_commit(parse_path("10018'/2'"), digest)
assert c0.pubkey != c1.pubkey assert c0.pubkey != c1.pubkey
assert c0.pubkey != c2.pubkey assert c0.pubkey != c2.pubkey
@ -44,9 +47,9 @@ class TestCosi(TrezorTest):
digestb = sha256(b'this is a different message').digest() digestb = sha256(b'this is a different message').digest()
c0b = self.client.cosi_commit(self.client.expand_path("10018'/0'"), digestb) c0b = self.client.cosi_commit(parse_path("10018'/0'"), digestb)
c1b = self.client.cosi_commit(self.client.expand_path("10018'/1'"), digestb) c1b = self.client.cosi_commit(parse_path("10018'/1'"), digestb)
c2b = self.client.cosi_commit(self.client.expand_path("10018'/2'"), digestb) c2b = self.client.cosi_commit(parse_path("10018'/2'"), digestb)
assert c0.pubkey == c0b.pubkey assert c0.pubkey == c0b.pubkey
assert c1.pubkey == c1b.pubkey assert c1.pubkey == c1b.pubkey
@ -61,17 +64,36 @@ class TestCosi(TrezorTest):
digest = sha256(b'this is a message').digest() digest = sha256(b'this is a message').digest()
c0 = self.client.cosi_commit(self.client.expand_path("10018'/0'"), digest) c0 = self.client.cosi_commit(parse_path("10018'/0'"), digest)
c1 = self.client.cosi_commit(self.client.expand_path("10018'/1'"), digest) c1 = self.client.cosi_commit(parse_path("10018'/1'"), digest)
c2 = self.client.cosi_commit(self.client.expand_path("10018'/2'"), digest) c2 = self.client.cosi_commit(parse_path("10018'/2'"), digest)
global_pk = ed25519cosi.combine_keys([c0.pubkey, c1.pubkey, c2.pubkey]) global_pk = cosi.combine_keys([c0.pubkey, c1.pubkey, c2.pubkey])
global_R = ed25519cosi.combine_keys([c0.commitment, c1.commitment, c2.commitment]) 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) sig0 = self.client.cosi_sign(parse_path("10018'/0'"), digest, global_R, global_pk)
sig1 = self.client.cosi_sign(self.client.expand_path("10018'/1'"), digest, global_R, global_pk) sig1 = self.client.cosi_sign(parse_path("10018'/1'"), digest, global_R, global_pk)
sig2 = self.client.cosi_sign(self.client.expand_path("10018'/2'"), 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 # 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/>. # 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 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 # 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/>. # along with this library. If not, see <http://www.gnu.org/licenses/>.
import pytest
from .common import * from .common import TrezorTest
import time import time
from trezorlib import messages as proto 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 # 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/>. # 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 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 # 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/>. # 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): class TestMsgCipherkeyvalue(TrezorTest):

View File

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

View File

@ -14,8 +14,10 @@
# #
# You should have received a copy of the GNU Lesser General Public License # 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/>. # 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 @pytest.mark.ethereum

View File

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

View File

@ -16,9 +16,13 @@
# You should have received a copy of the GNU Lesser General Public License # 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/>. # 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 from trezorlib import messages as proto
import trezorlib.ckd_public as bip32
from trezorlib.tools import parse_path
class TestMsgGetaddress(TrezorTest): class TestMsgGetaddress(TrezorTest):
@ -45,14 +49,14 @@ class TestMsgGetaddress(TrezorTest):
def test_bch(self): def test_bch(self):
self.setup_mnemonic_allallall() 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', parse_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', parse_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'/1/0")) == 'bitcoincash:qzc5q87w069lzg7g3gzx0c8dz83mn7l02scej5aluw'
def test_bch_multisig(self): def test_bch_multisig(self):
self.setup_mnemonic_allallall() self.setup_mnemonic_allallall()
xpubs = [] 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) xpubs.append(n.xpub)
def getmultisig(chain, nr, signatures=[b'', b'', b''], xpubs=xpubs): def getmultisig(chain, nr, signatures=[b'', b'', b''], xpubs=xpubs):
@ -62,8 +66,8 @@ class TestMsgGetaddress(TrezorTest):
m=2, m=2,
) )
for nr in range(1, 4): 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', parse_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) + "'/1/0"), show_display=(nr == 1), multisig=getmultisig(1, 0)) == 'bitcoincash:pp6kcpkhua7789g2vyj0qfkcux3yvje7euhyhltn0a'
def test_public_ckd(self): def test_public_ckd(self):
self.setup_mnemonic_nopin_nopassphrase() self.setup_mnemonic_nopin_nopassphrase()

View File

@ -15,23 +15,24 @@
# You should have received a copy of the GNU Lesser General Public License # 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/>. # along with this library. If not, see <http://www.gnu.org/licenses/>.
from .common import * from .common import TrezorTest
import trezorlib.ckd_public as bip32 from ..support import ckd_public as bip32
from trezorlib import messages as proto from trezorlib import messages as proto
from trezorlib.tools import parse_path
class TestMsgGetaddressSegwit(TrezorTest): class TestMsgGetaddressSegwit(TrezorTest):
def test_show_segwit(self): def test_show_segwit(self):
self.setup_mnemonic_allallall() 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", parse_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", parse_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", parse_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("44'/1'/0'/0/0"), False, None, script_type=proto.InputScriptType.SPENDADDRESS) == 'mvbu1Gdy8SUjTenqerxUaZyYjmveZvt33q'
def test_show_multisig_3(self): def test_show_multisig_3(self):
self.setup_mnemonic_allallall() 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( multisig1 = proto.MultisigRedeemScriptType(
pubkeys=list(map(lambda n: proto.HDNodePathType(node=bip32.deserialize(n.xpub), address_n=[2, 0]), nodes)), pubkeys=list(map(lambda n: proto.HDNodePathType(node=bip32.deserialize(n.xpub), address_n=[2, 0]), nodes)),
signatures=[b'', b'', b''], signatures=[b'', b'', b''],
@ -43,4 +44,4 @@ class TestMsgGetaddressSegwit(TrezorTest):
# m=2, # m=2,
# ) # )
for i in [1, 2, 3]: 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 # 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/>. # along with this library. If not, see <http://www.gnu.org/licenses/>.
from .common import * from .common import TrezorTest
import trezorlib.ckd_public as bip32 from ..support import ckd_public as bip32
from trezorlib import messages as proto from trezorlib import messages as proto
from trezorlib.tools import parse_path
class TestMsgGetaddressSegwitNative(TrezorTest): class TestMsgGetaddressSegwitNative(TrezorTest):
def test_show_segwit(self): def test_show_segwit(self):
self.setup_mnemonic_allallall() 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", parse_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", parse_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", parse_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("44'/1'/0'/0/0"), False, None, script_type=proto.InputScriptType.SPENDADDRESS) == 'mvbu1Gdy8SUjTenqerxUaZyYjmveZvt33q'
def test_show_multisig_3(self): def test_show_multisig_3(self):
self.setup_mnemonic_allallall() 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( multisig1 = proto.MultisigRedeemScriptType(
pubkeys=list(map(lambda n: proto.HDNodePathType(node=bip32.deserialize(n.xpub), address_n=[2, 0]), nodes)), pubkeys=list(map(lambda n: proto.HDNodePathType(node=bip32.deserialize(n.xpub), address_n=[2, 0]), nodes)),
signatures=[b'', b'', b''], signatures=[b'', b'', b''],
@ -43,5 +44,5 @@ class TestMsgGetaddressSegwitNative(TrezorTest):
m=2, m=2,
) )
for i in [1, 2, 3]: 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", parse_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/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 # 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/>. # along with this library. If not, see <http://www.gnu.org/licenses/>.
from .common import * from .common import TrezorTest
import trezorlib.ckd_public as bip32 from ..support import ckd_public as bip32
from trezorlib import messages as proto 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 # 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/>. # 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 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 # 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/>. # along with this library. If not, see <http://www.gnu.org/licenses/>.
from __future__ import print_function
import math import math
from .common import * from .common import TrezorTest
import trezorlib.messages as proto import trezorlib.messages as proto

View File

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

View File

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

View File

@ -21,6 +21,7 @@ import pytest
from .common import TrezorTest from .common import TrezorTest
from trezorlib import messages as proto from trezorlib import messages as proto
from trezorlib.tools import parse_path
PUBLIC_KEY = unhexlify('eb56d7bbb5e8ea9269405f7a8527fe126023d1db2c973cfac6f760b60ae27294') 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", "amount": "10000000",
"recipientId": "9971262264659915921L", "recipientId": "9971262264659915921L",
"timestamp": 57525937, "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", "amount": "10000000",
"recipientId": "9971262264659915921L", "recipientId": "9971262264659915921L",
"timestamp": 57525937, "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", "amount": "0",
"timestamp": 57525937, "timestamp": 57525937,
"type": 1, "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", "amount": "0",
"timestamp": 57525937, "timestamp": 57525937,
"type": 2, "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", "amount": "0",
"timestamp": 57525937, "timestamp": 57525937,
"type": 3, "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", "amount": "0",
"timestamp": 57525937, "timestamp": 57525937,
"type": 4, "type": 4,

View File

@ -15,8 +15,9 @@
# #
# You should have received a copy of the GNU Lesser General Public License # 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/>. # 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 @pytest.mark.skip_t2

View File

@ -15,8 +15,9 @@
# #
# You should have received a copy of the GNU Lesser General Public License # 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/>. # 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 @pytest.mark.skip_t2

View File

@ -15,7 +15,10 @@
# You should have received a copy of the GNU Lesser General Public License # 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/>. # 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 @pytest.mark.nem
@ -24,5 +27,5 @@ class TestMsgNEMGetaddress(TrezorTest):
def test_nem_getaddress(self): def test_nem_getaddress(self):
self.setup_mnemonic_nopin_nopassphrase() 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(parse_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'"), 0x98) == "TB3JCHVARQNGDS3UVGAJPTFE22UQFGMCQHSBNBMF"

View File

@ -15,8 +15,12 @@
# You should have received a copy of the GNU Lesser General Public License # 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/>. # 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 import nem
from trezorlib.tools import parse_path
# assertion data from T1 # assertion data from T1
@ -27,7 +31,7 @@ class TestMsgNEMSignTxMosaics(TrezorTest):
def test_nem_signtx_mosaic_supply_change(self): def test_nem_signtx_mosaic_supply_change(self):
self.setup_mnemonic_nopin_nopassphrase() 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, "timeStamp": 74649215,
"fee": 2000000, "fee": 2000000,
"type": nem.TYPE_MOSAIC_SUPPLY_CHANGE, "type": nem.TYPE_MOSAIC_SUPPLY_CHANGE,
@ -51,7 +55,7 @@ class TestMsgNEMSignTxMosaics(TrezorTest):
def test_nem_signtx_mosaic_creation(self): def test_nem_signtx_mosaic_creation(self):
self.setup_mnemonic_nopin_nopassphrase() 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, "timeStamp": 74649215,
"fee": 2000000, "fee": 2000000,
"type": nem.TYPE_MOSAIC_CREATION, "type": nem.TYPE_MOSAIC_CREATION,
@ -78,7 +82,7 @@ class TestMsgNEMSignTxMosaics(TrezorTest):
def test_nem_signtx_mosaic_creation_properties(self): def test_nem_signtx_mosaic_creation_properties(self):
self.setup_mnemonic_nopin_nopassphrase() 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, "timeStamp": 74649215,
"fee": 2000000, "fee": 2000000,
"type": nem.TYPE_MOSAIC_CREATION, "type": nem.TYPE_MOSAIC_CREATION,
@ -122,7 +126,7 @@ class TestMsgNEMSignTxMosaics(TrezorTest):
def test_nem_signtx_mosaic_creation_levy(self): def test_nem_signtx_mosaic_creation_levy(self):
self.setup_mnemonic_nopin_nopassphrase() 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, "timeStamp": 74649215,
"fee": 2000000, "fee": 2000000,
"type": nem.TYPE_MOSAIC_CREATION, "type": nem.TYPE_MOSAIC_CREATION,

View File

@ -15,11 +15,14 @@
# You should have received a copy of the GNU Lesser General Public License # 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/>. # 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 messages as proto
from trezorlib import nem from trezorlib import nem
import time from trezorlib.tools import parse_path
# assertion data from T1 # assertion data from T1
@ -32,7 +35,7 @@ class TestMsgNEMSignTxMosaics(TrezorTest):
self.setup_mnemonic_nopin_nopassphrase() self.setup_mnemonic_nopin_nopassphrase()
with self.client: 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, "timeStamp": 74649215,
"fee": 2000000, "fee": 2000000,
"type": nem.TYPE_MOSAIC_SUPPLY_CHANGE, "type": nem.TYPE_MOSAIC_SUPPLY_CHANGE,
@ -182,7 +185,7 @@ class TestMsgNEMSignTxMosaics(TrezorTest):
assert hexlify(tx.signature) == b'b87aac1ddf146d35e6a7f3451f57e2fe504ac559031e010a51261257c37bd50fcfa7b2939dd7a3203b54c4807d458475182f5d3dc135ec0d1d4a9cd42159fd0a' assert hexlify(tx.signature) == b'b87aac1ddf146d35e6a7f3451f57e2fe504ac559031e010a51261257c37bd50fcfa7b2939dd7a3203b54c4807d458475182f5d3dc135ec0d1d4a9cd42159fd0a'
def _nem_sign(self, num_of_swipes, test_suite): 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) n = self.client._convert_prime(n)
msg = nem.create_sign_tx(test_suite) msg = nem.create_sign_tx(test_suite)
assert msg.transaction is not None 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 # 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/>. # 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 from trezorlib import nem
@ -28,7 +32,7 @@ class TestMsgNEMSignTxMultisig(TrezorTest):
def test_nem_signtx_aggregate_modification(self): def test_nem_signtx_aggregate_modification(self):
self.setup_mnemonic_nopin_nopassphrase() 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, "timeStamp": 74649215,
"fee": 2000000, "fee": 2000000,
"type": nem.TYPE_AGGREGATE_MODIFICATION, "type": nem.TYPE_AGGREGATE_MODIFICATION,
@ -52,7 +56,7 @@ class TestMsgNEMSignTxMultisig(TrezorTest):
def test_nem_signtx_multisig(self): def test_nem_signtx_multisig(self):
self.setup_mnemonic_nopin_nopassphrase() 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, "timeStamp": 1,
"fee": 10000, "fee": 10000,
"type": nem.TYPE_MULTISIG, "type": nem.TYPE_MULTISIG,
@ -77,7 +81,7 @@ class TestMsgNEMSignTxMultisig(TrezorTest):
assert hexlify(tx.data) == b'04100000010000980100000020000000edfd32f6e760648c032f9acb4b30d514265f6a5b5f8a7154f2618922b40620841027000000000000ff5f74049900000001010000010000980200000020000000c5f54ba980fcbb657dbaaa42700539b207873e134d2375efeab5f1ab52f87844983a000000000000320901002800000054414c49434532474d4133344358484437584c4a513533364e4d35554e4b5148544f524e4e54324a80841e000000000025000000010000001d000000746573745f6e656d5f7472616e73616374696f6e5f7472616e73666572' assert hexlify(tx.data) == b'04100000010000980100000020000000edfd32f6e760648c032f9acb4b30d514265f6a5b5f8a7154f2618922b40620841027000000000000ff5f74049900000001010000010000980200000020000000c5f54ba980fcbb657dbaaa42700539b207873e134d2375efeab5f1ab52f87844983a000000000000320901002800000054414c49434532474d4133344358484437584c4a513533364e4d35554e4b5148544f524e4e54324a80841e000000000025000000010000001d000000746573745f6e656d5f7472616e73616374696f6e5f7472616e73666572'
assert hexlify(tx.signature) == b'0cab2fddf2f02b5d7201675b9a71869292fe25ed33a366c7d2cbea7676fed491faaa03310079b7e17884b6ba2e3ea21c4f728d1cca8f190b8288207f6514820a' 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, "timeStamp": 74649215,
"fee": 150, "fee": 150,
"type": nem.TYPE_MULTISIG, "type": nem.TYPE_MULTISIG,
@ -105,7 +109,7 @@ class TestMsgNEMSignTxMultisig(TrezorTest):
def test_nem_signtx_multisig_signer(self): def test_nem_signtx_multisig_signer(self):
self.setup_mnemonic_nopin_nopassphrase() 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, "timeStamp": 333,
"fee": 200, "fee": 200,
"type": nem.TYPE_MULTISIG_SIGNATURE, "type": nem.TYPE_MULTISIG_SIGNATURE,
@ -130,7 +134,7 @@ class TestMsgNEMSignTxMultisig(TrezorTest):
assert hexlify(tx.data) == b'02100000010000984d01000020000000edfd32f6e760648c032f9acb4b30d514265f6a5b5f8a7154f2618922b4062084c800000000000000bc010000240000002000000087923cd4805f3babe6b5af9cbb2b08be4458e39531618aed73c911f160c8e38528000000544444324354364c514c49595135364b49584933454e544d36454b3344343450354b5a50464d4b32' assert hexlify(tx.data) == b'02100000010000984d01000020000000edfd32f6e760648c032f9acb4b30d514265f6a5b5f8a7154f2618922b4062084c800000000000000bc010000240000002000000087923cd4805f3babe6b5af9cbb2b08be4458e39531618aed73c911f160c8e38528000000544444324354364c514c49595135364b49584933454e544d36454b3344343450354b5a50464d4b32'
assert hexlify(tx.signature) == b'286358a16ae545bff798feab93a713440c7c2f236d52ac0e995669d17a1915b0903667c97fa04418eccb42333cba95b19bccc8ac1faa8224dcfaeb41890ae807' 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, "timeStamp": 900000,
"fee": 200000, "fee": 200000,
"type": nem.TYPE_MULTISIG_SIGNATURE, "type": nem.TYPE_MULTISIG_SIGNATURE,

View File

@ -15,9 +15,13 @@
# You should have received a copy of the GNU Lesser General Public License # 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/>. # 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 import nem
from trezorlib.tools import parse_path
# assertion data from T1 # assertion data from T1
@ -29,7 +33,7 @@ class TestMsgNEMSignTxOther(TrezorTest):
self.setup_mnemonic_nopin_nopassphrase() self.setup_mnemonic_nopin_nopassphrase()
with self.client: 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, "timeStamp": 12349215,
"fee": 9900, "fee": 9900,
"type": nem.TYPE_IMPORTANCE_TRANSFER, "type": nem.TYPE_IMPORTANCE_TRANSFER,
@ -50,7 +54,7 @@ class TestMsgNEMSignTxOther(TrezorTest):
self.setup_mnemonic_nopin_nopassphrase() 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, "timeStamp": 74649215,
"fee": 2000000, "fee": 2000000,
"type": nem.TYPE_PROVISION_NAMESPACE, "type": nem.TYPE_PROVISION_NAMESPACE,

View File

@ -15,10 +15,14 @@
# You should have received a copy of the GNU Lesser General Public License # 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/>. # 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 messages as proto
from trezorlib import nem from trezorlib import nem
from trezorlib.tools import parse_path
# assertion data from T1 # assertion data from T1
@ -44,7 +48,7 @@ class TestMsgNEMSignTx(TrezorTest):
proto.NEMSignedTx(), 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, "timeStamp": 74649215,
"amount": 2000000, "amount": 2000000,
"fee": 2000000, "fee": 2000000,
@ -75,7 +79,7 @@ class TestMsgNEMSignTx(TrezorTest):
proto.NEMSignedTx(), 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, "timeStamp": 74649215,
"amount": 2000000, "amount": 2000000,
"fee": 2000000, "fee": 2000000,
@ -101,7 +105,7 @@ class TestMsgNEMSignTx(TrezorTest):
def test_nem_signtx_xem_as_mosaic(self): def test_nem_signtx_xem_as_mosaic(self):
self.setup_mnemonic_nopin_nopassphrase() 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, "timeStamp": 76809215,
"amount": 5000000, "amount": 5000000,
"fee": 1000000, "fee": 1000000,
@ -129,7 +133,7 @@ class TestMsgNEMSignTx(TrezorTest):
def test_nem_signtx_unknown_mosaic(self): def test_nem_signtx_unknown_mosaic(self):
self.setup_mnemonic_nopin_nopassphrase() 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, "timeStamp": 76809215,
"amount": 2000000, "amount": 2000000,
"fee": 1000000, "fee": 1000000,
@ -158,7 +162,7 @@ class TestMsgNEMSignTx(TrezorTest):
self.setup_mnemonic_nopin_nopassphrase() 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, "timeStamp": 76809215,
"amount": 3000000, "amount": 3000000,
"fee": 1000000, "fee": 1000000,
@ -187,7 +191,7 @@ class TestMsgNEMSignTx(TrezorTest):
self.setup_mnemonic_nopin_nopassphrase() 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, "timeStamp": 76809215,
"amount": 2000000, "amount": 2000000,
"fee": 1000000, "fee": 1000000,
@ -215,7 +219,7 @@ class TestMsgNEMSignTx(TrezorTest):
def test_nem_signtx_multiple_mosaics(self): def test_nem_signtx_multiple_mosaics(self):
self.setup_mnemonic_nopin_nopassphrase() 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, "timeStamp": 76809215,
"amount": 2000000, "amount": 2000000,
"fee": 1000000, "fee": 1000000,

View File

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

View File

@ -15,8 +15,9 @@
# #
# You should have received a copy of the GNU Lesser General Public License # 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/>. # 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 trezorlib import messages as proto
from mnemonic import Mnemonic from mnemonic import Mnemonic

View File

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

View File

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

View File

@ -15,8 +15,9 @@
# #
# You should have received a copy of the GNU Lesser General Public License # 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/>. # 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 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 # 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/>. # 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 from trezorlib import messages as proto

View File

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

View File

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

View File

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

View File

@ -15,10 +15,14 @@
# You should have received a copy of the GNU Lesser General Public License # 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/>. # 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 coins
from trezorlib import messages as proto from trezorlib import messages as proto
from trezorlib.tools import parse_path
TxApiDecredTestnet = coins.tx_api['Decred Testnet'] TxApiDecredTestnet = coins.tx_api['Decred Testnet']
@ -41,7 +45,7 @@ class TestMsgSigntxDecred(TrezorTest):
inp1 = proto.TxInputType( inp1 = proto.TxInputType(
# TscqTv1he8MZrV321SfRghw7LFBCJDKB3oz # 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_hash=TXHASH_e16248,
prev_index=1, prev_index=1,
script_type=proto.InputScriptType.SPENDADDRESS, script_type=proto.InputScriptType.SPENDADDRESS,
@ -80,7 +84,7 @@ class TestMsgSigntxDecred(TrezorTest):
inp1 = proto.TxInputType( inp1 = proto.TxInputType(
# TscqTv1he8MZrV321SfRghw7LFBCJDKB3oz # 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_hash=TXHASH_5e6e35,
prev_index=0, prev_index=0,
script_type=proto.InputScriptType.SPENDADDRESS, script_type=proto.InputScriptType.SPENDADDRESS,
@ -89,7 +93,7 @@ class TestMsgSigntxDecred(TrezorTest):
inp2 = proto.TxInputType( inp2 = proto.TxInputType(
# TscqTv1he8MZrV321SfRghw7LFBCJDKB3oz # 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_hash=TXHASH_ccf95b,
prev_index=1, prev_index=1,
script_type=proto.InputScriptType.SPENDADDRESS, script_type=proto.InputScriptType.SPENDADDRESS,
@ -98,7 +102,7 @@ class TestMsgSigntxDecred(TrezorTest):
inp3 = proto.TxInputType( inp3 = proto.TxInputType(
# Tskt39YEvzoJ5KBDH4f1auNzG3jViVjZ2RV # 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_hash=TXHASH_f395ef,
prev_index=0, prev_index=0,
script_type=proto.InputScriptType.SPENDADDRESS, script_type=proto.InputScriptType.SPENDADDRESS,
@ -114,7 +118,7 @@ class TestMsgSigntxDecred(TrezorTest):
out2 = proto.TxOutputType( out2 = proto.TxOutputType(
# TsaSFRwfN9muW5F6ZX36iSksc9hruiC5F97 # 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, amount=100000000,
script_type=proto.OutputScriptType.PAYTOADDRESS, script_type=proto.OutputScriptType.PAYTOADDRESS,
decred_script_version=0, decred_script_version=0,
@ -154,7 +158,7 @@ class TestMsgSigntxDecred(TrezorTest):
self.setup_mnemonic_allallall() self.setup_mnemonic_allallall()
self.client.set_tx_api(TxApiDecredTestnet) 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] nodes = [self.client.get_public_node(address_n, coin_name="Decred Testnet").node for address_n in paths]
signatures = [ signatures = [
@ -163,7 +167,7 @@ class TestMsgSigntxDecred(TrezorTest):
] ]
def create_multisig(index, address, signatures=None): def create_multisig(index, address, signatures=None):
address_n = self.client.expand_path(address) address_n = parse_path(address)
multisig = proto.MultisigRedeemScriptType( multisig = proto.MultisigRedeemScriptType(
pubkeys=[proto.HDNodePathType(node=node, address_n=address_n) for node in nodes], pubkeys=[proto.HDNodePathType(node=node, address_n=address_n) for node in nodes],
signatures=signatures, signatures=signatures,

View File

@ -18,12 +18,14 @@
from binascii import hexlify, unhexlify from binascii import hexlify, unhexlify
import pytest import pytest
from ..support.ckd_public import deserialize
from .conftest import TREZOR_VERSION from .conftest import TREZOR_VERSION
from .common import TrezorTest from .common import TrezorTest
from trezorlib import coins from trezorlib import coins
from trezorlib import messages as proto from trezorlib import messages as proto
from trezorlib.ckd_public import deserialize
from trezorlib.client import CallException from trezorlib.client import CallException
from trezorlib.tools import parse_path
TxApiTestnet = coins.tx_api["Testnet"] TxApiTestnet = coins.tx_api["Testnet"]
@ -34,7 +36,7 @@ class TestMsgSigntxSegwit(TrezorTest):
self.setup_mnemonic_allallall() self.setup_mnemonic_allallall()
self.client.set_tx_api(TxApiTestnet) self.client.set_tx_api(TxApiTestnet)
inp1 = proto.TxInputType( inp1 = proto.TxInputType(
address_n=self.client.expand_path("49'/1'/0'/1/0"), address_n=parse_path("49'/1'/0'/1/0"),
# 2N1LGaGg836mqSQqiuUBLfcyGBhyZbremDX # 2N1LGaGg836mqSQqiuUBLfcyGBhyZbremDX
amount=123456789, amount=123456789,
prev_hash=unhexlify('20912f98ea3ed849042efed0fdac8cb4fc301961c5988cba56902d8ffb61c337'), prev_hash=unhexlify('20912f98ea3ed849042efed0fdac8cb4fc301961c5988cba56902d8ffb61c337'),
@ -73,7 +75,7 @@ class TestMsgSigntxSegwit(TrezorTest):
self.setup_mnemonic_allallall() self.setup_mnemonic_allallall()
self.client.set_tx_api(TxApiTestnet) self.client.set_tx_api(TxApiTestnet)
inp1 = proto.TxInputType( inp1 = proto.TxInputType(
address_n=self.client.expand_path("49'/1'/0'/1/0"), address_n=parse_path("49'/1'/0'/1/0"),
# 2N1LGaGg836mqSQqiuUBLfcyGBhyZbremDX # 2N1LGaGg836mqSQqiuUBLfcyGBhyZbremDX
amount=123456789, amount=123456789,
prev_hash=unhexlify('20912f98ea3ed849042efed0fdac8cb4fc301961c5988cba56902d8ffb61c337'), prev_hash=unhexlify('20912f98ea3ed849042efed0fdac8cb4fc301961c5988cba56902d8ffb61c337'),
@ -86,7 +88,7 @@ class TestMsgSigntxSegwit(TrezorTest):
script_type=proto.OutputScriptType.PAYTOADDRESS, script_type=proto.OutputScriptType.PAYTOADDRESS,
) )
out2 = proto.TxOutputType( 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, script_type=proto.OutputScriptType.PAYTOP2SHWITNESS,
amount=123456789 - 11000 - 12300000, amount=123456789 - 11000 - 12300000,
) )
@ -110,7 +112,7 @@ class TestMsgSigntxSegwit(TrezorTest):
def test_send_multisig_1(self): def test_send_multisig_1(self):
self.setup_mnemonic_allallall() self.setup_mnemonic_allallall()
self.client.set_tx_api(TxApiTestnet) 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( multisig = proto.MultisigRedeemScriptType(
pubkeys=list(map(lambda n: proto.HDNodePathType(node=deserialize(n.xpub), address_n=[2, 0]), nodes)), pubkeys=list(map(lambda n: proto.HDNodePathType(node=deserialize(n.xpub), address_n=[2, 0]), nodes)),
signatures=[b'', b'', b''], signatures=[b'', b'', b''],
@ -118,7 +120,7 @@ class TestMsgSigntxSegwit(TrezorTest):
) )
inp1 = proto.TxInputType( 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_hash=unhexlify('9c31922be756c06d02167656465c8dc83bb553bf386a3f478ae65b5c021002be'),
prev_index=1, prev_index=1,
script_type=proto.InputScriptType.SPENDP2SHWITNESS, script_type=proto.InputScriptType.SPENDP2SHWITNESS,
@ -167,7 +169,7 @@ class TestMsgSigntxSegwit(TrezorTest):
self.setup_mnemonic_allallall() self.setup_mnemonic_allallall()
self.client.set_tx_api(TxApiTestnet) self.client.set_tx_api(TxApiTestnet)
inp1 = proto.TxInputType( inp1 = proto.TxInputType(
address_n=self.client.expand_path("49'/1'/0'/1/0"), address_n=parse_path("49'/1'/0'/1/0"),
# 2N1LGaGg836mqSQqiuUBLfcyGBhyZbremDX # 2N1LGaGg836mqSQqiuUBLfcyGBhyZbremDX
amount=123456789, amount=123456789,
prev_hash=unhexlify('20912f98ea3ed849042efed0fdac8cb4fc301961c5988cba56902d8ffb61c337'), prev_hash=unhexlify('20912f98ea3ed849042efed0fdac8cb4fc301961c5988cba56902d8ffb61c337'),
@ -180,7 +182,7 @@ class TestMsgSigntxSegwit(TrezorTest):
script_type=proto.OutputScriptType.PAYTOADDRESS, script_type=proto.OutputScriptType.PAYTOADDRESS,
) )
out2 = proto.TxOutputType( 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, script_type=proto.OutputScriptType.PAYTOP2SHWITNESS,
amount=123456789 - 11000 - 12300000, amount=123456789 - 11000 - 12300000,
) )
@ -189,7 +191,6 @@ class TestMsgSigntxSegwit(TrezorTest):
run_attack = True run_attack = True
def attack_processor(req, msg): def attack_processor(req, msg):
import sys
global run_attack global run_attack
if req.details.tx_hash is not None: 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 # 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/>. # 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 coins
from trezorlib import messages as proto from trezorlib import messages as proto
from trezorlib.ckd_public import deserialize from trezorlib.tools import parse_path
TxApiTestnet = coins.tx_api['Testnet'] TxApiTestnet = coins.tx_api['Testnet']
@ -30,7 +32,7 @@ class TestMsgSigntxSegwitNative(TrezorTest):
self.setup_mnemonic_allallall() self.setup_mnemonic_allallall()
self.client.set_tx_api(TxApiTestnet) self.client.set_tx_api(TxApiTestnet)
inp1 = proto.TxInputType( inp1 = proto.TxInputType(
address_n=self.client.expand_path("49'/1'/0'/1/0"), address_n=parse_path("49'/1'/0'/1/0"),
# 2N1LGaGg836mqSQqiuUBLfcyGBhyZbremDX # 2N1LGaGg836mqSQqiuUBLfcyGBhyZbremDX
amount=123456789, amount=123456789,
prev_hash=unhexlify('20912f98ea3ed849042efed0fdac8cb4fc301961c5988cba56902d8ffb61c337'), prev_hash=unhexlify('20912f98ea3ed849042efed0fdac8cb4fc301961c5988cba56902d8ffb61c337'),
@ -69,7 +71,7 @@ class TestMsgSigntxSegwitNative(TrezorTest):
self.setup_mnemonic_allallall() self.setup_mnemonic_allallall()
self.client.set_tx_api(TxApiTestnet) self.client.set_tx_api(TxApiTestnet)
inp1 = proto.TxInputType( inp1 = proto.TxInputType(
address_n=self.client.expand_path("49'/1'/0'/1/0"), address_n=parse_path("49'/1'/0'/1/0"),
# 2N1LGaGg836mqSQqiuUBLfcyGBhyZbremDX # 2N1LGaGg836mqSQqiuUBLfcyGBhyZbremDX
amount=123456789, amount=123456789,
prev_hash=unhexlify('20912f98ea3ed849042efed0fdac8cb4fc301961c5988cba56902d8ffb61c337'), prev_hash=unhexlify('20912f98ea3ed849042efed0fdac8cb4fc301961c5988cba56902d8ffb61c337'),
@ -82,7 +84,7 @@ class TestMsgSigntxSegwitNative(TrezorTest):
script_type=proto.OutputScriptType.PAYTOADDRESS, script_type=proto.OutputScriptType.PAYTOADDRESS,
) )
out2 = proto.TxOutputType( 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, script_type=proto.OutputScriptType.PAYTOP2SHWITNESS,
amount=123456789 - 11000 - 12300000, amount=123456789 - 11000 - 12300000,
) )
@ -107,7 +109,7 @@ class TestMsgSigntxSegwitNative(TrezorTest):
self.setup_mnemonic_allallall() self.setup_mnemonic_allallall()
self.client.set_tx_api(TxApiTestnet) self.client.set_tx_api(TxApiTestnet)
inp1 = proto.TxInputType( inp1 = proto.TxInputType(
address_n=self.client.expand_path("49'/1'/0'/0/0"), address_n=parse_path("49'/1'/0'/0/0"),
# tb1qqzv60m9ajw8drqulta4ld4gfx0rdh82un5s65s # tb1qqzv60m9ajw8drqulta4ld4gfx0rdh82un5s65s
amount=12300000, amount=12300000,
prev_hash=unhexlify('09144602765ce3dd8f4329445b20e3684e948709c5cdcaf12da3bb079c99448a'), prev_hash=unhexlify('09144602765ce3dd8f4329445b20e3684e948709c5cdcaf12da3bb079c99448a'),
@ -146,7 +148,7 @@ class TestMsgSigntxSegwitNative(TrezorTest):
self.setup_mnemonic_allallall() self.setup_mnemonic_allallall()
self.client.set_tx_api(TxApiTestnet) self.client.set_tx_api(TxApiTestnet)
inp1 = proto.TxInputType( inp1 = proto.TxInputType(
address_n=self.client.expand_path("49'/1'/0'/0/0"), address_n=parse_path("49'/1'/0'/0/0"),
# tb1qqzv60m9ajw8drqulta4ld4gfx0rdh82un5s65s # tb1qqzv60m9ajw8drqulta4ld4gfx0rdh82un5s65s
amount=12300000, amount=12300000,
prev_hash=unhexlify('09144602765ce3dd8f4329445b20e3684e948709c5cdcaf12da3bb079c99448a'), prev_hash=unhexlify('09144602765ce3dd8f4329445b20e3684e948709c5cdcaf12da3bb079c99448a'),
@ -159,7 +161,7 @@ class TestMsgSigntxSegwitNative(TrezorTest):
script_type=proto.OutputScriptType.PAYTOADDRESS, script_type=proto.OutputScriptType.PAYTOADDRESS,
) )
out2 = proto.TxOutputType( 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, script_type=proto.OutputScriptType.PAYTOWITNESS,
amount=12300000 - 11000 - 5000000, amount=12300000 - 11000 - 5000000,
) )
@ -184,7 +186,7 @@ class TestMsgSigntxSegwitNative(TrezorTest):
self.setup_mnemonic_allallall() self.setup_mnemonic_allallall()
self.client.set_tx_api(TxApiTestnet) self.client.set_tx_api(TxApiTestnet)
inp1 = proto.TxInputType( inp1 = proto.TxInputType(
address_n=self.client.expand_path("49'/1'/0'/1/0"), address_n=parse_path("49'/1'/0'/1/0"),
# 2N1LGaGg836mqSQqiuUBLfcyGBhyZbremDX # 2N1LGaGg836mqSQqiuUBLfcyGBhyZbremDX
amount=111145789, amount=111145789,
prev_hash=unhexlify('09144602765ce3dd8f4329445b20e3684e948709c5cdcaf12da3bb079c99448a'), prev_hash=unhexlify('09144602765ce3dd8f4329445b20e3684e948709c5cdcaf12da3bb079c99448a'),
@ -192,7 +194,7 @@ class TestMsgSigntxSegwitNative(TrezorTest):
script_type=proto.InputScriptType.SPENDP2SHWITNESS, script_type=proto.InputScriptType.SPENDP2SHWITNESS,
) )
inp2 = proto.TxInputType( inp2 = proto.TxInputType(
address_n=self.client.expand_path("49'/1'/0'/1/0"), address_n=parse_path("49'/1'/0'/1/0"),
# tb1q694ccp5qcc0udmfwgp692u2s2hjpq5h407urtu # tb1q694ccp5qcc0udmfwgp692u2s2hjpq5h407urtu
amount=7289000, amount=7289000,
prev_hash=unhexlify('65b811d3eca0fe6915d9f2d77c86c5a7f19bf66b1b1253c2c51cb4ae5f0c017b'), prev_hash=unhexlify('65b811d3eca0fe6915d9f2d77c86c5a7f19bf66b1b1253c2c51cb4ae5f0c017b'),
@ -205,7 +207,7 @@ class TestMsgSigntxSegwitNative(TrezorTest):
script_type=proto.OutputScriptType.PAYTOADDRESS, script_type=proto.OutputScriptType.PAYTOADDRESS,
) )
out2 = proto.TxOutputType( 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, # script_type=proto.OutputScriptType.PAYTOP2SHWITNESS,
address='2N6UeBoqYEEnybg4cReFYDammpsyDw8R2Mc', address='2N6UeBoqYEEnybg4cReFYDammpsyDw8R2Mc',
script_type=proto.OutputScriptType.PAYTOADDRESS, script_type=proto.OutputScriptType.PAYTOADDRESS,
@ -245,7 +247,7 @@ class TestMsgSigntxSegwitNative(TrezorTest):
def test_send_multisig_1(self): def test_send_multisig_1(self):
self.setup_mnemonic_allallall() self.setup_mnemonic_allallall()
self.client.set_tx_api(TxApiTestnet) 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( multisig = proto.MultisigRedeemScriptType(
pubkeys=list(map(lambda n: proto.HDNodePathType(node=deserialize(n.xpub), address_n=[2, 0]), nodes)), pubkeys=list(map(lambda n: proto.HDNodePathType(node=deserialize(n.xpub), address_n=[2, 0]), nodes)),
signatures=[b'', b'', b''], signatures=[b'', b'', b''],
@ -253,7 +255,7 @@ class TestMsgSigntxSegwitNative(TrezorTest):
) )
inp1 = proto.TxInputType( 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_hash=unhexlify('9c31922be756c06d02167656465c8dc83bb553bf386a3f478ae65b5c021002be'),
prev_index=1, prev_index=1,
script_type=proto.InputScriptType.SPENDP2SHWITNESS, script_type=proto.InputScriptType.SPENDP2SHWITNESS,
@ -301,7 +303,7 @@ class TestMsgSigntxSegwitNative(TrezorTest):
def test_send_multisig_2(self): def test_send_multisig_2(self):
self.setup_mnemonic_allallall() self.setup_mnemonic_allallall()
self.client.set_tx_api(TxApiTestnet) 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( multisig = proto.MultisigRedeemScriptType(
pubkeys=list(map(lambda n: proto.HDNodePathType(node=deserialize(n.xpub), address_n=[2, 1]), nodes)), pubkeys=list(map(lambda n: proto.HDNodePathType(node=deserialize(n.xpub), address_n=[2, 1]), nodes)),
signatures=[b'', b'', b''], signatures=[b'', b'', b''],
@ -309,7 +311,7 @@ class TestMsgSigntxSegwitNative(TrezorTest):
) )
inp1 = proto.TxInputType( 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_hash=unhexlify('f41cbedd8becee05a830f418d13aa665125464547db5c7a6cd28f21639fe1228'),
prev_index=0, prev_index=0,
script_type=proto.InputScriptType.SPENDWITNESS, script_type=proto.InputScriptType.SPENDWITNESS,
@ -357,7 +359,7 @@ class TestMsgSigntxSegwitNative(TrezorTest):
def test_send_multisig_3_change(self): def test_send_multisig_3_change(self):
self.setup_mnemonic_allallall() self.setup_mnemonic_allallall()
self.client.set_tx_api(TxApiTestnet) 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( multisig = proto.MultisigRedeemScriptType(
pubkeys=list(map(lambda n: proto.HDNodePathType(node=deserialize(n.xpub), address_n=[2, 0]), nodes)), pubkeys=list(map(lambda n: proto.HDNodePathType(node=deserialize(n.xpub), address_n=[2, 0]), nodes)),
signatures=[b'', b'', b''], signatures=[b'', b'', b''],
@ -370,7 +372,7 @@ class TestMsgSigntxSegwitNative(TrezorTest):
) )
inp1 = proto.TxInputType( 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_hash=unhexlify('c9348040bbc2024e12dcb4a0b4806b0398646b91acf314da028c3f03dd0179fc'),
prev_index=0, prev_index=0,
script_type=proto.InputScriptType.SPENDWITNESS, script_type=proto.InputScriptType.SPENDWITNESS,
@ -379,7 +381,7 @@ class TestMsgSigntxSegwitNative(TrezorTest):
) )
out1 = proto.TxOutputType( 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, amount=1603000,
multisig=multisig2, multisig=multisig2,
script_type=proto.OutputScriptType.PAYTOP2SHWITNESS script_type=proto.OutputScriptType.PAYTOP2SHWITNESS
@ -418,7 +420,7 @@ class TestMsgSigntxSegwitNative(TrezorTest):
def test_send_multisig_4_change(self): def test_send_multisig_4_change(self):
self.setup_mnemonic_allallall() self.setup_mnemonic_allallall()
self.client.set_tx_api(TxApiTestnet) 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( multisig = proto.MultisigRedeemScriptType(
pubkeys=list(map(lambda n: proto.HDNodePathType(node=deserialize(n.xpub), address_n=[1, 1]), nodes)), pubkeys=list(map(lambda n: proto.HDNodePathType(node=deserialize(n.xpub), address_n=[1, 1]), nodes)),
signatures=[b'', b'', b''], signatures=[b'', b'', b''],
@ -431,7 +433,7 @@ class TestMsgSigntxSegwitNative(TrezorTest):
) )
inp1 = proto.TxInputType( 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_hash=unhexlify('31bc1c88ce6ae337a6b3057a16d5bad0b561ad1dfc047d0a7fbb8814668f91e5'),
prev_index=0, prev_index=0,
script_type=proto.InputScriptType.SPENDP2SHWITNESS, script_type=proto.InputScriptType.SPENDP2SHWITNESS,
@ -440,7 +442,7 @@ class TestMsgSigntxSegwitNative(TrezorTest):
) )
out1 = proto.TxOutputType( 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, amount=1602000,
multisig=multisig2, multisig=multisig2,
script_type=proto.OutputScriptType.PAYTOWITNESS script_type=proto.OutputScriptType.PAYTOWITNESS

View File

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

View File

@ -12,11 +12,12 @@
# #
# You should have received a copy of the GNU Lesser General Public License # 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/>. # along with this library. If not, see <http://www.gnu.org/licenses/>.
import pytest
from .common import TrezorTest from .common import TrezorTest
from .conftest import TREZOR_VERSION from .conftest import TREZOR_VERSION
from trezorlib import stellar from trezorlib import stellar
import pytest from trezorlib.tools import parse_path
@pytest.mark.stellar @pytest.mark.stellar
@ -27,5 +28,5 @@ class TestMsgStellarGetPublicKey(TrezorTest):
self.setup_mnemonic_nopin_nopassphrase() self.setup_mnemonic_nopin_nopassphrase()
# GAK5MSF74TJW6GLM7NLTL76YZJKM2S4CGP3UH4REJHPHZ4YBZW2GSBPW # 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' 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 .conftest import TREZOR_VERSION
from binascii import hexlify, unhexlify from binascii import hexlify, unhexlify
from trezorlib import messages as proto from trezorlib import messages as proto
from trezorlib import stellar
from trezorlib.tools import parse_path
import pytest import pytest
@ -29,14 +31,12 @@ import pytest
@pytest.mark.xfail(TREZOR_VERSION == 2, reason="T2 support is not yet finished") @pytest.mark.xfail(TREZOR_VERSION == 2, reason="T2 support is not yet finished")
class TestMsgStellarSignTransaction(TrezorTest): class TestMsgStellarSignTransaction(TrezorTest):
ADDRESS_N = parse_path(stellar.DEFAULT_BIP32_PATH)
def get_network_passphrase(self): def get_network_passphrase(self):
"""Use the same passphrase as the network that generated the test XDR/signatures""" """Use the same passphrase as the network that generated the test XDR/signatures"""
return "Integration Test Network ; zulucrypto" 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): def test_sign_tx_bump_sequence_op(self):
self.setup_mnemonic_nopin_nopassphrase() self.setup_mnemonic_nopin_nopassphrase()
@ -44,7 +44,7 @@ class TestMsgStellarSignTransaction(TrezorTest):
op.bump_to = 0x7fffffffffffffff op.bump_to = 0x7fffffffffffffff
tx = self._create_msg() 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==' assert b64encode(response.signature) == b'UAOL4ZPYIOzEgM66kBrhyNjLR66dNXtuNrmvd3m0/pc8qCSoLmYY4TybS0lHiMtb+LFZESTaxrpErMHz1sZ6DQ=='
def test_sign_tx_account_merge_op(self): def test_sign_tx_account_merge_op(self):
@ -56,7 +56,7 @@ class TestMsgStellarSignTransaction(TrezorTest):
tx = self._create_msg() 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 hexlify(response.public_key) == b'15d648bfe4d36f196cfb5735ffd8ca54cd4b8233f743f22449de7cf301cdb469'
assert b64encode(response.signature) == b'gjoPRj4sW5o7NAXzYOqPK0uxfPbeKb4Qw48LJiCH/XUZ6YVCiZogePC0Z5ISUlozMh6YO6HoYtuLPbm7jq+eCA==' 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 # 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/>. # along with this library. If not, see <http://www.gnu.org/licenses/>.
from binascii import unhexlify
from .common import * from .common import TrezorTest
import base64
class TestMsgVerifymessage(TrezorTest): class TestMsgVerifymessage(TrezorTest):

View File

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

View File

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

View File

@ -16,7 +16,7 @@
# You should have received a copy of the GNU Lesser General Public License # 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/>. # 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 from trezorlib import messages as proto

View File

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

View File

@ -16,10 +16,13 @@
# You should have received a copy of the GNU Lesser General Public License # 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/>. # 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 from trezorlib import messages as proto
import trezorlib.ckd_public as bip32
from trezorlib.coins import tx_api from trezorlib.coins import tx_api
from trezorlib.tools import parse_path
class TestMultisigChange(TrezorTest): class TestMultisigChange(TrezorTest):
@ -193,7 +196,7 @@ class TestMultisigChange(TrezorTest):
) )
out2 = proto.TxOutputType( out2 = proto.TxOutputType(
address_n=self.client.expand_path("45'/0/1/1"), address_n=parse_path("45'/0/1/1"),
amount=44000000, amount=44000000,
script_type=proto.OutputScriptType.PAYTOADDRESS script_type=proto.OutputScriptType.PAYTOADDRESS
) )
@ -209,7 +212,7 @@ class TestMultisigChange(TrezorTest):
self.setup_mnemonic_nopin_nopassphrase() self.setup_mnemonic_nopin_nopassphrase()
out1 = proto.TxOutputType( out1 = proto.TxOutputType(
address_n=self.client.expand_path("45'/0/1/0"), address_n=parse_path("45'/0/1/0"),
amount=40000000, amount=40000000,
script_type=proto.OutputScriptType.PAYTOADDRESS script_type=proto.OutputScriptType.PAYTOADDRESS
) )

View File

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

View File

@ -16,10 +16,10 @@
# You should have received a copy of the GNU Lesser General Public License # 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/>. # along with this library. If not, see <http://www.gnu.org/licenses/>.
from __future__ import print_function
import time import time
from .common import * import pytest
from .common import TrezorTest
from trezorlib import messages as proto from trezorlib import messages as proto
from trezorlib.client import PinException, CallException 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 # 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/>. # 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 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 # 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/>. # along with this library. If not, see <http://www.gnu.org/licenses/>.
from binascii import unhexlify
from __future__ import print_function from .common import TrezorTest
import sys
from .common import *
from trezorlib import messages as proto 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.curves import SECP256k1
from ecdsa.ellipticcurve import Point, INFINITY from ecdsa.ellipticcurve import Point, INFINITY
from . import tools from trezorlib import tools
from . import messages as proto from trezorlib import messages
PRIME_DERIVATION_FLAG = 0x80000000
def point_to_pubkey(point): def point_to_pubkey(point):
@ -61,7 +59,7 @@ def sec_to_public_pair(pubkey):
def is_prime(n): def is_prime(n):
return (bool)(n & PRIME_DERIVATION_FLAG) return bool(n & tools.HARDENED_FLAG)
def fingerprint(pubkey): def fingerprint(pubkey):
@ -76,7 +74,7 @@ def public_ckd(public_node, n):
if not isinstance(n, list): if not isinstance(n, list):
raise ValueError('Parameter must be a list') raise ValueError('Parameter must be a list')
node = proto.HDNodeType() node = messages.HDNodeType()
node.CopyFrom(public_node) node.CopyFrom(public_node)
for i in n: 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() I64 = hmac.HMAC(key=node.chain_code, msg=data, digestmod=hashlib.sha512).digest()
I_left_as_exponent = string_to_number(I64[:32]) 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.depth = node.depth + 1
node_out.child_num = i node_out.child_num = i
node_out.chain_code = I64[32:] node_out.chain_code = I64[32:]
@ -128,17 +126,17 @@ def serialize(node, version=0x0488B21E):
s += b'\x00' + node.private_key s += b'\x00' + node.private_key
else: else:
s += node.public_key s += node.public_key
s += tools.Hash(s)[:4] s += tools.btc_hash(s)[:4]
return tools.b58encode(s) return tools.b58encode(s)
def deserialize(xpub): def deserialize(xpub):
data = tools.b58decode(xpub, None) 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") raise ValueError("Checksum failed")
node = proto.HDNodeType() node = messages.HDNodeType()
node.depth = struct.unpack('>B', data[4:5])[0] node.depth = struct.unpack('>B', data[4:5])[0]
node.fingerprint = struct.unpack('>I', data[5:9])[0] node.fingerprint = struct.unpack('>I', data[5:9])[0]
node.child_num = struct.unpack('>I', data[9:13])[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 # 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/>. # 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(): 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/>. # along with this library. If not, see <http://www.gnu.org/licenses/>.
import hashlib import hashlib
import binascii
import struct 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() 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): def hash_160_to_bc_address(h160, address_type):
vh160 = struct.pack('<B', address_type) + h160 vh160 = struct.pack('<B', address_type) + h160
h = Hash(vh160) h = btc_hash(vh160)
addr = vh160 + h[0:4] addr = vh160 + h[0:4]
return b58encode(addr) return b58encode(addr)
@ -109,3 +124,41 @@ def b58decode(v, length):
return None return None
return result 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 # 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/>. # 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): class TransportException(Exception):
pass pass
@ -63,54 +70,52 @@ class Transport(object):
raise TransportException('{} device not found: {}'.format(cls.PATH_PREFIX, path)) raise TransportException('{} device not found: {}'.format(cls.PATH_PREFIX, path))
def all_transports(): def all_transports() -> Iterable[Type[Transport]]:
transports = [] transports = set() # type: Set[Type[Transport]]
try: for modname in ("bridge", "hid", "udp", "webusb"):
from .bridge import BridgeTransport try:
transports.append(BridgeTransport) # Import the module and find the Transport class.
except: # To avoid iterating over every item, the module should assign its Transport class
pass # to a constant named TRANSPORT.
module = importlib.import_module("." + modname, __name__)
try: try:
from .hid import HidTransport transports.add(getattr(module, "TRANSPORT"))
transports.append(HidTransport) except AttributeError:
except: LOG.warning("Skipping broken module {}".format(modname))
pass except ImportError as e:
LOG.info("Failed to import module {}: {}".format(modname, e))
try:
from .udp import UdpTransport
transports.append(UdpTransport)
except:
pass
try:
from .webusb import WebUsbTransport
transports.append(WebUsbTransport)
except:
pass
return transports return transports
def enumerate_devices(): def enumerate_devices() -> Iterable[Transport]:
return [device devices = [] # type: List[Transport]
for transport in all_transports() for transport in all_transports():
for device in transport.enumerate()] 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: if path is None:
try: try:
return enumerate_devices()[0] return next(iter(enumerate_devices()))
except IndexError: except IndexError:
raise Exception("No TREZOR device found") from None raise Exception("No TREZOR device found") from None
# Find whether B is prefix of A (transport name is part of the path) # 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). # 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. # 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) 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)] transports = [t for t in all_transports() if match_prefix(path, t.PATH_PREFIX)]
if transports: if transports:
return transports[0].find_by_path(path, prefix_search=prefix_search) 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 # 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/>. # along with this library. If not, see <http://www.gnu.org/licenses/>.
import logging
import requests import requests
import binascii import binascii
from io import BytesIO from io import BytesIO
@ -27,6 +28,8 @@ from .. import messages
from .. import protobuf from .. import protobuf
from . import Transport, TransportException from . import Transport, TransportException
LOG = logging.getLogger(__name__)
TREZORD_HOST = 'http://127.0.0.1:21325' TREZORD_HOST = 'http://127.0.0.1:21325'
@ -78,6 +81,8 @@ class BridgeTransport(Transport):
self.session = None self.session = None
def write(self, msg): def write(self, msg):
LOG.debug("sending message: {}".format(msg.__class__.__name__),
extra={'protobuf': msg})
data = BytesIO() data = BytesIO()
protobuf.dump_message(data, msg) protobuf.dump_message(data, msg)
ser = data.getvalue() ser = data.getvalue()
@ -97,5 +102,10 @@ class BridgeTransport(Transport):
(msg_type, datalen) = struct.unpack('>HL', data[:headerlen]) (msg_type, datalen) = struct.unpack('>HL', data[:headerlen])
data = BytesIO(data[headerlen:headerlen + datalen]) data = BytesIO(data[headerlen:headerlen + datalen])
msg = protobuf.load_message(data, mapping.get_class(msg_type)) msg = protobuf.load_message(data, mapping.get_class(msg_type))
LOG.debug("received message: {}".format(msg.__class__.__name__),
extra={'protobuf': msg})
self.response = None self.response = None
return msg return msg
TRANSPORT = BridgeTransport

View File

@ -180,3 +180,6 @@ def is_wirelink(dev):
def is_debuglink(dev): def is_debuglink(dev):
return (dev['usage_page'] == 0xFF01 or dev['interface_number'] == 1) 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: if len(chunk) != 64:
raise TransportException('Unexpected chunk size: %d' % len(chunk)) raise TransportException('Unexpected chunk size: %d' % len(chunk))
return bytearray(chunk) return bytearray(chunk)
TRANSPORT = UdpTransport

View File

@ -188,3 +188,6 @@ def is_vendor_class(dev):
def dev_to_str(dev): def dev_to_str(dev):
return ':'.join(str(x) for x in ['%03i' % (dev.getBusNumber(), )] + dev.getPortNumberList()) 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; exit 0;
fi fi
if [ "$TRAVIS_BRANCH" != "master" ]; then
echo "not triggering from non-master branch"
exit 0;
fi
if [ "$TRAVIS_PULL_REQUEST" != "false" ]; then if [ "$TRAVIS_PULL_REQUEST" != "false" ]; then
echo "not triggering from pull requests" echo "not triggering from pull requests"
exit 0; exit 0;