rgb-cln/common/test/run-bolt12-format-string-te...

211 lines
9.1 KiB
C

/* 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();
}