mirror of
https://github.com/trezor/trezor-firmware.git
synced 2025-07-12 09:38:08 +00:00
Merge branch 'master' into matejcik/client-split
This commit is contained in:
commit
2bb7088281
42
README.md
42
README.md
@ -1,17 +1,13 @@
|
|||||||
python-trezor
|
# python-trezor
|
||||||
=============
|
|
||||||
|
|
||||||
[](https://travis-ci.org/trezor/python-trezor)
|
[](https://travis-ci.org/trezor/python-trezor) [](https://repology.org/metapackage/python:trezor) [](https://gitter.im/trezor/community)
|
||||||
|
|
||||||
[](https://gitter.im/trezor/community)
|
|
||||||
|
|
||||||
Python library and commandline client for communicating with TREZOR
|
Python library and commandline client for communicating with TREZOR
|
||||||
Hardware Wallet
|
Hardware Wallet
|
||||||
|
|
||||||
See <https://trezor.io> for more information
|
See <https://trezor.io> for more information
|
||||||
|
|
||||||
Install
|
## Install
|
||||||
-------
|
|
||||||
|
|
||||||
Python-trezor requires Python 3.3 or higher, and libusb 1.0. The easiest
|
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
|
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
|
make install clean
|
||||||
```
|
```
|
||||||
|
|
||||||
Command line client (trezorctl)
|
## Command line client (trezorctl)
|
||||||
------------------------------
|
|
||||||
|
|
||||||
The included `trezorctl` python script can perform various tasks such as
|
The included `trezorctl` python script can perform various tasks such as
|
||||||
changing setting in the Trezor, signing transactions, retrieving account
|
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)
|
Debian Stretch](https://packages.debian.org/en/stretch/python-trezor)
|
||||||
(and comes pre-installed on [Tails OS](https://tails.boum.org/)).
|
(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
|
You can use this python library to interact with a Bitcoin Trezor and
|
||||||
use its capabilities in your application. See examples here in the
|
use its capabilities in your application. See examples here in the
|
||||||
[tools/](tools/) sub folder.
|
[tools/](tools/) sub folder.
|
||||||
|
|
||||||
PIN Entering
|
## PIN Entering
|
||||||
------------
|
|
||||||
|
|
||||||
When you are asked for PIN, you have to enter scrambled PIN. Follow the
|
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
|
numbers shown on TREZOR display and enter the their positions using the
|
||||||
numeric keyboard mapping:
|
numeric keyboard mapping:
|
||||||
|
|
||||||
<table>
|
| | | |
|
||||||
<tr><td>7<td>8<td>9
|
|---|---|---|
|
||||||
<tr><td>4<td>5<td>6
|
| 7 | 8 | 9 |
|
||||||
<tr><td>1<td>2<td>3
|
| 4 | 5 | 6 |
|
||||||
</table>
|
| 1 | 2 | 3 |
|
||||||
|
|
||||||
Example: your PIN is **1234** and TREZOR is displaying the following:
|
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
|
| 2 | 8 | 3 |
|
||||||
<tr><td>7<td>9<td>1
|
| 5 | 4 | 6 |
|
||||||
</table>
|
| 7 | 9 | 1 |
|
||||||
|
|
||||||
You have to enter: **3795**
|
You have to enter: **3795**
|
||||||
|
|
||||||
Contributing
|
## Contributing
|
||||||
------------
|
|
||||||
|
|
||||||
Python-trezor pulls coins info and protobuf messages from
|
Python-trezor pulls coins info and protobuf messages from
|
||||||
[trezor-common](https://github.com/trezor/trezor-common) repository. If
|
[trezor-common](https://github.com/trezor/trezor-common) repository. If
|
||||||
|
1
setup.py
1
setup.py
@ -69,6 +69,7 @@ class PrebuildCommand(Command):
|
|||||||
try:
|
try:
|
||||||
proto_srcs = glob.glob(os.path.join(TREZOR_COMMON, "protob", "*.proto"))
|
proto_srcs = glob.glob(os.path.join(TREZOR_COMMON, "protob", "*.proto"))
|
||||||
subprocess.check_call([
|
subprocess.check_call([
|
||||||
|
sys.executable,
|
||||||
os.path.join(TREZOR_COMMON, "protob", "pb2py"),
|
os.path.join(TREZOR_COMMON, "protob", "pb2py"),
|
||||||
"-o", os.path.join(CWD, "trezorlib", "messages"),
|
"-o", os.path.join(CWD, "trezorlib", "messages"),
|
||||||
"-P", "..protobuf",
|
"-P", "..protobuf",
|
||||||
|
44
trezorctl
44
trezorctl
@ -38,6 +38,7 @@ from trezorlib import messages as proto
|
|||||||
from trezorlib import protobuf
|
from trezorlib import protobuf
|
||||||
from trezorlib import stellar
|
from trezorlib import stellar
|
||||||
from trezorlib import tools
|
from trezorlib import tools
|
||||||
|
from trezorlib import ripple
|
||||||
|
|
||||||
|
|
||||||
class ChoiceType(click.Choice):
|
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)
|
sequence = click.prompt('Sequence Number to use (RBF opt-in enabled by default)', type=int, default=0xfffffffd)
|
||||||
script_type = click.prompt('Input type', type=CHOICE_INPUT_SCRIPT_TYPE, default=default_script_type(address_n))
|
script_type = click.prompt('Input type', type=CHOICE_INPUT_SCRIPT_TYPE, default=default_script_type(address_n))
|
||||||
script_type = script_type if isinstance(script_type, int) else CHOICE_INPUT_SCRIPT_TYPE.typemap[script_type]
|
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(
|
inputs.append(proto.TxInputType(
|
||||||
address_n=address_n,
|
address_n=address_n,
|
||||||
prev_hash=prev_hash,
|
prev_hash=prev_hash,
|
||||||
@ -582,8 +587,15 @@ def sign_tx(connect, coin):
|
|||||||
amount=amount,
|
amount=amount,
|
||||||
script_type=script_type,
|
script_type=script_type,
|
||||||
sequence=sequence,
|
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 = []
|
outputs = []
|
||||||
while True:
|
while True:
|
||||||
click.echo()
|
click.echo()
|
||||||
@ -603,6 +615,8 @@ def sign_tx(connect, coin):
|
|||||||
address=address,
|
address=address,
|
||||||
amount=amount,
|
amount=amount,
|
||||||
script_type=script_type,
|
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)
|
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)
|
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
|
# Main
|
||||||
#
|
#
|
||||||
|
@ -39,8 +39,9 @@ def _insight_for_coin(coin):
|
|||||||
if not url:
|
if not url:
|
||||||
return None
|
return None
|
||||||
zcash = coin['coin_name'].lower().startswith('zcash')
|
zcash = coin['coin_name'].lower().startswith('zcash')
|
||||||
|
bip115 = coin['bip115']
|
||||||
network = 'insight_{}'.format(coin['coin_name'].lower().replace(' ', '_'))
|
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
|
# exported variables
|
||||||
|
59
trezorlib/ripple.py
Normal file
59
trezorlib/ripple.py
Normal 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")
|
||||||
|
)
|
@ -83,9 +83,7 @@ def parse_transaction_bytes(tx_bytes):
|
|||||||
tx - a StellarSignTx describing the transaction header
|
tx - a StellarSignTx describing the transaction header
|
||||||
operations - an array of protobuf message objects for each operation
|
operations - an array of protobuf message objects for each operation
|
||||||
"""
|
"""
|
||||||
tx = messages.StellarSignTx(
|
tx = messages.StellarSignTx()
|
||||||
protocol_version=1
|
|
||||||
)
|
|
||||||
unpacker = xdrlib.Unpacker(tx_bytes)
|
unpacker = xdrlib.Unpacker(tx_bytes)
|
||||||
|
|
||||||
tx.source_account = _xdr_read_address(unpacker)
|
tx.source_account = _xdr_read_address(unpacker)
|
||||||
|
@ -287,100 +287,3 @@ class TestMsgEthereumSigntx(TrezorTest):
|
|||||||
to=unhexlify('1d1c328764a41bda0492b66baa30c4a339ff85ef'),
|
to=unhexlify('1d1c328764a41bda0492b66baa30c4a339ff85ef'),
|
||||||
value=12345678901234567890
|
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'
|
|
||||||
|
177
trezorlib/tests/device_tests/test_msg_ethereum_signtx_eip155.py
Normal file
177
trezorlib/tests/device_tests/test_msg_ethereum_signtx_eip155.py
Normal 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
|
54
trezorlib/tests/device_tests/test_msg_ripple_get_address.py
Normal file
54
trezorlib/tests/device_tests/test_msg_ripple_get_address.py
Normal 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'
|
86
trezorlib/tests/device_tests/test_msg_ripple_sign_tx.py
Normal file
86
trezorlib/tests/device_tests/test_msg_ripple_sign_tx.py
Normal 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')
|
@ -26,7 +26,6 @@ from trezorlib.tools import parse_path
|
|||||||
|
|
||||||
|
|
||||||
@pytest.mark.stellar
|
@pytest.mark.stellar
|
||||||
@pytest.mark.xfail(TREZOR_VERSION == 2, reason="T2 support is not yet finished")
|
|
||||||
class TestMsgStellarGetAddress(TrezorTest):
|
class TestMsgStellarGetAddress(TrezorTest):
|
||||||
|
|
||||||
def test_stellar_get_address(self):
|
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))
|
address = self.client.stellar_get_address(parse_path(stellar.DEFAULT_BIP32_PATH))
|
||||||
assert address == 'GDRXE2BQUC3AZNPVFSCEZ76NJ3WWL25FYFK6RGZGIEKWE4SOOHSUJUJ6'
|
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'
|
assert address == 'GBAW5XGWORWVFE2XTJYDTLDHXTY2Q2MO73HYCGB3XMFMQ562Q2W2GJQX'
|
||||||
|
|
||||||
def test_stellar_get_address_get_pubkey(self):
|
def test_stellar_get_address_get_pubkey(self):
|
||||||
|
@ -20,20 +20,19 @@ from .common import TrezorTest
|
|||||||
from .conftest import TREZOR_VERSION
|
from .conftest import TREZOR_VERSION
|
||||||
from binascii import hexlify
|
from binascii import hexlify
|
||||||
from trezorlib import stellar
|
from trezorlib import stellar
|
||||||
from trezorlib import messages as proto
|
from trezorlib import messages
|
||||||
from trezorlib.client import CallException
|
from trezorlib.client import CallException
|
||||||
from trezorlib.tools import parse_path
|
from trezorlib.tools import parse_path
|
||||||
|
|
||||||
|
|
||||||
@pytest.mark.stellar
|
@pytest.mark.stellar
|
||||||
@pytest.mark.xfail(TREZOR_VERSION == 2, reason="T2 support is not yet finished")
|
|
||||||
class TestMsgStellarGetPublicKey(TrezorTest):
|
class TestMsgStellarGetPublicKey(TrezorTest):
|
||||||
|
|
||||||
def test_stellar_get_public_key(self):
|
def test_stellar_get_public_key(self):
|
||||||
self.setup_mnemonic_nopin_nopassphrase()
|
self.setup_mnemonic_nopin_nopassphrase()
|
||||||
|
|
||||||
# GAK5MSF74TJW6GLM7NLTL76YZJKM2S4CGP3UH4REJHPHZ4YBZW2GSBPW
|
# GAK5MSF74TJW6GLM7NLTL76YZJKM2S4CGP3UH4REJHPHZ4YBZW2GSBPW
|
||||||
response = 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 hexlify(response) == b'15d648bfe4d36f196cfb5735ffd8ca54cd4b8233f743f22449de7cf301cdb469'
|
||||||
assert stellar.address_from_public_key(response) == 'GAK5MSF74TJW6GLM7NLTL76YZJKM2S4CGP3UH4REJHPHZ4YBZW2GSBPW'
|
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'))
|
self.client.stellar_get_public_key(parse_path('m/0/1'))
|
||||||
|
|
||||||
if TREZOR_VERSION == 1:
|
if TREZOR_VERSION == 1:
|
||||||
assert exc.value.args[0] == proto.FailureType.ProcessError
|
assert exc.value.args[0] == messages.FailureType.ProcessError
|
||||||
assert exc.value.args[1].endswith('Failed to derive private key')
|
assert exc.value.args[1].endswith('Failed to derive private key')
|
||||||
else:
|
else:
|
||||||
assert exc.value.args[0] == proto.FailureType.FirmwareError
|
assert exc.value.args[0] == messages.FailureType.FirmwareError
|
||||||
assert exc.value.args[1].endswith('Firmware error')
|
assert exc.value.args[1].endswith('Firmware error')
|
||||||
|
@ -57,7 +57,6 @@ import pytest
|
|||||||
|
|
||||||
|
|
||||||
@pytest.mark.stellar
|
@pytest.mark.stellar
|
||||||
@pytest.mark.xfail(TREZOR_VERSION == 2, reason="T2 support is not yet finished")
|
|
||||||
class TestMsgStellarSignTransaction(TrezorTest):
|
class TestMsgStellarSignTransaction(TrezorTest):
|
||||||
|
|
||||||
ADDRESS_N = parse_path(stellar.DEFAULT_BIP32_PATH)
|
ADDRESS_N = parse_path(stellar.DEFAULT_BIP32_PATH)
|
||||||
@ -158,7 +157,6 @@ class TestMsgStellarSignTransaction(TrezorTest):
|
|||||||
|
|
||||||
def _create_msg(self) -> proto.StellarSignTx:
|
def _create_msg(self) -> proto.StellarSignTx:
|
||||||
tx = proto.StellarSignTx()
|
tx = proto.StellarSignTx()
|
||||||
tx.protocol_version = 1
|
|
||||||
tx.source_account = 'GAK5MSF74TJW6GLM7NLTL76YZJKM2S4CGP3UH4REJHPHZ4YBZW2GSBPW'
|
tx.source_account = 'GAK5MSF74TJW6GLM7NLTL76YZJKM2S4CGP3UH4REJHPHZ4YBZW2GSBPW'
|
||||||
tx.fee = 100
|
tx.fee = 100
|
||||||
tx.sequence_number = 0x100000000
|
tx.sequence_number = 0x100000000
|
||||||
|
@ -18,9 +18,11 @@ import os
|
|||||||
|
|
||||||
from trezorlib import coins
|
from trezorlib import coins
|
||||||
from trezorlib import tx_api
|
from trezorlib import tx_api
|
||||||
|
import binascii
|
||||||
|
|
||||||
TxApiBitcoin = coins.tx_api['Bitcoin']
|
TxApiBitcoin = coins.tx_api['Bitcoin']
|
||||||
TxApiTestnet = tx_api.TxApiInsight("insight_testnet")
|
TxApiTestnet = tx_api.TxApiInsight("insight_testnet")
|
||||||
|
TxApiZencash = coins.tx_api['Zencash']
|
||||||
|
|
||||||
tests_dir = os.path.dirname(os.path.abspath(__file__))
|
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('6f90f3c7cbec2258b0971056ef3fe34128dbde30daa9c0639a898f9977299d54')
|
||||||
TxApiTestnet.get_tx('d6da21677d7cca5f42fbc7631d062c9ae918a0254f7c6c22de8e8cb7fd5b8236')
|
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')
|
||||||
|
@ -33,6 +33,18 @@ class TxApi(object):
|
|||||||
url = '%s%s/%s' % (self.url, resource, resourceid)
|
url = '%s%s/%s' % (self.url, resource, resourceid)
|
||||||
return url
|
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):
|
def fetch_json(self, resource, resourceid):
|
||||||
global cache_dir
|
global cache_dir
|
||||||
if cache_dir:
|
if cache_dir:
|
||||||
@ -65,11 +77,13 @@ class TxApi(object):
|
|||||||
|
|
||||||
class TxApiInsight(TxApi):
|
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)
|
super().__init__(network, url)
|
||||||
self.zcash = zcash
|
self.zcash = zcash
|
||||||
|
self.bip115 = bip115
|
||||||
if url:
|
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):
|
def get_tx(self, txhash):
|
||||||
|
|
||||||
@ -97,6 +111,12 @@ class TxApiInsight(TxApi):
|
|||||||
o = t._add_bin_outputs()
|
o = t._add_bin_outputs()
|
||||||
o.amount = int(Decimal(vout['value']) * 100000000)
|
o.amount = int(Decimal(vout['value']) * 100000000)
|
||||||
o.script_pubkey = binascii.unhexlify(vout['scriptPubKey']['hex'])
|
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:
|
if self.zcash:
|
||||||
t.overwintered = data.get('fOverwintered', False)
|
t.overwintered = data.get('fOverwintered', False)
|
||||||
|
2
vendor/trezor-common
vendored
2
vendor/trezor-common
vendored
@ -1 +1 @@
|
|||||||
Subproject commit 2301f7034c1b7a3d1b0be5d4447d432593649a1e
|
Subproject commit 32850a62624ce1a6612ff545beb706560c3716da
|
Loading…
Reference in New Issue
Block a user