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