Skip to content

Commit b826c5b

Browse files
committed
askrene: refine: remove flows with HTLC min faults
Changelog-None Signed-off-by: Lagrang3 <[email protected]>
1 parent 54dea92 commit b826c5b

File tree

1 file changed

+63
-0
lines changed

1 file changed

+63
-0
lines changed

plugins/askrene/refine.c

Lines changed: 63 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -688,6 +688,53 @@ static struct amount_msat path_max_deliverable(struct channel_data *path)
688688
return deliver;
689689
}
690690

691+
// TODO: unit test:
692+
// -> make a path
693+
// -> compute x = path_min_deliverable
694+
// -> check that htlc_min are all satisfied
695+
// -> check that (x-1) at least one htlc_min is violated
696+
/* The least amount that we can deliver at the destination such that when one
697+
* computes the hop amounts backwards the htlc_min are always met. */
698+
static struct amount_msat path_min_deliverable(struct channel_data *path)
699+
{
700+
struct amount_msat least_send = AMOUNT_MSAT(1);
701+
const size_t pathlen = tal_count(path);
702+
for (size_t i = pathlen - 1; i < pathlen; i--) {
703+
least_send = amount_msat_max(least_send, path[i].htlc_min);
704+
if (!amount_msat_add_fee(&least_send, path[i].fee_base_msat,
705+
path[i].fee_proportional_millionths))
706+
abort();
707+
}
708+
/* least_send: is the least amount we can send in order to deliver at
709+
* least 1 msat at the destination. */
710+
struct amount_msat least_destination = least_send;
711+
for (size_t i = 0; i < pathlen; i++) {
712+
struct amount_msat in_value = least_destination;
713+
struct amount_msat out_value =
714+
amount_msat_sub_fee(in_value, path[i].fee_base_msat,
715+
path[i].fee_proportional_millionths);
716+
assert(amount_msat_greater_eq(out_value, path[i].htlc_min));
717+
struct amount_msat x = out_value;
718+
if (!amount_msat_add_fee(&x, path[i].fee_base_msat,
719+
path[i].fee_proportional_millionths))
720+
abort();
721+
/* if the in_value computed from the out_value is smaller than
722+
* it should, then we add 1msat */
723+
if (amount_msat_less(x, in_value) &&
724+
!amount_msat_accumulate(&out_value, AMOUNT_MSAT(1)))
725+
abort();
726+
/* check conditions */
727+
assert(amount_msat_greater_eq(out_value, path[i].htlc_min));
728+
x = out_value;
729+
assert(
730+
amount_msat_add_fee(&x, path[i].fee_base_msat,
731+
path[i].fee_proportional_millionths) &&
732+
amount_msat_greater_eq(x, in_value));
733+
least_destination = out_value;
734+
}
735+
return least_destination;
736+
}
737+
691738
static struct amount_msat sum_all_deliver(struct flow **flows,
692739
size_t *flows_index)
693740
{
@@ -773,6 +820,7 @@ const char *refine_flows(const tal_t *ctx, struct route_query *rq,
773820
{
774821
const tal_t *working_ctx = tal(ctx, tal_t);
775822
struct amount_msat *max_deliverable;
823+
struct amount_msat *min_deliverable;
776824
struct channel_data **channel_mpp_cache;
777825
size_t *flows_index;
778826

@@ -781,11 +829,14 @@ const char *refine_flows(const tal_t *ctx, struct route_query *rq,
781829
channel_mpp_cache = new_channel_mpp_cache(working_ctx, rq, *flows);
782830
max_deliverable = tal_arrz(working_ctx, struct amount_msat,
783831
tal_count(channel_mpp_cache));
832+
min_deliverable = tal_arrz(working_ctx, struct amount_msat,
833+
tal_count(channel_mpp_cache));
784834
flows_index = tal_arrz(working_ctx, size_t, tal_count(*flows));
785835
for (size_t i = 0; i < tal_count(channel_mpp_cache); i++) {
786836
// FIXME: does path_max_deliverable work for a single
787837
// channel with 0 fees?
788838
max_deliverable[i] = path_max_deliverable(channel_mpp_cache[i]);
839+
min_deliverable[i] = path_min_deliverable(channel_mpp_cache[i]);
789840
/* We use an array of indexes to keep track of the order
790841
* of the flows. Likewise flows can be removed by simply
791842
* shrinking the flows_index array. */
@@ -802,6 +853,18 @@ const char *refine_flows(const tal_t *ctx, struct route_query *rq,
802853
/* remove excess from MCF granularity if any */
803854
remove_excess(*flows, &flows_index, deliver);
804855

856+
/* detect htlc_min violations */
857+
for (size_t i = 0; i < tal_count(flows_index);) {
858+
size_t k = flows_index[i];
859+
if (amount_msat_greater_eq((*flows)[k]->delivers,
860+
min_deliverable[k])) {
861+
i++;
862+
continue;
863+
}
864+
/* htlc_min is not met for this flow */
865+
tal_arr_remove(&flows_index, i);
866+
}
867+
805868
/* remove 0 amount flows if any */
806869
asort(flows_index, tal_count(flows_index), revcmp_flows, *flows);
807870
for (int i = tal_count(flows_index) - 1; i >= 0; i--) {

0 commit comments

Comments
 (0)