askrene: paranoid checks ...
that new flows respect the HTLC min/max constraints. Changelog-None Signed-off-by: Lagrang3 <lagrang3@protonmail.com>
This commit is contained in:
@@ -1253,6 +1253,89 @@ fail:
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* Get the scidd for the i'th hop in flow */
|
||||
static void get_scidd(const struct gossmap *gossmap, const struct flow *flow,
|
||||
size_t i, struct short_channel_id_dir *scidd)
|
||||
{
|
||||
scidd->scid = gossmap_chan_scid(gossmap, flow->path[i]);
|
||||
scidd->dir = flow->dirs[i];
|
||||
}
|
||||
|
||||
/* We use an fp16_t approximatin for htlc_max/min: this gets the exact value. */
|
||||
static struct amount_msat
|
||||
get_chan_htlc_max(const struct route_query *rq, const struct gossmap_chan *c,
|
||||
const struct short_channel_id_dir *scidd)
|
||||
{
|
||||
struct amount_msat htlc_max;
|
||||
|
||||
gossmap_chan_get_update_details(rq->gossmap, c, scidd->dir, NULL, NULL,
|
||||
NULL, NULL, NULL, NULL, NULL,
|
||||
&htlc_max);
|
||||
return htlc_max;
|
||||
}
|
||||
|
||||
static struct amount_msat
|
||||
get_chan_htlc_min(const struct route_query *rq, const struct gossmap_chan *c,
|
||||
const struct short_channel_id_dir *scidd)
|
||||
{
|
||||
struct amount_msat htlc_min;
|
||||
|
||||
gossmap_chan_get_update_details(rq->gossmap, c, scidd->dir, NULL, NULL,
|
||||
NULL, NULL, NULL, NULL, &htlc_min,
|
||||
NULL);
|
||||
return htlc_min;
|
||||
}
|
||||
|
||||
static bool check_htlc_min_limits(struct route_query *rq, struct flow **flows)
|
||||
{
|
||||
|
||||
for (size_t k = 0; k < tal_count(flows); k++) {
|
||||
struct flow *flow = flows[k];
|
||||
size_t pathlen = tal_count(flow->path);
|
||||
struct amount_msat hop_amt = flow->delivers;
|
||||
for (size_t i = pathlen - 1; i < pathlen; i--) {
|
||||
const struct half_chan *h = flow_edge(flow, i);
|
||||
struct short_channel_id_dir scidd;
|
||||
|
||||
get_scidd(rq->gossmap, flow, i, &scidd);
|
||||
struct amount_msat htlc_min =
|
||||
get_chan_htlc_min(rq, flow->path[i], &scidd);
|
||||
if (amount_msat_less(hop_amt, htlc_min))
|
||||
return false;
|
||||
|
||||
if (!amount_msat_add_fee(&hop_amt, h->base_fee,
|
||||
h->proportional_fee))
|
||||
abort();
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool check_htlc_max_limits(struct route_query *rq, struct flow **flows)
|
||||
{
|
||||
|
||||
for (size_t k = 0; k < tal_count(flows); k++) {
|
||||
struct flow *flow = flows[k];
|
||||
size_t pathlen = tal_count(flow->path);
|
||||
struct amount_msat hop_amt = flow->delivers;
|
||||
for (size_t i = pathlen - 1; i < pathlen; i--) {
|
||||
const struct half_chan *h = flow_edge(flow, i);
|
||||
struct short_channel_id_dir scidd;
|
||||
|
||||
get_scidd(rq->gossmap, flow, i, &scidd);
|
||||
struct amount_msat htlc_max =
|
||||
get_chan_htlc_max(rq, flow->path[i], &scidd);
|
||||
if (amount_msat_greater(hop_amt, htlc_max))
|
||||
return false;
|
||||
|
||||
if (!amount_msat_add_fee(&hop_amt, h->base_fee,
|
||||
h->proportional_fee))
|
||||
abort();
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/* FIXME: add extra constraint maximum route length, use an activation
|
||||
* probability cost for each channel. Recall that every activation cost, eg.
|
||||
* base fee and activation probability can only be properly added modifying the
|
||||
@@ -1471,6 +1554,23 @@ linear_routes(const tal_t *ctx, struct route_query *rq,
|
||||
* hence after we freed working_ctx. */
|
||||
*probability = flows_probability(ctx, rq, flows);
|
||||
|
||||
/* we should have fixed all htlc violations, "don't trust,
|
||||
* verify" */
|
||||
if (!check_htlc_min_limits(rq, *flows)) {
|
||||
error_message =
|
||||
rq_log(rq, rq, LOG_BROKEN,
|
||||
"%s: check_htlc_min_limits failed", __func__);
|
||||
*flows = tal_free(*flows);
|
||||
goto fail;
|
||||
}
|
||||
if (!check_htlc_max_limits(rq, *flows)) {
|
||||
error_message =
|
||||
rq_log(rq, rq, LOG_BROKEN,
|
||||
"%s: check_htlc_max_limits failed", __func__);
|
||||
*flows = tal_free(*flows);
|
||||
goto fail;
|
||||
}
|
||||
|
||||
return NULL;
|
||||
fail:
|
||||
/* cleanup */
|
||||
|
||||
Reference in New Issue
Block a user