- for an onchain backups, if the channel is with a
hardcoded trampoline, try first without gossip DB.
- for imported backups, fallback to gossip DB if we
fail to connect with the provided network address.
follow-up e1d34300e5
follow-up dc15d59fcf
```
Traceback (most recent call last):
File ".../electrum/gui/qt/main_window.py", line 910, in timer_actions
self.update_wallet()
File ".../electrum/gui/qt/main_window.py", line 1068, in update_wallet
self.update_tabs()
File ".../electrum/gui/qt/main_window.py", line 1075, in update_tabs
self.history_model.refresh('update_tabs')
File ".../electrum/util.py", line 439, in <lambda>
return lambda *args, **kw_args: do_profile(args, kw_args)
File ".../electrum/util.py", line 435, in do_profile
o = func(*args, **kw_args)
File ".../electrum/gui/qt/history_list.py", line 275, in refresh
transactions = wallet.get_full_history(
File ".../electrum/util.py", line 439, in <lambda>
return lambda *args, **kw_args: do_profile(args, kw_args)
File ".../electrum/util.py", line 435, in do_profile
o = func(*args, **kw_args)
File ".../electrum/wallet.py", line 1109, in get_full_history
lightning_history = self.lnworker.get_lightning_history() if self.lnworker and include_lightning else {}
File ".../electrum/lnworker.py", line 839, in get_lightning_history
assert direction == PaymentDirection.FORWARDING
AssertionError
```
- the detection of self-payments was using the length
of the htlc list, incorrectly categorizing all MPPs.
- the fee for self-payments was not correctly computed.
get_unused_addresses() has been broken since #7730, because
addresses are considered as permanently used if they are in
the list of keys of receive_requests. This is true even if
an address is used as fallback for a lightning payment. This
means that the number of lightning payments we can receive
is constrained by the gap limit.
If a payment succeeds off-chain, we want to be able to reuse
its fallback address in other requests (this does not reduce
privacy, because invoices already share the same public key).
This implies that we should not use the onchain address as key
for lightning-enabled requests in wallet.receive_requests. If
we did, paid invoices would be overwritten when the address is
reused. That is the reason for the wallet_db upgrade.
Related: a3faf85e3c
- add new index: requests_rhash_to_key (fixes#7845)
- when creating a request, do not save its description in labels.
Instead, return it as default value in wallet.get_label_by_rhash
lnworker:
- rename 'payments' to 'payment_info'
- add note to delete_payment_info
commands: rename 'rmrequest' to 'delete_request'
- separate AddressSynchronizer from Wallet and LNWatcher
- the AddressSynchronizer class is referred to as 'adb' (address database)
- Use callbacks to replace overloaded methods
These methods return a list of channels that can be rebalanced,
in order to receive or send a given amount.
Also add 'channels' parameter to submarine swaps.
Previously, swaps were not considering which channel to use.
When we do not have liquidity to pay an invoice:
- add 'rebalance' option in order to pay an invoice
- use the suggested channel in the 'swap' option
When we do not have the liquidity to receive an invoice:
- add 'Rebalance' and 'Swap' buttons to the receive tab
I believe lightning requests created before https://github.com/spesmilo/electrum/pull/7730
can have an amount of None - ones created after have amount 0 instead.
We could do a wallet db upgrade potentially.
Regardless, the type hint is `get_amount_sat(self) -> Union[int, str, None]`,
so None should be handled. (well, arguably "!" should be handled too...)
```
E | gui.qt.exception_window.Exception_Hook | exception caught by crash reporter
Traceback (most recent call last):
File "...\electrum\electrum\gui\qt\request_list.py", line 101, in item_changed
self.parent.show_receive_request(req)
File "...\electrum\electrum\gui\qt\main_window.py", line 1279, in show_receive_request
URI = req.get_bip21_URI(lightning=bip21_lightning)
File "...\electrum\electrum\invoices.py", line 164, in get_bip21_URI
amount = int(self.get_amount_sat())
TypeError: int() argument must be a string, a bytes-like object or a real number, not 'NoneType'
```
```
E | gui.qt.exception_window.Exception_Hook | exception caught by crash reporter
Traceback (most recent call last):
File "...\electrum\electrum\gui\qt\request_list.py", line 101, in item_changed
self.parent.show_receive_request(req)
File "...\electrum\electrum\gui\qt\main_window.py", line 1281, in show_receive_request
can_receive_lightning = self.wallet.lnworker and req.get_amount_sat() <= self.wallet.lnworker.num_sats_can_receive()
TypeError: '<=' not supported between instances of 'NoneType' and 'decimal.Decimal'
```
follow-up https://github.com/spesmilo/electrum/pull/7818
- note it matters whether a sender pays us end-to-end-trampoline or just via legacy
- consider: Alice has 0.1 BTC recv cap in chan1 and 1 BTC recv cap in chan2, both with border-node T1
- if sender is paying e2e trampoline, it can realistically pay even ~1.1 BTC, as T1 can resplit the HTLCs
- if sender is paying legacy, it will have a hard time trying to pay more than 1 BTC, in practice
- although note if T1 has implemented non-strict-forwarding (see BOLT-04), achieving 1 BTC is easy,
as T1 can redirect HTLCs (but cannot split them, in this case)
- to make num_sats_can_receive realistic, it assumes the legacy case
- To calc num_sats_can_receive, we sort our channels in decreasing order of receive-capacities, iterate over them
and calculate a running sum - we stop adding channels when the next chan's recv cap is small compared to
the running total.
- When putting routing hints in an invoice, we do the same, with the added condition that we keep adding channels
if their recv cap is larger than the invoice amount.
- consider: Alice has 0.1 BTC recv cap in chan1 with Bob, and 1 BTC recv cap in chan2 with Carol
- if Alice wants to recv 100 sats, it is useful to add hints for both channels into the invoice, for redundancy
- if Alice wants to recv 0.9 BTC, it is questionable whether adding the smaller chan is useful - the code here won't add it
- increase MPP_RECEIVE_CUTOFF from 5 to 20 percent
- filter channels by node_id, not channel_id
- make num_sats_can_receive consistent with routing hints
return the max value allowed for legacy payments.
(that is, do not assume we can do MPP involving two trampolines)
This reverts fb6047ec46
Reason: num_sats_can_send may be used to decide the amount
we put in a new channel.
asyncio.get_event_loop() became deprecated in python3.10. (see https://github.com/python/cpython/issues/83710)
```
.../electrum/electrum/daemon.py:470: DeprecationWarning: There is no current event loop
self.asyncio_loop = asyncio.get_event_loop()
.../electrum/electrum/network.py:276: DeprecationWarning: There is no current event loop
self.asyncio_loop = asyncio.get_event_loop()
```
Also, according to that thread, "set_event_loop() [... is] not deprecated by oversight".
So, we stop using get_event_loop() and set_event_loop() in our own code.
Note that libraries we use (such as the stdlib for python <3.10), might call get_event_loop,
which then relies on us having called set_event_loop e.g. for the GUI thread. To work around
this, a custom event loop policy providing a get_event_loop implementation is used.
Previously, we have been using a single asyncio event loop, created with
util.create_and_start_event_loop, and code in many places got a reference to this loop
using asyncio.get_event_loop().
Now, we still use a single asyncio event loop, but it is now stored as a global in
util._asyncio_event_loop (access with util.get_asyncio_loop()).
I believe these changes also fix https://github.com/spesmilo/electrum/issues/5376
The call to super was removed in 4efcb53d24 ,
so that LNWallet's taskgroup would not run _maintain_connectivity, AFAICT.
The way it was done meant that "main_loop" itself would not run for LNWallet, only for LNGossip - very confusing.
It is only due to a quirk in the behaviour of TaskGroups that the group "started" at all.
```
Traceback (most recent call last):
File "...\electrum\electrum\gui\qt\main_window.py", line 898, in timer_actions
self.update_wallet()
File "...\electrum\electrum\gui\qt\main_window.py", line 1040, in update_wallet
self.update_tabs()
File "...\electrum\electrum\gui\qt\main_window.py", line 1047, in update_tabs
self.history_model.refresh('update_tabs')
File "...\electrum\electrum\util.py", line 439, in <lambda>
return lambda *args, **kw_args: do_profile(args, kw_args)
File "...\electrum\electrum\util.py", line 435, in do_profile
o = func(*args, **kw_args)
File "...\electrum\electrum\gui\qt\history_list.py", line 275, in refresh
transactions = wallet.get_full_history(
File "...\electrum\electrum\util.py", line 439, in <lambda>
return lambda *args, **kw_args: do_profile(args, kw_args)
File "...\electrum\electrum\util.py", line 435, in do_profile
o = func(*args, **kw_args)
File "...\electrum\electrum\wallet.py", line 947, in get_full_history
lnworker_history = self.lnworker.get_onchain_history() if self.lnworker and include_lightning else {}
File "...\electrum\electrum\lnworker.py", line 911, in get_onchain_history
tx_height = self.lnwatcher.get_tx_height(swap.funding_txid)
AttributeError: 'NoneType' object has no attribute 'get_tx_height'
```