Browse Source

json-rpc: make commands return 'struct command_result *'.

Usually, this means they return 'command_param_failed()' if param()
fails, and changing 'command_success(); return;' to 'return
command_success()'.

Occasionally, it's more complex: there's a command_its_complicated()
for the case where we can't exactly determine what the status is,
but it should be considered a last resort.

Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
plugin-7
Rusty Russell 6 years ago
parent
commit
68bb36b210
  1. 12
      lightningd/chaintopology.c
  2. 48
      lightningd/connect_control.c
  3. 101
      lightningd/gossip_control.c
  4. 176
      lightningd/invoice.c
  5. 141
      lightningd/jsonrpc.c
  6. 8
      lightningd/jsonrpc.h
  7. 12
      lightningd/log.c
  8. 29
      lightningd/memdump.c
  9. 38
      lightningd/opening_control.c
  10. 21
      lightningd/options.c
  11. 63
      lightningd/pay.c
  12. 39
      lightningd/payalgo.c
  13. 194
      lightningd/peer_control.c
  14. 29
      lightningd/peer_htlcs.c
  15. 22
      lightningd/ping.c
  16. 11
      lightningd/plugin.c
  17. 6
      lightningd/test/run-invoice-select-inchan.c
  18. 6
      wallet/test/run-wallet.c
  19. 99
      wallet/walletrpc.c

12
lightningd/chaintopology.c

@ -463,10 +463,10 @@ u32 feerate_to_style(u32 feerate_perkw, enum feerate_style style)
abort(); abort();
} }
static void json_feerates(struct command *cmd, static struct command_result *json_feerates(struct command *cmd,
const char *buffer, const char *buffer,
const jsmntok_t *obj UNNEEDED, const jsmntok_t *obj UNNEEDED,
const jsmntok_t *params) const jsmntok_t *params)
{ {
struct chain_topology *topo = cmd->ld->topology; struct chain_topology *topo = cmd->ld->topology;
struct json_stream *response; struct json_stream *response;
@ -477,7 +477,7 @@ static void json_feerates(struct command *cmd,
if (!param(cmd, buffer, params, if (!param(cmd, buffer, params,
p_req("style", param_feerate_style, &style), p_req("style", param_feerate_style, &style),
NULL)) NULL))
return; return command_param_failed();
missing = false; missing = false;
for (size_t i = 0; i < ARRAY_SIZE(feerates); i++) { for (size_t i = 0; i < ARRAY_SIZE(feerates); i++) {
@ -520,7 +520,7 @@ static void json_feerates(struct command *cmd,
json_object_end(response); json_object_end(response);
command_success(cmd, response); return command_success(cmd, response);
} }
static const struct json_command feerates_command = { static const struct json_command feerates_command = {

48
lightningd/connect_control.c

@ -65,19 +65,20 @@ static struct connect *find_connect(struct lightningd *ld,
return NULL; return NULL;
} }
static void connect_cmd_succeed(struct command *cmd, const struct pubkey *id) static struct command_result *connect_cmd_succeed(struct command *cmd,
const struct pubkey *id)
{ {
struct json_stream *response = json_stream_success(cmd); struct json_stream *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);
command_success(cmd, response); return command_success(cmd, response);
} }
static void json_connect(struct command *cmd, static struct command_result *json_connect(struct command *cmd,
const char *buffer, const char *buffer,
const jsmntok_t *obj UNNEEDED, const jsmntok_t *obj UNNEEDED,
const jsmntok_t *params) const jsmntok_t *params)
{ {
u32 *port; u32 *port;
jsmntok_t *idtok; jsmntok_t *idtok;
@ -96,7 +97,7 @@ static void json_connect(struct command *cmd,
p_opt("host", param_string, &name), p_opt("host", param_string, &name),
p_opt("port", param_number, &port), p_opt("port", param_number, &port),
NULL)) NULL))
return; return command_param_failed();
/* Check for id@addrport form */ /* Check for id@addrport form */
id_str = json_strdup(cmd, buffer, idtok); id_str = json_strdup(cmd, buffer, idtok);
@ -109,18 +110,16 @@ static void json_connect(struct command *cmd,
} }
if (!json_to_pubkey(buffer, idtok, &id)) { if (!json_to_pubkey(buffer, idtok, &id)) {
command_fail(cmd, JSONRPC2_INVALID_PARAMS, return command_fail(cmd, JSONRPC2_INVALID_PARAMS,
"id %.*s not valid", "id %.*s not valid",
json_tok_full_len(idtok), json_tok_full_len(idtok),
json_tok_full(buffer, idtok)); json_tok_full(buffer, idtok));
return;
} }
if (name && ataddr) { if (name && ataddr) {
command_fail(cmd, JSONRPC2_INVALID_PARAMS, return command_fail(cmd, JSONRPC2_INVALID_PARAMS,
"Can't specify host as both xxx@yyy " "Can't specify host as both xxx@yyy "
"and separate argument"); "and separate argument");
return;
} }
/* Get parseable host if provided somehow */ /* Get parseable host if provided somehow */
@ -129,9 +128,8 @@ static void json_connect(struct command *cmd,
/* Port without host name? */ /* Port without host name? */
if (port && !name) { if (port && !name) {
command_fail(cmd, JSONRPC2_INVALID_PARAMS, return command_fail(cmd, JSONRPC2_INVALID_PARAMS,
"Can't specify port without host"); "Can't specify port without host");
return;
} }
/* If we know about peer, see if it's already connected. */ /* If we know about peer, see if it's already connected. */
@ -141,8 +139,7 @@ static void json_connect(struct command *cmd,
if (peer->uncommitted_channel if (peer->uncommitted_channel
|| (channel && channel->connected)) { || (channel && channel->connected)) {
connect_cmd_succeed(cmd, &id); return connect_cmd_succeed(cmd, &id);
return;
} }
} }
@ -159,9 +156,10 @@ static void json_connect(struct command *cmd,
&& !cmd->ld->pure_tor_setup, && !cmd->ld->pure_tor_setup,
true, true,
&err_msg)) { &err_msg)) {
command_fail(cmd, LIGHTNINGD, "Host %s:%u not valid: %s", return command_fail(cmd, LIGHTNINGD,
name, *port, err_msg ? err_msg : "port is 0"); "Host %s:%u not valid: %s",
return; name, *port,
err_msg ? err_msg : "port is 0");
} }
} else } else
addr = NULL; addr = NULL;
@ -171,7 +169,7 @@ static void json_connect(struct command *cmd,
/* Leave this here for peer_connected or connect_failed. */ /* Leave this here for peer_connected or connect_failed. */
new_connect(cmd->ld, &id, cmd); new_connect(cmd->ld, &id, cmd);
command_still_pending(cmd); return command_still_pending(cmd);
} }
static const struct json_command connect_command = { static const struct json_command connect_command = {

101
lightningd/gossip_control.c

@ -244,10 +244,10 @@ static void json_getnodes_reply(struct subd *gossip UNUSED, const u8 *reply,
command_success(cmd, response); command_success(cmd, response);
} }
static void json_listnodes(struct command *cmd, static struct command_result *json_listnodes(struct command *cmd,
const char *buffer, const char *buffer,
const jsmntok_t *obj UNNEEDED, const jsmntok_t *obj UNNEEDED,
const jsmntok_t *params) const jsmntok_t *params)
{ {
u8 *req; u8 *req;
struct pubkey *id; struct pubkey *id;
@ -255,11 +255,11 @@ static void json_listnodes(struct command *cmd,
if (!param(cmd, buffer, params, if (!param(cmd, buffer, params,
p_opt("id", param_pubkey, &id), p_opt("id", param_pubkey, &id),
NULL)) NULL))
return; return command_param_failed();
req = towire_gossip_getnodes_request(cmd, id); req = towire_gossip_getnodes_request(cmd, id);
subd_req(cmd, cmd->ld->gossip, req, -1, 0, json_getnodes_reply, cmd); subd_req(cmd, cmd->ld->gossip, req, -1, 0, json_getnodes_reply, cmd);
command_still_pending(cmd); return command_still_pending(cmd);
} }
static const struct json_command listnodes_command = { static const struct json_command listnodes_command = {
@ -289,10 +289,10 @@ static void json_getroute_reply(struct subd *gossip UNUSED, const u8 *reply, con
command_success(cmd, response); command_success(cmd, response);
} }
static void json_getroute(struct command *cmd, static struct command_result *json_getroute(struct command *cmd,
const char *buffer, const char *buffer,
const jsmntok_t *obj UNNEEDED, const jsmntok_t *obj UNNEEDED,
const jsmntok_t *params) const jsmntok_t *params)
{ {
struct lightningd *ld = cmd->ld; struct lightningd *ld = cmd->ld;
struct pubkey *destination; struct pubkey *destination;
@ -318,7 +318,7 @@ static void json_getroute(struct command *cmd,
p_opt("seed", param_tok, &seedtok), p_opt("seed", param_tok, &seedtok),
p_opt_def("fuzzpercent", param_percent, &fuzz, 75.0), p_opt_def("fuzzpercent", param_percent, &fuzz, 75.0),
NULL)) NULL))
return; return command_param_failed();
/* Convert from percentage */ /* Convert from percentage */
*fuzz = *fuzz / 100.0; *fuzz = *fuzz / 100.0;
@ -338,7 +338,7 @@ static void json_getroute(struct command *cmd,
*msatoshi, *riskfactor * 1000, *msatoshi, *riskfactor * 1000,
*cltv, fuzz, &seed); *cltv, fuzz, &seed);
subd_req(ld->gossip, ld->gossip, req, -1, 0, json_getroute_reply, cmd); subd_req(ld->gossip, ld->gossip, req, -1, 0, json_getroute_reply, cmd);
command_still_pending(cmd); return command_still_pending(cmd);
} }
static const struct json_command getroute_command = { static const struct json_command getroute_command = {
@ -399,22 +399,22 @@ static void json_listchannels_reply(struct subd *gossip UNUSED, const u8 *reply,
command_success(cmd, response); command_success(cmd, response);
} }
static void json_listchannels(struct command *cmd, static struct command_result *json_listchannels(struct command *cmd,
const char *buffer, const char *buffer,
const jsmntok_t *obj UNNEEDED, const jsmntok_t *obj UNNEEDED,
const jsmntok_t *params) const jsmntok_t *params)
{ {
u8 *req; u8 *req;
struct short_channel_id *id; struct short_channel_id *id;
if (!param(cmd, buffer, params, if (!param(cmd, buffer, params,
p_opt("short_channel_id", param_short_channel_id, &id), p_opt("short_channel_id", param_short_channel_id, &id),
NULL)) NULL))
return; return command_param_failed();
req = towire_gossip_getchannels_request(cmd, id); req = towire_gossip_getchannels_request(cmd, id);
subd_req(cmd->ld->gossip, cmd->ld->gossip, subd_req(cmd->ld->gossip, cmd->ld->gossip,
req, -1, 0, json_listchannels_reply, cmd); req, -1, 0, json_listchannels_reply, cmd);
command_still_pending(cmd); return command_still_pending(cmd);
} }
static const struct json_command listchannels_command = { static const struct json_command listchannels_command = {
@ -450,10 +450,10 @@ static void json_scids_reply(struct subd *gossip UNUSED, const u8 *reply,
command_success(cmd, response); command_success(cmd, response);
} }
static void json_dev_query_scids(struct command *cmd, static struct command_result *json_dev_query_scids(struct command *cmd,
const char *buffer, const char *buffer,
const jsmntok_t *obj UNNEEDED, const jsmntok_t *obj UNNEEDED,
const jsmntok_t *params) const jsmntok_t *params)
{ {
u8 *msg; u8 *msg;
const jsmntok_t *scidstok; const jsmntok_t *scidstok;
@ -466,17 +466,16 @@ static void json_dev_query_scids(struct command *cmd,
p_req("id", param_pubkey, &id), p_req("id", param_pubkey, &id),
p_req("scids", param_array, &scidstok), p_req("scids", param_array, &scidstok),
NULL)) NULL))
return; return command_param_failed();
scids = tal_arr(cmd, struct short_channel_id, scidstok->size); scids = tal_arr(cmd, struct short_channel_id, scidstok->size);
end = json_next(scidstok); end = json_next(scidstok);
for (i = 0, t = scidstok + 1; t < end; t = json_next(t), i++) { for (i = 0, t = scidstok + 1; t < end; t = json_next(t), i++) {
if (!json_to_short_channel_id(buffer, t, &scids[i])) { if (!json_to_short_channel_id(buffer, t, &scids[i])) {
command_fail(cmd, JSONRPC2_INVALID_PARAMS, return command_fail(cmd, JSONRPC2_INVALID_PARAMS,
"scid %zu '%.*s' is not an scid", "scid %zu '%.*s' is not an scid",
i, json_tok_full_len(t), i, json_tok_full_len(t),
json_tok_full(buffer, t)); json_tok_full(buffer, t));
return;
} }
} }
@ -484,7 +483,7 @@ static void json_dev_query_scids(struct command *cmd,
msg = towire_gossip_query_scids(cmd, id, scids); msg = towire_gossip_query_scids(cmd, id, scids);
subd_req(cmd->ld->gossip, cmd->ld->gossip, subd_req(cmd->ld->gossip, cmd->ld->gossip,
take(msg), -1, 0, json_scids_reply, cmd); take(msg), -1, 0, json_scids_reply, cmd);
command_still_pending(cmd); return command_still_pending(cmd);
} }
static const struct json_command dev_query_scids_command = { static const struct json_command dev_query_scids_command = {
@ -494,10 +493,11 @@ static const struct json_command dev_query_scids_command = {
}; };
AUTODATA(json_command, &dev_query_scids_command); AUTODATA(json_command, &dev_query_scids_command);
static void json_dev_send_timestamp_filter(struct command *cmd, static struct command_result *
const char *buffer, json_dev_send_timestamp_filter(struct command *cmd,
const jsmntok_t *obj UNNEEDED, const char *buffer,
const jsmntok_t *params) const jsmntok_t *obj UNNEEDED,
const jsmntok_t *params)
{ {
u8 *msg; u8 *msg;
struct pubkey *id; struct pubkey *id;
@ -508,14 +508,14 @@ static void json_dev_send_timestamp_filter(struct command *cmd,
p_req("first", param_number, &first), p_req("first", param_number, &first),
p_req("range", param_number, &range), p_req("range", param_number, &range),
NULL)) NULL))
return; return command_param_failed();
log_debug(cmd->ld->log, "Setting timestamp range %u+%u", *first, *range); log_debug(cmd->ld->log, "Setting timestamp range %u+%u", *first, *range);
/* Tell gossipd, since this is a gossip query. */ /* Tell gossipd, since this is a gossip query. */
msg = towire_gossip_send_timestamp_filter(NULL, id, *first, *range); msg = towire_gossip_send_timestamp_filter(NULL, id, *first, *range);
subd_send_msg(cmd->ld->gossip, take(msg)); subd_send_msg(cmd->ld->gossip, take(msg));
command_success(cmd, null_response(cmd)); return command_success(cmd, null_response(cmd));
} }
static const struct json_command dev_send_timestamp_filter = { static const struct json_command dev_send_timestamp_filter = {
@ -564,7 +564,7 @@ static void json_channel_range_reply(struct subd *gossip UNUSED, const u8 *reply
command_success(cmd, response); command_success(cmd, response);
} }
static void json_dev_query_channel_range(struct command *cmd, static struct command_result *json_dev_query_channel_range(struct command *cmd,
const char *buffer, const char *buffer,
const jsmntok_t *obj UNNEEDED, const jsmntok_t *obj UNNEEDED,
const jsmntok_t *params) const jsmntok_t *params)
@ -578,13 +578,13 @@ static void json_dev_query_channel_range(struct command *cmd,
p_req("first", param_number, &first), p_req("first", param_number, &first),
p_req("num", param_number, &num), p_req("num", param_number, &num),
NULL)) NULL))
return; return command_param_failed();
/* Tell gossipd, since this is a gossip query. */ /* Tell gossipd, since this is a gossip query. */
msg = towire_gossip_query_channel_range(cmd, id, *first, *num); msg = towire_gossip_query_channel_range(cmd, id, *first, *num);
subd_req(cmd->ld->gossip, cmd->ld->gossip, subd_req(cmd->ld->gossip, cmd->ld->gossip,
take(msg), -1, 0, json_channel_range_reply, cmd); take(msg), -1, 0, json_channel_range_reply, cmd);
command_still_pending(cmd); return command_still_pending(cmd);
} }
static const struct json_command dev_query_channel_range_command = { static const struct json_command dev_query_channel_range_command = {
@ -594,10 +594,11 @@ static const struct json_command dev_query_channel_range_command = {
}; };
AUTODATA(json_command, &dev_query_channel_range_command); AUTODATA(json_command, &dev_query_channel_range_command);
static void json_dev_set_max_scids_encode_size(struct command *cmd, static struct command_result *
const char *buffer, json_dev_set_max_scids_encode_size(struct command *cmd,
const jsmntok_t *obj UNNEEDED, const char *buffer,
const jsmntok_t *params) const jsmntok_t *obj UNNEEDED,
const jsmntok_t *params)
{ {
u8 *msg; u8 *msg;
u32 *max; u32 *max;
@ -605,12 +606,12 @@ static void json_dev_set_max_scids_encode_size(struct command *cmd,
if (!param(cmd, buffer, params, if (!param(cmd, buffer, params,
p_req("max", param_number, &max), p_req("max", param_number, &max),
NULL)) NULL))
return; return command_param_failed();
msg = towire_gossip_dev_set_max_scids_encode_size(NULL, *max); msg = towire_gossip_dev_set_max_scids_encode_size(NULL, *max);
subd_send_msg(cmd->ld->gossip, take(msg)); subd_send_msg(cmd->ld->gossip, take(msg));
command_success(cmd, null_response(cmd)); return command_success(cmd, null_response(cmd));
} }
static const struct json_command dev_set_max_scids_encode_size = { static const struct json_command dev_set_max_scids_encode_size = {
@ -620,17 +621,17 @@ static const struct json_command dev_set_max_scids_encode_size = {
}; };
AUTODATA(json_command, &dev_set_max_scids_encode_size); AUTODATA(json_command, &dev_set_max_scids_encode_size);
static void json_dev_suppress_gossip(struct command *cmd, static struct command_result *json_dev_suppress_gossip(struct command *cmd,
const char *buffer, const char *buffer,
const jsmntok_t *obj UNNEEDED, const jsmntok_t *obj UNNEEDED,
const jsmntok_t *params) const jsmntok_t *params)
{ {
if (!param(cmd, buffer, params, NULL)) if (!param(cmd, buffer, params, NULL))
return; return command_param_failed();
subd_send_msg(cmd->ld->gossip, take(towire_gossip_dev_suppress(NULL))); subd_send_msg(cmd->ld->gossip, take(towire_gossip_dev_suppress(NULL)));
command_success(cmd, null_response(cmd)); return command_success(cmd, null_response(cmd));
} }
static const struct json_command dev_suppress_gossip = { static const struct json_command dev_suppress_gossip = {

176
lightningd/invoice.c

@ -62,7 +62,8 @@ static void json_add_invoice(struct json_stream *response,
json_object_end(response); json_object_end(response);
} }
static void tell_waiter(struct command *cmd, const struct invoice *inv) static struct command_result *tell_waiter(struct command *cmd,
const struct invoice *inv)
{ {
struct json_stream *response; struct json_stream *response;
const struct invoice_details *details; const struct invoice_details *details;
@ -71,13 +72,13 @@ static void tell_waiter(struct command *cmd, const struct invoice *inv)
if (details->state == PAID) { if (details->state == PAID) {
response = json_stream_success(cmd); response = json_stream_success(cmd);
json_add_invoice(response, details); json_add_invoice(response, details);
command_success(cmd, response); return 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. */
response = json_stream_fail(cmd, -2, response = json_stream_fail(cmd, -2,
"invoice expired during wait"); "invoice expired during wait");
json_add_invoice(response, details); json_add_invoice(response, details);
command_failed(cmd, response); return command_failed(cmd, response);
} }
} }
@ -111,9 +112,10 @@ static bool hsm_sign_b11(const u5 *u5bytes,
return true; return true;
} }
static bool parse_fallback(struct command *cmd, static struct command_result *parse_fallback(struct command *cmd,
const char *buffer, const jsmntok_t *fallback, const char *buffer,
const u8 **fallback_script) const jsmntok_t *fallback,
const u8 **fallback_script)
{ {
enum address_parse_result fallback_parse; enum address_parse_result fallback_parse;
@ -124,15 +126,14 @@ static bool parse_fallback(struct command *cmd,
buffer, fallback, buffer, fallback,
fallback_script); fallback_script);
if (fallback_parse == ADDRESS_PARSE_UNRECOGNIZED) { if (fallback_parse == ADDRESS_PARSE_UNRECOGNIZED) {
command_fail(cmd, LIGHTNINGD, "Fallback address not valid"); return command_fail(cmd, LIGHTNINGD,
return false; "Fallback address not valid");
} else if (fallback_parse == ADDRESS_PARSE_WRONG_NETWORK) { } else if (fallback_parse == ADDRESS_PARSE_WRONG_NETWORK) {
command_fail(cmd, LIGHTNINGD, return command_fail(cmd, LIGHTNINGD,
"Fallback address does not match our network %s", "Fallback address does not match our network %s",
get_chainparams(cmd->ld)->network_name); get_chainparams(cmd->ld)->network_name);
return false;
} }
return true; return NULL;
} }
/* BOLT11 struct wants an array of arrays (can provide multiple routes) */ /* BOLT11 struct wants an array of arrays (can provide multiple routes) */
@ -291,10 +292,10 @@ static void gossipd_incoming_channels_reply(struct subd *gossipd,
command_success(info->cmd, response); command_success(info->cmd, response);
} }
static void json_invoice(struct command *cmd, static struct command_result *json_invoice(struct command *cmd,
const char *buffer, const char *buffer,
const jsmntok_t *obj UNNEEDED, const jsmntok_t *obj UNNEEDED,
const jsmntok_t *params) const jsmntok_t *params)
{ {
const jsmntok_t *fallbacks; const jsmntok_t *fallbacks;
const jsmntok_t *preimagetok; const jsmntok_t *preimagetok;
@ -316,23 +317,21 @@ static void json_invoice(struct command *cmd,
p_opt("fallbacks", param_array, &fallbacks), p_opt("fallbacks", param_array, &fallbacks),
p_opt("preimage", param_tok, &preimagetok), p_opt("preimage", param_tok, &preimagetok),
NULL)) NULL))
return; return command_param_failed();
if (strlen(info->label->s) > INVOICE_MAX_LABEL_LEN) { if (strlen(info->label->s) > INVOICE_MAX_LABEL_LEN) {
command_fail(cmd, JSONRPC2_INVALID_PARAMS, return command_fail(cmd, JSONRPC2_INVALID_PARAMS,
"Label '%s' over %u bytes", info->label->s, "Label '%s' over %u bytes", info->label->s,
INVOICE_MAX_LABEL_LEN); INVOICE_MAX_LABEL_LEN);
return;
} }
if (strlen(desc_val) >= BOLT11_FIELD_BYTE_LIMIT) { if (strlen(desc_val) >= BOLT11_FIELD_BYTE_LIMIT) {
command_fail(cmd, JSONRPC2_INVALID_PARAMS, return command_fail(cmd, JSONRPC2_INVALID_PARAMS,
"Descriptions greater than %d bytes " "Descriptions greater than %d bytes "
"not yet supported " "not yet supported "
"(description length %zu)", "(description length %zu)",
BOLT11_FIELD_BYTE_LIMIT, BOLT11_FIELD_BYTE_LIMIT,
strlen(desc_val)); strlen(desc_val));
return;
} }
if (fallbacks) { if (fallbacks) {
@ -340,9 +339,11 @@ static void json_invoice(struct command *cmd,
fallback_scripts = tal_arr(cmd, const u8 *, 0); fallback_scripts = tal_arr(cmd, const u8 *, 0);
for (i = fallbacks + 1; i < end; i = json_next(i)) { for (i = fallbacks + 1; i < end; i = json_next(i)) {
if (!parse_fallback(cmd, buffer, i, struct command_result *r;
tal_arr_expand(&fallback_scripts))) r = parse_fallback(cmd, buffer, i,
return; tal_arr_expand(&fallback_scripts));
if (r)
return r;
} }
} }
@ -352,9 +353,8 @@ static void json_invoice(struct command *cmd,
preimagetok->end - preimagetok->start, preimagetok->end - preimagetok->start,
&info->payment_preimage, &info->payment_preimage,
sizeof(info->payment_preimage))) { sizeof(info->payment_preimage))) {
command_fail(cmd, JSONRPC2_INVALID_PARAMS, return command_fail(cmd, JSONRPC2_INVALID_PARAMS,
"preimage must be 64 hex digits"); "preimage must be 64 hex digits");
return;
} }
} else } else
/* Generate random secret preimage. */ /* Generate random secret preimage. */
@ -381,7 +381,7 @@ static void json_invoice(struct command *cmd,
take(towire_gossip_get_incoming_channels(NULL)), take(towire_gossip_get_incoming_channels(NULL)),
-1, 0, gossipd_incoming_channels_reply, info); -1, 0, gossipd_incoming_channels_reply, info);
command_still_pending(cmd); return command_still_pending(cmd);
} }
static const struct json_command invoice_command = { static const struct json_command invoice_command = {
@ -416,10 +416,10 @@ static void json_add_invoices(struct json_stream *response,
} }
} }
static void json_listinvoices(struct command *cmd, static struct command_result *json_listinvoices(struct command *cmd,
const char *buffer, const char *buffer,
const jsmntok_t *obj UNNEEDED, const jsmntok_t *obj UNNEEDED,
const jsmntok_t *params) const jsmntok_t *params)
{ {
struct json_escaped *label; struct json_escaped *label;
struct json_stream *response; struct json_stream *response;
@ -427,14 +427,14 @@ static void json_listinvoices(struct command *cmd,
if (!param(cmd, buffer, params, if (!param(cmd, buffer, params,
p_opt("label", param_label, &label), p_opt("label", param_label, &label),
NULL)) NULL))
return; return command_param_failed();
response = json_stream_success(cmd); 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);
json_array_end(response); json_array_end(response);
json_object_end(response); json_object_end(response);
command_success(cmd, response); return command_success(cmd, response);
} }
static const struct json_command listinvoices_command = { static const struct json_command listinvoices_command = {
@ -444,10 +444,10 @@ static const struct json_command listinvoices_command = {
}; };
AUTODATA(json_command, &listinvoices_command); AUTODATA(json_command, &listinvoices_command);
static void json_delinvoice(struct command *cmd, static struct command_result *json_delinvoice(struct command *cmd,
const char *buffer, const char *buffer,
const jsmntok_t *obj UNNEEDED, const jsmntok_t *obj UNNEEDED,
const jsmntok_t *params) const jsmntok_t *params)
{ {
struct invoice i; struct invoice i;
const struct invoice_details *details; const struct invoice_details *details;
@ -460,11 +460,10 @@ static void json_delinvoice(struct command *cmd,
p_req("label", param_label, &label), p_req("label", param_label, &label),
p_req("status", param_string, &status), p_req("status", param_string, &status),
NULL)) NULL))
return; return command_param_failed();
if (!wallet_invoice_find_by_label(wallet, &i, label)) { if (!wallet_invoice_find_by_label(wallet, &i, label)) {
command_fail(cmd, LIGHTNINGD, "Unknown invoice"); return command_fail(cmd, LIGHTNINGD, "Unknown invoice");
return;
} }
details = wallet_invoice_details(cmd, cmd->ld->wallet, i); details = wallet_invoice_details(cmd, cmd->ld->wallet, i);
@ -473,22 +472,21 @@ static void json_delinvoice(struct command *cmd,
* might not make sense if it changed! */ * might not make sense if it changed! */
actual_status = invoice_status_str(details); actual_status = invoice_status_str(details);
if (!streq(actual_status, status)) { if (!streq(actual_status, status)) {
command_fail(cmd, LIGHTNINGD, "Invoice status is %s not %s", return command_fail(cmd, LIGHTNINGD,
actual_status, status); "Invoice status is %s not %s",
return; actual_status, status);
} }
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,
i.id); i.id);
command_fail(cmd, LIGHTNINGD, "Database error"); return command_fail(cmd, LIGHTNINGD, "Database error");
return;
} }
response = json_stream_success(cmd); response = json_stream_success(cmd);
json_add_invoice(response, details); json_add_invoice(response, details);
command_success(cmd, response); return command_success(cmd, response);
} }
static const struct json_command delinvoice_command = { static const struct json_command delinvoice_command = {
@ -498,10 +496,10 @@ static const struct json_command delinvoice_command = {
}; };
AUTODATA(json_command, &delinvoice_command); AUTODATA(json_command, &delinvoice_command);
static void json_delexpiredinvoice(struct command *cmd, static struct command_result *json_delexpiredinvoice(struct command *cmd,
const char *buffer, const char *buffer,
const jsmntok_t *obj UNNEEDED, const jsmntok_t *obj UNNEEDED,
const jsmntok_t *params) const jsmntok_t *params)
{ {
u64 *maxexpirytime; u64 *maxexpirytime;
@ -509,11 +507,11 @@ static void json_delexpiredinvoice(struct command *cmd,
p_opt_def("maxexpirytime", param_u64, &maxexpirytime, p_opt_def("maxexpirytime", param_u64, &maxexpirytime,
time_now().ts.tv_sec), time_now().ts.tv_sec),
NULL)) NULL))
return; return command_param_failed();
wallet_invoice_delete_expired(cmd->ld->wallet, *maxexpirytime); wallet_invoice_delete_expired(cmd->ld->wallet, *maxexpirytime);
command_success(cmd, null_response(cmd)); return command_success(cmd, null_response(cmd));
} }
static const struct json_command delexpiredinvoice_command = { static const struct json_command delexpiredinvoice_command = {
"delexpiredinvoice", "delexpiredinvoice",
@ -522,10 +520,10 @@ static const struct json_command delexpiredinvoice_command = {
}; };
AUTODATA(json_command, &delexpiredinvoice_command); AUTODATA(json_command, &delexpiredinvoice_command);
static void json_autocleaninvoice(struct command *cmd, static struct command_result *json_autocleaninvoice(struct command *cmd,
const char *buffer, const char *buffer,
const jsmntok_t *obj UNNEEDED, const jsmntok_t *obj UNNEEDED,
const jsmntok_t *params) const jsmntok_t *params)
{ {
u64 *cycle; u64 *cycle;
u64 *exby; u64 *exby;
@ -534,11 +532,11 @@ static void json_autocleaninvoice(struct command *cmd,
p_opt_def("cycle_seconds", param_u64, &cycle, 3600), p_opt_def("cycle_seconds", param_u64, &cycle, 3600),
p_opt_def("expired_by", param_u64, &exby, 86400), p_opt_def("expired_by", param_u64, &exby, 86400),
NULL)) NULL))
return; return command_param_failed();
wallet_invoice_autoclean(cmd->ld->wallet, *cycle, *exby); wallet_invoice_autoclean(cmd->ld->wallet, *cycle, *exby);
command_success(cmd, null_response(cmd)); return command_success(cmd, null_response(cmd));
} }
static const struct json_command autocleaninvoice_command = { static const struct json_command autocleaninvoice_command = {
"autocleaninvoice", "autocleaninvoice",
@ -549,10 +547,10 @@ static const struct json_command autocleaninvoice_command = {
}; };
AUTODATA(json_command, &autocleaninvoice_command); AUTODATA(json_command, &autocleaninvoice_command);
static void json_waitanyinvoice(struct command *cmd, static struct command_result *json_waitanyinvoice(struct command *cmd,
const char *buffer, const char *buffer,
const jsmntok_t *obj UNNEEDED, const jsmntok_t *obj UNNEEDED,
const jsmntok_t *params) const jsmntok_t *params)
{ {
u64 *pay_index; u64 *pay_index;
struct wallet *wallet = cmd->ld->wallet; struct wallet *wallet = cmd->ld->wallet;
@ -560,7 +558,7 @@ static void json_waitanyinvoice(struct command *cmd,
if (!param(cmd, buffer, params, if (!param(cmd, buffer, params,
p_opt_def("lastpay_index", param_u64, &pay_index, 0), p_opt_def("lastpay_index", param_u64, &pay_index, 0),
NULL)) NULL))
return; return command_param_failed();
/* Set command as pending. We do not know if /* Set command as pending. We do not know if
* wallet_invoice_waitany will return immediately * wallet_invoice_waitany will return immediately
@ -570,6 +568,8 @@ static void json_waitanyinvoice(struct command *cmd,
/* Find next paid invoice. */ /* Find next paid invoice. */
wallet_invoice_waitany(cmd, wallet, *pay_index, wallet_invoice_waitany(cmd, wallet, *pay_index,
&wait_on_invoice, (void*) cmd); &wait_on_invoice, (void*) cmd);
return command_its_complicated();
} }
static const struct json_command waitanyinvoice_command = { static const struct json_command waitanyinvoice_command = {
@ -585,10 +585,10 @@ AUTODATA(json_command, &waitanyinvoice_command);
* already been received or it may add the `cmd` to the list of * already been received or it may add the `cmd` to the list of
* waiters, if the payment is still pending. * waiters, if the payment is still pending.
*/ */
static void json_waitinvoice(struct command *cmd, static struct command_result *json_waitinvoice(struct command *cmd,
const char *buffer, const char *buffer,
const jsmntok_t *obj UNNEEDED, const jsmntok_t *obj UNNEEDED,
const jsmntok_t *params) const jsmntok_t *params)
{ {
struct invoice i; struct invoice i;
const struct invoice_details *details; const struct invoice_details *details;
@ -598,23 +598,22 @@ static void json_waitinvoice(struct command *cmd,
if (!param(cmd, buffer, params, if (!param(cmd, buffer, params,
p_req("label", param_label, &label), p_req("label", param_label, &label),
NULL)) NULL))
return; return command_param_failed();
if (!wallet_invoice_find_by_label(wallet, &i, label)) { if (!wallet_invoice_find_by_label(wallet, &i, label)) {
command_fail(cmd, LIGHTNINGD, "Label not found"); return command_fail(cmd, LIGHTNINGD, "Label not found");
return;
} }
details = wallet_invoice_details(cmd, cmd->ld->wallet, i); details = wallet_invoice_details(cmd, cmd->ld->wallet, i);
/* If paid or expired return immediately */ /* If paid or expired return immediately */
if (details->state == PAID || details->state == EXPIRED) { if (details->state == PAID || details->state == EXPIRED) {
tell_waiter(cmd, &i); return tell_waiter(cmd, &i);
return;
} else { } else {
/* There is an unpaid one matching, let's wait... */ /* There is an unpaid one matching, let's wait... */
command_still_pending(cmd); command_still_pending(cmd);
wallet_invoice_waitone(cmd, wallet, i, wallet_invoice_waitone(cmd, wallet, i,
&wait_on_invoice, (void *) cmd); &wait_on_invoice, (void *) cmd);
return command_its_complicated();
} }
} }
@ -660,10 +659,10 @@ static void json_add_fallback(struct json_stream *response,
json_object_end(response); json_object_end(response);
} }
static void json_decodepay(struct command *cmd, static struct command_result *json_decodepay(struct command *cmd,
const char *buffer, const char *buffer,
const jsmntok_t *obj UNNEEDED, const jsmntok_t *obj UNNEEDED,
const jsmntok_t *params) const jsmntok_t *params)
{ {
struct bolt11 *b11; struct bolt11 *b11;
struct json_stream *response; struct json_stream *response;
@ -674,13 +673,12 @@ static void json_decodepay(struct command *cmd,
p_req("bolt11", param_string, &str), p_req("bolt11", param_string, &str),
p_opt("description", param_string, &desc), p_opt("description", param_string, &desc),
NULL)) NULL))
return; return command_param_failed();
b11 = bolt11_decode(cmd, str, desc, &fail); b11 = bolt11_decode(cmd, str, desc, &fail);
if (!b11) { if (!b11) {
command_fail(cmd, LIGHTNINGD, "Invalid bolt11: %s", fail); return command_fail(cmd, LIGHTNINGD, "Invalid bolt11: %s", fail);
return;
} }
response = json_stream_success(cmd); response = json_stream_success(cmd);
@ -766,7 +764,7 @@ static void json_decodepay(struct command *cmd,
type_to_string(cmd, secp256k1_ecdsa_signature, type_to_string(cmd, secp256k1_ecdsa_signature,
&b11->sig)); &b11->sig));
json_object_end(response); json_object_end(response);
command_success(cmd, response); return command_success(cmd, response);
} }
static const struct json_command decodepay_command = { static const struct json_command decodepay_command = {

141
lightningd/jsonrpc.c

@ -147,10 +147,10 @@ static void destroy_jcon(struct json_connection *jcon)
tal_free(jcon->log); tal_free(jcon->log);
} }
static void json_help(struct command *cmd, static struct command_result *json_help(struct command *cmd,
const char *buffer, const char *buffer,
const jsmntok_t *obj UNNEEDED, const jsmntok_t *obj UNNEEDED,
const jsmntok_t *params); const jsmntok_t *params);
static const struct json_command help_command = { static const struct json_command help_command = {
"help", "help",
@ -166,21 +166,21 @@ static const struct json_command help_command = {
}; };
AUTODATA(json_command, &help_command); AUTODATA(json_command, &help_command);
static void json_stop(struct command *cmd, static struct command_result *json_stop(struct command *cmd,
const char *buffer, const char *buffer,
const jsmntok_t *obj UNNEEDED, const jsmntok_t *obj UNNEEDED,
const jsmntok_t *params) const jsmntok_t *params)
{ {
struct json_stream *response; struct json_stream *response;
if (!param(cmd, buffer, params, NULL)) if (!param(cmd, buffer, params, NULL))
return; return command_param_failed();
/* 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); response = json_stream_success(cmd);
json_add_string(response, NULL, "Shutting down"); json_add_string(response, NULL, "Shutting down");
command_success(cmd, response); return command_success(cmd, response);
} }
static const struct json_command stop_command = { static const struct json_command stop_command = {
@ -191,10 +191,10 @@ static const struct json_command stop_command = {
AUTODATA(json_command, &stop_command); AUTODATA(json_command, &stop_command);
#if DEVELOPER #if DEVELOPER
static void json_rhash(struct command *cmd, static struct command_result *json_rhash(struct command *cmd,
const char *buffer, const char *buffer,
const jsmntok_t *obj UNUSED, const jsmntok_t *obj UNUSED,
const jsmntok_t *params) const jsmntok_t *params)
{ {
struct json_stream *response; struct json_stream *response;
struct sha256 *secret; struct sha256 *secret;
@ -202,7 +202,7 @@ static void json_rhash(struct command *cmd,
if (!param(cmd, buffer, params, if (!param(cmd, buffer, params,
p_req("secret", param_sha256, &secret), p_req("secret", param_sha256, &secret),
NULL)) NULL))
return; return command_param_failed();
/* Hash in place. */ /* Hash in place. */
sha256(secret, secret, sizeof(*secret)); sha256(secret, secret, sizeof(*secret));
@ -210,7 +210,7 @@ static void json_rhash(struct command *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);
command_success(cmd, response); return command_success(cmd, response);
} }
static const struct json_command dev_rhash_command = { static const struct json_command dev_rhash_command = {
@ -231,7 +231,7 @@ static void slowcmd_finish(struct slowcmd *sc)
json_object_start(sc->js, NULL); json_object_start(sc->js, NULL);
json_add_num(sc->js, "msec", *sc->msec); json_add_num(sc->js, "msec", *sc->msec);
json_object_end(sc->js); json_object_end(sc->js);
command_success(sc->cmd, sc->js); was_pending(command_success(sc->cmd, sc->js));
} }
static void slowcmd_start(struct slowcmd *sc) static void slowcmd_start(struct slowcmd *sc)
@ -241,10 +241,10 @@ static void slowcmd_start(struct slowcmd *sc)
slowcmd_finish, sc); slowcmd_finish, sc);
} }
static void json_slowcmd(struct command *cmd, static struct command_result *json_slowcmd(struct command *cmd,
const char *buffer, const char *buffer,
const jsmntok_t *obj UNUSED, const jsmntok_t *obj UNUSED,
const jsmntok_t *params) const jsmntok_t *params)
{ {
struct slowcmd *sc = tal(cmd, struct slowcmd); struct slowcmd *sc = tal(cmd, struct slowcmd);
@ -252,10 +252,10 @@ static void json_slowcmd(struct command *cmd,
if (!param(cmd, buffer, params, if (!param(cmd, buffer, params,
p_opt_def("msec", param_number, &sc->msec, 1000), p_opt_def("msec", param_number, &sc->msec, 1000),
NULL)) NULL))
return; return command_param_failed();
new_reltimer(&cmd->ld->timers, sc, time_from_msec(0), slowcmd_start, sc); new_reltimer(&cmd->ld->timers, sc, time_from_msec(0), slowcmd_start, sc);
command_still_pending(cmd); return command_still_pending(cmd);
} }
static const struct json_command dev_slowcmd_command = { static const struct json_command dev_slowcmd_command = {
@ -265,13 +265,13 @@ static const struct json_command dev_slowcmd_command = {
}; };
AUTODATA(json_command, &dev_slowcmd_command); AUTODATA(json_command, &dev_slowcmd_command);
static void json_crash(struct command *cmd UNUSED, static struct command_result *json_crash(struct command *cmd UNUSED,
const char *buffer, const char *buffer,
const jsmntok_t *obj UNNEEDED, const jsmntok_t *obj UNNEEDED,
const jsmntok_t *params) const jsmntok_t *params)
{ {
if (!param(cmd, buffer, params, NULL)) if (!param(cmd, buffer, params, NULL))
return; return command_param_failed();
fatal("Crash at user request"); fatal("Crash at user request");
} }
@ -325,10 +325,10 @@ static void json_add_help_command(struct command *cmd,
} }
static void json_help(struct command *cmd, static struct command_result *json_help(struct command *cmd,
const char *buffer, const char *buffer,
const jsmntok_t *obj UNNEEDED, const jsmntok_t *obj UNNEEDED,
const jsmntok_t *params) const jsmntok_t *params)
{ {
struct json_stream *response; struct json_stream *response;
const jsmntok_t *cmdtok; const jsmntok_t *cmdtok;
@ -337,7 +337,7 @@ static void json_help(struct command *cmd,
if (!param(cmd, buffer, params, if (!param(cmd, buffer, params,
p_opt("command", param_tok, &cmdtok), p_opt("command", param_tok, &cmdtok),
NULL)) NULL))
return; return command_param_failed();
if (cmdtok) { if (cmdtok) {
for (size_t i = 0; i < tal_count(commands); i++) { for (size_t i = 0; i < tal_count(commands); i++) {
@ -347,11 +347,10 @@ static void json_help(struct command *cmd,
goto done; goto done;
} }
} }
command_fail(cmd, JSONRPC2_METHOD_NOT_FOUND, return command_fail(cmd, JSONRPC2_METHOD_NOT_FOUND,
"Unknown command '%.*s'", "Unknown command '%.*s'",
json_tok_full_len(cmdtok), json_tok_full_len(cmdtok),
json_tok_full(buffer, cmdtok)); json_tok_full(buffer, cmdtok));
return;
} }
response = json_stream_success(cmd); response = json_stream_success(cmd);
@ -364,7 +363,7 @@ static void json_help(struct command *cmd,
json_object_end(response); json_object_end(response);
done: done:
command_success(cmd, response); return command_success(cmd, response);
} }
static const struct json_command *find_cmd(const struct jsonrpc *rpc, static const struct json_command *find_cmd(const struct jsonrpc *rpc,
@ -528,15 +527,19 @@ struct json_stream *json_stream_fail(struct command *cmd,
return r; return r;
} }
static void parse_request(struct json_connection *jcon, const jsmntok_t tok[]) /* We return struct command_result so command_fail return value has a natural
* sink; we don't actually use the result. */
static struct command_result *
parse_request(struct json_connection *jcon, const jsmntok_t tok[])
{ {
const jsmntok_t *method, *id, *params; const jsmntok_t *method, *id, *params;
struct command *c; struct command *c;
struct command_result *res;
if (tok[0].type != JSMN_OBJECT) { if (tok[0].type != JSMN_OBJECT) {
json_command_malformed(jcon, "null", json_command_malformed(jcon, "null",
"Expected {} for json command"); "Expected {} for json command");
return; return NULL;
} }
method = json_get_member(jcon->buffer, tok, "method"); method = json_get_member(jcon->buffer, tok, "method");
@ -545,12 +548,12 @@ static void parse_request(struct json_connection *jcon, const jsmntok_t tok[])
if (!id) { if (!id) {
json_command_malformed(jcon, "null", "No id"); json_command_malformed(jcon, "null", "No id");
return; return NULL;
} }
if (id->type != JSMN_STRING && id->type != JSMN_PRIMITIVE) { if (id->type != JSMN_STRING && id->type != JSMN_PRIMITIVE) {
json_command_malformed(jcon, "null", json_command_malformed(jcon, "null",
"Expected string/primitive for id"); "Expected string/primitive for id");
return; return NULL;
} }
/* Allocate the command off of the `jsonrpc` object and not /* Allocate the command off of the `jsonrpc` object and not
@ -568,41 +571,45 @@ static void parse_request(struct json_connection *jcon, const jsmntok_t tok[])
tal_add_destructor(c, destroy_command); tal_add_destructor(c, destroy_command);
if (!method || !params) { if (!method || !params) {
command_fail(c, JSONRPC2_INVALID_REQUEST, return command_fail(c, JSONRPC2_INVALID_REQUEST,
method ? "No params" : "No method"); method ? "No params" : "No method");
return;
} }
if (method->type != JSMN_STRING) { if (method->type != JSMN_STRING) {
command_fail(c, JSONRPC2_INVALID_REQUEST, return command_fail(c, JSONRPC2_INVALID_REQUEST,
"Expected string for method"); "Expected string for method");
return;
} }
c->json_cmd = find_cmd(jcon->ld->jsonrpc, jcon->buffer, method); c->json_cmd = find_cmd(jcon->ld->jsonrpc, jcon->buffer, method);
if (!c->json_cmd) { if (!c->json_cmd) {
command_fail(c, JSONRPC2_METHOD_NOT_FOUND, return command_fail(c, JSONRPC2_METHOD_NOT_FOUND,
"Unknown command '%.*s'", "Unknown command '%.*s'",
json_tok_full_len(method), json_tok_full_len(method),
json_tok_full(jcon->buffer, method)); json_tok_full(jcon->buffer, method));
return;
} }
if (c->json_cmd->deprecated && !deprecated_apis) { if (c->json_cmd->deprecated && !deprecated_apis) {
command_fail(c, JSONRPC2_METHOD_NOT_FOUND, return command_fail(c, JSONRPC2_METHOD_NOT_FOUND,
"Command '%.*s' is deprecated", "Command '%.*s' is deprecated",
method->end - method->start, method->end - method->start,
jcon->buffer + method->start); jcon->buffer + method->start);
return;
} }
db_begin_transaction(jcon->ld->wallet->db); db_begin_transaction(jcon->ld->wallet->db);
c->json_cmd->dispatch(c, jcon->buffer, tok, params); res = c->json_cmd->dispatch(c, jcon->buffer, tok, params);
db_commit_transaction(jcon->ld->wallet->db); db_commit_transaction(jcon->ld->wallet->db);
assert(res == &param_failed
|| res == &complete
|| res == &pending
|| res == &unknown);
/* If they didn't complete it, they must call command_still_pending. /* If they didn't complete it, they must call command_still_pending.
* If they completed it, it's freed already. */ * If they completed it, it's freed already. */
if (res == &pending)
assert(c->pending);
list_for_each(&jcon->commands, c, list) list_for_each(&jcon->commands, c, list)
assert(c->pending); assert(c->pending);
return res;
} }
/* Mutual recursion */ /* Mutual recursion */
@ -1002,10 +1009,10 @@ static void destroy_command_canary(struct command *cmd, bool *failed)
*failed = true; *failed = true;
} }
static void json_check(struct command *cmd, static struct command_result *json_check(struct command *cmd,
const char *buffer, const char *buffer,
const jsmntok_t *obj UNNEEDED, const jsmntok_t *obj UNNEEDED,
const jsmntok_t *params) const jsmntok_t *params)
{ {
jsmntok_t *mod_params; jsmntok_t *mod_params;
const jsmntok_t *name_tok; const jsmntok_t *name_tok;
@ -1022,7 +1029,7 @@ static void json_check(struct command *cmd,
p_req("command_to_check", param_command, &name_tok), p_req("command_to_check", param_command, &name_tok),
p_opt_any(), p_opt_any(),
NULL)) NULL))
return; return command_param_failed();
/* Point name_tok to the name, not the value */ /* Point name_tok to the name, not the value */
if (params->type == JSMN_OBJECT) if (params->type == JSMN_OBJECT)
@ -1036,13 +1043,13 @@ static void json_check(struct command *cmd,
cmd->json_cmd->dispatch(cmd, buffer, mod_params, mod_params); cmd->json_cmd->dispatch(cmd, buffer, mod_params, mod_params);
if (failed) if (failed)
return; return command_its_complicated();
response = json_stream_success(cmd); response = json_stream_success(cmd);
json_object_start(response, NULL); json_object_start(response, NULL);
json_add_string(response, "command_to_check", cmd->json_cmd->name); json_add_string(response, "command_to_check", cmd->json_cmd->name);
json_object_end(response); json_object_end(response);
command_success(cmd, response); return command_success(cmd, response);
} }
static const struct json_command check_command = { static const struct json_command check_command = {

8
lightningd/jsonrpc.h

@ -49,10 +49,10 @@ struct command_result;
struct json_command { struct json_command {
const char *name; const char *name;
void (*dispatch)(struct command *, struct command_result *(*dispatch)(struct command *,
const char *buffer, const char *buffer,
const jsmntok_t *obj, const jsmntok_t *obj,
const jsmntok_t *params); const jsmntok_t *params);
const char *description; const char *description;
bool deprecated; bool deprecated;
const char *verbose; const char *verbose;

12
lightningd/log.c

@ -728,10 +728,10 @@ struct command_result *param_loglevel(struct command *cmd,
return NULL; return NULL;
} }
static void json_getlog(struct command *cmd, static struct command_result *json_getlog(struct command *cmd,
const char *buffer, const char *buffer,
const jsmntok_t *obj UNNEEDED, const jsmntok_t *obj UNNEEDED,
const jsmntok_t * params) const jsmntok_t * params)
{ {
struct json_stream *response; struct json_stream *response;
enum log_level *minlevel; enum log_level *minlevel;
@ -740,7 +740,7 @@ static void json_getlog(struct command *cmd,
if (!param(cmd, buffer, params, if (!param(cmd, buffer, params,
p_opt_def("level", param_loglevel, &minlevel, LOG_INFORM), p_opt_def("level", param_loglevel, &minlevel, LOG_INFORM),
NULL)) NULL))
return; return command_param_failed();
response = json_stream_success(cmd); response = json_stream_success(cmd);
json_object_start(response, NULL); json_object_start(response, NULL);
@ -749,7 +749,7 @@ static void json_getlog(struct command *cmd,
json_add_num(response, "bytes_max", (unsigned int) log_max_mem(lr)); json_add_num(response, "bytes_max", (unsigned int) log_max_mem(lr));
json_add_log(response, lr, *minlevel); json_add_log(response, lr, *minlevel);
json_object_end(response); json_object_end(response);
command_success(cmd, response); return command_success(cmd, response);
} }
static const struct json_command getlog_command = { static const struct json_command getlog_command = {

29
lightningd/memdump.c

@ -62,20 +62,20 @@ static void add_memdump(struct json_stream *response,
json_array_end(response); json_array_end(response);
} }
static void json_memdump(struct command *cmd, static struct command_result *json_memdump(struct command *cmd,
const char *buffer, const char *buffer,
const jsmntok_t *obj UNNEEDED, const jsmntok_t *obj UNNEEDED,
const jsmntok_t *params) const jsmntok_t *params)
{ {
struct json_stream *response; struct json_stream *response;
if (!param(cmd, buffer, params, NULL)) if (!param(cmd, buffer, params, NULL))
return; return command_param_failed();
response = json_stream_success(cmd); response = json_stream_success(cmd);
add_memdump(response, NULL, NULL, cmd); add_memdump(response, NULL, NULL, cmd);
command_success(cmd, response); return command_success(cmd, response);
} }
static const struct json_command dev_memdump_command = { static const struct json_command dev_memdump_command = {
@ -284,18 +284,17 @@ void opening_memleak_done(struct command *cmd, struct subd *leaker)
} }
} }
static void json_memleak(struct command *cmd, static struct command_result *json_memleak(struct command *cmd,
const char *buffer, const char *buffer,
const jsmntok_t *obj UNNEEDED, const jsmntok_t *obj UNNEEDED,
const jsmntok_t *params) const jsmntok_t *params)
{ {
if (!param(cmd, buffer, params, NULL)) if (!param(cmd, buffer, params, NULL))
return; return command_param_failed();
if (!getenv("LIGHTNINGD_DEV_MEMLEAK")) { if (!getenv("LIGHTNINGD_DEV_MEMLEAK")) {
command_fail(cmd, LIGHTNINGD, return command_fail(cmd, LIGHTNINGD,
"Leak detection needs $LIGHTNINGD_DEV_MEMLEAK"); "Leak detection needs $LIGHTNINGD_DEV_MEMLEAK");
return;
} }
/* For simplicity, we mark pending, though an error may complete it /* For simplicity, we mark pending, though an error may complete it
@ -304,6 +303,8 @@ static void json_memleak(struct command *cmd,
/* This calls opening_memleak_done() async when all done. */ /* This calls opening_memleak_done() async when all done. */
opening_dev_memleak(cmd); opening_dev_memleak(cmd);
return command_its_complicated();
} }
static const struct json_command dev_memleak_command = { static const struct json_command dev_memleak_command = {

38
lightningd/opening_control.c

@ -762,10 +762,10 @@ void opening_peer_no_active_channels(struct peer *peer)
/** /**
* json_fund_channel - Entrypoint for funding a channel * json_fund_channel - Entrypoint for funding a channel
*/ */
static void json_fund_channel(struct command *cmd, static struct command_result *json_fund_channel(struct command *cmd,
const char *buffer, const char *buffer,
const jsmntok_t *obj UNNEEDED, const jsmntok_t *obj UNNEEDED,
const jsmntok_t *params) const jsmntok_t *params)
{ {
struct command_result *res; struct command_result *res;
const jsmntok_t *sattok; const jsmntok_t *sattok;
@ -787,47 +787,43 @@ static void json_fund_channel(struct command *cmd,
p_opt("feerate", param_feerate, &feerate_per_kw), p_opt("feerate", param_feerate, &feerate_per_kw),
p_opt_def("announce", param_bool, &announce_channel, true), p_opt_def("announce", param_bool, &announce_channel, true),
NULL)) NULL))
return; return command_param_failed();
res = param_wtx(&fc->wtx, buffer, sattok, max_funding_satoshi); res = param_wtx(&fc->wtx, buffer, sattok, max_funding_satoshi);
if (res) if (res)
return; return res;
if (!feerate_per_kw) { if (!feerate_per_kw) {
feerate_per_kw = tal(cmd, u32); feerate_per_kw = tal(cmd, u32);
*feerate_per_kw = opening_feerate(cmd->ld->topology); *feerate_per_kw = opening_feerate(cmd->ld->topology);
if (!*feerate_per_kw) { if (!*feerate_per_kw) {
command_fail(cmd, LIGHTNINGD, "Cannot estimate fees"); return command_fail(cmd, LIGHTNINGD,
return; "Cannot estimate fees");
} }
} }
if (*feerate_per_kw < feerate_floor()) { if (*feerate_per_kw < feerate_floor()) {
command_fail(cmd, LIGHTNINGD, "Feerate below feerate floor"); return command_fail(cmd, LIGHTNINGD,
return; "Feerate below feerate floor");
} }
peer = peer_by_id(cmd->ld, id); peer = peer_by_id(cmd->ld, id);
if (!peer) { if (!peer) {
command_fail(cmd, LIGHTNINGD, "Unknown peer"); return command_fail(cmd, LIGHTNINGD, "Unknown peer");
return;
} }
channel = peer_active_channel(peer); channel = peer_active_channel(peer);
if (channel) { if (channel) {
command_fail(cmd, LIGHTNINGD, "Peer already %s", return command_fail(cmd, LIGHTNINGD, "Peer already %s",
channel_state_name(channel)); channel_state_name(channel));
return;
} }
if (!peer->uncommitted_channel) { if (!peer->uncommitted_channel) {
command_fail(cmd, LIGHTNINGD, "Peer not connected"); return command_fail(cmd, LIGHTNINGD, "Peer not connected");
return;
} }
if (peer->uncommitted_channel->fc) { if (peer->uncommitted_channel->fc) {
command_fail(cmd, LIGHTNINGD, "Already funding channel"); return command_fail(cmd, LIGHTNINGD, "Already funding channel");
return;
} }
/* FIXME: Support push_msat? */ /* FIXME: Support push_msat? */
@ -842,7 +838,7 @@ static void json_fund_channel(struct command *cmd,
res = wtx_select_utxos(&fc->wtx, *feerate_per_kw, res = wtx_select_utxos(&fc->wtx, *feerate_per_kw,
BITCOIN_SCRIPTPUBKEY_P2WSH_LEN); BITCOIN_SCRIPTPUBKEY_P2WSH_LEN);
if (res) if (res)
return; return res;
assert(fc->wtx.amount <= max_funding_satoshi); assert(fc->wtx.amount <= max_funding_satoshi);
@ -862,7 +858,7 @@ static void json_fund_channel(struct command *cmd,
/* Openingd will either succeed, or fail, or tell us the other side /* Openingd will either succeed, or fail, or tell us the other side
* funded first. */ * funded first. */
subd_send_msg(peer->uncommitted_channel->openingd, take(msg)); subd_send_msg(peer->uncommitted_channel->openingd, take(msg));
command_still_pending(cmd); return command_still_pending(cmd);
} }
static const struct json_command fund_channel_command = { static const struct json_command fund_channel_command = {

21
lightningd/options.c

@ -1046,10 +1046,10 @@ static void add_config(struct lightningd *ld,
tal_free(name0); tal_free(name0);
} }
static void json_listconfigs(struct command *cmd, static struct command_result *json_listconfigs(struct command *cmd,
const char *buffer, const char *buffer,
const jsmntok_t *obj UNNEEDED, const jsmntok_t *obj UNNEEDED,
const jsmntok_t *params) const jsmntok_t *params)
{ {
size_t i; size_t i;
struct json_stream *response = NULL; struct json_stream *response = NULL;
@ -1058,7 +1058,7 @@ static void json_listconfigs(struct command *cmd,
if (!param(cmd, buffer, params, if (!param(cmd, buffer, params,
p_opt("config", param_tok, &configtok), p_opt("config", param_tok, &configtok),
NULL)) NULL))
return; return command_param_failed();
if (!configtok) { if (!configtok) {
response = json_stream_success(cmd); response = json_stream_success(cmd);
@ -1097,14 +1097,13 @@ static void json_listconfigs(struct command *cmd,
} }
if (configtok && !response) { if (configtok && !response) {
command_fail(cmd, JSONRPC2_INVALID_PARAMS, return command_fail(cmd, JSONRPC2_INVALID_PARAMS,
"Unknown config option '%.*s'", "Unknown config option '%.*s'",
json_tok_full_len(configtok), json_tok_full_len(configtok),
json_tok_full(buffer, configtok)); json_tok_full(buffer, configtok));
return;
} }
json_object_end(response); json_object_end(response);
command_success(cmd, response); return command_success(cmd, response);
} }
static const struct json_command listconfigs_command = { static const struct json_command listconfigs_command = {

63
lightningd/pay.c

@ -941,10 +941,10 @@ static void json_sendpay_on_resolve(const struct sendpay_result* r,
json_waitsendpay_on_resolve(r, cmd); json_waitsendpay_on_resolve(r, cmd);
} }
static void json_sendpay(struct command *cmd, static struct command_result *json_sendpay(struct command *cmd,
const char *buffer, const char *buffer,
const jsmntok_t *obj UNNEEDED, const jsmntok_t *obj UNNEEDED,
const jsmntok_t *params) const jsmntok_t *params)
{ {
const jsmntok_t *routetok; const jsmntok_t *routetok;
const jsmntok_t *t, *end; const jsmntok_t *t, *end;
@ -960,7 +960,7 @@ static void json_sendpay(struct command *cmd,
p_opt("description", param_escaped_string, &description), p_opt("description", param_escaped_string, &description),
p_opt("msatoshi", param_u64, &msatoshi), p_opt("msatoshi", param_u64, &msatoshi),
NULL)) NULL))
return; return command_param_failed();
end = json_next(routetok); end = json_next(routetok);
n_hops = 0; n_hops = 0;
@ -978,7 +978,7 @@ static void json_sendpay(struct command *cmd,
p_req("delay", param_number, &delay), p_req("delay", param_number, &delay),
p_req("channel", param_short_channel_id, &channel), p_req("channel", param_short_channel_id, &channel),
NULL)) NULL))
return; return command_param_failed();
tal_resize(&route, n_hops + 1); tal_resize(&route, n_hops + 1);
@ -990,8 +990,7 @@ static void json_sendpay(struct command *cmd,
} }
if (n_hops == 0) { if (n_hops == 0) {
command_fail(cmd, JSONRPC2_INVALID_PARAMS, "Empty route"); return command_fail(cmd, JSONRPC2_INVALID_PARAMS, "Empty route");
return;
} }
/* The given msatoshi is the actual payment that the payee is /* The given msatoshi is the actual payment that the payee is
@ -1002,10 +1001,9 @@ static void json_sendpay(struct command *cmd,
if (msatoshi) { if (msatoshi) {
if (!(*msatoshi <= route[n_hops-1].amount && if (!(*msatoshi <= route[n_hops-1].amount &&
route[n_hops-1].amount <= 2 * *msatoshi)) { route[n_hops-1].amount <= 2 * *msatoshi)) {
command_fail(cmd, JSONRPC2_INVALID_PARAMS, return command_fail(cmd, JSONRPC2_INVALID_PARAMS,
"msatoshi %"PRIu64" out of range", "msatoshi %"PRIu64" out of range",
*msatoshi); *msatoshi);
return;
} }
} }
@ -1013,7 +1011,8 @@ static void json_sendpay(struct command *cmd,
msatoshi ? *msatoshi : route[n_hops-1].amount, msatoshi ? *msatoshi : route[n_hops-1].amount,
description, description,
&json_sendpay_on_resolve, cmd)) &json_sendpay_on_resolve, cmd))
command_still_pending(cmd); return command_still_pending(cmd);
return command_its_complicated();
} }
static const struct json_command sendpay_command = { static const struct json_command sendpay_command = {
@ -1028,10 +1027,10 @@ static void waitsendpay_timeout(struct command *cmd)
command_fail(cmd, PAY_IN_PROGRESS, "Timed out while waiting"); command_fail(cmd, PAY_IN_PROGRESS, "Timed out while waiting");
} }
static void json_waitsendpay(struct command *cmd, static struct command_result *json_waitsendpay(struct command *cmd,
const char *buffer, const char *buffer,
const jsmntok_t *obj UNNEEDED, const jsmntok_t *obj UNNEEDED,
const jsmntok_t *params) const jsmntok_t *params)
{ {
struct sha256 *rhash; struct sha256 *rhash;
unsigned int *timeout; unsigned int *timeout;
@ -1040,15 +1039,15 @@ static void json_waitsendpay(struct command *cmd,
p_req("payment_hash", param_sha256, &rhash), p_req("payment_hash", param_sha256, &rhash),
p_opt("timeout", param_number, &timeout), p_opt("timeout", param_number, &timeout),
NULL)) NULL))
return; return command_param_failed();
if (!wait_payment(cmd, cmd->ld, rhash, &json_waitsendpay_on_resolve, cmd)) if (!wait_payment(cmd, cmd->ld, rhash, &json_waitsendpay_on_resolve, cmd))
return; return command_its_complicated();
if (timeout) if (timeout)
new_reltimer(&cmd->ld->timers, cmd, time_from_sec(*timeout), new_reltimer(&cmd->ld->timers, cmd, time_from_sec(*timeout),
&waitsendpay_timeout, cmd); &waitsendpay_timeout, cmd);
command_still_pending(cmd); return command_still_pending(cmd);
} }
static const struct json_command waitsendpay_command = { static const struct json_command waitsendpay_command = {
@ -1059,10 +1058,10 @@ static const struct json_command waitsendpay_command = {
}; };
AUTODATA(json_command, &waitsendpay_command); AUTODATA(json_command, &waitsendpay_command);
static void json_listpayments(struct command *cmd, static struct command_result *json_listpayments(struct command *cmd,
const char *buffer, const char *buffer,
const jsmntok_t *obj UNNEEDED, const jsmntok_t *obj UNNEEDED,
const jsmntok_t *params) const jsmntok_t *params)
{ {
const struct wallet_payment **payments; const struct wallet_payment **payments;
struct json_stream *response; struct json_stream *response;
@ -1073,13 +1072,12 @@ static void json_listpayments(struct command *cmd,
p_opt("bolt11", param_string, &b11str), p_opt("bolt11", param_string, &b11str),
p_opt("payment_hash", param_sha256, &rhash), p_opt("payment_hash", param_sha256, &rhash),
NULL)) NULL))
return; return command_param_failed();
if (rhash && b11str) { if (rhash && b11str) {
command_fail(cmd, JSONRPC2_INVALID_PARAMS, return command_fail(cmd, JSONRPC2_INVALID_PARAMS,
"Can only specify one of" "Can only specify one of"
" {bolt11} or {payment_hash}"); " {bolt11} or {payment_hash}");
return;
} }
if (b11str) { if (b11str) {
@ -1088,9 +1086,8 @@ static void json_listpayments(struct command *cmd,
b11 = bolt11_decode(cmd, b11str, NULL, &fail); b11 = bolt11_decode(cmd, b11str, NULL, &fail);
if (!b11) { if (!b11) {
command_fail(cmd, JSONRPC2_INVALID_PARAMS, return command_fail(cmd, JSONRPC2_INVALID_PARAMS,
"Invalid bolt11: %s", fail); "Invalid bolt11: %s", fail);
return;
} }
rhash = &b11->payment_hash; rhash = &b11->payment_hash;
} }
@ -1109,7 +1106,7 @@ static void json_listpayments(struct command *cmd,
json_array_end(response); json_array_end(response);
json_object_end(response); json_object_end(response);
command_success(cmd, response); return command_success(cmd, response);
} }
static const struct json_command listpayments_command = { static const struct json_command listpayments_command = {

39
lightningd/payalgo.c

@ -592,10 +592,10 @@ static void json_pay_stop_retrying(struct pay *pay)
json_pay_failure(pay, sr); json_pay_failure(pay, sr);
} }
static void json_pay(struct command *cmd, static struct command_result *json_pay(struct command *cmd,
const char *buffer, const char *buffer,
const jsmntok_t *obj UNNEEDED, const jsmntok_t *obj UNNEEDED,
const jsmntok_t *params) const jsmntok_t *params)
{ {
double *riskfactor; double *riskfactor;
double *maxfeepercent; double *maxfeepercent;
@ -619,13 +619,12 @@ static void json_pay(struct command *cmd,
cmd->ld->config.locktime_max), cmd->ld->config.locktime_max),
p_opt_def("exemptfee", param_number, &exemptfee, 5000), p_opt_def("exemptfee", param_number, &exemptfee, 5000),
NULL)) NULL))
return; return command_param_failed();
b11 = bolt11_decode(pay, b11str, desc, &fail); b11 = bolt11_decode(pay, b11str, desc, &fail);
if (!b11) { if (!b11) {
command_fail(cmd, JSONRPC2_INVALID_PARAMS, return command_fail(cmd, JSONRPC2_INVALID_PARAMS,
"Invalid bolt11: %s", fail); "Invalid bolt11: %s", fail);
return;
} }
pay->cmd = cmd; pay->cmd = cmd;
@ -638,16 +637,14 @@ static void json_pay(struct command *cmd,
if (b11->msatoshi) { if (b11->msatoshi) {
if (msatoshi) { if (msatoshi) {
command_fail(cmd, JSONRPC2_INVALID_PARAMS, return command_fail(cmd, JSONRPC2_INVALID_PARAMS,
"msatoshi parameter unnecessary"); "msatoshi parameter unnecessary");
return;
} }
msatoshi = b11->msatoshi; msatoshi = b11->msatoshi;
} else { } else {
if (!msatoshi) { if (!msatoshi) {
command_fail(cmd, JSONRPC2_INVALID_PARAMS, return command_fail(cmd, JSONRPC2_INVALID_PARAMS,
"msatoshi parameter required"); "msatoshi parameter required");
return;
} }
} }
pay->msatoshi = *msatoshi; pay->msatoshi = *msatoshi;
@ -655,12 +652,11 @@ static void json_pay(struct command *cmd,
pay->maxfeepercent = *maxfeepercent; pay->maxfeepercent = *maxfeepercent;
if (*maxdelay < pay->min_final_cltv_expiry) { if (*maxdelay < pay->min_final_cltv_expiry) {
command_fail(cmd, JSONRPC2_INVALID_PARAMS, return command_fail(cmd, JSONRPC2_INVALID_PARAMS,
"maxdelay (%u) must be greater than " "maxdelay (%u) must be greater than "
"min_final_cltv_expiry (%"PRIu32") of " "min_final_cltv_expiry (%"PRIu32") of "
"invoice", "invoice",
*maxdelay, pay->min_final_cltv_expiry); *maxdelay, pay->min_final_cltv_expiry);
return;
} }
pay->maxdelay = *maxdelay; pay->maxdelay = *maxdelay;
@ -688,11 +684,12 @@ static void json_pay(struct command *cmd,
if (json_pay_try(pay)) if (json_pay_try(pay))
command_still_pending(cmd); command_still_pending(cmd);
else else
return; return command_its_complicated();
/* Set up timeout. */ /* Set up timeout. */
new_reltimer(&cmd->ld->timers, pay, time_from_sec(*retryfor), new_reltimer(&cmd->ld->timers, pay, time_from_sec(*retryfor),
&json_pay_stop_retrying, pay); &json_pay_stop_retrying, pay);
return command_its_complicated();
} }
static const struct json_command pay_command = { static const struct json_command pay_command = {

194
lightningd/peer_control.c

@ -803,10 +803,10 @@ static void json_add_peer(struct lightningd *ld,
json_object_end(response); json_object_end(response);
} }
static void json_listpeers(struct command *cmd, static struct command_result *json_listpeers(struct command *cmd,
const char *buffer, const char *buffer,
const jsmntok_t *obj UNNEEDED, const jsmntok_t *obj UNNEEDED,
const jsmntok_t *params) const jsmntok_t *params)
{ {
enum log_level *ll; enum log_level *ll;
struct pubkey *specific_id; struct pubkey *specific_id;
@ -817,7 +817,7 @@ static void json_listpeers(struct command *cmd,
p_opt("id", param_pubkey, &specific_id), p_opt("id", param_pubkey, &specific_id),
p_opt("level", param_loglevel, &ll), p_opt("level", param_loglevel, &ll),
NULL)) NULL))
return; return command_param_failed();
response = json_stream_success(cmd); response = json_stream_success(cmd);
json_object_start(response, NULL); json_object_start(response, NULL);
@ -832,7 +832,7 @@ static void json_listpeers(struct command *cmd,
} }
json_array_end(response); json_array_end(response);
json_object_end(response); json_object_end(response);
command_success(cmd, response); return command_success(cmd, response);
} }
static const struct json_command listpeers_command = { static const struct json_command listpeers_command = {
@ -891,10 +891,10 @@ command_find_channel(struct command *cmd,
} }
} }
static void json_close(struct command *cmd, static struct command_result *json_close(struct command *cmd,
const char *buffer, const char *buffer,
const jsmntok_t *obj UNNEEDED, const jsmntok_t *obj UNNEEDED,
const jsmntok_t *params) const jsmntok_t *params)
{ {
const jsmntok_t *idtok; const jsmntok_t *idtok;
struct peer *peer; struct peer *peer;
@ -907,7 +907,7 @@ static void json_close(struct command *cmd,
p_opt_def("force", param_bool, &force, false), p_opt_def("force", param_bool, &force, false),
p_opt_def("timeout", param_number, &timeout, 30), p_opt_def("timeout", param_number, &timeout, 30),
NULL)) NULL))
return; return command_param_failed();
peer = peer_from_json(cmd->ld, buffer, idtok); peer = peer_from_json(cmd->ld, buffer, idtok);
if (peer) if (peer)
@ -915,7 +915,7 @@ static void json_close(struct command *cmd,
else { else {
channel = command_find_channel(cmd, buffer, idtok); channel = command_find_channel(cmd, buffer, idtok);
if (!channel) if (!channel)
return; return command_its_complicated();
} }
if (!channel && peer) { if (!channel && peer) {
@ -924,12 +924,10 @@ static void json_close(struct command *cmd,
/* Easy case: peer can simply be forgotten. */ /* Easy case: peer can simply be forgotten. */
kill_uncommitted_channel(uc, "close command called"); kill_uncommitted_channel(uc, "close command called");
command_success(cmd, null_response(cmd)); return command_success(cmd, null_response(cmd));
return;
} }
command_fail(cmd, LIGHTNINGD, return command_fail(cmd, LIGHTNINGD,
"Peer has no active channel"); "Peer has no active channel");
return;
} }
/* Normal case. /* Normal case.
@ -941,9 +939,8 @@ static void json_close(struct command *cmd,
channel->state != CHANNELD_AWAITING_LOCKIN && channel->state != CHANNELD_AWAITING_LOCKIN &&
channel->state != CHANNELD_SHUTTING_DOWN && channel->state != CHANNELD_SHUTTING_DOWN &&
channel->state != CLOSINGD_SIGEXCHANGE) { channel->state != CLOSINGD_SIGEXCHANGE) {
command_fail(cmd, LIGHTNINGD, "Channel is in state %s", return command_fail(cmd, LIGHTNINGD, "Channel is in state %s",
channel_state_name(channel)); channel_state_name(channel));
return;
} }
/* If normal or locking in, transition to shutting down /* If normal or locking in, transition to shutting down
@ -963,7 +960,7 @@ static void json_close(struct command *cmd,
register_close_command(cmd->ld, cmd, channel, *timeout, *force); register_close_command(cmd->ld, cmd, channel, *timeout, *force);
/* Wait until close drops down to chain. */ /* Wait until close drops down to chain. */
command_still_pending(cmd); return command_still_pending(cmd);
} }
static const struct json_command close_command = { static const struct json_command close_command = {
@ -1035,10 +1032,10 @@ void load_channels_from_wallet(struct lightningd *ld)
htlcs_reconnect(ld, &ld->htlcs_in, &ld->htlcs_out); htlcs_reconnect(ld, &ld->htlcs_in, &ld->htlcs_out);
} }
static void json_disconnect(struct command *cmd, static struct command_result *json_disconnect(struct command *cmd,
const char *buffer, const char *buffer,
const jsmntok_t *obj UNNEEDED, const jsmntok_t *obj UNNEEDED,
const jsmntok_t *params) const jsmntok_t *params)
{ {
struct pubkey *id; struct pubkey *id;
struct peer *peer; struct peer *peer;
@ -1049,32 +1046,28 @@ static void json_disconnect(struct command *cmd,
p_req("id", param_pubkey, &id), p_req("id", param_pubkey, &id),
p_opt_def("force", param_bool, &force, false), p_opt_def("force", param_bool, &force, false),
NULL)) NULL))
return; return command_param_failed();
peer = peer_by_id(cmd->ld, id); peer = peer_by_id(cmd->ld, id);
if (!peer) { if (!peer) {
command_fail(cmd, LIGHTNINGD, "Peer not connected"); return command_fail(cmd, LIGHTNINGD, "Peer not connected");
return;
} }
channel = peer_active_channel(peer); channel = peer_active_channel(peer);
if (channel) { if (channel) {
if (*force) { if (*force) {
channel_fail_transient(channel, channel_fail_transient(channel,
"disconnect command force=true"); "disconnect command force=true");
command_success(cmd, null_response(cmd)); return command_success(cmd, null_response(cmd));
return;
} }
command_fail(cmd, LIGHTNINGD, "Peer is in state %s", return command_fail(cmd, LIGHTNINGD, "Peer is in state %s",
channel_state_name(channel)); channel_state_name(channel));
return;
} }
if (!peer->uncommitted_channel) { if (!peer->uncommitted_channel) {
command_fail(cmd, LIGHTNINGD, "Peer not connected"); return command_fail(cmd, LIGHTNINGD, "Peer not connected");
return;
} }
kill_uncommitted_channel(peer->uncommitted_channel, kill_uncommitted_channel(peer->uncommitted_channel,
"disconnect command"); "disconnect command");
command_success(cmd, null_response(cmd)); return command_success(cmd, null_response(cmd));
} }
static const struct json_command disconnect_command = { static const struct json_command disconnect_command = {
@ -1084,10 +1077,10 @@ static const struct json_command disconnect_command = {
}; };
AUTODATA(json_command, &disconnect_command); AUTODATA(json_command, &disconnect_command);
static void json_getinfo(struct command *cmd, static struct command_result *json_getinfo(struct command *cmd,
const char *buffer, const char *buffer,
const jsmntok_t *obj UNNEEDED, const jsmntok_t *obj UNNEEDED,
const jsmntok_t *params) const jsmntok_t *params)
{ {
struct json_stream *response; struct json_stream *response;
struct peer *peer; struct peer *peer;
@ -1096,7 +1089,7 @@ static void json_getinfo(struct command *cmd,
inactive_channels = 0, num_peers = 0; inactive_channels = 0, num_peers = 0;
if (!param(cmd, buffer, params, NULL)) if (!param(cmd, buffer, params, NULL))
return; return command_param_failed();
response = json_stream_success(cmd); response = json_stream_success(cmd);
json_object_start(response, NULL); json_object_start(response, NULL);
@ -1148,7 +1141,7 @@ static void json_getinfo(struct command *cmd,
json_add_u64(response, "msatoshi_fees_collected", json_add_u64(response, "msatoshi_fees_collected",
wallet_total_forward_fees(cmd->ld->wallet)); wallet_total_forward_fees(cmd->ld->wallet));
json_object_end(response); json_object_end(response);
command_success(cmd, response); return command_success(cmd, response);
} }
static const struct json_command getinfo_command = { static const struct json_command getinfo_command = {
@ -1159,10 +1152,10 @@ static const struct json_command getinfo_command = {
AUTODATA(json_command, &getinfo_command); AUTODATA(json_command, &getinfo_command);
#if DEVELOPER #if DEVELOPER
static void json_sign_last_tx(struct command *cmd, static struct command_result *json_sign_last_tx(struct command *cmd,
const char *buffer, const char *buffer,
const jsmntok_t *obj UNNEEDED, const jsmntok_t *obj UNNEEDED,
const jsmntok_t *params) const jsmntok_t *params)
{ {
struct pubkey *peerid; struct pubkey *peerid;
struct peer *peer; struct peer *peer;
@ -1173,19 +1166,17 @@ static void json_sign_last_tx(struct command *cmd,
if (!param(cmd, buffer, params, if (!param(cmd, buffer, params,
p_req("id", param_pubkey, &peerid), p_req("id", param_pubkey, &peerid),
NULL)) NULL))
return; return command_param_failed();
peer = peer_by_id(cmd->ld, peerid); peer = peer_by_id(cmd->ld, peerid);
if (!peer) { if (!peer) {
command_fail(cmd, LIGHTNINGD, return command_fail(cmd, LIGHTNINGD,
"Could not find peer with that id"); "Could not find peer with that id");
return;
} }
channel = peer_active_channel(peer); channel = peer_active_channel(peer);
if (!channel) { if (!channel) {
command_fail(cmd, LIGHTNINGD, return command_fail(cmd, LIGHTNINGD,
"Could not find active channel"); "Could not find active channel");
return;
} }
response = json_stream_success(cmd); response = json_stream_success(cmd);
@ -1198,7 +1189,7 @@ static void json_sign_last_tx(struct command *cmd,
json_object_start(response, NULL); json_object_start(response, NULL);
json_add_hex_talarr(response, "tx", linear); json_add_hex_talarr(response, "tx", linear);
json_object_end(response); json_object_end(response);
command_success(cmd, response); return command_success(cmd, response);
} }
static const struct json_command dev_sign_last_tx = { static const struct json_command dev_sign_last_tx = {
@ -1208,10 +1199,10 @@ static const struct json_command dev_sign_last_tx = {
}; };
AUTODATA(json_command, &dev_sign_last_tx); AUTODATA(json_command, &dev_sign_last_tx);
static void json_dev_fail(struct command *cmd, static struct command_result *json_dev_fail(struct command *cmd,
const char *buffer, const char *buffer,
const jsmntok_t *obj UNNEEDED, const jsmntok_t *obj UNNEEDED,
const jsmntok_t *params) const jsmntok_t *params)
{ {
struct pubkey *peerid; struct pubkey *peerid;
struct peer *peer; struct peer *peer;
@ -1220,24 +1211,22 @@ static void json_dev_fail(struct command *cmd,
if (!param(cmd, buffer, params, if (!param(cmd, buffer, params,
p_req("id", param_pubkey, &peerid), p_req("id", param_pubkey, &peerid),
NULL)) NULL))
return; return command_param_failed();
peer = peer_by_id(cmd->ld, peerid); peer = peer_by_id(cmd->ld, peerid);
if (!peer) { if (!peer) {
command_fail(cmd, LIGHTNINGD, return command_fail(cmd, LIGHTNINGD,
"Could not find peer with that id"); "Could not find peer with that id");
return;
} }
channel = peer_active_channel(peer); channel = peer_active_channel(peer);
if (!channel) { if (!channel) {
command_fail(cmd, LIGHTNINGD, return command_fail(cmd, LIGHTNINGD,
"Could not find active channel with peer"); "Could not find active channel with peer");
return;
} }
channel_internal_error(channel, "Failing due to dev-fail command"); channel_internal_error(channel, "Failing due to dev-fail command");
command_success(cmd, null_response(cmd)); return command_success(cmd, null_response(cmd));
} }
static const struct json_command dev_fail_command = { static const struct json_command dev_fail_command = {
@ -1252,13 +1241,13 @@ static void dev_reenable_commit_finished(struct subd *channeld UNUSED,
const int *fds UNUSED, const int *fds UNUSED,
struct command *cmd) struct command *cmd)
{ {
command_success(cmd, null_response(cmd)); was_pending(command_success(cmd, null_response(cmd)));
} }
static void json_dev_reenable_commit(struct command *cmd, static struct command_result *json_dev_reenable_commit(struct command *cmd,
const char *buffer, const char *buffer,
const jsmntok_t *obj UNNEEDED, const jsmntok_t *obj UNNEEDED,
const jsmntok_t *params) const jsmntok_t *params)
{ {
struct pubkey *peerid; struct pubkey *peerid;
struct peer *peer; struct peer *peer;
@ -1268,37 +1257,33 @@ static void json_dev_reenable_commit(struct command *cmd,
if (!param(cmd, buffer, params, if (!param(cmd, buffer, params,
p_req("id", param_pubkey, &peerid), p_req("id", param_pubkey, &peerid),
NULL)) NULL))
return; return command_param_failed();
peer = peer_by_id(cmd->ld, peerid); peer = peer_by_id(cmd->ld, peerid);
if (!peer) { if (!peer) {
command_fail(cmd, LIGHTNINGD, return command_fail(cmd, LIGHTNINGD,
"Could not find peer with that id"); "Could not find peer with that id");
return;
} }
channel = peer_active_channel(peer); channel = peer_active_channel(peer);
if (!channel) { if (!channel) {
command_fail(cmd, LIGHTNINGD, return command_fail(cmd, LIGHTNINGD,
"Peer has no active channel"); "Peer has no active channel");
return;
} }
if (!channel->owner) { if (!channel->owner) {
command_fail(cmd, LIGHTNINGD, return command_fail(cmd, LIGHTNINGD,
"Peer has no owner"); "Peer has no owner");
return;
} }
if (!streq(channel->owner->name, "lightning_channeld")) { if (!streq(channel->owner->name, "lightning_channeld")) {
command_fail(cmd, LIGHTNINGD, return command_fail(cmd, LIGHTNINGD,
"Peer owned by %s", channel->owner->name); "Peer owned by %s", channel->owner->name);
return;
} }
msg = towire_channel_dev_reenable_commit(channel); msg = towire_channel_dev_reenable_commit(channel);
subd_req(peer, channel->owner, take(msg), -1, 0, subd_req(peer, channel->owner, take(msg), -1, 0,
dev_reenable_commit_finished, cmd); dev_reenable_commit_finished, cmd);
command_still_pending(cmd); return command_still_pending(cmd);
} }
static const struct json_command dev_reenable_commit = { static const struct json_command dev_reenable_commit = {
@ -1347,10 +1332,10 @@ static void process_dev_forget_channel(struct bitcoind *bitcoind UNUSED,
command_success(forget->cmd, response); command_success(forget->cmd, response);
} }
static void json_dev_forget_channel(struct command *cmd, static struct command_result *json_dev_forget_channel(struct command *cmd,
const char *buffer, const char *buffer,
const jsmntok_t *obj UNNEEDED, const jsmntok_t *obj UNNEEDED,
const jsmntok_t *params) const jsmntok_t *params)
{ {
struct pubkey *peerid; struct pubkey *peerid;
struct peer *peer; struct peer *peer;
@ -1365,14 +1350,13 @@ static void json_dev_forget_channel(struct command *cmd,
p_opt("short_channel_id", param_short_channel_id, &scid), p_opt("short_channel_id", param_short_channel_id, &scid),
p_opt_def("force", param_bool, &force, false), p_opt_def("force", param_bool, &force, false),
NULL)) NULL))
return; return command_param_failed();
forget->force = *force; forget->force = *force;
peer = peer_by_id(cmd->ld, peerid); peer = peer_by_id(cmd->ld, peerid);
if (!peer) { if (!peer) {
command_fail(cmd, LIGHTNINGD, return command_fail(cmd, LIGHTNINGD,
"Could not find channel with that peer"); "Could not find channel with that peer");
return;
} }
forget->channel = NULL; forget->channel = NULL;
@ -1384,34 +1368,30 @@ static void json_dev_forget_channel(struct command *cmd,
continue; continue;
} }
if (forget->channel) { if (forget->channel) {
command_fail(cmd, LIGHTNINGD, return command_fail(cmd, LIGHTNINGD,
"Multiple channels:" "Multiple channels:"
" please specify short_channel_id"); " please specify short_channel_id");
return;
} }
forget->channel = channel; forget->channel = channel;
} }
if (!forget->channel) { if (!forget->channel) {
command_fail(cmd, LIGHTNINGD, return command_fail(cmd, LIGHTNINGD,
"No channels matching that short_channel_id"); "No channels matching that short_channel_id");
return;
} }
if (channel_has_htlc_out(forget->channel) || if (channel_has_htlc_out(forget->channel) ||
channel_has_htlc_in(forget->channel)) { channel_has_htlc_in(forget->channel)) {
command_fail(cmd, LIGHTNINGD, return command_fail(cmd, LIGHTNINGD,
"This channel has HTLCs attached and it is " "This channel has HTLCs attached and it is "
"not safe to forget it. Please use `close` " "not safe to forget it. Please use `close` "
"or `dev-fail` instead."); "or `dev-fail` instead.");
return;
} }
bitcoind_gettxout(cmd->ld->topology->bitcoind, bitcoind_gettxout(cmd->ld->topology->bitcoind,
&forget->channel->funding_txid, &forget->channel->funding_txid,
forget->channel->funding_outnum, forget->channel->funding_outnum,
process_dev_forget_channel, forget); process_dev_forget_channel, forget);
command_still_pending(cmd); return command_still_pending(cmd);
} }
static const struct json_command dev_forget_channel_command = { static const struct json_command dev_forget_channel_command = {

29
lightningd/peer_htlcs.c

@ -1792,10 +1792,10 @@ void htlcs_reconnect(struct lightningd *ld,
#if DEVELOPER #if DEVELOPER
static void json_dev_ignore_htlcs(struct command *cmd, static struct command_result *json_dev_ignore_htlcs(struct command *cmd,
const char *buffer, const char *buffer,
const jsmntok_t *obj UNNEEDED, const jsmntok_t *obj UNNEEDED,
const jsmntok_t *params) const jsmntok_t *params)
{ {
struct pubkey *peerid; struct pubkey *peerid;
struct peer *peer; struct peer *peer;
@ -1805,17 +1805,16 @@ static void json_dev_ignore_htlcs(struct command *cmd,
p_req("id", param_pubkey, &peerid), p_req("id", param_pubkey, &peerid),
p_req("ignore", param_bool, &ignore), p_req("ignore", param_bool, &ignore),
NULL)) NULL))
return; return command_param_failed();
peer = peer_by_id(cmd->ld, peerid); peer = peer_by_id(cmd->ld, peerid);
if (!peer) { if (!peer) {
command_fail(cmd, LIGHTNINGD, return command_fail(cmd, LIGHTNINGD,
"Could not find channel with that peer"); "Could not find channel with that peer");
return;
} }
peer->ignore_htlcs = *ignore; peer->ignore_htlcs = *ignore;
command_success(cmd, null_response(cmd)); return command_success(cmd, null_response(cmd));
} }
static const struct json_command dev_ignore_htlcs = { static const struct json_command dev_ignore_htlcs = {
@ -1849,22 +1848,22 @@ static void listforwardings_add_forwardings(struct json_stream *response, struct
tal_free(forwardings); tal_free(forwardings);
} }
static void json_listforwards(struct command *cmd, static struct command_result *json_listforwards(struct command *cmd,
const char *buffer, const char *buffer,
const jsmntok_t *obj UNNEEDED, const jsmntok_t *obj UNNEEDED,
const jsmntok_t *params) const jsmntok_t *params)
{ {
struct json_stream *response; struct json_stream *response;
if (!param(cmd, buffer, params, NULL)) if (!param(cmd, buffer, params, NULL))
return; return command_param_failed();
response = json_stream_success(cmd); response = json_stream_success(cmd);
json_object_start(response, NULL); json_object_start(response, NULL);
listforwardings_add_forwardings(response, cmd->ld->wallet); listforwardings_add_forwardings(response, cmd->ld->wallet);
json_object_end(response); json_object_end(response);
command_success(cmd, response); return command_success(cmd, response);
} }
static const struct json_command listforwards_command = { static const struct json_command listforwards_command = {

22
lightningd/ping.c

@ -79,10 +79,10 @@ void ping_reply(struct subd *subd, const u8 *msg)
} }
} }
static void json_ping(struct command *cmd, static struct command_result *json_ping(struct command *cmd,
const char *buffer, const char *buffer,
const jsmntok_t *obj UNNEEDED, const jsmntok_t *obj UNNEEDED,
const jsmntok_t *params) const jsmntok_t *params)
{ {
u8 *msg; u8 *msg;
unsigned int *len, *pongbytes; unsigned int *len, *pongbytes;
@ -93,7 +93,7 @@ static void json_ping(struct command *cmd,
p_opt_def("len", param_number, &len, 128), p_opt_def("len", param_number, &len, 128),
p_opt_def("pongbytes", param_number, &pongbytes, 128), p_opt_def("pongbytes", param_number, &pongbytes, 128),
NULL)) NULL))
return; return command_param_failed();
/* BOLT #1: /* BOLT #1:
* *
@ -110,16 +110,14 @@ static void json_ping(struct command *cmd,
* * [`byteslen`:`ignored`] * * [`byteslen`:`ignored`]
*/ */
if (*len > 65535 - 2 - 2 - 2) { if (*len > 65535 - 2 - 2 - 2) {
command_fail(cmd, JSONRPC2_INVALID_PARAMS, return command_fail(cmd, JSONRPC2_INVALID_PARAMS,
"%u would result in oversize ping", *len); "%u would result in oversize ping", *len);
return;
} }
/* Note that > 65531 is valid: it means "no pong reply" */ /* Note that > 65531 is valid: it means "no pong reply" */
if (*pongbytes > 65535) { if (*pongbytes > 65535) {
command_fail(cmd, JSONRPC2_INVALID_PARAMS, return command_fail(cmd, JSONRPC2_INVALID_PARAMS,
"pongbytes %u > 65535", *pongbytes); "pongbytes %u > 65535", *pongbytes);
return;
} }
/* parent is cmd, so when we complete cmd, we free this. */ /* parent is cmd, so when we complete cmd, we free this. */
@ -128,7 +126,7 @@ static void json_ping(struct command *cmd,
/* gossipd handles all pinging, even if it's in another daemon. */ /* gossipd handles all pinging, even if it's in another daemon. */
msg = towire_gossip_ping(NULL, id, *pongbytes, *len); msg = towire_gossip_ping(NULL, id, *pongbytes, *len);
subd_send_msg(cmd->ld->gossip, take(msg)); subd_send_msg(cmd->ld->gossip, take(msg));
command_still_pending(cmd); return command_still_pending(cmd);
} }
static const struct json_command ping_command = { static const struct json_command ping_command = {

11
lightningd/plugin.c

@ -656,9 +656,10 @@ static struct plugin *find_plugin_for_command(struct command *cmd)
abort(); abort();
} }
static void plugin_rpcmethod_dispatch(struct command *cmd, const char *buffer, static struct command_result *plugin_rpcmethod_dispatch(struct command *cmd,
const jsmntok_t *toks, const char *buffer,
const jsmntok_t *params UNNEEDED) const jsmntok_t *toks,
const jsmntok_t *params UNNEEDED)
{ {
const jsmntok_t *idtok; const jsmntok_t *idtok;
struct plugin *plugin; struct plugin *plugin;
@ -668,7 +669,7 @@ static void plugin_rpcmethod_dispatch(struct command *cmd, const char *buffer,
if (cmd->mode == CMD_USAGE) { if (cmd->mode == CMD_USAGE) {
/* FIXME! */ /* FIXME! */
cmd->usage = "[params]"; cmd->usage = "[params]";
return; return command_param_failed();
} }
plugin = find_plugin_for_command(cmd); plugin = find_plugin_for_command(cmd);
@ -683,7 +684,7 @@ static void plugin_rpcmethod_dispatch(struct command *cmd, const char *buffer,
json_stream_forward_change_id(req->stream, buffer, toks, idtok, id); json_stream_forward_change_id(req->stream, buffer, toks, idtok, id);
plugin_request_queue(plugin, req); plugin_request_queue(plugin, req);
command_still_pending(cmd); return command_still_pending(cmd);
} }
static bool plugin_rpcmethod_add(struct plugin *plugin, static bool plugin_rpcmethod_add(struct plugin *plugin,

6
lightningd/test/run-invoice-select-inchan.c

@ -49,6 +49,12 @@ struct command_result *command_fail(struct command *cmd UNNEEDED, int code UNNEE
struct command_result *command_failed(struct command *cmd UNNEEDED, struct command_result *command_failed(struct command *cmd UNNEEDED,
struct json_stream *result UNNEEDED) struct json_stream *result UNNEEDED)
{ fprintf(stderr, "command_failed called!\n"); abort(); } { fprintf(stderr, "command_failed called!\n"); abort(); }
/* Generated stub for command_its_complicated */
struct command_result *command_its_complicated(void)
{ fprintf(stderr, "command_its_complicated called!\n"); abort(); }
/* Generated stub for command_param_failed */
struct command_result *command_param_failed(void)
{ fprintf(stderr, "command_param_failed called!\n"); abort(); }
/* Generated stub for command_still_pending */ /* Generated stub for command_still_pending */
struct command_result *command_still_pending(struct command *cmd UNNEEDED) struct command_result *command_still_pending(struct command *cmd UNNEEDED)
{ fprintf(stderr, "command_still_pending called!\n"); abort(); } { fprintf(stderr, "command_still_pending called!\n"); abort(); }

6
wallet/test/run-wallet.c

@ -55,6 +55,12 @@ struct command_result *command_fail(struct command *cmd UNNEEDED, int code UNNEE
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_its_complicated */
struct command_result *command_its_complicated(void)
{ fprintf(stderr, "command_its_complicated called!\n"); abort(); }
/* Generated stub for command_param_failed */
struct command_result *command_param_failed(void)
{ fprintf(stderr, "command_param_failed called!\n"); abort(); }
/* Generated stub for command_still_pending */ /* Generated stub for command_still_pending */
struct command_result *command_still_pending(struct command *cmd UNNEEDED) struct command_result *command_still_pending(struct command *cmd UNNEEDED)
{ fprintf(stderr, "command_still_pending called!\n"); abort(); } { fprintf(stderr, "command_still_pending called!\n"); abort(); }

99
wallet/walletrpc.c

@ -85,10 +85,10 @@ static void wallet_withdrawal_broadcast(struct bitcoind *bitcoind UNUSED,
* request, select coins and a change key. Then send the request to * request, select coins and a change key. Then send the request to
* the HSM to generate the signatures. * the HSM to generate the signatures.
*/ */
static void json_withdraw(struct command *cmd, static struct command_result *json_withdraw(struct command *cmd,
const char *buffer, const char *buffer,
const jsmntok_t *obj UNNEEDED, const jsmntok_t *obj UNNEEDED,
const jsmntok_t *params) const jsmntok_t *params)
{ {
const jsmntok_t *desttok, *sattok; const jsmntok_t *desttok, *sattok;
struct withdrawal *withdraw = tal(cmd, struct withdrawal); struct withdrawal *withdraw = tal(cmd, struct withdrawal);
@ -105,17 +105,17 @@ static void json_withdraw(struct command *cmd,
p_req("satoshi", param_tok, &sattok), p_req("satoshi", param_tok, &sattok),
p_opt("feerate", param_feerate, &feerate_per_kw), p_opt("feerate", param_feerate, &feerate_per_kw),
NULL)) NULL))
return; return command_param_failed();
res = param_wtx(&withdraw->wtx, buffer, sattok, -1ULL); res = param_wtx(&withdraw->wtx, buffer, sattok, -1ULL);
if (res) if (res)
return; return res;
if (!feerate_per_kw) { if (!feerate_per_kw) {
res = param_feerate_estimate(cmd, &feerate_per_kw, res = param_feerate_estimate(cmd, &feerate_per_kw,
FEERATE_NORMAL); FEERATE_NORMAL);
if (res) if (res)
return; return res;
} }
/* Parse address. */ /* Parse address. */
@ -126,22 +126,21 @@ static void json_withdraw(struct command *cmd,
/* Check that destination address could be understood. */ /* Check that destination address could be understood. */
if (addr_parse == ADDRESS_PARSE_UNRECOGNIZED) { if (addr_parse == ADDRESS_PARSE_UNRECOGNIZED) {
command_fail(cmd, LIGHTNINGD, "Could not parse destination address"); return command_fail(cmd, LIGHTNINGD,
return; "Could not parse destination address");
} }
/* Check address given is compatible with the chain we are on. */ /* Check address given is compatible with the chain we are on. */
if (addr_parse == ADDRESS_PARSE_WRONG_NETWORK) { if (addr_parse == ADDRESS_PARSE_WRONG_NETWORK) {
command_fail(cmd, LIGHTNINGD, return command_fail(cmd, LIGHTNINGD,
"Destination address is not on network %s", "Destination address is not on network %s",
get_chainparams(cmd->ld)->network_name); get_chainparams(cmd->ld)->network_name);
return;
} }
res = wtx_select_utxos(&withdraw->wtx, *feerate_per_kw, res = wtx_select_utxos(&withdraw->wtx, *feerate_per_kw,
tal_count(withdraw->destination)); tal_count(withdraw->destination));
if (res) if (res)
return; return res;
u8 *msg = towire_hsm_sign_withdrawal(cmd, u8 *msg = towire_hsm_sign_withdrawal(cmd,
withdraw->wtx.amount, withdraw->wtx.amount,
@ -164,7 +163,7 @@ static void json_withdraw(struct command *cmd,
withdraw->hextx = tal_hex(withdraw, linearize_tx(cmd, tx)); withdraw->hextx = tal_hex(withdraw, linearize_tx(cmd, tx));
bitcoind_sendrawtx(cmd->ld->topology->bitcoind, withdraw->hextx, bitcoind_sendrawtx(cmd->ld->topology->bitcoind, withdraw->hextx,
wallet_withdrawal_broadcast, withdraw); wallet_withdrawal_broadcast, withdraw);
command_still_pending(cmd); return command_still_pending(cmd);
} }
static const struct json_command withdraw_command = { static const struct json_command withdraw_command = {
@ -248,10 +247,10 @@ static struct command_result *param_newaddr(struct command *cmd,
name, tok->end - tok->start, buffer + tok->start); name, tok->end - tok->start, buffer + tok->start);
} }
static void json_newaddr(struct command *cmd, static struct command_result *json_newaddr(struct command *cmd,
const char *buffer, const char *buffer,
const jsmntok_t *obj UNNEEDED, const jsmntok_t *obj UNNEEDED,
const jsmntok_t *params) const jsmntok_t *params)
{ {
struct json_stream *response; struct json_stream *response;
struct ext_key ext; struct ext_key ext;
@ -263,24 +262,21 @@ static void json_newaddr(struct command *cmd,
if (!param(cmd, buffer, params, if (!param(cmd, buffer, params,
p_opt_def("addresstype", param_newaddr, &is_p2wpkh, true), p_opt_def("addresstype", param_newaddr, &is_p2wpkh, true),
NULL)) NULL))
return; return command_param_failed();
keyidx = wallet_get_newindex(cmd->ld); keyidx = wallet_get_newindex(cmd->ld);
if (keyidx < 0) { if (keyidx < 0) {
command_fail(cmd, LIGHTNINGD, "Keys exhausted "); return command_fail(cmd, LIGHTNINGD, "Keys exhausted ");
return;
} }
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, "Keys generation failure"); return command_fail(cmd, LIGHTNINGD, "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"); return command_fail(cmd, LIGHTNINGD, "Key parsing failure");
return;
} }
txfilter_add_derkey(cmd->ld->owned_txfilter, ext.pub_key); txfilter_add_derkey(cmd->ld->owned_txfilter, ext.pub_key);
@ -289,16 +285,15 @@ static void json_newaddr(struct command *cmd,
&pubkey, !*is_p2wpkh, &pubkey, !*is_p2wpkh,
NULL); NULL);
if (!out) { if (!out) {
command_fail(cmd, LIGHTNINGD, return command_fail(cmd, LIGHTNINGD,
"p2wpkh address encoding failure."); "p2wpkh address encoding failure.");
return;
} }
response = json_stream_success(cmd); 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);
command_success(cmd, response); return command_success(cmd, response);
} }
static const struct json_command newaddr_command = { static const struct json_command newaddr_command = {
@ -309,10 +304,10 @@ static const struct json_command newaddr_command = {
}; };
AUTODATA(json_command, &newaddr_command); AUTODATA(json_command, &newaddr_command);
static void json_listaddrs(struct command *cmd, static struct command_result *json_listaddrs(struct command *cmd,
const char *buffer, const char *buffer,
const jsmntok_t *obj UNNEEDED, const jsmntok_t *obj UNNEEDED,
const jsmntok_t *params) const jsmntok_t *params)
{ {
struct json_stream *response; struct json_stream *response;
struct ext_key ext; struct ext_key ext;
@ -324,7 +319,7 @@ static void json_listaddrs(struct command *cmd,
db_get_intvar(cmd->ld->wallet->db, db_get_intvar(cmd->ld->wallet->db,
"bip32_max_index", 0)), "bip32_max_index", 0)),
NULL)) NULL))
return; return command_param_failed();
response = json_stream_success(cmd); response = json_stream_success(cmd);
json_object_start(response, NULL); json_object_start(response, NULL);
@ -377,7 +372,7 @@ static void json_listaddrs(struct command *cmd,
} }
json_array_end(response); json_array_end(response);
json_object_end(response); json_object_end(response);
command_success(cmd, response); return command_success(cmd, response);
} }
static const struct json_command listaddrs_command = { static const struct json_command listaddrs_command = {
@ -389,10 +384,10 @@ static const struct json_command listaddrs_command = {
}; };
AUTODATA(json_command, &listaddrs_command); AUTODATA(json_command, &listaddrs_command);
static void json_listfunds(struct command *cmd, static struct command_result *json_listfunds(struct command *cmd,
const char *buffer, const char *buffer,
const jsmntok_t *obj UNNEEDED, const jsmntok_t *obj UNNEEDED,
const jsmntok_t *params) const jsmntok_t *params)
{ {
struct json_stream *response; struct json_stream *response;
struct peer *p; struct peer *p;
@ -401,7 +396,7 @@ static void json_listfunds(struct command *cmd,
struct pubkey funding_pubkey; struct pubkey funding_pubkey;
if (!param(cmd, buffer, params, NULL)) if (!param(cmd, buffer, params, NULL))
return; return command_param_failed();
utxos = wallet_get_utxos(cmd, cmd->ld->wallet, output_state_available); utxos = wallet_get_utxos(cmd, cmd->ld->wallet, output_state_available);
response = json_stream_success(cmd); response = json_stream_success(cmd);
@ -422,9 +417,8 @@ static void json_listfunds(struct command *cmd,
utxos[i]->is_p2sh, utxos[i]->is_p2sh,
NULL); NULL);
if (!out) { if (!out) {
command_fail(cmd, LIGHTNINGD, return command_fail(cmd, LIGHTNINGD,
"p2wpkh address encoding failure."); "p2wpkh address encoding failure.");
return;
} }
json_add_string(response, "address", out); json_add_string(response, "address", out);
} }
@ -464,7 +458,7 @@ static void json_listfunds(struct command *cmd,
json_array_end(response); json_array_end(response);
json_object_end(response); json_object_end(response);
command_success(cmd, response); return command_success(cmd, response);
} }
static const struct json_command listfunds_command = { static const struct json_command listfunds_command = {
@ -517,15 +511,15 @@ static void process_utxo_result(struct bitcoind *bitcoind,
} }
} }
static void json_dev_rescan_outputs(struct command *cmd, static struct command_result *json_dev_rescan_outputs(struct command *cmd,
const char *buffer, const char *buffer,
const jsmntok_t *obj UNNEEDED, const jsmntok_t *obj UNNEEDED,
const jsmntok_t *params) const jsmntok_t *params)
{ {
struct txo_rescan *rescan = tal(cmd, struct txo_rescan); struct txo_rescan *rescan = tal(cmd, struct txo_rescan);
if (!param(cmd, buffer, params, NULL)) if (!param(cmd, buffer, params, NULL))
return; return command_param_failed();
rescan->response = json_stream_success(cmd); rescan->response = json_stream_success(cmd);
rescan->cmd = cmd; rescan->cmd = cmd;
@ -537,13 +531,12 @@ static void json_dev_rescan_outputs(struct command *cmd,
if (tal_count(rescan->utxos) == 0) { if (tal_count(rescan->utxos) == 0) {
json_array_end(rescan->response); json_array_end(rescan->response);
json_object_end(rescan->response); json_object_end(rescan->response);
command_success(cmd, rescan->response); return command_success(cmd, rescan->response);
return;
} }
bitcoind_gettxout(cmd->ld->topology->bitcoind, &rescan->utxos[0]->txid, bitcoind_gettxout(cmd->ld->topology->bitcoind, &rescan->utxos[0]->txid,
rescan->utxos[0]->outnum, process_utxo_result, rescan->utxos[0]->outnum, process_utxo_result,
rescan); rescan);
command_still_pending(cmd); return command_still_pending(cmd);
} }
static const struct json_command dev_rescan_output_command = { static const struct json_command dev_rescan_output_command = {

Loading…
Cancel
Save