Skip to content

Commit 6d2455e

Browse files
committed
askrene: debug and check we actually reduce fees when mu increase.
Even after the previous fix, we still occasionally increase fees when my increases. This is due to the difference between MCF's linear fees, and actual fees, and is unavoidable, but add a check if it somehow happens. Signed-off-by: Rusty Russell <[email protected]>
1 parent 79a19d8 commit 6d2455e

File tree

3 files changed

+106
-2
lines changed

3 files changed

+106
-2
lines changed

plugins/askrene/askrene.c

Lines changed: 79 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -263,6 +263,56 @@ static const char *fmt_route(const tal_t *ctx,
263263
return str;
264264
}
265265

266+
static const char *fmt_flow_full(const tal_t *ctx,
267+
const struct route_query *rq,
268+
const struct flow *flow,
269+
struct amount_msat total_delivered,
270+
double delay_feefactor)
271+
{
272+
struct amount_msat amt = flow->delivers;
273+
char *str = tal_fmt(ctx, "%s (linear cost %s)",
274+
fmt_amount_msat(tmpctx, amt),
275+
fmt_amount_msat(tmpctx, linear_flow_cost(flow,
276+
total_delivered,
277+
delay_feefactor)));
278+
279+
for (int i = tal_count(flow->path) - 1; i >= 0; i--) {
280+
struct short_channel_id_dir scidd;
281+
struct amount_msat min, max;
282+
scidd.scid = gossmap_chan_scid(rq->gossmap, flow->path[i]);
283+
scidd.dir = flow->dirs[i];
284+
if (!amount_msat_add_fee(&amt,
285+
flow->path[i]->half[scidd.dir].base_fee,
286+
flow->path[i]->half[scidd.dir].proportional_fee))
287+
abort();
288+
get_constraints(rq, flow->path[i], scidd.dir, &min, &max);
289+
tal_append_fmt(&str, " <- %s %s (cap=%s,fee=%u+%u,delay=%u)",
290+
fmt_amount_msat(tmpctx, amt),
291+
fmt_short_channel_id_dir(tmpctx, &scidd),
292+
fmt_amount_msat(tmpctx, max),
293+
flow->path[i]->half[scidd.dir].base_fee,
294+
flow->path[i]->half[scidd.dir].proportional_fee,
295+
flow->path[i]->half[scidd.dir].delay);
296+
}
297+
return str;
298+
}
299+
300+
static struct amount_msat linear_flows_cost(struct flow **flows,
301+
struct amount_msat total_amount,
302+
double delay_feefactor)
303+
{
304+
struct amount_msat total = AMOUNT_MSAT(0);
305+
306+
for (size_t i = 0; i < tal_count(flows); i++) {
307+
if (!amount_msat_accumulate(&total,
308+
linear_flow_cost(flows[i],
309+
total_amount,
310+
delay_feefactor)))
311+
abort();
312+
}
313+
return total;
314+
}
315+
266316
/* Returns an error message, or sets *routes */
267317
static const char *get_routes(const tal_t *ctx,
268318
struct command *cmd,
@@ -383,19 +433,46 @@ static const char *get_routes(const tal_t *ctx,
383433
/* Too expensive? */
384434
too_expensive:
385435
while (amount_msat_greater(flowset_fee(rq->plugin, flows), maxfee)) {
436+
struct flow **new_flows;
437+
386438
mu += 10;
387439
rq_log(tmpctx, rq, LOG_UNUSUAL,
388440
"The flows had a fee of %s, greater than max of %s, retrying with mu of %u%%...",
389441
fmt_amount_msat(tmpctx, flowset_fee(rq->plugin, flows)),
390442
fmt_amount_msat(tmpctx, maxfee),
391443
mu);
392-
flows = minflow(rq, rq, srcnode, dstnode, amount,
393-
mu > 100 ? 100 : mu, delay_feefactor);
444+
new_flows = minflow(rq, rq, srcnode, dstnode, amount,
445+
mu > 100 ? 100 : mu, delay_feefactor);
394446
if (!flows || mu >= 100) {
395447
ret = rq_log(ctx, rq, LOG_UNUSUAL,
396448
"Could not find route without excessive cost");
397449
goto fail;
398450
}
451+
452+
/* This is possible, because MCF's linear fees are not the same. */
453+
if (amount_msat_greater(flowset_fee(rq->plugin, new_flows),
454+
flowset_fee(rq->plugin, flows))) {
455+
struct amount_msat old_cost = linear_flows_cost(flows, amount, delay_feefactor);
456+
struct amount_msat new_cost = linear_flows_cost(new_flows, amount, delay_feefactor);
457+
if (amount_msat_greater_eq(new_cost, old_cost)) {
458+
rq_log(tmpctx, rq, LOG_BROKEN, "Old flows cost %s:",
459+
fmt_amount_msat(tmpctx, old_cost));
460+
for (size_t i = 0; i < tal_count(flows); i++) {
461+
rq_log(tmpctx, rq, LOG_BROKEN,
462+
"Flow %zu/%zu: %s", i, tal_count(flows),
463+
fmt_flow_full(tmpctx, rq, flows[i], amount, delay_feefactor));
464+
}
465+
rq_log(tmpctx, rq, LOG_BROKEN, "Old flows cost %s:",
466+
fmt_amount_msat(tmpctx, new_cost));
467+
for (size_t i = 0; i < tal_count(new_flows); i++) {
468+
rq_log(tmpctx, rq, LOG_BROKEN,
469+
"Flow %zu/%zu: %s", i, tal_count(new_flows),
470+
fmt_flow_full(tmpctx, rq, new_flows[i], amount, delay_feefactor));
471+
}
472+
}
473+
}
474+
tal_free(flows);
475+
flows = new_flows;
399476
}
400477

401478
if (finalcltv + flows_worst_delay(flows) > 2016) {

plugins/askrene/mcf.c

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -549,6 +549,26 @@ static double base_fee_penalty_estimate(struct amount_msat amount)
549549
return amount_msat_ratio(AMOUNT_MSAT(10000000), amount);
550550
}
551551

552+
struct amount_msat linear_flow_cost(const struct flow *flow,
553+
struct amount_msat total_amount,
554+
double delay_feefactor)
555+
{
556+
struct amount_msat msat_cost;
557+
s64 cost = 0;
558+
double base_fee_penalty = base_fee_penalty_estimate(total_amount);
559+
560+
for (size_t i = 0; i < tal_count(flow->path); i++) {
561+
const struct half_chan *h = &flow->path[i]->half[flow->dirs[i]];
562+
563+
cost += linear_fee_cost(h->base_fee, h ->proportional_fee, h->delay,
564+
base_fee_penalty, delay_feefactor);
565+
}
566+
567+
if (!amount_msat_mul(&msat_cost, flow->delivers, cost))
568+
abort();
569+
return msat_cost;
570+
}
571+
552572
static struct linear_network *
553573
init_linear_network(const tal_t *ctx, const struct pay_parameters *params)
554574
{

plugins/askrene/mcf.h

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,4 +30,11 @@ struct flow **minflow(const tal_t *ctx,
3030
struct amount_msat amount,
3131
u32 mu,
3232
double delay_feefactor);
33+
34+
/* To sanity check: this is the approximation mcf uses for the cost
35+
* of each channel. */
36+
struct amount_msat linear_flow_cost(const struct flow *flow,
37+
struct amount_msat total_amount,
38+
double delay_feefactor);
39+
3340
#endif /* LIGHTNING_PLUGINS_ASKRENE_MCF_H */

0 commit comments

Comments
 (0)