diff --git a/plugins/libplugin-pay.c b/plugins/libplugin-pay.c index 68c7ea05e..effee07f1 100644 --- a/plugins/libplugin-pay.c +++ b/plugins/libplugin-pay.c @@ -2,6 +2,7 @@ #include #include #include +#include #include #include #include @@ -16,6 +17,7 @@ #include static struct gossmap *global_gossmap; +static bool got_gossmap; static void init_gossmap(struct plugin *plugin) { @@ -33,15 +35,29 @@ static void init_gossmap(struct plugin *plugin) num_channel_updates_rejected); } -struct gossmap *get_gossmap(struct plugin *plugin) +static struct gossmap *get_gossmap(struct payment *payment) { + assert(!got_gossmap); if (!global_gossmap) - init_gossmap(plugin); + init_gossmap(payment->plugin); else gossmap_refresh(global_gossmap, NULL); + got_gossmap = true; return global_gossmap; } +static void put_gossmap(struct payment *payment) +{ + assert(got_gossmap); + got_gossmap = false; +} + +int libplugin_pay_poll(struct pollfd *fds, nfds_t nfds, int timeout) +{ + assert(!got_gossmap); + return daemon_poll(fds, nfds, timeout); +} + struct payment *payment_new(tal_t *ctx, struct command *cmd, struct payment *parent, struct payment_modifier **mods) @@ -832,10 +848,11 @@ static struct command_result *payment_getroute(struct payment *p) * free an eventual stale route. */ p->route = tal_free(p->route); - gossmap = get_gossmap(p->plugin); + gossmap = get_gossmap(p); dst = gossmap_find_node(gossmap, p->getroute->destination); if (!dst) { + put_gossmap(p); payment_fail( p, "Unknown destination %s", type_to_string(tmpctx, struct node_id, @@ -848,6 +865,7 @@ static struct command_result *payment_getroute(struct payment *p) /* If we don't exist in gossip, routing can't happen. */ src = gossmap_find_node(gossmap, p->local_id); if (!src) { + put_gossmap(p); payment_fail(p, "We don't have any channels"); /* Let payment_finished_ handle this, so we mark it as pending */ @@ -857,6 +875,8 @@ static struct command_result *payment_getroute(struct payment *p) p->route = route(p, gossmap, src, dst, p->getroute->amount, p->getroute->cltv, p->getroute->riskfactorppm / 1000000.0, p->getroute->max_hops, p, &errstr); + put_gossmap(p); + if (!p->route) { payment_fail(p, "%s", errstr); /* Let payment_finished_ handle this, so we mark it as pending */ @@ -2751,7 +2771,7 @@ static void routehint_pre_getroute(struct routehints_data *d, struct payment *p) static void routehint_check_reachable(struct payment *p) { const struct gossmap_node *dst, *src; - struct gossmap *gossmap = get_gossmap(p->plugin); + struct gossmap *gossmap = get_gossmap(p); const struct dijkstra *dij; struct route_hop *r; struct payment *root = payment_root(p); @@ -2811,6 +2831,7 @@ static void routehint_check_reachable(struct payment *p) } routehint_pre_getroute(d, p); + put_gossmap(p); paymod_log(p, LOG_DBG, "The destination is%s directly reachable %s attempts " @@ -2835,7 +2856,7 @@ static void routehint_step_cb(struct routehints_data *d, struct payment *p) * beginning, and every other payment will filter out the * exluded ones on the fly. */ if (p->parent == NULL) { - map = get_gossmap(p->plugin); + map = get_gossmap(p); d->routehints = filter_routehints( map, p, d, p->local_id, p->routes); /* filter_routehints modifies the array, but @@ -2858,6 +2879,7 @@ static void routehint_step_cb(struct routehints_data *d, struct payment *p) * in paymod, paymod should use (and mutate) the * p->routes array, and */ + put_gossmap(p); p->routes = d->routehints; paymod_log(p, LOG_DBG, diff --git a/plugins/libplugin-pay.h b/plugins/libplugin-pay.h index c31f7b216..32eedcd69 100644 --- a/plugins/libplugin-pay.h +++ b/plugins/libplugin-pay.h @@ -2,6 +2,7 @@ #define LIGHTNING_PLUGINS_LIBPLUGIN_PAY_H #include "config.h" +#include #include #include #include @@ -488,7 +489,7 @@ void json_add_payment_success(struct json_stream *js, const struct preimage *preimage, const struct payment_tree_result *result); -/* For special effects, like inspecting your own routes. */ -struct gossmap *get_gossmap(struct plugin *plugin); +/* Overriding io_poll for extra checks. */ +int libplugin_pay_poll(struct pollfd *fds, nfds_t nfds, int timeout); #endif /* LIGHTNING_PLUGINS_LIBPLUGIN_PAY_H */ diff --git a/plugins/pay.c b/plugins/pay.c index 3bd1a6cda..153d86a32 100644 --- a/plugins/pay.c +++ b/plugins/pay.c @@ -1307,4 +1307,5 @@ int main(int argc, char *argv[]) "Disable multi-part payments.", flag_option, &disablempp), NULL); + io_poll_override(libplugin_pay_poll); } diff --git a/plugins/test/run-route-overlong.c b/plugins/test/run-route-overlong.c index f78f0fa56..221fff0a5 100644 --- a/plugins/test/run-route-overlong.c +++ b/plugins/test/run-route-overlong.c @@ -21,6 +21,9 @@ struct command_result *command_finished(struct command *cmd UNNEEDED, struct jso /* Generated stub for command_still_pending */ struct command_result *command_still_pending(struct command *cmd UNNEEDED) { fprintf(stderr, "command_still_pending called!\n"); abort(); } +/* Generated stub for daemon_poll */ +int daemon_poll(struct pollfd *fds UNNEEDED, nfds_t nfds UNNEEDED, int timeout UNNEEDED) +{ fprintf(stderr, "daemon_poll called!\n"); abort(); } /* Generated stub for feature_offered */ bool feature_offered(const u8 *features UNNEEDED, size_t f UNNEEDED) { fprintf(stderr, "feature_offered called!\n"); abort(); }