From 0df6d1ec9712d02f22339c2349336991904fae2e Mon Sep 17 00:00:00 2001 From: SomberNight Date: Sat, 3 Mar 2018 02:39:49 +0100 Subject: [PATCH] trezor: segwit offline signing --- lib/network.py | 3 ++- lib/util.py | 10 ++++++++++ lib/wallet.py | 17 ++++++++++++----- plugins/trezor/trezor.py | 3 +++ 4 files changed, 27 insertions(+), 6 deletions(-) diff --git a/lib/network.py b/lib/network.py index 92edda95..7d00d9c6 100644 --- a/lib/network.py +++ b/lib/network.py @@ -40,6 +40,7 @@ from .bitcoin import * from .interface import Connection, Interface from . import blockchain from .version import ELECTRUM_VERSION, PROTOCOL_VERSION +from .i18n import _ NODES_RETRY_INTERVAL = 60 @@ -1069,7 +1070,7 @@ class Network(util.DaemonThread): try: r = q.get(True, timeout) except queue.Empty: - raise BaseException('Server did not answer') + raise util.TimeoutException(_('Server did not answer')) if r.get('error'): raise BaseException(r.get('error')) return r.get('result') diff --git a/lib/util.py b/lib/util.py index 92523360..68d127f8 100644 --- a/lib/util.py +++ b/lib/util.py @@ -74,6 +74,16 @@ class FileExportFailed(Exception): return _("Failed to export to file.") + "\n" + self.message +class TimeoutException(Exception): + def __init__(self, message=''): + self.message = str(message) + + def __str__(self): + if not self.message: + return _("Operation timed out.") + return self.message + + # Throw this exception to unwind the stack like when an error occurs. # However unlike other exceptions the user won't be informed. class UserCancelled(Exception): diff --git a/lib/wallet.py b/lib/wallet.py index 35979be2..291d63db 100644 --- a/lib/wallet.py +++ b/lib/wallet.py @@ -44,7 +44,7 @@ import sys from .i18n import _ from .util import (NotEnoughFunds, PrintError, UserCancelled, profiler, - format_satoshis, NoDynamicFeeEstimates) + format_satoshis, NoDynamicFeeEstimates, TimeoutException) from .bitcoin import * from .version import * @@ -1401,21 +1401,28 @@ class Abstract_Wallet(PrintError): return True return False - def get_input_tx(self, tx_hash): + def get_input_tx(self, tx_hash, ignore_timeout=False): # First look up an input transaction in the wallet where it # will likely be. If co-signing a transaction it may not have # all the input txs, in which case we ask the network. - tx = self.transactions.get(tx_hash) + tx = self.transactions.get(tx_hash, None) if not tx and self.network: request = ('blockchain.transaction.get', [tx_hash]) - tx = Transaction(self.network.synchronous_get(request)) + try: + tx = Transaction(self.network.synchronous_get(request)) + except TimeoutException as e: + self.print_error('getting input txn from network timed out for {}'.format(tx_hash)) + if not ignore_timeout: + raise e return tx def add_hw_info(self, tx): # add previous tx for hw wallets for txin in tx.inputs(): tx_hash = txin['prevout_hash'] - txin['prev_tx'] = self.get_input_tx(tx_hash) + # segwit inputs might not be needed for some hw wallets + ignore_timeout = Transaction.is_segwit_input(txin) + txin['prev_tx'] = self.get_input_tx(tx_hash, ignore_timeout) # add output info for hw wallets info = {} xpubs = self.get_master_public_keys() diff --git a/plugins/trezor/trezor.py b/plugins/trezor/trezor.py index f80346c7..512168c1 100644 --- a/plugins/trezor/trezor.py +++ b/plugins/trezor/trezor.py @@ -434,6 +434,9 @@ class TrezorPlugin(HW_PluginBase): def electrum_tx_to_txtype(self, tx): t = self.types.TransactionType() + if tx is None: + # probably for segwit input and we don't need this prev txn + return t d = deserialize(tx.raw) t.version = d['version'] t.lock_time = d['lockTime']