6
6
#include <plugins/askrene/flow.h>
7
7
#include <plugins/askrene/refine.h>
8
8
#include <plugins/askrene/reserve.h>
9
+ #include <string.h>
9
10
10
11
/* Channel data for fast retrieval. */
11
12
struct channel_data {
@@ -35,8 +36,8 @@ static void destroy_reservations(struct reserve_hop *rhops, struct askrene *askr
35
36
reserve_remove (askrene -> reserved , & rhops [i ]);
36
37
}
37
38
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 )
40
41
{
41
42
struct reserve_hop * rhops = tal_arr (ctx , struct reserve_hop , 0 );
42
43
@@ -108,9 +109,9 @@ static void subtract_reservation(struct reserve_hop **reservations,
108
109
reserve_add (askrene -> reserved , prev , rq -> cmd -> id );
109
110
}
110
111
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 )
114
115
{
115
116
struct amount_msat msat ;
116
117
@@ -170,6 +171,32 @@ static void change_flow_delivers(const struct route_query *rq,
170
171
create_flow_reservations (rq , reservations , flow );
171
172
}
172
173
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
+
173
200
/* We use an fp16_t approximatin for htlc_max/min: this gets the exact value. */
174
201
static struct amount_msat get_chan_htlc_max (const struct route_query * rq ,
175
202
const struct gossmap_chan * c ,
@@ -846,6 +873,24 @@ static struct amount_msat remove_excess(struct flow **flows,
846
873
return all_deliver ;
847
874
}
848
875
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
+
849
894
/* FIXME: on failure return error message */
850
895
const char * refine_flows (const tal_t * ctx , struct route_query * rq ,
851
896
struct amount_msat deliver , struct flow * * * flows )
@@ -911,18 +956,7 @@ const char *refine_flows(const tal_t *ctx, struct route_query *rq,
911
956
}
912
957
913
958
/* 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 );
926
960
927
961
tal_free (working_ctx );
928
962
return NULL ;
@@ -931,3 +965,80 @@ const char *refine_flows(const tal_t *ctx, struct route_query *rq,
931
965
tal_free (working_ctx );
932
966
return error_message ;
933
967
}
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
+ struct channel_data * * channel_mpp_cache =
982
+ new_channel_mpp_cache (working_ctx , rq , * flows );
983
+ struct amount_msat * max_deliverable = tal_arrz (
984
+ working_ctx , struct amount_msat , tal_count (channel_mpp_cache ));
985
+
986
+ for (size_t i = 0 ; i < tal_count (flows_index ); i ++ ) {
987
+ struct flow * flow = (* flows )[i ];
988
+ struct short_channel_id_dir scidd ;
989
+ flows_index [i ] = i ;
990
+ paths_str [i ] = tal_strdup (working_ctx , "" );
991
+ max_deliverable [i ] = path_max_deliverable (channel_mpp_cache [i ]);
992
+
993
+ for (size_t j = 0 ; j < tal_count (flow -> path ); j ++ ) {
994
+ scidd .scid =
995
+ gossmap_chan_scid (rq -> gossmap , flow -> path [j ]);
996
+ scidd .dir = flow -> dirs [j ];
997
+ tal_append_fmt (
998
+ & paths_str [i ], "%s%s" , j > 0 ? "->" : "" ,
999
+ fmt_short_channel_id_dir (working_ctx , & scidd ));
1000
+ }
1001
+ }
1002
+
1003
+ asort (flows_index , tal_count (flows_index ), cmppath_flows , paths_str );
1004
+ for (size_t i = 0 ; i < tal_count (flows_index ); i ++ ) {
1005
+ const size_t j = i + 1 ;
1006
+ struct amount_msat combined ;
1007
+ struct amount_msat max = max_deliverable [flows_index [i ]];
1008
+
1009
+ /* same path? We merge */
1010
+ while (j < tal_count (flows_index ) &&
1011
+ cmppath_flows (& flows_index [i ],
1012
+ & flows_index [j ],
1013
+ paths_str ) == 0 ) {
1014
+ if (!amount_msat_add (
1015
+ & combined , (* flows )[flows_index [i ]]-> delivers ,
1016
+ (* flows )[flows_index [j ]]-> delivers ))
1017
+ abort ();
1018
+ /* do we break any HTLC max limits */
1019
+ if (amount_msat_greater (combined , max ))
1020
+ break ;
1021
+ (* flows )[flows_index [i ]]-> delivers = combined ;
1022
+ tal_arr_remove (& flows_index , j );
1023
+ }
1024
+ }
1025
+
1026
+ write_selected_flows (working_ctx , flows_index , flows );
1027
+
1028
+ tal_free (working_ctx );
1029
+ }
1030
+
1031
+ double flows_probability (const tal_t * ctx , struct route_query * rq ,
1032
+ struct flow * * * flows )
1033
+ {
1034
+ const tal_t * working_ctx = tal (ctx , tal_t );
1035
+ struct reserve_hop * reservations = new_reservations (working_ctx , rq );
1036
+ double probability = 1.0 ;
1037
+
1038
+ for (size_t i = 0 ; i < tal_count (* flows ); i ++ ) {
1039
+ probability *= flow_probability ((* flows )[i ], rq );
1040
+ create_flow_reservations (rq , & reservations , (* flows )[i ]);
1041
+ }
1042
+ tal_free (working_ctx );
1043
+ return probability ;
1044
+ }
0 commit comments