Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

libplugin-pay: use map for channel hints #7726

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
57 changes: 43 additions & 14 deletions plugins/channel_hint.c
Original file line number Diff line number Diff line change
@@ -1,6 +1,34 @@
#include "config.h"
#include <common/memleak.h>
#include <plugins/channel_hint.h>

size_t channel_hint_hash(const struct short_channel_id_dir *out)
{
struct siphash24_ctx ctx;
siphash24_init(&ctx, siphash_seed());
siphash24_update(&ctx, &out->scid.u64, sizeof(u64));
siphash24_update(&ctx, &out->dir, sizeof(int));
return siphash24_done(&ctx);
}

const struct short_channel_id_dir *channel_hint_keyof(const struct channel_hint *out)
{
return &out->scid;
}

bool channel_hint_eq(const struct channel_hint *a,
const struct short_channel_id_dir *b)
{
return short_channel_id_eq(a->scid.scid, b->scid) &&
a->scid.dir == b->dir;
}

static void memleak_help_channel_hint_map(struct htable *memtable,
struct channel_hint_map *channel_hints)
{
memleak_scan_htable(memtable, &channel_hints->raw);
}

void channel_hint_to_json(const char *name, const struct channel_hint *hint,
struct json_stream *dest)
{
Expand Down Expand Up @@ -91,15 +119,10 @@ bool channel_hint_update(const struct timeabs now, struct channel_hint *hint)
amount_msat_greater(capacity, hint->estimated_capacity);
}

struct channel_hint *channel_hint_set_find(struct channel_hint_set *self,
struct channel_hint *channel_hint_set_find(const struct channel_hint_set *self,
const struct short_channel_id_dir *scidd)
{
for (size_t i=0; i<tal_count(self->hints); i++) {
struct channel_hint *hint = &self->hints[i];
if (short_channel_id_dir_eq(&hint->scid, scidd))
return hint;
}
return NULL;
return channel_hint_map_get(self->hints, scidd);
}

/* See header */
Expand All @@ -119,16 +142,16 @@ channel_hint_set_add(struct channel_hint_set *self, u32 timestamp,
old = channel_hint_set_find(self, scidd);
copy = tal_dup(tmpctx, struct channel_hint, old);
if (old == NULL) {
newhint = tal(tmpctx, struct channel_hint);
newhint = tal(self, struct channel_hint);
newhint->enabled = enabled;
newhint->scid = *scidd;
newhint->capacity = capacity;
if (estimated_capacity != NULL)
newhint->estimated_capacity = *estimated_capacity;
newhint->local = NULL;
newhint->timestamp = timestamp;
tal_arr_expand(&self->hints, *newhint);
return &self->hints[tal_count(self->hints) - 1];
channel_hint_map_add(self->hints, newhint);
return newhint;
} else if (old->timestamp <= timestamp) {
/* `local` is kept, since we do not pass in those
* annotations here. */
Expand Down Expand Up @@ -182,18 +205,24 @@ struct channel_hint *channel_hint_from_json(const tal_t *ctx,
struct channel_hint_set *channel_hint_set_new(const tal_t *ctx)
{
struct channel_hint_set *set = tal(ctx, struct channel_hint_set);
set->hints = tal_arr(set, struct channel_hint, 0);
set->hints = tal(set, struct channel_hint_map);
channel_hint_map_init(set->hints);
memleak_add_helper(set->hints, memleak_help_channel_hint_map);
return set;
}

void channel_hint_set_update(struct channel_hint_set *set,
const struct timeabs now)
{
for (size_t i = 0; i < tal_count(set->hints); i++)
channel_hint_update(time_now(), &set->hints[i]);
struct channel_hint *hint;
struct channel_hint_map_iter iter;
for (hint = channel_hint_map_first(set->hints, &iter);
hint;
hint = channel_hint_map_next(set->hints, &iter))
channel_hint_update(now, hint);
}

size_t channel_hint_set_count(const struct channel_hint_set *set)
{
return tal_count(set->hints);
return channel_hint_map_count(set->hints);
}
16 changes: 13 additions & 3 deletions plugins/channel_hint.h
Original file line number Diff line number Diff line change
Expand Up @@ -45,11 +45,21 @@ struct channel_hint {
struct amount_msat capacity;
};

size_t channel_hint_hash(const struct short_channel_id_dir *out);

const struct short_channel_id_dir *channel_hint_keyof(const struct channel_hint *out);

bool channel_hint_eq(const struct channel_hint *a,
const struct short_channel_id_dir *b);

HTABLE_DEFINE_TYPE(struct channel_hint, channel_hint_keyof,
channel_hint_hash, channel_hint_eq, channel_hint_map)

/* A collection of channel_hint instances, allowing us to handle and
* update them more easily. */
struct channel_hint_set {
/* tal_arr of channel_hints. */
struct channel_hint *hints;
/* htable of channel_hints, indexed by scid and direction. */
struct channel_hint_map *hints;
};

bool channel_hint_update(const struct timeabs now,
Expand All @@ -70,7 +80,7 @@ void channel_hint_set_update(struct channel_hint_set *set, const struct timeabs
/**
* Look up a `channel_hint` from a `channel_hint_set` for a scidd.
*/
struct channel_hint *channel_hint_set_find(struct channel_hint_set *self,
struct channel_hint *channel_hint_set_find(const struct channel_hint_set *self,
const struct short_channel_id_dir *scidd);

/**
Expand Down
49 changes: 17 additions & 32 deletions plugins/libplugin-pay.c
Original file line number Diff line number Diff line change
Expand Up @@ -613,11 +613,12 @@ payment_get_excluded_channels(const tal_t *ctx, struct payment *p)
{
struct payment *root = payment_root(p);
struct channel_hint *hint;
struct channel_hint_map_iter iter;
struct short_channel_id_dir *res =
tal_arr(ctx, struct short_channel_id_dir, 0);
for (size_t i = 0; i < tal_count(root->hints->hints); i++) {
hint = &root->hints->hints[i];

for (hint = channel_hint_map_first(root->hints->hints, &iter);
hint;
hint = channel_hint_map_next(root->hints->hints, &iter)) {
if (!hint->enabled)
tal_arr_expand(&res, hint->scid);

Expand All @@ -640,19 +641,6 @@ static const struct node_id *payment_get_excluded_nodes(const tal_t *ctx,
return root->excluded_nodes;
}

/* FIXME: This is slow! */
static const struct channel_hint *find_hint(const struct channel_hint *hints,
struct short_channel_id scid,
int dir)
{
for (size_t i = 0; i < tal_count(hints); i++) {
if (short_channel_id_eq(scid, hints[i].scid.scid)
&& dir == hints[i].scid.dir)
return &hints[i];
}
return NULL;
}

/* FIXME: This is slow! */
static bool dst_is_excluded(const struct gossmap *gossmap,
const struct gossmap_chan *c,
Expand Down Expand Up @@ -680,7 +668,7 @@ static bool payment_route_check(const struct gossmap *gossmap,
struct amount_msat amount,
struct payment *p)
{
struct short_channel_id scid;
struct short_channel_id_dir scidd;
const struct channel_hint *hint;

if (dst_is_excluded(gossmap, c, dir, payment_root(p)->excluded_nodes))
Expand All @@ -689,8 +677,9 @@ static bool payment_route_check(const struct gossmap *gossmap,
if (dst_is_excluded(gossmap, c, dir, p->temp_exclusion))
return false;

scid = gossmap_chan_scid(gossmap, c);
hint = find_hint(payment_root(p)->hints->hints, scid, dir);
scidd.scid = gossmap_chan_scid(gossmap, c);
scidd.dir = dir;
hint = channel_hint_set_find(payment_root(p)->hints, &scidd);
if (!hint)
return true;

Expand Down Expand Up @@ -2613,10 +2602,7 @@ local_channel_hints_listpeerchannels(struct command *cmd, const char *buffer,
* observations, and should re-enable some channels that would
* otherwise start out as excluded and remain so until
* forever. */

struct channel_hint *hints = payment_root(p)->hints->hints;
for (size_t i = 0; i < tal_count(hints); i++)
channel_hint_update(time_now(), &hints[i]);
channel_hint_set_update(payment_root(p)->hints, time_now());

payment_continue(p);
return command_still_pending(cmd);
Expand Down Expand Up @@ -2758,6 +2744,8 @@ static bool routehint_excluded(struct payment *p,
const struct short_channel_id_dir *chans =
payment_get_excluded_channels(tmpctx, p);
const struct channel_hint_set *hints = payment_root(p)->hints;
struct short_channel_id_dir scidd;
struct channel_hint *hint;

/* Note that we ignore direction here: in theory, we could have
* found that one direction of a channel is unavailable, but they
Expand Down Expand Up @@ -2797,15 +2785,12 @@ static bool routehint_excluded(struct payment *p,
* know the exact capacity we need to send via this
* channel, which is greater than the destination.
*/
for (size_t j = 0; j < tal_count(hints); j++) {
if (!short_channel_id_eq(hints->hints[j].scid.scid, r->short_channel_id))
continue;
/* We exclude on equality because we set the estimate
* to the smallest failed attempt. */
if (amount_msat_greater_eq(needed_capacity,
hints->hints[j].estimated_capacity))
return true;
}
scidd.scid = r->short_channel_id;
scidd.dir = node_id_idx(&r->pubkey, p->pay_destination);
hint = channel_hint_set_find(hints, &scidd);
if (hint && amount_msat_greater_eq(needed_capacity,
hint->estimated_capacity))
return true;
}
return false;
}
Expand Down
6 changes: 6 additions & 0 deletions plugins/test/run-route-calc.c
Original file line number Diff line number Diff line change
Expand Up @@ -272,6 +272,12 @@ struct json_stream *jsonrpc_stream_fail(struct command *cmd UNNEEDED,
/* Generated stub for jsonrpc_stream_success */
struct json_stream *jsonrpc_stream_success(struct command *cmd UNNEEDED)
{ fprintf(stderr, "jsonrpc_stream_success called!\n"); abort(); }
/* Generated stub for memleak_add_helper_ */
void memleak_add_helper_(const tal_t *p UNNEEDED, void (*cb)(struct htable *memtable UNNEEDED,
const tal_t *)){ }
/* Generated stub for memleak_scan_htable */
void memleak_scan_htable(struct htable *memtable UNNEEDED, const struct htable *ht UNNEEDED)
{ fprintf(stderr, "memleak_scan_htable called!\n"); abort(); }
/* Generated stub for notleak_ */
void *notleak_(void *ptr UNNEEDED, bool plus_children UNNEEDED)
{ fprintf(stderr, "notleak_ called!\n"); abort(); }
Expand Down
6 changes: 6 additions & 0 deletions plugins/test/run-route-overlong.c
Original file line number Diff line number Diff line change
Expand Up @@ -269,6 +269,12 @@ struct json_stream *jsonrpc_stream_fail(struct command *cmd UNNEEDED,
/* Generated stub for jsonrpc_stream_success */
struct json_stream *jsonrpc_stream_success(struct command *cmd UNNEEDED)
{ fprintf(stderr, "jsonrpc_stream_success called!\n"); abort(); }
/* Generated stub for memleak_add_helper_ */
void memleak_add_helper_(const tal_t *p UNNEEDED, void (*cb)(struct htable *memtable UNNEEDED,
const tal_t *)){ }
/* Generated stub for memleak_scan_htable */
void memleak_scan_htable(struct htable *memtable UNNEEDED, const struct htable *ht UNNEEDED)
{ fprintf(stderr, "memleak_scan_htable called!\n"); abort(); }
/* Generated stub for notleak_ */
void *notleak_(void *ptr UNNEEDED, bool plus_children UNNEEDED)
{ fprintf(stderr, "notleak_ called!\n"); abort(); }
Expand Down
Loading