From 7f437715d5f6007d579fcc150bfa1c50008522f4 Mon Sep 17 00:00:00 2001 From: Mark Beckwith Date: Thu, 24 May 2018 16:40:18 -0500 Subject: [PATCH] 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). --- common/wallet_tx.c | 7 +-- lightningd/chaintopology.c | 4 +- lightningd/connect_control.c | 16 ++++--- lightningd/dev_ping.c | 22 +++++---- lightningd/gossip_control.c | 31 +++++++------ lightningd/invoice.c | 86 ++++++++++++++++++++++-------------- lightningd/jsonrpc.c | 86 ++++++++++++++++++------------------ lightningd/jsonrpc.h | 3 +- lightningd/jsonrpc_errors.h | 6 +++ lightningd/log.c | 3 +- lightningd/memdump.c | 3 +- lightningd/opening_control.c | 27 ++++++----- lightningd/options.c | 4 +- lightningd/pay.c | 50 +++++++++++++-------- lightningd/payalgo.c | 31 ++++++++----- lightningd/peer_control.c | 82 +++++++++++++++++++++------------- lightningd/peer_htlcs.c | 7 ++- wallet/test/run-wallet.c | 3 +- wallet/walletrpc.c | 30 ++++++++----- 19 files changed, 303 insertions(+), 198 deletions(-) diff --git a/common/wallet_tx.c b/common/wallet_tx.c index bc0ca3af6..104f265bd 100644 --- a/common/wallet_tx.c +++ b/common/wallet_tx.c @@ -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) { diff --git a/lightningd/chaintopology.c b/lightningd/chaintopology.c index 031c5edcc..3b19bcde9 100644 --- a/lightningd/chaintopology.c +++ b/lightningd/chaintopology.c @@ -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; diff --git a/lightningd/connect_control.c b/lightningd/connect_control.c index 068d600dd..63345e546 100644 --- a/lightningd/connect_control.c +++ b/lightningd/connect_control.c @@ -6,6 +6,7 @@ #include #include #include +#include #include #include #include @@ -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; } diff --git a/lightningd/dev_ping.c b/lightningd/dev_ping.c index 5f2d93588..131703fef 100644 --- a/lightningd/dev_ping.c +++ b/lightningd/dev_ping.c @@ -5,6 +5,7 @@ #include #include #include +#include #include #include #include @@ -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"); diff --git a/lightningd/gossip_control.c b/lightningd/gossip_control.c index c7153a1f9..33fe65757 100644 --- a/lightningd/gossip_control.c +++ b/lightningd/gossip_control.c @@ -24,6 +24,7 @@ #include #include #include +#include #include #include #include @@ -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; } } diff --git a/lightningd/invoice.c b/lightningd/invoice.c index a0feaea20..227a10031 100644 --- a/lightningd/invoice.c +++ b/lightningd/invoice.c @@ -1,6 +1,7 @@ #include "invoice.h" #include "json.h" #include "jsonrpc.h" +#include "jsonrpc_errors.h" #include "lightningd.h" #include #include @@ -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; } diff --git a/lightningd/jsonrpc.c b/lightningd/jsonrpc.c index 8fda08270..b50fc7a13 100644 --- a/lightningd/jsonrpc.c +++ b/lightningd/jsonrpc.c @@ -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; } + diff --git a/lightningd/jsonrpc.h b/lightningd/jsonrpc.h index 0cb8ff867..bb7715ef5 100644 --- a/lightningd/jsonrpc.h +++ b/lightningd/jsonrpc.h @@ -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, diff --git a/lightningd/jsonrpc_errors.h b/lightningd/jsonrpc_errors.h index 9312eb8de..7bf3fbb77 100644 --- a/lightningd/jsonrpc_errors.h +++ b/lightningd/jsonrpc_errors.h @@ -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 diff --git a/lightningd/log.c b/lightningd/log.c index 7e524f0aa..66c1adc4a 100644 --- a/lightningd/log.c +++ b/lightningd/log.c @@ -15,6 +15,7 @@ #include #include #include +#include #include #include #include @@ -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; } diff --git a/lightningd/memdump.c b/lightningd/memdump.c index d2d536c23..e82e31af4 100644 --- a/lightningd/memdump.c +++ b/lightningd/memdump.c @@ -5,6 +5,7 @@ #include #include #include +#include #include #include #include @@ -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; } diff --git a/lightningd/opening_control.c b/lightningd/opening_control.c index 9f833047d..272d63112 100644 --- a/lightningd/opening_control.c +++ b/lightningd/opening_control.c @@ -15,6 +15,7 @@ #include #include #include +#include #include #include #include @@ -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; } diff --git a/lightningd/options.c b/lightningd/options.c index bff71ac2a..eb0575e2a 100644 --- a/lightningd/options.c +++ b/lightningd/options.c @@ -20,6 +20,7 @@ #include #include #include +#include #include #include #include @@ -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; diff --git a/lightningd/pay.c b/lightningd/pay.c index 1836c8e23..3f5269142 100644 --- a/lightningd/pay.c +++ b/lightningd/pay.c @@ -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; diff --git a/lightningd/payalgo.c b/lightningd/payalgo.c index a84b7719a..ede917e1b 100644 --- a/lightningd/payalgo.c +++ b/lightningd/payalgo.c @@ -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", diff --git a/lightningd/peer_control.c b/lightningd/peer_control.c index 1439995c8..f2d51a439 100644 --- a/lightningd/peer_control.c +++ b/lightningd/peer_control.c @@ -33,6 +33,7 @@ #include #include #include +#include #include #include #include @@ -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; } diff --git a/lightningd/peer_htlcs.c b/lightningd/peer_htlcs.c index 560f57626..7490d3dab 100644 --- a/lightningd/peer_htlcs.c +++ b/lightningd/peer_htlcs.c @@ -11,6 +11,7 @@ #include #include #include +#include #include #include #include @@ -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; diff --git a/wallet/test/run-wallet.c b/wallet/test/run-wallet.c index d0d607f26..ed26dd16c 100644 --- a/wallet/test/run-wallet.c +++ b/wallet/test/run-wallet.c @@ -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) diff --git a/wallet/walletrpc.c b/wallet/walletrpc.c index d35bde6ee..b5dd4157e 100644 --- a/wallet/walletrpc.c +++ b/wallet/walletrpc.c @@ -16,6 +16,7 @@ #include #include #include +#include #include #include #include @@ -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);