Skip to content

Commit 1f0d488

Browse files
committed
askrene: refine: disable HTLC min violations
Disable channels with HTLC min violations so that we don't hit them twice when computing routes. Changelog-None Signed-off-by: Lagrang3 <[email protected]>
1 parent b826c5b commit 1f0d488

File tree

4 files changed

+67
-6
lines changed

4 files changed

+67
-6
lines changed

plugins/askrene/askrene.c

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -564,6 +564,13 @@ static struct command_result *do_getroutes(struct command *cmd,
564564
/* we temporarily apply localmods */
565565
gossmap_apply_localmods(askrene->gossmap, localmods);
566566

567+
/* I want to be able to disable channels while working on this query.
568+
* Layers are for user interaction and cannot be used for this purpose.
569+
*/
570+
rq->disabled_chans =
571+
tal_arrz(rq, bitmap,
572+
2 * BITMAP_NWORDS(gossmap_max_chan_idx(askrene->gossmap)));
573+
567574
/* localmods can add channels, so we need to allocate biases array
568575
* *afterwards* */
569576
rq->biases =

plugins/askrene/askrene.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
#define LIGHTNING_PLUGINS_ASKRENE_ASKRENE_H
33
#include "config.h"
44
#include <bitcoin/short_channel_id.h>
5+
#include <ccan/bitmap/bitmap.h>
56
#include <ccan/htable/htable_type.h>
67
#include <ccan/list/list.h>
78
#include <common/amount.h>
@@ -60,6 +61,9 @@ struct route_query {
6061

6162
/* Additional per-htlc cost for local channels */
6263
const struct additional_cost_htable *additional_costs;
64+
65+
/* channels we disable during computation to meet constraints */
66+
bitmap *disabled_chans;
6367
};
6468

6569
/* Given a gossmap channel, get the current known min/max */

plugins/askrene/mcf.c

Lines changed: 15 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -319,6 +319,15 @@ static void set_capacity(s64 *capacity, u64 value, u64 *cap_on_capacity)
319319
*cap_on_capacity -= *capacity;
320320
}
321321

322+
/* Helper to check whether a channel is available */
323+
static bool channel_is_available(const struct route_query *rq,
324+
const struct gossmap_chan *chan, const int dir)
325+
{
326+
const u32 c_idx = gossmap_chan_idx(rq->gossmap, chan);
327+
return gossmap_chan_set(chan, dir) && chan->half[dir].enabled &&
328+
!bitmap_test_bit(rq->disabled_chans, c_idx * 2 + dir);
329+
}
330+
322331
/* FIXME: unit test this */
323332
/* The probability of forwarding a payment amount given a high and low liquidity
324333
* bounds.
@@ -563,7 +572,7 @@ static void init_linear_network(const tal_t *ctx,
563572
const struct gossmap_chan *c = gossmap_nth_chan(gossmap,
564573
node, j, &half);
565574

566-
if (!gossmap_chan_set(c, half) || !c->half[half].enabled)
575+
if (!channel_is_available(params->rq, c, half))
567576
continue;
568577

569578
/* If a channel insists on more than our total, remove it */
@@ -639,7 +648,7 @@ struct chan_flow
639648
* */
640649
static struct node find_path_or_cycle(
641650
const tal_t *working_ctx,
642-
const struct gossmap *gossmap,
651+
const struct route_query *rq,
643652
const struct chan_flow *chan_flow,
644653
const struct node source,
645654
const s64 *balance,
@@ -648,6 +657,7 @@ static struct node find_path_or_cycle(
648657
int *prev_dir,
649658
u32 *prev_idx)
650659
{
660+
const struct gossmap *gossmap = rq->gossmap;
651661
const size_t max_num_nodes = gossmap_max_node_idx(gossmap);
652662
bitmap *visited =
653663
tal_arrz(working_ctx, bitmap, BITMAP_NWORDS(max_num_nodes));
@@ -666,7 +676,7 @@ static struct node find_path_or_cycle(
666676
const struct gossmap_chan *c =
667677
gossmap_nth_chan(gossmap, cur, i, &dir);
668678

669-
if (!gossmap_chan_set(c, dir) || !c->half[dir].enabled)
679+
if (!channel_is_available(rq, c, dir))
670680
continue;
671681

672682
const u32 c_idx = gossmap_chan_idx(gossmap, c);
@@ -872,7 +882,7 @@ get_flow_paths(const tal_t *ctx,
872882
while (balance[source.idx] < 0) {
873883
prev_chan[source.idx] = NULL;
874884
struct node sink = find_path_or_cycle(
875-
working_ctx, params->rq->gossmap, chan_flow, source,
885+
working_ctx, params->rq, chan_flow, source,
876886
balance, prev_chan, prev_dir, prev_idx);
877887

878888
if (balance[sink.idx] > 0)
@@ -1101,8 +1111,7 @@ static void init_linear_network_single_path(
11011111
gossmap_nth_chan(gossmap, node, j, &half);
11021112
struct amount_msat mincap, maxcap;
11031113

1104-
if (!gossmap_chan_set(c, half) ||
1105-
!c->half[half].enabled)
1114+
if (!channel_is_available(params->rq, c, half))
11061115
continue;
11071116

11081117
/* If a channel cannot forward the total amount we don't

plugins/askrene/refine.c

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -735,6 +735,38 @@ static struct amount_msat path_min_deliverable(struct channel_data *path)
735735
return least_destination;
736736
}
737737

738+
static const char *
739+
remove_htlc_min_violations(const tal_t *ctx, struct route_query *rq,
740+
const struct flow *flow,
741+
const struct channel_data *channels)
742+
{
743+
const char *error_message = NULL;
744+
struct amount_msat msat = flow->delivers;
745+
for (size_t i = tal_count(flow->path) - 1; i < tal_count(flow->path);
746+
i--) {
747+
if (amount_msat_less(msat, channels[i].htlc_min)) {
748+
rq_log(
749+
ctx, rq, LOG_INFORM,
750+
"Sending %s across %s would violate htlc_min "
751+
"(~%s), disabling this channel",
752+
fmt_amount_msat(ctx, msat),
753+
fmt_short_channel_id_dir(ctx, &channels[i].scidd),
754+
fmt_amount_msat(ctx, channels[i].htlc_min));
755+
bitmap_set_bit(rq->disabled_chans, channels[i].idx);
756+
break;
757+
}
758+
if (!amount_msat_add_fee(
759+
&msat, channels[i].fee_base_msat,
760+
channels[i].fee_proportional_millionths)) {
761+
error_message =
762+
rq_log(ctx, rq, LOG_BROKEN,
763+
"%s: Adding fee to amount", __func__);
764+
break;
765+
}
766+
}
767+
return error_message;
768+
}
769+
738770
static struct amount_msat sum_all_deliver(struct flow **flows,
739771
size_t *flows_index)
740772
{
@@ -819,6 +851,7 @@ const char *refine_flows(const tal_t *ctx, struct route_query *rq,
819851
struct amount_msat deliver, struct flow ***flows)
820852
{
821853
const tal_t *working_ctx = tal(ctx, tal_t);
854+
const char *error_message = NULL;
822855
struct amount_msat *max_deliverable;
823856
struct amount_msat *min_deliverable;
824857
struct channel_data **channel_mpp_cache;
@@ -863,6 +896,10 @@ const char *refine_flows(const tal_t *ctx, struct route_query *rq,
863896
}
864897
/* htlc_min is not met for this flow */
865898
tal_arr_remove(&flows_index, i);
899+
error_message = remove_htlc_min_violations(
900+
working_ctx, rq, (*flows)[k], channel_mpp_cache[k]);
901+
if (error_message)
902+
goto fail;
866903
}
867904

868905
/* remove 0 amount flows if any */
@@ -889,4 +926,8 @@ const char *refine_flows(const tal_t *ctx, struct route_query *rq,
889926

890927
tal_free(working_ctx);
891928
return NULL;
929+
930+
fail:
931+
tal_free(working_ctx);
932+
return error_message;
892933
}

0 commit comments

Comments
 (0)