mirror of
https://github.com/ElementsProject/lightning.git
synced 2025-03-01 17:47:30 +01:00
json_command: command_fail_badparam helper.
It's common to want to complain a token is not what we expected. Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
This commit is contained in:
parent
aa441e3b27
commit
39e4796ae3
13 changed files with 110 additions and 159 deletions
|
@ -5,6 +5,8 @@
|
||||||
#include "config.h"
|
#include "config.h"
|
||||||
#include <ccan/compiler/compiler.h>
|
#include <ccan/compiler/compiler.h>
|
||||||
#include <common/errcode.h>
|
#include <common/errcode.h>
|
||||||
|
#include <common/json.h>
|
||||||
|
#include <common/jsonrpc_errors.h>
|
||||||
#include <stdbool.h>
|
#include <stdbool.h>
|
||||||
|
|
||||||
struct command;
|
struct command;
|
||||||
|
@ -15,6 +17,21 @@ struct command_result *command_fail(struct command *cmd, errcode_t code,
|
||||||
const char *fmt, ...)
|
const char *fmt, ...)
|
||||||
PRINTF_FMT(3, 4) WARN_UNUSED_RESULT;
|
PRINTF_FMT(3, 4) WARN_UNUSED_RESULT;
|
||||||
|
|
||||||
|
/* Convenient wrapper for "paramname: msg: invalid token '.*%s'" */
|
||||||
|
static inline struct command_result *
|
||||||
|
command_fail_badparam(struct command *cmd,
|
||||||
|
const char *paramname,
|
||||||
|
const char *buffer,
|
||||||
|
const jsmntok_t *tok,
|
||||||
|
const char *msg)
|
||||||
|
{
|
||||||
|
return command_fail(cmd, JSONRPC2_INVALID_PARAMS,
|
||||||
|
"%s: %s: invalid token '%.*s'",
|
||||||
|
paramname, msg,
|
||||||
|
json_tok_full_len(tok),
|
||||||
|
json_tok_full(buffer, tok));
|
||||||
|
}
|
||||||
|
|
||||||
/* Also caller supplied: is this invoked simply to get usage? */
|
/* Also caller supplied: is this invoked simply to get usage? */
|
||||||
bool command_usage_only(const struct command *cmd);
|
bool command_usage_only(const struct command *cmd);
|
||||||
|
|
||||||
|
|
|
@ -25,9 +25,7 @@ struct command_result *param_array(struct command *cmd, const char *name,
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
return command_fail(cmd, JSONRPC2_INVALID_PARAMS,
|
return command_fail_badparam(cmd, name, buffer, tok, "should be an array");
|
||||||
"'%s' should be an array, not '%.*s'",
|
|
||||||
name, tok->end - tok->start, buffer + tok->start);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
struct command_result *param_bool(struct command *cmd, const char *name,
|
struct command_result *param_bool(struct command *cmd, const char *name,
|
||||||
|
@ -37,9 +35,8 @@ struct command_result *param_bool(struct command *cmd, const char *name,
|
||||||
*b = tal(cmd, bool);
|
*b = tal(cmd, bool);
|
||||||
if (json_to_bool(buffer, tok, *b))
|
if (json_to_bool(buffer, tok, *b))
|
||||||
return NULL;
|
return NULL;
|
||||||
return command_fail(cmd, JSONRPC2_INVALID_PARAMS,
|
return command_fail_badparam(cmd, name, buffer, tok,
|
||||||
"'%s' should be 'true' or 'false', not '%.*s'",
|
"should be 'true' or 'false'");
|
||||||
name, tok->end - tok->start, buffer + tok->start);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
struct command_result *param_millionths(struct command *cmd, const char *name,
|
struct command_result *param_millionths(struct command *cmd, const char *name,
|
||||||
|
@ -50,10 +47,8 @@ struct command_result *param_millionths(struct command *cmd, const char *name,
|
||||||
if (json_to_millionths(buffer, tok, *num))
|
if (json_to_millionths(buffer, tok, *num))
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
return command_fail(
|
return command_fail_badparam(cmd, name, buffer, tok,
|
||||||
cmd, JSONRPC2_INVALID_PARAMS,
|
"should be a non-negative floating-point number");
|
||||||
"'%s' should be a non-negative floating-point number, not '%.*s'",
|
|
||||||
name, tok->end - tok->start, buffer + tok->start);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
struct command_result *param_escaped_string(struct command *cmd,
|
struct command_result *param_escaped_string(struct command *cmd,
|
||||||
|
@ -71,11 +66,8 @@ struct command_result *param_escaped_string(struct command *cmd,
|
||||||
if (*str)
|
if (*str)
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
return command_fail(cmd, JSONRPC2_INVALID_PARAMS,
|
return command_fail_badparam(cmd, name, buffer, tok,
|
||||||
"'%s' should be a string, not '%.*s'"
|
"should be a string (without \\u)");
|
||||||
" (note, we don't allow \\u)",
|
|
||||||
name,
|
|
||||||
tok->end - tok->start, buffer + tok->start);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
struct command_result *param_string(struct command *cmd, const char *name,
|
struct command_result *param_string(struct command *cmd, const char *name,
|
||||||
|
@ -103,9 +95,8 @@ struct command_result *param_label(struct command *cmd, const char *name,
|
||||||
if (*label && (tok->type == JSMN_STRING || json_tok_is_num(buffer, tok)))
|
if (*label && (tok->type == JSMN_STRING || json_tok_is_num(buffer, tok)))
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
return command_fail(cmd, JSONRPC2_INVALID_PARAMS,
|
return command_fail_badparam(cmd, name, buffer, tok,
|
||||||
"'%s' should be a string or number, not '%.*s'",
|
"should be a string or number");
|
||||||
name, tok->end - tok->start, buffer + tok->start);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
struct command_result *param_number(struct command *cmd, const char *name,
|
struct command_result *param_number(struct command *cmd, const char *name,
|
||||||
|
@ -116,9 +107,8 @@ struct command_result *param_number(struct command *cmd, const char *name,
|
||||||
if (json_to_number(buffer, tok, *num))
|
if (json_to_number(buffer, tok, *num))
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
return command_fail(cmd, JSONRPC2_INVALID_PARAMS,
|
return command_fail_badparam(cmd, name, buffer, tok,
|
||||||
"'%s' should be an integer, not '%.*s'",
|
"should be an integer");
|
||||||
name, tok->end - tok->start, buffer + tok->start);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
struct command_result *param_sha256(struct command *cmd, const char *name,
|
struct command_result *param_sha256(struct command *cmd, const char *name,
|
||||||
|
@ -131,9 +121,8 @@ struct command_result *param_sha256(struct command *cmd, const char *name,
|
||||||
*hash, sizeof(**hash)))
|
*hash, sizeof(**hash)))
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
return command_fail(cmd, JSONRPC2_INVALID_PARAMS,
|
return command_fail_badparam(cmd, name, buffer, tok,
|
||||||
"'%s' should be a 32 byte hex value, not '%.*s'",
|
"should be a 32 byte hex value");
|
||||||
name, tok->end - tok->start, buffer + tok->start);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
struct command_result *param_u64(struct command *cmd, const char *name,
|
struct command_result *param_u64(struct command *cmd, const char *name,
|
||||||
|
@ -144,9 +133,8 @@ struct command_result *param_u64(struct command *cmd, const char *name,
|
||||||
if (json_to_u64(buffer, tok, *num))
|
if (json_to_u64(buffer, tok, *num))
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
return command_fail(cmd, JSONRPC2_INVALID_PARAMS,
|
return command_fail_badparam(cmd, name, buffer, tok,
|
||||||
"'%s' should be an unsigned 64 bit integer, not '%.*s'",
|
"should be an unsigned 64 bit integer");
|
||||||
name, tok->end - tok->start, buffer + tok->start);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
struct command_result *param_tok(struct command *cmd, const char *name,
|
struct command_result *param_tok(struct command *cmd, const char *name,
|
||||||
|
@ -165,9 +153,8 @@ struct command_result *param_msat(struct command *cmd, const char *name,
|
||||||
if (parse_amount_msat(*msat, buffer + tok->start, tok->end - tok->start))
|
if (parse_amount_msat(*msat, buffer + tok->start, tok->end - tok->start))
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
return command_fail(cmd, JSONRPC2_INVALID_PARAMS,
|
return command_fail_badparam(cmd, name, buffer, tok,
|
||||||
"'%s' should be a millisatoshi amount, not '%.*s'",
|
"should be a millisatoshi amount");
|
||||||
name, tok->end - tok->start, buffer + tok->start);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
struct command_result *param_sat(struct command *cmd, const char *name,
|
struct command_result *param_sat(struct command *cmd, const char *name,
|
||||||
|
@ -178,10 +165,8 @@ struct command_result *param_sat(struct command *cmd, const char *name,
|
||||||
if (parse_amount_sat(*sat, buffer + tok->start, tok->end - tok->start))
|
if (parse_amount_sat(*sat, buffer + tok->start, tok->end - tok->start))
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
return command_fail(cmd, JSONRPC2_INVALID_PARAMS,
|
return command_fail_badparam(cmd, name, buffer, tok,
|
||||||
"%s should be a satoshi amount, not '%.*s'",
|
"should be a satoshi amount");
|
||||||
name ? name : "amount field",
|
|
||||||
tok->end - tok->start, buffer + tok->start);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
struct command_result *param_sat_or_all(struct command *cmd, const char *name,
|
struct command_result *param_sat_or_all(struct command *cmd, const char *name,
|
||||||
|
@ -204,10 +189,8 @@ struct command_result *param_node_id(struct command *cmd, const char *name,
|
||||||
if (json_to_node_id(buffer, tok, *id))
|
if (json_to_node_id(buffer, tok, *id))
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
return command_fail(cmd, JSONRPC2_INVALID_PARAMS,
|
return command_fail_badparam(cmd, name, buffer, tok,
|
||||||
"'%s' should be a node id, not '%.*s'",
|
"should be a node id");
|
||||||
name, json_tok_full_len(tok),
|
|
||||||
json_tok_full(buffer, tok));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
struct command_result *param_channel_id(struct command *cmd, const char *name,
|
struct command_result *param_channel_id(struct command *cmd, const char *name,
|
||||||
|
@ -218,10 +201,8 @@ struct command_result *param_channel_id(struct command *cmd, const char *name,
|
||||||
if (json_to_channel_id(buffer, tok, *cid))
|
if (json_to_channel_id(buffer, tok, *cid))
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
return command_fail(cmd, JSONRPC2_INVALID_PARAMS,
|
return command_fail_badparam(cmd, name, buffer, tok,
|
||||||
"'%s' should be a channel id, not '%.*s'",
|
"should be a channel id");
|
||||||
name, json_tok_full_len(tok),
|
|
||||||
json_tok_full(buffer, tok));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
struct command_result *param_secret(struct command *cmd, const char *name,
|
struct command_result *param_secret(struct command *cmd, const char *name,
|
||||||
|
@ -234,9 +215,8 @@ struct command_result *param_secret(struct command *cmd, const char *name,
|
||||||
*secret, sizeof(**secret)))
|
*secret, sizeof(**secret)))
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
return command_fail(cmd, JSONRPC2_INVALID_PARAMS,
|
return command_fail_badparam(cmd, name, buffer, tok,
|
||||||
"'%s' should be a 32 byte hex value, not '%.*s'",
|
"should be a 32 byte hex value");
|
||||||
name, tok->end - tok->start, buffer + tok->start);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
struct command_result *param_bin_from_hex(struct command *cmd, const char *name,
|
struct command_result *param_bin_from_hex(struct command *cmd, const char *name,
|
||||||
|
@ -246,10 +226,9 @@ struct command_result *param_bin_from_hex(struct command *cmd, const char *name,
|
||||||
*bin = json_tok_bin_from_hex(cmd, buffer, tok);
|
*bin = json_tok_bin_from_hex(cmd, buffer, tok);
|
||||||
if (bin != NULL)
|
if (bin != NULL)
|
||||||
return NULL;
|
return NULL;
|
||||||
else
|
|
||||||
return command_fail(cmd, JSONRPC2_INVALID_PARAMS,
|
return command_fail_badparam(cmd, name, buffer, tok,
|
||||||
"'%s' should be a hex value, not '%.*s'",
|
"should be a hex value");
|
||||||
name, tok->end - tok->start, buffer + tok->start);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
struct command_result *param_hops_array(struct command *cmd, const char *name,
|
struct command_result *param_hops_array(struct command *cmd, const char *name,
|
||||||
|
@ -260,10 +239,8 @@ struct command_result *param_hops_array(struct command *cmd, const char *name,
|
||||||
struct sphinx_hop h;
|
struct sphinx_hop h;
|
||||||
size_t i;
|
size_t i;
|
||||||
if (tok->type != JSMN_ARRAY) {
|
if (tok->type != JSMN_ARRAY) {
|
||||||
return command_fail(
|
return command_fail_badparam(cmd, name, buffer, tok,
|
||||||
cmd, JSONRPC2_INVALID_PARAMS,
|
"should be an array of hops");
|
||||||
"'%s' should be an array of hops, got '%.*s'", name,
|
|
||||||
tok->end - tok->start, buffer + tok->start);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
*hops = tal_arr(cmd, struct sphinx_hop, 0);
|
*hops = tal_arr(cmd, struct sphinx_hop, 0);
|
||||||
|
@ -282,18 +259,13 @@ struct command_result *param_hops_array(struct command *cmd, const char *name,
|
||||||
|
|
||||||
h.raw_payload = json_tok_bin_from_hex(*hops, buffer, payloadtok);
|
h.raw_payload = json_tok_bin_from_hex(*hops, buffer, payloadtok);
|
||||||
if (!json_to_pubkey(buffer, pubkeytok, &h.pubkey))
|
if (!json_to_pubkey(buffer, pubkeytok, &h.pubkey))
|
||||||
return command_fail(
|
return command_fail_badparam(cmd, name, buffer, pubkeytok,
|
||||||
cmd, JSONRPC2_INVALID_PARAMS,
|
"should be a pubkey");
|
||||||
"'pubkey' should be a pubkey, not '%.*s'",
|
|
||||||
pubkeytok->end - pubkeytok->start,
|
|
||||||
buffer + pubkeytok->start);
|
|
||||||
|
|
||||||
if (!h.raw_payload)
|
if (!h.raw_payload)
|
||||||
return command_fail(
|
return command_fail_badparam(cmd, name, buffer,
|
||||||
cmd, JSONRPC2_INVALID_PARAMS,
|
payloadtok,
|
||||||
"'payload' should be a hex encoded binary, not '%.*s'",
|
"should be hex");
|
||||||
pubkeytok->end - pubkeytok->start,
|
|
||||||
buffer + pubkeytok->start);
|
|
||||||
|
|
||||||
tal_arr_expand(hops, h);
|
tal_arr_expand(hops, h);
|
||||||
}
|
}
|
||||||
|
@ -316,10 +288,8 @@ struct command_result *param_secrets_array(struct command *cmd,
|
||||||
struct secret secret;
|
struct secret secret;
|
||||||
|
|
||||||
if (tok->type != JSMN_ARRAY) {
|
if (tok->type != JSMN_ARRAY) {
|
||||||
return command_fail(
|
return command_fail_badparam(cmd, name, buffer, tok,
|
||||||
cmd, JSONRPC2_INVALID_PARAMS,
|
"should be an array of secrets");
|
||||||
"'%s' should be an array of secrets, got '%.*s'", name,
|
|
||||||
tok->end - tok->start, buffer + tok->start);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
*secrets = tal_arr(cmd, struct secret, 0);
|
*secrets = tal_arr(cmd, struct secret, 0);
|
||||||
|
@ -500,10 +470,8 @@ struct command_result *param_txid(struct command *cmd,
|
||||||
*txid = tal(cmd, struct bitcoin_txid);
|
*txid = tal(cmd, struct bitcoin_txid);
|
||||||
if (json_to_txid(buffer, tok, *txid))
|
if (json_to_txid(buffer, tok, *txid))
|
||||||
return NULL;
|
return NULL;
|
||||||
return command_fail(cmd, JSONRPC2_INVALID_PARAMS,
|
return command_fail_badparam(cmd, name, buffer, tok,
|
||||||
"'%s' should be txid, not '%.*s'",
|
"should be a txid");
|
||||||
name, json_tok_full_len(tok),
|
|
||||||
json_tok_full(buffer, tok));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
struct command_result *param_bitcoin_address(struct command *cmd,
|
struct command_result *param_bitcoin_address(struct command *cmd,
|
||||||
|
|
|
@ -516,7 +516,7 @@ static void advanced_fail(void)
|
||||||
p_req("msat", param_u64, &msat),
|
p_req("msat", param_u64, &msat),
|
||||||
NULL));
|
NULL));
|
||||||
assert(check_fail());
|
assert(check_fail());
|
||||||
assert(strstr(fail_msg, "'msat' should be an unsigned 64 bit integer, not 'anyx'"));
|
assert(strstr(fail_msg, "msat: should be an unsigned 64 bit integer: invalid token '\"anyx\"'"));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -415,11 +415,9 @@ static struct command_result *json_getroute(struct command *cmd,
|
||||||
struct node_id *node_id = tal(tmpctx, struct node_id);
|
struct node_id *node_id = tal(tmpctx, struct node_id);
|
||||||
|
|
||||||
if (!json_to_node_id(buffer, t, node_id))
|
if (!json_to_node_id(buffer, t, node_id))
|
||||||
return command_fail(cmd, JSONRPC2_INVALID_PARAMS,
|
return command_fail_badparam(cmd, "exclude",
|
||||||
"%.*s is not a valid"
|
buffer, t,
|
||||||
" short_channel_id/node_id",
|
"should be short_channel_id or node_id");
|
||||||
t->end - t->start,
|
|
||||||
buffer + t->start);
|
|
||||||
|
|
||||||
entry->type = EXCLUDE_NODE;
|
entry->type = EXCLUDE_NODE;
|
||||||
entry->u.node_id = *node_id;
|
entry->u.node_id = *node_id;
|
||||||
|
|
|
@ -982,12 +982,8 @@ static struct command_result *param_positive_msat_or_any(struct command *cmd,
|
||||||
&& !amount_msat_eq(**msat, AMOUNT_MSAT(0)))
|
&& !amount_msat_eq(**msat, AMOUNT_MSAT(0)))
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
return command_fail(cmd, JSONRPC2_INVALID_PARAMS,
|
return command_fail_badparam(cmd, name, buffer, tok,
|
||||||
"'%s' should be positive millisatoshis or 'any',"
|
"should be positive msat or 'any'");
|
||||||
" not '%.*s'",
|
|
||||||
name,
|
|
||||||
tok->end - tok->start,
|
|
||||||
buffer + tok->start);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Parse time with optional suffix, return seconds */
|
/* Parse time with optional suffix, return seconds */
|
||||||
|
@ -1026,18 +1022,15 @@ static struct command_result *param_time(struct command *cmd, const char *name,
|
||||||
*secs = tal(cmd, uint64_t);
|
*secs = tal(cmd, uint64_t);
|
||||||
if (json_to_u64(buffer, &timetok, *secs)) {
|
if (json_to_u64(buffer, &timetok, *secs)) {
|
||||||
if (mul_overflows_u64(**secs, mul)) {
|
if (mul_overflows_u64(**secs, mul)) {
|
||||||
return command_fail(cmd, JSONRPC2_INVALID_PARAMS,
|
return command_fail_badparam(cmd, name, buffer, tok,
|
||||||
"'%s' string '%.*s' is too large",
|
"value too large");
|
||||||
name, tok->end - tok->start,
|
|
||||||
buffer + tok->start);
|
|
||||||
}
|
}
|
||||||
**secs *= mul;
|
**secs *= mul;
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
return command_fail(cmd, JSONRPC2_INVALID_PARAMS,
|
return command_fail_badparam(cmd, name, buffer, tok,
|
||||||
"'%s' should be a number with optional {s,m,h,d,w} suffix, not '%.*s'",
|
"should be a number with optional {s,m,h,d,w} suffix");
|
||||||
name, tok->end - tok->start, buffer + tok->start);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static struct command_result *param_chanhints(struct command *cmd,
|
static struct command_result *param_chanhints(struct command *cmd,
|
||||||
|
@ -1070,10 +1063,8 @@ static struct command_result *param_chanhints(struct command *cmd,
|
||||||
json_for_each_arr(i, t, tok) {
|
json_for_each_arr(i, t, tok) {
|
||||||
if (!json_to_short_channel_id(buffer, t,
|
if (!json_to_short_channel_id(buffer, t,
|
||||||
&(*chanhints)->hints[i])) {
|
&(*chanhints)->hints[i])) {
|
||||||
return command_fail(cmd, JSONRPC2_INVALID_PARAMS,
|
return command_fail_badparam(cmd, name, buffer, t,
|
||||||
"'%s' should be a short channel id, not '%.*s'",
|
"should be a short channel id");
|
||||||
name, json_tok_full_len(t),
|
|
||||||
json_tok_full(buffer, t));
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return NULL;
|
return NULL;
|
||||||
|
@ -1163,8 +1154,9 @@ static struct command_result *json_invoice(struct command *cmd,
|
||||||
preimagetok->end - preimagetok->start,
|
preimagetok->end - preimagetok->start,
|
||||||
&info->payment_preimage,
|
&info->payment_preimage,
|
||||||
sizeof(info->payment_preimage))) {
|
sizeof(info->payment_preimage))) {
|
||||||
return command_fail(cmd, JSONRPC2_INVALID_PARAMS,
|
return command_fail_badparam(cmd, "preimage",
|
||||||
"preimage must be 64 hex digits");
|
buffer, preimagetok,
|
||||||
|
"should be 64 hex digits");
|
||||||
}
|
}
|
||||||
} else
|
} else
|
||||||
/* Generate random secret preimage. */
|
/* Generate random secret preimage. */
|
||||||
|
|
|
@ -31,10 +31,8 @@ struct command_result *param_pubkey(struct command *cmd, const char *name,
|
||||||
if (json_to_pubkey(buffer, tok, *pubkey))
|
if (json_to_pubkey(buffer, tok, *pubkey))
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
return command_fail(cmd, JSONRPC2_INVALID_PARAMS,
|
return command_fail_badparam(cmd, name, buffer, tok,
|
||||||
"'%s' should be a pubkey, not '%.*s'",
|
"should be a compressed pubkey");
|
||||||
name, json_tok_full_len(tok),
|
|
||||||
json_tok_full(buffer, tok));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
struct command_result *param_short_channel_id(struct command *cmd,
|
struct command_result *param_short_channel_id(struct command *cmd,
|
||||||
|
@ -47,10 +45,8 @@ struct command_result *param_short_channel_id(struct command *cmd,
|
||||||
if (json_to_short_channel_id(buffer, tok, *scid))
|
if (json_to_short_channel_id(buffer, tok, *scid))
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
return command_fail(cmd, JSONRPC2_INVALID_PARAMS,
|
return command_fail_badparam(cmd, name, buffer, tok,
|
||||||
"'%s' should be a short channel id, not '%.*s'",
|
"should be a short_channel_id of form NxNxN");
|
||||||
name, json_tok_full_len(tok),
|
|
||||||
json_tok_full(buffer, tok));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
struct command_result *param_feerate_style(struct command *cmd,
|
struct command_result *param_feerate_style(struct command *cmd,
|
||||||
|
|
|
@ -916,12 +916,9 @@ struct command_result *param_loglevel(struct command *cmd,
|
||||||
else if (json_tok_streq(buffer, tok, "unusual"))
|
else if (json_tok_streq(buffer, tok, "unusual"))
|
||||||
**level = LOG_UNUSUAL;
|
**level = LOG_UNUSUAL;
|
||||||
else {
|
else {
|
||||||
return command_fail(cmd, JSONRPC2_INVALID_PARAMS,
|
return command_fail_badparam(cmd, name, buffer, tok,
|
||||||
"'%s' should be 'io', 'debug', 'info', or "
|
"should be 'io', 'debug', 'info', or "
|
||||||
"'unusual', not '%.*s'",
|
"'unusual'");
|
||||||
name,
|
|
||||||
json_tok_full_len(tok),
|
|
||||||
json_tok_full(buffer, tok));
|
|
||||||
}
|
}
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
|
@ -240,8 +240,8 @@ static struct command_result *param_reply_path(struct command *cmd,
|
||||||
return command_fail(cmd, JSONRPC2_INVALID_PARAMS,
|
return command_fail(cmd, JSONRPC2_INVALID_PARAMS,
|
||||||
"%s has no 'blinding'", name);
|
"%s has no 'blinding'", name);
|
||||||
if (!json_to_pubkey(buffer, tblinding, &(*reply_path)->blinding))
|
if (!json_to_pubkey(buffer, tblinding, &(*reply_path)->blinding))
|
||||||
return command_fail(cmd, JSONRPC2_INVALID_PARAMS,
|
return command_fail_badparam(cmd, name, buffer, tblinding,
|
||||||
"%s 'blinding' invalid pubkey", name);
|
"'blinding' should be valid pubkey");
|
||||||
|
|
||||||
tpath = json_get_member(buffer, tok, "path");
|
tpath = json_get_member(buffer, tok, "path");
|
||||||
if (!tpath || tpath->type != JSMN_ARRAY)
|
if (!tpath || tpath->type != JSMN_ARRAY)
|
||||||
|
|
|
@ -1128,39 +1128,29 @@ param_route_hop(struct command *cmd, const char *name, const char *buffer,
|
||||||
if (!idtok) {
|
if (!idtok) {
|
||||||
memset(&res->nodeid, 0, sizeof(struct node_id));
|
memset(&res->nodeid, 0, sizeof(struct node_id));
|
||||||
} else if (!json_to_node_id(buffer, idtok, &res->nodeid)) {
|
} else if (!json_to_node_id(buffer, idtok, &res->nodeid)) {
|
||||||
return command_fail(cmd, JSONRPC2_INVALID_PARAMS,
|
return command_fail_badparam(cmd, name, buffer, idtok,
|
||||||
"'%s' should be a node_id, not '%.*s'",
|
"should be a node_id");
|
||||||
name, tok->end - tok->start,
|
|
||||||
buffer + tok->start);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!channeltok) {
|
if (!channeltok) {
|
||||||
memset(&res->channel_id, 0, sizeof(struct node_id));
|
memset(&res->channel_id, 0, sizeof(struct node_id));
|
||||||
} else if (!json_to_short_channel_id(buffer, channeltok, &res->channel_id)) {
|
} else if (!json_to_short_channel_id(buffer, channeltok, &res->channel_id)) {
|
||||||
return command_fail(
|
return command_fail_badparam(cmd, name, buffer, channeltok,
|
||||||
cmd, JSONRPC2_INVALID_PARAMS,
|
"should be a short_channel_id");
|
||||||
"'%s' should be a short_channel_id, not '%.*s'", name,
|
|
||||||
tok->end - tok->start, buffer + tok->start);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (directiontok && (!json_to_int(buffer, directiontok, &res->direction) ||
|
if (directiontok && (!json_to_int(buffer, directiontok, &res->direction) ||
|
||||||
res->direction > 1 || res->direction < 0))
|
res->direction > 1 || res->direction < 0))
|
||||||
return command_fail(
|
return command_fail_badparam(cmd, name, buffer, directiontok,
|
||||||
cmd, JSONRPC2_INVALID_PARAMS,
|
"should be 0 or 1");
|
||||||
"'%s' should be an integer in [0,1], not '%.*s'", name,
|
|
||||||
tok->end - tok->start, buffer + tok->start);
|
|
||||||
|
|
||||||
if (!json_to_msat(buffer, amounttok, &res->amount))
|
if (!json_to_msat(buffer, amounttok, &res->amount))
|
||||||
return command_fail(cmd, JSONRPC2_INVALID_PARAMS,
|
return command_fail_badparam(cmd, name, buffer, amounttok,
|
||||||
"'%s' should be a valid amount_msat, not '%.*s'",
|
"should be a valid amount_msat");
|
||||||
name, tok->end - tok->start,
|
|
||||||
buffer + tok->start);
|
|
||||||
|
|
||||||
if (!json_to_number(buffer, delaytok, &res->delay) || res->delay < 1)
|
if (!json_to_number(buffer, delaytok, &res->delay) || res->delay < 1)
|
||||||
return command_fail(
|
return command_fail_badparam(cmd, name, buffer, delaytok,
|
||||||
cmd, JSONRPC2_INVALID_PARAMS,
|
"should be a positive, non-zero, number");
|
||||||
"'%s' should be a positive, non-zero, number, not '%.*s'",
|
|
||||||
name, tok->end - tok->start, buffer + tok->start);
|
|
||||||
|
|
||||||
*hop = res;
|
*hop = res;
|
||||||
return NULL;
|
return NULL;
|
||||||
|
@ -1237,10 +1227,8 @@ static struct command_result *param_route_hop_style(struct command *cmd,
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
return command_fail(cmd, JSONRPC2_INVALID_PARAMS,
|
return command_fail_badparam(cmd, name, buffer, tok,
|
||||||
"'%s' should be a legacy or tlv, not '%.*s'",
|
"should be 'legacy' or 'tlv'");
|
||||||
name, json_tok_full_len(tok),
|
|
||||||
json_tok_full(buffer, tok));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static struct command_result *param_route_hops(struct command *cmd,
|
static struct command_result *param_route_hops(struct command *cmd,
|
||||||
|
|
|
@ -1291,11 +1291,8 @@ command_find_channel(struct command *cmd,
|
||||||
tok->end - tok->start,
|
tok->end - tok->start,
|
||||||
buffer + tok->start);
|
buffer + tok->start);
|
||||||
} else {
|
} else {
|
||||||
return command_fail(cmd, JSONRPC2_INVALID_PARAMS,
|
return command_fail_badparam(cmd, "id", buffer, tok,
|
||||||
"Given id is not a channel ID or "
|
"should be a channel ID or short channel ID");
|
||||||
"short channel ID: '%.*s'",
|
|
||||||
json_tok_full_len(tok),
|
|
||||||
json_tok_full(buffer, tok));
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1464,6 +1461,7 @@ static struct command_result *json_close(struct command *cmd,
|
||||||
return command_still_pending(cmd);
|
return command_still_pending(cmd);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Magic marker: remove at your own peril! */
|
||||||
static const struct json_command close_command = {
|
static const struct json_command close_command = {
|
||||||
"close",
|
"close",
|
||||||
"channels",
|
"channels",
|
||||||
|
@ -1854,11 +1852,8 @@ static struct command_result *param_msat_u32(struct command *cmd,
|
||||||
|
|
||||||
*num = tal(cmd, u32);
|
*num = tal(cmd, u32);
|
||||||
if (!amount_msat_to_u32(*msat, *num)) {
|
if (!amount_msat_to_u32(*msat, *num)) {
|
||||||
return command_fail(cmd, JSONRPC2_INVALID_PARAMS,
|
return command_fail_badparam(cmd, name, buffer, tok,
|
||||||
"'%s' value '%s' exceeds u32 max",
|
"exceeds u32 max");
|
||||||
name,
|
|
||||||
type_to_string(tmpctx, struct amount_msat,
|
|
||||||
msat));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
|
@ -63,19 +63,19 @@ def test_invoice_zeroval(node_factory):
|
||||||
"""A zero value invoice is unpayable, did you mean 'any'?"""
|
"""A zero value invoice is unpayable, did you mean 'any'?"""
|
||||||
l1 = node_factory.get_node()
|
l1 = node_factory.get_node()
|
||||||
|
|
||||||
with pytest.raises(RpcError, match=r"positive .* not '0'"):
|
with pytest.raises(RpcError, match=r"positive .*: invalid token '0'"):
|
||||||
l1.rpc.invoice(0, 'inv', '?')
|
l1.rpc.invoice(0, 'inv', '?')
|
||||||
|
|
||||||
with pytest.raises(RpcError, match=r"positive .* not '0msat'"):
|
with pytest.raises(RpcError, match=r"positive .*: invalid token .*0msat"):
|
||||||
l1.rpc.invoice('0msat', 'inv', '?')
|
l1.rpc.invoice('0msat', 'inv', '?')
|
||||||
|
|
||||||
with pytest.raises(RpcError, match=r"positive .* not '0sat'"):
|
with pytest.raises(RpcError, match=r"positive .*: invalid token .*0sat"):
|
||||||
l1.rpc.invoice('0sat', 'inv', '?')
|
l1.rpc.invoice('0sat', 'inv', '?')
|
||||||
|
|
||||||
with pytest.raises(RpcError, match=r"positive .* not '0.00000000btc'"):
|
with pytest.raises(RpcError, match=r"positive .*: invalid token .*0.00000000btc"):
|
||||||
l1.rpc.invoice('0.00000000btc', 'inv', '?')
|
l1.rpc.invoice('0.00000000btc', 'inv', '?')
|
||||||
|
|
||||||
with pytest.raises(RpcError, match=r"positive .* not '0.00000000000btc'"):
|
with pytest.raises(RpcError, match=r"positive .*: invalid token .*0.00000000000btc"):
|
||||||
l1.rpc.invoice('0.00000000000btc', 'inv', '?')
|
l1.rpc.invoice('0.00000000000btc', 'inv', '?')
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -1610,7 +1610,7 @@ def test_configfile_before_chdir(node_factory):
|
||||||
def test_json_error(node_factory):
|
def test_json_error(node_factory):
|
||||||
"""Must return valid json even if it quotes our weirdness"""
|
"""Must return valid json even if it quotes our weirdness"""
|
||||||
l1 = node_factory.get_node()
|
l1 = node_factory.get_node()
|
||||||
with pytest.raises(RpcError, match=r'Given id is not a channel ID or short channel ID'):
|
with pytest.raises(RpcError, match=r'id: should be a channel ID or short channel ID: invalid token'):
|
||||||
l1.rpc.close({"tx": "020000000001011490f737edd2ea2175a032b58ea7cd426dfc244c339cd044792096da3349b18a0100000000ffffffff021c900300000000001600140e64868e2f752314bc82a154c8c5bf32f3691bb74da00b00000000002200205b8cd3b914cf67cdd8fa6273c930353dd36476734fbd962102c2df53b90880cd0247304402202b2e3195a35dc694bbbc58942dc9ba59cc01d71ba55c9b0ad0610ccd6a65633702201a849254453d160205accc00843efb0ad1fe0e186efa6a7cee1fb6a1d36c736a012103d745445c9362665f22e0d96e9e766f273f3260dea39c8a76bfa05dd2684ddccf00000000", "txid": "2128c10f0355354479514f4a23eaa880d94e099406d419bbb0d800143accddbb", "channel_id": "bbddcc3a1400d8b0bb19d40694094ed980a8ea234a4f5179443555030fc12820"})
|
l1.rpc.close({"tx": "020000000001011490f737edd2ea2175a032b58ea7cd426dfc244c339cd044792096da3349b18a0100000000ffffffff021c900300000000001600140e64868e2f752314bc82a154c8c5bf32f3691bb74da00b00000000002200205b8cd3b914cf67cdd8fa6273c930353dd36476734fbd962102c2df53b90880cd0247304402202b2e3195a35dc694bbbc58942dc9ba59cc01d71ba55c9b0ad0610ccd6a65633702201a849254453d160205accc00843efb0ad1fe0e186efa6a7cee1fb6a1d36c736a012103d745445c9362665f22e0d96e9e766f273f3260dea39c8a76bfa05dd2684ddccf00000000", "txid": "2128c10f0355354479514f4a23eaa880d94e099406d419bbb0d800143accddbb", "channel_id": "bbddcc3a1400d8b0bb19d40694094ed980a8ea234a4f5179443555030fc12820"})
|
||||||
|
|
||||||
# Should not corrupt following RPC
|
# Should not corrupt following RPC
|
||||||
|
@ -1840,7 +1840,7 @@ def test_dev_demux(node_factory):
|
||||||
l1.rpc.check(command_to_check='dev', subcommand='foobar')
|
l1.rpc.check(command_to_check='dev', subcommand='foobar')
|
||||||
with pytest.raises(RpcError, match=r'unknown parameter'):
|
with pytest.raises(RpcError, match=r'unknown parameter'):
|
||||||
l1.rpc.check(command_to_check='dev', subcommand='crash', unk=1)
|
l1.rpc.check(command_to_check='dev', subcommand='crash', unk=1)
|
||||||
with pytest.raises(RpcError, match=r"'msec' should be an integer"):
|
with pytest.raises(RpcError, match=r"msec: should be an integer: invalid token"):
|
||||||
l1.rpc.check(command_to_check='dev', subcommand='slowcmd', msec='aaa')
|
l1.rpc.check(command_to_check='dev', subcommand='slowcmd', msec='aaa')
|
||||||
with pytest.raises(RpcError, match=r'missing required parameter'):
|
with pytest.raises(RpcError, match=r'missing required parameter'):
|
||||||
l1.rpc.check(command_to_check='dev', subcommand='rhash')
|
l1.rpc.check(command_to_check='dev', subcommand='rhash')
|
||||||
|
@ -1856,9 +1856,9 @@ def test_dev_demux(node_factory):
|
||||||
l1.rpc.call('dev', {'subcommand': 'crash', 'unk': 1})
|
l1.rpc.call('dev', {'subcommand': 'crash', 'unk': 1})
|
||||||
with pytest.raises(RpcError, match=r'too many parameters'):
|
with pytest.raises(RpcError, match=r'too many parameters'):
|
||||||
l1.rpc.call('dev', ['crash', 1])
|
l1.rpc.call('dev', ['crash', 1])
|
||||||
with pytest.raises(RpcError, match=r"'msec' should be an integer"):
|
with pytest.raises(RpcError, match=r"msec: should be an integer: invalid token"):
|
||||||
l1.rpc.call('dev', {'subcommand': 'slowcmd', 'msec': 'aaa'})
|
l1.rpc.call('dev', {'subcommand': 'slowcmd', 'msec': 'aaa'})
|
||||||
with pytest.raises(RpcError, match=r"'msec' should be an integer"):
|
with pytest.raises(RpcError, match=r"msec: should be an integer: invalid token"):
|
||||||
l1.rpc.call('dev', ['slowcmd', 'aaa'])
|
l1.rpc.call('dev', ['slowcmd', 'aaa'])
|
||||||
with pytest.raises(RpcError, match=r'missing required parameter'):
|
with pytest.raises(RpcError, match=r'missing required parameter'):
|
||||||
l1.rpc.call('dev', {'subcommand': 'rhash'})
|
l1.rpc.call('dev', {'subcommand': 'rhash'})
|
||||||
|
|
|
@ -1923,7 +1923,7 @@ def test_setchannelfee_usage(node_factory, bitcoind):
|
||||||
# check if invalid scid raises proper error
|
# check if invalid scid raises proper error
|
||||||
with pytest.raises(RpcError, match=r'-1.*Could not find active channel of peer with that id'):
|
with pytest.raises(RpcError, match=r'-1.*Could not find active channel of peer with that id'):
|
||||||
result = l1.rpc.setchannelfee(l3.info['id'], 42, 43)
|
result = l1.rpc.setchannelfee(l3.info['id'], 42, 43)
|
||||||
with pytest.raises(RpcError, match=r'-32602.*Given id is not a channel ID or short channel ID'):
|
with pytest.raises(RpcError, match=r'-32602.*id: should be a channel ID or short channel ID: invalid token'):
|
||||||
result = l1.rpc.setchannelfee('f42' + scid[3:], 42, 43)
|
result = l1.rpc.setchannelfee('f42' + scid[3:], 42, 43)
|
||||||
|
|
||||||
# check if 'base' unit can be modified to satoshi
|
# check if 'base' unit can be modified to satoshi
|
||||||
|
@ -1933,11 +1933,11 @@ def test_setchannelfee_usage(node_factory, bitcoind):
|
||||||
assert(db_fees[0]['feerate_base'] == 1000)
|
assert(db_fees[0]['feerate_base'] == 1000)
|
||||||
|
|
||||||
# check if 'ppm' values greater than u32_max fail
|
# check if 'ppm' values greater than u32_max fail
|
||||||
with pytest.raises(RpcError, match=r'-32602.*should be an integer, not'):
|
with pytest.raises(RpcError, match=r'-32602.*ppm: should be an integer: invalid token'):
|
||||||
l1.rpc.setchannelfee(scid, 0, 2**32)
|
l1.rpc.setchannelfee(scid, 0, 2**32)
|
||||||
|
|
||||||
# check if 'ppm' values greater than u32_max fail
|
# check if 'base' values greater than u32_max fail
|
||||||
with pytest.raises(RpcError, match=r'-32602.*exceeds u32 max'):
|
with pytest.raises(RpcError, match=r'-32602.*base: exceeds u32 max: invalid token'):
|
||||||
l1.rpc.setchannelfee(scid, 2**32)
|
l1.rpc.setchannelfee(scid, 2**32)
|
||||||
|
|
||||||
|
|
||||||
|
|
Loading…
Add table
Reference in a new issue