From ddc9500a64d3e1307ed2476395c38e600e624a2c Mon Sep 17 00:00:00 2001 From: niftynei Date: Thu, 22 Oct 2020 13:18:38 -0500 Subject: [PATCH] features: add 'feature_bit_sub', which will subtract/unset bits Given a two sets of featurebits, unset the featurebits in the first set that are set in the second set --- common/features.c | 29 +++++++++++++++++++++++++++++ common/features.h | 4 ++++ common/test/run-features.c | 33 +++++++++++++++++++++++++++++++++ 3 files changed, 66 insertions(+) diff --git a/common/features.c b/common/features.c index c8daf89ea..6f080153c 100644 --- a/common/features.c +++ b/common/features.c @@ -205,6 +205,35 @@ bool feature_set_or(struct feature_set *a, return true; } +bool feature_set_sub(struct feature_set *a, + const struct feature_set *b TAKES) +{ + /* Check first, before we change anything! */ + for (size_t i = 0; i < ARRAY_SIZE(b->bits); i++) { + for (size_t j = 0; j < tal_bytelen(b->bits[i])*8; j++) { + if (feature_is_set(b->bits[i], j) + && !feature_offered(a->bits[i], j)) { + if (taken(b)) + tal_free(b); + return false; + } + } + } + + for (size_t i = 0; i < ARRAY_SIZE(a->bits); i++) { + for (size_t j = 0; j < tal_bytelen(b->bits[i])*8; j++) { + if (feature_is_set(b->bits[i], j)) + clear_feature_bit(a->bits[i], j); + } + trim_features(&a->bits[i]); + } + + + if (taken(b)) + tal_free(b); + return true; +} + /* BOLT #1: * * All data fields are unsigned big-endian unless otherwise specified. diff --git a/common/features.h b/common/features.h index 1ac93e100..6777d4f1d 100644 --- a/common/features.h +++ b/common/features.h @@ -32,6 +32,10 @@ void towire_feature_set(u8 **pptr, const struct feature_set *fset); bool feature_set_or(struct feature_set *a, const struct feature_set *b TAKES); +/* a - b, or returns false if features not already in a */ +bool feature_set_sub(struct feature_set *a, + const struct feature_set *b TAKES); + /* Returns -1 if we're OK with all these offered features, otherwise first * unsupported (even) feature. */ int features_unsupported(const struct feature_set *our_features, diff --git a/common/test/run-features.c b/common/test/run-features.c index 0bbe1195a..028e8b473 100644 --- a/common/test/run-features.c +++ b/common/test/run-features.c @@ -179,6 +179,38 @@ static void test_feature_set_or(void) } } +static void test_feature_set_sub(void) +{ + struct feature_set *f1, *f2, *control; + for (size_t i = 0; i < ARRAY_SIZE(f1->bits); i++) { + f1 = talz(tmpctx, struct feature_set); + f2 = talz(tmpctx, struct feature_set); + control = talz(tmpctx, struct feature_set); + + f1->bits[i] = tal_arr(f1, u8, 0); + f2->bits[i] = tal_arr(f2, u8, 0); + control->bits[i] = tal_arr(control, u8, 0); + + /* sub with nothing is a nop */ + set_feature_bit(&f1->bits[i], 0); + set_feature_bit(&control->bits[i], 0); + assert(feature_set_eq(f1, control)); + assert(feature_set_sub(f1, f2)); + + /* can't sub feature bit that's not set */ + set_feature_bit(&f2->bits[i], 2); + assert(!feature_set_sub(f1, f2)); + assert(feature_set_eq(f1, control)); + assert(!feature_set_sub(f2, f1)); + + /* sub does the right thing */ + set_feature_bit(&f1->bits[i], 2); + assert(feature_set_sub(f1, f2)); + assert(feature_set_eq(f1, control)); + assert(!feature_set_sub(f1, f2)); + } +} + static void test_feature_trim(void) { struct feature_set *f; @@ -299,6 +331,7 @@ int main(void) test_featurebits_or(); test_feature_set_or(); test_feature_trim(); + test_feature_set_sub(); wally_cleanup(0); tal_free(tmpctx);