Skip to content

Commit c75f74b

Browse files
committed
libplugin-pay: bias towards larger channels.
We bias by channel by up to 2x the fee; this should drive us towards larger channels. Signed-off-by: Rusty Russell <[email protected]>
1 parent 171d463 commit c75f74b

File tree

2 files changed

+56
-8
lines changed

2 files changed

+56
-8
lines changed

plugins/libplugin-pay.c

Lines changed: 51 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -692,6 +692,55 @@ static bool payment_route_can_carry_even_disabled(const struct gossmap *map,
692692
return payment_route_check(map, c, dir, amount, p);
693693
}
694694

695+
/* Rene Pickhardt:
696+
*
697+
* Btw the linear term of the Taylor series of -log((c+1-x)/(c+1)) is 1/(c+1)
698+
* meaning that another suitable Weight for Dijkstra would be amt/(c+1) +
699+
* \mu*fee(amt) which is the linearized version which for small amounts and
700+
* suitable value of \mu should be good enough)
701+
*/
702+
static u64 capacity_bias(const struct gossmap *map,
703+
const struct gossmap_chan *c,
704+
int dir,
705+
struct amount_msat cost)
706+
{
707+
struct amount_msat fee;
708+
struct amount_sat capacity;
709+
710+
/* Overflow is pretty-much impossible, so ignore. */
711+
if (!amount_msat_fee(&fee, cost,
712+
c->half[dir].base_fee,
713+
c->half[dir].proportional_fee))
714+
return 0;
715+
716+
/* Can fail in theory if gossmap changed underneath. */
717+
if (!gossmap_chan_get_capacity(map, c, &capacity))
718+
return 0;
719+
720+
/* Assume we want \mu = 1/2 (i.e. capacity matters twice as much
721+
* as fees), we get: bias = 2 * fee * (amt / (c + 1)) */
722+
return 2
723+
* fee.millisatoshis /* Raw: complex math & laziness */
724+
* cost.millisatoshis /* Raw: complex math & laziness */
725+
/ (capacity.satoshis*1000 + 1); /* Raw: complex math & laziness */
726+
}
727+
728+
/* Prioritize costs over distance, but bias to larger channels. */
729+
static u64 route_score(u32 distance,
730+
struct amount_msat cost,
731+
struct amount_msat risk,
732+
int dir,
733+
const struct gossmap_chan *c)
734+
{
735+
u64 costs = cost.millisatoshis + risk.millisatoshis /* Raw: score */
736+
/* We use global_gossmap (can't still be NULL)
737+
* *without* which might change topology. */
738+
+ capacity_bias(global_gossmap, c, dir, cost);
739+
if (costs > 0xFFFFFFFF)
740+
costs = 0xFFFFFFFF;
741+
return costs;
742+
}
743+
695744
static struct route_hop *route(const tal_t *ctx,
696745
struct gossmap *gossmap,
697746
const struct gossmap_node *src,
@@ -713,14 +762,14 @@ static struct route_hop *route(const tal_t *ctx,
713762

714763
can_carry = payment_route_can_carry;
715764
dij = dijkstra(tmpctx, gossmap, dst, amount, riskfactor,
716-
can_carry, route_score_cheaper, p);
765+
can_carry, route_score, p);
717766
r = route_from_dijkstra(ctx, gossmap, dij, src, amount, final_delay);
718767
if (!r) {
719768
/* Try using disabled channels too */
720769
/* FIXME: is there somewhere we can annotate this for paystatus? */
721770
can_carry = payment_route_can_carry_even_disabled;
722771
dij = dijkstra(ctx, gossmap, dst, amount, riskfactor,
723-
can_carry, route_score_cheaper, p);
772+
can_carry, route_score, p);
724773
r = route_from_dijkstra(ctx, gossmap, dij, src,
725774
amount, final_delay);
726775
if (!r) {

plugins/test/run-route-overlong.c

Lines changed: 5 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -333,7 +333,6 @@ int main(void)
333333
int store_fd;
334334
struct payment *p;
335335
struct payment_modifier **mods;
336-
struct gossmap *gossmap;
337336
char gossip_version = GOSSIP_STORE_VERSION;
338337
char gossipfilename[] = "/tmp/run-route-overlong.XXXXXX";
339338

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

348-
gossmap = gossmap_load(tmpctx, gossipfilename, NULL);
347+
global_gossmap = gossmap_load(tmpctx, gossipfilename, NULL);
349348

350349
for (size_t i = 0; i < NUM_NODES; i++) {
351350
struct privkey tmp;
@@ -384,7 +383,7 @@ int main(void)
384383
1 << i);
385384
}
386385

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

396-
src = gossmap_find_node(gossmap, &ids[0]);
397-
dst = gossmap_find_node(gossmap, &ids[NUM_NODES-1]);
398-
r = route(tmpctx, gossmap, src, dst, AMOUNT_MSAT(1000), 0, 0.0,
395+
src = gossmap_find_node(global_gossmap, &ids[0]);
396+
dst = gossmap_find_node(global_gossmap, &ids[NUM_NODES-1]);
397+
r = route(tmpctx, global_gossmap, src, dst, AMOUNT_MSAT(1000), 0, 0.0,
399398
i - 1, p, &errmsg);
400399
assert(r);
401400
/* FIXME: We naively fall back on shortest, rather

0 commit comments

Comments
 (0)