* add invoice status to invoice_status callback
* debug statement fails tests
* removed commented lines, added progress/attempt counter comment in lnworker.pay_to_node,
and update the invoice_status event handler in qeinvoicelistmodel.py
If the short_channel_id of a channel update received
with update_fail_htlc does not match the channel in
our route, blacklist the channel in our route.
Before this commit, partial results were yielded before we had
examined the whole split configuration.
I think the correct behaviour is to create all the routes for the
current configuration, then to yield them. If there is an exception,
we should try the next one.
Upon receiving UNKNOWN_NEXT_PEER, TEMPORARY_NODE_FAILURE
or TEMPORARY_CHANNEL_FAILURE, remember the trampoline route
that was used, and try other routes before raising the
trampoline fee.
Before this commit, we used to raise the trampoline fee
upon receiving any error message, in order to ensure
termination of the payment loop.
Note that we will still retry failing routes after we have
raised the trampoline fee. This choice is questionable, it
is unclear if doing so significantly increases the probability
of success.
Tests: add a test for trampoline handling of UNKNOWN_NEXT_PEER
Replace get_key_for_outgoing_invoice, get_key_for_incoming_request
with Invoice.get_id()
When a new request is created, reuse addresses of expired requests (fixes#7927)
The API is changed for the following commands:
get_request, get_invoice,
list_requests, list_invoices,
delete_request, delete_invoice
`wallet.make_unsigned_transaction` can raise NotEnoughFunds or NoDynamicFeeEstimates.
These are "expected" exceptions that need to be handled or worked around. Added a note
of this in the docstring now.
We now handle NoDynamicFeeEstimates by allowing a static fallback fee in
`wallet.can_pay_onchain` and `lnworker.suggest_funding_amount`. It should be
fine to have a static fallback in these cases, as the user still has a chance
to set their own fee later in the flow.
(though ofc the static fallback might be too high in some mempool conditions,
in which case e.g. can_pay_onchain might return a false-negative, but this
is still an improvement over raising I believe)
fixes https://github.com/spesmilo/electrum/issues/5784
Previously lnworker called LNWatcher.add_channel() on these, and then LNWatcher itself decided to unwatch them.
-----
note: motivation related to https://github.com/spesmilo/electrum/pull/7932#discussion_r945755584 ,
where I have legacy (pre-staticremotekey) redeemed channels in a wallet.
Tracebacks:
```
E/W | lnwatcher.LNWalletWatcher.[default_wallet-LNW] | Exception in do_breach_remedy: AssertionError()
Traceback (most recent call last):
File "...\electrum\electrum\util.py", line 1235, in wrapper
return await func(*args, **kwargs)
File "...\electrum\electrum\lnwatcher.py", line 443, in do_breach_remedy
sweep_info_dict = chan.sweep_ctx(closing_tx)
File "...\electrum\electrum\lnchannel.py", line 264, in sweep_ctx
our_sweep_info = self.create_sweeptxs_for_our_ctx(ctx)
File "...\electrum\electrum\lnchannel.py", line 253, in create_sweeptxs_for_our_ctx
return create_sweeptxs_for_our_ctx(chan=self, ctx=ctx, sweep_address=self.sweep_address)
File "...\electrum\electrum\lnchannel.py", line 757, in sweep_address
assert self.is_static_remotekey_enabled()
AssertionError
```
```
E/W | lnwatcher.LNWalletWatcher.[default_wallet-LNW] | Exception in trigger_callbacks: AssertionError()
Traceback (most recent call last):
File "...\electrum\electrum\util.py", line 1235, in wrapper
return await func(*args, **kwargs)
File "...\electrum\electrum\lnwatcher.py", line 208, in trigger_callbacks
await callback()
File "...\electrum\electrum\lnwatcher.py", line 225, in check_onchain_situation
keep_watching = await self.do_breach_remedy(funding_outpoint, closing_tx, spenders)
File "...\electrum\electrum\util.py", line 1235, in wrapper
return await func(*args, **kwargs)
File "...\electrum\electrum\lnwatcher.py", line 443, in do_breach_remedy
sweep_info_dict = chan.sweep_ctx(closing_tx)
File "...\electrum\electrum\lnchannel.py", line 264, in sweep_ctx
our_sweep_info = self.create_sweeptxs_for_our_ctx(ctx)
File "...\electrum\electrum\lnchannel.py", line 253, in create_sweeptxs_for_our_ctx
return create_sweeptxs_for_our_ctx(chan=self, ctx=ctx, sweep_address=self.sweep_address)
File "...\electrum\electrum\lnchannel.py", line 757, in sweep_address
assert self.is_static_remotekey_enabled()
AssertionError
```
- 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.