mirror of
https://github.com/ElementsProject/lightning.git
synced 2024-12-29 10:04:41 +01:00
27220646c3
We did this originally because these types are referred to in the bolts, and we had no way of injecting the correct include lines into those. Now we do, so there's less excuse for this. Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
356 lines
11 KiB
C
356 lines
11 KiB
C
#include <ccan/array_size/array_size.h>
|
|
#include <ccan/str/hex/hex.h>
|
|
#include <ccan/tal/grab_file/grab_file.h>
|
|
#include <ccan/tal/str/str.h>
|
|
#include <common/json.c>
|
|
#include <common/utils.h>
|
|
#include <wire/wire.h>
|
|
|
|
static const char *reason;
|
|
#define SUPERVERBOSE(r) do { if (!reason) reason = (r); } while(0)
|
|
|
|
#include <common/bigsize.c>
|
|
|
|
/* AUTOGENERATED MOCKS START */
|
|
/* Generated stub for amount_asset_is_main */
|
|
bool amount_asset_is_main(struct amount_asset *asset UNNEEDED)
|
|
{ fprintf(stderr, "amount_asset_is_main called!\n"); abort(); }
|
|
/* 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_sat_add */
|
|
bool amount_sat_add(struct amount_sat *val UNNEEDED,
|
|
struct amount_sat a UNNEEDED,
|
|
struct amount_sat b UNNEEDED)
|
|
{ fprintf(stderr, "amount_sat_add called!\n"); abort(); }
|
|
/* Generated stub for amount_sat_eq */
|
|
bool amount_sat_eq(struct amount_sat a UNNEEDED, struct amount_sat b UNNEEDED)
|
|
{ fprintf(stderr, "amount_sat_eq called!\n"); abort(); }
|
|
/* Generated stub for amount_sat_sub */
|
|
bool amount_sat_sub(struct amount_sat *val UNNEEDED,
|
|
struct amount_sat a UNNEEDED,
|
|
struct amount_sat b UNNEEDED)
|
|
{ fprintf(stderr, "amount_sat_sub called!\n"); abort(); }
|
|
/* Generated stub for fromwire_amount_sat */
|
|
struct amount_sat fromwire_amount_sat(const u8 **cursor UNNEEDED, size_t *max UNNEEDED)
|
|
{ fprintf(stderr, "fromwire_amount_sat called!\n"); abort(); }
|
|
/* Generated stub for fromwire_fail */
|
|
const void *fromwire_fail(const u8 **cursor UNNEEDED, size_t *max UNNEEDED)
|
|
{ fprintf(stderr, "fromwire_fail called!\n"); abort(); }
|
|
/* Generated stub for fromwire_secp256k1_ecdsa_signature */
|
|
void fromwire_secp256k1_ecdsa_signature(const u8 **cursor UNNEEDED, size_t *max UNNEEDED,
|
|
secp256k1_ecdsa_signature *signature UNNEEDED)
|
|
{ fprintf(stderr, "fromwire_secp256k1_ecdsa_signature called!\n"); abort(); }
|
|
/* Generated stub for fromwire_sha256_double */
|
|
void fromwire_sha256_double(const u8 **cursor UNNEEDED, size_t *max UNNEEDED,
|
|
struct sha256_double *sha256d UNNEEDED)
|
|
{ fprintf(stderr, "fromwire_sha256_double called!\n"); abort(); }
|
|
/* Generated stub for fromwire_tal_arrn */
|
|
u8 *fromwire_tal_arrn(const tal_t *ctx UNNEEDED,
|
|
const u8 **cursor UNNEEDED, size_t *max UNNEEDED, size_t num UNNEEDED)
|
|
{ fprintf(stderr, "fromwire_tal_arrn called!\n"); abort(); }
|
|
/* Generated stub for fromwire_u16 */
|
|
u16 fromwire_u16(const u8 **cursor UNNEEDED, size_t *max UNNEEDED)
|
|
{ fprintf(stderr, "fromwire_u16 called!\n"); abort(); }
|
|
/* Generated stub for fromwire_u8 */
|
|
u8 fromwire_u8(const u8 **cursor UNNEEDED, size_t *max UNNEEDED)
|
|
{ fprintf(stderr, "fromwire_u8 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_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(); }
|
|
/* 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 towire_amount_sat */
|
|
void towire_amount_sat(u8 **pptr UNNEEDED, const struct amount_sat sat UNNEEDED)
|
|
{ fprintf(stderr, "towire_amount_sat called!\n"); abort(); }
|
|
/* Generated stub for towire_secp256k1_ecdsa_signature */
|
|
void towire_secp256k1_ecdsa_signature(u8 **pptr UNNEEDED,
|
|
const secp256k1_ecdsa_signature *signature UNNEEDED)
|
|
{ fprintf(stderr, "towire_secp256k1_ecdsa_signature called!\n"); abort(); }
|
|
/* Generated stub for towire_sha256_double */
|
|
void towire_sha256_double(u8 **pptr UNNEEDED, const struct sha256_double *sha256d UNNEEDED)
|
|
{ fprintf(stderr, "towire_sha256_double called!\n"); abort(); }
|
|
/* Generated stub for towire_u16 */
|
|
void towire_u16(u8 **pptr UNNEEDED, u16 v UNNEEDED)
|
|
{ fprintf(stderr, "towire_u16 called!\n"); abort(); }
|
|
/* Generated stub for towire_u8 */
|
|
void towire_u8(u8 **pptr UNNEEDED, u8 v UNNEEDED)
|
|
{ fprintf(stderr, "towire_u8 called!\n"); abort(); }
|
|
/* Generated stub for towire_u8_array */
|
|
void towire_u8_array(u8 **pptr UNNEEDED, const u8 *arr UNNEEDED, size_t num UNNEEDED)
|
|
{ fprintf(stderr, "towire_u8_array called!\n"); abort(); }
|
|
/* AUTOGENERATED MOCKS END */
|
|
|
|
/* BOLT #1:
|
|
*
|
|
* A correct implementation should pass against these test vectors:
|
|
* ```json
|
|
* [
|
|
* {
|
|
* "name": "zero",
|
|
* "value": 0,
|
|
* "bytes": "00"
|
|
* },
|
|
* {
|
|
* "name": "one byte high",
|
|
* "value": 252,
|
|
* "bytes": "fc"
|
|
* },
|
|
* {
|
|
* "name": "two byte low",
|
|
* "value": 253,
|
|
* "bytes": "fd00fd"
|
|
* },
|
|
* {
|
|
* "name": "two byte high",
|
|
* "value": 65535,
|
|
* "bytes": "fdffff"
|
|
* },
|
|
* {
|
|
* "name": "four byte low",
|
|
* "value": 65536,
|
|
* "bytes": "fe00010000"
|
|
* },
|
|
* {
|
|
* "name": "four byte high",
|
|
* "value": 4294967295,
|
|
* "bytes": "feffffffff"
|
|
* },
|
|
* {
|
|
* "name": "eight byte low",
|
|
* "value": 4294967296,
|
|
* "bytes": "ff0000000100000000"
|
|
* },
|
|
* {
|
|
* "name": "eight byte high",
|
|
* "value": 18446744073709551615,
|
|
* "bytes": "ffffffffffffffffff"
|
|
* },
|
|
* {
|
|
* "name": "two byte not canonical",
|
|
* "value": 0,
|
|
* "bytes": "fd00fc",
|
|
* "exp_error": "decoded varint is not canonical"
|
|
* },
|
|
* {
|
|
* "name": "four byte not canonical",
|
|
* "value": 0,
|
|
* "bytes": "fe0000ffff",
|
|
* "exp_error": "decoded varint is not canonical"
|
|
* },
|
|
* {
|
|
* "name": "eight byte not canonical",
|
|
* "value": 0,
|
|
* "bytes": "ff00000000ffffffff",
|
|
* "exp_error": "decoded varint is not canonical"
|
|
* },
|
|
* {
|
|
* "name": "two byte short read",
|
|
* "value": 0,
|
|
* "bytes": "fd00",
|
|
* "exp_error": "unexpected EOF"
|
|
* },
|
|
* {
|
|
* "name": "four byte short read",
|
|
* "value": 0,
|
|
* "bytes": "feffff",
|
|
* "exp_error": "unexpected EOF"
|
|
* },
|
|
* {
|
|
* "name": "eight byte short read",
|
|
* "value": 0,
|
|
* "bytes": "ffffffffff",
|
|
* "exp_error": "unexpected EOF"
|
|
* },
|
|
* {
|
|
* "name": "one byte no read",
|
|
* "value": 0,
|
|
* "bytes": "",
|
|
* "exp_error": "EOF"
|
|
* },
|
|
* {
|
|
* "name": "two byte no read",
|
|
* "value": 0,
|
|
* "bytes": "fd",
|
|
* "exp_error": "unexpected EOF"
|
|
* },
|
|
* {
|
|
* "name": "four byte no read",
|
|
* "value": 0,
|
|
* "bytes": "fe",
|
|
* "exp_error": "unexpected EOF"
|
|
* },
|
|
* {
|
|
* "name": "eight byte no read",
|
|
* "value": 0,
|
|
* "bytes": "ff",
|
|
* "exp_error": "unexpected EOF"
|
|
* }
|
|
* ]
|
|
* ```
|
|
*/
|
|
static void test_decode(const char *json, const jsmntok_t toks[])
|
|
{
|
|
size_t i;
|
|
const jsmntok_t *t;
|
|
|
|
json_for_each_arr(i, t, toks) {
|
|
const jsmntok_t *err = json_get_member(json, t, "exp_error");
|
|
const jsmntok_t *bytes = json_get_member(json, t, "bytes");
|
|
u64 num, expect;
|
|
const u8 *b;
|
|
size_t len;
|
|
|
|
if (!json_to_u64(json, json_get_member(json, t, "value"),
|
|
&expect))
|
|
abort();
|
|
b = tal_hexdata(tmpctx, json + bytes->start,
|
|
bytes->end - bytes->start);
|
|
|
|
reason = NULL;
|
|
len = bigsize_get(b, tal_bytelen(b), &num);
|
|
if (err) {
|
|
assert(len == 0);
|
|
assert(json_tok_streq(json, err, reason));
|
|
} else {
|
|
assert(len == tal_bytelen(b));
|
|
assert(num == expect);
|
|
}
|
|
}
|
|
}
|
|
|
|
/* BOLT #1:
|
|
*
|
|
* A correct implementation should pass against the following test vectors:
|
|
* ```json
|
|
* [
|
|
* {
|
|
* "name": "zero",
|
|
* "value": 0,
|
|
* "bytes": "00"
|
|
* },
|
|
* {
|
|
* "name": "one byte high",
|
|
* "value": 252,
|
|
* "bytes": "fc"
|
|
* },
|
|
* {
|
|
* "name": "two byte low",
|
|
* "value": 253,
|
|
* "bytes": "fd00fd"
|
|
* },
|
|
* {
|
|
* "name": "two byte high",
|
|
* "value": 65535,
|
|
* "bytes": "fdffff"
|
|
* },
|
|
* {
|
|
* "name": "four byte low",
|
|
* "value": 65536,
|
|
* "bytes": "fe00010000"
|
|
* },
|
|
* {
|
|
* "name": "four byte high",
|
|
* "value": 4294967295,
|
|
* "bytes": "feffffffff"
|
|
* },
|
|
* {
|
|
* "name": "eight byte low",
|
|
* "value": 4294967296,
|
|
* "bytes": "ff0000000100000000"
|
|
* },
|
|
* {
|
|
* "name": "eight byte high",
|
|
* "value": 18446744073709551615,
|
|
* "bytes": "ffffffffffffffffff"
|
|
* }
|
|
* ]
|
|
* ```
|
|
*/
|
|
static void test_encode(const char *json, const jsmntok_t toks[])
|
|
{
|
|
size_t i;
|
|
const jsmntok_t *t;
|
|
u8 buf[BIGSIZE_MAX_LEN];
|
|
|
|
json_for_each_arr(i, t, toks) {
|
|
const jsmntok_t *bytes = json_get_member(json, t, "bytes");
|
|
u64 num;
|
|
const u8 *expect;
|
|
size_t len;
|
|
|
|
if (!json_to_u64(json, json_get_member(json, t, "value"),
|
|
&num))
|
|
abort();
|
|
expect = tal_hexdata(tmpctx, json + bytes->start,
|
|
bytes->end - bytes->start);
|
|
|
|
len = bigsize_put(buf, num);
|
|
assert(memeq(buf, len, expect, tal_bytelen(expect)));
|
|
}
|
|
}
|
|
|
|
int main(int argc, char *argv[])
|
|
{
|
|
char **lines, *json = NULL;
|
|
int test_count = 0;
|
|
|
|
setup_locale();
|
|
setup_tmpctx();
|
|
|
|
lines = tal_strsplit(tmpctx, grab_file(tmpctx, tal_fmt(tmpctx, "%s.c",
|
|
argv[0])),
|
|
"\n", STR_NO_EMPTY);
|
|
|
|
for (size_t i = 0; lines[i]; i++) {
|
|
const char *l = lines[i];
|
|
if (!strstarts(l, " * "))
|
|
continue;
|
|
l += 3;
|
|
if (streq(l, "```json"))
|
|
json = tal_strdup(tmpctx, "");
|
|
else if (streq(l, "```")) {
|
|
jsmn_parser parser;
|
|
jsmntok_t toks[500];
|
|
|
|
jsmn_init(&parser);
|
|
if (jsmn_parse(&parser, json, strlen(json),
|
|
toks, ARRAY_SIZE(toks)) < 0)
|
|
abort();
|
|
|
|
switch (test_count) {
|
|
case 0:
|
|
test_decode(json, toks);
|
|
break;
|
|
case 1:
|
|
test_encode(json, toks);
|
|
break;
|
|
default:
|
|
abort();
|
|
}
|
|
test_count++;
|
|
json = NULL;
|
|
} else if (json)
|
|
tal_append_fmt(&json, "%s", l);
|
|
}
|
|
assert(test_count == 2);
|
|
tal_free(tmpctx);
|
|
}
|