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 <lagrang3@protonmail.com>
This commit is contained in:
@@ -564,6 +564,13 @@ static struct command_result *do_getroutes(struct command *cmd,
|
||||
/* we temporarily apply localmods */
|
||||
gossmap_apply_localmods(askrene->gossmap, localmods);
|
||||
|
||||
/* I want to be able to disable channels while working on this query.
|
||||
* Layers are for user interaction and cannot be used for this purpose.
|
||||
*/
|
||||
rq->disabled_chans =
|
||||
tal_arrz(rq, bitmap,
|
||||
2 * BITMAP_NWORDS(gossmap_max_chan_idx(askrene->gossmap)));
|
||||
|
||||
/* localmods can add channels, so we need to allocate biases array
|
||||
* *afterwards* */
|
||||
rq->biases =
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
#define LIGHTNING_PLUGINS_ASKRENE_ASKRENE_H
|
||||
#include "config.h"
|
||||
#include <bitcoin/short_channel_id.h>
|
||||
#include <ccan/bitmap/bitmap.h>
|
||||
#include <ccan/htable/htable_type.h>
|
||||
#include <ccan/list/list.h>
|
||||
#include <common/amount.h>
|
||||
@@ -60,6 +61,9 @@ struct route_query {
|
||||
|
||||
/* Additional per-htlc cost for local channels */
|
||||
const struct additional_cost_htable *additional_costs;
|
||||
|
||||
/* channels we disable during computation to meet constraints */
|
||||
bitmap *disabled_chans;
|
||||
};
|
||||
|
||||
/* Given a gossmap channel, get the current known min/max */
|
||||
|
||||
@@ -319,6 +319,15 @@ static void set_capacity(s64 *capacity, u64 value, u64 *cap_on_capacity)
|
||||
*cap_on_capacity -= *capacity;
|
||||
}
|
||||
|
||||
/* Helper to check whether a channel is available */
|
||||
static bool channel_is_available(const struct route_query *rq,
|
||||
const struct gossmap_chan *chan, const int dir)
|
||||
{
|
||||
const u32 c_idx = gossmap_chan_idx(rq->gossmap, chan);
|
||||
return gossmap_chan_set(chan, dir) && chan->half[dir].enabled &&
|
||||
!bitmap_test_bit(rq->disabled_chans, c_idx * 2 + dir);
|
||||
}
|
||||
|
||||
/* FIXME: unit test this */
|
||||
/* The probability of forwarding a payment amount given a high and low liquidity
|
||||
* bounds.
|
||||
@@ -568,7 +577,7 @@ static void init_linear_network(const tal_t *ctx,
|
||||
const struct gossmap_chan *c = gossmap_nth_chan(gossmap,
|
||||
node, j, &half);
|
||||
|
||||
if (!gossmap_chan_set(c, half) || !c->half[half].enabled)
|
||||
if (!channel_is_available(params->rq, c, half))
|
||||
continue;
|
||||
|
||||
/* If a channel insists on more than our total, remove it */
|
||||
@@ -644,7 +653,7 @@ struct chan_flow
|
||||
* */
|
||||
static struct node find_path_or_cycle(
|
||||
const tal_t *working_ctx,
|
||||
const struct gossmap *gossmap,
|
||||
const struct route_query *rq,
|
||||
const struct chan_flow *chan_flow,
|
||||
const struct node source,
|
||||
const s64 *balance,
|
||||
@@ -653,6 +662,7 @@ static struct node find_path_or_cycle(
|
||||
int *prev_dir,
|
||||
u32 *prev_idx)
|
||||
{
|
||||
const struct gossmap *gossmap = rq->gossmap;
|
||||
const size_t max_num_nodes = gossmap_max_node_idx(gossmap);
|
||||
bitmap *visited =
|
||||
tal_arrz(working_ctx, bitmap, BITMAP_NWORDS(max_num_nodes));
|
||||
@@ -671,7 +681,7 @@ static struct node find_path_or_cycle(
|
||||
const struct gossmap_chan *c =
|
||||
gossmap_nth_chan(gossmap, cur, i, &dir);
|
||||
|
||||
if (!gossmap_chan_set(c, dir) || !c->half[dir].enabled)
|
||||
if (!channel_is_available(rq, c, dir))
|
||||
continue;
|
||||
|
||||
const u32 c_idx = gossmap_chan_idx(gossmap, c);
|
||||
@@ -877,7 +887,7 @@ get_flow_paths(const tal_t *ctx,
|
||||
while (balance[source.idx] < 0) {
|
||||
prev_chan[source.idx] = NULL;
|
||||
struct node sink = find_path_or_cycle(
|
||||
working_ctx, params->rq->gossmap, chan_flow, source,
|
||||
working_ctx, params->rq, chan_flow, source,
|
||||
balance, prev_chan, prev_dir, prev_idx);
|
||||
|
||||
if (balance[sink.idx] > 0)
|
||||
@@ -1107,8 +1117,7 @@ static void init_linear_network_single_path(
|
||||
gossmap_nth_chan(gossmap, node, j, &half);
|
||||
struct amount_msat mincap, maxcap;
|
||||
|
||||
if (!gossmap_chan_set(c, half) ||
|
||||
!c->half[half].enabled)
|
||||
if (!channel_is_available(params->rq, c, half))
|
||||
continue;
|
||||
|
||||
/* If a channel cannot forward the total amount we don't
|
||||
|
||||
@@ -735,6 +735,38 @@ static struct amount_msat path_min_deliverable(struct channel_data *path)
|
||||
return least_destination;
|
||||
}
|
||||
|
||||
static const char *
|
||||
remove_htlc_min_violations(const tal_t *ctx, struct route_query *rq,
|
||||
const struct flow *flow,
|
||||
const struct channel_data *channels)
|
||||
{
|
||||
const char *error_message = NULL;
|
||||
struct amount_msat msat = flow->delivers;
|
||||
for (size_t i = tal_count(flow->path) - 1; i < tal_count(flow->path);
|
||||
i--) {
|
||||
if (amount_msat_less(msat, channels[i].htlc_min)) {
|
||||
rq_log(
|
||||
ctx, rq, LOG_INFORM,
|
||||
"Sending %s across %s would violate htlc_min "
|
||||
"(~%s), disabling this channel",
|
||||
fmt_amount_msat(ctx, msat),
|
||||
fmt_short_channel_id_dir(ctx, &channels[i].scidd),
|
||||
fmt_amount_msat(ctx, channels[i].htlc_min));
|
||||
bitmap_set_bit(rq->disabled_chans, channels[i].idx);
|
||||
break;
|
||||
}
|
||||
if (!amount_msat_add_fee(
|
||||
&msat, channels[i].fee_base_msat,
|
||||
channels[i].fee_proportional_millionths)) {
|
||||
error_message =
|
||||
rq_log(ctx, rq, LOG_BROKEN,
|
||||
"%s: Adding fee to amount", __func__);
|
||||
break;
|
||||
}
|
||||
}
|
||||
return error_message;
|
||||
}
|
||||
|
||||
static struct amount_msat sum_all_deliver(struct flow **flows,
|
||||
size_t *flows_index)
|
||||
{
|
||||
@@ -819,6 +851,7 @@ const char *refine_flows(const tal_t *ctx, struct route_query *rq,
|
||||
struct amount_msat deliver, struct flow ***flows)
|
||||
{
|
||||
const tal_t *working_ctx = tal(ctx, tal_t);
|
||||
const char *error_message = NULL;
|
||||
struct amount_msat *max_deliverable;
|
||||
struct amount_msat *min_deliverable;
|
||||
struct channel_data **channel_mpp_cache;
|
||||
@@ -863,6 +896,10 @@ const char *refine_flows(const tal_t *ctx, struct route_query *rq,
|
||||
}
|
||||
/* htlc_min is not met for this flow */
|
||||
tal_arr_remove(&flows_index, i);
|
||||
error_message = remove_htlc_min_violations(
|
||||
working_ctx, rq, (*flows)[k], channel_mpp_cache[k]);
|
||||
if (error_message)
|
||||
goto fail;
|
||||
}
|
||||
|
||||
/* remove 0 amount flows if any */
|
||||
@@ -889,4 +926,8 @@ const char *refine_flows(const tal_t *ctx, struct route_query *rq,
|
||||
|
||||
tal_free(working_ctx);
|
||||
return NULL;
|
||||
|
||||
fail:
|
||||
tal_free(working_ctx);
|
||||
return error_message;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user