```
electrum/tests/test_network.py::TestNetwork::test_can_connect_during_backward
electrum/tests/test_network.py::TestNetwork::test_chain_false_during_binary
electrum/tests/test_network.py::TestNetwork::test_fork_conflict
electrum/tests/test_network.py::TestNetwork::test_fork_noconflict
/tmp/cirrus-ci-build/electrum/interface.py:410: RuntimeWarning: coroutine 'Interface.run' was never awaited
task = await self.network.taskgroup.spawn(self.run())
Enable tracemalloc to get traceback where the object was allocated.
See https://docs.pytest.org/en/stable/how-to/capture-warnings.html#resource-warnings for more info.
```
closes https://github.com/spesmilo/electrum/pull/7817
Manage global event loop so that it is accessible to threads
other than the asyncio thread. In particular, the Plugins
thread needs to reference it in its on_stop().
Due to an indendation error, fw_info was returned only for one
HTLC of the MPP. Thus, maybe_fulfill_htlc was called again with
the remaining HTLCs, which could possibly be failed due to MPP
timeout, resulting in fund loss for the forwarder.
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.
```
script destinations.
This is mainly to support OP_RETURN outputs, which typically have a zero amount output value,
but as we don't special case OP_RETURN, this is currently done for all non-address scripts
Also, it's probably good to add a warning popup for OP_RETURN outputs with a non-zero output value, but this
would also need special casing for OP_RETURN.
Saving of script output payment identifiers is disabled for now, as reading the script from the stored invoice
back into human-readable form is currently not implemented, and currently only lightning invoices or address output
is supported.
Fix '!' amount expand while PaymentIdentifier not set due to editor pushback timer.
Fix '!' amount expand for BIP21 without a specified payment amount.
We never really supported pypy - the CI was running the tests there
just to see compatibility.
A few of the unit tests consistently hang, resulting in the whole
test runner timing out and wasting compute resources. Someone could
debug the hangs and try to fix them, but I don't have the time.
ChannelDB.load_data() takes ~15 seconds. Previously if the user tried
to close the program while load_data is running, we would block until
load_data() finished. (e.g. consider starting and immediately stopping
Electrum)
Now instead we can abort load_data early.
Electrum clients that have non-trampoline channels.
- if an invoice supports trampoline, but provides only
non-trampoline nodes in its routing hints, we must use
a legacy trampoline payment
- when we create a trampoline onion for a legacy payment,
the invoice_features field is a u64, so we need to remove
high feature bits.
Plugins.stop() is now part of the normal shutdown flow (since 90f39bce88),
so this shaves up to 100 ms off that (avg: 50 ms).
It is also waited on in around ~60 unit tests: this saves 3 sec.
In python 3.8 and 3.9, asyncio.Event/Lock/etc cannot be created before the
event loop itself is created. Hence, to have Plugins.__init__ create an
Event, we need to postpone creating Plugins() from setUpClass to setUp.
follow-up 90f39bce88
Plugins.stop was never called, so the Plugins thread only stopped
because of the is_running() check in run(), which triggers too late:
the Plugins thread was stopping after the main thread stopped.
E.g. playing around in the qt wizard with wallet creation for a Trezor,
and closing the wizard (only window):
``` 24.85 | E | p/plugin.Plugins |
Traceback (most recent call last):
File "/home/user/wspace/electrum/electrum/util.py", line 386, in run_jobs
job.run()
File "/home/user/wspace/electrum/electrum/plugin.py", line 430, in run
client.timeout(cutoff)
File "/home/user/wspace/electrum/electrum/plugin.py", line 363, in wrapper
return run_in_hwd_thread(partial(func, *args, **kwargs))
File "/home/user/wspace/electrum/electrum/plugin.py", line 355, in run_in_hwd_thread
fut = _hwd_comms_executor.submit(func)
File "/usr/lib/python3.10/concurrent/futures/thread.py", line 167, in submit
raise RuntimeError('cannot schedule new futures after shutdown')
RuntimeError: cannot schedule new futures after shutdown
```
- @amount_msat.validator prevents the creation of invoices with e.g. too large amounts
- however the qml gui is mutating invoices by directly setting the `amount_msat` field,
and it looks like attrs validators only run during init.
We can use `on_setattr` (introduced in attrs==20.1.0).
- a wallet db upgrade is added to rm existing insane invoices
- btw the qml gui was already doing its own input validation on the textedit
(see qeconfig.btcAmountRegex). however that only limits the input to not have more
chars than what is needed to represent 21M BTC (e.g. you can still enter 99M BTC,
which the invoice logic does not tolerate later on - but is normally caught).
fixes https://github.com/spesmilo/electrum/issues/8582
Note: We should probably require the password in load_wallet,
and store it in memory as long as the wallet is loaded. In that
case, commands that currently require a password would no longer
require it if the wallet is loaded.