Browse Source

hw wallets: generalise 'minimum_library' for those that provide a version number

master
SomberNight 7 years ago
parent
commit
91c369e392
No known key found for this signature in database
GPG Key ID: B33B5F232C6271E9
  1. 3
      electrum/base_wizard.py
  2. 3
      electrum/plugin.py
  3. 17
      electrum/plugins/coldcard/coldcard.py
  4. 36
      electrum/plugins/hw_wallet/plugin.py
  5. 6
      electrum/plugins/hw_wallet/qt.py
  6. 28
      electrum/plugins/safe_t/safe_t.py
  7. 28
      electrum/plugins/trezor/trezor.py

3
electrum/base_wizard.py

@ -240,7 +240,8 @@ class BaseWizard(object):
u = devmgr.unpaired_device_infos(None, plugin, devices=scanned_devices) u = devmgr.unpaired_device_infos(None, plugin, devices=scanned_devices)
except BaseException as e: except BaseException as e:
devmgr.print_error('error getting device infos for {}: {}'.format(name, e)) devmgr.print_error('error getting device infos for {}: {}'.format(name, e))
debug_msg += ' {}:\n {}\n'.format(plugin.name, e) indented_error_msg = ' '.join([''] + str(e).splitlines(keepends=True))
debug_msg += ' {}:\n{}\n'.format(plugin.name, indented_error_msg)
continue continue
devices += list(map(lambda x: (name, x), u)) devices += list(map(lambda x: (name, x), u))
if not debug_msg: if not debug_msg:

3
electrum/plugin.py

@ -457,7 +457,8 @@ class DeviceMgr(ThreadJob, PrintError):
'''Returns a list of DeviceInfo objects: one for each connected, '''Returns a list of DeviceInfo objects: one for each connected,
unpaired device accepted by the plugin.''' unpaired device accepted by the plugin.'''
if not plugin.libraries_available: if not plugin.libraries_available:
raise Exception('Missing libraries for {}'.format(plugin.name)) message = plugin.get_library_not_available_message()
raise Exception(message)
if devices is None: if devices is None:
devices = self.scan_devices() devices = self.scan_devices()
devices = [dev for dev in devices if not self.xpub_by_id(dev.id_)] devices = [dev for dev in devices if not self.xpub_by_id(dev.id_)]

17
electrum/plugins/coldcard/coldcard.py

@ -585,8 +585,8 @@ class Coldcard_KeyStore(Hardware_KeyStore):
class ColdcardPlugin(HW_PluginBase): class ColdcardPlugin(HW_PluginBase):
libraries_available = requirements_ok
keystore_class = Coldcard_KeyStore keystore_class = Coldcard_KeyStore
minimum_library = (0, 7, 2)
client = None client = None
DEVICE_IDS = [ DEVICE_IDS = [
@ -600,10 +600,19 @@ class ColdcardPlugin(HW_PluginBase):
def __init__(self, parent, config, name): def __init__(self, parent, config, name):
HW_PluginBase.__init__(self, parent, config, name) HW_PluginBase.__init__(self, parent, config, name)
if self.libraries_available: self.libraries_available = self.check_libraries_available() and requirements_ok
self.device_manager().register_devices(self.DEVICE_IDS) if not self.libraries_available:
return
self.device_manager().register_devices(self.DEVICE_IDS)
self.device_manager().register_enumerate_func(self.detect_simulator)
self.device_manager().register_enumerate_func(self.detect_simulator) def get_library_version(self):
import ckcc
try:
return ckcc.__version__
except AttributeError:
return 'unknown'
def detect_simulator(self): def detect_simulator(self):
# if there is a simulator running on this machine, # if there is a simulator running on this machine,

36
electrum/plugins/hw_wallet/plugin.py

@ -27,7 +27,7 @@
from electrum.plugin import BasePlugin, hook from electrum.plugin import BasePlugin, hook
from electrum.i18n import _ from electrum.i18n import _
from electrum.bitcoin import is_address, TYPE_SCRIPT from electrum.bitcoin import is_address, TYPE_SCRIPT
from electrum.util import bfh from electrum.util import bfh, versiontuple
from electrum.transaction import opcodes, TxOutput from electrum.transaction import opcodes, TxOutput
@ -38,6 +38,8 @@ class HW_PluginBase(BasePlugin):
# libraries_available, libraries_URL, minimum_firmware, # libraries_available, libraries_URL, minimum_firmware,
# wallet_class, ckd_public, types, HidTransport # wallet_class, ckd_public, types, HidTransport
minimum_library = (0, )
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.device = self.keystore_class.device self.device = self.keystore_class.device
@ -78,6 +80,38 @@ class HW_PluginBase(BasePlugin):
return False return False
return True return True
def get_library_version(self) -> str:
"""Returns the version of the 3rd party python library
for the hw wallet. For example '0.9.0'
Returns 'unknown' if library is found but cannot determine version.
Raises 'ImportError' if library is not found.
"""
raise NotImplementedError()
def check_libraries_available(self) -> bool:
try:
library_version = self.get_library_version()
except ImportError:
return False
if library_version == 'unknown' or \
versiontuple(library_version) < self.minimum_library:
self.libraries_available_message = (
_("Library version for '{}' is too old.").format(self.name)
+ '\nInstalled: {}, Needed: {}'
.format(library_version, self.minimum_library))
self.print_stderr(self.libraries_available_message)
return False
return True
def get_library_not_available_message(self) -> str:
if hasattr(self, 'libraries_available_message'):
message = self.libraries_available_message
else:
message = _("Missing libraries for {}.").format(self.name)
message += '\n' + _("Make sure you install it with python3")
return message
def is_any_tx_output_on_change_branch(tx): def is_any_tx_output_on_change_branch(tx):
if not hasattr(tx, 'output_info'): if not hasattr(tx, 'output_info'):

6
electrum/plugins/hw_wallet/qt.py

@ -189,11 +189,7 @@ class QtPluginBase(object):
if not isinstance(keystore, self.keystore_class): if not isinstance(keystore, self.keystore_class):
continue continue
if not self.libraries_available: if not self.libraries_available:
if hasattr(self, 'libraries_available_message'): message = keystore.plugin.get_library_not_available_message()
message = self.libraries_available_message + '\n'
else:
message = _("Cannot find python library for") + " '%s'.\n" % self.name
message += _("Make sure you install it with python3")
window.show_error(message) window.show_error(message)
return return
tooltip = self.device + '\n' + (keystore.label or 'unnamed') tooltip = self.device + '\n' + (keystore.label or 'unnamed')

28
electrum/plugins/safe_t/safe_t.py

@ -82,25 +82,8 @@ class SafeTPlugin(HW_PluginBase):
def __init__(self, parent, config, name): def __init__(self, parent, config, name):
HW_PluginBase.__init__(self, parent, config, name) HW_PluginBase.__init__(self, parent, config, name)
try: self.libraries_available = self.check_libraries_available()
# Minimal test if python-safet is installed if not self.libraries_available:
import safetlib
try:
library_version = safetlib.__version__
except AttributeError:
# python-safet only introduced __version__ in 0.1.0
library_version = 'unknown'
if library_version == 'unknown' or \
versiontuple(library_version) < self.minimum_library:
self.libraries_available_message = (
_("Library version for '{}' is too old.").format(name)
+ '\nInstalled: {}, Needed: {}'
.format(library_version, self.minimum_library))
self.print_stderr(self.libraries_available_message)
raise ImportError()
self.libraries_available = True
except ImportError:
self.libraries_available = False
return return
from . import client from . import client
@ -113,6 +96,13 @@ class SafeTPlugin(HW_PluginBase):
self.transport_handler = transport.SafeTTransport() self.transport_handler = transport.SafeTTransport()
self.device_manager().register_enumerate_func(self.enumerate) self.device_manager().register_enumerate_func(self.enumerate)
def get_library_version(self):
import safetlib
try:
return safetlib.__version__
except AttributeError:
return 'unknown'
def enumerate(self): def enumerate(self):
devices = self.transport_handler.enumerate_devices() devices = self.transport_handler.enumerate_devices()
return [Device(d.get_path(), -1, d.get_path(), 'Safe-T mini', 0) for d in devices] return [Device(d.get_path(), -1, d.get_path(), 'Safe-T mini', 0) for d in devices]

28
electrum/plugins/trezor/trezor.py

@ -83,25 +83,8 @@ class TrezorPlugin(HW_PluginBase):
def __init__(self, parent, config, name): def __init__(self, parent, config, name):
HW_PluginBase.__init__(self, parent, config, name) HW_PluginBase.__init__(self, parent, config, name)
try: self.libraries_available = self.check_libraries_available()
# Minimal test if python-trezor is installed if not self.libraries_available:
import trezorlib
try:
library_version = trezorlib.__version__
except AttributeError:
# python-trezor only introduced __version__ in 0.9.0
library_version = 'unknown'
if library_version == 'unknown' or \
versiontuple(library_version) < self.minimum_library:
self.libraries_available_message = (
_("Library version for '{}' is too old.").format(name)
+ '\nInstalled: {}, Needed: {}'
.format(library_version, self.minimum_library))
self.print_stderr(self.libraries_available_message)
raise ImportError()
self.libraries_available = True
except ImportError:
self.libraries_available = False
return return
from . import client from . import client
@ -114,6 +97,13 @@ class TrezorPlugin(HW_PluginBase):
self.transport_handler = transport.TrezorTransport() self.transport_handler = transport.TrezorTransport()
self.device_manager().register_enumerate_func(self.enumerate) self.device_manager().register_enumerate_func(self.enumerate)
def get_library_version(self):
import trezorlib
try:
return trezorlib.__version__
except AttributeError:
return 'unknown'
def enumerate(self): def enumerate(self):
devices = self.transport_handler.enumerate_devices() devices = self.transport_handler.enumerate_devices()
return [Device(d.get_path(), -1, d.get_path(), 'TREZOR', 0) for d in devices] return [Device(d.get_path(), -1, d.get_path(), 'TREZOR', 0) for d in devices]

Loading…
Cancel
Save