device manager: index devices by xpub
This commit is contained in:
@@ -144,7 +144,7 @@ class Plugins(DaemonThread):
|
||||
for name, (gui_good, details) in self.hw_wallets.items():
|
||||
if gui_good:
|
||||
try:
|
||||
p = self.wallet_plugin_loader(name)
|
||||
p = self.get_plugin(name)
|
||||
if action == 'restore' or p.is_enabled():
|
||||
wallet_types.append(details[1])
|
||||
descs.append(details[2])
|
||||
@@ -157,7 +157,7 @@ class Plugins(DaemonThread):
|
||||
from wallet import register_wallet_type, register_constructor
|
||||
self.print_error("registering wallet type", (wallet_type, name))
|
||||
def loader():
|
||||
plugin = self.wallet_plugin_loader(name)
|
||||
plugin = self.get_plugin(name)
|
||||
register_constructor(wallet_type, plugin.wallet_class)
|
||||
register_wallet_type(wallet_type)
|
||||
plugin_loaders[wallet_type] = loader
|
||||
@@ -165,13 +165,13 @@ class Plugins(DaemonThread):
|
||||
def register_keystore(self, name, gui_good, details):
|
||||
from keystore import register_keystore
|
||||
def dynamic_constructor():
|
||||
return self.wallet_plugin_loader(name).keystore_class()
|
||||
return self.get_plugin(name).keystore_class()
|
||||
if details[0] == 'hardware':
|
||||
self.hw_wallets[name] = (gui_good, details)
|
||||
self.print_error("registering keystore %s: %s" %(name, details))
|
||||
register_keystore(details[0], details[1], dynamic_constructor)
|
||||
|
||||
def wallet_plugin_loader(self, name):
|
||||
def get_plugin(self, name):
|
||||
if not name in self.plugins:
|
||||
self.load_plugin(name)
|
||||
return self.plugins[name]
|
||||
@@ -297,9 +297,9 @@ class DeviceMgr(ThreadJob, PrintError):
|
||||
|
||||
def __init__(self, config):
|
||||
super(DeviceMgr, self).__init__()
|
||||
# Keyed by wallet. The value is the device id if the wallet
|
||||
# Keyed by xpub. The value is the device id
|
||||
# has been paired, and None otherwise.
|
||||
self.wallets = {}
|
||||
self.xpub_ids = {}
|
||||
# A list of clients. The key is the client, the value is
|
||||
# a (path, id_) pair.
|
||||
self.clients = {}
|
||||
@@ -339,38 +339,38 @@ class DeviceMgr(ThreadJob, PrintError):
|
||||
self.clients[client] = (device.path, device.id_)
|
||||
return client
|
||||
|
||||
def wallet_id(self, wallet):
|
||||
def xpub_id(self, xpub):
|
||||
with self.lock:
|
||||
return self.wallets.get(wallet)
|
||||
return self.xpub_ids.get(xpub)
|
||||
|
||||
def wallet_by_id(self, id_):
|
||||
def xpub_by_id(self, id_):
|
||||
with self.lock:
|
||||
for wallet, wallet_id in self.wallets.items():
|
||||
if wallet_id == id_:
|
||||
return wallet
|
||||
for xpub, xpub_id in self.xpub_ids.items():
|
||||
if xpub_id == id_:
|
||||
return xpub
|
||||
return None
|
||||
|
||||
def unpair_wallet(self, wallet):
|
||||
def unpair_xpub(self, xpub):
|
||||
with self.lock:
|
||||
if not wallet in self.wallets:
|
||||
if not xpub in self.xpub_ids:
|
||||
return
|
||||
wallet_id = self.wallets.pop(wallet)
|
||||
client = self.client_lookup(wallet_id)
|
||||
_id = self.xpub_ids.pop(xpub)
|
||||
client = self.client_lookup(_id)
|
||||
self.clients.pop(client, None)
|
||||
wallet.unpaired()
|
||||
#wallet.unpaired()
|
||||
if client:
|
||||
client.close()
|
||||
|
||||
def unpair_id(self, id_):
|
||||
with self.lock:
|
||||
wallet = self.wallet_by_id(id_)
|
||||
if wallet:
|
||||
self.unpair_wallet(wallet)
|
||||
xpub = self.xpub_by_id(id_)
|
||||
if xpub:
|
||||
self.unpair_xpub(xpub)
|
||||
|
||||
def pair_wallet(self, wallet, id_):
|
||||
def pair_xpub(self, xpub, id_):
|
||||
with self.lock:
|
||||
self.wallets[wallet] = id_
|
||||
wallet.paired()
|
||||
self.xpub_ids[xpub] = id_
|
||||
#wallet.paired()
|
||||
|
||||
def client_lookup(self, id_):
|
||||
with self.lock:
|
||||
@@ -386,37 +386,33 @@ class DeviceMgr(ThreadJob, PrintError):
|
||||
self.scan_devices(handler)
|
||||
return self.client_lookup(id_)
|
||||
|
||||
def client_for_keystore(self, plugin, keystore, force_pair):
|
||||
assert keystore.handler
|
||||
devices = self.scan_devices(keystore.handler)
|
||||
wallet_id = self.wallet_id(keystore)
|
||||
client = self.client_lookup(wallet_id)
|
||||
def client_for_xpub(self, plugin, xpub, derivation, handler, force_pair):
|
||||
devices = self.scan_devices(handler)
|
||||
_id = self.xpub_id(xpub)
|
||||
client = self.client_lookup(_id)
|
||||
if client:
|
||||
# An unpaired client might have another wallet's handler
|
||||
# from a prior scan. Replace to fix dialog parenting.
|
||||
client.handler = keystore.handler
|
||||
client.handler = handler
|
||||
return client
|
||||
|
||||
for device in devices:
|
||||
if device.id_ == wallet_id:
|
||||
return self.create_client(device, keystore.handler, plugin)
|
||||
if device.id_ == _id:
|
||||
return self.create_client(device, handler, plugin)
|
||||
|
||||
if force_pair:
|
||||
return self.force_pair_wallet(plugin, keystore, devices)
|
||||
return self.force_pair_xpub(plugin, handler, xpub, derivation, devices)
|
||||
|
||||
return None
|
||||
|
||||
def force_pair_wallet(self, plugin, keystore, devices):
|
||||
xpub = keystore.get_master_public_key()
|
||||
derivation = keystore.get_derivation()
|
||||
|
||||
def force_pair_xpub(self, plugin, handler, xpub, derivation, devices):
|
||||
# The wallet has not been previously paired, so let the user
|
||||
# choose an unpaired device and compare its first address.
|
||||
info = self.select_device(keystore, plugin, devices)
|
||||
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
|
||||
client.handler = keystore.handler
|
||||
client.handler = handler
|
||||
# This will trigger a PIN/passphrase entry request
|
||||
try:
|
||||
client_xpub = client.get_xpub(derivation)
|
||||
@@ -424,7 +420,7 @@ class DeviceMgr(ThreadJob, PrintError):
|
||||
# Bad / cancelled PIN / passphrase
|
||||
client_xpub = None
|
||||
if client_xpub == xpub:
|
||||
self.pair_wallet(keystore, info.device.id_)
|
||||
self.pair_xpub(xpub, info.device.id_)
|
||||
return client
|
||||
|
||||
# The user input has wrong PIN or passphrase, or cancelled input,
|
||||
@@ -441,7 +437,7 @@ class DeviceMgr(ThreadJob, PrintError):
|
||||
unpaired device accepted by the plugin.'''
|
||||
if devices is None:
|
||||
devices = self.scan_devices(handler)
|
||||
devices = [dev for dev in devices if not self.wallet_by_id(dev.id_)]
|
||||
devices = [dev for dev in devices if not self.xpub_by_id(dev.id_)]
|
||||
|
||||
states = [_("wiped"), _("initialized")]
|
||||
infos = []
|
||||
@@ -458,17 +454,17 @@ class DeviceMgr(ThreadJob, PrintError):
|
||||
|
||||
return infos
|
||||
|
||||
def select_device(self, wallet, plugin, devices=None):
|
||||
def select_device(self, handler, plugin, 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:
|
||||
infos = self.unpaired_device_infos(wallet.handler, plugin, devices)
|
||||
infos = self.unpaired_device_infos(handler, plugin, devices)
|
||||
if infos:
|
||||
break
|
||||
msg = _('Could not connect to your %s. Verify the cable is '
|
||||
'connected and that no other application is using it.\n\n'
|
||||
'Try to connect again?') % plugin.device
|
||||
if not wallet.handler.yes_no_question(msg):
|
||||
if not handler.yes_no_question(msg):
|
||||
raise UserCancelled()
|
||||
devices = None
|
||||
|
||||
@@ -476,7 +472,7 @@ class DeviceMgr(ThreadJob, PrintError):
|
||||
return infos[0]
|
||||
msg = _("Please select which %s device to use:") % plugin.device
|
||||
descriptions = [info.description for info in infos]
|
||||
return infos[wallet.handler.query_choice(msg, descriptions)]
|
||||
return infos[handler.query_choice(msg, descriptions)]
|
||||
|
||||
def scan_devices(self, handler):
|
||||
# All currently supported hardware libraries use hid, so we
|
||||
|
||||
Reference in New Issue
Block a user