closes https://github.com/spesmilo/electrum/issues/7677
```
E/n | network | taskgroup died.
Traceback (most recent call last):
File "/opt/electrum/electrum/network.py", line 1204, in main
[await group.spawn(job) for job in self._jobs]
File "/home/voegtlin/.local/lib/python3.8/site-packages/aiorpcx/curio.py", line 297, in __aexit__
await self.join()
File "/opt/electrum/electrum/util.py", line 1255, in join
task.result()
File "/opt/electrum/electrum/network.py", line 1277, in _maintain_sessions
await maintain_main_interface()
File "/opt/electrum/electrum/network.py", line 1268, in maintain_main_interface
await self._ensure_there_is_a_main_interface()
File "/opt/electrum/electrum/network.py", line 1245, in _ensure_there_is_a_main_interface
await self._switch_to_random_interface()
File "/opt/electrum/electrum/network.py", line 648, in _switch_to_random_interface
await self.switch_to_interface(random.choice(servers))
File "/opt/electrum/electrum/network.py", line 714, in switch_to_interface
await i.taskgroup.spawn(self._request_server_info(i))
File "/home/voegtlin/.local/lib/python3.8/site-packages/aiorpcx/curio.py", line 204, in spawn
self._add_task(task)
File "/home/voegtlin/.local/lib/python3.8/site-packages/aiorpcx/curio.py", line 150, in _add_task
raise RuntimeError('task group terminated')
RuntimeError: task group terminated
```
I believe the "suppress spurious cancellations" block was added as SilentTaskGroup raised
CancelledError instead of RuntimeError for this scenario.
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
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
Adds liquidity hints for the sending capabilities of routing channels in the
graph. The channel blacklist is incorporated into liquidity hints.
Liquidity hints are updated when a payment fails with a temporary
channel failure or when it succeeds. Liquidity hints are used to give a
penalty in the _edge_cost heuristics used by the pathfinding algorithm.
The base penalty in (_edge_cost) is removed because it is now part of the
liquidity penalty. We don't return early from get_distances, as we want
to explore all channels.
It is not realistic to expect Electrum to be used as a watchtower
in GUI mode, and possibly counter-productive (may set wrong
expectations).
A proper watchtower should be configured as a daemon. The
documentation will be updated to reflect this change.
e.g. kivy GUI refreshes some fields based on this callback;
this should result in faster refreshes
(otherwise e.g. when switching servers, a callback might only come if
we successfully connect to the new server; or if an unrelated event
triggers it)
- trampoline is enabled by default in config, to prevent download of `gossip_db`.
(if disabled, `gossip_db` will be downloaded, regardless of the existence of channels)
- if trampoline is enabled:
- the wallet can only open channels with trampoline nodes
- already-existing channels with non-trampoline nodes are frozen for sending.
- there are two types of trampoline payments: legacy and end-to-end (e2e).
- we decide to perform legacy or e2e based on the invoice:
- we use trampoline_routing_opt in features to detect Eclair and Phoenix invoices
- we use trampoline_routing_hints to detect Electrum invoices
- when trying a legacy payment, we add a second trampoline to the path to preserve privacy.
(we fall back to a single trampoline if the payment fails for all trampolines)
- the trampoline list is hardcoded, it will remain so until `trampoline_routing_opt` feature flag is in INIT.
- there are currently only two nodes in the hardcoded list, it would be nice to have more.
- similar to Phoenix, we find the fee/cltv by trial-and-error.
- if there is a second trampoline in the path, we use the same fee for both.
- the final spec should add fee info in error messages, so we will be able to fine-tune fees
This was a regression from e83f0dd3fc,
introduced by the change in connection_down() there.
(if the initial connection to the main interface is not successful, the
network status will not be set to 'disconnected' - but it should be)
That change is now reverted here.
That change was somewhat independent of the rest of that commit,
except the rest highlighted that something of the sort was needed:
as it might sometimes take many seconds for an interface to close
and we might launch another interface for the same server while the
first one is still closing, the "server == self.default_server" test
is highly problematic.
To fix this second - original - issue, we now introduce a "closing" state
for interfaces (in the form of network._closing_ifaces).
The GUI blocks until network.set_parameters returns when switching servers,
which waits for switch_to_interface, which used to wait until interface.close()
returns. interface.close() tries to flush buffered writes to the wire, with a
30 sec timeout.
If the server or the network connection is slow, flushing the buffer can take
several seconds. In particular, servers running Fulcrum always seem to
timeout in this case, freezing the GUI for 30 seconds (when switching away).
The gossip db is loaded early when the network is started to save
time when the gui is locked and a wallet not yet loaded. Side effects
of the LNWallet to start peering when a channel db is loaded is
circumvented.
Enables lightning by creating a node private key and storing it in
the wallet. The gossiper is not launched at start up, only if there
are existing channels.
some basic sanity checks
Previously if the server sent back a malformed response, it could partially corrupt a wallet file.
(as sometimes the response would get persisted, and issues would only arise later when the values were used)
Previously this function would not switch to a different chain if the
current chain contained the preferred block. This was not the intended
behaviour: if there is a *stronger* chain that *also* contains the
preferred block, we should jump to that.
Note that with this commit there will now always be a preferred block
(defaults to genesis). Previously, it might seem that often there was none,
but actually in practice if the user used the GUI context menu to switch
servers even once, there was one (usually genesis).
Hence, with the old code, if an attacker mined a single header which
then got reorged, auto_connect clients which were connected to the
attacker's server would never switch servers (jump chains) even
without the user explicitly configuring preference for the stale branch.
Data returned by the main server for request "server.peers.subscribe"
is of course untrusted input. Previously if it contained e.g. invalid port numbers
or IP addresses, it could kill the whole network taskgroup.
(this might have only affected master and not released versions,
which would only raise exceptions once the client actually tried to connect to an invalid host/port)
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")