jsonrpc: declare up front whether a response is success or fail.

Such an API is required for when we stream it directly.  Almost all our
handlers fit this pattern already, or nearly do.

We remove new_json_result() in favor of explicit json_stream_success()
and json_stream_fail(), but still allowing command_fail() if you just
want a simple all-in-one fail wrapper.

Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
This commit is contained in:
Rusty Russell
2018-10-19 11:47:48 +10:30
parent 12adcda370
commit e46ce0fc84
21 changed files with 224 additions and 195 deletions

View File

@@ -483,7 +483,7 @@ static void json_feerates(struct command *cmd,
missing = true; missing = true;
} }
response = new_json_result(cmd); response = json_stream_success(cmd);
json_object_start(response, NULL); json_object_start(response, NULL);
json_object_start(response, json_feerate_style_name(*style)); json_object_start(response, json_feerate_style_name(*style));
for (size_t i = 0; i < ARRAY_SIZE(feerates); i++) { for (size_t i = 0; i < ARRAY_SIZE(feerates); i++) {

View File

@@ -65,7 +65,7 @@ static struct connect *find_connect(struct lightningd *ld,
static void connect_cmd_succeed(struct command *cmd, const struct pubkey *id) static void connect_cmd_succeed(struct command *cmd, const struct pubkey *id)
{ {
struct json_result *response = new_json_result(cmd); struct json_result *response = json_stream_success(cmd);
json_object_start(response, NULL); json_object_start(response, NULL);
json_add_pubkey(response, "id", id); json_add_pubkey(response, "id", id);
json_object_end(response); json_object_end(response);

View File

@@ -182,7 +182,7 @@ static void json_getnodes_reply(struct subd *gossip UNUSED, const u8 *reply,
struct command *cmd) struct command *cmd)
{ {
struct gossip_getnodes_entry **nodes; struct gossip_getnodes_entry **nodes;
struct json_result *response = new_json_result(cmd); struct json_result *response;
size_t i, j; size_t i, j;
if (!fromwire_gossip_getnodes_reply(reply, reply, &nodes)) { if (!fromwire_gossip_getnodes_reply(reply, reply, &nodes)) {
@@ -190,6 +190,7 @@ static void json_getnodes_reply(struct subd *gossip UNUSED, const u8 *reply,
return; return;
} }
response = json_stream_success(cmd);
json_object_start(response, NULL); json_object_start(response, NULL);
json_array_start(response, "nodes"); json_array_start(response, "nodes");
@@ -264,7 +265,7 @@ static void json_getroute_reply(struct subd *gossip UNUSED, const u8 *reply, con
return; return;
} }
response = new_json_result(cmd); response = json_stream_success(cmd);
json_object_start(response, NULL); json_object_start(response, NULL);
json_add_route(response, "route", hops, tal_count(hops)); json_add_route(response, "route", hops, tal_count(hops));
json_object_end(response); json_object_end(response);
@@ -336,13 +337,14 @@ static void json_listchannels_reply(struct subd *gossip UNUSED, const u8 *reply,
{ {
size_t i; size_t i;
struct gossip_getchannels_entry *entries; struct gossip_getchannels_entry *entries;
struct json_result *response = new_json_result(cmd); struct json_result *response;
if (!fromwire_gossip_getchannels_reply(reply, reply, &entries)) { if (!fromwire_gossip_getchannels_reply(reply, reply, &entries)) {
command_fail(cmd, LIGHTNINGD, "Invalid reply from gossipd"); command_fail(cmd, LIGHTNINGD, "Invalid reply from gossipd");
return; return;
} }
response = json_stream_success(cmd);
json_object_start(response, NULL); json_object_start(response, NULL);
json_array_start(response, "channels"); json_array_start(response, "channels");
for (i = 0; i < tal_count(entries); i++) { for (i = 0; i < tal_count(entries); i++) {
@@ -405,7 +407,7 @@ static void json_scids_reply(struct subd *gossip UNUSED, const u8 *reply,
const int *fds UNUSED, struct command *cmd) const int *fds UNUSED, struct command *cmd)
{ {
bool ok, complete; bool ok, complete;
struct json_result *response = new_json_result(cmd); struct json_result *response;
if (!fromwire_gossip_scids_reply(reply, &ok, &complete)) { if (!fromwire_gossip_scids_reply(reply, &ok, &complete)) {
command_fail(cmd, LIGHTNINGD, command_fail(cmd, LIGHTNINGD,
@@ -419,6 +421,7 @@ static void json_scids_reply(struct subd *gossip UNUSED, const u8 *reply,
return; return;
} }
response = json_stream_success(cmd);
json_object_start(response, NULL); json_object_start(response, NULL);
json_add_bool(response, "complete", complete); json_add_bool(response, "complete", complete);
json_object_end(response); json_object_end(response);
@@ -500,7 +503,7 @@ AUTODATA(json_command, &dev_send_timestamp_filter);
static void json_channel_range_reply(struct subd *gossip UNUSED, const u8 *reply, static void json_channel_range_reply(struct subd *gossip UNUSED, const u8 *reply,
const int *fds UNUSED, struct command *cmd) const int *fds UNUSED, struct command *cmd)
{ {
struct json_result *response = new_json_result(cmd); struct json_result *response;
u32 final_first_block, final_num_blocks; u32 final_first_block, final_num_blocks;
bool final_complete; bool final_complete;
struct short_channel_id *scids; struct short_channel_id *scids;
@@ -521,6 +524,7 @@ static void json_channel_range_reply(struct subd *gossip UNUSED, const u8 *reply
return; return;
} }
response = json_stream_success(cmd);
json_object_start(response, NULL); json_object_start(response, NULL);
/* As this is a dev interface, we don't bother saving and /* As this is a dev interface, we don't bother saving and
* returning all the replies, just the final one. */ * returning all the replies, just the final one. */

View File

@@ -64,19 +64,23 @@ static void json_add_invoice(struct json_result *response,
static void tell_waiter(struct command *cmd, const struct invoice *inv) static void tell_waiter(struct command *cmd, const struct invoice *inv)
{ {
struct json_result *response = new_json_result(cmd); struct json_result *response;
const struct invoice_details *details; const struct invoice_details *details;
details = wallet_invoice_details(cmd, cmd->ld->wallet, *inv); details = wallet_invoice_details(cmd, cmd->ld->wallet, *inv);
if (details->state == PAID) {
response = json_stream_success(cmd);
json_add_invoice(response, details); json_add_invoice(response, details);
if (details->state == PAID)
command_success(cmd, response); command_success(cmd, response);
else { } else {
/* FIXME: -2 should be a constant in jsonrpc_errors.h. */ /* FIXME: -2 should be a constant in jsonrpc_errors.h. */
command_fail_detailed(cmd, -2, response, response = json_stream_fail(cmd, -2,
"invoice expired during wait"); "invoice expired during wait");
json_add_invoice(response, details);
command_failed(cmd, response);
} }
} }
static void tell_waiter_deleted(struct command *cmd) static void tell_waiter_deleted(struct command *cmd)
{ {
command_fail(cmd, LIGHTNINGD, "Invoice deleted during wait"); command_fail(cmd, LIGHTNINGD, "Invoice deleted during wait");
@@ -209,7 +213,7 @@ static void gossipd_incoming_channels_reply(struct subd *gossipd,
const int *fs, const int *fs,
struct invoice_info *info) struct invoice_info *info)
{ {
struct json_result *response = new_json_result(info->cmd); struct json_result *response;
struct route_info *inchans; struct route_info *inchans;
bool any_offline; bool any_offline;
struct invoice invoice; struct invoice invoice;
@@ -257,6 +261,7 @@ static void gossipd_incoming_channels_reply(struct subd *gossipd,
/* Get details */ /* Get details */
details = wallet_invoice_details(info, wallet, invoice); details = wallet_invoice_details(info, wallet, invoice);
response = json_stream_success(info->cmd);
json_object_start(response, NULL); json_object_start(response, NULL);
json_add_hex(response, "payment_hash", details->rhash.u.u8, json_add_hex(response, "payment_hash", details->rhash.u.u8,
sizeof(details->rhash)); sizeof(details->rhash));
@@ -413,12 +418,13 @@ static void json_listinvoices(struct command *cmd,
const char *buffer, const jsmntok_t *params) const char *buffer, const jsmntok_t *params)
{ {
struct json_escaped *label; struct json_escaped *label;
struct json_result *response = new_json_result(cmd); struct json_result *response;
struct wallet *wallet = cmd->ld->wallet; struct wallet *wallet = cmd->ld->wallet;
if (!param(cmd, buffer, params, if (!param(cmd, buffer, params,
p_opt("label", json_tok_label, &label), p_opt("label", json_tok_label, &label),
NULL)) NULL))
return; return;
response = json_stream_success(cmd);
json_object_start(response, NULL); json_object_start(response, NULL);
json_array_start(response, "invoices"); json_array_start(response, "invoices");
json_add_invoices(response, wallet, label); json_add_invoices(response, wallet, label);
@@ -439,7 +445,7 @@ static void json_delinvoice(struct command *cmd,
{ {
struct invoice i; struct invoice i;
const struct invoice_details *details; const struct invoice_details *details;
struct json_result *response = new_json_result(cmd); struct json_result *response;
const char *status, *actual_status; const char *status, *actual_status;
struct json_escaped *label; struct json_escaped *label;
struct wallet *wallet = cmd->ld->wallet; struct wallet *wallet = cmd->ld->wallet;
@@ -466,10 +472,6 @@ static void json_delinvoice(struct command *cmd,
return; return;
} }
/* Get invoice details before attempting to delete, as
* otherwise the invoice will be freed. */
json_add_invoice(response, details);
if (!wallet_invoice_delete(wallet, i)) { if (!wallet_invoice_delete(wallet, i)) {
log_broken(cmd->ld->log, log_broken(cmd->ld->log,
"Error attempting to remove invoice %"PRIu64, "Error attempting to remove invoice %"PRIu64,
@@ -478,6 +480,8 @@ static void json_delinvoice(struct command *cmd,
return; return;
} }
response = json_stream_success(cmd);
json_add_invoice(response, details);
command_success(cmd, response); command_success(cmd, response);
} }
@@ -492,7 +496,6 @@ static void json_delexpiredinvoice(struct command *cmd, const char *buffer,
const jsmntok_t *params) const jsmntok_t *params)
{ {
u64 *maxexpirytime; u64 *maxexpirytime;
struct json_result *result;
if (!param(cmd, buffer, params, if (!param(cmd, buffer, params,
p_opt_def("maxexpirytime", json_tok_u64, &maxexpirytime, p_opt_def("maxexpirytime", json_tok_u64, &maxexpirytime,
@@ -502,10 +505,7 @@ static void json_delexpiredinvoice(struct command *cmd, const char *buffer,
wallet_invoice_delete_expired(cmd->ld->wallet, *maxexpirytime); wallet_invoice_delete_expired(cmd->ld->wallet, *maxexpirytime);
result = new_json_result(cmd); command_success(cmd, null_response(cmd));
json_object_start(result, NULL);
json_object_end(result);
command_success(cmd, result);
} }
static const struct json_command delexpiredinvoice_command = { static const struct json_command delexpiredinvoice_command = {
"delexpiredinvoice", "delexpiredinvoice",
@@ -520,7 +520,6 @@ static void json_autocleaninvoice(struct command *cmd,
{ {
u64 *cycle; u64 *cycle;
u64 *exby; u64 *exby;
struct json_result *result;
if (!param(cmd, buffer, params, if (!param(cmd, buffer, params,
p_opt_def("cycle_seconds", json_tok_u64, &cycle, 3600), p_opt_def("cycle_seconds", json_tok_u64, &cycle, 3600),
@@ -530,10 +529,7 @@ static void json_autocleaninvoice(struct command *cmd,
wallet_invoice_autoclean(cmd->ld->wallet, *cycle, *exby); wallet_invoice_autoclean(cmd->ld->wallet, *cycle, *exby);
result = new_json_result(cmd); command_success(cmd, null_response(cmd));
json_object_start(result, NULL);
json_object_end(result);
command_success(cmd, result);
} }
static const struct json_command autocleaninvoice_command = { static const struct json_command autocleaninvoice_command = {
"autocleaninvoice", "autocleaninvoice",
@@ -672,7 +668,7 @@ static void json_decodepay(struct command *cmd,
return; return;
} }
response = new_json_result(cmd); response = json_stream_success(cmd);
json_object_start(response, NULL); json_object_start(response, NULL);
json_add_string(response, "currency", b11->chain->bip173_name); json_add_string(response, "currency", b11->chain->bip173_name);

View File

@@ -703,9 +703,9 @@ void json_add_escaped_string(struct json_result *result, const char *fieldname,
tal_free(esc); tal_free(esc);
} }
struct json_result *new_json_result(const tal_t *ctx) static struct json_result *new_json_stream(struct command *cmd)
{ {
struct json_result *r = tal(ctx, struct json_result); struct json_result *r = tal(cmd, struct json_result);
r->s = tal_strdup(r, ""); r->s = tal_strdup(r, "");
#if DEVELOPER #if DEVELOPER
@@ -713,9 +713,29 @@ struct json_result *new_json_result(const tal_t *ctx)
#endif #endif
r->indent = 0; r->indent = 0;
r->empty = true; r->empty = true;
assert(!cmd->have_json_stream);
cmd->have_json_stream = true;
return r; return r;
} }
struct json_result *json_stream_success(struct command *cmd)
{
cmd->failcode = 0;
return new_json_stream(cmd);
}
struct json_result *json_stream_fail(struct command *cmd,
int code,
const char *errmsg)
{
assert(code);
assert(errmsg);
cmd->failcode = code;
cmd->errmsg = tal_strdup(cmd, errmsg);
return new_json_stream(cmd);
}
const char *json_result_string(const struct json_result *result) const char *json_result_string(const struct json_result *result)
{ {
#if DEVELOPER #if DEVELOPER

View File

@@ -170,7 +170,27 @@ void json_array_end(struct json_result *ptr);
/* ' }, ' */ /* ' }, ' */
void json_object_end(struct json_result *ptr); void json_object_end(struct json_result *ptr);
struct json_result *new_json_result(const tal_t *ctx); /**
* json_stream_success - start streaming a successful json result.
* @cmd: the command we're running.
*
* The returned value should go to command_success() when done.
* json_add_* will be placed into the 'result' field of the JSON reply.
*/
struct json_result *json_stream_success(struct command *cmd);
/**
* json_stream_fail - start streaming a failed json result.
* @cmd: the command we're running.
* @code: the error code from lightningd/jsonrpc_errors.h
* @errmsg: the error string.
*
* The returned value should go to command_failed() when done;
* json_add_* will be placed into the 'data' field of the 'error' JSON reply.
*/
struct json_result *json_stream_fail(struct command *cmd,
int code,
const char *errmsg);
/* '"fieldname" : "value"' or '"value"' if fieldname is NULL. Turns /* '"fieldname" : "value"' or '"value"' if fieldname is NULL. Turns
* any non-printable chars into JSON escapes, but leaves existing escapes alone. * any non-printable chars into JSON escapes, but leaves existing escapes alone.

View File

@@ -73,13 +73,14 @@ AUTODATA(json_command, &help_command);
static void json_stop(struct command *cmd, static void json_stop(struct command *cmd,
const char *buffer UNUSED, const jsmntok_t *params UNUSED) const char *buffer UNUSED, const jsmntok_t *params UNUSED)
{ {
struct json_result *response = new_json_result(cmd); struct json_result *response;
if (!param(cmd, buffer, params, NULL)) if (!param(cmd, buffer, params, NULL))
return; return;
/* This can't have closed yet! */ /* This can't have closed yet! */
cmd->jcon->stop = true; cmd->jcon->stop = true;
response = json_stream_success(cmd);
json_add_string(response, NULL, "Shutting down"); json_add_string(response, NULL, "Shutting down");
command_success(cmd, response); command_success(cmd, response);
} }
@@ -95,7 +96,7 @@ AUTODATA(json_command, &stop_command);
static void json_rhash(struct command *cmd, static void json_rhash(struct command *cmd,
const char *buffer, const jsmntok_t *params) const char *buffer, const jsmntok_t *params)
{ {
struct json_result *response = new_json_result(cmd); struct json_result *response;
struct sha256 *secret; struct sha256 *secret;
if (!param(cmd, buffer, params, if (!param(cmd, buffer, params,
@@ -105,6 +106,7 @@ static void json_rhash(struct command *cmd,
/* Hash in place. */ /* Hash in place. */
sha256(secret, secret, sizeof(*secret)); sha256(secret, secret, sizeof(*secret));
response = json_stream_success(cmd);
json_object_start(response, NULL); json_object_start(response, NULL);
json_add_hex(response, "rhash", secret, sizeof(*secret)); json_add_hex(response, "rhash", secret, sizeof(*secret));
json_object_end(response); json_object_end(response);
@@ -138,11 +140,12 @@ AUTODATA(json_command, &dev_crash_command);
static void json_getinfo(struct command *cmd, static void json_getinfo(struct command *cmd,
const char *buffer UNUSED, const jsmntok_t *params UNUSED) const char *buffer UNUSED, const jsmntok_t *params UNUSED)
{ {
struct json_result *response = new_json_result(cmd); struct json_result *response;
if (!param(cmd, buffer, params, NULL)) if (!param(cmd, buffer, params, NULL))
return; return;
response = json_stream_success(cmd);
json_object_start(response, NULL); json_object_start(response, NULL);
json_add_pubkey(response, "id", &cmd->ld->id); json_add_pubkey(response, "id", &cmd->ld->id);
json_add_string(response, "alias", (const char *)cmd->ld->alias); json_add_string(response, "alias", (const char *)cmd->ld->alias);
@@ -222,7 +225,7 @@ static void json_help(struct command *cmd,
const char *buffer, const jsmntok_t *params) const char *buffer, const jsmntok_t *params)
{ {
unsigned int i; unsigned int i;
struct json_result *response = new_json_result(cmd); struct json_result *response;
struct json_command **cmdlist = get_cmdlist(); struct json_command **cmdlist = get_cmdlist();
const jsmntok_t *cmdtok; const jsmntok_t *cmdtok;
@@ -234,6 +237,7 @@ static void json_help(struct command *cmd,
if (cmdtok) { if (cmdtok) {
for (i = 0; i < num_cmdlist; i++) { for (i = 0; i < num_cmdlist; i++) {
if (json_tok_streq(buffer, cmdtok, cmdlist[i]->name)) { if (json_tok_streq(buffer, cmdtok, cmdlist[i]->name)) {
response = json_stream_success(cmd);
json_add_help_command(cmd, response, cmdlist[i]); json_add_help_command(cmd, response, cmdlist[i]);
goto done; goto done;
} }
@@ -245,6 +249,7 @@ static void json_help(struct command *cmd,
return; return;
} }
response = json_stream_success(cmd);
json_object_start(response, NULL); json_object_start(response, NULL);
json_array_start(response, "help"); json_array_start(response, "help");
for (i = 0; i < num_cmdlist; i++) { for (i = 0; i < num_cmdlist; i++) {
@@ -341,11 +346,11 @@ static void connection_complete_error(struct json_connection *jcon,
id))); id)));
} }
struct json_result *null_response(const tal_t *ctx) struct json_result *null_response(struct command *cmd)
{ {
struct json_result *response; struct json_result *response;
response = new_json_result(ctx); response = json_stream_success(cmd);
json_object_start(response, NULL); json_object_start(response, NULL);
json_object_end(response); json_object_end(response);
return response; return response;
@@ -365,12 +370,11 @@ void command_success(struct command *cmd, struct json_result *result)
connection_complete_ok(jcon, cmd, cmd->id, result); connection_complete_ok(jcon, cmd, cmd->id, result);
} }
static void command_fail_v(struct command *cmd, static void command_fail_generic(struct command *cmd,
int code, int code,
const struct json_result *data, const struct json_result *data,
const char *fmt, va_list ap) const char *error)
{ {
char *error;
struct json_connection *jcon = cmd->jcon; struct json_connection *jcon = cmd->jcon;
if (!jcon) { if (!jcon) {
@@ -381,8 +385,6 @@ static void command_fail_v(struct command *cmd,
return; return;
} }
error = tal_vfmt(cmd, fmt, ap);
/* cmd->json_cmd can be NULL, if we're failing for command not found! */ /* cmd->json_cmd can be NULL, if we're failing for command not found! */
log_debug(jcon->log, "Failing %s: %s", log_debug(jcon->log, "Failing %s: %s",
cmd->json_cmd ? cmd->json_cmd->name : "invalid cmd", cmd->json_cmd ? cmd->json_cmd->name : "invalid cmd",
@@ -392,21 +394,18 @@ static void command_fail_v(struct command *cmd,
connection_complete_error(jcon, cmd, cmd->id, error, code, data); connection_complete_error(jcon, cmd, cmd->id, error, code, data);
} }
void command_fail(struct command *cmd, int code, const char *fmt, ...) void command_failed(struct command *cmd, struct json_result *result)
{ {
va_list ap; assert(cmd->failcode != 0);
va_start(ap, fmt); command_fail_generic(cmd, cmd->failcode, result, cmd->errmsg);
command_fail_v(cmd, code, NULL, fmt, ap);
va_end(ap);
} }
void command_fail_detailed(struct command *cmd, void PRINTF_FMT(3, 4) command_fail(struct command *cmd, int code,
int code, const struct json_result *data,
const char *fmt, ...) const char *fmt, ...)
{ {
va_list ap; va_list ap;
va_start(ap, fmt); va_start(ap, fmt);
command_fail_v(cmd, code, data, fmt, ap); command_fail_generic(cmd, code, NULL, tal_vfmt(cmd, fmt, ap));
va_end(ap); va_end(ap);
} }
@@ -457,6 +456,7 @@ static bool parse_request(struct json_connection *jcon, const jsmntok_t tok[])
c->jcon = jcon; c->jcon = jcon;
c->ld = jcon->ld; c->ld = jcon->ld;
c->pending = false; c->pending = false;
c->have_json_stream = false;
c->id = tal_strndup(c, c->id = tal_strndup(c,
json_tok_contents(jcon->buffer, id), json_tok_contents(jcon->buffer, id),
json_tok_len(id)); json_tok_len(id));

View File

@@ -38,6 +38,12 @@ struct command {
/* This is created if mode is CMD_USAGE */ /* This is created if mode is CMD_USAGE */
const char *usage; const char *usage;
bool *ok; bool *ok;
/* Have we started a json stream already? For debugging. */
bool have_json_stream;
/* FIXME: Temporary. */
int failcode;
const char *errmsg;
}; };
struct json_connection { struct json_connection {
@@ -79,14 +85,11 @@ struct json_command {
const char *verbose; const char *verbose;
}; };
struct json_result *null_response(const tal_t *ctx); struct json_result *null_response(struct command *cmd);
void command_success(struct command *cmd, struct json_result *response); void command_success(struct command *cmd, struct json_result *response);
void command_failed(struct command *cmd, struct json_result *result);
void PRINTF_FMT(3, 4) command_fail(struct command *cmd, int code, void PRINTF_FMT(3, 4) command_fail(struct command *cmd, int code,
const char *fmt, ...); const char *fmt, ...);
void PRINTF_FMT(4, 5) command_fail_detailed(struct command *cmd,
int code,
const struct json_result *data,
const char *fmt, ...);
/* Mainly for documentation, that we plan to close this later. */ /* Mainly for documentation, that we plan to close this later. */
void command_still_pending(struct command *cmd); void command_still_pending(struct command *cmd);

View File

@@ -718,7 +718,7 @@ bool json_tok_loglevel(struct command *cmd, const char *name,
static void json_getlog(struct command *cmd, static void json_getlog(struct command *cmd,
const char *buffer, const jsmntok_t * params) const char *buffer, const jsmntok_t * params)
{ {
struct json_result *response = new_json_result(cmd); struct json_result *response;
enum log_level *minlevel; enum log_level *minlevel;
struct log_book *lr = cmd->ld->log_book; struct log_book *lr = cmd->ld->log_book;
@@ -728,6 +728,7 @@ static void json_getlog(struct command *cmd,
NULL)) NULL))
return; return;
response = json_stream_success(cmd);
json_object_start(response, NULL); json_object_start(response, NULL);
json_add_time(response, "created_at", log_init_time(lr)->ts); json_add_time(response, "created_at", log_init_time(lr)->ts);
json_add_num(response, "bytes_used", (unsigned int) log_used(lr)); json_add_num(response, "bytes_used", (unsigned int) log_used(lr));

View File

@@ -56,11 +56,12 @@ static void json_memdump(struct command *cmd,
const char *buffer UNNEEDED, const char *buffer UNNEEDED,
const jsmntok_t *params UNNEEDED) const jsmntok_t *params UNNEEDED)
{ {
struct json_result *response = new_json_result(cmd); struct json_result *response;
if (!param(cmd, buffer, params, NULL)) if (!param(cmd, buffer, params, NULL))
return; return;
response = json_stream_success(cmd);
add_memdump(response, NULL, NULL, cmd); add_memdump(response, NULL, NULL, cmd);
command_success(cmd, response); command_success(cmd, response);
@@ -153,7 +154,7 @@ static void json_memleak(struct command *cmd,
const char *buffer UNNEEDED, const char *buffer UNNEEDED,
const jsmntok_t *params UNNEEDED) const jsmntok_t *params UNNEEDED)
{ {
struct json_result *response = new_json_result(cmd); struct json_result *response;
if (!param(cmd, buffer, params, NULL)) if (!param(cmd, buffer, params, NULL))
return; return;
@@ -164,6 +165,7 @@ static void json_memleak(struct command *cmd,
return; return;
} }
response = json_stream_success(cmd);
json_object_start(response, NULL); json_object_start(response, NULL);
scan_mem(cmd, response, cmd->ld); scan_mem(cmd, response, cmd->ld);
json_object_end(response); json_object_end(response);

View File

@@ -377,7 +377,7 @@ static void opening_funder_finished(struct subd *openingd, const u8 *resp,
wallet_confirm_utxos(ld->wallet, fc->wtx.utxos); wallet_confirm_utxos(ld->wallet, fc->wtx.utxos);
response = new_json_result(fc->cmd); response = json_stream_success(fc->cmd);
json_object_start(response, NULL); json_object_start(response, NULL);
linear = linearize_tx(response, fundingtx); linear = linearize_tx(response, fundingtx);
json_add_hex_talarr(response, "tx", linear); json_add_hex_talarr(response, "tx", linear);

View File

@@ -978,18 +978,19 @@ static void json_listconfigs(struct command *cmd,
const char *buffer, const jsmntok_t *params) const char *buffer, const jsmntok_t *params)
{ {
size_t i; size_t i;
struct json_result *response = new_json_result(cmd); struct json_result *response = NULL;
const jsmntok_t *configtok; const jsmntok_t *configtok;
bool found = false;
if (!param(cmd, buffer, params, if (!param(cmd, buffer, params,
p_opt("config", json_tok_tok, &configtok), p_opt("config", json_tok_tok, &configtok),
NULL)) NULL))
return; return;
if (!configtok) {
response = json_stream_success(cmd);
json_object_start(response, NULL); json_object_start(response, NULL);
if (!configtok)
json_add_string(response, "# version", version()); json_add_string(response, "# version", version());
}
for (i = 0; i < opt_count; i++) { for (i = 0; i < opt_count; i++) {
unsigned int len; unsigned int len;
@@ -1012,20 +1013,23 @@ static void json_listconfigs(struct command *cmd,
name + 1, len - 1)) name + 1, len - 1))
continue; continue;
found = true; if (!response) {
response = json_stream_success(cmd);
json_object_start(response, NULL);
}
add_config(cmd->ld, response, &opt_table[i], add_config(cmd->ld, response, &opt_table[i],
name+1, len-1); name+1, len-1);
} }
} }
json_object_end(response);
if (configtok && !found) { if (configtok && !response) {
command_fail(cmd, JSONRPC2_INVALID_PARAMS, command_fail(cmd, JSONRPC2_INVALID_PARAMS,
"Unknown config option '%.*s'", "Unknown config option '%.*s'",
configtok->end - configtok->start, configtok->end - configtok->start,
buffer + configtok->start); buffer + configtok->start);
return; return;
} }
json_object_end(response);
command_success(cmd, response); command_success(cmd, response);
} }

View File

@@ -851,7 +851,7 @@ json_sendpay_success(struct command *cmd,
assert(r->payment->status == PAYMENT_COMPLETE); assert(r->payment->status == PAYMENT_COMPLETE);
response = new_json_result(cmd); response = json_stream_success(cmd);
json_object_start(response, NULL); json_object_start(response, NULL);
json_add_payment_fields(response, r->payment); json_add_payment_fields(response, r->payment);
json_object_end(response); json_object_end(response);
@@ -863,13 +863,13 @@ static void json_waitsendpay_on_resolve(const struct sendpay_result *r,
{ {
struct command *cmd = (struct command*) vcmd; struct command *cmd = (struct command*) vcmd;
struct json_result *data = NULL;
const char *msg = NULL; const char *msg = NULL;
struct routing_failure *fail; struct routing_failure *fail;
if (r->succeeded) if (r->succeeded)
json_sendpay_success(cmd, r); json_sendpay_success(cmd, r);
else { else {
struct json_result *data;
switch (r->errorcode) { switch (r->errorcode) {
/* We will never handle this case */ /* We will never handle this case */
case PAY_IN_PROGRESS: case PAY_IN_PROGRESS:
@@ -878,28 +878,30 @@ static void json_waitsendpay_on_resolve(const struct sendpay_result *r,
case PAY_RHASH_ALREADY_USED: case PAY_RHASH_ALREADY_USED:
case PAY_UNSPECIFIED_ERROR: case PAY_UNSPECIFIED_ERROR:
case PAY_NO_SUCH_PAYMENT: case PAY_NO_SUCH_PAYMENT:
data = NULL; command_fail(cmd, r->errorcode, "%s", r->details);
msg = r->details; return;
break;
case PAY_UNPARSEABLE_ONION: case PAY_UNPARSEABLE_ONION:
data = new_json_result(cmd); msg = tal_fmt(tmpctx,
json_object_start(data, NULL);
json_add_hex_talarr(data, "onionreply", r->onionreply);
json_object_end(data);
assert(r->details != NULL);
msg = tal_fmt(cmd,
"failed: WIRE_PERMANENT_NODE_FAILURE " "failed: WIRE_PERMANENT_NODE_FAILURE "
"(%s)", "(%s)",
r->details); r->details);
break; data = json_stream_fail(cmd, r->errorcode, msg);
json_object_start(data, NULL);
json_add_hex_talarr(data, "onionreply", r->onionreply);
json_object_end(data);
command_failed(cmd, data);
return;
case PAY_DESTINATION_PERM_FAIL: case PAY_DESTINATION_PERM_FAIL:
case PAY_TRY_OTHER_ROUTE: case PAY_TRY_OTHER_ROUTE:
fail = r->routing_failure; fail = r->routing_failure;
data = new_json_result(cmd); msg = tal_fmt(cmd,
"failed: %s (%s)",
onion_type_name(fail->failcode),
r->details);
data = json_stream_fail(cmd, r->errorcode, msg);
json_object_start(data, NULL); json_object_start(data, NULL);
json_add_num(data, "erring_index", json_add_num(data, "erring_index",
@@ -913,18 +915,10 @@ static void json_waitsendpay_on_resolve(const struct sendpay_result *r,
json_add_hex_talarr(data, "channel_update", json_add_hex_talarr(data, "channel_update",
fail->channel_update); fail->channel_update);
json_object_end(data); json_object_end(data);
command_failed(cmd, data);
assert(r->details != NULL); return;
msg = tal_fmt(cmd,
"failed: %s (%s)",
onion_type_name(fail->failcode),
r->details);
break;
} }
abort();
assert(msg);
command_fail_detailed(cmd, r->errorcode, data, "%s", msg);
} }
} }
@@ -935,7 +929,7 @@ static void json_sendpay_on_resolve(const struct sendpay_result* r,
if (!r->succeeded && r->errorcode == PAY_IN_PROGRESS) { if (!r->succeeded && r->errorcode == PAY_IN_PROGRESS) {
/* This is normal for sendpay. Succeed. */ /* This is normal for sendpay. Succeed. */
struct json_result *response = new_json_result(cmd); struct json_result *response = json_stream_success(cmd);
json_object_start(response, NULL); json_object_start(response, NULL);
json_add_string(response, "message", json_add_string(response, "message",
"Monitor status with listpayments or waitsendpay"); "Monitor status with listpayments or waitsendpay");
@@ -1064,7 +1058,7 @@ static void json_listpayments(struct command *cmd, const char *buffer,
const jsmntok_t *params) const jsmntok_t *params)
{ {
const struct wallet_payment **payments; const struct wallet_payment **payments;
struct json_result *response = new_json_result(cmd); struct json_result *response;
struct sha256 *rhash; struct sha256 *rhash;
const char *b11str; const char *b11str;
@@ -1096,6 +1090,7 @@ static void json_listpayments(struct command *cmd, const char *buffer,
payments = wallet_payment_list(cmd, cmd->ld->wallet, rhash); payments = wallet_payment_list(cmd, cmd->ld->wallet, rhash);
response = json_stream_success(cmd);
json_object_start(response, NULL); json_object_start(response, NULL);
json_array_start(response, "payments"); json_array_start(response, "payments");

View File

@@ -196,7 +196,7 @@ json_pay_success(struct pay *pay,
struct command *cmd = pay->cmd; struct command *cmd = pay->cmd;
struct json_result *response; struct json_result *response;
response = new_json_result(cmd); response = json_stream_success(cmd);
json_object_start(response, NULL); json_object_start(response, NULL);
json_add_payment_fields(response, r->payment); json_add_payment_fields(response, r->payment);
json_add_num(response, "getroute_tries", pay->getroute_tries); json_add_num(response, "getroute_tries", pay->getroute_tries);
@@ -212,42 +212,44 @@ static void json_pay_failure(struct pay *pay,
const struct sendpay_result *r) const struct sendpay_result *r)
{ {
struct json_result *data; struct json_result *data;
const char *msg = NULL;
struct routing_failure *fail; struct routing_failure *fail;
assert(!r->succeeded); assert(!r->succeeded);
data = new_json_result(pay);
switch (r->errorcode) { switch (r->errorcode) {
case PAY_IN_PROGRESS: case PAY_IN_PROGRESS:
data = json_stream_fail(pay->cmd, r->errorcode, r->details);
json_object_start(data, NULL); json_object_start(data, NULL);
json_add_num(data, "getroute_tries", pay->getroute_tries); json_add_num(data, "getroute_tries", pay->getroute_tries);
json_add_num(data, "sendpay_tries", pay->sendpay_tries); json_add_num(data, "sendpay_tries", pay->sendpay_tries);
json_add_payment_fields(data, r->payment); json_add_payment_fields(data, r->payment);
json_add_failures(data, "failures", &pay->pay_failures); json_add_failures(data, "failures", &pay->pay_failures);
json_object_end(data); json_object_end(data);
msg = r->details; return;
break;
case PAY_RHASH_ALREADY_USED: case PAY_RHASH_ALREADY_USED:
case PAY_STOPPED_RETRYING: case PAY_STOPPED_RETRYING:
data = json_stream_fail(pay->cmd, r->errorcode, r->details);
json_object_start(data, NULL); json_object_start(data, NULL);
json_add_num(data, "getroute_tries", pay->getroute_tries); json_add_num(data, "getroute_tries", pay->getroute_tries);
json_add_num(data, "sendpay_tries", pay->sendpay_tries); json_add_num(data, "sendpay_tries", pay->sendpay_tries);
json_add_failures(data, "failures", &pay->pay_failures); json_add_failures(data, "failures", &pay->pay_failures);
json_object_end(data); json_object_end(data);
msg = r->details; return;
break;
case PAY_UNPARSEABLE_ONION: case PAY_UNPARSEABLE_ONION:
/* Impossible case */ /* Impossible case */
abort(); abort();
break;
case PAY_DESTINATION_PERM_FAIL: case PAY_DESTINATION_PERM_FAIL:
fail = r->routing_failure; fail = r->routing_failure;
assert(r->details != NULL);
data = json_stream_fail(pay->cmd,
r->errorcode,
tal_fmt(tmpctx, "failed: %s (%s)",
onion_type_name(fail->failcode),
r->details));
json_object_start(data, NULL); json_object_start(data, NULL);
json_add_num(data, "erring_index", json_add_num(data, "erring_index",
fail->erring_index); fail->erring_index);
@@ -261,23 +263,14 @@ static void json_pay_failure(struct pay *pay,
fail->channel_update); fail->channel_update);
json_add_failures(data, "failures", &pay->pay_failures); json_add_failures(data, "failures", &pay->pay_failures);
json_object_end(data); json_object_end(data);
return;
assert(r->details != NULL);
msg = tal_fmt(pay,
"failed: %s (%s)",
onion_type_name(fail->failcode),
r->details);
break;
case PAY_TRY_OTHER_ROUTE: case PAY_TRY_OTHER_ROUTE:
/* Impossible case */ /* Impossible case */
abort(); abort();
break; return;
} }
abort();
assert(msg);
command_fail_detailed(pay->cmd, r->errorcode, data, "%s", msg);
} }
/* Determine if we should delay before retrying. Return a reason /* Determine if we should delay before retrying. Return a reason
@@ -422,14 +415,14 @@ static void json_pay_getroute_reply(struct subd *gossip UNUSED,
fromwire_gossip_getroute_reply(reply, reply, &route); fromwire_gossip_getroute_reply(reply, reply, &route);
if (tal_count(route) == 0) { if (tal_count(route) == 0) {
data = new_json_result(pay); data = json_stream_fail(pay->cmd, PAY_ROUTE_NOT_FOUND,
"Could not find a route");
json_object_start(data, NULL); json_object_start(data, NULL);
json_add_num(data, "getroute_tries", pay->getroute_tries); json_add_num(data, "getroute_tries", pay->getroute_tries);
json_add_num(data, "sendpay_tries", pay->sendpay_tries); json_add_num(data, "sendpay_tries", pay->sendpay_tries);
json_add_failures(data, "failures", &pay->pay_failures); json_add_failures(data, "failures", &pay->pay_failures);
json_object_end(data); json_object_end(data);
command_fail_detailed(pay->cmd, PAY_ROUTE_NOT_FOUND, data, command_failed(pay->cmd, data);
"Could not find a route");
return; return;
} }
@@ -444,21 +437,6 @@ static void json_pay_getroute_reply(struct subd *gossip UNUSED,
delay_too_high = (route[0].delay > pay->maxdelay); delay_too_high = (route[0].delay > pay->maxdelay);
/* compare fuzz to range */ /* compare fuzz to range */
if ((fee_too_high || delay_too_high) && pay->fuzz < 0.01) { if ((fee_too_high || delay_too_high) && pay->fuzz < 0.01) {
data = new_json_result(pay);
json_object_start(data, NULL);
json_add_u64(data, "msatoshi", pay->msatoshi);
json_add_u64(data, "fee", fee);
json_add_double(data, "feepercent", feepercent);
json_add_double(data, "maxfeepercent", pay->maxfeepercent);
json_add_u64(data, "delay", (u64) route[0].delay);
json_add_num(data, "maxdelay", pay->maxdelay);
json_add_num(data, "getroute_tries", pay->getroute_tries);
json_add_num(data, "sendpay_tries", pay->sendpay_tries);
json_add_route(data, "route",
route, tal_count(route));
json_add_failures(data, "failures", &pay->pay_failures);
json_object_end(data);
err = ""; err = "";
if (fee_too_high) if (fee_too_high)
err = tal_fmt(pay, err = tal_fmt(pay,
@@ -477,9 +455,22 @@ static void json_pay_getroute_reply(struct subd *gossip UNUSED,
"max delay requested is %u.", "max delay requested is %u.",
err, route[0].delay, pay->maxdelay); err, route[0].delay, pay->maxdelay);
data = json_stream_fail(pay->cmd, PAY_ROUTE_TOO_EXPENSIVE, err);
json_object_start(data, NULL);
json_add_u64(data, "msatoshi", pay->msatoshi);
json_add_u64(data, "fee", fee);
json_add_double(data, "feepercent", feepercent);
json_add_double(data, "maxfeepercent", pay->maxfeepercent);
json_add_u64(data, "delay", (u64) route[0].delay);
json_add_num(data, "maxdelay", pay->maxdelay);
json_add_num(data, "getroute_tries", pay->getroute_tries);
json_add_num(data, "sendpay_tries", pay->sendpay_tries);
json_add_route(data, "route",
route, tal_count(route));
json_add_failures(data, "failures", &pay->pay_failures);
json_object_end(data);
command_fail_detailed(pay->cmd, PAY_ROUTE_TOO_EXPENSIVE, command_failed(pay->cmd, data);
data, "%s", err);
return; return;
} }
if (fee_too_high || delay_too_high) { if (fee_too_high || delay_too_high) {
@@ -519,7 +510,9 @@ static bool json_pay_try(struct pay *pay)
/* If too late anyway, fail now. */ /* If too late anyway, fail now. */
if (time_after(now, pay->expiry)) { if (time_after(now, pay->expiry)) {
struct json_result *data = new_json_result(cmd); struct json_result *data
= json_stream_fail(cmd, PAY_INVOICE_EXPIRED,
"Invoice expired");
json_object_start(data, NULL); json_object_start(data, NULL);
json_add_num(data, "now", now.ts.tv_sec); json_add_num(data, "now", now.ts.tv_sec);
json_add_num(data, "expiry", pay->expiry.ts.tv_sec); json_add_num(data, "expiry", pay->expiry.ts.tv_sec);
@@ -527,8 +520,7 @@ static bool json_pay_try(struct pay *pay)
json_add_num(data, "sendpay_tries", pay->sendpay_tries); json_add_num(data, "sendpay_tries", pay->sendpay_tries);
json_add_failures(data, "failures", &pay->pay_failures); json_add_failures(data, "failures", &pay->pay_failures);
json_object_end(data); json_object_end(data);
command_fail_detailed(cmd, PAY_INVOICE_EXPIRED, data, command_failed(cmd, data);
"Invoice expired");
return false; return false;
} }

View File

@@ -232,7 +232,7 @@ static void remove_sig(struct bitcoin_tx *signed_tx)
static void static void
resolve_one_close_command(struct close_command *cc, bool cooperative) resolve_one_close_command(struct close_command *cc, bool cooperative)
{ {
struct json_result *result = new_json_result(cc); struct json_result *result = json_stream_success(cc->cmd);
u8 *tx = linearize_tx(result, cc->channel->last_tx); u8 *tx = linearize_tx(result, cc->channel->last_tx);
struct bitcoin_txid txid; struct bitcoin_txid txid;
@@ -818,7 +818,7 @@ static void json_listpeers(struct command *cmd,
enum log_level *ll; enum log_level *ll;
struct pubkey *specific_id; struct pubkey *specific_id;
struct peer *peer; struct peer *peer;
struct json_result *response = new_json_result(cmd); struct json_result *response;
if (!param(cmd, buffer, params, if (!param(cmd, buffer, params,
p_opt("id", json_tok_pubkey, &specific_id), p_opt("id", json_tok_pubkey, &specific_id),
@@ -826,6 +826,7 @@ static void json_listpeers(struct command *cmd,
NULL)) NULL))
return; return;
response = json_stream_success(cmd);
json_object_start(response, NULL); json_object_start(response, NULL);
json_array_start(response, "peers"); json_array_start(response, "peers");
if (specific_id) { if (specific_id) {
@@ -1083,7 +1084,7 @@ static void json_sign_last_tx(struct command *cmd,
{ {
struct pubkey *peerid; struct pubkey *peerid;
struct peer *peer; struct peer *peer;
struct json_result *response = new_json_result(cmd); struct json_result *response;
u8 *linear; u8 *linear;
struct channel *channel; struct channel *channel;
@@ -1105,6 +1106,7 @@ static void json_sign_last_tx(struct command *cmd,
return; return;
} }
response = json_stream_success(cmd);
log_debug(channel->log, "dev-sign-last-tx: signing tx with %zu outputs", log_debug(channel->log, "dev-sign-last-tx: signing tx with %zu outputs",
tal_count(channel->last_tx->output)); tal_count(channel->last_tx->output));
sign_last_tx(channel); sign_last_tx(channel);
@@ -1244,7 +1246,7 @@ static void process_dev_forget_channel(struct bitcoind *bitcoind UNUSED,
"channel"); "channel");
return; return;
} }
response = new_json_result(forget->cmd); response = json_stream_success(forget->cmd);
json_object_start(response, NULL); json_object_start(response, NULL);
json_add_bool(response, "forced", forget->force); json_add_bool(response, "forced", forget->force);
json_add_bool(response, "funding_unspent", txout != NULL); json_add_bool(response, "funding_unspent", txout != NULL);

View File

@@ -69,7 +69,7 @@ void ping_reply(struct subd *subd, const u8 *msg)
else if (!sent) else if (!sent)
command_fail(pc->cmd, LIGHTNINGD, "Unknown peer"); command_fail(pc->cmd, LIGHTNINGD, "Unknown peer");
else { else {
struct json_result *response = new_json_result(pc->cmd); struct json_result *response = json_stream_success(pc->cmd);
json_object_start(response, NULL); json_object_start(response, NULL);
json_add_num(response, "totlen", totlen); json_add_num(response, "totlen", totlen);

View File

@@ -48,12 +48,9 @@ bool channel_tell_funding_locked(struct lightningd *ld UNNEEDED,
void command_fail(struct command *cmd UNNEEDED, int code UNNEEDED, void command_fail(struct command *cmd UNNEEDED, int code UNNEEDED,
const char *fmt UNNEEDED, ...) const char *fmt UNNEEDED, ...)
{ fprintf(stderr, "command_fail called!\n"); abort(); } { fprintf(stderr, "command_fail called!\n"); abort(); }
/* Generated stub for command_fail_detailed */ /* Generated stub for command_failed */
void command_fail_detailed(struct command *cmd UNNEEDED, void command_failed(struct command *cmd UNNEEDED, struct json_result *result UNNEEDED)
int code UNNEEDED, { fprintf(stderr, "command_failed called!\n"); abort(); }
const struct json_result *data UNNEEDED,
const char *fmt UNNEEDED, ...)
{ fprintf(stderr, "command_fail_detailed called!\n"); abort(); }
/* Generated stub for command_still_pending */ /* Generated stub for command_still_pending */
void command_still_pending(struct command *cmd UNNEEDED) void command_still_pending(struct command *cmd UNNEEDED)
{ fprintf(stderr, "command_still_pending called!\n"); abort(); } { fprintf(stderr, "command_still_pending called!\n"); abort(); }
@@ -162,6 +159,14 @@ void json_object_end(struct json_result *ptr UNNEEDED)
/* Generated stub for json_object_start */ /* Generated stub for json_object_start */
void json_object_start(struct json_result *ptr UNNEEDED, const char *fieldname UNNEEDED) void json_object_start(struct json_result *ptr UNNEEDED, const char *fieldname UNNEEDED)
{ fprintf(stderr, "json_object_start called!\n"); abort(); } { fprintf(stderr, "json_object_start called!\n"); abort(); }
/* Generated stub for json_stream_fail */
struct json_result *json_stream_fail(struct command *cmd UNNEEDED,
int code UNNEEDED,
const char *errmsg UNNEEDED)
{ fprintf(stderr, "json_stream_fail called!\n"); abort(); }
/* Generated stub for json_stream_success */
struct json_result *json_stream_success(struct command *cmd UNNEEDED)
{ fprintf(stderr, "json_stream_success called!\n"); abort(); }
/* Generated stub for json_tok_address_scriptpubkey */ /* Generated stub for json_tok_address_scriptpubkey */
enum address_parse_result json_tok_address_scriptpubkey(const tal_t *ctx UNNEEDED, enum address_parse_result json_tok_address_scriptpubkey(const tal_t *ctx UNNEEDED,
const struct chainparams *chainparams UNNEEDED, const struct chainparams *chainparams UNNEEDED,
@@ -258,9 +263,6 @@ void log_io(struct log *log UNNEEDED, enum log_level dir UNNEEDED, const char *c
/* Generated stub for new_bolt11 */ /* Generated stub for new_bolt11 */
struct bolt11 *new_bolt11(const tal_t *ctx UNNEEDED, u64 *msatoshi UNNEEDED) struct bolt11 *new_bolt11(const tal_t *ctx UNNEEDED, u64 *msatoshi UNNEEDED)
{ fprintf(stderr, "new_bolt11 called!\n"); abort(); } { fprintf(stderr, "new_bolt11 called!\n"); abort(); }
/* Generated stub for new_json_result */
struct json_result *new_json_result(const tal_t *ctx UNNEEDED)
{ fprintf(stderr, "new_json_result called!\n"); abort(); }
/* Generated stub for new_log */ /* Generated stub for new_log */
struct log *new_log(const tal_t *ctx UNNEEDED, struct log_book *record UNNEEDED, const char *fmt UNNEEDED, ...) struct log *new_log(const tal_t *ctx UNNEEDED, struct log_book *record UNNEEDED, const char *fmt UNNEEDED, ...)
{ fprintf(stderr, "new_log called!\n"); abort(); } { fprintf(stderr, "new_log called!\n"); abort(); }
@@ -275,7 +277,7 @@ struct oneshot *new_reltimer_(struct timers *timers UNNEEDED,
void (*cb)(void *) UNNEEDED, void *arg UNNEEDED) void (*cb)(void *) UNNEEDED, void *arg UNNEEDED)
{ fprintf(stderr, "new_reltimer_ called!\n"); abort(); } { fprintf(stderr, "new_reltimer_ called!\n"); abort(); }
/* Generated stub for null_response */ /* Generated stub for null_response */
struct json_result *null_response(const tal_t *ctx UNNEEDED) struct json_result *null_response(struct command *cmd UNNEEDED)
{ fprintf(stderr, "null_response called!\n"); abort(); } { fprintf(stderr, "null_response called!\n"); abort(); }
/* Generated stub for onchaind_funding_spent */ /* Generated stub for onchaind_funding_spent */
enum watch_result onchaind_funding_spent(struct channel *channel UNNEEDED, enum watch_result onchaind_funding_spent(struct channel *channel UNNEEDED,

View File

@@ -70,7 +70,8 @@ bool deprecated_apis;
static int test_json_filter(void) static int test_json_filter(void)
{ {
struct json_result *result = new_json_result(NULL); struct command *cmd = talz(NULL, struct command);
struct json_result *result = json_stream_success(cmd);
jsmntok_t *toks; jsmntok_t *toks;
const jsmntok_t *x; const jsmntok_t *x;
bool valid; bool valid;
@@ -105,7 +106,7 @@ static int test_json_filter(void)
assert((unsigned)str[i] >= ' '); assert((unsigned)str[i] >= ' ');
assert((unsigned)str[i] != 127); assert((unsigned)str[i] != 127);
} }
tal_free(result); tal_free(cmd);
return 0; return 0;
} }
@@ -115,7 +116,8 @@ static void test_json_escape(void)
for (i = 1; i < 256; i++) { for (i = 1; i < 256; i++) {
char badstr[2]; char badstr[2];
struct json_result *result = new_json_result(NULL); struct command *cmd = talz(NULL, struct command);
struct json_result *result = json_stream_success(cmd);
struct json_escaped *esc; struct json_escaped *esc;
badstr[0] = i; badstr[0] = i;
@@ -138,7 +140,7 @@ static void test_json_escape(void)
expect[11] = i; expect[11] = i;
assert(streq(str, expect)); assert(streq(str, expect));
} }
tal_free(result); tal_free(cmd);
} }
} }

View File

@@ -30,18 +30,6 @@ void command_fail(struct command *cmd, int code, const char *fmt, ...)
va_end(ap); va_end(ap);
} }
void command_fail_detailed(struct command *cmd, int code,
const struct json_result *data, const char *fmt, ...)
{
failed = true;
va_list ap;
va_start(ap, fmt);
fail_msg = tal_vfmt(cmd, fmt, ap);
fail_msg =
tal_fmt(cmd, "%s data: %s", fail_msg, json_result_string(data));
va_end(ap);
}
/* AUTOGENERATED MOCKS START */ /* AUTOGENERATED MOCKS START */
/* Generated stub for feerate_from_style */ /* Generated stub for feerate_from_style */
u32 feerate_from_style(u32 feerate UNNEEDED, enum feerate_style style UNNEEDED) u32 feerate_from_style(u32 feerate UNNEEDED, enum feerate_style style UNNEEDED)

View File

@@ -234,6 +234,9 @@ void json_object_end(struct json_result *ptr UNNEEDED)
/* Generated stub for json_object_start */ /* Generated stub for json_object_start */
void json_object_start(struct json_result *ptr UNNEEDED, const char *fieldname UNNEEDED) void json_object_start(struct json_result *ptr UNNEEDED, const char *fieldname UNNEEDED)
{ fprintf(stderr, "json_object_start called!\n"); abort(); } { fprintf(stderr, "json_object_start called!\n"); abort(); }
/* Generated stub for json_stream_success */
struct json_result *json_stream_success(struct command *cmd UNNEEDED)
{ fprintf(stderr, "json_stream_success called!\n"); abort(); }
/* Generated stub for json_tok_bool */ /* Generated stub for json_tok_bool */
bool json_tok_bool(struct command *cmd UNNEEDED, const char *name UNNEEDED, bool json_tok_bool(struct command *cmd UNNEEDED, const char *name UNNEEDED,
const char *buffer UNNEEDED, const jsmntok_t *tok UNNEEDED, const char *buffer UNNEEDED, const jsmntok_t *tok UNNEEDED,
@@ -287,11 +290,8 @@ void log_add(struct log *log UNNEEDED, const char *fmt UNNEEDED, ...)
void log_io(struct log *log UNNEEDED, enum log_level dir UNNEEDED, const char *comment UNNEEDED, void log_io(struct log *log UNNEEDED, enum log_level dir UNNEEDED, const char *comment UNNEEDED,
const void *data UNNEEDED, size_t len UNNEEDED) const void *data UNNEEDED, size_t len UNNEEDED)
{ fprintf(stderr, "log_io called!\n"); abort(); } { fprintf(stderr, "log_io called!\n"); abort(); }
/* Generated stub for new_json_result */
struct json_result *new_json_result(const tal_t *ctx UNNEEDED)
{ fprintf(stderr, "new_json_result called!\n"); abort(); }
/* Generated stub for null_response */ /* Generated stub for null_response */
struct json_result *null_response(const tal_t *ctx UNNEEDED) struct json_result *null_response(struct command *cmd UNNEEDED)
{ fprintf(stderr, "null_response called!\n"); abort(); } { fprintf(stderr, "null_response called!\n"); abort(); }
/* Generated stub for onchaind_funding_spent */ /* Generated stub for onchaind_funding_spent */
enum watch_result onchaind_funding_spent(struct channel *channel UNNEEDED, enum watch_result onchaind_funding_spent(struct channel *channel UNNEEDED,

View File

@@ -65,7 +65,7 @@ static void wallet_withdrawal_broadcast(struct bitcoind *bitcoind UNUSED,
* not if we're actually making a payment to ourselves! */ * not if we're actually making a payment to ourselves! */
assert(change_satoshi >= withdraw->wtx.change); assert(change_satoshi >= withdraw->wtx.change);
struct json_result *response = new_json_result(cmd); struct json_result *response = json_stream_success(cmd);
json_object_start(response, NULL); json_object_start(response, NULL);
json_add_string(response, "tx", withdraw->hextx); json_add_string(response, "tx", withdraw->hextx);
json_add_string(response, "txid", output); json_add_string(response, "txid", output);
@@ -242,7 +242,7 @@ static bool json_tok_newaddr(struct command *cmd, const char *name,
static void json_newaddr(struct command *cmd, const char *buffer UNUSED, static void json_newaddr(struct command *cmd, const char *buffer UNUSED,
const jsmntok_t *params UNUSED) const jsmntok_t *params UNUSED)
{ {
struct json_result *response = new_json_result(cmd); struct json_result *response;
struct ext_key ext; struct ext_key ext;
struct pubkey pubkey; struct pubkey pubkey;
bool *is_p2wpkh; bool *is_p2wpkh;
@@ -283,6 +283,7 @@ static void json_newaddr(struct command *cmd, const char *buffer UNUSED,
return; return;
} }
response = json_stream_success(cmd);
json_object_start(response, NULL); json_object_start(response, NULL);
json_add_string(response, "address", out); json_add_string(response, "address", out);
json_object_end(response); json_object_end(response);
@@ -300,7 +301,7 @@ AUTODATA(json_command, &newaddr_command);
static void json_listaddrs(struct command *cmd, static void json_listaddrs(struct command *cmd,
const char *buffer, const jsmntok_t *params) const char *buffer, const jsmntok_t *params)
{ {
struct json_result *response = new_json_result(cmd); struct json_result *response;
struct ext_key ext; struct ext_key ext;
struct pubkey pubkey; struct pubkey pubkey;
u64 *bip32_max_index; u64 *bip32_max_index;
@@ -312,6 +313,7 @@ static void json_listaddrs(struct command *cmd,
NULL)) NULL))
return; return;
response = json_stream_success(cmd);
json_object_start(response, NULL); json_object_start(response, NULL);
json_array_start(response, "addresses"); json_array_start(response, "addresses");
@@ -323,15 +325,12 @@ static void json_listaddrs(struct command *cmd,
if (bip32_key_from_parent(cmd->ld->wallet->bip32_base, keyidx, if (bip32_key_from_parent(cmd->ld->wallet->bip32_base, keyidx,
BIP32_FLAG_KEY_PUBLIC, &ext) != WALLY_OK) { BIP32_FLAG_KEY_PUBLIC, &ext) != WALLY_OK) {
command_fail(cmd, LIGHTNINGD, abort();
"Keys generation failure");
return;
} }
if (!secp256k1_ec_pubkey_parse(secp256k1_ctx, &pubkey.pubkey, if (!secp256k1_ec_pubkey_parse(secp256k1_ctx, &pubkey.pubkey,
ext.pub_key, sizeof(ext.pub_key))) { ext.pub_key, sizeof(ext.pub_key))) {
command_fail(cmd, LIGHTNINGD, "Key parsing failure"); abort();
return;
} }
// p2sh // p2sh
@@ -348,9 +347,7 @@ static void json_listaddrs(struct command *cmd,
false, false,
&redeemscript_p2wpkh); &redeemscript_p2wpkh);
if (!out_p2wpkh) { if (!out_p2wpkh) {
command_fail(cmd, LIGHTNINGD, abort();
"p2wpkh address encoding failure.");
return;
} }
// outputs // outputs
@@ -382,16 +379,17 @@ AUTODATA(json_command, &listaddrs_command);
static void json_listfunds(struct command *cmd, const char *buffer UNUSED, static void json_listfunds(struct command *cmd, const char *buffer UNUSED,
const jsmntok_t *params UNUSED) const jsmntok_t *params UNUSED)
{ {
struct json_result *response = new_json_result(cmd); struct json_result *response;
struct peer *p; struct peer *p;
struct utxo **utxos = struct utxo **utxos;
wallet_get_utxos(cmd, cmd->ld->wallet, output_state_available);
char* out; char* out;
struct pubkey funding_pubkey; struct pubkey funding_pubkey;
if (!param(cmd, buffer, params, NULL)) if (!param(cmd, buffer, params, NULL))
return; return;
utxos = wallet_get_utxos(cmd, cmd->ld->wallet, output_state_available);
response = json_stream_success(cmd);
json_object_start(response, NULL); json_object_start(response, NULL);
json_array_start(response, "outputs"); json_array_start(response, "outputs");
for (size_t i = 0; i < tal_count(utxos); i++) { for (size_t i = 0; i < tal_count(utxos); i++) {
@@ -513,7 +511,7 @@ static void json_dev_rescan_outputs(struct command *cmd,
if (!param(cmd, buffer, params, NULL)) if (!param(cmd, buffer, params, NULL))
return; return;
rescan->response = new_json_result(cmd); rescan->response = json_stream_success(cmd);
rescan->cmd = cmd; rescan->cmd = cmd;
/* Open the result structure so we can incrementally add results */ /* Open the result structure so we can incrementally add results */