Previously if the user tried to pay an invoice, we tried to construct
a tx with the desired feerate. If this raise NotEnoughFunds, we would just
show the error and not let the user change the feerate.
related: https://github.com/spesmilo/electrum/issues/6136#issuecomment-622254754 (method 2)
related #4905
related Electron-Cash/Electron-Cash@6a3d76b0ab
conceptually did not really make sense that the Exception_Hook kept a reference
to an ~arbitrary main window (preventing gc)
* Add --fingerprint option
* Simplify conditional checks
* Improve warning wording
* Throw error instead of logging and returning
* --fingerprint => --serverfingerprint
* Only run fingerprint checks against main server
* Throw error if --serverfingerprint is set for a non SSL main server
* Fix linting errors
* Don't check certificate fingerprint in a seperate connection
* Disallow CA signed certs when a fingerprint is provided
* Show clear error and then exit for Qt GUI users
* Remove leading newlines from error dialog
* Always check is_main_server() when getting fingerprint
* Document how to generate SSL cert fingerprint
Previously all the interfaces used either "t" or "s".
Now the network only tries to use "s" for all interfaces, except for
the main interface, which the user can manually specify to use "t".
(so e.g. if you run with "--server localhost:50002:t", the main server will use "t",
but all the rest will use "s")
There is a standardised location along with reserved hotkey for "Preferences"
in applications on macOS. Let's put *another* preferences menu item there.
The duplicate items ensure that
- an electrum user coming from a different OS,
- a macOS user used to the standardised preferences location,
will both find "Preferences" easily.
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.
follow-up f13f46c555
When on dialog n user presses "Back",
- previously, we went back to when dialog n-1 appeared
- now, go back to just after dialog n-2 finishes
This way, any calculations between when dialog n-2 finishes and
dialog n-1 appears will rerun, potentially populating dialog n-1 differently.
Namely if the user presses back on the confirm_seed_dialog, we want to
go back to the show_seed_dialog but with a freshly generated seed.
E | __main__ | daemon.run_gui errored
Traceback (most recent call last):
File ".../electrum/run_electrum", line 379, in <module>
d.run_gui(config, plugins)
File "...\electrum\electrum\daemon.py", line 522, in run_gui
self.gui_object.main()
File "...\electrum\electrum\gui\qt\__init__.py", line 362, in main
if not self.start_new_window(path, self.config.get('url'), app_is_starting=True):
File "...\electrum\electrum\gui\qt\__init__.py", line 246, in wrapper
return func(self, *args, **kwargs)
File "...\electrum\electrum\gui\qt\__init__.py", line 270, in start_new_window
wallet = self._start_wizard_to_select_or_create_wallet(path)
File "...\electrum\electrum\gui\qt\__init__.py", line 308, in _start_wizard_to_select_or_create_wallet
path, storage = wizard.select_storage(path, self.daemon.get_wallet)
File "...\electrum\electrum\gui\qt\installwizard.py", line 334, in select_storage
pw_e.clear()
File "...\electrum\electrum\gui\qt\util.py", line 759, in clear
self.setText(len(self.text()) * " ")
RuntimeError: wrapped C/C++ object of type PasswordLineEdit has been deleted
If an attacker has access to the process' memory, it's probably already game over,
still we can make their life a bit harder.
I really tried but failed to encapsulate this logic inside PasswordLineEdit.
The destroyed signal arrives too late.
deleteLater is not called.
__del__ gets called too late.
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).
E | gui.qt.exception_window.Exception_Hook | exception caught by crash reporter
Traceback (most recent call last):
File "...\electrum\electrum\plugins\ledger\ledger.py", line 167, in perform_hw1_preflight
firmwareInfo = self.dongleObject.getFirmwareVersion()
File "...\Python38\site-packages\btchip\btchip.py", line 561, 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 6faa
During handling of the above exception, another exception occurred:
Traceback (most recent call last):
File "...\electrum\electrum\gui\qt\main_window.py", line 120, in onPress
self.func()
File "...\electrum\electrum\plugins\hw_wallet\qt.py", line 260, in show_settings_dialog
device_id = self.choose_device(window, keystore)
File "...\electrum\electrum\plugins\hw_wallet\qt.py", line 253, in choose_device
info = self.device_manager().select_device(self, keystore.handler, keystore)
File "...\electrum\electrum\plugin.py", line 554, in select_device
infos = self.unpaired_device_infos(handler, plugin, devices)
File "...\electrum\electrum\plugin.py", line 545, in unpaired_device_infos
soft_device_id=client.get_soft_device_id()))
File "...\electrum\electrum\plugins\ledger\ledger.py", line 88, in get_soft_device_id
self._soft_device_id = self.request_root_fingerprint_from_device()
File "...\electrum\electrum\plugins\hw_wallet\plugin.py", line 197, in request_root_fingerprint_from_device
child_of_root_xpub = self.get_xpub("m/0'", xtype='standard')
File "...\electrum\electrum\plugins\ledger\ledger.py", line 55, in catch_exception
return func(self, *args, **kwargs)
File "...\electrum\electrum\plugins\ledger\ledger.py", line 103, in get_xpub
self.checkDevice()
File "...\electrum\electrum\plugins\ledger\ledger.py", line 210, in checkDevice
self.perform_hw1_preflight()
File "...\electrum\electrum\plugins\ledger\ledger.py", line 198, in perform_hw1_preflight
raise UserFacingException("Dongle is temporarily locked - please unplug it and replug it again")
electrum.util.UserFacingException: Dongle is temporarily locked - please unplug it and replug it again
E | gui.qt.installwizard.InstallWizard |
Traceback (most recent call last):
File "...\electrum\electrum\base_wizard.py", line 541, in create_wallet
password = k.get_password_for_storage_encryption()
File "...\electrum\electrum\keystore.py", line 768, in get_password_for_storage_encryption
client = self.plugin.get_client(self)
File "...\electrum\electrum\plugins\trezor\trezor.py", line 180, in get_client
client = devmgr.client_for_keystore(self, handler, keystore, force_pair)
File "...\electrum\electrum\plugin.py", line 465, in client_for_keystore
info = self.select_device(plugin, handler, keystore, devices)
File "...\electrum\electrum\plugin.py", line 585, in select_device
raise UserCancelled()
electrum.util.UserCancelled
During handling of the above exception, another exception occurred:
Traceback (most recent call last):
File "...\electrum\electrum\gui\qt\installwizard.py", line 300, in select_storage
self.run('choose_hw_device', HWD_SETUP_DECRYPT_WALLET, storage=temp_storage)
File "...\electrum\electrum\base_wizard.py", line 109, in run
f(*args, **kwargs)
File "...\electrum\electrum\base_wizard.py", line 332, in choose_hw_device
self.choice_dialog(title=title, message=msg, choices=choices,
File "...\electrum\electrum\gui\qt\installwizard.py", line 99, in func_wrapper
out = func(*args, **kwargs)
File "...\electrum\electrum\gui\qt\installwizard.py", line 536, in choice_dialog
self.exec_layout(vbox, title)
File "...\electrum\electrum\gui\qt\installwizard.py", line 392, in exec_layout
raise UserCancelled
electrum.util.UserCancelled
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