mirror of
https://github.com/ElementsProject/lightning.git
synced 2025-02-22 14:42:40 +01:00
askrene: fix base fee.
I noticed this in the logs: plugin-cln-askrene: notify msg unusual: The flows had a fee of 151950msat, greater than max of 53697msat, retrying with mu of 10%... plugin-cln-askrene: notify msg unusual: The flows had a fee of 220126msat, greater than max of 53697msat, retrying with mu of 20%... We would expect increasing mu to *reduce* the fee! Turns out that our linear fee is a bad terrible approximation, because I was using base_fee_penalty of 10.0. | | / __ <- real fee, with base: fee = base + propfee * amount. | / __/ | _// | __/ | __/_/ |/ _/ | _/ <- linearized fee: fee = linear * amount |/ +----------------------------------- These cross over where linear = propfee + base / amount. Assume we split the payment into 10 parts, this implies that the base_fee_penalty should be 10 / amount (this gives a slight penalty to the normal case, but that's ok). This gives better results, too: we get down to 650099 sats in fees, vs 801613 before. Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
This commit is contained in:
parent
6273adbe47
commit
08df93cb25
4 changed files with 15 additions and 16 deletions
|
@ -284,7 +284,6 @@ static const char *get_routes(const tal_t *ctx,
|
|||
struct flow **flows;
|
||||
const struct gossmap_node *srcnode, *dstnode;
|
||||
double delay_feefactor;
|
||||
double base_fee_penalty;
|
||||
u32 mu;
|
||||
const char *ret;
|
||||
|
||||
|
@ -349,12 +348,11 @@ static const char *get_routes(const tal_t *ctx,
|
|||
}
|
||||
|
||||
delay_feefactor = 1.0/1000000;
|
||||
base_fee_penalty = 10.0;
|
||||
|
||||
/* First up, don't care about fees. */
|
||||
mu = 0;
|
||||
flows = minflow(rq, rq, srcnode, dstnode, amount,
|
||||
mu, delay_feefactor, base_fee_penalty);
|
||||
mu, delay_feefactor);
|
||||
if (!flows) {
|
||||
ret = explain_failure(ctx, rq, srcnode, dstnode, amount);
|
||||
goto fail;
|
||||
|
@ -374,7 +372,7 @@ static const char *get_routes(const tal_t *ctx,
|
|||
"The worst flow delay is %"PRIu64" (> %i), retrying with delay_feefactor %f...",
|
||||
flows_worst_delay(flows), 2016 - finalcltv, delay_feefactor);
|
||||
flows = minflow(rq, rq, srcnode, dstnode, amount,
|
||||
mu, delay_feefactor, base_fee_penalty);
|
||||
mu, delay_feefactor);
|
||||
if (!flows || delay_feefactor > 10) {
|
||||
ret = rq_log(ctx, rq, LOG_UNUSUAL,
|
||||
"Could not find route without excessive delays");
|
||||
|
@ -392,7 +390,7 @@ too_expensive:
|
|||
fmt_amount_msat(tmpctx, maxfee),
|
||||
mu);
|
||||
flows = minflow(rq, rq, srcnode, dstnode, amount,
|
||||
mu > 100 ? 100 : mu, delay_feefactor, base_fee_penalty);
|
||||
mu > 100 ? 100 : mu, delay_feefactor);
|
||||
if (!flows || mu >= 100) {
|
||||
ret = rq_log(ctx, rq, LOG_UNUSUAL,
|
||||
"Could not find route without excessive cost");
|
||||
|
|
|
@ -541,6 +541,14 @@ static s64 linear_fee_cost(u32 base_fee, u32 proportional_fee, u16 cltv_delta,
|
|||
return pfee + bfee* base_fee_penalty+ delay*delay_feefactor;
|
||||
}
|
||||
|
||||
/* This is inversely proportional to the amount we expect to send. Let's
|
||||
* assume we will send ~10th of the total amount per path. But note
|
||||
* that it converts to parts per million! */
|
||||
static double base_fee_penalty_estimate(struct amount_msat amount)
|
||||
{
|
||||
return amount_msat_ratio(AMOUNT_MSAT(10000000), amount);
|
||||
}
|
||||
|
||||
static struct linear_network *
|
||||
init_linear_network(const tal_t *ctx, const struct pay_parameters *params)
|
||||
{
|
||||
|
@ -1249,7 +1257,7 @@ struct flow **minflow(const tal_t *ctx,
|
|||
const struct gossmap_node *target,
|
||||
struct amount_msat amount,
|
||||
u32 mu,
|
||||
double delay_feefactor, double base_fee_penalty)
|
||||
double delay_feefactor)
|
||||
{
|
||||
struct flow **flow_paths;
|
||||
/* We allocate everything off this, and free it at the end,
|
||||
|
@ -1278,7 +1286,7 @@ struct flow **minflow(const tal_t *ctx,
|
|||
}
|
||||
|
||||
params->delay_feefactor = delay_feefactor;
|
||||
params->base_fee_penalty = base_fee_penalty;
|
||||
params->base_fee_penalty = base_fee_penalty_estimate(amount);
|
||||
params->k_factor = 8.0;
|
||||
|
||||
// build the uncertainty network with linearization and residual arcs
|
||||
|
|
|
@ -21,12 +21,6 @@ struct route_query;
|
|||
* fee. So if a CLTV delay on a node is 5 blocks, that's treated as if it
|
||||
* were a fee of 5 * @delay_feefactor.
|
||||
*
|
||||
* @base_fee_penalty: factor to compute additional proportional cost from each
|
||||
* unit of base fee. So #base_fee_penalty will be added to the effective
|
||||
* proportional fee for each msat of base fee.
|
||||
*
|
||||
* effective_ppm = proportional_fee + base_fee_msat * base_fee_penalty
|
||||
*
|
||||
* Return a series of subflows which deliver amount to target, or NULL.
|
||||
*/
|
||||
struct flow **minflow(const tal_t *ctx,
|
||||
|
@ -35,6 +29,5 @@ struct flow **minflow(const tal_t *ctx,
|
|||
const struct gossmap_node *target,
|
||||
struct amount_msat amount,
|
||||
u32 mu,
|
||||
double delay_feefactor,
|
||||
double base_fee_penalty);
|
||||
double delay_feefactor);
|
||||
#endif /* LIGHTNING_PLUGINS_ASKRENE_MCF_H */
|
||||
|
|
|
@ -992,4 +992,4 @@ def test_real_data(node_factory, bitcoind):
|
|||
if len(fees[n]) > len(fees[best]):
|
||||
best = n
|
||||
|
||||
assert (len(fees[best]), len(improved), total_first_fee, total_final_fee, percent_fee_reduction) == (10, 96, 19969585, 801613, 96)
|
||||
assert (len(fees[best]), len(improved), total_first_fee, total_final_fee, percent_fee_reduction) == (9, 96, 19961361, 650099, 97)
|
||||
|
|
Loading…
Add table
Reference in a new issue