1
0
Commit Graph

1133 Commits

Author SHA1 Message Date
ThomasV
fdee31af05 Qt settings_dialog: use signals
- changes must apply to all windows
 - do not keep reference to the window object
2022-04-29 17:04:16 +02:00
ThomasV
334da245dc (minor) fix checkbox in qt settings 2022-04-29 13:03:33 +02:00
ThomasV
f4e902e907 LNWorker: give up payment after timeout, not number of attempts.
Limiting attempts may interrupt a MPP before we receive a MPP_timeout
The attempts parameter is still used in unit tests.
2022-04-29 12:17:38 +02:00
ThomasV
1f7ada3486 minor: fix #7789 2022-04-28 15:26:20 +02:00
ThomasV
96433ea2b4 Merge pull request #7778 from SomberNight/202204_invoice_recalc_ids
wallet_db upgrade: recalc keys of outgoing on-chain invoices
2022-04-28 15:12:29 +02:00
ThomasV
e3beae5c00 Merge pull request #7761 from SomberNight/202204_versioninfo_cmd
add `version_info` command
2022-04-27 09:59:27 +02:00
Rogach
6d049a30f2 fix typo in warning message shown when enabling lightning (#7782) 2022-04-25 21:35:42 +00:00
ThomasV
a0a81c31bd Qt: hide receive tabs when payment is received. 2022-04-23 19:25:24 +02:00
ThomasV
31dc93eade Qt: remove QR button from receive text widget. Add tooltip instead 2022-04-23 10:43:50 +02:00
ThomasV
b9139a2472 minor fix: update_receive_address_styling 2022-04-23 09:28:41 +02:00
SomberNight
adfe542fae wallet_db upgrade: recalc keys of outgoing on-chain invoices
closes https://github.com/spesmilo/electrum/issues/7777
2022-04-22 19:53:55 +02:00
ThomasV
fb6047ec46 lnworker: fix can_pay_invoice for trampoline MPP
Call it from the GUI
2022-04-22 15:13:12 +02:00
ThomasV
d34f513532 Qt: adapt receive_lightning_help text 2022-04-22 12:03:51 +02:00
ThomasV
7be7ea71db follow-up e992e3a9b2 2022-04-21 11:50:42 +02:00
ThomasV
e992e3a9b2 Qt: follow-up e362d1aac4 2022-04-20 13:42:06 +02:00
ThomasV
ba018c707f Qt: add bolt11_fallback and bip21_lightning options to preferences 2022-04-20 12:48:22 +02:00
ThomasV
0c64a884c9 Qt: show single balance in statusbar
- details in popup dialop
  - piechart in status bar
2022-04-20 12:48:22 +02:00
ThomasV
60865f3902 Show options if we do not have the liquidity to pay a lightning invoice:
pay onchain, open channel, rebalance.

If we do a swap or open a channel, the payment will be scheduled.
2022-04-20 12:48:22 +02:00
ThomasV
2c6e36e89d Fallback addresses
- add fallback address to BOLT-11 LN invoices
   - Qt: if LN payment fails, propose onchain fallback
2022-04-20 12:48:22 +02:00
ThomasV
f18a042955 Qt: receive_lightning_help text 2022-04-20 12:48:22 +02:00
ThomasV
9ba5a34800 Qt receive tab:
- show payment options in tabs: URI, Address or Lightning
 - use vertical tabs to save space
 - switch between QR and text views
 - open standalone QR window through menu, instead of clicking on QR code
2022-04-20 12:48:22 +02:00
ThomasV
7102fb732e follow-up prev:
- detect payment of requests both onchain or LN
 - create single type of requests in GUI
2022-04-20 12:48:22 +02:00
ThomasV
e392197ab9 wallet_db upgrade:
- unify lightning and onchain invoices, with optional fields for bip70 and lightning
 - add receive_address fields to submarine swaps
2022-04-20 12:48:22 +02:00
SomberNight
e47e0afa91 commands: add "version_info" cmd
example:
```
$ ./run_electrum -o version_info
{
    "aiohttp.version": "3.8.1",
    "aiorpcx.version": "0.22.1",
    "certifi.version": "2021.10.08",
    "cryptodome.version": null,
    "cryptography.path": "/home/user/.local/lib/python3.8/site-packages/cryptography",
    "cryptography.version": "3.4.6",
    "dnspython.version": "2.2.0",
    "electrum.path": "/home/user/wspace/electrum/electrum",
    "electrum.version": "4.2.1",
    "hidapi.version": "0.11.0.post2",
    "libsecp256k1.path": "/home/user/wspace/electrum/electrum/libsecp256k1.so.0",
    "libusb.path": "libusb-1.0.so",
    "libusb.version": "1.0.23.11397",
    "libzbar.path": "/home/user/wspace/electrum/electrum/libzbar.so.0",
    "pyaes.version": "1.3.0",
    "pyqt.path": "/usr/lib/python3/dist-packages/PyQt5",
    "pyqt.version": "5.14.1",
    "qt.version": "5.12.8"
}
```
2022-04-11 17:40:22 +02:00
SomberNight
419fc6e1c1 gui init: raise GuiImportError instead of sys.exit if dep is missing 2022-04-11 17:40:16 +02:00
SomberNight
8e234f3ccd qt gui: better detection of missing PyQt5 at startup
If I use apt on ubuntu to install python3-pyqt5 and then remove it, it leaves an empty namespace:
```
$ python3
Python 3.8.10 (default, Mar 15 2022, 12:22:08)
[GCC 9.4.0] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>> import PyQt5
>>> import PyQt5.QtGui
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
ModuleNotFoundError: No module named 'PyQt5.QtGui'
>>> PyQt5
<module 'PyQt5' (namespace)>
```
2022-04-11 17:38:45 +02:00
SomberNight
3451140ce7 qt coins list: fix populating labels
follow-up e362d1aac4
2022-04-10 15:17:40 +02:00
ThomasV
5bd2524bfb follow-up #7748 2022-04-09 10:51:09 +02:00
ThomasV
877a9f553b Merge pull request #7748 from spesmilo/confirm_reverse_swaps
Confirm reverse swaps
2022-04-09 10:41:02 +02:00
ThomasV
3e6595ae98 Merge pull request #7756 from SomberNight/202204_qt_taskthread_cancel
qt taskthread cleaner shutdown
2022-04-09 10:38:06 +02:00
SomberNight
29c1106988 qt main_window: move TaskThread from wallet.thread to window.thread 2022-04-08 20:50:03 +02:00
SomberNight
837fc1606c address_sync: change up_to_date to be private; no lock needed to read
After some consideration I am fairly certain there is no need to take
wallet.lock in `is_up_to_date()`. Any caller that might want some kind
of guarantees re the value returned by is_up_to_date() would need to
enforce them itself by e.g. taking wallet.lock around its critical code
block. That is, even if is_up_to_date() itself takes the lock, between
the call returning and the caller reading the value there could still
have been a race.
Also, the GUI was directly accessing the field already.
2022-04-08 20:33:13 +02:00
SomberNight
214ac19f15 window.run_coroutine_from_thread: don't use wallet.thread
wallet.thread was serialising the fut.result() calls, so consider e.g.
- coro1 gets scheduled,
- wallet.thread waits on fut1.result()
- coro2 gets scheduled,
- coro2 finished with exception and wants to show an error popup,
-> wallet.thread is still waiting on fut1.result() before it looks at fut2.result
2022-04-07 20:20:30 +02:00
SomberNight
96c063028a qt TaskThread: implement cancellation of tasks, for cleaner shutdown
fixes https://github.com/spesmilo/electrum/issues/7750

Each task we schedule on `TaskThread` can provide an optional `cancel` method.
When stopping `TaskThread`, we call this `cancel` method on all tasks in the queue.
If the currently running task does not implement `cancel`, `TaskThread.stop` will block
until that task finishes.

Note that there is a significant change in behaviour here:
`ElectrumWindow.run_coroutine_from_thread` and `ElectrumWindow.pay_lightning_invoice`
previously serialised the execution of their coroutines via wallet.thread.
This is no longer the case: they will now schedule coroutines immediately.
So for example, the GUI now allows trying to pay multiple LN invoices "concurrently".
2022-04-07 19:51:58 +02:00
ThomasV
083205714c Qt: reorganize settings dialog 2022-04-01 20:20:04 +02:00
ThomasV
e362d1aac4 Qt: make display of lists more stable.
Use refresh_row() for address, utxo and contact lists.
Replace unneeded calls to update_tabs() with refresh_tabs()

Fix right-click menu after selecting multiple addresses.
2022-04-01 14:11:31 +02:00
ThomasV
f01197b6b5 Reverse swaps: Wait until funding tx is confirmed
- override with allow_instant_swaps option (Qt)
2022-04-01 14:05:01 +02:00
ThomasV
1574e10869 follow-up 92c6d91157: remove paid item from request_list 2022-04-01 11:32:57 +02:00
SomberNight
7268fa55f2 config: abstract away mempool depth format str "%.1f MB from tip"
related: 4dd94172a6
(as that commit introduced depth targets that need more precision to display)
2022-03-31 22:50:31 +02:00
SomberNight
2b13576eb3 qt history tab: fix double-clicking inside collapsible items
Swaps (both reverse and forward) are displayed in the list as a tree, which can be
expanded/collapsed. When expanded, double-clicking on any of the children (regardless
of child being LN or onchain), was interacting with the incorrect item (the first few
items in the top-level list).

Consider `self.tx_item_from_proxy_row(idx.row())`.
`idx.row()` is probably a small int, e.g. `0`, and `tx_item_from_proxy_row` is just
getting that item from the top-level list.

Note that the right-click>"View ..." context menu behaves correctly, so prior to
this commit it was inconsistent with double-clicking.
2022-03-31 19:10:39 +02:00
SomberNight
68ba223ce1 qt ConfirmTxDialog: word-wrap error message text
e.g. this text:
"This transaction requires a higher fee, or it will not be propagated by your current server. Try to raise your transaction fee, or use a server with a lower relay fee."
is too long for a single line.
2022-03-29 20:15:52 +02:00
ThomasV
a15dac2b8c channel_establishment_flow: do not save wallet file backup in the background.
Instead, display a popup everytime, if the channel is not recoverable.
2022-03-24 14:55:45 +01:00
ThomasV
92c6d91157 Qt: on status changes, refresh item in invoice_list and request_list,
instead of calling update(), which repopulates the model.
2022-03-23 19:52:28 +01:00
SomberNight
05649861c8 qt gui: more resilient startup: catch more exceptions, better fallback
fixes https://github.com/spesmilo/electrum/issues/7447

Consider this trace for 4.2.0:
```
Traceback (most recent call last):
  File "electrum/gui/qt/__init__.py", line 332, in start_new_window
  File "electrum/gui/qt/__init__.py", line 363, in _start_wizard_to_select_or_create_wallet
  File "electrum/gui/qt/installwizard.py", line 302, in select_storage
  File "electrum/util.py", line 504, in get_new_wallet_name
PermissionError: [Errno 1] Operation not permitted: '/Users/admin/Documents/Peach/MS'

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
  File "electrum/gui/qt/__init__.py", line 426, in main
  File "electrum/gui/qt/__init__.py", line 307, in wrapper
  File "electrum/gui/qt/__init__.py", line 349, in start_new_window
  File "electrum/util.py", line 504, in get_new_wallet_name
PermissionError: [Errno 1] Operation not permitted: '/Users/admin/Documents/Peach/MS'
```

Note that `get_new_wallet_name` (os.listdir) can raise OSError,
and we were calling that on the main entrypoint codepath without exception-handling.
We were also calling it in the fallback codepath without exception-handling.
i.e. the GUI errored out on every startup for affected users, and without CLI usage
it was not possible to recover.
2022-03-23 03:58:33 +01:00
ghost43
483fed42d8 Merge pull request #7727 from SomberNight/202203_qtcamera_preferences_crash
qt gui: (maybe fix) opening "Preferences" segfaults on macOS for some
2022-03-22 14:40:49 +00:00
SomberNight
10b2d705a1 qt chan details dlg: break stats into 2 cols, add local/remote balance 2022-03-21 17:49:08 +01:00
SomberNight
d8e2582889 qt gui: (maybe fix) opening "Preferences" segfaults on macOS for some
see https://github.com/spesmilo/electrum/issues/7725
related https://github.com/Electron-Cash/Electron-Cash/pull/1545
2022-03-21 15:50:28 +01:00
SomberNight
a92dede490 lnpeer: some rework of error/warning message handling
- rm the `_get_channel_ids` abstraction as each of its usages needs subtle differences.
  Some code duplication is preferable in this case.
- raise exceptions in `wait_for_message`, so that callers such as the GUI can show user-feedback
- on_error/on_warning were dropping messages with temp_chan_ids if they were not stored in
  `temp_id_to_id` - which was only done once the mapping was known (so the normal chan_id was known).
  To fix this, we now store temp_chan_ids into `temp_id_to_id` early.
- `schedule_force_closing` only works if the chan_id is already in `channels`

related:
https://github.com/spesmilo/electrum/pull/7645 (and related commits)

-----

example before commit:
```
D/P | lnpeer.Peer.[LNWallet, 03933884aa-3b53e4ab] | Sending OPEN_CHANNEL
D/P | lnpeer.Peer.[LNWallet, 03933884aa-3b53e4ab] | Received ERROR
I/P | lnpeer.Peer.[LNWallet, 03933884aa-3b53e4ab] | remote peer sent error [DO NOT TRUST THIS MESSAGE]: invalid funding_satoshis=10000 sat (min=400000 sat max=1500000000 sat)

E | gui.qt.main_window.[test_segwit_2] | Could not open channel
Traceback (most recent call last):
  File "...\electrum\electrum\util.py", line 1160, in wrapper
    return await func(*args, **kwargs)
  File "...\electrum\electrum\lnpeer.py", line 661, in wrapper
    return await func(self, *args, **kwargs)
  File "...\electrum\electrum\lnpeer.py", line 742, in channel_establishment_flow
    payload = await self.wait_for_message('accept_channel', temp_channel_id)  #
  File "...\electrum\electrum\lnpeer.py", line 315, in wait_for_message
    name, payload = await asyncio.wait_for(q.get(), LN_P2P_NETWORK_TIMEOUT)
  File "...\Python39\lib\asyncio\tasks.py", line 468, in wait_for
    await waiter
asyncio.exceptions.CancelledError

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
  File "...\Python39\lib\asyncio\tasks.py", line 492, in wait_for
    fut.result()
asyncio.exceptions.CancelledError

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

Traceback (most recent call last):
  File "...\electrum\electrum\gui\qt\util.py", line 914, in run
    result = task.task()
  File "...\electrum\electrum\gui\qt\main_window.py", line 1875, in task
    return self.wallet.lnworker.open_channel(
  File "...\electrum\electrum\lnworker.py", line 1075, in open_channel
    chan, funding_tx = fut.result()
  File "...\Python39\lib\concurrent\futures\_base.py", line 445, in result
    return self.__get_result()
  File "...\Python39\lib\concurrent\futures\_base.py", line 390, in __get_result
    raise self._exception
  File "...\electrum\electrum\util.py", line 1160, in wrapper
    return await func(*args, **kwargs)
  File "...\electrum\electrum\lnworker.py", line 1006, in _open_channel_coroutine
    chan, funding_tx = await asyncio.wait_for(coro, LN_P2P_NETWORK_TIMEOUT)
  File "...\Python39\lib\asyncio\tasks.py", line 494, in wait_for
    raise exceptions.TimeoutError() from exc
asyncio.exceptions.TimeoutError
```

example after commit:
```
D/P | lnpeer.Peer.[LNWallet, 03933884aa-ff3a866f] | Sending OPEN_CHANNEL
D/P | lnpeer.Peer.[LNWallet, 03933884aa-ff3a866f] | Received ERROR
I/P | lnpeer.Peer.[LNWallet, 03933884aa-ff3a866f] | remote peer sent error [DO NOT TRUST THIS MESSAGE]: invalid funding_satoshis=10000 sat (min=400000 sat max=1500000000 sat). chan_id=124ca21fa6aa2993430ad71f465f0d44731ef87f7478e4b31327e4459b5a3988
E | lnworker.LNWallet.[test_segwit_2] | Exception in _open_channel_coroutine: GracefulDisconnect('remote peer sent error [DO NOT TRUST THIS MESSAGE]: invalid funding_satoshis=10000 sat (min=400000 sat max=1500000000 sat)')
Traceback (most recent call last):
  File "...\electrum\electrum\util.py", line 1160, in wrapper
    return await func(*args, **kwargs)
  File "...\electrum\electrum\lnworker.py", line 1006, in _open_channel_coroutine
    chan, funding_tx = await asyncio.wait_for(coro, LN_P2P_NETWORK_TIMEOUT)
  File "...\Python39\lib\asyncio\tasks.py", line 481, in wait_for
    return fut.result()
  File "...\electrum\electrum\lnpeer.py", line 673, in wrapper
    return await func(self, *args, **kwargs)
  File "...\electrum\electrum\lnpeer.py", line 755, in channel_establishment_flow
    payload = await self.wait_for_message('accept_channel', temp_channel_id)
  File "...\electrum\electrum\lnpeer.py", line 326, in wait_for_message
    raise GracefulDisconnect(
electrum.interface.GracefulDisconnect: remote peer sent error [DO NOT TRUST THIS MESSAGE]: invalid funding_satoshis=10000 sat (min=400000 sat max=1500000000 sat)
I/P | lnpeer.Peer.[LNWallet, 03933884aa-ff3a866f] | Disconnecting: GracefulDisconnect()
```
2022-03-17 17:52:38 +01:00
SomberNight
15643b7951 qt init: make sure wallet file parsing errors are shown in gui
Some exceptions were just killing the gui silently and not even logged.

E.g.:
```
E | gui.qt.ElectrumGui | error loading wallet (or creating window for it)
Traceback (most recent call last):
  File "/opt/electrum/electrum/gui/qt/__init__.py", line 433, in main
    if not self.start_new_window(path, self.config.get('url'), app_is_starting=True):
  File "/opt/electrum/electrum/gui/qt/__init__.py", line 307, in wrapper
    return func(self, *args, **kwargs)
  File "/opt/electrum/electrum/gui/qt/__init__.py", line 332, in start_new_window
    wallet = self._start_wizard_to_select_or_create_wallet(path)
  File "/opt/electrum/electrum/gui/qt/__init__.py", line 377, in _start_wizard_to_select_or_create_wallet
    db = WalletDB(storage.read(), manual_upgrades=False)
  File "/opt/electrum/electrum/wallet_db.py", line 73, in __init__
    self.load_data(raw)
  File "/opt/electrum/electrum/wallet_db.py", line 104, in load_data
    self._after_upgrade_tasks()
  File "/opt/electrum/electrum/wallet_db.py", line 202, in _after_upgrade_tasks
    self._load_transactions()
  File "/opt/electrum/electrum/util.py", line 439, in <lambda>
    return lambda *args, **kw_args: do_profile(args, kw_args)
  File "/opt/electrum/electrum/util.py", line 435, in do_profile
    o = func(*args, **kw_args)
  File "/opt/electrum/electrum/wallet_db.py", line 1310, in _load_transactions
    self.data = StoredDict(self.data, self, [])
  File "/opt/electrum/electrum/json_db.py", line 79, in __init__
    self.__setitem__(k, v)
  File "/opt/electrum/electrum/json_db.py", line 44, in wrapper
    return func(self, *args, **kwargs)
  File "/opt/electrum/electrum/json_db.py", line 97, in __setitem__
    v = self.db._convert_dict(self.path, key, v)
  File "/opt/electrum/electrum/wallet_db.py", line 1361, in _convert_dict
    v = dict((k, SwapData(**x)) for k, x in v.items())
```
2022-03-15 14:23:30 +01:00
SomberNight
3771553a2c crash reporter: if disabled via config, make sure EEQueue is flushed
If the user had `config.get("show_crash_reporter")==False`, they would
never get to see excs collected via `send_exception_to_crash_reporter(exc)`.

E.g.:
```
E | gui.qt.ElectrumGui | error loading wallet (or creating window for it)
Traceback (most recent call last):
  File "/opt/electrum/electrum/gui/qt/__init__.py", line 433, in main
    if not self.start_new_window(path, self.config.get('url'), app_is_starting=True):
  File "/opt/electrum/electrum/gui/qt/__init__.py", line 307, in wrapper
    return func(self, *args, **kwargs)
  File "/opt/electrum/electrum/gui/qt/__init__.py", line 332, in start_new_window
    wallet = self._start_wizard_to_select_or_create_wallet(path)
  File "/opt/electrum/electrum/gui/qt/__init__.py", line 377, in _start_wizard_to_select_or_create_wallet
    db = WalletDB(storage.read(), manual_upgrades=False)
  File "/opt/electrum/electrum/wallet_db.py", line 73, in __init__
    self.load_data(raw)
  File "/opt/electrum/electrum/wallet_db.py", line 104, in load_data
    self._after_upgrade_tasks()
  File "/opt/electrum/electrum/wallet_db.py", line 202, in _after_upgrade_tasks
    self._load_transactions()
  File "/opt/electrum/electrum/util.py", line 439, in <lambda>
    return lambda *args, **kw_args: do_profile(args, kw_args)
  File "/opt/electrum/electrum/util.py", line 435, in do_profile
    o = func(*args, **kw_args)
  File "/opt/electrum/electrum/wallet_db.py", line 1310, in _load_transactions
    self.data = StoredDict(self.data, self, [])
  File "/opt/electrum/electrum/json_db.py", line 79, in __init__
    self.__setitem__(k, v)
  File "/opt/electrum/electrum/json_db.py", line 44, in wrapper
    return func(self, *args, **kwargs)
  File "/opt/electrum/electrum/json_db.py", line 97, in __setitem__
    v = self.db._convert_dict(self.path, key, v)
  File "/opt/electrum/electrum/wallet_db.py", line 1361, in _convert_dict
    v = dict((k, SwapData(**x)) for k, x in v.items())
```
2022-03-15 13:39:33 +01:00