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
```
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.
- when creating an invoice, if we had multiple chans with the same trampoline,
were putting duplicate t-hints into the invoice
- when paying an invoice that had duplicate t-hints, we would sometimes
construct invalid paths (SRC>T1->T1->DST)
follow-up https://github.com/spesmilo/electrum/pull/8536
This replaces 69336befee, which was insufficient.
#8536 added a new field into the struct, which older versions do not ignore but raise:
opening a wallet file with new code updated the struct to include it,
after which old code could no longer open the wallet file.
i.e. #8536 was an invisible wallet upgrade, breaking compat.
This commit simply formalises the wallet upgrade: old code will now show
an understandable error when trying to open new files.
The input_qr_from_screenshot functionality is broken on some Linux machines:
on some machines, `screen.grabWindow(0)` returns an all-black image.
In such cases, instead of telling the user "No QR code was found on the screen",
we will tell them "Failed to take screenshot".
To test:
`QApplication.instance().primaryScreen().grabWindow(0).save("/home/user/wspace/tmp/pic2.png", "png")`
Tested on:
- machine 1:
- ubuntu 22.04, gnome, wayland
- pyqt.version: 5.15.9
- qt.version: 5.15.2
=> gets all-black image for screenshot
- machine 2:
- manjaro, kde, x11
- pyqt.version: 5.15.9
- qt.version: 5.15.8
=> screenshot works
I guess it might be due to x11 vs wayland.
eclair sends CHANNEL_DISABLED if its peer is offline. E.g. we might be
trying to pay a mobile phone with the app closed. In that case we
should not cache the CHANNEL_DISABLED for too long.
LnFeatures.supports() is became part of the hot path of
LNPathFinder.find_path_for_payment()
in 6b43eac6fd,
which made find_path_for_payment considerably slower than before.
It used to take around 0.8 sec originally, then after linked commit went to ~9 sec,
and now this takes it down to ~1.1 sec (on my laptop).
otherwise I can't click on list items if the window is moved too far to the right :O
follow-up 583afefe33
Note: on modern Android, apps don't always run full-screen.
You can pop them out into small windows and move them.
Haven't tested how the deadzones work then though.
```
191.73 | D | i/interface.[btc.electroncash.dk:60002] | (disconnect) trace for RPCError(-32603, 'internal error: bitcoind request timed out')
Traceback (most recent call last):
File "...\electrum\electrum\interface.py", line 514, in wrapper_func
return await func(self, *args, **kwargs)
File "...\electrum\electrum\interface.py", line 537, in run
await self.open_session(ssl_context)
File "...\electrum\electrum\interface.py", line 687, in open_session
async with self.taskgroup as group:
File "...\aiorpcX\aiorpcx\curio.py", line 304, in __aexit__
await self.join()
File "...\electrum\electrum\util.py", line 1309, in join
task.result()
File "...\electrum\electrum\interface.py", line 724, in request_fee_estimates
async with OldTaskGroup() as group:
File "...\aiorpcX\aiorpcx\curio.py", line 304, in __aexit__
await self.join()
File "...\electrum\electrum\util.py", line 1309, in join
task.result()
File "...\electrum\electrum\interface.py", line 1128, in get_estimatefee
res = await self.session.send_request('blockchain.estimatefee', [num_blocks])
File "...\electrum\electrum\interface.py", line 169, in send_request
response = await util.wait_for2(
File "...\electrum\electrum\util.py", line 1383, in wait_for2
return await asyncio.ensure_future(fut, loop=get_running_loop())
File "...\aiorpcX\aiorpcx\session.py", line 540, in send_request
return await self._send_concurrent(message, future, 1)
File "...\aiorpcX\aiorpcx\session.py", line 512, in _send_concurrent
return await future
aiorpcx.jsonrpc.RPCError: (-32603, 'internal error: bitcoind request timed out')
```
```
93.60 | E | asyncio | Task exception was never retrieved
future: <Task finished name='Task-7385' coro=<Interface.get_estimatefee() done, defined at ...\electrum\electrum\interface.py:1123> exception=RPCError(-32603, 'internal error: bitcoind request timed out')>
Traceback (most recent call last):
File "...\electrum\electrum\interface.py", line 1132, in get_estimatefee
res = await self.session.send_request('blockchain.estimatefee', [num_blocks])
File "...\electrum\electrum\interface.py", line 169, in send_request
response = await util.wait_for2(
File "...\electrum\electrum\util.py", line 1383, in wait_for2
return await asyncio.ensure_future(fut, loop=get_running_loop())
File "...\aiorpcX\aiorpcx\session.py", line 540, in send_request
return await self._send_concurrent(message, future, 1)
File "...\aiorpcX\aiorpcx\session.py", line 512, in _send_concurrent
return await future
aiorpcx.jsonrpc.RPCError: (-32603, 'internal error: bitcoind request timed out')
```
- client requests payment_hash from the server
- client sends an invoice with that hash
- client waits to receive HTLCs, then broadcasts funding tx
This means that we now use same script for normal and reverse swaps.
The new flow is enabled by setting option LIGHTNING_SWAP_HTLC_FIRST
in the client. The old protocol is still supported server-side.
if qt is not installed, e.g. on a server, was getting:
```
$ ./run_electrum sadasdasddsa
Traceback (most recent call last):
File "/home/user/wspace/electrum/./run_electrum", line 532, in <module>
main()
File "/home/user/wspace/electrum/./run_electrum", line 383, in main
lang = get_default_language(gui_name=gui_name)
File "/home/user/wspace/electrum/electrum/gui/default_lang.py", line 23, in get_default_language
from PyQt5.QtCore import QLocale
ModuleNotFoundError: No module named 'PyQt5.QtCore'
```
```
$ ./run_electrum sadasdasddsa
Traceback (most recent call last):
File "/home/user/wspace/electrum/./run_electrum", line 532, in <module>
main()
File "/home/user/wspace/electrum/./run_electrum", line 398, in main
if uri and not PaymentIdentifier(None, uri).is_valid():
File "/home/user/wspace/electrum/electrum/payment_identifier.py", line 136, in __init__
self.parse(text)
File "/home/user/wspace/electrum/electrum/payment_identifier.py", line 265, in parse
elif contact := self.contacts.by_name(text):
AttributeError: 'NoneType' object has no attribute 'by_name'
```
- rename trampoline_forwardings -> final_onion_forwardings,
because this dict is used for both trampoline and hold invoices
- remove timeout from hold_invoice_callbacks (redundant with invoice)
- add test_failure boolean parameter to TestPeer._test_simple_payment,
in order to test correct propagation of OnionRoutingFailures.
- maybe_fulfill_htlc: raise an OnionRoutingFailure if we do not have
the preimage for a payment that does not have a hold invoice callback.
Without this, the above unit tests stall when we use test_failure=True