diff --git a/common/json.c b/common/json.c index e4a4e00eb..48fee838d 100644 --- a/common/json.c +++ b/common/json.c @@ -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; diff --git a/common/json.h b/common/json.h index b2cfdb6e3..2f003e70a 100644 --- a/common/json.h +++ b/common/json.h @@ -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, diff --git a/lightningd/chaintopology.c b/lightningd/chaintopology.c index 1907c596d..506c2bf1a 100644 --- a/lightningd/chaintopology.c +++ b/lightningd/chaintopology.c @@ -19,6 +19,7 @@ #include #include #include +#include #include /* 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], diff --git a/lightningd/connect_control.c b/lightningd/connect_control.c index 3eff7c6ac..b31e06464 100644 --- a/lightningd/connect_control.c +++ b/lightningd/connect_control.c @@ -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 diff --git a/lightningd/gossip_control.c b/lightningd/gossip_control.c index 27ce11563..9e8d5db79 100644 --- a/lightningd/gossip_control.c +++ b/lightningd/gossip_control.c @@ -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)); diff --git a/lightningd/json.c b/lightningd/json.c index ec5fb7509..909faefaf 100644 --- a/lightningd/json.c +++ b/lightningd/json.c @@ -6,6 +6,8 @@ #include #include #include +#include +#include #include #include #include @@ -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) { diff --git a/lightningd/json.h b/lightningd/json.h index 2e85a3915..fa5cca01c 100644 --- a/lightningd/json.h +++ b/lightningd/json.h @@ -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); diff --git a/lightningd/param.c b/lightningd/param.c index 2924edddb..6c2efb401 100644 --- a/lightningd/param.c +++ b/lightningd/param.c @@ -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'"}, diff --git a/lightningd/pay.c b/lightningd/pay.c index c493b560f..ec4f1e875 100644 --- a/lightningd/pay.c +++ b/lightningd/pay.c @@ -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; diff --git a/lightningd/payalgo.c b/lightningd/payalgo.c index bc4b2755f..7ad578cb7 100644 --- a/lightningd/payalgo.c +++ b/lightningd/payalgo.c @@ -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); } diff --git a/lightningd/peer_control.c b/lightningd/peer_control.c index afe15a65a..3dda6d258 100644 --- a/lightningd/peer_control.c +++ b/lightningd/peer_control.c @@ -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); diff --git a/lightningd/ping.c b/lightningd/ping.c index ae216644c..b973e0deb 100644 --- a/lightningd/ping.c +++ b/lightningd/ping.c @@ -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); diff --git a/lightningd/test/run-param.c b/lightningd/test/run-param.c index 8028e1011..f57b096ad 100644 --- a/lightningd/test/run-param.c +++ b/lightningd/test/run-param.c @@ -3,6 +3,7 @@ #include #include +#include #include #include #include @@ -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, ¬e), 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, ¬e), p_opt("msatoshi", json_tok_u64, &msatoshi), NULL)) diff --git a/wallet/test/run-wallet.c b/wallet/test/run-wallet.c index 7380d8e5b..c04f91c91 100644 --- a/wallet/test/run-wallet.c +++ b/wallet/test/run-wallet.c @@ -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,