@@ -267,6 +267,32 @@ static struct flow *pick_most_likely_flow(struct route_query *rq,
267267 return best_flow ;
268268}
269269
270+ /* A secondary check for htlc_min violations, after excess trimming. */
271+ static const char * flow_violates_min (const tal_t * ctx ,
272+ struct route_query * rq ,
273+ const struct flow * flow )
274+ {
275+ struct amount_msat msat = flow -> delivers ;
276+ for (int i = tal_count (flow -> path ) - 1 ; i >= 0 ; i -- ) {
277+ const struct half_chan * h = flow_edge (flow , i );
278+ struct amount_msat min = amount_msat (fp16_to_u64 (h -> htlc_min ));
279+
280+ plugin_log (rq -> plugin , LOG_DBG , "flow_violates_min: %u/%zu amt=%s, min=%s" ,
281+ i , tal_count (flow -> path ), fmt_amount_msat (tmpctx , msat ), fmt_amount_msat (tmpctx , min ));
282+ if (amount_msat_less (msat , min )) {
283+ struct short_channel_id_dir scidd ;
284+ get_scidd (rq -> gossmap , flow , i , & scidd );
285+ return tal_fmt (ctx , "Sending %s across %s would violate htlc_min (~%s)" ,
286+ fmt_amount_msat (tmpctx , msat ),
287+ fmt_short_channel_id_dir (tmpctx , & scidd ),
288+ fmt_amount_msat (tmpctx , min ));
289+ }
290+ if (!amount_msat_add_fee (& msat , h -> base_fee , h -> proportional_fee ))
291+ plugin_err (rq -> plugin , "Adding fee to amount" );
292+ }
293+ return NULL ;
294+ }
295+
270296const char *
271297refine_with_fees_and_limits (const tal_t * ctx ,
272298 struct route_query * rq ,
@@ -314,20 +340,38 @@ refine_with_fees_and_limits(const tal_t *ctx,
314340 abort ();
315341 for (size_t i = 0 ; i < tal_count (* flows ); i ++ ) {
316342 if (amount_msat_sub (& (* flows )[i ]-> delivers , (* flows )[i ]-> delivers , excess )) {
343+ const char * err ;
317344 plugin_log (rq -> plugin , LOG_DBG ,
318345 "Flows delivered %s extra, trimming %zu/%zu" ,
319346 fmt_amount_msat (tmpctx , excess ),
320347 i , tal_count (* flows ));
348+ /* In theory, this can violate min_htlc! Thanks @Lagrang3! */
349+ err = flow_violates_min (tmpctx , rq , (* flows )[i ]);
350+ if (err ) {
351+ /* This flow was reduced to 0 / impossible, remove */
352+ tal_arr_remove (flows , i );
353+ i -- ;
354+ /* If this causes failure, indicate why! */
355+ flow_constraint_error = err ;
356+ continue ;
357+ }
321358 break ;
322359 }
323360 }
324- if (!amount_msat_eq (flowset_delivers (rq -> plugin , * flows ), deliver )) {
325- plugin_err (rq -> plugin ,
326- "Flowset delivers %s, can't shed excess?" ,
327- fmt_amount_msat (tmpctx , flowset_delivers (rq -> plugin , * flows )),
328- fmt_amount_msat (tmpctx , deliver ));
361+
362+ /* Usually this should shed excess, *BUT* maybe one
363+ * was deleted instead for being below minimum */
364+ if (!amount_msat_sub (& more_to_deliver , deliver ,
365+ flowset_delivers (rq -> plugin , * flows ))) {
366+ ret = tal_fmt (ctx ,
367+ "Flowset delivers %s instead of %s, can't shed excess?" ,
368+ fmt_amount_msat (tmpctx , flowset_delivers (rq -> plugin , * flows )),
369+ fmt_amount_msat (tmpctx , deliver ));
370+ goto out ;
329371 }
330- more_to_deliver = AMOUNT_MSAT (0 );
372+
373+ plugin_log (rq -> plugin , LOG_DBG , "After dealing with excess, more_to_deliver=%s" ,
374+ fmt_amount_msat (tmpctx , more_to_deliver ));
331375 }
332376
333377 /* The residual is minimal. In theory we could add one msat at a time
0 commit comments