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.
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
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
When initialising a Trezor as part of the wallet creation,
device_info.label is still the old (None) label in on_hw_derivation.
This is because device_info was created during the initial scan.
related: #6063
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
regression since #5947
Traceback (most recent call last):
File "...\electrum\electrum\base_wizard.py", line 339, in on_device
self.plugin.setup_device(device_info, self, purpose)
File "...\electrum\electrum\plugins\ledger\ledger.py", line 598, in setup_device
client.get_xpub("m/44'/0'", 'standard') # TODO replace by direct derivation once Nano S > 1.1
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 124, in get_xpub
eckey=ecc.ECPubkey(publicKey),
File "...\electrum\electrum\ecc.py", line 145, in __init__
self._x, self._y = _x_and_y_from_pubkey_bytes(b)
File "...\electrum\electrum\ecc.py", line 119, in _x_and_y_from_pubkey_bytes
ret = _libsecp256k1.secp256k1_ec_pubkey_parse(
ctypes.ArgumentError: argument 3: <class 'TypeError'>: wrong type
this is a regression from #5721
Removed the `TxInput.is_coinbase` method as I think it is a confusing API,
instead we now have `TxInput.is_coinbase_input` and `TxInput.is_coinbase_output`.
related #5872