mirror of
https://github.com/ElementsProject/lightning.git
synced 2025-02-22 14:42:40 +01:00
pay: ignore fees on our own channels when determining routing.
I noticed that run-route-infloop chose some worse-looking paths after routing was fixed, eg the second node: Before: Destination node, success, probability, hops, fees, cltv, scid... 02b3aa1e4ed31be83cca4bd367b2c01e39502cb25e282a9b4520ad376a1ba0a01a,1,0.991856,2,1004,40,2572260x39x0/1,2131897x45x0/0 After: Destination node, success, probability, hops, fees, cltv, scid... 02b3aa1e4ed31be83cca4bd367b2c01e39502cb25e282a9b4520ad376a1ba0a01a,1,0.954540,3,1046,46,2570715x21x0/1,2346882x26x14/1,2131897x45x0/0 This is because although the final costs don't reflect it, routing was taking into account local channels, and 2572260x39x0/1 has a base fee of 2970. There's an easy fix: when we the pay plugin creates localmods for our gossip graph, add all local channels with delay and fees equal to 0. We do the same thing in our unit test. This improves things across the board: Linear success probability (when found): min-max(mean +/- stddev) Before: 0.487040-0.999543(0.952548+/-0.075) After: 0.486985-0.999750(0.975978+/-0.053) Hops: Before: 1-5(2.98374+/-0.77) After: 1-5(2.09593+/-0.63) Fees: Before: 0-50848(922.457+/-2.7e+03) After: 0-50041(861.621+/-2.7e+03) Delay (blocks): Before: 0-196(65.8081+/-60) After: 0-190(60.3285+/-60) Signed-off-by: Rusty Russell <rusty@rustcorp.com.au> Changelog-Changed: Plugins: `pay` route algorithm doesn't bias against our own "expensive" channels any more.
This commit is contained in:
parent
ffb324f283
commit
e50539d852
8 changed files with 41 additions and 9 deletions
|
@ -35,6 +35,7 @@ gossmods_from_listpeerchannels_(const tal_t *ctx,
|
|||
const struct node_id *self,
|
||||
const char *buf,
|
||||
const jsmntok_t *toks,
|
||||
bool zero_rates,
|
||||
void (*cb)(struct gossmap_localmods *mods,
|
||||
const struct node_id *self,
|
||||
const struct node_id *peer,
|
||||
|
@ -133,6 +134,16 @@ gossmods_from_listpeerchannels_(const tal_t *ctx,
|
|||
if (amount_msat_less(spendable, htlc_max[LOCAL]))
|
||||
htlc_max[LOCAL] = spendable;
|
||||
|
||||
/* We route better if we know we won't charge
|
||||
* ourselves fees (though if fees are a signal on what
|
||||
* channel we prefer to use, this ignores that
|
||||
* signal!) */
|
||||
if (zero_rates) {
|
||||
fee_base[LOCAL] = AMOUNT_MSAT(0);
|
||||
fee_proportional[LOCAL] = 0;
|
||||
cltv_delta[LOCAL] = 0;
|
||||
}
|
||||
|
||||
/* We add both directions */
|
||||
cb(mods, self, &dst, &scidd, htlc_min[LOCAL], htlc_max[LOCAL],
|
||||
fee_base[LOCAL], fee_proportional[LOCAL], cltv_delta[LOCAL],
|
||||
|
|
|
@ -13,6 +13,7 @@ struct node_id;
|
|||
* @ctx: context to allocate return from
|
||||
* @buf: the JSON buffer from listpeerchannels
|
||||
* @toks: the JSON tokens
|
||||
* @zero_rates: set fees and cltv delay for these channels to 0 (better for routing)
|
||||
* @cb: optional per-channel callback.
|
||||
* @cbarg: arg for @cb.
|
||||
*
|
||||
|
@ -24,6 +25,7 @@ struct gossmap_localmods *gossmods_from_listpeerchannels_(const tal_t *ctx,
|
|||
const struct node_id *self,
|
||||
const char *buf,
|
||||
const jsmntok_t *toks,
|
||||
bool zero_rates,
|
||||
void (*cb)(struct gossmap_localmods *mods,
|
||||
const struct node_id *self_,
|
||||
const struct node_id *peer,
|
||||
|
@ -39,8 +41,8 @@ struct gossmap_localmods *gossmods_from_listpeerchannels_(const tal_t *ctx,
|
|||
void *cbarg_),
|
||||
void *cbarg);
|
||||
|
||||
#define gossmods_from_listpeerchannels(ctx, self, buf, toks, cb, cbarg) \
|
||||
gossmods_from_listpeerchannels_((ctx), (self), (buf), (toks), \
|
||||
#define gossmods_from_listpeerchannels(ctx, self, buf, toks, zero_rates, cb, cbarg) \
|
||||
gossmods_from_listpeerchannels_((ctx), (self), (buf), (toks), (zero_rates), \
|
||||
typesafe_cb_preargs(void, void *, (cb), (cbarg), \
|
||||
struct gossmap_localmods *, \
|
||||
const struct node_id *, \
|
||||
|
|
|
@ -131,6 +131,23 @@ int main(int argc, char *argv[])
|
|||
me = gossmap_find_node(gossmap, &my_id);
|
||||
assert(me);
|
||||
|
||||
/* We overlay our own channels as zero fee & delay, since we don't pay fees */
|
||||
struct gossmap_localmods *localmods = gossmap_localmods_new(gossmap);
|
||||
for (size_t i = 0; i < me->num_chans; i++) {
|
||||
int dir;
|
||||
struct short_channel_id scid;
|
||||
struct gossmap_chan *c = gossmap_nth_chan(gossmap, me, i, &dir);
|
||||
|
||||
if (!c->half[dir].enabled)
|
||||
continue;
|
||||
scid = gossmap_chan_scid(gossmap, c);
|
||||
assert(gossmap_local_updatechan(localmods, &scid,
|
||||
amount_msat(fp16_to_u64(c->half[dir].htlc_min)),
|
||||
amount_msat(fp16_to_u64(c->half[dir].htlc_max)),
|
||||
0, 0, 0, true, dir));
|
||||
}
|
||||
gossmap_apply_localmods(gossmap, localmods);
|
||||
|
||||
printf("Destination node, success, probability, hops, fees, cltv, scid...\n");
|
||||
for (size_t i = 0; i < tal_count(nodes); i++) {
|
||||
const struct dijkstra *dij;
|
||||
|
|
|
@ -469,7 +469,8 @@ static struct pubkey *path_to_node(const tal_t *ctx,
|
|||
node_id_from_pubkey(&local_nodeid, &local_id);
|
||||
node_id_from_pubkey(&dstid, node_id);
|
||||
|
||||
mods = gossmods_from_listpeerchannels(tmpctx, &local_nodeid, buf, listpeerchannels,
|
||||
mods = gossmods_from_listpeerchannels(tmpctx, &local_nodeid,
|
||||
buf, listpeerchannels, false,
|
||||
gossmod_add_localchan, NULL);
|
||||
|
||||
gossmap = get_gossmap(plugin);
|
||||
|
|
|
@ -963,7 +963,7 @@ payment_listpeerchannels_success(struct command *cmd,
|
|||
struct payment *p)
|
||||
{
|
||||
p->mods = gossmods_from_listpeerchannels(p, p->local_id,
|
||||
buffer, toks,
|
||||
buffer, toks, true,
|
||||
gossmod_add_localchan,
|
||||
NULL);
|
||||
return payment_getroute(p);
|
||||
|
@ -3389,7 +3389,7 @@ static struct command_result *direct_pay_listpeerchannels(struct command *cmd,
|
|||
/* We may still need local mods! */
|
||||
if (!p->mods)
|
||||
p->mods = gossmods_from_listpeerchannels(p, p->local_id,
|
||||
buffer, toks,
|
||||
buffer, toks, true,
|
||||
gossmod_add_localchan,
|
||||
NULL);
|
||||
|
||||
|
|
|
@ -490,7 +490,7 @@ static struct command_result *listpeerchannels_done(
|
|||
enum jsonrpc_errcode ecode;
|
||||
|
||||
payment->local_gossmods = gossmods_from_listpeerchannels(payment, &pay_plugin->my_id,
|
||||
buf, result,
|
||||
buf, result, true,
|
||||
gossmod_cb, payment);
|
||||
|
||||
// TODO(eduardo): check that there won't be a prob. cost associated with
|
||||
|
|
|
@ -54,6 +54,7 @@ struct gossmap_localmods *gossmods_from_listpeerchannels_(const tal_t *ctx UNNEE
|
|||
const struct node_id *self UNNEEDED,
|
||||
const char *buf UNNEEDED,
|
||||
const jsmntok_t *toks UNNEEDED,
|
||||
bool zero_rates UNNEEDED,
|
||||
void (*cb)(struct gossmap_localmods *mods UNNEEDED,
|
||||
const struct node_id *self_ UNNEEDED,
|
||||
const struct node_id *peer UNNEEDED,
|
||||
|
|
|
@ -161,7 +161,7 @@ listpeerchannels_getroute_done(struct command *cmd,
|
|||
|
||||
/* Get local knowledge */
|
||||
mods = gossmods_from_listpeerchannels(tmpctx, &local_id,
|
||||
buf, result,
|
||||
buf, result, true,
|
||||
gossmod_add_localchan, NULL);
|
||||
|
||||
/* Overlay local knowledge for dijkstra */
|
||||
|
@ -397,7 +397,7 @@ static struct command_result *listpeerchannels_done(struct command *cmd,
|
|||
if (command_deprecated_in_ok(cmd, "include_private", "v24.02", "v24.08")) {
|
||||
connected = local_connected(opts, buf, result);
|
||||
mods = gossmods_from_listpeerchannels(tmpctx, &local_id,
|
||||
buf, result,
|
||||
buf, result, false,
|
||||
gossmod_add_unknown_localchan,
|
||||
gossmap);
|
||||
gossmap_apply_localmods(gossmap, mods);
|
||||
|
@ -617,7 +617,7 @@ listpeerchannels_listincoming_done(struct command *cmd,
|
|||
|
||||
/* Get local knowledge */
|
||||
mods = gossmods_from_listpeerchannels(tmpctx, &local_id,
|
||||
buffer, result,
|
||||
buffer, result, false,
|
||||
gossmod_add_localchan,
|
||||
NULL);
|
||||
|
||||
|
|
Loading…
Add table
Reference in a new issue