mirror of
https://github.com/ElementsProject/lightning.git
synced 2025-01-19 05:44:12 +01:00
common: add test to generate BOLT formatting vectors.
They needed updating, so let's actually autogenerate them. Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
This commit is contained in:
parent
cc71f75c4b
commit
ea7d428579
@ -82,6 +82,18 @@ common/test/run-bolt12_merkle: \
|
||||
wire/peer_wiregen.o \
|
||||
wire/towire.o
|
||||
|
||||
common/test/run-bolt12-format-string-test: \
|
||||
common/amount.o \
|
||||
common/bigsize.o \
|
||||
common/base32.o \
|
||||
common/bech32.o \
|
||||
common/bech32_util.o \
|
||||
common/bolt12.o \
|
||||
common/node_id.o \
|
||||
wire/bolt12$(EXP)_wiregen.o \
|
||||
wire/tlvstream.o \
|
||||
wire/towire.o
|
||||
|
||||
common/test/run-bolt12_merkle-json: \
|
||||
common/base32.o \
|
||||
common/wireaddr.o
|
||||
|
210
common/test/run-bolt12-format-string-test.c
Normal file
210
common/test/run-bolt12-format-string-test.c
Normal file
@ -0,0 +1,210 @@
|
||||
/* Pipe through jq to create format-string-test.json */
|
||||
#include "config.h"
|
||||
#include <assert.h>
|
||||
#include <ccan/array_size/array_size.h>
|
||||
#include <ccan/tal/grab_file/grab_file.h>
|
||||
#include <ccan/tal/path/path.h>
|
||||
#include <ccan/tal/str/str.h>
|
||||
#include <common/bolt12.h>
|
||||
#include <common/bolt12_merkle.h>
|
||||
#include <common/features.h>
|
||||
#include <common/setup.h>
|
||||
|
||||
/* AUTOGENERATED MOCKS START */
|
||||
/* Generated stub for features_unsupported */
|
||||
int features_unsupported(const struct feature_set *our_features UNNEEDED,
|
||||
const u8 *their_features UNNEEDED,
|
||||
enum feature_place p UNNEEDED)
|
||||
{ fprintf(stderr, "features_unsupported called!\n"); abort(); }
|
||||
/* 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(); }
|
||||
/* Generated stub for fromwire_blinded_path */
|
||||
struct blinded_path *fromwire_blinded_path(const tal_t *ctx UNNEEDED, const u8 **cursor UNNEEDED, size_t *plen UNNEEDED)
|
||||
{ fprintf(stderr, "fromwire_blinded_path called!\n"); abort(); }
|
||||
/* Generated stub for fromwire_bool */
|
||||
bool fromwire_bool(const u8 **cursor UNNEEDED, size_t *max UNNEEDED)
|
||||
{ fprintf(stderr, "fromwire_bool called!\n"); abort(); }
|
||||
/* Generated stub for fromwire_fail */
|
||||
void *fromwire_fail(const u8 **cursor UNNEEDED, size_t *max UNNEEDED)
|
||||
{ fprintf(stderr, "fromwire_fail called!\n"); abort(); }
|
||||
/* Generated stub for fromwire_pad */
|
||||
void fromwire_pad(const u8 **cursor UNNEEDED, size_t *max UNNEEDED, size_t num UNNEEDED)
|
||||
{ fprintf(stderr, "fromwire_pad 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 */
|
||||
void fromwire_sha256(const u8 **cursor UNNEEDED, size_t *max UNNEEDED, struct sha256 *sha256 UNNEEDED)
|
||||
{ fprintf(stderr, "fromwire_sha256 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_tu32 */
|
||||
u32 fromwire_tu32(const u8 **cursor UNNEEDED, size_t *max UNNEEDED)
|
||||
{ fprintf(stderr, "fromwire_tu32 called!\n"); abort(); }
|
||||
/* Generated stub for fromwire_tu64 */
|
||||
u64 fromwire_tu64(const u8 **cursor UNNEEDED, size_t *max UNNEEDED)
|
||||
{ fprintf(stderr, "fromwire_tu64 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_u32 */
|
||||
u32 fromwire_u32(const u8 **cursor UNNEEDED, size_t *max UNNEEDED)
|
||||
{ fprintf(stderr, "fromwire_u32 called!\n"); abort(); }
|
||||
/* Generated stub for fromwire_u64 */
|
||||
u64 fromwire_u64(const u8 **cursor UNNEEDED, size_t *max UNNEEDED)
|
||||
{ fprintf(stderr, "fromwire_u64 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 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 fromwire_utf8_array */
|
||||
void fromwire_utf8_array(const u8 **cursor UNNEEDED, size_t *max UNNEEDED, char *arr UNNEEDED, size_t num UNNEEDED)
|
||||
{ fprintf(stderr, "fromwire_utf8_array 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 sighash_from_merkle */
|
||||
void sighash_from_merkle(const char *messagename UNNEEDED,
|
||||
const char *fieldname UNNEEDED,
|
||||
const struct sha256 *merkle UNNEEDED,
|
||||
struct sha256 *sighash UNNEEDED)
|
||||
{ fprintf(stderr, "sighash_from_merkle called!\n"); abort(); }
|
||||
/* Generated stub for towire_blinded_path */
|
||||
void towire_blinded_path(u8 **p UNNEEDED, const struct blinded_path *blinded_path UNNEEDED)
|
||||
{ fprintf(stderr, "towire_blinded_path called!\n"); abort(); }
|
||||
/* AUTOGENERATED MOCKS END */
|
||||
|
||||
static void example2(const char *comment, bool valid,
|
||||
const char *str, bool final)
|
||||
{
|
||||
printf("{\n");
|
||||
printf("\"comment\": \"%s\",\n", comment);
|
||||
printf("\"valid\": %s,\n", valid ? "true": "false");
|
||||
printf("\"string\": \"%s\"\n", str);
|
||||
printf("}%s\n", final ? "" : ",");
|
||||
}
|
||||
|
||||
static void example(const char *comment, bool valid, const char *str)
|
||||
{
|
||||
example2(comment, valid, str, false);
|
||||
}
|
||||
|
||||
static void example_final(const char *comment, bool valid, const char *str)
|
||||
{
|
||||
example2(comment, valid, str, true);
|
||||
}
|
||||
|
||||
static utf8 *tal_utf8(const tal_t *ctx, const char *str)
|
||||
{
|
||||
/* Non-NUL terminated! */
|
||||
return tal_dup_arr(ctx, char, str, strlen(str), 0);
|
||||
}
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
struct tlv_offer *offer;
|
||||
struct secret alice;
|
||||
char *str;
|
||||
|
||||
common_setup(argv[0]);
|
||||
|
||||
offer = tlv_offer_new(tmpctx);
|
||||
/* BOLT-offers #12:
|
||||
* A writer of an offer:
|
||||
* - MUST NOT set any tlv fields greater or equal to 80, or tlv field 0.
|
||||
* - MUST set `offer_node_id` to the node's public key to request the invoice from.
|
||||
* - MUST set `offer_description` to a complete description of the purpose
|
||||
* of the payment.
|
||||
* - if the chain for the invoice is not solely bitcoin:
|
||||
* - MUST specify `offer_chains` the offer is valid for.
|
||||
* - otherwise:
|
||||
* - MAY omit `offer_chains`, implying that bitcoin is only chain.
|
||||
* - if a specific minimum `offer_amount` is required for successful payment:
|
||||
* - MUST set `offer_amount` to the amount expected (per item).
|
||||
* - if the currency for `offer_amount` is that of all entries in `chains`:
|
||||
* - MUST specify `amount` in multiples of the minimum lightning-payable unit
|
||||
* (e.g. milli-satoshis for bitcoin).
|
||||
* - otherwise:
|
||||
* - MUST specify `offer_currency` `iso4217` as an ISO 4712 three-letter code.
|
||||
* - MUST specify `offer_amount` in the currency unit adjusted by the ISO 4712
|
||||
* exponent (e.g. USD cents).
|
||||
* - otherwise:
|
||||
* - MUST NOT set `offer_amount`
|
||||
* - MUST NOT set `offer_currency`
|
||||
* - MAY set `offer_metadata` for its own use.
|
||||
* - if it supports bolt12 offer features:
|
||||
* - MUST set `offer_features`.`features` to the bitmap of bolt12 features.
|
||||
* - if the offer expires:
|
||||
* - MUST set `offer_absolute_expiry` `seconds_from_epoch` to the number of seconds
|
||||
* after midnight 1 January 1970, UTC that invoice_request should not be
|
||||
* attempted.
|
||||
* - if it is connected only by private channels:
|
||||
* - MUST include `offer_paths` containing one or more paths to the node from
|
||||
* publicly reachable nodes.
|
||||
* - otherwise:
|
||||
* - MAY include `offer_paths`.
|
||||
* - if it includes `offer_paths`:
|
||||
* - SHOULD ignore any invoice_request which does not use the path.
|
||||
* - if it sets `offer_issuer`:
|
||||
* - SHOULD set it to identify the issuer of the invoice clearly.
|
||||
* - if it includes a domain name:
|
||||
* - SHOULD begin it with either user@domain or domain
|
||||
* - MAY follow with a space and more text
|
||||
* - if it can supply more than one item for a single invoice:
|
||||
* - if the maximum quantity is known:
|
||||
* - MUST set that maximum in `offer_quantity_max`.
|
||||
* - MUST NOT set `offer_quantity_max` to 0.
|
||||
* - otherwise:
|
||||
* - MUST set `offer_quantity_max` to 0.
|
||||
* - otherwise:
|
||||
* - MUST NOT set `offer_quantity_max`.
|
||||
*/
|
||||
memset(&alice, 'A', sizeof(alice));
|
||||
offer->offer_node_id = tal(offer, struct pubkey);
|
||||
assert(pubkey_from_secret(&alice, offer->offer_node_id));
|
||||
offer->offer_description = tal_utf8(offer, "An example description");
|
||||
offer->offer_issuer = tal_utf8(offer, "BOLT 12 industries");
|
||||
offer->offer_amount = tal(offer, u64);
|
||||
/* 1M msat */
|
||||
*offer->offer_amount = 1000000;
|
||||
|
||||
str = offer_encode(tmpctx, offer);
|
||||
printf("[\n");
|
||||
|
||||
example("A complete string is valid", true, str);
|
||||
example("+ can join anywhere", true,
|
||||
tal_fmt(tmpctx, "%.*s+%s", 1, str, str + 1));
|
||||
example("Multiple + can join", true,
|
||||
tal_fmt(tmpctx, "%.*s+%.*s+%.*s+%.*s+%s",
|
||||
15, str,
|
||||
31, str + 15,
|
||||
18, str + 15 + 31,
|
||||
70, str + 15 + 31 + 18,
|
||||
str + 15 + 31 + 18 + 70));
|
||||
example("+ can be followed by whitespace", true,
|
||||
tal_fmt(tmpctx, "%.*s+ %.*s+ %.*s+\\n%.*s+\\r\\n %s",
|
||||
15, str,
|
||||
31, str + 15,
|
||||
18, str + 15 + 31,
|
||||
70, str + 15 + 31 + 18,
|
||||
str + 15 + 31 + 18 + 70));
|
||||
|
||||
example("+ must be surrounded by bech32 characters", false,
|
||||
tal_fmt(tmpctx, "%s+", str));
|
||||
example("+ must be surrounded by bech32 characters", false,
|
||||
tal_fmt(tmpctx, "%s+ ", str));
|
||||
example("+ must be surrounded by bech32 characters", false,
|
||||
tal_fmt(tmpctx, "+%s", str));
|
||||
example("+ must be surrounded by bech32 characters", false,
|
||||
tal_fmt(tmpctx, "+ %s", str));
|
||||
example_final("+ must be surrounded by bech32 characters", false,
|
||||
tal_fmt(tmpctx, "%.*s++%s", 2, str, str+2));
|
||||
printf("]\n");
|
||||
common_shutdown();
|
||||
}
|
@ -203,6 +203,7 @@ int main(int argc, char *argv[])
|
||||
actual = (string_to_data(tmpctx, str, strlen(str),
|
||||
"lno", &dlen, &fail) != NULL);
|
||||
assert(actual == valid);
|
||||
printf("%s %s\n", str, valid ? "OK": "INVALID");
|
||||
}
|
||||
out:
|
||||
common_shutdown();
|
||||
|
Loading…
Reference in New Issue
Block a user