Commit Graph

934 Commits

Author SHA1 Message Date
SomberNight
1b600b49e9 lnmsg/lnonion: follow-up prev: "hide" MappingProxyType usage 2025-11-18 14:54:33 +00:00
f321x
936e7fd1c2 lnonion: immutable OnionPacket and OnionHopsDataSingle
Make OnionHopsDataSingle and OnionPacket immutable for safer caching and
handling.

# Conflicts:
#	electrum/onion_message.py
2025-11-11 14:37:37 +01:00
SomberNight
e53666ac86 lnworker: follow-up prev: split pay_to_node 2025-11-07 15:37:49 +00:00
f321x
f5aa82d4f0 lnworker: fix todo, collect failed htlcs in payment
This makes `LNWallet.pay_to_node()` wait
`PaySession.TIMEOUT_WAIT_FOR_NEXT_RESOLVED_HTLC` (0.5 sec) for another
htlc to get resolved after receiving a htlc failure during a payment
attempt.
This seems to make payments more reliable in scenarios where we receive
multiple htlc failures closely after each other as
`create_route_for_payment` then has access to the failed routes/failure
information of all these htlcs when trying to re-split the outstanding
amount.
2025-10-21 13:19:12 +02:00
SomberNight
6e45d6e690 lnworker: (trivial) add a few missing type-hints 2025-10-09 15:06:23 +00:00
ThomasV
f4e7ffd5f3 lnworker: set OPTION_ONION_MESSAGE_OPT feature if we are forwarding. 2025-10-07 11:19:37 +02:00
SomberNight
7d0ac64d06 Merge remote-tracking branch 'spesmilo/pr/9993': lnurl-withdraw
ref https://github.com/spesmilo/electrum/pull/9993
2025-10-02 23:34:40 +00:00
f321x
286fc4b86e lnworker: enforce creation of PaymentInfo for b11
Enforce that the information used to create a bolt11 invoice using
`get_bolt11_invoice()` is similar to the related instance of PaymentInfo
by requiring a PaymentInfo as argument for `get_bolt11_invoice()`.
This way the invoice cannot differ from the created PaymentInfo.
This allows to use the information in PaymentInfo for validation of
incoming htlcs more reliably.

To cover all required information for the creation of a b11 invoice the
PaymentInfo class has to be extended with a expiry and
min_final_cltv_expiry. This requires a db upgrade.
2025-09-30 09:54:35 +02:00
f321x
d62b627a0b lnpeer: move htlc forwarding funcs to lnworker
forwarding happens independent of the peer that received the htlc to
forward and fits better in lnworker.
2025-09-30 09:54:24 +02:00
f321x
32aa6ab20c lnutil: rename RecvMPPResolution.ACCEPTED
Renames RecvMPPResolution.ACCEPTED to .COMPLETE as .ACCEPTED is somewhat
misleading. Accepted could imply that the preimage for this set has been
revealed or that the set has been settled, however it only means that we
have received the full set (it is complete), but the set still can be
failed (e.g. through cltv timeout) and has not been claimed yet.
2025-09-29 16:11:26 +00:00
f321x
fcc3796079 lnworker: move RecvMPPResolution and status to lnutil
it is required both in lnpeer and lnworker, moving it to lnutil seems to
make more sense.

# Conflicts:
#	electrum/lnworker.py
2025-09-29 16:11:17 +00:00
f321x
4c0155c072 lnworker: make PaymentInfo dataclass
Move PaymentInfo from NamedTuple to dataclass to allow for easier
handling e.g. using dataclasses.astuple etc.
2025-09-29 16:11:03 +00:00
SomberNight
b944371ffd adb: change API of util.TxMinedInfo: height() is now always SPV-ed 2025-09-24 13:46:24 +00:00
ghost43
b4a6de46f4 Merge pull request #10188 from f321x/capacity_warning_zero_amount
qt: receive dialog: also propose swaps for 0 amount invoices
2025-09-09 16:16:23 +00:00
ThomasV
2d17252b4b lnworker.has_anchor_channels: return False if channel is closed but not redeemed yet
this fixes the following issue: user cannot spend max until channel is redeemed.
see https://x.com/AnyoneOReally1/status/1964352775245951291
2025-09-08 10:39:41 +02:00
f321x
45bdd6a827 swaps: add type hints to gui swap suggestion flow
Adds type more type hints and clearer variable names to the swap
suggestion flow.
2025-09-04 12:24:12 +02:00
f321x
a62dbb5650 qt: receive tab: also suggest swap for 0 amnt req
Also suggest a submarine swap if the user creates a 0 amount invoice and
has 0 sat incoming liquidity as it won't be possible to receive
anything.
Users potentially just open a channel, then want to create a lightning invoice
without amount like they are used to from onchain addresses, and then
wonder why receiving doesn't work. So we should at least propose a swap
if there is no inbound liquidity at all.
2025-09-01 11:41:02 +02:00
f321x
fdeada3f51 lnurl: implement LNURL-withdraw
adds handling of lnurl-withdraw payment identifiers which allow users to
withdraw bitcoin from a service by scanning a qr code or pasting the
lnurl-w code as "sending" address.
2025-08-27 15:31:43 +02:00
SomberNight
9e7c332b06 lnworker: rewrite payment_bundles: lower cpu-time-complexity 2025-08-23 02:41:46 +00:00
SomberNight
a7afd59dec swaps: more clean-up, add comments, more sanity checks 2025-08-23 02:41:43 +00:00
f321x
c623cca654 swaps: cleanup data after swap gets failed
Removes the persisted payment info from lnworker once a swap got failed.
Stops persisting the OnionRoutingFailure as it is sufficient to delete
the payment info to fail potential incoming htlcs.
Deletes stored swap leftovers in lnworker and SwapManager
2025-08-21 19:56:42 +02:00
SomberNight
c1d2fc2b42 lnworker: (trivial) get_payment_bundle to not return None 2025-08-21 17:39:31 +00:00
SomberNight
df96f87ed7 lnworker: limit max number of incoming channel-less peers 2025-08-19 18:28:16 +00:00
SomberNight
6ddc975a94 follow-up prev: clean-up PaymentFeeBudget API 2025-08-01 15:06:33 +00:00
f321x
23fa50df88 cli: add max_cltv and max_fee_msat parameter to lnpay
Adds `max_cltv` and `max_fee_msat` parameters to the `lnpay` cli command which allow to
specify the maximum total locktime of the payment and the maximum
absolute fee budget. This is enabled by
constructing a custom `PaymentFeeBudget` object in the lnpay command and
passing it as argument to `LNWallet.pay_invoice()`.
Allowing to specify a `max_cltv` value can be useful for certain
usecases, e.g. see https://github.com/spesmilo/electrum/issues/10056.

Closes #10056
2025-08-01 16:22:51 +02:00
shangchenglumetro
deca7837f1 chore: fix some minor issues in the comments
Signed-off-by: shangchenglumetro <shuang.cui@live.com>
2025-07-04 16:28:47 +08:00
SomberNight
ba670cc9dc wallet: add struct PiechartBalance 2025-06-29 22:25:56 +00:00
SomberNight
50d48aee2d fee_policy: move regtest fallback even deeper 2025-06-28 04:29:50 +00:00
SomberNight
848e605a80 fee_policy: instead of checking has_data, handle "eta_to_fee() is None" 2025-06-28 04:10:38 +00:00
SomberNight
92bdf70c73 fee_policy: separate fallback static fee vs regtest hardcoded fee 2025-06-28 04:10:35 +00:00
SomberNight
2b92e8a97a txbatcher: add type-hints 2025-06-26 14:10:18 +00:00
ThomasV
a0636e8f33 lnworker: fix timestamp in get_lightning_history 2025-06-06 08:46:21 +02:00
ThomasV
94517fbc0e lnworker: minor fix, follow-up fc4f995668 2025-06-03 10:26:25 +02:00
ThomasV
fc4f995668 lnworker: fix invoice status in htlc_failed from previous session
(status was remaining inflight)
2025-06-02 16:14:34 +02:00
ThomasV
ae7a1073cf Merge pull request #9685 from f321x/hold_invoice_cli
cli: add hold invoice cli functionality
2025-06-01 12:03:46 +02:00
ThomasV
853b793bef rm verbosity_shortcuts option (unused, redundant) 2025-05-29 16:20:41 +02:00
Sander van Grieken
84322500ef lnworker: imports, formatting, whitespace 2025-05-23 14:00:57 +02:00
f321x
539b83c2e4 followup #9845, fix broken mpp consolidation test
fixes broken test_trampoline_mpp_consolidation caused to fail by
https://github.com/spesmilo/electrum/pull/9845 by allowing single
channel splits for trampoline payments if TEST_FORCE_MPP is Trues
as the test relies on mpp through a single channel (it tests mpp and
there is only a single channel on the graph).
2025-05-20 18:34:46 +02:00
ThomasV
d1917b2951 Merge pull request #9837 from spesmilo/htlc_slots_left
pass number of htlc_slots_left to suggest_splits
2025-05-20 12:55:45 +02:00
ThomasV
4a17d5a316 pass number of htlc_slots_left to suggest_splits 2025-05-17 15:50:03 +02:00
f321x
f7ad95f42d make lightning dns seed fetching async 2025-05-16 17:10:10 +02:00
ThomasV
128eb9cc8b available_to_spend: remove unused 'strict' parameter 2025-05-16 12:29:49 +02:00
SomberNight
6320597f2c regtests: rm sleep from "swapserver_forceclose" test
less reliance on timing
(OTOH it hardcodes the output index of the commitment tx... meh)
2025-05-15 19:50:16 +00:00
ghost43
79a54c1578 Merge pull request #9826 from f321x/fix_fee_disagreement_ln
fix: reduce update_fee target for anchor channels
2025-05-15 13:30:11 +00:00
ThomasV
93e7de20e9 Merge pull request #9753 from f321x/debug_ln_payment_failure
ln: don't exclude single part configs for too small payments
2025-05-15 13:25:00 +02:00
f321x
e8171ca7c6 suggest_splits: don't exclude single part configs for too small multi
part configs

I noticed certain ln payments become very unreliable. These payments are ~21k sat, from gossip to gossip sender, with direct, unannounced channel.

Due to the recent fix https://github.com/spesmilo/electrum/pull/9723 `LNPathFinder.get_shortest_path_hops()` will not use channels for the last hop of a route anymore that aren't also passed to it in `my_sending_channels`:

```python
if edge_startnode == nodeA and my_sending_channels:  # payment outgoing, on our channel
    if edge_channel_id not in my_sending_channels:
        continue
```

Conceptually this makes sense as we only want to send through `my_sending_channels`, however if the only channel between us and the receiver is a direct channel that we got from the r_tag and it's not passed in `my_sending_channel` it's not able to construct a route now.

Previously this type of payment worked as `get_shortest_path_hops()` knew of the direct channel between us and `nodeB` from the invoices r_tag and then just used this channel as the route, even though it was (often) not contained in `my_sending_channels`.

`my_sending_channels`, passed in `LNWallet.create_routes_for_payment()` is either a single channel or all our channels, depending on `is_multichan_mpp`:

```python
for sc in split_configurations:
	  is_multichan_mpp = len(sc.config.items()) > 1
```

This causes the unreliable, random behavior as `LNWallet.suggest_splits()` is supposed to `exclude_single_part_payments` if the amount is > `MPP_SPLIT_PART_MINAMT_SAT` (5000 sat).
As `mpp_split.py suggest_splits()` is selecting channels randomly, and then removes single part configs, it sometimes doesn't return a single configuration, as it removes single part splits, and also removes multi part splits if a part is below 10 000 sat:

```python
if target_parts > 1 and config.is_any_amount_smaller_than_min_part_size():
    continue
```

This will result in a fallback to allow single part payments:

```python
split_configurations = get_splits()
if not split_configurations and exclude_single_part_payments:
    exclude_single_part_payments = False
    split_configurations = get_splits()
```

Then the payment works as all our channels are passed as `my_sending_channels` to  `LNWallet.create_routes_for_payment()`.

However sometimes this fallback doesn't happen, because a few mpp configurations found in the first iteration of `suggest_splits` have been kept, e.g. [10500, 10500], but at the same time most others have been removed as they crossed the limit, e.g. [11001, 9999], (which happens sometimes with payments ~20k sat), this makes `suggest_splits` return very few usable channels/configurations (sometimes just one or two, even with way more available channels).
This makes payments in this range unreliable as we do not retry to generate new split configurations if the following path finding fails with `NoPathFound()`, and there is no single part configuration that allows the path finding to access all channels. Also this does not only affect direct channel payments, but all gossip payments in this amount range.

There seem to be multiple ways to fix this, i think one simple approach is to just disable `exclude_single_part_payments` if the splitting loop already begins to sort out configs on the second iteration (the first split), as this indicates that the amount may be too small to split within the given limits, and prevents the issue of having only few valid splits returned and not going into the fallback. However this also results in increased usage of single part payments.
2025-05-15 10:26:33 +02:00
f321x
61874e9fe7 fix: reduce update_fee target for anchor channels
the update_fee logic for lightning channels was not adapted to anchor
channels causing us to send update_fee with a eta target of 2 blocks.
This causes force closes when there are mempool spikes as the fees we
try to update to are a lot higher than e.g. eclair uses. Eclair will
force close if our fee is 10x > than their fee.
2025-05-14 18:01:44 +02:00
SomberNight
44f3444795 lnworker: make "preimages" dict private
I want to hook into lnworker.save_preimage (not done yet).
Other modules should not put preimages into the dict directly.
2025-05-14 13:23:02 +00:00
f321x
41b8b16a7c add hold invoice cli functionality 2025-05-09 18:48:05 +02:00
ThomasV
5be646dfd2 call lnwatcher callbacks in asyncio thread
This partially reverts fbebe7de1a
lnwatcher.trigger_callbacks is called manually in commands.py
2025-05-06 12:37:00 +02:00