Skip to content

Commit 682bd9d

Browse files
committed
askrene: refine: expose some of the refine API
that can be useful for us in the mcf.c main loop. Changelog-None Signed-off-by: Lagrang3 <[email protected]>
1 parent f749cdb commit 682bd9d

File tree

2 files changed

+138
-17
lines changed

2 files changed

+138
-17
lines changed

plugins/askrene/refine.c

Lines changed: 116 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
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. */
1112
struct 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. */
174201
static 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 */
850895
const 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+
}

plugins/askrene/refine.h

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,13 @@ struct route_query;
77
struct amount_msat;
88
struct flow;
99

10+
struct reserve_hop *new_reservations(const tal_t *ctx,
11+
const struct route_query *rq);
12+
13+
void create_flow_reservations(const struct route_query *rq,
14+
struct reserve_hop **reservations,
15+
const struct flow *flow);
16+
1017
/* We got an answer from min-cost-flow, but we now need to:
1118
* 1. Add fixup exact delivery amounts since MCF deals in larger granularity than msat.
1219
* 2. Add fees which accumulate through the route.
@@ -24,8 +31,23 @@ refine_with_fees_and_limits(const tal_t *ctx,
2431
struct flow ***flows,
2532
double *flowset_probability);
2633

34+
/* create flow reservations, but first verify that the flow indeeds fits in the
35+
* liquidity constraints. Takes into account reservations that include per HTLC
36+
* extra amounts to pay for onchain fees. */
37+
bool create_flow_reservations_verify(const struct route_query *rq,
38+
struct reserve_hop **reservations,
39+
const struct flow *flow);
40+
2741
/* Modify flows to meet HTLC min/max requirements.
2842
* It takes into account the exact value of the fees expected at each hop. */
2943
const char *refine_flows(const tal_t *ctx, struct route_query *rq,
3044
struct amount_msat deliver, struct flow ***flows);
45+
46+
/* Duplicated flows are merged into one. This saves in base fee and HTLC fees.
47+
*/
48+
void squash_flows(const tal_t *ctx, struct route_query *rq,
49+
struct flow ***flows);
50+
51+
double flows_probability(const tal_t *ctx, struct route_query *rq,
52+
struct flow ***flows);
3153
#endif /* LIGHTNING_PLUGINS_ASKRENE_REFINE_H */

0 commit comments

Comments
 (0)