@@ -1256,6 +1256,13 @@ struct flow **single_path_flow(const tal_t *ctx, const struct route_query *rq,
1256
1256
return NULL ;
1257
1257
}
1258
1258
1259
+ /* FIXME: add extra constraint maximum route length, use an activation
1260
+ * probability cost for each channel. Recall that every activation cost, eg.
1261
+ * base fee and activation probability can only be properly added modifying the
1262
+ * graph topology by creating an activation node for every half channel. */
1263
+ /* FIXME: add extra constraint maximum number of routes, fixes issue 8331. */
1264
+ /* FIXME: add a boolean option to make recipient pay for fees, fixes issue 8353.
1265
+ */
1259
1266
static const char *
1260
1267
linear_routes (const tal_t * ctx , struct route_query * rq ,
1261
1268
const struct gossmap_node * srcnode ,
@@ -1267,133 +1274,183 @@ linear_routes(const tal_t *ctx, struct route_query *rq,
1267
1274
const struct gossmap_node * ,
1268
1275
struct amount_msat , u32 , double ))
1269
1276
{
1270
- * flows = NULL ;
1271
- const char * ret ;
1272
- double delay_feefactor = 1.0 / 1000000 ;
1273
-
1274
- /* First up, don't care about fees (well, just enough to tiebreak!) */
1277
+ const tal_t * working_ctx = tal (ctx , tal_t );
1278
+ const char * error_message ;
1279
+ struct amount_msat amount_to_deliver = amount ;
1280
+ struct amount_msat feebudget = maxfee ;
1281
+
1282
+ /* FIXME: mu is an integer from 0 to MU_MAX that we use to combine fees
1283
+ * and probability costs, but I think we can make it a real number from
1284
+ * 0 to 1. */
1275
1285
u32 mu = 1 ;
1276
- tal_free (* flows );
1277
- * flows = solver (ctx , rq , srcnode , dstnode , amount , mu , delay_feefactor );
1278
- if (!* flows ) {
1279
- ret = explain_failure (ctx , rq , srcnode , dstnode , amount );
1280
- goto fail ;
1281
- }
1286
+ /* we start at 1e-6 and increase it exponentially (x2) up to 10. */
1287
+ double delay_feefactor = 1e-6 ;
1288
+
1289
+ struct flow * * new_flows = NULL ;
1290
+
1291
+ * flows = tal_arr (working_ctx , struct flow * , 0 );
1292
+
1293
+ /* Re-use the reservation system to make flows aware of each other. */
1294
+ struct reserve_hop * reservations = new_reservations (working_ctx , rq );
1295
+
1296
+ while (!amount_msat_is_zero (amount_to_deliver )) {
1297
+ new_flows = tal_free (new_flows );
1282
1298
1283
- /* Too much delay? */
1284
- while (finalcltv + flows_worst_delay (* flows ) > maxdelay ) {
1285
- delay_feefactor *= 2 ;
1286
- rq_log (tmpctx , rq , LOG_UNUSUAL ,
1287
- "The worst flow delay is %" PRIu64
1288
- " (> %i), retrying with delay_feefactor %f..." ,
1289
- flows_worst_delay (* flows ), maxdelay - finalcltv ,
1290
- delay_feefactor );
1291
- tal_free (* flows );
1292
- * flows = solver (ctx , rq , srcnode , dstnode , amount , mu ,
1293
- delay_feefactor );
1294
- if (!* flows || delay_feefactor > 10 ) {
1295
- ret = rq_log (
1296
- ctx , rq , LOG_UNUSUAL ,
1297
- "Could not find route without excessive delays" );
1299
+ new_flows = solver (working_ctx , rq , srcnode , dstnode ,
1300
+ amount_to_deliver , mu , delay_feefactor );
1301
+ if (!new_flows ) {
1302
+ error_message = explain_failure (
1303
+ ctx , rq , srcnode , dstnode , amount_to_deliver );
1298
1304
goto fail ;
1299
1305
}
1300
- }
1301
1306
1302
- /* Too expensive? */
1303
- too_expensive :
1304
- while (amount_msat_greater (flowset_fee (rq -> plugin , * flows ), maxfee )) {
1305
- struct flow * * new_flows ;
1306
-
1307
- if (mu == 1 )
1308
- mu = 10 ;
1309
- else
1310
- mu += 10 ;
1311
- rq_log (tmpctx , rq , LOG_UNUSUAL ,
1312
- "The flows had a fee of %s, greater than max of %s, "
1313
- "retrying with mu of %u%%..." ,
1314
- fmt_amount_msat (tmpctx , flowset_fee (rq -> plugin , * flows )),
1315
- fmt_amount_msat (tmpctx , maxfee ), mu );
1316
- new_flows = solver (ctx , rq , srcnode , dstnode , amount ,
1317
- mu > 100 ? 100 : mu , delay_feefactor );
1318
- if (!* flows || mu >= 100 ) {
1319
- ret = rq_log (
1320
- ctx , rq , LOG_UNUSUAL ,
1321
- "Could not find route without excessive cost" );
1322
- goto fail ;
1307
+ // TODO:
1308
+ // trim flows to meet htlc_max constraints
1309
+ // trim flows to deliver no more amount_to_deliver
1310
+ //
1311
+ // ? increase flows to deliver no less than amount_to_deliver,
1312
+ // but
1313
+ // take max_deliverable into consideration
1314
+ //
1315
+ // remove flows that have htlc_min violations, disable the
1316
+ // culprit channel
1317
+
1318
+ // for each flow
1319
+ // compute amounts and adjust to htlc max
1320
+ // disable some channels to void violations of htlc_min
1321
+ // call refine_with_fees_and_limits?
1322
+ //
1323
+
1324
+ /* we finished removing flows and excess */
1325
+ const struct amount_msat all_deliver =
1326
+ flowset_delivers (rq -> plugin , new_flows );
1327
+ if (amount_msat_is_zero (all_deliver )) {
1328
+ /* We removed all flows and we have not modified the
1329
+ * MCF parameters. We will not have an infinite loop
1330
+ * here because at least we have disabled some channels.
1331
+ */
1332
+ continue ;
1323
1333
}
1324
1334
1325
- /* This is possible, because MCF's linear fees are not the same.
1326
- */
1327
- if (amount_msat_greater (flowset_fee (rq -> plugin , new_flows ),
1328
- flowset_fee (rq -> plugin , * flows ))) {
1329
- struct amount_msat old_cost =
1330
- linear_flows_cost (* flows , amount , delay_feefactor );
1331
- struct amount_msat new_cost = linear_flows_cost (
1332
- new_flows , amount , delay_feefactor );
1333
- if (amount_msat_greater_eq (new_cost , old_cost )) {
1334
- rq_log (tmpctx , rq , LOG_BROKEN ,
1335
- "Old flows cost %s:" ,
1336
- fmt_amount_msat (tmpctx , old_cost ));
1337
- for (size_t i = 0 ; i < tal_count (* flows ); i ++ ) {
1338
- rq_log (
1339
- tmpctx , rq , LOG_BROKEN ,
1340
- "Flow %zu/%zu: %s (linear cost %s)" ,
1341
- i , tal_count (* flows ),
1342
- fmt_flow_full (tmpctx , rq , (* flows )[i ]),
1343
- fmt_amount_msat (
1344
- tmpctx , linear_flow_cost (
1345
- (* flows )[i ], amount ,
1346
- delay_feefactor )));
1347
- }
1348
- rq_log (tmpctx , rq , LOG_BROKEN ,
1349
- "Old flows cost %s:" ,
1350
- fmt_amount_msat (tmpctx , new_cost ));
1351
- for (size_t i = 0 ; i < tal_count (new_flows );
1352
- i ++ ) {
1353
- rq_log (
1354
- tmpctx , rq , LOG_BROKEN ,
1355
- "Flow %zu/%zu: %s (linear cost %s)" ,
1356
- i , tal_count (new_flows ),
1357
- fmt_flow_full (tmpctx , rq ,
1358
- new_flows [i ]),
1359
- fmt_amount_msat (
1360
- tmpctx ,
1361
- linear_flow_cost (
1362
- new_flows [i ], amount ,
1363
- delay_feefactor )));
1364
- }
1335
+ /* We might want to overpay sometimes, eg. shadow routing, but
1336
+ * right now if all_deliver > amount_to_deliver means a bug. */
1337
+ assert (amount_msat_greater_eq (amount_to_deliver , all_deliver ));
1338
+
1339
+ /* Is this set of flows too expensive?
1340
+ * We can check if the new flows are within the fee budget,
1341
+ * however in some cases we have discarded some flows at this
1342
+ * point and the new flows do not deliver all the value we need
1343
+ * so that a further solver iteration is needed. Hence we
1344
+ * check if the fees paid by these new flows are below the
1345
+ * feebudget proportionally adjusted by the amount this set of
1346
+ * flows deliver with respect to the total remaining amount,
1347
+ * ie. we avoid "consuming" all the feebudget if we still need
1348
+ * to run MCF again for some remaining amount. */
1349
+ const struct amount_msat all_fees =
1350
+ flowset_fee (rq -> plugin , new_flows );
1351
+ const double deliver_fraction =
1352
+ amount_msat_ratio (all_deliver , amount_to_deliver );
1353
+ struct amount_msat partial_feebudget ;
1354
+ if (!amount_msat_scale (& partial_feebudget , feebudget ,
1355
+ deliver_fraction )) {
1356
+ error_message =
1357
+ rq_log (ctx , rq , LOG_BROKEN ,
1358
+ "%s: failed to scale the fee budget (%s) by "
1359
+ "fraction (%ld)" ,
1360
+ __func__ , fmt_amount_msat (tmpctx , feebudget ),
1361
+ deliver_fraction );
1362
+ goto fail ;
1363
+ }
1364
+ if (amount_msat_greater (all_fees , partial_feebudget )) {
1365
+ if (mu < MU_MAX ) {
1366
+ /* all_fees exceed the strong budget limit, try
1367
+ * to fix it increasing mu. */
1368
+ if (mu == 1 )
1369
+ mu = 10 ;
1370
+ else
1371
+ mu += 10 ;
1372
+ mu = MIN (mu , MU_MAX );
1373
+ rq_log (
1374
+ tmpctx , rq , LOG_UNUSUAL ,
1375
+ "The flows had a fee of %s, greater than "
1376
+ "max of %s, retrying with mu of %u%%..." ,
1377
+ fmt_amount_msat (tmpctx , all_fees ),
1378
+ fmt_amount_msat (tmpctx , partial_feebudget ),
1379
+ mu );
1380
+ continue ;
1381
+ } else if (amount_msat_greater (all_fees , feebudget )) {
1382
+ /* we cannot increase mu anymore and all_fees
1383
+ * already exceeds feebudget we fail. */
1384
+ error_message =
1385
+ rq_log (ctx , rq , LOG_UNUSUAL ,
1386
+ "Could not find route without "
1387
+ "excessive cost" );
1388
+ goto fail ;
1389
+ } else {
1390
+ /* mu cannot be increased but at least all_fees
1391
+ * does not exceed feebudget, we give it a shot.
1392
+ */
1393
+ rq_log (
1394
+ tmpctx , rq , LOG_UNUSUAL ,
1395
+ "The flows had a fee of %s, greater than "
1396
+ "max of %s, but still within the fee "
1397
+ "budget %s, we accept those flows." ,
1398
+ fmt_amount_msat (tmpctx , all_fees ),
1399
+ fmt_amount_msat (tmpctx , partial_feebudget ),
1400
+ fmt_amount_msat (tmpctx , feebudget ));
1365
1401
}
1366
1402
}
1367
- tal_free (* flows );
1368
- * flows = new_flows ;
1369
- }
1370
1403
1371
- if (finalcltv + flows_worst_delay (* flows ) > maxdelay ) {
1372
- ret = rq_log (
1373
- ctx , rq , LOG_UNUSUAL ,
1374
- "Could not find route without excessive cost or delays" );
1375
- goto fail ;
1376
- }
1404
+ /* Too much delay? */
1405
+ if (finalcltv + flows_worst_delay (new_flows ) > maxdelay ) {
1406
+ if (delay_feefactor > 10 ) {
1407
+ error_message =
1408
+ rq_log (ctx , rq , LOG_UNUSUAL ,
1409
+ "Could not find route without "
1410
+ "excessive delays" );
1411
+ goto fail ;
1412
+ }
1377
1413
1378
- /* The above did not take into account the extra funds to pay
1379
- * fees, so we try to adjust now. We could re-run MCF if this
1380
- * fails, but failure basically never happens where payment is
1381
- * still possible */
1382
- ret = refine_with_fees_and_limits (ctx , rq , amount , flows , probability );
1383
- if (ret )
1384
- goto fail ;
1414
+ delay_feefactor *= 2 ;
1415
+ rq_log (tmpctx , rq , LOG_UNUSUAL ,
1416
+ "The worst flow delay is %" PRIu64
1417
+ " (> %i), retrying with delay_feefactor %f..." ,
1418
+ flows_worst_delay (* flows ), maxdelay - finalcltv ,
1419
+ delay_feefactor );
1420
+ }
1421
+
1422
+ /* add the new flows to the final solution */
1423
+ for (size_t i = 0 ; i < tal_count (new_flows ); i ++ ) {
1424
+ tal_arr_expand (flows , new_flows [i ]);
1425
+ tal_steal (flows , new_flows [i ]);
1426
+ create_flow_reservations (rq , & reservations ,
1427
+ new_flows [i ]);
1428
+ }
1385
1429
1386
- /* Again, a tiny corner case: refine step can make us exceed maxfee */
1387
- if (amount_msat_greater (flowset_fee (rq -> plugin , * flows ), maxfee )) {
1388
- rq_log (tmpctx , rq , LOG_UNUSUAL ,
1389
- "After final refinement, fee was excessive: retrying" );
1390
- goto too_expensive ;
1430
+ if (!amount_msat_sub (& feebudget , feebudget , all_fees ) ||
1431
+ !amount_msat_sub (& amount_to_deliver , amount_to_deliver ,
1432
+ all_deliver )) {
1433
+ error_message =
1434
+ rq_log (ctx , rq , LOG_BROKEN ,
1435
+ "%s: unexpected arithmetic operation "
1436
+ "failure on amount_msat" ,
1437
+ __func__ );
1438
+ goto fail ;
1439
+ }
1391
1440
}
1392
1441
1442
+ /* transfer ownership */
1443
+ * flows = tal_steal (ctx , * flows );
1444
+
1445
+ /* cleanup */
1446
+ tal_free (working_ctx );
1393
1447
return NULL ;
1394
1448
fail :
1395
- assert (ret != NULL );
1396
- return ret ;
1449
+ /* cleanup */
1450
+ tal_free (working_ctx );
1451
+
1452
+ assert (error_message != NULL );
1453
+ return error_message ;
1397
1454
}
1398
1455
1399
1456
const char * default_routes (const tal_t * ctx , struct route_query * rq ,
0 commit comments