Skip to content

Commit

Permalink
libplugin-pay: bias towards larger channels.
Browse files Browse the repository at this point in the history
We bias by channel by up to 2x the fee; this should drive us towards
larger channels.

Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
  • Loading branch information
rustyrussell committed Sep 8, 2021
1 parent 171d463 commit c75f74b
Show file tree
Hide file tree
Showing 2 changed files with 56 additions and 8 deletions.
53 changes: 51 additions & 2 deletions plugins/libplugin-pay.c
Original file line number Diff line number Diff line change
Expand Up @@ -692,6 +692,55 @@ static bool payment_route_can_carry_even_disabled(const struct gossmap *map,
return payment_route_check(map, c, dir, amount, p);
}

/* Rene Pickhardt:
*
* Btw the linear term of the Taylor series of -log((c+1-x)/(c+1)) is 1/(c+1)
* meaning that another suitable Weight for Dijkstra would be amt/(c+1) +
* \mu*fee(amt) which is the linearized version which for small amounts and
* suitable value of \mu should be good enough)
*/
static u64 capacity_bias(const struct gossmap *map,
const struct gossmap_chan *c,
int dir,
struct amount_msat cost)
{
struct amount_msat fee;
struct amount_sat capacity;

/* Overflow is pretty-much impossible, so ignore. */
if (!amount_msat_fee(&fee, cost,
c->half[dir].base_fee,
c->half[dir].proportional_fee))
return 0;

/* Can fail in theory if gossmap changed underneath. */
if (!gossmap_chan_get_capacity(map, c, &capacity))
return 0;

/* Assume we want \mu = 1/2 (i.e. capacity matters twice as much
* as fees), we get: bias = 2 * fee * (amt / (c + 1)) */
return 2
* fee.millisatoshis /* Raw: complex math & laziness */
* cost.millisatoshis /* Raw: complex math & laziness */
/ (capacity.satoshis*1000 + 1); /* Raw: complex math & laziness */
}

/* Prioritize costs over distance, but bias to larger channels. */
static u64 route_score(u32 distance,
struct amount_msat cost,
struct amount_msat risk,
int dir,
const struct gossmap_chan *c)
{
u64 costs = cost.millisatoshis + risk.millisatoshis /* Raw: score */
/* We use global_gossmap (can't still be NULL)
* *without* which might change topology. */
+ capacity_bias(global_gossmap, c, dir, cost);
if (costs > 0xFFFFFFFF)
costs = 0xFFFFFFFF;
return costs;
}

static struct route_hop *route(const tal_t *ctx,
struct gossmap *gossmap,
const struct gossmap_node *src,
Expand All @@ -713,14 +762,14 @@ static struct route_hop *route(const tal_t *ctx,

can_carry = payment_route_can_carry;
dij = dijkstra(tmpctx, gossmap, dst, amount, riskfactor,
can_carry, route_score_cheaper, p);
can_carry, route_score, p);
r = route_from_dijkstra(ctx, gossmap, dij, src, amount, final_delay);
if (!r) {
/* Try using disabled channels too */
/* FIXME: is there somewhere we can annotate this for paystatus? */
can_carry = payment_route_can_carry_even_disabled;
dij = dijkstra(ctx, gossmap, dst, amount, riskfactor,
can_carry, route_score_cheaper, p);
can_carry, route_score, p);
r = route_from_dijkstra(ctx, gossmap, dij, src,
amount, final_delay);
if (!r) {
Expand Down
11 changes: 5 additions & 6 deletions plugins/test/run-route-overlong.c
Original file line number Diff line number Diff line change
Expand Up @@ -333,7 +333,6 @@ int main(void)
int store_fd;
struct payment *p;
struct payment_modifier **mods;
struct gossmap *gossmap;
char gossip_version = GOSSIP_STORE_VERSION;
char gossipfilename[] = "/tmp/run-route-overlong.XXXXXX";

Expand All @@ -345,7 +344,7 @@ int main(void)
assert(write(store_fd, &gossip_version, sizeof(gossip_version))
== sizeof(gossip_version));

gossmap = gossmap_load(tmpctx, gossipfilename, NULL);
global_gossmap = gossmap_load(tmpctx, gossipfilename, NULL);

for (size_t i = 0; i < NUM_NODES; i++) {
struct privkey tmp;
Expand Down Expand Up @@ -384,7 +383,7 @@ int main(void)
1 << i);
}

assert(gossmap_refresh(gossmap, NULL));
assert(gossmap_refresh(global_gossmap, NULL));
for (size_t i = ROUTING_MAX_HOPS; i > 2; i--) {
struct gossmap_node *dst, *src;
struct route_hop *r;
Expand All @@ -393,9 +392,9 @@ int main(void)
type_to_string(tmpctx, struct node_id, &ids[0]),
type_to_string(tmpctx, struct node_id, &ids[NUM_NODES-1]));

src = gossmap_find_node(gossmap, &ids[0]);
dst = gossmap_find_node(gossmap, &ids[NUM_NODES-1]);
r = route(tmpctx, gossmap, src, dst, AMOUNT_MSAT(1000), 0, 0.0,
src = gossmap_find_node(global_gossmap, &ids[0]);
dst = gossmap_find_node(global_gossmap, &ids[NUM_NODES-1]);
r = route(tmpctx, global_gossmap, src, dst, AMOUNT_MSAT(1000), 0, 0.0,
i - 1, p, &errmsg);
assert(r);
/* FIXME: We naively fall back on shortest, rather
Expand Down

0 comments on commit c75f74b

Please sign in to comment.