1
0
mirror of https://github.com/trezor/trezor-firmware.git synced 2025-06-25 01:18:54 +00:00

style: apply black/isort

This commit is contained in:
matejcik 2018-08-13 18:21:24 +02:00
parent e336f578af
commit 3d3e9b67b4
106 changed files with 8503 additions and 4057 deletions

890
trezorctl

File diff suppressed because it is too large Load Diff

View File

@ -2,7 +2,7 @@
# modified for Python 3 by Jochen Hoenicke <hoenicke@gmail.com> # modified for Python 3 by Jochen Hoenicke <hoenicke@gmail.com>
import hashlib import hashlib
from typing import Tuple, NewType from typing import NewType, Tuple
Point = NewType("Point", Tuple[int, int]) Point = NewType("Point", Tuple[int, int])
@ -17,7 +17,7 @@ def H(m: bytes) -> bytes:
def expmod(b: int, e: int, m: int) -> int: 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:
return 1 return 1
t = expmod(b, e >> 1, m) ** 2 % m t = expmod(b, e >> 1, m) ** 2 % m
@ -123,18 +123,18 @@ def decodepoint(s: bytes) -> Point:
x = q - x x = q - x
P = Point((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: bytes, m: bytes, pk: bytes) -> None: 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:
raise ValueError('public-key length is wrong') raise ValueError("public-key length is wrong")
R = decodepoint(s[0:b >> 3]) R = decodepoint(s[0 : b >> 3])
A = decodepoint(pk) A = decodepoint(pk)
S = decodeint(s[b >> 3:b >> 2]) S = decodeint(s[b >> 3 : b >> 2])
h = Hint(encodepoint(R) + pk + m) h = Hint(encodepoint(R) + pk + m)
if scalarmult(B, S) != edwards(R, scalarmult(A, h)): if scalarmult(B, S) != edwards(R, scalarmult(A, h)):
raise ValueError('signature does not pass verification') raise ValueError("signature does not pass verification")

View File

@ -1,37 +1,91 @@
from . import messages as proto from . import messages as proto
from .tools import expect, CallException, normalize_nfc, session from .tools import CallException, expect, normalize_nfc, session
@expect(proto.PublicKey) @expect(proto.PublicKey)
def get_public_node(client, n, ecdsa_curve_name=None, show_display=False, coin_name=None): def get_public_node(
return client.call(proto.GetPublicKey(address_n=n, ecdsa_curve_name=ecdsa_curve_name, show_display=show_display, coin_name=coin_name)) client, n, ecdsa_curve_name=None, show_display=False, coin_name=None
):
return client.call(
proto.GetPublicKey(
address_n=n,
ecdsa_curve_name=ecdsa_curve_name,
show_display=show_display,
coin_name=coin_name,
)
)
@expect(proto.Address, field="address") @expect(proto.Address, field="address")
def get_address(client, coin_name, n, show_display=False, multisig=None, script_type=proto.InputScriptType.SPENDADDRESS): def get_address(
client,
coin_name,
n,
show_display=False,
multisig=None,
script_type=proto.InputScriptType.SPENDADDRESS,
):
if multisig: if multisig:
return client.call(proto.GetAddress(address_n=n, coin_name=coin_name, show_display=show_display, multisig=multisig, script_type=script_type)) return client.call(
proto.GetAddress(
address_n=n,
coin_name=coin_name,
show_display=show_display,
multisig=multisig,
script_type=script_type,
)
)
else: else:
return client.call(proto.GetAddress(address_n=n, coin_name=coin_name, show_display=show_display, script_type=script_type)) return client.call(
proto.GetAddress(
address_n=n,
coin_name=coin_name,
show_display=show_display,
script_type=script_type,
)
)
@expect(proto.MessageSignature) @expect(proto.MessageSignature)
def sign_message(client, coin_name, n, message, script_type=proto.InputScriptType.SPENDADDRESS): def sign_message(
client, coin_name, n, message, script_type=proto.InputScriptType.SPENDADDRESS
):
message = normalize_nfc(message) message = normalize_nfc(message)
return client.call(proto.SignMessage(coin_name=coin_name, address_n=n, message=message, script_type=script_type)) return client.call(
proto.SignMessage(
coin_name=coin_name, address_n=n, message=message, script_type=script_type
)
)
def verify_message(client, coin_name, address, signature, message): def verify_message(client, coin_name, address, signature, message):
message = normalize_nfc(message) message = normalize_nfc(message)
try: try:
resp = client.call(proto.VerifyMessage(address=address, signature=signature, message=message, coin_name=coin_name)) resp = client.call(
proto.VerifyMessage(
address=address,
signature=signature,
message=message,
coin_name=coin_name,
)
)
except CallException as e: except CallException as e:
resp = e resp = e
return isinstance(resp, proto.Success) return isinstance(resp, proto.Success)
@session @session
def sign_tx(client, coin_name, inputs, outputs, version=None, lock_time=None, expiry=None, overwintered=None, debug_processor=None): def sign_tx(
client,
coin_name,
inputs,
outputs,
version=None,
lock_time=None,
expiry=None,
overwintered=None,
debug_processor=None,
):
# start = time.time() # start = time.time()
txes = client._prepare_sign_tx(inputs, outputs) txes = client._prepare_sign_tx(inputs, outputs)
@ -52,7 +106,7 @@ def sign_tx(client, coin_name, inputs, outputs, version=None, lock_time=None, ex
# Prepare structure for signatures # Prepare structure for signatures
signatures = [None] * len(inputs) signatures = [None] * len(inputs)
serialized_tx = b'' serialized_tx = b""
counter = 0 counter = 0
while True: while True:
@ -71,7 +125,10 @@ def sign_tx(client, coin_name, inputs, outputs, version=None, lock_time=None, ex
if res.serialized and res.serialized.signature_index is not None: if res.serialized and res.serialized.signature_index is not None:
if signatures[res.serialized.signature_index] is not None: if signatures[res.serialized.signature_index] is not None:
raise ValueError("Signature for index %d already filled" % res.serialized.signature_index) raise ValueError(
"Signature for index %d already filled"
% res.serialized.signature_index
)
signatures[res.serialized.signature_index] = res.serialized.signature signatures[res.serialized.signature_index] = res.serialized.signature
if res.request_type == proto.RequestType.TXFINISHED: if res.request_type == proto.RequestType.TXFINISHED:
@ -93,7 +150,9 @@ def sign_tx(client, coin_name, inputs, outputs, version=None, lock_time=None, ex
msg.outputs_cnt = len(current_tx.bin_outputs) msg.outputs_cnt = len(current_tx.bin_outputs)
else: else:
msg.outputs_cnt = len(current_tx.outputs) msg.outputs_cnt = len(current_tx.outputs)
msg.extra_data_len = len(current_tx.extra_data) if current_tx.extra_data else 0 msg.extra_data_len = (
len(current_tx.extra_data) if current_tx.extra_data else 0
)
res = client.call(proto.TxAck(tx=msg)) res = client.call(proto.TxAck(tx=msg))
continue continue
@ -104,6 +163,7 @@ def sign_tx(client, coin_name, inputs, outputs, version=None, lock_time=None, ex
# msg needs to be deep copied so when it's modified # msg needs to be deep copied so when it's modified
# the other messages stay intact # the other messages stay intact
from copy import deepcopy from copy import deepcopy
msg = deepcopy(msg) msg = deepcopy(msg)
# If debug_processor function is provided, # If debug_processor function is provided,
# pass thru it the request and prepared response. # pass thru it the request and prepared response.
@ -124,6 +184,7 @@ def sign_tx(client, coin_name, inputs, outputs, version=None, lock_time=None, ex
# msg needs to be deep copied so when it's modified # msg needs to be deep copied so when it's modified
# the other messages stay intact # the other messages stay intact
from copy import deepcopy from copy import deepcopy
msg = deepcopy(msg) msg = deepcopy(msg)
# If debug_processor function is provided, # If debug_processor function is provided,
# pass thru it the request and prepared response. # pass thru it the request and prepared response.
@ -136,7 +197,7 @@ def sign_tx(client, coin_name, inputs, outputs, version=None, lock_time=None, ex
elif res.request_type == proto.RequestType.TXEXTRADATA: elif res.request_type == proto.RequestType.TXEXTRADATA:
o, l = res.details.extra_data_offset, res.details.extra_data_len o, l = res.details.extra_data_offset, res.details.extra_data_len
msg = proto.TransactionType() msg = proto.TransactionType()
msg.extra_data = current_tx.extra_data[o:o + l] msg.extra_data = current_tx.extra_data[o : o + l]
res = client.call(proto.TxAck(tx=msg)) res = client.call(proto.TxAck(tx=msg))
continue continue

View File

@ -16,6 +16,6 @@
import warnings import warnings
warnings.warn("ckd_public module is deprecated and will be removed", DeprecationWarning)
from .tests.support.ckd_public import * # noqa from .tests.support.ckd_public import * # noqa
warnings.warn("ckd_public module is deprecated and will be removed", DeprecationWarning)

View File

@ -14,22 +14,32 @@
# You should have received a copy of the License along with this library. # You should have received a copy of the License along with this library.
# If not, see <https://www.gnu.org/licenses/lgpl-3.0.html>. # If not, see <https://www.gnu.org/licenses/lgpl-3.0.html>.
import binascii
import functools import functools
import getpass
import logging import logging
import os import os
import sys import sys
import time import time
import binascii
import getpass
import warnings import warnings
from mnemonic import Mnemonic from mnemonic import Mnemonic
from . import messages as proto from . import (
from . import btc, cosi, device, ethereum, firmware, lisk, misc, nem, stellar btc,
from . import mapping cosi,
from . import tools debuglink,
from . import debuglink device,
ethereum,
firmware,
lisk,
mapping,
messages as proto,
misc,
nem,
stellar,
tools,
)
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.")
@ -42,6 +52,7 @@ LOG = logging.getLogger(__name__)
try: try:
import termios import termios
import tty import tty
# POSIX system. Create and return a getch that manipulates the tty. # POSIX system. Create and return a getch that manipulates the tty.
# On Windows, termios will fail to import. # On Windows, termios will fail to import.
@ -55,6 +66,7 @@ try:
termios.tcsetattr(fd, termios.TCSADRAIN, old_settings) termios.tcsetattr(fd, termios.TCSADRAIN, old_settings)
return ch return ch
except ImportError: except ImportError:
# Windows system. # Windows system.
# Use msvcrt's getch function. # Use msvcrt's getch function.
@ -67,12 +79,16 @@ except ImportError:
# skip special keys: read the scancode and repeat # skip special keys: read the scancode and repeat
msvcrt.getch() msvcrt.getch()
continue continue
return key.decode('latin1') return key.decode("latin1")
def get_buttonrequest_value(code): def get_buttonrequest_value(code):
# Converts integer code to its string representation of ButtonRequestType # Converts integer code to its string representation of ButtonRequestType
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]
class PinException(tools.CallException): class PinException(tools.CallException):
@ -81,13 +97,18 @@ class PinException(tools.CallException):
class MovedTo: class MovedTo:
"""Deprecation redirector for methods that were formerly part of TrezorClient""" """Deprecation redirector for methods that were formerly part of TrezorClient"""
def __init__(self, where): def __init__(self, where):
self.where = where self.where = where
self.name = where.__module__ + '.' + where.__name__ self.name = where.__module__ + "." + where.__name__
def _deprecated_redirect(self, client, *args, **kwargs): def _deprecated_redirect(self, client, *args, **kwargs):
"""Redirector for a deprecated method on TrezorClient""" """Redirector for a deprecated method on TrezorClient"""
warnings.warn("Function has been moved to %s" % self.name, DeprecationWarning, stacklevel=2) warnings.warn(
"Function has been moved to %s" % self.name,
DeprecationWarning,
stacklevel=2,
)
return self.where(client, *args, **kwargs) return self.where(client, *args, **kwargs)
def __get__(self, instance, cls): def __get__(self, instance, cls):
@ -113,7 +134,7 @@ class BaseClient(object):
@tools.session @tools.session
def call_raw(self, msg): def call_raw(self, msg):
__tracebackhide__ = True # pytest traceback hiding - this function won't appear in tracebacks __tracebackhide__ = True # for pytest # pylint: disable=W0612
self.transport.write(msg) self.transport.write(msg)
return self.transport.read() return self.transport.read()
@ -126,20 +147,25 @@ class BaseClient(object):
if handler is not None: if handler is not None:
msg = handler(resp) msg = handler(resp)
if msg is None: if msg is None:
raise ValueError("Callback %s must return protobuf message, not None" % handler) raise ValueError(
"Callback %s must return protobuf message, not None" % handler
)
resp = self.call(msg) resp = self.call(msg)
return resp return resp
def callback_Failure(self, msg): def callback_Failure(self, msg):
if msg.code in (proto.FailureType.PinInvalid, if msg.code in (
proto.FailureType.PinCancelled, proto.FailureType.PinExpected): proto.FailureType.PinInvalid,
proto.FailureType.PinCancelled,
proto.FailureType.PinExpected,
):
raise PinException(msg.code, msg.message) raise PinException(msg.code, msg.message)
raise tools.CallException(msg.code, msg.message) raise tools.CallException(msg.code, msg.message)
def register_message(self, msg): def register_message(self, msg):
'''Allow application to register custom protobuf message type''' """Allow application to register custom protobuf message type"""
mapping.register_message(msg) mapping.register_message(msg)
@ -164,21 +190,27 @@ 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
self.print("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."
)
self.print("Use backspace to correct an entry. The keypad layout is:") self.print("Use backspace to correct an entry. The keypad layout is:")
self.print(" 7 8 9 7 | 9") self.print(" 7 8 9 7 | 9")
self.print(" 4 5 6 4 | 6") self.print(" 4 5 6 4 | 6")
self.print(" 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"):
return proto.Cancel() return proto.Cancel()
if character in ('\x08', '\x7f'): if character in ("\x08", "\x7f"):
return proto.WordAck(word='\x08') return proto.WordAck(word="\x08")
# ignore middle column if only 6 keys requested. # ignore middle column if only 6 keys requested.
if msg.type == proto.WordRequestType.Matrix6 and character in ('2', '5', '8'): if msg.type == proto.WordRequestType.Matrix6 and character in (
"2",
"5",
"8",
):
continue continue
if character.isdigit(): if character.isdigit():
@ -186,22 +218,24 @@ class TextUIMixin(object):
def callback_PinMatrixRequest(self, msg): def callback_PinMatrixRequest(self, msg):
if msg.type == proto.PinMatrixRequestType.Current: if msg.type == proto.PinMatrixRequestType.Current:
desc = 'current PIN' desc = "current PIN"
elif msg.type == proto.PinMatrixRequestType.NewFirst: elif msg.type == proto.PinMatrixRequestType.NewFirst:
desc = 'new PIN' desc = "new PIN"
elif msg.type == proto.PinMatrixRequestType.NewSecond: elif msg.type == proto.PinMatrixRequestType.NewSecond:
desc = 'new PIN again' desc = "new PIN again"
else: else:
desc = 'PIN' desc = "PIN"
self.print("Use the numeric keypad to describe number positions. The layout is:") self.print(
"Use the numeric keypad to describe number positions. The layout is:"
)
self.print(" 7 8 9") self.print(" 7 8 9")
self.print(" 4 5 6") self.print(" 4 5 6")
self.print(" 1 2 3") self.print(" 1 2 3")
self.print("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")
return proto.PinMatrixAck(pin=pin) return proto.PinMatrixAck(pin=pin)
def callback_PassphraseRequest(self, msg): def callback_PassphraseRequest(self, msg):
@ -214,9 +248,9 @@ class TextUIMixin(object):
return proto.PassphraseAck(passphrase=passphrase) return proto.PassphraseAck(passphrase=passphrase)
self.print("Passphrase required: ") self.print("Passphrase required: ")
passphrase = getpass.getpass('') passphrase = getpass.getpass("")
self.print("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:
@ -227,8 +261,7 @@ class TextUIMixin(object):
return proto.PassphraseStateAck() return proto.PassphraseStateAck()
def callback_WordRequest(self, msg): def callback_WordRequest(self, msg):
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)
self.print("Enter one word of mnemonic: ") self.print("Enter one word of mnemonic: ")
word = input() word = input()
@ -247,7 +280,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 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)
@ -263,7 +296,7 @@ class DebugLinkMixin(object):
self.expected_responses = None self.expected_responses = None
# Use blank passphrase # Use blank passphrase
self.set_passphrase('') self.set_passphrase("")
def close(self): def close(self):
super(DebugLinkMixin, self).close() super(DebugLinkMixin, self).close()
@ -291,8 +324,10 @@ class DebugLinkMixin(object):
# return isinstance(value, TypeError) # return isinstance(value, TypeError)
# 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(
[repr(x) for x in self.expected_responses]) "Some of expected responses didn't come from device: %s"
% [repr(x) for x in self.expected_responses]
)
# Cleanup # Cleanup
self.expected_responses = None self.expected_responses = None
@ -311,13 +346,14 @@ class DebugLinkMixin(object):
self.passphrase = Mnemonic.normalize_string(passphrase) self.passphrase = Mnemonic.normalize_string(passphrase)
def set_mnemonic(self, mnemonic): def set_mnemonic(self, mnemonic):
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 __tracebackhide__ = True # for pytest # pylint: disable=W0612
if SCREENSHOT and self.debug: if SCREENSHOT and self.debug:
from PIL import Image from PIL import Image
layout = self.debug.read_layout() layout = self.debug.read_layout()
im = Image.new("RGB", (128, 64)) im = Image.new("RGB", (128, 64))
pix = im.load() pix = im.load()
@ -326,7 +362,7 @@ class DebugLinkMixin(object):
rx, ry = 127 - x, 63 - y rx, ry = 127 - x, 63 - y
if (ord(layout[rx + (ry / 8) * 128]) & (1 << (ry % 8))) > 0: if (ord(layout[rx + (ry / 8) * 128]) & (1 << (ry % 8))) > 0:
pix[x, y] = (255, 255, 255) pix[x, y] = (255, 255, 255)
im.save('scr%05d.png' % self.screenshot_id) im.save("scr%05d.png" % self.screenshot_id)
self.screenshot_id += 1 self.screenshot_id += 1
resp = super(DebugLinkMixin, self).call_raw(msg) resp = super(DebugLinkMixin, self).call_raw(msg)
@ -334,25 +370,31 @@ 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 __tracebackhide__ = True # for pytest # pylint: disable=W0612
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 AssertionError(proto.FailureType.UnexpectedMessage, raise AssertionError(
"Got %s, but no message has been expected" % repr(msg)) proto.FailureType.UnexpectedMessage,
"Got %s, but no message has been expected" % repr(msg),
)
if msg.__class__ != expected.__class__: if msg.__class__ != expected.__class__:
raise AssertionError(proto.FailureType.UnexpectedMessage, raise AssertionError(
"Expected %s, got %s" % (repr(expected), repr(msg))) proto.FailureType.UnexpectedMessage,
"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 AssertionError(proto.FailureType.UnexpectedMessage, raise AssertionError(
"Expected %s, got %s" % (repr(expected), repr(msg))) proto.FailureType.UnexpectedMessage,
"Expected %s, got %s" % (repr(expected), repr(msg)),
)
def callback_ButtonRequest(self, msg): def callback_ButtonRequest(self, msg):
self.DEBUG("ButtonRequest code: " + get_buttonrequest_value(msg.code)) self.DEBUG("ButtonRequest code: " + get_buttonrequest_value(msg.code))
@ -368,7 +410,7 @@ class DebugLinkMixin(object):
if self.pin_correct: if self.pin_correct:
pin = self.debug.read_pin_encoded() pin = self.debug.read_pin_encoded()
else: else:
pin = '444222' pin = "444222"
return proto.PinMatrixAck(pin=pin) return proto.PinMatrixAck(pin=pin)
def callback_PassphraseRequest(self, msg): def callback_PassphraseRequest(self, msg):
@ -380,7 +422,7 @@ class DebugLinkMixin(object):
def callback_WordRequest(self, msg): def callback_WordRequest(self, msg):
(word, pos) = self.debug.read_recovery_word() (word, pos) = self.debug.read_recovery_word()
if word != '': if word != "":
return proto.WordAck(word=word) return proto.WordAck(word=word)
if pos != 0: if pos != 0:
return proto.WordAck(word=self.mnemonic[pos - 1]) return proto.WordAck(word=self.mnemonic[pos - 1])
@ -389,7 +431,7 @@ class DebugLinkMixin(object):
class ProtocolMixin(object): class ProtocolMixin(object):
VENDORS = ('bitcointrezor.com', 'trezor.io') VENDORS = ("bitcointrezor.com", "trezor.io")
def __init__(self, state=None, *args, **kwargs): def __init__(self, state=None, *args, **kwargs):
super(ProtocolMixin, self).__init__(*args, **kwargs) super(ProtocolMixin, self).__init__(*args, **kwargs)
@ -410,15 +452,27 @@ class ProtocolMixin(object):
@staticmethod @staticmethod
def expand_path(n): def expand_path(n):
warnings.warn('expand_path is deprecated, use tools.parse_path', DeprecationWarning, stacklevel=2) warnings.warn(
"expand_path is deprecated, use tools.parse_path",
DeprecationWarning,
stacklevel=2,
)
return tools.parse_path(n) return tools.parse_path(n)
@tools.expect(proto.Success, field="message") @tools.expect(proto.Success, field="message")
def ping(self, msg, button_protection=False, pin_protection=False, passphrase_protection=False): def ping(
msg = proto.Ping(message=msg, self,
button_protection=button_protection, msg,
pin_protection=pin_protection, button_protection=False,
passphrase_protection=passphrase_protection) pin_protection=False,
passphrase_protection=False,
):
msg = proto.Ping(
message=msg,
button_protection=button_protection,
pin_protection=pin_protection,
passphrase_protection=passphrase_protection,
)
return self.call(msg) return self.call(msg)
def get_device_id(self): def get_device_id(self):
@ -435,14 +489,18 @@ class ProtocolMixin(object):
if inp.prev_hash in txes: if inp.prev_hash in txes:
continue continue
if inp.script_type in (proto.InputScriptType.SPENDP2SHWITNESS, if inp.script_type in (
proto.InputScriptType.SPENDWITNESS): proto.InputScriptType.SPENDP2SHWITNESS,
proto.InputScriptType.SPENDWITNESS,
):
continue continue
if not self.tx_api: if not self.tx_api:
raise RuntimeError('TX_API not defined') raise RuntimeError("TX_API not defined")
prev_tx = self.tx_api.get_tx(binascii.hexlify(inp.prev_hash).decode('utf-8')) prev_tx = self.tx_api.get_tx(
binascii.hexlify(inp.prev_hash).decode("utf-8")
)
txes[inp.prev_hash] = prev_tx txes[inp.prev_hash] = prev_tx
return txes return txes

View File

@ -14,12 +14,12 @@
# You should have received a copy of the License along with this library. # You should have received a copy of the License along with this library.
# If not, see <https://www.gnu.org/licenses/lgpl-3.0.html>. # If not, see <https://www.gnu.org/licenses/lgpl-3.0.html>.
import os.path
import json import json
import os.path
from .tx_api import TxApiInsight from .tx_api import TxApiInsight
COINS_JSON = os.path.join(os.path.dirname(__file__), 'coins.json') COINS_JSON = os.path.join(os.path.dirname(__file__), "coins.json")
def _load_coins_json(): def _load_coins_json():
@ -35,24 +35,26 @@ def _load_coins_json():
def _insight_for_coin(coin): def _insight_for_coin(coin):
url = next(iter(coin['blockbook'] + coin['bitcore']), None) url = next(iter(coin["blockbook"] + coin["bitcore"]), None)
if not url: if not url:
return None return None
zcash = coin['coin_name'].lower().startswith('zcash') zcash = coin["coin_name"].lower().startswith("zcash")
bip115 = coin['bip115'] bip115 = coin["bip115"]
network = 'insight_{}'.format(coin['coin_name'].lower().replace(' ', '_')) network = "insight_{}".format(coin["coin_name"].lower().replace(" ", "_"))
return TxApiInsight(network=network, url=url, zcash=zcash, bip115=bip115) return TxApiInsight(network=network, url=url, zcash=zcash, bip115=bip115)
# exported variables # exported variables
__all__ = ['by_name', 'slip44', 'tx_api'] __all__ = ["by_name", "slip44", "tx_api"]
try: try:
by_name = _load_coins_json() by_name = _load_coins_json()
except Exception as e: except Exception as e:
raise ImportError("Failed to load coins.json. Check your installation.") from e raise ImportError("Failed to load coins.json. Check your installation.") from e
slip44 = {name: coin['slip44'] for name, coin in by_name.items()} slip44 = {name: coin["slip44"] for name, coin in by_name.items()}
tx_api = {name: _insight_for_coin(coin) tx_api = {
for name, coin in by_name.items() name: _insight_for_coin(coin)
if coin["blockbook"] or coin["bitcore"]} for name, coin in by_name.items()
if coin["blockbook"] or coin["bitcore"]
}

View File

@ -14,15 +14,13 @@
# You should have received a copy of the License along with this library. # You should have received a copy of the License along with this library.
# If not, see <https://www.gnu.org/licenses/lgpl-3.0.html>. # If not, see <https://www.gnu.org/licenses/lgpl-3.0.html>.
from functools import reduce
import binascii import binascii
from functools import reduce
from typing import Iterable, Tuple from typing import Iterable, Tuple
from . import messages from . import _ed25519, messages
from .tools import expect from .tools import expect
from . import _ed25519
# XXX, these could be NewType's, but that would infect users of the cosi module with these types as well. # 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. # Unsure if we want that.
Ed25519PrivateKey = bytes Ed25519PrivateKey = bytes
@ -37,7 +35,9 @@ def combine_keys(pks: Iterable[Ed25519PublicPoint]) -> Ed25519PublicPoint:
return Ed25519PublicPoint(_ed25519.encodepoint(combine)) return Ed25519PublicPoint(_ed25519.encodepoint(combine))
def combine_sig(global_R: Ed25519PublicPoint, sigs: Iterable[Ed25519Signature]) -> Ed25519Signature: def combine_sig(
global_R: Ed25519PublicPoint, sigs: Iterable[Ed25519Signature]
) -> Ed25519Signature:
"""Combine a list of signatures into a single CoSi signature.""" """Combine a list of signatures into a single CoSi signature."""
S = [_ed25519.decodeint(si) for si in sigs] S = [_ed25519.decodeint(si) for si in sigs]
s = sum(S) % _ed25519.l s = sum(S) % _ed25519.l
@ -45,7 +45,9 @@ def combine_sig(global_R: Ed25519PublicPoint, sigs: Iterable[Ed25519Signature])
return Ed25519Signature(sig) return Ed25519Signature(sig)
def get_nonce(sk: Ed25519PrivateKey, data: bytes, ctr: int = 0) -> Tuple[int, Ed25519PublicPoint]: def get_nonce(
sk: Ed25519PrivateKey, data: bytes, ctr: int = 0
) -> Tuple[int, Ed25519PublicPoint]:
"""Calculate CoSi nonces for given data. """Calculate CoSi nonces for given data.
These differ from Ed25519 deterministic nonces in that there is a counter appended at end. These differ from Ed25519 deterministic nonces in that there is a counter appended at end.
@ -58,12 +60,18 @@ def get_nonce(sk: Ed25519PrivateKey, data: bytes, ctr: int = 0) -> Tuple[int, Ed
""" """
h = _ed25519.H(sk) h = _ed25519.H(sk)
b = _ed25519.b b = _ed25519.b
r = _ed25519.Hint(bytes([h[i] for i in range(b >> 3, b >> 2)]) + data + binascii.unhexlify('%08x' % ctr)) 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) R = _ed25519.scalarmult(_ed25519.B, r)
return r, Ed25519PublicPoint(_ed25519.encodepoint(R)) return r, Ed25519PublicPoint(_ed25519.encodepoint(R))
def verify(signature: Ed25519Signature, digest: bytes, pub_key: Ed25519PublicPoint) -> None: def verify(
signature: Ed25519Signature, digest: bytes, pub_key: Ed25519PublicPoint
) -> None:
"""Verify Ed25519 signature. Raise exception if the signature is invalid.""" """Verify Ed25519 signature. Raise exception if the signature is invalid."""
# XXX this *might* change to bool function # XXX this *might* change to bool function
_ed25519.checkvalid(signature, digest, pub_key) _ed25519.checkvalid(signature, digest, pub_key)
@ -76,10 +84,13 @@ def pubkey_from_privkey(privkey: Ed25519PrivateKey) -> Ed25519PublicPoint:
return Ed25519PublicPoint(_ed25519.publickey(privkey)) return Ed25519PublicPoint(_ed25519.publickey(privkey))
def sign_with_privkey(digest: bytes, privkey: Ed25519PrivateKey, def sign_with_privkey(
global_pubkey: Ed25519PublicPoint, digest: bytes,
nonce: int, privkey: Ed25519PrivateKey,
global_commit: Ed25519PublicPoint) -> Ed25519Signature: global_pubkey: Ed25519PublicPoint,
nonce: int,
global_commit: Ed25519PublicPoint,
) -> Ed25519Signature:
"""Create a CoSi signature of `digest` with the supplied private key. """Create a CoSi signature of `digest` with the supplied private key.
This function needs to know the global public key and global commitment. This function needs to know the global public key and global commitment.
""" """
@ -100,4 +111,11 @@ def commit(client, n, data):
@expect(messages.CosiSignature) @expect(messages.CosiSignature)
def sign(client, n, data, global_commitment, global_pubkey): def sign(client, n, data, global_commitment, global_pubkey):
return client.call(messages.CosiSign(address_n=n, data=data, global_commitment=global_commitment, global_pubkey=global_pubkey)) return client.call(
messages.CosiSign(
address_n=n,
data=data,
global_commitment=global_commitment,
global_pubkey=global_pubkey,
)
)

View File

@ -18,8 +18,7 @@ import binascii
from mnemonic import Mnemonic from mnemonic import Mnemonic
from . import messages as proto from . import messages as proto, tools
from . import tools
from .tools import expect from .tools import expect
@ -69,7 +68,7 @@ class DebugLink(object):
# We have to encode that into encoded pin, # We have to encode that into encoded pin,
# because application must send back positions # because application must send back positions
# on keypad, not a real PIN. # on keypad, not a real PIN.
pin_encoded = ''.join([str(matrix.index(p) + 1) for p in pin]) pin_encoded = "".join([str(matrix.index(p) + 1) for p in pin])
print("Encoded PIN:", pin_encoded) print("Encoded PIN:", pin_encoded)
return pin_encoded return pin_encoded
@ -138,21 +137,33 @@ class DebugLink(object):
return obj.memory return obj.memory
def memory_write(self, address, memory, flash=False): def memory_write(self, address, memory, flash=False):
self._call(proto.DebugLinkMemoryWrite(address=address, memory=memory, flash=flash), nowait=True) self._call(
proto.DebugLinkMemoryWrite(address=address, memory=memory, flash=flash),
nowait=True,
)
def flash_erase(self, sector): def flash_erase(self, sector):
self._call(proto.DebugLinkFlashErase(sector=sector), nowait=True) self._call(proto.DebugLinkFlashErase(sector=sector), nowait=True)
@expect(proto.Success, field="message") @expect(proto.Success, field="message")
def load_device_by_mnemonic(client, mnemonic, pin, passphrase_protection, label, language='english', skip_checksum=False, expand=False): def load_device_by_mnemonic(
client,
mnemonic,
pin,
passphrase_protection,
label,
language="english",
skip_checksum=False,
expand=False,
):
# Convert mnemonic to UTF8 NKFD # Convert mnemonic to UTF8 NKFD
mnemonic = Mnemonic.normalize_string(mnemonic) mnemonic = Mnemonic.normalize_string(mnemonic)
# Convert mnemonic to ASCII stream # Convert mnemonic to ASCII stream
mnemonic = mnemonic.encode('utf-8') mnemonic = mnemonic.encode("utf-8")
m = Mnemonic('english') m = Mnemonic("english")
if expand: if expand:
mnemonic = m.expand(mnemonic) mnemonic = m.expand(mnemonic)
@ -161,13 +172,20 @@ def load_device_by_mnemonic(client, mnemonic, pin, passphrase_protection, label,
raise ValueError("Invalid mnemonic checksum") raise ValueError("Invalid mnemonic checksum")
if client.features.initialized: if client.features.initialized:
raise RuntimeError("Device is initialized already. Call wipe_device() and try again.") raise RuntimeError(
"Device is initialized already. Call wipe_device() and try again."
)
resp = client.call(proto.LoadDevice(mnemonic=mnemonic, pin=pin, resp = client.call(
passphrase_protection=passphrase_protection, proto.LoadDevice(
language=language, mnemonic=mnemonic,
label=label, pin=pin,
skip_checksum=skip_checksum)) passphrase_protection=passphrase_protection,
language=language,
label=label,
skip_checksum=skip_checksum,
)
)
client.init_device() client.init_device()
return resp return resp
@ -175,9 +193,11 @@ def load_device_by_mnemonic(client, mnemonic, pin, passphrase_protection, label,
@expect(proto.Success, field="message") @expect(proto.Success, field="message")
def load_device_by_xprv(client, xprv, pin, passphrase_protection, label, language): def load_device_by_xprv(client, xprv, pin, passphrase_protection, label, language):
if client.features.initialized: if client.features.initialized:
raise RuntimeError("Device is initialized already. Call wipe_device() and try again.") raise RuntimeError(
"Device is initialized already. Call wipe_device() and try again."
)
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 not 100 < len(xprv) < 112: # yes this is correct in Python if not 100 < len(xprv) < 112: # yes this is correct in Python
@ -186,7 +206,7 @@ def load_device_by_xprv(client, xprv, pin, passphrase_protection, label, languag
node = proto.HDNodeType() node = proto.HDNodeType()
data = binascii.hexlify(tools.b58decode(xprv, None)) data = binascii.hexlify(tools.b58decode(xprv, None))
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(tools.btc_hash(binascii.unhexlify(data[:156]))[:4]) checksum = binascii.hexlify(tools.btc_hash(binascii.unhexlify(data[:156]))[:4])
@ -207,11 +227,15 @@ def load_device_by_xprv(client, xprv, pin, passphrase_protection, label, languag
node.chain_code = binascii.unhexlify(data[26:90]) node.chain_code = binascii.unhexlify(data[26:90])
node.private_key = binascii.unhexlify(data[92:156]) # skip 0x00 indicating privkey node.private_key = binascii.unhexlify(data[92:156]) # skip 0x00 indicating privkey
resp = client.call(proto.LoadDevice(node=node, resp = client.call(
pin=pin, proto.LoadDevice(
passphrase_protection=passphrase_protection, node=node,
language=language, pin=pin,
label=label)) passphrase_protection=passphrase_protection,
language=language,
label=label,
)
)
client.init_device() client.init_device()
return resp return resp
@ -221,4 +245,8 @@ def self_test(client):
if client.features.bootloader_mode is not True: if client.features.bootloader_mode is not True:
raise RuntimeError("Device must be in bootloader mode") raise RuntimeError("Device must be in bootloader mode")
return client.call(proto.SelfTest(payload=b'\x00\xFF\x55\xAA\x66\x99\x33\xCCABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789!\x00\xFF\x55\xAA\x66\x99\x33\xCC')) return client.call(
proto.SelfTest(
payload=b"\x00\xFF\x55\xAA\x66\x99\x33\xCCABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789!\x00\xFF\x55\xAA\x66\x99\x33\xCC"
)
)

View File

@ -16,34 +16,42 @@
import os import os
import warnings import warnings
from mnemonic import Mnemonic from mnemonic import Mnemonic
from . import messages as proto from . import messages as proto
from .tools import expect, session from .tools import expect, session
from .transport import enumerate_devices, get_transport from .transport import enumerate_devices, get_transport
class TrezorDevice: class TrezorDevice:
''' """
This class is deprecated. (There is no reason for it to exist in the first This class is deprecated. (There is no reason for it to exist in the first
place, it is nothing but a collection of two functions.) place, it is nothing but a collection of two functions.)
Instead, please use functions from the ``trezorlib.transport`` module. Instead, please use functions from the ``trezorlib.transport`` module.
''' """
@classmethod @classmethod
def enumerate(cls): def enumerate(cls):
warnings.warn('TrezorDevice is deprecated.', DeprecationWarning) warnings.warn("TrezorDevice is deprecated.", DeprecationWarning)
return enumerate_devices() return enumerate_devices()
@classmethod @classmethod
def find_by_path(cls, path): def find_by_path(cls, path):
warnings.warn('TrezorDevice is deprecated.', DeprecationWarning) warnings.warn("TrezorDevice is deprecated.", DeprecationWarning)
return get_transport(path, prefix_search=False) return get_transport(path, prefix_search=False)
@expect(proto.Success, field="message") @expect(proto.Success, field="message")
def apply_settings(client, label=None, language=None, use_passphrase=None, homescreen=None, passphrase_source=None, auto_lock_delay_ms=None): def apply_settings(
client,
label=None,
language=None,
use_passphrase=None,
homescreen=None,
passphrase_source=None,
auto_lock_delay_ms=None,
):
settings = proto.ApplySettings() settings = proto.ApplySettings()
if label is not None: if label is not None:
settings.label = label settings.label = label
@ -91,9 +99,21 @@ def wipe(client):
@expect(proto.Success, field="message") @expect(proto.Success, field="message")
def recover(client, word_count, passphrase_protection, pin_protection, label, language, type=proto.RecoveryDeviceType.ScrambledWords, expand=False, dry_run=False): def recover(
client,
word_count,
passphrase_protection,
pin_protection,
label,
language,
type=proto.RecoveryDeviceType.ScrambledWords,
expand=False,
dry_run=False,
):
if client.features.initialized and not dry_run: if client.features.initialized and not dry_run:
raise RuntimeError("Device is initialized already. Call wipe_device() and try again.") raise RuntimeError(
"Device is initialized already. Call wipe_device() and try again."
)
if word_count not in (12, 18, 24): if word_count not in (12, 18, 24):
raise ValueError("Invalid word count. Use 12/18/24") raise ValueError("Invalid word count. Use 12/18/24")
@ -103,17 +123,20 @@ def recover(client, word_count, passphrase_protection, pin_protection, label, la
client.expand = expand client.expand = expand
if client.expand: if client.expand:
# optimization to load the wordlist once, instead of for each recovery word # optimization to load the wordlist once, instead of for each recovery word
client.mnemonic_wordlist = Mnemonic('english') client.mnemonic_wordlist = Mnemonic("english")
res = client.call(proto.RecoveryDevice( res = client.call(
word_count=int(word_count), proto.RecoveryDevice(
passphrase_protection=bool(passphrase_protection), word_count=int(word_count),
pin_protection=bool(pin_protection), passphrase_protection=bool(passphrase_protection),
label=label, pin_protection=bool(pin_protection),
language=language, label=label,
enforce_wordlist=True, language=language,
type=type, enforce_wordlist=True,
dry_run=dry_run)) type=type,
dry_run=dry_run,
)
)
client.init_device() client.init_device()
return res return res
@ -121,19 +144,33 @@ def recover(client, word_count, passphrase_protection, pin_protection, label, la
@expect(proto.Success, field="message") @expect(proto.Success, field="message")
@session @session
def reset(client, display_random, strength, passphrase_protection, pin_protection, label, language, u2f_counter=0, skip_backup=False): def reset(
client,
display_random,
strength,
passphrase_protection,
pin_protection,
label,
language,
u2f_counter=0,
skip_backup=False,
):
if client.features.initialized: if client.features.initialized:
raise RuntimeError("Device is initialized already. Call wipe_device() and try again.") raise RuntimeError(
"Device is initialized already. Call wipe_device() and try again."
)
# Begin with device reset workflow # Begin with device reset workflow
msg = proto.ResetDevice(display_random=display_random, msg = proto.ResetDevice(
strength=strength, display_random=display_random,
passphrase_protection=bool(passphrase_protection), strength=strength,
pin_protection=bool(pin_protection), passphrase_protection=bool(passphrase_protection),
language=language, pin_protection=bool(pin_protection),
label=label, language=language,
u2f_counter=u2f_counter, label=label,
skip_backup=bool(skip_backup)) u2f_counter=u2f_counter,
skip_backup=bool(skip_backup),
)
resp = client.call(msg) resp = client.call(msg)
if not isinstance(resp, proto.EntropyRequest): if not isinstance(resp, proto.EntropyRequest):

View File

@ -1,9 +1,9 @@
from . import messages as proto from . import messages as proto
from .tools import expect, CallException, normalize_nfc, session from .tools import CallException, expect, normalize_nfc, session
def int_to_big_endian(value): def int_to_big_endian(value):
return value.to_bytes((value.bit_length() + 7) // 8, 'big') return value.to_bytes((value.bit_length() + 7) // 8, "big")
# ====== Client functions ====== # # ====== Client functions ====== #
@ -15,13 +15,25 @@ def get_address(client, n, show_display=False, multisig=None):
@session @session
def sign_tx(client, n, nonce, gas_price, gas_limit, to, value, data=None, chain_id=None, tx_type=None): def sign_tx(
client,
n,
nonce,
gas_price,
gas_limit,
to,
value,
data=None,
chain_id=None,
tx_type=None,
):
msg = proto.EthereumSignTx( msg = proto.EthereumSignTx(
address_n=n, address_n=n,
nonce=int_to_big_endian(nonce), nonce=int_to_big_endian(nonce),
gas_price=int_to_big_endian(gas_price), gas_price=int_to_big_endian(gas_price),
gas_limit=int_to_big_endian(gas_limit), gas_limit=int_to_big_endian(gas_limit),
value=int_to_big_endian(value)) value=int_to_big_endian(value),
)
if to: if to:
msg.to = to msg.to = to
@ -56,7 +68,11 @@ def sign_message(client, n, message):
def verify_message(client, address, signature, message): def verify_message(client, address, signature, message):
message = normalize_nfc(message) message = normalize_nfc(message)
try: try:
resp = client.call(proto.EthereumVerifyMessage(address=address, signature=signature, message=message)) resp = client.call(
proto.EthereumVerifyMessage(
address=address, signature=signature, message=message
)
)
except CallException as e: except CallException as e:
resp = e resp = e
if isinstance(resp, proto.Success): if isinstance(resp, proto.Success):

View File

@ -1,12 +1,16 @@
import binascii import binascii
import construct as c import construct as c
import pyblake2 import pyblake2
from . import cosi from . import cosi, messages as proto, tools
from . import messages as proto
from . import tools
def bytes_not(data):
return bytes(~b & 0xff for b in data)
# fmt: off
Toif = c.Struct( Toif = c.Struct(
"magic" / c.Const(b"TOI"), "magic" / c.Const(b"TOI"),
"format" / c.Enum(c.Byte, full_color=b"f", grayscale=b"g"), "format" / c.Enum(c.Byte, full_color=b"f", grayscale=b"g"),
@ -16,10 +20,6 @@ Toif = c.Struct(
) )
def bytes_not(data):
return bytes(~b & 0xff for b in data)
VendorTrust = c.Transformed(c.BitStruct( VendorTrust = c.Transformed(c.BitStruct(
"reserved" / c.Padding(9), "reserved" / c.Padding(9),
"show_vendor_string" / c.Flag, "show_vendor_string" / c.Flag,
@ -87,7 +87,10 @@ FirmwareHeader = c.Struct(
"signature" / c.Bytes(64), "signature" / c.Bytes(64),
"_end_offset" / c.Tell, "_end_offset" / c.Tell,
"header_len" / c.Pointer(c.this._start_offset + 4, c.Rebuild(c.Int32ul, c.this._end_offset - c.this._start_offset)), "header_len" / c.Pointer(
c.this._start_offset + 4,
c.Rebuild(c.Int32ul, c.this._end_offset - c.this._start_offset)
),
) )
@ -97,12 +100,13 @@ Firmware = c.Struct(
"code" / c.Bytes(c.this.firmware_header.code_length), "code" / c.Bytes(c.this.firmware_header.code_length),
c.Terminated, c.Terminated,
) )
# fmt: on
def validate_firmware(filename): def validate_firmware(filename):
with open(filename, "rb") as f: with open(filename, "rb") as f:
data = f.read() data = f.read()
if data[:6] == b'54525a': if data[:6] == b"54525a":
data = binascii.unhexlify(data) data = binascii.unhexlify(data)
try: try:
@ -113,19 +117,29 @@ def validate_firmware(filename):
vendor = fw.vendor_header vendor = fw.vendor_header
header = fw.firmware_header header = fw.firmware_header
print("Vendor header from {}, version {}.{}".format(vendor.vendor_string, vendor.version.major, vendor.version.minor)) print(
print("Firmware version {v.major}.{v.minor}.{v.patch} build {v.build}".format(v=header.version)) "Vendor header from {}, version {}.{}".format(
vendor.vendor_string, vendor.version.major, vendor.version.minor
)
)
print(
"Firmware version {v.major}.{v.minor}.{v.patch} build {v.build}".format(
v=header.version
)
)
# rebuild header without signatures # rebuild header without signatures
stripped_header = header.copy() stripped_header = header.copy()
stripped_header.sigmask = 0 stripped_header.sigmask = 0
stripped_header.signature = b'\0' * 64 stripped_header.signature = b"\0" * 64
header_bytes = FirmwareHeader.build(stripped_header) header_bytes = FirmwareHeader.build(stripped_header)
digest = pyblake2.blake2s(header_bytes).digest() digest = pyblake2.blake2s(header_bytes).digest()
print("Fingerprint: {}".format(binascii.hexlify(digest).decode("ascii"))) print("Fingerprint: {}".format(binascii.hexlify(digest).decode("ascii")))
global_pk = cosi.combine_keys(vendor.pubkeys[i] for i in range(8) if header.sigmask & (1 << i)) global_pk = cosi.combine_keys(
vendor.pubkeys[i] for i in range(8) if header.sigmask & (1 << i)
)
try: try:
cosi.verify(header.signature, digest, global_pk) cosi.verify(header.signature, digest, global_pk)
@ -156,22 +170,29 @@ def update(client, fp):
resp = client.call(proto.FirmwareUpload(payload=data)) resp = client.call(proto.FirmwareUpload(payload=data))
if isinstance(resp, proto.Success): if isinstance(resp, proto.Success):
return True return True
elif isinstance(resp, proto.Failure) and resp.code == proto.FailureType.FirmwareError: elif (
isinstance(resp, proto.Failure)
and resp.code == proto.FailureType.FirmwareError
):
return False return False
raise RuntimeError("Unexpected result %s" % resp) raise RuntimeError("Unexpected result %s" % resp)
# TREZORv2 method # TREZORv2 method
if isinstance(resp, proto.FirmwareRequest): if isinstance(resp, proto.FirmwareRequest):
import pyblake2 import pyblake2
while True: while True:
payload = data[resp.offset:resp.offset + resp.length] payload = data[resp.offset : resp.offset + resp.length]
digest = pyblake2.blake2s(payload).digest() digest = pyblake2.blake2s(payload).digest()
resp = client.call(proto.FirmwareUpload(payload=payload, hash=digest)) resp = client.call(proto.FirmwareUpload(payload=payload, hash=digest))
if isinstance(resp, proto.FirmwareRequest): if isinstance(resp, proto.FirmwareRequest):
continue continue
elif isinstance(resp, proto.Success): elif isinstance(resp, proto.Success):
return True return True
elif isinstance(resp, proto.Failure) and resp.code == proto.FailureType.FirmwareError: elif (
isinstance(resp, proto.Failure)
and resp.code == proto.FailureType.FirmwareError
):
return False return False
raise RuntimeError("Unexpected result %s" % resp) raise RuntimeError("Unexpected result %s" % resp)

View File

@ -1,7 +1,7 @@
import binascii import binascii
from . import messages as proto from . import messages as proto
from .tools import expect, CallException, normalize_nfc from .tools import CallException, expect, normalize_nfc
@expect(proto.LiskAddress, field="address") @expect(proto.LiskAddress, field="address")
@ -23,7 +23,11 @@ def sign_message(client, n, message):
def verify_message(client, pubkey, signature, message): def verify_message(client, pubkey, signature, message):
message = normalize_nfc(message) message = normalize_nfc(message)
try: try:
resp = client.call(proto.LiskVerifyMessage(signature=signature, public_key=pubkey, message=message)) resp = client.call(
proto.LiskVerifyMessage(
signature=signature, public_key=pubkey, message=message
)
)
except CallException as e: except CallException as e:
resp = e resp = e
return isinstance(resp, proto.Success) return isinstance(resp, proto.Success)
@ -55,7 +59,9 @@ def sign_tx(client, n, transaction):
msg = proto.LiskTransactionCommon() msg = proto.LiskTransactionCommon()
msg.type = transaction["type"] msg.type = transaction["type"]
msg.fee = int(transaction["fee"]) # Lisk use strings for big numbers (javascript issue) msg.fee = int(
transaction["fee"]
) # Lisk use strings for big numbers (javascript issue)
msg.amount = int(transaction["amount"]) # And we convert it back to number msg.amount = int(transaction["amount"]) # And we convert it back to number
msg.timestamp = transaction["timestamp"] msg.timestamp = transaction["timestamp"]

View File

@ -23,14 +23,15 @@ OMITTED_MESSAGES = set() # type: Set[Type[protobuf.MessageType]]
class PrettyProtobufFormatter(logging.Formatter): class PrettyProtobufFormatter(logging.Formatter):
def format(self, record: logging.LogRecord) -> str: def format(self, record: logging.LogRecord) -> str:
time = self.formatTime(record) time = self.formatTime(record)
message = '[{time}] {source} {level}: {msg}'.format( message = "[{time}] {source} {level}: {msg}".format(
time=time, level=record.levelname.upper(), time=time,
level=record.levelname.upper(),
source=record.name, source=record.name,
msg=super().format(record)) msg=super().format(record),
if hasattr(record, 'protobuf'): )
if hasattr(record, "protobuf"):
if type(record.protobuf) in OMITTED_MESSAGES: if type(record.protobuf) in OMITTED_MESSAGES:
message += " ({} bytes)".format(record.protobuf.ByteSize()) message += " ({} bytes)".format(record.protobuf.ByteSize())
else: else:
@ -45,6 +46,6 @@ def enable_debug_output(handler: Optional[logging.Handler] = None):
formatter = PrettyProtobufFormatter() formatter = PrettyProtobufFormatter()
handler.setFormatter(formatter) handler.setFormatter(formatter)
logger = logging.getLogger('trezorlib') logger = logging.getLogger("trezorlib")
logger.setLevel(logging.DEBUG) logger.setLevel(logging.DEBUG)
logger.addHandler(handler) logger.addHandler(handler)

View File

@ -22,24 +22,30 @@ map_class_to_type = {}
def build_map(): def build_map():
for msg_name in dir(messages.MessageType): for msg_name in dir(messages.MessageType):
if msg_name.startswith('__'): if msg_name.startswith("__"):
continue continue
try: try:
msg_class = getattr(messages, msg_name) msg_class = getattr(messages, msg_name)
except AttributeError: except AttributeError:
raise ValueError("Implementation of protobuf message '%s' is missing" % msg_name) raise ValueError(
"Implementation of protobuf message '%s' is missing" % msg_name
)
if msg_class.MESSAGE_WIRE_TYPE != getattr(messages.MessageType, msg_name): if msg_class.MESSAGE_WIRE_TYPE != getattr(messages.MessageType, msg_name):
raise ValueError("Inconsistent wire type and MessageType record for '%s'" % msg_class) raise ValueError(
"Inconsistent wire type and MessageType record for '%s'" % msg_class
)
register_message(msg_class) register_message(msg_class)
def register_message(msg_class): def register_message(msg_class):
if msg_class.MESSAGE_WIRE_TYPE in map_type_to_class: if msg_class.MESSAGE_WIRE_TYPE in map_type_to_class:
raise Exception("Message for wire type %s is already registered by %s" % raise Exception(
(msg_class.MESSAGE_WIRE_TYPE, get_class(msg_class.MESSAGE_WIRE_TYPE))) "Message for wire type %s is already registered by %s"
% (msg_class.MESSAGE_WIRE_TYPE, get_class(msg_class.MESSAGE_WIRE_TYPE))
)
map_class_to_type[msg_class] = msg_class.MESSAGE_WIRE_TYPE map_class_to_type[msg_class] = msg_class.MESSAGE_WIRE_TYPE
map_type_to_class[msg_class.MESSAGE_WIRE_TYPE] = msg_class map_type_to_class[msg_class.MESSAGE_WIRE_TYPE] = msg_class

View File

@ -8,32 +8,59 @@ def get_entropy(client, size):
@expect(proto.SignedIdentity) @expect(proto.SignedIdentity)
def sign_identity(client, identity, challenge_hidden, challenge_visual, ecdsa_curve_name=None): def sign_identity(
return client.call(proto.SignIdentity(identity=identity, challenge_hidden=challenge_hidden, challenge_visual=challenge_visual, ecdsa_curve_name=ecdsa_curve_name)) client, identity, challenge_hidden, challenge_visual, ecdsa_curve_name=None
):
return client.call(
proto.SignIdentity(
identity=identity,
challenge_hidden=challenge_hidden,
challenge_visual=challenge_visual,
ecdsa_curve_name=ecdsa_curve_name,
)
)
@expect(proto.ECDHSessionKey) @expect(proto.ECDHSessionKey)
def get_ecdh_session_key(client, identity, peer_public_key, ecdsa_curve_name=None): def get_ecdh_session_key(client, identity, peer_public_key, ecdsa_curve_name=None):
return client.call(proto.GetECDHSessionKey(identity=identity, peer_public_key=peer_public_key, ecdsa_curve_name=ecdsa_curve_name)) return client.call(
proto.GetECDHSessionKey(
identity=identity,
peer_public_key=peer_public_key,
ecdsa_curve_name=ecdsa_curve_name,
)
)
@expect(proto.CipheredKeyValue, field="value") @expect(proto.CipheredKeyValue, field="value")
def encrypt_keyvalue(client, n, key, value, ask_on_encrypt=True, ask_on_decrypt=True, iv=b''): def encrypt_keyvalue(
return client.call(proto.CipherKeyValue(address_n=n, client, n, key, value, ask_on_encrypt=True, ask_on_decrypt=True, iv=b""
key=key, ):
value=value, return client.call(
encrypt=True, proto.CipherKeyValue(
ask_on_encrypt=ask_on_encrypt, address_n=n,
ask_on_decrypt=ask_on_decrypt, key=key,
iv=iv)) value=value,
encrypt=True,
ask_on_encrypt=ask_on_encrypt,
ask_on_decrypt=ask_on_decrypt,
iv=iv,
)
)
@expect(proto.CipheredKeyValue, field="value") @expect(proto.CipheredKeyValue, field="value")
def decrypt_keyvalue(client, n, key, value, ask_on_encrypt=True, ask_on_decrypt=True, iv=b''): def decrypt_keyvalue(
return client.call(proto.CipherKeyValue(address_n=n, client, n, key, value, ask_on_encrypt=True, ask_on_decrypt=True, iv=b""
key=key, ):
value=value, return client.call(
encrypt=False, proto.CipherKeyValue(
ask_on_encrypt=ask_on_encrypt, address_n=n,
ask_on_decrypt=ask_on_decrypt, key=key,
iv=iv)) value=value,
encrypt=False,
ask_on_encrypt=ask_on_encrypt,
ask_on_decrypt=ask_on_decrypt,
iv=iv,
)
)

View File

@ -16,8 +16,9 @@
import binascii import binascii
import json import json
from . import messages as proto from . import messages as proto
from .tools import expect, CallException from .tools import CallException, expect
TYPE_TRANSACTION_TRANSFER = 0x0101 TYPE_TRANSACTION_TRANSFER = 0x0101
TYPE_IMPORTANCE_TRANSFER = 0x0801 TYPE_IMPORTANCE_TRANSFER = 0x0801
@ -54,21 +55,27 @@ def create_transfer(transaction):
msg.public_key = binascii.unhexlify(transaction["message"]["publicKey"]) msg.public_key = binascii.unhexlify(transaction["message"]["publicKey"])
if "mosaics" in transaction: if "mosaics" in transaction:
msg.mosaics = [proto.NEMMosaic( msg.mosaics = [
namespace=mosaic["mosaicId"]["namespaceId"], proto.NEMMosaic(
mosaic=mosaic["mosaicId"]["name"], namespace=mosaic["mosaicId"]["namespaceId"],
quantity=mosaic["quantity"], mosaic=mosaic["mosaicId"]["name"],
) for mosaic in transaction["mosaics"]] quantity=mosaic["quantity"],
)
for mosaic in transaction["mosaics"]
]
return msg return msg
def create_aggregate_modification(transactions): def create_aggregate_modification(transactions):
msg = proto.NEMAggregateModification() msg = proto.NEMAggregateModification()
msg.modifications = [proto.NEMCosignatoryModification( msg.modifications = [
type=modification["modificationType"], proto.NEMCosignatoryModification(
public_key=binascii.unhexlify(modification["cosignatoryAccount"]), type=modification["modificationType"],
) for modification in transactions["modifications"]] public_key=binascii.unhexlify(modification["cosignatoryAccount"]),
)
for modification in transactions["modifications"]
]
if "minCosignatories" in transactions: if "minCosignatories" in transactions:
msg.relative_change = transactions["minCosignatories"]["relativeChange"] msg.relative_change = transactions["minCosignatories"]["relativeChange"]
@ -141,7 +148,7 @@ def create_importance_transfer(transaction):
def create_sign_tx(transaction): def create_sign_tx(transaction):
msg = proto.NEMSignTx() msg = proto.NEMSignTx()
msg.transaction = create_transaction_common(transaction) msg.transaction = create_transaction_common(transaction)
msg.cosigning = (transaction["type"] == TYPE_MULTISIG_SIGNATURE) msg.cosigning = transaction["type"] == TYPE_MULTISIG_SIGNATURE
if transaction["type"] in (TYPE_MULTISIG_SIGNATURE, TYPE_MULTISIG): if transaction["type"] in (TYPE_MULTISIG_SIGNATURE, TYPE_MULTISIG):
transaction = transaction["otherTrans"] transaction = transaction["otherTrans"]
@ -172,7 +179,9 @@ def create_sign_tx(transaction):
@expect(proto.NEMAddress, field="address") @expect(proto.NEMAddress, field="address")
def get_address(client, n, network, show_display=False): def get_address(client, n, network, show_display=False):
return client.call(proto.NEMGetAddress(address_n=n, network=network, show_display=show_display)) return client.call(
proto.NEMGetAddress(address_n=n, network=network, show_display=show_display)
)
@expect(proto.NEMSignedTx) @expect(proto.NEMSignedTx)

View File

@ -89,6 +89,7 @@ def dump_uvarint(writer, n):
# But this is harder in Python because we don't natively know the bit size of the number. # But this is harder in Python because we don't natively know the bit size of the number.
# So we have to branch on whether the number is negative. # So we have to branch on whether the number is negative.
def sint_to_uint(sint): def sint_to_uint(sint):
res = sint << 1 res = sint << 1
if sint < 0: if sint < 0:
@ -134,8 +135,7 @@ class MessageType:
self._fill_missing() self._fill_missing()
def __eq__(self, rhs): def __eq__(self, rhs):
return (self.__class__ is rhs.__class__ and return self.__class__ is rhs.__class__ and self.__dict__ == rhs.__dict__
self.__dict__ == rhs.__dict__)
def __repr__(self): def __repr__(self):
d = {} d = {}
@ -143,16 +143,16 @@ class MessageType:
if value is None or value == []: if value is None or value == []:
continue continue
d[key] = value d[key] = value
return '<%s: %s>' % (self.__class__.__name__, d) return "<%s: %s>" % (self.__class__.__name__, d)
def __iter__(self): def __iter__(self):
return self.__dict__.__iter__() return self.__dict__.__iter__()
def __getattr__(self, attr): def __getattr__(self, attr):
if attr.startswith('_add_'): if attr.startswith("_add_"):
return self._additem(attr[5:]) return self._additem(attr[5:])
if attr.startswith('_extend_'): if attr.startswith("_extend_"):
return self._extenditem(attr[8:]) return self._extenditem(attr[8:])
raise AttributeError(attr) raise AttributeError(attr)
@ -208,7 +208,6 @@ class MessageType:
class LimitedReader: class LimitedReader:
def __init__(self, reader, limit): def __init__(self, reader, limit):
self.reader = reader self.reader = reader
self.limit = limit self.limit = limit
@ -223,7 +222,6 @@ class LimitedReader:
class CountingWriter: class CountingWriter:
def __init__(self): def __init__(self):
self.size = 0 self.size = 0
@ -331,7 +329,7 @@ def dump_message(writer, msg):
elif ftype is UnicodeType: elif ftype is UnicodeType:
if not isinstance(svalue, bytes): if not isinstance(svalue, bytes):
svalue = svalue.encode('utf-8') svalue = svalue.encode("utf-8")
dump_uvarint(writer, len(svalue)) dump_uvarint(writer, len(svalue))
writer.write(svalue) writer.write(svalue)
@ -346,12 +344,13 @@ def dump_message(writer, msg):
raise TypeError raise TypeError
def format_message(pb: MessageType, def format_message(
indent: int = 0, pb: MessageType,
sep: str = ' ' * 4, indent: int = 0,
truncate_after: Optional[int] = 256, sep: str = " " * 4,
truncate_to: Optional[int] = 64) -> str: truncate_after: Optional[int] = 256,
truncate_to: Optional[int] = 64,
) -> str:
def mostly_printable(bytes): def mostly_printable(bytes):
if not bytes: if not bytes:
return True return True
@ -369,33 +368,33 @@ def format_message(pb: MessageType,
return repr(value) return repr(value)
# long list, one line per entry # long list, one line per entry
lines = ['[', level + ']'] lines = ["[", level + "]"]
lines[1:1] = [leadin + pformat_value(x, indent + 1) + ',' for x in value] lines[1:1] = [leadin + pformat_value(x, indent + 1) + "," for x in value]
return '\n'.join(lines) return "\n".join(lines)
if isinstance(value, dict): if isinstance(value, dict):
lines = ['{'] lines = ["{"]
for key, val in sorted(value.items()): for key, val in sorted(value.items()):
if val is None or val == []: if val is None or val == []:
continue continue
lines.append(leadin + key + ': ' + pformat_value(val, indent + 1) + ',') lines.append(leadin + key + ": " + pformat_value(val, indent + 1) + ",")
lines.append(level + '}') lines.append(level + "}")
return '\n'.join(lines) return "\n".join(lines)
if isinstance(value, (bytes, bytearray)): if isinstance(value, (bytes, bytearray)):
length = len(value) length = len(value)
suffix = '' suffix = ""
if truncate_after and length > truncate_after: if truncate_after and length > truncate_after:
suffix = '...' suffix = "..."
value = value[:truncate_to or 0] value = value[: truncate_to or 0]
if mostly_printable(value): if mostly_printable(value):
output = repr(value) output = repr(value)
else: else:
output = '0x' + binascii.hexlify(value).decode('ascii') output = "0x" + binascii.hexlify(value).decode("ascii")
return '{} bytes {}{}'.format(length, output, suffix) return "{} bytes {}{}".format(length, output, suffix)
return repr(value) return repr(value)
return '{name} ({size} bytes) {content}'.format( return "{name} ({size} bytes) {content}".format(
name=pb.__class__.__name__, name=pb.__class__.__name__,
size=pb.ByteSize(), size=pb.ByteSize(),
content=pformat_value(pb.__dict__, indent) content=pformat_value(pb.__dict__, indent),
) )

View File

@ -14,13 +14,12 @@
# You should have received a copy of the License along with this library. # You should have received a copy of the License along with this library.
# If not, see <https://www.gnu.org/licenses/lgpl-3.0.html>. # If not, see <https://www.gnu.org/licenses/lgpl-3.0.html>.
from io import BytesIO
import logging import logging
import struct import struct
from io import BytesIO
from typing import Tuple from typing import Tuple
from . import mapping from . import mapping, protobuf
from . import protobuf
from .transport import Transport from .transport import Transport
REPLEN = 64 REPLEN = 64
@ -29,7 +28,6 @@ LOG = logging.getLogger(__name__)
class ProtocolV1: class ProtocolV1:
def session_begin(self, transport: Transport) -> None: def session_begin(self, transport: Transport) -> None:
pass pass
@ -37,8 +35,10 @@ class ProtocolV1:
pass pass
def write(self, transport: Transport, msg: protobuf.MessageType) -> None: def write(self, transport: Transport, msg: protobuf.MessageType) -> None:
LOG.debug("sending message: {}".format(msg.__class__.__name__), LOG.debug(
extra={'protobuf': msg}) "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()
@ -47,8 +47,8 @@ class ProtocolV1:
while data: while data:
# Report ID, data padded to 63 bytes # Report ID, data padded to 63 bytes
chunk = b'?' + data[:REPLEN - 1] chunk = b"?" + data[: REPLEN - 1]
chunk = chunk.ljust(REPLEN, b'\x00') chunk = chunk.ljust(REPLEN, b"\x00")
transport.write_chunk(chunk) transport.write_chunk(chunk)
data = data[63:] data = data[63:]
@ -67,23 +67,25 @@ class ProtocolV1:
# 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__), LOG.debug(
extra={'protobuf': msg}) "received message: {}".format(msg.__class__.__name__),
extra={"protobuf": msg},
)
return msg return msg
def parse_first(self, chunk: bytes) -> Tuple[int, int, bytes]: 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 Exception: except Exception:
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: bytes) -> bytes: 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

@ -14,13 +14,12 @@
# You should have received a copy of the License along with this library. # You should have received a copy of the License along with this library.
# If not, see <https://www.gnu.org/licenses/lgpl-3.0.html>. # If not, see <https://www.gnu.org/licenses/lgpl-3.0.html>.
from io import BytesIO
import logging import logging
import struct import struct
from io import BytesIO
from typing import Tuple from typing import Tuple
from . import mapping from . import mapping, protobuf
from . import protobuf
from .transport import Transport from .transport import Transport
REPLEN = 64 REPLEN = 64
@ -29,13 +28,12 @@ LOG = logging.getLogger(__name__)
class ProtocolV2: class ProtocolV2:
def __init__(self) -> None: def __init__(self) -> None:
self.session = None self.session = None
def session_begin(self, transport: Transport) -> None: 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)
@ -44,46 +42,50 @@ class ProtocolV2:
def session_end(self, transport: Transport) -> None: 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)
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()
(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)) LOG.debug("[session {}] session ended".format(self.session))
self.session = None self.session = None
def write(self, transport: Transport, msg: protobuf.MessageType) -> None: 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__), LOG.debug(
extra={'protobuf': msg}) "[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)
data = data.getvalue() data = data.getvalue()
dataheader = struct.pack('>LL', mapping.get_type(msg), len(data)) dataheader = struct.pack(">LL", mapping.get_type(msg), len(data))
data = dataheader + data data = dataheader + data
seq = -1 seq = -1
# Write it out # Write it out
while data: while data:
if seq < 0: if seq < 0:
repheader = struct.pack('>BL', 0x01, self.session) repheader = struct.pack(">BL", 0x01, self.session)
else: else:
repheader = struct.pack('>BLL', 0x02, self.session, seq) repheader = struct.pack(">BLL", 0x02, self.session, seq)
datalen = REPLEN - len(repheader) datalen = REPLEN - len(repheader)
chunk = repheader + data[:datalen] chunk = repheader + data[:datalen]
chunk = chunk.ljust(REPLEN, b'\x00') chunk = chunk.ljust(REPLEN, b"\x00")
transport.write_chunk(chunk) transport.write_chunk(chunk)
data = data[datalen:] data = data[datalen:]
seq += 1 seq += 1
def read(self, transport: Transport) -> protobuf.MessageType: 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")
# Read header with first part of message data # Read header with first part of message data
chunk = transport.read_chunk() chunk = transport.read_chunk()
@ -100,40 +102,46 @@ class ProtocolV2:
# 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__), LOG.debug(
extra={'protobuf': msg}) "[session {}] received message: {}".format(
self.session, msg.__class__.__name__
),
extra={"protobuf": msg},
)
return msg return msg
def parse_first(self, chunk: bytes) -> Tuple[int, int, bytes]: 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 Exception: except Exception:
raise RuntimeError('Cannot parse header') raise RuntimeError("Cannot parse header")
if magic != 0x01: if magic != 0x01:
raise RuntimeError('Unexpected magic character') raise RuntimeError("Unexpected magic character")
if session != self.session: if session != self.session:
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: bytes) -> bytes: 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 Exception: except Exception:
raise RuntimeError('Cannot parse header') raise RuntimeError("Cannot parse header")
if magic != 0x02: if magic != 0x02:
raise RuntimeError('Unexpected magic characters') raise RuntimeError("Unexpected magic characters")
if session != self.session: if session != self.session:
raise RuntimeError('Session id mismatch') raise RuntimeError("Session id mismatch")
return chunk[headerlen:] return chunk[headerlen:]
def parse_session_open(self, chunk: bytes) -> int: 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 Exception: except Exception:
raise RuntimeError('Cannot parse header') raise RuntimeError("Cannot parse header")
if magic != 0x03: if magic != 0x03:
raise RuntimeError('Unexpected magic character') raise RuntimeError("Unexpected magic character")
return session return session

View File

@ -14,16 +14,35 @@
# You should have received a copy of the License along with this library. # You should have received a copy of the License along with this library.
# If not, see <https://www.gnu.org/licenses/lgpl-3.0.html>. # If not, see <https://www.gnu.org/licenses/lgpl-3.0.html>.
import sys
import math import math
import sys
try: try:
from PyQt4.QtGui import (QPushButton, QLineEdit, QSizePolicy, QRegExpValidator, QLabel, from PyQt4.QtGui import (
QApplication, QWidget, QGridLayout, QVBoxLayout, QHBoxLayout) QPushButton,
QLineEdit,
QSizePolicy,
QRegExpValidator,
QLabel,
QApplication,
QWidget,
QGridLayout,
QVBoxLayout,
QHBoxLayout,
)
from PyQt4.QtCore import QObject, SIGNAL, QRegExp, Qt, QT_VERSION_STR from PyQt4.QtCore import QObject, SIGNAL, QRegExp, Qt, QT_VERSION_STR
except ImportError: except ImportError:
from PyQt5.QtWidgets import (QPushButton, QLineEdit, QSizePolicy, QLabel, from PyQt5.QtWidgets import (
QApplication, QWidget, QGridLayout, QVBoxLayout, QHBoxLayout) QPushButton,
QLineEdit,
QSizePolicy,
QLabel,
QApplication,
QWidget,
QGridLayout,
QVBoxLayout,
QHBoxLayout,
)
from PyQt5.QtGui import QRegExpValidator from PyQt5.QtGui import QRegExpValidator
from PyQt5.QtCore import QRegExp, Qt from PyQt5.QtCore import QRegExp, Qt
from PyQt5.Qt import QT_VERSION_STR from PyQt5.Qt import QT_VERSION_STR
@ -31,16 +50,16 @@ except ImportError:
class PinButton(QPushButton): class PinButton(QPushButton):
def __init__(self, password, encoded_value): def __init__(self, password, encoded_value):
super(PinButton, self).__init__('?') super(PinButton, self).__init__("?")
self.password = password self.password = password
self.encoded_value = encoded_value self.encoded_value = encoded_value
if QT_VERSION_STR >= '5': if QT_VERSION_STR >= "5":
self.clicked.connect(self._pressed) self.clicked.connect(self._pressed)
elif QT_VERSION_STR >= '4': elif QT_VERSION_STR >= "4":
QObject.connect(self, SIGNAL('clicked()'), self._pressed) QObject.connect(self, SIGNAL("clicked()"), self._pressed)
else: else:
raise RuntimeError('Unsupported Qt version') raise RuntimeError("Unsupported Qt version")
def _pressed(self): def _pressed(self):
self.password.setText(self.password.text() + str(self.encoded_value)) self.password.setText(self.password.text() + str(self.encoded_value))
@ -48,26 +67,29 @@ class PinButton(QPushButton):
class PinMatrixWidget(QWidget): class PinMatrixWidget(QWidget):
''' """
Displays widget with nine blank buttons and password box. Displays widget with nine blank buttons and password box.
Encodes button clicks into sequence of numbers for passing Encodes button clicks into sequence of numbers for passing
into PinAck messages of TREZOR. into PinAck messages of TREZOR.
show_strength=True may be useful for entering new PIN show_strength=True may be useful for entering new PIN
''' """
def __init__(self, show_strength=True, parent=None): def __init__(self, show_strength=True, parent=None):
super(PinMatrixWidget, self).__init__(parent) super(PinMatrixWidget, self).__init__(parent)
self.password = QLineEdit() self.password = QLineEdit()
self.password.setValidator(QRegExpValidator(QRegExp('[1-9]+'), None)) self.password.setValidator(QRegExpValidator(QRegExp("[1-9]+"), None))
self.password.setEchoMode(QLineEdit.Password) self.password.setEchoMode(QLineEdit.Password)
if QT_VERSION_STR >= '5': if QT_VERSION_STR >= "5":
self.password.textChanged.connect(self._password_changed) self.password.textChanged.connect(self._password_changed)
elif QT_VERSION_STR >= '4': elif QT_VERSION_STR >= "4":
QObject.connect(self.password, SIGNAL('textChanged(QString)'), self._password_changed) QObject.connect(
self.password, SIGNAL("textChanged(QString)"), self._password_changed
)
else: else:
raise RuntimeError('Unsupported Qt version') raise RuntimeError("Unsupported Qt version")
self.strength = QLabel() self.strength = QLabel()
self.strength.setMinimumWidth(75) self.strength.setMinimumWidth(75)
@ -95,16 +117,16 @@ class PinMatrixWidget(QWidget):
def _set_strength(self, strength): def _set_strength(self, strength):
if strength < 3000: if strength < 3000:
self.strength.setText('weak') self.strength.setText("weak")
self.strength.setStyleSheet("QLabel { color : #d00; }") self.strength.setStyleSheet("QLabel { color : #d00; }")
elif strength < 60000: elif strength < 60000:
self.strength.setText('fine') self.strength.setText("fine")
self.strength.setStyleSheet("QLabel { color : #db0; }") self.strength.setStyleSheet("QLabel { color : #db0; }")
elif strength < 360000: elif strength < 360000:
self.strength.setText('strong') self.strength.setText("strong")
self.strength.setStyleSheet("QLabel { color : #0a0; }") self.strength.setStyleSheet("QLabel { color : #0a0; }")
else: else:
self.strength.setText('ULTIMATE') self.strength.setText("ULTIMATE")
self.strength.setStyleSheet("QLabel { color : #000; font-weight: bold;}") self.strength.setStyleSheet("QLabel { color : #000; font-weight: bold;}")
def _password_changed(self, password): def _password_changed(self, password):
@ -119,10 +141,10 @@ class PinMatrixWidget(QWidget):
return self.password.text() return self.password.text()
if __name__ == '__main__': if __name__ == "__main__":
''' """
Demo application showing PinMatrix widget in action Demo application showing PinMatrix widget in action
''' """
app = QApplication(sys.argv) app = QApplication(sys.argv)
matrix = PinMatrixWidget() matrix = PinMatrixWidget()
@ -132,13 +154,13 @@ if __name__ == '__main__':
print("Possible button combinations:", matrix.get_strength()) print("Possible button combinations:", matrix.get_strength())
sys.exit() sys.exit()
ok = QPushButton('OK') ok = QPushButton("OK")
if QT_VERSION_STR >= '5': if QT_VERSION_STR >= "5":
ok.clicked.connect(clicked) ok.clicked.connect(clicked)
elif QT_VERSION_STR >= '4': elif QT_VERSION_STR >= "4":
QObject.connect(ok, SIGNAL('clicked()'), clicked) QObject.connect(ok, SIGNAL("clicked()"), clicked)
else: else:
raise RuntimeError('Unsupported Qt version') raise RuntimeError("Unsupported Qt version")
vbox = QVBoxLayout() vbox = QVBoxLayout()
vbox.addWidget(matrix) vbox.addWidget(matrix)

View File

@ -18,12 +18,14 @@
from . import messages from . import messages
from .tools import expect from .tools import expect
REQUIRED_FIELDS = ("Fee", "Sequence", "TransactionType", "Amount", "Destination")
@expect(messages.RippleAddress, field="address") @expect(messages.RippleAddress, field="address")
def get_address(client, address_n, show_display=False): def get_address(client, address_n, show_display=False):
return client.call( return client.call(
messages.RippleGetAddress( messages.RippleGetAddress(address_n=address_n, show_display=show_display)
address_n=address_n, show_display=show_display)) )
@expect(messages.RippleSignedTx) @expect(messages.RippleSignedTx)
@ -33,8 +35,8 @@ def sign_tx(client, address_n, msg: messages.RippleSignTx):
def create_sign_tx_msg(transaction) -> messages.RippleSignTx: def create_sign_tx_msg(transaction) -> messages.RippleSignTx:
if not all(transaction.get(k) for k in ("Fee", "Sequence", "TransactionType", "Amount", "Destination")): if not all(transaction.get(k) for k in REQUIRED_FIELDS):
raise ValueError("Some of the required fields missing (Fee, Sequence, TransactionType, Amount, Destination") raise ValueError("Some of the required fields missing")
if transaction["TransactionType"] != "Payment": if transaction["TransactionType"] != "Payment":
raise ValueError("Only Payment transaction type is supported") raise ValueError("Only Payment transaction type is supported")
@ -49,6 +51,5 @@ def create_sign_tx_msg(transaction) -> messages.RippleSignTx:
def _create_payment(transaction) -> messages.RipplePayment: def _create_payment(transaction) -> messages.RipplePayment:
return messages.RipplePayment( return messages.RipplePayment(
amount=transaction.get("Amount"), amount=transaction.get("Amount"), destination=transaction.get("Destination")
destination=transaction.get("Destination")
) )

View File

@ -19,7 +19,7 @@ import struct
import xdrlib import xdrlib
from . import messages from . import messages
from .tools import expect, CallException from .tools import CallException, expect
# Memo types # Memo types
MEMO_TYPE_NONE = 0 MEMO_TYPE_NONE = 0
@ -65,7 +65,7 @@ def address_from_public_key(pk_bytes):
# checksum # checksum
final_bytes.extend(struct.pack("<H", _crc16_checksum(final_bytes))) final_bytes.extend(struct.pack("<H", _crc16_checksum(final_bytes)))
return str(base64.b32encode(final_bytes), 'utf-8') return str(base64.b32encode(final_bytes), "utf-8")
def address_to_public_key(address_str): def address_to_public_key(address_str):
@ -92,14 +92,21 @@ def parse_transaction_bytes(tx_bytes):
# Timebounds is an optional field # Timebounds is an optional field
if unpacker.unpack_bool(): if unpacker.unpack_bool():
max_timebound = 2**32 - 1 # max unsigned 32-bit int (trezor does not support the full 64-bit time value) max_timebound = 2 ** 32 - 1 # max unsigned 32-bit int
# (trezor does not support the full 64-bit time value)
tx.timebounds_start = unpacker.unpack_uhyper() tx.timebounds_start = unpacker.unpack_uhyper()
tx.timebounds_end = unpacker.unpack_uhyper() tx.timebounds_end = unpacker.unpack_uhyper()
if tx.timebounds_start > max_timebound or tx.timebounds_start < 0: if tx.timebounds_start > max_timebound or tx.timebounds_start < 0:
raise ValueError("Starting timebound out of range (must be between 0 and " + max_timebound) raise ValueError(
"Starting timebound out of range (must be between 0 and "
+ max_timebound
)
if tx.timebounds_end > max_timebound or tx.timebounds_end < 0: if tx.timebounds_end > max_timebound or tx.timebounds_end < 0:
raise ValueError("Ending timebound out of range (must be between 0 and " + max_timebound) raise ValueError(
"Ending timebound out of range (must be between 0 and " + max_timebound
)
# memo type determines what optional fields are set # memo type determines what optional fields are set
tx.memo_type = unpacker.unpack_uint() tx.memo_type = unpacker.unpack_uint()
@ -117,7 +124,7 @@ def parse_transaction_bytes(tx_bytes):
tx.num_operations = unpacker.unpack_uint() tx.num_operations = unpacker.unpack_uint()
operations = [] operations = []
for i in range(tx.num_operations): for _ in range(tx.num_operations):
operations.append(_parse_operation_bytes(unpacker)) operations.append(_parse_operation_bytes(unpacker))
return tx, operations return tx, operations
@ -140,7 +147,7 @@ def _parse_operation_bytes(unpacker):
return messages.StellarCreateAccountOp( return messages.StellarCreateAccountOp(
source_account=source_account, source_account=source_account,
new_account=_xdr_read_address(unpacker), new_account=_xdr_read_address(unpacker),
starting_balance=unpacker.unpack_hyper() starting_balance=unpacker.unpack_hyper(),
) )
if type == OP_PAYMENT: if type == OP_PAYMENT:
@ -148,7 +155,7 @@ def _parse_operation_bytes(unpacker):
source_account=source_account, source_account=source_account,
destination_account=_xdr_read_address(unpacker), destination_account=_xdr_read_address(unpacker),
asset=_xdr_read_asset(unpacker), asset=_xdr_read_asset(unpacker),
amount=unpacker.unpack_hyper() amount=unpacker.unpack_hyper(),
) )
if type == OP_PATH_PAYMENT: if type == OP_PATH_PAYMENT:
@ -159,11 +166,11 @@ def _parse_operation_bytes(unpacker):
destination_account=_xdr_read_address(unpacker), destination_account=_xdr_read_address(unpacker),
destination_asset=_xdr_read_asset(unpacker), destination_asset=_xdr_read_asset(unpacker),
destination_amount=unpacker.unpack_hyper(), destination_amount=unpacker.unpack_hyper(),
paths=[] paths=[],
) )
num_paths = unpacker.unpack_uint() num_paths = unpacker.unpack_uint()
for i in range(num_paths): for _ in range(num_paths):
op.paths.append(_xdr_read_asset(unpacker)) op.paths.append(_xdr_read_asset(unpacker))
return op return op
@ -176,7 +183,7 @@ def _parse_operation_bytes(unpacker):
amount=unpacker.unpack_hyper(), amount=unpacker.unpack_hyper(),
price_n=unpacker.unpack_uint(), price_n=unpacker.unpack_uint(),
price_d=unpacker.unpack_uint(), price_d=unpacker.unpack_uint(),
offer_id=unpacker.unpack_uhyper() offer_id=unpacker.unpack_uhyper(),
) )
if type == OP_CREATE_PASSIVE_OFFER: if type == OP_CREATE_PASSIVE_OFFER:
@ -186,13 +193,11 @@ def _parse_operation_bytes(unpacker):
buying_asset=_xdr_read_asset(unpacker), buying_asset=_xdr_read_asset(unpacker),
amount=unpacker.unpack_hyper(), amount=unpacker.unpack_hyper(),
price_n=unpacker.unpack_uint(), price_n=unpacker.unpack_uint(),
price_d=unpacker.unpack_uint() price_d=unpacker.unpack_uint(),
) )
if type == OP_SET_OPTIONS: if type == OP_SET_OPTIONS:
op = messages.StellarSetOptionsOp( op = messages.StellarSetOptionsOp(source_account=source_account)
source_account=source_account
)
# Inflation destination # Inflation destination
if unpacker.unpack_bool(): if unpacker.unpack_bool():
@ -238,14 +243,14 @@ def _parse_operation_bytes(unpacker):
return messages.StellarChangeTrustOp( return messages.StellarChangeTrustOp(
source_account=source_account, source_account=source_account,
asset=_xdr_read_asset(unpacker), asset=_xdr_read_asset(unpacker),
limit=unpacker.unpack_uhyper() limit=unpacker.unpack_uhyper(),
) )
if type == OP_ALLOW_TRUST: if type == OP_ALLOW_TRUST:
op = messages.StellarAllowTrustOp( op = messages.StellarAllowTrustOp(
source_account=source_account, source_account=source_account,
trusted_account=_xdr_read_address(unpacker), trusted_account=_xdr_read_address(unpacker),
asset_type=unpacker.unpack_uint() asset_type=unpacker.unpack_uint(),
) )
if op.asset_type == ASSET_TYPE_ALPHA4: if op.asset_type == ASSET_TYPE_ALPHA4:
@ -260,15 +265,14 @@ def _parse_operation_bytes(unpacker):
if type == OP_ACCOUNT_MERGE: if type == OP_ACCOUNT_MERGE:
return messages.StellarAccountMergeOp( return messages.StellarAccountMergeOp(
source_account=source_account, source_account=source_account,
destination_account=_xdr_read_address(unpacker) destination_account=_xdr_read_address(unpacker),
) )
# Inflation is not implemented since anyone can submit this operation to the network # Inflation is not implemented since anyone can submit this operation to the network
if type == OP_MANAGE_DATA: if type == OP_MANAGE_DATA:
op = messages.StellarManageDataOp( op = messages.StellarManageDataOp(
source_account=source_account, source_account=source_account, key=unpacker.unpack_string()
key=unpacker.unpack_string(),
) )
# Only set value if the field is present # Only set value if the field is present
@ -281,8 +285,7 @@ def _parse_operation_bytes(unpacker):
# see: https://github.com/stellar/stellar-core/blob/master/src/xdr/Stellar-transaction.x#L269 # see: https://github.com/stellar/stellar-core/blob/master/src/xdr/Stellar-transaction.x#L269
if type == OP_BUMP_SEQUENCE: if type == OP_BUMP_SEQUENCE:
return messages.StellarBumpSequenceOp( return messages.StellarBumpSequenceOp(
source_account=source_account, source_account=source_account, bump_to=unpacker.unpack_uhyper()
bump_to=unpacker.unpack_uhyper()
) )
raise ValueError("Unknown operation type: " + str(type)) raise ValueError("Unknown operation type: " + str(type))
@ -290,9 +293,7 @@ def _parse_operation_bytes(unpacker):
def _xdr_read_asset(unpacker): def _xdr_read_asset(unpacker):
"""Reads a stellar Asset from unpacker""" """Reads a stellar Asset from unpacker"""
asset = messages.StellarAssetType( asset = messages.StellarAssetType(type=unpacker.unpack_uint())
type=unpacker.unpack_uint()
)
if asset.type == ASSET_TYPE_ALPHA4: if asset.type == ASSET_TYPE_ALPHA4:
asset.code = unpacker.unpack_fstring(4) asset.code = unpacker.unpack_fstring(4)
@ -329,8 +330,8 @@ def _crc16_checksum(bytes):
for byte in bytes: for byte in bytes:
for i in range(8): for i in range(8):
bit = ((byte >> (7 - i) & 1) == 1) bit = (byte >> (7 - i) & 1) == 1
c15 = ((crc >> 15 & 1) == 1) c15 = (crc >> 15 & 1) == 1
crc <<= 1 crc <<= 1
if c15 ^ bit: if c15 ^ bit:
crc ^= polynomial crc ^= polynomial
@ -343,15 +344,21 @@ def _crc16_checksum(bytes):
@expect(messages.StellarPublicKey, field="public_key") @expect(messages.StellarPublicKey, field="public_key")
def get_public_key(client, address_n, show_display=False): def get_public_key(client, address_n, show_display=False):
return client.call(messages.StellarGetPublicKey(address_n=address_n, show_display=show_display)) return client.call(
messages.StellarGetPublicKey(address_n=address_n, show_display=show_display)
)
@expect(messages.StellarAddress, field="address") @expect(messages.StellarAddress, field="address")
def get_address(client, address_n, show_display=False): def get_address(client, address_n, show_display=False):
return client.call(messages.StellarGetAddress(address_n=address_n, show_display=show_display)) return client.call(
messages.StellarGetAddress(address_n=address_n, show_display=show_display)
)
def sign_tx(client, tx, operations, address_n, network_passphrase=DEFAULT_NETWORK_PASSPHRASE): def sign_tx(
client, tx, operations, address_n, network_passphrase=DEFAULT_NETWORK_PASSPHRASE
):
tx.network_passphrase = network_passphrase tx.network_passphrase = network_passphrase
tx.address_n = address_n tx.address_n = address_n
tx.num_operations = len(operations) tx.num_operations = len(operations)
@ -368,14 +375,18 @@ def sign_tx(client, tx, operations, address_n, network_passphrase=DEFAULT_NETWOR
resp = client.call(operations.pop(0)) resp = client.call(operations.pop(0))
except IndexError: except IndexError:
# pop from empty list # pop from empty list
raise CallException("Stellar.UnexpectedEndOfOperations", raise CallException(
"Reached end of operations without a signature.") from None "Stellar.UnexpectedEndOfOperations",
"Reached end of operations without a signature.",
) from None
if not isinstance(resp, messages.StellarSignedTx): if not isinstance(resp, messages.StellarSignedTx):
raise CallException(messages.FailureType.UnexpectedMessage, resp) raise CallException(messages.FailureType.UnexpectedMessage, resp)
if operations: if operations:
raise CallException("Stellar.UnprocessedOperations", raise CallException(
"Received a signature before processing all operations.") "Stellar.UnprocessedOperations",
"Received a signature before processing all operations.",
)
return resp return resp

View File

@ -16,35 +16,34 @@
import os import os
from trezorlib import coins, debuglink, device, tx_api
from trezorlib.client import TrezorClientDebugLink
from . import conftest from . import conftest
from trezorlib import coins
from trezorlib import tx_api
from trezorlib.client import TrezorClientDebugLink
from trezorlib import debuglink
from trezorlib import device
tests_dir = os.path.dirname(os.path.abspath(__file__)) tests_dir = os.path.dirname(os.path.abspath(__file__))
tx_api.cache_dir = os.path.join(tests_dir, '../txcache') tx_api.cache_dir = os.path.join(tests_dir, "../txcache")
class TrezorTest: class TrezorTest:
# fmt: off
# 1 2 3 4 5 6 7 8 9 10 11 12 # 1 2 3 4 5 6 7 8 9 10 11 12
mnemonic12 = 'alcohol woman abuse must during monitor noble actual mixed trade anger aisle' mnemonic12 = "alcohol woman abuse must during monitor noble actual mixed trade anger aisle"
mnemonic18 = 'owner little vague addict embark decide pink prosper true fork panda embody mixture exchange choose canoe electric jewel' mnemonic18 = "owner little vague addict embark decide pink prosper true fork panda embody mixture exchange choose canoe electric jewel"
mnemonic24 = 'dignity pass list indicate nasty swamp pool script soccer toe leaf photo multiply desk host tomato cradle drill spread actor shine dismiss champion exotic' mnemonic24 = "dignity pass list indicate nasty swamp pool script soccer toe leaf photo multiply desk host tomato cradle drill spread actor shine dismiss champion exotic"
mnemonic_all = ' '.join(['all'] * 12) mnemonic_all = " ".join(["all"] * 12)
# fmt: on
pin4 = '1234' pin4 = "1234"
pin6 = '789456' pin6 = "789456"
pin8 = '45678978' pin8 = "45678978"
def setup_method(self, method): def setup_method(self, method):
wirelink = conftest.get_device() wirelink = conftest.get_device()
debuglink = wirelink.find_debug() debuglink = wirelink.find_debug()
self.client = TrezorClientDebugLink(wirelink) self.client = TrezorClientDebugLink(wirelink)
self.client.set_debuglink(debuglink) self.client.set_debuglink(debuglink)
self.client.set_tx_api(coins.tx_api['Bitcoin']) self.client.set_tx_api(coins.tx_api["Bitcoin"])
# self.client.set_buttonwait(3) # self.client.set_buttonwait(3)
device.wipe(self.client) device.wipe(self.client)
@ -54,7 +53,7 @@ class TrezorTest:
self.client.transport.session_end() self.client.transport.session_end()
self.client.close() self.client.close()
def _setup_mnemonic(self, mnemonic=None, pin='', passphrase=False): def _setup_mnemonic(self, mnemonic=None, pin="", passphrase=False):
if mnemonic is None: if mnemonic is None:
mnemonic = TrezorTest.mnemonic12 mnemonic = TrezorTest.mnemonic12
debuglink.load_device_by_mnemonic( debuglink.load_device_by_mnemonic(
@ -83,10 +82,10 @@ class TrezorTest:
def generate_entropy(strength, internal_entropy, external_entropy): def generate_entropy(strength, internal_entropy, external_entropy):
''' """
strength - length of produced seed. One of 128, 192, 256 strength - length of produced seed. One of 128, 192, 256
random - binary stream of random data from external HRNG random - binary stream of random data from external HRNG
''' """
import hashlib import hashlib
if strength not in (128, 192, 256): if strength not in (128, 192, 256):
@ -105,7 +104,7 @@ def generate_entropy(strength, internal_entropy, external_entropy):
raise ValueError("External entropy too short") raise ValueError("External entropy too short")
entropy = hashlib.sha256(internal_entropy + external_entropy).digest() entropy = hashlib.sha256(internal_entropy + external_entropy).digest()
entropy_stripped = entropy[:strength // 8] entropy_stripped = entropy[: strength // 8]
if len(entropy_stripped) * 8 != strength: if len(entropy_stripped) * 8 != strength:
raise ValueError("Entropy length mismatch") raise ValueError("Entropy length mismatch")

View File

@ -24,7 +24,7 @@ from trezorlib import log, coins
def get_device(): def get_device():
path = os.environ.get('TREZOR_PATH') path = os.environ.get("TREZOR_PATH")
return get_transport(path) return get_transport(path)
@ -48,7 +48,7 @@ def client():
debuglink = wirelink.find_debug() debuglink = wirelink.find_debug()
client = TrezorClientDebugLink(wirelink) client = TrezorClientDebugLink(wirelink)
client.set_debuglink(debuglink) client.set_debuglink(debuglink)
client.set_tx_api(coins.tx_api['Bitcoin']) client.set_tx_api(coins.tx_api["Bitcoin"])
client.wipe_device() client.wipe_device()
client.transport.session_begin() client.transport.session_begin()
@ -62,29 +62,41 @@ def client():
client.close() client.close()
def setup_client(mnemonic=None, pin='', passphrase=False): def setup_client(mnemonic=None, pin="", passphrase=False):
if mnemonic is None: if mnemonic is None:
mnemonic = ' '.join(['all'] * 12) mnemonic = " ".join(["all"] * 12)
if pin is True: if pin is True:
pin = '1234' pin = "1234"
def client_decorator(function): def client_decorator(function):
@functools.wraps(function) @functools.wraps(function)
def wrapper(client, *args, **kwargs): def wrapper(client, *args, **kwargs):
client.load_device_by_mnemonic(mnemonic=mnemonic, pin=pin, passphrase_protection=passphrase, label='test', language='english') client.load_device_by_mnemonic(
mnemonic=mnemonic,
pin=pin,
passphrase_protection=passphrase,
label="test",
language="english",
)
return function(client, *args, **kwargs) return function(client, *args, **kwargs)
return wrapper return wrapper
return client_decorator return client_decorator
def pytest_configure(config): def pytest_configure(config):
if config.getoption('verbose'): if config.getoption("verbose"):
log.enable_debug_output() 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 tests that are marked as xfail",
"args",
[],
)
def pytest_runtest_setup(item): def pytest_runtest_setup(item):
@ -105,7 +117,8 @@ def pytest_runtest_setup(item):
pytest.skip("Test excluded on Trezor 1") pytest.skip("Test excluded on Trezor 1")
xfail = item.get_marker("xfail") xfail = item.get_marker("xfail")
run_xfail = any(item.get_marker(marker) for marker in item.config.getini("run_xfail")) runxfail_markers = item.config.getini("run_xfail")
run_xfail = any(item.get_marker(marker) for marker in runxfail_markers)
if xfail and run_xfail: if xfail and run_xfail:
# Deep hack: pytest's private _evalxfail helper determines whether the test should xfail or not. # Deep hack: pytest's private _evalxfail helper determines whether the test should xfail or not.
# The helper caches its result even before this hook runs. # The helper caches its result even before this hook runs.

View File

@ -14,22 +14,20 @@
# You should have received a copy of the License along with this library. # You should have received a copy of the License along with this library.
# If not, see <https://www.gnu.org/licenses/lgpl-3.0.html>. # If not, see <https://www.gnu.org/licenses/lgpl-3.0.html>.
from .common import TrezorTest from trezorlib import device, messages
from trezorlib import messages from .common import TrezorTest
from trezorlib import device
class TestBasic(TrezorTest): class TestBasic(TrezorTest):
def test_features(self): def test_features(self):
f0 = self.client.features f0 = self.client.features
f1 = self.client.call(messages.Initialize()) f1 = self.client.call(messages.Initialize())
assert f0 == f1 assert f0 == f1
def test_ping(self): def test_ping(self):
ping = self.client.call(messages.Ping(message='ahoj!')) ping = self.client.call(messages.Ping(message="ahoj!"))
assert ping == messages.Success(message='ahoj!') assert ping == messages.Success(message="ahoj!")
def test_device_id_same(self): def test_device_id_same(self):
id1 = self.client.get_device_id() id1 = self.client.get_device_id()

View File

@ -15,24 +15,24 @@
# If not, see <https://www.gnu.org/licenses/lgpl-3.0.html>. # If not, see <https://www.gnu.org/licenses/lgpl-3.0.html>.
import time import time
import pytest import pytest
from trezorlib import btc
from trezorlib.tools import H_
from .common import TrezorTest from .common import TrezorTest
from trezorlib.tools import H_
from trezorlib import btc
class TestBip32Speed(TrezorTest): class TestBip32Speed(TrezorTest):
def test_public_ckd(self): def test_public_ckd(self):
self.setup_mnemonic_nopin_nopassphrase() self.setup_mnemonic_nopin_nopassphrase()
btc.get_address(self.client, 'Bitcoin', []) # to compute root node via BIP39 btc.get_address(self.client, "Bitcoin", []) # to compute root node via BIP39
for depth in range(8): for depth in range(8):
start = time.time() start = time.time()
btc.get_address(self.client, 'Bitcoin', range(depth)) btc.get_address(self.client, "Bitcoin", range(depth))
delay = time.time() - start delay = time.time() - start
expected = (depth + 1) * 0.26 expected = (depth + 1) * 0.26
print("DEPTH", depth, "EXPECTED DELAY", expected, "REAL DELAY", delay) print("DEPTH", depth, "EXPECTED DELAY", expected, "REAL DELAY", delay)
@ -41,12 +41,12 @@ class TestBip32Speed(TrezorTest):
def test_private_ckd(self): def test_private_ckd(self):
self.setup_mnemonic_nopin_nopassphrase() self.setup_mnemonic_nopin_nopassphrase()
btc.get_address(self.client, 'Bitcoin', []) # to compute root node via BIP39 btc.get_address(self.client, "Bitcoin", []) # to compute root node via BIP39
for depth in range(8): for depth in range(8):
start = time.time() start = time.time()
address_n = [H_(-i) for i in range(-depth, 0)] address_n = [H_(-i) for i in range(-depth, 0)]
btc.get_address(self.client, 'Bitcoin', address_n) btc.get_address(self.client, "Bitcoin", address_n)
delay = time.time() - start delay = time.time() - start
expected = (depth + 1) * 0.26 expected = (depth + 1) * 0.26
print("DEPTH", depth, "EXPECTED DELAY", expected, "REAL DELAY", delay) print("DEPTH", depth, "EXPECTED DELAY", expected, "REAL DELAY", delay)
@ -58,12 +58,12 @@ class TestBip32Speed(TrezorTest):
start = time.time() start = time.time()
for x in range(10): for x in range(10):
btc.get_address(self.client, 'Bitcoin', [x, 2, 3, 4, 5, 6, 7, 8]) btc.get_address(self.client, "Bitcoin", [x, 2, 3, 4, 5, 6, 7, 8])
nocache_time = time.time() - start nocache_time = time.time() - start
start = time.time() start = time.time()
for x in range(10): for x in range(10):
btc.get_address(self.client, 'Bitcoin', [1, 2, 3, 4, 5, 6, 7, x]) btc.get_address(self.client, "Bitcoin", [1, 2, 3, 4, 5, 6, 7, x])
cache_time = time.time() - start cache_time = time.time() - start
print("NOCACHE TIME", nocache_time) print("NOCACHE TIME", nocache_time)

View File

@ -16,20 +16,24 @@
import pytest import pytest
from .conftest import setup_client
import trezorlib.messages as m import trezorlib.messages as m
from .conftest import setup_client
@setup_client() @setup_client()
@pytest.mark.parametrize("message", [ @pytest.mark.parametrize(
m.Ping(message="hello", button_protection=True), "message",
m.GetAddress( [
address_n=[0], m.Ping(message="hello", button_protection=True),
coin_name="Bitcoin", m.GetAddress(
script_type=m.InputScriptType.SPENDADDRESS, address_n=[0],
show_display=True coin_name="Bitcoin",
), script_type=m.InputScriptType.SPENDADDRESS,
]) show_display=True,
),
],
)
def test_cancel_message_via_cancel(client, message): def test_cancel_message_via_cancel(client, message):
resp = client.call_raw(message) resp = client.call_raw(message)
assert isinstance(resp, m.ButtonRequest) assert isinstance(resp, m.ButtonRequest)
@ -44,15 +48,18 @@ def test_cancel_message_via_cancel(client, message):
@setup_client() @setup_client()
@pytest.mark.parametrize("message", [ @pytest.mark.parametrize(
m.Ping(message="hello", button_protection=True), "message",
m.GetAddress( [
address_n=[0], m.Ping(message="hello", button_protection=True),
coin_name="Bitcoin", m.GetAddress(
script_type=m.InputScriptType.SPENDADDRESS, address_n=[0],
show_display=True coin_name="Bitcoin",
), script_type=m.InputScriptType.SPENDADDRESS,
]) show_display=True,
),
],
)
def test_cancel_message_via_initialize(client, message): def test_cancel_message_via_initialize(client, message):
resp = client.call_raw(message) resp = client.call_raw(message)
assert isinstance(resp, m.ButtonRequest) assert isinstance(resp, m.ButtonRequest)

View File

@ -14,22 +14,22 @@
# You should have received a copy of the License along with this library. # You should have received a copy of the License along with this library.
# If not, see <https://www.gnu.org/licenses/lgpl-3.0.html>. # If not, see <https://www.gnu.org/licenses/lgpl-3.0.html>.
import pytest
from hashlib import sha256 from hashlib import sha256
from .common import TrezorTest import pytest
from trezorlib import cosi
from trezorlib import cosi
from trezorlib.tools import parse_path from trezorlib.tools import parse_path
from .common import TrezorTest
@pytest.mark.skip_t2 @pytest.mark.skip_t2
class TestCosi(TrezorTest): class TestCosi(TrezorTest):
def test_cosi_commit(self): def test_cosi_commit(self):
self.setup_mnemonic_pin_passphrase() self.setup_mnemonic_pin_passphrase()
digest = sha256(b'this is a message').digest() digest = sha256(b"this is a message").digest()
c0 = cosi.commit(self.client, parse_path("10018'/0'"), digest) c0 = cosi.commit(self.client, parse_path("10018'/0'"), digest)
c1 = cosi.commit(self.client, parse_path("10018'/1'"), digest) c1 = cosi.commit(self.client, parse_path("10018'/1'"), digest)
@ -43,7 +43,7 @@ class TestCosi(TrezorTest):
assert c0.commitment != c2.commitment assert c0.commitment != c2.commitment
assert c1.commitment != c2.commitment assert c1.commitment != c2.commitment
digestb = sha256(b'this is a different message').digest() digestb = sha256(b"this is a different message").digest()
c0b = cosi.commit(self.client, parse_path("10018'/0'"), digestb) c0b = cosi.commit(self.client, parse_path("10018'/0'"), digestb)
c1b = cosi.commit(self.client, parse_path("10018'/1'"), digestb) c1b = cosi.commit(self.client, parse_path("10018'/1'"), digestb)
@ -60,7 +60,7 @@ class TestCosi(TrezorTest):
def test_cosi_sign(self): def test_cosi_sign(self):
self.setup_mnemonic_pin_passphrase() self.setup_mnemonic_pin_passphrase()
digest = sha256(b'this is a message').digest() digest = sha256(b"this is a message").digest()
c0 = cosi.commit(self.client, parse_path("10018'/0'"), digest) c0 = cosi.commit(self.client, parse_path("10018'/0'"), digest)
c1 = cosi.commit(self.client, parse_path("10018'/1'"), digest) c1 = cosi.commit(self.client, parse_path("10018'/1'"), digest)
@ -69,29 +69,37 @@ class TestCosi(TrezorTest):
global_pk = cosi.combine_keys([c0.pubkey, c1.pubkey, c2.pubkey]) global_pk = cosi.combine_keys([c0.pubkey, c1.pubkey, c2.pubkey])
global_R = cosi.combine_keys([c0.commitment, c1.commitment, c2.commitment]) global_R = cosi.combine_keys([c0.commitment, c1.commitment, c2.commitment])
# fmt: off
sig0 = cosi.sign(self.client, parse_path("10018'/0'"), digest, global_R, global_pk) sig0 = cosi.sign(self.client, parse_path("10018'/0'"), digest, global_R, global_pk)
sig1 = cosi.sign(self.client, parse_path("10018'/1'"), digest, global_R, global_pk) sig1 = cosi.sign(self.client, parse_path("10018'/1'"), digest, global_R, global_pk)
sig2 = cosi.sign(self.client, parse_path("10018'/2'"), digest, global_R, global_pk) sig2 = cosi.sign(self.client, parse_path("10018'/2'"), digest, global_R, global_pk)
# fmt: on
sig = cosi.combine_sig(global_R, [sig0.signature, sig1.signature, sig2.signature]) sig = cosi.combine_sig(
global_R, [sig0.signature, sig1.signature, sig2.signature]
)
cosi.verify(sig, digest, global_pk) cosi.verify(sig, digest, global_pk)
def test_cosi_compat(self): def test_cosi_compat(self):
self.setup_mnemonic_pin_passphrase() self.setup_mnemonic_pin_passphrase()
digest = sha256(b'this is not a pipe').digest() digest = sha256(b"this is not a pipe").digest()
remote_commit = cosi.commit(self.client, parse_path("10018'/0'"), digest) remote_commit = cosi.commit(self.client, parse_path("10018'/0'"), digest)
local_privkey = sha256(b'private key').digest()[:32] local_privkey = sha256(b"private key").digest()[:32]
local_pubkey = cosi.pubkey_from_privkey(local_privkey) local_pubkey = cosi.pubkey_from_privkey(local_privkey)
local_nonce, local_commitment = cosi.get_nonce(local_privkey, digest, 42) local_nonce, local_commitment = cosi.get_nonce(local_privkey, digest, 42)
global_pk = cosi.combine_keys([remote_commit.pubkey, local_pubkey]) global_pk = cosi.combine_keys([remote_commit.pubkey, local_pubkey])
global_R = cosi.combine_keys([remote_commit.commitment, local_commitment]) global_R = cosi.combine_keys([remote_commit.commitment, local_commitment])
remote_sig = cosi.sign(self.client, parse_path("10018'/0'"), digest, global_R, global_pk) remote_sig = cosi.sign(
local_sig = cosi.sign_with_privkey(digest, local_privkey, global_pk, local_nonce, global_R) self.client, 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]) sig = cosi.combine_sig(global_R, [remote_sig.signature, local_sig])
cosi.verify(sig, digest, global_pk) cosi.verify(sig, digest, global_pk)

View File

@ -16,13 +16,13 @@
import pytest import pytest
from .common import TrezorTest
from trezorlib import messages as proto from trezorlib import messages as proto
from .common import TrezorTest
@pytest.mark.skip_t2 @pytest.mark.skip_t2
class TestDebuglink(TrezorTest): class TestDebuglink(TrezorTest):
def test_layout(self): def test_layout(self):
layout = self.client.debug.read_layout() layout = self.client.debug.read_layout()
assert len(layout) == 1024 assert len(layout) == 1024
@ -36,12 +36,12 @@ class TestDebuglink(TrezorTest):
self.setup_mnemonic_pin_passphrase() self.setup_mnemonic_pin_passphrase()
# Manually trigger PinMatrixRequest # Manually trigger PinMatrixRequest
resp = self.client.call_raw(proto.Ping(message='test', pin_protection=True)) resp = self.client.call_raw(proto.Ping(message="test", pin_protection=True))
assert isinstance(resp, proto.PinMatrixRequest) assert isinstance(resp, proto.PinMatrixRequest)
pin = self.client.debug.read_pin() pin = self.client.debug.read_pin()
assert pin[0] == '1234' assert pin[0] == "1234"
assert pin[1] != '' assert pin[1] != ""
pin_encoded = self.client.debug.read_pin_encoded() pin_encoded = self.client.debug.read_pin_encoded()
resp = self.client.call_raw(proto.PinMatrixAck(pin=pin_encoded)) resp = self.client.call_raw(proto.PinMatrixAck(pin=pin_encoded))

View File

@ -14,45 +14,52 @@
# You should have received a copy of the License along with this library. # You should have received a copy of the License along with this library.
# If not, see <https://www.gnu.org/licenses/lgpl-3.0.html>. # If not, see <https://www.gnu.org/licenses/lgpl-3.0.html>.
import time
import pytest import pytest
from trezorlib import device, messages as proto
from .common import TrezorTest from .common import TrezorTest
import time
from trezorlib import messages as proto
from trezorlib import device
class TestMsgApplysettings(TrezorTest): class TestMsgApplysettings(TrezorTest):
def test_apply_settings(self): def test_apply_settings(self):
self.setup_mnemonic_pin_passphrase() self.setup_mnemonic_pin_passphrase()
assert self.client.features.label == 'test' assert self.client.features.label == "test"
with self.client: with self.client:
self.client.set_expected_responses([proto.PinMatrixRequest(), self.client.set_expected_responses(
proto.ButtonRequest(), [
proto.Success(), proto.PinMatrixRequest(),
proto.Features()]) proto.ButtonRequest(),
proto.Success(),
proto.Features(),
]
)
if self.client.features.major_version >= 2: if self.client.features.major_version >= 2:
self.client.expected_responses.pop(0) # skip PinMatrixRequest self.client.expected_responses.pop(0) # skip PinMatrixRequest
device.apply_settings(self.client, label='new label') device.apply_settings(self.client, label="new label")
assert self.client.features.label == 'new label' assert self.client.features.label == "new label"
@pytest.mark.skip_t2 @pytest.mark.skip_t2
def test_invalid_language(self): def test_invalid_language(self):
self.setup_mnemonic_pin_passphrase() self.setup_mnemonic_pin_passphrase()
assert self.client.features.language == 'english' assert self.client.features.language == "english"
with self.client: with self.client:
self.client.set_expected_responses([proto.PinMatrixRequest(), self.client.set_expected_responses(
proto.ButtonRequest(), [
proto.Success(), proto.PinMatrixRequest(),
proto.Features()]) proto.ButtonRequest(),
device.apply_settings(self.client, language='nonexistent') proto.Success(),
proto.Features(),
]
)
device.apply_settings(self.client, language="nonexistent")
assert self.client.features.language == 'english' assert self.client.features.language == "english"
def test_apply_settings_passphrase(self): def test_apply_settings_passphrase(self):
self.setup_mnemonic_pin_nopassphrase() self.setup_mnemonic_pin_nopassphrase()
@ -60,10 +67,14 @@ class TestMsgApplysettings(TrezorTest):
assert self.client.features.passphrase_protection is False assert self.client.features.passphrase_protection is False
with self.client: with self.client:
self.client.set_expected_responses([proto.PinMatrixRequest(), self.client.set_expected_responses(
proto.ButtonRequest(), [
proto.Success(), proto.PinMatrixRequest(),
proto.Features()]) proto.ButtonRequest(),
proto.Success(),
proto.Features(),
]
)
if self.client.features.major_version >= 2: if self.client.features.major_version >= 2:
self.client.expected_responses.pop(0) # skip PinMatrixRequest self.client.expected_responses.pop(0) # skip PinMatrixRequest
device.apply_settings(self.client, use_passphrase=True) device.apply_settings(self.client, use_passphrase=True)
@ -71,17 +82,17 @@ class TestMsgApplysettings(TrezorTest):
assert self.client.features.passphrase_protection is True assert self.client.features.passphrase_protection is True
with self.client: with self.client:
self.client.set_expected_responses([proto.ButtonRequest(), self.client.set_expected_responses(
proto.Success(), [proto.ButtonRequest(), proto.Success(), proto.Features()]
proto.Features()]) )
device.apply_settings(self.client, use_passphrase=False) device.apply_settings(self.client, use_passphrase=False)
assert self.client.features.passphrase_protection is False assert self.client.features.passphrase_protection is False
with self.client: with self.client:
self.client.set_expected_responses([proto.ButtonRequest(), self.client.set_expected_responses(
proto.Success(), [proto.ButtonRequest(), proto.Success(), proto.Features()]
proto.Features()]) )
device.apply_settings(self.client, use_passphrase=True) device.apply_settings(self.client, use_passphrase=True)
assert self.client.features.passphrase_protection is True assert self.client.features.passphrase_protection is True
@ -93,10 +104,14 @@ class TestMsgApplysettings(TrezorTest):
img = b'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"\x00\x00\x00\x00\x04\x80\x00\x00\x00\x00\x00\x00\x00\x00\x04\x88\x02\x00\x00\x00\x02\x91\x00\x00\x00\x00\x00\x00\x80\x00\x00\x00\x00\x90@\x00\x11@\x00\x00\x00\x00\x00\x00\x08\x00\x10\x92\x12\x04\x00\x00\x05\x12D\x00\x00\x00\x00\x00 \x00\x00\x08\x00Q\x00\x00\x02\xc0\x00\x00\x00\x00\x00\x00\x00\x10\x02 \x01\x04J\x00)$\x00\x00\x00\x00\x80\x00\x00\x00\x00\x08\x10\xa1\x00\x00\x02\x81 \x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x08\x00\x00\tP\x00\x00\x00\x00\x00\x00 \x00\x00\xa0\x00\xa0R \x12\x84\x80\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\t\x08\x00\tP\x00\x00\x00\x00 \x00\x04 \x00\x80\x02\x00@\x02T\xc2 \x00\x00\x00\x00\x00\x00\x00\x10@\x00)\t@\n\xa0\x80\x00\x00\x00\x00\x00\x00\x00\x00\x10\x00\x80@\x14\xa9H\x04\x00\x00\x88@\x00\x00\x00\x00\x00\x02\x02$\x00\x15B@\x00\nP\x00\x00\x00\x00\x00\x80\x00\x00\x91\x01UP\x00\x00 \x02\x00\x00\x00\x00\x00\x00\x02\x08@ Z\xa5 \x00\x00\x80\x00\x00\x00\x00\x00\x00\x08\xa1%\x14*\xa0\x00\x00\x02\x08\x00\x00\x00\x00\x00\x00\x00\x00\x00@\xaa\x91 \x00\x05E\x80\x00\x00\x00\x00\x00\x02*T\x05-D\x00\x00\x05 @\x00\x00\x00\x00\x00%@\x80\x11V\xa0\x88\x00\x05@\xb0\x00\x00\x00\x00\x00\x818$\x04\xabD \x00\x06\xa1T\x00\x00\x00\x00\x02\x03\xb8\x01R\xd5\x01\x00\x00\x05AP\x00\x00\x00\x00\x08\xadT\x00\x05j\xa4@\x00\x87ah\x00\x00\x00\x00\x02\x8d\xb8\x08\x00.\x01\x00\x00\x02\xa5\xa8\x10\x00\x00\x00*\xc1\xec \n\xaa\x88 \x02@\xf6\xd0\x02\x00\x00\x00\x0bB\xb6\x14@U"\x80\x00\x01{`\x00\x00\x00\x00M\xa3\xf8 \x15*\x00\x00\x00\x10n\xc0\x04\x00\x00\x02\x06\xc2\xa8)\x00\x96\x84\x80\x00\x00\x1b\x00\x00\x80@\x10\x87\xa7\xf0\x84\x10\xaa\x10\x00\x00D\x00\x00\x02 \x00\x8a\x06\xfa\xe0P\n-\x02@\x00\x12\x00\x00\x00\x00\x10@\x83\xdf\xa0\x00\x08\xaa@\x00\x00\x01H\x00\x05H\x04\x12\x01\xf7\x81P\x02T\t\x00\x00\x00 \x00\x00\x84\x10\x00\x00z\x00@)* \x00\x00\x01\n\xa0\x02 \x05\n\x00\x00\x05\x10\x84\xa8\x84\x80\x00\x00@\x14\x00\x92\x10\x80\x00\x04\x11@\tT\x00\x00\x00\x00\n@\x00\x08\x84@$\x00H\x00\x12Q\x02\x00\x00\x00\x00\x90\x02A\x12\xa8\n\xaa\x92\x10\x04\xa8\x10@\x00\x00\x04\x04\x00\x04I\x00\x04\x14H\x80"R\x01\x00\x00\x00!@\x00\x00$\xa0EB\x80\x08\x95hH\x00\x00\x00\x84\x10 \x05Z\x00\x00(\x00\x02\x00\xa1\x01\x00\x00\x04\x00@\x82\x00\xadH*\x92P\x00\xaaP\x00\x00\x00\x00\x11\x02\x01*\xad\x01\x00\x01\x01"\x11D\x08\x00\x00\x10\x80 \x00\x81W\x80J\x94\x04\x08\xa5 !\x00\x00\x00\x02\x00B*\xae\xa1\x00\x80\x10\x01\x08\xa4\x00\x00\x00\x00\x00\x84\x00\t[@"HA\x04E\x00\x84\x00\x00\x00\x10\x00\x01J\xd5\x82\x90\x02\x00!\x02\xa2\x00\x00\x00\x00\x00\x00\x00\x05~\xa0\x00 \x10\n)\x00\x11\x00\x00\x00\x00\x00\x00!U\x80\xa8\x88\x82\x80\x01\x00\x00\x00\x00\x00\x00H@\x11\xaa\xc0\x82\x00 *\n\x00\x00\x00\x00\x00\x00\x00\x00\n\xabb@ \x04\x00! \x84\x00\x00\x00\x00\x02@\xa5\x15A$\x04\x81(\n\x00\x00\x00\x00\x00\x00 \x01\x10\x02\xe0\x91\x02\x00\x00\x04\x00\x00\x00\x00\x00\x00\x01 \xa9\tQH@\x91 P\x00\x00\x00\x00\x00\x00\x08\x00\x00\xa0T\xa5\x00@\x80\x08\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"\x00\x00\x00\x00\xa2\x00\x00\x00\x00\x00\x00\x00\x08\x00\x00 T\xa0\t\x00\x08\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x02\x00\x00@\x02\xa0\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00*\x10\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x02\x00\x00\x10\x00\x00\x10\x02\x80\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\t\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x08\x00\x00@\x04\x80\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00@\x00\x00\x00\x02\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x02\x00\x00\x08@\x10\x00\x00\x00\x00' img = b'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"\x00\x00\x00\x00\x04\x80\x00\x00\x00\x00\x00\x00\x00\x00\x04\x88\x02\x00\x00\x00\x02\x91\x00\x00\x00\x00\x00\x00\x80\x00\x00\x00\x00\x90@\x00\x11@\x00\x00\x00\x00\x00\x00\x08\x00\x10\x92\x12\x04\x00\x00\x05\x12D\x00\x00\x00\x00\x00 \x00\x00\x08\x00Q\x00\x00\x02\xc0\x00\x00\x00\x00\x00\x00\x00\x10\x02 \x01\x04J\x00)$\x00\x00\x00\x00\x80\x00\x00\x00\x00\x08\x10\xa1\x00\x00\x02\x81 \x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x08\x00\x00\tP\x00\x00\x00\x00\x00\x00 \x00\x00\xa0\x00\xa0R \x12\x84\x80\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\t\x08\x00\tP\x00\x00\x00\x00 \x00\x04 \x00\x80\x02\x00@\x02T\xc2 \x00\x00\x00\x00\x00\x00\x00\x10@\x00)\t@\n\xa0\x80\x00\x00\x00\x00\x00\x00\x00\x00\x10\x00\x80@\x14\xa9H\x04\x00\x00\x88@\x00\x00\x00\x00\x00\x02\x02$\x00\x15B@\x00\nP\x00\x00\x00\x00\x00\x80\x00\x00\x91\x01UP\x00\x00 \x02\x00\x00\x00\x00\x00\x00\x02\x08@ Z\xa5 \x00\x00\x80\x00\x00\x00\x00\x00\x00\x08\xa1%\x14*\xa0\x00\x00\x02\x08\x00\x00\x00\x00\x00\x00\x00\x00\x00@\xaa\x91 \x00\x05E\x80\x00\x00\x00\x00\x00\x02*T\x05-D\x00\x00\x05 @\x00\x00\x00\x00\x00%@\x80\x11V\xa0\x88\x00\x05@\xb0\x00\x00\x00\x00\x00\x818$\x04\xabD \x00\x06\xa1T\x00\x00\x00\x00\x02\x03\xb8\x01R\xd5\x01\x00\x00\x05AP\x00\x00\x00\x00\x08\xadT\x00\x05j\xa4@\x00\x87ah\x00\x00\x00\x00\x02\x8d\xb8\x08\x00.\x01\x00\x00\x02\xa5\xa8\x10\x00\x00\x00*\xc1\xec \n\xaa\x88 \x02@\xf6\xd0\x02\x00\x00\x00\x0bB\xb6\x14@U"\x80\x00\x01{`\x00\x00\x00\x00M\xa3\xf8 \x15*\x00\x00\x00\x10n\xc0\x04\x00\x00\x02\x06\xc2\xa8)\x00\x96\x84\x80\x00\x00\x1b\x00\x00\x80@\x10\x87\xa7\xf0\x84\x10\xaa\x10\x00\x00D\x00\x00\x02 \x00\x8a\x06\xfa\xe0P\n-\x02@\x00\x12\x00\x00\x00\x00\x10@\x83\xdf\xa0\x00\x08\xaa@\x00\x00\x01H\x00\x05H\x04\x12\x01\xf7\x81P\x02T\t\x00\x00\x00 \x00\x00\x84\x10\x00\x00z\x00@)* \x00\x00\x01\n\xa0\x02 \x05\n\x00\x00\x05\x10\x84\xa8\x84\x80\x00\x00@\x14\x00\x92\x10\x80\x00\x04\x11@\tT\x00\x00\x00\x00\n@\x00\x08\x84@$\x00H\x00\x12Q\x02\x00\x00\x00\x00\x90\x02A\x12\xa8\n\xaa\x92\x10\x04\xa8\x10@\x00\x00\x04\x04\x00\x04I\x00\x04\x14H\x80"R\x01\x00\x00\x00!@\x00\x00$\xa0EB\x80\x08\x95hH\x00\x00\x00\x84\x10 \x05Z\x00\x00(\x00\x02\x00\xa1\x01\x00\x00\x04\x00@\x82\x00\xadH*\x92P\x00\xaaP\x00\x00\x00\x00\x11\x02\x01*\xad\x01\x00\x01\x01"\x11D\x08\x00\x00\x10\x80 \x00\x81W\x80J\x94\x04\x08\xa5 !\x00\x00\x00\x02\x00B*\xae\xa1\x00\x80\x10\x01\x08\xa4\x00\x00\x00\x00\x00\x84\x00\t[@"HA\x04E\x00\x84\x00\x00\x00\x10\x00\x01J\xd5\x82\x90\x02\x00!\x02\xa2\x00\x00\x00\x00\x00\x00\x00\x05~\xa0\x00 \x10\n)\x00\x11\x00\x00\x00\x00\x00\x00!U\x80\xa8\x88\x82\x80\x01\x00\x00\x00\x00\x00\x00H@\x11\xaa\xc0\x82\x00 *\n\x00\x00\x00\x00\x00\x00\x00\x00\n\xabb@ \x04\x00! \x84\x00\x00\x00\x00\x02@\xa5\x15A$\x04\x81(\n\x00\x00\x00\x00\x00\x00 \x01\x10\x02\xe0\x91\x02\x00\x00\x04\x00\x00\x00\x00\x00\x00\x01 \xa9\tQH@\x91 P\x00\x00\x00\x00\x00\x00\x08\x00\x00\xa0T\xa5\x00@\x80\x08\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"\x00\x00\x00\x00\xa2\x00\x00\x00\x00\x00\x00\x00\x08\x00\x00 T\xa0\t\x00\x08\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x02\x00\x00@\x02\xa0\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00*\x10\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x02\x00\x00\x10\x00\x00\x10\x02\x80\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\t\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x08\x00\x00@\x04\x80\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00@\x00\x00\x00\x02\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x02\x00\x00\x08@\x10\x00\x00\x00\x00'
with self.client: with self.client:
self.client.set_expected_responses([proto.PinMatrixRequest(), self.client.set_expected_responses(
proto.ButtonRequest(), [
proto.Success(), proto.PinMatrixRequest(),
proto.Features()]) proto.ButtonRequest(),
proto.Success(),
proto.Features(),
]
)
device.apply_settings(self.client, homescreen=img) device.apply_settings(self.client, homescreen=img)
@pytest.mark.skip_t2 @pytest.mark.skip_t2
@ -104,23 +119,28 @@ class TestMsgApplysettings(TrezorTest):
self.setup_mnemonic_pin_passphrase() self.setup_mnemonic_pin_passphrase()
with self.client: with self.client:
self.client.set_expected_responses([proto.PinMatrixRequest(), self.client.set_expected_responses(
proto.ButtonRequest(), [
proto.Success(), proto.PinMatrixRequest(),
proto.Features()]) proto.ButtonRequest(),
proto.Success(),
proto.Features(),
]
)
device.apply_settings(self.client, auto_lock_delay_ms=int(10e3)) # 10 secs device.apply_settings(self.client, auto_lock_delay_ms=int(10e3)) # 10 secs
time.sleep(0.1) # sleep less than auto-lock delay time.sleep(0.1) # sleep less than auto-lock delay
with self.client: with self.client:
# No PIN protection is required. # No PIN protection is required.
self.client.set_expected_responses([proto.Success()]) self.client.set_expected_responses([proto.Success()])
self.client.ping(msg='', pin_protection=True) self.client.ping(msg="", pin_protection=True)
time.sleep(10.1) # sleep more than auto-lock delay time.sleep(10.1) # sleep more than auto-lock delay
with self.client: with self.client:
self.client.set_expected_responses([proto.PinMatrixRequest(), self.client.set_expected_responses(
proto.Success()]) [proto.PinMatrixRequest(), proto.Success()]
self.client.ping(msg='', pin_protection=True) )
self.client.ping(msg="", pin_protection=True)
@pytest.mark.skip_t2 @pytest.mark.skip_t2
def test_apply_minimal_auto_lock_delay(self): def test_apply_minimal_auto_lock_delay(self):
@ -131,10 +151,14 @@ class TestMsgApplysettings(TrezorTest):
self.setup_mnemonic_pin_passphrase() self.setup_mnemonic_pin_passphrase()
with self.client: with self.client:
self.client.set_expected_responses([proto.PinMatrixRequest(), self.client.set_expected_responses(
proto.ButtonRequest(), [
proto.Success(), proto.PinMatrixRequest(),
proto.Features()]) proto.ButtonRequest(),
proto.Success(),
proto.Features(),
]
)
# Note: the actual delay will be 10 secs (see above). # Note: the actual delay will be 10 secs (see above).
device.apply_settings(self.client, auto_lock_delay_ms=int(1e3)) device.apply_settings(self.client, auto_lock_delay_ms=int(1e3))
@ -142,16 +166,17 @@ class TestMsgApplysettings(TrezorTest):
with self.client: with self.client:
# No PIN protection is required. # No PIN protection is required.
self.client.set_expected_responses([proto.Success()]) self.client.set_expected_responses([proto.Success()])
self.client.ping(msg='', pin_protection=True) self.client.ping(msg="", pin_protection=True)
time.sleep(2) # sleep less than the minimal auto-lock delay time.sleep(2) # sleep less than the minimal auto-lock delay
with self.client: with self.client:
# No PIN protection is required. # No PIN protection is required.
self.client.set_expected_responses([proto.Success()]) self.client.set_expected_responses([proto.Success()])
self.client.ping(msg='', pin_protection=True) self.client.ping(msg="", pin_protection=True)
time.sleep(10.1) # sleep more than the minimal auto-lock delay time.sleep(10.1) # sleep more than the minimal auto-lock delay
with self.client: with self.client:
self.client.set_expected_responses([proto.PinMatrixRequest(), self.client.set_expected_responses(
proto.Success()]) [proto.PinMatrixRequest(), proto.Success()]
self.client.ping(msg='', pin_protection=True) )
self.client.ping(msg="", pin_protection=True)

View File

@ -16,14 +16,13 @@
import pytest import pytest
from .common import TrezorTest
from trezorlib import messages as proto from trezorlib import messages as proto
from .common import TrezorTest
@pytest.mark.skip_t2 @pytest.mark.skip_t2
class TestMsgChangepin(TrezorTest): class TestMsgChangepin(TrezorTest):
def test_set_pin(self): def test_set_pin(self):
self.setup_mnemonic_nopin_nopassphrase() self.setup_mnemonic_nopin_nopassphrase()
features = self.client.call_raw(proto.Initialize()) features = self.client.call_raw(proto.Initialize())
@ -206,7 +205,7 @@ class TestMsgChangepin(TrezorTest):
# Send the PIN for second time, but with typo # Send the PIN for second time, but with typo
assert isinstance(ret, proto.PinMatrixRequest) assert isinstance(ret, proto.PinMatrixRequest)
pin_encoded = self.client.debug.encode_pin(self.pin6 + '3') pin_encoded = self.client.debug.encode_pin(self.pin6 + "3")
ret = self.client.call_raw(proto.PinMatrixAck(pin=pin_encoded)) ret = self.client.call_raw(proto.PinMatrixAck(pin=pin_encoded))
# Now it should fail, because pins are different # Now it should fail, because pins are different

View File

@ -15,69 +15,173 @@
# If not, see <https://www.gnu.org/licenses/lgpl-3.0.html>. # If not, see <https://www.gnu.org/licenses/lgpl-3.0.html>.
from binascii import hexlify, unhexlify from binascii import hexlify, unhexlify
import pytest import pytest
from .common import TrezorTest
from trezorlib import misc from trezorlib import misc
from .common import TrezorTest
class TestMsgCipherkeyvalue(TrezorTest): class TestMsgCipherkeyvalue(TrezorTest):
def test_encrypt(self): def test_encrypt(self):
self.setup_mnemonic_nopin_nopassphrase() self.setup_mnemonic_nopin_nopassphrase()
# different ask values # different ask values
res = misc.encrypt_keyvalue(self.client, [0, 1, 2], b"test", b"testing message!", ask_on_encrypt=True, ask_on_decrypt=True) res = misc.encrypt_keyvalue(
assert hexlify(res) == b'676faf8f13272af601776bc31bc14e8f' self.client,
[0, 1, 2],
b"test",
b"testing message!",
ask_on_encrypt=True,
ask_on_decrypt=True,
)
assert hexlify(res) == b"676faf8f13272af601776bc31bc14e8f"
res = misc.encrypt_keyvalue(self.client, [0, 1, 2], b"test", b"testing message!", ask_on_encrypt=True, ask_on_decrypt=False) res = misc.encrypt_keyvalue(
assert hexlify(res) == b'5aa0fbcb9d7fa669880745479d80c622' self.client,
[0, 1, 2],
b"test",
b"testing message!",
ask_on_encrypt=True,
ask_on_decrypt=False,
)
assert hexlify(res) == b"5aa0fbcb9d7fa669880745479d80c622"
res = misc.encrypt_keyvalue(self.client, [0, 1, 2], b"test", b"testing message!", ask_on_encrypt=False, ask_on_decrypt=True) res = misc.encrypt_keyvalue(
assert hexlify(res) == b'958d4f63269b61044aaedc900c8d6208' self.client,
[0, 1, 2],
b"test",
b"testing message!",
ask_on_encrypt=False,
ask_on_decrypt=True,
)
assert hexlify(res) == b"958d4f63269b61044aaedc900c8d6208"
res = misc.encrypt_keyvalue(self.client, [0, 1, 2], b"test", b"testing message!", ask_on_encrypt=False, ask_on_decrypt=False) res = misc.encrypt_keyvalue(
assert hexlify(res) == b'e0cf0eb0425947000eb546cc3994bc6c' self.client,
[0, 1, 2],
b"test",
b"testing message!",
ask_on_encrypt=False,
ask_on_decrypt=False,
)
assert hexlify(res) == b"e0cf0eb0425947000eb546cc3994bc6c"
# different key # different key
res = misc.encrypt_keyvalue(self.client, [0, 1, 2], b"test2", b"testing message!", ask_on_encrypt=True, ask_on_decrypt=True) res = misc.encrypt_keyvalue(
assert hexlify(res) == b'de247a6aa6be77a134bb3f3f925f13af' self.client,
[0, 1, 2],
b"test2",
b"testing message!",
ask_on_encrypt=True,
ask_on_decrypt=True,
)
assert hexlify(res) == b"de247a6aa6be77a134bb3f3f925f13af"
# different message # different message
res = misc.encrypt_keyvalue(self.client, [0, 1, 2], b"test", b"testing message! it is different", ask_on_encrypt=True, ask_on_decrypt=True) res = misc.encrypt_keyvalue(
assert hexlify(res) == b'676faf8f13272af601776bc31bc14e8f3ae1c88536bf18f1b44f1e4c2c4a613d' self.client,
[0, 1, 2],
b"test",
b"testing message! it is different",
ask_on_encrypt=True,
ask_on_decrypt=True,
)
assert (
hexlify(res)
== b"676faf8f13272af601776bc31bc14e8f3ae1c88536bf18f1b44f1e4c2c4a613d"
)
# different path # different path
res = misc.encrypt_keyvalue(self.client, [0, 1, 3], b"test", b"testing message!", ask_on_encrypt=True, ask_on_decrypt=True) res = misc.encrypt_keyvalue(
assert hexlify(res) == b'b4811a9d492f5355a5186ddbfccaae7b' self.client,
[0, 1, 3],
b"test",
b"testing message!",
ask_on_encrypt=True,
ask_on_decrypt=True,
)
assert hexlify(res) == b"b4811a9d492f5355a5186ddbfccaae7b"
def test_decrypt(self): def test_decrypt(self):
self.setup_mnemonic_nopin_nopassphrase() self.setup_mnemonic_nopin_nopassphrase()
# different ask values # different ask values
res = misc.decrypt_keyvalue(self.client, [0, 1, 2], b"test", unhexlify("676faf8f13272af601776bc31bc14e8f"), ask_on_encrypt=True, ask_on_decrypt=True) res = misc.decrypt_keyvalue(
assert res == b'testing message!' self.client,
[0, 1, 2],
b"test",
unhexlify("676faf8f13272af601776bc31bc14e8f"),
ask_on_encrypt=True,
ask_on_decrypt=True,
)
assert res == b"testing message!"
res = misc.decrypt_keyvalue(self.client, [0, 1, 2], b"test", unhexlify("5aa0fbcb9d7fa669880745479d80c622"), ask_on_encrypt=True, ask_on_decrypt=False) res = misc.decrypt_keyvalue(
assert res == b'testing message!' self.client,
[0, 1, 2],
b"test",
unhexlify("5aa0fbcb9d7fa669880745479d80c622"),
ask_on_encrypt=True,
ask_on_decrypt=False,
)
assert res == b"testing message!"
res = misc.decrypt_keyvalue(self.client, [0, 1, 2], b"test", unhexlify("958d4f63269b61044aaedc900c8d6208"), ask_on_encrypt=False, ask_on_decrypt=True) res = misc.decrypt_keyvalue(
assert res == b'testing message!' self.client,
[0, 1, 2],
b"test",
unhexlify("958d4f63269b61044aaedc900c8d6208"),
ask_on_encrypt=False,
ask_on_decrypt=True,
)
assert res == b"testing message!"
res = misc.decrypt_keyvalue(self.client, [0, 1, 2], b"test", unhexlify("e0cf0eb0425947000eb546cc3994bc6c"), ask_on_encrypt=False, ask_on_decrypt=False) res = misc.decrypt_keyvalue(
assert res == b'testing message!' self.client,
[0, 1, 2],
b"test",
unhexlify("e0cf0eb0425947000eb546cc3994bc6c"),
ask_on_encrypt=False,
ask_on_decrypt=False,
)
assert res == b"testing message!"
# different key # different key
res = misc.decrypt_keyvalue(self.client, [0, 1, 2], b"test2", unhexlify("de247a6aa6be77a134bb3f3f925f13af"), ask_on_encrypt=True, ask_on_decrypt=True) res = misc.decrypt_keyvalue(
assert res == b'testing message!' self.client,
[0, 1, 2],
b"test2",
unhexlify("de247a6aa6be77a134bb3f3f925f13af"),
ask_on_encrypt=True,
ask_on_decrypt=True,
)
assert res == b"testing message!"
# different message # different message
res = misc.decrypt_keyvalue(self.client, [0, 1, 2], b"test", unhexlify("676faf8f13272af601776bc31bc14e8f3ae1c88536bf18f1b44f1e4c2c4a613d"), ask_on_encrypt=True, ask_on_decrypt=True) res = misc.decrypt_keyvalue(
assert res == b'testing message! it is different' self.client,
[0, 1, 2],
b"test",
unhexlify(
"676faf8f13272af601776bc31bc14e8f3ae1c88536bf18f1b44f1e4c2c4a613d"
),
ask_on_encrypt=True,
ask_on_decrypt=True,
)
assert res == b"testing message! it is different"
# different path # different path
res = misc.decrypt_keyvalue(self.client, [0, 1, 3], b"test", unhexlify("b4811a9d492f5355a5186ddbfccaae7b"), ask_on_encrypt=True, ask_on_decrypt=True) res = misc.decrypt_keyvalue(
assert res == b'testing message!' self.client,
[0, 1, 3],
b"test",
unhexlify("b4811a9d492f5355a5186ddbfccaae7b"),
ask_on_encrypt=True,
ask_on_decrypt=True,
)
assert res == b"testing message!"
def test_encrypt_badlen(self): def test_encrypt_badlen(self):
self.setup_mnemonic_nopin_nopassphrase() self.setup_mnemonic_nopin_nopassphrase()

View File

@ -16,38 +16,81 @@
import pytest import pytest
from .common import TrezorTest
from trezorlib import messages as proto from trezorlib import messages as proto
from .common import TrezorTest
@pytest.mark.skip_t2 @pytest.mark.skip_t2
class TestMsgClearsession(TrezorTest): class TestMsgClearsession(TrezorTest):
def test_clearsession(self): def test_clearsession(self):
self.setup_mnemonic_pin_passphrase() self.setup_mnemonic_pin_passphrase()
with self.client: with self.client:
self.client.set_expected_responses([proto.ButtonRequest(code=proto.ButtonRequestType.ProtectCall), proto.PinMatrixRequest(), proto.PassphraseRequest(), proto.Success()]) self.client.set_expected_responses(
res = self.client.ping('random data', button_protection=True, pin_protection=True, passphrase_protection=True) [
assert res == 'random data' proto.ButtonRequest(code=proto.ButtonRequestType.ProtectCall),
proto.PinMatrixRequest(),
proto.PassphraseRequest(),
proto.Success(),
]
)
res = self.client.ping(
"random data",
button_protection=True,
pin_protection=True,
passphrase_protection=True,
)
assert res == "random data"
with self.client: with self.client:
# pin and passphrase are cached # pin and passphrase are cached
self.client.set_expected_responses([proto.ButtonRequest(code=proto.ButtonRequestType.ProtectCall), proto.Success()]) self.client.set_expected_responses(
res = self.client.ping('random data', button_protection=True, pin_protection=True, passphrase_protection=True) [
assert res == 'random data' proto.ButtonRequest(code=proto.ButtonRequestType.ProtectCall),
proto.Success(),
]
)
res = self.client.ping(
"random data",
button_protection=True,
pin_protection=True,
passphrase_protection=True,
)
assert res == "random data"
self.client.clear_session() self.client.clear_session()
# session cache is cleared # session cache is cleared
with self.client: with self.client:
self.client.set_expected_responses([proto.ButtonRequest(code=proto.ButtonRequestType.ProtectCall), proto.PinMatrixRequest(), proto.PassphraseRequest(), proto.Success()]) self.client.set_expected_responses(
res = self.client.ping('random data', button_protection=True, pin_protection=True, passphrase_protection=True) [
assert res == 'random data' proto.ButtonRequest(code=proto.ButtonRequestType.ProtectCall),
proto.PinMatrixRequest(),
proto.PassphraseRequest(),
proto.Success(),
]
)
res = self.client.ping(
"random data",
button_protection=True,
pin_protection=True,
passphrase_protection=True,
)
assert res == "random data"
with self.client: with self.client:
# pin and passphrase are cached # pin and passphrase are cached
self.client.set_expected_responses([proto.ButtonRequest(code=proto.ButtonRequestType.ProtectCall), proto.Success()]) self.client.set_expected_responses(
res = self.client.ping('random data', button_protection=True, pin_protection=True, passphrase_protection=True) [
assert res == 'random data' proto.ButtonRequest(code=proto.ButtonRequestType.ProtectCall),
proto.Success(),
]
)
res = self.client.ping(
"random data",
button_protection=True,
pin_protection=True,
passphrase_protection=True,
)
assert res == "random data"

View File

@ -15,21 +15,36 @@
# If not, see <https://www.gnu.org/licenses/lgpl-3.0.html>. # If not, see <https://www.gnu.org/licenses/lgpl-3.0.html>.
from binascii import hexlify from binascii import hexlify
import pytest import pytest
from .common import TrezorTest
from trezorlib.tools import H_
from trezorlib import ethereum from trezorlib import ethereum
from trezorlib.tools import H_
from .common import TrezorTest
@pytest.mark.ethereum @pytest.mark.ethereum
class TestMsgEthereumGetaddress(TrezorTest): class TestMsgEthereumGetaddress(TrezorTest):
def test_ethereum_getaddress(self): def test_ethereum_getaddress(self):
self.setup_mnemonic_nopin_nopassphrase() self.setup_mnemonic_nopin_nopassphrase()
assert hexlify(ethereum.get_address(self.client, [])) == b'1d1c328764a41bda0492b66baa30c4a339ff85ef' assert (
assert hexlify(ethereum.get_address(self.client, [1])) == b'437207ca3cf43bf2e47dea0756d736c5df4f597a' hexlify(ethereum.get_address(self.client, []))
assert hexlify(ethereum.get_address(self.client, [0, H_(1)])) == b'e5d96dfa07bcf1a3ae43677840c31394258861bf' == b"1d1c328764a41bda0492b66baa30c4a339ff85ef"
assert hexlify(ethereum.get_address(self.client, [H_(9), 0])) == b'f68804ac9eca9483ab4241d3e4751590d2c05102' )
assert hexlify(ethereum.get_address(self.client, [0, 9999999])) == b'7a6366ecfcaf0d5dcc1539c171696c6cdd1eb8ed' assert (
hexlify(ethereum.get_address(self.client, [1]))
== b"437207ca3cf43bf2e47dea0756d736c5df4f597a"
)
assert (
hexlify(ethereum.get_address(self.client, [0, H_(1)]))
== b"e5d96dfa07bcf1a3ae43677840c31394258861bf"
)
assert (
hexlify(ethereum.get_address(self.client, [H_(9), 0]))
== b"f68804ac9eca9483ab4241d3e4751590d2c05102"
)
assert (
hexlify(ethereum.get_address(self.client, [0, 9999999]))
== b"7a6366ecfcaf0d5dcc1539c171696c6cdd1eb8ed"
)

View File

@ -15,20 +15,28 @@
# If not, see <https://www.gnu.org/licenses/lgpl-3.0.html>. # If not, see <https://www.gnu.org/licenses/lgpl-3.0.html>.
from binascii import hexlify from binascii import hexlify
import pytest import pytest
from .common import TrezorTest
from trezorlib import ethereum from trezorlib import ethereum
from .common import TrezorTest
@pytest.mark.ethereum @pytest.mark.ethereum
class TestMsgEthereumSignmessage(TrezorTest): class TestMsgEthereumSignmessage(TrezorTest):
PATH = [0] PATH = [0]
ADDRESS = b'cb3864960e8db1a751212c580af27ee8867d688f' ADDRESS = b"cb3864960e8db1a751212c580af27ee8867d688f"
VECTORS = [ VECTORS = [
('This is an example of a signed message.', b'b7837058907192dbc9427bf57d93a0acca3816c92927a08be573b785f2d72dab65dad9c92fbe03a358acdb455eab2107b869945d11f4e353d9cc6ea957d08a871b'), (
('VeryLongMessage!' * 64, b'da2b73b0170479c2bfba3dd4839bf0d67732a44df8c873f3f3a2aca8a57d7bdc0b5d534f54c649e2d44135717001998b176d3cd1212366464db51f5838430fb31c'), "This is an example of a signed message.",
b"b7837058907192dbc9427bf57d93a0acca3816c92927a08be573b785f2d72dab65dad9c92fbe03a358acdb455eab2107b869945d11f4e353d9cc6ea957d08a871b",
),
(
"VeryLongMessage!" * 64,
b"da2b73b0170479c2bfba3dd4839bf0d67732a44df8c873f3f3a2aca8a57d7bdc0b5d534f54c649e2d44135717001998b176d3cd1212366464db51f5838430fb31c",
),
] ]
def test_sign(self): def test_sign(self):

View File

@ -14,34 +14,44 @@
# You should have received a copy of the License along with this library. # You should have received a copy of the License along with this library.
# If not, see <https://www.gnu.org/licenses/lgpl-3.0.html>. # If not, see <https://www.gnu.org/licenses/lgpl-3.0.html>.
from binascii import unhexlify, hexlify from binascii import hexlify, unhexlify
import pytest import pytest
from trezorlib import ethereum, messages as proto
from .common import TrezorTest from .common import TrezorTest
from trezorlib import messages as proto
from trezorlib import ethereum
@pytest.mark.ethereum @pytest.mark.ethereum
class TestMsgEthereumSigntx(TrezorTest): class TestMsgEthereumSigntx(TrezorTest):
def test_ethereum_signtx_known_erc20_token(self): def test_ethereum_signtx_known_erc20_token(self):
self.setup_mnemonic_nopin_nopassphrase() self.setup_mnemonic_nopin_nopassphrase()
with self.client: with self.client:
self.client.set_expected_responses([ self.client.set_expected_responses(
proto.ButtonRequest(code=proto.ButtonRequestType.SignTx), [
proto.ButtonRequest(code=proto.ButtonRequestType.SignTx), proto.ButtonRequest(code=proto.ButtonRequestType.SignTx),
proto.EthereumTxRequest(data_length=None), proto.ButtonRequest(code=proto.ButtonRequestType.SignTx),
]) proto.EthereumTxRequest(data_length=None),
]
)
data = bytearray() data = bytearray()
# method id signalizing `transfer(address _to, uint256 _value)` function # method id signalizing `transfer(address _to, uint256 _value)` function
data.extend(unhexlify('a9059cbb')) data.extend(unhexlify("a9059cbb"))
# 1st function argument (to - the receiver) # 1st function argument (to - the receiver)
data.extend(unhexlify('000000000000000000000000574bbb36871ba6b78e27f4b4dcfb76ea0091880b')) data.extend(
unhexlify(
"000000000000000000000000574bbb36871ba6b78e27f4b4dcfb76ea0091880b"
)
)
# 2nd function argument (value - amount to be transferred) # 2nd function argument (value - amount to be transferred)
data.extend(unhexlify('000000000000000000000000000000000000000000000000000000000bebc200')) data.extend(
unhexlify(
"000000000000000000000000000000000000000000000000000000000bebc200"
)
)
# 200 000 000 in dec, divisibility of ADT = 9, trezor1 displays 0.2 ADT, Trezor T 200 000 000 Wei ADT # 200 000 000 in dec, divisibility of ADT = 9, trezor1 displays 0.2 ADT, Trezor T 200 000 000 Wei ADT
sig_v, sig_r, sig_s = ethereum.sign_tx( sig_v, sig_r, sig_s = ethereum.sign_tx(
@ -51,33 +61,50 @@ class TestMsgEthereumSigntx(TrezorTest):
gas_price=20, gas_price=20,
gas_limit=20, gas_limit=20,
# ADT token address # ADT token address
to=b'\xd0\xd6\xd6\xc5\xfe\x4a\x67\x7d\x34\x3c\xc4\x33\x53\x6b\xb7\x17\xba\xe1\x67\xdd', to=b"\xd0\xd6\xd6\xc5\xfe\x4a\x67\x7d\x34\x3c\xc4\x33\x53\x6b\xb7\x17\xba\xe1\x67\xdd",
chain_id=1, chain_id=1,
# value needs to be 0, token value is set in the contract (data) # value needs to be 0, token value is set in the contract (data)
value=0, value=0,
data=data) data=data,
)
# taken from T1 might not be 100% correct but still better than nothing # taken from T1 might not be 100% correct but still better than nothing
assert hexlify(sig_r) == b'75cf48fa173d8ceb68af9e4fb6b78ef69e6ed5e7679ba6f8e3e91d74b2fb0f96' assert (
assert hexlify(sig_s) == b'65de4a8c35263b2cfff3954b12146e8e568aa67a1c2461d6865e74ef75c7e190' hexlify(sig_r)
== b"75cf48fa173d8ceb68af9e4fb6b78ef69e6ed5e7679ba6f8e3e91d74b2fb0f96"
)
assert (
hexlify(sig_s)
== b"65de4a8c35263b2cfff3954b12146e8e568aa67a1c2461d6865e74ef75c7e190"
)
def test_ethereum_signtx_unknown_erc20_token(self): def test_ethereum_signtx_unknown_erc20_token(self):
self.setup_mnemonic_nopin_nopassphrase() self.setup_mnemonic_nopin_nopassphrase()
with self.client: with self.client:
self.client.set_expected_responses([ self.client.set_expected_responses(
proto.ButtonRequest(code=proto.ButtonRequestType.SignTx), [
proto.ButtonRequest(code=proto.ButtonRequestType.SignTx), proto.ButtonRequest(code=proto.ButtonRequestType.SignTx),
proto.EthereumTxRequest(data_length=None), proto.ButtonRequest(code=proto.ButtonRequestType.SignTx),
]) proto.EthereumTxRequest(data_length=None),
]
)
data = bytearray() data = bytearray()
# method id signalizing `transfer(address _to, uint256 _value)` function # method id signalizing `transfer(address _to, uint256 _value)` function
data.extend(unhexlify('a9059cbb')) data.extend(unhexlify("a9059cbb"))
# 1st function argument (to - the receiver) # 1st function argument (to - the receiver)
data.extend(unhexlify('000000000000000000000000574bbb36871ba6b78e27f4b4dcfb76ea0091880b')) data.extend(
unhexlify(
"000000000000000000000000574bbb36871ba6b78e27f4b4dcfb76ea0091880b"
)
)
# 2nd function argument (value - amount to be transferred) # 2nd function argument (value - amount to be transferred)
data.extend(unhexlify('0000000000000000000000000000000000000000000000000000000000000123')) data.extend(
unhexlify(
"0000000000000000000000000000000000000000000000000000000000000123"
)
)
# since this token is unknown trezor should display "unknown token value" # since this token is unknown trezor should display "unknown token value"
sig_v, sig_r, sig_s = ethereum.sign_tx( sig_v, sig_r, sig_s = ethereum.sign_tx(
@ -87,25 +114,34 @@ class TestMsgEthereumSigntx(TrezorTest):
gas_price=20, gas_price=20,
gas_limit=20, gas_limit=20,
# unknown token address (Grzegorz Brzęczyszczykiewicz Token) # unknown token address (Grzegorz Brzęczyszczykiewicz Token)
to=b'\xfc\x6b\x5d\x6a\xf8\xa1\x32\x58\xf7\xcb\xd0\xd3\x9e\x11\xb3\x5e\x01\xa3\x2f\x93', to=b"\xfc\x6b\x5d\x6a\xf8\xa1\x32\x58\xf7\xcb\xd0\xd3\x9e\x11\xb3\x5e\x01\xa3\x2f\x93",
chain_id=1, chain_id=1,
# value needs to be 0, token value is set in the contract (data) # value needs to be 0, token value is set in the contract (data)
value=0, value=0,
data=data) data=data,
)
# taken from T1 might not be 100% correct but still better than nothing # taken from T1 might not be 100% correct but still better than nothing
assert hexlify(sig_r) == b'1707471fbf632e42d18144157aaf4cde101cd9aa9782ad8e30583cfc95ddeef6' assert (
assert hexlify(sig_s) == b'3d2e52ba5904a4bf131abde3f79db826199f5d6f4d241d531d7e8a30a3b9cfd9' hexlify(sig_r)
== b"1707471fbf632e42d18144157aaf4cde101cd9aa9782ad8e30583cfc95ddeef6"
)
assert (
hexlify(sig_s)
== b"3d2e52ba5904a4bf131abde3f79db826199f5d6f4d241d531d7e8a30a3b9cfd9"
)
def test_ethereum_signtx_nodata(self): def test_ethereum_signtx_nodata(self):
self.setup_mnemonic_nopin_nopassphrase() self.setup_mnemonic_nopin_nopassphrase()
with self.client: with self.client:
self.client.set_expected_responses([ self.client.set_expected_responses(
proto.ButtonRequest(code=proto.ButtonRequestType.SignTx), [
proto.ButtonRequest(code=proto.ButtonRequestType.SignTx), proto.ButtonRequest(code=proto.ButtonRequestType.SignTx),
proto.EthereumTxRequest(data_length=None), # v,r,s checked with assert proto.ButtonRequest(code=proto.ButtonRequestType.SignTx),
]) proto.EthereumTxRequest(data_length=None), # v,r,s checked later
]
)
sig_v, sig_r, sig_s = ethereum.sign_tx( sig_v, sig_r, sig_s = ethereum.sign_tx(
self.client, self.client,
@ -113,19 +149,28 @@ class TestMsgEthereumSigntx(TrezorTest):
nonce=0, nonce=0,
gas_price=20, gas_price=20,
gas_limit=20, gas_limit=20,
to=unhexlify('1d1c328764a41bda0492b66baa30c4a339ff85ef'), to=unhexlify("1d1c328764a41bda0492b66baa30c4a339ff85ef"),
value=10) value=10,
)
assert sig_v == 27 assert sig_v == 27
assert hexlify(sig_r) == b'9b61192a161d056c66cfbbd331edb2d783a0193bd4f65f49ee965f791d898f72' assert (
assert hexlify(sig_s) == b'49c0bbe35131592c6ed5c871ac457feeb16a1493f64237387fab9b83c1a202f7' hexlify(sig_r)
== b"9b61192a161d056c66cfbbd331edb2d783a0193bd4f65f49ee965f791d898f72"
)
assert (
hexlify(sig_s)
== b"49c0bbe35131592c6ed5c871ac457feeb16a1493f64237387fab9b83c1a202f7"
)
with self.client: with self.client:
self.client.set_expected_responses([ self.client.set_expected_responses(
proto.ButtonRequest(code=proto.ButtonRequestType.SignTx), [
proto.ButtonRequest(code=proto.ButtonRequestType.SignTx), proto.ButtonRequest(code=proto.ButtonRequestType.SignTx),
proto.EthereumTxRequest(data_length=None), proto.ButtonRequest(code=proto.ButtonRequestType.SignTx),
]) proto.EthereumTxRequest(data_length=None),
]
)
sig_v, sig_r, sig_s = ethereum.sign_tx( sig_v, sig_r, sig_s = ethereum.sign_tx(
self.client, self.client,
@ -133,22 +178,31 @@ class TestMsgEthereumSigntx(TrezorTest):
nonce=123456, nonce=123456,
gas_price=20000, gas_price=20000,
gas_limit=20000, gas_limit=20000,
to=unhexlify('1d1c328764a41bda0492b66baa30c4a339ff85ef'), to=unhexlify("1d1c328764a41bda0492b66baa30c4a339ff85ef"),
value=12345678901234567890) value=12345678901234567890,
)
assert sig_v == 28 assert sig_v == 28
assert hexlify(sig_r) == b'6de597b8ec1b46501e5b159676e132c1aa78a95bd5892ef23560a9867528975a' assert (
assert hexlify(sig_s) == b'6e33c4230b1ecf96a8dbb514b4aec0a6d6ba53f8991c8143f77812aa6daa993f' hexlify(sig_r)
== b"6de597b8ec1b46501e5b159676e132c1aa78a95bd5892ef23560a9867528975a"
)
assert (
hexlify(sig_s)
== b"6e33c4230b1ecf96a8dbb514b4aec0a6d6ba53f8991c8143f77812aa6daa993f"
)
def test_ethereum_signtx_data(self): def test_ethereum_signtx_data(self):
self.setup_mnemonic_nopin_nopassphrase() self.setup_mnemonic_nopin_nopassphrase()
with self.client: with self.client:
self.client.set_expected_responses([ self.client.set_expected_responses(
proto.ButtonRequest(code=proto.ButtonRequestType.SignTx), [
proto.ButtonRequest(code=proto.ButtonRequestType.SignTx), proto.ButtonRequest(code=proto.ButtonRequestType.SignTx),
proto.ButtonRequest(code=proto.ButtonRequestType.SignTx), proto.ButtonRequest(code=proto.ButtonRequestType.SignTx),
proto.EthereumTxRequest(data_length=None), proto.ButtonRequest(code=proto.ButtonRequestType.SignTx),
]) proto.EthereumTxRequest(data_length=None),
]
)
sig_v, sig_r, sig_s = ethereum.sign_tx( sig_v, sig_r, sig_s = ethereum.sign_tx(
self.client, self.client,
@ -156,24 +210,38 @@ class TestMsgEthereumSigntx(TrezorTest):
nonce=0, nonce=0,
gas_price=20, gas_price=20,
gas_limit=20, gas_limit=20,
to=unhexlify('1d1c328764a41bda0492b66baa30c4a339ff85ef'), to=unhexlify("1d1c328764a41bda0492b66baa30c4a339ff85ef"),
value=10, value=10,
data=b'abcdefghijklmnop' * 16) data=b"abcdefghijklmnop" * 16,
)
assert sig_v == 28 assert sig_v == 28
assert hexlify(sig_r) == b'6da89ed8627a491bedc9e0382f37707ac4e5102e25e7a1234cb697cedb7cd2c0' assert (
assert hexlify(sig_s) == b'691f73b145647623e2d115b208a7c3455a6a8a83e3b4db5b9c6d9bc75825038a' hexlify(sig_r)
== b"6da89ed8627a491bedc9e0382f37707ac4e5102e25e7a1234cb697cedb7cd2c0"
)
assert (
hexlify(sig_s)
== b"691f73b145647623e2d115b208a7c3455a6a8a83e3b4db5b9c6d9bc75825038a"
)
with self.client: with self.client:
self.client.set_expected_responses([ self.client.set_expected_responses(
proto.ButtonRequest(code=proto.ButtonRequestType.SignTx), [
proto.ButtonRequest(code=proto.ButtonRequestType.SignTx), proto.ButtonRequest(code=proto.ButtonRequestType.SignTx),
proto.ButtonRequest(code=proto.ButtonRequestType.SignTx), proto.ButtonRequest(code=proto.ButtonRequestType.SignTx),
proto.EthereumTxRequest(data_length=1024, signature_r=None, signature_s=None, signature_v=None), proto.ButtonRequest(code=proto.ButtonRequestType.SignTx),
proto.EthereumTxRequest(data_length=1024), proto.EthereumTxRequest(
proto.EthereumTxRequest(data_length=1024), data_length=1024,
proto.EthereumTxRequest(data_length=3), signature_r=None,
proto.EthereumTxRequest(), signature_s=None,
]) signature_v=None,
),
proto.EthereumTxRequest(data_length=1024),
proto.EthereumTxRequest(data_length=1024),
proto.EthereumTxRequest(data_length=3),
proto.EthereumTxRequest(),
]
)
sig_v, sig_r, sig_s = ethereum.sign_tx( sig_v, sig_r, sig_s = ethereum.sign_tx(
self.client, self.client,
@ -181,27 +249,41 @@ class TestMsgEthereumSigntx(TrezorTest):
nonce=123456, nonce=123456,
gas_price=20000, gas_price=20000,
gas_limit=20000, gas_limit=20000,
to=unhexlify('1d1c328764a41bda0492b66baa30c4a339ff85ef'), to=unhexlify("1d1c328764a41bda0492b66baa30c4a339ff85ef"),
value=12345678901234567890, value=12345678901234567890,
data=b'ABCDEFGHIJKLMNOP' * 256 + b'!!!') data=b"ABCDEFGHIJKLMNOP" * 256 + b"!!!",
)
assert sig_v == 28 assert sig_v == 28
assert hexlify(sig_r) == b'4e90b13c45c6a9bf4aaad0e5427c3e62d76692b36eb727c78d332441b7400404' assert (
assert hexlify(sig_s) == b'3ff236e7d05f0f9b1ee3d70599bb4200638f28388a8faf6bb36db9e04dc544be' hexlify(sig_r)
== b"4e90b13c45c6a9bf4aaad0e5427c3e62d76692b36eb727c78d332441b7400404"
)
assert (
hexlify(sig_s)
== b"3ff236e7d05f0f9b1ee3d70599bb4200638f28388a8faf6bb36db9e04dc544be"
)
def test_ethereum_signtx_message(self): def test_ethereum_signtx_message(self):
self.setup_mnemonic_nopin_nopassphrase() self.setup_mnemonic_nopin_nopassphrase()
with self.client: with self.client:
self.client.set_expected_responses([ self.client.set_expected_responses(
proto.ButtonRequest(code=proto.ButtonRequestType.SignTx), [
proto.ButtonRequest(code=proto.ButtonRequestType.SignTx), proto.ButtonRequest(code=proto.ButtonRequestType.SignTx),
proto.ButtonRequest(code=proto.ButtonRequestType.SignTx), proto.ButtonRequest(code=proto.ButtonRequestType.SignTx),
proto.EthereumTxRequest(data_length=1024, signature_r=None, signature_s=None, signature_v=None), proto.ButtonRequest(code=proto.ButtonRequestType.SignTx),
proto.EthereumTxRequest(data_length=1024), proto.EthereumTxRequest(
proto.EthereumTxRequest(data_length=1024), data_length=1024,
proto.EthereumTxRequest(data_length=3), signature_r=None,
proto.EthereumTxRequest(), signature_s=None,
]) signature_v=None,
),
proto.EthereumTxRequest(data_length=1024),
proto.EthereumTxRequest(data_length=1024),
proto.EthereumTxRequest(data_length=3),
proto.EthereumTxRequest(),
]
)
sig_v, sig_r, sig_s = ethereum.sign_tx( sig_v, sig_r, sig_s = ethereum.sign_tx(
self.client, self.client,
@ -209,12 +291,19 @@ class TestMsgEthereumSigntx(TrezorTest):
nonce=0, nonce=0,
gas_price=20000, gas_price=20000,
gas_limit=20000, gas_limit=20000,
to=unhexlify('1d1c328764a41bda0492b66baa30c4a339ff85ef'), to=unhexlify("1d1c328764a41bda0492b66baa30c4a339ff85ef"),
value=0, value=0,
data=b'ABCDEFGHIJKLMNOP' * 256 + b'!!!') data=b"ABCDEFGHIJKLMNOP" * 256 + b"!!!",
)
assert sig_v == 28 assert sig_v == 28
assert hexlify(sig_r) == b'070e9dafda4d9e733fa7b6747a75f8a4916459560efb85e3e73cd39f31aa160d' assert (
assert hexlify(sig_s) == b'7842db33ef15c27049ed52741db41fe3238a6fa3a6a0888fcfb74d6917600e41' hexlify(sig_r)
== b"070e9dafda4d9e733fa7b6747a75f8a4916459560efb85e3e73cd39f31aa160d"
)
assert (
hexlify(sig_s)
== b"7842db33ef15c27049ed52741db41fe3238a6fa3a6a0888fcfb74d6917600e41"
)
def test_ethereum_signtx_newcontract(self): def test_ethereum_signtx_newcontract(self):
self.setup_mnemonic_nopin_nopassphrase() self.setup_mnemonic_nopin_nopassphrase()
@ -227,21 +316,28 @@ class TestMsgEthereumSigntx(TrezorTest):
nonce=123456, nonce=123456,
gas_price=20000, gas_price=20000,
gas_limit=20000, gas_limit=20000,
to='', to="",
value=12345678901234567890 value=12345678901234567890,
) )
with self.client: with self.client:
self.client.set_expected_responses([ self.client.set_expected_responses(
proto.ButtonRequest(code=proto.ButtonRequestType.SignTx), [
proto.ButtonRequest(code=proto.ButtonRequestType.SignTx), proto.ButtonRequest(code=proto.ButtonRequestType.SignTx),
proto.ButtonRequest(code=proto.ButtonRequestType.SignTx), proto.ButtonRequest(code=proto.ButtonRequestType.SignTx),
proto.EthereumTxRequest(data_length=1024, signature_r=None, signature_s=None, signature_v=None), proto.ButtonRequest(code=proto.ButtonRequestType.SignTx),
proto.EthereumTxRequest(data_length=1024), proto.EthereumTxRequest(
proto.EthereumTxRequest(data_length=1024), data_length=1024,
proto.EthereumTxRequest(data_length=3), signature_r=None,
proto.EthereumTxRequest(), signature_s=None,
]) signature_v=None,
),
proto.EthereumTxRequest(data_length=1024),
proto.EthereumTxRequest(data_length=1024),
proto.EthereumTxRequest(data_length=3),
proto.EthereumTxRequest(),
]
)
sig_v, sig_r, sig_s = ethereum.sign_tx( sig_v, sig_r, sig_s = ethereum.sign_tx(
self.client, self.client,
@ -249,12 +345,19 @@ class TestMsgEthereumSigntx(TrezorTest):
nonce=0, nonce=0,
gas_price=20000, gas_price=20000,
gas_limit=20000, gas_limit=20000,
to='', to="",
value=12345678901234567890, value=12345678901234567890,
data=b'ABCDEFGHIJKLMNOP' * 256 + b'!!!') data=b"ABCDEFGHIJKLMNOP" * 256 + b"!!!",
)
assert sig_v == 28 assert sig_v == 28
assert hexlify(sig_r) == b'b401884c10ae435a2e792303b5fc257a09f94403b2883ad8c0ac7a7282f5f1f9' assert (
assert hexlify(sig_s) == b'4742fc9e6a5fa8db3db15c2d856914a7f3daab21603a6c1ce9e9927482f8352e' hexlify(sig_r)
== b"b401884c10ae435a2e792303b5fc257a09f94403b2883ad8c0ac7a7282f5f1f9"
)
assert (
hexlify(sig_s)
== b"4742fc9e6a5fa8db3db15c2d856914a7f3daab21603a6c1ce9e9927482f8352e"
)
def test_ethereum_sanity_checks(self): def test_ethereum_sanity_checks(self):
# gas overflow # gas overflow
@ -265,8 +368,8 @@ class TestMsgEthereumSigntx(TrezorTest):
nonce=123456, nonce=123456,
gas_price=0xffffffffffffffffffffffffffffffff, gas_price=0xffffffffffffffffffffffffffffffff,
gas_limit=0xffffffffffffffffffffffffffffff, gas_limit=0xffffffffffffffffffffffffffffff,
to=unhexlify('1d1c328764a41bda0492b66baa30c4a339ff85ef'), to=unhexlify("1d1c328764a41bda0492b66baa30c4a339ff85ef"),
value=12345678901234567890 value=12345678901234567890,
) )
# no gas price # no gas price
@ -276,8 +379,8 @@ class TestMsgEthereumSigntx(TrezorTest):
n=[0, 0], n=[0, 0],
nonce=123456, nonce=123456,
gas_limit=10000, gas_limit=10000,
to=unhexlify('1d1c328764a41bda0492b66baa30c4a339ff85ef'), to=unhexlify("1d1c328764a41bda0492b66baa30c4a339ff85ef"),
value=12345678901234567890 value=12345678901234567890,
) )
# no gas limit # no gas limit
@ -287,8 +390,8 @@ class TestMsgEthereumSigntx(TrezorTest):
n=[0, 0], n=[0, 0],
nonce=123456, nonce=123456,
gas_price=10000, gas_price=10000,
to=unhexlify('1d1c328764a41bda0492b66baa30c4a339ff85ef'), to=unhexlify("1d1c328764a41bda0492b66baa30c4a339ff85ef"),
value=12345678901234567890 value=12345678901234567890,
) )
# no nonce # no nonce
@ -298,6 +401,6 @@ class TestMsgEthereumSigntx(TrezorTest):
n=[0, 0], n=[0, 0],
gas_price=10000, gas_price=10000,
gas_limit=123456, gas_limit=123456,
to=unhexlify('1d1c328764a41bda0492b66baa30c4a339ff85ef'), to=unhexlify("1d1c328764a41bda0492b66baa30c4a339ff85ef"),
value=12345678901234567890 value=12345678901234567890,
) )

View File

@ -14,13 +14,15 @@
# You should have received a copy of the License along with this library. # You should have received a copy of the License along with this library.
# If not, see <https://www.gnu.org/licenses/lgpl-3.0.html>. # If not, see <https://www.gnu.org/licenses/lgpl-3.0.html>.
from binascii import unhexlify, hexlify from binascii import hexlify, unhexlify
import pytest import pytest
from .common import TrezorTest
from trezorlib import ethereum from trezorlib import ethereum
from trezorlib.tools import H_ from trezorlib.tools import H_
from .common import TrezorTest
@pytest.mark.ethereum @pytest.mark.ethereum
class TestMsgEthereumSigntxChainId(TrezorTest): class TestMsgEthereumSigntxChainId(TrezorTest):

View File

@ -18,26 +18,30 @@ from binascii import unhexlify
import pytest import pytest
from .common import TrezorTest
from trezorlib import ethereum from trezorlib import ethereum
from .common import TrezorTest
@pytest.mark.ethereum @pytest.mark.ethereum
class TestMsgEthereumVerifymessage(TrezorTest): class TestMsgEthereumVerifymessage(TrezorTest):
ADDRESS = b'cb3864960e8db1a751212c580af27ee8867d688f' ADDRESS = b"cb3864960e8db1a751212c580af27ee8867d688f"
VECTORS = [ VECTORS = [
('This is an example of a signed message.', b'b7837058907192dbc9427bf57d93a0acca3816c92927a08be573b785f2d72dab65dad9c92fbe03a358acdb455eab2107b869945d11f4e353d9cc6ea957d08a871b'), (
('VeryLongMessage!' * 64, b'da2b73b0170479c2bfba3dd4839bf0d67732a44df8c873f3f3a2aca8a57d7bdc0b5d534f54c649e2d44135717001998b176d3cd1212366464db51f5838430fb31c'), "This is an example of a signed message.",
b"b7837058907192dbc9427bf57d93a0acca3816c92927a08be573b785f2d72dab65dad9c92fbe03a358acdb455eab2107b869945d11f4e353d9cc6ea957d08a871b",
),
(
"VeryLongMessage!" * 64,
b"da2b73b0170479c2bfba3dd4839bf0d67732a44df8c873f3f3a2aca8a57d7bdc0b5d534f54c649e2d44135717001998b176d3cd1212366464db51f5838430fb31c",
),
] ]
def test_verify(self): def test_verify(self):
self.setup_mnemonic_nopin_nopassphrase() self.setup_mnemonic_nopin_nopassphrase()
for msg, sig in self.VECTORS: for msg, sig in self.VECTORS:
res = ethereum.verify_message( res = ethereum.verify_message(
self.client, self.client, unhexlify(self.ADDRESS), unhexlify(sig), msg
unhexlify(self.ADDRESS),
unhexlify(sig),
msg
) )
assert res is True assert res is True

View File

@ -15,57 +15,128 @@
# If not, see <https://www.gnu.org/licenses/lgpl-3.0.html>. # If not, see <https://www.gnu.org/licenses/lgpl-3.0.html>.
from .common import TrezorTest from trezorlib import btc, messages as proto
from ..support import ckd_public as bip32 from trezorlib.tools import H_, parse_path
from trezorlib import messages as proto
from trezorlib.tools import parse_path, H_ from ..support import ckd_public as bip32
from trezorlib import btc from .common import TrezorTest
class TestMsgGetaddress(TrezorTest): class TestMsgGetaddress(TrezorTest):
def test_btc(self): def test_btc(self):
self.setup_mnemonic_nopin_nopassphrase() self.setup_mnemonic_nopin_nopassphrase()
assert btc.get_address(self.client, 'Bitcoin', []) == '1EfKbQupktEMXf4gujJ9kCFo83k1iMqwqK' assert (
assert btc.get_address(self.client, 'Bitcoin', [1]) == '1CK7SJdcb8z9HuvVft3D91HLpLC6KSsGb' btc.get_address(self.client, "Bitcoin", [])
assert btc.get_address(self.client, 'Bitcoin', [0, H_(1)]) == '1JVq66pzRBvqaBRFeU9SPVvg3er4ZDgoMs' == "1EfKbQupktEMXf4gujJ9kCFo83k1iMqwqK"
assert btc.get_address(self.client, 'Bitcoin', [H_(9), 0]) == '1F4YdQdL9ZQwvcNTuy5mjyQxXkyCfMcP2P' )
assert btc.get_address(self.client, 'Bitcoin', [0, 9999999]) == '1GS8X3yc7ntzwGw9vXwj9wqmBWZkTFewBV' assert (
btc.get_address(self.client, "Bitcoin", [1])
== "1CK7SJdcb8z9HuvVft3D91HLpLC6KSsGb"
)
assert (
btc.get_address(self.client, "Bitcoin", [0, H_(1)])
== "1JVq66pzRBvqaBRFeU9SPVvg3er4ZDgoMs"
)
assert (
btc.get_address(self.client, "Bitcoin", [H_(9), 0])
== "1F4YdQdL9ZQwvcNTuy5mjyQxXkyCfMcP2P"
)
assert (
btc.get_address(self.client, "Bitcoin", [0, 9999999])
== "1GS8X3yc7ntzwGw9vXwj9wqmBWZkTFewBV"
)
def test_ltc(self): def test_ltc(self):
self.setup_mnemonic_nopin_nopassphrase() self.setup_mnemonic_nopin_nopassphrase()
assert btc.get_address(self.client, 'Litecoin', []) == 'LYtGrdDeqYUQnTkr5sHT2DKZLG7Hqg7HTK' assert (
assert btc.get_address(self.client, 'Litecoin', [1]) == 'LKRGNecThFP3Q6c5fosLVA53Z2hUDb1qnE' btc.get_address(self.client, "Litecoin", [])
assert btc.get_address(self.client, 'Litecoin', [0, H_(1)]) == 'LcinMK8pVrAtpz7Qpc8jfWzSFsDLgLYfG6' == "LYtGrdDeqYUQnTkr5sHT2DKZLG7Hqg7HTK"
assert btc.get_address(self.client, 'Litecoin', [H_(9), 0]) == 'LZHVtcwAEDf1BR4d67551zUijyLUpDF9EX' )
assert btc.get_address(self.client, 'Litecoin', [0, 9999999]) == 'Laf5nGHSCT94C5dK6fw2RxuXPiw2ZuRR9S' assert (
btc.get_address(self.client, "Litecoin", [1])
== "LKRGNecThFP3Q6c5fosLVA53Z2hUDb1qnE"
)
assert (
btc.get_address(self.client, "Litecoin", [0, H_(1)])
== "LcinMK8pVrAtpz7Qpc8jfWzSFsDLgLYfG6"
)
assert (
btc.get_address(self.client, "Litecoin", [H_(9), 0])
== "LZHVtcwAEDf1BR4d67551zUijyLUpDF9EX"
)
assert (
btc.get_address(self.client, "Litecoin", [0, 9999999])
== "Laf5nGHSCT94C5dK6fw2RxuXPiw2ZuRR9S"
)
def test_tbtc(self): def test_tbtc(self):
self.setup_mnemonic_nopin_nopassphrase() self.setup_mnemonic_nopin_nopassphrase()
assert btc.get_address(self.client, 'Testnet', [111, 42]) == 'moN6aN6NP1KWgnPSqzrrRPvx2x1UtZJssa' assert (
btc.get_address(self.client, "Testnet", [111, 42])
== "moN6aN6NP1KWgnPSqzrrRPvx2x1UtZJssa"
)
def test_bch(self): def test_bch(self):
self.setup_mnemonic_allallall() self.setup_mnemonic_allallall()
assert btc.get_address(self.client, 'Bcash', parse_path("44'/145'/0'/0/0")) == 'bitcoincash:qr08q88p9etk89wgv05nwlrkm4l0urz4cyl36hh9sv' assert (
assert btc.get_address(self.client, 'Bcash', parse_path("44'/145'/0'/0/1")) == 'bitcoincash:qr23ajjfd9wd73l87j642puf8cad20lfmqdgwvpat4' btc.get_address(self.client, "Bcash", parse_path("44'/145'/0'/0/0"))
assert btc.get_address(self.client, 'Bcash', parse_path("44'/145'/0'/1/0")) == 'bitcoincash:qzc5q87w069lzg7g3gzx0c8dz83mn7l02scej5aluw' == "bitcoincash:qr08q88p9etk89wgv05nwlrkm4l0urz4cyl36hh9sv"
)
assert (
btc.get_address(self.client, "Bcash", parse_path("44'/145'/0'/0/1"))
== "bitcoincash:qr23ajjfd9wd73l87j642puf8cad20lfmqdgwvpat4"
)
assert (
btc.get_address(self.client, "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: btc.get_public_node(self.client, parse_path("44'/145'/" + str(index) + "'")), range(1, 4)): for n in map(
lambda index: btc.get_public_node(
self.client, 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):
return proto.MultisigRedeemScriptType( return proto.MultisigRedeemScriptType(
pubkeys=list(map(lambda xpub: proto.HDNodePathType(node=bip32.deserialize(xpub), address_n=[chain, nr]), xpubs)), pubkeys=list(
map(
lambda xpub: proto.HDNodePathType(
node=bip32.deserialize(xpub), address_n=[chain, nr]
),
xpubs,
)
),
signatures=signatures, signatures=signatures,
m=2, m=2,
) )
for nr in range(1, 4): for nr in range(1, 4):
assert btc.get_address(self.client, 'Bcash', parse_path("44'/145'/" + str(nr) + "'/0/0"), show_display=(nr == 1), multisig=getmultisig(0, 0)) == 'bitcoincash:pqguz4nqq64jhr5v3kvpq4dsjrkda75hwy86gq0qzw' assert (
assert btc.get_address(self.client, 'Bcash', parse_path("44'/145'/" + str(nr) + "'/1/0"), show_display=(nr == 1), multisig=getmultisig(1, 0)) == 'bitcoincash:pp6kcpkhua7789g2vyj0qfkcux3yvje7euhyhltn0a' btc.get_address(
self.client,
"Bcash",
parse_path("44'/145'/" + str(nr) + "'/0/0"),
show_display=(nr == 1),
multisig=getmultisig(0, 0),
)
== "bitcoincash:pqguz4nqq64jhr5v3kvpq4dsjrkda75hwy86gq0qzw"
)
assert (
btc.get_address(
self.client,
"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()
@ -77,8 +148,8 @@ class TestMsgGetaddress(TrezorTest):
assert node_sub1.chain_code == node_sub2.chain_code assert node_sub1.chain_code == node_sub2.chain_code
assert node_sub1.public_key == node_sub2.public_key assert node_sub1.public_key == node_sub2.public_key
address1 = btc.get_address(self.client, 'Bitcoin', [1]) address1 = btc.get_address(self.client, "Bitcoin", [1])
address2 = bip32.get_address(node_sub2, 0) address2 = bip32.get_address(node_sub2, 0)
assert address2 == '1CK7SJdcb8z9HuvVft3D91HLpLC6KSsGb' assert address2 == "1CK7SJdcb8z9HuvVft3D91HLpLC6KSsGb"
assert address1 == address2 assert address1 == address2

View File

@ -14,28 +14,79 @@
# You should have received a copy of the License along with this library. # You should have received a copy of the License along with this library.
# If not, see <https://www.gnu.org/licenses/lgpl-3.0.html>. # If not, see <https://www.gnu.org/licenses/lgpl-3.0.html>.
from .common import TrezorTest from trezorlib import btc, messages as proto
from ..support import ckd_public as bip32
from trezorlib import messages as proto
from trezorlib.tools import parse_path from trezorlib.tools import parse_path
from trezorlib import btc
from ..support import ckd_public as bip32
from .common import TrezorTest
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 btc.get_address(self.client, "Testnet", parse_path("49'/1'/0'/1/0"), True, None, script_type=proto.InputScriptType.SPENDP2SHWITNESS) == '2N1LGaGg836mqSQqiuUBLfcyGBhyZbremDX' assert (
assert btc.get_address(self.client, "Testnet", parse_path("49'/1'/0'/0/0"), False, None, script_type=proto.InputScriptType.SPENDP2SHWITNESS) == '2N4Q5FhU2497BryFfUgbqkAJE87aKHUhXMp' btc.get_address(
assert btc.get_address(self.client, "Testnet", parse_path("44'/1'/0'/0/0"), False, None, script_type=proto.InputScriptType.SPENDP2SHWITNESS) == '2N6UeBoqYEEnybg4cReFYDammpsyDw8R2Mc' self.client,
assert btc.get_address(self.client, "Testnet", parse_path("44'/1'/0'/0/0"), False, None, script_type=proto.InputScriptType.SPENDADDRESS) == 'mvbu1Gdy8SUjTenqerxUaZyYjmveZvt33q' "Testnet",
parse_path("49'/1'/0'/1/0"),
True,
None,
script_type=proto.InputScriptType.SPENDP2SHWITNESS,
)
== "2N1LGaGg836mqSQqiuUBLfcyGBhyZbremDX"
)
assert (
btc.get_address(
self.client,
"Testnet",
parse_path("49'/1'/0'/0/0"),
False,
None,
script_type=proto.InputScriptType.SPENDP2SHWITNESS,
)
== "2N4Q5FhU2497BryFfUgbqkAJE87aKHUhXMp"
)
assert (
btc.get_address(
self.client,
"Testnet",
parse_path("44'/1'/0'/0/0"),
False,
None,
script_type=proto.InputScriptType.SPENDP2SHWITNESS,
)
== "2N6UeBoqYEEnybg4cReFYDammpsyDw8R2Mc"
)
assert (
btc.get_address(
self.client,
"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: btc.get_public_node(self.client, parse_path("999'/1'/%d'" % index)), range(1, 4)) nodes = map(
lambda index: btc.get_public_node(
self.client, 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(
signatures=[b'', b'', b''], map(
lambda n: proto.HDNodePathType(
node=bip32.deserialize(n.xpub), address_n=[2, 0]
),
nodes,
)
),
signatures=[b"", b"", b""],
m=2, m=2,
) )
# multisig2 = proto.MultisigRedeemScriptType( # multisig2 = proto.MultisigRedeemScriptType(
@ -44,4 +95,14 @@ class TestMsgGetaddressSegwit(TrezorTest):
# m=2, # m=2,
# ) # )
for i in [1, 2, 3]: for i in [1, 2, 3]:
assert btc.get_address(self.client, "Testnet", parse_path("999'/1'/%d'/2/0" % i), False, multisig1, script_type=proto.InputScriptType.SPENDP2SHWITNESS) == '2N2MxyAfifVhb3AMagisxaj3uij8bfXqf4Y' assert (
btc.get_address(
self.client,
"Testnet",
parse_path("999'/1'/%d'/2/0" % i),
False,
multisig1,
script_type=proto.InputScriptType.SPENDP2SHWITNESS,
)
== "2N2MxyAfifVhb3AMagisxaj3uij8bfXqf4Y"
)

View File

@ -14,35 +14,111 @@
# You should have received a copy of the License along with this library. # You should have received a copy of the License along with this library.
# If not, see <https://www.gnu.org/licenses/lgpl-3.0.html>. # If not, see <https://www.gnu.org/licenses/lgpl-3.0.html>.
from .common import TrezorTest from trezorlib import btc, messages as proto
from ..support import ckd_public as bip32
from trezorlib import messages as proto
from trezorlib.tools import parse_path from trezorlib.tools import parse_path
from trezorlib import btc
from ..support import ckd_public as bip32
from .common import TrezorTest
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 btc.get_address(self.client, "Testnet", parse_path("49'/1'/0'/0/0"), True, None, script_type=proto.InputScriptType.SPENDWITNESS) == 'tb1qqzv60m9ajw8drqulta4ld4gfx0rdh82un5s65s' assert (
assert btc.get_address(self.client, "Testnet", parse_path("49'/1'/0'/1/0"), False, None, script_type=proto.InputScriptType.SPENDWITNESS) == 'tb1q694ccp5qcc0udmfwgp692u2s2hjpq5h407urtu' btc.get_address(
assert btc.get_address(self.client, "Testnet", parse_path("44'/1'/0'/0/0"), False, None, script_type=proto.InputScriptType.SPENDWITNESS) == 'tb1q54un3q39sf7e7tlfq99d6ezys7qgc62a6rxllc' self.client,
assert btc.get_address(self.client, "Testnet", parse_path("44'/1'/0'/0/0"), False, None, script_type=proto.InputScriptType.SPENDADDRESS) == 'mvbu1Gdy8SUjTenqerxUaZyYjmveZvt33q' "Testnet",
parse_path("49'/1'/0'/0/0"),
True,
None,
script_type=proto.InputScriptType.SPENDWITNESS,
)
== "tb1qqzv60m9ajw8drqulta4ld4gfx0rdh82un5s65s"
)
assert (
btc.get_address(
self.client,
"Testnet",
parse_path("49'/1'/0'/1/0"),
False,
None,
script_type=proto.InputScriptType.SPENDWITNESS,
)
== "tb1q694ccp5qcc0udmfwgp692u2s2hjpq5h407urtu"
)
assert (
btc.get_address(
self.client,
"Testnet",
parse_path("44'/1'/0'/0/0"),
False,
None,
script_type=proto.InputScriptType.SPENDWITNESS,
)
== "tb1q54un3q39sf7e7tlfq99d6ezys7qgc62a6rxllc"
)
assert (
btc.get_address(
self.client,
"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 = [btc.get_public_node(self.client, parse_path("999'/1'/%d'" % index)) for index in range(1, 4)] nodes = [
btc.get_public_node(self.client, 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(
signatures=[b'', b'', b''], map(
lambda n: proto.HDNodePathType(
node=bip32.deserialize(n.xpub), address_n=[2, 0]
),
nodes,
)
),
signatures=[b"", b"", b""],
m=2, m=2,
) )
multisig2 = proto.MultisigRedeemScriptType( multisig2 = proto.MultisigRedeemScriptType(
pubkeys=list(map(lambda n: proto.HDNodePathType(node=bip32.deserialize(n.xpub), address_n=[2, 1]), nodes)), pubkeys=list(
signatures=[b'', b'', b''], map(
lambda n: proto.HDNodePathType(
node=bip32.deserialize(n.xpub), address_n=[2, 1]
),
nodes,
)
),
signatures=[b"", b"", b""],
m=2, m=2,
) )
for i in [1, 2, 3]: for i in [1, 2, 3]:
assert btc.get_address(self.client, "Testnet", parse_path("999'/1'/%d'/2/1" % i), False, multisig2, script_type=proto.InputScriptType.SPENDWITNESS) == 'tb1qch62pf820spe9mlq49ns5uexfnl6jzcezp7d328fw58lj0rhlhasge9hzy' assert (
assert btc.get_address(self.client, "Testnet", parse_path("999'/1'/%d'/2/0" % i), False, multisig1, script_type=proto.InputScriptType.SPENDWITNESS) == 'tb1qr6xa5v60zyt3ry9nmfew2fk5g9y3gerkjeu6xxdz7qga5kknz2ssld9z2z' btc.get_address(
self.client,
"Testnet",
parse_path("999'/1'/%d'/2/1" % i),
False,
multisig2,
script_type=proto.InputScriptType.SPENDWITNESS,
)
== "tb1qch62pf820spe9mlq49ns5uexfnl6jzcezp7d328fw58lj0rhlhasge9hzy"
)
assert (
btc.get_address(
self.client,
"Testnet",
parse_path("999'/1'/%d'/2/0" % i),
False,
multisig1,
script_type=proto.InputScriptType.SPENDWITNESS,
)
== "tb1qr6xa5v60zyt3ry9nmfew2fk5g9y3gerkjeu6xxdz7qga5kknz2ssld9z2z"
)

View File

@ -14,51 +14,71 @@
# You should have received a copy of the License along with this library. # You should have received a copy of the License along with this library.
# If not, see <https://www.gnu.org/licenses/lgpl-3.0.html>. # If not, see <https://www.gnu.org/licenses/lgpl-3.0.html>.
from .common import TrezorTest from trezorlib import btc, messages as proto
from ..support import ckd_public as bip32 from ..support import ckd_public as bip32
from trezorlib import messages as proto from .common import TrezorTest
from trezorlib import btc
class TestMsgGetaddressShow(TrezorTest): class TestMsgGetaddressShow(TrezorTest):
def test_show(self): def test_show(self):
self.setup_mnemonic_nopin_nopassphrase() self.setup_mnemonic_nopin_nopassphrase()
assert btc.get_address(self.client, 'Bitcoin', [1], show_display=True) == '1CK7SJdcb8z9HuvVft3D91HLpLC6KSsGb' assert (
assert btc.get_address(self.client, 'Bitcoin', [2], show_display=True) == '15AeAhtNJNKyowK8qPHwgpXkhsokzLtUpG' btc.get_address(self.client, "Bitcoin", [1], show_display=True)
assert btc.get_address(self.client, 'Bitcoin', [3], show_display=True) == '1CmzyJp9w3NafXMSEFH4SLYUPAVCSUrrJ5' == "1CK7SJdcb8z9HuvVft3D91HLpLC6KSsGb"
)
assert (
btc.get_address(self.client, "Bitcoin", [2], show_display=True)
== "15AeAhtNJNKyowK8qPHwgpXkhsokzLtUpG"
)
assert (
btc.get_address(self.client, "Bitcoin", [3], show_display=True)
== "1CmzyJp9w3NafXMSEFH4SLYUPAVCSUrrJ5"
)
def test_show_multisig_3(self): def test_show_multisig_3(self):
self.setup_mnemonic_nopin_nopassphrase() self.setup_mnemonic_nopin_nopassphrase()
node = bip32.deserialize('xpub661MyMwAqRbcF1zGijBb2K6x9YiJPh58xpcCeLvTxMX6spkY3PcpJ4ABcCyWfskq5DDxM3e6Ez5ePCqG5bnPUXR4wL8TZWyoDaUdiWW7bKy') node = bip32.deserialize(
"xpub661MyMwAqRbcF1zGijBb2K6x9YiJPh58xpcCeLvTxMX6spkY3PcpJ4ABcCyWfskq5DDxM3e6Ez5ePCqG5bnPUXR4wL8TZWyoDaUdiWW7bKy"
)
multisig = proto.MultisigRedeemScriptType( multisig = proto.MultisigRedeemScriptType(
pubkeys=[ pubkeys=[
proto.HDNodePathType(node=node, address_n=[1]), proto.HDNodePathType(node=node, address_n=[1]),
proto.HDNodePathType(node=node, address_n=[2]), proto.HDNodePathType(node=node, address_n=[2]),
proto.HDNodePathType(node=node, address_n=[3]) proto.HDNodePathType(node=node, address_n=[3]),
], ],
signatures=[b'', b'', b''], signatures=[b"", b"", b""],
m=2, m=2,
) )
for i in [1, 2, 3]: for i in [1, 2, 3]:
assert btc.get_address(self.client, 'Bitcoin', [i], show_display=True, multisig=multisig) == '3E7GDtuHqnqPmDgwH59pVC7AvySiSkbibz' assert (
btc.get_address(
self.client, "Bitcoin", [i], show_display=True, multisig=multisig
)
== "3E7GDtuHqnqPmDgwH59pVC7AvySiSkbibz"
)
def test_show_multisig_15(self): def test_show_multisig_15(self):
self.setup_mnemonic_nopin_nopassphrase() self.setup_mnemonic_nopin_nopassphrase()
node = bip32.deserialize('xpub661MyMwAqRbcF1zGijBb2K6x9YiJPh58xpcCeLvTxMX6spkY3PcpJ4ABcCyWfskq5DDxM3e6Ez5ePCqG5bnPUXR4wL8TZWyoDaUdiWW7bKy') node = bip32.deserialize(
"xpub661MyMwAqRbcF1zGijBb2K6x9YiJPh58xpcCeLvTxMX6spkY3PcpJ4ABcCyWfskq5DDxM3e6Ez5ePCqG5bnPUXR4wL8TZWyoDaUdiWW7bKy"
)
pubs = [] pubs = []
for x in range(15): for x in range(15):
pubs.append(proto.HDNodePathType(node=node, address_n=[x])) pubs.append(proto.HDNodePathType(node=node, address_n=[x]))
multisig = proto.MultisigRedeemScriptType( multisig = proto.MultisigRedeemScriptType(
pubkeys=pubs, pubkeys=pubs, signatures=[b""] * 15, m=15
signatures=[b''] * 15,
m=15,
) )
for i in range(15): for i in range(15):
assert btc.get_address(self.client, 'Bitcoin', [i], show_display=True, multisig=multisig) == '3QaKF8zobqcqY8aS6nxCD5ZYdiRfL3RCmU' assert (
btc.get_address(
self.client, "Bitcoin", [i], show_display=True, multisig=multisig
)
== "3QaKF8zobqcqY8aS6nxCD5ZYdiRfL3RCmU"
)

View File

@ -16,27 +16,60 @@
from binascii import unhexlify from binascii import unhexlify
from trezorlib import messages as proto, misc
from .common import TrezorTest from .common import TrezorTest
from trezorlib import messages as proto
from trezorlib import misc
class TestMsgGetECDHSessionKey(TrezorTest): class TestMsgGetECDHSessionKey(TrezorTest):
def test_ecdh(self): def test_ecdh(self):
self.setup_mnemonic_nopin_nopassphrase() self.setup_mnemonic_nopin_nopassphrase()
# URI : gpg://Satoshi Nakamoto <satoshi@bitcoin.org> # URI : gpg://Satoshi Nakamoto <satoshi@bitcoin.org>
identity = proto.IdentityType(proto='gpg', user='', host='Satoshi Nakamoto <satoshi@bitcoin.org>', port='', path='', index=0) identity = proto.IdentityType(
proto="gpg",
user="",
host="Satoshi Nakamoto <satoshi@bitcoin.org>",
port="",
path="",
index=0,
)
peer_public_key = unhexlify('0407f2c6e5becf3213c1d07df0cfbe8e39f70a8c643df7575e5c56859ec52c45ca950499c019719dae0fda04248d851e52cf9d66eeb211d89a77be40de22b6c89d') peer_public_key = unhexlify(
result = misc.get_ecdh_session_key(self.client, identity=identity, peer_public_key=peer_public_key, ecdsa_curve_name='secp256k1') "0407f2c6e5becf3213c1d07df0cfbe8e39f70a8c643df7575e5c56859ec52c45ca950499c019719dae0fda04248d851e52cf9d66eeb211d89a77be40de22b6c89d"
assert result.session_key == unhexlify('0495e5d8c9e5cc09e7cf4908774f52decb381ce97f2fc9ba56e959c13f03f9f47a03dd151cbc908bc1db84d46e2c33e7bbb9daddc800f985244c924fd64adf6647') )
result = misc.get_ecdh_session_key(
self.client,
identity=identity,
peer_public_key=peer_public_key,
ecdsa_curve_name="secp256k1",
)
assert result.session_key == unhexlify(
"0495e5d8c9e5cc09e7cf4908774f52decb381ce97f2fc9ba56e959c13f03f9f47a03dd151cbc908bc1db84d46e2c33e7bbb9daddc800f985244c924fd64adf6647"
)
peer_public_key = unhexlify('04811a6c2bd2a547d0dd84747297fec47719e7c3f9b0024f027c2b237be99aac39a9230acbd163d0cb1524a0f5ea4bfed6058cec6f18368f72a12aa0c4d083ff64') peer_public_key = unhexlify(
result = misc.get_ecdh_session_key(self.client, identity=identity, peer_public_key=peer_public_key, ecdsa_curve_name='nist256p1') "04811a6c2bd2a547d0dd84747297fec47719e7c3f9b0024f027c2b237be99aac39a9230acbd163d0cb1524a0f5ea4bfed6058cec6f18368f72a12aa0c4d083ff64"
assert result.session_key == unhexlify('046d1f5c48af2cf2c57076ac2c9d7808db2086f614cb7b8107119ff2c6270cd209749809efe0196f01a0cc633788cef1f4a2bd650c99570d06962f923fca6d8fdf') )
result = misc.get_ecdh_session_key(
self.client,
identity=identity,
peer_public_key=peer_public_key,
ecdsa_curve_name="nist256p1",
)
assert result.session_key == unhexlify(
"046d1f5c48af2cf2c57076ac2c9d7808db2086f614cb7b8107119ff2c6270cd209749809efe0196f01a0cc633788cef1f4a2bd650c99570d06962f923fca6d8fdf"
)
peer_public_key = unhexlify('40a8cf4b6a64c4314e80f15a8ea55812bd735fbb365936a48b2d78807b575fa17a') peer_public_key = unhexlify(
result = misc.get_ecdh_session_key(self.client, identity=identity, peer_public_key=peer_public_key, ecdsa_curve_name='curve25519') "40a8cf4b6a64c4314e80f15a8ea55812bd735fbb365936a48b2d78807b575fa17a"
assert result.session_key == unhexlify('04e24516669e0b7d3d72e5129fddd07b6644c30915f5c8b7f1f62324afb3624311') )
result = misc.get_ecdh_session_key(
self.client,
identity=identity,
peer_public_key=peer_public_key,
ecdsa_curve_name="curve25519",
)
assert result.session_key == unhexlify(
"04e24516669e0b7d3d72e5129fddd07b6644c30915f5c8b7f1f62324afb3624311"
)

View File

@ -14,42 +14,121 @@
# You should have received a copy of the License along with this library. # You should have received a copy of the License along with this library.
# If not, see <https://www.gnu.org/licenses/lgpl-3.0.html>. # If not, see <https://www.gnu.org/licenses/lgpl-3.0.html>.
from .common import TrezorTest
from ..support import ckd_public as bip32
from trezorlib.tools import H_
from trezorlib import btc from trezorlib import btc
from trezorlib.tools import H_
from ..support import ckd_public as bip32
from .common import TrezorTest
class TestMsgGetpublickey(TrezorTest): class TestMsgGetpublickey(TrezorTest):
def test_btc(self): def test_btc(self):
self.setup_mnemonic_nopin_nopassphrase() self.setup_mnemonic_nopin_nopassphrase()
assert bip32.serialize(btc.get_public_node(self.client, []).node, 0x0488B21E) == 'xpub661MyMwAqRbcF1zGijBb2K6x9YiJPh58xpcCeLvTxMX6spkY3PcpJ4ABcCyWfskq5DDxM3e6Ez5ePCqG5bnPUXR4wL8TZWyoDaUdiWW7bKy' assert (
assert btc.get_public_node(self.client, [], coin_name='Bitcoin').xpub == 'xpub661MyMwAqRbcF1zGijBb2K6x9YiJPh58xpcCeLvTxMX6spkY3PcpJ4ABcCyWfskq5DDxM3e6Ez5ePCqG5bnPUXR4wL8TZWyoDaUdiWW7bKy' bip32.serialize(btc.get_public_node(self.client, []).node, 0x0488B21E)
assert bip32.serialize(btc.get_public_node(self.client, [1]).node, 0x0488B21E) == 'xpub68zNxjsTrV8y9AadThLW7dTAqEpZ7xBLFSyJ3X9pjTv6Njg6kxgjXJkzxq8u3ttnjBw1jupQHMP3gpGZzZqd1eh5S4GjkaMhPR18vMyUi8N' == "xpub661MyMwAqRbcF1zGijBb2K6x9YiJPh58xpcCeLvTxMX6spkY3PcpJ4ABcCyWfskq5DDxM3e6Ez5ePCqG5bnPUXR4wL8TZWyoDaUdiWW7bKy"
assert btc.get_public_node(self.client, [1], coin_name='Bitcoin').xpub == 'xpub68zNxjsTrV8y9AadThLW7dTAqEpZ7xBLFSyJ3X9pjTv6Njg6kxgjXJkzxq8u3ttnjBw1jupQHMP3gpGZzZqd1eh5S4GjkaMhPR18vMyUi8N' )
assert bip32.serialize(btc.get_public_node(self.client, [0, H_(1)]).node, 0x0488B21E) == 'xpub6A3FoZqYXj1AbW4thRwBh26YwZWbmoyjTaZwwxJjY1oKUpefLepL3RFS9DHKQrjAfxDrzDepYMDZPqXN6upQm3bHQ9xaXD5a3mqni3goF4v' assert (
assert btc.get_public_node(self.client, [0, H_(1)], coin_name='Bitcoin').xpub == 'xpub6A3FoZqYXj1AbW4thRwBh26YwZWbmoyjTaZwwxJjY1oKUpefLepL3RFS9DHKQrjAfxDrzDepYMDZPqXN6upQm3bHQ9xaXD5a3mqni3goF4v' btc.get_public_node(self.client, [], coin_name="Bitcoin").xpub
assert bip32.serialize(btc.get_public_node(self.client, [H_(9), 0]).node, 0x0488B21E) == 'xpub6A2h5mzLDfYginoD7q7wCWbq18wTbN9gducRr2w5NRTwdLeoT3cJSwefFqW7uXTpVFGtpUyDMBNYs3DNvvXx6NPjF9YEbUQrtxFSWnPtVrv' == "xpub661MyMwAqRbcF1zGijBb2K6x9YiJPh58xpcCeLvTxMX6spkY3PcpJ4ABcCyWfskq5DDxM3e6Ez5ePCqG5bnPUXR4wL8TZWyoDaUdiWW7bKy"
assert btc.get_public_node(self.client, [H_(9), 0], coin_name='Bitcoin').xpub == 'xpub6A2h5mzLDfYginoD7q7wCWbq18wTbN9gducRr2w5NRTwdLeoT3cJSwefFqW7uXTpVFGtpUyDMBNYs3DNvvXx6NPjF9YEbUQrtxFSWnPtVrv' )
assert bip32.serialize(btc.get_public_node(self.client, [0, 9999999]).node, 0x0488B21E) == 'xpub6A3FoZqQEK6iwLZ4HFkqSo5fb35BH4bpjC4SPZ63prfLdGYPwYxEuC6o91bUvFFdMzKWe5rs3axHRUjxJaSvBnKKFtnfLwDACRxPxabsv2r' assert (
assert btc.get_public_node(self.client, [0, 9999999], coin_name='Bitcoin').xpub == 'xpub6A3FoZqQEK6iwLZ4HFkqSo5fb35BH4bpjC4SPZ63prfLdGYPwYxEuC6o91bUvFFdMzKWe5rs3axHRUjxJaSvBnKKFtnfLwDACRxPxabsv2r' bip32.serialize(btc.get_public_node(self.client, [1]).node, 0x0488B21E)
== "xpub68zNxjsTrV8y9AadThLW7dTAqEpZ7xBLFSyJ3X9pjTv6Njg6kxgjXJkzxq8u3ttnjBw1jupQHMP3gpGZzZqd1eh5S4GjkaMhPR18vMyUi8N"
)
assert (
btc.get_public_node(self.client, [1], coin_name="Bitcoin").xpub
== "xpub68zNxjsTrV8y9AadThLW7dTAqEpZ7xBLFSyJ3X9pjTv6Njg6kxgjXJkzxq8u3ttnjBw1jupQHMP3gpGZzZqd1eh5S4GjkaMhPR18vMyUi8N"
)
assert (
bip32.serialize(
btc.get_public_node(self.client, [0, H_(1)]).node, 0x0488B21E
)
== "xpub6A3FoZqYXj1AbW4thRwBh26YwZWbmoyjTaZwwxJjY1oKUpefLepL3RFS9DHKQrjAfxDrzDepYMDZPqXN6upQm3bHQ9xaXD5a3mqni3goF4v"
)
assert (
btc.get_public_node(self.client, [0, H_(1)], coin_name="Bitcoin").xpub
== "xpub6A3FoZqYXj1AbW4thRwBh26YwZWbmoyjTaZwwxJjY1oKUpefLepL3RFS9DHKQrjAfxDrzDepYMDZPqXN6upQm3bHQ9xaXD5a3mqni3goF4v"
)
assert (
bip32.serialize(
btc.get_public_node(self.client, [H_(9), 0]).node, 0x0488B21E
)
== "xpub6A2h5mzLDfYginoD7q7wCWbq18wTbN9gducRr2w5NRTwdLeoT3cJSwefFqW7uXTpVFGtpUyDMBNYs3DNvvXx6NPjF9YEbUQrtxFSWnPtVrv"
)
assert (
btc.get_public_node(self.client, [H_(9), 0], coin_name="Bitcoin").xpub
== "xpub6A2h5mzLDfYginoD7q7wCWbq18wTbN9gducRr2w5NRTwdLeoT3cJSwefFqW7uXTpVFGtpUyDMBNYs3DNvvXx6NPjF9YEbUQrtxFSWnPtVrv"
)
assert (
bip32.serialize(
btc.get_public_node(self.client, [0, 9999999]).node, 0x0488B21E
)
== "xpub6A3FoZqQEK6iwLZ4HFkqSo5fb35BH4bpjC4SPZ63prfLdGYPwYxEuC6o91bUvFFdMzKWe5rs3axHRUjxJaSvBnKKFtnfLwDACRxPxabsv2r"
)
assert (
btc.get_public_node(self.client, [0, 9999999], coin_name="Bitcoin").xpub
== "xpub6A3FoZqQEK6iwLZ4HFkqSo5fb35BH4bpjC4SPZ63prfLdGYPwYxEuC6o91bUvFFdMzKWe5rs3axHRUjxJaSvBnKKFtnfLwDACRxPxabsv2r"
)
def test_ltc(self): def test_ltc(self):
self.setup_mnemonic_nopin_nopassphrase() self.setup_mnemonic_nopin_nopassphrase()
assert bip32.serialize(btc.get_public_node(self.client, []).node, 0x019DA462) == 'Ltub2SSUS19CirucVPGDKDBatBDBEM2s9UbH66pBURfaKrMocCPLhQ7Z7hecy5VYLHA5fRdXwB2e61j2VJCNzVsqKTCVEU1vECjqi5EyczFX9xp' assert (
assert btc.get_public_node(self.client, [], coin_name='Litecoin').xpub == 'Ltub2SSUS19CirucVPGDKDBatBDBEM2s9UbH66pBURfaKrMocCPLhQ7Z7hecy5VYLHA5fRdXwB2e61j2VJCNzVsqKTCVEU1vECjqi5EyczFX9xp' bip32.serialize(btc.get_public_node(self.client, []).node, 0x019DA462)
assert bip32.serialize(btc.get_public_node(self.client, [1]).node, 0x019DA462) == 'Ltub2VRVRP5VjvSyPXra4BLVyVZPv397sjhUNjBGsbtw6xko77JuQyBULxFSKheviJJ3KQLbL3Cx8P2RnudguTw4raUVjCACRG7jsumUptYx55C' == "Ltub2SSUS19CirucVPGDKDBatBDBEM2s9UbH66pBURfaKrMocCPLhQ7Z7hecy5VYLHA5fRdXwB2e61j2VJCNzVsqKTCVEU1vECjqi5EyczFX9xp"
assert btc.get_public_node(self.client, [1], coin_name='Litecoin').xpub == 'Ltub2VRVRP5VjvSyPXra4BLVyVZPv397sjhUNjBGsbtw6xko77JuQyBULxFSKheviJJ3KQLbL3Cx8P2RnudguTw4raUVjCACRG7jsumUptYx55C' )
assert bip32.serialize(btc.get_public_node(self.client, [0, H_(1)]).node, 0x019DA462) == 'Ltub2WUNGD3aRAKAqsLqHuwBYtCn2MqAXbVsarmvn33quWe2DCHTzfK4s4jsW5oM5G8RGAdSaM3NPNrwVvtV1ourbyNhhHr3BtqcYGc8caf5GoT' assert (
assert btc.get_public_node(self.client, [0, H_(1)], coin_name='Litecoin').xpub == 'Ltub2WUNGD3aRAKAqsLqHuwBYtCn2MqAXbVsarmvn33quWe2DCHTzfK4s4jsW5oM5G8RGAdSaM3NPNrwVvtV1ourbyNhhHr3BtqcYGc8caf5GoT' btc.get_public_node(self.client, [], coin_name="Litecoin").xpub
assert bip32.serialize(btc.get_public_node(self.client, [H_(9), 0]).node, 0x019DA462) == 'Ltub2WToYRCN76rgyA59iK7w4Ni45wG2M9fpmBpQg7gBjvJeMiHc7473Gb96ci29Zvs55TgUQcMmCD1vy8aVqpdPwJB9YHRhGAAuPT1nRLLXmFu' == "Ltub2SSUS19CirucVPGDKDBatBDBEM2s9UbH66pBURfaKrMocCPLhQ7Z7hecy5VYLHA5fRdXwB2e61j2VJCNzVsqKTCVEU1vECjqi5EyczFX9xp"
assert btc.get_public_node(self.client, [H_(9), 0], coin_name='Litecoin').xpub == 'Ltub2WToYRCN76rgyA59iK7w4Ni45wG2M9fpmBpQg7gBjvJeMiHc7473Gb96ci29Zvs55TgUQcMmCD1vy8aVqpdPwJB9YHRhGAAuPT1nRLLXmFu' )
assert bip32.serialize(btc.get_public_node(self.client, [0, 9999999]).node, 0x019DA462) == 'Ltub2WUNGD3S7kQjBhpzsjkqJfBtfqPk2r7xrUGRDdqACMW3MeBCbZSyiqbEVt7WaeesxCj6EDFQtcbfXa75DUYN2i6jZ2g81cyCgvijs9J2u2n' assert (
assert btc.get_public_node(self.client, [0, 9999999], coin_name='Litecoin').xpub == 'Ltub2WUNGD3S7kQjBhpzsjkqJfBtfqPk2r7xrUGRDdqACMW3MeBCbZSyiqbEVt7WaeesxCj6EDFQtcbfXa75DUYN2i6jZ2g81cyCgvijs9J2u2n' bip32.serialize(btc.get_public_node(self.client, [1]).node, 0x019DA462)
== "Ltub2VRVRP5VjvSyPXra4BLVyVZPv397sjhUNjBGsbtw6xko77JuQyBULxFSKheviJJ3KQLbL3Cx8P2RnudguTw4raUVjCACRG7jsumUptYx55C"
)
assert (
btc.get_public_node(self.client, [1], coin_name="Litecoin").xpub
== "Ltub2VRVRP5VjvSyPXra4BLVyVZPv397sjhUNjBGsbtw6xko77JuQyBULxFSKheviJJ3KQLbL3Cx8P2RnudguTw4raUVjCACRG7jsumUptYx55C"
)
assert (
bip32.serialize(
btc.get_public_node(self.client, [0, H_(1)]).node, 0x019DA462
)
== "Ltub2WUNGD3aRAKAqsLqHuwBYtCn2MqAXbVsarmvn33quWe2DCHTzfK4s4jsW5oM5G8RGAdSaM3NPNrwVvtV1ourbyNhhHr3BtqcYGc8caf5GoT"
)
assert (
btc.get_public_node(self.client, [0, H_(1)], coin_name="Litecoin").xpub
== "Ltub2WUNGD3aRAKAqsLqHuwBYtCn2MqAXbVsarmvn33quWe2DCHTzfK4s4jsW5oM5G8RGAdSaM3NPNrwVvtV1ourbyNhhHr3BtqcYGc8caf5GoT"
)
assert (
bip32.serialize(
btc.get_public_node(self.client, [H_(9), 0]).node, 0x019DA462
)
== "Ltub2WToYRCN76rgyA59iK7w4Ni45wG2M9fpmBpQg7gBjvJeMiHc7473Gb96ci29Zvs55TgUQcMmCD1vy8aVqpdPwJB9YHRhGAAuPT1nRLLXmFu"
)
assert (
btc.get_public_node(self.client, [H_(9), 0], coin_name="Litecoin").xpub
== "Ltub2WToYRCN76rgyA59iK7w4Ni45wG2M9fpmBpQg7gBjvJeMiHc7473Gb96ci29Zvs55TgUQcMmCD1vy8aVqpdPwJB9YHRhGAAuPT1nRLLXmFu"
)
assert (
bip32.serialize(
btc.get_public_node(self.client, [0, 9999999]).node, 0x019DA462
)
== "Ltub2WUNGD3S7kQjBhpzsjkqJfBtfqPk2r7xrUGRDdqACMW3MeBCbZSyiqbEVt7WaeesxCj6EDFQtcbfXa75DUYN2i6jZ2g81cyCgvijs9J2u2n"
)
assert (
btc.get_public_node(self.client, [0, 9999999], coin_name="Litecoin").xpub
== "Ltub2WUNGD3S7kQjBhpzsjkqJfBtfqPk2r7xrUGRDdqACMW3MeBCbZSyiqbEVt7WaeesxCj6EDFQtcbfXa75DUYN2i6jZ2g81cyCgvijs9J2u2n"
)
def test_tbtc(self): def test_tbtc(self):
self.setup_mnemonic_nopin_nopassphrase() self.setup_mnemonic_nopin_nopassphrase()
assert bip32.serialize(btc.get_public_node(self.client, [111, 42]).node, 0x043587CF) == 'tpubDAgixSyai5PWbc8N1mBkHDR5nLgAnHFtY7r4y5EzxqAxrt9YUDpZL3kaRoHVvCfrcwNo31c2isBP2uTHcZxEosuKbyJhCAbrvGoPuLUZ7Mz' assert (
assert btc.get_public_node(self.client, [111, 42], coin_name='Testnet').xpub == 'tpubDAgixSyai5PWbc8N1mBkHDR5nLgAnHFtY7r4y5EzxqAxrt9YUDpZL3kaRoHVvCfrcwNo31c2isBP2uTHcZxEosuKbyJhCAbrvGoPuLUZ7Mz' bip32.serialize(
btc.get_public_node(self.client, [111, 42]).node, 0x043587CF
)
== "tpubDAgixSyai5PWbc8N1mBkHDR5nLgAnHFtY7r4y5EzxqAxrt9YUDpZL3kaRoHVvCfrcwNo31c2isBP2uTHcZxEosuKbyJhCAbrvGoPuLUZ7Mz"
)
assert (
btc.get_public_node(self.client, [111, 42], coin_name="Testnet").xpub
== "tpubDAgixSyai5PWbc8N1mBkHDR5nLgAnHFtY7r4y5EzxqAxrt9YUDpZL3kaRoHVvCfrcwNo31c2isBP2uTHcZxEosuKbyJhCAbrvGoPuLUZ7Mz"
)

View File

@ -15,35 +15,84 @@
# If not, see <https://www.gnu.org/licenses/lgpl-3.0.html>. # If not, see <https://www.gnu.org/licenses/lgpl-3.0.html>.
from binascii import hexlify from binascii import hexlify
import pytest import pytest
from .common import TrezorTest
from trezorlib.tools import CallException, H_
from trezorlib import btc from trezorlib import btc
from trezorlib.tools import H_, CallException
from .common import TrezorTest
class TestMsgGetpublickeyCurve(TrezorTest): class TestMsgGetpublickeyCurve(TrezorTest):
def test_default_curve(self): def test_default_curve(self):
self.setup_mnemonic_nopin_nopassphrase() self.setup_mnemonic_nopin_nopassphrase()
assert hexlify(btc.get_public_node(self.client, [H_(111), 42]).node.public_key).decode() == '02e7fcec053f0df94d88c86447970743e8a1979d242d09338dcf8687a9966f7fbc' assert (
assert hexlify(btc.get_public_node(self.client, [H_(111), H_(42)]).node.public_key).decode() == '03ce7b690969d773ba9ed212464eb2b534b87b9b8a9383300bddabe1f093f79220' hexlify(btc.get_public_node(self.client, [H_(111), 42]).node.public_key)
== b"02e7fcec053f0df94d88c86447970743e8a1979d242d09338dcf8687a9966f7fbc"
)
assert (
hexlify(btc.get_public_node(self.client, [H_(111), H_(42)]).node.public_key)
== b"03ce7b690969d773ba9ed212464eb2b534b87b9b8a9383300bddabe1f093f79220"
)
def test_secp256k1_curve(self): def test_secp256k1_curve(self):
self.setup_mnemonic_nopin_nopassphrase() self.setup_mnemonic_nopin_nopassphrase()
assert hexlify(btc.get_public_node(self.client, [H_(111), 42], ecdsa_curve_name='secp256k1').node.public_key).decode() == '02e7fcec053f0df94d88c86447970743e8a1979d242d09338dcf8687a9966f7fbc' assert (
assert hexlify(btc.get_public_node(self.client, [H_(111), H_(42)], ecdsa_curve_name='secp256k1').node.public_key).decode() == '03ce7b690969d773ba9ed212464eb2b534b87b9b8a9383300bddabe1f093f79220' hexlify(
btc.get_public_node(
self.client, [H_(111), 42], ecdsa_curve_name="secp256k1"
).node.public_key
)
== b"02e7fcec053f0df94d88c86447970743e8a1979d242d09338dcf8687a9966f7fbc"
)
assert (
hexlify(
btc.get_public_node(
self.client, [H_(111), H_(42)], ecdsa_curve_name="secp256k1"
).node.public_key
)
== b"03ce7b690969d773ba9ed212464eb2b534b87b9b8a9383300bddabe1f093f79220"
)
def test_nist256p1_curve(self): def test_nist256p1_curve(self):
self.setup_mnemonic_nopin_nopassphrase() self.setup_mnemonic_nopin_nopassphrase()
assert hexlify(btc.get_public_node(self.client, [H_(111), 42], ecdsa_curve_name='nist256p1').node.public_key).decode() == '02a9ce59b32bd64a70bc52aca96e5d09af65c6b9593ba2a60af8fccfe1437f2129' assert (
assert hexlify(btc.get_public_node(self.client, [H_(111), H_(42)], ecdsa_curve_name='nist256p1').node.public_key).decode() == '026fe35d8afed67dbf0561a1d32922e8ad0cd0d86effbc82be970cbed7d9bab2c2' hexlify(
btc.get_public_node(
self.client, [H_(111), 42], ecdsa_curve_name="nist256p1"
).node.public_key
)
== b"02a9ce59b32bd64a70bc52aca96e5d09af65c6b9593ba2a60af8fccfe1437f2129"
)
assert (
hexlify(
btc.get_public_node(
self.client, [H_(111), H_(42)], ecdsa_curve_name="nist256p1"
).node.public_key
)
== b"026fe35d8afed67dbf0561a1d32922e8ad0cd0d86effbc82be970cbed7d9bab2c2"
)
def test_ed25519_curve(self): def test_ed25519_curve(self):
self.setup_mnemonic_nopin_nopassphrase() self.setup_mnemonic_nopin_nopassphrase()
# ed25519 curve does not support public derivation, so test only private derivation paths # ed25519 curve does not support public derivation, so test only private derivation paths
assert hexlify(btc.get_public_node(self.client, [H_(111), H_(42)], ecdsa_curve_name='ed25519').node.public_key).decode() == '0069a14b478e508eab6e93303f4e6f5c50b8136627830f2ed5c3a835fc6c0ea2b7' assert (
assert hexlify(btc.get_public_node(self.client, [H_(111), H_(65535)], ecdsa_curve_name='ed25519').node.public_key).decode() == '00514f73a05184458611b14c348fee4fd988d36cf3aee7207737861bac611de991' hexlify(
btc.get_public_node(
self.client, [H_(111), H_(42)], ecdsa_curve_name="ed25519"
).node.public_key
)
== b"0069a14b478e508eab6e93303f4e6f5c50b8136627830f2ed5c3a835fc6c0ea2b7"
)
assert (
hexlify(
btc.get_public_node(
self.client, [H_(111), H_(65535)], ecdsa_curve_name="ed25519"
).node.public_key
)
== b"00514f73a05184458611b14c348fee4fd988d36cf3aee7207737861bac611de991"
)
# test failure when using public derivation # test failure when using public derivation
with pytest.raises(CallException): with pytest.raises(CallException):
btc.get_public_node(self.client, [H_(111), 42], ecdsa_curve_name='ed25519') btc.get_public_node(self.client, [H_(111), 42], ecdsa_curve_name="ed25519")

View File

@ -16,20 +16,23 @@
import pytest import pytest
from .common import TrezorTest
from trezorlib import lisk from trezorlib import lisk
from trezorlib.tools import parse_path from trezorlib.tools import parse_path
from .common import TrezorTest
LISK_PATH = parse_path("m/44h/134h/0h/1h") LISK_PATH = parse_path("m/44h/134h/0h/1h")
@pytest.mark.lisk @pytest.mark.lisk
@pytest.mark.skip_t1 @pytest.mark.skip_t1
class TestMsgLiskGetaddress(TrezorTest): class TestMsgLiskGetaddress(TrezorTest):
def test_lisk_getaddress(self): def test_lisk_getaddress(self):
self.setup_mnemonic_nopin_nopassphrase() self.setup_mnemonic_nopin_nopassphrase()
assert lisk.get_address(self.client, LISK_PATH[:2]) == '1431530009238518937L' assert lisk.get_address(self.client, LISK_PATH[:2]) == "1431530009238518937L"
assert lisk.get_address(self.client, LISK_PATH[:3]) == '17563781916205589679L' assert lisk.get_address(self.client, LISK_PATH[:3]) == "17563781916205589679L"
assert lisk.get_address(self.client, LISK_PATH) == '1874186517773691964L' assert lisk.get_address(self.client, LISK_PATH) == "1874186517773691964L"
assert lisk.get_address(self.client, parse_path("m/44h/134h/999h/999h")) == '16295203558710684671L' assert (
lisk.get_address(self.client, parse_path("m/44h/134h/999h/999h"))
== "16295203558710684671L"
)

View File

@ -15,20 +15,24 @@
# If not, see <https://www.gnu.org/licenses/lgpl-3.0.html>. # If not, see <https://www.gnu.org/licenses/lgpl-3.0.html>.
from binascii import hexlify from binascii import hexlify
import pytest import pytest
from .common import TrezorTest
from trezorlib import lisk from trezorlib import lisk
from trezorlib.tools import parse_path from trezorlib.tools import parse_path
from .common import TrezorTest
LISK_PATH = parse_path("m/44h/134h/0h/0h") LISK_PATH = parse_path("m/44h/134h/0h/0h")
@pytest.mark.lisk @pytest.mark.lisk
@pytest.mark.skip_t1 @pytest.mark.skip_t1
class TestMsgLiskGetPublicKey(TrezorTest): class TestMsgLiskGetPublicKey(TrezorTest):
def test_lisk_get_public_key(self): def test_lisk_get_public_key(self):
self.setup_mnemonic_nopin_nopassphrase() self.setup_mnemonic_nopin_nopassphrase()
sig = lisk.get_public_key(self.client, LISK_PATH) sig = lisk.get_public_key(self.client, LISK_PATH)
assert hexlify(sig.public_key) == b'eb56d7bbb5e8ea9269405f7a8527fe126023d1db2c973cfac6f760b60ae27294' assert (
hexlify(sig.public_key)
== b"eb56d7bbb5e8ea9269405f7a8527fe126023d1db2c973cfac6f760b60ae27294"
)

View File

@ -15,27 +15,42 @@
# If not, see <https://www.gnu.org/licenses/lgpl-3.0.html>. # If not, see <https://www.gnu.org/licenses/lgpl-3.0.html>.
from binascii import hexlify from binascii import hexlify
import pytest import pytest
from .common import TrezorTest
from trezorlib import lisk from trezorlib import lisk
from trezorlib.tools import parse_path from trezorlib.tools import parse_path
from .common import TrezorTest
LISK_PATH = parse_path("m/44h/134h/0h/0h") LISK_PATH = parse_path("m/44h/134h/0h/0h")
@pytest.mark.lisk @pytest.mark.lisk
@pytest.mark.skip_t1 @pytest.mark.skip_t1
class TestMsgLiskSignmessage(TrezorTest): class TestMsgLiskSignmessage(TrezorTest):
def test_sign(self): def test_sign(self):
self.setup_mnemonic_nopin_nopassphrase() self.setup_mnemonic_nopin_nopassphrase()
sig = lisk.sign_message(self.client, LISK_PATH, 'This is an example of a signed message.') sig = lisk.sign_message(
assert hexlify(sig.public_key) == b'eb56d7bbb5e8ea9269405f7a8527fe126023d1db2c973cfac6f760b60ae27294' self.client, LISK_PATH, "This is an example of a signed message."
assert hexlify(sig.signature) == b'7858ae7cd52ea6d4b17e800ca60144423db5560bfd618b663ffbf26ab66758563df45cbffae8463db22dc285dd94309083b8c807776085b97d05374d79867d05' )
assert (
hexlify(sig.public_key)
== b"eb56d7bbb5e8ea9269405f7a8527fe126023d1db2c973cfac6f760b60ae27294"
)
assert (
hexlify(sig.signature)
== b"7858ae7cd52ea6d4b17e800ca60144423db5560bfd618b663ffbf26ab66758563df45cbffae8463db22dc285dd94309083b8c807776085b97d05374d79867d05"
)
def test_sign_long(self): def test_sign_long(self):
self.setup_mnemonic_nopin_nopassphrase() self.setup_mnemonic_nopin_nopassphrase()
sig = lisk.sign_message(self.client, LISK_PATH, 'VeryLongMessage!' * 64) sig = lisk.sign_message(self.client, LISK_PATH, "VeryLongMessage!" * 64)
assert hexlify(sig.public_key) == b'eb56d7bbb5e8ea9269405f7a8527fe126023d1db2c973cfac6f760b60ae27294' assert (
assert hexlify(sig.signature) == b'19c26f4b6f2ecf2feef57d22237cf97eb7862fdc2fb8c303878843f5dd728191f7837cf8d0ed41f8e470b15181223a3a5131881add9c22b2453b01be4edef104' hexlify(sig.public_key)
== b"eb56d7bbb5e8ea9269405f7a8527fe126023d1db2c973cfac6f760b60ae27294"
)
assert (
hexlify(sig.signature)
== b"19c26f4b6f2ecf2feef57d22237cf97eb7862fdc2fb8c303878843f5dd728191f7837cf8d0ed41f8e470b15181223a3a5131881add9c22b2453b01be4edef104"
)

View File

@ -15,162 +15,206 @@
# If not, see <https://www.gnu.org/licenses/lgpl-3.0.html>. # If not, see <https://www.gnu.org/licenses/lgpl-3.0.html>.
from binascii import unhexlify from binascii import unhexlify
import pytest import pytest
from .common import TrezorTest from trezorlib import lisk, messages as proto
from trezorlib import messages as proto
from trezorlib.tools import parse_path from trezorlib.tools import parse_path
from trezorlib import lisk
PUBLIC_KEY = unhexlify('eb56d7bbb5e8ea9269405f7a8527fe126023d1db2c973cfac6f760b60ae27294') from .common import TrezorTest
PUBLIC_KEY = unhexlify(
"eb56d7bbb5e8ea9269405f7a8527fe126023d1db2c973cfac6f760b60ae27294"
)
@pytest.mark.lisk @pytest.mark.lisk
@pytest.mark.skip_t1 @pytest.mark.skip_t1
class TestMsgLiskSignTx(TrezorTest): class TestMsgLiskSignTx(TrezorTest):
def test_lisk_sign_tx_send(self): def test_lisk_sign_tx_send(self):
self.setup_mnemonic_nopin_nopassphrase() self.setup_mnemonic_nopin_nopassphrase()
with self.client: with self.client:
self.client.set_expected_responses([ self.client.set_expected_responses(
proto.ButtonRequest(code=proto.ButtonRequestType.SignTx), [
proto.ButtonRequest(code=proto.ButtonRequestType.ConfirmOutput), proto.ButtonRequest(code=proto.ButtonRequestType.SignTx),
proto.LiskSignedTx( proto.ButtonRequest(code=proto.ButtonRequestType.ConfirmOutput),
signature=unhexlify('b62717d581e5713bca60b758b661e6cfa091addc6caedd57534e06cda805943ee80797b9fb9a1e1b2bd584e292d2a7f832a4d1b3f15f00e1ee1b72de7e195a08') proto.LiskSignedTx(
) signature=unhexlify(
]) "b62717d581e5713bca60b758b661e6cfa091addc6caedd57534e06cda805943ee80797b9fb9a1e1b2bd584e292d2a7f832a4d1b3f15f00e1ee1b72de7e195a08"
)
),
]
)
lisk.sign_tx(self.client, parse_path("m/44'/134'/0'/0'"), { lisk.sign_tx(
"amount": "10000000", self.client,
"recipientId": "9971262264659915921L", parse_path("m/44'/134'/0'/0'"),
"timestamp": 57525937, {
"type": 0, "amount": "10000000",
"fee": "10000000", "recipientId": "9971262264659915921L",
"asset": {} "timestamp": 57525937,
}) "type": 0,
"fee": "10000000",
"asset": {},
},
)
def test_lisk_sign_tx_send_with_data(self): def test_lisk_sign_tx_send_with_data(self):
self.setup_mnemonic_nopin_nopassphrase() self.setup_mnemonic_nopin_nopassphrase()
with self.client: with self.client:
self.client.set_expected_responses([ self.client.set_expected_responses(
proto.ButtonRequest(code=proto.ButtonRequestType.SignTx), [
proto.ButtonRequest(code=proto.ButtonRequestType.ConfirmOutput), proto.ButtonRequest(code=proto.ButtonRequestType.SignTx),
proto.LiskSignedTx( proto.ButtonRequest(code=proto.ButtonRequestType.ConfirmOutput),
signature=unhexlify('5dd0dbb87ee46f3e985b1ef2df85cb0bec481e8601d150388f73e198cdd57a698eab076c7cd5b281fbb6a83dd3dc64d91a6eccd1614dffd46f101194ffa3a004') proto.LiskSignedTx(
) signature=unhexlify(
]) "5dd0dbb87ee46f3e985b1ef2df85cb0bec481e8601d150388f73e198cdd57a698eab076c7cd5b281fbb6a83dd3dc64d91a6eccd1614dffd46f101194ffa3a004"
)
),
]
)
lisk.sign_tx(self.client, parse_path("m/44'/134'/0'/0'"), { lisk.sign_tx(
"amount": "10000000", self.client,
"recipientId": "9971262264659915921L", parse_path("m/44'/134'/0'/0'"),
"timestamp": 57525937, {
"type": 0, "amount": "10000000",
"fee": "20000000", "recipientId": "9971262264659915921L",
"asset": { "timestamp": 57525937,
"data": "Test data" "type": 0,
} "fee": "20000000",
}) "asset": {"data": "Test data"},
},
)
def test_lisk_sign_tx_second_signature(self): def test_lisk_sign_tx_second_signature(self):
self.setup_mnemonic_nopin_nopassphrase() self.setup_mnemonic_nopin_nopassphrase()
with self.client: with self.client:
self.client.set_expected_responses([ self.client.set_expected_responses(
proto.ButtonRequest(code=proto.ButtonRequestType.PublicKey), [
proto.ButtonRequest(code=proto.ButtonRequestType.ConfirmOutput), proto.ButtonRequest(code=proto.ButtonRequestType.PublicKey),
proto.LiskSignedTx( proto.ButtonRequest(code=proto.ButtonRequestType.ConfirmOutput),
signature=unhexlify('f02bdc40a7599c21d29db4080ff1ff8934f76eedf5b0c4fa695c8a64af2f0b40a5c4f92db203863eebbbfad8f0611a23f451ed8bb711490234cdfb034728fd01') proto.LiskSignedTx(
) signature=unhexlify(
]) "f02bdc40a7599c21d29db4080ff1ff8934f76eedf5b0c4fa695c8a64af2f0b40a5c4f92db203863eebbbfad8f0611a23f451ed8bb711490234cdfb034728fd01"
)
),
]
)
lisk.sign_tx(self.client, parse_path("m/44'/134'/0'/0'"), { lisk.sign_tx(
"amount": "0", self.client,
"timestamp": 57525937, parse_path("m/44'/134'/0'/0'"),
"type": 1, {
"fee": "500000000", "amount": "0",
"asset": { "timestamp": 57525937,
"signature": { "type": 1,
"publicKey": "5d036a858ce89f844491762eb89e2bfbd50a4a0a0da658e4b2628b25b117ae09" "fee": "500000000",
} "asset": {
} "signature": {
}) "publicKey": "5d036a858ce89f844491762eb89e2bfbd50a4a0a0da658e4b2628b25b117ae09"
}
},
},
)
def test_lisk_sign_tx_delegate_registration(self): def test_lisk_sign_tx_delegate_registration(self):
self.setup_mnemonic_nopin_nopassphrase() self.setup_mnemonic_nopin_nopassphrase()
with self.client: with self.client:
self.client.set_expected_responses([ self.client.set_expected_responses(
proto.ButtonRequest(code=proto.ButtonRequestType.SignTx), [
proto.ButtonRequest(code=proto.ButtonRequestType.ConfirmOutput), proto.ButtonRequest(code=proto.ButtonRequestType.SignTx),
proto.LiskSignedTx( proto.ButtonRequest(code=proto.ButtonRequestType.ConfirmOutput),
signature=unhexlify('5ac02b2882b9d7d0f944e48baadc27de1296cc08c3533f7c8e380fbbb9fb4a6ac81b5dc57060d7d8c68912eea24eb6e39024801bccc0d55020e2052b0c2bb701') proto.LiskSignedTx(
) signature=unhexlify(
]) "5ac02b2882b9d7d0f944e48baadc27de1296cc08c3533f7c8e380fbbb9fb4a6ac81b5dc57060d7d8c68912eea24eb6e39024801bccc0d55020e2052b0c2bb701"
)
),
]
)
lisk.sign_tx(self.client, parse_path("m/44'/134'/0'/0'"), { lisk.sign_tx(
"amount": "0", self.client,
"timestamp": 57525937, parse_path("m/44'/134'/0'/0'"),
"type": 2, {
"fee": "2500000000", "amount": "0",
"asset": { "timestamp": 57525937,
"delegate": { "type": 2,
"username": "trezor_t" "fee": "2500000000",
} "asset": {"delegate": {"username": "trezor_t"}},
} },
}) )
def test_lisk_sign_tx_cast_votes(self): def test_lisk_sign_tx_cast_votes(self):
self.setup_mnemonic_nopin_nopassphrase() self.setup_mnemonic_nopin_nopassphrase()
with self.client: with self.client:
self.client.set_expected_responses([ self.client.set_expected_responses(
proto.ButtonRequest(code=proto.ButtonRequestType.SignTx), [
proto.ButtonRequest(code=proto.ButtonRequestType.ConfirmOutput), proto.ButtonRequest(code=proto.ButtonRequestType.SignTx),
proto.LiskSignedTx( proto.ButtonRequest(code=proto.ButtonRequestType.ConfirmOutput),
signature=unhexlify('1d0599a8387edaa4a6d309b8a78accd1ceaff20ff9d87136b01cba0efbcb9781c13dc2b0bab5a1ea4f196d8dcc9dbdbd2d56dbffcc088fc77686b2e2c2fe560f') proto.LiskSignedTx(
) signature=unhexlify(
]) "1d0599a8387edaa4a6d309b8a78accd1ceaff20ff9d87136b01cba0efbcb9781c13dc2b0bab5a1ea4f196d8dcc9dbdbd2d56dbffcc088fc77686b2e2c2fe560f"
)
),
]
)
lisk.sign_tx(self.client, parse_path("m/44'/134'/0'/0'"), { lisk.sign_tx(
"amount": "0", self.client,
"timestamp": 57525937, parse_path("m/44'/134'/0'/0'"),
"type": 3, {
"fee": "100000000", "amount": "0",
"asset": { "timestamp": 57525937,
"votes": [ "type": 3,
"+b002f58531c074c7190714523eec08c48db8c7cfc0c943097db1a2e82ed87f84", "fee": "100000000",
"-ec111c8ad482445cfe83d811a7edd1f1d2765079c99d7d958cca1354740b7614" "asset": {
] "votes": [
} "+b002f58531c074c7190714523eec08c48db8c7cfc0c943097db1a2e82ed87f84",
}) "-ec111c8ad482445cfe83d811a7edd1f1d2765079c99d7d958cca1354740b7614",
]
},
},
)
def test_lisk_sign_tx_multisignature(self): def test_lisk_sign_tx_multisignature(self):
self.setup_mnemonic_nopin_nopassphrase() self.setup_mnemonic_nopin_nopassphrase()
with self.client: with self.client:
self.client.set_expected_responses([ self.client.set_expected_responses(
proto.ButtonRequest(code=proto.ButtonRequestType.SignTx), [
proto.ButtonRequest(code=proto.ButtonRequestType.ConfirmOutput), proto.ButtonRequest(code=proto.ButtonRequestType.SignTx),
proto.LiskSignedTx( proto.ButtonRequest(code=proto.ButtonRequestType.ConfirmOutput),
signature=unhexlify('88923866c2d500a6927715699ab41a0f58ea4b52e552d90e923bc24ac9da240f2328c93f9ce043a1da4937d4b61c7f57c02fc931f9824d06b24731e7be23c506') proto.LiskSignedTx(
) signature=unhexlify(
]) "88923866c2d500a6927715699ab41a0f58ea4b52e552d90e923bc24ac9da240f2328c93f9ce043a1da4937d4b61c7f57c02fc931f9824d06b24731e7be23c506"
)
),
]
)
lisk.sign_tx(self.client, parse_path("m/44'/134'/0'/0'"), { lisk.sign_tx(
"amount": "0", self.client,
"timestamp": 57525937, parse_path("m/44'/134'/0'/0'"),
"type": 4, {
"fee": "1500000000", "amount": "0",
"asset": { "timestamp": 57525937,
"multisignature": { "type": 4,
"min": 2, "fee": "1500000000",
"lifetime": 5, "asset": {
"keysgroup": [ "multisignature": {
"+5d036a858ce89f844491762eb89e2bfbd50a4a0a0da658e4b2628b25b117ae09", "min": 2,
"+922fbfdd596fa78269bbcadc67ec2a1cc15fc929a19c462169568d7a3df1a1aa" "lifetime": 5,
] "keysgroup": [
} "+5d036a858ce89f844491762eb89e2bfbd50a4a0a0da658e4b2628b25b117ae09",
} "+922fbfdd596fa78269bbcadc67ec2a1cc15fc929a19c462169568d7a3df1a1aa",
}) ],
}
},
},
)

View File

@ -15,43 +15,55 @@
# If not, see <https://www.gnu.org/licenses/lgpl-3.0.html>. # If not, see <https://www.gnu.org/licenses/lgpl-3.0.html>.
from binascii import unhexlify from binascii import unhexlify
import pytest import pytest
from trezorlib import lisk, messages as proto
from .common import TrezorTest from .common import TrezorTest
from trezorlib import messages as proto
from trezorlib import lisk
@pytest.mark.lisk @pytest.mark.lisk
@pytest.mark.skip_t1 @pytest.mark.skip_t1
class TestMsgLiskVerifymessage(TrezorTest): class TestMsgLiskVerifymessage(TrezorTest):
def test_verify(self): def test_verify(self):
self.setup_mnemonic_nopin_nopassphrase() self.setup_mnemonic_nopin_nopassphrase()
with self.client: with self.client:
self.client.set_expected_responses([ self.client.set_expected_responses(
proto.ButtonRequest(code=proto.ButtonRequestType.Other), [
proto.ButtonRequest(code=proto.ButtonRequestType.Other), proto.ButtonRequest(code=proto.ButtonRequestType.Other),
proto.Success(message='Message verified') proto.ButtonRequest(code=proto.ButtonRequestType.Other),
]) proto.Success(message="Message verified"),
]
)
lisk.verify_message( lisk.verify_message(
self.client, self.client,
unhexlify('eb56d7bbb5e8ea9269405f7a8527fe126023d1db2c973cfac6f760b60ae27294'), unhexlify(
unhexlify('7858ae7cd52ea6d4b17e800ca60144423db5560bfd618b663ffbf26ab66758563df45cbffae8463db22dc285dd94309083b8c807776085b97d05374d79867d05'), "eb56d7bbb5e8ea9269405f7a8527fe126023d1db2c973cfac6f760b60ae27294"
'This is an example of a signed message.' ),
unhexlify(
"7858ae7cd52ea6d4b17e800ca60144423db5560bfd618b663ffbf26ab66758563df45cbffae8463db22dc285dd94309083b8c807776085b97d05374d79867d05"
),
"This is an example of a signed message.",
) )
def test_verify_long(self): def test_verify_long(self):
self.setup_mnemonic_nopin_nopassphrase() self.setup_mnemonic_nopin_nopassphrase()
with self.client: with self.client:
self.client.set_expected_responses([ self.client.set_expected_responses(
proto.ButtonRequest(code=proto.ButtonRequestType.Other), [
proto.ButtonRequest(code=proto.ButtonRequestType.Other), proto.ButtonRequest(code=proto.ButtonRequestType.Other),
proto.Success(message='Message verified') proto.ButtonRequest(code=proto.ButtonRequestType.Other),
]) proto.Success(message="Message verified"),
]
)
lisk.verify_message( lisk.verify_message(
self.client, self.client,
unhexlify('8bca6b65a1a877767b746ea0b3c4310d404aa113df99c1b554e1802d70185ab5'), unhexlify(
unhexlify('458ca5896d0934866992268f7509b5e954d568b1251e20c19bd3149ee3c86ffb5a44d1c2a0abbb99a3ab4767272dbb0e419b4579e890a24919ebbbe6cc0f970f'), "8bca6b65a1a877767b746ea0b3c4310d404aa113df99c1b554e1802d70185ab5"
'VeryLongMessage!' * 64 ),
unhexlify(
"458ca5896d0934866992268f7509b5e954d568b1251e20c19bd3149ee3c86ffb5a44d1c2a0abbb99a3ab4767272dbb0e419b4579e890a24919ebbbe6cc0f970f"
),
"VeryLongMessage!" * 64,
) )

View File

@ -16,10 +16,9 @@
import pytest import pytest
from trezorlib import btc, debuglink, device
from .common import TrezorTest from .common import TrezorTest
from trezorlib import btc
from trezorlib import debuglink
from trezorlib import device
@pytest.mark.skip_t2 @pytest.mark.skip_t2
@ -36,12 +35,12 @@ class TestDeviceLoad(TrezorTest):
passphrase_protection = self.client.debug.read_passphrase_protection() passphrase_protection = self.client.debug.read_passphrase_protection()
assert passphrase_protection is False assert passphrase_protection is False
address = btc.get_address(self.client, 'Bitcoin', []) address = btc.get_address(self.client, "Bitcoin", [])
assert address == '1EfKbQupktEMXf4gujJ9kCFo83k1iMqwqK' assert address == "1EfKbQupktEMXf4gujJ9kCFo83k1iMqwqK"
def test_load_device_2(self): def test_load_device_2(self):
self.setup_mnemonic_pin_passphrase() self.setup_mnemonic_pin_passphrase()
self.client.set_passphrase('passphrase') self.client.set_passphrase("passphrase")
mnemonic = self.client.debug.read_mnemonic() mnemonic = self.client.debug.read_mnemonic()
assert mnemonic == self.mnemonic12 assert mnemonic == self.mnemonic12
@ -52,39 +51,79 @@ class TestDeviceLoad(TrezorTest):
passphrase_protection = self.client.debug.read_passphrase_protection() passphrase_protection = self.client.debug.read_passphrase_protection()
assert passphrase_protection is True assert passphrase_protection is True
address = btc.get_address(self.client, 'Bitcoin', []) address = btc.get_address(self.client, "Bitcoin", [])
assert address == '15fiTDFwZd2kauHYYseifGi9daH2wniDHH' assert address == "15fiTDFwZd2kauHYYseifGi9daH2wniDHH"
def test_load_device_utf(self): def test_load_device_utf(self):
words_nfkd = u'Pr\u030ci\u0301s\u030cerne\u030c z\u030clut\u030couc\u030cky\u0301 ku\u030an\u030c u\u0301pe\u030cl d\u030ca\u0301belske\u0301 o\u0301dy za\u0301ker\u030cny\u0301 uc\u030cen\u030c be\u030cz\u030ci\u0301 pode\u0301l zo\u0301ny u\u0301lu\u030a' words_nfkd = u"Pr\u030ci\u0301s\u030cerne\u030c z\u030clut\u030couc\u030cky\u0301 ku\u030an\u030c u\u0301pe\u030cl d\u030ca\u0301belske\u0301 o\u0301dy za\u0301ker\u030cny\u0301 uc\u030cen\u030c be\u030cz\u030ci\u0301 pode\u0301l zo\u0301ny u\u0301lu\u030a"
words_nfc = u'P\u0159\xed\u0161ern\u011b \u017elu\u0165ou\u010dk\xfd k\u016f\u0148 \xfap\u011bl \u010f\xe1belsk\xe9 \xf3dy z\xe1ke\u0159n\xfd u\u010de\u0148 b\u011b\u017e\xed pod\xe9l z\xf3ny \xfal\u016f' words_nfc = u"P\u0159\xed\u0161ern\u011b \u017elu\u0165ou\u010dk\xfd k\u016f\u0148 \xfap\u011bl \u010f\xe1belsk\xe9 \xf3dy z\xe1ke\u0159n\xfd u\u010de\u0148 b\u011b\u017e\xed pod\xe9l z\xf3ny \xfal\u016f"
words_nfkc = u'P\u0159\xed\u0161ern\u011b \u017elu\u0165ou\u010dk\xfd k\u016f\u0148 \xfap\u011bl \u010f\xe1belsk\xe9 \xf3dy z\xe1ke\u0159n\xfd u\u010de\u0148 b\u011b\u017e\xed pod\xe9l z\xf3ny \xfal\u016f' words_nfkc = u"P\u0159\xed\u0161ern\u011b \u017elu\u0165ou\u010dk\xfd k\u016f\u0148 \xfap\u011bl \u010f\xe1belsk\xe9 \xf3dy z\xe1ke\u0159n\xfd u\u010de\u0148 b\u011b\u017e\xed pod\xe9l z\xf3ny \xfal\u016f"
words_nfd = u'Pr\u030ci\u0301s\u030cerne\u030c z\u030clut\u030couc\u030cky\u0301 ku\u030an\u030c u\u0301pe\u030cl d\u030ca\u0301belske\u0301 o\u0301dy za\u0301ker\u030cny\u0301 uc\u030cen\u030c be\u030cz\u030ci\u0301 pode\u0301l zo\u0301ny u\u0301lu\u030a' words_nfd = u"Pr\u030ci\u0301s\u030cerne\u030c z\u030clut\u030couc\u030cky\u0301 ku\u030an\u030c u\u0301pe\u030cl d\u030ca\u0301belske\u0301 o\u0301dy za\u0301ker\u030cny\u0301 uc\u030cen\u030c be\u030cz\u030ci\u0301 pode\u0301l zo\u0301ny u\u0301lu\u030a"
passphrase_nfkd = u'Neuve\u030cr\u030citelne\u030c bezpec\u030cne\u0301 hesli\u0301c\u030cko' passphrase_nfkd = (
passphrase_nfc = u'Neuv\u011b\u0159iteln\u011b bezpe\u010dn\xe9 hesl\xed\u010dko' u"Neuve\u030cr\u030citelne\u030c bezpec\u030cne\u0301 hesli\u0301c\u030cko"
passphrase_nfkc = u'Neuv\u011b\u0159iteln\u011b bezpe\u010dn\xe9 hesl\xed\u010dko' )
passphrase_nfd = u'Neuve\u030cr\u030citelne\u030c bezpec\u030cne\u0301 hesli\u0301c\u030cko' passphrase_nfc = (
u"Neuv\u011b\u0159iteln\u011b bezpe\u010dn\xe9 hesl\xed\u010dko"
)
passphrase_nfkc = (
u"Neuv\u011b\u0159iteln\u011b bezpe\u010dn\xe9 hesl\xed\u010dko"
)
passphrase_nfd = (
u"Neuve\u030cr\u030citelne\u030c bezpec\u030cne\u0301 hesli\u0301c\u030cko"
)
device.wipe(self.client) device.wipe(self.client)
debuglink.load_device_by_mnemonic(self.client, mnemonic=words_nfkd, pin='', passphrase_protection=True, label='test', language='english', skip_checksum=True) debuglink.load_device_by_mnemonic(
self.client,
mnemonic=words_nfkd,
pin="",
passphrase_protection=True,
label="test",
language="english",
skip_checksum=True,
)
self.client.set_passphrase(passphrase_nfkd) self.client.set_passphrase(passphrase_nfkd)
address_nfkd = btc.get_address(self.client, 'Bitcoin', []) address_nfkd = btc.get_address(self.client, "Bitcoin", [])
device.wipe(self.client) device.wipe(self.client)
debuglink.load_device_by_mnemonic(self.client, mnemonic=words_nfc, pin='', passphrase_protection=True, label='test', language='english', skip_checksum=True) debuglink.load_device_by_mnemonic(
self.client,
mnemonic=words_nfc,
pin="",
passphrase_protection=True,
label="test",
language="english",
skip_checksum=True,
)
self.client.set_passphrase(passphrase_nfc) self.client.set_passphrase(passphrase_nfc)
address_nfc = btc.get_address(self.client, 'Bitcoin', []) address_nfc = btc.get_address(self.client, "Bitcoin", [])
device.wipe(self.client) device.wipe(self.client)
debuglink.load_device_by_mnemonic(self.client, mnemonic=words_nfkc, pin='', passphrase_protection=True, label='test', language='english', skip_checksum=True) debuglink.load_device_by_mnemonic(
self.client,
mnemonic=words_nfkc,
pin="",
passphrase_protection=True,
label="test",
language="english",
skip_checksum=True,
)
self.client.set_passphrase(passphrase_nfkc) self.client.set_passphrase(passphrase_nfkc)
address_nfkc = btc.get_address(self.client, 'Bitcoin', []) address_nfkc = btc.get_address(self.client, "Bitcoin", [])
device.wipe(self.client) device.wipe(self.client)
debuglink.load_device_by_mnemonic(self.client, mnemonic=words_nfd, pin='', passphrase_protection=True, label='test', language='english', skip_checksum=True) debuglink.load_device_by_mnemonic(
self.client,
mnemonic=words_nfd,
pin="",
passphrase_protection=True,
label="test",
language="english",
skip_checksum=True,
)
self.client.set_passphrase(passphrase_nfd) self.client.set_passphrase(passphrase_nfd)
address_nfd = btc.get_address(self.client, 'Bitcoin', []) address_nfd = btc.get_address(self.client, "Bitcoin", [])
assert address_nfkd == address_nfc assert address_nfkd == address_nfc
assert address_nfkd == address_nfkc assert address_nfkd == address_nfkc

View File

@ -16,30 +16,43 @@
import pytest import pytest
from trezorlib import btc, debuglink
from .common import TrezorTest from .common import TrezorTest
from trezorlib import btc
from trezorlib import debuglink
@pytest.mark.skip_t2 @pytest.mark.skip_t2
class TestDeviceLoadXprv(TrezorTest): class TestDeviceLoadXprv(TrezorTest):
def test_load_device_xprv_1(self): def test_load_device_xprv_1(self):
debuglink.load_device_by_xprv(self.client, xprv='xprv9s21ZrQH143K2JF8RafpqtKiTbsbaxEeUaMnNHsm5o6wCW3z8ySyH4UxFVSfZ8n7ESu7fgir8imbZKLYVBxFPND1pniTZ81vKfd45EHKX73', pin='', passphrase_protection=False, label='test', language='english') debuglink.load_device_by_xprv(
self.client,
xprv="xprv9s21ZrQH143K2JF8RafpqtKiTbsbaxEeUaMnNHsm5o6wCW3z8ySyH4UxFVSfZ8n7ESu7fgir8imbZKLYVBxFPND1pniTZ81vKfd45EHKX73",
pin="",
passphrase_protection=False,
label="test",
language="english",
)
passphrase_protection = self.client.debug.read_passphrase_protection() passphrase_protection = self.client.debug.read_passphrase_protection()
assert passphrase_protection is False assert passphrase_protection is False
address = btc.get_address(self.client, 'Bitcoin', []) address = btc.get_address(self.client, "Bitcoin", [])
assert address == '128RdrAkJDmqasgvfRf6MC5VcX4HKqH4mR' assert address == "128RdrAkJDmqasgvfRf6MC5VcX4HKqH4mR"
def test_load_device_xprv_2(self): def test_load_device_xprv_2(self):
debuglink.load_device_by_xprv(self.client, xprv='xprv9s21ZrQH143K2JF8RafpqtKiTbsbaxEeUaMnNHsm5o6wCW3z8ySyH4UxFVSfZ8n7ESu7fgir8imbZKLYVBxFPND1pniTZ81vKfd45EHKX73', pin='', passphrase_protection=True, label='test', language='english') debuglink.load_device_by_xprv(
self.client,
xprv="xprv9s21ZrQH143K2JF8RafpqtKiTbsbaxEeUaMnNHsm5o6wCW3z8ySyH4UxFVSfZ8n7ESu7fgir8imbZKLYVBxFPND1pniTZ81vKfd45EHKX73",
pin="",
passphrase_protection=True,
label="test",
language="english",
)
self.client.set_passphrase('passphrase') self.client.set_passphrase("passphrase")
passphrase_protection = self.client.debug.read_passphrase_protection() passphrase_protection = self.client.debug.read_passphrase_protection()
assert passphrase_protection is True assert passphrase_protection is True
address = btc.get_address(self.client, 'Bitcoin', []) address = btc.get_address(self.client, "Bitcoin", [])
assert address == '1CHUbFa4wTTPYgkYaw2LHSd5D4qJjMU8ri' assert address == "1CHUbFa4wTTPYgkYaw2LHSd5D4qJjMU8ri"

View File

@ -16,15 +16,21 @@
import pytest import pytest
from .common import TrezorTest
from trezorlib.tools import parse_path
from trezorlib import nem from trezorlib import nem
from trezorlib.tools import parse_path
from .common import TrezorTest
@pytest.mark.nem @pytest.mark.nem
class TestMsgNEMGetaddress(TrezorTest): class TestMsgNEMGetaddress(TrezorTest):
def test_nem_getaddress(self): def test_nem_getaddress(self):
self.setup_mnemonic_nopin_nopassphrase() self.setup_mnemonic_nopin_nopassphrase()
assert nem.get_address(self.client, parse_path("m/44'/1'/0'/0'/0'"), 0x68) == "NB3JCHVARQNGDS3UVGAJPTFE22UQFGMCQGHUBWQN" assert (
assert nem.get_address(self.client, parse_path("m/44'/1'/0'/0'/0'"), 0x98) == "TB3JCHVARQNGDS3UVGAJPTFE22UQFGMCQHSBNBMF" nem.get_address(self.client, parse_path("m/44'/1'/0'/0'/0'"), 0x68)
== "NB3JCHVARQNGDS3UVGAJPTFE22UQFGMCQGHUBWQN"
)
assert (
nem.get_address(self.client, parse_path("m/44'/1'/0'/0'/0'"), 0x98)
== "TB3JCHVARQNGDS3UVGAJPTFE22UQFGMCQHSBNBMF"
)

View File

@ -14,162 +14,160 @@
# You should have received a copy of the License along with this library. # You should have received a copy of the License along with this library.
# If not, see <https://www.gnu.org/licenses/lgpl-3.0.html>. # If not, see <https://www.gnu.org/licenses/lgpl-3.0.html>.
import pytest
from binascii import hexlify from binascii import hexlify
from .common import TrezorTest import pytest
from trezorlib import nem from trezorlib import nem
from trezorlib.tools import parse_path from trezorlib.tools import parse_path
from .common import TrezorTest
# assertion data from T1 # assertion data from T1
@pytest.mark.nem @pytest.mark.nem
@pytest.mark.skip_t2 @pytest.mark.skip_t2
class TestMsgNEMSignTxMosaics(TrezorTest): 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 = nem.sign_tx(self.client, parse_path("m/44'/1'/0'/0'/0'"), { tx = nem.sign_tx(
"timeStamp": 74649215, self.client,
"fee": 2000000, parse_path("m/44'/1'/0'/0'/0'"),
"type": nem.TYPE_MOSAIC_SUPPLY_CHANGE, {
"deadline": 74735615, "timeStamp": 74649215,
"message": { "fee": 2000000,
"type": nem.TYPE_MOSAIC_SUPPLY_CHANGE,
"deadline": 74735615,
"message": {},
"mosaicId": {"namespaceId": "hellom", "name": "Hello mosaic"},
"supplyType": 1,
"delta": 1,
"version": (0x98 << 24),
"creationFeeSink": "TALICE2GMA34CXHD7XLJQ536NM5UNKQHTORNNT2J",
"creationFee": 1500,
}, },
"mosaicId": { )
"namespaceId": "hellom",
"name": "Hello mosaic"
},
"supplyType": 1,
"delta": 1,
"version": (0x98 << 24),
"creationFeeSink": "TALICE2GMA34CXHD7XLJQ536NM5UNKQHTORNNT2J",
"creationFee": 1500,
})
assert hexlify(tx.data) == b'02400000010000987f0e730420000000edfd32f6e760648c032f9acb4b30d514265f6a5b5f8a7154f2618922b406208480841e0000000000ff5f74041a0000000600000068656c6c6f6d0c00000048656c6c6f206d6f73616963010000000100000000000000' assert (
assert hexlify(tx.signature) == b'928b03c4a69fff35ecf0912066ea705895b3028fad141197d7ea2b56f1eef2a2516455e6f35d318f6fa39e2bb40492ac4ae603260790f7ebc7ea69feb4ca4c0a' hexlify(tx.data)
== b"02400000010000987f0e730420000000edfd32f6e760648c032f9acb4b30d514265f6a5b5f8a7154f2618922b406208480841e0000000000ff5f74041a0000000600000068656c6c6f6d0c00000048656c6c6f206d6f73616963010000000100000000000000"
)
assert (
hexlify(tx.signature)
== b"928b03c4a69fff35ecf0912066ea705895b3028fad141197d7ea2b56f1eef2a2516455e6f35d318f6fa39e2bb40492ac4ae603260790f7ebc7ea69feb4ca4c0a"
)
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 = nem.sign_tx(self.client, parse_path("m/44'/1'/0'/0'/0'"), { tx = nem.sign_tx(
"timeStamp": 74649215, self.client,
"fee": 2000000, parse_path("m/44'/1'/0'/0'/0'"),
"type": nem.TYPE_MOSAIC_CREATION, {
"deadline": 74735615, "timeStamp": 74649215,
"message": { "fee": 2000000,
}, "type": nem.TYPE_MOSAIC_CREATION,
"mosaicDefinition": { "deadline": 74735615,
"id": { "message": {},
"namespaceId": "hellom", "mosaicDefinition": {
"name": "Hello mosaic" "id": {"namespaceId": "hellom", "name": "Hello mosaic"},
"levy": {},
"properties": {},
"description": "lorem",
}, },
"levy": {}, "version": (0x98 << 24),
"properties": {}, "creationFeeSink": "TALICE2GMA34CXHD7XLJQ536NM5UNKQHTORNNT2J",
"description": "lorem" "creationFee": 1500,
}, },
"version": (0x98 << 24), )
"creationFeeSink": "TALICE2GMA34CXHD7XLJQ536NM5UNKQHTORNNT2J",
"creationFee": 1500,
})
assert hexlify(tx.data) == b'01400000010000987f0e730420000000edfd32f6e760648c032f9acb4b30d514265f6a5b5f8a7154f2618922b406208480841e0000000000ff5f7404c100000020000000edfd32f6e760648c032f9acb4b30d514265f6a5b5f8a7154f2618922b40620841a0000000600000068656c6c6f6d0c00000048656c6c6f206d6f73616963050000006c6f72656d04000000150000000c00000064697669736962696c6974790100000030160000000d000000696e697469616c537570706c7901000000301a0000000d000000737570706c794d757461626c650500000066616c7365190000000c0000007472616e7366657261626c650500000066616c7365000000002800000054414c49434532474d4133344358484437584c4a513533364e4d35554e4b5148544f524e4e54324adc05000000000000' assert (
assert hexlify(tx.signature) == b'537adf4fd9bd5b46e204b2db0a435257a951ed26008305e0aa9e1201dafa4c306d7601a8dbacabf36b5137724386124958d53202015ab31fb3d0849dfed2df0e' hexlify(tx.data)
== b"01400000010000987f0e730420000000edfd32f6e760648c032f9acb4b30d514265f6a5b5f8a7154f2618922b406208480841e0000000000ff5f7404c100000020000000edfd32f6e760648c032f9acb4b30d514265f6a5b5f8a7154f2618922b40620841a0000000600000068656c6c6f6d0c00000048656c6c6f206d6f73616963050000006c6f72656d04000000150000000c00000064697669736962696c6974790100000030160000000d000000696e697469616c537570706c7901000000301a0000000d000000737570706c794d757461626c650500000066616c7365190000000c0000007472616e7366657261626c650500000066616c7365000000002800000054414c49434532474d4133344358484437584c4a513533364e4d35554e4b5148544f524e4e54324adc05000000000000"
)
assert (
hexlify(tx.signature)
== b"537adf4fd9bd5b46e204b2db0a435257a951ed26008305e0aa9e1201dafa4c306d7601a8dbacabf36b5137724386124958d53202015ab31fb3d0849dfed2df0e"
)
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 = nem.sign_tx(self.client, parse_path("m/44'/1'/0'/0'/0'"), { tx = nem.sign_tx(
"timeStamp": 74649215, self.client,
"fee": 2000000, parse_path("m/44'/1'/0'/0'/0'"),
"type": nem.TYPE_MOSAIC_CREATION, {
"deadline": 74735615, "timeStamp": 74649215,
"message": { "fee": 2000000,
}, "type": nem.TYPE_MOSAIC_CREATION,
"mosaicDefinition": { "deadline": 74735615,
"id": { "message": {},
"namespaceId": "hellom", "mosaicDefinition": {
"name": "Hello mosaic" "id": {"namespaceId": "hellom", "name": "Hello mosaic"},
"levy": {},
"properties": [
{"name": "divisibility", "value": "4"},
{"name": "initialSupply", "value": "200"},
{"name": "supplyMutable", "value": "false"},
{"name": "transferable", "value": "true"},
],
"description": "lorem",
}, },
"levy": {}, "version": (0x98 << 24),
"properties": [ "creationFeeSink": "TALICE2GMA34CXHD7XLJQ536NM5UNKQHTORNNT2J",
{ "creationFee": 1500,
"name": "divisibility",
"value": "4"
},
{
"name": "initialSupply",
"value": "200"
},
{
"name": "supplyMutable",
"value": "false"
},
{
"name": "transferable",
"value": "true"
}
],
"description": "lorem"
}, },
"version": (0x98 << 24), )
"creationFeeSink": "TALICE2GMA34CXHD7XLJQ536NM5UNKQHTORNNT2J",
"creationFee": 1500,
})
assert hexlify(tx.data) == b'01400000010000987f0e730420000000edfd32f6e760648c032f9acb4b30d514265f6a5b5f8a7154f2618922b406208480841e0000000000ff5f7404c200000020000000edfd32f6e760648c032f9acb4b30d514265f6a5b5f8a7154f2618922b40620841a0000000600000068656c6c6f6d0c00000048656c6c6f206d6f73616963050000006c6f72656d04000000150000000c00000064697669736962696c6974790100000034180000000d000000696e697469616c537570706c79030000003230301a0000000d000000737570706c794d757461626c650500000066616c7365180000000c0000007472616e7366657261626c650400000074727565000000002800000054414c49434532474d4133344358484437584c4a513533364e4d35554e4b5148544f524e4e54324adc05000000000000' assert (
assert hexlify(tx.signature) == b'f17c859710060f2ea9a0ab740ef427431cf36bdc7d263570ca282bd66032e9f5737a921be9839429732e663be2bb74ccc16f34f5157ff2ef00a65796b54e800e' hexlify(tx.data)
== b"01400000010000987f0e730420000000edfd32f6e760648c032f9acb4b30d514265f6a5b5f8a7154f2618922b406208480841e0000000000ff5f7404c200000020000000edfd32f6e760648c032f9acb4b30d514265f6a5b5f8a7154f2618922b40620841a0000000600000068656c6c6f6d0c00000048656c6c6f206d6f73616963050000006c6f72656d04000000150000000c00000064697669736962696c6974790100000034180000000d000000696e697469616c537570706c79030000003230301a0000000d000000737570706c794d757461626c650500000066616c7365180000000c0000007472616e7366657261626c650400000074727565000000002800000054414c49434532474d4133344358484437584c4a513533364e4d35554e4b5148544f524e4e54324adc05000000000000"
)
assert (
hexlify(tx.signature)
== b"f17c859710060f2ea9a0ab740ef427431cf36bdc7d263570ca282bd66032e9f5737a921be9839429732e663be2bb74ccc16f34f5157ff2ef00a65796b54e800e"
)
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 = nem.sign_tx(self.client, parse_path("m/44'/1'/0'/0'/0'"), { tx = nem.sign_tx(
"timeStamp": 74649215, self.client,
"fee": 2000000, parse_path("m/44'/1'/0'/0'/0'"),
"type": nem.TYPE_MOSAIC_CREATION, {
"deadline": 74735615, "timeStamp": 74649215,
"message": { "fee": 2000000,
}, "type": nem.TYPE_MOSAIC_CREATION,
"mosaicDefinition": { "deadline": 74735615,
"id": { "message": {},
"namespaceId": "hellom", "mosaicDefinition": {
"name": "Hello mosaic" "id": {"namespaceId": "hellom", "name": "Hello mosaic"},
"properties": [
{"name": "divisibility", "value": "4"},
{"name": "initialSupply", "value": "200"},
{"name": "supplyMutable", "value": "false"},
{"name": "transferable", "value": "true"},
],
"levy": {
"type": 1,
"fee": 2,
"recipient": "TALICE2GMA34CXHD7XLJQ536NM5UNKQHTORNNT2J",
"mosaicId": {"namespaceId": "hellom", "name": "Hello mosaic"},
},
"description": "lorem",
}, },
"properties": [ "version": (0x98 << 24),
{ "creationFeeSink": "TALICE2GMA34CXHD7XLJQ536NM5UNKQHTORNNT2J",
"name": "divisibility", "creationFee": 1500,
"value": "4"
},
{
"name": "initialSupply",
"value": "200"
},
{
"name": "supplyMutable",
"value": "false"
},
{
"name": "transferable",
"value": "true"
}
],
"levy": {
"type": 1,
"fee": 2,
"recipient": "TALICE2GMA34CXHD7XLJQ536NM5UNKQHTORNNT2J",
"mosaicId": {
"namespaceId": "hellom",
"name": "Hello mosaic"
},
},
"description": "lorem"
}, },
"version": (0x98 << 24), )
"creationFeeSink": "TALICE2GMA34CXHD7XLJQ536NM5UNKQHTORNNT2J",
"creationFee": 1500,
})
assert hexlify(tx.data) == b'01400000010000987f0e730420000000edfd32f6e760648c032f9acb4b30d514265f6a5b5f8a7154f2618922b406208480841e0000000000ff5f74041801000020000000edfd32f6e760648c032f9acb4b30d514265f6a5b5f8a7154f2618922b40620841a0000000600000068656c6c6f6d0c00000048656c6c6f206d6f73616963050000006c6f72656d04000000150000000c00000064697669736962696c6974790100000034180000000d000000696e697469616c537570706c79030000003230301a0000000d000000737570706c794d757461626c650500000066616c7365180000000c0000007472616e7366657261626c65040000007472756556000000010000002800000054414c49434532474d4133344358484437584c4a513533364e4d35554e4b5148544f524e4e54324a1a0000000600000068656c6c6f6d0c00000048656c6c6f206d6f7361696302000000000000002800000054414c49434532474d4133344358484437584c4a513533364e4d35554e4b5148544f524e4e54324adc05000000000000' assert (
assert hexlify(tx.signature) == b'b87aac1ddf146d35e6a7f3451f57e2fe504ac559031e010a51261257c37bd50fcfa7b2939dd7a3203b54c4807d458475182f5d3dc135ec0d1d4a9cd42159fd0a' hexlify(tx.data)
== b"01400000010000987f0e730420000000edfd32f6e760648c032f9acb4b30d514265f6a5b5f8a7154f2618922b406208480841e0000000000ff5f74041801000020000000edfd32f6e760648c032f9acb4b30d514265f6a5b5f8a7154f2618922b40620841a0000000600000068656c6c6f6d0c00000048656c6c6f206d6f73616963050000006c6f72656d04000000150000000c00000064697669736962696c6974790100000034180000000d000000696e697469616c537570706c79030000003230301a0000000d000000737570706c794d757461626c650500000066616c7365180000000c0000007472616e7366657261626c65040000007472756556000000010000002800000054414c49434532474d4133344358484437584c4a513533364e4d35554e4b5148544f524e4e54324a1a0000000600000068656c6c6f6d0c00000048656c6c6f206d6f7361696302000000000000002800000054414c49434532474d4133344358484437584c4a513533364e4d35554e4b5148544f524e4e54324adc05000000000000"
)
assert (
hexlify(tx.signature)
== b"b87aac1ddf146d35e6a7f3451f57e2fe504ac559031e010a51261257c37bd50fcfa7b2939dd7a3203b54c4807d458475182f5d3dc135ec0d1d4a9cd42159fd0a"
)

View File

@ -14,45 +14,51 @@
# You should have received a copy of the License along with this library. # You should have received a copy of the License along with this library.
# If not, see <https://www.gnu.org/licenses/lgpl-3.0.html>. # If not, see <https://www.gnu.org/licenses/lgpl-3.0.html>.
from binascii import hexlify
import pytest
import time import time
from binascii import hexlify
import pytest
from trezorlib import messages as proto, nem
from trezorlib.tools import parse_path
from .common import TrezorTest from .common import TrezorTest
from trezorlib import messages as proto
from trezorlib import nem
from trezorlib.tools import parse_path
# assertion data from T1 # assertion data from T1
@pytest.mark.nem @pytest.mark.nem
@pytest.mark.skip_t1 @pytest.mark.skip_t1
class TestMsgNEMSignTxMosaics(TrezorTest): 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()
with self.client: with self.client:
tx = nem.sign_tx(self.client, parse_path("m/44'/1'/0'/0'/0'"), { tx = nem.sign_tx(
"timeStamp": 74649215, self.client,
"fee": 2000000, parse_path("m/44'/1'/0'/0'/0'"),
"type": nem.TYPE_MOSAIC_SUPPLY_CHANGE, {
"deadline": 74735615, "timeStamp": 74649215,
"message": { "fee": 2000000,
"type": nem.TYPE_MOSAIC_SUPPLY_CHANGE,
"deadline": 74735615,
"message": {},
"mosaicId": {"namespaceId": "hellom", "name": "Hello mosaic"},
"supplyType": 1,
"delta": 1,
"version": (0x98 << 24),
"creationFeeSink": "TALICE2GMA34CXHD7XLJQ536NM5UNKQHTORNNT2J",
"creationFee": 1500,
}, },
"mosaicId": { )
"namespaceId": "hellom",
"name": "Hello mosaic"
},
"supplyType": 1,
"delta": 1,
"version": (0x98 << 24),
"creationFeeSink": "TALICE2GMA34CXHD7XLJQ536NM5UNKQHTORNNT2J",
"creationFee": 1500,
})
assert hexlify(tx.data) == b'02400000010000987f0e730420000000edfd32f6e760648c032f9acb4b30d514265f6a5b5f8a7154f2618922b406208480841e0000000000ff5f74041a0000000600000068656c6c6f6d0c00000048656c6c6f206d6f73616963010000000100000000000000' assert (
assert hexlify(tx.signature) == b'928b03c4a69fff35ecf0912066ea705895b3028fad141197d7ea2b56f1eef2a2516455e6f35d318f6fa39e2bb40492ac4ae603260790f7ebc7ea69feb4ca4c0a' hexlify(tx.data)
== b"02400000010000987f0e730420000000edfd32f6e760648c032f9acb4b30d514265f6a5b5f8a7154f2618922b406208480841e0000000000ff5f74041a0000000600000068656c6c6f6d0c00000048656c6c6f206d6f73616963010000000100000000000000"
)
assert (
hexlify(tx.signature)
== b"928b03c4a69fff35ecf0912066ea705895b3028fad141197d7ea2b56f1eef2a2516455e6f35d318f6fa39e2bb40492ac4ae603260790f7ebc7ea69feb4ca4c0a"
)
def test_nem_signtx_mosaic_creation(self): def test_nem_signtx_mosaic_creation(self):
self.setup_mnemonic_nopin_nopassphrase() self.setup_mnemonic_nopin_nopassphrase()
@ -62,16 +68,12 @@ class TestMsgNEMSignTxMosaics(TrezorTest):
"fee": 2000000, "fee": 2000000,
"type": nem.TYPE_MOSAIC_CREATION, "type": nem.TYPE_MOSAIC_CREATION,
"deadline": 74735615, "deadline": 74735615,
"message": { "message": {},
},
"mosaicDefinition": { "mosaicDefinition": {
"id": { "id": {"namespaceId": "hellom", "name": "Hello mosaic"},
"namespaceId": "hellom",
"name": "Hello mosaic"
},
"levy": {}, "levy": {},
"properties": {}, "properties": {},
"description": "lorem" "description": "lorem",
}, },
"version": (0x98 << 24), "version": (0x98 << 24),
"creationFeeSink": "TALICE2GMA34CXHD7XLJQ536NM5UNKQHTORNNT2J", "creationFeeSink": "TALICE2GMA34CXHD7XLJQ536NM5UNKQHTORNNT2J",
@ -80,8 +82,14 @@ class TestMsgNEMSignTxMosaics(TrezorTest):
# not using client.nem_sign_tx() because of swiping # not using client.nem_sign_tx() because of swiping
tx = self._nem_sign(2, test_suite) tx = self._nem_sign(2, test_suite)
assert hexlify(tx.data) == b'01400000010000987f0e730420000000edfd32f6e760648c032f9acb4b30d514265f6a5b5f8a7154f2618922b406208480841e0000000000ff5f7404c100000020000000edfd32f6e760648c032f9acb4b30d514265f6a5b5f8a7154f2618922b40620841a0000000600000068656c6c6f6d0c00000048656c6c6f206d6f73616963050000006c6f72656d04000000150000000c00000064697669736962696c6974790100000030160000000d000000696e697469616c537570706c7901000000301a0000000d000000737570706c794d757461626c650500000066616c7365190000000c0000007472616e7366657261626c650500000066616c7365000000002800000054414c49434532474d4133344358484437584c4a513533364e4d35554e4b5148544f524e4e54324adc05000000000000' assert (
assert hexlify(tx.signature) == b'537adf4fd9bd5b46e204b2db0a435257a951ed26008305e0aa9e1201dafa4c306d7601a8dbacabf36b5137724386124958d53202015ab31fb3d0849dfed2df0e' hexlify(tx.data)
== b"01400000010000987f0e730420000000edfd32f6e760648c032f9acb4b30d514265f6a5b5f8a7154f2618922b406208480841e0000000000ff5f7404c100000020000000edfd32f6e760648c032f9acb4b30d514265f6a5b5f8a7154f2618922b40620841a0000000600000068656c6c6f6d0c00000048656c6c6f206d6f73616963050000006c6f72656d04000000150000000c00000064697669736962696c6974790100000030160000000d000000696e697469616c537570706c7901000000301a0000000d000000737570706c794d757461626c650500000066616c7365190000000c0000007472616e7366657261626c650500000066616c7365000000002800000054414c49434532474d4133344358484437584c4a513533364e4d35554e4b5148544f524e4e54324adc05000000000000"
)
assert (
hexlify(tx.signature)
== b"537adf4fd9bd5b46e204b2db0a435257a951ed26008305e0aa9e1201dafa4c306d7601a8dbacabf36b5137724386124958d53202015ab31fb3d0849dfed2df0e"
)
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()
@ -91,33 +99,17 @@ class TestMsgNEMSignTxMosaics(TrezorTest):
"fee": 2000000, "fee": 2000000,
"type": nem.TYPE_MOSAIC_CREATION, "type": nem.TYPE_MOSAIC_CREATION,
"deadline": 74735615, "deadline": 74735615,
"message": { "message": {},
},
"mosaicDefinition": { "mosaicDefinition": {
"id": { "id": {"namespaceId": "hellom", "name": "Hello mosaic"},
"namespaceId": "hellom",
"name": "Hello mosaic"
},
"levy": {}, "levy": {},
"properties": [ "properties": [
{ {"name": "divisibility", "value": "4"},
"name": "divisibility", {"name": "initialSupply", "value": "200"},
"value": "4" {"name": "supplyMutable", "value": "false"},
}, {"name": "transferable", "value": "true"},
{
"name": "initialSupply",
"value": "200"
},
{
"name": "supplyMutable",
"value": "false"
},
{
"name": "transferable",
"value": "true"
}
], ],
"description": "lorem" "description": "lorem",
}, },
"version": (0x98 << 24), "version": (0x98 << 24),
"creationFeeSink": "TALICE2GMA34CXHD7XLJQ536NM5UNKQHTORNNT2J", "creationFeeSink": "TALICE2GMA34CXHD7XLJQ536NM5UNKQHTORNNT2J",
@ -126,8 +118,14 @@ class TestMsgNEMSignTxMosaics(TrezorTest):
# not using client.nem_sign_tx() because of swiping # not using client.nem_sign_tx() because of swiping
tx = self._nem_sign(2, test_suite) tx = self._nem_sign(2, test_suite)
assert hexlify(tx.data) == b'01400000010000987f0e730420000000edfd32f6e760648c032f9acb4b30d514265f6a5b5f8a7154f2618922b406208480841e0000000000ff5f7404c200000020000000edfd32f6e760648c032f9acb4b30d514265f6a5b5f8a7154f2618922b40620841a0000000600000068656c6c6f6d0c00000048656c6c6f206d6f73616963050000006c6f72656d04000000150000000c00000064697669736962696c6974790100000034180000000d000000696e697469616c537570706c79030000003230301a0000000d000000737570706c794d757461626c650500000066616c7365180000000c0000007472616e7366657261626c650400000074727565000000002800000054414c49434532474d4133344358484437584c4a513533364e4d35554e4b5148544f524e4e54324adc05000000000000' assert (
assert hexlify(tx.signature) == b'f17c859710060f2ea9a0ab740ef427431cf36bdc7d263570ca282bd66032e9f5737a921be9839429732e663be2bb74ccc16f34f5157ff2ef00a65796b54e800e' hexlify(tx.data)
== b"01400000010000987f0e730420000000edfd32f6e760648c032f9acb4b30d514265f6a5b5f8a7154f2618922b406208480841e0000000000ff5f7404c200000020000000edfd32f6e760648c032f9acb4b30d514265f6a5b5f8a7154f2618922b40620841a0000000600000068656c6c6f6d0c00000048656c6c6f206d6f73616963050000006c6f72656d04000000150000000c00000064697669736962696c6974790100000034180000000d000000696e697469616c537570706c79030000003230301a0000000d000000737570706c794d757461626c650500000066616c7365180000000c0000007472616e7366657261626c650400000074727565000000002800000054414c49434532474d4133344358484437584c4a513533364e4d35554e4b5148544f524e4e54324adc05000000000000"
)
assert (
hexlify(tx.signature)
== b"f17c859710060f2ea9a0ab740ef427431cf36bdc7d263570ca282bd66032e9f5737a921be9839429732e663be2bb74ccc16f34f5157ff2ef00a65796b54e800e"
)
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()
@ -137,41 +135,22 @@ class TestMsgNEMSignTxMosaics(TrezorTest):
"fee": 2000000, "fee": 2000000,
"type": nem.TYPE_MOSAIC_CREATION, "type": nem.TYPE_MOSAIC_CREATION,
"deadline": 74735615, "deadline": 74735615,
"message": { "message": {},
},
"mosaicDefinition": { "mosaicDefinition": {
"id": { "id": {"namespaceId": "hellom", "name": "Hello mosaic"},
"namespaceId": "hellom",
"name": "Hello mosaic"
},
"properties": [ "properties": [
{ {"name": "divisibility", "value": "4"},
"name": "divisibility", {"name": "initialSupply", "value": "200"},
"value": "4" {"name": "supplyMutable", "value": "false"},
}, {"name": "transferable", "value": "true"},
{
"name": "initialSupply",
"value": "200"
},
{
"name": "supplyMutable",
"value": "false"
},
{
"name": "transferable",
"value": "true"
}
], ],
"levy": { "levy": {
"type": 1, "type": 1,
"fee": 2, "fee": 2,
"recipient": "TALICE2GMA34CXHD7XLJQ536NM5UNKQHTORNNT2J", "recipient": "TALICE2GMA34CXHD7XLJQ536NM5UNKQHTORNNT2J",
"mosaicId": { "mosaicId": {"namespaceId": "hellom", "name": "Hello mosaic"},
"namespaceId": "hellom",
"name": "Hello mosaic"
},
}, },
"description": "lorem" "description": "lorem",
}, },
"version": (0x98 << 24), "version": (0x98 << 24),
"creationFeeSink": "TALICE2GMA34CXHD7XLJQ536NM5UNKQHTORNNT2J", "creationFeeSink": "TALICE2GMA34CXHD7XLJQ536NM5UNKQHTORNNT2J",
@ -179,8 +158,14 @@ class TestMsgNEMSignTxMosaics(TrezorTest):
} }
tx = self._nem_sign(6, test_suite) tx = self._nem_sign(6, test_suite)
assert hexlify(tx.data) == b'01400000010000987f0e730420000000edfd32f6e760648c032f9acb4b30d514265f6a5b5f8a7154f2618922b406208480841e0000000000ff5f74041801000020000000edfd32f6e760648c032f9acb4b30d514265f6a5b5f8a7154f2618922b40620841a0000000600000068656c6c6f6d0c00000048656c6c6f206d6f73616963050000006c6f72656d04000000150000000c00000064697669736962696c6974790100000034180000000d000000696e697469616c537570706c79030000003230301a0000000d000000737570706c794d757461626c650500000066616c7365180000000c0000007472616e7366657261626c65040000007472756556000000010000002800000054414c49434532474d4133344358484437584c4a513533364e4d35554e4b5148544f524e4e54324a1a0000000600000068656c6c6f6d0c00000048656c6c6f206d6f7361696302000000000000002800000054414c49434532474d4133344358484437584c4a513533364e4d35554e4b5148544f524e4e54324adc05000000000000' assert (
assert hexlify(tx.signature) == b'b87aac1ddf146d35e6a7f3451f57e2fe504ac559031e010a51261257c37bd50fcfa7b2939dd7a3203b54c4807d458475182f5d3dc135ec0d1d4a9cd42159fd0a' hexlify(tx.data)
== b"01400000010000987f0e730420000000edfd32f6e760648c032f9acb4b30d514265f6a5b5f8a7154f2618922b406208480841e0000000000ff5f74041801000020000000edfd32f6e760648c032f9acb4b30d514265f6a5b5f8a7154f2618922b40620841a0000000600000068656c6c6f6d0c00000048656c6c6f206d6f73616963050000006c6f72656d04000000150000000c00000064697669736962696c6974790100000034180000000d000000696e697469616c537570706c79030000003230301a0000000d000000737570706c794d757461626c650500000066616c7365180000000c0000007472616e7366657261626c65040000007472756556000000010000002800000054414c49434532474d4133344358484437584c4a513533364e4d35554e4b5148544f524e4e54324a1a0000000600000068656c6c6f6d0c00000048656c6c6f206d6f7361696302000000000000002800000054414c49434532474d4133344358484437584c4a513533364e4d35554e4b5148544f524e4e54324adc05000000000000"
)
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 = parse_path("m/44'/1'/0'/0'/0'") n = parse_path("m/44'/1'/0'/0'/0'")

View File

@ -15,148 +15,190 @@
# If not, see <https://www.gnu.org/licenses/lgpl-3.0.html>. # If not, see <https://www.gnu.org/licenses/lgpl-3.0.html>.
from binascii import hexlify from binascii import hexlify
import pytest import pytest
from .common import TrezorTest from trezorlib import nem
from trezorlib.tools import parse_path from trezorlib.tools import parse_path
from trezorlib import nem from .common import TrezorTest
# assertion data from T1 # assertion data from T1
@pytest.mark.nem @pytest.mark.nem
class TestMsgNEMSignTxMultisig(TrezorTest): 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 = nem.sign_tx(self.client, parse_path("m/44'/1'/0'/0'/0'"), { tx = nem.sign_tx(
"timeStamp": 74649215, self.client,
"fee": 2000000, parse_path("m/44'/1'/0'/0'/0'"),
"type": nem.TYPE_AGGREGATE_MODIFICATION, {
"deadline": 74735615, "timeStamp": 74649215,
"message": { "fee": 2000000,
"type": nem.TYPE_AGGREGATE_MODIFICATION,
"deadline": 74735615,
"message": {},
"modifications": [
{
"modificationType": 1, # Add
"cosignatoryAccount": "c5f54ba980fcbb657dbaaa42700539b207873e134d2375efeab5f1ab52f87844",
}
],
"minCosignatories": {"relativeChange": 3},
"version": (0x98 << 24),
}, },
"modifications": [ )
{ assert (
"modificationType": 1, # Add hexlify(tx.data)
"cosignatoryAccount": "c5f54ba980fcbb657dbaaa42700539b207873e134d2375efeab5f1ab52f87844" == b"01100000020000987f0e730420000000edfd32f6e760648c032f9acb4b30d514265f6a5b5f8a7154f2618922b406208480841e0000000000ff5f740401000000280000000100000020000000c5f54ba980fcbb657dbaaa42700539b207873e134d2375efeab5f1ab52f878440400000003000000"
}, )
], assert (
"minCosignatories": { hexlify(tx.signature)
"relativeChange": 3 == b"1200e552d8732ce3eae96719731194abfc5a09d98f61bb35684f4eeaeff15b1bdf326ee7b1bbbe89d3f68c8e07ad3daf72e4c7f031094ad2236b97918ad98601"
}, )
"version": (0x98 << 24),
})
assert hexlify(tx.data) == b'01100000020000987f0e730420000000edfd32f6e760648c032f9acb4b30d514265f6a5b5f8a7154f2618922b406208480841e0000000000ff5f740401000000280000000100000020000000c5f54ba980fcbb657dbaaa42700539b207873e134d2375efeab5f1ab52f878440400000003000000'
assert hexlify(tx.signature) == b'1200e552d8732ce3eae96719731194abfc5a09d98f61bb35684f4eeaeff15b1bdf326ee7b1bbbe89d3f68c8e07ad3daf72e4c7f031094ad2236b97918ad98601'
def test_nem_signtx_multisig(self): def test_nem_signtx_multisig(self):
self.setup_mnemonic_nopin_nopassphrase() self.setup_mnemonic_nopin_nopassphrase()
tx = nem.sign_tx(self.client, parse_path("m/44'/1'/0'/0'/0'"), { tx = nem.sign_tx(
"timeStamp": 1, self.client,
"fee": 10000, parse_path("m/44'/1'/0'/0'/0'"),
"type": nem.TYPE_MULTISIG, {
"deadline": 74735615, "timeStamp": 1,
"otherTrans": { # simple transaction transfer "fee": 10000,
"timeStamp": 2, "type": nem.TYPE_MULTISIG,
"amount": 2000000, "deadline": 74735615,
"fee": 15000, "otherTrans": { # simple transaction transfer
"recipient": "TALICE2GMA34CXHD7XLJQ536NM5UNKQHTORNNT2J", "timeStamp": 2,
"type": nem.TYPE_TRANSACTION_TRANSFER, "amount": 2000000,
"deadline": 67890, "fee": 15000,
"message": { "recipient": "TALICE2GMA34CXHD7XLJQ536NM5UNKQHTORNNT2J",
"payload": hexlify(b"test_nem_transaction_transfer"), "type": nem.TYPE_TRANSACTION_TRANSFER,
"type": 1, "deadline": 67890,
"message": {
"payload": hexlify(b"test_nem_transaction_transfer"),
"type": 1,
},
"version": (0x98 << 24),
"signer": "c5f54ba980fcbb657dbaaa42700539b207873e134d2375efeab5f1ab52f87844",
}, },
"version": (0x98 << 24), "version": (0x98 << 24),
"signer": 'c5f54ba980fcbb657dbaaa42700539b207873e134d2375efeab5f1ab52f87844',
}, },
"version": (0x98 << 24), )
})
assert hexlify(tx.data) == b'04100000010000980100000020000000edfd32f6e760648c032f9acb4b30d514265f6a5b5f8a7154f2618922b40620841027000000000000ff5f74049900000001010000010000980200000020000000c5f54ba980fcbb657dbaaa42700539b207873e134d2375efeab5f1ab52f87844983a000000000000320901002800000054414c49434532474d4133344358484437584c4a513533364e4d35554e4b5148544f524e4e54324a80841e000000000025000000010000001d000000746573745f6e656d5f7472616e73616374696f6e5f7472616e73666572' assert (
assert hexlify(tx.signature) == b'0cab2fddf2f02b5d7201675b9a71869292fe25ed33a366c7d2cbea7676fed491faaa03310079b7e17884b6ba2e3ea21c4f728d1cca8f190b8288207f6514820a' hexlify(tx.data)
== b"04100000010000980100000020000000edfd32f6e760648c032f9acb4b30d514265f6a5b5f8a7154f2618922b40620841027000000000000ff5f74049900000001010000010000980200000020000000c5f54ba980fcbb657dbaaa42700539b207873e134d2375efeab5f1ab52f87844983a000000000000320901002800000054414c49434532474d4133344358484437584c4a513533364e4d35554e4b5148544f524e4e54324a80841e000000000025000000010000001d000000746573745f6e656d5f7472616e73616374696f6e5f7472616e73666572"
)
assert (
hexlify(tx.signature)
== b"0cab2fddf2f02b5d7201675b9a71869292fe25ed33a366c7d2cbea7676fed491faaa03310079b7e17884b6ba2e3ea21c4f728d1cca8f190b8288207f6514820a"
)
tx = nem.sign_tx(self.client, parse_path("m/44'/1'/0'/0'/0'"), { tx = nem.sign_tx(
"timeStamp": 74649215, self.client,
"fee": 150, parse_path("m/44'/1'/0'/0'/0'"),
"type": nem.TYPE_MULTISIG, {
"deadline": 789, "timeStamp": 74649215,
"otherTrans": { "fee": 150,
"timeStamp": 123456, "type": nem.TYPE_MULTISIG,
"fee": 2000, "deadline": 789,
"type": nem.TYPE_PROVISION_NAMESPACE, "otherTrans": {
"deadline": 100, "timeStamp": 123456,
"message": { "fee": 2000,
"type": nem.TYPE_PROVISION_NAMESPACE,
"deadline": 100,
"message": {},
"newPart": "ABCDE",
"rentalFeeSink": "TALICE2GMA34CXHD7XLJQ536NM5UNKQHTORNNT2J",
"rentalFee": 1500,
"parent": None,
"version": (0x98 << 24),
"signer": "c5f54ba980fcbb657dbaaa42700539b207873e134d2375efeab5f1ab52f87844",
}, },
"newPart": "ABCDE",
"rentalFeeSink": "TALICE2GMA34CXHD7XLJQ536NM5UNKQHTORNNT2J",
"rentalFee": 1500,
"parent": None,
"version": (0x98 << 24), "version": (0x98 << 24),
"signer": 'c5f54ba980fcbb657dbaaa42700539b207873e134d2375efeab5f1ab52f87844',
}, },
"version": (0x98 << 24), )
})
assert hexlify(tx.data) == b'04100000010000987f0e730420000000edfd32f6e760648c032f9acb4b30d514265f6a5b5f8a7154f2618922b40620849600000000000000150300007d000000012000000100009840e2010020000000c5f54ba980fcbb657dbaaa42700539b207873e134d2375efeab5f1ab52f87844d007000000000000640000002800000054414c49434532474d4133344358484437584c4a513533364e4d35554e4b5148544f524e4e54324adc05000000000000050000004142434445ffffffff' assert (
assert hexlify(tx.signature) == b'c915ca3332380925f4050301cdc62269cf29437ac5955321b18da34e570c7fdbb1aec2940a2a553a2a5c90950a4db3c8d3ef899c1a108582e0657f66fbbb0b04' hexlify(tx.data)
== b"04100000010000987f0e730420000000edfd32f6e760648c032f9acb4b30d514265f6a5b5f8a7154f2618922b40620849600000000000000150300007d000000012000000100009840e2010020000000c5f54ba980fcbb657dbaaa42700539b207873e134d2375efeab5f1ab52f87844d007000000000000640000002800000054414c49434532474d4133344358484437584c4a513533364e4d35554e4b5148544f524e4e54324adc05000000000000050000004142434445ffffffff"
)
assert (
hexlify(tx.signature)
== b"c915ca3332380925f4050301cdc62269cf29437ac5955321b18da34e570c7fdbb1aec2940a2a553a2a5c90950a4db3c8d3ef899c1a108582e0657f66fbbb0b04"
)
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 = nem.sign_tx(self.client, parse_path("m/44'/1'/0'/0'/0'"), { tx = nem.sign_tx(
"timeStamp": 333, self.client,
"fee": 200, parse_path("m/44'/1'/0'/0'/0'"),
"type": nem.TYPE_MULTISIG_SIGNATURE, {
"deadline": 444, "timeStamp": 333,
"otherTrans": { # simple transaction transfer "fee": 200,
"timeStamp": 555, "type": nem.TYPE_MULTISIG_SIGNATURE,
"amount": 2000000, "deadline": 444,
"fee": 2000000, "otherTrans": { # simple transaction transfer
"recipient": "TALICE2GMA34CXHD7XLJQ536NM5UNKQHTORNNT2J", "timeStamp": 555,
"type": nem.TYPE_TRANSACTION_TRANSFER, "amount": 2000000,
"deadline": 666, "fee": 2000000,
"message": { "recipient": "TALICE2GMA34CXHD7XLJQ536NM5UNKQHTORNNT2J",
"payload": hexlify(b"test_nem_transaction_transfer"), "type": nem.TYPE_TRANSACTION_TRANSFER,
"type": 1, "deadline": 666,
"message": {
"payload": hexlify(b"test_nem_transaction_transfer"),
"type": 1,
},
"version": (0x98 << 24),
"signer": "c5f54ba980fcbb657dbaaa42700539b207873e134d2375efeab5f1ab52f87844",
}, },
"version": (0x98 << 24), "version": (0x98 << 24),
"signer": 'c5f54ba980fcbb657dbaaa42700539b207873e134d2375efeab5f1ab52f87844',
}, },
"version": (0x98 << 24), )
})
assert hexlify(tx.data) == b'02100000010000984d01000020000000edfd32f6e760648c032f9acb4b30d514265f6a5b5f8a7154f2618922b4062084c800000000000000bc010000240000002000000087923cd4805f3babe6b5af9cbb2b08be4458e39531618aed73c911f160c8e38528000000544444324354364c514c49595135364b49584933454e544d36454b3344343450354b5a50464d4b32' assert (
assert hexlify(tx.signature) == b'286358a16ae545bff798feab93a713440c7c2f236d52ac0e995669d17a1915b0903667c97fa04418eccb42333cba95b19bccc8ac1faa8224dcfaeb41890ae807' hexlify(tx.data)
== b"02100000010000984d01000020000000edfd32f6e760648c032f9acb4b30d514265f6a5b5f8a7154f2618922b4062084c800000000000000bc010000240000002000000087923cd4805f3babe6b5af9cbb2b08be4458e39531618aed73c911f160c8e38528000000544444324354364c514c49595135364b49584933454e544d36454b3344343450354b5a50464d4b32"
)
assert (
hexlify(tx.signature)
== b"286358a16ae545bff798feab93a713440c7c2f236d52ac0e995669d17a1915b0903667c97fa04418eccb42333cba95b19bccc8ac1faa8224dcfaeb41890ae807"
)
tx = nem.sign_tx(self.client, parse_path("m/44'/1'/0'/0'/0'"), { tx = nem.sign_tx(
"timeStamp": 900000, self.client,
"fee": 200000, parse_path("m/44'/1'/0'/0'/0'"),
"type": nem.TYPE_MULTISIG_SIGNATURE, {
"deadline": 100, "timeStamp": 900000,
"otherTrans": { # simple transaction transfer "fee": 200000,
"timeStamp": 101111, "type": nem.TYPE_MULTISIG_SIGNATURE,
"fee": 1000, "deadline": 100,
"type": nem.TYPE_MOSAIC_SUPPLY_CHANGE, "otherTrans": { # simple transaction transfer
"deadline": 13123, "timeStamp": 101111,
"message": { "fee": 1000,
"type": nem.TYPE_MOSAIC_SUPPLY_CHANGE,
"deadline": 13123,
"message": {},
"mosaicId": {"namespaceId": "hellom", "name": "Hello mosaic"},
"supplyType": 1,
"delta": 1,
"version": (0x98 << 24),
"creationFeeSink": "TALICE2GMA34CXHD7XLJQ536NM5UNKQHTORNNT2J",
"creationFee": 1500,
"signer": "c5f54ba980fcbb657dbaaa42700539b207873e134d2375efeab5f1ab52f87844",
}, },
"mosaicId": {
"namespaceId": "hellom",
"name": "Hello mosaic"
},
"supplyType": 1,
"delta": 1,
"version": (0x98 << 24), "version": (0x98 << 24),
"creationFeeSink": "TALICE2GMA34CXHD7XLJQ536NM5UNKQHTORNNT2J",
"creationFee": 1500,
"signer": 'c5f54ba980fcbb657dbaaa42700539b207873e134d2375efeab5f1ab52f87844',
}, },
"version": (0x98 << 24), )
})
assert hexlify(tx.data) == b'0210000001000098a0bb0d0020000000edfd32f6e760648c032f9acb4b30d514265f6a5b5f8a7154f2618922b4062084400d030000000000640000002400000020000000c51395626a89a71c1ed785fb5974307a049b3b9e2165d56ed0302fe6b4f02a0128000000544444324354364c514c49595135364b49584933454e544d36454b3344343450354b5a50464d4b32' assert (
assert hexlify(tx.signature) == b'32b1fdf788c4a90c01eedf5972b7709745831d620c13e1e97b0de6481837e162ee551573f2409822754ae940731909ec4b79cf836487e898df476adb10467506' hexlify(tx.data)
== b"0210000001000098a0bb0d0020000000edfd32f6e760648c032f9acb4b30d514265f6a5b5f8a7154f2618922b4062084400d030000000000640000002400000020000000c51395626a89a71c1ed785fb5974307a049b3b9e2165d56ed0302fe6b4f02a0128000000544444324354364c514c49595135364b49584933454e544d36454b3344343450354b5a50464d4b32"
)
assert (
hexlify(tx.signature)
== b"32b1fdf788c4a90c01eedf5972b7709745831d620c13e1e97b0de6481837e162ee551573f2409822754ae940731909ec4b79cf836487e898df476adb10467506"
)

View File

@ -15,56 +15,74 @@
# If not, see <https://www.gnu.org/licenses/lgpl-3.0.html>. # If not, see <https://www.gnu.org/licenses/lgpl-3.0.html>.
from binascii import hexlify from binascii import hexlify
import pytest
from .common import TrezorTest import pytest
from trezorlib import nem from trezorlib import nem
from trezorlib.tools import parse_path from trezorlib.tools import parse_path
from .common import TrezorTest
# assertion data from T1 # assertion data from T1
@pytest.mark.nem @pytest.mark.nem
class TestMsgNEMSignTxOther(TrezorTest): class TestMsgNEMSignTxOther(TrezorTest):
def test_nem_signtx_importance_transfer(self): def test_nem_signtx_importance_transfer(self):
self.setup_mnemonic_nopin_nopassphrase() self.setup_mnemonic_nopin_nopassphrase()
with self.client: with self.client:
tx = nem.sign_tx(self.client, parse_path("m/44'/1'/0'/0'/0'"), { tx = nem.sign_tx(
"timeStamp": 12349215, self.client,
"fee": 9900, parse_path("m/44'/1'/0'/0'/0'"),
"type": nem.TYPE_IMPORTANCE_TRANSFER, {
"deadline": 99, "timeStamp": 12349215,
"message": { "fee": 9900,
"type": nem.TYPE_IMPORTANCE_TRANSFER,
"deadline": 99,
"message": {},
"importanceTransfer": {
"mode": 1, # activate
"publicKey": "c5f54ba980fcbb657dbaaa42700539b207873e134d2375efeab5f1ab52f87844",
},
"version": (0x98 << 24),
}, },
"importanceTransfer": { )
"mode": 1, # activate
"publicKey": "c5f54ba980fcbb657dbaaa42700539b207873e134d2375efeab5f1ab52f87844",
},
"version": (0x98 << 24),
})
assert hexlify(tx.data) == b'01080000010000981f6fbc0020000000edfd32f6e760648c032f9acb4b30d514265f6a5b5f8a7154f2618922b4062084ac26000000000000630000000100000020000000c5f54ba980fcbb657dbaaa42700539b207873e134d2375efeab5f1ab52f87844' assert (
assert hexlify(tx.signature) == b'b6d9434ec5df80e65e6e45d7f0f3c579b4adfe8567c42d981b06e8ac368b1aad2b24eebecd5efd41f4497051fca8ea8a5e77636a79afc46ee1a8e0fe9e3ba90b' hexlify(tx.data)
== b"01080000010000981f6fbc0020000000edfd32f6e760648c032f9acb4b30d514265f6a5b5f8a7154f2618922b4062084ac26000000000000630000000100000020000000c5f54ba980fcbb657dbaaa42700539b207873e134d2375efeab5f1ab52f87844"
)
assert (
hexlify(tx.signature)
== b"b6d9434ec5df80e65e6e45d7f0f3c579b4adfe8567c42d981b06e8ac368b1aad2b24eebecd5efd41f4497051fca8ea8a5e77636a79afc46ee1a8e0fe9e3ba90b"
)
def test_nem_signtx_provision_namespace(self): def test_nem_signtx_provision_namespace(self):
self.setup_mnemonic_nopin_nopassphrase() self.setup_mnemonic_nopin_nopassphrase()
tx = nem.sign_tx(self.client, parse_path("m/44'/1'/0'/0'/0'"), { tx = nem.sign_tx(
"timeStamp": 74649215, self.client,
"fee": 2000000, parse_path("m/44'/1'/0'/0'/0'"),
"type": nem.TYPE_PROVISION_NAMESPACE, {
"deadline": 74735615, "timeStamp": 74649215,
"message": { "fee": 2000000,
"type": nem.TYPE_PROVISION_NAMESPACE,
"deadline": 74735615,
"message": {},
"newPart": "ABCDE",
"rentalFeeSink": "TALICE2GMA34CXHD7XLJQ536NM5UNKQHTORNNT2J",
"rentalFee": 1500,
"parent": None,
"version": (0x98 << 24),
}, },
"newPart": "ABCDE", )
"rentalFeeSink": "TALICE2GMA34CXHD7XLJQ536NM5UNKQHTORNNT2J",
"rentalFee": 1500,
"parent": None,
"version": (0x98 << 24),
})
assert hexlify(tx.data) == b'01200000010000987f0e730420000000edfd32f6e760648c032f9acb4b30d514265f6a5b5f8a7154f2618922b406208480841e0000000000ff5f74042800000054414c49434532474d4133344358484437584c4a513533364e4d35554e4b5148544f524e4e54324adc05000000000000050000004142434445ffffffff' assert (
assert hexlify(tx.signature) == b'f047ae7987cd3a60c0d5ad123aba211185cb6266a7469dfb0491a0df6b5cd9c92b2e2b9f396cc2a3146ee185ba02df4f9e7fb238fe479917b3d274d97336640d' hexlify(tx.data)
== b"01200000010000987f0e730420000000edfd32f6e760648c032f9acb4b30d514265f6a5b5f8a7154f2618922b406208480841e0000000000ff5f74042800000054414c49434532474d4133344358484437584c4a513533364e4d35554e4b5148544f524e4e54324adc05000000000000050000004142434445ffffffff"
)
assert (
hexlify(tx.signature)
== b"f047ae7987cd3a60c0d5ad123aba211185cb6266a7469dfb0491a0df6b5cd9c92b2e2b9f396cc2a3146ee185ba02df4f9e7fb238fe479917b3d274d97336640d"
)

View File

@ -15,19 +15,18 @@
# If not, see <https://www.gnu.org/licenses/lgpl-3.0.html>. # If not, see <https://www.gnu.org/licenses/lgpl-3.0.html>.
from binascii import hexlify, unhexlify from binascii import hexlify, unhexlify
import pytest import pytest
from .common import TrezorTest from trezorlib import messages as proto, nem
from trezorlib import messages as proto
from trezorlib import nem
from trezorlib.tools import parse_path from trezorlib.tools import parse_path
from .common import TrezorTest
# assertion data from T1 # assertion data from T1
@pytest.mark.nem @pytest.mark.nem
class TestMsgNEMSignTx(TrezorTest): class TestMsgNEMSignTx(TrezorTest):
def test_nem_signtx_simple(self): def test_nem_signtx_simple(self):
# tx hash: 209368053ac61969b6838ceb7e31badeb622ed6aa42d6c58365c42ad1a11e19d # tx hash: 209368053ac61969b6838ceb7e31badeb622ed6aa42d6c58365c42ad1a11e19d
signature = unhexlify( signature = unhexlify(
@ -36,65 +35,83 @@ class TestMsgNEMSignTx(TrezorTest):
self.setup_mnemonic_nopin_nopassphrase() self.setup_mnemonic_nopin_nopassphrase()
with self.client: with self.client:
self.client.set_expected_responses([ self.client.set_expected_responses(
# Confirm transfer and network fee [
proto.ButtonRequest(code=proto.ButtonRequestType.ConfirmOutput), # Confirm transfer and network fee
# Unencrypted message proto.ButtonRequest(code=proto.ButtonRequestType.ConfirmOutput),
proto.ButtonRequest(code=proto.ButtonRequestType.ConfirmOutput), # Unencrypted message
# Confirm recipient proto.ButtonRequest(code=proto.ButtonRequestType.ConfirmOutput),
proto.ButtonRequest(code=proto.ButtonRequestType.SignTx), # Confirm recipient
proto.NEMSignedTx(), proto.ButtonRequest(code=proto.ButtonRequestType.SignTx),
]) proto.NEMSignedTx(),
]
)
tx = nem.sign_tx(self.client, parse_path("m/44'/1'/0'/0'/0'"), { tx = nem.sign_tx(
"timeStamp": 74649215, self.client,
"amount": 2000000, parse_path("m/44'/1'/0'/0'/0'"),
"fee": 2000000, {
"recipient": "TALICE2GMA34CXHD7XLJQ536NM5UNKQHTORNNT2J", "timeStamp": 74649215,
"type": nem.TYPE_TRANSACTION_TRANSFER, "amount": 2000000,
"deadline": 74735615, "fee": 2000000,
"message": { "recipient": "TALICE2GMA34CXHD7XLJQ536NM5UNKQHTORNNT2J",
"payload": hexlify(b"test_nem_transaction_transfer"), "type": nem.TYPE_TRANSACTION_TRANSFER,
"type": 1, "deadline": 74735615,
"message": {
"payload": hexlify(b"test_nem_transaction_transfer"),
"type": 1,
},
"version": (0x98 << 24),
}, },
"version": (0x98 << 24), )
})
assert hexlify(tx.data) == b'01010000010000987f0e730420000000edfd32f6e760648c032f9acb4b30d514265f6a5b5f8a7154f2618922b406208480841e0000000000ff5f74042800000054414c49434532474d4133344358484437584c4a513533364e4d35554e4b5148544f524e4e54324a80841e000000000025000000010000001d000000746573745f6e656d5f7472616e73616374696f6e5f7472616e73666572' assert (
hexlify(tx.data)
== b"01010000010000987f0e730420000000edfd32f6e760648c032f9acb4b30d514265f6a5b5f8a7154f2618922b406208480841e0000000000ff5f74042800000054414c49434532474d4133344358484437584c4a513533364e4d35554e4b5148544f524e4e54324a80841e000000000025000000010000001d000000746573745f6e656d5f7472616e73616374696f6e5f7472616e73666572"
)
assert tx.signature == signature assert tx.signature == signature
def test_nem_signtx_encrypted_payload(self): def test_nem_signtx_encrypted_payload(self):
self.setup_mnemonic_nopin_nopassphrase() self.setup_mnemonic_nopin_nopassphrase()
with self.client: with self.client:
self.client.set_expected_responses([ self.client.set_expected_responses(
# Confirm transfer and network fee [
proto.ButtonRequest(code=proto.ButtonRequestType.ConfirmOutput), # Confirm transfer and network fee
# Ask for encryption proto.ButtonRequest(code=proto.ButtonRequestType.ConfirmOutput),
proto.ButtonRequest(code=proto.ButtonRequestType.ConfirmOutput), # Ask for encryption
# Confirm recipient proto.ButtonRequest(code=proto.ButtonRequestType.ConfirmOutput),
proto.ButtonRequest(code=proto.ButtonRequestType.SignTx), # Confirm recipient
proto.NEMSignedTx(), proto.ButtonRequest(code=proto.ButtonRequestType.SignTx),
]) proto.NEMSignedTx(),
]
)
tx = nem.sign_tx(self.client, parse_path("m/44'/1'/0'/0'/0'"), { tx = nem.sign_tx(
"timeStamp": 74649215, self.client,
"amount": 2000000, parse_path("m/44'/1'/0'/0'/0'"),
"fee": 2000000, {
"recipient": "TALICE2GMA34CXHD7XLJQ536NM5UNKQHTORNNT2J", "timeStamp": 74649215,
"type": nem.TYPE_TRANSACTION_TRANSFER, "amount": 2000000,
"deadline": 74735615, "fee": 2000000,
"message": { "recipient": "TALICE2GMA34CXHD7XLJQ536NM5UNKQHTORNNT2J",
# plain text is 32B long => cipher text is 48B "type": nem.TYPE_TRANSACTION_TRANSFER,
# as per PKCS#7 another block containing padding is added "deadline": 74735615,
"payload": hexlify(b"this message should be encrypted"), "message": {
"publicKey": "5a5e14c633d7d269302849d739d80344ff14db51d7bcda86045723f05c4e4541", # plain text is 32B long => cipher text is 48B
"type": 2, # as per PKCS#7 another block containing padding is added
"payload": hexlify(b"this message should be encrypted"),
"publicKey": "5a5e14c633d7d269302849d739d80344ff14db51d7bcda86045723f05c4e4541",
"type": 2,
},
"version": (0x98 << 24),
}, },
"version": (0x98 << 24), )
})
assert hexlify(tx.data[:124]) == b'01010000010000987f0e730420000000edfd32f6e760648c032f9acb4b30d514265f6a5b5f8a7154f2618922b406208480841e0000000000ff5f74042800000054414c49434532474d4133344358484437584c4a513533364e4d35554e4b5148544f524e4e54324a80841e0000000000680000000200000060000000' assert (
hexlify(tx.data[:124])
== b"01010000010000987f0e730420000000edfd32f6e760648c032f9acb4b30d514265f6a5b5f8a7154f2618922b406208480841e0000000000ff5f74042800000054414c49434532474d4133344358484437584c4a513533364e4d35554e4b5148544f524e4e54324a80841e0000000000680000000200000060000000"
)
# after 124th byte comes iv (16B) salt (32B) and encrypted payload (48B) # after 124th byte comes iv (16B) salt (32B) and encrypted payload (48B)
assert len(tx.data[124:]) == 16 + 32 + 48 assert len(tx.data[124:]) == 16 + 32 + 48
# because IV and salt are random (therefore the encrypted payload as well) those data can't be asserted # because IV and salt are random (therefore the encrypted payload as well) those data can't be asserted
@ -103,170 +120,188 @@ 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 = nem.sign_tx(self.client, parse_path("m/44'/1'/0'/0'/0'"), { tx = nem.sign_tx(
"timeStamp": 76809215, self.client,
"amount": 5000000, parse_path("m/44'/1'/0'/0'/0'"),
"fee": 1000000, {
"recipient": "TALICE2GMA34CXHD7XLJQ536NM5UNKQHTORNNT2J", "timeStamp": 76809215,
"type": nem.TYPE_TRANSACTION_TRANSFER, "amount": 5000000,
"deadline": 76895615, "fee": 1000000,
"version": (0x98 << 24), "recipient": "TALICE2GMA34CXHD7XLJQ536NM5UNKQHTORNNT2J",
"message": { "type": nem.TYPE_TRANSACTION_TRANSFER,
"deadline": 76895615,
"version": (0x98 << 24),
"message": {},
"mosaics": [
{
"mosaicId": {"namespaceId": "nem", "name": "xem"},
"quantity": 9000000,
}
],
}, },
"mosaics": [ )
{
"mosaicId": {
"namespaceId": "nem",
"name": "xem",
},
"quantity": 9000000,
},
],
})
# trezor should display 45 XEM (multiplied by amount) # trezor should display 45 XEM (multiplied by amount)
assert hexlify(tx.data) == b'0101000002000098ff03940420000000edfd32f6e760648c032f9acb4b30d514265f6a5b5f8a7154f2618922b406208440420f00000000007f5595042800000054414c49434532474d4133344358484437584c4a513533364e4d35554e4b5148544f524e4e54324a404b4c000000000000000000010000001a0000000e000000030000006e656d0300000078656d4054890000000000' assert (
assert hexlify(tx.signature) == b'7b25a84b65adb489ea55739f1ca2d83a0ae069c3c58d0ea075fc30bfe8f649519199ad2324ca229c6c3214191469f95326e99712124592cae7cd3a092c93ac0c' hexlify(tx.data)
== b"0101000002000098ff03940420000000edfd32f6e760648c032f9acb4b30d514265f6a5b5f8a7154f2618922b406208440420f00000000007f5595042800000054414c49434532474d4133344358484437584c4a513533364e4d35554e4b5148544f524e4e54324a404b4c000000000000000000010000001a0000000e000000030000006e656d0300000078656d4054890000000000"
)
assert (
hexlify(tx.signature)
== b"7b25a84b65adb489ea55739f1ca2d83a0ae069c3c58d0ea075fc30bfe8f649519199ad2324ca229c6c3214191469f95326e99712124592cae7cd3a092c93ac0c"
)
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 = nem.sign_tx(self.client, parse_path("m/44'/1'/0'/0'/0'"), { tx = nem.sign_tx(
"timeStamp": 76809215, self.client,
"amount": 2000000, parse_path("m/44'/1'/0'/0'/0'"),
"fee": 1000000, {
"recipient": "TALICE2GMA34CXHD7XLJQ536NM5UNKQHTORNNT2J", "timeStamp": 76809215,
"type": nem.TYPE_TRANSACTION_TRANSFER, "amount": 2000000,
"deadline": 76895615, "fee": 1000000,
"version": (0x98 << 24), "recipient": "TALICE2GMA34CXHD7XLJQ536NM5UNKQHTORNNT2J",
"message": { "type": nem.TYPE_TRANSACTION_TRANSFER,
"deadline": 76895615,
"version": (0x98 << 24),
"message": {},
"mosaics": [
{
"mosaicId": {"namespaceId": "xxx", "name": "aa"},
"quantity": 3500000,
}
],
}, },
"mosaics": [ )
{
"mosaicId": {
"namespaceId": "xxx",
"name": "aa",
},
"quantity": 3500000,
},
],
})
# trezor should display warning about unknown mosaic and then dialog for 7000000 raw units of xxx.aa and 0 XEM # trezor should display warning about unknown mosaic and then dialog for 7000000 raw units of xxx.aa and 0 XEM
assert hexlify(tx.data) == b'0101000002000098ff03940420000000edfd32f6e760648c032f9acb4b30d514265f6a5b5f8a7154f2618922b406208440420f00000000007f5595042800000054414c49434532474d4133344358484437584c4a513533364e4d35554e4b5148544f524e4e54324a80841e00000000000000000001000000190000000d00000003000000787878020000006161e067350000000000' assert (
assert hexlify(tx.signature) == b'2f0280420eceb41ef9e5d94fa44ddda9cdc70b8f423ae18af577f6d85df64bb4aaf40cf24fc6eef47c63b0963611f8682348cecdc49a9b64eafcbe7afcb49102' hexlify(tx.data)
== b"0101000002000098ff03940420000000edfd32f6e760648c032f9acb4b30d514265f6a5b5f8a7154f2618922b406208440420f00000000007f5595042800000054414c49434532474d4133344358484437584c4a513533364e4d35554e4b5148544f524e4e54324a80841e00000000000000000001000000190000000d00000003000000787878020000006161e067350000000000"
)
assert (
hexlify(tx.signature)
== b"2f0280420eceb41ef9e5d94fa44ddda9cdc70b8f423ae18af577f6d85df64bb4aaf40cf24fc6eef47c63b0963611f8682348cecdc49a9b64eafcbe7afcb49102"
)
def test_nem_signtx_known_mosaic(self): def test_nem_signtx_known_mosaic(self):
self.setup_mnemonic_nopin_nopassphrase() self.setup_mnemonic_nopin_nopassphrase()
tx = nem.sign_tx(self.client, parse_path("m/44'/1'/0'/0'/0'"), { tx = nem.sign_tx(
"timeStamp": 76809215, self.client,
"amount": 3000000, parse_path("m/44'/1'/0'/0'/0'"),
"fee": 1000000, {
"recipient": "NDMYSLXI4L3FYUQWO4MJOVL6BSTJJXKDSZRMT4LT", "timeStamp": 76809215,
"type": nem.TYPE_TRANSACTION_TRANSFER, "amount": 3000000,
"deadline": 76895615, "fee": 1000000,
"version": (0x68 << 24), "recipient": "NDMYSLXI4L3FYUQWO4MJOVL6BSTJJXKDSZRMT4LT",
"message": { "type": nem.TYPE_TRANSACTION_TRANSFER,
"deadline": 76895615,
"version": (0x68 << 24),
"message": {},
"mosaics": [
{
"mosaicId": {"namespaceId": "dim", "name": "token"},
"quantity": 111000,
}
],
}, },
"mosaics": [ )
{
"mosaicId": {
"namespaceId": "dim",
"name": "token",
},
"quantity": 111000,
},
],
})
# trezor should display 0 XEM and 0.333 DIMTOK # trezor should display 0 XEM and 0.333 DIMTOK
assert hexlify(tx.data) == b'0101000002000068ff03940420000000edfd32f6e760648c032f9acb4b30d514265f6a5b5f8a7154f2618922b406208440420f00000000007f559504280000004e444d59534c5849344c3346595551574f344d4a4f564c364253544a4a584b44535a524d54344c54c0c62d000000000000000000010000001c000000100000000300000064696d05000000746f6b656e98b1010000000000' assert (
assert hexlify(tx.signature) == b'e7f14ef8c39727bfd257e109cd5acac31542f2e41f2e5deb258fc1db602b690eb1cabca41a627fe2adc51f3193db85c76b41c80bb60161eb8738ebf20b507104' hexlify(tx.data)
== b"0101000002000068ff03940420000000edfd32f6e760648c032f9acb4b30d514265f6a5b5f8a7154f2618922b406208440420f00000000007f559504280000004e444d59534c5849344c3346595551574f344d4a4f564c364253544a4a584b44535a524d54344c54c0c62d000000000000000000010000001c000000100000000300000064696d05000000746f6b656e98b1010000000000"
)
assert (
hexlify(tx.signature)
== b"e7f14ef8c39727bfd257e109cd5acac31542f2e41f2e5deb258fc1db602b690eb1cabca41a627fe2adc51f3193db85c76b41c80bb60161eb8738ebf20b507104"
)
def test_nem_signtx_known_mosaic_with_levy(self): def test_nem_signtx_known_mosaic_with_levy(self):
self.setup_mnemonic_nopin_nopassphrase() self.setup_mnemonic_nopin_nopassphrase()
tx = nem.sign_tx(self.client, parse_path("m/44'/1'/0'/0'/0'"), { tx = nem.sign_tx(
"timeStamp": 76809215, self.client,
"amount": 2000000, parse_path("m/44'/1'/0'/0'/0'"),
"fee": 1000000, {
"recipient": "NDMYSLXI4L3FYUQWO4MJOVL6BSTJJXKDSZRMT4LT", "timeStamp": 76809215,
"type": nem.TYPE_TRANSACTION_TRANSFER, "amount": 2000000,
"deadline": 76895615, "fee": 1000000,
"version": (0x68 << 24), "recipient": "NDMYSLXI4L3FYUQWO4MJOVL6BSTJJXKDSZRMT4LT",
"message": { "type": nem.TYPE_TRANSACTION_TRANSFER,
"deadline": 76895615,
"version": (0x68 << 24),
"message": {},
"mosaics": [
{
"mosaicId": {"namespaceId": "dim", "name": "coin"},
"quantity": 222000,
}
],
}, },
"mosaics": [ )
{
"mosaicId": {
"namespaceId": "dim",
"name": "coin",
},
"quantity": 222000,
},
],
})
# trezor should display 0 XEM and 0.444 DIM and levy of 0.000444 DIM # trezor should display 0 XEM and 0.444 DIM and levy of 0.000444 DIM
assert hexlify(tx.data) == b'0101000002000068ff03940420000000edfd32f6e760648c032f9acb4b30d514265f6a5b5f8a7154f2618922b406208440420f00000000007f559504280000004e444d59534c5849344c3346595551574f344d4a4f564c364253544a4a584b44535a524d54344c5480841e000000000000000000010000001b0000000f0000000300000064696d04000000636f696e3063030000000000' assert (
assert hexlify(tx.signature) == b'd3222dd7b83d66bda0539827ac6f909d06e40350b5e5e893d6fa762f954e9bf7da61022ef04950e7b6dfa88a2278f2f8a1b21df2bc3af22b388cb3a90bf76f07' hexlify(tx.data)
== b"0101000002000068ff03940420000000edfd32f6e760648c032f9acb4b30d514265f6a5b5f8a7154f2618922b406208440420f00000000007f559504280000004e444d59534c5849344c3346595551574f344d4a4f564c364253544a4a584b44535a524d54344c5480841e000000000000000000010000001b0000000f0000000300000064696d04000000636f696e3063030000000000"
)
assert (
hexlify(tx.signature)
== b"d3222dd7b83d66bda0539827ac6f909d06e40350b5e5e893d6fa762f954e9bf7da61022ef04950e7b6dfa88a2278f2f8a1b21df2bc3af22b388cb3a90bf76f07"
)
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 = nem.sign_tx(self.client, parse_path("m/44'/1'/0'/0'/0'"), { tx = nem.sign_tx(
"timeStamp": 76809215, self.client,
"amount": 2000000, parse_path("m/44'/1'/0'/0'/0'"),
"fee": 1000000, {
"recipient": "NDMYSLXI4L3FYUQWO4MJOVL6BSTJJXKDSZRMT4LT", "timeStamp": 76809215,
"type": nem.TYPE_TRANSACTION_TRANSFER, "amount": 2000000,
"deadline": 76895615, "fee": 1000000,
"version": (0x68 << 24), "recipient": "NDMYSLXI4L3FYUQWO4MJOVL6BSTJJXKDSZRMT4LT",
"message": { "type": nem.TYPE_TRANSACTION_TRANSFER,
"deadline": 76895615,
"version": (0x68 << 24),
"message": {},
"mosaics": [
{
"mosaicId": {"namespaceId": "nem", "name": "xem"},
"quantity": 3000000,
},
{
"mosaicId": {"namespaceId": "abc", "name": "mosaic"},
"quantity": 200,
},
{
"mosaicId": {"namespaceId": "nem", "name": "xem"},
"quantity": 30000,
},
{
"mosaicId": {"namespaceId": "abc", "name": "mosaic"},
"quantity": 2000000,
},
{
"mosaicId": {"namespaceId": "breeze", "name": "breeze-token"},
"quantity": 111000,
},
],
}, },
"mosaics": [ )
{
"mosaicId": {
"namespaceId": "nem",
"name": "xem",
},
"quantity": 3000000,
},
{
"mosaicId": {
"namespaceId": "abc",
"name": "mosaic",
},
"quantity": 200,
},
{
"mosaicId": {
"namespaceId": "nem",
"name": "xem",
},
"quantity": 30000,
},
{
"mosaicId": {
"namespaceId": "abc",
"name": "mosaic",
},
"quantity": 2000000,
},
{
"mosaicId": {
"namespaceId": "breeze",
"name": "breeze-token",
},
"quantity": 111000,
}
]
})
# trezor should display warning, 6.06 XEM, 4000400 raw units of abc.mosaic (mosaics are merged) # trezor should display warning, 6.06 XEM, 4000400 raw units of abc.mosaic (mosaics are merged)
# and 222000 BREEZE # and 222000 BREEZE
assert hexlify(tx.data) == b'0101000002000068ff03940420000000edfd32f6e760648c032f9acb4b30d514265f6a5b5f8a7154f2618922b406208440420f00000000007f559504280000004e444d59534c5849344c3346595551574f344d4a4f564c364253544a4a584b44535a524d54344c5480841e000000000000000000030000001d0000001100000003000000616263060000006d6f7361696348851e0000000000260000001a00000006000000627265657a650c000000627265657a652d746f6b656e98b10100000000001a0000000e000000030000006e656d0300000078656df03b2e0000000000' assert (
assert hexlify(tx.signature) == b'b2b9319fca87a05bee17108edd9a8f78aeffef74bf6b4badc6da5d46e8ff4fe82e24bf69d8e6c4097d072adf39d0c753e7580f8afb21e3288ebfb7c4d84e470d' hexlify(tx.data)
== b"0101000002000068ff03940420000000edfd32f6e760648c032f9acb4b30d514265f6a5b5f8a7154f2618922b406208440420f00000000007f559504280000004e444d59534c5849344c3346595551574f344d4a4f564c364253544a4a584b44535a524d54344c5480841e000000000000000000030000001d0000001100000003000000616263060000006d6f7361696348851e0000000000260000001a00000006000000627265657a650c000000627265657a652d746f6b656e98b10100000000001a0000000e000000030000006e656d0300000078656df03b2e0000000000"
)
assert (
hexlify(tx.signature)
== b"b2b9319fca87a05bee17108edd9a8f78aeffef74bf6b4badc6da5d46e8ff4fe82e24bf69d8e6c4097d072adf39d0c753e7580f8afb21e3288ebfb7c4d84e470d"
)

View File

@ -16,47 +16,77 @@
import pytest import pytest
from .common import TrezorTest
from trezorlib import messages as proto from trezorlib import messages as proto
from .common import TrezorTest
@pytest.mark.skip_t2 @pytest.mark.skip_t2
class TestMsgPing(TrezorTest): class TestMsgPing(TrezorTest):
def test_ping(self): def test_ping(self):
self.setup_mnemonic_pin_passphrase() self.setup_mnemonic_pin_passphrase()
with self.client: with self.client:
self.client.set_expected_responses([proto.Success()]) self.client.set_expected_responses([proto.Success()])
res = self.client.ping('random data') res = self.client.ping("random data")
assert res == 'random data' assert res == "random data"
with self.client: with self.client:
self.client.set_expected_responses([proto.ButtonRequest(code=proto.ButtonRequestType.ProtectCall), proto.Success()]) self.client.set_expected_responses(
res = self.client.ping('random data', button_protection=True) [
assert res == 'random data' proto.ButtonRequest(code=proto.ButtonRequestType.ProtectCall),
proto.Success(),
]
)
res = self.client.ping("random data", button_protection=True)
assert res == "random data"
with self.client: with self.client:
self.client.set_expected_responses([proto.PinMatrixRequest(), proto.Success()]) self.client.set_expected_responses(
res = self.client.ping('random data', pin_protection=True) [proto.PinMatrixRequest(), proto.Success()]
assert res == 'random data' )
res = self.client.ping("random data", pin_protection=True)
assert res == "random data"
with self.client: with self.client:
self.client.set_expected_responses([proto.PassphraseRequest(), proto.Success()]) self.client.set_expected_responses(
res = self.client.ping('random data', passphrase_protection=True) [proto.PassphraseRequest(), proto.Success()]
assert res == 'random data' )
res = self.client.ping("random data", passphrase_protection=True)
assert res == "random data"
def test_ping_caching(self): def test_ping_caching(self):
self.setup_mnemonic_pin_passphrase() self.setup_mnemonic_pin_passphrase()
with self.client: with self.client:
self.client.set_expected_responses([proto.ButtonRequest(code=proto.ButtonRequestType.ProtectCall), proto.PinMatrixRequest(), proto.PassphraseRequest(), proto.Success()]) self.client.set_expected_responses(
res = self.client.ping('random data', button_protection=True, pin_protection=True, passphrase_protection=True) [
assert res == 'random data' proto.ButtonRequest(code=proto.ButtonRequestType.ProtectCall),
proto.PinMatrixRequest(),
proto.PassphraseRequest(),
proto.Success(),
]
)
res = self.client.ping(
"random data",
button_protection=True,
pin_protection=True,
passphrase_protection=True,
)
assert res == "random data"
with self.client: with self.client:
# pin and passphrase are cached # pin and passphrase are cached
self.client.set_expected_responses([proto.ButtonRequest(code=proto.ButtonRequestType.ProtectCall), proto.Success()]) self.client.set_expected_responses(
res = self.client.ping('random data', button_protection=True, pin_protection=True, passphrase_protection=True) [
assert res == 'random data' proto.ButtonRequest(code=proto.ButtonRequestType.ProtectCall),
proto.Success(),
]
)
res = self.client.ping(
"random data",
button_protection=True,
pin_protection=True,
passphrase_protection=True,
)
assert res == "random data"

View File

@ -16,22 +16,25 @@
import pytest import pytest
from trezorlib import device, messages as proto
from .common import TrezorTest from .common import TrezorTest
from trezorlib import messages as proto
from trezorlib import device
@pytest.mark.skip_t2 @pytest.mark.skip_t2
class TestMsgRecoverydevice(TrezorTest): class TestMsgRecoverydevice(TrezorTest):
def test_pin_passphrase(self): def test_pin_passphrase(self):
mnemonic = self.mnemonic12.split(' ') mnemonic = self.mnemonic12.split(" ")
ret = self.client.call_raw(proto.RecoveryDevice(word_count=12, ret = self.client.call_raw(
passphrase_protection=True, proto.RecoveryDevice(
pin_protection=True, word_count=12,
label='label', passphrase_protection=True,
language='english', pin_protection=True,
enforce_wordlist=True)) label="label",
language="english",
enforce_wordlist=True,
)
)
# click through confirmation # click through confirmation
assert isinstance(ret, proto.ButtonRequest) assert isinstance(ret, proto.ButtonRequest)
@ -88,13 +91,17 @@ class TestMsgRecoverydevice(TrezorTest):
self.client.call_raw(proto.Cancel()) self.client.call_raw(proto.Cancel())
def test_nopin_nopassphrase(self): def test_nopin_nopassphrase(self):
mnemonic = self.mnemonic12.split(' ') mnemonic = self.mnemonic12.split(" ")
ret = self.client.call_raw(proto.RecoveryDevice(word_count=12, ret = self.client.call_raw(
passphrase_protection=False, proto.RecoveryDevice(
pin_protection=False, word_count=12,
label='label', passphrase_protection=False,
language='english', pin_protection=False,
enforce_wordlist=True)) label="label",
language="english",
enforce_wordlist=True,
)
)
# click through confirmation # click through confirmation
assert isinstance(ret, proto.ButtonRequest) assert isinstance(ret, proto.ButtonRequest)
@ -138,12 +145,16 @@ class TestMsgRecoverydevice(TrezorTest):
assert isinstance(resp, proto.Success) assert isinstance(resp, proto.Success)
def test_word_fail(self): def test_word_fail(self):
ret = self.client.call_raw(proto.RecoveryDevice(word_count=12, ret = self.client.call_raw(
passphrase_protection=False, proto.RecoveryDevice(
pin_protection=False, word_count=12,
label='label', passphrase_protection=False,
language='english', pin_protection=False,
enforce_wordlist=True)) label="label",
language="english",
enforce_wordlist=True,
)
)
# click through confirmation # click through confirmation
assert isinstance(ret, proto.ButtonRequest) assert isinstance(ret, proto.ButtonRequest)
@ -154,19 +165,23 @@ class TestMsgRecoverydevice(TrezorTest):
for _ in range(int(12 * 2)): for _ in range(int(12 * 2)):
(word, pos) = self.client.debug.read_recovery_word() (word, pos) = self.client.debug.read_recovery_word()
if pos != 0: if pos != 0:
ret = self.client.call_raw(proto.WordAck(word='kwyjibo')) ret = self.client.call_raw(proto.WordAck(word="kwyjibo"))
assert isinstance(ret, proto.Failure) assert isinstance(ret, proto.Failure)
break break
else: else:
self.client.call_raw(proto.WordAck(word=word)) self.client.call_raw(proto.WordAck(word=word))
def test_pin_fail(self): def test_pin_fail(self):
ret = self.client.call_raw(proto.RecoveryDevice(word_count=12, ret = self.client.call_raw(
passphrase_protection=True, proto.RecoveryDevice(
pin_protection=True, word_count=12,
label='label', passphrase_protection=True,
language='english', pin_protection=True,
enforce_wordlist=True)) label="label",
language="english",
enforce_wordlist=True,
)
)
# click through confirmation # click through confirmation
assert isinstance(ret, proto.ButtonRequest) assert isinstance(ret, proto.ButtonRequest)
@ -190,4 +205,4 @@ class TestMsgRecoverydevice(TrezorTest):
def test_already_initialized(self): def test_already_initialized(self):
self.setup_mnemonic_nopin_nopassphrase() self.setup_mnemonic_nopin_nopassphrase()
with pytest.raises(Exception): with pytest.raises(Exception):
device.recover(self.client, 12, False, False, 'label', 'english') device.recover(self.client, 12, False, False, "label", "english")

View File

@ -16,21 +16,25 @@
import pytest import pytest
from .common import TrezorTest
from trezorlib import messages as proto from trezorlib import messages as proto
from .common import TrezorTest
@pytest.mark.skip_t2 @pytest.mark.skip_t2
class TestMsgRecoverydeviceDryrun(TrezorTest): class TestMsgRecoverydeviceDryrun(TrezorTest):
def recovery_loop(self, mnemonic, result): def recovery_loop(self, mnemonic, result):
ret = self.client.call_raw(proto.RecoveryDevice(word_count=12, ret = self.client.call_raw(
passphrase_protection=False, proto.RecoveryDevice(
pin_protection=False, word_count=12,
label='label', passphrase_protection=False,
language='english', pin_protection=False,
enforce_wordlist=True, label="label",
dry_run=True)) language="english",
enforce_wordlist=True,
dry_run=True,
)
)
fakes = 0 fakes = 0
for _ in range(int(12 * 2)): for _ in range(int(12 * 2)):
@ -54,15 +58,15 @@ class TestMsgRecoverydeviceDryrun(TrezorTest):
def test_correct_notsame(self): def test_correct_notsame(self):
self.setup_mnemonic_nopin_nopassphrase() self.setup_mnemonic_nopin_nopassphrase()
mnemonic = ['all'] * 12 mnemonic = ["all"] * 12
self.recovery_loop(mnemonic, proto.Failure) self.recovery_loop(mnemonic, proto.Failure)
def test_correct_same(self): def test_correct_same(self):
self.setup_mnemonic_nopin_nopassphrase() self.setup_mnemonic_nopin_nopassphrase()
mnemonic = self.mnemonic12.split(' ') mnemonic = self.mnemonic12.split(" ")
self.recovery_loop(mnemonic, proto.Success) self.recovery_loop(mnemonic, proto.Success)
def test_incorrect(self): def test_incorrect(self):
self.setup_mnemonic_nopin_nopassphrase() self.setup_mnemonic_nopin_nopassphrase()
mnemonic = ['stick'] * 12 mnemonic = ["stick"] * 12
self.recovery_loop(mnemonic, proto.Failure) self.recovery_loop(mnemonic, proto.Failure)

View File

@ -18,24 +18,28 @@ import time
import pytest import pytest
from trezorlib import device, messages as proto
from .common import TrezorTest from .common import TrezorTest
from trezorlib import messages as proto
from trezorlib import device
@pytest.mark.skip_t1 @pytest.mark.skip_t1
class TestMsgRecoverydeviceT2(TrezorTest): class TestMsgRecoverydeviceT2(TrezorTest):
def test_pin_passphrase(self): def test_pin_passphrase(self):
mnemonic = self.mnemonic12.split(' ') mnemonic = self.mnemonic12.split(" ")
ret = self.client.call_raw(proto.RecoveryDevice( ret = self.client.call_raw(
passphrase_protection=True, proto.RecoveryDevice(
pin_protection=True, passphrase_protection=True,
label='label', pin_protection=True,
enforce_wordlist=True)) label="label",
enforce_wordlist=True,
)
)
# Enter word count # Enter word count
assert ret == proto.ButtonRequest(code=proto.ButtonRequestType.MnemonicWordCount) assert ret == proto.ButtonRequest(
code=proto.ButtonRequestType.MnemonicWordCount
)
self.client.debug.input(str(len(mnemonic))) self.client.debug.input(str(len(mnemonic)))
ret = self.client.call_raw(proto.ButtonAck()) ret = self.client.call_raw(proto.ButtonAck())
@ -49,16 +53,16 @@ class TestMsgRecoverydeviceT2(TrezorTest):
# Enter PIN for first time # Enter PIN for first time
assert ret == proto.ButtonRequest(code=proto.ButtonRequestType.Other) assert ret == proto.ButtonRequest(code=proto.ButtonRequestType.Other)
self.client.debug.input('654') self.client.debug.input("654")
ret = self.client.call_raw(proto.ButtonAck()) ret = self.client.call_raw(proto.ButtonAck())
# Enter PIN for second time # Enter PIN for second time
assert ret == proto.ButtonRequest(code=proto.ButtonRequestType.Other) assert ret == proto.ButtonRequest(code=proto.ButtonRequestType.Other)
self.client.debug.input('654') self.client.debug.input("654")
ret = self.client.call_raw(proto.ButtonAck()) ret = self.client.call_raw(proto.ButtonAck())
# Workflow succesfully ended # Workflow succesfully ended
assert ret == proto.Success(message='Device recovered') assert ret == proto.Success(message="Device recovered")
# Mnemonic is the same # Mnemonic is the same
self.client.init_device() self.client.init_device()
@ -68,15 +72,20 @@ class TestMsgRecoverydeviceT2(TrezorTest):
assert self.client.features.passphrase_protection is True assert self.client.features.passphrase_protection is True
def test_nopin_nopassphrase(self): def test_nopin_nopassphrase(self):
mnemonic = self.mnemonic12.split(' ') mnemonic = self.mnemonic12.split(" ")
ret = self.client.call_raw(proto.RecoveryDevice( ret = self.client.call_raw(
passphrase_protection=False, proto.RecoveryDevice(
pin_protection=False, passphrase_protection=False,
label='label', pin_protection=False,
enforce_wordlist=True)) label="label",
enforce_wordlist=True,
)
)
# Enter word count # Enter word count
assert ret == proto.ButtonRequest(code=proto.ButtonRequestType.MnemonicWordCount) assert ret == proto.ButtonRequest(
code=proto.ButtonRequestType.MnemonicWordCount
)
self.client.debug.input(str(len(mnemonic))) self.client.debug.input(str(len(mnemonic)))
ret = self.client.call_raw(proto.ButtonAck()) ret = self.client.call_raw(proto.ButtonAck())
@ -89,7 +98,7 @@ class TestMsgRecoverydeviceT2(TrezorTest):
ret = self.client.transport.read() ret = self.client.transport.read()
# Workflow succesfully ended # Workflow succesfully ended
assert ret == proto.Success(message='Device recovered') assert ret == proto.Success(message="Device recovered")
# Mnemonic is the same # Mnemonic is the same
self.client.init_device() self.client.init_device()
@ -101,4 +110,4 @@ class TestMsgRecoverydeviceT2(TrezorTest):
def test_already_initialized(self): def test_already_initialized(self):
self.setup_mnemonic_nopin_nopassphrase() self.setup_mnemonic_nopin_nopassphrase()
with pytest.raises(Exception): with pytest.raises(Exception):
device.recover(self.client, 12, False, False, 'label', 'english') device.recover(self.client, 12, False, False, "label", "english")

View File

@ -15,31 +15,31 @@
# If not, see <https://www.gnu.org/licenses/lgpl-3.0.html>. # If not, see <https://www.gnu.org/licenses/lgpl-3.0.html>.
import pytest import pytest
from mnemonic import Mnemonic
from trezorlib import device, messages as proto
from .common import TrezorTest, generate_entropy from .common import TrezorTest, generate_entropy
from trezorlib import messages as proto
from trezorlib import device
from mnemonic import Mnemonic
@pytest.mark.skip_t2 @pytest.mark.skip_t2
class TestMsgResetDevice(TrezorTest): class TestMsgResetDevice(TrezorTest):
def test_reset_device(self): def test_reset_device(self):
# No PIN, no passphrase # No PIN, no passphrase
external_entropy = b'zlutoucky kun upel divoke ody' * 2 external_entropy = b"zlutoucky kun upel divoke ody" * 2
strength = 128 strength = 128
ret = self.client.call_raw(proto.ResetDevice( ret = self.client.call_raw(
display_random=False, proto.ResetDevice(
strength=strength, display_random=False,
passphrase_protection=False, strength=strength,
pin_protection=False, passphrase_protection=False,
language='english', pin_protection=False,
label='test' language="english",
)) label="test",
)
)
# Provide entropy # Provide entropy
assert isinstance(ret, proto.EntropyRequest) assert isinstance(ret, proto.EntropyRequest)
@ -48,7 +48,7 @@ class TestMsgResetDevice(TrezorTest):
# Generate mnemonic locally # Generate mnemonic locally
entropy = generate_entropy(strength, internal_entropy, external_entropy) entropy = generate_entropy(strength, internal_entropy, external_entropy)
expected_mnemonic = Mnemonic('english').to_mnemonic(entropy) expected_mnemonic = Mnemonic("english").to_mnemonic(entropy)
mnemonic = [] mnemonic = []
for _ in range(strength // 32 * 3): for _ in range(strength // 32 * 3):
@ -57,7 +57,7 @@ class TestMsgResetDevice(TrezorTest):
self.client.debug.press_yes() self.client.debug.press_yes()
self.client.call_raw(proto.ButtonAck()) self.client.call_raw(proto.ButtonAck())
mnemonic = ' '.join(mnemonic) mnemonic = " ".join(mnemonic)
# Compare that device generated proper mnemonic for given entropies # Compare that device generated proper mnemonic for given entropies
assert mnemonic == expected_mnemonic assert mnemonic == expected_mnemonic
@ -71,7 +71,7 @@ class TestMsgResetDevice(TrezorTest):
assert isinstance(resp, proto.Success) assert isinstance(resp, proto.Success)
mnemonic = ' '.join(mnemonic) mnemonic = " ".join(mnemonic)
# Compare that second pass printed out the same mnemonic once again # Compare that second pass printed out the same mnemonic once again
assert mnemonic == expected_mnemonic assert mnemonic == expected_mnemonic
@ -92,17 +92,19 @@ class TestMsgResetDevice(TrezorTest):
assert isinstance(resp, proto.Success) assert isinstance(resp, proto.Success)
def test_reset_device_pin(self): def test_reset_device_pin(self):
external_entropy = b'zlutoucky kun upel divoke ody' * 2 external_entropy = b"zlutoucky kun upel divoke ody" * 2
strength = 128 strength = 128
ret = self.client.call_raw(proto.ResetDevice( ret = self.client.call_raw(
display_random=True, proto.ResetDevice(
strength=strength, display_random=True,
passphrase_protection=True, strength=strength,
pin_protection=True, passphrase_protection=True,
language='english', pin_protection=True,
label='test' language="english",
)) label="test",
)
)
assert isinstance(ret, proto.ButtonRequest) assert isinstance(ret, proto.ButtonRequest)
self.client.debug.press_yes() self.client.debug.press_yes()
@ -111,12 +113,12 @@ class TestMsgResetDevice(TrezorTest):
assert isinstance(ret, proto.PinMatrixRequest) assert isinstance(ret, proto.PinMatrixRequest)
# Enter PIN for first time # Enter PIN for first time
pin_encoded = self.client.debug.encode_pin('654') pin_encoded = self.client.debug.encode_pin("654")
ret = self.client.call_raw(proto.PinMatrixAck(pin=pin_encoded)) ret = self.client.call_raw(proto.PinMatrixAck(pin=pin_encoded))
assert isinstance(ret, proto.PinMatrixRequest) assert isinstance(ret, proto.PinMatrixRequest)
# Enter PIN for second time # Enter PIN for second time
pin_encoded = self.client.debug.encode_pin('654') pin_encoded = self.client.debug.encode_pin("654")
ret = self.client.call_raw(proto.PinMatrixAck(pin=pin_encoded)) ret = self.client.call_raw(proto.PinMatrixAck(pin=pin_encoded))
# Provide entropy # Provide entropy
@ -126,7 +128,7 @@ class TestMsgResetDevice(TrezorTest):
# Generate mnemonic locally # Generate mnemonic locally
entropy = generate_entropy(strength, internal_entropy, external_entropy) entropy = generate_entropy(strength, internal_entropy, external_entropy)
expected_mnemonic = Mnemonic('english').to_mnemonic(entropy) expected_mnemonic = Mnemonic("english").to_mnemonic(entropy)
mnemonic = [] mnemonic = []
for _ in range(strength // 32 * 3): for _ in range(strength // 32 * 3):
@ -135,7 +137,7 @@ class TestMsgResetDevice(TrezorTest):
self.client.debug.press_yes() self.client.debug.press_yes()
self.client.call_raw(proto.ButtonAck()) self.client.call_raw(proto.ButtonAck())
mnemonic = ' '.join(mnemonic) mnemonic = " ".join(mnemonic)
# Compare that device generated proper mnemonic for given entropies # Compare that device generated proper mnemonic for given entropies
assert mnemonic == expected_mnemonic assert mnemonic == expected_mnemonic
@ -149,7 +151,7 @@ class TestMsgResetDevice(TrezorTest):
assert isinstance(resp, proto.Success) assert isinstance(resp, proto.Success)
mnemonic = ' '.join(mnemonic) mnemonic = " ".join(mnemonic)
# Compare that second pass printed out the same mnemonic once again # Compare that second pass printed out the same mnemonic once again
assert mnemonic == expected_mnemonic assert mnemonic == expected_mnemonic
@ -175,14 +177,16 @@ class TestMsgResetDevice(TrezorTest):
# external_entropy = b'zlutoucky kun upel divoke ody' * 2 # external_entropy = b'zlutoucky kun upel divoke ody' * 2
strength = 128 strength = 128
ret = self.client.call_raw(proto.ResetDevice( ret = self.client.call_raw(
display_random=True, proto.ResetDevice(
strength=strength, display_random=True,
passphrase_protection=True, strength=strength,
pin_protection=True, passphrase_protection=True,
language='english', pin_protection=True,
label='test' language="english",
)) label="test",
)
)
assert isinstance(ret, proto.ButtonRequest) assert isinstance(ret, proto.ButtonRequest)
self.client.debug.press_yes() self.client.debug.press_yes()
@ -204,4 +208,4 @@ class TestMsgResetDevice(TrezorTest):
def test_already_initialized(self): def test_already_initialized(self):
self.setup_mnemonic_nopin_nopassphrase() self.setup_mnemonic_nopin_nopassphrase()
with pytest.raises(Exception): with pytest.raises(Exception):
device.reset(self.client, False, 128, True, True, 'label', 'english') device.reset(self.client, False, 128, True, True, "label", "english")

View File

@ -15,29 +15,31 @@
# If not, see <https://www.gnu.org/licenses/lgpl-3.0.html>. # If not, see <https://www.gnu.org/licenses/lgpl-3.0.html>.
import pytest import pytest
from mnemonic import Mnemonic
from trezorlib import messages as proto
from .common import TrezorTest, generate_entropy from .common import TrezorTest, generate_entropy
from trezorlib import messages as proto
from mnemonic import Mnemonic
@pytest.mark.skip_t2 @pytest.mark.skip_t2
class TestMsgResetDeviceSkipbackup(TrezorTest): class TestMsgResetDeviceSkipbackup(TrezorTest):
def test_reset_device_skip_backup(self): def test_reset_device_skip_backup(self):
external_entropy = b'zlutoucky kun upel divoke ody' * 2 external_entropy = b"zlutoucky kun upel divoke ody" * 2
strength = 128 strength = 128
ret = self.client.call_raw(proto.ResetDevice( ret = self.client.call_raw(
display_random=False, proto.ResetDevice(
strength=strength, display_random=False,
passphrase_protection=False, strength=strength,
pin_protection=False, passphrase_protection=False,
language='english', pin_protection=False,
label='test', language="english",
skip_backup=True label="test",
)) skip_backup=True,
)
)
# Provide entropy # Provide entropy
assert isinstance(ret, proto.EntropyRequest) assert isinstance(ret, proto.EntropyRequest)
@ -52,7 +54,7 @@ class TestMsgResetDeviceSkipbackup(TrezorTest):
# Generate mnemonic locally # Generate mnemonic locally
entropy = generate_entropy(strength, internal_entropy, external_entropy) entropy = generate_entropy(strength, internal_entropy, external_entropy)
expected_mnemonic = Mnemonic('english').to_mnemonic(entropy) expected_mnemonic = Mnemonic("english").to_mnemonic(entropy)
# start Backup workflow # start Backup workflow
ret = self.client.call_raw(proto.BackupDevice()) ret = self.client.call_raw(proto.BackupDevice())
@ -64,7 +66,7 @@ class TestMsgResetDeviceSkipbackup(TrezorTest):
self.client.debug.press_yes() self.client.debug.press_yes()
self.client.call_raw(proto.ButtonAck()) self.client.call_raw(proto.ButtonAck())
mnemonic = ' '.join(mnemonic) mnemonic = " ".join(mnemonic)
# Compare that device generated proper mnemonic for given entropies # Compare that device generated proper mnemonic for given entropies
assert mnemonic == expected_mnemonic assert mnemonic == expected_mnemonic
@ -78,7 +80,7 @@ class TestMsgResetDeviceSkipbackup(TrezorTest):
assert isinstance(resp, proto.Success) assert isinstance(resp, proto.Success)
mnemonic = ' '.join(mnemonic) mnemonic = " ".join(mnemonic)
# Compare that second pass printed out the same mnemonic once again # Compare that second pass printed out the same mnemonic once again
assert mnemonic == expected_mnemonic assert mnemonic == expected_mnemonic
@ -89,18 +91,20 @@ class TestMsgResetDeviceSkipbackup(TrezorTest):
def test_reset_device_skip_backup_break(self): def test_reset_device_skip_backup_break(self):
external_entropy = b'zlutoucky kun upel divoke ody' * 2 external_entropy = b"zlutoucky kun upel divoke ody" * 2
strength = 128 strength = 128
ret = self.client.call_raw(proto.ResetDevice( ret = self.client.call_raw(
display_random=False, proto.ResetDevice(
strength=strength, display_random=False,
passphrase_protection=False, strength=strength,
pin_protection=False, passphrase_protection=False,
language='english', pin_protection=False,
label='test', language="english",
skip_backup=True label="test",
)) skip_backup=True,
)
)
# Provide entropy # Provide entropy
assert isinstance(ret, proto.EntropyRequest) assert isinstance(ret, proto.EntropyRequest)

View File

@ -15,30 +15,31 @@
# If not, see <https://www.gnu.org/licenses/lgpl-3.0.html>. # If not, see <https://www.gnu.org/licenses/lgpl-3.0.html>.
import time import time
import pytest import pytest
from mnemonic import Mnemonic
from trezorlib import device, messages as proto
from .common import TrezorTest, generate_entropy from .common import TrezorTest, generate_entropy
from trezorlib import messages as proto
from trezorlib import device
from mnemonic import Mnemonic
@pytest.mark.skip_t1 @pytest.mark.skip_t1
class TestMsgResetDeviceT2(TrezorTest): class TestMsgResetDeviceT2(TrezorTest):
def test_reset_device(self): def test_reset_device(self):
# No PIN, no passphrase, don't display random # No PIN, no passphrase, don't display random
external_entropy = b'zlutoucky kun upel divoke ody' * 2 external_entropy = b"zlutoucky kun upel divoke ody" * 2
strength = 128 strength = 128
ret = self.client.call_raw(proto.ResetDevice( ret = self.client.call_raw(
display_random=False, proto.ResetDevice(
strength=strength, display_random=False,
passphrase_protection=False, strength=strength,
pin_protection=False, passphrase_protection=False,
label='test' pin_protection=False,
)) label="test",
)
)
# Provide entropy # Provide entropy
assert isinstance(ret, proto.EntropyRequest) assert isinstance(ret, proto.EntropyRequest)
@ -47,7 +48,7 @@ class TestMsgResetDeviceT2(TrezorTest):
# Generate mnemonic locally # Generate mnemonic locally
entropy = generate_entropy(strength, internal_entropy, external_entropy) entropy = generate_entropy(strength, internal_entropy, external_entropy)
expected_mnemonic = Mnemonic('english').to_mnemonic(entropy) expected_mnemonic = Mnemonic("english").to_mnemonic(entropy)
# Safety warning # Safety warning
assert isinstance(ret, proto.ButtonRequest) assert isinstance(ret, proto.ButtonRequest)
@ -69,7 +70,7 @@ class TestMsgResetDeviceT2(TrezorTest):
words.extend(self.client.debug.read_reset_word().split()) words.extend(self.client.debug.read_reset_word().split())
# Compare that device generated proper mnemonic for given entropies # Compare that device generated proper mnemonic for given entropies
assert ' '.join(words) == expected_mnemonic assert " ".join(words) == expected_mnemonic
# Confirm the mnemonic # Confirm the mnemonic
self.client.debug.press_yes() self.client.debug.press_yes()
@ -99,24 +100,26 @@ class TestMsgResetDeviceT2(TrezorTest):
def test_reset_device_pin(self): def test_reset_device_pin(self):
# PIN, passphrase, display random # PIN, passphrase, display random
external_entropy = b'zlutoucky kun upel divoke ody' * 2 external_entropy = b"zlutoucky kun upel divoke ody" * 2
strength = 128 strength = 128
ret = self.client.call_raw(proto.ResetDevice( ret = self.client.call_raw(
display_random=True, proto.ResetDevice(
strength=strength, display_random=True,
passphrase_protection=True, strength=strength,
pin_protection=True, passphrase_protection=True,
label='test' pin_protection=True,
)) label="test",
)
)
# Enter PIN for first time # Enter PIN for first time
assert isinstance(ret, proto.ButtonRequest) assert isinstance(ret, proto.ButtonRequest)
self.client.debug.input('654') self.client.debug.input("654")
ret = self.client.call_raw(proto.ButtonAck()) ret = self.client.call_raw(proto.ButtonAck())
# Enter PIN for second time # Enter PIN for second time
assert isinstance(ret, proto.ButtonRequest) assert isinstance(ret, proto.ButtonRequest)
self.client.debug.input('654') self.client.debug.input("654")
ret = self.client.call_raw(proto.ButtonAck()) ret = self.client.call_raw(proto.ButtonAck())
# Confirm entropy # Confirm entropy
@ -131,7 +134,7 @@ class TestMsgResetDeviceT2(TrezorTest):
# Generate mnemonic locally # Generate mnemonic locally
entropy = generate_entropy(strength, internal_entropy, external_entropy) entropy = generate_entropy(strength, internal_entropy, external_entropy)
expected_mnemonic = Mnemonic('english').to_mnemonic(entropy) expected_mnemonic = Mnemonic("english").to_mnemonic(entropy)
# Safety warning # Safety warning
assert isinstance(ret, proto.ButtonRequest) assert isinstance(ret, proto.ButtonRequest)
@ -153,7 +156,7 @@ class TestMsgResetDeviceT2(TrezorTest):
words.extend(self.client.debug.read_reset_word().split()) words.extend(self.client.debug.read_reset_word().split())
# Compare that device generated proper mnemonic for given entropies # Compare that device generated proper mnemonic for given entropies
assert ' '.join(words) == expected_mnemonic assert " ".join(words) == expected_mnemonic
# Confirm the mnemonic # Confirm the mnemonic
self.client.debug.press_yes() self.client.debug.press_yes()
@ -183,20 +186,18 @@ class TestMsgResetDeviceT2(TrezorTest):
def test_failed_pin(self): def test_failed_pin(self):
# external_entropy = b'zlutoucky kun upel divoke ody' * 2 # external_entropy = b'zlutoucky kun upel divoke ody' * 2
strength = 128 strength = 128
ret = self.client.call_raw(proto.ResetDevice( ret = self.client.call_raw(
strength=strength, proto.ResetDevice(strength=strength, pin_protection=True, label="test")
pin_protection=True, )
label='test'
))
# Enter PIN for first time # Enter PIN for first time
assert isinstance(ret, proto.ButtonRequest) assert isinstance(ret, proto.ButtonRequest)
self.client.debug.input('654') self.client.debug.input("654")
ret = self.client.call_raw(proto.ButtonAck()) ret = self.client.call_raw(proto.ButtonAck())
# Enter PIN for second time # Enter PIN for second time
assert isinstance(ret, proto.ButtonRequest) assert isinstance(ret, proto.ButtonRequest)
self.client.debug.input('456') self.client.debug.input("456")
ret = self.client.call_raw(proto.ButtonAck()) ret = self.client.call_raw(proto.ButtonAck())
assert isinstance(ret, proto.ButtonRequest) assert isinstance(ret, proto.ButtonRequest)
@ -204,4 +205,4 @@ class TestMsgResetDeviceT2(TrezorTest):
def test_already_initialized(self): def test_already_initialized(self):
self.setup_mnemonic_nopin_nopassphrase() self.setup_mnemonic_nopin_nopassphrase()
with pytest.raises(Exception): with pytest.raises(Exception):
device.reset(self.client, False, 128, True, True, 'label', 'english') device.reset(self.client, False, 128, True, True, "label", "english")

View File

@ -16,39 +16,40 @@
import pytest import pytest
from .common import TrezorTest from trezorlib import debuglink
from .conftest import TREZOR_VERSION
from trezorlib.ripple import get_address from trezorlib.ripple import get_address
from trezorlib.tools import parse_path from trezorlib.tools import parse_path
from trezorlib import debuglink
from .common import TrezorTest
from .conftest import TREZOR_VERSION
@pytest.mark.ripple @pytest.mark.ripple
@pytest.mark.skip_t1 # T1 support is not planned @pytest.mark.skip_t1 # T1 support is not planned
@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 TestMsgRippleGetAddress(TrezorTest): class TestMsgRippleGetAddress(TrezorTest):
def test_ripple_get_address(self): def test_ripple_get_address(self):
# data from https://iancoleman.io/bip39/#english # data from https://iancoleman.io/bip39/#english
self.setup_mnemonic_allallall() self.setup_mnemonic_allallall()
address = get_address(self.client, parse_path("m/44'/144'/0'/0/0")) address = get_address(self.client, parse_path("m/44'/144'/0'/0/0"))
assert address == 'rNaqKtKrMSwpwZSzRckPf7S96DkimjkF4H' assert address == "rNaqKtKrMSwpwZSzRckPf7S96DkimjkF4H"
address = get_address(self.client, parse_path("m/44'/144'/0'/0/1")) address = get_address(self.client, parse_path("m/44'/144'/0'/0/1"))
assert address == 'rBKz5MC2iXdoS3XgnNSYmF69K1Yo4NS3Ws' assert address == "rBKz5MC2iXdoS3XgnNSYmF69K1Yo4NS3Ws"
address = get_address(self.client, parse_path("m/44'/144'/1'/0/0")) address = get_address(self.client, parse_path("m/44'/144'/1'/0/0"))
assert address == 'rJX2KwzaLJDyFhhtXKi3htaLfaUH2tptEX' assert address == "rJX2KwzaLJDyFhhtXKi3htaLfaUH2tptEX"
def test_ripple_get_address_other(self): def test_ripple_get_address_other(self):
# data from https://github.com/you21979/node-ripple-bip32/blob/master/test/test.js # data from https://github.com/you21979/node-ripple-bip32/blob/master/test/test.js
debuglink.load_device_by_mnemonic( debuglink.load_device_by_mnemonic(
self.client, self.client,
mnemonic='armed bundle pudding lazy strategy impulse where identify submit weekend physical antenna flight social acoustic absurd whip snack decide blur unfold fiction pumpkin athlete', mnemonic="armed bundle pudding lazy strategy impulse where identify submit weekend physical antenna flight social acoustic absurd whip snack decide blur unfold fiction pumpkin athlete",
pin='', pin="",
passphrase_protection=False, passphrase_protection=False,
label='test', label="test",
language='english') language="english",
)
address = get_address(self.client, parse_path("m/44'/144'/0'/0/0")) address = get_address(self.client, parse_path("m/44'/144'/0'/0/0"))
assert address == 'r4ocGE47gm4G4LkA9mriVHQqzpMLBTgnTY' assert address == "r4ocGE47gm4G4LkA9mriVHQqzpMLBTgnTY"
address = get_address(self.client, parse_path("m/44'/144'/0'/0/1")) address = get_address(self.client, parse_path("m/44'/144'/0'/0/1"))
assert address == 'rUt9ULSrUvfCmke8HTFU1szbmFpWzVbBXW' assert address == "rUt9ULSrUvfCmke8HTFU1szbmFpWzVbBXW"

View File

@ -14,72 +14,94 @@
# You should have received a copy of the License along with this library. # You should have received a copy of the License along with this library.
# If not, see <https://www.gnu.org/licenses/lgpl-3.0.html>. # If not, see <https://www.gnu.org/licenses/lgpl-3.0.html>.
from binascii import unhexlify
import pytest import pytest
from trezorlib import messages, ripple
from trezorlib.tools import CallException, parse_path
from .common import TrezorTest from .common import TrezorTest
from .conftest import TREZOR_VERSION from .conftest import TREZOR_VERSION
from binascii import unhexlify
from trezorlib import messages
from trezorlib import ripple
from trezorlib.tools import parse_path, CallException
@pytest.mark.ripple @pytest.mark.ripple
@pytest.mark.skip_t1 # T1 support is not planned @pytest.mark.skip_t1 # T1 support is not planned
@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 TestMsgRippleSignTx(TrezorTest): class TestMsgRippleSignTx(TrezorTest):
def test_ripple_sign_simple_tx(self): def test_ripple_sign_simple_tx(self):
self.setup_mnemonic_allallall() self.setup_mnemonic_allallall()
msg = ripple.create_sign_tx_msg({ msg = ripple.create_sign_tx_msg(
"TransactionType": "Payment", {
"Destination": "rBKz5MC2iXdoS3XgnNSYmF69K1Yo4NS3Ws", "TransactionType": "Payment",
"Amount": 100000000, "Destination": "rBKz5MC2iXdoS3XgnNSYmF69K1Yo4NS3Ws",
"Flags": 0x80000000, "Amount": 100000000,
"Fee": 100000, "Flags": 0x80000000,
"Sequence": 25, "Fee": 100000,
}) "Sequence": 25,
}
)
resp = ripple.sign_tx(self.client, parse_path("m/44'/144'/0'/0/0"), msg) resp = ripple.sign_tx(self.client, parse_path("m/44'/144'/0'/0/0"), msg)
assert resp.signature == unhexlify('3045022100e243ef623675eeeb95965c35c3e06d63a9fc68bb37e17dc87af9c0af83ec057e02206ca8aa5eaab8396397aef6d38d25710441faf7c79d292ee1d627df15ad9346c0') assert resp.signature == unhexlify(
assert resp.serialized_tx == unhexlify('12000022800000002400000019614000000005f5e1006840000000000186a0732102131facd1eab748d6cddc492f54b04e8c35658894f4add2232ebc5afe7521dbe474473045022100e243ef623675eeeb95965c35c3e06d63a9fc68bb37e17dc87af9c0af83ec057e02206ca8aa5eaab8396397aef6d38d25710441faf7c79d292ee1d627df15ad9346c081148fb40e1ffa5d557ce9851a535af94965e0dd098883147148ebebf7304ccdf1676fefcf9734cf1e780826') "3045022100e243ef623675eeeb95965c35c3e06d63a9fc68bb37e17dc87af9c0af83ec057e02206ca8aa5eaab8396397aef6d38d25710441faf7c79d292ee1d627df15ad9346c0"
)
assert resp.serialized_tx == unhexlify(
"12000022800000002400000019614000000005f5e1006840000000000186a0732102131facd1eab748d6cddc492f54b04e8c35658894f4add2232ebc5afe7521dbe474473045022100e243ef623675eeeb95965c35c3e06d63a9fc68bb37e17dc87af9c0af83ec057e02206ca8aa5eaab8396397aef6d38d25710441faf7c79d292ee1d627df15ad9346c081148fb40e1ffa5d557ce9851a535af94965e0dd098883147148ebebf7304ccdf1676fefcf9734cf1e780826"
)
msg = ripple.create_sign_tx_msg({ msg = ripple.create_sign_tx_msg(
"TransactionType": "Payment", {
"Destination": "rNaqKtKrMSwpwZSzRckPf7S96DkimjkF4H", "TransactionType": "Payment",
"Amount": 1, "Destination": "rNaqKtKrMSwpwZSzRckPf7S96DkimjkF4H",
"Fee": 10, "Amount": 1,
"Sequence": 1, "Fee": 10,
}) "Sequence": 1,
}
)
resp = ripple.sign_tx(self.client, parse_path("m/44'/144'/0'/0/2"), msg) resp = ripple.sign_tx(self.client, parse_path("m/44'/144'/0'/0/2"), msg)
assert resp.signature == unhexlify('3044022069900e6e578997fad5189981b74b16badc7ba8b9f1052694033fa2779113ddc002206c8006ada310edf099fb22c0c12073550c8fc73247b236a974c5f1144831dd5f') assert resp.signature == unhexlify(
assert resp.serialized_tx == unhexlify('1200002280000000240000000161400000000000000168400000000000000a732103dbed1e77cb91a005e2ec71afbccce5444c9be58276665a3859040f692de8fed274463044022069900e6e578997fad5189981b74b16badc7ba8b9f1052694033fa2779113ddc002206c8006ada310edf099fb22c0c12073550c8fc73247b236a974c5f1144831dd5f8114bdf86f3ae715ba346b7772ea0e133f48828b766483148fb40e1ffa5d557ce9851a535af94965e0dd0988') "3044022069900e6e578997fad5189981b74b16badc7ba8b9f1052694033fa2779113ddc002206c8006ada310edf099fb22c0c12073550c8fc73247b236a974c5f1144831dd5f"
)
assert resp.serialized_tx == unhexlify(
"1200002280000000240000000161400000000000000168400000000000000a732103dbed1e77cb91a005e2ec71afbccce5444c9be58276665a3859040f692de8fed274463044022069900e6e578997fad5189981b74b16badc7ba8b9f1052694033fa2779113ddc002206c8006ada310edf099fb22c0c12073550c8fc73247b236a974c5f1144831dd5f8114bdf86f3ae715ba346b7772ea0e133f48828b766483148fb40e1ffa5d557ce9851a535af94965e0dd0988"
)
msg = ripple.create_sign_tx_msg({ msg = ripple.create_sign_tx_msg(
"TransactionType": "Payment", {
"Destination": "rNaqKtKrMSwpwZSzRckPf7S96DkimjkF4H", "TransactionType": "Payment",
"Amount": 100000009, "Destination": "rNaqKtKrMSwpwZSzRckPf7S96DkimjkF4H",
"Flags": 0, "Amount": 100000009,
"Fee": 100, "Flags": 0,
"Sequence": 100, "Fee": 100,
"LastLedgerSequence": 333111, "Sequence": 100,
}) "LastLedgerSequence": 333111,
}
)
resp = ripple.sign_tx(self.client, parse_path("m/44'/144'/0'/0/2"), msg) resp = ripple.sign_tx(self.client, parse_path("m/44'/144'/0'/0/2"), msg)
assert resp.signature == unhexlify('30440220025a9cc2809527799e6ea5eb029488dc46c6632a8ca1ed7d3ca2d9211e80403a02202cfe8604e6c6d1d3c64246626cc1a1a9bd8a2163b969e561c6adda5dca8fc2a5') assert resp.signature == unhexlify(
assert resp.serialized_tx == unhexlify('12000022800000002400000064201b00051537614000000005f5e109684000000000000064732103dbed1e77cb91a005e2ec71afbccce5444c9be58276665a3859040f692de8fed2744630440220025a9cc2809527799e6ea5eb029488dc46c6632a8ca1ed7d3ca2d9211e80403a02202cfe8604e6c6d1d3c64246626cc1a1a9bd8a2163b969e561c6adda5dca8fc2a58114bdf86f3ae715ba346b7772ea0e133f48828b766483148fb40e1ffa5d557ce9851a535af94965e0dd0988') "30440220025a9cc2809527799e6ea5eb029488dc46c6632a8ca1ed7d3ca2d9211e80403a02202cfe8604e6c6d1d3c64246626cc1a1a9bd8a2163b969e561c6adda5dca8fc2a5"
)
assert resp.serialized_tx == unhexlify(
"12000022800000002400000064201b00051537614000000005f5e109684000000000000064732103dbed1e77cb91a005e2ec71afbccce5444c9be58276665a3859040f692de8fed2744630440220025a9cc2809527799e6ea5eb029488dc46c6632a8ca1ed7d3ca2d9211e80403a02202cfe8604e6c6d1d3c64246626cc1a1a9bd8a2163b969e561c6adda5dca8fc2a58114bdf86f3ae715ba346b7772ea0e133f48828b766483148fb40e1ffa5d557ce9851a535af94965e0dd0988"
)
def test_ripple_sign_invalid_fee(self): def test_ripple_sign_invalid_fee(self):
self.setup_mnemonic_allallall() self.setup_mnemonic_allallall()
msg = ripple.create_sign_tx_msg({ msg = ripple.create_sign_tx_msg(
"TransactionType": "Payment", {
"Destination": "rNaqKtKrMSwpwZSzRckPf7S96DkimjkF4H", "TransactionType": "Payment",
"Amount": 1, "Destination": "rNaqKtKrMSwpwZSzRckPf7S96DkimjkF4H",
"Flags": 1, "Amount": 1,
"Fee": 1, "Flags": 1,
"Sequence": 1, "Fee": 1,
}) "Sequence": 1,
}
)
with pytest.raises(CallException) as exc: with pytest.raises(CallException) as exc:
ripple.sign_tx(self.client, parse_path("m/44'/144'/0'/0/2"), msg) ripple.sign_tx(self.client, parse_path("m/44'/144'/0'/0/2"), msg)
assert exc.value.args[0] == messages.FailureType.ProcessError assert exc.value.args[0] == messages.FailureType.ProcessError
assert exc.value.args[1].endswith('Fee must be in the range of 10 to 10,000 drops') assert exc.value.args[1].endswith(
"Fee must be in the range of 10 to 10,000 drops"
)

View File

@ -17,75 +17,122 @@
import struct import struct
from binascii import hexlify, unhexlify from binascii import hexlify, unhexlify
from .common import TrezorTest from trezorlib import messages as proto, misc
from trezorlib import messages as proto
from trezorlib import misc
from trezorlib.tools import H_ from trezorlib.tools import H_
from .common import TrezorTest
def check_path(identity): def check_path(identity):
from hashlib import sha256 from hashlib import sha256
m = sha256() m = sha256()
m.update(struct.pack("<I", identity.index)) m.update(struct.pack("<I", identity.index))
uri = '' uri = ""
if identity.proto: if identity.proto:
uri += identity.proto + '://' uri += identity.proto + "://"
if identity.user: if identity.user:
uri += identity.user + '@' uri += identity.user + "@"
if identity.host: if identity.host:
uri += identity.host uri += identity.host
if identity.port: if identity.port:
uri += ':' + identity.port uri += ":" + identity.port
if identity.path: if identity.path:
uri += identity.path uri += identity.path
m.update(uri) m.update(uri)
print('hash:', m.hexdigest()) print("hash:", m.hexdigest())
(a, b, c, d, _, _, _, _) = struct.unpack('<8I', m.digest()) (a, b, c, d, _, _, _, _) = struct.unpack("<8I", m.digest())
address_n = [H_(13), H_(a), H_(b), H_(c), H_(d)] address_n = [H_(13), H_(a), H_(b), H_(c), H_(d)]
print('path:', 'm/' + '/'.join([str(x) for x in address_n])) print("path:", "m/" + "/".join([str(x) for x in address_n]))
class TestMsgSignidentity(TrezorTest): class TestMsgSignidentity(TrezorTest):
def test_sign(self): def test_sign(self):
self.setup_mnemonic_nopin_nopassphrase() self.setup_mnemonic_nopin_nopassphrase()
hidden = unhexlify('cd8552569d6e4509266ef137584d1e62c7579b5b8ed69bbafa4b864c6521e7c2') hidden = unhexlify(
visual = '2015-03-23 17:39:22' "cd8552569d6e4509266ef137584d1e62c7579b5b8ed69bbafa4b864c6521e7c2"
)
visual = "2015-03-23 17:39:22"
# URI : https://satoshi@bitcoin.org/login # URI : https://satoshi@bitcoin.org/login
# hash : d0e2389d4c8394a9f3e32de01104bf6e8db2d9e2bb0905d60fffa5a18fd696db # hash : d0e2389d4c8394a9f3e32de01104bf6e8db2d9e2bb0905d60fffa5a18fd696db
# path : m/2147483661/2637750992/2845082444/3761103859/4005495825 # path : m/2147483661/2637750992/2845082444/3761103859/4005495825
identity = proto.IdentityType(proto='https', user='satoshi', host='bitcoin.org', port='', path='/login', index=0) identity = proto.IdentityType(
proto="https",
user="satoshi",
host="bitcoin.org",
port="",
path="/login",
index=0,
)
sig = misc.sign_identity(self.client, identity, hidden, visual) sig = misc.sign_identity(self.client, identity, hidden, visual)
assert sig.address == '17F17smBTX9VTZA9Mj8LM5QGYNZnmziCjL' assert sig.address == "17F17smBTX9VTZA9Mj8LM5QGYNZnmziCjL"
assert hexlify(sig.public_key) == b'023a472219ad3327b07c18273717bb3a40b39b743756bf287fbd5fa9d263237f45' assert (
assert hexlify(sig.signature) == b'20f2d1a42d08c3a362be49275c3ffeeaa415fc040971985548b9f910812237bb41770bf2c8d488428799fbb7e52c11f1a3404011375e4080e077e0e42ab7a5ba02' hexlify(sig.public_key)
== b"023a472219ad3327b07c18273717bb3a40b39b743756bf287fbd5fa9d263237f45"
)
assert (
hexlify(sig.signature)
== b"20f2d1a42d08c3a362be49275c3ffeeaa415fc040971985548b9f910812237bb41770bf2c8d488428799fbb7e52c11f1a3404011375e4080e077e0e42ab7a5ba02"
)
# URI : ftp://satoshi@bitcoin.org:2323/pub # URI : ftp://satoshi@bitcoin.org:2323/pub
# hash : 79a6b53831c6ff224fb283587adc4ebae8fb0d734734a46c876838f52dff53f3 # hash : 79a6b53831c6ff224fb283587adc4ebae8fb0d734734a46c876838f52dff53f3
# path : m/2147483661/3098912377/2734671409/3632509519/3125730426 # path : m/2147483661/3098912377/2734671409/3632509519/3125730426
identity = proto.IdentityType(proto='ftp', user='satoshi', host='bitcoin.org', port='2323', path='/pub', index=3) identity = proto.IdentityType(
proto="ftp",
user="satoshi",
host="bitcoin.org",
port="2323",
path="/pub",
index=3,
)
sig = misc.sign_identity(self.client, identity, hidden, visual) sig = misc.sign_identity(self.client, identity, hidden, visual)
assert sig.address == '1KAr6r5qF2kADL8bAaRQBjGKYEGxn9WrbS' assert sig.address == "1KAr6r5qF2kADL8bAaRQBjGKYEGxn9WrbS"
assert hexlify(sig.public_key) == b'0266cf12d2ba381c5fd797da0d64f59c07a6f1b034ad276cca6bf2729e92b20d9c' assert (
assert hexlify(sig.signature) == b'20bbd12dc657d534fc0f7e40186e22c447e0866a016f654f380adffa9a84e9faf412a1bb0ae908296537838cf91145e77da08681c63d07b7dca40728b9e6cb17cf' hexlify(sig.public_key)
== b"0266cf12d2ba381c5fd797da0d64f59c07a6f1b034ad276cca6bf2729e92b20d9c"
)
assert (
hexlify(sig.signature)
== b"20bbd12dc657d534fc0f7e40186e22c447e0866a016f654f380adffa9a84e9faf412a1bb0ae908296537838cf91145e77da08681c63d07b7dca40728b9e6cb17cf"
)
# URI : ssh://satoshi@bitcoin.org # URI : ssh://satoshi@bitcoin.org
# hash : 5fa612f558a1a3b1fb7f010b2ea0a25cb02520a0ffa202ce74a92fc6145da5f3 # hash : 5fa612f558a1a3b1fb7f010b2ea0a25cb02520a0ffa202ce74a92fc6145da5f3
# path : m/2147483661/4111640159/2980290904/2332131323/3701645358 # path : m/2147483661/4111640159/2980290904/2332131323/3701645358
identity = proto.IdentityType(proto='ssh', user='satoshi', host='bitcoin.org', port='', path='', index=47) identity = proto.IdentityType(
sig = misc.sign_identity(self.client, identity, hidden, visual, ecdsa_curve_name='nist256p1') proto="ssh", user="satoshi", host="bitcoin.org", port="", path="", index=47
)
sig = misc.sign_identity(
self.client, identity, hidden, visual, ecdsa_curve_name="nist256p1"
)
assert sig.address is None assert sig.address is None
assert hexlify(sig.public_key) == b'0373f21a3da3d0e96fc2189f81dd826658c3d76b2d55bd1da349bc6c3573b13ae4' assert (
assert hexlify(sig.signature) == b'005122cebabb852cdd32103b602662afa88e54c0c0c1b38d7099c64dcd49efe908288114e66ed2d8c82f23a70b769a4db723173ec53840c08aafb840d3f09a18d3' hexlify(sig.public_key)
== b"0373f21a3da3d0e96fc2189f81dd826658c3d76b2d55bd1da349bc6c3573b13ae4"
)
assert (
hexlify(sig.signature)
== b"005122cebabb852cdd32103b602662afa88e54c0c0c1b38d7099c64dcd49efe908288114e66ed2d8c82f23a70b769a4db723173ec53840c08aafb840d3f09a18d3"
)
# URI : ssh://satoshi@bitcoin.org # URI : ssh://satoshi@bitcoin.org
# hash : 5fa612f558a1a3b1fb7f010b2ea0a25cb02520a0ffa202ce74a92fc6145da5f3 # hash : 5fa612f558a1a3b1fb7f010b2ea0a25cb02520a0ffa202ce74a92fc6145da5f3
# path : m/2147483661/4111640159/2980290904/2332131323/3701645358 # path : m/2147483661/4111640159/2980290904/2332131323/3701645358
identity = proto.IdentityType(proto='ssh', user='satoshi', host='bitcoin.org', port='', path='', index=47) identity = proto.IdentityType(
sig = misc.sign_identity(self.client, identity, hidden, visual, ecdsa_curve_name='ed25519') proto="ssh", user="satoshi", host="bitcoin.org", port="", path="", index=47
)
sig = misc.sign_identity(
self.client, identity, hidden, visual, ecdsa_curve_name="ed25519"
)
assert sig.address is None assert sig.address is None
assert hexlify(sig.public_key) == b'000fac2a491e0f5b871dc48288a4cae551bac5cb0ed19df0764d6e721ec5fade18' assert (
assert hexlify(sig.signature) == b'00f05e5085e666429de397c70a081932654369619c0bd2a6579ea6c1ef2af112ef79998d6c862a16b932d44b1ac1b83c8cbcd0fbda228274fde9e0d0ca6e9cb709' hexlify(sig.public_key)
== b"000fac2a491e0f5b871dc48288a4cae551bac5cb0ed19df0764d6e721ec5fade18"
)
assert (
hexlify(sig.signature)
== b"00f05e5085e666429de397c70a081932654369619c0bd2a6579ea6c1ef2af112ef79998d6c862a16b932d44b1ac1b83c8cbcd0fbda228274fde9e0d0ca6e9cb709"
)

View File

@ -16,46 +16,70 @@
from binascii import hexlify from binascii import hexlify
from .common import TrezorTest
from trezorlib import btc from trezorlib import btc
from .common import TrezorTest
class TestMsgSignmessage(TrezorTest): class TestMsgSignmessage(TrezorTest):
def test_sign(self): def test_sign(self):
self.setup_mnemonic_nopin_nopassphrase() self.setup_mnemonic_nopin_nopassphrase()
sig = btc.sign_message(self.client, 'Bitcoin', [0], "This is an example of a signed message.") sig = btc.sign_message(
assert sig.address == '14LmW5k4ssUrtbAB4255zdqv3b4w1TuX9e' self.client, "Bitcoin", [0], "This is an example of a signed message."
assert hexlify(sig.signature) == b'209e23edf0e4e47ff1dec27f32cd78c50e74ef018ee8a6adf35ae17c7a9b0dd96f48b493fd7dbab03efb6f439c6383c9523b3bbc5f1a7d158a6af90ab154e9be80' )
assert sig.address == "14LmW5k4ssUrtbAB4255zdqv3b4w1TuX9e"
assert (
hexlify(sig.signature)
== b"209e23edf0e4e47ff1dec27f32cd78c50e74ef018ee8a6adf35ae17c7a9b0dd96f48b493fd7dbab03efb6f439c6383c9523b3bbc5f1a7d158a6af90ab154e9be80"
)
def test_sign_testnet(self): def test_sign_testnet(self):
self.setup_mnemonic_nopin_nopassphrase() self.setup_mnemonic_nopin_nopassphrase()
sig = btc.sign_message(self.client, 'Testnet', [0], "This is an example of a signed message.") sig = btc.sign_message(
assert sig.address == 'mirio8q3gtv7fhdnmb3TpZ4EuafdzSs7zL' self.client, "Testnet", [0], "This is an example of a signed message."
assert hexlify(sig.signature) == b'209e23edf0e4e47ff1dec27f32cd78c50e74ef018ee8a6adf35ae17c7a9b0dd96f48b493fd7dbab03efb6f439c6383c9523b3bbc5f1a7d158a6af90ab154e9be80' )
assert sig.address == "mirio8q3gtv7fhdnmb3TpZ4EuafdzSs7zL"
assert (
hexlify(sig.signature)
== b"209e23edf0e4e47ff1dec27f32cd78c50e74ef018ee8a6adf35ae17c7a9b0dd96f48b493fd7dbab03efb6f439c6383c9523b3bbc5f1a7d158a6af90ab154e9be80"
)
def test_sign_bch(self): def test_sign_bch(self):
self.setup_mnemonic_nopin_nopassphrase() self.setup_mnemonic_nopin_nopassphrase()
sig = btc.sign_message(self.client, 'Bcash', [0], "This is an example of a signed message.") sig = btc.sign_message(
assert sig.address == 'bitcoincash:qqj22md58nm09vpwsw82fyletkxkq36zxyxh322pru' self.client, "Bcash", [0], "This is an example of a signed message."
assert hexlify(sig.signature) == b'209e23edf0e4e47ff1dec27f32cd78c50e74ef018ee8a6adf35ae17c7a9b0dd96f48b493fd7dbab03efb6f439c6383c9523b3bbc5f1a7d158a6af90ab154e9be80' )
assert sig.address == "bitcoincash:qqj22md58nm09vpwsw82fyletkxkq36zxyxh322pru"
assert (
hexlify(sig.signature)
== b"209e23edf0e4e47ff1dec27f32cd78c50e74ef018ee8a6adf35ae17c7a9b0dd96f48b493fd7dbab03efb6f439c6383c9523b3bbc5f1a7d158a6af90ab154e9be80"
)
def test_sign_long(self): def test_sign_long(self):
self.setup_mnemonic_nopin_nopassphrase() self.setup_mnemonic_nopin_nopassphrase()
sig = btc.sign_message(self.client, 'Bitcoin', [0], "VeryLongMessage!" * 64) sig = btc.sign_message(self.client, "Bitcoin", [0], "VeryLongMessage!" * 64)
assert sig.address == '14LmW5k4ssUrtbAB4255zdqv3b4w1TuX9e' assert sig.address == "14LmW5k4ssUrtbAB4255zdqv3b4w1TuX9e"
assert hexlify(sig.signature) == b'205ff795c29aef7538f8b3bdb2e8add0d0722ad630a140b6aefd504a5a895cbd867cbb00981afc50edd0398211e8d7c304bb8efa461181bc0afa67ea4a720a89ed' assert (
hexlify(sig.signature)
== b"205ff795c29aef7538f8b3bdb2e8add0d0722ad630a140b6aefd504a5a895cbd867cbb00981afc50edd0398211e8d7c304bb8efa461181bc0afa67ea4a720a89ed"
)
def test_sign_utf(self): def test_sign_utf(self):
self.setup_mnemonic_nopin_nopassphrase() self.setup_mnemonic_nopin_nopassphrase()
words_nfkd = u'Pr\u030ci\u0301s\u030cerne\u030c z\u030clut\u030couc\u030cky\u0301 ku\u030an\u030c u\u0301pe\u030cl d\u030ca\u0301belske\u0301 o\u0301dy za\u0301ker\u030cny\u0301 uc\u030cen\u030c be\u030cz\u030ci\u0301 pode\u0301l zo\u0301ny u\u0301lu\u030a' words_nfkd = u"Pr\u030ci\u0301s\u030cerne\u030c z\u030clut\u030couc\u030cky\u0301 ku\u030an\u030c u\u0301pe\u030cl d\u030ca\u0301belske\u0301 o\u0301dy za\u0301ker\u030cny\u0301 uc\u030cen\u030c be\u030cz\u030ci\u0301 pode\u0301l zo\u0301ny u\u0301lu\u030a"
words_nfc = u'P\u0159\xed\u0161ern\u011b \u017elu\u0165ou\u010dk\xfd k\u016f\u0148 \xfap\u011bl \u010f\xe1belsk\xe9 \xf3dy z\xe1ke\u0159n\xfd u\u010de\u0148 b\u011b\u017e\xed pod\xe9l z\xf3ny \xfal\u016f' words_nfc = u"P\u0159\xed\u0161ern\u011b \u017elu\u0165ou\u010dk\xfd k\u016f\u0148 \xfap\u011bl \u010f\xe1belsk\xe9 \xf3dy z\xe1ke\u0159n\xfd u\u010de\u0148 b\u011b\u017e\xed pod\xe9l z\xf3ny \xfal\u016f"
sig_nfkd = btc.sign_message(self.client, 'Bitcoin', [0], words_nfkd) sig_nfkd = btc.sign_message(self.client, "Bitcoin", [0], words_nfkd)
assert sig_nfkd.address == '14LmW5k4ssUrtbAB4255zdqv3b4w1TuX9e' assert sig_nfkd.address == "14LmW5k4ssUrtbAB4255zdqv3b4w1TuX9e"
assert hexlify(sig_nfkd.signature) == b'20d0ec02ed8da8df23e7fe9e680e7867cc290312fe1c970749d8306ddad1a1eda41c6a771b13d495dd225b13b0a9d0f915a984ee3d0703f92287bf8009fbb9f7d6' assert (
hexlify(sig_nfkd.signature)
== b"20d0ec02ed8da8df23e7fe9e680e7867cc290312fe1c970749d8306ddad1a1eda41c6a771b13d495dd225b13b0a9d0f915a984ee3d0703f92287bf8009fbb9f7d6"
)
sig_nfc = btc.sign_message(self.client, 'Bitcoin', [0], words_nfc) sig_nfc = btc.sign_message(self.client, "Bitcoin", [0], words_nfc)
assert sig_nfc.address == '14LmW5k4ssUrtbAB4255zdqv3b4w1TuX9e' assert sig_nfc.address == "14LmW5k4ssUrtbAB4255zdqv3b4w1TuX9e"
assert hexlify(sig_nfc.signature) == b'20d0ec02ed8da8df23e7fe9e680e7867cc290312fe1c970749d8306ddad1a1eda41c6a771b13d495dd225b13b0a9d0f915a984ee3d0703f92287bf8009fbb9f7d6' assert (
hexlify(sig_nfc.signature)
== b"20d0ec02ed8da8df23e7fe9e680e7867cc290312fe1c970749d8306ddad1a1eda41c6a771b13d495dd225b13b0a9d0f915a984ee3d0703f92287bf8009fbb9f7d6"
)

View File

@ -16,41 +16,85 @@
from binascii import hexlify from binascii import hexlify
from trezorlib import btc, messages as proto
from .common import TrezorTest from .common import TrezorTest
from trezorlib import messages as proto
from trezorlib import btc
class TestMsgSignmessageSegwit(TrezorTest): class TestMsgSignmessageSegwit(TrezorTest):
def test_sign(self): def test_sign(self):
self.setup_mnemonic_nopin_nopassphrase() self.setup_mnemonic_nopin_nopassphrase()
sig = btc.sign_message(self.client, 'Bitcoin', [0], "This is an example of a signed message.", script_type=proto.InputScriptType.SPENDP2SHWITNESS) sig = btc.sign_message(
assert sig.address == '3CwYaeWxhpXXiHue3ciQez1DLaTEAXcKa1' self.client,
assert hexlify(sig.signature) == b'249e23edf0e4e47ff1dec27f32cd78c50e74ef018ee8a6adf35ae17c7a9b0dd96f48b493fd7dbab03efb6f439c6383c9523b3bbc5f1a7d158a6af90ab154e9be80' "Bitcoin",
[0],
"This is an example of a signed message.",
script_type=proto.InputScriptType.SPENDP2SHWITNESS,
)
assert sig.address == "3CwYaeWxhpXXiHue3ciQez1DLaTEAXcKa1"
assert (
hexlify(sig.signature)
== b"249e23edf0e4e47ff1dec27f32cd78c50e74ef018ee8a6adf35ae17c7a9b0dd96f48b493fd7dbab03efb6f439c6383c9523b3bbc5f1a7d158a6af90ab154e9be80"
)
def test_sign_testnet(self): def test_sign_testnet(self):
self.setup_mnemonic_nopin_nopassphrase() self.setup_mnemonic_nopin_nopassphrase()
sig = btc.sign_message(self.client, 'Testnet', [0], "This is an example of a signed message.", script_type=proto.InputScriptType.SPENDP2SHWITNESS) sig = btc.sign_message(
assert sig.address == '2N4VkePSzKH2sv5YBikLHGvzUYvfPxV6zS9' self.client,
assert hexlify(sig.signature) == b'249e23edf0e4e47ff1dec27f32cd78c50e74ef018ee8a6adf35ae17c7a9b0dd96f48b493fd7dbab03efb6f439c6383c9523b3bbc5f1a7d158a6af90ab154e9be80' "Testnet",
[0],
"This is an example of a signed message.",
script_type=proto.InputScriptType.SPENDP2SHWITNESS,
)
assert sig.address == "2N4VkePSzKH2sv5YBikLHGvzUYvfPxV6zS9"
assert (
hexlify(sig.signature)
== b"249e23edf0e4e47ff1dec27f32cd78c50e74ef018ee8a6adf35ae17c7a9b0dd96f48b493fd7dbab03efb6f439c6383c9523b3bbc5f1a7d158a6af90ab154e9be80"
)
def test_sign_long(self): def test_sign_long(self):
self.setup_mnemonic_nopin_nopassphrase() self.setup_mnemonic_nopin_nopassphrase()
sig = btc.sign_message(self.client, 'Bitcoin', [0], "VeryLongMessage!" * 64, script_type=proto.InputScriptType.SPENDP2SHWITNESS) sig = btc.sign_message(
assert sig.address == '3CwYaeWxhpXXiHue3ciQez1DLaTEAXcKa1' self.client,
assert hexlify(sig.signature) == b'245ff795c29aef7538f8b3bdb2e8add0d0722ad630a140b6aefd504a5a895cbd867cbb00981afc50edd0398211e8d7c304bb8efa461181bc0afa67ea4a720a89ed' "Bitcoin",
[0],
"VeryLongMessage!" * 64,
script_type=proto.InputScriptType.SPENDP2SHWITNESS,
)
assert sig.address == "3CwYaeWxhpXXiHue3ciQez1DLaTEAXcKa1"
assert (
hexlify(sig.signature)
== b"245ff795c29aef7538f8b3bdb2e8add0d0722ad630a140b6aefd504a5a895cbd867cbb00981afc50edd0398211e8d7c304bb8efa461181bc0afa67ea4a720a89ed"
)
def test_sign_utf(self): def test_sign_utf(self):
self.setup_mnemonic_nopin_nopassphrase() self.setup_mnemonic_nopin_nopassphrase()
words_nfkd = u'Pr\u030ci\u0301s\u030cerne\u030c z\u030clut\u030couc\u030cky\u0301 ku\u030an\u030c u\u0301pe\u030cl d\u030ca\u0301belske\u0301 o\u0301dy za\u0301ker\u030cny\u0301 uc\u030cen\u030c be\u030cz\u030ci\u0301 pode\u0301l zo\u0301ny u\u0301lu\u030a' words_nfkd = u"Pr\u030ci\u0301s\u030cerne\u030c z\u030clut\u030couc\u030cky\u0301 ku\u030an\u030c u\u0301pe\u030cl d\u030ca\u0301belske\u0301 o\u0301dy za\u0301ker\u030cny\u0301 uc\u030cen\u030c be\u030cz\u030ci\u0301 pode\u0301l zo\u0301ny u\u0301lu\u030a"
words_nfc = u'P\u0159\xed\u0161ern\u011b \u017elu\u0165ou\u010dk\xfd k\u016f\u0148 \xfap\u011bl \u010f\xe1belsk\xe9 \xf3dy z\xe1ke\u0159n\xfd u\u010de\u0148 b\u011b\u017e\xed pod\xe9l z\xf3ny \xfal\u016f' words_nfc = u"P\u0159\xed\u0161ern\u011b \u017elu\u0165ou\u010dk\xfd k\u016f\u0148 \xfap\u011bl \u010f\xe1belsk\xe9 \xf3dy z\xe1ke\u0159n\xfd u\u010de\u0148 b\u011b\u017e\xed pod\xe9l z\xf3ny \xfal\u016f"
sig_nfkd = btc.sign_message(self.client, 'Bitcoin', [0], words_nfkd, script_type=proto.InputScriptType.SPENDP2SHWITNESS) sig_nfkd = btc.sign_message(
assert sig_nfkd.address == '3CwYaeWxhpXXiHue3ciQez1DLaTEAXcKa1' self.client,
assert hexlify(sig_nfkd.signature) == b'24d0ec02ed8da8df23e7fe9e680e7867cc290312fe1c970749d8306ddad1a1eda41c6a771b13d495dd225b13b0a9d0f915a984ee3d0703f92287bf8009fbb9f7d6' "Bitcoin",
[0],
words_nfkd,
script_type=proto.InputScriptType.SPENDP2SHWITNESS,
)
assert sig_nfkd.address == "3CwYaeWxhpXXiHue3ciQez1DLaTEAXcKa1"
assert (
hexlify(sig_nfkd.signature)
== b"24d0ec02ed8da8df23e7fe9e680e7867cc290312fe1c970749d8306ddad1a1eda41c6a771b13d495dd225b13b0a9d0f915a984ee3d0703f92287bf8009fbb9f7d6"
)
sig_nfc = btc.sign_message(self.client, 'Bitcoin', [0], words_nfc, script_type=proto.InputScriptType.SPENDP2SHWITNESS) sig_nfc = btc.sign_message(
assert sig_nfc.address == '3CwYaeWxhpXXiHue3ciQez1DLaTEAXcKa1' self.client,
assert hexlify(sig_nfc.signature) == b'24d0ec02ed8da8df23e7fe9e680e7867cc290312fe1c970749d8306ddad1a1eda41c6a771b13d495dd225b13b0a9d0f915a984ee3d0703f92287bf8009fbb9f7d6' "Bitcoin",
[0],
words_nfc,
script_type=proto.InputScriptType.SPENDP2SHWITNESS,
)
assert sig_nfc.address == "3CwYaeWxhpXXiHue3ciQez1DLaTEAXcKa1"
assert (
hexlify(sig_nfc.signature)
== b"24d0ec02ed8da8df23e7fe9e680e7867cc290312fe1c970749d8306ddad1a1eda41c6a771b13d495dd225b13b0a9d0f915a984ee3d0703f92287bf8009fbb9f7d6"
)

View File

@ -16,41 +16,85 @@
from binascii import hexlify from binascii import hexlify
from trezorlib import btc, messages as proto
from .common import TrezorTest from .common import TrezorTest
from trezorlib import messages as proto
from trezorlib import btc
class TestMsgSignmessageSegwitNative(TrezorTest): class TestMsgSignmessageSegwitNative(TrezorTest):
def test_sign(self): def test_sign(self):
self.setup_mnemonic_nopin_nopassphrase() self.setup_mnemonic_nopin_nopassphrase()
sig = btc.sign_message(self.client, 'Bitcoin', [0], "This is an example of a signed message.", script_type=proto.InputScriptType.SPENDWITNESS) sig = btc.sign_message(
assert sig.address == 'bc1qyjjkmdpu7metqt5r36jf872a34syws33s82q2j' self.client,
assert hexlify(sig.signature) == b'289e23edf0e4e47ff1dec27f32cd78c50e74ef018ee8a6adf35ae17c7a9b0dd96f48b493fd7dbab03efb6f439c6383c9523b3bbc5f1a7d158a6af90ab154e9be80' "Bitcoin",
[0],
"This is an example of a signed message.",
script_type=proto.InputScriptType.SPENDWITNESS,
)
assert sig.address == "bc1qyjjkmdpu7metqt5r36jf872a34syws33s82q2j"
assert (
hexlify(sig.signature)
== b"289e23edf0e4e47ff1dec27f32cd78c50e74ef018ee8a6adf35ae17c7a9b0dd96f48b493fd7dbab03efb6f439c6383c9523b3bbc5f1a7d158a6af90ab154e9be80"
)
def test_sign_testnet(self): def test_sign_testnet(self):
self.setup_mnemonic_nopin_nopassphrase() self.setup_mnemonic_nopin_nopassphrase()
sig = btc.sign_message(self.client, 'Testnet', [0], "This is an example of a signed message.", script_type=proto.InputScriptType.SPENDWITNESS) sig = btc.sign_message(
assert sig.address == 'tb1qyjjkmdpu7metqt5r36jf872a34syws336p3n3p' self.client,
assert hexlify(sig.signature) == b'289e23edf0e4e47ff1dec27f32cd78c50e74ef018ee8a6adf35ae17c7a9b0dd96f48b493fd7dbab03efb6f439c6383c9523b3bbc5f1a7d158a6af90ab154e9be80' "Testnet",
[0],
"This is an example of a signed message.",
script_type=proto.InputScriptType.SPENDWITNESS,
)
assert sig.address == "tb1qyjjkmdpu7metqt5r36jf872a34syws336p3n3p"
assert (
hexlify(sig.signature)
== b"289e23edf0e4e47ff1dec27f32cd78c50e74ef018ee8a6adf35ae17c7a9b0dd96f48b493fd7dbab03efb6f439c6383c9523b3bbc5f1a7d158a6af90ab154e9be80"
)
def test_sign_long(self): def test_sign_long(self):
self.setup_mnemonic_nopin_nopassphrase() self.setup_mnemonic_nopin_nopassphrase()
sig = btc.sign_message(self.client, 'Bitcoin', [0], "VeryLongMessage!" * 64, script_type=proto.InputScriptType.SPENDWITNESS) sig = btc.sign_message(
assert sig.address == 'bc1qyjjkmdpu7metqt5r36jf872a34syws33s82q2j' self.client,
assert hexlify(sig.signature) == b'285ff795c29aef7538f8b3bdb2e8add0d0722ad630a140b6aefd504a5a895cbd867cbb00981afc50edd0398211e8d7c304bb8efa461181bc0afa67ea4a720a89ed' "Bitcoin",
[0],
"VeryLongMessage!" * 64,
script_type=proto.InputScriptType.SPENDWITNESS,
)
assert sig.address == "bc1qyjjkmdpu7metqt5r36jf872a34syws33s82q2j"
assert (
hexlify(sig.signature)
== b"285ff795c29aef7538f8b3bdb2e8add0d0722ad630a140b6aefd504a5a895cbd867cbb00981afc50edd0398211e8d7c304bb8efa461181bc0afa67ea4a720a89ed"
)
def test_sign_utf(self): def test_sign_utf(self):
self.setup_mnemonic_nopin_nopassphrase() self.setup_mnemonic_nopin_nopassphrase()
words_nfkd = u'Pr\u030ci\u0301s\u030cerne\u030c z\u030clut\u030couc\u030cky\u0301 ku\u030an\u030c u\u0301pe\u030cl d\u030ca\u0301belske\u0301 o\u0301dy za\u0301ker\u030cny\u0301 uc\u030cen\u030c be\u030cz\u030ci\u0301 pode\u0301l zo\u0301ny u\u0301lu\u030a' words_nfkd = u"Pr\u030ci\u0301s\u030cerne\u030c z\u030clut\u030couc\u030cky\u0301 ku\u030an\u030c u\u0301pe\u030cl d\u030ca\u0301belske\u0301 o\u0301dy za\u0301ker\u030cny\u0301 uc\u030cen\u030c be\u030cz\u030ci\u0301 pode\u0301l zo\u0301ny u\u0301lu\u030a"
words_nfc = u'P\u0159\xed\u0161ern\u011b \u017elu\u0165ou\u010dk\xfd k\u016f\u0148 \xfap\u011bl \u010f\xe1belsk\xe9 \xf3dy z\xe1ke\u0159n\xfd u\u010de\u0148 b\u011b\u017e\xed pod\xe9l z\xf3ny \xfal\u016f' words_nfc = u"P\u0159\xed\u0161ern\u011b \u017elu\u0165ou\u010dk\xfd k\u016f\u0148 \xfap\u011bl \u010f\xe1belsk\xe9 \xf3dy z\xe1ke\u0159n\xfd u\u010de\u0148 b\u011b\u017e\xed pod\xe9l z\xf3ny \xfal\u016f"
sig_nfkd = btc.sign_message(self.client, 'Bitcoin', [0], words_nfkd, script_type=proto.InputScriptType.SPENDWITNESS) sig_nfkd = btc.sign_message(
assert sig_nfkd.address == 'bc1qyjjkmdpu7metqt5r36jf872a34syws33s82q2j' self.client,
assert hexlify(sig_nfkd.signature) == b'28d0ec02ed8da8df23e7fe9e680e7867cc290312fe1c970749d8306ddad1a1eda41c6a771b13d495dd225b13b0a9d0f915a984ee3d0703f92287bf8009fbb9f7d6' "Bitcoin",
[0],
words_nfkd,
script_type=proto.InputScriptType.SPENDWITNESS,
)
assert sig_nfkd.address == "bc1qyjjkmdpu7metqt5r36jf872a34syws33s82q2j"
assert (
hexlify(sig_nfkd.signature)
== b"28d0ec02ed8da8df23e7fe9e680e7867cc290312fe1c970749d8306ddad1a1eda41c6a771b13d495dd225b13b0a9d0f915a984ee3d0703f92287bf8009fbb9f7d6"
)
sig_nfc = btc.sign_message(self.client, 'Bitcoin', [0], words_nfc, script_type=proto.InputScriptType.SPENDWITNESS) sig_nfc = btc.sign_message(
assert sig_nfc.address == 'bc1qyjjkmdpu7metqt5r36jf872a34syws33s82q2j' self.client,
assert hexlify(sig_nfc.signature) == b'28d0ec02ed8da8df23e7fe9e680e7867cc290312fe1c970749d8306ddad1a1eda41c6a771b13d495dd225b13b0a9d0f915a984ee3d0703f92287bf8009fbb9f7d6' "Bitcoin",
[0],
words_nfc,
script_type=proto.InputScriptType.SPENDWITNESS,
)
assert sig_nfc.address == "bc1qyjjkmdpu7metqt5r36jf872a34syws33s82q2j"
assert (
hexlify(sig_nfc.signature)
== b"28d0ec02ed8da8df23e7fe9e680e7867cc290312fe1c970749d8306ddad1a1eda41c6a771b13d495dd225b13b0a9d0f915a984ee3d0703f92287bf8009fbb9f7d6"
)

File diff suppressed because it is too large Load Diff

View File

@ -14,21 +14,20 @@
# You should have received a copy of the License along with this library. # You should have received a copy of the License along with this library.
# If not, see <https://www.gnu.org/licenses/lgpl-3.0.html>. # If not, see <https://www.gnu.org/licenses/lgpl-3.0.html>.
import pytest
from binascii import hexlify, unhexlify from binascii import hexlify, unhexlify
from .common import TrezorTest import pytest
from ..support.ckd_public import deserialize
from trezorlib import coins
from trezorlib import messages as proto
from trezorlib.tools import parse_path, CallException, H_
from trezorlib import btc
TxApiBcash = coins.tx_api['Bcash'] from trezorlib import btc, coins, messages as proto
from trezorlib.tools import H_, CallException, parse_path
from ..support.ckd_public import deserialize
from .common import TrezorTest
TxApiBcash = coins.tx_api["Bcash"]
class TestMsgSigntxBch(TrezorTest): class TestMsgSigntxBch(TrezorTest):
def test_send_bch_change(self): def test_send_bch_change(self):
self.setup_mnemonic_allallall() self.setup_mnemonic_allallall()
self.client.set_tx_api(TxApiBcash) self.client.set_tx_api(TxApiBcash)
@ -36,7 +35,9 @@ class TestMsgSigntxBch(TrezorTest):
address_n=parse_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"
),
prev_index=0, prev_index=0,
script_type=proto.InputScriptType.SPENDADDRESS, script_type=proto.InputScriptType.SPENDADDRESS,
) )
@ -46,25 +47,50 @@ class TestMsgSigntxBch(TrezorTest):
script_type=proto.OutputScriptType.PAYTOADDRESS, script_type=proto.OutputScriptType.PAYTOADDRESS,
) )
out2 = proto.TxOutputType( out2 = proto.TxOutputType(
address='bitcoincash:qr23ajjfd9wd73l87j642puf8cad20lfmqdgwvpat4', address="bitcoincash:qr23ajjfd9wd73l87j642puf8cad20lfmqdgwvpat4",
amount=73452, amount=73452,
script_type=proto.OutputScriptType.PAYTOADDRESS, script_type=proto.OutputScriptType.PAYTOADDRESS,
) )
with self.client: with self.client:
self.client.set_expected_responses([ self.client.set_expected_responses(
proto.TxRequest(request_type=proto.RequestType.TXINPUT, details=proto.TxRequestDetailsType(request_index=0)), [
proto.TxRequest(request_type=proto.RequestType.TXOUTPUT, details=proto.TxRequestDetailsType(request_index=0)), proto.TxRequest(
proto.TxRequest(request_type=proto.RequestType.TXOUTPUT, details=proto.TxRequestDetailsType(request_index=1)), request_type=proto.RequestType.TXINPUT,
proto.ButtonRequest(code=proto.ButtonRequestType.ConfirmOutput), details=proto.TxRequestDetailsType(request_index=0),
proto.ButtonRequest(code=proto.ButtonRequestType.SignTx), ),
proto.TxRequest(request_type=proto.RequestType.TXINPUT, details=proto.TxRequestDetailsType(request_index=0)), proto.TxRequest(
proto.TxRequest(request_type=proto.RequestType.TXOUTPUT, details=proto.TxRequestDetailsType(request_index=0)), request_type=proto.RequestType.TXOUTPUT,
proto.TxRequest(request_type=proto.RequestType.TXOUTPUT, details=proto.TxRequestDetailsType(request_index=1)), details=proto.TxRequestDetailsType(request_index=0),
proto.TxRequest(request_type=proto.RequestType.TXFINISHED), ),
]) proto.TxRequest(
(signatures, serialized_tx) = btc.sign_tx(self.client, 'Bcash', [inp1], [out1, out2]) request_type=proto.RequestType.TXOUTPUT,
details=proto.TxRequestDetailsType(request_index=1),
),
proto.ButtonRequest(code=proto.ButtonRequestType.ConfirmOutput),
proto.ButtonRequest(code=proto.ButtonRequestType.SignTx),
proto.TxRequest(
request_type=proto.RequestType.TXINPUT,
details=proto.TxRequestDetailsType(request_index=0),
),
proto.TxRequest(
request_type=proto.RequestType.TXOUTPUT,
details=proto.TxRequestDetailsType(request_index=0),
),
proto.TxRequest(
request_type=proto.RequestType.TXOUTPUT,
details=proto.TxRequestDetailsType(request_index=1),
),
proto.TxRequest(request_type=proto.RequestType.TXFINISHED),
]
)
(signatures, serialized_tx) = btc.sign_tx(
self.client, "Bcash", [inp1], [out1, out2]
)
assert hexlify(serialized_tx) == b'0100000001781a716b1e15b41b07157933e5d777392a75bf87132650cb2e7d46fb8dc237bc000000006a473044022061aee4f17abe044d5df8c52c9ffd3b84e5a29743517e488b20ecf1ae0b3e4d3a02206bb84c55e407f3b684ff8d9bea0a3409cfd865795a19d10b3d3c31f12795c34a412103a020b36130021a0f037c1d1a02042e325c0cb666d6478c1afdcd9d913b9ef080ffffffff0272ee1c00000000001976a914b1401fce7e8bf123c88a0467e0ed11e3b9fbef5488acec1e0100000000001976a914d51eca49695cdf47e7f4b55507893e3ad53fe9d888ac00000000' assert (
hexlify(serialized_tx)
== b"0100000001781a716b1e15b41b07157933e5d777392a75bf87132650cb2e7d46fb8dc237bc000000006a473044022061aee4f17abe044d5df8c52c9ffd3b84e5a29743517e488b20ecf1ae0b3e4d3a02206bb84c55e407f3b684ff8d9bea0a3409cfd865795a19d10b3d3c31f12795c34a412103a020b36130021a0f037c1d1a02042e325c0cb666d6478c1afdcd9d913b9ef080ffffffff0272ee1c00000000001976a914b1401fce7e8bf123c88a0467e0ed11e3b9fbef5488acec1e0100000000001976a914d51eca49695cdf47e7f4b55507893e3ad53fe9d888ac00000000"
)
def test_send_bch_nochange(self): def test_send_bch_nochange(self):
self.setup_mnemonic_allallall() self.setup_mnemonic_allallall()
@ -73,7 +99,9 @@ class TestMsgSigntxBch(TrezorTest):
address_n=parse_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"
),
prev_index=0, prev_index=0,
script_type=proto.InputScriptType.SPENDADDRESS, script_type=proto.InputScriptType.SPENDADDRESS,
) )
@ -81,30 +109,57 @@ class TestMsgSigntxBch(TrezorTest):
address_n=parse_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"
),
prev_index=1, prev_index=1,
script_type=proto.InputScriptType.SPENDADDRESS, script_type=proto.InputScriptType.SPENDADDRESS,
) )
out1 = proto.TxOutputType( out1 = proto.TxOutputType(
address='bitcoincash:qq6wnnkrz7ykaqvxrx4hmjvayvzjzml54uyk76arx4', address="bitcoincash:qq6wnnkrz7ykaqvxrx4hmjvayvzjzml54uyk76arx4",
amount=1934960, amount=1934960,
script_type=proto.OutputScriptType.PAYTOADDRESS, script_type=proto.OutputScriptType.PAYTOADDRESS,
) )
with self.client: with self.client:
self.client.set_expected_responses([ self.client.set_expected_responses(
proto.TxRequest(request_type=proto.RequestType.TXINPUT, details=proto.TxRequestDetailsType(request_index=0)), [
proto.TxRequest(request_type=proto.RequestType.TXINPUT, details=proto.TxRequestDetailsType(request_index=1)), proto.TxRequest(
proto.TxRequest(request_type=proto.RequestType.TXOUTPUT, details=proto.TxRequestDetailsType(request_index=0)), request_type=proto.RequestType.TXINPUT,
proto.ButtonRequest(code=proto.ButtonRequestType.ConfirmOutput), details=proto.TxRequestDetailsType(request_index=0),
proto.ButtonRequest(code=proto.ButtonRequestType.SignTx), ),
proto.TxRequest(request_type=proto.RequestType.TXINPUT, details=proto.TxRequestDetailsType(request_index=0)), proto.TxRequest(
proto.TxRequest(request_type=proto.RequestType.TXINPUT, details=proto.TxRequestDetailsType(request_index=1)), request_type=proto.RequestType.TXINPUT,
proto.TxRequest(request_type=proto.RequestType.TXOUTPUT, details=proto.TxRequestDetailsType(request_index=0)), details=proto.TxRequestDetailsType(request_index=1),
proto.TxRequest(request_type=proto.RequestType.TXFINISHED), ),
]) proto.TxRequest(
(signatures, serialized_tx) = btc.sign_tx(self.client, 'Bcash', [inp1, inp2], [out1]) request_type=proto.RequestType.TXOUTPUT,
details=proto.TxRequestDetailsType(request_index=0),
),
proto.ButtonRequest(code=proto.ButtonRequestType.ConfirmOutput),
proto.ButtonRequest(code=proto.ButtonRequestType.SignTx),
proto.TxRequest(
request_type=proto.RequestType.TXINPUT,
details=proto.TxRequestDetailsType(request_index=0),
),
proto.TxRequest(
request_type=proto.RequestType.TXINPUT,
details=proto.TxRequestDetailsType(request_index=1),
),
proto.TxRequest(
request_type=proto.RequestType.TXOUTPUT,
details=proto.TxRequestDetailsType(request_index=0),
),
proto.TxRequest(request_type=proto.RequestType.TXFINISHED),
]
)
(signatures, serialized_tx) = btc.sign_tx(
self.client, "Bcash", [inp1, inp2], [out1]
)
assert hexlify(serialized_tx) == b'01000000022c06cf6f215c5cbfd7caa8e71b1b32630cabf1f816a4432815b037b277852e50000000006a47304402207a2a955f1cb3dc5f03f2c82934f55654882af4e852e5159639f6349e9386ec4002205fb8419dce4e648eae8f67bc4e369adfb130a87d2ea2d668f8144213b12bb457412103174c61e9c5362507e8061e28d2c0ce3d4df4e73f3535ae0b12f37809e0f92d2dffffffff2c06cf6f215c5cbfd7caa8e71b1b32630cabf1f816a4432815b037b277852e50010000006a473044022062151cf960b71823bbe68c7ed2c2a93ad1b9706a30255fddb02fcbe056d8c26102207bad1f0872bc5f0cfaf22e45c925c35d6c1466e303163b75cb7688038f1a5541412102595caf9aeb6ffdd0e82b150739a83297358b9a77564de382671056ad9e5b8c58ffffffff0170861d00000000001976a91434e9cec317896e818619ab7dc99d2305216ff4af88ac00000000' assert (
hexlify(serialized_tx)
== b"01000000022c06cf6f215c5cbfd7caa8e71b1b32630cabf1f816a4432815b037b277852e50000000006a47304402207a2a955f1cb3dc5f03f2c82934f55654882af4e852e5159639f6349e9386ec4002205fb8419dce4e648eae8f67bc4e369adfb130a87d2ea2d668f8144213b12bb457412103174c61e9c5362507e8061e28d2c0ce3d4df4e73f3535ae0b12f37809e0f92d2dffffffff2c06cf6f215c5cbfd7caa8e71b1b32630cabf1f816a4432815b037b277852e50010000006a473044022062151cf960b71823bbe68c7ed2c2a93ad1b9706a30255fddb02fcbe056d8c26102207bad1f0872bc5f0cfaf22e45c925c35d6c1466e303163b75cb7688038f1a5541412102595caf9aeb6ffdd0e82b150739a83297358b9a77564de382671056ad9e5b8c58ffffffff0170861d00000000001976a91434e9cec317896e818619ab7dc99d2305216ff4af88ac00000000"
)
def test_send_bch_oldaddr(self): def test_send_bch_oldaddr(self):
self.setup_mnemonic_allallall() self.setup_mnemonic_allallall()
@ -113,7 +168,9 @@ class TestMsgSigntxBch(TrezorTest):
address_n=parse_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"
),
prev_index=0, prev_index=0,
script_type=proto.InputScriptType.SPENDADDRESS, script_type=proto.InputScriptType.SPENDADDRESS,
) )
@ -121,30 +178,57 @@ class TestMsgSigntxBch(TrezorTest):
address_n=parse_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"
),
prev_index=1, prev_index=1,
script_type=proto.InputScriptType.SPENDADDRESS, script_type=proto.InputScriptType.SPENDADDRESS,
) )
out1 = proto.TxOutputType( out1 = proto.TxOutputType(
address='15pnEDZJo3ycPUamqP3tEDnEju1oW5fBCz', address="15pnEDZJo3ycPUamqP3tEDnEju1oW5fBCz",
amount=1934960, amount=1934960,
script_type=proto.OutputScriptType.PAYTOADDRESS, script_type=proto.OutputScriptType.PAYTOADDRESS,
) )
with self.client: with self.client:
self.client.set_expected_responses([ self.client.set_expected_responses(
proto.TxRequest(request_type=proto.RequestType.TXINPUT, details=proto.TxRequestDetailsType(request_index=0)), [
proto.TxRequest(request_type=proto.RequestType.TXINPUT, details=proto.TxRequestDetailsType(request_index=1)), proto.TxRequest(
proto.TxRequest(request_type=proto.RequestType.TXOUTPUT, details=proto.TxRequestDetailsType(request_index=0)), request_type=proto.RequestType.TXINPUT,
proto.ButtonRequest(code=proto.ButtonRequestType.ConfirmOutput), details=proto.TxRequestDetailsType(request_index=0),
proto.ButtonRequest(code=proto.ButtonRequestType.SignTx), ),
proto.TxRequest(request_type=proto.RequestType.TXINPUT, details=proto.TxRequestDetailsType(request_index=0)), proto.TxRequest(
proto.TxRequest(request_type=proto.RequestType.TXINPUT, details=proto.TxRequestDetailsType(request_index=1)), request_type=proto.RequestType.TXINPUT,
proto.TxRequest(request_type=proto.RequestType.TXOUTPUT, details=proto.TxRequestDetailsType(request_index=0)), details=proto.TxRequestDetailsType(request_index=1),
proto.TxRequest(request_type=proto.RequestType.TXFINISHED), ),
]) proto.TxRequest(
(signatures, serialized_tx) = btc.sign_tx(self.client, 'Bcash', [inp1, inp2], [out1]) request_type=proto.RequestType.TXOUTPUT,
details=proto.TxRequestDetailsType(request_index=0),
),
proto.ButtonRequest(code=proto.ButtonRequestType.ConfirmOutput),
proto.ButtonRequest(code=proto.ButtonRequestType.SignTx),
proto.TxRequest(
request_type=proto.RequestType.TXINPUT,
details=proto.TxRequestDetailsType(request_index=0),
),
proto.TxRequest(
request_type=proto.RequestType.TXINPUT,
details=proto.TxRequestDetailsType(request_index=1),
),
proto.TxRequest(
request_type=proto.RequestType.TXOUTPUT,
details=proto.TxRequestDetailsType(request_index=0),
),
proto.TxRequest(request_type=proto.RequestType.TXFINISHED),
]
)
(signatures, serialized_tx) = btc.sign_tx(
self.client, "Bcash", [inp1, inp2], [out1]
)
assert hexlify(serialized_tx) == b'01000000022c06cf6f215c5cbfd7caa8e71b1b32630cabf1f816a4432815b037b277852e50000000006a47304402207a2a955f1cb3dc5f03f2c82934f55654882af4e852e5159639f6349e9386ec4002205fb8419dce4e648eae8f67bc4e369adfb130a87d2ea2d668f8144213b12bb457412103174c61e9c5362507e8061e28d2c0ce3d4df4e73f3535ae0b12f37809e0f92d2dffffffff2c06cf6f215c5cbfd7caa8e71b1b32630cabf1f816a4432815b037b277852e50010000006a473044022062151cf960b71823bbe68c7ed2c2a93ad1b9706a30255fddb02fcbe056d8c26102207bad1f0872bc5f0cfaf22e45c925c35d6c1466e303163b75cb7688038f1a5541412102595caf9aeb6ffdd0e82b150739a83297358b9a77564de382671056ad9e5b8c58ffffffff0170861d00000000001976a91434e9cec317896e818619ab7dc99d2305216ff4af88ac00000000' assert (
hexlify(serialized_tx)
== b"01000000022c06cf6f215c5cbfd7caa8e71b1b32630cabf1f816a4432815b037b277852e50000000006a47304402207a2a955f1cb3dc5f03f2c82934f55654882af4e852e5159639f6349e9386ec4002205fb8419dce4e648eae8f67bc4e369adfb130a87d2ea2d668f8144213b12bb457412103174c61e9c5362507e8061e28d2c0ce3d4df4e73f3535ae0b12f37809e0f92d2dffffffff2c06cf6f215c5cbfd7caa8e71b1b32630cabf1f816a4432815b037b277852e50010000006a473044022062151cf960b71823bbe68c7ed2c2a93ad1b9706a30255fddb02fcbe056d8c26102207bad1f0872bc5f0cfaf22e45c925c35d6c1466e303163b75cb7688038f1a5541412102595caf9aeb6ffdd0e82b150739a83297358b9a77564de382671056ad9e5b8c58ffffffff0170861d00000000001976a91434e9cec317896e818619ab7dc99d2305216ff4af88ac00000000"
)
def test_attack_amount(self): def test_attack_amount(self):
self.setup_mnemonic_allallall() self.setup_mnemonic_allallall()
@ -153,7 +237,9 @@ class TestMsgSigntxBch(TrezorTest):
address_n=parse_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"
),
prev_index=0, prev_index=0,
script_type=proto.InputScriptType.SPENDADDRESS, script_type=proto.InputScriptType.SPENDADDRESS,
) )
@ -161,12 +247,14 @@ class TestMsgSigntxBch(TrezorTest):
address_n=parse_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"
),
prev_index=1, prev_index=1,
script_type=proto.InputScriptType.SPENDADDRESS, script_type=proto.InputScriptType.SPENDADDRESS,
) )
out1 = proto.TxOutputType( out1 = proto.TxOutputType(
address='bitcoincash:qq6wnnkrz7ykaqvxrx4hmjvayvzjzml54uyk76arx4', address="bitcoincash:qq6wnnkrz7ykaqvxrx4hmjvayvzjzml54uyk76arx4",
amount=200, amount=200,
script_type=proto.OutputScriptType.PAYTOADDRESS, script_type=proto.OutputScriptType.PAYTOADDRESS,
) )
@ -198,37 +286,83 @@ class TestMsgSigntxBch(TrezorTest):
# test if passes without modifications # test if passes without modifications
with self.client: with self.client:
self.client.set_expected_responses([ self.client.set_expected_responses(
proto.TxRequest(request_type=proto.RequestType.TXINPUT, details=proto.TxRequestDetailsType(request_index=0)), [
proto.TxRequest(request_type=proto.RequestType.TXINPUT, details=proto.TxRequestDetailsType(request_index=1)), proto.TxRequest(
proto.TxRequest(request_type=proto.RequestType.TXOUTPUT, details=proto.TxRequestDetailsType(request_index=0)), request_type=proto.RequestType.TXINPUT,
proto.ButtonRequest(code=proto.ButtonRequestType.ConfirmOutput), details=proto.TxRequestDetailsType(request_index=0),
proto.ButtonRequest(code=proto.ButtonRequestType.SignTx), ),
proto.TxRequest(request_type=proto.RequestType.TXINPUT, details=proto.TxRequestDetailsType(request_index=0)), proto.TxRequest(
proto.TxRequest(request_type=proto.RequestType.TXINPUT, details=proto.TxRequestDetailsType(request_index=1)), request_type=proto.RequestType.TXINPUT,
proto.TxRequest(request_type=proto.RequestType.TXOUTPUT, details=proto.TxRequestDetailsType(request_index=0)), details=proto.TxRequestDetailsType(request_index=1),
proto.TxRequest(request_type=proto.RequestType.TXFINISHED), ),
]) proto.TxRequest(
btc.sign_tx(self.client, 'Bcash', [inp1, inp2], [out1]) request_type=proto.RequestType.TXOUTPUT,
details=proto.TxRequestDetailsType(request_index=0),
),
proto.ButtonRequest(code=proto.ButtonRequestType.ConfirmOutput),
proto.ButtonRequest(code=proto.ButtonRequestType.SignTx),
proto.TxRequest(
request_type=proto.RequestType.TXINPUT,
details=proto.TxRequestDetailsType(request_index=0),
),
proto.TxRequest(
request_type=proto.RequestType.TXINPUT,
details=proto.TxRequestDetailsType(request_index=1),
),
proto.TxRequest(
request_type=proto.RequestType.TXOUTPUT,
details=proto.TxRequestDetailsType(request_index=0),
),
proto.TxRequest(request_type=proto.RequestType.TXFINISHED),
]
)
btc.sign_tx(self.client, "Bcash", [inp1, inp2], [out1])
# now fails # now fails
with self.client: with self.client:
self.client.set_expected_responses([ self.client.set_expected_responses(
proto.TxRequest(request_type=proto.RequestType.TXINPUT, details=proto.TxRequestDetailsType(request_index=0)), [
proto.TxRequest(request_type=proto.RequestType.TXINPUT, details=proto.TxRequestDetailsType(request_index=1)), proto.TxRequest(
proto.TxRequest(request_type=proto.RequestType.TXOUTPUT, details=proto.TxRequestDetailsType(request_index=0)), request_type=proto.RequestType.TXINPUT,
proto.ButtonRequest(code=proto.ButtonRequestType.ConfirmOutput), details=proto.TxRequestDetailsType(request_index=0),
proto.ButtonRequest(code=proto.ButtonRequestType.SignTx), ),
proto.TxRequest(request_type=proto.RequestType.TXINPUT, details=proto.TxRequestDetailsType(request_index=0)), proto.TxRequest(
proto.TxRequest(request_type=proto.RequestType.TXINPUT, details=proto.TxRequestDetailsType(request_index=1)), request_type=proto.RequestType.TXINPUT,
proto.Failure(), details=proto.TxRequestDetailsType(request_index=1),
]) ),
proto.TxRequest(
request_type=proto.RequestType.TXOUTPUT,
details=proto.TxRequestDetailsType(request_index=0),
),
proto.ButtonRequest(code=proto.ButtonRequestType.ConfirmOutput),
proto.ButtonRequest(code=proto.ButtonRequestType.SignTx),
proto.TxRequest(
request_type=proto.RequestType.TXINPUT,
details=proto.TxRequestDetailsType(request_index=0),
),
proto.TxRequest(
request_type=proto.RequestType.TXINPUT,
details=proto.TxRequestDetailsType(request_index=1),
),
proto.Failure(),
]
)
with pytest.raises(CallException) as exc: with pytest.raises(CallException) as exc:
btc.sign_tx(self.client, 'Bcash', [inp1, inp2], [out1], debug_processor=attack_processor) btc.sign_tx(
self.client,
"Bcash",
[inp1, inp2],
[out1],
debug_processor=attack_processor,
)
assert exc.value.args[0] in (proto.FailureType.ProcessError, proto.FailureType.DataError) assert exc.value.args[0] in (
assert exc.value.args[1].endswith('Transaction has changed during signing') proto.FailureType.ProcessError,
proto.FailureType.DataError,
)
assert exc.value.args[1].endswith("Transaction has changed during signing")
def test_attack_change_input(self): def test_attack_change_input(self):
self.setup_mnemonic_allallall() self.setup_mnemonic_allallall()
@ -237,7 +371,9 @@ class TestMsgSigntxBch(TrezorTest):
address_n=parse_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"
),
prev_index=0, prev_index=0,
script_type=proto.InputScriptType.SPENDADDRESS, script_type=proto.InputScriptType.SPENDADDRESS,
) )
@ -247,7 +383,7 @@ class TestMsgSigntxBch(TrezorTest):
script_type=proto.OutputScriptType.PAYTOADDRESS, script_type=proto.OutputScriptType.PAYTOADDRESS,
) )
out2 = proto.TxOutputType( out2 = proto.TxOutputType(
address='bitcoincash:qr23ajjfd9wd73l87j642puf8cad20lfmqdgwvpat4', address="bitcoincash:qr23ajjfd9wd73l87j642puf8cad20lfmqdgwvpat4",
amount=73452, amount=73452,
script_type=proto.OutputScriptType.PAYTOADDRESS, script_type=proto.OutputScriptType.PAYTOADDRESS,
) )
@ -272,95 +408,178 @@ class TestMsgSigntxBch(TrezorTest):
return msg return msg
with self.client: with self.client:
self.client.set_expected_responses([ self.client.set_expected_responses(
proto.TxRequest(request_type=proto.RequestType.TXINPUT, details=proto.TxRequestDetailsType(request_index=0)), [
proto.TxRequest(request_type=proto.RequestType.TXOUTPUT, details=proto.TxRequestDetailsType(request_index=0)), proto.TxRequest(
proto.TxRequest(request_type=proto.RequestType.TXOUTPUT, details=proto.TxRequestDetailsType(request_index=1)), request_type=proto.RequestType.TXINPUT,
proto.ButtonRequest(code=proto.ButtonRequestType.ConfirmOutput), details=proto.TxRequestDetailsType(request_index=0),
proto.ButtonRequest(code=proto.ButtonRequestType.SignTx), ),
proto.TxRequest(request_type=proto.RequestType.TXINPUT, details=proto.TxRequestDetailsType(request_index=0)), proto.TxRequest(
proto.Failure(code=proto.FailureType.ProcessError), request_type=proto.RequestType.TXOUTPUT,
]) details=proto.TxRequestDetailsType(request_index=0),
),
proto.TxRequest(
request_type=proto.RequestType.TXOUTPUT,
details=proto.TxRequestDetailsType(request_index=1),
),
proto.ButtonRequest(code=proto.ButtonRequestType.ConfirmOutput),
proto.ButtonRequest(code=proto.ButtonRequestType.SignTx),
proto.TxRequest(
request_type=proto.RequestType.TXINPUT,
details=proto.TxRequestDetailsType(request_index=0),
),
proto.Failure(code=proto.FailureType.ProcessError),
]
)
with pytest.raises(CallException): with pytest.raises(CallException):
btc.sign_tx(self.client, 'Bcash', [inp1], [out1, out2], debug_processor=attack_processor) btc.sign_tx(
self.client,
"Bcash",
[inp1],
[out1, out2],
debug_processor=attack_processor,
)
def test_send_bch_multisig_wrongchange(self): def test_send_bch_multisig_wrongchange(self):
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: btc.get_public_node(self.client, parse_path("44'/145'/" + str(index) + "'")), range(1, 4)): for n in map(
lambda index: btc.get_public_node(
self.client, 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):
return proto.MultisigRedeemScriptType( return proto.MultisigRedeemScriptType(
pubkeys=list(map(lambda xpub: proto.HDNodePathType(node=deserialize(xpub), address_n=[chain, nr]), xpubs)), pubkeys=list(
map(
lambda xpub: proto.HDNodePathType(
node=deserialize(xpub), address_n=[chain, nr]
),
xpubs,
)
),
signatures=signatures, signatures=signatures,
m=2, m=2,
) )
correcthorse = proto.HDNodeType( correcthorse = proto.HDNodeType(
depth=1, fingerprint=0, child_num=0, depth=1,
chain_code=unhexlify('0000000000000000000000000000000000000000000000000000000000000000'), fingerprint=0,
public_key=unhexlify('0378d430274f8c5ec1321338151e9f27f4c676a008bdf8638d07c0b6be9ab35c71')) child_num=0,
sig = unhexlify(b'304402207274b5a4d15e75f3df7319a375557b0efba9b27bc63f9f183a17da95a6125c94022000efac57629f1522e2d3958430e2ef073b0706cfac06cce492651b79858f09ae') chain_code=unhexlify(
"0000000000000000000000000000000000000000000000000000000000000000"
),
public_key=unhexlify(
"0378d430274f8c5ec1321338151e9f27f4c676a008bdf8638d07c0b6be9ab35c71"
),
)
sig = unhexlify(
b"304402207274b5a4d15e75f3df7319a375557b0efba9b27bc63f9f183a17da95a6125c94022000efac57629f1522e2d3958430e2ef073b0706cfac06cce492651b79858f09ae"
)
inp1 = proto.TxInputType( inp1 = proto.TxInputType(
address_n=parse_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,
prev_hash=unhexlify('f68caf10df12d5b07a34601d88fa6856c6edcbf4d05ebef3486510ae1c293d5f'), prev_hash=unhexlify(
"f68caf10df12d5b07a34601d88fa6856c6edcbf4d05ebef3486510ae1c293d5f"
),
prev_index=1, prev_index=1,
script_type=proto.InputScriptType.SPENDMULTISIG, script_type=proto.InputScriptType.SPENDMULTISIG,
) )
out1 = proto.TxOutputType( out1 = proto.TxOutputType(
address_n=parse_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=correcthorse, address_n=[]), proto.HDNodePathType(node=deserialize(xpubs[0]), address_n=[1, 1]),
proto.HDNodePathType(node=correcthorse, address_n=[])], proto.HDNodePathType(node=correcthorse, address_n=[]),
signatures=[b'', b'', b''], proto.HDNodePathType(node=correcthorse, address_n=[]),
],
signatures=[b"", b"", b""],
m=2, m=2,
), ),
script_type=proto.OutputScriptType.PAYTOMULTISIG, script_type=proto.OutputScriptType.PAYTOMULTISIG,
amount=23000 amount=23000,
) )
with self.client: with self.client:
self.client.set_expected_responses([ self.client.set_expected_responses(
proto.TxRequest(request_type=proto.RequestType.TXINPUT, details=proto.TxRequestDetailsType(request_index=0)), [
proto.TxRequest(request_type=proto.RequestType.TXOUTPUT, details=proto.TxRequestDetailsType(request_index=0)), proto.TxRequest(
proto.ButtonRequest(code=proto.ButtonRequestType.ConfirmOutput), request_type=proto.RequestType.TXINPUT,
proto.ButtonRequest(code=proto.ButtonRequestType.SignTx), details=proto.TxRequestDetailsType(request_index=0),
proto.TxRequest(request_type=proto.RequestType.TXINPUT, details=proto.TxRequestDetailsType(request_index=0)), ),
proto.TxRequest(request_type=proto.RequestType.TXOUTPUT, details=proto.TxRequestDetailsType(request_index=0)), proto.TxRequest(
proto.TxRequest(request_type=proto.RequestType.TXFINISHED), request_type=proto.RequestType.TXOUTPUT,
]) details=proto.TxRequestDetailsType(request_index=0),
(signatures1, serialized_tx) = btc.sign_tx(self.client, 'Bcash', [inp1], [out1]) ),
assert hexlify(signatures1[0]) == b'3044022052ccf022b3684ecce9f961ce8828387b97267c86bedf0ce16a24bf014e62e42c022035d315ddbeeef7ab3456bd09aed8b625ea58852216b60e4b84ba9f85827d305c' proto.ButtonRequest(code=proto.ButtonRequestType.ConfirmOutput),
assert hexlify(serialized_tx) == b'01000000015f3d291cae106548f3be5ed0f4cbedc65668fa881d60347ab0d512df10af8cf601000000fc00473044022052ccf022b3684ecce9f961ce8828387b97267c86bedf0ce16a24bf014e62e42c022035d315ddbeeef7ab3456bd09aed8b625ea58852216b60e4b84ba9f85827d305c4147304402207274b5a4d15e75f3df7319a375557b0efba9b27bc63f9f183a17da95a6125c94022000efac57629f1522e2d3958430e2ef073b0706cfac06cce492651b79858f09ae414c69522103d62b2af2272bbd67cbe30eeaf4226c7f2d57d2a0ed1aab5ab736fb40bb2f5ffe21036d5e0d7ca3589465711eec91436249d7234d3a994c219024fc75cec98fc02ae221024f58378a69b68e89301a6ff882116e0fa35446ec9bfd86532eeb05941ec1f8c853aeffffffff01d85900000000000017a9140bb11de6558871f49fc241341992ece9986f7c5c8700000000' proto.ButtonRequest(code=proto.ButtonRequestType.SignTx),
proto.TxRequest(
request_type=proto.RequestType.TXINPUT,
details=proto.TxRequestDetailsType(request_index=0),
),
proto.TxRequest(
request_type=proto.RequestType.TXOUTPUT,
details=proto.TxRequestDetailsType(request_index=0),
),
proto.TxRequest(request_type=proto.RequestType.TXFINISHED),
]
)
(signatures1, serialized_tx) = btc.sign_tx(
self.client, "Bcash", [inp1], [out1]
)
assert (
hexlify(signatures1[0])
== b"3044022052ccf022b3684ecce9f961ce8828387b97267c86bedf0ce16a24bf014e62e42c022035d315ddbeeef7ab3456bd09aed8b625ea58852216b60e4b84ba9f85827d305c"
)
assert (
hexlify(serialized_tx)
== b"01000000015f3d291cae106548f3be5ed0f4cbedc65668fa881d60347ab0d512df10af8cf601000000fc00473044022052ccf022b3684ecce9f961ce8828387b97267c86bedf0ce16a24bf014e62e42c022035d315ddbeeef7ab3456bd09aed8b625ea58852216b60e4b84ba9f85827d305c4147304402207274b5a4d15e75f3df7319a375557b0efba9b27bc63f9f183a17da95a6125c94022000efac57629f1522e2d3958430e2ef073b0706cfac06cce492651b79858f09ae414c69522103d62b2af2272bbd67cbe30eeaf4226c7f2d57d2a0ed1aab5ab736fb40bb2f5ffe21036d5e0d7ca3589465711eec91436249d7234d3a994c219024fc75cec98fc02ae221024f58378a69b68e89301a6ff882116e0fa35446ec9bfd86532eeb05941ec1f8c853aeffffffff01d85900000000000017a9140bb11de6558871f49fc241341992ece9986f7c5c8700000000"
)
def test_send_bch_multisig_change(self): def test_send_bch_multisig_change(self):
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: btc.get_public_node(self.client, parse_path("44'/145'/" + str(index) + "'")), range(1, 4)): for n in map(
lambda index: btc.get_public_node(
self.client, 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):
return proto.MultisigRedeemScriptType( return proto.MultisigRedeemScriptType(
pubkeys=list(map(lambda xpub: proto.HDNodePathType(node=deserialize(xpub), address_n=[chain, nr]), xpubs)), pubkeys=list(
map(
lambda xpub: proto.HDNodePathType(
node=deserialize(xpub), address_n=[chain, nr]
),
xpubs,
)
),
signatures=signatures, signatures=signatures,
m=2, m=2,
) )
inp1 = proto.TxInputType( inp1 = proto.TxInputType(
address_n=parse_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,
prev_hash=unhexlify('8b6db9b8ba24235d86b053ea2ccb484fc32b96f89c3c39f98d86f90db16076a0'), prev_hash=unhexlify(
"8b6db9b8ba24235d86b053ea2ccb484fc32b96f89c3c39f98d86f90db16076a0"
),
prev_index=0, prev_index=0,
script_type=proto.InputScriptType.SPENDMULTISIG, script_type=proto.InputScriptType.SPENDMULTISIG,
) )
out1 = proto.TxOutputType( out1 = proto.TxOutputType(
address='bitcoincash:qqq8gx2j76nw4dfefumxmdwvtf2tpsjznusgsmzex9', address="bitcoincash:qqq8gx2j76nw4dfefumxmdwvtf2tpsjznusgsmzex9",
amount=24000, amount=24000,
script_type=proto.OutputScriptType.PAYTOADDRESS, script_type=proto.OutputScriptType.PAYTOADDRESS,
) )
@ -368,48 +587,103 @@ class TestMsgSigntxBch(TrezorTest):
address_n=parse_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,
) )
with self.client: with self.client:
self.client.set_expected_responses([ self.client.set_expected_responses(
proto.TxRequest(request_type=proto.RequestType.TXINPUT, details=proto.TxRequestDetailsType(request_index=0)), [
proto.TxRequest(request_type=proto.RequestType.TXOUTPUT, details=proto.TxRequestDetailsType(request_index=0)), proto.TxRequest(
proto.ButtonRequest(code=proto.ButtonRequestType.ConfirmOutput), request_type=proto.RequestType.TXINPUT,
proto.TxRequest(request_type=proto.RequestType.TXOUTPUT, details=proto.TxRequestDetailsType(request_index=1)), details=proto.TxRequestDetailsType(request_index=0),
proto.ButtonRequest(code=proto.ButtonRequestType.SignTx), ),
proto.TxRequest(request_type=proto.RequestType.TXINPUT, details=proto.TxRequestDetailsType(request_index=0)), proto.TxRequest(
proto.TxRequest(request_type=proto.RequestType.TXOUTPUT, details=proto.TxRequestDetailsType(request_index=0)), request_type=proto.RequestType.TXOUTPUT,
proto.TxRequest(request_type=proto.RequestType.TXOUTPUT, details=proto.TxRequestDetailsType(request_index=1)), details=proto.TxRequestDetailsType(request_index=0),
proto.TxRequest(request_type=proto.RequestType.TXFINISHED), ),
]) proto.ButtonRequest(code=proto.ButtonRequestType.ConfirmOutput),
(signatures1, serialized_tx) = btc.sign_tx(self.client, 'Bcash', [inp1], [out1, out2]) proto.TxRequest(
request_type=proto.RequestType.TXOUTPUT,
details=proto.TxRequestDetailsType(request_index=1),
),
proto.ButtonRequest(code=proto.ButtonRequestType.SignTx),
proto.TxRequest(
request_type=proto.RequestType.TXINPUT,
details=proto.TxRequestDetailsType(request_index=0),
),
proto.TxRequest(
request_type=proto.RequestType.TXOUTPUT,
details=proto.TxRequestDetailsType(request_index=0),
),
proto.TxRequest(
request_type=proto.RequestType.TXOUTPUT,
details=proto.TxRequestDetailsType(request_index=1),
),
proto.TxRequest(request_type=proto.RequestType.TXFINISHED),
]
)
(signatures1, serialized_tx) = btc.sign_tx(
self.client, "Bcash", [inp1], [out1, out2]
)
assert hexlify(signatures1[0]) == b'3045022100bcb1a7134a13025a06052546ee1c6ac3640a0abd2d130190ed13ed7fcb43e9cd02207c381478e2ee123c850425bfbf6d3c691230eb37e333832cb32a1ed3f2cd9e85' assert (
hexlify(signatures1[0])
== b"3045022100bcb1a7134a13025a06052546ee1c6ac3640a0abd2d130190ed13ed7fcb43e9cd02207c381478e2ee123c850425bfbf6d3c691230eb37e333832cb32a1ed3f2cd9e85"
)
inp1 = proto.TxInputType( inp1 = proto.TxInputType(
address_n=parse_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,
prev_hash=unhexlify('8b6db9b8ba24235d86b053ea2ccb484fc32b96f89c3c39f98d86f90db16076a0'), prev_hash=unhexlify(
"8b6db9b8ba24235d86b053ea2ccb484fc32b96f89c3c39f98d86f90db16076a0"
),
prev_index=0, prev_index=0,
script_type=proto.InputScriptType.SPENDMULTISIG, script_type=proto.InputScriptType.SPENDMULTISIG,
) )
out2.address_n[2] = H_(1) out2.address_n[2] = H_(1)
with self.client: with self.client:
self.client.set_expected_responses([ self.client.set_expected_responses(
proto.TxRequest(request_type=proto.RequestType.TXINPUT, details=proto.TxRequestDetailsType(request_index=0)), [
proto.TxRequest(request_type=proto.RequestType.TXOUTPUT, details=proto.TxRequestDetailsType(request_index=0)), proto.TxRequest(
proto.ButtonRequest(code=proto.ButtonRequestType.ConfirmOutput), request_type=proto.RequestType.TXINPUT,
proto.TxRequest(request_type=proto.RequestType.TXOUTPUT, details=proto.TxRequestDetailsType(request_index=1)), details=proto.TxRequestDetailsType(request_index=0),
proto.ButtonRequest(code=proto.ButtonRequestType.SignTx), ),
proto.TxRequest(request_type=proto.RequestType.TXINPUT, details=proto.TxRequestDetailsType(request_index=0)), proto.TxRequest(
proto.TxRequest(request_type=proto.RequestType.TXOUTPUT, details=proto.TxRequestDetailsType(request_index=0)), request_type=proto.RequestType.TXOUTPUT,
proto.TxRequest(request_type=proto.RequestType.TXOUTPUT, details=proto.TxRequestDetailsType(request_index=1)), details=proto.TxRequestDetailsType(request_index=0),
proto.TxRequest(request_type=proto.RequestType.TXFINISHED), ),
]) proto.ButtonRequest(code=proto.ButtonRequestType.ConfirmOutput),
(signatures1, serialized_tx) = btc.sign_tx(self.client, 'Bcash', [inp1], [out1, out2]) proto.TxRequest(
request_type=proto.RequestType.TXOUTPUT,
details=proto.TxRequestDetailsType(request_index=1),
),
proto.ButtonRequest(code=proto.ButtonRequestType.SignTx),
proto.TxRequest(
request_type=proto.RequestType.TXINPUT,
details=proto.TxRequestDetailsType(request_index=0),
),
proto.TxRequest(
request_type=proto.RequestType.TXOUTPUT,
details=proto.TxRequestDetailsType(request_index=0),
),
proto.TxRequest(
request_type=proto.RequestType.TXOUTPUT,
details=proto.TxRequestDetailsType(request_index=1),
),
proto.TxRequest(request_type=proto.RequestType.TXFINISHED),
]
)
(signatures1, serialized_tx) = btc.sign_tx(
self.client, "Bcash", [inp1], [out1, out2]
)
assert hexlify(signatures1[0]) == b'3045022100f1153636371ba1f84389460e1265a8fa296569bc18e117c31f4e8f0fc0650c01022022932cc84766ff0c0f65ed9633ad311ae90d4c8fe71f5e1890b1e8f74dd516fa' assert (
assert hexlify(serialized_tx) == b'0100000001a07660b10df9868df9393c9cf8962bc34f48cb2cea53b0865d2324bab8b96d8b00000000fdfe0000483045022100f1153636371ba1f84389460e1265a8fa296569bc18e117c31f4e8f0fc0650c01022022932cc84766ff0c0f65ed9633ad311ae90d4c8fe71f5e1890b1e8f74dd516fa41483045022100bcb1a7134a13025a06052546ee1c6ac3640a0abd2d130190ed13ed7fcb43e9cd02207c381478e2ee123c850425bfbf6d3c691230eb37e333832cb32a1ed3f2cd9e85414c69522102fcf63419c319ce1a42d69120a3599d6da8c5dd4caf2888220eccde5a1ff7c5d021036d7d5ef79370b7fabe2c058698a20219e97fc70868e65ecdd6b37cc18e8a88bd2103505dc649dab8cd1655a4c0daf0ec5f955881c9d7011478ea881fac11cab1e49953aeffffffff02c05d0000000000001976a91400741952f6a6eab5394f366db5cc5a54b0c2429f88acc05d00000000000017a914756c06d7e77de3950a6124f026d8e1a2464b3ecf8700000000' hexlify(signatures1[0])
== b"3045022100f1153636371ba1f84389460e1265a8fa296569bc18e117c31f4e8f0fc0650c01022022932cc84766ff0c0f65ed9633ad311ae90d4c8fe71f5e1890b1e8f74dd516fa"
)
assert (
hexlify(serialized_tx)
== b"0100000001a07660b10df9868df9393c9cf8962bc34f48cb2cea53b0865d2324bab8b96d8b00000000fdfe0000483045022100f1153636371ba1f84389460e1265a8fa296569bc18e117c31f4e8f0fc0650c01022022932cc84766ff0c0f65ed9633ad311ae90d4c8fe71f5e1890b1e8f74dd516fa41483045022100bcb1a7134a13025a06052546ee1c6ac3640a0abd2d130190ed13ed7fcb43e9cd02207c381478e2ee123c850425bfbf6d3c691230eb37e333832cb32a1ed3f2cd9e85414c69522102fcf63419c319ce1a42d69120a3599d6da8c5dd4caf2888220eccde5a1ff7c5d021036d7d5ef79370b7fabe2c058698a20219e97fc70868e65ecdd6b37cc18e8a88bd2103505dc649dab8cd1655a4c0daf0ec5f955881c9d7011478ea881fac11cab1e49953aeffffffff02c05d0000000000001976a91400741952f6a6eab5394f366db5cc5a54b0c2429f88acc05d00000000000017a914756c06d7e77de3950a6124f026d8e1a2464b3ecf8700000000"
)

View File

@ -14,29 +14,30 @@
# You should have received a copy of the License along with this library. # You should have received a copy of the License along with this library.
# If not, see <https://www.gnu.org/licenses/lgpl-3.0.html>. # If not, see <https://www.gnu.org/licenses/lgpl-3.0.html>.
import pytest
from binascii import hexlify, unhexlify from binascii import hexlify, unhexlify
from .common import TrezorTest import pytest
from trezorlib import btc, coins, messages as proto
from trezorlib.tools import H_, CallException, parse_path
from ..support.ckd_public import deserialize from ..support.ckd_public import deserialize
from trezorlib import coins from .common import TrezorTest
from trezorlib import messages as proto
from trezorlib.tools import parse_path, CallException, H_
from trezorlib import btc
TxApiBitcoinGold = coins.tx_api["Bgold"] TxApiBitcoinGold = coins.tx_api["Bgold"]
# All data taken from T1 # All data taken from T1
class TestMsgSigntxBitcoinGold(TrezorTest): class TestMsgSigntxBitcoinGold(TrezorTest):
def test_send_bitcoin_gold_change(self): def test_send_bitcoin_gold_change(self):
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=parse_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,
) )
@ -46,25 +47,50 @@ class TestMsgSigntxBitcoinGold(TrezorTest):
script_type=proto.OutputScriptType.PAYTOADDRESS, script_type=proto.OutputScriptType.PAYTOADDRESS,
) )
out2 = proto.TxOutputType( out2 = proto.TxOutputType(
address='GfDB1tvjfm3bukeoBTtfNqrJVFohS2kCTe', address="GfDB1tvjfm3bukeoBTtfNqrJVFohS2kCTe",
amount=73452, amount=73452,
script_type=proto.OutputScriptType.PAYTOADDRESS, script_type=proto.OutputScriptType.PAYTOADDRESS,
) )
with self.client: with self.client:
self.client.set_expected_responses([ self.client.set_expected_responses(
proto.TxRequest(request_type=proto.RequestType.TXINPUT, details=proto.TxRequestDetailsType(request_index=0)), [
proto.TxRequest(request_type=proto.RequestType.TXOUTPUT, details=proto.TxRequestDetailsType(request_index=0)), proto.TxRequest(
proto.TxRequest(request_type=proto.RequestType.TXOUTPUT, details=proto.TxRequestDetailsType(request_index=1)), request_type=proto.RequestType.TXINPUT,
proto.ButtonRequest(code=proto.ButtonRequestType.ConfirmOutput), details=proto.TxRequestDetailsType(request_index=0),
proto.ButtonRequest(code=proto.ButtonRequestType.SignTx), ),
proto.TxRequest(request_type=proto.RequestType.TXINPUT, details=proto.TxRequestDetailsType(request_index=0)), proto.TxRequest(
proto.TxRequest(request_type=proto.RequestType.TXOUTPUT, details=proto.TxRequestDetailsType(request_index=0)), request_type=proto.RequestType.TXOUTPUT,
proto.TxRequest(request_type=proto.RequestType.TXOUTPUT, details=proto.TxRequestDetailsType(request_index=1)), details=proto.TxRequestDetailsType(request_index=0),
proto.TxRequest(request_type=proto.RequestType.TXFINISHED), ),
]) proto.TxRequest(
(signatures, serialized_tx) = btc.sign_tx(self.client, 'Bgold', [inp1], [out1, out2]) request_type=proto.RequestType.TXOUTPUT,
details=proto.TxRequestDetailsType(request_index=1),
),
proto.ButtonRequest(code=proto.ButtonRequestType.ConfirmOutput),
proto.ButtonRequest(code=proto.ButtonRequestType.SignTx),
proto.TxRequest(
request_type=proto.RequestType.TXINPUT,
details=proto.TxRequestDetailsType(request_index=0),
),
proto.TxRequest(
request_type=proto.RequestType.TXOUTPUT,
details=proto.TxRequestDetailsType(request_index=0),
),
proto.TxRequest(
request_type=proto.RequestType.TXOUTPUT,
details=proto.TxRequestDetailsType(request_index=1),
),
proto.TxRequest(request_type=proto.RequestType.TXFINISHED),
]
)
(signatures, serialized_tx) = btc.sign_tx(
self.client, "Bgold", [inp1], [out1, out2]
)
assert hexlify(serialized_tx) == b'010000000185c9dd4ae1071affd77d90b9d03c1b5fdd7c62cf30a9bb8230ad766cf06b5225000000006b483045022100963904da0731b71ce468afd45366dd80fbff566ec0d39c1161ab85d17459c7ca02202f5c24a7a7272d98b14a3f5bc000c7cde8ac0eb773f20f4c3131518186cc98854121023bd0ec4022d12d0106c5b7308a25572953ba1951f576f691354a7b147ee0cc1fffffffff0272ee1c00000000001976a9141c82b9c11f193ad82413caadc0955730572b50ae88acec1e0100000000001976a914ea5f904d195079a350b534db4446433b3cec222e88ac00000000' assert (
hexlify(serialized_tx)
== b"010000000185c9dd4ae1071affd77d90b9d03c1b5fdd7c62cf30a9bb8230ad766cf06b5225000000006b483045022100963904da0731b71ce468afd45366dd80fbff566ec0d39c1161ab85d17459c7ca02202f5c24a7a7272d98b14a3f5bc000c7cde8ac0eb773f20f4c3131518186cc98854121023bd0ec4022d12d0106c5b7308a25572953ba1951f576f691354a7b147ee0cc1fffffffff0272ee1c00000000001976a9141c82b9c11f193ad82413caadc0955730572b50ae88acec1e0100000000001976a914ea5f904d195079a350b534db4446433b3cec222e88ac00000000"
)
def test_send_bitcoin_gold_nochange(self): def test_send_bitcoin_gold_nochange(self):
self.setup_mnemonic_allallall() self.setup_mnemonic_allallall()
@ -72,7 +98,9 @@ class TestMsgSigntxBitcoinGold(TrezorTest):
inp1 = proto.TxInputType( inp1 = proto.TxInputType(
address_n=parse_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,
) )
@ -80,30 +108,57 @@ class TestMsgSigntxBitcoinGold(TrezorTest):
address_n=parse_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"
),
prev_index=1, prev_index=1,
script_type=proto.InputScriptType.SPENDADDRESS, script_type=proto.InputScriptType.SPENDADDRESS,
) )
out1 = proto.TxOutputType( out1 = proto.TxOutputType(
address='GfDB1tvjfm3bukeoBTtfNqrJVFohS2kCTe', address="GfDB1tvjfm3bukeoBTtfNqrJVFohS2kCTe",
amount=1934960, amount=1934960,
script_type=proto.OutputScriptType.PAYTOADDRESS, script_type=proto.OutputScriptType.PAYTOADDRESS,
) )
with self.client: with self.client:
self.client.set_expected_responses([ self.client.set_expected_responses(
proto.TxRequest(request_type=proto.RequestType.TXINPUT, details=proto.TxRequestDetailsType(request_index=0)), [
proto.TxRequest(request_type=proto.RequestType.TXINPUT, details=proto.TxRequestDetailsType(request_index=1)), proto.TxRequest(
proto.TxRequest(request_type=proto.RequestType.TXOUTPUT, details=proto.TxRequestDetailsType(request_index=0)), request_type=proto.RequestType.TXINPUT,
proto.ButtonRequest(code=proto.ButtonRequestType.ConfirmOutput), details=proto.TxRequestDetailsType(request_index=0),
proto.ButtonRequest(code=proto.ButtonRequestType.SignTx), ),
proto.TxRequest(request_type=proto.RequestType.TXINPUT, details=proto.TxRequestDetailsType(request_index=0)), proto.TxRequest(
proto.TxRequest(request_type=proto.RequestType.TXINPUT, details=proto.TxRequestDetailsType(request_index=1)), request_type=proto.RequestType.TXINPUT,
proto.TxRequest(request_type=proto.RequestType.TXOUTPUT, details=proto.TxRequestDetailsType(request_index=0)), details=proto.TxRequestDetailsType(request_index=1),
proto.TxRequest(request_type=proto.RequestType.TXFINISHED), ),
]) proto.TxRequest(
(signatures, serialized_tx) = btc.sign_tx(self.client, 'Bgold', [inp1, inp2], [out1]) request_type=proto.RequestType.TXOUTPUT,
details=proto.TxRequestDetailsType(request_index=0),
),
proto.ButtonRequest(code=proto.ButtonRequestType.ConfirmOutput),
proto.ButtonRequest(code=proto.ButtonRequestType.SignTx),
proto.TxRequest(
request_type=proto.RequestType.TXINPUT,
details=proto.TxRequestDetailsType(request_index=0),
),
proto.TxRequest(
request_type=proto.RequestType.TXINPUT,
details=proto.TxRequestDetailsType(request_index=1),
),
proto.TxRequest(
request_type=proto.RequestType.TXOUTPUT,
details=proto.TxRequestDetailsType(request_index=0),
),
proto.TxRequest(request_type=proto.RequestType.TXFINISHED),
]
)
(signatures, serialized_tx) = btc.sign_tx(
self.client, "Bgold", [inp1, inp2], [out1]
)
assert hexlify(serialized_tx) == b'010000000285c9dd4ae1071affd77d90b9d03c1b5fdd7c62cf30a9bb8230ad766cf06b5225000000006b483045022100928852076c9fab160c07564cd54691af1cbc37fb28f0b7bee7299c7925ef62f0022058856387afecc6508f2f04ecdfd292a13026a5b2107ebdd2cc789bdf8820d552412102a6c3998d0d4e5197ff41aab5c53580253b3b91f583f4c31f7624be7dc83ce15fffffffff18fba85125ef7ccb651b5c79d920e0984a18430028f9e7db6e0e841b46c277db010000006b483045022100faa2f4f01cc95e680349a093923aae0aa2ea01429873555aa8a84bf630ef33a002204c3f4bf567e2d20540c0f71dc278481d6ccb6b95acda2a2f87ce521c79d6b872412102d54a7e5733b1635e5e9442943f48179b1700206b2d1925250ba10f1c86878be8ffffffff0170861d00000000001976a914ea5f904d195079a350b534db4446433b3cec222e88ac00000000' assert (
hexlify(serialized_tx)
== b"010000000285c9dd4ae1071affd77d90b9d03c1b5fdd7c62cf30a9bb8230ad766cf06b5225000000006b483045022100928852076c9fab160c07564cd54691af1cbc37fb28f0b7bee7299c7925ef62f0022058856387afecc6508f2f04ecdfd292a13026a5b2107ebdd2cc789bdf8820d552412102a6c3998d0d4e5197ff41aab5c53580253b3b91f583f4c31f7624be7dc83ce15fffffffff18fba85125ef7ccb651b5c79d920e0984a18430028f9e7db6e0e841b46c277db010000006b483045022100faa2f4f01cc95e680349a093923aae0aa2ea01429873555aa8a84bf630ef33a002204c3f4bf567e2d20540c0f71dc278481d6ccb6b95acda2a2f87ce521c79d6b872412102d54a7e5733b1635e5e9442943f48179b1700206b2d1925250ba10f1c86878be8ffffffff0170861d00000000001976a914ea5f904d195079a350b534db4446433b3cec222e88ac00000000"
)
def test_attack_change_input(self): def test_attack_change_input(self):
self.setup_mnemonic_allallall() self.setup_mnemonic_allallall()
@ -112,7 +167,9 @@ class TestMsgSigntxBitcoinGold(TrezorTest):
address_n=parse_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"
),
prev_index=0, prev_index=0,
script_type=proto.InputScriptType.SPENDADDRESS, script_type=proto.InputScriptType.SPENDADDRESS,
) )
@ -122,7 +179,7 @@ class TestMsgSigntxBitcoinGold(TrezorTest):
script_type=proto.OutputScriptType.PAYTOADDRESS, script_type=proto.OutputScriptType.PAYTOADDRESS,
) )
out2 = proto.TxOutputType( out2 = proto.TxOutputType(
address='GfDB1tvjfm3bukeoBTtfNqrJVFohS2kCTe', address="GfDB1tvjfm3bukeoBTtfNqrJVFohS2kCTe",
amount=73452, amount=73452,
script_type=proto.OutputScriptType.PAYTOADDRESS, script_type=proto.OutputScriptType.PAYTOADDRESS,
) )
@ -147,42 +204,77 @@ class TestMsgSigntxBitcoinGold(TrezorTest):
return msg return msg
with self.client: with self.client:
self.client.set_expected_responses([ self.client.set_expected_responses(
proto.TxRequest(request_type=proto.RequestType.TXINPUT, details=proto.TxRequestDetailsType(request_index=0)), [
proto.TxRequest(request_type=proto.RequestType.TXOUTPUT, details=proto.TxRequestDetailsType(request_index=0)), proto.TxRequest(
proto.TxRequest(request_type=proto.RequestType.TXOUTPUT, details=proto.TxRequestDetailsType(request_index=1)), request_type=proto.RequestType.TXINPUT,
proto.ButtonRequest(code=proto.ButtonRequestType.ConfirmOutput), details=proto.TxRequestDetailsType(request_index=0),
proto.ButtonRequest(code=proto.ButtonRequestType.SignTx), ),
proto.TxRequest(request_type=proto.RequestType.TXINPUT, details=proto.TxRequestDetailsType(request_index=0)), proto.TxRequest(
proto.Failure(code=proto.FailureType.ProcessError), request_type=proto.RequestType.TXOUTPUT,
]) details=proto.TxRequestDetailsType(request_index=0),
),
proto.TxRequest(
request_type=proto.RequestType.TXOUTPUT,
details=proto.TxRequestDetailsType(request_index=1),
),
proto.ButtonRequest(code=proto.ButtonRequestType.ConfirmOutput),
proto.ButtonRequest(code=proto.ButtonRequestType.SignTx),
proto.TxRequest(
request_type=proto.RequestType.TXINPUT,
details=proto.TxRequestDetailsType(request_index=0),
),
proto.Failure(code=proto.FailureType.ProcessError),
]
)
with pytest.raises(CallException): with pytest.raises(CallException):
btc.sign_tx(self.client, 'Bgold', [inp1], [out1, out2], debug_processor=attack_processor) btc.sign_tx(
self.client,
"Bgold",
[inp1],
[out1, out2],
debug_processor=attack_processor,
)
def test_send_bch_multisig_change(self): def test_send_bch_multisig_change(self):
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: btc.get_public_node(self.client, parse_path("44'/156'/" + str(index) + "'")), range(1, 4)): for n in map(
lambda index: btc.get_public_node(
self.client, 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):
return proto.MultisigRedeemScriptType( return proto.MultisigRedeemScriptType(
pubkeys=list(map(lambda xpub: proto.HDNodePathType(node=deserialize(xpub), address_n=[chain, nr]), xpubs)), pubkeys=list(
map(
lambda xpub: proto.HDNodePathType(
node=deserialize(xpub), address_n=[chain, nr]
),
xpubs,
)
),
signatures=signatures, signatures=signatures,
m=2, m=2,
) )
inp1 = proto.TxInputType( inp1 = proto.TxInputType(
address_n=parse_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,
prev_hash=unhexlify('25526bf06c76ad3082bba930cf627cdd5f1b3cd0b9907dd7ff1a07e14addc985'), prev_hash=unhexlify(
"25526bf06c76ad3082bba930cf627cdd5f1b3cd0b9907dd7ff1a07e14addc985"
),
prev_index=0, prev_index=0,
script_type=proto.InputScriptType.SPENDMULTISIG, script_type=proto.InputScriptType.SPENDMULTISIG,
) )
out1 = proto.TxOutputType( out1 = proto.TxOutputType(
address='GfDB1tvjfm3bukeoBTtfNqrJVFohS2kCTe', address="GfDB1tvjfm3bukeoBTtfNqrJVFohS2kCTe",
amount=24000, amount=24000,
script_type=proto.OutputScriptType.PAYTOADDRESS, script_type=proto.OutputScriptType.PAYTOADDRESS,
) )
@ -190,51 +282,106 @@ class TestMsgSigntxBitcoinGold(TrezorTest):
address_n=parse_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,
) )
with self.client: with self.client:
self.client.set_expected_responses([ self.client.set_expected_responses(
proto.TxRequest(request_type=proto.RequestType.TXINPUT, details=proto.TxRequestDetailsType(request_index=0)), [
proto.TxRequest(request_type=proto.RequestType.TXOUTPUT, details=proto.TxRequestDetailsType(request_index=0)), proto.TxRequest(
proto.ButtonRequest(code=proto.ButtonRequestType.ConfirmOutput), request_type=proto.RequestType.TXINPUT,
proto.TxRequest(request_type=proto.RequestType.TXOUTPUT, details=proto.TxRequestDetailsType(request_index=1)), details=proto.TxRequestDetailsType(request_index=0),
proto.ButtonRequest(code=proto.ButtonRequestType.SignTx), ),
proto.TxRequest(request_type=proto.RequestType.TXINPUT, details=proto.TxRequestDetailsType(request_index=0)), proto.TxRequest(
proto.TxRequest(request_type=proto.RequestType.TXOUTPUT, details=proto.TxRequestDetailsType(request_index=0)), request_type=proto.RequestType.TXOUTPUT,
proto.TxRequest(request_type=proto.RequestType.TXOUTPUT, details=proto.TxRequestDetailsType(request_index=1)), details=proto.TxRequestDetailsType(request_index=0),
proto.TxRequest(request_type=proto.RequestType.TXFINISHED), ),
]) proto.ButtonRequest(code=proto.ButtonRequestType.ConfirmOutput),
(signatures1, serialized_tx) = btc.sign_tx(self.client, 'Bgold', [inp1], [out1, out2]) proto.TxRequest(
request_type=proto.RequestType.TXOUTPUT,
details=proto.TxRequestDetailsType(request_index=1),
),
proto.ButtonRequest(code=proto.ButtonRequestType.SignTx),
proto.TxRequest(
request_type=proto.RequestType.TXINPUT,
details=proto.TxRequestDetailsType(request_index=0),
),
proto.TxRequest(
request_type=proto.RequestType.TXOUTPUT,
details=proto.TxRequestDetailsType(request_index=0),
),
proto.TxRequest(
request_type=proto.RequestType.TXOUTPUT,
details=proto.TxRequestDetailsType(request_index=1),
),
proto.TxRequest(request_type=proto.RequestType.TXFINISHED),
]
)
(signatures1, serialized_tx) = btc.sign_tx(
self.client, "Bgold", [inp1], [out1, out2]
)
assert hexlify(signatures1[0]) == b'3045022100b1594f3b186d0dedbf61e53a1c407b1e0747098b7375941df85af045040f578e022013ba1893eb9e2fd854dd07073a83b261cf4beba76f66b07742e462b4088a7e4a' assert (
hexlify(signatures1[0])
== b"3045022100b1594f3b186d0dedbf61e53a1c407b1e0747098b7375941df85af045040f578e022013ba1893eb9e2fd854dd07073a83b261cf4beba76f66b07742e462b4088a7e4a"
)
inp1 = proto.TxInputType( inp1 = proto.TxInputType(
address_n=parse_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,
prev_hash=unhexlify('25526bf06c76ad3082bba930cf627cdd5f1b3cd0b9907dd7ff1a07e14addc985'), prev_hash=unhexlify(
"25526bf06c76ad3082bba930cf627cdd5f1b3cd0b9907dd7ff1a07e14addc985"
),
prev_index=0, prev_index=0,
script_type=proto.InputScriptType.SPENDMULTISIG, script_type=proto.InputScriptType.SPENDMULTISIG,
) )
out2.address_n[2] = H_(1) out2.address_n[2] = H_(1)
with self.client: with self.client:
self.client.set_expected_responses([ self.client.set_expected_responses(
proto.TxRequest(request_type=proto.RequestType.TXINPUT, details=proto.TxRequestDetailsType(request_index=0)), [
proto.TxRequest(request_type=proto.RequestType.TXOUTPUT, details=proto.TxRequestDetailsType(request_index=0)), proto.TxRequest(
proto.ButtonRequest(code=proto.ButtonRequestType.ConfirmOutput), request_type=proto.RequestType.TXINPUT,
proto.TxRequest(request_type=proto.RequestType.TXOUTPUT, details=proto.TxRequestDetailsType(request_index=1)), details=proto.TxRequestDetailsType(request_index=0),
proto.ButtonRequest(code=proto.ButtonRequestType.SignTx), ),
proto.TxRequest(request_type=proto.RequestType.TXINPUT, details=proto.TxRequestDetailsType(request_index=0)), proto.TxRequest(
proto.TxRequest(request_type=proto.RequestType.TXOUTPUT, details=proto.TxRequestDetailsType(request_index=0)), request_type=proto.RequestType.TXOUTPUT,
proto.TxRequest(request_type=proto.RequestType.TXOUTPUT, details=proto.TxRequestDetailsType(request_index=1)), details=proto.TxRequestDetailsType(request_index=0),
proto.TxRequest(request_type=proto.RequestType.TXFINISHED), ),
]) proto.ButtonRequest(code=proto.ButtonRequestType.ConfirmOutput),
(signatures1, serialized_tx) = btc.sign_tx(self.client, 'Bgold', [inp1], [out1, out2]) proto.TxRequest(
request_type=proto.RequestType.TXOUTPUT,
details=proto.TxRequestDetailsType(request_index=1),
),
proto.ButtonRequest(code=proto.ButtonRequestType.SignTx),
proto.TxRequest(
request_type=proto.RequestType.TXINPUT,
details=proto.TxRequestDetailsType(request_index=0),
),
proto.TxRequest(
request_type=proto.RequestType.TXOUTPUT,
details=proto.TxRequestDetailsType(request_index=0),
),
proto.TxRequest(
request_type=proto.RequestType.TXOUTPUT,
details=proto.TxRequestDetailsType(request_index=1),
),
proto.TxRequest(request_type=proto.RequestType.TXFINISHED),
]
)
(signatures1, serialized_tx) = btc.sign_tx(
self.client, "Bgold", [inp1], [out1, out2]
)
assert hexlify(signatures1[0]) == b'3044022006da8dbd14e6656ac8dcb956f4c0498574e88680eaeceb2cbafd8d2b2329d8cc02200972d076d444c5ff8f2ab18e14d8249ab661cb9c53335039bedcde037a40d747' assert (
assert hexlify(serialized_tx) == b'010000000185c9dd4ae1071affd77d90b9d03c1b5fdd7c62cf30a9bb8230ad766cf06b522500000000fdfd0000473044022006da8dbd14e6656ac8dcb956f4c0498574e88680eaeceb2cbafd8d2b2329d8cc02200972d076d444c5ff8f2ab18e14d8249ab661cb9c53335039bedcde037a40d74741483045022100b1594f3b186d0dedbf61e53a1c407b1e0747098b7375941df85af045040f578e022013ba1893eb9e2fd854dd07073a83b261cf4beba76f66b07742e462b4088a7e4a414c69522102290e6649574d17938c1ecb959ae92954f9ee48e1bd5b73f35ea931a3ab8a6087210379e0107b173e2c143426760627128c5eea3f862e8df92f3c2558eeeae4e347842103ff1746ca7dcf9e5c2eea9a73779b7c5bafed549f45cf3638a94cdf1e89c7f28f53aeffffffff02c05d0000000000001976a914ea5f904d195079a350b534db4446433b3cec222e88acc05d00000000000017a91445e917e46815d2b38d3f1cf072e63dd4f3b7a7e38700000000' hexlify(signatures1[0])
== b"3044022006da8dbd14e6656ac8dcb956f4c0498574e88680eaeceb2cbafd8d2b2329d8cc02200972d076d444c5ff8f2ab18e14d8249ab661cb9c53335039bedcde037a40d747"
)
assert (
hexlify(serialized_tx)
== b"010000000185c9dd4ae1071affd77d90b9d03c1b5fdd7c62cf30a9bb8230ad766cf06b522500000000fdfd0000473044022006da8dbd14e6656ac8dcb956f4c0498574e88680eaeceb2cbafd8d2b2329d8cc02200972d076d444c5ff8f2ab18e14d8249ab661cb9c53335039bedcde037a40d74741483045022100b1594f3b186d0dedbf61e53a1c407b1e0747098b7375941df85af045040f578e022013ba1893eb9e2fd854dd07073a83b261cf4beba76f66b07742e462b4088a7e4a414c69522102290e6649574d17938c1ecb959ae92954f9ee48e1bd5b73f35ea931a3ab8a6087210379e0107b173e2c143426760627128c5eea3f862e8df92f3c2558eeeae4e347842103ff1746ca7dcf9e5c2eea9a73779b7c5bafed549f45cf3638a94cdf1e89c7f28f53aeffffffff02c05d0000000000001976a914ea5f904d195079a350b534db4446433b3cec222e88acc05d00000000000017a91445e917e46815d2b38d3f1cf072e63dd4f3b7a7e38700000000"
)
def test_send_p2sh(self): def test_send_p2sh(self):
self.setup_mnemonic_allallall() self.setup_mnemonic_allallall()
@ -242,37 +389,67 @@ class TestMsgSigntxBitcoinGold(TrezorTest):
inp1 = proto.TxInputType( inp1 = proto.TxInputType(
address_n=parse_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,
script_type=proto.InputScriptType.SPENDP2SHWITNESS, script_type=proto.InputScriptType.SPENDP2SHWITNESS,
) )
out1 = proto.TxOutputType( out1 = proto.TxOutputType(
address='GfDB1tvjfm3bukeoBTtfNqrJVFohS2kCTe', address="GfDB1tvjfm3bukeoBTtfNqrJVFohS2kCTe",
amount=12300000, amount=12300000,
script_type=proto.OutputScriptType.PAYTOADDRESS, script_type=proto.OutputScriptType.PAYTOADDRESS,
) )
out2 = proto.TxOutputType( out2 = proto.TxOutputType(
address='GZFLExxrvWFuFT1xRzhfwQWSE2bPDedBfn', address="GZFLExxrvWFuFT1xRzhfwQWSE2bPDedBfn",
script_type=proto.OutputScriptType.PAYTOADDRESS, script_type=proto.OutputScriptType.PAYTOADDRESS,
amount=123456789 - 11000 - 12300000, amount=123456789 - 11000 - 12300000,
) )
with self.client: with self.client:
self.client.set_expected_responses([ self.client.set_expected_responses(
proto.TxRequest(request_type=proto.RequestType.TXINPUT, details=proto.TxRequestDetailsType(request_index=0)), [
proto.TxRequest(request_type=proto.RequestType.TXOUTPUT, details=proto.TxRequestDetailsType(request_index=0)), proto.TxRequest(
proto.ButtonRequest(code=proto.ButtonRequestType.ConfirmOutput), request_type=proto.RequestType.TXINPUT,
proto.TxRequest(request_type=proto.RequestType.TXOUTPUT, details=proto.TxRequestDetailsType(request_index=1)), details=proto.TxRequestDetailsType(request_index=0),
proto.ButtonRequest(code=proto.ButtonRequestType.ConfirmOutput), ),
proto.ButtonRequest(code=proto.ButtonRequestType.SignTx), proto.TxRequest(
proto.TxRequest(request_type=proto.RequestType.TXINPUT, details=proto.TxRequestDetailsType(request_index=0)), request_type=proto.RequestType.TXOUTPUT,
proto.TxRequest(request_type=proto.RequestType.TXOUTPUT, details=proto.TxRequestDetailsType(request_index=0)), details=proto.TxRequestDetailsType(request_index=0),
proto.TxRequest(request_type=proto.RequestType.TXOUTPUT, details=proto.TxRequestDetailsType(request_index=1)), ),
proto.TxRequest(request_type=proto.RequestType.TXINPUT, details=proto.TxRequestDetailsType(request_index=0)), proto.ButtonRequest(code=proto.ButtonRequestType.ConfirmOutput),
proto.TxRequest(request_type=proto.RequestType.TXFINISHED), proto.TxRequest(
]) request_type=proto.RequestType.TXOUTPUT,
(signatures, serialized_tx) = btc.sign_tx(self.client, 'Bgold', [inp1], [out1, out2]) details=proto.TxRequestDetailsType(request_index=1),
),
proto.ButtonRequest(code=proto.ButtonRequestType.ConfirmOutput),
proto.ButtonRequest(code=proto.ButtonRequestType.SignTx),
proto.TxRequest(
request_type=proto.RequestType.TXINPUT,
details=proto.TxRequestDetailsType(request_index=0),
),
proto.TxRequest(
request_type=proto.RequestType.TXOUTPUT,
details=proto.TxRequestDetailsType(request_index=0),
),
proto.TxRequest(
request_type=proto.RequestType.TXOUTPUT,
details=proto.TxRequestDetailsType(request_index=1),
),
proto.TxRequest(
request_type=proto.RequestType.TXINPUT,
details=proto.TxRequestDetailsType(request_index=0),
),
proto.TxRequest(request_type=proto.RequestType.TXFINISHED),
]
)
(signatures, serialized_tx) = btc.sign_tx(
self.client, "Bgold", [inp1], [out1, out2]
)
assert hexlify(serialized_tx) == b'0100000000010185c9dd4ae1071affd77d90b9d03c1b5fdd7c62cf30a9bb8230ad766cf06b52250000000017160014b5355d001e720d8f4513da00ff2bba4dcf9d39fcffffffff02e0aebb00000000001976a914ea5f904d195079a350b534db4446433b3cec222e88ac3df39f06000000001976a914a8f757819ec6779409f45788f7b4a0e8f51ec50488ac02473044022073fcbf2876f073f78923ab427f14de5b2a0fbeb313a9b2b650b3567061f242a702202f45fc22c501108ff6222afe3aca7da9d8c7dc860f9cda335bef31fa184e7bef412102ecea08b559fc5abd009acf77cfae13fa8a3b1933e3e031956c65c12cec8ca3e300000000' assert (
hexlify(serialized_tx)
== b"0100000000010185c9dd4ae1071affd77d90b9d03c1b5fdd7c62cf30a9bb8230ad766cf06b52250000000017160014b5355d001e720d8f4513da00ff2bba4dcf9d39fcffffffff02e0aebb00000000001976a914ea5f904d195079a350b534db4446433b3cec222e88ac3df39f06000000001976a914a8f757819ec6779409f45788f7b4a0e8f51ec50488ac02473044022073fcbf2876f073f78923ab427f14de5b2a0fbeb313a9b2b650b3567061f242a702202f45fc22c501108ff6222afe3aca7da9d8c7dc860f9cda335bef31fa184e7bef412102ecea08b559fc5abd009acf77cfae13fa8a3b1933e3e031956c65c12cec8ca3e300000000"
)
def test_send_p2sh_witness_change(self): def test_send_p2sh_witness_change(self):
self.setup_mnemonic_allallall() self.setup_mnemonic_allallall()
@ -280,12 +457,14 @@ class TestMsgSigntxBitcoinGold(TrezorTest):
inp1 = proto.TxInputType( inp1 = proto.TxInputType(
address_n=parse_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,
script_type=proto.InputScriptType.SPENDP2SHWITNESS, script_type=proto.InputScriptType.SPENDP2SHWITNESS,
) )
out1 = proto.TxOutputType( out1 = proto.TxOutputType(
address='GfDB1tvjfm3bukeoBTtfNqrJVFohS2kCTe', address="GfDB1tvjfm3bukeoBTtfNqrJVFohS2kCTe",
amount=12300000, amount=12300000,
script_type=proto.OutputScriptType.PAYTOADDRESS, script_type=proto.OutputScriptType.PAYTOADDRESS,
) )
@ -295,73 +474,156 @@ class TestMsgSigntxBitcoinGold(TrezorTest):
amount=123456789 - 11000 - 12300000, amount=123456789 - 11000 - 12300000,
) )
with self.client: with self.client:
self.client.set_expected_responses([ self.client.set_expected_responses(
proto.TxRequest(request_type=proto.RequestType.TXINPUT, details=proto.TxRequestDetailsType(request_index=0)), [
proto.TxRequest(request_type=proto.RequestType.TXOUTPUT, details=proto.TxRequestDetailsType(request_index=0)), proto.TxRequest(
proto.ButtonRequest(code=proto.ButtonRequestType.ConfirmOutput), request_type=proto.RequestType.TXINPUT,
proto.TxRequest(request_type=proto.RequestType.TXOUTPUT, details=proto.TxRequestDetailsType(request_index=1)), details=proto.TxRequestDetailsType(request_index=0),
proto.ButtonRequest(code=proto.ButtonRequestType.SignTx), ),
proto.TxRequest(request_type=proto.RequestType.TXINPUT, details=proto.TxRequestDetailsType(request_index=0)), proto.TxRequest(
proto.TxRequest(request_type=proto.RequestType.TXOUTPUT, details=proto.TxRequestDetailsType(request_index=0)), request_type=proto.RequestType.TXOUTPUT,
proto.TxRequest(request_type=proto.RequestType.TXOUTPUT, details=proto.TxRequestDetailsType(request_index=1)), details=proto.TxRequestDetailsType(request_index=0),
proto.TxRequest(request_type=proto.RequestType.TXINPUT, details=proto.TxRequestDetailsType(request_index=0)), ),
proto.TxRequest(request_type=proto.RequestType.TXFINISHED), proto.ButtonRequest(code=proto.ButtonRequestType.ConfirmOutput),
]) proto.TxRequest(
(signatures, serialized_tx) = btc.sign_tx(self.client, 'Bgold', [inp1], [out1, out2]) request_type=proto.RequestType.TXOUTPUT,
details=proto.TxRequestDetailsType(request_index=1),
),
proto.ButtonRequest(code=proto.ButtonRequestType.SignTx),
proto.TxRequest(
request_type=proto.RequestType.TXINPUT,
details=proto.TxRequestDetailsType(request_index=0),
),
proto.TxRequest(
request_type=proto.RequestType.TXOUTPUT,
details=proto.TxRequestDetailsType(request_index=0),
),
proto.TxRequest(
request_type=proto.RequestType.TXOUTPUT,
details=proto.TxRequestDetailsType(request_index=1),
),
proto.TxRequest(
request_type=proto.RequestType.TXINPUT,
details=proto.TxRequestDetailsType(request_index=0),
),
proto.TxRequest(request_type=proto.RequestType.TXFINISHED),
]
)
(signatures, serialized_tx) = btc.sign_tx(
self.client, "Bgold", [inp1], [out1, out2]
)
# print(hexlify(serialized_tx)) # print(hexlify(serialized_tx))
# assert False # assert False
assert hexlify(serialized_tx) == b'0100000000010185c9dd4ae1071affd77d90b9d03c1b5fdd7c62cf30a9bb8230ad766cf06b52250000000017160014b5355d001e720d8f4513da00ff2bba4dcf9d39fcffffffff02e0aebb00000000001976a914ea5f904d195079a350b534db4446433b3cec222e88ac3df39f060000000017a9140cd03822b799a452c106d1b3771844a067b17f118702483045022100d79b33384c686d8dd40ad5f84f46691d30994992c1cb42e934c2a625d86cb2f902206859805a9a98ba140b71a9d4b9a6b8df94a9424f9c40f3bd804149fd6e278d63412102ecea08b559fc5abd009acf77cfae13fa8a3b1933e3e031956c65c12cec8ca3e300000000' assert (
hexlify(serialized_tx)
== b"0100000000010185c9dd4ae1071affd77d90b9d03c1b5fdd7c62cf30a9bb8230ad766cf06b52250000000017160014b5355d001e720d8f4513da00ff2bba4dcf9d39fcffffffff02e0aebb00000000001976a914ea5f904d195079a350b534db4446433b3cec222e88ac3df39f060000000017a9140cd03822b799a452c106d1b3771844a067b17f118702483045022100d79b33384c686d8dd40ad5f84f46691d30994992c1cb42e934c2a625d86cb2f902206859805a9a98ba140b71a9d4b9a6b8df94a9424f9c40f3bd804149fd6e278d63412102ecea08b559fc5abd009acf77cfae13fa8a3b1933e3e031956c65c12cec8ca3e300000000"
)
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: btc.get_public_node(self.client, parse_path("999'/1'/%d'" % index)), range(1, 4)) nodes = map(
lambda index: btc.get_public_node(
self.client, 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(
signatures=[b'', b'', b''], map(
lambda n: proto.HDNodePathType(
node=deserialize(n.xpub), address_n=[2, 0]
),
nodes,
)
),
signatures=[b"", b"", b""],
m=2, m=2,
) )
inp1 = proto.TxInputType( inp1 = proto.TxInputType(
address_n=parse_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,
multisig=multisig, multisig=multisig,
amount=1610436 amount=1610436,
) )
out1 = proto.TxOutputType(address='GfDB1tvjfm3bukeoBTtfNqrJVFohS2kCTe', out1 = proto.TxOutputType(
amount=1605000, address="GfDB1tvjfm3bukeoBTtfNqrJVFohS2kCTe",
script_type=proto.OutputScriptType.PAYTOADDRESS) amount=1605000,
script_type=proto.OutputScriptType.PAYTOADDRESS,
)
with self.client: with self.client:
self.client.set_expected_responses([ self.client.set_expected_responses(
proto.TxRequest(request_type=proto.RequestType.TXINPUT, details=proto.TxRequestDetailsType(request_index=0)), [
proto.TxRequest(request_type=proto.RequestType.TXOUTPUT, details=proto.TxRequestDetailsType(request_index=0)), proto.TxRequest(
proto.ButtonRequest(code=proto.ButtonRequestType.ConfirmOutput), request_type=proto.RequestType.TXINPUT,
proto.ButtonRequest(code=proto.ButtonRequestType.SignTx), details=proto.TxRequestDetailsType(request_index=0),
proto.TxRequest(request_type=proto.RequestType.TXINPUT, details=proto.TxRequestDetailsType(request_index=0)), ),
proto.TxRequest(request_type=proto.RequestType.TXOUTPUT, details=proto.TxRequestDetailsType(request_index=0)), proto.TxRequest(
proto.TxRequest(request_type=proto.RequestType.TXINPUT, details=proto.TxRequestDetailsType(request_index=0)), request_type=proto.RequestType.TXOUTPUT,
proto.TxRequest(request_type=proto.RequestType.TXFINISHED), details=proto.TxRequestDetailsType(request_index=0),
]) ),
(signatures1, _) = btc.sign_tx(self.client, 'Bgold', [inp1], [out1]) proto.ButtonRequest(code=proto.ButtonRequestType.ConfirmOutput),
proto.ButtonRequest(code=proto.ButtonRequestType.SignTx),
proto.TxRequest(
request_type=proto.RequestType.TXINPUT,
details=proto.TxRequestDetailsType(request_index=0),
),
proto.TxRequest(
request_type=proto.RequestType.TXOUTPUT,
details=proto.TxRequestDetailsType(request_index=0),
),
proto.TxRequest(
request_type=proto.RequestType.TXINPUT,
details=proto.TxRequestDetailsType(request_index=0),
),
proto.TxRequest(request_type=proto.RequestType.TXFINISHED),
]
)
(signatures1, _) = btc.sign_tx(self.client, "Bgold", [inp1], [out1])
# store signature # store signature
inp1.multisig.signatures[0] = signatures1[0] inp1.multisig.signatures[0] = signatures1[0]
# sign with third key # sign with third key
inp1.address_n[2] = H_(3) inp1.address_n[2] = H_(3)
self.client.set_expected_responses([ self.client.set_expected_responses(
proto.TxRequest(request_type=proto.RequestType.TXINPUT, details=proto.TxRequestDetailsType(request_index=0)), [
proto.TxRequest(request_type=proto.RequestType.TXOUTPUT, details=proto.TxRequestDetailsType(request_index=0)), proto.TxRequest(
proto.ButtonRequest(code=proto.ButtonRequestType.ConfirmOutput), request_type=proto.RequestType.TXINPUT,
proto.ButtonRequest(code=proto.ButtonRequestType.SignTx), details=proto.TxRequestDetailsType(request_index=0),
proto.TxRequest(request_type=proto.RequestType.TXINPUT, details=proto.TxRequestDetailsType(request_index=0)), ),
proto.TxRequest(request_type=proto.RequestType.TXOUTPUT, details=proto.TxRequestDetailsType(request_index=0)), proto.TxRequest(
proto.TxRequest(request_type=proto.RequestType.TXINPUT, details=proto.TxRequestDetailsType(request_index=0)), request_type=proto.RequestType.TXOUTPUT,
proto.TxRequest(request_type=proto.RequestType.TXFINISHED), details=proto.TxRequestDetailsType(request_index=0),
]) ),
(signatures2, serialized_tx) = btc.sign_tx(self.client, 'Bgold', [inp1], [out1]) proto.ButtonRequest(code=proto.ButtonRequestType.ConfirmOutput),
proto.ButtonRequest(code=proto.ButtonRequestType.SignTx),
proto.TxRequest(
request_type=proto.RequestType.TXINPUT,
details=proto.TxRequestDetailsType(request_index=0),
),
proto.TxRequest(
request_type=proto.RequestType.TXOUTPUT,
details=proto.TxRequestDetailsType(request_index=0),
),
proto.TxRequest(
request_type=proto.RequestType.TXINPUT,
details=proto.TxRequestDetailsType(request_index=0),
),
proto.TxRequest(request_type=proto.RequestType.TXFINISHED),
]
)
(signatures2, serialized_tx) = btc.sign_tx(
self.client, "Bgold", [inp1], [out1]
)
assert hexlify(serialized_tx) == b'0100000000010185c9dd4ae1071affd77d90b9d03c1b5fdd7c62cf30a9bb8230ad766cf06b522501000000232200201e8dda334f11171190b3da72e526d441491464769679a319a2f011da5ad312a1ffffffff01887d1800000000001976a914ea5f904d195079a350b534db4446433b3cec222e88ac0400483045022100e728485c8337f9a09ebbf36edc0fef10f8bcf5c1ba601b7d8ba43a9250a898f002206b9e3401c297f9ab9afb7f1be59bb342db53b5b65aff7c557e3109679697df0f41473044022062ea69ecdc07d0dadc1971fbda50a629a56dd30f431db26327428f4992601ce602204a1c8ab9c7d81c36cb6f819109a26f9baaa9607b8d37bff5e24eee6fab4a04e441695221038e81669c085a5846e68e03875113ddb339ecbb7cb11376d4163bca5dc2e2a0c1210348c5c3be9f0e6cf1954ded1c0475beccc4d26aaa9d0cce2dd902538ff1018a112103931140ebe0fbbb7df0be04ed032a54e9589e30339ba7bbb8b0b71b15df1294da53ae00000000' assert (
hexlify(serialized_tx)
== b"0100000000010185c9dd4ae1071affd77d90b9d03c1b5fdd7c62cf30a9bb8230ad766cf06b522501000000232200201e8dda334f11171190b3da72e526d441491464769679a319a2f011da5ad312a1ffffffff01887d1800000000001976a914ea5f904d195079a350b534db4446433b3cec222e88ac0400483045022100e728485c8337f9a09ebbf36edc0fef10f8bcf5c1ba601b7d8ba43a9250a898f002206b9e3401c297f9ab9afb7f1be59bb342db53b5b65aff7c557e3109679697df0f41473044022062ea69ecdc07d0dadc1971fbda50a629a56dd30f431db26327428f4992601ce602204a1c8ab9c7d81c36cb6f819109a26f9baaa9607b8d37bff5e24eee6fab4a04e441695221038e81669c085a5846e68e03875113ddb339ecbb7cb11376d4163bca5dc2e2a0c1210348c5c3be9f0e6cf1954ded1c0475beccc4d26aaa9d0cce2dd902538ff1018a112103931140ebe0fbbb7df0be04ed032a54e9589e30339ba7bbb8b0b71b15df1294da53ae00000000"
)

View File

@ -15,30 +15,40 @@
# If not, see <https://www.gnu.org/licenses/lgpl-3.0.html>. # If not, see <https://www.gnu.org/licenses/lgpl-3.0.html>.
from binascii import unhexlify from binascii import unhexlify
import pytest import pytest
from trezorlib import btc, coins, messages as proto
from trezorlib.tools import parse_path
from .common import TrezorTest from .common import TrezorTest
from trezorlib import coins TxApiDecredTestnet = coins.tx_api["Decred Testnet"]
from trezorlib import messages as proto
from trezorlib.tools import parse_path
from trezorlib import btc
TxApiDecredTestnet = coins.tx_api['Decred Testnet']
TXHASH_e16248 = unhexlify("e16248f0b39a0a0c0e53d6f2f84c2a944f0d50e017a82701e8e02e46e979d5ed") TXHASH_e16248 = unhexlify(
TXHASH_5e6e35 = unhexlify("5e6e3500a333c53c02f523db5f1a9b17538a8850b4c2c24ecb9b7ba48059b970") "e16248f0b39a0a0c0e53d6f2f84c2a944f0d50e017a82701e8e02e46e979d5ed"
TXHASH_ccf95b = unhexlify("ccf95b0fd220ef59ae2e5b17005a81e222758122682d522eff8ae1fcbc93bc74") )
TXHASH_f395ef = unhexlify("f395ef3e72a831a766db15e7a38bc28025d4ee02234d68bdea2d8353b47a3113") TXHASH_5e6e35 = unhexlify(
TXHASH_3f7c39 = unhexlify("3f7c395521d38387e7617565fe17628723ef6635a08537ad9c46cfb1619e4c3f") "5e6e3500a333c53c02f523db5f1a9b17538a8850b4c2c24ecb9b7ba48059b970"
TXHASH_16da18 = unhexlify("16da185052740d85a630e79c140558215b64e26c500212b90e16b55d13ca06a8") )
TXHASH_ccf95b = unhexlify(
"ccf95b0fd220ef59ae2e5b17005a81e222758122682d522eff8ae1fcbc93bc74"
)
TXHASH_f395ef = unhexlify(
"f395ef3e72a831a766db15e7a38bc28025d4ee02234d68bdea2d8353b47a3113"
)
TXHASH_3f7c39 = unhexlify(
"3f7c395521d38387e7617565fe17628723ef6635a08537ad9c46cfb1619e4c3f"
)
TXHASH_16da18 = unhexlify(
"16da185052740d85a630e79c140558215b64e26c500212b90e16b55d13ca06a8"
)
@pytest.mark.skip_t2 @pytest.mark.skip_t2
@pytest.mark.decred @pytest.mark.decred
class TestMsgSigntxDecred(TrezorTest): class TestMsgSigntxDecred(TrezorTest):
def test_send_decred(self): def test_send_decred(self):
self.setup_mnemonic_allallall() self.setup_mnemonic_allallall()
self.client.set_tx_api(TxApiDecredTestnet) self.client.set_tx_api(TxApiDecredTestnet)
@ -60,23 +70,56 @@ class TestMsgSigntxDecred(TrezorTest):
) )
with self.client: with self.client:
self.client.set_expected_responses([ self.client.set_expected_responses(
proto.TxRequest(request_type=proto.RequestType.TXINPUT, details=proto.TxRequestDetailsType(request_index=0)), [
proto.TxRequest(request_type=proto.RequestType.TXMETA, details=proto.TxRequestDetailsType(tx_hash=TXHASH_e16248)), proto.TxRequest(
proto.TxRequest(request_type=proto.RequestType.TXINPUT, details=proto.TxRequestDetailsType(tx_hash=TXHASH_e16248, request_index=0)), request_type=proto.RequestType.TXINPUT,
proto.TxRequest(request_type=proto.RequestType.TXOUTPUT, details=proto.TxRequestDetailsType(tx_hash=TXHASH_e16248, request_index=0)), details=proto.TxRequestDetailsType(request_index=0),
proto.TxRequest(request_type=proto.RequestType.TXOUTPUT, details=proto.TxRequestDetailsType(tx_hash=TXHASH_e16248, request_index=1)), ),
proto.TxRequest(request_type=proto.RequestType.TXOUTPUT, details=proto.TxRequestDetailsType(request_index=0)), proto.TxRequest(
proto.ButtonRequest(code=proto.ButtonRequestType.ConfirmOutput), request_type=proto.RequestType.TXMETA,
proto.ButtonRequest(code=proto.ButtonRequestType.FeeOverThreshold), details=proto.TxRequestDetailsType(tx_hash=TXHASH_e16248),
proto.ButtonRequest(code=proto.ButtonRequestType.SignTx), ),
proto.TxRequest(request_type=proto.RequestType.TXINPUT, details=proto.TxRequestDetailsType(request_index=0)), proto.TxRequest(
proto.TxRequest(request_type=proto.RequestType.TXFINISHED), request_type=proto.RequestType.TXINPUT,
]) details=proto.TxRequestDetailsType(
(signatures, serialized_tx) = btc.sign_tx(self.client, "Decred Testnet", [inp1], [out1]) tx_hash=TXHASH_e16248, request_index=0
),
),
proto.TxRequest(
request_type=proto.RequestType.TXOUTPUT,
details=proto.TxRequestDetailsType(
tx_hash=TXHASH_e16248, request_index=0
),
),
proto.TxRequest(
request_type=proto.RequestType.TXOUTPUT,
details=proto.TxRequestDetailsType(
tx_hash=TXHASH_e16248, request_index=1
),
),
proto.TxRequest(
request_type=proto.RequestType.TXOUTPUT,
details=proto.TxRequestDetailsType(request_index=0),
),
proto.ButtonRequest(code=proto.ButtonRequestType.ConfirmOutput),
proto.ButtonRequest(code=proto.ButtonRequestType.FeeOverThreshold),
proto.ButtonRequest(code=proto.ButtonRequestType.SignTx),
proto.TxRequest(
request_type=proto.RequestType.TXINPUT,
details=proto.TxRequestDetailsType(request_index=0),
),
proto.TxRequest(request_type=proto.RequestType.TXFINISHED),
]
)
(signatures, serialized_tx) = btc.sign_tx(
self.client, "Decred Testnet", [inp1], [out1]
)
# Accepted by network: 5e6e3500a333c53c02f523db5f1a9b17538a8850b4c2c24ecb9b7ba48059b970 # Accepted by network: 5e6e3500a333c53c02f523db5f1a9b17538a8850b4c2c24ecb9b7ba48059b970
assert serialized_tx == unhexlify("0100000001edd579e9462ee0e80127a817e0500d4f942a4cf8f2d6530e0c0a9ab3f04862e10100000000ffffffff01802b530b0000000000001976a914819d291a2f7fbf770e784bfd78b5ce92c58e95ea88ac000000000000000001000000000000000000000000ffffffff6b483045022100bad68486491e449a731513805c129201d7f65601d6f07c97fda0588453c97d22022013e9ef59657ae4f344ac4f0db2b7a23dbfcdb51ebeb85277146ac189e547d3f7012102f5a745afb96077c071e4d19911a5d3d024faa1314ee8688bc6eec39751d0818f") assert serialized_tx == unhexlify(
"0100000001edd579e9462ee0e80127a817e0500d4f942a4cf8f2d6530e0c0a9ab3f04862e10100000000ffffffff01802b530b0000000000001976a914819d291a2f7fbf770e784bfd78b5ce92c58e95ea88ac000000000000000001000000000000000000000000ffffffff6b483045022100bad68486491e449a731513805c129201d7f65601d6f07c97fda0588453c97d22022013e9ef59657ae4f344ac4f0db2b7a23dbfcdb51ebeb85277146ac189e547d3f7012102f5a745afb96077c071e4d19911a5d3d024faa1314ee8688bc6eec39751d0818f"
)
def test_send_decred_change(self): def test_send_decred_change(self):
self.setup_mnemonic_allallall() self.setup_mnemonic_allallall()
@ -125,51 +168,133 @@ class TestMsgSigntxDecred(TrezorTest):
) )
with self.client: with self.client:
self.client.set_expected_responses([ self.client.set_expected_responses(
proto.TxRequest(request_type=proto.RequestType.TXINPUT, details=proto.TxRequestDetailsType(request_index=0)), [
proto.TxRequest(request_type=proto.RequestType.TXMETA, details=proto.TxRequestDetailsType(tx_hash=TXHASH_5e6e35)), proto.TxRequest(
proto.TxRequest(request_type=proto.RequestType.TXINPUT, details=proto.TxRequestDetailsType(tx_hash=TXHASH_5e6e35, request_index=0)), request_type=proto.RequestType.TXINPUT,
proto.TxRequest(request_type=proto.RequestType.TXOUTPUT, details=proto.TxRequestDetailsType(tx_hash=TXHASH_5e6e35, request_index=0)), details=proto.TxRequestDetailsType(request_index=0),
proto.TxRequest(request_type=proto.RequestType.TXINPUT, details=proto.TxRequestDetailsType(request_index=1)), ),
proto.TxRequest(request_type=proto.RequestType.TXMETA, details=proto.TxRequestDetailsType(tx_hash=TXHASH_ccf95b)), proto.TxRequest(
proto.TxRequest(request_type=proto.RequestType.TXINPUT, details=proto.TxRequestDetailsType(tx_hash=TXHASH_ccf95b, request_index=0)), request_type=proto.RequestType.TXMETA,
proto.TxRequest(request_type=proto.RequestType.TXOUTPUT, details=proto.TxRequestDetailsType(tx_hash=TXHASH_ccf95b, request_index=0)), details=proto.TxRequestDetailsType(tx_hash=TXHASH_5e6e35),
proto.TxRequest(request_type=proto.RequestType.TXOUTPUT, details=proto.TxRequestDetailsType(tx_hash=TXHASH_ccf95b, request_index=1)), ),
proto.TxRequest(request_type=proto.RequestType.TXINPUT, details=proto.TxRequestDetailsType(request_index=2)), proto.TxRequest(
proto.TxRequest(request_type=proto.RequestType.TXMETA, details=proto.TxRequestDetailsType(tx_hash=TXHASH_f395ef)), request_type=proto.RequestType.TXINPUT,
proto.TxRequest(request_type=proto.RequestType.TXINPUT, details=proto.TxRequestDetailsType(tx_hash=TXHASH_f395ef, request_index=0)), details=proto.TxRequestDetailsType(
proto.TxRequest(request_type=proto.RequestType.TXOUTPUT, details=proto.TxRequestDetailsType(tx_hash=TXHASH_f395ef, request_index=0)), tx_hash=TXHASH_5e6e35, request_index=0
proto.TxRequest(request_type=proto.RequestType.TXOUTPUT, details=proto.TxRequestDetailsType(tx_hash=TXHASH_f395ef, request_index=1)), ),
proto.TxRequest(request_type=proto.RequestType.TXOUTPUT, details=proto.TxRequestDetailsType(request_index=0)), ),
proto.ButtonRequest(code=proto.ButtonRequestType.ConfirmOutput), proto.TxRequest(
proto.TxRequest(request_type=proto.RequestType.TXOUTPUT, details=proto.TxRequestDetailsType(request_index=1)), request_type=proto.RequestType.TXOUTPUT,
proto.ButtonRequest(code=proto.ButtonRequestType.SignTx), details=proto.TxRequestDetailsType(
proto.TxRequest(request_type=proto.RequestType.TXINPUT, details=proto.TxRequestDetailsType(request_index=0)), tx_hash=TXHASH_5e6e35, request_index=0
proto.TxRequest(request_type=proto.RequestType.TXINPUT, details=proto.TxRequestDetailsType(request_index=1)), ),
proto.TxRequest(request_type=proto.RequestType.TXINPUT, details=proto.TxRequestDetailsType(request_index=2)), ),
proto.TxRequest(request_type=proto.RequestType.TXFINISHED), proto.TxRequest(
]) request_type=proto.RequestType.TXINPUT,
(signatures, serialized_tx) = btc.sign_tx(self.client, "Decred Testnet", [inp1, inp2, inp3], [out1, out2]) details=proto.TxRequestDetailsType(request_index=1),
),
proto.TxRequest(
request_type=proto.RequestType.TXMETA,
details=proto.TxRequestDetailsType(tx_hash=TXHASH_ccf95b),
),
proto.TxRequest(
request_type=proto.RequestType.TXINPUT,
details=proto.TxRequestDetailsType(
tx_hash=TXHASH_ccf95b, request_index=0
),
),
proto.TxRequest(
request_type=proto.RequestType.TXOUTPUT,
details=proto.TxRequestDetailsType(
tx_hash=TXHASH_ccf95b, request_index=0
),
),
proto.TxRequest(
request_type=proto.RequestType.TXOUTPUT,
details=proto.TxRequestDetailsType(
tx_hash=TXHASH_ccf95b, request_index=1
),
),
proto.TxRequest(
request_type=proto.RequestType.TXINPUT,
details=proto.TxRequestDetailsType(request_index=2),
),
proto.TxRequest(
request_type=proto.RequestType.TXMETA,
details=proto.TxRequestDetailsType(tx_hash=TXHASH_f395ef),
),
proto.TxRequest(
request_type=proto.RequestType.TXINPUT,
details=proto.TxRequestDetailsType(
tx_hash=TXHASH_f395ef, request_index=0
),
),
proto.TxRequest(
request_type=proto.RequestType.TXOUTPUT,
details=proto.TxRequestDetailsType(
tx_hash=TXHASH_f395ef, request_index=0
),
),
proto.TxRequest(
request_type=proto.RequestType.TXOUTPUT,
details=proto.TxRequestDetailsType(
tx_hash=TXHASH_f395ef, request_index=1
),
),
proto.TxRequest(
request_type=proto.RequestType.TXOUTPUT,
details=proto.TxRequestDetailsType(request_index=0),
),
proto.ButtonRequest(code=proto.ButtonRequestType.ConfirmOutput),
proto.TxRequest(
request_type=proto.RequestType.TXOUTPUT,
details=proto.TxRequestDetailsType(request_index=1),
),
proto.ButtonRequest(code=proto.ButtonRequestType.SignTx),
proto.TxRequest(
request_type=proto.RequestType.TXINPUT,
details=proto.TxRequestDetailsType(request_index=0),
),
proto.TxRequest(
request_type=proto.RequestType.TXINPUT,
details=proto.TxRequestDetailsType(request_index=1),
),
proto.TxRequest(
request_type=proto.RequestType.TXINPUT,
details=proto.TxRequestDetailsType(request_index=2),
),
proto.TxRequest(request_type=proto.RequestType.TXFINISHED),
]
)
(signatures, serialized_tx) = btc.sign_tx(
self.client, "Decred Testnet", [inp1, inp2, inp3], [out1, out2]
)
# Accepted by network: c5ff767141a162b665acf775fcc35b60ff622fbe21a21e0a6609ed768c3737f4 # Accepted by network: c5ff767141a162b665acf775fcc35b60ff622fbe21a21e0a6609ed768c3737f4
assert serialized_tx == unhexlify("010000000370b95980a47b9bcb4ec2c2b450888a53179b1a5fdb23f5023cc533a300356e5e0000000000ffffffff74bc93bcfce18aff2e522d6822817522e2815a00175b2eae59ef20d20f5bf9cc0100000000ffffffff13317ab453832deabd684d2302eed42580c28ba3e715db66a731a8723eef95f30000000000ffffffff02d86c341d0000000000001976a9143eb656115197956125365348c542e37b6d3d259988ac00e1f5050000000000001976a9146748ebb8694c069742ee69eab2159c33c7f57d2b88ac000000000000000003000000000000000000000000ffffffff6b483045022100d91237a32b8968e1d3316b76f045cc18fed12736aebd570dd023a61826279cc102204222b133189762368d3398d11eb9a6843a67de11d70ac58426a28b605fa102b1012102f5a745afb96077c071e4d19911a5d3d024faa1314ee8688bc6eec39751d0818f000000000000000000000000ffffffff69463043021f7cf9b0b180f3fcde8d3d036d81e575e368d6ab5c8c6a2ffef47c06a0170023022036b964bf26ff276c58862dfacafa93216618832d6240f16b6100a9d10d5eb753012102f5a745afb96077c071e4d19911a5d3d024faa1314ee8688bc6eec39751d0818f000000000000000000000000ffffffff6b48304502210098f3a0cc17c3383f5998c542950b5cccb1175cc94b8d0343f420dc64abe9a50e0220507974c6ef0761925634fe3e13ec458b8cd3e42856828d584d4a5d39cc4d0f890121022c6099c7af8124d58e97beefc85c529dcfb3865794d46ec04095e70872e32a2e") assert serialized_tx == unhexlify(
"010000000370b95980a47b9bcb4ec2c2b450888a53179b1a5fdb23f5023cc533a300356e5e0000000000ffffffff74bc93bcfce18aff2e522d6822817522e2815a00175b2eae59ef20d20f5bf9cc0100000000ffffffff13317ab453832deabd684d2302eed42580c28ba3e715db66a731a8723eef95f30000000000ffffffff02d86c341d0000000000001976a9143eb656115197956125365348c542e37b6d3d259988ac00e1f5050000000000001976a9146748ebb8694c069742ee69eab2159c33c7f57d2b88ac000000000000000003000000000000000000000000ffffffff6b483045022100d91237a32b8968e1d3316b76f045cc18fed12736aebd570dd023a61826279cc102204222b133189762368d3398d11eb9a6843a67de11d70ac58426a28b605fa102b1012102f5a745afb96077c071e4d19911a5d3d024faa1314ee8688bc6eec39751d0818f000000000000000000000000ffffffff69463043021f7cf9b0b180f3fcde8d3d036d81e575e368d6ab5c8c6a2ffef47c06a0170023022036b964bf26ff276c58862dfacafa93216618832d6240f16b6100a9d10d5eb753012102f5a745afb96077c071e4d19911a5d3d024faa1314ee8688bc6eec39751d0818f000000000000000000000000ffffffff6b48304502210098f3a0cc17c3383f5998c542950b5cccb1175cc94b8d0343f420dc64abe9a50e0220507974c6ef0761925634fe3e13ec458b8cd3e42856828d584d4a5d39cc4d0f890121022c6099c7af8124d58e97beefc85c529dcfb3865794d46ec04095e70872e32a2e"
)
def test_decred_multisig_change(self): def test_decred_multisig_change(self):
self.setup_mnemonic_allallall() self.setup_mnemonic_allallall()
self.client.set_tx_api(TxApiDecredTestnet) self.client.set_tx_api(TxApiDecredTestnet)
paths = [parse_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 = [btc.get_public_node(self.client, address_n, coin_name="Decred Testnet").node for address_n in paths] nodes = [
btc.get_public_node(self.client, address_n, coin_name="Decred Testnet").node
signatures = [ for address_n in paths
[b'', b'', b''],
[b'', b'', b''],
] ]
signatures = [[b"", b"", b""], [b"", b"", b""]]
def create_multisig(index, address, signatures=None): def create_multisig(index, address, signatures=None):
address_n = parse_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,
m=2, m=2,
) )
@ -217,26 +342,84 @@ class TestMsgSigntxDecred(TrezorTest):
) )
with self.client: with self.client:
self.client.set_expected_responses([ self.client.set_expected_responses(
proto.TxRequest(request_type=proto.RequestType.TXINPUT, details=proto.TxRequestDetailsType(request_index=0)), [
proto.TxRequest(request_type=proto.RequestType.TXMETA, details=proto.TxRequestDetailsType(tx_hash=TXHASH_3f7c39)), proto.TxRequest(
proto.TxRequest(request_type=proto.RequestType.TXINPUT, details=proto.TxRequestDetailsType(tx_hash=TXHASH_3f7c39, request_index=0)), request_type=proto.RequestType.TXINPUT,
proto.TxRequest(request_type=proto.RequestType.TXOUTPUT, details=proto.TxRequestDetailsType(tx_hash=TXHASH_3f7c39, request_index=0)), details=proto.TxRequestDetailsType(request_index=0),
proto.TxRequest(request_type=proto.RequestType.TXOUTPUT, details=proto.TxRequestDetailsType(tx_hash=TXHASH_3f7c39, request_index=1)), ),
proto.TxRequest(request_type=proto.RequestType.TXINPUT, details=proto.TxRequestDetailsType(request_index=1)), proto.TxRequest(
proto.TxRequest(request_type=proto.RequestType.TXMETA, details=proto.TxRequestDetailsType(tx_hash=TXHASH_16da18)), request_type=proto.RequestType.TXMETA,
proto.TxRequest(request_type=proto.RequestType.TXINPUT, details=proto.TxRequestDetailsType(tx_hash=TXHASH_16da18, request_index=0)), details=proto.TxRequestDetailsType(tx_hash=TXHASH_3f7c39),
proto.TxRequest(request_type=proto.RequestType.TXOUTPUT, details=proto.TxRequestDetailsType(tx_hash=TXHASH_16da18, request_index=0)), ),
proto.TxRequest(request_type=proto.RequestType.TXOUTPUT, details=proto.TxRequestDetailsType(tx_hash=TXHASH_16da18, request_index=1)), proto.TxRequest(
proto.TxRequest(request_type=proto.RequestType.TXOUTPUT, details=proto.TxRequestDetailsType(request_index=0)), request_type=proto.RequestType.TXINPUT,
proto.TxRequest(request_type=proto.RequestType.TXOUTPUT, details=proto.TxRequestDetailsType(request_index=1)), details=proto.TxRequestDetailsType(
proto.ButtonRequest(code=proto.ButtonRequestType.ConfirmOutput), tx_hash=TXHASH_3f7c39, request_index=0
proto.ButtonRequest(code=proto.ButtonRequestType.SignTx), ),
proto.TxRequest(request_type=proto.RequestType.TXINPUT, details=proto.TxRequestDetailsType(request_index=0)), ),
proto.TxRequest(request_type=proto.RequestType.TXINPUT, details=proto.TxRequestDetailsType(request_index=1)), proto.TxRequest(
proto.TxRequest(request_type=proto.RequestType.TXFINISHED), request_type=proto.RequestType.TXOUTPUT,
]) details=proto.TxRequestDetailsType(
(signature, serialized_tx) = btc.sign_tx(self.client, "Decred Testnet", [inp1, inp2], [out1, out2]) tx_hash=TXHASH_3f7c39, request_index=0
),
),
proto.TxRequest(
request_type=proto.RequestType.TXOUTPUT,
details=proto.TxRequestDetailsType(
tx_hash=TXHASH_3f7c39, request_index=1
),
),
proto.TxRequest(
request_type=proto.RequestType.TXINPUT,
details=proto.TxRequestDetailsType(request_index=1),
),
proto.TxRequest(
request_type=proto.RequestType.TXMETA,
details=proto.TxRequestDetailsType(tx_hash=TXHASH_16da18),
),
proto.TxRequest(
request_type=proto.RequestType.TXINPUT,
details=proto.TxRequestDetailsType(
tx_hash=TXHASH_16da18, request_index=0
),
),
proto.TxRequest(
request_type=proto.RequestType.TXOUTPUT,
details=proto.TxRequestDetailsType(
tx_hash=TXHASH_16da18, request_index=0
),
),
proto.TxRequest(
request_type=proto.RequestType.TXOUTPUT,
details=proto.TxRequestDetailsType(
tx_hash=TXHASH_16da18, request_index=1
),
),
proto.TxRequest(
request_type=proto.RequestType.TXOUTPUT,
details=proto.TxRequestDetailsType(request_index=0),
),
proto.TxRequest(
request_type=proto.RequestType.TXOUTPUT,
details=proto.TxRequestDetailsType(request_index=1),
),
proto.ButtonRequest(code=proto.ButtonRequestType.ConfirmOutput),
proto.ButtonRequest(code=proto.ButtonRequestType.SignTx),
proto.TxRequest(
request_type=proto.RequestType.TXINPUT,
details=proto.TxRequestDetailsType(request_index=0),
),
proto.TxRequest(
request_type=proto.RequestType.TXINPUT,
details=proto.TxRequestDetailsType(request_index=1),
),
proto.TxRequest(request_type=proto.RequestType.TXFINISHED),
]
)
(signature, serialized_tx) = btc.sign_tx(
self.client, "Decred Testnet", [inp1, inp2], [out1, out2]
)
signatures[0][index] = signature[0] signatures[0][index] = signature[0]
signatures[1][index] = signature[1] signatures[1][index] = signature[1]
@ -246,4 +429,6 @@ class TestMsgSigntxDecred(TrezorTest):
serialized_tx = test_multisig(0) serialized_tx = test_multisig(0)
# Accepted by network: eccfecc0dc3275f7fa5a966b58c8d503f8b3d23964f2ce2c3336e5883919f45f # Accepted by network: eccfecc0dc3275f7fa5a966b58c8d503f8b3d23964f2ce2c3336e5883919f45f
assert serialized_tx == unhexlify("01000000023f4c9e61b1cf469cad3785a03566ef23876217fe657561e78783d32155397c3f0100000000ffffffffa806ca135db5160eb91202506ce2645b215805149ce730a6850d74525018da160000000000ffffffff02605af40500000000000017a914d42253369723b43e114b31807ef68f84363e54418700a3e1110000000000001976a9143eb656115197956125365348c542e37b6d3d259988ac000000000000000002000000000000000000000000fffffffffc483045022100be61bbcfd804f1e092c432511884bf8bdc00b6d302f00811149d20628bf3d33502200680721d1d03a71476f65e8815e2fba35bec6be982aa7686a57134eeae9a66f3014730440220016f9dd48ca0ceecf481d96f2c65389abb491af5f0eb63d76eb0f6a67a99718b02204fdeadace9167472411bb44bb63009ebd2373aa77cc08989a25fca37648dc685014c69522102a7ee50c2ceeacaed42aea05b29ac2ac3ec3c7e151dd95780929f53a0011f97a121038f9ebf01b25d80b4b8ad179542859ca96a9c5c8cbf0b5a50a92c0d9a7501efe62103b8d7f5663458e545af7de7a037e61a0e32c291ed2695f3cae120d6a0fe98052e53ae000000000000000000000000fffffffffdfd00483045022100ca8dd36eee86c4cefecfdd91cdf40a35a4274f71c4283e5b98af6bc242e2d5ad022009247ea5663367c2964f61b6111ea1a0790b381a40310f4e867a3725b249f12c01483045022100abc7b1440c31a564e1cd9d0a75abaa5abd8c1285b874c0e97e311e697782954302202fa43fb00149bb2d14b1a31a81b7660d6c9a17c4621a07eb4c2290b627aa540a014c69522103334dd6c58fae3d462f359125f0d6835e57ad885e5058b417f217decc21fdbba4210392af36b8a65ea0bb6f0acdec9069a0b5b75b00d9667b89e2a77f92d4efc92b9821025945b9f11a71546afe4af28cd291830fd77cb184006a90223de1b2c26502bfc353ae") assert serialized_tx == unhexlify(
"01000000023f4c9e61b1cf469cad3785a03566ef23876217fe657561e78783d32155397c3f0100000000ffffffffa806ca135db5160eb91202506ce2645b215805149ce730a6850d74525018da160000000000ffffffff02605af40500000000000017a914d42253369723b43e114b31807ef68f84363e54418700a3e1110000000000001976a9143eb656115197956125365348c542e37b6d3d259988ac000000000000000002000000000000000000000000fffffffffc483045022100be61bbcfd804f1e092c432511884bf8bdc00b6d302f00811149d20628bf3d33502200680721d1d03a71476f65e8815e2fba35bec6be982aa7686a57134eeae9a66f3014730440220016f9dd48ca0ceecf481d96f2c65389abb491af5f0eb63d76eb0f6a67a99718b02204fdeadace9167472411bb44bb63009ebd2373aa77cc08989a25fca37648dc685014c69522102a7ee50c2ceeacaed42aea05b29ac2ac3ec3c7e151dd95780929f53a0011f97a121038f9ebf01b25d80b4b8ad179542859ca96a9c5c8cbf0b5a50a92c0d9a7501efe62103b8d7f5663458e545af7de7a037e61a0e32c291ed2695f3cae120d6a0fe98052e53ae000000000000000000000000fffffffffdfd00483045022100ca8dd36eee86c4cefecfdd91cdf40a35a4274f71c4283e5b98af6bc242e2d5ad022009247ea5663367c2964f61b6111ea1a0790b381a40310f4e867a3725b249f12c01483045022100abc7b1440c31a564e1cd9d0a75abaa5abd8c1285b874c0e97e311e697782954302202fa43fb00149bb2d14b1a31a81b7660d6c9a17c4621a07eb4c2290b627aa540a014c69522103334dd6c58fae3d462f359125f0d6835e57ad885e5058b417f217decc21fdbba4210392af36b8a65ea0bb6f0acdec9069a0b5b75b00d9667b89e2a77f92d4efc92b9821025945b9f11a71546afe4af28cd291830fd77cb184006a90223de1b2c26502bfc353ae"
)

View File

@ -15,22 +15,21 @@
# If not, see <https://www.gnu.org/licenses/lgpl-3.0.html>. # If not, see <https://www.gnu.org/licenses/lgpl-3.0.html>.
from binascii import hexlify, unhexlify from binascii import hexlify, unhexlify
import pytest import pytest
from ..support.ckd_public import deserialize from trezorlib import btc, messages as proto
from .conftest import TREZOR_VERSION from trezorlib.tools import H_, CallException, parse_path
from .common import TrezorTest
from trezorlib import messages as proto
from trezorlib.tx_api import TxApiInsight from trezorlib.tx_api import TxApiInsight
from trezorlib.tools import parse_path, CallException, H_
from trezorlib import btc from ..support.ckd_public import deserialize
from .common import TrezorTest
from .conftest import TREZOR_VERSION
TxApiTestnet = TxApiInsight("insight_testnet") TxApiTestnet = TxApiInsight("insight_testnet")
class TestMsgSigntxSegwit(TrezorTest): class TestMsgSigntxSegwit(TrezorTest):
def test_send_p2sh(self): def test_send_p2sh(self):
self.setup_mnemonic_allallall() self.setup_mnemonic_allallall()
self.client.set_tx_api(TxApiTestnet) self.client.set_tx_api(TxApiTestnet)
@ -38,37 +37,67 @@ class TestMsgSigntxSegwit(TrezorTest):
address_n=parse_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"
),
prev_index=0, prev_index=0,
script_type=proto.InputScriptType.SPENDP2SHWITNESS, script_type=proto.InputScriptType.SPENDP2SHWITNESS,
) )
out1 = proto.TxOutputType( out1 = proto.TxOutputType(
address='mhRx1CeVfaayqRwq5zgRQmD7W5aWBfD5mC', address="mhRx1CeVfaayqRwq5zgRQmD7W5aWBfD5mC",
amount=12300000, amount=12300000,
script_type=proto.OutputScriptType.PAYTOADDRESS, script_type=proto.OutputScriptType.PAYTOADDRESS,
) )
out2 = proto.TxOutputType( out2 = proto.TxOutputType(
address='2N1LGaGg836mqSQqiuUBLfcyGBhyZbremDX', address="2N1LGaGg836mqSQqiuUBLfcyGBhyZbremDX",
script_type=proto.OutputScriptType.PAYTOADDRESS, script_type=proto.OutputScriptType.PAYTOADDRESS,
amount=123456789 - 11000 - 12300000, amount=123456789 - 11000 - 12300000,
) )
with self.client: with self.client:
self.client.set_expected_responses([ self.client.set_expected_responses(
proto.TxRequest(request_type=proto.RequestType.TXINPUT, details=proto.TxRequestDetailsType(request_index=0)), [
proto.TxRequest(request_type=proto.RequestType.TXOUTPUT, details=proto.TxRequestDetailsType(request_index=0)), proto.TxRequest(
proto.ButtonRequest(code=proto.ButtonRequestType.ConfirmOutput), request_type=proto.RequestType.TXINPUT,
proto.TxRequest(request_type=proto.RequestType.TXOUTPUT, details=proto.TxRequestDetailsType(request_index=1)), details=proto.TxRequestDetailsType(request_index=0),
proto.ButtonRequest(code=proto.ButtonRequestType.ConfirmOutput), ),
proto.ButtonRequest(code=proto.ButtonRequestType.SignTx), proto.TxRequest(
proto.TxRequest(request_type=proto.RequestType.TXINPUT, details=proto.TxRequestDetailsType(request_index=0)), request_type=proto.RequestType.TXOUTPUT,
proto.TxRequest(request_type=proto.RequestType.TXOUTPUT, details=proto.TxRequestDetailsType(request_index=0)), details=proto.TxRequestDetailsType(request_index=0),
proto.TxRequest(request_type=proto.RequestType.TXOUTPUT, details=proto.TxRequestDetailsType(request_index=1)), ),
proto.TxRequest(request_type=proto.RequestType.TXINPUT, details=proto.TxRequestDetailsType(request_index=0)), proto.ButtonRequest(code=proto.ButtonRequestType.ConfirmOutput),
proto.TxRequest(request_type=proto.RequestType.TXFINISHED), proto.TxRequest(
]) request_type=proto.RequestType.TXOUTPUT,
(signatures, serialized_tx) = btc.sign_tx(self.client, 'Testnet', [inp1], [out1, out2]) details=proto.TxRequestDetailsType(request_index=1),
),
proto.ButtonRequest(code=proto.ButtonRequestType.ConfirmOutput),
proto.ButtonRequest(code=proto.ButtonRequestType.SignTx),
proto.TxRequest(
request_type=proto.RequestType.TXINPUT,
details=proto.TxRequestDetailsType(request_index=0),
),
proto.TxRequest(
request_type=proto.RequestType.TXOUTPUT,
details=proto.TxRequestDetailsType(request_index=0),
),
proto.TxRequest(
request_type=proto.RequestType.TXOUTPUT,
details=proto.TxRequestDetailsType(request_index=1),
),
proto.TxRequest(
request_type=proto.RequestType.TXINPUT,
details=proto.TxRequestDetailsType(request_index=0),
),
proto.TxRequest(request_type=proto.RequestType.TXFINISHED),
]
)
(signatures, serialized_tx) = btc.sign_tx(
self.client, "Testnet", [inp1], [out1, out2]
)
assert hexlify(serialized_tx) == b'0100000000010137c361fb8f2d9056ba8c98c5611930fcb48cacfdd0fe2e0449d83eea982f91200000000017160014d16b8c0680c61fc6ed2e407455715055e41052f5ffffffff02e0aebb00000000001976a91414fdede0ddc3be652a0ce1afbc1b509a55b6b94888ac3df39f060000000017a91458b53ea7f832e8f096e896b8713a8c6df0e892ca8702483045022100ccd253bfdf8a5593cd7b6701370c531199f0f05a418cd547dfc7da3f21515f0f02203fa08a0753688871c220648f9edadbdb98af42e5d8269364a326572cf703895b012103e7bfe10708f715e8538c92d46ca50db6f657bbc455b7494e6a0303ccdb868b7900000000' assert (
hexlify(serialized_tx)
== b"0100000000010137c361fb8f2d9056ba8c98c5611930fcb48cacfdd0fe2e0449d83eea982f91200000000017160014d16b8c0680c61fc6ed2e407455715055e41052f5ffffffff02e0aebb00000000001976a91414fdede0ddc3be652a0ce1afbc1b509a55b6b94888ac3df39f060000000017a91458b53ea7f832e8f096e896b8713a8c6df0e892ca8702483045022100ccd253bfdf8a5593cd7b6701370c531199f0f05a418cd547dfc7da3f21515f0f02203fa08a0753688871c220648f9edadbdb98af42e5d8269364a326572cf703895b012103e7bfe10708f715e8538c92d46ca50db6f657bbc455b7494e6a0303ccdb868b7900000000"
)
def test_send_p2sh_change(self): def test_send_p2sh_change(self):
self.setup_mnemonic_allallall() self.setup_mnemonic_allallall()
@ -77,12 +106,14 @@ class TestMsgSigntxSegwit(TrezorTest):
address_n=parse_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"
),
prev_index=0, prev_index=0,
script_type=proto.InputScriptType.SPENDP2SHWITNESS, script_type=proto.InputScriptType.SPENDP2SHWITNESS,
) )
out1 = proto.TxOutputType( out1 = proto.TxOutputType(
address='mhRx1CeVfaayqRwq5zgRQmD7W5aWBfD5mC', address="mhRx1CeVfaayqRwq5zgRQmD7W5aWBfD5mC",
amount=12300000, amount=12300000,
script_type=proto.OutputScriptType.PAYTOADDRESS, script_type=proto.OutputScriptType.PAYTOADDRESS,
) )
@ -92,74 +123,157 @@ class TestMsgSigntxSegwit(TrezorTest):
amount=123456789 - 11000 - 12300000, amount=123456789 - 11000 - 12300000,
) )
with self.client: with self.client:
self.client.set_expected_responses([ self.client.set_expected_responses(
proto.TxRequest(request_type=proto.RequestType.TXINPUT, details=proto.TxRequestDetailsType(request_index=0)), [
proto.TxRequest(request_type=proto.RequestType.TXOUTPUT, details=proto.TxRequestDetailsType(request_index=0)), proto.TxRequest(
proto.ButtonRequest(code=proto.ButtonRequestType.ConfirmOutput), request_type=proto.RequestType.TXINPUT,
proto.TxRequest(request_type=proto.RequestType.TXOUTPUT, details=proto.TxRequestDetailsType(request_index=1)), details=proto.TxRequestDetailsType(request_index=0),
proto.ButtonRequest(code=proto.ButtonRequestType.SignTx), ),
proto.TxRequest(request_type=proto.RequestType.TXINPUT, details=proto.TxRequestDetailsType(request_index=0)), proto.TxRequest(
proto.TxRequest(request_type=proto.RequestType.TXOUTPUT, details=proto.TxRequestDetailsType(request_index=0)), request_type=proto.RequestType.TXOUTPUT,
proto.TxRequest(request_type=proto.RequestType.TXOUTPUT, details=proto.TxRequestDetailsType(request_index=1)), details=proto.TxRequestDetailsType(request_index=0),
proto.TxRequest(request_type=proto.RequestType.TXINPUT, details=proto.TxRequestDetailsType(request_index=0)), ),
proto.TxRequest(request_type=proto.RequestType.TXFINISHED), proto.ButtonRequest(code=proto.ButtonRequestType.ConfirmOutput),
]) proto.TxRequest(
(signatures, serialized_tx) = btc.sign_tx(self.client, 'Testnet', [inp1], [out1, out2]) request_type=proto.RequestType.TXOUTPUT,
details=proto.TxRequestDetailsType(request_index=1),
),
proto.ButtonRequest(code=proto.ButtonRequestType.SignTx),
proto.TxRequest(
request_type=proto.RequestType.TXINPUT,
details=proto.TxRequestDetailsType(request_index=0),
),
proto.TxRequest(
request_type=proto.RequestType.TXOUTPUT,
details=proto.TxRequestDetailsType(request_index=0),
),
proto.TxRequest(
request_type=proto.RequestType.TXOUTPUT,
details=proto.TxRequestDetailsType(request_index=1),
),
proto.TxRequest(
request_type=proto.RequestType.TXINPUT,
details=proto.TxRequestDetailsType(request_index=0),
),
proto.TxRequest(request_type=proto.RequestType.TXFINISHED),
]
)
(signatures, serialized_tx) = btc.sign_tx(
self.client, "Testnet", [inp1], [out1, out2]
)
assert hexlify(serialized_tx) == b'0100000000010137c361fb8f2d9056ba8c98c5611930fcb48cacfdd0fe2e0449d83eea982f91200000000017160014d16b8c0680c61fc6ed2e407455715055e41052f5ffffffff02e0aebb00000000001976a91414fdede0ddc3be652a0ce1afbc1b509a55b6b94888ac3df39f060000000017a91458b53ea7f832e8f096e896b8713a8c6df0e892ca8702483045022100ccd253bfdf8a5593cd7b6701370c531199f0f05a418cd547dfc7da3f21515f0f02203fa08a0753688871c220648f9edadbdb98af42e5d8269364a326572cf703895b012103e7bfe10708f715e8538c92d46ca50db6f657bbc455b7494e6a0303ccdb868b7900000000' assert (
hexlify(serialized_tx)
== b"0100000000010137c361fb8f2d9056ba8c98c5611930fcb48cacfdd0fe2e0449d83eea982f91200000000017160014d16b8c0680c61fc6ed2e407455715055e41052f5ffffffff02e0aebb00000000001976a91414fdede0ddc3be652a0ce1afbc1b509a55b6b94888ac3df39f060000000017a91458b53ea7f832e8f096e896b8713a8c6df0e892ca8702483045022100ccd253bfdf8a5593cd7b6701370c531199f0f05a418cd547dfc7da3f21515f0f02203fa08a0753688871c220648f9edadbdb98af42e5d8269364a326572cf703895b012103e7bfe10708f715e8538c92d46ca50db6f657bbc455b7494e6a0303ccdb868b7900000000"
)
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: btc.get_public_node(self.client, parse_path("999'/1'/%d'" % index)), range(1, 4)) nodes = map(
lambda index: btc.get_public_node(
self.client, 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(
signatures=[b'', b'', b''], map(
lambda n: proto.HDNodePathType(
node=deserialize(n.xpub), address_n=[2, 0]
),
nodes,
)
),
signatures=[b"", b"", b""],
m=2, m=2,
) )
inp1 = proto.TxInputType( inp1 = proto.TxInputType(
address_n=parse_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,
multisig=multisig, multisig=multisig,
amount=1610436 amount=1610436,
) )
out1 = proto.TxOutputType(address='mhRx1CeVfaayqRwq5zgRQmD7W5aWBfD5mC', out1 = proto.TxOutputType(
amount=1605000, address="mhRx1CeVfaayqRwq5zgRQmD7W5aWBfD5mC",
script_type=proto.OutputScriptType.PAYTOADDRESS) amount=1605000,
script_type=proto.OutputScriptType.PAYTOADDRESS,
)
with self.client: with self.client:
self.client.set_expected_responses([ self.client.set_expected_responses(
proto.TxRequest(request_type=proto.RequestType.TXINPUT, details=proto.TxRequestDetailsType(request_index=0)), [
proto.TxRequest(request_type=proto.RequestType.TXOUTPUT, details=proto.TxRequestDetailsType(request_index=0)), proto.TxRequest(
proto.ButtonRequest(code=proto.ButtonRequestType.ConfirmOutput), request_type=proto.RequestType.TXINPUT,
proto.ButtonRequest(code=proto.ButtonRequestType.SignTx), details=proto.TxRequestDetailsType(request_index=0),
proto.TxRequest(request_type=proto.RequestType.TXINPUT, details=proto.TxRequestDetailsType(request_index=0)), ),
proto.TxRequest(request_type=proto.RequestType.TXOUTPUT, details=proto.TxRequestDetailsType(request_index=0)), proto.TxRequest(
proto.TxRequest(request_type=proto.RequestType.TXINPUT, details=proto.TxRequestDetailsType(request_index=0)), request_type=proto.RequestType.TXOUTPUT,
proto.TxRequest(request_type=proto.RequestType.TXFINISHED), details=proto.TxRequestDetailsType(request_index=0),
]) ),
(signatures1, _) = btc.sign_tx(self.client, 'Testnet', [inp1], [out1]) proto.ButtonRequest(code=proto.ButtonRequestType.ConfirmOutput),
proto.ButtonRequest(code=proto.ButtonRequestType.SignTx),
proto.TxRequest(
request_type=proto.RequestType.TXINPUT,
details=proto.TxRequestDetailsType(request_index=0),
),
proto.TxRequest(
request_type=proto.RequestType.TXOUTPUT,
details=proto.TxRequestDetailsType(request_index=0),
),
proto.TxRequest(
request_type=proto.RequestType.TXINPUT,
details=proto.TxRequestDetailsType(request_index=0),
),
proto.TxRequest(request_type=proto.RequestType.TXFINISHED),
]
)
(signatures1, _) = btc.sign_tx(self.client, "Testnet", [inp1], [out1])
# store signature # store signature
inp1.multisig.signatures[0] = signatures1[0] inp1.multisig.signatures[0] = signatures1[0]
# sign with third key # sign with third key
inp1.address_n[2] = H_(3) inp1.address_n[2] = H_(3)
self.client.set_expected_responses([ self.client.set_expected_responses(
proto.TxRequest(request_type=proto.RequestType.TXINPUT, details=proto.TxRequestDetailsType(request_index=0)), [
proto.TxRequest(request_type=proto.RequestType.TXOUTPUT, details=proto.TxRequestDetailsType(request_index=0)), proto.TxRequest(
proto.ButtonRequest(code=proto.ButtonRequestType.ConfirmOutput), request_type=proto.RequestType.TXINPUT,
proto.ButtonRequest(code=proto.ButtonRequestType.SignTx), details=proto.TxRequestDetailsType(request_index=0),
proto.TxRequest(request_type=proto.RequestType.TXINPUT, details=proto.TxRequestDetailsType(request_index=0)), ),
proto.TxRequest(request_type=proto.RequestType.TXOUTPUT, details=proto.TxRequestDetailsType(request_index=0)), proto.TxRequest(
proto.TxRequest(request_type=proto.RequestType.TXINPUT, details=proto.TxRequestDetailsType(request_index=0)), request_type=proto.RequestType.TXOUTPUT,
proto.TxRequest(request_type=proto.RequestType.TXFINISHED), details=proto.TxRequestDetailsType(request_index=0),
]) ),
(signatures2, serialized_tx) = btc.sign_tx(self.client, 'Testnet', [inp1], [out1]) proto.ButtonRequest(code=proto.ButtonRequestType.ConfirmOutput),
proto.ButtonRequest(code=proto.ButtonRequestType.SignTx),
proto.TxRequest(
request_type=proto.RequestType.TXINPUT,
details=proto.TxRequestDetailsType(request_index=0),
),
proto.TxRequest(
request_type=proto.RequestType.TXOUTPUT,
details=proto.TxRequestDetailsType(request_index=0),
),
proto.TxRequest(
request_type=proto.RequestType.TXINPUT,
details=proto.TxRequestDetailsType(request_index=0),
),
proto.TxRequest(request_type=proto.RequestType.TXFINISHED),
]
)
(signatures2, serialized_tx) = btc.sign_tx(
self.client, "Testnet", [inp1], [out1]
)
assert hexlify(serialized_tx) == b'01000000000101be0210025c5be68a473f6a38bf53b53bc88d5c46567616026dc056e72b92319c01000000232200201e8dda334f11171190b3da72e526d441491464769679a319a2f011da5ad312a1ffffffff01887d1800000000001976a91414fdede0ddc3be652a0ce1afbc1b509a55b6b94888ac040047304402205b44c20cf2681690edaaf7cd2e30d4704124dd8b7eb1fb7f459d3906c3c374a602205ca359b6544ce2c101c979899c782f7d141c3b0454ea69202b1fb4c09d3b715701473044022052fafa64022554ae436dbf781e550bf0d326fef31eea1438350b3ff1940a180102202851bd19203b7fe8582a9ef52e82aa9f61cd52d4bcedfe6dcc0cf782468e6a8e01695221038e81669c085a5846e68e03875113ddb339ecbb7cb11376d4163bca5dc2e2a0c1210348c5c3be9f0e6cf1954ded1c0475beccc4d26aaa9d0cce2dd902538ff1018a112103931140ebe0fbbb7df0be04ed032a54e9589e30339ba7bbb8b0b71b15df1294da53ae00000000' assert (
hexlify(serialized_tx)
== b"01000000000101be0210025c5be68a473f6a38bf53b53bc88d5c46567616026dc056e72b92319c01000000232200201e8dda334f11171190b3da72e526d441491464769679a319a2f011da5ad312a1ffffffff01887d1800000000001976a91414fdede0ddc3be652a0ce1afbc1b509a55b6b94888ac040047304402205b44c20cf2681690edaaf7cd2e30d4704124dd8b7eb1fb7f459d3906c3c374a602205ca359b6544ce2c101c979899c782f7d141c3b0454ea69202b1fb4c09d3b715701473044022052fafa64022554ae436dbf781e550bf0d326fef31eea1438350b3ff1940a180102202851bd19203b7fe8582a9ef52e82aa9f61cd52d4bcedfe6dcc0cf782468e6a8e01695221038e81669c085a5846e68e03875113ddb339ecbb7cb11376d4163bca5dc2e2a0c1210348c5c3be9f0e6cf1954ded1c0475beccc4d26aaa9d0cce2dd902538ff1018a112103931140ebe0fbbb7df0be04ed032a54e9589e30339ba7bbb8b0b71b15df1294da53ae00000000"
)
def test_attack_change_input_address(self): def test_attack_change_input_address(self):
# This unit test attempts to modify input address after the Trezor checked # This unit test attempts to modify input address after the Trezor checked
@ -171,12 +285,14 @@ class TestMsgSigntxSegwit(TrezorTest):
address_n=parse_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"
),
prev_index=0, prev_index=0,
script_type=proto.InputScriptType.SPENDP2SHWITNESS, script_type=proto.InputScriptType.SPENDP2SHWITNESS,
) )
out1 = proto.TxOutputType( out1 = proto.TxOutputType(
address='mhRx1CeVfaayqRwq5zgRQmD7W5aWBfD5mC', address="mhRx1CeVfaayqRwq5zgRQmD7W5aWBfD5mC",
amount=12300000, amount=12300000,
script_type=proto.OutputScriptType.PAYTOADDRESS, script_type=proto.OutputScriptType.PAYTOADDRESS,
) )
@ -210,38 +326,88 @@ class TestMsgSigntxSegwit(TrezorTest):
# Test if the transaction can be signed normally # Test if the transaction can be signed normally
with self.client: with self.client:
self.client.set_expected_responses([ self.client.set_expected_responses(
proto.TxRequest(request_type=proto.RequestType.TXINPUT, details=proto.TxRequestDetailsType(request_index=0)), [
proto.TxRequest(request_type=proto.RequestType.TXOUTPUT, details=proto.TxRequestDetailsType(request_index=0)), proto.TxRequest(
proto.ButtonRequest(code=proto.ButtonRequestType.ConfirmOutput), request_type=proto.RequestType.TXINPUT,
proto.TxRequest(request_type=proto.RequestType.TXOUTPUT, details=proto.TxRequestDetailsType(request_index=1)), details=proto.TxRequestDetailsType(request_index=0),
proto.ButtonRequest(code=proto.ButtonRequestType.ConfirmOutput), ),
proto.ButtonRequest(code=proto.ButtonRequestType.SignTx), proto.TxRequest(
proto.TxRequest(request_type=proto.RequestType.TXINPUT, details=proto.TxRequestDetailsType(request_index=0)), request_type=proto.RequestType.TXOUTPUT,
proto.TxRequest(request_type=proto.RequestType.TXOUTPUT, details=proto.TxRequestDetailsType(request_index=0)), details=proto.TxRequestDetailsType(request_index=0),
proto.TxRequest(request_type=proto.RequestType.TXOUTPUT, details=proto.TxRequestDetailsType(request_index=1)), ),
proto.TxRequest(request_type=proto.RequestType.TXINPUT, details=proto.TxRequestDetailsType(request_index=0)), proto.ButtonRequest(code=proto.ButtonRequestType.ConfirmOutput),
proto.TxRequest(request_type=proto.RequestType.TXFINISHED), proto.TxRequest(
]) request_type=proto.RequestType.TXOUTPUT,
(signatures, serialized_tx) = btc.sign_tx(self.client, 'Testnet', [inp1], [out1, out2]) details=proto.TxRequestDetailsType(request_index=1),
),
proto.ButtonRequest(code=proto.ButtonRequestType.ConfirmOutput),
proto.ButtonRequest(code=proto.ButtonRequestType.SignTx),
proto.TxRequest(
request_type=proto.RequestType.TXINPUT,
details=proto.TxRequestDetailsType(request_index=0),
),
proto.TxRequest(
request_type=proto.RequestType.TXOUTPUT,
details=proto.TxRequestDetailsType(request_index=0),
),
proto.TxRequest(
request_type=proto.RequestType.TXOUTPUT,
details=proto.TxRequestDetailsType(request_index=1),
),
proto.TxRequest(
request_type=proto.RequestType.TXINPUT,
details=proto.TxRequestDetailsType(request_index=0),
),
proto.TxRequest(request_type=proto.RequestType.TXFINISHED),
]
)
(signatures, serialized_tx) = btc.sign_tx(
self.client, "Testnet", [inp1], [out1, out2]
)
assert hexlify(serialized_tx) == b'0100000000010137c361fb8f2d9056ba8c98c5611930fcb48cacfdd0fe2e0449d83eea982f91200000000017160014d16b8c0680c61fc6ed2e407455715055e41052f5ffffffff02e0aebb00000000001976a91414fdede0ddc3be652a0ce1afbc1b509a55b6b94888ac3df39f060000000017a914dae9e09a7fc3bbe5a716fffec1bbb340b82a4fb9870248304502210099b5c4f8fd4402c9c0136fee5f711137d64fc9f14587e01bfa7798f5428f845d0220253e21c98f5b1b64efae69bc2ea9799c5620a43450baa6762a0c3cf4fdc886e5012103e7bfe10708f715e8538c92d46ca50db6f657bbc455b7494e6a0303ccdb868b7900000000' assert (
hexlify(serialized_tx)
== b"0100000000010137c361fb8f2d9056ba8c98c5611930fcb48cacfdd0fe2e0449d83eea982f91200000000017160014d16b8c0680c61fc6ed2e407455715055e41052f5ffffffff02e0aebb00000000001976a91414fdede0ddc3be652a0ce1afbc1b509a55b6b94888ac3df39f060000000017a914dae9e09a7fc3bbe5a716fffec1bbb340b82a4fb9870248304502210099b5c4f8fd4402c9c0136fee5f711137d64fc9f14587e01bfa7798f5428f845d0220253e21c98f5b1b64efae69bc2ea9799c5620a43450baa6762a0c3cf4fdc886e5012103e7bfe10708f715e8538c92d46ca50db6f657bbc455b7494e6a0303ccdb868b7900000000"
)
# Now run the attack, must trigger the exception # Now run the attack, must trigger the exception
with self.client: with self.client:
self.client.set_expected_responses([ self.client.set_expected_responses(
proto.TxRequest(request_type=proto.RequestType.TXINPUT, details=proto.TxRequestDetailsType(request_index=0)), [
proto.TxRequest(request_type=proto.RequestType.TXOUTPUT, details=proto.TxRequestDetailsType(request_index=0)), proto.TxRequest(
proto.ButtonRequest(code=proto.ButtonRequestType.ConfirmOutput), request_type=proto.RequestType.TXINPUT,
proto.TxRequest(request_type=proto.RequestType.TXOUTPUT, details=proto.TxRequestDetailsType(request_index=1)), details=proto.TxRequestDetailsType(request_index=0),
proto.ButtonRequest(code=proto.ButtonRequestType.SignTx), ),
proto.TxRequest(request_type=proto.RequestType.TXINPUT, details=proto.TxRequestDetailsType(request_index=0)), proto.TxRequest(
proto.Failure(code=proto.FailureType.ProcessError), request_type=proto.RequestType.TXOUTPUT,
]) details=proto.TxRequestDetailsType(request_index=0),
),
proto.ButtonRequest(code=proto.ButtonRequestType.ConfirmOutput),
proto.TxRequest(
request_type=proto.RequestType.TXOUTPUT,
details=proto.TxRequestDetailsType(request_index=1),
),
proto.ButtonRequest(code=proto.ButtonRequestType.SignTx),
proto.TxRequest(
request_type=proto.RequestType.TXINPUT,
details=proto.TxRequestDetailsType(request_index=0),
),
proto.Failure(code=proto.FailureType.ProcessError),
]
)
with pytest.raises(CallException) as exc: with pytest.raises(CallException) as exc:
btc.sign_tx(self.client, 'Testnet', [inp1], [out1, out2], debug_processor=attack_processor) btc.sign_tx(
self.client,
"Testnet",
[inp1],
[out1, out2],
debug_processor=attack_processor,
)
assert exc.value.args[0] == proto.FailureType.ProcessError assert exc.value.args[0] == proto.FailureType.ProcessError
if TREZOR_VERSION == 1: if TREZOR_VERSION == 1:
assert exc.value.args[1].endswith("Failed to compile input") assert exc.value.args[1].endswith("Failed to compile input")
else: else:
assert exc.value.args[1].endswith('Transaction has changed during signing') assert exc.value.args[1].endswith(
"Transaction has changed during signing"
)

File diff suppressed because it is too large Load Diff

View File

@ -14,24 +14,24 @@
# You should have received a copy of the License along with this library. # You should have received a copy of the License along with this library.
# If not, see <https://www.gnu.org/licenses/lgpl-3.0.html>. # If not, see <https://www.gnu.org/licenses/lgpl-3.0.html>.
from binascii import unhexlify, hexlify from binascii import hexlify, unhexlify
import pytest import pytest
from trezorlib import btc, coins, messages as proto
from trezorlib.tools import parse_path
from .common import TrezorTest from .common import TrezorTest
from trezorlib import coins TxApiZcashTestnet = coins.tx_api["Zcash Testnet"]
from trezorlib import messages as proto
from trezorlib.tools import parse_path
from trezorlib import btc
TxApiZcashTestnet = coins.tx_api['Zcash Testnet'] TXHASH_aaf51e = unhexlify(
"aaf51e4606c264e47e5c42c958fe4cf1539c5172684721e38e69f4ef634d75dc"
TXHASH_aaf51e = unhexlify('aaf51e4606c264e47e5c42c958fe4cf1539c5172684721e38e69f4ef634d75dc') )
@pytest.mark.zcash @pytest.mark.zcash
class TestMsgSigntxZcash(TrezorTest): class TestMsgSigntxZcash(TrezorTest):
def test_one_one_fee(self): def test_one_one_fee(self):
self.setup_mnemonic_allallall() self.setup_mnemonic_allallall()
@ -39,31 +39,57 @@ class TestMsgSigntxZcash(TrezorTest):
# input 1: 3.0 TAZ # input 1: 3.0 TAZ
inp1 = proto.TxInputType( inp1 = proto.TxInputType(
address_n=parse_path("m/Zcash Testnet/0h/0/0"), # tmQoJ3PTXgQLaRRZZYT6xk8XtjRbr2kCqwu address_n=parse_path(
"m/Zcash Testnet/0h/0/0"
), # tmQoJ3PTXgQLaRRZZYT6xk8XtjRbr2kCqwu
amount=300000000, amount=300000000,
prev_hash=TXHASH_aaf51e, prev_hash=TXHASH_aaf51e,
prev_index=1, prev_index=1,
) )
out1 = proto.TxOutputType( out1 = proto.TxOutputType(
address='tmJ1xYxP8XNTtCoDgvdmQPSrxh5qZJgy65Z', address="tmJ1xYxP8XNTtCoDgvdmQPSrxh5qZJgy65Z",
amount=300000000 - 1940, amount=300000000 - 1940,
script_type=proto.OutputScriptType.PAYTOADDRESS, script_type=proto.OutputScriptType.PAYTOADDRESS,
) )
with self.client: with self.client:
self.client.set_tx_api(TxApiZcashTestnet) self.client.set_tx_api(TxApiZcashTestnet)
self.client.set_expected_responses([ self.client.set_expected_responses(
proto.TxRequest(request_type=proto.RequestType.TXINPUT, details=proto.TxRequestDetailsType(request_index=0)), [
proto.TxRequest(request_type=proto.RequestType.TXOUTPUT, details=proto.TxRequestDetailsType(request_index=0)), proto.TxRequest(
proto.ButtonRequest(code=proto.ButtonRequestType.ConfirmOutput), request_type=proto.RequestType.TXINPUT,
proto.ButtonRequest(code=proto.ButtonRequestType.SignTx), details=proto.TxRequestDetailsType(request_index=0),
proto.TxRequest(request_type=proto.RequestType.TXINPUT, details=proto.TxRequestDetailsType(request_index=0)), ),
proto.TxRequest(request_type=proto.RequestType.TXOUTPUT, details=proto.TxRequestDetailsType(request_index=0)), proto.TxRequest(
proto.TxRequest(request_type=proto.RequestType.TXFINISHED), request_type=proto.RequestType.TXOUTPUT,
]) details=proto.TxRequestDetailsType(request_index=0),
),
proto.ButtonRequest(code=proto.ButtonRequestType.ConfirmOutput),
proto.ButtonRequest(code=proto.ButtonRequestType.SignTx),
proto.TxRequest(
request_type=proto.RequestType.TXINPUT,
details=proto.TxRequestDetailsType(request_index=0),
),
proto.TxRequest(
request_type=proto.RequestType.TXOUTPUT,
details=proto.TxRequestDetailsType(request_index=0),
),
proto.TxRequest(request_type=proto.RequestType.TXFINISHED),
]
)
(signatures, serialized_tx) = btc.sign_tx(self.client, 'Zcash Testnet', [inp1, ], [out1, ], version=3, overwintered=True) (signatures, serialized_tx) = btc.sign_tx(
self.client,
"Zcash Testnet",
[inp1],
[out1],
version=3,
overwintered=True,
)
# Accepted by network: tx eda9b772c47f0c29310759960e0081c98707aa67a0a2738bcc71439fcf360675 # Accepted by network: tx eda9b772c47f0c29310759960e0081c98707aa67a0a2738bcc71439fcf360675
assert hexlify(serialized_tx) == b'030000807082c40301dc754d63eff4698ee321476872519c53f14cfe58c9425c7ee464c206461ef5aa010000006a47304402207e45f303b4e42be824513855eb21653e1d2749cd94dcd0f0613d3f85d4efd1e20220699ffbdbcad889af7ede5ce9febf7a5ef8f5619b2464824529974c400cffaebc0121030e669acac1f280d1ddf441cd2ba5e97417bf2689e4bbec86df4f831bf9f7ffd0ffffffff016c9be111000000001976a9145b157a678a10021243307e4bb58f36375aa80e1088ac000000000000000000' assert (
hexlify(serialized_tx)
== b"030000807082c40301dc754d63eff4698ee321476872519c53f14cfe58c9425c7ee464c206461ef5aa010000006a47304402207e45f303b4e42be824513855eb21653e1d2749cd94dcd0f0613d3f85d4efd1e20220699ffbdbcad889af7ede5ce9febf7a5ef8f5619b2464824529974c400cffaebc0121030e669acac1f280d1ddf441cd2ba5e97417bf2689e4bbec86df4f831bf9f7ffd0ffffffff016c9be111000000001976a9145b157a678a10021243307e4bb58f36375aa80e1088ac000000000000000000"
)

View File

@ -16,45 +16,54 @@
import pytest import pytest
from trezorlib import debuglink, messages as proto, stellar
from trezorlib.tools import CallException, parse_path
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 messages as proto
from trezorlib.tools import parse_path, CallException
from trezorlib import debuglink
@pytest.mark.stellar @pytest.mark.stellar
class TestMsgStellarGetAddress(TrezorTest): class TestMsgStellarGetAddress(TrezorTest):
def test_stellar_get_address(self): def test_stellar_get_address(self):
self.setup_mnemonic_nopin_nopassphrase() self.setup_mnemonic_nopin_nopassphrase()
address = stellar.get_address(self.client, parse_path(stellar.DEFAULT_BIP32_PATH)) address = stellar.get_address(
assert address == 'GAK5MSF74TJW6GLM7NLTL76YZJKM2S4CGP3UH4REJHPHZ4YBZW2GSBPW' self.client, parse_path(stellar.DEFAULT_BIP32_PATH)
)
assert address == "GAK5MSF74TJW6GLM7NLTL76YZJKM2S4CGP3UH4REJHPHZ4YBZW2GSBPW"
def test_stellar_get_address_sep(self): def test_stellar_get_address_sep(self):
# data from https://github.com/stellar/stellar-protocol/blob/master/ecosystem/sep-0005.md # data from https://github.com/stellar/stellar-protocol/blob/master/ecosystem/sep-0005.md
debuglink.load_device_by_mnemonic( debuglink.load_device_by_mnemonic(
self.client, self.client,
mnemonic='illness spike retreat truth genius clock brain pass fit cave bargain toe', mnemonic="illness spike retreat truth genius clock brain pass fit cave bargain toe",
pin='', pin="",
passphrase_protection=False, passphrase_protection=False,
label='test', label="test",
language='english') language="english",
)
address = stellar.get_address(self.client, parse_path(stellar.DEFAULT_BIP32_PATH)) address = stellar.get_address(
assert address == 'GDRXE2BQUC3AZNPVFSCEZ76NJ3WWL25FYFK6RGZGIEKWE4SOOHSUJUJ6' self.client, parse_path(stellar.DEFAULT_BIP32_PATH)
)
assert address == "GDRXE2BQUC3AZNPVFSCEZ76NJ3WWL25FYFK6RGZGIEKWE4SOOHSUJUJ6"
address = stellar.get_address(self.client, parse_path("m/44h/148h/1h"), show_display=True) address = stellar.get_address(
assert address == 'GBAW5XGWORWVFE2XTJYDTLDHXTY2Q2MO73HYCGB3XMFMQ562Q2W2GJQX' self.client, parse_path("m/44h/148h/1h"), show_display=True
)
assert address == "GBAW5XGWORWVFE2XTJYDTLDHXTY2Q2MO73HYCGB3XMFMQ562Q2W2GJQX"
def test_stellar_get_address_get_pubkey(self): def test_stellar_get_address_get_pubkey(self):
self.setup_mnemonic_nopin_nopassphrase() self.setup_mnemonic_nopin_nopassphrase()
pubkey = stellar.get_public_key(self.client, parse_path(stellar.DEFAULT_BIP32_PATH)) pubkey = stellar.get_public_key(
self.client, parse_path(stellar.DEFAULT_BIP32_PATH)
)
# GAK5MSF74TJW6GLM7NLTL76YZJKM2S4CGP3UH4REJHPHZ4YBZW2GSBPW # GAK5MSF74TJW6GLM7NLTL76YZJKM2S4CGP3UH4REJHPHZ4YBZW2GSBPW
address = stellar.get_address(self.client, parse_path(stellar.DEFAULT_BIP32_PATH)) address = stellar.get_address(
self.client, parse_path(stellar.DEFAULT_BIP32_PATH)
)
assert stellar.address_from_public_key(pubkey) == address assert stellar.address_from_public_key(pubkey) == address
@ -62,11 +71,11 @@ class TestMsgStellarGetAddress(TrezorTest):
self.setup_mnemonic_nopin_nopassphrase() self.setup_mnemonic_nopin_nopassphrase()
with pytest.raises(CallException) as exc: with pytest.raises(CallException) as exc:
stellar.get_address(self.client, parse_path('m/0/1')) stellar.get_address(self.client, parse_path("m/0/1"))
if TREZOR_VERSION == 1: if TREZOR_VERSION == 1:
assert exc.value.args[0] == proto.FailureType.ProcessError assert exc.value.args[0] == proto.FailureType.ProcessError
assert exc.value.args[1].endswith('Failed to derive private key') assert exc.value.args[1].endswith("Failed to derive private key")
else: else:
assert exc.value.args[0] == proto.FailureType.FirmwareError assert exc.value.args[0] == proto.FailureType.FirmwareError
assert exc.value.args[1].endswith('Firmware error') assert exc.value.args[1].endswith("Firmware error")

View File

@ -14,36 +14,44 @@
# You should have received a copy of the License along with this library. # You should have received a copy of the License along with this library.
# If not, see <https://www.gnu.org/licenses/lgpl-3.0.html>. # If not, see <https://www.gnu.org/licenses/lgpl-3.0.html>.
from binascii import hexlify
import pytest import pytest
from trezorlib import messages, stellar
from trezorlib.tools import CallException, parse_path
from .common import TrezorTest from .common import TrezorTest
from .conftest import TREZOR_VERSION from .conftest import TREZOR_VERSION
from binascii import hexlify
from trezorlib import stellar
from trezorlib import messages
from trezorlib.tools import parse_path, CallException
@pytest.mark.stellar @pytest.mark.stellar
class TestMsgStellarGetPublicKey(TrezorTest): class TestMsgStellarGetPublicKey(TrezorTest):
def test_stellar_get_public_key(self): def test_stellar_get_public_key(self):
self.setup_mnemonic_nopin_nopassphrase() self.setup_mnemonic_nopin_nopassphrase()
# GAK5MSF74TJW6GLM7NLTL76YZJKM2S4CGP3UH4REJHPHZ4YBZW2GSBPW # GAK5MSF74TJW6GLM7NLTL76YZJKM2S4CGP3UH4REJHPHZ4YBZW2GSBPW
response = stellar.get_public_key(self.client, parse_path(stellar.DEFAULT_BIP32_PATH), show_display=True) response = stellar.get_public_key(
assert hexlify(response) == b'15d648bfe4d36f196cfb5735ffd8ca54cd4b8233f743f22449de7cf301cdb469' self.client, parse_path(stellar.DEFAULT_BIP32_PATH), show_display=True
assert stellar.address_from_public_key(response) == 'GAK5MSF74TJW6GLM7NLTL76YZJKM2S4CGP3UH4REJHPHZ4YBZW2GSBPW' )
assert (
hexlify(response)
== b"15d648bfe4d36f196cfb5735ffd8ca54cd4b8233f743f22449de7cf301cdb469"
)
assert (
stellar.address_from_public_key(response)
== "GAK5MSF74TJW6GLM7NLTL76YZJKM2S4CGP3UH4REJHPHZ4YBZW2GSBPW"
)
def test_stellar_get_public_key_fail(self): def test_stellar_get_public_key_fail(self):
self.setup_mnemonic_nopin_nopassphrase() self.setup_mnemonic_nopin_nopassphrase()
with pytest.raises(CallException) as exc: with pytest.raises(CallException) as exc:
stellar.get_public_key(self.client, parse_path('m/0/1')) stellar.get_public_key(self.client, parse_path("m/0/1"))
if TREZOR_VERSION == 1: if TREZOR_VERSION == 1:
assert exc.value.args[0] == messages.FailureType.ProcessError assert exc.value.args[0] == messages.FailureType.ProcessError
assert exc.value.args[1].endswith('Failed to derive private key') assert exc.value.args[1].endswith("Failed to derive private key")
else: else:
assert exc.value.args[0] == messages.FailureType.FirmwareError assert exc.value.args[0] == messages.FailureType.FirmwareError
assert exc.value.args[1].endswith('Firmware error') assert exc.value.args[1].endswith("Firmware error")

View File

@ -47,19 +47,21 @@
# #
from base64 import b64encode from base64 import b64encode
from .common import TrezorTest
from binascii import hexlify from binascii import hexlify
from trezorlib import messages as proto
from trezorlib import stellar
from trezorlib.tools import parse_path
import pytest import pytest
from trezorlib import messages as proto, stellar
from trezorlib.tools import parse_path
from .common import TrezorTest
@pytest.mark.stellar @pytest.mark.stellar
class TestMsgStellarSignTransaction(TrezorTest): class TestMsgStellarSignTransaction(TrezorTest):
ADDRESS_N = parse_path(stellar.DEFAULT_BIP32_PATH) ADDRESS_N = parse_path(stellar.DEFAULT_BIP32_PATH)
NETWORK_PASSPHRASE = 'Test SDF Network ; September 2015' NETWORK_PASSPHRASE = "Test SDF Network ; September 2015"
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()
@ -68,35 +70,55 @@ class TestMsgStellarSignTransaction(TrezorTest):
op.bump_to = 0x7fffffffffffffff op.bump_to = 0x7fffffffffffffff
tx = self._create_msg() tx = self._create_msg()
response = stellar.sign_tx(self.client, tx, [op], self.ADDRESS_N, self.NETWORK_PASSPHRASE) response = stellar.sign_tx(
assert b64encode(response.signature) == b'ZMIfHWhpyXdg40PzwOtkcXYnbZIO12Qy0WvkGqoYpb7jyWbG2HQCG7dgWhCoU5K81pvZTA2pMwiPjMwCXA//Bg==' self.client, tx, [op], self.ADDRESS_N, self.NETWORK_PASSPHRASE
)
assert (
b64encode(response.signature)
== b"ZMIfHWhpyXdg40PzwOtkcXYnbZIO12Qy0WvkGqoYpb7jyWbG2HQCG7dgWhCoU5K81pvZTA2pMwiPjMwCXA//Bg=="
)
def test_sign_tx_account_merge_op(self): def test_sign_tx_account_merge_op(self):
self.setup_mnemonic_nopin_nopassphrase() self.setup_mnemonic_nopin_nopassphrase()
op = proto.StellarAccountMergeOp() op = proto.StellarAccountMergeOp()
op.destination_account = 'GBOVKZBEM2YYLOCDCUXJ4IMRKHN4LCJAE7WEAEA2KF562XFAGDBOB64V' op.destination_account = (
"GBOVKZBEM2YYLOCDCUXJ4IMRKHN4LCJAE7WEAEA2KF562XFAGDBOB64V"
)
tx = self._create_msg() tx = self._create_msg()
response = stellar.sign_tx(self.client, tx, [op], self.ADDRESS_N, self.NETWORK_PASSPHRASE) response = stellar.sign_tx(
self.client, tx, [op], self.ADDRESS_N, self.NETWORK_PASSPHRASE
)
assert hexlify(response.public_key) == b'15d648bfe4d36f196cfb5735ffd8ca54cd4b8233f743f22449de7cf301cdb469' assert (
assert b64encode(response.signature) == b'2R3Pj89U+dWrqy7otUrLLjtANjAg0lmBQL8E+89Po0Y94oqZkauP8j3WE7+/z7vF6XvAMLoOdqRYkUzr2oh7Dg==' hexlify(response.public_key)
== b"15d648bfe4d36f196cfb5735ffd8ca54cd4b8233f743f22449de7cf301cdb469"
)
assert (
b64encode(response.signature)
== b"2R3Pj89U+dWrqy7otUrLLjtANjAg0lmBQL8E+89Po0Y94oqZkauP8j3WE7+/z7vF6XvAMLoOdqRYkUzr2oh7Dg=="
)
def test_sign_tx_create_account_op(self): def test_sign_tx_create_account_op(self):
"""Create new account with initial balance of 100.0333""" """Create new account with initial balance of 100.0333"""
self.setup_mnemonic_nopin_nopassphrase() self.setup_mnemonic_nopin_nopassphrase()
op = proto.StellarCreateAccountOp() op = proto.StellarCreateAccountOp()
op.new_account = 'GBOVKZBEM2YYLOCDCUXJ4IMRKHN4LCJAE7WEAEA2KF562XFAGDBOB64V' op.new_account = "GBOVKZBEM2YYLOCDCUXJ4IMRKHN4LCJAE7WEAEA2KF562XFAGDBOB64V"
op.starting_balance = 1000333000 op.starting_balance = 1000333000
tx = self._create_msg() tx = self._create_msg()
response = stellar.sign_tx(self.client, tx, [op], self.ADDRESS_N, self.NETWORK_PASSPHRASE) response = stellar.sign_tx(
self.client, tx, [op], self.ADDRESS_N, self.NETWORK_PASSPHRASE
)
assert b64encode(response.signature) == b'vrRYqkM4b54NrDR05UrW7ZHU7CNcidV0fn+bk9dqOW1bCbmX3YfeRbk2Tf1aea8nr9SD0sfBhtrDpdyxUenjBw==' assert (
b64encode(response.signature)
== b"vrRYqkM4b54NrDR05UrW7ZHU7CNcidV0fn+bk9dqOW1bCbmX3YfeRbk2Tf1aea8nr9SD0sfBhtrDpdyxUenjBw=="
)
def test_sign_tx_payment_op_native(self): def test_sign_tx_payment_op_native(self):
"""Native payment of 50.0111 XLM to GBOVKZBEM2YYLOCDCUXJ4IMRKHN4LCJAE7WEAEA2KF562XFAGDBOB64V""" """Native payment of 50.0111 XLM to GBOVKZBEM2YYLOCDCUXJ4IMRKHN4LCJAE7WEAEA2KF562XFAGDBOB64V"""
@ -104,13 +126,20 @@ class TestMsgStellarSignTransaction(TrezorTest):
op = proto.StellarPaymentOp() op = proto.StellarPaymentOp()
op.amount = 500111000 op.amount = 500111000
op.destination_account = 'GBOVKZBEM2YYLOCDCUXJ4IMRKHN4LCJAE7WEAEA2KF562XFAGDBOB64V' op.destination_account = (
"GBOVKZBEM2YYLOCDCUXJ4IMRKHN4LCJAE7WEAEA2KF562XFAGDBOB64V"
)
tx = self._create_msg() tx = self._create_msg()
response = stellar.sign_tx(self.client, tx, [op], self.ADDRESS_N, self.NETWORK_PASSPHRASE) response = stellar.sign_tx(
self.client, tx, [op], self.ADDRESS_N, self.NETWORK_PASSPHRASE
)
assert b64encode(response.signature) == b'pDc6ghKCLNoYbt3h4eBw+533237m0BB0Jp/d/TxJCA83mF3o5Fr4l5vwAWBR62hdTWAP9MhVluY0cd5i54UwDg==' assert (
b64encode(response.signature)
== b"pDc6ghKCLNoYbt3h4eBw+533237m0BB0Jp/d/TxJCA83mF3o5Fr4l5vwAWBR62hdTWAP9MhVluY0cd5i54UwDg=="
)
def test_sign_tx_payment_op_custom_asset1(self): def test_sign_tx_payment_op_custom_asset1(self):
"""Custom asset payment (code length 1) of 50.0111 X to GBOVKZBEM2YYLOCDCUXJ4IMRKHN4LCJAE7WEAEA2KF562XFAGDBOB64V""" """Custom asset payment (code length 1) of 50.0111 X to GBOVKZBEM2YYLOCDCUXJ4IMRKHN4LCJAE7WEAEA2KF562XFAGDBOB64V"""
@ -118,14 +147,23 @@ class TestMsgStellarSignTransaction(TrezorTest):
op = proto.StellarPaymentOp() op = proto.StellarPaymentOp()
op.amount = 500111000 op.amount = 500111000
op.destination_account = 'GBOVKZBEM2YYLOCDCUXJ4IMRKHN4LCJAE7WEAEA2KF562XFAGDBOB64V' op.destination_account = (
"GBOVKZBEM2YYLOCDCUXJ4IMRKHN4LCJAE7WEAEA2KF562XFAGDBOB64V"
)
op.asset = proto.StellarAssetType(1, 'X', 'GAUYJFQCYIHFQNS7CI6BFWD2DSSFKDIQZUQ3BLQODDKE4PSW7VVBKENC') op.asset = proto.StellarAssetType(
1, "X", "GAUYJFQCYIHFQNS7CI6BFWD2DSSFKDIQZUQ3BLQODDKE4PSW7VVBKENC"
)
tx = self._create_msg() tx = self._create_msg()
response = stellar.sign_tx(self.client, tx, [op], self.ADDRESS_N, self.NETWORK_PASSPHRASE) response = stellar.sign_tx(
self.client, tx, [op], self.ADDRESS_N, self.NETWORK_PASSPHRASE
)
assert b64encode(response.signature) == b'ArZydOtXU2whoRuSjJLFIWPSIsq3AbsncJZ+THF24CRSriVWw5Fy/dHrDlUOu4fzU28I6osDMeI39aWezg5tDw==' assert (
b64encode(response.signature)
== b"ArZydOtXU2whoRuSjJLFIWPSIsq3AbsncJZ+THF24CRSriVWw5Fy/dHrDlUOu4fzU28I6osDMeI39aWezg5tDw=="
)
def test_sign_tx_payment_op_custom_asset12(self): def test_sign_tx_payment_op_custom_asset12(self):
"""Custom asset payment (code length 12) of 50.0111 ABCDEFGHIJKL to GBOVKZBEM2YYLOCDCUXJ4IMRKHN4LCJAE7WEAEA2KF562XFAGDBOB64V""" """Custom asset payment (code length 12) of 50.0111 ABCDEFGHIJKL to GBOVKZBEM2YYLOCDCUXJ4IMRKHN4LCJAE7WEAEA2KF562XFAGDBOB64V"""
@ -133,30 +171,48 @@ class TestMsgStellarSignTransaction(TrezorTest):
op = proto.StellarPaymentOp() op = proto.StellarPaymentOp()
op.amount = 500111000 op.amount = 500111000
op.destination_account = 'GBOVKZBEM2YYLOCDCUXJ4IMRKHN4LCJAE7WEAEA2KF562XFAGDBOB64V' op.destination_account = (
"GBOVKZBEM2YYLOCDCUXJ4IMRKHN4LCJAE7WEAEA2KF562XFAGDBOB64V"
)
op.asset = proto.StellarAssetType(2, 'ABCDEFGHIJKL', 'GAUYJFQCYIHFQNS7CI6BFWD2DSSFKDIQZUQ3BLQODDKE4PSW7VVBKENC') op.asset = proto.StellarAssetType(
2,
"ABCDEFGHIJKL",
"GAUYJFQCYIHFQNS7CI6BFWD2DSSFKDIQZUQ3BLQODDKE4PSW7VVBKENC",
)
tx = self._create_msg() tx = self._create_msg()
response = stellar.sign_tx(self.client, tx, [op], self.ADDRESS_N, self.NETWORK_PASSPHRASE) response = stellar.sign_tx(
self.client, tx, [op], self.ADDRESS_N, self.NETWORK_PASSPHRASE
)
assert b64encode(response.signature) == b'QZIP4XKPfe4OpZtuJiyrMZBX9YBzvGpHGcngdgFfHn2kcdONreF384/pCF80xfEnGm8grKaoOnUEKxqcMKvxAA==' assert (
b64encode(response.signature)
== b"QZIP4XKPfe4OpZtuJiyrMZBX9YBzvGpHGcngdgFfHn2kcdONreF384/pCF80xfEnGm8grKaoOnUEKxqcMKvxAA=="
)
def test_sign_tx_set_options_op_inflation(self): def test_sign_tx_set_options_op_inflation(self):
"""Set inflation destination""" """Set inflation destination"""
self.setup_mnemonic_nopin_nopassphrase() self.setup_mnemonic_nopin_nopassphrase()
op = proto.StellarSetOptionsOp() op = proto.StellarSetOptionsOp()
op.inflation_destination_account = 'GAFXTC5OV5XQD66T7WGOB2HUVUC3ZVJDJMBDPTVQYV3G3K7TUHC6CLBR' op.inflation_destination_account = (
"GAFXTC5OV5XQD66T7WGOB2HUVUC3ZVJDJMBDPTVQYV3G3K7TUHC6CLBR"
)
tx = self._create_msg() tx = self._create_msg()
response = stellar.sign_tx(self.client, tx, [op], self.ADDRESS_N, self.NETWORK_PASSPHRASE) response = stellar.sign_tx(
self.client, tx, [op], self.ADDRESS_N, self.NETWORK_PASSPHRASE
)
assert b64encode(response.signature) == b'dveWhKY8x7b0YqGHWH6Fo1SskxaHP11NXd2n6oHKGiv+T/LqB+CCzbmJA0tplZ+0HNPJbHD7L3Bsg/y462qLDA==' assert (
b64encode(response.signature)
== b"dveWhKY8x7b0YqGHWH6Fo1SskxaHP11NXd2n6oHKGiv+T/LqB+CCzbmJA0tplZ+0HNPJbHD7L3Bsg/y462qLDA=="
)
def _create_msg(self) -> proto.StellarSignTx: def _create_msg(self) -> proto.StellarSignTx:
tx = proto.StellarSignTx() tx = proto.StellarSignTx()
tx.source_account = 'GAK5MSF74TJW6GLM7NLTL76YZJKM2S4CGP3UH4REJHPHZ4YBZW2GSBPW' tx.source_account = "GAK5MSF74TJW6GLM7NLTL76YZJKM2S4CGP3UH4REJHPHZ4YBZW2GSBPW"
tx.fee = 100 tx.fee = 100
tx.sequence_number = 0x100000000 tx.sequence_number = 0x100000000
tx.memo_type = 0 tx.memo_type = 0

View File

@ -16,20 +16,22 @@
from binascii import unhexlify from binascii import unhexlify
from .common import TrezorTest
from trezorlib import btc from trezorlib import btc
from .common import TrezorTest
class TestMsgVerifymessage(TrezorTest): class TestMsgVerifymessage(TrezorTest):
def test_message_long(self): def test_message_long(self):
self.setup_mnemonic_nopin_nopassphrase() self.setup_mnemonic_nopin_nopassphrase()
ret = btc.verify_message( ret = btc.verify_message(
self.client, self.client,
'Bitcoin', "Bitcoin",
'14LmW5k4ssUrtbAB4255zdqv3b4w1TuX9e', "14LmW5k4ssUrtbAB4255zdqv3b4w1TuX9e",
unhexlify('205ff795c29aef7538f8b3bdb2e8add0d0722ad630a140b6aefd504a5a895cbd867cbb00981afc50edd0398211e8d7c304bb8efa461181bc0afa67ea4a720a89ed'), unhexlify(
"VeryLongMessage!" * 64 "205ff795c29aef7538f8b3bdb2e8add0d0722ad630a140b6aefd504a5a895cbd867cbb00981afc50edd0398211e8d7c304bb8efa461181bc0afa67ea4a720a89ed"
),
"VeryLongMessage!" * 64,
) )
assert ret is True assert ret is True
@ -37,10 +39,12 @@ class TestMsgVerifymessage(TrezorTest):
self.setup_mnemonic_nopin_nopassphrase() self.setup_mnemonic_nopin_nopassphrase()
ret = btc.verify_message( ret = btc.verify_message(
self.client, self.client,
'Testnet', "Testnet",
'mirio8q3gtv7fhdnmb3TpZ4EuafdzSs7zL', "mirio8q3gtv7fhdnmb3TpZ4EuafdzSs7zL",
unhexlify('209e23edf0e4e47ff1dec27f32cd78c50e74ef018ee8a6adf35ae17c7a9b0dd96f48b493fd7dbab03efb6f439c6383c9523b3bbc5f1a7d158a6af90ab154e9be80'), unhexlify(
'This is an example of a signed message.' "209e23edf0e4e47ff1dec27f32cd78c50e74ef018ee8a6adf35ae17c7a9b0dd96f48b493fd7dbab03efb6f439c6383c9523b3bbc5f1a7d158a6af90ab154e9be80"
),
"This is an example of a signed message.",
) )
assert ret is True assert ret is True
@ -50,88 +54,108 @@ class TestMsgVerifymessage(TrezorTest):
# uncompressed pubkey - OK # uncompressed pubkey - OK
res = btc.verify_message( res = btc.verify_message(
self.client, self.client,
'Bitcoin', "Bitcoin",
'1JwSSubhmg6iPtRjtyqhUYYH7bZg3Lfy1T', "1JwSSubhmg6iPtRjtyqhUYYH7bZg3Lfy1T",
unhexlify('1ba77e01a9e17ba158b962cfef5f13dfed676ffc2b4bada24e58f784458b52b97421470d001d53d5880cf5e10e76f02be3e80bf21e18398cbd41e8c3b4af74c8c2'), unhexlify(
'This is an example of a signed message.' "1ba77e01a9e17ba158b962cfef5f13dfed676ffc2b4bada24e58f784458b52b97421470d001d53d5880cf5e10e76f02be3e80bf21e18398cbd41e8c3b4af74c8c2"
),
"This is an example of a signed message.",
) )
assert res is True assert res is True
# uncompressed pubkey - FAIL - wrong sig # uncompressed pubkey - FAIL - wrong sig
res = btc.verify_message( res = btc.verify_message(
self.client, self.client,
'Bitcoin', "Bitcoin",
'1JwSSubhmg6iPtRjtyqhUYYH7bZg3Lfy1T', "1JwSSubhmg6iPtRjtyqhUYYH7bZg3Lfy1T",
unhexlify('1ba77e01a9e17ba158b962cfef5f13dfed676ffc2b4bada24e58f784458b52b97421470d001d53d5880cf5e10e76f02be3e80bf21e18398cbd41e8c3b4af74c800'), unhexlify(
'This is an example of a signed message.' "1ba77e01a9e17ba158b962cfef5f13dfed676ffc2b4bada24e58f784458b52b97421470d001d53d5880cf5e10e76f02be3e80bf21e18398cbd41e8c3b4af74c800"
),
"This is an example of a signed message.",
) )
assert res is False assert res is False
# uncompressed pubkey - FAIL - wrong msg # uncompressed pubkey - FAIL - wrong msg
res = btc.verify_message( res = btc.verify_message(
self.client, self.client,
'Bitcoin', "Bitcoin",
'1JwSSubhmg6iPtRjtyqhUYYH7bZg3Lfy1T', "1JwSSubhmg6iPtRjtyqhUYYH7bZg3Lfy1T",
unhexlify('1ba77e01a9e17ba158b962cfef5f13dfed676ffc2b4bada24e58f784458b52b97421470d001d53d5880cf5e10e76f02be3e80bf21e18398cbd41e8c3b4af74c8c2'), unhexlify(
'This is an example of a signed message!' "1ba77e01a9e17ba158b962cfef5f13dfed676ffc2b4bada24e58f784458b52b97421470d001d53d5880cf5e10e76f02be3e80bf21e18398cbd41e8c3b4af74c8c2"
),
"This is an example of a signed message!",
) )
assert res is False assert res is False
# compressed pubkey - OK # compressed pubkey - OK
res = btc.verify_message( res = btc.verify_message(
self.client, self.client,
'Bitcoin', "Bitcoin",
'1C7zdTfnkzmr13HfA2vNm5SJYRK6nEKyq8', "1C7zdTfnkzmr13HfA2vNm5SJYRK6nEKyq8",
unhexlify('1f44e3e461f7ca9f57c472ce1a28214df1de1dadefb6551a32d1907b80c74d5a1fbfd6daaba12dd8cb06699ce3f6941fbe0f3957b5802d13076181046e741eaaaf'), unhexlify(
'This is an example of a signed message.') "1f44e3e461f7ca9f57c472ce1a28214df1de1dadefb6551a32d1907b80c74d5a1fbfd6daaba12dd8cb06699ce3f6941fbe0f3957b5802d13076181046e741eaaaf"
),
"This is an example of a signed message.",
)
assert res is True assert res is True
# compressed pubkey - FAIL - wrong sig # compressed pubkey - FAIL - wrong sig
res = btc.verify_message( res = btc.verify_message(
self.client, self.client,
'Bitcoin', "Bitcoin",
'1C7zdTfnkzmr13HfA2vNm5SJYRK6nEKyq8', "1C7zdTfnkzmr13HfA2vNm5SJYRK6nEKyq8",
unhexlify('1f44e3e461f7ca9f57c472ce1a28214df1de1dadefb6551a32d1907b80c74d5a1fbfd6daaba12dd8cb06699ce3f6941fbe0f3957b5802d13076181046e741eaa00'), unhexlify(
'This is an example of a signed message.' "1f44e3e461f7ca9f57c472ce1a28214df1de1dadefb6551a32d1907b80c74d5a1fbfd6daaba12dd8cb06699ce3f6941fbe0f3957b5802d13076181046e741eaa00"
),
"This is an example of a signed message.",
) )
assert res is False assert res is False
# compressed pubkey - FAIL - wrong msg # compressed pubkey - FAIL - wrong msg
res = btc.verify_message( res = btc.verify_message(
self.client, self.client,
'Bitcoin', "Bitcoin",
'1C7zdTfnkzmr13HfA2vNm5SJYRK6nEKyq8', "1C7zdTfnkzmr13HfA2vNm5SJYRK6nEKyq8",
unhexlify('1f44e3e461f7ca9f57c472ce1a28214df1de1dadefb6551a32d1907b80c74d5a1fbfd6daaba12dd8cb06699ce3f6941fbe0f3957b5802d13076181046e741eaaaf'), unhexlify(
'This is an example of a signed message!') "1f44e3e461f7ca9f57c472ce1a28214df1de1dadefb6551a32d1907b80c74d5a1fbfd6daaba12dd8cb06699ce3f6941fbe0f3957b5802d13076181046e741eaaaf"
),
"This is an example of a signed message!",
)
assert res is False assert res is False
# trezor pubkey - OK # trezor pubkey - OK
res = btc.verify_message( res = btc.verify_message(
self.client, self.client,
'Bitcoin', "Bitcoin",
'14LmW5k4ssUrtbAB4255zdqv3b4w1TuX9e', "14LmW5k4ssUrtbAB4255zdqv3b4w1TuX9e",
unhexlify('209e23edf0e4e47ff1dec27f32cd78c50e74ef018ee8a6adf35ae17c7a9b0dd96f48b493fd7dbab03efb6f439c6383c9523b3bbc5f1a7d158a6af90ab154e9be80'), unhexlify(
'This is an example of a signed message.' "209e23edf0e4e47ff1dec27f32cd78c50e74ef018ee8a6adf35ae17c7a9b0dd96f48b493fd7dbab03efb6f439c6383c9523b3bbc5f1a7d158a6af90ab154e9be80"
),
"This is an example of a signed message.",
) )
assert res is True assert res is True
# trezor pubkey - FAIL - wrong sig # trezor pubkey - FAIL - wrong sig
res = btc.verify_message( res = btc.verify_message(
self.client, self.client,
'Bitcoin', "Bitcoin",
'14LmW5k4ssUrtbAB4255zdqv3b4w1TuX9e', "14LmW5k4ssUrtbAB4255zdqv3b4w1TuX9e",
unhexlify('209e23edf0e4e47ff1dec27f32cd78c50e74ef018ee8a6adf35ae17c7a9b0dd96f48b493fd7dbab03efb6f439c6383c9523b3bbc5f1a7d158a6af90ab154e9be00'), unhexlify(
'This is an example of a signed message.' "209e23edf0e4e47ff1dec27f32cd78c50e74ef018ee8a6adf35ae17c7a9b0dd96f48b493fd7dbab03efb6f439c6383c9523b3bbc5f1a7d158a6af90ab154e9be00"
),
"This is an example of a signed message.",
) )
assert res is False assert res is False
# trezor pubkey - FAIL - wrong msg # trezor pubkey - FAIL - wrong msg
res = btc.verify_message( res = btc.verify_message(
self.client, self.client,
'Bitcoin', "Bitcoin",
'14LmW5k4ssUrtbAB4255zdqv3b4w1TuX9e', "14LmW5k4ssUrtbAB4255zdqv3b4w1TuX9e",
unhexlify('209e23edf0e4e47ff1dec27f32cd78c50e74ef018ee8a6adf35ae17c7a9b0dd96f48b493fd7dbab03efb6f439c6383c9523b3bbc5f1a7d158a6af90ab154e9be80'), unhexlify(
'This is an example of a signed message!' "209e23edf0e4e47ff1dec27f32cd78c50e74ef018ee8a6adf35ae17c7a9b0dd96f48b493fd7dbab03efb6f439c6383c9523b3bbc5f1a7d158a6af90ab154e9be80"
),
"This is an example of a signed message!",
) )
assert res is False assert res is False
@ -139,10 +163,12 @@ class TestMsgVerifymessage(TrezorTest):
self.setup_mnemonic_nopin_nopassphrase() self.setup_mnemonic_nopin_nopassphrase()
res = btc.verify_message( res = btc.verify_message(
self.client, self.client,
'Bcash', "Bcash",
'bitcoincash:qqj22md58nm09vpwsw82fyletkxkq36zxyxh322pru', "bitcoincash:qqj22md58nm09vpwsw82fyletkxkq36zxyxh322pru",
unhexlify('209e23edf0e4e47ff1dec27f32cd78c50e74ef018ee8a6adf35ae17c7a9b0dd96f48b493fd7dbab03efb6f439c6383c9523b3bbc5f1a7d158a6af90ab154e9be80'), unhexlify(
'This is an example of a signed message.' "209e23edf0e4e47ff1dec27f32cd78c50e74ef018ee8a6adf35ae17c7a9b0dd96f48b493fd7dbab03efb6f439c6383c9523b3bbc5f1a7d158a6af90ab154e9be80"
),
"This is an example of a signed message.",
) )
assert res is True assert res is True
@ -151,10 +177,12 @@ class TestMsgVerifymessage(TrezorTest):
res = btc.verify_message( res = btc.verify_message(
self.client, self.client,
'Bitcoin', "Bitcoin",
'1KzXE97kV7DrpxCViCN3HbGbiKhzzPM7TQ', "1KzXE97kV7DrpxCViCN3HbGbiKhzzPM7TQ",
unhexlify('1cc694f0f23901dfe3603789142f36a3fc582d0d5c0ec7215cf2ccd641e4e37228504f3d4dc3eea28bbdbf5da27c49d4635c097004d9f228750ccd836a8e1460c0'), unhexlify(
u'\u017elu\u0165ou\u010dk\xfd k\u016f\u0148 \xfap\u011bl \u010f\xe1belsk\xe9 \xf3dy' "1cc694f0f23901dfe3603789142f36a3fc582d0d5c0ec7215cf2ccd641e4e37228504f3d4dc3eea28bbdbf5da27c49d4635c097004d9f228750ccd836a8e1460c0"
),
u"\u017elu\u0165ou\u010dk\xfd k\u016f\u0148 \xfap\u011bl \u010f\xe1belsk\xe9 \xf3dy",
) )
assert res is True assert res is True
@ -162,23 +190,27 @@ class TestMsgVerifymessage(TrezorTest):
def test_verify_utf(self): def test_verify_utf(self):
self.setup_mnemonic_nopin_nopassphrase() self.setup_mnemonic_nopin_nopassphrase()
words_nfkd = u'Pr\u030ci\u0301s\u030cerne\u030c z\u030clut\u030couc\u030cky\u0301 ku\u030an\u030c u\u0301pe\u030cl d\u030ca\u0301belske\u0301 o\u0301dy za\u0301ker\u030cny\u0301 uc\u030cen\u030c be\u030cz\u030ci\u0301 pode\u0301l zo\u0301ny u\u0301lu\u030a' words_nfkd = u"Pr\u030ci\u0301s\u030cerne\u030c z\u030clut\u030couc\u030cky\u0301 ku\u030an\u030c u\u0301pe\u030cl d\u030ca\u0301belske\u0301 o\u0301dy za\u0301ker\u030cny\u0301 uc\u030cen\u030c be\u030cz\u030ci\u0301 pode\u0301l zo\u0301ny u\u0301lu\u030a"
words_nfc = u'P\u0159\xed\u0161ern\u011b \u017elu\u0165ou\u010dk\xfd k\u016f\u0148 \xfap\u011bl \u010f\xe1belsk\xe9 \xf3dy z\xe1ke\u0159n\xfd u\u010de\u0148 b\u011b\u017e\xed pod\xe9l z\xf3ny \xfal\u016f' words_nfc = u"P\u0159\xed\u0161ern\u011b \u017elu\u0165ou\u010dk\xfd k\u016f\u0148 \xfap\u011bl \u010f\xe1belsk\xe9 \xf3dy z\xe1ke\u0159n\xfd u\u010de\u0148 b\u011b\u017e\xed pod\xe9l z\xf3ny \xfal\u016f"
res_nfkd = btc.verify_message( res_nfkd = btc.verify_message(
self.client, self.client,
'Bitcoin', "Bitcoin",
'14LmW5k4ssUrtbAB4255zdqv3b4w1TuX9e', "14LmW5k4ssUrtbAB4255zdqv3b4w1TuX9e",
unhexlify('20d0ec02ed8da8df23e7fe9e680e7867cc290312fe1c970749d8306ddad1a1eda41c6a771b13d495dd225b13b0a9d0f915a984ee3d0703f92287bf8009fbb9f7d6'), unhexlify(
words_nfkd "20d0ec02ed8da8df23e7fe9e680e7867cc290312fe1c970749d8306ddad1a1eda41c6a771b13d495dd225b13b0a9d0f915a984ee3d0703f92287bf8009fbb9f7d6"
),
words_nfkd,
) )
res_nfc = btc.verify_message( res_nfc = btc.verify_message(
self.client, self.client,
'Bitcoin', "Bitcoin",
'14LmW5k4ssUrtbAB4255zdqv3b4w1TuX9e', "14LmW5k4ssUrtbAB4255zdqv3b4w1TuX9e",
unhexlify('20d0ec02ed8da8df23e7fe9e680e7867cc290312fe1c970749d8306ddad1a1eda41c6a771b13d495dd225b13b0a9d0f915a984ee3d0703f92287bf8009fbb9f7d6'), unhexlify(
words_nfc "20d0ec02ed8da8df23e7fe9e680e7867cc290312fe1c970749d8306ddad1a1eda41c6a771b13d495dd225b13b0a9d0f915a984ee3d0703f92287bf8009fbb9f7d6"
),
words_nfc,
) )
assert res_nfkd is True assert res_nfkd is True

View File

@ -16,20 +16,22 @@
from binascii import unhexlify from binascii import unhexlify
from .common import TrezorTest
from trezorlib import btc from trezorlib import btc
from .common import TrezorTest
class TestMsgVerifymessageSegwit(TrezorTest): class TestMsgVerifymessageSegwit(TrezorTest):
def test_message_long(self): def test_message_long(self):
self.setup_mnemonic_nopin_nopassphrase() self.setup_mnemonic_nopin_nopassphrase()
ret = btc.verify_message( ret = btc.verify_message(
self.client, self.client,
'Bitcoin', "Bitcoin",
'3CwYaeWxhpXXiHue3ciQez1DLaTEAXcKa1', "3CwYaeWxhpXXiHue3ciQez1DLaTEAXcKa1",
unhexlify('245ff795c29aef7538f8b3bdb2e8add0d0722ad630a140b6aefd504a5a895cbd867cbb00981afc50edd0398211e8d7c304bb8efa461181bc0afa67ea4a720a89ed'), unhexlify(
"VeryLongMessage!" * 64 "245ff795c29aef7538f8b3bdb2e8add0d0722ad630a140b6aefd504a5a895cbd867cbb00981afc50edd0398211e8d7c304bb8efa461181bc0afa67ea4a720a89ed"
),
"VeryLongMessage!" * 64,
) )
assert ret is True assert ret is True
@ -37,10 +39,12 @@ class TestMsgVerifymessageSegwit(TrezorTest):
self.setup_mnemonic_nopin_nopassphrase() self.setup_mnemonic_nopin_nopassphrase()
ret = btc.verify_message( ret = btc.verify_message(
self.client, self.client,
'Testnet', "Testnet",
'2N4VkePSzKH2sv5YBikLHGvzUYvfPxV6zS9', "2N4VkePSzKH2sv5YBikLHGvzUYvfPxV6zS9",
unhexlify('249e23edf0e4e47ff1dec27f32cd78c50e74ef018ee8a6adf35ae17c7a9b0dd96f48b493fd7dbab03efb6f439c6383c9523b3bbc5f1a7d158a6af90ab154e9be80'), unhexlify(
'This is an example of a signed message.' "249e23edf0e4e47ff1dec27f32cd78c50e74ef018ee8a6adf35ae17c7a9b0dd96f48b493fd7dbab03efb6f439c6383c9523b3bbc5f1a7d158a6af90ab154e9be80"
),
"This is an example of a signed message.",
) )
assert ret is True assert ret is True
@ -50,53 +54,63 @@ class TestMsgVerifymessageSegwit(TrezorTest):
# trezor pubkey - OK # trezor pubkey - OK
res = btc.verify_message( res = btc.verify_message(
self.client, self.client,
'Bitcoin', "Bitcoin",
'3CwYaeWxhpXXiHue3ciQez1DLaTEAXcKa1', "3CwYaeWxhpXXiHue3ciQez1DLaTEAXcKa1",
unhexlify('249e23edf0e4e47ff1dec27f32cd78c50e74ef018ee8a6adf35ae17c7a9b0dd96f48b493fd7dbab03efb6f439c6383c9523b3bbc5f1a7d158a6af90ab154e9be80'), unhexlify(
'This is an example of a signed message.' "249e23edf0e4e47ff1dec27f32cd78c50e74ef018ee8a6adf35ae17c7a9b0dd96f48b493fd7dbab03efb6f439c6383c9523b3bbc5f1a7d158a6af90ab154e9be80"
),
"This is an example of a signed message.",
) )
assert res is True assert res is True
# trezor pubkey - FAIL - wrong sig # trezor pubkey - FAIL - wrong sig
res = btc.verify_message( res = btc.verify_message(
self.client, self.client,
'Bitcoin', "Bitcoin",
'3CwYaeWxhpXXiHue3ciQez1DLaTEAXcKa1', "3CwYaeWxhpXXiHue3ciQez1DLaTEAXcKa1",
unhexlify('249e23edf0e4e47ff1dec27f32cd78c50e74ef018ee8a6adf35ae17c7a9b0dd96f48b493fd7dbab03efb6f439c6383c9523b3bbc5f1a7d158a6af90ab154e9be00'), unhexlify(
'This is an example of a signed message.' "249e23edf0e4e47ff1dec27f32cd78c50e74ef018ee8a6adf35ae17c7a9b0dd96f48b493fd7dbab03efb6f439c6383c9523b3bbc5f1a7d158a6af90ab154e9be00"
),
"This is an example of a signed message.",
) )
assert res is False assert res is False
# trezor pubkey - FAIL - wrong msg # trezor pubkey - FAIL - wrong msg
res = btc.verify_message( res = btc.verify_message(
self.client, self.client,
'Bitcoin', "Bitcoin",
'3CwYaeWxhpXXiHue3ciQez1DLaTEAXcKa1', "3CwYaeWxhpXXiHue3ciQez1DLaTEAXcKa1",
unhexlify('249e23edf0e4e47ff1dec27f32cd78c50e74ef018ee8a6adf35ae17c7a9b0dd96f48b493fd7dbab03efb6f439c6383c9523b3bbc5f1a7d158a6af90ab154e9be80'), unhexlify(
'This is an example of a signed message!' "249e23edf0e4e47ff1dec27f32cd78c50e74ef018ee8a6adf35ae17c7a9b0dd96f48b493fd7dbab03efb6f439c6383c9523b3bbc5f1a7d158a6af90ab154e9be80"
),
"This is an example of a signed message!",
) )
assert res is False assert res is False
def test_verify_utf(self): def test_verify_utf(self):
self.setup_mnemonic_nopin_nopassphrase() self.setup_mnemonic_nopin_nopassphrase()
words_nfkd = u'Pr\u030ci\u0301s\u030cerne\u030c z\u030clut\u030couc\u030cky\u0301 ku\u030an\u030c u\u0301pe\u030cl d\u030ca\u0301belske\u0301 o\u0301dy za\u0301ker\u030cny\u0301 uc\u030cen\u030c be\u030cz\u030ci\u0301 pode\u0301l zo\u0301ny u\u0301lu\u030a' words_nfkd = u"Pr\u030ci\u0301s\u030cerne\u030c z\u030clut\u030couc\u030cky\u0301 ku\u030an\u030c u\u0301pe\u030cl d\u030ca\u0301belske\u0301 o\u0301dy za\u0301ker\u030cny\u0301 uc\u030cen\u030c be\u030cz\u030ci\u0301 pode\u0301l zo\u0301ny u\u0301lu\u030a"
words_nfc = u'P\u0159\xed\u0161ern\u011b \u017elu\u0165ou\u010dk\xfd k\u016f\u0148 \xfap\u011bl \u010f\xe1belsk\xe9 \xf3dy z\xe1ke\u0159n\xfd u\u010de\u0148 b\u011b\u017e\xed pod\xe9l z\xf3ny \xfal\u016f' words_nfc = u"P\u0159\xed\u0161ern\u011b \u017elu\u0165ou\u010dk\xfd k\u016f\u0148 \xfap\u011bl \u010f\xe1belsk\xe9 \xf3dy z\xe1ke\u0159n\xfd u\u010de\u0148 b\u011b\u017e\xed pod\xe9l z\xf3ny \xfal\u016f"
res_nfkd = btc.verify_message( res_nfkd = btc.verify_message(
self.client, self.client,
'Bitcoin', "Bitcoin",
'3CwYaeWxhpXXiHue3ciQez1DLaTEAXcKa1', "3CwYaeWxhpXXiHue3ciQez1DLaTEAXcKa1",
unhexlify('24d0ec02ed8da8df23e7fe9e680e7867cc290312fe1c970749d8306ddad1a1eda41c6a771b13d495dd225b13b0a9d0f915a984ee3d0703f92287bf8009fbb9f7d6'), unhexlify(
words_nfkd "24d0ec02ed8da8df23e7fe9e680e7867cc290312fe1c970749d8306ddad1a1eda41c6a771b13d495dd225b13b0a9d0f915a984ee3d0703f92287bf8009fbb9f7d6"
),
words_nfkd,
) )
res_nfc = btc.verify_message( res_nfc = btc.verify_message(
self.client, self.client,
'Bitcoin', "Bitcoin",
'3CwYaeWxhpXXiHue3ciQez1DLaTEAXcKa1', "3CwYaeWxhpXXiHue3ciQez1DLaTEAXcKa1",
unhexlify('24d0ec02ed8da8df23e7fe9e680e7867cc290312fe1c970749d8306ddad1a1eda41c6a771b13d495dd225b13b0a9d0f915a984ee3d0703f92287bf8009fbb9f7d6'), unhexlify(
words_nfc "24d0ec02ed8da8df23e7fe9e680e7867cc290312fe1c970749d8306ddad1a1eda41c6a771b13d495dd225b13b0a9d0f915a984ee3d0703f92287bf8009fbb9f7d6"
),
words_nfc,
) )
assert res_nfkd is True assert res_nfkd is True

View File

@ -16,20 +16,22 @@
from binascii import unhexlify from binascii import unhexlify
from .common import TrezorTest
from trezorlib import btc from trezorlib import btc
from .common import TrezorTest
class TestMsgVerifymessageSegwitNative(TrezorTest): class TestMsgVerifymessageSegwitNative(TrezorTest):
def test_message_long(self): def test_message_long(self):
self.setup_mnemonic_nopin_nopassphrase() self.setup_mnemonic_nopin_nopassphrase()
ret = btc.verify_message( ret = btc.verify_message(
self.client, self.client,
'Bitcoin', "Bitcoin",
'bc1qyjjkmdpu7metqt5r36jf872a34syws33s82q2j', "bc1qyjjkmdpu7metqt5r36jf872a34syws33s82q2j",
unhexlify('285ff795c29aef7538f8b3bdb2e8add0d0722ad630a140b6aefd504a5a895cbd867cbb00981afc50edd0398211e8d7c304bb8efa461181bc0afa67ea4a720a89ed'), unhexlify(
"VeryLongMessage!" * 64 "285ff795c29aef7538f8b3bdb2e8add0d0722ad630a140b6aefd504a5a895cbd867cbb00981afc50edd0398211e8d7c304bb8efa461181bc0afa67ea4a720a89ed"
),
"VeryLongMessage!" * 64,
) )
assert ret is True assert ret is True
@ -37,10 +39,12 @@ class TestMsgVerifymessageSegwitNative(TrezorTest):
self.setup_mnemonic_nopin_nopassphrase() self.setup_mnemonic_nopin_nopassphrase()
ret = btc.verify_message( ret = btc.verify_message(
self.client, self.client,
'Testnet', "Testnet",
'tb1qyjjkmdpu7metqt5r36jf872a34syws336p3n3p', "tb1qyjjkmdpu7metqt5r36jf872a34syws336p3n3p",
unhexlify('289e23edf0e4e47ff1dec27f32cd78c50e74ef018ee8a6adf35ae17c7a9b0dd96f48b493fd7dbab03efb6f439c6383c9523b3bbc5f1a7d158a6af90ab154e9be80'), unhexlify(
'This is an example of a signed message.' "289e23edf0e4e47ff1dec27f32cd78c50e74ef018ee8a6adf35ae17c7a9b0dd96f48b493fd7dbab03efb6f439c6383c9523b3bbc5f1a7d158a6af90ab154e9be80"
),
"This is an example of a signed message.",
) )
assert ret is True assert ret is True
@ -50,53 +54,63 @@ class TestMsgVerifymessageSegwitNative(TrezorTest):
# trezor pubkey - OK # trezor pubkey - OK
res = btc.verify_message( res = btc.verify_message(
self.client, self.client,
'Bitcoin', "Bitcoin",
'bc1qyjjkmdpu7metqt5r36jf872a34syws33s82q2j', "bc1qyjjkmdpu7metqt5r36jf872a34syws33s82q2j",
unhexlify('289e23edf0e4e47ff1dec27f32cd78c50e74ef018ee8a6adf35ae17c7a9b0dd96f48b493fd7dbab03efb6f439c6383c9523b3bbc5f1a7d158a6af90ab154e9be80'), unhexlify(
'This is an example of a signed message.' "289e23edf0e4e47ff1dec27f32cd78c50e74ef018ee8a6adf35ae17c7a9b0dd96f48b493fd7dbab03efb6f439c6383c9523b3bbc5f1a7d158a6af90ab154e9be80"
),
"This is an example of a signed message.",
) )
assert res is True assert res is True
# trezor pubkey - FAIL - wrong sig # trezor pubkey - FAIL - wrong sig
res = btc.verify_message( res = btc.verify_message(
self.client, self.client,
'Bitcoin', "Bitcoin",
'bc1qyjjkmdpu7metqt5r36jf872a34syws33s82q2j', "bc1qyjjkmdpu7metqt5r36jf872a34syws33s82q2j",
unhexlify('289e23edf0e4e47ff1dec27f32cd78c50e74ef018ee8a6adf35ae17c7a9b0dd96f48b493fd7dbab03efb6f439c6383c9523b3bbc5f1a7d158a6af90ab154e9be00'), unhexlify(
'This is an example of a signed message.' "289e23edf0e4e47ff1dec27f32cd78c50e74ef018ee8a6adf35ae17c7a9b0dd96f48b493fd7dbab03efb6f439c6383c9523b3bbc5f1a7d158a6af90ab154e9be00"
),
"This is an example of a signed message.",
) )
assert res is False assert res is False
# trezor pubkey - FAIL - wrong msg # trezor pubkey - FAIL - wrong msg
res = btc.verify_message( res = btc.verify_message(
self.client, self.client,
'Bitcoin', "Bitcoin",
'bc1qyjjkmdpu7metqt5r36jf872a34syws33s82q2j', "bc1qyjjkmdpu7metqt5r36jf872a34syws33s82q2j",
unhexlify('289e23edf0e4e47ff1dec27f32cd78c50e74ef018ee8a6adf35ae17c7a9b0dd96f48b493fd7dbab03efb6f439c6383c9523b3bbc5f1a7d158a6af90ab154e9be80'), unhexlify(
'This is an example of a signed message!' "289e23edf0e4e47ff1dec27f32cd78c50e74ef018ee8a6adf35ae17c7a9b0dd96f48b493fd7dbab03efb6f439c6383c9523b3bbc5f1a7d158a6af90ab154e9be80"
),
"This is an example of a signed message!",
) )
assert res is False assert res is False
def test_verify_utf(self): def test_verify_utf(self):
self.setup_mnemonic_nopin_nopassphrase() self.setup_mnemonic_nopin_nopassphrase()
words_nfkd = u'Pr\u030ci\u0301s\u030cerne\u030c z\u030clut\u030couc\u030cky\u0301 ku\u030an\u030c u\u0301pe\u030cl d\u030ca\u0301belske\u0301 o\u0301dy za\u0301ker\u030cny\u0301 uc\u030cen\u030c be\u030cz\u030ci\u0301 pode\u0301l zo\u0301ny u\u0301lu\u030a' words_nfkd = u"Pr\u030ci\u0301s\u030cerne\u030c z\u030clut\u030couc\u030cky\u0301 ku\u030an\u030c u\u0301pe\u030cl d\u030ca\u0301belske\u0301 o\u0301dy za\u0301ker\u030cny\u0301 uc\u030cen\u030c be\u030cz\u030ci\u0301 pode\u0301l zo\u0301ny u\u0301lu\u030a"
words_nfc = u'P\u0159\xed\u0161ern\u011b \u017elu\u0165ou\u010dk\xfd k\u016f\u0148 \xfap\u011bl \u010f\xe1belsk\xe9 \xf3dy z\xe1ke\u0159n\xfd u\u010de\u0148 b\u011b\u017e\xed pod\xe9l z\xf3ny \xfal\u016f' words_nfc = u"P\u0159\xed\u0161ern\u011b \u017elu\u0165ou\u010dk\xfd k\u016f\u0148 \xfap\u011bl \u010f\xe1belsk\xe9 \xf3dy z\xe1ke\u0159n\xfd u\u010de\u0148 b\u011b\u017e\xed pod\xe9l z\xf3ny \xfal\u016f"
res_nfkd = btc.verify_message( res_nfkd = btc.verify_message(
self.client, self.client,
'Bitcoin', "Bitcoin",
'bc1qyjjkmdpu7metqt5r36jf872a34syws33s82q2j', "bc1qyjjkmdpu7metqt5r36jf872a34syws33s82q2j",
unhexlify('28d0ec02ed8da8df23e7fe9e680e7867cc290312fe1c970749d8306ddad1a1eda41c6a771b13d495dd225b13b0a9d0f915a984ee3d0703f92287bf8009fbb9f7d6'), unhexlify(
words_nfkd "28d0ec02ed8da8df23e7fe9e680e7867cc290312fe1c970749d8306ddad1a1eda41c6a771b13d495dd225b13b0a9d0f915a984ee3d0703f92287bf8009fbb9f7d6"
),
words_nfkd,
) )
res_nfc = btc.verify_message( res_nfc = btc.verify_message(
self.client, self.client,
'Bitcoin', "Bitcoin",
'bc1qyjjkmdpu7metqt5r36jf872a34syws33s82q2j', "bc1qyjjkmdpu7metqt5r36jf872a34syws33s82q2j",
unhexlify('28d0ec02ed8da8df23e7fe9e680e7867cc290312fe1c970749d8306ddad1a1eda41c6a771b13d495dd225b13b0a9d0f915a984ee3d0703f92287bf8009fbb9f7d6'), unhexlify(
words_nfc "28d0ec02ed8da8df23e7fe9e680e7867cc290312fe1c970749d8306ddad1a1eda41c6a771b13d495dd225b13b0a9d0f915a984ee3d0703f92287bf8009fbb9f7d6"
),
words_nfc,
) )
assert res_nfkd is True assert res_nfkd is True

View File

@ -14,14 +14,12 @@
# You should have received a copy of the License along with this library. # You should have received a copy of the License along with this library.
# If not, see <https://www.gnu.org/licenses/lgpl-3.0.html>. # If not, see <https://www.gnu.org/licenses/lgpl-3.0.html>.
from .common import TrezorTest from trezorlib import device, messages as proto
from trezorlib import messages as proto from .common import TrezorTest
from trezorlib import device
class TestMsgWipedevice(TrezorTest): class TestMsgWipedevice(TrezorTest):
def test_wipe_device(self): def test_wipe_device(self):
self.setup_mnemonic_pin_passphrase() self.setup_mnemonic_pin_passphrase()
features = self.client.call_raw(proto.Initialize()) features = self.client.call_raw(proto.Initialize())

View File

@ -15,15 +15,18 @@
# If not, see <https://www.gnu.org/licenses/lgpl-3.0.html>. # If not, see <https://www.gnu.org/licenses/lgpl-3.0.html>.
from binascii import hexlify, unhexlify from binascii import hexlify, unhexlify
import pytest import pytest
from .common import TrezorTest from trezorlib import btc, messages as proto
from ..support import ckd_public as bip32
from trezorlib import messages as proto
from trezorlib.tools import CallException from trezorlib.tools import CallException
from trezorlib import btc
TXHASH_c6091a = unhexlify('c6091adf4c0c23982a35899a6e58ae11e703eacd7954f588ed4b9cdefc4dba52') from ..support import ckd_public as bip32
from .common import TrezorTest
TXHASH_c6091a = unhexlify(
"c6091adf4c0c23982a35899a6e58ae11e703eacd7954f588ed4b9cdefc4dba52"
)
# Multisig howto: # Multisig howto:
@ -33,7 +36,6 @@ TXHASH_c6091a = unhexlify('c6091adf4c0c23982a35899a6e58ae11e703eacd7954f588ed4b9
class TestMultisig(TrezorTest): class TestMultisig(TrezorTest):
def test_2_of_3(self): def test_2_of_3(self):
self.setup_mnemonic_nopin_nopassphrase() self.setup_mnemonic_nopin_nopassphrase()
@ -58,15 +60,17 @@ class TestMultisig(TrezorTest):
# tx: c6091adf4c0c23982a35899a6e58ae11e703eacd7954f588ed4b9cdefc4dba52 # tx: c6091adf4c0c23982a35899a6e58ae11e703eacd7954f588ed4b9cdefc4dba52
# input 1: 0.001 BTC # input 1: 0.001 BTC
node = bip32.deserialize('xpub661MyMwAqRbcF1zGijBb2K6x9YiJPh58xpcCeLvTxMX6spkY3PcpJ4ABcCyWfskq5DDxM3e6Ez5ePCqG5bnPUXR4wL8TZWyoDaUdiWW7bKy') node = bip32.deserialize(
"xpub661MyMwAqRbcF1zGijBb2K6x9YiJPh58xpcCeLvTxMX6spkY3PcpJ4ABcCyWfskq5DDxM3e6Ez5ePCqG5bnPUXR4wL8TZWyoDaUdiWW7bKy"
)
multisig = proto.MultisigRedeemScriptType( multisig = proto.MultisigRedeemScriptType(
pubkeys=[ pubkeys=[
proto.HDNodePathType(node=node, address_n=[1]), proto.HDNodePathType(node=node, address_n=[1]),
proto.HDNodePathType(node=node, address_n=[2]), proto.HDNodePathType(node=node, address_n=[2]),
proto.HDNodePathType(node=node, address_n=[3]) proto.HDNodePathType(node=node, address_n=[3]),
], ],
signatures=[b'', b'', b''], signatures=[b"", b"", b""],
m=2, m=2,
) )
@ -80,31 +84,69 @@ class TestMultisig(TrezorTest):
) )
out1 = proto.TxOutputType( out1 = proto.TxOutputType(
address='12iyMbUb4R2K3gre4dHSrbu5azG5KaqVss', address="12iyMbUb4R2K3gre4dHSrbu5azG5KaqVss",
amount=100000, amount=100000,
script_type=proto.OutputScriptType.PAYTOADDRESS script_type=proto.OutputScriptType.PAYTOADDRESS,
) )
with self.client: with self.client:
self.client.set_expected_responses([ self.client.set_expected_responses(
proto.TxRequest(request_type=proto.RequestType.TXINPUT, details=proto.TxRequestDetailsType(request_index=0)), [
proto.TxRequest(request_type=proto.RequestType.TXMETA, details=proto.TxRequestDetailsType(tx_hash=TXHASH_c6091a)), proto.TxRequest(
proto.TxRequest(request_type=proto.RequestType.TXINPUT, details=proto.TxRequestDetailsType(request_index=0, tx_hash=TXHASH_c6091a)), request_type=proto.RequestType.TXINPUT,
proto.TxRequest(request_type=proto.RequestType.TXOUTPUT, details=proto.TxRequestDetailsType(request_index=0, tx_hash=TXHASH_c6091a)), details=proto.TxRequestDetailsType(request_index=0),
proto.TxRequest(request_type=proto.RequestType.TXOUTPUT, details=proto.TxRequestDetailsType(request_index=1, tx_hash=TXHASH_c6091a)), ),
proto.TxRequest(request_type=proto.RequestType.TXOUTPUT, details=proto.TxRequestDetailsType(request_index=0)), proto.TxRequest(
proto.ButtonRequest(code=proto.ButtonRequestType.ConfirmOutput), request_type=proto.RequestType.TXMETA,
proto.ButtonRequest(code=proto.ButtonRequestType.SignTx), details=proto.TxRequestDetailsType(tx_hash=TXHASH_c6091a),
proto.TxRequest(request_type=proto.RequestType.TXINPUT, details=proto.TxRequestDetailsType(request_index=0)), ),
proto.TxRequest(request_type=proto.RequestType.TXOUTPUT, details=proto.TxRequestDetailsType(request_index=0)), proto.TxRequest(
proto.TxRequest(request_type=proto.RequestType.TXOUTPUT, details=proto.TxRequestDetailsType(request_index=0)), request_type=proto.RequestType.TXINPUT,
proto.TxRequest(request_type=proto.RequestType.TXFINISHED), details=proto.TxRequestDetailsType(
]) request_index=0, tx_hash=TXHASH_c6091a
),
),
proto.TxRequest(
request_type=proto.RequestType.TXOUTPUT,
details=proto.TxRequestDetailsType(
request_index=0, tx_hash=TXHASH_c6091a
),
),
proto.TxRequest(
request_type=proto.RequestType.TXOUTPUT,
details=proto.TxRequestDetailsType(
request_index=1, tx_hash=TXHASH_c6091a
),
),
proto.TxRequest(
request_type=proto.RequestType.TXOUTPUT,
details=proto.TxRequestDetailsType(request_index=0),
),
proto.ButtonRequest(code=proto.ButtonRequestType.ConfirmOutput),
proto.ButtonRequest(code=proto.ButtonRequestType.SignTx),
proto.TxRequest(
request_type=proto.RequestType.TXINPUT,
details=proto.TxRequestDetailsType(request_index=0),
),
proto.TxRequest(
request_type=proto.RequestType.TXOUTPUT,
details=proto.TxRequestDetailsType(request_index=0),
),
proto.TxRequest(
request_type=proto.RequestType.TXOUTPUT,
details=proto.TxRequestDetailsType(request_index=0),
),
proto.TxRequest(request_type=proto.RequestType.TXFINISHED),
]
)
# Now we have first signature # Now we have first signature
(signatures1, _) = btc.sign_tx(self.client, 'Bitcoin', [inp1, ], [out1, ]) (signatures1, _) = btc.sign_tx(self.client, "Bitcoin", [inp1], [out1])
assert hexlify(signatures1[0]) == b'3045022100985cc1ba316d140eb4b2d4028d8cd1c451f87bff8ff679858732e516ad04cd3402207af6edda99972af0baa7702a3b7448517c8242e7bca669f6861771cdd16ee058' assert (
hexlify(signatures1[0])
== b"3045022100985cc1ba316d140eb4b2d4028d8cd1c451f87bff8ff679858732e516ad04cd3402207af6edda99972af0baa7702a3b7448517c8242e7bca669f6861771cdd16ee058"
)
# --------------------------------------- # ---------------------------------------
# Let's do second signature using 3rd key # Let's do second signature using 3rd key
@ -113,9 +155,13 @@ class TestMultisig(TrezorTest):
pubkeys=[ pubkeys=[
proto.HDNodePathType(node=node, address_n=[1]), proto.HDNodePathType(node=node, address_n=[1]),
proto.HDNodePathType(node=node, address_n=[2]), proto.HDNodePathType(node=node, address_n=[2]),
proto.HDNodePathType(node=node, address_n=[3]) proto.HDNodePathType(node=node, address_n=[3]),
], ],
signatures=[signatures1[0], b'', b''], # Fill signature from previous signing process signatures=[
signatures1[0],
b"",
b"",
], # Fill signature from previous signing process
m=2, m=2,
) )
@ -129,26 +175,69 @@ class TestMultisig(TrezorTest):
) )
with self.client: with self.client:
self.client.set_expected_responses([ self.client.set_expected_responses(
proto.TxRequest(request_type=proto.RequestType.TXINPUT, details=proto.TxRequestDetailsType(request_index=0)), [
proto.TxRequest(request_type=proto.RequestType.TXMETA, details=proto.TxRequestDetailsType(tx_hash=TXHASH_c6091a)), proto.TxRequest(
proto.TxRequest(request_type=proto.RequestType.TXINPUT, details=proto.TxRequestDetailsType(request_index=0, tx_hash=TXHASH_c6091a)), request_type=proto.RequestType.TXINPUT,
proto.TxRequest(request_type=proto.RequestType.TXOUTPUT, details=proto.TxRequestDetailsType(request_index=0, tx_hash=TXHASH_c6091a)), details=proto.TxRequestDetailsType(request_index=0),
proto.TxRequest(request_type=proto.RequestType.TXOUTPUT, details=proto.TxRequestDetailsType(request_index=1, tx_hash=TXHASH_c6091a)), ),
proto.TxRequest(request_type=proto.RequestType.TXOUTPUT, details=proto.TxRequestDetailsType(request_index=0)), proto.TxRequest(
proto.ButtonRequest(code=proto.ButtonRequestType.ConfirmOutput), request_type=proto.RequestType.TXMETA,
proto.ButtonRequest(code=proto.ButtonRequestType.SignTx), details=proto.TxRequestDetailsType(tx_hash=TXHASH_c6091a),
proto.TxRequest(request_type=proto.RequestType.TXINPUT, details=proto.TxRequestDetailsType(request_index=0)), ),
proto.TxRequest(request_type=proto.RequestType.TXOUTPUT, details=proto.TxRequestDetailsType(request_index=0)), proto.TxRequest(
proto.TxRequest(request_type=proto.RequestType.TXOUTPUT, details=proto.TxRequestDetailsType(request_index=0)), request_type=proto.RequestType.TXINPUT,
proto.TxRequest(request_type=proto.RequestType.TXFINISHED), details=proto.TxRequestDetailsType(
]) request_index=0, tx_hash=TXHASH_c6091a
(signatures2, serialized_tx) = btc.sign_tx(self.client, 'Bitcoin', [inp3, ], [out1, ]) ),
),
proto.TxRequest(
request_type=proto.RequestType.TXOUTPUT,
details=proto.TxRequestDetailsType(
request_index=0, tx_hash=TXHASH_c6091a
),
),
proto.TxRequest(
request_type=proto.RequestType.TXOUTPUT,
details=proto.TxRequestDetailsType(
request_index=1, tx_hash=TXHASH_c6091a
),
),
proto.TxRequest(
request_type=proto.RequestType.TXOUTPUT,
details=proto.TxRequestDetailsType(request_index=0),
),
proto.ButtonRequest(code=proto.ButtonRequestType.ConfirmOutput),
proto.ButtonRequest(code=proto.ButtonRequestType.SignTx),
proto.TxRequest(
request_type=proto.RequestType.TXINPUT,
details=proto.TxRequestDetailsType(request_index=0),
),
proto.TxRequest(
request_type=proto.RequestType.TXOUTPUT,
details=proto.TxRequestDetailsType(request_index=0),
),
proto.TxRequest(
request_type=proto.RequestType.TXOUTPUT,
details=proto.TxRequestDetailsType(request_index=0),
),
proto.TxRequest(request_type=proto.RequestType.TXFINISHED),
]
)
(signatures2, serialized_tx) = btc.sign_tx(
self.client, "Bitcoin", [inp3], [out1]
)
assert hexlify(signatures2[0]) == b'3045022100f5428fe0531b3095675b40d87cab607ee036fac823b22e8dcec35b65aff6e52b022032129b4577ff923d321a1c70db5a6cec5bcc142cb2c51901af8b989cced23e0d' assert (
hexlify(signatures2[0])
== b"3045022100f5428fe0531b3095675b40d87cab607ee036fac823b22e8dcec35b65aff6e52b022032129b4577ff923d321a1c70db5a6cec5bcc142cb2c51901af8b989cced23e0d"
)
# Accepted by network: tx 8382a2b2e3ec8788800c1d46d285dfa9dd4051edddd75982fad166b9273e5ac6 # Accepted by network: tx 8382a2b2e3ec8788800c1d46d285dfa9dd4051edddd75982fad166b9273e5ac6
assert hexlify(serialized_tx) == b'010000000152ba4dfcde9c4bed88f55479cdea03e711ae586e9a89352a98230c4cdf1a09c601000000fdfe0000483045022100985cc1ba316d140eb4b2d4028d8cd1c451f87bff8ff679858732e516ad04cd3402207af6edda99972af0baa7702a3b7448517c8242e7bca669f6861771cdd16ee05801483045022100f5428fe0531b3095675b40d87cab607ee036fac823b22e8dcec35b65aff6e52b022032129b4577ff923d321a1c70db5a6cec5bcc142cb2c51901af8b989cced23e0d014c6952210338d78612e990f2eea0c426b5e48a8db70b9d7ed66282b3b26511e0b1c75515a621038caebd6f753bbbd2bb1f3346a43cd32140648583673a31d62f2dfb56ad0ab9e32103477b9f0f34ae85434ce795f0c5e1e90c9420e5b5fad084d7cce9a487b94a790253aeffffffff01a0860100000000001976a91412e8391ad256dcdc023365978418d658dfecba1c88ac00000000' assert (
hexlify(serialized_tx)
== b"010000000152ba4dfcde9c4bed88f55479cdea03e711ae586e9a89352a98230c4cdf1a09c601000000fdfe0000483045022100985cc1ba316d140eb4b2d4028d8cd1c451f87bff8ff679858732e516ad04cd3402207af6edda99972af0baa7702a3b7448517c8242e7bca669f6861771cdd16ee05801483045022100f5428fe0531b3095675b40d87cab607ee036fac823b22e8dcec35b65aff6e52b022032129b4577ff923d321a1c70db5a6cec5bcc142cb2c51901af8b989cced23e0d014c6952210338d78612e990f2eea0c426b5e48a8db70b9d7ed66282b3b26511e0b1c75515a621038caebd6f753bbbd2bb1f3346a43cd32140648583673a31d62f2dfb56ad0ab9e32103477b9f0f34ae85434ce795f0c5e1e90c9420e5b5fad084d7cce9a487b94a790253aeffffffff01a0860100000000001976a91412e8391ad256dcdc023365978418d658dfecba1c88ac00000000"
)
def test_15_of_15(self): def test_15_of_15(self):
self.setup_mnemonic_nopin_nopassphrase() self.setup_mnemonic_nopin_nopassphrase()
@ -162,7 +251,9 @@ class TestMultisig(TrezorTest):
# xpub: # xpub:
# print(bip32.serialize(self.client.get_public_node([]).node)) # print(bip32.serialize(self.client.get_public_node([]).node))
# xpub661MyMwAqRbcF1zGijBb2K6x9YiJPh58xpcCeLvTxMX6spkY3PcpJ4ABcCyWfskq5DDxM3e6Ez5ePCqG5bnPUXR4wL8TZWyoDaUdiWW7bKy # xpub661MyMwAqRbcF1zGijBb2K6x9YiJPh58xpcCeLvTxMX6spkY3PcpJ4ABcCyWfskq5DDxM3e6Ez5ePCqG5bnPUXR4wL8TZWyoDaUdiWW7bKy
node = bip32.deserialize('xpub661MyMwAqRbcF1zGijBb2K6x9YiJPh58xpcCeLvTxMX6spkY3PcpJ4ABcCyWfskq5DDxM3e6Ez5ePCqG5bnPUXR4wL8TZWyoDaUdiWW7bKy') node = bip32.deserialize(
"xpub661MyMwAqRbcF1zGijBb2K6x9YiJPh58xpcCeLvTxMX6spkY3PcpJ4ABcCyWfskq5DDxM3e6Ez5ePCqG5bnPUXR4wL8TZWyoDaUdiWW7bKy"
)
pubs = [] pubs = []
for x in range(15): for x in range(15):
@ -174,35 +265,40 @@ class TestMultisig(TrezorTest):
# multisig address # multisig address
# 3QaKF8zobqcqY8aS6nxCD5ZYdiRfL3RCmU # 3QaKF8zobqcqY8aS6nxCD5ZYdiRfL3RCmU
signatures = [b''] * 15 signatures = [b""] * 15
out1 = proto.TxOutputType( out1 = proto.TxOutputType(
address='17kTB7qSk3MupQxWdiv5ZU3zcrZc2Azes1', address="17kTB7qSk3MupQxWdiv5ZU3zcrZc2Azes1",
amount=10000, amount=10000,
script_type=proto.OutputScriptType.PAYTOADDRESS script_type=proto.OutputScriptType.PAYTOADDRESS,
) )
for x in range(15): for x in range(15):
multisig = proto.MultisigRedeemScriptType( multisig = proto.MultisigRedeemScriptType(
pubkeys=pubs, pubkeys=pubs, signatures=signatures, m=15
signatures=signatures,
m=15,
) )
inp1 = proto.TxInputType( inp1 = proto.TxInputType(
address_n=[x], address_n=[x],
prev_hash=unhexlify('6189e3febb5a21cee8b725aa1ef04ffce7e609448446d3a8d6f483c634ef5315'), prev_hash=unhexlify(
"6189e3febb5a21cee8b725aa1ef04ffce7e609448446d3a8d6f483c634ef5315"
),
prev_index=1, prev_index=1,
script_type=proto.InputScriptType.SPENDMULTISIG, script_type=proto.InputScriptType.SPENDMULTISIG,
multisig=multisig, multisig=multisig,
) )
with self.client: with self.client:
(sig, serialized_tx) = btc.sign_tx(self.client, 'Bitcoin', [inp1, ], [out1, ]) (sig, serialized_tx) = btc.sign_tx(
self.client, "Bitcoin", [inp1], [out1]
)
signatures[x] = sig[0] signatures[x] = sig[0]
# Accepted as tx id dd320786d1f58c095be0509dc56b277b6de8f2fb5517f519c6e6708414e3300b # Accepted as tx id dd320786d1f58c095be0509dc56b277b6de8f2fb5517f519c6e6708414e3300b
assert hexlify(serialized_tx) == b'01000000011553ef34c683f4d6a8d346844409e6e7fc4ff01eaa25b7e8ce215abbfee3896101000000fd43060048304502210098e23085ad7282de988bf98afa1e9add9c9830009132f8902a9fa4624d5dc98b0220733216e70ab67791aa64be5c83d2050cb4ed9ff7eda2a1acc35da024d2ab2a670147304402201f8c11fb6e90fd616e484986e9451929797eba039882a9abcc203210948060b9022044da031530de7d9747d3c5a8e7cec04b04b7af495c9120b854ce7362af7fa05a01483045022100ea67c70186acef019bdf1551881bf38e6f88186501b64d3a756a2ce18e4ba18002201c35110325653e21e448b60053a4b5dda46b61096faf701a1faca61fcde91f00014730440220315598992f156d2f9d7b4275395fa067aa61ea95829fa17730885c86df4de70d02203eda9ade1656e2198c668603b17e197acb0969ed183ab0841303ea261205618901473044022060fdd6621edde9b8cf6776bc4eef26ace9b57514d725b7214ba11d333520a30e022044c30744f94484aec0f896233c5613a3256878ec0379f566226906b6d1b6061401483045022100b1d907e3574f60f7834c7e9f2e367998ce0461dad7d742d84ef8917d713f41f902203b3ac54f7bb2f7fb8685f582d2a94f7213a37cb508acffe29090cc06ae01588b01483045022100e3bf90ff3ad6395e42f46002f253f94ca0e8ffaa0620f2ceb4fa21493abdca4d02201d4c28b10b740bb2dc4b3695b4205c18f8c0dad2bb69540eb8a36576463cd5280147304402202cfaf9fab7dc1c9f0c3c23bd46bd6d5cea0664d914139fc9add80766ce998808022012db2802c07853e4cbe147afdf0b47e60bdcbcd31f9df19e04c177ed9aa66c6d0147304402207cbc2d83f351eee5ee91df26bb0c7e1cb07fe328cbbcdb0bb9656d37922c497302201b3435d4c71ffd1b34d45892f2a487bd79c8c7f57cc04373287642bb9610cb840147304402202dc3eab30ccb06553703e794212f43ee9a659f5e787a8374e9ea0bf6de0def7402201a70e970c21a807783313ed102bf4f0a3406ac7c84f94bc8194c5e209464d7230147304402206b04530c190c46a879d7771a6ad53acd33547e0d7fd320d5ad0b5b1fdeb5d4c202207b812be81c3419daadc942cca0c55aa32c7759fa7566c6dc35f030ca87a1c5be01483045022100ce523dddd6eef73d5ae7c44c870466e1ac5a7a77d43475e8def024af68977a1e022028be0276435bfa2ea887d6cf89fa829f96c1c7a55edc57bb3fd667d523fd3bf601473044022019410b20ebcd8eb3ee7ec1eff6bf0f9cbfaea82116811c61f3cf24af7e4434b1022009e5823f3349f695be09ae40754185300d8442a22715ddb5ffa17c4213140e7201483045022100964ef26a9074c3cdafffcfbe4bd445933f8c842ba11fd887922adcf7fabe0c82022023055d94c75ab223c767fbaa825c917e9beecbc7d5758cccf20d886c63d4b72a0147304402207aa3a98197697d258a8baae681f0b4c0ee682982f4205534e6c95a37dabaddd60220517a7ed5c03da2f242e17ccfdae0d81d6f454d7f9ea931fc62df6c0eab922186014d01025f21023230848585885f63803a0a8aecdd6538792d5c539215c91698e315bf0253b43d210338d78612e990f2eea0c426b5e48a8db70b9d7ed66282b3b26511e0b1c75515a621038caebd6f753bbbd2bb1f3346a43cd32140648583673a31d62f2dfb56ad0ab9e32103477b9f0f34ae85434ce795f0c5e1e90c9420e5b5fad084d7cce9a487b94a79022103fe91eca10602d7dad4c9dab2b2a0858f71e25a219a6940749ce7a48118480dae210234716c01c2dd03fa7ee302705e2b8fbd1311895d94b1dca15e62eedea9b0968f210341fb2ead334952cf60f4481ba435c4693d0be649be01d2cfe9b02018e483e7bd2102dad8b2bce360a705c16e74a50a36459b4f8f4b78f9cd67def29d54ef6f7c7cf9210222dbe3f5f197a34a1d50e2cbe2a1085cac2d605c9e176f9a240e0fd0c669330d2103fb41afab56c9cdb013fda63d777d4938ddc3cb2ad939712da688e3ed333f95982102435f177646bdc717cb3211bf46656ca7e8d642726144778c9ce816b8b8c36ccf2102158d8e20095364031d923c7e9f7f08a14b1be1ddee21fe1a5431168e31345e5521026259794892428ca0818c8fb61d2d459ddfe20e57f50803c7295e6f4e2f5586652102815f910a8689151db627e6e262e0a2075ad5ec2993a6bc1b876a9d420923d681210318f54647f645ff01bd49fedc0219343a6a22d3ea3180a3c3d3097e4b888a8db45faeffffffff0110270000000000001976a9144a087d89f8ad16ca029c675b037c02fd1c5f9aec88ac00000000' assert (
hexlify(serialized_tx)
== b"01000000011553ef34c683f4d6a8d346844409e6e7fc4ff01eaa25b7e8ce215abbfee3896101000000fd43060048304502210098e23085ad7282de988bf98afa1e9add9c9830009132f8902a9fa4624d5dc98b0220733216e70ab67791aa64be5c83d2050cb4ed9ff7eda2a1acc35da024d2ab2a670147304402201f8c11fb6e90fd616e484986e9451929797eba039882a9abcc203210948060b9022044da031530de7d9747d3c5a8e7cec04b04b7af495c9120b854ce7362af7fa05a01483045022100ea67c70186acef019bdf1551881bf38e6f88186501b64d3a756a2ce18e4ba18002201c35110325653e21e448b60053a4b5dda46b61096faf701a1faca61fcde91f00014730440220315598992f156d2f9d7b4275395fa067aa61ea95829fa17730885c86df4de70d02203eda9ade1656e2198c668603b17e197acb0969ed183ab0841303ea261205618901473044022060fdd6621edde9b8cf6776bc4eef26ace9b57514d725b7214ba11d333520a30e022044c30744f94484aec0f896233c5613a3256878ec0379f566226906b6d1b6061401483045022100b1d907e3574f60f7834c7e9f2e367998ce0461dad7d742d84ef8917d713f41f902203b3ac54f7bb2f7fb8685f582d2a94f7213a37cb508acffe29090cc06ae01588b01483045022100e3bf90ff3ad6395e42f46002f253f94ca0e8ffaa0620f2ceb4fa21493abdca4d02201d4c28b10b740bb2dc4b3695b4205c18f8c0dad2bb69540eb8a36576463cd5280147304402202cfaf9fab7dc1c9f0c3c23bd46bd6d5cea0664d914139fc9add80766ce998808022012db2802c07853e4cbe147afdf0b47e60bdcbcd31f9df19e04c177ed9aa66c6d0147304402207cbc2d83f351eee5ee91df26bb0c7e1cb07fe328cbbcdb0bb9656d37922c497302201b3435d4c71ffd1b34d45892f2a487bd79c8c7f57cc04373287642bb9610cb840147304402202dc3eab30ccb06553703e794212f43ee9a659f5e787a8374e9ea0bf6de0def7402201a70e970c21a807783313ed102bf4f0a3406ac7c84f94bc8194c5e209464d7230147304402206b04530c190c46a879d7771a6ad53acd33547e0d7fd320d5ad0b5b1fdeb5d4c202207b812be81c3419daadc942cca0c55aa32c7759fa7566c6dc35f030ca87a1c5be01483045022100ce523dddd6eef73d5ae7c44c870466e1ac5a7a77d43475e8def024af68977a1e022028be0276435bfa2ea887d6cf89fa829f96c1c7a55edc57bb3fd667d523fd3bf601473044022019410b20ebcd8eb3ee7ec1eff6bf0f9cbfaea82116811c61f3cf24af7e4434b1022009e5823f3349f695be09ae40754185300d8442a22715ddb5ffa17c4213140e7201483045022100964ef26a9074c3cdafffcfbe4bd445933f8c842ba11fd887922adcf7fabe0c82022023055d94c75ab223c767fbaa825c917e9beecbc7d5758cccf20d886c63d4b72a0147304402207aa3a98197697d258a8baae681f0b4c0ee682982f4205534e6c95a37dabaddd60220517a7ed5c03da2f242e17ccfdae0d81d6f454d7f9ea931fc62df6c0eab922186014d01025f21023230848585885f63803a0a8aecdd6538792d5c539215c91698e315bf0253b43d210338d78612e990f2eea0c426b5e48a8db70b9d7ed66282b3b26511e0b1c75515a621038caebd6f753bbbd2bb1f3346a43cd32140648583673a31d62f2dfb56ad0ab9e32103477b9f0f34ae85434ce795f0c5e1e90c9420e5b5fad084d7cce9a487b94a79022103fe91eca10602d7dad4c9dab2b2a0858f71e25a219a6940749ce7a48118480dae210234716c01c2dd03fa7ee302705e2b8fbd1311895d94b1dca15e62eedea9b0968f210341fb2ead334952cf60f4481ba435c4693d0be649be01d2cfe9b02018e483e7bd2102dad8b2bce360a705c16e74a50a36459b4f8f4b78f9cd67def29d54ef6f7c7cf9210222dbe3f5f197a34a1d50e2cbe2a1085cac2d605c9e176f9a240e0fd0c669330d2103fb41afab56c9cdb013fda63d777d4938ddc3cb2ad939712da688e3ed333f95982102435f177646bdc717cb3211bf46656ca7e8d642726144778c9ce816b8b8c36ccf2102158d8e20095364031d923c7e9f7f08a14b1be1ddee21fe1a5431168e31345e5521026259794892428ca0818c8fb61d2d459ddfe20e57f50803c7295e6f4e2f5586652102815f910a8689151db627e6e262e0a2075ad5ec2993a6bc1b876a9d420923d681210318f54647f645ff01bd49fedc0219343a6a22d3ea3180a3c3d3097e4b888a8db45faeffffffff0110270000000000001976a9144a087d89f8ad16ca029c675b037c02fd1c5f9aec88ac00000000"
)
def test_missing_pubkey(self): def test_missing_pubkey(self):
self.setup_mnemonic_nopin_nopassphrase() self.setup_mnemonic_nopin_nopassphrase()
@ -221,15 +317,17 @@ class TestMultisig(TrezorTest):
# xpub: # xpub:
# print(bip32.serialize(self.client.get_public_node([]).node)) # print(bip32.serialize(self.client.get_public_node([]).node))
# xpub661MyMwAqRbcF1zGijBb2K6x9YiJPh58xpcCeLvTxMX6spkY3PcpJ4ABcCyWfskq5DDxM3e6Ez5ePCqG5bnPUXR4wL8TZWyoDaUdiWW7bKy # xpub661MyMwAqRbcF1zGijBb2K6x9YiJPh58xpcCeLvTxMX6spkY3PcpJ4ABcCyWfskq5DDxM3e6Ez5ePCqG5bnPUXR4wL8TZWyoDaUdiWW7bKy
node = bip32.deserialize('xpub661MyMwAqRbcF1zGijBb2K6x9YiJPh58xpcCeLvTxMX6spkY3PcpJ4ABcCyWfskq5DDxM3e6Ez5ePCqG5bnPUXR4wL8TZWyoDaUdiWW7bKy') node = bip32.deserialize(
"xpub661MyMwAqRbcF1zGijBb2K6x9YiJPh58xpcCeLvTxMX6spkY3PcpJ4ABcCyWfskq5DDxM3e6Ez5ePCqG5bnPUXR4wL8TZWyoDaUdiWW7bKy"
)
multisig = proto.MultisigRedeemScriptType( multisig = proto.MultisigRedeemScriptType(
pubkeys=[ pubkeys=[
proto.HDNodePathType(node=node, address_n=[1]), proto.HDNodePathType(node=node, address_n=[1]),
proto.HDNodePathType(node=node, address_n=[2]), proto.HDNodePathType(node=node, address_n=[2]),
proto.HDNodePathType(node=node, address_n=[3]) proto.HDNodePathType(node=node, address_n=[3]),
], ],
signatures=[b'', b'', b''], signatures=[b"", b"", b""],
m=2, m=2,
) )
@ -243,13 +341,13 @@ class TestMultisig(TrezorTest):
) )
out1 = proto.TxOutputType( out1 = proto.TxOutputType(
address='12iyMbUb4R2K3gre4dHSrbu5azG5KaqVss', address="12iyMbUb4R2K3gre4dHSrbu5azG5KaqVss",
amount=100000, amount=100000,
script_type=proto.OutputScriptType.PAYTOADDRESS script_type=proto.OutputScriptType.PAYTOADDRESS,
) )
with pytest.raises(CallException) as exc: with pytest.raises(CallException) as exc:
btc.sign_tx(self.client, 'Bitcoin', [inp1, ], [out1, ]) btc.sign_tx(self.client, "Bitcoin", [inp1], [out1])
assert exc.value.args[0] == proto.FailureType.DataError assert exc.value.args[0] == proto.FailureType.DataError
assert exc.value.args[1].endswith('Pubkey not found in multisig script') assert exc.value.args[1].endswith("Pubkey not found in multisig script")

View File

@ -16,35 +16,42 @@
from binascii import hexlify, unhexlify from binascii import hexlify, unhexlify
from .common import TrezorTest from trezorlib import btc, messages as proto
from ..support import ckd_public as bip32 from trezorlib.tools import H_, parse_path
from trezorlib import messages as proto
from trezorlib.tools import parse_path, H_
from trezorlib.tx_api import TxApiInsight from trezorlib.tx_api import TxApiInsight
from trezorlib import btc
from ..support import ckd_public as bip32
from .common import TrezorTest
TxApiTestnet = TxApiInsight("insight_testnet") TxApiTestnet = TxApiInsight("insight_testnet")
class TestMultisigChange(TrezorTest): class TestMultisigChange(TrezorTest):
def setup_method(self, method): def setup_method(self, method):
super(TestMultisigChange, self).setup_method(method) super(TestMultisigChange, self).setup_method(method)
self.client.set_tx_api(TxApiTestnet) self.client.set_tx_api(TxApiTestnet)
node_ext1 = bip32.deserialize('tpubDADHV9u9Y6gkggintTdMjJE3be58zKNLhpxBQyuEM6Pwx3sN9JVLmMCMN4DNVwL9AKec27z5TaWcWuHzMXiGAtcra5DjwWbvppGX4gaEGVN') node_ext1 = bip32.deserialize(
"tpubDADHV9u9Y6gkggintTdMjJE3be58zKNLhpxBQyuEM6Pwx3sN9JVLmMCMN4DNVwL9AKec27z5TaWcWuHzMXiGAtcra5DjwWbvppGX4gaEGVN"
)
# m/1 => 02c0d0c5fee952620757c6128dbf327c996cd72ed3358d15d6518a1186099bc15e # m/1 => 02c0d0c5fee952620757c6128dbf327c996cd72ed3358d15d6518a1186099bc15e
# m/2 => 0375b9dfaad928ce1a7eed88df7c084e67d99e9ab74332419458a9a45779706801 # m/2 => 0375b9dfaad928ce1a7eed88df7c084e67d99e9ab74332419458a9a45779706801
node_ext2 = bip32.deserialize('tpubDADHV9u9Y6gkhWXBmDJ6TUhZajLWjvKukRe2w9FfhdbQpUux8Z8jnPHNAZqFRgHPg9sR7YR93xThM32M7NfRu8S5WyDtext7S62sqxeJNkd') node_ext2 = bip32.deserialize(
"tpubDADHV9u9Y6gkhWXBmDJ6TUhZajLWjvKukRe2w9FfhdbQpUux8Z8jnPHNAZqFRgHPg9sR7YR93xThM32M7NfRu8S5WyDtext7S62sqxeJNkd"
)
# m/1 => 0388460dc439f4c8f5bcfc268c36e11b4375cad5c3535c336cfdf8c32c3afad5c1 # m/1 => 0388460dc439f4c8f5bcfc268c36e11b4375cad5c3535c336cfdf8c32c3afad5c1
# m/2 => 03a04f945d5a3685729dde697d574076de4bdf38e904f813b22a851548e1110fc0 # m/2 => 03a04f945d5a3685729dde697d574076de4bdf38e904f813b22a851548e1110fc0
node_ext3 = bip32.deserialize('tpubDADHV9u9Y6gkmM5ohWRGTswrc6fr7soH7e2D2ic5a86PDUaHc5Ln9EbER69cEr5bDZPa7EXguJ1MhWVzPZpZWVdG5fvoF3hfirXvRbpCCBg') node_ext3 = bip32.deserialize(
"tpubDADHV9u9Y6gkmM5ohWRGTswrc6fr7soH7e2D2ic5a86PDUaHc5Ln9EbER69cEr5bDZPa7EXguJ1MhWVzPZpZWVdG5fvoF3hfirXvRbpCCBg"
)
# m/1 => 02e0c21e2a7cf00b94c5421725acff97f9826598b91f2340c5ddda730caca7d648 # m/1 => 02e0c21e2a7cf00b94c5421725acff97f9826598b91f2340c5ddda730caca7d648
# m/2 => 03928301ffb8c0d7a364b794914c716ba3107cc78a6fe581028b0d8638b22e8573 # m/2 => 03928301ffb8c0d7a364b794914c716ba3107cc78a6fe581028b0d8638b22e8573
node_int = bip32.deserialize('tpubDADHV9u9Y6gke2Vw3rWE8KRXmeK8PTtsF5B3Cqjo6h3SoiyRtzxjnDVG1knxrqB8BpP1dMAd6MR3Ps5UXibiFDtQuWVPXLkJ3HvttZYbH12') node_int = bip32.deserialize(
"tpubDADHV9u9Y6gke2Vw3rWE8KRXmeK8PTtsF5B3Cqjo6h3SoiyRtzxjnDVG1knxrqB8BpP1dMAd6MR3Ps5UXibiFDtQuWVPXLkJ3HvttZYbH12"
)
# m/1 => 03f91460d79e4e463d7d90cb75254bcd62b515a99a950574c721efdc5f711dff35 # m/1 => 03f91460d79e4e463d7d90cb75254bcd62b515a99a950574c721efdc5f711dff35
# m/2 => 038caebd6f753bbbd2bb1f3346a43cd32140648583673a31d62f2dfb56ad0ab9e3 # m/2 => 038caebd6f753bbbd2bb1f3346a43cd32140648583673a31d62f2dfb56ad0ab9e3
@ -70,9 +77,9 @@ class TestMultisigChange(TrezorTest):
pubkeys=[ pubkeys=[
proto.HDNodePathType(node=node_ext2, address_n=[0, 0]), proto.HDNodePathType(node=node_ext2, address_n=[0, 0]),
proto.HDNodePathType(node=node_ext1, address_n=[0, 0]), proto.HDNodePathType(node=node_ext1, address_n=[0, 0]),
proto.HDNodePathType(node=node_int, address_n=[0, 0]) proto.HDNodePathType(node=node_int, address_n=[0, 0]),
], ],
signatures=[b'', b'', b''], signatures=[b"", b"", b""],
m=2, m=2,
) )
@ -82,7 +89,7 @@ class TestMultisigChange(TrezorTest):
proto.HDNodePathType(node=node_ext2, address_n=[0, 1]), proto.HDNodePathType(node=node_ext2, address_n=[0, 1]),
proto.HDNodePathType(node=node_int, address_n=[0, 1]), proto.HDNodePathType(node=node_int, address_n=[0, 1]),
], ],
signatures=[b'', b'', b''], signatures=[b"", b"", b""],
m=2, m=2,
) )
@ -90,16 +97,18 @@ class TestMultisigChange(TrezorTest):
pubkeys=[ pubkeys=[
proto.HDNodePathType(node=node_ext1, address_n=[0, 1]), proto.HDNodePathType(node=node_ext1, address_n=[0, 1]),
proto.HDNodePathType(node=node_ext3, address_n=[0, 1]), proto.HDNodePathType(node=node_ext3, address_n=[0, 1]),
proto.HDNodePathType(node=node_int, address_n=[0, 1]) proto.HDNodePathType(node=node_int, address_n=[0, 1]),
], ],
signatures=[b'', b'', b''], signatures=[b"", b"", b""],
m=2, m=2,
) )
# 2N9W4z9AhAPaHghtqVQPbaTAGHdbrhKeBQw # 2N9W4z9AhAPaHghtqVQPbaTAGHdbrhKeBQw
inp1 = proto.TxInputType( inp1 = proto.TxInputType(
address_n=[H_(45), 0, 0, 0], address_n=[H_(45), 0, 0, 0],
prev_hash=unhexlify('16c6c8471b8db7a628f2b2bb86bfeefae1766463ce8692438c7fd3fce3f43ce5'), prev_hash=unhexlify(
"16c6c8471b8db7a628f2b2bb86bfeefae1766463ce8692438c7fd3fce3f43ce5"
),
prev_index=1, prev_index=1,
script_type=proto.InputScriptType.SPENDMULTISIG, script_type=proto.InputScriptType.SPENDMULTISIG,
multisig=multisig_in1, multisig=multisig_in1,
@ -108,7 +117,9 @@ class TestMultisigChange(TrezorTest):
# 2NDBG6QXQLtnQ3jRGkrqo53BiCeXfQXLdj4 # 2NDBG6QXQLtnQ3jRGkrqo53BiCeXfQXLdj4
inp2 = proto.TxInputType( inp2 = proto.TxInputType(
address_n=[H_(45), 0, 0, 1], address_n=[H_(45), 0, 0, 1],
prev_hash=unhexlify('d80c34ee14143a8bf61125102b7ef594118a3796cad670fa8ee15080ae155318'), prev_hash=unhexlify(
"d80c34ee14143a8bf61125102b7ef594118a3796cad670fa8ee15080ae155318"
),
prev_index=0, prev_index=0,
script_type=proto.InputScriptType.SPENDMULTISIG, script_type=proto.InputScriptType.SPENDMULTISIG,
multisig=multisig_in2, multisig=multisig_in2,
@ -117,7 +128,9 @@ class TestMultisigChange(TrezorTest):
# 2MvwPWfp2XPU3S1cMwgEMKBPUw38VP5SBE4 # 2MvwPWfp2XPU3S1cMwgEMKBPUw38VP5SBE4
inp3 = proto.TxInputType( inp3 = proto.TxInputType(
address_n=[H_(45), 0, 0, 1], address_n=[H_(45), 0, 0, 1],
prev_hash=unhexlify('b0946dc27ba308a749b11afecc2018980af18f79e89ad6b080b58220d856f739'), prev_hash=unhexlify(
"b0946dc27ba308a749b11afecc2018980af18f79e89ad6b080b58220d856f739"
),
prev_index=0, prev_index=0,
script_type=proto.InputScriptType.SPENDMULTISIG, script_type=proto.InputScriptType.SPENDMULTISIG,
multisig=multisig_in3, multisig=multisig_in3,
@ -125,41 +138,115 @@ class TestMultisigChange(TrezorTest):
def _responses(self, inp1, inp2, change=0): def _responses(self, inp1, inp2, change=0):
resp = [ resp = [
proto.TxRequest(request_type=proto.RequestType.TXINPUT, details=proto.TxRequestDetailsType(request_index=0)), proto.TxRequest(
proto.TxRequest(request_type=proto.RequestType.TXMETA, details=proto.TxRequestDetailsType(tx_hash=inp1.prev_hash)), request_type=proto.RequestType.TXINPUT,
proto.TxRequest(request_type=proto.RequestType.TXINPUT, details=proto.TxRequestDetailsType(request_index=0, tx_hash=inp1.prev_hash)), details=proto.TxRequestDetailsType(request_index=0),
proto.TxRequest(request_type=proto.RequestType.TXOUTPUT, details=proto.TxRequestDetailsType(request_index=0, tx_hash=inp1.prev_hash)), ),
proto.TxRequest(request_type=proto.RequestType.TXOUTPUT, details=proto.TxRequestDetailsType(request_index=1, tx_hash=inp1.prev_hash)), proto.TxRequest(
proto.TxRequest(request_type=proto.RequestType.TXINPUT, details=proto.TxRequestDetailsType(request_index=1)), request_type=proto.RequestType.TXMETA,
proto.TxRequest(request_type=proto.RequestType.TXMETA, details=proto.TxRequestDetailsType(tx_hash=inp2.prev_hash)), details=proto.TxRequestDetailsType(tx_hash=inp1.prev_hash),
proto.TxRequest(request_type=proto.RequestType.TXINPUT, details=proto.TxRequestDetailsType(request_index=0, tx_hash=inp2.prev_hash)), ),
proto.TxRequest(request_type=proto.RequestType.TXOUTPUT, details=proto.TxRequestDetailsType(request_index=0, tx_hash=inp2.prev_hash)), proto.TxRequest(
proto.TxRequest(request_type=proto.RequestType.TXOUTPUT, details=proto.TxRequestDetailsType(request_index=1, tx_hash=inp2.prev_hash)), request_type=proto.RequestType.TXINPUT,
proto.TxRequest(request_type=proto.RequestType.TXOUTPUT, details=proto.TxRequestDetailsType(request_index=0)), details=proto.TxRequestDetailsType(
request_index=0, tx_hash=inp1.prev_hash
),
),
proto.TxRequest(
request_type=proto.RequestType.TXOUTPUT,
details=proto.TxRequestDetailsType(
request_index=0, tx_hash=inp1.prev_hash
),
),
proto.TxRequest(
request_type=proto.RequestType.TXOUTPUT,
details=proto.TxRequestDetailsType(
request_index=1, tx_hash=inp1.prev_hash
),
),
proto.TxRequest(
request_type=proto.RequestType.TXINPUT,
details=proto.TxRequestDetailsType(request_index=1),
),
proto.TxRequest(
request_type=proto.RequestType.TXMETA,
details=proto.TxRequestDetailsType(tx_hash=inp2.prev_hash),
),
proto.TxRequest(
request_type=proto.RequestType.TXINPUT,
details=proto.TxRequestDetailsType(
request_index=0, tx_hash=inp2.prev_hash
),
),
proto.TxRequest(
request_type=proto.RequestType.TXOUTPUT,
details=proto.TxRequestDetailsType(
request_index=0, tx_hash=inp2.prev_hash
),
),
proto.TxRequest(
request_type=proto.RequestType.TXOUTPUT,
details=proto.TxRequestDetailsType(
request_index=1, tx_hash=inp2.prev_hash
),
),
proto.TxRequest(
request_type=proto.RequestType.TXOUTPUT,
details=proto.TxRequestDetailsType(request_index=0),
),
] ]
if change != 1: if change != 1:
resp.append( resp.append(proto.ButtonRequest(code=proto.ButtonRequestType.ConfirmOutput))
proto.ButtonRequest(code=proto.ButtonRequestType.ConfirmOutput)
)
resp.append( resp.append(
proto.TxRequest(request_type=proto.RequestType.TXOUTPUT, details=proto.TxRequestDetailsType(request_index=1)) proto.TxRequest(
request_type=proto.RequestType.TXOUTPUT,
details=proto.TxRequestDetailsType(request_index=1),
)
) )
if change != 2: if change != 2:
resp.append( resp.append(proto.ButtonRequest(code=proto.ButtonRequestType.ConfirmOutput))
proto.ButtonRequest(code=proto.ButtonRequestType.ConfirmOutput)
)
resp += [ resp += [
proto.ButtonRequest(code=proto.ButtonRequestType.SignTx), proto.ButtonRequest(code=proto.ButtonRequestType.SignTx),
proto.TxRequest(request_type=proto.RequestType.TXINPUT, details=proto.TxRequestDetailsType(request_index=0)), proto.TxRequest(
proto.TxRequest(request_type=proto.RequestType.TXINPUT, details=proto.TxRequestDetailsType(request_index=1)), request_type=proto.RequestType.TXINPUT,
proto.TxRequest(request_type=proto.RequestType.TXOUTPUT, details=proto.TxRequestDetailsType(request_index=0)), details=proto.TxRequestDetailsType(request_index=0),
proto.TxRequest(request_type=proto.RequestType.TXOUTPUT, details=proto.TxRequestDetailsType(request_index=1)), ),
proto.TxRequest(request_type=proto.RequestType.TXINPUT, details=proto.TxRequestDetailsType(request_index=0)), proto.TxRequest(
proto.TxRequest(request_type=proto.RequestType.TXINPUT, details=proto.TxRequestDetailsType(request_index=1)), request_type=proto.RequestType.TXINPUT,
proto.TxRequest(request_type=proto.RequestType.TXOUTPUT, details=proto.TxRequestDetailsType(request_index=0)), details=proto.TxRequestDetailsType(request_index=1),
proto.TxRequest(request_type=proto.RequestType.TXOUTPUT, details=proto.TxRequestDetailsType(request_index=1)), ),
proto.TxRequest(request_type=proto.RequestType.TXOUTPUT, details=proto.TxRequestDetailsType(request_index=0)), proto.TxRequest(
proto.TxRequest(request_type=proto.RequestType.TXOUTPUT, details=proto.TxRequestDetailsType(request_index=1)), request_type=proto.RequestType.TXOUTPUT,
details=proto.TxRequestDetailsType(request_index=0),
),
proto.TxRequest(
request_type=proto.RequestType.TXOUTPUT,
details=proto.TxRequestDetailsType(request_index=1),
),
proto.TxRequest(
request_type=proto.RequestType.TXINPUT,
details=proto.TxRequestDetailsType(request_index=0),
),
proto.TxRequest(
request_type=proto.RequestType.TXINPUT,
details=proto.TxRequestDetailsType(request_index=1),
),
proto.TxRequest(
request_type=proto.RequestType.TXOUTPUT,
details=proto.TxRequestDetailsType(request_index=0),
),
proto.TxRequest(
request_type=proto.RequestType.TXOUTPUT,
details=proto.TxRequestDetailsType(request_index=1),
),
proto.TxRequest(
request_type=proto.RequestType.TXOUTPUT,
details=proto.TxRequestDetailsType(request_index=0),
),
proto.TxRequest(
request_type=proto.RequestType.TXOUTPUT,
details=proto.TxRequestDetailsType(request_index=1),
),
proto.TxRequest(request_type=proto.RequestType.TXFINISHED), proto.TxRequest(request_type=proto.RequestType.TXFINISHED),
] ]
return resp return resp
@ -169,44 +256,56 @@ class TestMultisigChange(TrezorTest):
self.setup_mnemonic_nopin_nopassphrase() self.setup_mnemonic_nopin_nopassphrase()
out1 = proto.TxOutputType( out1 = proto.TxOutputType(
address='muevUcG1Bb8eM2nGUGhqmeujHRX7YXjSEu', address="muevUcG1Bb8eM2nGUGhqmeujHRX7YXjSEu",
amount=40000000, amount=40000000,
script_type=proto.OutputScriptType.PAYTOADDRESS script_type=proto.OutputScriptType.PAYTOADDRESS,
) )
out2 = proto.TxOutputType( out2 = proto.TxOutputType(
address='mwdrpMVSJxxsM8f8xbnCHn9ERaRT1NG1UX', address="mwdrpMVSJxxsM8f8xbnCHn9ERaRT1NG1UX",
amount=44000000, amount=44000000,
script_type=proto.OutputScriptType.PAYTOADDRESS script_type=proto.OutputScriptType.PAYTOADDRESS,
) )
with self.client: with self.client:
self.client.set_expected_responses(self._responses(self.inp1, self.inp2)) self.client.set_expected_responses(self._responses(self.inp1, self.inp2))
(_, serialized_tx) = btc.sign_tx(self.client, 'Testnet', [self.inp1, self.inp2, ], [out1, out2, ]) (_, serialized_tx) = btc.sign_tx(
self.client, "Testnet", [self.inp1, self.inp2], [out1, out2]
)
assert hexlify(serialized_tx) == b'0100000002e53cf4e3fcd37f8c439286ce636476e1faeebf86bbb2f228a6b78d1b47c8c61601000000b400473044022064f13801744a6c21b694f62cdb5d834e852f13ecf85ed4d0a56ba279571c24e3022010fab4cb05bdd7b24c8376dda4f62a418548eea6eb483e58675fa06e0d5c642c014c69522103dc07026aacb5918dac4e09f9da8290d0ae22161699636c22cace78082116a7792103e70db185fad69c2971f0107a42930e5d82a9ed3a11b922a96fdfc4124b63e54c2103f3fe007a1e34ac76c1a2528e9149f90f9f93739929797afab6a8e18d682fa71053aeffffffff185315ae8050e18efa70d6ca96378a1194f57e2b102511f68b3a1414ee340cd800000000b4004730440220727b2522268f913acd213c507d7801b146e5b6cef666ad44b769c26d6c762e4d022021c0c2e9e8298dee2a490d956f7ab1b2d3160c1e37a50cc6d19a5e62eb484fc9014c6952210297ad8a5df42f9e362ef37d9a4ddced89d8f7a143690649aa0d0ff049c7daca842103ed1fd93989595d7ad4b488efd05a22c0239482c9a20923f2f214a38e54f6c41a2103f91460d79e4e463d7d90cb75254bcd62b515a99a950574c721efdc5f711dff3553aeffffffff02005a6202000000001976a9149b139230e4fe91c05a37ec334dc8378f3dbe377088ac00639f02000000001976a914b0d05a10926a7925508febdbab9a5bd4cda8c8f688ac00000000' assert (
hexlify(serialized_tx)
== b"0100000002e53cf4e3fcd37f8c439286ce636476e1faeebf86bbb2f228a6b78d1b47c8c61601000000b400473044022064f13801744a6c21b694f62cdb5d834e852f13ecf85ed4d0a56ba279571c24e3022010fab4cb05bdd7b24c8376dda4f62a418548eea6eb483e58675fa06e0d5c642c014c69522103dc07026aacb5918dac4e09f9da8290d0ae22161699636c22cace78082116a7792103e70db185fad69c2971f0107a42930e5d82a9ed3a11b922a96fdfc4124b63e54c2103f3fe007a1e34ac76c1a2528e9149f90f9f93739929797afab6a8e18d682fa71053aeffffffff185315ae8050e18efa70d6ca96378a1194f57e2b102511f68b3a1414ee340cd800000000b4004730440220727b2522268f913acd213c507d7801b146e5b6cef666ad44b769c26d6c762e4d022021c0c2e9e8298dee2a490d956f7ab1b2d3160c1e37a50cc6d19a5e62eb484fc9014c6952210297ad8a5df42f9e362ef37d9a4ddced89d8f7a143690649aa0d0ff049c7daca842103ed1fd93989595d7ad4b488efd05a22c0239482c9a20923f2f214a38e54f6c41a2103f91460d79e4e463d7d90cb75254bcd62b515a99a950574c721efdc5f711dff3553aeffffffff02005a6202000000001976a9149b139230e4fe91c05a37ec334dc8378f3dbe377088ac00639f02000000001976a914b0d05a10926a7925508febdbab9a5bd4cda8c8f688ac00000000"
)
# first external, second internal # first external, second internal
def test_external_internal(self): def test_external_internal(self):
self.setup_mnemonic_nopin_nopassphrase() self.setup_mnemonic_nopin_nopassphrase()
out1 = proto.TxOutputType( out1 = proto.TxOutputType(
address='muevUcG1Bb8eM2nGUGhqmeujHRX7YXjSEu', address="muevUcG1Bb8eM2nGUGhqmeujHRX7YXjSEu",
amount=40000000, amount=40000000,
script_type=proto.OutputScriptType.PAYTOADDRESS script_type=proto.OutputScriptType.PAYTOADDRESS,
) )
out2 = proto.TxOutputType( out2 = proto.TxOutputType(
address_n=parse_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,
) )
with self.client: with self.client:
self.client.set_expected_responses(self._responses(self.inp1, self.inp2, change=2)) self.client.set_expected_responses(
(_, serialized_tx) = btc.sign_tx(self.client, 'Testnet', [self.inp1, self.inp2, ], [out1, out2, ]) self._responses(self.inp1, self.inp2, change=2)
)
(_, serialized_tx) = btc.sign_tx(
self.client, "Testnet", [self.inp1, self.inp2], [out1, out2]
)
assert hexlify(serialized_tx) == b'0100000002e53cf4e3fcd37f8c439286ce636476e1faeebf86bbb2f228a6b78d1b47c8c61601000000b400473044022064f13801744a6c21b694f62cdb5d834e852f13ecf85ed4d0a56ba279571c24e3022010fab4cb05bdd7b24c8376dda4f62a418548eea6eb483e58675fa06e0d5c642c014c69522103dc07026aacb5918dac4e09f9da8290d0ae22161699636c22cace78082116a7792103e70db185fad69c2971f0107a42930e5d82a9ed3a11b922a96fdfc4124b63e54c2103f3fe007a1e34ac76c1a2528e9149f90f9f93739929797afab6a8e18d682fa71053aeffffffff185315ae8050e18efa70d6ca96378a1194f57e2b102511f68b3a1414ee340cd800000000b4004730440220727b2522268f913acd213c507d7801b146e5b6cef666ad44b769c26d6c762e4d022021c0c2e9e8298dee2a490d956f7ab1b2d3160c1e37a50cc6d19a5e62eb484fc9014c6952210297ad8a5df42f9e362ef37d9a4ddced89d8f7a143690649aa0d0ff049c7daca842103ed1fd93989595d7ad4b488efd05a22c0239482c9a20923f2f214a38e54f6c41a2103f91460d79e4e463d7d90cb75254bcd62b515a99a950574c721efdc5f711dff3553aeffffffff02005a6202000000001976a9149b139230e4fe91c05a37ec334dc8378f3dbe377088ac00639f02000000001976a914b0d05a10926a7925508febdbab9a5bd4cda8c8f688ac00000000' assert (
hexlify(serialized_tx)
== b"0100000002e53cf4e3fcd37f8c439286ce636476e1faeebf86bbb2f228a6b78d1b47c8c61601000000b400473044022064f13801744a6c21b694f62cdb5d834e852f13ecf85ed4d0a56ba279571c24e3022010fab4cb05bdd7b24c8376dda4f62a418548eea6eb483e58675fa06e0d5c642c014c69522103dc07026aacb5918dac4e09f9da8290d0ae22161699636c22cace78082116a7792103e70db185fad69c2971f0107a42930e5d82a9ed3a11b922a96fdfc4124b63e54c2103f3fe007a1e34ac76c1a2528e9149f90f9f93739929797afab6a8e18d682fa71053aeffffffff185315ae8050e18efa70d6ca96378a1194f57e2b102511f68b3a1414ee340cd800000000b4004730440220727b2522268f913acd213c507d7801b146e5b6cef666ad44b769c26d6c762e4d022021c0c2e9e8298dee2a490d956f7ab1b2d3160c1e37a50cc6d19a5e62eb484fc9014c6952210297ad8a5df42f9e362ef37d9a4ddced89d8f7a143690649aa0d0ff049c7daca842103ed1fd93989595d7ad4b488efd05a22c0239482c9a20923f2f214a38e54f6c41a2103f91460d79e4e463d7d90cb75254bcd62b515a99a950574c721efdc5f711dff3553aeffffffff02005a6202000000001976a9149b139230e4fe91c05a37ec334dc8378f3dbe377088ac00639f02000000001976a914b0d05a10926a7925508febdbab9a5bd4cda8c8f688ac00000000"
)
# first internal, second external # first internal, second external
def test_internal_external(self): def test_internal_external(self):
@ -215,42 +314,54 @@ class TestMultisigChange(TrezorTest):
out1 = proto.TxOutputType( out1 = proto.TxOutputType(
address_n=parse_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,
) )
out2 = proto.TxOutputType( out2 = proto.TxOutputType(
address='mwdrpMVSJxxsM8f8xbnCHn9ERaRT1NG1UX', address="mwdrpMVSJxxsM8f8xbnCHn9ERaRT1NG1UX",
amount=44000000, amount=44000000,
script_type=proto.OutputScriptType.PAYTOADDRESS script_type=proto.OutputScriptType.PAYTOADDRESS,
) )
with self.client: with self.client:
self.client.set_expected_responses(self._responses(self.inp1, self.inp2, change=1)) self.client.set_expected_responses(
(_, serialized_tx) = btc.sign_tx(self.client, 'Testnet', [self.inp1, self.inp2, ], [out1, out2, ]) self._responses(self.inp1, self.inp2, change=1)
)
(_, serialized_tx) = btc.sign_tx(
self.client, "Testnet", [self.inp1, self.inp2], [out1, out2]
)
assert hexlify(serialized_tx) == b'0100000002e53cf4e3fcd37f8c439286ce636476e1faeebf86bbb2f228a6b78d1b47c8c61601000000b400473044022064f13801744a6c21b694f62cdb5d834e852f13ecf85ed4d0a56ba279571c24e3022010fab4cb05bdd7b24c8376dda4f62a418548eea6eb483e58675fa06e0d5c642c014c69522103dc07026aacb5918dac4e09f9da8290d0ae22161699636c22cace78082116a7792103e70db185fad69c2971f0107a42930e5d82a9ed3a11b922a96fdfc4124b63e54c2103f3fe007a1e34ac76c1a2528e9149f90f9f93739929797afab6a8e18d682fa71053aeffffffff185315ae8050e18efa70d6ca96378a1194f57e2b102511f68b3a1414ee340cd800000000b4004730440220727b2522268f913acd213c507d7801b146e5b6cef666ad44b769c26d6c762e4d022021c0c2e9e8298dee2a490d956f7ab1b2d3160c1e37a50cc6d19a5e62eb484fc9014c6952210297ad8a5df42f9e362ef37d9a4ddced89d8f7a143690649aa0d0ff049c7daca842103ed1fd93989595d7ad4b488efd05a22c0239482c9a20923f2f214a38e54f6c41a2103f91460d79e4e463d7d90cb75254bcd62b515a99a950574c721efdc5f711dff3553aeffffffff02005a6202000000001976a9149b139230e4fe91c05a37ec334dc8378f3dbe377088ac00639f02000000001976a914b0d05a10926a7925508febdbab9a5bd4cda8c8f688ac00000000' assert (
hexlify(serialized_tx)
== b"0100000002e53cf4e3fcd37f8c439286ce636476e1faeebf86bbb2f228a6b78d1b47c8c61601000000b400473044022064f13801744a6c21b694f62cdb5d834e852f13ecf85ed4d0a56ba279571c24e3022010fab4cb05bdd7b24c8376dda4f62a418548eea6eb483e58675fa06e0d5c642c014c69522103dc07026aacb5918dac4e09f9da8290d0ae22161699636c22cace78082116a7792103e70db185fad69c2971f0107a42930e5d82a9ed3a11b922a96fdfc4124b63e54c2103f3fe007a1e34ac76c1a2528e9149f90f9f93739929797afab6a8e18d682fa71053aeffffffff185315ae8050e18efa70d6ca96378a1194f57e2b102511f68b3a1414ee340cd800000000b4004730440220727b2522268f913acd213c507d7801b146e5b6cef666ad44b769c26d6c762e4d022021c0c2e9e8298dee2a490d956f7ab1b2d3160c1e37a50cc6d19a5e62eb484fc9014c6952210297ad8a5df42f9e362ef37d9a4ddced89d8f7a143690649aa0d0ff049c7daca842103ed1fd93989595d7ad4b488efd05a22c0239482c9a20923f2f214a38e54f6c41a2103f91460d79e4e463d7d90cb75254bcd62b515a99a950574c721efdc5f711dff3553aeffffffff02005a6202000000001976a9149b139230e4fe91c05a37ec334dc8378f3dbe377088ac00639f02000000001976a914b0d05a10926a7925508febdbab9a5bd4cda8c8f688ac00000000"
)
# both outputs are external # both outputs are external
def test_multisig_external_external(self): def test_multisig_external_external(self):
self.setup_mnemonic_nopin_nopassphrase() self.setup_mnemonic_nopin_nopassphrase()
out1 = proto.TxOutputType( out1 = proto.TxOutputType(
address='2N2aFoogGntQFFwdUVPfRmutXD22ThcNTsR', address="2N2aFoogGntQFFwdUVPfRmutXD22ThcNTsR",
amount=40000000, amount=40000000,
script_type=proto.OutputScriptType.PAYTOADDRESS script_type=proto.OutputScriptType.PAYTOADDRESS,
) )
out2 = proto.TxOutputType( out2 = proto.TxOutputType(
address='2NFJjQcU8mw4Z3ywpbek8HL1VoJ27GDrkHw', address="2NFJjQcU8mw4Z3ywpbek8HL1VoJ27GDrkHw",
amount=44000000, amount=44000000,
script_type=proto.OutputScriptType.PAYTOADDRESS script_type=proto.OutputScriptType.PAYTOADDRESS,
) )
with self.client: with self.client:
self.client.set_expected_responses(self._responses(self.inp1, self.inp2)) self.client.set_expected_responses(self._responses(self.inp1, self.inp2))
(_, serialized_tx) = btc.sign_tx(self.client, 'Testnet', [self.inp1, self.inp2, ], [out1, out2, ]) (_, serialized_tx) = btc.sign_tx(
self.client, "Testnet", [self.inp1, self.inp2], [out1, out2]
)
assert hexlify(serialized_tx) == b'0100000002e53cf4e3fcd37f8c439286ce636476e1faeebf86bbb2f228a6b78d1b47c8c61601000000b400473044022059394e0dfcb2d2f4a6108703f801545ca5a820c0ac6a1859d0a3854813de55fa02207b6a57d70b82932ff58163336c461653a2dc82c78ed8157159e5178ac7325390014c69522103dc07026aacb5918dac4e09f9da8290d0ae22161699636c22cace78082116a7792103e70db185fad69c2971f0107a42930e5d82a9ed3a11b922a96fdfc4124b63e54c2103f3fe007a1e34ac76c1a2528e9149f90f9f93739929797afab6a8e18d682fa71053aeffffffff185315ae8050e18efa70d6ca96378a1194f57e2b102511f68b3a1414ee340cd800000000b40047304402205a911685f5b974b2fc4a19d5ce056218773a4d20b5eaae2c2f9594929308182002201e03449f5a8813ec19f408bf1b6f4f334886d6fcf9920e300fd7678ef0724f81014c6952210297ad8a5df42f9e362ef37d9a4ddced89d8f7a143690649aa0d0ff049c7daca842103ed1fd93989595d7ad4b488efd05a22c0239482c9a20923f2f214a38e54f6c41a2103f91460d79e4e463d7d90cb75254bcd62b515a99a950574c721efdc5f711dff3553aeffffffff02005a62020000000017a91466528dd543f94d162c8111d2ec248d25ba9b90948700639f020000000017a914f1fc92c0aed1712911c70a2e09ac15ff0922652f8700000000' assert (
hexlify(serialized_tx)
== b"0100000002e53cf4e3fcd37f8c439286ce636476e1faeebf86bbb2f228a6b78d1b47c8c61601000000b400473044022059394e0dfcb2d2f4a6108703f801545ca5a820c0ac6a1859d0a3854813de55fa02207b6a57d70b82932ff58163336c461653a2dc82c78ed8157159e5178ac7325390014c69522103dc07026aacb5918dac4e09f9da8290d0ae22161699636c22cace78082116a7792103e70db185fad69c2971f0107a42930e5d82a9ed3a11b922a96fdfc4124b63e54c2103f3fe007a1e34ac76c1a2528e9149f90f9f93739929797afab6a8e18d682fa71053aeffffffff185315ae8050e18efa70d6ca96378a1194f57e2b102511f68b3a1414ee340cd800000000b40047304402205a911685f5b974b2fc4a19d5ce056218773a4d20b5eaae2c2f9594929308182002201e03449f5a8813ec19f408bf1b6f4f334886d6fcf9920e300fd7678ef0724f81014c6952210297ad8a5df42f9e362ef37d9a4ddced89d8f7a143690649aa0d0ff049c7daca842103ed1fd93989595d7ad4b488efd05a22c0239482c9a20923f2f214a38e54f6c41a2103f91460d79e4e463d7d90cb75254bcd62b515a99a950574c721efdc5f711dff3553aeffffffff02005a62020000000017a91466528dd543f94d162c8111d2ec248d25ba9b90948700639f020000000017a914f1fc92c0aed1712911c70a2e09ac15ff0922652f8700000000"
)
# inputs match, change matches (first is change) # inputs match, change matches (first is change)
def test_multisig_change_match_first(self): def test_multisig_change_match_first(self):
@ -260,9 +371,9 @@ class TestMultisigChange(TrezorTest):
pubkeys=[ pubkeys=[
proto.HDNodePathType(node=self.node_ext2, address_n=[1, 0]), proto.HDNodePathType(node=self.node_ext2, address_n=[1, 0]),
proto.HDNodePathType(node=self.node_ext1, address_n=[1, 0]), proto.HDNodePathType(node=self.node_ext1, address_n=[1, 0]),
proto.HDNodePathType(node=self.node_int, address_n=[1, 0]) proto.HDNodePathType(node=self.node_int, address_n=[1, 0]),
], ],
signatures=[b'', b'', b''], signatures=[b"", b"", b""],
m=2, m=2,
) )
@ -270,20 +381,27 @@ class TestMultisigChange(TrezorTest):
address_n=[H_(45), 0, 1, 0], address_n=[H_(45), 0, 1, 0],
multisig=multisig_out1, multisig=multisig_out1,
amount=40000000, amount=40000000,
script_type=proto.OutputScriptType.PAYTOMULTISIG script_type=proto.OutputScriptType.PAYTOMULTISIG,
) )
out2 = proto.TxOutputType( out2 = proto.TxOutputType(
address='2NFJjQcU8mw4Z3ywpbek8HL1VoJ27GDrkHw', address="2NFJjQcU8mw4Z3ywpbek8HL1VoJ27GDrkHw",
amount=44000000, amount=44000000,
script_type=proto.OutputScriptType.PAYTOADDRESS script_type=proto.OutputScriptType.PAYTOADDRESS,
) )
with self.client: with self.client:
self.client.set_expected_responses(self._responses(self.inp1, self.inp2, change=1)) self.client.set_expected_responses(
(_, serialized_tx) = btc.sign_tx(self.client, 'Testnet', [self.inp1, self.inp2, ], [out1, out2, ]) self._responses(self.inp1, self.inp2, change=1)
)
(_, serialized_tx) = btc.sign_tx(
self.client, "Testnet", [self.inp1, self.inp2], [out1, out2]
)
assert hexlify(serialized_tx) == b'0100000002e53cf4e3fcd37f8c439286ce636476e1faeebf86bbb2f228a6b78d1b47c8c61601000000b400473044022059394e0dfcb2d2f4a6108703f801545ca5a820c0ac6a1859d0a3854813de55fa02207b6a57d70b82932ff58163336c461653a2dc82c78ed8157159e5178ac7325390014c69522103dc07026aacb5918dac4e09f9da8290d0ae22161699636c22cace78082116a7792103e70db185fad69c2971f0107a42930e5d82a9ed3a11b922a96fdfc4124b63e54c2103f3fe007a1e34ac76c1a2528e9149f90f9f93739929797afab6a8e18d682fa71053aeffffffff185315ae8050e18efa70d6ca96378a1194f57e2b102511f68b3a1414ee340cd800000000b40047304402205a911685f5b974b2fc4a19d5ce056218773a4d20b5eaae2c2f9594929308182002201e03449f5a8813ec19f408bf1b6f4f334886d6fcf9920e300fd7678ef0724f81014c6952210297ad8a5df42f9e362ef37d9a4ddced89d8f7a143690649aa0d0ff049c7daca842103ed1fd93989595d7ad4b488efd05a22c0239482c9a20923f2f214a38e54f6c41a2103f91460d79e4e463d7d90cb75254bcd62b515a99a950574c721efdc5f711dff3553aeffffffff02005a62020000000017a91466528dd543f94d162c8111d2ec248d25ba9b90948700639f020000000017a914f1fc92c0aed1712911c70a2e09ac15ff0922652f8700000000' assert (
hexlify(serialized_tx)
== b"0100000002e53cf4e3fcd37f8c439286ce636476e1faeebf86bbb2f228a6b78d1b47c8c61601000000b400473044022059394e0dfcb2d2f4a6108703f801545ca5a820c0ac6a1859d0a3854813de55fa02207b6a57d70b82932ff58163336c461653a2dc82c78ed8157159e5178ac7325390014c69522103dc07026aacb5918dac4e09f9da8290d0ae22161699636c22cace78082116a7792103e70db185fad69c2971f0107a42930e5d82a9ed3a11b922a96fdfc4124b63e54c2103f3fe007a1e34ac76c1a2528e9149f90f9f93739929797afab6a8e18d682fa71053aeffffffff185315ae8050e18efa70d6ca96378a1194f57e2b102511f68b3a1414ee340cd800000000b40047304402205a911685f5b974b2fc4a19d5ce056218773a4d20b5eaae2c2f9594929308182002201e03449f5a8813ec19f408bf1b6f4f334886d6fcf9920e300fd7678ef0724f81014c6952210297ad8a5df42f9e362ef37d9a4ddced89d8f7a143690649aa0d0ff049c7daca842103ed1fd93989595d7ad4b488efd05a22c0239482c9a20923f2f214a38e54f6c41a2103f91460d79e4e463d7d90cb75254bcd62b515a99a950574c721efdc5f711dff3553aeffffffff02005a62020000000017a91466528dd543f94d162c8111d2ec248d25ba9b90948700639f020000000017a914f1fc92c0aed1712911c70a2e09ac15ff0922652f8700000000"
)
# inputs match, change matches (second is change) # inputs match, change matches (second is change)
def test_multisig_change_match_second(self): def test_multisig_change_match_second(self):
@ -293,30 +411,37 @@ class TestMultisigChange(TrezorTest):
pubkeys=[ pubkeys=[
proto.HDNodePathType(node=self.node_ext1, address_n=[1, 1]), proto.HDNodePathType(node=self.node_ext1, address_n=[1, 1]),
proto.HDNodePathType(node=self.node_ext2, address_n=[1, 1]), proto.HDNodePathType(node=self.node_ext2, address_n=[1, 1]),
proto.HDNodePathType(node=self.node_int, address_n=[1, 1]) proto.HDNodePathType(node=self.node_int, address_n=[1, 1]),
], ],
signatures=[b'', b'', b''], signatures=[b"", b"", b""],
m=2, m=2,
) )
out1 = proto.TxOutputType( out1 = proto.TxOutputType(
address='2N2aFoogGntQFFwdUVPfRmutXD22ThcNTsR', address="2N2aFoogGntQFFwdUVPfRmutXD22ThcNTsR",
amount=40000000, amount=40000000,
script_type=proto.OutputScriptType.PAYTOADDRESS script_type=proto.OutputScriptType.PAYTOADDRESS,
) )
out2 = proto.TxOutputType( out2 = proto.TxOutputType(
address_n=[H_(45), 0, 1, 1], address_n=[H_(45), 0, 1, 1],
multisig=multisig_out2, multisig=multisig_out2,
amount=44000000, amount=44000000,
script_type=proto.OutputScriptType.PAYTOMULTISIG script_type=proto.OutputScriptType.PAYTOMULTISIG,
) )
with self.client: with self.client:
self.client.set_expected_responses(self._responses(self.inp1, self.inp2, change=2)) self.client.set_expected_responses(
(_, serialized_tx) = btc.sign_tx(self.client, 'Testnet', [self.inp1, self.inp2, ], [out1, out2, ]) self._responses(self.inp1, self.inp2, change=2)
)
(_, serialized_tx) = btc.sign_tx(
self.client, "Testnet", [self.inp1, self.inp2], [out1, out2]
)
assert hexlify(serialized_tx) == b'0100000002e53cf4e3fcd37f8c439286ce636476e1faeebf86bbb2f228a6b78d1b47c8c61601000000b400473044022059394e0dfcb2d2f4a6108703f801545ca5a820c0ac6a1859d0a3854813de55fa02207b6a57d70b82932ff58163336c461653a2dc82c78ed8157159e5178ac7325390014c69522103dc07026aacb5918dac4e09f9da8290d0ae22161699636c22cace78082116a7792103e70db185fad69c2971f0107a42930e5d82a9ed3a11b922a96fdfc4124b63e54c2103f3fe007a1e34ac76c1a2528e9149f90f9f93739929797afab6a8e18d682fa71053aeffffffff185315ae8050e18efa70d6ca96378a1194f57e2b102511f68b3a1414ee340cd800000000b40047304402205a911685f5b974b2fc4a19d5ce056218773a4d20b5eaae2c2f9594929308182002201e03449f5a8813ec19f408bf1b6f4f334886d6fcf9920e300fd7678ef0724f81014c6952210297ad8a5df42f9e362ef37d9a4ddced89d8f7a143690649aa0d0ff049c7daca842103ed1fd93989595d7ad4b488efd05a22c0239482c9a20923f2f214a38e54f6c41a2103f91460d79e4e463d7d90cb75254bcd62b515a99a950574c721efdc5f711dff3553aeffffffff02005a62020000000017a91466528dd543f94d162c8111d2ec248d25ba9b90948700639f020000000017a914f1fc92c0aed1712911c70a2e09ac15ff0922652f8700000000' assert (
hexlify(serialized_tx)
== b"0100000002e53cf4e3fcd37f8c439286ce636476e1faeebf86bbb2f228a6b78d1b47c8c61601000000b400473044022059394e0dfcb2d2f4a6108703f801545ca5a820c0ac6a1859d0a3854813de55fa02207b6a57d70b82932ff58163336c461653a2dc82c78ed8157159e5178ac7325390014c69522103dc07026aacb5918dac4e09f9da8290d0ae22161699636c22cace78082116a7792103e70db185fad69c2971f0107a42930e5d82a9ed3a11b922a96fdfc4124b63e54c2103f3fe007a1e34ac76c1a2528e9149f90f9f93739929797afab6a8e18d682fa71053aeffffffff185315ae8050e18efa70d6ca96378a1194f57e2b102511f68b3a1414ee340cd800000000b40047304402205a911685f5b974b2fc4a19d5ce056218773a4d20b5eaae2c2f9594929308182002201e03449f5a8813ec19f408bf1b6f4f334886d6fcf9920e300fd7678ef0724f81014c6952210297ad8a5df42f9e362ef37d9a4ddced89d8f7a143690649aa0d0ff049c7daca842103ed1fd93989595d7ad4b488efd05a22c0239482c9a20923f2f214a38e54f6c41a2103f91460d79e4e463d7d90cb75254bcd62b515a99a950574c721efdc5f711dff3553aeffffffff02005a62020000000017a91466528dd543f94d162c8111d2ec248d25ba9b90948700639f020000000017a914f1fc92c0aed1712911c70a2e09ac15ff0922652f8700000000"
)
# inputs match, change mismatches (second tries to be change but isn't) # inputs match, change mismatches (second tries to be change but isn't)
def test_multisig_mismatch_change(self): def test_multisig_mismatch_change(self):
@ -326,30 +451,35 @@ class TestMultisigChange(TrezorTest):
pubkeys=[ pubkeys=[
proto.HDNodePathType(node=self.node_ext1, address_n=[1, 0]), proto.HDNodePathType(node=self.node_ext1, address_n=[1, 0]),
proto.HDNodePathType(node=self.node_int, address_n=[1, 0]), proto.HDNodePathType(node=self.node_int, address_n=[1, 0]),
proto.HDNodePathType(node=self.node_ext3, address_n=[1, 0]) proto.HDNodePathType(node=self.node_ext3, address_n=[1, 0]),
], ],
signatures=[b'', b'', b''], signatures=[b"", b"", b""],
m=2, m=2,
) )
out1 = proto.TxOutputType( out1 = proto.TxOutputType(
address='2N2aFoogGntQFFwdUVPfRmutXD22ThcNTsR', address="2N2aFoogGntQFFwdUVPfRmutXD22ThcNTsR",
amount=40000000, amount=40000000,
script_type=proto.OutputScriptType.PAYTOADDRESS script_type=proto.OutputScriptType.PAYTOADDRESS,
) )
out2 = proto.TxOutputType( out2 = proto.TxOutputType(
address_n=[H_(45), 0, 1, 0], address_n=[H_(45), 0, 1, 0],
multisig=multisig_out2, multisig=multisig_out2,
amount=44000000, amount=44000000,
script_type=proto.OutputScriptType.PAYTOMULTISIG script_type=proto.OutputScriptType.PAYTOMULTISIG,
) )
with self.client: with self.client:
self.client.set_expected_responses(self._responses(self.inp1, self.inp2)) self.client.set_expected_responses(self._responses(self.inp1, self.inp2))
(_, serialized_tx) = btc.sign_tx(self.client, 'Testnet', [self.inp1, self.inp2, ], [out1, out2, ]) (_, serialized_tx) = btc.sign_tx(
self.client, "Testnet", [self.inp1, self.inp2], [out1, out2]
)
assert hexlify(serialized_tx) == b'0100000002e53cf4e3fcd37f8c439286ce636476e1faeebf86bbb2f228a6b78d1b47c8c61601000000b40047304402207f9992cc0230527faf54ec6bd233307db82bc8fac039dcee418bc6feb4e96a3a02206bb4cb157ad27c123277328a877572563a45d70b844d9ab07cc42238112f8c2a014c69522103dc07026aacb5918dac4e09f9da8290d0ae22161699636c22cace78082116a7792103e70db185fad69c2971f0107a42930e5d82a9ed3a11b922a96fdfc4124b63e54c2103f3fe007a1e34ac76c1a2528e9149f90f9f93739929797afab6a8e18d682fa71053aeffffffff185315ae8050e18efa70d6ca96378a1194f57e2b102511f68b3a1414ee340cd800000000b400473044022078a41bfa87d72d6ba810d84bf568b5a29acf8b851ba6c3a8dbff079b34a7feb0022037b770c776db0b6c883c38a684a121b90a59ed1958774cbf64de70e53e29639f014c6952210297ad8a5df42f9e362ef37d9a4ddced89d8f7a143690649aa0d0ff049c7daca842103ed1fd93989595d7ad4b488efd05a22c0239482c9a20923f2f214a38e54f6c41a2103f91460d79e4e463d7d90cb75254bcd62b515a99a950574c721efdc5f711dff3553aeffffffff02005a62020000000017a91466528dd543f94d162c8111d2ec248d25ba9b90948700639f020000000017a914e6a3e2fbadb7f559f8d20c46aceae78c96fcf1d18700000000' assert (
hexlify(serialized_tx)
== b"0100000002e53cf4e3fcd37f8c439286ce636476e1faeebf86bbb2f228a6b78d1b47c8c61601000000b40047304402207f9992cc0230527faf54ec6bd233307db82bc8fac039dcee418bc6feb4e96a3a02206bb4cb157ad27c123277328a877572563a45d70b844d9ab07cc42238112f8c2a014c69522103dc07026aacb5918dac4e09f9da8290d0ae22161699636c22cace78082116a7792103e70db185fad69c2971f0107a42930e5d82a9ed3a11b922a96fdfc4124b63e54c2103f3fe007a1e34ac76c1a2528e9149f90f9f93739929797afab6a8e18d682fa71053aeffffffff185315ae8050e18efa70d6ca96378a1194f57e2b102511f68b3a1414ee340cd800000000b400473044022078a41bfa87d72d6ba810d84bf568b5a29acf8b851ba6c3a8dbff079b34a7feb0022037b770c776db0b6c883c38a684a121b90a59ed1958774cbf64de70e53e29639f014c6952210297ad8a5df42f9e362ef37d9a4ddced89d8f7a143690649aa0d0ff049c7daca842103ed1fd93989595d7ad4b488efd05a22c0239482c9a20923f2f214a38e54f6c41a2103f91460d79e4e463d7d90cb75254bcd62b515a99a950574c721efdc5f711dff3553aeffffffff02005a62020000000017a91466528dd543f94d162c8111d2ec248d25ba9b90948700639f020000000017a914e6a3e2fbadb7f559f8d20c46aceae78c96fcf1d18700000000"
)
# inputs mismatch, change matches with first input # inputs mismatch, change matches with first input
def test_multisig_mismatch_inputs(self): def test_multisig_mismatch_inputs(self):
@ -359,9 +489,9 @@ class TestMultisigChange(TrezorTest):
pubkeys=[ pubkeys=[
proto.HDNodePathType(node=self.node_ext2, address_n=[1, 0]), proto.HDNodePathType(node=self.node_ext2, address_n=[1, 0]),
proto.HDNodePathType(node=self.node_ext1, address_n=[1, 0]), proto.HDNodePathType(node=self.node_ext1, address_n=[1, 0]),
proto.HDNodePathType(node=self.node_int, address_n=[1, 0]) proto.HDNodePathType(node=self.node_int, address_n=[1, 0]),
], ],
signatures=[b'', b'', b''], signatures=[b"", b"", b""],
m=2, m=2,
) )
@ -369,17 +499,22 @@ class TestMultisigChange(TrezorTest):
address_n=[H_(45), 0, 1, 0], address_n=[H_(45), 0, 1, 0],
multisig=multisig_out1, multisig=multisig_out1,
amount=40000000, amount=40000000,
script_type=proto.OutputScriptType.PAYTOMULTISIG script_type=proto.OutputScriptType.PAYTOMULTISIG,
) )
out2 = proto.TxOutputType( out2 = proto.TxOutputType(
address='2NFJjQcU8mw4Z3ywpbek8HL1VoJ27GDrkHw', address="2NFJjQcU8mw4Z3ywpbek8HL1VoJ27GDrkHw",
amount=65000000, amount=65000000,
script_type=proto.OutputScriptType.PAYTOADDRESS script_type=proto.OutputScriptType.PAYTOADDRESS,
) )
with self.client: with self.client:
self.client.set_expected_responses(self._responses(self.inp1, self.inp3)) self.client.set_expected_responses(self._responses(self.inp1, self.inp3))
(_, serialized_tx) = btc.sign_tx(self.client, 'Testnet', [self.inp1, self.inp3, ], [out1, out2, ]) (_, serialized_tx) = btc.sign_tx(
self.client, "Testnet", [self.inp1, self.inp3], [out1, out2]
)
assert hexlify(serialized_tx) == b'0100000002e53cf4e3fcd37f8c439286ce636476e1faeebf86bbb2f228a6b78d1b47c8c61601000000b500483045022100d907b9339951c96ef4515ef7aff8b3c28c4c8c5875d7421aa1de9f3a94e3508302205cdc311a6c91dfbb74f1a9a940a994a65dbfb0cf6dedcaaaeee839e0b8fd016d014c69522103dc07026aacb5918dac4e09f9da8290d0ae22161699636c22cace78082116a7792103e70db185fad69c2971f0107a42930e5d82a9ed3a11b922a96fdfc4124b63e54c2103f3fe007a1e34ac76c1a2528e9149f90f9f93739929797afab6a8e18d682fa71053aeffffffff39f756d82082b580b0d69ae8798ff10a981820ccfe1ab149a708a37bc26d94b000000000b500483045022100fdad4a47d15f47cc364fe0cbed11b1ced1f9ef210bc1bd413ec4384f630c63720220752e4f09ea4e5e6623f5ebe89b3983ec6e5702f63f9bce696f10b2d594d23532014c6952210297ad8a5df42f9e362ef37d9a4ddced89d8f7a143690649aa0d0ff049c7daca842103b6321a1194e5cc47b6b7edc3f67a096e6f71ccb72440f84f390b6e98df0ea8ec2103f91460d79e4e463d7d90cb75254bcd62b515a99a950574c721efdc5f711dff3553aeffffffff02005a62020000000017a91466528dd543f94d162c8111d2ec248d25ba9b90948740d2df030000000017a914f1fc92c0aed1712911c70a2e09ac15ff0922652f8700000000' assert (
hexlify(serialized_tx)
== b"0100000002e53cf4e3fcd37f8c439286ce636476e1faeebf86bbb2f228a6b78d1b47c8c61601000000b500483045022100d907b9339951c96ef4515ef7aff8b3c28c4c8c5875d7421aa1de9f3a94e3508302205cdc311a6c91dfbb74f1a9a940a994a65dbfb0cf6dedcaaaeee839e0b8fd016d014c69522103dc07026aacb5918dac4e09f9da8290d0ae22161699636c22cace78082116a7792103e70db185fad69c2971f0107a42930e5d82a9ed3a11b922a96fdfc4124b63e54c2103f3fe007a1e34ac76c1a2528e9149f90f9f93739929797afab6a8e18d682fa71053aeffffffff39f756d82082b580b0d69ae8798ff10a981820ccfe1ab149a708a37bc26d94b000000000b500483045022100fdad4a47d15f47cc364fe0cbed11b1ced1f9ef210bc1bd413ec4384f630c63720220752e4f09ea4e5e6623f5ebe89b3983ec6e5702f63f9bce696f10b2d594d23532014c6952210297ad8a5df42f9e362ef37d9a4ddced89d8f7a143690649aa0d0ff049c7daca842103b6321a1194e5cc47b6b7edc3f67a096e6f71ccb72440f84f390b6e98df0ea8ec2103f91460d79e4e463d7d90cb75254bcd62b515a99a950574c721efdc5f711dff3553aeffffffff02005a62020000000017a91466528dd543f94d162c8111d2ec248d25ba9b90948740d2df030000000017a914f1fc92c0aed1712911c70a2e09ac15ff0922652f8700000000"
)

View File

@ -14,20 +14,22 @@
# You should have received a copy of the License along with this library. # You should have received a copy of the License along with this library.
# If not, see <https://www.gnu.org/licenses/lgpl-3.0.html>. # If not, see <https://www.gnu.org/licenses/lgpl-3.0.html>.
from binascii import unhexlify, hexlify from binascii import hexlify, unhexlify
import pytest import pytest
from trezorlib import btc, messages as proto
from trezorlib.tools import CallException
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.tools import CallException
from trezorlib import btc
TXHASH_d5f65e = unhexlify('d5f65ee80147b4bcc70b75e4bbf2d7382021b871bd8867ef8fa525ef50864882') TXHASH_d5f65e = unhexlify(
"d5f65ee80147b4bcc70b75e4bbf2d7382021b871bd8867ef8fa525ef50864882"
)
class TestOpReturn(TrezorTest): class TestOpReturn(TrezorTest):
def test_opreturn(self): def test_opreturn(self):
self.setup_mnemonic_nopin_nopassphrase() self.setup_mnemonic_nopin_nopassphrase()
@ -42,39 +44,88 @@ class TestOpReturn(TrezorTest):
) )
out1 = proto.TxOutputType( out1 = proto.TxOutputType(
address='1MJ2tj2ThBE62zXbBYA5ZaN3fdve5CPAz1', address="1MJ2tj2ThBE62zXbBYA5ZaN3fdve5CPAz1",
amount=390000 - 10000, amount=390000 - 10000,
script_type=proto.OutputScriptType.PAYTOADDRESS, script_type=proto.OutputScriptType.PAYTOADDRESS,
) )
out2 = proto.TxOutputType( out2 = proto.TxOutputType(
op_return_data=b'test of the op_return data', op_return_data=b"test of the op_return data",
amount=0, amount=0,
script_type=proto.OutputScriptType.PAYTOOPRETURN, script_type=proto.OutputScriptType.PAYTOOPRETURN,
) )
with self.client: with self.client:
self.client.set_expected_responses([ self.client.set_expected_responses(
proto.TxRequest(request_type=proto.RequestType.TXINPUT, details=proto.TxRequestDetailsType(request_index=0)), [
proto.TxRequest(request_type=proto.RequestType.TXMETA, details=proto.TxRequestDetailsType(tx_hash=TXHASH_d5f65e)), proto.TxRequest(
proto.TxRequest(request_type=proto.RequestType.TXINPUT, details=proto.TxRequestDetailsType(request_index=0, tx_hash=TXHASH_d5f65e)), request_type=proto.RequestType.TXINPUT,
proto.TxRequest(request_type=proto.RequestType.TXINPUT, details=proto.TxRequestDetailsType(request_index=1, tx_hash=TXHASH_d5f65e)), details=proto.TxRequestDetailsType(request_index=0),
proto.TxRequest(request_type=proto.RequestType.TXOUTPUT, details=proto.TxRequestDetailsType(request_index=0, tx_hash=TXHASH_d5f65e)), ),
proto.TxRequest(request_type=proto.RequestType.TXOUTPUT, details=proto.TxRequestDetailsType(request_index=0)), proto.TxRequest(
proto.ButtonRequest(code=proto.ButtonRequestType.ConfirmOutput), request_type=proto.RequestType.TXMETA,
proto.TxRequest(request_type=proto.RequestType.TXOUTPUT, details=proto.TxRequestDetailsType(request_index=1)), details=proto.TxRequestDetailsType(tx_hash=TXHASH_d5f65e),
proto.ButtonRequest(code=proto.ButtonRequestType.ConfirmOutput), ),
proto.ButtonRequest(code=proto.ButtonRequestType.SignTx), proto.TxRequest(
proto.TxRequest(request_type=proto.RequestType.TXINPUT, details=proto.TxRequestDetailsType(request_index=0)), request_type=proto.RequestType.TXINPUT,
proto.TxRequest(request_type=proto.RequestType.TXOUTPUT, details=proto.TxRequestDetailsType(request_index=0)), details=proto.TxRequestDetailsType(
proto.TxRequest(request_type=proto.RequestType.TXOUTPUT, details=proto.TxRequestDetailsType(request_index=1)), request_index=0, tx_hash=TXHASH_d5f65e
proto.TxRequest(request_type=proto.RequestType.TXOUTPUT, details=proto.TxRequestDetailsType(request_index=0)), ),
proto.TxRequest(request_type=proto.RequestType.TXOUTPUT, details=proto.TxRequestDetailsType(request_index=1)), ),
proto.TxRequest(request_type=proto.RequestType.TXFINISHED), proto.TxRequest(
]) request_type=proto.RequestType.TXINPUT,
(signatures, serialized_tx) = btc.sign_tx(self.client, 'Bitcoin', [inp1, ], [out1, out2]) details=proto.TxRequestDetailsType(
request_index=1, tx_hash=TXHASH_d5f65e
),
),
proto.TxRequest(
request_type=proto.RequestType.TXOUTPUT,
details=proto.TxRequestDetailsType(
request_index=0, tx_hash=TXHASH_d5f65e
),
),
proto.TxRequest(
request_type=proto.RequestType.TXOUTPUT,
details=proto.TxRequestDetailsType(request_index=0),
),
proto.ButtonRequest(code=proto.ButtonRequestType.ConfirmOutput),
proto.TxRequest(
request_type=proto.RequestType.TXOUTPUT,
details=proto.TxRequestDetailsType(request_index=1),
),
proto.ButtonRequest(code=proto.ButtonRequestType.ConfirmOutput),
proto.ButtonRequest(code=proto.ButtonRequestType.SignTx),
proto.TxRequest(
request_type=proto.RequestType.TXINPUT,
details=proto.TxRequestDetailsType(request_index=0),
),
proto.TxRequest(
request_type=proto.RequestType.TXOUTPUT,
details=proto.TxRequestDetailsType(request_index=0),
),
proto.TxRequest(
request_type=proto.RequestType.TXOUTPUT,
details=proto.TxRequestDetailsType(request_index=1),
),
proto.TxRequest(
request_type=proto.RequestType.TXOUTPUT,
details=proto.TxRequestDetailsType(request_index=0),
),
proto.TxRequest(
request_type=proto.RequestType.TXOUTPUT,
details=proto.TxRequestDetailsType(request_index=1),
),
proto.TxRequest(request_type=proto.RequestType.TXFINISHED),
]
)
(signatures, serialized_tx) = btc.sign_tx(
self.client, "Bitcoin", [inp1], [out1, out2]
)
assert hexlify(serialized_tx) == b'010000000182488650ef25a58fef6788bd71b8212038d7f2bbe4750bc7bcb44701e85ef6d5000000006a4730440220187b7b9c340a32fc8445418ad11fb3827d2e8bac7d730e1c9ad800353e7ba62f02206c0c5820ba8882c82923a39aee8d36d6d32e13daed73f7a3d6199de5f8e7ddfd0121023230848585885f63803a0a8aecdd6538792d5c539215c91698e315bf0253b43dffffffff0260cc0500000000001976a914de9b2a8da088824e8fe51debea566617d851537888ac00000000000000001c6a1a74657374206f6620746865206f705f72657475726e206461746100000000' assert (
hexlify(serialized_tx)
== b"010000000182488650ef25a58fef6788bd71b8212038d7f2bbe4750bc7bcb44701e85ef6d5000000006a4730440220187b7b9c340a32fc8445418ad11fb3827d2e8bac7d730e1c9ad800353e7ba62f02206c0c5820ba8882c82923a39aee8d36d6d32e13daed73f7a3d6199de5f8e7ddfd0121023230848585885f63803a0a8aecdd6538792d5c539215c91698e315bf0253b43dffffffff0260cc0500000000001976a914de9b2a8da088824e8fe51debea566617d851537888ac00000000000000001c6a1a74657374206f6620746865206f705f72657475726e206461746100000000"
)
def test_nonzero_opreturn(self): def test_nonzero_opreturn(self):
self.setup_mnemonic_nopin_nopassphrase() self.setup_mnemonic_nopin_nopassphrase()
@ -90,28 +141,56 @@ class TestOpReturn(TrezorTest):
) )
out1 = proto.TxOutputType( out1 = proto.TxOutputType(
op_return_data=b'test of the op_return data', op_return_data=b"test of the op_return data",
amount=10000, amount=10000,
script_type=proto.OutputScriptType.PAYTOOPRETURN, script_type=proto.OutputScriptType.PAYTOOPRETURN,
) )
with self.client: with self.client:
self.client.set_expected_responses([ self.client.set_expected_responses(
proto.TxRequest(request_type=proto.RequestType.TXINPUT, details=proto.TxRequestDetailsType(request_index=0)), [
proto.TxRequest(request_type=proto.RequestType.TXMETA, details=proto.TxRequestDetailsType(tx_hash=TXHASH_d5f65e)), proto.TxRequest(
proto.TxRequest(request_type=proto.RequestType.TXINPUT, details=proto.TxRequestDetailsType(request_index=0, tx_hash=TXHASH_d5f65e)), request_type=proto.RequestType.TXINPUT,
proto.TxRequest(request_type=proto.RequestType.TXINPUT, details=proto.TxRequestDetailsType(request_index=1, tx_hash=TXHASH_d5f65e)), details=proto.TxRequestDetailsType(request_index=0),
proto.TxRequest(request_type=proto.RequestType.TXOUTPUT, details=proto.TxRequestDetailsType(request_index=0, tx_hash=TXHASH_d5f65e)), ),
proto.TxRequest(request_type=proto.RequestType.TXOUTPUT, details=proto.TxRequestDetailsType(request_index=0)), proto.TxRequest(
proto.Failure() request_type=proto.RequestType.TXMETA,
]) details=proto.TxRequestDetailsType(tx_hash=TXHASH_d5f65e),
),
proto.TxRequest(
request_type=proto.RequestType.TXINPUT,
details=proto.TxRequestDetailsType(
request_index=0, tx_hash=TXHASH_d5f65e
),
),
proto.TxRequest(
request_type=proto.RequestType.TXINPUT,
details=proto.TxRequestDetailsType(
request_index=1, tx_hash=TXHASH_d5f65e
),
),
proto.TxRequest(
request_type=proto.RequestType.TXOUTPUT,
details=proto.TxRequestDetailsType(
request_index=0, tx_hash=TXHASH_d5f65e
),
),
proto.TxRequest(
request_type=proto.RequestType.TXOUTPUT,
details=proto.TxRequestDetailsType(request_index=0),
),
proto.Failure(),
]
)
with pytest.raises(CallException) as exc: with pytest.raises(CallException) as exc:
btc.sign_tx(self.client, 'Bitcoin', [inp1], [out1]) btc.sign_tx(self.client, "Bitcoin", [inp1], [out1])
if TREZOR_VERSION == 1: if TREZOR_VERSION == 1:
assert exc.value.args[0] == proto.FailureType.ProcessError assert exc.value.args[0] == proto.FailureType.ProcessError
assert exc.value.args[1].endswith("Failed to compile output") assert exc.value.args[1].endswith("Failed to compile output")
else: else:
assert exc.value.args[0] == proto.FailureType.DataError assert exc.value.args[0] == proto.FailureType.DataError
assert exc.value.args[1].endswith('OP_RETURN output with non-zero amount') assert exc.value.args[1].endswith(
"OP_RETURN output with non-zero amount"
)

View File

@ -15,28 +15,28 @@
# If not, see <https://www.gnu.org/licenses/lgpl-3.0.html>. # If not, see <https://www.gnu.org/licenses/lgpl-3.0.html>.
import time import time
import pytest import pytest
from .common import TrezorTest
from trezorlib import messages as proto from trezorlib import messages as proto
from trezorlib.client import PinException from trezorlib.client import PinException
from .common import TrezorTest
# FIXME TODO Add passphrase tests # FIXME TODO Add passphrase tests
@pytest.mark.skip_t2 @pytest.mark.skip_t2
class TestProtectCall(TrezorTest): class TestProtectCall(TrezorTest):
def _some_protected_call(self, button, pin, passphrase): def _some_protected_call(self, button, pin, passphrase):
# This method perform any call which have protection in the device # This method perform any call which have protection in the device
res = self.client.ping( res = self.client.ping(
'random data', "random data",
button_protection=button, button_protection=button,
pin_protection=pin, pin_protection=pin,
passphrase_protection=passphrase passphrase_protection=passphrase,
) )
assert res == 'random data' assert res == "random data"
""" """
def test_expected_responses(self): def test_expected_responses(self):
@ -99,9 +99,9 @@ class TestProtectCall(TrezorTest):
with self.client: with self.client:
assert self.client.debug.read_pin()[0] == self.pin4 assert self.client.debug.read_pin()[0] == self.pin4
self.client.setup_debuglink(button=True, pin_correct=True) self.client.setup_debuglink(button=True, pin_correct=True)
self.client.set_expected_responses([proto.ButtonRequest(), self.client.set_expected_responses(
proto.PinMatrixRequest(), [proto.ButtonRequest(), proto.PinMatrixRequest(), proto.Success()]
proto.Success()]) )
self._some_protected_call(True, True, False) self._some_protected_call(True, True, False)
def test_incorrect_pin(self): def test_incorrect_pin(self):
@ -128,7 +128,10 @@ class TestProtectCall(TrezorTest):
expected = (2 ** (attempts - 1)) - 1 expected = (2 ** (attempts - 1)) - 1
got = round(time.time() - start, 2) got = round(time.time() - start, 2)
msg = "Pin delay expected to be at least %s seconds, got %s" % (expected, got) msg = "Pin delay expected to be at least %s seconds, got %s" % (
expected,
got,
)
print(msg) print(msg)
assert got >= expected assert got >= expected

View File

@ -15,22 +15,20 @@
# If not, see <https://www.gnu.org/licenses/lgpl-3.0.html>. # If not, see <https://www.gnu.org/licenses/lgpl-3.0.html>.
from binascii import unhexlify from binascii import unhexlify
import pytest import pytest
from trezorlib import btc, debuglink, device, messages as proto, misc
from .common import TrezorTest from .common import TrezorTest
from trezorlib import messages as proto
from trezorlib import btc
from trezorlib import debuglink
from trezorlib import device
from trezorlib import misc
TXHASH_d5f65e = unhexlify(
TXHASH_d5f65e = unhexlify('d5f65ee80147b4bcc70b75e4bbf2d7382021b871bd8867ef8fa525ef50864882') "d5f65ee80147b4bcc70b75e4bbf2d7382021b871bd8867ef8fa525ef50864882"
)
@pytest.mark.skip_t2 @pytest.mark.skip_t2
class TestProtectionLevels(TrezorTest): class TestProtectionLevels(TrezorTest):
def test_initialize(self): def test_initialize(self):
with self.client: with self.client:
self.setup_mnemonic_pin_passphrase() self.setup_mnemonic_pin_passphrase()
@ -40,131 +38,156 @@ class TestProtectionLevels(TrezorTest):
def test_apply_settings(self): def test_apply_settings(self):
with self.client: with self.client:
self.setup_mnemonic_pin_passphrase() self.setup_mnemonic_pin_passphrase()
self.client.set_expected_responses([ self.client.set_expected_responses(
proto.PinMatrixRequest(), [
proto.ButtonRequest(), proto.PinMatrixRequest(),
proto.Success(), proto.ButtonRequest(),
proto.Features() proto.Success(),
]) # TrezorClient reinitializes device proto.Features(),
device.apply_settings(self.client, label='nazdar') ]
) # TrezorClient reinitializes device
device.apply_settings(self.client, label="nazdar")
def test_change_pin(self): def test_change_pin(self):
with self.client: with self.client:
self.setup_mnemonic_pin_passphrase() self.setup_mnemonic_pin_passphrase()
self.client.set_expected_responses([ self.client.set_expected_responses(
proto.ButtonRequest(), [
proto.PinMatrixRequest(), proto.ButtonRequest(),
proto.PinMatrixRequest(), proto.PinMatrixRequest(),
proto.PinMatrixRequest(), proto.PinMatrixRequest(),
proto.Success(), proto.PinMatrixRequest(),
proto.Features() proto.Success(),
]) proto.Features(),
]
)
device.change_pin(self.client) device.change_pin(self.client)
def test_ping(self): def test_ping(self):
with self.client: with self.client:
self.setup_mnemonic_pin_passphrase() self.setup_mnemonic_pin_passphrase()
self.client.set_expected_responses([ self.client.set_expected_responses(
proto.ButtonRequest(), [
proto.PinMatrixRequest(), proto.ButtonRequest(),
proto.PassphraseRequest(), proto.PinMatrixRequest(),
proto.Success() proto.PassphraseRequest(),
]) proto.Success(),
self.client.ping('msg', True, True, True) ]
)
self.client.ping("msg", True, True, True)
def test_get_entropy(self): def test_get_entropy(self):
with self.client: with self.client:
self.setup_mnemonic_pin_passphrase() self.setup_mnemonic_pin_passphrase()
self.client.set_expected_responses([ self.client.set_expected_responses([proto.ButtonRequest(), proto.Entropy()])
proto.ButtonRequest(),
proto.Entropy()
])
misc.get_entropy(self.client, 10) misc.get_entropy(self.client, 10)
def test_get_public_key(self): def test_get_public_key(self):
with self.client: with self.client:
self.setup_mnemonic_pin_passphrase() self.setup_mnemonic_pin_passphrase()
self.client.set_expected_responses([ self.client.set_expected_responses(
proto.PinMatrixRequest(), [proto.PinMatrixRequest(), proto.PassphraseRequest(), proto.PublicKey()]
proto.PassphraseRequest(), )
proto.PublicKey()
])
btc.get_public_node(self.client, []) btc.get_public_node(self.client, [])
def test_get_address(self): def test_get_address(self):
with self.client: with self.client:
self.setup_mnemonic_pin_passphrase() self.setup_mnemonic_pin_passphrase()
self.client.set_expected_responses([ self.client.set_expected_responses(
proto.PinMatrixRequest(), [proto.PinMatrixRequest(), proto.PassphraseRequest(), proto.Address()]
proto.PassphraseRequest(), )
proto.Address() btc.get_address(self.client, "Bitcoin", [])
])
btc.get_address(self.client, 'Bitcoin', [])
def test_wipe_device(self): def test_wipe_device(self):
with self.client: with self.client:
self.setup_mnemonic_pin_passphrase() self.setup_mnemonic_pin_passphrase()
self.client.set_expected_responses([ self.client.set_expected_responses(
proto.ButtonRequest(), [proto.ButtonRequest(), proto.Success(), proto.Features()]
proto.Success(), )
proto.Features()
])
device.wipe(self.client) device.wipe(self.client)
def test_load_device(self): def test_load_device(self):
with self.client: with self.client:
self.client.set_expected_responses([proto.ButtonRequest(), self.client.set_expected_responses(
proto.Success(), [proto.ButtonRequest(), proto.Success(), proto.Features()]
proto.Features()]) )
debuglink.load_device_by_mnemonic(self.client, 'this is mnemonic', '1234', True, 'label', 'english', skip_checksum=True) debuglink.load_device_by_mnemonic(
self.client,
"this is mnemonic",
"1234",
True,
"label",
"english",
skip_checksum=True,
)
# This must fail, because device is already initialized # This must fail, because device is already initialized
with pytest.raises(Exception): with pytest.raises(Exception):
debuglink.load_device_by_mnemonic(self.client, 'this is mnemonic', '1234', True, 'label', 'english', skip_checksum=True) debuglink.load_device_by_mnemonic(
self.client,
"this is mnemonic",
"1234",
True,
"label",
"english",
skip_checksum=True,
)
def test_reset_device(self): def test_reset_device(self):
with self.client: with self.client:
self.client.set_expected_responses([proto.EntropyRequest()] + [proto.ButtonRequest()] * 24 + [proto.Success(), proto.Features()]) self.client.set_expected_responses(
device.reset(self.client, False, 128, True, False, 'label', 'english') [proto.EntropyRequest()]
+ [proto.ButtonRequest()] * 24
+ [proto.Success(), proto.Features()]
)
device.reset(self.client, False, 128, True, False, "label", "english")
# This must fail, because device is already initialized # This must fail, because device is already initialized
with pytest.raises(Exception): with pytest.raises(Exception):
device.reset(self.client, False, 128, True, False, 'label', 'english') device.reset(self.client, False, 128, True, False, "label", "english")
def test_recovery_device(self): def test_recovery_device(self):
with self.client: with self.client:
self.client.set_mnemonic(self.mnemonic12) self.client.set_mnemonic(self.mnemonic12)
self.client.set_expected_responses( self.client.set_expected_responses(
[proto.ButtonRequest()] + [proto.ButtonRequest()]
[proto.WordRequest()] * 24 + + [proto.WordRequest()] * 24
[proto.Success(), proto.Features()]) + [proto.Success(), proto.Features()]
device.recover(self.client, 12, False, False, 'label', 'english') )
device.recover(self.client, 12, False, False, "label", "english")
# This must fail, because device is already initialized # This must fail, because device is already initialized
with pytest.raises(Exception): with pytest.raises(Exception):
device.recover(self.client, 12, False, False, 'label', 'english') device.recover(self.client, 12, False, False, "label", "english")
def test_sign_message(self): def test_sign_message(self):
with self.client: with self.client:
self.setup_mnemonic_pin_passphrase() self.setup_mnemonic_pin_passphrase()
self.client.set_expected_responses([ self.client.set_expected_responses(
proto.ButtonRequest(), [
proto.PinMatrixRequest(), proto.ButtonRequest(),
proto.PassphraseRequest(), proto.PinMatrixRequest(),
proto.MessageSignature() proto.PassphraseRequest(),
]) proto.MessageSignature(),
btc.sign_message(self.client, 'Bitcoin', [], 'testing message') ]
)
btc.sign_message(self.client, "Bitcoin", [], "testing message")
def test_verify_message(self): def test_verify_message(self):
with self.client: with self.client:
self.setup_mnemonic_pin_passphrase() self.setup_mnemonic_pin_passphrase()
self.client.set_expected_responses([proto.ButtonRequest(), proto.ButtonRequest(), proto.Success()]) self.client.set_expected_responses(
[proto.ButtonRequest(), proto.ButtonRequest(), proto.Success()]
)
btc.verify_message( btc.verify_message(
self.client, self.client,
'Bitcoin', "Bitcoin",
'14LmW5k4ssUrtbAB4255zdqv3b4w1TuX9e', "14LmW5k4ssUrtbAB4255zdqv3b4w1TuX9e",
unhexlify('209e23edf0e4e47ff1dec27f32cd78c50e74ef018ee8a6adf35ae17c7a9b0dd96f48b493fd7dbab03efb6f439c6383c9523b3bbc5f1a7d158a6af90ab154e9be80'), unhexlify(
'This is an example of a signed message.') "209e23edf0e4e47ff1dec27f32cd78c50e74ef018ee8a6adf35ae17c7a9b0dd96f48b493fd7dbab03efb6f439c6383c9523b3bbc5f1a7d158a6af90ab154e9be80"
),
"This is an example of a signed message.",
)
def test_signtx(self): def test_signtx(self):
self.setup_mnemonic_pin_passphrase() self.setup_mnemonic_pin_passphrase()
@ -176,30 +199,65 @@ class TestProtectionLevels(TrezorTest):
) )
out1 = proto.TxOutputType( out1 = proto.TxOutputType(
address='1MJ2tj2ThBE62zXbBYA5ZaN3fdve5CPAz1', address="1MJ2tj2ThBE62zXbBYA5ZaN3fdve5CPAz1",
amount=390000 - 10000, amount=390000 - 10000,
script_type=proto.OutputScriptType.PAYTOADDRESS, script_type=proto.OutputScriptType.PAYTOADDRESS,
) )
with self.client: with self.client:
self.client.set_expected_responses([ self.client.set_expected_responses(
proto.PinMatrixRequest(), [
proto.PassphraseRequest(), proto.PinMatrixRequest(),
proto.TxRequest(request_type=proto.RequestType.TXINPUT, details=proto.TxRequestDetailsType(request_index=0)), proto.PassphraseRequest(),
proto.TxRequest(request_type=proto.RequestType.TXMETA, details=proto.TxRequestDetailsType(tx_hash=TXHASH_d5f65e)), proto.TxRequest(
proto.TxRequest(request_type=proto.RequestType.TXINPUT, details=proto.TxRequestDetailsType(request_index=0, tx_hash=TXHASH_d5f65e)), request_type=proto.RequestType.TXINPUT,
proto.TxRequest(request_type=proto.RequestType.TXINPUT, details=proto.TxRequestDetailsType(request_index=1, tx_hash=TXHASH_d5f65e)), details=proto.TxRequestDetailsType(request_index=0),
proto.TxRequest(request_type=proto.RequestType.TXOUTPUT, details=proto.TxRequestDetailsType(request_index=0, tx_hash=TXHASH_d5f65e)), ),
proto.TxRequest(request_type=proto.RequestType.TXOUTPUT, details=proto.TxRequestDetailsType(request_index=0)), proto.TxRequest(
proto.ButtonRequest(code=proto.ButtonRequestType.ConfirmOutput), request_type=proto.RequestType.TXMETA,
proto.ButtonRequest(code=proto.ButtonRequestType.SignTx), details=proto.TxRequestDetailsType(tx_hash=TXHASH_d5f65e),
proto.TxRequest(request_type=proto.RequestType.TXINPUT, details=proto.TxRequestDetailsType(request_index=0)), ),
proto.TxRequest(request_type=proto.RequestType.TXOUTPUT, details=proto.TxRequestDetailsType(request_index=0)), proto.TxRequest(
proto.TxRequest(request_type=proto.RequestType.TXOUTPUT, details=proto.TxRequestDetailsType(request_index=0)), request_type=proto.RequestType.TXINPUT,
proto.TxRequest(request_type=proto.RequestType.TXFINISHED), details=proto.TxRequestDetailsType(
]) request_index=0, tx_hash=TXHASH_d5f65e
btc.sign_tx(self.client, 'Bitcoin', [inp1, ], [out1, ]) ),
),
proto.TxRequest(
request_type=proto.RequestType.TXINPUT,
details=proto.TxRequestDetailsType(
request_index=1, tx_hash=TXHASH_d5f65e
),
),
proto.TxRequest(
request_type=proto.RequestType.TXOUTPUT,
details=proto.TxRequestDetailsType(
request_index=0, tx_hash=TXHASH_d5f65e
),
),
proto.TxRequest(
request_type=proto.RequestType.TXOUTPUT,
details=proto.TxRequestDetailsType(request_index=0),
),
proto.ButtonRequest(code=proto.ButtonRequestType.ConfirmOutput),
proto.ButtonRequest(code=proto.ButtonRequestType.SignTx),
proto.TxRequest(
request_type=proto.RequestType.TXINPUT,
details=proto.TxRequestDetailsType(request_index=0),
),
proto.TxRequest(
request_type=proto.RequestType.TXOUTPUT,
details=proto.TxRequestDetailsType(request_index=0),
),
proto.TxRequest(
request_type=proto.RequestType.TXOUTPUT,
details=proto.TxRequestDetailsType(request_index=0),
),
proto.TxRequest(request_type=proto.RequestType.TXFINISHED),
]
)
btc.sign_tx(self.client, "Bitcoin", [inp1], [out1])
# def test_firmware_erase(self): # def test_firmware_erase(self):
# pass # pass

View File

@ -16,19 +16,20 @@
from binascii import unhexlify from binascii import unhexlify
from trezorlib import btc, messages as proto
from .common import TrezorTest from .common import TrezorTest
from trezorlib import messages as proto
from trezorlib import btc
TXHASH_d5f65e = unhexlify(
TXHASH_d5f65e = unhexlify('d5f65ee80147b4bcc70b75e4bbf2d7382021b871bd8867ef8fa525ef50864882') "d5f65ee80147b4bcc70b75e4bbf2d7382021b871bd8867ef8fa525ef50864882"
)
# address_n = [177] < 68 # address_n = [177] < 68
# address_n = [16518] < 66 # address_n = [16518] < 66
class TestZerosig(TrezorTest): class TestZerosig(TrezorTest):
''' """
def test_mine_zero_signature(self): def test_mine_zero_signature(self):
# tx: d5f65ee80147b4bcc70b75e4bbf2d7382021b871bd8867ef8fa525ef50864882 # tx: d5f65ee80147b4bcc70b75e4bbf2d7382021b871bd8867ef8fa525ef50864882
# input 0: 0.0039 BTC # input 0: 0.0039 BTC
@ -57,7 +58,7 @@ class TestZerosig(TrezorTest):
print("!!!!", n) print("!!!!", n)
print(hexlify(tx.serialized_tx)) print(hexlify(tx.serialized_tx))
return return
''' """
def test_one_zero_signature(self): def test_one_zero_signature(self):
self.setup_mnemonic_nopin_nopassphrase() self.setup_mnemonic_nopin_nopassphrase()
@ -76,7 +77,9 @@ class TestZerosig(TrezorTest):
script_type=proto.OutputScriptType.PAYTOADDRESS, script_type=proto.OutputScriptType.PAYTOADDRESS,
) )
(signatures, serialized_tx) = btc.sign_tx(self.client, 'Bitcoin', [inp1, ], [out1, ]) (signatures, serialized_tx) = btc.sign_tx(
self.client, "Bitcoin", [inp1], [out1]
)
siglen = serialized_tx[44] siglen = serialized_tx[44]
# TREZOR must strip leading zero from signature # TREZOR must strip leading zero from signature
@ -99,7 +102,9 @@ class TestZerosig(TrezorTest):
script_type=proto.OutputScriptType.PAYTOADDRESS, script_type=proto.OutputScriptType.PAYTOADDRESS,
) )
(signatures, serialized_tx) = btc.sign_tx(self.client, 'Bitcoin', [inp1, ], [out1, ]) (signatures, serialized_tx) = btc.sign_tx(
self.client, "Bitcoin", [inp1], [out1]
)
siglen = serialized_tx[44] siglen = serialized_tx[44]
# TREZOR must strip leading zero from signature # TREZOR must strip leading zero from signature

View File

@ -14,17 +14,16 @@
# You should have received a copy of the License along with this library. # You should have received a copy of the License along with this library.
# If not, see <https://www.gnu.org/licenses/lgpl-3.0.html>. # If not, see <https://www.gnu.org/licenses/lgpl-3.0.html>.
import struct
import hmac
import hashlib import hashlib
import hmac
import struct
import ecdsa import ecdsa
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 INFINITY, Point
from ecdsa.util import number_to_string, string_to_number
from trezorlib import tools from trezorlib import messages, tools
from trezorlib import messages
def point_to_pubkey(point): def point_to_pubkey(point):
@ -32,14 +31,14 @@ def point_to_pubkey(point):
x_str = number_to_string(point.x(), order) x_str = number_to_string(point.x(), order)
y_str = number_to_string(point.y(), order) y_str = number_to_string(point.y(), order)
vk = x_str + y_str vk = x_str + y_str
return struct.pack('B', (vk[63] & 1) + 2) + vk[0:32] # To compressed key return struct.pack("B", (vk[63] & 1) + 2) + vk[0:32] # To compressed key
def sec_to_public_pair(pubkey): def sec_to_public_pair(pubkey):
"""Convert a public key in sec binary format to a public pair.""" """Convert a public key in sec binary format to a public pair."""
x = string_to_number(pubkey[1:33]) x = string_to_number(pubkey[1:33])
sec0 = pubkey[:1] sec0 = pubkey[:1]
if sec0 not in (b'\2', b'\3'): if sec0 not in (b"\2", b"\3"):
raise ValueError("Compressed pubkey expected") raise ValueError("Compressed pubkey expected")
def public_pair_for_x(generator, x, is_even): def public_pair_for_x(generator, x, is_even):
@ -51,7 +50,9 @@ def sec_to_public_pair(pubkey):
return (x, p - beta) return (x, p - beta)
return (x, beta) return (x, beta)
return public_pair_for_x(ecdsa.ecdsa.generator_secp256k1, x, is_even=(sec0 == b'\2')) return public_pair_for_x(
ecdsa.ecdsa.generator_secp256k1, x, is_even=(sec0 == b"\2")
)
def is_prime(n): def is_prime(n):
@ -68,7 +69,7 @@ def get_address(public_node, address_type):
def public_ckd(public_node, n): 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 = messages.HDNodeType() node = messages.HDNodeType()
node.CopyFrom(public_node) node.CopyFrom(public_node)
@ -100,7 +101,9 @@ def get_subnode(node, i):
# BIP32 magic converts old public key to new public point # BIP32 magic converts old public key to new public point
x, y = sec_to_public_pair(node.public_key) x, y = sec_to_public_pair(node.public_key)
point = I_left_as_exponent * SECP256k1.generator + Point(SECP256k1.curve, x, y, SECP256k1.order) point = I_left_as_exponent * SECP256k1.generator + Point(
SECP256k1.curve, x, y, SECP256k1.order
)
if point == INFINITY: if point == INFINITY:
raise ValueError("Point cannot be INFINITY") raise ValueError("Point cannot be INFINITY")
@ -112,14 +115,14 @@ def get_subnode(node, i):
def serialize(node, version=0x0488B21E): def serialize(node, version=0x0488B21E):
s = b'' s = b""
s += struct.pack('>I', version) s += struct.pack(">I", version)
s += struct.pack('>B', node.depth) s += struct.pack(">B", node.depth)
s += struct.pack('>I', node.fingerprint) s += struct.pack(">I", node.fingerprint)
s += struct.pack('>I', node.child_num) s += struct.pack(">I", node.child_num)
s += node.chain_code s += node.chain_code
if node.private_key: if node.private_key:
s += b'\x00' + node.private_key s += b"\x00" + node.private_key
else: else:
s += node.public_key s += node.public_key
s += tools.btc_hash(s)[:4] s += tools.btc_hash(s)[:4]
@ -133,9 +136,9 @@ def deserialize(xpub):
raise ValueError("Checksum failed") raise ValueError("Checksum failed")
node = messages.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]
node.chain_code = data[13:45] node.chain_code = data[13:45]
key = data[45:-4] key = data[45:-4]

View File

@ -18,11 +18,17 @@ from ..support import ckd_public
def test_ckd_public(): def test_ckd_public():
xpub1 = 'xpub661MyMwAqRbcEnKbXcCqD2GT1di5zQxVqoHPAgHNe8dv5JP8gWmDproS6kFHJnLZd23tWevhdn4urGJ6b264DfTGKr8zjmYDjyDTi9U7iyT' xpub1 = "xpub661MyMwAqRbcEnKbXcCqD2GT1di5zQxVqoHPAgHNe8dv5JP8gWmDproS6kFHJnLZd23tWevhdn4urGJ6b264DfTGKr8zjmYDjyDTi9U7iyT"
node1 = ckd_public.deserialize(xpub1) node1 = ckd_public.deserialize(xpub1)
node2 = ckd_public.public_ckd(node1, [0]) node2 = ckd_public.public_ckd(node1, [0])
node3 = ckd_public.public_ckd(node1, [0, 0]) node3 = ckd_public.public_ckd(node1, [0, 0])
xpub2 = ckd_public.serialize(node2) xpub2 = ckd_public.serialize(node2)
xpub3 = ckd_public.serialize(node3) xpub3 = ckd_public.serialize(node3)
assert xpub2 == 'xpub67ymn1YTdE2iSGXitxUEZeUdHF2FsejJATroeAxVMtzTAK9o3vjmFLrE7TqE1X76iobkVc3p8h3gNzNRTwPeQGYW3CCmYCG8n5ThVkXaQzs' assert (
assert xpub3 == 'xpub6BD2MwdEg5PJPqiGetL9DJs7oDo6zP3XwAABX2vAQb5eLpY3QhHGUEm25V4nkQhnFMsqEVfTwtax2gKz8EFrt1PnBN6xQjE9jGmWDR6modu' xpub2
== "xpub67ymn1YTdE2iSGXitxUEZeUdHF2FsejJATroeAxVMtzTAK9o3vjmFLrE7TqE1X76iobkVc3p8h3gNzNRTwPeQGYW3CCmYCG8n5ThVkXaQzs"
)
assert (
xpub3
== "xpub6BD2MwdEg5PJPqiGetL9DJs7oDo6zP3XwAABX2vAQb5eLpY3QhHGUEm25V4nkQhnFMsqEVfTwtax2gKz8EFrt1PnBN6xQjE9jGmWDR6modu"
)

View File

@ -16,6 +16,7 @@
import binascii import binascii
import hashlib import hashlib
import pytest import pytest
from trezorlib import cosi from trezorlib import cosi
@ -30,62 +31,91 @@ from trezorlib import cosi
pytestmark = pytest.mark.slow_cosi pytestmark = pytest.mark.slow_cosi
if "slow_cosi" not in pytest.config.getoption("-m"): if "slow_cosi" not in pytest.config.getoption("-m"):
pytestmark = pytest.mark.skip("Skipping slow CoSi tests. 'pytest -m slow_cosi' to run.") pytestmark = pytest.mark.skip(
"Skipping slow CoSi tests. 'pytest -m slow_cosi' to run."
)
RFC8032_VECTORS = ( RFC8032_VECTORS = (
( # test 1 ( # test 1
# privkey # privkey
binascii.unhexlify("9d61b19deffd5a60ba844af492ec2cc44449c5697b326919703bac031cae7f60"), binascii.unhexlify(
"9d61b19deffd5a60ba844af492ec2cc44449c5697b326919703bac031cae7f60"
),
# pubkey # pubkey
binascii.unhexlify("d75a980182b10ab7d54bfed3c964073a0ee172f3daa62325af021a68f707511a"), binascii.unhexlify(
"d75a980182b10ab7d54bfed3c964073a0ee172f3daa62325af021a68f707511a"
),
# message # message
binascii.unhexlify(""), binascii.unhexlify(""),
# signature # signature
binascii.unhexlify("e5564300c360ac729086e2cc806e828a84877f1eb8e5d974d873e06522490155" binascii.unhexlify(
"5fb8821590a33bacc61e39701cf9b46bd25bf5f0595bbe24655141438e7a100b"), "e5564300c360ac729086e2cc806e828a84877f1eb8e5d974d873e06522490155"
"5fb8821590a33bacc61e39701cf9b46bd25bf5f0595bbe24655141438e7a100b"
),
), ),
( # test 2 ( # test 2
# privkey # privkey
binascii.unhexlify("4ccd089b28ff96da9db6c346ec114e0f5b8a319f35aba624da8cf6ed4fb8a6fb"), binascii.unhexlify(
"4ccd089b28ff96da9db6c346ec114e0f5b8a319f35aba624da8cf6ed4fb8a6fb"
),
# pubkey # pubkey
binascii.unhexlify("3d4017c3e843895a92b70aa74d1b7ebc9c982ccf2ec4968cc0cd55f12af4660c"), binascii.unhexlify(
"3d4017c3e843895a92b70aa74d1b7ebc9c982ccf2ec4968cc0cd55f12af4660c"
),
# message # message
binascii.unhexlify("72"), binascii.unhexlify("72"),
# signature # signature
binascii.unhexlify("92a009a9f0d4cab8720e820b5f642540a2b27b5416503f8fb3762223ebdb69da" binascii.unhexlify(
"085ac1e43e15996e458f3613d0f11d8c387b2eaeb4302aeeb00d291612bb0c00"), "92a009a9f0d4cab8720e820b5f642540a2b27b5416503f8fb3762223ebdb69da"
"085ac1e43e15996e458f3613d0f11d8c387b2eaeb4302aeeb00d291612bb0c00"
),
), ),
( # test 3 ( # test 3
# privkey # privkey
binascii.unhexlify("c5aa8df43f9f837bedb7442f31dcb7b166d38535076f094b85ce3a2e0b4458f7"), binascii.unhexlify(
"c5aa8df43f9f837bedb7442f31dcb7b166d38535076f094b85ce3a2e0b4458f7"
),
# pubkey # pubkey
binascii.unhexlify("fc51cd8e6218a1a38da47ed00230f0580816ed13ba3303ac5deb911548908025"), binascii.unhexlify(
"fc51cd8e6218a1a38da47ed00230f0580816ed13ba3303ac5deb911548908025"
),
# message # message
binascii.unhexlify("af82"), binascii.unhexlify("af82"),
# signature # signature
binascii.unhexlify("6291d657deec24024827e69c3abe01a30ce548a284743a445e3680d7db5ac3ac" binascii.unhexlify(
"18ff9b538d16f290ae67f760984dc6594a7c15e9716ed28dc027beceea1ec40a"), "6291d657deec24024827e69c3abe01a30ce548a284743a445e3680d7db5ac3ac"
"18ff9b538d16f290ae67f760984dc6594a7c15e9716ed28dc027beceea1ec40a"
),
), ),
( # test SHA(abc) ( # test SHA(abc)
# privkey # privkey
binascii.unhexlify("833fe62409237b9d62ec77587520911e9a759cec1d19755b7da901b96dca3d42"), binascii.unhexlify(
"833fe62409237b9d62ec77587520911e9a759cec1d19755b7da901b96dca3d42"
),
# pubkey # pubkey
binascii.unhexlify("ec172b93ad5e563bf4932c70e1245034c35467ef2efd4d64ebf819683467e2bf"), binascii.unhexlify(
"ec172b93ad5e563bf4932c70e1245034c35467ef2efd4d64ebf819683467e2bf"
),
# message # message
hashlib.sha512(b"abc").digest(), hashlib.sha512(b"abc").digest(),
# signature # signature
binascii.unhexlify("dc2a4459e7369633a52b1bf277839a00201009a3efbf3ecb69bea2186c26b589" binascii.unhexlify(
"09351fc9ac90b3ecfdfbc7c66431e0303dca179c138ac17ad9bef1177331a704"), "dc2a4459e7369633a52b1bf277839a00201009a3efbf3ecb69bea2186c26b589"
"09351fc9ac90b3ecfdfbc7c66431e0303dca179c138ac17ad9bef1177331a704"
),
), ),
) )
COMBINED_KEY = binascii.unhexlify("283967b1c19ff93d2924cdcba95e586547cafef509ea402963ceefe96ccb44f2") COMBINED_KEY = binascii.unhexlify(
GLOBAL_COMMIT = binascii.unhexlify("75bd5806c6366e0374a1c6e020c53feb0791d6cc07560d27d8c158f886ecf389") "283967b1c19ff93d2924cdcba95e586547cafef509ea402963ceefe96ccb44f2"
)
GLOBAL_COMMIT = binascii.unhexlify(
"75bd5806c6366e0374a1c6e020c53feb0791d6cc07560d27d8c158f886ecf389"
)
@pytest.mark.parametrize("privkey, pubkey, message, signature", @pytest.mark.parametrize("privkey, pubkey, message, signature", RFC8032_VECTORS)
RFC8032_VECTORS)
def test_single_eddsa_vector(privkey, pubkey, message, signature): def test_single_eddsa_vector(privkey, pubkey, message, signature):
my_pubkey = cosi.pubkey_from_privkey(privkey) my_pubkey = cosi.pubkey_from_privkey(privkey)
assert my_pubkey == pubkey assert my_pubkey == pubkey
@ -94,7 +124,7 @@ def test_single_eddsa_vector(privkey, pubkey, message, signature):
except ValueError: except ValueError:
pytest.fail("Signature does not verify.") pytest.fail("Signature does not verify.")
fake_signature = b'\xf1' + signature[1:] fake_signature = b"\xf1" + signature[1:]
with pytest.raises(ValueError): with pytest.raises(ValueError):
cosi.verify(fake_signature, message, pubkey) cosi.verify(fake_signature, message, pubkey)
@ -103,17 +133,14 @@ def test_combine_keys():
pubkeys = [pubkey for _, pubkey, _, _ in RFC8032_VECTORS] pubkeys = [pubkey for _, pubkey, _, _ in RFC8032_VECTORS]
assert cosi.combine_keys(pubkeys) == COMBINED_KEY assert cosi.combine_keys(pubkeys) == COMBINED_KEY
Rs = [cosi.get_nonce(privkey, message)[1] for privkey, _, message, _ in RFC8032_VECTORS] Rs = [
cosi.get_nonce(privkey, message)[1]
for privkey, _, message, _ in RFC8032_VECTORS
]
assert cosi.combine_keys(Rs) == GLOBAL_COMMIT assert cosi.combine_keys(Rs) == GLOBAL_COMMIT
@pytest.mark.parametrize("keyset", [ @pytest.mark.parametrize("keyset", [(0,), (0, 1), (0, 1, 2), (0, 1, 2, 3), (1, 3)])
(0,),
(0, 1),
(0, 1, 2),
(0, 1, 2, 3),
(1, 3),
])
def test_cosi_combination(keyset): def test_cosi_combination(keyset):
message = hashlib.sha512(b"You all have to sign this.").digest() message = hashlib.sha512(b"You all have to sign this.").digest()
selection = [RFC8032_VECTORS[i] for i in keyset] selection = [RFC8032_VECTORS[i] for i in keyset]
@ -128,8 +155,10 @@ def test_cosi_combination(keyset):
global_commit = cosi.combine_keys(commits) global_commit = cosi.combine_keys(commits)
# generate individual signatures # generate individual signatures
signatures = [cosi.sign_with_privkey(message, privkey, global_pk, nonce, global_commit) signatures = [
for privkey, nonce in zip(privkeys, nonces)] cosi.sign_with_privkey(message, privkey, global_pk, nonce, global_commit)
for privkey, nonce in zip(privkeys, nonces)
]
# combine signatures # combine signatures
global_sig = cosi.combine_sig(global_commit, signatures) global_sig = cosi.combine_sig(global_commit, signatures)

View File

@ -15,6 +15,7 @@
# If not, see <https://www.gnu.org/licenses/lgpl-3.0.html>. # If not, see <https://www.gnu.org/licenses/lgpl-3.0.html>.
import binascii import binascii
from trezorlib import nem from trezorlib import nem
@ -27,18 +28,9 @@ def test_nem_basic():
"type": nem.TYPE_TRANSACTION_TRANSFER, "type": nem.TYPE_TRANSACTION_TRANSFER,
"deadline": 76895615, "deadline": 76895615,
"version": (0x98 << 24), "version": (0x98 << 24),
"message": { "message": {"payload": binascii.hexlify(b"hello world"), "type": 1},
"payload": binascii.hexlify(b'hello world'),
"type": 1,
},
"mosaics": [ "mosaics": [
{ {"mosaicId": {"namespaceId": "nem", "name": "xem"}, "quantity": 1000000}
"mosaicId": {
"namespaceId": "nem",
"name": "xem",
},
"quantity": 1000000,
},
], ],
} }

View File

@ -15,6 +15,7 @@
# If not, see <https://www.gnu.org/licenses/lgpl-3.0.html>. # If not, see <https://www.gnu.org/licenses/lgpl-3.0.html>.
from io import BytesIO from io import BytesIO
import pytest import pytest
from trezorlib import protobuf from trezorlib import protobuf
@ -42,20 +43,20 @@ def dump_uvarint(value):
def test_dump_uvarint(): def test_dump_uvarint():
assert dump_uvarint(0) == b'\x00' assert dump_uvarint(0) == b"\x00"
assert dump_uvarint(1) == b'\x01' assert dump_uvarint(1) == b"\x01"
assert dump_uvarint(0xff) == b'\xff\x01' assert dump_uvarint(0xff) == b"\xff\x01"
assert dump_uvarint(123456) == b'\xc0\xc4\x07' assert dump_uvarint(123456) == b"\xc0\xc4\x07"
with pytest.raises(ValueError): with pytest.raises(ValueError):
dump_uvarint(-1) dump_uvarint(-1)
def test_load_uvarint(): def test_load_uvarint():
assert load_uvarint(b'\x00') == 0 assert load_uvarint(b"\x00") == 0
assert load_uvarint(b'\x01') == 1 assert load_uvarint(b"\x01") == 1
assert load_uvarint(b'\xff\x01') == 0xff assert load_uvarint(b"\xff\x01") == 0xff
assert load_uvarint(b'\xc0\xc4\x07') == 123456 assert load_uvarint(b"\xc0\xc4\x07") == 123456
def test_sint_uint(): def test_sint_uint():
@ -75,12 +76,8 @@ def test_sint_uint():
assert protobuf.uint_to_sint(2) == 1 assert protobuf.uint_to_sint(2) == 1
# roundtrip: # roundtrip:
assert protobuf.uint_to_sint( assert protobuf.uint_to_sint(protobuf.sint_to_uint(1234567891011)) == 1234567891011
protobuf.sint_to_uint(1234567891011) assert protobuf.uint_to_sint(protobuf.sint_to_uint(-2 ** 32)) == -2 ** 32
) == 1234567891011
assert protobuf.uint_to_sint(
protobuf.sint_to_uint(- 2 ** 32)
) == - 2 ** 32
def test_simple_message(): def test_simple_message():
@ -88,7 +85,7 @@ def test_simple_message():
uvarint=12345678910, uvarint=12345678910,
svarint=-12345678910, svarint=-12345678910,
bool=True, bool=True,
bytes=b'\xDE\xAD\xCA\xFE', bytes=b"\xDE\xAD\xCA\xFE",
unicode="Příliš žluťoučký kůň úpěl ďábelské ódy 😊", unicode="Příliš žluťoučký kůň úpěl ďábelské ódy 😊",
) )
@ -102,5 +99,5 @@ def test_simple_message():
assert retr.uvarint == 12345678910 assert retr.uvarint == 12345678910
assert retr.svarint == -12345678910 assert retr.svarint == -12345678910
assert retr.bool is True assert retr.bool is True
assert retr.bytes == b'\xDE\xAD\xCA\xFE' assert retr.bytes == b"\xDE\xAD\xCA\xFE"
assert retr.unicode == "Příliš žluťoučký kůň úpěl ďábelské ódy 😊" assert retr.unicode == "Příliš žluťoučký kůň úpěl ďábelské ódy 😊"

View File

@ -15,16 +15,18 @@
# If not, see <https://www.gnu.org/licenses/lgpl-3.0.html>. # If not, see <https://www.gnu.org/licenses/lgpl-3.0.html>.
import base64 import base64
from trezorlib import stellar
from trezorlib import messages from trezorlib import messages, stellar
def test_stellar_parse_transaction_bytes_simple(): def test_stellar_parse_transaction_bytes_simple():
b64 = b'AAAAABXWSL/k028ZbPtXNf/YylTNS4Iz90PyJEnefPMBzbRpAAAAZAAAAAEAAAAAAAAAAAAAAAAAAAABAAAAAAAAAAAAAAAAXVVkJGaxhbhDFS6eIZFR28WJICfsQBAaUXvtXKAwwuAAAAAAO5/eyAAAAAA=' b64 = b"AAAAABXWSL/k028ZbPtXNf/YylTNS4Iz90PyJEnefPMBzbRpAAAAZAAAAAEAAAAAAAAAAAAAAAAAAAABAAAAAAAAAAAAAAAAXVVkJGaxhbhDFS6eIZFR28WJICfsQBAaUXvtXKAwwuAAAAAAO5/eyAAAAAA="
tx, operations = stellar.parse_transaction_bytes(base64.b64decode(b64)) tx, operations = stellar.parse_transaction_bytes(base64.b64decode(b64))
assert tx.source_account == 'GAK5MSF74TJW6GLM7NLTL76YZJKM2S4CGP3UH4REJHPHZ4YBZW2GSBPW' assert (
tx.source_account == "GAK5MSF74TJW6GLM7NLTL76YZJKM2S4CGP3UH4REJHPHZ4YBZW2GSBPW"
)
assert tx.fee == 100 assert tx.fee == 100
assert tx.sequence_number == 4294967296 assert tx.sequence_number == 4294967296
assert tx.timebounds_start is None assert tx.timebounds_start is None
@ -37,28 +39,32 @@ def test_stellar_parse_transaction_bytes_simple():
def test_stellar_parse_transaction_bytes_memo_text(): def test_stellar_parse_transaction_bytes_memo_text():
b64 = b'AAAAABXWSL/k028ZbPtXNf/YylTNS4Iz90PyJEnefPMBzbRpAAAAZAAAAAEAAAAAAAAAAAAAAAEAAAAMZXhhbXBsZSBtZW1vAAAAAQAAAAAAAAAAAAAAAF1VZCRmsYW4QxUuniGRUdvFiSAn7EAQGlF77VygMMLgAAAAADuf3sgAAAAA' b64 = b"AAAAABXWSL/k028ZbPtXNf/YylTNS4Iz90PyJEnefPMBzbRpAAAAZAAAAAEAAAAAAAAAAAAAAAEAAAAMZXhhbXBsZSBtZW1vAAAAAQAAAAAAAAAAAAAAAF1VZCRmsYW4QxUuniGRUdvFiSAn7EAQGlF77VygMMLgAAAAADuf3sgAAAAA"
tx, operations = stellar.parse_transaction_bytes(base64.b64decode(b64)) tx, operations = stellar.parse_transaction_bytes(base64.b64decode(b64))
assert tx.source_account == 'GAK5MSF74TJW6GLM7NLTL76YZJKM2S4CGP3UH4REJHPHZ4YBZW2GSBPW' assert (
tx.source_account == "GAK5MSF74TJW6GLM7NLTL76YZJKM2S4CGP3UH4REJHPHZ4YBZW2GSBPW"
)
assert tx.fee == 100 assert tx.fee == 100
assert tx.sequence_number == 4294967296 assert tx.sequence_number == 4294967296
assert tx.timebounds_start is None assert tx.timebounds_start is None
assert tx.timebounds_end is None assert tx.timebounds_end is None
assert tx.memo_type == stellar.MEMO_TYPE_TEXT assert tx.memo_type == stellar.MEMO_TYPE_TEXT
assert tx.memo_text == b'example memo' assert tx.memo_text == b"example memo"
assert tx.memo_id is None assert tx.memo_id is None
assert tx.memo_hash is None assert tx.memo_hash is None
assert tx.num_operations == len(operations) assert tx.num_operations == len(operations)
def test_stellar_parse_transaction_bytes_memo_id(): def test_stellar_parse_transaction_bytes_memo_id():
b64 = b'AAAAABXWSL/k028ZbPtXNf/YylTNS4Iz90PyJEnefPMBzbRpAAAAZAAAAAEAAAAAAAAAAAAAAAIAAAAAB1vNFQAAAAEAAAAAAAAAAAAAAABdVWQkZrGFuEMVLp4hkVHbxYkgJ+xAEBpRe+1coDDC4AAAAAA7n97IAAAAAA==' b64 = b"AAAAABXWSL/k028ZbPtXNf/YylTNS4Iz90PyJEnefPMBzbRpAAAAZAAAAAEAAAAAAAAAAAAAAAIAAAAAB1vNFQAAAAEAAAAAAAAAAAAAAABdVWQkZrGFuEMVLp4hkVHbxYkgJ+xAEBpRe+1coDDC4AAAAAA7n97IAAAAAA=="
tx, operations = stellar.parse_transaction_bytes(base64.b64decode(b64)) tx, operations = stellar.parse_transaction_bytes(base64.b64decode(b64))
assert tx.source_account == 'GAK5MSF74TJW6GLM7NLTL76YZJKM2S4CGP3UH4REJHPHZ4YBZW2GSBPW' assert (
tx.source_account == "GAK5MSF74TJW6GLM7NLTL76YZJKM2S4CGP3UH4REJHPHZ4YBZW2GSBPW"
)
assert tx.fee == 100 assert tx.fee == 100
assert tx.sequence_number == 4294967296 assert tx.sequence_number == 4294967296
assert tx.timebounds_start is None assert tx.timebounds_start is None
@ -71,11 +77,13 @@ def test_stellar_parse_transaction_bytes_memo_id():
def test_stellar_parse_transaction_bytes_memo_hash(): def test_stellar_parse_transaction_bytes_memo_hash():
b64 = b'AAAAABXWSL/k028ZbPtXNf/YylTNS4Iz90PyJEnefPMBzbRpAAAAZAAAAAEAAAAAAAAAAAAAAAMjLtb5+r8U47tVOSsYz+PQ/ryU0gzGMnw4odB11uoRjAAAAAEAAAAAAAAAAAAAAABdVWQkZrGFuEMVLp4hkVHbxYkgJ+xAEBpRe+1coDDC4AAAAAA7n97IAAAAAA==' b64 = b"AAAAABXWSL/k028ZbPtXNf/YylTNS4Iz90PyJEnefPMBzbRpAAAAZAAAAAEAAAAAAAAAAAAAAAMjLtb5+r8U47tVOSsYz+PQ/ryU0gzGMnw4odB11uoRjAAAAAEAAAAAAAAAAAAAAABdVWQkZrGFuEMVLp4hkVHbxYkgJ+xAEBpRe+1coDDC4AAAAAA7n97IAAAAAA=="
tx, operations = stellar.parse_transaction_bytes(base64.b64decode(b64)) tx, operations = stellar.parse_transaction_bytes(base64.b64decode(b64))
assert tx.source_account == 'GAK5MSF74TJW6GLM7NLTL76YZJKM2S4CGP3UH4REJHPHZ4YBZW2GSBPW' assert (
tx.source_account == "GAK5MSF74TJW6GLM7NLTL76YZJKM2S4CGP3UH4REJHPHZ4YBZW2GSBPW"
)
assert tx.fee == 100 assert tx.fee == 100
assert tx.sequence_number == 4294967296 assert tx.sequence_number == 4294967296
assert tx.timebounds_start is None assert tx.timebounds_start is None
@ -84,16 +92,21 @@ def test_stellar_parse_transaction_bytes_memo_hash():
assert tx.memo_text is None assert tx.memo_text is None
assert tx.memo_id is None assert tx.memo_id is None
# base-64 encoding of the raw bytes of sha256('stellar') # base-64 encoding of the raw bytes of sha256('stellar')
assert base64.b64encode(tx.memo_hash) == b'Iy7W+fq/FOO7VTkrGM/j0P68lNIMxjJ8OKHQddbqEYw=' assert (
base64.b64encode(tx.memo_hash)
== b"Iy7W+fq/FOO7VTkrGM/j0P68lNIMxjJ8OKHQddbqEYw="
)
assert tx.num_operations == len(operations) assert tx.num_operations == len(operations)
def test_stellar_parse_transaction_bytes_memo_return(): def test_stellar_parse_transaction_bytes_memo_return():
b64 = b'AAAAABXWSL/k028ZbPtXNf/YylTNS4Iz90PyJEnefPMBzbRpAAAAZAAAAAEAAAAAAAAAAAAAAAQjLtb5+r8U47tVOSsYz+PQ/ryU0gzGMnw4odB11uoRjAAAAAEAAAAAAAAAAAAAAABdVWQkZrGFuEMVLp4hkVHbxYkgJ+xAEBpRe+1coDDC4AAAAAA7n97IAAAAAA==' b64 = b"AAAAABXWSL/k028ZbPtXNf/YylTNS4Iz90PyJEnefPMBzbRpAAAAZAAAAAEAAAAAAAAAAAAAAAQjLtb5+r8U47tVOSsYz+PQ/ryU0gzGMnw4odB11uoRjAAAAAEAAAAAAAAAAAAAAABdVWQkZrGFuEMVLp4hkVHbxYkgJ+xAEBpRe+1coDDC4AAAAAA7n97IAAAAAA=="
tx, operations = stellar.parse_transaction_bytes(base64.b64decode(b64)) tx, operations = stellar.parse_transaction_bytes(base64.b64decode(b64))
assert tx.source_account == 'GAK5MSF74TJW6GLM7NLTL76YZJKM2S4CGP3UH4REJHPHZ4YBZW2GSBPW' assert (
tx.source_account == "GAK5MSF74TJW6GLM7NLTL76YZJKM2S4CGP3UH4REJHPHZ4YBZW2GSBPW"
)
assert tx.fee == 100 assert tx.fee == 100
assert tx.sequence_number == 4294967296 assert tx.sequence_number == 4294967296
assert tx.timebounds_start is None assert tx.timebounds_start is None
@ -102,115 +115,147 @@ def test_stellar_parse_transaction_bytes_memo_return():
assert tx.memo_text is None assert tx.memo_text is None
assert tx.memo_id is None assert tx.memo_id is None
# base-64 encoding of the raw bytes of sha256('stellar') # base-64 encoding of the raw bytes of sha256('stellar')
assert base64.b64encode(tx.memo_hash) == b'Iy7W+fq/FOO7VTkrGM/j0P68lNIMxjJ8OKHQddbqEYw=' assert (
base64.b64encode(tx.memo_hash)
== b"Iy7W+fq/FOO7VTkrGM/j0P68lNIMxjJ8OKHQddbqEYw="
)
assert tx.num_operations == len(operations) assert tx.num_operations == len(operations)
def test_stellar_parse_operation_bytes_create_account_simple(): def test_stellar_parse_operation_bytes_create_account_simple():
b64 = b'AAAAABXWSL/k028ZbPtXNf/YylTNS4Iz90PyJEnefPMBzbRpAAAAZAAAAAEAAAAAAAAAAAAAAAAAAAABAAAAAAAAAAAAAAAAXVVkJGaxhbhDFS6eIZFR28WJICfsQBAaUXvtXKAwwuAAAAAAO5/eyAAAAAA=' b64 = b"AAAAABXWSL/k028ZbPtXNf/YylTNS4Iz90PyJEnefPMBzbRpAAAAZAAAAAEAAAAAAAAAAAAAAAAAAAABAAAAAAAAAAAAAAAAXVVkJGaxhbhDFS6eIZFR28WJICfsQBAaUXvtXKAwwuAAAAAAO5/eyAAAAAA="
tx, operations = stellar.parse_transaction_bytes(base64.b64decode(b64)) tx, operations = stellar.parse_transaction_bytes(base64.b64decode(b64))
op = operations[0] op = operations[0]
assert isinstance(op, messages.StellarCreateAccountOp) assert isinstance(op, messages.StellarCreateAccountOp)
assert op.source_account is None assert op.source_account is None
assert op.new_account == 'GBOVKZBEM2YYLOCDCUXJ4IMRKHN4LCJAE7WEAEA2KF562XFAGDBOB64V' assert op.new_account == "GBOVKZBEM2YYLOCDCUXJ4IMRKHN4LCJAE7WEAEA2KF562XFAGDBOB64V"
assert op.starting_balance == 1000333000 assert op.starting_balance == 1000333000
def test_stellar_parse_operation_bytes_payment_native(): def test_stellar_parse_operation_bytes_payment_native():
b64 = b'AAAAABXWSL/k028ZbPtXNf/YylTNS4Iz90PyJEnefPMBzbRpAAAAZAAAAAEAAAAAAAAAAAAAAAAAAAABAAAAAAAAAAEAAAAAXVVkJGaxhbhDFS6eIZFR28WJICfsQBAaUXvtXKAwwuAAAAAAAAAAAB3PFpgAAAAA' b64 = b"AAAAABXWSL/k028ZbPtXNf/YylTNS4Iz90PyJEnefPMBzbRpAAAAZAAAAAEAAAAAAAAAAAAAAAAAAAABAAAAAAAAAAEAAAAAXVVkJGaxhbhDFS6eIZFR28WJICfsQBAaUXvtXKAwwuAAAAAAAAAAAB3PFpgAAAAA"
tx, operations = stellar.parse_transaction_bytes(base64.b64decode(b64)) tx, operations = stellar.parse_transaction_bytes(base64.b64decode(b64))
op = operations[0] op = operations[0]
assert isinstance(op, messages.StellarPaymentOp) assert isinstance(op, messages.StellarPaymentOp)
assert op.source_account is None assert op.source_account is None
assert op.destination_account == 'GBOVKZBEM2YYLOCDCUXJ4IMRKHN4LCJAE7WEAEA2KF562XFAGDBOB64V' assert (
op.destination_account
== "GBOVKZBEM2YYLOCDCUXJ4IMRKHN4LCJAE7WEAEA2KF562XFAGDBOB64V"
)
assert op.asset.type == stellar.ASSET_TYPE_NATIVE assert op.asset.type == stellar.ASSET_TYPE_NATIVE
assert op.amount == 500111000 assert op.amount == 500111000
def test_stellar_parse_operation_bytes_payment_custom4(): def test_stellar_parse_operation_bytes_payment_custom4():
b64 = b'AAAAABXWSL/k028ZbPtXNf/YylTNS4Iz90PyJEnefPMBzbRpAAAAZAAAAAEAAAAAAAAAAAAAAAAAAAABAAAAAAAAAAEAAAAAXVVkJGaxhbhDFS6eIZFR28WJICfsQBAaUXvtXKAwwuAAAAABVEVTVAAAAAAphJYCwg5YNl8SPBLYehykVQ0QzSGwrg4Y1E4+Vv1qFQAAAAAdzxaYAAAAAA==' b64 = b"AAAAABXWSL/k028ZbPtXNf/YylTNS4Iz90PyJEnefPMBzbRpAAAAZAAAAAEAAAAAAAAAAAAAAAAAAAABAAAAAAAAAAEAAAAAXVVkJGaxhbhDFS6eIZFR28WJICfsQBAaUXvtXKAwwuAAAAABVEVTVAAAAAAphJYCwg5YNl8SPBLYehykVQ0QzSGwrg4Y1E4+Vv1qFQAAAAAdzxaYAAAAAA=="
tx, operations = stellar.parse_transaction_bytes(base64.b64decode(b64)) tx, operations = stellar.parse_transaction_bytes(base64.b64decode(b64))
op = operations[0] op = operations[0]
assert op.source_account is None assert op.source_account is None
assert op.destination_account == 'GBOVKZBEM2YYLOCDCUXJ4IMRKHN4LCJAE7WEAEA2KF562XFAGDBOB64V' assert (
op.destination_account
== "GBOVKZBEM2YYLOCDCUXJ4IMRKHN4LCJAE7WEAEA2KF562XFAGDBOB64V"
)
assert op.asset.type == stellar.ASSET_TYPE_ALPHA4 assert op.asset.type == stellar.ASSET_TYPE_ALPHA4
assert op.asset.code == b'TEST' assert op.asset.code == b"TEST"
assert op.asset.issuer == 'GAUYJFQCYIHFQNS7CI6BFWD2DSSFKDIQZUQ3BLQODDKE4PSW7VVBKENC' assert op.asset.issuer == "GAUYJFQCYIHFQNS7CI6BFWD2DSSFKDIQZUQ3BLQODDKE4PSW7VVBKENC"
assert op.amount == 500111000 assert op.amount == 500111000
def test_stellar_parse_operation_bytes_payment_custom7(): def test_stellar_parse_operation_bytes_payment_custom7():
b64 = b'AAAAABXWSL/k028ZbPtXNf/YylTNS4Iz90PyJEnefPMBzbRpAAAAZAAAAAEAAAAAAAAAAAAAAAAAAAABAAAAAAAAAAEAAAAAXVVkJGaxhbhDFS6eIZFR28WJICfsQBAaUXvtXKAwwuAAAAACU0VWRU5YWAAAAAAAAAAAACmElgLCDlg2XxI8Eth6HKRVDRDNIbCuDhjUTj5W/WoVAAAAAB3PFpgAAAAA' b64 = b"AAAAABXWSL/k028ZbPtXNf/YylTNS4Iz90PyJEnefPMBzbRpAAAAZAAAAAEAAAAAAAAAAAAAAAAAAAABAAAAAAAAAAEAAAAAXVVkJGaxhbhDFS6eIZFR28WJICfsQBAaUXvtXKAwwuAAAAACU0VWRU5YWAAAAAAAAAAAACmElgLCDlg2XxI8Eth6HKRVDRDNIbCuDhjUTj5W/WoVAAAAAB3PFpgAAAAA"
tx, operations = stellar.parse_transaction_bytes(base64.b64decode(b64)) tx, operations = stellar.parse_transaction_bytes(base64.b64decode(b64))
op = operations[0] op = operations[0]
assert isinstance(op, messages.StellarPaymentOp) assert isinstance(op, messages.StellarPaymentOp)
assert op.source_account is None assert op.source_account is None
assert op.destination_account == 'GBOVKZBEM2YYLOCDCUXJ4IMRKHN4LCJAE7WEAEA2KF562XFAGDBOB64V' assert (
op.destination_account
== "GBOVKZBEM2YYLOCDCUXJ4IMRKHN4LCJAE7WEAEA2KF562XFAGDBOB64V"
)
assert op.asset.type == stellar.ASSET_TYPE_ALPHA12 assert op.asset.type == stellar.ASSET_TYPE_ALPHA12
# asset codes are either 4 or 12 characters, so this will be null-padded at the end # asset codes are either 4 or 12 characters, so this will be null-padded at the end
assert op.asset.code == b'SEVENXX\x00\x00\x00\x00\x00' assert op.asset.code == b"SEVENXX\x00\x00\x00\x00\x00"
assert op.asset.issuer == 'GAUYJFQCYIHFQNS7CI6BFWD2DSSFKDIQZUQ3BLQODDKE4PSW7VVBKENC' assert op.asset.issuer == "GAUYJFQCYIHFQNS7CI6BFWD2DSSFKDIQZUQ3BLQODDKE4PSW7VVBKENC"
assert op.amount == 500111000 assert op.amount == 500111000
def test_stellar_parse_operation_bytes_path_payment_none(): def test_stellar_parse_operation_bytes_path_payment_none():
b64 = b'AAAAABXWSL/k028ZbPtXNf/YylTNS4Iz90PyJEnefPMBzbRpAAAAZAAAAAEAAAAAAAAAAAAAAAAAAAABAAAAAAAAAAIAAAAAAAAAAHfOKn8AAAAAXVVkJGaxhbhDFS6eIZFR28WJICfsQBAaUXvtXKAwwuAAAAABSlBZAAAAAADE+xa3Eb3cy85WSdqgwnUtC6UDwrC41YDANuCqe8vGxgAAAAAL68IBAAAAAAAAAAA=' b64 = b"AAAAABXWSL/k028ZbPtXNf/YylTNS4Iz90PyJEnefPMBzbRpAAAAZAAAAAEAAAAAAAAAAAAAAAAAAAABAAAAAAAAAAIAAAAAAAAAAHfOKn8AAAAAXVVkJGaxhbhDFS6eIZFR28WJICfsQBAaUXvtXKAwwuAAAAABSlBZAAAAAADE+xa3Eb3cy85WSdqgwnUtC6UDwrC41YDANuCqe8vGxgAAAAAL68IBAAAAAAAAAAA="
tx, operations = stellar.parse_transaction_bytes(base64.b64decode(b64)) tx, operations = stellar.parse_transaction_bytes(base64.b64decode(b64))
op = operations[0] op = operations[0]
assert isinstance(op, messages.StellarPathPaymentOp) assert isinstance(op, messages.StellarPathPaymentOp)
assert op.source_account is None assert op.source_account is None
assert op.destination_account == 'GBOVKZBEM2YYLOCDCUXJ4IMRKHN4LCJAE7WEAEA2KF562XFAGDBOB64V' assert (
op.destination_account
== "GBOVKZBEM2YYLOCDCUXJ4IMRKHN4LCJAE7WEAEA2KF562XFAGDBOB64V"
)
assert op.send_asset.type == stellar.ASSET_TYPE_NATIVE assert op.send_asset.type == stellar.ASSET_TYPE_NATIVE
assert op.send_max == 2009999999 assert op.send_max == 2009999999
assert op.destination_account == 'GBOVKZBEM2YYLOCDCUXJ4IMRKHN4LCJAE7WEAEA2KF562XFAGDBOB64V' assert (
op.destination_account
== "GBOVKZBEM2YYLOCDCUXJ4IMRKHN4LCJAE7WEAEA2KF562XFAGDBOB64V"
)
assert op.destination_asset.type == stellar.ASSET_TYPE_ALPHA4 assert op.destination_asset.type == stellar.ASSET_TYPE_ALPHA4
# asset codes are either 4 or 12 characters, so this will be null-padded at the end # asset codes are either 4 or 12 characters, so this will be null-padded at the end
assert op.destination_asset.code == b'JPY\x00' assert op.destination_asset.code == b"JPY\x00"
assert op.destination_asset.issuer == 'GDCPWFVXCG65ZS6OKZE5VIGCOUWQXJIDYKYLRVMAYA3OBKT3ZPDMNTIJ' assert (
op.destination_asset.issuer
== "GDCPWFVXCG65ZS6OKZE5VIGCOUWQXJIDYKYLRVMAYA3OBKT3ZPDMNTIJ"
)
assert len(op.paths) == 0 assert len(op.paths) == 0
def test_stellar_parse_operation_bytes_path_payment_one(): def test_stellar_parse_operation_bytes_path_payment_one():
b64 = b'AAAAABXWSL/k028ZbPtXNf/YylTNS4Iz90PyJEnefPMBzbRpAAAAZAAAAAEAAAAAAAAAAAAAAAAAAAABAAAAAAAAAAIAAAAAAAAAAHfOKn8AAAAAXVVkJGaxhbhDFS6eIZFR28WJICfsQBAaUXvtXKAwwuAAAAABSlBZAAAAAADE+xa3Eb3cy85WSdqgwnUtC6UDwrC41YDANuCqe8vGxgAAAAAL68IBAAAAAQAAAAFQVEgxAAAAAMz/d9fJ3rFifblw3jT7sRZv/Ja+fqLfob//aLZQRQibAAAAAA==' b64 = b"AAAAABXWSL/k028ZbPtXNf/YylTNS4Iz90PyJEnefPMBzbRpAAAAZAAAAAEAAAAAAAAAAAAAAAAAAAABAAAAAAAAAAIAAAAAAAAAAHfOKn8AAAAAXVVkJGaxhbhDFS6eIZFR28WJICfsQBAaUXvtXKAwwuAAAAABSlBZAAAAAADE+xa3Eb3cy85WSdqgwnUtC6UDwrC41YDANuCqe8vGxgAAAAAL68IBAAAAAQAAAAFQVEgxAAAAAMz/d9fJ3rFifblw3jT7sRZv/Ja+fqLfob//aLZQRQibAAAAAA=="
tx, operations = stellar.parse_transaction_bytes(base64.b64decode(b64)) tx, operations = stellar.parse_transaction_bytes(base64.b64decode(b64))
op = operations[0] op = operations[0]
assert isinstance(op, messages.StellarPathPaymentOp) assert isinstance(op, messages.StellarPathPaymentOp)
assert op.source_account is None assert op.source_account is None
assert op.destination_account == 'GBOVKZBEM2YYLOCDCUXJ4IMRKHN4LCJAE7WEAEA2KF562XFAGDBOB64V' assert (
op.destination_account
== "GBOVKZBEM2YYLOCDCUXJ4IMRKHN4LCJAE7WEAEA2KF562XFAGDBOB64V"
)
assert op.send_asset.type == stellar.ASSET_TYPE_NATIVE assert op.send_asset.type == stellar.ASSET_TYPE_NATIVE
assert op.send_max == 2009999999 assert op.send_max == 2009999999
assert op.destination_account == 'GBOVKZBEM2YYLOCDCUXJ4IMRKHN4LCJAE7WEAEA2KF562XFAGDBOB64V' assert (
op.destination_account
== "GBOVKZBEM2YYLOCDCUXJ4IMRKHN4LCJAE7WEAEA2KF562XFAGDBOB64V"
)
assert op.destination_asset.type == stellar.ASSET_TYPE_ALPHA4 assert op.destination_asset.type == stellar.ASSET_TYPE_ALPHA4
# asset codes are either 4 or 12 characters, so this will be null-padded at the end # asset codes are either 4 or 12 characters, so this will be null-padded at the end
assert op.destination_asset.code == b'JPY\x00' assert op.destination_asset.code == b"JPY\x00"
assert op.destination_asset.issuer == 'GDCPWFVXCG65ZS6OKZE5VIGCOUWQXJIDYKYLRVMAYA3OBKT3ZPDMNTIJ' assert (
op.destination_asset.issuer
== "GDCPWFVXCG65ZS6OKZE5VIGCOUWQXJIDYKYLRVMAYA3OBKT3ZPDMNTIJ"
)
assert op.destination_amount == 200000001 assert op.destination_amount == 200000001
assert len(op.paths) == 1 assert len(op.paths) == 1
assert op.paths[0].type == stellar.ASSET_TYPE_ALPHA4 assert op.paths[0].type == stellar.ASSET_TYPE_ALPHA4
assert op.paths[0].code == b'PTH1' assert op.paths[0].code == b"PTH1"
assert op.paths[0].issuer == 'GDGP656XZHPLCYT5XFYN4NH3WELG77EWXZ7KFX5BX77WRNSQIUEJXAJK' assert (
op.paths[0].issuer == "GDGP656XZHPLCYT5XFYN4NH3WELG77EWXZ7KFX5BX77WRNSQIUEJXAJK"
)
def test_stellar_parse_operation_bytes_manage_offer_new(): def test_stellar_parse_operation_bytes_manage_offer_new():
b64 = b'AAAAABXWSL/k028ZbPtXNf/YylTNS4Iz90PyJEnefPMBzbRpAAAAZAAAAAEAAAAAAAAAAAAAAAAAAAABAAAAAAAAAAMAAAAAAAAAAVVTRAAAAAAABkAD8fq0d+bofA1LCatUL0dCTJexnyYYd4Y1ghnNUXMAAAAAdzWUAAAKSzYAD0JAAAAAAAAAAAAAAAAA' b64 = b"AAAAABXWSL/k028ZbPtXNf/YylTNS4Iz90PyJEnefPMBzbRpAAAAZAAAAAEAAAAAAAAAAAAAAAAAAAABAAAAAAAAAAMAAAAAAAAAAVVTRAAAAAAABkAD8fq0d+bofA1LCatUL0dCTJexnyYYd4Y1ghnNUXMAAAAAdzWUAAAKSzYAD0JAAAAAAAAAAAAAAAAA"
tx, operations = stellar.parse_transaction_bytes(base64.b64decode(b64)) tx, operations = stellar.parse_transaction_bytes(base64.b64decode(b64))
op = operations[0] op = operations[0]
@ -222,8 +267,11 @@ def test_stellar_parse_operation_bytes_manage_offer_new():
assert op.buying_asset.type == stellar.ASSET_TYPE_ALPHA4 assert op.buying_asset.type == stellar.ASSET_TYPE_ALPHA4
# asset codes are either 4 or 12 characters, so this will be null-padded at the end # asset codes are either 4 or 12 characters, so this will be null-padded at the end
assert op.buying_asset.code == b'USD\x00' assert op.buying_asset.code == b"USD\x00"
assert op.buying_asset.issuer == 'GADEAA7R7K2HPZXIPQGUWCNLKQXUOQSMS6YZ6JQYO6DDLAQZZVIXG74A' assert (
op.buying_asset.issuer
== "GADEAA7R7K2HPZXIPQGUWCNLKQXUOQSMS6YZ6JQYO6DDLAQZZVIXG74A"
)
assert op.amount == 2000000000 assert op.amount == 2000000000
assert op.price_n == 674614 assert op.price_n == 674614
@ -232,7 +280,7 @@ def test_stellar_parse_operation_bytes_manage_offer_new():
def test_stellar_parse_operation_bytes_passive_offer_new(): def test_stellar_parse_operation_bytes_passive_offer_new():
b64 = b'AAAAABXWSL/k028ZbPtXNf/YylTNS4Iz90PyJEnefPMBzbRpAAAAZAAAAAEAAAAAAAAAAAAAAAAAAAABAAAAAAAAAAQAAAAAAAAAAVVTRAAAAAAABkAD8fq0d+bofA1LCatUL0dCTJexnyYYd4Y1ghnNUXMAAAAAdzWUAAAKSzYAD0JAAAAAAA==' b64 = b"AAAAABXWSL/k028ZbPtXNf/YylTNS4Iz90PyJEnefPMBzbRpAAAAZAAAAAEAAAAAAAAAAAAAAAAAAAABAAAAAAAAAAQAAAAAAAAAAVVTRAAAAAAABkAD8fq0d+bofA1LCatUL0dCTJexnyYYd4Y1ghnNUXMAAAAAdzWUAAAKSzYAD0JAAAAAAA=="
tx, operations = stellar.parse_transaction_bytes(base64.b64decode(b64)) tx, operations = stellar.parse_transaction_bytes(base64.b64decode(b64))
op = operations[0] op = operations[0]
@ -244,8 +292,11 @@ def test_stellar_parse_operation_bytes_passive_offer_new():
assert op.buying_asset.type == stellar.ASSET_TYPE_ALPHA4 assert op.buying_asset.type == stellar.ASSET_TYPE_ALPHA4
# asset codes are either 4 or 12 characters, so this will be null-padded at the end # asset codes are either 4 or 12 characters, so this will be null-padded at the end
assert op.buying_asset.code == b'USD\x00' assert op.buying_asset.code == b"USD\x00"
assert op.buying_asset.issuer == 'GADEAA7R7K2HPZXIPQGUWCNLKQXUOQSMS6YZ6JQYO6DDLAQZZVIXG74A' assert (
op.buying_asset.issuer
== "GADEAA7R7K2HPZXIPQGUWCNLKQXUOQSMS6YZ6JQYO6DDLAQZZVIXG74A"
)
assert op.amount == 2000000000 assert op.amount == 2000000000
assert op.price_n == 674614 assert op.price_n == 674614
@ -253,7 +304,7 @@ def test_stellar_parse_operation_bytes_passive_offer_new():
def test_stellar_parse_operation_bytes_set_options_inflation(): def test_stellar_parse_operation_bytes_set_options_inflation():
b64 = b'AAAAABXWSL/k028ZbPtXNf/YylTNS4Iz90PyJEnefPMBzbRpAAAAZAAAAAEAAAAAAAAAAAAAAAAAAAABAAAAAAAAAAUAAAABAAAAAAt5i66vbwH70/2M4Oj0rQW81SNLAjfOsMV2bavzocXhAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA' b64 = b"AAAAABXWSL/k028ZbPtXNf/YylTNS4Iz90PyJEnefPMBzbRpAAAAZAAAAAEAAAAAAAAAAAAAAAAAAAABAAAAAAAAAAUAAAABAAAAAAt5i66vbwH70/2M4Oj0rQW81SNLAjfOsMV2bavzocXhAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA"
tx, operations = stellar.parse_transaction_bytes(base64.b64decode(b64)) tx, operations = stellar.parse_transaction_bytes(base64.b64decode(b64))
op = operations[0] op = operations[0]
@ -261,11 +312,14 @@ def test_stellar_parse_operation_bytes_set_options_inflation():
assert isinstance(op, messages.StellarSetOptionsOp) assert isinstance(op, messages.StellarSetOptionsOp)
assert op.source_account is None assert op.source_account is None
assert op.inflation_destination_account == 'GAFXTC5OV5XQD66T7WGOB2HUVUC3ZVJDJMBDPTVQYV3G3K7TUHC6CLBR' assert (
op.inflation_destination_account
== "GAFXTC5OV5XQD66T7WGOB2HUVUC3ZVJDJMBDPTVQYV3G3K7TUHC6CLBR"
)
def test_stellar_parse_operation_bytes_change_trust_add(): def test_stellar_parse_operation_bytes_change_trust_add():
b64 = b'AAAAABXWSL/k028ZbPtXNf/YylTNS4Iz90PyJEnefPMBzbRpAAAAZAAAAAEAAAAAAAAAAAAAAAAAAAABAAAAAAAAAAYAAAABVVNEAAAAAACkn7CoQZEWAlyO6z6VBUAddrDDR078TtLt/nP/hZJ9KQAAAAJUC+QAAAAAAA==' b64 = b"AAAAABXWSL/k028ZbPtXNf/YylTNS4Iz90PyJEnefPMBzbRpAAAAZAAAAAEAAAAAAAAAAAAAAAAAAAABAAAAAAAAAAYAAAABVVNEAAAAAACkn7CoQZEWAlyO6z6VBUAddrDDR078TtLt/nP/hZJ9KQAAAAJUC+QAAAAAAA=="
tx, operations = stellar.parse_transaction_bytes(base64.b64decode(b64)) tx, operations = stellar.parse_transaction_bytes(base64.b64decode(b64))
op = operations[0] op = operations[0]
@ -274,14 +328,14 @@ def test_stellar_parse_operation_bytes_change_trust_add():
assert op.source_account is None assert op.source_account is None
assert op.asset.type == stellar.ASSET_TYPE_ALPHA4 assert op.asset.type == stellar.ASSET_TYPE_ALPHA4
assert op.asset.code == b'USD\x00' assert op.asset.code == b"USD\x00"
assert op.asset.issuer == 'GCSJ7MFIIGIRMAS4R3VT5FIFIAOXNMGDI5HPYTWS5X7HH74FSJ6STSGF' assert op.asset.issuer == "GCSJ7MFIIGIRMAS4R3VT5FIFIAOXNMGDI5HPYTWS5X7HH74FSJ6STSGF"
assert op.limit == 10000000000 assert op.limit == 10000000000
def test_stellar_parse_operation_bytes_allow_trust_allow(): def test_stellar_parse_operation_bytes_allow_trust_allow():
b64 = b'AAAAABXWSL/k028ZbPtXNf/YylTNS4Iz90PyJEnefPMBzbRpAAAAZAAAAAEAAAAAAAAAAAAAAAAAAAABAAAAAAAAAAcAAAAAZ0Me3OnxI2tuaC8qt95THF1fuB42qARTnP2ookJapQUAAAABSlBZAAAAAAEAAAAA' b64 = b"AAAAABXWSL/k028ZbPtXNf/YylTNS4Iz90PyJEnefPMBzbRpAAAAZAAAAAEAAAAAAAAAAAAAAAAAAAABAAAAAAAAAAcAAAAAZ0Me3OnxI2tuaC8qt95THF1fuB42qARTnP2ookJapQUAAAABSlBZAAAAAAEAAAAA"
tx, operations = stellar.parse_transaction_bytes(base64.b64decode(b64)) tx, operations = stellar.parse_transaction_bytes(base64.b64decode(b64))
op = operations[0] op = operations[0]
@ -290,13 +344,15 @@ def test_stellar_parse_operation_bytes_allow_trust_allow():
assert op.source_account is None assert op.source_account is None
assert op.asset_type == stellar.ASSET_TYPE_ALPHA4 assert op.asset_type == stellar.ASSET_TYPE_ALPHA4
assert op.asset_code == b'JPY\x00' assert op.asset_code == b"JPY\x00"
assert op.trusted_account == 'GBTUGHW45HYSG23ONAXSVN66KMOF2X5YDY3KQBCTTT62RISCLKSQLYF4' assert (
op.trusted_account == "GBTUGHW45HYSG23ONAXSVN66KMOF2X5YDY3KQBCTTT62RISCLKSQLYF4"
)
def test_stellar_parse_operation_bytes_account_merge_simple(): def test_stellar_parse_operation_bytes_account_merge_simple():
b64 = b'AAAAABXWSL/k028ZbPtXNf/YylTNS4Iz90PyJEnefPMBzbRpAAAAZAAAAAEAAAAAAAAAAAAAAAAAAAABAAAAAAAAAAgAAAAAXVVkJGaxhbhDFS6eIZFR28WJICfsQBAaUXvtXKAwwuAAAAAA' b64 = b"AAAAABXWSL/k028ZbPtXNf/YylTNS4Iz90PyJEnefPMBzbRpAAAAZAAAAAEAAAAAAAAAAAAAAAAAAAABAAAAAAAAAAgAAAAAXVVkJGaxhbhDFS6eIZFR28WJICfsQBAaUXvtXKAwwuAAAAAA"
tx, operations = stellar.parse_transaction_bytes(base64.b64decode(b64)) tx, operations = stellar.parse_transaction_bytes(base64.b64decode(b64))
op = operations[0] op = operations[0]
@ -304,11 +360,14 @@ def test_stellar_parse_operation_bytes_account_merge_simple():
assert isinstance(op, messages.StellarAccountMergeOp) assert isinstance(op, messages.StellarAccountMergeOp)
assert op.source_account is None assert op.source_account is None
assert op.destination_account == 'GBOVKZBEM2YYLOCDCUXJ4IMRKHN4LCJAE7WEAEA2KF562XFAGDBOB64V' assert (
op.destination_account
== "GBOVKZBEM2YYLOCDCUXJ4IMRKHN4LCJAE7WEAEA2KF562XFAGDBOB64V"
)
def test_stellar_parse_operation_bytes_manage_data_set_simple(): def test_stellar_parse_operation_bytes_manage_data_set_simple():
b64 = b'AAAAABXWSL/k028ZbPtXNf/YylTNS4Iz90PyJEnefPMBzbRpAAAAZAAAAAEAAAAAAAAAAAAAAAAAAAABAAAAAAAAAAoAAAAJdGVzdCBkYXRhAAAAAAAAAQAAAARhc2RmAAAAAA==' b64 = b"AAAAABXWSL/k028ZbPtXNf/YylTNS4Iz90PyJEnefPMBzbRpAAAAZAAAAAEAAAAAAAAAAAAAAAAAAAABAAAAAAAAAAoAAAAJdGVzdCBkYXRhAAAAAAAAAQAAAARhc2RmAAAAAA=="
tx, operations = stellar.parse_transaction_bytes(base64.b64decode(b64)) tx, operations = stellar.parse_transaction_bytes(base64.b64decode(b64))
op = operations[0] op = operations[0]
@ -316,12 +375,12 @@ def test_stellar_parse_operation_bytes_manage_data_set_simple():
assert isinstance(op, messages.StellarManageDataOp) assert isinstance(op, messages.StellarManageDataOp)
assert op.source_account is None assert op.source_account is None
assert op.key == b'test data' assert op.key == b"test data"
assert op.value == b'asdf' assert op.value == b"asdf"
def test_stellar_parse_operation_bytes_bump_sequence_simple(): def test_stellar_parse_operation_bytes_bump_sequence_simple():
b64 = b'AAAAABXWSL/k028ZbPtXNf/YylTNS4Iz90PyJEnefPMBzbRpAAAAZAAAAAEAAAAAAAAAAAAAAAAAAAABAAAAAAAAAAsAAAAASZYC0gAAAAA=' b64 = b"AAAAABXWSL/k028ZbPtXNf/YylTNS4Iz90PyJEnefPMBzbRpAAAAZAAAAAEAAAAAAAAAAAAAAAAAAAABAAAAAAAAAAsAAAAASZYC0gAAAAA="
tx, operations = stellar.parse_transaction_bytes(base64.b64decode(b64)) tx, operations = stellar.parse_transaction_bytes(base64.b64decode(b64))
op = operations[0] op = operations[0]

View File

@ -23,7 +23,7 @@ def test_all_transports_without_hid():
# import all transports, assume this doesn't fail # import all transports, assume this doesn't fail
transports_ref = all_transports() transports_ref = all_transports()
# also shouldn't fail when bridge transport is missing # also shouldn't fail when bridge transport is missing
with mock.patch.dict('sys.modules', {'trezorlib.transport.bridge': None}): with mock.patch.dict("sys.modules", {"trezorlib.transport.bridge": None}):
transports = all_transports() transports = all_transports()
# there should now be less transports # there should now be less transports
assert len(transports_ref) > len(transports) assert len(transports_ref) > len(transports)

View File

@ -14,36 +14,61 @@
# You should have received a copy of the License along with this library. # You should have received a copy of the License along with this library.
# If not, see <https://www.gnu.org/licenses/lgpl-3.0.html>. # If not, see <https://www.gnu.org/licenses/lgpl-3.0.html>.
import binascii
import os import os
from trezorlib import coins from trezorlib import coins, tx_api
from trezorlib import tx_api
import binascii
TxApiBitcoin = coins.tx_api['Bitcoin'] TxApiBitcoin = coins.tx_api["Bitcoin"]
TxApiTestnet = tx_api.TxApiInsight("insight_testnet") TxApiTestnet = tx_api.TxApiInsight("insight_testnet")
TxApiZencash = coins.tx_api['Zencash'] TxApiZencash = coins.tx_api["Zencash"]
tests_dir = os.path.dirname(os.path.abspath(__file__)) tests_dir = os.path.dirname(os.path.abspath(__file__))
def test_tx_api_gettx(): def test_tx_api_gettx():
tx_api.cache_dir = os.path.join(tests_dir, '../txcache') tx_api.cache_dir = os.path.join(tests_dir, "../txcache")
TxApiBitcoin.get_tx('39a29e954977662ab3879c66fb251ef753e0912223a83d1dcb009111d28265e5') TxApiBitcoin.get_tx(
TxApiBitcoin.get_tx('54aa5680dea781f45ebb536e53dffc526d68c0eb5c00547e323b2c32382dfba3') "39a29e954977662ab3879c66fb251ef753e0912223a83d1dcb009111d28265e5"
TxApiBitcoin.get_tx('58497a7757224d1ff1941488d23087071103e5bf855f4c1c44e5c8d9d82ca46e') )
TxApiBitcoin.get_tx('6189e3febb5a21cee8b725aa1ef04ffce7e609448446d3a8d6f483c634ef5315') TxApiBitcoin.get_tx(
TxApiBitcoin.get_tx('a6e2829d089cee47e481b1a753a53081b40738cc87e38f1d9b23ab57d9ad4396') "54aa5680dea781f45ebb536e53dffc526d68c0eb5c00547e323b2c32382dfba3"
TxApiBitcoin.get_tx('c6091adf4c0c23982a35899a6e58ae11e703eacd7954f588ed4b9cdefc4dba52') )
TxApiBitcoin.get_tx('c63e24ed820c5851b60c54613fbc4bcb37df6cd49b4c96143e99580a472f79fb') TxApiBitcoin.get_tx(
TxApiBitcoin.get_tx('c6be22d34946593bcad1d2b013e12f74159e69574ffea21581dad115572e031c') "58497a7757224d1ff1941488d23087071103e5bf855f4c1c44e5c8d9d82ca46e"
TxApiBitcoin.get_tx('d1d08ea63255af4ad16b098e9885a252632086fa6be53301521d05253ce8a73d') )
TxApiBitcoin.get_tx('d5f65ee80147b4bcc70b75e4bbf2d7382021b871bd8867ef8fa525ef50864882') TxApiBitcoin.get_tx(
TxApiBitcoin.get_tx('e4bc1ae5e5007a08f2b3926fe11c66612e8f73c6b00c69c7027213b84d259be3') "6189e3febb5a21cee8b725aa1ef04ffce7e609448446d3a8d6f483c634ef5315"
)
TxApiBitcoin.get_tx(
"a6e2829d089cee47e481b1a753a53081b40738cc87e38f1d9b23ab57d9ad4396"
)
TxApiBitcoin.get_tx(
"c6091adf4c0c23982a35899a6e58ae11e703eacd7954f588ed4b9cdefc4dba52"
)
TxApiBitcoin.get_tx(
"c63e24ed820c5851b60c54613fbc4bcb37df6cd49b4c96143e99580a472f79fb"
)
TxApiBitcoin.get_tx(
"c6be22d34946593bcad1d2b013e12f74159e69574ffea21581dad115572e031c"
)
TxApiBitcoin.get_tx(
"d1d08ea63255af4ad16b098e9885a252632086fa6be53301521d05253ce8a73d"
)
TxApiBitcoin.get_tx(
"d5f65ee80147b4bcc70b75e4bbf2d7382021b871bd8867ef8fa525ef50864882"
)
TxApiBitcoin.get_tx(
"e4bc1ae5e5007a08f2b3926fe11c66612e8f73c6b00c69c7027213b84d259be3"
)
TxApiTestnet.get_tx('6f90f3c7cbec2258b0971056ef3fe34128dbde30daa9c0639a898f9977299d54') TxApiTestnet.get_tx(
TxApiTestnet.get_tx('d6da21677d7cca5f42fbc7631d062c9ae918a0254f7c6c22de8e8cb7fd5b8236') "6f90f3c7cbec2258b0971056ef3fe34128dbde30daa9c0639a898f9977299d54"
)
TxApiTestnet.get_tx(
"d6da21677d7cca5f42fbc7631d062c9ae918a0254f7c6c22de8e8cb7fd5b8236"
)
def test_tx_api_current_block(): def test_tx_api_current_block():
@ -53,4 +78,6 @@ def test_tx_api_current_block():
def test_tx_api_get_block_hash(): def test_tx_api_get_block_hash():
hash = TxApiZencash.get_block_hash(110000) hash = TxApiZencash.get_block_hash(110000)
assert hash == binascii.unhexlify('000000003f5d6ba1385c6cd2d4f836dfc5adf7f98834309ad67e26faef462454') assert hash == binascii.unhexlify(
"000000003f5d6ba1385c6cd2d4f836dfc5adf7f98834309ad67e26faef462454"
)

View File

@ -18,13 +18,13 @@ import functools
import hashlib import hashlib
import struct import struct
import unicodedata import unicodedata
from typing import NewType, List from typing import List, NewType
from .coins import slip44 from .coins import slip44
HARDENED_FLAG = 1 << 31 HARDENED_FLAG = 1 << 31
Address = NewType('Address', List[int]) Address = NewType("Address", List[int])
def H_(x: int) -> int: def H_(x: int) -> int:
@ -42,13 +42,13 @@ def btc_hash(data):
def hash_160(public_key): def hash_160(public_key):
md = hashlib.new('ripemd160') md = hashlib.new("ripemd160")
md.update(hashlib.sha256(public_key).digest()) md.update(hashlib.sha256(public_key).digest())
return md.digest() return md.digest()
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 = btc_hash(vh160) h = btc_hash(vh160)
addr = vh160 + h[0:4] addr = vh160 + h[0:4]
return b58encode(addr) return b58encode(addr)
@ -61,14 +61,14 @@ def compress_pubkey(public_key):
def public_key_to_bc_address(public_key, address_type, compress=True): def public_key_to_bc_address(public_key, address_type, compress=True):
if public_key[0] == '\x04' and compress: if public_key[0] == "\x04" and compress:
public_key = compress_pubkey(public_key) public_key = compress_pubkey(public_key)
h160 = hash_160(public_key) h160 = hash_160(public_key)
return hash_160_to_bc_address(h160, address_type) return hash_160_to_bc_address(h160, address_type)
__b58chars = '123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz' __b58chars = "123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz"
__b58base = len(__b58chars) __b58base = len(__b58chars)
@ -79,7 +79,7 @@ def b58encode(v):
for c in v: for c in v:
long_value = long_value * 256 + c long_value = long_value * 256 + c
result = '' result = ""
while long_value >= __b58base: while long_value >= __b58base:
div, mod = divmod(long_value, __b58base) div, mod = divmod(long_value, __b58base)
result = __b58chars[mod] + result result = __b58chars[mod] + result
@ -104,12 +104,12 @@ def b58decode(v, length):
for (i, c) in enumerate(v[::-1]): for (i, c) in enumerate(v[::-1]):
long_value += __b58chars.find(c) * (__b58base ** i) long_value += __b58chars.find(c) * (__b58base ** i)
result = b'' result = b""
while long_value >= 256: while long_value >= 256:
div, mod = divmod(long_value, 256) div, mod = divmod(long_value, 256)
result = struct.pack('B', mod) + result result = struct.pack("B", mod) + result
long_value = div long_value = div
result = struct.pack('B', long_value) + result result = struct.pack("B", long_value) + result
nPad = 0 nPad = 0
for c in v: for c in v:
@ -118,7 +118,7 @@ def b58decode(v, length):
else: else:
break break
result = b'\x00' * nPad + result result = b"\x00" * nPad + result
if length is not None and len(result) != length: if length is not None and len(result) != length:
return None return None
@ -138,21 +138,21 @@ def parse_path(nstr: str) -> Address:
if not nstr: if not nstr:
return [] return []
n = nstr.split('/') n = nstr.split("/")
# m/a/b/c => a/b/c # m/a/b/c => a/b/c
if n[0] == 'm': if n[0] == "m":
n = n[1:] n = n[1:]
# coin_name/a/b/c => 44'/SLIP44_constant'/a/b/c # coin_name/a/b/c => 44'/SLIP44_constant'/a/b/c
if n[0] in slip44: if n[0] in slip44:
coin_id = slip44[n[0]] coin_id = slip44[n[0]]
n[0:1] = ['44h', '{}h'.format(coin_id)] n[0:1] = ["44h", "{}h".format(coin_id)]
def str_to_harden(x: str) -> int: def str_to_harden(x: str) -> int:
if x.startswith('-'): if x.startswith("-"):
return H_(abs(int(x))) return H_(abs(int(x)))
elif x.endswith(('h', "'")): elif x.endswith(("h", "'")):
return H_(int(x[:-1])) return H_(int(x[:-1]))
else: else:
return int(x) return int(x)
@ -160,17 +160,17 @@ def parse_path(nstr: str) -> Address:
try: try:
return [str_to_harden(x) for x in n] return [str_to_harden(x) for x in n]
except Exception: except Exception:
raise ValueError('Invalid BIP32 path', nstr) raise ValueError("Invalid BIP32 path", nstr)
def normalize_nfc(txt): def normalize_nfc(txt):
''' """
Normalize message to NFC and return bytes suitable for protobuf. Normalize message to NFC and return bytes suitable for protobuf.
This seems to be bitcoin-qt standard of doing things. This seems to be bitcoin-qt standard of doing things.
''' """
if isinstance(txt, bytes): if isinstance(txt, bytes):
txt = txt.decode('utf-8') txt = txt.decode("utf-8")
return unicodedata.normalize('NFC', txt).encode('utf-8') return unicodedata.normalize("NFC", txt).encode("utf-8")
class CallException(Exception): class CallException(Exception):
@ -190,7 +190,9 @@ class expect:
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):
raise RuntimeError("Got %s, expected %s" % (ret.__class__, self.expected)) raise RuntimeError(
"Got %s, expected %s" % (ret.__class__, self.expected)
)
if self.field is not None: if self.field is not None:
return getattr(ret, self.field) return getattr(ret, self.field)
else: else:
@ -204,11 +206,12 @@ def session(f):
# with session activation / deactivation # with session activation / deactivation
@functools.wraps(f) @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 __tracebackhide__ = True # for pytest # pylint: disable=W0612
client = args[0] client = args[0]
client.transport.session_begin() client.transport.session_begin()
try: try:
return f(*args, **kwargs) return f(*args, **kwargs)
finally: finally:
client.transport.session_end() client.transport.session_end()
return wrapped_f return wrapped_f

Some files were not shown because too many files have changed in this diff Show More