From 86e23d998900b07b84c716c7cb804646a4232b9b Mon Sep 17 00:00:00 2001 From: ThomasV Date: Fri, 26 Aug 2016 11:45:12 +0200 Subject: [PATCH] save wallet label in keystore, to facilitate pairing --- lib/base_wizard.py | 1 + lib/keystore.py | 7 ++++++- lib/plugins.py | 38 +++++++++++++++++++++++------------- lib/wallet.py | 4 ++++ plugins/trezor/plugin.py | 5 +---- plugins/trezor/qt_generic.py | 2 +- 6 files changed, 37 insertions(+), 20 deletions(-) diff --git a/lib/base_wizard.py b/lib/base_wizard.py index 00d644b0c..8fc28d9bc 100644 --- a/lib/base_wizard.py +++ b/lib/base_wizard.py @@ -218,6 +218,7 @@ class BaseWizard(object): 'hw_type': name, 'derivation': derivation, 'xpub': xpub, + 'label': device_info.label, } k = hardware_keystore(d) self.on_keystore(k) diff --git a/lib/keystore.py b/lib/keystore.py index 7c0af65b5..068383afb 100644 --- a/lib/keystore.py +++ b/lib/keystore.py @@ -49,6 +49,7 @@ class KeyStore(PrintError): def can_import(self): return False + class Software_KeyStore(KeyStore): def __init__(self): @@ -70,7 +71,6 @@ class Software_KeyStore(KeyStore): return decrypted - class Imported_KeyStore(Software_KeyStore): # keystore for imported private keys @@ -459,9 +459,13 @@ class Hardware_KeyStore(KeyStore, Xpub): # handler. The handler is per-window and preserved across # device reconnects self.xpub = d.get('xpub') + self.label = d.get('label') self.derivation = d.get('derivation') self.handler = None + def set_label(self, label): + self.label = label + def may_have_password(self): return False @@ -474,6 +478,7 @@ class Hardware_KeyStore(KeyStore, Xpub): 'hw_type': self.hw_type, 'xpub': self.xpub, 'derivation':self.derivation, + 'label':self.label, } def unpaired(self): diff --git a/lib/plugins.py b/lib/plugins.py index 5b82a6ccc..13ee3987f 100644 --- a/lib/plugins.py +++ b/lib/plugins.py @@ -383,8 +383,18 @@ class DeviceMgr(ThreadJob, PrintError): self.scan_devices() return self.client_lookup(id_) - def client_for_xpub(self, plugin, xpub, derivation, handler, force_pair): - devices = self.scan_devices() + def client_for_keystore(self, plugin, keystore, force_pair): + with self.lock: + devices = self.scan_devices() + xpub = keystore.xpub + derivation = keystore.get_derivation() + handler = keystore.handler + client = self.client_by_xpub(plugin, xpub, handler, devices) + if client is None and force_pair: + info = self.select_device(handler, plugin, keystore, devices) + client = self.force_pair_xpub(plugin, handler, info, xpub, derivation, devices) + + def client_by_xpub(self, plugin, xpub, handler, devices): _id = self.xpub_id(xpub) client = self.client_lookup(_id) if client: @@ -397,16 +407,11 @@ class DeviceMgr(ThreadJob, PrintError): if device.id_ == _id: return self.create_client(device, handler, plugin) - if force_pair: - return self.force_pair_xpub(plugin, handler, xpub, derivation, devices) - - return None - def force_pair_xpub(self, plugin, handler, xpub, derivation, devices): + def force_pair_xpub(self, plugin, handler, info, xpub, derivation, devices): # The wallet has not been previously paired, so let the user # choose an unpaired device and compare its first address. - with self.lock: - info = self.select_device(handler, plugin, devices) + client = self.client_lookup(info.device.id_) if client and client.is_pairable(): # See comment above for same code @@ -447,7 +452,7 @@ class DeviceMgr(ThreadJob, PrintError): return infos - def select_device(self, handler, plugin, devices=None): + def select_device(self, handler, plugin, keystore, devices=None): '''Ask the user to select a device to use if there is more than one, and return the DeviceInfo for the device.''' while True: @@ -460,12 +465,17 @@ class DeviceMgr(ThreadJob, PrintError): if not handler.yes_no_question(msg): raise UserCancelled() devices = None - - if len(infos) == 1: - return infos[0] + # select device by label + for info in infos: + if info.label == keystore.label: + return info msg = _("Please select which %s device to use:") % plugin.device descriptions = [info.label + ' (%s)'%(_("initialized") if info.initialized else _("wiped")) for info in infos] - return infos[handler.query_choice(msg, descriptions)] + info = infos[handler.query_choice(msg, descriptions)] + # save new label + keystore.set_label(info.label) + keystore.handler.win.wallet.save_keystore() + return info def scan_devices(self): # All currently supported hardware libraries use hid, so we diff --git a/lib/wallet.py b/lib/wallet.py index 1970f5000..62faefd09 100644 --- a/lib/wallet.py +++ b/lib/wallet.py @@ -1489,6 +1489,10 @@ class Multisig_Wallet(Deterministic_Wallet): self.keystores[name] = load_keystore(self.storage, name) self.keystore = self.keystores['x1/'] + def save_keystore(self): + for name, k in self.keystores.items(): + self.storage.put(name, k.dump()) + def get_keystore(self): return self.keystores.get('x1/') diff --git a/plugins/trezor/plugin.py b/plugins/trezor/plugin.py index a741f20aa..0f1795580 100644 --- a/plugins/trezor/plugin.py +++ b/plugins/trezor/plugin.py @@ -134,10 +134,7 @@ class TrezorCompatiblePlugin(HW_PluginBase): # All client interaction should not be in the main GUI thread assert self.main_thread != threading.current_thread() devmgr = self.device_manager() - derivation = keystore.get_derivation() - xpub = keystore.xpub - handler = keystore.handler - client = devmgr.client_for_xpub(self, xpub, derivation, handler, force_pair) + client = devmgr.client_for_keystore(self, keystore, force_pair) # returns the client for a given keystore. can use xpub if client: client.used() diff --git a/plugins/trezor/qt_generic.py b/plugins/trezor/qt_generic.py index 2e4e47d0f..854d92dec 100644 --- a/plugins/trezor/qt_generic.py +++ b/plugins/trezor/qt_generic.py @@ -219,7 +219,7 @@ def qt_plugin_class(base_plugin_class): forgotten their PIN or it is in bootloader mode.''' device_id = self.device_manager().xpub_id(keystore.xpub) if not device_id: - info = self.device_manager().select_device(keystore.handler, self) + info = self.device_manager().select_device(keystore.handler, self, keystore) device_id = info.device.id_ return device_id