Skip to content

[WIP] askrene-getroutes adaptive bounds - #9380

Draft
Lagrang3 wants to merge 8 commits into
ElementsProject:masterfrom
Lagrang3:xpay-adaptive-bounds
Draft

[WIP] askrene-getroutes adaptive bounds#9380
Lagrang3 wants to merge 8 commits into
ElementsProject:masterfrom
Lagrang3:xpay-adaptive-bounds

Conversation

@Lagrang3

@Lagrang3 Lagrang3 commented Aug 5, 2026

Copy link
Copy Markdown
Collaborator

After #9150, some flaws in askrene came to light. I've documented as much as I saw appropriate
in the code and commit messages, but for more details there was a thought process explained in #9282.

TLDR:

  • we update fake channeld to simulate an evolving network, liquidity is not just assigned but it moves when a payment succeeds,
  • in askrene's probability cost function we drop the assumption that the cost of X is not far from the cost of X+fees, we instead pessimistically assume a 1% fee attached to every amount,
  • min/max bounds are adaptively relaxed when there is evidence of our knowledge being wrong,
  • we spice a little bit the min/max bound computation with an exponential time evolution operation,
  • added unit tests,
  • re-enable fake channeld tests.

@Lagrang3 Lagrang3 added this to the v26.09 milestone Aug 5, 2026
@Lagrang3
Lagrang3 marked this pull request as draft August 5, 2026 07:07
Improved the fakenet simulation by moving funds after a payment
succeeds.

This triggers a bug in xpay. At PAYING Node ElementsProject#8 xpay fails after trying
many 1msat routes:
```
error: {'code': 209, 'message': "Timed out after after 842 attempts.
We got temporary_channel_failure for 45210x2134x44171/0, assuming it can't carry 198102199msat.
We got temporary_channel_failure for 45210x2134x44171/0, assuming it can't carry 198102197msat.
We got temporary_channel_failure for 45210x2134x44171/0, assuming it can't carry 198102196msat.
We got temporary_channel_failure for 45210x2134x44171/0, assuming it can't carry 198102195msat.
We got temporary_channel_failure for 45210x2134x44171/0, assuming it can't carry 198102194msat.
We got temporary_channel_failure for 45210x2134x44171/0, assuming it can't carry 198102193msat.
We got temporary_channel_failure for 45210x2134x44171/0, assuming it can't carry 198102192msat.
We got temporary_channel_failure for 45210x2134x44171/0, assuming it can't carry 198102191msat.
We got temporary_channel_failure for 45210x2134x44171/0, assuming it can't carry 198102190msat
...
We got temporary_channel_failure for 45210x2134x44171/0, assuming it can't carry 198101779msat.
Payment of 9996982msat reached destination, but timed out before the rest arrived..
Payment of 998000msat reached destination, but timed out before the rest arrived..
Payment of 3000000msat reached destination, but timed out before the rest arrived..
Payment of 197000000msat reached destination, but timed out before the rest arrived..
Payment of 91005018msat reached destination, but timed out before the rest arrived..
Payment of 1msat reached destination, but timed out before the rest arrived..
Payment of 1msat reached destination, but timed out before the rest arrived..
Payment of 1msat reached destination, but timed out before the rest arrived..
Payment of 1msat reached destination, but timed out before the rest arrived..
Payment of 1msat reached destination, but timed out before the rest arrived..
Payment of 1msat reached destination, but timed out before the rest arrived..
Payment of 1msat reached destination, but timed out before the rest arrived..
Payment of 1msat reached destination, but timed out before the rest arrived..
Payment of 1msat reached destination, but timed out before the rest arrived..
...
Payment of 1msat reached destination, but timed out before the rest arrived..
Payment of 1msat reached destination, but timed out before the rest arrived.. "}
```

A lower bound learned for channel 45210x2134x44171 at a previous payment
is to blame. xpay thinks it has enough liquidity for ~198ksat 100% sure
and it keeps trying and failing, while refine produces 1msat alternative
payment routes after every MCF computation because fees don't fit even
for our current knowledge. As a matter of fact the computed routes are
attributed a very low probability of success at around ~0.4%. This is a
case for which our assumption that "the cost of X+fees is not much
greater than the cost of X" breaks down.

To fix this:
-  we need xpay to relax that lower bound. The multiple failures are
empirical evidence that our knowledge is wrong and we should correct it,
- the probability cost function should add a buffer for hypothetical
  fees, ie. New_cost(x) = Old_cost(x + fees).

Changelog-None

Signed-off-by: Lagrang3 <lagrang3@protonmail.com>
When the known max and known min are about the same value, the
probability cost of sending x=value is zero and MCF will try it.
It doesn't take into account the possibility that when we hit that
channel the actual flow is x+fees. We adjust the min/max bounds
by a factor of 1/1.01 like if we had a 1% reserve for fees.

Changelog-Fixed: askrene-getroutes: Account for a worst case 1% fee in the flow amount when computing probability costs.

Signed-off-by: Lagrang3 <lagrang3@protonmail.com>
@Lagrang3
Lagrang3 force-pushed the xpay-adaptive-bounds branch from 8ac9c19 to 7bca9fb Compare August 5, 2026 11:27
Changelog-None

Signed-off-by: Lagrang3 <lagrang3@protonmail.com>
Changelog-None

Signed-off-by: Lagrang3 <lagrang3@protonmail.com>
@Lagrang3
Lagrang3 force-pushed the xpay-adaptive-bounds branch 3 times, most recently from d1727d5 to 6d2ff19 Compare August 6, 2026 21:11
@Lagrang3 Lagrang3 changed the title askrene-getroutes adaptive bounds [WIP] askrene-getroutes adaptive bounds Aug 6, 2026
@Lagrang3
Lagrang3 marked this pull request as ready for review August 6, 2026 21:19
@Lagrang3
Lagrang3 force-pushed the xpay-adaptive-bounds branch 2 times, most recently from 4009272 to 5860bf2 Compare August 7, 2026 07:10
Liquidity bounds are estimated from the observations gathered from
askrene-inform-channel. When combined, these intel entries are relaxed
base on the likelyhood of the observation with the prior knowledge, eg.
observing a channel failure when Pickhardt-Richer probability of success
is 99% indicates that it is likely that our prior knowledge was wrong.

We also use observations corresponding to the opposite direction of the
channel.

Changelog-Fixed: askrene-getroutes: liquidity bounds change with the evidence gathered from askrene-inform-channel

Signed-off-by: Lagrang3 <lagrang3@protonmail.com>
@Lagrang3
Lagrang3 force-pushed the xpay-adaptive-bounds branch 2 times, most recently from 2323e5b to c6d596a Compare August 7, 2026 11:30
Use an exponential function to relax the liquidity bounds in
askrene-getroutes. The choice of the time scale, currently lifetime=24h
is arbitrary, the choice of the function is arbitrary as well.
For whatever decay function we use it is important for consistency that
the semi-group property of time evolution be satisfied.

This time relaxation is useful because it allow us to smoothly discard
old information, eg. we can try routes that have failed on us in the past
and we don't get too optimistic about lower bounds we have learned a
while ago.

Another benefit is that we can combine channel intels giving older
entries "less importance" by applying the time evolution between intel
time gaps.

Changelog-None

Signed-off-by: Lagrang3 <lagrang3@protonmail.com>
We have set an exponential decay time for liquidity bounds with a
lifetime of 1 day, it halves every 16 hours. This parameter can be
tuned. But I think throwing away entries after 1 hour is too aggresive.
Better to remove them after 1 week. In that time it will be halved 10
times.

Changelog-None

Signed-off-by: Lagrang3 <lagrang3@protonmail.com>
@Lagrang3
Lagrang3 force-pushed the xpay-adaptive-bounds branch 3 times, most recently from a2357db to 6505622 Compare August 8, 2026 11:04
The 3 channel intel types, constraint_min, constraint_max and
impressions, are basically the same type. Instead of doing pointer magic
define a single channel intel type to gather these 3 cases for the
internal use.
The JSON API still makes a distinction between them.

Changelog-None

Signed-off-by: Lagrang3 <lagrang3@protonmail.com>
@Lagrang3
Lagrang3 force-pushed the xpay-adaptive-bounds branch from 6505622 to 1524935 Compare August 10, 2026 07:43
@Lagrang3 Lagrang3 modified the milestones: v26.09, v26.12 Aug 10, 2026
@Lagrang3
Lagrang3 marked this pull request as draft August 10, 2026 08:41
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant