Merge branch 'develop'

pull/25/head
matejcik 6 years ago
commit e8e61861f6

@ -1,22 +0,0 @@
[flake8]
filename =
*.py,
./trezorctl
exclude =
.tox/,
build/,
dist/,
vendor/,
ignore =
# F401: module imported but unused
F401,
# E241: multiple spaces after ':'
E241,
# E402: module level import not at top of file
E402,
# E501: line too long
E501,
# E722: do not use bare except
E722,
# E741: ambiguous variable name
E741

@ -19,7 +19,6 @@ env:
PROTOBUF_VERSION=3.4.0
python:
- "3.3"
- "3.4"
- "3.5"
- "3.6"
@ -28,21 +27,19 @@ install:
# Optimisation: build requirements as wheels, which get cached by Travis
- pip install "pip>=9.0" wheel # pip 9.0 understands `python_requires` constraints
- pip install "setuptools>=38" # setuptools >= 38 are capable of using prebuilt wheels
- pip install "virtualenv<16.0.0" # virtualenv 16.0.0 drops support for py33 without properly declaring it
- pip install tox-travis
- pip install flake8
- pip install -r requirements-dev.txt
# protobuf-related dependencies
- curl -LO "https://github.com/google/protobuf/releases/download/v${PROTOBUF_VERSION}/protoc-${PROTOBUF_VERSION}-linux-x86_64.zip"
- unzip "protoc-${PROTOBUF_VERSION}-linux-x86_64.zip" -d protoc
- export PATH="$(pwd)/protoc/bin:$PATH"
- pip install "protobuf == ${PROTOBUF_VERSION}"
before_script:
- ./trigger-travis.sh
script:
- python setup.py install
- flake8
- if [ $TRAVIS_PYTHON_VERSION == 3.6 ]; then make stylecheck; fi
- tox
notifications:

@ -0,0 +1,29 @@
PYTHON=python3
SETUP=$(PYTHON) setup.py
EXCLUDES=.vscode
STYLE_TARGETS=trezorlib trezorctl
EXCLUDE_TARGETS=trezorlib/messages
all: build
build:
$(SETUP) build
install:
$(SETUP) install
clean:
git clean -dfx -e $(EXCLUDES)
style:
black $(STYLE_TARGETS)
isort --apply --recursive $(STYLE_TARGETS) --skip-glob "*/$(EXCLUDE_TARGETS)/*"
autoflake -i --remove-all-unused-imports -r $(STYLE_TARGETS) --exclude "$(EXCLUDE_TARGETS)"
stylecheck:
black --check $(STYLE_TARGETS)
isort --diff --check-only --recursive $(STYLE_TARGETS) --skip-glob "*/$(EXCLUDE_TARGETS)/*"
flake8
.PHONY: all build install clean style stylecheck

@ -4,3 +4,6 @@ pytest>=3.2.5
mock>=2.0.0
flake8
protobuf
isort
black; python_version >= "3.6"
autoflake

@ -4,5 +4,5 @@ requests>=2.4.0
click>=6.2
pyblake2>=0.9.3
libusb1>=1.6.4
pip>=6
construct>=2.9
typing>=3.0.0; python_version < '3.5'

@ -0,0 +1,36 @@
[flake8]
filename =
*.py,
./trezorctl
exclude =
.tox/,
build/,
dist/,
vendor/,
trezorlib/messages/__init__.py
ignore =
# E203 whitespace before ':'
E203,
# E221: multiple spaces before operator
E221,
# E241: multiple spaces after ':'
E241,
# E402: module level import not at top of file
E402,
# E501: line too long
E501,
# E741 ambiguous variable name
E741,
# W503: line break before binary operator
W503
[isort]
multi_line_output = 3
include_trailing_comma = True
force_grid_wrap = 0
combine_as_imports = True
line_length = 88
not_skip=__init__.py
known_first_party=trezorlib
known_third_party=hidapi, rlp, ethjsonrpc, ecdsa, mnemonic, requests, click, pyblake2, \
usb, construct

@ -20,6 +20,7 @@ install_requires = [
'click>=6.2',
'pyblake2>=0.9.3',
'libusb1>=1.6.4',
'construct>=2.9',
]
CWD = os.path.dirname(os.path.realpath(__file__))

@ -1,6 +1,4 @@
#!/usr/bin/env python3
from __future__ import print_function
'''
Use TREZOR as a hardware key for opening EncFS filesystem!
@ -62,7 +60,7 @@ def choose_device(devices):
try:
device_id = int(input())
return devices[device_id]
except:
except Exception:
raise ValueError("Invalid choice, exiting...")

@ -2,7 +2,6 @@
from trezorlib.debuglink import DebugLink
from trezorlib.client import TrezorClient
from trezorlib.transport import enumerate_devices
import binascii
import sys
sectoraddrs = [0x8000000, 0x8004000, 0x8008000, 0x800c000,

@ -4,7 +4,6 @@
# that has DEBUG_RNG == 1 as that will disable the user button
# push confirmation
from __future__ import print_function
import io
import sys
from trezorlib.client import TrezorClient

@ -1,233 +0,0 @@
#!/usr/bin/env python
import binascii
import os
import random
import trezorlib.messages_pb2 as proto
import trezorlib.types_pb2 as proto_types
import trezorlib.tools as tools
import trezorlib.ckd_public as bip32
import hashlib
from trezorlib.client import TrezorClient
from trezorlib.tx_api import TxApiTestnet
from trezorlib.tx_api import TxApiBitcoin
from trezorlib.transport import get_transport
# This script has survived unmodified through several significant changes
# of the trezorlib library. While we want to have something like this,
# we're waiting on a couple more changes in order to implement this a little more cleanly.
# Wait for trezorlib v1.0.
raise Exception("This code is too old to run. Sorry.")
def hash160(x):
h = hashlib.new("ripemd160")
h.update(hashlib.sha256(x).digest())
return h.digest()
def pack_varint(x):
if (x < 0xfd):
return chr(x)
else:
return '\xfd' + chr(x & 0xff) + chr((x >> 8) & 0xff)
def int_to_string(x, pad):
result = ['\x00'] * pad
while x > 0:
pad -= 1
ordinal = x & 0xFF
result[pad] = (chr(ordinal))
x >>= 8
return ''.join(result)
def string_to_int(s):
result = 0
for c in s:
if not isinstance(c, int):
c = ord(c)
result = (result << 8) + c
return result
class MyTxApiBitcoin(object):
def set_publickey(self, node):
self.node = node.node
def set_client(self, client):
self.client = client
def serialize_tx(self, tx):
ser = ''
ser = ser + int_to_string(tx.version, 4)[::-1]
ser = ser + pack_varint(len(tx.inputs))
for i in tx.inputs:
ser = ser + i.prev_hash[::-1]
ser = ser + int_to_string(i.prev_index, 4)[::-1]
ser = ser + pack_varint(len(i.script_sig)) + i.script_sig
ser = ser + int_to_string(i.sequence, 4)[::-1]
ser = ser + pack_varint(len(tx.bin_outputs))
for o in tx.bin_outputs:
ser = ser + int_to_string(o.amount, 8)[::-1]
ser = ser + pack_varint(len(o.script_pubkey)) + o.script_pubkey
ser = ser + int_to_string(tx.lock_time, 4)[::-1]
return ser
def create_inputs(self, numinputs, txsize):
idx = 0
sum = 0
self.inputs = []
self.txs = {}
for nr in range(numinputs):
t = proto_types.TransactionType()
t.version = 1
t.lock_time = 0
i = t.inputs.add()
i.prev_hash = os.urandom(32)
i.prev_index = random.randint(0, 4)
i.script_sig = os.urandom(100)
i.sequence = 0xffffffff
if nr % 50 == 0:
print(nr)
myout = random.randint(0, txsize - 1)
segwit = random.randint(0, 2)
for vout in range(txsize):
o = t.bin_outputs.add()
o.amount = random.randint(10000, 1000000)
if vout == myout:
amount = o.amount
sum = sum + o.amount
node = self.node
path = [0, idx]
node = bip32.public_ckd(node, path)
idx = idx + 1
pubkey = tools.hash_160(node.public_key)
else:
pubkey = os.urandom(20)
if segwit == 2:
# p2sh segwit
o.script_pubkey = b'\xa9\x14' + hash160(b'\x00\x14' + pubkey) + b'\x87'
elif segwit == 1:
o.script_pubkey = b'\x00\x14' + pubkey
else:
o.script_pubkey = b'\x76\xa9\x14' + pubkey + b'\x88\xac'
txser = self.serialize_tx(t)
txhash = tools.btc_hash(txser)[::-1]
self.inputs.append(
proto_types.TxInputType(
address_n=self.client.expand_path("44'/0'/0'/0/%d" % idx),
script_type=(
proto_types.SPENDWITNESS if segwit == 1 else
proto_types.SPENDP2SHWITNESS if segwit == 2 else
proto_types.SPENDADDRESS
),
prev_hash=txhash,
prev_index=myout,
amount=amount if segwit > 0 else 0
))
# print(binascii.hexlify(txser))
# print(binascii.hexlify(txhash))
self.txs[binascii.hexlify(txhash)] = t
self.outputs = [
proto_types.TxOutputType(
amount=sum,
script_type=proto_types.PAYTOADDRESS,
address_n=self.client.expand_path("44'/0'/0'/1/0")
)]
def get_inputs(self):
return self.inputs
def get_outputs(self):
return self.outputs
def get_tx(self, txhash):
t = self.txs[txhash]
# print(t)
return t
def main():
numinputs = 100
sizeinputtx = 10
# Use first connected device
try:
transport = get_transport()
except Exception as e:
print(e)
return
print(transport)
txstore = MyTxApiBitcoin()
# Creates object for manipulating TREZOR
client = TrezorClient(transport)
# client.set_tx_api(TxApiTestnet)
txstore.set_client(client)
txstore.set_publickey(client.get_public_node(client.expand_path("44'/0'/0'")))
print("creating input txs")
txstore.create_inputs(numinputs, sizeinputtx)
print("go")
client.set_tx_api(txstore)
# client.set_tx_api(MyTxApiBitcoin())
# Print out TREZOR's features and settings
print(client.features)
# Get the first address of first BIP44 account
# (should be the same address as shown in wallet.trezor.io)
# outputs = [
# proto_types.TxOutputType(
# amount=0,
# script_type=proto_types.PAYTOADDRESS,
# address='p2xtZoXeX5X8BP8JfFhQK2nD3emtjch7UeFm'
# # op_return_data=binascii.unhexlify('2890770995194662774cd192ee383b805e9a066e6a456be037727649228fb7f6')
# # address_n=client.expand_path("44'/0'/0'/0/35"),
# # address='3PUxV6Cc4udQZQsJhArVUzvvVoKC8ohkAj',
# ),
# proto_types.TxOutputType(
# amount=0,
# script_type=proto_types.PAYTOOPRETURN,
# op_return_data=binascii.unhexlify('2890770995194662774cd192ee383b805e9a066e6a456be037727649228fb7f6')
# ),
# proto_types.TxOutputType(
# amount= 8120,
# script_type=proto_types.PAYTOADDRESS,
# address_n=client.expand_path("44'/1'/0'/1/0"),
# address='1PtCkQgyN6xHmXWzLmFFrDNA5vYhYLeNFZ',
# address='14KRxYgFc7Se8j7MDdrK5PTNv8meq4GivK',
# ),
# proto_types.TxOutputType(
# amount= 18684 - 2000,
# script_type=proto_types.PAYTOADDRESS,
# address_n=client.expand_path("44'/0'/0'/0/7"),
# # address='1PtCkQgyN6xHmXWzLmFFrDNA5vYhYLeNFZ',
# # address='1s9TSqr3PHZdXGrYws59Uaf5SPqavH43z',
# ),
# proto_types.TxOutputType(
# amount= 1000,
# script_type=proto_types.PAYTOADDRESS,
# # address_n=client.expand_path("44'/0'/0'/0/18"),
# # address='1PtCkQgyN6xHmXWzLmFFrDNA5vYhYLeNFZ',
# # address='1NcMqUvyWv1K3Zxwmx5sqfj7ZEmPCSdJFM',
# ),
# ]
# (signatures, serialized_tx) = client.sign_tx('Testnet', inputs, outputs)
(signatures, serialized_tx) = client.sign_tx('Bitcoin', txstore.get_inputs(), txstore.get_outputs())
print('Transaction:', binascii.hexlify(serialized_tx))
client.close()
if __name__ == '__main__':
main()

@ -10,13 +10,10 @@ deps =
-rrequirements-dev.txt
commands =
# Generate local files
python setup.py prebuild
python setup.py build
# Working in the local directory, try to compile all bytecode
python -m compileall trezorlib/
# From installed version, smoke-test trezorctl
trezorctl --help
# Run non-device-dependent tests
python -m pytest --pyarg trezorlib.tests.unit_tests
# This whole thing is a hack, as the tests run against the cwd version of
# python-trezor, as opposed to what is installed.
# A better solution would be to put `trezorlib` into `src`. But that's not done yet
# Run non-device-dependent tests from installed version
python -E -m pytest --pyarg trezorlib.tests.unit_tests

File diff suppressed because it is too large Load Diff

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

@ -0,0 +1,210 @@
from . import messages as proto
from .tools import CallException, expect, normalize_nfc, session
@expect(proto.PublicKey)
def get_public_node(
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")
def get_address(
client,
coin_name,
n,
show_display=False,
multisig=None,
script_type=proto.InputScriptType.SPENDADDRESS,
):
if multisig:
return client.call(
proto.GetAddress(
address_n=n,
coin_name=coin_name,
show_display=show_display,
multisig=multisig,
script_type=script_type,
)
)
else:
return client.call(
proto.GetAddress(
address_n=n,
coin_name=coin_name,
show_display=show_display,
script_type=script_type,
)
)
@expect(proto.MessageSignature)
def sign_message(
client, coin_name, n, message, script_type=proto.InputScriptType.SPENDADDRESS
):
message = normalize_nfc(message)
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):
message = normalize_nfc(message)
try:
resp = client.call(
proto.VerifyMessage(
address=address,
signature=signature,
message=message,
coin_name=coin_name,
)
)
except CallException as e:
resp = e
return isinstance(resp, proto.Success)
@session
def sign_tx(
client,
coin_name,
inputs,
outputs,
version=None,
lock_time=None,
expiry=None,
overwintered=None,
debug_processor=None,
):
# start = time.time()
txes = client._prepare_sign_tx(inputs, outputs)
# Prepare and send initial message
tx = proto.SignTx()
tx.inputs_count = len(inputs)
tx.outputs_count = len(outputs)
tx.coin_name = coin_name
if version is not None:
tx.version = version
if lock_time is not None:
tx.lock_time = lock_time
if expiry is not None:
tx.expiry = expiry
if overwintered is not None:
tx.overwintered = overwintered
res = client.call(tx)
# Prepare structure for signatures
signatures = [None] * len(inputs)
serialized_tx = b""
counter = 0
while True:
counter += 1
if isinstance(res, proto.Failure):
raise CallException("Signing failed")
if not isinstance(res, proto.TxRequest):
raise CallException("Unexpected message")
# If there's some part of signed transaction, let's add it
if res.serialized and res.serialized.serialized_tx:
# log("RECEIVED PART OF SERIALIZED TX (%d BYTES)" % len(res.serialized.serialized_tx))
serialized_tx += res.serialized.serialized_tx
if res.serialized and 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
)
signatures[res.serialized.signature_index] = res.serialized.signature
if res.request_type == proto.RequestType.TXFINISHED:
# Device didn't ask for more information, finish workflow
break
# Device asked for one more information, let's process it.
if not res.details.tx_hash:
current_tx = txes[None]
else:
current_tx = txes[bytes(res.details.tx_hash)]
if res.request_type == proto.RequestType.TXMETA:
msg = proto.TransactionType()
msg.version = current_tx.version
msg.lock_time = current_tx.lock_time
msg.inputs_cnt = len(current_tx.inputs)
if res.details.tx_hash:
msg.outputs_cnt = len(current_tx.bin_outputs)
else:
msg.outputs_cnt = len(current_tx.outputs)
msg.extra_data_len = (
len(current_tx.extra_data) if current_tx.extra_data else 0
)
res = client.call(proto.TxAck(tx=msg))
continue
elif res.request_type == proto.RequestType.TXINPUT:
msg = proto.TransactionType()
msg.inputs = [current_tx.inputs[res.details.request_index]]
if debug_processor is not None:
# msg needs to be deep copied so when it's modified
# the other messages stay intact
from copy import deepcopy
msg = deepcopy(msg)
# If debug_processor function is provided,
# pass thru it the request and prepared response.
# This is useful for tests, see test_msg_signtx
msg = debug_processor(res, msg)
res = client.call(proto.TxAck(tx=msg))
continue
elif res.request_type == proto.RequestType.TXOUTPUT:
msg = proto.TransactionType()
if res.details.tx_hash:
msg.bin_outputs = [current_tx.bin_outputs[res.details.request_index]]
else:
msg.outputs = [current_tx.outputs[res.details.request_index]]
if debug_processor is not None:
# msg needs to be deep copied so when it's modified
# the other messages stay intact
from copy import deepcopy
msg = deepcopy(msg)
# If debug_processor function is provided,
# pass thru it the request and prepared response.
# This is useful for tests, see test_msg_signtx
msg = debug_processor(res, msg)
res = client.call(proto.TxAck(tx=msg))
continue
elif res.request_type == proto.RequestType.TXEXTRADATA:
o, l = res.details.extra_data_offset, res.details.extra_data_len
msg = proto.TransactionType()
msg.extra_data = current_tx.extra_data[o : o + l]
res = client.call(proto.TxAck(tx=msg))
continue
if None in signatures:
raise RuntimeError("Some signatures are missing!")
# log("SIGNED IN %.03f SECONDS, CALLED %d MESSAGES, %d BYTES" %
# (time.time() - start, counter, len(serialized_tx)))
return (signatures, serialized_tx)

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

File diff suppressed because it is too large Load Diff

@ -14,12 +14,12 @@
# 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>.
import os.path
import json
import os.path
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():
@ -35,24 +35,26 @@ def _load_coins_json():
def _insight_for_coin(coin):
url = next(iter(coin['blockbook'] + coin['bitcore']), None)
url = next(iter(coin["blockbook"] + coin["bitcore"]), None)
if not url:
return None
zcash = coin['coin_name'].lower().startswith('zcash')
bip115 = coin['bip115']
network = 'insight_{}'.format(coin['coin_name'].lower().replace(' ', '_'))
zcash = coin["coin_name"].lower().startswith("zcash")
bip115 = coin["bip115"]
network = "insight_{}".format(coin["coin_name"].lower().replace(" ", "_"))
return TxApiInsight(network=network, url=url, zcash=zcash, bip115=bip115)
# exported variables
__all__ = ['by_name', 'slip44', 'tx_api']
__all__ = ["by_name", "slip44", "tx_api"]
try:
by_name = _load_coins_json()
except Exception as e:
raise ImportError("Failed to load coins.json. Check your installation.") from e
slip44 = {name: coin['slip44'] for name, coin in by_name.items()}
tx_api = {name: _insight_for_coin(coin)
for name, coin in by_name.items()
if coin["blockbook"] or coin["bitcore"]}
slip44 = {name: coin["slip44"] for name, coin in by_name.items()}
tx_api = {
name: _insight_for_coin(coin)
for name, coin in by_name.items()
if coin["blockbook"] or coin["bitcore"]
}

@ -14,12 +14,12 @@
# 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>.
import sys
from functools import reduce
import binascii
from functools import reduce
from typing import Iterable, Tuple
from trezorlib import _ed25519
from . import _ed25519, messages
from .tools import expect
# 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.
@ -35,7 +35,9 @@ def combine_keys(pks: Iterable[Ed25519PublicPoint]) -> Ed25519PublicPoint:
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."""
S = [_ed25519.decodeint(si) for si in sigs]
s = sum(S) % _ed25519.l
@ -43,7 +45,9 @@ def combine_sig(global_R: Ed25519PublicPoint, sigs: Iterable[Ed25519Signature])
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.
These differ from Ed25519 deterministic nonces in that there is a counter appended at end.
@ -56,12 +60,18 @@ def get_nonce(sk: Ed25519PrivateKey, data: bytes, ctr: int = 0) -> Tuple[int, Ed
"""
h = _ed25519.H(sk)
b = _ed25519.b
r = _ed25519.Hint(bytes([h[i] for i in range(b >> 3, b >> 2)]) + data + binascii.unhexlify('%08x' % ctr))
r = _ed25519.Hint(
bytes([h[i] for i in range(b >> 3, b >> 2)])
+ data
+ binascii.unhexlify("%08x" % ctr)
)
R = _ed25519.scalarmult(_ed25519.B, r)
return r, Ed25519PublicPoint(_ed25519.encodepoint(R))
def verify(signature: Ed25519Signature, digest: bytes, pub_key: Ed25519PublicPoint) -> None:
def verify(
signature: Ed25519Signature, digest: bytes, pub_key: Ed25519PublicPoint
) -> None:
"""Verify Ed25519 signature. Raise exception if the signature is invalid."""
# XXX this *might* change to bool function
_ed25519.checkvalid(signature, digest, pub_key)
@ -74,10 +84,13 @@ def pubkey_from_privkey(privkey: Ed25519PrivateKey) -> Ed25519PublicPoint:
return Ed25519PublicPoint(_ed25519.publickey(privkey))
def sign_with_privkey(digest: bytes, privkey: Ed25519PrivateKey,
global_pubkey: Ed25519PublicPoint,
nonce: int,
global_commit: Ed25519PublicPoint) -> Ed25519Signature:
def sign_with_privkey(
digest: bytes,
privkey: Ed25519PrivateKey,
global_pubkey: Ed25519PublicPoint,
nonce: int,
global_commit: Ed25519PublicPoint,
) -> Ed25519Signature:
"""Create a CoSi signature of `digest` with the supplied private key.
This function needs to know the global public key and global commitment.
"""
@ -86,3 +99,23 @@ def sign_with_privkey(digest: bytes, privkey: Ed25519PrivateKey,
a = 2 ** (b - 2) + sum(2 ** i * _ed25519.bit(h, i) for i in range(3, b - 2))
S = (nonce + _ed25519.Hint(global_commit + global_pubkey + digest) * a) % _ed25519.l
return Ed25519Signature(_ed25519.encodeint(S))
# ====== Client functions ====== #
@expect(messages.CosiCommitment)
def commit(client, n, data):
return client.call(messages.CosiCommit(address_n=n, data=data))
@expect(messages.CosiSignature)
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,
)
)

@ -14,9 +14,12 @@
# 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>.
from __future__ import print_function
import binascii
from . import messages as proto
from mnemonic import Mnemonic
from . import messages as proto, tools
from .tools import expect
def pin_info(pin):
@ -65,7 +68,7 @@ class DebugLink(object):
# We have to encode that into encoded pin,
# because application must send back positions
# 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)
return pin_encoded
@ -134,7 +137,116 @@ class DebugLink(object):
return obj.memory
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):
self._call(proto.DebugLinkFlashErase(sector=sector), nowait=True)
@expect(proto.Success, field="message")
def load_device_by_mnemonic(
client,
mnemonic,
pin,
passphrase_protection,
label,
language="english",
skip_checksum=False,
expand=False,
):
# Convert mnemonic to UTF8 NKFD
mnemonic = Mnemonic.normalize_string(mnemonic)
# Convert mnemonic to ASCII stream
mnemonic = mnemonic.encode("utf-8")
m = Mnemonic("english")
if expand:
mnemonic = m.expand(mnemonic)
if not skip_checksum and not m.check(mnemonic):
raise ValueError("Invalid mnemonic checksum")
if client.features.initialized:
raise RuntimeError(
"Device is initialized already. Call wipe_device() and try again."
)
resp = client.call(
proto.LoadDevice(
mnemonic=mnemonic,
pin=pin,
passphrase_protection=passphrase_protection,
language=language,
label=label,
skip_checksum=skip_checksum,
)
)
client.init_device()
return resp
@expect(proto.Success, field="message")
def load_device_by_xprv(client, xprv, pin, passphrase_protection, label, language):
if client.features.initialized:
raise RuntimeError(
"Device is initialized already. Call wipe_device() and try again."
)
if xprv[0:4] not in ("xprv", "tprv"):
raise ValueError("Unknown type of xprv")
if not 100 < len(xprv) < 112: # yes this is correct in Python
raise ValueError("Invalid length of xprv")
node = proto.HDNodeType()
data = binascii.hexlify(tools.b58decode(xprv, None))
if data[90:92] != b"00":
raise ValueError("Contain invalid private key")
checksum = binascii.hexlify(tools.btc_hash(binascii.unhexlify(data[:156]))[:4])
if checksum != data[156:]:
raise ValueError("Checksum doesn't match")
# version 0488ade4
# depth 00
# fingerprint 00000000
# child_num 00000000
# chaincode 873dff81c02f525623fd1fe5167eac3a55a049de3d314bb42ee227ffed37d508
# privkey 00e8f32e723decf4051aefac8e2c93c9c5b214313817cdb01a1494b917c8436b35
# checksum e77e9d71
node.depth = int(data[8:10], 16)
node.fingerprint = int(data[10:18], 16)
node.child_num = int(data[18:26], 16)
node.chain_code = binascii.unhexlify(data[26:90])
node.private_key = binascii.unhexlify(data[92:156]) # skip 0x00 indicating privkey
resp = client.call(
proto.LoadDevice(
node=node,
pin=pin,
passphrase_protection=passphrase_protection,
language=language,
label=label,
)
)
client.init_device()
return resp
@expect(proto.Success, field="message")
def self_test(client):
if client.features.bootloader_mode is not True:
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"
)
)

@ -14,24 +14,176 @@
# 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>.
import os
import warnings
from mnemonic import Mnemonic
from . import messages as proto
from .tools import expect, session
from .transport import enumerate_devices, get_transport
class TrezorDevice:
'''
"""
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.)
Instead, please use functions from the ``trezorlib.transport`` module.
'''
"""
@classmethod
def enumerate(cls):
warnings.warn('TrezorDevice is deprecated.', DeprecationWarning)
warnings.warn("TrezorDevice is deprecated.", DeprecationWarning)
return enumerate_devices()
@classmethod
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)
@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,
):
settings = proto.ApplySettings()
if label is not None:
settings.label = label
if language:
settings.language = language
if use_passphrase is not None:
settings.use_passphrase = use_passphrase
if homescreen is not None:
settings.homescreen = homescreen
if passphrase_source is not None:
settings.passphrase_source = passphrase_source
if auto_lock_delay_ms is not None:
settings.auto_lock_delay_ms = auto_lock_delay_ms
out = client.call(settings)
client.init_device() # Reload Features
return out
@expect(proto.Success, field="message")
def apply_flags(client, flags):
out = client.call(proto.ApplyFlags(flags=flags))
client.init_device() # Reload Features
return out
@expect(proto.Success, field="message")
def change_pin(client, remove=False):
ret = client.call(proto.ChangePin(remove=remove))
client.init_device() # Re-read features
return ret
@expect(proto.Success, field="message")
def set_u2f_counter(client, u2f_counter):
ret = client.call(proto.SetU2FCounter(u2f_counter=u2f_counter))
return ret
@expect(proto.Success, field="message")
def wipe(client):
ret = client.call(proto.WipeDevice())
client.init_device()
return ret
@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,
):
if client.features.initialized and not dry_run:
raise RuntimeError(
"Device is initialized already. Call wipe_device() and try again."
)
if word_count not in (12, 18, 24):
raise ValueError("Invalid word count. Use 12/18/24")
client.recovery_matrix_first_pass = True
client.expand = expand
if client.expand:
# optimization to load the wordlist once, instead of for each recovery word
client.mnemonic_wordlist = Mnemonic("english")
res = client.call(
proto.RecoveryDevice(
word_count=int(word_count),
passphrase_protection=bool(passphrase_protection),
pin_protection=bool(pin_protection),
label=label,
language=language,
enforce_wordlist=True,
type=type,
dry_run=dry_run,
)
)
client.init_device()
return res
@expect(proto.Success, field="message")
@session
def reset(
client,
display_random,
strength,
passphrase_protection,
pin_protection,
label,
language,
u2f_counter=0,
skip_backup=False,
):
if client.features.initialized:
raise RuntimeError(
"Device is initialized already. Call wipe_device() and try again."
)
# Begin with device reset workflow
msg = proto.ResetDevice(
display_random=display_random,
strength=strength,
passphrase_protection=bool(passphrase_protection),
pin_protection=bool(pin_protection),
language=language,
label=label,
u2f_counter=u2f_counter,
skip_backup=bool(skip_backup),
)
resp = client.call(msg)
if not isinstance(resp, proto.EntropyRequest):
raise RuntimeError("Invalid response, expected EntropyRequest")
external_entropy = os.urandom(32)
# LOG.debug("Computer generated entropy: " + binascii.hexlify(external_entropy).decode())
ret = client.call(proto.EntropyAck(entropy=external_entropy))
client.init_device()
return ret
@expect(proto.Success, field="message")
def backup(client):
ret = client.call(proto.BackupDevice())
return ret

@ -0,0 +1,85 @@
from . import messages as proto
from .tools import CallException, expect, normalize_nfc, session
def int_to_big_endian(value):
return value.to_bytes((value.bit_length() + 7) // 8, "big")
# ====== Client functions ====== #
@expect(proto.EthereumAddress, field="address")
def get_address(client, n, show_display=False, multisig=None):
return client.call(proto.EthereumGetAddress(address_n=n, show_display=show_display))
@session
def sign_tx(
client,
n,
nonce,
gas_price,
gas_limit,
to,
value,
data=None,
chain_id=None,
tx_type=None,
):
msg = proto.EthereumSignTx(
address_n=n,
nonce=int_to_big_endian(nonce),
gas_price=int_to_big_endian(gas_price),
gas_limit=int_to_big_endian(gas_limit),
value=int_to_big_endian(value),
)
if to:
msg.to = to
if data:
msg.data_length = len(data)
data, chunk = data[1024:], data[:1024]
msg.data_initial_chunk = chunk
if chain_id:
msg.chain_id = chain_id
if tx_type is not None:
msg.tx_type = tx_type
response = client.call(msg)
while response.data_length is not None:
data_length = response.data_length
data, chunk = data[data_length:], data[:data_length]
response = client.call(proto.EthereumTxAck(data_chunk=chunk))
# https://github.com/trezor/trezor-core/pull/311
# only signature bit returned. recalculate signature_v
if response.signature_v <= 1:
response.signature_v += 2 * chain_id + 35
return response.signature_v, response.signature_r, response.signature_s
@expect(proto.EthereumMessageSignature)
def sign_message(client, n, message):
message = normalize_nfc(message)
return client.call(proto.EthereumSignMessage(address_n=n, message=message))
def verify_message(client, address, signature, message):
message = normalize_nfc(message)
try:
resp = client.call(
proto.EthereumVerifyMessage(
address=address, signature=signature, message=message
)
)
except CallException as e:
resp = e
if isinstance(resp, proto.Success):
return True
return False

@ -0,0 +1,199 @@
import binascii
import construct as c
import pyblake2
from . import cosi, messages as proto, tools
def bytes_not(data):
return bytes(~b & 0xff for b in data)
# fmt: off
Toif = c.Struct(
"magic" / c.Const(b"TOI"),
"format" / c.Enum(c.Byte, full_color=b"f", grayscale=b"g"),
"width" / c.Int16ul,
"height" / c.Int16ul,
"data" / c.Prefixed(c.Int32ul, c.GreedyBytes),
)
VendorTrust = c.Transformed(c.BitStruct(
"reserved" / c.Padding(9),
"show_vendor_string" / c.Flag,
"require_user_click" / c.Flag,
"red_background" / c.Flag,
"delay" / c.BitsInteger(4),
), bytes_not, 2, bytes_not, 2)
VendorHeader = c.Struct(
"_start_offset" / c.Tell,
"magic" / c.Const(b"TRZV"),
"_header_len" / c.Padding(4),
"expiry" / c.Int32ul,
"version" / c.Struct(
"major" / c.Int8ul,
"minor" / c.Int8ul,
),
"vendor_sigs_required" / c.Int8ul,
"vendor_sigs_n" / c.Rebuild(c.Int8ul, c.len_(c.this.pubkeys)),
"vendor_trust" / VendorTrust,
"reserved" / c.Padding(14),
"pubkeys" / c.Bytes(32)[c.this.vendor_sigs_n],
"vendor_string" / c.Aligned(4, c.PascalString(c.Int8ul, "utf-8")),
"vendor_image" / Toif,
"_data_end_offset" / c.Tell,
c.Padding(-(c.this._data_end_offset + 65) % 512),
"sigmask" / c.Byte,
"signature" / c.Bytes(64),
"_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)
),
)
VersionLong = c.Struct(
"major" / c.Int8ul,
"minor" / c.Int8ul,
"patch" / c.Int8ul,
"build" / c.Int8ul,
)
FirmwareHeader = c.Struct(
"_start_offset" / c.Tell,
"magic" / c.Const(b"TRZF"),
"_header_len" / c.Padding(4),
"expiry" / c.Int32ul,
"code_length" / c.Rebuild(
c.Int32ul,
lambda this:
len(this._.code) if "code" in this._
else (this.code_length or 0)),
"version" / VersionLong,
"fix_version" / VersionLong,
"reserved" / c.Padding(8),
"hashes" / c.Bytes(32)[16],
"reserved" / c.Padding(415),
"sigmask" / c.Byte,
"signature" / c.Bytes(64),
"_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)
),
)
Firmware = c.Struct(
"vendor_header" / VendorHeader,
"firmware_header" / FirmwareHeader,
"code" / c.Bytes(c.this.firmware_header.code_length),
c.Terminated,
)
# fmt: on
def validate_firmware(filename):
with open(filename, "rb") as f:
data = f.read()
if data[:6] == b"54525a":
data = binascii.unhexlify(data)
try:
fw = Firmware.parse(data)
except Exception as e:
raise ValueError("Invalid firmware image format") from e
vendor = fw.vendor_header
header = fw.firmware_header
print(
"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
stripped_header = header.copy()
stripped_header.sigmask = 0
stripped_header.signature = b"\0" * 64
header_bytes = FirmwareHeader.build(stripped_header)
digest = pyblake2.blake2s(header_bytes).digest()
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)
)
try:
cosi.verify(header.signature, digest, global_pk)
print("Signature OK")
except Exception:
print("Signature FAILED")
raise
# ====== Client functions ====== #
@tools.session
def update(client, fp):
if client.features.bootloader_mode is False:
raise RuntimeError("Device must be in bootloader mode")
data = fp.read()
resp = client.call(proto.FirmwareErase(length=len(data)))
if isinstance(resp, proto.Failure) and resp.code == proto.FailureType.FirmwareError:
return False
# TREZORv1 method
if isinstance(resp, proto.Success):
# fingerprint = hashlib.sha256(data[256:]).hexdigest()
# LOG.debug("Firmware fingerprint: " + fingerprint)
resp = client.call(proto.FirmwareUpload(payload=data))
if isinstance(resp, proto.Success):
return True
elif (
isinstance(resp, proto.Failure)
and resp.code == proto.FailureType.FirmwareError
):
return False
raise RuntimeError("Unexpected result %s" % resp)
# TREZORv2 method
if isinstance(resp, proto.FirmwareRequest):
import pyblake2
while True:
payload = data[resp.offset : resp.offset + resp.length]
digest = pyblake2.blake2s(payload).digest()
resp = client.call(proto.FirmwareUpload(payload=payload, hash=digest))
if isinstance(resp, proto.FirmwareRequest):
continue
elif isinstance(resp, proto.Success):
return True
elif (
isinstance(resp, proto.Failure)
and resp.code == proto.FailureType.FirmwareError
):
return False
raise RuntimeError("Unexpected result %s" % resp)
raise RuntimeError("Unexpected message %s" % resp)

@ -0,0 +1,43 @@
from . import messages as proto
from .protobuf import dict_to_proto
from .tools import CallException, dict_from_camelcase, expect, normalize_nfc
@expect(proto.LiskAddress, field="address")
def get_address(client, n, show_display=False):
return client.call(proto.LiskGetAddress(address_n=n, show_display=show_display))
@expect(proto.LiskPublicKey)
def get_public_key(client, n, show_display=False):
return client.call(proto.LiskGetPublicKey(address_n=n, show_display=show_display))
@expect(proto.LiskMessageSignature)
def sign_message(client, n, message):
message = normalize_nfc(message)
return client.call(proto.LiskSignMessage(address_n=n, message=message))
def verify_message(client, pubkey, signature, message):
message = normalize_nfc(message)
try:
resp = client.call(
proto.LiskVerifyMessage(
signature=signature, public_key=pubkey, message=message
)
)
except CallException as e:
resp = e
return isinstance(resp, proto.Success)
RENAMES = {"lifetime": "life_time", "keysgroup": "keys_group"}
@expect(proto.LiskSignedTx)
def sign_tx(client, n, transaction):
transaction = dict_from_camelcase(transaction, renames=RENAMES)
msg = dict_to_proto(proto.LiskTransactionCommon, transaction)
return client.call(proto.LiskSignTx(address_n=n, transaction=msg))

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

@ -15,7 +15,6 @@
# If not, see <https://www.gnu.org/licenses/lgpl-3.0.html>.
from . import messages
from . import protobuf
map_type_to_class = {}
map_class_to_type = {}
@ -23,24 +22,30 @@ map_class_to_type = {}
def build_map():
for msg_name in dir(messages.MessageType):
if msg_name.startswith('__'):
if msg_name.startswith("__"):
continue
try:
msg_class = getattr(messages, msg_name)
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):
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)
def register_message(msg_class):
if msg_class.MESSAGE_WIRE_TYPE in map_type_to_class:
raise Exception("Message for wire type %s is already registered by %s" %
(msg_class.MESSAGE_WIRE_TYPE, get_class(msg_class.MESSAGE_WIRE_TYPE)))
raise Exception(
"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_type_to_class[msg_class.MESSAGE_WIRE_TYPE] = msg_class

@ -0,0 +1,66 @@
from . import messages as proto
from .tools import expect
@expect(proto.Entropy, field="entropy")
def get_entropy(client, size):
return client.call(proto.GetEntropy(size=size))
@expect(proto.SignedIdentity)
def sign_identity(
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)
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,
)
)
@expect(proto.CipheredKeyValue, field="value")
def encrypt_keyvalue(
client, n, key, value, ask_on_encrypt=True, ask_on_decrypt=True, iv=b""
):
return client.call(
proto.CipherKeyValue(
address_n=n,
key=key,
value=value,
encrypt=True,
ask_on_encrypt=ask_on_encrypt,
ask_on_decrypt=ask_on_decrypt,
iv=iv,
)
)
@expect(proto.CipheredKeyValue, field="value")
def decrypt_keyvalue(
client, n, key, value, ask_on_encrypt=True, ask_on_decrypt=True, iv=b""
):
return client.call(
proto.CipherKeyValue(
address_n=n,
key=key,
value=value,
encrypt=False,
ask_on_encrypt=ask_on_encrypt,
ask_on_decrypt=ask_on_decrypt,
iv=iv,
)
)

@ -16,7 +16,9 @@
import binascii
import json
from . import messages as proto
from .tools import CallException, expect
TYPE_TRANSACTION_TRANSFER = 0x0101
TYPE_IMPORTANCE_TRANSFER = 0x0801
@ -53,21 +55,27 @@ def create_transfer(transaction):
msg.public_key = binascii.unhexlify(transaction["message"]["publicKey"])
if "mosaics" in transaction:
msg.mosaics = [proto.NEMMosaic(
namespace=mosaic["mosaicId"]["namespaceId"],
mosaic=mosaic["mosaicId"]["name"],
quantity=mosaic["quantity"],
) for mosaic in transaction["mosaics"]]
msg.mosaics = [
proto.NEMMosaic(
namespace=mosaic["mosaicId"]["namespaceId"],
mosaic=mosaic["mosaicId"]["name"],
quantity=mosaic["quantity"],
)
for mosaic in transaction["mosaics"]
]
return msg
def create_aggregate_modification(transactions):
msg = proto.NEMAggregateModification()
msg.modifications = [proto.NEMCosignatoryModification(
type=modification["modificationType"],
public_key=binascii.unhexlify(modification["cosignatoryAccount"]),
) for modification in transactions["modifications"]]
msg.modifications = [
proto.NEMCosignatoryModification(
type=modification["modificationType"],
public_key=binascii.unhexlify(modification["cosignatoryAccount"]),
)
for modification in transactions["modifications"]
]
if "minCosignatories" in transactions:
msg.relative_change = transactions["minCosignatories"]["relativeChange"]
@ -137,17 +145,7 @@ def create_importance_transfer(transaction):
return msg
def create_sign_tx(transaction):
msg = proto.NEMSignTx()
msg.transaction = create_transaction_common(transaction)
msg.cosigning = (transaction["type"] == TYPE_MULTISIG_SIGNATURE)
if transaction["type"] in (TYPE_MULTISIG_SIGNATURE, TYPE_MULTISIG):
transaction = transaction["otherTrans"]
msg.multisig = create_transaction_common(transaction)
elif "otherTrans" in transaction:
raise ValueError("Transaction does not support inner transaction")
def fill_transaction_by_type(msg, transaction):
if transaction["type"] == TYPE_TRANSACTION_TRANSFER:
msg.transfer = create_transfer(transaction)
elif transaction["type"] == TYPE_AGGREGATE_MODIFICATION:
@ -163,4 +161,41 @@ def create_sign_tx(transaction):
else:
raise ValueError("Unknown transaction type")
def create_sign_tx(transaction):
msg = proto.NEMSignTx()
msg.transaction = create_transaction_common(transaction)
msg.cosigning = transaction["type"] == TYPE_MULTISIG_SIGNATURE
if transaction["type"] in (TYPE_MULTISIG_SIGNATURE, TYPE_MULTISIG):
other_trans = transaction["otherTrans"]
msg.multisig = create_transaction_common(other_trans)
fill_transaction_by_type(msg, other_trans)
elif "otherTrans" in transaction:
raise ValueError("Transaction does not support inner transaction")
else:
fill_transaction_by_type(msg, transaction)
return msg
# ====== Client functions ====== #
@expect(proto.NEMAddress, field="address")
def get_address(client, n, network, show_display=False):
return client.call(
proto.NEMGetAddress(address_n=n, network=network, show_display=show_display)
)
@expect(proto.NEMSignedTx)
def sign_tx(client, n, transaction):
try:
msg = create_sign_tx(transaction)
except ValueError as e:
raise CallException(e.args)
assert msg.transaction is not None
msg.transaction.address_n = n
return client.call(msg)

@ -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.
# So we have to branch on whether the number is negative.
def sint_to_uint(sint):
res = sint << 1
if sint < 0:
@ -134,8 +135,7 @@ class MessageType:
self._fill_missing()
def __eq__(self, rhs):
return (self.__class__ is rhs.__class__ and
self.__dict__ == rhs.__dict__)
return self.__class__ is rhs.__class__ and self.__dict__ == rhs.__dict__
def __repr__(self):
d = {}
@ -143,16 +143,16 @@ class MessageType:
if value is None or value == []:
continue
d[key] = value
return '<%s: %s>' % (self.__class__.__name__, d)
return "<%s: %s>" % (self.__class__.__name__, d)
def __iter__(self):
return self.__dict__.__iter__()
def __getattr__(self, attr):
if attr.startswith('_add_'):
if attr.startswith("_add_"):
return self._additem(attr[5:])
if attr.startswith('_extend_'):
if attr.startswith("_extend_"):
return self._extenditem(attr[8:])
raise AttributeError(attr)
@ -208,7 +208,6 @@ class MessageType:
class LimitedReader:
def __init__(self, reader, limit):
self.reader = reader
self.limit = limit
@ -223,7 +222,6 @@ class LimitedReader:
class CountingWriter:
def __init__(self):
self.size = 0
@ -331,7 +329,7 @@ def dump_message(writer, msg):
elif ftype is UnicodeType:
if not isinstance(svalue, bytes):
svalue = svalue.encode('utf-8')
svalue = svalue.encode("utf-8")
dump_uvarint(writer, len(svalue))
writer.write(svalue)
@ -346,12 +344,13 @@ def dump_message(writer, msg):
raise TypeError
def format_message(pb: MessageType,
indent: int = 0,
sep: str = ' ' * 4,
truncate_after: Optional[int] = 256,
truncate_to: Optional[int] = 64) -> str:
def format_message(
pb: MessageType,
indent: int = 0,
sep: str = " " * 4,
truncate_after: Optional[int] = 256,
truncate_to: Optional[int] = 64,
) -> str:
def mostly_printable(bytes):
if not bytes:
return True
@ -369,33 +368,80 @@ def format_message(pb: MessageType,
return repr(value)
# long list, one line per entry
lines = ['[', level + ']']
lines[1:1] = [leadin + pformat_value(x, indent + 1) + ',' for x in value]
return '\n'.join(lines)
lines = ["[", level + "]"]
lines[1:1] = [leadin + pformat_value(x, indent + 1) + "," for x in value]
return "\n".join(lines)
if isinstance(value, dict):
lines = ['{']
lines = ["{"]
for key, val in sorted(value.items()):
if val is None or val == []:
continue
lines.append(leadin + key + ': ' + pformat_value(val, indent + 1) + ',')
lines.append(level + '}')
return '\n'.join(lines)
lines.append(leadin + key + ": " + pformat_value(val, indent + 1) + ",")
lines.append(level + "}")
return "\n".join(lines)
if isinstance(value, (bytes, bytearray)):
length = len(value)
suffix = ''
suffix = ""
if truncate_after and length > truncate_after:
suffix = '...'
value = value[:truncate_to or 0]
suffix = "..."
value = value[: truncate_to or 0]
if mostly_printable(value):
output = repr(value)
else:
output = '0x' + binascii.hexlify(value).decode('ascii')
return '{} bytes {}{}'.format(length, output, suffix)
output = "0x" + binascii.hexlify(value).decode("ascii")
return "{} bytes {}{}".format(length, output, suffix)
return repr(value)
return '{name} ({size} bytes) {content}'.format(
return "{name} ({size} bytes) {content}".format(
name=pb.__class__.__name__,
size=pb.ByteSize(),
content=pformat_value(pb.__dict__, indent)
content=pformat_value(pb.__dict__, indent),
)
def value_to_proto(ftype, value):
if issubclass(ftype, MessageType):
raise TypeError("value_to_proto only converts simple values")
if ftype in (UVarintType, SVarintType):
return int(value)
if ftype is BoolType:
return bool(value)
if ftype is UnicodeType:
return str(value)
if ftype is BytesType:
if isinstance(value, str):
return binascii.unhexlify(value)
elif isinstance(value, bytes):
return value
else:
raise TypeError("can't convert {} value to bytes".format(type(value)))
def dict_to_proto(message_type, d):
params = {}
for fname, ftype, fflags in message_type.FIELDS.values():
repeated = fflags & FLAG_REPEATED
value = d.get(fname)
if value is None:
continue
if not repeated:
value = [value]
if issubclass(ftype, MessageType):
function = dict_to_proto
else:
function = value_to_proto
newvalue = [function(ftype, v) for v in value]
if not repeated:
newvalue = newvalue[0]
params[fname] = newvalue
return message_type(**params)

@ -14,15 +14,12 @@
# 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>.
from __future__ import absolute_import
from io import BytesIO
import logging
import struct
from typing import Tuple, Type
from io import BytesIO
from typing import Tuple
from . import mapping
from . import protobuf
from . import mapping, protobuf
from .transport import Transport
REPLEN = 64
@ -31,7 +28,6 @@ LOG = logging.getLogger(__name__)
class ProtocolV1:
def session_begin(self, transport: Transport) -> None:
pass
@ -39,8 +35,10 @@ class ProtocolV1:
pass
def write(self, transport: Transport, msg: protobuf.MessageType) -> None:
LOG.debug("sending message: {}".format(msg.__class__.__name__),
extra={'protobuf': msg})
LOG.debug(
"sending message: {}".format(msg.__class__.__name__),
extra={"protobuf": msg},
)
data = BytesIO()
protobuf.dump_message(data, msg)
ser = data.getvalue()
@ -49,8 +47,8 @@ class ProtocolV1:
while data:
# Report ID, data padded to 63 bytes
chunk = b'?' + data[:REPLEN - 1]
chunk = chunk.ljust(REPLEN, b'\x00')
chunk = b"?" + data[: REPLEN - 1]
chunk = chunk.ljust(REPLEN, b"\x00")
transport.write_chunk(chunk)
data = data[63:]
@ -69,23 +67,25 @@ class ProtocolV1:
# Parse to protobuf
msg = protobuf.load_message(data, mapping.get_class(msg_type))
LOG.debug("received message: {}".format(msg.__class__.__name__),
extra={'protobuf': msg})
LOG.debug(
"received message: {}".format(msg.__class__.__name__),
extra={"protobuf": msg},
)
return msg
def parse_first(self, chunk: bytes) -> Tuple[int, int, bytes]:
if chunk[:3] != b'?##':
raise RuntimeError('Unexpected magic characters')
if chunk[:3] != b"?##":
raise RuntimeError("Unexpected magic characters")
try:
headerlen = struct.calcsize('>HL')
msg_type, datalen = struct.unpack('>HL', chunk[3:3 + headerlen])
except:
raise RuntimeError('Cannot parse header')
headerlen = struct.calcsize(">HL")
msg_type, datalen = struct.unpack(">HL", chunk[3 : 3 + headerlen])
except Exception:
raise RuntimeError("Cannot parse header")
data = chunk[3 + headerlen:]
data = chunk[3 + headerlen :]
return msg_type, datalen, data
def parse_next(self, chunk: bytes) -> bytes:
if chunk[:1] != b'?':
raise RuntimeError('Unexpected magic characters')
if chunk[:1] != b"?":
raise RuntimeError("Unexpected magic characters")
return chunk[1:]

@ -14,15 +14,12 @@
# 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>.
from __future__ import absolute_import
from io import BytesIO
import logging
import struct
from io import BytesIO
from typing import Tuple
from . import mapping
from . import protobuf
from . import mapping, protobuf
from .transport import Transport
REPLEN = 64
@ -31,13 +28,12 @@ LOG = logging.getLogger(__name__)
class ProtocolV2:
def __init__(self) -> None:
self.session = None
def session_begin(self, transport: Transport) -> None:
chunk = struct.pack('>B', 0x03)
chunk = chunk.ljust(REPLEN, b'\x00')
chunk = struct.pack(">B", 0x03)
chunk = chunk.ljust(REPLEN, b"\x00")
transport.write_chunk(chunk)
resp = transport.read_chunk()
self.session = self.parse_session_open(resp)
@ -46,46 +42,50 @@ class ProtocolV2:
def session_end(self, transport: Transport) -> None:
if not self.session:
return
chunk = struct.pack('>BL', 0x04, self.session)
chunk = chunk.ljust(REPLEN, b'\x00')
chunk = struct.pack(">BL", 0x04, self.session)
chunk = chunk.ljust(REPLEN, b"\x00")
transport.write_chunk(chunk)
resp = transport.read_chunk()
(magic, ) = struct.unpack('>B', resp[:1])
(magic,) = struct.unpack(">B", resp[:1])
if magic != 0x04:
raise RuntimeError('Expected session close')
raise RuntimeError("Expected session close")
LOG.debug("[session {}] session ended".format(self.session))
self.session = None
def write(self, transport: Transport, msg: protobuf.MessageType) -> None:
if not self.session:
raise RuntimeError('Missing session for v2 protocol')
LOG.debug("[session {}] sending message: {}".format(self.session, msg.__class__.__name__),
extra={'protobuf': msg})
raise RuntimeError("Missing session for v2 protocol")
LOG.debug(
"[session {}] sending message: {}".format(
self.session, msg.__class__.__name__
),
extra={"protobuf": msg},
)
# Serialize whole message
data = BytesIO()
protobuf.dump_message(data, msg)
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
seq = -1
# Write it out
while data:
if seq < 0:
repheader = struct.pack('>BL', 0x01, self.session)
repheader = struct.pack(">BL", 0x01, self.session)
else:
repheader = struct.pack('>BLL', 0x02, self.session, seq)
repheader = struct.pack(">BLL", 0x02, self.session, seq)
datalen = REPLEN - len(repheader)
chunk = repheader + data[:datalen]
chunk = chunk.ljust(REPLEN, b'\x00')
chunk = chunk.ljust(REPLEN, b"\x00")
transport.write_chunk(chunk)
data = data[datalen:]
seq += 1
def read(self, transport: Transport) -> protobuf.MessageType:
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
chunk = transport.read_chunk()
@ -102,40 +102,46 @@ class ProtocolV2:
# Parse to protobuf
msg = protobuf.load_message(data, mapping.get_class(msg_type))
LOG.debug("[session {}] received message: {}".format(self.session, msg.__class__.__name__),
extra={'protobuf': msg})
LOG.debug(
"[session {}] received message: {}".format(
self.session, msg.__class__.__name__
),
extra={"protobuf": msg},
)
return msg
def parse_first(self, chunk: bytes) -> Tuple[int, int, bytes]:
try:
headerlen = struct.calcsize('>BLLL')
magic, session, msg_type, datalen = struct.unpack('>BLLL', chunk[:headerlen])
except:
raise RuntimeError('Cannot parse header')
headerlen = struct.calcsize(">BLLL")
magic, session, msg_type, datalen = struct.unpack(
">BLLL", chunk[:headerlen]
)
except Exception:
raise RuntimeError("Cannot parse header")
if magic != 0x01:
raise RuntimeError('Unexpected magic character')
raise RuntimeError("Unexpected magic character")
if session != self.session:
raise RuntimeError('Session id mismatch')
raise RuntimeError("Session id mismatch")
return msg_type, datalen, chunk[headerlen:]
def parse_next(self, chunk: bytes) -> bytes:
try:
headerlen = struct.calcsize('>BLL')
magic, session, sequence = struct.unpack('>BLL', chunk[:headerlen])
except:
raise RuntimeError('Cannot parse header')
headerlen = struct.calcsize(">BLL")
magic, session, sequence = struct.unpack(">BLL", chunk[:headerlen])
except Exception:
raise RuntimeError("Cannot parse header")
if magic != 0x02:
raise RuntimeError('Unexpected magic characters')
raise RuntimeError("Unexpected magic characters")
if session != self.session:
raise RuntimeError('Session id mismatch')
raise RuntimeError("Session id mismatch")
return chunk[headerlen:]
def parse_session_open(self, chunk: bytes) -> int:
try:
headerlen = struct.calcsize('>BL')
magic, session = struct.unpack('>BL', chunk[:headerlen])
except:
raise RuntimeError('Cannot parse header')
headerlen = struct.calcsize(">BL")
magic, session = struct.unpack(">BL", chunk[:headerlen])
except Exception:
raise RuntimeError("Cannot parse header")
if magic != 0x03:
raise RuntimeError('Unexpected magic character')
raise RuntimeError("Unexpected magic character")
return session

@ -14,17 +14,35 @@
# 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>.
from __future__ import print_function
import sys
import math
import sys
try:
from PyQt4.QtGui import (QPushButton, QLineEdit, QSizePolicy, QRegExpValidator, QLabel,
QApplication, QWidget, QGridLayout, QVBoxLayout, QHBoxLayout)
from PyQt4.QtGui import (
QPushButton,
QLineEdit,
QSizePolicy,
QRegExpValidator,
QLabel,
QApplication,
QWidget,
QGridLayout,
QVBoxLayout,
QHBoxLayout,
)
from PyQt4.QtCore import QObject, SIGNAL, QRegExp, Qt, QT_VERSION_STR
except:
from PyQt5.QtWidgets import (QPushButton, QLineEdit, QSizePolicy, QLabel,
QApplication, QWidget, QGridLayout, QVBoxLayout, QHBoxLayout)
except ImportError:
from PyQt5.QtWidgets import (
QPushButton,
QLineEdit,
QSizePolicy,
QLabel,
QApplication,
QWidget,
QGridLayout,
QVBoxLayout,
QHBoxLayout,
)
from PyQt5.QtGui import QRegExpValidator
from PyQt5.QtCore import QRegExp, Qt
from PyQt5.Qt import QT_VERSION_STR
@ -32,16 +50,16 @@ except:
class PinButton(QPushButton):
def __init__(self, password, encoded_value):
super(PinButton, self).__init__('?')
super(PinButton, self).__init__("?")
self.password = password
self.encoded_value = encoded_value
if QT_VERSION_STR >= '5':
if QT_VERSION_STR >= "5":
self.clicked.connect(self._pressed)
elif QT_VERSION_STR >= '4':
QObject.connect(self, SIGNAL('clicked()'), self._pressed)
elif QT_VERSION_STR >= "4":
QObject.connect(self, SIGNAL("clicked()"), self._pressed)
else:
raise RuntimeError('Unsupported Qt version')
raise RuntimeError("Unsupported Qt version")
def _pressed(self):
self.password.setText(self.password.text() + str(self.encoded_value))
@ -49,26 +67,29 @@ class PinButton(QPushButton):
class PinMatrixWidget(QWidget):
'''
"""
Displays widget with nine blank buttons and password box.
Encodes button clicks into sequence of numbers for passing
into PinAck messages of TREZOR.
show_strength=True may be useful for entering new PIN
'''
"""
def __init__(self, show_strength=True, parent=None):
super(PinMatrixWidget, self).__init__(parent)
self.password = QLineEdit()
self.password.setValidator(QRegExpValidator(QRegExp('[1-9]+'), None))
self.password.setValidator(QRegExpValidator(QRegExp("[1-9]+"), None))
self.password.setEchoMode(QLineEdit.Password)
if QT_VERSION_STR >= '5':
if QT_VERSION_STR >= "5":
self.password.textChanged.connect(self._password_changed)
elif QT_VERSION_STR >= '4':
QObject.connect(self.password, SIGNAL('textChanged(QString)'), self._password_changed)
elif QT_VERSION_STR >= "4":
QObject.connect(
self.password, SIGNAL("textChanged(QString)"), self._password_changed
)
else:
raise RuntimeError('Unsupported Qt version')
raise RuntimeError("Unsupported Qt version")
self.strength = QLabel()
self.strength.setMinimumWidth(75)
@ -96,16 +117,16 @@ class PinMatrixWidget(QWidget):
def _set_strength(self, strength):
if strength < 3000:
self.strength.setText('weak')
self.strength.setText("weak")
self.strength.setStyleSheet("QLabel { color : #d00; }")
elif strength < 60000:
self.strength.setText('fine')
self.strength.setText("fine")
self.strength.setStyleSheet("QLabel { color : #db0; }")
elif strength < 360000:
self.strength.setText('strong')
self.strength.setText("strong")
self.strength.setStyleSheet("QLabel { color : #0a0; }")
else:
self.strength.setText('ULTIMATE')
self.strength.setText("ULTIMATE")
self.strength.setStyleSheet("QLabel { color : #000; font-weight: bold;}")
def _password_changed(self, password):
@ -120,10 +141,10 @@ class PinMatrixWidget(QWidget):
return self.password.text()
if __name__ == '__main__':
'''
if __name__ == "__main__":
"""
Demo application showing PinMatrix widget in action
'''
"""
app = QApplication(sys.argv)
matrix = PinMatrixWidget()
@ -133,13 +154,13 @@ if __name__ == '__main__':
print("Possible button combinations:", matrix.get_strength())
sys.exit()
ok = QPushButton('OK')
if QT_VERSION_STR >= '5':
ok = QPushButton("OK")
if QT_VERSION_STR >= "5":
ok.clicked.connect(clicked)
elif QT_VERSION_STR >= '4':
QObject.connect(ok, SIGNAL('clicked()'), clicked)
elif QT_VERSION_STR >= "4":
QObject.connect(ok, SIGNAL("clicked()"), clicked)
else:
raise RuntimeError('Unsupported Qt version')
raise RuntimeError("Unsupported Qt version")
vbox = QVBoxLayout()
vbox.addWidget(matrix)

@ -14,21 +14,19 @@
# 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>.
import base64
import struct
from . import messages
from . import tools
from .client import field
from .client import expect
from .protobuf import dict_to_proto
from .tools import dict_from_camelcase, expect
REQUIRED_FIELDS = ("Fee", "Sequence", "TransactionType", "Amount", "Destination")
@field('address')
@expect(messages.RippleAddress)
@expect(messages.RippleAddress, field="address")
def get_address(client, address_n, show_display=False):
return client.call(
messages.RippleGetAddress(
address_n=address_n, show_display=show_display))
messages.RippleGetAddress(address_n=address_n, show_display=show_display)
)
@expect(messages.RippleSignedTx)
@ -38,22 +36,10 @@ def sign_tx(client, address_n, msg: messages.RippleSignTx):
def create_sign_tx_msg(transaction) -> messages.RippleSignTx:
if not all(transaction.get(k) for k in ("Fee", "Sequence", "TransactionType", "Amount", "Destination")):
raise ValueError("Some of the required fields missing (Fee, Sequence, TransactionType, Amount, Destination")
if not all(transaction.get(k) for k in REQUIRED_FIELDS):
raise ValueError("Some of the required fields missing")
if transaction["TransactionType"] != "Payment":
raise ValueError("Only Payment transaction type is supported")
return messages.RippleSignTx(
fee=transaction.get("Fee"),
sequence=transaction.get("Sequence"),
flags=transaction.get("Flags"),
last_ledger_sequence=transaction.get("LastLedgerSequence"),
payment=_create_payment(transaction),
)
def _create_payment(transaction) -> messages.RipplePayment:
return messages.RipplePayment(
amount=transaction.get("Amount"),
destination=transaction.get("Destination")
)
converted = dict_from_camelcase(transaction)
return dict_to_proto(messages.RippleSignTx, converted)

@ -19,6 +19,7 @@ import struct
import xdrlib
from . import messages
from .tools import CallException, expect
# Memo types
MEMO_TYPE_NONE = 0
@ -49,6 +50,7 @@ OP_BUMP_SEQUENCE = 11
DEFAULT_BIP32_PATH = "m/44h/148h/0h"
# Stellar's BIP32 differs to Bitcoin's see https://github.com/stellar/stellar-protocol/blob/master/ecosystem/sep-0005.md
DEFAULT_NETWORK_PASSPHRASE = "Public Global Stellar Network ; September 2015"
def address_from_public_key(pk_bytes):
@ -63,7 +65,7 @@ def address_from_public_key(pk_bytes):
# checksum
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):
@ -90,14 +92,21 @@ def parse_transaction_bytes(tx_bytes):
# Timebounds is an optional field
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_end = unpacker.unpack_uhyper()
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:
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
tx.memo_type = unpacker.unpack_uint()
@ -115,7 +124,7 @@ def parse_transaction_bytes(tx_bytes):
tx.num_operations = unpacker.unpack_uint()
operations = []
for i in range(tx.num_operations):
for _ in range(tx.num_operations):
operations.append(_parse_operation_bytes(unpacker))
return tx, operations
@ -138,7 +147,7 @@ def _parse_operation_bytes(unpacker):
return messages.StellarCreateAccountOp(
source_account=source_account,
new_account=_xdr_read_address(unpacker),
starting_balance=unpacker.unpack_hyper()
starting_balance=unpacker.unpack_hyper(),
)
if type == OP_PAYMENT:
@ -146,7 +155,7 @@ def _parse_operation_bytes(unpacker):
source_account=source_account,
destination_account=_xdr_read_address(unpacker),
asset=_xdr_read_asset(unpacker),
amount=unpacker.unpack_hyper()
amount=unpacker.unpack_hyper(),
)
if type == OP_PATH_PAYMENT:
@ -157,11 +166,11 @@ def _parse_operation_bytes(unpacker):
destination_account=_xdr_read_address(unpacker),
destination_asset=_xdr_read_asset(unpacker),
destination_amount=unpacker.unpack_hyper(),
paths=[]
paths=[],
)
num_paths = unpacker.unpack_uint()
for i in range(num_paths):
for _ in range(num_paths):
op.paths.append(_xdr_read_asset(unpacker))
return op
@ -174,7 +183,7 @@ def _parse_operation_bytes(unpacker):
amount=unpacker.unpack_hyper(),
price_n=unpacker.unpack_uint(),
price_d=unpacker.unpack_uint(),
offer_id=unpacker.unpack_uhyper()
offer_id=unpacker.unpack_uhyper(),
)
if type == OP_CREATE_PASSIVE_OFFER:
@ -184,13 +193,11 @@ def _parse_operation_bytes(unpacker):
buying_asset=_xdr_read_asset(unpacker),
amount=unpacker.unpack_hyper(),
price_n=unpacker.unpack_uint(),
price_d=unpacker.unpack_uint()
price_d=unpacker.unpack_uint(),
)
if type == OP_SET_OPTIONS:
op = messages.StellarSetOptionsOp(
source_account=source_account
)
op = messages.StellarSetOptionsOp(source_account=source_account)
# Inflation destination
if unpacker.unpack_bool():
@ -236,14 +243,14 @@ def _parse_operation_bytes(unpacker):
return messages.StellarChangeTrustOp(
source_account=source_account,
asset=_xdr_read_asset(unpacker),
limit=unpacker.unpack_uhyper()
limit=unpacker.unpack_uhyper(),
)
if type == OP_ALLOW_TRUST:
op = messages.StellarAllowTrustOp(
source_account=source_account,
trusted_account=_xdr_read_address(unpacker),
asset_type=unpacker.unpack_uint()
asset_type=unpacker.unpack_uint(),
)
if op.asset_type == ASSET_TYPE_ALPHA4:
@ -258,15 +265,14 @@ def _parse_operation_bytes(unpacker):
if type == OP_ACCOUNT_MERGE:
return messages.StellarAccountMergeOp(
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
if type == OP_MANAGE_DATA:
op = messages.StellarManageDataOp(
source_account=source_account,
key=unpacker.unpack_string(),
source_account=source_account, key=unpacker.unpack_string()
)
# Only set value if the field is present
@ -279,8 +285,7 @@ def _parse_operation_bytes(unpacker):
# see: https://github.com/stellar/stellar-core/blob/master/src/xdr/Stellar-transaction.x#L269
if type == OP_BUMP_SEQUENCE:
return messages.StellarBumpSequenceOp(
source_account=source_account,
bump_to=unpacker.unpack_uhyper()
source_account=source_account, bump_to=unpacker.unpack_uhyper()
)
raise ValueError("Unknown operation type: " + str(type))
@ -288,9 +293,7 @@ def _parse_operation_bytes(unpacker):
def _xdr_read_asset(unpacker):
"""Reads a stellar Asset from unpacker"""
asset = messages.StellarAssetType(
type=unpacker.unpack_uint()
)
asset = messages.StellarAssetType(type=unpacker.unpack_uint())
if asset.type == ASSET_TYPE_ALPHA4:
asset.code = unpacker.unpack_fstring(4)
@ -327,10 +330,56 @@ def _crc16_checksum(bytes):
for byte in bytes:
for i in range(8):
bit = ((byte >> (7 - i) & 1) == 1)
c15 = ((crc >> 15 & 1) == 1)
bit = (byte >> (7 - i) & 1) == 1
c15 = (crc >> 15 & 1) == 1
crc <<= 1
if c15 ^ bit:
crc ^= polynomial
return crc & 0xffff
# ====== Client functions ====== #
@expect(messages.StellarAddress, field="address")
def get_address(client, address_n, show_display=False):
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
):
tx.network_passphrase = network_passphrase
tx.address_n = address_n
tx.num_operations = len(operations)
# Signing loop works as follows:
#
# 1. Start with tx (header information for the transaction) and operations (an array of operation protobuf messagess)
# 2. Send the tx header to the device
# 3. Receive a StellarTxOpRequest message
# 4. Send operations one by one until all operations have been sent. If there are more operations to sign, the device will send a StellarTxOpRequest message
# 5. The final message received will be StellarSignedTx which is returned from this method
resp = client.call(tx)
try:
while isinstance(resp, messages.StellarTxOpRequest):
resp = client.call(operations.pop(0))
except IndexError:
# pop from empty list
raise CallException(
"Stellar.UnexpectedEndOfOperations",
"Reached end of operations without a signature.",
) from None
if not isinstance(resp, messages.StellarSignedTx):
raise CallException(messages.FailureType.UnexpectedMessage, resp)
if operations:
raise CallException(
"Stellar.UnprocessedOperations",
"Received a signature before processing all operations.",
)
return resp

@ -16,64 +16,76 @@
import os
from . import conftest
from trezorlib import coins
from trezorlib import tx_api
from trezorlib import coins, debuglink, device, tx_api
from trezorlib.client import TrezorClientDebugLink
from . import conftest
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:
# fmt: off
# 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"
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"
mnemonic_all = " ".join(["all"] * 12)
# fmt: on
pin4 = "1234"
pin6 = "789456"
pin8 = "45678978"
def setup_method(self, method):
wirelink = conftest.get_device()
debuglink = wirelink.find_debug()
self.client = TrezorClientDebugLink(wirelink)
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)
# 1 2 3 4 5 6 7 8 9 10 11 12
self.mnemonic12 = 'alcohol woman abuse must during monitor noble actual mixed trade anger aisle'
self.mnemonic18 = 'owner little vague addict embark decide pink prosper true fork panda embody mixture exchange choose canoe electric jewel'
self.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'
self.mnemonic_all = ' '.join(['all'] * 12)
self.pin4 = '1234'
self.pin6 = '789456'
self.pin8 = '45678978'
self.client.wipe_device()
device.wipe(self.client)
self.client.transport.session_begin()
def teardown_method(self, method):
self.client.transport.session_end()
self.client.close()
def _setup_mnemonic(self, mnemonic=None, pin="", passphrase=False):
if mnemonic is None:
mnemonic = TrezorTest.mnemonic12
debuglink.load_device_by_mnemonic(
self.client,
mnemonic=mnemonic,
pin=pin,
passphrase_protection=passphrase,
label="test",
language="english",
)
def setup_mnemonic_allallall(self):
self.client.load_device_by_mnemonic(mnemonic=self.mnemonic_all, pin='', passphrase_protection=False, label='test', language='english')
self._setup_mnemonic(mnemonic=TrezorTest.mnemonic_all)
def setup_mnemonic_nopin_nopassphrase(self):
self.client.load_device_by_mnemonic(mnemonic=self.mnemonic12, pin='', passphrase_protection=False, label='test', language='english')
self._setup_mnemonic()
def setup_mnemonic_nopin_passphrase(self):
self.client.load_device_by_mnemonic(mnemonic=self.mnemonic12, pin='', passphrase_protection=True, label='test', language='english')
self._setup_mnemonic(passphrase=True)
def setup_mnemonic_pin_nopassphrase(self):
self.client.load_device_by_mnemonic(mnemonic=self.mnemonic12, pin=self.pin4, passphrase_protection=False, label='test', language='english')
self._setup_mnemonic(pin=TrezorTest.pin4)
def setup_mnemonic_pin_passphrase(self):
self.client.load_device_by_mnemonic(mnemonic=self.mnemonic12, pin=self.pin4, passphrase_protection=True, label='test', language='english')
self._setup_mnemonic(pin=TrezorTest.pin4, passphrase=True)
def generate_entropy(strength, internal_entropy, external_entropy):
'''
"""
strength - length of produced seed. One of 128, 192, 256
random - binary stream of random data from external HRNG
'''
"""
import hashlib
if strength not in (128, 192, 256):
@ -92,7 +104,7 @@ def generate_entropy(strength, internal_entropy, external_entropy):
raise ValueError("External entropy too short")
entropy = hashlib.sha256(internal_entropy + external_entropy).digest()
entropy_stripped = entropy[:strength // 8]
entropy_stripped = entropy[: strength // 8]
if len(entropy_stripped) * 8 != strength:
raise ValueError("Entropy length mismatch")

@ -16,16 +16,26 @@
import functools
import os
import pytest
from trezorlib.transport import get_transport
from trezorlib import coins, log
from trezorlib.client import TrezorClient, TrezorClientDebugLink
from trezorlib import log, coins
from trezorlib.transport import enumerate_devices, get_transport
TREZOR_VERSION = None
def get_device():
path = os.environ.get('TREZOR_PATH')
return get_transport(path)
path = os.environ.get("TREZOR_PATH")
if path:
return get_transport(path)
else:
devices = enumerate_devices()
for device in devices:
if hasattr(device, "find_debug"):
return device
raise RuntimeError("No debuggable device found")
def device_version():
@ -39,16 +49,13 @@ def device_version():
return 1
TREZOR_VERSION = device_version()
@pytest.fixture(scope="function")
def client():
wirelink = get_device()
debuglink = wirelink.find_debug()
client = TrezorClientDebugLink(wirelink)
client.set_debuglink(debuglink)
client.set_tx_api(coins.tx_api['Bitcoin'])
client.set_tx_api(coins.tx_api["Bitcoin"])
client.wipe_device()
client.transport.session_begin()
@ -62,29 +69,44 @@ def client():
client.close()
def setup_client(mnemonic=None, pin='', passphrase=False):
def setup_client(mnemonic=None, pin="", passphrase=False):
if mnemonic is None:
mnemonic = ' '.join(['all'] * 12)
mnemonic = " ".join(["all"] * 12)
if pin is True:
pin = '1234'
pin = "1234"
def client_decorator(function):
@functools.wraps(function)
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 wrapper
return client_decorator
def pytest_configure(config):
if config.getoption('verbose'):
global TREZOR_VERSION
TREZOR_VERSION = device_version()
if config.getoption("verbose"):
log.enable_debug_output()
def pytest_addoption(parser):
parser.addini("run_xfail", "List of markers that will run even if marked as xfail", "args", [])
parser.addini(
"run_xfail",
"List of markers that will run even tests that are marked as xfail",
"args",
[],
)
def pytest_runtest_setup(item):
@ -105,7 +127,8 @@ def pytest_runtest_setup(item):
pytest.skip("Test excluded on Trezor 1")
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:
# 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.

@ -14,21 +14,20 @@
# 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>.
from .common import TrezorTest
from trezorlib import device, messages
from trezorlib import messages
from .common import TrezorTest
class TestBasic(TrezorTest):
def test_features(self):
f0 = self.client.features
f1 = self.client.call(messages.Initialize())
assert f0 == f1
def test_ping(self):
ping = self.client.call(messages.Ping(message='ahoj!'))
assert ping == messages.Success(message='ahoj!')
ping = self.client.call(messages.Ping(message="ahoj!"))
assert ping == messages.Success(message="ahoj!")
def test_device_id_same(self):
id1 = self.client.get_device_id()
@ -43,7 +42,7 @@ class TestBasic(TrezorTest):
def test_device_id_different(self):
id1 = self.client.get_device_id()
self.client.wipe_device()
device.wipe(self.client)
id2 = self.client.get_device_id()
# Device ID must be fresh after every reset

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

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

@ -14,26 +14,26 @@
# 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>.
import pytest
from hashlib import sha256
from .common import TrezorTest
from trezorlib import cosi
import pytest
from trezorlib import cosi
from trezorlib.tools import parse_path
from .common import TrezorTest
@pytest.mark.skip_t2
class TestCosi(TrezorTest):
def test_cosi_commit(self):
self.setup_mnemonic_pin_passphrase()
digest = sha256(b'this is a message').digest()
digest = sha256(b"this is a message").digest()
c0 = self.client.cosi_commit(parse_path("10018'/0'"), digest)
c1 = self.client.cosi_commit(parse_path("10018'/1'"), digest)
c2 = self.client.cosi_commit(parse_path("10018'/2'"), digest)
c0 = cosi.commit(self.client, parse_path("10018'/0'"), digest)
c1 = cosi.commit(self.client, parse_path("10018'/1'"), digest)
c2 = cosi.commit(self.client, parse_path("10018'/2'"), digest)
assert c0.pubkey != c1.pubkey
assert c0.pubkey != c2.pubkey
@ -43,11 +43,11 @@ class TestCosi(TrezorTest):
assert c0.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 = self.client.cosi_commit(parse_path("10018'/0'"), digestb)
c1b = self.client.cosi_commit(parse_path("10018'/1'"), digestb)
c2b = self.client.cosi_commit(parse_path("10018'/2'"), digestb)
c0b = cosi.commit(self.client, parse_path("10018'/0'"), digestb)
c1b = cosi.commit(self.client, parse_path("10018'/1'"), digestb)
c2b = cosi.commit(self.client, parse_path("10018'/2'"), digestb)
assert c0.pubkey == c0b.pubkey
assert c1.pubkey == c1b.pubkey
@ -60,38 +60,46 @@ class TestCosi(TrezorTest):
def test_cosi_sign(self):
self.setup_mnemonic_pin_passphrase()
digest = sha256(b'this is a message').digest()
digest = sha256(b"this is a message").digest()
c0 = self.client.cosi_commit(parse_path("10018'/0'"), digest)
c1 = self.client.cosi_commit(parse_path("10018'/1'"), digest)
c2 = self.client.cosi_commit(parse_path("10018'/2'"), digest)
c0 = cosi.commit(self.client, parse_path("10018'/0'"), digest)
c1 = cosi.commit(self.client, parse_path("10018'/1'"), digest)
c2 = cosi.commit(self.client, parse_path("10018'/2'"), digest)
global_pk = cosi.combine_keys([c0.pubkey, c1.pubkey, c2.pubkey])
global_R = cosi.combine_keys([c0.commitment, c1.commitment, c2.commitment])
sig0 = self.client.cosi_sign(parse_path("10018'/0'"), digest, global_R, global_pk)
sig1 = self.client.cosi_sign(parse_path("10018'/1'"), digest, global_R, global_pk)
sig2 = self.client.cosi_sign(parse_path("10018'/2'"), digest, global_R, global_pk)
# fmt: off
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)
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)
def test_cosi_compat(self):
self.setup_mnemonic_pin_passphrase()
digest = sha256(b'this is not a pipe').digest()
remote_commit = self.client.cosi_commit(parse_path("10018'/0'"), digest)
digest = sha256(b"this is not a pipe").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_nonce, local_commitment = cosi.get_nonce(local_privkey, digest, 42)
global_pk = cosi.combine_keys([remote_commit.pubkey, local_pubkey])
global_R = cosi.combine_keys([remote_commit.commitment, local_commitment])
remote_sig = self.client.cosi_sign(parse_path("10018'/0'"), digest, global_R, global_pk)
local_sig = cosi.sign_with_privkey(digest, local_privkey, global_pk, local_nonce, global_R)
remote_sig = cosi.sign(
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])
cosi.verify(sig, digest, global_pk)

@ -16,13 +16,13 @@
import pytest
from .common import TrezorTest
from trezorlib import messages as proto
from .common import TrezorTest
@pytest.mark.skip_t2
class TestDebuglink(TrezorTest):
def test_layout(self):
layout = self.client.debug.read_layout()
assert len(layout) == 1024
@ -36,12 +36,12 @@ class TestDebuglink(TrezorTest):
self.setup_mnemonic_pin_passphrase()
# 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)
pin = self.client.debug.read_pin()
assert pin[0] == '1234'
assert pin[1] != ''
assert pin[0] == "1234"
assert pin[1] != ""
pin_encoded = self.client.debug.read_pin_encoded()
resp = self.client.call_raw(proto.PinMatrixAck(pin=pin_encoded))

@ -14,44 +14,52 @@
# 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>.
import time
import pytest
from .common import TrezorTest
from trezorlib import device, messages as proto
import time
from trezorlib import messages as proto
from .common import TrezorTest
class TestMsgApplysettings(TrezorTest):
def test_apply_settings(self):
self.setup_mnemonic_pin_passphrase()
assert self.client.features.label == 'test'
assert self.client.features.label == "test"
with self.client:
self.client.set_expected_responses([proto.PinMatrixRequest(),
proto.ButtonRequest(),
proto.Success(),
proto.Features()])
self.client.set_expected_responses(
[
proto.PinMatrixRequest(),
proto.ButtonRequest(),
proto.Success(),
proto.Features(),
]
)
if self.client.features.major_version >= 2:
self.client.expected_responses.pop(0) # skip PinMatrixRequest
self.client.apply_settings(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
def test_invalid_language(self):
self.setup_mnemonic_pin_passphrase()
assert self.client.features.language == 'english'
assert self.client.features.language == "english"
with self.client:
self.client.set_expected_responses([proto.PinMatrixRequest(),
proto.ButtonRequest(),
proto.Success(),
proto.Features()])
self.client.apply_settings(language='nonexistent')
assert self.client.features.language == 'english'
self.client.set_expected_responses(
[
proto.PinMatrixRequest(),
proto.ButtonRequest(),
proto.Success(),
proto.Features(),
]
)
device.apply_settings(self.client, language="nonexistent")
assert self.client.features.language == "english"
def test_apply_settings_passphrase(self):
self.setup_mnemonic_pin_nopassphrase()
@ -59,29 +67,33 @@ class TestMsgApplysettings(TrezorTest):
assert self.client.features.passphrase_protection is False
with self.client:
self.client.set_expected_responses([proto.PinMatrixRequest(),
proto.ButtonRequest(),
proto.Success(),
proto.Features()])
self.client.set_expected_responses(
[
proto.PinMatrixRequest(),
proto.ButtonRequest(),
proto.Success(),
proto.Features(),
]
)
if self.client.features.major_version >= 2:
self.client.expected_responses.pop(0) # skip PinMatrixRequest
self.client.apply_settings(use_passphrase=True)
device.apply_settings(self.client, use_passphrase=True)
assert self.client.features.passphrase_protection is True
with self.client:
self.client.set_expected_responses([proto.ButtonRequest(),
proto.Success(),
proto.Features()])
self.client.apply_settings(use_passphrase=False)
self.client.set_expected_responses(
[proto.ButtonRequest(), proto.Success(), proto.Features()]
)
device.apply_settings(self.client, use_passphrase=False)
assert self.client.features.passphrase_protection is False
with self.client:
self.client.set_expected_responses([proto.ButtonRequest(),
proto.Success(),
proto.Features()])
self.client.apply_settings(use_passphrase=True)
self.client.set_expected_responses(
[proto.ButtonRequest(), proto.Success(), proto.Features()]
)
device.apply_settings(self.client, use_passphrase=True)
assert self.client.features.passphrase_protection is True
@ -92,34 +104,43 @@ 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'
with self.client:
self.client.set_expected_responses([proto.PinMatrixRequest(),
proto.ButtonRequest(),
proto.Success(),
proto.Features()])
self.client.apply_settings(homescreen=img)
self.client.set_expected_responses(
[
proto.PinMatrixRequest(),
proto.ButtonRequest(),
proto.Success(),
proto.Features(),
]
)
device.apply_settings(self.client, homescreen=img)
@pytest.mark.skip_t2
def test_apply_auto_lock_delay(self):
self.setup_mnemonic_pin_passphrase()
with self.client:
self.client.set_expected_responses([proto.PinMatrixRequest(),
proto.ButtonRequest(),
proto.Success(),
proto.Features()])
self.client.apply_settings(auto_lock_delay_ms=int(10e3)) # 10 secs
self.client.set_expected_responses(
[
proto.PinMatrixRequest(),
proto.ButtonRequest(),
proto.Success(),
proto.Features(),
]
)
device.apply_settings(self.client, auto_lock_delay_ms=int(10e3)) # 10 secs
time.sleep(0.1) # sleep less than auto-lock delay
with self.client:
# No PIN protection is required.
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
with self.client:
self.client.set_expected_responses([proto.PinMatrixRequest(),
proto.Success()])
self.client.ping(msg='', pin_protection=True)
self.client.set_expected_responses(
[proto.PinMatrixRequest(), proto.Success()]
)
self.client.ping(msg="", pin_protection=True)
@pytest.mark.skip_t2
def test_apply_minimal_auto_lock_delay(self):
@ -130,27 +151,32 @@ class TestMsgApplysettings(TrezorTest):
self.setup_mnemonic_pin_passphrase()
with self.client:
self.client.set_expected_responses([proto.PinMatrixRequest(),
proto.ButtonRequest(),
proto.Success(),
proto.Features()])
self.client.set_expected_responses(
[
proto.PinMatrixRequest(),
proto.ButtonRequest(),
proto.Success(),
proto.Features(),
]
)
# Note: the actual delay will be 10 secs (see above).
self.client.apply_settings(auto_lock_delay_ms=int(1e3))
device.apply_settings(self.client, auto_lock_delay_ms=int(1e3))
time.sleep(0.1) # sleep less than auto-lock delay
with self.client:
# No PIN protection is required.
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
with self.client:
# No PIN protection is required.
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
with self.client:
self.client.set_expected_responses([proto.PinMatrixRequest(),
proto.Success()])
self.client.ping(msg='', pin_protection=True)
self.client.set_expected_responses(
[proto.PinMatrixRequest(), proto.Success()]
)
self.client.ping(msg="", pin_protection=True)

@ -16,14 +16,13 @@
import pytest
from .common import TrezorTest
from trezorlib import messages as proto
from .common import TrezorTest
@pytest.mark.skip_t2
class TestMsgChangepin(TrezorTest):
def test_set_pin(self):
self.setup_mnemonic_nopin_nopassphrase()
features = self.client.call_raw(proto.Initialize())
@ -206,7 +205,7 @@ class TestMsgChangepin(TrezorTest):
# Send the PIN for second time, but with typo
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))
# Now it should fail, because pins are different

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

@ -16,38 +16,81 @@
import pytest
from .common import TrezorTest
from trezorlib import messages as proto
from .common import TrezorTest
@pytest.mark.skip_t2
class TestMsgClearsession(TrezorTest):
def test_clearsession(self):
self.setup_mnemonic_pin_passphrase()
with self.client:
self.client.set_expected_responses([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'
self.client.set_expected_responses(
[
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:
# pin and passphrase are cached
self.client.set_expected_responses([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.set_expected_responses(
[
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()
# session cache is cleared
with self.client:
self.client.set_expected_responses([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'
self.client.set_expected_responses(
[
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:
# pin and passphrase are cached
self.client.set_expected_responses([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.set_expected_responses(
[
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"

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

@ -15,8 +15,11 @@
# If not, see <https://www.gnu.org/licenses/lgpl-3.0.html>.
from binascii import hexlify
import pytest
from trezorlib import ethereum
from .common import TrezorTest
@ -24,15 +27,21 @@ from .common import TrezorTest
class TestMsgEthereumSignmessage(TrezorTest):
PATH = [0]
ADDRESS = b'cb3864960e8db1a751212c580af27ee8867d688f'
ADDRESS = b"cb3864960e8db1a751212c580af27ee8867d688f"
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):
self.setup_mnemonic_nopin_nopassphrase()
for msg, sig in self.VECTORS:
res = self.client.ethereum_sign_message(self.PATH, msg)
res = ethereum.sign_message(self.client, self.PATH, msg)
assert hexlify(res.address) == self.ADDRESS
assert hexlify(res.signature) == sig

@ -14,276 +14,393 @@
# 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>.
from binascii import unhexlify, hexlify
from binascii import hexlify, unhexlify
import pytest
from trezorlib import ethereum, messages as proto
from .common import TrezorTest
from trezorlib import messages as proto
@pytest.mark.ethereum
class TestMsgEthereumSigntx(TrezorTest):
def test_ethereum_signtx_known_erc20_token(self):
self.setup_mnemonic_nopin_nopassphrase()
with self.client:
self.client.set_expected_responses([
proto.ButtonRequest(code=proto.ButtonRequestType.SignTx),
proto.ButtonRequest(code=proto.ButtonRequestType.SignTx),
proto.EthereumTxRequest(data_length=None),
])
self.client.set_expected_responses(
[
proto.ButtonRequest(code=proto.ButtonRequestType.SignTx),
proto.ButtonRequest(code=proto.ButtonRequestType.SignTx),
proto.EthereumTxRequest(data_length=None),
]
)
data = bytearray()
# method id signalizing `transfer(address _to, uint256 _value)` function
data.extend(unhexlify('a9059cbb'))
data.extend(unhexlify("a9059cbb"))
# 1st function argument (to - the receiver)
data.extend(unhexlify('000000000000000000000000574bbb36871ba6b78e27f4b4dcfb76ea0091880b'))
data.extend(
unhexlify(
"000000000000000000000000574bbb36871ba6b78e27f4b4dcfb76ea0091880b"
)
)
# 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
sig_v, sig_r, sig_s = self.client.ethereum_sign_tx(
sig_v, sig_r, sig_s = ethereum.sign_tx(
self.client,
n=[0, 0],
nonce=0,
gas_price=20,
gas_limit=20,
# 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,
# value needs to be 0, token value is set in the contract (data)
value=0,
data=data)
data=data,
)
# taken from T1 might not be 100% correct but still better than nothing
assert hexlify(sig_r) == b'75cf48fa173d8ceb68af9e4fb6b78ef69e6ed5e7679ba6f8e3e91d74b2fb0f96'
assert hexlify(sig_s) == b'65de4a8c35263b2cfff3954b12146e8e568aa67a1c2461d6865e74ef75c7e190'
assert (
hexlify(sig_r)
== b"75cf48fa173d8ceb68af9e4fb6b78ef69e6ed5e7679ba6f8e3e91d74b2fb0f96"
)
assert (
hexlify(sig_s)
== b"65de4a8c35263b2cfff3954b12146e8e568aa67a1c2461d6865e74ef75c7e190"
)
def test_ethereum_signtx_unknown_erc20_token(self):
self.setup_mnemonic_nopin_nopassphrase()
with self.client:
self.client.set_expected_responses([
proto.ButtonRequest(code=proto.ButtonRequestType.SignTx),
proto.ButtonRequest(code=proto.ButtonRequestType.SignTx),
proto.EthereumTxRequest(data_length=None),
])
self.client.set_expected_responses(
[
proto.ButtonRequest(code=proto.ButtonRequestType.SignTx),
proto.ButtonRequest(code=proto.ButtonRequestType.SignTx),
proto.EthereumTxRequest(data_length=None),
]
)
data = bytearray()
# method id signalizing `transfer(address _to, uint256 _value)` function
data.extend(unhexlify('a9059cbb'))
data.extend(unhexlify("a9059cbb"))
# 1st function argument (to - the receiver)
data.extend(unhexlify('000000000000000000000000574bbb36871ba6b78e27f4b4dcfb76ea0091880b'))
data.extend(
unhexlify(
"000000000000000000000000574bbb36871ba6b78e27f4b4dcfb76ea0091880b"
)
)
# 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"
sig_v, sig_r, sig_s = self.client.ethereum_sign_tx(
sig_v, sig_r, sig_s = ethereum.sign_tx(
self.client,
n=[0, 0],
nonce=0,
gas_price=20,
gas_limit=20,
# 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,
# value needs to be 0, token value is set in the contract (data)
value=0,
data=data)
data=data,
)
# taken from T1 might not be 100% correct but still better than nothing
assert hexlify(sig_r) == b'1707471fbf632e42d18144157aaf4cde101cd9aa9782ad8e30583cfc95ddeef6'
assert hexlify(sig_s) == b'3d2e52ba5904a4bf131abde3f79db826199f5d6f4d241d531d7e8a30a3b9cfd9'
assert (
hexlify(sig_r)
== b"1707471fbf632e42d18144157aaf4cde101cd9aa9782ad8e30583cfc95ddeef6"
)
assert (
hexlify(sig_s)
== b"3d2e52ba5904a4bf131abde3f79db826199f5d6f4d241d531d7e8a30a3b9cfd9"
)
def test_ethereum_signtx_nodata(self):
self.setup_mnemonic_nopin_nopassphrase()
with self.client:
self.client.set_expected_responses([
proto.ButtonRequest(code=proto.ButtonRequestType.SignTx),
proto.ButtonRequest(code=proto.ButtonRequestType.SignTx),
proto.EthereumTxRequest(data_length=None), # v,r,s checked with assert
])
self.client.set_expected_responses(
[
proto.ButtonRequest(code=proto.ButtonRequestType.SignTx),
proto.ButtonRequest(code=proto.ButtonRequestType.SignTx),
proto.EthereumTxRequest(data_length=None), # v,r,s checked later
]
)
sig_v, sig_r, sig_s = self.client.ethereum_sign_tx(
sig_v, sig_r, sig_s = ethereum.sign_tx(
self.client,
n=[0, 0],
nonce=0,
gas_price=20,
gas_limit=20,
to=unhexlify('1d1c328764a41bda0492b66baa30c4a339ff85ef'),
value=10)
to=unhexlify("1d1c328764a41bda0492b66baa30c4a339ff85ef"),
value=10,
)
assert sig_v == 27
assert hexlify(sig_r) == b'9b61192a161d056c66cfbbd331edb2d783a0193bd4f65f49ee965f791d898f72'
assert hexlify(sig_s) == b'49c0bbe35131592c6ed5c871ac457feeb16a1493f64237387fab9b83c1a202f7'
assert (
hexlify(sig_r)
== b"9b61192a161d056c66cfbbd331edb2d783a0193bd4f65f49ee965f791d898f72"
)
assert (
hexlify(sig_s)
== b"49c0bbe35131592c6ed5c871ac457feeb16a1493f64237387fab9b83c1a202f7"
)
with self.client:
self.client.set_expected_responses([
proto.ButtonRequest(code=proto.ButtonRequestType.SignTx),
proto.ButtonRequest(code=proto.ButtonRequestType.SignTx),
proto.EthereumTxRequest(data_length=None),
])
self.client.set_expected_responses(
[
proto.ButtonRequest(code=proto.ButtonRequestType.SignTx),
proto.ButtonRequest(code=proto.ButtonRequestType.SignTx),
proto.EthereumTxRequest(data_length=None),
]
)
sig_v, sig_r, sig_s = self.client.ethereum_sign_tx(
sig_v, sig_r, sig_s = ethereum.sign_tx(
self.client,
n=[0, 0],
nonce=123456,
gas_price=20000,
gas_limit=20000,
to=unhexlify('1d1c328764a41bda0492b66baa30c4a339ff85ef'),
value=12345678901234567890)
to=unhexlify("1d1c328764a41bda0492b66baa30c4a339ff85ef"),
value=12345678901234567890,
)
assert sig_v == 28
assert hexlify(sig_r) == b'6de597b8ec1b46501e5b159676e132c1aa78a95bd5892ef23560a9867528975a'
assert hexlify(sig_s) == b'6e33c4230b1ecf96a8dbb514b4aec0a6d6ba53f8991c8143f77812aa6daa993f'
assert (
hexlify(sig_r)
== b"6de597b8ec1b46501e5b159676e132c1aa78a95bd5892ef23560a9867528975a"
)
assert (
hexlify(sig_s)
== b"6e33c4230b1ecf96a8dbb514b4aec0a6d6ba53f8991c8143f77812aa6daa993f"
)
def test_ethereum_signtx_data(self):
self.setup_mnemonic_nopin_nopassphrase()
with self.client:
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),
])
sig_v, sig_r, sig_s = self.client.ethereum_sign_tx(
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),
]
)
sig_v, sig_r, sig_s = ethereum.sign_tx(
self.client,
n=[0, 0],
nonce=0,
gas_price=20,
gas_limit=20,
to=unhexlify('1d1c328764a41bda0492b66baa30c4a339ff85ef'),
to=unhexlify("1d1c328764a41bda0492b66baa30c4a339ff85ef"),
value=10,
data=b'abcdefghijklmnop' * 16)
data=b"abcdefghijklmnop" * 16,
)
assert sig_v == 28
assert hexlify(sig_r) == b'6da89ed8627a491bedc9e0382f37707ac4e5102e25e7a1234cb697cedb7cd2c0'
assert hexlify(sig_s) == b'691f73b145647623e2d115b208a7c3455a6a8a83e3b4db5b9c6d9bc75825038a'
assert (
hexlify(sig_r)
== b"6da89ed8627a491bedc9e0382f37707ac4e5102e25e7a1234cb697cedb7cd2c0"
)
assert (
hexlify(sig_s)
== b"691f73b145647623e2d115b208a7c3455a6a8a83e3b4db5b9c6d9bc75825038a"
)
with self.client:
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=1024, signature_r=None, 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 = self.client.ethereum_sign_tx(
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=1024,
signature_r=None,
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(
self.client,
n=[0, 0],
nonce=123456,
gas_price=20000,
gas_limit=20000,
to=unhexlify('1d1c328764a41bda0492b66baa30c4a339ff85ef'),
to=unhexlify("1d1c328764a41bda0492b66baa30c4a339ff85ef"),
value=12345678901234567890,
data=b'ABCDEFGHIJKLMNOP' * 256 + b'!!!')
data=b"ABCDEFGHIJKLMNOP" * 256 + b"!!!",
)
assert sig_v == 28
assert hexlify(sig_r) == b'4e90b13c45c6a9bf4aaad0e5427c3e62d76692b36eb727c78d332441b7400404'
assert hexlify(sig_s) == b'3ff236e7d05f0f9b1ee3d70599bb4200638f28388a8faf6bb36db9e04dc544be'
assert (
hexlify(sig_r)
== b"4e90b13c45c6a9bf4aaad0e5427c3e62d76692b36eb727c78d332441b7400404"
)
assert (
hexlify(sig_s)
== b"3ff236e7d05f0f9b1ee3d70599bb4200638f28388a8faf6bb36db9e04dc544be"
)
def test_ethereum_signtx_message(self):
self.setup_mnemonic_nopin_nopassphrase()
with self.client:
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=1024, signature_r=None, 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 = self.client.ethereum_sign_tx(
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=1024,
signature_r=None,
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(
self.client,
n=[0, 0],
nonce=0,
gas_price=20000,
gas_limit=20000,
to=unhexlify('1d1c328764a41bda0492b66baa30c4a339ff85ef'),
to=unhexlify("1d1c328764a41bda0492b66baa30c4a339ff85ef"),
value=0,
data=b'ABCDEFGHIJKLMNOP' * 256 + b'!!!')
data=b"ABCDEFGHIJKLMNOP" * 256 + b"!!!",
)
assert sig_v == 28
assert hexlify(sig_r) == b'070e9dafda4d9e733fa7b6747a75f8a4916459560efb85e3e73cd39f31aa160d'
assert hexlify(sig_s) == b'7842db33ef15c27049ed52741db41fe3238a6fa3a6a0888fcfb74d6917600e41'
assert (
hexlify(sig_r)
== b"070e9dafda4d9e733fa7b6747a75f8a4916459560efb85e3e73cd39f31aa160d"
)
assert (
hexlify(sig_s)
== b"7842db33ef15c27049ed52741db41fe3238a6fa3a6a0888fcfb74d6917600e41"
)
def test_ethereum_signtx_newcontract(self):
self.setup_mnemonic_nopin_nopassphrase()
# contract creation without data should fail.
with pytest.raises(Exception):
self.client.ethereum_sign_tx(
ethereum.sign_tx(
self.client,
n=[0, 0],
nonce=123456,
gas_price=20000,
gas_limit=20000,
to='',
value=12345678901234567890
to="",
value=12345678901234567890,
)
with self.client:
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=1024, signature_r=None, 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 = self.client.ethereum_sign_tx(
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=1024,
signature_r=None,
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(
self.client,
n=[0, 0],
nonce=0,
gas_price=20000,
gas_limit=20000,
to='',
to="",
value=12345678901234567890,
data=b'ABCDEFGHIJKLMNOP' * 256 + b'!!!')
data=b"ABCDEFGHIJKLMNOP" * 256 + b"!!!",
)
assert sig_v == 28
assert hexlify(sig_r) == b'b401884c10ae435a2e792303b5fc257a09f94403b2883ad8c0ac7a7282f5f1f9'
assert hexlify(sig_s) == b'4742fc9e6a5fa8db3db15c2d856914a7f3daab21603a6c1ce9e9927482f8352e'
assert (
hexlify(sig_r)
== b"b401884c10ae435a2e792303b5fc257a09f94403b2883ad8c0ac7a7282f5f1f9"
)
assert (
hexlify(sig_s)
== b"4742fc9e6a5fa8db3db15c2d856914a7f3daab21603a6c1ce9e9927482f8352e"
)
def test_ethereum_sanity_checks(self):
# gas overflow
with pytest.raises(Exception):
self.client.ethereum_sign_tx(
ethereum.sign_tx(
self.client,
n=[0, 0],
nonce=123456,
gas_price=0xffffffffffffffffffffffffffffffff,
gas_limit=0xffffffffffffffffffffffffffffff,
to=unhexlify('1d1c328764a41bda0492b66baa30c4a339ff85ef'),
value=12345678901234567890
to=unhexlify("1d1c328764a41bda0492b66baa30c4a339ff85ef"),
value=12345678901234567890,
)
# no gas price
with pytest.raises(Exception):
self.client.ethereum_sign_tx(
ethereum.sign_tx(
self.client,
n=[0, 0],
nonce=123456,
gas_limit=10000,
to=unhexlify('1d1c328764a41bda0492b66baa30c4a339ff85ef'),
value=12345678901234567890
to=unhexlify("1d1c328764a41bda0492b66baa30c4a339ff85ef"),
value=12345678901234567890,
)
# no gas limit
with pytest.raises(Exception):
self.client.ethereum_sign_tx(
ethereum.sign_tx(
self.client,
n=[0, 0],
nonce=123456,
gas_price=10000,
to=unhexlify('1d1c328764a41bda0492b66baa30c4a339ff85ef'),
value=12345678901234567890
to=unhexlify("1d1c328764a41bda0492b66baa30c4a339ff85ef"),
value=12345678901234567890,
)
# no nonce
with pytest.raises(Exception):
self.client.ethereum_sign_tx(
ethereum.sign_tx(
self.client,
n=[0, 0],
gas_price=10000,
gas_limit=123456,
to=unhexlify('1d1c328764a41bda0492b66baa30c4a339ff85ef'),
value=12345678901234567890
to=unhexlify("1d1c328764a41bda0492b66baa30c4a339ff85ef"),
value=12345678901234567890,
)

@ -14,11 +14,14 @@
# 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>.
from binascii import unhexlify, hexlify
from binascii import hexlify, unhexlify
import pytest
from trezorlib import ethereum
from trezorlib.tools import H_
from .common import TrezorTest
from trezorlib import messages as proto
@pytest.mark.ethereum
@ -202,8 +205,9 @@ class TestMsgEthereumSigntxChainId(TrezorTest):
self.setup_mnemonic_allallall()
for ci, n, sv, sr, ss, v, gl, d in VECTORS:
sig_v, sig_r, sig_s = self.client.ethereum_sign_tx(
n=[0x80000000 | 44, 0x80000000 | 1, 0x80000000, 0, 0],
sig_v, sig_r, sig_s = ethereum.sign_tx(
self.client,
n=[H_(44), H_(1), H_(0), 0, 0],
nonce=n,
gas_price=20000000000,
gas_limit=gl,

@ -18,24 +18,30 @@ from binascii import unhexlify
import pytest
from trezorlib import ethereum
from .common import TrezorTest
@pytest.mark.ethereum
class TestMsgEthereumVerifymessage(TrezorTest):
ADDRESS = b'cb3864960e8db1a751212c580af27ee8867d688f'
ADDRESS = b"cb3864960e8db1a751212c580af27ee8867d688f"
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):
self.setup_mnemonic_nopin_nopassphrase()
for msg, sig in self.VECTORS:
res = self.client.ethereum_verify_message(
unhexlify(self.ADDRESS),
unhexlify(sig),
msg
res = ethereum.verify_message(
self.client, unhexlify(self.ADDRESS), unhexlify(sig), msg
)
assert res is True

@ -14,71 +14,142 @@
# 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>.
import pytest
from .common import TrezorTest
from ..support import ckd_public as bip32
from trezorlib import messages as proto
from trezorlib import btc, messages as proto
from trezorlib.tools import H_, parse_path
from trezorlib.tools import parse_path
from ..support import ckd_public as bip32
from .common import TrezorTest
class TestMsgGetaddress(TrezorTest):
def test_btc(self):
self.setup_mnemonic_nopin_nopassphrase()
assert self.client.get_address('Bitcoin', []) == '1EfKbQupktEMXf4gujJ9kCFo83k1iMqwqK'
assert self.client.get_address('Bitcoin', [1]) == '1CK7SJdcb8z9HuvVft3D91HLpLC6KSsGb'
assert self.client.get_address('Bitcoin', [0, -1]) == '1JVq66pzRBvqaBRFeU9SPVvg3er4ZDgoMs'
assert self.client.get_address('Bitcoin', [-9, 0]) == '1F4YdQdL9ZQwvcNTuy5mjyQxXkyCfMcP2P'
assert self.client.get_address('Bitcoin', [0, 9999999]) == '1GS8X3yc7ntzwGw9vXwj9wqmBWZkTFewBV'
assert (
btc.get_address(self.client, "Bitcoin", [])
== "1EfKbQupktEMXf4gujJ9kCFo83k1iMqwqK"
)
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):
self.setup_mnemonic_nopin_nopassphrase()
assert self.client.get_address('Litecoin', []) == 'LYtGrdDeqYUQnTkr5sHT2DKZLG7Hqg7HTK'
assert self.client.get_address('Litecoin', [1]) == 'LKRGNecThFP3Q6c5fosLVA53Z2hUDb1qnE'
assert self.client.get_address('Litecoin', [0, -1]) == 'LcinMK8pVrAtpz7Qpc8jfWzSFsDLgLYfG6'
assert self.client.get_address('Litecoin', [-9, 0]) == 'LZHVtcwAEDf1BR4d67551zUijyLUpDF9EX'
assert self.client.get_address('Litecoin', [0, 9999999]) == 'Laf5nGHSCT94C5dK6fw2RxuXPiw2ZuRR9S'
assert (
btc.get_address(self.client, "Litecoin", [])
== "LYtGrdDeqYUQnTkr5sHT2DKZLG7Hqg7HTK"
)
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):
self.setup_mnemonic_nopin_nopassphrase()
assert self.client.get_address('Testnet', [111, 42]) == 'moN6aN6NP1KWgnPSqzrrRPvx2x1UtZJssa'
assert (
btc.get_address(self.client, "Testnet", [111, 42])
== "moN6aN6NP1KWgnPSqzrrRPvx2x1UtZJssa"
)
def test_bch(self):
self.setup_mnemonic_allallall()
assert self.client.get_address('Bcash', parse_path("44'/145'/0'/0/0")) == 'bitcoincash:qr08q88p9etk89wgv05nwlrkm4l0urz4cyl36hh9sv'
assert self.client.get_address('Bcash', parse_path("44'/145'/0'/0/1")) == 'bitcoincash:qr23ajjfd9wd73l87j642puf8cad20lfmqdgwvpat4'
assert self.client.get_address('Bcash', parse_path("44'/145'/0'/1/0")) == 'bitcoincash:qzc5q87w069lzg7g3gzx0c8dz83mn7l02scej5aluw'
assert (
btc.get_address(self.client, "Bcash", parse_path("44'/145'/0'/0/0"))
== "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):
self.setup_mnemonic_allallall()
xpubs = []
for n in map(lambda index: self.client.get_public_node(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)
def getmultisig(chain, nr, signatures=[b'', b'', b''], xpubs=xpubs):
def getmultisig(chain, nr, signatures=[b"", b"", b""], xpubs=xpubs):
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,
m=2,
)
for nr in range(1, 4):
assert self.client.get_address('Bcash', parse_path("44'/145'/" + str(nr) + "'/0/0"), show_display=(nr == 1), multisig=getmultisig(0, 0)) == 'bitcoincash:pqguz4nqq64jhr5v3kvpq4dsjrkda75hwy86gq0qzw'
assert self.client.get_address('Bcash', parse_path("44'/145'/" + str(nr) + "'/1/0"), show_display=(nr == 1), multisig=getmultisig(1, 0)) == 'bitcoincash:pp6kcpkhua7789g2vyj0qfkcux3yvje7euhyhltn0a'
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 (
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):
self.setup_mnemonic_nopin_nopassphrase()
node = self.client.get_public_node([]).node
node_sub1 = self.client.get_public_node([1]).node
node = btc.get_public_node(self.client, []).node
node_sub1 = btc.get_public_node(self.client, [1]).node
node_sub2 = bip32.public_ckd(node, [1])
assert node_sub1.chain_code == node_sub2.chain_code
assert node_sub1.public_key == node_sub2.public_key
address1 = self.client.get_address('Bitcoin', [1])
address1 = btc.get_address(self.client, "Bitcoin", [1])
address2 = bip32.get_address(node_sub2, 0)
assert address2 == '1CK7SJdcb8z9HuvVft3D91HLpLC6KSsGb'
assert address2 == "1CK7SJdcb8z9HuvVft3D91HLpLC6KSsGb"
assert address1 == address2

@ -14,27 +14,79 @@
# 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>.
from .common import TrezorTest
from ..support import ckd_public as bip32
from trezorlib import messages as proto
from trezorlib import btc, messages as proto
from trezorlib.tools import parse_path
from ..support import ckd_public as bip32
from .common import TrezorTest
class TestMsgGetaddressSegwit(TrezorTest):
def test_show_segwit(self):
self.setup_mnemonic_allallall()
assert self.client.get_address("Testnet", parse_path("49'/1'/0'/1/0"), True, None, script_type=proto.InputScriptType.SPENDP2SHWITNESS) == '2N1LGaGg836mqSQqiuUBLfcyGBhyZbremDX'
assert self.client.get_address("Testnet", parse_path("49'/1'/0'/0/0"), False, None, script_type=proto.InputScriptType.SPENDP2SHWITNESS) == '2N4Q5FhU2497BryFfUgbqkAJE87aKHUhXMp'
assert self.client.get_address("Testnet", parse_path("44'/1'/0'/0/0"), False, None, script_type=proto.InputScriptType.SPENDP2SHWITNESS) == '2N6UeBoqYEEnybg4cReFYDammpsyDw8R2Mc'
assert self.client.get_address("Testnet", parse_path("44'/1'/0'/0/0"), False, None, script_type=proto.InputScriptType.SPENDADDRESS) == 'mvbu1Gdy8SUjTenqerxUaZyYjmveZvt33q'
assert (
btc.get_address(
self.client,
"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):
self.setup_mnemonic_allallall()
nodes = map(lambda index: self.client.get_public_node(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(
pubkeys=list(map(lambda n: proto.HDNodePathType(node=bip32.deserialize(n.xpub), address_n=[2, 0]), nodes)),
signatures=[b'', b'', b''],
pubkeys=list(
map(
lambda n: proto.HDNodePathType(
node=bip32.deserialize(n.xpub), address_n=[2, 0]
),
nodes,
)
),
signatures=[b"", b"", b""],
m=2,
)
# multisig2 = proto.MultisigRedeemScriptType(
@ -43,4 +95,14 @@ class TestMsgGetaddressSegwit(TrezorTest):
# m=2,
# )
for i in [1, 2, 3]:
assert self.client.get_address("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"
)

@ -14,34 +14,111 @@
# 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>.
from .common import TrezorTest
from ..support import ckd_public as bip32
from trezorlib import messages as proto
from trezorlib import btc, messages as proto
from trezorlib.tools import parse_path
from ..support import ckd_public as bip32
from .common import TrezorTest
class TestMsgGetaddressSegwitNative(TrezorTest):
class TestMsgGetaddressSegwitNative(TrezorTest):
def test_show_segwit(self):
self.setup_mnemonic_allallall()
assert self.client.get_address("Testnet", parse_path("49'/1'/0'/0/0"), True, None, script_type=proto.InputScriptType.SPENDWITNESS) == 'tb1qqzv60m9ajw8drqulta4ld4gfx0rdh82un5s65s'
assert self.client.get_address("Testnet", parse_path("49'/1'/0'/1/0"), False, None, script_type=proto.InputScriptType.SPENDWITNESS) == 'tb1q694ccp5qcc0udmfwgp692u2s2hjpq5h407urtu'
assert self.client.get_address("Testnet", parse_path("44'/1'/0'/0/0"), False, None, script_type=proto.InputScriptType.SPENDWITNESS) == 'tb1q54un3q39sf7e7tlfq99d6ezys7qgc62a6rxllc'
assert self.client.get_address("Testnet", parse_path("44'/1'/0'/0/0"), False, None, script_type=proto.InputScriptType.SPENDADDRESS) == 'mvbu1Gdy8SUjTenqerxUaZyYjmveZvt33q'
assert (
btc.get_address(
self.client,
"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):
self.setup_mnemonic_allallall()
nodes = [self.client.get_public_node(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(
pubkeys=list(map(lambda n: proto.HDNodePathType(node=bip32.deserialize(n.xpub), address_n=[2, 0]), nodes)),
signatures=[b'', b'', b''],
pubkeys=list(
map(
lambda n: proto.HDNodePathType(
node=bip32.deserialize(n.xpub), address_n=[2, 0]
),
nodes,
)
),
signatures=[b"", b"", b""],
m=2,
)
multisig2 = proto.MultisigRedeemScriptType(
pubkeys=list(map(lambda n: proto.HDNodePathType(node=bip32.deserialize(n.xpub), address_n=[2, 1]), nodes)),
signatures=[b'', b'', b''],
pubkeys=list(
map(
lambda n: proto.HDNodePathType(
node=bip32.deserialize(n.xpub), address_n=[2, 1]
),
nodes,
)
),
signatures=[b"", b"", b""],
m=2,
)
for i in [1, 2, 3]:
assert self.client.get_address("Testnet", parse_path("999'/1'/%d'/2/1" % i), False, multisig2, script_type=proto.InputScriptType.SPENDWITNESS) == 'tb1qch62pf820spe9mlq49ns5uexfnl6jzcezp7d328fw58lj0rhlhasge9hzy'
assert self.client.get_address("Testnet", parse_path("999'/1'/%d'/2/0" % i), False, multisig1, script_type=proto.InputScriptType.SPENDWITNESS) == 'tb1qr6xa5v60zyt3ry9nmfew2fk5g9y3gerkjeu6xxdz7qga5kknz2ssld9z2z'
assert (
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"
)

@ -14,50 +14,71 @@
# 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>.
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 .common import TrezorTest
class TestMsgGetaddressShow(TrezorTest):
def test_show(self):
self.setup_mnemonic_nopin_nopassphrase()
assert self.client.get_address('Bitcoin', [1], show_display=True) == '1CK7SJdcb8z9HuvVft3D91HLpLC6KSsGb'
assert self.client.get_address('Bitcoin', [2], show_display=True) == '15AeAhtNJNKyowK8qPHwgpXkhsokzLtUpG'
assert self.client.get_address('Bitcoin', [3], show_display=True) == '1CmzyJp9w3NafXMSEFH4SLYUPAVCSUrrJ5'
assert (
btc.get_address(self.client, "Bitcoin", [1], show_display=True)
== "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):
self.setup_mnemonic_nopin_nopassphrase()
node = bip32.deserialize('xpub661MyMwAqRbcF1zGijBb2K6x9YiJPh58xpcCeLvTxMX6spkY3PcpJ4ABcCyWfskq5DDxM3e6Ez5ePCqG5bnPUXR4wL8TZWyoDaUdiWW7bKy')
node = bip32.deserialize(
"xpub661MyMwAqRbcF1zGijBb2K6x9YiJPh58xpcCeLvTxMX6spkY3PcpJ4ABcCyWfskq5DDxM3e6Ez5ePCqG5bnPUXR4wL8TZWyoDaUdiWW7bKy"
)
multisig = proto.MultisigRedeemScriptType(
pubkeys=[
proto.HDNodePathType(node=node, address_n=[1]),
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,
)
for i in [1, 2, 3]:
assert self.client.get_address('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):
self.setup_mnemonic_nopin_nopassphrase()
node = bip32.deserialize('xpub661MyMwAqRbcF1zGijBb2K6x9YiJPh58xpcCeLvTxMX6spkY3PcpJ4ABcCyWfskq5DDxM3e6Ez5ePCqG5bnPUXR4wL8TZWyoDaUdiWW7bKy')
node = bip32.deserialize(
"xpub661MyMwAqRbcF1zGijBb2K6x9YiJPh58xpcCeLvTxMX6spkY3PcpJ4ABcCyWfskq5DDxM3e6Ez5ePCqG5bnPUXR4wL8TZWyoDaUdiWW7bKy"
)
pubs = []
for x in range(15):
pubs.append(proto.HDNodePathType(node=node, address_n=[x]))
multisig = proto.MultisigRedeemScriptType(
pubkeys=pubs,
signatures=[b''] * 15,
m=15,
pubkeys=pubs, signatures=[b""] * 15, m=15
)
for i in range(15):
assert self.client.get_address('Bitcoin', [i], show_display=True, multisig=multisig) == '3QaKF8zobqcqY8aS6nxCD5ZYdiRfL3RCmU'
assert (
btc.get_address(
self.client, "Bitcoin", [i], show_display=True, multisig=multisig
)
== "3QaKF8zobqcqY8aS6nxCD5ZYdiRfL3RCmU"
)

@ -16,26 +16,60 @@
from binascii import unhexlify
from trezorlib import messages as proto, misc
from .common import TrezorTest
from trezorlib import messages as proto
class TestMsgGetECDHSessionKey(TrezorTest):
def test_ecdh(self):
self.setup_mnemonic_nopin_nopassphrase()
# 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')
result = self.client.get_ecdh_session_key(identity=identity, peer_public_key=peer_public_key, ecdsa_curve_name='secp256k1')
assert result.session_key == unhexlify('0495e5d8c9e5cc09e7cf4908774f52decb381ce97f2fc9ba56e959c13f03f9f47a03dd151cbc908bc1db84d46e2c33e7bbb9daddc800f985244c924fd64adf6647')
peer_public_key = unhexlify(
"0407f2c6e5becf3213c1d07df0cfbe8e39f70a8c643df7575e5c56859ec52c45ca950499c019719dae0fda04248d851e52cf9d66eeb211d89a77be40de22b6c89d"
)
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')
result = self.client.get_ecdh_session_key(identity=identity, peer_public_key=peer_public_key, ecdsa_curve_name='nist256p1')
assert result.session_key == unhexlify('046d1f5c48af2cf2c57076ac2c9d7808db2086f614cb7b8107119ff2c6270cd209749809efe0196f01a0cc633788cef1f4a2bd650c99570d06962f923fca6d8fdf')
peer_public_key = unhexlify(
"04811a6c2bd2a547d0dd84747297fec47719e7c3f9b0024f027c2b237be99aac39a9230acbd163d0cb1524a0f5ea4bfed6058cec6f18368f72a12aa0c4d083ff64"
)
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')
result = self.client.get_ecdh_session_key(identity=identity, peer_public_key=peer_public_key, ecdsa_curve_name='curve25519')
assert result.session_key == unhexlify('04e24516669e0b7d3d72e5129fddd07b6644c30915f5c8b7f1f62324afb3624311')
peer_public_key = unhexlify(
"40a8cf4b6a64c4314e80f15a8ea55812bd735fbb365936a48b2d78807b575fa17a"
)
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"
)

@ -15,31 +15,34 @@
# If not, see <https://www.gnu.org/licenses/lgpl-3.0.html>.
import math
from .common import TrezorTest
import trezorlib.messages as proto
import pytest
from trezorlib import messages as m, misc
ENTROPY_LENGTHS_POW2 = [2 ** l for l in range(10)]
ENTROPY_LENGTHS_POW2_1 = [2 ** l + 1 for l in range(10)]
ENTROPY_LENGTHS = ENTROPY_LENGTHS_POW2 + ENTROPY_LENGTHS_POW2_1
def entropy(data):
counts = {}
for c in data:
if c in counts:
counts[c] += 1
else:
counts[c] = 1
counts[c] = counts.get(c, 0) + 1
e = 0
for _, v in counts.items():
p = 1.0 * v / len(data)
for v in counts.values():
p = v / len(data)
e -= p * math.log(p, 256)
return e
class TestMsgGetentropy(TrezorTest):
def test_entropy(self):
for l in [0, 1, 2, 3, 4, 5, 8, 9, 16, 17, 32, 33, 64, 65, 128, 129, 256, 257, 512, 513, 1024]:
with self.client:
self.client.set_expected_responses([proto.ButtonRequest(code=proto.ButtonRequestType.ProtectCall), proto.Entropy()])
ent = self.client.get_entropy(l)
assert len(ent) == l
print('entropy = ', entropy(ent))
@pytest.mark.parametrize("entropy_length", ENTROPY_LENGTHS)
def test_entropy(client, entropy_length):
with client:
client.set_expected_responses(
[m.ButtonRequest(code=m.ButtonRequestType.ProtectCall), m.Entropy()]
)
ent = misc.get_entropy(client, entropy_length)
assert len(ent) == entropy_length
print("{} bytes: entropy = {}".format(entropy_length, entropy(ent)))

@ -14,39 +14,121 @@
# 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>.
from .common import TrezorTest
from trezorlib import btc
from trezorlib.tools import H_
from ..support import ckd_public as bip32
from .common import TrezorTest
class TestMsgGetpublickey(TrezorTest):
def test_btc(self):
self.setup_mnemonic_nopin_nopassphrase()
assert bip32.serialize(self.client.get_public_node([]).node, 0x0488B21E) == 'xpub661MyMwAqRbcF1zGijBb2K6x9YiJPh58xpcCeLvTxMX6spkY3PcpJ4ABcCyWfskq5DDxM3e6Ez5ePCqG5bnPUXR4wL8TZWyoDaUdiWW7bKy'
assert self.client.get_public_node([], coin_name='Bitcoin').xpub == 'xpub661MyMwAqRbcF1zGijBb2K6x9YiJPh58xpcCeLvTxMX6spkY3PcpJ4ABcCyWfskq5DDxM3e6Ez5ePCqG5bnPUXR4wL8TZWyoDaUdiWW7bKy'
assert bip32.serialize(self.client.get_public_node([1]).node, 0x0488B21E) == 'xpub68zNxjsTrV8y9AadThLW7dTAqEpZ7xBLFSyJ3X9pjTv6Njg6kxgjXJkzxq8u3ttnjBw1jupQHMP3gpGZzZqd1eh5S4GjkaMhPR18vMyUi8N'
assert self.client.get_public_node([1], coin_name='Bitcoin').xpub == 'xpub68zNxjsTrV8y9AadThLW7dTAqEpZ7xBLFSyJ3X9pjTv6Njg6kxgjXJkzxq8u3ttnjBw1jupQHMP3gpGZzZqd1eh5S4GjkaMhPR18vMyUi8N'
assert bip32.serialize(self.client.get_public_node([0, -1]).node, 0x0488B21E) == 'xpub6A3FoZqYXj1AbW4thRwBh26YwZWbmoyjTaZwwxJjY1oKUpefLepL3RFS9DHKQrjAfxDrzDepYMDZPqXN6upQm3bHQ9xaXD5a3mqni3goF4v'
assert self.client.get_public_node([0, -1], coin_name='Bitcoin').xpub == 'xpub6A3FoZqYXj1AbW4thRwBh26YwZWbmoyjTaZwwxJjY1oKUpefLepL3RFS9DHKQrjAfxDrzDepYMDZPqXN6upQm3bHQ9xaXD5a3mqni3goF4v'
assert bip32.serialize(self.client.get_public_node([-9, 0]).node, 0x0488B21E) == 'xpub6A2h5mzLDfYginoD7q7wCWbq18wTbN9gducRr2w5NRTwdLeoT3cJSwefFqW7uXTpVFGtpUyDMBNYs3DNvvXx6NPjF9YEbUQrtxFSWnPtVrv'
assert self.client.get_public_node([-9, 0], coin_name='Bitcoin').xpub == 'xpub6A2h5mzLDfYginoD7q7wCWbq18wTbN9gducRr2w5NRTwdLeoT3cJSwefFqW7uXTpVFGtpUyDMBNYs3DNvvXx6NPjF9YEbUQrtxFSWnPtVrv'
assert bip32.serialize(self.client.get_public_node([0, 9999999]).node, 0x0488B21E) == 'xpub6A3FoZqQEK6iwLZ4HFkqSo5fb35BH4bpjC4SPZ63prfLdGYPwYxEuC6o91bUvFFdMzKWe5rs3axHRUjxJaSvBnKKFtnfLwDACRxPxabsv2r'
assert self.client.get_public_node([0, 9999999], coin_name='Bitcoin').xpub == 'xpub6A3FoZqQEK6iwLZ4HFkqSo5fb35BH4bpjC4SPZ63prfLdGYPwYxEuC6o91bUvFFdMzKWe5rs3axHRUjxJaSvBnKKFtnfLwDACRxPxabsv2r'
assert (
bip32.serialize(btc.get_public_node(self.client, []).node, 0x0488B21E)
== "xpub661MyMwAqRbcF1zGijBb2K6x9YiJPh58xpcCeLvTxMX6spkY3PcpJ4ABcCyWfskq5DDxM3e6Ez5ePCqG5bnPUXR4wL8TZWyoDaUdiWW7bKy"
)
assert (
btc.get_public_node(self.client, [], coin_name="Bitcoin").xpub
== "xpub661MyMwAqRbcF1zGijBb2K6x9YiJPh58xpcCeLvTxMX6spkY3PcpJ4ABcCyWfskq5DDxM3e6Ez5ePCqG5bnPUXR4wL8TZWyoDaUdiWW7bKy"
)
assert (
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):
self.setup_mnemonic_nopin_nopassphrase()
assert bip32.serialize(self.client.get_public_node([]).node, 0x019DA462) == 'Ltub2SSUS19CirucVPGDKDBatBDBEM2s9UbH66pBURfaKrMocCPLhQ7Z7hecy5VYLHA5fRdXwB2e61j2VJCNzVsqKTCVEU1vECjqi5EyczFX9xp'
assert self.client.get_public_node([], coin_name='Litecoin').xpub == 'Ltub2SSUS19CirucVPGDKDBatBDBEM2s9UbH66pBURfaKrMocCPLhQ7Z7hecy5VYLHA5fRdXwB2e61j2VJCNzVsqKTCVEU1vECjqi5EyczFX9xp'
assert bip32.serialize(self.client.get_public_node([1]).node, 0x019DA462) == 'Ltub2VRVRP5VjvSyPXra4BLVyVZPv397sjhUNjBGsbtw6xko77JuQyBULxFSKheviJJ3KQLbL3Cx8P2RnudguTw4raUVjCACRG7jsumUptYx55C'
assert self.client.get_public_node([1], coin_name='Litecoin').xpub == 'Ltub2VRVRP5VjvSyPXra4BLVyVZPv397sjhUNjBGsbtw6xko77JuQyBULxFSKheviJJ3KQLbL3Cx8P2RnudguTw4raUVjCACRG7jsumUptYx55C'
assert bip32.serialize(self.client.get_public_node([0, -1]).node, 0x019DA462) == 'Ltub2WUNGD3aRAKAqsLqHuwBYtCn2MqAXbVsarmvn33quWe2DCHTzfK4s4jsW5oM5G8RGAdSaM3NPNrwVvtV1ourbyNhhHr3BtqcYGc8caf5GoT'
assert self.client.get_public_node([0, -1], coin_name='Litecoin').xpub == 'Ltub2WUNGD3aRAKAqsLqHuwBYtCn2MqAXbVsarmvn33quWe2DCHTzfK4s4jsW5oM5G8RGAdSaM3NPNrwVvtV1ourbyNhhHr3BtqcYGc8caf5GoT'
assert bip32.serialize(self.client.get_public_node([-9, 0]).node, 0x019DA462) == 'Ltub2WToYRCN76rgyA59iK7w4Ni45wG2M9fpmBpQg7gBjvJeMiHc7473Gb96ci29Zvs55TgUQcMmCD1vy8aVqpdPwJB9YHRhGAAuPT1nRLLXmFu'
assert self.client.get_public_node([-9, 0], coin_name='Litecoin').xpub == 'Ltub2WToYRCN76rgyA59iK7w4Ni45wG2M9fpmBpQg7gBjvJeMiHc7473Gb96ci29Zvs55TgUQcMmCD1vy8aVqpdPwJB9YHRhGAAuPT1nRLLXmFu'
assert bip32.serialize(self.client.get_public_node([0, 9999999]).node, 0x019DA462) == 'Ltub2WUNGD3S7kQjBhpzsjkqJfBtfqPk2r7xrUGRDdqACMW3MeBCbZSyiqbEVt7WaeesxCj6EDFQtcbfXa75DUYN2i6jZ2g81cyCgvijs9J2u2n'
assert self.client.get_public_node([0, 9999999], coin_name='Litecoin').xpub == 'Ltub2WUNGD3S7kQjBhpzsjkqJfBtfqPk2r7xrUGRDdqACMW3MeBCbZSyiqbEVt7WaeesxCj6EDFQtcbfXa75DUYN2i6jZ2g81cyCgvijs9J2u2n'
assert (
bip32.serialize(btc.get_public_node(self.client, []).node, 0x019DA462)
== "Ltub2SSUS19CirucVPGDKDBatBDBEM2s9UbH66pBURfaKrMocCPLhQ7Z7hecy5VYLHA5fRdXwB2e61j2VJCNzVsqKTCVEU1vECjqi5EyczFX9xp"
)
assert (
btc.get_public_node(self.client, [], coin_name="Litecoin").xpub
== "Ltub2SSUS19CirucVPGDKDBatBDBEM2s9UbH66pBURfaKrMocCPLhQ7Z7hecy5VYLHA5fRdXwB2e61j2VJCNzVsqKTCVEU1vECjqi5EyczFX9xp"
)
assert (
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):
self.setup_mnemonic_nopin_nopassphrase()
assert bip32.serialize(self.client.get_public_node([111, 42]).node, 0x043587CF) == 'tpubDAgixSyai5PWbc8N1mBkHDR5nLgAnHFtY7r4y5EzxqAxrt9YUDpZL3kaRoHVvCfrcwNo31c2isBP2uTHcZxEosuKbyJhCAbrvGoPuLUZ7Mz'
assert self.client.get_public_node([111, 42], coin_name='Testnet').xpub == 'tpubDAgixSyai5PWbc8N1mBkHDR5nLgAnHFtY7r4y5EzxqAxrt9YUDpZL3kaRoHVvCfrcwNo31c2isBP2uTHcZxEosuKbyJhCAbrvGoPuLUZ7Mz'
assert (
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"
)

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

@ -16,16 +16,23 @@
import pytest
from trezorlib import lisk
from trezorlib.tools import parse_path
from .common import TrezorTest
LISK_PATH = parse_path("m/44h/134h/0h/1h")
@pytest.mark.lisk
@pytest.mark.skip_t1
class TestMsgLiskGetaddress(TrezorTest):
def test_lisk_getaddress(self):
self.setup_mnemonic_nopin_nopassphrase()
assert self.client.lisk_get_address([2147483692, 2147483782]) == '1431530009238518937L'
assert self.client.lisk_get_address([2147483692, 2147483782, 2147483648]) == '17563781916205589679L'
assert self.client.lisk_get_address([2147483692, 2147483782, 2147483648, 2147483649]) == '1874186517773691964L'
assert self.client.lisk_get_address([2147483692, 2147483782, 2147484647, 2147484647]) == '16295203558710684671L'
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) == "1874186517773691964L"
assert (
lisk.get_address(self.client, parse_path("m/44h/134h/999h/999h"))
== "16295203558710684671L"
)

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

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

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

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

@ -16,6 +16,8 @@
import pytest
from trezorlib import btc, debuglink, device
from .common import TrezorTest
@ -33,12 +35,12 @@ class TestDeviceLoad(TrezorTest):
passphrase_protection = self.client.debug.read_passphrase_protection()
assert passphrase_protection is False
address = self.client.get_address('Bitcoin', [])
assert address == '1EfKbQupktEMXf4gujJ9kCFo83k1iMqwqK'
address = btc.get_address(self.client, "Bitcoin", [])
assert address == "1EfKbQupktEMXf4gujJ9kCFo83k1iMqwqK"
def test_load_device_2(self):
self.setup_mnemonic_pin_passphrase()
self.client.set_passphrase('passphrase')
self.client.set_passphrase("passphrase")
mnemonic = self.client.debug.read_mnemonic()
assert mnemonic == self.mnemonic12
@ -49,39 +51,79 @@ class TestDeviceLoad(TrezorTest):
passphrase_protection = self.client.debug.read_passphrase_protection()
assert passphrase_protection is True
address = self.client.get_address('Bitcoin', [])
assert address == '15fiTDFwZd2kauHYYseifGi9daH2wniDHH'
address = btc.get_address(self.client, "Bitcoin", [])
assert address == "15fiTDFwZd2kauHYYseifGi9daH2wniDHH"
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_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_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_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'
self.client.wipe_device()
self.client.load_device_by_mnemonic(mnemonic=words_nfkd, pin='', passphrase_protection=True, label='test', language='english', skip_checksum=True)
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_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"
passphrase_nfkd = (
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)
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)
address_nfkd = self.client.get_address('Bitcoin', [])
self.client.wipe_device()
self.client.load_device_by_mnemonic(mnemonic=words_nfc, pin='', passphrase_protection=True, label='test', language='english', skip_checksum=True)
address_nfkd = btc.get_address(self.client, "Bitcoin", [])
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,
)
self.client.set_passphrase(passphrase_nfc)
address_nfc = self.client.get_address('Bitcoin', [])
self.client.wipe_device()
self.client.load_device_by_mnemonic(mnemonic=words_nfkc, pin='', passphrase_protection=True, label='test', language='english', skip_checksum=True)
address_nfc = btc.get_address(self.client, "Bitcoin", [])
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,
)
self.client.set_passphrase(passphrase_nfkc)
address_nfkc = self.client.get_address('Bitcoin', [])
self.client.wipe_device()
self.client.load_device_by_mnemonic(mnemonic=words_nfd, pin='', passphrase_protection=True, label='test', language='english', skip_checksum=True)
address_nfkc = btc.get_address(self.client, "Bitcoin", [])
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,
)
self.client.set_passphrase(passphrase_nfd)
address_nfd = self.client.get_address('Bitcoin', [])
address_nfd = btc.get_address(self.client, "Bitcoin", [])
assert address_nfkd == address_nfc
assert address_nfkd == address_nfkc

@ -16,28 +16,43 @@
import pytest
from trezorlib import btc, debuglink
from .common import TrezorTest
@pytest.mark.skip_t2
class TestDeviceLoadXprv(TrezorTest):
def test_load_device_xprv_1(self):
self.client.load_device_by_xprv(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()
assert passphrase_protection is False
address = self.client.get_address('Bitcoin', [])
assert address == '128RdrAkJDmqasgvfRf6MC5VcX4HKqH4mR'
address = btc.get_address(self.client, "Bitcoin", [])
assert address == "128RdrAkJDmqasgvfRf6MC5VcX4HKqH4mR"
def test_load_device_xprv_2(self):
self.client.load_device_by_xprv(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()
assert passphrase_protection is True
address = self.client.get_address('Bitcoin', [])
assert address == '1CHUbFa4wTTPYgkYaw2LHSd5D4qJjMU8ri'
address = btc.get_address(self.client, "Bitcoin", [])
assert address == "1CHUbFa4wTTPYgkYaw2LHSd5D4qJjMU8ri"

@ -16,14 +16,21 @@
import pytest
from .common import TrezorTest
from trezorlib import nem
from trezorlib.tools import parse_path
from .common import TrezorTest
@pytest.mark.nem
class TestMsgNEMGetaddress(TrezorTest):
def test_nem_getaddress(self):
self.setup_mnemonic_nopin_nopassphrase()
assert self.client.nem_get_address(parse_path("m/44'/1'/0'/0'/0'"), 0x68) == "NB3JCHVARQNGDS3UVGAJPTFE22UQFGMCQGHUBWQN"
assert self.client.nem_get_address(parse_path("m/44'/1'/0'/0'/0'"), 0x98) == "TB3JCHVARQNGDS3UVGAJPTFE22UQFGMCQHSBNBMF"
assert (
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"
)

@ -14,162 +14,160 @@
# 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>.
import pytest
from binascii import hexlify
from .common import TrezorTest
import pytest
from trezorlib import nem
from trezorlib.tools import parse_path
from .common import TrezorTest
# assertion data from T1
@pytest.mark.nem
@pytest.mark.skip_t2
class TestMsgNEMSignTxMosaics(TrezorTest):
def test_nem_signtx_mosaic_supply_change(self):
self.setup_mnemonic_nopin_nopassphrase()
tx = self.client.nem_sign_tx(parse_path("m/44'/1'/0'/0'/0'"), {
"timeStamp": 74649215,
"fee": 2000000,
"type": nem.TYPE_MOSAIC_SUPPLY_CHANGE,
"deadline": 74735615,
"message": {
},
"mosaicId": {
"namespaceId": "hellom",
"name": "Hello mosaic"
tx = nem.sign_tx(
self.client,
parse_path("m/44'/1'/0'/0'/0'"),
{
"timeStamp": 74649215,
"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,
},
"supplyType": 1,
"delta": 1,
"version": (0x98 << 24),
"creationFeeSink": "TALICE2GMA34CXHD7XLJQ536NM5UNKQHTORNNT2J",
"creationFee": 1500,
})
)
assert hexlify(tx.data) == b'02400000010000987f0e730420000000edfd32f6e760648c032f9acb4b30d514265f6a5b5f8a7154f2618922b406208480841e0000000000ff5f74041a0000000600000068656c6c6f6d0c00000048656c6c6f206d6f73616963010000000100000000000000'
assert hexlify(tx.signature) == b'928b03c4a69fff35ecf0912066ea705895b3028fad141197d7ea2b56f1eef2a2516455e6f35d318f6fa39e2bb40492ac4ae603260790f7ebc7ea69feb4ca4c0a'
assert (
hexlify(tx.data)
== b"02400000010000987f0e730420000000edfd32f6e760648c032f9acb4b30d514265f6a5b5f8a7154f2618922b406208480841e0000000000ff5f74041a0000000600000068656c6c6f6d0c00000048656c6c6f206d6f73616963010000000100000000000000"
)
assert (
hexlify(tx.signature)
== b"928b03c4a69fff35ecf0912066ea705895b3028fad141197d7ea2b56f1eef2a2516455e6f35d318f6fa39e2bb40492ac4ae603260790f7ebc7ea69feb4ca4c0a"
)
def test_nem_signtx_mosaic_creation(self):
self.setup_mnemonic_nopin_nopassphrase()
tx = self.client.nem_sign_tx(parse_path("m/44'/1'/0'/0'/0'"), {
"timeStamp": 74649215,
"fee": 2000000,
"type": nem.TYPE_MOSAIC_CREATION,
"deadline": 74735615,
"message": {
},
"mosaicDefinition": {
"id": {
"namespaceId": "hellom",
"name": "Hello mosaic"
tx = nem.sign_tx(
self.client,
parse_path("m/44'/1'/0'/0'/0'"),
{
"timeStamp": 74649215,
"fee": 2000000,
"type": nem.TYPE_MOSAIC_CREATION,
"deadline": 74735615,
"message": {},
"mosaicDefinition": {
"id": {"namespaceId": "hellom", "name": "Hello mosaic"},
"levy": {},
"properties": {},
"description": "lorem",
},
"levy": {},
"properties": {},
"description": "lorem"
"version": (0x98 << 24),
"creationFeeSink": "TALICE2GMA34CXHD7XLJQ536NM5UNKQHTORNNT2J",
"creationFee": 1500,
},
"version": (0x98 << 24),
"creationFeeSink": "TALICE2GMA34CXHD7XLJQ536NM5UNKQHTORNNT2J",
"creationFee": 1500,
})
)
assert hexlify(tx.data) == b'01400000010000987f0e730420000000edfd32f6e760648c032f9acb4b30d514265f6a5b5f8a7154f2618922b406208480841e0000000000ff5f7404c100000020000000edfd32f6e760648c032f9acb4b30d514265f6a5b5f8a7154f2618922b40620841a0000000600000068656c6c6f6d0c00000048656c6c6f206d6f73616963050000006c6f72656d04000000150000000c00000064697669736962696c6974790100000030160000000d000000696e697469616c537570706c7901000000301a0000000d000000737570706c794d757461626c650500000066616c7365190000000c0000007472616e7366657261626c650500000066616c7365000000002800000054414c49434532474d4133344358484437584c4a513533364e4d35554e4b5148544f524e4e54324adc05000000000000'
assert hexlify(tx.signature) == b'537adf4fd9bd5b46e204b2db0a435257a951ed26008305e0aa9e1201dafa4c306d7601a8dbacabf36b5137724386124958d53202015ab31fb3d0849dfed2df0e'
assert (
hexlify(tx.data)
== b"01400000010000987f0e730420000000edfd32f6e760648c032f9acb4b30d514265f6a5b5f8a7154f2618922b406208480841e0000000000ff5f7404c100000020000000edfd32f6e760648c032f9acb4b30d514265f6a5b5f8a7154f2618922b40620841a0000000600000068656c6c6f6d0c00000048656c6c6f206d6f73616963050000006c6f72656d04000000150000000c00000064697669736962696c6974790100000030160000000d000000696e697469616c537570706c7901000000301a0000000d000000737570706c794d757461626c650500000066616c7365190000000c0000007472616e7366657261626c650500000066616c7365000000002800000054414c49434532474d4133344358484437584c4a513533364e4d35554e4b5148544f524e4e54324adc05000000000000"
)
assert (
hexlify(tx.signature)
== b"537adf4fd9bd5b46e204b2db0a435257a951ed26008305e0aa9e1201dafa4c306d7601a8dbacabf36b5137724386124958d53202015ab31fb3d0849dfed2df0e"
)
def test_nem_signtx_mosaic_creation_properties(self):
self.setup_mnemonic_nopin_nopassphrase()
tx = self.client.nem_sign_tx(parse_path("m/44'/1'/0'/0'/0'"), {
"timeStamp": 74649215,
"fee": 2000000,
"type": nem.TYPE_MOSAIC_CREATION,
"deadline": 74735615,
"message": {
},
"mosaicDefinition": {
"id": {
"namespaceId": "hellom",
"name": "Hello mosaic"
tx = nem.sign_tx(
self.client,
parse_path("m/44'/1'/0'/0'/0'"),
{
"timeStamp": 74649215,
"fee": 2000000,
"type": nem.TYPE_MOSAIC_CREATION,
"deadline": 74735615,
"message": {},
"mosaicDefinition": {
"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": {},
"properties": [
{
"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,
},
"version": (0x98 << 24),
"creationFeeSink": "TALICE2GMA34CXHD7XLJQ536NM5UNKQHTORNNT2J",
"creationFee": 1500,
})
)
assert hexlify(tx.data) == b'01400000010000987f0e730420000000edfd32f6e760648c032f9acb4b30d514265f6a5b5f8a7154f2618922b406208480841e0000000000ff5f7404c200000020000000edfd32f6e760648c032f9acb4b30d514265f6a5b5f8a7154f2618922b40620841a0000000600000068656c6c6f6d0c00000048656c6c6f206d6f73616963050000006c6f72656d04000000150000000c00000064697669736962696c6974790100000034180000000d000000696e697469616c537570706c79030000003230301a0000000d000000737570706c794d757461626c650500000066616c7365180000000c0000007472616e7366657261626c650400000074727565000000002800000054414c49434532474d4133344358484437584c4a513533364e4d35554e4b5148544f524e4e54324adc05000000000000'
assert hexlify(tx.signature) == b'f17c859710060f2ea9a0ab740ef427431cf36bdc7d263570ca282bd66032e9f5737a921be9839429732e663be2bb74ccc16f34f5157ff2ef00a65796b54e800e'
assert (
hexlify(tx.data)
== b"01400000010000987f0e730420000000edfd32f6e760648c032f9acb4b30d514265f6a5b5f8a7154f2618922b406208480841e0000000000ff5f7404c200000020000000edfd32f6e760648c032f9acb4b30d514265f6a5b5f8a7154f2618922b40620841a0000000600000068656c6c6f6d0c00000048656c6c6f206d6f73616963050000006c6f72656d04000000150000000c00000064697669736962696c6974790100000034180000000d000000696e697469616c537570706c79030000003230301a0000000d000000737570706c794d757461626c650500000066616c7365180000000c0000007472616e7366657261626c650400000074727565000000002800000054414c49434532474d4133344358484437584c4a513533364e4d35554e4b5148544f524e4e54324adc05000000000000"
)
assert (
hexlify(tx.signature)
== b"f17c859710060f2ea9a0ab740ef427431cf36bdc7d263570ca282bd66032e9f5737a921be9839429732e663be2bb74ccc16f34f5157ff2ef00a65796b54e800e"
)
def test_nem_signtx_mosaic_creation_levy(self):
self.setup_mnemonic_nopin_nopassphrase()
tx = self.client.nem_sign_tx(parse_path("m/44'/1'/0'/0'/0'"), {
"timeStamp": 74649215,
"fee": 2000000,
"type": nem.TYPE_MOSAIC_CREATION,
"deadline": 74735615,
"message": {
},
"mosaicDefinition": {
"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"
tx = nem.sign_tx(
self.client,
parse_path("m/44'/1'/0'/0'/0'"),
{
"timeStamp": 74649215,
"fee": 2000000,
"type": nem.TYPE_MOSAIC_CREATION,
"deadline": 74735615,
"message": {},
"mosaicDefinition": {
"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",
},
"description": "lorem"
"version": (0x98 << 24),
"creationFeeSink": "TALICE2GMA34CXHD7XLJQ536NM5UNKQHTORNNT2J",
"creationFee": 1500,
},
"version": (0x98 << 24),
"creationFeeSink": "TALICE2GMA34CXHD7XLJQ536NM5UNKQHTORNNT2J",
"creationFee": 1500,
})
assert hexlify(tx.data) == b'01400000010000987f0e730420000000edfd32f6e760648c032f9acb4b30d514265f6a5b5f8a7154f2618922b406208480841e0000000000ff5f74041801000020000000edfd32f6e760648c032f9acb4b30d514265f6a5b5f8a7154f2618922b40620841a0000000600000068656c6c6f6d0c00000048656c6c6f206d6f73616963050000006c6f72656d04000000150000000c00000064697669736962696c6974790100000034180000000d000000696e697469616c537570706c79030000003230301a0000000d000000737570706c794d757461626c650500000066616c7365180000000c0000007472616e7366657261626c65040000007472756556000000010000002800000054414c49434532474d4133344358484437584c4a513533364e4d35554e4b5148544f524e4e54324a1a0000000600000068656c6c6f6d0c00000048656c6c6f206d6f7361696302000000000000002800000054414c49434532474d4133344358484437584c4a513533364e4d35554e4b5148544f524e4e54324adc05000000000000'
assert hexlify(tx.signature) == b'b87aac1ddf146d35e6a7f3451f57e2fe504ac559031e010a51261257c37bd50fcfa7b2939dd7a3203b54c4807d458475182f5d3dc135ec0d1d4a9cd42159fd0a'
)
assert (
hexlify(tx.data)
== b"01400000010000987f0e730420000000edfd32f6e760648c032f9acb4b30d514265f6a5b5f8a7154f2618922b406208480841e0000000000ff5f74041801000020000000edfd32f6e760648c032f9acb4b30d514265f6a5b5f8a7154f2618922b40620841a0000000600000068656c6c6f6d0c00000048656c6c6f206d6f73616963050000006c6f72656d04000000150000000c00000064697669736962696c6974790100000034180000000d000000696e697469616c537570706c79030000003230301a0000000d000000737570706c794d757461626c650500000066616c7365180000000c0000007472616e7366657261626c65040000007472756556000000010000002800000054414c49434532474d4133344358484437584c4a513533364e4d35554e4b5148544f524e4e54324a1a0000000600000068656c6c6f6d0c00000048656c6c6f206d6f7361696302000000000000002800000054414c49434532474d4133344358484437584c4a513533364e4d35554e4b5148544f524e4e54324adc05000000000000"
)
assert (
hexlify(tx.signature)
== b"b87aac1ddf146d35e6a7f3451f57e2fe504ac559031e010a51261257c37bd50fcfa7b2939dd7a3203b54c4807d458475182f5d3dc135ec0d1d4a9cd42159fd0a"
)

@ -14,45 +14,51 @@
# 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>.
import time
from binascii import hexlify
import pytest
import time
from .common import TrezorTest
from trezorlib import messages as proto
from trezorlib import nem
from trezorlib import messages as proto, nem
from trezorlib.tools import parse_path
from .common import TrezorTest
# assertion data from T1
@pytest.mark.nem
@pytest.mark.skip_t1
class TestMsgNEMSignTxMosaics(TrezorTest):
def test_nem_signtx_mosaic_supply_change(self):
self.setup_mnemonic_nopin_nopassphrase()
with self.client:
tx = self.client.nem_sign_tx(parse_path("m/44'/1'/0'/0'/0'"), {
"timeStamp": 74649215,
"fee": 2000000,
"type": nem.TYPE_MOSAIC_SUPPLY_CHANGE,
"deadline": 74735615,
"message": {
tx = nem.sign_tx(
self.client,
parse_path("m/44'/1'/0'/0'/0'"),
{
"timeStamp": 74649215,
"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 hexlify(tx.signature) == b'928b03c4a69fff35ecf0912066ea705895b3028fad141197d7ea2b56f1eef2a2516455e6f35d318f6fa39e2bb40492ac4ae603260790f7ebc7ea69feb4ca4c0a'
assert (
hexlify(tx.data)
== b"02400000010000987f0e730420000000edfd32f6e760648c032f9acb4b30d514265f6a5b5f8a7154f2618922b406208480841e0000000000ff5f74041a0000000600000068656c6c6f6d0c00000048656c6c6f206d6f73616963010000000100000000000000"
)
assert (
hexlify(tx.signature)
== b"928b03c4a69fff35ecf0912066ea705895b3028fad141197d7ea2b56f1eef2a2516455e6f35d318f6fa39e2bb40492ac4ae603260790f7ebc7ea69feb4ca4c0a"
)
def test_nem_signtx_mosaic_creation(self):
self.setup_mnemonic_nopin_nopassphrase()
@ -62,16 +68,12 @@ class TestMsgNEMSignTxMosaics(TrezorTest):
"fee": 2000000,
"type": nem.TYPE_MOSAIC_CREATION,
"deadline": 74735615,
"message": {
},
"message": {},
"mosaicDefinition": {
"id": {
"namespaceId": "hellom",
"name": "Hello mosaic"
},
"id": {"namespaceId": "hellom", "name": "Hello mosaic"},
"levy": {},
"properties": {},
"description": "lorem"
"description": "lorem",
},
"version": (0x98 << 24),
"creationFeeSink": "TALICE2GMA34CXHD7XLJQ536NM5UNKQHTORNNT2J",
@ -80,8 +82,14 @@ class TestMsgNEMSignTxMosaics(TrezorTest):
# not using client.nem_sign_tx() because of swiping
tx = self._nem_sign(2, test_suite)
assert hexlify(tx.data) == b'01400000010000987f0e730420000000edfd32f6e760648c032f9acb4b30d514265f6a5b5f8a7154f2618922b406208480841e0000000000ff5f7404c100000020000000edfd32f6e760648c032f9acb4b30d514265f6a5b5f8a7154f2618922b40620841a0000000600000068656c6c6f6d0c00000048656c6c6f206d6f73616963050000006c6f72656d04000000150000000c00000064697669736962696c6974790100000030160000000d000000696e697469616c537570706c7901000000301a0000000d000000737570706c794d757461626c650500000066616c7365190000000c0000007472616e7366657261626c650500000066616c7365000000002800000054414c49434532474d4133344358484437584c4a513533364e4d35554e4b5148544f524e4e54324adc05000000000000'
assert hexlify(tx.signature) == b'537adf4fd9bd5b46e204b2db0a435257a951ed26008305e0aa9e1201dafa4c306d7601a8dbacabf36b5137724386124958d53202015ab31fb3d0849dfed2df0e'
assert (
hexlify(tx.data)
== b"01400000010000987f0e730420000000edfd32f6e760648c032f9acb4b30d514265f6a5b5f8a7154f2618922b406208480841e0000000000ff5f7404c100000020000000edfd32f6e760648c032f9acb4b30d514265f6a5b5f8a7154f2618922b40620841a0000000600000068656c6c6f6d0c00000048656c6c6f206d6f73616963050000006c6f72656d04000000150000000c00000064697669736962696c6974790100000030160000000d000000696e697469616c537570706c7901000000301a0000000d000000737570706c794d757461626c650500000066616c7365190000000c0000007472616e7366657261626c650500000066616c7365000000002800000054414c49434532474d4133344358484437584c4a513533364e4d35554e4b5148544f524e4e54324adc05000000000000"
)
assert (
hexlify(tx.signature)
== b"537adf4fd9bd5b46e204b2db0a435257a951ed26008305e0aa9e1201dafa4c306d7601a8dbacabf36b5137724386124958d53202015ab31fb3d0849dfed2df0e"
)
def test_nem_signtx_mosaic_creation_properties(self):
self.setup_mnemonic_nopin_nopassphrase()
@ -91,33 +99,17 @@ class TestMsgNEMSignTxMosaics(TrezorTest):
"fee": 2000000,
"type": nem.TYPE_MOSAIC_CREATION,
"deadline": 74735615,
"message": {
},
"message": {},
"mosaicDefinition": {
"id": {
"namespaceId": "hellom",
"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"
}
{"name": "divisibility", "value": "4"},
{"name": "initialSupply", "value": "200"},
{"name": "supplyMutable", "value": "false"},
{"name": "transferable", "value": "true"},
],
"description": "lorem"
"description": "lorem",
},
"version": (0x98 << 24),
"creationFeeSink": "TALICE2GMA34CXHD7XLJQ536NM5UNKQHTORNNT2J",
@ -126,8 +118,14 @@ class TestMsgNEMSignTxMosaics(TrezorTest):
# not using client.nem_sign_tx() because of swiping
tx = self._nem_sign(2, test_suite)
assert hexlify(tx.data) == b'01400000010000987f0e730420000000edfd32f6e760648c032f9acb4b30d514265f6a5b5f8a7154f2618922b406208480841e0000000000ff5f7404c200000020000000edfd32f6e760648c032f9acb4b30d514265f6a5b5f8a7154f2618922b40620841a0000000600000068656c6c6f6d0c00000048656c6c6f206d6f73616963050000006c6f72656d04000000150000000c00000064697669736962696c6974790100000034180000000d000000696e697469616c537570706c79030000003230301a0000000d000000737570706c794d757461626c650500000066616c7365180000000c0000007472616e7366657261626c650400000074727565000000002800000054414c49434532474d4133344358484437584c4a513533364e4d35554e4b5148544f524e4e54324adc05000000000000'
assert hexlify(tx.signature) == b'f17c859710060f2ea9a0ab740ef427431cf36bdc7d263570ca282bd66032e9f5737a921be9839429732e663be2bb74ccc16f34f5157ff2ef00a65796b54e800e'
assert (
hexlify(tx.data)
== b"01400000010000987f0e730420000000edfd32f6e760648c032f9acb4b30d514265f6a5b5f8a7154f2618922b406208480841e0000000000ff5f7404c200000020000000edfd32f6e760648c032f9acb4b30d514265f6a5b5f8a7154f2618922b40620841a0000000600000068656c6c6f6d0c00000048656c6c6f206d6f73616963050000006c6f72656d04000000150000000c00000064697669736962696c6974790100000034180000000d000000696e697469616c537570706c79030000003230301a0000000d000000737570706c794d757461626c650500000066616c7365180000000c0000007472616e7366657261626c650400000074727565000000002800000054414c49434532474d4133344358484437584c4a513533364e4d35554e4b5148544f524e4e54324adc05000000000000"
)
assert (
hexlify(tx.signature)
== b"f17c859710060f2ea9a0ab740ef427431cf36bdc7d263570ca282bd66032e9f5737a921be9839429732e663be2bb74ccc16f34f5157ff2ef00a65796b54e800e"
)
def test_nem_signtx_mosaic_creation_levy(self):
self.setup_mnemonic_nopin_nopassphrase()
@ -137,41 +135,22 @@ class TestMsgNEMSignTxMosaics(TrezorTest):
"fee": 2000000,
"type": nem.TYPE_MOSAIC_CREATION,
"deadline": 74735615,
"message": {
},
"message": {},
"mosaicDefinition": {
"id": {
"namespaceId": "hellom",
"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"
}
{"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"
},
"mosaicId": {"namespaceId": "hellom", "name": "Hello mosaic"},
},
"description": "lorem"
"description": "lorem",
},
"version": (0x98 << 24),
"creationFeeSink": "TALICE2GMA34CXHD7XLJQ536NM5UNKQHTORNNT2J",
@ -179,12 +158,17 @@ class TestMsgNEMSignTxMosaics(TrezorTest):
}
tx = self._nem_sign(6, test_suite)
assert hexlify(tx.data) == b'01400000010000987f0e730420000000edfd32f6e760648c032f9acb4b30d514265f6a5b5f8a7154f2618922b406208480841e0000000000ff5f74041801000020000000edfd32f6e760648c032f9acb4b30d514265f6a5b5f8a7154f2618922b40620841a0000000600000068656c6c6f6d0c00000048656c6c6f206d6f73616963050000006c6f72656d04000000150000000c00000064697669736962696c6974790100000034180000000d000000696e697469616c537570706c79030000003230301a0000000d000000737570706c794d757461626c650500000066616c7365180000000c0000007472616e7366657261626c65040000007472756556000000010000002800000054414c49434532474d4133344358484437584c4a513533364e4d35554e4b5148544f524e4e54324a1a0000000600000068656c6c6f6d0c00000048656c6c6f206d6f7361696302000000000000002800000054414c49434532474d4133344358484437584c4a513533364e4d35554e4b5148544f524e4e54324adc05000000000000'
assert hexlify(tx.signature) == b'b87aac1ddf146d35e6a7f3451f57e2fe504ac559031e010a51261257c37bd50fcfa7b2939dd7a3203b54c4807d458475182f5d3dc135ec0d1d4a9cd42159fd0a'
assert (
hexlify(tx.data)
== b"01400000010000987f0e730420000000edfd32f6e760648c032f9acb4b30d514265f6a5b5f8a7154f2618922b406208480841e0000000000ff5f74041801000020000000edfd32f6e760648c032f9acb4b30d514265f6a5b5f8a7154f2618922b40620841a0000000600000068656c6c6f6d0c00000048656c6c6f206d6f73616963050000006c6f72656d04000000150000000c00000064697669736962696c6974790100000034180000000d000000696e697469616c537570706c79030000003230301a0000000d000000737570706c794d757461626c650500000066616c7365180000000c0000007472616e7366657261626c65040000007472756556000000010000002800000054414c49434532474d4133344358484437584c4a513533364e4d35554e4b5148544f524e4e54324a1a0000000600000068656c6c6f6d0c00000048656c6c6f206d6f7361696302000000000000002800000054414c49434532474d4133344358484437584c4a513533364e4d35554e4b5148544f524e4e54324adc05000000000000"
)
assert (
hexlify(tx.signature)
== b"b87aac1ddf146d35e6a7f3451f57e2fe504ac559031e010a51261257c37bd50fcfa7b2939dd7a3203b54c4807d458475182f5d3dc135ec0d1d4a9cd42159fd0a"
)
def _nem_sign(self, num_of_swipes, test_suite):
n = parse_path("m/44'/1'/0'/0'/0'")
n = self.client._convert_prime(n)
msg = nem.create_sign_tx(test_suite)
assert msg.transaction is not None
msg.transaction.address_n = n

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

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

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

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

@ -16,21 +16,25 @@
import pytest
from trezorlib import device, messages as proto
from .common import TrezorTest
from trezorlib import messages as proto
@pytest.mark.skip_t2
class TestMsgRecoverydevice(TrezorTest):
def test_pin_passphrase(self):
mnemonic = self.mnemonic12.split(' ')
ret = self.client.call_raw(proto.RecoveryDevice(word_count=12,
passphrase_protection=True,
pin_protection=True,
label='label',
language='english',
enforce_wordlist=True))
mnemonic = self.mnemonic12.split(" ")
ret = self.client.call_raw(
proto.RecoveryDevice(
word_count=12,
passphrase_protection=True,
pin_protection=True,
label="label",
language="english",
enforce_wordlist=True,
)
)
# click through confirmation
assert isinstance(ret, proto.ButtonRequest)
@ -87,13 +91,17 @@ class TestMsgRecoverydevice(TrezorTest):
self.client.call_raw(proto.Cancel())
def test_nopin_nopassphrase(self):
mnemonic = self.mnemonic12.split(' ')
ret = self.client.call_raw(proto.RecoveryDevice(word_count=12,
passphrase_protection=False,
pin_protection=False,
label='label',
language='english',
enforce_wordlist=True))
mnemonic = self.mnemonic12.split(" ")
ret = self.client.call_raw(
proto.RecoveryDevice(
word_count=12,
passphrase_protection=False,
pin_protection=False,
label="label",
language="english",
enforce_wordlist=True,
)
)
# click through confirmation
assert isinstance(ret, proto.ButtonRequest)
@ -137,12 +145,16 @@ class TestMsgRecoverydevice(TrezorTest):
assert isinstance(resp, proto.Success)
def test_word_fail(self):
ret = self.client.call_raw(proto.RecoveryDevice(word_count=12,
passphrase_protection=False,
pin_protection=False,
label='label',
language='english',
enforce_wordlist=True))
ret = self.client.call_raw(
proto.RecoveryDevice(
word_count=12,
passphrase_protection=False,
pin_protection=False,
label="label",
language="english",
enforce_wordlist=True,
)
)
# click through confirmation
assert isinstance(ret, proto.ButtonRequest)
@ -153,19 +165,23 @@ class TestMsgRecoverydevice(TrezorTest):
for _ in range(int(12 * 2)):
(word, pos) = self.client.debug.read_recovery_word()
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)
break
else:
self.client.call_raw(proto.WordAck(word=word))
def test_pin_fail(self):
ret = self.client.call_raw(proto.RecoveryDevice(word_count=12,
passphrase_protection=True,
pin_protection=True,
label='label',
language='english',
enforce_wordlist=True))
ret = self.client.call_raw(
proto.RecoveryDevice(
word_count=12,
passphrase_protection=True,
pin_protection=True,
label="label",
language="english",
enforce_wordlist=True,
)
)
# click through confirmation
assert isinstance(ret, proto.ButtonRequest)
@ -189,4 +205,4 @@ class TestMsgRecoverydevice(TrezorTest):
def test_already_initialized(self):
self.setup_mnemonic_nopin_nopassphrase()
with pytest.raises(Exception):
self.client.recovery_device(12, False, False, 'label', 'english')
device.recover(self.client, 12, False, False, "label", "english")

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

@ -18,23 +18,28 @@ import time
import pytest
from trezorlib import device, messages as proto
from .common import TrezorTest
from trezorlib import messages as proto
@pytest.mark.skip_t1
class TestMsgRecoverydeviceT2(TrezorTest):
def test_pin_passphrase(self):
mnemonic = self.mnemonic12.split(' ')
ret = self.client.call_raw(proto.RecoveryDevice(
passphrase_protection=True,
pin_protection=True,
label='label',
enforce_wordlist=True))
mnemonic = self.mnemonic12.split(" ")
ret = self.client.call_raw(
proto.RecoveryDevice(
passphrase_protection=True,
pin_protection=True,
label="label",
enforce_wordlist=True,
)
)
# 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)))
ret = self.client.call_raw(proto.ButtonAck())
@ -48,16 +53,16 @@ class TestMsgRecoverydeviceT2(TrezorTest):
# Enter PIN for first time
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())
# Enter PIN for second time
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())
# Workflow succesfully ended
assert ret == proto.Success(message='Device recovered')
assert ret == proto.Success(message="Device recovered")
# Mnemonic is the same
self.client.init_device()
@ -67,15 +72,20 @@ class TestMsgRecoverydeviceT2(TrezorTest):
assert self.client.features.passphrase_protection is True
def test_nopin_nopassphrase(self):
mnemonic = self.mnemonic12.split(' ')
ret = self.client.call_raw(proto.RecoveryDevice(
passphrase_protection=False,
pin_protection=False,
label='label',
enforce_wordlist=True))
mnemonic = self.mnemonic12.split(" ")
ret = self.client.call_raw(
proto.RecoveryDevice(
passphrase_protection=False,
pin_protection=False,
label="label",
enforce_wordlist=True,
)
)
# 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)))
ret = self.client.call_raw(proto.ButtonAck())
@ -88,7 +98,7 @@ class TestMsgRecoverydeviceT2(TrezorTest):
ret = self.client.transport.read()
# Workflow succesfully ended
assert ret == proto.Success(message='Device recovered')
assert ret == proto.Success(message="Device recovered")
# Mnemonic is the same
self.client.init_device()
@ -100,4 +110,4 @@ class TestMsgRecoverydeviceT2(TrezorTest):
def test_already_initialized(self):
self.setup_mnemonic_nopin_nopassphrase()
with pytest.raises(Exception):
self.client.recovery_device(12, False, False, 'label', 'english')
device.recover(self.client, 12, False, False, "label", "english")

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

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

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

@ -16,39 +16,40 @@
import pytest
from .common import TrezorTest
from .conftest import TREZOR_VERSION
from binascii import hexlify
from trezorlib.client import CallException
from trezorlib import debuglink
from trezorlib.ripple import get_address
from trezorlib.tools import parse_path
from .common import TrezorTest
from .conftest import TREZOR_VERSION
@pytest.mark.ripple
@pytest.mark.skip_t1 # T1 support is not planned
@pytest.mark.xfail(TREZOR_VERSION == 2, reason="T2 support is not yet finished")
class TestMsgRippleGetAddress(TrezorTest):
def test_ripple_get_address(self):
# data from https://iancoleman.io/bip39/#english
self.setup_mnemonic_allallall()
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"))
assert address == 'rBKz5MC2iXdoS3XgnNSYmF69K1Yo4NS3Ws'
assert address == "rBKz5MC2iXdoS3XgnNSYmF69K1Yo4NS3Ws"
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):
# data from https://github.com/you21979/node-ripple-bip32/blob/master/test/test.js
self.client.load_device_by_mnemonic(
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='',
debuglink.load_device_by_mnemonic(
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",
pin="",
passphrase_protection=False,
label='test',
language='english')
label="test",
language="english",
)
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"))
assert address == 'rUt9ULSrUvfCmke8HTFU1szbmFpWzVbBXW'
assert address == "rUt9ULSrUvfCmke8HTFU1szbmFpWzVbBXW"

@ -14,73 +14,94 @@
# 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>.
from binascii import unhexlify
import pytest
from trezorlib import messages, ripple
from trezorlib.tools import CallException, parse_path
from .common import TrezorTest
from .conftest import TREZOR_VERSION
from binascii import unhexlify
from trezorlib import messages
from trezorlib import ripple
from trezorlib.client import CallException
from trezorlib.tools import parse_path
@pytest.mark.ripple
@pytest.mark.skip_t1 # T1 support is not planned
@pytest.mark.xfail(TREZOR_VERSION == 2, reason="T2 support is not yet finished")
class TestMsgRippleSignTx(TrezorTest):
def test_ripple_sign_simple_tx(self):
self.setup_mnemonic_allallall()
msg = ripple.create_sign_tx_msg({
"TransactionType": "Payment",
"Destination": "rBKz5MC2iXdoS3XgnNSYmF69K1Yo4NS3Ws",
"Amount": 100000000,
"Flags": 0x80000000,
"Fee": 100000,
"Sequence": 25,
})
msg = ripple.create_sign_tx_msg(
{
"TransactionType": "Payment",
"Destination": "rBKz5MC2iXdoS3XgnNSYmF69K1Yo4NS3Ws",
"Amount": 100000000,
"Flags": 0x80000000,
"Fee": 100000,
"Sequence": 25,
}
)
resp = ripple.sign_tx(self.client, parse_path("m/44'/144'/0'/0/0"), msg)
assert resp.signature == unhexlify('3045022100e243ef623675eeeb95965c35c3e06d63a9fc68bb37e17dc87af9c0af83ec057e02206ca8aa5eaab8396397aef6d38d25710441faf7c79d292ee1d627df15ad9346c0')
assert resp.serialized_tx == unhexlify('12000022800000002400000019614000000005f5e1006840000000000186a0732102131facd1eab748d6cddc492f54b04e8c35658894f4add2232ebc5afe7521dbe474473045022100e243ef623675eeeb95965c35c3e06d63a9fc68bb37e17dc87af9c0af83ec057e02206ca8aa5eaab8396397aef6d38d25710441faf7c79d292ee1d627df15ad9346c081148fb40e1ffa5d557ce9851a535af94965e0dd098883147148ebebf7304ccdf1676fefcf9734cf1e780826')
assert resp.signature == unhexlify(
"3045022100e243ef623675eeeb95965c35c3e06d63a9fc68bb37e17dc87af9c0af83ec057e02206ca8aa5eaab8396397aef6d38d25710441faf7c79d292ee1d627df15ad9346c0"
)
assert resp.serialized_tx == unhexlify(
"12000022800000002400000019614000000005f5e1006840000000000186a0732102131facd1eab748d6cddc492f54b04e8c35658894f4add2232ebc5afe7521dbe474473045022100e243ef623675eeeb95965c35c3e06d63a9fc68bb37e17dc87af9c0af83ec057e02206ca8aa5eaab8396397aef6d38d25710441faf7c79d292ee1d627df15ad9346c081148fb40e1ffa5d557ce9851a535af94965e0dd098883147148ebebf7304ccdf1676fefcf9734cf1e780826"
)
msg = ripple.create_sign_tx_msg({
"TransactionType": "Payment",
"Destination": "rNaqKtKrMSwpwZSzRckPf7S96DkimjkF4H",
"Amount": 1,
"Fee": 10,
"Sequence": 1,
})
msg = ripple.create_sign_tx_msg(
{
"TransactionType": "Payment",
"Destination": "rNaqKtKrMSwpwZSzRckPf7S96DkimjkF4H",
"Amount": 1,
"Fee": 10,
"Sequence": 1,
}
)
resp = ripple.sign_tx(self.client, parse_path("m/44'/144'/0'/0/2"), msg)
assert resp.signature == unhexlify('3044022069900e6e578997fad5189981b74b16badc7ba8b9f1052694033fa2779113ddc002206c8006ada310edf099fb22c0c12073550c8fc73247b236a974c5f1144831dd5f')
assert resp.serialized_tx == unhexlify('1200002280000000240000000161400000000000000168400000000000000a732103dbed1e77cb91a005e2ec71afbccce5444c9be58276665a3859040f692de8fed274463044022069900e6e578997fad5189981b74b16badc7ba8b9f1052694033fa2779113ddc002206c8006ada310edf099fb22c0c12073550c8fc73247b236a974c5f1144831dd5f8114bdf86f3ae715ba346b7772ea0e133f48828b766483148fb40e1ffa5d557ce9851a535af94965e0dd0988')
assert resp.signature == unhexlify(
"3044022069900e6e578997fad5189981b74b16badc7ba8b9f1052694033fa2779113ddc002206c8006ada310edf099fb22c0c12073550c8fc73247b236a974c5f1144831dd5f"
)
assert resp.serialized_tx == unhexlify(
"1200002280000000240000000161400000000000000168400000000000000a732103dbed1e77cb91a005e2ec71afbccce5444c9be58276665a3859040f692de8fed274463044022069900e6e578997fad5189981b74b16badc7ba8b9f1052694033fa2779113ddc002206c8006ada310edf099fb22c0c12073550c8fc73247b236a974c5f1144831dd5f8114bdf86f3ae715ba346b7772ea0e133f48828b766483148fb40e1ffa5d557ce9851a535af94965e0dd0988"
)
msg = ripple.create_sign_tx_msg({
"TransactionType": "Payment",
"Destination": "rNaqKtKrMSwpwZSzRckPf7S96DkimjkF4H",
"Amount": 100000009,
"Flags": 0,
"Fee": 100,
"Sequence": 100,
"LastLedgerSequence": 333111,
})
msg = ripple.create_sign_tx_msg(
{
"TransactionType": "Payment",
"Destination": "rNaqKtKrMSwpwZSzRckPf7S96DkimjkF4H",
"Amount": 100000009,
"Flags": 0,
"Fee": 100,
"Sequence": 100,
"LastLedgerSequence": 333111,
}
)
resp = ripple.sign_tx(self.client, parse_path("m/44'/144'/0'/0/2"), msg)
assert resp.signature == unhexlify('30440220025a9cc2809527799e6ea5eb029488dc46c6632a8ca1ed7d3ca2d9211e80403a02202cfe8604e6c6d1d3c64246626cc1a1a9bd8a2163b969e561c6adda5dca8fc2a5')
assert resp.serialized_tx == unhexlify('12000022800000002400000064201b00051537614000000005f5e109684000000000000064732103dbed1e77cb91a005e2ec71afbccce5444c9be58276665a3859040f692de8fed2744630440220025a9cc2809527799e6ea5eb029488dc46c6632a8ca1ed7d3ca2d9211e80403a02202cfe8604e6c6d1d3c64246626cc1a1a9bd8a2163b969e561c6adda5dca8fc2a58114bdf86f3ae715ba346b7772ea0e133f48828b766483148fb40e1ffa5d557ce9851a535af94965e0dd0988')
assert resp.signature == unhexlify(
"30440220025a9cc2809527799e6ea5eb029488dc46c6632a8ca1ed7d3ca2d9211e80403a02202cfe8604e6c6d1d3c64246626cc1a1a9bd8a2163b969e561c6adda5dca8fc2a5"
)
assert resp.serialized_tx == unhexlify(
"12000022800000002400000064201b00051537614000000005f5e109684000000000000064732103dbed1e77cb91a005e2ec71afbccce5444c9be58276665a3859040f692de8fed2744630440220025a9cc2809527799e6ea5eb029488dc46c6632a8ca1ed7d3ca2d9211e80403a02202cfe8604e6c6d1d3c64246626cc1a1a9bd8a2163b969e561c6adda5dca8fc2a58114bdf86f3ae715ba346b7772ea0e133f48828b766483148fb40e1ffa5d557ce9851a535af94965e0dd0988"
)
def test_ripple_sign_invalid_fee(self):
self.setup_mnemonic_allallall()
msg = ripple.create_sign_tx_msg({
"TransactionType": "Payment",
"Destination": "rNaqKtKrMSwpwZSzRckPf7S96DkimjkF4H",
"Amount": 1,
"Flags": 1,
"Fee": 1,
"Sequence": 1,
})
msg = ripple.create_sign_tx_msg(
{
"TransactionType": "Payment",
"Destination": "rNaqKtKrMSwpwZSzRckPf7S96DkimjkF4H",
"Amount": 1,
"Flags": 1,
"Fee": 1,
"Sequence": 1,
}
)
with pytest.raises(CallException) as exc:
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[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"
)

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

@ -16,45 +16,70 @@
from binascii import hexlify
from trezorlib import btc
from .common import TrezorTest
class TestMsgSignmessage(TrezorTest):
def test_sign(self):
self.setup_mnemonic_nopin_nopassphrase()
sig = self.client.sign_message('Bitcoin', [0], "This is an example of a signed message.")
assert sig.address == '14LmW5k4ssUrtbAB4255zdqv3b4w1TuX9e'
assert hexlify(sig.signature) == b'209e23edf0e4e47ff1dec27f32cd78c50e74ef018ee8a6adf35ae17c7a9b0dd96f48b493fd7dbab03efb6f439c6383c9523b3bbc5f1a7d158a6af90ab154e9be80'
sig = btc.sign_message(
self.client, "Bitcoin", [0], "This is an example of a signed message."
)
assert sig.address == "14LmW5k4ssUrtbAB4255zdqv3b4w1TuX9e"
assert (
hexlify(sig.signature)
== b"209e23edf0e4e47ff1dec27f32cd78c50e74ef018ee8a6adf35ae17c7a9b0dd96f48b493fd7dbab03efb6f439c6383c9523b3bbc5f1a7d158a6af90ab154e9be80"
)
def test_sign_testnet(self):
self.setup_mnemonic_nopin_nopassphrase()
sig = self.client.sign_message('Testnet', [0], "This is an example of a signed message.")
assert sig.address == 'mirio8q3gtv7fhdnmb3TpZ4EuafdzSs7zL'
assert hexlify(sig.signature) == b'209e23edf0e4e47ff1dec27f32cd78c50e74ef018ee8a6adf35ae17c7a9b0dd96f48b493fd7dbab03efb6f439c6383c9523b3bbc5f1a7d158a6af90ab154e9be80'
sig = btc.sign_message(
self.client, "Testnet", [0], "This is an example of a signed message."
)
assert sig.address == "mirio8q3gtv7fhdnmb3TpZ4EuafdzSs7zL"
assert (
hexlify(sig.signature)
== b"209e23edf0e4e47ff1dec27f32cd78c50e74ef018ee8a6adf35ae17c7a9b0dd96f48b493fd7dbab03efb6f439c6383c9523b3bbc5f1a7d158a6af90ab154e9be80"
)
def test_sign_bch(self):
self.setup_mnemonic_nopin_nopassphrase()
sig = self.client.sign_message('Bcash', [0], "This is an example of a signed message.")
assert sig.address == 'bitcoincash:qqj22md58nm09vpwsw82fyletkxkq36zxyxh322pru'
assert hexlify(sig.signature) == b'209e23edf0e4e47ff1dec27f32cd78c50e74ef018ee8a6adf35ae17c7a9b0dd96f48b493fd7dbab03efb6f439c6383c9523b3bbc5f1a7d158a6af90ab154e9be80'
sig = btc.sign_message(
self.client, "Bcash", [0], "This is an example of a signed message."
)
assert sig.address == "bitcoincash:qqj22md58nm09vpwsw82fyletkxkq36zxyxh322pru"
assert (
hexlify(sig.signature)
== b"209e23edf0e4e47ff1dec27f32cd78c50e74ef018ee8a6adf35ae17c7a9b0dd96f48b493fd7dbab03efb6f439c6383c9523b3bbc5f1a7d158a6af90ab154e9be80"
)
def test_sign_long(self):
self.setup_mnemonic_nopin_nopassphrase()
sig = self.client.sign_message('Bitcoin', [0], "VeryLongMessage!" * 64)
assert sig.address == '14LmW5k4ssUrtbAB4255zdqv3b4w1TuX9e'
assert hexlify(sig.signature) == b'205ff795c29aef7538f8b3bdb2e8add0d0722ad630a140b6aefd504a5a895cbd867cbb00981afc50edd0398211e8d7c304bb8efa461181bc0afa67ea4a720a89ed'
sig = btc.sign_message(self.client, "Bitcoin", [0], "VeryLongMessage!" * 64)
assert sig.address == "14LmW5k4ssUrtbAB4255zdqv3b4w1TuX9e"
assert (
hexlify(sig.signature)
== b"205ff795c29aef7538f8b3bdb2e8add0d0722ad630a140b6aefd504a5a895cbd867cbb00981afc50edd0398211e8d7c304bb8efa461181bc0afa67ea4a720a89ed"
)
def test_sign_utf(self):
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_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_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"
sig_nfkd = self.client.sign_message('Bitcoin', [0], words_nfkd)
assert sig_nfkd.address == '14LmW5k4ssUrtbAB4255zdqv3b4w1TuX9e'
assert hexlify(sig_nfkd.signature) == b'20d0ec02ed8da8df23e7fe9e680e7867cc290312fe1c970749d8306ddad1a1eda41c6a771b13d495dd225b13b0a9d0f915a984ee3d0703f92287bf8009fbb9f7d6'
sig_nfkd = btc.sign_message(self.client, "Bitcoin", [0], words_nfkd)
assert sig_nfkd.address == "14LmW5k4ssUrtbAB4255zdqv3b4w1TuX9e"
assert (
hexlify(sig_nfkd.signature)
== b"20d0ec02ed8da8df23e7fe9e680e7867cc290312fe1c970749d8306ddad1a1eda41c6a771b13d495dd225b13b0a9d0f915a984ee3d0703f92287bf8009fbb9f7d6"
)
sig_nfc = self.client.sign_message('Bitcoin', [0], words_nfc)
assert sig_nfc.address == '14LmW5k4ssUrtbAB4255zdqv3b4w1TuX9e'
assert hexlify(sig_nfc.signature) == b'20d0ec02ed8da8df23e7fe9e680e7867cc290312fe1c970749d8306ddad1a1eda41c6a771b13d495dd225b13b0a9d0f915a984ee3d0703f92287bf8009fbb9f7d6'
sig_nfc = btc.sign_message(self.client, "Bitcoin", [0], words_nfc)
assert sig_nfc.address == "14LmW5k4ssUrtbAB4255zdqv3b4w1TuX9e"
assert (
hexlify(sig_nfc.signature)
== b"20d0ec02ed8da8df23e7fe9e680e7867cc290312fe1c970749d8306ddad1a1eda41c6a771b13d495dd225b13b0a9d0f915a984ee3d0703f92287bf8009fbb9f7d6"
)

@ -16,40 +16,85 @@
from binascii import hexlify
from trezorlib import btc, messages as proto
from .common import TrezorTest
from trezorlib import messages as proto
class TestMsgSignmessageSegwit(TrezorTest):
def test_sign(self):
self.setup_mnemonic_nopin_nopassphrase()
sig = self.client.sign_message('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'
sig = btc.sign_message(
self.client,
"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):
self.setup_mnemonic_nopin_nopassphrase()
sig = self.client.sign_message('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'
sig = btc.sign_message(
self.client,
"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):
self.setup_mnemonic_nopin_nopassphrase()
sig = self.client.sign_message('Bitcoin', [0], "VeryLongMessage!" * 64, script_type=proto.InputScriptType.SPENDP2SHWITNESS)
assert sig.address == '3CwYaeWxhpXXiHue3ciQez1DLaTEAXcKa1'
assert hexlify(sig.signature) == b'245ff795c29aef7538f8b3bdb2e8add0d0722ad630a140b6aefd504a5a895cbd867cbb00981afc50edd0398211e8d7c304bb8efa461181bc0afa67ea4a720a89ed'
sig = btc.sign_message(
self.client,
"Bitcoin",
[0],
"VeryLongMessage!" * 64,
script_type=proto.InputScriptType.SPENDP2SHWITNESS,
)
assert sig.address == "3CwYaeWxhpXXiHue3ciQez1DLaTEAXcKa1"
assert (
hexlify(sig.signature)
== b"245ff795c29aef7538f8b3bdb2e8add0d0722ad630a140b6aefd504a5a895cbd867cbb00981afc50edd0398211e8d7c304bb8efa461181bc0afa67ea4a720a89ed"
)
def test_sign_utf(self):
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_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_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"
sig_nfkd = self.client.sign_message('Bitcoin', [0], words_nfkd, script_type=proto.InputScriptType.SPENDP2SHWITNESS)
assert sig_nfkd.address == '3CwYaeWxhpXXiHue3ciQez1DLaTEAXcKa1'
assert hexlify(sig_nfkd.signature) == b'24d0ec02ed8da8df23e7fe9e680e7867cc290312fe1c970749d8306ddad1a1eda41c6a771b13d495dd225b13b0a9d0f915a984ee3d0703f92287bf8009fbb9f7d6'
sig_nfkd = btc.sign_message(
self.client,
"Bitcoin",
[0],
words_nfkd,
script_type=proto.InputScriptType.SPENDP2SHWITNESS,
)
assert sig_nfkd.address == "3CwYaeWxhpXXiHue3ciQez1DLaTEAXcKa1"
assert (
hexlify(sig_nfkd.signature)
== b"24d0ec02ed8da8df23e7fe9e680e7867cc290312fe1c970749d8306ddad1a1eda41c6a771b13d495dd225b13b0a9d0f915a984ee3d0703f92287bf8009fbb9f7d6"
)
sig_nfc = self.client.sign_message('Bitcoin', [0], words_nfc, script_type=proto.InputScriptType.SPENDP2SHWITNESS)
assert sig_nfc.address == '3CwYaeWxhpXXiHue3ciQez1DLaTEAXcKa1'
assert hexlify(sig_nfc.signature) == b'24d0ec02ed8da8df23e7fe9e680e7867cc290312fe1c970749d8306ddad1a1eda41c6a771b13d495dd225b13b0a9d0f915a984ee3d0703f92287bf8009fbb9f7d6'
sig_nfc = btc.sign_message(
self.client,
"Bitcoin",
[0],
words_nfc,
script_type=proto.InputScriptType.SPENDP2SHWITNESS,
)
assert sig_nfc.address == "3CwYaeWxhpXXiHue3ciQez1DLaTEAXcKa1"
assert (
hexlify(sig_nfc.signature)
== b"24d0ec02ed8da8df23e7fe9e680e7867cc290312fe1c970749d8306ddad1a1eda41c6a771b13d495dd225b13b0a9d0f915a984ee3d0703f92287bf8009fbb9f7d6"
)

@ -16,40 +16,85 @@
from binascii import hexlify
from trezorlib import btc, messages as proto
from .common import TrezorTest
from trezorlib import messages as proto
class TestMsgSignmessageSegwitNative(TrezorTest):
def test_sign(self):
self.setup_mnemonic_nopin_nopassphrase()
sig = self.client.sign_message('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'
sig = btc.sign_message(
self.client,
"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):
self.setup_mnemonic_nopin_nopassphrase()
sig = self.client.sign_message('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'
sig = btc.sign_message(
self.client,
"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):
self.setup_mnemonic_nopin_nopassphrase()
sig = self.client.sign_message('Bitcoin', [0], "VeryLongMessage!" * 64, script_type=proto.InputScriptType.SPENDWITNESS)
assert sig.address == 'bc1qyjjkmdpu7metqt5r36jf872a34syws33s82q2j'
assert hexlify(sig.signature) == b'285ff795c29aef7538f8b3bdb2e8add0d0722ad630a140b6aefd504a5a895cbd867cbb00981afc50edd0398211e8d7c304bb8efa461181bc0afa67ea4a720a89ed'
sig = btc.sign_message(
self.client,
"Bitcoin",
[0],
"VeryLongMessage!" * 64,
script_type=proto.InputScriptType.SPENDWITNESS,
)
assert sig.address == "bc1qyjjkmdpu7metqt5r36jf872a34syws33s82q2j"
assert (
hexlify(sig.signature)
== b"285ff795c29aef7538f8b3bdb2e8add0d0722ad630a140b6aefd504a5a895cbd867cbb00981afc50edd0398211e8d7c304bb8efa461181bc0afa67ea4a720a89ed"
)
def test_sign_utf(self):
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_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_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"
sig_nfkd = self.client.sign_message('Bitcoin', [0], words_nfkd, script_type=proto.InputScriptType.SPENDWITNESS)
assert sig_nfkd.address == 'bc1qyjjkmdpu7metqt5r36jf872a34syws33s82q2j'
assert hexlify(sig_nfkd.signature) == b'28d0ec02ed8da8df23e7fe9e680e7867cc290312fe1c970749d8306ddad1a1eda41c6a771b13d495dd225b13b0a9d0f915a984ee3d0703f92287bf8009fbb9f7d6'
sig_nfkd = btc.sign_message(
self.client,
"Bitcoin",
[0],
words_nfkd,
script_type=proto.InputScriptType.SPENDWITNESS,
)
assert sig_nfkd.address == "bc1qyjjkmdpu7metqt5r36jf872a34syws33s82q2j"
assert (
hexlify(sig_nfkd.signature)
== b"28d0ec02ed8da8df23e7fe9e680e7867cc290312fe1c970749d8306ddad1a1eda41c6a771b13d495dd225b13b0a9d0f915a984ee3d0703f92287bf8009fbb9f7d6"
)
sig_nfc = self.client.sign_message('Bitcoin', [0], words_nfc, script_type=proto.InputScriptType.SPENDWITNESS)
assert sig_nfc.address == 'bc1qyjjkmdpu7metqt5r36jf872a34syws33s82q2j'
assert hexlify(sig_nfc.signature) == b'28d0ec02ed8da8df23e7fe9e680e7867cc290312fe1c970749d8306ddad1a1eda41c6a771b13d495dd225b13b0a9d0f915a984ee3d0703f92287bf8009fbb9f7d6'
sig_nfc = btc.sign_message(
self.client,
"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

@ -14,22 +14,20 @@
# 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>.
import pytest
from binascii import hexlify, unhexlify
from .common import TrezorTest
from ..support.ckd_public import deserialize
from trezorlib import coins
from trezorlib import messages as proto
from trezorlib.client import CallException
from trezorlib.tools import parse_path
import pytest
from trezorlib import btc, coins, messages as proto
from trezorlib.tools import H_, CallException, parse_path
TxApiBcash = coins.tx_api['Bcash']
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):
self.setup_mnemonic_allallall()
self.client.set_tx_api(TxApiBcash)
@ -37,7 +35,9 @@ class TestMsgSigntxBch(TrezorTest):
address_n=parse_path("44'/145'/0'/0/0"),
# bitcoincash:qr08q88p9etk89wgv05nwlrkm4l0urz4cyl36hh9sv
amount=1995344,
prev_hash=unhexlify('bc37c28dfb467d2ecb50261387bf752a3977d7e5337915071bb4151e6b711a78'),
prev_hash=unhexlify(
"bc37c28dfb467d2ecb50261387bf752a3977d7e5337915071bb4151e6b711a78"
),
prev_index=0,
script_type=proto.InputScriptType.SPENDADDRESS,
)
@ -47,25 +47,50 @@ class TestMsgSigntxBch(TrezorTest):
script_type=proto.OutputScriptType.PAYTOADDRESS,
)
out2 = proto.TxOutputType(
address='bitcoincash:qr23ajjfd9wd73l87j642puf8cad20lfmqdgwvpat4',
address="bitcoincash:qr23ajjfd9wd73l87j642puf8cad20lfmqdgwvpat4",
amount=73452,
script_type=proto.OutputScriptType.PAYTOADDRESS,
)
with self.client:
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(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) = self.client.sign_tx('Bcash', [inp1], [out1, out2])
assert hexlify(serialized_tx) == b'0100000001781a716b1e15b41b07157933e5d777392a75bf87132650cb2e7d46fb8dc237bc000000006a473044022061aee4f17abe044d5df8c52c9ffd3b84e5a29743517e488b20ecf1ae0b3e4d3a02206bb84c55e407f3b684ff8d9bea0a3409cfd865795a19d10b3d3c31f12795c34a412103a020b36130021a0f037c1d1a02042e325c0cb666d6478c1afdcd9d913b9ef080ffffffff0272ee1c00000000001976a914b1401fce7e8bf123c88a0467e0ed11e3b9fbef5488acec1e0100000000001976a914d51eca49695cdf47e7f4b55507893e3ad53fe9d888ac00000000'
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(
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"
)
def test_send_bch_nochange(self):
self.setup_mnemonic_allallall()
@ -74,7 +99,9 @@ class TestMsgSigntxBch(TrezorTest):
address_n=parse_path("44'/145'/0'/1/0"),
# bitcoincash:qzc5q87w069lzg7g3gzx0c8dz83mn7l02scej5aluw
amount=1896050,
prev_hash=unhexlify('502e8577b237b0152843a416f8f1ab0c63321b1be7a8cad7bf5c5c216fcf062c'),
prev_hash=unhexlify(
"502e8577b237b0152843a416f8f1ab0c63321b1be7a8cad7bf5c5c216fcf062c"
),
prev_index=0,
script_type=proto.InputScriptType.SPENDADDRESS,
)
@ -82,30 +109,57 @@ class TestMsgSigntxBch(TrezorTest):
address_n=parse_path("44'/145'/0'/0/1"),
# bitcoincash:qr23ajjfd9wd73l87j642puf8cad20lfmqdgwvpat4
amount=73452,
prev_hash=unhexlify('502e8577b237b0152843a416f8f1ab0c63321b1be7a8cad7bf5c5c216fcf062c'),
prev_hash=unhexlify(
"502e8577b237b0152843a416f8f1ab0c63321b1be7a8cad7bf5c5c216fcf062c"
),
prev_index=1,
script_type=proto.InputScriptType.SPENDADDRESS,
)
out1 = proto.TxOutputType(
address='bitcoincash:qq6wnnkrz7ykaqvxrx4hmjvayvzjzml54uyk76arx4',
address="bitcoincash:qq6wnnkrz7ykaqvxrx4hmjvayvzjzml54uyk76arx4",
amount=1934960,
script_type=proto.OutputScriptType.PAYTOADDRESS,
)
with self.client:
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(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) = self.client.sign_tx('Bcash', [inp1, inp2], [out1])
assert hexlify(serialized_tx) == b'01000000022c06cf6f215c5cbfd7caa8e71b1b32630cabf1f816a4432815b037b277852e50000000006a47304402207a2a955f1cb3dc5f03f2c82934f55654882af4e852e5159639f6349e9386ec4002205fb8419dce4e648eae8f67bc4e369adfb130a87d2ea2d668f8144213b12bb457412103174c61e9c5362507e8061e28d2c0ce3d4df4e73f3535ae0b12f37809e0f92d2dffffffff2c06cf6f215c5cbfd7caa8e71b1b32630cabf1f816a4432815b037b277852e50010000006a473044022062151cf960b71823bbe68c7ed2c2a93ad1b9706a30255fddb02fcbe056d8c26102207bad1f0872bc5f0cfaf22e45c925c35d6c1466e303163b75cb7688038f1a5541412102595caf9aeb6ffdd0e82b150739a83297358b9a77564de382671056ad9e5b8c58ffffffff0170861d00000000001976a91434e9cec317896e818619ab7dc99d2305216ff4af88ac00000000'
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(
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"
)
def test_send_bch_oldaddr(self):
self.setup_mnemonic_allallall()
@ -114,7 +168,9 @@ class TestMsgSigntxBch(TrezorTest):
address_n=parse_path("44'/145'/0'/1/0"),
# bitcoincash:qzc5q87w069lzg7g3gzx0c8dz83mn7l02scej5aluw
amount=1896050,
prev_hash=unhexlify('502e8577b237b0152843a416f8f1ab0c63321b1be7a8cad7bf5c5c216fcf062c'),
prev_hash=unhexlify(
"502e8577b237b0152843a416f8f1ab0c63321b1be7a8cad7bf5c5c216fcf062c"
),
prev_index=0,
script_type=proto.InputScriptType.SPENDADDRESS,
)
@ -122,30 +178,57 @@ class TestMsgSigntxBch(TrezorTest):
address_n=parse_path("44'/145'/0'/0/1"),
# bitcoincash:qr23ajjfd9wd73l87j642puf8cad20lfmqdgwvpat4
amount=73452,
prev_hash=unhexlify('502e8577b237b0152843a416f8f1ab0c63321b1be7a8cad7bf5c5c216fcf062c'),
prev_hash=unhexlify(
"502e8577b237b0152843a416f8f1ab0c63321b1be7a8cad7bf5c5c216fcf062c"
),
prev_index=1,
script_type=proto.InputScriptType.SPENDADDRESS,
)
out1 = proto.TxOutputType(
address='15pnEDZJo3ycPUamqP3tEDnEju1oW5fBCz',
address="15pnEDZJo3ycPUamqP3tEDnEju1oW5fBCz",
amount=1934960,
script_type=proto.OutputScriptType.PAYTOADDRESS,
)
with self.client:
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(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) = self.client.sign_tx('Bcash', [inp1, inp2], [out1])
assert hexlify(serialized_tx) == b'01000000022c06cf6f215c5cbfd7caa8e71b1b32630cabf1f816a4432815b037b277852e50000000006a47304402207a2a955f1cb3dc5f03f2c82934f55654882af4e852e5159639f6349e9386ec4002205fb8419dce4e648eae8f67bc4e369adfb130a87d2ea2d668f8144213b12bb457412103174c61e9c5362507e8061e28d2c0ce3d4df4e73f3535ae0b12f37809e0f92d2dffffffff2c06cf6f215c5cbfd7caa8e71b1b32630cabf1f816a4432815b037b277852e50010000006a473044022062151cf960b71823bbe68c7ed2c2a93ad1b9706a30255fddb02fcbe056d8c26102207bad1f0872bc5f0cfaf22e45c925c35d6c1466e303163b75cb7688038f1a5541412102595caf9aeb6ffdd0e82b150739a83297358b9a77564de382671056ad9e5b8c58ffffffff0170861d00000000001976a91434e9cec317896e818619ab7dc99d2305216ff4af88ac00000000'
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(
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"
)
def test_attack_amount(self):
self.setup_mnemonic_allallall()
@ -154,7 +237,9 @@ class TestMsgSigntxBch(TrezorTest):
address_n=parse_path("44'/145'/0'/1/0"),
# bitcoincash:qzc5q87w069lzg7g3gzx0c8dz83mn7l02scej5aluw
amount=300,
prev_hash=unhexlify('502e8577b237b0152843a416f8f1ab0c63321b1be7a8cad7bf5c5c216fcf062c'),
prev_hash=unhexlify(
"502e8577b237b0152843a416f8f1ab0c63321b1be7a8cad7bf5c5c216fcf062c"
),
prev_index=0,
script_type=proto.InputScriptType.SPENDADDRESS,
)
@ -162,12 +247,14 @@ class TestMsgSigntxBch(TrezorTest):
address_n=parse_path("44'/145'/0'/0/1"),
# bitcoincash:qr23ajjfd9wd73l87j642puf8cad20lfmqdgwvpat4
amount=70,
prev_hash=unhexlify('502e8577b237b0152843a416f8f1ab0c63321b1be7a8cad7bf5c5c216fcf062c'),
prev_hash=unhexlify(
"502e8577b237b0152843a416f8f1ab0c63321b1be7a8cad7bf5c5c216fcf062c"
),
prev_index=1,
script_type=proto.InputScriptType.SPENDADDRESS,
)
out1 = proto.TxOutputType(
address='bitcoincash:qq6wnnkrz7ykaqvxrx4hmjvayvzjzml54uyk76arx4',
address="bitcoincash:qq6wnnkrz7ykaqvxrx4hmjvayvzjzml54uyk76arx4",
amount=200,
script_type=proto.OutputScriptType.PAYTOADDRESS,
)
@ -199,37 +286,83 @@ class TestMsgSigntxBch(TrezorTest):
# test if passes without modifications
with self.client:
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(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),
])
self.client.sign_tx('Bcash', [inp1, inp2], [out1])
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(
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
with self.client:
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(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(),
])
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(
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:
self.client.sign_tx('Bcash', [inp1, inp2], [out1], debug_processor=attack_processor)
assert exc.value.args[0] in (proto.FailureType.ProcessError, proto.FailureType.DataError)
assert exc.value.args[1].endswith('Transaction has changed during signing')
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[1].endswith("Transaction has changed during signing")
def test_attack_change_input(self):
self.setup_mnemonic_allallall()
@ -238,7 +371,9 @@ class TestMsgSigntxBch(TrezorTest):
address_n=parse_path("44'/145'/1000'/0/0"),
# bitcoincash:qr08q88p9etk89wgv05nwlrkm4l0urz4cyl36hh9sv
amount=1995344,
prev_hash=unhexlify('bc37c28dfb467d2ecb50261387bf752a3977d7e5337915071bb4151e6b711a78'),
prev_hash=unhexlify(
"bc37c28dfb467d2ecb50261387bf752a3977d7e5337915071bb4151e6b711a78"
),
prev_index=0,
script_type=proto.InputScriptType.SPENDADDRESS,
)
@ -248,7 +383,7 @@ class TestMsgSigntxBch(TrezorTest):
script_type=proto.OutputScriptType.PAYTOADDRESS,
)
out2 = proto.TxOutputType(
address='bitcoincash:qr23ajjfd9wd73l87j642puf8cad20lfmqdgwvpat4',
address="bitcoincash:qr23ajjfd9wd73l87j642puf8cad20lfmqdgwvpat4",
amount=73452,
script_type=proto.OutputScriptType.PAYTOADDRESS,
)
@ -269,99 +404,182 @@ class TestMsgSigntxBch(TrezorTest):
if attack_ctr <= 1:
return msg
msg.inputs[0].address_n[2] = 1 + 0x80000000
msg.inputs[0].address_n[2] = H_(1)
return msg
with self.client:
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(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),
])
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(
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):
self.client.sign_tx('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):
self.setup_mnemonic_allallall()
self.client.set_tx_api(TxApiBcash)
xpubs = []
for n in map(lambda index: self.client.get_public_node(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)
def getmultisig(chain, nr, signatures=[b'', b'', b''], xpubs=xpubs):
def getmultisig(chain, nr, signatures=[b"", b"", b""], xpubs=xpubs):
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,
m=2,
)
correcthorse = proto.HDNodeType(
depth=1, fingerprint=0, child_num=0,
chain_code=unhexlify('0000000000000000000000000000000000000000000000000000000000000000'),
public_key=unhexlify('0378d430274f8c5ec1321338151e9f27f4c676a008bdf8638d07c0b6be9ab35c71'))
sig = unhexlify(b'304402207274b5a4d15e75f3df7319a375557b0efba9b27bc63f9f183a17da95a6125c94022000efac57629f1522e2d3958430e2ef073b0706cfac06cce492651b79858f09ae')
depth=1,
fingerprint=0,
child_num=0,
chain_code=unhexlify(
"0000000000000000000000000000000000000000000000000000000000000000"
),
public_key=unhexlify(
"0378d430274f8c5ec1321338151e9f27f4c676a008bdf8638d07c0b6be9ab35c71"
),
)
sig = unhexlify(
b"304402207274b5a4d15e75f3df7319a375557b0efba9b27bc63f9f183a17da95a6125c94022000efac57629f1522e2d3958430e2ef073b0706cfac06cce492651b79858f09ae"
)
inp1 = proto.TxInputType(
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
amount=24000,
prev_hash=unhexlify('f68caf10df12d5b07a34601d88fa6856c6edcbf4d05ebef3486510ae1c293d5f'),
prev_hash=unhexlify(
"f68caf10df12d5b07a34601d88fa6856c6edcbf4d05ebef3486510ae1c293d5f"
),
prev_index=1,
script_type=proto.InputScriptType.SPENDMULTISIG,
)
out1 = proto.TxOutputType(
address_n=parse_path("44'/145'/1'/1/1"),
multisig=proto.MultisigRedeemScriptType(
pubkeys=[proto.HDNodePathType(node=deserialize(xpubs[0]), address_n=[1, 1]),
proto.HDNodePathType(node=correcthorse, address_n=[]),
proto.HDNodePathType(node=correcthorse, address_n=[])],
signatures=[b'', b'', b''],
pubkeys=[
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""],
m=2,
),
script_type=proto.OutputScriptType.PAYTOMULTISIG,
amount=23000
amount=23000,
)
with self.client:
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.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),
])
(signatures1, serialized_tx) = self.client.sign_tx('Bcash', [inp1], [out1])
assert hexlify(signatures1[0]) == b'3044022052ccf022b3684ecce9f961ce8828387b97267c86bedf0ce16a24bf014e62e42c022035d315ddbeeef7ab3456bd09aed8b625ea58852216b60e4b84ba9f85827d305c'
assert hexlify(serialized_tx) == b'01000000015f3d291cae106548f3be5ed0f4cbedc65668fa881d60347ab0d512df10af8cf601000000fc00473044022052ccf022b3684ecce9f961ce8828387b97267c86bedf0ce16a24bf014e62e42c022035d315ddbeeef7ab3456bd09aed8b625ea58852216b60e4b84ba9f85827d305c4147304402207274b5a4d15e75f3df7319a375557b0efba9b27bc63f9f183a17da95a6125c94022000efac57629f1522e2d3958430e2ef073b0706cfac06cce492651b79858f09ae414c69522103d62b2af2272bbd67cbe30eeaf4226c7f2d57d2a0ed1aab5ab736fb40bb2f5ffe21036d5e0d7ca3589465711eec91436249d7234d3a994c219024fc75cec98fc02ae221024f58378a69b68e89301a6ff882116e0fa35446ec9bfd86532eeb05941ec1f8c853aeffffffff01d85900000000000017a9140bb11de6558871f49fc241341992ece9986f7c5c8700000000'
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.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),
]
)
(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):
self.setup_mnemonic_allallall()
self.client.set_tx_api(TxApiBcash)
xpubs = []
for n in map(lambda index: self.client.get_public_node(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)
def getmultisig(chain, nr, signatures=[b'', b'', b''], xpubs=xpubs):
def getmultisig(chain, nr, signatures=[b"", b"", b""], xpubs=xpubs):
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,
m=2,
)
inp1 = proto.TxInputType(
address_n=parse_path("44'/145'/3'/0/0"),
multisig=getmultisig(0, 0),
# bitcoincash:pqguz4nqq64jhr5v3kvpq4dsjrkda75hwy86gq0qzw
amount=48490,
prev_hash=unhexlify('8b6db9b8ba24235d86b053ea2ccb484fc32b96f89c3c39f98d86f90db16076a0'),
prev_hash=unhexlify(
"8b6db9b8ba24235d86b053ea2ccb484fc32b96f89c3c39f98d86f90db16076a0"
),
prev_index=0,
script_type=proto.InputScriptType.SPENDMULTISIG,
)
out1 = proto.TxOutputType(
address='bitcoincash:qqq8gx2j76nw4dfefumxmdwvtf2tpsjznusgsmzex9',
address="bitcoincash:qqq8gx2j76nw4dfefumxmdwvtf2tpsjznusgsmzex9",
amount=24000,
script_type=proto.OutputScriptType.PAYTOADDRESS,
)
@ -369,48 +587,103 @@ class TestMsgSigntxBch(TrezorTest):
address_n=parse_path("44'/145'/3'/1/0"),
multisig=getmultisig(1, 0),
script_type=proto.OutputScriptType.PAYTOMULTISIG,
amount=24000
amount=24000,
)
with self.client:
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.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.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) = self.client.sign_tx('Bcash', [inp1], [out1, out2])
assert hexlify(signatures1[0]) == b'3045022100bcb1a7134a13025a06052546ee1c6ac3640a0abd2d130190ed13ed7fcb43e9cd02207c381478e2ee123c850425bfbf6d3c691230eb37e333832cb32a1ed3f2cd9e85'
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.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.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"
)
inp1 = proto.TxInputType(
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
amount=48490,
prev_hash=unhexlify('8b6db9b8ba24235d86b053ea2ccb484fc32b96f89c3c39f98d86f90db16076a0'),
prev_hash=unhexlify(
"8b6db9b8ba24235d86b053ea2ccb484fc32b96f89c3c39f98d86f90db16076a0"
),
prev_index=0,
script_type=proto.InputScriptType.SPENDMULTISIG,
)
out2.address_n[2] = 1 + 0x80000000
out2.address_n[2] = H_(1)
with self.client:
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.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.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) = self.client.sign_tx('Bcash', [inp1], [out1, out2])
assert hexlify(signatures1[0]) == b'3045022100f1153636371ba1f84389460e1265a8fa296569bc18e117c31f4e8f0fc0650c01022022932cc84766ff0c0f65ed9633ad311ae90d4c8fe71f5e1890b1e8f74dd516fa'
assert hexlify(serialized_tx) == b'0100000001a07660b10df9868df9393c9cf8962bc34f48cb2cea53b0865d2324bab8b96d8b00000000fdfe0000483045022100f1153636371ba1f84389460e1265a8fa296569bc18e117c31f4e8f0fc0650c01022022932cc84766ff0c0f65ed9633ad311ae90d4c8fe71f5e1890b1e8f74dd516fa41483045022100bcb1a7134a13025a06052546ee1c6ac3640a0abd2d130190ed13ed7fcb43e9cd02207c381478e2ee123c850425bfbf6d3c691230eb37e333832cb32a1ed3f2cd9e85414c69522102fcf63419c319ce1a42d69120a3599d6da8c5dd4caf2888220eccde5a1ff7c5d021036d7d5ef79370b7fabe2c058698a20219e97fc70868e65ecdd6b37cc18e8a88bd2103505dc649dab8cd1655a4c0daf0ec5f955881c9d7011478ea881fac11cab1e49953aeffffffff02c05d0000000000001976a91400741952f6a6eab5394f366db5cc5a54b0c2429f88acc05d00000000000017a914756c06d7e77de3950a6124f026d8e1a2464b3ecf8700000000'
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.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.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 (
hexlify(serialized_tx)
== b"0100000001a07660b10df9868df9393c9cf8962bc34f48cb2cea53b0865d2324bab8b96d8b00000000fdfe0000483045022100f1153636371ba1f84389460e1265a8fa296569bc18e117c31f4e8f0fc0650c01022022932cc84766ff0c0f65ed9633ad311ae90d4c8fe71f5e1890b1e8f74dd516fa41483045022100bcb1a7134a13025a06052546ee1c6ac3640a0abd2d130190ed13ed7fcb43e9cd02207c381478e2ee123c850425bfbf6d3c691230eb37e333832cb32a1ed3f2cd9e85414c69522102fcf63419c319ce1a42d69120a3599d6da8c5dd4caf2888220eccde5a1ff7c5d021036d7d5ef79370b7fabe2c058698a20219e97fc70868e65ecdd6b37cc18e8a88bd2103505dc649dab8cd1655a4c0daf0ec5f955881c9d7011478ea881fac11cab1e49953aeffffffff02c05d0000000000001976a91400741952f6a6eab5394f366db5cc5a54b0c2429f88acc05d00000000000017a914756c06d7e77de3950a6124f026d8e1a2464b3ecf8700000000"
)

@ -14,29 +14,30 @@
# 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>.
import pytest
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 trezorlib import coins
from trezorlib import messages as proto
from trezorlib.client import CallException
from trezorlib.tools import parse_path
from .common import TrezorTest
TxApiBitcoinGold = coins.tx_api["Bgold"]
# All data taken from T1
class TestMsgSigntxBitcoinGold(TrezorTest):
def test_send_bitcoin_gold_change(self):
self.setup_mnemonic_allallall()
self.client.set_tx_api(TxApiBitcoinGold)
inp1 = proto.TxInputType(
address_n=parse_path("44'/156'/0'/0/0"),
amount=1995344,
prev_hash=unhexlify('25526bf06c76ad3082bba930cf627cdd5f1b3cd0b9907dd7ff1a07e14addc985'),
prev_hash=unhexlify(
"25526bf06c76ad3082bba930cf627cdd5f1b3cd0b9907dd7ff1a07e14addc985"
),
prev_index=0,
script_type=proto.InputScriptType.SPENDADDRESS,
)
@ -46,25 +47,50 @@ class TestMsgSigntxBitcoinGold(TrezorTest):
script_type=proto.OutputScriptType.PAYTOADDRESS,
)
out2 = proto.TxOutputType(
address='GfDB1tvjfm3bukeoBTtfNqrJVFohS2kCTe',
address="GfDB1tvjfm3bukeoBTtfNqrJVFohS2kCTe",
amount=73452,
script_type=proto.OutputScriptType.PAYTOADDRESS,
)
with self.client:
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(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) = self.client.sign_tx('Bgold', [inp1], [out1, out2])
assert hexlify(serialized_tx) == b'010000000185c9dd4ae1071affd77d90b9d03c1b5fdd7c62cf30a9bb8230ad766cf06b5225000000006b483045022100963904da0731b71ce468afd45366dd80fbff566ec0d39c1161ab85d17459c7ca02202f5c24a7a7272d98b14a3f5bc000c7cde8ac0eb773f20f4c3131518186cc98854121023bd0ec4022d12d0106c5b7308a25572953ba1951f576f691354a7b147ee0cc1fffffffff0272ee1c00000000001976a9141c82b9c11f193ad82413caadc0955730572b50ae88acec1e0100000000001976a914ea5f904d195079a350b534db4446433b3cec222e88ac00000000'
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(
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"
)
def test_send_bitcoin_gold_nochange(self):
self.setup_mnemonic_allallall()
@ -72,7 +98,9 @@ class TestMsgSigntxBitcoinGold(TrezorTest):
inp1 = proto.TxInputType(
address_n=parse_path("44'/156'/0'/1/0"),
amount=1896050,
prev_hash=unhexlify('25526bf06c76ad3082bba930cf627cdd5f1b3cd0b9907dd7ff1a07e14addc985'),
prev_hash=unhexlify(
"25526bf06c76ad3082bba930cf627cdd5f1b3cd0b9907dd7ff1a07e14addc985"
),
prev_index=0,
script_type=proto.InputScriptType.SPENDADDRESS,
)
@ -80,30 +108,57 @@ class TestMsgSigntxBitcoinGold(TrezorTest):
address_n=parse_path("44'/156'/0'/0/1"),
# 1LRspCZNFJcbuNKQkXgHMDucctFRQya5a3
amount=73452,
prev_hash=unhexlify('db77c2461b840e6edbe7f9280043184a98e020d9795c1b65cb7cef2551a8fb18'),
prev_hash=unhexlify(
"db77c2461b840e6edbe7f9280043184a98e020d9795c1b65cb7cef2551a8fb18"
),
prev_index=1,
script_type=proto.InputScriptType.SPENDADDRESS,
)
out1 = proto.TxOutputType(
address='GfDB1tvjfm3bukeoBTtfNqrJVFohS2kCTe',
address="GfDB1tvjfm3bukeoBTtfNqrJVFohS2kCTe",
amount=1934960,
script_type=proto.OutputScriptType.PAYTOADDRESS,
)
with self.client:
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(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) = self.client.sign_tx('Bgold', [inp1, inp2], [out1])
assert hexlify(serialized_tx) == b'010000000285c9dd4ae1071affd77d90b9d03c1b5fdd7c62cf30a9bb8230ad766cf06b5225000000006b483045022100928852076c9fab160c07564cd54691af1cbc37fb28f0b7bee7299c7925ef62f0022058856387afecc6508f2f04ecdfd292a13026a5b2107ebdd2cc789bdf8820d552412102a6c3998d0d4e5197ff41aab5c53580253b3b91f583f4c31f7624be7dc83ce15fffffffff18fba85125ef7ccb651b5c79d920e0984a18430028f9e7db6e0e841b46c277db010000006b483045022100faa2f4f01cc95e680349a093923aae0aa2ea01429873555aa8a84bf630ef33a002204c3f4bf567e2d20540c0f71dc278481d6ccb6b95acda2a2f87ce521c79d6b872412102d54a7e5733b1635e5e9442943f48179b1700206b2d1925250ba10f1c86878be8ffffffff0170861d00000000001976a914ea5f904d195079a350b534db4446433b3cec222e88ac00000000'
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(
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"
)
def test_attack_change_input(self):
self.setup_mnemonic_allallall()
@ -112,7 +167,9 @@ class TestMsgSigntxBitcoinGold(TrezorTest):
address_n=parse_path("44'/156'/1000'/0/0"),
# 1MH9KKcvdCTY44xVDC2k3fjBbX5Cz29N1q
amount=1995344,
prev_hash=unhexlify('25526bf06c76ad3082bba930cf627cdd5f1b3cd0b9907dd7ff1a07e14addc985'),
prev_hash=unhexlify(
"25526bf06c76ad3082bba930cf627cdd5f1b3cd0b9907dd7ff1a07e14addc985"
),
prev_index=0,
script_type=proto.InputScriptType.SPENDADDRESS,
)
@ -122,7 +179,7 @@ class TestMsgSigntxBitcoinGold(TrezorTest):
script_type=proto.OutputScriptType.PAYTOADDRESS,
)
out2 = proto.TxOutputType(
address='GfDB1tvjfm3bukeoBTtfNqrJVFohS2kCTe',
address="GfDB1tvjfm3bukeoBTtfNqrJVFohS2kCTe",
amount=73452,
script_type=proto.OutputScriptType.PAYTOADDRESS,
)
@ -143,46 +200,81 @@ class TestMsgSigntxBitcoinGold(TrezorTest):
if attack_ctr <= 1:
return msg
msg.inputs[0].address_n[2] = 1 + 0x80000000
msg.inputs[0].address_n[2] = H_(1)
return msg
with self.client:
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(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),
])
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(
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):
self.client.sign_tx('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):
self.setup_mnemonic_allallall()
self.client.set_tx_api(TxApiBitcoinGold)
xpubs = []
for n in map(lambda index: self.client.get_public_node(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)
def getmultisig(chain, nr, signatures=[b'', b'', b''], xpubs=xpubs):
def getmultisig(chain, nr, signatures=[b"", b"", b""], xpubs=xpubs):
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,
m=2,
)
inp1 = proto.TxInputType(
address_n=parse_path("44'/156'/3'/0/0"),
multisig=getmultisig(0, 0),
# 33Ju286QvonBz5N1V754ZekQv4GLJqcc5R
amount=48490,
prev_hash=unhexlify('25526bf06c76ad3082bba930cf627cdd5f1b3cd0b9907dd7ff1a07e14addc985'),
prev_hash=unhexlify(
"25526bf06c76ad3082bba930cf627cdd5f1b3cd0b9907dd7ff1a07e14addc985"
),
prev_index=0,
script_type=proto.InputScriptType.SPENDMULTISIG,
)
out1 = proto.TxOutputType(
address='GfDB1tvjfm3bukeoBTtfNqrJVFohS2kCTe',
address="GfDB1tvjfm3bukeoBTtfNqrJVFohS2kCTe",
amount=24000,
script_type=proto.OutputScriptType.PAYTOADDRESS,
)
@ -190,51 +282,106 @@ class TestMsgSigntxBitcoinGold(TrezorTest):
address_n=parse_path("44'/156'/3'/1/0"),
multisig=getmultisig(1, 0),
script_type=proto.OutputScriptType.PAYTOMULTISIG,
amount=24000
amount=24000,
)
with self.client:
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.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.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) = self.client.sign_tx('Bgold', [inp1], [out1, out2])
assert hexlify(signatures1[0]) == b'3045022100b1594f3b186d0dedbf61e53a1c407b1e0747098b7375941df85af045040f578e022013ba1893eb9e2fd854dd07073a83b261cf4beba76f66b07742e462b4088a7e4a'
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.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.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"
)
inp1 = proto.TxInputType(
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
amount=48490,
prev_hash=unhexlify('25526bf06c76ad3082bba930cf627cdd5f1b3cd0b9907dd7ff1a07e14addc985'),
prev_hash=unhexlify(
"25526bf06c76ad3082bba930cf627cdd5f1b3cd0b9907dd7ff1a07e14addc985"
),
prev_index=0,
script_type=proto.InputScriptType.SPENDMULTISIG,
)
out2.address_n[2] = 1 + 0x80000000
out2.address_n[2] = H_(1)
with self.client:
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.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.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) = self.client.sign_tx('Bgold', [inp1], [out1, out2])
assert hexlify(signatures1[0]) == b'3044022006da8dbd14e6656ac8dcb956f4c0498574e88680eaeceb2cbafd8d2b2329d8cc02200972d076d444c5ff8f2ab18e14d8249ab661cb9c53335039bedcde037a40d747'
assert hexlify(serialized_tx) == b'010000000185c9dd4ae1071affd77d90b9d03c1b5fdd7c62cf30a9bb8230ad766cf06b522500000000fdfd0000473044022006da8dbd14e6656ac8dcb956f4c0498574e88680eaeceb2cbafd8d2b2329d8cc02200972d076d444c5ff8f2ab18e14d8249ab661cb9c53335039bedcde037a40d74741483045022100b1594f3b186d0dedbf61e53a1c407b1e0747098b7375941df85af045040f578e022013ba1893eb9e2fd854dd07073a83b261cf4beba76f66b07742e462b4088a7e4a414c69522102290e6649574d17938c1ecb959ae92954f9ee48e1bd5b73f35ea931a3ab8a6087210379e0107b173e2c143426760627128c5eea3f862e8df92f3c2558eeeae4e347842103ff1746ca7dcf9e5c2eea9a73779b7c5bafed549f45cf3638a94cdf1e89c7f28f53aeffffffff02c05d0000000000001976a914ea5f904d195079a350b534db4446433b3cec222e88acc05d00000000000017a91445e917e46815d2b38d3f1cf072e63dd4f3b7a7e38700000000'
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.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.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 (
hexlify(serialized_tx)
== b"010000000185c9dd4ae1071affd77d90b9d03c1b5fdd7c62cf30a9bb8230ad766cf06b522500000000fdfd0000473044022006da8dbd14e6656ac8dcb956f4c0498574e88680eaeceb2cbafd8d2b2329d8cc02200972d076d444c5ff8f2ab18e14d8249ab661cb9c53335039bedcde037a40d74741483045022100b1594f3b186d0dedbf61e53a1c407b1e0747098b7375941df85af045040f578e022013ba1893eb9e2fd854dd07073a83b261cf4beba76f66b07742e462b4088a7e4a414c69522102290e6649574d17938c1ecb959ae92954f9ee48e1bd5b73f35ea931a3ab8a6087210379e0107b173e2c143426760627128c5eea3f862e8df92f3c2558eeeae4e347842103ff1746ca7dcf9e5c2eea9a73779b7c5bafed549f45cf3638a94cdf1e89c7f28f53aeffffffff02c05d0000000000001976a914ea5f904d195079a350b534db4446433b3cec222e88acc05d00000000000017a91445e917e46815d2b38d3f1cf072e63dd4f3b7a7e38700000000"
)
def test_send_p2sh(self):
self.setup_mnemonic_allallall()
@ -242,37 +389,67 @@ class TestMsgSigntxBitcoinGold(TrezorTest):
inp1 = proto.TxInputType(
address_n=parse_path("49'/156'/0'/1/0"),
amount=123456789,
prev_hash=unhexlify('25526bf06c76ad3082bba930cf627cdd5f1b3cd0b9907dd7ff1a07e14addc985'),
prev_hash=unhexlify(
"25526bf06c76ad3082bba930cf627cdd5f1b3cd0b9907dd7ff1a07e14addc985"
),
prev_index=0,
script_type=proto.InputScriptType.SPENDP2SHWITNESS,
)
out1 = proto.TxOutputType(
address='GfDB1tvjfm3bukeoBTtfNqrJVFohS2kCTe',
address="GfDB1tvjfm3bukeoBTtfNqrJVFohS2kCTe",
amount=12300000,
script_type=proto.OutputScriptType.PAYTOADDRESS,
)
out2 = proto.TxOutputType(
address='GZFLExxrvWFuFT1xRzhfwQWSE2bPDedBfn',
address="GZFLExxrvWFuFT1xRzhfwQWSE2bPDedBfn",
script_type=proto.OutputScriptType.PAYTOADDRESS,
amount=123456789 - 11000 - 12300000,
)
with self.client:
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.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.TXINPUT, details=proto.TxRequestDetailsType(request_index=0)),
proto.TxRequest(request_type=proto.RequestType.TXFINISHED),
])
(signatures, serialized_tx) = self.client.sign_tx('Bgold', [inp1], [out1, out2])
assert hexlify(serialized_tx) == b'0100000000010185c9dd4ae1071affd77d90b9d03c1b5fdd7c62cf30a9bb8230ad766cf06b52250000000017160014b5355d001e720d8f4513da00ff2bba4dcf9d39fcffffffff02e0aebb00000000001976a914ea5f904d195079a350b534db4446433b3cec222e88ac3df39f06000000001976a914a8f757819ec6779409f45788f7b4a0e8f51ec50488ac02473044022073fcbf2876f073f78923ab427f14de5b2a0fbeb313a9b2b650b3567061f242a702202f45fc22c501108ff6222afe3aca7da9d8c7dc860f9cda335bef31fa184e7bef412102ecea08b559fc5abd009acf77cfae13fa8a3b1933e3e031956c65c12cec8ca3e300000000'
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.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.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"
)
def test_send_p2sh_witness_change(self):
self.setup_mnemonic_allallall()
@ -280,12 +457,14 @@ class TestMsgSigntxBitcoinGold(TrezorTest):
inp1 = proto.TxInputType(
address_n=parse_path("49'/156'/0'/1/0"),
amount=123456789,
prev_hash=unhexlify('25526bf06c76ad3082bba930cf627cdd5f1b3cd0b9907dd7ff1a07e14addc985'),
prev_hash=unhexlify(
"25526bf06c76ad3082bba930cf627cdd5f1b3cd0b9907dd7ff1a07e14addc985"
),
prev_index=0,
script_type=proto.InputScriptType.SPENDP2SHWITNESS,
)
out1 = proto.TxOutputType(
address='GfDB1tvjfm3bukeoBTtfNqrJVFohS2kCTe',
address="GfDB1tvjfm3bukeoBTtfNqrJVFohS2kCTe",
amount=12300000,
script_type=proto.OutputScriptType.PAYTOADDRESS,
)
@ -295,73 +474,156 @@ class TestMsgSigntxBitcoinGold(TrezorTest):
amount=123456789 - 11000 - 12300000,
)
with self.client:
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.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.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) = self.client.sign_tx('Bgold', [inp1], [out1, out2])
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.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.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))
# assert False
assert hexlify(serialized_tx) == b'0100000000010185c9dd4ae1071affd77d90b9d03c1b5fdd7c62cf30a9bb8230ad766cf06b52250000000017160014b5355d001e720d8f4513da00ff2bba4dcf9d39fcffffffff02e0aebb00000000001976a914ea5f904d195079a350b534db4446433b3cec222e88ac3df39f060000000017a9140cd03822b799a452c106d1b3771844a067b17f118702483045022100d79b33384c686d8dd40ad5f84f46691d30994992c1cb42e934c2a625d86cb2f902206859805a9a98ba140b71a9d4b9a6b8df94a9424f9c40f3bd804149fd6e278d63412102ecea08b559fc5abd009acf77cfae13fa8a3b1933e3e031956c65c12cec8ca3e300000000'
assert (
hexlify(serialized_tx)
== b"0100000000010185c9dd4ae1071affd77d90b9d03c1b5fdd7c62cf30a9bb8230ad766cf06b52250000000017160014b5355d001e720d8f4513da00ff2bba4dcf9d39fcffffffff02e0aebb00000000001976a914ea5f904d195079a350b534db4446433b3cec222e88ac3df39f060000000017a9140cd03822b799a452c106d1b3771844a067b17f118702483045022100d79b33384c686d8dd40ad5f84f46691d30994992c1cb42e934c2a625d86cb2f902206859805a9a98ba140b71a9d4b9a6b8df94a9424f9c40f3bd804149fd6e278d63412102ecea08b559fc5abd009acf77cfae13fa8a3b1933e3e031956c65c12cec8ca3e300000000"
)
def test_send_multisig_1(self):
self.setup_mnemonic_allallall()
self.client.set_tx_api(TxApiBitcoinGold)
nodes = map(lambda index: self.client.get_public_node(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(
pubkeys=list(map(lambda n: proto.HDNodePathType(node=deserialize(n.xpub), address_n=[2, 0]), nodes)),
signatures=[b'', b'', b''],
pubkeys=list(
map(
lambda n: proto.HDNodePathType(
node=deserialize(n.xpub), address_n=[2, 0]
),
nodes,
)
),
signatures=[b"", b"", b""],
m=2,
)
inp1 = proto.TxInputType(
address_n=parse_path("999'/1'/1'/2/0"),
prev_hash=unhexlify('25526bf06c76ad3082bba930cf627cdd5f1b3cd0b9907dd7ff1a07e14addc985'),
prev_hash=unhexlify(
"25526bf06c76ad3082bba930cf627cdd5f1b3cd0b9907dd7ff1a07e14addc985"
),
prev_index=1,
script_type=proto.InputScriptType.SPENDP2SHWITNESS,
multisig=multisig,
amount=1610436
amount=1610436,
)
out1 = proto.TxOutputType(address='GfDB1tvjfm3bukeoBTtfNqrJVFohS2kCTe',
amount=1605000,
script_type=proto.OutputScriptType.PAYTOADDRESS)
out1 = proto.TxOutputType(
address="GfDB1tvjfm3bukeoBTtfNqrJVFohS2kCTe",
amount=1605000,
script_type=proto.OutputScriptType.PAYTOADDRESS,
)
with self.client:
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.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, _) = self.client.sign_tx('Bgold', [inp1], [out1])
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.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
inp1.multisig.signatures[0] = signatures1[0]
# sign with third key
inp1.address_n[2] = 0x80000003
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.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) = self.client.sign_tx('Bgold', [inp1], [out1])
assert hexlify(serialized_tx) == b'0100000000010185c9dd4ae1071affd77d90b9d03c1b5fdd7c62cf30a9bb8230ad766cf06b522501000000232200201e8dda334f11171190b3da72e526d441491464769679a319a2f011da5ad312a1ffffffff01887d1800000000001976a914ea5f904d195079a350b534db4446433b3cec222e88ac0400483045022100e728485c8337f9a09ebbf36edc0fef10f8bcf5c1ba601b7d8ba43a9250a898f002206b9e3401c297f9ab9afb7f1be59bb342db53b5b65aff7c557e3109679697df0f41473044022062ea69ecdc07d0dadc1971fbda50a629a56dd30f431db26327428f4992601ce602204a1c8ab9c7d81c36cb6f819109a26f9baaa9607b8d37bff5e24eee6fab4a04e441695221038e81669c085a5846e68e03875113ddb339ecbb7cb11376d4163bca5dc2e2a0c1210348c5c3be9f0e6cf1954ded1c0475beccc4d26aaa9d0cce2dd902538ff1018a112103931140ebe0fbbb7df0be04ed032a54e9589e30339ba7bbb8b0b71b15df1294da53ae00000000'
inp1.address_n[2] = H_(3)
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.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"
)

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

@ -15,22 +15,21 @@
# If not, see <https://www.gnu.org/licenses/lgpl-3.0.html>.
from binascii import hexlify, unhexlify
import pytest
from trezorlib import btc, messages as proto
from trezorlib.tools import H_, CallException, parse_path
from trezorlib.tx_api import TxApiInsight
from ..support.ckd_public import deserialize
from .conftest import TREZOR_VERSION
from .common import TrezorTest
from trezorlib import messages as proto
from trezorlib.client import CallException
from trezorlib.tools import parse_path
from trezorlib.tx_api import TxApiInsight
from .conftest import TREZOR_VERSION
TxApiTestnet = TxApiInsight("insight_testnet")
class TestMsgSigntxSegwit(TrezorTest):
def test_send_p2sh(self):
self.setup_mnemonic_allallall()
self.client.set_tx_api(TxApiTestnet)
@ -38,37 +37,67 @@ class TestMsgSigntxSegwit(TrezorTest):
address_n=parse_path("49'/1'/0'/1/0"),
# 2N1LGaGg836mqSQqiuUBLfcyGBhyZbremDX
amount=123456789,
prev_hash=unhexlify('20912f98ea3ed849042efed0fdac8cb4fc301961c5988cba56902d8ffb61c337'),
prev_hash=unhexlify(
"20912f98ea3ed849042efed0fdac8cb4fc301961c5988cba56902d8ffb61c337"
),
prev_index=0,
script_type=proto.InputScriptType.SPENDP2SHWITNESS,
)
out1 = proto.TxOutputType(
address='mhRx1CeVfaayqRwq5zgRQmD7W5aWBfD5mC',
address="mhRx1CeVfaayqRwq5zgRQmD7W5aWBfD5mC",
amount=12300000,
script_type=proto.OutputScriptType.PAYTOADDRESS,
)
out2 = proto.TxOutputType(
address='2N1LGaGg836mqSQqiuUBLfcyGBhyZbremDX',
address="2N1LGaGg836mqSQqiuUBLfcyGBhyZbremDX",
script_type=proto.OutputScriptType.PAYTOADDRESS,
amount=123456789 - 11000 - 12300000,
)
with self.client:
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.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.TXINPUT, details=proto.TxRequestDetailsType(request_index=0)),
proto.TxRequest(request_type=proto.RequestType.TXFINISHED),
])
(signatures, serialized_tx) = self.client.sign_tx('Testnet', [inp1], [out1, out2])
assert hexlify(serialized_tx) == b'0100000000010137c361fb8f2d9056ba8c98c5611930fcb48cacfdd0fe2e0449d83eea982f91200000000017160014d16b8c0680c61fc6ed2e407455715055e41052f5ffffffff02e0aebb00000000001976a91414fdede0ddc3be652a0ce1afbc1b509a55b6b94888ac3df39f060000000017a91458b53ea7f832e8f096e896b8713a8c6df0e892ca8702483045022100ccd253bfdf8a5593cd7b6701370c531199f0f05a418cd547dfc7da3f21515f0f02203fa08a0753688871c220648f9edadbdb98af42e5d8269364a326572cf703895b012103e7bfe10708f715e8538c92d46ca50db6f657bbc455b7494e6a0303ccdb868b7900000000'
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.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.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"
)
def test_send_p2sh_change(self):
self.setup_mnemonic_allallall()
@ -77,12 +106,14 @@ class TestMsgSigntxSegwit(TrezorTest):
address_n=parse_path("49'/1'/0'/1/0"),
# 2N1LGaGg836mqSQqiuUBLfcyGBhyZbremDX
amount=123456789,
prev_hash=unhexlify('20912f98ea3ed849042efed0fdac8cb4fc301961c5988cba56902d8ffb61c337'),
prev_hash=unhexlify(
"20912f98ea3ed849042efed0fdac8cb4fc301961c5988cba56902d8ffb61c337"
),
prev_index=0,
script_type=proto.InputScriptType.SPENDP2SHWITNESS,
)
out1 = proto.TxOutputType(
address='mhRx1CeVfaayqRwq5zgRQmD7W5aWBfD5mC',
address="mhRx1CeVfaayqRwq5zgRQmD7W5aWBfD5mC",
amount=12300000,
script_type=proto.OutputScriptType.PAYTOADDRESS,
)
@ -92,74 +123,157 @@ class TestMsgSigntxSegwit(TrezorTest):
amount=123456789 - 11000 - 12300000,
)
with self.client:
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.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.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) = self.client.sign_tx('Testnet', [inp1], [out1, out2])
assert hexlify(serialized_tx) == b'0100000000010137c361fb8f2d9056ba8c98c5611930fcb48cacfdd0fe2e0449d83eea982f91200000000017160014d16b8c0680c61fc6ed2e407455715055e41052f5ffffffff02e0aebb00000000001976a91414fdede0ddc3be652a0ce1afbc1b509a55b6b94888ac3df39f060000000017a91458b53ea7f832e8f096e896b8713a8c6df0e892ca8702483045022100ccd253bfdf8a5593cd7b6701370c531199f0f05a418cd547dfc7da3f21515f0f02203fa08a0753688871c220648f9edadbdb98af42e5d8269364a326572cf703895b012103e7bfe10708f715e8538c92d46ca50db6f657bbc455b7494e6a0303ccdb868b7900000000'
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.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.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"
)
def test_send_multisig_1(self):
self.setup_mnemonic_allallall()
self.client.set_tx_api(TxApiTestnet)
nodes = map(lambda index: self.client.get_public_node(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(
pubkeys=list(map(lambda n: proto.HDNodePathType(node=deserialize(n.xpub), address_n=[2, 0]), nodes)),
signatures=[b'', b'', b''],
pubkeys=list(
map(
lambda n: proto.HDNodePathType(
node=deserialize(n.xpub), address_n=[2, 0]
),
nodes,
)
),
signatures=[b"", b"", b""],
m=2,
)
inp1 = proto.TxInputType(
address_n=parse_path("999'/1'/1'/2/0"),
prev_hash=unhexlify('9c31922be756c06d02167656465c8dc83bb553bf386a3f478ae65b5c021002be'),
prev_hash=unhexlify(
"9c31922be756c06d02167656465c8dc83bb553bf386a3f478ae65b5c021002be"
),
prev_index=1,
script_type=proto.InputScriptType.SPENDP2SHWITNESS,
multisig=multisig,
amount=1610436
amount=1610436,
)
out1 = proto.TxOutputType(address='mhRx1CeVfaayqRwq5zgRQmD7W5aWBfD5mC',
amount=1605000,
script_type=proto.OutputScriptType.PAYTOADDRESS)
out1 = proto.TxOutputType(
address="mhRx1CeVfaayqRwq5zgRQmD7W5aWBfD5mC",
amount=1605000,
script_type=proto.OutputScriptType.PAYTOADDRESS,
)
with self.client:
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.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, _) = self.client.sign_tx('Testnet', [inp1], [out1])
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.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
inp1.multisig.signatures[0] = signatures1[0]
# sign with third key
inp1.address_n[2] = 0x80000003
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.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) = self.client.sign_tx('Testnet', [inp1], [out1])
assert hexlify(serialized_tx) == b'01000000000101be0210025c5be68a473f6a38bf53b53bc88d5c46567616026dc056e72b92319c01000000232200201e8dda334f11171190b3da72e526d441491464769679a319a2f011da5ad312a1ffffffff01887d1800000000001976a91414fdede0ddc3be652a0ce1afbc1b509a55b6b94888ac040047304402205b44c20cf2681690edaaf7cd2e30d4704124dd8b7eb1fb7f459d3906c3c374a602205ca359b6544ce2c101c979899c782f7d141c3b0454ea69202b1fb4c09d3b715701473044022052fafa64022554ae436dbf781e550bf0d326fef31eea1438350b3ff1940a180102202851bd19203b7fe8582a9ef52e82aa9f61cd52d4bcedfe6dcc0cf782468e6a8e01695221038e81669c085a5846e68e03875113ddb339ecbb7cb11376d4163bca5dc2e2a0c1210348c5c3be9f0e6cf1954ded1c0475beccc4d26aaa9d0cce2dd902538ff1018a112103931140ebe0fbbb7df0be04ed032a54e9589e30339ba7bbb8b0b71b15df1294da53ae00000000'
inp1.address_n[2] = H_(3)
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.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"
)
def test_attack_change_input_address(self):
# 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"),
# 2N1LGaGg836mqSQqiuUBLfcyGBhyZbremDX
amount=123456789,
prev_hash=unhexlify('20912f98ea3ed849042efed0fdac8cb4fc301961c5988cba56902d8ffb61c337'),
prev_hash=unhexlify(
"20912f98ea3ed849042efed0fdac8cb4fc301961c5988cba56902d8ffb61c337"
),
prev_index=0,
script_type=proto.InputScriptType.SPENDP2SHWITNESS,
)
out1 = proto.TxOutputType(
address='mhRx1CeVfaayqRwq5zgRQmD7W5aWBfD5mC',
address="mhRx1CeVfaayqRwq5zgRQmD7W5aWBfD5mC",
amount=12300000,
script_type=proto.OutputScriptType.PAYTOADDRESS,
)
@ -204,44 +320,94 @@ class TestMsgSigntxSegwit(TrezorTest):
if not run_attack:
return msg
msg.inputs[0].address_n[2] = 12345 + 0x80000000
msg.inputs[0].address_n[2] = H_(12345)
run_attack = False
return msg
# Test if the transaction can be signed normally
with self.client:
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.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.TXINPUT, details=proto.TxRequestDetailsType(request_index=0)),
proto.TxRequest(request_type=proto.RequestType.TXFINISHED),
])
(signatures, serialized_tx) = self.client.sign_tx('Testnet', [inp1], [out1, out2])
assert hexlify(serialized_tx) == b'0100000000010137c361fb8f2d9056ba8c98c5611930fcb48cacfdd0fe2e0449d83eea982f91200000000017160014d16b8c0680c61fc6ed2e407455715055e41052f5ffffffff02e0aebb00000000001976a91414fdede0ddc3be652a0ce1afbc1b509a55b6b94888ac3df39f060000000017a914dae9e09a7fc3bbe5a716fffec1bbb340b82a4fb9870248304502210099b5c4f8fd4402c9c0136fee5f711137d64fc9f14587e01bfa7798f5428f845d0220253e21c98f5b1b64efae69bc2ea9799c5620a43450baa6762a0c3cf4fdc886e5012103e7bfe10708f715e8538c92d46ca50db6f657bbc455b7494e6a0303ccdb868b7900000000'
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.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.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"
)
# Now run the attack, must trigger the exception
with self.client:
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.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),
])
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.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:
self.client.sign_tx('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
if TREZOR_VERSION == 1:
assert exc.value.args[1].endswith("Failed to compile input")
else:
assert exc.value.args[1].endswith('Transaction has changed during signing')
assert exc.value.args[1].endswith(
"Transaction has changed during signing"
)

@ -14,23 +14,24 @@
# 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>.
from binascii import unhexlify, hexlify
import pytest
from binascii import hexlify, unhexlify
from .common import TrezorTest
import pytest
from trezorlib import coins
from trezorlib import messages as proto
from trezorlib import btc, coins, messages as proto
from trezorlib.tools import parse_path
TxApiZcashTestnet = coins.tx_api['Zcash Testnet']
from .common import TrezorTest
TXHASH_aaf51e = unhexlify('aaf51e4606c264e47e5c42c958fe4cf1539c5172684721e38e69f4ef634d75dc')
TxApiZcashTestnet = coins.tx_api["Zcash Testnet"]
TXHASH_aaf51e = unhexlify(
"aaf51e4606c264e47e5c42c958fe4cf1539c5172684721e38e69f4ef634d75dc"
)
@pytest.mark.zcash
class TestMsgSigntxZcash(TrezorTest):
def test_one_one_fee(self):
self.setup_mnemonic_allallall()
@ -38,31 +39,57 @@ class TestMsgSigntxZcash(TrezorTest):
# input 1: 3.0 TAZ
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,
prev_hash=TXHASH_aaf51e,
prev_index=1,
)
out1 = proto.TxOutputType(
address='tmJ1xYxP8XNTtCoDgvdmQPSrxh5qZJgy65Z',
address="tmJ1xYxP8XNTtCoDgvdmQPSrxh5qZJgy65Z",
amount=300000000 - 1940,
script_type=proto.OutputScriptType.PAYTOADDRESS,
)
with self.client:
self.client.set_tx_api(TxApiZcashTestnet)
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.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),
])
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.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) = self.client.sign_tx('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
assert hexlify(serialized_tx) == b'030000807082c40301dc754d63eff4698ee321476872519c53f14cfe58c9425c7ee464c206461ef5aa010000006a47304402207e45f303b4e42be824513855eb21653e1d2749cd94dcd0f0613d3f85d4efd1e20220699ffbdbcad889af7ede5ce9febf7a5ef8f5619b2464824529974c400cffaebc0121030e669acac1f280d1ddf441cd2ba5e97417bf2689e4bbec86df4f831bf9f7ffd0ffffffff016c9be111000000001976a9145b157a678a10021243307e4bb58f36375aa80e1088ac000000000000000000'
assert (
hexlify(serialized_tx)
== b"030000807082c40301dc754d63eff4698ee321476872519c53f14cfe58c9425c7ee464c206461ef5aa010000006a47304402207e45f303b4e42be824513855eb21653e1d2749cd94dcd0f0613d3f85d4efd1e20220699ffbdbcad889af7ede5ce9febf7a5ef8f5619b2464824529974c400cffaebc0121030e669acac1f280d1ddf441cd2ba5e97417bf2689e4bbec86df4f831bf9f7ffd0ffffffff016c9be111000000001976a9145b157a678a10021243307e4bb58f36375aa80e1088ac000000000000000000"
)

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

@ -47,20 +47,21 @@
#
from base64 import b64encode
from .common import TrezorTest
from .conftest import TREZOR_VERSION
from binascii import hexlify, unhexlify
from trezorlib import messages as proto
from trezorlib import stellar
from trezorlib.tools import parse_path
from binascii import hexlify
import pytest
from trezorlib import messages as proto, stellar
from trezorlib.tools import parse_path
from .common import TrezorTest
@pytest.mark.stellar
class TestMsgStellarSignTransaction(TrezorTest):
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):
self.setup_mnemonic_nopin_nopassphrase()
@ -69,35 +70,55 @@ class TestMsgStellarSignTransaction(TrezorTest):
op.bump_to = 0x7fffffffffffffff
tx = self._create_msg()
response = self.client.stellar_sign_transaction(tx, [op], self.ADDRESS_N, self.NETWORK_PASSPHRASE)
assert b64encode(response.signature) == b'ZMIfHWhpyXdg40PzwOtkcXYnbZIO12Qy0WvkGqoYpb7jyWbG2HQCG7dgWhCoU5K81pvZTA2pMwiPjMwCXA//Bg=='
response = stellar.sign_tx(
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):
self.setup_mnemonic_nopin_nopassphrase()
op = proto.StellarAccountMergeOp()
op.destination_account = 'GBOVKZBEM2YYLOCDCUXJ4IMRKHN4LCJAE7WEAEA2KF562XFAGDBOB64V'
op.destination_account = (
"GBOVKZBEM2YYLOCDCUXJ4IMRKHN4LCJAE7WEAEA2KF562XFAGDBOB64V"
)
tx = self._create_msg()
response = self.client.stellar_sign_transaction(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 b64encode(response.signature) == b'2R3Pj89U+dWrqy7otUrLLjtANjAg0lmBQL8E+89Po0Y94oqZkauP8j3WE7+/z7vF6XvAMLoOdqRYkUzr2oh7Dg=='
assert (
hexlify(response.public_key)
== b"15d648bfe4d36f196cfb5735ffd8ca54cd4b8233f743f22449de7cf301cdb469"
)
assert (
b64encode(response.signature)
== b"2R3Pj89U+dWrqy7otUrLLjtANjAg0lmBQL8E+89Po0Y94oqZkauP8j3WE7+/z7vF6XvAMLoOdqRYkUzr2oh7Dg=="
)
def test_sign_tx_create_account_op(self):
"""Create new account with initial balance of 100.0333"""
self.setup_mnemonic_nopin_nopassphrase()
op = proto.StellarCreateAccountOp()
op.new_account = 'GBOVKZBEM2YYLOCDCUXJ4IMRKHN4LCJAE7WEAEA2KF562XFAGDBOB64V'
op.new_account = "GBOVKZBEM2YYLOCDCUXJ4IMRKHN4LCJAE7WEAEA2KF562XFAGDBOB64V"
op.starting_balance = 1000333000
tx = self._create_msg()
response = self.client.stellar_sign_transaction(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):
"""Native payment of 50.0111 XLM to GBOVKZBEM2YYLOCDCUXJ4IMRKHN4LCJAE7WEAEA2KF562XFAGDBOB64V"""
@ -105,13 +126,20 @@ class TestMsgStellarSignTransaction(TrezorTest):
op = proto.StellarPaymentOp()
op.amount = 500111000
op.destination_account = 'GBOVKZBEM2YYLOCDCUXJ4IMRKHN4LCJAE7WEAEA2KF562XFAGDBOB64V'
op.destination_account = (
"GBOVKZBEM2YYLOCDCUXJ4IMRKHN4LCJAE7WEAEA2KF562XFAGDBOB64V"
)
tx = self._create_msg()
response = self.client.stellar_sign_transaction(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):
"""Custom asset payment (code length 1) of 50.0111 X to GBOVKZBEM2YYLOCDCUXJ4IMRKHN4LCJAE7WEAEA2KF562XFAGDBOB64V"""
@ -119,14 +147,23 @@ class TestMsgStellarSignTransaction(TrezorTest):
op = proto.StellarPaymentOp()
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()
response = self.client.stellar_sign_transaction(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):
"""Custom asset payment (code length 12) of 50.0111 ABCDEFGHIJKL to GBOVKZBEM2YYLOCDCUXJ4IMRKHN4LCJAE7WEAEA2KF562XFAGDBOB64V"""
@ -134,30 +171,48 @@ class TestMsgStellarSignTransaction(TrezorTest):
op = proto.StellarPaymentOp()
op.amount = 500111000
op.destination_account = 'GBOVKZBEM2YYLOCDCUXJ4IMRKHN4LCJAE7WEAEA2KF562XFAGDBOB64V'
op.asset = proto.StellarAssetType(2, 'ABCDEFGHIJKL', 'GAUYJFQCYIHFQNS7CI6BFWD2DSSFKDIQZUQ3BLQODDKE4PSW7VVBKENC')
op.destination_account = (
"GBOVKZBEM2YYLOCDCUXJ4IMRKHN4LCJAE7WEAEA2KF562XFAGDBOB64V"
)
op.asset = proto.StellarAssetType(
2,
"ABCDEFGHIJKL",
"GAUYJFQCYIHFQNS7CI6BFWD2DSSFKDIQZUQ3BLQODDKE4PSW7VVBKENC",
)
tx = self._create_msg()
response = self.client.stellar_sign_transaction(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):
"""Set inflation destination"""
self.setup_mnemonic_nopin_nopassphrase()
op = proto.StellarSetOptionsOp()
op.inflation_destination_account = 'GAFXTC5OV5XQD66T7WGOB2HUVUC3ZVJDJMBDPTVQYV3G3K7TUHC6CLBR'
op.inflation_destination_account = (
"GAFXTC5OV5XQD66T7WGOB2HUVUC3ZVJDJMBDPTVQYV3G3K7TUHC6CLBR"
)
tx = self._create_msg()
response = self.client.stellar_sign_transaction(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:
tx = proto.StellarSignTx()
tx.source_account = 'GAK5MSF74TJW6GLM7NLTL76YZJKM2S4CGP3UH4REJHPHZ4YBZW2GSBPW'
tx.source_account = "GAK5MSF74TJW6GLM7NLTL76YZJKM2S4CGP3UH4REJHPHZ4YBZW2GSBPW"
tx.fee = 100
tx.sequence_number = 0x100000000
tx.memo_type = 0

@ -16,28 +16,35 @@
from binascii import unhexlify
from trezorlib import btc
from .common import TrezorTest
class TestMsgVerifymessage(TrezorTest):
def test_message_long(self):
self.setup_mnemonic_nopin_nopassphrase()
ret = self.client.verify_message(
'Bitcoin',
'14LmW5k4ssUrtbAB4255zdqv3b4w1TuX9e',
unhexlify('205ff795c29aef7538f8b3bdb2e8add0d0722ad630a140b6aefd504a5a895cbd867cbb00981afc50edd0398211e8d7c304bb8efa461181bc0afa67ea4a720a89ed'),
"VeryLongMessage!" * 64
ret = btc.verify_message(
self.client,
"Bitcoin",
"14LmW5k4ssUrtbAB4255zdqv3b4w1TuX9e",
unhexlify(
"205ff795c29aef7538f8b3bdb2e8add0d0722ad630a140b6aefd504a5a895cbd867cbb00981afc50edd0398211e8d7c304bb8efa461181bc0afa67ea4a720a89ed"
),
"VeryLongMessage!" * 64,
)
assert ret is True
def test_message_testnet(self):
self.setup_mnemonic_nopin_nopassphrase()
ret = self.client.verify_message(
'Testnet',
'mirio8q3gtv7fhdnmb3TpZ4EuafdzSs7zL',
unhexlify('209e23edf0e4e47ff1dec27f32cd78c50e74ef018ee8a6adf35ae17c7a9b0dd96f48b493fd7dbab03efb6f439c6383c9523b3bbc5f1a7d158a6af90ab154e9be80'),
'This is an example of a signed message.'
ret = btc.verify_message(
self.client,
"Testnet",
"mirio8q3gtv7fhdnmb3TpZ4EuafdzSs7zL",
unhexlify(
"209e23edf0e4e47ff1dec27f32cd78c50e74ef018ee8a6adf35ae17c7a9b0dd96f48b493fd7dbab03efb6f439c6383c9523b3bbc5f1a7d158a6af90ab154e9be80"
),
"This is an example of a signed message.",
)
assert ret is True
@ -45,102 +52,137 @@ class TestMsgVerifymessage(TrezorTest):
self.setup_mnemonic_nopin_nopassphrase()
# uncompressed pubkey - OK
res = self.client.verify_message(
'Bitcoin',
'1JwSSubhmg6iPtRjtyqhUYYH7bZg3Lfy1T',
unhexlify('1ba77e01a9e17ba158b962cfef5f13dfed676ffc2b4bada24e58f784458b52b97421470d001d53d5880cf5e10e76f02be3e80bf21e18398cbd41e8c3b4af74c8c2'),
'This is an example of a signed message.'
res = btc.verify_message(
self.client,
"Bitcoin",
"1JwSSubhmg6iPtRjtyqhUYYH7bZg3Lfy1T",
unhexlify(
"1ba77e01a9e17ba158b962cfef5f13dfed676ffc2b4bada24e58f784458b52b97421470d001d53d5880cf5e10e76f02be3e80bf21e18398cbd41e8c3b4af74c8c2"
),
"This is an example of a signed message.",
)
assert res is True
# uncompressed pubkey - FAIL - wrong sig
res = self.client.verify_message(
'Bitcoin',
'1JwSSubhmg6iPtRjtyqhUYYH7bZg3Lfy1T',
unhexlify('1ba77e01a9e17ba158b962cfef5f13dfed676ffc2b4bada24e58f784458b52b97421470d001d53d5880cf5e10e76f02be3e80bf21e18398cbd41e8c3b4af74c800'),
'This is an example of a signed message.'
res = btc.verify_message(
self.client,
"Bitcoin",
"1JwSSubhmg6iPtRjtyqhUYYH7bZg3Lfy1T",
unhexlify(
"1ba77e01a9e17ba158b962cfef5f13dfed676ffc2b4bada24e58f784458b52b97421470d001d53d5880cf5e10e76f02be3e80bf21e18398cbd41e8c3b4af74c800"
),
"This is an example of a signed message.",
)
assert res is False
# uncompressed pubkey - FAIL - wrong msg
res = self.client.verify_message(
'Bitcoin',
'1JwSSubhmg6iPtRjtyqhUYYH7bZg3Lfy1T',
unhexlify('1ba77e01a9e17ba158b962cfef5f13dfed676ffc2b4bada24e58f784458b52b97421470d001d53d5880cf5e10e76f02be3e80bf21e18398cbd41e8c3b4af74c8c2'),
'This is an example of a signed message!'
res = btc.verify_message(
self.client,
"Bitcoin",
"1JwSSubhmg6iPtRjtyqhUYYH7bZg3Lfy1T",
unhexlify(
"1ba77e01a9e17ba158b962cfef5f13dfed676ffc2b4bada24e58f784458b52b97421470d001d53d5880cf5e10e76f02be3e80bf21e18398cbd41e8c3b4af74c8c2"
),
"This is an example of a signed message!",
)
assert res is False
# compressed pubkey - OK
res = self.client.verify_message(
'Bitcoin',
'1C7zdTfnkzmr13HfA2vNm5SJYRK6nEKyq8',
unhexlify('1f44e3e461f7ca9f57c472ce1a28214df1de1dadefb6551a32d1907b80c74d5a1fbfd6daaba12dd8cb06699ce3f6941fbe0f3957b5802d13076181046e741eaaaf'),
'This is an example of a signed message.')
res = btc.verify_message(
self.client,
"Bitcoin",
"1C7zdTfnkzmr13HfA2vNm5SJYRK6nEKyq8",
unhexlify(
"1f44e3e461f7ca9f57c472ce1a28214df1de1dadefb6551a32d1907b80c74d5a1fbfd6daaba12dd8cb06699ce3f6941fbe0f3957b5802d13076181046e741eaaaf"
),
"This is an example of a signed message.",
)
assert res is True
# compressed pubkey - FAIL - wrong sig
res = self.client.verify_message(
'Bitcoin',
'1C7zdTfnkzmr13HfA2vNm5SJYRK6nEKyq8',
unhexlify('1f44e3e461f7ca9f57c472ce1a28214df1de1dadefb6551a32d1907b80c74d5a1fbfd6daaba12dd8cb06699ce3f6941fbe0f3957b5802d13076181046e741eaa00'),
'This is an example of a signed message.'
res = btc.verify_message(
self.client,
"Bitcoin",
"1C7zdTfnkzmr13HfA2vNm5SJYRK6nEKyq8",
unhexlify(
"1f44e3e461f7ca9f57c472ce1a28214df1de1dadefb6551a32d1907b80c74d5a1fbfd6daaba12dd8cb06699ce3f6941fbe0f3957b5802d13076181046e741eaa00"
),
"This is an example of a signed message.",
)
assert res is False
# compressed pubkey - FAIL - wrong msg
res = self.client.verify_message(
'Bitcoin',
'1C7zdTfnkzmr13HfA2vNm5SJYRK6nEKyq8',
unhexlify('1f44e3e461f7ca9f57c472ce1a28214df1de1dadefb6551a32d1907b80c74d5a1fbfd6daaba12dd8cb06699ce3f6941fbe0f3957b5802d13076181046e741eaaaf'),
'This is an example of a signed message!')
res = btc.verify_message(
self.client,
"Bitcoin",
"1C7zdTfnkzmr13HfA2vNm5SJYRK6nEKyq8",
unhexlify(
"1f44e3e461f7ca9f57c472ce1a28214df1de1dadefb6551a32d1907b80c74d5a1fbfd6daaba12dd8cb06699ce3f6941fbe0f3957b5802d13076181046e741eaaaf"
),
"This is an example of a signed message!",
)
assert res is False
# trezor pubkey - OK
res = self.client.verify_message(
'Bitcoin',
'14LmW5k4ssUrtbAB4255zdqv3b4w1TuX9e',
unhexlify('209e23edf0e4e47ff1dec27f32cd78c50e74ef018ee8a6adf35ae17c7a9b0dd96f48b493fd7dbab03efb6f439c6383c9523b3bbc5f1a7d158a6af90ab154e9be80'),
'This is an example of a signed message.'
res = btc.verify_message(
self.client,
"Bitcoin",
"14LmW5k4ssUrtbAB4255zdqv3b4w1TuX9e",
unhexlify(
"209e23edf0e4e47ff1dec27f32cd78c50e74ef018ee8a6adf35ae17c7a9b0dd96f48b493fd7dbab03efb6f439c6383c9523b3bbc5f1a7d158a6af90ab154e9be80"
),
"This is an example of a signed message.",
)
assert res is True
# trezor pubkey - FAIL - wrong sig
res = self.client.verify_message(
'Bitcoin',
'14LmW5k4ssUrtbAB4255zdqv3b4w1TuX9e',
unhexlify('209e23edf0e4e47ff1dec27f32cd78c50e74ef018ee8a6adf35ae17c7a9b0dd96f48b493fd7dbab03efb6f439c6383c9523b3bbc5f1a7d158a6af90ab154e9be00'),
'This is an example of a signed message.'
res = btc.verify_message(
self.client,
"Bitcoin",
"14LmW5k4ssUrtbAB4255zdqv3b4w1TuX9e",
unhexlify(
"209e23edf0e4e47ff1dec27f32cd78c50e74ef018ee8a6adf35ae17c7a9b0dd96f48b493fd7dbab03efb6f439c6383c9523b3bbc5f1a7d158a6af90ab154e9be00"
),
"This is an example of a signed message.",
)
assert res is False
# trezor pubkey - FAIL - wrong msg
res = self.client.verify_message(
'Bitcoin',
'14LmW5k4ssUrtbAB4255zdqv3b4w1TuX9e',
unhexlify('209e23edf0e4e47ff1dec27f32cd78c50e74ef018ee8a6adf35ae17c7a9b0dd96f48b493fd7dbab03efb6f439c6383c9523b3bbc5f1a7d158a6af90ab154e9be80'),
'This is an example of a signed message!'
res = btc.verify_message(
self.client,
"Bitcoin",
"14LmW5k4ssUrtbAB4255zdqv3b4w1TuX9e",
unhexlify(
"209e23edf0e4e47ff1dec27f32cd78c50e74ef018ee8a6adf35ae17c7a9b0dd96f48b493fd7dbab03efb6f439c6383c9523b3bbc5f1a7d158a6af90ab154e9be80"
),
"This is an example of a signed message!",
)
assert res is False
def test_message_verify_bcash(self):
self.setup_mnemonic_nopin_nopassphrase()
res = self.client.verify_message(
'Bcash',
'bitcoincash:qqj22md58nm09vpwsw82fyletkxkq36zxyxh322pru',
unhexlify('209e23edf0e4e47ff1dec27f32cd78c50e74ef018ee8a6adf35ae17c7a9b0dd96f48b493fd7dbab03efb6f439c6383c9523b3bbc5f1a7d158a6af90ab154e9be80'),
'This is an example of a signed message.'
res = btc.verify_message(
self.client,
"Bcash",
"bitcoincash:qqj22md58nm09vpwsw82fyletkxkq36zxyxh322pru",
unhexlify(
"209e23edf0e4e47ff1dec27f32cd78c50e74ef018ee8a6adf35ae17c7a9b0dd96f48b493fd7dbab03efb6f439c6383c9523b3bbc5f1a7d158a6af90ab154e9be80"
),
"This is an example of a signed message.",
)
assert res is True
def test_verify_bitcoind(self):
self.setup_mnemonic_nopin_nopassphrase()
res = self.client.verify_message(
'Bitcoin',
'1KzXE97kV7DrpxCViCN3HbGbiKhzzPM7TQ',
unhexlify('1cc694f0f23901dfe3603789142f36a3fc582d0d5c0ec7215cf2ccd641e4e37228504f3d4dc3eea28bbdbf5da27c49d4635c097004d9f228750ccd836a8e1460c0'),
u'\u017elu\u0165ou\u010dk\xfd k\u016f\u0148 \xfap\u011bl \u010f\xe1belsk\xe9 \xf3dy'
res = btc.verify_message(
self.client,
"Bitcoin",
"1KzXE97kV7DrpxCViCN3HbGbiKhzzPM7TQ",
unhexlify(
"1cc694f0f23901dfe3603789142f36a3fc582d0d5c0ec7215cf2ccd641e4e37228504f3d4dc3eea28bbdbf5da27c49d4635c097004d9f228750ccd836a8e1460c0"
),
u"\u017elu\u0165ou\u010dk\xfd k\u016f\u0148 \xfap\u011bl \u010f\xe1belsk\xe9 \xf3dy",
)
assert res is True
@ -148,21 +190,27 @@ class TestMsgVerifymessage(TrezorTest):
def test_verify_utf(self):
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_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 = self.client.verify_message(
'Bitcoin',
'14LmW5k4ssUrtbAB4255zdqv3b4w1TuX9e',
unhexlify('20d0ec02ed8da8df23e7fe9e680e7867cc290312fe1c970749d8306ddad1a1eda41c6a771b13d495dd225b13b0a9d0f915a984ee3d0703f92287bf8009fbb9f7d6'),
words_nfkd
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"
res_nfkd = btc.verify_message(
self.client,
"Bitcoin",
"14LmW5k4ssUrtbAB4255zdqv3b4w1TuX9e",
unhexlify(
"20d0ec02ed8da8df23e7fe9e680e7867cc290312fe1c970749d8306ddad1a1eda41c6a771b13d495dd225b13b0a9d0f915a984ee3d0703f92287bf8009fbb9f7d6"
),
words_nfkd,
)
res_nfc = self.client.verify_message(
'Bitcoin',
'14LmW5k4ssUrtbAB4255zdqv3b4w1TuX9e',
unhexlify('20d0ec02ed8da8df23e7fe9e680e7867cc290312fe1c970749d8306ddad1a1eda41c6a771b13d495dd225b13b0a9d0f915a984ee3d0703f92287bf8009fbb9f7d6'),
words_nfc
res_nfc = btc.verify_message(
self.client,
"Bitcoin",
"14LmW5k4ssUrtbAB4255zdqv3b4w1TuX9e",
unhexlify(
"20d0ec02ed8da8df23e7fe9e680e7867cc290312fe1c970749d8306ddad1a1eda41c6a771b13d495dd225b13b0a9d0f915a984ee3d0703f92287bf8009fbb9f7d6"
),
words_nfc,
)
assert res_nfkd is True

@ -16,28 +16,35 @@
from binascii import unhexlify
from trezorlib import btc
from .common import TrezorTest
class TestMsgVerifymessageSegwit(TrezorTest):
def test_message_long(self):
self.setup_mnemonic_nopin_nopassphrase()
ret = self.client.verify_message(
'Bitcoin',
'3CwYaeWxhpXXiHue3ciQez1DLaTEAXcKa1',
unhexlify('245ff795c29aef7538f8b3bdb2e8add0d0722ad630a140b6aefd504a5a895cbd867cbb00981afc50edd0398211e8d7c304bb8efa461181bc0afa67ea4a720a89ed'),
"VeryLongMessage!" * 64
ret = btc.verify_message(
self.client,
"Bitcoin",
"3CwYaeWxhpXXiHue3ciQez1DLaTEAXcKa1",
unhexlify(
"245ff795c29aef7538f8b3bdb2e8add0d0722ad630a140b6aefd504a5a895cbd867cbb00981afc50edd0398211e8d7c304bb8efa461181bc0afa67ea4a720a89ed"
),
"VeryLongMessage!" * 64,
)
assert ret is True
def test_message_testnet(self):
self.setup_mnemonic_nopin_nopassphrase()
ret = self.client.verify_message(
'Testnet',
'2N4VkePSzKH2sv5YBikLHGvzUYvfPxV6zS9',
unhexlify('249e23edf0e4e47ff1dec27f32cd78c50e74ef018ee8a6adf35ae17c7a9b0dd96f48b493fd7dbab03efb6f439c6383c9523b3bbc5f1a7d158a6af90ab154e9be80'),
'This is an example of a signed message.'
ret = btc.verify_message(
self.client,
"Testnet",
"2N4VkePSzKH2sv5YBikLHGvzUYvfPxV6zS9",
unhexlify(
"249e23edf0e4e47ff1dec27f32cd78c50e74ef018ee8a6adf35ae17c7a9b0dd96f48b493fd7dbab03efb6f439c6383c9523b3bbc5f1a7d158a6af90ab154e9be80"
),
"This is an example of a signed message.",
)
assert ret is True
@ -45,50 +52,65 @@ class TestMsgVerifymessageSegwit(TrezorTest):
self.setup_mnemonic_nopin_nopassphrase()
# trezor pubkey - OK
res = self.client.verify_message(
'Bitcoin',
'3CwYaeWxhpXXiHue3ciQez1DLaTEAXcKa1',
unhexlify('249e23edf0e4e47ff1dec27f32cd78c50e74ef018ee8a6adf35ae17c7a9b0dd96f48b493fd7dbab03efb6f439c6383c9523b3bbc5f1a7d158a6af90ab154e9be80'),
'This is an example of a signed message.'
res = btc.verify_message(
self.client,
"Bitcoin",
"3CwYaeWxhpXXiHue3ciQez1DLaTEAXcKa1",
unhexlify(
"249e23edf0e4e47ff1dec27f32cd78c50e74ef018ee8a6adf35ae17c7a9b0dd96f48b493fd7dbab03efb6f439c6383c9523b3bbc5f1a7d158a6af90ab154e9be80"
),
"This is an example of a signed message.",
)
assert res is True
# trezor pubkey - FAIL - wrong sig
res = self.client.verify_message(
'Bitcoin',
'3CwYaeWxhpXXiHue3ciQez1DLaTEAXcKa1',
unhexlify('249e23edf0e4e47ff1dec27f32cd78c50e74ef018ee8a6adf35ae17c7a9b0dd96f48b493fd7dbab03efb6f439c6383c9523b3bbc5f1a7d158a6af90ab154e9be00'),
'This is an example of a signed message.'
res = btc.verify_message(
self.client,
"Bitcoin",
"3CwYaeWxhpXXiHue3ciQez1DLaTEAXcKa1",
unhexlify(
"249e23edf0e4e47ff1dec27f32cd78c50e74ef018ee8a6adf35ae17c7a9b0dd96f48b493fd7dbab03efb6f439c6383c9523b3bbc5f1a7d158a6af90ab154e9be00"
),
"This is an example of a signed message.",
)
assert res is False
# trezor pubkey - FAIL - wrong msg
res = self.client.verify_message(
'Bitcoin',
'3CwYaeWxhpXXiHue3ciQez1DLaTEAXcKa1',
unhexlify('249e23edf0e4e47ff1dec27f32cd78c50e74ef018ee8a6adf35ae17c7a9b0dd96f48b493fd7dbab03efb6f439c6383c9523b3bbc5f1a7d158a6af90ab154e9be80'),
'This is an example of a signed message!'
res = btc.verify_message(
self.client,
"Bitcoin",
"3CwYaeWxhpXXiHue3ciQez1DLaTEAXcKa1",
unhexlify(
"249e23edf0e4e47ff1dec27f32cd78c50e74ef018ee8a6adf35ae17c7a9b0dd96f48b493fd7dbab03efb6f439c6383c9523b3bbc5f1a7d158a6af90ab154e9be80"
),
"This is an example of a signed message!",
)
assert res is False
def test_verify_utf(self):
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_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_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"
res_nfkd = self.client.verify_message(
'Bitcoin',
'3CwYaeWxhpXXiHue3ciQez1DLaTEAXcKa1',
unhexlify('24d0ec02ed8da8df23e7fe9e680e7867cc290312fe1c970749d8306ddad1a1eda41c6a771b13d495dd225b13b0a9d0f915a984ee3d0703f92287bf8009fbb9f7d6'),
words_nfkd
res_nfkd = btc.verify_message(
self.client,
"Bitcoin",
"3CwYaeWxhpXXiHue3ciQez1DLaTEAXcKa1",
unhexlify(
"24d0ec02ed8da8df23e7fe9e680e7867cc290312fe1c970749d8306ddad1a1eda41c6a771b13d495dd225b13b0a9d0f915a984ee3d0703f92287bf8009fbb9f7d6"
),
words_nfkd,
)
res_nfc = self.client.verify_message(
'Bitcoin',
'3CwYaeWxhpXXiHue3ciQez1DLaTEAXcKa1',
unhexlify('24d0ec02ed8da8df23e7fe9e680e7867cc290312fe1c970749d8306ddad1a1eda41c6a771b13d495dd225b13b0a9d0f915a984ee3d0703f92287bf8009fbb9f7d6'),
words_nfc
res_nfc = btc.verify_message(
self.client,
"Bitcoin",
"3CwYaeWxhpXXiHue3ciQez1DLaTEAXcKa1",
unhexlify(
"24d0ec02ed8da8df23e7fe9e680e7867cc290312fe1c970749d8306ddad1a1eda41c6a771b13d495dd225b13b0a9d0f915a984ee3d0703f92287bf8009fbb9f7d6"
),
words_nfc,
)
assert res_nfkd is True

@ -16,28 +16,35 @@
from binascii import unhexlify
from trezorlib import btc
from .common import TrezorTest
class TestMsgVerifymessageSegwitNative(TrezorTest):
def test_message_long(self):
self.setup_mnemonic_nopin_nopassphrase()
ret = self.client.verify_message(
'Bitcoin',
'bc1qyjjkmdpu7metqt5r36jf872a34syws33s82q2j',
unhexlify('285ff795c29aef7538f8b3bdb2e8add0d0722ad630a140b6aefd504a5a895cbd867cbb00981afc50edd0398211e8d7c304bb8efa461181bc0afa67ea4a720a89ed'),
"VeryLongMessage!" * 64
ret = btc.verify_message(
self.client,
"Bitcoin",
"bc1qyjjkmdpu7metqt5r36jf872a34syws33s82q2j",
unhexlify(
"285ff795c29aef7538f8b3bdb2e8add0d0722ad630a140b6aefd504a5a895cbd867cbb00981afc50edd0398211e8d7c304bb8efa461181bc0afa67ea4a720a89ed"
),
"VeryLongMessage!" * 64,
)
assert ret is True
def test_message_testnet(self):
self.setup_mnemonic_nopin_nopassphrase()
ret = self.client.verify_message(
'Testnet',
'tb1qyjjkmdpu7metqt5r36jf872a34syws336p3n3p',
unhexlify('289e23edf0e4e47ff1dec27f32cd78c50e74ef018ee8a6adf35ae17c7a9b0dd96f48b493fd7dbab03efb6f439c6383c9523b3bbc5f1a7d158a6af90ab154e9be80'),
'This is an example of a signed message.'
ret = btc.verify_message(
self.client,
"Testnet",
"tb1qyjjkmdpu7metqt5r36jf872a34syws336p3n3p",
unhexlify(
"289e23edf0e4e47ff1dec27f32cd78c50e74ef018ee8a6adf35ae17c7a9b0dd96f48b493fd7dbab03efb6f439c6383c9523b3bbc5f1a7d158a6af90ab154e9be80"
),
"This is an example of a signed message.",
)
assert ret is True
@ -45,50 +52,65 @@ class TestMsgVerifymessageSegwitNative(TrezorTest):
self.setup_mnemonic_nopin_nopassphrase()
# trezor pubkey - OK
res = self.client.verify_message(
'Bitcoin',
'bc1qyjjkmdpu7metqt5r36jf872a34syws33s82q2j',
unhexlify('289e23edf0e4e47ff1dec27f32cd78c50e74ef018ee8a6adf35ae17c7a9b0dd96f48b493fd7dbab03efb6f439c6383c9523b3bbc5f1a7d158a6af90ab154e9be80'),
'This is an example of a signed message.'
res = btc.verify_message(
self.client,
"Bitcoin",
"bc1qyjjkmdpu7metqt5r36jf872a34syws33s82q2j",
unhexlify(
"289e23edf0e4e47ff1dec27f32cd78c50e74ef018ee8a6adf35ae17c7a9b0dd96f48b493fd7dbab03efb6f439c6383c9523b3bbc5f1a7d158a6af90ab154e9be80"
),
"This is an example of a signed message.",
)
assert res is True
# trezor pubkey - FAIL - wrong sig
res = self.client.verify_message(
'Bitcoin',
'bc1qyjjkmdpu7metqt5r36jf872a34syws33s82q2j',
unhexlify('289e23edf0e4e47ff1dec27f32cd78c50e74ef018ee8a6adf35ae17c7a9b0dd96f48b493fd7dbab03efb6f439c6383c9523b3bbc5f1a7d158a6af90ab154e9be00'),
'This is an example of a signed message.'
res = btc.verify_message(
self.client,
"Bitcoin",
"bc1qyjjkmdpu7metqt5r36jf872a34syws33s82q2j",
unhexlify(
"289e23edf0e4e47ff1dec27f32cd78c50e74ef018ee8a6adf35ae17c7a9b0dd96f48b493fd7dbab03efb6f439c6383c9523b3bbc5f1a7d158a6af90ab154e9be00"
),
"This is an example of a signed message.",
)
assert res is False
# trezor pubkey - FAIL - wrong msg
res = self.client.verify_message(
'Bitcoin',
'bc1qyjjkmdpu7metqt5r36jf872a34syws33s82q2j',
unhexlify('289e23edf0e4e47ff1dec27f32cd78c50e74ef018ee8a6adf35ae17c7a9b0dd96f48b493fd7dbab03efb6f439c6383c9523b3bbc5f1a7d158a6af90ab154e9be80'),
'This is an example of a signed message!'
res = btc.verify_message(
self.client,
"Bitcoin",
"bc1qyjjkmdpu7metqt5r36jf872a34syws33s82q2j",
unhexlify(
"289e23edf0e4e47ff1dec27f32cd78c50e74ef018ee8a6adf35ae17c7a9b0dd96f48b493fd7dbab03efb6f439c6383c9523b3bbc5f1a7d158a6af90ab154e9be80"
),
"This is an example of a signed message!",
)
assert res is False
def test_verify_utf(self):
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_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_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"
res_nfkd = self.client.verify_message(
'Bitcoin',
'bc1qyjjkmdpu7metqt5r36jf872a34syws33s82q2j',
unhexlify('28d0ec02ed8da8df23e7fe9e680e7867cc290312fe1c970749d8306ddad1a1eda41c6a771b13d495dd225b13b0a9d0f915a984ee3d0703f92287bf8009fbb9f7d6'),
words_nfkd
res_nfkd = btc.verify_message(
self.client,
"Bitcoin",
"bc1qyjjkmdpu7metqt5r36jf872a34syws33s82q2j",
unhexlify(
"28d0ec02ed8da8df23e7fe9e680e7867cc290312fe1c970749d8306ddad1a1eda41c6a771b13d495dd225b13b0a9d0f915a984ee3d0703f92287bf8009fbb9f7d6"
),
words_nfkd,
)
res_nfc = self.client.verify_message(
'Bitcoin',
'bc1qyjjkmdpu7metqt5r36jf872a34syws33s82q2j',
unhexlify('28d0ec02ed8da8df23e7fe9e680e7867cc290312fe1c970749d8306ddad1a1eda41c6a771b13d495dd225b13b0a9d0f915a984ee3d0703f92287bf8009fbb9f7d6'),
words_nfc
res_nfc = btc.verify_message(
self.client,
"Bitcoin",
"bc1qyjjkmdpu7metqt5r36jf872a34syws33s82q2j",
unhexlify(
"28d0ec02ed8da8df23e7fe9e680e7867cc290312fe1c970749d8306ddad1a1eda41c6a771b13d495dd225b13b0a9d0f915a984ee3d0703f92287bf8009fbb9f7d6"
),
words_nfc,
)
assert res_nfkd is True

@ -14,13 +14,12 @@
# 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>.
from .common import TrezorTest
from trezorlib import device, messages as proto
from trezorlib import messages as proto
from .common import TrezorTest
class TestMsgWipedevice(TrezorTest):
def test_wipe_device(self):
self.setup_mnemonic_pin_passphrase()
features = self.client.call_raw(proto.Initialize())
@ -30,7 +29,7 @@ class TestMsgWipedevice(TrezorTest):
assert features.passphrase_protection is True
device_id = features.device_id
self.client.wipe_device()
device.wipe(self.client)
features = self.client.call_raw(proto.Initialize())
assert features.initialized is False

@ -15,14 +15,18 @@
# If not, see <https://www.gnu.org/licenses/lgpl-3.0.html>.
from binascii import hexlify, unhexlify
import pytest
from .common import TrezorTest
from trezorlib import btc, messages as proto
from trezorlib.tools import CallException
from ..support import ckd_public as bip32
from trezorlib import messages as proto
from trezorlib.client import CallException
from .common import TrezorTest
TXHASH_c6091a = unhexlify('c6091adf4c0c23982a35899a6e58ae11e703eacd7954f588ed4b9cdefc4dba52')
TXHASH_c6091a = unhexlify(
"c6091adf4c0c23982a35899a6e58ae11e703eacd7954f588ed4b9cdefc4dba52"
)
# Multisig howto:
@ -32,7 +36,6 @@ TXHASH_c6091a = unhexlify('c6091adf4c0c23982a35899a6e58ae11e703eacd7954f588ed4b9
class TestMultisig(TrezorTest):
def test_2_of_3(self):
self.setup_mnemonic_nopin_nopassphrase()
@ -57,15 +60,17 @@ class TestMultisig(TrezorTest):
# tx: c6091adf4c0c23982a35899a6e58ae11e703eacd7954f588ed4b9cdefc4dba52
# input 1: 0.001 BTC
node = bip32.deserialize('xpub661MyMwAqRbcF1zGijBb2K6x9YiJPh58xpcCeLvTxMX6spkY3PcpJ4ABcCyWfskq5DDxM3e6Ez5ePCqG5bnPUXR4wL8TZWyoDaUdiWW7bKy')
node = bip32.deserialize(
"xpub661MyMwAqRbcF1zGijBb2K6x9YiJPh58xpcCeLvTxMX6spkY3PcpJ4ABcCyWfskq5DDxM3e6Ez5ePCqG5bnPUXR4wL8TZWyoDaUdiWW7bKy"
)
multisig = proto.MultisigRedeemScriptType(
pubkeys=[
proto.HDNodePathType(node=node, address_n=[1]),
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,
)
@ -79,31 +84,69 @@ class TestMultisig(TrezorTest):
)
out1 = proto.TxOutputType(
address='12iyMbUb4R2K3gre4dHSrbu5azG5KaqVss',
address="12iyMbUb4R2K3gre4dHSrbu5azG5KaqVss",
amount=100000,
script_type=proto.OutputScriptType.PAYTOADDRESS
script_type=proto.OutputScriptType.PAYTOADDRESS,
)
with self.client:
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(request_type=proto.RequestType.TXINPUT, 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),
])
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(
request_type=proto.RequestType.TXINPUT,
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
(signatures1, _) = self.client.sign_tx('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
@ -112,9 +155,13 @@ class TestMultisig(TrezorTest):
pubkeys=[
proto.HDNodePathType(node=node, address_n=[1]),
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,
)
@ -128,26 +175,69 @@ class TestMultisig(TrezorTest):
)
with self.client:
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(request_type=proto.RequestType.TXINPUT, 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),
])
(signatures2, serialized_tx) = self.client.sign_tx('Bitcoin', [inp3, ], [out1, ])
assert hexlify(signatures2[0]) == b'3045022100f5428fe0531b3095675b40d87cab607ee036fac823b22e8dcec35b65aff6e52b022032129b4577ff923d321a1c70db5a6cec5bcc142cb2c51901af8b989cced23e0d'
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(
request_type=proto.RequestType.TXINPUT,
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),
]
)
(signatures2, serialized_tx) = btc.sign_tx(
self.client, "Bitcoin", [inp3], [out1]
)
assert (
hexlify(signatures2[0])
== b"3045022100f5428fe0531b3095675b40d87cab607ee036fac823b22e8dcec35b65aff6e52b022032129b4577ff923d321a1c70db5a6cec5bcc142cb2c51901af8b989cced23e0d"
)
# Accepted by network: tx 8382a2b2e3ec8788800c1d46d285dfa9dd4051edddd75982fad166b9273e5ac6
assert hexlify(serialized_tx) == b'010000000152ba4dfcde9c4bed88f55479cdea03e711ae586e9a89352a98230c4cdf1a09c601000000fdfe0000483045022100985cc1ba316d140eb4b2d4028d8cd1c451f87bff8ff679858732e516ad04cd3402207af6edda99972af0baa7702a3b7448517c8242e7bca669f6861771cdd16ee05801483045022100f5428fe0531b3095675b40d87cab607ee036fac823b22e8dcec35b65aff6e52b022032129b4577ff923d321a1c70db5a6cec5bcc142cb2c51901af8b989cced23e0d014c6952210338d78612e990f2eea0c426b5e48a8db70b9d7ed66282b3b26511e0b1c75515a621038caebd6f753bbbd2bb1f3346a43cd32140648583673a31d62f2dfb56ad0ab9e32103477b9f0f34ae85434ce795f0c5e1e90c9420e5b5fad084d7cce9a487b94a790253aeffffffff01a0860100000000001976a91412e8391ad256dcdc023365978418d658dfecba1c88ac00000000'
assert (
hexlify(serialized_tx)
== b"010000000152ba4dfcde9c4bed88f55479cdea03e711ae586e9a89352a98230c4cdf1a09c601000000fdfe0000483045022100985cc1ba316d140eb4b2d4028d8cd1c451f87bff8ff679858732e516ad04cd3402207af6edda99972af0baa7702a3b7448517c8242e7bca669f6861771cdd16ee05801483045022100f5428fe0531b3095675b40d87cab607ee036fac823b22e8dcec35b65aff6e52b022032129b4577ff923d321a1c70db5a6cec5bcc142cb2c51901af8b989cced23e0d014c6952210338d78612e990f2eea0c426b5e48a8db70b9d7ed66282b3b26511e0b1c75515a621038caebd6f753bbbd2bb1f3346a43cd32140648583673a31d62f2dfb56ad0ab9e32103477b9f0f34ae85434ce795f0c5e1e90c9420e5b5fad084d7cce9a487b94a790253aeffffffff01a0860100000000001976a91412e8391ad256dcdc023365978418d658dfecba1c88ac00000000"
)
def test_15_of_15(self):
self.setup_mnemonic_nopin_nopassphrase()
@ -161,7 +251,9 @@ class TestMultisig(TrezorTest):
# xpub:
# print(bip32.serialize(self.client.get_public_node([]).node))
# xpub661MyMwAqRbcF1zGijBb2K6x9YiJPh58xpcCeLvTxMX6spkY3PcpJ4ABcCyWfskq5DDxM3e6Ez5ePCqG5bnPUXR4wL8TZWyoDaUdiWW7bKy
node = bip32.deserialize('xpub661MyMwAqRbcF1zGijBb2K6x9YiJPh58xpcCeLvTxMX6spkY3PcpJ4ABcCyWfskq5DDxM3e6Ez5ePCqG5bnPUXR4wL8TZWyoDaUdiWW7bKy')
node = bip32.deserialize(
"xpub661MyMwAqRbcF1zGijBb2K6x9YiJPh58xpcCeLvTxMX6spkY3PcpJ4ABcCyWfskq5DDxM3e6Ez5ePCqG5bnPUXR4wL8TZWyoDaUdiWW7bKy"
)
pubs = []
for x in range(15):
@ -173,35 +265,40 @@ class TestMultisig(TrezorTest):
# multisig address
# 3QaKF8zobqcqY8aS6nxCD5ZYdiRfL3RCmU
signatures = [b''] * 15
signatures = [b""] * 15
out1 = proto.TxOutputType(
address='17kTB7qSk3MupQxWdiv5ZU3zcrZc2Azes1',
address="17kTB7qSk3MupQxWdiv5ZU3zcrZc2Azes1",
amount=10000,
script_type=proto.OutputScriptType.PAYTOADDRESS
script_type=proto.OutputScriptType.PAYTOADDRESS,
)
for x in range(15):
multisig = proto.MultisigRedeemScriptType(
pubkeys=pubs,
signatures=signatures,
m=15,
pubkeys=pubs, signatures=signatures, m=15
)
inp1 = proto.TxInputType(
address_n=[x],
prev_hash=unhexlify('6189e3febb5a21cee8b725aa1ef04ffce7e609448446d3a8d6f483c634ef5315'),
prev_hash=unhexlify(
"6189e3febb5a21cee8b725aa1ef04ffce7e609448446d3a8d6f483c634ef5315"
),
prev_index=1,
script_type=proto.InputScriptType.SPENDMULTISIG,
multisig=multisig,
)
with self.client:
(sig, serialized_tx) = self.client.sign_tx('Bitcoin', [inp1, ], [out1, ])
(sig, serialized_tx) = btc.sign_tx(
self.client, "Bitcoin", [inp1], [out1]
)
signatures[x] = sig[0]
# Accepted as tx id dd320786d1f58c095be0509dc56b277b6de8f2fb5517f519c6e6708414e3300b
assert hexlify(serialized_tx) == b'01000000011553ef34c683f4d6a8d346844409e6e7fc4ff01eaa25b7e8ce215abbfee3896101000000fd43060048304502210098e23085ad7282de988bf98afa1e9add9c9830009132f8902a9fa4624d5dc98b0220733216e70ab67791aa64be5c83d2050cb4ed9ff7eda2a1acc35da024d2ab2a670147304402201f8c11fb6e90fd616e484986e9451929797eba039882a9abcc203210948060b9022044da031530de7d9747d3c5a8e7cec04b04b7af495c9120b854ce7362af7fa05a01483045022100ea67c70186acef019bdf1551881bf38e6f88186501b64d3a756a2ce18e4ba18002201c35110325653e21e448b60053a4b5dda46b61096faf701a1faca61fcde91f00014730440220315598992f156d2f9d7b4275395fa067aa61ea95829fa17730885c86df4de70d02203eda9ade1656e2198c668603b17e197acb0969ed183ab0841303ea261205618901473044022060fdd6621edde9b8cf6776bc4eef26ace9b57514d725b7214ba11d333520a30e022044c30744f94484aec0f896233c5613a3256878ec0379f566226906b6d1b6061401483045022100b1d907e3574f60f7834c7e9f2e367998ce0461dad7d742d84ef8917d713f41f902203b3ac54f7bb2f7fb8685f582d2a94f7213a37cb508acffe29090cc06ae01588b01483045022100e3bf90ff3ad6395e42f46002f253f94ca0e8ffaa0620f2ceb4fa21493abdca4d02201d4c28b10b740bb2dc4b3695b4205c18f8c0dad2bb69540eb8a36576463cd5280147304402202cfaf9fab7dc1c9f0c3c23bd46bd6d5cea0664d914139fc9add80766ce998808022012db2802c07853e4cbe147afdf0b47e60bdcbcd31f9df19e04c177ed9aa66c6d0147304402207cbc2d83f351eee5ee91df26bb0c7e1cb07fe328cbbcdb0bb9656d37922c497302201b3435d4c71ffd1b34d45892f2a487bd79c8c7f57cc04373287642bb9610cb840147304402202dc3eab30ccb06553703e794212f43ee9a659f5e787a8374e9ea0bf6de0def7402201a70e970c21a807783313ed102bf4f0a3406ac7c84f94bc8194c5e209464d7230147304402206b04530c190c46a879d7771a6ad53acd33547e0d7fd320d5ad0b5b1fdeb5d4c202207b812be81c3419daadc942cca0c55aa32c7759fa7566c6dc35f030ca87a1c5be01483045022100ce523dddd6eef73d5ae7c44c870466e1ac5a7a77d43475e8def024af68977a1e022028be0276435bfa2ea887d6cf89fa829f96c1c7a55edc57bb3fd667d523fd3bf601473044022019410b20ebcd8eb3ee7ec1eff6bf0f9cbfaea82116811c61f3cf24af7e4434b1022009e5823f3349f695be09ae40754185300d8442a22715ddb5ffa17c4213140e7201483045022100964ef26a9074c3cdafffcfbe4bd445933f8c842ba11fd887922adcf7fabe0c82022023055d94c75ab223c767fbaa825c917e9beecbc7d5758cccf20d886c63d4b72a0147304402207aa3a98197697d258a8baae681f0b4c0ee682982f4205534e6c95a37dabaddd60220517a7ed5c03da2f242e17ccfdae0d81d6f454d7f9ea931fc62df6c0eab922186014d01025f21023230848585885f63803a0a8aecdd6538792d5c539215c91698e315bf0253b43d210338d78612e990f2eea0c426b5e48a8db70b9d7ed66282b3b26511e0b1c75515a621038caebd6f753bbbd2bb1f3346a43cd32140648583673a31d62f2dfb56ad0ab9e32103477b9f0f34ae85434ce795f0c5e1e90c9420e5b5fad084d7cce9a487b94a79022103fe91eca10602d7dad4c9dab2b2a0858f71e25a219a6940749ce7a48118480dae210234716c01c2dd03fa7ee302705e2b8fbd1311895d94b1dca15e62eedea9b0968f210341fb2ead334952cf60f4481ba435c4693d0be649be01d2cfe9b02018e483e7bd2102dad8b2bce360a705c16e74a50a36459b4f8f4b78f9cd67def29d54ef6f7c7cf9210222dbe3f5f197a34a1d50e2cbe2a1085cac2d605c9e176f9a240e0fd0c669330d2103fb41afab56c9cdb013fda63d777d4938ddc3cb2ad939712da688e3ed333f95982102435f177646bdc717cb3211bf46656ca7e8d642726144778c9ce816b8b8c36ccf2102158d8e20095364031d923c7e9f7f08a14b1be1ddee21fe1a5431168e31345e5521026259794892428ca0818c8fb61d2d459ddfe20e57f50803c7295e6f4e2f5586652102815f910a8689151db627e6e262e0a2075ad5ec2993a6bc1b876a9d420923d681210318f54647f645ff01bd49fedc0219343a6a22d3ea3180a3c3d3097e4b888a8db45faeffffffff0110270000000000001976a9144a087d89f8ad16ca029c675b037c02fd1c5f9aec88ac00000000'
assert (
hexlify(serialized_tx)
== b"01000000011553ef34c683f4d6a8d346844409e6e7fc4ff01eaa25b7e8ce215abbfee3896101000000fd43060048304502210098e23085ad7282de988bf98afa1e9add9c9830009132f8902a9fa4624d5dc98b0220733216e70ab67791aa64be5c83d2050cb4ed9ff7eda2a1acc35da024d2ab2a670147304402201f8c11fb6e90fd616e484986e9451929797eba039882a9abcc203210948060b9022044da031530de7d9747d3c5a8e7cec04b04b7af495c9120b854ce7362af7fa05a01483045022100ea67c70186acef019bdf1551881bf38e6f88186501b64d3a756a2ce18e4ba18002201c35110325653e21e448b60053a4b5dda46b61096faf701a1faca61fcde91f00014730440220315598992f156d2f9d7b4275395fa067aa61ea95829fa17730885c86df4de70d02203eda9ade1656e2198c668603b17e197acb0969ed183ab0841303ea261205618901473044022060fdd6621edde9b8cf6776bc4eef26ace9b57514d725b7214ba11d333520a30e022044c30744f94484aec0f896233c5613a3256878ec0379f566226906b6d1b6061401483045022100b1d907e3574f60f7834c7e9f2e367998ce0461dad7d742d84ef8917d713f41f902203b3ac54f7bb2f7fb8685f582d2a94f7213a37cb508acffe29090cc06ae01588b01483045022100e3bf90ff3ad6395e42f46002f253f94ca0e8ffaa0620f2ceb4fa21493abdca4d02201d4c28b10b740bb2dc4b3695b4205c18f8c0dad2bb69540eb8a36576463cd5280147304402202cfaf9fab7dc1c9f0c3c23bd46bd6d5cea0664d914139fc9add80766ce998808022012db2802c07853e4cbe147afdf0b47e60bdcbcd31f9df19e04c177ed9aa66c6d0147304402207cbc2d83f351eee5ee91df26bb0c7e1cb07fe328cbbcdb0bb9656d37922c497302201b3435d4c71ffd1b34d45892f2a487bd79c8c7f57cc04373287642bb9610cb840147304402202dc3eab30ccb06553703e794212f43ee9a659f5e787a8374e9ea0bf6de0def7402201a70e970c21a807783313ed102bf4f0a3406ac7c84f94bc8194c5e209464d7230147304402206b04530c190c46a879d7771a6ad53acd33547e0d7fd320d5ad0b5b1fdeb5d4c202207b812be81c3419daadc942cca0c55aa32c7759fa7566c6dc35f030ca87a1c5be01483045022100ce523dddd6eef73d5ae7c44c870466e1ac5a7a77d43475e8def024af68977a1e022028be0276435bfa2ea887d6cf89fa829f96c1c7a55edc57bb3fd667d523fd3bf601473044022019410b20ebcd8eb3ee7ec1eff6bf0f9cbfaea82116811c61f3cf24af7e4434b1022009e5823f3349f695be09ae40754185300d8442a22715ddb5ffa17c4213140e7201483045022100964ef26a9074c3cdafffcfbe4bd445933f8c842ba11fd887922adcf7fabe0c82022023055d94c75ab223c767fbaa825c917e9beecbc7d5758cccf20d886c63d4b72a0147304402207aa3a98197697d258a8baae681f0b4c0ee682982f4205534e6c95a37dabaddd60220517a7ed5c03da2f242e17ccfdae0d81d6f454d7f9ea931fc62df6c0eab922186014d01025f21023230848585885f63803a0a8aecdd6538792d5c539215c91698e315bf0253b43d210338d78612e990f2eea0c426b5e48a8db70b9d7ed66282b3b26511e0b1c75515a621038caebd6f753bbbd2bb1f3346a43cd32140648583673a31d62f2dfb56ad0ab9e32103477b9f0f34ae85434ce795f0c5e1e90c9420e5b5fad084d7cce9a487b94a79022103fe91eca10602d7dad4c9dab2b2a0858f71e25a219a6940749ce7a48118480dae210234716c01c2dd03fa7ee302705e2b8fbd1311895d94b1dca15e62eedea9b0968f210341fb2ead334952cf60f4481ba435c4693d0be649be01d2cfe9b02018e483e7bd2102dad8b2bce360a705c16e74a50a36459b4f8f4b78f9cd67def29d54ef6f7c7cf9210222dbe3f5f197a34a1d50e2cbe2a1085cac2d605c9e176f9a240e0fd0c669330d2103fb41afab56c9cdb013fda63d777d4938ddc3cb2ad939712da688e3ed333f95982102435f177646bdc717cb3211bf46656ca7e8d642726144778c9ce816b8b8c36ccf2102158d8e20095364031d923c7e9f7f08a14b1be1ddee21fe1a5431168e31345e5521026259794892428ca0818c8fb61d2d459ddfe20e57f50803c7295e6f4e2f5586652102815f910a8689151db627e6e262e0a2075ad5ec2993a6bc1b876a9d420923d681210318f54647f645ff01bd49fedc0219343a6a22d3ea3180a3c3d3097e4b888a8db45faeffffffff0110270000000000001976a9144a087d89f8ad16ca029c675b037c02fd1c5f9aec88ac00000000"
)
def test_missing_pubkey(self):
self.setup_mnemonic_nopin_nopassphrase()
@ -220,15 +317,17 @@ class TestMultisig(TrezorTest):
# xpub:
# print(bip32.serialize(self.client.get_public_node([]).node))
# xpub661MyMwAqRbcF1zGijBb2K6x9YiJPh58xpcCeLvTxMX6spkY3PcpJ4ABcCyWfskq5DDxM3e6Ez5ePCqG5bnPUXR4wL8TZWyoDaUdiWW7bKy
node = bip32.deserialize('xpub661MyMwAqRbcF1zGijBb2K6x9YiJPh58xpcCeLvTxMX6spkY3PcpJ4ABcCyWfskq5DDxM3e6Ez5ePCqG5bnPUXR4wL8TZWyoDaUdiWW7bKy')
node = bip32.deserialize(
"xpub661MyMwAqRbcF1zGijBb2K6x9YiJPh58xpcCeLvTxMX6spkY3PcpJ4ABcCyWfskq5DDxM3e6Ez5ePCqG5bnPUXR4wL8TZWyoDaUdiWW7bKy"
)
multisig = proto.MultisigRedeemScriptType(
pubkeys=[
proto.HDNodePathType(node=node, address_n=[1]),
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,
)
@ -242,13 +341,13 @@ class TestMultisig(TrezorTest):
)
out1 = proto.TxOutputType(
address='12iyMbUb4R2K3gre4dHSrbu5azG5KaqVss',
address="12iyMbUb4R2K3gre4dHSrbu5azG5KaqVss",
amount=100000,
script_type=proto.OutputScriptType.PAYTOADDRESS
script_type=proto.OutputScriptType.PAYTOADDRESS,
)
with pytest.raises(CallException) as exc:
self.client.sign_tx('Bitcoin', [inp1, ], [out1, ])
btc.sign_tx(self.client, "Bitcoin", [inp1], [out1])
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")

@ -16,34 +16,42 @@
from binascii import hexlify, unhexlify
from .common import TrezorTest
from ..support import ckd_public as bip32
from trezorlib import messages as proto
from trezorlib.tools import parse_path
from trezorlib import btc, messages as proto
from trezorlib.tools import H_, parse_path
from trezorlib.tx_api import TxApiInsight
from ..support import ckd_public as bip32
from .common import TrezorTest
TxApiTestnet = TxApiInsight("insight_testnet")
class TestMultisigChange(TrezorTest):
def setup_method(self, method):
super(TestMultisigChange, self).setup_method(method)
self.client.set_tx_api(TxApiTestnet)
node_ext1 = bip32.deserialize('tpubDADHV9u9Y6gkggintTdMjJE3be58zKNLhpxBQyuEM6Pwx3sN9JVLmMCMN4DNVwL9AKec27z5TaWcWuHzMXiGAtcra5DjwWbvppGX4gaEGVN')
node_ext1 = bip32.deserialize(
"tpubDADHV9u9Y6gkggintTdMjJE3be58zKNLhpxBQyuEM6Pwx3sN9JVLmMCMN4DNVwL9AKec27z5TaWcWuHzMXiGAtcra5DjwWbvppGX4gaEGVN"
)
# m/1 => 02c0d0c5fee952620757c6128dbf327c996cd72ed3358d15d6518a1186099bc15e
# m/2 => 0375b9dfaad928ce1a7eed88df7c084e67d99e9ab74332419458a9a45779706801
node_ext2 = bip32.deserialize('tpubDADHV9u9Y6gkhWXBmDJ6TUhZajLWjvKukRe2w9FfhdbQpUux8Z8jnPHNAZqFRgHPg9sR7YR93xThM32M7NfRu8S5WyDtext7S62sqxeJNkd')
node_ext2 = bip32.deserialize(
"tpubDADHV9u9Y6gkhWXBmDJ6TUhZajLWjvKukRe2w9FfhdbQpUux8Z8jnPHNAZqFRgHPg9sR7YR93xThM32M7NfRu8S5WyDtext7S62sqxeJNkd"
)
# m/1 => 0388460dc439f4c8f5bcfc268c36e11b4375cad5c3535c336cfdf8c32c3afad5c1
# m/2 => 03a04f945d5a3685729dde697d574076de4bdf38e904f813b22a851548e1110fc0
node_ext3 = bip32.deserialize('tpubDADHV9u9Y6gkmM5ohWRGTswrc6fr7soH7e2D2ic5a86PDUaHc5Ln9EbER69cEr5bDZPa7EXguJ1MhWVzPZpZWVdG5fvoF3hfirXvRbpCCBg')
node_ext3 = bip32.deserialize(
"tpubDADHV9u9Y6gkmM5ohWRGTswrc6fr7soH7e2D2ic5a86PDUaHc5Ln9EbER69cEr5bDZPa7EXguJ1MhWVzPZpZWVdG5fvoF3hfirXvRbpCCBg"
)
# m/1 => 02e0c21e2a7cf00b94c5421725acff97f9826598b91f2340c5ddda730caca7d648
# m/2 => 03928301ffb8c0d7a364b794914c716ba3107cc78a6fe581028b0d8638b22e8573
node_int = bip32.deserialize('tpubDADHV9u9Y6gke2Vw3rWE8KRXmeK8PTtsF5B3Cqjo6h3SoiyRtzxjnDVG1knxrqB8BpP1dMAd6MR3Ps5UXibiFDtQuWVPXLkJ3HvttZYbH12')
node_int = bip32.deserialize(
"tpubDADHV9u9Y6gke2Vw3rWE8KRXmeK8PTtsF5B3Cqjo6h3SoiyRtzxjnDVG1knxrqB8BpP1dMAd6MR3Ps5UXibiFDtQuWVPXLkJ3HvttZYbH12"
)
# m/1 => 03f91460d79e4e463d7d90cb75254bcd62b515a99a950574c721efdc5f711dff35
# m/2 => 038caebd6f753bbbd2bb1f3346a43cd32140648583673a31d62f2dfb56ad0ab9e3
@ -69,9 +77,9 @@ class TestMultisigChange(TrezorTest):
pubkeys=[
proto.HDNodePathType(node=node_ext2, 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,
)
@ -81,7 +89,7 @@ class TestMultisigChange(TrezorTest):
proto.HDNodePathType(node=node_ext2, address_n=[0, 1]),
proto.HDNodePathType(node=node_int, address_n=[0, 1]),
],
signatures=[b'', b'', b''],
signatures=[b"", b"", b""],
m=2,
)
@ -89,16 +97,18 @@ class TestMultisigChange(TrezorTest):
pubkeys=[
proto.HDNodePathType(node=node_ext1, 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,
)
# 2N9W4z9AhAPaHghtqVQPbaTAGHdbrhKeBQw
inp1 = proto.TxInputType(
address_n=[45 | 0x80000000, 0, 0, 0],
prev_hash=unhexlify('16c6c8471b8db7a628f2b2bb86bfeefae1766463ce8692438c7fd3fce3f43ce5'),
address_n=[H_(45), 0, 0, 0],
prev_hash=unhexlify(
"16c6c8471b8db7a628f2b2bb86bfeefae1766463ce8692438c7fd3fce3f43ce5"
),
prev_index=1,
script_type=proto.InputScriptType.SPENDMULTISIG,
multisig=multisig_in1,
@ -106,8 +116,10 @@ class TestMultisigChange(TrezorTest):
# 2NDBG6QXQLtnQ3jRGkrqo53BiCeXfQXLdj4
inp2 = proto.TxInputType(
address_n=[45 | 0x80000000, 0, 0, 1],
prev_hash=unhexlify('d80c34ee14143a8bf61125102b7ef594118a3796cad670fa8ee15080ae155318'),
address_n=[H_(45), 0, 0, 1],
prev_hash=unhexlify(
"d80c34ee14143a8bf61125102b7ef594118a3796cad670fa8ee15080ae155318"
),
prev_index=0,
script_type=proto.InputScriptType.SPENDMULTISIG,
multisig=multisig_in2,
@ -115,8 +127,10 @@ class TestMultisigChange(TrezorTest):
# 2MvwPWfp2XPU3S1cMwgEMKBPUw38VP5SBE4
inp3 = proto.TxInputType(
address_n=[45 | 0x80000000, 0, 0, 1],
prev_hash=unhexlify('b0946dc27ba308a749b11afecc2018980af18f79e89ad6b080b58220d856f739'),
address_n=[H_(45), 0, 0, 1],
prev_hash=unhexlify(
"b0946dc27ba308a749b11afecc2018980af18f79e89ad6b080b58220d856f739"
),
prev_index=0,
script_type=proto.InputScriptType.SPENDMULTISIG,
multisig=multisig_in3,
@ -124,41 +138,115 @@ class TestMultisigChange(TrezorTest):
def _responses(self, inp1, inp2, change=0):
resp = [
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=inp1.prev_hash)),
proto.TxRequest(request_type=proto.RequestType.TXINPUT, 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)),
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=inp1.prev_hash),
),
proto.TxRequest(
request_type=proto.RequestType.TXINPUT,
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:
resp.append(
proto.ButtonRequest(code=proto.ButtonRequestType.ConfirmOutput)
)
resp.append(proto.ButtonRequest(code=proto.ButtonRequestType.ConfirmOutput))
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:
resp.append(
proto.ButtonRequest(code=proto.ButtonRequestType.ConfirmOutput)
)
resp.append(proto.ButtonRequest(code=proto.ButtonRequestType.ConfirmOutput))
resp += [
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.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.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.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),
]
return resp
@ -168,44 +256,56 @@ class TestMultisigChange(TrezorTest):
self.setup_mnemonic_nopin_nopassphrase()
out1 = proto.TxOutputType(
address='muevUcG1Bb8eM2nGUGhqmeujHRX7YXjSEu',
address="muevUcG1Bb8eM2nGUGhqmeujHRX7YXjSEu",
amount=40000000,
script_type=proto.OutputScriptType.PAYTOADDRESS
script_type=proto.OutputScriptType.PAYTOADDRESS,
)
out2 = proto.TxOutputType(
address='mwdrpMVSJxxsM8f8xbnCHn9ERaRT1NG1UX',
address="mwdrpMVSJxxsM8f8xbnCHn9ERaRT1NG1UX",
amount=44000000,
script_type=proto.OutputScriptType.PAYTOADDRESS
script_type=proto.OutputScriptType.PAYTOADDRESS,
)
with self.client:
self.client.set_expected_responses(self._responses(self.inp1, self.inp2))
(_, serialized_tx) = self.client.sign_tx('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
def test_external_internal(self):
self.setup_mnemonic_nopin_nopassphrase()
out1 = proto.TxOutputType(
address='muevUcG1Bb8eM2nGUGhqmeujHRX7YXjSEu',
address="muevUcG1Bb8eM2nGUGhqmeujHRX7YXjSEu",
amount=40000000,
script_type=proto.OutputScriptType.PAYTOADDRESS
script_type=proto.OutputScriptType.PAYTOADDRESS,
)
out2 = proto.TxOutputType(
address_n=parse_path("45'/0/1/1"),
amount=44000000,
script_type=proto.OutputScriptType.PAYTOADDRESS
script_type=proto.OutputScriptType.PAYTOADDRESS,
)
with self.client:
self.client.set_expected_responses(self._responses(self.inp1, self.inp2, change=2))
(_, serialized_tx) = self.client.sign_tx('Testnet', [self.inp1, self.inp2, ], [out1, out2, ])
self.client.set_expected_responses(
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
def test_internal_external(self):
@ -214,42 +314,54 @@ class TestMultisigChange(TrezorTest):
out1 = proto.TxOutputType(
address_n=parse_path("45'/0/1/0"),
amount=40000000,
script_type=proto.OutputScriptType.PAYTOADDRESS
script_type=proto.OutputScriptType.PAYTOADDRESS,
)
out2 = proto.TxOutputType(
address='mwdrpMVSJxxsM8f8xbnCHn9ERaRT1NG1UX',
address="mwdrpMVSJxxsM8f8xbnCHn9ERaRT1NG1UX",
amount=44000000,
script_type=proto.OutputScriptType.PAYTOADDRESS
script_type=proto.OutputScriptType.PAYTOADDRESS,
)
with self.client:
self.client.set_expected_responses(self._responses(self.inp1, self.inp2, change=1))
(_, serialized_tx) = self.client.sign_tx('Testnet', [self.inp1, self.inp2, ], [out1, out2, ])
self.client.set_expected_responses(
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
def test_multisig_external_external(self):
self.setup_mnemonic_nopin_nopassphrase()
out1 = proto.TxOutputType(
address='2N2aFoogGntQFFwdUVPfRmutXD22ThcNTsR',
address="2N2aFoogGntQFFwdUVPfRmutXD22ThcNTsR",
amount=40000000,
script_type=proto.OutputScriptType.PAYTOADDRESS
script_type=proto.OutputScriptType.PAYTOADDRESS,
)
out2 = proto.TxOutputType(
address='2NFJjQcU8mw4Z3ywpbek8HL1VoJ27GDrkHw',
address="2NFJjQcU8mw4Z3ywpbek8HL1VoJ27GDrkHw",
amount=44000000,
script_type=proto.OutputScriptType.PAYTOADDRESS
script_type=proto.OutputScriptType.PAYTOADDRESS,
)
with self.client:
self.client.set_expected_responses(self._responses(self.inp1, self.inp2))
(_, serialized_tx) = self.client.sign_tx('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)
def test_multisig_change_match_first(self):
@ -259,30 +371,37 @@ class TestMultisigChange(TrezorTest):
pubkeys=[
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_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,
)
out1 = proto.TxOutputType(
address_n=[0x80000000 | 45, 0, 1, 0],
address_n=[H_(45), 0, 1, 0],
multisig=multisig_out1,
amount=40000000,
script_type=proto.OutputScriptType.PAYTOMULTISIG
script_type=proto.OutputScriptType.PAYTOMULTISIG,
)
out2 = proto.TxOutputType(
address='2NFJjQcU8mw4Z3ywpbek8HL1VoJ27GDrkHw',
address="2NFJjQcU8mw4Z3ywpbek8HL1VoJ27GDrkHw",
amount=44000000,
script_type=proto.OutputScriptType.PAYTOADDRESS
script_type=proto.OutputScriptType.PAYTOADDRESS,
)
with self.client:
self.client.set_expected_responses(self._responses(self.inp1, self.inp2, change=1))
(_, serialized_tx) = self.client.sign_tx('Testnet', [self.inp1, self.inp2, ], [out1, out2, ])
self.client.set_expected_responses(
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)
def test_multisig_change_match_second(self):
@ -292,30 +411,37 @@ class TestMultisigChange(TrezorTest):
pubkeys=[
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_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,
)
out1 = proto.TxOutputType(
address='2N2aFoogGntQFFwdUVPfRmutXD22ThcNTsR',
address="2N2aFoogGntQFFwdUVPfRmutXD22ThcNTsR",
amount=40000000,
script_type=proto.OutputScriptType.PAYTOADDRESS
script_type=proto.OutputScriptType.PAYTOADDRESS,
)
out2 = proto.TxOutputType(
address_n=[0x80000000 | 45, 0, 1, 1],
address_n=[H_(45), 0, 1, 1],
multisig=multisig_out2,
amount=44000000,
script_type=proto.OutputScriptType.PAYTOMULTISIG
script_type=proto.OutputScriptType.PAYTOMULTISIG,
)
with self.client:
self.client.set_expected_responses(self._responses(self.inp1, self.inp2, change=2))
(_, serialized_tx) = self.client.sign_tx('Testnet', [self.inp1, self.inp2, ], [out1, out2, ])
self.client.set_expected_responses(
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)
def test_multisig_mismatch_change(self):
@ -325,30 +451,35 @@ class TestMultisigChange(TrezorTest):
pubkeys=[
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_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,
)
out1 = proto.TxOutputType(
address='2N2aFoogGntQFFwdUVPfRmutXD22ThcNTsR',
address="2N2aFoogGntQFFwdUVPfRmutXD22ThcNTsR",
amount=40000000,
script_type=proto.OutputScriptType.PAYTOADDRESS
script_type=proto.OutputScriptType.PAYTOADDRESS,
)
out2 = proto.TxOutputType(
address_n=[0x80000000 | 45, 0, 1, 0],
address_n=[H_(45), 0, 1, 0],
multisig=multisig_out2,
amount=44000000,
script_type=proto.OutputScriptType.PAYTOMULTISIG
script_type=proto.OutputScriptType.PAYTOMULTISIG,
)
with self.client:
self.client.set_expected_responses(self._responses(self.inp1, self.inp2))
(_, serialized_tx) = self.client.sign_tx('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
def test_multisig_mismatch_inputs(self):
@ -358,27 +489,32 @@ class TestMultisigChange(TrezorTest):
pubkeys=[
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_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,
)
out1 = proto.TxOutputType(
address_n=[0x80000000 | 45, 0, 1, 0],
address_n=[H_(45), 0, 1, 0],
multisig=multisig_out1,
amount=40000000,
script_type=proto.OutputScriptType.PAYTOMULTISIG
script_type=proto.OutputScriptType.PAYTOMULTISIG,
)
out2 = proto.TxOutputType(
address='2NFJjQcU8mw4Z3ywpbek8HL1VoJ27GDrkHw',
address="2NFJjQcU8mw4Z3ywpbek8HL1VoJ27GDrkHw",
amount=65000000,
script_type=proto.OutputScriptType.PAYTOADDRESS
script_type=proto.OutputScriptType.PAYTOADDRESS,
)
with self.client:
self.client.set_expected_responses(self._responses(self.inp1, self.inp3))
(_, serialized_tx) = self.client.sign_tx('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"
)

@ -14,20 +14,22 @@
# 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>.
from binascii import unhexlify, hexlify
from binascii import hexlify, unhexlify
import pytest
from trezorlib import btc, messages as proto
from trezorlib.tools import CallException
from .common import TrezorTest
from .conftest import TREZOR_VERSION
from trezorlib import messages as proto
from trezorlib.client import CallException
TXHASH_d5f65e = unhexlify('d5f65ee80147b4bcc70b75e4bbf2d7382021b871bd8867ef8fa525ef50864882')
TXHASH_d5f65e = unhexlify(
"d5f65ee80147b4bcc70b75e4bbf2d7382021b871bd8867ef8fa525ef50864882"
)
class TestOpReturn(TrezorTest):
def test_opreturn(self):
self.setup_mnemonic_nopin_nopassphrase()
@ -42,39 +44,88 @@ class TestOpReturn(TrezorTest):
)
out1 = proto.TxOutputType(
address='1MJ2tj2ThBE62zXbBYA5ZaN3fdve5CPAz1',
address="1MJ2tj2ThBE62zXbBYA5ZaN3fdve5CPAz1",
amount=390000 - 10000,
script_type=proto.OutputScriptType.PAYTOADDRESS,
)
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,
script_type=proto.OutputScriptType.PAYTOOPRETURN,
)
with self.client:
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(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.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) = self.client.sign_tx('Bitcoin', [inp1, ], [out1, out2])
assert hexlify(serialized_tx) == b'010000000182488650ef25a58fef6788bd71b8212038d7f2bbe4750bc7bcb44701e85ef6d5000000006a4730440220187b7b9c340a32fc8445418ad11fb3827d2e8bac7d730e1c9ad800353e7ba62f02206c0c5820ba8882c82923a39aee8d36d6d32e13daed73f7a3d6199de5f8e7ddfd0121023230848585885f63803a0a8aecdd6538792d5c539215c91698e315bf0253b43dffffffff0260cc0500000000001976a914de9b2a8da088824e8fe51debea566617d851537888ac00000000000000001c6a1a74657374206f6620746865206f705f72657475726e206461746100000000'
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(
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.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"
)
def test_nonzero_opreturn(self):
self.setup_mnemonic_nopin_nopassphrase()
@ -90,28 +141,56 @@ class TestOpReturn(TrezorTest):
)
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,
script_type=proto.OutputScriptType.PAYTOOPRETURN,
)
with self.client:
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(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()
])
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(
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:
self.client.sign_tx('Bitcoin', [inp1], [out1])
btc.sign_tx(self.client, "Bitcoin", [inp1], [out1])
if TREZOR_VERSION == 1:
assert exc.value.args[0] == proto.FailureType.ProcessError
assert exc.value.args[1].endswith("Failed to compile output")
else:
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"
)

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

Loading…
Cancel
Save