param: upgraded json_tok_number

Also renamed old version to json_to_number for use as a utility function.

Signed-off-by: Mark Beckwith <wythe@intrig.com>
This commit is contained in:
Mark Beckwith 2018-08-10 15:16:22 -05:00 committed by Rusty Russell
parent 80a875a9a5
commit 294dc06de9
14 changed files with 108 additions and 85 deletions

View File

@ -91,8 +91,8 @@ bool json_tok_percent(const char *buffer, const jsmntok_t *tok, double *num)
return true;
}
bool json_tok_number(const char *buffer, const jsmntok_t *tok,
unsigned int *num)
bool json_to_number(const char *buffer, const jsmntok_t *tok,
unsigned int *num)
{
uint64_t u64;

View File

@ -25,8 +25,8 @@ int json_tok_len(const jsmntok_t *t);
bool json_tok_streq(const char *buffer, const jsmntok_t *tok, const char *str);
/* Extract number from this (may be a string, or a number literal) */
bool json_tok_number(const char *buffer, const jsmntok_t *tok,
unsigned int *num);
bool json_to_number(const char *buffer, const jsmntok_t *tok,
unsigned int *num);
/* Extract number from this (may be a string, or a number literal) */
bool json_tok_u64(const char *buffer, const jsmntok_t *tok,

View File

@ -19,6 +19,7 @@
#include <inttypes.h>
#include <lightningd/channel_control.h>
#include <lightningd/gossip_control.h>
#include <lightningd/json.h>
#include <lightningd/param.h>
/* Mutual recursion via timer. */
@ -603,6 +604,7 @@ static void json_dev_setfees(struct command *cmd,
{
struct chain_topology *topo = cmd->ld->topology;
struct json_result *response;
u32 *imm, *norm, *slow;
if (!topo->dev_override_fee_rate) {
u32 fees[NUM_FEERATES];
@ -613,18 +615,19 @@ static void json_dev_setfees(struct command *cmd,
}
if (!param(cmd, buffer, params,
p_opt_def("immediate", json_tok_number,
&topo->dev_override_fee_rate[FEERATE_IMMEDIATE],
topo->dev_override_fee_rate[FEERATE_IMMEDIATE]),
p_opt_def("normal", json_tok_number,
&topo->dev_override_fee_rate[FEERATE_NORMAL],
topo->dev_override_fee_rate[FEERATE_NORMAL]),
p_opt_def("slow", json_tok_number,
&topo->dev_override_fee_rate[FEERATE_SLOW],
topo->dev_override_fee_rate[FEERATE_SLOW]),
p_opt_tal("immediate", json_tok_number, &imm),
p_opt_tal("normal", json_tok_number, &norm),
p_opt_tal("slow", json_tok_number, &slow),
NULL))
return;
if (imm)
topo->dev_override_fee_rate[FEERATE_IMMEDIATE] = *imm;
if (norm)
topo->dev_override_fee_rate[FEERATE_NORMAL] = *norm;
if (slow)
topo->dev_override_fee_rate[FEERATE_SLOW] = *slow;
log_debug(topo->log,
"dev-setfees: fees now %u/%u/%u",
topo->dev_override_fee_rate[FEERATE_IMMEDIATE],

View File

@ -74,7 +74,8 @@ static void connect_cmd_succeed(struct command *cmd, const struct pubkey *id)
static void json_connect(struct command *cmd,
const char *buffer, const jsmntok_t *params)
{
const jsmntok_t *hosttok, *porttok;
const jsmntok_t *hosttok;
u32 *port;
jsmntok_t *idtok;
struct pubkey id;
char *id_str;
@ -89,7 +90,7 @@ static void json_connect(struct command *cmd,
if (!param(cmd, buffer, params,
p_req_tal("id", json_tok_tok, (const jsmntok_t **) &idtok),
p_opt_tal("host", json_tok_tok, &hosttok),
p_opt_tal("port", json_tok_tok, &porttok),
p_opt_tal("port", json_tok_number, &port),
NULL))
return;
@ -129,7 +130,7 @@ static void json_connect(struct command *cmd,
name = NULL;
/* Port without host name? */
if (porttok && !name) {
if (port && !name) {
command_fail(cmd, JSONRPC2_INVALID_PARAMS,
"Can't specify port without host");
return;
@ -149,27 +150,19 @@ static void json_connect(struct command *cmd,
/* Was there parseable host name? */
if (name) {
u32 port;
/* Is there a port? */
if (porttok) {
if (!json_tok_number(buffer, porttok, &port) || !port) {
command_fail(cmd, JSONRPC2_INVALID_PARAMS,
"Port %.*s not valid",
porttok->end - porttok->start,
buffer + porttok->start);
return;
}
} else {
port = DEFAULT_PORT;
if (!port) {
port = tal(cmd, u32);
*port = DEFAULT_PORT;
}
addr = tal(cmd, struct wireaddr_internal);
if (!parse_wireaddr_internal(name, addr, port, false,
if (!parse_wireaddr_internal(name, addr, *port, false,
!cmd->ld->use_proxy_always
&& !cmd->ld->pure_tor_setup,
true,
&err_msg)) {
command_fail(cmd, LIGHTNINGD, "Host %s:%u not valid: %s",
name, port, err_msg ? err_msg : "port is 0");
name, *port, err_msg ? err_msg : "port is 0");
return;
}
} else

View File

@ -276,7 +276,7 @@ static void json_getroute(struct command *cmd, const char *buffer, const jsmntok
struct pubkey source;
const jsmntok_t *seedtok;
u64 msatoshi;
unsigned cltv;
unsigned *cltv;
double riskfactor;
/* Higher fuzz means that some high-fee paths can be discounted
* for an even larger value, increasing the scope for route
@ -290,7 +290,7 @@ static void json_getroute(struct command *cmd, const char *buffer, const jsmntok
p_req("id", json_tok_pubkey, &destination),
p_req("msatoshi", json_tok_u64, &msatoshi),
p_req("riskfactor", json_tok_double, &riskfactor),
p_opt_def("cltv", json_tok_number, &cltv, 9),
p_opt_def_tal("cltv", json_tok_number, &cltv, 9),
p_opt_def("fromid", json_tok_pubkey, &source, ld->id),
p_opt_def("fuzzpercent", json_tok_double, &fuzz, 75.0),
p_opt_tal("seed", json_tok_tok, &seedtok),
@ -317,7 +317,7 @@ static void json_getroute(struct command *cmd, const char *buffer, const jsmntok
} else
randombytes_buf(&seed, sizeof(seed));
u8 *req = towire_gossip_getroute_request(cmd, &source, &destination, msatoshi, riskfactor*1000, cltv, &fuzz, &seed);
u8 *req = towire_gossip_getroute_request(cmd, &source, &destination, msatoshi, riskfactor*1000, *cltv, &fuzz, &seed);
subd_req(ld->gossip, ld->gossip, req, -1, 0, json_getroute_reply, cmd);
command_still_pending(cmd);
}
@ -479,18 +479,18 @@ static void json_dev_send_timestamp_filter(struct command *cmd,
{
u8 *msg;
struct pubkey id;
u32 first, range;
u32 *first, *range;
if (!param(cmd, buffer, params,
p_req("id", json_tok_pubkey, &id),
p_req("first", json_tok_number, &first),
p_req("range", json_tok_number, &range),
p_req_tal("first", json_tok_number, &first),
p_req_tal("range", json_tok_number, &range),
NULL))
return;
log_debug(cmd->ld->log, "Setting timestamp range %u+%u", first, range);
log_debug(cmd->ld->log, "Setting timestamp range %u+%u", *first, *range);
/* Tell gossipd, since this is a gossip query. */
msg = towire_gossip_send_timestamp_filter(NULL, &id, first, range);
msg = towire_gossip_send_timestamp_filter(NULL, &id, *first, *range);
subd_send_msg(cmd->ld->gossip, take(msg));
command_success(cmd, null_response(cmd));
@ -547,17 +547,17 @@ static void json_dev_query_channel_range(struct command *cmd,
{
u8 *msg;
struct pubkey id;
u32 first, num;
u32 *first, *num;
if (!param(cmd, buffer, params,
p_req("id", json_tok_pubkey, &id),
p_req("first", json_tok_number, &first),
p_req("num", json_tok_number, &num),
p_req_tal("first", json_tok_number, &first),
p_req_tal("num", json_tok_number, &num),
NULL))
return;
/* Tell gossipd, since this is a gossip query. */
msg = towire_gossip_query_channel_range(cmd, &id, first, num);
msg = towire_gossip_query_channel_range(cmd, &id, *first, *num);
subd_req(cmd->ld->gossip, cmd->ld->gossip,
take(msg), -1, 0, json_channel_range_reply, cmd);
command_still_pending(cmd);
@ -575,14 +575,14 @@ static void json_dev_set_max_scids_encode_size(struct command *cmd,
const jsmntok_t *params)
{
u8 *msg;
u32 max;
u32 *max;
if (!param(cmd, buffer, params,
p_req("max", json_tok_number, &max),
p_req_tal("max", json_tok_number, &max),
NULL))
return;
msg = towire_gossip_dev_set_max_scids_encode_size(NULL, max);
msg = towire_gossip_dev_set_max_scids_encode_size(NULL, *max);
subd_send_msg(cmd->ld->gossip, take(msg));
command_success(cmd, null_response(cmd));

View File

@ -6,6 +6,8 @@
#include <common/type_to_string.h>
#include <common/wireaddr.h>
#include <gossipd/routing.h>
#include <lightningd/jsonrpc.h>
#include <lightningd/jsonrpc_errors.h>
#include <lightningd/options.h>
#include <sys/socket.h>
#include <wallet/wallet.h>
@ -89,6 +91,20 @@ void json_add_txid(struct json_result *result, const char *fieldname,
json_add_string(result, fieldname, hex);
}
bool json_tok_number(struct command *cmd, const char *name,
const char *buffer, const jsmntok_t *tok,
unsigned int **num)
{
*num = tal(cmd, unsigned int);
if (!json_to_number(buffer, tok, *num)) {
command_fail(cmd, JSONRPC2_INVALID_PARAMS,
"'%s' should be an integer, not '%.*s'",
name, tok->end - tok->start, buffer + tok->start);
return false;
}
return true;
}
bool json_tok_pubkey(const char *buffer, const jsmntok_t *tok,
struct pubkey *pubkey)
{

View File

@ -40,6 +40,11 @@ void json_add_pubkey(struct json_result *response,
void json_add_txid(struct json_result *result, const char *fieldname,
const struct bitcoin_txid *txid);
/* Extract number from this (may be a string, or a number literal) */
bool json_tok_number(struct command *cmd, const char *name,
const char *buffer, const jsmntok_t *tok,
unsigned int **num);
/* Extract a pubkey from this */
bool json_tok_pubkey(const char *buffer, const jsmntok_t *tok,
struct pubkey *pubkey);

View File

@ -56,7 +56,6 @@ static struct fail_format fail_formats[] = {
"'%s' should be a double in range [0.0, 100.0], not '%.*s'"},
{json_tok_u64, "'%s' should be an unsigned 64 bit integer, not '%.*s'"},
{json_tok_newaddr, "'%s' should be 'bech32' or 'p2sh-segwit', not '%.*s'"},
{json_tok_number, "'%s' should be an integer, not '%.*s'"},
{json_tok_wtx,
"'%s' should be 'all' or a positive integer greater than "
"545, not '%.*s'"},

View File

@ -1017,7 +1017,7 @@ static void json_sendpay(struct command *cmd,
"Route %zu invalid id", n_hops);
return;
}
if (!json_tok_number(buffer, delaytok, &route[n_hops].delay)) {
if (!json_to_number(buffer, delaytok, &route[n_hops].delay)) {
command_fail(cmd, JSONRPC2_INVALID_PARAMS,
"Route %zu invalid delay", n_hops);
return;
@ -1094,7 +1094,7 @@ static void json_waitsendpay(struct command *cmd, const char *buffer,
if (!param(cmd, buffer, params,
p_req("payment_hash", json_tok_sha256, &rhash),
p_opt("timeout", json_tok_number, &timeout),
p_opt_tal("timeout", json_tok_number, &timeout),
NULL))
return;

View File

@ -606,9 +606,9 @@ static void json_pay(struct command *cmd,
struct pay *pay = tal(cmd, struct pay);
struct bolt11 *b11;
char *fail, *b11str, *desc;
unsigned int retryfor;
unsigned int maxdelay;
unsigned int exemptfee;
unsigned int *retryfor;
unsigned int *maxdelay;
unsigned int *exemptfee;
if (!param(cmd, buffer, params,
p_req_tal("bolt11", json_tok_tok, &bolt11tok),
@ -616,10 +616,10 @@ static void json_pay(struct command *cmd,
p_opt_tal("description", json_tok_tok, &desctok),
p_opt_def("riskfactor", json_tok_double, &riskfactor, 1.0),
p_opt_def("maxfeepercent", json_tok_percent, &maxfeepercent, 0.5),
p_opt_def("retry_for", json_tok_number, &retryfor, 60),
p_opt_def("maxdelay", json_tok_number, &maxdelay,
p_opt_def_tal("retry_for", json_tok_number, &retryfor, 60),
p_opt_def_tal("maxdelay", json_tok_number, &maxdelay,
cmd->ld->config.locktime_max),
p_opt_def("exemptfee", json_tok_number, &exemptfee, 5000),
p_opt_def_tal("exemptfee", json_tok_number, &exemptfee, 5000),
NULL))
return;
@ -644,7 +644,7 @@ static void json_pay(struct command *cmd,
memset(&pay->expiry, 0, sizeof(pay->expiry));
pay->expiry.ts.tv_sec = b11->timestamp + b11->expiry;
pay->min_final_cltv_expiry = b11->min_final_cltv_expiry;
pay->exemptfee = exemptfee;
pay->exemptfee = *exemptfee;
if (b11->msatoshi) {
if (msatoshi) {
@ -664,15 +664,15 @@ static void json_pay(struct command *cmd,
pay->riskfactor = riskfactor * 1000;
pay->maxfeepercent = maxfeepercent;
if (maxdelay < pay->min_final_cltv_expiry) {
if (*maxdelay < pay->min_final_cltv_expiry) {
command_fail(cmd, JSONRPC2_INVALID_PARAMS,
"maxdelay (%u) must be greater than "
"min_final_cltv_expiry (%"PRIu32") of "
"invoice",
maxdelay, pay->min_final_cltv_expiry);
*maxdelay, pay->min_final_cltv_expiry);
return;
}
pay->maxdelay = maxdelay;
pay->maxdelay = *maxdelay;
pay->getroute_tries = 0;
pay->sendpay_tries = 0;
@ -701,7 +701,7 @@ static void json_pay(struct command *cmd,
return;
/* Set up timeout. */
new_reltimer(&cmd->ld->timers, pay, time_from_sec(retryfor),
new_reltimer(&cmd->ld->timers, pay, time_from_sec(*retryfor),
&json_pay_stop_retrying, pay);
}

View File

@ -832,13 +832,13 @@ static void json_close(struct command *cmd,
const jsmntok_t *idtok;
struct peer *peer;
struct channel *channel;
unsigned int timeout;
unsigned int *timeout;
bool force;
if (!param(cmd, buffer, params,
p_req_tal("id", json_tok_tok, &idtok),
p_opt_def("force", json_tok_bool, &force, false),
p_opt_def("timeout", json_tok_number, &timeout, 30),
p_opt_def_tal("timeout", json_tok_number, &timeout, 30),
NULL))
return;
@ -891,7 +891,7 @@ static void json_close(struct command *cmd,
}
/* Register this command for later handling. */
register_close_command(cmd->ld, cmd, channel, timeout, force);
register_close_command(cmd->ld, cmd, channel, *timeout, force);
/* Wait until close drops down to chain. */
command_still_pending(cmd);

View File

@ -39,13 +39,13 @@ static void json_ping(struct command *cmd,
const char *buffer, const jsmntok_t *params)
{
u8 *msg;
unsigned int len, pongbytes;
unsigned int *len, *pongbytes;
struct pubkey id;
if (!param(cmd, buffer, params,
p_req("id", json_tok_pubkey, &id),
p_opt_def("len", json_tok_number, &len, 128),
p_opt_def("pongbytes", json_tok_number, &pongbytes, 128),
p_opt_def_tal("len", json_tok_number, &len, 128),
p_opt_def_tal("pongbytes", json_tok_number, &pongbytes, 128),
NULL))
return;
@ -63,21 +63,21 @@ static void json_ping(struct command *cmd,
* * [`2`:`byteslen`]
* * [`byteslen`:`ignored`]
*/
if (len > 65535 - 2 - 2 - 2) {
if (*len > 65535 - 2 - 2 - 2) {
command_fail(cmd, JSONRPC2_INVALID_PARAMS,
"%u would result in oversize ping", len);
"%u would result in oversize ping", *len);
return;
}
/* Note that > 65531 is valid: it means "no pong reply" */
if (pongbytes > 65535) {
if (*pongbytes > 65535) {
command_fail(cmd, JSONRPC2_INVALID_PARAMS,
"pongbytes %u > 65535", pongbytes);
"pongbytes %u > 65535", *pongbytes);
return;
}
/* gossipd handles all pinging, even if it's in another daemon. */
msg = towire_gossip_ping(NULL, &id, pongbytes, len);
msg = towire_gossip_ping(NULL, &id, *pongbytes, *len);
subd_req(cmd->ld->gossip, cmd->ld->gossip,
take(msg), -1, 0, ping_reply, cmd);
command_still_pending(cmd);

View File

@ -3,6 +3,7 @@
#include <setjmp.h>
#include <lightningd/jsonrpc.h>
#include <lightningd/json.c>
#include <lightningd/param.c>
#include <lightningd/json.c>
#include <common/json.c>
@ -175,7 +176,7 @@ static void tok_tok(void)
assert(param(cmd, j->buffer, j->toks,
p_req_tal("satoshi", json_tok_tok, &tok), NULL));
assert(tok);
assert(json_tok_number(j->buffer, tok, &n));
assert(json_to_number(j->buffer, tok, &n));
assert(n == 546);
}
// again with missing optional parameter
@ -298,13 +299,15 @@ static void bad_programmer(void)
/* Add required param after optional */
j = json_parse(cmd, "[ '25', '546', '26', '1.1' ]");
unsigned int msatoshi;
unsigned int *msatoshi;
double riskfactor;
assert(!param(cmd, j->buffer, j->toks,
p_req("u64", json_tok_u64, &ival),
p_req("double", json_tok_double, &dval),
p_opt_def("msatoshi", json_tok_number, &msatoshi, 100),
p_opt_def_tal("msatoshi", json_tok_number, &msatoshi, 100),
p_req("riskfactor", json_tok_double, &riskfactor), NULL));
assert(*msatoshi);
assert(*msatoshi == 100);
assert(check_fail());
assert(strstr(fail_msg, "developer error"));
}
@ -312,19 +315,21 @@ static void bad_programmer(void)
static void add_members(struct param **params,
struct json_result *obj,
struct json_result *arr, unsigned int *ints)
struct json_result *arr, unsigned int **ints)
{
for (int i = 0; i < tal_count(ints); ++i) {
char *name = tal_fmt(tmpctx, "%i", i);
json_add_num(obj, name, i);
json_add_num(arr, NULL, i);
param_add(params, name, true,
typesafe_cb_preargs(bool, void *,
NULL,
typesafe_cb_preargs(bool, void **,
json_tok_number,
&ints[i],
struct command *,
const char *,
const char *,
const jsmntok_t *),
NULL,
&ints[i], 0);
}
}
@ -337,7 +342,7 @@ static void five_hundred_params(void)
{
struct param *params = tal_arr(NULL, struct param, 0);
unsigned int *ints = tal_arr(params, unsigned int, 500);
unsigned int **ints = tal_arr(params, unsigned int*, 500);
struct json_result *obj = new_json_result(params);
struct json_result *arr = new_json_result(params);
json_object_start(obj, NULL);
@ -350,15 +355,16 @@ static void five_hundred_params(void)
struct json *j = json_parse(params, obj->s);
assert(param_arr(cmd, j->buffer, j->toks, params));
for (int i = 0; i < tal_count(ints); ++i) {
assert(ints[i] == i);
ints[i] = 65535;
assert(ints[i]);
assert(*ints[i] == i);
*ints[i] = 65535;
}
/* now test array */
j = json_parse(params, arr->s);
assert(param_arr(cmd, j->buffer, j->toks, params));
for (int i = 0; i < tal_count(ints); ++i) {
assert(ints[i] == i);
assert(*ints[i] == i);
}
tal_free(params);
@ -370,11 +376,11 @@ static void sendpay(void)
const jsmntok_t *routetok, *note;
u64 *msatoshi;
unsigned cltv;
unsigned *cltv;
if (!param(cmd, j->buffer, j->toks,
p_req_tal("route", json_tok_tok, &routetok),
p_req("cltv", json_tok_number, &cltv),
p_req_tal("cltv", json_tok_number, &cltv),
p_opt_tal("note", json_tok_tok, &note),
p_opt("msatoshi", json_tok_u64, &msatoshi),
NULL))
@ -393,11 +399,11 @@ static void sendpay_nulltok(void)
const jsmntok_t *routetok, *note = (void *) 65535;
u64 *msatoshi;
unsigned cltv;
unsigned *cltv;
if (!param(cmd, j->buffer, j->toks,
p_req_tal("route", json_tok_tok, &routetok),
p_req("cltv", json_tok_number, &cltv),
p_req_tal("cltv", json_tok_number, &cltv),
p_opt_tal("note", json_tok_tok, &note),
p_opt("msatoshi", json_tok_u64, &msatoshi),
NULL))

View File

@ -229,8 +229,9 @@ bool json_tok_loglevel(const char *buffer UNNEEDED, const jsmntok_t *tok UNNEEDE
enum log_level *level UNNEEDED)
{ fprintf(stderr, "json_tok_loglevel called!\n"); abort(); }
/* Generated stub for json_tok_number */
bool json_tok_number(const char *buffer UNNEEDED, const jsmntok_t *tok UNNEEDED,
unsigned int *num UNNEEDED)
bool json_tok_number(struct command *cmd UNNEEDED, const char *name UNNEEDED,
const char *buffer UNNEEDED, const jsmntok_t *tok UNNEEDED,
unsigned int **num UNNEEDED)
{ fprintf(stderr, "json_tok_number called!\n"); abort(); }
/* Generated stub for json_tok_pubkey */
bool json_tok_pubkey(const char *buffer UNNEEDED, const jsmntok_t *tok UNNEEDED,