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); 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/askrene/askrene.c b/plugins/askrene/askrene.c index 8bb8dc97a18e..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) @@ -759,11 +760,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 +1153,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 +1167,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 f1e2e5198170..197d659667da 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, @@ -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)), @@ -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); } } @@ -304,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) @@ -313,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) @@ -476,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) @@ -508,10 +512,10 @@ 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(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; @@ -519,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) @@ -554,7 +559,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(cinfo->cmd, tal_fmt(tmpctx, "list%s", ops->system_name), @@ -566,16 +571,17 @@ 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++; } if (cinfo->cleanup_reqs_remaining) - return command_still_pending(NULL); + return command_still_pending(cinfo->cmd); return clean_finished(cinfo); } static struct command_result *wait_done(struct command *cmd, + const char *method, const char *buf, const jsmntok_t *result, struct per_subsystem *ps) @@ -598,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; @@ -627,13 +622,13 @@ static struct command_result *start_clean(struct clean_info *cinfo) } ps->offset = 0; - req = jsonrpc_request_start(plugin, NULL, + 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); - send_outreq(plugin, req); + send_outreq(req); cinfo->cleanup_reqs_remaining++; } @@ -641,11 +636,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, @@ -740,29 +736,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 = plugin_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; } @@ -777,7 +773,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 b169a74df754..5dc2de968643 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) @@ -1006,17 +1007,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" @@ -1098,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")) @@ -1109,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 78af58c6e4f4..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) { @@ -123,11 +125,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, @@ -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) @@ -891,7 +895,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 +911,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, @@ -1122,13 +1126,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"); @@ -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; @@ -1288,20 +1298,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 { @@ -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; @@ -1327,7 +1340,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 +1359,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 +1373,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))) { @@ -1564,19 +1577,19 @@ 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 */ 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) { @@ -1977,8 +1990,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..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) @@ -261,9 +262,9 @@ 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); + forward_error, NULL); json_array_start(req->js, "scb"); for (size_t i=0; ijs); - return send_outreq(cmd->plugin, req); + return send_outreq(req); } static void update_scb(struct plugin *p, struct scb_chan **channels) @@ -319,6 +320,7 @@ static void update_scb(struct plugin *p, struct scb_chan **channels) static struct command_result *peer_after_send_their_peer_strg(struct command *cmd, + const char *method, const char *buf, const jsmntok_t *params, void *cb_arg UNUSED) @@ -329,6 +331,7 @@ static struct command_result static struct command_result *peer_after_send_their_peer_strg_err(struct command *cmd, + const char *method, const char *buf, const jsmntok_t *params, void *cb_arg UNUSED) @@ -353,8 +356,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,18 +366,18 @@ 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, + const char *method, const char *buf, const jsmntok_t *params, struct node_id *nodeid) { 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, @@ -385,6 +387,7 @@ static struct command_result *peer_after_send_scb(struct command *cmd, } static struct command_result *peer_after_send_scb_failed(struct command *cmd, + const char *method, const char *buf, const jsmntok_t *params, struct node_id *nodeid) @@ -399,6 +402,7 @@ struct info { }; static struct command_result *after_send_scb_single(struct command *cmd, + const char *method, const char *buf, const jsmntok_t *params, struct info *info) @@ -411,6 +415,7 @@ static struct command_result *after_send_scb_single(struct command *cmd, } static struct command_result *after_send_scb_single_fail(struct command *cmd, + const char *method, const char *buf, const jsmntok_t *params, struct info *info) @@ -423,6 +428,7 @@ static struct command_result *after_send_scb_single_fail(struct command *cmd, } static struct command_result *after_listpeers(struct command *cmd, + const char *method, const char *buf, const jsmntok_t *params, void *cb_arg UNUSED) @@ -464,8 +470,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 +480,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); } } @@ -485,6 +490,7 @@ static struct command_result *after_listpeers(struct command *cmd, } static struct command_result *after_staticbackup(struct command *cmd, + const char *method, const char *buf, const jsmntok_t *params, void *cb_arg UNUSED) @@ -498,13 +504,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 +525,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 +573,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 +583,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, @@ -594,6 +597,7 @@ static struct command_result *failed_peer_restore(struct command *cmd, } static struct command_result *datastore_success(struct command *cmd, + const char *method, const char *buf, const jsmntok_t *result, char *what) @@ -603,6 +607,7 @@ static struct command_result *datastore_success(struct command *cmd, } static struct command_result *datastore_failed(struct command *cmd, + const char *method, const char *buf, const jsmntok_t *result, char *what) @@ -635,8 +640,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 +685,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 +730,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 +742,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 +753,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 +776,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 +786,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 aede4c35b634..1c1eea5cb27d 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,8 @@ 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 *method UNUSED, const char *buf UNUSED, const jsmntok_t *result, struct reply *reply) @@ -133,7 +135,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,18 +146,19 @@ 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(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_done(); + return command_still_pending(cmd); } static struct command_result *cmd_done(struct command *command, + const char *method, const char *buf, const jsmntok_t *obj, struct commando *incoming) @@ -189,17 +192,19 @@ static struct command_result *cmd_done(struct command *command, } reply->off = 0; - return send_response(command, NULL, NULL, reply); + return send_response(command, NULL, 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 +218,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, NULL, reply); } struct cond_info { @@ -259,9 +264,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), @@ -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(cmd, json_strdup(tmpctx, cinfo->buf, cinfo->method), cinfo->cmdid_prefix, cmd_done, cinfo->incoming); @@ -314,10 +318,11 @@ static struct command_result *execute_command(struct cond_info *cinfo) 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, + const char *method, const char *buf, const jsmntok_t *result, struct cond_info *cinfo) @@ -336,15 +341,16 @@ 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, + const char *method, const char *buf, const jsmntok_t *result, struct cond_info *cinfo) @@ -357,13 +363,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 +380,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 +422,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(cmd, "checkrune", checkrune_done, checkrune_failed, cinfo); json_add_node_id(req->js, "nodeid", &incoming->peer); @@ -428,14 +430,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(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 +464,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 +594,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, @@ -620,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) @@ -631,12 +633,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, @@ -706,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, @@ -729,11 +732,10 @@ 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, - 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(plugin, req); + return send_outreq(req); } static struct command_result *json_commando_rune(struct command *cmd, @@ -788,13 +790,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..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) @@ -53,10 +55,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, @@ -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) @@ -231,9 +234,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 8e49de23ef33..93fc23bab202 100644 --- a/plugins/fetchinvoice.c +++ b/plugins/fetchinvoice.c @@ -397,21 +397,24 @@ 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, + const char *method UNUSED, const char *buf UNUSED, 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); } @@ -491,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); @@ -603,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)) @@ -618,7 +623,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,20 +636,23 @@ 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, + const char *method UNUSED, const char *buf UNUSED, 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)); - return sendonionmsg_done(cmd, buf, result, sent); + command_timer(cmd, + time_from_sec(sent->wait_timeout), + timeout_sent_inv, 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) @@ -1041,7 +1050,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); @@ -1051,7 +1060,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 @@ -1090,18 +1099,19 @@ 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); } static struct command_result *createinvoice_done(struct command *cmd, + const char *method, const char *buf, const jsmntok_t *result, struct sent *sent) @@ -1153,14 +1163,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 fc9a5a4f62f5..285c2a13c8c0 100644 --- a/plugins/funder.c +++ b/plugins/funder.c @@ -73,7 +73,8 @@ 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 *method, const char *buf, const jsmntok_t *result, struct pending_open *open) @@ -84,39 +85,45 @@ 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(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! */ 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); } } } @@ -134,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) @@ -144,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) @@ -159,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); @@ -174,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) @@ -209,7 +220,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, @@ -231,11 +242,12 @@ 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 * signpsbt_done(struct command *cmd, + const char *method, const char *buf, const jsmntok_t *result, struct pending_open *open) @@ -313,7 +325,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, @@ -336,7 +348,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 * @@ -411,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) @@ -456,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) @@ -463,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), @@ -528,7 +543,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, @@ -561,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) @@ -717,7 +733,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, @@ -739,11 +755,12 @@ 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 * listfunds_failed(struct command *cmd, + const char *method, const char *buf, const jsmntok_t *error, struct open_info *info) @@ -886,17 +903,18 @@ 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 * datastore_list_fail(struct command *cmd, + const char *method, const char *buf, const jsmntok_t *error, struct open_info *info) @@ -911,16 +929,17 @@ 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 * datastore_list_success(struct command *cmd, + const char *method, const char *buf, const jsmntok_t *result, struct open_info *info) @@ -980,12 +999,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 */ @@ -1055,7 +1074,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, @@ -1064,7 +1083,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, @@ -1088,7 +1107,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); } @@ -1103,7 +1122,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, @@ -1111,7 +1130,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, @@ -1176,7 +1195,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); @@ -1311,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) { @@ -1411,7 +1432,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, @@ -1426,7 +1447,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[] = { @@ -1436,7 +1457,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; @@ -1464,7 +1485,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)); @@ -1477,7 +1498,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; @@ -1486,19 +1507,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 16d9baa8d50c..b92f22c73731 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; @@ -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:%}," @@ -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) @@ -311,19 +312,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[] = { @@ -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) { @@ -571,7 +576,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 +597,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 14a250926c16..ed78d76815d2 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; @@ -171,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; @@ -203,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; @@ -219,21 +210,20 @@ 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. */ static struct command_result *payment_rpc_failure(struct command *cmd, + const char *method, const char *buffer, 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: %.*s", + method, toks->end - toks->start, buffer + toks->start); } struct payment_tree_result payment_collect_result(struct payment *p) @@ -290,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) @@ -306,12 +297,12 @@ 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 * payment_getblockheight_success(struct command *cmd, + const char *method, const char *buffer, const jsmntok_t *toks, struct payment *p) @@ -330,19 +321,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(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(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 +367,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(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(req); } void payment_start(struct payment *p) @@ -864,22 +853,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 +871,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 +879,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 +888,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 +912,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); } /** @@ -980,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 @@ -1018,12 +998,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 +1013,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,10 +1027,10 @@ 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(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, @@ -1393,9 +1372,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 +1471,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: @@ -1596,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; @@ -1609,8 +1587,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) @@ -1623,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; @@ -1650,16 +1631,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,35 +1651,34 @@ 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(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(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(p->plugin, NULL, "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); - send_outreq(p->plugin, req); - - return command_still_pending(cmd); + return send_outreq(req); } static struct command_result *payment_createonion_success(struct command *cmd, + const char *method, const char *buffer, const jsmntok_t *toks, struct payment *p) @@ -1719,7 +1697,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(payment_cmd(p), "sendonion", payment_sendonion_success, payment_rpc_failure, p); json_add_hex_talarr(req->js, "onion", p->createonion_response->onion); @@ -1762,8 +1740,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(req); } /* Temporary serialization method for the tlv_payload.data until we rework the @@ -1857,7 +1834,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 +1920,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(payment_cmd(p), "createonion", payment_createonion_success, payment_rpc_failure, p); @@ -1979,11 +1956,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(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 +2010,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 +2121,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; @@ -2156,134 +2133,121 @@ 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"); - } + if (p->parent != NULL) + return payment_child_finished(p->parent, p); - json_add_amount_msat(ret, "amount_msat", p->our_amount); - json_add_amount_msat(ret, "amount_sent_msat", - result.sent); + if (p->finished) { + /* cmd is the aux_command: real cmd has been freed. */ + return command_still_pending(p->cmd); + } - if (failure != NULL) { - if (failure->erring_index) - json_add_num(ret, "erring_index", - *failure->erring_index); + /* 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); + + /* 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->erring_node) - json_add_node_id(ret, "erring_node", - failure->erring_node); + } else { + json_add_string(ret, "status", "failed"); + } - if (failure->erring_channel) - json_add_short_channel_id( - ret, "erring_channel", - *failure->erring_channel); + json_add_amount_msat(ret, "amount_msat", p->our_amount); + json_add_amount_msat(ret, "amount_sent_msat", + result.sent); - if (failure->erring_direction) - json_add_num( - ret, "erring_direction", - *failure->erring_direction); - } + if (failure != NULL) { + if (failure->erring_index) + json_add_num(ret, "erring_index", + *failure->erring_index); - payment_notify_failure(p, failure->message); + if (failure->erring_node) + json_add_node_id(ret, "erring_node", + failure->erring_node); - if (command_finished(cmd, ret)) { /* Ignore result. */} - p->cmd = NULL; - return; + if (failure->erring_channel) + json_add_short_channel_id( + ret, "erring_channel", + *failure->erring_channel); + + 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); } + + /* 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) @@ -2296,7 +2260,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; @@ -2316,27 +2280,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 @@ -2344,7 +2304,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); @@ -2369,10 +2329,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(); @@ -2385,7 +2345,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, @@ -2403,8 +2363,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) @@ -2477,8 +2437,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); @@ -2528,14 +2488,16 @@ 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, 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; @@ -2603,11 +2565,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 @@ -2618,10 +2579,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(payment_cmd(p), "listpeerchannels", local_channel_hints_listpeerchannels, local_channel_hints_listpeerchannels, p); - send_outreq(p->plugin, req); + return send_outreq(req); } REGISTER_PAYMENT_MODIFIER(local_channel_hints, void *, NULL, local_channel_hints_cb); @@ -2925,7 +2886,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); @@ -2979,14 +2940,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); @@ -2999,10 +2959,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); @@ -3092,7 +3052,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) @@ -3174,7 +3134,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); @@ -3232,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); @@ -3240,17 +3201,18 @@ 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(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, - 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; @@ -3381,14 +3343,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) @@ -3407,15 +3368,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; @@ -3449,14 +3410,14 @@ 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 * 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) @@ -3497,12 +3458,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; @@ -3510,14 +3470,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(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(req); } static struct direct_pay_data *direct_pay_init(struct payment *p) @@ -3613,7 +3571,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 = @@ -3722,7 +3680,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 *, @@ -3763,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) @@ -3802,11 +3761,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. @@ -3817,11 +3775,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(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(req); } REGISTER_PAYMENT_MODIFIER(payee_incoming_limit, void *, NULL, @@ -3840,7 +3798,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) @@ -3858,17 +3816,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/libplugin.c b/plugins/libplugin.c index af1c5a70b7c0..e64c9b99b282 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; }; @@ -119,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; @@ -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; @@ -164,42 +164,26 @@ 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; } -static void complain_deprecated_nocmd(const char *feature, - bool allowing, - struct plugin *plugin) +/* 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, + enum command_type type) { - 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); - } -} + struct command *cmd = tal(ctx, struct command); -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); + cmd->plugin = plugin; + cmd->type = type; + cmd->filter = NULL; + cmd->methodname = tal_strdup(cmd, methodname); + cmd->id = tal_strdup(cmd, id); + return cmd; } static void complain_deprecated(const char *feature, @@ -274,11 +258,68 @@ 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) { - return command_done(); + 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) @@ -289,32 +330,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) { - if (!cmd) - return ""; - - /* Notifications have no cmd->id, use methodname */ - if (!cmd->id) - return tal_fmt(ctx, "%s/", cmd->methodname); + 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) @@ -325,15 +360,17 @@ 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, 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), @@ -341,18 +378,19 @@ 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->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; 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! */ - 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); @@ -397,6 +435,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) @@ -410,6 +450,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); @@ -443,6 +485,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); @@ -460,8 +506,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; } @@ -548,6 +593,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); @@ -559,6 +606,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); @@ -574,18 +623,21 @@ 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)); } -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; } struct command_result *forward_error(struct command *cmd, + const char *method, const char *buf, const jsmntok_t *error, void *arg UNNEEDED) @@ -596,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) @@ -621,7 +674,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) @@ -631,7 +684,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, @@ -649,11 +702,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) @@ -712,7 +767,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"); @@ -733,12 +788,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' */ @@ -757,7 +814,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, @@ -766,12 +823,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); } @@ -786,7 +844,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) @@ -794,6 +852,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); @@ -801,12 +860,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, ...) { @@ -814,14 +873,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, ...) { @@ -829,7 +888,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; } @@ -849,27 +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 plugin *plugin, - struct command *cmd, +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), @@ -880,9 +930,9 @@ struct command_result *jsonrpc_set_datastore_(struct plugin *plugin, if (!cb) cb = ignore_cb; if (!errcb) - errcb = datastore_fail; + errcb = plugin_broken_cb; - 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) @@ -890,7 +940,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 { @@ -904,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) @@ -942,8 +993,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, @@ -961,12 +1011,17 @@ 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", - listdatastore_done, datastore_fail, dsi); + req = jsonrpc_request_start(cmd, "listdatastore", + listdatastore_done, plugin_broken_cb, 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) +{ + *cmd_freed = true; } static void handle_rpc_reply(struct plugin *plugin, const jsmntok_t *toks) @@ -974,6 +1029,7 @@ 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"); @@ -993,18 +1049,21 @@ 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); + /* 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) - 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) @@ -1013,16 +1072,23 @@ 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); } - 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 * -send_outreq(struct plugin *plugin, const struct out_req *req) +send_outreq(const struct out_req *req) { /* The "param" object. */ if (req->errcb) @@ -1030,10 +1096,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; } @@ -1041,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 *); @@ -1055,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 *), @@ -1094,24 +1162,26 @@ 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) - return command_done(); + 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) - return command_done(); + if (batch->errcb && batch->errcb(cmd, method, buf, result, batch->arg) == &complete) + return &complete; return batch_one_complete(cmd, batch); } @@ -1121,7 +1191,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); @@ -1416,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) @@ -1491,19 +1582,22 @@ 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)); } if (with_rpc) { - p->beglist = NULL; - rpc_scan(p, "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)); @@ -1630,11 +1724,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", + COMMAND_TYPE_USAGE_ONLY); /* 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; @@ -1648,11 +1742,24 @@ 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); - - p->in_timer++; - /* Free this if they don't. */ - tal_steal(tmpctx, t); - t->cb(t->cb_arg); + 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); + 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) @@ -1660,11 +1767,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); @@ -1673,6 +1784,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) { @@ -1706,6 +1835,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) { @@ -1881,7 +2011,10 @@ static void ld_command_handle(struct plugin *plugin, const jsmntok_t *toks) { const jsmntok_t *methtok, *paramstok, *filtertok; + 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"); @@ -1893,12 +2026,20 @@ 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); + 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), + type); if (!plugin->manifested) { if (streq(cmd->methodname, "getmanifest")) { @@ -1921,7 +2062,7 @@ static void ld_command_handle(struct plugin *plugin, } /* If that's a notification. */ - if (!cmd->id) { + if (cmd->type == COMMAND_TYPE_NOTIFICATION) { bool is_shutdown = streq(cmd->methodname, "shutdown"); if (is_shutdown && plugin->developer) memleak_check(plugin, cmd); @@ -1961,6 +2102,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); @@ -1976,8 +2118,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; @@ -2184,7 +2325,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, @@ -2226,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) { @@ -2239,7 +2381,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)) @@ -2279,7 +2420,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, @@ -2503,13 +2644,29 @@ 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) +{ + return new_command(cmd->plugin, cmd->plugin, cmd->id, + 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; +} + 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 b44899bbd7ac..b7c2fc44e7b8 100644 --- a/plugins/libplugin.h +++ b/plugins/libplugin.h @@ -34,26 +34,45 @@ 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); 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, + /* Terminate with timer_complete */ + COMMAND_TYPE_TIMER, + /* These self-terminate */ + 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; @@ -95,61 +114,85 @@ 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 plugin *plugin, - struct command *cmd, +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), - void *arg); + void *arg) + NON_NULL_ARGS(1, 2, 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), \ - 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, \ + 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)) -#define jsonrpc_request_with_filter_start(plugin, cmd, method, filter, cb, errcb, arg) \ - jsonrpc_request_start_((plugin), (cmd), (method), \ - json_id_prefix(tmpctx, (cmd)), (filter), \ +#define jsonrpc_request_with_filter_start(cmd, method, filter, cb, errcb, arg) \ + jsonrpc_request_start_((cmd), (method), NULL, (filter), \ 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)) /* 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, \ + const char *mthod, \ const char *buf, \ const jsmntok_t *result), \ NULL, \ @@ -158,10 +201,12 @@ struct out_req *jsonrpc_request_start_(struct plugin *plugin, /* 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 *), @@ -174,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 *, \ @@ -188,69 +235,86 @@ 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) + 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. */ -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, 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), - void *arg); + void *arg) + 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, \ + 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)) -#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, \ + 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)) @@ -258,8 +322,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, @@ -267,10 +330,11 @@ 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); -#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), \ @@ -279,8 +343,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 *, \ @@ -293,11 +357,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. */ @@ -315,14 +381,8 @@ 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 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); @@ -336,24 +396,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) + NON_NULL_ARGS(1); /** * What's the deprecation_ok state for this cmd? @@ -361,14 +431,15 @@ notification_handled(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) /* 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, @@ -379,12 +450,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, ...); @@ -392,45 +463,60 @@ 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, + const char *method, const char *buf, const jsmntok_t *error, - void *arg); + void *arg) + 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); + void *arg) + 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 * send_req() path. */ -struct command_result *timer_complete(struct plugin *p); - -/* Signals that we've completed a command. Useful for when - * there's no `cmd` present */ -struct command_result *command_done(void); +struct command_result *timer_complete(struct command *cmd) + NON_NULL_ARGS(1); -/* 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); @@ -545,7 +631,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, @@ -596,16 +682,14 @@ 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)); /* 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..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), @@ -104,7 +108,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 +119,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 */ @@ -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) @@ -326,9 +331,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[] = { @@ -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) @@ -1377,30 +1383,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 +1414,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.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 42f9295ca787..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) @@ -190,14 +193,15 @@ 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, + const char *method, const char *buf, const jsmntok_t *err, struct inv *inv) @@ -359,9 +363,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..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, @@ -223,7 +226,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 +234,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: @@ -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) @@ -545,7 +549,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 +558,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: @@ -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) @@ -750,16 +755,17 @@ 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, + const char *method, const char *buf, const jsmntok_t *result, struct invreq *ir) @@ -1063,8 +1069,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..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, @@ -265,7 +266,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 +275,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, @@ -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); } @@ -567,14 +569,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 +589,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 +597,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 98dcd1df1424..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) @@ -552,7 +553,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 +564,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 +572,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 +587,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; } @@ -625,11 +626,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 +715,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. */ @@ -806,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) @@ -833,7 +837,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" */ @@ -853,7 +857,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 / @@ -862,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; @@ -1031,12 +1038,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, @@ -1056,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) @@ -1104,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) @@ -1174,10 +1183,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", @@ -1187,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) @@ -1200,13 +1210,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); @@ -1463,17 +1473,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 b46d55dc74ea..6ceee127a4eb 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 */ @@ -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,16 +80,18 @@ 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"); 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) @@ -94,21 +99,20 @@ 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 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; @@ -128,8 +132,7 @@ static void do_check_gossip (struct command *cmd) 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,19 +142,20 @@ static void do_check_gossip (struct command *cmd) plugin_log(plugin, LOG_DBG, "Connecting to: %s", fmt_node_id(tmpctx, &peer_id)); - send_outreq(plugin, req); + send_outreq(req); } 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) @@ -159,35 +163,34 @@ 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); - find_exes_timer = plugin_timer( + send_outreq(req_emer_recovery); + find_exes_timer = global_timer( plugin, time_from_sec(CHECK_GOSSIP_INTERVAL), do_check_gossip, cmd); return; } static struct command_result *after_listpeerchannels(struct command *cmd, + const char *method, const char *buf, const jsmntok_t *params, void *cb_arg UNUSED) @@ -216,48 +219,48 @@ 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(cmd, "listpeerchannels", + after_listpeerchannels, + &forward_error, NULL); - return send_outreq(plugin, req); + return send_outreq(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, +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 = 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; /* 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), @@ -268,15 +271,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/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) 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 3d410cbce0d5..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) @@ -216,13 +218,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); @@ -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) @@ -312,11 +316,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); @@ -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) @@ -452,9 +457,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); @@ -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) @@ -622,10 +628,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); @@ -771,21 +777,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); } @@ -864,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) @@ -876,10 +886,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); @@ -909,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) @@ -1065,12 +1076,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..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) @@ -152,10 +154,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..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) @@ -329,7 +331,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 +339,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..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); @@ -75,7 +76,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 +112,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) @@ -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/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 4a06ad177ab5..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) @@ -168,8 +169,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 +188,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 +206,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 +223,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. */ @@ -398,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) { @@ -520,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) @@ -554,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) @@ -647,7 +648,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 +657,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 +670,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 +685,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); } /*~ @@ -740,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) @@ -766,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) @@ -795,8 +798,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 +806,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 * @@ -1035,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) @@ -1069,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) @@ -1108,8 +1112,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 +1147,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 * @@ -1200,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) @@ -1211,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) @@ -1325,8 +1330,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 +1343,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,11 +1427,12 @@ 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 * after_getfeerate(struct command *cmd, + const char *method, const char *buf, const jsmntok_t *result, struct multifundchannel_command *mfc) @@ -1460,8 +1464,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 +1474,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); } /*---------------------------------------------------------------------------*/ @@ -1536,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) @@ -1580,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) @@ -1610,7 +1615,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 +1627,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); } /*----------------------------------------------------------------------------- @@ -1649,10 +1654,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 +1785,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 +2018,7 @@ json_multifundchannel(struct command *cmd, mfc->sigs_collected = false; - perform_multifundchannel(mfc); + perform_multiconnect(mfc); return command_still_pending(mfc->cmd); } 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 04d35383f43d..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); @@ -248,16 +249,16 @@ 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, + const char *method UNUSED, const char *buf UNUSED, const jsmntok_t *result UNUSED, struct multiwithdraw_cleanup *cleanup) @@ -274,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) @@ -319,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); @@ -344,8 +347,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 +358,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 +380,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); } /*----------------------------------------------------------------------------- @@ -396,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) @@ -487,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); @@ -500,15 +503,16 @@ 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 * mw_after_newaddr(struct command *cmd, + const char *method, const char *buf, const jsmntok_t *result, struct multiwithdraw_command *mw) @@ -615,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); @@ -627,17 +632,18 @@ 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 * mw_after_signpsbt(struct command *cmd, + const char *method, const char *buf, const jsmntok_t *result, struct multiwithdraw_command *mw) @@ -668,8 +674,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 +688,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..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) @@ -444,8 +446,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 +454,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 * @@ -671,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) @@ -764,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) @@ -786,8 +789,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 +797,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 * @@ -903,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) @@ -952,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) @@ -972,7 +976,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 +1030,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..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) @@ -735,10 +736,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, @@ -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) @@ -870,12 +872,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)) { @@ -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) @@ -1007,12 +1010,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 +1540,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 8e4eda56a9b1..6cef7eeee5ed 100644 --- a/plugins/test/run-route-calc.c +++ b/plugins/test/run-route-calc.c @@ -12,6 +12,10 @@ #include /* AUTOGENERATED MOCKS START */ +/* Generated stub for aux_command */ +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, struct amount_msat final_amount UNNEEDED, @@ -20,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) @@ -155,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(); } @@ -243,28 +246,32 @@ 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, 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, - 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, @@ -299,8 +306,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 308361c7c4c7..3e7bacfc2622 100644 --- a/plugins/test/run-route-overlong.c +++ b/plugins/test/run-route-overlong.c @@ -9,6 +9,10 @@ #include /* AUTOGENERATED MOCKS START */ +/* Generated stub for aux_command */ +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, struct amount_msat final_amount UNNEEDED, @@ -17,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) @@ -152,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(); } @@ -240,28 +243,32 @@ 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, 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, - 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, @@ -296,8 +303,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..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) @@ -204,10 +194,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); + plugin_broken_cb, info); + return send_outreq(req); } HTABLE_DEFINE_TYPE(struct node_id, node_id_keyof, node_id_hash, node_id_eq, @@ -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; @@ -476,14 +467,14 @@ 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, // 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) @@ -696,11 +688,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); + plugin_broken_cb, NULL); + return send_outreq(req); } static void memleak_mark(struct plugin *p, struct htable *memtable) @@ -708,13 +699,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 +720,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..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) @@ -168,11 +170,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 +220,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); @@ -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) @@ -308,7 +311,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 +321,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 +337,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, @@ -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) @@ -413,11 +417,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 +441,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, @@ -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) @@ -597,12 +603,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 +627,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 +664,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..d6f269610229 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"); @@ -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) @@ -147,12 +148,13 @@ 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, + 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 */ @@ -178,13 +180,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 +207,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 +225,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)