RunCoroutineDialog has a run() method that blocks the thread
without blocking the GUI (using exec), and a Cancel button
that cancels the coroutine.
main_window.run_coroutine_dialog() is a wrapper that returns
the coroutine result and may raise exceptions.
BlockingWaitingDialog was removed is transaction_dialog,
where it was not particularly useful.
I just had a channel force-closed over a fee-estimate-disagreement :(
Scenario:
1. started electrum, opened wallet
2. waited around 10 seconds, opened the lightning channels overview, saw that channels are open/ready
3. after around 10 more seconds, scanned bolt11 invoice and tried to pay
4. channel got force-closed
Before this commit, we only call maybe_update_fee via lnwatcher callbacks.
These callbacks trigger on events such as "adb_set_up_to_date", "blockchain_updated", "network_updated", "fee".
In my case there was a race that all these events triggered *before* the channel got reestablished
(in fact before the peer handshake finished). And also, by chance there were none of these events after
the reestablish but before I sent the HTLC.
When I sent the HTLC, the channel counterparty (eclair) sent back an "error" msg that the feerates are
too different, which led us to do a local-force-close.
I have other channels in this wallet (with other peers), which reestablished faster and got lucky with
timing: the lnwatcher callbacks came just in time to trigger update_fee for them.
```
20241017T222847.598163Z | INFO | lnpeer.Peer.[LNWallet, 03ecef675b-98960573] | handshake done for 03ecef675be448b615e6176424070673ef8284e0fd19d8be062a6cb5b130a0a0d1@lightning.electrum.org:9740
20241017T222847.602594Z | DEBUG | lnpeer.Peer.[LNWallet, 03ecef675b-98960573] | Sending INIT
20241017T222847.641383Z | DEBUG | lnpeer.Peer.[LNWallet, 03ecef675b-98960573] | Received INIT
20241017T222847.655041Z | DEBUG | lnpeer.Peer.[LNWallet, 03ecef675b-98960573] | Sending CHANNEL_REESTABLISH
20241017T222847.658355Z | INFO | lnpeer.Peer.[LNWallet, 03ecef675b-98960573] | channel_reestablish (<redacted_shortchanid>): sent channel_reestablish with (next_local_ctn=157, oldest_unrevoked_remote_ctn=156)
20241017T222847.659524Z | INFO | lnpeer.Peer.[LNWallet, 03ecef675b-98960573] | reestablish_channel was called but channel <redacted_shortchanid> already in peer_state <PeerState.REESTABLISHING: 1>
20241017T222847.660491Z | INFO | lnpeer.Peer.[LNWallet, 03ecef675b-98960573] | reestablish_channel was called but channel <redacted_shortchanid> already in peer_state <PeerState.REESTABLISHING: 1>
20241017T222847.661442Z | INFO | lnpeer.Peer.[LNWallet, 03ecef675b-98960573] | reestablish_channel was called but channel <redacted_shortchanid> already in peer_state <PeerState.REESTABLISHING: 1>
20241017T222847.662768Z | INFO | lnpeer.Peer.[LNWallet, 03ecef675b-98960573] | reestablish_channel was called but channel <redacted_shortchanid> already in peer_state <PeerState.REESTABLISHING: 1>
20241017T222847.669875Z | DEBUG | lnpeer.Peer.[LNWallet, 03ecef675b-98960573] | Received QUERY_CHANNEL_RANGE
20241017T222847.690318Z | DEBUG | lnpeer.Peer.[LNWallet, 03ecef675b-98960573] | Received GOSSIP_TIMESTAMP_FILTER
20241017T222847.705782Z | DEBUG | lnpeer.Peer.[LNWallet, 03ecef675b-98960573] | Received CHANNEL_REESTABLISH
20241017T222847.707932Z | INFO | lnpeer.Peer.[LNWallet, 03ecef675b-98960573] | channel_reestablish (<redacted_shortchanid>): received channel_reestablish with (their_next_local_ctn=157, their_oldest_unrevoked_remote_ctn=156)
20241017T222847.712504Z | INFO | lnpeer.Peer.[LNWallet, 03ecef675b-98960573] | channel_reestablish (<redacted_shortchanid>): replayed 0 unacked messages. []
20241017T222847.716096Z | DEBUG | lnpeer.Peer.[LNWallet, 03ecef675b-98960573] | Sending CHANNEL_READY
20241017T222847.738709Z | INFO | lnpeer.Peer.[LNWallet, 03ecef675b-98960573] | saved remote channel_update gossip msg for chan <redacted_shortchanid>
20241017T222907.627447Z | INFO | lnpeer.Peer.[LNWallet, 03ecef675b-98960573] | lnpeer.pay len(route)=1
20241017T222907.628927Z | INFO | lnpeer.Peer.[LNWallet, 03ecef675b-98960573] | 0: edge=<redacted_shortchanid> hop_data=<OnionHopsDataSingle. payload={<redacted>}. hmac=None>
20241017T222907.629184Z | INFO | lnpeer.Peer.[LNWallet, 03ecef675b-98960573] | adding trampoline onion to final payload
20241017T222907.629405Z | INFO | lnpeer.Peer.[LNWallet, 03ecef675b-98960573] | lnpeer.pay len(t_route)=2
20241017T222907.629653Z | INFO | lnpeer.Peer.[LNWallet, 03ecef675b-98960573] | 0: t_node=03ecef675be448b615e6176424070673ef8284e0fd19d8be062a6cb5b130a0a0d1 hop_data=<OnionHopsDataSingle. payload={<redacted>}. hmac=<redacted>>
20241017T222907.629894Z | INFO | lnpeer.Peer.[LNWallet, 03ecef675b-98960573] | 1: t_node=<redacted> hop_data=<OnionHopsDataSingle. payload={<redacted>}. hmac=b'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00'>
20241017T222907.631495Z | INFO | lnpeer.Peer.[LNWallet, 03ecef675b-98960573] | starting payment. len(route)=1.
20241017T222907.633075Z | INFO | lnpeer.Peer.[LNWallet, 03ecef675b-98960573] | starting payment. htlc: UpdateAddHtlc(amount_msat=<redacted>, payment_hash=<redacted>, cltv_abs=<redacted>, timestamp=1729204147, htlc_id=66)
20241017T222907.633385Z | DEBUG | lnpeer.Peer.[LNWallet, 03ecef675b-98960573] | Sending UPDATE_ADD_HTLC
20241017T222907.635118Z | INFO | lnpeer.Peer.[LNWallet, 03ecef675b-98960573] | send_commitment. chan <redacted_shortchanid>. ctn: 157.
20241017T222907.643229Z | DEBUG | lnpeer.Peer.[LNWallet, 03ecef675b-98960573] | Sending COMMITMENT_SIGNED
20241017T222907.721929Z | DEBUG | lnpeer.Peer.[LNWallet, 03ecef675b-98960573] | Received ERROR
20241017T222907.722621Z | INFO | lnpeer.Peer.[LNWallet, 03ecef675b-98960573] | remote peer sent error [DO NOT TRUST THIS MESSAGE]: 'local/remote feerates are too different: remoteFeeratePerKw=<redacted_low_val> localFeeratePerKw=50125'. chan_id=<redacted>. is_known_chan_id=True
20241017T222907.734272Z | DEBUG | lnchannel.Channel.[<redacted_shortchanid>] | Setting channel state: OPEN -> FORCE_CLOSING
20241017T222907.825540Z | INFO | lnpeer.Peer.[LNWallet, 03ecef675b-98960573] | Disconnecting: GracefulDisconnect()
```
yay
Given how few providers have free historical APIs, each one is very much appreciated.
They are doing a public service. Thanks. Not that they ever read commit messages. :)
```
cannot find currencies.json. will regenerate it now.
Traceback (most recent call last):
File "...\electrum\run_electrum", line 94, in <module>
from electrum.logging import get_logger, configure_logging # import logging submodule first
File "...\electrum\electrum\__init__.py", line 27, in <module>
from . import daemon
File "...\electrum\electrum\daemon.py", line 55, in <module>
from .exchange_rate import FxThread
File "...\electrum\electrum\exchange_rate.py", line 539, in <module>
CURRENCIES = get_exchanges_and_currencies()
File "...\electrum\electrum\exchange_rate.py", line 529, in get_exchanges_and_currencies
loop = util.get_asyncio_loop()
File "...\electrum\electrum\util.py", line 1578, in get_asyncio_loop
raise Exception("event loop not created yet")
Exception: event loop not created yet
```
```
$ ./run_electrum --testnet signmessage -w /home/user/.electrum/testnet/wallets/test_trezor_white_bip84 tb1q5pguna9y2g9y2gsu8r8gmxeye2cefvyly8dg02 heyheyhey -o
0.84 | W | plugins.jade.jadepy.jade | No module named 'electrum.plugins.jade.jadepy.jade_ble'
0.84 | W | plugins.jade.jadepy.jade | BLE scanning/connectivity will not be available
3.73 | E | __main__ | error running command (without daemon)
Traceback (most recent call last):
File "/home/user/wspace/electrum/electrum/plugins/trezor/clientbase.py", line 151, in get_xpub
node = trezorlib.btc.get_public_node(self.client, address_n).node
File "/home/user/.local/lib/python3.10/site-packages/trezorlib/tools.py", line 274, in wrapped_f
ret = f(*args, **kwargs)
File "/home/user/.local/lib/python3.10/site-packages/trezorlib/btc.py", line 125, in get_public_node
return client.call(
File "/home/user/.local/lib/python3.10/site-packages/trezorlib/tools.py", line 297, in wrapped_f
return f(client, *args, **kwargs)
File "/home/user/.local/lib/python3.10/site-packages/trezorlib/client.py", line 260, in call
resp = self._callback_pin(resp)
File "/home/user/.local/lib/python3.10/site-packages/trezorlib/client.py", line 186, in _callback_pin
pin = self.ui.get_pin(msg.type)
File "/home/user/wspace/electrum/electrum/plugins/trezor/clientbase.py", line 308, in get_pin
pin = self.handler.get_pin(msg.format(self.device), show_strength=show_strength)
AttributeError: 'NoneType' object has no attribute 'get_pin'
During handling of the above exception, another exception occurred:
Traceback (most recent call last):
File "/home/user/wspace/electrum/./run_electrum", line 540, in handle_cmd
result = fut.result()
File "/usr/lib/python3.10/concurrent/futures/_base.py", line 458, in result
return self.__get_result()
File "/usr/lib/python3.10/concurrent/futures/_base.py", line 403, in __get_result
raise self._exception
File "/home/user/wspace/electrum/./run_electrum", line 227, in run_offline_command
password = get_password_for_hw_device_encrypted_storage(plugins)
File "/home/user/wspace/electrum/./run_electrum", line 212, in get_password_for_hw_device_encrypted_storage
return client.get_password_for_storage_encryption()
File "/home/user/wspace/electrum/electrum/plugin.py", line 523, in wrapper
return run_in_hwd_thread(partial(func, *args, **kwargs))
File "/home/user/wspace/electrum/electrum/plugin.py", line 516, in run_in_hwd_thread
return fut.result()
File "/usr/lib/python3.10/concurrent/futures/_base.py", line 458, in result
return self.__get_result()
File "/usr/lib/python3.10/concurrent/futures/_base.py", line 403, in __get_result
raise self._exception
File "/usr/lib/python3.10/concurrent/futures/thread.py", line 58, in run
result = self.fn(*self.args, **self.kwargs)
File "/home/user/wspace/electrum/electrum/plugins/hw_wallet/plugin.py", line 260, in get_password_for_storage_encryption
xpub = self.get_xpub(derivation, "standard")
File "/home/user/wspace/electrum/electrum/plugin.py", line 523, in wrapper
return run_in_hwd_thread(partial(func, *args, **kwargs))
File "/home/user/wspace/electrum/electrum/plugin.py", line 513, in run_in_hwd_thread
return func()
File "/home/user/wspace/electrum/electrum/plugins/trezor/clientbase.py", line 150, in get_xpub
with self.run_flow(creating_wallet=creating):
File "/home/user/wspace/electrum/electrum/plugins/trezor/clientbase.py", line 89, in __exit__
self.end_flow()
File "/home/user/wspace/electrum/electrum/plugins/trezor/clientbase.py", line 82, in end_flow
self.handler.finished()
AttributeError: 'NoneType' object has no attribute 'finished'
```
- include a copy of pinmatrix.py from python-trezor, as-is
- adapt that to qt6: the upstream version(s) only support qt4/qt5
- use it in trezor/keepkey/safet plugins
3f1d2059ca/python/src/trezorlib/qt/pinmatrix.py
I will use this in the trezor (and clones) plugins in a modified form to work with qt6.
Otherwise we would have to ask the trezor devs, who would actually respond,
but also the keepkey and safet lib authors, who would not... to support qt6.