@@ -174,6 +174,9 @@ static const double CHANNEL_PIVOTS[]={0,0.5,0.8,0.95};
174174static const s64 INFINITE = INT64_MAX ;
175175static const s64 MU_MAX = 100 ;
176176
177+ /* every payment under 1000sat will be routed through a single path */
178+ static const struct amount_msat SINGLE_PATH_THRESHOLD = AMOUNT_MSAT (1000000 );
179+
177180/* Let's try this encoding of arcs:
178181 * Each channel `c` has two possible directions identified by a bit
179182 * `half` or `!half`, and each one of them has to be
@@ -324,6 +327,15 @@ static void set_capacity(s64 *capacity, u64 value, u64 *cap_on_capacity)
324327 * cap_on_capacity -= * capacity ;
325328}
326329
330+ /* Helper to check whether a channel is available */
331+ static bool channel_is_available (const struct route_query * rq ,
332+ const struct gossmap_chan * chan , const int dir )
333+ {
334+ const u32 c_idx = gossmap_chan_idx (rq -> gossmap , chan );
335+ return gossmap_chan_set (chan , dir ) && chan -> half [dir ].enabled &&
336+ !bitmap_test_bit (rq -> disabled_chans , c_idx * 2 + dir );
337+ }
338+
327339/* FIXME: unit test this */
328340/* The probability of forwarding a payment amount given a high and low liquidity
329341 * bounds.
@@ -567,16 +579,15 @@ static void init_linear_network(const tal_t *ctx,
567579 int half ;
568580 const struct gossmap_chan * c = gossmap_nth_chan (gossmap ,
569581 node , j , & half );
582+ const u32 chan_id = gossmap_chan_idx (gossmap , c );
570583
571- if (!gossmap_chan_set ( c , half ) || ! c -> half [ half ]. enabled )
584+ if (!channel_is_available ( params -> rq , c , half ))
572585 continue ;
573586
574587 /* If a channel insists on more than our total, remove it */
575588 if (amount_msat_less (params -> amount , gossmap_chan_htlc_min (c , half )))
576589 continue ;
577590
578- const u32 chan_id = gossmap_chan_idx (gossmap , c );
579-
580591 const struct gossmap_node * next = gossmap_nth_node (gossmap ,
581592 c ,!half );
582593
@@ -644,15 +655,16 @@ struct chan_flow
644655 * */
645656static struct node find_path_or_cycle (
646657 const tal_t * working_ctx ,
647- const struct gossmap * gossmap ,
648- const struct chan_flow * chan_flow ,
658+ const struct route_query * rq ,
659+ const struct chan_flow * chan_flow ,
649660 const struct node source ,
650661 const s64 * balance ,
651662
652663 const struct gossmap_chan * * prev_chan ,
653664 int * prev_dir ,
654665 u32 * prev_idx )
655666{
667+ const struct gossmap * gossmap = rq -> gossmap ;
656668 const size_t max_num_nodes = gossmap_max_node_idx (gossmap );
657669 bitmap * visited =
658670 tal_arrz (working_ctx , bitmap , BITMAP_NWORDS (max_num_nodes ));
@@ -670,12 +682,11 @@ static struct node find_path_or_cycle(
670682 int dir ;
671683 const struct gossmap_chan * c =
672684 gossmap_nth_chan (gossmap , cur , i , & dir );
685+ const u32 c_idx = gossmap_chan_idx (gossmap , c );
673686
674- if (!gossmap_chan_set ( c , dir ) || ! c -> half [ dir ]. enabled )
687+ if (!channel_is_available ( rq , c , dir ))
675688 continue ;
676689
677- const u32 c_idx = gossmap_chan_idx (gossmap , c );
678-
679690 /* follow the flow */
680691 if (chan_flow [c_idx ].half [dir ] > 0 ) {
681692 const struct gossmap_node * n =
@@ -877,7 +888,7 @@ get_flow_paths(const tal_t *ctx,
877888 while (balance [source .idx ] < 0 ) {
878889 prev_chan [source .idx ] = NULL ;
879890 struct node sink = find_path_or_cycle (
880- working_ctx , params -> rq -> gossmap , chan_flow , source ,
891+ working_ctx , params -> rq , chan_flow , source ,
881892 balance , prev_chan , prev_dir , prev_idx );
882893
883894 if (balance [sink .idx ] > 0 )
@@ -1059,22 +1070,6 @@ struct flow **minflow(const tal_t *ctx,
10591070 return NULL ;
10601071}
10611072
1062- static struct amount_msat linear_flows_cost (struct flow * * flows ,
1063- struct amount_msat total_amount ,
1064- double delay_feefactor )
1065- {
1066- struct amount_msat total = AMOUNT_MSAT (0 );
1067-
1068- for (size_t i = 0 ; i < tal_count (flows ); i ++ ) {
1069- if (!amount_msat_accumulate (& total ,
1070- linear_flow_cost (flows [i ],
1071- total_amount ,
1072- delay_feefactor )))
1073- abort ();
1074- }
1075- return total ;
1076- }
1077-
10781073/* Initialize the data vectors for the single-path solver. */
10791074static void init_linear_network_single_path (
10801075 const tal_t * ctx , const struct pay_parameters * params , struct graph * * graph ,
@@ -1105,9 +1100,9 @@ static void init_linear_network_single_path(
11051100 const struct gossmap_chan * c =
11061101 gossmap_nth_chan (gossmap , node , j , & half );
11071102 struct amount_msat mincap , maxcap ;
1103+ const u32 chan_id = gossmap_chan_idx (gossmap , c );
11081104
1109- if (!gossmap_chan_set (c , half ) ||
1110- !c -> half [half ].enabled )
1105+ if (!channel_is_available (params -> rq , c , half ))
11111106 continue ;
11121107
11131108 /* If a channel cannot forward the total amount we don't
@@ -1132,8 +1127,6 @@ static void init_linear_network_single_path(
11321127 if (amount_msat_greater_eq (params -> amount , maxcap ))
11331128 continue ;
11341129
1135- const u32 chan_id = gossmap_chan_idx (gossmap , c );
1136-
11371130 const struct gossmap_node * next =
11381131 gossmap_nth_node (gossmap , c , !half );
11391132
@@ -1256,6 +1249,67 @@ struct flow **single_path_flow(const tal_t *ctx, const struct route_query *rq,
12561249 return NULL ;
12571250}
12581251
1252+ /* Get the scidd for the i'th hop in flow */
1253+ static void get_scidd (const struct gossmap * gossmap , const struct flow * flow ,
1254+ size_t i , struct short_channel_id_dir * scidd )
1255+ {
1256+ scidd -> scid = gossmap_chan_scid (gossmap , flow -> path [i ]);
1257+ scidd -> dir = flow -> dirs [i ];
1258+ }
1259+
1260+ /* We use an fp16_t approximatin for htlc_max/min: this gets the exact value. */
1261+ static struct amount_msat
1262+ get_chan_htlc_max (const struct route_query * rq , const struct gossmap_chan * c ,
1263+ const struct short_channel_id_dir * scidd )
1264+ {
1265+ struct amount_msat htlc_max ;
1266+
1267+ gossmap_chan_get_update_details (rq -> gossmap , c , scidd -> dir , NULL , NULL ,
1268+ NULL , NULL , NULL , NULL , NULL ,
1269+ & htlc_max );
1270+ return htlc_max ;
1271+ }
1272+
1273+ static struct amount_msat
1274+ get_chan_htlc_min (const struct route_query * rq , const struct gossmap_chan * c ,
1275+ const struct short_channel_id_dir * scidd )
1276+ {
1277+ struct amount_msat htlc_min ;
1278+
1279+ gossmap_chan_get_update_details (rq -> gossmap , c , scidd -> dir , NULL , NULL ,
1280+ NULL , NULL , NULL , NULL , & htlc_min ,
1281+ NULL );
1282+ return htlc_min ;
1283+ }
1284+
1285+ static bool check_htlc_limits (struct route_query * rq , struct flow * * flows )
1286+ {
1287+
1288+ for (size_t k = 0 ; k < tal_count (flows ); k ++ ) {
1289+ struct flow * flow = flows [k ];
1290+ size_t pathlen = tal_count (flow -> path );
1291+ struct amount_msat hop_amt = flow -> delivers ;
1292+ for (size_t i = pathlen - 1 ; i < pathlen ; i -- ) {
1293+ const struct half_chan * h = flow_edge (flow , i );
1294+ struct short_channel_id_dir scidd ;
1295+
1296+ get_scidd (rq -> gossmap , flow , i , & scidd );
1297+ struct amount_msat htlc_min =
1298+ get_chan_htlc_min (rq , flow -> path [i ], & scidd );
1299+ struct amount_msat htlc_max =
1300+ get_chan_htlc_max (rq , flow -> path [i ], & scidd );
1301+ if (amount_msat_greater (hop_amt , htlc_max ) ||
1302+ amount_msat_less (hop_amt , htlc_min ))
1303+ return false;
1304+
1305+ if (!amount_msat_add_fee (& hop_amt , h -> base_fee ,
1306+ h -> proportional_fee ))
1307+ abort ();
1308+ }
1309+ }
1310+ return true;
1311+ }
1312+
12591313/* FIXME: add extra constraint maximum route length, use an activation
12601314 * probability cost for each channel. Recall that every activation cost, eg.
12611315 * base fee and activation probability can only be properly added modifying the
@@ -1287,43 +1341,50 @@ linear_routes(const tal_t *ctx, struct route_query *rq,
12871341 double delay_feefactor = 1e-6 ;
12881342
12891343 struct flow * * new_flows = NULL ;
1344+ struct amount_msat all_deliver ;
12901345
12911346 * flows = tal_arr (working_ctx , struct flow * , 0 );
12921347
12931348 /* Re-use the reservation system to make flows aware of each other. */
12941349 struct reserve_hop * reservations = new_reservations (working_ctx , rq );
12951350
1351+ /* compute the probability one flow at a time. */
1352+ * probability = 1.0 ;
1353+
12961354 while (!amount_msat_is_zero (amount_to_deliver )) {
1297- new_flows = tal_free (new_flows );
1355+ new_flows = tal_free (new_flows );
1356+
1357+ /* If the amount_to_deliver is very small we better use a single
1358+ * path computation because:
1359+ * 1. we save cpu cycles
1360+ * 2. we have better control over htlc_min violations.
1361+ * We need to make the distinction here because after
1362+ * refine_with_fees_and_limits we might have a set of flows that
1363+ * do not deliver the entire payment amount by just a small
1364+ * amount. */
1365+ if (amount_msat_less_eq (amount_to_deliver , SINGLE_PATH_THRESHOLD )){
1366+ new_flows = single_path_flow (working_ctx , rq , srcnode , dstnode ,
1367+ amount_to_deliver , mu , delay_feefactor );
1368+ } else {
12981369
1299- new_flows = solver (working_ctx , rq , srcnode , dstnode ,
1370+ new_flows =
1371+ solver (working_ctx , rq , srcnode , dstnode ,
13001372 amount_to_deliver , mu , delay_feefactor );
1373+ }
1374+
13011375 if (!new_flows ) {
13021376 error_message = explain_failure (
13031377 ctx , rq , srcnode , dstnode , amount_to_deliver );
13041378 goto fail ;
13051379 }
13061380
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- //
1381+ error_message = refine_with_fees_and_limits (
1382+ ctx , rq , amount_to_deliver , & new_flows );
1383+ if (error_message )
1384+ goto fail ;
13231385
13241386 /* we finished removing flows and excess */
1325- const struct amount_msat all_deliver =
1326- flowset_delivers (rq -> plugin , new_flows );
1387+ all_deliver = flowset_delivers (rq -> plugin , new_flows );
13271388 if (amount_msat_is_zero (all_deliver )) {
13281389 /* We removed all flows and we have not modified the
13291390 * MCF parameters. We will not have an infinite loop
@@ -1336,6 +1397,15 @@ linear_routes(const tal_t *ctx, struct route_query *rq,
13361397 * right now if all_deliver > amount_to_deliver means a bug. */
13371398 assert (amount_msat_greater_eq (amount_to_deliver , all_deliver ));
13381399
1400+ /* we should have fixed all htlc violations, "don't trust,
1401+ * verify" */
1402+ assert (check_htlc_limits (rq , new_flows ));
1403+
1404+ /* no flows should send 0 amount */
1405+ for (size_t i = 0 ; i < tal_count (new_flows ); i ++ ) {
1406+ assert (!amount_msat_is_zero (new_flows [i ]-> delivers ));
1407+ }
1408+
13391409 /* Is this set of flows too expensive?
13401410 * We can check if the new flows are within the fee budget,
13411411 * however in some cases we have discarded some flows at this
@@ -1356,7 +1426,7 @@ linear_routes(const tal_t *ctx, struct route_query *rq,
13561426 error_message =
13571427 rq_log (ctx , rq , LOG_BROKEN ,
13581428 "%s: failed to scale the fee budget (%s) by "
1359- "fraction (%ld )" ,
1429+ "fraction (%lf )" ,
13601430 __func__ , fmt_amount_msat (tmpctx , feebudget ),
13611431 deliver_fraction );
13621432 goto fail ;
@@ -1422,7 +1492,8 @@ linear_routes(const tal_t *ctx, struct route_query *rq,
14221492 /* add the new flows to the final solution */
14231493 for (size_t i = 0 ; i < tal_count (new_flows ); i ++ ) {
14241494 tal_arr_expand (flows , new_flows [i ]);
1425- tal_steal (flows , new_flows [i ]);
1495+ tal_steal (* flows , new_flows [i ]);
1496+ * probability *= flow_probability (new_flows [i ], rq );
14261497 create_flow_reservations (rq , & reservations ,
14271498 new_flows [i ]);
14281499 }
0 commit comments