/* Pipe through jq to create format-string-test.json */ #include "config.h" #include #include #include #include #include #include #include #include #include /* 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(); }