From 10928b5c45da73f9f0b3a6b78c71967269153905 Mon Sep 17 00:00:00 2001 From: Rusty Russell Date: Wed, 6 Nov 2024 21:18:36 +1030 Subject: [PATCH 01/18] libplugin: tell compiler that plugin_err is like printf. And fix the fallout! Signed-off-by: Rusty Russell --- plugins/bcli.c | 7 ++++--- plugins/bkpr/bookkeeper.c | 12 ++++++------ plugins/libplugin.h | 2 +- 3 files changed, 11 insertions(+), 10 deletions(-) diff --git a/plugins/bcli.c b/plugins/bcli.c index b169a74df754..9e2f1eff2c6e 100644 --- a/plugins/bcli.c +++ b/plugins/bcli.c @@ -1006,17 +1006,18 @@ static void parse_getnetworkinfo_result(struct plugin *p, const char *buf) if (!result) plugin_err(p, "Invalid response to '%s': '%s'. Can not " "continue without proceeding to sanity checks.", - gather_args(bitcoind, "getnetworkinfo", NULL), buf); + args_string(tmpctx, gather_args(bitcoind, "getnetworkinfo", NULL)), + buf); /* Check that we have a fully-featured `estimatesmartfee`. */ err = json_scan(tmpctx, buf, result, "{version:%,localrelay:%}", JSON_SCAN(json_to_u32, &bitcoind->version), JSON_SCAN(json_to_bool, &tx_relay)); if (err) - plugin_err(p, "%s. Got '%s'. Can not" + plugin_err(p, "%s. Got '%.*s'. Can not" " continue without proceeding to sanity checks.", err, - gather_args(bitcoind, "getnetworkinfo", NULL), buf); + json_tok_full_len(result), json_tok_full(buf, result)); if (bitcoind->version < min_version) plugin_err(p, "Unsupported bitcoind version %"PRIu32", at least" diff --git a/plugins/bkpr/bookkeeper.c b/plugins/bkpr/bookkeeper.c index 78af58c6e4f4..e2a6489ea0e4 100644 --- a/plugins/bkpr/bookkeeper.c +++ b/plugins/bkpr/bookkeeper.c @@ -891,7 +891,7 @@ static struct command_result *listpeerchannels_multi_done(struct command *cmd, db_commit_transaction(db); if (err) - plugin_err(cmd->plugin, err); + plugin_err(cmd->plugin, "%s", err); /* FIXME: multiple currencies */ if (tal_count(balances) > 0) @@ -907,7 +907,7 @@ static struct command_result *listpeerchannels_multi_done(struct command *cmd, bal->debit, &credit_diff, &debit_diff); if (err) - plugin_err(cmd->plugin, err); + plugin_err(cmd->plugin, "%s", err); log_journal_entry(info->acct, info->currency, @@ -1327,7 +1327,7 @@ listpeerchannels_done(struct command *cmd, const char *buf, db_commit_transaction(db); if (err) - plugin_err(cmd->plugin, err); + plugin_err(cmd->plugin, "%s", err); /* FIXME: multiple currencies per account? */ if (tal_count(balances) > 0) @@ -1346,7 +1346,7 @@ listpeerchannels_done(struct command *cmd, const char *buf, bal->debit, &credit_diff, &debit_diff); if (err) - plugin_err(cmd->plugin, err); + plugin_err(cmd->plugin, "%s", err); log_journal_entry(info->acct, info->ev->currency, @@ -1360,7 +1360,7 @@ listpeerchannels_done(struct command *cmd, const char *buf, /* Maybe mark acct as onchain resolved */ err = do_account_close_checks(cmd, info->ev, info->acct); if (err) - plugin_err(cmd->plugin, err); + plugin_err(cmd->plugin, "%s", err); if (info->ev->payment_id && streq(info->ev->tag, mvt_tag_str(INVOICE))) { @@ -1576,7 +1576,7 @@ parse_and_log_chain_move(struct command *cmd, /* Maybe mark acct as onchain resolved */ err = do_account_close_checks(cmd, e, acct); if (err) - plugin_err(cmd->plugin, err); + plugin_err(cmd->plugin, "%s", err); /* Check for invoice desc data, necessary */ if (e->payment_id) { diff --git a/plugins/libplugin.h b/plugins/libplugin.h index b44899bbd7ac..f4dc7d5991ea 100644 --- a/plugins/libplugin.h +++ b/plugins/libplugin.h @@ -322,7 +322,7 @@ bool command_deprecated_in_nocmd_ok(struct plugin *plugin, const char *depr_end); /* Call this on fatal error. */ -void NORETURN plugin_err(struct plugin *p, const char *fmt, ...); +void NORETURN PRINTF_FMT(2,3) plugin_err(struct plugin *p, const char *fmt, ...); /* Call this on fatal error. */ void NORETURN plugin_errv(struct plugin *p, const char *fmt, va_list ap); From cf6a2f5acaea85923f945b8584fd99886ea50951 Mon Sep 17 00:00:00 2001 From: Rusty Russell Date: Wed, 6 Nov 2024 21:19:36 +1030 Subject: [PATCH 02/18] libplugin: add aux_command. Sometimes we want to clean up *after* a command has completed, but we're moving to a model where all libplugin operations require a `struct command`. This adds `aux_command` to create an independent-lifetime command with the same id. Signed-off-by: Rusty Russell --- plugins/libplugin.c | 57 ++++++++++++++++++++++++++++++++++++++------- plugins/libplugin.h | 9 +++++++ 2 files changed, 57 insertions(+), 9 deletions(-) diff --git a/plugins/libplugin.c b/plugins/libplugin.c index af1c5a70b7c0..e3dc37da1a26 100644 --- a/plugins/libplugin.c +++ b/plugins/libplugin.c @@ -190,6 +190,31 @@ static void complain_deprecated_nocmd(const char *feature, } } +/* New command, without a filter */ +static struct command *new_command(const tal_t *ctx, + struct plugin *plugin, + const char *id TAKES, + const char *methodname TAKES, + bool usage_only, + bool check) +{ + struct command *cmd = tal(ctx, struct command); + + cmd->plugin = plugin; + cmd->usage_only = usage_only; + cmd->check = check; + cmd->filter = NULL; + cmd->methodname = tal_strdup(cmd, methodname); + if (id) { + cmd->id = tal_strdup(cmd, id); + } else { + /* Might be taken, even if NULL */ + taken(id); + cmd->id = NULL; + } + return cmd; +} + bool command_deprecated_in_nocmd_ok(struct plugin *plugin, const char *name, const char *depr_start, @@ -1630,11 +1655,11 @@ bool flag_jsonfmt(struct plugin *plugin, struct json_stream *js, const char *fie static void setup_command_usage(struct plugin *p) { - struct command *usage_cmd = tal(tmpctx, struct command); + struct command *usage_cmd = new_command(tmpctx, p, "usage", + "check-usage", + true, false); /* This is how common/param can tell it's just a usage request */ - usage_cmd->usage_only = true; - usage_cmd->plugin = p; for (size_t i = 0; i < p->num_commands; i++) { struct command_result *res; @@ -1881,6 +1906,7 @@ static void ld_command_handle(struct plugin *plugin, const jsmntok_t *toks) { const jsmntok_t *methtok, *paramstok, *filtertok; + const char *methodname; struct command *cmd; methtok = json_get_member(plugin->buffer, toks, "method"); @@ -1893,12 +1919,11 @@ static void ld_command_handle(struct plugin *plugin, json_tok_full_len(toks), json_tok_full(plugin->buffer, toks)); - cmd = tal(plugin, struct command); - cmd->plugin = plugin; - cmd->usage_only = false; - cmd->filter = NULL; - cmd->methodname = json_strdup(cmd, plugin->buffer, methtok); - cmd->id = json_get_id(cmd, plugin->buffer, toks); + methodname = json_strdup(NULL, plugin->buffer, methtok); + cmd = new_command(plugin, plugin, + take(json_get_id(NULL, plugin->buffer, toks)), + take(methodname), + false, streq(methodname, "check")); if (!plugin->manifested) { if (streq(cmd->methodname, "getmanifest")) { @@ -2507,6 +2532,20 @@ command_hook_success(struct command *cmd) return command_finished(cmd, response); } +struct command *aux_command(const struct command *cmd) +{ + assert(!cmd->check); + return new_command(cmd->plugin, cmd->plugin, cmd->id, + cmd->methodname, false, false); +} + +struct command_result *WARN_UNUSED_RESULT +aux_command_done(struct command *cmd) +{ + tal_free(cmd); + return &complete; +} + struct command_result *WARN_UNUSED_RESULT notification_handled(struct command *cmd) { diff --git a/plugins/libplugin.h b/plugins/libplugin.h index f4dc7d5991ea..7f50a4623c30 100644 --- a/plugins/libplugin.h +++ b/plugins/libplugin.h @@ -190,6 +190,11 @@ struct out_req *add_to_batch(struct command *cmd, struct request_batch *batch, const char *cmdname); +/* We want some commands to live after this command (possibly) + * completes. This creates a new command with the same id but its own + * lifetime: use aux_command_done() or tal_free() when you're done. */ +struct command *aux_command(const struct command *cmd); + /* Runs finalcb immediately if batch is empty. */ struct command_result *batch_done(struct command *cmd, struct request_batch *batch); @@ -355,6 +360,10 @@ command_hook_success(struct command *cmd); struct command_result *WARN_UNUSED_RESULT notification_handled(struct command *cmd); +/* End a command created with aux_command. */ +struct command_result *WARN_UNUSED_RESULT +aux_command_done(struct command *cmd); + /** * What's the deprecation_ok state for this cmd? * @cmd: the command. From 5fe7445188ceed95bd0e4448572ca0b60b75bd60 Mon Sep 17 00:00:00 2001 From: Rusty Russell Date: Wed, 6 Nov 2024 21:20:36 +1030 Subject: [PATCH 03/18] libplugin: always set the "id" field of a command. We didn't set this previously when it was a notification. Signed-off-by: Rusty Russell --- plugins/libplugin.c | 19 ++++++------------- 1 file changed, 6 insertions(+), 13 deletions(-) diff --git a/plugins/libplugin.c b/plugins/libplugin.c index e3dc37da1a26..66b718188776 100644 --- a/plugins/libplugin.c +++ b/plugins/libplugin.c @@ -205,13 +205,7 @@ static struct command *new_command(const tal_t *ctx, cmd->check = check; cmd->filter = NULL; cmd->methodname = tal_strdup(cmd, methodname); - if (id) { - cmd->id = tal_strdup(cmd, id); - } else { - /* Might be taken, even if NULL */ - taken(id); - cmd->id = NULL; - } + cmd->id = tal_strdup(cmd, id); return cmd; } @@ -319,10 +313,6 @@ const char *json_id_prefix(const tal_t *ctx, const struct command *cmd) if (!cmd) return ""; - /* Notifications have no cmd->id, use methodname */ - if (!cmd->id) - return tal_fmt(ctx, "%s/", cmd->methodname); - /* Strip quotes! */ if (strstarts(cmd->id, "\"")) { assert(strlen(cmd->id) >= 2); @@ -1908,6 +1898,7 @@ static void ld_command_handle(struct plugin *plugin, const jsmntok_t *methtok, *paramstok, *filtertok; const char *methodname; struct command *cmd; + const char *id; methtok = json_get_member(plugin->buffer, toks, "method"); paramstok = json_get_member(plugin->buffer, toks, "params"); @@ -1920,8 +1911,10 @@ static void ld_command_handle(struct plugin *plugin, json_tok_full(plugin->buffer, toks)); methodname = json_strdup(NULL, plugin->buffer, methtok); + id = json_get_id(tmpctx, plugin->buffer, toks); + cmd = new_command(plugin, plugin, - take(json_get_id(NULL, plugin->buffer, toks)), + id ? id : tal_fmt(tmpctx, "notification-%s", methodname), take(methodname), false, streq(methodname, "check")); @@ -1946,7 +1939,7 @@ static void ld_command_handle(struct plugin *plugin, } /* If that's a notification. */ - if (!cmd->id) { + if (!id) { bool is_shutdown = streq(cmd->methodname, "shutdown"); if (is_shutdown && plugin->developer) memleak_check(plugin, cmd); From b0c0c46e28be90b846cb5e4cc23ec667bb3b74dd Mon Sep 17 00:00:00 2001 From: Rusty Russell Date: Wed, 6 Nov 2024 21:21:36 +1030 Subject: [PATCH 04/18] libplugin: enumerate the specific "struct command" types. This is clearer than the previous "two booleans". Signed-off-by: Rusty Russell --- plugins/libplugin.c | 57 ++++++++++++++++++++++++++++++++------------- plugins/libplugin.h | 18 ++++++++++++-- 2 files changed, 57 insertions(+), 18 deletions(-) diff --git a/plugins/libplugin.c b/plugins/libplugin.c index 66b718188776..77fee44e2197 100644 --- a/plugins/libplugin.c +++ b/plugins/libplugin.c @@ -195,14 +195,12 @@ static struct command *new_command(const tal_t *ctx, struct plugin *plugin, const char *id TAKES, const char *methodname TAKES, - bool usage_only, - bool check) + enum command_type type) { struct command *cmd = tal(ctx, struct command); cmd->plugin = plugin; - cmd->usage_only = usage_only; - cmd->check = check; + cmd->type = type; cmd->filter = NULL; cmd->methodname = tal_strdup(cmd, methodname); cmd->id = tal_strdup(cmd, id); @@ -412,6 +410,8 @@ static struct json_stream *jsonrpc_stream_start(struct command *cmd) struct json_stream *jsonrpc_stream_success(struct command *cmd) { struct json_stream *js = jsonrpc_stream_start(cmd); + assert(cmd->type == COMMAND_TYPE_NORMAL + || cmd->type == COMMAND_TYPE_HOOK); json_object_start(js, "result"); if (cmd->filter) @@ -425,6 +425,8 @@ struct json_stream *jsonrpc_stream_fail(struct command *cmd, { struct json_stream *js = jsonrpc_stream_start(cmd); + assert(cmd->type == COMMAND_TYPE_NORMAL + || cmd->type == COMMAND_TYPE_CHECK); json_object_start(js, "error"); json_add_primitive_fmt(js, "code", "%d", code); json_add_string(js, "message", err); @@ -458,6 +460,10 @@ static struct command_result *command_complete(struct command *cmd, struct command_result *command_finished(struct command *cmd, struct json_stream *response) { + assert(cmd->type == COMMAND_TYPE_NORMAL + || cmd->type == COMMAND_TYPE_HOOK + || cmd->type == COMMAND_TYPE_CHECK); + /* Detach filter before it complains about closing object it never saw */ if (cmd->filter) { const char *err = json_stream_detach_filter(tmpctx, response); @@ -563,6 +569,8 @@ struct command_result *WARN_UNUSED_RESULT command_success(struct command *cmd, const struct json_out *result) { struct json_stream *js = jsonrpc_stream_start(cmd); + assert(cmd->type == COMMAND_TYPE_NORMAL + || cmd->type == COMMAND_TYPE_HOOK); json_out_add_splice(js->jout, "result", result); return command_complete(cmd, js); @@ -574,6 +582,8 @@ struct command_result *command_done_err(struct command *cmd, const struct json_out *data) { struct json_stream *js = jsonrpc_stream_start(cmd); + assert(cmd->type == COMMAND_TYPE_NORMAL + || cmd->type == COMMAND_TYPE_CHECK); json_object_start(js, "error"); json_add_jsonrpc_errcode(js, "code", code); @@ -589,6 +599,8 @@ struct command_result *command_done_err(struct command *cmd, struct command_result *command_err_raw(struct command *cmd, const char *json_str) { + assert(cmd->type == COMMAND_TYPE_NORMAL + || cmd->type == COMMAND_TYPE_CHECK); return command_done_raw(cmd, "error", json_str, strlen(json_str)); } @@ -636,7 +648,7 @@ struct command_result *command_fail(struct command *cmd, /* We invoke param for usage at registration time. */ bool command_usage_only(const struct command *cmd) { - return cmd->usage_only; + return cmd->type == COMMAND_TYPE_USAGE_ONLY; } bool command_dev_apis(const struct command *cmd) @@ -646,7 +658,7 @@ bool command_dev_apis(const struct command *cmd) bool command_check_only(const struct command *cmd) { - return cmd->check; + return cmd->type == COMMAND_TYPE_CHECK; } void command_log(struct command *cmd, enum log_level level, @@ -664,11 +676,13 @@ void command_log(struct command *cmd, enum log_level level, struct command_result *command_check_done(struct command *cmd) { + struct json_stream *js = jsonrpc_stream_start(cmd); assert(command_check_only(cmd)); - return command_success(cmd, - json_out_obj(cmd, "command_to_check", - cmd->methodname)); + json_out_add_splice(js->jout, "result", + json_out_obj(cmd, "command_to_check", + cmd->methodname)); + return command_complete(cmd, js); } void command_set_usage(struct command *cmd, const char *usage TAKES) @@ -1647,7 +1661,7 @@ static void setup_command_usage(struct plugin *p) { struct command *usage_cmd = new_command(tmpctx, p, "usage", "check-usage", - true, false); + COMMAND_TYPE_USAGE_ONLY); /* This is how common/param can tell it's just a usage request */ for (size_t i = 0; i < p->num_commands; i++) { @@ -1721,6 +1735,7 @@ struct json_stream *plugin_notification_start(struct plugin *plugin, json_object_start(js, "params"); return js; } + void plugin_notification_end(struct plugin *plugin, struct json_stream *stream) { @@ -1899,6 +1914,7 @@ static void ld_command_handle(struct plugin *plugin, const char *methodname; struct command *cmd; const char *id; + enum command_type type; methtok = json_get_member(plugin->buffer, toks, "method"); paramstok = json_get_member(plugin->buffer, toks, "params"); @@ -1913,10 +1929,17 @@ static void ld_command_handle(struct plugin *plugin, methodname = json_strdup(NULL, plugin->buffer, methtok); id = json_get_id(tmpctx, plugin->buffer, toks); + if (!id) + type = COMMAND_TYPE_NOTIFICATION; + else if (streq(methodname, "check")) + type = COMMAND_TYPE_CHECK; + else + type = COMMAND_TYPE_NORMAL; + cmd = new_command(plugin, plugin, id ? id : tal_fmt(tmpctx, "notification-%s", methodname), take(methodname), - false, streq(methodname, "check")); + type); if (!plugin->manifested) { if (streq(cmd->methodname, "getmanifest")) { @@ -1939,7 +1962,7 @@ static void ld_command_handle(struct plugin *plugin, } /* If that's a notification. */ - if (!id) { + if (cmd->type == COMMAND_TYPE_NOTIFICATION) { bool is_shutdown = streq(cmd->methodname, "shutdown"); if (is_shutdown && plugin->developer) memleak_check(plugin, cmd); @@ -1979,6 +2002,7 @@ static void ld_command_handle(struct plugin *plugin, for (size_t i = 0; i < plugin->num_hook_subs; i++) { if (streq(cmd->methodname, plugin->hook_subs[i].name)) { + cmd->type = COMMAND_TYPE_HOOK; plugin->hook_subs[i].handle(cmd, plugin->buffer, paramstok); @@ -1994,8 +2018,7 @@ static void ld_command_handle(struct plugin *plugin, } /* Is this actually a check command? */ - cmd->check = streq(cmd->methodname, "check"); - if (cmd->check) { + if (cmd->type == COMMAND_TYPE_CHECK) { const jsmntok_t *method; jsmntok_t *mod_params; @@ -2521,20 +2544,21 @@ struct command_result *WARN_UNUSED_RESULT command_hook_success(struct command *cmd) { struct json_stream *response = jsonrpc_stream_success(cmd); + assert(cmd->type == COMMAND_TYPE_HOOK); json_add_string(response, "result", "continue"); return command_finished(cmd, response); } struct command *aux_command(const struct command *cmd) { - assert(!cmd->check); return new_command(cmd->plugin, cmd->plugin, cmd->id, - cmd->methodname, false, false); + cmd->methodname, COMMAND_TYPE_AUX); } struct command_result *WARN_UNUSED_RESULT aux_command_done(struct command *cmd) { + assert(cmd->type == COMMAND_TYPE_AUX); tal_free(cmd); return &complete; } @@ -2542,6 +2566,7 @@ aux_command_done(struct command *cmd) struct command_result *WARN_UNUSED_RESULT notification_handled(struct command *cmd) { + assert(cmd->type == COMMAND_TYPE_NOTIFICATION); tal_free(cmd); return &complete; } diff --git a/plugins/libplugin.h b/plugins/libplugin.h index 7f50a4623c30..7633f0ed74bc 100644 --- a/plugins/libplugin.h +++ b/plugins/libplugin.h @@ -49,11 +49,25 @@ struct out_req { void *arg; }; +enum command_type { + /* Terminate with jsonrpc_stream_success/fail etc */ + COMMAND_TYPE_NORMAL, + /* Terminate with command_hook_success or command_success */ + COMMAND_TYPE_HOOK, + /* Terminate with aux_command_done */ + COMMAND_TYPE_AUX, + /* Terminate with notification_handled */ + COMMAND_TYPE_NOTIFICATION, + /* These self-terminate */ + COMMAND_TYPE_TIMER, + COMMAND_TYPE_CHECK, + COMMAND_TYPE_USAGE_ONLY, +}; + struct command { const char *id; const char *methodname; - bool usage_only; - bool check; + enum command_type type; struct plugin *plugin; /* Optional output field filter. */ struct json_filter *filter; From 56184acade48522590f93cebfb608ced61d88a31 Mon Sep 17 00:00:00 2001 From: Rusty Russell Date: Wed, 6 Nov 2024 21:22:36 +1030 Subject: [PATCH 05/18] libplugin: make timers have a "command" context. This is cleaner: everything can now be associated with a command context. You're supposed to eventually dispose of it using timer_complete(). Signed-off-by: Rusty Russell --- plugins/autoclean.c | 21 +++++++----- plugins/bcli.c | 7 ++-- plugins/fetchinvoice.c | 20 ++++++----- plugins/libplugin.c | 52 +++++++++++++++++++++-------- plugins/libplugin.h | 39 +++++++++++++++------- plugins/recover.c | 53 +++++++++++++++--------------- plugins/renepay/mods.c | 15 +++++---- plugins/spender/multifundchannel.c | 12 ++++--- 8 files changed, 136 insertions(+), 83 deletions(-) diff --git a/plugins/autoclean.c b/plugins/autoclean.c index f1e2e5198170..83c896db8863 100644 --- a/plugins/autoclean.c +++ b/plugins/autoclean.c @@ -206,7 +206,7 @@ static const struct subsystem_ops *get_subsystem_ops(const struct per_subsystem } /* Mutual recursion */ -static void do_clean_timer(void *unused); +static struct command_result *do_clean_timer(struct command *cmd, void *unused); static struct command_result *do_clean(struct clean_info *cinfo); static struct clean_info *new_clean_info(const tal_t *ctx, @@ -267,7 +267,7 @@ static struct command_result *clean_finished(struct clean_info *cinfo) } while (next_sv(&sv)); /* autoclean-once? */ - if (cinfo->cmd) { + if (cinfo != timer_cinfo) { struct json_stream *response = jsonrpc_stream_success(cinfo->cmd); json_object_start(response, "autoclean"); @@ -287,9 +287,10 @@ static struct command_result *clean_finished(struct clean_info *cinfo) return command_finished(cinfo->cmd, response); } else { /* timer */ plugin_log(plugin, LOG_DBG, "setting next timer"); - cleantimer = plugin_timer(plugin, time_from_sec(cycle_seconds), + cleantimer = global_timer(plugin, + time_from_sec(cycle_seconds), do_clean_timer, NULL); - return timer_complete(plugin); + return timer_complete(cinfo->cmd); } } @@ -554,7 +555,7 @@ static struct command_result *do_clean(struct clean_info *cinfo) filter = tal_fmt(tmpctx, "{\"%s\":[{%s}]}", ops->arr_name, ops->list_filter); - req = jsonrpc_request_with_filter_start(plugin, NULL, + req = jsonrpc_request_with_filter_start(plugin, cinfo->cmd, tal_fmt(tmpctx, "list%s", ops->system_name), @@ -641,11 +642,12 @@ static struct command_result *start_clean(struct clean_info *cinfo) } /* Needs a different signature than do_clean */ -static void do_clean_timer(void *unused) +static struct command_result *do_clean_timer(struct command *cmd, void *unused) { assert(timer_cinfo->cleanup_reqs_remaining == 0); cleantimer = NULL; - start_clean(timer_cinfo); + timer_cinfo->cmd = cmd; + return start_clean(timer_cinfo); } static struct command_result *param_subsystem(struct command *cmd, @@ -750,7 +752,7 @@ static const char *init(struct plugin *p, tal_steal(plugin, timer_cinfo); plugin_set_memleak_handler(plugin, memleak_mark_timer_cinfo); - cleantimer = plugin_timer(p, time_from_sec(cycle_seconds), do_clean_timer, NULL); + cleantimer = global_timer(p, time_from_sec(cycle_seconds), do_clean_timer, NULL); /* We don't care if this fails (it usually does, since entries * don't exist! */ @@ -777,7 +779,8 @@ static char *cycle_seconds_option(struct plugin *plugin, const char *arg, /* If timer is not running right now, reset it to new cycle_seconds */ if (cleantimer) { tal_free(cleantimer); - cleantimer = plugin_timer(plugin, time_from_sec(*cycle_seconds), + cleantimer = global_timer(plugin, + time_from_sec(*cycle_seconds), do_clean_timer, NULL); } return NULL; diff --git a/plugins/bcli.c b/plugins/bcli.c index 9e2f1eff2c6e..1bb0226a9f74 100644 --- a/plugins/bcli.c +++ b/plugins/bcli.c @@ -199,15 +199,16 @@ static void destroy_bcli(struct bitcoin_cli *bcli) list_del_from(&bitcoind->current, &bcli->list); } -static void retry_bcli(void *cb_arg) +static struct command_result *retry_bcli(struct command *cmd, + struct bitcoin_cli *bcli) { - struct bitcoin_cli *bcli = cb_arg; list_del_from(&bitcoind->current, &bcli->list); tal_del_destructor(bcli, destroy_bcli); list_add_tail(&bitcoind->pending[bcli->prio], &bcli->list); tal_free(bcli->output); next_bcli(bcli->prio); + return timer_complete(cmd); } /* We allow 60 seconds of spurious errors, eg. reorg. */ @@ -238,7 +239,7 @@ static void bcli_failure(struct bitcoin_cli *bcli, bitcoind->error_count++; /* Retry in 1 second */ - plugin_timer(bcli->cmd->plugin, time_from_sec(1), retry_bcli, bcli); + command_timer(bcli->cmd, time_from_sec(1), retry_bcli, bcli); } static void bcli_finished(struct io_conn *conn UNUSED, struct bitcoin_cli *bcli) diff --git a/plugins/fetchinvoice.c b/plugins/fetchinvoice.c index 8e49de23ef33..2ca652d81a25 100644 --- a/plugins/fetchinvoice.c +++ b/plugins/fetchinvoice.c @@ -397,11 +397,13 @@ static void destroy_sent(struct sent *sent) } /* We've received neither a reply nor a payment; return failure. */ -static void timeout_sent_invreq(struct sent *sent) +static struct command_result *timeout_sent_invreq(struct command *timer_cmd, + struct sent *sent) { /* This will free sent! */ discard_result(command_fail(sent->cmd, OFFER_TIMEOUT, "Timeout waiting for response")); + return timer_complete(timer_cmd); } static struct command_result *sendonionmsg_done(struct command *cmd, @@ -409,9 +411,9 @@ static struct command_result *sendonionmsg_done(struct command *cmd, const jsmntok_t *result UNUSED, struct sent *sent) { - tal_steal(cmd, plugin_timer(cmd->plugin, - time_from_sec(sent->wait_timeout), - timeout_sent_invreq, sent)); + command_timer(cmd, + time_from_sec(sent->wait_timeout), + timeout_sent_invreq, sent); return command_still_pending(cmd); } @@ -618,7 +620,8 @@ static struct command_result *send_message(struct command *cmd, } /* We've received neither a reply nor a payment; return failure. */ -static void timeout_sent_inv(struct sent *sent) +static struct command_result *timeout_sent_inv(struct command *timer_cmd, + struct sent *sent) { struct json_out *details = json_out_new(sent); @@ -630,6 +633,7 @@ static void timeout_sent_inv(struct sent *sent) discard_result(command_done_err(sent->cmd, OFFER_TIMEOUT, "Failed: timeout waiting for response", details)); + return timer_complete(timer_cmd); } static struct command_result *prepare_inv_timeout(struct command *cmd, @@ -637,9 +641,9 @@ static struct command_result *prepare_inv_timeout(struct command *cmd, const jsmntok_t *result UNUSED, struct sent *sent) { - tal_steal(cmd, plugin_timer(cmd->plugin, - time_from_sec(sent->wait_timeout), - timeout_sent_inv, sent)); + command_timer(cmd, + time_from_sec(sent->wait_timeout), + timeout_sent_inv, sent); return sendonionmsg_done(cmd, buf, result, sent); } diff --git a/plugins/libplugin.c b/plugins/libplugin.c index 77fee44e2197..20f0ecdecebc 100644 --- a/plugins/libplugin.c +++ b/plugins/libplugin.c @@ -25,7 +25,8 @@ struct plugin_timer { struct timer timer; - void (*cb)(void *cb_arg); + const char *id; + struct command_result *(*cb)(struct command *cmd, void *cb_arg); void *cb_arg; }; @@ -133,7 +134,6 @@ struct plugin { STRMAP(const char *) usagemap; /* Timers */ struct timers timers; - size_t in_timer; /* Feature set for lightningd */ struct feature_set *our_features; @@ -605,10 +605,10 @@ struct command_result *command_err_raw(struct command *cmd, json_str, strlen(json_str)); } -struct command_result *timer_complete(struct plugin *p) +struct command_result *timer_complete(struct command *cmd) { - assert(p->in_timer > 0); - p->in_timer--; + assert(cmd->type == COMMAND_TYPE_TIMER); + tal_free(cmd); return &complete; } @@ -1677,11 +1677,14 @@ static void setup_command_usage(struct plugin *p) static void call_plugin_timer(struct plugin *p, struct timer *timer) { struct plugin_timer *t = container_of(timer, struct plugin_timer, timer); + struct command *timer_cmd; + struct command_result *res; - p->in_timer++; - /* Free this if they don't. */ - tal_steal(tmpctx, t); - t->cb(t->cb_arg); + /* This *isn't* owned by timer, which is owned by original command, + * since they may free that in callback */ + timer_cmd = new_command(p, p, t->id, "timer", COMMAND_TYPE_TIMER); + res = t->cb(timer_cmd, t->cb_arg); + assert(res == &pending || res == &complete); } static void destroy_plugin_timer(struct plugin_timer *timer, struct plugin *p) @@ -1689,11 +1692,15 @@ static void destroy_plugin_timer(struct plugin_timer *timer, struct plugin *p) timer_del(&p->timers, &timer->timer); } -struct plugin_timer *plugin_timer_(struct plugin *p, struct timerel t, - void (*cb)(void *cb_arg), - void *cb_arg) +static struct plugin_timer *new_timer(const tal_t *ctx, + struct plugin *p, + const char *id TAKES, + struct timerel t, + struct command_result *(*cb)(struct command *, void *), + void *cb_arg) { - struct plugin_timer *timer = notleak(tal(NULL, struct plugin_timer)); + struct plugin_timer *timer = notleak(tal(ctx, struct plugin_timer)); + timer->id = tal_strdup(timer, id); timer->cb = cb; timer->cb_arg = cb_arg; timer_init(&timer->timer); @@ -1702,6 +1709,24 @@ struct plugin_timer *plugin_timer_(struct plugin *p, struct timerel t, return timer; } +struct plugin_timer *global_timer_(struct plugin *p, + struct timerel t, + struct command_result *(*cb)(struct command *cmd, void *cb_arg), + void *cb_arg) +{ + return new_timer(p, p, "timer", t, cb, cb_arg); +} + +struct plugin_timer *command_timer_(struct command *cmd, + struct timerel t, + struct command_result *(*cb)(struct command *cmd, void *cb_arg), + void *cb_arg) +{ + return new_timer(cmd, cmd->plugin, + take(tal_fmt(NULL, "%s-timer", cmd->id)), + t, cb, cb_arg); +} + void plugin_logv(struct plugin *p, enum log_level l, const char *fmt, va_list ap) { @@ -2280,7 +2305,6 @@ static struct plugin *new_plugin(const tal_t *ctx, p->manifested = p->initialized = p->exiting = false; p->restartability = restartability; strmap_init(&p->usagemap); - p->in_timer = 0; p->commands = commands; if (taken(commands)) diff --git a/plugins/libplugin.h b/plugins/libplugin.h index 7633f0ed74bc..4a1f1be26655 100644 --- a/plugins/libplugin.h +++ b/plugins/libplugin.h @@ -433,27 +433,42 @@ struct command_result *forward_result(struct command *cmd, /* Callback for timer where we expect a 'command_result'. All timers * must return this eventually, though they may do so via a convoluted * send_req() path. */ -struct command_result *timer_complete(struct plugin *p); +struct command_result *timer_complete(struct command *cmd); /* Signals that we've completed a command. Useful for when - * there's no `cmd` present */ + * there's no `cmd` present. Deprecated! */ struct command_result *command_done(void); -/* Access timer infrastructure to add a timer. +/* Access timer infrastructure to add a global timer for the plugin. * - * Freeing this releases the timer, otherwise it's freed after @cb - * if it hasn't been freed already. + * This is a timer with the same lifetime as the plugin. */ -struct plugin_timer *plugin_timer_(struct plugin *p, +struct plugin_timer *global_timer_(struct plugin *p, struct timerel t, - void (*cb)(void *cb_arg), + struct command_result *(*cb)(struct command *cmd, void *cb_arg), void *cb_arg); -#define plugin_timer(plugin, time, cb, cb_arg) \ - plugin_timer_((plugin), (time), \ - typesafe_cb(void, void *, \ - (cb), (cb_arg)), \ - (cb_arg)) \ +#define global_timer(plugin, time, cb, cb_arg) \ + global_timer_((plugin), (time), \ + typesafe_cb_preargs(struct command_result *, \ + void *, \ + (cb), (cb_arg), \ + struct command *), \ + (cb_arg)) \ + +/* Timer based off specific cmd */ +struct plugin_timer *command_timer_(struct command *cmd, + struct timerel t, + struct command_result *(*cb)(struct command *cmd, void *cb_arg), + void *cb_arg); + +#define command_timer(cmd, time, cb, cb_arg) \ + command_timer_((cmd), (time), \ + typesafe_cb_preargs(struct command_result *, \ + void *, \ + (cb), (cb_arg), \ + struct command *), \ + (cb_arg)) \ /* Log something */ void plugin_log(struct plugin *p, enum log_level l, const char *fmt, ...) PRINTF_FMT(3, 4); diff --git a/plugins/recover.c b/plugins/recover.c index b46d55dc74ea..052de006f94f 100644 --- a/plugins/recover.c +++ b/plugins/recover.c @@ -28,9 +28,9 @@ static struct plugin_timer *lost_state_timer, *find_exes_timer, *peer_storage_ti /* This tells if we are already in the process of recovery. */ static bool recovery, already_has_peers; -static void do_check_lost_peer (void *unused); -static void do_check_gossip (struct command *cmd); -static void do_find_peer_storage (struct command *cmd); +static struct command_result *do_check_lost_peer (struct command *cmd, void *unused); +static struct command_result *do_check_gossip (struct command *cmd, void *unused); +static struct command_result *do_find_peer_storage (struct command *cmd, void *unused); static struct node_id local_id; /* List of most connected nodes on the network */ @@ -84,9 +84,10 @@ static struct command_result *after_restorefrompeer(struct command *cmd, plugin_log(plugin, LOG_DBG, "restorefrompeer called"); peer_storage_timer = - plugin_timer(plugin, time_from_sec(CHECK_STORAGE_INTERVAL), - do_find_peer_storage, cmd); - return command_still_pending(cmd); + global_timer(plugin, + time_from_sec(CHECK_STORAGE_INTERVAL), + do_find_peer_storage, NULL); + return timer_complete(cmd); } static struct command_result *find_peer_storage (struct command *cmd) @@ -101,14 +102,13 @@ static struct command_result *find_peer_storage (struct command *cmd) return send_outreq(plugin, req); } -static void do_find_peer_storage (struct command *cmd) +static struct command_result *do_find_peer_storage(struct command *cmd, void *unused) { - find_peer_storage(cmd); - return; + return find_peer_storage(cmd); } -static void do_check_gossip (struct command *cmd) +static struct command_result *do_check_gossip(struct command *cmd, void *unused) { find_exes_timer = NULL; @@ -144,14 +144,15 @@ static void do_check_gossip (struct command *cmd) } peer_storage_timer = - plugin_timer(plugin, time_from_sec(CHECK_STORAGE_INTERVAL), - do_find_peer_storage, cmd); - return; + global_timer(plugin, + time_from_sec(CHECK_STORAGE_INTERVAL), + do_find_peer_storage, NULL); + return timer_complete(cmd); } - find_exes_timer = plugin_timer( - plugin, time_from_sec(CHECK_PEER_INTERVAL), do_check_gossip, cmd); - return; + find_exes_timer = global_timer( + plugin, time_from_sec(CHECK_PEER_INTERVAL), do_check_gossip, NULL); + return timer_complete(cmd); } static void entering_recovery_mode(struct command *cmd) @@ -182,7 +183,7 @@ static void entering_recovery_mode(struct command *cmd) NULL); send_outreq(plugin, req_emer_recovery); - find_exes_timer = plugin_timer( + find_exes_timer = global_timer( plugin, time_from_sec(CHECK_GOSSIP_INTERVAL), do_check_gossip, cmd); return; } @@ -216,32 +217,32 @@ static struct command_result *after_listpeerchannels(struct command *cmd, } lost_state_timer = - plugin_timer(plugin, time_from_sec(CHECK_PEER_INTERVAL), + global_timer(plugin, time_from_sec(CHECK_PEER_INTERVAL), do_check_lost_peer, NULL); return command_still_pending(cmd); } -static struct command_result *check_lost_peer(void *unused) +static struct command_result *check_lost_peer(struct command *cmd) { struct out_req *req; - req = jsonrpc_request_start(plugin, NULL, "listpeerchannels", - after_listpeerchannels, - &forward_error, NULL); + req = jsonrpc_request_start(plugin, cmd, "listpeerchannels", + after_listpeerchannels, + &forward_error, NULL); return send_outreq(plugin, req); } -static void do_check_lost_peer (void *unused) +static struct command_result *do_check_lost_peer(struct command *cmd, void *unused) { /* Set to NULL when already in progress. */ lost_state_timer = NULL; if (recovery) { - return; + return timer_complete(cmd); } - check_lost_peer(unused); + return check_lost_peer(cmd); } static const char *init(struct plugin *p, @@ -251,7 +252,7 @@ static const char *init(struct plugin *p, plugin = p; plugin_log(p, LOG_DBG, "Recover Plugin Initialised!"); recovery = false; - lost_state_timer = plugin_timer(plugin, time_from_sec(STARTUP_TIME), + lost_state_timer = global_timer(plugin, time_from_sec(STARTUP_TIME), do_check_lost_peer, NULL); u32 num_peers; size_t num_cupdates_rejected; diff --git a/plugins/renepay/mods.c b/plugins/renepay/mods.c index 3d410cbce0d5..f5e232eea0f8 100644 --- a/plugins/renepay/mods.c +++ b/plugins/renepay/mods.c @@ -771,21 +771,24 @@ REGISTER_PAYMENT_MODIFIER(send_routes, send_routes_cb); * The payment main thread sleeps for some time. */ -static void sleep_done(struct payment *payment) +static struct command_result *sleep_done(struct command *cmd, struct payment *payment) { + struct command_result *ret; payment->waitresult_timer = NULL; - // TODO: is this compulsory? - timer_complete(pay_plugin->plugin); + ret = timer_complete(cmd); payment_continue(payment); + return ret; } static struct command_result *sleep_cb(struct payment *payment) { - assert(payment->waitresult_timer == NULL); - payment->waitresult_timer = plugin_timer( - pay_plugin->plugin, time_from_msec(COLLECTOR_TIME_WINDOW_MSEC), sleep_done, payment); struct command *cmd = payment_command(payment); assert(cmd); + assert(payment->waitresult_timer == NULL); + payment->waitresult_timer + = command_timer(cmd, + time_from_msec(COLLECTOR_TIME_WINDOW_MSEC), + sleep_done, payment); return command_still_pending(cmd); } diff --git a/plugins/spender/multifundchannel.c b/plugins/spender/multifundchannel.c index 4a06ad177ab5..a2eaf8113607 100644 --- a/plugins/spender/multifundchannel.c +++ b/plugins/spender/multifundchannel.c @@ -1649,10 +1649,12 @@ perform_multiconnect(struct multifundchannel_command *mfc) /* Initiate the multifundchannel execution. */ -static void -perform_multifundchannel(struct multifundchannel_command *mfc) +static struct command_result * +perform_multifundchannel(struct command *timer_cmd, + struct multifundchannel_command *mfc) { perform_multiconnect(mfc); + return timer_complete(timer_cmd); } @@ -1778,8 +1780,8 @@ post_cleanup_redo_multifundchannel(struct multifundchannel_redo *redo) /* Okay, we still have destinations to try: wait a second in case it * takes that long to disconnect from peer, then retry. */ - plugin_timer(mfc->cmd->plugin, time_from_sec(1), - perform_multifundchannel, mfc); + command_timer(mfc->cmd, time_from_sec(1), + perform_multifundchannel, mfc); return command_still_pending(mfc->cmd); } @@ -2011,7 +2013,7 @@ json_multifundchannel(struct command *cmd, mfc->sigs_collected = false; - perform_multifundchannel(mfc); + perform_multiconnect(mfc); return command_still_pending(mfc->cmd); } From 9a441b61a4155e9b15ba9c57c892ff2f6ed0c53f Mon Sep 17 00:00:00 2001 From: Rusty Russell Date: Wed, 6 Nov 2024 21:23:36 +1030 Subject: [PATCH 06/18] commando: always use proper responses for commands. All `struct command` should be terminated properly. Signed-off-by: Rusty Russell --- plugins/commando.c | 109 ++++++++++++++++++++++----------------------- 1 file changed, 54 insertions(+), 55 deletions(-) diff --git a/plugins/commando.c b/plugins/commando.c index aede4c35b634..ab8d056b75a0 100644 --- a/plugins/commando.c +++ b/plugins/commando.c @@ -32,6 +32,7 @@ enum commando_msgtype { }; struct commando { + /* Only non-NULL for outgoing cmds */ struct command *cmd; struct node_id peer; u64 id; @@ -116,7 +117,7 @@ struct reply { }; /* Calls itself repeatedly: first time, result is NULL */ -static struct command_result *send_response(struct command *command UNUSED, +static struct command_result *send_response(struct command *cmd, const char *buf UNUSED, const jsmntok_t *result, struct reply *reply) @@ -133,7 +134,7 @@ static struct command_result *send_response(struct command *command UNUSED, } else { if (msglen == 0) { tal_free(reply); - return command_done(); + return command_hook_success(cmd); } msgtype = COMMANDO_MSG_REPLY_TERM; } @@ -144,7 +145,7 @@ static struct command_result *send_response(struct command *command UNUSED, towire(&cmd_msg, reply->buf + reply->off, msglen); reply->off += msglen; - req = jsonrpc_request_start(plugin, NULL, "sendcustommsg", + req = jsonrpc_request_start(plugin, cmd, "sendcustommsg", send_response, send_response, reply); json_add_node_id(req->js, "node_id", &reply->incoming->peer); @@ -152,7 +153,7 @@ static struct command_result *send_response(struct command *command UNUSED, tal_free(cmd_msg); send_outreq(plugin, req); - return command_done(); + return command_still_pending(cmd); } static struct command_result *cmd_done(struct command *command, @@ -192,14 +193,16 @@ static struct command_result *cmd_done(struct command *command, return send_response(command, NULL, NULL, reply); } -static void commando_error(struct commando *incoming, - int ecode, - const char *fmt, ...) - PRINTF_FMT(3,4); +static struct command_result *commando_error(struct command *cmd, + struct commando *incoming, + int ecode, + const char *fmt, ...) + PRINTF_FMT(4, 5); -static void commando_error(struct commando *incoming, - int ecode, - const char *fmt, ...) +static struct command_result *commando_error(struct command *cmd, + struct commando *incoming, + int ecode, + const char *fmt, ...) { struct reply *reply = tal(plugin, struct reply); va_list ap; @@ -213,7 +216,7 @@ static void commando_error(struct commando *incoming, reply->off = 0; reply->len = tal_bytelen(reply->buf) - 1; - send_response(NULL, NULL, NULL, reply); + return send_response(cmd, NULL, NULL, reply); } struct cond_info { @@ -270,12 +273,13 @@ static struct cond_info *new_cond_info(const tal_t *ctx, return cinfo; } -static struct command_result *execute_command(struct cond_info *cinfo) +static struct command_result *execute_command(struct command *cmd, + struct cond_info *cinfo) { struct out_req *req; /* We handle success and failure the same */ - req = jsonrpc_request_whole_object_start(plugin, NULL, + req = jsonrpc_request_whole_object_start(plugin, cmd, json_strdup(tmpctx, cinfo->buf, cinfo->method), cinfo->cmdid_prefix, cmd_done, cinfo->incoming); @@ -336,12 +340,12 @@ static struct command_result *checkrune_done(struct command *cmd, /* Shouldn't happen! */ if (!valid) { - commando_error(cinfo->incoming, COMMANDO_ERROR_REMOTE, - "Invalid rune"); - return command_done(); + return commando_error(cmd, cinfo->incoming, + COMMANDO_ERROR_REMOTE, + "Invalid rune"); } - return execute_command(cinfo); + return execute_command(cmd, cinfo); } static struct command_result *checkrune_failed(struct command *cmd, @@ -357,13 +361,14 @@ static struct command_result *checkrune_failed(struct command *cmd, json_tok_full(buf, result)); } - commando_error(cinfo->incoming, COMMANDO_ERROR_REMOTE_AUTH, - "Invalid rune: %.*s", - msg->end - msg->start, buf + msg->start); - return command_done(); + return commando_error(cmd, cinfo->incoming, + COMMANDO_ERROR_REMOTE_AUTH, + "Invalid rune: %.*s", + msg->end - msg->start, buf + msg->start); } -static void try_command(struct commando *incoming STEALS) +static struct command_result *try_command(struct command *cmd, + struct commando *incoming STEALS) { const jsmntok_t *toks, *method, *params, *runetok, *id, *filter; const char *buf = (const char *)incoming->contents; @@ -373,45 +378,40 @@ static void try_command(struct commando *incoming STEALS) toks = json_parse_simple(incoming, buf, tal_bytelen(buf)); if (!toks) { - commando_error(incoming, COMMANDO_ERROR_REMOTE, - "Invalid JSON"); - return; + return commando_error(cmd, incoming, COMMANDO_ERROR_REMOTE, + "Invalid JSON"); } if (toks[0].type != JSMN_OBJECT) { - commando_error(incoming, COMMANDO_ERROR_REMOTE, - "Not a JSON object"); - return; + return commando_error(cmd, incoming, COMMANDO_ERROR_REMOTE, + "Not a JSON object"); } method = json_get_member(buf, toks, "method"); if (!method) { - commando_error(incoming, COMMANDO_ERROR_REMOTE, - "No method"); - return; + return commando_error(cmd, incoming, COMMANDO_ERROR_REMOTE, + "No method"); } params = json_get_member(buf, toks, "params"); if (params && (params->type != JSMN_OBJECT && params->type != JSMN_ARRAY)) { - commando_error(incoming, COMMANDO_ERROR_REMOTE, - "Params must be object or array"); - return; + return commando_error(cmd, incoming, COMMANDO_ERROR_REMOTE, + "Params must be object or array"); } filter = json_get_member(buf, toks, "filter"); id = json_get_member(buf, toks, "id"); if (!id) { - commando_error(incoming, COMMANDO_ERROR_REMOTE, - "missing id field"); - return; + return commando_error(cmd, incoming, COMMANDO_ERROR_REMOTE, + "missing id field"); } runetok = json_get_member(buf, toks, "rune"); if (!runetok) { - commando_error(incoming, COMMANDO_ERROR_REMOTE, "Missing rune"); - return; + return commando_error(cmd, incoming, COMMANDO_ERROR_REMOTE, + "Missing rune"); } rune = rune_from_base64n(tmpctx, buf + runetok->start, runetok->end - runetok->start); if (!rune) { - commando_error(incoming, COMMANDO_ERROR_REMOTE, "Invalid rune"); - return; + return commando_error(cmd, incoming, COMMANDO_ERROR_REMOTE, + "Invalid rune"); } /* Gather all the info we need to execute this command (steals toks). */ cinfo = new_cond_info(incoming, incoming, toks, method, params, id, filter); @@ -420,7 +420,7 @@ static void try_command(struct commando *incoming STEALS) destroy_commando(incoming, &incoming_commands); tal_del_destructor2(incoming, destroy_commando, &incoming_commands); - req = jsonrpc_request_start(plugin, NULL, "checkrune", + req = jsonrpc_request_start(plugin, cmd, "checkrune", checkrune_done, checkrune_failed, cinfo); json_add_node_id(req->js, "nodeid", &incoming->peer); @@ -428,14 +428,14 @@ static void try_command(struct commando *incoming STEALS) json_add_tok(req->js, "method", method, cinfo->buf); if (params) json_add_tok(req->js, "params", params, cinfo->buf); - send_outreq(plugin, req); + return send_outreq(plugin, req); } -static void handle_incmd(struct command *cmd, - struct node_id *peer, - u64 idnum, - const u8 *msg, size_t msglen, - bool terminal) +static struct command_result *handle_incmd(struct command *cmd, + struct node_id *peer, + u64 idnum, + const u8 *msg, size_t msglen, + bool terminal) { struct commando *incmd; @@ -462,15 +462,15 @@ static void handle_incmd(struct command *cmd, append_contents(incmd, msg, msglen, 1024*1024); if (!terminal) - return; + return command_hook_success(cmd); if (!incmd->contents) { plugin_log(plugin, LOG_UNUSUAL, "%s: ignoring oversize request", fmt_node_id(tmpctx, peer)); - return; + return command_hook_success(cmd); } - try_command(incmd); + return try_command(cmd, incmd); } static struct command_result *handle_reply(struct node_id *peer, @@ -592,9 +592,8 @@ static struct command_result *handle_custommsg(struct command *cmd, switch (mtype) { case COMMANDO_MSG_CMD_CONTINUES: case COMMANDO_MSG_CMD_TERM: - handle_incmd(cmd, &peer, idnum, msg, len, - mtype == COMMANDO_MSG_CMD_TERM); - break; + return handle_incmd(cmd, &peer, idnum, msg, len, + mtype == COMMANDO_MSG_CMD_TERM); case COMMANDO_MSG_REPLY_CONTINUES: case COMMANDO_MSG_REPLY_TERM: handle_reply(&peer, idnum, msg, len, From 6c563a9d9d9224b63c0931be13a1d7503c97f146 Mon Sep 17 00:00:00 2001 From: Rusty Russell Date: Wed, 6 Nov 2024 21:24:36 +1030 Subject: [PATCH 07/18] funder: use auxilliary command instead of NULL command. Signed-off-by: Rusty Russell --- plugins/funder.c | 26 ++++++++++++++++---------- 1 file changed, 16 insertions(+), 10 deletions(-) diff --git a/plugins/funder.c b/plugins/funder.c index fc9a5a4f62f5..b12707f92588 100644 --- a/plugins/funder.c +++ b/plugins/funder.c @@ -73,7 +73,7 @@ new_channel_open(const tal_t *ctx, } static struct command_result * -unreserve_done(struct command *cmd UNUSED, +unreserve_done(struct command *aux_cmd, const char *buf, const jsmntok_t *result, struct pending_open *open) @@ -84,21 +84,24 @@ unreserve_done(struct command *cmd UNUSED, json_tok_full_len(result), json_tok_full(buf, result)); - tal_free(open); - return command_done(); + return aux_command_done(aux_cmd); } /* Frees open (eventually, in unreserve_done callback) */ -static void unreserve_psbt(struct pending_open *open) +static struct command_result *unreserve_psbt(struct command *cmd, + struct pending_open *open) { struct out_req *req; + struct command *aux; plugin_log(open->p, LOG_DBG, "Calling `unreserveinputs` for channel %s", fmt_channel_id(tmpctx, &open->channel_id)); - req = jsonrpc_request_start(open->p, NULL, + /* This can outlive the underlying cmd, so use an aux! */ + aux = aux_command(cmd); + req = jsonrpc_request_start(open->p, aux, "unreserveinputs", unreserve_done, unreserve_done, open); @@ -108,15 +111,18 @@ static void unreserve_psbt(struct pending_open *open) /* We will free this in callback, but remove from list *now* * to avoid calling twice! */ list_del_from(&pending_opens, &open->list); - notleak(open); + tal_steal(aux, open); + + return command_still_pending(aux); } -static void cleanup_peer_pending_opens(const struct node_id *id) +static void cleanup_peer_pending_opens(struct command *cmd, + const struct node_id *id) { struct pending_open *i, *next; list_for_each_safe(&pending_opens, i, next, list) { if (node_id_eq(&i->peer_id, id)) { - unreserve_psbt(i); + unreserve_psbt(cmd, i); } } } @@ -1088,7 +1094,7 @@ static struct command_result *json_disconnect(struct command *cmd, "Cleaning up inflights for peer id %s", fmt_node_id(tmpctx, &id)); - cleanup_peer_pending_opens(&id); + cleanup_peer_pending_opens(cmd, &id); return notification_handled(cmd); } @@ -1176,7 +1182,7 @@ static struct command_result *json_channel_open_failed(struct command *cmd, open = find_channel_pending_open(&cid); if (open) - unreserve_psbt(open); + unreserve_psbt(cmd, open); /* Also clean up datastore for this channel */ return delete_channel_from_datastore(cmd, &cid); From ddab665fcf5cf588a998f7b17656f22d50e08e31 Mon Sep 17 00:00:00 2001 From: Rusty Russell Date: Wed, 6 Nov 2024 21:25:36 +1030 Subject: [PATCH 08/18] libplugin: reindent. This does not code changes, but makes the next changes easier. We short-cut the "we are a child" case and de-indent the main cases. Signed-off-by: Rusty Russell --- plugins/libplugin-pay.c | 223 +++++++++++++++++++--------------------- 1 file changed, 103 insertions(+), 120 deletions(-) diff --git a/plugins/libplugin-pay.c b/plugins/libplugin-pay.c index 14a250926c16..24b448ddc6c2 100644 --- a/plugins/libplugin-pay.c +++ b/plugins/libplugin-pay.c @@ -2156,134 +2156,117 @@ static void payment_finished(struct payment *p) assert((result.leafstates & PAYMENT_STEP_SUCCESS) == 0 || result.preimage != NULL); - if (p->parent == NULL) { - /* We are about to reply, unset the pointer to the cmd so we - * don't attempt to return a response twice. */ - p->cmd = NULL; - if (cmd == NULL) { - /* This is the tree root, but we already reported - * success or failure, so noop. */ - return; - } else if (payment_is_success(p)) { - assert(result.treestates & PAYMENT_STEP_SUCCESS); - assert(result.leafstates & PAYMENT_STEP_SUCCESS); - assert(result.preimage != NULL); - - /* Call any callback we might have registered. */ - if (p->on_payment_success != NULL) - p->on_payment_success(p); - - ret = jsonrpc_stream_success(cmd); - json_add_payment_success(ret, p, result.preimage, - &result); - - if (command_finished(cmd, ret)) {/* Ignore result. */} - p->cmd = NULL; - return; - } else if (p->aborterror != NULL) { - /* We set an explicit toplevel error message, - * so let's report that. */ - ret = jsonrpc_stream_fail(cmd, p->errorcode, - p->aborterror); - payment_json_add_attempts(ret, "attempts", p); - - payment_notify_failure(p, p->aborterror); - - if (command_finished(cmd, ret)) {/* Ignore result. */} - p->cmd = NULL; - return; - } else if (result.failure == NULL || result.failure->failcode < NODE) { - if (p->on_payment_failure != NULL) - p->on_payment_failure(p); - - /* This is failing because we have no more routes to try */ - msg = tal_fmt(cmd, - "Ran out of routes to try after " - "%d attempt%s: see `paystatus`", - result.attempts, - result.attempts == 1 ? "" : "s"); - ret = jsonrpc_stream_fail(cmd, PAY_STOPPED_RETRYING, - msg); - payment_json_add_attempts(ret, "attempts", p); - - payment_notify_failure(p, msg); - - if (command_finished(cmd, ret)) {/* Ignore result. */} - p->cmd = NULL; - return; - - } else { - struct payment_result *failure = result.failure; - assert(failure!= NULL); - if (p->on_payment_failure != NULL) - p->on_payment_failure(p); - ret = jsonrpc_stream_fail(cmd, failure->code, - failure->message); - - json_add_u64(ret, "id", failure->id); - - json_add_u32(ret, "failcode", failure->failcode); - if (failure->failcodename) - json_add_string(ret, "failcodename", - failure->failcodename); - - if (p->invstring) - json_add_invstring(ret, p->invstring); - - json_add_hex_talarr(ret, "raw_message", - result.failure->raw_message); - json_add_num(ret, "created_at", p->start_time.ts.tv_sec); - json_add_node_id(ret, "destination", p->pay_destination); - json_add_sha256(ret, "payment_hash", p->payment_hash); - - if (result.leafstates & PAYMENT_STEP_SUCCESS) { - /* If one sub-payment succeeded then we have - * proof of payment, and the payment is a - * success. */ - json_add_string(ret, "status", "complete"); - - } else if (result.leafstates & ~PAYMENT_STEP_FAILED) { - /* If there are non-failed leafs we are still trying. */ - json_add_string(ret, "status", "pending"); - - } else { - json_add_string(ret, "status", "failed"); - } - - json_add_amount_msat(ret, "amount_msat", p->our_amount); - json_add_amount_msat(ret, "amount_sent_msat", - result.sent); + if (p->parent != NULL) + return payment_child_finished(p->parent, p); + + /* We are about to reply, unset the pointer to the cmd so we + * don't attempt to return a response twice. */ + p->cmd = NULL; + if (cmd == NULL) { + /* This is the tree root, but we already reported + * success or failure, so noop. */ + return; + } else if (payment_is_success(p)) { + assert(result.treestates & PAYMENT_STEP_SUCCESS); + assert(result.leafstates & PAYMENT_STEP_SUCCESS); + assert(result.preimage != NULL); + + /* Call any callback we might have registered. */ + if (p->on_payment_success != NULL) + p->on_payment_success(p); + + ret = jsonrpc_stream_success(cmd); + json_add_payment_success(ret, p, result.preimage, + &result); + } else if (p->aborterror != NULL) { + /* We set an explicit toplevel error message, + * so let's report that. */ + ret = jsonrpc_stream_fail(cmd, p->errorcode, + p->aborterror); + payment_json_add_attempts(ret, "attempts", p); + + payment_notify_failure(p, p->aborterror); + } else if (result.failure == NULL || result.failure->failcode < NODE) { + if (p->on_payment_failure != NULL) + p->on_payment_failure(p); + + /* This is failing because we have no more routes to try */ + msg = tal_fmt(cmd, + "Ran out of routes to try after " + "%d attempt%s: see `paystatus`", + result.attempts, + result.attempts == 1 ? "" : "s"); + ret = jsonrpc_stream_fail(cmd, PAY_STOPPED_RETRYING, + msg); + payment_json_add_attempts(ret, "attempts", p); + + payment_notify_failure(p, msg); + } else { + struct payment_result *failure = result.failure; + assert(failure!= NULL); + if (p->on_payment_failure != NULL) + p->on_payment_failure(p); + ret = jsonrpc_stream_fail(cmd, failure->code, + failure->message); + + json_add_u64(ret, "id", failure->id); + + json_add_u32(ret, "failcode", failure->failcode); + if (failure->failcodename) + json_add_string(ret, "failcodename", + failure->failcodename); + + if (p->invstring) + json_add_invstring(ret, p->invstring); + + json_add_hex_talarr(ret, "raw_message", + result.failure->raw_message); + json_add_num(ret, "created_at", p->start_time.ts.tv_sec); + json_add_node_id(ret, "destination", p->pay_destination); + json_add_sha256(ret, "payment_hash", p->payment_hash); + + if (result.leafstates & PAYMENT_STEP_SUCCESS) { + /* If one sub-payment succeeded then we have + * proof of payment, and the payment is a + * success. */ + json_add_string(ret, "status", "complete"); + + } else if (result.leafstates & ~PAYMENT_STEP_FAILED) { + /* If there are non-failed leafs we are still trying. */ + json_add_string(ret, "status", "pending"); - if (failure != NULL) { - if (failure->erring_index) - json_add_num(ret, "erring_index", - *failure->erring_index); + } else { + json_add_string(ret, "status", "failed"); + } - if (failure->erring_node) - json_add_node_id(ret, "erring_node", - failure->erring_node); + json_add_amount_msat(ret, "amount_msat", p->our_amount); + json_add_amount_msat(ret, "amount_sent_msat", + result.sent); - if (failure->erring_channel) - json_add_short_channel_id( - ret, "erring_channel", - *failure->erring_channel); + if (failure != NULL) { + if (failure->erring_index) + json_add_num(ret, "erring_index", + *failure->erring_index); - if (failure->erring_direction) - json_add_num( - ret, "erring_direction", - *failure->erring_direction); - } + if (failure->erring_node) + json_add_node_id(ret, "erring_node", + failure->erring_node); - payment_notify_failure(p, failure->message); + if (failure->erring_channel) + json_add_short_channel_id( + ret, "erring_channel", + *failure->erring_channel); - if (command_finished(cmd, ret)) { /* Ignore result. */} - p->cmd = NULL; - return; + if (failure->erring_direction) + json_add_num( + ret, "erring_direction", + *failure->erring_direction); } - } else { - payment_child_finished(p->parent, p); - return; + + payment_notify_failure(p, failure->message); } + + if (command_finished(cmd, ret)) { /* Ignore result. */} } void payment_set_step(struct payment *p, enum payment_step newstep) From dfad69d5407ef96c36729c45b09d8b245ef50dc8 Mon Sep 17 00:00:00 2001 From: Rusty Russell Date: Wed, 6 Nov 2024 21:26:36 +1030 Subject: [PATCH 09/18] libplugin-pay: always use a non-NULL `struct command`. This means we replace p->cmd with an auxillary command after we've finished, so we have a valid command to use. It also means we weave `struct command_result` returns back through all the callers. Signed-off-by: Rusty Russell --- plugins/keysend.c | 2 +- plugins/libplugin-pay.c | 256 +++++++++++++----------------- plugins/libplugin-pay.h | 15 +- plugins/pay.c | 10 +- plugins/test/run-route-calc.c | 3 + plugins/test/run-route-overlong.c | 3 + 6 files changed, 134 insertions(+), 155 deletions(-) diff --git a/plugins/keysend.c b/plugins/keysend.c index 16d9baa8d50c..b04386d504b8 100644 --- a/plugins/keysend.c +++ b/plugins/keysend.c @@ -62,7 +62,7 @@ static struct keysend_data *keysend_init(struct payment *p) } } -static void keysend_cb(struct keysend_data *d, struct payment *p) { +static struct command_result *keysend_cb(struct keysend_data *d, struct payment *p) { struct createonion_hop *last_payload; size_t hopcount; diff --git a/plugins/libplugin-pay.c b/plugins/libplugin-pay.c index 24b448ddc6c2..6ba34214d15f 100644 --- a/plugins/libplugin-pay.c +++ b/plugins/libplugin-pay.c @@ -69,6 +69,12 @@ int libplugin_pay_poll(struct pollfd *fds, nfds_t nfds, int timeout) return daemon_poll(fds, nfds, timeout); } +/* Only root has a non-NULL cmd ptr */ +static struct command *payment_cmd(struct payment *p) +{ + return payment_root(p)->cmd; +} + struct payment *payment_new(tal_t *ctx, struct command *cmd, struct payment *parent, struct channel_hint_set *channel_hints, @@ -82,6 +88,7 @@ struct payment *payment_new(tal_t *ctx, struct command *cmd, p->parent = parent; p->modifiers = mods; p->cmd = cmd; + p->finished = false; p->start_time = time_now(); p->result = NULL; p->why = NULL; @@ -230,10 +237,9 @@ static struct command_result *payment_rpc_failure(struct command *cmd, const jsmntok_t *toks, struct payment *p) { - payment_fail(p, - "Failing a partial payment due to a failed RPC call: %.*s", - toks->end - toks->start, buffer + toks->start); - return command_still_pending(cmd); + return payment_fail(p, + "Failing a partial payment due to a failed RPC call: %.*s", + toks->end - toks->start, buffer + toks->start); } struct payment_tree_result payment_collect_result(struct payment *p) @@ -306,8 +312,7 @@ static struct command_result *payment_waitblockheight_cb(struct command *cmd, "(syncheight=%d < headercount=%d)", p->chainlag, syncheight, p->start_block); - payment_continue(p); - return command_still_pending(cmd); + return payment_continue(p); } static struct command_result * @@ -330,19 +335,17 @@ payment_getblockheight_success(struct command *cmd, /* Now we just need to ask `lightningd` what height it has * synced up to, and we remember that as chainlag. */ - req = jsonrpc_request_start(p->plugin, NULL, "waitblockheight", + req = jsonrpc_request_start(p->plugin, cmd, "waitblockheight", &payment_waitblockheight_cb, &payment_rpc_failure, p); json_add_u32(req->js, "blockheight", 0); - send_outreq(p->plugin, req); - - return command_still_pending(cmd); + return send_outreq(p->plugin, req); } #define INVALID_BLOCKHEIGHT UINT32_MAX -static -void payment_start_at_blockheight(struct payment *p, u32 blockheight) +static struct command_result * +payment_start_at_blockheight(struct payment *p, u32 blockheight) { struct payment *root = payment_root(p); @@ -378,11 +381,11 @@ void payment_start_at_blockheight(struct payment *p, u32 blockheight) * height, allowing us to send while still syncing. */ struct out_req *req; - req = jsonrpc_request_start(p->plugin, NULL, "getchaininfo", + req = jsonrpc_request_start(p->plugin, payment_cmd(p), "getchaininfo", &payment_getblockheight_success, &payment_rpc_failure, p); json_add_u32(req->js, "last_height", 0); - send_outreq(p->plugin, req); + return send_outreq(p->plugin, req); } void payment_start(struct payment *p) @@ -864,22 +867,16 @@ static struct command_result *payment_getroute(struct payment *p) dst = gossmap_find_node(gossmap, p->getroute->destination); if (!dst) { put_gossmap(p); - payment_fail( + return payment_fail( p, "Unknown destination %s", fmt_node_id(tmpctx, p->getroute->destination)); - - /* Let payment_finished_ handle this, so we mark it as pending */ - return command_still_pending(p->cmd); } /* 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 */ - return command_still_pending(p->cmd); + return payment_fail(p, "We don't have any channels"); } p->route = route(p, gossmap, src, dst, p->getroute->amount, p->getroute->cltv, @@ -888,9 +885,7 @@ static struct command_result *payment_getroute(struct payment *p) put_gossmap(p); if (!p->route) { - payment_fail(p, "%s", errstr); - /* Let payment_finished_ handle this, so we mark it as pending */ - return command_still_pending(p->cmd); + return payment_fail(p, "%s", errstr); } /* OK, now we *have* a route */ @@ -898,9 +893,8 @@ static struct command_result *payment_getroute(struct payment *p) if (tal_count(p->route) == 0) { payment_root(p)->abort = true; - payment_fail(p, "Empty route returned by getroute, are you " - "trying to pay yourself?"); - return command_still_pending(p->cmd); + return payment_fail(p, "Empty route returned by getroute, are you " + "trying to pay yourself?"); } fee = payment_route_fee(p); @@ -908,19 +902,17 @@ static struct command_result *payment_getroute(struct payment *p) /* Ensure that our fee and CLTV budgets are respected. */ if (amount_msat_greater(fee, p->constraints.fee_budget)) { p->route = tal_free(p->route); - payment_fail( - p, "Fee exceeds our fee budget: %s > %s, discarding route", - fmt_amount_msat(tmpctx, fee), - fmt_amount_msat(tmpctx, p->constraints.fee_budget)); - return command_still_pending(p->cmd); + return payment_fail( + p, "Fee exceeds our fee budget: %s > %s, discarding route", + fmt_amount_msat(tmpctx, fee), + fmt_amount_msat(tmpctx, p->constraints.fee_budget)); } if (p->route[0].delay > p->constraints.cltv_budget) { u32 delay = p->route[0].delay; p->route = tal_free(p->route); - payment_fail(p, "CLTV delay exceeds our CLTV budget: %d > %d", - delay, p->constraints.cltv_budget); - return command_still_pending(p->cmd); + return payment_fail(p, "CLTV delay exceeds our CLTV budget: %d > %d", + delay, p->constraints.cltv_budget); } /* Now update the constraints in fee_budget and cltv_budget so @@ -934,8 +926,7 @@ static struct command_result *payment_getroute(struct payment *p) /* Allow modifiers to modify the route, before * payment_compute_onion_payloads uses the route to generate the * onion_payloads */ - payment_continue(p); - return command_still_pending(p->cmd); + return payment_continue(p); } /** @@ -1018,12 +1009,11 @@ payment_listpeerchannels_success(struct command *cmd, const char *buffer, "spendable=%s < payment=%s", fmt_amount_msat(tmpctx, spendable), fmt_amount_msat(tmpctx, p->getroute->amount)); - payment_abort(p, PAY_INSUFFICIENT_FUNDS, + return payment_abort(p, PAY_INSUFFICIENT_FUNDS, "Insufficient funds to perform the payment: " "spendable=%s < payment=%s", fmt_amount_msat(tmpctx, spendable), fmt_amount_msat(tmpctx, p->getroute->amount)); - return command_still_pending(p->cmd); } else if (amount_msat_greater(maxrequired, spendable)) { char *msg = tal_fmt( tmpctx, @@ -1034,7 +1024,7 @@ payment_listpeerchannels_success(struct command *cmd, const char *buffer, fmt_amount_msat(tmpctx, p->getroute->amount), fmt_amount_msat(tmpctx, p->constraints.fee_budget)); - plugin_notify_message(p->cmd, LOG_INFORM, "%s", msg); + plugin_notify_message(payment_cmd(p), LOG_INFORM, "%s", msg); } return payment_getroute(p); @@ -1048,7 +1038,7 @@ static struct command_result *payment_getlocalmods(struct payment *p) if (p->mods) return payment_getroute(p); - req = jsonrpc_request_start(p->plugin, NULL, "listpeerchannels", + req = jsonrpc_request_start(p->plugin, payment_cmd(p), "listpeerchannels", &payment_listpeerchannels_success, &payment_rpc_failure, p); return send_outreq(p->plugin, req); @@ -1393,9 +1383,7 @@ handle_final_failure(struct command *cmd, payment_root(p)->abort = true; nonerror: - payment_fail(p, "%s", p->result->message); - return command_still_pending(cmd); - + return payment_fail(p, "%s", p->result->message); } @@ -1494,8 +1482,7 @@ handle_intermediate_failure(struct command *cmd, failcode, describe_failcode(tmpctx, failcode)); error: - payment_fail(p, "%s", p->result->message); - return command_still_pending(cmd); + return payment_fail(p, "%s", p->result->message); } /* From the docs: @@ -1609,8 +1596,7 @@ payment_addgossip_success(struct command *cmd, const char *buffer, json_tok_full(buffer, toks)); /* FIXME: Pick a random channel to fail? */ payment_set_step(p, PAYMENT_STEP_FAILED); - payment_continue(p); - return command_still_pending(cmd); + return payment_continue(p); } if (!errchan) @@ -1650,16 +1636,14 @@ payment_waitsendpay_finished(struct command *cmd, const char *buffer, json_tok_full_len(toks), json_tok_full(buffer, toks)); payment_set_step(p, PAYMENT_STEP_FAILED); - payment_continue(p); - return command_still_pending(cmd); + return payment_continue(p); } payment_result_infer(p->route, p->result); if (p->result->state == PAYMENT_COMPLETE) { payment_set_step(p, PAYMENT_STEP_SUCCESS); - payment_continue(p); - return command_still_pending(cmd); + return payment_continue(p); } payment_chanhints_unapply_route(p); @@ -1672,12 +1656,11 @@ payment_waitsendpay_finished(struct command *cmd, const char *buffer, "Extracted channel_update %s from onionreply %s", tal_hex(tmpctx, update), tal_hex(tmpctx, p->result->raw_message)); - req = jsonrpc_request_start(p->plugin, NULL, "addgossip", + req = jsonrpc_request_start(p->plugin, payment_cmd(p), "addgossip", payment_addgossip_success, payment_addgossip_failure, p); json_add_hex_talarr(req->js, "message", update); - send_outreq(p->plugin, req); - return command_still_pending(cmd); + return send_outreq(p->plugin, req); } return payment_addgossip_success(cmd, NULL, NULL, p); @@ -1689,15 +1672,13 @@ static struct command_result *payment_sendonion_success(struct command *cmd, struct payment *p) { struct out_req *req; - req = jsonrpc_request_start(p->plugin, NULL, "waitsendpay", + req = jsonrpc_request_start(p->plugin, payment_cmd(p), "waitsendpay", payment_waitsendpay_finished, payment_waitsendpay_finished, p); json_add_sha256(req->js, "payment_hash", p->payment_hash); json_add_num(req->js, "partid", p->partid); json_add_u64(req->js, "groupid", p->groupid); - send_outreq(p->plugin, req); - - return command_still_pending(cmd); + return send_outreq(p->plugin, req); } static struct command_result *payment_createonion_success(struct command *cmd, @@ -1719,7 +1700,7 @@ static struct command_result *payment_createonion_success(struct command *cmd, p->createonion_response = json_to_createonion_response(p, buffer, toks); - req = jsonrpc_request_start(p->plugin, NULL, "sendonion", + req = jsonrpc_request_start(p->plugin, payment_cmd(p), "sendonion", payment_sendonion_success, payment_rpc_failure, p); json_add_hex_talarr(req->js, "onion", p->createonion_response->onion); @@ -1762,8 +1743,7 @@ static struct command_result *payment_createonion_success(struct command *cmd, if (p->local_invreq_id) json_add_sha256(req->js, "localinvreqid", p->local_invreq_id); - send_outreq(p->plugin, req); - return command_still_pending(cmd); + return send_outreq(p->plugin, req); } /* Temporary serialization method for the tlv_payload.data until we rework the @@ -1857,7 +1837,7 @@ static void payment_add_blindedpath(const tal_t *ctx, } } -static void payment_compute_onion_payloads(struct payment *p) +static struct command_result *payment_compute_onion_payloads(struct payment *p) { struct createonion_request *cr; size_t hopcount; @@ -1943,14 +1923,14 @@ static void payment_compute_onion_payloads(struct payment *p) /* Now allow all the modifiers to mess with the payloads, before we * serialize via a call to createonion in the next step. */ - payment_continue(p); + return payment_continue(p); } -static void payment_sendonion(struct payment *p) +static struct command_result *payment_sendonion(struct payment *p) { struct out_req *req; u8 *payload, *tlv; - req = jsonrpc_request_start(p->plugin, NULL, "createonion", + req = jsonrpc_request_start(p->plugin, payment_cmd(p), "createonion", payment_createonion_success, payment_rpc_failure, p); @@ -1979,11 +1959,11 @@ static void payment_sendonion(struct payment *p) json_add_secret(req->js, "sessionkey", p->createonion_request->session_key); - send_outreq(p->plugin, req); + return send_outreq(p->plugin, req); } /* Mutual recursion. */ -static void payment_finished(struct payment *p); +static struct command_result *payment_finished(struct payment *p); /* A payment is finished if a) it is in a final state, of b) it's in a * child-spawning state and all of its children are in a final state. */ @@ -2033,14 +2013,14 @@ static bool payment_is_success(struct payment *p) /* Function to bubble up completions to the root, which actually holds on to * the command that initiated the flow. */ -static void payment_child_finished(struct payment *p, +static struct command_result *payment_child_finished(struct payment *p, struct payment *child) { if (!payment_is_finished(p)) - return; + return command_still_pending(payment_cmd(p)); /* Should we continue bubbling up? */ - payment_finished(p); + return payment_finished(p); } static void payment_add_attempt(struct json_stream *s, const char *fieldname, struct payment *p, bool recurse) @@ -2144,7 +2124,7 @@ void json_add_payment_success(struct json_stream *js, * leafs in the subtree rooted in the payment are all in a final state. It is * called only once, and it is guaranteed to be called in post-order * traversal, i.e., all children are finished before the parent is called. */ -static void payment_finished(struct payment *p) +static struct command_result *payment_finished(struct payment *p) { struct payment_tree_result result = payment_collect_result(p); struct json_stream *ret; @@ -2159,14 +2139,14 @@ static void payment_finished(struct payment *p) if (p->parent != NULL) return payment_child_finished(p->parent, p); - /* We are about to reply, unset the pointer to the cmd so we - * don't attempt to return a response twice. */ - p->cmd = NULL; - if (cmd == NULL) { - /* This is the tree root, but we already reported - * success or failure, so noop. */ - return; - } else if (payment_is_success(p)) { + if (p->finished) { + /* cmd is the aux_command: real cmd has been freed. */ + return command_still_pending(p->cmd); + } + + /* on_payment_failure / on_payment_success looks at this! */ + p->finished = true; + if (payment_is_success(p)) { assert(result.treestates & PAYMENT_STEP_SUCCESS); assert(result.leafstates & PAYMENT_STEP_SUCCESS); assert(result.preimage != NULL); @@ -2266,7 +2246,11 @@ static void payment_finished(struct payment *p) payment_notify_failure(p, failure->message); } - if (command_finished(cmd, ret)) { /* Ignore result. */} + /* We're going to resolve p->cmd. Put an aux_command in place + * so we can use that to wrap up any remaining payments */ + p->cmd = aux_command(cmd); + + return command_finished(cmd, ret); } void payment_set_step(struct payment *p, enum payment_step newstep) @@ -2279,7 +2263,7 @@ void payment_set_step(struct payment *p, enum payment_step newstep) p->end_time = time_now(); } -void payment_continue(struct payment *p) +struct command_result *payment_continue(struct payment *p) { struct payment_modifier *mod; void *moddata; @@ -2299,27 +2283,23 @@ void payment_continue(struct payment *p) switch (p->step) { case PAYMENT_STEP_INITIALIZED: case PAYMENT_STEP_RETRY_GETROUTE: - payment_getlocalmods(p); - return; + return payment_getlocalmods(p); case PAYMENT_STEP_GOT_ROUTE: - payment_compute_onion_payloads(p); - return; + return payment_compute_onion_payloads(p); case PAYMENT_STEP_ONION_PAYLOAD: - payment_sendonion(p); - return; + return payment_sendonion(p); case PAYMENT_STEP_SUCCESS: case PAYMENT_STEP_FAILED: - payment_finished(p); - return; + return payment_finished(p); case PAYMENT_STEP_RETRY: case PAYMENT_STEP_SPLIT: /* Do nothing, we'll get pinged by a child succeeding * or failing. */ - return; + return command_still_pending(payment_cmd(p)); } } /* We should never get here, it'd mean one of the state machine called @@ -2327,7 +2307,7 @@ void payment_continue(struct payment *p) abort(); } -void payment_abort(struct payment *p, enum jsonrpc_errcode code, const char *fmt, ...) { +struct command_result *payment_abort(struct payment *p, enum jsonrpc_errcode code, const char *fmt, ...) { va_list ap; struct payment *root = payment_root(p); payment_set_step(p, PAYMENT_STEP_FAILED); @@ -2352,10 +2332,10 @@ void payment_abort(struct payment *p, enum jsonrpc_errcode code, const char *fmt /* Do not use payment_continue, because that'd continue * applying the modifiers before calling * payment_finished(). */ - payment_finished(p); + return payment_finished(p); } -void payment_fail(struct payment *p, const char *fmt, ...) +struct command_result *payment_fail(struct payment *p, const char *fmt, ...) { va_list ap; p->end_time = time_now(); @@ -2368,7 +2348,7 @@ void payment_fail(struct payment *p, const char *fmt, ...) paymod_log(p, LOG_INFORM, "%s", p->failreason); - payment_continue(p); + return payment_continue(p); } void *payment_mod_get_data(const struct payment *p, @@ -2386,8 +2366,8 @@ void *payment_mod_get_data(const struct payment *p, static struct retry_mod_data *retry_data_init(struct payment *p); -static inline void retry_step_cb(struct retry_mod_data *rd, - struct payment *p); +static struct command_result *retry_step_cb(struct retry_mod_data *rd, + struct payment *p); static struct retry_mod_data * retry_data_init(struct payment *p) @@ -2460,8 +2440,8 @@ static bool payment_can_retry(struct payment *p) return true; } -static inline void retry_step_cb(struct retry_mod_data *rd, - struct payment *p) +static struct command_result *retry_step_cb(struct retry_mod_data *rd, + struct payment *p) { struct payment *subpayment, *root = payment_root(p); struct retry_mod_data *rdata = payment_mod_retry_get_data(p); @@ -2511,7 +2491,7 @@ static inline void retry_step_cb(struct retry_mod_data *rd, rdata->retries - 1); } - payment_continue(p); + return payment_continue(p); } REGISTER_PAYMENT_MODIFIER(retry, struct retry_mod_data *, retry_data_init, @@ -2586,11 +2566,10 @@ local_channel_hints_listpeerchannels(struct command *cmd, const char *buffer, p->mods = gossmods_from_listpeerchannels( p, p->local_id, buffer, toks, true, gossmod_add_localchan, NULL); - payment_continue(p); - return command_still_pending(cmd); + return payment_continue(p); } -static void local_channel_hints_cb(void *d UNUSED, struct payment *p) +static struct command_result *local_channel_hints_cb(void *d UNUSED, struct payment *p) { struct out_req *req; /* If we are not the root we don't look up the channel balances since @@ -2601,10 +2580,10 @@ static void local_channel_hints_cb(void *d UNUSED, struct payment *p) if (p->parent != NULL || p->step != PAYMENT_STEP_INITIALIZED) return payment_continue(p); - req = jsonrpc_request_start(p->plugin, NULL, "listpeerchannels", + req = jsonrpc_request_start(p->plugin, payment_cmd(p), "listpeerchannels", local_channel_hints_listpeerchannels, local_channel_hints_listpeerchannels, p); - send_outreq(p->plugin, req); + return send_outreq(p->plugin, req); } REGISTER_PAYMENT_MODIFIER(local_channel_hints, void *, NULL, local_channel_hints_cb); @@ -2908,7 +2887,7 @@ static void routehint_pre_getroute(struct routehints_data *d, struct payment *p) paymod_log(p, LOG_DBG, "Not using a routehint"); } -static void routehint_check_reachable(struct payment *p) +static struct command_result *routehint_check_reachable(struct payment *p) { const struct gossmap_node *dst, *src; struct gossmap *gossmap = get_gossmap(p); @@ -2962,14 +2941,13 @@ static void routehint_check_reachable(struct payment *p) * isn't reachable, then there is no point in * continuing. */ - payment_abort( + put_gossmap(p); + return payment_abort( p, PAY_UNREACHABLE, "Destination %s is not reachable directly and " "all routehints were unusable.", fmt_node_id(tmpctx, p->route_destination)); - put_gossmap(p); - return; } routehint_pre_getroute(d, p); @@ -2982,10 +2960,10 @@ static void routehint_check_reachable(struct payment *p) d->destination_reachable ? "including" : "excluding"); /* Now we can continue on our merry way. */ - payment_continue(p); + return payment_continue(p); } -static void routehint_step_cb(struct routehints_data *d, struct payment *p) +static struct command_result *routehint_step_cb(struct routehints_data *d, struct payment *p) { struct route_hop hop; const struct payment *root = payment_root(p); @@ -3075,7 +3053,7 @@ static void routehint_step_cb(struct routehints_data *d, struct payment *p) } } - payment_continue(p); + return payment_continue(p); } static struct routehints_data *routehint_data_init(struct payment *p) @@ -3157,7 +3135,7 @@ static struct exemptfee_data *exemptfee_data_init(struct payment *p) } } -static void exemptfee_cb(struct exemptfee_data *d, struct payment *p) +static struct command_result *exemptfee_cb(struct exemptfee_data *d, struct payment *p) { if (p->step != PAYMENT_STEP_INITIALIZED || p->parent != NULL) return payment_continue(p); @@ -3223,7 +3201,7 @@ static struct command_result *shadow_route_extend(struct shadow_route_data *d, struct payment *p) { struct out_req *req; - req = jsonrpc_request_start(p->plugin, NULL, "listchannels", + req = jsonrpc_request_start(p->plugin, payment_cmd(p), "listchannels", shadow_route_listchannels, payment_rpc_failure, p); json_add_node_id(req->js, "source", &d->destination); @@ -3364,14 +3342,13 @@ static struct command_result *shadow_route_listchannels(struct command *cmd, /* Now it's time to decide whether we want to extend or continue. */ if (best == NULL || pseudorand(2) == 0) { - payment_continue(p); - return command_still_pending(cmd); + return payment_continue(p); } else { return shadow_route_extend(d, p); } } -static void shadow_route_cb(struct shadow_route_data *d, +static struct command_result *shadow_route_cb(struct shadow_route_data *d, struct payment *p) { if (!d->use_shadow) @@ -3390,15 +3367,15 @@ static void shadow_route_cb(struct shadow_route_data *d, if (pseudorand(2) == 0) { return payment_continue(p); } else { - shadow_route_extend(d, p); + return shadow_route_extend(d, p); } } REGISTER_PAYMENT_MODIFIER(shadowroute, struct shadow_route_data *, shadow_route_init, shadow_route_cb); -static void direct_pay_override(struct payment *p) { - +static struct command_result *direct_pay_override(struct payment *p) +{ /* The root has performed the search for a direct channel. */ struct payment *root = payment_root(p); struct direct_pay_data *d; @@ -3432,8 +3409,7 @@ static void direct_pay_override(struct payment *p) { payment_set_step(p, PAYMENT_STEP_GOT_ROUTE); } - - payment_continue(p); + return payment_continue(p); } /* Now that we have the listpeerchannels result for the root payment, let's search @@ -3480,12 +3456,11 @@ static struct command_result *direct_pay_listpeerchannels(struct command *cmd, gossmod_add_localchan, NULL); - direct_pay_override(p); - return command_still_pending(cmd); + return direct_pay_override(p); } -static void direct_pay_cb(struct direct_pay_data *d, struct payment *p) +static struct command_result *direct_pay_cb(struct direct_pay_data *d, struct payment *p) { struct out_req *req; @@ -3493,14 +3468,12 @@ static void direct_pay_cb(struct direct_pay_data *d, struct payment *p) if (p->step != PAYMENT_STEP_INITIALIZED) return payment_continue(p); - - - req = jsonrpc_request_start(p->plugin, NULL, "listpeerchannels", + req = jsonrpc_request_start(p->plugin, payment_cmd(p), "listpeerchannels", direct_pay_listpeerchannels, direct_pay_listpeerchannels, p); json_add_node_id(req->js, "id", p->route_destination); - send_outreq(p->plugin, req); + return send_outreq(p->plugin, req); } static struct direct_pay_data *direct_pay_init(struct payment *p) @@ -3596,7 +3569,7 @@ static struct adaptive_split_mod_data *adaptive_splitter_data_init(struct paymen } } -static void adaptive_splitter_cb(struct adaptive_split_mod_data *d, struct payment *p) +static struct command_result *adaptive_splitter_cb(struct adaptive_split_mod_data *d, struct payment *p) { struct payment *root = payment_root(p); struct adaptive_split_mod_data *root_data = @@ -3705,7 +3678,7 @@ static void adaptive_splitter_cb(struct adaptive_split_mod_data *d, struct payme MPP_ADAPTIVE_LOWER_LIMIT)); } } - payment_continue(p); + return payment_continue(p); } REGISTER_PAYMENT_MODIFIER(adaptive_splitter, struct adaptive_split_mod_data *, @@ -3785,11 +3758,10 @@ payee_incoming_limit_count(struct command *cmd, payment_lower_max_htlcs(p, lim, why); } - payment_continue(p); - return command_still_pending(cmd); + return payment_continue(p); } -static void payee_incoming_limit_step_cb(void *d UNUSED, struct payment *p) +static struct command_result *payee_incoming_limit_step_cb(void *d UNUSED, struct payment *p) { /* Only operate at the initialization of te root payment. * Also, no point operating if payment does not support MPP anyway. @@ -3800,11 +3772,11 @@ static void payee_incoming_limit_step_cb(void *d UNUSED, struct payment *p) /* Get information on the destination. */ struct out_req *req; - req = jsonrpc_request_start(p->plugin, NULL, "listchannels", + req = jsonrpc_request_start(p->plugin, payment_cmd(p), "listchannels", &payee_incoming_limit_count, &payment_rpc_failure, p); json_add_node_id(req->js, "source", p->route_destination); - (void) send_outreq(p->plugin, req); + return send_outreq(p->plugin, req); } REGISTER_PAYMENT_MODIFIER(payee_incoming_limit, void *, NULL, @@ -3823,7 +3795,7 @@ route_exclusions_data_init(struct payment *p) return d; } -static void route_exclusions_step_cb(struct route_exclusions_data *d, +static struct command_result *route_exclusions_step_cb(struct route_exclusions_data *d, struct payment *p) { if (p->parent) @@ -3841,17 +3813,15 @@ static void route_exclusions_step_cb(struct route_exclusions_data *d, NULL, total, NULL); } else { if (node_id_eq(&e->u.node_id, p->route_destination)) { - payment_abort(p, PAY_USER_ERROR, "Payee is manually excluded"); - return; + return payment_abort(p, PAY_USER_ERROR, "Payee is manually excluded"); } else if (node_id_eq(&e->u.node_id, p->local_id)) { - payment_abort(p, PAY_USER_ERROR, "Payer is manually excluded"); - return; + return payment_abort(p, PAY_USER_ERROR, "Payer is manually excluded"); } tal_arr_expand(&p->excluded_nodes, e->u.node_id); } } - payment_continue(p); + return payment_continue(p); } REGISTER_PAYMENT_MODIFIER(route_exclusions, struct route_exclusions_data *, diff --git a/plugins/libplugin-pay.h b/plugins/libplugin-pay.h index efa253623ce9..bc1ec51b5dc9 100644 --- a/plugins/libplugin-pay.h +++ b/plugins/libplugin-pay.h @@ -145,8 +145,9 @@ struct payment { /* Usually in global payments list */ struct list_node list; /* The command that triggered this payment. Only set for the root - * payment. */ + * payment. It's an aux command if finished is set. */ struct command *cmd; + bool finished; struct plugin *plugin; struct node_id *local_id; @@ -322,7 +323,7 @@ struct payment { struct payment_modifier { const char *name; void *(*data_init)(struct payment *p); - void (*post_step_cb)(void *data, struct payment *p); + struct command_result *(*post_step_cb)(void *data, struct payment *p); }; void *payment_mod_get_data(const struct payment *payment, @@ -333,8 +334,8 @@ void *payment_mod_get_data(const struct payment *payment, stringify(name), \ typesafe_cb_cast(void *(*)(struct payment *), \ data_type (*)(struct payment *), data_init_cb), \ - typesafe_cb_cast(void (*)(void *, struct payment *), \ - void (*)(data_type, struct payment *), step_cb), \ + typesafe_cb_cast(struct command_result *(*)(void *, struct payment *), \ + struct command_result *(*)(data_type, struct payment *), step_cb), \ }; /* The UNUSED marker is used to shut some compilers up. */ @@ -450,7 +451,7 @@ struct payment *payment_new(tal_t *ctx, struct command *cmd, struct payment_modifier **mods); void payment_start(struct payment *p); -void payment_continue(struct payment *p); +struct command_result *payment_continue(struct payment *p); /** * Set the payment to the current step. @@ -463,14 +464,14 @@ void payment_set_step(struct payment *p, enum payment_step newstep); /* Fails a partial payment and continues with the core flow. */ -void payment_fail(struct payment *p, const char *fmt, ...) PRINTF_FMT(2,3); +struct command_result *payment_fail(struct payment *p, const char *fmt, ...) PRINTF_FMT(2,3); /* Fails a payment process by setting the root payment to * aborted. This will cause all subpayments to terminate as soon as * they can, and sets the root failreason so we have a sensible error * message. The failreason is overwritten if it is already set, since * we probably know better what happened in the modifier.. */ -void payment_abort(struct payment *p, enum jsonrpc_errcode code, const char *fmt, ...) PRINTF_FMT(3,4); +struct command_result *payment_abort(struct payment *p, enum jsonrpc_errcode code, const char *fmt, ...) PRINTF_FMT(3,4); struct payment *payment_root(struct payment *p); struct payment_tree_result payment_collect_result(struct payment *p); diff --git a/plugins/pay.c b/plugins/pay.c index 98dcd1df1424..37f9ce661b4a 100644 --- a/plugins/pay.c +++ b/plugins/pay.c @@ -625,11 +625,12 @@ static void on_payment_success(struct payment *payment) if (!sha256_eq(payment->payment_hash, p->payment_hash) || payment->groupid != p->groupid) continue; - if (p->cmd == NULL) + if (p->finished) continue; cmd = p->cmd; - p->cmd = NULL; + p->cmd = aux_command(cmd); + p->finished = true; ret = jsonrpc_stream_success(cmd); json_add_node_id(ret, "destination", p->pay_destination); @@ -713,11 +714,12 @@ static void on_payment_failure(struct payment *payment) if (!sha256_eq(payment->payment_hash, p->payment_hash) || payment->groupid != p->groupid) continue; - if (p->cmd == NULL) + if (p->finished) continue; cmd = p->cmd; - p->cmd = NULL; + p->cmd = aux_command(cmd); + p->finished = true; if (p->aborterror != NULL) { /* We set an explicit toplevel error message, * so let's report that. */ diff --git a/plugins/test/run-route-calc.c b/plugins/test/run-route-calc.c index 8e4eda56a9b1..e8b93ec7fb40 100644 --- a/plugins/test/run-route-calc.c +++ b/plugins/test/run-route-calc.c @@ -12,6 +12,9 @@ #include /* AUTOGENERATED MOCKS START */ +/* Generated stub for aux_command */ +struct command *aux_command(const struct command *cmd UNNEEDED) +{ fprintf(stderr, "aux_command called!\n"); abort(); } /* Generated stub for blinded_onion_hops */ u8 **blinded_onion_hops(const tal_t *ctx UNNEEDED, struct amount_msat final_amount UNNEEDED, diff --git a/plugins/test/run-route-overlong.c b/plugins/test/run-route-overlong.c index 308361c7c4c7..cb3dd356dee8 100644 --- a/plugins/test/run-route-overlong.c +++ b/plugins/test/run-route-overlong.c @@ -9,6 +9,9 @@ #include /* AUTOGENERATED MOCKS START */ +/* Generated stub for aux_command */ +struct command *aux_command(const struct command *cmd UNNEEDED) +{ fprintf(stderr, "aux_command called!\n"); abort(); } /* Generated stub for blinded_onion_hops */ u8 **blinded_onion_hops(const tal_t *ctx UNNEEDED, struct amount_msat final_amount UNNEEDED, From fea822eb25abcdc9baf5d74a3cc50cc4cea1faeb Mon Sep 17 00:00:00 2001 From: Rusty Russell Date: Wed, 6 Nov 2024 21:27:36 +1030 Subject: [PATCH 10/18] libplugin-pay: fix command logging We were dereferencing the first character of the id, (always '"') which meant everything was id 34. Before: plugin-pay: cmd 34 partid 5 After: cmd pytest:pay#62/cln:pay#105 partid 0 Signed-off-by: Rusty Russell Changelog-Fixed: `pay`: debug logging now uses correct JSON ids. --- plugins/libplugin-pay.c | 37 ++++++++++--------------------------- 1 file changed, 10 insertions(+), 27 deletions(-) diff --git a/plugins/libplugin-pay.c b/plugins/libplugin-pay.c index 6ba34214d15f..944a169df96d 100644 --- a/plugins/libplugin-pay.c +++ b/plugins/libplugin-pay.c @@ -178,31 +178,18 @@ struct payment *payment_root(struct payment *p) return payment_root(p->parent); } -static void -paymod_log_header(struct payment *p, const char **type, u64 *id) +static const char *paymod_log_header(const tal_t *ctx, + struct payment *p) { - struct payment *root = payment_root(p); - /* We prefer to show the command ID here since it is also known - * by `lightningd`, so in theory it can be used to correlate - * debugging logs between the main `lightningd` and whatever - * plugin is using the paymod system. - * We only fall back to a unique id per root payment if there - * is no command with an id associated with this payment. - */ - if (root->cmd && root->cmd->id) { - *type = "cmd"; - *id = *root->cmd->id; - } else { - *type = "id"; - *id = root->id; - } + const char *id = payment_cmd(p)->id; + if (strstarts(id, "\"")) + return tal_strndup(ctx, id+1, strlen(id+1)-1); + return tal_strdup(ctx, id); } void paymod_log(struct payment *p, enum log_level l, const char *fmt, ...) { - const char *type; - u64 id; char *txt; va_list ap; @@ -210,15 +197,12 @@ paymod_log(struct payment *p, enum log_level l, const char *fmt, ...) txt = tal_vfmt(tmpctx, fmt, ap); va_end(ap); - paymod_log_header(p, &type, &id); - plugin_log(p->plugin, l, "%s %"PRIu64" partid %"PRIu32": %s", - type, id, p->partid, txt); + plugin_log(p->plugin, l, "cmd %s partid %"PRIu32": %s", + paymod_log_header(tmpctx, p), p->partid, txt); } static void paymod_err(struct payment *p, const char *fmt, ...) { - const char *type; - u64 id; char *txt; va_list ap; @@ -226,9 +210,8 @@ paymod_err(struct payment *p, const char *fmt, ...) txt = tal_vfmt(tmpctx, fmt, ap); va_end(ap); - paymod_log_header(p, &type, &id); - plugin_err(p->plugin, "%s %"PRIu64" partid %"PRIu32": %s", - type, id, p->partid, txt); + plugin_err(p->plugin, "cmd %s partid %"PRIu32": %s", + paymod_log_header(tmpctx, p), p->partid, txt); } /* Generic handler for RPC failures that should end up failing the payment. */ From 1c12eadea003422ec090444d12a4126f05b679ac Mon Sep 17 00:00:00 2001 From: Rusty Russell Date: Wed, 6 Nov 2024 21:28:36 +1030 Subject: [PATCH 11/18] libplugin: insist on always having a non-NULL command context. And remove command_done() which was used when there was no cmd. Signed-off-by: Rusty Russell --- plugins/autoclean.c | 6 +-- plugins/libplugin.c | 24 ++++------- plugins/libplugin.h | 67 +++++++++++++++++++------------ plugins/test/run-route-calc.c | 18 ++++++--- plugins/test/run-route-overlong.c | 18 ++++++--- 5 files changed, 76 insertions(+), 57 deletions(-) diff --git a/plugins/autoclean.c b/plugins/autoclean.c index 83c896db8863..5e560efe2c7d 100644 --- a/plugins/autoclean.c +++ b/plugins/autoclean.c @@ -509,7 +509,7 @@ static struct command_result *list_done(struct command *cmd, } subsystem->cinfo->cleanup_reqs_remaining++; - req = jsonrpc_request_start(plugin, NULL, ops->del_command, + req = jsonrpc_request_start(plugin, cmd, ops->del_command, del_done, del_failed, variant); ops->add_del_fields(req, buf, t); send_outreq(plugin, req); @@ -572,7 +572,7 @@ static struct command_result *do_clean(struct clean_info *cinfo) } if (cinfo->cleanup_reqs_remaining) - return command_still_pending(NULL); + return command_still_pending(cinfo->cmd); return clean_finished(cinfo); } @@ -628,7 +628,7 @@ static struct command_result *start_clean(struct clean_info *cinfo) } ps->offset = 0; - req = jsonrpc_request_start(plugin, NULL, + req = jsonrpc_request_start(plugin, cinfo->cmd, "wait", wait_done, wait_failed, ps); json_add_string(req->js, "subsystem", ops->system_name); diff --git a/plugins/libplugin.c b/plugins/libplugin.c index 20f0ecdecebc..dcd9c9ff10f3 100644 --- a/plugins/libplugin.c +++ b/plugins/libplugin.c @@ -164,11 +164,6 @@ struct command_result *command_param_failed(void) return &complete; } -struct command_result *command_done(void) -{ - return &complete; -} - struct json_filter **command_filter_ptr(struct command *cmd) { return &cmd->filter; @@ -295,7 +290,7 @@ static struct command_result *ignore_cb(struct command *command, const jsmntok_t *result, void *arg) { - return command_done(); + return &complete; } static void disable_request_cb(struct command *cmd, struct out_req *out) @@ -308,9 +303,6 @@ static void disable_request_cb(struct command *cmd, struct out_req *out) const char *json_id_prefix(const tal_t *ctx, const struct command *cmd) { - if (!cmd) - return ""; - /* Strip quotes! */ if (strstarts(cmd->id, "\"")) { assert(strlen(cmd->id) >= 2); @@ -354,6 +346,7 @@ jsonrpc_request_start_(struct plugin *plugin, struct command *cmd, { struct out_req *out; + assert(cmd); out = tal(cmd, struct out_req); out->id = append_json_id(out, plugin, method, id_prefix); out->cmd = cmd; @@ -364,8 +357,7 @@ jsonrpc_request_start_(struct plugin *plugin, struct command *cmd, tal_add_destructor2(out, destroy_out_req, plugin); /* If command goes away, don't call callbacks! */ - if (out->cmd) - tal_add_destructor2(out->cmd, disable_request_cb, out); + tal_add_destructor2(out->cmd, disable_request_cb, out); out->js = new_json_stream(NULL, cmd, NULL); json_object_start(out->js, NULL); @@ -481,8 +473,7 @@ struct command_result *command_finished(struct command *cmd, struct command_result *WARN_UNUSED_RESULT command_still_pending(struct command *cmd) { - if (cmd) - notleak_with_children(cmd); + notleak_with_children(cmd); return &pending; } @@ -1022,8 +1013,7 @@ static void handle_rpc_reply(struct plugin *plugin, const jsmntok_t *toks) } /* Remove destructor if one existed */ - if (out->cmd) - tal_del_destructor2(out->cmd, disable_request_cb, out); + tal_del_destructor2(out->cmd, disable_request_cb, out); /* We want to free this if callback doesn't. */ tal_steal(tmpctx, out); @@ -1129,7 +1119,7 @@ static struct command_result *batch_one_success(struct command *cmd, { /* If this frees stuff (e.g. fails), just return */ if (batch->cb && batch->cb(cmd, buf, result, batch->arg) == &complete) - return command_done(); + return &complete; return batch_one_complete(cmd, batch); } @@ -1140,7 +1130,7 @@ static struct command_result *batch_one_failed(struct command *cmd, { /* If this frees stuff (e.g. fails), just return */ if (batch->errcb && batch->errcb(cmd, buf, result, batch->arg) == &complete) - return command_done(); + return &complete; return batch_one_complete(cmd, batch); } diff --git a/plugins/libplugin.h b/plugins/libplugin.h index 4a1f1be26655..5d8204b32fed 100644 --- a/plugins/libplugin.h +++ b/plugins/libplugin.h @@ -123,7 +123,8 @@ struct out_req *jsonrpc_request_start_(struct plugin *plugin, const char *buf, const jsmntok_t *result, void *arg), - void *arg); + void *arg) + NON_NULL_ARGS(1, 2, 3, 4, 6); /* This variant has callbacks received whole obj, not "result" or * "error" members. */ @@ -202,30 +203,36 @@ struct request_batch *request_batch_new_(const tal_t *ctx, struct out_req *add_to_batch(struct command *cmd, struct request_batch *batch, - const char *cmdname); + const char *cmdname) + NON_NULL_ARGS(1, 2, 3); /* We want some commands to live after this command (possibly) * completes. This creates a new command with the same id but its own * lifetime: use aux_command_done() or tal_free() when you're done. */ -struct command *aux_command(const struct command *cmd); +struct command *aux_command(const struct command *cmd) + NON_NULL_ARGS(1); /* Runs finalcb immediately if batch is empty. */ struct command_result *batch_done(struct command *cmd, - struct request_batch *batch); + struct request_batch *batch) + NON_NULL_ARGS(1, 2); /* Helper to create a JSONRPC2 response stream with a "result" object. */ -struct json_stream *jsonrpc_stream_success(struct command *cmd); +struct json_stream *jsonrpc_stream_success(struct command *cmd) + NON_NULL_ARGS(1); /* Helper to create a JSONRPC2 response stream with an "error" object. */ struct json_stream *jsonrpc_stream_fail(struct command *cmd, int code, - const char *err); + const char *err) + NON_NULL_ARGS(1, 3); /* Helper to create a JSONRPC2 response stream with an "error" object, * to which will be added a "data" object. */ struct json_stream *jsonrpc_stream_fail_data(struct command *cmd, int code, - const char *err); + const char *err) + NON_NULL_ARGS(1, 3); /* Helper to jsonrpc_request_start() and send_outreq() to update datastore. * NULL cb means ignore, NULL errcb means plugin_error. @@ -244,7 +251,8 @@ struct command_result *jsonrpc_set_datastore_(struct plugin *plugin, const char *buf, const jsmntok_t *result, void *arg), - void *arg); + void *arg) + NON_NULL_ARGS(1, 2, 3, 4, 6); #define jsonrpc_set_datastore_string(plugin, cmd, path, str, mode, cb, errcb, arg) \ jsonrpc_set_datastore_((plugin), (cmd), (path), (str), true, (mode), \ @@ -286,7 +294,8 @@ struct command_result *jsonrpc_get_datastore_(struct plugin *plugin, struct command_result *(*binary_cb)(struct command *command, const u8 *val, void *arg), - void *arg); + void *arg) + NON_NULL_ARGS(1, 2, 3); #define jsonrpc_get_datastore_string(plugin, cmd, path, cb, arg) \ jsonrpc_get_datastore_((plugin), (cmd), (path), \ @@ -312,11 +321,13 @@ struct command_result *jsonrpc_get_datastore_(struct plugin *plugin, /* This command is finished, here's the response (the content of the * "result" or "error" field) */ WARN_UNUSED_RESULT -struct command_result *command_finished(struct command *cmd, struct json_stream *response); +struct command_result *command_finished(struct command *cmd, struct json_stream *response) + NON_NULL_ARGS(1, 2); /* Helper for a command that'll be finished in a callback. */ WARN_UNUSED_RESULT -struct command_result *command_still_pending(struct command *cmd); +struct command_result *command_still_pending(struct command *cmd) + NON_NULL_ARGS(1); /* Helper to create a zero or single-value JSON object; if @str is NULL, * object is empty. */ @@ -355,28 +366,34 @@ struct command_result *WARN_UNUSED_RESULT command_done_err(struct command *cmd, enum jsonrpc_errcode code, const char *errmsg, - const struct json_out *data); + const struct json_out *data) + NON_NULL_ARGS(1, 3); /* Send a raw error response. Useful for forwarding a previous * error after cleanup */ struct command_result *command_err_raw(struct command *cmd, - const char *json_str); + const char *json_str) + NON_NULL_ARGS(1, 2); /* This command is finished, here's the result object; @cmd cannot be NULL. */ struct command_result *WARN_UNUSED_RESULT -command_success(struct command *cmd, const struct json_out *result); +command_success(struct command *cmd, const struct json_out *result) + NON_NULL_ARGS(1, 2); /* End a hook normally (with "result": "continue") */ struct command_result *WARN_UNUSED_RESULT -command_hook_success(struct command *cmd); +command_hook_success(struct command *cmd) + NON_NULL_ARGS(1); /* End a notification handler. */ struct command_result *WARN_UNUSED_RESULT -notification_handled(struct command *cmd); +notification_handled(struct command *cmd) + NON_NULL_ARGS(1); /* End a command created with aux_command. */ struct command_result *WARN_UNUSED_RESULT -aux_command_done(struct command *cmd); +aux_command_done(struct command *cmd) + NON_NULL_ARGS(1); /** * What's the deprecation_ok state for this cmd? @@ -384,7 +401,8 @@ aux_command_done(struct command *cmd); * * Either the default, or the explicit connection override. */ -bool command_deprecated_ok_flag(const struct command *cmd); +bool command_deprecated_ok_flag(const struct command *cmd) + NON_NULL_ARGS(1); /* Helper for notification handler that will be finished in a callback. */ #define notification_handler_pending(cmd) command_still_pending(cmd) @@ -422,22 +440,21 @@ struct command_result *send_outreq(struct plugin *plugin, struct command_result *forward_error(struct command *cmd, const char *buf, const jsmntok_t *error, - void *arg); + void *arg) + NON_NULL_ARGS(1, 2, 3); /* Callback to just forward result and close request; @cmd cannot be NULL */ struct command_result *forward_result(struct command *cmd, const char *buf, const jsmntok_t *result, - void *arg); + void *arg) + NON_NULL_ARGS(1, 2, 3); /* Callback for timer where we expect a 'command_result'. All timers * must return this eventually, though they may do so via a convoluted * send_req() path. */ -struct command_result *timer_complete(struct command *cmd); - -/* Signals that we've completed a command. Useful for when - * there's no `cmd` present. Deprecated! */ -struct command_result *command_done(void); +struct command_result *timer_complete(struct command *cmd) + NON_NULL_ARGS(1); /* Access timer infrastructure to add a global timer for the plugin. * diff --git a/plugins/test/run-route-calc.c b/plugins/test/run-route-calc.c index e8b93ec7fb40..d2078e00d77b 100644 --- a/plugins/test/run-route-calc.c +++ b/plugins/test/run-route-calc.c @@ -13,7 +13,8 @@ /* AUTOGENERATED MOCKS START */ /* Generated stub for aux_command */ -struct command *aux_command(const struct command *cmd UNNEEDED) +struct command *aux_command(const struct command *cmd) + { fprintf(stderr, "aux_command called!\n"); abort(); } /* Generated stub for blinded_onion_hops */ u8 **blinded_onion_hops(const tal_t *ctx UNNEEDED, @@ -23,10 +24,12 @@ u8 **blinded_onion_hops(const tal_t *ctx UNNEEDED, const struct blinded_path *path UNNEEDED) { fprintf(stderr, "blinded_onion_hops called!\n"); abort(); } /* Generated stub for command_finished */ -struct command_result *command_finished(struct command *cmd UNNEEDED, struct json_stream *response UNNEEDED) +struct command_result *command_finished(struct command *cmd UNNEEDED, struct json_stream *response) + { fprintf(stderr, "command_finished called!\n"); abort(); } /* Generated stub for command_still_pending */ -struct command_result *command_still_pending(struct command *cmd UNNEEDED) +struct command_result *command_still_pending(struct command *cmd) + { 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) @@ -259,15 +262,18 @@ struct out_req *jsonrpc_request_start_(struct plugin *plugin UNNEEDED, const char *buf UNNEEDED, const jsmntok_t *result UNNEEDED, void *arg) UNNEEDED, - void *arg UNNEEDED) + void *arg) + { fprintf(stderr, "jsonrpc_request_start_ called!\n"); abort(); } /* Generated stub for jsonrpc_stream_fail */ struct json_stream *jsonrpc_stream_fail(struct command *cmd UNNEEDED, int code UNNEEDED, - const char *err UNNEEDED) + const char *err) + { fprintf(stderr, "jsonrpc_stream_fail called!\n"); abort(); } /* Generated stub for jsonrpc_stream_success */ -struct json_stream *jsonrpc_stream_success(struct command *cmd UNNEEDED) +struct json_stream *jsonrpc_stream_success(struct command *cmd) + { 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, diff --git a/plugins/test/run-route-overlong.c b/plugins/test/run-route-overlong.c index cb3dd356dee8..bf2186f16b3b 100644 --- a/plugins/test/run-route-overlong.c +++ b/plugins/test/run-route-overlong.c @@ -10,7 +10,8 @@ /* AUTOGENERATED MOCKS START */ /* Generated stub for aux_command */ -struct command *aux_command(const struct command *cmd UNNEEDED) +struct command *aux_command(const struct command *cmd) + { fprintf(stderr, "aux_command called!\n"); abort(); } /* Generated stub for blinded_onion_hops */ u8 **blinded_onion_hops(const tal_t *ctx UNNEEDED, @@ -20,10 +21,12 @@ u8 **blinded_onion_hops(const tal_t *ctx UNNEEDED, const struct blinded_path *path UNNEEDED) { fprintf(stderr, "blinded_onion_hops called!\n"); abort(); } /* Generated stub for command_finished */ -struct command_result *command_finished(struct command *cmd UNNEEDED, struct json_stream *response UNNEEDED) +struct command_result *command_finished(struct command *cmd UNNEEDED, struct json_stream *response) + { fprintf(stderr, "command_finished called!\n"); abort(); } /* Generated stub for command_still_pending */ -struct command_result *command_still_pending(struct command *cmd UNNEEDED) +struct command_result *command_still_pending(struct command *cmd) + { 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) @@ -256,15 +259,18 @@ struct out_req *jsonrpc_request_start_(struct plugin *plugin UNNEEDED, const char *buf UNNEEDED, const jsmntok_t *result UNNEEDED, void *arg) UNNEEDED, - void *arg UNNEEDED) + void *arg) + { fprintf(stderr, "jsonrpc_request_start_ called!\n"); abort(); } /* Generated stub for jsonrpc_stream_fail */ struct json_stream *jsonrpc_stream_fail(struct command *cmd UNNEEDED, int code UNNEEDED, - const char *err UNNEEDED) + const char *err) + { fprintf(stderr, "jsonrpc_stream_fail called!\n"); abort(); } /* Generated stub for jsonrpc_stream_success */ -struct json_stream *jsonrpc_stream_success(struct command *cmd UNNEEDED) +struct json_stream *jsonrpc_stream_success(struct command *cmd) + { 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, From e9c2c13edea783e75e544ec980e5a3a6d6175f75 Mon Sep 17 00:00:00 2001 From: Rusty Russell Date: Wed, 6 Nov 2024 21:29:36 +1030 Subject: [PATCH 12/18] libplugin: check that command has/hasn't terminated when we get pending/complete. Signed-off-by: Rusty Russell --- plugins/libplugin.c | 31 +++++++++++++++++++++++++++++-- 1 file changed, 29 insertions(+), 2 deletions(-) diff --git a/plugins/libplugin.c b/plugins/libplugin.c index dcd9c9ff10f3..1f65b5f0b3ab 100644 --- a/plugins/libplugin.c +++ b/plugins/libplugin.c @@ -989,11 +989,17 @@ struct command_result *jsonrpc_get_datastore_(struct plugin *plugin, return send_outreq(plugin, req); } +static void destroy_cmd_mark_freed(struct command *cmd, bool *cmd_freed) +{ + *cmd_freed = true; +} + static void handle_rpc_reply(struct plugin *plugin, const jsmntok_t *toks) { const jsmntok_t *idtok, *contenttok; struct out_req *out; struct command_result *res; + bool cmd_freed; const char *buf = plugin->rpc_buffer + plugin->rpc_read_offset; idtok = json_get_member(buf, toks, "id"); @@ -1018,6 +1024,10 @@ static void handle_rpc_reply(struct plugin *plugin, const jsmntok_t *toks) /* We want to free this if callback doesn't. */ tal_steal(tmpctx, out); + /* If they return complete, cmd should have been freed! */ + cmd_freed = false; + tal_add_destructor2(out->cmd, destroy_cmd_mark_freed, &cmd_freed); + contenttok = json_get_member(buf, toks, "error"); if (contenttok) { if (out->errcb) @@ -1037,7 +1047,14 @@ static void handle_rpc_reply(struct plugin *plugin, const jsmntok_t *toks) res = out->cb(out->cmd, buf, toks, out->arg); } - assert(res == &pending || res == &complete); + if (res == &complete) { + assert(cmd_freed); + } else { + assert(res == &pending); + assert(!cmd_freed); + tal_del_destructor2(out->cmd, destroy_cmd_mark_freed, + &cmd_freed); + } } struct command_result * @@ -1669,12 +1686,22 @@ static void call_plugin_timer(struct plugin *p, struct timer *timer) struct plugin_timer *t = container_of(timer, struct plugin_timer, timer); struct command *timer_cmd; struct command_result *res; + bool cmd_freed = false; /* This *isn't* owned by timer, which is owned by original command, * since they may free that in callback */ timer_cmd = new_command(p, p, t->id, "timer", COMMAND_TYPE_TIMER); + tal_add_destructor2(timer_cmd, destroy_cmd_mark_freed, &cmd_freed); + res = t->cb(timer_cmd, t->cb_arg); - assert(res == &pending || res == &complete); + if (res == &pending) { + assert(!cmd_freed); + tal_del_destructor2(timer_cmd, destroy_cmd_mark_freed, + &cmd_freed); + } else { + assert(res == &complete); + assert(cmd_freed); + } } static void destroy_plugin_timer(struct plugin_timer *timer, struct plugin *p) From cbf70dec4c1207e9636f03e735d476110f5b0f2d Mon Sep 17 00:00:00 2001 From: Rusty Russell Date: Wed, 6 Nov 2024 21:30:36 +1030 Subject: [PATCH 13/18] libplugin: clean up API. When we used to allow cmd to be NULL, we had to hand the plugin everywhere. We no longer do. 1. Various jsonrpc_ functions no longer need the plugin arg. 2. send_outreq no longer needs a plugin arg. 3. The init function takes a command, not a plugin. 4. Remove command_deprecated_in_nocmd_ok. Signed-off-by: Rusty Russell --- plugins/askrene/askrene.c | 9 +-- plugins/autoclean.c | 24 ++++---- plugins/bcli.c | 8 +-- plugins/bkpr/bookkeeper.c | 22 +++---- plugins/chanbackup.c | 57 ++++++++---------- plugins/commando.c | 30 +++++----- plugins/establish_onion_path.c | 8 +-- plugins/fetchinvoice.c | 12 ++-- plugins/funder.c | 56 ++++++++--------- plugins/keysend.c | 18 +++--- plugins/libplugin-pay.c | 44 +++++++------- plugins/libplugin.c | 96 +++++++++++------------------- plugins/libplugin.h | 63 +++++++++----------- plugins/offers.c | 26 ++++---- plugins/offers_inv_hook.c | 8 +-- plugins/offers_invreq_hook.c | 16 ++--- plugins/offers_offer.c | 12 ++-- plugins/pay.c | 48 +++++++-------- plugins/recklessrpc.c | 16 ++--- plugins/recover.c | 37 ++++++------ plugins/renepay/main.c | 7 ++- plugins/renepay/mods.c | 24 ++++---- plugins/renepay/routefail.c | 4 +- plugins/renepay/routetracker.c | 4 +- plugins/spender/fundchannel.c | 4 +- plugins/spender/main.c | 4 +- plugins/spender/multifundchannel.c | 50 +++++++--------- plugins/spender/multiwithdraw.c | 26 ++++---- plugins/spender/openchannel.c | 14 ++--- plugins/sql.c | 15 ++--- plugins/test/run-route-calc.c | 6 +- plugins/test/run-route-overlong.c | 6 +- plugins/topology.c | 21 ++++--- plugins/txprepare.c | 34 +++++------ tests/plugins/test_libplugin.c | 19 +++--- 35 files changed, 393 insertions(+), 455 deletions(-) diff --git a/plugins/askrene/askrene.c b/plugins/askrene/askrene.c index 8bb8dc97a18e..0d35add211f3 100644 --- a/plugins/askrene/askrene.c +++ b/plugins/askrene/askrene.c @@ -759,11 +759,11 @@ static struct command_result *json_getroutes(struct command *cmd, if (have_layer(info->layers, "auto.localchans")) { struct out_req *req; - req = jsonrpc_request_start(cmd->plugin, cmd, + req = jsonrpc_request_start(cmd, "listpeerchannels", listpeerchannels_done, forward_error, info); - return send_outreq(cmd->plugin, req); + return send_outreq(req); } else info->local_layer = NULL; @@ -1152,9 +1152,10 @@ static void askrene_markmem(struct plugin *plugin, struct htable *memtable) reserve_memleak_mark(askrene, memtable); } -static const char *init(struct plugin *plugin, +static const char *init(struct command *init_cmd, const char *buf UNUSED, const jsmntok_t *config UNUSED) { + struct plugin *plugin = init_cmd->plugin; struct askrene *askrene = tal(plugin, struct askrene); askrene->plugin = plugin; list_head_init(&askrene->layers); @@ -1165,7 +1166,7 @@ static const char *init(struct plugin *plugin, plugin_err(plugin, "Could not load gossmap %s: %s", GOSSIP_STORE_FILENAME, strerror(errno)); askrene->capacities = get_capacities(askrene, askrene->plugin, askrene->gossmap); - rpc_scan(plugin, "getinfo", take(json_out_obj(NULL, NULL, NULL)), + rpc_scan(init_cmd, "getinfo", take(json_out_obj(NULL, NULL, NULL)), "{id:%}", JSON_SCAN(json_to_node_id, &askrene->my_id)); plugin_set_data(plugin, askrene); diff --git a/plugins/autoclean.c b/plugins/autoclean.c index 5e560efe2c7d..c69683cfe30b 100644 --- a/plugins/autoclean.c +++ b/plugins/autoclean.c @@ -259,7 +259,7 @@ static struct command_result *clean_finished(struct clean_info *cinfo) plugin_log(plugin, LOG_DBG, "cleaned %zu from %s", num_cleaned, subsystem_to_str(&sv)); *total_cleaned(&sv) += num_cleaned; - jsonrpc_set_datastore_string(plugin, cinfo->cmd, + jsonrpc_set_datastore_string(cinfo->cmd, datastore_path(tmpctx, &sv, "num"), tal_fmt(tmpctx, "%"PRIu64, *total_cleaned(&sv)), @@ -509,10 +509,10 @@ static struct command_result *list_done(struct command *cmd, } subsystem->cinfo->cleanup_reqs_remaining++; - req = jsonrpc_request_start(plugin, cmd, ops->del_command, + req = jsonrpc_request_start(cmd, ops->del_command, del_done, del_failed, variant); ops->add_del_fields(req, buf, t); - send_outreq(plugin, req); + send_outreq(req); } subsystem->offset += max_entries_per_call; @@ -555,7 +555,7 @@ static struct command_result *do_clean(struct clean_info *cinfo) filter = tal_fmt(tmpctx, "{\"%s\":[{%s}]}", ops->arr_name, ops->list_filter); - req = jsonrpc_request_with_filter_start(plugin, cinfo->cmd, + req = jsonrpc_request_with_filter_start(cinfo->cmd, tal_fmt(tmpctx, "list%s", ops->system_name), @@ -567,7 +567,7 @@ static struct command_result *do_clean(struct clean_info *cinfo) json_add_string(req->js, "index", "created"); json_add_u64(req->js, "start", ps->offset); json_add_u64(req->js, "limit", max_entries_per_call); - send_outreq(plugin, req); + send_outreq(req); cinfo->cleanup_reqs_remaining++; } @@ -628,13 +628,13 @@ static struct command_result *start_clean(struct clean_info *cinfo) } ps->offset = 0; - req = jsonrpc_request_start(plugin, cinfo->cmd, + req = jsonrpc_request_start(cinfo->cmd, "wait", wait_done, wait_failed, ps); json_add_string(req->js, "subsystem", ops->system_name); json_add_string(req->js, "indexname", "created"); json_add_u64(req->js, "nextvalue", 0); - send_outreq(plugin, req); + send_outreq(req); cinfo->cleanup_reqs_remaining++; } @@ -742,29 +742,29 @@ static void memleak_mark_timer_cinfo(struct plugin *plugin, memleak_scan_obj(memtable, timer_cinfo); } -static const char *init(struct plugin *p, +static const char *init(struct command *init_cmd, const char *buf UNUSED, const jsmntok_t *config UNUSED) { struct subsystem_and_variant sv; - plugin = p; + plugin = init_cmd->plugin; /* Plugin owns global */ tal_steal(plugin, timer_cinfo); plugin_set_memleak_handler(plugin, memleak_mark_timer_cinfo); - cleantimer = global_timer(p, time_from_sec(cycle_seconds), do_clean_timer, NULL); + cleantimer = global_timer(plugin, time_from_sec(cycle_seconds), do_clean_timer, NULL); /* We don't care if this fails (it usually does, since entries * don't exist! */ sv = first_sv(); do { - rpc_scan_datastore_str(tmpctx, plugin, + rpc_scan_datastore_str(tmpctx, init_cmd, datastore_path(tmpctx, &sv, "num"), JSON_SCAN(json_to_u64, total_cleaned(&sv))); } while (next_sv(&sv)); /* Optimization FTW! */ - rpc_enable_batching(p); + rpc_enable_batching(plugin); return NULL; } diff --git a/plugins/bcli.c b/plugins/bcli.c index 1bb0226a9f74..5dc2de968643 100644 --- a/plugins/bcli.c +++ b/plugins/bcli.c @@ -1100,10 +1100,10 @@ static void memleak_mark_bitcoind(struct plugin *p, struct htable *memtable) memleak_scan_obj(memtable, bitcoind); } -static const char *init(struct plugin *p, const char *buffer UNUSED, +static const char *init(struct command *init_cmd, const char *buffer UNUSED, const jsmntok_t *config UNUSED) { - wait_and_check_bitcoind(p); + wait_and_check_bitcoind(init_cmd->plugin); /* Usually we fake up fees in regtest */ if (streq(chainparams->network_name, "regtest")) @@ -1111,8 +1111,8 @@ static const char *init(struct plugin *p, const char *buffer UNUSED, else bitcoind->fake_fees = false; - plugin_set_memleak_handler(p, memleak_mark_bitcoind); - plugin_log(p, LOG_INFORM, + plugin_set_memleak_handler(init_cmd->plugin, memleak_mark_bitcoind); + plugin_log(init_cmd->plugin, LOG_INFORM, "bitcoin-cli initialized and connected to bitcoind."); return NULL; diff --git a/plugins/bkpr/bookkeeper.c b/plugins/bkpr/bookkeeper.c index e2a6489ea0e4..13821538c02f 100644 --- a/plugins/bkpr/bookkeeper.c +++ b/plugins/bkpr/bookkeeper.c @@ -123,11 +123,11 @@ static struct command_result *json_channel_apy(struct command *cmd, return command_param_failed(); /* First get the current blockheight */ - req = jsonrpc_request_start(cmd->plugin, cmd, "getinfo", + req = jsonrpc_request_start(cmd, "getinfo", &getblockheight_done, forward_error, apyreq); - return send_outreq(cmd->plugin, req); + return send_outreq(req); } static struct command_result *param_csv_format(struct command *cmd, const char *name, @@ -1122,13 +1122,13 @@ static struct command_result *json_balance_snapshot(struct command *cmd, if (tal_count(new_accts) > 0) { struct out_req *req; - req = jsonrpc_request_start(cmd->plugin, cmd, + req = jsonrpc_request_start(cmd, "listpeerchannels", listpeerchannels_multi_done, log_error, new_accts); /* FIXME(vicenzopalazzo) require the channel by channel_id to avoid parsing not useful json */ - return send_outreq(cmd->plugin, req); + return send_outreq(req); } plugin_log(cmd->plugin, LOG_DBG, "Snapshot balances updated"); @@ -1288,20 +1288,20 @@ static struct command_result *lookup_invoice_desc(struct command *cmd, /* Otherwise will go away when event is cleaned up */ tal_steal(cmd, payment_hash); if (!amount_msat_is_zero(credit)) - req = jsonrpc_request_start(cmd->plugin, cmd, + req = jsonrpc_request_start(cmd, "listinvoices", listinvoices_done, log_error, payment_hash); else - req = jsonrpc_request_start(cmd->plugin, cmd, + req = jsonrpc_request_start(cmd, "listsendpays", listsendpays_done, log_error, payment_hash); json_add_sha256(req->js, "payment_hash", payment_hash); - return send_outreq(cmd->plugin, req); + return send_outreq(req); } struct event_info { @@ -1564,13 +1564,13 @@ parse_and_log_chain_move(struct command *cmd, is_channel_account(acct) ? acct : orig_acct); - req = jsonrpc_request_start(cmd->plugin, cmd, + req = jsonrpc_request_start(cmd, "listpeerchannels", listpeerchannels_done, log_error, info); /* FIXME: use the peer_id to reduce work here */ - return send_outreq(cmd->plugin, req); + return send_outreq(req); } /* Maybe mark acct as onchain resolved */ @@ -1977,8 +1977,10 @@ static const struct plugin_command commands[] = { }, }; -static const char *init(struct plugin *p, const char *b, const jsmntok_t *t) +static const char *init(struct command *init_cmd, const char *b, const jsmntok_t *t) { + struct plugin *p = init_cmd->plugin; + /* Switch to bookkeeper-dir, if specified */ if (datadir && chdir(datadir) != 0) { if (mkdir(datadir, 0700) != 0 && errno != EEXIST) diff --git a/plugins/chanbackup.c b/plugins/chanbackup.c index 60efc5ce5344..98835af1bbcd 100644 --- a/plugins/chanbackup.c +++ b/plugins/chanbackup.c @@ -261,7 +261,7 @@ static struct command_result *json_emergencyrecover(struct command *cmd, "Incompatible SCB file version on disk, contact the admin!"); } - req = jsonrpc_request_start(cmd->plugin, cmd, "recoverchannel", + req = jsonrpc_request_start(cmd, "recoverchannel", after_recover_rpc, &forward_error, NULL); @@ -273,7 +273,7 @@ static struct command_result *json_emergencyrecover(struct command *cmd, } json_array_end(req->js); - return send_outreq(cmd->plugin, req); + return send_outreq(req); } static void update_scb(struct plugin *p, struct scb_chan **channels) @@ -353,8 +353,7 @@ static struct command_result *peer_after_listdatastore(struct command *cmd, plugin_log(cmd->plugin, LOG_DBG, "sending their backup from our datastore"); - req = jsonrpc_request_start(cmd->plugin, - cmd, + req = jsonrpc_request_start(cmd, "sendcustommsg", peer_after_send_their_peer_strg, peer_after_send_their_peer_strg_err, @@ -364,7 +363,7 @@ static struct command_result *peer_after_listdatastore(struct command *cmd, json_add_hex(req->js, "msg", payload, tal_bytelen(payload)); - return send_outreq(cmd->plugin, req); + return send_outreq(req); } static struct command_result *peer_after_send_scb(struct command *cmd, @@ -374,8 +373,7 @@ static struct command_result *peer_after_send_scb(struct command *cmd, { plugin_log(cmd->plugin, LOG_DBG, "Peer storage sent!"); - return jsonrpc_get_datastore_binary(cmd->plugin, - cmd, + return jsonrpc_get_datastore_binary(cmd, tal_fmt(cmd, "chanbackup/peers/%s", fmt_node_id(tmpctx, @@ -464,8 +462,7 @@ static struct command_result *after_listpeers(struct command *cmd, nodeid = json_get_member(buf, peer, "id"); json_to_node_id(buf, nodeid, &node_id); - req = jsonrpc_request_start(cmd->plugin, - cmd, + req = jsonrpc_request_start(cmd, "sendcustommsg", after_send_scb_single, after_send_scb_single_fail, @@ -475,7 +472,7 @@ static struct command_result *after_listpeers(struct command *cmd, json_add_hex(req->js, "msg", serialise_scb, tal_bytelen(serialise_scb)); info->idx++; - send_outreq(cmd->plugin, req); + send_outreq(req); } } @@ -498,13 +495,12 @@ static struct command_result *after_staticbackup(struct command *cmd, update_scb(cmd->plugin, scb_chan); struct info *info = tal(cmd, struct info); info->idx = 0; - req = jsonrpc_request_start(cmd->plugin, - cmd, + req = jsonrpc_request_start(cmd, "listpeers", after_listpeers, &forward_error, info); - return send_outreq(cmd->plugin, req); + return send_outreq(req); } static struct command_result *json_state_changed(struct command *cmd, @@ -520,14 +516,13 @@ static struct command_result *json_state_changed(struct command *cmd, json_tok_streq(buf, statetok, "CHANNELD_AWAITING_LOCKIN") || json_tok_streq(buf, statetok, "DUALOPEND_AWAITING_LOCKIN")) { struct out_req *req; - req = jsonrpc_request_start(cmd->plugin, - cmd, + req = jsonrpc_request_start(cmd, "staticbackup", after_staticbackup, &forward_error, NULL); - return send_outreq(cmd->plugin, req); + return send_outreq(req); } return notification_handled(cmd); @@ -569,8 +564,7 @@ static struct command_result *peer_connected(struct command *cmd, return command_hook_success(cmd); } - req = jsonrpc_request_start(cmd->plugin, - cmd, + req = jsonrpc_request_start(cmd, "sendcustommsg", peer_after_send_scb, peer_after_send_scb_failed, @@ -580,7 +574,7 @@ static struct command_result *peer_connected(struct command *cmd, json_add_hex(req->js, "msg", serialise_scb, tal_bytelen(serialise_scb)); - return send_outreq(cmd->plugin, req); + return send_outreq(req); } static struct command_result *failed_peer_restore(struct command *cmd, @@ -635,8 +629,7 @@ static struct command_result *handle_your_peer_storage(struct command *cmd, } if (fromwire_peer_storage(cmd, payload, &payload_deserialise)) { - return jsonrpc_set_datastore_binary(cmd->plugin, - cmd, + return jsonrpc_set_datastore_binary(cmd, tal_fmt(cmd, "chanbackup/peers/%s", fmt_node_id(tmpctx, @@ -681,8 +674,7 @@ static struct command_result *handle_your_peer_storage(struct command *cmd, "Peer altered our data"); - return jsonrpc_set_datastore_binary(cmd->plugin, - cmd, + return jsonrpc_set_datastore_binary(cmd, "chanbackup/latestscb", decoded_bkp, "create-or-replace", @@ -727,7 +719,7 @@ static struct command_result *after_latestscb(struct command *cmd, "Incompatible version, Contact the admin!"); } - req = jsonrpc_request_start(cmd->plugin, cmd, "recoverchannel", + req = jsonrpc_request_start(cmd, "recoverchannel", after_recover_rpc, &forward_error, NULL); @@ -739,7 +731,7 @@ static struct command_result *after_latestscb(struct command *cmd, } json_array_end(req->js); - return send_outreq(cmd->plugin, req); + return send_outreq(req); } @@ -750,8 +742,7 @@ static struct command_result *json_restorefrompeer(struct command *cmd, if (!param(cmd, buf, params, NULL)) return command_param_failed(); - return jsonrpc_get_datastore_binary(cmd->plugin, - cmd, + return jsonrpc_get_datastore_binary(cmd, "chanbackup/latestscb", after_latestscb, NULL); @@ -774,7 +765,7 @@ static struct command_result *json_getemergencyrecoverdata(struct command *cmd, return command_finished(cmd, response); } -static const char *init(struct plugin *p, +static const char *init(struct command *init_cmd, const char *buf UNUSED, const jsmntok_t *config UNUSED) { @@ -784,29 +775,29 @@ static const char *init(struct plugin *p, u8 *features; /* Figure out if they specified --experimental-peer-storage */ - rpc_scan(p, "getinfo", + rpc_scan(init_cmd, "getinfo", take(json_out_obj(NULL, NULL, NULL)), "{our_features:{init:%}}", JSON_SCAN_TAL(tmpctx, json_tok_bin_from_hex, &features)); peer_backup = feature_offered(features, OPT_WANT_PEER_BACKUP_STORAGE); - rpc_scan(p, "staticbackup", + rpc_scan(init_cmd, "staticbackup", take(json_out_obj(NULL, NULL, NULL)), "{scb:%}", JSON_SCAN(json_to_scb_chan, &scb_chan)); - rpc_scan(p, "makesecret", + rpc_scan(init_cmd, "makesecret", take(json_out_obj(NULL, "hex", tal_hexstr(tmpctx, info_hex, tal_bytelen(info_hex)))), "{secret:%}", JSON_SCAN(json_to_secret, &secret)); - plugin_log(p, LOG_DBG, "Chanbackup Initialised!"); + plugin_log(init_cmd->plugin, LOG_DBG, "Chanbackup Initialised!"); /* flush the tmp file, if exists */ unlink_noerr("scb.tmp"); - maybe_create_new_scb(p, scb_chan); + maybe_create_new_scb(init_cmd->plugin, scb_chan); return NULL; } diff --git a/plugins/commando.c b/plugins/commando.c index ab8d056b75a0..f814e1f1e561 100644 --- a/plugins/commando.c +++ b/plugins/commando.c @@ -145,13 +145,13 @@ static struct command_result *send_response(struct command *cmd, towire(&cmd_msg, reply->buf + reply->off, msglen); reply->off += msglen; - req = jsonrpc_request_start(plugin, cmd, "sendcustommsg", + req = jsonrpc_request_start(cmd, "sendcustommsg", send_response, send_response, reply); json_add_node_id(req->js, "node_id", &reply->incoming->peer); json_add_hex_talarr(req->js, "msg", cmd_msg); tal_free(cmd_msg); - send_outreq(plugin, req); + send_outreq(req); return command_still_pending(cmd); } @@ -279,7 +279,7 @@ static struct command_result *execute_command(struct command *cmd, struct out_req *req; /* We handle success and failure the same */ - req = jsonrpc_request_whole_object_start(plugin, cmd, + req = jsonrpc_request_whole_object_start(cmd, json_strdup(tmpctx, cinfo->buf, cinfo->method), cinfo->cmdid_prefix, cmd_done, cinfo->incoming); @@ -318,7 +318,7 @@ static struct command_result *execute_command(struct command *cmd, json_tok_full(cinfo->buf, cinfo->filter), json_tok_full_len(cinfo->filter)); } - return send_outreq(plugin, req); + return send_outreq(req); } static struct command_result *checkrune_done(struct command *cmd, @@ -420,7 +420,7 @@ static struct command_result *try_command(struct command *cmd, destroy_commando(incoming, &incoming_commands); tal_del_destructor2(incoming, destroy_commando, &incoming_commands); - req = jsonrpc_request_start(plugin, cmd, "checkrune", + req = jsonrpc_request_start(cmd, "checkrune", checkrune_done, checkrune_failed, cinfo); json_add_node_id(req->js, "nodeid", &incoming->peer); @@ -428,7 +428,7 @@ static struct command_result *try_command(struct command *cmd, json_add_tok(req->js, "method", method, cinfo->buf); if (params) json_add_tok(req->js, "params", params, cinfo->buf); - return send_outreq(plugin, req); + return send_outreq(req); } static struct command_result *handle_incmd(struct command *cmd, @@ -630,12 +630,12 @@ static struct command_result *send_more_cmd(struct command *cmd, return command_still_pending(cmd); } - req = jsonrpc_request_start(plugin, cmd, "sendcustommsg", + req = jsonrpc_request_start(cmd, "sendcustommsg", send_more_cmd, forward_error, outgoing); json_add_node_id(req->js, "node_id", &outgoing->peer); json_add_hex_talarr(req->js, "msg", outgoing->msgs[outgoing->msg_off++]); - return send_outreq(plugin, req); + return send_outreq(req); } static struct command_result *json_commando(struct command *cmd, @@ -728,11 +728,11 @@ static struct command_result *forward_command(struct command *cmd, /* params could be an array, so use low-level helper */ struct out_req *req; - req = jsonrpc_request_whole_object_start(plugin, cmd, method, + req = jsonrpc_request_whole_object_start(cmd, method, json_id_prefix(tmpctx, cmd), forward_reply, NULL); json_add_tok(req->js, "params", params, buffer); - return send_outreq(plugin, req); + return send_outreq(req); } static struct command_result *json_commando_rune(struct command *cmd, @@ -787,13 +787,13 @@ static void memleak_mark_globals(struct plugin *p, struct htable *memtable) memleak_scan_obj(memtable, incoming_commands); } -static const char *init(struct plugin *p, +static const char *init(struct command *init_cmd, const char *buf UNUSED, const jsmntok_t *config UNUSED) { - outgoing_commands = tal_arr(p, struct commando *, 0); - incoming_commands = tal_arr(p, struct commando *, 0); - plugin = p; - plugin_set_memleak_handler(p, memleak_mark_globals); + plugin = init_cmd->plugin; + outgoing_commands = tal_arr(plugin, struct commando *, 0); + incoming_commands = tal_arr(plugin, struct commando *, 0); + plugin_set_memleak_handler(plugin, memleak_mark_globals); return NULL; } diff --git a/plugins/establish_onion_path.c b/plugins/establish_onion_path.c index 5aa723fb3093..c58702b92a04 100644 --- a/plugins/establish_onion_path.c +++ b/plugins/establish_onion_path.c @@ -53,10 +53,10 @@ static struct command_result *connect_direct(struct command *cmd, plugin_log(cmd->plugin, LOG_DBG, "connecting directly to %s", fmt_pubkey(tmpctx, &ci->dst)); - req = jsonrpc_request_start(cmd->plugin, cmd, + req = jsonrpc_request_start(cmd, "connect", connect_ok, command_failed, ci); json_add_pubkey(req->js, "id", &ci->dst); - return send_outreq(cmd->plugin, req); + return send_outreq(req); } static bool can_carry_onionmsg(const struct gossmap *map, @@ -231,9 +231,9 @@ struct command_result *establish_onion_path_(struct command *cmd, ci->gossmap = gossmap; /* We use listpeers here: we don't actually care about channels, just connections! */ - req = jsonrpc_request_start(cmd->plugin, cmd, "listpeers", + req = jsonrpc_request_start(cmd, "listpeers", listpeers_done, command_failed, ci); - return send_outreq(cmd->plugin, req); + return send_outreq(req); } diff --git a/plugins/fetchinvoice.c b/plugins/fetchinvoice.c index 2ca652d81a25..8ce7fc96370f 100644 --- a/plugins/fetchinvoice.c +++ b/plugins/fetchinvoice.c @@ -1045,7 +1045,7 @@ struct command_result *json_fetchinvoice(struct command *cmd, 0); /* Make the invoice request (fills in payer_key and payer_info) */ - req = jsonrpc_request_start(cmd->plugin, cmd, "createinvoicerequest", + req = jsonrpc_request_start(cmd, "createinvoicerequest", &invreq_done, &forward_error, sent); @@ -1055,7 +1055,7 @@ struct command_result *json_fetchinvoice(struct command *cmd, json_add_bool(req->js, "savetodb", false); if (rec_label) json_add_string(req->js, "recurrence_label", rec_label); - return send_outreq(cmd->plugin, req); + return send_outreq(req); } /* FIXME: Using a hook here is not ideal: technically it doesn't mean @@ -1094,12 +1094,12 @@ struct command_result *invoice_payment(struct command *cmd, continue; /* It was paid! Success. Return as per waitinvoice. */ - req = jsonrpc_request_start(cmd->plugin, i->cmd, "waitinvoice", + req = jsonrpc_request_start(i->cmd, "waitinvoice", &forward_result, &forward_error, i); json_add_escaped_string(req->js, "label", i->inv_label); - discard_result(send_outreq(cmd->plugin, req)); + discard_result(send_outreq(req)); break; } return command_hook_success(cmd); @@ -1157,14 +1157,14 @@ static struct command_result *sign_invoice(struct command *cmd, struct out_req *req; /* Get invoice signature and put in db so we can receive payment */ - req = jsonrpc_request_start(cmd->plugin, cmd, "createinvoice", + req = jsonrpc_request_start(cmd, "createinvoice", &createinvoice_done, &forward_error, sent); json_add_string(req->js, "invstring", invoice_encode(tmpctx, sent->inv)); json_add_preimage(req->js, "preimage", &sent->inv_preimage); json_add_escaped_string(req->js, "label", sent->inv_label); - return send_outreq(cmd->plugin, req); + return send_outreq(req); } static struct command_result *param_invreq(struct command *cmd, diff --git a/plugins/funder.c b/plugins/funder.c index b12707f92588..20c38a3d62cf 100644 --- a/plugins/funder.c +++ b/plugins/funder.c @@ -101,12 +101,12 @@ static struct command_result *unreserve_psbt(struct command *cmd, /* This can outlive the underlying cmd, so use an aux! */ aux = aux_command(cmd); - req = jsonrpc_request_start(open->p, aux, + req = jsonrpc_request_start(aux, "unreserveinputs", unreserve_done, unreserve_done, open); json_add_psbt(req->js, "psbt", open->psbt); - send_outreq(open->p, req); + send_outreq(req); /* We will free this in callback, but remove from list *now* * to avoid calling twice! */ @@ -215,7 +215,7 @@ remember_channel_utxos(struct command *cmd, fmt_channel_id(cmd, &open->channel_id)); - req = jsonrpc_request_start(cmd->plugin, cmd, + req = jsonrpc_request_start(cmd, "datastore", &datastore_add_success, &datastore_add_fail, @@ -237,7 +237,7 @@ remember_channel_utxos(struct command *cmd, /* We either update the existing or add a new one, nbd */ json_add_string(req->js, "mode", "create-or-replace"); json_add_hex(req->js, "hex", utxos_bin, tal_bytelen(utxos_bin)); - return send_outreq(cmd->plugin, req); + return send_outreq(req); } static struct command_result * @@ -319,7 +319,7 @@ json_openchannel2_sign_call(struct command *cmd, "openchannel_sign PSBT is %s", fmt_wally_psbt(tmpctx, psbt)); - req = jsonrpc_request_start(cmd->plugin, cmd, + req = jsonrpc_request_start(cmd, "signpsbt", &signpsbt_done, &forward_error, @@ -342,7 +342,7 @@ json_openchannel2_sign_call(struct command *cmd, fmt_channel_id(tmpctx, &open->channel_id), count, count == 1 ? "" : "s"); - return send_outreq(cmd->plugin, req); + return send_outreq(req); } static struct command_result * @@ -534,7 +534,7 @@ build_utxopsbt_request(struct command *cmd, { struct out_req *req; - req = jsonrpc_request_start(cmd->plugin, cmd, + req = jsonrpc_request_start(cmd, "utxopsbt", &psbt_funded, &psbt_fund_failed, @@ -723,7 +723,7 @@ listfunds_success(struct command *cmd, /* We don't re-reserve any UTXOS :) */ json_add_num(req->js, "reserve", 0); } else { - req = jsonrpc_request_start(cmd->plugin, cmd, + req = jsonrpc_request_start(cmd, "fundpsbt", &psbt_funded, &psbt_fund_failed, @@ -745,7 +745,7 @@ listfunds_success(struct command *cmd, json_add_bool(req->js, "excess_as_change", true); json_add_num(req->js, "locktime", info->locktime); - return send_outreq(cmd->plugin, req); + return send_outreq(req); } static struct command_result * @@ -892,13 +892,13 @@ json_openchannel2_call(struct command *cmd, } /* Figure out what our funds are */ - req = jsonrpc_request_start(cmd->plugin, cmd, + req = jsonrpc_request_start(cmd, "listfunds", &listfunds_success, &listfunds_failed, info); - return send_outreq(cmd->plugin, req); + return send_outreq(req); } static struct command_result * @@ -917,12 +917,12 @@ datastore_list_fail(struct command *cmd, /* Figure out what our funds are... same flow * as with openchannel2 callback. */ - req = jsonrpc_request_start(cmd->plugin, cmd, + req = jsonrpc_request_start(cmd, "listfunds", &listfunds_success, &listfunds_failed, info); - return send_outreq(cmd->plugin, req); + return send_outreq(req); } static struct command_result * @@ -986,12 +986,12 @@ datastore_list_success(struct command *cmd, tal_arr_expand(&info->prev_outs, outpoint); } - req = jsonrpc_request_start(cmd->plugin, cmd, + req = jsonrpc_request_start(cmd, "listfunds", &listfunds_success, &listfunds_failed, info); - return send_outreq(cmd->plugin, req); + return send_outreq(req); } /* Peer has asked us to RBF */ @@ -1061,7 +1061,7 @@ json_rbf_channel_call(struct command *cmd, } /* Fetch out previous utxos from the datastore */ - req = jsonrpc_request_start(cmd->plugin, cmd, + req = jsonrpc_request_start(cmd, "listdatastore", &datastore_list_success, &datastore_list_fail, @@ -1070,7 +1070,7 @@ json_rbf_channel_call(struct command *cmd, fmt_channel_id(cmd, &info->cid)); json_add_string(req->js, "key", chan_key); - return send_outreq(cmd->plugin, req); + return send_outreq(req); } static struct command_result *json_disconnect(struct command *cmd, @@ -1109,7 +1109,7 @@ delete_channel_from_datastore(struct command *cmd, * If we were clever, we'd have some way of tracking * channels that we actually might have data for * but this is much easier */ - req = jsonrpc_request_start(cmd->plugin, cmd, + req = jsonrpc_request_start(cmd, "deldatastore", &datastore_del_success, &datastore_del_fail, @@ -1117,7 +1117,7 @@ delete_channel_from_datastore(struct command *cmd, json_add_string(req->js, "key", tal_fmt(cmd, "funder/%s", fmt_channel_id(cmd, cid))); - return send_outreq(cmd->plugin, req); + return send_outreq(req); } static struct command_result *json_channel_state_changed(struct command *cmd, @@ -1417,7 +1417,7 @@ json_funderupdate(struct command *cmd, current_policy = tal_steal(NULL, policy); /* Update lightningd, also */ - req = jsonrpc_request_start(cmd->plugin, cmd, + req = jsonrpc_request_start(cmd, "setleaserates", &leaserates_set, &forward_error, @@ -1432,7 +1432,7 @@ json_funderupdate(struct command *cmd, json_add_lease_rates(req->js, &rates); } - return send_outreq(cmd->plugin, req); + return send_outreq(req); } static const struct plugin_command commands[] = { @@ -1442,7 +1442,7 @@ static const struct plugin_command commands[] = { }, }; -static void tell_lightningd_lease_rates(struct plugin *p, +static void tell_lightningd_lease_rates(struct command *init_cmd, struct lease_rates *rates) { struct json_out *jout; @@ -1470,7 +1470,7 @@ static void tell_lightningd_lease_rates(struct plugin *p, json_out_end(jout, '}'); json_out_finished(jout); - rpc_scan(p, "setleaserates", take(jout), + rpc_scan(init_cmd, "setleaserates", take(jout), /* Unused */ "{lease_fee_base_msat:%}", JSON_SCAN(json_to_msat, &mval)); @@ -1483,7 +1483,7 @@ static void memleak_mark(struct plugin *p, struct htable *memtable) memleak_scan_obj(memtable, current_policy); } -static const char *init(struct plugin *p, const char *b, const jsmntok_t *t) +static const char *init(struct command *init_cmd, const char *b, const jsmntok_t *t) { const char *err; struct amount_msat msat; @@ -1492,19 +1492,19 @@ static const char *init(struct plugin *p, const char *b, const jsmntok_t *t) err = funder_check_policy(current_policy); if (err) - plugin_err(p, "Invalid parameter combination: %s", err); + plugin_err(init_cmd->plugin, "Invalid parameter combination: %s", err); if (current_policy->rates) - tell_lightningd_lease_rates(p, current_policy->rates); + tell_lightningd_lease_rates(init_cmd, current_policy->rates); - rpc_scan(p, "listconfigs", + rpc_scan(init_cmd, "listconfigs", take(json_out_obj(NULL, NULL, NULL)), "{configs:" "{min-emergency-msat:{value_msat:%}}}", JSON_SCAN(json_to_msat, &msat)); emergency_reserve = amount_msat_to_sat_round_down(msat); - plugin_set_memleak_handler(p, memleak_mark); + plugin_set_memleak_handler(init_cmd->plugin, memleak_mark); return NULL; } diff --git a/plugins/keysend.c b/plugins/keysend.c index b04386d504b8..a2020f1558dd 100644 --- a/plugins/keysend.c +++ b/plugins/keysend.c @@ -154,13 +154,13 @@ static bool jsonarr_accumulate_u64(const char *buffer, return true; } -static const char *init(struct plugin *p, const char *buf UNUSED, +static const char *init(struct command *init_cmd, const char *buf UNUSED, const jsmntok_t *config UNUSED) { - rpc_scan(p, "getinfo", take(json_out_obj(NULL, NULL, NULL)), "{id:%}", + rpc_scan(init_cmd, "getinfo", take(json_out_obj(NULL, NULL, NULL)), "{id:%}", JSON_SCAN(json_to_node_id, &my_id)); - global_hints = notleak_with_children(channel_hint_set_new(p)); + global_hints = notleak_with_children(channel_hint_set_new(init_cmd->plugin)); accepted_extra_tlvs = notleak(tal_arr(NULL, u64, 0)); /* BOLT #4: @@ -173,7 +173,7 @@ static const char *init(struct plugin *p, const char *buf UNUSED, maxdelay_default = 2016; /* accept-htlc-tlv-types deprecated in v23.08, but still grab it! */ /* max-locktime-blocks deprecated in v24.05, but still grab it! */ - rpc_scan(p, "listconfigs", take(json_out_obj(NULL, NULL, NULL)), + rpc_scan(init_cmd, "listconfigs", take(json_out_obj(NULL, NULL, NULL)), "{configs:{" "max-locktime-blocks?:{value_int:%}," "accept-htlc-tlv-types?:{value_str:%}," @@ -311,19 +311,19 @@ static struct command_result *json_keysend(struct command *cmd, const char *buf, /* We do pre-approval immediately (note: even if command_check_only!) */ if (command_check_only(cmd)) { - req = jsonrpc_request_start(p->plugin, cmd, "check", + req = jsonrpc_request_start(cmd, "check", preapprovekeysend_succeed, forward_error, p); json_add_string(req->js, "command_to_check", "preapprovekeysend"); } else { - req = jsonrpc_request_start(p->plugin, cmd, "preapprovekeysend", + req = jsonrpc_request_start(cmd, "preapprovekeysend", preapprovekeysend_succeed, forward_error, p); } json_add_node_id(req->js, "destination", p->route_destination); json_add_sha256(req->js, "payment_hash", p->payment_hash); json_add_amount_msat(req->js, "amount_msat", p->our_amount); - return send_outreq(cmd->plugin, req); + return send_outreq(req); } static const struct plugin_command commands[] = { @@ -571,7 +571,7 @@ static struct command_result *htlc_accepted_call(struct command *cmd, * label could collide (unlikely since we use the nanosecond time). If * the call to `invoice` fails we will just continue, and `lightningd` * will be nice and reject the payment. */ - req = jsonrpc_request_start(cmd->plugin, cmd, "invoice", + req = jsonrpc_request_start(cmd, "invoice", &htlc_accepted_invoice_created, &htlc_accepted_invoice_failed, ki); @@ -592,7 +592,7 @@ static struct command_result *htlc_accepted_call(struct command *cmd, } json_add_preimage(req->js, "preimage", &ki->payment_preimage); - return send_outreq(cmd->plugin, req); + return send_outreq(req); } static const struct plugin_hook hooks[] = { diff --git a/plugins/libplugin-pay.c b/plugins/libplugin-pay.c index 944a169df96d..7a086a262c78 100644 --- a/plugins/libplugin-pay.c +++ b/plugins/libplugin-pay.c @@ -318,11 +318,11 @@ payment_getblockheight_success(struct command *cmd, /* Now we just need to ask `lightningd` what height it has * synced up to, and we remember that as chainlag. */ - req = jsonrpc_request_start(p->plugin, cmd, "waitblockheight", + req = jsonrpc_request_start(cmd, "waitblockheight", &payment_waitblockheight_cb, &payment_rpc_failure, p); json_add_u32(req->js, "blockheight", 0); - return send_outreq(p->plugin, req); + return send_outreq(req); } #define INVALID_BLOCKHEIGHT UINT32_MAX @@ -364,11 +364,11 @@ payment_start_at_blockheight(struct payment *p, u32 blockheight) * height, allowing us to send while still syncing. */ struct out_req *req; - req = jsonrpc_request_start(p->plugin, payment_cmd(p), "getchaininfo", + req = jsonrpc_request_start(payment_cmd(p), "getchaininfo", &payment_getblockheight_success, &payment_rpc_failure, p); json_add_u32(req->js, "last_height", 0); - return send_outreq(p->plugin, req); + return send_outreq(req); } void payment_start(struct payment *p) @@ -1021,10 +1021,10 @@ static struct command_result *payment_getlocalmods(struct payment *p) if (p->mods) return payment_getroute(p); - req = jsonrpc_request_start(p->plugin, payment_cmd(p), "listpeerchannels", + req = jsonrpc_request_start(payment_cmd(p), "listpeerchannels", &payment_listpeerchannels_success, &payment_rpc_failure, p); - return send_outreq(p->plugin, req); + return send_outreq(req); } static struct payment_result *tal_sendpay_result_from_json(const tal_t *ctx, @@ -1639,11 +1639,11 @@ payment_waitsendpay_finished(struct command *cmd, const char *buffer, "Extracted channel_update %s from onionreply %s", tal_hex(tmpctx, update), tal_hex(tmpctx, p->result->raw_message)); - req = jsonrpc_request_start(p->plugin, payment_cmd(p), "addgossip", + req = jsonrpc_request_start(payment_cmd(p), "addgossip", payment_addgossip_success, payment_addgossip_failure, p); json_add_hex_talarr(req->js, "message", update); - return send_outreq(p->plugin, req); + return send_outreq(req); } return payment_addgossip_success(cmd, NULL, NULL, p); @@ -1655,13 +1655,13 @@ static struct command_result *payment_sendonion_success(struct command *cmd, struct payment *p) { struct out_req *req; - req = jsonrpc_request_start(p->plugin, payment_cmd(p), "waitsendpay", + req = jsonrpc_request_start(payment_cmd(p), "waitsendpay", payment_waitsendpay_finished, payment_waitsendpay_finished, p); json_add_sha256(req->js, "payment_hash", p->payment_hash); json_add_num(req->js, "partid", p->partid); json_add_u64(req->js, "groupid", p->groupid); - return send_outreq(p->plugin, req); + return send_outreq(req); } static struct command_result *payment_createonion_success(struct command *cmd, @@ -1683,7 +1683,7 @@ static struct command_result *payment_createonion_success(struct command *cmd, p->createonion_response = json_to_createonion_response(p, buffer, toks); - req = jsonrpc_request_start(p->plugin, payment_cmd(p), "sendonion", + req = jsonrpc_request_start(payment_cmd(p), "sendonion", payment_sendonion_success, payment_rpc_failure, p); json_add_hex_talarr(req->js, "onion", p->createonion_response->onion); @@ -1726,7 +1726,7 @@ static struct command_result *payment_createonion_success(struct command *cmd, if (p->local_invreq_id) json_add_sha256(req->js, "localinvreqid", p->local_invreq_id); - return send_outreq(p->plugin, req); + return send_outreq(req); } /* Temporary serialization method for the tlv_payload.data until we rework the @@ -1913,7 +1913,7 @@ static struct command_result *payment_sendonion(struct payment *p) { struct out_req *req; u8 *payload, *tlv; - req = jsonrpc_request_start(p->plugin, payment_cmd(p), "createonion", + req = jsonrpc_request_start(payment_cmd(p), "createonion", payment_createonion_success, payment_rpc_failure, p); @@ -1942,7 +1942,7 @@ static struct command_result *payment_sendonion(struct payment *p) json_add_secret(req->js, "sessionkey", p->createonion_request->session_key); - return send_outreq(p->plugin, req); + return send_outreq(req); } /* Mutual recursion. */ @@ -2563,10 +2563,10 @@ static struct command_result *local_channel_hints_cb(void *d UNUSED, struct paym if (p->parent != NULL || p->step != PAYMENT_STEP_INITIALIZED) return payment_continue(p); - req = jsonrpc_request_start(p->plugin, payment_cmd(p), "listpeerchannels", + req = jsonrpc_request_start(payment_cmd(p), "listpeerchannels", local_channel_hints_listpeerchannels, local_channel_hints_listpeerchannels, p); - return send_outreq(p->plugin, req); + return send_outreq(req); } REGISTER_PAYMENT_MODIFIER(local_channel_hints, void *, NULL, local_channel_hints_cb); @@ -3184,11 +3184,11 @@ static struct command_result *shadow_route_extend(struct shadow_route_data *d, struct payment *p) { struct out_req *req; - req = jsonrpc_request_start(p->plugin, payment_cmd(p), "listchannels", + req = jsonrpc_request_start(payment_cmd(p), "listchannels", shadow_route_listchannels, payment_rpc_failure, p); json_add_node_id(req->js, "source", &d->destination); - return send_outreq(p->plugin, req); + return send_outreq(req); } static struct command_result *shadow_route_listchannels(struct command *cmd, @@ -3451,12 +3451,12 @@ static struct command_result *direct_pay_cb(struct direct_pay_data *d, struct pa if (p->step != PAYMENT_STEP_INITIALIZED) return payment_continue(p); - req = jsonrpc_request_start(p->plugin, payment_cmd(p), "listpeerchannels", + req = jsonrpc_request_start(payment_cmd(p), "listpeerchannels", direct_pay_listpeerchannels, direct_pay_listpeerchannels, p); json_add_node_id(req->js, "id", p->route_destination); - return send_outreq(p->plugin, req); + return send_outreq(req); } static struct direct_pay_data *direct_pay_init(struct payment *p) @@ -3755,11 +3755,11 @@ static struct command_result *payee_incoming_limit_step_cb(void *d UNUSED, struc /* Get information on the destination. */ struct out_req *req; - req = jsonrpc_request_start(p->plugin, payment_cmd(p), "listchannels", + req = jsonrpc_request_start(payment_cmd(p), "listchannels", &payee_incoming_limit_count, &payment_rpc_failure, p); json_add_node_id(req->js, "source", p->route_destination); - return send_outreq(p->plugin, req); + return send_outreq(req); } REGISTER_PAYMENT_MODIFIER(payee_incoming_limit, void *, NULL, diff --git a/plugins/libplugin.c b/plugins/libplugin.c index 1f65b5f0b3ab..6c7d5891d14e 100644 --- a/plugins/libplugin.c +++ b/plugins/libplugin.c @@ -120,7 +120,7 @@ struct plugin { struct plugin_option *opts; /* Anything special to do at init ? */ - const char *(*init)(struct plugin *p, + const char *(*init)(struct command *init_cmd, const char *buf, const jsmntok_t *); /* Has the manifest been sent already ? */ bool manifested; @@ -169,22 +169,6 @@ struct json_filter **command_filter_ptr(struct command *cmd) return &cmd->filter; } -static void complain_deprecated_nocmd(const char *feature, - bool allowing, - struct plugin *plugin) -{ - if (!allowing) { - /* Mild log message for disallowing */ - plugin_log(plugin, LOG_DBG, - "Note: disallowing deprecated %s", - feature); - } else { - plugin_log(plugin, LOG_BROKEN, - "DEPRECATED API USED: %s", - feature); - } -} - /* New command, without a filter */ static struct command *new_command(const tal_t *ctx, struct plugin *plugin, @@ -202,18 +186,6 @@ static struct command *new_command(const tal_t *ctx, return cmd; } -bool command_deprecated_in_nocmd_ok(struct plugin *plugin, - const char *name, - const char *depr_start, - const char *depr_end) -{ - return deprecated_ok(plugin->deprecated_ok, - name, - depr_start, depr_end, - plugin->beglist, - complain_deprecated_nocmd, plugin); -} - static void complain_deprecated(const char *feature, bool allowing, struct command *cmd) @@ -330,7 +302,7 @@ static void destroy_out_req(struct out_req *out_req, struct plugin *plugin) /* FIXME: Move lightningd/jsonrpc to common/ ? */ struct out_req * -jsonrpc_request_start_(struct plugin *plugin, struct command *cmd, +jsonrpc_request_start_(struct command *cmd, const char *method, const char *id_prefix, const char *filter, @@ -348,13 +320,13 @@ jsonrpc_request_start_(struct plugin *plugin, struct command *cmd, assert(cmd); out = tal(cmd, struct out_req); - out->id = append_json_id(out, plugin, method, id_prefix); + out->id = append_json_id(out, cmd->plugin, method, id_prefix); out->cmd = cmd; out->cb = cb; out->errcb = errcb; out->arg = arg; - strmap_add(&plugin->out_reqs, out->id, out); - tal_add_destructor2(out, destroy_out_req, plugin); + strmap_add(&cmd->plugin->out_reqs, out->id, out); + tal_add_destructor2(out, destroy_out_req, cmd->plugin); /* If command goes away, don't call callbacks! */ tal_add_destructor2(out->cmd, disable_request_cb, out); @@ -753,12 +725,14 @@ static const jsmntok_t *sync_req(const tal_t *ctx, return contents; } -const jsmntok_t *jsonrpc_request_sync(const tal_t *ctx, struct plugin *plugin, +const jsmntok_t *jsonrpc_request_sync(const tal_t *ctx, + struct command *init_cmd, const char *method, const struct json_out *params TAKES, const char **resp) { - return sync_req(ctx, plugin, method, params, resp); + assert(streq(init_cmd->methodname, "init")); + return sync_req(ctx, init_cmd->plugin, method, params, resp); } /* Returns contents of scanning guide on 'result' */ @@ -777,7 +751,7 @@ static const char *rpc_scan_core(const tal_t *ctx, } /* Synchronous routine to send command and extract fields from response */ -void rpc_scan(struct plugin *plugin, +void rpc_scan(struct command *init_cmd, const char *method, const struct json_out *params TAKES, const char *guide, @@ -786,12 +760,13 @@ void rpc_scan(struct plugin *plugin, const char *err; va_list ap; + assert(streq(init_cmd->methodname, "init")); va_start(ap, guide); - err = rpc_scan_core(tmpctx, plugin, method, params, guide, ap); + err = rpc_scan_core(tmpctx, init_cmd->plugin, method, params, guide, ap); va_end(ap); if (err) - plugin_err(plugin, "Could not parse %s in reply to %s: %s", + plugin_err(init_cmd->plugin, "Could not parse %s in reply to %s: %s", guide, method, err); } @@ -806,7 +781,7 @@ static void json_add_keypath(struct json_out *jout, const char *fieldname, const } static const char *rpc_scan_datastore(const tal_t *ctx, - struct plugin *plugin, + struct command *init_cmd, const char *path, const char *hex_or_string, va_list ap) @@ -814,6 +789,7 @@ static const char *rpc_scan_datastore(const tal_t *ctx, const char *guide; struct json_out *params; + assert(streq(init_cmd->methodname, "init")); params = json_out_new(NULL); json_out_start(params, NULL, '{'); json_add_keypath(params, "key", path); @@ -821,12 +797,12 @@ static const char *rpc_scan_datastore(const tal_t *ctx, json_out_finished(params); guide = tal_fmt(tmpctx, "{datastore:[0:{%s:%%}]}", hex_or_string); - return rpc_scan_core(ctx, plugin, "listdatastore", take(params), + return rpc_scan_core(ctx, init_cmd->plugin, "listdatastore", take(params), guide, ap); } const char *rpc_scan_datastore_str(const tal_t *ctx, - struct plugin *plugin, + struct command *init_cmd, const char *path, ...) { @@ -834,14 +810,14 @@ const char *rpc_scan_datastore_str(const tal_t *ctx, va_list ap; va_start(ap, path); - ret = rpc_scan_datastore(ctx, plugin, path, "string", ap); + ret = rpc_scan_datastore(ctx, init_cmd, path, "string", ap); va_end(ap); return ret; } /* This variant scans the hex encoding, not the string */ const char *rpc_scan_datastore_hex(const tal_t *ctx, - struct plugin *plugin, + struct command *init_cmd, const char *path, ...) { @@ -849,7 +825,7 @@ const char *rpc_scan_datastore_hex(const tal_t *ctx, va_list ap; va_start(ap, path); - ret = rpc_scan_datastore(ctx, plugin, path, "hex", ap); + ret = rpc_scan_datastore(ctx, init_cmd, path, "hex", ap); va_end(ap); return ret; } @@ -879,8 +855,7 @@ static struct command_result *datastore_fail(struct command *command, json_tok_full(buf, result)); } -struct command_result *jsonrpc_set_datastore_(struct plugin *plugin, - struct command *cmd, +struct command_result *jsonrpc_set_datastore_(struct command *cmd, const char *path, const void *value, bool value_is_string, @@ -902,7 +877,7 @@ struct command_result *jsonrpc_set_datastore_(struct plugin *plugin, if (!errcb) errcb = datastore_fail; - req = jsonrpc_request_start(plugin, cmd, "datastore", cb, errcb, arg); + req = jsonrpc_request_start(cmd, "datastore", cb, errcb, arg); json_add_keypath(req->js->jout, "key", path); if (value_is_string) @@ -910,7 +885,7 @@ struct command_result *jsonrpc_set_datastore_(struct plugin *plugin, else json_add_hex_talarr(req->js, "hex", value); json_add_string(req->js, "mode", mode); - return send_outreq(plugin, req); + return send_outreq(req); } struct get_ds_info { @@ -962,8 +937,7 @@ static struct command_result *listdatastore_done(struct command *cmd, return dsi->binary_cb(cmd, val, dsi->arg); } -struct command_result *jsonrpc_get_datastore_(struct plugin *plugin, - struct command *cmd, +struct command_result *jsonrpc_get_datastore_(struct command *cmd, const char *path, struct command_result *(*string_cb)(struct command *command, const char *val, @@ -981,12 +955,12 @@ struct command_result *jsonrpc_get_datastore_(struct plugin *plugin, dsi->arg = arg; /* listdatastore doesn't fail (except API misuse) */ - req = jsonrpc_request_start(plugin, cmd, "listdatastore", + req = jsonrpc_request_start(cmd, "listdatastore", listdatastore_done, datastore_fail, dsi); tal_steal(req, dsi); json_add_keypath(req->js->jout, "key", path); - return send_outreq(plugin, req); + return send_outreq(req); } static void destroy_cmd_mark_freed(struct command *cmd, bool *cmd_freed) @@ -1058,7 +1032,7 @@ static void handle_rpc_reply(struct plugin *plugin, const jsmntok_t *toks) } struct command_result * -send_outreq(struct plugin *plugin, const struct out_req *req) +send_outreq(const struct out_req *req) { /* The "param" object. */ if (req->errcb) @@ -1066,10 +1040,8 @@ send_outreq(struct plugin *plugin, const struct out_req *req) json_object_end(req->js); json_stream_close(req->js, req->cmd); - ld_rpc_send(plugin, req->js); - - if (req->cmd != NULL) - notleak_with_children(req->cmd); + ld_rpc_send(req->cmd->plugin, req->js); + notleak_with_children(req->cmd); return &pending; } @@ -1157,7 +1129,7 @@ struct out_req *add_to_batch(struct command *cmd, { batch->num_remaining++; - return jsonrpc_request_start(cmd->plugin, cmd, cmdname, + return jsonrpc_request_start(cmd, cmdname, batch_one_success, batch_one_failed, batch); @@ -1527,7 +1499,7 @@ static struct command_result *handle_init(struct command *cmd, } if (p->init) { - const char *disable = p->init(p, buf, configtok); + const char *disable = p->init(cmd, buf, configtok); if (disable) return command_success(cmd, json_out_obj(cmd, "disable", disable)); @@ -1535,7 +1507,7 @@ static struct command_result *handle_init(struct command *cmd, if (with_rpc) { p->beglist = NULL; - rpc_scan(p, "listconfigs", + rpc_scan(cmd, "listconfigs", take(json_out_obj(NULL, "config", "i-promise-to-fix-broken-api-user")), "{configs:{i-promise-to-fix-broken-api-user?:%}}", JSON_SCAN_TAL(p, json_to_apilist, &p->beglist)); @@ -2267,7 +2239,7 @@ static struct io_plan *stdout_conn_init(struct io_conn *conn, static struct plugin *new_plugin(const tal_t *ctx, const char *argv0, bool developer, - const char *(*init)(struct plugin *p, + const char *(*init)(struct command *init_cmd, const char *buf, const jsmntok_t *), const enum plugin_restartability restartability, @@ -2361,7 +2333,7 @@ static struct plugin *new_plugin(const tal_t *ctx, } void plugin_main(char *argv[], - const char *(*init)(struct plugin *p, + const char *(*init)(struct command *init_cmd, const char *buf, const jsmntok_t *), void *data, const enum plugin_restartability restartability, diff --git a/plugins/libplugin.h b/plugins/libplugin.h index 5d8204b32fed..af9728bd9ff8 100644 --- a/plugins/libplugin.h +++ b/plugins/libplugin.h @@ -110,8 +110,7 @@ struct plugin_hook { const struct feature_set *plugin_feature_set(const struct plugin *p); /* Helper to create a JSONRPC2 request stream. Send it with `send_outreq`. */ -struct out_req *jsonrpc_request_start_(struct plugin *plugin, - struct command *cmd, +struct out_req *jsonrpc_request_start_(struct command *cmd, const char *method, const char *id_prefix, const char *filter, @@ -124,12 +123,12 @@ struct out_req *jsonrpc_request_start_(struct plugin *plugin, const jsmntok_t *result, void *arg), void *arg) - NON_NULL_ARGS(1, 2, 3, 4, 6); + NON_NULL_ARGS(1, 2, 3, 5); /* This variant has callbacks received whole obj, not "result" or * "error" members. */ -#define jsonrpc_request_start(plugin, cmd, method, cb, errcb, arg) \ - jsonrpc_request_start_((plugin), (cmd), (method), \ +#define jsonrpc_request_start(cmd, method, cb, errcb, arg) \ + jsonrpc_request_start_((cmd), (method), \ json_id_prefix(tmpctx, (cmd)), NULL, \ typesafe_cb_preargs(struct command_result *, void *, \ (cb), (arg), \ @@ -143,8 +142,8 @@ struct out_req *jsonrpc_request_start_(struct plugin *plugin, const jsmntok_t *result), \ (arg)) -#define jsonrpc_request_with_filter_start(plugin, cmd, method, filter, cb, errcb, arg) \ - jsonrpc_request_start_((plugin), (cmd), (method), \ +#define jsonrpc_request_with_filter_start(cmd, method, filter, cb, errcb, arg) \ + jsonrpc_request_start_((cmd), (method), \ json_id_prefix(tmpctx, (cmd)), (filter), \ typesafe_cb_preargs(struct command_result *, void *, \ (cb), (arg), \ @@ -160,8 +159,8 @@ struct out_req *jsonrpc_request_start_(struct plugin *plugin, /* This variant has callbacks received whole obj, not "result" or * "error" members. It also doesn't start params{}. */ -#define jsonrpc_request_whole_object_start(plugin, cmd, method, id_prefix, cb, arg) \ - jsonrpc_request_start_((plugin), (cmd), (method), (id_prefix), NULL, \ +#define jsonrpc_request_whole_object_start(cmd, method, id_prefix, cb, arg) \ + jsonrpc_request_start_((cmd), (method), (id_prefix), NULL, \ typesafe_cb_preargs(struct command_result *, void *, \ (cb), (arg), \ struct command *command, \ @@ -237,8 +236,7 @@ struct json_stream *jsonrpc_stream_fail_data(struct command *cmd, /* Helper to jsonrpc_request_start() and send_outreq() to update datastore. * NULL cb means ignore, NULL errcb means plugin_error. */ -struct command_result *jsonrpc_set_datastore_(struct plugin *plugin, - struct command *cmd, +struct command_result *jsonrpc_set_datastore_(struct command *cmd, const char *path, const void *value, bool value_is_string, @@ -252,10 +250,10 @@ struct command_result *jsonrpc_set_datastore_(struct plugin *plugin, const jsmntok_t *result, void *arg), void *arg) - NON_NULL_ARGS(1, 2, 3, 4, 6); + NON_NULL_ARGS(1, 2, 3, 5); -#define jsonrpc_set_datastore_string(plugin, cmd, path, str, mode, cb, errcb, arg) \ - jsonrpc_set_datastore_((plugin), (cmd), (path), (str), true, (mode), \ +#define jsonrpc_set_datastore_string(cmd, path, str, mode, cb, errcb, arg) \ + jsonrpc_set_datastore_((cmd), (path), (str), true, (mode), \ typesafe_cb_preargs(struct command_result *, void *, \ (cb), (arg), \ struct command *command, \ @@ -268,8 +266,8 @@ struct command_result *jsonrpc_set_datastore_(struct plugin *plugin, const jsmntok_t *result), \ (arg)) -#define jsonrpc_set_datastore_binary(plugin, cmd, path, tal_ptr, mode, cb, errcb, arg) \ - jsonrpc_set_datastore_((plugin), (cmd), (path), (tal_ptr), false, (mode), \ +#define jsonrpc_set_datastore_binary(cmd, path, tal_ptr, mode, cb, errcb, arg) \ + jsonrpc_set_datastore_((cmd), (path), (tal_ptr), false, (mode), \ typesafe_cb_preargs(struct command_result *, void *, \ (cb), (arg), \ struct command *command, \ @@ -285,8 +283,7 @@ struct command_result *jsonrpc_set_datastore_(struct plugin *plugin, /* Helper to jsonrpc_request_start() and send_outreq() to read datastore. * If the value not found, cb gets NULL @val. */ -struct command_result *jsonrpc_get_datastore_(struct plugin *plugin, - struct command *cmd, +struct command_result *jsonrpc_get_datastore_(struct command *cmd, const char *path, struct command_result *(*string_cb)(struct command *command, const char *val, @@ -295,10 +292,10 @@ struct command_result *jsonrpc_get_datastore_(struct plugin *plugin, const u8 *val, void *arg), void *arg) - NON_NULL_ARGS(1, 2, 3); + NON_NULL_ARGS(1, 2); -#define jsonrpc_get_datastore_string(plugin, cmd, path, cb, arg) \ - jsonrpc_get_datastore_((plugin), (cmd), (path), \ +#define jsonrpc_get_datastore_string(cmd, path, cb, arg) \ + jsonrpc_get_datastore_((cmd), (path), \ typesafe_cb_preargs(struct command_result *, \ void *, \ (cb), (arg), \ @@ -307,8 +304,8 @@ struct command_result *jsonrpc_get_datastore_(struct plugin *plugin, NULL, \ (arg)) -#define jsonrpc_get_datastore_binary(plugin, cmd, path, cb, arg) \ - jsonrpc_get_datastore_((plugin), (cmd), (path), \ +#define jsonrpc_get_datastore_binary(cmd, path, cb, arg) \ + jsonrpc_get_datastore_((cmd), (path), \ NULL, \ typesafe_cb_preargs(struct command_result *, \ void *, \ @@ -345,12 +342,6 @@ bool command_deprecated_in_named_ok(struct command *cmd, const char *depr_start, const char *depr_end); -/* For commando, which doesn't have a "cmd" incoming */ -bool command_deprecated_in_nocmd_ok(struct plugin *plugin, - const char *name, - const char *depr_start, - const char *depr_end); - /* Call this on fatal error. */ void NORETURN PRINTF_FMT(2,3) plugin_err(struct plugin *p, const char *fmt, ...); @@ -409,7 +400,7 @@ bool command_deprecated_ok_flag(const struct command *cmd) /* Synchronous helper to send command and extract fields from * response; can only be used in init callback. */ -void rpc_scan(struct plugin *plugin, +void rpc_scan(struct command *init_cmd, const char *method, const struct json_out *params TAKES, const char *guide, @@ -420,12 +411,12 @@ void rpc_scan(struct plugin *plugin, * /-separated. Final arg is JSON_SCAN or JSON_SCAN_TAL. */ const char *rpc_scan_datastore_str(const tal_t *ctx, - struct plugin *plugin, + struct command *init_cmd, const char *path, ...); /* This variant scans the hex encoding, not the string */ const char *rpc_scan_datastore_hex(const tal_t *ctx, - struct plugin *plugin, + struct command *init_cmd, const char *path, ...); @@ -433,8 +424,7 @@ const char *rpc_scan_datastore_hex(const tal_t *ctx, void rpc_enable_batching(struct plugin *plugin); /* Send an async rpc request to lightningd. */ -struct command_result *send_outreq(struct plugin *plugin, - const struct out_req *req); +struct command_result *send_outreq(const struct out_req *req); /* Callback to just forward error and close request; @cmd cannot be NULL */ struct command_result *forward_error(struct command *cmd, @@ -600,7 +590,7 @@ bool flag_jsonfmt(struct plugin *plugin, struct json_stream *js, const char *fie /* The main plugin runner: append with 0 or more plugin_option(), then NULL. */ void NORETURN LAST_ARG_NULL plugin_main(char *argv[], - const char *(*init)(struct plugin *p, + const char *(*init)(struct command *init_cmd, const char *buf, const jsmntok_t *), void *data TAKES, @@ -660,7 +650,8 @@ void plugin_set_memleak_handler(struct plugin *plugin, /* Synchronously call a JSON-RPC method and return its contents and * the parser token. */ -const jsmntok_t *jsonrpc_request_sync(const tal_t *ctx, struct plugin *plugin, +const jsmntok_t *jsonrpc_request_sync(const tal_t *ctx, + struct command *init_cmd, const char *method, const struct json_out *params TAKES, const char **resp); diff --git a/plugins/offers.c b/plugins/offers.c index 21b50943bdaa..c4248455e664 100644 --- a/plugins/offers.c +++ b/plugins/offers.c @@ -104,7 +104,7 @@ inject_onionmessage_(struct command *cmd, { struct out_req *req; - req = jsonrpc_request_start(cmd->plugin, cmd, "injectonionmessage", + req = jsonrpc_request_start(cmd, "injectonionmessage", cb, errcb, arg); json_add_pubkey(req->js, "path_key", &omsg->first_path_key); json_array_start(req->js, "hops"); @@ -115,7 +115,7 @@ inject_onionmessage_(struct command *cmd, json_object_end(req->js); } json_array_end(req->js); - return send_outreq(cmd->plugin, req); + return send_outreq(req); } /* Holds the details while we wait for establish_onion_path to connect */ @@ -326,9 +326,9 @@ struct command_result *find_best_peer_(struct command *cmd, data->cb = cb; data->arg = arg; data->needed_feature = needed_feature; - req = jsonrpc_request_start(cmd->plugin, cmd, "listincoming", + req = jsonrpc_request_start(cmd, "listincoming", listincoming_done, forward_error, data); - return send_outreq(cmd->plugin, req); + return send_outreq(req); } static const struct plugin_hook hooks[] = { @@ -1377,30 +1377,30 @@ static struct command_result *json_decode(struct command *cmd, if (decodable->emergency_recover) { struct out_req *req; - req = jsonrpc_request_start(cmd->plugin, cmd, "makesecret", + req = jsonrpc_request_start(cmd, "makesecret", after_makesecret, &forward_error, decodable); json_add_string(req->js, "string", "scb secret"); - return send_outreq(cmd->plugin, req); + return send_outreq(req); } return command_finished(cmd, response); } -static const char *init(struct plugin *p, +static const char *init(struct command *init_cmd, const char *buf UNUSED, const jsmntok_t *config UNUSED) { - rpc_scan(p, "getinfo", + rpc_scan(init_cmd, "getinfo", take(json_out_obj(NULL, NULL, NULL)), "{id:%}", JSON_SCAN(json_to_pubkey, &id)); - rpc_scan(p, "getchaininfo", + rpc_scan(init_cmd, "getchaininfo", take(json_out_obj(NULL, "last_height", NULL)), "{headercount:%}", JSON_SCAN(json_to_u32, &blockheight)); - rpc_scan(p, "listconfigs", + rpc_scan(init_cmd, "listconfigs", take(json_out_obj(NULL, NULL, NULL)), "{configs:" "{cltv-final:{value_int:%}," @@ -1408,17 +1408,17 @@ static const char *init(struct plugin *p, JSON_SCAN(json_to_u16, &cltv_final), JSON_SCAN(json_to_bool, &offers_enabled)); - rpc_scan(p, "makesecret", + rpc_scan(init_cmd, "makesecret", take(json_out_obj(NULL, "string", BOLT12_ID_BASE_STRING)), "{secret:%}", JSON_SCAN(json_to_secret, &invoicesecret_base)); - rpc_scan(p, "makesecret", + rpc_scan(init_cmd, "makesecret", take(json_out_obj(NULL, "string", "offer-blinded-path")), "{secret:%}", JSON_SCAN(json_to_secret, &offerblinding_base)); - rpc_scan(p, "makesecret", + rpc_scan(init_cmd, "makesecret", take(json_out_obj(NULL, "string", NODE_ALIAS_BASE_STRING)), "{secret:%}", JSON_SCAN(json_to_secret, &nodealias_base)); diff --git a/plugins/offers_inv_hook.c b/plugins/offers_inv_hook.c index 42f9295ca787..658ae255b537 100644 --- a/plugins/offers_inv_hook.c +++ b/plugins/offers_inv_hook.c @@ -190,11 +190,11 @@ static struct command_result *listinvreqs_done(struct command *cmd, fmt_amount_msat(tmpctx, amt), fmt_sha256(tmpctx, &inv->invreq_id)); - req = jsonrpc_request_start(cmd->plugin, cmd, "pay", + req = jsonrpc_request_start(cmd, "pay", pay_done, pay_error, inv); json_add_string(req->js, "bolt11", invoice_encode(tmpctx, inv->inv)); json_add_sha256(req->js, "localinvreqid", &inv->invreq_id); - return send_outreq(cmd->plugin, req); + return send_outreq(req); } static struct command_result *listinvreqs_error(struct command *cmd, @@ -359,9 +359,9 @@ struct command_result *handle_invoice(struct command *cmd, } /* Now find the invoice_request. */ - req = jsonrpc_request_start(cmd->plugin, cmd, "listinvoicerequests", + req = jsonrpc_request_start(cmd, "listinvoicerequests", listinvreqs_done, listinvreqs_error, inv); json_add_sha256(req->js, "invreq_id", &inv->invreq_id); - return send_outreq(cmd->plugin, req); + return send_outreq(req); } diff --git a/plugins/offers_invreq_hook.c b/plugins/offers_invreq_hook.c index eced33fc6800..fdbcbcd59f74 100644 --- a/plugins/offers_invreq_hook.c +++ b/plugins/offers_invreq_hook.c @@ -223,7 +223,7 @@ static struct command_result *create_invoicereq(struct command *cmd, * if we don't have public channels! */ /* Now, write invoice to db (returns the signed version) */ - req = jsonrpc_request_start(cmd->plugin, cmd, "createinvoice", + req = jsonrpc_request_start(cmd, "createinvoice", createinvoice_done, createinvoice_error, ir); json_add_string(req->js, "invstring", invoice_encode(tmpctx, ir->inv)); @@ -231,7 +231,7 @@ static struct command_result *create_invoicereq(struct command *cmd, json_add_label(req->js, &ir->offer_id, ir->inv->invreq_payer_id, ir->inv->invreq_recurrence_counter ? *ir->inv->invreq_recurrence_counter : 0); - return send_outreq(cmd->plugin, req); + return send_outreq(req); } /* FIXME: This is naive: @@ -545,7 +545,7 @@ static struct command_result *check_previous_invoice(struct command *cmd, if (*ir->invreq->invreq_recurrence_counter == 0) return check_period(cmd, ir, *ir->inv->invoice_created_at); - req = jsonrpc_request_start(cmd->plugin, cmd, + req = jsonrpc_request_start(cmd, "listinvoices", prev_invoice_done, error, @@ -554,7 +554,7 @@ static struct command_result *check_previous_invoice(struct command *cmd, &ir->offer_id, ir->invreq->invreq_payer_id, *ir->invreq->invreq_recurrence_counter - 1); - return send_outreq(cmd->plugin, req); + return send_outreq(req); } /* BOLT-offers #12: @@ -750,13 +750,13 @@ static struct command_result *convert_currency(struct command *cmd, for (size_t i = 0; i < iso4217->minor_unit; i++) double_amount /= 10; - req = jsonrpc_request_start(cmd->plugin, cmd, "currencyconvert", + req = jsonrpc_request_start(cmd, "currencyconvert", currency_done, error, ir); json_add_stringn(req->js, "currency", (const char *)ir->invreq->offer_currency, tal_bytelen(ir->invreq->offer_currency)); json_add_primitive_fmt(req->js, "amount", "%f", double_amount); - return send_outreq(cmd->plugin, req); + return send_outreq(req); } static struct command_result *listoffers_done(struct command *cmd, @@ -1063,8 +1063,8 @@ struct command_result *handle_invoice_request(struct command *cmd, invreq_offer_id(ir->invreq, &ir->offer_id); /* Now, look up offer */ - req = jsonrpc_request_start(cmd->plugin, cmd, "listoffers", + req = jsonrpc_request_start(cmd, "listoffers", listoffers_done, error, ir); json_add_sha256(req->js, "offer_id", &ir->offer_id); - return send_outreq(cmd->plugin, req); + return send_outreq(req); } diff --git a/plugins/offers_offer.c b/plugins/offers_offer.c index d8d75f93e284..5541a1979391 100644 --- a/plugins/offers_offer.c +++ b/plugins/offers_offer.c @@ -265,7 +265,7 @@ static struct command_result *create_offer(struct command *cmd, struct out_req *req; /* We simply pass this through. */ - req = jsonrpc_request_start(cmd->plugin, cmd, "createoffer", + req = jsonrpc_request_start(cmd, "createoffer", check_result, forward_error, offinfo); json_add_string(req->js, "bolt12", @@ -274,7 +274,7 @@ static struct command_result *create_offer(struct command *cmd, json_add_string(req->js, "label", offinfo->label); json_add_bool(req->js, "single_use", *offinfo->single_use); - return send_outreq(cmd->plugin, req); + return send_outreq(req); } static struct command_result *found_best_peer(struct command *cmd, @@ -567,14 +567,14 @@ struct command_result *json_offer(struct command *cmd, if (offer->offer_currency) { struct out_req *req; - req = jsonrpc_request_start(cmd->plugin, cmd, "currencyconvert", + req = jsonrpc_request_start(cmd, "currencyconvert", currency_done, forward_error, offinfo); json_add_u32(req->js, "amount", 1); json_add_stringn(req->js, "currency", (const char *)offer->offer_currency, tal_bytelen(offer->offer_currency)); - return send_outreq(cmd->plugin, req); + return send_outreq(req); } return maybe_add_path(cmd, offinfo); @@ -587,7 +587,7 @@ static struct command_result *call_createinvoicerequest(struct command *cmd, { struct out_req *req; - req = jsonrpc_request_start(cmd->plugin, cmd, "createinvoicerequest", + req = jsonrpc_request_start(cmd, "createinvoicerequest", check_result, forward_error, invreq); json_add_string(req->js, "bolt12", invrequest_encode(tmpctx, invreq)); @@ -595,7 +595,7 @@ static struct command_result *call_createinvoicerequest(struct command *cmd, json_add_bool(req->js, "single_use", single_use); if (label) json_add_string(req->js, "recurrence_label", label); - return send_outreq(cmd->plugin, req); + return send_outreq(req); } struct invrequest_data { diff --git a/plugins/pay.c b/plugins/pay.c index 37f9ce661b4a..9d91fabdba61 100644 --- a/plugins/pay.c +++ b/plugins/pay.c @@ -552,7 +552,7 @@ static struct command_result *json_listpays(struct command *cmd, NULL)) return command_param_failed(); - req = jsonrpc_request_start(cmd->plugin, cmd, "listsendpays", + req = jsonrpc_request_start(cmd, "listsendpays", listsendpays_done, forward_error, cast_const(char *, invstring)); if (invstring) @@ -563,7 +563,7 @@ static struct command_result *json_listpays(struct command *cmd, if (status_str) json_add_string(req->js, "status", status_str); - return send_outreq(cmd->plugin, req); + return send_outreq(req); } static void memleak_mark_payments(struct plugin *p, struct htable *memtable) @@ -571,10 +571,10 @@ static void memleak_mark_payments(struct plugin *p, struct htable *memtable) memleak_scan_list_head(memtable, &payments); } -static const char *init(struct plugin *p, +static const char *init(struct command *init_cmd, const char *buf UNUSED, const jsmntok_t *config UNUSED) { - rpc_scan(p, "getinfo", take(json_out_obj(NULL, NULL, NULL)), + rpc_scan(init_cmd, "getinfo", take(json_out_obj(NULL, NULL, NULL)), "{id:%}", JSON_SCAN(json_to_node_id, &my_id)); /* BOLT #4: @@ -586,17 +586,17 @@ static const char *init(struct plugin *p, /* FIXME: Typo in spec for CLTV in descripton! But it breaks our spelling check, so we omit it above */ maxdelay_default = 2016; - global_hints = notleak_with_children(channel_hint_set_new(p)); + global_hints = notleak_with_children(channel_hint_set_new(init_cmd->plugin)); - /* max-locktime-blocks deprecated in v24.05, but still grab it! */ - rpc_scan(p, "listconfigs", take(json_out_obj(NULL, NULL, NULL)), - "{configs:" - "{max-locktime-blocks?:{value_int:%}," - "experimental-offers:{set:%}}}", - JSON_SCAN(json_to_number, &maxdelay_default), - JSON_SCAN(json_to_bool, &exp_offers)); + /* max-locktime-blocks deprecated in v24.05, but still grab it! */ + rpc_scan(init_cmd, "listconfigs", take(json_out_obj(NULL, NULL, NULL)), + "{configs:" + "{max-locktime-blocks?:{value_int:%}," + "experimental-offers:{set:%}}}", + JSON_SCAN(json_to_number, &maxdelay_default), + JSON_SCAN(json_to_bool, &exp_offers)); - plugin_set_memleak_handler(p, memleak_mark_payments); + plugin_set_memleak_handler(init_cmd->plugin, memleak_mark_payments); return NULL; } @@ -835,7 +835,7 @@ static struct command_result *selfpay(struct command *cmd, struct payment *p) /* This "struct payment" simply gets freed once command is done. */ tal_steal(cmd, p); - req = jsonrpc_request_start(cmd->plugin, cmd, "sendpay", + req = jsonrpc_request_start(cmd, "sendpay", selfpay_success, forward_error, p); /* Empty route means "to-self" */ @@ -855,7 +855,7 @@ static struct command_result *selfpay(struct command *cmd, struct payment *p) json_add_hex_talarr(req->js, "payment_metadata", p->payment_metadata); if (p->description) json_add_string(req->js, "description", p->description); - return send_outreq(cmd->plugin, req); + return send_outreq(req); } /* We are interested in any prior attempts to pay this payment_hash / @@ -1033,12 +1033,12 @@ start_payment(struct command *cmd, struct payment *p) /* We're keeping this around now */ tal_steal(cmd->plugin, p); - req = jsonrpc_request_start(cmd->plugin, cmd, "listsendpays", + req = jsonrpc_request_start(cmd, "listsendpays", payment_listsendpays_previous, payment_listsendpays_previous, p); json_add_sha256(req->js, "payment_hash", p->payment_hash); - return send_outreq(cmd->plugin, req); + return send_outreq(req); } static bool scidtok_eq(const char *buf, @@ -1176,10 +1176,10 @@ decrypt_done(struct command *cmd, p->blindedpath->first_node_id.is_pubkey = false; p->blindedpath->first_node_id.scidd.scid = *enctlv->short_channel_id; - req = jsonrpc_request_with_filter_start(cmd->plugin, cmd, "listpeerchannels", + req = jsonrpc_request_with_filter_start(cmd, "listpeerchannels", "{\"channels\":[{\"peer_id\":true,\"short_channel_id\":true,\"alias\":{\"local\":true}}]}", listpeerchannels_done, forward_error, p); - return send_outreq(cmd->plugin, req); + return send_outreq(req); } else { return command_fail(cmd, PAY_UNPARSEABLE_ONION, "Invalid TLV for blinded path (no next!): %s", @@ -1202,13 +1202,13 @@ preapproveinvoice_succeed(struct command *cmd, if (p->blindedpath && node_id_eq(p->route_destination, &my_id)) { struct out_req *req; - req = jsonrpc_request_start(cmd->plugin, cmd, "decryptencrypteddata", + req = jsonrpc_request_start(cmd, "decryptencrypteddata", decrypt_done, forward_error, p); json_add_hex_talarr(req->js, "encrypted_data", p->blindedpath->path[0]->encrypted_recipient_data); json_add_pubkey(req->js, "path_key", &p->blindedpath->first_path_key); - return send_outreq(cmd->plugin, req); + return send_outreq(req); } return start_payment(cmd, p); @@ -1465,17 +1465,17 @@ static struct command_result *json_pay(struct command *cmd, /* Now preapprove, then start payment. */ if (command_check_only(cmd)) { - req = jsonrpc_request_start(p->plugin, cmd, "check", + req = jsonrpc_request_start(cmd, "check", &preapproveinvoice_succeed, &forward_error, p); json_add_string(req->js, "command_to_check", "preapproveinvoice"); } else { - req = jsonrpc_request_start(p->plugin, cmd, "preapproveinvoice", + req = jsonrpc_request_start(cmd, "preapproveinvoice", &preapproveinvoice_succeed, &forward_error, p); } json_add_string(req->js, "bolt11", p->invstring); - return send_outreq(cmd->plugin, req); + return send_outreq(req); } static struct command_result *handle_channel_hint_update(struct command *cmd, diff --git a/plugins/recklessrpc.c b/plugins/recklessrpc.c index c64bfb413209..7ade61945d60 100644 --- a/plugins/recklessrpc.c +++ b/plugins/recklessrpc.c @@ -281,29 +281,29 @@ static struct command_result *json_reckless(struct command *cmd, return reckless_call(cmd, command, target, target2); } -static const char *init(struct plugin *p, +static const char *init(struct command *init_cmd, const char *buf UNUSED, const jsmntok_t *config UNUSED) { - plugin = p; - rpc_scan(p, "listconfigs", + plugin = init_cmd->plugin; + rpc_scan(init_cmd, "listconfigs", take(json_out_obj(NULL, NULL, NULL)), "{configs:{" "conf?:{value_str:%}," "lightning-dir:{value_str:%}," "network:{value_str:%}" "}}", - JSON_SCAN_TAL(p, json_strdup, &lconfig.config), - JSON_SCAN_TAL(p, json_strdup, &lconfig.lightningdir), - JSON_SCAN_TAL(p, json_strdup, &lconfig.network)); + JSON_SCAN_TAL(plugin, json_strdup, &lconfig.config), + JSON_SCAN_TAL(plugin, json_strdup, &lconfig.lightningdir), + JSON_SCAN_TAL(plugin, json_strdup, &lconfig.network)); /* These lightning config parameters need to stick around for each * reckless call. */ if (lconfig.config) notleak(lconfig.config); notleak(lconfig.lightningdir); notleak(lconfig.network); - plugin_log(p, LOG_DBG, "plugin initialized!"); - plugin_log(p, LOG_DBG, "lightning-dir: %s", lconfig.lightningdir); + plugin_log(plugin, LOG_DBG, "plugin initialized!"); + plugin_log(plugin, LOG_DBG, "lightning-dir: %s", lconfig.lightningdir); return NULL; } diff --git a/plugins/recover.c b/plugins/recover.c index 052de006f94f..e2f069859684 100644 --- a/plugins/recover.c +++ b/plugins/recover.c @@ -95,11 +95,11 @@ static struct command_result *find_peer_storage (struct command *cmd) peer_storage_timer = NULL; struct out_req *req; - req = jsonrpc_request_start(plugin, cmd, "restorefrompeer", + req = jsonrpc_request_start(cmd, "restorefrompeer", after_restorefrompeer, &forward_error, NULL); - return send_outreq(plugin, req); + return send_outreq(req); } static struct command_result *do_find_peer_storage(struct command *cmd, void *unused) @@ -128,8 +128,7 @@ static struct command_result *do_check_gossip(struct command *cmd, void *unused) gossmap_node_get_id(global_gossmap, neighbour, &peer_id); struct out_req *req; - req = jsonrpc_request_start(plugin, - cmd, + req = jsonrpc_request_start(cmd, "connect", connect_success, connect_fail, @@ -139,7 +138,7 @@ static struct command_result *do_check_gossip(struct command *cmd, void *unused) plugin_log(plugin, LOG_DBG, "Connecting to: %s", fmt_node_id(tmpctx, &peer_id)); - send_outreq(plugin, req); + send_outreq(req); } @@ -160,29 +159,27 @@ static void entering_recovery_mode(struct command *cmd) if (!already_has_peers) { for (size_t i = 0; i < ARRAY_SIZE(nodes_for_gossip); i++) { struct out_req *req; - req = jsonrpc_request_start(plugin, - cmd, + req = jsonrpc_request_start(cmd, "connect", connect_success, connect_fail, NULL); plugin_log (plugin, LOG_DBG, "Connecting to %s", nodes_for_gossip[i]); json_add_string(req->js, "id", nodes_for_gossip[i]); - send_outreq(plugin, req); + send_outreq(req); } } struct out_req *req_emer_recovery; /* Let's try to recover whatever we have in the emergencyrecover file. */ - req_emer_recovery = jsonrpc_request_start(plugin, - cmd, + req_emer_recovery = jsonrpc_request_start(cmd, "emergencyrecover", after_emergency_recover, &forward_error, NULL); - send_outreq(plugin, req_emer_recovery); + send_outreq(req_emer_recovery); find_exes_timer = global_timer( plugin, time_from_sec(CHECK_GOSSIP_INTERVAL), do_check_gossip, cmd); return; @@ -225,11 +222,11 @@ static struct command_result *after_listpeerchannels(struct command *cmd, static struct command_result *check_lost_peer(struct command *cmd) { struct out_req *req; - req = jsonrpc_request_start(plugin, cmd, "listpeerchannels", + req = jsonrpc_request_start(cmd, "listpeerchannels", after_listpeerchannels, &forward_error, NULL); - return send_outreq(plugin, req); + return send_outreq(req); } static struct command_result *do_check_lost_peer(struct command *cmd, void *unused) @@ -245,12 +242,12 @@ static struct command_result *do_check_lost_peer(struct command *cmd, void *unus return check_lost_peer(cmd); } -static const char *init(struct plugin *p, +static const char *init(struct command *init_cmd, const char *buf UNUSED, const jsmntok_t *config UNUSED) { - plugin = p; - plugin_log(p, LOG_DBG, "Recover Plugin Initialised!"); + plugin = init_cmd->plugin; + plugin_log(plugin, LOG_DBG, "Recover Plugin Initialised!"); recovery = false; lost_state_timer = global_timer(plugin, time_from_sec(STARTUP_TIME), do_check_lost_peer, NULL); @@ -258,7 +255,7 @@ static const char *init(struct plugin *p, size_t num_cupdates_rejected; /* Find number of peers */ - rpc_scan(p, "getinfo", + rpc_scan(init_cmd, "getinfo", take(json_out_obj(NULL, NULL, NULL)), "{id:%,num_peers:%}", JSON_SCAN(json_to_node_id, &local_id), @@ -269,15 +266,15 @@ static const char *init(struct plugin *p, &num_cupdates_rejected)); if (!global_gossmap) - plugin_err(p, "Could not load gossmap %s: %s", + plugin_err(plugin, "Could not load gossmap %s: %s", GOSSIP_STORE_FILENAME, strerror(errno)); if (num_cupdates_rejected) - plugin_log(p, LOG_DBG, + plugin_log(plugin, LOG_DBG, "gossmap ignored %zu channel updates", num_cupdates_rejected); - plugin_log(p, LOG_DBG, "Gossmap loaded!"); + plugin_log(plugin, LOG_DBG, "Gossmap loaded!"); already_has_peers = num_peers > 1 ? 1: 0; diff --git a/plugins/renepay/main.c b/plugins/renepay/main.c index f7ff5c5023b0..fee200b2c52f 100644 --- a/plugins/renepay/main.c +++ b/plugins/renepay/main.c @@ -35,16 +35,17 @@ static void memleak_mark(struct plugin *p, struct htable *memtable) memleak_scan_htable(memtable, &pay_plugin->pending_routes->raw); } -static const char *init(struct plugin *p, +static const char *init(struct command *init_cmd, const char *buf UNUSED, const jsmntok_t *config UNUSED) { + struct plugin *p = init_cmd->plugin; size_t num_channel_updates_rejected = 0; tal_steal(p, pay_plugin); pay_plugin->plugin = p; pay_plugin->last_time = 0; - rpc_scan(p, "getinfo", take(json_out_obj(NULL, NULL, NULL)), + rpc_scan(init_cmd, "getinfo", take(json_out_obj(NULL, NULL, NULL)), "{id:%}", JSON_SCAN(json_to_node_id, &pay_plugin->my_id)); /* BOLT #4: @@ -56,7 +57,7 @@ static const char *init(struct plugin *p, /* FIXME: Typo in spec for CLTV in descripton! But it breaks our spelling check, so we omit it above */ pay_plugin->maxdelay_default = 2016; /* max-locktime-blocks deprecated in v24.05, but still grab it! */ - rpc_scan(p, "listconfigs", + rpc_scan(init_cmd, "listconfigs", take(json_out_obj(NULL, NULL, NULL)), "{configs:" "{max-locktime-blocks?:{value_int:%}," diff --git a/plugins/renepay/mods.c b/plugins/renepay/mods.c index f5e232eea0f8..4b167aec5447 100644 --- a/plugins/renepay/mods.c +++ b/plugins/renepay/mods.c @@ -216,13 +216,13 @@ static struct command_result *previoussuccess_cb(struct payment *payment) assert(cmd); struct out_req *req = jsonrpc_request_start( - cmd->plugin, cmd, "listsendpays", previoussuccess_done, + cmd, "listsendpays", previoussuccess_done, payment_rpc_failure, payment); json_add_sha256(req->js, "payment_hash", &payment->payment_info.payment_hash); json_add_string(req->js, "status", "complete"); - return send_outreq(cmd->plugin, req); + return send_outreq(req); } REGISTER_PAYMENT_MODIFIER(previoussuccess, previoussuccess_cb); @@ -312,11 +312,11 @@ static struct command_result *selfpay_cb(struct payment *payment) /*partid=*/0, pinfo->payment_hash, pinfo->amount, pinfo->amount); struct out_req *req; - req = jsonrpc_request_start(cmd->plugin, cmd, "sendpay", + req = jsonrpc_request_start(cmd, "sendpay", selfpay_success, selfpay_failure, route); route->hops = tal_arr(route, struct route_hop, 0); json_add_route(req->js, route, payment); - return send_outreq(cmd->plugin, req); + return send_outreq(req); } REGISTER_PAYMENT_MODIFIER(selfpay, selfpay_cb); @@ -452,9 +452,9 @@ static struct command_result *getmychannels_cb(struct payment *payment) "getmychannels_pay_mod: cannot get a valid cmd."); struct out_req *req = jsonrpc_request_start( - cmd->plugin, cmd, "listpeerchannels", getmychannels_done, + cmd, "listpeerchannels", getmychannels_done, payment_rpc_failure, payment); - return send_outreq(cmd->plugin, req); + return send_outreq(req); } REGISTER_PAYMENT_MODIFIER(getmychannels, getmychannels_cb); @@ -622,10 +622,10 @@ static struct command_result *routehints_cb(struct payment *payment) struct command *cmd = payment_command(payment); assert(cmd); struct out_req *req = jsonrpc_request_start( - cmd->plugin, cmd, "waitblockheight", routehints_done, + cmd, "waitblockheight", routehints_done, payment_rpc_failure, payment); json_add_num(req->js, "blockheight", 0); - return send_outreq(cmd->plugin, req); + return send_outreq(req); } REGISTER_PAYMENT_MODIFIER(routehints, routehints_cb); @@ -879,10 +879,10 @@ static struct command_result *end_cb(struct payment *payment) struct command *cmd = payment_command(payment); assert(cmd); struct out_req *req = - jsonrpc_request_start(cmd->plugin, cmd, "waitblockheight", end_done, + jsonrpc_request_start(cmd, "waitblockheight", end_done, payment_rpc_failure, payment); json_add_num(req->js, "blockheight", 0); - return send_outreq(cmd->plugin, req); + return send_outreq(req); } REGISTER_PAYMENT_MODIFIER(end, end_cb); @@ -1068,12 +1068,12 @@ static struct command_result *pendingsendpays_cb(struct payment *payment) assert(cmd); struct out_req *req = jsonrpc_request_start( - cmd->plugin, cmd, "listsendpays", pendingsendpays_done, + cmd, "listsendpays", pendingsendpays_done, payment_rpc_failure, payment); json_add_sha256(req->js, "payment_hash", &payment->payment_info.payment_hash); - return send_outreq(cmd->plugin, req); + return send_outreq(req); } REGISTER_PAYMENT_MODIFIER(pendingsendpays, pendingsendpays_cb); diff --git a/plugins/renepay/routefail.c b/plugins/renepay/routefail.c index a149fa32244e..6b362dc86baf 100644 --- a/plugins/renepay/routefail.c +++ b/plugins/renepay/routefail.c @@ -152,10 +152,10 @@ static struct command_result *update_gossip(struct routefail *r) goto skip_update_gossip; struct out_req *req = - jsonrpc_request_start(r->cmd->plugin, r->cmd, "addgossip", + jsonrpc_request_start(r->cmd, "addgossip", update_gossip_done, update_gossip_failure, r); json_add_hex_talarr(req->js, "message", update); - return send_outreq(r->cmd->plugin, req); + return send_outreq(req); skip_update_gossip: return handle_failure(r); diff --git a/plugins/renepay/routetracker.c b/plugins/renepay/routetracker.c index f08f8becbd78..3184eda7dfb5 100644 --- a/plugins/renepay/routetracker.c +++ b/plugins/renepay/routetracker.c @@ -329,7 +329,7 @@ struct command_result *route_sendpay_request(struct command *cmd, struct payment *payment) { struct out_req *req = - jsonrpc_request_start(pay_plugin->plugin, cmd, "sendpay", + jsonrpc_request_start(cmd, "sendpay", sendpay_done, sendpay_failed, route); json_add_route(req->js, route, payment); @@ -337,7 +337,7 @@ struct command_result *route_sendpay_request(struct command *cmd, route_map_add(payment->routetracker->sent_routes, route); if(taken(route)) tal_steal(payment->routetracker->sent_routes, route); - return send_outreq(pay_plugin->plugin, req); + return send_outreq(req); } struct command_result *notification_sendpay_failure(struct command *cmd, diff --git a/plugins/spender/fundchannel.c b/plugins/spender/fundchannel.c index e797492b61f5..6fc722fa94cc 100644 --- a/plugins/spender/fundchannel.c +++ b/plugins/spender/fundchannel.c @@ -75,7 +75,7 @@ json_fundchannel(struct command *cmd, "Must pass in 'compact_lease' if requesting" " funds from peer"); - req = jsonrpc_request_start(cmd->plugin, cmd, "multifundchannel", + req = jsonrpc_request_start(cmd, "multifundchannel", &fundchannel_get_result, &forward_error, NULL); @@ -111,7 +111,7 @@ json_fundchannel(struct command *cmd, if (utxos) json_add_tok(req->js, "utxos", utxos, buf); - return send_outreq(cmd->plugin, req); + return send_outreq(req); } static bool json_to_tok(const char *buffer, const jsmntok_t *tok, const jsmntok_t **ret) diff --git a/plugins/spender/main.c b/plugins/spender/main.c index ce0e84d100cb..5a94785dacbc 100644 --- a/plugins/spender/main.c +++ b/plugins/spender/main.c @@ -8,9 +8,9 @@ * spending from the onchain wallet. */ static -const char *spender_init(struct plugin *p, const char *b, const jsmntok_t *t) +const char *spender_init(struct command *init_cmd, const char *b, const jsmntok_t *t) { - openchannel_init(p, b, t); + openchannel_init(init_cmd->plugin, b, t); /* whatever_init(p, b, t); */ return NULL; } diff --git a/plugins/spender/multifundchannel.c b/plugins/spender/multifundchannel.c index a2eaf8113607..952b9963b1d2 100644 --- a/plugins/spender/multifundchannel.c +++ b/plugins/spender/multifundchannel.c @@ -168,8 +168,7 @@ static struct command_result *unreserve_call(struct command *cmd, void *cb, void *cbdata) { struct wally_psbt *pruned_psbt; - struct out_req *req = jsonrpc_request_start(cmd->plugin, - cmd, + struct out_req *req = jsonrpc_request_start(cmd, "unreserveinputs", cb, cb, cbdata); @@ -188,7 +187,7 @@ static struct command_result *unreserve_call(struct command *cmd, json_add_psbt(req->js, "psbt", take(pruned_psbt)); json_add_u32(req->js, "reserve", 2016); - return send_outreq(cmd->plugin, req); + return send_outreq(req); } /* Cleans up a txid by doing `txdiscard` on it. */ @@ -206,14 +205,13 @@ mfc_cleanup_oc(struct command *cmd, struct multifundchannel_cleanup *cleanup, struct multifundchannel_destination *dest) { - struct out_req *req = jsonrpc_request_start(cmd->plugin, - cmd, + struct out_req *req = jsonrpc_request_start(cmd, "openchannel_abort", &mfc_cleanup_done, &mfc_cleanup_done, cleanup); json_add_channel_id(req->js, "channel_id", &dest->channel_id); - send_outreq(cmd->plugin, req); + send_outreq(req); } /* Cleans up a `fundchannel_start` by doing `fundchannel_cancel` on @@ -224,15 +222,14 @@ mfc_cleanup_fc(struct command *cmd, struct multifundchannel_cleanup *cleanup, struct multifundchannel_destination *dest) { - struct out_req *req = jsonrpc_request_start(cmd->plugin, - cmd, + struct out_req *req = jsonrpc_request_start(cmd, "fundchannel_cancel", &mfc_cleanup_done, &mfc_cleanup_done, cleanup); json_add_node_id(req->js, "id", &dest->id); - send_outreq(cmd->plugin, req); + send_outreq(req); } /* Core cleanup function. */ @@ -647,7 +644,7 @@ after_signpsbt(struct command *cmd, plugin_log(mfc->cmd->plugin, LOG_DBG, "mfc %"PRIu64": sendpsbt.", mfc->id); - req = jsonrpc_request_start(mfc->cmd->plugin, mfc->cmd, + req = jsonrpc_request_start(mfc->cmd, "sendpsbt", &after_sendpsbt, &mfc_forward_error, @@ -656,7 +653,7 @@ after_signpsbt(struct command *cmd, /* We already reserved inputs by 2 weeks, we don't need * another 72 blocks. */ json_add_u32(req->js, "reserve", 0); - return send_outreq(mfc->cmd->plugin, req); + return send_outreq(req); } struct command_result * @@ -669,7 +666,7 @@ perform_signpsbt(struct multifundchannel_command *mfc) plugin_log(mfc->cmd->plugin, LOG_DBG, "mfc %"PRIu64": signpsbt.", mfc->id); - req = jsonrpc_request_start(mfc->cmd->plugin, mfc->cmd, + req = jsonrpc_request_start(mfc->cmd, "signpsbt", &after_signpsbt, &mfc_forward_error, @@ -684,7 +681,7 @@ perform_signpsbt(struct multifundchannel_command *mfc) json_add_num(req->js, NULL, i); } json_array_end(req->js); - return send_outreq(mfc->cmd->plugin, req); + return send_outreq(req); } /*~ @@ -795,8 +792,7 @@ fundchannel_complete_dest(struct multifundchannel_destination *dest) mfc->id, dest->index, fmt_node_id(tmpctx, &dest->id)); - req = jsonrpc_request_start(cmd->plugin, - cmd, + req = jsonrpc_request_start(cmd, "fundchannel_complete", &fundchannel_complete_ok, &fundchannel_complete_err, @@ -804,7 +800,7 @@ fundchannel_complete_dest(struct multifundchannel_destination *dest) json_add_node_id(req->js, "id", &dest->id); json_add_psbt(req->js, "psbt", mfc->psbt); - send_outreq(cmd->plugin, req); + send_outreq(req); } struct command_result * @@ -1108,8 +1104,7 @@ fundchannel_start_dest(struct multifundchannel_destination *dest) mfc->id, dest->index, fmt_node_id(tmpctx, &dest->id)); - req = jsonrpc_request_start(cmd->plugin, - cmd, + req = jsonrpc_request_start(cmd, "fundchannel_start", &fundchannel_start_ok, &fundchannel_start_err, @@ -1144,7 +1139,7 @@ fundchannel_start_dest(struct multifundchannel_destination *dest) req->js, "reserve", fmt_amount_sat(tmpctx, *dest->reserve)); - send_outreq(cmd->plugin, req); + send_outreq(req); } static struct command_result * @@ -1325,8 +1320,7 @@ perform_fundpsbt(struct multifundchannel_command *mfc, u32 feerate) "mfc %"PRIu64": utxopsbt.", mfc->id); - req = jsonrpc_request_start(mfc->cmd->plugin, - mfc->cmd, + req = jsonrpc_request_start(mfc->cmd, "utxopsbt", &after_fundpsbt, &mfc_forward_error, @@ -1339,8 +1333,7 @@ perform_fundpsbt(struct multifundchannel_command *mfc, u32 feerate) "mfc %"PRIu64": fundpsbt.", mfc->id); - req = jsonrpc_request_start(mfc->cmd->plugin, - mfc->cmd, + req = jsonrpc_request_start(mfc->cmd, "fundpsbt", &after_fundpsbt, &mfc_forward_error, @@ -1424,7 +1417,7 @@ perform_fundpsbt(struct multifundchannel_command *mfc, u32 feerate) /* Handle adding a change output if required. */ json_add_bool(req->js, "excess_as_change", true); - return send_outreq(mfc->cmd->plugin, req); + return send_outreq(req); } static struct command_result * @@ -1460,8 +1453,7 @@ getfeerate(struct multifundchannel_command *mfc) * fees for the channel open. This requires that we know * the feerate ahead of time, so that we can figure the * expected lease fees, and add that to the funding amount. */ - req = jsonrpc_request_start(mfc->cmd->plugin, - mfc->cmd, + req = jsonrpc_request_start(mfc->cmd, "parsefeerate", &after_getfeerate, &mfc_forward_error, @@ -1471,7 +1463,7 @@ getfeerate(struct multifundchannel_command *mfc) json_add_string(req->js, "feerate", mfc->feerate_str ? mfc->feerate_str: "opening"); - return send_outreq(mfc->cmd->plugin, req); + return send_outreq(req); } /*---------------------------------------------------------------------------*/ @@ -1610,7 +1602,7 @@ connect_dest(struct multifundchannel_destination *dest) "mfc %"PRIu64", dest %u: connect %s.", mfc->id, dest->index, id); - req = jsonrpc_request_start(cmd->plugin, cmd, + req = jsonrpc_request_start(cmd, "connect", &connect_ok, &connect_err, @@ -1622,7 +1614,7 @@ connect_dest(struct multifundchannel_destination *dest) dest->addrhint)); else json_add_node_id(req->js, "id", &dest->id); - send_outreq(cmd->plugin, req); + send_outreq(req); } /*----------------------------------------------------------------------------- diff --git a/plugins/spender/multiwithdraw.c b/plugins/spender/multiwithdraw.c index 04d35383f43d..bf374757328a 100644 --- a/plugins/spender/multiwithdraw.c +++ b/plugins/spender/multiwithdraw.c @@ -248,13 +248,12 @@ mw_perform_cleanup(struct multiwithdraw_command *mw, cleanup->mw = mw; cleanup->error_json = tal_strdup(cleanup, error_json); - req = jsonrpc_request_start(mw->cmd->plugin, - mw->cmd, + req = jsonrpc_request_start(mw->cmd, "unreserveinputs", &mw_after_cleanup, &mw_after_cleanup, cleanup); json_add_psbt(req->js, "psbt", mw->psbt); - return send_outreq(mw->cmd->plugin, req); + return send_outreq(req); } static struct command_result * mw_after_cleanup(struct command *cmd UNUSED, @@ -344,8 +343,7 @@ static struct command_result *start_mw(struct multiwithdraw_command *mw) plugin_log(mw->cmd->plugin, LOG_DBG, "multiwithdraw %"PRIu64": utxopsbt.", mw->id); - req = jsonrpc_request_start(mw->cmd->plugin, - mw->cmd, + req = jsonrpc_request_start(mw->cmd, "utxopsbt", &mw_after_fundpsbt, &mw_forward_error, @@ -356,8 +354,7 @@ static struct command_result *start_mw(struct multiwithdraw_command *mw) plugin_log(mw->cmd->plugin, LOG_DBG, "multiwithdraw %"PRIu64": fundpsbt.", mw->id); - req = jsonrpc_request_start(mw->cmd->plugin, - mw->cmd, + req = jsonrpc_request_start(mw->cmd, "fundpsbt", &mw_after_fundpsbt, &mw_forward_error, @@ -379,7 +376,7 @@ static struct command_result *start_mw(struct multiwithdraw_command *mw) json_add_string(req->js, "feerate", mw->feerate); json_add_u64(req->js, "startweight", startweight); - return send_outreq(mw->cmd->plugin, req); + return send_outreq(req); } /*----------------------------------------------------------------------------- @@ -500,11 +497,11 @@ mw_get_change_addr(struct multiwithdraw_command *mw) "multiwithdraw %"PRIu64": change output newaddr.", mw->id); - req = jsonrpc_request_start(mw->cmd->plugin, mw->cmd, + req = jsonrpc_request_start(mw->cmd, "newaddr", &mw_after_newaddr, &mw_forward_error, mw); json_add_string(req->js, "addresstype", chainparams->is_elements ? "bech32" : "p2tr"); - return send_outreq(mw->cmd->plugin, req); + return send_outreq(req); } static struct command_result * @@ -627,13 +624,13 @@ mw_sign_and_send(struct multiwithdraw_command *mw) plugin_log(mw->cmd->plugin, LOG_DBG, "multiwithdraw %"PRIu64": signpsbt.", mw->id); - req = jsonrpc_request_start(mw->cmd->plugin, mw->cmd, + req = jsonrpc_request_start(mw->cmd, "signpsbt", &mw_after_signpsbt, &mw_forward_error, mw); json_add_psbt(req->js, "psbt", mw->psbt); - return send_outreq(mw->cmd->plugin, req); + return send_outreq(req); } static struct command_result * @@ -668,8 +665,7 @@ mw_after_signpsbt(struct command *cmd, plugin_log(mw->cmd->plugin, LOG_DBG, "multiwithdraw: %"PRIu64": sendpsbt.", mw->id); - req = jsonrpc_request_start(mw->cmd->plugin, - mw->cmd, + req = jsonrpc_request_start(mw->cmd, "sendpsbt", &forward_result, /* Properly speaking, if `sendpsbt` fails, @@ -683,5 +679,5 @@ mw_after_signpsbt(struct command *cmd, &mw_forward_error, mw); json_add_psbt(req->js, "psbt", mw->psbt); - return send_outreq(mw->cmd->plugin, req); + return send_outreq(req); } diff --git a/plugins/spender/openchannel.c b/plugins/spender/openchannel.c index d6d75bd15468..944679976b1f 100644 --- a/plugins/spender/openchannel.c +++ b/plugins/spender/openchannel.c @@ -444,8 +444,7 @@ openchannel_signed_dest(struct multifundchannel_destination *dest) fmt_channel_id(tmpctx, &dest->channel_id), fmt_wally_psbt(tmpctx, dest->psbt)); - req = jsonrpc_request_start(cmd->plugin, - cmd, + req = jsonrpc_request_start(cmd, "openchannel_signed", &openchannel_signed_ok, &openchannel_signed_err, @@ -453,7 +452,7 @@ openchannel_signed_dest(struct multifundchannel_destination *dest) json_add_channel_id(req->js, "channel_id", &dest->channel_id); json_add_psbt(req->js, "signed_psbt", dest->psbt); - send_outreq(cmd->plugin, req); + send_outreq(req); } struct command_result * @@ -786,8 +785,7 @@ openchannel_update_dest(struct multifundchannel_destination *dest) fmt_node_id(tmpctx, &dest->id), fmt_wally_psbt(tmpctx, dest->psbt)); - req = jsonrpc_request_start(cmd->plugin, - cmd, + req = jsonrpc_request_start(cmd, "openchannel_update", &openchannel_update_ok, &openchannel_update_err, @@ -795,7 +793,7 @@ openchannel_update_dest(struct multifundchannel_destination *dest) json_add_channel_id(req->js, "channel_id", &dest->channel_id); json_add_psbt(req->js, "psbt", dest->psbt); - send_outreq(cmd->plugin, req); + send_outreq(req); } struct command_result * @@ -972,7 +970,7 @@ openchannel_init_dest(struct multifundchannel_destination *dest) mfc->id, dest->index, fmt_node_id(tmpctx, &dest->id)); - req = jsonrpc_request_start(cmd->plugin, cmd, + req = jsonrpc_request_start(cmd, "openchannel_init", &openchannel_init_ok, &openchannel_init_err, @@ -1026,7 +1024,7 @@ openchannel_init_dest(struct multifundchannel_destination *dest) json_add_channel_type_arr(req->js, "channel_type", dest->channel_type); } - return send_outreq(cmd->plugin, req); + return send_outreq(req); } void openchannel_init(struct plugin *p, const char *b, const jsmntok_t *t) diff --git a/plugins/sql.c b/plugins/sql.c index 9493696a343a..23b290156875 100644 --- a/plugins/sql.c +++ b/plugins/sql.c @@ -735,10 +735,10 @@ static struct command_result *default_refresh(struct command *cmd, struct db_query *dbq) { struct out_req *req; - req = jsonrpc_request_start(cmd->plugin, cmd, td->cmdname, + req = jsonrpc_request_start(cmd, td->cmdname, default_list_done, forward_error, dbq); - return send_outreq(cmd->plugin, req); + return send_outreq(req); } static bool extract_scid(int gosstore_fd, size_t off, u16 type, @@ -870,12 +870,12 @@ static struct command_result *channels_refresh(struct command *cmd, /* FIXME: sqlite 3.24.0 (2018-06-04) added UPSERT, but * we don't require it. */ delete_channel_from_db(cmd, scid); - req = jsonrpc_request_start(cmd->plugin, cmd, "listchannels", + req = jsonrpc_request_start(cmd, "listchannels", listchannels_one_done, forward_error, dbq); json_add_short_channel_id(req->js, "short_channel_id", scid); - return send_outreq(cmd->plugin, req); + return send_outreq(req); } else if (type == WIRE_GOSSIP_STORE_DELETE_CHAN) { /* This can fail if entry not fully written yet. */ if (!extract_scid(gosstore_fd, off, type, &scid)) { @@ -1007,12 +1007,12 @@ static struct command_result *nodes_refresh(struct command *cmd, /* FIXME: sqlite 3.24.0 (2018-06-04) added UPSERT, but * we don't require it. */ delete_node_from_db(cmd, &id); - req = jsonrpc_request_start(cmd->plugin, cmd, "listnodes", + req = jsonrpc_request_start(cmd, "listnodes", listnodes_one_done, forward_error, dbq); json_add_node_id(req->js, "id", &id); - return send_outreq(cmd->plugin, req); + return send_outreq(req); } /* FIXME: Add WIRE_GOSSIP_STORE_DELETE_NODE marker! */ } @@ -1537,9 +1537,10 @@ static void memleak_mark_tablemap(struct plugin *p, struct htable *memtable) memleak_scan_strmap(memtable, &tablemap); } -static const char *init(struct plugin *plugin, +static const char *init(struct command *init_cmd, const char *buf UNUSED, const jsmntok_t *config UNUSED) { + struct plugin *plugin = init_cmd->plugin; db = sqlite_setup(plugin); init_tablemap(plugin); init_indices(plugin); diff --git a/plugins/test/run-route-calc.c b/plugins/test/run-route-calc.c index d2078e00d77b..ee5859e2d475 100644 --- a/plugins/test/run-route-calc.c +++ b/plugins/test/run-route-calc.c @@ -249,8 +249,7 @@ int json_tok_full_len(const jsmntok_t *t UNNEEDED) bool json_tok_streq(const char *buffer UNNEEDED, const jsmntok_t *tok UNNEEDED, const char *str UNNEEDED) { fprintf(stderr, "json_tok_streq called!\n"); abort(); } /* Generated stub for jsonrpc_request_start_ */ -struct out_req *jsonrpc_request_start_(struct plugin *plugin UNNEEDED, - struct command *cmd UNNEEDED, +struct out_req *jsonrpc_request_start_(struct command *cmd UNNEEDED, const char *method UNNEEDED, const char *id_prefix UNNEEDED, const char *filter UNNEEDED, @@ -308,8 +307,7 @@ void plugin_notify_message(struct command *cmd UNNEEDED, bool random_select(double weight UNNEEDED, double *tot_weight UNNEEDED) { fprintf(stderr, "random_select called!\n"); abort(); } /* Generated stub for send_outreq */ -struct command_result *send_outreq(struct plugin *plugin UNNEEDED, - const struct out_req *req UNNEEDED) +struct command_result *send_outreq(const struct out_req *req UNNEEDED) { fprintf(stderr, "send_outreq called!\n"); abort(); } /* Generated stub for towire_bigsize */ void towire_bigsize(u8 **pptr UNNEEDED, const bigsize_t val UNNEEDED) diff --git a/plugins/test/run-route-overlong.c b/plugins/test/run-route-overlong.c index bf2186f16b3b..fc5a40c5b51f 100644 --- a/plugins/test/run-route-overlong.c +++ b/plugins/test/run-route-overlong.c @@ -246,8 +246,7 @@ int json_tok_full_len(const jsmntok_t *t UNNEEDED) bool json_tok_streq(const char *buffer UNNEEDED, const jsmntok_t *tok UNNEEDED, const char *str UNNEEDED) { fprintf(stderr, "json_tok_streq called!\n"); abort(); } /* Generated stub for jsonrpc_request_start_ */ -struct out_req *jsonrpc_request_start_(struct plugin *plugin UNNEEDED, - struct command *cmd UNNEEDED, +struct out_req *jsonrpc_request_start_(struct command *cmd UNNEEDED, const char *method UNNEEDED, const char *id_prefix UNNEEDED, const char *filter UNNEEDED, @@ -305,8 +304,7 @@ void plugin_notify_message(struct command *cmd UNNEEDED, bool random_select(double weight UNNEEDED, double *tot_weight UNNEEDED) { fprintf(stderr, "random_select called!\n"); abort(); } /* Generated stub for send_outreq */ -struct command_result *send_outreq(struct plugin *plugin UNNEEDED, - const struct out_req *req UNNEEDED) +struct command_result *send_outreq(const struct out_req *req UNNEEDED) { fprintf(stderr, "send_outreq called!\n"); abort(); } /* Generated stub for towire_bigsize */ void towire_bigsize(u8 **pptr UNNEEDED, const bigsize_t val UNNEEDED) diff --git a/plugins/topology.c b/plugins/topology.c index 51565cb2f363..ac05bc05d03c 100644 --- a/plugins/topology.c +++ b/plugins/topology.c @@ -204,10 +204,10 @@ static struct command_result *json_getroute(struct command *cmd, return command_param_failed(); /* Add local info */ - req = jsonrpc_request_start(cmd->plugin, cmd, "listpeerchannels", + req = jsonrpc_request_start(cmd, "listpeerchannels", listpeerchannels_getroute_done, listpeerchannels_err, info); - return send_outreq(cmd->plugin, req); + return send_outreq(req); } HTABLE_DEFINE_TYPE(struct node_id, node_id_keyof, node_id_hash, node_id_eq, @@ -476,9 +476,9 @@ static struct command_result *json_listchannels(struct command *cmd, // FIXME: Once this deprecation is removed, `listpeerchannels_done` can // be embedded in the current function. if (command_deprecated_out_ok(cmd, "include_private", "v24.02", "v24.08")) { - req = jsonrpc_request_start(cmd->plugin, cmd, "listpeerchannels", + req = jsonrpc_request_start(cmd, "listpeerchannels", listpeerchannels_done, forward_error, opts); - return send_outreq(cmd->plugin, req); + return send_outreq(req); } // If deprecations are not necessary, call listpeerchannels_done directly, @@ -696,11 +696,10 @@ static struct command_result *json_listincoming(struct command *cmd, return command_param_failed(); /* Add local info */ - req = jsonrpc_request_start(cmd->plugin, - cmd, "listpeerchannels", + req = jsonrpc_request_start(cmd, "listpeerchannels", listpeerchannels_listincoming_done, listpeerchannels_err, NULL); - return send_outreq(cmd->plugin, req); + return send_outreq(req); } static void memleak_mark(struct plugin *p, struct htable *memtable) @@ -708,13 +707,13 @@ static void memleak_mark(struct plugin *p, struct htable *memtable) memleak_scan_obj(memtable, global_gossmap); } -static const char *init(struct plugin *p, +static const char *init(struct command *init_cmd, const char *buf UNUSED, const jsmntok_t *config UNUSED) { size_t num_cupdates_rejected; - plugin = p; - rpc_scan(p, "getinfo", + plugin = init_cmd->plugin; + rpc_scan(init_cmd, "getinfo", take(json_out_obj(NULL, NULL, NULL)), "{id:%}", JSON_SCAN(json_to_node_id, &local_id)); @@ -729,7 +728,7 @@ static const char *init(struct plugin *p, plugin_log(plugin, LOG_DBG, "gossmap ignored %zu channel updates", num_cupdates_rejected); - plugin_set_memleak_handler(p, memleak_mark); + plugin_set_memleak_handler(plugin, memleak_mark); return NULL; } diff --git a/plugins/txprepare.c b/plugins/txprepare.c index 3024f305b2fa..b1529c59e312 100644 --- a/plugins/txprepare.c +++ b/plugins/txprepare.c @@ -168,11 +168,11 @@ static struct command_result *signpsbt_done(struct command *cmd, fmt_wally_psbt(tmpctx, utx->psbt)); } - req = jsonrpc_request_start(cmd->plugin, cmd, "sendpsbt", + req = jsonrpc_request_start(cmd, "sendpsbt", sendpsbt_done, forward_error, utx); json_add_psbt(req->js, "psbt", utx->psbt); - return send_outreq(cmd->plugin, req); + return send_outreq(req); } static struct command_result *finish_txprepare(struct command *cmd, @@ -218,11 +218,11 @@ static struct command_result *finish_txprepare(struct command *cmd, /* Won't live beyond this cmd. */ tal_steal(cmd, utx); - req = jsonrpc_request_start(cmd->plugin, cmd, "signpsbt", + req = jsonrpc_request_start(cmd, "signpsbt", signpsbt_done, forward_error, utx); json_add_psbt(req->js, "psbt", utx->psbt); - return send_outreq(cmd->plugin, req); + return send_outreq(req); } list_add(&unreleased_txs, &utx->list); @@ -308,7 +308,7 @@ static struct command_result *txprepare_continue(struct command *cmd, /* These calls are deliberately very similar, but utxopsbt wants utxos, * and fundpsbt wants minconf */ if (utxos) { - req = jsonrpc_request_start(cmd->plugin, cmd, "utxopsbt", + req = jsonrpc_request_start(cmd, "utxopsbt", psbt_created, forward_error, txp); json_array_start(req->js, "utxos"); @@ -318,7 +318,7 @@ static struct command_result *txprepare_continue(struct command *cmd, json_array_end(req->js); json_add_bool(req->js, "reservedok", reservedok); } else { - req = jsonrpc_request_start(cmd->plugin, cmd, "fundpsbt", + req = jsonrpc_request_start(cmd, "fundpsbt", psbt_created, forward_error, txp); if (minconf) @@ -334,7 +334,7 @@ static struct command_result *txprepare_continue(struct command *cmd, json_add_bool(req->js, "excess_as_change", true); json_add_string(req->js, "feerate", feerate); - return send_outreq(cmd->plugin, req); + return send_outreq(req); } static struct command_result *json_txprepare(struct command *cmd, @@ -413,11 +413,11 @@ static struct command_result *json_txdiscard(struct command *cmd, /* Whatever happens, we free it once this command is done. */ tal_steal(cmd, utx); - req = jsonrpc_request_start(cmd->plugin, cmd, "unreserveinputs", + req = jsonrpc_request_start(cmd, "unreserveinputs", unreserve_done, forward_error, utx); json_add_psbt(req->js, "psbt", utx->psbt); - return send_outreq(cmd->plugin, req); + return send_outreq(req); } static struct command_result *json_txsend(struct command *cmd, @@ -437,11 +437,11 @@ static struct command_result *json_txsend(struct command *cmd, /* If things go wrong, free it. */ tal_steal(cmd, utx); - req = jsonrpc_request_start(cmd->plugin, cmd, "signpsbt", + req = jsonrpc_request_start(cmd, "signpsbt", signpsbt_done, forward_error, utx); json_add_psbt(req->js, "psbt", utx->psbt); - return send_outreq(cmd->plugin, req); + return send_outreq(req); } static struct command_result *json_withdraw(struct command *cmd, @@ -597,12 +597,12 @@ static struct command_result *newaddr_sweep_done(struct command *cmd, + bitcoin_tx_output_weight(tal_bytelen(info->txp->outputs[0].script)); /* Find all the utxos we want to spend on this tx */ - req = jsonrpc_request_start(cmd->plugin, cmd, + req = jsonrpc_request_start(cmd, "listfunds", listfunds_done, forward_error, info); - return send_outreq(cmd->plugin, req); + return send_outreq(req); } static struct command_result *json_upgradewallet(struct command *cmd, @@ -621,13 +621,13 @@ static struct command_result *json_upgradewallet(struct command *cmd, info->reservedok = *reservedok; /* Get an address to send everything to */ - req = jsonrpc_request_start(cmd->plugin, cmd, + req = jsonrpc_request_start(cmd, "newaddr", newaddr_sweep_done, forward_error, info); json_add_string(req->js, "addresstype", "all"); - return send_outreq(cmd->plugin, req); + return send_outreq(req); } static const struct plugin_command commands[] = { @@ -658,10 +658,10 @@ static void mark_unreleased_txs(struct plugin *plugin, struct htable *memtable) memleak_scan_list_head(memtable, &unreleased_txs); } -static const char *init(struct plugin *p, +static const char *init(struct command *init_cmd, const char *buf UNUSED, const jsmntok_t *config UNUSED) { - plugin_set_memleak_handler(p, mark_unreleased_txs); + plugin_set_memleak_handler(init_cmd->plugin, mark_unreleased_txs); return NULL; } diff --git a/tests/plugins/test_libplugin.c b/tests/plugins/test_libplugin.c index 71a306b512b2..4116eef9b663 100644 --- a/tests/plugins/test_libplugin.c +++ b/tests/plugins/test_libplugin.c @@ -35,7 +35,7 @@ static struct command_result *get_ds_bin_done(struct command *cmd, plugin_log(cmd->plugin, LOG_INFORM, "get_ds_bin_done: %s", val ? tal_hex(tmpctx, val) : "NOT FOUND"); - return jsonrpc_get_datastore_string(cmd->plugin, cmd, + return jsonrpc_get_datastore_string(cmd, "test_libplugin/name", get_ds_done, arg); } @@ -54,7 +54,7 @@ static struct command_result *json_helloworld(struct command *cmd, plugin_notify_message(cmd, LOG_INFORM, "Notification from %s", "json_helloworld"); if (!name) - return jsonrpc_get_datastore_binary(cmd->plugin, cmd, + return jsonrpc_get_datastore_binary(cmd, "test_libplugin/name", get_ds_bin_done, "hello"); @@ -147,9 +147,9 @@ static struct command_result *json_testrpc(struct command *cmd, if (!param(cmd, buf, params, NULL)) return command_param_failed(); - req = jsonrpc_request_start(cmd->plugin, cmd, "getinfo", testrpc_cb, + req = jsonrpc_request_start(cmd, "getinfo", testrpc_cb, testrpc_cb, NULL); - return send_outreq(cmd->plugin, req); + return send_outreq(req); } static struct command_result *listdatastore_ok(struct command *cmd, @@ -178,13 +178,13 @@ static struct command_result *json_checkthis(struct command *cmd, NULL)) return command_param_failed(); - req = jsonrpc_request_start(cmd->plugin, cmd, + req = jsonrpc_request_start(cmd, "listdatastore", listdatastore_ok, forward_error, NULL); if (key) json_add_tok(req->js, "key", key, buf); - return send_outreq(cmd->plugin, req); + return send_outreq(req); } static char *set_dynamic(struct plugin *plugin, @@ -205,12 +205,13 @@ static char *set_dynamic(struct plugin *plugin, return NULL; } -static const char *init(struct plugin *p, +static const char *init(struct command *init_cmd, const char *buf UNUSED, const jsmntok_t *config UNUSED) { const char *name, *err_str, *err_hex; const u8 *binname; + struct plugin *p = init_cmd->plugin; struct test_libplugin *tlp = get_test_libplugin(p); plugin_log(p, LOG_DBG, "test_libplugin initialised!"); @@ -222,12 +223,12 @@ static const char *init(struct plugin *p, return "Disabled via selfdisable option"; /* Test rpc_scan_datastore funcs */ - err_str = rpc_scan_datastore_str(tmpctx, p, "test_libplugin/name", + err_str = rpc_scan_datastore_str(tmpctx, init_cmd, "test_libplugin/name", JSON_SCAN_TAL(tmpctx, json_strdup, &name)); if (err_str) name = NULL; - err_hex = rpc_scan_datastore_hex(tmpctx, p, "test_libplugin/name", + err_hex = rpc_scan_datastore_hex(tmpctx, init_cmd, "test_libplugin/name", JSON_SCAN_TAL(tmpctx, json_tok_bin_from_hex, &binname)); if (err_hex) From 4884cf4c81c99671a46b9fc83b694bdafe1b3fb6 Mon Sep 17 00:00:00 2001 From: Rusty Russell Date: Wed, 6 Nov 2024 21:31:36 +1030 Subject: [PATCH 14/18] askrene: make sure we depend on libplugin.h Signed-off-by: Rusty Russell --- plugins/Makefile | 3 ++- plugins/askrene/Makefile | 4 ++-- plugins/renepay/Makefile | 4 ++-- 3 files changed, 6 insertions(+), 5 deletions(-) diff --git a/plugins/Makefile b/plugins/Makefile index 320aefa0c00b..1e2ff2168424 100644 --- a/plugins/Makefile +++ b/plugins/Makefile @@ -128,7 +128,6 @@ endif # This is non-python plugins (PY_PLUGINS need their whole directory!) PLUGINS := $(C_PLUGINS) -PLUGIN_ALL_OBJS := $(PLUGIN_ALL_SRC:.c=.o) ifneq ($(RUST),0) # Builtin plugins must be in this plugins dir to work when we're executed @@ -199,6 +198,8 @@ ALL_C_SOURCES += $(PLUGIN_ALL_SRC) ALL_C_HEADERS += $(PLUGIN_ALL_HEADER) ALL_PROGRAMS += $(C_PLUGINS) +PLUGIN_ALL_OBJS := $(PLUGIN_ALL_SRC:.c=.o) + # Make all plugins depend on all plugin headers, for simplicity. $(PLUGIN_ALL_OBJS): $(PLUGIN_ALL_HEADER) diff --git a/plugins/askrene/Makefile b/plugins/askrene/Makefile index 989905aee192..4628e80f2151 100644 --- a/plugins/askrene/Makefile +++ b/plugins/askrene/Makefile @@ -4,7 +4,7 @@ PLUGIN_ASKRENE_OBJS := $(PLUGIN_ASKRENE_SRC:.c=.o) $(PLUGIN_ASKRENE_OBJS): $(PLUGIN_ASKRENE_HEADER) -ALL_C_SOURCES += $(PLUGIN_ASKRENE_SRC) -ALL_C_HEADERS += $(PLUGIN_ASKRENE_HEADER) +PLUGIN_ALL_SRC += $(PLUGIN_ASKRENE_SRC) +PLUGIN_ALL_HEADER += $(PLUGIN_ASKRENE_HEADER) plugins/cln-askrene: $(PLUGIN_ASKRENE_OBJS) $(PLUGIN_LIB_OBJS) $(PLUGIN_COMMON_OBJS) $(JSMN_OBJS) $(CCAN_OBJS) bitcoin/chainparams.o common/gossmap.o common/sciddir_or_pubkey.o common/gossmods_listpeerchannels.o common/fp16.o common/dijkstra.o common/bolt12.o common/bolt12_merkle.o wire/bolt12_wiregen.o wire/onion_wiregen.o common/route.o diff --git a/plugins/renepay/Makefile b/plugins/renepay/Makefile index 501db8a51c57..38406183df23 100644 --- a/plugins/renepay/Makefile +++ b/plugins/renepay/Makefile @@ -37,8 +37,8 @@ PLUGIN_RENEPAY_HDRS := \ PLUGIN_RENEPAY_OBJS := $(PLUGIN_RENEPAY_SRC:.c=.o) # Make sure these depend on everything. -ALL_C_SOURCES += $(PLUGIN_RENEPAY_SRC) -ALL_C_HEADERS += $(PLUGIN_RENEPAY_HDRS) +PLUGIN_ALL_SRC += $(PLUGIN_RENEPAY_SRC) +PLUGIN_ALL_HEADER += $(PLUGIN_RENEPAY_HDRS) # Make all plugins depend on all plugin headers, for simplicity. $(PLUGIN_RENEPAY_OBJS): $(PLUGIN_RENEPAY_HDRS) From 69654eeb1be0e39cbd6615a47cf24d3f39e56140 Mon Sep 17 00:00:00 2001 From: Rusty Russell Date: Thu, 7 Nov 2024 11:57:28 +1030 Subject: [PATCH 15/18] libplugin: use NULL to imply "take prefix from cmd". This avoids jsonrpc_request_start() double-evaluating its cmd arg. Signed-off-by: Rusty Russell --- plugins/commando.c | 7 ++----- plugins/libplugin.c | 35 ++++++++++++++++--------------- plugins/libplugin.h | 17 +++++---------- plugins/test/run-route-calc.c | 3 --- plugins/test/run-route-overlong.c | 3 --- 5 files changed, 25 insertions(+), 40 deletions(-) diff --git a/plugins/commando.c b/plugins/commando.c index f814e1f1e561..00d9495d5782 100644 --- a/plugins/commando.c +++ b/plugins/commando.c @@ -262,9 +262,7 @@ static struct cond_info *new_cond_info(const tal_t *ctx, cinfo->cmdid_prefix = NULL; incoming->json_id = NULL; } else { - cinfo->cmdid_prefix = tal_fmt(cinfo, "%.*s/", - id->end - id->start, - cinfo->buf + id->start); + cinfo->cmdid_prefix = json_strdup(cinfo, cinfo->buf, id); /* Includes quotes, if any! */ incoming->json_id = tal_strndup(incoming, json_tok_full(cinfo->buf, id), @@ -728,8 +726,7 @@ static struct command_result *forward_command(struct command *cmd, /* params could be an array, so use low-level helper */ struct out_req *req; - req = jsonrpc_request_whole_object_start(cmd, method, - json_id_prefix(tmpctx, cmd), + req = jsonrpc_request_whole_object_start(cmd, method, NULL, forward_reply, NULL); json_add_tok(req->js, "params", params, buffer); return send_outreq(req); diff --git a/plugins/libplugin.c b/plugins/libplugin.c index 6c7d5891d14e..a912082b7c7d 100644 --- a/plugins/libplugin.c +++ b/plugins/libplugin.c @@ -273,25 +273,26 @@ static void disable_request_cb(struct command *cmd, struct out_req *out) out->cmd = NULL; } -const char *json_id_prefix(const tal_t *ctx, const struct command *cmd) +/* Prefix is usually a cmd->id */ +static const char *json_id(const tal_t *ctx, struct plugin *plugin, + const char *method, const char *prefix) { + const char *rawid; + int rawidlen; + /* Strip quotes! */ - if (strstarts(cmd->id, "\"")) { - assert(strlen(cmd->id) >= 2); - assert(strends(cmd->id, "\"")); - return tal_fmt(ctx, "%.*s/", - (int)strlen(cmd->id) - 2, cmd->id + 1); + if (strstarts(prefix, "\"")) { + assert(strlen(prefix) >= 2); + assert(strends(prefix, "\"")); + rawid = prefix + 1; + rawidlen = strlen(prefix) - 2; + } else { + rawid = prefix; + rawidlen = strlen(prefix); } - return tal_fmt(ctx, "%s/", cmd->id); -} -static const char *append_json_id(const tal_t *ctx, - struct plugin *plugin, - const char *method, - const char *prefix) -{ - return tal_fmt(ctx, "\"%s%s:%s#%"PRIu64"\"", - prefix, plugin->id, method, plugin->next_outreq_id++); + return tal_fmt(ctx, "\"%.*s/%s:%s#%"PRIu64"\"", + rawidlen, rawid, plugin->id, method, plugin->next_outreq_id++); } static void destroy_out_req(struct out_req *out_req, struct plugin *plugin) @@ -320,7 +321,7 @@ jsonrpc_request_start_(struct command *cmd, assert(cmd); out = tal(cmd, struct out_req); - out->id = append_json_id(out, cmd->plugin, method, id_prefix); + out->id = json_id(out, cmd->plugin, method, id_prefix ? id_prefix : cmd->id); out->cmd = cmd; out->cb = cb; out->errcb = errcb; @@ -704,7 +705,7 @@ static const jsmntok_t *sync_req(const tal_t *ctx, const jsmntok_t *contents; int reqlen; struct json_out *jout = json_out_new(tmpctx); - const char *id = append_json_id(tmpctx, plugin, method, "init/"); + const char *id = json_id(tmpctx, plugin, "init/", method); json_out_start(jout, NULL, '{'); json_out_addstr(jout, "jsonrpc", "2.0"); diff --git a/plugins/libplugin.h b/plugins/libplugin.h index af9728bd9ff8..7d13ae226452 100644 --- a/plugins/libplugin.h +++ b/plugins/libplugin.h @@ -123,13 +123,10 @@ struct out_req *jsonrpc_request_start_(struct command *cmd, const jsmntok_t *result, void *arg), void *arg) - NON_NULL_ARGS(1, 2, 3, 5); + NON_NULL_ARGS(1, 2, 5); -/* This variant has callbacks received whole obj, not "result" or - * "error" members. */ -#define jsonrpc_request_start(cmd, method, cb, errcb, arg) \ - jsonrpc_request_start_((cmd), (method), \ - json_id_prefix(tmpctx, (cmd)), NULL, \ +#define jsonrpc_request_start(cmd, method, cb, errcb, arg) \ + jsonrpc_request_start_((cmd), (method), NULL, NULL, \ typesafe_cb_preargs(struct command_result *, void *, \ (cb), (arg), \ struct command *command, \ @@ -143,8 +140,7 @@ struct out_req *jsonrpc_request_start_(struct command *cmd, (arg)) #define jsonrpc_request_with_filter_start(cmd, method, filter, cb, errcb, arg) \ - jsonrpc_request_start_((cmd), (method), \ - json_id_prefix(tmpctx, (cmd)), (filter), \ + jsonrpc_request_start_((cmd), (method), NULL, (filter), \ typesafe_cb_preargs(struct command_result *, void *, \ (cb), (arg), \ struct command *command, \ @@ -160,7 +156,7 @@ struct out_req *jsonrpc_request_start_(struct command *cmd, /* This variant has callbacks received whole obj, not "result" or * "error" members. It also doesn't start params{}. */ #define jsonrpc_request_whole_object_start(cmd, method, id_prefix, cb, arg) \ - jsonrpc_request_start_((cmd), (method), (id_prefix), NULL, \ + jsonrpc_request_start_((cmd), (method), (id_prefix), NULL, \ typesafe_cb_preargs(struct command_result *, void *, \ (cb), (arg), \ struct command *command, \ @@ -641,9 +637,6 @@ struct createonion_response *json_to_createonion_response(const tal_t *ctx, struct route_hop *json_to_route(const tal_t *ctx, const char *buffer, const jsmntok_t *toks); -/* Create a prefix (ending in /) for this cmd_id, if any. */ -const char *json_id_prefix(const tal_t *ctx, const struct command *cmd); - void plugin_set_memleak_handler(struct plugin *plugin, void (*mark_mem)(struct plugin *plugin, struct htable *memtable)); diff --git a/plugins/test/run-route-calc.c b/plugins/test/run-route-calc.c index ee5859e2d475..f6a68ff64d36 100644 --- a/plugins/test/run-route-calc.c +++ b/plugins/test/run-route-calc.c @@ -161,9 +161,6 @@ void json_array_start(struct json_stream *js UNNEEDED, const char *fieldname UNN const jsmntok_t *json_get_member(const char *buffer UNNEEDED, const jsmntok_t tok[] UNNEEDED, const char *label UNNEEDED) { fprintf(stderr, "json_get_member called!\n"); abort(); } -/* Generated stub for json_id_prefix */ -const char *json_id_prefix(const tal_t *ctx UNNEEDED, const struct command *cmd UNNEEDED) -{ fprintf(stderr, "json_id_prefix called!\n"); abort(); } /* Generated stub for json_next */ const jsmntok_t *json_next(const jsmntok_t *tok UNNEEDED) { fprintf(stderr, "json_next called!\n"); abort(); } diff --git a/plugins/test/run-route-overlong.c b/plugins/test/run-route-overlong.c index fc5a40c5b51f..3a7e6888e94f 100644 --- a/plugins/test/run-route-overlong.c +++ b/plugins/test/run-route-overlong.c @@ -158,9 +158,6 @@ void json_array_start(struct json_stream *js UNNEEDED, const char *fieldname UNN const jsmntok_t *json_get_member(const char *buffer UNNEEDED, const jsmntok_t tok[] UNNEEDED, const char *label UNNEEDED) { fprintf(stderr, "json_get_member called!\n"); abort(); } -/* Generated stub for json_id_prefix */ -const char *json_id_prefix(const tal_t *ctx UNNEEDED, const struct command *cmd UNNEEDED) -{ fprintf(stderr, "json_id_prefix called!\n"); abort(); } /* Generated stub for json_next */ const jsmntok_t *json_next(const jsmntok_t *tok UNNEEDED) { fprintf(stderr, "json_next called!\n"); abort(); } From 774b54a9007877ec9fc1aae9c11ef760f608098b Mon Sep 17 00:00:00 2001 From: Rusty Russell Date: Thu, 7 Nov 2024 11:57:37 +1030 Subject: [PATCH 16/18] libplugin: add method string to jsonrpc callbacks, implement generic helpers. Without knowing what method was called, we can't have useful general logging methods, so go through the pain of adding "const char *method" everywhere, and add: 1. ignore_and_complete - we're done when jsonrpc returned 2. log_broken_and_complete - we're done, but emit BROKEN log. 3. plugin_broken_cb - if this happens, fail the plugin. Signed-off-by: Rusty Russell --- plugins/askrene/askrene.c | 1 + plugins/autoclean.c | 18 ++---- plugins/bkpr/bookkeeper.c | 31 +++++++--- plugins/chanbackup.c | 13 +++- plugins/commando.c | 16 +++-- plugins/establish_onion_path.c | 3 + plugins/fetchinvoice.c | 8 ++- plugins/funder.c | 23 +++++-- plugins/keysend.c | 9 ++- plugins/libplugin-pay.c | 52 +++++++++++----- plugins/libplugin.c | 97 ++++++++++++++++++++++++------ plugins/libplugin.h | 51 +++++++++++++++- plugins/offers.c | 6 ++ plugins/offers.h | 4 ++ plugins/offers_inv_hook.c | 4 ++ plugins/offers_invreq_hook.c | 10 ++- plugins/offers_offer.c | 6 +- plugins/pay.c | 12 +++- plugins/recover.c | 11 +++- plugins/renepay/mods.c | 8 +++ plugins/renepay/routefail.c | 4 +- plugins/renepay/routetracker.c | 2 + plugins/spender/fundchannel.c | 2 + plugins/spender/multifundchannel.c | 19 +++++- plugins/spender/multifundchannel.h | 1 + plugins/spender/multiwithdraw.c | 9 +++ plugins/spender/openchannel.c | 6 ++ plugins/sql.c | 3 + plugins/test/run-route-calc.c | 2 + plugins/test/run-route-overlong.c | 2 + plugins/topology.c | 26 +++----- plugins/txprepare.c | 6 ++ tests/plugins/test_libplugin.c | 4 +- 33 files changed, 367 insertions(+), 102 deletions(-) diff --git a/plugins/askrene/askrene.c b/plugins/askrene/askrene.c index 0d35add211f3..d01d4a90c2e4 100644 --- a/plugins/askrene/askrene.c +++ b/plugins/askrene/askrene.c @@ -719,6 +719,7 @@ static void add_localchan(struct gossmap_localmods *mods, static struct command_result * listpeerchannels_done(struct command *cmd, + const char *method UNUSED, const char *buffer, const jsmntok_t *toks, struct getroutes_info *info) diff --git a/plugins/autoclean.c b/plugins/autoclean.c index c69683cfe30b..197d659667da 100644 --- a/plugins/autoclean.c +++ b/plugins/autoclean.c @@ -305,6 +305,7 @@ static struct command_result *clean_finished_one(struct clean_info *cinfo) } static struct command_result *del_done(struct command *cmd, + const char *method, const char *buf, const jsmntok_t *result, struct per_variant *variant) @@ -314,6 +315,7 @@ static struct command_result *del_done(struct command *cmd, } static struct command_result *del_failed(struct command *cmd, + const char *method, const char *buf, const jsmntok_t *result, struct per_variant *variant) @@ -477,6 +479,7 @@ static void add_forward_del_fields(struct out_req *req, } static struct command_result *list_done(struct command *cmd, + const char *method, const char *buf, const jsmntok_t *result, struct per_subsystem *subsystem) @@ -520,6 +523,7 @@ static struct command_result *list_done(struct command *cmd, } static struct command_result *list_failed(struct command *cmd, + const char *method, const char *buf, const jsmntok_t *result, struct per_subsystem *subsystem) @@ -577,6 +581,7 @@ static struct command_result *do_clean(struct clean_info *cinfo) } static struct command_result *wait_done(struct command *cmd, + const char *method, const char *buf, const jsmntok_t *result, struct per_subsystem *ps) @@ -599,17 +604,6 @@ static struct command_result *wait_done(struct command *cmd, return do_clean(ps->cinfo); } -static struct command_result *wait_failed(struct command *cmd, - const char *buf, - const jsmntok_t *result, - struct per_subsystem *subsystem) -{ - plugin_err(plugin, "Failed wait '%s': '%.*s'", - get_subsystem_ops(subsystem)->system_name, - json_tok_full_len(result), - json_tok_full(buf, result)); -} - static struct command_result *start_clean(struct clean_info *cinfo) { cinfo->cleanup_reqs_remaining = 0; @@ -630,7 +624,7 @@ static struct command_result *start_clean(struct clean_info *cinfo) req = jsonrpc_request_start(cinfo->cmd, "wait", - wait_done, wait_failed, ps); + wait_done, plugin_broken_cb, ps); json_add_string(req->js, "subsystem", ops->system_name); json_add_string(req->js, "indexname", "created"); json_add_u64(req->js, "nextvalue", 0); diff --git a/plugins/bkpr/bookkeeper.c b/plugins/bkpr/bookkeeper.c index 13821538c02f..596d64ddd999 100644 --- a/plugins/bkpr/bookkeeper.c +++ b/plugins/bkpr/bookkeeper.c @@ -52,7 +52,9 @@ struct apy_req { }; static struct command_result * -getblockheight_done(struct command *cmd, const char *buf, +getblockheight_done(struct command *cmd, + const char *method, + const char *buf, const jsmntok_t *result, struct apy_req *req) { @@ -851,19 +853,21 @@ static void log_journal_entry(struct account *acct, } static struct command_result *log_error(struct command *cmd, + const char *method, const char *buf, const jsmntok_t *error, void *arg UNNEEDED) { plugin_log(cmd->plugin, LOG_BROKEN, - "error calling rpc: %.*s", - json_tok_full_len(error), + "error calling %s: %.*s", + method, json_tok_full_len(error), json_tok_full(buf, error)); return notification_handled(cmd); } static struct command_result *listpeerchannels_multi_done(struct command *cmd, + const char *method, const char *buf, const jsmntok_t *result, struct new_account_info **new_accts) @@ -1198,8 +1202,11 @@ static char *fetch_out_desc_invstr(const tal_t *ctx, const char *buf, } static struct command_result * -listinvoices_done(struct command *cmd, const char *buf, - const jsmntok_t *result, struct sha256 *payment_hash) +listinvoices_done(struct command *cmd, + const char *method, + const char *buf, + const jsmntok_t *result, + struct sha256 *payment_hash) { size_t i; const jsmntok_t *inv_arr_tok, *inv_tok; @@ -1243,8 +1250,11 @@ listinvoices_done(struct command *cmd, const char *buf, } static struct command_result * -listsendpays_done(struct command *cmd, const char *buf, - const jsmntok_t *result, struct sha256 *payment_hash) +listsendpays_done(struct command *cmd, + const char *method, + const char *buf, + const jsmntok_t *result, + struct sha256 *payment_hash) { size_t i; const jsmntok_t *pays_arr_tok, *pays_tok; @@ -1310,8 +1320,11 @@ struct event_info { }; static struct command_result * -listpeerchannels_done(struct command *cmd, const char *buf, - const jsmntok_t *result, struct event_info *info) +listpeerchannels_done(struct command *cmd, + const char *method, + const char *buf, + const jsmntok_t *result, + struct event_info *info) { struct acct_balance **balances, *bal; struct amount_msat credit_diff, debit_diff; diff --git a/plugins/chanbackup.c b/plugins/chanbackup.c index 98835af1bbcd..34d1b50a4d09 100644 --- a/plugins/chanbackup.c +++ b/plugins/chanbackup.c @@ -216,6 +216,7 @@ static u8 *decrypt_scb(struct plugin *p) } static struct command_result *after_recover_rpc(struct command *cmd, + const char *method, const char *buf, const jsmntok_t *params, void *cb_arg UNUSED) @@ -263,7 +264,7 @@ static struct command_result *json_emergencyrecover(struct command *cmd, req = jsonrpc_request_start(cmd, "recoverchannel", after_recover_rpc, - &forward_error, NULL); + forward_error, NULL); json_array_start(req->js, "scb"); for (size_t i=0; ioff = 0; - return send_response(command, NULL, NULL, reply); + return send_response(command, NULL, NULL, NULL, reply); } static struct command_result *commando_error(struct command *cmd, @@ -216,7 +218,7 @@ static struct command_result *commando_error(struct command *cmd, reply->off = 0; reply->len = tal_bytelen(reply->buf) - 1; - return send_response(cmd, NULL, NULL, reply); + return send_response(cmd, NULL, NULL, NULL, reply); } struct cond_info { @@ -320,6 +322,7 @@ static struct command_result *execute_command(struct command *cmd, } static struct command_result *checkrune_done(struct command *cmd, + const char *method, const char *buf, const jsmntok_t *result, struct cond_info *cinfo) @@ -347,6 +350,7 @@ static struct command_result *checkrune_done(struct command *cmd, } static struct command_result *checkrune_failed(struct command *cmd, + const char *method, const char *buf, const jsmntok_t *result, struct cond_info *cinfo) @@ -617,6 +621,7 @@ struct outgoing { }; static struct command_result *send_more_cmd(struct command *cmd, + const char *method UNUSED, const char *buf UNUSED, const jsmntok_t *result UNUSED, struct outgoing *outgoing) @@ -703,19 +708,20 @@ static struct command_result *json_commando(struct command *cmd, outgoing->msgs[i] = cmd_msg; } - return send_more_cmd(cmd, NULL, NULL, outgoing); + return send_more_cmd(cmd, NULL, NULL, NULL, outgoing); } /* Handles error or success */ static struct command_result *forward_reply(struct command *cmd, + const char *method, const char *buf, const jsmntok_t *result, void *arg) { const jsmntok_t *err = json_get_member(buf, result, "error"); if (err) - return forward_error(cmd, buf, err, arg); - return forward_result(cmd, buf, json_get_member(buf, result, "result"), arg); + return forward_error(cmd, method, buf, err, arg); + return forward_result(cmd, method, buf, json_get_member(buf, result, "result"), arg); } static struct command_result *forward_command(struct command *cmd, diff --git a/plugins/establish_onion_path.c b/plugins/establish_onion_path.c index c58702b92a04..2659a839e7b6 100644 --- a/plugins/establish_onion_path.c +++ b/plugins/establish_onion_path.c @@ -20,6 +20,7 @@ struct connect_info { }; static struct command_result *connect_ok(struct command *cmd, + const char *method, const char *buf, const jsmntok_t *result, struct connect_info *ci) @@ -34,6 +35,7 @@ static struct command_result *connect_ok(struct command *cmd, } static struct command_result *command_failed(struct command *cmd, + const char *method, const char *buf, const jsmntok_t *result, struct connect_info *ci) @@ -185,6 +187,7 @@ static const struct pubkey *path_to_node(const tal_t *ctx, } static struct command_result *listpeers_done(struct command *cmd, + const char *method, const char *buf, const jsmntok_t *result, struct connect_info *ci) diff --git a/plugins/fetchinvoice.c b/plugins/fetchinvoice.c index 8ce7fc96370f..93fc23bab202 100644 --- a/plugins/fetchinvoice.c +++ b/plugins/fetchinvoice.c @@ -407,6 +407,7 @@ static struct command_result *timeout_sent_invreq(struct command *timer_cmd, } static struct command_result *sendonionmsg_done(struct command *cmd, + const char *method UNUSED, const char *buf UNUSED, const jsmntok_t *result UNUSED, struct sent *sent) @@ -493,6 +494,7 @@ struct establishing_paths { struct sent *sent; struct tlv_onionmsg_tlv *final_tlv; struct command_result *(*done)(struct command *cmd, + const char *method UNUSED, const char *buf UNUSED, const jsmntok_t *result UNUSED, struct sent *sent); @@ -605,6 +607,7 @@ static struct command_result *send_message(struct command *cmd, struct tlv_onionmsg_tlv *final_tlv STEALS, struct command_result *(*done) (struct command *cmd, + const char *method UNUSED, const char *buf UNUSED, const jsmntok_t *result UNUSED, struct sent *sent)) @@ -637,6 +640,7 @@ static struct command_result *timeout_sent_inv(struct command *timer_cmd, } static struct command_result *prepare_inv_timeout(struct command *cmd, + const char *method UNUSED, const char *buf UNUSED, const jsmntok_t *result UNUSED, struct sent *sent) @@ -644,10 +648,11 @@ static struct command_result *prepare_inv_timeout(struct command *cmd, command_timer(cmd, time_from_sec(sent->wait_timeout), timeout_sent_inv, sent); - return sendonionmsg_done(cmd, buf, result, sent); + return sendonionmsg_done(cmd, method, buf, result, sent); } static struct command_result *invreq_done(struct command *cmd, + const char *method, const char *buf, const jsmntok_t *result, struct sent *sent) @@ -1106,6 +1111,7 @@ struct command_result *invoice_payment(struct command *cmd, } static struct command_result *createinvoice_done(struct command *cmd, + const char *method, const char *buf, const jsmntok_t *result, struct sent *sent) diff --git a/plugins/funder.c b/plugins/funder.c index 20c38a3d62cf..285c2a13c8c0 100644 --- a/plugins/funder.c +++ b/plugins/funder.c @@ -74,6 +74,7 @@ new_channel_open(const tal_t *ctx, static struct command_result * unreserve_done(struct command *aux_cmd, + const char *method, const char *buf, const jsmntok_t *result, struct pending_open *open) @@ -140,6 +141,7 @@ command_hook_cont_psbt(struct command *cmd, struct wally_psbt *psbt) static struct command_result * datastore_del_fail(struct command *cmd, + const char *method, const char *buf, const jsmntok_t *error, void *data UNUSED) @@ -150,6 +152,7 @@ datastore_del_fail(struct command *cmd, static struct command_result * datastore_del_success(struct command *cmd, + const char *method, const char *buf, const jsmntok_t *result, void *data UNUSED) @@ -165,14 +168,15 @@ datastore_del_success(struct command *cmd, static struct command_result * datastore_add_fail(struct command *cmd, + const char *method, const char *buf, const jsmntok_t *error, struct wally_psbt *signed_psbt) { /* Oops, something's broken */ plugin_log(cmd->plugin, LOG_BROKEN, - "`datastore` add failed: %*.s", - json_tok_full_len(error), + "%s failed: %*.s", + method, json_tok_full_len(error), json_tok_full(buf, error)); return command_hook_cont_psbt(cmd, signed_psbt); @@ -180,6 +184,7 @@ datastore_add_fail(struct command *cmd, static struct command_result * datastore_add_success(struct command *cmd, + const char *method, const char *buf, const jsmntok_t *result, struct wally_psbt *signed_psbt) @@ -242,6 +247,7 @@ remember_channel_utxos(struct command *cmd, static struct command_result * signpsbt_done(struct command *cmd, + const char *method, const char *buf, const jsmntok_t *result, struct pending_open *open) @@ -417,6 +423,7 @@ static struct open_info *new_open_info(const tal_t *ctx) static struct command_result * psbt_funded(struct command *cmd, + const char *method, const char *buf, const jsmntok_t *result, struct open_info *info) @@ -462,6 +469,7 @@ psbt_funded(struct command *cmd, static struct command_result * psbt_fund_failed(struct command *cmd, + const char *method, const char *buf, const jsmntok_t *error, struct open_info *info) @@ -469,9 +477,10 @@ psbt_fund_failed(struct command *cmd, /* Attempt to fund a psbt for this open failed. * We probably ran out of funds (race?) */ plugin_log(cmd->plugin, LOG_INFORM, - "Unable to secure %s from wallet," + "%s: unable to secure %s from wallet," " continuing channel open to %s" " without our participation. err %.*s", + method, fmt_amount_sat(tmpctx, info->our_funding), fmt_node_id(tmpctx, &info->id), json_tok_full_len(error), @@ -567,6 +576,7 @@ build_utxopsbt_request(struct command *cmd, static struct command_result * listfunds_success(struct command *cmd, + const char *method, const char *buf, const jsmntok_t *result, struct open_info *info) @@ -750,6 +760,7 @@ listfunds_success(struct command *cmd, static struct command_result * listfunds_failed(struct command *cmd, + const char *method, const char *buf, const jsmntok_t *error, struct open_info *info) @@ -903,6 +914,7 @@ json_openchannel2_call(struct command *cmd, static struct command_result * datastore_list_fail(struct command *cmd, + const char *method, const char *buf, const jsmntok_t *error, struct open_info *info) @@ -927,6 +939,7 @@ datastore_list_fail(struct command *cmd, static struct command_result * datastore_list_success(struct command *cmd, + const char *method, const char *buf, const jsmntok_t *result, struct open_info *info) @@ -1317,7 +1330,9 @@ parse_lease_rates(struct command *cmd, const char *buffer, } static struct command_result * -leaserates_set(struct command *cmd, const char *buf, +leaserates_set(struct command *cmd, + const char *method, + const char *buf, const jsmntok_t *result, struct funder_policy *policy) { diff --git a/plugins/keysend.c b/plugins/keysend.c index a2020f1558dd..b92f22c73731 100644 --- a/plugins/keysend.c +++ b/plugins/keysend.c @@ -198,6 +198,7 @@ struct payment_modifier *pay_mods[] = { static struct command_result * preapprovekeysend_succeed(struct command *cmd, + const char *method, const char *buf, const jsmntok_t *result, struct payment *p) @@ -378,7 +379,9 @@ static bool keysend_accept_extra_tlv_type(u64 type) } static struct command_result * -htlc_accepted_invoice_created(struct command *cmd, const char *buf, +htlc_accepted_invoice_created(struct command *cmd, + const char *method, + const char *buf, const jsmntok_t *result, struct keysend_in *ki) { @@ -445,7 +448,9 @@ htlc_accepted_invoice_created(struct command *cmd, const char *buf, } static struct command_result * -htlc_accepted_invoice_failed(struct command *cmd, const char *buf, +htlc_accepted_invoice_failed(struct command *cmd, + const char *method, + const char *buf, const jsmntok_t *error, struct keysend_in *ki) { diff --git a/plugins/libplugin-pay.c b/plugins/libplugin-pay.c index 7a086a262c78..ed78d76815d2 100644 --- a/plugins/libplugin-pay.c +++ b/plugins/libplugin-pay.c @@ -216,13 +216,14 @@ paymod_err(struct payment *p, const char *fmt, ...) /* Generic handler for RPC failures that should end up failing the payment. */ static struct command_result *payment_rpc_failure(struct command *cmd, + const char *method, const char *buffer, const jsmntok_t *toks, struct payment *p) { return payment_fail(p, - "Failing a partial payment due to a failed RPC call: %.*s", - toks->end - toks->start, buffer + toks->start); + "Failing a partial payment due to a failed RPC call %s: %.*s", + method, toks->end - toks->start, buffer + toks->start); } struct payment_tree_result payment_collect_result(struct payment *p) @@ -279,6 +280,7 @@ struct payment_tree_result payment_collect_result(struct payment *p) } static struct command_result *payment_waitblockheight_cb(struct command *cmd, + const char *method, const char *buffer, const jsmntok_t *toks, struct payment *p) @@ -300,6 +302,7 @@ static struct command_result *payment_waitblockheight_cb(struct command *cmd, static struct command_result * payment_getblockheight_success(struct command *cmd, + const char *method, const char *buffer, const jsmntok_t *toks, struct payment *p) @@ -954,8 +957,11 @@ static bool payment_listpeerchannels_balance_sum(struct payment *p, } static struct command_result * -payment_listpeerchannels_success(struct command *cmd, const char *buffer, - const jsmntok_t *toks, struct payment *p) +payment_listpeerchannels_success(struct command *cmd, + const char *method, + const char *buffer, + const jsmntok_t *toks, + struct payment *p) { /* The maximum amount we may end up trying to send. This * includes the value and the full fee budget. If the @@ -1566,7 +1572,9 @@ static u8 *channel_update_from_onion_error(const tal_t *ctx, static struct command_result * -payment_addgossip_success(struct command *cmd, const char *buffer, +payment_addgossip_success(struct command *cmd, + const char *method, + const char *buffer, const jsmntok_t *toks, struct payment *p) { const struct node_id *errnode; @@ -1592,18 +1600,22 @@ payment_addgossip_success(struct command *cmd, const char *buffer, /* If someone gives us an invalid update, all we can do is log it */ static struct command_result * -payment_addgossip_failure(struct command *cmd, const char *buffer, +payment_addgossip_failure(struct command *cmd, + const char *method, + const char *buffer, const jsmntok_t *toks, struct payment *p) { paymod_log(p, LOG_DBG, "Invalid channel_update: %.*s", json_tok_full_len(toks), json_tok_full(buffer, toks)); - return payment_addgossip_success(cmd, NULL, NULL, p); + return payment_addgossip_success(cmd, NULL, NULL, NULL, p); } static struct command_result * -payment_waitsendpay_finished(struct command *cmd, const char *buffer, +payment_waitsendpay_finished(struct command *cmd, + const char *method, + const char *buffer, const jsmntok_t *toks, struct payment *p) { u8 *update; @@ -1646,13 +1658,14 @@ payment_waitsendpay_finished(struct command *cmd, const char *buffer, return send_outreq(req); } - return payment_addgossip_success(cmd, NULL, NULL, p); + return payment_addgossip_success(cmd, NULL, NULL, NULL, p); } static struct command_result *payment_sendonion_success(struct command *cmd, - const char *buffer, - const jsmntok_t *toks, - struct payment *p) + const char *method, + const char *buffer, + const jsmntok_t *toks, + struct payment *p) { struct out_req *req; req = jsonrpc_request_start(payment_cmd(p), "waitsendpay", @@ -1665,6 +1678,7 @@ static struct command_result *payment_sendonion_success(struct command *cmd, } static struct command_result *payment_createonion_success(struct command *cmd, + const char *method, const char *buffer, const jsmntok_t *toks, struct payment *p) @@ -2481,7 +2495,9 @@ REGISTER_PAYMENT_MODIFIER(retry, struct retry_mod_data *, retry_data_init, retry_step_cb); static struct command_result * -local_channel_hints_listpeerchannels(struct command *cmd, const char *buffer, +local_channel_hints_listpeerchannels(struct command *cmd, + const char *method, + const char *buffer, const jsmntok_t *toks, struct payment *p) { struct listpeers_channel **chans; @@ -3176,6 +3192,7 @@ static struct shadow_route_data *shadow_route_init(struct payment *p) /* Mutual recursion */ static struct command_result *shadow_route_listchannels(struct command *cmd, + const char *method, const char *buf, const jsmntok_t *result, struct payment *p); @@ -3192,9 +3209,10 @@ static struct command_result *shadow_route_extend(struct shadow_route_data *d, } static struct command_result *shadow_route_listchannels(struct command *cmd, - const char *buf, - const jsmntok_t *result, - struct payment *p) + const char *method, + const char *buf, + const jsmntok_t *result, + struct payment *p) { struct shadow_route_data *d = payment_mod_shadowroute_get_data(p); struct payment_constraints *cons = &d->constraints; @@ -3399,6 +3417,7 @@ static struct command_result *direct_pay_override(struct payment *p) * for a direct channel that is a) connected and b) in state normal. We will * check the capacity based on the channel_hints in the override. */ static struct command_result *direct_pay_listpeerchannels(struct command *cmd, + const char *method, const char *buffer, const jsmntok_t *toks, struct payment *p) @@ -3702,6 +3721,7 @@ REGISTER_PAYMENT_MODIFIER(adaptive_splitter, struct adaptive_split_mod_data *, static struct command_result * payee_incoming_limit_count(struct command *cmd, + const char *method, const char *buf, const jsmntok_t *result, struct payment *p) diff --git a/plugins/libplugin.c b/plugins/libplugin.c index a912082b7c7d..384850033615 100644 --- a/plugins/libplugin.c +++ b/plugins/libplugin.c @@ -258,6 +258,7 @@ static void ld_rpc_send(struct plugin *plugin, struct json_stream *stream) /* When cmd for request is gone, we use this as noop callback */ static struct command_result *ignore_cb(struct command *command, + const char *method, const char *buf, const jsmntok_t *result, void *arg) @@ -265,6 +266,62 @@ static struct command_result *ignore_cb(struct command *command, return &complete; } +/* Ignore the result, and terminate the timer/aux/hook */ +struct command_result *ignore_and_complete(struct command *cmd, + const char *method, + const char *buf, + const jsmntok_t *result, + void *arg) +{ + switch (cmd->type) { + case COMMAND_TYPE_NORMAL: + case COMMAND_TYPE_CHECK: + case COMMAND_TYPE_USAGE_ONLY: + plugin_err(cmd->plugin, + "%s: cannot ignore_and_complete type %u", + method, cmd->type); + case COMMAND_TYPE_HOOK: + return command_hook_success(cmd); + /* Terminate with aux_command_done */ + case COMMAND_TYPE_AUX: + return aux_command_done(cmd); + case COMMAND_TYPE_NOTIFICATION: + return notification_handled(cmd); + case COMMAND_TYPE_TIMER: + return timer_complete(cmd); + } + abort(); +} + +/* Broken the result, and terminate the command */ +struct command_result *log_broken_and_complete(struct command *cmd, + const char *method, + const char *buf, + const jsmntok_t *result, + void *arg) +{ + plugin_log(cmd->plugin, LOG_BROKEN, + "%s failed with %.*s", + method, + json_tok_full_len(result), + json_tok_full(buf, result)); + return ignore_and_complete(cmd, method, buf, result, arg); +} + +/* Call plugin_err */ +struct command_result *plugin_broken_cb(struct command *cmd, + const char *method, + const char *buf, + const jsmntok_t *result, + void *arg) +{ + plugin_err(cmd->plugin, + "%s failed with %.*s", + method, + json_tok_full_len(result), + json_tok_full(buf, result)); +} + static void disable_request_cb(struct command *cmd, struct out_req *out) { out->errcb = NULL; @@ -308,10 +365,12 @@ jsonrpc_request_start_(struct command *cmd, const char *id_prefix, const char *filter, struct command_result *(*cb)(struct command *command, + const char *methodname, const char *buf, const jsmntok_t *result, void *arg), struct command_result *(*errcb)(struct command *command, + const char *methodname, const char *buf, const jsmntok_t *result, void *arg), @@ -321,6 +380,7 @@ jsonrpc_request_start_(struct command *cmd, assert(cmd); out = tal(cmd, struct out_req); + out->method = tal_strdup(out, method); out->id = json_id(out, cmd->plugin, method, id_prefix ? id_prefix : cmd->id); out->cmd = cmd; out->cb = cb; @@ -577,6 +637,7 @@ struct command_result *timer_complete(struct command *cmd) } struct command_result *forward_error(struct command *cmd, + const char *method, const char *buf, const jsmntok_t *error, void *arg UNNEEDED) @@ -587,6 +648,7 @@ struct command_result *forward_error(struct command *cmd, } struct command_result *forward_result(struct command *cmd, + const char *method, const char *buf, const jsmntok_t *result, void *arg UNNEEDED) @@ -846,26 +908,18 @@ void rpc_enable_batching(struct plugin *plugin) sync_req(tmpctx, plugin, "batching", take(params), &p); } -static struct command_result *datastore_fail(struct command *command, - const char *buf, - const jsmntok_t *result, - void *unused) -{ - plugin_err(command->plugin, "datastore failed: %.*s", - json_tok_full_len(result), - json_tok_full(buf, result)); -} - struct command_result *jsonrpc_set_datastore_(struct command *cmd, const char *path, const void *value, bool value_is_string, const char *mode, struct command_result *(*cb)(struct command *command, + const char *method, const char *buf, const jsmntok_t *result, void *arg), struct command_result *(*errcb)(struct command *command, + const char *method, const char *buf, const jsmntok_t *result, void *arg), @@ -876,7 +930,7 @@ struct command_result *jsonrpc_set_datastore_(struct command *cmd, if (!cb) cb = ignore_cb; if (!errcb) - errcb = datastore_fail; + errcb = plugin_broken_cb; req = jsonrpc_request_start(cmd, "datastore", cb, errcb, arg); @@ -900,6 +954,7 @@ struct get_ds_info { }; static struct command_result *listdatastore_done(struct command *cmd, + const char *method, const char *buf, const jsmntok_t *result, struct get_ds_info *dsi) @@ -957,7 +1012,7 @@ struct command_result *jsonrpc_get_datastore_(struct command *cmd, /* listdatastore doesn't fail (except API misuse) */ req = jsonrpc_request_start(cmd, "listdatastore", - listdatastore_done, datastore_fail, dsi); + listdatastore_done, plugin_broken_cb, dsi); tal_steal(req, dsi); json_add_keypath(req->js->jout, "key", path); @@ -1006,9 +1061,9 @@ static void handle_rpc_reply(struct plugin *plugin, const jsmntok_t *toks) contenttok = json_get_member(buf, toks, "error"); if (contenttok) { if (out->errcb) - res = out->errcb(out->cmd, buf, contenttok, out->arg); + res = out->errcb(out->cmd, out->method, buf, contenttok, out->arg); else - res = out->cb(out->cmd, buf, toks, out->arg); + res = out->cb(out->cmd, out->method, buf, toks, out->arg); } else { contenttok = json_get_member(buf, toks, "result"); if (!contenttok) @@ -1017,9 +1072,9 @@ static void handle_rpc_reply(struct plugin *plugin, const jsmntok_t *toks) json_tok_full(buf, toks)); /* errcb is NULL if it's a single whole-object callback */ if (out->errcb) - res = out->cb(out->cmd, buf, contenttok, out->arg); + res = out->cb(out->cmd, out->method, buf, contenttok, out->arg); else - res = out->cb(out->cmd, buf, toks, out->arg); + res = out->cb(out->cmd, out->method, buf, toks, out->arg); } if (res == &complete) { @@ -1050,10 +1105,12 @@ struct request_batch { size_t num_remaining; struct command_result *(*cb)(struct command *, + const char *, const char *, const jsmntok_t *, void *); struct command_result *(*errcb)(struct command *, + const char *, const char *, const jsmntok_t *, void *); @@ -1064,10 +1121,12 @@ struct request_batch { struct request_batch *request_batch_new_(const tal_t *ctx, struct command_result *(*cb)(struct command *, + const char *, const char *, const jsmntok_t *, void *), struct command_result *(*errcb)(struct command *, + const char *, const char *, const jsmntok_t *, void *), @@ -1103,23 +1162,25 @@ static struct command_result *batch_one_complete(struct command *cmd, } static struct command_result *batch_one_success(struct command *cmd, + const char *method, const char *buf, const jsmntok_t *result, struct request_batch *batch) { /* If this frees stuff (e.g. fails), just return */ - if (batch->cb && batch->cb(cmd, buf, result, batch->arg) == &complete) + if (batch->cb && batch->cb(cmd, method, buf, result, batch->arg) == &complete) return &complete; return batch_one_complete(cmd, batch); } static struct command_result *batch_one_failed(struct command *cmd, + const char *method, const char *buf, const jsmntok_t *result, struct request_batch *batch) { /* If this frees stuff (e.g. fails), just return */ - if (batch->errcb && batch->errcb(cmd, buf, result, batch->arg) == &complete) + if (batch->errcb && batch->errcb(cmd, method, buf, result, batch->arg) == &complete) return &complete; return batch_one_complete(cmd, batch); } diff --git a/plugins/libplugin.h b/plugins/libplugin.h index 7d13ae226452..b7c2fc44e7b8 100644 --- a/plugins/libplugin.h +++ b/plugins/libplugin.h @@ -34,15 +34,19 @@ struct out_req { const char *id; /* The command which is why we're calling this rpc. */ struct command *cmd; + /* The method this is calling */ + const char *method; /* The request stream. */ struct json_stream *js; /* The callback when we get a response. */ struct command_result *(*cb)(struct command *command, + const char *method, const char *buf, const jsmntok_t *result, void *arg); /* The callback when we get an error. */ struct command_result *(*errcb)(struct command *command, + const char *method, const char *buf, const jsmntok_t *error, void *arg); @@ -58,8 +62,9 @@ enum command_type { COMMAND_TYPE_AUX, /* Terminate with notification_handled */ COMMAND_TYPE_NOTIFICATION, - /* These self-terminate */ + /* Terminate with timer_complete */ COMMAND_TYPE_TIMER, + /* These self-terminate */ COMMAND_TYPE_CHECK, COMMAND_TYPE_USAGE_ONLY, }; @@ -109,16 +114,39 @@ struct plugin_hook { /* Return the feature set of the current lightning node */ const struct feature_set *plugin_feature_set(const struct plugin *p); +/* Ignore the result, and terminate the command */ +struct command_result *ignore_and_complete(struct command *cmd, + const char *method, + const char *buf, + const jsmntok_t *result, + void *arg); + +/* Broken the result, and terminate the command */ +struct command_result *log_broken_and_complete(struct command *cmd, + const char *method, + const char *buf, + const jsmntok_t *result, + void *arg); + +/* Call plugin_err */ +struct command_result *plugin_broken_cb(struct command *cmd, + const char *method, + const char *buf, + const jsmntok_t *result, + void *arg); + /* Helper to create a JSONRPC2 request stream. Send it with `send_outreq`. */ struct out_req *jsonrpc_request_start_(struct command *cmd, const char *method, const char *id_prefix, const char *filter, struct command_result *(*cb)(struct command *command, + const char *methodname, const char *buf, const jsmntok_t *result, void *arg), struct command_result *(*errcb)(struct command *command, + const char *methodname, const char *buf, const jsmntok_t *result, void *arg), @@ -130,11 +158,13 @@ struct out_req *jsonrpc_request_start_(struct command *cmd, typesafe_cb_preargs(struct command_result *, void *, \ (cb), (arg), \ struct command *command, \ + const char *mthod, \ const char *buf, \ const jsmntok_t *result), \ typesafe_cb_preargs(struct command_result *, void *, \ (errcb), (arg), \ struct command *command, \ + const char *mthod, \ const char *buf, \ const jsmntok_t *result), \ (arg)) @@ -144,11 +174,13 @@ struct out_req *jsonrpc_request_start_(struct command *cmd, typesafe_cb_preargs(struct command_result *, void *, \ (cb), (arg), \ struct command *command, \ + const char *mthod, \ const char *buf, \ const jsmntok_t *result), \ typesafe_cb_preargs(struct command_result *, void *, \ (errcb), (arg), \ struct command *command, \ + const char *mthod, \ const char *buf, \ const jsmntok_t *result), \ (arg)) @@ -160,6 +192,7 @@ struct out_req *jsonrpc_request_start_(struct command *cmd, typesafe_cb_preargs(struct command_result *, void *, \ (cb), (arg), \ struct command *command, \ + const char *mthod, \ const char *buf, \ const jsmntok_t *result), \ NULL, \ @@ -168,10 +201,12 @@ struct out_req *jsonrpc_request_start_(struct command *cmd, /* Batch of requests: cb and errcb are optional, finalcb is called when all complete. */ struct request_batch *request_batch_new_(const tal_t *ctx, struct command_result *(*cb)(struct command *, + const char *method, const char *, const jsmntok_t *, void *), struct command_result *(*errcb)(struct command *, + const char *method, const char *, const jsmntok_t *, void *), @@ -184,11 +219,13 @@ struct request_batch *request_batch_new_(const tal_t *ctx, typesafe_cb_preargs(struct command_result *, void *, \ (cb), (arg), \ struct command *command, \ + const char *method, \ const char *buf, \ const jsmntok_t *result), \ typesafe_cb_preargs(struct command_result *, void *, \ (errcb), (arg), \ struct command *command, \ + const char *method, \ const char *buf, \ const jsmntok_t *result), \ typesafe_cb_preargs(struct command_result *, void *, \ @@ -238,10 +275,12 @@ struct command_result *jsonrpc_set_datastore_(struct command *cmd, bool value_is_string, const char *mode, struct command_result *(*cb)(struct command *command, + const char *method, const char *buf, const jsmntok_t *result, void *arg), struct command_result *(*errcb)(struct command *command, + const char *method, const char *buf, const jsmntok_t *result, void *arg), @@ -253,11 +292,13 @@ struct command_result *jsonrpc_set_datastore_(struct command *cmd, typesafe_cb_preargs(struct command_result *, void *, \ (cb), (arg), \ struct command *command, \ + const char *method, \ const char *buf, \ const jsmntok_t *result), \ typesafe_cb_preargs(struct command_result *, void *, \ (errcb), (arg), \ struct command *command, \ + const char *method, \ const char *buf, \ const jsmntok_t *result), \ (arg)) @@ -267,11 +308,13 @@ struct command_result *jsonrpc_set_datastore_(struct command *cmd, typesafe_cb_preargs(struct command_result *, void *, \ (cb), (arg), \ struct command *command, \ + const char *method, \ const char *buf, \ const jsmntok_t *result), \ typesafe_cb_preargs(struct command_result *, void *, \ (errcb), (arg), \ struct command *command, \ + const char *method, \ const char *buf, \ const jsmntok_t *result), \ (arg)) @@ -424,17 +467,19 @@ struct command_result *send_outreq(const struct out_req *req); /* Callback to just forward error and close request; @cmd cannot be NULL */ struct command_result *forward_error(struct command *cmd, + const char *method, const char *buf, const jsmntok_t *error, void *arg) - NON_NULL_ARGS(1, 2, 3); + NON_NULL_ARGS(1, 2, 3, 4); /* Callback to just forward result and close request; @cmd cannot be NULL */ struct command_result *forward_result(struct command *cmd, + const char *method, const char *buf, const jsmntok_t *result, void *arg) - NON_NULL_ARGS(1, 2, 3); + NON_NULL_ARGS(1, 2, 3, 4); /* Callback for timer where we expect a 'command_result'. All timers * must return this eventually, though they may do so via a convoluted diff --git a/plugins/offers.c b/plugins/offers.c index c4248455e664..3bead103f2e8 100644 --- a/plugins/offers.c +++ b/plugins/offers.c @@ -68,6 +68,7 @@ struct gossmap *get_gossmap(struct plugin *plugin) } static struct command_result *finished(struct command *cmd, + const char *method, const char *buf, const jsmntok_t *result, void *unused) @@ -76,6 +77,7 @@ static struct command_result *finished(struct command *cmd, } static struct command_result *injectonionmessage_error(struct command *cmd, + const char *method, const char *buf, const jsmntok_t *err, void *unused) @@ -93,10 +95,12 @@ struct command_result * inject_onionmessage_(struct command *cmd, const struct onion_message *omsg, struct command_result *(*cb)(struct command *command, + const char *method, const char *buf, const jsmntok_t *result, void *arg), struct command_result *(*errcb)(struct command *command, + const char *method, const char *buf, const jsmntok_t *result, void *arg), @@ -256,6 +260,7 @@ struct find_best_peer_data { }; static struct command_result *listincoming_done(struct command *cmd, + const char *method, const char *buf, const jsmntok_t *result, struct find_best_peer_data *data) @@ -1299,6 +1304,7 @@ static void json_add_rune(struct command *cmd, struct json_stream *js, const str } static struct command_result *after_makesecret(struct command *cmd, + const char *method, const char *buf, const jsmntok_t *result, struct decodable *decodable) diff --git a/plugins/offers.h b/plugins/offers.h index 038be35a837f..d689046be330 100644 --- a/plugins/offers.h +++ b/plugins/offers.h @@ -43,11 +43,13 @@ send_onion_reply(struct command *cmd, (success), (arg), \ struct command *, \ const char *, \ + const char *, \ const jsmntok_t *), \ typesafe_cb_preargs(struct command_result *, void *, \ (fail), (arg), \ struct command *, \ const char *, \ + const char *, \ const jsmntok_t *), \ (arg)) @@ -55,10 +57,12 @@ struct command_result * inject_onionmessage_(struct command *cmd, const struct onion_message *omsg, struct command_result *(*cb)(struct command *command, + const char *method, const char *buf, const jsmntok_t *result, void *arg), struct command_result *(*errcb)(struct command *command, + const char *method, const char *buf, const jsmntok_t *result, void *arg), diff --git a/plugins/offers_inv_hook.c b/plugins/offers_inv_hook.c index 658ae255b537..67fda233b28b 100644 --- a/plugins/offers_inv_hook.c +++ b/plugins/offers_inv_hook.c @@ -91,6 +91,7 @@ fail_internalerr(struct command *cmd, } static struct command_result *pay_done(struct command *cmd, + const char *method, const char *buf, const jsmntok_t *result, struct inv *inv) @@ -107,6 +108,7 @@ static struct command_result *pay_done(struct command *cmd, } static struct command_result *pay_error(struct command *cmd, + const char *method, const char *buf, const jsmntok_t *error, struct inv *inv) @@ -119,6 +121,7 @@ static struct command_result *pay_error(struct command *cmd, } static struct command_result *listinvreqs_done(struct command *cmd, + const char *method, const char *buf, const jsmntok_t *result, struct inv *inv) @@ -198,6 +201,7 @@ static struct command_result *listinvreqs_done(struct command *cmd, } static struct command_result *listinvreqs_error(struct command *cmd, + const char *method, const char *buf, const jsmntok_t *err, struct inv *inv) diff --git a/plugins/offers_invreq_hook.c b/plugins/offers_invreq_hook.c index fdbcbcd59f74..a0c18428bb9f 100644 --- a/plugins/offers_invreq_hook.c +++ b/plugins/offers_invreq_hook.c @@ -161,6 +161,7 @@ static void json_add_label(struct json_stream *js, * used at the same time between the check and now. */ static struct command_result *error(struct command *cmd, + const char *method, const char *buf, const jsmntok_t *err, struct invreq *ir) @@ -173,6 +174,7 @@ static struct command_result *error(struct command *cmd, /* We can fail to create the invoice if we've already done so. */ static struct command_result *createinvoice_done(struct command *cmd, + const char *method, const char *buf, const jsmntok_t *result, struct invreq *ir) @@ -198,6 +200,7 @@ static struct command_result *createinvoice_done(struct command *cmd, } static struct command_result *createinvoice_error(struct command *cmd, + const char *method, const char *buf, const jsmntok_t *err, struct invreq *ir) @@ -208,10 +211,10 @@ static struct command_result *createinvoice_error(struct command *cmd, if (json_scan(tmpctx, buf, err, "{code:%}", JSON_SCAN(json_to_u32, &code)) == NULL && code == INVOICE_LABEL_ALREADY_EXISTS) { - return createinvoice_done(cmd, buf, + return createinvoice_done(cmd, method, buf, json_get_member(buf, err, "data"), ir); } - return error(cmd, buf, err, ir); + return error(cmd, method, buf, err, ir); } static struct command_result *create_invoicereq(struct command *cmd, @@ -483,6 +486,7 @@ static struct command_result *check_period(struct command *cmd, } static struct command_result *prev_invoice_done(struct command *cmd, + const char *method, const char *buf, const jsmntok_t *result, struct invreq *ir) @@ -690,6 +694,7 @@ static struct command_result *handle_amount_and_recurrence(struct command *cmd, } static struct command_result *currency_done(struct command *cmd, + const char *method, const char *buf, const jsmntok_t *result, struct invreq *ir) @@ -760,6 +765,7 @@ static struct command_result *convert_currency(struct command *cmd, } static struct command_result *listoffers_done(struct command *cmd, + const char *method, const char *buf, const jsmntok_t *result, struct invreq *ir) diff --git a/plugins/offers_offer.c b/plugins/offers_offer.c index 5541a1979391..0f84843c76ad 100644 --- a/plugins/offers_offer.c +++ b/plugins/offers_offer.c @@ -235,6 +235,7 @@ struct offer_info { }; static struct command_result *check_result(struct command *cmd, + const char *method, const char *buf, const jsmntok_t *result, void *arg UNNEEDED) @@ -256,7 +257,7 @@ static struct command_result *check_result(struct command *cmd, "Already exists, but isn't active"); /* Otherwise, push through the result. */ - return forward_result(cmd, buf, result, arg); + return forward_result(cmd, method, buf, result, arg); } static struct command_result *create_offer(struct command *cmd, @@ -339,13 +340,14 @@ static struct command_result *maybe_add_path(struct command *cmd, } static struct command_result *currency_done(struct command *cmd, + const char *method, const char *buf, const jsmntok_t *result, struct offer_info *offinfo) { /* Fail in this case, by forwarding warnings. */ if (!json_get_member(buf, result, "msat")) - return forward_error(cmd, buf, result, offinfo); + return forward_error(cmd, method, buf, result, offinfo); return maybe_add_path(cmd, offinfo); } diff --git a/plugins/pay.c b/plugins/pay.c index 9d91fabdba61..6f1590b3e737 100644 --- a/plugins/pay.c +++ b/plugins/pay.c @@ -416,6 +416,7 @@ static void add_new_entry(struct json_stream *ret, } static struct command_result *listsendpays_done(struct command *cmd, + const char *method, const char *buf, const jsmntok_t *result, char *invstring) @@ -808,6 +809,7 @@ static void on_payment_failure(struct payment *payment) } static struct command_result *selfpay_success(struct command *cmd, + const char *method, const char *buf, const jsmntok_t *result, struct payment *p) @@ -864,8 +866,11 @@ static struct command_result *selfpay(struct command *cmd, struct payment *p) * about an eventual previous complete payment so we can return that * as a no-op. */ static struct command_result * -payment_listsendpays_previous(struct command *cmd, const char *buf, - const jsmntok_t *result, struct payment *p) +payment_listsendpays_previous(struct command *cmd, + const char *method, + const char *buf, + const jsmntok_t *result, + struct payment *p) { size_t i; const jsmntok_t *t, *arr, *err; @@ -1058,6 +1063,7 @@ static bool scidtok_eq(const char *buf, /* We are the entry point, so the next hop could actually be an scid alias, * so we can't just use gossmap. */ static struct command_result *listpeerchannels_done(struct command *cmd, + const char *method, const char *buf, const jsmntok_t *result, struct payment *p) @@ -1106,6 +1112,7 @@ static struct command_result *listpeerchannels_done(struct command *cmd, static struct command_result * decrypt_done(struct command *cmd, + const char *method, const char *buf, const jsmntok_t *result, struct payment *p) @@ -1189,6 +1196,7 @@ decrypt_done(struct command *cmd, static struct command_result * preapproveinvoice_succeed(struct command *cmd, + const char *method, const char *buf, const jsmntok_t *result, struct payment *p) diff --git a/plugins/recover.c b/plugins/recover.c index e2f069859684..6ceee127a4eb 100644 --- a/plugins/recover.c +++ b/plugins/recover.c @@ -49,6 +49,7 @@ static const char *nodes_for_gossip[] = { static struct command_result *connect_success(struct command *cmd, + const char *method, const char *buf, const jsmntok_t *params, void *cb_arg UNUSED) @@ -58,6 +59,7 @@ static struct command_result *connect_success(struct command *cmd, } static struct command_result *connect_fail(struct command *cmd, + const char *method, const char *buf, const jsmntok_t *params, void *cb_arg UNUSED) @@ -67,6 +69,7 @@ static struct command_result *connect_fail(struct command *cmd, } static struct command_result *after_emergency_recover(struct command *cmd, + const char *method, const char *buf, const jsmntok_t *params, void *cb_arg UNUSED) @@ -77,9 +80,10 @@ static struct command_result *after_emergency_recover(struct command *cmd, } static struct command_result *after_restorefrompeer(struct command *cmd, - const char *buf, - const jsmntok_t *params, - void *cb_arg UNUSED) + const char *method, + const char *buf, + const jsmntok_t *params, + void *cb_arg UNUSED) { plugin_log(plugin, LOG_DBG, "restorefrompeer called"); @@ -186,6 +190,7 @@ static void entering_recovery_mode(struct command *cmd) } static struct command_result *after_listpeerchannels(struct command *cmd, + const char *method, const char *buf, const jsmntok_t *params, void *cb_arg UNUSED) diff --git a/plugins/renepay/mods.c b/plugins/renepay/mods.c index 4b167aec5447..dd601f23bc6b 100644 --- a/plugins/renepay/mods.c +++ b/plugins/renepay/mods.c @@ -73,6 +73,7 @@ struct command_result *payment_continue(struct payment *payment) /* Generic handler for RPC failures that should end up failing the payment. */ static struct command_result *payment_rpc_failure(struct command *cmd, + const char *method UNUSED, const char *buffer, const jsmntok_t *toks, struct payment *payment) @@ -180,6 +181,7 @@ static bool success_data_from_listsendpays(const char *buf, } static struct command_result *previoussuccess_done(struct command *cmd, + const char *method UNUSED, const char *buf, const jsmntok_t *result, struct payment *payment) @@ -252,6 +254,7 @@ REGISTER_PAYMENT_MODIFIER(initial_sanity_checks, initial_sanity_checks_cb); */ static struct command_result *selfpay_success(struct command *cmd, + const char *method UNUSED, const char *buf, const jsmntok_t *tok, struct route *route) @@ -275,6 +278,7 @@ static struct command_result *selfpay_success(struct command *cmd, return payment_success(payment, &preimage); } static struct command_result *selfpay_failure(struct command *cmd, + const char *method UNUSED, const char *buf, const jsmntok_t *tok, struct route *route) @@ -431,6 +435,7 @@ static void gossmod_cb(struct gossmap_localmods *mods, } static struct command_result *getmychannels_done(struct command *cmd, + const char *method UNUSED, const char *buf, const jsmntok_t *result, struct payment *payment) @@ -576,6 +581,7 @@ static void add_hintchan(struct payment *payment, const struct node_id *src, } static struct command_result *routehints_done(struct command *cmd UNUSED, + const char *method UNUSED, const char *buf UNUSED, const jsmntok_t *result UNUSED, struct payment *payment) @@ -867,6 +873,7 @@ REGISTER_PAYMENT_MODIFIER(collect_results, collect_results_cb); * The default ending of a payment. */ static struct command_result *end_done(struct command *cmd UNUSED, + const char *method UNUSED, const char *buf UNUSED, const jsmntok_t *result UNUSED, struct payment *payment) @@ -912,6 +919,7 @@ REGISTER_PAYMENT_MODIFIER(checktimeout, checktimeout_cb); */ static struct command_result *pendingsendpays_done(struct command *cmd, + const char *method UNUSED, const char *buf, const jsmntok_t *result, struct payment *payment) diff --git a/plugins/renepay/routefail.c b/plugins/renepay/routefail.c index 6b362dc86baf..29d515349565 100644 --- a/plugins/renepay/routefail.c +++ b/plugins/renepay/routefail.c @@ -110,6 +110,7 @@ static u8 *channel_update_from_onion_error(const tal_t *ctx, } static struct command_result *update_gossip_done(struct command *cmd UNUSED, + const char *method UNUSED, const char *buf UNUSED, const jsmntok_t *result UNUSED, struct routefail *r) @@ -118,6 +119,7 @@ static struct command_result *update_gossip_done(struct command *cmd UNUSED, } static struct command_result *update_gossip_failure(struct command *cmd UNUSED, + const char *method UNUSED, const char *buf, const jsmntok_t *result, struct routefail *r) @@ -136,7 +138,7 @@ static struct command_result *update_gossip_failure(struct command *cmd UNUSED, r->payment, scidd, LOG_INFORM, "addgossip failed (%.*s)", json_tok_full_len(result), json_tok_full(buf, result)); - return update_gossip_done(cmd, buf, result, r); + return update_gossip_done(cmd, method, buf, result, r); } static struct command_result *update_gossip(struct routefail *r) diff --git a/plugins/renepay/routetracker.c b/plugins/renepay/routetracker.c index 3184eda7dfb5..5309af1a8bf8 100644 --- a/plugins/renepay/routetracker.c +++ b/plugins/renepay/routetracker.c @@ -194,6 +194,7 @@ static void route_pending_register(struct routetracker *routetracker, /* Callback function for sendpay request success. */ static struct command_result *sendpay_done(struct command *cmd, + const char *method UNUSED, const char *buf UNUSED, const jsmntok_t *result UNUSED, struct route *route) @@ -209,6 +210,7 @@ static struct command_result *sendpay_done(struct command *cmd, * 2. The first peer is disconnected. */ static struct command_result *sendpay_failed(struct command *cmd, + const char *method UNUSED, const char *buf, const jsmntok_t *tok, struct route *route) diff --git a/plugins/spender/fundchannel.c b/plugins/spender/fundchannel.c index 6fc722fa94cc..9dd48c22cf55 100644 --- a/plugins/spender/fundchannel.c +++ b/plugins/spender/fundchannel.c @@ -18,6 +18,7 @@ const size_t num_fundchannel_commands = ARRAY_SIZE(fundchannel_commands); static struct command_result * fundchannel_get_result(struct command *cmd, + const char *method, const char *buf, const jsmntok_t *result, void *nothing UNUSED); @@ -122,6 +123,7 @@ static bool json_to_tok(const char *buffer, const jsmntok_t *tok, const jsmntok_ static struct command_result * fundchannel_get_result(struct command *cmd, + const char *method, const char *buf, const jsmntok_t *result, void *nothing UNUSED) diff --git a/plugins/spender/multifundchannel.c b/plugins/spender/multifundchannel.c index 952b9963b1d2..ef854bee99a0 100644 --- a/plugins/spender/multifundchannel.c +++ b/plugins/spender/multifundchannel.c @@ -152,9 +152,10 @@ mfc_cleanup_complete(struct multifundchannel_cleanup *cleanup) static struct command_result * mfc_cleanup_done(struct command *cmd, - const char *buf UNUSED, - const jsmntok_t *res UNUSED, - struct multifundchannel_cleanup *cleanup) + const char *method, + const char *buf UNUSED, + const jsmntok_t *res UNUSED, + struct multifundchannel_cleanup *cleanup) { --cleanup->pending; if (cleanup->pending == 0) @@ -395,6 +396,7 @@ mfc_err_raw(struct multifundchannel_command *mfc, const char *json_string) } struct command_result * mfc_forward_error(struct command *cmd, + const char *method, const char *buf, const jsmntok_t *error, struct multifundchannel_command *mfc) { @@ -517,6 +519,7 @@ multifundchannel_finished(struct multifundchannel_command *mfc) static struct command_result * after_sendpsbt(struct command *cmd, + const char *method, const char *buf, const jsmntok_t *result, struct multifundchannel_command *mfc) @@ -551,6 +554,7 @@ after_sendpsbt(struct command *cmd, static struct command_result * after_signpsbt(struct command *cmd, + const char *method, const char *buf, const jsmntok_t *result, struct multifundchannel_command *mfc) @@ -737,6 +741,7 @@ fundchannel_complete_done(struct multifundchannel_destination *dest) static struct command_result * fundchannel_complete_ok(struct command *cmd, + const char *method, const char *buf, const jsmntok_t *result, struct multifundchannel_destination *dest) @@ -763,6 +768,7 @@ fundchannel_complete_ok(struct command *cmd, static struct command_result * fundchannel_complete_err(struct command *cmd, + const char *method, const char *buf, const jsmntok_t *error, struct multifundchannel_destination *dest) @@ -1031,6 +1037,7 @@ struct channel_type *json_bits_to_channel_type(const tal_t *ctx, static struct command_result * fundchannel_start_ok(struct command *cmd, + const char *method, const char *buf, const jsmntok_t *result, struct multifundchannel_destination *dest) @@ -1065,6 +1072,7 @@ fundchannel_start_ok(struct command *cmd, static struct command_result * fundchannel_start_err(struct command *cmd, + const char *method, const char *buf, const jsmntok_t *error, struct multifundchannel_destination *dest) @@ -1195,6 +1203,7 @@ perform_fundpsbt(struct multifundchannel_command *mfc, u32 feerate); static struct command_result * retry_fundpsbt_capped_all(struct command *cmd, + const char *method, const char *buf, const jsmntok_t *result, struct multifundchannel_command *mfc) @@ -1206,6 +1215,7 @@ retry_fundpsbt_capped_all(struct command *cmd, static struct command_result * after_fundpsbt(struct command *cmd, + const char *method, const char *buf, const jsmntok_t *result, struct multifundchannel_command *mfc) @@ -1422,6 +1432,7 @@ perform_fundpsbt(struct multifundchannel_command *mfc, u32 feerate) static struct command_result * after_getfeerate(struct command *cmd, + const char *method, const char *buf, const jsmntok_t *result, struct multifundchannel_command *mfc) @@ -1528,6 +1539,7 @@ connect_done(struct multifundchannel_destination *dest) static struct command_result * connect_ok(struct command *cmd, + const char *method, const char *buf, const jsmntok_t *result, struct multifundchannel_destination *dest) @@ -1572,6 +1584,7 @@ connect_ok(struct command *cmd, static struct command_result * connect_err(struct command *cmd, + const char *method, const char *buf, const jsmntok_t *error, struct multifundchannel_destination *dest) diff --git a/plugins/spender/multifundchannel.h b/plugins/spender/multifundchannel.h index 0549a4165f57..966ebd4b3c3e 100644 --- a/plugins/spender/multifundchannel.h +++ b/plugins/spender/multifundchannel.h @@ -240,6 +240,7 @@ struct multifundchannel_command { /* Use this instead of forward_error. */ struct command_result * mfc_forward_error(struct command *cmd, + const char *method, const char *buf, const jsmntok_t *error, struct multifundchannel_command *); diff --git a/plugins/spender/multiwithdraw.c b/plugins/spender/multiwithdraw.c index bf374757328a..c6f448131e46 100644 --- a/plugins/spender/multiwithdraw.c +++ b/plugins/spender/multiwithdraw.c @@ -220,6 +220,7 @@ struct multiwithdraw_cleanup { static struct command_result * mw_after_cleanup(struct command *cmd UNUSED, + const char *method UNUSED, const char *buf UNUSED, const jsmntok_t *result UNUSED, struct multiwithdraw_cleanup *cleanup); @@ -257,6 +258,7 @@ mw_perform_cleanup(struct multiwithdraw_command *mw, } static struct command_result * mw_after_cleanup(struct command *cmd UNUSED, + const char *method UNUSED, const char *buf UNUSED, const jsmntok_t *result UNUSED, struct multiwithdraw_cleanup *cleanup) @@ -273,6 +275,7 @@ mw_after_cleanup(struct command *cmd UNUSED, /* Use this instead of forward_error. */ static struct command_result * mw_forward_error(struct command *cmd UNUSED, + const char *method, const char *buf, const jsmntok_t *error, struct multiwithdraw_command *mw) @@ -318,6 +321,7 @@ specified, from a `utxopsbt` command. static struct command_result * mw_after_fundpsbt(struct command *cmd, + const char *method, const char *buf, const jsmntok_t *result, struct multiwithdraw_command *mw); @@ -393,6 +397,7 @@ mw_load_outputs(struct multiwithdraw_command *mw); static struct command_result * mw_after_fundpsbt(struct command *cmd, + const char *method, const char *buf, const jsmntok_t *result, struct multiwithdraw_command *mw) @@ -484,6 +489,7 @@ we need to `newaddr` and get one. */ static struct command_result * mw_after_newaddr(struct command *cmd, + const char *method, const char *buf, const jsmntok_t *result, struct multiwithdraw_command *mw); @@ -506,6 +512,7 @@ mw_get_change_addr(struct multiwithdraw_command *mw) static struct command_result * mw_after_newaddr(struct command *cmd, + const char *method, const char *buf, const jsmntok_t *result, struct multiwithdraw_command *mw) @@ -612,6 +619,7 @@ Sign and Send PSBT static struct command_result * mw_after_signpsbt(struct command *cmd, + const char *method, const char *buf, const jsmntok_t *result, struct multiwithdraw_command *mw); @@ -635,6 +643,7 @@ mw_sign_and_send(struct multiwithdraw_command *mw) static struct command_result * mw_after_signpsbt(struct command *cmd, + const char *method, const char *buf, const jsmntok_t *result, struct multiwithdraw_command *mw) diff --git a/plugins/spender/openchannel.c b/plugins/spender/openchannel.c index 944679976b1f..90c5cdb28a46 100644 --- a/plugins/spender/openchannel.c +++ b/plugins/spender/openchannel.c @@ -380,6 +380,7 @@ after_openchannel_signed(struct multifundchannel_command *mfc) static struct command_result * openchannel_signed_ok(struct command *cmd, + const char *method, const char *buf, const jsmntok_t *result, struct multifundchannel_destination *dest) @@ -420,6 +421,7 @@ openchannel_signed_ok(struct command *cmd, static struct command_result * openchannel_signed_err(struct command *cmd, + const char *method, const char *buf, const jsmntok_t *error, struct multifundchannel_destination *dest) @@ -670,6 +672,7 @@ openchannel_update_returned(struct multifundchannel_destination *dest) static struct command_result * openchannel_update_ok(struct command *cmd, + const char *method, const char *buf, const jsmntok_t *result, struct multifundchannel_destination *dest) @@ -763,6 +766,7 @@ openchannel_update_ok(struct command *cmd, static struct command_result * openchannel_update_err(struct command *cmd, + const char *method, const char *buf, const jsmntok_t *error, struct multifundchannel_destination *dest) @@ -901,6 +905,7 @@ openchannel_init_done(struct multifundchannel_destination *dest) static struct command_result * openchannel_init_ok(struct command *cmd, + const char *method, const char *buf, const jsmntok_t *result, struct multifundchannel_destination *dest) @@ -950,6 +955,7 @@ openchannel_init_ok(struct command *cmd, static struct command_result * openchannel_init_err(struct command *cmd, + const char *method, const char *buf, const jsmntok_t *error, struct multifundchannel_destination *dest) diff --git a/plugins/sql.c b/plugins/sql.c index 23b290156875..c6ec13f4b6ed 100644 --- a/plugins/sql.c +++ b/plugins/sql.c @@ -706,6 +706,7 @@ static struct command_result *process_json_result(struct command *cmd, } static struct command_result *default_list_done(struct command *cmd, + const char *method, const char *buf, const jsmntok_t *result, struct db_query *dbq) @@ -797,6 +798,7 @@ static struct command_result *channels_refresh(struct command *cmd, struct db_query *dbq); static struct command_result *listchannels_one_done(struct command *cmd, + const char *method, const char *buf, const jsmntok_t *result, struct db_query *dbq) @@ -896,6 +898,7 @@ static struct command_result *nodes_refresh(struct command *cmd, struct db_query *dbq); static struct command_result *listnodes_one_done(struct command *cmd, + const char *method, const char *buf, const jsmntok_t *result, struct db_query *dbq) diff --git a/plugins/test/run-route-calc.c b/plugins/test/run-route-calc.c index f6a68ff64d36..6cef7eeee5ed 100644 --- a/plugins/test/run-route-calc.c +++ b/plugins/test/run-route-calc.c @@ -251,10 +251,12 @@ struct out_req *jsonrpc_request_start_(struct command *cmd UNNEEDED, const char *id_prefix UNNEEDED, const char *filter UNNEEDED, struct command_result *(*cb)(struct command *command UNNEEDED, + const char *methodname UNNEEDED, const char *buf UNNEEDED, const jsmntok_t *result UNNEEDED, void *arg) UNNEEDED, struct command_result *(*errcb)(struct command *command UNNEEDED, + const char *methodname UNNEEDED, const char *buf UNNEEDED, const jsmntok_t *result UNNEEDED, void *arg) UNNEEDED, diff --git a/plugins/test/run-route-overlong.c b/plugins/test/run-route-overlong.c index 3a7e6888e94f..3e7bacfc2622 100644 --- a/plugins/test/run-route-overlong.c +++ b/plugins/test/run-route-overlong.c @@ -248,10 +248,12 @@ struct out_req *jsonrpc_request_start_(struct command *cmd UNNEEDED, const char *id_prefix UNNEEDED, const char *filter UNNEEDED, struct command_result *(*cb)(struct command *command UNNEEDED, + const char *methodname UNNEEDED, const char *buf UNNEEDED, const jsmntok_t *result UNNEEDED, void *arg) UNNEEDED, struct command_result *(*errcb)(struct command *command UNNEEDED, + const char *methodname UNNEEDED, const char *buf UNNEEDED, const jsmntok_t *result UNNEEDED, void *arg) UNNEEDED, diff --git a/plugins/topology.c b/plugins/topology.c index ac05bc05d03c..77d34e48bc45 100644 --- a/plugins/topology.c +++ b/plugins/topology.c @@ -150,6 +150,7 @@ static struct command_result *try_route(struct command *cmd, static struct command_result * listpeerchannels_getroute_done(struct command *cmd, + const char *method, const char *buf, const jsmntok_t *result, struct getroute_info *info) @@ -172,17 +173,6 @@ listpeerchannels_getroute_done(struct command *cmd, return res; } -static struct command_result *listpeerchannels_err(struct command *cmd, - const char *buf, - const jsmntok_t *result, - void *unused) -{ - plugin_err(cmd->plugin, - "Bad listpeerchannels: %.*s", - json_tok_full_len(result), - json_tok_full(buf, result)); -} - static struct command_result *json_getroute(struct command *cmd, const char *buffer, const jsmntok_t *params) @@ -206,7 +196,7 @@ static struct command_result *json_getroute(struct command *cmd, /* Add local info */ req = jsonrpc_request_start(cmd, "listpeerchannels", listpeerchannels_getroute_done, - listpeerchannels_err, info); + plugin_broken_cb, info); return send_outreq(req); } @@ -383,9 +373,10 @@ static void gossmod_add_unknown_localchan(struct gossmap_localmods *mods, } static struct command_result *listpeerchannels_done(struct command *cmd, - const char *buf, - const jsmntok_t *result, - struct listchannels_opts *opts) + const char *method, + const char *buf, + const jsmntok_t *result, + struct listchannels_opts *opts) { struct node_map *connected; struct gossmap_chan *c; @@ -483,7 +474,7 @@ static struct command_result *json_listchannels(struct command *cmd, // If deprecations are not necessary, call listpeerchannels_done directly, // the output will not be used there. - return listpeerchannels_done(cmd, NULL, NULL, opts); + return listpeerchannels_done(cmd, NULL, NULL, NULL, opts); } static void json_add_node(struct json_stream *js, @@ -613,6 +604,7 @@ static struct amount_msat peer_capacity(const struct gossmap *gossmap, static struct command_result * listpeerchannels_listincoming_done(struct command *cmd, + const char *method, const char *buffer, const jsmntok_t *result, void *unused) @@ -698,7 +690,7 @@ static struct command_result *json_listincoming(struct command *cmd, /* Add local info */ req = jsonrpc_request_start(cmd, "listpeerchannels", listpeerchannels_listincoming_done, - listpeerchannels_err, NULL); + plugin_broken_cb, NULL); return send_outreq(req); } diff --git a/plugins/txprepare.c b/plugins/txprepare.c index b1529c59e312..b71b6717716e 100644 --- a/plugins/txprepare.c +++ b/plugins/txprepare.c @@ -128,6 +128,7 @@ static struct command_result *param_outputs(struct command *cmd, /* Called after lightningd has broadcast the transaction. */ static struct command_result *sendpsbt_done(struct command *cmd, + const char *method, const char *buf, const jsmntok_t *result, struct unreleased_tx *utx) @@ -145,6 +146,7 @@ static struct command_result *sendpsbt_done(struct command *cmd, /* Called after lightningd has signed the inputs. */ static struct command_result *signpsbt_done(struct command *cmd, + const char *method, const char *buf, const jsmntok_t *result, struct unreleased_tx *utx) @@ -235,6 +237,7 @@ static struct command_result *finish_txprepare(struct command *cmd, /* fundpsbt/utxopsbt gets a viable PSBT for us. */ static struct command_result *psbt_created(struct command *cmd, + const char *method, const char *buf, const jsmntok_t *result, struct txprepare *txp) @@ -360,6 +363,7 @@ static struct command_result *json_txprepare(struct command *cmd, /* Called after we've unreserved the inputs. */ static struct command_result *unreserve_done(struct command *cmd, + const char *method, const char *buf, const jsmntok_t *result, struct unreleased_tx *utx) @@ -493,6 +497,7 @@ struct listfunds_info { /* Find all the utxos that are p2sh in our wallet */ static struct command_result *listfunds_done(struct command *cmd, + const char *method, const char *buf, const jsmntok_t *result, struct listfunds_info *info) @@ -566,6 +571,7 @@ static struct command_result *listfunds_done(struct command *cmd, /* We've got an address for sending funds */ static struct command_result *newaddr_sweep_done(struct command *cmd, + const char *method, const char *buf, const jsmntok_t *result, struct listfunds_info *info) diff --git a/tests/plugins/test_libplugin.c b/tests/plugins/test_libplugin.c index 4116eef9b663..d6f269610229 100644 --- a/tests/plugins/test_libplugin.c +++ b/tests/plugins/test_libplugin.c @@ -123,6 +123,7 @@ static struct command_result *json_all_notifs(struct command *cmd, } static struct command_result *testrpc_cb(struct command *cmd, + const char *method UNUSED, const char *buf, const jsmntok_t *params, void *cb_arg UNUSED) @@ -153,6 +154,7 @@ static struct command_result *json_testrpc(struct command *cmd, } static struct command_result *listdatastore_ok(struct command *cmd, + const char *method, const char *buf, const jsmntok_t *params, void *cb_arg UNUSED) @@ -160,7 +162,7 @@ static struct command_result *listdatastore_ok(struct command *cmd, if (command_check_only(cmd)) return command_check_done(cmd); - return forward_result(cmd, buf, params, NULL); + return forward_result(cmd, method, buf, params, NULL); } /* A command which does async, even if it is a check */ From 59c864d8328c3f7b1042051b9e49da3ac6596e9d Mon Sep 17 00:00:00 2001 From: Rusty Russell Date: Thu, 7 Nov 2024 11:57:37 +1030 Subject: [PATCH 17/18] libplugin: call get_beglist async, in case they subscribe to the rpc_command hook. Signed-off-by: Rusty Russell Changelog-Fixed: libplugin: plugins can now intercept `rpc_command` hook without deadlocking. --- plugins/libplugin.c | 35 ++++++++++++++++++++++++++++++----- 1 file changed, 30 insertions(+), 5 deletions(-) diff --git a/plugins/libplugin.c b/plugins/libplugin.c index 384850033615..e64c9b99b282 100644 --- a/plugins/libplugin.c +++ b/plugins/libplugin.c @@ -1486,6 +1486,27 @@ static const char **json_to_apilist(const tal_t *ctx, const char *buffer, const return ret; } +static struct command_result *get_beglist(struct command *aux_cmd, + const char *method, + const char *buf, + const jsmntok_t *result, + void *unused) +{ + struct plugin *plugin = aux_cmd->plugin; + const char *err; + + err = json_scan(tmpctx, buf, result, + "{configs:{i-promise-to-fix-broken-api-user?:%}}", + JSON_SCAN_TAL(plugin, json_to_apilist, &plugin->beglist)); + if (err) + plugin_err(aux_cmd->plugin, "bad listconfigs '%.*s': %s", + json_tok_full_len(result), + json_tok_full(buf, result), + err); + + return aux_command_done(aux_cmd); +} + static struct command_result *handle_init(struct command *cmd, const char *buf, const jsmntok_t *params) @@ -1568,12 +1589,15 @@ static struct command_result *handle_init(struct command *cmd, } if (with_rpc) { - p->beglist = NULL; - rpc_scan(cmd, "listconfigs", - take(json_out_obj(NULL, "config", "i-promise-to-fix-broken-api-user")), - "{configs:{i-promise-to-fix-broken-api-user?:%}}", - JSON_SCAN_TAL(p, json_to_apilist, &p->beglist)); + struct out_req *req; + struct command *aux_cmd = aux_command(cmd); + io_new_conn(p, p->rpc_conn->fd, rpc_conn_init, p); + /* In case they intercept rpc_command, we can't do this sync. */ + req = jsonrpc_request_start(aux_cmd, "listconfigs", + get_beglist, plugin_broken_cb, NULL); + json_add_string(req->js, "config", "i-promise-to-fix-broken-api-user"); + send_outreq(req); } return command_success(cmd, json_out_obj(cmd, NULL, NULL)); @@ -2343,6 +2367,7 @@ static struct plugin *new_plugin(const tal_t *ctx, p->rpc_toks = toks_alloc(p); p->next_outreq_id = 0; strmap_init(&p->out_reqs); + p->beglist = NULL; p->desired_features = tal_steal(p, features); if (init_rpc) { From 0b5f37d69b19abbfea41b35368b084367fbc5387 Mon Sep 17 00:00:00 2001 From: Rusty Russell Date: Thu, 7 Nov 2024 11:57:37 +1030 Subject: [PATCH 18/18] lightningd: avoid false memleak positive with rpc_command_hook. On `dev-memleak`, if someone is using rpc_command_hook, we'll call it when the hook returns. But it will see these contexts as a leak. So attach them to tmpctx (which is excluded from leak detection). Signed-off-by: Rusty Russell --- lightningd/plugin.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/lightningd/plugin.c b/lightningd/plugin.c index 3e5f6f291187..9dcb312484b1 100644 --- a/lightningd/plugin.c +++ b/lightningd/plugin.c @@ -615,7 +615,7 @@ static void mark_plugin_destroyed(const struct plugin *unused, static struct plugin_destroyed * plugin_detect_destruction(const struct plugin *plugin) { - struct plugin_destroyed *pd = tal(NULL, struct plugin_destroyed); + struct plugin_destroyed *pd = notleak(tal(NULL, struct plugin_destroyed)); pd->plugin = plugin; tal_add_destructor2(plugin, mark_plugin_destroyed, pd); return pd; @@ -655,7 +655,7 @@ static void plugin_response_handle(struct plugin *plugin, /* Request callback often frees request: if not, we do. */ - ctx = tal(NULL, char); + ctx = tal(tmpctx, char); tal_steal(ctx, request); /* Don't keep track of this request; we will terminate it */ tal_del_destructor2(request, destroy_request, plugin);