66#include <plugins/askrene/flow.h>
77#include <plugins/askrene/refine.h>
88#include <plugins/askrene/reserve.h>
9+ #include <string.h>
910
1011/* Channel data for fast retrieval. */
1112struct channel_data {
@@ -35,8 +36,8 @@ static void destroy_reservations(struct reserve_hop *rhops, struct askrene *askr
3536 reserve_remove (askrene -> reserved , & rhops [i ]);
3637}
3738
38- static struct reserve_hop * new_reservations (const tal_t * ctx ,
39- const struct route_query * rq )
39+ struct reserve_hop * new_reservations (const tal_t * ctx ,
40+ const struct route_query * rq )
4041{
4142 struct reserve_hop * rhops = tal_arr (ctx , struct reserve_hop , 0 );
4243
@@ -108,9 +109,9 @@ static void subtract_reservation(struct reserve_hop **reservations,
108109 reserve_add (askrene -> reserved , prev , rq -> cmd -> id );
109110}
110111
111- static void create_flow_reservations (const struct route_query * rq ,
112- struct reserve_hop * * reservations ,
113- const struct flow * flow )
112+ void create_flow_reservations (const struct route_query * rq ,
113+ struct reserve_hop * * reservations ,
114+ const struct flow * flow )
114115{
115116 struct amount_msat msat ;
116117
@@ -170,6 +171,32 @@ static void change_flow_delivers(const struct route_query *rq,
170171 create_flow_reservations (rq , reservations , flow );
171172}
172173
174+ bool create_flow_reservations_verify (const struct route_query * rq ,
175+ struct reserve_hop * * reservations ,
176+ const struct flow * flow )
177+ {
178+ struct amount_msat msat ;
179+ msat = flow -> delivers ;
180+ for (int i = tal_count (flow -> path ) - 1 ; i >= 0 ; i -- ) {
181+ struct amount_msat known_min , known_max ;
182+ const struct half_chan * h = flow_edge (flow , i );
183+ struct amount_msat amount_to_reserve = msat ;
184+ struct short_channel_id_dir scidd ;
185+
186+ get_scidd (rq -> gossmap , flow , i , & scidd );
187+ get_constraints (rq , flow -> path [i ], flow -> dirs [i ], & known_min ,
188+ & known_max );
189+ if (amount_msat_greater (amount_to_reserve , known_max ))
190+ return false;
191+
192+ if (!amount_msat_add_fee (& msat , h -> base_fee ,
193+ h -> proportional_fee ))
194+ abort ();
195+ }
196+ create_flow_reservations (rq , reservations , flow );
197+ return true;
198+ }
199+
173200/* We use an fp16_t approximatin for htlc_max/min: this gets the exact value. */
174201static struct amount_msat get_chan_htlc_max (const struct route_query * rq ,
175202 const struct gossmap_chan * c ,
@@ -846,6 +873,24 @@ static struct amount_msat remove_excess(struct flow **flows,
846873 return all_deliver ;
847874}
848875
876+ static void write_selected_flows (const tal_t * ctx , size_t * flows_index ,
877+ struct flow * * * flows )
878+ {
879+ struct flow * * tmp_flows = tal_arr (ctx , struct flow * , 0 );
880+ for (size_t i = 0 ; i < tal_count (flows_index ); i ++ ) {
881+ tal_arr_expand (& tmp_flows , (* flows )[flows_index [i ]]);
882+ (* flows )[flows_index [i ]] = NULL ;
883+ }
884+ for (size_t i = 0 ; i < tal_count (* flows ); i ++ ) {
885+ (* flows )[i ] = tal_free ((* flows )[i ]);
886+ }
887+ tal_resize (flows , 0 );
888+ for (size_t i = 0 ; i < tal_count (tmp_flows ); i ++ ) {
889+ tal_arr_expand (flows , tmp_flows [i ]);
890+ }
891+ tal_free (tmp_flows );
892+ }
893+
849894/* FIXME: on failure return error message */
850895const char * refine_flows (const tal_t * ctx , struct route_query * rq ,
851896 struct amount_msat deliver , struct flow * * * flows )
@@ -911,18 +956,7 @@ const char *refine_flows(const tal_t *ctx, struct route_query *rq,
911956 }
912957
913958 /* finally write the remaining flows */
914- struct flow * * tmp_flows = tal_arr (working_ctx , struct flow * , 0 );
915- for (size_t i = 0 ; i < tal_count (flows_index ); i ++ ) {
916- tal_arr_expand (& tmp_flows , (* flows )[flows_index [i ]]);
917- (* flows )[flows_index [i ]] = NULL ;
918- }
919- for (size_t i = 0 ; i < tal_count (* flows ); i ++ ) {
920- (* flows )[i ] = tal_free ((* flows )[i ]);
921- }
922- tal_resize (flows , 0 );
923- for (size_t i = 0 ; i < tal_count (tmp_flows ); i ++ ) {
924- tal_arr_expand (flows , tmp_flows [i ]);
925- }
959+ write_selected_flows (working_ctx , flows_index , flows );
926960
927961 tal_free (working_ctx );
928962 return NULL ;
@@ -931,3 +965,68 @@ const char *refine_flows(const tal_t *ctx, struct route_query *rq,
931965 tal_free (working_ctx );
932966 return error_message ;
933967}
968+
969+ /* Order of flows according to path string */
970+ static int cmppath_flows (const size_t * a , const size_t * b , char * * paths_str )
971+ {
972+ return strcmp (paths_str [* a ], paths_str [* b ]);
973+ }
974+
975+ void squash_flows (const tal_t * ctx , struct route_query * rq ,
976+ struct flow * * * flows )
977+ {
978+ const tal_t * working_ctx = tal (ctx , tal_t );
979+ size_t * flows_index = tal_arrz (working_ctx , size_t , tal_count (* flows ));
980+ char * * paths_str = tal_arrz (working_ctx , char * , tal_count (* flows ));
981+
982+ for (size_t i = 0 ; i < tal_count (flows_index ); i ++ ) {
983+ struct flow * flow = (* flows )[i ];
984+ struct short_channel_id_dir scidd ;
985+ flows_index [i ] = i ;
986+ paths_str [i ] = tal_strdup (working_ctx , "" );
987+
988+ for (size_t j = 0 ; j < tal_count (flow -> path ); j ++ ) {
989+ scidd .scid =
990+ gossmap_chan_scid (rq -> gossmap , flow -> path [j ]);
991+ scidd .dir = flow -> dirs [j ];
992+ tal_append_fmt (
993+ & paths_str [i ], "%s%s" , j > 0 ? "->" : "" ,
994+ fmt_short_channel_id_dir (working_ctx , & scidd ));
995+ }
996+ }
997+
998+ asort (flows_index , tal_count (flows_index ), cmppath_flows , paths_str );
999+ for (size_t i = 0 ; i < tal_count (flows_index ); i ++ ) {
1000+ const size_t j = i + 1 ;
1001+ /* same path? We merge */
1002+ while (j < tal_count (flows_index ) &&
1003+ cmppath_flows (& flows_index [i ],
1004+ & flows_index [j ],
1005+ paths_str ) == 0 ) {
1006+ if (!amount_msat_accumulate (
1007+ & (* flows )[flows_index [i ]]-> delivers ,
1008+ (* flows )[flows_index [j ]]-> delivers ))
1009+ abort ();
1010+ tal_arr_remove (& flows_index , j );
1011+ }
1012+ }
1013+
1014+ write_selected_flows (working_ctx , flows_index , flows );
1015+
1016+ tal_free (working_ctx );
1017+ }
1018+
1019+ double flows_probability (const tal_t * ctx , struct route_query * rq ,
1020+ struct flow * * * flows )
1021+ {
1022+ const tal_t * working_ctx = tal (ctx , tal_t );
1023+ struct reserve_hop * reservations = new_reservations (working_ctx , rq );
1024+ double probability = 1.0 ;
1025+
1026+ for (size_t i = 0 ; i < tal_count (* flows ); i ++ ) {
1027+ probability *= flow_probability ((* flows )[i ], rq );
1028+ create_flow_reservations (rq , & reservations , (* flows )[i ]);
1029+ }
1030+ tal_free (working_ctx );
1031+ return probability ;
1032+ }
0 commit comments