mirror of
https://github.com/ElementsProject/lightning.git
synced 2025-01-19 05:44:12 +01:00
libplugin-pay: bias towards larger channels.
We bias by channel linearly by capacity, scaled by median fee. This means that we effectively double the fee if we would use the entire capacity, and only increase it by 50% if we would only use 1/2 the capacity. This should drive us towards larger channels. Signed-off-by: Rusty Russell <rusty@rustcorp.com.au> Changelog-Changed: Plugins: `pay` now biases towards larger channels, improving success probability.
This commit is contained in:
parent
0b3c79b3c2
commit
233d339061
@ -695,6 +695,52 @@ 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 amount)
|
||||
{
|
||||
struct amount_msat fee;
|
||||
struct amount_sat capacity;
|
||||
|
||||
/* Median fees are 1000 base, 10 ppm, so scale capacity bias to that */
|
||||
/* Overflow is pretty-much impossible, so ignore. */
|
||||
if (!amount_msat_fee(&fee, amount, 1000, 10))
|
||||
return 0;
|
||||
|
||||
/* Can fail in theory if gossmap changed underneath. */
|
||||
if (!gossmap_chan_get_capacity(map, c, &capacity))
|
||||
return 0;
|
||||
|
||||
/* bias = fee * (amt / (c + 1)) */
|
||||
return fee.millisatoshis /* Raw: complex math & laziness */
|
||||
* amount.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* get_gossmap() 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,
|
||||
@ -716,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) {
|
||||
|
@ -332,7 +332,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";
|
||||
|
||||
@ -344,7 +343,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;
|
||||
@ -383,7 +382,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;
|
||||
@ -392,9 +391,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
|
||||
|
Loading…
Reference in New Issue
Block a user