Commit Graph

12 Commits

Author SHA1 Message Date
f321x
cfdaafdd52 fix: suggest_splits exclude single channel splits 2025-05-20 17:34:48 +02:00
ThomasV
4a17d5a316 pass number of htlc_slots_left to suggest_splits 2025-05-17 15:50:03 +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
Sander van Grieken
64a160027a imports, whitespace, type hints 2025-04-23 16:09:31 +02:00
SomberNight
39ef1cd4b9 mpp_split: make SplitConfig a subclass of dict, not just a type-hint 2023-10-27 14:24:12 +00:00
bitromortac
68bc9c2474 lnworker: improve route creation
- Separates the trampoline and local routing multi-part payment cases.
- Ask only for splits that don't send over a single channel (those have
  been tried already in the single-part case).
- Makes sure that create_routes_for_payment only yields partial routes
  that belong to a single split configuration.
- Tracks trampoline fee levels on a per node basis, previously, in the
  case of having two channels with a trampoline forwarder, the global
  fee level would have increased by two levels upon first try.
2021-07-16 11:27:36 +02:00
bitromortac
3c521f4ce3 mpp_split: split algorithm with channel splits
- The splitting algorithm is redesigned to use random distribution of
  subsplittings over channels.
- Splittings can include multiple subamounts within a channel.
- The single-channel splittings are implicitly activated once the
  liquidity hints don't support payments of large size.
2021-07-16 11:22:38 +02:00
bitromortac
8828998093 mpp_split: use single nodes for mpp payments over trampoline 2021-03-17 08:22:19 +01:00
bitromortac
10c799faab mpp_split: add penalty for exhaustion of channels
A penalty is added for split configurations which saturate a channel.
Saturation of channels is discouraged as we don't know the fees
beforehand. The penalty is accomplished via an exponential function that
kicks in when the subamount reaches about the total funds available
(this amount is controlled by the parameter EXHAUST_DECAY_FRACTION).
2021-03-11 16:19:15 +01:00
bitromortac
bf87169469 mpp_split: tweak split parameters
Increases STARTING_CONFIGS to sample more starting configurations.
Reduces CANDIDATES_PER_LEVEL to reduce computational effort.
Increases REDISTRIBUTE.

The time it takes for a typical suggest_split call is about 2 msec a
desktop machine.
2021-02-25 08:37:39 +01:00
SomberNight
a9d0e3fca9 tests: try to eliminate random failures from mpp_split tests
closes: #7062
2021-02-24 12:54:43 +01:00
bitromortac
613bab145d mpp_split: implement splitting logic 2021-02-22 11:25:00 +01:00