common: clean up json routine locations.

We have them split over common/param.c, common/json.c,
common/json_helpers.c, common/json_tok.c and common/json_stream.c.

Change that to:
* common/json_parse (all the json_to_xxx routines)
* common/json_parse_simple (simplest the json parsing routines, for cli too)
* common/json_stream (all the json_add_xxx routines)
* common/json_param (all the param and param_xxx routines)

Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
This commit is contained in:
Rusty Russell
2022-07-04 13:19:38 +09:30
committed by neil saitug
parent f12f0d6929
commit 401f1debc5
103 changed files with 3113 additions and 3139 deletions

View File

@@ -8,8 +8,7 @@ ALL_PROGRAMS += cli/lightning-cli
LIGHTNING_CLI_COMMON_OBJS := \
bitcoin/chainparams.o \
common/configdir.o \
common/json.o \
common/json_stream.o \
common/json_parse_simple.o \
common/status_levels.o \
common/utils.o \
common/version.o

View File

@@ -12,7 +12,7 @@ CLI_TEST_COMMON_OBJS := \
common/configdir.o \
common/daemon_conn.o \
common/htlc_state.o \
common/json.o \
common/json_parse_simple.o \
common/pseudorand.o \
common/memleak.o \
common/msg_queue.o \

View File

@@ -78,16 +78,6 @@ bool fromwire_channel_id(const u8 **cursor UNNEEDED, size_t *max UNNEEDED,
/* Generated stub for fromwire_node_id */
void fromwire_node_id(const u8 **cursor UNNEEDED, size_t *max UNNEEDED, struct node_id *id UNNEEDED)
{ fprintf(stderr, "fromwire_node_id called!\n"); abort(); }
/* Generated stub for json_add_member */
void json_add_member(struct json_stream *js UNNEEDED,
const char *fieldname UNNEEDED,
bool quote UNNEEDED,
const char *fmt UNNEEDED, ...)
{ fprintf(stderr, "json_add_member called!\n"); abort(); }
/* Generated stub for json_member_direct */
char *json_member_direct(struct json_stream *js UNNEEDED,
const char *fieldname UNNEEDED, size_t extra UNNEEDED)
{ fprintf(stderr, "json_member_direct called!\n"); abort(); }
/* Generated stub for log_level_name */
const char *log_level_name(enum log_level level UNNEEDED)
{ fprintf(stderr, "log_level_name called!\n"); abort(); }

View File

@@ -78,16 +78,6 @@ bool fromwire_channel_id(const u8 **cursor UNNEEDED, size_t *max UNNEEDED,
/* Generated stub for fromwire_node_id */
void fromwire_node_id(const u8 **cursor UNNEEDED, size_t *max UNNEEDED, struct node_id *id UNNEEDED)
{ fprintf(stderr, "fromwire_node_id called!\n"); abort(); }
/* Generated stub for json_add_member */
void json_add_member(struct json_stream *js UNNEEDED,
const char *fieldname UNNEEDED,
bool quote UNNEEDED,
const char *fmt UNNEEDED, ...)
{ fprintf(stderr, "json_add_member called!\n"); abort(); }
/* Generated stub for json_member_direct */
char *json_member_direct(struct json_stream *js UNNEEDED,
const char *fieldname UNNEEDED, size_t extra UNNEEDED)
{ fprintf(stderr, "json_member_direct called!\n"); abort(); }
/* Generated stub for log_level_name */
const char *log_level_name(enum log_level level UNNEEDED)
{ fprintf(stderr, "log_level_name called!\n"); abort(); }

View File

@@ -81,16 +81,6 @@ bool fromwire_channel_id(const u8 **cursor UNNEEDED, size_t *max UNNEEDED,
/* Generated stub for fromwire_node_id */
void fromwire_node_id(const u8 **cursor UNNEEDED, size_t *max UNNEEDED, struct node_id *id UNNEEDED)
{ fprintf(stderr, "fromwire_node_id called!\n"); abort(); }
/* Generated stub for json_add_member */
void json_add_member(struct json_stream *js UNNEEDED,
const char *fieldname UNNEEDED,
bool quote UNNEEDED,
const char *fmt UNNEEDED, ...)
{ fprintf(stderr, "json_add_member called!\n"); abort(); }
/* Generated stub for json_member_direct */
char *json_member_direct(struct json_stream *js UNNEEDED,
const char *fieldname UNNEEDED, size_t extra UNNEEDED)
{ fprintf(stderr, "json_member_direct called!\n"); abort(); }
/* Generated stub for log_level_name */
const char *log_level_name(enum log_level level UNNEEDED)
{ fprintf(stderr, "log_level_name called!\n"); abort(); }

View File

@@ -46,10 +46,10 @@ COMMON_SRC_NOGEN := \
common/initial_channel.c \
common/initial_commit_tx.c \
common/iso4217.c \
common/json.c \
common/json_helpers.c \
common/json_param.c \
common/json_parse.c \
common/json_parse_simple.c \
common/json_stream.c \
common/json_tok.c \
common/key_derive.c \
common/keyset.c \
common/lease_rates.c \
@@ -58,7 +58,6 @@ COMMON_SRC_NOGEN := \
common/node_id.c \
common/onion.c \
common/onionreply.c \
common/param.c \
common/peer_billboard.c \
common/peer_failed.c \
common/peer_io.c \

View File

@@ -6,7 +6,6 @@
#include <common/bech32.h>
#include <common/bolt11.h>
#include <common/bolt11_json.h>
#include <common/json_helpers.h>
#include <common/json_stream.h>
static void json_add_fallback(struct json_stream *response,

File diff suppressed because it is too large Load Diff

View File

@@ -1,259 +0,0 @@
#ifndef LIGHTNING_COMMON_JSON_H
#define LIGHTNING_COMMON_JSON_H
#include "config.h"
#include <ccan/crypto/sha256/sha256.h>
#include <ccan/tal/tal.h>
#include <common/errcode.h>
#define JSMN_STRICT 1
# include <external/jsmn/jsmn.h>
struct json_escape;
struct json_stream;
struct timeabs;
struct timespec;
/* Include " if it's a string. */
const char *json_tok_full(const char *buffer, const jsmntok_t *t);
/* Include " if it's a string. */
int json_tok_full_len(const jsmntok_t *t);
/* Is this a string equal to str? */
bool json_tok_streq(const char *buffer, const jsmntok_t *tok, const char *str);
/* Is this a string equal to str of length len? */
bool json_tok_strneq(const char *buffer, const jsmntok_t *tok,
const char *str, size_t len);
/* Does this string token start with prefix? */
bool json_tok_startswith(const char *buffer, const jsmntok_t *tok,
const char *prefix);
/* Does this string token end with suffix? */
bool json_tok_endswith(const char *buffer, const jsmntok_t *tok,
const char *suffix);
/* Allocate a tal string copy */
char *json_strdup(const tal_t *ctx, const char *buffer, const jsmntok_t *tok);
/* Decode a hex-encoded binary */
u8 *json_tok_bin_from_hex(const tal_t *ctx, const char *buffer, const jsmntok_t *tok);
/* Extract number from this (may be a string, or a number literal) */
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_to_u64(const char *buffer, const jsmntok_t *tok,
uint64_t *num);
/* Extract signed 64 bit integer from this (may be a string, or a number literal) */
bool json_to_s64(const char *buffer, const jsmntok_t *tok, s64 *num);
/* Extract number from this (may be a string, or a number literal) */
bool json_to_u32(const char *buffer, const jsmntok_t *tok,
uint32_t *num);
/* Extract number from this (may be a string, or a number literal) */
bool json_to_u16(const char *buffer, const jsmntok_t *tok,
uint16_t *num);
bool json_to_sha256(const char *buffer, const jsmntok_t *tok, struct sha256 *dest);
/*
* Extract a non-negative (either 0 or positive) floating-point number from this
* (must be a number literal), multiply it by 1 million and return it as an
* integer. Any fraction smaller than 0.000001 is ignored.
*/
bool json_to_millionths(const char *buffer, const jsmntok_t *tok,
u64 *millionths);
/* Extract signed integer from this (may be a string, or a number literal) */
bool json_to_int(const char *buffer, const jsmntok_t *tok, int *num);
/* Extract an error code from this (may be a string, or a number literal) */
bool json_to_errcode(const char *buffer, const jsmntok_t *tok, errcode_t *errcode);
/* Extract boolean from this */
bool json_to_bool(const char *buffer, const jsmntok_t *tok, bool *b);
/* Is this a number? [0..9]+ */
bool json_tok_is_num(const char *buffer, const jsmntok_t *tok);
/* Is this the null primitive? */
bool json_tok_is_null(const char *buffer, const jsmntok_t *tok);
/* Returns next token with same parent (WARNING: slow!). */
const jsmntok_t *json_next(const jsmntok_t *tok);
/* Get top-level member. */
const jsmntok_t *json_get_member(const char *buffer, const jsmntok_t tok[],
const char *label);
/* Get index'th array member. */
const jsmntok_t *json_get_arr(const jsmntok_t tok[], size_t index);
/* Allocate a starter array of tokens for json_parse_input */
jsmntok_t *toks_alloc(const tal_t *ctx);
/* Reset a token array to reuse it. */
void toks_reset(jsmntok_t *toks);
/**
* json_parse_input: parse and validate JSON.
* @parser: parser initialized with jsmn_init.
* @toks: tallocated array from toks_alloc()
* @input, @len: input string.
* @complete: set to true if the valid JSON is complete, or NULL if must be.
*
* This returns false if the JSON is invalid, true otherwise.
* If it returns true, *@complete indicates that (*@toks)[0] points to a
* valid, complete JSON element. If @complete is NULL, then incomplete
* JSON returns false (i.e. is considered invalid).
*
* *@toks is resized to the complete set of tokens, with a dummy
* terminator (type == -1) at the end.
*
* If it returns true, and *@complete is false, you can append more
* data to @input and call it again (with the same perser) and the parser
* will continue where it left off.
*/
bool json_parse_input(jsmn_parser *parser,
jsmntok_t **toks,
const char *input, int len,
bool *complete);
/* Simplified version of above which parses only a complete, valid
* JSON string */
jsmntok_t *json_parse_simple(const tal_t *ctx, const char *input, int len);
/* Convert a jsmntype_t enum to a human readable string. */
const char *jsmntype_to_string(jsmntype_t t);
/* Return a copy of a json value as an array. */
jsmntok_t *json_tok_copy(const tal_t *ctx, const jsmntok_t *tok);
/*
* Remove @num json values from a json array or object @obj. @tok points
* to the first value to remove. The array @tokens will be resized.
*/
void json_tok_remove(jsmntok_t **tokens,
jsmntok_t *obj_or_array, const jsmntok_t *tok, size_t num);
/* Guide is % for a token: each must be followed by JSON_SCAN().
* Returns NULL on error (asserts() on bad guide). */
const char *json_scan(const tal_t *ctx,
const char *buffer,
const jsmntok_t *tok,
const char *guide,
...);
/* eg. JSON_SCAN(json_to_bool, &boolvar) */
#define JSON_SCAN(fmt, var) \
json_scan, \
stringify(fmt), \
((var) + 0*sizeof(fmt((const char *)NULL, \
(const jsmntok_t *)NULL, var) == true)), \
(fmt)
/* eg. JSON_SCAN_TAL(tmpctx, json_strdup, &charvar) */
#define JSON_SCAN_TAL(ctx, fmt, var) \
(ctx), \
stringify(fmt), \
((var) + 0*sizeof((*var) = fmt((ctx), \
(const char *)NULL, \
(const jsmntok_t *)NULL))), \
(fmt)
/* Already-have-varargs version */
const char *json_scanv(const tal_t *ctx,
const char *buffer,
const jsmntok_t *tok,
const char *guide,
va_list ap);
/* Iterator macro for array: i is counter, t is token ptr, arr is JSMN_ARRAY */
#define json_for_each_arr(i, t, arr) \
for (i = 0, t = (arr) + 1; i < (arr)->size; t = json_next(t), i++)
/* Iterator macro for object: i is counter, t is token ptr (t+1 is
* contents of obj member), obj is JSMN_OBJECT */
#define json_for_each_obj(i, t, obj) \
for (i = 0, t = (obj) + 1; i < (obj)->size; t = json_next(t+1), i++)
/* '"fieldname" : "value"' or '"value"' if fieldname is NULL. Turns
* any non-printable chars into JSON escapes, but leaves existing escapes alone.
*/
void json_add_string(struct json_stream *result, const char *fieldname, const char *value TAKES);
/* '"fieldname" : "value[:value_len]"' or '"value[:value_len]"' if
* fieldname is NULL. Turns any non-printable chars into JSON
* escapes, but leaves existing escapes alone.
*/
void json_add_stringn(struct json_stream *result, const char *fieldname,
const char *value TAKES, size_t value_len);
/* '"fieldname" : "value"' or '"value"' if fieldname is NULL. String must
* already be JSON escaped as necessary. */
void json_add_escaped_string(struct json_stream *result,
const char *fieldname,
const struct json_escape *esc TAKES);
/* '"fieldname" : literal' or 'literal' if fieldname is NULL*/
void json_add_literal(struct json_stream *result, const char *fieldname,
const char *literal, int len);
/* '"fieldname" : value' or 'value' if fieldname is NULL */
void json_add_num(struct json_stream *result, const char *fieldname,
unsigned int value);
/* '"fieldname" : value' or 'value' if fieldname is NULL */
void json_add_u64(struct json_stream *result, const char *fieldname,
uint64_t value);
/* '"fieldname" : value' or 'value' if fieldname is NULL */
void json_add_s64(struct json_stream *result, const char *fieldname,
int64_t value);
/* '"fieldname" : value' or 'value' if fieldname is NULL */
void json_add_u32(struct json_stream *result, const char *fieldname,
uint32_t value);
/* '"fieldname" : value' or 'value' if fieldname is NULL */
void json_add_s32(struct json_stream *result, const char *fieldname,
int32_t value);
/* '"fieldname" : true|false' or 'true|false' if fieldname is NULL */
void json_add_bool(struct json_stream *result, const char *fieldname,
bool value);
/* '"fieldname" : null' or 'null' if fieldname is NULL */
void json_add_null(struct json_stream *stream, const char *fieldname);
/* '"fieldname" : "0189abcdef..."' or "0189abcdef..." if fieldname is NULL */
void json_add_hex(struct json_stream *result, const char *fieldname,
const void *data, size_t len);
/* '"fieldname" : "0189abcdef..."' or "0189abcdef..." if fieldname is NULL */
void json_add_hex_talarr(struct json_stream *result,
const char *fieldname,
const tal_t *data);
void json_add_timeabs(struct json_stream *result, const char *fieldname,
struct timeabs t);
/* used in log.c and notification.c*/
void json_add_time(struct json_stream *result, const char *fieldname,
struct timespec ts);
/* Add ISO_8601 timestamp string, i.e. "2019-09-07T15:50+01:00" */
void json_add_timeiso(struct json_stream *result,
const char *fieldname,
struct timeabs *time);
/* Add any json token */
void json_add_tok(struct json_stream *result, const char *fieldname,
const jsmntok_t *tok, const char *buffer);
/* Add an error code */
void json_add_errcode(struct json_stream *result, const char *fieldname,
errcode_t code);
/* Add "bolt11" or "bolt12" field, depending on invstring. */
void json_add_invstring(struct json_stream *result, const char *invstring);
#endif /* LIGHTNING_COMMON_JSON_H */

View File

@@ -4,7 +4,7 @@
#define LIGHTNING_COMMON_JSON_COMMAND_H
#include "config.h"
#include <ccan/compiler/compiler.h>
#include <common/json.h>
#include <common/json_parse.h>
#include <common/jsonrpc_errors.h>
struct command;

View File

@@ -1,495 +0,0 @@
#include "config.h"
#include <arpa/inet.h>
#include <assert.h>
#include <bitcoin/psbt.h>
#include <ccan/ccan/str/hex/hex.h>
#include <common/configdir.h>
#include <common/json_helpers.h>
#include <common/json_stream.h>
#include <common/type_to_string.h>
#include <common/wireaddr.h>
#include <errno.h>
#include <wire/onion_wire.h>
#include <wire/peer_wire.h>
bool json_to_bitcoin_amount(const char *buffer, const jsmntok_t *tok,
uint64_t *satoshi)
{
char *end;
unsigned long btc, sat;
btc = strtoul(buffer + tok->start, &end, 10);
if (btc == ULONG_MAX && errno == ERANGE)
return false;
if (end != buffer + tok->end) {
/* Expect always 8 decimal places. */
if (*end != '.' || buffer + tok->end - end != 9)
return false;
sat = strtoul(end+1, &end, 10);
if (sat == ULONG_MAX && errno == ERANGE)
return false;
if (end != buffer + tok->end)
return false;
} else
sat = 0;
*satoshi = btc * (uint64_t)100000000 + sat;
if (*satoshi != btc * (uint64_t)100000000 + sat)
return false;
return true;
}
bool json_to_node_id(const char *buffer, const jsmntok_t *tok,
struct node_id *id)
{
return node_id_from_hexstr(buffer + tok->start,
tok->end - tok->start, id);
}
bool json_to_pubkey(const char *buffer, const jsmntok_t *tok,
struct pubkey *pubkey)
{
return pubkey_from_hexstr(buffer + tok->start,
tok->end - tok->start, pubkey);
}
bool json_to_msat(const char *buffer, const jsmntok_t *tok,
struct amount_msat *msat)
{
return parse_amount_msat(msat,
buffer + tok->start, tok->end - tok->start);
}
bool json_to_sat(const char *buffer, const jsmntok_t *tok,
struct amount_sat *sat)
{
return parse_amount_sat(sat, buffer + tok->start, tok->end - tok->start);
}
bool json_to_sat_or_all(const char *buffer, const jsmntok_t *tok,
struct amount_sat *sat)
{
if (json_tok_streq(buffer, tok, "all")) {
*sat = AMOUNT_SAT(-1ULL);
return true;
}
return json_to_sat(buffer, tok, sat);
}
bool json_to_short_channel_id(const char *buffer, const jsmntok_t *tok,
struct short_channel_id *scid)
{
return (short_channel_id_from_str(buffer + tok->start,
tok->end - tok->start, scid));
}
bool json_to_txid(const char *buffer, const jsmntok_t *tok,
struct bitcoin_txid *txid)
{
return bitcoin_txid_from_hex(buffer + tok->start,
tok->end - tok->start, txid);
}
bool json_to_outpoint(const char *buffer, const jsmntok_t *tok,
struct bitcoin_outpoint *op)
{
jsmntok_t t1, t2;
if (!split_tok(buffer, tok, ':', &t1, &t2))
return false;
return json_to_txid(buffer, &t1, &op->txid)
&& json_to_u32(buffer, &t2, &op->n);
}
bool json_to_channel_id(const char *buffer, const jsmntok_t *tok,
struct channel_id *cid)
{
return hex_decode(buffer + tok->start, tok->end - tok->start,
cid, sizeof(*cid));
}
bool json_to_coin_mvt_tag(const char *buffer, const jsmntok_t *tok,
enum mvt_tag *tag)
{
enum mvt_tag i_tag;
for (size_t i = 0; i < NUM_MVT_TAGS; i++) {
i_tag = (enum mvt_tag) i;
if (json_tok_streq(buffer, tok, mvt_tag_str(i_tag))) {
*tag = i_tag;
return true;
}
}
return false;
}
bool split_tok(const char *buffer, const jsmntok_t *tok,
char split,
jsmntok_t *a,
jsmntok_t *b)
{
const char *p = memchr(buffer + tok->start, split, tok->end - tok->start);
if (!p)
return false;
*a = *b = *tok;
a->end = p - buffer;
b->start = p + 1 - buffer;
return true;
}
bool json_to_secret(const char *buffer, const jsmntok_t *tok, struct secret *dest)
{
return hex_decode(buffer + tok->start, tok->end - tok->start,
dest->data, sizeof(struct secret));
}
bool json_to_preimage(const char *buffer, const jsmntok_t *tok, struct preimage *preimage)
{
size_t hexlen = tok->end - tok->start;
return hex_decode(buffer + tok->start, hexlen, preimage->r, sizeof(preimage->r));
}
struct wally_psbt *json_to_psbt(const tal_t *ctx, const char *buffer,
const jsmntok_t *tok)
{
return psbt_from_b64(ctx, buffer + tok->start, tok->end - tok->start);
}
struct tlv_obs2_onionmsg_payload_reply_path *
json_to_obs2_reply_path(const tal_t *ctx, const char *buffer, const jsmntok_t *tok)
{
struct tlv_obs2_onionmsg_payload_reply_path *rpath;
const jsmntok_t *hops, *t;
size_t i;
const char *err;
rpath = tal(ctx, struct tlv_obs2_onionmsg_payload_reply_path);
err = json_scan(tmpctx, buffer, tok, "{blinding:%,first_node_id:%}",
JSON_SCAN(json_to_pubkey, &rpath->blinding),
JSON_SCAN(json_to_pubkey, &rpath->first_node_id),
NULL);
if (err)
return tal_free(rpath);
hops = json_get_member(buffer, tok, "hops");
if (!hops || hops->size < 1)
return tal_free(rpath);
rpath->path = tal_arr(rpath, struct onionmsg_path *, hops->size);
json_for_each_arr(i, t, hops) {
rpath->path[i] = tal(rpath->path, struct onionmsg_path);
err = json_scan(tmpctx, buffer, t, "{id:%,encrypted_recipient_data:%}",
JSON_SCAN(json_to_pubkey,
&rpath->path[i]->node_id),
JSON_SCAN_TAL(rpath->path[i],
json_tok_bin_from_hex,
&rpath->path[i]->encrypted_recipient_data));
if (err)
return tal_free(rpath);
}
return rpath;
}
struct tlv_onionmsg_payload_reply_path *
json_to_reply_path(const tal_t *ctx, const char *buffer, const jsmntok_t *tok)
{
struct tlv_onionmsg_payload_reply_path *rpath;
const jsmntok_t *hops, *t;
size_t i;
const char *err;
rpath = tal(ctx, struct tlv_onionmsg_payload_reply_path);
err = json_scan(tmpctx, buffer, tok, "{blinding:%,first_node_id:%}",
JSON_SCAN(json_to_pubkey, &rpath->blinding),
JSON_SCAN(json_to_pubkey, &rpath->first_node_id),
NULL);
if (err)
return tal_free(rpath);
hops = json_get_member(buffer, tok, "hops");
if (!hops || hops->size < 1)
return tal_free(rpath);
rpath->path = tal_arr(rpath, struct onionmsg_path *, hops->size);
json_for_each_arr(i, t, hops) {
rpath->path[i] = tal(rpath->path, struct onionmsg_path);
err = json_scan(tmpctx, buffer, t, "{id:%,encrypted_recipient_data:%}",
JSON_SCAN(json_to_pubkey,
&rpath->path[i]->node_id),
JSON_SCAN_TAL(rpath->path[i],
json_tok_bin_from_hex,
&rpath->path[i]->encrypted_recipient_data));
if (err)
return tal_free(rpath);
}
return rpath;
}
void json_add_node_id(struct json_stream *response,
const char *fieldname,
const struct node_id *id)
{
json_add_hex(response, fieldname, id->k, sizeof(id->k));
}
void json_add_channel_id(struct json_stream *response,
const char *fieldname,
const struct channel_id *cid)
{
json_add_hex(response, fieldname, cid->id, sizeof(cid->id));
}
void json_add_pubkey(struct json_stream *response,
const char *fieldname,
const struct pubkey *key)
{
u8 der[PUBKEY_CMPR_LEN];
pubkey_to_der(der, key);
json_add_hex(response, fieldname, der, sizeof(der));
}
void json_add_point32(struct json_stream *response,
const char *fieldname,
const struct point32 *key)
{
u8 output[32];
secp256k1_xonly_pubkey_serialize(secp256k1_ctx, output, &key->pubkey);
json_add_hex(response, fieldname, output, sizeof(output));
}
void json_add_bip340sig(struct json_stream *response,
const char *fieldname,
const struct bip340sig *sig)
{
json_add_hex(response, fieldname, sig->u8, sizeof(sig->u8));
}
void json_add_txid(struct json_stream *result, const char *fieldname,
const struct bitcoin_txid *txid)
{
char hex[hex_str_size(sizeof(*txid))];
bitcoin_txid_to_hex(txid, hex, sizeof(hex));
json_add_string(result, fieldname, hex);
}
void json_add_outpoint(struct json_stream *result, const char *fieldname,
const struct bitcoin_outpoint *out)
{
char hex[hex_str_size(sizeof(out->txid))];
bitcoin_txid_to_hex(&out->txid, hex, sizeof(hex));
json_add_member(result, fieldname, true, "%s:%d", hex, out->n);
}
void json_add_short_channel_id(struct json_stream *response,
const char *fieldname,
const struct short_channel_id *scid)
{
json_add_member(response, fieldname, true, "%dx%dx%d",
short_channel_id_blocknum(scid),
short_channel_id_txnum(scid),
short_channel_id_outnum(scid));
}
void json_add_address(struct json_stream *response, const char *fieldname,
const struct wireaddr *addr)
{
json_object_start(response, fieldname);
if (addr->type == ADDR_TYPE_IPV4) {
char addrstr[INET_ADDRSTRLEN];
inet_ntop(AF_INET, addr->addr, addrstr, INET_ADDRSTRLEN);
json_add_string(response, "type", "ipv4");
json_add_string(response, "address", addrstr);
json_add_num(response, "port", addr->port);
} else if (addr->type == ADDR_TYPE_IPV6) {
char addrstr[INET6_ADDRSTRLEN];
inet_ntop(AF_INET6, addr->addr, addrstr, INET6_ADDRSTRLEN);
json_add_string(response, "type", "ipv6");
json_add_string(response, "address", addrstr);
json_add_num(response, "port", addr->port);
} else if (addr->type == ADDR_TYPE_TOR_V2_REMOVED) {
json_add_string(response, "type", "torv2");
json_add_string(response, "address", fmt_wireaddr_without_port(tmpctx, addr));
json_add_num(response, "port", addr->port);
} else if (addr->type == ADDR_TYPE_TOR_V3) {
json_add_string(response, "type", "torv3");
json_add_string(response, "address", fmt_wireaddr_without_port(tmpctx, addr));
json_add_num(response, "port", addr->port);
} else if (addr->type == ADDR_TYPE_DNS) {
json_add_string(response, "type", "dns");
json_add_string(response, "address", fmt_wireaddr_without_port(tmpctx, addr));
json_add_num(response, "port", addr->port);
} else if (addr->type == ADDR_TYPE_WEBSOCKET) {
json_add_string(response, "type", "websocket");
json_add_num(response, "port", addr->port);
}
json_object_end(response);
}
void json_add_address_internal(struct json_stream *response,
const char *fieldname,
const struct wireaddr_internal *addr)
{
switch (addr->itype) {
case ADDR_INTERNAL_SOCKNAME:
json_object_start(response, fieldname);
json_add_string(response, "type", "local socket");
json_add_string(response, "socket", addr->u.sockname);
json_object_end(response);
return;
case ADDR_INTERNAL_ALLPROTO:
json_object_start(response, fieldname);
json_add_string(response, "type", "any protocol");
json_add_num(response, "port", addr->u.port);
json_object_end(response);
return;
case ADDR_INTERNAL_AUTOTOR:
json_object_start(response, fieldname);
json_add_string(response, "type", "Tor generated address");
json_add_address(response, "service", &addr->u.torservice.address);
json_object_end(response);
return;
case ADDR_INTERNAL_STATICTOR:
json_object_start(response, fieldname);
json_add_string(response, "type", "Tor from blob generated static address");
json_add_address(response, "service", &addr->u.torservice.address);
json_object_end(response);
return;
case ADDR_INTERNAL_FORPROXY:
json_object_start(response, fieldname);
json_add_string(response, "type", "unresolved");
json_add_string(response, "name", addr->u.unresolved.name);
json_add_num(response, "port", addr->u.unresolved.port);
json_object_end(response);
return;
case ADDR_INTERNAL_WIREADDR:
json_add_address(response, fieldname, &addr->u.wireaddr);
return;
}
abort();
}
void json_add_tx(struct json_stream *result,
const char *fieldname,
const struct bitcoin_tx *tx)
{
json_add_hex_talarr(result, fieldname, linearize_tx(tmpctx, tx));
}
void json_add_psbt(struct json_stream *stream,
const char *fieldname,
const struct wally_psbt *psbt TAKES)
{
const char *psbt_b64;
psbt_b64 = psbt_to_b64(NULL, psbt);
json_add_string(stream, fieldname, take(psbt_b64));
if (taken(psbt))
tal_free(psbt);
}
void json_add_amount_msat_compat(struct json_stream *result,
struct amount_msat msat,
const char *rawfieldname,
const char *msatfieldname)
{
if (deprecated_apis)
json_add_u64(result, rawfieldname, msat.millisatoshis); /* Raw: low-level helper */
json_add_amount_msat_only(result, msatfieldname, msat);
}
void json_add_amount_msat_only(struct json_stream *result,
const char *msatfieldname,
struct amount_msat msat)
{
if (!deprecated_apis)
assert(strends(msatfieldname, "_msat"));
if (deprecated_apis)
json_add_string(result, msatfieldname,
type_to_string(tmpctx, struct amount_msat, &msat));
else
json_add_u64(result, msatfieldname, msat.millisatoshis); /* Raw: low-level helper */
}
void json_add_amount_sat_compat(struct json_stream *result,
struct amount_sat sat,
const char *rawfieldname,
const char *msatfieldname)
{
if (deprecated_apis)
json_add_u64(result, rawfieldname, sat.satoshis); /* Raw: low-level helper */
json_add_amount_sat_msat(result, msatfieldname, sat);
}
void json_add_amount_sat_msat(struct json_stream *result,
const char *msatfieldname,
struct amount_sat sat)
{
struct amount_msat msat;
assert(strends(msatfieldname, "_msat"));
if (amount_sat_to_msat(&msat, sat))
json_add_amount_msat_only(result, msatfieldname, msat);
}
/* When I noticed that we were adding "XXXmsat" fields *not* ending in _msat */
void json_add_amount_sats_deprecated(struct json_stream *result,
const char *fieldname,
const char *msatfieldname,
struct amount_sat sat)
{
if (deprecated_apis) {
struct amount_msat msat;
assert(!strends(fieldname, "_msat"));
if (amount_sat_to_msat(&msat, sat))
json_add_string(result, fieldname,
take(fmt_amount_msat(NULL, msat)));
}
json_add_amount_sat_msat(result, msatfieldname, sat);
}
void json_add_sats(struct json_stream *result,
const char *fieldname,
struct amount_sat sat)
{
json_add_string(result, fieldname, take(fmt_amount_sat(NULL, sat)));
}
void json_add_secret(struct json_stream *response, const char *fieldname,
const struct secret *secret)
{
json_add_hex(response, fieldname, secret, sizeof(struct secret));
}
void json_add_sha256(struct json_stream *result, const char *fieldname,
const struct sha256 *hash)
{
json_add_hex(result, fieldname, hash, sizeof(*hash));
}
void json_add_preimage(struct json_stream *result, const char *fieldname,
const struct preimage *preimage)
{
json_add_hex(result, fieldname, preimage, sizeof(*preimage));
}
void json_add_lease_rates(struct json_stream *result,
const struct lease_rates *rates)
{
json_add_amount_sat_msat(result, "lease_fee_base_msat",
amount_sat(rates->lease_fee_base_sat));
json_add_num(result, "lease_fee_basis", rates->lease_fee_basis);
json_add_num(result, "funding_weight", rates->funding_weight);
json_add_amount_msat_only(result,
"channel_fee_max_base_msat",
amount_msat(rates->channel_fee_max_base_msat));
json_add_num(result, "channel_fee_max_proportional_thousandths",
rates->channel_fee_max_proportional_thousandths);
}

View File

@@ -1,208 +0,0 @@
/* More specialized (bitcoin, lightning-specific) JSON helpers. */
#ifndef LIGHTNING_COMMON_JSON_HELPERS_H
#define LIGHTNING_COMMON_JSON_HELPERS_H
#include "config.h"
#include <bitcoin/tx.h>
#include <common/coin_mvt.h>
#include <common/json.h>
#include <wire/wire.h>
struct amount_msat;
struct amount_sat;
struct bip340sig;
struct channel_id;
struct lease_rates;
struct node_id;
struct preimage;
struct pubkey;
struct point32;
struct secret;
struct short_channel_id;
struct short_channel_id_dir;
struct wireaddr;
struct wireaddr_internal;
struct wally_psbt;
/* Decode a hex-encoded payment preimage */
bool json_to_preimage(const char *buffer, const jsmntok_t *tok, struct preimage *preimage);
/* Extract a secret from this. */
bool json_to_secret(const char *buffer, const jsmntok_t *tok, struct secret *dest);
/* Extract a psbt from this. */
struct wally_psbt *json_to_psbt(const tal_t *ctx, const char *buffer,
const jsmntok_t *tok);
/* Extract a pubkey from this */
bool json_to_pubkey(const char *buffer, const jsmntok_t *tok,
struct pubkey *pubkey);
/* Extract node_id from this: makes sure *id is valid! */
bool json_to_node_id(const char *buffer, const jsmntok_t *tok,
struct node_id *id);
/* Extract satoshis from this (may be a string, or a decimal number literal) */
bool json_to_bitcoin_amount(const char *buffer, const jsmntok_t *tok,
uint64_t *satoshi);
/* Extract a short_channel_id from this */
bool json_to_short_channel_id(const char *buffer, const jsmntok_t *tok,
struct short_channel_id *scid);
/* Extract a satoshis amount from this */
bool json_to_sat(const char *buffer, const jsmntok_t *tok,
struct amount_sat *sat);
/* Extract a satoshis amount from this */
/* If the string is "all", set amonut as AMOUNT_SAT(-1ULL). */
bool json_to_sat_or_all(const char *buffer, const jsmntok_t *tok,
struct amount_sat *sat);
/* Extract a millisatoshis amount from this */
bool json_to_msat(const char *buffer, const jsmntok_t *tok,
struct amount_msat *msat);
/* Extract a bitcoin txid from this */
bool json_to_txid(const char *buffer, const jsmntok_t *tok,
struct bitcoin_txid *txid);
/* Extract a bitcoin outpoint from this */
bool json_to_outpoint(const char *buffer, const jsmntok_t *tok,
struct bitcoin_outpoint *op);
/* Extract a channel id from this */
bool json_to_channel_id(const char *buffer, const jsmntok_t *tok,
struct channel_id *cid);
/* Extract a coin movement 'tag' from this */
bool json_to_coin_mvt_tag(const char *buffer, const jsmntok_t *tok,
enum mvt_tag *tag);
/* Split a json token into 2 tokens given a splitting character */
bool split_tok(const char *buffer, const jsmntok_t *tok,
char split,
jsmntok_t *a,
jsmntok_t *b);
/* Extract reply path from this JSON */
struct tlv_onionmsg_payload_reply_path *
json_to_reply_path(const tal_t *ctx, const char *buffer, const jsmntok_t *tok);
/* Obsolete version! */
struct tlv_obs2_onionmsg_payload_reply_path *
json_to_obs2_reply_path(const tal_t *ctx, const char *buffer, const jsmntok_t *tok);
/* Helpers for outputting JSON results */
/* '"fieldname" : "0289abcdef..."' or "0289abcdef..." if fieldname is NULL */
void json_add_pubkey(struct json_stream *response,
const char *fieldname,
const struct pubkey *key);
/* '"fieldname" : "89abcdef..."' or "89abcdef..." if fieldname is NULL */
void json_add_point32(struct json_stream *response,
const char *fieldname,
const struct point32 *key);
/* '"fieldname" : "89abcdef..."' or "89abcdef..." if fieldname is NULL */
void json_add_bip340sig(struct json_stream *response,
const char *fieldname,
const struct bip340sig *sig);
/* '"fieldname" : "89abcdef..."' or "89abcdef..." if fieldname is NULL */
void json_add_secret(struct json_stream *response,
const char *fieldname,
const struct secret *secret);
/* '"fieldname" : "0289abcdef..."' or "0289abcdef..." if fieldname is NULL */
void json_add_node_id(struct json_stream *response,
const char *fieldname,
const struct node_id *id);
/* '"fieldname" : "0289abcdef..."' or "0289abcdef..." if fieldname is NULL */
void json_add_channel_id(struct json_stream *response,
const char *fieldname,
const struct channel_id *cid);
/* '"fieldname" : <hexrev>' or "<hexrev>" if fieldname is NULL */
void json_add_txid(struct json_stream *result, const char *fieldname,
const struct bitcoin_txid *txid);
/* '"fieldname" : "txid:n" */
void json_add_outpoint(struct json_stream *result, const char *fieldname,
const struct bitcoin_outpoint *out);
/* '"fieldname" : "1234:5:6"' */
void json_add_short_channel_id(struct json_stream *response,
const char *fieldname,
const struct short_channel_id *id);
/* JSON serialize a network address for a node */
void json_add_address(struct json_stream *response, const char *fieldname,
const struct wireaddr *addr);
/* JSON serialize a network address for a node. */
void json_add_address_internal(struct json_stream *response,
const char *fieldname,
const struct wireaddr_internal *addr);
/* Adds both a 'raw' number field and an 'amount_msat' field */
void json_add_amount_msat_compat(struct json_stream *result,
struct amount_msat msat,
const char *rawfieldname,
const char *msatfieldname)
NO_NULL_ARGS;
/* Adds both a 'raw' number field and an 'amount_msat' field */
void json_add_amount_sat_compat(struct json_stream *result,
struct amount_sat sat,
const char *rawfieldname,
const char *msatfieldname)
NO_NULL_ARGS;
/* Adds an 'msat' field */
void json_add_amount_msat_only(struct json_stream *result,
const char *msatfieldname,
struct amount_msat msat)
NO_NULL_ARGS;
/* Adds an 'msat' field */
void json_add_amount_sat_msat(struct json_stream *result,
const char *msatfieldname,
struct amount_sat sat)
NO_NULL_ARGS;
/* Adds an 'msat' field, and an older deprecated field. */
void json_add_amount_sats_deprecated(struct json_stream *result,
const char *fieldname,
const char *msatfieldname,
struct amount_sat sat)
NO_NULL_ARGS;
/* This is used to create requests, *never* for output (output is always
* msat!) */
void json_add_sats(struct json_stream *result,
const char *fieldname,
struct amount_sat sat);
void json_add_sha256(struct json_stream *result, const char *fieldname,
const struct sha256 *hash);
void json_add_preimage(struct json_stream *result, const char *fieldname,
const struct preimage *preimage);
/* '"fieldname" : "010000000001..."' or "010000000001..." if fieldname is NULL */
void json_add_tx(struct json_stream *result,
const char *fieldname,
const struct bitcoin_tx *tx);
/* '"fieldname" : "cHNidP8BAJoCAAAAAljo..." or "cHNidP8BAJoCAAAAAljo..." if fieldname is NULL */
void json_add_psbt(struct json_stream *stream,
const char *fieldname,
const struct wally_psbt *psbt);
/* Add fields from the lease_rates to a json stream.
* Note that field names are set */
void json_add_lease_rates(struct json_stream *result,
const struct lease_rates *rates);
#endif /* LIGHTNING_COMMON_JSON_HELPERS_H */

View File

@@ -4,15 +4,378 @@
#include <bitcoin/feerate.h>
#include <bitcoin/psbt.h>
#include <bitcoin/script.h>
#include <ccan/asort/asort.h>
#include <ccan/json_escape/json_escape.h>
#include <ccan/mem/mem.h>
#include <ccan/str/hex/hex.h>
#include <ccan/tal/str/str.h>
#include <common/bech32.h>
#include <common/configdir.h>
#include <common/json_command.h>
#include <common/json_helpers.h>
#include <common/json_tok.h>
#include <common/json_param.h>
#include <common/route.h>
struct param {
const char *name;
bool is_set;
enum param_style style;
param_cbx cbx;
void *arg;
};
static bool param_add(struct param **params,
const char *name,
enum param_style style,
param_cbx cbx, void *arg)
{
#if DEVELOPER
if (!(name && cbx && arg))
return false;
#endif
struct param last;
last.is_set = false;
last.name = name;
last.style = style;
last.cbx = cbx;
last.arg = arg;
tal_arr_expand(params, last);
return true;
}
/* FIXME: To support the deprecated p_req_dup_ok */
static bool is_required(enum param_style style)
{
return style == PARAM_REQUIRED || style == PARAM_REQUIRED_ALLOW_DUPS;
}
static struct command_result *make_callback(struct command *cmd,
struct param *def,
const char *buffer,
const jsmntok_t *tok)
{
/* If it had a default, free that now to avoid leak */
if (def->style == PARAM_OPTIONAL_WITH_DEFAULT && !def->is_set)
tal_free(*(void **)def->arg);
def->is_set = true;
return def->cbx(cmd, def->name, buffer, tok, def->arg);
}
static struct command_result *post_check(struct command *cmd,
struct param *params)
{
struct param *first = params;
struct param *last = first + tal_count(params);
/* Make sure required params were provided. */
while (first != last && is_required(first->style)) {
if (!first->is_set) {
return command_fail(cmd, JSONRPC2_INVALID_PARAMS,
"missing required parameter: %s",
first->name);
}
first++;
}
return NULL;
}
static struct command_result *parse_by_position(struct command *cmd,
struct param *params,
const char *buffer,
const jsmntok_t tokens[],
bool allow_extra)
{
struct command_result *res;
const jsmntok_t *tok;
size_t i;
json_for_each_arr(i, tok, tokens) {
/* check for unexpected trailing params */
if (i == tal_count(params)) {
if (!allow_extra) {
return command_fail(cmd, JSONRPC2_INVALID_PARAMS,
"too many parameters:"
" got %u, expected %zu",
tokens->size,
tal_count(params));
}
break;
}
if (!json_tok_is_null(buffer, tok)) {
res = make_callback(cmd, params+i, buffer, tok);
if (res)
return res;
}
}
return post_check(cmd, params);
}
static struct param *find_param(struct param *params, const char *start,
size_t n)
{
struct param *first = params;
struct param *last = first + tal_count(params);
while (first != last) {
size_t arglen = strcspn(first->name, "|");
if (memeq(first->name, arglen, start, n))
return first;
if (deprecated_apis
&& first->name[arglen]
&& memeq(first->name + arglen + 1,
strlen(first->name + arglen + 1),
start, n))
return first;
first++;
}
return NULL;
}
static struct command_result *parse_by_name(struct command *cmd,
struct param *params,
const char *buffer,
const jsmntok_t tokens[],
bool allow_extra)
{
size_t i;
const jsmntok_t *t;
json_for_each_obj(i, t, tokens) {
struct param *p = find_param(params, buffer + t->start,
t->end - t->start);
if (!p) {
if (!allow_extra) {
return command_fail(cmd, JSONRPC2_INVALID_PARAMS,
"unknown parameter: %.*s, this may be caused by a failure to autodetect key=value-style parameters. Please try using the -k flag and explicit key=value pairs of parameters.",
t->end - t->start,
buffer + t->start);
}
} else {
struct command_result *res;
if (p->is_set) {
if (p->style == PARAM_REQUIRED_ALLOW_DUPS)
continue;
return command_fail(cmd, JSONRPC2_INVALID_PARAMS,
"duplicate json names: %s",
p->name);
}
res = make_callback(cmd, p, buffer, t + 1);
if (res)
return res;
}
}
return post_check(cmd, params);
}
#if DEVELOPER
static int comp_by_name(const struct param *a, const struct param *b,
void *unused)
{
return strcmp(a->name, b->name);
}
static int comp_by_arg(const struct param *a, const struct param *b,
void *unused)
{
/* size_t could be larger than int: don't turn a 4bn difference into 0 */
if (a->arg > b->arg)
return 1;
else if (a->arg < b->arg)
return -1;
return 0;
}
/* This comparator is a bit different, but works well.
* Return 0 if @a is optional and @b is required. Otherwise return 1.
*/
static int comp_req_order(const struct param *a, const struct param *b,
void *unused)
{
if (!is_required(a->style) && is_required(b->style))
return 0;
return 1;
}
/*
* Make sure 2 sequential items in @params are not equal (based on
* provided comparator).
*/
static bool check_distinct(struct param *params,
int (*compar) (const struct param *a,
const struct param *b, void *unused))
{
struct param *first = params;
struct param *last = first + tal_count(params);
first++;
while (first != last) {
if (compar(first - 1, first, NULL) == 0)
return false;
first++;
}
return true;
}
static bool check_unique(struct param *copy,
int (*compar) (const struct param *a,
const struct param *b, void *unused))
{
asort(copy, tal_count(copy), compar, NULL);
return check_distinct(copy, compar);
}
/*
* Verify consistent internal state.
*/
static bool check_params(struct param *params)
{
if (tal_count(params) < 2)
return true;
/* make sure there are no required params following optional */
if (!check_distinct(params, comp_req_order))
return false;
/* duplicate so we can sort */
struct param *copy = tal_dup_talarr(params, struct param, params);
/* check for repeated names and args */
if (!check_unique(copy, comp_by_name))
return false;
if (!check_unique(copy, comp_by_arg))
return false;
tal_free(copy);
return true;
}
#endif
static char *param_usage(const tal_t *ctx,
const struct param *params)
{
char *usage = tal_strdup(ctx, "");
for (size_t i = 0; i < tal_count(params); i++) {
/* Don't print |deprecated part! */
int len = strcspn(params[i].name, "|");
if (i != 0)
tal_append_fmt(&usage, " ");
if (is_required(params[i].style))
tal_append_fmt(&usage, "%.*s", len, params[i].name);
else
tal_append_fmt(&usage, "[%.*s]", len, params[i].name);
}
return usage;
}
static struct command_result *param_arr(struct command *cmd, const char *buffer,
const jsmntok_t tokens[],
struct param *params,
bool allow_extra)
{
#if DEVELOPER
if (!check_params(params)) {
return command_fail(cmd, PARAM_DEV_ERROR,
"developer error: check_params");
}
#endif
if (tokens->type == JSMN_ARRAY)
return parse_by_position(cmd, params, buffer, tokens, allow_extra);
else if (tokens->type == JSMN_OBJECT)
return parse_by_name(cmd, params, buffer, tokens, allow_extra);
return command_fail(cmd, JSONRPC2_INVALID_PARAMS,
"Expected array or object for params");
}
const char *param_subcommand(struct command *cmd, const char *buffer,
const jsmntok_t tokens[],
const char *name, ...)
{
va_list ap;
struct param *params = tal_arr(cmd, struct param, 0);
const char *arg, **names = tal_arr(tmpctx, const char *, 1);
const char *subcmd;
param_add(&params, "subcommand", PARAM_REQUIRED, (void *)param_string, &subcmd);
names[0] = name;
va_start(ap, name);
while ((arg = va_arg(ap, const char *)) != NULL)
tal_arr_expand(&names, arg);
va_end(ap);
if (command_usage_only(cmd)) {
char *usage = tal_strdup(cmd, "subcommand");
for (size_t i = 0; i < tal_count(names); i++)
tal_append_fmt(&usage, "%c%s",
i == 0 ? '=' : '|', names[i]);
command_set_usage(cmd, usage);
return NULL;
}
/* Check it's valid */
if (param_arr(cmd, buffer, tokens, params, true) != NULL) {
return NULL;
}
/* Check it's one of the known ones. */
for (size_t i = 0; i < tal_count(names); i++)
if (streq(subcmd, names[i]))
return subcmd;
/* We really do ignore this. */
struct command_result *ignore;
ignore = command_fail(cmd, JSONRPC2_INVALID_PARAMS,
"Unknown subcommand '%s'", subcmd);
assert(ignore);
return NULL;
}
bool param(struct command *cmd, const char *buffer,
const jsmntok_t tokens[], ...)
{
struct param *params = tal_arr(tmpctx, struct param, 0);
const char *name;
va_list ap;
bool allow_extra = false;
va_start(ap, tokens);
while ((name = va_arg(ap, const char *)) != NULL) {
enum param_style style = va_arg(ap, enum param_style);
param_cbx cbx = va_arg(ap, param_cbx);
void *arg = va_arg(ap, void *);
if (streq(name, "")) {
allow_extra = true;
continue;
}
if (!param_add(&params, name, style, cbx, arg)) {
/* We really do ignore this return! */
struct command_result *ignore;
ignore = command_fail(cmd, PARAM_DEV_ERROR,
"developer error: param_add %s", name);
assert(ignore);
va_end(ap);
return false;
}
}
va_end(ap);
if (command_usage_only(cmd)) {
command_set_usage(cmd, param_usage(cmd, params));
return false;
}
/* Always return false if we're simply checking command parameters;
* normally this returns true if all parameters are valid. */
return param_arr(cmd, buffer, tokens, params, allow_extra) == NULL
&& !command_check_only(cmd);
}
struct command_result *param_array(struct command *cmd, const char *name,
const char *buffer, const jsmntok_t *tok,
const jsmntok_t **arr)

View File

@@ -1,22 +1,152 @@
/* Helpers for use with param parsing. */
#ifndef LIGHTNING_COMMON_JSON_TOK_H
#define LIGHTNING_COMMON_JSON_TOK_H
#ifndef LIGHTNING_COMMON_JSON_PARAM_H
#define LIGHTNING_COMMON_JSON_PARAM_H
#include "config.h"
#include <ccan/short_types/short_types.h>
#include <common/bolt11.h>
#include <common/json.h>
#include <common/json_parse.h>
#include <common/lease_rates.h>
#include <common/node_id.h>
#include <common/sphinx.h>
#include <wire/wire.h>
/*~ Greetings adventurer!
*
* Do you want to automatically validate json input and unmarshal it into
* local variables, all using typesafe callbacks? And on error,
* call command_fail with a proper error message? Then you've come to the
* right place!
*
* Here is a simple example of using the system:
*
* unsigned *cltv;
* u64 *msatoshi;
* const jsmntok_t *note;
* u64 *expiry;
*
* if (!param(cmd, buffer, params,
* p_req("cltv", json_tok_number, &cltv),
* p_opt("msatoshi", json_tok_u64, &msatoshi),
* p_opt("note", json_tok_tok, &note),
* p_opt_def("expiry", json_tok_u64, &expiry, 3600),
* NULL))
* return;
*
* If param() returns true then you're good to go.
*
* All the command handlers throughout the code use this system.
* json_invoice() is a great example. The common callbacks can be found in
* common/json_tok.c. Use them directly or feel free to write your own.
*/
struct command;
/* A dummy type returned by command_ functions, to ensure you return them
* immediately */
struct command_result;
/*
* Parse the json tokens. @params can be an array of values or an object
* of named values.
*/
bool param(struct command *cmd, const char *buffer,
const jsmntok_t params[], ...) LAST_ARG_NULL;
/*
* The callback signature.
*
* Callbacks must return NULL on success. On failure they
* must return command_fail(...).
*/
typedef struct command_result *(*param_cbx)(struct command *cmd,
const char *name,
const char *buffer,
const jsmntok_t *tok,
void **arg);
/**
* Parse the first json value.
*
* name...: NULL-terminated array of valid values.
*
* Returns subcommand: if it returns NULL if you should return
* command_param_failed() immediately.
*/
const char *param_subcommand(struct command *cmd, const char *buffer,
const jsmntok_t tokens[],
const char *name, ...) LAST_ARG_NULL;
enum param_style {
PARAM_REQUIRED,
PARAM_REQUIRED_ALLOW_DUPS,
PARAM_OPTIONAL,
PARAM_OPTIONAL_WITH_DEFAULT,
};
/*
* Add a required parameter.
*/
#define p_req(name, cbx, arg) \
name"", \
PARAM_REQUIRED, \
(param_cbx)(cbx), \
(arg) + 0*sizeof((cbx)((struct command *)NULL, \
(const char *)NULL, \
(const char *)NULL, \
(const jsmntok_t *)NULL, \
(arg)) == (struct command_result *)NULL)
/*
* Add an optional parameter. *arg is set to NULL if it isn't found.
*/
#define p_opt(name, cbx, arg) \
name"", \
PARAM_OPTIONAL, \
(param_cbx)(cbx), \
({ *arg = NULL; \
(arg) + 0*sizeof((cbx)((struct command *)NULL, \
(const char *)NULL, \
(const char *)NULL, \
(const jsmntok_t *)NULL, \
(arg)) == (struct command_result *)NULL); })
/*
* Add an required parameter, like p_req, but ignore duplicates.
*/
#define p_req_dup_ok(name, cbx, arg) \
name"", \
PARAM_REQUIRED_ALLOW_DUPS, \
(param_cbx)(cbx), \
({ *arg = NULL; \
(arg) + 0*sizeof((cbx)((struct command *)NULL, \
(const char *)NULL, \
(const char *)NULL, \
(const jsmntok_t *)NULL, \
(arg)) == (struct command_result *)NULL); })
/*
* Add an optional parameter. *arg is set to @def if it isn't found.
*/
#define p_opt_def(name, cbx, arg, def) \
name"", \
PARAM_OPTIONAL_WITH_DEFAULT, \
(param_cbx)(cbx), \
({ (*arg) = tal((cmd), typeof(**arg)); \
(**arg) = (def); \
(arg) + 0*sizeof((cbx)((struct command *)NULL, \
(const char *)NULL, \
(const char *)NULL, \
(const jsmntok_t *)NULL, \
(arg)) == (struct command_result *)NULL); })
/* Special flag for 'check' which allows any parameters. */
#define p_opt_any() "", PARAM_OPTIONAL, NULL, NULL
/* All the helper routines. */
struct amount_msat;
struct amount_sat;
struct bitcoin_txid;
struct bitcoin_outpoint;
struct channel_id;
struct command;
struct command_result;
struct json_escape;
struct route_exclusion;
struct sha256;
@@ -213,4 +343,4 @@ struct command_result *param_lease_hex(struct command *cmd,
const char *buffer,
const jsmntok_t *tok,
struct lease_rates **rates);
#endif /* LIGHTNING_COMMON_JSON_TOK_H */
#endif /* LIGHTNING_COMMON_JSON_PARAM_H */

719
common/json_parse.c Normal file
View File

@@ -0,0 +1,719 @@
/* JSON core and helpers */
#include "config.h"
#include <assert.h>
#include <bitcoin/preimage.h>
#include <bitcoin/privkey.h>
#include <bitcoin/psbt.h>
#include <bitcoin/pubkey.h>
#include <bitcoin/short_channel_id.h>
#include <bitcoin/tx.h>
#include <ccan/json_escape/json_escape.h>
#include <ccan/mem/mem.h>
#include <ccan/str/hex/hex.h>
#include <ccan/tal/str/str.h>
#include <ccan/time/time.h>
#include <common/amount.h>
#include <common/channel_id.h>
#include <common/json_parse.h>
#include <common/node_id.h>
#include <common/overflows.h>
#include <common/utils.h>
#include <errno.h>
#include <inttypes.h>
#include <stdio.h>
#include <wire/onion_wire.h>
bool json_to_s64(const char *buffer, const jsmntok_t *tok, s64 *num)
{
char *end;
long long l;
l = strtoll(buffer + tok->start, &end, 0);
if (end != buffer + tok->end)
return false;
BUILD_ASSERT(sizeof(l) >= sizeof(*num));
*num = l;
/* Check for overflow/underflow */
if ((l == LONG_MAX || l == LONG_MIN) && errno == ERANGE)
return false;
/* Check if the number did not fit in `s64` (in case `long long`
is a bigger type). */
if (*num != l)
return false;
return true;
}
bool json_to_millionths(const char *buffer, const jsmntok_t *tok,
u64 *millionths)
{
int decimal_places = -1;
bool has_digits = 0;
*millionths = 0;
for (int i = tok->start; i < tok->end; i++) {
if (isdigit(buffer[i])) {
has_digits = true;
/* Ignore too much precision */
if (decimal_places >= 0 && ++decimal_places > 6)
continue;
if (mul_overflows_u64(*millionths, 10))
return false;
*millionths *= 10;
if (add_overflows_u64(*millionths, buffer[i] - '0'))
return false;
*millionths += buffer[i] - '0';
} else if (buffer[i] == '.') {
if (decimal_places != -1)
return false;
decimal_places = 0;
} else
return false;
}
if (!has_digits)
return false;
if (decimal_places == -1)
decimal_places = 0;
while (decimal_places < 6) {
if (mul_overflows_u64(*millionths, 10))
return false;
*millionths *= 10;
decimal_places++;
}
return true;
}
bool json_to_number(const char *buffer, const jsmntok_t *tok,
unsigned int *num)
{
uint64_t u64;
if (!json_to_u64(buffer, tok, &u64))
return false;
*num = u64;
/* Just in case it doesn't fit. */
if (*num != u64)
return false;
return true;
}
bool json_to_u16(const char *buffer, const jsmntok_t *tok,
short unsigned int *num)
{
uint64_t u64;
if (!json_to_u64(buffer, tok, &u64))
return false;
*num = u64;
/* Just in case it doesn't fit. */
if (*num != u64)
return false;
return true;
}
bool json_to_int(const char *buffer, const jsmntok_t *tok, int *num)
{
s64 tmp;
if (!json_to_s64(buffer, tok, &tmp))
return false;
*num = tmp;
/* Just in case it doesn't fit. */
if (*num != tmp)
return false;
return true;
}
bool json_to_errcode(const char *buffer, const jsmntok_t *tok, errcode_t *errcode)
{
s64 tmp;
if (!json_to_s64(buffer, tok, &tmp))
return false;
*errcode = tmp;
/* Just in case it doesn't fit. */
if (*errcode != tmp)
return false;
return true;
}
bool json_to_sha256(const char *buffer, const jsmntok_t *tok, struct sha256 *dest)
{
if (tok->type != JSMN_STRING)
return false;
return hex_decode(buffer + tok->start, tok->end - tok->start, dest,
sizeof(struct sha256));
}
u8 *json_tok_bin_from_hex(const tal_t *ctx, const char *buffer, const jsmntok_t *tok)
{
u8 *result;
size_t hexlen, rawlen;
hexlen = tok->end - tok->start;
rawlen = hex_data_size(hexlen);
result = tal_arr(ctx, u8, rawlen);
if (!hex_decode(buffer + tok->start, hexlen, result, rawlen))
return tal_free(result);
return result;
}
/* talfmt take a ctx pointer and return NULL or a valid pointer.
* fmt takes the argument, and returns a bool.
*
* This function returns NULL on success, or errmsg on failure.
*/
static const char *handle_percent(const char *buffer,
const jsmntok_t *tok,
va_list *ap)
{
void *ctx;
const char *fmtname;
/* This is set to (dummy) json_scan if it's a non-tal fmt */
ctx = va_arg(*ap, void *);
fmtname = va_arg(*ap, const char *);
if (ctx != json_scan) {
void *(*talfmt)(void *, const char *, const jsmntok_t *);
void **p;
p = va_arg(*ap, void **);
talfmt = va_arg(*ap, void *(*)(void *, const char *, const jsmntok_t *));
*p = talfmt(ctx, buffer, tok);
if (*p != NULL)
return NULL;
} else {
bool (*fmt)(const char *, const jsmntok_t *, void *);
void *p;
p = va_arg(*ap, void *);
fmt = va_arg(*ap, bool (*)(const char *, const jsmntok_t *, void *));
if (fmt(buffer, tok, p))
return NULL;
}
return tal_fmt(tmpctx, "%s could not parse %.*s",
fmtname,
json_tok_full_len(tok),
json_tok_full(buffer, tok));
}
/* GUIDE := OBJ | ARRAY | '%'
* OBJ := '{' FIELDLIST '}'
* FIELDLIST := FIELD [',' FIELD]*
* FIELD := LITERAL ':' FIELDVAL
* FIELDVAL := OBJ | ARRAY | LITERAL | '%'
* ARRAY := '[' ARRLIST ']'
* ARRLIST := ARRELEM [',' ARRELEM]*
* ARRELEM := NUMBER ':' FIELDVAL
*/
static void parse_literal(const char **guide,
const char **literal,
size_t *len)
{
*literal = *guide;
*len = strspn(*guide,
"ABCDEFGHIJKLMNOPQRSTUVWXYZ"
"abcdefghijklmnopqrstuvwxyz"
"0123456789"
"_-");
*guide += *len;
}
static void parse_number(const char **guide, u32 *number)
{
char *endp;
long int l;
l = strtol(*guide, &endp, 10);
assert(endp != *guide);
assert(errno != ERANGE);
/* Test for overflow */
*number = l;
assert(*number == l);
*guide = endp;
}
static char guide_consume_one(const char **guide)
{
char c = **guide;
(*guide)++;
return c;
}
static void guide_must_be(const char **guide, char c)
{
char actual = guide_consume_one(guide);
assert(actual == c);
}
/* Recursion: return NULL on success, errmsg on fail */
static const char *parse_obj(const char *buffer,
const jsmntok_t *tok,
const char **guide,
va_list *ap);
static const char *parse_arr(const char *buffer,
const jsmntok_t *tok,
const char **guide,
va_list *ap);
static const char *parse_guide(const char *buffer,
const jsmntok_t *tok,
const char **guide,
va_list *ap)
{
const char *errmsg;
if (**guide == '{') {
errmsg = parse_obj(buffer, tok, guide, ap);
if (errmsg)
return errmsg;
} else if (**guide == '[') {
errmsg = parse_arr(buffer, tok, guide, ap);
if (errmsg)
return errmsg;
} else {
guide_must_be(guide, '%');
errmsg = handle_percent(buffer, tok, ap);
if (errmsg)
return errmsg;
}
return NULL;
}
static const char *parse_fieldval(const char *buffer,
const jsmntok_t *tok,
const char **guide,
va_list *ap)
{
const char *errmsg;
if (**guide == '{') {
errmsg = parse_obj(buffer, tok, guide, ap);
if (errmsg)
return errmsg;
} else if (**guide == '[') {
errmsg = parse_arr(buffer, tok, guide, ap);
if (errmsg)
return errmsg;
} else if (**guide == '%') {
guide_consume_one(guide);
errmsg = handle_percent(buffer, tok, ap);
if (errmsg)
return errmsg;
} else {
const char *literal;
size_t len;
/* Literal must match exactly (modulo quotes for strings) */
parse_literal(guide, &literal, &len);
if (!memeq(buffer + tok->start, tok->end - tok->start,
literal, len)) {
return tal_fmt(tmpctx,
"%.*s does not match expected %.*s",
json_tok_full_len(tok),
json_tok_full(buffer, tok),
(int)len, literal);
}
}
return NULL;
}
static const char *parse_field(const char *buffer,
const jsmntok_t *tok,
const char **guide,
va_list *ap)
{
const jsmntok_t *member;
size_t len;
const char *memname;
parse_literal(guide, &memname, &len);
guide_must_be(guide, ':');
member = json_get_membern(buffer, tok, memname, len);
if (!member) {
return tal_fmt(tmpctx, "object does not have member %.*s",
(int)len, memname);
}
return parse_fieldval(buffer, member, guide, ap);
}
static const char *parse_fieldlist(const char *buffer,
const jsmntok_t *tok,
const char **guide,
va_list *ap)
{
for (;;) {
const char *errmsg;
errmsg = parse_field(buffer, tok, guide, ap);
if (errmsg)
return errmsg;
if (**guide != ',')
break;
guide_consume_one(guide);
}
return NULL;
}
static const char *parse_obj(const char *buffer,
const jsmntok_t *tok,
const char **guide,
va_list *ap)
{
const char *errmsg;
guide_must_be(guide, '{');
if (tok->type != JSMN_OBJECT) {
return tal_fmt(tmpctx, "token is not an object: %.*s",
json_tok_full_len(tok),
json_tok_full(buffer, tok));
}
errmsg = parse_fieldlist(buffer, tok, guide, ap);
if (errmsg)
return errmsg;
guide_must_be(guide, '}');
return NULL;
}
static const char *parse_arrelem(const char *buffer,
const jsmntok_t *tok,
const char **guide,
va_list *ap)
{
const jsmntok_t *member;
u32 idx;
parse_number(guide, &idx);
guide_must_be(guide, ':');
member = json_get_arr(tok, idx);
if (!member) {
return tal_fmt(tmpctx, "token has no index %u: %.*s",
idx,
json_tok_full_len(tok),
json_tok_full(buffer, tok));
}
return parse_fieldval(buffer, member, guide, ap);
}
static const char *parse_arrlist(const char *buffer,
const jsmntok_t *tok,
const char **guide,
va_list *ap)
{
const char *errmsg;
for (;;) {
errmsg = parse_arrelem(buffer, tok, guide, ap);
if (errmsg)
return errmsg;
if (**guide != ',')
break;
guide_consume_one(guide);
}
return NULL;
}
static const char *parse_arr(const char *buffer,
const jsmntok_t *tok,
const char **guide,
va_list *ap)
{
const char *errmsg;
guide_must_be(guide, '[');
if (tok->type != JSMN_ARRAY) {
return tal_fmt(tmpctx, "token is not an array: %.*s",
json_tok_full_len(tok),
json_tok_full(buffer, tok));
}
errmsg = parse_arrlist(buffer, tok, guide, ap);
if (errmsg)
return errmsg;
guide_must_be(guide, ']');
return NULL;
}
const char *json_scanv(const tal_t *ctx,
const char *buffer,
const jsmntok_t *tok,
const char *guide,
va_list ap)
{
va_list cpy;
const char *orig_guide = guide, *errmsg;
/* We need this, since &ap doesn't work on some platforms... */
va_copy(cpy, ap);
errmsg = parse_guide(buffer, tok, &guide, &cpy);
va_end(cpy);
if (errmsg) {
return tal_fmt(ctx, "Parsing '%.*s': %s",
(int)(guide - orig_guide), orig_guide,
errmsg);
}
assert(guide[0] == '\0');
return NULL;
}
const char *json_scan(const tal_t *ctx,
const char *buffer,
const jsmntok_t *tok,
const char *guide,
...)
{
va_list ap;
const char *ret;
va_start(ap, guide);
ret = json_scanv(ctx, buffer, tok, guide, ap);
va_end(ap);
return ret;
}
bool json_to_bitcoin_amount(const char *buffer, const jsmntok_t *tok,
uint64_t *satoshi)
{
char *end;
unsigned long btc, sat;
btc = strtoul(buffer + tok->start, &end, 10);
if (btc == ULONG_MAX && errno == ERANGE)
return false;
if (end != buffer + tok->end) {
/* Expect always 8 decimal places. */
if (*end != '.' || buffer + tok->end - end != 9)
return false;
sat = strtoul(end+1, &end, 10);
if (sat == ULONG_MAX && errno == ERANGE)
return false;
if (end != buffer + tok->end)
return false;
} else
sat = 0;
*satoshi = btc * (uint64_t)100000000 + sat;
if (*satoshi != btc * (uint64_t)100000000 + sat)
return false;
return true;
}
bool json_to_node_id(const char *buffer, const jsmntok_t *tok,
struct node_id *id)
{
return node_id_from_hexstr(buffer + tok->start,
tok->end - tok->start, id);
}
bool json_to_pubkey(const char *buffer, const jsmntok_t *tok,
struct pubkey *pubkey)
{
return pubkey_from_hexstr(buffer + tok->start,
tok->end - tok->start, pubkey);
}
bool json_to_msat(const char *buffer, const jsmntok_t *tok,
struct amount_msat *msat)
{
return parse_amount_msat(msat,
buffer + tok->start, tok->end - tok->start);
}
bool json_to_sat(const char *buffer, const jsmntok_t *tok,
struct amount_sat *sat)
{
return parse_amount_sat(sat, buffer + tok->start, tok->end - tok->start);
}
bool json_to_sat_or_all(const char *buffer, const jsmntok_t *tok,
struct amount_sat *sat)
{
if (json_tok_streq(buffer, tok, "all")) {
*sat = AMOUNT_SAT(-1ULL);
return true;
}
return json_to_sat(buffer, tok, sat);
}
bool json_to_short_channel_id(const char *buffer, const jsmntok_t *tok,
struct short_channel_id *scid)
{
return (short_channel_id_from_str(buffer + tok->start,
tok->end - tok->start, scid));
}
bool json_to_txid(const char *buffer, const jsmntok_t *tok,
struct bitcoin_txid *txid)
{
return bitcoin_txid_from_hex(buffer + tok->start,
tok->end - tok->start, txid);
}
bool json_to_outpoint(const char *buffer, const jsmntok_t *tok,
struct bitcoin_outpoint *op)
{
jsmntok_t t1, t2;
if (!split_tok(buffer, tok, ':', &t1, &t2))
return false;
return json_to_txid(buffer, &t1, &op->txid)
&& json_to_u32(buffer, &t2, &op->n);
}
bool json_to_channel_id(const char *buffer, const jsmntok_t *tok,
struct channel_id *cid)
{
return hex_decode(buffer + tok->start, tok->end - tok->start,
cid, sizeof(*cid));
}
bool json_to_coin_mvt_tag(const char *buffer, const jsmntok_t *tok,
enum mvt_tag *tag)
{
enum mvt_tag i_tag;
for (size_t i = 0; i < NUM_MVT_TAGS; i++) {
i_tag = (enum mvt_tag) i;
if (json_tok_streq(buffer, tok, mvt_tag_str(i_tag))) {
*tag = i_tag;
return true;
}
}
return false;
}
bool split_tok(const char *buffer, const jsmntok_t *tok,
char split,
jsmntok_t *a,
jsmntok_t *b)
{
const char *p = memchr(buffer + tok->start, split, tok->end - tok->start);
if (!p)
return false;
*a = *b = *tok;
a->end = p - buffer;
b->start = p + 1 - buffer;
return true;
}
bool json_to_secret(const char *buffer, const jsmntok_t *tok, struct secret *dest)
{
return hex_decode(buffer + tok->start, tok->end - tok->start,
dest->data, sizeof(struct secret));
}
bool json_to_preimage(const char *buffer, const jsmntok_t *tok, struct preimage *preimage)
{
size_t hexlen = tok->end - tok->start;
return hex_decode(buffer + tok->start, hexlen, preimage->r, sizeof(preimage->r));
}
struct wally_psbt *json_to_psbt(const tal_t *ctx, const char *buffer,
const jsmntok_t *tok)
{
return psbt_from_b64(ctx, buffer + tok->start, tok->end - tok->start);
}
struct tlv_obs2_onionmsg_payload_reply_path *
json_to_obs2_reply_path(const tal_t *ctx, const char *buffer, const jsmntok_t *tok)
{
struct tlv_obs2_onionmsg_payload_reply_path *rpath;
const jsmntok_t *hops, *t;
size_t i;
const char *err;
rpath = tal(ctx, struct tlv_obs2_onionmsg_payload_reply_path);
err = json_scan(tmpctx, buffer, tok, "{blinding:%,first_node_id:%}",
JSON_SCAN(json_to_pubkey, &rpath->blinding),
JSON_SCAN(json_to_pubkey, &rpath->first_node_id),
NULL);
if (err)
return tal_free(rpath);
hops = json_get_member(buffer, tok, "hops");
if (!hops || hops->size < 1)
return tal_free(rpath);
rpath->path = tal_arr(rpath, struct onionmsg_path *, hops->size);
json_for_each_arr(i, t, hops) {
rpath->path[i] = tal(rpath->path, struct onionmsg_path);
err = json_scan(tmpctx, buffer, t, "{id:%,encrypted_recipient_data:%}",
JSON_SCAN(json_to_pubkey,
&rpath->path[i]->node_id),
JSON_SCAN_TAL(rpath->path[i],
json_tok_bin_from_hex,
&rpath->path[i]->encrypted_recipient_data));
if (err)
return tal_free(rpath);
}
return rpath;
}
struct tlv_onionmsg_payload_reply_path *
json_to_reply_path(const tal_t *ctx, const char *buffer, const jsmntok_t *tok)
{
struct tlv_onionmsg_payload_reply_path *rpath;
const jsmntok_t *hops, *t;
size_t i;
const char *err;
rpath = tal(ctx, struct tlv_onionmsg_payload_reply_path);
err = json_scan(tmpctx, buffer, tok, "{blinding:%,first_node_id:%}",
JSON_SCAN(json_to_pubkey, &rpath->blinding),
JSON_SCAN(json_to_pubkey, &rpath->first_node_id),
NULL);
if (err)
return tal_free(rpath);
hops = json_get_member(buffer, tok, "hops");
if (!hops || hops->size < 1)
return tal_free(rpath);
rpath->path = tal_arr(rpath, struct onionmsg_path *, hops->size);
json_for_each_arr(i, t, hops) {
rpath->path[i] = tal(rpath->path, struct onionmsg_path);
err = json_scan(tmpctx, buffer, t, "{id:%,encrypted_recipient_data:%}",
JSON_SCAN(json_to_pubkey,
&rpath->path[i]->node_id),
JSON_SCAN_TAL(rpath->path[i],
json_tok_bin_from_hex,
&rpath->path[i]->encrypted_recipient_data));
if (err)
return tal_free(rpath);
}
return rpath;
}

156
common/json_parse.h Normal file
View File

@@ -0,0 +1,156 @@
#ifndef LIGHTNING_COMMON_JSON_PARSE_H
#define LIGHTNING_COMMON_JSON_PARSE_H
#include "config.h"
#include <ccan/crypto/sha256/sha256.h>
#include <common/coin_mvt.h>
#include <common/errcode.h>
/* Simple helpers are here: this file contains heavier ones */
#include <common/json_parse_simple.h>
struct json_escape;
struct json_stream;
struct timeabs;
struct timespec;
struct preimage;
struct secret;
struct pubkey;
struct node_id;
struct short_channel_id;
struct amount_sat;
struct amount_msat;
struct bitcoin_txid;
struct bitcoin_outpoint;
struct channel_id;
/* Decode a hex-encoded binary */
u8 *json_tok_bin_from_hex(const tal_t *ctx, const char *buffer, const jsmntok_t *tok);
/* Extract number from this (may be a string, or a number literal) */
bool json_to_number(const char *buffer, const jsmntok_t *tok,
unsigned int *num);
/* Extract signed 64 bit integer from this (may be a string, or a number literal) */
bool json_to_s64(const char *buffer, const jsmntok_t *tok, s64 *num);
/* Extract number from this (may be a string, or a number literal) */
bool json_to_u16(const char *buffer, const jsmntok_t *tok,
uint16_t *num);
bool json_to_sha256(const char *buffer, const jsmntok_t *tok, struct sha256 *dest);
/*
* Extract a non-negative (either 0 or positive) floating-point number from this
* (must be a number literal), multiply it by 1 million and return it as an
* integer. Any fraction smaller than 0.000001 is ignored.
*/
bool json_to_millionths(const char *buffer, const jsmntok_t *tok,
u64 *millionths);
/* Extract signed integer from this (may be a string, or a number literal) */
bool json_to_int(const char *buffer, const jsmntok_t *tok, int *num);
/* Extract an error code from this (may be a string, or a number literal) */
bool json_to_errcode(const char *buffer, const jsmntok_t *tok, errcode_t *errcode);
/* Split a json token into 2 tokens given a splitting character */
bool split_tok(const char *buffer, const jsmntok_t *tok,
char split,
jsmntok_t *a,
jsmntok_t *b);
/* Decode a hex-encoded payment preimage */
bool json_to_preimage(const char *buffer, const jsmntok_t *tok, struct preimage *preimage);
/* Extract a secret from this. */
bool json_to_secret(const char *buffer, const jsmntok_t *tok, struct secret *dest);
/* Extract a psbt from this. */
struct wally_psbt *json_to_psbt(const tal_t *ctx, const char *buffer,
const jsmntok_t *tok);
/* Extract a pubkey from this */
bool json_to_pubkey(const char *buffer, const jsmntok_t *tok,
struct pubkey *pubkey);
/* Extract node_id from this: makes sure *id is valid! */
bool json_to_node_id(const char *buffer, const jsmntok_t *tok,
struct node_id *id);
/* Extract satoshis from this (may be a string, or a decimal number literal) */
bool json_to_bitcoin_amount(const char *buffer, const jsmntok_t *tok,
uint64_t *satoshi);
/* Extract a short_channel_id from this */
bool json_to_short_channel_id(const char *buffer, const jsmntok_t *tok,
struct short_channel_id *scid);
/* Extract a satoshis amount from this */
bool json_to_sat(const char *buffer, const jsmntok_t *tok,
struct amount_sat *sat);
/* Extract a satoshis amount from this */
/* If the string is "all", set amonut as AMOUNT_SAT(-1ULL). */
bool json_to_sat_or_all(const char *buffer, const jsmntok_t *tok,
struct amount_sat *sat);
/* Extract a millisatoshis amount from this */
bool json_to_msat(const char *buffer, const jsmntok_t *tok,
struct amount_msat *msat);
/* Extract a bitcoin txid from this */
bool json_to_txid(const char *buffer, const jsmntok_t *tok,
struct bitcoin_txid *txid);
/* Extract a bitcoin outpoint from this */
bool json_to_outpoint(const char *buffer, const jsmntok_t *tok,
struct bitcoin_outpoint *op);
/* Extract a channel id from this */
bool json_to_channel_id(const char *buffer, const jsmntok_t *tok,
struct channel_id *cid);
/* Extract a coin movement 'tag' from this */
bool json_to_coin_mvt_tag(const char *buffer, const jsmntok_t *tok,
enum mvt_tag *tag);
/* Extract reply path from this JSON */
struct tlv_onionmsg_payload_reply_path *
json_to_reply_path(const tal_t *ctx, const char *buffer, const jsmntok_t *tok);
/* Obsolete version! */
struct tlv_obs2_onionmsg_payload_reply_path *
json_to_obs2_reply_path(const tal_t *ctx, const char *buffer, const jsmntok_t *tok);
/* Guide is % for a token: each must be followed by JSON_SCAN().
* Returns NULL on error (asserts() on bad guide). */
const char *json_scan(const tal_t *ctx,
const char *buffer,
const jsmntok_t *tok,
const char *guide,
...);
/* eg. JSON_SCAN(json_to_bool, &boolvar) */
#define JSON_SCAN(fmt, var) \
json_scan, \
stringify(fmt), \
((var) + 0*sizeof(fmt((const char *)NULL, \
(const jsmntok_t *)NULL, var) == true)), \
(fmt)
/* eg. JSON_SCAN_TAL(tmpctx, json_strdup, &charvar) */
#define JSON_SCAN_TAL(ctx, fmt, var) \
(ctx), \
stringify(fmt), \
((var) + 0*sizeof((*var) = fmt((ctx), \
(const char *)NULL, \
(const jsmntok_t *)NULL))), \
(fmt)
/* Already-have-varargs version */
const char *json_scanv(const tal_t *ctx,
const char *buffer,
const jsmntok_t *tok,
const char *guide,
va_list ap);
#endif /* LIGHTNING_COMMON_JSON_PARSE_H */

552
common/json_parse_simple.c Normal file
View File

@@ -0,0 +1,552 @@
/* JSON core and helpers */
#include "config.h"
#include <assert.h>
#include <ccan/mem/mem.h>
#include <ccan/tal/str/str.h>
#include <common/json_parse_simple.h>
#include <common/utils.h>
#include <errno.h>
#include <inttypes.h>
#include <stdio.h>
#include <wire/onion_wire.h>
const char *json_tok_full(const char *buffer, const jsmntok_t *t)
{
if (t->type == JSMN_STRING)
return buffer + t->start - 1;
return buffer + t->start;
}
/* Include " if it's a string. */
int json_tok_full_len(const jsmntok_t *t)
{
if (t->type == JSMN_STRING)
return t->end - t->start + 2;
return t->end - t->start;
}
bool json_tok_strneq(const char *buffer, const jsmntok_t *tok,
const char *str, size_t len)
{
if (tok->type != JSMN_STRING)
return false;
return memeq(buffer + tok->start, tok->end - tok->start, str, len);
}
bool json_tok_streq(const char *buffer, const jsmntok_t *tok, const char *str)
{
return json_tok_strneq(buffer, tok, str, strlen(str));
}
bool json_tok_startswith(const char *buffer, const jsmntok_t *tok,
const char *prefix)
{
if (tok->type != JSMN_STRING)
return false;
if (tok->end - tok->start < strlen(prefix))
return false;
return memcmp(buffer + tok->start,
prefix, strlen(prefix)) == 0;
}
bool json_tok_endswith(const char *buffer, const jsmntok_t *tok,
const char *suffix)
{
if (tok->type != JSMN_STRING)
return false;
if (tok->end - tok->start < strlen(suffix))
return false;
return memcmp(buffer + tok->end - strlen(suffix),
suffix, strlen(suffix)) == 0;
}
char *json_strdup(const tal_t *ctx, const char *buffer, const jsmntok_t *tok)
{
return tal_strndup(ctx, buffer + tok->start, tok->end - tok->start);
}
bool json_to_u64(const char *buffer, const jsmntok_t *tok, u64 *num)
{
char *end;
unsigned long long l;
l = strtoull(buffer + tok->start, &end, 0);
if (end != buffer + tok->end)
return false;
BUILD_ASSERT(sizeof(l) >= sizeof(*num));
*num = l;
/* Check for overflow */
if (l == ULLONG_MAX && errno == ERANGE)
return false;
if (*num != l)
return false;
return true;
}
bool json_to_u32(const char *buffer, const jsmntok_t *tok, u32 *num)
{
uint64_t u64;
if (!json_to_u64(buffer, tok, &u64))
return false;
*num = u64;
/* Just in case it doesn't fit. */
if (*num != u64)
return false;
return true;
}
bool json_to_bool(const char *buffer, const jsmntok_t *tok, bool *b)
{
if (tok->type != JSMN_PRIMITIVE)
return false;
if (memeqstr(buffer + tok->start, tok->end - tok->start, "true")) {
*b = true;
return true;
}
if (memeqstr(buffer + tok->start, tok->end - tok->start, "false")) {
*b = false;
return true;
}
return false;
}
bool json_tok_is_num(const char *buffer, const jsmntok_t *tok)
{
if (tok->type != JSMN_PRIMITIVE)
return false;
for (int i = tok->start; i < tok->end; i++)
if (!cisdigit(buffer[i]))
return false;
return true;
}
bool json_tok_is_null(const char *buffer, const jsmntok_t *tok)
{
if (tok->type != JSMN_PRIMITIVE)
return false;
return buffer[tok->start] == 'n';
}
const jsmntok_t *json_next(const jsmntok_t *tok)
{
const jsmntok_t *t;
size_t i;
for (t = tok + 1, i = 0; i < tok->size; i++)
t = json_next(t);
return t;
}
const jsmntok_t *json_get_membern(const char *buffer,
const jsmntok_t tok[],
const char *label, size_t len)
{
const jsmntok_t *t;
size_t i;
if (tok->type != JSMN_OBJECT)
return NULL;
json_for_each_obj(i, t, tok)
if (json_tok_strneq(buffer, t, label, len))
return t + 1;
return NULL;
}
const jsmntok_t *json_get_member(const char *buffer, const jsmntok_t tok[],
const char *label)
{
return json_get_membern(buffer, tok, label, strlen(label));
}
const jsmntok_t *json_get_arr(const jsmntok_t tok[], size_t index)
{
const jsmntok_t *t;
size_t i;
if (tok->type != JSMN_ARRAY)
return NULL;
json_for_each_arr(i, t, tok) {
if (index == 0)
return t;
index--;
}
return NULL;
}
/*-----------------------------------------------------------------------------
JSMN Result Validation Starts
-----------------------------------------------------------------------------*/
/*~ LIBJSMN is a fast, small JSON parsing library.
*
* "Fast, small" means it does not, in fact, do a
* lot of checking for invalid JSON.
*
* For example, by itself it would accept the strings
* `{"1" "2" "3" "4"}` and `["key": 1 2 3 4]` as valid.
* Obviously those are not in any way valid JSON.
*
* This part of the code performs some filtering so
* that at least some of the invalid JSON that
* LIBJSMN accepts, will be rejected by
* json_parse_input. It also checks that strings are valid UTF-8.
*/
/*~ These functions are used in JSMN validation.
*
* The calling convention is that the "current" token
* is passed in as the first argument, and after the
* validator, is returned from the function.
*
* p = validate_jsmn_datum(p, end, valid);
*
* The reason has to do with typical C ABIs.
* Usually, the first few arguments are passed in via
* register, and the return value is also returned
* via register.
* This calling convention generally ensures that
* the current token pointer `p` is always in a
* register and is never forced into memory by the
* compiler.
*
* These functions are pre-declared here as they
* are interrecursive.
* Note that despite the recursion, `p` is only ever
* advanced, and there is only ever one `p` value,
* thus the overall algorithm is strict O(n)
* (*not* amortized) in time.
* The recursion does mean the algorithm is O(d)
* in memory (specifically stack frames), where d
* is the nestedness of objects in the input.
* This may become an issue later if we are in a
* stack-limited environment, such as if we actually
* went and used threads.
*/
/* Validate a *single* datum. */
static const jsmntok_t *
validate_jsmn_datum(const char *buf,
const jsmntok_t *p,
const jsmntok_t *end,
bool *valid);
/*~ Validate a key-value pair.
*
* In JSMN, objects are not dictionaries.
* Instead, they are a sequence of datums.
*
* In fact, objects and arrays in JSMN are "the same",
* they only differ in delimiter characters.
*
* Of course, in "real" JSON, an object is a dictionary
* of key-value pairs.
*
* So what JSMN does is that the syntax "key": "value"
* is considered a *single* datum, a string "key"
* that contains a value "value".
*
* Indeed, JSMN accepts `["key": "value"]` as well as
* `{"item1", "item2"}`.
* The entire point of the validate_jsmn_result function
* is to reject such improper arrays and objects.
*/
static const jsmntok_t *
validate_jsmn_keyvalue(const char *buf,
const jsmntok_t *p,
const jsmntok_t *end,
bool *valid);
static const jsmntok_t *
validate_jsmn_datum(const char *buf,
const jsmntok_t *p,
const jsmntok_t *end,
bool *valid)
{
int i;
int sz;
if (p >= end) {
*valid = false;
return p;
}
switch (p->type) {
case JSMN_STRING:
if (!utf8_check(buf + p->start, p->end - p->start))
*valid = false;
/* Fall thru */
case JSMN_UNDEFINED:
case JSMN_PRIMITIVE:
/* These types should not have sub-datums. */
if (p->size != 0)
*valid = false;
else
++p;
break;
case JSMN_ARRAY:
/* Save the array size; we will advance p. */
sz = p->size;
++p;
for (i = 0; i < sz; ++i) {
/* Arrays should only contain standard JSON datums. */
p = validate_jsmn_datum(buf, p, end, valid);
if (!*valid)
break;
}
break;
case JSMN_OBJECT:
/* Save the object size; we will advance p. */
sz = p->size;
++p;
for (i = 0; i < sz; ++i) {
/* Objects should only contain key-value pairs. */
p = validate_jsmn_keyvalue(buf, p, end, valid);
if (!*valid)
break;
}
break;
default:
*valid = false;
break;
}
return p;
}
/* Key-value pairs *must* be strings with size 1. */
static inline const jsmntok_t *
validate_jsmn_keyvalue(const char *buf,
const jsmntok_t *p,
const jsmntok_t *end,
bool *valid)
{
if (p >= end) {
*valid = false;
return p;
}
/* Check key.
*
* JSMN parses the syntax `"key": "value"` as a
* JSMN_STRING of size 1, containing the value
* datum as a sub-datum.
*
* Thus, keys in JSON objects are really strings
* that "contain" the value, thus we check if
* the size is 1.
*
* JSMN supports a non-standard syntax such as
* `"key": 1 2 3 4`, which it considers as a
* string object that contains a sequence of
* sub-datums 1 2 3 4.
* The check below that p->size == 1 also
* incidentally rejects that non-standard
* JSON.
*/
if (p->type != JSMN_STRING || p->size != 1
|| !utf8_check(buf + p->start, p->end - p->start)) {
*valid = false;
return p;
}
++p;
return validate_jsmn_datum(buf, p, end, valid);
}
/** validate_jsmn_parse_output
*
* @brief Validates the result of jsmn_parse.
*
* @desc LIBJMSN is a small fast library, not a
* comprehensive library.
*
* This simply means that LIBJSMN will accept a
* *lot* of very strange text that is technically
* not JSON.
*
* For example, LIBJSMN would accept the strings
* `{"1" "2" "3" "4"}` and `["key": 1 2 3 4]` as valid.
*
* This can lead to strange sequences of jsmntok_t
* objects.
* Unfortunately, most of our code assumes that
* the data fed into our JSON-RPC interface is
* valid JSON, and in particular is not invalid
* JSON that tickles LIBJSMN into emitting
* strange sequences of `jsmntok_t`.
*
* This function detects such possible problems
* and returns false if such an issue is found.
* If so, it is probably unsafe to pass the
* `jsmntok_t` generated by LIBJSMN to any other
* parts of our code.
*
* @param p - The first jsmntok_t token to process.
* This function does not assume that semantically
* only one JSON datum is processed; it does expect
* a sequence of complete JSON datums (which is
* what LIBJSMN *should* output).
* @param end - One past the end of jsmntok_t.
* Basically, this function is assured to read tokens
* starting at p up to end - 1.
* If p >= end, this will not validate anything and
* trivially return true.
*
* @return true if there appears to be no problem
* with the jsmntok_t sequence outputted by
* `jsmn_parse`, false otherwise.
*/
static bool
validate_jsmn_parse_output(const char *buf,
const jsmntok_t *p, const jsmntok_t *end)
{
bool valid = true;
while (p < end && valid)
p = validate_jsmn_datum(buf, p, end, &valid);
return valid;
}
/*-----------------------------------------------------------------------------
JSMN Result Validation Ends
-----------------------------------------------------------------------------*/
void toks_reset(jsmntok_t *toks)
{
assert(tal_count(toks) >= 1);
toks[0].type = JSMN_UNDEFINED;
}
jsmntok_t *toks_alloc(const tal_t *ctx)
{
jsmntok_t *toks = tal_arr(ctx, jsmntok_t, 10);
toks_reset(toks);
return toks;
}
bool json_parse_input(jsmn_parser *parser,
jsmntok_t **toks,
const char *input, int len,
bool *complete)
{
int ret;
again:
ret = jsmn_parse(parser, input, len, *toks, tal_count(*toks) - 1);
switch (ret) {
case JSMN_ERROR_INVAL:
return false;
case JSMN_ERROR_NOMEM:
tal_resize(toks, tal_count(*toks) * 2);
goto again;
}
/* Check whether we read at least one full root element, i.e., root
* element has its end set. */
if ((*toks)[0].type == JSMN_UNDEFINED || (*toks)[0].end == -1) {
*complete = false;
return true;
}
/* If we read a partial element at the end of the stream we'll get a
* ret=JSMN_ERROR_PART, but due to the previous check we know we read at
* least one full element, so count tokens that are part of this root
* element. */
ret = json_next(*toks) - *toks;
if (!validate_jsmn_parse_output(input, *toks, *toks + ret))
return false;
/* Cut to length and return. */
tal_resize(toks, ret + 1);
/* Make sure last one is always referenceable. */
(*toks)[ret].type = -1;
(*toks)[ret].start = (*toks)[ret].end = (*toks)[ret].size = 0;
*complete = true;
return true;
}
jsmntok_t *json_parse_simple(const tal_t *ctx, const char *input, int len)
{
bool complete;
jsmn_parser parser;
jsmntok_t *toks = toks_alloc(ctx);
jsmn_init(&parser);
if (!json_parse_input(&parser, &toks, input, len, &complete)
|| !complete)
return tal_free(toks);
return toks;
}
const char *jsmntype_to_string(jsmntype_t t)
{
switch (t) {
case JSMN_UNDEFINED :
return "UNDEFINED";
case JSMN_OBJECT :
return "OBJECT";
case JSMN_ARRAY :
return "ARRAY";
case JSMN_STRING :
return "STRING";
case JSMN_PRIMITIVE :
return "PRIMITIVE";
}
return "INVALID";
}
jsmntok_t *json_tok_copy(const tal_t *ctx, const jsmntok_t *tok)
{
return tal_dup_arr(ctx, jsmntok_t, tok, json_next(tok) - tok, 0);
}
void json_tok_remove(jsmntok_t **tokens,
jsmntok_t *obj_or_array, const jsmntok_t *tok, size_t num)
{
const jsmntok_t *src = tok;
const jsmntok_t *end = json_next(*tokens);
jsmntok_t *dest = *tokens + (tok - *tokens);
int remove_count;
assert(*tokens);
assert(obj_or_array->type == JSMN_ARRAY
|| obj_or_array->type == JSMN_OBJECT);
/* obj_or_array must be inside tokens, and tok must be inside
* obj_or_array */
assert(obj_or_array >= *tokens
&& obj_or_array < *tokens + tal_count(*tokens));
assert(tok >= obj_or_array
&& tok < *tokens + tal_count(*tokens));
for (int i = 0; i < num; i++)
src = json_next(src);
/* Don't give us a num which goes over end of obj_or_array. */
assert(src <= json_next(obj_or_array));
remove_count = src - tok;
memmove(dest, src, sizeof(jsmntok_t) * (end - src));
/* Subtract first: this ptr may move after tal_resize! */
obj_or_array->size -= num;
tal_resize(tokens, tal_count(*tokens) - remove_count);
}

122
common/json_parse_simple.h Normal file
View File

@@ -0,0 +1,122 @@
/* Very simple core JSON parse helpers: used by lightning-cli too */
#ifndef LIGHTNING_COMMON_JSON_PARSE_SIMPLE_H
#define LIGHTNING_COMMON_JSON_PARSE_SIMPLE_H
#include "config.h"
#include <ccan/short_types/short_types.h>
#include <ccan/tal/tal.h>
#define JSMN_STRICT 1
# include <external/jsmn/jsmn.h>
/* Include " if it's a string. */
const char *json_tok_full(const char *buffer, const jsmntok_t *t);
/* Include " if it's a string. */
int json_tok_full_len(const jsmntok_t *t);
/* Is this a string equal to str? */
bool json_tok_streq(const char *buffer, const jsmntok_t *tok, const char *str);
/* Is this a string equal to str of length len? */
bool json_tok_strneq(const char *buffer, const jsmntok_t *tok,
const char *str, size_t len);
/* Does this string token start with prefix? */
bool json_tok_startswith(const char *buffer, const jsmntok_t *tok,
const char *prefix);
/* Does this string token end with suffix? */
bool json_tok_endswith(const char *buffer, const jsmntok_t *tok,
const char *suffix);
/* Allocate a tal string copy */
char *json_strdup(const tal_t *ctx, const char *buffer, const jsmntok_t *tok);
/* Extract number from this (may be a string, or a number literal) */
bool json_to_u64(const char *buffer, const jsmntok_t *tok, u64 *num);
/* Extract number from this (may be a string, or a number literal) */
bool json_to_u32(const char *buffer, const jsmntok_t *tok, u32 *num);
/* Extract boolean from this */
bool json_to_bool(const char *buffer, const jsmntok_t *tok, bool *b);
/* Is this a number? [0..9]+ */
bool json_tok_is_num(const char *buffer, const jsmntok_t *tok);
/* Is this the null primitive? */
bool json_tok_is_null(const char *buffer, const jsmntok_t *tok);
/* Returns next token with same parent (WARNING: slow!). */
const jsmntok_t *json_next(const jsmntok_t *tok);
/* Get top-level member with explicit label len */
const jsmntok_t *json_get_membern(const char *buffer,
const jsmntok_t tok[],
const char *label, size_t len);
/* Get top-level member. */
const jsmntok_t *json_get_member(const char *buffer, const jsmntok_t tok[],
const char *label);
/* Get index'th array member. */
const jsmntok_t *json_get_arr(const jsmntok_t tok[], size_t index);
/* Allocate a starter array of tokens for json_parse_input */
jsmntok_t *toks_alloc(const tal_t *ctx);
/* Reset a token array to reuse it. */
void toks_reset(jsmntok_t *toks);
/**
* json_parse_input: parse and validate JSON.
* @parser: parser initialized with jsmn_init.
* @toks: tallocated array from toks_alloc()
* @input, @len: input string.
* @complete: set to true if the valid JSON is complete, or NULL if must be.
*
* This returns false if the JSON is invalid, true otherwise.
* If it returns true, *@complete indicates that (*@toks)[0] points to a
* valid, complete JSON element. If @complete is NULL, then incomplete
* JSON returns false (i.e. is considered invalid).
*
* *@toks is resized to the complete set of tokens, with a dummy
* terminator (type == -1) at the end.
*
* If it returns true, and *@complete is false, you can append more
* data to @input and call it again (with the same perser) and the parser
* will continue where it left off.
*/
bool json_parse_input(jsmn_parser *parser,
jsmntok_t **toks,
const char *input, int len,
bool *complete);
/* Simplified version of above which parses only a complete, valid
* JSON string */
jsmntok_t *json_parse_simple(const tal_t *ctx, const char *input, int len);
/* Convert a jsmntype_t enum to a human readable string. */
const char *jsmntype_to_string(jsmntype_t t);
/* Return a copy of a json value as an array. */
jsmntok_t *json_tok_copy(const tal_t *ctx, const jsmntok_t *tok);
/*
* Remove @num json values from a json array or object @obj. @tok points
* to the first value to remove. The array @tokens will be resized.
*/
void json_tok_remove(jsmntok_t **tokens,
jsmntok_t *obj_or_array, const jsmntok_t *tok, size_t num);
/* Iterator macro for array: i is counter, t is token ptr, arr is JSMN_ARRAY */
#define json_for_each_arr(i, t, arr) \
for (i = 0, t = (arr) + 1; i < (arr)->size; t = json_next(t), i++)
/* Iterator macro for object: i is counter, t is token ptr (t+1 is
* contents of obj member), obj is JSMN_OBJECT */
#define json_for_each_obj(i, t, obj) \
for (i = 0, t = (obj) + 1; i < (obj)->size; t = json_next(t+1), i++)
#endif /* LIGHTNING_COMMON_JSON_PARSE_SIMPLE_H */

View File

@@ -1,10 +1,28 @@
#include "config.h"
#include <arpa/inet.h>
#include <bitcoin/preimage.h>
#include <bitcoin/privkey.h>
#include <bitcoin/psbt.h>
#include <bitcoin/short_channel_id.h>
#include <bitcoin/signature.h>
#include <bitcoin/tx.h>
#include <ccan/io/io.h>
/* To reach into io_plan: not a public header! */
#include <ccan/io/backend.h>
#include <ccan/json_escape/json_escape.h>
#include <ccan/json_out/json_out.h>
#include <ccan/str/hex/hex.h>
#include <common/channel_id.h>
#include <common/configdir.h>
#include <common/json_parse.h>
#include <common/json_stream.h>
#include <common/node_id.h>
#include <common/type_to_string.h>
#include <common/utils.h>
#include <common/wireaddr.h>
#include <inttypes.h>
#include <stdio.h>
#include <wire/peer_wire.h>
static void adjust_io_write(struct json_out *jout,
ptrdiff_t delta,
@@ -204,3 +222,419 @@ struct io_plan *json_stream_output_(struct json_stream *js,
js->len_read = 0;
return json_stream_output_write(conn, js);
}
void json_add_num(struct json_stream *result, const char *fieldname, unsigned int value)
{
json_add_member(result, fieldname, false, "%u", value);
}
void json_add_u64(struct json_stream *result, const char *fieldname,
uint64_t value)
{
json_add_member(result, fieldname, false, "%"PRIu64, value);
}
void json_add_s64(struct json_stream *result, const char *fieldname,
int64_t value)
{
json_add_member(result, fieldname, false, "%"PRIi64, value);
}
void json_add_u32(struct json_stream *result, const char *fieldname,
uint32_t value)
{
json_add_member(result, fieldname, false, "%u", value);
}
void json_add_s32(struct json_stream *result, const char *fieldname,
int32_t value)
{
json_add_member(result, fieldname, false, "%d", value);
}
void json_add_literal(struct json_stream *result, const char *fieldname,
const char *literal, int len)
{
/* Literal may contain quotes, so bypass normal checks */
char *dest = json_member_direct(result, fieldname, len);
memcpy(dest, literal, len);
}
void json_add_stringn(struct json_stream *result, const char *fieldname,
const char *value TAKES, size_t value_len)
{
json_add_member(result, fieldname, true, "%.*s", (int)value_len, value);
if (taken(value))
tal_free(value);
}
void json_add_string(struct json_stream *result, const char *fieldname, const char *value TAKES)
{
json_add_stringn(result, fieldname, value, strlen(value));
}
void json_add_bool(struct json_stream *result, const char *fieldname, bool value)
{
json_add_member(result, fieldname, false, value ? "true" : "false");
}
void json_add_null(struct json_stream *stream, const char *fieldname)
{
json_add_member(stream, fieldname, false, "null");
}
void json_add_hex(struct json_stream *js, const char *fieldname,
const void *data, size_t len)
{
/* Size without NUL term */
size_t hexlen = hex_str_size(len) - 1;
char *dest;
dest = json_member_direct(js, fieldname, 1 + hexlen + 1);
dest[0] = '"';
if (!hex_encode(data, len, dest + 1, hexlen + 1))
abort();
dest[1+hexlen] = '"';
}
void json_add_hex_talarr(struct json_stream *result,
const char *fieldname,
const tal_t *data)
{
json_add_hex(result, fieldname, data, tal_bytelen(data));
}
void json_add_escaped_string(struct json_stream *result, const char *fieldname,
const struct json_escape *esc TAKES)
{
/* Already escaped, don't re-escape! */
char *dest = json_member_direct(result, fieldname,
1 + strlen(esc->s) + 1);
dest[0] = '"';
memcpy(dest + 1, esc->s, strlen(esc->s));
dest[1+strlen(esc->s)] = '"';
if (taken(esc))
tal_free(esc);
}
void json_add_timeabs(struct json_stream *result, const char *fieldname,
struct timeabs t)
{
json_add_member(result, fieldname, false, "%" PRIu64 ".%03" PRIu64,
(u64)t.ts.tv_sec, (u64)t.ts.tv_nsec / 1000000);
}
void json_add_time(struct json_stream *result, const char *fieldname,
struct timespec ts)
{
char timebuf[100];
snprintf(timebuf, sizeof(timebuf), "%lu.%09u",
(unsigned long)ts.tv_sec,
(unsigned)ts.tv_nsec);
json_add_string(result, fieldname, timebuf);
}
void json_add_timeiso(struct json_stream *result,
const char *fieldname,
struct timeabs *time)
{
char iso8601_msec_fmt[sizeof("YYYY-mm-ddTHH:MM:SS.%03dZ")];
char iso8601_s[sizeof("YYYY-mm-ddTHH:MM:SS.nnnZ")];
strftime(iso8601_msec_fmt, sizeof(iso8601_msec_fmt),
"%FT%T.%%03dZ", gmtime(&time->ts.tv_sec));
snprintf(iso8601_s, sizeof(iso8601_s),
iso8601_msec_fmt, (int) time->ts.tv_nsec / 1000000);
json_add_string(result, fieldname, iso8601_s);
}
void json_add_tok(struct json_stream *result, const char *fieldname,
const jsmntok_t *tok, const char *buffer)
{
char *space;
assert(tok->type != JSMN_UNDEFINED);
space = json_member_direct(result, fieldname, json_tok_full_len(tok));
memcpy(space, json_tok_full(buffer, tok), json_tok_full_len(tok));
}
void json_add_errcode(struct json_stream *result, const char *fieldname,
errcode_t code)
{
json_add_member(result, fieldname, false, "%"PRIerrcode, code);
}
void json_add_invstring(struct json_stream *result, const char *invstring)
{
if (strstarts(invstring, "lni"))
json_add_string(result, "bolt12", invstring);
else
json_add_string(result, "bolt11", invstring);
}
void json_add_node_id(struct json_stream *response,
const char *fieldname,
const struct node_id *id)
{
json_add_hex(response, fieldname, id->k, sizeof(id->k));
}
void json_add_channel_id(struct json_stream *response,
const char *fieldname,
const struct channel_id *cid)
{
json_add_hex(response, fieldname, cid->id, sizeof(cid->id));
}
void json_add_pubkey(struct json_stream *response,
const char *fieldname,
const struct pubkey *key)
{
u8 der[PUBKEY_CMPR_LEN];
pubkey_to_der(der, key);
json_add_hex(response, fieldname, der, sizeof(der));
}
void json_add_point32(struct json_stream *response,
const char *fieldname,
const struct point32 *key)
{
u8 output[32];
secp256k1_xonly_pubkey_serialize(secp256k1_ctx, output, &key->pubkey);
json_add_hex(response, fieldname, output, sizeof(output));
}
void json_add_bip340sig(struct json_stream *response,
const char *fieldname,
const struct bip340sig *sig)
{
json_add_hex(response, fieldname, sig->u8, sizeof(sig->u8));
}
void json_add_txid(struct json_stream *result, const char *fieldname,
const struct bitcoin_txid *txid)
{
char hex[hex_str_size(sizeof(*txid))];
bitcoin_txid_to_hex(txid, hex, sizeof(hex));
json_add_string(result, fieldname, hex);
}
void json_add_outpoint(struct json_stream *result, const char *fieldname,
const struct bitcoin_outpoint *out)
{
char hex[hex_str_size(sizeof(out->txid))];
bitcoin_txid_to_hex(&out->txid, hex, sizeof(hex));
json_add_member(result, fieldname, true, "%s:%d", hex, out->n);
}
void json_add_short_channel_id(struct json_stream *response,
const char *fieldname,
const struct short_channel_id *scid)
{
json_add_member(response, fieldname, true, "%dx%dx%d",
short_channel_id_blocknum(scid),
short_channel_id_txnum(scid),
short_channel_id_outnum(scid));
}
void json_add_address(struct json_stream *response, const char *fieldname,
const struct wireaddr *addr)
{
json_object_start(response, fieldname);
if (addr->type == ADDR_TYPE_IPV4) {
char addrstr[INET_ADDRSTRLEN];
inet_ntop(AF_INET, addr->addr, addrstr, INET_ADDRSTRLEN);
json_add_string(response, "type", "ipv4");
json_add_string(response, "address", addrstr);
json_add_num(response, "port", addr->port);
} else if (addr->type == ADDR_TYPE_IPV6) {
char addrstr[INET6_ADDRSTRLEN];
inet_ntop(AF_INET6, addr->addr, addrstr, INET6_ADDRSTRLEN);
json_add_string(response, "type", "ipv6");
json_add_string(response, "address", addrstr);
json_add_num(response, "port", addr->port);
} else if (addr->type == ADDR_TYPE_TOR_V2_REMOVED) {
json_add_string(response, "type", "torv2");
json_add_string(response, "address", fmt_wireaddr_without_port(tmpctx, addr));
json_add_num(response, "port", addr->port);
} else if (addr->type == ADDR_TYPE_TOR_V3) {
json_add_string(response, "type", "torv3");
json_add_string(response, "address", fmt_wireaddr_without_port(tmpctx, addr));
json_add_num(response, "port", addr->port);
} else if (addr->type == ADDR_TYPE_DNS) {
json_add_string(response, "type", "dns");
json_add_string(response, "address", fmt_wireaddr_without_port(tmpctx, addr));
json_add_num(response, "port", addr->port);
} else if (addr->type == ADDR_TYPE_WEBSOCKET) {
json_add_string(response, "type", "websocket");
json_add_num(response, "port", addr->port);
}
json_object_end(response);
}
void json_add_address_internal(struct json_stream *response,
const char *fieldname,
const struct wireaddr_internal *addr)
{
switch (addr->itype) {
case ADDR_INTERNAL_SOCKNAME:
json_object_start(response, fieldname);
json_add_string(response, "type", "local socket");
json_add_string(response, "socket", addr->u.sockname);
json_object_end(response);
return;
case ADDR_INTERNAL_ALLPROTO:
json_object_start(response, fieldname);
json_add_string(response, "type", "any protocol");
json_add_num(response, "port", addr->u.port);
json_object_end(response);
return;
case ADDR_INTERNAL_AUTOTOR:
json_object_start(response, fieldname);
json_add_string(response, "type", "Tor generated address");
json_add_address(response, "service", &addr->u.torservice.address);
json_object_end(response);
return;
case ADDR_INTERNAL_STATICTOR:
json_object_start(response, fieldname);
json_add_string(response, "type", "Tor from blob generated static address");
json_add_address(response, "service", &addr->u.torservice.address);
json_object_end(response);
return;
case ADDR_INTERNAL_FORPROXY:
json_object_start(response, fieldname);
json_add_string(response, "type", "unresolved");
json_add_string(response, "name", addr->u.unresolved.name);
json_add_num(response, "port", addr->u.unresolved.port);
json_object_end(response);
return;
case ADDR_INTERNAL_WIREADDR:
json_add_address(response, fieldname, &addr->u.wireaddr);
return;
}
abort();
}
void json_add_tx(struct json_stream *result,
const char *fieldname,
const struct bitcoin_tx *tx)
{
json_add_hex_talarr(result, fieldname, linearize_tx(tmpctx, tx));
}
void json_add_psbt(struct json_stream *stream,
const char *fieldname,
const struct wally_psbt *psbt TAKES)
{
const char *psbt_b64;
psbt_b64 = psbt_to_b64(NULL, psbt);
json_add_string(stream, fieldname, take(psbt_b64));
if (taken(psbt))
tal_free(psbt);
}
void json_add_amount_msat_compat(struct json_stream *result,
struct amount_msat msat,
const char *rawfieldname,
const char *msatfieldname)
{
if (deprecated_apis)
json_add_u64(result, rawfieldname, msat.millisatoshis); /* Raw: low-level helper */
json_add_amount_msat_only(result, msatfieldname, msat);
}
void json_add_amount_msat_only(struct json_stream *result,
const char *msatfieldname,
struct amount_msat msat)
{
if (!deprecated_apis)
assert(strends(msatfieldname, "_msat"));
if (deprecated_apis)
json_add_string(result, msatfieldname,
type_to_string(tmpctx, struct amount_msat, &msat));
else
json_add_u64(result, msatfieldname, msat.millisatoshis); /* Raw: low-level helper */
}
void json_add_amount_sat_compat(struct json_stream *result,
struct amount_sat sat,
const char *rawfieldname,
const char *msatfieldname)
{
if (deprecated_apis)
json_add_u64(result, rawfieldname, sat.satoshis); /* Raw: low-level helper */
json_add_amount_sat_msat(result, msatfieldname, sat);
}
void json_add_amount_sat_msat(struct json_stream *result,
const char *msatfieldname,
struct amount_sat sat)
{
struct amount_msat msat;
assert(strends(msatfieldname, "_msat"));
if (amount_sat_to_msat(&msat, sat))
json_add_amount_msat_only(result, msatfieldname, msat);
}
/* When I noticed that we were adding "XXXmsat" fields *not* ending in _msat */
void json_add_amount_sats_deprecated(struct json_stream *result,
const char *fieldname,
const char *msatfieldname,
struct amount_sat sat)
{
if (deprecated_apis) {
struct amount_msat msat;
assert(!strends(fieldname, "_msat"));
if (amount_sat_to_msat(&msat, sat))
json_add_string(result, fieldname,
take(fmt_amount_msat(NULL, msat)));
}
json_add_amount_sat_msat(result, msatfieldname, sat);
}
void json_add_sats(struct json_stream *result,
const char *fieldname,
struct amount_sat sat)
{
json_add_string(result, fieldname, take(fmt_amount_sat(NULL, sat)));
}
void json_add_secret(struct json_stream *response, const char *fieldname,
const struct secret *secret)
{
json_add_hex(response, fieldname, secret, sizeof(struct secret));
}
void json_add_sha256(struct json_stream *result, const char *fieldname,
const struct sha256 *hash)
{
json_add_hex(result, fieldname, hash, sizeof(*hash));
}
void json_add_preimage(struct json_stream *result, const char *fieldname,
const struct preimage *preimage)
{
json_add_hex(result, fieldname, preimage, sizeof(*preimage));
}
void json_add_lease_rates(struct json_stream *result,
const struct lease_rates *rates)
{
json_add_amount_sat_msat(result, "lease_fee_base_msat",
amount_sat(rates->lease_fee_base_sat));
json_add_num(result, "lease_fee_basis", rates->lease_fee_basis);
json_add_num(result, "funding_weight", rates->funding_weight);
json_add_amount_msat_only(result,
"channel_fee_max_base_msat",
amount_msat(rates->channel_fee_max_base_msat));
json_add_num(result, "channel_fee_max_proportional_thousandths",
rates->channel_fee_max_proportional_thousandths);
}

View File

@@ -4,11 +4,36 @@
#ifndef LIGHTNING_COMMON_JSON_STREAM_H
#define LIGHTNING_COMMON_JSON_STREAM_H
#include "config.h"
#define JSMN_STRICT 1
# include <external/jsmn/jsmn.h>
#include <ccan/short_types/short_types.h>
#include <ccan/tal/tal.h>
#include <ccan/time/time.h>
#include <common/amount.h>
#include <common/errcode.h>
struct command;
struct io_conn;
struct log;
struct json_escape;
struct pubkey;
struct point32;
struct bip340sig;
struct secret;
struct node_id;
struct channel_id;
struct bitcoin_txid;
struct bitcoin_outpoint;
struct short_channel_id;
struct sha256;
struct preimage;
struct bitcoin_tx;
struct wally_psbt;
struct lease_rates;
struct wireaddr;
struct wireaddr_internal;
struct json_stream {
struct json_out *jout;
@@ -146,4 +171,196 @@ struct io_plan *json_stream_output_(struct json_stream *js,
void json_stream_double_cr(struct json_stream *js);
void json_stream_flush(struct json_stream *js);
/* '"fieldname" : "value"' or '"value"' if fieldname is NULL. Turns
* any non-printable chars into JSON escapes, but leaves existing escapes alone.
*/
void json_add_string(struct json_stream *result, const char *fieldname, const char *value);
/* '"fieldname" : "value[:value_len]"' or '"value[:value_len]"' if
* fieldname is NULL. Turns any non-printable chars into JSON
* escapes, but leaves existing escapes alone.
*/
void json_add_stringn(struct json_stream *result, const char *fieldname,
const char *value TAKES, size_t value_len);
/* '"fieldname" : "value"' or '"value"' if fieldname is NULL. String must
* already be JSON escaped as necessary. */
void json_add_escaped_string(struct json_stream *result,
const char *fieldname,
const struct json_escape *esc TAKES);
/* '"fieldname" : literal' or 'literal' if fieldname is NULL*/
void json_add_literal(struct json_stream *result, const char *fieldname,
const char *literal, int len);
/* '"fieldname" : value' or 'value' if fieldname is NULL */
void json_add_num(struct json_stream *result, const char *fieldname,
unsigned int value);
/* '"fieldname" : value' or 'value' if fieldname is NULL */
void json_add_u64(struct json_stream *result, const char *fieldname,
uint64_t value);
/* '"fieldname" : value' or 'value' if fieldname is NULL */
void json_add_s64(struct json_stream *result, const char *fieldname,
int64_t value);
/* '"fieldname" : value' or 'value' if fieldname is NULL */
void json_add_u32(struct json_stream *result, const char *fieldname,
uint32_t value);
/* '"fieldname" : value' or 'value' if fieldname is NULL */
void json_add_s32(struct json_stream *result, const char *fieldname,
int32_t value);
/* '"fieldname" : true|false' or 'true|false' if fieldname is NULL */
void json_add_bool(struct json_stream *result, const char *fieldname,
bool value);
/* '"fieldname" : null' or 'null' if fieldname is NULL */
void json_add_null(struct json_stream *stream, const char *fieldname);
/* '"fieldname" : "0189abcdef..."' or "0189abcdef..." if fieldname is NULL */
void json_add_hex(struct json_stream *result, const char *fieldname,
const void *data, size_t len);
/* '"fieldname" : "0189abcdef..."' or "0189abcdef..." if fieldname is NULL */
void json_add_hex_talarr(struct json_stream *result,
const char *fieldname,
const tal_t *data);
void json_add_timeabs(struct json_stream *result, const char *fieldname,
struct timeabs t);
/* used in log.c and notification.c*/
void json_add_time(struct json_stream *result, const char *fieldname,
struct timespec ts);
/* Add ISO_8601 timestamp string, i.e. "2019-09-07T15:50+01:00" */
void json_add_timeiso(struct json_stream *result,
const char *fieldname,
struct timeabs *time);
/* Add any json token */
void json_add_tok(struct json_stream *result, const char *fieldname,
const jsmntok_t *tok, const char *buffer);
/* Add an error code */
void json_add_errcode(struct json_stream *result, const char *fieldname,
errcode_t code);
/* Add "bolt11" or "bolt12" field, depending on invstring. */
void json_add_invstring(struct json_stream *result, const char *invstring);
/* '"fieldname" : "0289abcdef..."' or "0289abcdef..." if fieldname is NULL */
void json_add_pubkey(struct json_stream *response,
const char *fieldname,
const struct pubkey *key);
/* '"fieldname" : "89abcdef..."' or "89abcdef..." if fieldname is NULL */
void json_add_point32(struct json_stream *response,
const char *fieldname,
const struct point32 *key);
/* '"fieldname" : "89abcdef..."' or "89abcdef..." if fieldname is NULL */
void json_add_bip340sig(struct json_stream *response,
const char *fieldname,
const struct bip340sig *sig);
/* '"fieldname" : "89abcdef..."' or "89abcdef..." if fieldname is NULL */
void json_add_secret(struct json_stream *response,
const char *fieldname,
const struct secret *secret);
/* '"fieldname" : "0289abcdef..."' or "0289abcdef..." if fieldname is NULL */
void json_add_node_id(struct json_stream *response,
const char *fieldname,
const struct node_id *id);
/* '"fieldname" : "0289abcdef..."' or "0289abcdef..." if fieldname is NULL */
void json_add_channel_id(struct json_stream *response,
const char *fieldname,
const struct channel_id *cid);
/* '"fieldname" : <hexrev>' or "<hexrev>" if fieldname is NULL */
void json_add_txid(struct json_stream *result, const char *fieldname,
const struct bitcoin_txid *txid);
/* '"fieldname" : "txid:n" */
void json_add_outpoint(struct json_stream *result, const char *fieldname,
const struct bitcoin_outpoint *out);
/* '"fieldname" : "1234:5:6"' */
void json_add_short_channel_id(struct json_stream *response,
const char *fieldname,
const struct short_channel_id *id);
/* JSON serialize a network address for a node */
void json_add_address(struct json_stream *response, const char *fieldname,
const struct wireaddr *addr);
/* JSON serialize a network address for a node. */
void json_add_address_internal(struct json_stream *response,
const char *fieldname,
const struct wireaddr_internal *addr);
/* Adds both a 'raw' number field and an 'amount_msat' field */
void json_add_amount_msat_compat(struct json_stream *result,
struct amount_msat msat,
const char *rawfieldname,
const char *msatfieldname)
NO_NULL_ARGS;
/* Adds both a 'raw' number field and an 'amount_msat' field */
void json_add_amount_sat_compat(struct json_stream *result,
struct amount_sat sat,
const char *rawfieldname,
const char *msatfieldname)
NO_NULL_ARGS;
/* Adds an 'msat' field */
void json_add_amount_msat_only(struct json_stream *result,
const char *msatfieldname,
struct amount_msat msat)
NO_NULL_ARGS;
/* Adds an 'msat' field */
void json_add_amount_sat_only(struct json_stream *result,
const char *msatfieldname,
struct amount_sat sat)
NO_NULL_ARGS;
/* Adds an 'msat' field */
void json_add_amount_sat_msat(struct json_stream *result,
const char *msatfieldname,
struct amount_sat sat)
NO_NULL_ARGS;
/* Adds an 'msat' field, and an older deprecated field. */
void json_add_amount_sats_deprecated(struct json_stream *result,
const char *fieldname,
const char *msatfieldname,
struct amount_sat sat)
NO_NULL_ARGS;
/* This is used to create requests, *never* for output (output is always
* msat!) */
void json_add_sats(struct json_stream *result,
const char *fieldname,
struct amount_sat sat)
NO_NULL_ARGS;
void json_add_sha256(struct json_stream *result, const char *fieldname,
const struct sha256 *hash);
void json_add_preimage(struct json_stream *result, const char *fieldname,
const struct preimage *preimage);
/* '"fieldname" : "010000000001..."' or "010000000001..." if fieldname is NULL */
void json_add_tx(struct json_stream *result,
const char *fieldname,
const struct bitcoin_tx *tx);
/* '"fieldname" : "cHNidP8BAJoCAAAAAljo..." or "cHNidP8BAJoCAAAAAljo..." if fieldname is NULL */
void json_add_psbt(struct json_stream *stream,
const char *fieldname,
const struct wally_psbt *psbt);
/* Add fields from the lease_rates to a json stream.
* Note that field names are set */
void json_add_lease_rates(struct json_stream *result,
const struct lease_rates *rates);
#endif /* LIGHTNING_COMMON_JSON_STREAM_H */

View File

@@ -1,369 +0,0 @@
#include "config.h"
#include <ccan/asort/asort.h>
#include <ccan/mem/mem.h>
#include <ccan/tal/str/str.h>
#include <common/configdir.h>
#include <common/json_command.h>
#include <common/json_tok.h>
#include <common/param.h>
struct param {
const char *name;
bool is_set;
enum param_style style;
param_cbx cbx;
void *arg;
};
static bool param_add(struct param **params,
const char *name,
enum param_style style,
param_cbx cbx, void *arg)
{
#if DEVELOPER
if (!(name && cbx && arg))
return false;
#endif
struct param last;
last.is_set = false;
last.name = name;
last.style = style;
last.cbx = cbx;
last.arg = arg;
tal_arr_expand(params, last);
return true;
}
/* FIXME: To support the deprecated p_req_dup_ok */
static bool is_required(enum param_style style)
{
return style == PARAM_REQUIRED || style == PARAM_REQUIRED_ALLOW_DUPS;
}
static struct command_result *make_callback(struct command *cmd,
struct param *def,
const char *buffer,
const jsmntok_t *tok)
{
/* If it had a default, free that now to avoid leak */
if (def->style == PARAM_OPTIONAL_WITH_DEFAULT && !def->is_set)
tal_free(*(void **)def->arg);
def->is_set = true;
return def->cbx(cmd, def->name, buffer, tok, def->arg);
}
static struct command_result *post_check(struct command *cmd,
struct param *params)
{
struct param *first = params;
struct param *last = first + tal_count(params);
/* Make sure required params were provided. */
while (first != last && is_required(first->style)) {
if (!first->is_set) {
return command_fail(cmd, JSONRPC2_INVALID_PARAMS,
"missing required parameter: %s",
first->name);
}
first++;
}
return NULL;
}
static struct command_result *parse_by_position(struct command *cmd,
struct param *params,
const char *buffer,
const jsmntok_t tokens[],
bool allow_extra)
{
struct command_result *res;
const jsmntok_t *tok;
size_t i;
json_for_each_arr(i, tok, tokens) {
/* check for unexpected trailing params */
if (i == tal_count(params)) {
if (!allow_extra) {
return command_fail(cmd, JSONRPC2_INVALID_PARAMS,
"too many parameters:"
" got %u, expected %zu",
tokens->size,
tal_count(params));
}
break;
}
if (!json_tok_is_null(buffer, tok)) {
res = make_callback(cmd, params+i, buffer, tok);
if (res)
return res;
}
}
return post_check(cmd, params);
}
static struct param *find_param(struct param *params, const char *start,
size_t n)
{
struct param *first = params;
struct param *last = first + tal_count(params);
while (first != last) {
size_t arglen = strcspn(first->name, "|");
if (memeq(first->name, arglen, start, n))
return first;
if (deprecated_apis
&& first->name[arglen]
&& memeq(first->name + arglen + 1,
strlen(first->name + arglen + 1),
start, n))
return first;
first++;
}
return NULL;
}
static struct command_result *parse_by_name(struct command *cmd,
struct param *params,
const char *buffer,
const jsmntok_t tokens[],
bool allow_extra)
{
size_t i;
const jsmntok_t *t;
json_for_each_obj(i, t, tokens) {
struct param *p = find_param(params, buffer + t->start,
t->end - t->start);
if (!p) {
if (!allow_extra) {
return command_fail(cmd, JSONRPC2_INVALID_PARAMS,
"unknown parameter: %.*s, this may be caused by a failure to autodetect key=value-style parameters. Please try using the -k flag and explicit key=value pairs of parameters.",
t->end - t->start,
buffer + t->start);
}
} else {
struct command_result *res;
if (p->is_set) {
if (p->style == PARAM_REQUIRED_ALLOW_DUPS)
continue;
return command_fail(cmd, JSONRPC2_INVALID_PARAMS,
"duplicate json names: %s",
p->name);
}
res = make_callback(cmd, p, buffer, t + 1);
if (res)
return res;
}
}
return post_check(cmd, params);
}
#if DEVELOPER
static int comp_by_name(const struct param *a, const struct param *b,
void *unused)
{
return strcmp(a->name, b->name);
}
static int comp_by_arg(const struct param *a, const struct param *b,
void *unused)
{
/* size_t could be larger than int: don't turn a 4bn difference into 0 */
if (a->arg > b->arg)
return 1;
else if (a->arg < b->arg)
return -1;
return 0;
}
/* This comparator is a bit different, but works well.
* Return 0 if @a is optional and @b is required. Otherwise return 1.
*/
static int comp_req_order(const struct param *a, const struct param *b,
void *unused)
{
if (!is_required(a->style) && is_required(b->style))
return 0;
return 1;
}
/*
* Make sure 2 sequential items in @params are not equal (based on
* provided comparator).
*/
static bool check_distinct(struct param *params,
int (*compar) (const struct param *a,
const struct param *b, void *unused))
{
struct param *first = params;
struct param *last = first + tal_count(params);
first++;
while (first != last) {
if (compar(first - 1, first, NULL) == 0)
return false;
first++;
}
return true;
}
static bool check_unique(struct param *copy,
int (*compar) (const struct param *a,
const struct param *b, void *unused))
{
asort(copy, tal_count(copy), compar, NULL);
return check_distinct(copy, compar);
}
/*
* Verify consistent internal state.
*/
static bool check_params(struct param *params)
{
if (tal_count(params) < 2)
return true;
/* make sure there are no required params following optional */
if (!check_distinct(params, comp_req_order))
return false;
/* duplicate so we can sort */
struct param *copy = tal_dup_talarr(params, struct param, params);
/* check for repeated names and args */
if (!check_unique(copy, comp_by_name))
return false;
if (!check_unique(copy, comp_by_arg))
return false;
tal_free(copy);
return true;
}
#endif
static char *param_usage(const tal_t *ctx,
const struct param *params)
{
char *usage = tal_strdup(ctx, "");
for (size_t i = 0; i < tal_count(params); i++) {
/* Don't print |deprecated part! */
int len = strcspn(params[i].name, "|");
if (i != 0)
tal_append_fmt(&usage, " ");
if (is_required(params[i].style))
tal_append_fmt(&usage, "%.*s", len, params[i].name);
else
tal_append_fmt(&usage, "[%.*s]", len, params[i].name);
}
return usage;
}
static struct command_result *param_arr(struct command *cmd, const char *buffer,
const jsmntok_t tokens[],
struct param *params,
bool allow_extra)
{
#if DEVELOPER
if (!check_params(params)) {
return command_fail(cmd, PARAM_DEV_ERROR,
"developer error: check_params");
}
#endif
if (tokens->type == JSMN_ARRAY)
return parse_by_position(cmd, params, buffer, tokens, allow_extra);
else if (tokens->type == JSMN_OBJECT)
return parse_by_name(cmd, params, buffer, tokens, allow_extra);
return command_fail(cmd, JSONRPC2_INVALID_PARAMS,
"Expected array or object for params");
}
const char *param_subcommand(struct command *cmd, const char *buffer,
const jsmntok_t tokens[],
const char *name, ...)
{
va_list ap;
struct param *params = tal_arr(cmd, struct param, 0);
const char *arg, **names = tal_arr(tmpctx, const char *, 1);
const char *subcmd;
param_add(&params, "subcommand", PARAM_REQUIRED, (void *)param_string, &subcmd);
names[0] = name;
va_start(ap, name);
while ((arg = va_arg(ap, const char *)) != NULL)
tal_arr_expand(&names, arg);
va_end(ap);
if (command_usage_only(cmd)) {
char *usage = tal_strdup(cmd, "subcommand");
for (size_t i = 0; i < tal_count(names); i++)
tal_append_fmt(&usage, "%c%s",
i == 0 ? '=' : '|', names[i]);
command_set_usage(cmd, usage);
return NULL;
}
/* Check it's valid */
if (param_arr(cmd, buffer, tokens, params, true) != NULL) {
return NULL;
}
/* Check it's one of the known ones. */
for (size_t i = 0; i < tal_count(names); i++)
if (streq(subcmd, names[i]))
return subcmd;
/* We really do ignore this. */
struct command_result *ignore;
ignore = command_fail(cmd, JSONRPC2_INVALID_PARAMS,
"Unknown subcommand '%s'", subcmd);
assert(ignore);
return NULL;
}
bool param(struct command *cmd, const char *buffer,
const jsmntok_t tokens[], ...)
{
struct param *params = tal_arr(tmpctx, struct param, 0);
const char *name;
va_list ap;
bool allow_extra = false;
va_start(ap, tokens);
while ((name = va_arg(ap, const char *)) != NULL) {
enum param_style style = va_arg(ap, enum param_style);
param_cbx cbx = va_arg(ap, param_cbx);
void *arg = va_arg(ap, void *);
if (streq(name, "")) {
allow_extra = true;
continue;
}
if (!param_add(&params, name, style, cbx, arg)) {
/* We really do ignore this return! */
struct command_result *ignore;
ignore = command_fail(cmd, PARAM_DEV_ERROR,
"developer error: param_add %s", name);
assert(ignore);
va_end(ap);
return false;
}
}
va_end(ap);
if (command_usage_only(cmd)) {
command_set_usage(cmd, param_usage(cmd, params));
return false;
}
/* Always return false if we're simply checking command parameters;
* normally this returns true if all parameters are valid. */
return param_arr(cmd, buffer, tokens, params, allow_extra) == NULL
&& !command_check_only(cmd);
}

View File

@@ -1,139 +0,0 @@
#ifndef LIGHTNING_COMMON_PARAM_H
#define LIGHTNING_COMMON_PARAM_H
#include "config.h"
#include <common/json.h>
/*~ Greetings adventurer!
*
* Do you want to automatically validate json input and unmarshal it into
* local variables, all using typesafe callbacks? And on error,
* call command_fail with a proper error message? Then you've come to the
* right place!
*
* Here is a simple example of using the system:
*
* unsigned *cltv;
* u64 *msatoshi;
* const jsmntok_t *note;
* u64 *expiry;
*
* if (!param(cmd, buffer, params,
* p_req("cltv", json_tok_number, &cltv),
* p_opt("amount_msat|msatoshi", json_tok_u64, &msatoshi),
* p_opt("note", json_tok_tok, &note),
* p_opt_def("expiry", json_tok_u64, &expiry, 3600),
* NULL))
* return;
*
* If param() returns true then you're good to go.
*
* All the command handlers throughout the code use this system.
* json_invoice() is a great example. The common callbacks can be found in
* common/json_tok.c. Use them directly or feel free to write your own.
*/
struct command;
/* A dummy type returned by command_ functions, to ensure you return them
* immediately */
struct command_result;
/*
* Parse the json tokens. @params can be an array of values or an object
* of named values.
*/
bool param(struct command *cmd, const char *buffer,
const jsmntok_t params[], ...) LAST_ARG_NULL;
/*
* The callback signature.
*
* Callbacks must return NULL on success. On failure they
* must return command_fail(...).
*/
typedef struct command_result *(*param_cbx)(struct command *cmd,
const char *name,
const char *buffer,
const jsmntok_t *tok,
void **arg);
/**
* Parse the first json value.
*
* name...: NULL-terminated array of valid values.
*
* Returns subcommand: if it returns NULL if you should return
* command_param_failed() immediately.
*/
const char *param_subcommand(struct command *cmd, const char *buffer,
const jsmntok_t tokens[],
const char *name, ...) LAST_ARG_NULL;
enum param_style {
PARAM_REQUIRED,
PARAM_REQUIRED_ALLOW_DUPS,
PARAM_OPTIONAL,
PARAM_OPTIONAL_WITH_DEFAULT,
};
/*
* Add a required parameter.
* name can be <normal>|<deprecated> if it's been renamed.
*/
#define p_req(name, cbx, arg) \
name"", \
PARAM_REQUIRED, \
(param_cbx)(cbx), \
(arg) + 0*sizeof((cbx)((struct command *)NULL, \
(const char *)NULL, \
(const char *)NULL, \
(const jsmntok_t *)NULL, \
(arg)) == (struct command_result *)NULL)
/*
* Add an optional parameter. *arg is set to NULL if it isn't found.
* name can be <normal>|<deprecated> if it's been renamed.
*/
#define p_opt(name, cbx, arg) \
name"", \
PARAM_OPTIONAL, \
(param_cbx)(cbx), \
({ *arg = NULL; \
(arg) + 0*sizeof((cbx)((struct command *)NULL, \
(const char *)NULL, \
(const char *)NULL, \
(const jsmntok_t *)NULL, \
(arg)) == (struct command_result *)NULL); })
/*
* Add an required parameter, like p_req, but ignore duplicates.
*/
#define p_req_dup_ok(name, cbx, arg) \
name"", \
PARAM_REQUIRED_ALLOW_DUPS, \
(param_cbx)(cbx), \
({ *arg = NULL; \
(arg) + 0*sizeof((cbx)((struct command *)NULL, \
(const char *)NULL, \
(const char *)NULL, \
(const jsmntok_t *)NULL, \
(arg)) == (struct command_result *)NULL); })
/*
* Add an optional parameter. *arg is set to @def if it isn't found.
* name can be <normal>|<deprecated> if it's been renamed.
*/
#define p_opt_def(name, cbx, arg, def) \
name"", \
PARAM_OPTIONAL_WITH_DEFAULT, \
(param_cbx)(cbx), \
({ (*arg) = tal((cmd), typeof(**arg)); \
(**arg) = (def); \
(arg) + 0*sizeof((cbx)((struct command *)NULL, \
(const char *)NULL, \
(const char *)NULL, \
(const jsmntok_t *)NULL, \
(arg)) == (struct command_result *)NULL); })
/* Special flag for 'check' which allows any parameters. */
#define p_opt_any() "", PARAM_OPTIONAL, NULL, NULL
#endif /* LIGHTNING_COMMON_PARAM_H */

View File

@@ -21,8 +21,8 @@ ALL_TEST_PROGRAMS += $(COMMON_TEST_PROGRAMS)
# Sphinx test wants to decode TLVs.
common/test/run-sphinx: wire/onion$(EXP)_wiregen.o wire/towire.o wire/fromwire.o
common/test/run-blindedpath_enctlv common/test/run-blindedpath_onion: common/base32.o common/wireaddr.o wire/onion$(EXP)_wiregen.o wire/peer$(EXP)_wiregen.o wire/towire.o wire/fromwire.o wire/tlvstream.o
common/test/run-route_blinding_test: wire/onion$(EXP)_wiregen.o wire/peer$(EXP)_wiregen.o wire/towire.o wire/fromwire.o wire/tlvstream.o common/json.o common/json_helpers.o common/coin_mvt.o
common/test/run-route_blinding_override_test: common/base32.o common/wireaddr.o wire/onion$(EXP)_wiregen.o wire/peer$(EXP)_wiregen.o wire/towire.o wire/fromwire.o wire/tlvstream.o common/json.o common/json_helpers.o common/coin_mvt.o
common/test/run-route_blinding_test: wire/onion$(EXP)_wiregen.o wire/peer$(EXP)_wiregen.o wire/towire.o wire/fromwire.o wire/tlvstream.o common/coin_mvt.o
common/test/run-route_blinding_override_test: common/base32.o common/wireaddr.o wire/onion$(EXP)_wiregen.o wire/peer$(EXP)_wiregen.o wire/towire.o wire/fromwire.o wire/tlvstream.o common/coin_mvt.o
common/test/run-param \
common/test/run-json: \
@@ -31,7 +31,6 @@ common/test/run-json: \
common/bigsize.o \
common/channel_id.o \
common/coin_mvt.o \
common/json.o \
common/json_stream.o \
common/lease_rates.o \
common/node_id.o \

View File

@@ -2,7 +2,8 @@
#include <ccan/array_size/array_size.h>
#include <ccan/tal/grab_file/grab_file.h>
#include <common/amount.h>
#include <common/json.c>
#include <common/json_parse.c>
#include <common/json_parse_simple.c>
#include <common/setup.h>
static const char *reason;
@@ -74,16 +75,18 @@ u8 fromwire_u8(const u8 **cursor UNNEEDED, size_t *max UNNEEDED)
/* Generated stub for fromwire_u8_array */
void fromwire_u8_array(const u8 **cursor UNNEEDED, size_t *max UNNEEDED, u8 *arr UNNEEDED, size_t num UNNEEDED)
{ fprintf(stderr, "fromwire_u8_array called!\n"); abort(); }
/* Generated stub for json_add_member */
void json_add_member(struct json_stream *js UNNEEDED,
const char *fieldname UNNEEDED,
bool quote UNNEEDED,
const char *fmt UNNEEDED, ...)
{ fprintf(stderr, "json_add_member called!\n"); abort(); }
/* Generated stub for json_member_direct */
char *json_member_direct(struct json_stream *js UNNEEDED,
const char *fieldname UNNEEDED, size_t extra UNNEEDED)
{ fprintf(stderr, "json_member_direct called!\n"); abort(); }
/* Generated stub for mvt_tag_str */
const char *mvt_tag_str(enum mvt_tag tag UNNEEDED)
{ fprintf(stderr, "mvt_tag_str called!\n"); abort(); }
/* Generated stub for node_id_from_hexstr */
bool node_id_from_hexstr(const char *str UNNEEDED, size_t slen UNNEEDED, struct node_id *id UNNEEDED)
{ fprintf(stderr, "node_id_from_hexstr called!\n"); abort(); }
/* Generated stub for parse_amount_msat */
bool parse_amount_msat(struct amount_msat *msat UNNEEDED, const char *s UNNEEDED, size_t slen UNNEEDED)
{ fprintf(stderr, "parse_amount_msat called!\n"); abort(); }
/* Generated stub for parse_amount_sat */
bool parse_amount_sat(struct amount_sat *sat UNNEEDED, const char *s UNNEEDED, size_t slen UNNEEDED)
{ fprintf(stderr, "parse_amount_sat called!\n"); abort(); }
/* Generated stub for towire */
void towire(u8 **pptr UNNEEDED, const void *data UNNEEDED, size_t len UNNEEDED)
{ fprintf(stderr, "towire called!\n"); abort(); }

View File

@@ -2,7 +2,8 @@
#include "../bolt12.c"
#include "../bech32_util.c"
#include "../bech32.c"
#include "../json.c"
#include "../json_parse.c"
#include "../json_parse_simple.c"
#include <ccan/array_size/array_size.h>
#include <ccan/tal/grab_file/grab_file.h>
#include <ccan/tal/path/path.h>
@@ -89,19 +90,21 @@ u8 fromwire_u8(const u8 **cursor UNNEEDED, size_t *max UNNEEDED)
/* Generated stub for fromwire_u8_array */
void fromwire_u8_array(const u8 **cursor UNNEEDED, size_t *max UNNEEDED, u8 *arr UNNEEDED, size_t num UNNEEDED)
{ fprintf(stderr, "fromwire_u8_array called!\n"); abort(); }
/* Generated stub for json_add_member */
void json_add_member(struct json_stream *js UNNEEDED,
const char *fieldname UNNEEDED,
bool quote UNNEEDED,
const char *fmt UNNEEDED, ...)
{ fprintf(stderr, "json_add_member called!\n"); abort(); }
/* Generated stub for json_member_direct */
char *json_member_direct(struct json_stream *js UNNEEDED,
const char *fieldname UNNEEDED, size_t extra UNNEEDED)
{ fprintf(stderr, "json_member_direct called!\n"); abort(); }
/* Generated stub for merkle_tlv */
void merkle_tlv(const struct tlv_field *fields UNNEEDED, struct sha256 *merkle UNNEEDED)
{ fprintf(stderr, "merkle_tlv called!\n"); abort(); }
/* Generated stub for mvt_tag_str */
const char *mvt_tag_str(enum mvt_tag tag UNNEEDED)
{ fprintf(stderr, "mvt_tag_str called!\n"); abort(); }
/* Generated stub for node_id_from_hexstr */
bool node_id_from_hexstr(const char *str UNNEEDED, size_t slen UNNEEDED, struct node_id *id UNNEEDED)
{ fprintf(stderr, "node_id_from_hexstr called!\n"); abort(); }
/* Generated stub for parse_amount_msat */
bool parse_amount_msat(struct amount_msat *msat UNNEEDED, const char *s UNNEEDED, size_t slen UNNEEDED)
{ fprintf(stderr, "parse_amount_msat called!\n"); abort(); }
/* Generated stub for parse_amount_sat */
bool parse_amount_sat(struct amount_sat *sat UNNEEDED, const char *s UNNEEDED, size_t slen UNNEEDED)
{ fprintf(stderr, "parse_amount_sat called!\n"); abort(); }
/* Generated stub for sighash_from_merkle */
void sighash_from_merkle(const char *messagename UNNEEDED,
const char *fieldname UNNEEDED,

View File

@@ -2,7 +2,7 @@
#include "../amount.c"
#include "../bigsize.c"
#include "../bolt12_merkle.c"
#include "../json.c"
#include "../json_parse.c"
#include "../../wire/fromwire.c"
#include "../../wire/tlvstream.c"
#if EXPERIMENTAL_FEATURES
@@ -28,16 +28,47 @@ void fromwire_node_id(const u8 **cursor UNNEEDED, size_t *max UNNEEDED, struct n
/* Generated stub for fromwire_onionmsg_path */
struct onionmsg_path *fromwire_onionmsg_path(const tal_t *ctx UNNEEDED, const u8 **cursor UNNEEDED, size_t *plen UNNEEDED)
{ fprintf(stderr, "fromwire_onionmsg_path called!\n"); abort(); }
/* Generated stub for json_add_member */
void json_add_member(struct json_stream *js UNNEEDED,
const char *fieldname UNNEEDED,
bool quote UNNEEDED,
const char *fmt UNNEEDED, ...)
{ fprintf(stderr, "json_add_member called!\n"); abort(); }
/* Generated stub for json_member_direct */
char *json_member_direct(struct json_stream *js UNNEEDED,
const char *fieldname UNNEEDED, size_t extra UNNEEDED)
{ fprintf(stderr, "json_member_direct called!\n"); abort(); }
/* Generated stub for json_get_arr */
const jsmntok_t *json_get_arr(const jsmntok_t tok[] UNNEEDED, size_t index UNNEEDED)
{ fprintf(stderr, "json_get_arr called!\n"); abort(); }
/* Generated stub for json_get_member */
const jsmntok_t *json_get_member(const char *buffer UNNEEDED, const jsmntok_t tok[] UNNEEDED,
const char *label UNNEEDED)
{ fprintf(stderr, "json_get_member called!\n"); abort(); }
/* Generated stub for json_get_membern */
const jsmntok_t *json_get_membern(const char *buffer UNNEEDED,
const jsmntok_t tok[] UNNEEDED,
const char *label UNNEEDED, size_t len UNNEEDED)
{ fprintf(stderr, "json_get_membern called!\n"); abort(); }
/* Generated stub for json_next */
const jsmntok_t *json_next(const jsmntok_t *tok UNNEEDED)
{ fprintf(stderr, "json_next called!\n"); abort(); }
/* Generated stub for json_strdup */
char *json_strdup(const tal_t *ctx UNNEEDED, const char *buffer UNNEEDED, const jsmntok_t *tok UNNEEDED)
{ fprintf(stderr, "json_strdup called!\n"); abort(); }
/* Generated stub for json_to_u32 */
bool json_to_u32(const char *buffer UNNEEDED, const jsmntok_t *tok UNNEEDED,
uint32_t *num UNNEEDED)
{ fprintf(stderr, "json_to_u32 called!\n"); abort(); }
/* Generated stub for json_to_u64 */
bool json_to_u64(const char *buffer UNNEEDED, const jsmntok_t *tok UNNEEDED,
uint64_t *num UNNEEDED)
{ fprintf(stderr, "json_to_u64 called!\n"); abort(); }
/* Generated stub for json_tok_full */
const char *json_tok_full(const char *buffer UNNEEDED, const jsmntok_t *t UNNEEDED)
{ fprintf(stderr, "json_tok_full called!\n"); abort(); }
/* Generated stub for json_tok_full_len */
int json_tok_full_len(const jsmntok_t *t UNNEEDED)
{ fprintf(stderr, "json_tok_full_len called!\n"); abort(); }
/* Generated stub for json_tok_streq */
bool json_tok_streq(const char *buffer UNNEEDED, const jsmntok_t *tok UNNEEDED, const char *str UNNEEDED)
{ fprintf(stderr, "json_tok_streq called!\n"); abort(); }
/* Generated stub for mvt_tag_str */
const char *mvt_tag_str(enum mvt_tag tag UNNEEDED)
{ fprintf(stderr, "mvt_tag_str called!\n"); abort(); }
/* Generated stub for node_id_from_hexstr */
bool node_id_from_hexstr(const char *str UNNEEDED, size_t slen UNNEEDED, struct node_id *id UNNEEDED)
{ fprintf(stderr, "node_id_from_hexstr called!\n"); abort(); }
/* Generated stub for towire */
void towire(u8 **pptr UNNEEDED, const void *data UNNEEDED, size_t len UNNEEDED)
{ fprintf(stderr, "towire called!\n"); abort(); }

View File

@@ -1,6 +1,7 @@
#include "config.h"
#include "../bolt12.c"
#include "../json.c"
#include "../json_parse.c"
#include "../json_parse_simple.c"
#include <ccan/array_size/array_size.h>
#include <ccan/tal/grab_file/grab_file.h>
#include <ccan/tal/path/path.h>
@@ -92,19 +93,21 @@ u8 fromwire_u8(const u8 **cursor UNNEEDED, size_t *max UNNEEDED)
/* Generated stub for fromwire_u8_array */
void fromwire_u8_array(const u8 **cursor UNNEEDED, size_t *max UNNEEDED, u8 *arr UNNEEDED, size_t num UNNEEDED)
{ fprintf(stderr, "fromwire_u8_array called!\n"); abort(); }
/* Generated stub for json_add_member */
void json_add_member(struct json_stream *js UNNEEDED,
const char *fieldname UNNEEDED,
bool quote UNNEEDED,
const char *fmt UNNEEDED, ...)
{ fprintf(stderr, "json_add_member called!\n"); abort(); }
/* Generated stub for json_member_direct */
char *json_member_direct(struct json_stream *js UNNEEDED,
const char *fieldname UNNEEDED, size_t extra UNNEEDED)
{ fprintf(stderr, "json_member_direct called!\n"); abort(); }
/* Generated stub for merkle_tlv */
void merkle_tlv(const struct tlv_field *fields UNNEEDED, struct sha256 *merkle UNNEEDED)
{ fprintf(stderr, "merkle_tlv called!\n"); abort(); }
/* Generated stub for mvt_tag_str */
const char *mvt_tag_str(enum mvt_tag tag UNNEEDED)
{ fprintf(stderr, "mvt_tag_str called!\n"); abort(); }
/* Generated stub for node_id_from_hexstr */
bool node_id_from_hexstr(const char *str UNNEEDED, size_t slen UNNEEDED, struct node_id *id UNNEEDED)
{ fprintf(stderr, "node_id_from_hexstr called!\n"); abort(); }
/* Generated stub for parse_amount_msat */
bool parse_amount_msat(struct amount_msat *msat UNNEEDED, const char *s UNNEEDED, size_t slen UNNEEDED)
{ fprintf(stderr, "parse_amount_msat called!\n"); abort(); }
/* Generated stub for parse_amount_sat */
bool parse_amount_sat(struct amount_sat *sat UNNEEDED, const char *s UNNEEDED, size_t slen UNNEEDED)
{ fprintf(stderr, "parse_amount_sat called!\n"); abort(); }
/* Generated stub for sighash_from_merkle */
void sighash_from_merkle(const char *messagename UNNEEDED,
const char *fieldname UNNEEDED,

View File

@@ -1,5 +1,6 @@
#include "config.h"
#include "../json_helpers.c"
#include "../json_parse.c"
#include "../json_parse_simple.c"
#include <assert.h>
#include <ccan/tal/str/str.h>
#include <common/channel_type.h>

View File

@@ -1,7 +1,9 @@
#include "config.h"
#include <common/amount.h>
#include <common/json.c>
#include <common/json_param.c>
#include <common/json_parse_simple.c>
#include <common/setup.h>
#include <stdio.h>
#include <wire/wire.h>
/* AUTOGENERATED MOCKS START */
@@ -36,6 +38,22 @@ struct amount_asset amount_sat_to_asset(struct amount_sat *sat UNNEEDED, const u
/* Generated stub for amount_tx_fee */
struct amount_sat amount_tx_fee(u32 fee_per_kw UNNEEDED, size_t weight UNNEEDED)
{ fprintf(stderr, "amount_tx_fee called!\n"); abort(); }
/* Generated stub for command_check_only */
bool command_check_only(const struct command *cmd UNNEEDED)
{ fprintf(stderr, "command_check_only called!\n"); abort(); }
/* Generated stub for command_fail */
struct command_result *command_fail(struct command *cmd UNNEEDED, errcode_t code UNNEEDED,
const char *fmt UNNEEDED, ...)
{ fprintf(stderr, "command_fail called!\n"); abort(); }
/* Generated stub for command_set_usage */
void command_set_usage(struct command *cmd UNNEEDED, const char *usage UNNEEDED)
{ fprintf(stderr, "command_set_usage called!\n"); abort(); }
/* Generated stub for command_usage_only */
bool command_usage_only(const struct command *cmd UNNEEDED)
{ fprintf(stderr, "command_usage_only called!\n"); abort(); }
/* Generated stub for deprecated_apis */
bool deprecated_apis;
/* Generated stub for fromwire */
const u8 *fromwire(const u8 **cursor UNNEEDED, size_t *max UNNEEDED, void *copy UNNEEDED, size_t n UNNEEDED)
{ fprintf(stderr, "fromwire called!\n"); abort(); }
@@ -68,16 +86,75 @@ u8 fromwire_u8(const u8 **cursor UNNEEDED, size_t *max UNNEEDED)
/* Generated stub for fromwire_u8_array */
void fromwire_u8_array(const u8 **cursor UNNEEDED, size_t *max UNNEEDED, u8 *arr UNNEEDED, size_t num UNNEEDED)
{ fprintf(stderr, "fromwire_u8_array called!\n"); abort(); }
/* Generated stub for json_add_member */
void json_add_member(struct json_stream *js UNNEEDED,
const char *fieldname UNNEEDED,
bool quote UNNEEDED,
const char *fmt UNNEEDED, ...)
{ fprintf(stderr, "json_add_member called!\n"); abort(); }
/* Generated stub for json_member_direct */
char *json_member_direct(struct json_stream *js UNNEEDED,
const char *fieldname UNNEEDED, size_t extra UNNEEDED)
{ fprintf(stderr, "json_member_direct called!\n"); abort(); }
/* Generated stub for json_scan */
const char *json_scan(const tal_t *ctx UNNEEDED,
const char *buffer UNNEEDED,
const jsmntok_t *tok UNNEEDED,
const char *guide UNNEEDED,
...)
{ fprintf(stderr, "json_scan called!\n"); abort(); }
/* Generated stub for json_to_channel_id */
bool json_to_channel_id(const char *buffer UNNEEDED, const jsmntok_t *tok UNNEEDED,
struct channel_id *cid UNNEEDED)
{ fprintf(stderr, "json_to_channel_id called!\n"); abort(); }
/* Generated stub for json_to_millionths */
bool json_to_millionths(const char *buffer UNNEEDED, const jsmntok_t *tok UNNEEDED,
u64 *millionths UNNEEDED)
{ fprintf(stderr, "json_to_millionths called!\n"); abort(); }
/* Generated stub for json_to_msat */
bool json_to_msat(const char *buffer UNNEEDED, const jsmntok_t *tok UNNEEDED,
struct amount_msat *msat UNNEEDED)
{ fprintf(stderr, "json_to_msat called!\n"); abort(); }
/* Generated stub for json_to_node_id */
bool json_to_node_id(const char *buffer UNNEEDED, const jsmntok_t *tok UNNEEDED,
struct node_id *id UNNEEDED)
{ fprintf(stderr, "json_to_node_id called!\n"); abort(); }
/* Generated stub for json_to_number */
bool json_to_number(const char *buffer UNNEEDED, const jsmntok_t *tok UNNEEDED,
unsigned int *num UNNEEDED)
{ fprintf(stderr, "json_to_number called!\n"); abort(); }
/* Generated stub for json_to_outpoint */
bool json_to_outpoint(const char *buffer UNNEEDED, const jsmntok_t *tok UNNEEDED,
struct bitcoin_outpoint *op UNNEEDED)
{ fprintf(stderr, "json_to_outpoint called!\n"); abort(); }
/* Generated stub for json_to_pubkey */
bool json_to_pubkey(const char *buffer UNNEEDED, const jsmntok_t *tok UNNEEDED,
struct pubkey *pubkey UNNEEDED)
{ fprintf(stderr, "json_to_pubkey called!\n"); abort(); }
/* Generated stub for json_to_short_channel_id */
bool json_to_short_channel_id(const char *buffer UNNEEDED, const jsmntok_t *tok UNNEEDED,
struct short_channel_id *scid UNNEEDED)
{ fprintf(stderr, "json_to_short_channel_id called!\n"); abort(); }
/* Generated stub for json_to_txid */
bool json_to_txid(const char *buffer UNNEEDED, const jsmntok_t *tok UNNEEDED,
struct bitcoin_txid *txid UNNEEDED)
{ fprintf(stderr, "json_to_txid called!\n"); abort(); }
/* Generated stub for json_to_u16 */
bool json_to_u16(const char *buffer UNNEEDED, const jsmntok_t *tok UNNEEDED,
uint16_t *num UNNEEDED)
{ fprintf(stderr, "json_to_u16 called!\n"); abort(); }
/* Generated stub for json_tok_bin_from_hex */
u8 *json_tok_bin_from_hex(const tal_t *ctx UNNEEDED, const char *buffer UNNEEDED, const jsmntok_t *tok UNNEEDED)
{ fprintf(stderr, "json_tok_bin_from_hex called!\n"); abort(); }
/* Generated stub for lease_rates_fromhex */
struct lease_rates *lease_rates_fromhex(const tal_t *ctx UNNEEDED,
const char *hexdata UNNEEDED, size_t len UNNEEDED)
{ fprintf(stderr, "lease_rates_fromhex called!\n"); abort(); }
/* Generated stub for parse_amount_msat */
bool parse_amount_msat(struct amount_msat *msat UNNEEDED, const char *s UNNEEDED, size_t slen UNNEEDED)
{ fprintf(stderr, "parse_amount_msat called!\n"); abort(); }
/* Generated stub for parse_amount_sat */
bool parse_amount_sat(struct amount_sat *sat UNNEEDED, const char *s UNNEEDED, size_t slen UNNEEDED)
{ fprintf(stderr, "parse_amount_sat called!\n"); abort(); }
/* Generated stub for segwit_addr_decode */
int segwit_addr_decode(
int* ver UNNEEDED,
uint8_t* prog UNNEEDED,
size_t* prog_len UNNEEDED,
const char* hrp UNNEEDED,
const char* addr
)
{ fprintf(stderr, "segwit_addr_decode called!\n"); abort(); }
/* Generated stub for towire */
void towire(u8 **pptr UNNEEDED, const void *data UNNEEDED, size_t len UNNEEDED)
{ fprintf(stderr, "towire called!\n"); abort(); }

View File

@@ -1,5 +1,6 @@
#include "config.h"
#include "../json.c"
#include "../json_parse.c"
#include "../json_parse_simple.c"
#include <common/amount.h>
#include <common/setup.h>
#include <wire/wire.h>
@@ -68,16 +69,18 @@ u8 fromwire_u8(const u8 **cursor UNNEEDED, size_t *max UNNEEDED)
/* Generated stub for fromwire_u8_array */
void fromwire_u8_array(const u8 **cursor UNNEEDED, size_t *max UNNEEDED, u8 *arr UNNEEDED, size_t num UNNEEDED)
{ fprintf(stderr, "fromwire_u8_array called!\n"); abort(); }
/* Generated stub for json_add_member */
void json_add_member(struct json_stream *js UNNEEDED,
const char *fieldname UNNEEDED,
bool quote UNNEEDED,
const char *fmt UNNEEDED, ...)
{ fprintf(stderr, "json_add_member called!\n"); abort(); }
/* Generated stub for json_member_direct */
char *json_member_direct(struct json_stream *js UNNEEDED,
const char *fieldname UNNEEDED, size_t extra UNNEEDED)
{ fprintf(stderr, "json_member_direct called!\n"); abort(); }
/* Generated stub for mvt_tag_str */
const char *mvt_tag_str(enum mvt_tag tag UNNEEDED)
{ fprintf(stderr, "mvt_tag_str called!\n"); abort(); }
/* Generated stub for node_id_from_hexstr */
bool node_id_from_hexstr(const char *str UNNEEDED, size_t slen UNNEEDED, struct node_id *id UNNEEDED)
{ fprintf(stderr, "node_id_from_hexstr called!\n"); abort(); }
/* Generated stub for parse_amount_msat */
bool parse_amount_msat(struct amount_msat *msat UNNEEDED, const char *s UNNEEDED, size_t slen UNNEEDED)
{ fprintf(stderr, "parse_amount_msat called!\n"); abort(); }
/* Generated stub for parse_amount_sat */
bool parse_amount_sat(struct amount_sat *sat UNNEEDED, const char *s UNNEEDED, size_t slen UNNEEDED)
{ fprintf(stderr, "parse_amount_sat called!\n"); abort(); }
/* Generated stub for towire */
void towire(u8 **pptr UNNEEDED, const void *data UNNEEDED, size_t len UNNEEDED)
{ fprintf(stderr, "towire called!\n"); abort(); }

View File

@@ -1,6 +1,7 @@
#include "config.h"
#include "../json_tok.c"
#include "../param.c"
#include "../json_parse.c"
#include "../json_parse_simple.c"
#include "../json_param.c"
#include <ccan/array_size/array_size.h>
#include <common/channel_type.h>
#include <common/setup.h>
@@ -42,34 +43,6 @@ bool fromwire_tlv(const u8 **cursor UNNEEDED, size_t *max UNNEEDED,
void *record UNNEEDED, struct tlv_field **fields UNNEEDED,
const u64 *extra_types UNNEEDED, size_t *err_off UNNEEDED, u64 *err_type UNNEEDED)
{ fprintf(stderr, "fromwire_tlv called!\n"); abort(); }
/* Generated stub for json_to_channel_id */
bool json_to_channel_id(const char *buffer UNNEEDED, const jsmntok_t *tok UNNEEDED,
struct channel_id *cid UNNEEDED)
{ fprintf(stderr, "json_to_channel_id called!\n"); abort(); }
/* Generated stub for json_to_msat */
bool json_to_msat(const char *buffer UNNEEDED, const jsmntok_t *tok UNNEEDED,
struct amount_msat *msat UNNEEDED)
{ fprintf(stderr, "json_to_msat called!\n"); abort(); }
/* Generated stub for json_to_node_id */
bool json_to_node_id(const char *buffer UNNEEDED, const jsmntok_t *tok UNNEEDED,
struct node_id *id UNNEEDED)
{ fprintf(stderr, "json_to_node_id called!\n"); abort(); }
/* Generated stub for json_to_outpoint */
bool json_to_outpoint(const char *buffer UNNEEDED, const jsmntok_t *tok UNNEEDED,
struct bitcoin_outpoint *op UNNEEDED)
{ fprintf(stderr, "json_to_outpoint called!\n"); abort(); }
/* Generated stub for json_to_pubkey */
bool json_to_pubkey(const char *buffer UNNEEDED, const jsmntok_t *tok UNNEEDED,
struct pubkey *pubkey UNNEEDED)
{ fprintf(stderr, "json_to_pubkey called!\n"); abort(); }
/* Generated stub for json_to_short_channel_id */
bool json_to_short_channel_id(const char *buffer UNNEEDED, const jsmntok_t *tok UNNEEDED,
struct short_channel_id *scid UNNEEDED)
{ fprintf(stderr, "json_to_short_channel_id called!\n"); abort(); }
/* Generated stub for json_to_txid */
bool json_to_txid(const char *buffer UNNEEDED, const jsmntok_t *tok UNNEEDED,
struct bitcoin_txid *txid UNNEEDED)
{ fprintf(stderr, "json_to_txid called!\n"); abort(); }
/* Generated stub for segwit_addr_decode */
int segwit_addr_decode(
int* ver UNNEEDED,

View File

@@ -7,8 +7,7 @@
#include <ccan/tal/grab_file/grab_file.h>
#include <ccan/tal/path/path.h>
#include <common/channel_id.h>
#include <common/json.h>
#include <common/json_helpers.h>
#include <common/json_parse.h>
#include <common/json_stream.h>
#include <common/setup.h>
#include <common/wireaddr.h>
@@ -21,9 +20,6 @@ bool amount_asset_is_main(struct amount_asset *asset UNNEEDED)
/* Generated stub for amount_asset_to_sat */
struct amount_sat amount_asset_to_sat(struct amount_asset *asset UNNEEDED)
{ fprintf(stderr, "amount_asset_to_sat called!\n"); abort(); }
/* Generated stub for amount_msat */
struct amount_msat amount_msat(u64 millisatoshis UNNEEDED)
{ fprintf(stderr, "amount_msat called!\n"); abort(); }
/* Generated stub for amount_sat */
struct amount_sat amount_sat(u64 satoshis UNNEEDED)
{ fprintf(stderr, "amount_sat called!\n"); abort(); }
@@ -53,14 +49,6 @@ struct amount_asset amount_sat_to_asset(struct amount_sat *sat UNNEEDED, const u
/* Generated stub for amount_tx_fee */
struct amount_sat amount_tx_fee(u32 fee_per_kw UNNEEDED, size_t weight UNNEEDED)
{ fprintf(stderr, "amount_tx_fee called!\n"); abort(); }
/* Generated stub for deprecated_apis */
bool deprecated_apis;
/* Generated stub for fmt_amount_msat */
const char *fmt_amount_msat(const tal_t *ctx UNNEEDED, struct amount_msat msat UNNEEDED)
{ fprintf(stderr, "fmt_amount_msat called!\n"); abort(); }
/* Generated stub for fmt_amount_sat */
const char *fmt_amount_sat(const tal_t *ctx UNNEEDED, struct amount_sat sat UNNEEDED)
{ fprintf(stderr, "fmt_amount_sat called!\n"); abort(); }
/* Generated stub for fromwire_amount_msat */
struct amount_msat fromwire_amount_msat(const u8 **cursor UNNEEDED, size_t *max UNNEEDED)
{ fprintf(stderr, "fromwire_amount_msat called!\n"); abort(); }
@@ -74,31 +62,34 @@ bool fromwire_channel_id(const u8 **cursor UNNEEDED, size_t *max UNNEEDED,
/* Generated stub for fromwire_node_id */
void fromwire_node_id(const u8 **cursor UNNEEDED, size_t *max UNNEEDED, struct node_id *id UNNEEDED)
{ fprintf(stderr, "fromwire_node_id called!\n"); abort(); }
/* Generated stub for json_add_member */
void json_add_member(struct json_stream *js UNNEEDED,
const char *fieldname UNNEEDED,
bool quote UNNEEDED,
const char *fmt UNNEEDED, ...)
{ fprintf(stderr, "json_add_member called!\n"); abort(); }
/* Generated stub for json_member_direct */
char *json_member_direct(struct json_stream *js UNNEEDED,
const char *fieldname UNNEEDED, size_t extra UNNEEDED)
{ fprintf(stderr, "json_member_direct called!\n"); abort(); }
/* Generated stub for json_object_end */
void json_object_end(struct json_stream *js UNNEEDED)
{ fprintf(stderr, "json_object_end called!\n"); abort(); }
/* Generated stub for json_object_start */
void json_object_start(struct json_stream *ks UNNEEDED, const char *fieldname UNNEEDED)
{ fprintf(stderr, "json_object_start called!\n"); abort(); }
/* Generated stub for node_id_from_hexstr */
bool node_id_from_hexstr(const char *str UNNEEDED, size_t slen UNNEEDED, struct node_id *id UNNEEDED)
{ fprintf(stderr, "node_id_from_hexstr called!\n"); abort(); }
/* Generated stub for parse_amount_msat */
bool parse_amount_msat(struct amount_msat *msat UNNEEDED, const char *s UNNEEDED, size_t slen UNNEEDED)
{ fprintf(stderr, "parse_amount_msat called!\n"); abort(); }
/* Generated stub for parse_amount_sat */
bool parse_amount_sat(struct amount_sat *sat UNNEEDED, const char *s UNNEEDED, size_t slen UNNEEDED)
{ fprintf(stderr, "parse_amount_sat called!\n"); abort(); }
/* Generated stub for json_get_member */
const jsmntok_t *json_get_member(const char *buffer UNNEEDED, const jsmntok_t tok[] UNNEEDED,
const char *label UNNEEDED)
{ fprintf(stderr, "json_get_member called!\n"); abort(); }
/* Generated stub for json_next */
const jsmntok_t *json_next(const jsmntok_t *tok UNNEEDED)
{ fprintf(stderr, "json_next called!\n"); abort(); }
/* Generated stub for json_to_pubkey */
bool json_to_pubkey(const char *buffer UNNEEDED, const jsmntok_t *tok UNNEEDED,
struct pubkey *pubkey UNNEEDED)
{ fprintf(stderr, "json_to_pubkey called!\n"); abort(); }
/* Generated stub for json_to_secret */
bool json_to_secret(const char *buffer UNNEEDED, const jsmntok_t *tok UNNEEDED, struct secret *dest UNNEEDED)
{ fprintf(stderr, "json_to_secret called!\n"); abort(); }
/* Generated stub for json_to_short_channel_id */
bool json_to_short_channel_id(const char *buffer UNNEEDED, const jsmntok_t *tok UNNEEDED,
struct short_channel_id *scid UNNEEDED)
{ fprintf(stderr, "json_to_short_channel_id called!\n"); abort(); }
/* Generated stub for json_tok_bin_from_hex */
u8 *json_tok_bin_from_hex(const tal_t *ctx UNNEEDED, const char *buffer UNNEEDED, const jsmntok_t *tok UNNEEDED)
{ fprintf(stderr, "json_tok_bin_from_hex called!\n"); abort(); }
/* Generated stub for json_tok_startswith */
bool json_tok_startswith(const char *buffer UNNEEDED, const jsmntok_t *tok UNNEEDED,
const char *prefix UNNEEDED)
{ fprintf(stderr, "json_tok_startswith called!\n"); abort(); }
/* Generated stub for json_tok_streq */
bool json_tok_streq(const char *buffer UNNEEDED, const jsmntok_t *tok UNNEEDED, const char *str UNNEEDED)
{ fprintf(stderr, "json_tok_streq called!\n"); abort(); }
/* Generated stub for towire_amount_msat */
void towire_amount_msat(u8 **pptr UNNEEDED, const struct amount_msat msat UNNEEDED)
{ fprintf(stderr, "towire_amount_msat called!\n"); abort(); }

View File

@@ -7,8 +7,7 @@
#include <ccan/tal/grab_file/grab_file.h>
#include <ccan/tal/path/path.h>
#include <common/channel_id.h>
#include <common/json.h>
#include <common/json_helpers.h>
#include <common/json_parse.h>
#include <common/json_stream.h>
#include <common/setup.h>
#include <common/wireaddr.h>
@@ -21,9 +20,6 @@ bool amount_asset_is_main(struct amount_asset *asset UNNEEDED)
/* Generated stub for amount_asset_to_sat */
struct amount_sat amount_asset_to_sat(struct amount_asset *asset UNNEEDED)
{ fprintf(stderr, "amount_asset_to_sat called!\n"); abort(); }
/* Generated stub for amount_msat */
struct amount_msat amount_msat(u64 millisatoshis UNNEEDED)
{ fprintf(stderr, "amount_msat called!\n"); abort(); }
/* Generated stub for amount_sat */
struct amount_sat amount_sat(u64 satoshis UNNEEDED)
{ fprintf(stderr, "amount_sat called!\n"); abort(); }
@@ -53,17 +49,6 @@ struct amount_asset amount_sat_to_asset(struct amount_sat *sat UNNEEDED, const u
/* Generated stub for amount_tx_fee */
struct amount_sat amount_tx_fee(u32 fee_per_kw UNNEEDED, size_t weight UNNEEDED)
{ fprintf(stderr, "amount_tx_fee called!\n"); abort(); }
/* Generated stub for deprecated_apis */
bool deprecated_apis;
/* Generated stub for fmt_amount_msat */
const char *fmt_amount_msat(const tal_t *ctx UNNEEDED, struct amount_msat msat UNNEEDED)
{ fprintf(stderr, "fmt_amount_msat called!\n"); abort(); }
/* Generated stub for fmt_amount_sat */
const char *fmt_amount_sat(const tal_t *ctx UNNEEDED, struct amount_sat sat UNNEEDED)
{ fprintf(stderr, "fmt_amount_sat called!\n"); abort(); }
/* Generated stub for fmt_wireaddr_without_port */
char *fmt_wireaddr_without_port(const tal_t *ctx UNNEEDED, const struct wireaddr *a UNNEEDED)
{ fprintf(stderr, "fmt_wireaddr_without_port called!\n"); abort(); }
/* Generated stub for fromwire_amount_msat */
struct amount_msat fromwire_amount_msat(const u8 **cursor UNNEEDED, size_t *max UNNEEDED)
{ fprintf(stderr, "fromwire_amount_msat called!\n"); abort(); }
@@ -77,31 +62,34 @@ bool fromwire_channel_id(const u8 **cursor UNNEEDED, size_t *max UNNEEDED,
/* Generated stub for fromwire_node_id */
void fromwire_node_id(const u8 **cursor UNNEEDED, size_t *max UNNEEDED, struct node_id *id UNNEEDED)
{ fprintf(stderr, "fromwire_node_id called!\n"); abort(); }
/* Generated stub for json_add_member */
void json_add_member(struct json_stream *js UNNEEDED,
const char *fieldname UNNEEDED,
bool quote UNNEEDED,
const char *fmt UNNEEDED, ...)
{ fprintf(stderr, "json_add_member called!\n"); abort(); }
/* Generated stub for json_member_direct */
char *json_member_direct(struct json_stream *js UNNEEDED,
const char *fieldname UNNEEDED, size_t extra UNNEEDED)
{ fprintf(stderr, "json_member_direct called!\n"); abort(); }
/* Generated stub for json_object_end */
void json_object_end(struct json_stream *js UNNEEDED)
{ fprintf(stderr, "json_object_end called!\n"); abort(); }
/* Generated stub for json_object_start */
void json_object_start(struct json_stream *ks UNNEEDED, const char *fieldname UNNEEDED)
{ fprintf(stderr, "json_object_start called!\n"); abort(); }
/* Generated stub for node_id_from_hexstr */
bool node_id_from_hexstr(const char *str UNNEEDED, size_t slen UNNEEDED, struct node_id *id UNNEEDED)
{ fprintf(stderr, "node_id_from_hexstr called!\n"); abort(); }
/* Generated stub for parse_amount_msat */
bool parse_amount_msat(struct amount_msat *msat UNNEEDED, const char *s UNNEEDED, size_t slen UNNEEDED)
{ fprintf(stderr, "parse_amount_msat called!\n"); abort(); }
/* Generated stub for parse_amount_sat */
bool parse_amount_sat(struct amount_sat *sat UNNEEDED, const char *s UNNEEDED, size_t slen UNNEEDED)
{ fprintf(stderr, "parse_amount_sat called!\n"); abort(); }
/* Generated stub for json_get_member */
const jsmntok_t *json_get_member(const char *buffer UNNEEDED, const jsmntok_t tok[] UNNEEDED,
const char *label UNNEEDED)
{ fprintf(stderr, "json_get_member called!\n"); abort(); }
/* Generated stub for json_next */
const jsmntok_t *json_next(const jsmntok_t *tok UNNEEDED)
{ fprintf(stderr, "json_next called!\n"); abort(); }
/* Generated stub for json_to_pubkey */
bool json_to_pubkey(const char *buffer UNNEEDED, const jsmntok_t *tok UNNEEDED,
struct pubkey *pubkey UNNEEDED)
{ fprintf(stderr, "json_to_pubkey called!\n"); abort(); }
/* Generated stub for json_to_secret */
bool json_to_secret(const char *buffer UNNEEDED, const jsmntok_t *tok UNNEEDED, struct secret *dest UNNEEDED)
{ fprintf(stderr, "json_to_secret called!\n"); abort(); }
/* Generated stub for json_to_short_channel_id */
bool json_to_short_channel_id(const char *buffer UNNEEDED, const jsmntok_t *tok UNNEEDED,
struct short_channel_id *scid UNNEEDED)
{ fprintf(stderr, "json_to_short_channel_id called!\n"); abort(); }
/* Generated stub for json_tok_bin_from_hex */
u8 *json_tok_bin_from_hex(const tal_t *ctx UNNEEDED, const char *buffer UNNEEDED, const jsmntok_t *tok UNNEEDED)
{ fprintf(stderr, "json_tok_bin_from_hex called!\n"); abort(); }
/* Generated stub for json_tok_startswith */
bool json_tok_startswith(const char *buffer UNNEEDED, const jsmntok_t *tok UNNEEDED,
const char *prefix UNNEEDED)
{ fprintf(stderr, "json_tok_startswith called!\n"); abort(); }
/* Generated stub for json_tok_streq */
bool json_tok_streq(const char *buffer UNNEEDED, const jsmntok_t *tok UNNEEDED, const char *str UNNEEDED)
{ fprintf(stderr, "json_tok_streq called!\n"); abort(); }
/* Generated stub for towire_amount_msat */
void towire_amount_msat(u8 **pptr UNNEEDED, const struct amount_msat msat UNNEEDED)
{ fprintf(stderr, "towire_amount_msat called!\n"); abort(); }

View File

@@ -29,14 +29,13 @@ DEVTOOLS_COMMON_OBJS := \
common/hash_u5.o \
common/hmac.o \
common/htlc_state.o \
common/json_parse.o \
common/json_parse_simple.o \
common/memleak.o \
common/node_id.o \
common/per_peer_state.o \
common/psbt_open.o \
common/pseudorand.o \
common/json.o \
common/json_helpers.o \
common/json_stream.o \
common/setup.o \
common/type_to_string.o \
common/utils.o \

View File

@@ -6,7 +6,7 @@
#include <ccan/tal/grab_file/grab_file.h>
#include <ccan/tal/str/str.h>
#include <common/ecdh.h>
#include <common/json_helpers.h>
#include <common/json_parse.h>
#include <common/onion.h>
#include <common/sphinx.h>
#include <common/version.h>

View File

@@ -17,8 +17,6 @@ GOSSIPD_TEST_COMMON_OBJS := \
common/features.o \
common/hmac.o \
common/node_id.o \
common/json.o \
common/json_helpers.o \
common/lease_rates.o \
common/onion.o \
common/pseudorand.o \
@@ -46,6 +44,10 @@ gossipd/test/run-onion_message: \
common/onion.o \
common/sphinx.o \
# JSON needed for this test
gossipd/test/run-extended-info: \
common/json_parse.o \
common/json_parse_simple.o
$(GOSSIPD_TEST_PROGRAMS): $(GOSSIPD_TEST_COMMON_OBJS) $(BITCOIN_OBJS)

View File

@@ -59,8 +59,6 @@ bool cupdate_different(struct gossip_store *gs UNNEEDED,
const struct half_chan *hc UNNEEDED,
const u8 *cupdate UNNEEDED)
{ fprintf(stderr, "cupdate_different called!\n"); abort(); }
/* Generated stub for deprecated_apis */
bool deprecated_apis;
/* Generated stub for ecdh */
void ecdh(const struct pubkey *point UNNEEDED, struct secret *ss UNNEEDED)
{ fprintf(stderr, "ecdh called!\n"); abort(); }
@@ -94,22 +92,6 @@ void gossip_store_mark_channel_deleted(struct gossip_store *gs UNNEEDED,
struct gossip_store *gossip_store_new(struct routing_state *rstate UNNEEDED,
struct list_head *peers UNNEEDED)
{ fprintf(stderr, "gossip_store_new called!\n"); abort(); }
/* Generated stub for json_add_member */
void json_add_member(struct json_stream *js UNNEEDED,
const char *fieldname UNNEEDED,
bool quote UNNEEDED,
const char *fmt UNNEEDED, ...)
{ fprintf(stderr, "json_add_member called!\n"); abort(); }
/* Generated stub for json_member_direct */
char *json_member_direct(struct json_stream *js UNNEEDED,
const char *fieldname UNNEEDED, size_t extra UNNEEDED)
{ fprintf(stderr, "json_member_direct called!\n"); abort(); }
/* Generated stub for json_object_end */
void json_object_end(struct json_stream *js UNNEEDED)
{ fprintf(stderr, "json_object_end called!\n"); abort(); }
/* Generated stub for json_object_start */
void json_object_start(struct json_stream *ks UNNEEDED, const char *fieldname UNNEEDED)
{ fprintf(stderr, "json_object_start called!\n"); abort(); }
/* Generated stub for memleak_add_helper_ */
void memleak_add_helper_(const tal_t *p UNNEEDED, void (*cb)(struct htable *memtable UNNEEDED,
const tal_t *)){ }

View File

@@ -27,8 +27,6 @@ bool blinding_next_pubkey(const struct pubkey *pk UNNEEDED,
/* Generated stub for daemon_conn_send */
void daemon_conn_send(struct daemon_conn *dc UNNEEDED, const u8 *msg UNNEEDED)
{ fprintf(stderr, "daemon_conn_send called!\n"); abort(); }
/* Generated stub for deprecated_apis */
bool deprecated_apis;
/* Generated stub for ecdh */
void ecdh(const struct pubkey *point UNNEEDED, struct secret *ss UNNEEDED)
{ fprintf(stderr, "ecdh called!\n"); abort(); }
@@ -64,22 +62,6 @@ u8 *handle_channel_update(struct routing_state *rstate UNNEEDED, const u8 *updat
u8 *handle_node_announcement(struct routing_state *rstate UNNEEDED, const u8 *node UNNEEDED,
struct peer *peer UNNEEDED, bool *was_unknown UNNEEDED)
{ fprintf(stderr, "handle_node_announcement called!\n"); abort(); }
/* Generated stub for json_add_member */
void json_add_member(struct json_stream *js UNNEEDED,
const char *fieldname UNNEEDED,
bool quote UNNEEDED,
const char *fmt UNNEEDED, ...)
{ fprintf(stderr, "json_add_member called!\n"); abort(); }
/* Generated stub for json_member_direct */
char *json_member_direct(struct json_stream *js UNNEEDED,
const char *fieldname UNNEEDED, size_t extra UNNEEDED)
{ fprintf(stderr, "json_member_direct called!\n"); abort(); }
/* Generated stub for json_object_end */
void json_object_end(struct json_stream *js UNNEEDED)
{ fprintf(stderr, "json_object_end called!\n"); abort(); }
/* Generated stub for json_object_start */
void json_object_start(struct json_stream *ks UNNEEDED, const char *fieldname UNNEEDED)
{ fprintf(stderr, "json_object_start called!\n"); abort(); }
/* Generated stub for master_badmsg */
void master_badmsg(u32 type_expected UNNEEDED, const u8 *msg)
{ fprintf(stderr, "master_badmsg called!\n"); abort(); }

View File

@@ -45,8 +45,6 @@ bigsize_t *decode_scid_query_flags(const tal_t *ctx UNNEEDED,
/* Generated stub for decode_short_ids */
struct short_channel_id *decode_short_ids(const tal_t *ctx UNNEEDED, const u8 *encoded UNNEEDED)
{ fprintf(stderr, "decode_short_ids called!\n"); abort(); }
/* Generated stub for deprecated_apis */
bool deprecated_apis;
/* Generated stub for ecdh */
void ecdh(const struct pubkey *point UNNEEDED, struct secret *ss UNNEEDED)
{ fprintf(stderr, "ecdh called!\n"); abort(); }
@@ -90,22 +88,6 @@ u8 *handle_channel_update(struct routing_state *rstate UNNEEDED, const u8 *updat
u8 *handle_node_announcement(struct routing_state *rstate UNNEEDED, const u8 *node UNNEEDED,
struct peer *peer UNNEEDED, bool *was_unknown UNNEEDED)
{ fprintf(stderr, "handle_node_announcement called!\n"); abort(); }
/* Generated stub for json_add_member */
void json_add_member(struct json_stream *js UNNEEDED,
const char *fieldname UNNEEDED,
bool quote UNNEEDED,
const char *fmt UNNEEDED, ...)
{ fprintf(stderr, "json_add_member called!\n"); abort(); }
/* Generated stub for json_member_direct */
char *json_member_direct(struct json_stream *js UNNEEDED,
const char *fieldname UNNEEDED, size_t extra UNNEEDED)
{ fprintf(stderr, "json_member_direct called!\n"); abort(); }
/* Generated stub for json_object_end */
void json_object_end(struct json_stream *js UNNEEDED)
{ fprintf(stderr, "json_object_end called!\n"); abort(); }
/* Generated stub for json_object_start */
void json_object_start(struct json_stream *ks UNNEEDED, const char *fieldname UNNEEDED)
{ fprintf(stderr, "json_object_start called!\n"); abort(); }
/* Generated stub for master_badmsg */
void master_badmsg(u32 type_expected UNNEEDED, const u8 *msg)
{ fprintf(stderr, "master_badmsg called!\n"); abort(); }

View File

@@ -5,7 +5,7 @@
#include <common/blinding.h>
#include <common/channel_type.h>
#include <common/ecdh.h>
#include <common/json_helpers.h>
#include <common/json_parse.h>
#include <common/json_stream.h>
#include <common/onionreply.h>
#include <common/setup.h>
@@ -45,8 +45,6 @@ bigsize_t *decode_scid_query_flags(const tal_t *ctx UNNEEDED,
/* Generated stub for decode_short_ids */
struct short_channel_id *decode_short_ids(const tal_t *ctx UNNEEDED, const u8 *encoded UNNEEDED)
{ fprintf(stderr, "decode_short_ids called!\n"); abort(); }
/* Generated stub for deprecated_apis */
bool deprecated_apis;
/* Generated stub for ecdh */
void ecdh(const struct pubkey *point UNNEEDED, struct secret *ss UNNEEDED)
{ fprintf(stderr, "ecdh called!\n"); abort(); }
@@ -67,22 +65,6 @@ const u8 *gossip_store_get(const tal_t *ctx UNNEEDED,
struct gossip_store *gs UNNEEDED,
u64 offset UNNEEDED)
{ fprintf(stderr, "gossip_store_get called!\n"); abort(); }
/* Generated stub for json_add_member */
void json_add_member(struct json_stream *js UNNEEDED,
const char *fieldname UNNEEDED,
bool quote UNNEEDED,
const char *fmt UNNEEDED, ...)
{ fprintf(stderr, "json_add_member called!\n"); abort(); }
/* Generated stub for json_member_direct */
char *json_member_direct(struct json_stream *js UNNEEDED,
const char *fieldname UNNEEDED, size_t extra UNNEEDED)
{ fprintf(stderr, "json_member_direct called!\n"); abort(); }
/* Generated stub for json_object_end */
void json_object_end(struct json_stream *js UNNEEDED)
{ fprintf(stderr, "json_object_end called!\n"); abort(); }
/* Generated stub for json_object_start */
void json_object_start(struct json_stream *ks UNNEEDED, const char *fieldname UNNEEDED)
{ fprintf(stderr, "json_object_start called!\n"); abort(); }
/* Generated stub for master_badmsg */
void master_badmsg(u32 type_expected UNNEEDED, const u8 *msg)
{ fprintf(stderr, "master_badmsg called!\n"); abort(); }

View File

@@ -26,27 +26,9 @@ bool blinding_next_pubkey(const struct pubkey *pk UNNEEDED,
const struct sha256 *h UNNEEDED,
struct pubkey *next UNNEEDED)
{ fprintf(stderr, "blinding_next_pubkey called!\n"); abort(); }
/* Generated stub for deprecated_apis */
bool deprecated_apis;
/* Generated stub for ecdh */
void ecdh(const struct pubkey *point UNNEEDED, struct secret *ss UNNEEDED)
{ fprintf(stderr, "ecdh called!\n"); abort(); }
/* Generated stub for json_add_member */
void json_add_member(struct json_stream *js UNNEEDED,
const char *fieldname UNNEEDED,
bool quote UNNEEDED,
const char *fmt UNNEEDED, ...)
{ fprintf(stderr, "json_add_member called!\n"); abort(); }
/* Generated stub for json_member_direct */
char *json_member_direct(struct json_stream *js UNNEEDED,
const char *fieldname UNNEEDED, size_t extra UNNEEDED)
{ fprintf(stderr, "json_member_direct called!\n"); abort(); }
/* Generated stub for json_object_end */
void json_object_end(struct json_stream *js UNNEEDED)
{ fprintf(stderr, "json_object_end called!\n"); abort(); }
/* Generated stub for json_object_start */
void json_object_start(struct json_stream *ks UNNEEDED, const char *fieldname UNNEEDED)
{ fprintf(stderr, "json_object_start called!\n"); abort(); }
/* Generated stub for new_onionreply */
struct onionreply *new_onionreply(const tal_t *ctx UNNEEDED, const u8 *contents TAKES UNNEEDED)
{ fprintf(stderr, "new_onionreply called!\n"); abort(); }

View File

@@ -30,8 +30,6 @@ bool cupdate_different(struct gossip_store *gs UNNEEDED,
const struct half_chan *hc UNNEEDED,
const u8 *cupdate UNNEEDED)
{ fprintf(stderr, "cupdate_different called!\n"); abort(); }
/* Generated stub for deprecated_apis */
bool deprecated_apis;
/* Generated stub for ecdh */
void ecdh(const struct pubkey *point UNNEEDED, struct secret *ss UNNEEDED)
{ fprintf(stderr, "ecdh called!\n"); abort(); }
@@ -61,22 +59,6 @@ const u8 *gossip_store_get_private_update(const tal_t *ctx UNNEEDED,
void gossip_store_mark_channel_deleted(struct gossip_store *gs UNNEEDED,
const struct short_channel_id *scid UNNEEDED)
{ fprintf(stderr, "gossip_store_mark_channel_deleted called!\n"); abort(); }
/* Generated stub for json_add_member */
void json_add_member(struct json_stream *js UNNEEDED,
const char *fieldname UNNEEDED,
bool quote UNNEEDED,
const char *fmt UNNEEDED, ...)
{ fprintf(stderr, "json_add_member called!\n"); abort(); }
/* Generated stub for json_member_direct */
char *json_member_direct(struct json_stream *js UNNEEDED,
const char *fieldname UNNEEDED, size_t extra UNNEEDED)
{ fprintf(stderr, "json_member_direct called!\n"); abort(); }
/* Generated stub for json_object_end */
void json_object_end(struct json_stream *js UNNEEDED)
{ fprintf(stderr, "json_object_end called!\n"); abort(); }
/* Generated stub for json_object_start */
void json_object_start(struct json_stream *ks UNNEEDED, const char *fieldname UNNEEDED)
{ fprintf(stderr, "json_object_start called!\n"); abort(); }
/* Generated stub for memleak_add_helper_ */
void memleak_add_helper_(const tal_t *p UNNEEDED, void (*cb)(struct htable *memtable UNNEEDED,
const tal_t *)){ }

View File

@@ -101,17 +101,16 @@ LIGHTNINGD_COMMON_OBJS := \
common/htlc_wire.o \
common/key_derive.o \
common/keyset.o \
common/json.o \
common/json_helpers.o \
common/json_param.o \
common/json_parse.o \
common/json_parse_simple.o \
common/json_stream.o \
common/json_tok.o \
common/lease_rates.o \
common/memleak.o \
common/msg_queue.o \
common/node_id.o \
common/onion.o \
common/onionreply.o \
common/param.o \
common/penalty_base.o \
common/per_peer_state.o \
common/permute_tx.o \

View File

@@ -12,7 +12,7 @@
#include <ccan/array_size/array_size.h>
#include <ccan/io/io.h>
#include <ccan/tal/str/str.h>
#include <common/json_helpers.h>
#include <common/json_parse.h>
#include <common/memleak.h>
#include <db/exec.h>
#include <lightningd/bitcoind.h>

View File

@@ -7,8 +7,8 @@
#include <ccan/tal/str/str.h>
#include <common/htlc_tx.h>
#include <common/json_command.h>
#include <common/json_param.h>
#include <common/memleak.h>
#include <common/param.h>
#include <common/timeout.h>
#include <common/type_to_string.h>
#include <db/exec.h>

View File

@@ -4,7 +4,6 @@
#include <common/closing_fee.h>
#include <common/fee_states.h>
#include <common/json_command.h>
#include <common/json_helpers.h>
#include <common/type_to_string.h>
#include <common/wire_error.h>
#include <connectd/connectd_wiregen.h>

View File

@@ -2,10 +2,9 @@
#include <ccan/cast/cast.h>
#include <channeld/channeld_wiregen.h>
#include <common/json_command.h>
#include <common/json_helpers.h>
#include <common/json_tok.h>
#include <common/json_param.h>
#include <common/json_stream.h>
#include <common/memleak.h>
#include <common/param.h>
#include <common/shutdown_scriptpubkey.h>
#include <common/type_to_string.h>
#include <common/wire_error.h>

View File

@@ -12,9 +12,7 @@
#include <common/fee_states.h>
#include <common/initial_commit_tx.h>
#include <common/json_command.h>
#include <common/json_helpers.h>
#include <common/json_tok.h>
#include <common/param.h>
#include <common/json_param.h>
#include <common/shutdown_scriptpubkey.h>
#include <common/timeout.h>
#include <common/type_to_string.h>

View File

@@ -4,10 +4,8 @@
#include <ccan/tal/str/str.h>
#include <common/configdir.h>
#include <common/json_command.h>
#include <common/json_helpers.h>
#include <common/json_tok.h>
#include <common/json_param.h>
#include <common/memleak.h>
#include <common/param.h>
#include <common/timeout.h>
#include <common/type_to_string.h>
#include <connectd/connectd_wiregen.h>
@@ -17,7 +15,6 @@
#include <lightningd/connect_control.h>
#include <lightningd/dual_open_control.h>
#include <lightningd/hsm_control.h>
#include <lightningd/jsonrpc.h>
#include <lightningd/lightningd.h>
#include <lightningd/onion_message.h>
#include <lightningd/opening_common.h>

View File

@@ -1,8 +1,8 @@
#include "config.h"
#include <ccan/tal/str/str.h>
#include <common/json_command.h>
#include <common/json_tok.h>
#include <common/param.h>
#include <common/json_param.h>
#include <common/json_stream.h>
#include <lightningd/jsonrpc.h>
#include <lightningd/lightningd.h>

View File

@@ -9,9 +9,7 @@
#include <ccan/tal/str/str.h>
#include <common/blockheight_states.h>
#include <common/json_command.h>
#include <common/json_helpers.h>
#include <common/json_tok.h>
#include <common/param.h>
#include <common/json_param.h>
#include <common/psbt_open.h>
#include <common/shutdown_scriptpubkey.h>
#include <common/type_to_string.h>

View File

@@ -3,9 +3,8 @@
#include <ccan/ptrint/ptrint.h>
#include <channeld/channeld_wiregen.h>
#include <common/json_command.h>
#include <common/json_helpers.h>
#include <common/json_tok.h>
#include <common/param.h>
#include <common/json_param.h>
#include <common/json_stream.h>
#include <common/type_to_string.h>
#include <gossipd/gossipd_wiregen.h>
#include <hsmd/capabilities.h>

View File

@@ -5,9 +5,8 @@
#include <common/errcode.h>
#include <common/hsm_encryption.h>
#include <common/json_command.h>
#include <common/json_helpers.h>
#include <common/json_tok.h>
#include <common/param.h>
#include <common/json_param.h>
#include <common/jsonrpc_errors.h>
#include <common/type_to_string.h>
#include <errno.h>
#include <hsmd/hsmd_wiregen.h>

View File

@@ -9,11 +9,9 @@
#include <common/bolt12_merkle.h>
#include <common/configdir.h>
#include <common/json_command.h>
#include <common/json_helpers.h>
#include <common/json_tok.h>
#include <common/json_param.h>
#include <common/onion.h>
#include <common/overflows.h>
#include <common/param.h>
#include <common/random_select.h>
#include <common/timeout.h>
#include <common/type_to_string.h>

View File

@@ -1,8 +1,8 @@
#include "config.h"
#include <bitcoin/pubkey.h>
#include <ccan/str/hex/hex.h>
#include <common/json_command.h>
#include <common/json_helpers.h>
#include <common/json_tok.h>
#include <common/json_param.h>
#include <lightningd/chaintopology.h>
#include <lightningd/json.h>

View File

@@ -22,10 +22,8 @@
#include <ccan/tal/str/str.h>
#include <common/configdir.h>
#include <common/json_command.h>
#include <common/json_helpers.h>
#include <common/json_tok.h>
#include <common/json_param.h>
#include <common/memleak.h>
#include <common/param.h>
#include <common/timeout.h>
#include <db/exec.h>
#include <fcntl.h>

View File

@@ -3,7 +3,6 @@
#include "config.h"
#include <ccan/list/list.h>
#include <common/autodata.h>
#include <common/json.h>
#include <common/json_stream.h>
#include <common/status_levels.h>

View File

@@ -7,9 +7,8 @@
#include <ccan/tal/link/link.h>
#include <ccan/tal/str/str.h>
#include <common/json_command.h>
#include <common/json_helpers.h>
#include <common/json_param.h>
#include <common/memleak.h>
#include <common/param.h>
#include <errno.h>
#include <fcntl.h>
#include <lightningd/log.h>

View File

@@ -4,8 +4,8 @@
#include <backtrace.h>
#include <ccan/tal/str/str.h>
#include <common/json_command.h>
#include <common/json_param.h>
#include <common/memleak.h>
#include <common/param.h>
#include <common/timeout.h>
#include <connectd/connectd_wiregen.h>
#include <errno.h>

View File

@@ -1,6 +1,5 @@
#include "config.h"
#include <common/configdir.h>
#include <common/json_helpers.h>
#include <common/type_to_string.h>
#include <lightningd/channel.h>
#include <lightningd/coin_mvts.h>

View File

@@ -5,9 +5,8 @@
#include <common/bolt12_merkle.h>
#include <common/configdir.h>
#include <common/json_command.h>
#include <common/json_helpers.h>
#include <common/json_tok.h>
#include <common/param.h>
#include <common/json_param.h>
#include <common/json_stream.h>
#include <common/type_to_string.h>
#include <errno.h>
#include <hsmd/hsmd_wiregen.h>

View File

@@ -2,9 +2,7 @@
#include <ccan/mem/mem.h>
#include <common/blindedpath.h>
#include <common/json_command.h>
#include <common/json_helpers.h>
#include <common/json_tok.h>
#include <common/param.h>
#include <common/json_param.h>
#include <common/type_to_string.h>
#include <connectd/connectd_wiregen.h>
#include <lightningd/channel.h>

View File

@@ -9,10 +9,8 @@
#include <common/configdir.h>
#include <common/fee_states.h>
#include <common/json_command.h>
#include <common/json_helpers.h>
#include <common/json_tok.h>
#include <common/json_param.h>
#include <common/memleak.h>
#include <common/param.h>
#include <common/scb_wiregen.h>
#include <common/type_to_string.h>
#include <connectd/connectd_wiregen.h>

View File

@@ -12,9 +12,7 @@
#include <common/features.h>
#include <common/hsm_encryption.h>
#include <common/json_command.h>
#include <common/json_helpers.h>
#include <common/json_tok.h>
#include <common/param.h>
#include <common/json_param.h>
#include <common/type_to_string.h>
#include <common/version.h>
#include <common/wireaddr.h>

View File

@@ -3,11 +3,9 @@
#include <common/bolt12_merkle.h>
#include <common/configdir.h>
#include <common/json_command.h>
#include <common/json_helpers.h>
#include <common/json_tok.h>
#include <common/json_param.h>
#include <common/onion.h>
#include <common/onionreply.h>
#include <common/param.h>
#include <common/route.h>
#include <common/timeout.h>
#include <common/type_to_string.h>

View File

@@ -20,11 +20,9 @@
#include <common/htlc_trim.h>
#include <common/initial_commit_tx.h>
#include <common/json_command.h>
#include <common/json_helpers.h>
#include <common/json_tok.h>
#include <common/json_param.h>
#include <common/jsonrpc_errors.h>
#include <common/key_derive.h>
#include <common/param.h>
#include <common/scb_wiregen.h>
#include <common/shutdown_scriptpubkey.h>
#include <common/status.h>

View File

@@ -6,7 +6,7 @@
#include <ccan/list/list.h>
#include <common/channel_config.h>
#include <common/htlc.h>
#include <common/json.h>
#include <common/json_parse.h>
#include <common/node_id.h>
#include <common/wireaddr.h>
#include <wallet/wallet.h>

View File

@@ -6,11 +6,9 @@
#include <common/configdir.h>
#include <common/ecdh.h>
#include <common/json_command.h>
#include <common/json_helpers.h>
#include <common/json_tok.h>
#include <common/json_param.h>
#include <common/onion.h>
#include <common/onionreply.h>
#include <common/param.h>
#include <common/timeout.h>
#include <common/type_to_string.h>
#include <db/exec.h>

View File

@@ -1,7 +1,6 @@
#include "config.h"
#include <common/json_command.h>
#include <common/json_tok.h>
#include <common/param.h>
#include <common/json_param.h>
#include <connectd/connectd_wiregen.h>
#include <lightningd/channel.h>
#include <lightningd/jsonrpc.h>

View File

@@ -12,7 +12,6 @@
#include <common/configdir.h>
#include <common/features.h>
#include <common/json_command.h>
#include <common/json_helpers.h>
#include <common/memleak.h>
#include <common/timeout.h>
#include <common/version.h>

View File

@@ -2,9 +2,8 @@
#include <ccan/tal/path/path.h>
#include <ccan/tal/str/str.h>
#include <common/json_command.h>
#include <common/json_tok.h>
#include <common/json_param.h>
#include <common/memleak.h>
#include <common/param.h>
#include <common/timeout.h>
#include <errno.h>
#include <lightningd/notification.h>

View File

@@ -1,5 +1,6 @@
#include "config.h"
#include <ccan/io/io.h>
#include <common/json_parse.h>
#include <common/memleak.h>
#include <db/exec.h>
#include <db/utils.h>

View File

@@ -1,6 +1,6 @@
#include "config.h"
#include <common/bolt11.h>
#include <common/json_helpers.h>
#include <common/json_parse.h>
#include <common/type_to_string.h>
#include <gossipd/gossipd_wiregen.h>
#include <lightningd/channel.h>

View File

@@ -1,9 +1,7 @@
#include "config.h"
#include <common/bech32.h>
#include <common/json_command.h>
#include <common/json_helpers.h>
#include <common/json_tok.h>
#include <common/param.h>
#include <common/json_param.h>
#include <errno.h>
#include <hsmd/hsmd_wiregen.h>
#include <lightningd/json.h>

View File

@@ -15,7 +15,7 @@ LIGHTNINGD_TEST_COMMON_OBJS := \
common/daemon_conn.o \
common/htlc_state.o \
common/htlc_wire.o \
common/json.o \
common/json_parse_simple.o \
common/key_derive.o \
common/pseudorand.o \
common/random_select.o \

View File

@@ -111,16 +111,6 @@ void htlcs_notify_new_block(struct lightningd *ld UNNEEDED, u32 height UNNEEDED)
void htlcs_resubmit(struct lightningd *ld UNNEEDED,
struct htlc_in_map *unconnected_htlcs_in UNNEEDED)
{ fprintf(stderr, "htlcs_resubmit called!\n"); abort(); }
/* Generated stub for json_add_member */
void json_add_member(struct json_stream *js UNNEEDED,
const char *fieldname UNNEEDED,
bool quote UNNEEDED,
const char *fmt UNNEEDED, ...)
{ fprintf(stderr, "json_add_member called!\n"); abort(); }
/* Generated stub for json_member_direct */
char *json_member_direct(struct json_stream *js UNNEEDED,
const char *fieldname UNNEEDED, size_t extra UNNEEDED)
{ fprintf(stderr, "json_member_direct called!\n"); abort(); }
/* Generated stub for jsonrpc_listen */
void jsonrpc_listen(struct jsonrpc *rpc UNNEEDED, struct lightningd *ld UNNEEDED)
{ fprintf(stderr, "jsonrpc_listen called!\n"); abort(); }

View File

@@ -331,23 +331,38 @@ void json_add_amount_sat_msat(struct json_stream *result UNNEEDED,
void json_add_bolt11(struct json_stream *response UNNEEDED,
const struct bolt11 *b11 UNNEEDED)
{ fprintf(stderr, "json_add_bolt11 called!\n"); abort(); }
/* Generated stub for json_add_bool */
void json_add_bool(struct json_stream *result UNNEEDED, const char *fieldname UNNEEDED,
bool value UNNEEDED)
{ fprintf(stderr, "json_add_bool called!\n"); abort(); }
/* Generated stub for json_add_escaped_string */
void json_add_escaped_string(struct json_stream *result UNNEEDED,
const char *fieldname UNNEEDED,
const struct json_escape *esc TAKES UNNEEDED)
{ fprintf(stderr, "json_add_escaped_string called!\n"); abort(); }
/* Generated stub for json_add_hex_talarr */
void json_add_hex_talarr(struct json_stream *result UNNEEDED,
const char *fieldname UNNEEDED,
const tal_t *data UNNEEDED)
{ fprintf(stderr, "json_add_hex_talarr called!\n"); abort(); }
/* Generated stub for json_add_invstring */
void json_add_invstring(struct json_stream *result UNNEEDED, const char *invstring UNNEEDED)
{ fprintf(stderr, "json_add_invstring called!\n"); abort(); }
/* Generated stub for json_add_log */
void json_add_log(struct json_stream *result UNNEEDED,
const struct log_book *lr UNNEEDED,
const struct node_id *node_id UNNEEDED,
enum log_level minlevel UNNEEDED)
{ fprintf(stderr, "json_add_log called!\n"); abort(); }
/* Generated stub for json_add_member */
void json_add_member(struct json_stream *js UNNEEDED,
const char *fieldname UNNEEDED,
bool quote UNNEEDED,
const char *fmt UNNEEDED, ...)
{ fprintf(stderr, "json_add_member called!\n"); abort(); }
/* Generated stub for json_add_node_id */
void json_add_node_id(struct json_stream *response UNNEEDED,
const char *fieldname UNNEEDED,
const struct node_id *id UNNEEDED)
{ fprintf(stderr, "json_add_node_id called!\n"); abort(); }
/* Generated stub for json_add_num */
void json_add_num(struct json_stream *result UNNEEDED, const char *fieldname UNNEEDED,
unsigned int value UNNEEDED)
{ fprintf(stderr, "json_add_num called!\n"); abort(); }
/* Generated stub for json_add_preimage */
void json_add_preimage(struct json_stream *result UNNEEDED, const char *fieldname UNNEEDED,
const struct preimage *preimage UNNEEDED)
@@ -366,6 +381,18 @@ void json_add_short_channel_id(struct json_stream *response UNNEEDED,
const char *fieldname UNNEEDED,
const struct short_channel_id *id UNNEEDED)
{ fprintf(stderr, "json_add_short_channel_id called!\n"); abort(); }
/* Generated stub for json_add_string */
void json_add_string(struct json_stream *result UNNEEDED, const char *fieldname UNNEEDED, const char *value TAKES UNNEEDED)
{ fprintf(stderr, "json_add_string called!\n"); abort(); }
/* Generated stub for json_add_stringn */
void json_add_stringn(struct json_stream *result UNNEEDED, const char *fieldname UNNEEDED,
const char *value TAKES UNNEEDED, size_t value_len UNNEEDED)
{ fprintf(stderr, "json_add_stringn called!\n"); abort(); }
/* Generated stub for json_add_timeiso */
void json_add_timeiso(struct json_stream *result UNNEEDED,
const char *fieldname UNNEEDED,
struct timeabs *time UNNEEDED)
{ fprintf(stderr, "json_add_timeiso called!\n"); abort(); }
/* Generated stub for json_add_tx */
void json_add_tx(struct json_stream *result UNNEEDED,
const char *fieldname UNNEEDED,
@@ -375,6 +402,14 @@ void json_add_tx(struct json_stream *result UNNEEDED,
void json_add_txid(struct json_stream *result UNNEEDED, const char *fieldname UNNEEDED,
const struct bitcoin_txid *txid UNNEEDED)
{ fprintf(stderr, "json_add_txid called!\n"); abort(); }
/* Generated stub for json_add_u32 */
void json_add_u32(struct json_stream *result UNNEEDED, const char *fieldname UNNEEDED,
uint32_t value UNNEEDED)
{ fprintf(stderr, "json_add_u32 called!\n"); abort(); }
/* Generated stub for json_add_u64 */
void json_add_u64(struct json_stream *result UNNEEDED, const char *fieldname UNNEEDED,
uint64_t value UNNEEDED)
{ fprintf(stderr, "json_add_u64 called!\n"); abort(); }
/* Generated stub for json_add_uncommitted_channel */
void json_add_uncommitted_channel(struct json_stream *response UNNEEDED,
const struct uncommitted_channel *uc UNNEEDED)
@@ -389,16 +424,19 @@ void json_array_end(struct json_stream *js UNNEEDED)
/* Generated stub for json_array_start */
void json_array_start(struct json_stream *js UNNEEDED, const char *fieldname UNNEEDED)
{ fprintf(stderr, "json_array_start called!\n"); abort(); }
/* Generated stub for json_member_direct */
char *json_member_direct(struct json_stream *js UNNEEDED,
const char *fieldname UNNEEDED, size_t extra UNNEEDED)
{ fprintf(stderr, "json_member_direct called!\n"); abort(); }
/* Generated stub for json_object_end */
void json_object_end(struct json_stream *js UNNEEDED)
{ fprintf(stderr, "json_object_end called!\n"); abort(); }
/* Generated stub for json_object_start */
void json_object_start(struct json_stream *ks UNNEEDED, const char *fieldname UNNEEDED)
{ fprintf(stderr, "json_object_start called!\n"); abort(); }
/* Generated stub for json_scan */
const char *json_scan(const tal_t *ctx UNNEEDED,
const char *buffer UNNEEDED,
const jsmntok_t *tok UNNEEDED,
const char *guide UNNEEDED,
...)
{ fprintf(stderr, "json_scan called!\n"); abort(); }
/* Generated stub for json_stream_fail */
struct json_stream *json_stream_fail(struct command *cmd UNNEEDED,
errcode_t code UNNEEDED,
@@ -421,10 +459,21 @@ bool json_to_msat(const char *buffer UNNEEDED, const jsmntok_t *tok UNNEEDED,
bool json_to_node_id(const char *buffer UNNEEDED, const jsmntok_t *tok UNNEEDED,
struct node_id *id UNNEEDED)
{ fprintf(stderr, "json_to_node_id called!\n"); abort(); }
/* Generated stub for json_to_number */
bool json_to_number(const char *buffer UNNEEDED, const jsmntok_t *tok UNNEEDED,
unsigned int *num UNNEEDED)
{ fprintf(stderr, "json_to_number called!\n"); abort(); }
/* Generated stub for json_to_short_channel_id */
bool json_to_short_channel_id(const char *buffer UNNEEDED, const jsmntok_t *tok UNNEEDED,
struct short_channel_id *scid UNNEEDED)
{ fprintf(stderr, "json_to_short_channel_id called!\n"); abort(); }
/* Generated stub for json_to_u16 */
bool json_to_u16(const char *buffer UNNEEDED, const jsmntok_t *tok UNNEEDED,
uint16_t *num UNNEEDED)
{ fprintf(stderr, "json_to_u16 called!\n"); abort(); }
/* Generated stub for json_tok_bin_from_hex */
u8 *json_tok_bin_from_hex(const tal_t *ctx UNNEEDED, const char *buffer UNNEEDED, const jsmntok_t *tok UNNEEDED)
{ fprintf(stderr, "json_tok_bin_from_hex called!\n"); abort(); }
/* Generated stub for json_tok_channel_id */
bool json_tok_channel_id(const char *buffer UNNEEDED, const jsmntok_t *tok UNNEEDED,
struct channel_id *cid UNNEEDED)

View File

@@ -30,10 +30,9 @@ bool fromwire_channel_id(const u8 **cursor UNNEEDED, size_t *max UNNEEDED,
/* Generated stub for fromwire_node_id */
void fromwire_node_id(const u8 **cursor UNNEEDED, size_t *max UNNEEDED, struct node_id *id UNNEEDED)
{ fprintf(stderr, "fromwire_node_id called!\n"); abort(); }
/* Generated stub for json_add_sha256 */
void json_add_sha256(struct json_stream *result UNNEEDED, const char *fieldname UNNEEDED,
const struct sha256 *hash UNNEEDED)
{ fprintf(stderr, "json_add_sha256 called!\n"); abort(); }
/* Generated stub for json_to_errcode */
bool json_to_errcode(const char *buffer UNNEEDED, const jsmntok_t *tok UNNEEDED, errcode_t *errcode UNNEEDED)
{ fprintf(stderr, "json_to_errcode called!\n"); abort(); }
/* Generated stub for json_to_pubkey */
bool json_to_pubkey(const char *buffer UNNEEDED, const jsmntok_t *tok UNNEEDED,
struct pubkey *pubkey UNNEEDED)

View File

@@ -27,6 +27,11 @@ bool fromwire_channel_id(const u8 **cursor UNNEEDED, size_t *max UNNEEDED,
/* Generated stub for fromwire_node_id */
void fromwire_node_id(const u8 **cursor UNNEEDED, size_t *max UNNEEDED, struct node_id *id UNNEEDED)
{ fprintf(stderr, "fromwire_node_id called!\n"); abort(); }
/* Generated stub for json_add_hex_talarr */
void json_add_hex_talarr(struct json_stream *result UNNEEDED,
const char *fieldname UNNEEDED,
const tal_t *data UNNEEDED)
{ fprintf(stderr, "json_add_hex_talarr called!\n"); abort(); }
/* Generated stub for json_add_member */
void json_add_member(struct json_stream *js UNNEEDED,
const char *fieldname UNNEEDED,
@@ -38,16 +43,23 @@ void json_add_node_id(struct json_stream *response UNNEEDED,
const char *fieldname UNNEEDED,
const struct node_id *id UNNEEDED)
{ fprintf(stderr, "json_add_node_id called!\n"); abort(); }
/* Generated stub for json_add_num */
void json_add_num(struct json_stream *result UNNEEDED, const char *fieldname UNNEEDED,
unsigned int value UNNEEDED)
{ fprintf(stderr, "json_add_num called!\n"); abort(); }
/* Generated stub for json_add_string */
void json_add_string(struct json_stream *result UNNEEDED, const char *fieldname UNNEEDED, const char *value TAKES UNNEEDED)
{ fprintf(stderr, "json_add_string called!\n"); abort(); }
/* Generated stub for json_add_time */
void json_add_time(struct json_stream *result UNNEEDED, const char *fieldname UNNEEDED,
struct timespec ts UNNEEDED)
{ fprintf(stderr, "json_add_time called!\n"); abort(); }
/* Generated stub for json_array_end */
void json_array_end(struct json_stream *js UNNEEDED)
{ fprintf(stderr, "json_array_end called!\n"); abort(); }
/* Generated stub for json_array_start */
void json_array_start(struct json_stream *js UNNEEDED, const char *fieldname UNNEEDED)
{ fprintf(stderr, "json_array_start called!\n"); abort(); }
/* Generated stub for json_member_direct */
char *json_member_direct(struct json_stream *js UNNEEDED,
const char *fieldname UNNEEDED, size_t extra UNNEEDED)
{ fprintf(stderr, "json_member_direct called!\n"); abort(); }
/* Generated stub for json_object_end */
void json_object_end(struct json_stream *js UNNEEDED)
{ fprintf(stderr, "json_object_end called!\n"); abort(); }

View File

@@ -75,16 +75,6 @@ bool fromwire_status_peer_error(const tal_t *ctx UNNEEDED, const void *p UNNEEDE
/* Generated stub for fromwire_status_version */
bool fromwire_status_version(const tal_t *ctx UNNEEDED, const void *p UNNEEDED, wirestring **version UNNEEDED)
{ fprintf(stderr, "fromwire_status_version called!\n"); abort(); }
/* Generated stub for json_add_member */
void json_add_member(struct json_stream *js UNNEEDED,
const char *fieldname UNNEEDED,
bool quote UNNEEDED,
const char *fmt UNNEEDED, ...)
{ fprintf(stderr, "json_add_member called!\n"); abort(); }
/* Generated stub for json_member_direct */
char *json_member_direct(struct json_stream *js UNNEEDED,
const char *fieldname UNNEEDED, size_t extra UNNEEDED)
{ fprintf(stderr, "json_member_direct called!\n"); abort(); }
/* Generated stub for log_ */
void log_(struct log *log UNNEEDED, enum log_level level UNNEEDED,
const struct node_id *node_id UNNEEDED,

View File

@@ -134,14 +134,13 @@ PLUGIN_COMMON_OBJS := \
common/daemon.o \
common/features.o \
common/hash_u5.o \
common/json.o \
common/json_helpers.o \
common/json_param.o \
common/json_parse.o \
common/json_parse_simple.o \
common/json_stream.o \
common/json_tok.o \
common/lease_rates.o \
common/memleak.o \
common/node_id.o \
common/param.o \
common/psbt_open.o \
common/pseudorand.o \
common/random_select.o \

View File

@@ -1,6 +1,7 @@
#include "config.h"
#include <ccan/array_size/array_size.h>
#include <common/json_tok.h>
#include <common/json_param.h>
#include <common/json_stream.h>
#include <plugins/libplugin.h>
static u64 cycle_seconds = 0, expired_by = 86400;

View File

@@ -6,7 +6,8 @@
#include <ccan/pipecmd/pipecmd.h>
#include <ccan/tal/grab_file/grab_file.h>
#include <ccan/tal/str/str.h>
#include <common/json_tok.h>
#include <common/json_param.h>
#include <common/json_stream.h>
#include <common/memleak.h>
#include <errno.h>
#include <plugins/libplugin.h>

View File

@@ -8,9 +8,8 @@
#include <ccan/tal/str/str.h>
#include <ccan/time/time.h>
#include <common/hsm_encryption.h>
#include <common/json.h>
#include <common/json_param.h>
#include <common/json_stream.h>
#include <common/json_tok.h>
#include <common/scb_wiregen.h>
#include <errno.h>
#include <fcntl.h>

View File

@@ -10,8 +10,8 @@
#include <common/bolt12_merkle.h>
#include <common/dijkstra.h>
#include <common/gossmap.h>
#include <common/json_param.h>
#include <common/json_stream.h>
#include <common/json_tok.h>
#include <common/memleak.h>
#include <common/overflows.h>
#include <common/route.h>

View File

@@ -13,8 +13,9 @@
#include <ccan/array_size/array_size.h>
#include <ccan/json_out/json_out.h>
#include <ccan/tal/str/str.h>
#include <common/json_param.h>
#include <common/json_stream.h>
#include <common/json_tok.h>
#include <common/lease_rates.h>
#include <common/memleak.h>
#include <common/overflows.h>
#include <common/psbt_open.h>

View File

@@ -1,9 +1,11 @@
#include "config.h"
#include <bitcoin/preimage.h>
#include <ccan/array_size/array_size.h>
#include <ccan/asort/asort.h>
#include <ccan/cast/cast.h>
#include <ccan/tal/str/str.h>
#include <common/json_tok.h>
#include <common/json_param.h>
#include <common/json_stream.h>
#include <common/memleak.h>
#include <common/type_to_string.h>
#include <plugins/libplugin-pay.h>

View File

@@ -3,6 +3,7 @@
#define LIGHTNING_PLUGINS_LIBPLUGIN_H
#include "config.h"
#include <bitcoin/tx.h>
#include <ccan/intmap/intmap.h>
#include <ccan/membuf/membuf.h>
#include <ccan/strmap/strmap.h>
@@ -11,12 +12,9 @@
#include <common/errcode.h>
#include <common/features.h>
#include <common/htlc.h>
#include <common/json.h>
#include <common/json_command.h>
#include <common/json_helpers.h>
#include <common/jsonrpc_errors.h>
#include <common/node_id.h>
#include <common/param.h>
#include <common/status_levels.h>
#include <common/utils.h>

View File

@@ -9,6 +9,7 @@
#include <common/bolt11_json.h>
#include <common/bolt12_merkle.h>
#include <common/iso4217.h>
#include <common/json_param.h>
#include <common/json_stream.h>
#include <plugins/offers.h>
#include <plugins/offers_inv_hook.h>

View File

@@ -1,7 +1,6 @@
#ifndef LIGHTNING_PLUGINS_OFFERS_H
#define LIGHTNING_PLUGINS_OFFERS_H
#include "config.h"
#include <common/json.h>
struct command_result;
struct command;

View File

@@ -2,6 +2,7 @@
#include <ccan/mem/mem.h>
#include <ccan/tal/str/str.h>
#include <common/bolt12_merkle.h>
#include <common/json_stream.h>
#include <common/type_to_string.h>
#include <plugins/offers.h>
#include <plugins/offers_inv_hook.h>

View File

@@ -4,7 +4,8 @@
#include <ccan/tal/str/str.h>
#include <common/bolt12.h>
#include <common/iso4217.h>
#include <common/json_tok.h>
#include <common/json_param.h>
#include <common/json_stream.h>
#include <common/overflows.h>
#include <plugins/offers_offer.h>

View File

@@ -10,8 +10,8 @@
#include <ccan/tal/str/str.h>
#include <common/bolt12_merkle.h>
#include <common/gossmap.h>
#include <common/json_param.h>
#include <common/json_stream.h>
#include <common/json_tok.h>
#include <common/memleak.h>
#include <common/pseudorand.h>
#include <common/type_to_string.h>

View File

@@ -1,7 +1,7 @@
#include "config.h"
#include <ccan/array_size/array_size.h>
#include <common/json_param.h>
#include <common/json_stream.h>
#include <common/json_tok.h>
#include <plugins/spender/fundchannel.h>
static struct command_result *

View File

@@ -4,8 +4,8 @@
#include <ccan/array_size/array_size.h>
#include <ccan/tal/str/str.h>
#include <common/addr.h>
#include <common/json_param.h>
#include <common/json_stream.h>
#include <common/json_tok.h>
#include <common/psbt_open.h>
#include <common/pseudorand.h>
#include <common/type_to_string.h>

View File

@@ -4,8 +4,8 @@
#include <ccan/array_size/array_size.h>
#include <ccan/json_out/json_out.h>
#include <ccan/tal/str/str.h>
#include <common/json_param.h>
#include <common/json_stream.h>
#include <common/json_tok.h>
#include <common/psbt_open.h>
#include <common/pseudorand.h>
#include <common/type_to_string.h>

View File

@@ -6,8 +6,8 @@
#include <ccan/tal/str/str.h>
#include <common/dijkstra.h>
#include <common/gossmap.h>
#include <common/json_param.h>
#include <common/json_stream.h>
#include <common/json_tok.h>
#include <common/memleak.h>
#include <common/pseudorand.h>
#include <common/route.h>

View File

@@ -2,8 +2,8 @@
#include <bitcoin/psbt.h>
#include <ccan/array_size/array_size.h>
#include <common/addr.h>
#include <common/json_param.h>
#include <common/json_stream.h>
#include <common/json_tok.h>
#include <common/memleak.h>
#include <common/psbt_open.h>
#include <common/pseudorand.h>

View File

@@ -8,7 +8,7 @@ $(PLUGIN_TESTLIBPLUGIN_OBJS): $(PLUGIN_LIB_HEADER)
PLUGIN_TESTSELFDISABLE_AFTER_GETMANIFEST_SRC := tests/plugins/test_selfdisable_after_getmanifest.c
PLUGIN_TESTSELFDISABLE_AFTER_GETMANIFEST_OBJS := $(PLUGIN_TESTSELFDISABLE_AFTER_GETMANIFEST_SRC:.c=.o)
tests/plugins/test_selfdisable_after_getmanifest: bitcoin/chainparams.o $(PLUGIN_TESTSELFDISABLE_AFTER_GETMANIFEST_OBJS) common/autodata.o common/json.o common/json_stream.o common/setup.o common/utils.o $(JSMN_OBJS) $(CCAN_OBJS)
tests/plugins/test_selfdisable_after_getmanifest: bitcoin/chainparams.o $(PLUGIN_TESTSELFDISABLE_AFTER_GETMANIFEST_OBJS) common/autodata.o common/json_parse_simple.o common/setup.o common/utils.o $(JSMN_OBJS) $(CCAN_OBJS)
# Make sure these depend on everything.
ALL_TEST_PROGRAMS += tests/plugins/test_libplugin tests/plugins/test_selfdisable_after_getmanifest

View File

@@ -1,7 +1,8 @@
#include "config.h"
#include <ccan/array_size/array_size.h>
#include <ccan/tal/str/str.h>
#include <common/json_tok.h>
#include <common/json_param.h>
#include <common/json_stream.h>
#include <common/memleak.h>
#include <plugins/libplugin.h>

Some files were not shown because too many files have changed in this diff Show More