From 8738d78c866e21234f44ca1b6aedc7567d360554 Mon Sep 17 00:00:00 2001 From: Rusty Russell Date: Wed, 13 Dec 2023 16:05:42 +1030 Subject: [PATCH] plugins/pay: use gossmods_from_listpeerchannels instead of private gossip_store records. Signed-off-by: Rusty Russell --- plugins/Makefile | 4 +-- plugins/keysend.c | 3 ++ plugins/libplugin-pay.c | 49 +++++++++++++++++++++++++++++-- plugins/libplugin-pay.h | 3 ++ plugins/pay.c | 2 ++ plugins/test/run-route-overlong.c | 35 ++++++++++++++++++++++ 6 files changed, 92 insertions(+), 4 deletions(-) diff --git a/plugins/Makefile b/plugins/Makefile index ed796d20d..0e831f133 100644 --- a/plugins/Makefile +++ b/plugins/Makefile @@ -188,7 +188,7 @@ ALL_PROGRAMS += $(C_PLUGINS) # Make all plugins depend on all plugin headers, for simplicity. $(PLUGIN_ALL_OBJS): $(PLUGIN_ALL_HEADER) -plugins/pay: $(PLUGIN_PAY_OBJS) $(PLUGIN_LIB_OBJS) $(PLUGIN_PAY_LIB_OBJS) $(PLUGIN_COMMON_OBJS) $(JSMN_OBJS) common/gossmap.o common/fp16.o common/route.o common/dijkstra.o common/bolt12.o common/bolt12_merkle.o wire/bolt12_wiregen.o bitcoin/block.o common/blindedpay.o common/blindedpath.o common/hmac.o common/blinding.o common/onion_encode.o +plugins/pay: $(PLUGIN_PAY_OBJS) $(PLUGIN_LIB_OBJS) $(PLUGIN_PAY_LIB_OBJS) $(PLUGIN_COMMON_OBJS) $(JSMN_OBJS) common/gossmap.o common/fp16.o common/route.o common/dijkstra.o common/bolt12.o common/bolt12_merkle.o wire/bolt12_wiregen.o bitcoin/block.o common/blindedpay.o common/blindedpath.o common/hmac.o common/blinding.o common/onion_encode.o common/gossmods_listpeerchannels.o plugins/autoclean: $(PLUGIN_AUTOCLEAN_OBJS) $(PLUGIN_LIB_OBJS) $(PLUGIN_COMMON_OBJS) $(JSMN_OBJS) @@ -204,7 +204,7 @@ plugins/txprepare: $(PLUGIN_TXPREPARE_OBJS) $(PLUGIN_LIB_OBJS) $(PLUGIN_COMMON_O plugins/bcli: $(PLUGIN_BCLI_OBJS) $(PLUGIN_LIB_OBJS) $(PLUGIN_COMMON_OBJS) $(JSMN_OBJS) -plugins/keysend: wire/tlvstream.o wire/onion_wiregen.o $(PLUGIN_KEYSEND_OBJS) $(PLUGIN_LIB_OBJS) $(PLUGIN_PAY_LIB_OBJS) $(PLUGIN_COMMON_OBJS) $(JSMN_OBJS) common/gossmap.o common/fp16.o common/route.o common/dijkstra.o common/blindedpay.o common/blindedpath.o common/hmac.o common/blinding.o common/onion_encode.o +plugins/keysend: wire/tlvstream.o wire/onion_wiregen.o $(PLUGIN_KEYSEND_OBJS) $(PLUGIN_LIB_OBJS) $(PLUGIN_PAY_LIB_OBJS) $(PLUGIN_COMMON_OBJS) $(JSMN_OBJS) common/gossmap.o common/fp16.o common/route.o common/dijkstra.o common/blindedpay.o common/blindedpath.o common/hmac.o common/blinding.o common/onion_encode.o common/gossmods_listpeerchannels.o $(PLUGIN_KEYSEND_OBJS): $(PLUGIN_PAY_LIB_HEADER) plugins/spenderp: bitcoin/block.o bitcoin/preimage.o bitcoin/psbt.o common/psbt_open.o wire/peer${EXP}_wiregen.o $(PLUGIN_SPENDER_OBJS) $(PLUGIN_LIB_OBJS) $(PLUGIN_COMMON_OBJS) $(JSMN_OBJS) diff --git a/plugins/keysend.c b/plugins/keysend.c index c74eb3ad2..17e39fd02 100644 --- a/plugins/keysend.c +++ b/plugins/keysend.c @@ -4,6 +4,7 @@ #include #include #include +#include #include #include #include @@ -610,6 +611,8 @@ int main(int argc, char *argv[]) features->bits[i] = tal_arr(features, u8, 0); set_feature_bit(&features->bits[NODE_ANNOUNCE_FEATURE], KEYSEND_FEATUREBIT); + /* We are migrated, ready for public-only gossmap! */ + gossmap_public_only = true; plugin_main(argv, init, PLUGIN_STATIC, true, features, commands, ARRAY_SIZE(commands), NULL, 0, hooks, ARRAY_SIZE(hooks), notification_topics, ARRAY_SIZE(notification_topics), NULL); diff --git a/plugins/libplugin-pay.c b/plugins/libplugin-pay.c index effee07f1..3bd5230b5 100644 --- a/plugins/libplugin-pay.c +++ b/plugins/libplugin-pay.c @@ -5,6 +5,7 @@ #include #include #include +#include #include #include #include @@ -43,13 +44,17 @@ static struct gossmap *get_gossmap(struct payment *payment) else gossmap_refresh(global_gossmap, NULL); got_gossmap = true; + assert(payment->mods); + gossmap_apply_localmods(global_gossmap, payment->mods); return global_gossmap; } + static void put_gossmap(struct payment *payment) { assert(got_gossmap); got_gossmap = false; + gossmap_remove_localmods(global_gossmap, payment->mods); } int libplugin_pay_poll(struct pollfd *fds, nfds_t nfds, int timeout) @@ -112,6 +117,7 @@ struct payment *payment_new(tal_t *ctx, struct command *cmd, p->groupid = parent->groupid; p->invstring = parent->invstring; p->description = parent->description; + p->mods = parent->mods; } else { assert(cmd != NULL); p->partid = 0; @@ -125,6 +131,7 @@ struct payment *payment_new(tal_t *ctx, struct command *cmd, p->local_id = NULL; p->local_invreq_id = NULL; p->groupid = 0; + p->mods = NULL; } /* Initialize all modifier data so we can point to the fields when @@ -331,6 +338,7 @@ void payment_start_at_blockheight(struct payment *p, u32 blockheight) json_add_u32(req->js, "blockheight", 0); send_outreq(p->plugin, req); } + void payment_start(struct payment *p) { payment_start_at_blockheight(p, INVALID_BLOCKHEIGHT); @@ -930,6 +938,33 @@ static struct command_result *payment_getroute(struct payment *p) return command_still_pending(p->cmd); } +static struct command_result * +payment_listpeerchannels_success(struct command *cmd, + const char *buffer, + const jsmntok_t *toks, + struct payment *p) +{ + p->mods = gossmods_from_listpeerchannels(p, p->local_id, + buffer, toks, + gossmod_add_localchan, + NULL); + return payment_getroute(p); +} + +static struct command_result *payment_getlocalmods(struct payment *p) +{ + struct out_req *req; + + /* Don't call listpeerchannels if we already have mods */ + if (p->mods) + return payment_getroute(p); + + req = jsonrpc_request_start(p->plugin, NULL, "listpeerchannels", + &payment_listpeerchannels_success, + &payment_rpc_failure, p); + return send_outreq(p->plugin, req); +} + static struct payment_result *tal_sendpay_result_from_json(const tal_t *ctx, const char *buffer, const jsmntok_t *toks) @@ -2168,7 +2203,7 @@ void payment_continue(struct payment *p) switch (p->step) { case PAYMENT_STEP_INITIALIZED: case PAYMENT_STEP_RETRY_GETROUTE: - payment_getroute(p); + payment_getlocalmods(p); return; case PAYMENT_STEP_GOT_ROUTE: @@ -2827,6 +2862,7 @@ static void routehint_check_reachable(struct payment *p) "Destination %s is not reachable directly and " "all routehints were unusable.", type_to_string(tmpctx, struct node_id, p->destination)); + put_gossmap(p); return; } @@ -3309,6 +3345,9 @@ static struct command_result *direct_pay_listpeerchannels(struct command *cmd, for (size_t i=0; iid, p->destination)) + continue; + if (!chan->connected) continue; @@ -3329,6 +3368,13 @@ static struct command_result *direct_pay_listpeerchannels(struct command *cmd, d->chan->dir = chan->direction; } + /* We may still need local mods! */ + if (!p->mods) + p->mods = gossmods_from_listpeerchannels(p, p->local_id, + buffer, toks, + gossmod_add_localchan, + NULL); + direct_pay_override(p); return command_still_pending(cmd); @@ -3348,7 +3394,6 @@ static void direct_pay_cb(struct direct_pay_data *d, struct payment *p) direct_pay_listpeerchannels, direct_pay_listpeerchannels, p); - json_add_node_id(req->js, "id", p->destination); send_outreq(p->plugin, req); } diff --git a/plugins/libplugin-pay.h b/plugins/libplugin-pay.h index 32eedcd69..77783c627 100644 --- a/plugins/libplugin-pay.h +++ b/plugins/libplugin-pay.h @@ -237,6 +237,9 @@ struct payment { struct short_channel_id *exclusions; + /* Local modifications, from listpeerchannels */ + struct gossmap_localmods *mods; + /* Tree structure of payments and subpayments. */ struct payment *parent, **children; diff --git a/plugins/pay.c b/plugins/pay.c index 153d86a32..d162e70bf 100644 --- a/plugins/pay.c +++ b/plugins/pay.c @@ -1300,6 +1300,8 @@ static const char *notification_topics[] = { int main(int argc, char *argv[]) { setup_locale(); + /* We are migrated, ready for public-only gossmap! */ + gossmap_public_only = true; plugin_main(argv, init, PLUGIN_RESTARTABLE, true, NULL, commands, ARRAY_SIZE(commands), NULL, 0, NULL, 0, notification_topics, ARRAY_SIZE(notification_topics), diff --git a/plugins/test/run-route-overlong.c b/plugins/test/run-route-overlong.c index 221fff0a5..881f20ba6 100644 --- a/plugins/test/run-route-overlong.c +++ b/plugins/test/run-route-overlong.c @@ -34,6 +34,41 @@ bigsize_t fromwire_bigsize(const u8 **cursor UNNEEDED, size_t *max UNNEEDED) bool fromwire_channel_id(const u8 **cursor UNNEEDED, size_t *max UNNEEDED, struct channel_id *channel_id UNNEEDED) { fprintf(stderr, "fromwire_channel_id called!\n"); abort(); } +/* Generated stub for gossmod_add_localchan */ +void gossmod_add_localchan(struct gossmap_localmods *mods UNNEEDED, + const struct node_id *self UNNEEDED, + const struct node_id *peer UNNEEDED, + const struct short_channel_id_dir *scidd UNNEEDED, + struct amount_msat min UNNEEDED, + struct amount_msat max UNNEEDED, + struct amount_msat fee_base UNNEEDED, + u32 fee_proportional UNNEEDED, + u32 cltv_delta UNNEEDED, + bool enabled UNNEEDED, + const char *buf UNUSED UNNEEDED, + const jsmntok_t *chantok UNUSED UNNEEDED, + void *cbarg UNUSED UNNEEDED) +{ fprintf(stderr, "gossmod_add_localchan called!\n"); abort(); } +/* Generated stub for gossmods_from_listpeerchannels_ */ +struct gossmap_localmods *gossmods_from_listpeerchannels_(const tal_t *ctx UNNEEDED, + const struct node_id *self UNNEEDED, + const char *buf UNNEEDED, + const jsmntok_t *toks UNNEEDED, + void (*cb)(struct gossmap_localmods *mods UNNEEDED, + const struct node_id *self_ UNNEEDED, + const struct node_id *peer UNNEEDED, + const struct short_channel_id_dir *scidd UNNEEDED, + struct amount_msat min UNNEEDED, + struct amount_msat max UNNEEDED, + struct amount_msat fee_base UNNEEDED, + u32 fee_proportional UNNEEDED, + u32 cltv_delta UNNEEDED, + bool enabled UNNEEDED, + const char *buf_ UNNEEDED, + const jsmntok_t *chantok UNNEEDED, + void *cbarg_) UNNEEDED, + void *cbarg UNNEEDED) +{ fprintf(stderr, "gossmods_from_listpeerchannels_ called!\n"); abort(); } /* Generated stub for json_add_amount_msat */ void json_add_amount_msat(struct json_stream *result UNNEEDED, const char *msatfieldname UNNEEDED,