From 9b976da3bc9ac971f4a519cc6b6e46396e6e0e49 Mon Sep 17 00:00:00 2001 From: Christian Decker Date: Thu, 30 Jan 2020 15:40:09 +0100 Subject: [PATCH] features: Add featurebits_or helper to combine two featurebitstrings We will be doing this when collecting featurebits from the plugins, so make this a reusable function. --- common/features.c | 22 ++++++++++++++++++++++ common/features.h | 3 +++ common/test/run-features.c | 23 +++++++++++++++++++++++ connectd/peer_exchange_initmsg.c | 5 +---- 4 files changed, 49 insertions(+), 4 deletions(-) diff --git a/common/features.c b/common/features.c index 4aed4d272..884875122 100644 --- a/common/features.c +++ b/common/features.c @@ -253,3 +253,25 @@ const char **list_supported_features(const tal_t *ctx) return list; } + +u8 *featurebits_or(const tal_t *ctx, const u8 *f1 TAKES, const u8 *f2 TAKES) +{ + size_t l1 = tal_bytelen(f1), l2 = tal_bytelen(f2); + size_t lm = l1 > l2 ? l1 : l2; + u8 *result = tal_arrz(ctx, u8, lm); + + for (size_t i = 0; i < l1; i++) + result[lm - l1 + i] = f1[i]; + + for (size_t i = 0; i < l2; i++) + result[lm - l2 + i] |= f2[i]; + + /* Cleanup the featurebits if we were told to do so. */ + if (taken(f1)) + tal_free(f1); + + if (taken(f2)) + tal_free(f2); + + return result; +} diff --git a/common/features.h b/common/features.h index a145145ce..1ca900602 100644 --- a/common/features.h +++ b/common/features.h @@ -27,6 +27,9 @@ const char **list_supported_features(const tal_t *ctx); bool feature_is_set(const u8 *features, size_t bit); void set_feature_bit(u8 **ptr, u32 bit); +/* Given two featurebit vectors, combine them by applying a logical OR. */ +u8 *featurebits_or(const tal_t *ctx, const u8 *f1 TAKES, const u8 *f2 TAKES); + /* BOLT #9: * * Flags are numbered from the least-significant bit, at bit 0 (i.e. 0x1, diff --git a/common/test/run-features.c b/common/test/run-features.c index bb1a1644c..4286475f5 100644 --- a/common/test/run-features.c +++ b/common/test/run-features.c @@ -31,6 +31,26 @@ const void *fromwire_fail(const u8 **cursor UNNEEDED, size_t *max UNNEEDED) { fprintf(stderr, "fromwire_fail called!\n"); abort(); } /* AUTOGENERATED MOCKS END */ + +static void test_featurebits_or(void) +{ + u8 *f1 = tal_arr(tmpctx, u8, 0); + u8 *f2 = tal_arr(tmpctx, u8, 0); + u8 *control = tal_arr(tmpctx, u8, 0); + for (size_t i = 0; i < 100; i += 3) { + set_feature_bit(&f1, i); + set_feature_bit(&control, i); + } + + for (size_t i = 0; i < 10; i += 2) { + set_feature_bit(&f2, i); + set_feature_bit(&control, i); + } + u8 *result = featurebits_or(tmpctx, take(f1), f2); + assert( + memeq(result, tal_bytelen(result), control, tal_bytelen(control))); +} + int main(void) { u8 *bits, *lf; @@ -112,7 +132,10 @@ int main(void) } } + test_featurebits_or(); + wally_cleanup(0); tal_free(tmpctx); + take_cleanup(); return 0; } diff --git a/connectd/peer_exchange_initmsg.c b/connectd/peer_exchange_initmsg.c index 865d02199..20c924424 100644 --- a/connectd/peer_exchange_initmsg.c +++ b/connectd/peer_exchange_initmsg.c @@ -87,10 +87,7 @@ static struct io_plan *peer_init_received(struct io_conn *conn, /* The globalfeatures field is now unused, but there was a * window where it was: combine the two. */ - for (size_t i = 0; i < tal_bytelen(globalfeatures) * 8; i++) { - if (feature_is_set(globalfeatures, i)) - set_feature_bit(&features, i); - } + features = featurebits_or(tmpctx, take(features), globalfeatures); /* BOLT #1: *