@@ -444,6 +444,21 @@ payment_constraints_update(struct payment_constraints *cons,
444444 return true;
445445}
446446
447+ static struct channel_hint * payment_chanhints_get (struct payment * p ,
448+ struct route_hop * h )
449+ {
450+ struct payment * root = payment_root (p );
451+ struct channel_hint * curhint ;
452+ for (size_t j = 0 ; j < tal_count (root -> channel_hints ); j ++ ) {
453+ curhint = & root -> channel_hints [j ];
454+ if (short_channel_id_eq (& curhint -> scid .scid , & h -> channel_id ) &&
455+ curhint -> scid .dir == h -> direction ) {
456+ return curhint ;
457+ }
458+ }
459+ return NULL ;
460+ }
461+
447462/* Given a route and a couple of channel hints, apply the route to the channel
448463 * hints, so we have a better estimation of channel's capacity. We apply a
449464 * route to a channel hint before calling `sendonion` so subsequent `route`
@@ -453,57 +468,83 @@ payment_constraints_update(struct payment_constraints *cons,
453468 * through, since the balances really changed in that case. The `remove`
454469 * argument indicates whether we want to apply (`remove=false`), or clear a
455470 * prior application (`remove=true`). */
456- static void payment_chanhints_apply_route (struct payment * p , bool remove )
471+ static bool payment_chanhints_apply_route (struct payment * p , bool remove )
457472{
458473 struct route_hop * curhop ;
459474 struct channel_hint * curhint ;
460475 struct payment * root = payment_root (p );
461476 assert (p -> route != NULL );
477+
478+ /* No need to check for applicability if we increase
479+ * capacity and budgets. */
480+ if (remove )
481+ goto apply_changes ;
482+
483+ /* First round: make sure we can cleanly apply the update. */
462484 for (size_t i = 0 ; i < tal_count (p -> route ); i ++ ) {
463485 curhop = & p -> route [i ];
464- for (size_t j = 0 ; j < tal_count (root -> channel_hints ); j ++ ) {
465- curhint = & root -> channel_hints [j ];
466- if (short_channel_id_eq (& curhint -> scid .scid ,
467- & curhop -> channel_id ) &&
468- curhint -> scid .dir == curhop -> direction ) {
469-
470- /* Update the number of htlcs for any local
471- * channel in the route */
472- if (curhint -> local && remove )
473- curhint -> htlc_budget ++ ;
474- else if (curhint -> local )
475- curhint -> htlc_budget -- ;
476-
477- if (remove && !amount_msat_add (
478- & curhint -> estimated_capacity ,
479- curhint -> estimated_capacity ,
480- curhop -> amount )) {
481- /* This should never happen, it'd mean
482- * that we unapply a route that would
483- * result in a msatoshi
484- * wrap-around. */
485- abort ();
486- } else if (!amount_msat_sub (
487- & curhint -> estimated_capacity ,
488- curhint -> estimated_capacity ,
489- curhop -> amount )) {
490- /* This can happen in case of multipl
491- * concurrent getroute calls using the
492- * same channel_hints, no biggy, it's
493- * an estimation anyway. */
494- paymod_log (
495- p , LOG_UNUSUAL ,
496- "Could not update the channel hint "
497- "for %s. Could be a concurrent "
498- "`getroute` call." ,
499- type_to_string (
500- tmpctx ,
501- struct short_channel_id_dir ,
502- & curhint -> scid ));
503- }
504- }
486+ curhint = payment_chanhints_get (root , curhop );
487+
488+ /* If we don't have a hint we can't fail updating it. */
489+ if (!curhint )
490+ continue ;
491+
492+ /* A failure can happen if we add an HTLC, and either
493+ * the local htlc_budget is exhausted, or the capacity
494+ * is exceeded. */
495+ if ((curhint -> local && curhint -> htlc_budget <= 0 ) ||
496+ amount_msat_greater (curhop -> amount ,
497+ curhint -> estimated_capacity )) {
498+ /* This can happen in case of multiple
499+ * concurrent getroute calls using the
500+ * same channel_hints, no biggy, it's
501+ * an estimation anyway. */
502+ paymod_log (p , LOG_DBG ,
503+ "Could not update the channel hint "
504+ "for %s. Could be a concurrent "
505+ "`getroute` call." ,
506+ type_to_string (tmpctx ,
507+ struct short_channel_id_dir ,
508+ & curhint -> scid ));
509+ return false;
505510 }
506511 }
512+
513+ apply_changes :
514+ /* Second round: apply the changes, now that we know they'll succeed. */
515+ for (size_t i = 0 ; i < tal_count (p -> route ); i ++ ) {
516+ curhop = & p -> route [i ];
517+ curhint = payment_chanhints_get (root , curhop );
518+ if (!curhint )
519+ continue ;
520+
521+ /* Update the number of htlcs for any local
522+ * channel in the route */
523+ if (curhint -> local && remove )
524+ curhint -> htlc_budget ++ ;
525+ else if (curhint -> local )
526+ curhint -> htlc_budget -- ;
527+
528+ if (remove && !amount_msat_add (
529+ & curhint -> estimated_capacity ,
530+ curhint -> estimated_capacity ,
531+ curhop -> amount )) {
532+ /* This should never happen, it'd mean
533+ * that we unapply a route that would
534+ * result in a msatoshi
535+ * wrap-around. */
536+ abort ();
537+ } else if (!amount_msat_sub (
538+ & curhint -> estimated_capacity ,
539+ curhint -> estimated_capacity ,
540+ curhop -> amount )) {
541+ /* Given our preemptive test
542+ * above, this should never
543+ * happen either. */
544+ abort ();
545+ }
546+ }
547+ return true;
507548}
508549
509550static const struct short_channel_id_dir *
0 commit comments