Skip to content

Commit 3c2d662

Browse files
committed
askrene: paranoid checks ...
that new flows respect the HTLC min/max constraints. Changelog-None Signed-off-by: Lagrang3 <[email protected]>
1 parent 7743b0f commit 3c2d662

File tree

1 file changed

+98
-0
lines changed

1 file changed

+98
-0
lines changed

plugins/askrene/mcf.c

Lines changed: 98 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
@@ -1336,6 +1419,21 @@ linear_routes(const tal_t *ctx, struct route_query *rq,
13361419
* right now if all_deliver > amount_to_deliver means a bug. */
13371420
assert(amount_msat_greater_eq(amount_to_deliver, all_deliver));
13381421

1422+
/* we should have fixed all htlc violations, "don't trust,
1423+
* verify" */
1424+
if (!check_htlc_min_limits(rq, new_flows)) {
1425+
error_message = rq_log(
1426+
rq, rq, LOG_BROKEN,
1427+
"%s: check_htlc_min_limits failed", __func__);
1428+
goto fail;
1429+
}
1430+
if (!check_htlc_max_limits(rq, new_flows)) {
1431+
error_message = rq_log(
1432+
rq, rq, LOG_BROKEN,
1433+
"%s: check_htlc_max_limits failed", __func__);
1434+
goto fail;
1435+
}
1436+
13391437
/* no flows should send 0 amount */
13401438
for (size_t i = 0; i < tal_count(new_flows); i++) {
13411439
// FIXME: replace all assertions with LOG_BROKEN

0 commit comments

Comments
 (0)