TrezorClient: should be in a separate thread
First steps; get show_address working. Client is not responsible for showing exceptions. Suppress uninteresting exceptions.
This commit is contained in:
parent
e2627e0944
commit
d6e8e534a3
|
@ -37,9 +37,10 @@ import icons_rc
|
||||||
from electrum.bitcoin import COIN, is_valid, TYPE_ADDRESS
|
from electrum.bitcoin import COIN, is_valid, TYPE_ADDRESS
|
||||||
from electrum.plugins import run_hook
|
from electrum.plugins import run_hook
|
||||||
from electrum.i18n import _
|
from electrum.i18n import _
|
||||||
from electrum.util import block_explorer, block_explorer_info, block_explorer_URL
|
from electrum.util import (block_explorer, block_explorer_info, format_time,
|
||||||
from electrum.util import format_satoshis, format_satoshis_plain, format_time
|
block_explorer_URL, format_satoshis, PrintError,
|
||||||
from electrum.util import PrintError, NotEnoughFunds, StoreDict
|
format_satoshis_plain, NotEnoughFunds, StoreDict,
|
||||||
|
SilentException)
|
||||||
from electrum import Transaction, mnemonic
|
from electrum import Transaction, mnemonic
|
||||||
from electrum import util, bitcoin, commands
|
from electrum import util, bitcoin, commands
|
||||||
from electrum import SimpleConfig, COIN_CHOOSERS, paymentrequest
|
from electrum import SimpleConfig, COIN_CHOOSERS, paymentrequest
|
||||||
|
@ -198,8 +199,9 @@ class ElectrumWindow(QMainWindow, MessageBoxMixin, PrintError):
|
||||||
self.raise_()
|
self.raise_()
|
||||||
|
|
||||||
def on_error(self, exc_info):
|
def on_error(self, exc_info):
|
||||||
traceback.print_exception(*exc_info)
|
if not isinstance(exc_info[1], SilentException):
|
||||||
self.show_error(str(exc_info[1]))
|
traceback.print_exception(*exc_info)
|
||||||
|
self.show_error(str(exc_info[1]))
|
||||||
|
|
||||||
def on_network(self, event, *args):
|
def on_network(self, event, *args):
|
||||||
if event == 'updated':
|
if event == 'updated':
|
||||||
|
@ -254,6 +256,7 @@ class ElectrumWindow(QMainWindow, MessageBoxMixin, PrintError):
|
||||||
run_hook('close_wallet', self.wallet)
|
run_hook('close_wallet', self.wallet)
|
||||||
|
|
||||||
def load_wallet(self, wallet):
|
def load_wallet(self, wallet):
|
||||||
|
wallet.thread = TaskThread(self, self.on_error)
|
||||||
self.wallet = wallet
|
self.wallet = wallet
|
||||||
self.update_recently_visited(wallet.storage.path)
|
self.update_recently_visited(wallet.storage.path)
|
||||||
self.import_old_contacts()
|
self.import_old_contacts()
|
||||||
|
@ -2856,6 +2859,7 @@ class ElectrumWindow(QMainWindow, MessageBoxMixin, PrintError):
|
||||||
event.accept()
|
event.accept()
|
||||||
|
|
||||||
def clean_up(self):
|
def clean_up(self):
|
||||||
|
self.wallet.thread.stop()
|
||||||
if self.network:
|
if self.network:
|
||||||
self.network.unregister_callback(self.on_network)
|
self.network.unregister_callback(self.on_network)
|
||||||
self.config.set_key("is_maximized", self.isMaximized())
|
self.config.set_key("is_maximized", self.isMaximized())
|
||||||
|
|
|
@ -21,6 +21,10 @@ class InvalidPassword(Exception):
|
||||||
def __str__(self):
|
def __str__(self):
|
||||||
return _("Incorrect password")
|
return _("Incorrect password")
|
||||||
|
|
||||||
|
class SilentException(Exception):
|
||||||
|
'''An exception that should probably be suppressed from the user'''
|
||||||
|
pass
|
||||||
|
|
||||||
class MyEncoder(json.JSONEncoder):
|
class MyEncoder(json.JSONEncoder):
|
||||||
def default(self, obj):
|
def default(self, obj):
|
||||||
from transaction import Transaction
|
from transaction import Transaction
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
from sys import stderr
|
from sys import stderr
|
||||||
|
|
||||||
from electrum.i18n import _
|
from electrum.i18n import _
|
||||||
from electrum.util import PrintError
|
from electrum.util import PrintError, SilentException
|
||||||
|
|
||||||
|
|
||||||
class GuiMixin(object):
|
class GuiMixin(object):
|
||||||
|
@ -20,6 +20,16 @@ class GuiMixin(object):
|
||||||
'passphrase': _("Confirm on %s device to continue"),
|
'passphrase': _("Confirm on %s device to continue"),
|
||||||
}
|
}
|
||||||
|
|
||||||
|
def callback_Failure(self, msg):
|
||||||
|
# BaseClient's unfortunate call() implementation forces us to
|
||||||
|
# raise exceptions on failure in order to unwind the stack.
|
||||||
|
# However, making the user acknowledge they cancelled
|
||||||
|
# gets old very quickly, so we suppress those.
|
||||||
|
if msg.code in (self.types.Failure_PinCancelled,
|
||||||
|
self.types.Failure_ActionCancelled):
|
||||||
|
raise SilentException()
|
||||||
|
raise RuntimeError(msg.message)
|
||||||
|
|
||||||
def callback_ButtonRequest(self, msg):
|
def callback_ButtonRequest(self, msg):
|
||||||
msg_code = self.msg_code_override or msg.code
|
msg_code = self.msg_code_override or msg.code
|
||||||
message = self.messages.get(msg_code, self.messages['default'])
|
message = self.messages.get(msg_code, self.messages['default'])
|
||||||
|
@ -65,6 +75,7 @@ class TrezorClientBase(GuiMixin, PrintError):
|
||||||
self.handler = handler
|
self.handler = handler
|
||||||
self.hid_id_ = hid_id
|
self.hid_id_ = hid_id
|
||||||
self.tx_api = plugin
|
self.tx_api = plugin
|
||||||
|
self.types = plugin.types
|
||||||
self.msg_code_override = None
|
self.msg_code_override = None
|
||||||
|
|
||||||
def __str__(self):
|
def __str__(self):
|
||||||
|
@ -172,9 +183,6 @@ class TrezorClientBase(GuiMixin, PrintError):
|
||||||
def wrapped(self, *args, **kwargs):
|
def wrapped(self, *args, **kwargs):
|
||||||
try:
|
try:
|
||||||
return func(self, *args, **kwargs)
|
return func(self, *args, **kwargs)
|
||||||
except BaseException as e:
|
|
||||||
self.handler.show_error(str(e))
|
|
||||||
raise e
|
|
||||||
finally:
|
finally:
|
||||||
self.handler.finished()
|
self.handler.finished()
|
||||||
|
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
import base64
|
import base64
|
||||||
import re
|
import re
|
||||||
|
import threading
|
||||||
import time
|
import time
|
||||||
|
|
||||||
from binascii import unhexlify
|
from binascii import unhexlify
|
||||||
|
@ -172,6 +173,7 @@ class TrezorCompatiblePlugin(BasePlugin, ThreadJob):
|
||||||
|
|
||||||
def __init__(self, parent, config, name):
|
def __init__(self, parent, config, name):
|
||||||
BasePlugin.__init__(self, parent, config, name)
|
BasePlugin.__init__(self, parent, config, name)
|
||||||
|
self.main_thread = threading.current_thread()
|
||||||
self.device = self.wallet_class.device
|
self.device = self.wallet_class.device
|
||||||
self.wallet_class.plugin = self
|
self.wallet_class.plugin = self
|
||||||
self.prevent_timeout = time.time() + 3600 * 24 * 365
|
self.prevent_timeout = time.time() + 3600 * 24 * 365
|
||||||
|
@ -216,6 +218,8 @@ class TrezorCompatiblePlugin(BasePlugin, ThreadJob):
|
||||||
return self.client_class(transport, handler, self, hid_id)
|
return self.client_class(transport, handler, self, hid_id)
|
||||||
|
|
||||||
def get_client(self, wallet, force_pair=True, check_firmware=True):
|
def get_client(self, wallet, force_pair=True, check_firmware=True):
|
||||||
|
assert self.main_thread != threading.current_thread()
|
||||||
|
|
||||||
'''check_firmware is ignored unless force_pair is True.'''
|
'''check_firmware is ignored unless force_pair is True.'''
|
||||||
client = self.device_manager().get_client(wallet, force_pair)
|
client = self.device_manager().get_client(wallet, force_pair)
|
||||||
|
|
||||||
|
|
|
@ -232,7 +232,7 @@ def qt_plugin_class(base_plugin_class):
|
||||||
window.statusBar().addPermanentWidget(window.tzb)
|
window.statusBar().addPermanentWidget(window.tzb)
|
||||||
wallet.handler = self.create_handler(window)
|
wallet.handler = self.create_handler(window)
|
||||||
# Trigger a pairing
|
# Trigger a pairing
|
||||||
self.get_client(wallet)
|
wallet.thread.add(partial(self.get_client, wallet))
|
||||||
|
|
||||||
def on_create_wallet(self, wallet, wizard):
|
def on_create_wallet(self, wallet, wizard):
|
||||||
assert type(wallet) == self.wallet_class
|
assert type(wallet) == self.wallet_class
|
||||||
|
@ -243,8 +243,9 @@ def qt_plugin_class(base_plugin_class):
|
||||||
@hook
|
@hook
|
||||||
def receive_menu(self, menu, addrs, wallet):
|
def receive_menu(self, menu, addrs, wallet):
|
||||||
if type(wallet) == self.wallet_class and len(addrs) == 1:
|
if type(wallet) == self.wallet_class and len(addrs) == 1:
|
||||||
menu.addAction(_("Show on %s") % self.device,
|
def show_address():
|
||||||
lambda: self.show_address(wallet, addrs[0]))
|
wallet.thread.add(partial(self.show_address, wallet, addrs[0]))
|
||||||
|
menu.addAction(_("Show on %s") % self.device, show_address)
|
||||||
|
|
||||||
def settings_dialog(self, window):
|
def settings_dialog(self, window):
|
||||||
hid_id = self.choose_device(window)
|
hid_id = self.choose_device(window)
|
||||||
|
|
Loading…
Reference in New Issue