Browse Source

common: make BOLT11 use the normal feature array.

This was decided at a recent spec meeting: in particular, mpp and
var_onion_optin options will be used here.

We enhanced "features_supported" into "features_unsupported" so it
can return the first un-handlable bit number.

Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
travis-debug
Rusty Russell 5 years ago
parent
commit
09cdbb70eb
  1. 7
      common/bolt11.c
  2. 12
      common/features.c
  3. 5
      common/features.h
  4. 10
      common/test/run-features.c
  5. 2
      connectd/peer_exchange_initmsg.c

7
common/bolt11.c

@ -458,6 +458,7 @@ static char *decode_9(struct bolt11 *b11,
size_t data_length) size_t data_length)
{ {
size_t flen = (data_length * 5 + 7) / 8; size_t flen = (data_length * 5 + 7) / 8;
int badf;
b11->features = tal_arr(b11, u8, flen); b11->features = tal_arr(b11, u8, flen);
pull_bits_certain(hu5, data, data_len, b11->features, 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, * 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 _even_, and the next most significant bit is numbered 1,
* which is _odd_. */ * which is _odd_. */
for (size_t i = 0; i < data_length * 5; i += 2) badf = features_unsupported(b11->features);
if (feature_is_set(b11->features, i)) if (badf != -1)
return tal_fmt(b11, "9: unknown feature bit %zu", i); return tal_fmt(b11, "9: unknown feature bit %i", badf);
return NULL; return NULL;
} }

12
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 * @bitmap: the features bitmap the peer is asking for
* @supported: array of features we support * @supported: array of features we support
* @num_supported: how many elements in supported * @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, const u32 *supported,
size_t num_supported) size_t num_supported)
{ {
@ -126,18 +128,18 @@ static bool all_supported_features(const u8 *bitmap,
if (feature_supported(bitnum, supported, num_supported)) if (feature_supported(bitnum, supported, num_supported))
continue; 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 /* BIT 2 would logically be "compulsory initial_routing_sync", but
* that does not exist, so we special case it. */ * that does not exist, so we special case it. */
if (feature_is_set(features, if (feature_is_set(features,
COMPULSORY_FEATURE(OPT_INITIAL_ROUTING_SYNC))) COMPULSORY_FEATURE(OPT_INITIAL_ROUTING_SYNC)))
return false; return COMPULSORY_FEATURE(OPT_INITIAL_ROUTING_SYNC);
return all_supported_features(features, return all_supported_features(features,
our_features, our_features,

5
common/features.h

@ -4,8 +4,9 @@
#include <ccan/short_types/short_types.h> #include <ccan/short_types/short_types.h>
#include <ccan/tal/tal.h> #include <ccan/tal/tal.h>
/* Returns true if we're OK with all these offered features. */ /* Returns -1 if we're OK with all these offered features, otherwise first
bool features_supported(const u8 *features); * unsupported (even) feature. */
int features_unsupported(const u8 *features);
/* For sending our features: tal_count() returns length. */ /* For sending our features: tal_count() returns length. */
u8 *get_offered_features(const tal_t *ctx); u8 *get_offered_features(const tal_t *ctx);

10
common/test/run-features.c

@ -84,17 +84,17 @@ int main(void)
/* We always support no features. */ /* We always support no features. */
memset(bits, 0, tal_count(bits)); memset(bits, 0, tal_count(bits));
assert(features_supported(bits)); assert(features_unsupported(bits) == -1);
/* We must support our own features. */ /* We must support our own features. */
lf = get_offered_features(tmpctx); lf = get_offered_features(tmpctx);
assert(features_supported(lf)); assert(features_unsupported(lf) == -1);
/* We can add random odd features, no problem. */ /* We can add random odd features, no problem. */
for (size_t i = 1; i < 16; i += 2) { for (size_t i = 1; i < 16; i += 2) {
bits = tal_dup_arr(tmpctx, u8, lf, tal_count(lf), 0); bits = tal_dup_arr(tmpctx, u8, lf, tal_count(lf), 0);
set_feature_bit(&bits, i); set_feature_bit(&bits, i);
assert(features_supported(bits)); assert(features_unsupported(bits) == -1);
} }
/* We can't add random even features. */ /* We can't add random even features. */
@ -104,9 +104,9 @@ int main(void)
/* Special case for missing compulsory feature */ /* Special case for missing compulsory feature */
if (i == 2) { if (i == 2) {
assert(!features_supported(bits)); assert(features_unsupported(bits) == i);
} else { } else {
assert(features_supported(bits) assert((features_unsupported(bits) == -1)
== feature_supported(i, our_features, == feature_supported(i, our_features,
ARRAY_SIZE(our_features))); ARRAY_SIZE(our_features)));
} }

2
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: * - upon receiving unknown _even_ feature bits that are non-zero:
* - MUST fail the connection. * - MUST fail the connection.
*/ */
if (!features_supported(features)) { if (features_unsupported(features) != -1) {
const u8 *our_features = get_offered_features(msg); const u8 *our_features = get_offered_features(msg);
msg = towire_errorfmt(NULL, NULL, "Unsupported features %s:" msg = towire_errorfmt(NULL, NULL, "Unsupported features %s:"
" we only offer features %s", " we only offer features %s",

Loading…
Cancel
Save