mirror of
https://github.com/trezor/trezor-firmware.git
synced 2024-12-22 14:28:07 +00:00
trezorctl: sign_tx command based on tx_sign_tool by mruddy
This commit is contained in:
parent
54426761c6
commit
23d75bfc10
1
setup.py
1
setup.py
@ -26,6 +26,7 @@ setup(
|
||||
py_modules=[
|
||||
'trezorlib.ckd_public',
|
||||
'trezorlib.client',
|
||||
'trezorlib.coins',
|
||||
'trezorlib.debuglink',
|
||||
'trezorlib.ed25519cosi',
|
||||
'trezorlib.ed25519raw',
|
||||
|
@ -1,114 +0,0 @@
|
||||
#!/usr/bin/env python2
|
||||
#
|
||||
# Copyright (C) 2017 mruddy
|
||||
#
|
||||
# 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 binascii
|
||||
from trezorlib.client import TrezorClient
|
||||
from trezorlib.transport_hid import HidTransport
|
||||
from trezorlib.tx_api import TxApiBitcoin, TxApiTestnet, TxApiLitecoin
|
||||
from trezorlib import types_pb2 as types
|
||||
|
||||
# Python2 vs Python3
|
||||
try:
|
||||
input = raw_input
|
||||
except NameError:
|
||||
pass
|
||||
|
||||
|
||||
def get_client():
|
||||
devices = HidTransport.enumerate() # list all connected TREZORs on USB
|
||||
if len(devices) == 0: # check whether we found any
|
||||
return None
|
||||
transport = devices[0] # use first connected device
|
||||
return TrezorClient(transport) # creates object for communicating with TREZOR
|
||||
|
||||
|
||||
def get_txapi():
|
||||
coin = input('Which coin {Bitcoin, Testnet, Litecoin}? ').strip()
|
||||
if coin not in {'Bitcoin', 'Testnet', 'Litecoin'}:
|
||||
return None, None
|
||||
txapi_lookup = {
|
||||
'Bitcoin': TxApiBitcoin,
|
||||
'Testnet': TxApiTestnet,
|
||||
'Litecoin': TxApiLitecoin
|
||||
}
|
||||
return coin, txapi_lookup[coin]
|
||||
|
||||
|
||||
def main():
|
||||
client = get_client()
|
||||
if not client:
|
||||
print('No TREZOR connected')
|
||||
return
|
||||
|
||||
print()
|
||||
print('Welcome to the user-unfriendly transaction signing tool')
|
||||
print('USE AT YOUR OWN RISK!!!')
|
||||
print()
|
||||
|
||||
coin, txapi = get_txapi()
|
||||
if not txapi:
|
||||
print('Coin not supported')
|
||||
return
|
||||
|
||||
client.set_tx_api(txapi)
|
||||
|
||||
inputs = []
|
||||
|
||||
while True:
|
||||
print()
|
||||
prev_in_hash = input('Previous input hash (empty to move on): ').strip()
|
||||
if prev_in_hash == '':
|
||||
break
|
||||
prev_in_vout = input('Previous input index: ').strip()
|
||||
addrn = input("Node path to sign with (e.g.- %s/0'/0/0): " % coin).strip()
|
||||
inputs.append(types.TxInputType(
|
||||
prev_hash=binascii.unhexlify(prev_in_hash),
|
||||
prev_index=int(prev_in_vout, 10),
|
||||
address_n=client.expand_path(addrn)
|
||||
))
|
||||
|
||||
outputs = []
|
||||
|
||||
while True:
|
||||
print()
|
||||
out_addr = input('Pay to address (empty to move on): ').strip()
|
||||
if out_addr == '':
|
||||
break
|
||||
out_amount = input('Amount (in satoshis): ').strip()
|
||||
outputs.append(types.TxOutputType(
|
||||
amount=int(out_amount, 10),
|
||||
script_type=types.PAYTOADDRESS,
|
||||
address=out_addr
|
||||
))
|
||||
|
||||
(signatures, serialized_tx) = client.sign_tx(coin, inputs, outputs)
|
||||
|
||||
client.close()
|
||||
|
||||
print()
|
||||
print('Signed Transaction:', binascii.hexlify(serialized_tx))
|
||||
|
||||
# note: these api's are useful for checking and sending the output of this tool:
|
||||
# https://btc.blockr.io/tx/push -or- https://live.blockcypher.com/btc/pushtx/
|
||||
# https://tbtc.blockr.io/tx/push -or- https://live.blockcypher.com/btc-testnet/pushtx/
|
||||
# https://ltc.blockr.io/tx/push -or - https://live.blockcypher.com/ltc/pushtx/
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
main()
|
71
trezorctl
71
trezorctl
@ -2,9 +2,10 @@
|
||||
|
||||
# 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>
|
||||
# Copyright (C) 2016 Jochen Hoenicke <hoenicke@gmail.com>
|
||||
# Copyright (C) 2012-2017 Marek Palatinus <slush@satoshilabs.com>
|
||||
# Copyright (C) 2012-2017 Pavol Rusnak <stick@satoshilabs.com>
|
||||
# Copyright (C) 2016-2017 Jochen Hoenicke <hoenicke@gmail.com>
|
||||
# Copyright (C) 2017 mruddy
|
||||
#
|
||||
# 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
|
||||
@ -27,6 +28,7 @@ import json
|
||||
|
||||
from trezorlib.client import TrezorClient, TrezorClientVerbose, CallException
|
||||
import trezorlib.types_pb2 as types
|
||||
from trezorlib.coins import coins_txapi
|
||||
|
||||
|
||||
def get_transport_class_by_name(name):
|
||||
@ -431,6 +433,69 @@ def get_public_node(connect, coin, address, curve, show_display):
|
||||
}
|
||||
|
||||
|
||||
#
|
||||
# Signing options
|
||||
#
|
||||
|
||||
@cli.command(help='Sign transaction.')
|
||||
@click.option('-c', '--coin', default='Bitcoin')
|
||||
# @click.option('-n', '--address', required=True, help="BIP-32 path, e.g. m/44'/0'/0'/0/0")
|
||||
# @click.option('-t', '--script-type', type=click.Choice(['address', 'segwit', 'p2shsegwit']), default='address')
|
||||
# @click.option('-o', '--output', required=True, help='Transaction output')
|
||||
# @click.option('-f', '--fee', required=True, help='Transaction fee (sat/B)')
|
||||
@click.pass_obj
|
||||
def sign_tx(connect, coin):
|
||||
client = connect()
|
||||
try:
|
||||
txapi = coins_txapi[coin]
|
||||
except:
|
||||
raise Exception('Coin "%s" is not supported' % coin)
|
||||
client.set_tx_api(txapi)
|
||||
|
||||
try:
|
||||
input = raw_input
|
||||
except:
|
||||
pass
|
||||
|
||||
inputs = []
|
||||
while True:
|
||||
click.echo()
|
||||
prev = input('Input (prevhash:previndex, empty to move on): ').strip()
|
||||
if prev == '':
|
||||
break
|
||||
prev_in_hash, prev_in_vout = prev.split(':')
|
||||
addrn = input("Node path to sign with (e.g.- %s/0'/0/0): " % coin).strip()
|
||||
inputs.append(types.TxInputType(
|
||||
prev_hash=binascii.unhexlify(prev_in_hash),
|
||||
prev_index=int(prev_in_vout, 10),
|
||||
address_n=client.expand_path(addrn)
|
||||
))
|
||||
|
||||
outputs = []
|
||||
while True:
|
||||
click.echo()
|
||||
out_addr = input('Pay to address (empty to move on): ').strip()
|
||||
if out_addr == '':
|
||||
break
|
||||
out_amount = input('Amount (in satoshis): ').strip()
|
||||
outputs.append(types.TxOutputType(
|
||||
amount=int(out_amount, 10),
|
||||
script_type=types.PAYTOADDRESS,
|
||||
address=out_addr
|
||||
))
|
||||
|
||||
(signatures, serialized_tx) = client.sign_tx(coin, inputs, outputs)
|
||||
|
||||
client.close()
|
||||
|
||||
click.echo()
|
||||
click.echo('Signed Transaction:')
|
||||
click.echo(binascii.hexlify(serialized_tx))
|
||||
click.echo()
|
||||
click.echo('Use the following form to broadcast it to the network:')
|
||||
click.echo(txapi.url.replace('/api/', '/tx/send'))
|
||||
|
||||
|
||||
#
|
||||
# Message functions
|
||||
#
|
||||
|
@ -34,6 +34,7 @@ from . import tools
|
||||
# from . import mapping
|
||||
from . import messages_pb2 as proto
|
||||
from . import types_pb2 as types
|
||||
from .coins import coins_slip44
|
||||
from .debuglink import DebugLink
|
||||
|
||||
# Python2 vs Python3
|
||||
@ -481,20 +482,8 @@ class ProtocolMixin(object):
|
||||
n = n[1:]
|
||||
|
||||
# coin_name/a/b/c => 44'/SLIP44_constant'/a/b/c
|
||||
coins = {
|
||||
"Bitcoin": 0,
|
||||
"Testnet": 1,
|
||||
"Namecoin": 7,
|
||||
"Litecoin": 2,
|
||||
"Dogecoin": 3,
|
||||
"Dash": 5,
|
||||
"Ether": 60,
|
||||
"EtherClassic": 61,
|
||||
"Zcash": 133,
|
||||
"Decred": 42
|
||||
}
|
||||
if n[0] in coins:
|
||||
n = ["44'", "%d'" % coins[n[0]]] + n[1:]
|
||||
if n[0] in coins_slip44:
|
||||
n = ["44'", "%d'" % coins_slip44[n[0]]] + n[1:]
|
||||
|
||||
path = []
|
||||
for x in n:
|
||||
|
24
trezorlib/coins.py
Normal file
24
trezorlib/coins.py
Normal file
@ -0,0 +1,24 @@
|
||||
from .tx_api import TxApiBitcoin, TxApiTestnet, TxApiLitecoin, TxApiZcash, TxApiDash, TxApiBcash
|
||||
|
||||
coins_slip44 = {
|
||||
'Bitcoin': 0,
|
||||
'Testnet': 1,
|
||||
'Litecoin': 2,
|
||||
'Dogecoin': 3,
|
||||
'Dash': 5,
|
||||
'Namecoin': 7,
|
||||
'Decred': 42,
|
||||
'Ether': 60,
|
||||
'EtherClassic': 61,
|
||||
'Zcash': 133,
|
||||
'Bcash': 145,
|
||||
}
|
||||
|
||||
coins_txapi = {
|
||||
'Bitcoin': TxApiBitcoin,
|
||||
'Testnet': TxApiTestnet,
|
||||
'Litecoin': TxApiLitecoin,
|
||||
'Dash': TxApiDash,
|
||||
'Zcash': TxApiZcash,
|
||||
'Bcash': TxApiBcash,
|
||||
}
|
@ -173,8 +173,11 @@ class TxApiBlockCypher(TxApi):
|
||||
return t
|
||||
|
||||
|
||||
TxApiBitcoin = TxApiInsight(network='insight_bitcoin', url='https://insight.bitpay.com/api/')
|
||||
TxApiTestnet = TxApiInsight(network='insight_testnet', url='https://test-insight.bitpay.com/api/')
|
||||
TxApiLitecoin = TxApiBlockCypher(network='blockcypher_litecoin', url='https://api.blockcypher.com/v1/ltc/main/')
|
||||
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_zcash', url='https://bch-bitcore2.trezor.io/api/')
|
||||
|
||||
TxApiSegnet = TxApiSmartbit(network='smartbit_segnet', url='https://segnet-api.smartbit.com.au/v1/blockchain/')
|
||||
TxApiZcashTestnet = TxApiInsight(network='insight_zcashtestnet', url='https://explorer.testnet.z.cash/api/', zcash=True)
|
||||
|
Loading…
Reference in New Issue
Block a user