diff --git a/common/Makefile b/common/Makefile index ab7a83e64..ee582544e 100644 --- a/common/Makefile +++ b/common/Makefile @@ -9,6 +9,7 @@ COMMON_SRC_NOGEN := \ common/billboard.c \ common/bip32.c \ common/blinding.c \ + common/blindedpath.c \ common/bolt11.c \ common/bolt11_json.c \ common/bolt12.c \ @@ -87,7 +88,6 @@ COMMON_SRC_NOGEN := \ ifeq ($(EXPERIMENTAL_FEATURES),1) COMMON_SRC_NOGEN += common/psbt_internal.c -COMMON_SRC_NOGEN += common/blindedpath.c endif COMMON_SRC_GEN := common/status_wiregen.c common/peer_status_wiregen.c diff --git a/common/blindedpath.h b/common/blindedpath.h index ae198132c..bf52d9a8a 100644 --- a/common/blindedpath.h +++ b/common/blindedpath.h @@ -3,7 +3,6 @@ #include "config.h" #include -#if EXPERIMENTAL_FEATURES struct route_info; struct pubkey; @@ -13,5 +12,4 @@ struct onionmsg_path **make_blindedpath(const tal_t *ctx, const struct pubkey *route, struct pubkey *initial_blinding, struct pubkey *final_blinding); -#endif /* EXPERIMENTAL_FEATURES */ #endif /* LIGHTNING_COMMON_BLINDEDPATH_H */ diff --git a/common/json.c b/common/json.c index 4395112f4..cc7eddaad 100644 --- a/common/json.c +++ b/common/json.c @@ -1198,10 +1198,8 @@ void json_add_errcode(struct json_stream *result, const char *fieldname, void json_add_invstring(struct json_stream *result, const char *invstring) { -#if EXPERIMENTAL_FEATURES if (strstarts(invstring, "lni")) json_add_string(result, "bolt12", invstring); else -#endif json_add_string(result, "bolt11", invstring); } diff --git a/common/utils.h b/common/utils.h index 851825e20..0b396bb87 100644 --- a/common/utils.h +++ b/common/utils.h @@ -118,6 +118,13 @@ STRUCTEQ_DEF(ripemd160, 0, u); #define IFDEV(dev, nondev) (nondev) #endif +#if EXPERIMENTAL_FEATURES +/* Make sure that nondev is evaluated, and valid, but is a constant */ +#define IFEXPERIMENTAL(exp, nonexp) (0 ? (nonexp) : (exp)) +#else +#define IFEXPERIMENTAL(exp, nonexp) (nonexp) +#endif + /* Context which all wally allocations use (see common/setup.c) */ extern const tal_t *wally_tal_ctx; diff --git a/devtools/Makefile b/devtools/Makefile index bc505c76b..4bb8418f0 100644 --- a/devtools/Makefile +++ b/devtools/Makefile @@ -1,10 +1,7 @@ -DEVTOOLS := devtools/bolt11-cli devtools/decodemsg devtools/onion devtools/dump-gossipstore devtools/gossipwith devtools/create-gossipstore devtools/mkcommit devtools/mkfunding devtools/mkclose devtools/mkgossip devtools/mkencoded devtools/mkquery devtools/lightning-checkmessage devtools/topology devtools/route +DEVTOOLS := devtools/bolt11-cli devtools/decodemsg devtools/onion devtools/dump-gossipstore devtools/gossipwith devtools/create-gossipstore devtools/mkcommit devtools/mkfunding devtools/mkclose devtools/mkgossip devtools/mkencoded devtools/mkquery devtools/lightning-checkmessage devtools/topology devtools/route devtools/blindedpath devtools/bolt12-cli ifeq ($(HAVE_SQLITE3),1) DEVTOOLS += devtools/checkchannels endif -ifeq ($(EXPERIMENTAL_FEATURES),1) -DEVTOOLS += devtools/blindedpath devtools/bolt12-cli -endif DEVTOOLS_TOOL_SRC := $(DEVTOOLS:=.c) devtools/print_wire.c devtools/clean_topo.c DEVTOOLS_TOOL_OBJS := $(DEVTOOLS_TOOL_SRC:.c=.o) diff --git a/hsmd/Makefile b/hsmd/Makefile index dadbe280a..5982302d4 100644 --- a/hsmd/Makefile +++ b/hsmd/Makefile @@ -20,6 +20,7 @@ HSMD_COMMON_OBJS := \ common/amount.o \ common/bigsize.o \ common/bip32.o \ + common/bolt12_merkle.o \ common/channel_id.o \ common/daemon.o \ common/daemon_conn.o \ @@ -43,10 +44,6 @@ HSMD_COMMON_OBJS := \ common/utxo.o \ common/version.o -ifeq ($(EXPERIMENTAL_FEATURES),1) -HSMD_COMMON_OBJS += common/bolt12_merkle.o -endif - lightningd/lightning_hsmd: $(HSMD_OBJS) $(HSMD_COMMON_OBJS) $(BITCOIN_OBJS) $(WIRE_OBJS) -include hsmd/test/Makefile diff --git a/hsmd/hsmd.c b/hsmd/hsmd.c index 2356945fc..5333f9eee 100644 --- a/hsmd/hsmd.c +++ b/hsmd/hsmd.c @@ -25,9 +25,7 @@ #include #include #include -#if EXPERIMENTAL_FEATURES #include -#endif #include #include #include @@ -349,7 +347,6 @@ static void node_key(struct privkey *node_privkey, struct pubkey *node_id) #endif } -#if EXPERIMENTAL_FEATURES /*~ This returns the secret and/or public x-only key for this node. */ static void node_schnorrkey(secp256k1_keypair *node_keypair, struct pubkey32 *node_id32) @@ -374,7 +371,6 @@ static void node_schnorrkey(secp256k1_keypair *node_keypair, "Failed to derive xonly pub"); } } -#endif /*~ This secret is the basis for all per-channel secrets: the per-channel seeds * will be generated by mixing in the dbid and the peer node_id. */ @@ -1842,7 +1838,6 @@ static struct io_plan *handle_sign_message(struct io_conn *conn, take(towire_hsmd_sign_message_reply(NULL, &rsig))); } -#if EXPERIMENTAL_FEATURES /*~ lightningd asks us to sign a bolt12 (e.g. offer). */ static struct io_plan *handle_sign_bolt12(struct io_conn *conn, struct client *c, @@ -1896,7 +1891,6 @@ static struct io_plan *handle_sign_bolt12(struct io_conn *conn, return req_reply(conn, c, take(towire_hsmd_sign_bolt12_reply(NULL, &sig))); } -#endif #if DEVELOPER static struct io_plan *handle_memleak(struct io_conn *conn, @@ -2087,11 +2081,7 @@ static struct io_plan *handle_client(struct io_conn *conn, struct client *c) return handle_sign_message(conn, c, c->msg_in); case WIRE_HSMD_SIGN_BOLT12: -#if EXPERIMENTAL_FEATURES return handle_sign_bolt12(conn, c, c->msg_in); -#else - break; -#endif #if DEVELOPER case WIRE_HSMD_DEV_MEMLEAK: return handle_memleak(conn, c, c->msg_in); diff --git a/lightningd/Makefile b/lightningd/Makefile index 6d006f228..497a01801 100644 --- a/lightningd/Makefile +++ b/lightningd/Makefile @@ -45,12 +45,9 @@ LIGHTNINGD_SRC += lightningd/dual_open_control.c endif LIGHTNINGD_SRC_NOHDR := \ + lightningd/offer.c \ lightningd/signmessage.c -ifeq ($(EXPERIMENTAL_FEATURES),1) -LIGHTNINGD_SRC_NOHDR += lightningd/offer.c -endif - LIGHTNINGD_HEADERS := \ $(LIGHTNINGD_SRC:.c=.h) \ lightningd/channel_state.h \ @@ -81,6 +78,8 @@ LIGHTNINGD_COMMON_OBJS := \ common/blinding.o \ common/bolt11.o \ common/bolt11_json.o \ + common/bolt12.o \ + common/bolt12_merkle.o \ common/channel_id.o \ common/channel_config.o \ common/coin_mvt.o \ @@ -132,10 +131,6 @@ LIGHTNINGD_COMMON_OBJS := \ common/wire_error.o \ common/wireaddr.o \ -ifeq ($(EXPERIMENTAL_FEATURES),1) -LIGHTNINGD_COMMON_OBJS += common/bolt12.o common/bolt12_merkle.o -endif - include wallet/Makefile # All together in one convenient var diff --git a/lightningd/invoice.c b/lightningd/invoice.c index 96a7f9ae8..b7e3b372c 100644 --- a/lightningd/invoice.c +++ b/lightningd/invoice.c @@ -8,10 +8,8 @@ #include #include #include -#if EXPERIMENTAL_FEATURES #include #include -#endif #include #include #include @@ -133,7 +131,6 @@ static void invoice_secret(const struct preimage *payment_preimage, memcpy(payment_secret->data, secret.u.u8, sizeof(secret.u.u8)); } -#if EXPERIMENTAL_FEATURES /* FIXME: This is a hack. The real secret should be a signature of some * onion key, using the payer_id */ static void invoice_secret_bolt12(struct lightningd *ld, @@ -156,7 +153,6 @@ static void invoice_secret_bolt12(struct lightningd *ld, BUILD_ASSERT(sizeof(*payment_secret) == sizeof(merkle)); memcpy(payment_secret, &merkle, sizeof(merkle)); } -#endif /* EXPERIMENTAL_FEATURES */ struct invoice_payment_hook_payload { struct lightningd *ld; @@ -371,12 +367,10 @@ invoice_check_payment(const tal_t *ctx, if (payment_secret) { struct secret expected; -#if EXPERIMENTAL_FEATURES if (details->invstring && strstarts(details->invstring, "lni1")) invoice_secret_bolt12(ld, details->invstring, &expected); else -#endif /* EXPERIMENTAL_FEATURES */ - invoice_secret(&details->r, &expected); + invoice_secret(&details->r, &expected); if (!secret_eq_consttime(payment_secret, &expected)) { log_debug(ld->log, "Attept to pay %s with wrong secret", type_to_string(tmpctx, struct sha256, @@ -460,7 +454,6 @@ static bool hsm_sign_b11(const u5 *u5bytes, return true; } -#if EXPERIMENTAL_FEATURES static void hsm_sign_b12_invoice(struct lightningd *ld, struct tlv_invoice *invoice) { @@ -481,7 +474,6 @@ static void hsm_sign_b12_invoice(struct lightningd *ld, fatal("HSM gave bad sign_invoice_reply %s", tal_hex(msg, msg)); } -#endif /* EXPERIMENTAL_FEATURES */ static struct command_result *parse_fallback(struct command *cmd, const char *buffer, @@ -1505,7 +1497,6 @@ static struct command_result *json_createinvoice(struct command *cmd, notify_invoice_creation(cmd->ld, b11->msat, *preimage, label); } else { -#if EXPERIMENTAL_FEATURES struct tlv_invoice *inv; struct sha256 *local_offer_id; @@ -1574,7 +1565,6 @@ static struct command_result *json_createinvoice(struct command *cmd, inv->amount ? &msat : NULL, *preimage, label); } else -#endif /* EXPERIMENTAL_FEATURES */ return command_fail(cmd, JSONRPC2_INVALID_PARAMS, "Unparsable invoice '%s': %s", invstring, fail); diff --git a/lightningd/lightningd.h b/lightningd/lightningd.h index afcac17d6..bef1bbc8f 100644 --- a/lightningd/lightningd.h +++ b/lightningd/lightningd.h @@ -66,6 +66,9 @@ struct config { /* How long before we give up waiting for INIT msg */ u32 connection_timeout_secs; + + /* EXPERIMENTAL: offers support */ + bool exp_offers; }; typedef STRMAP(const char *) alt_subdaemon_map; diff --git a/lightningd/options.c b/lightningd/options.c index 5d77e5958..70dbda91d 100644 --- a/lightningd/options.c +++ b/lightningd/options.c @@ -649,6 +649,8 @@ static const struct config testnet_config = { /* 1 minute should be enough for anyone! */ .connection_timeout_secs = 60, + + .exp_offers = IFEXPERIMENTAL(true, false), }; /* aka. "Dude, where's my coins?" */ @@ -704,6 +706,8 @@ static const struct config mainnet_config = { /* 1 minute should be enough for anyone! */ .connection_timeout_secs = 60, + + .exp_offers = IFEXPERIMENTAL(true, false), }; static void check_config(struct lightningd *ld) @@ -807,6 +811,12 @@ static char *opt_set_onion_messages(struct lightningd *ld) return NULL; } +static char *opt_set_offers(struct lightningd *ld) +{ + ld->config.exp_offers = true; + return opt_set_onion_messages(ld); +} + static void register_opts(struct lightningd *ld) { /* This happens before plugins started */ @@ -859,6 +869,10 @@ static void register_opts(struct lightningd *ld) opt_set_onion_messages, ld, "EXPERIMENTAL: enable send, receive and relay" " of onion messages"); + opt_register_early_noarg("--experimental-offers", + opt_set_offers, ld, + "EXPERIMENTAL: enable send and receive of offers" + " (also sets experimental-onion-messages)"); opt_register_noarg("--help|-h", opt_lightningd_usage, ld, "Print this message."); @@ -1280,6 +1294,8 @@ static void add_config(struct lightningd *ld, feature_offered(ld->our_features ->bits[INIT_FEATURE], OPT_ONION_MESSAGES)); + } else if (opt->cb == (void *)opt_set_offers) { + json_add_bool(response, name0, ld->config.exp_offers); } else if (opt->cb == (void *)plugin_opt_flag_set) { /* Noop, they will get added below along with the * OPT_HASARG options. */ diff --git a/lightningd/pay.c b/lightningd/pay.c index 2ad2c75ca..515230f0d 100644 --- a/lightningd/pay.c +++ b/lightningd/pay.c @@ -2,10 +2,8 @@ #include #include #include -#if EXPERIMENTAL_FEATURES #include #include -#endif #include #include #include @@ -156,11 +154,9 @@ void json_add_payment_fields(struct json_stream *response, if (t->label) json_add_string(response, "label", t->label); if (t->invstring) { -#if EXPERIMENTAL_FEATURES if (strstarts(t->invstring, "lni")) json_add_string(response, "bolt12", t->invstring); else -#endif json_add_string(response, "bolt11", t->invstring); } @@ -344,10 +340,8 @@ void payment_succeeded(struct lightningd *ld, struct htlc_out *hout, hout->partid); assert(payment); -#if EXPERIMENTAL_FEATURES if (payment->local_offer_id) wallet_offer_mark_used(ld->wallet->db, payment->local_offer_id); -#endif tell_waiters_success(ld, &hout->payment_hash, payment); } @@ -803,7 +797,6 @@ static const u8 *send_onion(const tal_t *ctx, struct lightningd *ld, &dont_care_about_channel_update); } -#if EXPERIMENTAL_FEATURES static struct command_result *check_offer_usage(struct command *cmd, const struct sha256 *local_offer_id) { @@ -855,7 +848,6 @@ static struct command_result *check_offer_usage(struct command *cmd, return NULL; } -#endif /* EXPERIMENTAL_FEATURES */ /* destination/route_channels/route_nodes are NULL (and path_secrets may be NULL) * if we're sending a raw onion. */ @@ -1011,12 +1003,10 @@ send_payment_core(struct lightningd *ld, &total_msat)); } -#if EXPERIMENTAL_FEATURES struct command_result *offer_err; offer_err = check_offer_usage(cmd, local_offer_id); if (offer_err) return offer_err; -#endif channel = active_channel_by_id(ld, &first_hop->nodeid, NULL); if (!channel) { @@ -1296,9 +1286,7 @@ static struct command_result *json_sendonion(struct command *cmd, p_opt("bolt11", param_string, &invstring), p_opt_def("msatoshi", param_msat, &msat, AMOUNT_MSAT(0)), p_opt("destination", param_node_id, &destination), -#if EXPERIMENTAL_FEATURES p_opt("localofferid", param_sha256, &local_offer_id), -#endif NULL)) return command_param_failed(); @@ -1451,9 +1439,7 @@ static struct command_result *json_sendpay(struct command *cmd, p_opt("bolt11", param_string, &invstring), p_opt("payment_secret", param_secret, &payment_secret), p_opt_def("partid", param_u64, &partid, 0), -#if EXPERIMENTAL_FEATURES p_opt("localofferid", param_sha256, &local_offer_id), -#endif NULL)) return command_param_failed(); @@ -1582,7 +1568,6 @@ static struct command_result *json_listsendpays(struct command *cmd, if (b11) { rhash = &b11->payment_hash; } else { -#if EXPERIMENTAL_FEATURES struct tlv_invoice *b12; b12 = invoice_decode(cmd, invstring, strlen(invstring), @@ -1591,7 +1576,6 @@ static struct command_result *json_listsendpays(struct command *cmd, if (b12 && b12->payment_hash) rhash = b12->payment_hash; else -#endif return command_fail(cmd, JSONRPC2_INVALID_PARAMS, "Invalid invstring: %s", fail); } diff --git a/lightningd/test/run-invoice-select-inchan.c b/lightningd/test/run-invoice-select-inchan.c index 5a21e7d4f..50df74b7e 100644 --- a/lightningd/test/run-invoice-select-inchan.c +++ b/lightningd/test/run-invoice-select-inchan.c @@ -221,6 +221,23 @@ void htlc_set_fail(struct htlc_set *set UNNEEDED, const u8 *failmsg TAKES UNNEED /* Generated stub for htlc_set_fulfill */ void htlc_set_fulfill(struct htlc_set *set UNNEEDED, const struct preimage *preimage UNNEEDED) { fprintf(stderr, "htlc_set_fulfill called!\n"); abort(); } +/* Generated stub for invoice_decode */ +struct tlv_invoice *invoice_decode(const tal_t *ctx UNNEEDED, + const char *b12 UNNEEDED, size_t b12len UNNEEDED, + const struct feature_set *our_features UNNEEDED, + const struct chainparams *must_be_chain UNNEEDED, + char **fail UNNEEDED) +{ fprintf(stderr, "invoice_decode called!\n"); abort(); } +/* Generated stub for invoice_decode_nosig */ +struct tlv_invoice *invoice_decode_nosig(const tal_t *ctx UNNEEDED, + const char *b12 UNNEEDED, size_t b12len UNNEEDED, + const struct feature_set *our_features UNNEEDED, + const struct chainparams *must_be_chain UNNEEDED, + char **fail UNNEEDED) +{ fprintf(stderr, "invoice_decode_nosig called!\n"); abort(); } +/* Generated stub for invoice_encode */ +char *invoice_encode(const tal_t *ctx UNNEEDED, const struct tlv_invoice *bolt12_tlv UNNEEDED) +{ fprintf(stderr, "invoice_encode called!\n"); abort(); } /* Generated stub for json_add_address */ void json_add_address(struct json_stream *response UNNEEDED, const char *fieldname UNNEEDED, const struct wireaddr *addr UNNEEDED) @@ -356,6 +373,9 @@ void log_(struct log *log UNNEEDED, enum log_level level UNNEEDED, const char *fmt UNNEEDED, ...) { fprintf(stderr, "log_ 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 new_bolt11 */ struct bolt11 *new_bolt11(const tal_t *ctx UNNEEDED, const struct amount_msat *msat TAKES UNNEEDED) @@ -758,29 +778,6 @@ bool dev_disconnect_permanent(struct lightningd *ld UNNEEDED) { fprintf(stderr, "dev_disconnect_permanent called!\n"); abort(); } #endif -#if EXPERIMENTAL_FEATURES -/* 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 invoice_decode_nosig */ -struct tlv_invoice *invoice_decode_nosig(const tal_t *ctx UNNEEDED, - const char *b12 UNNEEDED, size_t b12len UNNEEDED, - const struct feature_set *our_features UNNEEDED, - const struct chainparams *must_be_chain UNNEEDED, - char **fail UNNEEDED) -{ fprintf(stderr, "invoice_decode_nosig called!\n"); abort(); } -/* Generated stub for invoice_encode */ -char *invoice_encode(const tal_t *ctx UNNEEDED, const struct tlv_invoice *bolt12_tlv UNNEEDED) -{ fprintf(stderr, "invoice_encode called!\n"); abort(); } -/* Generated stub for invoice_decode */ -struct tlv_invoice *invoice_decode(const tal_t *ctx UNNEEDED, - const char *b12 UNNEEDED, size_t b12len UNNEEDED, - const struct feature_set *our_features UNNEEDED, - const struct chainparams *must_be_chain UNNEEDED, - char **fail UNNEEDED) -{ fprintf(stderr, "invoice_decode called!\n"); abort(); } -#endif - static void add_candidate(struct routehint_candidate **candidates, int n, struct channel *c) { diff --git a/plugins/Makefile b/plugins/Makefile index de7ff5155..cbaf5b35c 100644 --- a/plugins/Makefile +++ b/plugins/Makefile @@ -1,10 +1,6 @@ PLUGIN_PAY_SRC := plugins/pay.c PLUGIN_PAY_OBJS := $(PLUGIN_PAY_SRC:.c=.o) -ifeq ($(EXPERIMENTAL_FEATURES),1) -PLUGIN_PAY_EXPERIMENTAL_OBJS := common/bolt12.o common/bolt12_merkle.o wire/bolt12$(EXP)_wiregen.o bitcoin/block.o -endif - PLUGIN_AUTOCLEAN_SRC := plugins/autoclean.c PLUGIN_AUTOCLEAN_OBJS := $(PLUGIN_AUTOCLEAN_SRC:.c=.o) @@ -50,18 +46,15 @@ PLUGIN_SPENDER_OBJS := $(PLUGIN_SPENDER_SRC:.c=.o) PLUGIN_ALL_SRC := \ $(PLUGIN_AUTOCLEAN_SRC) \ $(PLUGIN_BCLI_SRC) \ + $(PLUGIN_FETCHINVOICE_SRC) \ $(PLUGIN_KEYSEND_SRC) \ $(PLUGIN_TXPREPARE_SRC) \ $(PLUGIN_LIB_SRC) \ + $(PLUGIN_OFFERS_SRC) \ $(PLUGIN_PAY_LIB_SRC) \ $(PLUGIN_PAY_SRC) \ $(PLUGIN_SPENDER_SRC) -ifeq ($(EXPERIMENTAL_FEATURES),1) -PLUGIN_ALL_SRC += $(PLUGIN_OFFERS_SRC) -PLUGIN_ALL_SRC += $(PLUGIN_FETCHINVOICE_SRC) -endif - PLUGIN_ALL_HEADER := \ $(PLUGIN_LIB_HEADER) \ $(PLUGIN_PAY_LIB_HEADER) \ @@ -72,15 +65,13 @@ PLUGIN_ALL_OBJS := $(PLUGIN_ALL_SRC:.c=.o) PLUGINS := \ plugins/autoclean \ plugins/bcli \ + plugins/fetchinvoice \ plugins/keysend \ + plugins/offers \ plugins/pay \ plugins/txprepare \ plugins/spenderp -ifeq ($(EXPERIMENTAL_FEATURES),1) -PLUGINS += plugins/offers plugins/fetchinvoice -endif - # Make sure these depend on everything. ALL_C_SOURCES += $(PLUGIN_ALL_SRC) ALL_C_HEADERS += $(PLUGIN_ALL_HEADER) @@ -127,7 +118,7 @@ PLUGIN_COMMON_OBJS := \ wire/tlvstream.o \ wire/towire.o -plugins/pay: bitcoin/chainparams.o $(PLUGIN_PAY_OBJS) $(PLUGIN_LIB_OBJS) $(PLUGIN_PAY_LIB_OBJS) $(PLUGIN_COMMON_OBJS) $(JSMN_OBJS) $(CCAN_OBJS) common/gossmap.o common/route.o common/dijkstra.o $(PLUGIN_PAY_EXPERIMENTAL_OBJS) +plugins/pay: bitcoin/chainparams.o $(PLUGIN_PAY_OBJS) $(PLUGIN_LIB_OBJS) $(PLUGIN_PAY_LIB_OBJS) $(PLUGIN_COMMON_OBJS) $(JSMN_OBJS) $(CCAN_OBJS) common/gossmap.o common/route.o common/dijkstra.o common/bolt12.o common/bolt12_merkle.o wire/bolt12$(EXP)_wiregen.o bitcoin/block.o $(PLUGIN_PAY_OBJS): $(PLUGIN_PAY_LIB_HEADER) plugins/autoclean: bitcoin/chainparams.o $(PLUGIN_AUTOCLEAN_OBJS) $(PLUGIN_LIB_OBJS) $(PLUGIN_COMMON_OBJS) $(JSMN_OBJS) $(CCAN_OBJS) @@ -141,9 +132,9 @@ $(PLUGIN_KEYSEND_OBJS): $(PLUGIN_PAY_LIB_HEADER) plugins/spenderp: bitcoin/chainparams.o bitcoin/psbt.o common/psbt_open.o $(PLUGIN_SPENDER_OBJS) $(PLUGIN_LIB_OBJS) $(PLUGIN_COMMON_OBJS) $(JSMN_OBJS) $(CCAN_OBJS) -plugins/offers: bitcoin/chainparams.o $(PLUGIN_OFFERS_OBJS) $(PLUGIN_LIB_OBJS) $(PLUGIN_COMMON_OBJS) common/bolt12.o common/bolt12_merkle.o common/bolt11_json.o common/iso4217.o wire/bolt12_exp_wiregen.o $(WIRE_OBJS) bitcoin/block.o common/channel_id.o bitcoin/preimage.o $(JSMN_OBJS) $(CCAN_OBJS) +plugins/offers: bitcoin/chainparams.o $(PLUGIN_OFFERS_OBJS) $(PLUGIN_LIB_OBJS) $(PLUGIN_COMMON_OBJS) common/bolt12.o common/bolt12_merkle.o common/bolt11_json.o common/iso4217.o $(WIRE_OBJS) bitcoin/block.o common/channel_id.o bitcoin/preimage.o $(JSMN_OBJS) $(CCAN_OBJS) -plugins/fetchinvoice: bitcoin/chainparams.o $(PLUGIN_FETCHINVOICE_OBJS) $(PLUGIN_LIB_OBJS) $(PLUGIN_COMMON_OBJS) common/bolt12.o common/bolt12_merkle.o common/iso4217.o wire/bolt12_exp_wiregen.o $(WIRE_OBJS) bitcoin/block.o common/channel_id.o bitcoin/preimage.o $(JSMN_OBJS) $(CCAN_OBJS) common/gossmap.o common/dijkstra.o common/route.o common/blindedpath.o common/hmac.o common/blinding.o +plugins/fetchinvoice: bitcoin/chainparams.o $(PLUGIN_FETCHINVOICE_OBJS) $(PLUGIN_LIB_OBJS) $(PLUGIN_COMMON_OBJS) common/bolt12.o common/bolt12_merkle.o common/iso4217.o $(WIRE_OBJS) bitcoin/block.o common/channel_id.o bitcoin/preimage.o $(JSMN_OBJS) $(CCAN_OBJS) common/gossmap.o common/dijkstra.o common/route.o common/blindedpath.o common/hmac.o common/blinding.o $(PLUGIN_ALL_OBJS): $(PLUGIN_LIB_HEADER) diff --git a/plugins/fetchinvoice.c b/plugins/fetchinvoice.c index a7e3ce284..a2a2928f2 100644 --- a/plugins/fetchinvoice.c +++ b/plugins/fetchinvoice.c @@ -1349,10 +1349,19 @@ static const struct plugin_command commands[] = { static const char *init(struct plugin *p, const char *buf UNUSED, const jsmntok_t *config UNUSED) { + bool exp_offers; + rpc_scan(p, "getinfo", take(json_out_obj(NULL, NULL, NULL)), "{id:%}", JSON_SCAN(json_to_node_id, &local_id)); + rpc_scan(p, "listconfigs", + take(json_out_obj(NULL, "config", "experimental-offers")), + "{experimental-offers:%}", + JSON_SCAN(json_to_bool, &exp_offers)); + + if (!exp_offers) + return "offers not enabled in config"; return NULL; } diff --git a/plugins/offers.c b/plugins/offers.c index 919a7653c..17117eef9 100644 --- a/plugins/offers.c +++ b/plugins/offers.c @@ -670,6 +670,7 @@ static const char *init(struct plugin *p, const jsmntok_t *config UNUSED) { struct pubkey k; + bool exp_offers; rpc_scan(p, "getinfo", take(json_out_obj(NULL, NULL, NULL)), @@ -679,9 +680,13 @@ static const char *init(struct plugin *p, abort(); rpc_scan(p, "listconfigs", - take(json_out_obj(NULL, "config", "cltv-final")), - "{cltv-final:%}", JSON_SCAN(json_to_number, &cltv_final)); + take(json_out_obj(NULL, NULL, NULL)), + "{cltv-final:%,experimental-offers:%}", + JSON_SCAN(json_to_number, &cltv_final), + JSON_SCAN(json_to_bool, &exp_offers)); + if (!exp_offers) + return "offers not enabled in config"; return NULL; } diff --git a/plugins/pay.c b/plugins/pay.c index 544cb8784..2a79f5ee5 100644 --- a/plugins/pay.c +++ b/plugins/pay.c @@ -9,10 +9,8 @@ #include #include #include -#if EXPERIMENTAL_FEATURES #include #include -#endif #include #include #include @@ -31,6 +29,7 @@ /* Public key of this node. */ static struct node_id my_id; static unsigned int maxdelay_default; +static bool exp_offers; static bool disablempp = false; static LIST_HEAD(pay_status); @@ -1804,10 +1803,8 @@ static struct command_result *listsendpays_done(struct command *cmd, u32 created_at; invstrtok = json_get_member(buf, t, "bolt11"); -#if EXPERIMENTAL_FEATURES if (!invstrtok) invstrtok = json_get_member(buf, t, "bolt12"); -#endif hashtok = json_get_member(buf, t, "payment_hash"); createdtok = json_get_member(buf, t, "created_at"); assert(hashtok != NULL); @@ -1909,9 +1906,10 @@ static const char *init(struct plugin *p, "{id:%}", JSON_SCAN(json_to_node_id, &my_id)); rpc_scan(p, "listconfigs", - take(json_out_obj(NULL, "config", "max-locktime-blocks")), - "{max-locktime-blocks:%}", - JSON_SCAN(json_to_number, &maxdelay_default)); + take(json_out_obj(NULL, NULL, NULL)), + "{max-locktime-blocks:%,experimental-offers:%}", + JSON_SCAN(json_to_number, &maxdelay_default), + JSON_SCAN(json_to_bool, &exp_offers)); return NULL; } @@ -1964,10 +1962,8 @@ static struct command_result *json_paymod(struct command *cmd, struct shadow_route_data *shadow_route; struct amount_msat *invmsat; u64 invexpiry; -#if EXPERIMENTAL_FEATURES struct sha256 *local_offer_id; const struct tlv_invoice *b12; -#endif #if DEVELOPER bool *use_shadow; #endif @@ -1988,9 +1984,7 @@ static struct command_result *json_paymod(struct command *cmd, p_opt_def("maxdelay", param_number, &maxdelay, maxdelay_default), p_opt_def("exemptfee", param_msat, &exemptfee, AMOUNT_MSAT(5000)), -#if EXPERIMENTAL_FEATURES p_opt("localofferid", param_sha256, &local_offer_id), -#endif #if DEVELOPER p_opt_def("use_shadow", param_bool, &use_shadow, true), #endif @@ -2022,10 +2016,13 @@ static struct command_result *json_paymod(struct command *cmd, return command_fail(cmd, JSONRPC2_INVALID_PARAMS, "Invalid bolt11:" " sets feature var_onion with no secret"); -#if EXPERIMENTAL_FEATURES } else if ((b12 = invoice_decode(cmd, b11str, strlen(b11str), plugin_feature_set(cmd->plugin), chainparams, &fail)) != NULL) { + if (!exp_offers) + return command_fail(cmd, JSONRPC2_INVALID_PARAMS, + "experimental-offers disabled"); + p->features = tal_steal(p, b12->features); if (!b12->node_id) @@ -2082,7 +2079,6 @@ static struct command_result *json_paymod(struct command *cmd, else invexpiry = *b12->timestamp + BOLT12_DEFAULT_REL_EXPIRY; p->local_offer_id = tal_steal(p, local_offer_id); -#endif /* EXPERIMENTAL_FEATURES */ } else return command_fail(cmd, JSONRPC2_INVALID_PARAMS, "Invalid bolt11: %s", fail); diff --git a/tests/test_pay.py b/tests/test_pay.py index ff0719933..b52d27213 100644 --- a/tests/test_pay.py +++ b/tests/test_pay.py @@ -3723,10 +3723,19 @@ def test_mpp_overload_payee(node_factory, bitcoind): l1.rpc.pay(inv) -@unittest.skipIf(not EXPERIMENTAL_FEATURES, "offers are experimental") +@unittest.skipIf(EXPERIMENTAL_FEATURES, "this is always on with EXPERIMENTAL_FEATURES") +def test_offer_needs_option(node_factory): + """Make sure we don't make offers without offer command""" + l1 = node_factory.get_node() + with pytest.raises(RpcError, match='Unknown command'): + l1.rpc.call('offer', {'amount': '1msat', 'description': 'test'}) + with pytest.raises(RpcError, match='Unknown command'): + l1.rpc.call('fetchinvoice', {'offer': 'aaaa'}) + + def test_offer(node_factory, bitcoind): plugin = os.path.join(os.path.dirname(__file__), 'plugins/currencyUSDAUD5000.py') - l1 = node_factory.get_node(options={'plugin': plugin}) + l1 = node_factory.get_node(options={'plugin': plugin, 'experimental-offers': None}) bolt12tool = os.path.join(os.path.dirname(__file__), "..", "devtools", "bolt12-cli") # Try different amount strings @@ -3885,12 +3894,13 @@ def test_offer(node_factory, bitcoind): assert 'recurrence: every 600 seconds paywindow -10 to +600 (pay proportional)\n' in output -@unittest.skipIf(not EXPERIMENTAL_FEATURES, "offers are experimental") def test_fetchinvoice(node_factory, bitcoind): # We remove the conversion plugin on l3, causing it to get upset. l1, l2, l3 = node_factory.line_graph(3, wait_for_announce=True, - opts=[{}, {}, - {'allow_broken_log': True}]) + opts=[{'experimental-offers': None}, + {'experimental-offers': None}, + {'experimental-offers': None, + 'allow_broken_log': True}]) # Simple offer first. offer1 = l3.rpc.call('offer', {'amount': '2msat', @@ -3988,7 +3998,7 @@ def test_fetchinvoice(node_factory, bitcoind): 'recurrence_label': 'test recurrence'}) # Check we can request invoice without a channel. - l4 = node_factory.get_node() + l4 = node_factory.get_node(options={'experimental-offers': None}) l4.rpc.connect(l2.info['id'], 'localhost', l2.port) ret = l4.rpc.call('fetchinvoice', {'offer': offer3, 'recurrence_counter': 0, @@ -4062,9 +4072,9 @@ def test_pay_waitblockheight_timeout(node_factory, bitcoind): assert len(status['pay'][0]['attempts']) == 1 -@unittest.skipIf(not EXPERIMENTAL_FEATURES, "offers are experimental") def test_sendinvoice(node_factory, bitcoind): - l1, l2 = node_factory.line_graph(2, wait_for_announce=True) + l1, l2 = node_factory.line_graph(2, wait_for_announce=True, + opts={'experimental-offers': None}) # Simple offer to send money (balances channel a little) offer = l1.rpc.call('offerout', {'amount': '100000sat', diff --git a/tests/test_plugin.py b/tests/test_plugin.py index 8b0d67eac..deeb6123d 100644 --- a/tests/test_plugin.py +++ b/tests/test_plugin.py @@ -386,9 +386,7 @@ def test_pay_plugin(node_factory): # Make sure usage messages are present. msg = 'pay bolt11 [msatoshi] [label] [riskfactor] [maxfeepercent] '\ - '[retry_for] [maxdelay] [exemptfee]' - if EXPERIMENTAL_FEATURES: - msg += ' [localofferid]' + '[retry_for] [maxdelay] [exemptfee] [localofferid]' if DEVELOPER: msg += ' [use_shadow]' assert only_one(l1.rpc.help('pay')['help'])['command'] == msg diff --git a/wire/bolt12_wiregen.c b/wire/bolt12_wiregen.c new file mode 100644 index 000000000..b52cf3326 --- /dev/null +++ b/wire/bolt12_wiregen.c @@ -0,0 +1,1565 @@ +/* This file was generated by generate-wire.py */ +/* Do not modify this file! Modify the .csv file it was generated from. */ +/* Original template can be found at tools/gen/impl_template */ + +#include +#include +#include +#include +#include +#include +#include + +#ifndef SUPERVERBOSE +#define SUPERVERBOSE(...) +#endif + + + + +/* SUBTYPE: BLINDED_PATH */ +void towire_blinded_path(u8 **p, const struct blinded_path *blinded_path) +{ + u16 num_hops = tal_count(blinded_path->path); + + towire_pubkey(p, &blinded_path->blinding); + towire_u16(p, num_hops); + for (size_t i = 0; i < num_hops; i++) + towire_onionmsg_path(p, blinded_path->path[i]); +} +struct blinded_path * +fromwire_blinded_path(const tal_t *ctx, const u8 **cursor, size_t *plen) +{ + struct blinded_path *blinded_path = tal(ctx, struct blinded_path); + u16 num_hops; + + fromwire_pubkey(cursor, plen, &blinded_path->blinding); + num_hops = fromwire_u16(cursor, plen); + blinded_path->path = num_hops ? tal_arr(blinded_path, struct onionmsg_path *, 0) : NULL; + for (size_t i = 0; i < num_hops; i++) { + struct onionmsg_path * tmp; + tmp = fromwire_onionmsg_path(blinded_path, cursor, plen); + tal_arr_expand(&blinded_path->path, tmp); + } + + return blinded_path; +} + +/* SUBTYPE: BLINDED_PAYINFO */ +void towire_blinded_payinfo(u8 **p, const struct blinded_payinfo *blinded_payinfo) +{ + u16 flen = tal_count(blinded_payinfo->features); + + towire_u32(p, blinded_payinfo->fee_base_msat); + towire_u32(p, blinded_payinfo->fee_proportional_millionths); + towire_u16(p, blinded_payinfo->cltv_expiry_delta); + towire_u16(p, flen); + towire_u8_array(p, blinded_payinfo->features, flen); +} +struct blinded_payinfo * +fromwire_blinded_payinfo(const tal_t *ctx, const u8 **cursor, size_t *plen) +{ + struct blinded_payinfo *blinded_payinfo = tal(ctx, struct blinded_payinfo); + u16 flen; + + blinded_payinfo->fee_base_msat = fromwire_u32(cursor, plen); + blinded_payinfo->fee_proportional_millionths = fromwire_u32(cursor, plen); + blinded_payinfo->cltv_expiry_delta = fromwire_u16(cursor, plen); + flen = fromwire_u16(cursor, plen); + blinded_payinfo->features = flen ? tal_arr(blinded_payinfo, u8, flen) : NULL; +fromwire_u8_array(cursor, plen, blinded_payinfo->features, flen); + + return blinded_payinfo; +} + +/* SUBTYPE: FALLBACK_ADDRESS */ +void towire_fallback_address(u8 **p, const struct fallback_address *fallback_address) +{ + u16 len = tal_count(fallback_address->address); + + towire_u8(p, fallback_address->version); + towire_u16(p, len); + towire_u8_array(p, fallback_address->address, len); +} +struct fallback_address * +fromwire_fallback_address(const tal_t *ctx, const u8 **cursor, size_t *plen) +{ + struct fallback_address *fallback_address = tal(ctx, struct fallback_address); + u16 len; + + fallback_address->version = fromwire_u8(cursor, plen); + len = fromwire_u16(cursor, plen); + fallback_address->address = len ? tal_arr(fallback_address, u8, len) : NULL; +fromwire_u8_array(cursor, plen, fallback_address->address, len); + + return fallback_address; +} + + +struct tlv_offer *tlv_offer_new(const tal_t *ctx) +{ + /* Initialize everything to NULL. (Quiet, C pedants!) */ + struct tlv_offer *inst = talz(ctx, struct tlv_offer); + + /* Initialized the fields to an empty array. */ + inst->fields = tal_arr(inst, struct tlv_field, 0); + return inst; +} + +/* OFFER MSG: chains */ +static u8 *towire_tlv_offer_chains(const tal_t *ctx, const void *vrecord) +{ + const struct tlv_offer *r = vrecord; + u8 *ptr; + + if (!r->chains) + return NULL; + + + ptr = tal_arr(ctx, u8, 0); + + for (size_t i = 0; i < tal_count(r->chains); i++) + towire_bitcoin_blkid(&ptr, r->chains + i); + return ptr; +} +static void fromwire_tlv_offer_chains(const u8 **cursor, size_t *plen, void *vrecord) +{ + struct tlv_offer *r = vrecord; + + r->chains = *plen ? tal_arr(r, struct bitcoin_blkid, 0) : NULL; + for (size_t i = 0; *plen != 0; i++) { + struct bitcoin_blkid tmp; + fromwire_bitcoin_blkid(cursor, plen, &tmp); + tal_arr_expand(&r->chains, tmp); + } +} +/* OFFER MSG: currency */ +static u8 *towire_tlv_offer_currency(const tal_t *ctx, const void *vrecord) +{ + const struct tlv_offer *r = vrecord; + u8 *ptr; + + if (!r->currency) + return NULL; + + + ptr = tal_arr(ctx, u8, 0); + + towire_utf8_array(&ptr, r->currency, tal_count(r->currency)); + return ptr; +} +static void fromwire_tlv_offer_currency(const u8 **cursor, size_t *plen, void *vrecord) +{ + struct tlv_offer *r = vrecord; + + r->currency = *plen ? tal_arr(r, utf8, *plen) : NULL; +fromwire_utf8_array(cursor, plen, r->currency, *plen); +} +/* OFFER MSG: amount */ +static u8 *towire_tlv_offer_amount(const tal_t *ctx, const void *vrecord) +{ + const struct tlv_offer *r = vrecord; + u8 *ptr; + + if (!r->amount) + return NULL; + + + ptr = tal_arr(ctx, u8, 0); + + towire_tu64(&ptr, *r->amount); + return ptr; +} +static void fromwire_tlv_offer_amount(const u8 **cursor, size_t *plen, void *vrecord) +{ + struct tlv_offer *r = vrecord; + + r->amount = tal(r, u64); + +*r->amount = fromwire_tu64(cursor, plen); +} +/* OFFER MSG: description */ +static u8 *towire_tlv_offer_description(const tal_t *ctx, const void *vrecord) +{ + const struct tlv_offer *r = vrecord; + u8 *ptr; + + if (!r->description) + return NULL; + + + ptr = tal_arr(ctx, u8, 0); + + towire_utf8_array(&ptr, r->description, tal_count(r->description)); + return ptr; +} +static void fromwire_tlv_offer_description(const u8 **cursor, size_t *plen, void *vrecord) +{ + struct tlv_offer *r = vrecord; + + r->description = *plen ? tal_arr(r, utf8, *plen) : NULL; +fromwire_utf8_array(cursor, plen, r->description, *plen); +} +/* OFFER MSG: features */ +static u8 *towire_tlv_offer_features(const tal_t *ctx, const void *vrecord) +{ + const struct tlv_offer *r = vrecord; + u8 *ptr; + + if (!r->features) + return NULL; + + + ptr = tal_arr(ctx, u8, 0); + + towire_u8_array(&ptr, r->features, tal_count(r->features)); + return ptr; +} +static void fromwire_tlv_offer_features(const u8 **cursor, size_t *plen, void *vrecord) +{ + struct tlv_offer *r = vrecord; + + r->features = *plen ? tal_arr(r, u8, *plen) : NULL; +fromwire_u8_array(cursor, plen, r->features, *plen); +} +/* OFFER MSG: absolute_expiry */ +static u8 *towire_tlv_offer_absolute_expiry(const tal_t *ctx, const void *vrecord) +{ + const struct tlv_offer *r = vrecord; + u8 *ptr; + + if (!r->absolute_expiry) + return NULL; + + + ptr = tal_arr(ctx, u8, 0); + + towire_tu64(&ptr, *r->absolute_expiry); + return ptr; +} +static void fromwire_tlv_offer_absolute_expiry(const u8 **cursor, size_t *plen, void *vrecord) +{ + struct tlv_offer *r = vrecord; + + r->absolute_expiry = tal(r, u64); + +*r->absolute_expiry = fromwire_tu64(cursor, plen); +} +/* OFFER MSG: paths */ +static u8 *towire_tlv_offer_paths(const tal_t *ctx, const void *vrecord) +{ + const struct tlv_offer *r = vrecord; + u8 *ptr; + + if (!r->paths) + return NULL; + + + ptr = tal_arr(ctx, u8, 0); + + for (size_t i = 0; i < tal_count(r->paths); i++) + towire_blinded_path(&ptr, r->paths[i]); + return ptr; +} +static void fromwire_tlv_offer_paths(const u8 **cursor, size_t *plen, void *vrecord) +{ + struct tlv_offer *r = vrecord; + + r->paths = *plen ? tal_arr(r, struct blinded_path *, 0) : NULL; + for (size_t i = 0; *plen != 0; i++) { + struct blinded_path * tmp; + tmp = fromwire_blinded_path(r, cursor, plen); + tal_arr_expand(&r->paths, tmp); + } +} +/* OFFER MSG: vendor */ +static u8 *towire_tlv_offer_vendor(const tal_t *ctx, const void *vrecord) +{ + const struct tlv_offer *r = vrecord; + u8 *ptr; + + if (!r->vendor) + return NULL; + + + ptr = tal_arr(ctx, u8, 0); + + towire_utf8_array(&ptr, r->vendor, tal_count(r->vendor)); + return ptr; +} +static void fromwire_tlv_offer_vendor(const u8 **cursor, size_t *plen, void *vrecord) +{ + struct tlv_offer *r = vrecord; + + r->vendor = *plen ? tal_arr(r, utf8, *plen) : NULL; +fromwire_utf8_array(cursor, plen, r->vendor, *plen); +} +/* OFFER MSG: quantity_min */ +static u8 *towire_tlv_offer_quantity_min(const tal_t *ctx, const void *vrecord) +{ + const struct tlv_offer *r = vrecord; + u8 *ptr; + + if (!r->quantity_min) + return NULL; + + + ptr = tal_arr(ctx, u8, 0); + + towire_tu64(&ptr, *r->quantity_min); + return ptr; +} +static void fromwire_tlv_offer_quantity_min(const u8 **cursor, size_t *plen, void *vrecord) +{ + struct tlv_offer *r = vrecord; + + r->quantity_min = tal(r, u64); + +*r->quantity_min = fromwire_tu64(cursor, plen); +} +/* OFFER MSG: quantity_max */ +static u8 *towire_tlv_offer_quantity_max(const tal_t *ctx, const void *vrecord) +{ + const struct tlv_offer *r = vrecord; + u8 *ptr; + + if (!r->quantity_max) + return NULL; + + + ptr = tal_arr(ctx, u8, 0); + + towire_tu64(&ptr, *r->quantity_max); + return ptr; +} +static void fromwire_tlv_offer_quantity_max(const u8 **cursor, size_t *plen, void *vrecord) +{ + struct tlv_offer *r = vrecord; + + r->quantity_max = tal(r, u64); + +*r->quantity_max = fromwire_tu64(cursor, plen); +} +/* OFFER MSG: recurrence */ +static u8 *towire_tlv_offer_recurrence(const tal_t *ctx, const void *vrecord) +{ + const struct tlv_offer *r = vrecord; + u8 *ptr; + + if (!r->recurrence) + return NULL; + + + ptr = tal_arr(ctx, u8, 0); + + towire_u8(&ptr, r->recurrence->time_unit); + + towire_tu32(&ptr, r->recurrence->period); + return ptr; +} +static void fromwire_tlv_offer_recurrence(const u8 **cursor, size_t *plen, void *vrecord) +{ + struct tlv_offer *r = vrecord; + + r->recurrence = tal(r, struct tlv_offer_recurrence); + r->recurrence->time_unit = fromwire_u8(cursor, plen); + r->recurrence->period = fromwire_tu32(cursor, plen); +} +/* OFFER MSG: recurrence_paywindow */ +static u8 *towire_tlv_offer_recurrence_paywindow(const tal_t *ctx, const void *vrecord) +{ + const struct tlv_offer *r = vrecord; + u8 *ptr; + + if (!r->recurrence_paywindow) + return NULL; + + + ptr = tal_arr(ctx, u8, 0); + + towire_u32(&ptr, r->recurrence_paywindow->seconds_before); + + towire_u8(&ptr, r->recurrence_paywindow->proportional_amount); + + towire_tu32(&ptr, r->recurrence_paywindow->seconds_after); + return ptr; +} +static void fromwire_tlv_offer_recurrence_paywindow(const u8 **cursor, size_t *plen, void *vrecord) +{ + struct tlv_offer *r = vrecord; + + r->recurrence_paywindow = tal(r, struct tlv_offer_recurrence_paywindow); + r->recurrence_paywindow->seconds_before = fromwire_u32(cursor, plen); + r->recurrence_paywindow->proportional_amount = fromwire_u8(cursor, plen); + r->recurrence_paywindow->seconds_after = fromwire_tu32(cursor, plen); +} +/* OFFER MSG: recurrence_limit */ +static u8 *towire_tlv_offer_recurrence_limit(const tal_t *ctx, const void *vrecord) +{ + const struct tlv_offer *r = vrecord; + u8 *ptr; + + if (!r->recurrence_limit) + return NULL; + + + ptr = tal_arr(ctx, u8, 0); + + towire_tu32(&ptr, *r->recurrence_limit); + return ptr; +} +static void fromwire_tlv_offer_recurrence_limit(const u8 **cursor, size_t *plen, void *vrecord) +{ + struct tlv_offer *r = vrecord; + + r->recurrence_limit = tal(r, u32); + +*r->recurrence_limit = fromwire_tu32(cursor, plen); +} +/* OFFER MSG: recurrence_base */ +static u8 *towire_tlv_offer_recurrence_base(const tal_t *ctx, const void *vrecord) +{ + const struct tlv_offer *r = vrecord; + u8 *ptr; + + if (!r->recurrence_base) + return NULL; + + + ptr = tal_arr(ctx, u8, 0); + + towire_u8(&ptr, r->recurrence_base->start_any_period); + + towire_tu64(&ptr, r->recurrence_base->basetime); + return ptr; +} +static void fromwire_tlv_offer_recurrence_base(const u8 **cursor, size_t *plen, void *vrecord) +{ + struct tlv_offer *r = vrecord; + + r->recurrence_base = tal(r, struct tlv_offer_recurrence_base); + r->recurrence_base->start_any_period = fromwire_u8(cursor, plen); + r->recurrence_base->basetime = fromwire_tu64(cursor, plen); +} +/* OFFER MSG: node_id */ +static u8 *towire_tlv_offer_node_id(const tal_t *ctx, const void *vrecord) +{ + const struct tlv_offer *r = vrecord; + u8 *ptr; + + if (!r->node_id) + return NULL; + + + ptr = tal_arr(ctx, u8, 0); + + towire_pubkey32(&ptr, r->node_id); + return ptr; +} +static void fromwire_tlv_offer_node_id(const u8 **cursor, size_t *plen, void *vrecord) +{ + struct tlv_offer *r = vrecord; + + r->node_id = tal(r, struct pubkey32); + +fromwire_pubkey32(cursor, plen, &*r->node_id); +} +/* OFFER MSG: send_invoice */ +static u8 *towire_tlv_offer_send_invoice(const tal_t *ctx, const void *vrecord) +{ + const struct tlv_offer *r = vrecord; + u8 *ptr; + + if (!r->send_invoice) + return NULL; + + + ptr = tal_arr(ctx, u8, 0); + return ptr; +} +static void fromwire_tlv_offer_send_invoice(const u8 **cursor, size_t *plen, void *vrecord) +{ + struct tlv_offer *r = vrecord; + + r->send_invoice = tal(r, struct tlv_offer_send_invoice); +} +/* OFFER MSG: refund_for */ +static u8 *towire_tlv_offer_refund_for(const tal_t *ctx, const void *vrecord) +{ + const struct tlv_offer *r = vrecord; + u8 *ptr; + + if (!r->refund_for) + return NULL; + + + ptr = tal_arr(ctx, u8, 0); + + towire_sha256(&ptr, r->refund_for); + return ptr; +} +static void fromwire_tlv_offer_refund_for(const u8 **cursor, size_t *plen, void *vrecord) +{ + struct tlv_offer *r = vrecord; + + r->refund_for = tal(r, struct sha256); + +fromwire_sha256(cursor, plen, &*r->refund_for); +} +/* OFFER MSG: signature */ +static u8 *towire_tlv_offer_signature(const tal_t *ctx, const void *vrecord) +{ + const struct tlv_offer *r = vrecord; + u8 *ptr; + + if (!r->signature) + return NULL; + + + ptr = tal_arr(ctx, u8, 0); + + towire_bip340sig(&ptr, r->signature); + return ptr; +} +static void fromwire_tlv_offer_signature(const u8 **cursor, size_t *plen, void *vrecord) +{ + struct tlv_offer *r = vrecord; + + r->signature = tal(r, struct bip340sig); + +fromwire_bip340sig(cursor, plen, &*r->signature); +} + +static const struct tlv_record_type tlvs_offer[] = { + { 2, towire_tlv_offer_chains, fromwire_tlv_offer_chains }, + { 6, towire_tlv_offer_currency, fromwire_tlv_offer_currency }, + { 8, towire_tlv_offer_amount, fromwire_tlv_offer_amount }, + { 10, towire_tlv_offer_description, fromwire_tlv_offer_description }, + { 12, towire_tlv_offer_features, fromwire_tlv_offer_features }, + { 14, towire_tlv_offer_absolute_expiry, fromwire_tlv_offer_absolute_expiry }, + { 16, towire_tlv_offer_paths, fromwire_tlv_offer_paths }, + { 20, towire_tlv_offer_vendor, fromwire_tlv_offer_vendor }, + { 22, towire_tlv_offer_quantity_min, fromwire_tlv_offer_quantity_min }, + { 24, towire_tlv_offer_quantity_max, fromwire_tlv_offer_quantity_max }, + { 26, towire_tlv_offer_recurrence, fromwire_tlv_offer_recurrence }, + { 28, towire_tlv_offer_recurrence_base, fromwire_tlv_offer_recurrence_base }, + { 30, towire_tlv_offer_node_id, fromwire_tlv_offer_node_id }, + { 34, towire_tlv_offer_refund_for, fromwire_tlv_offer_refund_for }, + { 54, towire_tlv_offer_send_invoice, fromwire_tlv_offer_send_invoice }, + { 64, towire_tlv_offer_recurrence_paywindow, fromwire_tlv_offer_recurrence_paywindow }, + { 66, towire_tlv_offer_recurrence_limit, fromwire_tlv_offer_recurrence_limit }, + { 240, towire_tlv_offer_signature, fromwire_tlv_offer_signature }, +}; + +void towire_offer(u8 **pptr, const struct tlv_offer *record) +{ + towire_tlv(pptr, tlvs_offer, 18, record); +} + + +bool fromwire_offer(const u8 **cursor, size_t *max, struct tlv_offer *record) +{ + return fromwire_tlv(cursor, max, tlvs_offer, 18, record, &record->fields); +} + +bool offer_is_valid(const struct tlv_offer *record, size_t *err_index) +{ + return tlv_fields_valid(record->fields, err_index); +} + + +struct tlv_invoice_request *tlv_invoice_request_new(const tal_t *ctx) +{ + /* Initialize everything to NULL. (Quiet, C pedants!) */ + struct tlv_invoice_request *inst = talz(ctx, struct tlv_invoice_request); + + /* Initialized the fields to an empty array. */ + inst->fields = tal_arr(inst, struct tlv_field, 0); + return inst; +} + +/* INVOICE_REQUEST MSG: chains */ +static u8 *towire_tlv_invoice_request_chains(const tal_t *ctx, const void *vrecord) +{ + const struct tlv_invoice_request *r = vrecord; + u8 *ptr; + + if (!r->chains) + return NULL; + + + ptr = tal_arr(ctx, u8, 0); + + for (size_t i = 0; i < tal_count(r->chains); i++) + towire_bitcoin_blkid(&ptr, r->chains + i); + return ptr; +} +static void fromwire_tlv_invoice_request_chains(const u8 **cursor, size_t *plen, void *vrecord) +{ + struct tlv_invoice_request *r = vrecord; + + r->chains = *plen ? tal_arr(r, struct bitcoin_blkid, 0) : NULL; + for (size_t i = 0; *plen != 0; i++) { + struct bitcoin_blkid tmp; + fromwire_bitcoin_blkid(cursor, plen, &tmp); + tal_arr_expand(&r->chains, tmp); + } +} +/* INVOICE_REQUEST MSG: offer_id */ +static u8 *towire_tlv_invoice_request_offer_id(const tal_t *ctx, const void *vrecord) +{ + const struct tlv_invoice_request *r = vrecord; + u8 *ptr; + + if (!r->offer_id) + return NULL; + + + ptr = tal_arr(ctx, u8, 0); + + towire_sha256(&ptr, r->offer_id); + return ptr; +} +static void fromwire_tlv_invoice_request_offer_id(const u8 **cursor, size_t *plen, void *vrecord) +{ + struct tlv_invoice_request *r = vrecord; + + r->offer_id = tal(r, struct sha256); + +fromwire_sha256(cursor, plen, &*r->offer_id); +} +/* INVOICE_REQUEST MSG: amount */ +static u8 *towire_tlv_invoice_request_amount(const tal_t *ctx, const void *vrecord) +{ + const struct tlv_invoice_request *r = vrecord; + u8 *ptr; + + if (!r->amount) + return NULL; + + + ptr = tal_arr(ctx, u8, 0); + + towire_tu64(&ptr, *r->amount); + return ptr; +} +static void fromwire_tlv_invoice_request_amount(const u8 **cursor, size_t *plen, void *vrecord) +{ + struct tlv_invoice_request *r = vrecord; + + r->amount = tal(r, u64); + +*r->amount = fromwire_tu64(cursor, plen); +} +/* INVOICE_REQUEST MSG: features */ +static u8 *towire_tlv_invoice_request_features(const tal_t *ctx, const void *vrecord) +{ + const struct tlv_invoice_request *r = vrecord; + u8 *ptr; + + if (!r->features) + return NULL; + + + ptr = tal_arr(ctx, u8, 0); + + towire_u8_array(&ptr, r->features, tal_count(r->features)); + return ptr; +} +static void fromwire_tlv_invoice_request_features(const u8 **cursor, size_t *plen, void *vrecord) +{ + struct tlv_invoice_request *r = vrecord; + + r->features = *plen ? tal_arr(r, u8, *plen) : NULL; +fromwire_u8_array(cursor, plen, r->features, *plen); +} +/* INVOICE_REQUEST MSG: quantity */ +static u8 *towire_tlv_invoice_request_quantity(const tal_t *ctx, const void *vrecord) +{ + const struct tlv_invoice_request *r = vrecord; + u8 *ptr; + + if (!r->quantity) + return NULL; + + + ptr = tal_arr(ctx, u8, 0); + + towire_tu64(&ptr, *r->quantity); + return ptr; +} +static void fromwire_tlv_invoice_request_quantity(const u8 **cursor, size_t *plen, void *vrecord) +{ + struct tlv_invoice_request *r = vrecord; + + r->quantity = tal(r, u64); + +*r->quantity = fromwire_tu64(cursor, plen); +} +/* INVOICE_REQUEST MSG: recurrence_counter */ +static u8 *towire_tlv_invoice_request_recurrence_counter(const tal_t *ctx, const void *vrecord) +{ + const struct tlv_invoice_request *r = vrecord; + u8 *ptr; + + if (!r->recurrence_counter) + return NULL; + + + ptr = tal_arr(ctx, u8, 0); + + towire_tu32(&ptr, *r->recurrence_counter); + return ptr; +} +static void fromwire_tlv_invoice_request_recurrence_counter(const u8 **cursor, size_t *plen, void *vrecord) +{ + struct tlv_invoice_request *r = vrecord; + + r->recurrence_counter = tal(r, u32); + +*r->recurrence_counter = fromwire_tu32(cursor, plen); +} +/* INVOICE_REQUEST MSG: recurrence_start */ +static u8 *towire_tlv_invoice_request_recurrence_start(const tal_t *ctx, const void *vrecord) +{ + const struct tlv_invoice_request *r = vrecord; + u8 *ptr; + + if (!r->recurrence_start) + return NULL; + + + ptr = tal_arr(ctx, u8, 0); + + towire_tu32(&ptr, *r->recurrence_start); + return ptr; +} +static void fromwire_tlv_invoice_request_recurrence_start(const u8 **cursor, size_t *plen, void *vrecord) +{ + struct tlv_invoice_request *r = vrecord; + + r->recurrence_start = tal(r, u32); + +*r->recurrence_start = fromwire_tu32(cursor, plen); +} +/* INVOICE_REQUEST MSG: payer_key */ +static u8 *towire_tlv_invoice_request_payer_key(const tal_t *ctx, const void *vrecord) +{ + const struct tlv_invoice_request *r = vrecord; + u8 *ptr; + + if (!r->payer_key) + return NULL; + + + ptr = tal_arr(ctx, u8, 0); + + towire_pubkey32(&ptr, r->payer_key); + return ptr; +} +static void fromwire_tlv_invoice_request_payer_key(const u8 **cursor, size_t *plen, void *vrecord) +{ + struct tlv_invoice_request *r = vrecord; + + r->payer_key = tal(r, struct pubkey32); + +fromwire_pubkey32(cursor, plen, &*r->payer_key); +} +/* INVOICE_REQUEST MSG: payer_info */ +static u8 *towire_tlv_invoice_request_payer_info(const tal_t *ctx, const void *vrecord) +{ + const struct tlv_invoice_request *r = vrecord; + u8 *ptr; + + if (!r->payer_info) + return NULL; + + + ptr = tal_arr(ctx, u8, 0); + + towire_u8_array(&ptr, r->payer_info, tal_count(r->payer_info)); + return ptr; +} +static void fromwire_tlv_invoice_request_payer_info(const u8 **cursor, size_t *plen, void *vrecord) +{ + struct tlv_invoice_request *r = vrecord; + + r->payer_info = *plen ? tal_arr(r, u8, *plen) : NULL; +fromwire_u8_array(cursor, plen, r->payer_info, *plen); +} +/* INVOICE_REQUEST MSG: recurrence_signature */ +static u8 *towire_tlv_invoice_request_recurrence_signature(const tal_t *ctx, const void *vrecord) +{ + const struct tlv_invoice_request *r = vrecord; + u8 *ptr; + + if (!r->recurrence_signature) + return NULL; + + + ptr = tal_arr(ctx, u8, 0); + + towire_bip340sig(&ptr, r->recurrence_signature); + return ptr; +} +static void fromwire_tlv_invoice_request_recurrence_signature(const u8 **cursor, size_t *plen, void *vrecord) +{ + struct tlv_invoice_request *r = vrecord; + + r->recurrence_signature = tal(r, struct bip340sig); + +fromwire_bip340sig(cursor, plen, &*r->recurrence_signature); +} + +const struct tlv_record_type tlvs_invoice_request[] = { + { 2, towire_tlv_invoice_request_chains, fromwire_tlv_invoice_request_chains }, + { 4, towire_tlv_invoice_request_offer_id, fromwire_tlv_invoice_request_offer_id }, + { 8, towire_tlv_invoice_request_amount, fromwire_tlv_invoice_request_amount }, + { 12, towire_tlv_invoice_request_features, fromwire_tlv_invoice_request_features }, + { 32, towire_tlv_invoice_request_quantity, fromwire_tlv_invoice_request_quantity }, + { 36, towire_tlv_invoice_request_recurrence_counter, fromwire_tlv_invoice_request_recurrence_counter }, + { 38, towire_tlv_invoice_request_payer_key, fromwire_tlv_invoice_request_payer_key }, + { 50, towire_tlv_invoice_request_payer_info, fromwire_tlv_invoice_request_payer_info }, + { 68, towire_tlv_invoice_request_recurrence_start, fromwire_tlv_invoice_request_recurrence_start }, + { 242, towire_tlv_invoice_request_recurrence_signature, fromwire_tlv_invoice_request_recurrence_signature }, +}; + +void towire_invoice_request(u8 **pptr, const struct tlv_invoice_request *record) +{ + towire_tlv(pptr, tlvs_invoice_request, 10, record); +} + + +bool fromwire_invoice_request(const u8 **cursor, size_t *max, struct tlv_invoice_request *record) +{ + return fromwire_tlv(cursor, max, tlvs_invoice_request, 10, record, &record->fields); +} + +bool invoice_request_is_valid(const struct tlv_invoice_request *record, size_t *err_index) +{ + return tlv_fields_valid(record->fields, err_index); +} + + +struct tlv_invoice *tlv_invoice_new(const tal_t *ctx) +{ + /* Initialize everything to NULL. (Quiet, C pedants!) */ + struct tlv_invoice *inst = talz(ctx, struct tlv_invoice); + + /* Initialized the fields to an empty array. */ + inst->fields = tal_arr(inst, struct tlv_field, 0); + return inst; +} + +/* INVOICE MSG: chains */ +static u8 *towire_tlv_invoice_chains(const tal_t *ctx, const void *vrecord) +{ + const struct tlv_invoice *r = vrecord; + u8 *ptr; + + if (!r->chains) + return NULL; + + + ptr = tal_arr(ctx, u8, 0); + + for (size_t i = 0; i < tal_count(r->chains); i++) + towire_bitcoin_blkid(&ptr, r->chains + i); + return ptr; +} +static void fromwire_tlv_invoice_chains(const u8 **cursor, size_t *plen, void *vrecord) +{ + struct tlv_invoice *r = vrecord; + + r->chains = *plen ? tal_arr(r, struct bitcoin_blkid, 0) : NULL; + for (size_t i = 0; *plen != 0; i++) { + struct bitcoin_blkid tmp; + fromwire_bitcoin_blkid(cursor, plen, &tmp); + tal_arr_expand(&r->chains, tmp); + } +} +/* INVOICE MSG: offer_id */ +static u8 *towire_tlv_invoice_offer_id(const tal_t *ctx, const void *vrecord) +{ + const struct tlv_invoice *r = vrecord; + u8 *ptr; + + if (!r->offer_id) + return NULL; + + + ptr = tal_arr(ctx, u8, 0); + + towire_sha256(&ptr, r->offer_id); + return ptr; +} +static void fromwire_tlv_invoice_offer_id(const u8 **cursor, size_t *plen, void *vrecord) +{ + struct tlv_invoice *r = vrecord; + + r->offer_id = tal(r, struct sha256); + +fromwire_sha256(cursor, plen, &*r->offer_id); +} +/* INVOICE MSG: amount */ +static u8 *towire_tlv_invoice_amount(const tal_t *ctx, const void *vrecord) +{ + const struct tlv_invoice *r = vrecord; + u8 *ptr; + + if (!r->amount) + return NULL; + + + ptr = tal_arr(ctx, u8, 0); + + towire_tu64(&ptr, *r->amount); + return ptr; +} +static void fromwire_tlv_invoice_amount(const u8 **cursor, size_t *plen, void *vrecord) +{ + struct tlv_invoice *r = vrecord; + + r->amount = tal(r, u64); + +*r->amount = fromwire_tu64(cursor, plen); +} +/* INVOICE MSG: description */ +static u8 *towire_tlv_invoice_description(const tal_t *ctx, const void *vrecord) +{ + const struct tlv_invoice *r = vrecord; + u8 *ptr; + + if (!r->description) + return NULL; + + + ptr = tal_arr(ctx, u8, 0); + + towire_utf8_array(&ptr, r->description, tal_count(r->description)); + return ptr; +} +static void fromwire_tlv_invoice_description(const u8 **cursor, size_t *plen, void *vrecord) +{ + struct tlv_invoice *r = vrecord; + + r->description = *plen ? tal_arr(r, utf8, *plen) : NULL; +fromwire_utf8_array(cursor, plen, r->description, *plen); +} +/* INVOICE MSG: features */ +static u8 *towire_tlv_invoice_features(const tal_t *ctx, const void *vrecord) +{ + const struct tlv_invoice *r = vrecord; + u8 *ptr; + + if (!r->features) + return NULL; + + + ptr = tal_arr(ctx, u8, 0); + + towire_u8_array(&ptr, r->features, tal_count(r->features)); + return ptr; +} +static void fromwire_tlv_invoice_features(const u8 **cursor, size_t *plen, void *vrecord) +{ + struct tlv_invoice *r = vrecord; + + r->features = *plen ? tal_arr(r, u8, *plen) : NULL; +fromwire_u8_array(cursor, plen, r->features, *plen); +} +/* INVOICE MSG: paths */ +static u8 *towire_tlv_invoice_paths(const tal_t *ctx, const void *vrecord) +{ + const struct tlv_invoice *r = vrecord; + u8 *ptr; + + if (!r->paths) + return NULL; + + + ptr = tal_arr(ctx, u8, 0); + + for (size_t i = 0; i < tal_count(r->paths); i++) + towire_blinded_path(&ptr, r->paths[i]); + return ptr; +} +static void fromwire_tlv_invoice_paths(const u8 **cursor, size_t *plen, void *vrecord) +{ + struct tlv_invoice *r = vrecord; + + r->paths = *plen ? tal_arr(r, struct blinded_path *, 0) : NULL; + for (size_t i = 0; *plen != 0; i++) { + struct blinded_path * tmp; + tmp = fromwire_blinded_path(r, cursor, plen); + tal_arr_expand(&r->paths, tmp); + } +} +/* INVOICE MSG: blindedpay */ +static u8 *towire_tlv_invoice_blindedpay(const tal_t *ctx, const void *vrecord) +{ + const struct tlv_invoice *r = vrecord; + u8 *ptr; + + if (!r->blindedpay) + return NULL; + + + ptr = tal_arr(ctx, u8, 0); + + for (size_t i = 0; i < tal_count(r->blindedpay); i++) + towire_blinded_payinfo(&ptr, r->blindedpay[i]); + return ptr; +} +static void fromwire_tlv_invoice_blindedpay(const u8 **cursor, size_t *plen, void *vrecord) +{ + struct tlv_invoice *r = vrecord; + + r->blindedpay = *plen ? tal_arr(r, struct blinded_payinfo *, 0) : NULL; + for (size_t i = 0; *plen != 0; i++) { + struct blinded_payinfo * tmp; + tmp = fromwire_blinded_payinfo(r, cursor, plen); + tal_arr_expand(&r->blindedpay, tmp); + } +} +/* INVOICE MSG: vendor */ +static u8 *towire_tlv_invoice_vendor(const tal_t *ctx, const void *vrecord) +{ + const struct tlv_invoice *r = vrecord; + u8 *ptr; + + if (!r->vendor) + return NULL; + + + ptr = tal_arr(ctx, u8, 0); + + towire_utf8_array(&ptr, r->vendor, tal_count(r->vendor)); + return ptr; +} +static void fromwire_tlv_invoice_vendor(const u8 **cursor, size_t *plen, void *vrecord) +{ + struct tlv_invoice *r = vrecord; + + r->vendor = *plen ? tal_arr(r, utf8, *plen) : NULL; +fromwire_utf8_array(cursor, plen, r->vendor, *plen); +} +/* INVOICE MSG: node_id */ +static u8 *towire_tlv_invoice_node_id(const tal_t *ctx, const void *vrecord) +{ + const struct tlv_invoice *r = vrecord; + u8 *ptr; + + if (!r->node_id) + return NULL; + + + ptr = tal_arr(ctx, u8, 0); + + towire_pubkey32(&ptr, r->node_id); + return ptr; +} +static void fromwire_tlv_invoice_node_id(const u8 **cursor, size_t *plen, void *vrecord) +{ + struct tlv_invoice *r = vrecord; + + r->node_id = tal(r, struct pubkey32); + +fromwire_pubkey32(cursor, plen, &*r->node_id); +} +/* INVOICE MSG: quantity */ +static u8 *towire_tlv_invoice_quantity(const tal_t *ctx, const void *vrecord) +{ + const struct tlv_invoice *r = vrecord; + u8 *ptr; + + if (!r->quantity) + return NULL; + + + ptr = tal_arr(ctx, u8, 0); + + towire_tu64(&ptr, *r->quantity); + return ptr; +} +static void fromwire_tlv_invoice_quantity(const u8 **cursor, size_t *plen, void *vrecord) +{ + struct tlv_invoice *r = vrecord; + + r->quantity = tal(r, u64); + +*r->quantity = fromwire_tu64(cursor, plen); +} +/* INVOICE MSG: refund_for */ +static u8 *towire_tlv_invoice_refund_for(const tal_t *ctx, const void *vrecord) +{ + const struct tlv_invoice *r = vrecord; + u8 *ptr; + + if (!r->refund_for) + return NULL; + + + ptr = tal_arr(ctx, u8, 0); + + towire_sha256(&ptr, r->refund_for); + return ptr; +} +static void fromwire_tlv_invoice_refund_for(const u8 **cursor, size_t *plen, void *vrecord) +{ + struct tlv_invoice *r = vrecord; + + r->refund_for = tal(r, struct sha256); + +fromwire_sha256(cursor, plen, &*r->refund_for); +} +/* INVOICE MSG: recurrence_counter */ +static u8 *towire_tlv_invoice_recurrence_counter(const tal_t *ctx, const void *vrecord) +{ + const struct tlv_invoice *r = vrecord; + u8 *ptr; + + if (!r->recurrence_counter) + return NULL; + + + ptr = tal_arr(ctx, u8, 0); + + towire_tu32(&ptr, *r->recurrence_counter); + return ptr; +} +static void fromwire_tlv_invoice_recurrence_counter(const u8 **cursor, size_t *plen, void *vrecord) +{ + struct tlv_invoice *r = vrecord; + + r->recurrence_counter = tal(r, u32); + +*r->recurrence_counter = fromwire_tu32(cursor, plen); +} +/* INVOICE MSG: send_invoice */ +static u8 *towire_tlv_invoice_send_invoice(const tal_t *ctx, const void *vrecord) +{ + const struct tlv_invoice *r = vrecord; + u8 *ptr; + + if (!r->send_invoice) + return NULL; + + + ptr = tal_arr(ctx, u8, 0); + return ptr; +} +static void fromwire_tlv_invoice_send_invoice(const u8 **cursor, size_t *plen, void *vrecord) +{ + struct tlv_invoice *r = vrecord; + + r->send_invoice = tal(r, struct tlv_invoice_send_invoice); +} +/* INVOICE MSG: recurrence_start */ +static u8 *towire_tlv_invoice_recurrence_start(const tal_t *ctx, const void *vrecord) +{ + const struct tlv_invoice *r = vrecord; + u8 *ptr; + + if (!r->recurrence_start) + return NULL; + + + ptr = tal_arr(ctx, u8, 0); + + towire_tu32(&ptr, *r->recurrence_start); + return ptr; +} +static void fromwire_tlv_invoice_recurrence_start(const u8 **cursor, size_t *plen, void *vrecord) +{ + struct tlv_invoice *r = vrecord; + + r->recurrence_start = tal(r, u32); + +*r->recurrence_start = fromwire_tu32(cursor, plen); +} +/* INVOICE MSG: recurrence_basetime */ +static u8 *towire_tlv_invoice_recurrence_basetime(const tal_t *ctx, const void *vrecord) +{ + const struct tlv_invoice *r = vrecord; + u8 *ptr; + + if (!r->recurrence_basetime) + return NULL; + + + ptr = tal_arr(ctx, u8, 0); + + towire_tu64(&ptr, *r->recurrence_basetime); + return ptr; +} +static void fromwire_tlv_invoice_recurrence_basetime(const u8 **cursor, size_t *plen, void *vrecord) +{ + struct tlv_invoice *r = vrecord; + + r->recurrence_basetime = tal(r, u64); + +*r->recurrence_basetime = fromwire_tu64(cursor, plen); +} +/* INVOICE MSG: payer_key */ +static u8 *towire_tlv_invoice_payer_key(const tal_t *ctx, const void *vrecord) +{ + const struct tlv_invoice *r = vrecord; + u8 *ptr; + + if (!r->payer_key) + return NULL; + + + ptr = tal_arr(ctx, u8, 0); + + towire_pubkey32(&ptr, r->payer_key); + return ptr; +} +static void fromwire_tlv_invoice_payer_key(const u8 **cursor, size_t *plen, void *vrecord) +{ + struct tlv_invoice *r = vrecord; + + r->payer_key = tal(r, struct pubkey32); + +fromwire_pubkey32(cursor, plen, &*r->payer_key); +} +/* INVOICE MSG: payer_info */ +static u8 *towire_tlv_invoice_payer_info(const tal_t *ctx, const void *vrecord) +{ + const struct tlv_invoice *r = vrecord; + u8 *ptr; + + if (!r->payer_info) + return NULL; + + + ptr = tal_arr(ctx, u8, 0); + + towire_u8_array(&ptr, r->payer_info, tal_count(r->payer_info)); + return ptr; +} +static void fromwire_tlv_invoice_payer_info(const u8 **cursor, size_t *plen, void *vrecord) +{ + struct tlv_invoice *r = vrecord; + + r->payer_info = *plen ? tal_arr(r, u8, *plen) : NULL; +fromwire_u8_array(cursor, plen, r->payer_info, *plen); +} +/* INVOICE MSG: timestamp */ +static u8 *towire_tlv_invoice_timestamp(const tal_t *ctx, const void *vrecord) +{ + const struct tlv_invoice *r = vrecord; + u8 *ptr; + + if (!r->timestamp) + return NULL; + + + ptr = tal_arr(ctx, u8, 0); + + towire_tu64(&ptr, *r->timestamp); + return ptr; +} +static void fromwire_tlv_invoice_timestamp(const u8 **cursor, size_t *plen, void *vrecord) +{ + struct tlv_invoice *r = vrecord; + + r->timestamp = tal(r, u64); + +*r->timestamp = fromwire_tu64(cursor, plen); +} +/* INVOICE MSG: payment_hash */ +static u8 *towire_tlv_invoice_payment_hash(const tal_t *ctx, const void *vrecord) +{ + const struct tlv_invoice *r = vrecord; + u8 *ptr; + + if (!r->payment_hash) + return NULL; + + + ptr = tal_arr(ctx, u8, 0); + + towire_sha256(&ptr, r->payment_hash); + return ptr; +} +static void fromwire_tlv_invoice_payment_hash(const u8 **cursor, size_t *plen, void *vrecord) +{ + struct tlv_invoice *r = vrecord; + + r->payment_hash = tal(r, struct sha256); + +fromwire_sha256(cursor, plen, &*r->payment_hash); +} +/* INVOICE MSG: relative_expiry */ +static u8 *towire_tlv_invoice_relative_expiry(const tal_t *ctx, const void *vrecord) +{ + const struct tlv_invoice *r = vrecord; + u8 *ptr; + + if (!r->relative_expiry) + return NULL; + + + ptr = tal_arr(ctx, u8, 0); + + towire_tu32(&ptr, *r->relative_expiry); + return ptr; +} +static void fromwire_tlv_invoice_relative_expiry(const u8 **cursor, size_t *plen, void *vrecord) +{ + struct tlv_invoice *r = vrecord; + + r->relative_expiry = tal(r, u32); + +*r->relative_expiry = fromwire_tu32(cursor, plen); +} +/* INVOICE MSG: cltv */ +static u8 *towire_tlv_invoice_cltv(const tal_t *ctx, const void *vrecord) +{ + const struct tlv_invoice *r = vrecord; + u8 *ptr; + + if (!r->cltv) + return NULL; + + + ptr = tal_arr(ctx, u8, 0); + + towire_tu32(&ptr, *r->cltv); + return ptr; +} +static void fromwire_tlv_invoice_cltv(const u8 **cursor, size_t *plen, void *vrecord) +{ + struct tlv_invoice *r = vrecord; + + r->cltv = tal(r, u32); + +*r->cltv = fromwire_tu32(cursor, plen); +} +/* INVOICE MSG: fallbacks */ +static u8 *towire_tlv_invoice_fallbacks(const tal_t *ctx, const void *vrecord) +{ + const struct tlv_invoice *r = vrecord; + u8 *ptr; + + if (!r->fallbacks) + return NULL; + + u8 num = tal_count(r->fallbacks->fallbacks); + + ptr = tal_arr(ctx, u8, 0); + + towire_u8(&ptr, num); + + for (size_t i = 0; i < num; i++) + towire_fallback_address(&ptr, r->fallbacks->fallbacks[i]); + return ptr; +} +static void fromwire_tlv_invoice_fallbacks(const u8 **cursor, size_t *plen, void *vrecord) +{ + struct tlv_invoice *r = vrecord; + u8 num; + + r->fallbacks = tal(r, struct tlv_invoice_fallbacks); + num = fromwire_u8(cursor, plen); + r->fallbacks->fallbacks = num ? tal_arr(r->fallbacks, struct fallback_address *, 0) : NULL; + for (size_t i = 0; i < num; i++) { + struct fallback_address * tmp; + tmp = fromwire_fallback_address(r->fallbacks, cursor, plen); + tal_arr_expand(&r->fallbacks->fallbacks, tmp); + } +} +/* INVOICE MSG: refund_signature */ +static u8 *towire_tlv_invoice_refund_signature(const tal_t *ctx, const void *vrecord) +{ + const struct tlv_invoice *r = vrecord; + u8 *ptr; + + if (!r->refund_signature) + return NULL; + + + ptr = tal_arr(ctx, u8, 0); + + towire_bip340sig(&ptr, r->refund_signature); + return ptr; +} +static void fromwire_tlv_invoice_refund_signature(const u8 **cursor, size_t *plen, void *vrecord) +{ + struct tlv_invoice *r = vrecord; + + r->refund_signature = tal(r, struct bip340sig); + +fromwire_bip340sig(cursor, plen, &*r->refund_signature); +} +/* INVOICE MSG: signature */ +static u8 *towire_tlv_invoice_signature(const tal_t *ctx, const void *vrecord) +{ + const struct tlv_invoice *r = vrecord; + u8 *ptr; + + if (!r->signature) + return NULL; + + + ptr = tal_arr(ctx, u8, 0); + + towire_bip340sig(&ptr, r->signature); + return ptr; +} +static void fromwire_tlv_invoice_signature(const u8 **cursor, size_t *plen, void *vrecord) +{ + struct tlv_invoice *r = vrecord; + + r->signature = tal(r, struct bip340sig); + +fromwire_bip340sig(cursor, plen, &*r->signature); +} + +static const struct tlv_record_type tlvs_invoice[] = { + { 2, towire_tlv_invoice_chains, fromwire_tlv_invoice_chains }, + { 4, towire_tlv_invoice_offer_id, fromwire_tlv_invoice_offer_id }, + { 8, towire_tlv_invoice_amount, fromwire_tlv_invoice_amount }, + { 10, towire_tlv_invoice_description, fromwire_tlv_invoice_description }, + { 12, towire_tlv_invoice_features, fromwire_tlv_invoice_features }, + { 16, towire_tlv_invoice_paths, fromwire_tlv_invoice_paths }, + { 18, towire_tlv_invoice_blindedpay, fromwire_tlv_invoice_blindedpay }, + { 20, towire_tlv_invoice_vendor, fromwire_tlv_invoice_vendor }, + { 30, towire_tlv_invoice_node_id, fromwire_tlv_invoice_node_id }, + { 32, towire_tlv_invoice_quantity, fromwire_tlv_invoice_quantity }, + { 34, towire_tlv_invoice_refund_for, fromwire_tlv_invoice_refund_for }, + { 36, towire_tlv_invoice_recurrence_counter, fromwire_tlv_invoice_recurrence_counter }, + { 38, towire_tlv_invoice_payer_key, fromwire_tlv_invoice_payer_key }, + { 40, towire_tlv_invoice_timestamp, fromwire_tlv_invoice_timestamp }, + { 42, towire_tlv_invoice_payment_hash, fromwire_tlv_invoice_payment_hash }, + { 44, towire_tlv_invoice_relative_expiry, fromwire_tlv_invoice_relative_expiry }, + { 46, towire_tlv_invoice_cltv, fromwire_tlv_invoice_cltv }, + { 48, towire_tlv_invoice_fallbacks, fromwire_tlv_invoice_fallbacks }, + { 50, towire_tlv_invoice_payer_info, fromwire_tlv_invoice_payer_info }, + { 52, towire_tlv_invoice_refund_signature, fromwire_tlv_invoice_refund_signature }, + { 54, towire_tlv_invoice_send_invoice, fromwire_tlv_invoice_send_invoice }, + { 64, towire_tlv_invoice_recurrence_basetime, fromwire_tlv_invoice_recurrence_basetime }, + { 68, towire_tlv_invoice_recurrence_start, fromwire_tlv_invoice_recurrence_start }, + { 240, towire_tlv_invoice_signature, fromwire_tlv_invoice_signature }, +}; + +void towire_invoice(u8 **pptr, const struct tlv_invoice *record) +{ + towire_tlv(pptr, tlvs_invoice, 24, record); +} + + +bool fromwire_invoice(const u8 **cursor, size_t *max, struct tlv_invoice *record) +{ + return fromwire_tlv(cursor, max, tlvs_invoice, 24, record, &record->fields); +} + +bool invoice_is_valid(const struct tlv_invoice *record, size_t *err_index) +{ + return tlv_fields_valid(record->fields, err_index); +} + + +struct tlv_invoice_error *tlv_invoice_error_new(const tal_t *ctx) +{ + /* Initialize everything to NULL. (Quiet, C pedants!) */ + struct tlv_invoice_error *inst = talz(ctx, struct tlv_invoice_error); + + /* Initialized the fields to an empty array. */ + inst->fields = tal_arr(inst, struct tlv_field, 0); + return inst; +} + +/* INVOICE_ERROR MSG: erroneous_field */ +static u8 *towire_tlv_invoice_error_erroneous_field(const tal_t *ctx, const void *vrecord) +{ + const struct tlv_invoice_error *r = vrecord; + u8 *ptr; + + if (!r->erroneous_field) + return NULL; + + + ptr = tal_arr(ctx, u8, 0); + + towire_tu64(&ptr, *r->erroneous_field); + return ptr; +} +static void fromwire_tlv_invoice_error_erroneous_field(const u8 **cursor, size_t *plen, void *vrecord) +{ + struct tlv_invoice_error *r = vrecord; + + r->erroneous_field = tal(r, u64); + +*r->erroneous_field = fromwire_tu64(cursor, plen); +} +/* INVOICE_ERROR MSG: suggested_value */ +static u8 *towire_tlv_invoice_error_suggested_value(const tal_t *ctx, const void *vrecord) +{ + const struct tlv_invoice_error *r = vrecord; + u8 *ptr; + + if (!r->suggested_value) + return NULL; + + + ptr = tal_arr(ctx, u8, 0); + + towire_u8_array(&ptr, r->suggested_value, tal_count(r->suggested_value)); + return ptr; +} +static void fromwire_tlv_invoice_error_suggested_value(const u8 **cursor, size_t *plen, void *vrecord) +{ + struct tlv_invoice_error *r = vrecord; + + r->suggested_value = *plen ? tal_arr(r, u8, *plen) : NULL; +fromwire_u8_array(cursor, plen, r->suggested_value, *plen); +} +/* INVOICE_ERROR MSG: error */ +static u8 *towire_tlv_invoice_error_error(const tal_t *ctx, const void *vrecord) +{ + const struct tlv_invoice_error *r = vrecord; + u8 *ptr; + + if (!r->error) + return NULL; + + + ptr = tal_arr(ctx, u8, 0); + + towire_utf8_array(&ptr, r->error, tal_count(r->error)); + return ptr; +} +static void fromwire_tlv_invoice_error_error(const u8 **cursor, size_t *plen, void *vrecord) +{ + struct tlv_invoice_error *r = vrecord; + + r->error = *plen ? tal_arr(r, utf8, *plen) : NULL; +fromwire_utf8_array(cursor, plen, r->error, *plen); +} + +static const struct tlv_record_type tlvs_invoice_error[] = { + { 1, towire_tlv_invoice_error_erroneous_field, fromwire_tlv_invoice_error_erroneous_field }, + { 3, towire_tlv_invoice_error_suggested_value, fromwire_tlv_invoice_error_suggested_value }, + { 5, towire_tlv_invoice_error_error, fromwire_tlv_invoice_error_error }, +}; + +void towire_invoice_error(u8 **pptr, const struct tlv_invoice_error *record) +{ + towire_tlv(pptr, tlvs_invoice_error, 3, record); +} + + +bool fromwire_invoice_error(const u8 **cursor, size_t *max, struct tlv_invoice_error *record) +{ + return fromwire_tlv(cursor, max, tlvs_invoice_error, 3, record, &record->fields); +} + +bool invoice_error_is_valid(const struct tlv_invoice_error *record, size_t *err_index) +{ + return tlv_fields_valid(record->fields, err_index); +} + +// SHA256STAMP:b09ebf868d0b5b9792d0054bee17d763c1243d18c419847c554c63aefb7a8548 diff --git a/wire/bolt12_wiregen.h b/wire/bolt12_wiregen.h new file mode 100644 index 000000000..91d79a349 --- /dev/null +++ b/wire/bolt12_wiregen.h @@ -0,0 +1,319 @@ +/* This file was generated by generate-wire.py */ +/* Do not modify this file! Modify the _csv file it was generated from. */ +/* Original template can be found at tools/gen/header_template */ + +#ifndef LIGHTNING_WIRE_BOLT12_WIREGEN_H +#define LIGHTNING_WIRE_BOLT12_WIREGEN_H +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +struct blinded_path { + struct pubkey blinding; + struct onionmsg_path **path; +}; +struct blinded_payinfo { + u32 fee_base_msat; + u32 fee_proportional_millionths; + u16 cltv_expiry_delta; + u8 *features; +}; +struct fallback_address { + u8 version; + u8 *address; +}; +struct tlv_offer_recurrence { + u8 time_unit; + u32 period; +}; +struct tlv_offer_recurrence_paywindow { + u32 seconds_before; + u8 proportional_amount; + u32 seconds_after; +}; +struct tlv_offer_recurrence_base { + u8 start_any_period; + u64 basetime; +}; +struct tlv_offer_send_invoice { +}; +struct tlv_invoice_send_invoice { +}; +struct tlv_invoice_fallbacks { + struct fallback_address **fallbacks; +}; +struct tlv_offer { + /* Raw fields including unknown ones. */ + struct tlv_field *fields; + + /* TODO The following explicit fields could just point into the + * tlv_field entries above to save on memory. */ + struct bitcoin_blkid *chains; + utf8 *currency; + u64 *amount; + utf8 *description; + u8 *features; + u64 *absolute_expiry; + struct blinded_path **paths; + utf8 *vendor; + u64 *quantity_min; + u64 *quantity_max; + struct tlv_offer_recurrence *recurrence; + struct tlv_offer_recurrence_paywindow *recurrence_paywindow; + u32 *recurrence_limit; + struct tlv_offer_recurrence_base *recurrence_base; + struct pubkey32 *node_id; + struct tlv_offer_send_invoice *send_invoice; + struct sha256 *refund_for; + struct bip340sig *signature; +}; +struct tlv_invoice_request { + /* Raw fields including unknown ones. */ + struct tlv_field *fields; + + /* TODO The following explicit fields could just point into the + * tlv_field entries above to save on memory. */ + struct bitcoin_blkid *chains; + struct sha256 *offer_id; + u64 *amount; + u8 *features; + u64 *quantity; + u32 *recurrence_counter; + u32 *recurrence_start; + struct pubkey32 *payer_key; + u8 *payer_info; + struct bip340sig *recurrence_signature; +}; +struct tlv_invoice { + /* Raw fields including unknown ones. */ + struct tlv_field *fields; + + /* TODO The following explicit fields could just point into the + * tlv_field entries above to save on memory. */ + struct bitcoin_blkid *chains; + struct sha256 *offer_id; + u64 *amount; + utf8 *description; + u8 *features; + struct blinded_path **paths; + struct blinded_payinfo **blindedpay; + utf8 *vendor; + struct pubkey32 *node_id; + u64 *quantity; + struct sha256 *refund_for; + u32 *recurrence_counter; + struct tlv_invoice_send_invoice *send_invoice; + u32 *recurrence_start; + u64 *recurrence_basetime; + struct pubkey32 *payer_key; + u8 *payer_info; + u64 *timestamp; + struct sha256 *payment_hash; + u32 *relative_expiry; + u32 *cltv; + struct tlv_invoice_fallbacks *fallbacks; + struct bip340sig *refund_signature; + struct bip340sig *signature; +}; +struct tlv_invoice_error { + /* Raw fields including unknown ones. */ + struct tlv_field *fields; + + /* TODO The following explicit fields could just point into the + * tlv_field entries above to save on memory. */ + u64 *erroneous_field; + u8 *suggested_value; + utf8 *error; +}; + +struct tlv_offer *tlv_offer_new(const tal_t *ctx); + +/** + * Deserialize a TLV stream for the offer namespace. + * + * This function will parse any TLV stream, as long as the type, length and + * value fields are formatted correctly. Fields that are not known in the + * current namespace are stored in the `fields` member. Validity can be + * checked using offer_is_valid. + */ +bool fromwire_offer(const u8 **cursor, size_t *max, + struct tlv_offer * record); + +/** + * Serialize a TLV stream for the offer namespace. + * + * This function only considers known fields from the offer namespace, + * and will ignore any fields that may be stored in the `fields` member. This + * ensures that the resulting stream is valid according to + * `offer_is_valid`. + */ +void towire_offer(u8 **pptr, const struct tlv_offer *record); + +/** + * Check that the TLV stream is valid. + * + * Enforces the followin validity rules: + * - Types must be in monotonic non-repeating order + * - We must understand all even types + * + * Returns false if an error was detected, otherwise returns true. If err_index + * is non-null and we detect an error it is set to the index of the first error + * detected. + */ +bool offer_is_valid(const struct tlv_offer *record, + size_t *err_index); + +struct tlv_invoice_request *tlv_invoice_request_new(const tal_t *ctx); + +/** + * Deserialize a TLV stream for the invoice_request namespace. + * + * This function will parse any TLV stream, as long as the type, length and + * value fields are formatted correctly. Fields that are not known in the + * current namespace are stored in the `fields` member. Validity can be + * checked using invoice_request_is_valid. + */ +bool fromwire_invoice_request(const u8 **cursor, size_t *max, + struct tlv_invoice_request * record); + +/** + * Serialize a TLV stream for the invoice_request namespace. + * + * This function only considers known fields from the invoice_request namespace, + * and will ignore any fields that may be stored in the `fields` member. This + * ensures that the resulting stream is valid according to + * `invoice_request_is_valid`. + */ +void towire_invoice_request(u8 **pptr, const struct tlv_invoice_request *record); + +/** + * Check that the TLV stream is valid. + * + * Enforces the followin validity rules: + * - Types must be in monotonic non-repeating order + * - We must understand all even types + * + * Returns false if an error was detected, otherwise returns true. If err_index + * is non-null and we detect an error it is set to the index of the first error + * detected. + */ +bool invoice_request_is_valid(const struct tlv_invoice_request *record, + size_t *err_index); + +#define TLVS_ARRAY_SIZE_invoice_request 10 +extern const struct tlv_record_type tlvs_invoice_request[]; + + + +/* Define an enum with the constants */ +enum invoice_request_types { + TLV_INVOICE_REQUEST_CHAINS = 2, + TLV_INVOICE_REQUEST_OFFER_ID = 4, + TLV_INVOICE_REQUEST_AMOUNT = 8, + TLV_INVOICE_REQUEST_FEATURES = 12, + TLV_INVOICE_REQUEST_QUANTITY = 32, + TLV_INVOICE_REQUEST_RECURRENCE_COUNTER = 36, + TLV_INVOICE_REQUEST_PAYER_KEY = 38, + TLV_INVOICE_REQUEST_PAYER_INFO = 50, + TLV_INVOICE_REQUEST_RECURRENCE_START = 68, + TLV_INVOICE_REQUEST_RECURRENCE_SIGNATURE = 242, +}; + +struct tlv_invoice *tlv_invoice_new(const tal_t *ctx); + +/** + * Deserialize a TLV stream for the invoice namespace. + * + * This function will parse any TLV stream, as long as the type, length and + * value fields are formatted correctly. Fields that are not known in the + * current namespace are stored in the `fields` member. Validity can be + * checked using invoice_is_valid. + */ +bool fromwire_invoice(const u8 **cursor, size_t *max, + struct tlv_invoice * record); + +/** + * Serialize a TLV stream for the invoice namespace. + * + * This function only considers known fields from the invoice namespace, + * and will ignore any fields that may be stored in the `fields` member. This + * ensures that the resulting stream is valid according to + * `invoice_is_valid`. + */ +void towire_invoice(u8 **pptr, const struct tlv_invoice *record); + +/** + * Check that the TLV stream is valid. + * + * Enforces the followin validity rules: + * - Types must be in monotonic non-repeating order + * - We must understand all even types + * + * Returns false if an error was detected, otherwise returns true. If err_index + * is non-null and we detect an error it is set to the index of the first error + * detected. + */ +bool invoice_is_valid(const struct tlv_invoice *record, + size_t *err_index); + +struct tlv_invoice_error *tlv_invoice_error_new(const tal_t *ctx); + +/** + * Deserialize a TLV stream for the invoice_error namespace. + * + * This function will parse any TLV stream, as long as the type, length and + * value fields are formatted correctly. Fields that are not known in the + * current namespace are stored in the `fields` member. Validity can be + * checked using invoice_error_is_valid. + */ +bool fromwire_invoice_error(const u8 **cursor, size_t *max, + struct tlv_invoice_error * record); + +/** + * Serialize a TLV stream for the invoice_error namespace. + * + * This function only considers known fields from the invoice_error namespace, + * and will ignore any fields that may be stored in the `fields` member. This + * ensures that the resulting stream is valid according to + * `invoice_error_is_valid`. + */ +void towire_invoice_error(u8 **pptr, const struct tlv_invoice_error *record); + +/** + * Check that the TLV stream is valid. + * + * Enforces the followin validity rules: + * - Types must be in monotonic non-repeating order + * - We must understand all even types + * + * Returns false if an error was detected, otherwise returns true. If err_index + * is non-null and we detect an error it is set to the index of the first error + * detected. + */ +bool invoice_error_is_valid(const struct tlv_invoice_error *record, + size_t *err_index); + +/* SUBTYPE: BLINDED_PATH */ +void towire_blinded_path(u8 **p, const struct blinded_path *blinded_path); +struct blinded_path *fromwire_blinded_path(const tal_t *ctx, const u8 **cursor, size_t *plen); + +/* SUBTYPE: BLINDED_PAYINFO */ +void towire_blinded_payinfo(u8 **p, const struct blinded_payinfo *blinded_payinfo); +struct blinded_payinfo *fromwire_blinded_payinfo(const tal_t *ctx, const u8 **cursor, size_t *plen); + +/* SUBTYPE: FALLBACK_ADDRESS */ +void towire_fallback_address(u8 **p, const struct fallback_address *fallback_address); +struct fallback_address *fromwire_fallback_address(const tal_t *ctx, const u8 **cursor, size_t *plen); + + +#endif /* LIGHTNING_WIRE_BOLT12_WIREGEN_H */ +// SHA256STAMP:b09ebf868d0b5b9792d0054bee17d763c1243d18c419847c554c63aefb7a8548 diff --git a/wire/common_wiregen.c b/wire/common_wiregen.c index 7dea9032e..25f7fc46a 100644 --- a/wire/common_wiregen.c +++ b/wire/common_wiregen.c @@ -100,4 +100,4 @@ bool fromwire_custommsg_out(const tal_t *ctx, const void *p, u8 **msg) fromwire_u8_array(&cursor, &plen, *msg, msg_len); return cursor != NULL; } -// SHA256STAMP:c97dcd31559f7a0764d6bad2a532cbe79355b4c7c17b32f60ceb810329959865 +// SHA256STAMP:304c3015d0df2a9436adf3c2c96365d438781a5cf55b9ccba73a05dd7bc28a4d diff --git a/wire/common_wiregen.h b/wire/common_wiregen.h index 95cb040f1..faa8de609 100644 --- a/wire/common_wiregen.h +++ b/wire/common_wiregen.h @@ -41,4 +41,4 @@ bool fromwire_custommsg_out(const tal_t *ctx, const void *p, u8 **msg); #endif /* LIGHTNING_WIRE_COMMON_WIREGEN_H */ -// SHA256STAMP:c97dcd31559f7a0764d6bad2a532cbe79355b4c7c17b32f60ceb810329959865 +// SHA256STAMP:304c3015d0df2a9436adf3c2c96365d438781a5cf55b9ccba73a05dd7bc28a4d diff --git a/wire/onion_printgen.c b/wire/onion_printgen.c index 091545315..921c529c7 100644 --- a/wire/onion_printgen.c +++ b/wire/onion_printgen.c @@ -859,4 +859,4 @@ void printonion_wire_tlv_message(const char *tlv_name, const u8 *msg) { printwire_tlvs(tlv_name, &msg, &plen, print_tlvs_encmsg_tlvs, ARRAY_SIZE(print_tlvs_encmsg_tlvs)); } } -// SHA256STAMP:b6eb425ab1211e5f7a8413489527aea4565904f548e72f635e4ebce72e50cdd4 +// SHA256STAMP:897accc52196e69cffeee8386a5e1af8754fe49baefd58460c788024e4e8dd6f diff --git a/wire/onion_printgen.h b/wire/onion_printgen.h index dc23db5f1..21dbd534b 100644 --- a/wire/onion_printgen.h +++ b/wire/onion_printgen.h @@ -58,4 +58,4 @@ void printwire_mpp_timeout(const char *fieldname, const u8 *cursor); void printwire_onionmsg_path(const char *fieldname, const u8 **cursor, size_t *plen); #endif /* LIGHTNING_WIRE_ONION_PRINTGEN_H */ -// SHA256STAMP:b6eb425ab1211e5f7a8413489527aea4565904f548e72f635e4ebce72e50cdd4 +// SHA256STAMP:897accc52196e69cffeee8386a5e1af8754fe49baefd58460c788024e4e8dd6f diff --git a/wire/onion_wiregen.c b/wire/onion_wiregen.c index f0cd9ce09..fdf848c4f 100644 --- a/wire/onion_wiregen.c +++ b/wire/onion_wiregen.c @@ -1026,4 +1026,4 @@ bool fromwire_mpp_timeout(const void *p) return false; return cursor != NULL; } -// SHA256STAMP:b6eb425ab1211e5f7a8413489527aea4565904f548e72f635e4ebce72e50cdd4 +// SHA256STAMP:897accc52196e69cffeee8386a5e1af8754fe49baefd58460c788024e4e8dd6f diff --git a/wire/onion_wiregen.h b/wire/onion_wiregen.h index 365997cf8..71e78b33c 100644 --- a/wire/onion_wiregen.h +++ b/wire/onion_wiregen.h @@ -317,4 +317,4 @@ bool fromwire_mpp_timeout(const void *p); #endif /* LIGHTNING_WIRE_ONION_WIREGEN_H */ -// SHA256STAMP:b6eb425ab1211e5f7a8413489527aea4565904f548e72f635e4ebce72e50cdd4 +// SHA256STAMP:897accc52196e69cffeee8386a5e1af8754fe49baefd58460c788024e4e8dd6f diff --git a/wire/peer_printgen.c b/wire/peer_printgen.c index 5ab0bf557..0bc457af6 100644 --- a/wire/peer_printgen.c +++ b/wire/peer_printgen.c @@ -2091,4 +2091,4 @@ void printpeer_wire_tlv_message(const char *tlv_name, const u8 *msg) { printwire_tlvs(tlv_name, &msg, &plen, print_tlvs_onion_message_tlvs, ARRAY_SIZE(print_tlvs_onion_message_tlvs)); } } -// SHA256STAMP:3e12752fa68ecad34eca722bae0a5027b6ea71ace1d2b825c6f87613d97863d5 +// SHA256STAMP:9f70670271b0856273026df920106d9c2ef2b60a1fa7c9c687e83a38d7d85a00 diff --git a/wire/peer_printgen.h b/wire/peer_printgen.h index a4066325a..3845d6a6d 100644 --- a/wire/peer_printgen.h +++ b/wire/peer_printgen.h @@ -72,4 +72,4 @@ void printwire_onion_message(const char *fieldname, const u8 *cursor); void printwire_channel_update_checksums(const char *fieldname, const u8 **cursor, size_t *plen); void printwire_channel_update_timestamps(const char *fieldname, const u8 **cursor, size_t *plen); #endif /* LIGHTNING_WIRE_PEER_PRINTGEN_H */ -// SHA256STAMP:3e12752fa68ecad34eca722bae0a5027b6ea71ace1d2b825c6f87613d97863d5 +// SHA256STAMP:9f70670271b0856273026df920106d9c2ef2b60a1fa7c9c687e83a38d7d85a00 diff --git a/wire/peer_wiregen.c b/wire/peer_wiregen.c index dc50a6878..99af45d42 100644 --- a/wire/peer_wiregen.c +++ b/wire/peer_wiregen.c @@ -1717,4 +1717,4 @@ bool fromwire_channel_update_option_channel_htlc_max(const void *p, secp256k1_ec *htlc_maximum_msat = fromwire_amount_msat(&cursor, &plen); return cursor != NULL; } -// SHA256STAMP:3e12752fa68ecad34eca722bae0a5027b6ea71ace1d2b825c6f87613d97863d5 +// SHA256STAMP:9f70670271b0856273026df920106d9c2ef2b60a1fa7c9c687e83a38d7d85a00 diff --git a/wire/peer_wiregen.h b/wire/peer_wiregen.h index 1127f9a4c..6c4625109 100644 --- a/wire/peer_wiregen.h +++ b/wire/peer_wiregen.h @@ -645,4 +645,4 @@ bool fromwire_channel_update_option_channel_htlc_max(const void *p, secp256k1_ec #endif /* LIGHTNING_WIRE_PEER_WIREGEN_H */ -// SHA256STAMP:3e12752fa68ecad34eca722bae0a5027b6ea71ace1d2b825c6f87613d97863d5 +// SHA256STAMP:9f70670271b0856273026df920106d9c2ef2b60a1fa7c9c687e83a38d7d85a00