Commit Graph

294 Commits

Author SHA1 Message Date
SomberNight
6d99717d5b txbatcher: add comment to _to_pay_after 2025-08-21 15:15:08 +00:00
SomberNight
8b99c218b4 network: move broadcast_transaction move network to interface.py 2025-08-07 16:29:49 +00:00
ghost43
dfd480d5dd Merge pull request #10033 from SomberNight/202507_interface_fast_forward
interface: parallel header-chunks download
2025-07-31 15:47:11 +00:00
SomberNight
eef562389c qml: qenetwork: fix type confusion for "server"
exc triggered when switching from same server to same server:
```
  9.43 | D | gui.qml.qenetwork | server_status updated: Connecting
  9.43 | E | network | Exception in _run_new_interface: Exception('diagnostic name not yet available?')
Traceback (most recent call last):
  File "/home/user/wspace/electrum/electrum/logging.py", line 241, in __get_logger_for_obj
    diag_name = self.diagnostic_name()
  File "/home/user/wspace/electrum/electrum/interface.py", line 555, in diagnostic_name
    return self.server.net_addr_str()
AttributeError: 'str' object has no attribute 'net_addr_str'

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

Traceback (most recent call last):
  File "/home/user/wspace/electrum/electrum/util.py", line 1218, in wrapper
    return await func(*args, **kwargs)
  File "/home/user/wspace/electrum/electrum/network.py", line 986, in _run_new_interface
    interface = Interface(network=self, server=server)
  File "/home/user/wspace/electrum/electrum/interface.py", line 502, in __init__
    Logger.__init__(self)
  File "/home/user/wspace/electrum/electrum/logging.py", line 232, in __init__
    self.logger = self.__get_logger_for_obj()
  File "/home/user/wspace/electrum/electrum/logging.py", line 243, in __get_logger_for_obj
    raise Exception("diagnostic name not yet available?") from e
Exception: diagnostic name not yet available?
```
2025-07-18 14:16:30 +00:00
SomberNight
6a56fd756b interface: split request_chunk, based on "can_return_early" param 2025-07-15 22:53:35 +00:00
SomberNight
27599ac537 interface: small clean-up. intro ChainResolutionMode.
- type hints
- minor API changes
- no functional changes
2025-06-06 16:42:15 +00:00
ThomasV
853b793bef rm verbosity_shortcuts option (unused, redundant) 2025-05-29 16:20:41 +02:00
Sander van Grieken
82e3932aaf network: add oneserver/auto_connect both enabled checks, avoid connecting to random/multiple servers
if oneserver is enabled.
2025-05-19 18:07:29 +02:00
SomberNight
1c41bd23b7 network: broadcast_transaction: log full raw tx on errors 2025-05-16 15:49:54 +00:00
SomberNight
68ac2d8079 network: sanitize_tx_broadcast_response: add new error messages 2025-05-16 15:48:12 +00:00
Sander van Grieken
64a160027a imports, whitespace, type hints 2025-04-23 16:09:31 +02:00
SomberNight
0b3a283586 asyncio: hold our own strong refs for tasks and futures
see https://docs.python.org/3.13/library/asyncio-task.html#asyncio.create_task :

> Important
>
> Save a reference to the result of this function, to avoid a task
> disappearing mid-execution. The event loop only keeps weak references
> to tasks. A task that isn’t referenced elsewhere may get garbage
> collected at any time, even before it’s done. For reliable
> “fire-and-forget” background tasks, gather them in a collection

ref https://github.com/python/cpython/issues/91887
ref https://github.com/beeware/toga/pull/2814
2025-03-05 17:06:04 +00:00
SomberNight
b88d9f9d06 network: follow-up ProxySettings. make sure probe_tor cleans-up.
follow-up 2aa427b4bf
2025-03-05 17:04:49 +00:00
SomberNight
2aa427b4bf Merge branch 'pr/9507': qt: refactor NetworkChoiceLayout to ProxyWidget+ServerWidget
ref https://github.com/spesmilo/electrum/pull/9507
2025-03-05 15:01:05 +00:00
SomberNight
5dc2ae243e util: refactor Tor-detection to be async
- on my PC, with Tor Browser running (socks proxy on port 9150), detect_tor_socks_proxy took ~4.01 seconds
- this was because we probed port 9050, 2 sec timeout, 9051, 2 sec timeout, 9150, ~few ms to succeed
- instead we now probe all ports concurrently
2025-03-05 14:46:47 +00:00
Sander van Grieken
f1e9abf04e qt,qml: review rework, refactor spinner, add tor probe active indicator 2025-03-05 10:52:25 +01:00
ThomasV
840243e029 separate fee policy from config
- Wallet.make_unsigned_transaction takes a FeePolicy parameter
 - fee sliders act on a FeePolicy instead of config
 - different fee policies may be used for different purposes
 - do not detect dust outputs in lnsweep, delegate that to lnwatcher
2025-03-05 10:29:26 +01:00
Sander van Grieken
fea598cfbe network: create ProxySettings class replacing dict and encapsulating proxy related funcs,
allow enable/disable proxy without nuking proxy mode, host and port (explicit enable_proxy config setting),
move tor probe from frontend to backend code, add probe buttons for Qt and QML
2025-03-04 14:23:33 +01:00
SomberNight
be2cd02e54 some clean-ups now that we require python 3.10 2025-01-10 18:52:53 +00:00
ThomasV
29a8c41025 move watchtower to a plugin.
remove watchtower dialog in qt
2024-12-20 15:34:26 +01:00
Sander van Grieken
f4520b9e0d network: use TOR stream isolation
also refactor, for proxy instantiation, use Network instance, not a proxy dict.
2024-10-25 01:10:58 +02:00
SomberNight
7a0bffc3e3 swaps: broadcast_transaction error-handling 2024-06-05 19:00:51 +00:00
SomberNight
bc57926498 network: (trivial) simplify send_http_on_proxy 2024-06-04 13:48:37 +00:00
SomberNight
b9a2b0d19b network: re-detect is_proxy_tor every time we connect to a server
This avoids some false negatives for is_proxy_tor.
(previously we only set is_proxy_tor when the proxy settings were changed)
In particular, consider scenario:
- Tor browser not running
- user sets "localhost:9150" as proxy
- detection sets network.is_proxy_tor to False
- user starts Tor browser
- network, due to retries, finds proxy working and connects to some servers
- network.is_proxy_tor remains False
2024-04-25 22:48:56 +00:00
SomberNight
e5d28563cc network: implement basic "add server as bookmark" functionality
implement backend and expose it to qt gui
2024-02-03 12:33:34 +00:00
Sander van Grieken
831be3b680 network: fix issue starting tor probe when proxy disabled 2023-12-12 13:27:42 +01:00
Sander van Grieken
15592d4987 followup 0d476f73df 2023-12-05 11:08:20 +01:00
accumulator
134fd6c656 Merge pull request #8714 from accumulator/tor_probe
network: async tor probe
2023-12-04 16:45:03 +01:00
Sander van Grieken
0d476f73df network: rename network.tor_proxy to network.is_proxy_tor and keep it at None until TOR probe is done. 2023-12-04 10:42:32 +01:00
SomberNight
64f82cd260 qt wizard bip39 recovery: better handle --offline mode
```
 32.40 | E | gui.qt.exception_window.Exception_Hook | exception caught by crash reporter
Traceback (most recent call last):
  File "/home/user/wspace/electrum/electrum/gui/qt/wizard/wallet.py", line 709, in <lambda>
    button.clicked.connect(lambda: Bip39RecoveryDialog(self, get_account_xpub, on_account_select))
  File "/home/user/wspace/electrum/electrum/gui/qt/bip39_recovery_dialog.py", line 40, in __init__
    fut = asyncio.run_coroutine_threadsafe(coro, network.asyncio_loop)
AttributeError: 'NoneType' object has no attribute 'asyncio_loop'
```
2023-12-01 17:37:58 +00:00
Sander van Grieken
90d1d587e8 network: async tor probe 2023-11-30 14:32:19 +01:00
Sander van Grieken
70da74166c network: no assert for port number range check 2023-11-30 14:27:32 +01:00
Sander van Grieken
297568a148 network: remove resolver monkey-patch as no local hostname lookups are performed when
enabling SOCKS5 proxy.
2023-11-30 14:27:31 +01:00
Sander van Grieken
667485b17e network: split off proxy_user and proxy_pass from serialized proxy string and add separate cmdline params and config keys for them.
support parsing both old style mode:host:port:user:pass and new mode:host:port, where new form also accepts IPv6 addresses
2023-11-30 14:27:31 +01:00
ThomasV
7447cf9dcc lnworker: always initialize self.config in constructor 2023-11-13 14:54:40 +01:00
SomberNight
4c63d8729b add sanity checks we don't sign tx including dummy addr
Somewhat a follow-up to 649ce979ab.

This adds some safety belts so we don't accidentally sign a tx that
contains a dummy address.
Specifically we check that tx does not contain output for dummy addr:
- in wallet.sign_transaction
- in network.broadcast_transaction

The second one is perhaps redundant, but I think it does not hurt.
2023-09-16 04:36:08 +00:00
SomberNight
f28a2824d5 qt: do not show UntrustedServerReturnedError when sweeping
We should not show the untrusted text in the GUI...
With this change, we still log the text, but otherwise it should avoid
unintentionally showing it anywhere, as the original exception is
masked away.

related: https://github.com/spesmilo/electrum/issues/8599#issuecomment-1706775508

Example traceback (and the exc is then shown in main_window.on_error):
```
 10.77 | D | n/network | got error from server for Network.listunspent_for_scripthash: <UntrustedServerReturnedError [DO NOT TRUST THIS MESSAGE] original_exception: "RPCError(0, 'heyheyhey')">
 10.78 | E | gui.qt.main_window.[test_segwit_2] | on_error
Traceback (most recent call last):
  File "...\electrum\electrum\network.py", line 898, in wrapper
    return await func(self, *args, **kwargs)
  File "...\electrum\electrum\network.py", line 1149, in listunspent_for_scripthash
    return await self.interface.listunspent_for_scripthash(sh)
  File "...\electrum\electrum\interface.py", line 1027, in listunspent_for_scripthash
    raise aiorpcx.jsonrpc.RPCError(0, "heyheyhey")
aiorpcx.jsonrpc.RPCError: (0, 'heyheyhey')

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

Traceback (most recent call last):
  File "...\electrum\electrum\gui\qt\util.py", line 925, in run
    result = task.task()
  File "...\electrum\electrum\gui\qt\main_window.py", line 2505, in <lambda>
    task = lambda: self.network.run_from_another_thread(
  File "...\electrum\electrum\network.py", line 383, in run_from_another_thread
    return fut.result(timeout)
  File "...\Python310\lib\concurrent\futures\_base.py", line 458, in result
    return self.__get_result()
  File "...\Python310\lib\concurrent\futures\_base.py", line 403, in __get_result
    raise self._exception
  File "...\electrum\electrum\wallet.py", line 151, in sweep_preparations
    async with OldTaskGroup() as group:
  File "...\aiorpcX\aiorpcx\curio.py", line 304, in __aexit__
    await self.join()
  File "...\electrum\electrum\util.py", line 1316, in join
    task.result()
  File "...\electrum\electrum\wallet.py", line 142, in find_utxos_for_privkey
    await _append_utxos_to_inputs(
  File "...\electrum\electrum\wallet.py", line 129, in _append_utxos_to_inputs
    u = await network.listunspent_for_scripthash(scripthash)
  File "...\electrum\electrum\network.py", line 872, in make_reliable_wrapper
    async with OldTaskGroup(wait=any) as group:
  File "...\aiorpcX\aiorpcx\curio.py", line 304, in __aexit__
    await self.join()
  File "...\electrum\electrum\util.py", line 1327, in join
    self.completed.result()
  File "...\electrum\electrum\network.py", line 903, in wrapper
    raise wrapped_exc from e
electrum.network.UntrustedServerReturnedError: The server returned an error.
```
2023-09-05 15:47:33 +00:00
ThomasV
5f3a1f0b71 do not spam log with fee_histogram 2023-08-14 09:58:17 +02:00
SomberNight
d51f00e2a3 asyncio.wait_for() is too buggy. use util.wait_for2() instead
wasted some time because asyncio.wait_for() was suppressing cancellations. [0][1][2]
deja vu... [3]

Looks like this is finally getting fixed in cpython 3.12 [4]
So far away...
In attempt to avoid encountering this again, let's try using
asyncio.timeout in 3.11, which is how upstream reimplemented wait_for in 3.12 [4], and
aiorpcx.timeout_after in 3.8-3.10.

[0] https://github.com/python/cpython/issues/86296
[1] https://bugs.python.org/issue42130
[2] https://bugs.python.org/issue45098
[3] https://github.com/kyuupichan/aiorpcX/issues/44
[4] https://github.com/python/cpython/pull/98518
2023-08-04 18:18:21 +00:00
Sander van Grieken
1e725b6baa break the cyclic dependency 2023-06-28 16:49:28 +02:00
SomberNight
24980feab7 config: introduce ConfigVars
A new config API is introduced, and ~all of the codebase is adapted to it.
The old API is kept but mainly only for dynamic usage where its extra flexibility is needed.

Using examples, the old config API looked this:
```
>>> config.get("request_expiry", 86400)
604800
>>> config.set_key("request_expiry", 86400)
>>>
```

The new config API instead:
```
>>> config.WALLET_PAYREQ_EXPIRY_SECONDS
604800
>>> config.WALLET_PAYREQ_EXPIRY_SECONDS = 86400
>>>
```

The old API operated on arbitrary string keys, the new one uses
a static ~enum-like list of variables.

With the new API:
- there is a single centralised list of config variables, as opposed to
  these being scattered all over
- no more duplication of default values (in the getters)
- there is now some (minimal for now) type-validation/conversion for
  the config values

closes https://github.com/spesmilo/electrum/pull/5640
closes https://github.com/spesmilo/electrum/pull/5649

Note: there is yet a third API added here, for certain niche/abstract use-cases,
where we need a reference to the config variable itself.
It should only be used when needed:
```
>>> var = config.cv.WALLET_PAYREQ_EXPIRY_SECONDS
>>> var
<ConfigVarWithConfig key='request_expiry'>
>>> var.get()
604800
>>> var.set(3600)
>>> var.get_default_value()
86400
>>> var.is_set()
True
>>> var.is_modifiable()
True
```
2023-05-25 17:39:48 +00:00
SomberNight
03ab33f4b2 SimpleConfig: change API of set_key(): "save" is now kwarg-only 2023-05-25 17:37:16 +00:00
SomberNight
fd41308c6b network: log original error text in catch_server_exceptions
related: https://github.com/spesmilo/electrum/issues/8439
2023-05-16 15:10:12 +00:00
SomberNight
53d61c011a qml network: restrict cases where server is shown "lagging" 2023-05-03 13:49:44 +00:00
SomberNight
e2406f21b4 fix flake8-bugbear B011
B011 Do not call assert False since python -O removes these calls. Instead callers should raise AssertionError().
2023-04-24 12:58:19 +00:00
SomberNight
312f2641e7 don't use bare except
use "except Exception", or if really needed explicitly "except BaseException"
2023-04-24 12:58:01 +00:00
SomberNight
a6c36b8588 regtests: test_watchtower started failing due to newly exposed bug
local_watchtower.adb.start_network was getting called twice.

follow-up 6ac3f84095

```
20230418T014725.636141Z |    ERROR | __main__ |
Traceback (most recent call last):
  File "/home/user/wspace/electrum/./run_electrum", line 435, in main
    handle_cmd(
  File "/home/user/wspace/electrum/./run_electrum", line 469, in handle_cmd
    d = daemon.Daemon(config, fd)
  File "/home/user/wspace/electrum/electrum/util.py", line 462, in <lambda>
    return lambda *args, **kw_args: do_profile(args, kw_args)
  File "/home/user/wspace/electrum/electrum/util.py", line 458, in do_profile
    o = func(*args, **kw_args)
  File "/home/user/wspace/electrum/electrum/daemon.py", line 404, in __init__
    self.network = Network(config, daemon=self)
  File "/home/user/wspace/electrum/electrum/network.py", line 348, in __init__
    self.local_watchtower.adb.start_network(self)
  File "/home/user/wspace/electrum/electrum/address_synchronizer.py", line 185, in start_network
    assert self.network is None, "already started"
AssertionError: already started
```
2023-04-18 02:02:07 +00:00
ThomasV
08c478f8d2 network: use IntEnum for connection states. Export user-visible strings in get_connection_status_for_GUI 2023-04-14 15:55:03 +02:00
ThomasV
697bf2b1c8 Revert commit ddd778f7f7.
This fixes #8298. The initial commit was good.
2023-04-10 21:23:50 +02:00
ThomasV
ddd778f7f7 follow-up previous commit 2023-04-09 11:32:01 +02:00