askrene: don't have get_flow_paths() handle htlc_max, htlc_min and extra millisats.

We don't actually hit the htlc_max cases, since the flow code already
constrains us to that.

And handling htlc_min is better done in the caller, where diagnostics
are better (basically, we should eliminate them, and if that means no
route, give a clear error message).

And the refinement step can handle any extra millisats from rounding.

Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
This commit is contained in:
Rusty Russell 2024-09-18 17:16:27 +09:30
parent f0331cd82e
commit db29a2d6b5
2 changed files with 10 additions and 76 deletions

View file

@ -297,6 +297,11 @@ static void add_reservation(struct reservations *r,
* push us again over capacity or htlc_maximum_msat.
*
* We may have to reduce the flow amount in response to these.
*
* We also check for going below htlc_maximum_msat at this point: this
* is unusual and means it's small, so we just remove that flow if
* this happens, as we can make it up by buffing up the other flows
* (or, it's simply impossible).
*/
static const char *constrain_flow(const tal_t *ctx,
struct route_query *rq,

View file

@ -194,7 +194,6 @@
static const double CHANNEL_PIVOTS[]={0,0.5,0.8,0.95};
static const s64 INFINITE = INT64_MAX;
static const u64 INFINITE_MSAT = UINT64_MAX;
static const u32 INVALID_INDEX = 0xffffffff;
static const s64 MU_MAX = 101;
@ -1102,16 +1101,10 @@ static struct flow **
get_flow_paths(const tal_t *ctx,
const struct route_query *rq,
const struct linear_network *linear_network,
const struct residual_network *residual_network,
// how many msats in excess we paid for not having msat accuracy
// in the MCF solver
struct amount_msat excess)
const struct residual_network *residual_network)
{
struct flow **flows = tal_arr(ctx,struct flow*,0);
assert(amount_msat_less(excess, AMOUNT_MSAT(1000)));
const size_t max_num_chans = gossmap_max_chan_idx(rq->gossmap);
struct chan_flow *chan_flow = tal_arrz(tmpctx,struct chan_flow,max_num_chans);
@ -1167,13 +1160,6 @@ get_flow_paths(const tal_t *ctx,
rq->gossmap, chan_flow, node_idx, balance,
prev_chan, prev_dir, prev_idx);
/* For each route we will compute the highest htlc_min
* and the smallest htlc_max and use those to constraint
* the flow we will allocate. */
struct amount_msat sup_htlc_min = AMOUNT_MSAT_INIT(0),
inf_htlc_max =
AMOUNT_MSAT_INIT(INFINITE_MSAT);
s64 delta=-balance[node_idx];
int length = 0;
delta = MIN(delta,balance[final_idx]);
@ -1192,44 +1178,9 @@ get_flow_paths(const tal_t *ctx,
delta=MIN(delta,chan_flow[c_idx].half[dir]);
length++;
/* obtain the supremum htlc_min along the route
*/
sup_htlc_min = amount_msat_max(
sup_htlc_min, gossmap_chan_htlc_min(c, dir));
/* obtain the infimum htlc_max along the route
*/
inf_htlc_max = amount_msat_min(
inf_htlc_max, gossmap_chan_htlc_max(c, dir));
}
s64 htlc_max=inf_htlc_max.millisatoshis/1000;/* Raw: need htlc_max in sats to do arithmetic operations.*/
s64 htlc_min=(sup_htlc_min.millisatoshis+999)/1000;/* Raw: need htlc_min in sats to do arithmetic operations.*/
if (htlc_min > htlc_max) {
/* htlc_min is too big or htlc_max is too small,
* we cannot send `delta` along this route.
*
* FIXME: We try anyways because failing
* channels will be blacklisted downstream. */
htlc_min = 0;
}
/* If we divide this route into different flows make it
* random to avoid routing nodes making correlations. */
if (delta > htlc_max) {
// FIXME: choosing a number in the range
// [htlc_min, htlc_max] or
// [0.5 htlc_max, htlc_max]
// The choice of the fraction was completely
// arbitrary.
delta = pseudorand_interval(
MAX(htlc_min, (htlc_max * 50) / 100),
htlc_max);
}
struct flow *fp = tal(tmpctx,struct flow);
struct flow *fp = tal(flows,struct flow);
fp->path = tal_arr(fp,const struct gossmap_chan *,length);
fp->dirs = tal_arr(fp,int,length);
@ -1257,29 +1208,12 @@ get_flow_paths(const tal_t *ctx,
}
assert(delta>0);
// substract the excess of msats for not having msat
// accuracy
struct amount_msat delivered = amount_msat(delta*1000);
if (!amount_msat_sub(&delivered, delivered, excess)) {
plugin_err(rq->plugin, "Unable to subtract excess %s from %s",
fmt_amount_msat(tmpctx, excess),
fmt_amount_msat(tmpctx, delivered));
}
excess = amount_msat(0);
fp->delivers = delivered;
fp->delivers = amount_msat(delta*1000);
// add fp to flows
tal_arr_expand(&flows, fp);
}
}
/* Establish ownership. */
for(size_t i=0;i<tal_count(flows);++i)
{
flows[i] = tal_steal(flows,flows[i]);
assert(flows[i]);
}
return flows;
}
@ -1358,11 +1292,7 @@ struct flow **minflow(const tal_t *ctx,
* For example if we are trying to pay 1M sats our precision could be
* set to 1000sat, then channels that had capacity for 3M sats become 3k
* flow units. */
const u64 pay_amount_msats = params->amount.millisatoshis % 1000; /* Raw: minflow */
const u64 pay_amount_sats = params->amount.millisatoshis/1000 /* Raw: minflow */
+ (pay_amount_msats ? 1 : 0);
const struct amount_msat excess
= amount_msat(pay_amount_msats ? 1000 - pay_amount_msats : 0);
const u64 pay_amount_sats = (params->amount.millisatoshis + 999)/1000; /* Raw: minflow */
if (!find_feasible_flow(linear_network, residual_network,
source_idx, target_idx, pay_amount_sats)) {
@ -1381,7 +1311,6 @@ struct flow **minflow(const tal_t *ctx,
* Actual amounts considering fees are computed for every
* channel in the routes. */
flow_paths = get_flow_paths(tmpctx, rq,
linear_network, residual_network, excess);
linear_network, residual_network);
return flow_paths;
}