Added error code parameter to command_fail

Until now, `command_fail()` reported an error code of -1 for all uses.
This PR adds an `int code` parameter to `command_fail()`, requiring the
caller to explicitly include the error code.

This is part of #1464.

The majority of the calls are used during parameter validation and
their error code is now JSONRPC2_INVALID_PARAMS.

The rest of the calls report an error code of LIGHTNINGD, which I defined to
-1 in `jsonrpc_errors.h`.  The intention here is that as we improve our error
reporting, all occurenaces of LIGHTNINGD will go away and we can eventually
remove it.

I also converted calls to `command_fail_detailed()` that took a `NULL` `data`
parameter to use the new `command_fail()`.

The only difference from an end user perspecive is that bad input errors that
used to be -1 will now be -32602 (JSONRPC2_INVALID_PARAMS).
This commit is contained in:
Mark Beckwith 2018-05-24 16:40:18 -05:00 committed by Christian Decker
parent c20e859f05
commit 7f437715d5
19 changed files with 303 additions and 198 deletions

View File

@ -22,7 +22,8 @@ bool wtx_select_utxos(struct wallet_tx * tx, u32 fee_rate_per_kw,
&tx->amount,
&fee_estimate);
if (!tx->utxos || tx->amount < 546) {
command_fail(tx->cmd, "Cannot afford fee %"PRIu64,
command_fail(tx->cmd, LIGHTNINGD,
"Cannot afford fee %"PRIu64,
fee_estimate);
return false;
}
@ -33,8 +34,8 @@ bool wtx_select_utxos(struct wallet_tx * tx, u32 fee_rate_per_kw,
fee_rate_per_kw, out_len,
&fee_estimate, &tx->change);
if (!tx->utxos || tx->amount < 546) {
command_fail(tx->cmd,
"Cannot afford funding transaction");
command_fail(tx->cmd, LIGHTNINGD,
"Cannot afford funding transaction");
return false;
}
if (tx->change < 546) {

View File

@ -4,6 +4,7 @@
#include "bitcoind.h"
#include "chaintopology.h"
#include "jsonrpc.h"
#include "jsonrpc_errors.h"
#include "lightningd.h"
#include "log.h"
#include "watch.h"
@ -656,7 +657,8 @@ static void json_dev_setfees(struct command *cmd,
continue;
if (!json_tok_number(buffer, ratetok[i],
&topo->dev_override_fee_rate[i])) {
command_fail(cmd, "Invalid feerate %.*s",
command_fail(cmd, JSONRPC2_INVALID_PARAMS,
"Invalid feerate %.*s",
ratetok[i]->end - ratetok[i]->start,
buffer + ratetok[i]->start);
return;

View File

@ -6,6 +6,7 @@
#include <lightningd/connect_control.h>
#include <lightningd/json.h>
#include <lightningd/jsonrpc.h>
#include <lightningd/jsonrpc_errors.h>
#include <lightningd/lightningd.h>
#include <lightningd/log.h>
#include <lightningd/subd.h>
@ -70,7 +71,7 @@ void gossip_connect_result(struct lightningd *ld, const u8 *msg)
json_object_end(response);
command_success(c->cmd, response);
} else {
command_fail(c->cmd, "%s", err);
command_fail(c->cmd, LIGHTNINGD, "%s", err);
}
/* They delete themselves from list */
}
@ -109,14 +110,15 @@ static void json_connect(struct command *cmd,
}
if (!json_tok_pubkey(buffer, idtok, &id)) {
command_fail(cmd, "id %.*s not valid",
command_fail(cmd, JSONRPC2_INVALID_PARAMS,
"id %.*s not valid",
idtok->end - idtok->start,
buffer + idtok->start);
return;
}
if (hosttok && ataddr) {
command_fail(cmd,
command_fail(cmd, JSONRPC2_INVALID_PARAMS,
"Can't specify host as both xxx@yyy "
"and separate argument");
return;
@ -133,7 +135,8 @@ static void json_connect(struct command *cmd,
/* Port without host name? */
if (porttok && !name) {
command_fail(cmd, "Can't specify port without host");
command_fail(cmd, JSONRPC2_INVALID_PARAMS,
"Can't specify port without host");
return;
}
@ -143,7 +146,8 @@ static void json_connect(struct command *cmd,
/* Is there a port? */
if (porttok) {
if (!json_tok_number(buffer, porttok, &port) || !port) {
command_fail(cmd, "Port %.*s not valid",
command_fail(cmd, JSONRPC2_INVALID_PARAMS,
"Port %.*s not valid",
porttok->end - porttok->start,
buffer + porttok->start);
return;
@ -156,7 +160,7 @@ static void json_connect(struct command *cmd,
&& !cmd->ld->pure_tor_setup,
true,
&err_msg)) {
command_fail(cmd, "Host %s:%u not valid: %s",
command_fail(cmd, LIGHTNINGD, "Host %s:%u not valid: %s",
name, port, err_msg ? err_msg : "port is 0");
return;
}

View File

@ -5,6 +5,7 @@
#include <lightningd/htlc_end.h>
#include <lightningd/json.h>
#include <lightningd/jsonrpc.h>
#include <lightningd/jsonrpc_errors.h>
#include <lightningd/lightningd.h>
#include <lightningd/log.h>
#include <lightningd/peer_control.h>
@ -23,9 +24,9 @@ static void ping_reply(struct subd *subd, const u8 *msg, const int *fds UNUSED,
ok = fromwire_gossip_ping_reply(msg, &sent, &totlen);
if (!ok)
command_fail(cmd, "Bad reply message");
command_fail(cmd, LIGHTNINGD, "Bad reply message");
else if (!sent)
command_fail(cmd, "Unknown peer");
command_fail(cmd, LIGHTNINGD, "Unknown peer");
else {
struct json_result *response = new_json_result(cmd);
@ -57,7 +58,8 @@ static void json_dev_ping(struct command *cmd,
/* FIXME: These checks are horrible, use a peer flag to say it's
* ready to forward! */
if (!json_tok_number(buffer, lentok, &len)) {
command_fail(cmd, "'%.*s' is not a valid number",
command_fail(cmd, JSONRPC2_INVALID_PARAMS,
"'%.*s' is not a valid number",
lentok->end - lentok->start,
buffer + lentok->start);
return;
@ -79,12 +81,14 @@ static void json_dev_ping(struct command *cmd,
* * [`byteslen`:`ignored`]
*/
if (len > 65535 - 2 - 2 - 2) {
command_fail(cmd, "%u would result in oversize ping", len);
command_fail(cmd, JSONRPC2_INVALID_PARAMS,
"%u would result in oversize ping", len);
return;
}
if (!json_tok_number(buffer, pongbytestok, &pongbytes)) {
command_fail(cmd, "'%.*s' is not a valid number",
command_fail(cmd, JSONRPC2_INVALID_PARAMS,
"'%.*s' is not a valid number",
pongbytestok->end - pongbytestok->start,
buffer + pongbytestok->start);
return;
@ -92,12 +96,14 @@ static void json_dev_ping(struct command *cmd,
/* Note that > 65531 is valid: it means "no pong reply" */
if (pongbytes > 65535) {
command_fail(cmd, "pongbytes %u > 65535", pongbytes);
command_fail(cmd, JSONRPC2_INVALID_PARAMS,
"pongbytes %u > 65535", pongbytes);
return;
}
if (!json_tok_pubkey(buffer, idtok, &id)) {
command_fail(cmd, "'%.*s' is not a valid pubkey",
command_fail(cmd, JSONRPC2_INVALID_PARAMS,
"'%.*s' is not a valid pubkey",
idtok->end - idtok->start,
buffer + idtok->start);
return;
@ -111,7 +117,7 @@ static void json_dev_ping(struct command *cmd,
if (!channel
|| !channel->owner
|| !streq(channel->owner->name, "lightning_channeld")) {
command_fail(cmd, "Peer in %s",
command_fail(cmd, LIGHTNINGD, "Peer in %s",
channel && channel->owner
? channel->owner->name
: "unattached");

View File

@ -24,6 +24,7 @@
#include <lightningd/hsm_control.h>
#include <lightningd/json.h>
#include <lightningd/jsonrpc.h>
#include <lightningd/jsonrpc_errors.h>
#include <lightningd/log.h>
#include <sodium/randombytes.h>
#include <string.h>
@ -275,7 +276,7 @@ static void json_getnodes_reply(struct subd *gossip UNUSED, const u8 *reply,
size_t i, j;
if (!fromwire_gossip_getnodes_reply(reply, reply, &nodes)) {
command_fail(cmd, "Malformed gossip_getnodes response");
command_fail(cmd, LIGHTNINGD, "Malformed gossip_getnodes response");
return;
}
@ -325,7 +326,7 @@ static void json_listnodes(struct command *cmd, const char *buffer,
if (idtok) {
id = tal_arr(cmd, struct pubkey, 1);
if (!json_tok_pubkey(buffer, idtok, id)) {
command_fail(cmd, "Invalid id");
command_fail(cmd, JSONRPC2_INVALID_PARAMS, "Invalid id");
return;
}
}
@ -351,7 +352,7 @@ static void json_getroute_reply(struct subd *gossip UNUSED, const u8 *reply, con
fromwire_gossip_getroute_reply(reply, reply, &hops);
if (tal_count(hops) == 0) {
command_fail(cmd, "Could not find a route");
command_fail(cmd, LIGHTNINGD, "Could not find a route");
return;
}
@ -393,43 +394,46 @@ static void json_getroute(struct command *cmd, const char *buffer, const jsmntok
}
if (!json_tok_pubkey(buffer, idtok, &destination)) {
command_fail(cmd, "Invalid id");
command_fail(cmd, JSONRPC2_INVALID_PARAMS, "Invalid id");
return;
}
if (cltvtok && !json_tok_number(buffer, cltvtok, &cltv)) {
command_fail(cmd, "Invalid cltv");
command_fail(cmd, JSONRPC2_INVALID_PARAMS, "Invalid cltv");
return;
}
if (!json_tok_u64(buffer, msatoshitok, &msatoshi)) {
command_fail(cmd, "'%.*s' is not a valid number",
command_fail(cmd, JSONRPC2_INVALID_PARAMS,
"'%.*s' is not a valid number",
msatoshitok->end - msatoshitok->start,
buffer + msatoshitok->start);
return;
}
if (!json_tok_double(buffer, riskfactortok, &riskfactor)) {
command_fail(cmd, "'%.*s' is not a valid double",
command_fail(cmd, JSONRPC2_INVALID_PARAMS,
"'%.*s' is not a valid double",
riskfactortok->end - riskfactortok->start,
buffer + riskfactortok->start);
return;
}
if (fromidtok && !json_tok_pubkey(buffer, fromidtok, &source)) {
command_fail(cmd, "Invalid from id");
command_fail(cmd, JSONRPC2_INVALID_PARAMS, "Invalid from id");
return;
}
if (fuzztok &&
!json_tok_double(buffer, fuzztok, &fuzz)) {
command_fail(cmd, "'%.*s' is not a valid double",
command_fail(cmd, JSONRPC2_INVALID_PARAMS,
"'%.*s' is not a valid double",
fuzztok->end - fuzztok->start,
buffer + fuzztok->start);
return;
}
if (!(0.0 <= fuzz && fuzz <= 100.0)) {
command_fail(cmd,
command_fail(cmd, JSONRPC2_INVALID_PARAMS,
"fuzz must be in range 0.0 <= %f <= 100.0",
fuzz);
return;
@ -439,7 +443,7 @@ static void json_getroute(struct command *cmd, const char *buffer, const jsmntok
if (seedtok) {
if (seedtok->end - seedtok->start > sizeof(seed))
command_fail(cmd,
command_fail(cmd, JSONRPC2_INVALID_PARAMS,
"seed must be < %zu bytes", sizeof(seed));
memset(&seed, 0, sizeof(seed));
@ -472,7 +476,7 @@ static void json_listchannels_reply(struct subd *gossip UNUSED, const u8 *reply,
struct json_result *response = new_json_result(cmd);
if (!fromwire_gossip_getchannels_reply(reply, reply, &entries)) {
command_fail(cmd, "Invalid reply from gossipd");
command_fail(cmd, LIGHTNINGD, "Invalid reply from gossipd");
return;
}
@ -521,7 +525,8 @@ static void json_listchannels(struct command *cmd, const char *buffer,
if (idtok) {
id = tal_arr(cmd, struct short_channel_id, 1);
if (!json_tok_short_channel_id(buffer, idtok, id)) {
command_fail(cmd, "Invalid short_channel_id");
command_fail(cmd, JSONRPC2_INVALID_PARAMS,
"Invalid short_channel_id");
return;
}
}

View File

@ -1,6 +1,7 @@
#include "invoice.h"
#include "json.h"
#include "jsonrpc.h"
#include "jsonrpc_errors.h"
#include "lightningd.h"
#include <bitcoin/address.h>
#include <bitcoin/base58.h>
@ -70,13 +71,15 @@ static void tell_waiter(struct command *cmd, const struct invoice *inv)
json_add_invoice(response, &details, true);
if (details.state == PAID)
command_success(cmd, response);
else
else {
/* FIXME: -2 should be a constant in jsonrpc_errors.h. */
command_fail_detailed(cmd, -2, response,
"invoice expired during wait");
}
}
static void tell_waiter_deleted(struct command *cmd)
{
command_fail(cmd, "Invoice deleted during wait");
command_fail(cmd, LIGHTNINGD, "Invoice deleted during wait");
}
static void wait_on_invoice(const struct invoice *invoice, void *cmd)
{
@ -141,10 +144,11 @@ static bool parse_fallback(struct command *cmd,
buffer, fallback,
fallback_script);
if (fallback_parse == ADDRESS_PARSE_UNRECOGNIZED) {
command_fail(cmd, "Fallback address not valid");
command_fail(cmd, LIGHTNINGD, "Fallback address not valid");
return false;
} else if (fallback_parse == ADDRESS_PARSE_WRONG_NETWORK) {
command_fail(cmd, "Fallback address does not match our network %s",
command_fail(cmd, LIGHTNINGD,
"Fallback address does not match our network %s",
get_chainparams(cmd->ld)->network_name);
return false;
}
@ -189,7 +193,7 @@ static void json_invoice(struct command *cmd,
msatoshi_val = tal(cmd, u64);
if (!json_tok_u64(buffer, msatoshi, msatoshi_val)
|| *msatoshi_val == 0) {
command_fail(cmd,
command_fail(cmd, JSONRPC2_INVALID_PARAMS,
"'%.*s' is not a valid positive number",
msatoshi->end - msatoshi->start,
buffer + msatoshi->start);
@ -199,39 +203,42 @@ static void json_invoice(struct command *cmd,
/* label */
label_val = json_tok_label(cmd, buffer, label);
if (!label_val) {
command_fail(cmd, "label '%.*s' not a string or number",
command_fail(cmd, JSONRPC2_INVALID_PARAMS,
"label '%.*s' not a string or number",
label->end - label->start, buffer + label->start);
return;
}
if (wallet_invoice_find_by_label(wallet, &invoice, label_val)) {
command_fail_detailed(cmd, INVOICE_LABEL_ALREADY_EXISTS,
NULL,
"Duplicate label '%s'", label_val->s);
command_fail(cmd, INVOICE_LABEL_ALREADY_EXISTS,
"Duplicate label '%s'", label_val->s);
return;
}
if (strlen(label_val->s) > INVOICE_MAX_LABEL_LEN) {
command_fail(cmd, "Label '%s' over %u bytes", label_val->s,
command_fail(cmd, JSONRPC2_INVALID_PARAMS,
"Label '%s' over %u bytes", label_val->s,
INVOICE_MAX_LABEL_LEN);
return;
}
desc = json_tok_escaped_string(cmd, buffer, desctok);
if (!desc) {
command_fail(cmd, "description '%.*s' not a string",
command_fail(cmd, JSONRPC2_INVALID_PARAMS,
"description '%.*s' not a string",
desctok->end - desctok->start,
buffer + desctok->start);
return;
}
desc_val = json_escaped_unescape(cmd, desc);
if (!desc_val) {
command_fail(cmd, "description '%s' is invalid"
command_fail(cmd, JSONRPC2_INVALID_PARAMS,
"description '%s' is invalid"
" (note: we don't allow \\u)",
desc->s);
return;
}
/* description */
if (strlen(desc_val) >= BOLT11_FIELD_BYTE_LIMIT) {
command_fail(cmd,
command_fail(cmd, JSONRPC2_INVALID_PARAMS,
"Descriptions greater than %d bytes "
"not yet supported "
"(description length %zu)",
@ -241,7 +248,8 @@ static void json_invoice(struct command *cmd,
}
/* expiry */
if (exp && !json_tok_u64(buffer, exp, &expiry)) {
command_fail(cmd, "Expiry '%.*s' invalid seconds",
command_fail(cmd, JSONRPC2_INVALID_PARAMS,
"Expiry '%.*s' invalid seconds",
exp->end - exp->start,
buffer + exp->start);
return;
@ -255,7 +263,8 @@ static void json_invoice(struct command *cmd,
&fallback_scripts[0]))
return;
} else {
command_fail(cmd, "fallback is deprecated: use fallbacks");
command_fail(cmd, JSONRPC2_INVALID_PARAMS,
"fallback is deprecated: use fallbacks");
return;
}
}
@ -265,12 +274,14 @@ static void json_invoice(struct command *cmd,
size_t n = 0;
if (fallback) {
command_fail(cmd, "Cannot use fallback and fallbacks");
command_fail(cmd, JSONRPC2_INVALID_PARAMS,
"Cannot use fallback and fallbacks");
return;
}
if (fallbacks->type != JSMN_ARRAY) {
command_fail(cmd, "fallback must be an array");
command_fail(cmd, JSONRPC2_INVALID_PARAMS,
"fallback must be an array");
return;
}
fallback_scripts = tal_arr(cmd, const u8 *, n);
@ -291,7 +302,8 @@ static void json_invoice(struct command *cmd,
if (!hex_decode(buffer + preimagetok->start,
preimagetok->end - preimagetok->start,
r.r, sizeof(r.r))) {
command_fail(cmd, "preimage must be 64 hex digits");
command_fail(cmd, JSONRPC2_INVALID_PARAMS,
"preimage must be 64 hex digits");
return;
}
} else
@ -306,8 +318,8 @@ static void json_invoice(struct command *cmd,
*/
if (preimagetok &&
wallet_invoice_find_by_rhash(cmd->ld->wallet, &invoice, &rhash)) {
command_fail_detailed(cmd, INVOICE_PREIMAGE_ALREADY_EXISTS,
NULL, "preimage already used");
command_fail(cmd, INVOICE_PREIMAGE_ALREADY_EXISTS,
"preimage already used");
return;
}
@ -337,7 +349,8 @@ static void json_invoice(struct command *cmd,
&rhash);
if (!result) {
command_fail(cmd, "Failed to create invoice on database");
command_fail(cmd, LIGHTNINGD,
"Failed to create invoice on database");
return;
}
@ -399,7 +412,8 @@ static void json_listinvoice_internal(struct command *cmd,
if (labeltok) {
label = json_tok_label(cmd, buffer, labeltok);
if (!label) {
command_fail(cmd, "label '%.*s' is not a string or number",
command_fail(cmd, JSONRPC2_INVALID_PARAMS,
"label '%.*s' is not a string or number",
labeltok->end - labeltok->start,
buffer + labeltok->start);
return;
@ -467,13 +481,14 @@ static void json_delinvoice(struct command *cmd,
label = json_tok_label(cmd, buffer, labeltok);
if (!label) {
command_fail(cmd, "label '%.*s' is not a string or number",
command_fail(cmd, JSONRPC2_INVALID_PARAMS,
"label '%.*s' is not a string or number",
labeltok->end - labeltok->start,
buffer + labeltok->start);
return;
}
if (!wallet_invoice_find_by_label(wallet, &i, label)) {
command_fail(cmd, "Unknown invoice");
command_fail(cmd, LIGHTNINGD, "Unknown invoice");
return;
}
wallet_invoice_details(cmd, cmd->ld->wallet, i, &details);
@ -484,7 +499,7 @@ static void json_delinvoice(struct command *cmd,
* might not make sense if it changed! */
actual_status = invoice_status_str(&details);
if (!streq(actual_status, status)) {
command_fail(cmd, "Invoice status is %s not %s",
command_fail(cmd, LIGHTNINGD, "Invoice status is %s not %s",
actual_status, status);
return;
}
@ -497,7 +512,7 @@ static void json_delinvoice(struct command *cmd,
log_broken(cmd->ld->log,
"Error attempting to remove invoice %"PRIu64,
i.id);
command_fail(cmd, "Database error");
command_fail(cmd, LIGHTNINGD, "Database error");
return;
}
@ -526,7 +541,8 @@ static void json_delexpiredinvoice(struct command *cmd, const char *buffer,
if (maxexpirytimetok) {
if (!json_tok_u64(buffer, maxexpirytimetok, &maxexpirytime)) {
command_fail(cmd, "'%.*s' is not a valid number",
command_fail(cmd, JSONRPC2_INVALID_PARAMS,
"'%.*s' is not a valid number",
maxexpirytimetok->end - maxexpirytimetok->start,
buffer + maxexpirytimetok->start);
return;
@ -566,7 +582,8 @@ static void json_autocleaninvoice(struct command *cmd,
if (cycletok) {
if (!json_tok_u64(buffer, cycletok, &cycle)) {
command_fail(cmd, "'%.*s' is not a valid number",
command_fail(cmd, JSONRPC2_INVALID_PARAMS,
"'%.*s' is not a valid number",
cycletok->end - cycletok->start,
buffer + cycletok->start);
return;
@ -574,7 +591,8 @@ static void json_autocleaninvoice(struct command *cmd,
}
if (exbytok) {
if (!json_tok_u64(buffer, exbytok, &exby)) {
command_fail(cmd, "'%.*s' is not a valid number",
command_fail(cmd, JSONRPC2_INVALID_PARAMS,
"'%.*s' is not a valid number",
exbytok->end - exbytok->start,
buffer + exbytok->start);
return;
@ -614,7 +632,8 @@ static void json_waitanyinvoice(struct command *cmd,
pay_index = 0;
} else {
if (!json_tok_u64(buffer, pay_indextok, &pay_index)) {
command_fail(cmd, "'%.*s' is not a valid number",
command_fail(cmd, JSONRPC2_INVALID_PARAMS,
"'%.*s' is not a valid number",
pay_indextok->end - pay_indextok->start,
buffer + pay_indextok->start);
return;
@ -660,14 +679,15 @@ static void json_waitinvoice(struct command *cmd,
/* Search for invoice */
label = json_tok_label(cmd, buffer, labeltok);
if (!label) {
command_fail(cmd, "label '%.*s' is not a string or number",
command_fail(cmd, JSONRPC2_INVALID_PARAMS,
"label '%.*s' is not a string or number",
labeltok->end - labeltok->start,
buffer + labeltok->start);
return;
}
if (!wallet_invoice_find_by_label(wallet, &i, label)) {
command_fail(cmd, "Label not found");
command_fail(cmd, LIGHTNINGD, "Label not found");
return;
}
wallet_invoice_details(cmd, cmd->ld->wallet, i, &details);
@ -753,7 +773,7 @@ static void json_decodepay(struct command *cmd,
b11 = bolt11_decode(cmd, str, desc, &fail);
if (!b11) {
command_fail(cmd, "Invalid bolt11: %s", fail);
command_fail(cmd, LIGHTNINGD, "Invalid bolt11: %s", fail);
return;
}

View File

@ -107,7 +107,8 @@ static void json_rhash(struct command *cmd,
if (!hex_decode(buffer + secrettok->start,
secrettok->end - secrettok->start,
&secret, sizeof(secret))) {
command_fail(cmd, "'%.*s' is not a valid 32-byte hex value",
command_fail(cmd, JSONRPC2_INVALID_PARAMS,
"'%.*s' is not a valid 32-byte hex value",
secrettok->end - secrettok->start,
buffer + secrettok->start);
return;
@ -225,7 +226,8 @@ static void json_help(struct command *cmd,
goto done;
}
}
command_fail(cmd, "Unknown command '%.*s'",
command_fail(cmd, JSONRPC2_METHOD_NOT_FOUND,
"Unknown command '%.*s'",
cmdtok->end - cmdtok->start,
buffer + cmdtok->start);
return;
@ -380,13 +382,15 @@ static void command_fail_v(struct command *cmd,
assert(cmd_in_jcon(jcon, cmd));
connection_complete_error(jcon, cmd, cmd->id, error, code, data);
}
void command_fail(struct command *cmd, const char *fmt, ...)
void command_fail(struct command *cmd, int code, const char *fmt, ...)
{
va_list ap;
va_start(ap, fmt);
command_fail_v(cmd, -1, NULL, fmt, ap);
command_fail_v(cmd, code, NULL, fmt, ap);
va_end(ap);
}
void command_fail_detailed(struct command *cmd,
int code, const struct json_result *data,
const char *fmt, ...)
@ -451,34 +455,30 @@ static void parse_request(struct json_connection *jcon, const jsmntok_t tok[])
tal_add_destructor(c, destroy_cmd);
if (!method || !params) {
command_fail_detailed(c,
JSONRPC2_INVALID_REQUEST, NULL,
method ? "No params" : "No method");
command_fail(c, JSONRPC2_INVALID_REQUEST,
method ? "No params" : "No method");
return;
}
if (method->type != JSMN_STRING) {
command_fail_detailed(c,
JSONRPC2_INVALID_REQUEST, NULL,
"Expected string for method");
command_fail(c, JSONRPC2_INVALID_REQUEST,
"Expected string for method");
return;
}
cmd = find_cmd(jcon->buffer, method);
if (!cmd) {
command_fail_detailed(c,
JSONRPC2_METHOD_NOT_FOUND, NULL,
"Unknown command '%.*s'",
method->end - method->start,
jcon->buffer + method->start);
command_fail(c, JSONRPC2_METHOD_NOT_FOUND,
"Unknown command '%.*s'",
method->end - method->start,
jcon->buffer + method->start);
return;
}
if (cmd->deprecated && !deprecated_apis) {
command_fail_detailed(c,
JSONRPC2_METHOD_NOT_FOUND, NULL,
"Command '%.*s' is deprecated",
method->end - method->start,
jcon->buffer + method->start);
command_fail(c, JSONRPC2_METHOD_NOT_FOUND,
"Command '%.*s' is deprecated",
method->end - method->start,
jcon->buffer + method->start);
return;
}
@ -507,8 +507,8 @@ bool json_get_params(struct command *cmd,
p = param + 1;
end = json_next(param);
} else if (param->type != JSMN_OBJECT) {
command_fail_detailed(cmd, JSONRPC2_INVALID_PARAMS, NULL,
"Expected array or object for params");
command_fail(cmd, JSONRPC2_INVALID_PARAMS,
"Expected array or object for params");
return false;
}
@ -541,9 +541,9 @@ bool json_get_params(struct command *cmd,
}
if (compulsory && !*tokptr) {
va_end(ap);
command_fail_detailed(cmd, JSONRPC2_INVALID_PARAMS, NULL,
"Missing '%s' parameter",
names[num_names]);
command_fail(cmd, JSONRPC2_INVALID_PARAMS,
"Missing '%s' parameter",
names[num_names]);
return false;
}
num_names++;
@ -556,10 +556,10 @@ bool json_get_params(struct command *cmd,
if (param->type == JSMN_ARRAY) {
if (param->size > num_names) {
tal_free(names);
command_fail_detailed(cmd, JSONRPC2_INVALID_PARAMS, NULL,
"Too many parameters:"
" got %u, expected %zu",
param->size, num_names);
command_fail(cmd, JSONRPC2_INVALID_PARAMS,
"Too many parameters:"
" got %u, expected %zu",
param->size, num_names);
return false;
}
} else {
@ -576,12 +576,10 @@ bool json_get_params(struct command *cmd,
}
if (!found) {
tal_free(names);
command_fail_detailed(cmd,
JSONRPC2_INVALID_PARAMS,
NULL,
"Unknown parameter '%.*s'",
t->end - t->start,
buffer + t->start);
command_fail(cmd, JSONRPC2_INVALID_PARAMS,
"Unknown parameter '%.*s'",
t->end - t->start,
buffer + t->start);
return false;
}
}
@ -865,13 +863,15 @@ json_tok_address_scriptpubkey(const tal_t *cxt,
}
bool json_tok_wtx(struct wallet_tx * tx, const char * buffer,
const jsmntok_t *sattok)
const jsmntok_t *sattok)
{
if (json_tok_streq(buffer, sattok, "all")) {
tx->all_funds = true;
} else if (!json_tok_u64(buffer, sattok, &tx->amount)) {
command_fail(tx->cmd, "Invalid satoshis");
return false;
}
return true;
if (json_tok_streq(buffer, sattok, "all")) {
tx->all_funds = true;
} else if (!json_tok_u64(buffer, sattok, &tx->amount)) {
command_fail(tx->cmd, JSONRPC2_INVALID_PARAMS,
"Invalid satoshis");
return false;
}
return true;
}

View File

@ -72,7 +72,8 @@ bool json_get_params(struct command *cmd,
struct json_result *null_response(const tal_t *ctx);
void command_success(struct command *cmd, struct json_result *response);
void PRINTF_FMT(2, 3) command_fail(struct command *cmd, const char *fmt, ...);
void PRINTF_FMT(3, 4) command_fail(struct command *cmd, int code,
const char *fmt, ...);
void PRINTF_FMT(4, 5) command_fail_detailed(struct command *cmd,
int code,
const struct json_result *data,

View File

@ -10,6 +10,12 @@
#define JSONRPC2_METHOD_NOT_FOUND -32601
#define JSONRPC2_INVALID_PARAMS -32602
/* Uncategorized error.
* FIXME: This should be replaced in all places
* with a specific error code, and then removed.
*/
#define LIGHTNINGD -1
/* Errors from `pay`, `sendpay`, or `waitsendpay` commands */
#define PAY_IN_PROGRESS 200
#define PAY_RHASH_ALREADY_USED 201

View File

@ -15,6 +15,7 @@
#include <fcntl.h>
#include <inttypes.h>
#include <lightningd/jsonrpc.h>
#include <lightningd/jsonrpc_errors.h>
#include <lightningd/lightningd.h>
#include <lightningd/options.h>
#include <signal.h>
@ -664,7 +665,7 @@ static void json_getlog(struct command *cmd,
if (!level)
minlevel = LOG_INFORM;
else if (!json_tok_loglevel(buffer, level, &minlevel)) {
command_fail(cmd, "Invalid level param");
command_fail(cmd, JSONRPC2_INVALID_PARAMS, "Invalid level param");
return;
}

View File

@ -5,6 +5,7 @@
#include <common/memleak.h>
#include <lightningd/chaintopology.h>
#include <lightningd/jsonrpc.h>
#include <lightningd/jsonrpc_errors.h>
#include <lightningd/lightningd.h>
#include <lightningd/log.h>
#include <stdio.h>
@ -148,7 +149,7 @@ static void json_memleak(struct command *cmd,
struct json_result *response = new_json_result(cmd);
if (!getenv("LIGHTNINGD_DEV_MEMLEAK")) {
command_fail(cmd,
command_fail(cmd, LIGHTNINGD,
"Leak detection needs $LIGHTNINGD_DEV_MEMLEAK");
return;
}

View File

@ -15,6 +15,7 @@
#include <lightningd/hsm_control.h>
#include <lightningd/json.h>
#include <lightningd/jsonrpc.h>
#include <lightningd/jsonrpc_errors.h>
#include <lightningd/lightningd.h>
#include <lightningd/log.h>
#include <lightningd/opening_control.h>
@ -113,7 +114,7 @@ static void uncommitted_channel_to_gossipd(struct lightningd *ld,
log_unusual(uc->log, "Opening channel: %s", errstr);
if (uc->fc)
command_fail(uc->fc->cmd, "%s", errstr);
command_fail(uc->fc->cmd, LIGHTNINGD, "%s", errstr);
/* Hand back to gossipd, (maybe) with an error packet to send. */
msg = towire_gossipctl_hand_back_peer(errstr, &uc->peer->id, cs,
@ -133,7 +134,7 @@ void kill_uncommitted_channel(struct uncommitted_channel *uc,
uc->openingd = NULL;
if (uc->fc)
command_fail(uc->fc->cmd, "%s", why);
command_fail(uc->fc->cmd, LIGHTNINGD, "%s", why);
tal_free(uc);
}
@ -305,7 +306,7 @@ static void opening_funder_finished(struct subd *openingd, const u8 *resp,
log_broken(fc->uc->log,
"bad OPENING_FUNDER_REPLY %s",
tal_hex(resp, resp));
command_fail(fc->cmd, "bad OPENING_FUNDER_REPLY %s",
command_fail(fc->cmd, LIGHTNINGD, "bad OPENING_FUNDER_REPLY %s",
tal_hex(fc->cmd, resp));
goto failed;
}
@ -354,7 +355,7 @@ static void opening_funder_finished(struct subd *openingd, const u8 *resp,
&local_fundingkey),
type_to_string(fc, struct pubkey,
&channel_info.remote_fundingkey));
command_fail(fc->cmd,
command_fail(fc->cmd, JSONRPC2_INVALID_PARAMS,
"Funding txid mismatch:"
" satoshi %"PRIu64" change %"PRIu64
" changeidx %u"
@ -380,7 +381,8 @@ static void opening_funder_finished(struct subd *openingd, const u8 *resp,
&channel_info,
feerate);
if (!channel) {
command_fail(fc->cmd, "Key generation failure");
command_fail(fc->cmd, LIGHTNINGD,
"Key generation failure");
goto failed;
}
@ -542,7 +544,7 @@ static void opening_channel_errmsg(struct uncommitted_channel *uc,
log_info(uc->log, "%s", desc);
subd_send_msg(uc->peer->ld->gossip, msg);
if (uc->fc)
command_fail(uc->fc->cmd, "%s", desc);
command_fail(uc->fc->cmd, LIGHTNINGD, "%s", desc);
} else {
/* An error occurred (presumably negotiation fail). */
const char *errsrc = err_for_them ? "sent" : "received";
@ -761,7 +763,7 @@ static void peer_offer_channel(struct lightningd *ld,
/* We asked to release this peer, but another raced in? Corner case,
* close this is easiest. */
if (!fc->uc) {
command_fail(fc->cmd, "Peer already active");
command_fail(fc->cmd, LIGHTNINGD, "Peer already active");
close(peer_fd);
close(gossip_fd);
return;
@ -840,12 +842,12 @@ static void gossip_peer_released(struct subd *gossip,
tal_hex(gossip, resp));
}
if (uc)
command_fail(fc->cmd, "Peer already OPENING");
command_fail(fc->cmd, LIGHTNINGD, "Peer already OPENING");
else if (c)
command_fail(fc->cmd, "Peer already %s",
command_fail(fc->cmd, LIGHTNINGD, "Peer already %s",
channel_state_name(c));
else
command_fail(fc->cmd, "Peer not connected");
command_fail(fc->cmd, LIGHTNINGD, "Peer not connected");
return;
}
assert(tal_count(fds) == 2);
@ -904,7 +906,7 @@ static void json_fund_channel(struct command *cmd,
if (!pubkey_from_hexstr(buffer + desttok->start,
desttok->end - desttok->start,
&fc->peerid)) {
command_fail(cmd, "Could not parse id");
command_fail(cmd, JSONRPC2_INVALID_PARAMS, "Could not parse id");
return;
}
@ -917,7 +919,8 @@ static void json_fund_channel(struct command *cmd,
return;
if (fc->wtx.amount > MAX_FUNDING_SATOSHI) {
command_fail(cmd, "Funding satoshi must be <= %d",
command_fail(cmd, JSONRPC2_INVALID_PARAMS,
"Funding satoshi must be <= %d",
MAX_FUNDING_SATOSHI);
return;
}

View File

@ -20,6 +20,7 @@
#include <lightningd/bitcoind.h>
#include <lightningd/chaintopology.h>
#include <lightningd/jsonrpc.h>
#include <lightningd/jsonrpc_errors.h>
#include <lightningd/lightningd.h>
#include <lightningd/log.h>
#include <lightningd/options.h>
@ -1031,7 +1032,8 @@ static void json_listconfigs(struct command *cmd,
json_object_end(response);
if (configtok && !found) {
command_fail(cmd, "Unknown config option '%.*s'",
command_fail(cmd, JSONRPC2_INVALID_PARAMS,
"Unknown config option '%.*s'",
configtok->end - configtok->start,
buffer + configtok->start);
return;

View File

@ -932,14 +932,16 @@ static void json_sendpay(struct command *cmd,
if (!hex_decode(buffer + rhashtok->start,
rhashtok->end - rhashtok->start,
&rhash, sizeof(rhash))) {
command_fail(cmd, "'%.*s' is not a valid sha256 hash",
command_fail(cmd, JSONRPC2_INVALID_PARAMS,
"'%.*s' is not a valid sha256 hash",
rhashtok->end - rhashtok->start,
buffer + rhashtok->start);
return;
}
if (routetok->type != JSMN_ARRAY) {
command_fail(cmd, "'%.*s' is not an array",
command_fail(cmd, JSONRPC2_INVALID_PARAMS,
"'%.*s' is not an array",
routetok->end - routetok->start,
buffer + routetok->start);
return;
@ -953,7 +955,8 @@ static void json_sendpay(struct command *cmd,
const jsmntok_t *amttok, *idtok, *delaytok, *chantok;
if (t->type != JSMN_OBJECT) {
command_fail(cmd, "Route %zu '%.*s' is not an object",
command_fail(cmd, JSONRPC2_INVALID_PARAMS,
"Route %zu '%.*s' is not an object",
n_hops,
t->end - t->start,
buffer + t->start);
@ -964,7 +967,8 @@ static void json_sendpay(struct command *cmd,
delaytok = json_get_member(buffer, t, "delay");
chantok = json_get_member(buffer, t, "channel");
if (!amttok || !idtok || !delaytok || !chantok) {
command_fail(cmd, "Route %zu needs msatoshi/id/channel/delay",
command_fail(cmd, JSONRPC2_INVALID_PARAMS,
"Route %zu needs msatoshi/id/channel/delay",
n_hops);
return;
}
@ -973,35 +977,40 @@ static void json_sendpay(struct command *cmd,
/* What that hop will forward */
if (!json_tok_u64(buffer, amttok, &route[n_hops].amount)) {
command_fail(cmd, "Route %zu invalid msatoshi",
command_fail(cmd, JSONRPC2_INVALID_PARAMS,
"Route %zu invalid msatoshi",
n_hops);
return;
}
if (!json_tok_short_channel_id(buffer, chantok,
&route[n_hops].channel_id)) {
command_fail(cmd, "Route %zu invalid channel_id", n_hops);
command_fail(cmd, JSONRPC2_INVALID_PARAMS,
"Route %zu invalid channel_id", n_hops);
return;
}
if (!json_tok_pubkey(buffer, idtok, &route[n_hops].nodeid)) {
command_fail(cmd, "Route %zu invalid id", n_hops);
command_fail(cmd, JSONRPC2_INVALID_PARAMS,
"Route %zu invalid id", n_hops);
return;
}
if (!json_tok_number(buffer, delaytok, &route[n_hops].delay)) {
command_fail(cmd, "Route %zu invalid delay", n_hops);
command_fail(cmd, JSONRPC2_INVALID_PARAMS,
"Route %zu invalid delay", n_hops);
return;
}
n_hops++;
}
if (n_hops == 0) {
command_fail(cmd, "Empty route");
command_fail(cmd, JSONRPC2_INVALID_PARAMS, "Empty route");
return;
}
if (msatoshitok) {
if (!json_tok_u64(buffer, msatoshitok, &msatoshi)) {
command_fail(cmd, "'%.*s' is not a number",
command_fail(cmd, JSONRPC2_INVALID_PARAMS,
"'%.*s' is not a number",
msatoshitok->end - msatoshitok->start,
buffer + msatoshitok->start);
return;
@ -1014,7 +1023,8 @@ static void json_sendpay(struct command *cmd,
* fail. */
if (!(msatoshi <= route[n_hops-1].amount &&
route[n_hops-1].amount <= 2 * msatoshi)) {
command_fail(cmd, "msatoshi %"PRIu64" out of range",
command_fail(cmd, JSONRPC2_INVALID_PARAMS,
"msatoshi %"PRIu64" out of range",
msatoshi);
return;
}
@ -1035,8 +1045,7 @@ AUTODATA(json_command, &sendpay_command);
static void waitsendpay_timeout(struct command *cmd)
{
command_fail_detailed(cmd, PAY_IN_PROGRESS, NULL,
"Timed out while waiting");
command_fail(cmd, PAY_IN_PROGRESS, "Timed out while waiting");
}
static void json_waitsendpay(struct command *cmd, const char *buffer,
@ -1056,14 +1065,16 @@ static void json_waitsendpay(struct command *cmd, const char *buffer,
if (!hex_decode(buffer + rhashtok->start,
rhashtok->end - rhashtok->start,
&rhash, sizeof(rhash))) {
command_fail(cmd, "'%.*s' is not a valid sha256 hash",
command_fail(cmd, JSONRPC2_INVALID_PARAMS,
"'%.*s' is not a valid sha256 hash",
rhashtok->end - rhashtok->start,
buffer + rhashtok->start);
return;
}
if (timeouttok && !json_tok_number(buffer, timeouttok, &timeout)) {
command_fail(cmd, "'%.*s' is not a valid number",
command_fail(cmd, JSONRPC2_INVALID_PARAMS,
"'%.*s' is not a valid number",
timeouttok->end - timeouttok->start,
buffer + timeouttok->start);
return;
@ -1107,7 +1118,8 @@ static void json_listpayments(struct command *cmd, const char *buffer,
char *b11str, *fail;
if (rhashtok) {
command_fail(cmd, "Can only specify one of"
command_fail(cmd, JSONRPC2_INVALID_PARAMS,
"Can only specify one of"
" {bolt11} or {payment_hash}");
return;
}
@ -1117,7 +1129,8 @@ static void json_listpayments(struct command *cmd, const char *buffer,
b11 = bolt11_decode(cmd, b11str, NULL, &fail);
if (!b11) {
command_fail(cmd, "Invalid bolt11: %s", fail);
command_fail(cmd, JSONRPC2_INVALID_PARAMS,
"Invalid bolt11: %s", fail);
return;
}
rhash = &b11->payment_hash;
@ -1126,7 +1139,8 @@ static void json_listpayments(struct command *cmd, const char *buffer,
if (!hex_decode(buffer + rhashtok->start,
rhashtok->end - rhashtok->start,
rhash, sizeof(*rhash))) {
command_fail(cmd, "'%.*s' is not a valid sha256 hash",
command_fail(cmd, JSONRPC2_INVALID_PARAMS,
"'%.*s' is not a valid sha256 hash",
rhashtok->end - rhashtok->start,
buffer + rhashtok->start);
return;

View File

@ -626,7 +626,8 @@ static void json_pay(struct command *cmd,
b11 = bolt11_decode(pay, b11str, desc, &fail);
if (!b11) {
command_fail(cmd, "Invalid bolt11: %s", fail);
command_fail(cmd, JSONRPC2_INVALID_PARAMS,
"Invalid bolt11: %s", fail);
return;
}
@ -638,7 +639,8 @@ static void json_pay(struct command *cmd,
pay->min_final_cltv_expiry = b11->min_final_cltv_expiry;
if (retryfortok && !json_tok_number(buffer, retryfortok, &retryfor)) {
command_fail(cmd, "'%.*s' is not an integer",
command_fail(cmd, JSONRPC2_INVALID_PARAMS,
"'%.*s' is not an integer",
retryfortok->end - retryfortok->start,
buffer + retryfortok->start);
return;
@ -647,16 +649,18 @@ static void json_pay(struct command *cmd,
if (b11->msatoshi) {
msatoshi = *b11->msatoshi;
if (msatoshitok) {
command_fail(cmd, "msatoshi parameter unnecessary");
command_fail(cmd, JSONRPC2_INVALID_PARAMS,
"msatoshi parameter unnecessary");
return;
}
} else {
if (!msatoshitok) {
command_fail(cmd, "msatoshi parameter required");
command_fail(cmd, JSONRPC2_INVALID_PARAMS,
"msatoshi parameter required");
return;
}
if (!json_tok_u64(buffer, msatoshitok, &msatoshi)) {
command_fail(cmd,
command_fail(cmd, JSONRPC2_INVALID_PARAMS,
"msatoshi '%.*s' is not a valid number",
msatoshitok->end-msatoshitok->start,
buffer + msatoshitok->start);
@ -667,7 +671,8 @@ static void json_pay(struct command *cmd,
if (riskfactortok
&& !json_tok_double(buffer, riskfactortok, &riskfactor)) {
command_fail(cmd, "'%.*s' is not a valid double",
command_fail(cmd, JSONRPC2_INVALID_PARAMS,
"'%.*s' is not a valid double",
riskfactortok->end - riskfactortok->start,
buffer + riskfactortok->start);
return;
@ -676,19 +681,22 @@ static void json_pay(struct command *cmd,
if (maxfeetok
&& !json_tok_double(buffer, maxfeetok, &maxfeepercent)) {
command_fail(cmd, "'%.*s' is not a valid double",
command_fail(cmd, JSONRPC2_INVALID_PARAMS,
"'%.*s' is not a valid double",
maxfeetok->end - maxfeetok->start,
buffer + maxfeetok->start);
return;
}
/* Ensure it is in range 0.0 <= maxfeepercent <= 100.0 */
if (!(0.0 <= maxfeepercent)) {
command_fail(cmd, "%f maxfeepercent must be non-negative",
command_fail(cmd, JSONRPC2_INVALID_PARAMS,
"%f maxfeepercent must be non-negative",
maxfeepercent);
return;
}
if (!(maxfeepercent <= 100.0)) {
command_fail(cmd, "%f maxfeepercent must be <= 100.0",
command_fail(cmd, JSONRPC2_INVALID_PARAMS,
"%f maxfeepercent must be <= 100.0",
maxfeepercent);
return;
}
@ -696,13 +704,14 @@ static void json_pay(struct command *cmd,
if (maxdelaytok
&& !json_tok_number(buffer, maxdelaytok, &maxdelay)) {
command_fail(cmd, "'%.*s' is not a valid double",
command_fail(cmd, JSONRPC2_INVALID_PARAMS,
"'%.*s' is not a valid integer",
maxdelaytok->end - maxdelaytok->start,
buffer + maxdelaytok->start);
return;
}
if (maxdelay < pay->min_final_cltv_expiry) {
command_fail(cmd,
command_fail(cmd, JSONRPC2_INVALID_PARAMS,
"maxdelay (%u) must be greater than "
"min_final_cltv_expiry (%"PRIu32") of "
"invoice",

View File

@ -33,6 +33,7 @@
#include <lightningd/hsm_control.h>
#include <lightningd/json.h>
#include <lightningd/jsonrpc.h>
#include <lightningd/jsonrpc_errors.h>
#include <lightningd/log.h>
#include <lightningd/onchain_control.h>
#include <lightningd/opening_control.h>
@ -275,7 +276,8 @@ destroy_close_command_on_channel_destroy(struct channel *_ UNUSED,
* Clear the cc->channel first so that we will not try to
* remove a destructor. */
cc->channel = NULL;
command_fail(cc->cmd, "Channel forgotten before proper close.");
command_fail(cc->cmd, LIGHTNINGD,
"Channel forgotten before proper close.");
}
/* Destroy the close command structure. */
@ -307,7 +309,7 @@ close_command_timeout(struct close_command *cc)
else
/* Fail the command directly, which will resolve the
* command and destroy the close_command. */
command_fail(cc->cmd,
command_fail(cc->cmd, LIGHTNINGD,
"Channel close negotiation not finished "
"before timeout");
}
@ -727,7 +729,8 @@ static void gossipd_getpeers_complete(struct subd *gossip, const u8 *msg,
struct peer *p;
if (!fromwire_gossip_getpeers_reply(msg, msg, &ids, &addrs, &nodes)) {
command_fail(gpa->cmd, "Bad response from gossipd");
command_fail(gpa->cmd, LIGHTNINGD,
"Bad response from gossipd");
return;
}
@ -934,7 +937,8 @@ static void json_listpeers(struct command *cmd,
if (idtok) {
gpa->specific_id = tal_arr(cmd, struct pubkey, 1);
if (!json_tok_pubkey(buffer, idtok, gpa->specific_id)) {
command_fail(cmd, "id %.*s not valid",
command_fail(cmd, LIGHTNINGD,
"id %.*s not valid",
idtok->end - idtok->start,
buffer + idtok->start);
return;
@ -943,7 +947,8 @@ static void json_listpeers(struct command *cmd,
if (leveltok) {
gpa->ll = tal(gpa, enum log_level);
if (!json_tok_loglevel(buffer, leveltok, gpa->ll)) {
command_fail(cmd, "Invalid level param");
command_fail(cmd, LIGHTNINGD,
"Invalid level param");
return;
}
} else
@ -985,7 +990,7 @@ command_find_channel(struct command *cmd,
if (structeq(&channel_cid, &cid))
return channel;
}
command_fail(cmd,
command_fail(cmd, JSONRPC2_INVALID_PARAMS,
"Channel ID not found: '%.*s'",
tok->end - tok->start,
buffer + tok->start);
@ -998,13 +1003,13 @@ command_find_channel(struct command *cmd,
if (channel->scid && channel->scid->u64 == scid.u64)
return channel;
}
command_fail(cmd,
command_fail(cmd, JSONRPC2_INVALID_PARAMS,
"Short channel ID not found: '%.*s'",
tok->end - tok->start,
buffer + tok->start);
return NULL;
} else {
command_fail(cmd,
command_fail(cmd, JSONRPC2_INVALID_PARAMS,
"Given id is not a channel ID or "
"short channel ID: '%.*s'",
tok->end - tok->start,
@ -1033,13 +1038,15 @@ static void json_close(struct command *cmd,
}
if (forcetok && !json_tok_bool(buffer, forcetok, &force)) {
command_fail(cmd, "Force '%.*s' must be true or false",
command_fail(cmd, JSONRPC2_INVALID_PARAMS,
"Force '%.*s' must be true or false",
forcetok->end - forcetok->start,
buffer + forcetok->start);
return;
}
if (timeouttok && !json_tok_number(buffer, timeouttok, &timeout)) {
command_fail(cmd, "Timeout '%.*s' is not a number",
command_fail(cmd, JSONRPC2_INVALID_PARAMS,
"Timeout '%.*s' is not a number",
timeouttok->end - timeouttok->start,
buffer + timeouttok->start);
return;
@ -1063,7 +1070,8 @@ static void json_close(struct command *cmd,
command_success(cmd, null_response(cmd));
return;
}
command_fail(cmd, "Peer has no active channel");
command_fail(cmd, LIGHTNINGD,
"Peer has no active channel");
return;
}
@ -1076,7 +1084,7 @@ static void json_close(struct command *cmd,
channel->state != CHANNELD_AWAITING_LOCKIN &&
channel->state != CHANNELD_SHUTTING_DOWN &&
channel->state != CLOSINGD_SIGEXCHANGE)
command_fail(cmd, "Channel is in state %s",
command_fail(cmd, LIGHTNINGD, "Channel is in state %s",
channel_state_name(channel));
/* If normal or locking in, transition to shutting down
@ -1153,9 +1161,10 @@ static void gossip_peer_disconnected (struct subd *gossip,
fatal("Gossip daemon gave invalid reply %s",
tal_hex(gossip, resp));
if (isconnected)
command_fail(cmd, "Peer is not in gossip mode");
command_fail(cmd, LIGHTNINGD,
"Peer is not in gossip mode");
else
command_fail(cmd, "Peer not connected");
command_fail(cmd, LIGHTNINGD, "Peer not connected");
} else {
/* Successfully disconnected */
command_success(cmd, null_response(cmd));
@ -1177,7 +1186,7 @@ static void json_disconnect(struct command *cmd,
}
if (!json_tok_pubkey(buffer, idtok, &id)) {
command_fail(cmd, "id %.*s not valid",
command_fail(cmd, LIGHTNINGD, "id %.*s not valid",
idtok->end - idtok->start,
buffer + idtok->start);
return;
@ -1213,12 +1222,14 @@ static void json_sign_last_tx(struct command *cmd,
peer = peer_from_json(cmd->ld, buffer, peertok);
if (!peer) {
command_fail(cmd, "Could not find peer with that id");
command_fail(cmd, LIGHTNINGD,
"Could not find peer with that id");
return;
}
channel = peer_active_channel(peer);
if (!channel) {
command_fail(cmd, "Could has not active channel");
command_fail(cmd, LIGHTNINGD,
"Could not find active channel");
return;
}
@ -1256,13 +1267,15 @@ static void json_dev_fail(struct command *cmd,
peer = peer_from_json(cmd->ld, buffer, peertok);
if (!peer) {
command_fail(cmd, "Could not find peer with that id");
command_fail(cmd, LIGHTNINGD,
"Could not find peer with that id");
return;
}
channel = peer_active_channel(peer);
if (!channel) {
command_fail(cmd, "Could not find active channel with peer");
command_fail(cmd, LIGHTNINGD,
"Could not find active channel with peer");
return;
}
@ -1301,22 +1314,26 @@ static void json_dev_reenable_commit(struct command *cmd,
peer = peer_from_json(cmd->ld, buffer, peertok);
if (!peer) {
command_fail(cmd, "Could not find peer with that id");
command_fail(cmd, LIGHTNINGD,
"Could not find peer with that id");
return;
}
channel = peer_active_channel(peer);
if (!channel) {
command_fail(cmd, "Peer has no active channel");
command_fail(cmd, LIGHTNINGD,
"Peer has no active channel");
return;
}
if (!channel->owner) {
command_fail(cmd, "Peer has no owner");
command_fail(cmd, LIGHTNINGD,
"Peer has no owner");
return;
}
if (!streq(channel->owner->name, "lightning_channeld")) {
command_fail(cmd, "Peer owned by %s", channel->owner->name);
command_fail(cmd, LIGHTNINGD,
"Peer owned by %s", channel->owner->name);
return;
}
@ -1347,7 +1364,7 @@ static void process_dev_forget_channel(struct bitcoind *bitcoind UNUSED,
struct json_result *response;
struct dev_forget_channel_cmd *forget = arg;
if (txout != NULL && !forget->force) {
command_fail(forget->cmd,
command_fail(forget->cmd, LIGHTNINGD,
"Cowardly refusing to forget channel with an "
"unspent funding output, if you know what "
"you're doing you can override with "
@ -1387,7 +1404,8 @@ static void json_dev_forget_channel(struct command *cmd, const char *buffer,
}
if (scidtok && !json_tok_short_channel_id(buffer, scidtok, &scid)) {
command_fail(cmd, "Invalid short_channel_id '%.*s'",
command_fail(cmd, JSONRPC2_INVALID_PARAMS,
"Invalid short_channel_id '%.*s'",
scidtok->end - scidtok->start,
buffer + scidtok->start);
return;
@ -1399,7 +1417,8 @@ static void json_dev_forget_channel(struct command *cmd, const char *buffer,
peer = peer_from_json(cmd->ld, buffer, nodeidtok);
if (!peer) {
command_fail(cmd, "Could not find channel with that peer");
command_fail(cmd, LIGHTNINGD,
"Could not find channel with that peer");
return;
}
@ -1412,7 +1431,7 @@ static void json_dev_forget_channel(struct command *cmd, const char *buffer,
continue;
}
if (forget->channel) {
command_fail(cmd,
command_fail(cmd, LIGHTNINGD,
"Multiple channels:"
" please specify short_channel_id");
return;
@ -1420,16 +1439,17 @@ static void json_dev_forget_channel(struct command *cmd, const char *buffer,
forget->channel = channel;
}
if (!forget->channel) {
command_fail(cmd,
command_fail(cmd, LIGHTNINGD,
"No channels matching that short_channel_id");
return;
}
if (channel_has_htlc_out(forget->channel) ||
channel_has_htlc_in(forget->channel)) {
command_fail(cmd, "This channel has HTLCs attached and it is "
"not safe to forget it. Please use `close` "
"or `dev-fail` instead.");
command_fail(cmd, LIGHTNINGD,
"This channel has HTLCs attached and it is "
"not safe to forget it. Please use `close` "
"or `dev-fail` instead.");
return;
}

View File

@ -11,6 +11,7 @@
#include <lightningd/chaintopology.h>
#include <lightningd/htlc_end.h>
#include <lightningd/jsonrpc.h>
#include <lightningd/jsonrpc_errors.h>
#include <lightningd/lightningd.h>
#include <lightningd/log.h>
#include <lightningd/pay.h>
@ -1647,12 +1648,14 @@ static void json_dev_ignore_htlcs(struct command *cmd, const char *buffer,
peer = peer_from_json(cmd->ld, buffer, nodeidtok);
if (!peer) {
command_fail(cmd, "Could not find channel with that peer");
command_fail(cmd, LIGHTNINGD,
"Could not find channel with that peer");
return;
}
if (!json_tok_bool(buffer, ignoretok, &peer->ignore_htlcs)) {
command_fail(cmd, "Invalid boolean '%.*s'",
command_fail(cmd, JSONRPC2_INVALID_PARAMS,
"Invalid boolean '%.*s'",
ignoretok->end - ignoretok->start,
buffer + ignoretok->start);
return;

View File

@ -51,7 +51,8 @@ bool channel_tell_funding_locked(struct lightningd *ld UNNEEDED,
u32 depth UNNEEDED)
{ fprintf(stderr, "channel_tell_funding_locked called!\n"); abort(); }
/* Generated stub for command_fail */
void command_fail(struct command *cmd UNNEEDED, const char *fmt UNNEEDED, ...)
void command_fail(struct command *cmd UNNEEDED, int code UNNEEDED,
const char *fmt UNNEEDED, ...)
{ fprintf(stderr, "command_fail called!\n"); abort(); }
/* Generated stub for command_still_pending */
void command_still_pending(struct command *cmd UNNEEDED)

View File

@ -16,6 +16,7 @@
#include <lightningd/hsm_control.h>
#include <lightningd/json.h>
#include <lightningd/jsonrpc.h>
#include <lightningd/jsonrpc_errors.h>
#include <lightningd/lightningd.h>
#include <lightningd/log.h>
#include <lightningd/peer_control.h>
@ -70,7 +71,8 @@ static void wallet_withdrawal_broadcast(struct bitcoind *bitcoind UNUSED,
json_object_end(response);
command_success(cmd, response);
} else {
command_fail(cmd, "Error broadcasting transaction: %s", output);
command_fail(cmd, LIGHTNINGD,
"Error broadcasting transaction: %s", output);
}
}
@ -109,13 +111,13 @@ static void json_withdraw(struct command *cmd,
/* Check that destination address could be understood. */
if (addr_parse == ADDRESS_PARSE_UNRECOGNIZED) {
command_fail(cmd, "Could not parse destination address");
command_fail(cmd, LIGHTNINGD, "Could not parse destination address");
return;
}
/* Check address given is compatible with the chain we are on. */
if (addr_parse == ADDRESS_PARSE_WRONG_NETWORK) {
command_fail(cmd,
command_fail(cmd, LIGHTNINGD,
"Destination address is not on network %s",
get_chainparams(cmd->ld)->network_name);
return;
@ -230,7 +232,7 @@ static void json_newaddr(struct command *cmd, const char *buffer UNUSED,
else if (json_tok_streq(buffer, addrtype, "bech32"))
is_p2wpkh = true;
else {
command_fail(cmd,
command_fail(cmd, JSONRPC2_INVALID_PARAMS,
"Invalid address type "
"(expected bech32 or p2sh-segwit)");
return;
@ -238,19 +240,19 @@ static void json_newaddr(struct command *cmd, const char *buffer UNUSED,
keyidx = wallet_get_newindex(cmd->ld);
if (keyidx < 0) {
command_fail(cmd, "Keys exhausted ");
command_fail(cmd, LIGHTNINGD, "Keys exhausted ");
return;
}
if (bip32_key_from_parent(cmd->ld->wallet->bip32_base, keyidx,
BIP32_FLAG_KEY_PUBLIC, &ext) != WALLY_OK) {
command_fail(cmd, "Keys generation failure");
command_fail(cmd, LIGHTNINGD, "Keys generation failure");
return;
}
if (!secp256k1_ec_pubkey_parse(secp256k1_ctx, &pubkey.pubkey,
ext.pub_key, sizeof(ext.pub_key))) {
command_fail(cmd, "Key parsing failure");
command_fail(cmd, LIGHTNINGD, "Key parsing failure");
return;
}
@ -260,7 +262,8 @@ static void json_newaddr(struct command *cmd, const char *buffer UNUSED,
&pubkey, !is_p2wpkh,
NULL);
if (!out) {
command_fail(cmd, "p2wpkh address encoding failure.");
command_fail(cmd, LIGHTNINGD,
"p2wpkh address encoding failure.");
return;
}
@ -307,13 +310,14 @@ static void json_listaddrs(struct command *cmd,
if (bip32_key_from_parent(cmd->ld->wallet->bip32_base, keyidx,
BIP32_FLAG_KEY_PUBLIC, &ext) != WALLY_OK) {
command_fail(cmd, "Keys generation failure");
command_fail(cmd, LIGHTNINGD,
"Keys generation failure");
return;
}
if (!secp256k1_ec_pubkey_parse(secp256k1_ctx, &pubkey.pubkey,
ext.pub_key, sizeof(ext.pub_key))) {
command_fail(cmd, "Key parsing failure");
command_fail(cmd, LIGHTNINGD, "Key parsing failure");
return;
}
@ -331,7 +335,8 @@ static void json_listaddrs(struct command *cmd,
false,
&redeemscript_p2wpkh);
if (!out_p2wpkh) {
command_fail(cmd, "p2wpkh address encoding failure.");
command_fail(cmd, LIGHTNINGD,
"p2wpkh address encoding failure.");
return;
}
@ -387,7 +392,8 @@ static void json_listfunds(struct command *cmd, const char *buffer UNUSED,
utxos[i]->is_p2sh,
NULL);
if (!out) {
command_fail(cmd, "p2wpkh address encoding failure.");
command_fail(cmd, LIGHTNINGD,
"p2wpkh address encoding failure.");
return;
}
json_add_string(response, "address", out);