closes https://github.com/spesmilo/electrum/issues/8403
> In Python 3.10 that worked fine, however in Python 3.11 large integer check https://github.com/python/cpython/issues/95778, so now this throws an error.
Apparently this change was deemed a security fix and was backported to all supported branches of CPython (going back to 3.7). i.e. it affects ~all versions of python (if sufficiently updated with bugfix patches), not just 3.11
> Some offending node aliases:
> ```
> ergvein-fiatchannels
> test-mainnet
> arakis
> ```
The features bits set by some of these nodes:
```
(1, 7, 8, 11, 13, 14, 17, 19, 23, 27, 45, 32973, 52973)
(1, 7, 8, 11, 13, 14, 17, 19, 23, 27, 39, 45, 55, 32973, 52973)
```
> P.S. I see there are a lot of nodes with 253 bytes in their feature vectors. Any idea why that could happen?
Note that the valid [merged-into-spec features](50b2df24a2/09-features.md) currently only go as high as ~51.
However the spec does not specify how to choose feature bits for experimental stuff, so I guess some people are using values in the 50k range. The only limit imposed by the spec on the length of the features bitvector is an implicit one due to the max message size: every msg must be smaller than 65KB, and the features bitvector needs to fit inside the init message, hence it can be up to ~524K bits.
(note that the features are not stored in a sparse representation in the init message and in gossip messages, so if many nodes set such high feature bits, that would noticably impact the size of the gossip).
-----
Anyway, our current implementation of LnFeatures is subclassing IntFlag, and it looks like it does not work well for such large integers. I've managed to make IntFlags reasonably in python 3.11 by overriding __str__ and __repr__ (note that in cpython it is apparently only the base2<->base10 conversions that are slow, power-of-2 conversions are fast, so we can e.g. use `hex()`). However in python 3.10 and older, enum.py itself seems really slow for bigints, e.g. enum._decompose in python 3.10.
Try e.g. this script, which is instant in py3.11 but takes minutes in py3.10:
```py
from enum import IntFlag
class c(IntFlag):
known_flag_1 = 1 << 0
known_flag_2 = 1 << 1
known_flag_3 = 1 << 2
if hasattr(IntFlag, "_numeric_repr_"): # python 3.11+
_numeric_repr_ = hex
def __repr__(self):
return f"<{self._name_}: {hex(self._value_)}>"
def __str__(self):
return hex(self._value_)
a = c(2**70000-1)
q1 = repr(a)
q2 = str(a)
```
AFAICT we have two options: either we rewrite LnFeatures so that it does not use IntFlag (and enum.py), or, for the short term as workaround, we could just reject very large feature bits.
For now, I've opted to the latter, rejecting feature bits over 10k.
(note that another option is bumping the min required python to 3.11, in which case with the overrides added in this commit the performance looks perfectly fine)
fixes https://github.com/spesmilo/electrum/issues/8402
To reproduce,
- create wallet from a zpub
- LN is disabled there by default
- create a receive request, which won't have a lightning part
- enable config var "bip21_lightning"
- enable LN
- existing request is now ~breaking receive tab
follow-up a0c43573ab
This now runs the more advanced GUI-specific default lang detection
before the specific GUI is imported. This means even module-level
translated strings will use the correct language, at least in the
GUI modules.
Before this commit, more UI strings would be translated to German
if the user explicitly set the language to German, compared to
how many were translated if the language was "default" and got
set to German via the default-lang mechanism. This should no longer
be the case.
related: https://github.com/spesmilo/electrum/issues/4621
regression from cea4238b81
```
975.04 | E | plugin.DeviceMgr | failed to create client for digitalbitbox at <REDACTED>: AttributeError("'NoneType' object has no attribute 'get_passphrase'")
Traceback (most recent call last):
File "...\electrum\electrum\plugin.py", line 620, in list_pairable_device_infos
soft_device_id = client.get_soft_device_id()
File "...\electrum\electrum\plugins\hw_wallet\plugin.py", line 251, in get_soft_device_id
root_fp = 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 264, in request_root_fingerprint_from_device
child_of_root_xpub = self.get_xpub("m/0'", xtype='standard')
File "...\electrum\electrum\plugins\digitalbitbox\digitalbitbox.py", line 115, in get_xpub
reply = self._get_xpub(bip32_path)
File "...\electrum\electrum\plugins\digitalbitbox\digitalbitbox.py", line 110, in _get_xpub
if self.check_device_dialog():
File "...\electrum\electrum\plugins\digitalbitbox\digitalbitbox.py", line 197, in check_device_dialog
if not self.password_dialog(msg):
File "...\electrum\electrum\plugins\digitalbitbox\digitalbitbox.py", line 159, in password_dialog
password = self.handler.get_passphrase(msg, False)
AttributeError: 'NoneType' object has no attribute 'get_passphrase'
```
in particular, ledger: fix sign_message for some wallets
```
156.02 | E | plugins.ledger.ledger |
Traceback (most recent call last):
File "...\electrum\electrum\plugins\ledger\ledger.py", line 1265, in sign_message
result = base64.b64decode(self.client.sign_message(message, address_path))
File "...\Python310\site-packages\ledger_bitcoin\client.py", line 230, in sign_message
sw, response = self._make_request(self.builder.sign_message(message_bytes, bip32_path), client_intepreter)
File "...\Python310\site-packages\ledger_bitcoin\command_builder.py", line 176, in sign_message
bip32_path: List[bytes] = bip32_path_from_string(bip32_path)
File "...\Python310\site-packages\ledger_bitcoin\common.py", line 68, in bip32_path_from_string
return [int(p).to_bytes(4, byteorder="big") if "'" not in p
File "...\Python310\site-packages\ledger_bitcoin\common.py", line 68, in <listcomp>
return [int(p).to_bytes(4, byteorder="big") if "'" not in p
ValueError: invalid literal for int() with base 10: '84h'
```
Regression from df2bd61de6, where the
default hardened char was changed from "'" to "h". Note that there was
no corresponding wallet db upgrade, so some files use one char and
others use the other.