libplugin-pay: make sure get_gossmap calls are balanced by put_gossmap.

This will become important when we apply localmods to the gossmap at these points.

Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
This commit is contained in:
Rusty Russell
2023-12-13 16:05:01 +10:30
parent a5c0563612
commit 3fdae99524
4 changed files with 34 additions and 7 deletions

View File

@@ -2,6 +2,7 @@
#include <ccan/array_size/array_size.h>
#include <ccan/tal/str/str.h>
#include <common/blindedpay.h>
#include <common/daemon.h>
#include <common/dijkstra.h>
#include <common/gossmap.h>
#include <common/json_stream.h>
@@ -16,6 +17,7 @@
#include <wire/peer_wire.h>
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,

View File

@@ -2,6 +2,7 @@
#define LIGHTNING_PLUGINS_LIBPLUGIN_PAY_H
#include "config.h"
#include <ccan/io/io.h>
#include <common/bolt11.h>
#include <common/route.h>
#include <plugins/libplugin.h>
@@ -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 */

View File

@@ -1307,4 +1307,5 @@ int main(int argc, char *argv[])
"Disable multi-part payments.",
flag_option, &disablempp),
NULL);
io_poll_override(libplugin_pay_poll);
}

View File

@@ -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(); }