From 2bde9c68171e1c06eca45f965d810c0456a05acd Mon Sep 17 00:00:00 2001 From: Lagrang3 Date: Mon, 7 Sep 2026 08:03:21 +0100 Subject: [PATCH] askrene: cut-off arcs with very low probability Arcs with very low probability of success are pruned early. This only applies to the single path solver because the MPP code uses arc linearization and already the low probability tail is removed. Changelog-None Signed-off-by: Lagrang3 --- plugins/askrene/child/mcf.c | 11 +++++++++-- tests/test_askrene.py | 10 +++++----- tests/test_pay.py | 8 +++----- 3 files changed, 17 insertions(+), 12 deletions(-) diff --git a/plugins/askrene/child/mcf.c b/plugins/askrene/child/mcf.c index 3c455b852822..a60983fee9d9 100644 --- a/plugins/askrene/child/mcf.c +++ b/plugins/askrene/child/mcf.c @@ -1110,6 +1110,14 @@ static void init_linear_network_single_path( if (amount_msat_greater_eq(params->amount, maxcap)) continue; + const double probability = + pickhardt_richter_probability(mincap, maxcap, + params->amount); + + /* too unlikely it is not worth considering */ + if (probability < 1e-6) + continue; + const u32 chan_id = gossmap_chan_idx(gossmap, c); const struct gossmap_node *next = @@ -1129,8 +1137,7 @@ static void init_linear_network_single_path( (*arc_capacity)[arc.idx] = 1; (*arc_prob_cost)[arc.idx] = - (-1.0) * log(pickhardt_richter_probability( - mincap, maxcap, params->amount)); + (-1.0) * log(probability); struct amount_msat fee; if (!amount_msat_fee(&fee, params->amount, diff --git a/tests/test_askrene.py b/tests/test_askrene.py index 49d27460468c..9c62d99fb37e 100644 --- a/tests/test_askrene.py +++ b/tests/test_askrene.py @@ -958,13 +958,13 @@ def test_getroutes_single_path(node_factory): l1, nodemap[1], nodemap[2], - 10000000, + 9100000, [ [ { "short_channel_id_dir": "3x2x2/1", "node_id_out": nodemap[2], - "amount_in_msat": 10000010, + "amount_in_msat": 9100009, "cltv_in": 99 + 6, } ] @@ -991,19 +991,19 @@ def test_getroutes_single_path(node_factory): l1, nodemap[0], nodemap[2], - 10000000, + 9100000, [ [ { "short_channel_id_dir": "0x1x0/1", "node_id_out": nodemap[1], - "amount_in_msat": 10000020, + "amount_in_msat": 9100018, "cltv_in": 99 + 6 + 6, }, { "short_channel_id_dir": "3x2x2/1", "node_id_out": nodemap[2], - "amount_in_msat": 10000010, + "amount_in_msat": 9100009, "cltv_in": 99 + 6, }, ] diff --git a/tests/test_pay.py b/tests/test_pay.py index 72a15855e0a8..879798f36c65 100644 --- a/tests/test_pay.py +++ b/tests/test_pay.py @@ -5400,10 +5400,7 @@ def test_sendpay_grouping(node_factory, bitcoind): We always use slightly decreasing values for the payment, in order to avoid having to adjust the channel_hints that are being - remembered across attempts. In case of a failure the - `channel_hint` will be `attempted amount - 1msat` so use that as - the next payment's amount. - + remembered across attempts. """ l1, l2, l3 = node_factory.line_graph( 3, @@ -5428,8 +5425,9 @@ def test_sendpay_grouping(node_factory, bitcoind): # After this one invocation we have one entry in `listpays` assert(len(l1.rpc.listpays()['pays']) == 1) + # try again with a smaller amount with pytest.raises(RpcError, match=r'Failed after 1 attempts'): - l1.rpc.xpay(inv, amount_msat='100001msat') + l1.rpc.xpay(inv, amount_msat='90000msat') # Surprise: we should have 2 entries after 2 invocations assert(len(l1.rpc.listpays()['pays']) == 2)