mirror of
https://github.com/trezor/trezor-firmware.git
synced 2024-11-23 07:58:09 +00:00
Merge remote-tracking branch 'upstream/master' into stellar
This commit is contained in:
commit
200b5a71df
8
.flake8
8
.flake8
@ -1,17 +1,13 @@
|
||||
[flake8]
|
||||
filename =
|
||||
*.py,
|
||||
trezorctl
|
||||
./trezorctl
|
||||
exclude =
|
||||
.tox/,
|
||||
build/,
|
||||
dist/,
|
||||
trezorlib/*_pb2.py
|
||||
vendor/,
|
||||
ignore =
|
||||
# F821 undefined name 'unicode'
|
||||
F821,
|
||||
# F841 local variable is assigned to but never used
|
||||
F841,
|
||||
# F401: module imported but unused
|
||||
F401,
|
||||
# F403: used import *
|
||||
|
3
.gitignore
vendored
3
.gitignore
vendored
@ -14,3 +14,6 @@ docs/_build
|
||||
docs/.docs-build-environment
|
||||
.tox/
|
||||
.cache/
|
||||
.pytest_cache/
|
||||
|
||||
trezorlib/coins.json
|
||||
|
3
.gitmodules
vendored
Normal file
3
.gitmodules
vendored
Normal file
@ -0,0 +1,3 @@
|
||||
[submodule "vendor/trezor-common"]
|
||||
path = vendor/trezor-common
|
||||
url = https://github.com/trezor/trezor-common.git
|
14
.travis.yml
14
.travis.yml
@ -14,6 +14,10 @@ addons:
|
||||
- libudev-dev
|
||||
- libusb-1.0-0-dev
|
||||
|
||||
env:
|
||||
global:
|
||||
PROTOBUF_VERSION=3.4.0
|
||||
|
||||
python:
|
||||
- "3.3"
|
||||
- "3.4"
|
||||
@ -23,14 +27,20 @@ python:
|
||||
install:
|
||||
# Optimisation: build requirements as wheels, which get cached by Travis
|
||||
- pip install "pip>=7.0" wheel
|
||||
- pip install "setuptools>=19.0"
|
||||
- pip install "setuptools>=38"
|
||||
- pip install tox-travis
|
||||
- pip install flake8
|
||||
# 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}"
|
||||
|
||||
script:
|
||||
# check that generated protobuf messages are identical to in-tree ones
|
||||
- ./tools/build_protobuf messages.tmp && diff -ur messages.tmp trezorlib/messages && rm -r messages.tmp
|
||||
- python setup.py install
|
||||
- flake8
|
||||
- flake8 trezorctl
|
||||
- tox
|
||||
|
||||
notifications:
|
||||
|
@ -1,3 +1,6 @@
|
||||
recursive-include bash_completion.d *.sh
|
||||
include tools/*
|
||||
include trezorlib/tests/txcache/*.json
|
||||
include vendor/trezor-common/coins.json
|
||||
include vendor/trezor-common/protob/*.proto
|
||||
include COPYING
|
||||
|
20
README.rst
20
README.rst
@ -77,3 +77,23 @@ Example: your PIN is **1234** and TREZOR is displaying the following:
|
||||
=== === ===
|
||||
|
||||
You have to enter: **3795**
|
||||
|
||||
|
||||
Contributing
|
||||
------------
|
||||
|
||||
Python-trezor pulls coins info and protobuf messages from `trezor-common <https://github.com/trezor/trezor-common>`_ repository. If you are
|
||||
developing new features for Trezor, you will want to start there. Once your changes are accepted to ``trezor-common``, you can make a PR
|
||||
against this repository. Don't forget to update the submodule with:
|
||||
|
||||
.. code::
|
||||
|
||||
git submodule update --init --remote
|
||||
|
||||
Then, rebuild the protobuf messages and get ``coins.json`` by running:
|
||||
|
||||
.. code::
|
||||
|
||||
python3 setup.py prebuild
|
||||
|
||||
To get support for BTC-like coins, these steps are enough and no further changes to the library are necessary.
|
||||
|
52
setup.py
52
setup.py
@ -1,5 +1,10 @@
|
||||
#!/usr/bin/env python3
|
||||
from setuptools import setup
|
||||
import os.path
|
||||
import shutil
|
||||
import subprocess
|
||||
|
||||
from setuptools import setup, Command
|
||||
from setuptools.command.build_py import build_py
|
||||
|
||||
install_requires = [
|
||||
'setuptools>=19.0',
|
||||
@ -24,6 +29,44 @@ else:
|
||||
|
||||
from trezorlib import __version__ as VERSION
|
||||
|
||||
|
||||
class PrebuildCommand(Command):
|
||||
description = 'update vendored files (coins.json, protobuf messages)'
|
||||
user_options = []
|
||||
|
||||
TREZOR_COMMON = os.path.join('vendor', 'trezor-common')
|
||||
|
||||
def initialize_options(self):
|
||||
pass
|
||||
|
||||
def finalize_options(self):
|
||||
pass
|
||||
|
||||
def run(self):
|
||||
# check for existence of the submodule directory
|
||||
coins_json = os.path.join(self.TREZOR_COMMON, 'coins.json')
|
||||
if not os.path.exists(coins_json):
|
||||
raise Exception('trezor-common submodule seems to be missing.\n' +
|
||||
'Use "git submodule update --init" to retrieve it.')
|
||||
|
||||
# copy coins.json to the tree
|
||||
shutil.copy(coins_json, 'trezorlib')
|
||||
|
||||
# regenerate messages
|
||||
try:
|
||||
subprocess.check_call(os.path.join(os.getcwd(), 'tools', 'build_protobuf'))
|
||||
except Exception as e:
|
||||
print(e)
|
||||
print("Generating protobuf failed. Maybe you don't have 'protoc', or maybe you are on Windows?")
|
||||
print("Using pre-generated files.")
|
||||
|
||||
|
||||
class CustomBuild(build_py):
|
||||
def run(self):
|
||||
self.run_command('prebuild')
|
||||
super().run()
|
||||
|
||||
|
||||
setup(
|
||||
name='trezor',
|
||||
version=VERSION,
|
||||
@ -39,6 +82,9 @@ setup(
|
||||
'trezorlib.tests.device_tests',
|
||||
'trezorlib.tests.unit_tests',
|
||||
],
|
||||
package_data={
|
||||
'trezorlib': ['coins.json'],
|
||||
},
|
||||
scripts=['trezorctl'],
|
||||
install_requires=install_requires,
|
||||
python_requires='>=3.3',
|
||||
@ -51,4 +97,8 @@ setup(
|
||||
'Operating System :: MacOS :: MacOS X',
|
||||
'Programming Language :: Python :: 3 :: Only',
|
||||
],
|
||||
cmdclass={
|
||||
'prebuild': PrebuildCommand,
|
||||
'build_py': CustomBuild,
|
||||
},
|
||||
)
|
||||
|
@ -1,32 +1,52 @@
|
||||
#!/bin/bash
|
||||
set -e
|
||||
|
||||
if [ -n "$1" ]; then
|
||||
OUTDIR=`readlink -f "$1"`
|
||||
fi
|
||||
|
||||
cd "$(dirname "$0")"
|
||||
|
||||
GENPATH="../trezorlib/messages"
|
||||
INDEX="$GENPATH/__init__.py"
|
||||
PROTO_PATH="../../trezor-common/protob"
|
||||
# set up paths
|
||||
INDEX="__init__.py"
|
||||
GENPATH="${OUTDIR:-../trezorlib/messages}"
|
||||
PROTO_PATH="../vendor/trezor-common/protob"
|
||||
PROTO_FILES="types messages"
|
||||
PB2_OUT="pb2"
|
||||
|
||||
rm -f "$GENPATH/[A-Z]*.py"
|
||||
mkdir -p "$GENPATH"
|
||||
# set up temporary directory & cleanup
|
||||
TMPDIR=$(mktemp -d)
|
||||
function cleanup {
|
||||
rm -r $TMPDIR
|
||||
}
|
||||
trap cleanup EXIT
|
||||
|
||||
cat > "$INDEX" << EOF
|
||||
# set up pb2 outdir
|
||||
PB2_OUT="$TMPDIR/pb2"
|
||||
mkdir -p "$PB2_OUT"
|
||||
|
||||
# compile .proto files to python2 modules using google protobuf library
|
||||
for file in $PROTO_FILES; do
|
||||
protoc --python_out="$PB2_OUT" -I/usr/include -I"$PROTO_PATH" "$PROTO_PATH/$file.proto"
|
||||
done
|
||||
|
||||
# create index (__init__.py)
|
||||
cat > "$TMPDIR/$INDEX" << EOF
|
||||
# Automatically generated by pb2py
|
||||
|
||||
EOF
|
||||
|
||||
mkdir -p "$PB2_OUT"
|
||||
|
||||
# convert google protobuf library to trezor's internal format
|
||||
for file in $PROTO_FILES; do
|
||||
# Compile .proto files to python2 modules using google protobuf library
|
||||
protoc --python_out="$PB2_OUT" -I/usr/include -I"$PROTO_PATH" "$PROTO_PATH/$file.proto"
|
||||
./pb2py -P "trezorlib.protobuf" -p "$PB2_OUT" -l "$TMPDIR/$INDEX" "$file" "$TMPDIR"
|
||||
done
|
||||
|
||||
for file in $PROTO_FILES; do
|
||||
# Convert google protobuf library to trezor's internal format
|
||||
./pb2py -P "trezorlib.protobuf" -p "$PB2_OUT" -l "$INDEX" "$file" "$GENPATH"
|
||||
done
|
||||
# ensure $GENPATH exists and is empty of messages
|
||||
mkdir -p "$GENPATH"
|
||||
# only remove messages - there could possibly be other files not starting with capital letter
|
||||
rm -f "$GENPATH"/[A-Z]*.py
|
||||
|
||||
rm -rf "$PB2_OUT"
|
||||
# move generated files to the destination
|
||||
# (this assumes $INDEX is *.py, otherwise we'd have to add $INDEX separately)
|
||||
mv "$TMPDIR"/*.py "$GENPATH"
|
||||
|
||||
# the exit trap handles removing the tmp directory
|
||||
|
85
tools/deserialize_tx.py
Executable file
85
tools/deserialize_tx.py
Executable file
@ -0,0 +1,85 @@
|
||||
#!/usr/bin/env python3
|
||||
|
||||
import binascii
|
||||
import os
|
||||
import sys
|
||||
|
||||
try:
|
||||
import construct as c
|
||||
except ImportError:
|
||||
sys.stderr.write("This tool requires Construct. Install it with 'pip install Construct'.\n")
|
||||
sys.exit(1)
|
||||
|
||||
from construct import this, len_
|
||||
|
||||
if os.isatty(sys.stdin.fileno()):
|
||||
tx_hex = input("Enter transaction in hex format: ")
|
||||
else:
|
||||
tx_hex = sys.stdin.read().strip()
|
||||
|
||||
tx_bin = binascii.unhexlify(tx_hex)
|
||||
|
||||
|
||||
CompactUintStruct = c.Struct(
|
||||
"base" / c.Int8ul,
|
||||
"ext" / c.Switch(this.base, {0xfd: c.Int16ul, 0xfe: c.Int32ul, 0xff: c.Int64ul}),
|
||||
)
|
||||
|
||||
|
||||
class CompactUintAdapter(c.Adapter):
|
||||
def _encode(self, obj, context, path):
|
||||
if obj < 0xfd:
|
||||
return {"base": obj}
|
||||
if obj < 2 ** 16:
|
||||
return {"base": 0xfd, "ext": obj}
|
||||
if obj < 2 ** 32:
|
||||
return {"base": 0xfe, "ext": obj}
|
||||
if obj < 2 ** 64:
|
||||
return {"base": 0xff, "ext": obj}
|
||||
raise ValueError("Value too big for compact uint")
|
||||
|
||||
def _decode(self, obj, context, path):
|
||||
return obj["ext"] or obj["base"]
|
||||
|
||||
|
||||
class ConstFlag(c.Adapter):
|
||||
def __init__(self, const):
|
||||
self.const = const
|
||||
super().__init__(c.Optional(c.Const(const)))
|
||||
|
||||
def _encode(self, obj, context, path):
|
||||
return self.const if obj else None
|
||||
|
||||
def _decode(self, obj, context, path):
|
||||
return obj is not None
|
||||
|
||||
|
||||
CompactUint = CompactUintAdapter(CompactUintStruct)
|
||||
|
||||
TxInput = c.Struct(
|
||||
"tx" / c.Bytes(32),
|
||||
"index" / c.Int32ul,
|
||||
# TODO coinbase tx
|
||||
"script" / c.Prefixed(CompactUint, c.GreedyBytes),
|
||||
"sequence" / c.Int32ul,
|
||||
)
|
||||
|
||||
TxOutput = c.Struct(
|
||||
"value" / c.Int64ul,
|
||||
"pk_script" / c.Prefixed(CompactUint, c.GreedyBytes),
|
||||
)
|
||||
|
||||
StackItem = c.Prefixed(CompactUint, c.GreedyBytes)
|
||||
TxInputWitness = c.PrefixedArray(CompactUint, StackItem)
|
||||
|
||||
Transaction = c.Struct(
|
||||
"version" / c.Int32ul,
|
||||
"segwit" / ConstFlag(b"\x00\x01"),
|
||||
"inputs" / c.PrefixedArray(CompactUint, TxInput),
|
||||
"outputs" / c.PrefixedArray(CompactUint, TxOutput),
|
||||
"witness" / c.If(this.segwit, TxInputWitness[len_(this.inputs)]),
|
||||
"lock_time" / c.Int32ul,
|
||||
c.Terminated,
|
||||
)
|
||||
|
||||
print(Transaction.parse(tx_bin))
|
@ -102,9 +102,9 @@ def main():
|
||||
|
||||
data = {'label': label,
|
||||
'bip32_path': bip32_path,
|
||||
'password_encrypted_hex': binascii.hexlify(passw_encrypted)}
|
||||
'password_encrypted_hex': binascii.hexlify(passw_encrypted).decode('ascii')}
|
||||
|
||||
json.dump(data, open(passw_file, 'wb'))
|
||||
json.dump(data, open(passw_file, 'w'))
|
||||
|
||||
# Let's load password
|
||||
data = json.load(open(passw_file, 'r'))
|
||||
|
@ -111,7 +111,7 @@ class MyTxApiBitcoin(object):
|
||||
|
||||
txser = self.serialize_tx(t)
|
||||
txhash = tools.Hash(txser)[::-1]
|
||||
outi = self.inputs.append(
|
||||
self.inputs.append(
|
||||
proto_types.TxInputType(
|
||||
address_n=self.client.expand_path("44'/0'/0'/0/%d" % idx),
|
||||
script_type=(
|
||||
@ -178,42 +178,42 @@ def main():
|
||||
# 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',
|
||||
# ),
|
||||
]
|
||||
# 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())
|
||||
|
116
trezorctl
116
trezorctl
@ -30,9 +30,9 @@ import sys
|
||||
|
||||
from trezorlib.client import TrezorClient, TrezorClientVerbose, CallException, format_protobuf
|
||||
from trezorlib.transport import get_transport, enumerate_devices, TransportException
|
||||
from trezorlib import coins
|
||||
from trezorlib import messages as proto
|
||||
from trezorlib import protobuf
|
||||
from trezorlib.coins import coins_txapi
|
||||
from trezorlib.ckd_public import PRIME_DERIVATION_FLAG
|
||||
from trezorlib import stellar
|
||||
|
||||
@ -88,7 +88,7 @@ def cli(ctx, path, verbose, is_json):
|
||||
if path is not None:
|
||||
click.echo("Using path: {}".format(path))
|
||||
sys.exit(1)
|
||||
return cls(device)
|
||||
return cls(transport=device)
|
||||
|
||||
ctx.obj = get_device
|
||||
|
||||
@ -211,6 +211,23 @@ def set_passphrase_source(connect, source):
|
||||
return connect().apply_settings(passphrase_source=source)
|
||||
|
||||
|
||||
@cli.command(help='Set auto-lock delay (in seconds).')
|
||||
@click.argument('delay', type=str)
|
||||
@click.pass_obj
|
||||
def set_auto_lock_delay(connect, delay):
|
||||
value, unit = delay[:-1], delay[-1:]
|
||||
units = {
|
||||
's': 1,
|
||||
'm': 60,
|
||||
'h': 3600,
|
||||
}
|
||||
if unit in units:
|
||||
seconds = float(value) * units[unit]
|
||||
else:
|
||||
seconds = float(delay) # assume seconds if no unit is specified
|
||||
return connect().apply_settings(auto_lock_delay_ms=int(seconds * 1000))
|
||||
|
||||
|
||||
@cli.command(help='Set device flags.')
|
||||
@click.argument('flags')
|
||||
@click.pass_obj
|
||||
@ -234,7 +251,7 @@ def set_homescreen(connect, filename):
|
||||
elif filename.endswith('.toif'):
|
||||
img = open(filename, 'rb').read()
|
||||
if img[:8] != b'TOIf\x90\x00\x90\x00':
|
||||
raise CallException(types.Failure_DataError, 'File is not a TOIF file with size of 144x144')
|
||||
raise CallException(proto.FailureType.DataError, 'File is not a TOIF file with size of 144x144')
|
||||
else:
|
||||
from PIL import Image
|
||||
im = Image.open(filename)
|
||||
@ -471,11 +488,11 @@ def get_public_node(connect, coin, address, curve, show_display):
|
||||
@click.pass_obj
|
||||
def sign_tx(connect, coin):
|
||||
client = connect()
|
||||
if coin in coins_txapi:
|
||||
txapi = coins_txapi[coin]
|
||||
if coin in coins.tx_api:
|
||||
txapi = coins.tx_api[coin]
|
||||
else:
|
||||
click.echo('Coin "%s" is not recognized.' % coin, err=True)
|
||||
click.echo('Supported coin types: %s' % ', '.join(coins_txapi.keys()), err=True)
|
||||
click.echo('Supported coin types: %s' % ', '.join(coins.tx_api.keys()), err=True)
|
||||
sys.exit(1)
|
||||
|
||||
client.set_tx_api(txapi)
|
||||
@ -705,9 +722,10 @@ def ethereum_get_address(connect, address, show_display):
|
||||
@click.option('-i', '--nonce', type=int, help='Transaction counter - Required for offline signing')
|
||||
@click.option('-d', '--data', default='', help='Data as hex string, e.g. 0x12345678')
|
||||
@click.option('-p', '--publish', is_flag=True, help='Publish transaction via RPC')
|
||||
@click.option('-x', '--tx-type', type=int, help='TX type (used only for Wanchain)')
|
||||
@click.argument('to')
|
||||
@click.pass_obj
|
||||
def ethereum_sign_tx(connect, host, chain_id, address, value, gas_limit, gas_price, nonce, data, publish, to):
|
||||
def ethereum_sign_tx(connect, host, chain_id, address, value, gas_limit, gas_price, nonce, data, publish, to, tx_type):
|
||||
from ethjsonrpc import EthJsonRpc
|
||||
import rlp
|
||||
|
||||
@ -759,7 +777,7 @@ def ethereum_sign_tx(connect, host, chain_id, address, value, gas_limit, gas_pri
|
||||
address_n = client.expand_path(address)
|
||||
address = '0x%s' % (binascii.hexlify(client.ethereum_get_address(address_n)).decode())
|
||||
|
||||
if gas_price is None or gas_limit is None or nonce is None:
|
||||
if gas_price is None or gas_limit is None or nonce is None or publish:
|
||||
host, port = host.split(':')
|
||||
eth = EthJsonRpc(host, int(port))
|
||||
|
||||
@ -782,6 +800,7 @@ def ethereum_sign_tx(connect, host, chain_id, address, value, gas_limit, gas_pri
|
||||
|
||||
sig = client.ethereum_sign_tx(
|
||||
n=address_n,
|
||||
tx_type=tx_type,
|
||||
nonce=nonce,
|
||||
gas_price=gas_price,
|
||||
gas_limit=gas_limit,
|
||||
@ -790,8 +809,12 @@ def ethereum_sign_tx(connect, host, chain_id, address, value, gas_limit, gas_pri
|
||||
data=data,
|
||||
chain_id=chain_id)
|
||||
|
||||
transaction = rlp.encode(
|
||||
(nonce, gas_price, gas_limit, to_address, value, data) + sig)
|
||||
if tx_type is None:
|
||||
transaction = rlp.encode(
|
||||
(nonce, gas_price, gas_limit, to_address, value, data) + sig)
|
||||
else:
|
||||
transaction = rlp.encode(
|
||||
(tx_type, nonce, gas_price, gas_limit, to_address, value, data) + sig)
|
||||
tx_hex = '0x%s' % binascii.hexlify(transaction).decode()
|
||||
|
||||
if publish:
|
||||
@ -839,6 +862,79 @@ def nem_sign_tx(connect, address, file, broadcast):
|
||||
return payload
|
||||
|
||||
|
||||
#
|
||||
# Lisk functions
|
||||
#
|
||||
|
||||
|
||||
@cli.command(help='Get Lisk address for specified path.')
|
||||
@click.option('-n', '--address', required=True, help="BIP-32 path, e.g. m/44'/134'/0'/0'")
|
||||
@click.option('-d', '--show-display', is_flag=True)
|
||||
@click.pass_obj
|
||||
def lisk_get_address(connect, address, show_display):
|
||||
client = connect()
|
||||
address_n = client.expand_path(address)
|
||||
return client.lisk_get_address(address_n, show_display)
|
||||
|
||||
|
||||
@cli.command(help='Get Lisk public key for specified path.')
|
||||
@click.option('-n', '--address', required=True, help="BIP-32 path, e.g. m/44'/134'/0'/0'")
|
||||
@click.option('-d', '--show-display', is_flag=True)
|
||||
@click.pass_obj
|
||||
def lisk_get_public_key(connect, address, show_display):
|
||||
client = connect()
|
||||
address_n = client.expand_path(address)
|
||||
res = client.lisk_get_public_key(address_n, show_display)
|
||||
output = {
|
||||
"public_key": binascii.hexlify(res.public_key).decode()
|
||||
}
|
||||
return output
|
||||
|
||||
|
||||
@cli.command(help='Sign message with Lisk address.')
|
||||
@click.option('-n', '--address', required=True, help="BIP-32 path, e.g. m/44'/134'/0'/0'")
|
||||
@click.argument('message')
|
||||
@click.pass_obj
|
||||
def lisk_sign_message(connect, address, message):
|
||||
client = connect()
|
||||
address_n = client.expand_path(address)
|
||||
res = client.lisk_sign_message(address_n, message)
|
||||
output = {
|
||||
'message': message,
|
||||
'address': res.address,
|
||||
'signature': binascii.hexlify(res.signature).decode()
|
||||
}
|
||||
return output
|
||||
|
||||
|
||||
@cli.command(help='Verify message signed with Lisk address.')
|
||||
@click.argument('pubkey')
|
||||
@click.argument('signature')
|
||||
@click.argument('message')
|
||||
@click.pass_obj
|
||||
def lisk_verify_message(connect, pubkey, signature, message):
|
||||
signature = bytes.fromhex(signature)
|
||||
pubkey = bytes.fromhex(pubkey)
|
||||
return connect().lisk_verify_message(pubkey, signature, message)
|
||||
|
||||
|
||||
@cli.command(help='Sign Lisk transaction.')
|
||||
@click.option('-n', '--address', required=True, help="BIP-32 path to signing key, e.g. m/44'/134'/0'/0'")
|
||||
@click.option('-f', '--file', type=click.File('r'), default='-', help='Transaction in JSON format')
|
||||
# @click.option('-b', '--broadcast', help='Broadcast Lisk transaction')
|
||||
@click.pass_obj
|
||||
def lisk_sign_tx(connect, address, file):
|
||||
client = connect()
|
||||
address_n = client.expand_path(address)
|
||||
transaction = client.lisk_sign_tx(address_n, json.load(file))
|
||||
|
||||
payload = {
|
||||
"signature": binascii.hexlify(transaction.signature).decode()
|
||||
}
|
||||
|
||||
return payload
|
||||
|
||||
|
||||
#
|
||||
# CoSi functions
|
||||
#
|
||||
|
@ -34,8 +34,8 @@ from . import messages as proto
|
||||
from . import tools
|
||||
from . import mapping
|
||||
from . import nem
|
||||
from .coins import slip44
|
||||
from . import stellar
|
||||
from .coins import coins_slip44
|
||||
from .debuglink import DebugLink
|
||||
from .protobuf import MessageType
|
||||
|
||||
@ -43,11 +43,6 @@ from .protobuf import MessageType
|
||||
if sys.version_info.major < 3:
|
||||
raise Exception("Trezorlib does not support Python 2 anymore.")
|
||||
|
||||
# try:
|
||||
# from PIL import Image
|
||||
# SCREENSHOT = True
|
||||
# except:
|
||||
# SCREENSHOT = False
|
||||
|
||||
SCREENSHOT = False
|
||||
|
||||
@ -425,6 +420,7 @@ class DebugLinkMixin(object):
|
||||
def call_raw(self, msg):
|
||||
|
||||
if SCREENSHOT and self.debug:
|
||||
from PIL import Image
|
||||
layout = self.debug.read_layout()
|
||||
im = Image.new("RGB", (128, 64))
|
||||
pix = im.load()
|
||||
@ -497,8 +493,9 @@ class ProtocolMixin(object):
|
||||
PRIME_DERIVATION_FLAG = 0x80000000
|
||||
VENDORS = ('bitcointrezor.com', 'trezor.io')
|
||||
|
||||
def __init__(self, *args, **kwargs):
|
||||
def __init__(self, state=None, *args, **kwargs):
|
||||
super(ProtocolMixin, self).__init__(*args, **kwargs)
|
||||
self.state = state
|
||||
self.init_device()
|
||||
self.tx_api = None
|
||||
|
||||
@ -506,7 +503,10 @@ class ProtocolMixin(object):
|
||||
self.tx_api = tx_api
|
||||
|
||||
def init_device(self):
|
||||
self.features = expect(proto.Features)(self.call)(proto.Initialize())
|
||||
init_msg = proto.Initialize()
|
||||
if self.state is not None:
|
||||
init_msg.state = self.state
|
||||
self.features = expect(proto.Features)(self.call)(init_msg)
|
||||
if str(self.features.vendor) not in self.VENDORS:
|
||||
raise RuntimeError("Unsupported device")
|
||||
|
||||
@ -531,8 +531,8 @@ class ProtocolMixin(object):
|
||||
n = n[1:]
|
||||
|
||||
# coin_name/a/b/c => 44'/SLIP44_constant'/a/b/c
|
||||
if n[0] in coins_slip44:
|
||||
n = ["44'", "%d'" % coins_slip44[n[0]]] + n[1:]
|
||||
if n[0] in slip44:
|
||||
n = ["44'", "%d'" % slip44[n[0]]] + n[1:]
|
||||
|
||||
path = []
|
||||
for x in n:
|
||||
@ -573,7 +573,7 @@ class ProtocolMixin(object):
|
||||
return self.call(proto.EthereumGetAddress(address_n=n, show_display=show_display))
|
||||
|
||||
@session
|
||||
def ethereum_sign_tx(self, n, nonce, gas_price, gas_limit, to, value, data=None, chain_id=None):
|
||||
def ethereum_sign_tx(self, n, nonce, gas_price, gas_limit, to, value, data=None, chain_id=None, tx_type=None):
|
||||
def int_to_big_endian(value):
|
||||
import rlp.utils
|
||||
if value == 0:
|
||||
@ -600,6 +600,9 @@ class ProtocolMixin(object):
|
||||
if chain_id:
|
||||
msg.chain_id = chain_id
|
||||
|
||||
if tx_type is not None:
|
||||
msg.tx_type = tx_type
|
||||
|
||||
response = self.call(msg)
|
||||
|
||||
while response.data_length is not None:
|
||||
@ -625,6 +628,78 @@ class ProtocolMixin(object):
|
||||
return True
|
||||
return False
|
||||
|
||||
#
|
||||
# Lisk functions
|
||||
#
|
||||
|
||||
@field('address')
|
||||
@expect(proto.LiskAddress)
|
||||
def lisk_get_address(self, n, show_display=False):
|
||||
n = self._convert_prime(n)
|
||||
return self.call(proto.LiskGetAddress(address_n=n, show_display=show_display))
|
||||
|
||||
@expect(proto.LiskPublicKey)
|
||||
def lisk_get_public_key(self, n, show_display=False):
|
||||
n = self._convert_prime(n)
|
||||
return self.call(proto.LiskGetPublicKey(address_n=n, show_display=show_display))
|
||||
|
||||
@expect(proto.LiskMessageSignature)
|
||||
def lisk_sign_message(self, n, message):
|
||||
n = self._convert_prime(n)
|
||||
message = normalize_nfc(message)
|
||||
return self.call(proto.LiskSignMessage(address_n=n, message=message))
|
||||
|
||||
def lisk_verify_message(self, pubkey, signature, message):
|
||||
message = normalize_nfc(message)
|
||||
try:
|
||||
resp = self.call(proto.LiskVerifyMessage(signature=signature, public_key=pubkey, message=message))
|
||||
except CallException as e:
|
||||
resp = e
|
||||
return isinstance(resp, proto.Success)
|
||||
|
||||
@expect(proto.LiskSignedTx)
|
||||
def lisk_sign_tx(self, n, transaction):
|
||||
n = self._convert_prime(n)
|
||||
|
||||
def asset_to_proto(asset):
|
||||
msg = proto.LiskTransactionAsset()
|
||||
|
||||
if "votes" in asset:
|
||||
msg.votes = asset["votes"]
|
||||
if "data" in asset:
|
||||
msg.data = asset["data"]
|
||||
if "signature" in asset:
|
||||
msg.signature = proto.LiskSignatureType()
|
||||
msg.signature.public_key = binascii.unhexlify(asset["signature"]["publicKey"])
|
||||
if "delegate" in asset:
|
||||
msg.delegate = proto.LiskDelegateType()
|
||||
msg.delegate.username = asset["delegate"]["username"]
|
||||
if "multisignature" in asset:
|
||||
msg.multisignature = proto.LiskMultisignatureType()
|
||||
msg.multisignature.min = asset["multisignature"]["min"]
|
||||
msg.multisignature.life_time = asset["multisignature"]["lifetime"]
|
||||
msg.multisignature.keys_group = asset["multisignature"]["keysgroup"]
|
||||
return msg
|
||||
|
||||
msg = proto.LiskTransactionCommon()
|
||||
|
||||
msg.type = transaction["type"]
|
||||
msg.fee = int(transaction["fee"]) # Lisk use strings for big numbers (javascript issue)
|
||||
msg.amount = int(transaction["amount"]) # And we convert it back to number
|
||||
msg.timestamp = transaction["timestamp"]
|
||||
|
||||
if "recipientId" in transaction:
|
||||
msg.recipient_id = transaction["recipientId"]
|
||||
if "senderPublicKey" in transaction:
|
||||
msg.sender_public_key = binascii.unhexlify(transaction["senderPublicKey"])
|
||||
if "requesterPublicKey" in transaction:
|
||||
msg.requester_public_key = binascii.unhexlify(transaction["requesterPublicKey"])
|
||||
if "signature" in transaction:
|
||||
msg.signature = binascii.unhexlify(transaction["signature"])
|
||||
|
||||
msg.asset = asset_to_proto(transaction["asset"])
|
||||
return self.call(proto.LiskSignTx(address_n=n, transaction=msg))
|
||||
|
||||
@field('entropy')
|
||||
@expect(proto.Entropy)
|
||||
def get_entropy(self, size):
|
||||
@ -644,7 +719,7 @@ class ProtocolMixin(object):
|
||||
|
||||
@field('message')
|
||||
@expect(proto.Success)
|
||||
def apply_settings(self, label=None, language=None, use_passphrase=None, homescreen=None, passphrase_source=None):
|
||||
def apply_settings(self, 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
|
||||
@ -656,6 +731,8 @@ class ProtocolMixin(object):
|
||||
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 = self.call(settings)
|
||||
self.init_device() # Reload Features
|
||||
@ -801,7 +878,7 @@ class ProtocolMixin(object):
|
||||
@session
|
||||
def sign_tx(self, coin_name, inputs, outputs, version=None, lock_time=None, debug_processor=None):
|
||||
|
||||
start = time.time()
|
||||
# start = time.time()
|
||||
txes = self._prepare_sign_tx(inputs, outputs)
|
||||
|
||||
# Prepare and send initial message
|
||||
@ -1151,12 +1228,15 @@ class ProtocolMixin(object):
|
||||
|
||||
|
||||
class TrezorClient(ProtocolMixin, TextUIMixin, BaseClient):
|
||||
pass
|
||||
def __init__(self, transport, *args, **kwargs):
|
||||
super().__init__(transport=transport, *args, **kwargs)
|
||||
|
||||
|
||||
class TrezorClientVerbose(ProtocolMixin, TextUIMixin, VerboseWireMixin, BaseClient):
|
||||
pass
|
||||
def __init__(self, transport, *args, **kwargs):
|
||||
super().__init__(transport=transport, *args, **kwargs)
|
||||
|
||||
|
||||
class TrezorClientDebugLink(ProtocolMixin, DebugLinkMixin, VerboseWireMixin, BaseClient):
|
||||
pass
|
||||
def __init__(self, transport, *args, **kwargs):
|
||||
super().__init__(transport=transport, *args, **kwargs)
|
||||
|
@ -1,31 +1,45 @@
|
||||
from .tx_api import TxApiBitcoin, TxApiTestnet, TxApiLitecoin, TxApiZcash, TxApiDash, TxApiBcash, TxApiDecredTestnet, TxApiDogecoin, TxApiMonacoin, TxApiBitcoinGold
|
||||
import os.path
|
||||
import json
|
||||
|
||||
coins_slip44 = {
|
||||
'Bitcoin': 0,
|
||||
'Testnet': 1,
|
||||
'Decred Testnet': 1,
|
||||
'Litecoin': 2,
|
||||
'Dogecoin': 3,
|
||||
'Dash': 5,
|
||||
'Namecoin': 7,
|
||||
'Monacoin': 22,
|
||||
'Decred': 42,
|
||||
'Ether': 60,
|
||||
'EtherClassic': 61,
|
||||
'Zcash': 133,
|
||||
'Bcash': 145,
|
||||
'Bitcoin Gold': 156,
|
||||
}
|
||||
from .tx_api import TxApiInsight, TxApiBlockCypher
|
||||
|
||||
coins_txapi = {
|
||||
'Bitcoin': TxApiBitcoin,
|
||||
'Testnet': TxApiTestnet,
|
||||
'Litecoin': TxApiLitecoin,
|
||||
'Dash': TxApiDash,
|
||||
'Zcash': TxApiZcash,
|
||||
'Bcash': TxApiBcash,
|
||||
'Decred Testnet': TxApiDecredTestnet,
|
||||
'Dogecoin': TxApiDogecoin,
|
||||
'Monacoin': TxApiMonacoin,
|
||||
'Bitcoin Gold': TxApiBitcoinGold,
|
||||
}
|
||||
COINS_JSON = os.path.join(os.path.dirname(__file__), 'coins.json')
|
||||
|
||||
|
||||
def _load_coins_json():
|
||||
# Load coins.json to local variables
|
||||
# NOTE: coins.json comes from 'vendor/trezor-common/coins.json',
|
||||
# which is a git submodule. If you're trying to run trezorlib directly
|
||||
# from the checkout (or tarball), initialize the submodule with:
|
||||
# $ git submodule update --init
|
||||
# and install coins.json with:
|
||||
# $ python setup.py prebuild
|
||||
with open(COINS_JSON) as coins_json:
|
||||
coins_list = json.load(coins_json)
|
||||
return {coin['coin_name']: coin for coin in coins_list}
|
||||
|
||||
|
||||
def _insight_for_coin(coin):
|
||||
if not coin['bitcore']:
|
||||
return None
|
||||
zcash = coin['coin_name'].lower().startswith('zcash')
|
||||
network = 'insight_{}'.format(coin['coin_name'].lower().replace(' ', '_'))
|
||||
url = coin['bitcore'][0] + 'api/'
|
||||
return TxApiInsight(network=network, url=url, zcash=zcash)
|
||||
|
||||
|
||||
# exported variables
|
||||
__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['bip44'] for name, coin in by_name.items()}
|
||||
tx_api = {name: _insight_for_coin(coin)
|
||||
for name, coin in by_name.items()
|
||||
if coin["bitcore"]}
|
||||
|
||||
# fixup for Dogecoin
|
||||
tx_api['Dogecoin'] = TxApiBlockCypher(network='blockcypher_dogecoin', url='https://api.blockcypher.com/v1/doge/main/')
|
||||
|
9
trezorlib/messages/LiskAddress.py
Normal file
9
trezorlib/messages/LiskAddress.py
Normal file
@ -0,0 +1,9 @@
|
||||
# Automatically generated by pb2py
|
||||
from .. import protobuf as p
|
||||
|
||||
|
||||
class LiskAddress(p.MessageType):
|
||||
FIELDS = {
|
||||
1: ('address', p.UnicodeType, 0),
|
||||
}
|
||||
MESSAGE_WIRE_TYPE = 115
|
8
trezorlib/messages/LiskDelegateType.py
Normal file
8
trezorlib/messages/LiskDelegateType.py
Normal file
@ -0,0 +1,8 @@
|
||||
# Automatically generated by pb2py
|
||||
from .. import protobuf as p
|
||||
|
||||
|
||||
class LiskDelegateType(p.MessageType):
|
||||
FIELDS = {
|
||||
1: ('username', p.UnicodeType, 0),
|
||||
}
|
10
trezorlib/messages/LiskGetAddress.py
Normal file
10
trezorlib/messages/LiskGetAddress.py
Normal file
@ -0,0 +1,10 @@
|
||||
# Automatically generated by pb2py
|
||||
from .. import protobuf as p
|
||||
|
||||
|
||||
class LiskGetAddress(p.MessageType):
|
||||
FIELDS = {
|
||||
1: ('address_n', p.UVarintType, p.FLAG_REPEATED),
|
||||
2: ('show_display', p.BoolType, 0),
|
||||
}
|
||||
MESSAGE_WIRE_TYPE = 114
|
10
trezorlib/messages/LiskGetPublicKey.py
Normal file
10
trezorlib/messages/LiskGetPublicKey.py
Normal file
@ -0,0 +1,10 @@
|
||||
# Automatically generated by pb2py
|
||||
from .. import protobuf as p
|
||||
|
||||
|
||||
class LiskGetPublicKey(p.MessageType):
|
||||
FIELDS = {
|
||||
1: ('address_n', p.UVarintType, p.FLAG_REPEATED),
|
||||
2: ('show_display', p.BoolType, 0),
|
||||
}
|
||||
MESSAGE_WIRE_TYPE = 121
|
10
trezorlib/messages/LiskMessageSignature.py
Normal file
10
trezorlib/messages/LiskMessageSignature.py
Normal file
@ -0,0 +1,10 @@
|
||||
# Automatically generated by pb2py
|
||||
from .. import protobuf as p
|
||||
|
||||
|
||||
class LiskMessageSignature(p.MessageType):
|
||||
FIELDS = {
|
||||
1: ('address', p.UnicodeType, 0),
|
||||
2: ('signature', p.BytesType, 0),
|
||||
}
|
||||
MESSAGE_WIRE_TYPE = 119
|
10
trezorlib/messages/LiskMultisignatureType.py
Normal file
10
trezorlib/messages/LiskMultisignatureType.py
Normal file
@ -0,0 +1,10 @@
|
||||
# Automatically generated by pb2py
|
||||
from .. import protobuf as p
|
||||
|
||||
|
||||
class LiskMultisignatureType(p.MessageType):
|
||||
FIELDS = {
|
||||
1: ('min', p.UVarintType, 0),
|
||||
2: ('life_time', p.UVarintType, 0),
|
||||
3: ('keys_group', p.UnicodeType, p.FLAG_REPEATED),
|
||||
}
|
9
trezorlib/messages/LiskPublicKey.py
Normal file
9
trezorlib/messages/LiskPublicKey.py
Normal file
@ -0,0 +1,9 @@
|
||||
# Automatically generated by pb2py
|
||||
from .. import protobuf as p
|
||||
|
||||
|
||||
class LiskPublicKey(p.MessageType):
|
||||
FIELDS = {
|
||||
1: ('public_key', p.BytesType, 0),
|
||||
}
|
||||
MESSAGE_WIRE_TYPE = 122
|
10
trezorlib/messages/LiskSignMessage.py
Normal file
10
trezorlib/messages/LiskSignMessage.py
Normal file
@ -0,0 +1,10 @@
|
||||
# Automatically generated by pb2py
|
||||
from .. import protobuf as p
|
||||
|
||||
|
||||
class LiskSignMessage(p.MessageType):
|
||||
FIELDS = {
|
||||
1: ('address_n', p.UVarintType, p.FLAG_REPEATED),
|
||||
2: ('message', p.BytesType, 0),
|
||||
}
|
||||
MESSAGE_WIRE_TYPE = 118
|
11
trezorlib/messages/LiskSignTx.py
Normal file
11
trezorlib/messages/LiskSignTx.py
Normal file
@ -0,0 +1,11 @@
|
||||
# Automatically generated by pb2py
|
||||
from .. import protobuf as p
|
||||
from .LiskTransactionCommon import LiskTransactionCommon
|
||||
|
||||
|
||||
class LiskSignTx(p.MessageType):
|
||||
FIELDS = {
|
||||
1: ('address_n', p.UVarintType, p.FLAG_REPEATED),
|
||||
2: ('transaction', LiskTransactionCommon, 0),
|
||||
}
|
||||
MESSAGE_WIRE_TYPE = 116
|
8
trezorlib/messages/LiskSignatureType.py
Normal file
8
trezorlib/messages/LiskSignatureType.py
Normal file
@ -0,0 +1,8 @@
|
||||
# Automatically generated by pb2py
|
||||
from .. import protobuf as p
|
||||
|
||||
|
||||
class LiskSignatureType(p.MessageType):
|
||||
FIELDS = {
|
||||
1: ('public_key', p.BytesType, 0),
|
||||
}
|
9
trezorlib/messages/LiskSignedTx.py
Normal file
9
trezorlib/messages/LiskSignedTx.py
Normal file
@ -0,0 +1,9 @@
|
||||
# Automatically generated by pb2py
|
||||
from .. import protobuf as p
|
||||
|
||||
|
||||
class LiskSignedTx(p.MessageType):
|
||||
FIELDS = {
|
||||
1: ('signature', p.BytesType, 0),
|
||||
}
|
||||
MESSAGE_WIRE_TYPE = 117
|
15
trezorlib/messages/LiskTransactionAsset.py
Normal file
15
trezorlib/messages/LiskTransactionAsset.py
Normal file
@ -0,0 +1,15 @@
|
||||
# Automatically generated by pb2py
|
||||
from .. import protobuf as p
|
||||
from .LiskDelegateType import LiskDelegateType
|
||||
from .LiskMultisignatureType import LiskMultisignatureType
|
||||
from .LiskSignatureType import LiskSignatureType
|
||||
|
||||
|
||||
class LiskTransactionAsset(p.MessageType):
|
||||
FIELDS = {
|
||||
1: ('signature', LiskSignatureType, 0),
|
||||
2: ('delegate', LiskDelegateType, 0),
|
||||
3: ('votes', p.UnicodeType, p.FLAG_REPEATED),
|
||||
4: ('multisignature', LiskMultisignatureType, 0),
|
||||
5: ('data', p.UnicodeType, 0),
|
||||
}
|
17
trezorlib/messages/LiskTransactionCommon.py
Normal file
17
trezorlib/messages/LiskTransactionCommon.py
Normal file
@ -0,0 +1,17 @@
|
||||
# Automatically generated by pb2py
|
||||
from .. import protobuf as p
|
||||
from .LiskTransactionAsset import LiskTransactionAsset
|
||||
|
||||
|
||||
class LiskTransactionCommon(p.MessageType):
|
||||
FIELDS = {
|
||||
1: ('type', p.UVarintType, 0),
|
||||
2: ('amount', p.UVarintType, 0), # default=0
|
||||
3: ('fee', p.UVarintType, 0),
|
||||
4: ('recipient_id', p.UnicodeType, 0),
|
||||
5: ('sender_public_key', p.BytesType, 0),
|
||||
6: ('requester_public_key', p.BytesType, 0),
|
||||
7: ('signature', p.BytesType, 0),
|
||||
8: ('timestamp', p.UVarintType, 0),
|
||||
9: ('asset', LiskTransactionAsset, 0),
|
||||
}
|
9
trezorlib/messages/LiskTransactionType.py
Normal file
9
trezorlib/messages/LiskTransactionType.py
Normal file
@ -0,0 +1,9 @@
|
||||
# Automatically generated by pb2py
|
||||
Transfer = 0
|
||||
RegisterSecondPassphrase = 1
|
||||
RegisterDelegate = 2
|
||||
CastVotes = 3
|
||||
RegisterMultisignatureAccount = 4
|
||||
CreateDapp = 5
|
||||
TransferIntoDapp = 6
|
||||
TransferOutOfDapp = 7
|
11
trezorlib/messages/LiskVerifyMessage.py
Normal file
11
trezorlib/messages/LiskVerifyMessage.py
Normal file
@ -0,0 +1,11 @@
|
||||
# Automatically generated by pb2py
|
||||
from .. import protobuf as p
|
||||
|
||||
|
||||
class LiskVerifyMessage(p.MessageType):
|
||||
FIELDS = {
|
||||
1: ('signature', p.BytesType, 0),
|
||||
2: ('public_key', p.BytesType, 0),
|
||||
3: ('message', p.BytesType, 0),
|
||||
}
|
||||
MESSAGE_WIRE_TYPE = 120
|
@ -84,6 +84,15 @@ DebugLinkMemoryRead = 110
|
||||
DebugLinkMemory = 111
|
||||
DebugLinkMemoryWrite = 112
|
||||
DebugLinkFlashErase = 113
|
||||
LiskGetAddress = 114
|
||||
LiskAddress = 115
|
||||
LiskSignTx = 116
|
||||
LiskSignedTx = 117
|
||||
LiskSignMessage = 118
|
||||
LiskMessageSignature = 119
|
||||
LiskVerifyMessage = 120
|
||||
LiskGetPublicKey = 121
|
||||
LiskPublicKey = 122
|
||||
StellarGetPublicKey = 200
|
||||
StellarPublicKey = 201
|
||||
StellarSignTx = 202
|
||||
|
@ -4,6 +4,11 @@ from .CoinType import CoinType
|
||||
from .HDNodePathType import HDNodePathType
|
||||
from .HDNodeType import HDNodeType
|
||||
from .IdentityType import IdentityType
|
||||
from .LiskDelegateType import LiskDelegateType
|
||||
from .LiskMultisignatureType import LiskMultisignatureType
|
||||
from .LiskSignatureType import LiskSignatureType
|
||||
from .LiskTransactionAsset import LiskTransactionAsset
|
||||
from .LiskTransactionCommon import LiskTransactionCommon
|
||||
from .MultisigRedeemScriptType import MultisigRedeemScriptType
|
||||
from .NEMAggregateModification import NEMAggregateModification
|
||||
from .NEMCosignatoryModification import NEMCosignatoryModification
|
||||
@ -35,6 +40,7 @@ from . import NEMMosaicLevy
|
||||
from . import NEMSupplyChangeType
|
||||
from . import NEMModificationType
|
||||
from . import NEMImportanceTransferMode
|
||||
from . import LiskTransactionType
|
||||
from .Address import Address
|
||||
from .ApplyFlags import ApplyFlags
|
||||
from .ApplySettings import ApplySettings
|
||||
@ -87,6 +93,15 @@ from .GetEntropy import GetEntropy
|
||||
from .GetFeatures import GetFeatures
|
||||
from .GetPublicKey import GetPublicKey
|
||||
from .Initialize import Initialize
|
||||
from .LiskAddress import LiskAddress
|
||||
from .LiskGetAddress import LiskGetAddress
|
||||
from .LiskGetPublicKey import LiskGetPublicKey
|
||||
from .LiskMessageSignature import LiskMessageSignature
|
||||
from .LiskPublicKey import LiskPublicKey
|
||||
from .LiskSignMessage import LiskSignMessage
|
||||
from .LiskSignTx import LiskSignTx
|
||||
from .LiskSignedTx import LiskSignedTx
|
||||
from .LiskVerifyMessage import LiskVerifyMessage
|
||||
from .LoadDevice import LoadDevice
|
||||
from .MessageSignature import MessageSignature
|
||||
from .NEMAddress import NEMAddress
|
||||
|
@ -2,13 +2,13 @@ import binascii
|
||||
import json
|
||||
from . import messages as proto
|
||||
|
||||
TYPE_MOSAIC_TRANSFER = 0x0101
|
||||
TYPE_TRANSACTION_TRANSFER = 0x0101
|
||||
TYPE_IMPORTANCE_TRANSFER = 0x0801
|
||||
TYPE_MULTISIG_CHANGE = 0x1001
|
||||
TYPE_MULTISIG_SIGN = 0x1002
|
||||
TYPE_MULTISIG_TX = 0x1004
|
||||
TYPE_AGGREGATE_MODIFICATION = 0x1001
|
||||
TYPE_MULTISIG_SIGNATURE = 0x1002
|
||||
TYPE_MULTISIG = 0x1004
|
||||
TYPE_PROVISION_NAMESPACE = 0x2001
|
||||
TYPE_MOSAIC_DEFINITION_CREATION = 0x4001
|
||||
TYPE_MOSAIC_CREATION = 0x4001
|
||||
TYPE_MOSAIC_SUPPLY_CHANGE = 0x4002
|
||||
|
||||
|
||||
@ -19,7 +19,7 @@ def create_transaction_common(transaction):
|
||||
msg.fee = transaction["fee"]
|
||||
msg.deadline = transaction["deadline"]
|
||||
|
||||
if "signed" in transaction:
|
||||
if "signer" in transaction:
|
||||
msg.signer = binascii.unhexlify(transaction["signer"])
|
||||
|
||||
return msg
|
||||
@ -68,6 +68,7 @@ def create_provision_namespace(transaction):
|
||||
|
||||
msg.sink = transaction["rentalFeeSink"]
|
||||
msg.fee = transaction["rentalFee"]
|
||||
return msg
|
||||
|
||||
|
||||
def create_mosaic_creation(transaction):
|
||||
@ -113,27 +114,36 @@ def create_supply_change(transaction):
|
||||
return msg
|
||||
|
||||
|
||||
def create_importance_transfer(transaction):
|
||||
msg = proto.NEMImportanceTransfer()
|
||||
msg.mode = transaction["importanceTransfer"]["mode"]
|
||||
msg.public_key = binascii.unhexlify(transaction["importanceTransfer"]["publicKey"])
|
||||
return msg
|
||||
|
||||
|
||||
def create_sign_tx(transaction):
|
||||
msg = proto.NEMSignTx()
|
||||
msg.transaction = create_transaction_common(transaction)
|
||||
msg.cosigning = (transaction["type"] == TYPE_MULTISIG_SIGN)
|
||||
msg.cosigning = (transaction["type"] == TYPE_MULTISIG_SIGNATURE)
|
||||
|
||||
if transaction["type"] in (TYPE_MULTISIG_SIGN, TYPE_MULTISIG_TX):
|
||||
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")
|
||||
|
||||
if transaction["type"] == TYPE_MOSAIC_TRANSFER:
|
||||
if transaction["type"] == TYPE_TRANSACTION_TRANSFER:
|
||||
msg.transfer = create_transfer(transaction)
|
||||
elif transaction["type"] == TYPE_MULTISIG_CHANGE:
|
||||
elif transaction["type"] == TYPE_AGGREGATE_MODIFICATION:
|
||||
msg.aggregate_modification = create_aggregate_modification(transaction)
|
||||
elif transaction["type"] == TYPE_PROVISION_NAMESPACE:
|
||||
msg.provision_namespace = create_provision_namespace(transaction)
|
||||
elif transaction["type"] == TYPE_MOSAIC_DEFINITION_CREATION:
|
||||
elif transaction["type"] == TYPE_MOSAIC_CREATION:
|
||||
msg.mosaic_creation = create_mosaic_creation(transaction)
|
||||
elif transaction["type"] == TYPE_MOSAIC_SUPPLY_CHANGE:
|
||||
msg.mosaic_supply_change = create_supply_change(transaction)
|
||||
msg.supply_change = create_supply_change(transaction)
|
||||
elif transaction["type"] == TYPE_IMPORTANCE_TRANSFER:
|
||||
msg.importance_transfer = create_importance_transfer(transaction)
|
||||
else:
|
||||
raise ValueError("Unknown transaction type")
|
||||
|
||||
|
@ -22,9 +22,10 @@ from binascii import hexlify, unhexlify
|
||||
import pytest
|
||||
import os
|
||||
|
||||
from trezorlib import coins
|
||||
from trezorlib import tx_api
|
||||
from trezorlib.client import TrezorClient, TrezorClientDebugLink
|
||||
from trezorlib.transport import get_transport
|
||||
from trezorlib import tx_api
|
||||
|
||||
tests_dir = os.path.dirname(os.path.abspath(__file__))
|
||||
tx_api.cache_dir = os.path.join(tests_dir, '../txcache')
|
||||
@ -42,7 +43,7 @@ class TrezorTest:
|
||||
debuglink = wirelink.find_debug()
|
||||
self.client = TrezorClientDebugLink(wirelink)
|
||||
self.client.set_debuglink(debuglink)
|
||||
self.client.set_tx_api(tx_api.TxApiBitcoin)
|
||||
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
|
||||
|
34
trezorlib/tests/device_tests/conftest.py
Normal file
34
trezorlib/tests/device_tests/conftest.py
Normal file
@ -0,0 +1,34 @@
|
||||
import pytest
|
||||
|
||||
from . import common
|
||||
from trezorlib.client import TrezorClient
|
||||
|
||||
|
||||
def device_version():
|
||||
device = common.get_device()
|
||||
if not device:
|
||||
raise RuntimeError()
|
||||
client = TrezorClient(device)
|
||||
if client.features.model == "T":
|
||||
return 2
|
||||
else:
|
||||
return 1
|
||||
|
||||
|
||||
try:
|
||||
TREZOR_VERSION = device_version()
|
||||
except:
|
||||
raise
|
||||
TREZOR_VERSION = None
|
||||
|
||||
|
||||
def pytest_runtest_setup(item):
|
||||
'''
|
||||
Called for each test item (class, individual tests).
|
||||
Ensures that 'skip_t2' tests are skipped on T2
|
||||
and 'skip_t1' tests are skipped on T1.
|
||||
'''
|
||||
if item.get_marker("skip_t2") and TREZOR_VERSION == 2:
|
||||
pytest.skip("Test excluded on Trezor T")
|
||||
if item.get_marker("skip_t1") and TREZOR_VERSION == 1:
|
||||
pytest.skip("Test excluded on Trezor 1")
|
@ -18,6 +18,7 @@
|
||||
|
||||
from .common import *
|
||||
|
||||
import time
|
||||
from trezorlib import messages as proto
|
||||
|
||||
|
||||
@ -96,3 +97,60 @@ class TestMsgApplysettings(TrezorTest):
|
||||
proto.Success(),
|
||||
proto.Features()])
|
||||
self.client.apply_settings(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
|
||||
|
||||
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)
|
||||
|
||||
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)
|
||||
|
||||
@pytest.mark.skip_t2
|
||||
def test_apply_minimal_auto_lock_delay(self):
|
||||
"""
|
||||
Verify that the delay is not below the minimal auto-lock delay (10 secs)
|
||||
otherwise the device may auto-lock before any user interaction.
|
||||
"""
|
||||
self.setup_mnemonic_pin_passphrase()
|
||||
|
||||
with self.client:
|
||||
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))
|
||||
|
||||
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)
|
||||
|
||||
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)
|
||||
|
||||
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)
|
||||
|
@ -43,12 +43,14 @@ class TestMsgGetaddress(TrezorTest):
|
||||
self.setup_mnemonic_nopin_nopassphrase()
|
||||
assert self.client.get_address('Testnet', [111, 42]) == 'moN6aN6NP1KWgnPSqzrrRPvx2x1UtZJssa'
|
||||
|
||||
@pytest.mark.skip_t2
|
||||
def test_bch(self):
|
||||
self.setup_mnemonic_allallall()
|
||||
assert self.client.get_address('Bcash', self.client.expand_path("44'/145'/0'/0/0")) == '1MH9KKcvdCTY44xVDC2k3fjBbX5Cz29N1q'
|
||||
assert self.client.get_address('Bcash', self.client.expand_path("44'/145'/0'/0/1")) == '1LRspCZNFJcbuNKQkXgHMDucctFRQya5a3'
|
||||
assert self.client.get_address('Bcash', self.client.expand_path("44'/145'/0'/1/0")) == '1HADRPJpgqBzThepERpVXNi6qRgiLQRNoE'
|
||||
assert self.client.get_address('Bcash', self.client.expand_path("44'/145'/0'/0/0")) == 'bitcoincash:qr08q88p9etk89wgv05nwlrkm4l0urz4cyl36hh9sv'
|
||||
assert self.client.get_address('Bcash', self.client.expand_path("44'/145'/0'/0/1")) == 'bitcoincash:qr23ajjfd9wd73l87j642puf8cad20lfmqdgwvpat4'
|
||||
assert self.client.get_address('Bcash', self.client.expand_path("44'/145'/0'/1/0")) == 'bitcoincash:qzc5q87w069lzg7g3gzx0c8dz83mn7l02scej5aluw'
|
||||
|
||||
@pytest.mark.skip_t2
|
||||
def test_bch_multisig(self):
|
||||
self.setup_mnemonic_allallall()
|
||||
xpubs = []
|
||||
@ -62,8 +64,8 @@ class TestMsgGetaddress(TrezorTest):
|
||||
m=2,
|
||||
)
|
||||
for nr in range(1, 4):
|
||||
assert self.client.get_address('Bcash', self.client.expand_path("44'/145'/" + str(nr) + "'/0/0"), show_display=(nr == 1), multisig=getmultisig(0, 0)) == '33Ju286QvonBz5N1V754ZekQv4GLJqcc5R'
|
||||
assert self.client.get_address('Bcash', self.client.expand_path("44'/145'/" + str(nr) + "'/1/0"), show_display=(nr == 1), multisig=getmultisig(1, 0)) == '3CPtPpL5mGAPdxUeUDfm2RNdWoSN9dKpXE'
|
||||
assert self.client.get_address('Bcash', self.client.expand_path("44'/145'/" + str(nr) + "'/0/0"), show_display=(nr == 1), multisig=getmultisig(0, 0)) == 'bitcoincash:pqguz4nqq64jhr5v3kvpq4dsjrkda75hwy86gq0qzw'
|
||||
assert self.client.get_address('Bcash', self.client.expand_path("44'/145'/" + str(nr) + "'/1/0"), show_display=(nr == 1), multisig=getmultisig(1, 0)) == 'bitcoincash:pp6kcpkhua7789g2vyj0qfkcux3yvje7euhyhltn0a'
|
||||
|
||||
def test_public_ckd(self):
|
||||
self.setup_mnemonic_nopin_nopassphrase()
|
||||
|
33
trezorlib/tests/device_tests/test_msg_lisk_getaddress.py
Normal file
33
trezorlib/tests/device_tests/test_msg_lisk_getaddress.py
Normal file
@ -0,0 +1,33 @@
|
||||
# This file is part of the TREZOR project.
|
||||
#
|
||||
# Copyright (C) 2012-2016 Marek Palatinus <slush@satoshilabs.com>
|
||||
# Copyright (C) 2012-2016 Pavol Rusnak <stick@satoshilabs.com>
|
||||
#
|
||||
# This library is free software: you can redistribute it and/or modify
|
||||
# it under the terms of the GNU Lesser General Public License as published by
|
||||
# the Free Software Foundation, either version 3 of the License, or
|
||||
# (at your option) any later version.
|
||||
#
|
||||
# This library is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU Lesser General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU Lesser General Public License
|
||||
# along with this library. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
import pytest
|
||||
|
||||
from .common import TrezorTest
|
||||
|
||||
|
||||
@pytest.mark.xfail # drop when trezor-core PR #90 is merged
|
||||
@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'
|
31
trezorlib/tests/device_tests/test_msg_lisk_getpublickey.py
Normal file
31
trezorlib/tests/device_tests/test_msg_lisk_getpublickey.py
Normal file
@ -0,0 +1,31 @@
|
||||
# This file is part of the TREZOR project.
|
||||
#
|
||||
# Copyright (C) 2016-2017 Pavol Rusnak <stick@satoshilabs.com>
|
||||
#
|
||||
# This library is free software: you can redistribute it and/or modify
|
||||
# it under the terms of the GNU Lesser General Public License as published by
|
||||
# the Free Software Foundation, either version 3 of the License, or
|
||||
# (at your option) any later version.
|
||||
#
|
||||
# This library is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU Lesser General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU Lesser General Public License
|
||||
# along with this library. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
from binascii import hexlify
|
||||
import pytest
|
||||
|
||||
from .common import TrezorTest
|
||||
|
||||
|
||||
@pytest.mark.xfail # drop when trezor-core PR #90 is merged
|
||||
@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'
|
39
trezorlib/tests/device_tests/test_msg_lisk_signmessage.py
Normal file
39
trezorlib/tests/device_tests/test_msg_lisk_signmessage.py
Normal file
@ -0,0 +1,39 @@
|
||||
# This file is part of the TREZOR project.
|
||||
#
|
||||
# Copyright (C) 2016-2017 Pavol Rusnak <stick@satoshilabs.com>
|
||||
#
|
||||
# This library is free software: you can redistribute it and/or modify
|
||||
# it under the terms of the GNU Lesser General Public License as published by
|
||||
# the Free Software Foundation, either version 3 of the License, or
|
||||
# (at your option) any later version.
|
||||
#
|
||||
# This library is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU Lesser General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU Lesser General Public License
|
||||
# along with this library. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
from binascii import hexlify
|
||||
import pytest
|
||||
|
||||
from .common import TrezorTest
|
||||
|
||||
|
||||
@pytest.mark.xfail # drop when trezor-core PR #90 is merged
|
||||
@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 sig.address == '7623396847864198749L'
|
||||
assert hexlify(sig.signature) == b'af1d384cce25354b5af129662caed6f3514c6f1f6a206662d301fd56aa5549aa23c3f82009f213a7a4d9297015c2e5b06584273df7c42d78b4e531fe4d4fc80e'
|
||||
|
||||
def test_sign_long(self):
|
||||
self.setup_mnemonic_nopin_nopassphrase()
|
||||
sig = self.client.lisk_sign_message([2147483692, 2147483782, 2147483648], 'VeryLongMessage!' * 64)
|
||||
assert sig.address == '17563781916205589679L'
|
||||
print(hexlify(sig.signature))
|
||||
assert hexlify(sig.signature) == b'a675152c2af34e85dbd75740681efb7d67bf910561d6c9d1e075be2f99d9bc544d62c52f6619756b0e329a2f2d82756ced53b4261a028fcee0d37d7e641ef404'
|
176
trezorlib/tests/device_tests/test_msg_lisk_signtx.py
Normal file
176
trezorlib/tests/device_tests/test_msg_lisk_signtx.py
Normal file
@ -0,0 +1,176 @@
|
||||
# This file is part of the TREZOR project.
|
||||
#
|
||||
# Copyright (C) 2012-2016 Marek Palatinus <slush@satoshilabs.com>
|
||||
# Copyright (C) 2012-2016 Pavol Rusnak <stick@satoshilabs.com>
|
||||
#
|
||||
# This library is free software: you can redistribute it and/or modify
|
||||
# it under the terms of the GNU Lesser General Public License as published by
|
||||
# the Free Software Foundation, either version 3 of the License, or
|
||||
# (at your option) any later version.
|
||||
#
|
||||
# This library is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU Lesser General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU Lesser General Public License
|
||||
# along with this library. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
from binascii import unhexlify
|
||||
import pytest
|
||||
|
||||
from .common import TrezorTest
|
||||
from trezorlib import messages as proto
|
||||
|
||||
PUBLIC_KEY = unhexlify('eb56d7bbb5e8ea9269405f7a8527fe126023d1db2c973cfac6f760b60ae27294')
|
||||
|
||||
|
||||
@pytest.mark.xfail # drop when trezor-core PR #90 is merged
|
||||
@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(self.client.expand_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(self.client.expand_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(self.client.expand_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(self.client.expand_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(self.client.expand_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(self.client.expand_path("m/44'/134'/0'/0'"), {
|
||||
"amount": "0",
|
||||
"timestamp": 57525937,
|
||||
"type": 4,
|
||||
"fee": "1500000000",
|
||||
"asset": {
|
||||
"multisignature": {
|
||||
"min": 2,
|
||||
"lifetime": 5,
|
||||
"keysgroup": [
|
||||
"+5d036a858ce89f844491762eb89e2bfbd50a4a0a0da658e4b2628b25b117ae09",
|
||||
"+922fbfdd596fa78269bbcadc67ec2a1cc15fc929a19c462169568d7a3df1a1aa"
|
||||
]
|
||||
}
|
||||
}
|
||||
})
|
55
trezorlib/tests/device_tests/test_msg_lisk_verifymessage.py
Normal file
55
trezorlib/tests/device_tests/test_msg_lisk_verifymessage.py
Normal file
@ -0,0 +1,55 @@
|
||||
# This file is part of the TREZOR project.
|
||||
#
|
||||
# Copyright (C) 2016-2017 Pavol Rusnak <stick@satoshilabs.com>
|
||||
#
|
||||
# This library is free software: you can redistribute it and/or modify
|
||||
# it under the terms of the GNU Lesser General Public License as published by
|
||||
# the Free Software Foundation, either version 3 of the License, or
|
||||
# (at your option) any later version.
|
||||
#
|
||||
# This library is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU Lesser General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU Lesser General Public License
|
||||
# along with this library. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
from binascii import unhexlify
|
||||
import pytest
|
||||
|
||||
from .common import TrezorTest
|
||||
from trezorlib import messages as proto
|
||||
|
||||
|
||||
@pytest.mark.xfail # drop when trezor-core PR #90 is merged
|
||||
@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('af1d384cce25354b5af129662caed6f3514c6f1f6a206662d301fd56aa5549aa23c3f82009f213a7a4d9297015c2e5b06584273df7c42d78b4e531fe4d4fc80e'),
|
||||
'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('eb56d7bbb5e8ea9269405f7a8527fe126023d1db2c973cfac6f760b60ae27294'),
|
||||
unhexlify('7b4b481f6a07a874bdd1b590cd2b933c8b571c721484d9dc303f81b22d1f3c5f55ffe0704dbfd543ff9ea3e795facda871ddb422522257d33a8fe16ab4169601'),
|
||||
'VeryLongMessage!' * 64
|
||||
)
|
@ -18,7 +18,7 @@
|
||||
from .common import *
|
||||
|
||||
|
||||
@pytest.mark.skip_t2
|
||||
@pytest.mark.xfail # to be removed when nem is merged
|
||||
class TestMsgNEMGetaddress(TrezorTest):
|
||||
|
||||
def test_nem_getaddress(self):
|
||||
|
@ -1,139 +0,0 @@
|
||||
# This file is part of the TREZOR project.
|
||||
#
|
||||
# Copyright (C) 2017 Saleem Rashid <trezor@saleemrashid.com>
|
||||
#
|
||||
# This library is free software: you can redistribute it and/or modify
|
||||
# it under the terms of the GNU Lesser General Public License as published by
|
||||
# the Free Software Foundation, either version 3 of the License, or
|
||||
# (at your option) any later version.
|
||||
#
|
||||
# This library is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU Lesser General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU Lesser General Public License
|
||||
# along with this library. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
from .common import *
|
||||
|
||||
from trezorlib import messages as proto
|
||||
|
||||
|
||||
# assertion data from T1
|
||||
@pytest.mark.skip_t2
|
||||
class TestMsgNEMSigntx(TrezorTest):
|
||||
|
||||
def test_nem_signtx_simple(self):
|
||||
# tx hash: 209368053ac61969b6838ceb7e31badeb622ed6aa42d6c58365c42ad1a11e19d
|
||||
signature = unhexlify(
|
||||
"9cda2045324d05c791a4fc312ecceb62954e7740482f8df8928560d63cf273dea595023640179f112de755c79717757ef76962175378d6d87360ddb3f3e5f70f"
|
||||
)
|
||||
|
||||
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(signature=signature),
|
||||
])
|
||||
|
||||
tx = self.client.nem_sign_tx(self.client.expand_path("m/44'/1'/0'/0'/0'"), {
|
||||
"timeStamp": 74649215,
|
||||
"amount": 2000000,
|
||||
"fee": 2000000,
|
||||
"recipient": "TALICE2GMA34CXHD7XLJQ536NM5UNKQHTORNNT2J",
|
||||
"type": 257,
|
||||
"deadline": 74735615,
|
||||
"message": {
|
||||
"payload": hexlify(b"test_nem_transaction_transfer"),
|
||||
"type": 1,
|
||||
},
|
||||
"version": (0x98 << 24),
|
||||
})
|
||||
|
||||
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(),
|
||||
])
|
||||
|
||||
tx = self.client.nem_sign_tx(self.client.expand_path("m/44'/1'/0'/0'/0'"), {
|
||||
"timeStamp": 74649215,
|
||||
"amount": 2000000,
|
||||
"fee": 2000000,
|
||||
"recipient": "TALICE2GMA34CXHD7XLJQ536NM5UNKQHTORNNT2J",
|
||||
"type": 257,
|
||||
"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),
|
||||
})
|
||||
|
||||
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
|
||||
assert len(tx.signature) == 64
|
||||
|
||||
def test_nem_signtx_xem_as_mosaic(self):
|
||||
# tx hash: 9f8741194576a090bc71a3f43a03855950f94278fa121e99203e45967e19a7d0
|
||||
signature = unhexlify(
|
||||
"1bca7b1b9ffb16d2c2adffa665be072bd2d7a0eafe4a9911dc473500c272905edf3d626274deb52aa490137a276d1fca67ee487079ebf9c09f9faa414f8e7c02"
|
||||
)
|
||||
|
||||
self.setup_mnemonic_nopin_nopassphrase()
|
||||
|
||||
with self.client:
|
||||
self.client.set_expected_responses([
|
||||
# Confirm transfer and network fee
|
||||
proto.ButtonRequest(code=proto.ButtonRequestType.ConfirmOutput),
|
||||
# Confirm recipient
|
||||
proto.ButtonRequest(code=proto.ButtonRequestType.SignTx),
|
||||
proto.NEMSignedTx(signature=signature),
|
||||
])
|
||||
|
||||
tx = self.client.nem_sign_tx(self.client.expand_path("m/44'/1'/0'/0'/0'"), {
|
||||
"timeStamp": 76809215,
|
||||
"amount": 1000000,
|
||||
"fee": 1000000,
|
||||
"recipient": "TALICE2GMA34CXHD7XLJQ536NM5UNKQHTORNNT2J",
|
||||
"type": 257,
|
||||
"deadline": 76895615,
|
||||
"version": (0x98 << 24),
|
||||
"message": {
|
||||
},
|
||||
"mosaics": [
|
||||
{
|
||||
"mosaicId": {
|
||||
"namespaceId": "nem",
|
||||
"name": "xem",
|
||||
},
|
||||
"quantity": 1000000,
|
||||
},
|
||||
],
|
||||
})
|
||||
|
||||
assert hexlify(tx.data) == b'0101000002000098ff03940420000000edfd32f6e760648c032f9acb4b30d514265f6a5b5f8a7154f2618922b406208440420f00000000007f5595042800000054414c49434532474d4133344358484437584c4a513533364e4d35554e4b5148544f524e4e54324a40420f000000000000000000010000001a0000000e000000030000006e656d0300000078656d40420f0000000000'
|
||||
assert tx.signature == signature
|
171
trezorlib/tests/device_tests/test_msg_nem_signtx_mosaics.py
Normal file
171
trezorlib/tests/device_tests/test_msg_nem_signtx_mosaics.py
Normal file
@ -0,0 +1,171 @@
|
||||
# This file is part of the TREZOR project.
|
||||
#
|
||||
# Copyright (C) 2017 Saleem Rashid <trezor@saleemrashid.com>
|
||||
#
|
||||
# This library is free software: you can redistribute it and/or modify
|
||||
# it under the terms of the GNU Lesser General Public License as published by
|
||||
# the Free Software Foundation, either version 3 of the License, or
|
||||
# (at your option) any later version.
|
||||
#
|
||||
# This library is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU Lesser General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU Lesser General Public License
|
||||
# along with this library. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
from .common import *
|
||||
from trezorlib import nem
|
||||
|
||||
|
||||
# assertion data from T1
|
||||
@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(self.client.expand_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,
|
||||
})
|
||||
|
||||
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(self.client.expand_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"
|
||||
},
|
||||
"version": (0x98 << 24),
|
||||
"creationFeeSink": "TALICE2GMA34CXHD7XLJQ536NM5UNKQHTORNNT2J",
|
||||
"creationFee": 1500,
|
||||
})
|
||||
|
||||
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(self.client.expand_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"
|
||||
},
|
||||
"version": (0x98 << 24),
|
||||
"creationFeeSink": "TALICE2GMA34CXHD7XLJQ536NM5UNKQHTORNNT2J",
|
||||
"creationFee": 1500,
|
||||
})
|
||||
|
||||
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(self.client.expand_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"
|
||||
},
|
||||
"version": (0x98 << 24),
|
||||
"creationFeeSink": "TALICE2GMA34CXHD7XLJQ536NM5UNKQHTORNNT2J",
|
||||
"creationFee": 1500,
|
||||
})
|
||||
|
||||
assert hexlify(tx.data) == b'01400000010000987f0e730420000000edfd32f6e760648c032f9acb4b30d514265f6a5b5f8a7154f2618922b406208480841e0000000000ff5f74041801000020000000edfd32f6e760648c032f9acb4b30d514265f6a5b5f8a7154f2618922b40620841a0000000600000068656c6c6f6d0c00000048656c6c6f206d6f73616963050000006c6f72656d04000000150000000c00000064697669736962696c6974790100000034180000000d000000696e697469616c537570706c79030000003230301a0000000d000000737570706c794d757461626c650500000066616c7365180000000c0000007472616e7366657261626c65040000007472756556000000010000002800000054414c49434532474d4133344358484437584c4a513533364e4d35554e4b5148544f524e4e54324a1a0000000600000068656c6c6f6d0c00000048656c6c6f206d6f7361696302000000000000002800000054414c49434532474d4133344358484437584c4a513533364e4d35554e4b5148544f524e4e54324adc05000000000000'
|
||||
assert hexlify(tx.signature) == b'b87aac1ddf146d35e6a7f3451f57e2fe504ac559031e010a51261257c37bd50fcfa7b2939dd7a3203b54c4807d458475182f5d3dc135ec0d1d4a9cd42159fd0a'
|
215
trezorlib/tests/device_tests/test_msg_nem_signtx_mosaics_t2.py
Normal file
215
trezorlib/tests/device_tests/test_msg_nem_signtx_mosaics_t2.py
Normal file
@ -0,0 +1,215 @@
|
||||
# This file is part of the TREZOR project.
|
||||
#
|
||||
# Copyright (C) 2017 Saleem Rashid <trezor@saleemrashid.com>
|
||||
#
|
||||
# This library is free software: you can redistribute it and/or modify
|
||||
# it under the terms of the GNU Lesser General Public License as published by
|
||||
# the Free Software Foundation, either version 3 of the License, or
|
||||
# (at your option) any later version.
|
||||
#
|
||||
# This library is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU Lesser General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU Lesser General Public License
|
||||
# along with this library. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
from .common import *
|
||||
|
||||
from trezorlib import messages as proto
|
||||
from trezorlib import nem
|
||||
import time
|
||||
|
||||
|
||||
# assertion data from T1
|
||||
@pytest.mark.skip_t1
|
||||
@pytest.mark.xfail # to be removed when nem is merged
|
||||
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(self.client.expand_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,
|
||||
})
|
||||
|
||||
assert hexlify(tx.data) == b'02400000010000987f0e730420000000edfd32f6e760648c032f9acb4b30d514265f6a5b5f8a7154f2618922b406208480841e0000000000ff5f74041a0000000600000068656c6c6f6d0c00000048656c6c6f206d6f73616963010000000100000000000000'
|
||||
assert hexlify(tx.signature) == b'928b03c4a69fff35ecf0912066ea705895b3028fad141197d7ea2b56f1eef2a2516455e6f35d318f6fa39e2bb40492ac4ae603260790f7ebc7ea69feb4ca4c0a'
|
||||
|
||||
def test_nem_signtx_mosaic_creation(self):
|
||||
self.setup_mnemonic_nopin_nopassphrase()
|
||||
|
||||
test_suite = {
|
||||
"timeStamp": 74649215,
|
||||
"fee": 2000000,
|
||||
"type": nem.TYPE_MOSAIC_CREATION,
|
||||
"deadline": 74735615,
|
||||
"message": {
|
||||
},
|
||||
"mosaicDefinition": {
|
||||
"id": {
|
||||
"namespaceId": "hellom",
|
||||
"name": "Hello mosaic"
|
||||
},
|
||||
"levy": {},
|
||||
"properties": {},
|
||||
"description": "lorem"
|
||||
},
|
||||
"version": (0x98 << 24),
|
||||
"creationFeeSink": "TALICE2GMA34CXHD7XLJQ536NM5UNKQHTORNNT2J",
|
||||
"creationFee": 1500,
|
||||
}
|
||||
|
||||
# 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'
|
||||
|
||||
def test_nem_signtx_mosaic_creation_properties(self):
|
||||
self.setup_mnemonic_nopin_nopassphrase()
|
||||
|
||||
test_suite = {
|
||||
"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"
|
||||
},
|
||||
"version": (0x98 << 24),
|
||||
"creationFeeSink": "TALICE2GMA34CXHD7XLJQ536NM5UNKQHTORNNT2J",
|
||||
"creationFee": 1500,
|
||||
}
|
||||
|
||||
# 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'
|
||||
|
||||
def test_nem_signtx_mosaic_creation_levy(self):
|
||||
self.setup_mnemonic_nopin_nopassphrase()
|
||||
|
||||
test_suite = {
|
||||
"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"
|
||||
},
|
||||
"version": (0x98 << 24),
|
||||
"creationFeeSink": "TALICE2GMA34CXHD7XLJQ536NM5UNKQHTORNNT2J",
|
||||
"creationFee": 1500,
|
||||
}
|
||||
|
||||
tx = self._nem_sign(6, test_suite)
|
||||
assert hexlify(tx.data) == b'01400000010000987f0e730420000000edfd32f6e760648c032f9acb4b30d514265f6a5b5f8a7154f2618922b406208480841e0000000000ff5f74041801000020000000edfd32f6e760648c032f9acb4b30d514265f6a5b5f8a7154f2618922b40620841a0000000600000068656c6c6f6d0c00000048656c6c6f206d6f73616963050000006c6f72656d04000000150000000c00000064697669736962696c6974790100000034180000000d000000696e697469616c537570706c79030000003230301a0000000d000000737570706c794d757461626c650500000066616c7365180000000c0000007472616e7366657261626c65040000007472756556000000010000002800000054414c49434532474d4133344358484437584c4a513533364e4d35554e4b5148544f524e4e54324a1a0000000600000068656c6c6f6d0c00000048656c6c6f206d6f7361696302000000000000002800000054414c49434532474d4133344358484437584c4a513533364e4d35554e4b5148544f524e4e54324adc05000000000000'
|
||||
assert hexlify(tx.signature) == b'b87aac1ddf146d35e6a7f3451f57e2fe504ac559031e010a51261257c37bd50fcfa7b2939dd7a3203b54c4807d458475182f5d3dc135ec0d1d4a9cd42159fd0a'
|
||||
|
||||
def _nem_sign(self, num_of_swipes, test_suite):
|
||||
n = self.client.expand_path("m/44'/1'/0'/0'/0'")
|
||||
n = self.client._convert_prime(n)
|
||||
msg = nem.create_sign_tx(test_suite)
|
||||
assert msg.transaction is not None
|
||||
msg.transaction.address_n = n
|
||||
|
||||
# Sending NEMSignTx message
|
||||
self.client.transport.write(msg)
|
||||
ret = self.client.transport.read()
|
||||
|
||||
# Confirm action
|
||||
assert isinstance(ret, proto.ButtonRequest)
|
||||
self.client.debug.press_yes()
|
||||
self.client.transport.write(proto.ButtonAck())
|
||||
time.sleep(1)
|
||||
for i in range(num_of_swipes):
|
||||
self.client.debug.swipe_down()
|
||||
time.sleep(1)
|
||||
self.client.debug.press_yes()
|
||||
ret = self.client.transport.read()
|
||||
|
||||
# Confirm action
|
||||
assert isinstance(ret, proto.ButtonRequest)
|
||||
self.client.debug.press_yes()
|
||||
self.client.transport.write(proto.ButtonAck())
|
||||
ret = self.client.transport.read()
|
||||
|
||||
# Confirm tx
|
||||
assert isinstance(ret, proto.ButtonRequest)
|
||||
self.client.debug.press_yes()
|
||||
self.client.transport.write(proto.ButtonAck())
|
||||
return self.client.transport.read()
|
159
trezorlib/tests/device_tests/test_msg_nem_signtx_multisig.py
Normal file
159
trezorlib/tests/device_tests/test_msg_nem_signtx_multisig.py
Normal file
@ -0,0 +1,159 @@
|
||||
# This file is part of the TREZOR project.
|
||||
#
|
||||
# Copyright (C) 2017 Saleem Rashid <trezor@saleemrashid.com>
|
||||
#
|
||||
# This library is free software: you can redistribute it and/or modify
|
||||
# it under the terms of the GNU Lesser General Public License as published by
|
||||
# the Free Software Foundation, either version 3 of the License, or
|
||||
# (at your option) any later version.
|
||||
#
|
||||
# This library is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU Lesser General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU Lesser General Public License
|
||||
# along with this library. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
from .common import *
|
||||
|
||||
from trezorlib import nem
|
||||
|
||||
|
||||
# assertion data from T1
|
||||
@pytest.mark.xfail # to be removed when nem is merged
|
||||
class TestMsgNEMSignTxMultisig(TrezorTest):
|
||||
|
||||
def test_nem_signtx_aggregate_modification(self):
|
||||
self.setup_mnemonic_nopin_nopassphrase()
|
||||
|
||||
tx = self.client.nem_sign_tx(self.client.expand_path("m/44'/1'/0'/0'/0'"), {
|
||||
"timeStamp": 74649215,
|
||||
"fee": 2000000,
|
||||
"type": nem.TYPE_AGGREGATE_MODIFICATION,
|
||||
"deadline": 74735615,
|
||||
"message": {
|
||||
},
|
||||
"modifications": [
|
||||
{
|
||||
"modificationType": 1, # Add
|
||||
"cosignatoryAccount": "c5f54ba980fcbb657dbaaa42700539b207873e134d2375efeab5f1ab52f87844"
|
||||
},
|
||||
],
|
||||
"minCosignatories": {
|
||||
"relativeChange": 3
|
||||
},
|
||||
"version": (0x98 << 24),
|
||||
})
|
||||
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(self.client.expand_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),
|
||||
})
|
||||
|
||||
assert hexlify(tx.data) == b'04100000010000980100000020000000edfd32f6e760648c032f9acb4b30d514265f6a5b5f8a7154f2618922b40620841027000000000000ff5f74049900000001010000010000980200000020000000c5f54ba980fcbb657dbaaa42700539b207873e134d2375efeab5f1ab52f87844983a000000000000320901002800000054414c49434532474d4133344358484437584c4a513533364e4d35554e4b5148544f524e4e54324a80841e000000000025000000010000001d000000746573745f6e656d5f7472616e73616374696f6e5f7472616e73666572'
|
||||
assert hexlify(tx.signature) == b'0cab2fddf2f02b5d7201675b9a71869292fe25ed33a366c7d2cbea7676fed491faaa03310079b7e17884b6ba2e3ea21c4f728d1cca8f190b8288207f6514820a'
|
||||
|
||||
tx = self.client.nem_sign_tx(self.client.expand_path("m/44'/1'/0'/0'/0'"), {
|
||||
"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',
|
||||
},
|
||||
"version": (0x98 << 24),
|
||||
})
|
||||
|
||||
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(self.client.expand_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),
|
||||
})
|
||||
|
||||
assert hexlify(tx.data) == b'02100000010000984d01000020000000edfd32f6e760648c032f9acb4b30d514265f6a5b5f8a7154f2618922b4062084c800000000000000bc010000240000002000000087923cd4805f3babe6b5af9cbb2b08be4458e39531618aed73c911f160c8e38528000000544444324354364c514c49595135364b49584933454e544d36454b3344343450354b5a50464d4b32'
|
||||
assert hexlify(tx.signature) == b'286358a16ae545bff798feab93a713440c7c2f236d52ac0e995669d17a1915b0903667c97fa04418eccb42333cba95b19bccc8ac1faa8224dcfaeb41890ae807'
|
||||
|
||||
tx = self.client.nem_sign_tx(self.client.expand_path("m/44'/1'/0'/0'/0'"), {
|
||||
"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',
|
||||
},
|
||||
"version": (0x98 << 24),
|
||||
})
|
||||
|
||||
assert hexlify(tx.data) == b'0210000001000098a0bb0d0020000000edfd32f6e760648c032f9acb4b30d514265f6a5b5f8a7154f2618922b4062084400d030000000000640000002400000020000000c51395626a89a71c1ed785fb5974307a049b3b9e2165d56ed0302fe6b4f02a0128000000544444324354364c514c49595135364b49584933454e544d36454b3344343450354b5a50464d4b32'
|
||||
assert hexlify(tx.signature) == b'32b1fdf788c4a90c01eedf5972b7709745831d620c13e1e97b0de6481837e162ee551573f2409822754ae940731909ec4b79cf836487e898df476adb10467506'
|
67
trezorlib/tests/device_tests/test_msg_nem_signtx_others.py
Normal file
67
trezorlib/tests/device_tests/test_msg_nem_signtx_others.py
Normal file
@ -0,0 +1,67 @@
|
||||
# This file is part of the TREZOR project.
|
||||
#
|
||||
# Copyright (C) 2017 Saleem Rashid <trezor@saleemrashid.com>
|
||||
#
|
||||
# This library is free software: you can redistribute it and/or modify
|
||||
# it under the terms of the GNU Lesser General Public License as published by
|
||||
# the Free Software Foundation, either version 3 of the License, or
|
||||
# (at your option) any later version.
|
||||
#
|
||||
# This library is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU Lesser General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU Lesser General Public License
|
||||
# along with this library. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
from .common import *
|
||||
|
||||
from trezorlib import nem
|
||||
|
||||
|
||||
# assertion data from T1
|
||||
@pytest.mark.xfail # to be removed when nem is merged
|
||||
class TestMsgNEMSignTxOther(TrezorTest):
|
||||
|
||||
def test_nem_signtx_importance_transfer(self):
|
||||
self.setup_mnemonic_nopin_nopassphrase()
|
||||
|
||||
with self.client:
|
||||
tx = self.client.nem_sign_tx(self.client.expand_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),
|
||||
})
|
||||
|
||||
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(self.client.expand_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),
|
||||
})
|
||||
|
||||
assert hexlify(tx.data) == b'01200000010000987f0e730420000000edfd32f6e760648c032f9acb4b30d514265f6a5b5f8a7154f2618922b406208480841e0000000000ff5f74042800000054414c49434532474d4133344358484437584c4a513533364e4d35554e4b5148544f524e4e54324adc05000000000000050000004142434445ffffffff'
|
||||
assert hexlify(tx.signature) == b'f047ae7987cd3a60c0d5ad123aba211185cb6266a7469dfb0491a0df6b5cd9c92b2e2b9f396cc2a3146ee185ba02df4f9e7fb238fe479917b3d274d97336640d'
|
240
trezorlib/tests/device_tests/test_msg_nem_signtx_transfers.py
Normal file
240
trezorlib/tests/device_tests/test_msg_nem_signtx_transfers.py
Normal file
@ -0,0 +1,240 @@
|
||||
# This file is part of the TREZOR project.
|
||||
#
|
||||
# Copyright (C) 2017 Saleem Rashid <trezor@saleemrashid.com>
|
||||
#
|
||||
# This library is free software: you can redistribute it and/or modify
|
||||
# it under the terms of the GNU Lesser General Public License as published by
|
||||
# the Free Software Foundation, either version 3 of the License, or
|
||||
# (at your option) any later version.
|
||||
#
|
||||
# This library is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU Lesser General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU Lesser General Public License
|
||||
# along with this library. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
from .common import *
|
||||
|
||||
from trezorlib import messages as proto
|
||||
from trezorlib import nem
|
||||
|
||||
|
||||
# assertion data from T1
|
||||
@pytest.mark.xfail # to be removed when nem is merged
|
||||
class TestMsgNEMSignTx(TrezorTest):
|
||||
|
||||
def test_nem_signtx_simple(self):
|
||||
# tx hash: 209368053ac61969b6838ceb7e31badeb622ed6aa42d6c58365c42ad1a11e19d
|
||||
signature = unhexlify(
|
||||
"9cda2045324d05c791a4fc312ecceb62954e7740482f8df8928560d63cf273dea595023640179f112de755c79717757ef76962175378d6d87360ddb3f3e5f70f"
|
||||
)
|
||||
|
||||
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(),
|
||||
])
|
||||
|
||||
tx = self.client.nem_sign_tx(self.client.expand_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),
|
||||
})
|
||||
|
||||
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(),
|
||||
])
|
||||
|
||||
tx = self.client.nem_sign_tx(self.client.expand_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),
|
||||
})
|
||||
|
||||
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
|
||||
assert len(tx.signature) == 64
|
||||
|
||||
def test_nem_signtx_xem_as_mosaic(self):
|
||||
self.setup_mnemonic_nopin_nopassphrase()
|
||||
|
||||
tx = self.client.nem_sign_tx(self.client.expand_path("m/44'/1'/0'/0'/0'"), {
|
||||
"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,
|
||||
},
|
||||
],
|
||||
})
|
||||
|
||||
# trezor should display 45 XEM (multiplied by amount)
|
||||
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(self.client.expand_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,
|
||||
},
|
||||
],
|
||||
})
|
||||
|
||||
# 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'
|
||||
|
||||
def test_nem_signtx_known_mosaic(self):
|
||||
|
||||
self.setup_mnemonic_nopin_nopassphrase()
|
||||
|
||||
tx = self.client.nem_sign_tx(self.client.expand_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,
|
||||
},
|
||||
],
|
||||
})
|
||||
|
||||
# trezor should display 0 XEM and 0.333 DIMTOK
|
||||
assert hexlify(tx.data) == b'0101000002000068ff03940420000000edfd32f6e760648c032f9acb4b30d514265f6a5b5f8a7154f2618922b406208440420f00000000007f559504280000004e444d59534c5849344c3346595551574f344d4a4f564c364253544a4a584b44535a524d54344c54c0c62d000000000000000000010000001c000000100000000300000064696d05000000746f6b656e98b1010000000000'
|
||||
assert hexlify(tx.signature) == b'e7f14ef8c39727bfd257e109cd5acac31542f2e41f2e5deb258fc1db602b690eb1cabca41a627fe2adc51f3193db85c76b41c80bb60161eb8738ebf20b507104'
|
||||
|
||||
def test_nem_signtx_multiple_mosaics(self):
|
||||
self.setup_mnemonic_nopin_nopassphrase()
|
||||
|
||||
tx = self.client.nem_sign_tx(self.client.expand_path("m/44'/1'/0'/0'/0'"), {
|
||||
"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,
|
||||
},
|
||||
{
|
||||
"mosaicId": {
|
||||
"namespaceId": "abc",
|
||||
"name": "mosaic",
|
||||
},
|
||||
"quantity": 200,
|
||||
},
|
||||
{
|
||||
"mosaicId": {
|
||||
"namespaceId": "nem",
|
||||
"name": "xem",
|
||||
},
|
||||
"quantity": 30000,
|
||||
},
|
||||
{
|
||||
"mosaicId": {
|
||||
"namespaceId": "abc",
|
||||
"name": "mosaic",
|
||||
},
|
||||
"quantity": 2000000,
|
||||
},
|
||||
{
|
||||
"mosaicId": {
|
||||
"namespaceId": "breeze",
|
||||
"name": "breeze-token",
|
||||
},
|
||||
"quantity": 111000,
|
||||
}
|
||||
]
|
||||
})
|
||||
|
||||
# trezor should display warning, 6.06 XEM, 4000400 raw units of abc.mosaic (mosaics are merged)
|
||||
# and 222000 BREEZE
|
||||
assert hexlify(tx.data) == b'0101000002000068ff03940420000000edfd32f6e760648c032f9acb4b30d514265f6a5b5f8a7154f2618922b406208440420f00000000007f559504280000004e444d59534c5849344c3346595551574f344d4a4f564c364253544a4a584b44535a524d54344c5480841e000000000000000000030000001d0000001100000003000000616263060000006d6f7361696348851e0000000000260000001a00000006000000627265657a650c000000627265657a652d746f6b656e98b10100000000001a0000000e000000030000006e656d0300000078656df03b2e0000000000'
|
||||
assert hexlify(tx.signature) == b'b2b9319fca87a05bee17108edd9a8f78aeffef74bf6b4badc6da5d46e8ff4fe82e24bf69d8e6c4097d072adf39d0c753e7580f8afb21e3288ebfb7c4d84e470d'
|
105
trezorlib/tests/device_tests/test_msg_recoverydevice_t2.py
Normal file
105
trezorlib/tests/device_tests/test_msg_recoverydevice_t2.py
Normal file
@ -0,0 +1,105 @@
|
||||
# This file is part of the TREZOR project.
|
||||
#
|
||||
# Copyright (C) 2012-2016 Marek Palatinus <slush@satoshilabs.com>
|
||||
# Copyright (C) 2012-2016 Pavol Rusnak <stick@satoshilabs.com>
|
||||
#
|
||||
# This library is free software: you can redistribute it and/or modify
|
||||
# it under the terms of the GNU Lesser General Public License as published by
|
||||
# the Free Software Foundation, either version 3 of the License, or
|
||||
# (at your option) any later version.
|
||||
#
|
||||
# This library is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU Lesser General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU Lesser General Public License
|
||||
# along with this library. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
from __future__ import print_function
|
||||
|
||||
import time
|
||||
|
||||
from .common import *
|
||||
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))
|
||||
|
||||
# Enter word count
|
||||
assert ret == proto.ButtonRequest(code=proto.ButtonRequestType.MnemonicWordCount)
|
||||
self.client.debug.input(str(len(mnemonic)))
|
||||
ret = self.client.call_raw(proto.ButtonAck())
|
||||
|
||||
# Enter mnemonic words
|
||||
assert ret == proto.ButtonRequest(code=proto.ButtonRequestType.MnemonicInput)
|
||||
self.client.transport.write(proto.ButtonAck())
|
||||
for word in mnemonic:
|
||||
time.sleep(1)
|
||||
self.client.debug.input(word)
|
||||
ret = self.client.transport.read()
|
||||
|
||||
# Enter PIN for first time
|
||||
assert ret == proto.ButtonRequest(code=proto.ButtonRequestType.Other)
|
||||
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')
|
||||
ret = self.client.call_raw(proto.ButtonAck())
|
||||
|
||||
# Workflow succesfully ended
|
||||
assert ret == proto.Success(message='Device recovered')
|
||||
|
||||
# Mnemonic is the same
|
||||
self.client.init_device()
|
||||
assert self.client.debug.read_mnemonic() == self.mnemonic12
|
||||
|
||||
assert self.client.features.pin_protection is True
|
||||
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))
|
||||
|
||||
# Enter word count
|
||||
assert ret == proto.ButtonRequest(code=proto.ButtonRequestType.MnemonicWordCount)
|
||||
self.client.debug.input(str(len(mnemonic)))
|
||||
ret = self.client.call_raw(proto.ButtonAck())
|
||||
|
||||
# Enter mnemonic words
|
||||
assert ret == proto.ButtonRequest(code=proto.ButtonRequestType.MnemonicInput)
|
||||
self.client.transport.write(proto.ButtonAck())
|
||||
for word in mnemonic:
|
||||
time.sleep(1)
|
||||
self.client.debug.input(word)
|
||||
ret = self.client.transport.read()
|
||||
|
||||
# Workflow succesfully ended
|
||||
assert ret == proto.Success(message='Device recovered')
|
||||
|
||||
# Mnemonic is the same
|
||||
self.client.init_device()
|
||||
assert self.client.debug.read_mnemonic() == self.mnemonic12
|
||||
|
||||
assert self.client.features.pin_protection is False
|
||||
assert self.client.features.passphrase_protection is False
|
||||
|
||||
def test_already_initialized(self):
|
||||
self.setup_mnemonic_nopin_nopassphrase()
|
||||
with pytest.raises(Exception):
|
||||
self.client.recovery_device(12, False, False, 'label', 'english')
|
@ -18,9 +18,11 @@
|
||||
|
||||
from .common import *
|
||||
|
||||
from trezorlib import coins
|
||||
from trezorlib import messages as proto
|
||||
from trezorlib.client import CallException
|
||||
from trezorlib.tx_api import TxApiTestnet
|
||||
|
||||
TxApiTestnet = coins.tx_api['Testnet']
|
||||
|
||||
|
||||
TXHASH_157041 = unhexlify('1570416eb4302cf52979afd5e6909e37d8fdd874301f7cc87e547e509cb1caa6')
|
||||
|
@ -16,12 +16,15 @@
|
||||
# along with this library. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
from .common import *
|
||||
from trezorlib import coins
|
||||
from trezorlib import messages as proto
|
||||
from trezorlib.tx_api import TxApiBcash
|
||||
from trezorlib.ckd_public import deserialize
|
||||
from trezorlib.client import CallException
|
||||
|
||||
TxApiBcash = coins.tx_api['Bcash']
|
||||
|
||||
|
||||
@pytest.mark.skip_t2
|
||||
class TestMsgSigntxBch(TrezorTest):
|
||||
|
||||
def test_send_bch_change(self):
|
||||
@ -29,7 +32,7 @@ class TestMsgSigntxBch(TrezorTest):
|
||||
self.client.set_tx_api(TxApiBcash)
|
||||
inp1 = proto.TxInputType(
|
||||
address_n=self.client.expand_path("44'/145'/0'/0/0"),
|
||||
# 1MH9KKcvdCTY44xVDC2k3fjBbX5Cz29N1q
|
||||
# bitcoincash:qr08q88p9etk89wgv05nwlrkm4l0urz4cyl36hh9sv
|
||||
amount=1995344,
|
||||
prev_hash=unhexlify('bc37c28dfb467d2ecb50261387bf752a3977d7e5337915071bb4151e6b711a78'),
|
||||
prev_index=0,
|
||||
@ -41,7 +44,7 @@ class TestMsgSigntxBch(TrezorTest):
|
||||
script_type=proto.OutputScriptType.PAYTOADDRESS,
|
||||
)
|
||||
out2 = proto.TxOutputType(
|
||||
address='1LRspCZNFJcbuNKQkXgHMDucctFRQya5a3',
|
||||
address='bitcoincash:qr23ajjfd9wd73l87j642puf8cad20lfmqdgwvpat4',
|
||||
amount=73452,
|
||||
script_type=proto.OutputScriptType.PAYTOADDRESS,
|
||||
)
|
||||
@ -66,7 +69,7 @@ class TestMsgSigntxBch(TrezorTest):
|
||||
self.client.set_tx_api(TxApiBcash)
|
||||
inp1 = proto.TxInputType(
|
||||
address_n=self.client.expand_path("44'/145'/0'/1/0"),
|
||||
# 1HADRPJpgqBzThepERpVXNi6qRgiLQRNoE
|
||||
# bitcoincash:qzc5q87w069lzg7g3gzx0c8dz83mn7l02scej5aluw
|
||||
amount=1896050,
|
||||
prev_hash=unhexlify('502e8577b237b0152843a416f8f1ab0c63321b1be7a8cad7bf5c5c216fcf062c'),
|
||||
prev_index=0,
|
||||
@ -74,7 +77,47 @@ class TestMsgSigntxBch(TrezorTest):
|
||||
)
|
||||
inp2 = proto.TxInputType(
|
||||
address_n=self.client.expand_path("44'/145'/0'/0/1"),
|
||||
# 1LRspCZNFJcbuNKQkXgHMDucctFRQya5a3
|
||||
# bitcoincash:qr23ajjfd9wd73l87j642puf8cad20lfmqdgwvpat4
|
||||
amount=73452,
|
||||
prev_hash=unhexlify('502e8577b237b0152843a416f8f1ab0c63321b1be7a8cad7bf5c5c216fcf062c'),
|
||||
prev_index=1,
|
||||
script_type=proto.InputScriptType.SPENDADDRESS,
|
||||
)
|
||||
out1 = proto.TxOutputType(
|
||||
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'
|
||||
|
||||
def test_send_bch_oldaddr(self):
|
||||
self.setup_mnemonic_allallall()
|
||||
self.client.set_tx_api(TxApiBcash)
|
||||
inp1 = proto.TxInputType(
|
||||
address_n=self.client.expand_path("44'/145'/0'/1/0"),
|
||||
# bitcoincash:qzc5q87w069lzg7g3gzx0c8dz83mn7l02scej5aluw
|
||||
amount=1896050,
|
||||
prev_hash=unhexlify('502e8577b237b0152843a416f8f1ab0c63321b1be7a8cad7bf5c5c216fcf062c'),
|
||||
prev_index=0,
|
||||
script_type=proto.InputScriptType.SPENDADDRESS,
|
||||
)
|
||||
inp2 = proto.TxInputType(
|
||||
address_n=self.client.expand_path("44'/145'/0'/0/1"),
|
||||
# bitcoincash:qr23ajjfd9wd73l87j642puf8cad20lfmqdgwvpat4
|
||||
amount=73452,
|
||||
prev_hash=unhexlify('502e8577b237b0152843a416f8f1ab0c63321b1be7a8cad7bf5c5c216fcf062c'),
|
||||
prev_index=1,
|
||||
@ -106,7 +149,7 @@ class TestMsgSigntxBch(TrezorTest):
|
||||
self.client.set_tx_api(TxApiBcash)
|
||||
inp1 = proto.TxInputType(
|
||||
address_n=self.client.expand_path("44'/145'/0'/1/0"),
|
||||
# 1HADRPJpgqBzThepERpVXNi6qRgiLQRNoE
|
||||
# bitcoincash:qzc5q87w069lzg7g3gzx0c8dz83mn7l02scej5aluw
|
||||
amount=300,
|
||||
prev_hash=unhexlify('502e8577b237b0152843a416f8f1ab0c63321b1be7a8cad7bf5c5c216fcf062c'),
|
||||
prev_index=0,
|
||||
@ -114,14 +157,14 @@ class TestMsgSigntxBch(TrezorTest):
|
||||
)
|
||||
inp2 = proto.TxInputType(
|
||||
address_n=self.client.expand_path("44'/145'/0'/0/1"),
|
||||
# 1LRspCZNFJcbuNKQkXgHMDucctFRQya5a3
|
||||
# bitcoincash:qr23ajjfd9wd73l87j642puf8cad20lfmqdgwvpat4
|
||||
amount=70,
|
||||
prev_hash=unhexlify('502e8577b237b0152843a416f8f1ab0c63321b1be7a8cad7bf5c5c216fcf062c'),
|
||||
prev_index=1,
|
||||
script_type=proto.InputScriptType.SPENDADDRESS,
|
||||
)
|
||||
out1 = proto.TxOutputType(
|
||||
address='15pnEDZJo3ycPUamqP3tEDnEju1oW5fBCz',
|
||||
address='bitcoincash:qq6wnnkrz7ykaqvxrx4hmjvayvzjzml54uyk76arx4',
|
||||
amount=200,
|
||||
script_type=proto.OutputScriptType.PAYTOADDRESS,
|
||||
)
|
||||
@ -192,7 +235,7 @@ class TestMsgSigntxBch(TrezorTest):
|
||||
self.client.set_tx_api(TxApiBcash)
|
||||
inp1 = proto.TxInputType(
|
||||
address_n=self.client.expand_path("44'/145'/1000'/0/0"),
|
||||
# 1MH9KKcvdCTY44xVDC2k3fjBbX5Cz29N1q
|
||||
# bitcoincash:qr08q88p9etk89wgv05nwlrkm4l0urz4cyl36hh9sv
|
||||
amount=1995344,
|
||||
prev_hash=unhexlify('bc37c28dfb467d2ecb50261387bf752a3977d7e5337915071bb4151e6b711a78'),
|
||||
prev_index=0,
|
||||
@ -204,7 +247,7 @@ class TestMsgSigntxBch(TrezorTest):
|
||||
script_type=proto.OutputScriptType.PAYTOADDRESS,
|
||||
)
|
||||
out2 = proto.TxOutputType(
|
||||
address='1LRspCZNFJcbuNKQkXgHMDucctFRQya5a3',
|
||||
address='bitcoincash:qr23ajjfd9wd73l87j642puf8cad20lfmqdgwvpat4',
|
||||
amount=73452,
|
||||
script_type=proto.OutputScriptType.PAYTOADDRESS,
|
||||
)
|
||||
@ -263,7 +306,7 @@ class TestMsgSigntxBch(TrezorTest):
|
||||
inp1 = proto.TxInputType(
|
||||
address_n=self.client.expand_path("44'/145'/1'/1/0"),
|
||||
multisig=getmultisig(1, 0, [b'', sig, b'']),
|
||||
# 3CPtPpL5mGAPdxUeUDfm2RNdWoSN9dKpXE
|
||||
# bitcoincash:pp6kcpkhua7789g2vyj0qfkcux3yvje7euhyhltn0a
|
||||
amount=24000,
|
||||
prev_hash=unhexlify('f68caf10df12d5b07a34601d88fa6856c6edcbf4d05ebef3486510ae1c293d5f'),
|
||||
prev_index=1,
|
||||
@ -311,14 +354,14 @@ class TestMsgSigntxBch(TrezorTest):
|
||||
inp1 = proto.TxInputType(
|
||||
address_n=self.client.expand_path("44'/145'/3'/0/0"),
|
||||
multisig=getmultisig(0, 0),
|
||||
# 33Ju286QvonBz5N1V754ZekQv4GLJqcc5R
|
||||
# bitcoincash:pqguz4nqq64jhr5v3kvpq4dsjrkda75hwy86gq0qzw
|
||||
amount=48490,
|
||||
prev_hash=unhexlify('8b6db9b8ba24235d86b053ea2ccb484fc32b96f89c3c39f98d86f90db16076a0'),
|
||||
prev_index=0,
|
||||
script_type=proto.InputScriptType.SPENDMULTISIG,
|
||||
)
|
||||
out1 = proto.TxOutputType(
|
||||
address='113Q5hHQNQ3bc1RpPX6UNw4GAXstyeA3Dk',
|
||||
address='bitcoincash:qqq8gx2j76nw4dfefumxmdwvtf2tpsjznusgsmzex9',
|
||||
amount=24000,
|
||||
script_type=proto.OutputScriptType.PAYTOADDRESS,
|
||||
)
|
||||
@ -347,7 +390,7 @@ class TestMsgSigntxBch(TrezorTest):
|
||||
inp1 = proto.TxInputType(
|
||||
address_n=self.client.expand_path("44'/145'/1'/0/0"),
|
||||
multisig=getmultisig(0, 0, [b'', b'', signatures1[0]]),
|
||||
# 33Ju286QvonBz5N1V754ZekQv4GLJqcc5R
|
||||
# bitcoincash:pqguz4nqq64jhr5v3kvpq4dsjrkda75hwy86gq0qzw
|
||||
amount=48490,
|
||||
prev_hash=unhexlify('8b6db9b8ba24235d86b053ea2ccb484fc32b96f89c3c39f98d86f90db16076a0'),
|
||||
prev_index=0,
|
||||
|
@ -17,11 +17,13 @@
|
||||
# along with this library. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
from .common import *
|
||||
from trezorlib import coins
|
||||
from trezorlib import messages as proto
|
||||
from trezorlib.tx_api import TxApiBitcoinGold
|
||||
from trezorlib.ckd_public import deserialize
|
||||
from trezorlib.client import CallException
|
||||
|
||||
TxApiBitcoinGold = coins.tx_api["Bitcoin Gold"]
|
||||
|
||||
|
||||
# All data taken from T1
|
||||
class TestMsgSigntxBitcoinGold(TrezorTest):
|
||||
|
@ -17,8 +17,10 @@
|
||||
|
||||
from .common import *
|
||||
|
||||
from trezorlib import coins
|
||||
from trezorlib import messages as proto
|
||||
from trezorlib.tx_api import TxApiDecredTestnet
|
||||
|
||||
TxApiDecredTestnet = coins.tx_api['Decred Testnet']
|
||||
|
||||
|
||||
TXHASH_e16248 = unhexlify("e16248f0b39a0a0c0e53d6f2f84c2a944f0d50e017a82701e8e02e46e979d5ed")
|
||||
|
@ -17,11 +17,13 @@
|
||||
|
||||
from .common import *
|
||||
|
||||
from trezorlib import coins
|
||||
from trezorlib import messages as proto
|
||||
from trezorlib.tx_api import TxApiTestnet
|
||||
from trezorlib.ckd_public import deserialize
|
||||
from trezorlib.client import CallException
|
||||
|
||||
TxApiTestnet = coins.tx_api["Testnet"]
|
||||
|
||||
|
||||
class TestMsgSigntxSegwit(TrezorTest):
|
||||
|
||||
|
@ -17,10 +17,12 @@
|
||||
|
||||
from .common import *
|
||||
|
||||
from trezorlib import coins
|
||||
from trezorlib import messages as proto
|
||||
from trezorlib.tx_api import TxApiTestnet
|
||||
from trezorlib.ckd_public import deserialize
|
||||
|
||||
TxApiTestnet = coins.tx_api['Testnet']
|
||||
|
||||
|
||||
class TestMsgSigntxSegwitNative(TrezorTest):
|
||||
|
||||
|
@ -18,8 +18,11 @@
|
||||
|
||||
|
||||
from .common import *
|
||||
|
||||
from trezorlib import coins
|
||||
from trezorlib import messages as proto
|
||||
from trezorlib.tx_api import TxApiZcash
|
||||
|
||||
TxApiZcash = coins.tx_api["Zcash"]
|
||||
|
||||
|
||||
TXHASH_93373e = unhexlify('93373e63cc626c4a7d049ad775d6511bb5eba985f142db660c9b9f955c722f5c')
|
||||
|
@ -19,14 +19,14 @@
|
||||
from .common import *
|
||||
from trezorlib import messages as proto
|
||||
import trezorlib.ckd_public as bip32
|
||||
from trezorlib import tx_api
|
||||
from trezorlib.coins import tx_api
|
||||
|
||||
|
||||
class TestMultisigChange(TrezorTest):
|
||||
|
||||
def setup_method(self, method):
|
||||
super(TestMultisigChange, self).setup_method(method)
|
||||
self.client.set_tx_api(tx_api.TxApiTestnet)
|
||||
self.client.set_tx_api(tx_api['Testnet'])
|
||||
|
||||
node_ext1 = bip32.deserialize('tpubDADHV9u9Y6gkggintTdMjJE3be58zKNLhpxBQyuEM6Pwx3sN9JVLmMCMN4DNVwL9AKec27z5TaWcWuHzMXiGAtcra5DjwWbvppGX4gaEGVN')
|
||||
# m/1 => 02c0d0c5fee952620757c6128dbf327c996cd72ed3358d15d6518a1186099bc15e
|
||||
|
@ -8,7 +8,7 @@ def test_nem_basic():
|
||||
"amount": 1000000,
|
||||
"fee": 1000000,
|
||||
"recipient": "TALICE2GMA34CXHD7XLJQ536NM5UNKQHTORNNT2J",
|
||||
"type": nem.TYPE_MOSAIC_TRANSFER,
|
||||
"type": nem.TYPE_TRANSACTION_TRANSFER,
|
||||
"deadline": 76895615,
|
||||
"version": (0x98 << 24),
|
||||
"message": {
|
||||
|
@ -18,8 +18,11 @@
|
||||
|
||||
import os
|
||||
|
||||
from trezorlib import coins
|
||||
from trezorlib import tx_api
|
||||
from trezorlib.tx_api import TxApiBitcoin, TxApiTestnet
|
||||
|
||||
TxApiBitcoin = coins.tx_api['Bitcoin']
|
||||
TxApiTestnet = coins.tx_api['Testnet']
|
||||
|
||||
tests_dir = os.path.dirname(os.path.abspath(__file__))
|
||||
|
||||
|
@ -115,4 +115,4 @@ def get_transport(path=None, prefix_search=False):
|
||||
if transports:
|
||||
return transports[0].find_by_path(path, prefix_search=prefix_search)
|
||||
|
||||
raise Exception("Unknown path prefix '%s'" % prefix)
|
||||
raise Exception("Could not find device by path: {}".format(path))
|
||||
|
@ -19,6 +19,7 @@
|
||||
import time
|
||||
import hid
|
||||
import os
|
||||
import sys
|
||||
|
||||
from ..protocol_v1 import ProtocolV1
|
||||
from ..protocol_v2 import ProtocolV2
|
||||
@ -39,7 +40,12 @@ class HidHandle:
|
||||
def open(self):
|
||||
if self.count == 0:
|
||||
self.handle = hid.device()
|
||||
self.handle.open_path(self.path)
|
||||
try:
|
||||
self.handle.open_path(self.path)
|
||||
except (IOError, OSError) as e:
|
||||
if sys.platform.startswith('linux'):
|
||||
e.args = e.args + ('Do you have udev rules installed? https://github.com/trezor/trezor-common/blob/master/udev/51-trezor.rules', )
|
||||
raise e
|
||||
self.handle.set_nonblocking(True)
|
||||
self.count += 1
|
||||
|
||||
|
@ -67,7 +67,6 @@ class UdpTransport(Transport):
|
||||
|
||||
@classmethod
|
||||
def enumerate(cls):
|
||||
devices = []
|
||||
default_path = '{}:{}'.format(cls.DEFAULT_HOST, cls.DEFAULT_PORT)
|
||||
try:
|
||||
return [cls._try_path(default_path)]
|
||||
|
@ -20,6 +20,7 @@ import time
|
||||
import os
|
||||
import atexit
|
||||
import usb1
|
||||
import sys
|
||||
|
||||
from ..protocol_v1 import ProtocolV1
|
||||
from ..protocol_v2 import ProtocolV2
|
||||
@ -46,7 +47,11 @@ class WebUsbHandle:
|
||||
if self.count == 0:
|
||||
self.handle = self.device.open()
|
||||
if self.handle is None:
|
||||
raise Exception('Cannot open device')
|
||||
if sys.platform.startswith('linux'):
|
||||
args = ('Do you have udev rules installed? https://github.com/trezor/trezor-common/blob/master/udev/51-trezor.rules', )
|
||||
else:
|
||||
args = ()
|
||||
raise IOError('Cannot open device', *args)
|
||||
self.handle.claimInterface(interface)
|
||||
self.count += 1
|
||||
|
||||
|
@ -115,40 +115,6 @@ class TxApiInsight(TxApi):
|
||||
return t
|
||||
|
||||
|
||||
class TxApiSmartbit(TxApi):
|
||||
|
||||
def get_tx(self, txhash):
|
||||
|
||||
data = self.fetch_json('tx', txhash)
|
||||
|
||||
data = data['transaction']
|
||||
|
||||
t = proto.TransactionType()
|
||||
t.version = int(data['version'])
|
||||
t.lock_time = data['locktime']
|
||||
|
||||
for vin in data['inputs']:
|
||||
i = t.inputs.add()
|
||||
if 'coinbase' in vin.keys():
|
||||
i.prev_hash = b"\0" * 32
|
||||
i.prev_index = 0xffffffff # signed int -1
|
||||
i.script_sig = binascii.unhexlify(vin['coinbase'])
|
||||
i.sequence = vin['sequence']
|
||||
|
||||
else:
|
||||
i.prev_hash = binascii.unhexlify(vin['txid'])
|
||||
i.prev_index = vin['vout']
|
||||
i.script_sig = binascii.unhexlify(vin['script_sig']['hex'])
|
||||
i.sequence = vin['sequence']
|
||||
|
||||
for vout in data['outputs']:
|
||||
o = t.bin_outputs.add()
|
||||
o.amount = int(Decimal(vout['value']) * 100000000)
|
||||
o.script_pubkey = binascii.unhexlify(vout['script_pub_key']['hex'])
|
||||
|
||||
return t
|
||||
|
||||
|
||||
class TxApiBlockCypher(TxApi):
|
||||
|
||||
def __init__(self, network, url, zcash=None):
|
||||
@ -182,16 +148,3 @@ class TxApiBlockCypher(TxApi):
|
||||
o.script_pubkey = binascii.unhexlify(vout['script'])
|
||||
|
||||
return t
|
||||
|
||||
|
||||
TxApiBitcoin = TxApiInsight(network='insight_bitcoin', url='https://btc-bitcore1.trezor.io/api/')
|
||||
TxApiTestnet = TxApiInsight(network='insight_testnet', url='https://testnet-bitcore3.trezor.io/api/')
|
||||
TxApiLitecoin = TxApiInsight(network='insight_litecoin', url='https://ltc-bitcore1.trezor.io/api/')
|
||||
TxApiDash = TxApiInsight(network='insight_dash', url='https://dash-bitcore1.trezor.io/api/')
|
||||
TxApiZcash = TxApiInsight(network='insight_zcash', url='https://zec-bitcore1.trezor.io/api/', zcash=True)
|
||||
TxApiBcash = TxApiInsight(network='insight_bcash', url='https://bch-bitcore2.trezor.io/api/')
|
||||
TxApiBitcoinGold = TxApiInsight(network='insight_bitcoin_gold', url='https://btg-bitcore2.trezor.io/api/')
|
||||
TxApiDecredTestnet = TxApiInsight(network='insight_decred_testnet', url='https://testnet.decred.org/api/')
|
||||
TxApiDogecoin = TxApiBlockCypher(network='blockcypher_dogecoin', url='https://api.blockcypher.com/v1/doge/main/')
|
||||
TxApiSegnet = TxApiSmartbit(network='smartbit_segnet', url='https://segnet-api.smartbit.com.au/v1/blockchain/')
|
||||
TxApiMonacoin = TxApiInsight(network='insight_monacoin', url='https://mona.insight.monaco-ex.org/insight-api-monacoin/')
|
||||
|
1
vendor/trezor-common
vendored
Submodule
1
vendor/trezor-common
vendored
Submodule
@ -0,0 +1 @@
|
||||
Subproject commit 9abe3a7c69000cc7ee3cda2ec940193fa9d62e6c
|
Loading…
Reference in New Issue
Block a user