diff --git a/plugins/autoclean.c b/plugins/autoclean.c index 414b59400..27a99c6b3 100644 --- a/plugins/autoclean.c +++ b/plugins/autoclean.c @@ -72,11 +72,11 @@ static void init(struct plugin *p, rpc = &p->rpc_conn; if (cycle_seconds) { - plugin_log(LOG_INFORM, "autocleaning every %"PRIu64" seconds", cycle_seconds); + plugin_log(p, LOG_INFORM, "autocleaning every %"PRIu64" seconds", cycle_seconds); cleantimer = plugin_timer(p, time_from_sec(cycle_seconds), do_clean); } else - plugin_log(LOG_DBG, "autocleaning not active"); + plugin_log(p, LOG_DBG, "autocleaning not active"); } static const struct plugin_command commands[] = { { diff --git a/plugins/fundchannel.c b/plugins/fundchannel.c index 5b83ad453..1f63f9d4c 100644 --- a/plugins/fundchannel.c +++ b/plugins/fundchannel.c @@ -143,7 +143,7 @@ static struct command_result *send_tx(struct command *cmd, tok = json_get_member(buf, result, "commitments_secured"); if (!json_to_bool(buf, tok, &commitments_secured) || !commitments_secured) /* TODO: better failure path? this should never fail though. */ - plugin_err("Commitment not secured."); + plugin_err(cmd->plugin, "Commitment not secured."); /* Stash the channel_id so we can return it when finalized */ tok = json_get_member(buf, result, "channel_id"); @@ -175,16 +175,16 @@ static struct command_result *tx_prepare_done(struct command *cmd, txid_tok = json_get_member(buf, result, "txid"); if (!txid_tok) - plugin_err("txprepare missing 'txid' field"); + plugin_err(cmd->plugin, "txprepare missing 'txid' field"); tx_tok = json_get_member(buf, result, "unsigned_tx"); if (!tx_tok) - plugin_err("txprepare missing 'unsigned_tx' field"); + plugin_err(cmd->plugin, "txprepare missing 'unsigned_tx' field"); hex = json_strdup(tmpctx, buf, tx_tok); tx = bitcoin_tx_from_hex(fr, hex, strlen(hex)); if (!tx) - plugin_err("Unable to parse tx %s", hex); + plugin_err(cmd->plugin, "Unable to parse tx %s", hex); /* Find the txout */ outnum_found = false; @@ -197,14 +197,14 @@ static struct command_result *tx_prepare_done(struct command *cmd, } } if (!outnum_found) - plugin_err("txprepare doesn't include our funding output. " + plugin_err(cmd->plugin, "txprepare doesn't include our funding output. " "tx: %s, output: %s", type_to_string(tmpctx, struct bitcoin_tx, tx), tal_hex(tmpctx, fr->out_script)); hex = json_strdup(tmpctx, buf, txid_tok); if (!bitcoin_txid_from_hex(hex, strlen(hex), &fr->tx_id)) - plugin_err("Unable to parse txid %s", hex); + plugin_err(cmd->plugin, "Unable to parse txid %s", hex); ret = json_out_new(NULL); json_out_start(ret, NULL, '{'); @@ -350,7 +350,7 @@ static struct command_result *post_dryrun(struct command *cmd, /* Stash the 'reserved' txid to unreserve later */ hex = json_strdup(tmpctx, buf, json_get_member(buf, result, "txid")); if (!bitcoin_txid_from_hex(hex, strlen(hex), &fr->tx_id)) - plugin_err("Unable to parse reserved txid %s", hex); + plugin_err(cmd->plugin, "Unable to parse reserved txid %s", hex); hex = json_strdup(tmpctx, buf, json_get_member(buf, result, "unsigned_tx")); @@ -376,7 +376,7 @@ static struct command_result *post_dryrun(struct command *cmd, } if (!funding_found) - plugin_err("Error creating placebo funding tx, funding_out not found. %s", hex); + plugin_err(cmd->plugin, "Error creating placebo funding tx, funding_out not found. %s", hex); /* Update funding to actual amount */ if (fr->funding_all && amount_sat_greater(funding, chainparams->max_funding)) diff --git a/plugins/libplugin.c b/plugins/libplugin.c index 93221a133..03726f5b7 100644 --- a/plugins/libplugin.c +++ b/plugins/libplugin.c @@ -72,6 +72,13 @@ static void ld_send(struct plugin *plugin, struct json_stream *stream) /* FIXME: Move lightningd/jsonrpc to common/ ? */ +static void jsonrpc_finish_and_send(struct plugin *p, struct json_stream *js) +{ + json_object_compat_end(js); + json_stream_close(js, NULL); + ld_send(p, js); +} + static struct json_stream *jsonrpc_stream_start(struct command *cmd) { struct json_stream *js = new_json_stream(cmd, cmd, NULL); @@ -138,7 +145,7 @@ static int read_json_from_rpc(struct plugin *p) if (r == 0) exit(0); if (r < 0) - plugin_err("Reading JSON input: %s", strerror(errno)); + plugin_err(p, "Reading JSON input: %s", strerror(errno)); membuf_added(&p->rpc_conn.mb, r); } @@ -291,7 +298,8 @@ void command_set_usage(struct command *cmd, const char *usage TAKES) { usage = tal_strdup(NULL, usage); if (!strmap_add(&cmd->plugin->usagemap, cmd->methodname, usage)) - plugin_err("Two usages for command %s?", cmd->methodname); + plugin_err(cmd->plugin, "Two usages for command %s?", + cmd->methodname); } /* Reads rpc reply and returns tokens, setting contents to 'error' or @@ -309,7 +317,7 @@ static const jsmntok_t *read_rpc_reply(const tal_t *ctx, toks = json_parse_input(ctx, membuf_elems(&plugin->rpc_conn.mb), *reqlen, &valid); if (!valid) - plugin_err("Malformed JSON reply '%.*s'", + plugin_err(plugin, "Malformed JSON reply '%.*s'", *reqlen, membuf_elems(&plugin->rpc_conn.mb)); *contents = json_get_member(membuf_elems(&plugin->rpc_conn.mb), toks, "error"); @@ -319,7 +327,7 @@ static const jsmntok_t *read_rpc_reply(const tal_t *ctx, *contents = json_get_member(membuf_elems(&plugin->rpc_conn.mb), toks, "result"); if (!*contents) - plugin_err("JSON reply with no 'result' nor 'error'? '%.*s'", + plugin_err(plugin, "JSON reply with no 'result' nor 'error'? '%.*s'", *reqlen, membuf_elems(&plugin->rpc_conn.mb)); *error = false; } @@ -360,13 +368,13 @@ const char *rpc_delve(const tal_t *ctx, read_rpc_reply(tmpctx, plugin, &contents, &error, &reqlen); if (error) - plugin_err("Got error reply to %s: '%.*s'", + plugin_err(plugin, "Got error reply to %s: '%.*s'", method, reqlen, membuf_elems(&plugin->rpc_conn.mb)); t = json_delve(membuf_elems(&plugin->rpc_conn.mb), contents, guide); if (!t) - plugin_err("Could not find %s in reply to %s: '%.*s'", - guide, method, reqlen, membuf_elems(&plugin->rpc_conn.mb)); + plugin_err(plugin, "Could not find %s in reply to %s: '%.*s'", + guide, method, reqlen, membuf_elems(&plugin->rpc_conn.mb)); ret = json_strdup(ctx, membuf_elems(&plugin->rpc_conn.mb), t); membuf_consume(&plugin->rpc_conn.mb, reqlen); @@ -386,14 +394,14 @@ static void handle_rpc_reply(struct plugin *plugin) t = json_get_member(membuf_elems(&plugin->rpc_conn.mb), toks, "id"); if (!t) - plugin_err("JSON reply without id '%.*s'", + plugin_err(plugin, "JSON reply without id '%.*s'", reqlen, membuf_elems(&plugin->rpc_conn.mb)); if (!json_to_u64(membuf_elems(&plugin->rpc_conn.mb), t, &id)) - plugin_err("JSON reply without numeric id '%.*s'", + plugin_err(plugin, "JSON reply without numeric id '%.*s'", reqlen, membuf_elems(&plugin->rpc_conn.mb)); out = uintmap_get(&out_reqs, id); if (!out) - plugin_err("JSON reply with unknown id '%.*s' (%"PRIu64")", + plugin_err(plugin, "JSON reply with unknown id '%.*s' (%"PRIu64")", reqlen, membuf_elems(&plugin->rpc_conn.mb), id); /* We want to free this if callback doesn't. */ @@ -508,7 +516,7 @@ static struct command_result *handle_init(struct command *cmd, dirtok = json_delve(buf, configtok, ".lightning-dir"); dir = json_strdup(tmpctx, buf, dirtok); if (chdir(dir) != 0) - plugin_err("chdir to %s: %s", dir, strerror(errno)); + plugin_err(p, "chdir to %s: %s", dir, strerror(errno)); nettok = json_delve(buf, configtok, ".network"); network = json_strdup(tmpctx, buf, nettok); @@ -517,7 +525,7 @@ static struct command_result *handle_init(struct command *cmd, rpctok = json_delve(buf, configtok, ".rpc-file"); p->rpc_conn.fd = socket(AF_UNIX, SOCK_STREAM, 0); if (rpctok->end - rpctok->start + 1 > sizeof(addr.sun_path)) - plugin_err("rpc filename '%.*s' too long", + plugin_err(p, "rpc filename '%.*s' too long", rpctok->end - rpctok->start, buf + rpctok->start); memcpy(addr.sun_path, buf + rpctok->start, rpctok->end - rpctok->start); @@ -525,7 +533,7 @@ static struct command_result *handle_init(struct command *cmd, addr.sun_family = AF_UNIX; if (connect(p->rpc_conn.fd, (struct sockaddr *)&addr, sizeof(addr)) != 0) - plugin_err("Connecting to '%.*s': %s", + plugin_err(p, "Connecting to '%.*s': %s", rpctok->end - rpctok->start, buf + rpctok->start, strerror(errno)); @@ -544,7 +552,7 @@ static struct command_result *handle_init(struct command *cmd, problem = p->opts[i].handle(json_strdup(opt, buf, t+1), p->opts[i].arg); if (problem) - plugin_err("option '%s': %s", + plugin_err(p, "option '%s': %s", p->opts[i].name, problem); break; } @@ -620,45 +628,45 @@ struct plugin_timer *plugin_timer(struct plugin *p, struct timerel t, return timer; } -static void plugin_logv(enum log_level l, const char *fmt, va_list ap) +static void plugin_logv(struct plugin *p, enum log_level l, + const char *fmt, va_list ap) { - struct json_out *jout = json_out_new(tmpctx); + struct json_stream *js = new_json_stream(NULL, NULL, NULL); - json_out_start(jout, NULL, '{'); - json_out_addstr(jout, "jsonrpc", "2.0"); - json_out_addstr(jout, "method", "log"); + json_object_start(js, NULL); + json_add_string(js, "jsonrpc", "2.0"); + json_add_string(js, "method", "log"); - json_out_start(jout, "params", '{'); - json_out_addstr(jout, "level", + json_object_start(js, "params"); + json_add_string(js, "level", l == LOG_DBG ? "debug" : l == LOG_INFORM ? "info" : l == LOG_UNUSUAL ? "warn" : "error"); - json_out_addv(jout, "message", true, fmt, ap); - json_out_end(jout, '}'); + json_out_addv(js->jout, "message", true, fmt, ap); + json_object_end(js); - /* Last '}' is done by finish_and_send_json */ - finish_and_send_json(STDOUT_FILENO, jout); + jsonrpc_finish_and_send(p, js); } -void NORETURN plugin_err(const char *fmt, ...) +void NORETURN plugin_err(struct plugin *p, const char *fmt, ...) { va_list ap; va_start(ap, fmt); - plugin_logv(LOG_BROKEN, fmt, ap); + plugin_logv(p, LOG_BROKEN, fmt, ap); va_end(ap); va_start(ap, fmt); errx(1, "%s", tal_vfmt(NULL, fmt, ap)); va_end(ap); } -void plugin_log(enum log_level l, const char *fmt, ...) +void plugin_log(struct plugin *p, enum log_level l, const char *fmt, ...) { va_list ap; va_start(ap, fmt); - plugin_logv(l, fmt, ap); + plugin_logv(p, l, fmt, ap); va_end(ap); } @@ -673,7 +681,7 @@ static void ld_command_handle(struct plugin *plugin, paramstok = json_get_member(plugin->buffer, toks, "params"); if (!methtok || !paramstok) - plugin_err("Malformed JSON-RPC notification missing " + plugin_err(plugin, "Malformed JSON-RPC notification missing " "\"method\" or \"params\": %.*s", json_tok_full_len(toks), json_tok_full(plugin->buffer, toks)); @@ -685,7 +693,7 @@ static void ld_command_handle(struct plugin *plugin, if (idtok) { cmd->id = tal(cmd, u64); if (!json_to_u64(plugin->buffer, idtok, cmd->id)) - plugin_err("JSON id '%*.s' is not a number", + plugin_err(plugin, "JSON id '%*.s' is not a number", json_tok_full_len(idtok), json_tok_full(plugin->buffer, idtok)); } @@ -696,7 +704,7 @@ static void ld_command_handle(struct plugin *plugin, plugin->manifested = true; return; } - plugin_err("Did not receive 'getmanifest' yet, but got '%s'" + plugin_err(plugin, "Did not receive 'getmanifest' yet, but got '%s'" " instead", cmd->methodname); } @@ -706,7 +714,7 @@ static void ld_command_handle(struct plugin *plugin, plugin->initialized = true; return; } - plugin_err("Did not receive 'init' yet, but got '%s'" + plugin_err(plugin, "Did not receive 'init' yet, but got '%s'" " instead", cmd->methodname); } @@ -721,7 +729,7 @@ static void ld_command_handle(struct plugin *plugin, return; } } - plugin_err("Unregistered notification %.*s", + plugin_err(plugin, "Unregistered notification %.*s", json_tok_full_len(methtok), json_tok_full(plugin->buffer, methtok)); } @@ -744,7 +752,7 @@ static void ld_command_handle(struct plugin *plugin, } } - plugin_err("Unknown command '%s'", cmd->methodname); + plugin_err(plugin, "Unknown command '%s'", cmd->methodname); } /** @@ -764,7 +772,7 @@ static bool ld_read_json_one(struct plugin *plugin) &valid); if (!toks) { if (!valid) { - plugin_err("Failed to parse JSON response '%.*s'", + plugin_err(plugin, "Failed to parse JSON response '%.*s'", (int)plugin->used, plugin->buffer); return false; } @@ -780,7 +788,7 @@ static bool ld_read_json_one(struct plugin *plugin) jrtok = json_get_member(plugin->buffer, toks, "jsonrpc"); if (!jrtok) { - plugin_err("JSON-RPC message does not contain \"jsonrpc\" field"); + plugin_err(plugin, "JSON-RPC message does not contain \"jsonrpc\" field"); return false; } diff --git a/plugins/libplugin.h b/plugins/libplugin.h index 283a958c2..ed9eb4905 100644 --- a/plugins/libplugin.h +++ b/plugins/libplugin.h @@ -121,7 +121,7 @@ struct json_out *json_out_obj(const tal_t *ctx, struct command_result *command_param_failed(void); /* Call this on fatal error. */ -void NORETURN plugin_err(const char *fmt, ...); +void NORETURN plugin_err(struct plugin *p, const char *fmt, ...); /* This command is finished, here's a detailed error; @cmd cannot be * NULL, data can be NULL; otherwise it must be a JSON object. */ @@ -212,7 +212,7 @@ struct plugin_timer *plugin_timer(struct plugin *p, struct command_result *(*cb)(struct plugin *p)); /* Log something */ -void plugin_log(enum log_level l, const char *fmt, ...) PRINTF_FMT(2, 3); +void plugin_log(struct plugin *p, enum log_level l, const char *fmt, ...) PRINTF_FMT(3, 4); /* Macro to define arguments */ #define plugin_option(name, type, description, set, arg) \ diff --git a/plugins/pay.c b/plugins/pay.c index b84fbb940..b9d3ded92 100644 --- a/plugins/pay.c +++ b/plugins/pay.c @@ -74,6 +74,9 @@ struct pay_status { }; struct pay_command { + /* Global state */ + struct plugin *plugin; + /* Destination, as text */ const char *dest; @@ -215,7 +218,8 @@ static struct command_result *start_pay_attempt(struct command *cmd, const char *fmt, ...); /* Is this (erring) channel within the routehint itself? */ -static bool node_or_channel_in_routehint(const struct route_info *routehint, +static bool node_or_channel_in_routehint(struct plugin *plugin, + const struct route_info *routehint, const char *idstr, size_t idlen) { struct node_id nodeid; @@ -224,7 +228,7 @@ static bool node_or_channel_in_routehint(const struct route_info *routehint, if (!node_id_from_hexstr(idstr, idlen, &nodeid)) { if (!short_channel_id_from_str(idstr, idlen, &scid)) - plugin_err("bad erring_node or erring_channel '%.*s'", + plugin_err(plugin, "bad erring_node or erring_channel '%.*s'", (int)idlen, idstr); else node_err = false; @@ -280,14 +284,16 @@ static struct command_result *waitsendpay_expired(struct command *cmd, return command_done_err(cmd, PAY_STOPPED_RETRYING, errmsg, data); } -static bool routehint_excluded(const struct route_info *routehint, +static bool routehint_excluded(struct plugin *plugin, + const struct route_info *routehint, const char **excludes) { /* Note that we ignore direction here: in theory, we could have * found that one direction of a channel is unavailable, but they * are suggesting we use it the other way. Very unlikely though! */ for (size_t i = 0; i < tal_count(excludes); i++) - if (node_or_channel_in_routehint(routehint, + if (node_or_channel_in_routehint(plugin, + routehint, excludes[i], strlen(excludes[i]))) return true; @@ -300,7 +306,8 @@ static struct command_result *next_routehint(struct command *cmd, size_t num_attempts = count_sendpays(pc->ps->attempts); while (tal_count(pc->routehints) > 0) { - if (!routehint_excluded(pc->routehints[0], pc->excludes)) { + if (!routehint_excluded(pc->plugin, pc->routehints[0], + pc->excludes)) { pc->current_routehint = pc->routehints[0]; tal_arr_remove(&pc->routehints, 0); return start_pay_attempt(cmd, pc, "Trying route hint"); @@ -434,13 +441,13 @@ static struct command_result *waitsendpay_error(struct command *cmd, codetok = json_get_member(buf, error, "code"); if (!json_to_errcode(buf, codetok, &code)) - plugin_err("waitsendpay error gave no 'code'? '%.*s'", + plugin_err(cmd->plugin, "waitsendpay error gave no 'code'? '%.*s'", error->end - error->start, buf + error->start); if (code != PAY_UNPARSEABLE_ONION) { failcodetok = json_delve(buf, error, ".data.failcode"); if (!json_to_int(buf, failcodetok, &failcode)) - plugin_err("waitsendpay error gave no 'failcode'? '%.*s'", + plugin_err(cmd->plugin, "waitsendpay error gave no 'failcode'? '%.*s'", error->end - error->start, buf + error->start); } @@ -505,17 +512,17 @@ static struct command_result *waitsendpay_error(struct command *cmd, if (failcode & NODE) { nodeidtok = json_delve(buf, error, ".data.erring_node"); if (!nodeidtok) - plugin_err("waitsendpay error no erring_node '%.*s'", + plugin_err(cmd->plugin, "waitsendpay error no erring_node '%.*s'", error->end - error->start, buf + error->start); node_err = true; } else { scidtok = json_delve(buf, error, ".data.erring_channel"); if (!scidtok) - plugin_err("waitsendpay error no erring_channel '%.*s'", + plugin_err(cmd->plugin, "waitsendpay error no erring_channel '%.*s'", error->end - error->start, buf + error->start); dirtok = json_delve(buf, error, ".data.erring_direction"); if (!dirtok) - plugin_err("waitsendpay error no erring_direction '%.*s'", + plugin_err(cmd->plugin, "waitsendpay error no erring_direction '%.*s'", error->end - error->start, buf + error->start); } @@ -525,7 +532,7 @@ static struct command_result *waitsendpay_error(struct command *cmd, if (node_err) { /* If failure is in routehint part, try next one */ - if (node_or_channel_in_routehint(pc->current_routehint, + if (node_or_channel_in_routehint(pc->plugin, pc->current_routehint, buf + nodeidtok->start, nodeidtok->end - nodeidtok->start)) return next_routehint(cmd, pc); @@ -537,7 +544,7 @@ static struct command_result *waitsendpay_error(struct command *cmd, buf + nodeidtok->start)); } else { /* If failure is in routehint part, try next one */ - if (node_or_channel_in_routehint(pc->current_routehint, + if (node_or_channel_in_routehint(pc->plugin, pc->current_routehint, buf + scidtok->start, scidtok->end - scidtok->start)) return next_routehint(cmd, pc); @@ -705,7 +712,8 @@ static bool maybe_exclude(struct pay_command *pc, scid = json_get_member(buf, route, "channel"); - if (node_or_channel_in_routehint(pc->current_routehint, + if (node_or_channel_in_routehint(pc->plugin, + pc->current_routehint, buf + scid->start, scid->end - scid->start)) return false; @@ -732,7 +740,7 @@ static struct command_result *getroute_done(struct command *cmd, struct json_out *params; if (!t) - plugin_err("getroute gave no 'route'? '%.*s'", + plugin_err(cmd->plugin, "getroute gave no 'route'? '%.*s'", result->end - result->start, buf); if (pc->current_routehint) { @@ -749,15 +757,15 @@ static struct command_result *getroute_done(struct command *cmd, attempt->route = json_strdup(pc->ps->attempts, buf, t); if (!json_to_msat(buf, json_delve(buf, t, "[0].msatoshi"), &fee)) - plugin_err("getroute with invalid msatoshi? %.*s", + plugin_err(cmd->plugin, "getroute with invalid msatoshi? %.*s", result->end - result->start, buf); if (!amount_msat_sub(&fee, fee, pc->msat)) - plugin_err("final amount %s less than paid %s", + plugin_err(cmd->plugin, "final amount %s less than paid %s", type_to_string(tmpctx, struct amount_msat, &fee), type_to_string(tmpctx, struct amount_msat, &pc->msat)); if (!json_to_number(buf, json_delve(buf, t, "[0].delay"), &delay)) - plugin_err("getroute with invalid delay? %.*s", + plugin_err(cmd->plugin, "getroute with invalid delay? %.*s", result->end - result->start, buf); /* Casting u64 to double will lose some precision. The loss of precision @@ -858,7 +866,7 @@ static struct command_result *getroute_error(struct command *cmd, codetok = json_get_member(buf, error, "code"); if (!json_to_errcode(buf, codetok, &code)) - plugin_err("getroute error gave no 'code'? '%.*s'", + plugin_err(cmd->plugin, "getroute error gave no 'code'? '%.*s'", error->end - error->start, buf + error->start); /* Strange errors from getroute should be forwarded. */ @@ -952,12 +960,12 @@ getstartblockheight_done(struct command *cmd, blockheight_tok = json_get_member(buf, result, "blockheight"); if (!blockheight_tok) - plugin_err("getstartblockheight: " + plugin_err(cmd->plugin, "getstartblockheight: " "getinfo gave no 'blockheight'? '%.*s'", result->end - result->start, buf); if (!json_to_u32(buf, blockheight_tok, &blockheight)) - plugin_err("getstartblockheight: " + plugin_err(cmd->plugin, "getstartblockheight: " "getinfo gave non-unsigned-32-bit 'blockheight'? '%.*s'", result->end - result->start, buf); @@ -973,7 +981,7 @@ getstartblockheight_error(struct command *cmd, struct pay_command *pc) { /* Should never happen. */ - plugin_err("getstartblockheight: getinfo failed!? '%.*s'", + plugin_err(cmd->plugin, "getstartblockheight: getinfo failed!? '%.*s'", error->end - error->start, buf); } @@ -1124,7 +1132,7 @@ static struct command_result *listpeers_done(struct command *cmd, peers = json_get_member(buf, result, "peers"); if (!peers) - plugin_err("listpeers gave no 'peers'? '%.*s'", + plugin_err(cmd->plugin, "listpeers gave no 'peers'? '%.*s'", result->end - result->start, buf); json_for_each_arr(i, peer, peers) { @@ -1526,7 +1534,8 @@ static bool pay_mpp_eq(const struct pay_mpp *pm, const char *b11) HTABLE_DEFINE_TYPE(struct pay_mpp, pay_mpp_key, b11str_hash, pay_mpp_eq, pay_map); -static void add_amount_sent(const char *b11, +static void add_amount_sent(struct plugin *p, + const char *b11, struct amount_msat *total, const char *buf, const jsmntok_t *t) @@ -1534,7 +1543,7 @@ static void add_amount_sent(const char *b11, struct amount_msat sent; json_to_msat(buf, json_get_member(buf, t, "amount_sent_msat"), &sent); if (!amount_msat_add(total, *total, sent)) - plugin_log(LOG_BROKEN, + plugin_log(p, LOG_BROKEN, "Cannot add amount_sent_msat for %s: %s + %s", b11, type_to_string(tmpctx, struct amount_msat, total), @@ -1612,13 +1621,15 @@ static struct command_result *listsendpays_done(struct command *cmd, status = json_get_member(buf, t, "status"); if (json_tok_streq(buf, status, "complete")) { - add_amount_sent(pm->b11, &pm->amount_sent, buf, t); + add_amount_sent(cmd->plugin, pm->b11, + &pm->amount_sent, buf, t); pm->num_nonfailed_parts++; pm->status = "complete"; pm->preimage = json_get_member(buf, t, "payment_preimage"); } else if (json_tok_streq(buf, status, "pending")) { - add_amount_sent(pm->b11, &pm->amount_sent, buf, t); + add_amount_sent(cmd->plugin, pm->b11, + &pm->amount_sent, buf, t); pm->num_nonfailed_parts++; /* Failed -> pending; don't downgrade success. */ if (!pm->status || !streq(pm->status, "complete")) @@ -1674,7 +1685,7 @@ static void init(struct plugin *p, field = rpc_delve(tmpctx, p, "getinfo", take(json_out_obj(NULL, NULL, NULL)), ".id"); if (!node_id_from_hexstr(field, strlen(field), &my_id)) - plugin_err("getinfo didn't contain valid id: '%s'", field); + plugin_err(p, "getinfo didn't contain valid id: '%s'", field); field = rpc_delve(tmpctx, p, "listconfigs", take(json_out_obj(NULL,