diff --git a/common/bolt11.c b/common/bolt11.c index 626779c61..f21279c50 100644 --- a/common/bolt11.c +++ b/common/bolt11.c @@ -458,6 +458,7 @@ static char *decode_9(struct bolt11 *b11, size_t data_length) { size_t flen = (data_length * 5 + 7) / 8; + int badf; b11->features = tal_arr(b11, u8, flen); pull_bits_certain(hu5, data, data_len, b11->features, @@ -478,9 +479,9 @@ static char *decode_9(struct bolt11 *b11, * The field is big-endian. The least-significant bit is numbered 0, * which is _even_, and the next most significant bit is numbered 1, * which is _odd_. */ - for (size_t i = 0; i < data_length * 5; i += 2) - if (feature_is_set(b11->features, i)) - return tal_fmt(b11, "9: unknown feature bit %zu", i); + badf = features_unsupported(b11->features); + if (badf != -1) + return tal_fmt(b11, "9: unknown feature bit %i", badf); return NULL; } diff --git a/common/features.c b/common/features.c index 8d41a88b0..29f42ae45 100644 --- a/common/features.c +++ b/common/features.c @@ -111,8 +111,10 @@ bool feature_negotiated(const u8 *lfeatures, size_t f) * @bitmap: the features bitmap the peer is asking for * @supported: array of features we support * @num_supported: how many elements in supported + * + * Returns -1 on success, or first unsupported feature. */ -static bool all_supported_features(const u8 *bitmap, +static int all_supported_features(const u8 *bitmap, const u32 *supported, size_t num_supported) { @@ -126,18 +128,18 @@ static bool all_supported_features(const u8 *bitmap, if (feature_supported(bitnum, supported, num_supported)) continue; - return false; + return bitnum; } - return true; + return -1; } -bool features_supported(const u8 *features) +int features_unsupported(const u8 *features) { /* BIT 2 would logically be "compulsory initial_routing_sync", but * that does not exist, so we special case it. */ if (feature_is_set(features, COMPULSORY_FEATURE(OPT_INITIAL_ROUTING_SYNC))) - return false; + return COMPULSORY_FEATURE(OPT_INITIAL_ROUTING_SYNC); return all_supported_features(features, our_features, diff --git a/common/features.h b/common/features.h index 8c7a1bb5f..bcb8ccf4c 100644 --- a/common/features.h +++ b/common/features.h @@ -4,8 +4,9 @@ #include #include -/* Returns true if we're OK with all these offered features. */ -bool features_supported(const u8 *features); +/* Returns -1 if we're OK with all these offered features, otherwise first + * unsupported (even) feature. */ +int features_unsupported(const u8 *features); /* For sending our features: tal_count() returns length. */ u8 *get_offered_features(const tal_t *ctx); diff --git a/common/test/run-features.c b/common/test/run-features.c index 81ced7d78..fccbef750 100644 --- a/common/test/run-features.c +++ b/common/test/run-features.c @@ -84,17 +84,17 @@ int main(void) /* We always support no features. */ memset(bits, 0, tal_count(bits)); - assert(features_supported(bits)); + assert(features_unsupported(bits) == -1); /* We must support our own features. */ lf = get_offered_features(tmpctx); - assert(features_supported(lf)); + assert(features_unsupported(lf) == -1); /* We can add random odd features, no problem. */ for (size_t i = 1; i < 16; i += 2) { bits = tal_dup_arr(tmpctx, u8, lf, tal_count(lf), 0); set_feature_bit(&bits, i); - assert(features_supported(bits)); + assert(features_unsupported(bits) == -1); } /* We can't add random even features. */ @@ -104,9 +104,9 @@ int main(void) /* Special case for missing compulsory feature */ if (i == 2) { - assert(!features_supported(bits)); + assert(features_unsupported(bits) == i); } else { - assert(features_supported(bits) + assert((features_unsupported(bits) == -1) == feature_supported(i, our_features, ARRAY_SIZE(our_features))); } diff --git a/connectd/peer_exchange_initmsg.c b/connectd/peer_exchange_initmsg.c index dfbd361f1..014c6b064 100644 --- a/connectd/peer_exchange_initmsg.c +++ b/connectd/peer_exchange_initmsg.c @@ -73,7 +73,7 @@ static struct io_plan *peer_init_received(struct io_conn *conn, * - upon receiving unknown _even_ feature bits that are non-zero: * - MUST fail the connection. */ - if (!features_supported(features)) { + if (features_unsupported(features) != -1) { const u8 *our_features = get_offered_features(msg); msg = towire_errorfmt(NULL, NULL, "Unsupported features %s:" " we only offer features %s",