From 9a0d2040d34d20722accaa5daf20e5c907922eb9 Mon Sep 17 00:00:00 2001 From: Rusty Russell Date: Wed, 9 Nov 2022 13:02:00 +1030 Subject: [PATCH] common/features: add explicit bolt12 feature sets. The spec only specifies the mpp bit for invoices, but in general they are separate spaces. Signed-off-by: Rusty Russell --- common/bolt12.c | 7 +++++-- common/features.c | 3 ++- common/features.h | 5 ++++- lightningd/options.c | 4 ++-- tests/test_connection.py | 2 +- 5 files changed, 14 insertions(+), 7 deletions(-) diff --git a/common/bolt12.c b/common/bolt12.c index a43fcee83bb6..192ecdaec3bf 100644 --- a/common/bolt12.c +++ b/common/bolt12.c @@ -53,6 +53,7 @@ static char *check_features_and_chain(const tal_t *ctx, const struct feature_set *our_features, const struct chainparams *must_be_chain, const u8 *features, + enum feature_place fplace, const struct bitcoin_blkid *chains, size_t num_chains) { @@ -62,8 +63,7 @@ static char *check_features_and_chain(const tal_t *ctx, } if (our_features) { - int badf = features_unsupported(our_features, features, - BOLT11_FEATURE); + int badf = features_unsupported(our_features, features, fplace); if (badf != -1) return tal_fmt(ctx, "unknown feature bit %i", badf); } @@ -182,6 +182,7 @@ struct tlv_offer *offer_decode(const tal_t *ctx, *fail = check_features_and_chain(ctx, our_features, must_be_chain, offer->features, + BOLT12_OFFER_FEATURE, offer->chains, tal_count(offer->chains)); if (*fail) @@ -236,6 +237,7 @@ struct tlv_invoice_request *invrequest_decode(const tal_t *ctx, *fail = check_features_and_chain(ctx, our_features, must_be_chain, invrequest->features, + BOLT12_INVREQ_FEATURE, invrequest->chain, 1); if (*fail) return tal_free(invrequest); @@ -276,6 +278,7 @@ struct tlv_invoice *invoice_decode_nosig(const tal_t *ctx, *fail = check_features_and_chain(ctx, our_features, must_be_chain, invoice->features, + BOLT12_INVOICE_FEATURE, invoice->chain, 1); if (*fail) return tal_free(invoice); diff --git a/common/features.c b/common/features.c index 1295cf3dcaa3..2a090f1e80f9 100644 --- a/common/features.c +++ b/common/features.c @@ -59,7 +59,8 @@ static const struct feature_style feature_styles[] = { { OPT_BASIC_MPP, .copy_style = { [INIT_FEATURE] = FEATURE_REPRESENT, [NODE_ANNOUNCE_FEATURE] = FEATURE_REPRESENT, - [BOLT11_FEATURE] = FEATURE_REPRESENT } }, + [BOLT11_FEATURE] = FEATURE_REPRESENT, + [BOLT12_INVOICE_FEATURE] = FEATURE_REPRESENT } }, /* BOLT #9: * | 18/19 | `option_support_large_channel` |... IN ... */ diff --git a/common/features.h b/common/features.h index 02c58d6f2bad..a862bafe1c53 100644 --- a/common/features.h +++ b/common/features.h @@ -10,8 +10,11 @@ enum feature_place { NODE_ANNOUNCE_FEATURE, CHANNEL_FEATURE, BOLT11_FEATURE, + BOLT12_OFFER_FEATURE, + BOLT12_INVREQ_FEATURE, + BOLT12_INVOICE_FEATURE, }; -#define NUM_FEATURE_PLACE (BOLT11_FEATURE+1) +#define NUM_FEATURE_PLACE (BOLT12_INVOICE_FEATURE+1) extern const char *feature_place_names[NUM_FEATURE_PLACE]; diff --git a/lightningd/options.c b/lightningd/options.c index 07504bda942a..501fef5bed3b 100644 --- a/lightningd/options.c +++ b/lightningd/options.c @@ -635,8 +635,8 @@ static char *opt_force_featureset(const char *optarg, char **parts = tal_strsplit(tmpctx, optarg, "/", STR_EMPTY_OK); if (tal_count(parts) != NUM_FEATURE_PLACE + 1) { if (!strstarts(optarg, "-") && !strstarts(optarg, "+")) - return "Expected 5 feature sets (init/globalinit/" - " node_announce/channel/bolt11) each terminated by /" + return "Expected 8 feature sets (init/globalinit/" + " node_announce/channel/bolt11/b12offer/b12invreq/b12inv) each terminated by /" " OR +/-"; char *endp; diff --git a/tests/test_connection.py b/tests/test_connection.py index a0860386eaaa..3521c9180f40 100644 --- a/tests/test_connection.py +++ b/tests/test_connection.py @@ -3510,7 +3510,7 @@ def test_nonstatic_channel(node_factory, bitcoind): opts=[{}, # needs at least 15 to connect # (and 9 is a dependent) - {'dev-force-features': '9,15/////'}]) + {'dev-force-features': '9,15////////'}]) chan = only_one(only_one(l1.rpc.listpeers()['peers'])['channels']) assert 'option_static_remotekey' not in chan['features'] assert 'option_anchor_outputs' not in chan['features']