@@ -27,6 +27,47 @@ static struct askrene *get_askrene(struct plugin *plugin)
2727 return plugin_get_data (plugin , struct askrene );
2828}
2929
30+ /* "spendable" for a channel assumes a single HTLC: for additional HTLCs,
31+ * the need to pay for fees (if we're the owner) reduces it */
32+ struct per_htlc_cost {
33+ struct short_channel_id_dir scidd ;
34+ struct amount_msat per_htlc_cost ;
35+ };
36+
37+ static const struct short_channel_id_dir *
38+ per_htlc_cost_key (const struct per_htlc_cost * phc )
39+ {
40+ return & phc -> scidd ;
41+ }
42+
43+ static size_t hash_scidd (const struct short_channel_id_dir * scidd )
44+ {
45+ /* scids cost money to generate, so simple hash works here */
46+ return (scidd -> scid .u64 >> 32 ) ^ (scidd -> scid .u64 << 1 ) ^ scidd -> dir ;
47+ }
48+
49+ static inline bool per_htlc_cost_eq_key (const struct per_htlc_cost * phc ,
50+ const struct short_channel_id_dir * scidd )
51+ {
52+ return short_channel_id_dir_eq (scidd , & phc -> scidd );
53+ }
54+
55+ HTABLE_DEFINE_TYPE (struct per_htlc_cost ,
56+ per_htlc_cost_key ,
57+ hash_scidd ,
58+ per_htlc_cost_eq_key ,
59+ additional_cost_htable );
60+
61+ /* Get the scidd for the i'th hop in flow */
62+ static void get_scidd (const struct gossmap * gossmap ,
63+ const struct flow * flow ,
64+ size_t i ,
65+ struct short_channel_id_dir * scidd )
66+ {
67+ scidd -> scid = gossmap_chan_scid (gossmap , flow -> path [i ]);
68+ scidd -> dir = flow -> dirs [i ];
69+ }
70+
3071static bool have_layer (const char * * layers , const char * name )
3172{
3273 for (size_t i = 0 ; i < tal_count (layers ); i ++ ) {
@@ -271,8 +312,7 @@ static void add_reservation(struct reservations *r,
271312 struct askrene * askrene = get_askrene (rq -> plugin );
272313 size_t idx ;
273314
274- scidd .scid = gossmap_chan_scid (rq -> gossmap , flow -> path [i ]);
275- scidd .dir = flow -> dirs [i ];
315+ get_scidd (rq -> gossmap , flow , i , & scidd );
276316
277317 /* This should not happen, but simply don't reserve if it does */
278318 if (!reserves_add (askrene -> reserved , & scidd , & amt , 1 )) {
@@ -293,7 +333,8 @@ static void add_reservation(struct reservations *r,
293333 tal_arr_expand (& r -> amounts , amt );
294334}
295335
296- /* We have a basic set of flows, but we need to add fees. This can
336+ /* We have a basic set of flows, but we need to add fees, and take into
337+ * account that "spendable" estimates are for a single HTLC. This can
297338 * push us again over capacity or htlc_maximum_msat.
298339 *
299340 * We may have to reduce the flow amount in response to these.
@@ -317,7 +358,9 @@ static const char *constrain_flow(const tal_t *ctx,
317358 msat = flow -> delivers ;
318359 for (int i = tal_count (flow -> path ) - 1 ; i >= 0 ; i -- ) {
319360 const struct half_chan * h = flow_edge (flow , i );
320- struct amount_msat min , max ;
361+ struct amount_msat min , max , amount_to_reserve ;
362+ struct short_channel_id_dir scidd ;
363+ const struct per_htlc_cost * phc ;
321364 const char * max_cause ;
322365
323366 /* We can pass constraints due to addition of fees! */
@@ -343,9 +386,19 @@ static const char *constrain_flow(const tal_t *ctx,
343386 why_decreased = max_cause ;
344387 }
345388
389+ /* Reserve more for local channels if it reduces capacity */
390+ get_scidd (rq -> gossmap , flow , i , & scidd );
391+ phc = additional_cost_htable_get (rq -> additional_costs , & scidd );
392+ if (phc ) {
393+ if (!amount_msat_add (& amount_to_reserve , msat , phc -> per_htlc_cost ))
394+ abort ();
395+ } else {
396+ amount_to_reserve = msat ;
397+ }
398+
346399 /* Reserve it, so if the next flow asks about the same channel,
347400 it will see the reduced capacity from this one. */
348- add_reservation (reservations , rq , flow , i , msat );
401+ add_reservation (reservations , rq , flow , i , amount_to_reserve );
349402
350403 if (!amount_msat_add_fee (& msat , h -> base_fee , h -> proportional_fee ))
351404 plugin_err (rq -> plugin , "Adding fee to amount" );
@@ -472,9 +525,11 @@ static void add_to_flow(struct flow *flow,
472525 }
473526}
474527
475- /* We got an answer from min-cost-flow, but we now need to add fees.
476- * This can cause us to hit limits, and even find that some flows are
477- * impossible. Returns NULL on success, or an error message.*/
528+ /* We got an answer from min-cost-flow, but we now need to add fees,
529+ * and take into account the cost of individual HTLCs (for local
530+ * channels, at least). This can cause us to hit limits, and even
531+ * find that some flows are impossible. Returns NULL on success, or
532+ * an error message.*/
478533static const char *
479534refine_with_fees_and_limits (const tal_t * ctx ,
480535 struct route_query * rq ,
@@ -599,6 +654,7 @@ static const char *get_routes(const tal_t *ctx,
599654 const struct layer * local_layer ,
600655 struct route * * * routes ,
601656 struct amount_msat * * amounts ,
657+ const struct additional_cost_htable * additional_costs ,
602658 double * probability )
603659{
604660 struct askrene * askrene = get_askrene (plugin );
@@ -621,6 +677,7 @@ static const char *get_routes(const tal_t *ctx,
621677 rq -> reserved = askrene -> reserved ;
622678 rq -> layers = tal_arr (rq , const struct layer * , 0 );
623679 rq -> capacities = tal_dup_talarr (rq , fp16_t , askrene -> capacities );
680+ rq -> additional_costs = additional_costs ;
624681
625682 /* Layers don't have to exist: they might be empty! */
626683 for (size_t i = 0 ; i < tal_count (layers ); i ++ ) {
@@ -841,15 +898,18 @@ void get_constraints(const struct route_query *rq,
841898}
842899
843900struct getroutes_info {
901+ struct command * cmd ;
844902 struct node_id * source , * dest ;
845903 struct amount_msat * amount , * maxfee ;
846904 u32 * finalcltv ;
847905 const char * * layers ;
906+ struct additional_cost_htable * additional_costs ;
907+ /* Non-NULL if we are told to use "auto.localchans" */
908+ struct layer * local_layer ;
848909};
849910
850911static struct command_result * do_getroutes (struct command * cmd ,
851912 struct gossmap_localmods * localmods ,
852- const struct layer * local_layer ,
853913 const struct getroutes_info * info )
854914{
855915 const char * err ;
@@ -861,8 +921,8 @@ static struct command_result *do_getroutes(struct command *cmd,
861921 err = get_routes (cmd , cmd -> plugin ,
862922 info -> source , info -> dest ,
863923 * info -> amount , * info -> maxfee , * info -> finalcltv ,
864- info -> layers , localmods , local_layer ,
865- & routes , & amounts , & probability );
924+ info -> layers , localmods , info -> local_layer ,
925+ & routes , & amounts , info -> additional_costs , & probability );
866926 if (err )
867927 return command_fail (cmd , PAY_ROUTE_NOT_FOUND , "%s" , err );
868928
@@ -903,17 +963,60 @@ static void add_localchan(struct gossmap_localmods *mods,
903963 u32 fee_proportional ,
904964 u32 cltv_delta ,
905965 bool enabled ,
906- const char * buf UNUSED ,
907- const jsmntok_t * chantok UNUSED ,
908- struct layer * local_layer )
966+ const char * buf ,
967+ const jsmntok_t * chantok ,
968+ struct getroutes_info * info )
909969{
970+ u32 feerate ;
971+ const char * opener ;
972+ const char * err ;
973+
910974 gossmod_add_localchan (mods , self , peer , scidd , htlcmin , htlcmax ,
911975 spendable , fee_base , fee_proportional , cltv_delta , enabled ,
912- buf , chantok , local_layer );
976+ buf , chantok , info -> local_layer );
977+
978+ /* We also need to know the feerate and opener, so we can calculate per-HTLC cost */
979+ feerate = 0 ; /* Can be unset on unconfirmed channels */
980+ err = json_scan (tmpctx , buf , chantok ,
981+ "{feerate?:{perkw:%},opener:%}" ,
982+ JSON_SCAN (json_to_u32 , & feerate ),
983+ JSON_SCAN_TAL (tmpctx , json_strdup , & opener ));
984+ if (err ) {
985+ plugin_log (info -> cmd -> plugin , LOG_BROKEN ,
986+ "Cannot scan channel for feerate and owner (%s): %.*s" ,
987+ err , json_tok_full_len (chantok ), json_tok_full (buf , chantok ));
988+ return ;
989+ }
990+
991+ if (feerate != 0 && streq (opener , "local" )) {
992+ /* BOLT #3:
993+ * The base fee for a commitment transaction:
994+ * - MUST be calculated to match:
995+ * 1. Start with `weight` = 724 (1124 if `option_anchors` applies).
996+ * 2. For each committed HTLC, if that output is not trimmed as specified in
997+ * [Trimmed Outputs](#trimmed-outputs), add 172 to `weight`.
998+ * 3. Multiply `feerate_per_kw` by `weight`, divide by 1000 (rounding down).
999+ */
1000+ struct per_htlc_cost * phc
1001+ = tal (info -> additional_costs , struct per_htlc_cost );
1002+
1003+ phc -> scidd = * scidd ;
1004+ if (!amount_sat_to_msat (& phc -> per_htlc_cost ,
1005+ amount_tx_fee (feerate , 172 ))) {
1006+ /* Can't happen, since feerate is u32... */
1007+ abort ();
1008+ }
1009+
1010+ plugin_log (info -> cmd -> plugin , LOG_DBG , "Per-htlc cost for %s = %s (%u x 172)" ,
1011+ fmt_short_channel_id_dir (tmpctx , scidd ),
1012+ fmt_amount_msat (tmpctx , phc -> per_htlc_cost ),
1013+ feerate );
1014+ additional_cost_htable_add (info -> additional_costs , phc );
1015+ }
9131016
9141017 /* Known capacity on local channels (ts = max) */
915- layer_update_constraint (local_layer , scidd , CONSTRAINT_MIN , UINT64_MAX , spendable );
916- layer_update_constraint (local_layer , scidd , CONSTRAINT_MAX , UINT64_MAX , spendable );
1018+ layer_update_constraint (info -> local_layer , scidd , CONSTRAINT_MIN , UINT64_MAX , spendable );
1019+ layer_update_constraint (info -> local_layer , scidd , CONSTRAINT_MAX , UINT64_MAX , spendable );
9171020}
9181021
9191022static struct command_result *
@@ -922,17 +1025,17 @@ listpeerchannels_done(struct command *cmd,
9221025 const jsmntok_t * toks ,
9231026 struct getroutes_info * info )
9241027{
925- struct layer * local_layer = new_temp_layer (info , "auto.localchans" );
9261028 struct gossmap_localmods * localmods ;
9271029
1030+ info -> local_layer = new_temp_layer (info , "auto.localchans" );
9281031 localmods = gossmods_from_listpeerchannels (cmd ,
9291032 & get_askrene (cmd -> plugin )-> my_id ,
9301033 buffer , toks ,
9311034 false,
9321035 add_localchan ,
933- local_layer );
1036+ info );
9341037
935- return do_getroutes (cmd , localmods , local_layer , info );
1038+ return do_getroutes (cmd , localmods , info );
9361039}
9371040
9381041static struct command_result * json_getroutes (struct command * cmd ,
@@ -951,6 +1054,10 @@ static struct command_result *json_getroutes(struct command *cmd,
9511054 NULL ))
9521055 return command_param_failed ();
9531056
1057+ info -> cmd = cmd ;
1058+ info -> additional_costs = tal (info , struct additional_cost_htable );
1059+ additional_cost_htable_init (info -> additional_costs );
1060+
9541061 if (have_layer (info -> layers , "auto.localchans" )) {
9551062 struct out_req * req ;
9561063
@@ -959,9 +1066,10 @@ static struct command_result *json_getroutes(struct command *cmd,
9591066 listpeerchannels_done ,
9601067 forward_error , info );
9611068 return send_outreq (cmd -> plugin , req );
962- }
1069+ } else
1070+ info -> local_layer = NULL ;
9631071
964- return do_getroutes (cmd , gossmap_localmods_new (cmd ), NULL , info );
1072+ return do_getroutes (cmd , gossmap_localmods_new (cmd ), info );
9651073}
9661074
9671075static struct command_result * json_askrene_reserve (struct command * cmd ,
0 commit comments