Commit Graph

84 Commits

Author SHA1 Message Date
SomberNight
8d07672345 plugin: load_plugin: better exception msg if not found 2024-04-18 16:53:48 +00:00
ThomasV
c9820aeca0 Qt: add download_plugin_dialog 2024-04-13 11:35:49 +02:00
ThomasV
ad774a49be external plugins: add methods to read image files 2024-04-13 11:35:49 +02:00
ThomasV
858d999d31 Allow external plugins
- borrows code brom ElectronCash
 - external plugins are imported as zip files
 - check hash from plugins.json file
2024-04-13 11:35:49 +02:00
ThomasV
3e7d4749cf turn classmethod 'find_all_plugins' into an instance method.
change 'use_' prefix to 'enable_plugin_'
2024-04-13 11:35:49 +02:00
SomberNight
b5d8d31723 plugins: follow-up prev, log thread name when loading plugins
Correction to comment in prev commit (and removing it here):
spec.loader.exec_module does not spawn new threads, it simply
executes the module in the current thread.
I got confused but turns out "load_plugin" itself is sometimes
not called from the main thread. Specifically (e.g.), since the recent
wizard rewrite, in the qt gui, the wizard loads the hww plugins
from a new thread.

This now better explains the macos hww crashes: they had started
appearing because we upgraded hidapi (which made it more sensitive
to having to import from main thread) AND scanning(->importing) from
the wizard no longer happened on the main thread after the rewrite.

Plugins should be thread-safe in terms of where they are imported from.
Let's log the importer thread's name (added here), to help recognise
related threading issues.
2023-12-17 06:07:37 +00:00
SomberNight
740016e0d5 hw wallets: fix crashes on macOS
related https://github.com/trezor/cython-hidapi/pull/150#issuecomment-1542391087
2023-12-17 05:22:40 +00:00
SomberNight
0912e5615d pyinstaller build: follow-up: dirty hack for duplicate plugins
Ah ok, I give up for now... the prev does not really work.

The prior commit works on Windows but not on macOS.
On Windows, it would package all plugins as code and only as code.
On MacOS however, it would not package any plugins at all. And with this commit,
where I mark the plugins folder to be packaged as *data*, it packages all plugins as *both* code and data.
Not sure why.

Let's just package all plugins as both code and data, and ignore the code instances explicitly...
2023-11-30 13:48:53 +00:00
SomberNight
b5f1783a62 plugins: better error and logging on duplicate plugins
(=plugin name collision)

This assert is currently failing in pyinstaller builds
(probably have been since it was added in 552bfb589a).

Looks like the pyinstaller binaries include two copies of the hw_wallet and the jade plugins.
This likely has been the case for years, we just never noticed. -- but it started triggering the new assert.
```
  2.78 | I | plugin | iter_modules=[
ModuleInfo(module_finder=FileFinder('C:\\Program Files (x86)\\Electrum\\electrum\\plugins'), name='audio_modem', ispkg=True),
ModuleInfo(module_finder=FileFinder('C:\\Program Files (x86)\\Electrum\\electrum\\plugins'), name='bitbox02', ispkg=True),
ModuleInfo(module_finder=FileFinder('C:\\Program Files (x86)\\Electrum\\electrum\\plugins'), name='coldcard', ispkg=True),
ModuleInfo(module_finder=FileFinder('C:\\Program Files (x86)\\Electrum\\electrum\\plugins'), name='cosigner_pool', ispkg=True),
ModuleInfo(module_finder=FileFinder('C:\\Program Files (x86)\\Electrum\\electrum\\plugins'), name='digitalbitbox', ispkg=True),
ModuleInfo(module_finder=FileFinder('C:\\Program Files (x86)\\Electrum\\electrum\\plugins'), name='hw_wallet', ispkg=True),
ModuleInfo(module_finder=FileFinder('C:\\Program Files (x86)\\Electrum\\electrum\\plugins'), name='jade', ispkg=True),
ModuleInfo(module_finder=FileFinder('C:\\Program Files (x86)\\Electrum\\electrum\\plugins'), name='keepkey', ispkg=True),
ModuleInfo(module_finder=FileFinder('C:\\Program Files (x86)\\Electrum\\electrum\\plugins'), name='labels', ispkg=True),
ModuleInfo(module_finder=FileFinder('C:\\Program Files (x86)\\Electrum\\electrum\\plugins'), name='ledger', ispkg=True),
ModuleInfo(module_finder=FileFinder('C:\\Program Files (x86)\\Electrum\\electrum\\plugins'), name='payserver', ispkg=True),
ModuleInfo(module_finder=FileFinder('C:\\Program Files (x86)\\Electrum\\electrum\\plugins'), name='revealer', ispkg=True),
ModuleInfo(module_finder=FileFinder('C:\\Program Files (x86)\\Electrum\\electrum\\plugins'), name='safe_t', ispkg=True),
ModuleInfo(module_finder=FileFinder('C:\\Program Files (x86)\\Electrum\\electrum\\plugins'), name='swapserver', ispkg=True),
ModuleInfo(module_finder=FileFinder('C:\\Program Files (x86)\\Electrum\\electrum\\plugins'), name='trezor', ispkg=True),
ModuleInfo(module_finder=FileFinder('C:\\Program Files (x86)\\Electrum\\electrum\\plugins'), name='trustedcoin', ispkg=True),
ModuleInfo(module_finder=FileFinder('C:\\Program Files (x86)\\Electrum\\electrum\\plugins'), name='virtualkeyboard', ispkg=True),
ModuleInfo(module_finder=<pyimod02_importers.FrozenImporter object at 0x015FDFB8>, name='hw_wallet', ispkg=True),
ModuleInfo(module_finder=<pyimod02_importers.FrozenImporter object at 0x015FDFB8>, name='jade', ispkg=True)]
```
2023-11-30 13:44:00 +00:00
SomberNight
8c9fec4ab8 commands: getconfig to use default values, add existence checks
- getconfig and setconfig now both check configvars for existence
- getconfig returns default values when applicable
- setconfig does not side-step type-checks for values

fixes https://github.com/spesmilo/electrum/issues/8607
closes https://github.com/spesmilo/electrum/pull/8608
2023-09-08 15:11:55 +00:00
SomberNight
552bfb589a plugins: split load_plugins() 2023-09-08 14:48:36 +00:00
SomberNight
6a9e532ff1 Plugins: make Plugins.stop() faster
Plugins.stop() is now part of the normal shutdown flow (since 90f39bce88),
so this shaves up to 100 ms off that (avg: 50 ms).
It is also waited on in around ~60 unit tests: this saves 3 sec.
2023-08-24 18:27:34 +00:00
Sander van Grieken
b6863b4854 qml: add LabelSync toggle 2023-07-11 12:51:37 +02:00
SomberNight
184281d2fc version_info cmd: better version for hidapi
was added in https://github.com/trezor/cython-hidapi/pull/143
2023-05-30 22:54:26 +00:00
SomberNight
03ab33f4b2 SimpleConfig: change API of set_key(): "save" is now kwarg-only 2023-05-25 17:37:16 +00:00
SomberNight
d821e26f6e hw DeviceMgr: speed-up client_for_keystore() for common-case
This method is often called when there is already an existing paired
client for the keystore, in which case we can avoid scan_devices() -
which would needlessly take several seconds.
2022-12-19 13:10:24 +00:00
SomberNight
a4276102f2 hw DeviceMgr: don't filter already paired devices in wizard
Related to prev commit: multiple (compatible) keystores can now match
with the same HardwareClientBase, so we might as well also allow
reusing existing Clients for the wizard.
2022-12-19 13:10:20 +00:00
SomberNight
cea4238b81 hw DeviceMgr: mostly switch away from xpubs for device pairing
- the DeviceMgr no longer uses xpubs to keep track of paired hw devices
- instead, introduce keystore.pairing_code(), based on soft_device_id
- xpubs are now only used in a single place when the actual pairing happens
- motivation is to allow pairing a single device with multiple generic
  output script descriptors, not just a single account-level xpub
- as a side-effect, we now allow pairing a device with multiple open
  windows simultaneously (if keystores have the same root fingerprint
  -- was already the case before if keystores had the same xpub)
2022-12-19 08:19:19 +00:00
SomberNight
4d3f50e80d hw DeviceMgr: simplify pairing management
No semantic/functional changes.
2022-12-12 11:33:13 +00:00
SomberNight
752b37a03b dependencies: bundle older hidapi in binaries
closes https://github.com/spesmilo/electrum/issues/7738
2022-08-04 21:47:50 +02:00
SomberNight
780408285c qt "Wallet Info" dialog: show bip32 root fingerprint
and also show it in DeviceMgr.select_device

follow-up 998cd0d356
2022-06-03 18:02:58 +02:00
SomberNight
998cd0d356 hww: make DeviceMgr.select_device dlg msg more explicit (add details)
related https://github.com/spesmilo/electrum/issues/4199#issuecomment-1145063552
2022-06-03 17:14:47 +02:00
SomberNight
b5d3f1458a hww: impl get_client in Hardware_KeyStore instead of subclasses 2022-06-03 17:14:44 +02:00
SomberNight
745e697188 hww: move trigger_pairings to DeviceMgr 2022-06-03 17:14:40 +02:00
SomberNight
1182972be1 hardware wallets: mention keystore.label in select_device
Without it, it is not clear for which keystore the user is supposed to select the device.
(though note that not all plugins implement labels, e.g. ledger does not)

related: https://github.com/spesmilo/electrum/issues/4199#issuecomment-1112552416
2022-04-28 21:38:12 +02:00
SomberNight
e47e0afa91 commands: add "version_info" cmd
example:
```
$ ./run_electrum -o version_info
{
    "aiohttp.version": "3.8.1",
    "aiorpcx.version": "0.22.1",
    "certifi.version": "2021.10.08",
    "cryptodome.version": null,
    "cryptography.path": "/home/user/.local/lib/python3.8/site-packages/cryptography",
    "cryptography.version": "3.4.6",
    "dnspython.version": "2.2.0",
    "electrum.path": "/home/user/wspace/electrum/electrum",
    "electrum.version": "4.2.1",
    "hidapi.version": "0.11.0.post2",
    "libsecp256k1.path": "/home/user/wspace/electrum/electrum/libsecp256k1.so.0",
    "libusb.path": "libusb-1.0.so",
    "libusb.version": "1.0.23.11397",
    "libzbar.path": "/home/user/wspace/electrum/electrum/libzbar.so.0",
    "pyaes.version": "1.3.0",
    "pyqt.path": "/usr/lib/python3/dist-packages/PyQt5",
    "pyqt.version": "5.14.1",
    "qt.version": "5.12.8"
}
```
2022-04-11 17:40:22 +02:00
SomberNight
c8dd68bd63 DeviceMgr.select_device: add some log lines
related https://github.com/spesmilo/electrum/issues/5759#issuecomment-1060093399
2022-03-11 15:49:30 +01:00
scgbckbone
122c09cc04 BUGFIX: invalid client loaded for identical wallet with different HW type (#7689)
* typecheck client selected by keystore - check if plugin types match

* add log msg + refactor if branching

* moved type check to own function; moved from 'client_for_keystore' to 'force_pair_xpub' and 'client_by_xpub'

* refactor

Co-authored-by: avirgovi <avirgovi@cisco.com>
2022-03-03 12:24:28 +00:00
SomberNight
88a1c1a618 python 3.10: fix some deprecation warnings and compat with 3.10 2021-11-09 01:02:57 +01:00
SomberNight
99845942e5 DeviceMgr: don't mark client as failing if create_client() is None
Otherwise the exception raised by client.label() would seem important.
2021-02-22 20:11:14 +01:00
SomberNight
096d853482 qt: rm some usages of get_parent_main_window
instead, pass around the main window or config (whichever is actually needed)

fixes #6342
2020-12-20 15:25:31 +01:00
SomberNight
3f04520d0f ledger: suppress traceback during device enumeration for locked device
ledger now gives an error if querying xpub while device is not (unlocked and in bitcoin app).
we do query the xpub however, to calc root fingerprint to be used as soft device id.

trace:

I | plugin.DeviceMgr | scanning devices...
D | util.profiler | DeviceMgr.scan_devices 3.4463
I | plugin.DeviceMgr | Registering <electrum.plugins.ledger.ledger.Ledger_Client object at 0x0000029DF6B08520>
E | gui.qt.installwizard.InstallWizard |
Traceback (most recent call last):
  File "...\electrum\electrum\plugins\ledger\ledger.py", line 225, in checkDevice
    self.perform_hw1_preflight()
  File "...\electrum\electrum\plugin.py", line 362, in wrapper
    return run_in_hwd_thread(partial(func, *args, **kwargs))
  File "...\electrum\electrum\plugin.py", line 352, in run_in_hwd_thread
    return func()
  File "...\electrum\electrum\plugins\ledger\ledger.py", line 219, in perform_hw1_preflight
    raise e
  File "...\electrum\electrum\plugins\ledger\ledger.py", line 179, in perform_hw1_preflight
    firmwareInfo = self.dongleObject.getFirmwareVersion()
  File "...\Python38\site-packages\btchip\btchip.py", line 563, in getFirmwareVersion
    response = self.dongle.exchange(bytearray(apdu))
  File "...\Python38\site-packages\btchip\btchipComm.py", line 127, in exchange
    raise BTChipException("Invalid status %04x" % sw, sw)
btchip.btchipException.BTChipException: Exception : Invalid status 6700

The above exception was the direct cause of the following exception:

Traceback (most recent call last):
  File "...\electrum\electrum\base_wizard.py", line 317, in _choose_hw_device
    device_infos = devmgr.unpaired_device_infos(None, plugin, devices=scanned_devices,
  File "...\electrum\electrum\plugin.py", line 612, in unpaired_device_infos
    soft_device_id=client.get_soft_device_id(),
  File "...\electrum\electrum\plugin.py", line 362, in wrapper
    return run_in_hwd_thread(partial(func, *args, **kwargs))
  File "...\electrum\electrum\plugin.py", line 355, in run_in_hwd_thread
    return fut.result()
  File "...\Python38\lib\concurrent\futures\_base.py", line 439, in result
    return self.__get_result()
  File "...\Python38\lib\concurrent\futures\_base.py", line 388, in __get_result
    raise self._exception
  File "...\Python38\lib\concurrent\futures\thread.py", line 57, in run
    result = self.fn(*self.args, **self.kwargs)
  File "...\electrum\electrum\plugins\ledger\ledger.py", line 91, in get_soft_device_id
    self._soft_device_id = self.request_root_fingerprint_from_device()
  File "...\electrum\electrum\plugin.py", line 362, in wrapper
    return run_in_hwd_thread(partial(func, *args, **kwargs))
  File "...\electrum\electrum\plugin.py", line 352, in run_in_hwd_thread
    return func()
  File "...\electrum\electrum\plugins\hw_wallet\plugin.py", line 259, in request_root_fingerprint_from_device
    child_of_root_xpub = self.get_xpub("m/0'", xtype='standard')
  File "...\electrum\electrum\plugin.py", line 362, in wrapper
    return run_in_hwd_thread(partial(func, *args, **kwargs))
  File "...\electrum\electrum\plugin.py", line 352, in run_in_hwd_thread
    return func()
  File "...\electrum\electrum\plugins\ledger\ledger.py", line 57, in catch_exception
    return func(self, *args, **kwargs)
  File "...\electrum\electrum\plugins\ledger\ledger.py", line 111, in get_xpub
    self.checkDevice()
  File "...\electrum\electrum\plugin.py", line 362, in wrapper
    return run_in_hwd_thread(partial(func, *args, **kwargs))
  File "...\electrum\electrum\plugin.py", line 352, in run_in_hwd_thread
    return func()
  File "...\electrum\electrum\plugins\ledger\ledger.py", line 228, in checkDevice
    raise UserFacingException(_("Device not in Bitcoin mode")) from e
electrum.util.UserFacingException: Device not in Bitcoin mode
W | gui.qt.installwizard.InstallWizard | error getting device infos for ledger: Device not in Bitcoin mode
2020-11-18 15:36:15 +01:00
SomberNight
b78cbcffd1 ledger: fix enumerating ledger devices with new bitcoin app (1.5.1)
see https://github.com/bitcoin-core/HWI/issues/402
2020-11-18 15:36:11 +01:00
ghost43
21c3572600 hardware devices: run all device communication on dedicated thread (#6561)
hidapi/libusb etc are not thread-safe.

related: #6554
2020-09-08 15:52:53 +00:00
SomberNight
53a5a21ee8 hardware: update device conn. status faster (through GUI indicator)
Qt status bar icon will now refresh to reflect disconnected device
during next scan
2020-09-07 17:16:06 +02:00
SomberNight
f265acd234 DeviceMgr.scan_devices: do all scanning on hidapi thread
e.g. the trezor custom enumerate function calls hid.enumerate() which is not thread safe (?).
see comment on line 330
2020-08-31 22:17:44 +02:00
SomberNight
4d8fcded4b qt plugins dialog: fix caching "settings" button
shesek reported on IRC:
> the button widget for opening plugins configuration gets cached in `settings_widgets`
> even after the plugin is disabled and re-enabled, which causes it to call `settings_dialog()`
> on the previous plugin instance that got unloaded instead of the new one.
2020-05-26 00:54:22 +02:00
SomberNight
2cfa3bd6c8 hww hidapi usage: try to mitigate some thread-safety issues
related: #6097
2020-04-17 19:53:39 +02:00
SomberNight
e830ef309f hww: factor out part of hid scan code to HW_PluginBase
so that bitbox02 can override it
2020-04-12 15:34:19 +02:00
TheCharlatan
a4fe14bb82 BitBox02 Electrum plugin support
This commit adds support for the BitBox02 hardware wallet.
It supports both single and multisig for the electrum gui wallet.

To use the plugin a local installation of the BitBox02 python library is
required. It can be found on PiPy under the name 'bitbox02' and can be
installed from the bitbox02-firmware repository in the py/bitbox02
directory.

All communication to and from the BitBox02 is noise encrypted, the keys
required for this are stored in the wallet config file under the
bitbox02 key.

The BitBox02 registers a multisig configuration before allowing
transaction signing. This multisig configuration includes the threshold,
cosigner xpubs, keypath, a variable to indicate for mainnet and testnet,
and a name that the user can choose during configuration registration.
The user is asked to register the multisig configuration either during
address verification or during transaction signing.

The check the xpub of the BitBox02 for other hardware wallets, a button
is added in the wallet info dialog.

The wallet encryption key is fetched in a separate api call, requiring a
slightly tweaked override version of the wallet encryption password.
2020-04-12 15:34:37 +02:00
SomberNight
4b1d835304 wizard hww: scan devices fewer times and move away from GUI thread 2020-04-09 19:45:31 +02:00
SomberNight
7a4acb05f2 hww: fix threading issue in DeviceMgr: enumerate_func needs self.lock
E | gui.qt.main_window.[test_ms_p2wsh_2of3_cc3132_trezort_cc3133] | on_error
Traceback (most recent call last):
  File "...\electrum\electrum\gui\qt\util.py", line 794, in run
    result = task.task()
  File "...\electrum\electrum\plugins\hw_wallet\qt.py", line 232, in trigger_pairings
    devices = devmgr.scan_devices()
  File "...\electrum\electrum\plugin.py", line 376, in func_wrapper
    return func(self, *args, **kwargs)
  File "...\electrum\electrum\plugin.py", line 656, in scan_devices
    for f in self.enumerate_func:
RuntimeError: Set changed size during iteration
2020-04-08 18:46:28 +02:00
SomberNight
db1ff4915f hww: show model name in device enum lists (e.g. "Trezor T") 2020-04-08 17:53:40 +02:00
SomberNight
e1996bde01 hww: select_device: only update label/dev_id after pairing succeeds 2020-04-08 17:53:37 +02:00
SomberNight
4ef313a1ac hww: smarter auto-selection of which device to pair with
scenario1:
- 2of2 multisig wallet with trezor1 and trezor2 keystores
- only trezor2 connected
- previously we would pair first keystore with connected device and then display error.
  now we will pair the device with the correct keystore on the first try

scenario2:
- standard wallet with trezor1 keystore
- trezor2 connected (different device)
- previously we would pair trezor2 with the keystore and then display error.
  now we will prompt the user to select which device to pair with (out of one)

related: #5789
2020-04-08 17:53:33 +02:00
SomberNight
9d0bb295e6 hww: distinguish devices based on "soft device id" (not just labels)
fixes #5759
2020-04-08 14:44:42 +02:00
SomberNight
e6d43b60fa qt hww show_settings_dialog: don't scan devices in GUI thread
Just makes sense in general.
Also, previously, the GUI would freeze if right after startup the user
clicked the hww status bar icon (especially with multiple hww connected).
2020-04-01 21:09:06 +02:00
SomberNight
7f1c7955dc DeviceMgr: clean-up locks a bit 2020-04-01 21:09:00 +02:00
SomberNight
3ea2872b31 hw wallets: show e.g. "An unnamed trezor" if no label in select_device
related: #6063
2020-03-31 15:18:24 +02:00
SomberNight
6760c3f252 hw wallets: introduce HardwareHandlerBase
previously, client.handler was sometimes
- an InstallWizard
- a QtHandlerBase where win was an ElectrumWindow
- a QtHandlerBase where win was an InstallWizard
- a CmdLineHandler

That's just too much dynamic untyped undocumented polymorphism...
Now it will never be an InstallWizard (replaced with QtHandlerBase where win is an InstallWizard),
and now in all cases client.handler is an instance of HardwareHandlerBase, yay.

related: #6063
2020-03-31 14:40:25 +02:00