Commit Graph

216 Commits

Author SHA1 Message Date
SomberNight
2e06a7992e util: improve Tor SOCKS detection
see https://github.com/spesmilo/electrum/issues/7317#issuecomment-1369281075

I guess this should be at least as reliable as the old method -
however the old method would log an error for the Tor process,
and this does not.
Suggested by Tor contributor: trinity-1686a.
2023-01-03 14:49:57 +00:00
SomberNight
253150cb36 qt network dialog: don't poll Tor socks proxy, but scan on interaction
Polling is introduces spam in Tor logs.
Also, Tor Browser 12.0 apparently has a bug where our polling renders
the socks proxy unusuable after some time.
see https://gitlab.torproject.org/tpo/applications/tor-browser/-/issues/41549

Instead of trying to detect a Tor socks proxy every 10 seconds, we now
run detection when the Qt network dialog gets opened, and also when
the user switches to the "Proxy" tab in the dialog.

fixes https://github.com/spesmilo/electrum/issues/7317
2023-01-02 11:58:16 +00:00
SomberNight
21dac9f8a6 util.EventListener: don't log "registering callback"
IMO this is just too spammy to log in the general case when running with -v
2022-11-06 06:12:41 +00:00
SomberNight
21c18bbbe7 util.parse_URI: honour docstring and only raise InvalidBitcoinURI
follow-up ac1d53f067
2022-11-03 12:47:21 +00:00
SomberNight
ac1d53f067 util.parse_URI: allow bip21 with lightning key without fallback addr
We would reject bip21 URIs that contained both an "address=" and a "lightning=" key with a bolt11 invoice,
where the bolt11 invoice did not contain a fallback address.
2022-10-31 19:03:12 +00:00
SomberNight
12e628e2e6 aiorpcx: fix bug in timeout_after monkeypatch
fixes https://github.com/spesmilo/electrum/issues/7952

see in particular https://github.com/spesmilo/electrum/issues/7952#issuecomment-1227225602
> So the issue is with the aiorpcx monkey patch in util.py, as it
> relies on side-effecting the asyncio.Task, and it patches Task.cancel.
> However, aiohttp also uses Task.cancel for its own timeouting of the
> http request, with the same Task object, and this confuses timeout_after.
> Ultimately FxThread.run exits.

related https://github.com/kyuupichan/aiorpcX/pull/47

---

note: I am not content at all with this monkey-patching approach,
but at the same time I don't see how to properly fix this handling all
edge-cases in aiorpcx.

python 3.11 is finally adding an implementation of TaskGroup [0] and
an async timeout context manager [1] in the asyncio module of the stdlib.
Looking at the implementations, they look unfeasible to backport:
much of the implementation of asyncio.Task had to be changed for them
to work, and TaskGroup in particular relies on the new ExceptionGroups.
Some of these edge cases we are battling with aiorpcx.curio look
difficult to fix without those stdlib changes...
Anyway, when we bump the min python to 3.11, I look forward to switching
to that code instead, and ripping this stuff out.

[0]: https://docs.python.org/3.11/library/asyncio-task.html#task-groups
[1]: https://docs.python.org/3.11/library/asyncio-task.html#asyncio.timeout
2022-08-26 15:27:53 +00:00
SomberNight
abef454237 qt: better handle unparseable URIs
fixes https://github.com/spesmilo/electrum/issues/7941
2022-08-16 15:27:13 +00:00
avirgovi
b5d2b3c512 create chmod aware of XDG_RUNTIME_DIR
closes https://github.com/spesmilo/electrum/pull/7681
related https://github.com/spesmilo/electrum/issues/6334

Co-authored-by: avirgovi <avirgovi@cisco.com>
Co-authored-by: SomberNight <somber.night@protonmail.com>
2022-08-09 19:04:17 +02:00
SomberNight
233d2373df util: implement is_subpath 2022-08-09 18:48:21 +02:00
SomberNight
28fe345b0b keystore.check_password: raise better exc if called on pwless ks
If keystore.check_password is called with some pw on a keystore that does not have a password set,
it now raises better exceptions: it should now always raise InvalidPassword, and with a nicer msg.
Previously the exc type would depend on the ks type.

Examples before change:

```
>>> wallet.keystore.check_password("asd")
Traceback (most recent call last):
  File "/home/user/wspace/electrum/electrum/keystore.py", line 580, in check_password
    xprv = pw_decode(self.xprv, password, version=self.pw_hash_version)
  File "/home/user/wspace/electrum/electrum/crypto.py", line 311, in pw_decode
    plaintext_bytes = pw_decode_bytes(data, password, version=version)
  File "/home/user/wspace/electrum/electrum/crypto.py", line 270, in pw_decode_bytes
    data_bytes = bytes(base64.b64decode(data))
  File "/usr/lib/python3.10/base64.py", line 87, in b64decode
    return binascii.a2b_base64(s)
binascii.Error: Incorrect padding
```

```
>>> wallet.keystore.check_password("asd")
Traceback (most recent call last):
    s = aes_decrypt_with_iv(secret, iv, e)
  File "/home/user/wspace/electrum/electrum/crypto.py", line 157, in aes_decrypt_with_iv
    data = decryptor.update(data) + decryptor.finalize()
  File "/usr/lib/python3/dist-packages/cryptography/hazmat/primitives/ciphers/base.py", line 148, in finalize
    data = self._ctx.finalize()
  File "/usr/lib/python3/dist-packages/cryptography/hazmat/backends/openssl/ciphers.py", line 193, in finalize
    raise ValueError(
ValueError: The length of the provided data is not a multiple of the block length.

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

Traceback (most recent call last):
  File "/home/user/wspace/electrum/electrum/gui/qt/console.py", line 254, in exec_command
    result = eval(command, self.namespace, self.namespace)
  File "<string>", line 1, in <module>
  File "/home/user/wspace/electrum/electrum/keystore.py", line 248, in check_password
    self.get_private_key(pubkey, password)
  File "/home/user/wspace/electrum/electrum/keystore.py", line 267, in get_private_key
    sec = pw_decode(self.keypairs[pubkey], password, version=self.pw_hash_version)
  File "/home/user/wspace/electrum/electrum/crypto.py", line 311, in pw_decode
    plaintext_bytes = pw_decode_bytes(data, password, version=version)
  File "/home/user/wspace/electrum/electrum/crypto.py", line 271, in pw_decode_bytes
    return _pw_decode_raw(data_bytes, password, version=version)
  File "/home/user/wspace/electrum/electrum/crypto.py", line 255, in _pw_decode_raw
    raise InvalidPassword() from e
electrum.util.InvalidPassword: Incorrect password
```

-----

Examples after change:
```
>>> wallet.keystore.check_password("asd")
Traceback (most recent call last):
    return binascii.a2b_base64(s)
binascii.Error: Incorrect padding

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

Traceback (most recent call last):
  File "...\electrum\keystore.py", line 68, in wrapper
    return check_password_fn(self, password)
  File "...\electrum\keystore.py", line 605, in check_password
    xprv = pw_decode(self.xprv, password, version=self.pw_hash_version)
  File "...\electrum\crypto.py", line 311, in pw_decode
    plaintext_bytes = pw_decode_bytes(data, password, version=version)
  File "...\electrum\crypto.py", line 267, in pw_decode_bytes
    raise CiphertextFormatError("ciphertext not valid base64") from e
electrum.crypto.CiphertextFormatError: ciphertext not valid base64

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

Traceback (most recent call last):
  File "...\electrum\gui\qt\console.py", line 254, in exec_command
    result = eval(command, self.namespace, self.namespace)
  File "<string>", line 1, in <module>
  File "...\electrum\keystore.py", line 76, in wrapper
    raise InvalidPassword("password given but keystore has no password") from e
electrum.util.InvalidPassword: password given but keystore has no password
```

```
>>> wallet.keystore.check_password("asd")
Traceback (most recent call last):
    s = aes_decrypt_with_iv(secret, iv, e)
  File "...\electrum\crypto.py", line 158, in aes_decrypt_with_iv
    data = cipher.decrypt(data)
  File "...\Python310\site-packages\Cryptodome\Cipher\_mode_cbc.py", line 246, in decrypt
    raise ValueError("Data must be padded to %d byte boundary in CBC mode" % self.block_size)
ValueError: Data must be padded to 16 byte boundary in CBC mode

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

Traceback (most recent call last):
  File "...\electrum\keystore.py", line 68, in wrapper
    return check_password_fn(self, password)
  File "...\electrum\keystore.py", line 272, in check_password
    self.get_private_key(pubkey, password)
  File "...\electrum\keystore.py", line 291, in get_private_key
    sec = pw_decode(self.keypairs[pubkey], password, version=self.pw_hash_version)
  File "...\electrum\crypto.py", line 311, in pw_decode
    plaintext_bytes = pw_decode_bytes(data, password, version=version)
  File "...\electrum\crypto.py", line 268, in pw_decode_bytes
    return _pw_decode_raw(data_bytes, password, version=version)
  File "...\electrum\crypto.py", line 249, in _pw_decode_raw
    raise InvalidPassword() from e
electrum.util.InvalidPassword: Incorrect password

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

Traceback (most recent call last):
  File "...\electrum\gui\qt\console.py", line 254, in exec_command
    result = eval(command, self.namespace, self.namespace)
  File "<string>", line 1, in <module>
  File "...\electrum\keystore.py", line 76, in wrapper
    raise InvalidPassword("password given but keystore has no password") from e
electrum.util.InvalidPassword: password given but keystore has no password
```
2022-07-12 15:50:45 +02:00
SomberNight
e72f575eea android build: factor out package name ("org.electrum.electrum")
to make it easier to change, to make it easy to have a co-existing mainnet and testnet install
(or two mainnet installs, etc)
2022-07-09 04:47:32 +02:00
SomberNight
649cad0122 lnurl: clean-up 2022-06-29 16:18:23 +02:00
bitromortac
fe2fbbd9b1 add lnurl-pay and lightning address support
* bundles all payment identifiers into handle_payment_identifier
* adds lnurl decoding
* adds lightning address decoding
2022-06-29 16:18:15 +02:00
SomberNight
81880e8538 EventListener: key global dict by modulepath+clsname instead of clsname
follow-up fe74e4b9c9

Just for sanity -- there could be a collision of class names (defined in separate modules).
```
>>> wallet.is_up_to_date.__qualname__
'Abstract_Wallet.is_up_to_date'
>>> wallet.is_up_to_date.__module__
'electrum.wallet'
```
2022-06-27 17:23:08 +02:00
ThomasV
fe74e4b9c9 EventListener: pre-register event listeners in the decorator,
and use that registration in the iterator.

That way, we do not invoke getattr on arbitrary methods, which
could trigger unwanted code execution (for example, if a method
is decorated with @property, getattr will execute its code).
2022-06-23 09:11:16 +02:00
SomberNight
5b000a871f EventListener follow-ups: adapt left-out classes and minor clean-ups 2022-06-22 02:09:26 +02:00
ThomasV
dbf055de9a EventListener class to handle callbacks
and QtEventListener for Qt
2022-06-22 02:07:46 +02:00
SomberNight
b6de15b95d util.profiler: make log line easier to understand 2022-06-09 19:46:42 +02:00
ThomasV
a0e791a6e5 If util.trigger_callback() is called from the asyncio loop,
run the callback synchronously.
2022-06-03 16:38:47 +02:00
SomberNight
32f88ae419 util: rm a magic number 2022-05-30 21:42:52 +02:00
SomberNight
3eddc17e21 util.parse_URI: fix typo 2022-05-19 19:30:11 +02:00
SomberNight
d7678e14b5 interface: bypass proxy for servers on localhost
closes https://github.com/spesmilo/electrum/issues/3126
closes https://github.com/spesmilo/electrum/issues/7256

I am unsure if this would be safe to do for the more general "server running on private ip" case,
so this is restricted to localhost only atm.
2022-05-16 22:24:07 +02:00
SomberNight
2c57c78ebe asyncio: stop using get_event_loop(). introduce ~singleton loop.
asyncio.get_event_loop() became deprecated in python3.10. (see https://github.com/python/cpython/issues/83710)
```
.../electrum/electrum/daemon.py:470: DeprecationWarning: There is no current event loop
  self.asyncio_loop = asyncio.get_event_loop()
.../electrum/electrum/network.py:276: DeprecationWarning: There is no current event loop
  self.asyncio_loop = asyncio.get_event_loop()
```
Also, according to that thread, "set_event_loop() [... is] not deprecated by oversight".
So, we stop using get_event_loop() and set_event_loop() in our own code.
Note that libraries we use (such as the stdlib for python <3.10), might call get_event_loop,
which then relies on us having called set_event_loop e.g. for the GUI thread. To work around
this, a custom event loop policy providing a get_event_loop implementation is used.

Previously, we have been using a single asyncio event loop, created with
util.create_and_start_event_loop, and code in many places got a reference to this loop
using asyncio.get_event_loop().
Now, we still use a single asyncio event loop, but it is now stored as a global in
util._asyncio_event_loop (access with util.get_asyncio_loop()).

I believe these changes also fix https://github.com/spesmilo/electrum/issues/5376
2022-04-29 18:49:07 +02:00
ThomasV
ba018c707f Qt: add bolt11_fallback and bip21_lightning options to preferences 2022-04-20 12:48:22 +02:00
SomberNight
428dff90f8 address_sync: include verifier in sync_state progress indicator 2022-04-08 20:36:45 +02:00
SomberNight
05649861c8 qt gui: more resilient startup: catch more exceptions, better fallback
fixes https://github.com/spesmilo/electrum/issues/7447

Consider this trace for 4.2.0:
```
Traceback (most recent call last):
  File "electrum/gui/qt/__init__.py", line 332, in start_new_window
  File "electrum/gui/qt/__init__.py", line 363, in _start_wizard_to_select_or_create_wallet
  File "electrum/gui/qt/installwizard.py", line 302, in select_storage
  File "electrum/util.py", line 504, in get_new_wallet_name
PermissionError: [Errno 1] Operation not permitted: '/Users/admin/Documents/Peach/MS'

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
  File "electrum/gui/qt/__init__.py", line 426, in main
  File "electrum/gui/qt/__init__.py", line 307, in wrapper
  File "electrum/gui/qt/__init__.py", line 349, in start_new_window
  File "electrum/util.py", line 504, in get_new_wallet_name
PermissionError: [Errno 1] Operation not permitted: '/Users/admin/Documents/Peach/MS'
```

Note that `get_new_wallet_name` (os.listdir) can raise OSError,
and we were calling that on the main entrypoint codepath without exception-handling.
We were also calling it in the fallback codepath without exception-handling.
i.e. the GUI errored out on every startup for affected users, and without CLI usage
it was not possible to recover.
2022-03-23 03:58:33 +01:00
SomberNight
cf3f92531e aiorpcx: monkeypatch TimeoutAfter internals
see https://github.com/kyuupichan/aiorpcX/issues/44
2022-02-15 18:22:47 +01:00
SomberNight
c9c094cfab requirements: bump min aiorpcx to 0.22.0
aiorpcx 0.20 changed the behaviour/API of TaskGroups.
When used as a context manager, TaskGroups no longer propagate
exceptions raised by their tasks. Instead, the calling code has
to explicitly check the results of tasks and decide whether to re-raise
any exceptions.
This is a significant change, and so this commit introduces "OldTaskGroup",
which should behave as the TaskGroup class of old aiorpcx. All existing
usages of TaskGroup are replaced with OldTaskGroup.

closes https://github.com/spesmilo/electrum/issues/7446
2022-02-15 18:22:44 +01:00
SomberNight
c131831373 util: rm SilentTaskGroup. this does not seem to be needed anymore
I think this was originally needed due to incorrect management of group lifecycles,
which our current code is doing better.

also note that if we needed this, in newer aiorpcx, the name of
the field was ~changed from `_closed` to `joined`:
239002689a
2022-02-15 18:22:40 +01:00
SomberNight
3f3212e94d some clean-ups now that we require python 3.8
In particular, asyncio.CancelledError no longer inherits Exception (it inherits BaseException directly)
2022-02-15 18:22:36 +01:00
SomberNight
88a1c1a618 python 3.10: fix some deprecation warnings and compat with 3.10 2021-11-09 01:02:57 +01:00
SomberNight
c331c311db crash reporter: add EarlyExceptionsQueue
`util.send_exception_to_crash_reporter` is now useful and can be transparently
used even before the exception hook is set up.
2021-11-05 20:01:43 +01:00
SomberNight
acbb363240 follow-up prev: some clean-ups
re https://github.com/spesmilo/electrum/pull/7492
2021-09-15 16:41:41 +02:00
Siddhant Chawla
65c3a892cf Multiple max spends functionality added (#7492)
this implements https://github.com/spesmilo/electrum/issues/7054
2021-09-15 14:35:15 +00:00
SomberNight
9f5370f9c6 util.format_satoshis: fix (add_thousands_sep & whitespaces) param combo 2021-07-28 15:29:12 +02:00
djboi
6a431aab8c Fixed issue with thousands separator for better readability (#7427)
util.format_satoshis: introduce new option to add thousands separators
2021-07-28 13:26:30 +00:00
SomberNight
18c9a1af10 kivy: format_amount: minor clean-up 2021-07-21 18:35:06 +02:00
SomberNight
46badd128e util.format_satoshis: fix whitespaces param for non-zero precision 2021-07-20 20:31:48 +02:00
SomberNight
5c80293696 util.format_satoshis: fix for amounts with higher than sat precision
Previously, msat precision was leaking through format_satoshis if the
user's base unit was set to "sat". This was a bug.
Some features of format_satoshis did not work well with such values, such
as the "whitespaces" param.

Old code:

>>> util.format_satoshis(Decimal('45831275.748'), decimal_point=2)
'458312.76'
>>> util.format_satoshis(Decimal('45831275.748'), decimal_point=0)
'45831275.748'

New code:

>>> util.format_satoshis(Decimal('45831275.748'), decimal_point=2)
'458312.76'
>>> util.format_satoshis(Decimal('45831275.748'), decimal_point=0)
'45831276.'
2021-07-20 20:02:45 +02:00
MrNaif2018
aafa74ed08 Improve _mythread checks (#7403)
* Improve _mythread checks

* Create get_running_loop util
2021-07-15 14:52:25 +00:00
SomberNight
57e52da77f lnaddr: clean-up SEGWIT_HRP vs BOLT11_HRP confusion
With signet, SEGWIT_HRP != BOLT11_HRP, so the previous "currency" string
became a flawed concept. Instead we pass around net objects now.
2021-06-22 16:16:21 +02:00
ghost43
5dff461aaa Merge pull request #7282 from wakiyamap/add_signet
add signet support
2021-06-22 16:15:38 +02:00
bitromortac
6ce96306ca util: check bip21 url for amount 2021-05-06 15:37:17 +02:00
wakiyamap
639cd94dcb add signet support 2021-05-06 19:47:22 +09:00
bitromortac
63308f94a0 reorganize with_lock decorator 2021-04-02 09:38:39 +02:00
ThomasV
18d7db12da Change warning shown on first channel creation
Qt: if created channel is not recoverable, show channel backup after creation
2021-03-24 10:24:14 +01:00
Benoit Verret
f731c38293 Minor style changes 2021-03-21 00:36:23 -04:00
ThomasV
2fee920f43 On Android, if channels are not recoverable, display channel backup when a new channel is created.
Remove the 'android_backups' setting, which was unpractical.
2021-03-19 13:17:58 +01:00
SomberNight
1ba5997238 qt lightning_tx_dialog: use historical fx rate for fiat amounts 2021-03-12 18:29:00 +01:00
SomberNight
28a7d204ad util: document CallbackManager behaviour 2021-03-11 18:50:59 +01:00