Skip to content

Commit 5b8102e

Browse files
Lagrang3rustyrussell
authored andcommitted
askrene: paranoid checks ...
that new flows respect the HTLC min/max constraints. Changelog-None Signed-off-by: Lagrang3 <[email protected]>
1 parent f7ba8f1 commit 5b8102e

File tree

1 file changed

+100
-0
lines changed

1 file changed

+100
-0
lines changed

plugins/askrene/mcf.c

Lines changed: 100 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1253,6 +1253,89 @@ struct flow **single_path_flow(const tal_t *ctx, const struct route_query *rq,
12531253
return NULL;
12541254
}
12551255

1256+
/* Get the scidd for the i'th hop in flow */
1257+
static void get_scidd(const struct gossmap *gossmap, const struct flow *flow,
1258+
size_t i, struct short_channel_id_dir *scidd)
1259+
{
1260+
scidd->scid = gossmap_chan_scid(gossmap, flow->path[i]);
1261+
scidd->dir = flow->dirs[i];
1262+
}
1263+
1264+
/* We use an fp16_t approximatin for htlc_max/min: this gets the exact value. */
1265+
static struct amount_msat
1266+
get_chan_htlc_max(const struct route_query *rq, const struct gossmap_chan *c,
1267+
const struct short_channel_id_dir *scidd)
1268+
{
1269+
struct amount_msat htlc_max;
1270+
1271+
gossmap_chan_get_update_details(rq->gossmap, c, scidd->dir, NULL, NULL,
1272+
NULL, NULL, NULL, NULL, NULL,
1273+
&htlc_max);
1274+
return htlc_max;
1275+
}
1276+
1277+
static struct amount_msat
1278+
get_chan_htlc_min(const struct route_query *rq, const struct gossmap_chan *c,
1279+
const struct short_channel_id_dir *scidd)
1280+
{
1281+
struct amount_msat htlc_min;
1282+
1283+
gossmap_chan_get_update_details(rq->gossmap, c, scidd->dir, NULL, NULL,
1284+
NULL, NULL, NULL, NULL, &htlc_min,
1285+
NULL);
1286+
return htlc_min;
1287+
}
1288+
1289+
static bool check_htlc_min_limits(struct route_query *rq, struct flow **flows)
1290+
{
1291+
1292+
for (size_t k = 0; k < tal_count(flows); k++) {
1293+
struct flow *flow = flows[k];
1294+
size_t pathlen = tal_count(flow->path);
1295+
struct amount_msat hop_amt = flow->delivers;
1296+
for (size_t i = pathlen - 1; i < pathlen; i--) {
1297+
const struct half_chan *h = flow_edge(flow, i);
1298+
struct short_channel_id_dir scidd;
1299+
1300+
get_scidd(rq->gossmap, flow, i, &scidd);
1301+
struct amount_msat htlc_min =
1302+
get_chan_htlc_min(rq, flow->path[i], &scidd);
1303+
if (amount_msat_less(hop_amt, htlc_min))
1304+
return false;
1305+
1306+
if (!amount_msat_add_fee(&hop_amt, h->base_fee,
1307+
h->proportional_fee))
1308+
abort();
1309+
}
1310+
}
1311+
return true;
1312+
}
1313+
1314+
static bool check_htlc_max_limits(struct route_query *rq, struct flow **flows)
1315+
{
1316+
1317+
for (size_t k = 0; k < tal_count(flows); k++) {
1318+
struct flow *flow = flows[k];
1319+
size_t pathlen = tal_count(flow->path);
1320+
struct amount_msat hop_amt = flow->delivers;
1321+
for (size_t i = pathlen - 1; i < pathlen; i--) {
1322+
const struct half_chan *h = flow_edge(flow, i);
1323+
struct short_channel_id_dir scidd;
1324+
1325+
get_scidd(rq->gossmap, flow, i, &scidd);
1326+
struct amount_msat htlc_max =
1327+
get_chan_htlc_max(rq, flow->path[i], &scidd);
1328+
if (amount_msat_greater(hop_amt, htlc_max))
1329+
return false;
1330+
1331+
if (!amount_msat_add_fee(&hop_amt, h->base_fee,
1332+
h->proportional_fee))
1333+
abort();
1334+
}
1335+
}
1336+
return true;
1337+
}
1338+
12561339
/* FIXME: add extra constraint maximum route length, use an activation
12571340
* probability cost for each channel. Recall that every activation cost, eg.
12581341
* 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,
14711554
* hence after we freed working_ctx. */
14721555
*probability = flows_probability(ctx, rq, flows);
14731556

1557+
/* we should have fixed all htlc violations, "don't trust,
1558+
* verify" */
1559+
if (!check_htlc_min_limits(rq, *flows)) {
1560+
error_message =
1561+
rq_log(rq, rq, LOG_BROKEN,
1562+
"%s: check_htlc_min_limits failed", __func__);
1563+
*flows = tal_free(*flows);
1564+
goto fail;
1565+
}
1566+
if (!check_htlc_max_limits(rq, *flows)) {
1567+
error_message =
1568+
rq_log(rq, rq, LOG_BROKEN,
1569+
"%s: check_htlc_max_limits failed", __func__);
1570+
*flows = tal_free(*flows);
1571+
goto fail;
1572+
}
1573+
14741574
return NULL;
14751575
fail:
14761576
/* cleanup */

0 commit comments

Comments
 (0)