mirror of
https://github.com/aljazceru/lightning.git
synced 2025-12-19 15:14:23 +01:00
libplugin: use ccan/io for notifications
This commit is contained in:
@@ -72,11 +72,11 @@ static void init(struct plugin *p,
|
|||||||
rpc = &p->rpc_conn;
|
rpc = &p->rpc_conn;
|
||||||
|
|
||||||
if (cycle_seconds) {
|
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),
|
cleantimer = plugin_timer(p, time_from_sec(cycle_seconds),
|
||||||
do_clean);
|
do_clean);
|
||||||
} else
|
} else
|
||||||
plugin_log(LOG_DBG, "autocleaning not active");
|
plugin_log(p, LOG_DBG, "autocleaning not active");
|
||||||
}
|
}
|
||||||
|
|
||||||
static const struct plugin_command commands[] = { {
|
static const struct plugin_command commands[] = { {
|
||||||
|
|||||||
@@ -143,7 +143,7 @@ static struct command_result *send_tx(struct command *cmd,
|
|||||||
tok = json_get_member(buf, result, "commitments_secured");
|
tok = json_get_member(buf, result, "commitments_secured");
|
||||||
if (!json_to_bool(buf, tok, &commitments_secured) || !commitments_secured)
|
if (!json_to_bool(buf, tok, &commitments_secured) || !commitments_secured)
|
||||||
/* TODO: better failure path? this should never fail though. */
|
/* 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 */
|
/* Stash the channel_id so we can return it when finalized */
|
||||||
tok = json_get_member(buf, result, "channel_id");
|
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");
|
txid_tok = json_get_member(buf, result, "txid");
|
||||||
if (!txid_tok)
|
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");
|
tx_tok = json_get_member(buf, result, "unsigned_tx");
|
||||||
if (!tx_tok)
|
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);
|
hex = json_strdup(tmpctx, buf, tx_tok);
|
||||||
tx = bitcoin_tx_from_hex(fr, hex, strlen(hex));
|
tx = bitcoin_tx_from_hex(fr, hex, strlen(hex));
|
||||||
if (!tx)
|
if (!tx)
|
||||||
plugin_err("Unable to parse tx %s", hex);
|
plugin_err(cmd->plugin, "Unable to parse tx %s", hex);
|
||||||
|
|
||||||
/* Find the txout */
|
/* Find the txout */
|
||||||
outnum_found = false;
|
outnum_found = false;
|
||||||
@@ -197,14 +197,14 @@ static struct command_result *tx_prepare_done(struct command *cmd,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (!outnum_found)
|
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",
|
"tx: %s, output: %s",
|
||||||
type_to_string(tmpctx, struct bitcoin_tx, tx),
|
type_to_string(tmpctx, struct bitcoin_tx, tx),
|
||||||
tal_hex(tmpctx, fr->out_script));
|
tal_hex(tmpctx, fr->out_script));
|
||||||
|
|
||||||
hex = json_strdup(tmpctx, buf, txid_tok);
|
hex = json_strdup(tmpctx, buf, txid_tok);
|
||||||
if (!bitcoin_txid_from_hex(hex, strlen(hex), &fr->tx_id))
|
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);
|
ret = json_out_new(NULL);
|
||||||
json_out_start(ret, 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 */
|
/* Stash the 'reserved' txid to unreserve later */
|
||||||
hex = json_strdup(tmpctx, buf, json_get_member(buf, result, "txid"));
|
hex = json_strdup(tmpctx, buf, json_get_member(buf, result, "txid"));
|
||||||
if (!bitcoin_txid_from_hex(hex, strlen(hex), &fr->tx_id))
|
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"));
|
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)
|
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 */
|
/* Update funding to actual amount */
|
||||||
if (fr->funding_all && amount_sat_greater(funding, chainparams->max_funding))
|
if (fr->funding_all && amount_sat_greater(funding, chainparams->max_funding))
|
||||||
|
|||||||
@@ -72,6 +72,13 @@ static void ld_send(struct plugin *plugin, struct json_stream *stream)
|
|||||||
|
|
||||||
/* FIXME: Move lightningd/jsonrpc to common/ ? */
|
/* 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)
|
static struct json_stream *jsonrpc_stream_start(struct command *cmd)
|
||||||
{
|
{
|
||||||
struct json_stream *js = new_json_stream(cmd, cmd, NULL);
|
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)
|
if (r == 0)
|
||||||
exit(0);
|
exit(0);
|
||||||
if (r < 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);
|
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);
|
usage = tal_strdup(NULL, usage);
|
||||||
if (!strmap_add(&cmd->plugin->usagemap, cmd->methodname, 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
|
/* 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);
|
toks = json_parse_input(ctx, membuf_elems(&plugin->rpc_conn.mb), *reqlen, &valid);
|
||||||
if (!valid)
|
if (!valid)
|
||||||
plugin_err("Malformed JSON reply '%.*s'",
|
plugin_err(plugin, "Malformed JSON reply '%.*s'",
|
||||||
*reqlen, membuf_elems(&plugin->rpc_conn.mb));
|
*reqlen, membuf_elems(&plugin->rpc_conn.mb));
|
||||||
|
|
||||||
*contents = json_get_member(membuf_elems(&plugin->rpc_conn.mb), toks, "error");
|
*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,
|
*contents = json_get_member(membuf_elems(&plugin->rpc_conn.mb), toks,
|
||||||
"result");
|
"result");
|
||||||
if (!*contents)
|
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));
|
*reqlen, membuf_elems(&plugin->rpc_conn.mb));
|
||||||
*error = false;
|
*error = false;
|
||||||
}
|
}
|
||||||
@@ -360,13 +368,13 @@ const char *rpc_delve(const tal_t *ctx,
|
|||||||
|
|
||||||
read_rpc_reply(tmpctx, plugin, &contents, &error, &reqlen);
|
read_rpc_reply(tmpctx, plugin, &contents, &error, &reqlen);
|
||||||
if (error)
|
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));
|
method, reqlen, membuf_elems(&plugin->rpc_conn.mb));
|
||||||
|
|
||||||
t = json_delve(membuf_elems(&plugin->rpc_conn.mb), contents, guide);
|
t = json_delve(membuf_elems(&plugin->rpc_conn.mb), contents, guide);
|
||||||
if (!t)
|
if (!t)
|
||||||
plugin_err("Could not find %s in reply to %s: '%.*s'",
|
plugin_err(plugin, "Could not find %s in reply to %s: '%.*s'",
|
||||||
guide, method, reqlen, membuf_elems(&plugin->rpc_conn.mb));
|
guide, method, reqlen, membuf_elems(&plugin->rpc_conn.mb));
|
||||||
|
|
||||||
ret = json_strdup(ctx, membuf_elems(&plugin->rpc_conn.mb), t);
|
ret = json_strdup(ctx, membuf_elems(&plugin->rpc_conn.mb), t);
|
||||||
membuf_consume(&plugin->rpc_conn.mb, reqlen);
|
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");
|
t = json_get_member(membuf_elems(&plugin->rpc_conn.mb), toks, "id");
|
||||||
if (!t)
|
if (!t)
|
||||||
plugin_err("JSON reply without id '%.*s'",
|
plugin_err(plugin, "JSON reply without id '%.*s'",
|
||||||
reqlen, membuf_elems(&plugin->rpc_conn.mb));
|
reqlen, membuf_elems(&plugin->rpc_conn.mb));
|
||||||
if (!json_to_u64(membuf_elems(&plugin->rpc_conn.mb), t, &id))
|
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));
|
reqlen, membuf_elems(&plugin->rpc_conn.mb));
|
||||||
out = uintmap_get(&out_reqs, id);
|
out = uintmap_get(&out_reqs, id);
|
||||||
if (!out)
|
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);
|
reqlen, membuf_elems(&plugin->rpc_conn.mb), id);
|
||||||
|
|
||||||
/* We want to free this if callback doesn't. */
|
/* 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");
|
dirtok = json_delve(buf, configtok, ".lightning-dir");
|
||||||
dir = json_strdup(tmpctx, buf, dirtok);
|
dir = json_strdup(tmpctx, buf, dirtok);
|
||||||
if (chdir(dir) != 0)
|
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");
|
nettok = json_delve(buf, configtok, ".network");
|
||||||
network = json_strdup(tmpctx, buf, nettok);
|
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");
|
rpctok = json_delve(buf, configtok, ".rpc-file");
|
||||||
p->rpc_conn.fd = socket(AF_UNIX, SOCK_STREAM, 0);
|
p->rpc_conn.fd = socket(AF_UNIX, SOCK_STREAM, 0);
|
||||||
if (rpctok->end - rpctok->start + 1 > sizeof(addr.sun_path))
|
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,
|
rpctok->end - rpctok->start,
|
||||||
buf + rpctok->start);
|
buf + rpctok->start);
|
||||||
memcpy(addr.sun_path, buf + rpctok->start, rpctok->end - 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;
|
addr.sun_family = AF_UNIX;
|
||||||
|
|
||||||
if (connect(p->rpc_conn.fd, (struct sockaddr *)&addr, sizeof(addr)) != 0)
|
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,
|
rpctok->end - rpctok->start, buf + rpctok->start,
|
||||||
strerror(errno));
|
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),
|
problem = p->opts[i].handle(json_strdup(opt, buf, t+1),
|
||||||
p->opts[i].arg);
|
p->opts[i].arg);
|
||||||
if (problem)
|
if (problem)
|
||||||
plugin_err("option '%s': %s",
|
plugin_err(p, "option '%s': %s",
|
||||||
p->opts[i].name, problem);
|
p->opts[i].name, problem);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@@ -620,45 +628,45 @@ struct plugin_timer *plugin_timer(struct plugin *p, struct timerel t,
|
|||||||
return timer;
|
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_object_start(js, NULL);
|
||||||
json_out_addstr(jout, "jsonrpc", "2.0");
|
json_add_string(js, "jsonrpc", "2.0");
|
||||||
json_out_addstr(jout, "method", "log");
|
json_add_string(js, "method", "log");
|
||||||
|
|
||||||
json_out_start(jout, "params", '{');
|
json_object_start(js, "params");
|
||||||
json_out_addstr(jout, "level",
|
json_add_string(js, "level",
|
||||||
l == LOG_DBG ? "debug"
|
l == LOG_DBG ? "debug"
|
||||||
: l == LOG_INFORM ? "info"
|
: l == LOG_INFORM ? "info"
|
||||||
: l == LOG_UNUSUAL ? "warn"
|
: l == LOG_UNUSUAL ? "warn"
|
||||||
: "error");
|
: "error");
|
||||||
json_out_addv(jout, "message", true, fmt, ap);
|
json_out_addv(js->jout, "message", true, fmt, ap);
|
||||||
json_out_end(jout, '}');
|
json_object_end(js);
|
||||||
|
|
||||||
/* Last '}' is done by finish_and_send_json */
|
jsonrpc_finish_and_send(p, js);
|
||||||
finish_and_send_json(STDOUT_FILENO, jout);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void NORETURN plugin_err(const char *fmt, ...)
|
void NORETURN plugin_err(struct plugin *p, const char *fmt, ...)
|
||||||
{
|
{
|
||||||
va_list ap;
|
va_list ap;
|
||||||
|
|
||||||
va_start(ap, fmt);
|
va_start(ap, fmt);
|
||||||
plugin_logv(LOG_BROKEN, fmt, ap);
|
plugin_logv(p, LOG_BROKEN, fmt, ap);
|
||||||
va_end(ap);
|
va_end(ap);
|
||||||
va_start(ap, fmt);
|
va_start(ap, fmt);
|
||||||
errx(1, "%s", tal_vfmt(NULL, fmt, ap));
|
errx(1, "%s", tal_vfmt(NULL, fmt, ap));
|
||||||
va_end(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_list ap;
|
||||||
|
|
||||||
va_start(ap, fmt);
|
va_start(ap, fmt);
|
||||||
plugin_logv(l, fmt, ap);
|
plugin_logv(p, l, fmt, ap);
|
||||||
va_end(ap);
|
va_end(ap);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -673,7 +681,7 @@ static void ld_command_handle(struct plugin *plugin,
|
|||||||
paramstok = json_get_member(plugin->buffer, toks, "params");
|
paramstok = json_get_member(plugin->buffer, toks, "params");
|
||||||
|
|
||||||
if (!methtok || !paramstok)
|
if (!methtok || !paramstok)
|
||||||
plugin_err("Malformed JSON-RPC notification missing "
|
plugin_err(plugin, "Malformed JSON-RPC notification missing "
|
||||||
"\"method\" or \"params\": %.*s",
|
"\"method\" or \"params\": %.*s",
|
||||||
json_tok_full_len(toks),
|
json_tok_full_len(toks),
|
||||||
json_tok_full(plugin->buffer, toks));
|
json_tok_full(plugin->buffer, toks));
|
||||||
@@ -685,7 +693,7 @@ static void ld_command_handle(struct plugin *plugin,
|
|||||||
if (idtok) {
|
if (idtok) {
|
||||||
cmd->id = tal(cmd, u64);
|
cmd->id = tal(cmd, u64);
|
||||||
if (!json_to_u64(plugin->buffer, idtok, cmd->id))
|
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_len(idtok),
|
||||||
json_tok_full(plugin->buffer, idtok));
|
json_tok_full(plugin->buffer, idtok));
|
||||||
}
|
}
|
||||||
@@ -696,7 +704,7 @@ static void ld_command_handle(struct plugin *plugin,
|
|||||||
plugin->manifested = true;
|
plugin->manifested = true;
|
||||||
return;
|
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);
|
" instead", cmd->methodname);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -706,7 +714,7 @@ static void ld_command_handle(struct plugin *plugin,
|
|||||||
plugin->initialized = true;
|
plugin->initialized = true;
|
||||||
return;
|
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);
|
" instead", cmd->methodname);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -721,7 +729,7 @@ static void ld_command_handle(struct plugin *plugin,
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
plugin_err("Unregistered notification %.*s",
|
plugin_err(plugin, "Unregistered notification %.*s",
|
||||||
json_tok_full_len(methtok),
|
json_tok_full_len(methtok),
|
||||||
json_tok_full(plugin->buffer, 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);
|
&valid);
|
||||||
if (!toks) {
|
if (!toks) {
|
||||||
if (!valid) {
|
if (!valid) {
|
||||||
plugin_err("Failed to parse JSON response '%.*s'",
|
plugin_err(plugin, "Failed to parse JSON response '%.*s'",
|
||||||
(int)plugin->used, plugin->buffer);
|
(int)plugin->used, plugin->buffer);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@@ -780,7 +788,7 @@ static bool ld_read_json_one(struct plugin *plugin)
|
|||||||
|
|
||||||
jrtok = json_get_member(plugin->buffer, toks, "jsonrpc");
|
jrtok = json_get_member(plugin->buffer, toks, "jsonrpc");
|
||||||
if (!jrtok) {
|
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;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -121,7 +121,7 @@ struct json_out *json_out_obj(const tal_t *ctx,
|
|||||||
struct command_result *command_param_failed(void);
|
struct command_result *command_param_failed(void);
|
||||||
|
|
||||||
/* Call this on fatal error. */
|
/* 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
|
/* This command is finished, here's a detailed error; @cmd cannot be
|
||||||
* NULL, data can be NULL; otherwise it must be a JSON object. */
|
* 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));
|
struct command_result *(*cb)(struct plugin *p));
|
||||||
|
|
||||||
/* Log something */
|
/* 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 */
|
/* Macro to define arguments */
|
||||||
#define plugin_option(name, type, description, set, arg) \
|
#define plugin_option(name, type, description, set, arg) \
|
||||||
|
|||||||
@@ -74,6 +74,9 @@ struct pay_status {
|
|||||||
};
|
};
|
||||||
|
|
||||||
struct pay_command {
|
struct pay_command {
|
||||||
|
/* Global state */
|
||||||
|
struct plugin *plugin;
|
||||||
|
|
||||||
/* Destination, as text */
|
/* Destination, as text */
|
||||||
const char *dest;
|
const char *dest;
|
||||||
|
|
||||||
@@ -215,7 +218,8 @@ static struct command_result *start_pay_attempt(struct command *cmd,
|
|||||||
const char *fmt, ...);
|
const char *fmt, ...);
|
||||||
|
|
||||||
/* Is this (erring) channel within the routehint itself? */
|
/* 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)
|
const char *idstr, size_t idlen)
|
||||||
{
|
{
|
||||||
struct node_id nodeid;
|
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 (!node_id_from_hexstr(idstr, idlen, &nodeid)) {
|
||||||
if (!short_channel_id_from_str(idstr, idlen, &scid))
|
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);
|
(int)idlen, idstr);
|
||||||
else
|
else
|
||||||
node_err = false;
|
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);
|
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)
|
const char **excludes)
|
||||||
{
|
{
|
||||||
/* Note that we ignore direction here: in theory, we could have
|
/* Note that we ignore direction here: in theory, we could have
|
||||||
* found that one direction of a channel is unavailable, but they
|
* found that one direction of a channel is unavailable, but they
|
||||||
* are suggesting we use it the other way. Very unlikely though! */
|
* are suggesting we use it the other way. Very unlikely though! */
|
||||||
for (size_t i = 0; i < tal_count(excludes); i++)
|
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],
|
excludes[i],
|
||||||
strlen(excludes[i])))
|
strlen(excludes[i])))
|
||||||
return true;
|
return true;
|
||||||
@@ -300,7 +306,8 @@ static struct command_result *next_routehint(struct command *cmd,
|
|||||||
size_t num_attempts = count_sendpays(pc->ps->attempts);
|
size_t num_attempts = count_sendpays(pc->ps->attempts);
|
||||||
|
|
||||||
while (tal_count(pc->routehints) > 0) {
|
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];
|
pc->current_routehint = pc->routehints[0];
|
||||||
tal_arr_remove(&pc->routehints, 0);
|
tal_arr_remove(&pc->routehints, 0);
|
||||||
return start_pay_attempt(cmd, pc, "Trying route hint");
|
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");
|
codetok = json_get_member(buf, error, "code");
|
||||||
if (!json_to_errcode(buf, codetok, &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);
|
error->end - error->start, buf + error->start);
|
||||||
|
|
||||||
if (code != PAY_UNPARSEABLE_ONION) {
|
if (code != PAY_UNPARSEABLE_ONION) {
|
||||||
failcodetok = json_delve(buf, error, ".data.failcode");
|
failcodetok = json_delve(buf, error, ".data.failcode");
|
||||||
if (!json_to_int(buf, failcodetok, &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);
|
error->end - error->start, buf + error->start);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -505,17 +512,17 @@ static struct command_result *waitsendpay_error(struct command *cmd,
|
|||||||
if (failcode & NODE) {
|
if (failcode & NODE) {
|
||||||
nodeidtok = json_delve(buf, error, ".data.erring_node");
|
nodeidtok = json_delve(buf, error, ".data.erring_node");
|
||||||
if (!nodeidtok)
|
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);
|
error->end - error->start, buf + error->start);
|
||||||
node_err = true;
|
node_err = true;
|
||||||
} else {
|
} else {
|
||||||
scidtok = json_delve(buf, error, ".data.erring_channel");
|
scidtok = json_delve(buf, error, ".data.erring_channel");
|
||||||
if (!scidtok)
|
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);
|
error->end - error->start, buf + error->start);
|
||||||
dirtok = json_delve(buf, error, ".data.erring_direction");
|
dirtok = json_delve(buf, error, ".data.erring_direction");
|
||||||
if (!dirtok)
|
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);
|
error->end - error->start, buf + error->start);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -525,7 +532,7 @@ static struct command_result *waitsendpay_error(struct command *cmd,
|
|||||||
|
|
||||||
if (node_err) {
|
if (node_err) {
|
||||||
/* If failure is in routehint part, try next one */
|
/* 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,
|
buf + nodeidtok->start,
|
||||||
nodeidtok->end - nodeidtok->start))
|
nodeidtok->end - nodeidtok->start))
|
||||||
return next_routehint(cmd, pc);
|
return next_routehint(cmd, pc);
|
||||||
@@ -537,7 +544,7 @@ static struct command_result *waitsendpay_error(struct command *cmd,
|
|||||||
buf + nodeidtok->start));
|
buf + nodeidtok->start));
|
||||||
} else {
|
} else {
|
||||||
/* If failure is in routehint part, try next one */
|
/* 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,
|
buf + scidtok->start,
|
||||||
scidtok->end - scidtok->start))
|
scidtok->end - scidtok->start))
|
||||||
return next_routehint(cmd, pc);
|
return next_routehint(cmd, pc);
|
||||||
@@ -705,7 +712,8 @@ static bool maybe_exclude(struct pay_command *pc,
|
|||||||
|
|
||||||
scid = json_get_member(buf, route, "channel");
|
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,
|
buf + scid->start,
|
||||||
scid->end - scid->start))
|
scid->end - scid->start))
|
||||||
return false;
|
return false;
|
||||||
@@ -732,7 +740,7 @@ static struct command_result *getroute_done(struct command *cmd,
|
|||||||
struct json_out *params;
|
struct json_out *params;
|
||||||
|
|
||||||
if (!t)
|
if (!t)
|
||||||
plugin_err("getroute gave no 'route'? '%.*s'",
|
plugin_err(cmd->plugin, "getroute gave no 'route'? '%.*s'",
|
||||||
result->end - result->start, buf);
|
result->end - result->start, buf);
|
||||||
|
|
||||||
if (pc->current_routehint) {
|
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);
|
attempt->route = json_strdup(pc->ps->attempts, buf, t);
|
||||||
|
|
||||||
if (!json_to_msat(buf, json_delve(buf, t, "[0].msatoshi"), &fee))
|
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);
|
result->end - result->start, buf);
|
||||||
if (!amount_msat_sub(&fee, fee, pc->msat))
|
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, &fee),
|
||||||
type_to_string(tmpctx, struct amount_msat, &pc->msat));
|
type_to_string(tmpctx, struct amount_msat, &pc->msat));
|
||||||
|
|
||||||
if (!json_to_number(buf, json_delve(buf, t, "[0].delay"), &delay))
|
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);
|
result->end - result->start, buf);
|
||||||
|
|
||||||
/* Casting u64 to double will lose some precision. The loss of precision
|
/* 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");
|
codetok = json_get_member(buf, error, "code");
|
||||||
if (!json_to_errcode(buf, codetok, &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);
|
error->end - error->start, buf + error->start);
|
||||||
|
|
||||||
/* Strange errors from getroute should be forwarded. */
|
/* Strange errors from getroute should be forwarded. */
|
||||||
@@ -952,12 +960,12 @@ getstartblockheight_done(struct command *cmd,
|
|||||||
|
|
||||||
blockheight_tok = json_get_member(buf, result, "blockheight");
|
blockheight_tok = json_get_member(buf, result, "blockheight");
|
||||||
if (!blockheight_tok)
|
if (!blockheight_tok)
|
||||||
plugin_err("getstartblockheight: "
|
plugin_err(cmd->plugin, "getstartblockheight: "
|
||||||
"getinfo gave no 'blockheight'? '%.*s'",
|
"getinfo gave no 'blockheight'? '%.*s'",
|
||||||
result->end - result->start, buf);
|
result->end - result->start, buf);
|
||||||
|
|
||||||
if (!json_to_u32(buf, blockheight_tok, &blockheight))
|
if (!json_to_u32(buf, blockheight_tok, &blockheight))
|
||||||
plugin_err("getstartblockheight: "
|
plugin_err(cmd->plugin, "getstartblockheight: "
|
||||||
"getinfo gave non-unsigned-32-bit 'blockheight'? '%.*s'",
|
"getinfo gave non-unsigned-32-bit 'blockheight'? '%.*s'",
|
||||||
result->end - result->start, buf);
|
result->end - result->start, buf);
|
||||||
|
|
||||||
@@ -973,7 +981,7 @@ getstartblockheight_error(struct command *cmd,
|
|||||||
struct pay_command *pc)
|
struct pay_command *pc)
|
||||||
{
|
{
|
||||||
/* Should never happen. */
|
/* Should never happen. */
|
||||||
plugin_err("getstartblockheight: getinfo failed!? '%.*s'",
|
plugin_err(cmd->plugin, "getstartblockheight: getinfo failed!? '%.*s'",
|
||||||
error->end - error->start, buf);
|
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");
|
peers = json_get_member(buf, result, "peers");
|
||||||
if (!peers)
|
if (!peers)
|
||||||
plugin_err("listpeers gave no 'peers'? '%.*s'",
|
plugin_err(cmd->plugin, "listpeers gave no 'peers'? '%.*s'",
|
||||||
result->end - result->start, buf);
|
result->end - result->start, buf);
|
||||||
|
|
||||||
json_for_each_arr(i, peer, peers) {
|
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,
|
HTABLE_DEFINE_TYPE(struct pay_mpp, pay_mpp_key, b11str_hash, pay_mpp_eq,
|
||||||
pay_map);
|
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,
|
struct amount_msat *total,
|
||||||
const char *buf,
|
const char *buf,
|
||||||
const jsmntok_t *t)
|
const jsmntok_t *t)
|
||||||
@@ -1534,7 +1543,7 @@ static void add_amount_sent(const char *b11,
|
|||||||
struct amount_msat sent;
|
struct amount_msat sent;
|
||||||
json_to_msat(buf, json_get_member(buf, t, "amount_sent_msat"), &sent);
|
json_to_msat(buf, json_get_member(buf, t, "amount_sent_msat"), &sent);
|
||||||
if (!amount_msat_add(total, *total, 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",
|
"Cannot add amount_sent_msat for %s: %s + %s",
|
||||||
b11,
|
b11,
|
||||||
type_to_string(tmpctx, struct amount_msat, total),
|
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");
|
status = json_get_member(buf, t, "status");
|
||||||
if (json_tok_streq(buf, status, "complete")) {
|
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->num_nonfailed_parts++;
|
||||||
pm->status = "complete";
|
pm->status = "complete";
|
||||||
pm->preimage
|
pm->preimage
|
||||||
= json_get_member(buf, t, "payment_preimage");
|
= json_get_member(buf, t, "payment_preimage");
|
||||||
} else if (json_tok_streq(buf, status, "pending")) {
|
} 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++;
|
pm->num_nonfailed_parts++;
|
||||||
/* Failed -> pending; don't downgrade success. */
|
/* Failed -> pending; don't downgrade success. */
|
||||||
if (!pm->status || !streq(pm->status, "complete"))
|
if (!pm->status || !streq(pm->status, "complete"))
|
||||||
@@ -1674,7 +1685,7 @@ static void init(struct plugin *p,
|
|||||||
field = rpc_delve(tmpctx, p, "getinfo",
|
field = rpc_delve(tmpctx, p, "getinfo",
|
||||||
take(json_out_obj(NULL, NULL, NULL)), ".id");
|
take(json_out_obj(NULL, NULL, NULL)), ".id");
|
||||||
if (!node_id_from_hexstr(field, strlen(field), &my_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",
|
field = rpc_delve(tmpctx, p, "listconfigs",
|
||||||
take(json_out_obj(NULL,
|
take(json_out_obj(NULL,
|
||||||
|
|||||||
Reference in New Issue
Block a user