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

Merge branch 'master' into matejcik/client-split

This commit is contained in:
matejcik 2018-08-06 16:13:04 +02:00
commit 2bb7088281
16 changed files with 481 additions and 138 deletions

View File

@ -1,17 +1,13 @@
python-trezor
=============
# python-trezor
[![image](https://travis-ci.org/trezor/python-trezor.svg?branch=master)](https://travis-ci.org/trezor/python-trezor)
[![image](https://badges.gitter.im/trezor/community.svg)](https://gitter.im/trezor/community)
[![image](https://travis-ci.org/trezor/python-trezor.svg?branch=master)](https://travis-ci.org/trezor/python-trezor) [![repology](https://repology.org/badge/tiny-repos/python:trezor.svg)](https://repology.org/metapackage/python:trezor) [![image](https://badges.gitter.im/trezor/community.svg)](https://gitter.im/trezor/community)
Python library and commandline client for communicating with TREZOR
Hardware Wallet
See <https://trezor.io> for more information
Install
-------
## Install
Python-trezor requires Python 3.3 or higher, and libusb 1.0. The easiest
way to install it is with `pip`. The rest of this guide assumes you have
@ -79,8 +75,7 @@ cd /usr/ports/security/py-trezor
make install clean
```
Command line client (trezorctl)
------------------------------
## Command line client (trezorctl)
The included `trezorctl` python script can perform various tasks such as
changing setting in the Trezor, signing transactions, retrieving account
@ -91,38 +86,35 @@ NOTE: An older version of the `trezorctl` command is [available for
Debian Stretch](https://packages.debian.org/en/stretch/python-trezor)
(and comes pre-installed on [Tails OS](https://tails.boum.org/)).
Python Library
--------------
## Python Library
You can use this python library to interact with a Bitcoin Trezor and
use its capabilities in your application. See examples here in the
[tools/](tools/) sub folder.
PIN Entering
------------
## PIN Entering
When you are asked for PIN, you have to enter scrambled PIN. Follow the
numbers shown on TREZOR display and enter the their positions using the
numeric keyboard mapping:
<table>
<tr><td>7<td>8<td>9
<tr><td>4<td>5<td>6
<tr><td>1<td>2<td>3
</table>
| | | |
|---|---|---|
| 7 | 8 | 9 |
| 4 | 5 | 6 |
| 1 | 2 | 3 |
Example: your PIN is **1234** and TREZOR is displaying the following:
<table>
<tr><td>2<td>8<td>3
<tr><td>5<td>4<td>6
<tr><td>7<td>9<td>1
</table>
| | | |
|---|---|---|
| 2 | 8 | 3 |
| 5 | 4 | 6 |
| 7 | 9 | 1 |
You have to enter: **3795**
Contributing
------------
## Contributing
Python-trezor pulls coins info and protobuf messages from
[trezor-common](https://github.com/trezor/trezor-common) repository. If

View File

@ -69,6 +69,7 @@ class PrebuildCommand(Command):
try:
proto_srcs = glob.glob(os.path.join(TREZOR_COMMON, "protob", "*.proto"))
subprocess.check_call([
sys.executable,
os.path.join(TREZOR_COMMON, "protob", "pb2py"),
"-o", os.path.join(CWD, "trezorlib", "messages"),
"-P", "..protobuf",

View File

@ -38,6 +38,7 @@ from trezorlib import messages as proto
from trezorlib import protobuf
from trezorlib import stellar
from trezorlib import tools
from trezorlib import ripple
class ChoiceType(click.Choice):
@ -575,6 +576,10 @@ def sign_tx(connect, coin):
sequence = click.prompt('Sequence Number to use (RBF opt-in enabled by default)', type=int, default=0xfffffffd)
script_type = click.prompt('Input type', type=CHOICE_INPUT_SCRIPT_TYPE, default=default_script_type(address_n))
script_type = script_type if isinstance(script_type, int) else CHOICE_INPUT_SCRIPT_TYPE.typemap[script_type]
if txapi.bip115:
prev_output = txapi.get_tx(binascii.hexlify(prev_hash).decode("utf-8")).bin_outputs[prev_index]
prev_blockhash = prev_output.block_hash
prev_blockheight = prev_output.block_height
inputs.append(proto.TxInputType(
address_n=address_n,
prev_hash=prev_hash,
@ -582,8 +587,15 @@ def sign_tx(connect, coin):
amount=amount,
script_type=script_type,
sequence=sequence,
prev_block_hash_bip115=prev_blockhash,
prev_block_height_bip115=prev_blockheight,
))
if txapi.bip115:
current_block_height = txapi.current_height()
block_height = current_block_height - 300 # Zencash recommendation for the better protection
block_hash = txapi.get_block_hash(block_height)
outputs = []
while True:
click.echo()
@ -603,6 +615,8 @@ def sign_tx(connect, coin):
address=address,
amount=amount,
script_type=script_type,
block_hash_bip115=block_hash[::-1], # Blockhash passed in reverse order
block_height_bip115=block_height
))
tx_version = click.prompt('Transaction version', type=int, default=2)
@ -1050,6 +1064,36 @@ def stellar_sign_transaction(connect, b64envelope, address, network_passphrase):
return base64.b64encode(resp.signature)
#
# Ripple functions
#
@cli.command(help='Get Ripple address')
@click.option('-n', '--address', required=True, help="BIP-32 path to key, e.g. m/44'/144'/0'/0/0")
@click.option('-d', '--show-display', is_flag=True)
@click.pass_obj
def ripple_get_address(connect, address, show_display):
client = connect()
address_n = tools.parse_path(address)
return ripple.get_address(client, address_n, show_display)
@cli.command(help='Sign Ripple transaction')
@click.option('-n', '--address', required=True, help="BIP-32 path to key, e.g. m/44'/144'/0'/0/0")
@click.option('-f', '--file', type=click.File('r'), default='-', help='Transaction in JSON format')
@click.pass_obj
def ripple_sign_tx(connect, address, file):
client = connect()
address_n = tools.parse_path(address)
msg = ripple.create_sign_tx_msg(json.load(file))
result = ripple.sign_tx(client, address_n, msg)
click.echo("Signature:")
click.echo(binascii.hexlify(result.signature))
click.echo()
click.echo("Serialized tx including the signature:")
click.echo(binascii.hexlify(result.serialized_tx))
#
# Main
#

View File

@ -39,8 +39,9 @@ def _insight_for_coin(coin):
if not url:
return None
zcash = coin['coin_name'].lower().startswith('zcash')
bip115 = coin['bip115']
network = 'insight_{}'.format(coin['coin_name'].lower().replace(' ', '_'))
return TxApiInsight(network=network, url=url, zcash=zcash)
return TxApiInsight(network=network, url=url, zcash=zcash, bip115=bip115)
# exported variables

59
trezorlib/ripple.py Normal file
View File

@ -0,0 +1,59 @@
# This file is part of the Trezor project.
#
# Copyright (C) 2012-2018 SatoshiLabs and contributors
#
# This library is free software: you can redistribute it and/or modify
# it under the terms of the GNU Lesser General Public License version 3
# as published by the Free Software Foundation.
#
# 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 License along with this library.
# If not, see <https://www.gnu.org/licenses/lgpl-3.0.html>.
import base64
import struct
from . import messages
from . import tools
from .client import field
from .client import expect
@field('address')
@expect(messages.RippleAddress)
def get_address(client, address_n, show_display=False):
return client.call(
messages.RippleGetAddress(
address_n=address_n, show_display=show_display))
@expect(messages.RippleSignedTx)
def sign_tx(client, address_n, msg: messages.RippleSignTx):
msg.address_n = address_n
return client.call(msg)
def create_sign_tx_msg(transaction) -> messages.RippleSignTx:
if not all(transaction.get(k) for k in ("Fee", "Sequence", "TransactionType", "Amount", "Destination")):
raise ValueError("Some of the required fields missing (Fee, Sequence, TransactionType, Amount, Destination")
if transaction["TransactionType"] != "Payment":
raise ValueError("Only Payment transaction type is supported")
return messages.RippleSignTx(
fee=transaction.get("Fee"),
sequence=transaction.get("Sequence"),
flags=transaction.get("Flags"),
last_ledger_sequence=transaction.get("LastLedgerSequence"),
payment=_create_payment(transaction),
)
def _create_payment(transaction) -> messages.RipplePayment:
return messages.RipplePayment(
amount=transaction.get("Amount"),
destination=transaction.get("Destination")
)

View File

@ -83,9 +83,7 @@ def parse_transaction_bytes(tx_bytes):
tx - a StellarSignTx describing the transaction header
operations - an array of protobuf message objects for each operation
"""
tx = messages.StellarSignTx(
protocol_version=1
)
tx = messages.StellarSignTx()
unpacker = xdrlib.Unpacker(tx_bytes)
tx.source_account = _xdr_read_address(unpacker)

View File

@ -287,100 +287,3 @@ class TestMsgEthereumSigntx(TrezorTest):
to=unhexlify('1d1c328764a41bda0492b66baa30c4a339ff85ef'),
value=12345678901234567890
)
def test_ethereum_signtx_nodata_eip155(self):
self.setup_mnemonic_allallall()
with self.client:
self.client.set_expected_responses([
proto.ButtonRequest(code=proto.ButtonRequestType.SignTx),
proto.ButtonRequest(code=proto.ButtonRequestType.SignTx),
proto.EthereumTxRequest(),
])
sig_v, sig_r, sig_s = self.client.ethereum_sign_tx(
n=[0x80000000 | 44, 0x80000000 | 1, 0x80000000, 0, 0],
nonce=0,
gas_price=20000000000,
gas_limit=21000,
to=unhexlify('8ea7a3fccc211ed48b763b4164884ddbcf3b0a98'),
value=100000000000000000,
chain_id=3)
assert sig_v == 41
assert hexlify(sig_r) == b'a90d0bc4f8d63be69453dd62f2bb5fff53c610000abf956672564d8a654d401a'
assert hexlify(sig_s) == b'544a2e57bc8b4da18660a1e6036967ea581cc635f5137e3ba97a750867c27cf2'
sig_v, sig_r, sig_s = self.client.ethereum_sign_tx(
n=[0x80000000 | 44, 0x80000000 | 1, 0x80000000, 0, 0],
nonce=1,
gas_price=20000000000,
gas_limit=21000,
to=unhexlify('8ea7a3fccc211ed48b763b4164884ddbcf3b0a98'),
value=100000000000000000,
chain_id=3)
assert sig_v == 42
assert hexlify(sig_r) == b'699428a6950e23c6843f1bf3754f847e64e047e829978df80d55187d19a401ce'
assert hexlify(sig_s) == b'087343d0a3a2f10842218ffccb146b59a8431b6245ab389fde22dc833f171e6e'
def test_ethereum_signtx_data_eip155(self):
self.setup_mnemonic_allallall()
with self.client:
self.client.set_expected_responses([
proto.ButtonRequest(code=proto.ButtonRequestType.SignTx),
proto.ButtonRequest(code=proto.ButtonRequestType.SignTx),
proto.ButtonRequest(code=proto.ButtonRequestType.SignTx),
proto.EthereumTxRequest(),
])
sig_v, sig_r, sig_s = self.client.ethereum_sign_tx(
n=[0x80000000 | 44, 0x80000000 | 1, 0x80000000, 0, 0],
nonce=2,
gas_price=20000000000,
gas_limit=21004,
to=unhexlify('8ea7a3fccc211ed48b763b4164884ddbcf3b0a98'),
value=100000000000000000,
data=b'\0',
chain_id=3)
assert sig_v == 42
assert hexlify(sig_r) == b'ba85b622a8bb82606ba96c132e81fa8058172192d15bc41d7e57c031bca17df4'
assert hexlify(sig_s) == b'6473b75997634b6f692f8d672193591d299d5bf1c2d6e51f1a14ed0530b91c7d'
sig_v, sig_r, sig_s = self.client.ethereum_sign_tx(
n=[0x80000000 | 44, 0x80000000 | 1, 0x80000000, 0, 0],
nonce=3,
gas_price=20000000000,
gas_limit=299732,
to=unhexlify('8ea7a3fccc211ed48b763b4164884ddbcf3b0a98'),
value=100000000000000000,
data=b'ABCDEFGHIJKLMNOP' * 256 + b'!!!',
chain_id=3)
assert sig_v == 42
assert hexlify(sig_r) == b'd021c98f92859c8db5e4de2f0e410a8deb0c977eb1a631e323ebf7484bd0d79a'
assert hexlify(sig_s) == b'2c0e9defc9b1e895dc9520ff25ba3c635b14ad70aa86a5ad6c0a3acb82b569b6'
sig_v, sig_r, sig_s = self.client.ethereum_sign_tx(
n=[0x80000000 | 44, 0x80000000 | 1, 0x80000000, 0, 0],
nonce=4,
gas_price=20000000000,
gas_limit=21004,
to=unhexlify('8ea7a3fccc211ed48b763b4164884ddbcf3b0a98'),
value=0,
data=b'\0',
chain_id=3)
assert sig_v == 42
assert hexlify(sig_r) == b'dd52f026972a83c56b7dea356836fcfc70a68e3b879cdc8ef2bb5fea23e0a7aa'
assert hexlify(sig_s) == b'079285fe579c9a2da25c811b1c5c0a74cd19b6301ee42cf20ef7b3b1353f7242'
sig_v, sig_r, sig_s = self.client.ethereum_sign_tx(
n=[0x80000000 | 44, 0x80000000 | 1, 0x80000000, 0, 0],
nonce=5,
gas_price=0,
gas_limit=21004,
to=unhexlify('8ea7a3fccc211ed48b763b4164884ddbcf3b0a98'),
value=0,
data=b'\0',
chain_id=3)
assert sig_v == 42
assert hexlify(sig_r) == b'f7505f709d5999343aea3c384034c62d0514336ff6c6af65582006f708f81503'
assert hexlify(sig_s) == b'44e09e29a4b6247000b46ddc94fe391e94deb2b39ad6ac6398e6db5bec095ba9'

View File

@ -0,0 +1,177 @@
# This file is part of the Trezor project.
#
# Copyright (C) 2012-2018 SatoshiLabs and contributors
#
# This library is free software: you can redistribute it and/or modify
# it under the terms of the GNU Lesser General Public License version 3
# as published by the Free Software Foundation.
#
# 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 License along with this library.
# If not, see <https://www.gnu.org/licenses/lgpl-3.0.html>.
from binascii import unhexlify, hexlify
import pytest
from .common import TrezorTest
from trezorlib import messages as proto
@pytest.mark.ethereum
class TestMsgEthereumSigntxChainId(TrezorTest):
def test_ethereum_signtx_eip155(self):
# chain_id, nonce, sig_v, sig_r, sig_s, value, gas_limit, data
VECTORS = [
(
3,
0,
41,
b"a90d0bc4f8d63be69453dd62f2bb5fff53c610000abf956672564d8a654d401a",
b"544a2e57bc8b4da18660a1e6036967ea581cc635f5137e3ba97a750867c27cf2",
100000000000000000,
21000,
None,
),
(
3,
1,
42,
b"699428a6950e23c6843f1bf3754f847e64e047e829978df80d55187d19a401ce",
b"087343d0a3a2f10842218ffccb146b59a8431b6245ab389fde22dc833f171e6e",
100000000000000000,
21000,
None,
),
(
3,
2,
42,
b"ba85b622a8bb82606ba96c132e81fa8058172192d15bc41d7e57c031bca17df4",
b"6473b75997634b6f692f8d672193591d299d5bf1c2d6e51f1a14ed0530b91c7d",
100000000000000000,
21004,
b"\0",
),
(
3,
3,
42,
b"d021c98f92859c8db5e4de2f0e410a8deb0c977eb1a631e323ebf7484bd0d79a",
b"2c0e9defc9b1e895dc9520ff25ba3c635b14ad70aa86a5ad6c0a3acb82b569b6",
100000000000000000,
299732,
b"ABCDEFGHIJKLMNOP" * 256 + b"!!!",
),
(
3,
4,
42,
b"dd52f026972a83c56b7dea356836fcfc70a68e3b879cdc8ef2bb5fea23e0a7aa",
b"079285fe579c9a2da25c811b1c5c0a74cd19b6301ee42cf20ef7b3b1353f7242",
0,
21004,
b"\0",
),
(
1,
1,
37,
b"bae6198fdc87ccad6256e543617a34d052bfd17ae3be0bec7fbf8ea34bf9c930",
b"7d12f625f3e54700b6ed14ab669f45a8a2b5552c39f0781b0ab3796f19e6b4d1",
0,
21004,
b"\0",
),
(
255,
1,
546,
b"7597a40719509ae3850d2eba808b7b2f7d272fda316e1321e5ebcc911e9f1b0d",
b"269dd69248273820f65b43d8824bb7aff1aa4e35ee663a5433a5df8f0c47dc31",
0,
21004,
b"\0",
),
(
256,
1,
547,
b"64e9821db2001ff5dff13c9d8c7fb0701ff860f5f95155d378fb9fcc06088f28",
b"4d03f339afed717e2155f044a6b0a895b5ac98343f1745e7525870c2046c36bc",
0,
21004,
b"\0",
),
(
65535,
1,
131106,
b"6f2275808dc328184d7aa019d0a68f8dd8234969576a477670934145bb358969",
b"2be1ff9045bccff9ba3d6d5c7789a52c52c9679526dd3ec349caa318c3d055ff",
0,
21004,
b"\0",
),
(
65536,
1,
131107,
b"e16e35afe534a46e3e4cf09f355cbf02edc01937c2b444238162c2aca79037b8",
b"1083b84e21b1cbad95c7ea9792818c18fa716aa25951c5341b48732d611a396a",
0,
21004,
b"\0",
),
(
16777215,
1,
33554466,
b"f9753ee68cf2af20638cc753945d157039504f82d6d6fe0ec98806b64366c551",
b"056b57a69d88a4b71fba993c580d8bbf04f2c857f97a8b7d4b2892b5dafa9114",
0,
21004,
b"\0",
),
(
16777216,
1,
33554468,
b"23a5399650c6efa46a25a0a966a29119830d9c587b6b93da43cb0be6d3c69059",
b"5a6eddffc62317a6a3801608071655a9c43423aef9705b2f5df4212942265c37",
0,
21004,
b"\0",
),
(
2147483629,
1,
4294967294,
b"6a996586f1ea19afe9cb0ca44dec6bb8643cdf53b5cf148323c94a32a04b087d",
b"0d086b208df6826657edf98010972b2649b323466a7ea4b67e7285fb9e829481",
0,
21004,
b"\0",
),
]
self.setup_mnemonic_allallall()
for ci, n, sv, sr, ss, v, gl, d in VECTORS:
sig_v, sig_r, sig_s = self.client.ethereum_sign_tx(
n=[0x80000000 | 44, 0x80000000 | 1, 0x80000000, 0, 0],
nonce=n,
gas_price=20000000000,
gas_limit=gl,
to=unhexlify("8ea7a3fccc211ed48b763b4164884ddbcf3b0a98"),
value=v,
chain_id=ci,
data=d,
)
assert sig_v == sv
assert hexlify(sig_r) == sr
assert hexlify(sig_s) == ss

View File

@ -0,0 +1,54 @@
# This file is part of the Trezor project.
#
# Copyright (C) 2012-2018 SatoshiLabs and contributors
#
# This library is free software: you can redistribute it and/or modify
# it under the terms of the GNU Lesser General Public License version 3
# as published by the Free Software Foundation.
#
# 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 License along with this library.
# If not, see <https://www.gnu.org/licenses/lgpl-3.0.html>.
import pytest
from .common import TrezorTest
from .conftest import TREZOR_VERSION
from binascii import hexlify
from trezorlib.client import CallException
from trezorlib.ripple import get_address
from trezorlib.tools import parse_path
@pytest.mark.ripple
@pytest.mark.skip_t1 # T1 support is not planned
@pytest.mark.xfail(TREZOR_VERSION == 2, reason="T2 support is not yet finished")
class TestMsgRippleGetAddress(TrezorTest):
def test_ripple_get_address(self):
# data from https://iancoleman.io/bip39/#english
self.setup_mnemonic_allallall()
address = get_address(self.client, parse_path("m/44'/144'/0'/0/0"))
assert address == 'rNaqKtKrMSwpwZSzRckPf7S96DkimjkF4H'
address = get_address(self.client, parse_path("m/44'/144'/0'/0/1"))
assert address == 'rBKz5MC2iXdoS3XgnNSYmF69K1Yo4NS3Ws'
address = get_address(self.client, parse_path("m/44'/144'/1'/0/0"))
assert address == 'rJX2KwzaLJDyFhhtXKi3htaLfaUH2tptEX'
def test_ripple_get_address_other(self):
# data from https://github.com/you21979/node-ripple-bip32/blob/master/test/test.js
self.client.load_device_by_mnemonic(
mnemonic='armed bundle pudding lazy strategy impulse where identify submit weekend physical antenna flight social acoustic absurd whip snack decide blur unfold fiction pumpkin athlete',
pin='',
passphrase_protection=False,
label='test',
language='english')
address = get_address(self.client, parse_path("m/44'/144'/0'/0/0"))
assert address == 'r4ocGE47gm4G4LkA9mriVHQqzpMLBTgnTY'
address = get_address(self.client, parse_path("m/44'/144'/0'/0/1"))
assert address == 'rUt9ULSrUvfCmke8HTFU1szbmFpWzVbBXW'

View File

@ -0,0 +1,86 @@
# This file is part of the Trezor project.
#
# Copyright (C) 2012-2018 SatoshiLabs and contributors
#
# This library is free software: you can redistribute it and/or modify
# it under the terms of the GNU Lesser General Public License version 3
# as published by the Free Software Foundation.
#
# 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 License along with this library.
# If not, see <https://www.gnu.org/licenses/lgpl-3.0.html>.
import pytest
from .common import TrezorTest
from .conftest import TREZOR_VERSION
from binascii import unhexlify
from trezorlib import messages
from trezorlib import ripple
from trezorlib.client import CallException
from trezorlib.tools import parse_path
@pytest.mark.ripple
@pytest.mark.skip_t1 # T1 support is not planned
@pytest.mark.xfail(TREZOR_VERSION == 2, reason="T2 support is not yet finished")
class TestMsgRippleSignTx(TrezorTest):
def test_ripple_sign_simple_tx(self):
self.setup_mnemonic_allallall()
msg = ripple.create_sign_tx_msg({
"TransactionType": "Payment",
"Destination": "rBKz5MC2iXdoS3XgnNSYmF69K1Yo4NS3Ws",
"Amount": 100000000,
"Flags": 0x80000000,
"Fee": 100000,
"Sequence": 25,
})
resp = ripple.sign_tx(self.client, parse_path("m/44'/144'/0'/0/0"), msg)
assert resp.signature == unhexlify('3045022100e243ef623675eeeb95965c35c3e06d63a9fc68bb37e17dc87af9c0af83ec057e02206ca8aa5eaab8396397aef6d38d25710441faf7c79d292ee1d627df15ad9346c0')
assert resp.serialized_tx == unhexlify('12000022800000002400000019614000000005f5e1006840000000000186a0732102131facd1eab748d6cddc492f54b04e8c35658894f4add2232ebc5afe7521dbe474473045022100e243ef623675eeeb95965c35c3e06d63a9fc68bb37e17dc87af9c0af83ec057e02206ca8aa5eaab8396397aef6d38d25710441faf7c79d292ee1d627df15ad9346c081148fb40e1ffa5d557ce9851a535af94965e0dd098883147148ebebf7304ccdf1676fefcf9734cf1e780826')
msg = ripple.create_sign_tx_msg({
"TransactionType": "Payment",
"Destination": "rNaqKtKrMSwpwZSzRckPf7S96DkimjkF4H",
"Amount": 1,
"Fee": 10,
"Sequence": 1,
})
resp = ripple.sign_tx(self.client, parse_path("m/44'/144'/0'/0/2"), msg)
assert resp.signature == unhexlify('3044022069900e6e578997fad5189981b74b16badc7ba8b9f1052694033fa2779113ddc002206c8006ada310edf099fb22c0c12073550c8fc73247b236a974c5f1144831dd5f')
assert resp.serialized_tx == unhexlify('1200002280000000240000000161400000000000000168400000000000000a732103dbed1e77cb91a005e2ec71afbccce5444c9be58276665a3859040f692de8fed274463044022069900e6e578997fad5189981b74b16badc7ba8b9f1052694033fa2779113ddc002206c8006ada310edf099fb22c0c12073550c8fc73247b236a974c5f1144831dd5f8114bdf86f3ae715ba346b7772ea0e133f48828b766483148fb40e1ffa5d557ce9851a535af94965e0dd0988')
msg = ripple.create_sign_tx_msg({
"TransactionType": "Payment",
"Destination": "rNaqKtKrMSwpwZSzRckPf7S96DkimjkF4H",
"Amount": 100000009,
"Flags": 0,
"Fee": 100,
"Sequence": 100,
"LastLedgerSequence": 333111,
})
resp = ripple.sign_tx(self.client, parse_path("m/44'/144'/0'/0/2"), msg)
assert resp.signature == unhexlify('30440220025a9cc2809527799e6ea5eb029488dc46c6632a8ca1ed7d3ca2d9211e80403a02202cfe8604e6c6d1d3c64246626cc1a1a9bd8a2163b969e561c6adda5dca8fc2a5')
assert resp.serialized_tx == unhexlify('12000022800000002400000064201b00051537614000000005f5e109684000000000000064732103dbed1e77cb91a005e2ec71afbccce5444c9be58276665a3859040f692de8fed2744630440220025a9cc2809527799e6ea5eb029488dc46c6632a8ca1ed7d3ca2d9211e80403a02202cfe8604e6c6d1d3c64246626cc1a1a9bd8a2163b969e561c6adda5dca8fc2a58114bdf86f3ae715ba346b7772ea0e133f48828b766483148fb40e1ffa5d557ce9851a535af94965e0dd0988')
def test_ripple_sign_invalid_fee(self):
self.setup_mnemonic_allallall()
msg = ripple.create_sign_tx_msg({
"TransactionType": "Payment",
"Destination": "rNaqKtKrMSwpwZSzRckPf7S96DkimjkF4H",
"Amount": 1,
"Flags": 1,
"Fee": 1,
"Sequence": 1,
})
with pytest.raises(CallException) as exc:
ripple.sign_tx(self.client, parse_path("m/44'/144'/0'/0/2"), msg)
assert exc.value.args[0] == messages.FailureType.ProcessError
assert exc.value.args[1].endswith('Fee must be in the range of 10 to 10,000 drops')

View File

@ -26,7 +26,6 @@ from trezorlib.tools import parse_path
@pytest.mark.stellar
@pytest.mark.xfail(TREZOR_VERSION == 2, reason="T2 support is not yet finished")
class TestMsgStellarGetAddress(TrezorTest):
def test_stellar_get_address(self):
@ -47,7 +46,7 @@ class TestMsgStellarGetAddress(TrezorTest):
address = self.client.stellar_get_address(parse_path(stellar.DEFAULT_BIP32_PATH))
assert address == 'GDRXE2BQUC3AZNPVFSCEZ76NJ3WWL25FYFK6RGZGIEKWE4SOOHSUJUJ6'
address = self.client.stellar_get_address(parse_path("m/44h/148h/1h"))
address = self.client.stellar_get_address(parse_path("m/44h/148h/1h"), show_display=True)
assert address == 'GBAW5XGWORWVFE2XTJYDTLDHXTY2Q2MO73HYCGB3XMFMQ562Q2W2GJQX'
def test_stellar_get_address_get_pubkey(self):

View File

@ -20,20 +20,19 @@ from .common import TrezorTest
from .conftest import TREZOR_VERSION
from binascii import hexlify
from trezorlib import stellar
from trezorlib import messages as proto
from trezorlib import messages
from trezorlib.client import CallException
from trezorlib.tools import parse_path
@pytest.mark.stellar
@pytest.mark.xfail(TREZOR_VERSION == 2, reason="T2 support is not yet finished")
class TestMsgStellarGetPublicKey(TrezorTest):
def test_stellar_get_public_key(self):
self.setup_mnemonic_nopin_nopassphrase()
# GAK5MSF74TJW6GLM7NLTL76YZJKM2S4CGP3UH4REJHPHZ4YBZW2GSBPW
response = self.client.stellar_get_public_key(parse_path(stellar.DEFAULT_BIP32_PATH))
response = self.client.stellar_get_public_key(parse_path(stellar.DEFAULT_BIP32_PATH), show_display=True)
assert hexlify(response) == b'15d648bfe4d36f196cfb5735ffd8ca54cd4b8233f743f22449de7cf301cdb469'
assert stellar.address_from_public_key(response) == 'GAK5MSF74TJW6GLM7NLTL76YZJKM2S4CGP3UH4REJHPHZ4YBZW2GSBPW'
@ -44,8 +43,8 @@ class TestMsgStellarGetPublicKey(TrezorTest):
self.client.stellar_get_public_key(parse_path('m/0/1'))
if TREZOR_VERSION == 1:
assert exc.value.args[0] == proto.FailureType.ProcessError
assert exc.value.args[0] == messages.FailureType.ProcessError
assert exc.value.args[1].endswith('Failed to derive private key')
else:
assert exc.value.args[0] == proto.FailureType.FirmwareError
assert exc.value.args[0] == messages.FailureType.FirmwareError
assert exc.value.args[1].endswith('Firmware error')

View File

@ -57,7 +57,6 @@ import pytest
@pytest.mark.stellar
@pytest.mark.xfail(TREZOR_VERSION == 2, reason="T2 support is not yet finished")
class TestMsgStellarSignTransaction(TrezorTest):
ADDRESS_N = parse_path(stellar.DEFAULT_BIP32_PATH)
@ -158,7 +157,6 @@ class TestMsgStellarSignTransaction(TrezorTest):
def _create_msg(self) -> proto.StellarSignTx:
tx = proto.StellarSignTx()
tx.protocol_version = 1
tx.source_account = 'GAK5MSF74TJW6GLM7NLTL76YZJKM2S4CGP3UH4REJHPHZ4YBZW2GSBPW'
tx.fee = 100
tx.sequence_number = 0x100000000

View File

@ -18,9 +18,11 @@ import os
from trezorlib import coins
from trezorlib import tx_api
import binascii
TxApiBitcoin = coins.tx_api['Bitcoin']
TxApiTestnet = tx_api.TxApiInsight("insight_testnet")
TxApiZencash = coins.tx_api['Zencash']
tests_dir = os.path.dirname(os.path.abspath(__file__))
@ -42,3 +44,13 @@ def test_tx_api_gettx():
TxApiTestnet.get_tx('6f90f3c7cbec2258b0971056ef3fe34128dbde30daa9c0639a898f9977299d54')
TxApiTestnet.get_tx('d6da21677d7cca5f42fbc7631d062c9ae918a0254f7c6c22de8e8cb7fd5b8236')
def test_tx_api_current_block():
height = TxApiZencash.current_height()
assert height > 347041
def test_tx_api_get_block_hash():
hash = TxApiZencash.get_block_hash(110000)
assert hash == binascii.unhexlify('000000003f5d6ba1385c6cd2d4f836dfc5adf7f98834309ad67e26faef462454')

View File

@ -33,6 +33,18 @@ class TxApi(object):
url = '%s%s/%s' % (self.url, resource, resourceid)
return url
def current_height(self):
r = requests.get(self.url + '/status?q=getBlockCount')
j = r.json(parse_float=str)
block_height = j['info']['blocks']
return block_height
def get_block_hash(self, block_number):
r = requests.get(self.url + '/block-index/' + str(block_number))
j = r.json(parse_float=str)
block_hash = binascii.unhexlify(j['blockHash'])
return block_hash
def fetch_json(self, resource, resourceid):
global cache_dir
if cache_dir:
@ -65,11 +77,13 @@ class TxApi(object):
class TxApiInsight(TxApi):
def __init__(self, network, url=None, zcash=None):
def __init__(self, network, url=None, zcash=None, bip115=False):
super().__init__(network, url)
self.zcash = zcash
self.bip115 = bip115
if url:
self.pushtx_url = url.replace('/api/', '/tx/send')
prefix, suffix = url.rsplit('/', maxsplit=1)
self.pushtx_url = prefix + '/tx/send'
def get_tx(self, txhash):
@ -97,6 +111,12 @@ class TxApiInsight(TxApi):
o = t._add_bin_outputs()
o.amount = int(Decimal(vout['value']) * 100000000)
o.script_pubkey = binascii.unhexlify(vout['scriptPubKey']['hex'])
if self.bip115 and o.script_pubkey[-1] == 0xb4:
# Verify if coin implements replay protection bip115 and script includes checkblockatheight opcode. 0xb4 - is op_code (OP_CHECKBLOCKATHEIGHT)
# <OP_32> <32-byte block hash> <OP_3> <3-byte block height> <OP_CHECKBLOCKATHEIGHT>
tail = o.script_pubkey[-38:]
o.block_hash = tail[1:33] # <32-byte block hash>
o.block_height = int.from_bytes(tail[34:37], byteorder='little') # <3-byte block height>
if self.zcash:
t.overwintered = data.get('fOverwintered', False)

@ -1 +1 @@
Subproject commit 2301f7034c1b7a3d1b0be5d4447d432593649a1e
Subproject commit 32850a62624ce1a6612ff545beb706560c3716da