Browse Source

common/features: don't use internal global.

Turns out that unnecessary: all callers can access the feature_set,
so make it much more like a normal primitive.

Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
travis-debug
Rusty Russell 5 years ago
parent
commit
cf43e44378
  1. 13
      channeld/channeld.c
  2. 17
      common/bolt11.c
  3. 7
      common/bolt11.h
  4. 134
      common/features.c
  5. 37
      common/features.h
  6. 37
      common/test/run-bolt11.c
  7. 91
      common/test/run-features.c
  8. 18
      connectd/connectd.c
  9. 5
      connectd/peer_exchange_initmsg.c
  10. 1
      connectd/peer_exchange_initmsg.h
  11. 3
      connectd/test/run-initiator-success.c
  12. 2
      devtools/bolt11-cli.c
  13. 3
      gossipd/gossip_generation.c
  14. 4
      gossipd/gossipd.c
  15. 3
      gossipd/gossipd.h
  16. 3
      gossipd/test/run-extended-info.c
  17. 3
      gossipd/test/run-next_block_range.c
  18. 6
      lightningd/invoice.c
  19. 36
      lightningd/lightningd.c
  20. 2
      lightningd/lightningd.h
  21. 6
      lightningd/opening_control.c
  22. 25
      lightningd/options.c
  23. 2
      lightningd/pay.c
  24. 2
      lightningd/plugin.c
  25. 7
      lightningd/test/run-find_my_abspath.c
  26. 4
      lightningd/test/run-invoice-select-inchan.c
  27. 12
      openingd/openingd.c
  28. 3
      plugins/pay.c

13
channeld/channeld.c

@ -76,6 +76,9 @@ struct peer {
/* Features peer supports. */
u8 *features;
/* Features we support. */
struct feature_set *fset;
/* Tolerable amounts for feerate (only relevant for fundee). */
u32 feerate_min, feerate_max;
@ -415,7 +418,7 @@ static void send_announcement_signatures(struct peer *peer)
static u8 *create_channel_announcement(const tal_t *ctx, struct peer *peer)
{
int first, second;
u8 *cannounce, *features = get_agreed_channelfeatures(tmpctx, peer->features);
u8 *cannounce, *features = get_agreed_channelfeatures(tmpctx, peer->fset, peer->features);
if (peer->channel_direction == 0) {
first = LOCAL;
@ -2325,7 +2328,7 @@ static void peer_reconnect(struct peer *peer,
bool dataloss_protect, check_extra_fields;
const u8 **premature_msgs = tal_arr(peer, const u8 *, 0);
dataloss_protect = feature_negotiated(peer->features,
dataloss_protect = feature_negotiated(peer->fset, peer->features,
OPT_DATA_LOSS_PROTECT);
/* Both these options give us extra fields to check. */
@ -3045,7 +3048,6 @@ static void init_channel(struct peer *peer)
secp256k1_ecdsa_signature *remote_ann_node_sig;
secp256k1_ecdsa_signature *remote_ann_bitcoin_sig;
bool option_static_remotekey;
struct feature_set *feature_set;
#if !DEVELOPER
bool dev_fail_process_onionpacket; /* Ignored */
#endif
@ -3057,7 +3059,7 @@ static void init_channel(struct peer *peer)
msg = wire_sync_read(tmpctx, MASTER_FD);
if (!fromwire_channel_init(peer, msg,
&chainparams,
&feature_set,
&peer->fset,
&funding_txid, &funding_txout,
&funding,
&minimum_depth,
@ -3113,9 +3115,6 @@ static void init_channel(struct peer *peer)
master_badmsg(WIRE_CHANNEL_INIT, msg);
}
/* Now we know what features to advertize. */
features_init(take(feature_set));
/* stdin == requests, 3 == peer, 4 = gossip, 5 = gossip_store, 6 = HSM */
per_peer_state_set_fds(peer->pps, 3, 4, 5);

17
common/bolt11.c

@ -489,6 +489,7 @@ static void shift_bitmap_down(u8 *bitmap, size_t bits)
* See [Feature Bits](#feature-bits).
*/
static char *decode_9(struct bolt11 *b11,
const struct feature_set *fset,
struct hash_u5 *hu5,
u5 **data, size_t *data_len,
size_t data_length)
@ -511,13 +512,12 @@ static char *decode_9(struct bolt11 *b11,
* - if the `9` field contains unknown _even_ bits that are non-zero:
* - MUST fail the payment.
*/
/* BOLT #11:
* 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_. */
badf = features_unsupported(b11->features);
if (badf != -1)
return tal_fmt(b11, "9: unknown feature bit %i", badf);
/* We skip this check for the cli tool, which sets fset to NULL */
if (fset) {
badf = features_unsupported(fset, b11->features, BOLT11_FEATURE);
if (badf != -1)
return tal_fmt(b11, "9: unknown feature bit %i", badf);
}
return NULL;
}
@ -545,6 +545,7 @@ struct bolt11 *new_bolt11(const tal_t *ctx,
/* Decodes and checks signature; returns NULL on error. */
struct bolt11 *bolt11_decode(const tal_t *ctx, const char *str,
const struct feature_set *fset,
const char *description, char **fail)
{
char *hrp, *amountstr, *prefix;
@ -739,7 +740,7 @@ struct bolt11 *bolt11_decode(const tal_t *ctx, const char *str,
data_length);
break;
case '9':
problem = decode_9(b11, &hu5, &data, &data_len,
problem = decode_9(b11, fset, &hu5, &data, &data_len,
data_length);
break;
case 's':

7
common/bolt11.h

@ -14,6 +14,8 @@
/* We only have 10 bits for the field length, meaning < 640 bytes */
#define BOLT11_FIELD_BYTE_LIMIT ((1 << 10) * 5 / 8)
struct feature_set;
struct bolt11_field {
struct list_node list;
@ -74,8 +76,11 @@ struct bolt11 {
};
/* Decodes and checks signature; returns NULL on error; description is
* (optional) out-of-band description of payment, for `h` field. */
* (optional) out-of-band description of payment, for `h` field.
* fset is NULL to accept any features (usually not desirable!).
*/
struct bolt11 *bolt11_decode(const tal_t *ctx, const char *str,
const struct feature_set *fset,
const char *description, char **fail);
/* Initialize an empty bolt11 struct with optional amount */

134
common/features.c

@ -5,10 +5,6 @@
#include <common/utils.h>
#include <wire/peer_wire.h>
/* We keep a map of our features for each context, with the assumption that
* the init features is a superset of the others. */
static struct feature_set *our_features;
enum feature_copy_style {
/* Feature is not exposed (importantly, being 0, this is the default!). */
FEATURE_DONT_REPRESENT,
@ -67,84 +63,53 @@ static enum feature_copy_style feature_copy_style(u32 f, enum feature_place p)
abort();
}
static u8 *mkfeatures(const tal_t *ctx, enum feature_place place)
struct feature_set *feature_set_for_feature(const tal_t *ctx, int feature)
{
u8 *f = tal_arr(ctx, u8, 0);
const u8 *base = our_features->bits[INIT_FEATURE];
assert(place != INIT_FEATURE);
for (size_t i = 0; i < tal_bytelen(base)*8; i++) {
if (!feature_is_set(base, i))
continue;
struct feature_set *fs = tal(ctx, struct feature_set);
switch (feature_copy_style(i, place)) {
for (size_t i = 0; i < ARRAY_SIZE(fs->bits); i++) {
fs->bits[i] = tal_arr(fs, u8, 0);
switch (feature_copy_style(feature, i)) {
case FEATURE_DONT_REPRESENT:
continue;
case FEATURE_REPRESENT:
set_feature_bit(&f, i);
set_feature_bit(&fs->bits[i], feature);
continue;
case FEATURE_REPRESENT_AS_OPTIONAL:
set_feature_bit(&f, OPTIONAL_FEATURE(i));
set_feature_bit(&fs->bits[i], OPTIONAL_FEATURE(feature));
continue;
}
abort();
}
return f;
}
struct feature_set *features_core_init(const u8 *feature_bits)
{
assert(!our_features);
our_features = notleak(tal(NULL, struct feature_set));
our_features->bits[INIT_FEATURE]
= tal_dup_talarr(our_features, u8, feature_bits);
/* Make other masks too */
for (enum feature_place f = INIT_FEATURE+1; f < NUM_FEATURE_PLACE; f++)
our_features->bits[f] = mkfeatures(our_features, f);
return our_features;
}
void features_init(struct feature_set *fset TAKES)
{
assert(!our_features);
if (taken(fset))
our_features = notleak(tal_steal(NULL, fset));
else {
our_features = notleak(tal(NULL, struct feature_set));
for (size_t i = 0; i < ARRAY_SIZE(fset->bits); i++)
our_features->bits[i] = tal_dup_talarr(our_features, u8,
fset->bits[i]);
}
}
void features_cleanup(void)
{
our_features = tal_free(our_features);
return fs;
}
bool features_additional(const struct feature_set *newfset)
bool feature_set_or(struct feature_set *a,
const struct feature_set *b TAKES)
{
/* Check first, before we change anything! */
for (size_t i = 0; i < ARRAY_SIZE(newfset->bits); i++) {
for (size_t i = 0; i < ARRAY_SIZE(b->bits); i++) {
/* FIXME: We could allow a plugin to upgrade an optional feature
* to a compulsory one? */
for (size_t b = 0; b < tal_bytelen(newfset->bits[i])*8; b++) {
if (feature_is_set(newfset->bits[i], b)
&& feature_is_set(our_features->bits[i], b))
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(newfset->bits); i++) {
for (size_t b = 0; b < tal_bytelen(newfset->bits[i])*8; b++) {
if (feature_is_set(newfset->bits[i], b))
set_feature_bit(&our_features->bits[i], b);
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))
set_feature_bit(&a->bits[i], j);
}
}
if (taken(b))
tal_free(b);
return true;
}
@ -172,21 +137,6 @@ static bool test_bit(const u8 *features, size_t byte, unsigned int bit)
return features[tal_count(features) - 1 - byte] & (1 << (bit % 8));
}
u8 *get_offered_nodefeatures(const tal_t *ctx)
{
return tal_dup_talarr(ctx, u8, our_features->bits[NODE_ANNOUNCE_FEATURE]);
}
u8 *get_offered_initfeatures(const tal_t *ctx)
{
return tal_dup_talarr(ctx, u8, our_features->bits[INIT_FEATURE]);
}
u8 *get_offered_globalinitfeatures(const tal_t *ctx)
{
return tal_dup_talarr(ctx, u8, our_features->bits[GLOBAL_INIT_FEATURE]);
}
static void clear_feature_bit(u8 *features, u32 bit)
{
size_t bytenum = bit / 8, bitnum = bit % 8, len = tal_count(features);
@ -203,9 +153,11 @@ static void clear_feature_bit(u8 *features, u32 bit)
* - MUST set `len` to the minimum length required to hold the `features` bits
* it sets.
*/
u8 *get_agreed_channelfeatures(const tal_t *ctx, const u8 *theirfeatures)
u8 *get_agreed_channelfeatures(const tal_t *ctx,
const struct feature_set *ours,
const u8 *theirfeatures)
{
u8 *f = tal_dup_talarr(ctx, u8, our_features->bits[CHANNEL_FEATURE]);
u8 *f = tal_dup_talarr(ctx, u8, ours->bits[CHANNEL_FEATURE]);
size_t max_len = 0;
/* Clear any features which they didn't offer too */
@ -225,11 +177,6 @@ u8 *get_agreed_channelfeatures(const tal_t *ctx, const u8 *theirfeatures)
return f;
}
u8 *get_offered_bolt11features(const tal_t *ctx)
{
return tal_dup_talarr(ctx, u8, our_features->bits[BOLT11_FEATURE]);
}
bool feature_is_set(const u8 *features, size_t bit)
{
size_t bytenum = bit / 8;
@ -246,10 +193,11 @@ bool feature_offered(const u8 *features, size_t f)
|| feature_is_set(features, OPTIONAL_FEATURE(f));
}
bool feature_negotiated(const u8 *lfeatures, size_t f)
bool feature_negotiated(const struct feature_set *ours,
const u8 *lfeatures, size_t f)
{
return feature_offered(lfeatures, f)
&& feature_offered(our_features->bits[INIT_FEATURE], f);
&& feature_offered(ours->bits[INIT_FEATURE], f);
}
/**
@ -263,7 +211,9 @@ bool feature_negotiated(const u8 *lfeatures, size_t f)
*
* Returns -1 on success, or first unsupported feature.
*/
static int all_supported_features(const u8 *bitmap)
static int all_supported_features(const struct feature_set *ours,
const u8 *bitmap,
enum feature_place p)
{
size_t len = tal_count(bitmap) * 8;
@ -272,7 +222,7 @@ static int all_supported_features(const u8 *bitmap)
if (!test_bit(bitmap, bitnum/8, bitnum%8))
continue;
if (feature_offered(our_features->bits[INIT_FEATURE], bitnum))
if (feature_offered(ours->bits[p], bitnum))
continue;
return bitnum;
@ -280,15 +230,16 @@ static int all_supported_features(const u8 *bitmap)
return -1;
}
int features_unsupported(const u8 *features)
int features_unsupported(const struct feature_set *ours, const u8 *theirs,
enum feature_place p)
{
/* BIT 2 would logically be "compulsory initial_routing_sync", but
* that does not exist, so we special case it. */
if (feature_is_set(features,
if (feature_is_set(theirs,
COMPULSORY_FEATURE(OPT_INITIAL_ROUTING_SYNC)))
return COMPULSORY_FEATURE(OPT_INITIAL_ROUTING_SYNC);
return all_supported_features(features);
return all_supported_features(ours, theirs, p);
}
static const char *feature_name(const tal_t *ctx, size_t f)
@ -313,12 +264,13 @@ static const char *feature_name(const tal_t *ctx, size_t f)
fnames[f / 2], (f & 1) ? "odd" : "even");
}
const char **list_supported_features(const tal_t *ctx)
const char **list_supported_features(const tal_t *ctx,
const struct feature_set *ours)
{
const char **list = tal_arr(ctx, const char *, 0);
for (size_t i = 0; i < tal_bytelen(our_features->bits[INIT_FEATURE]) * 8; i++) {
if (test_bit(our_features->bits[INIT_FEATURE], i / 8, i % 8))
for (size_t i = 0; i < tal_bytelen(ours->bits[INIT_FEATURE]) * 8; i++) {
if (test_bit(ours->bits[INIT_FEATURE], i / 8, i % 8))
tal_arr_expand(&list, feature_name(list, i));
}

37
common/features.h

@ -18,43 +18,38 @@ struct feature_set {
u8 *bits[NUM_FEATURE_PLACE];
};
/* Initialize core features (for lightningd). */
struct feature_set *features_core_init(const u8 *features TAKES);
/* Initialize subdaemon features. */
void features_init(struct feature_set *fset TAKES);
/* Free feature allocations */
void features_cleanup(void);
/* Create feature set for a known feature. */
struct feature_set *feature_set_for_feature(const tal_t *ctx, int feature);
/* Marshalling a feature set */
struct feature_set *fromwire_feature_set(const tal_t *ctx,
const u8 **ptr, size_t *max);
void towire_feature_set(u8 **pptr, const struct feature_set *fset);
/* Add features supplied by a plugin: returns false if we already have them */
bool features_additional(const struct feature_set *feature_set);
/* a |= b, or returns false if features already in a */
bool feature_set_or(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 u8 *features);
/* For sending our features: tal_count() returns length. */
u8 *get_offered_initfeatures(const tal_t *ctx);
u8 *get_offered_globalinitfeatures(const tal_t *ctx);
u8 *get_offered_nodefeatures(const tal_t *ctx);
u8 *get_offered_bolt11features(const tal_t *ctx);
int features_unsupported(const struct feature_set *ours, const u8 *theirs,
enum feature_place p);
/* For the features in channel_announcement */
u8 *get_agreed_channelfeatures(const tal_t *ctx, const u8 *theirfeatures);
u8 *get_agreed_channelfeatures(const tal_t *ctx,
const struct feature_set *ours,
const u8 *theirfeatures);
/* Is this feature bit requested? (Either compulsory or optional) */
bool feature_offered(const u8 *features, size_t f);
/* Was this feature bit offered by them and us? */
bool feature_negotiated(const u8 *lfeatures, size_t f);
bool feature_negotiated(const struct feature_set *ours,
const u8 *features, size_t f);
/* Return a list of what features we advertize. */
const char **list_supported_features(const tal_t *ctx);
/* Return a list of what (init) features we advertize. */
const char **list_supported_features(const tal_t *ctx,
const struct feature_set *ours);
/* Low-level helpers to deal with big-endian bitfields. */
bool feature_is_set(const u8 *features, size_t bit);

37
common/test/run-bolt11.c

@ -64,7 +64,7 @@ static void test_b11(const char *b11str,
char *reproduce;
struct bolt11_field *b11_extra, *expect_extra;
b11 = bolt11_decode(tmpctx, b11str, hashed_desc, &fail);
b11 = bolt11_decode(tmpctx, b11str, NULL, hashed_desc, &fail);
if (!b11)
errx(1, "%s:%u:%s", __FILE__, __LINE__, fail);
@ -145,11 +145,11 @@ int main(void)
const char *badstr;
struct bolt11_field *extra;
char *fail;
struct feature_set *fset;
wally_init(0);
secp256k1_ctx = wally_get_secp_context();
setup_tmpctx();
features_core_init(NULL);
/* BOLT #11:
*
@ -268,7 +268,7 @@ int main(void)
for (size_t i = 0; i <= strlen(badstr); i++) {
if (bolt11_decode(tmpctx, tal_strndup(tmpctx, badstr, i),
NULL, &fail))
NULL, NULL, &fail))
abort();
assert(strstr(fail, "Bad bech32")
|| strstr(fail, "Invoices must start with ln"));
@ -461,9 +461,23 @@ int main(void)
set_feature_bit(&b11->features, 100);
badstr = bolt11_encode(tmpctx, b11, false, test_sign, NULL);
assert(streq(badstr, "lnbc25m1pvjluezpp5qqqsyqcyq5rqwzqfqqqsyqcyq5rqwzqfqqqsyqcyq5rqwzqfqypqdq5vdhkven9v5sxyetpdeessp5zyg3zyg3zyg3zyg3zyg3zyg3zyg3zyg3zyg3zyg3zyg3zyg3zygs9q4psqqqqqqqqqqqqqqqpqsqq40wa3khl49yue3zsgm26jrepqr2eghqlx86rttutve3ugd05em86nsefzh4pfurpd9ek9w2vp95zxqnfe2u7ckudyahsa52q66tgzcp6t2dyk"));
assert(!bolt11_decode(tmpctx, badstr, NULL, &fail));
/* Empty set of allowed bits, ensures this fails! */
fset = tal(tmpctx, struct feature_set);
fset->bits[BOLT11_FEATURE] = tal_arr(fset, u8, 0);
assert(!bolt11_decode(tmpctx, badstr, fset, NULL, &fail));
assert(streq(fail, "9: unknown feature bit 100"));
/* We'd actually allow this if we either (1) don't check, or (2) accept that feature in
* either compulsory or optional forms. */
assert(bolt11_decode(tmpctx, badstr, NULL, NULL, &fail));
set_feature_bit(&fset->bits[BOLT11_FEATURE], 100);
assert(bolt11_decode(tmpctx, badstr, fset, NULL,&fail));
clear_feature_bit(fset->bits[BOLT11_FEATURE], 100);
set_feature_bit(&fset->bits[BOLT11_FEATURE], 101);
assert(bolt11_decode(tmpctx, badstr, fset, NULL, &fail));
/* BOLT-1fbccd30bb503203e4a255de67f9adb504563425 #11:
*
* > ### Please send 0.00967878534 BTC for a list of items within one week, amount in pico-BTC
@ -527,53 +541,52 @@ int main(void)
* > ### Bech32 checksum is invalid.
* > lnbc2500u1pvjluezpp5qqqsyqcyq5rqwzqfqqqsyqcyq5rqwzqfqqqsyqcyq5rqwzqfqypqdpquwpc4curk03c9wlrswe78q4eyqc7d8d0xqzpuyk0sg5g70me25alkluzd2x62aysf2pyy8edtjeevuv4p2d5p76r4zkmneet7uvyakky2zr4cusd45tftc9c5fh0nnqpnl2jfll544esqchsrnt
*/
assert(!bolt11_decode(tmpctx, "lnbc2500u1pvjluezpp5qqqsyqcyq5rqwzqfqqqsyqcyq5rqwzqfqqqsyqcyq5rqwzqfqypqdpquwpc4curk03c9wlrswe78q4eyqc7d8d0xqzpuyk0sg5g70me25alkluzd2x62aysf2pyy8edtjeevuv4p2d5p76r4zkmneet7uvyakky2zr4cusd45tftc9c5fh0nnqpnl2jfll544esqchsrnt", NULL, &fail));
assert(!bolt11_decode(tmpctx, "lnbc2500u1pvjluezpp5qqqsyqcyq5rqwzqfqqqsyqcyq5rqwzqfqqqsyqcyq5rqwzqfqypqdpquwpc4curk03c9wlrswe78q4eyqc7d8d0xqzpuyk0sg5g70me25alkluzd2x62aysf2pyy8edtjeevuv4p2d5p76r4zkmneet7uvyakky2zr4cusd45tftc9c5fh0nnqpnl2jfll544esqchsrnt", NULL, NULL, &fail));
assert(streq(fail, "Bad bech32 string"));
/* BOLT-4e228a7fb4ea78af914d1ce82a63cbce8026279e #11:
* > ### Malformed bech32 string (no 1)
* > pvjluezpp5qqqsyqcyq5rqwzqfqqqsyqcyq5rqwzqfqqqsyqcyq5rqwzqfqypqdpquwpc4curk03c9wlrswe78q4eyqc7d8d0xqzpuyk0sg5g70me25alkluzd2x62aysf2pyy8edtjeevuv4p2d5p76r4zkmneet7uvyakky2zr4cusd45tftc9c5fh0nnqpnl2jfll544esqchsrny
*/
assert(!bolt11_decode(tmpctx, "pvjluezpp5qqqsyqcyq5rqwzqfqqqsyqcyq5rqwzqfqqqsyqcyq5rqwzqfqypqdpquwpc4curk03c9wlrswe78q4eyqc7d8d0xqzpuyk0sg5g70me25alkluzd2x62aysf2pyy8edtjeevuv4p2d5p76r4zkmneet7uvyakky2zr4cusd45tftc9c5fh0nnqpnl2jfll544esqchsrny", NULL, &fail));
assert(!bolt11_decode(tmpctx, "pvjluezpp5qqqsyqcyq5rqwzqfqqqsyqcyq5rqwzqfqqqsyqcyq5rqwzqfqypqdpquwpc4curk03c9wlrswe78q4eyqc7d8d0xqzpuyk0sg5g70me25alkluzd2x62aysf2pyy8edtjeevuv4p2d5p76r4zkmneet7uvyakky2zr4cusd45tftc9c5fh0nnqpnl2jfll544esqchsrny", NULL, NULL, &fail));
assert(streq(fail, "Bad bech32 string"));
/* BOLT-4e228a7fb4ea78af914d1ce82a63cbce8026279e #11:
* > ### Malformed bech32 string (mixed case)
* > LNBC2500u1pvjluezpp5qqqsyqcyq5rqwzqfqqqsyqcyq5rqwzqfqqqsyqcyq5rqwzqfqypqdpquwpc4curk03c9wlrswe78q4eyqc7d8d0xqzpuyk0sg5g70me25alkluzd2x62aysf2pyy8edtjeevuv4p2d5p76r4zkmneet7uvyakky2zr4cusd45tftc9c5fh0nnqpnl2jfll544esqchsrny
*/
assert(!bolt11_decode(tmpctx, "LNBC2500u1pvjluezpp5qqqsyqcyq5rqwzqfqqqsyqcyq5rqwzqfqqqsyqcyq5rqwzqfqypqdpquwpc4curk03c9wlrswe78q4eyqc7d8d0xqzpuyk0sg5g70me25alkluzd2x62aysf2pyy8edtjeevuv4p2d5p76r4zkmneet7uvyakky2zr4cusd45tftc9c5fh0nnqpnl2jfll544esqchsrny", NULL, &fail));
assert(!bolt11_decode(tmpctx, "LNBC2500u1pvjluezpp5qqqsyqcyq5rqwzqfqqqsyqcyq5rqwzqfqqqsyqcyq5rqwzqfqypqdpquwpc4curk03c9wlrswe78q4eyqc7d8d0xqzpuyk0sg5g70me25alkluzd2x62aysf2pyy8edtjeevuv4p2d5p76r4zkmneet7uvyakky2zr4cusd45tftc9c5fh0nnqpnl2jfll544esqchsrny", NULL, NULL, &fail));
assert(streq(fail, "Bad bech32 string"));
/* BOLT-4e228a7fb4ea78af914d1ce82a63cbce8026279e #11:
* > ### Signature is not recoverable.
* > lnbc2500u1pvjluezpp5qqqsyqcyq5rqwzqfqqqsyqcyq5rqwzqfqqqsyqcyq5rqwzqfqypqdq5xysxxatsyp3k7enxv4jsxqzpuaxtrnwngzn3kdzw5hydlzf03qdgm2hdq27cqv3agm2awhz5se903vruatfhq77w3ls4evs3ch9zw97j25emudupq63nyw24cg27h2rspk28uwq
*/
assert(!bolt11_decode(tmpctx, "lnbc2500u1pvjluezpp5qqqsyqcyq5rqwzqfqqqsyqcyq5rqwzqfqqqsyqcyq5rqwzqfqypqdq5xysxxatsyp3k7enxv4jsxqzpuaxtrnwngzn3kdzw5hydlzf03qdgm2hdq27cqv3agm2awhz5se903vruatfhq77w3ls4evs3ch9zw97j25emudupq63nyw24cg27h2rspk28uwq", NULL, &fail));
assert(!bolt11_decode(tmpctx, "lnbc2500u1pvjluezpp5qqqsyqcyq5rqwzqfqqqsyqcyq5rqwzqfqqqsyqcyq5rqwzqfqypqdq5xysxxatsyp3k7enxv4jsxqzpuaxtrnwngzn3kdzw5hydlzf03qdgm2hdq27cqv3agm2awhz5se903vruatfhq77w3ls4evs3ch9zw97j25emudupq63nyw24cg27h2rspk28uwq", NULL, NULL, &fail));
assert(streq(fail, "signature recovery failed"));
/* BOLT-4e228a7fb4ea78af914d1ce82a63cbce8026279e #11:
* > ### String is too short.
* > lnbc1pvjluezpp5qqqsyqcyq5rqwzqfqqqsyqcyq5rqwzqfqqqsyqcyq5rqwzqfqypqdpl2pkx2ctnv5sxxmmwwd5kgetjypeh2ursdae8g6na6hlh
*/
assert(!bolt11_decode(tmpctx, "lnbc1pvjluezpp5qqqsyqcyq5rqwzqfqqqsyqcyq5rqwzqfqqqsyqcyq5rqwzqfqypqdpl2pkx2ctnv5sxxmmwwd5kgetjypeh2ursdae8g6na6hlh", NULL, &fail));
assert(!bolt11_decode(tmpctx, "lnbc1pvjluezpp5qqqsyqcyq5rqwzqfqqqsyqcyq5rqwzqfqqqsyqcyq5rqwzqfqypqdpl2pkx2ctnv5sxxmmwwd5kgetjypeh2ursdae8g6na6hlh", NULL, NULL, &fail));
/* BOLT-4e228a7fb4ea78af914d1ce82a63cbce8026279e #11:
* > ### Invalid multiplier
* > lnbc2500x1pvjluezpp5qqqsyqcyq5rqwzqfqqqsyqcyq5rqwzqfqqqsyqcyq5rqwzqfqypqdq5xysxxatsyp3k7enxv4jsxqzpujr6jxr9gq9pv6g46y7d20jfkegkg4gljz2ea2a3m9lmvvr95tq2s0kvu70u3axgelz3kyvtp2ywwt0y8hkx2869zq5dll9nelr83zzqqpgl2zg
*/
assert(!bolt11_decode(tmpctx, "lnbc2500x1pvjluezpp5qqqsyqcyq5rqwzqfqqqsyqcyq5rqwzqfqqqsyqcyq5rqwzqfqypqdq5xysxxatsyp3k7enxv4jsxqzpujr6jxr9gq9pv6g46y7d20jfkegkg4gljz2ea2a3m9lmvvr95tq2s0kvu70u3axgelz3kyvtp2ywwt0y8hkx2869zq5dll9nelr83zzqqpgl2zg", NULL, &fail));
assert(!bolt11_decode(tmpctx, "lnbc2500x1pvjluezpp5qqqsyqcyq5rqwzqfqqqsyqcyq5rqwzqfqqqsyqcyq5rqwzqfqypqdq5xysxxatsyp3k7enxv4jsxqzpujr6jxr9gq9pv6g46y7d20jfkegkg4gljz2ea2a3m9lmvvr95tq2s0kvu70u3axgelz3kyvtp2ywwt0y8hkx2869zq5dll9nelr83zzqqpgl2zg", NULL, NULL, &fail));
assert(streq(fail, "Invalid amount postfix 'x'"));
/* BOLT- #11:
* > ### Invalid sub-millisatoshi precision.
* > lnbc2500000001p1pvjluezpp5qqqsyqcyq5rqwzqfqqqsyqcyq5rqwzqfqqqsyqcyq5rqwzqfqypqdq5xysxxatsyp3k7enxv4jsxqzpu7hqtk93pkf7sw55rdv4k9z2vj050rxdr6za9ekfs3nlt5lr89jqpdmxsmlj9urqumg0h9wzpqecw7th56tdms40p2ny9q4ddvjsedzcplva53s
*/
assert(!bolt11_decode(tmpctx, "lnbc2500000001p1pvjluezpp5qqqsyqcyq5rqwzqfqqqsyqcyq5rqwzqfqqqsyqcyq5rqwzqfqypqdq5xysxxatsyp3k7enxv4jsxqzpu7hqtk93pkf7sw55rdv4k9z2vj050rxdr6za9ekfs3nlt5lr89jqpdmxsmlj9urqumg0h9wzpqecw7th56tdms40p2ny9q4ddvjsedzcplva53s", NULL, &fail));
assert(!bolt11_decode(tmpctx, "lnbc2500000001p1pvjluezpp5qqqsyqcyq5rqwzqfqqqsyqcyq5rqwzqfqqqsyqcyq5rqwzqfqypqdq5xysxxatsyp3k7enxv4jsxqzpu7hqtk93pkf7sw55rdv4k9z2vj050rxdr6za9ekfs3nlt5lr89jqpdmxsmlj9urqumg0h9wzpqecw7th56tdms40p2ny9q4ddvjsedzcplva53s", NULL, NULL, &fail));
assert(streq(fail, "Invalid sub-millisatoshi amount '2500000001p'"));
/* FIXME: Test the others! */
wally_cleanup(0);
tal_free(tmpctx);
features_cleanup();
return 0;
}

91
common/test/run-features.c

@ -65,32 +65,70 @@ static void test_featurebits_or(void)
memeq(result, tal_bytelen(result), control, tal_bytelen(control)));
}
static void setup_features(void)
static bool feature_set_eq(const struct feature_set *f1,
const struct feature_set *f2)
{
static const u32 default_features[] = {
OPTIONAL_FEATURE(OPT_DATA_LOSS_PROTECT),
OPTIONAL_FEATURE(OPT_UPFRONT_SHUTDOWN_SCRIPT),
OPTIONAL_FEATURE(OPT_GOSSIP_QUERIES),
OPTIONAL_FEATURE(OPT_VAR_ONION),
OPTIONAL_FEATURE(OPT_PAYMENT_SECRET),
OPTIONAL_FEATURE(OPT_BASIC_MPP),
OPTIONAL_FEATURE(OPT_GOSSIP_QUERIES_EX),
OPTIONAL_FEATURE(OPT_STATIC_REMOTEKEY),
};
u8 *f = tal_arr(NULL, u8, 0);
for (size_t i = 0; i < ARRAY_SIZE(default_features); i++)
set_feature_bit(&f, default_features[i]);
features_core_init(take(f));
/* We assume minimal sizing */
for (size_t i = 0; i < ARRAY_SIZE(f1->bits); i++) {
if (!memeq(f1->bits[i], tal_bytelen(f1->bits[i]),
f2->bits[i], tal_bytelen(f2->bits[i])))
return false;
}
return true;
}
static void test_feature_set_or(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);
/* or with nothing is a nop */
set_feature_bit(&f1->bits[i], 0);
set_feature_bit(&control->bits[i], 0);
assert(feature_set_or(f1, f2));
assert(feature_set_eq(f1, control));
/* or compulsory with either compulsory or optional is a fail */
set_feature_bit(&f2->bits[i], 0);
assert(!feature_set_or(f1, f2));
assert(feature_set_eq(f1, control));
assert(!feature_set_or(f2, f1));
clear_feature_bit(f2->bits[i], 0);
set_feature_bit(&f2->bits[i], 1);
assert(!feature_set_or(f1, f2));
assert(feature_set_eq(f1, control));
assert(!feature_set_or(f2, f1));
clear_feature_bit(f2->bits[i], 1);
set_feature_bit(&f2->bits[i], 10);
set_feature_bit(&control->bits[i], 10);
assert(feature_set_or(f1, f2));
assert(feature_set_eq(f1, control));
}
}
int main(void)
{
u8 *bits, *lf;
u8 *bits;
struct feature_set *fset;
setup_locale();
wally_init(0);
secp256k1_ctx = wally_get_secp_context();
setup_tmpctx();
setup_features();
/* Just some bits to set. */
fset = feature_set_for_feature(tmpctx,
OPTIONAL_FEATURE(OPT_DATA_LOSS_PROTECT));
bits = tal_arr(tmpctx, u8, 0);
for (size_t i = 0; i < 100; i += 3)
@ -136,38 +174,37 @@ int main(void)
/* We always support no features. */
memset(bits, 0, tal_count(bits));
assert(features_unsupported(bits) == -1);
assert(features_unsupported(fset, bits, INIT_FEATURE) == -1);
/* We must support our own features. */
lf = get_offered_initfeatures(tmpctx);
assert(features_unsupported(lf) == -1);
assert(features_unsupported(fset, fset->bits[INIT_FEATURE], INIT_FEATURE) == -1);
/* We can add random odd features, no problem. */
for (size_t i = 1; i < 16; i += 2) {
bits = tal_dup_talarr(tmpctx, u8, lf);
bits = tal_dup_talarr(tmpctx, u8, fset->bits[INIT_FEATURE]);
set_feature_bit(&bits, i);
assert(features_unsupported(bits) == -1);
assert(features_unsupported(fset, bits, INIT_FEATURE) == -1);
}
/* We can't add random even features. */
for (size_t i = 0; i < 16; i += 2) {
bits = tal_dup_talarr(tmpctx, u8, lf);
bits = tal_dup_talarr(tmpctx, u8, fset->bits[INIT_FEATURE]);
set_feature_bit(&bits, i);
/* Special case for missing compulsory feature */
if (i == 2) {
assert(features_unsupported(bits) == i);
assert(features_unsupported(fset, bits, INIT_FEATURE) == i);
} else {
assert((features_unsupported(bits) == -1)
== feature_offered(our_features->bits[INIT_FEATURE], i));
assert((features_unsupported(fset, bits, INIT_FEATURE) == -1)
== feature_offered(fset->bits[INIT_FEATURE], i));
}
}
test_featurebits_or();
test_feature_set_or();
wally_cleanup(0);
tal_free(tmpctx);
take_cleanup();
features_cleanup();
return 0;
}

18
connectd/connectd.c

@ -154,6 +154,9 @@ struct daemon {
/* Allow to define the default behavior of tor services calls*/
bool use_v3_autotor;
/* Our features, as lightningd told us */
struct feature_set *fset;
};
/* Peers we're trying to reach: we iterate through addrs until we succeed
@ -300,7 +303,7 @@ static bool get_gossipfds(struct daemon *daemon,
/*~ The way features generally work is that both sides need to offer it;
* we always offer `gossip_queries`, but this check is explicit. */
gossip_queries_feature
= feature_negotiated(features, OPT_GOSSIP_QUERIES);
= feature_negotiated(daemon->fset, features, OPT_GOSSIP_QUERIES);
/*~ `initial_routing_sync` is supported by every node, since it was in
* the initial lightning specification: it means the peer wants the
@ -436,7 +439,7 @@ struct io_plan *peer_connected(struct io_conn *conn,
* - upon receiving unknown _even_ feature bits that are non-zero:
* - MUST fail the connection.
*/
unsup = features_unsupported(features);
unsup = features_unsupported(daemon->fset, features, INIT_FEATURE);
if (unsup != -1) {
msg = towire_errorfmt(NULL, NULL, "Unsupported feature %u",
unsup);
@ -490,7 +493,7 @@ static struct io_plan *handshake_in_success(struct io_conn *conn,
struct node_id id;
node_id_from_pubkey(&id, id_key);
status_peer_debug(&id, "Connect IN");
return peer_exchange_initmsg(conn, daemon, cs, &id, addr);
return peer_exchange_initmsg(conn, daemon, daemon->fset, cs, &id, addr);
}
/*~ When we get a connection in we set up its network address then call
@ -550,7 +553,8 @@ static struct io_plan *handshake_out_success(struct io_conn *conn,
node_id_from_pubkey(&id, key);
connect->connstate = "Exchanging init messages";
status_peer_debug(&id, "Connect OUT");
return peer_exchange_initmsg(conn, connect->daemon, cs, &id, addr);
return peer_exchange_initmsg(conn, connect->daemon,
connect->daemon->fset, cs, &id, addr);
}
struct io_plan *connection_out(struct io_conn *conn, struct connecting *connect)
@ -1201,14 +1205,13 @@ static struct io_plan *connect_init(struct io_conn *conn,
struct wireaddr_internal *proposed_wireaddr;
enum addr_listen_announce *proposed_listen_announce;
struct wireaddr *announcable;
struct feature_set *feature_set;
char *tor_password;
/* Fields which require allocation are allocated off daemon */
if (!fromwire_connectctl_init(
daemon, msg,
&chainparams,
&feature_set,
&daemon->fset,
&daemon->id,
&proposed_wireaddr,
&proposed_listen_announce,
@ -1221,9 +1224,6 @@ static struct io_plan *connect_init(struct io_conn *conn,
master_badmsg(WIRE_CONNECTCTL_INIT, msg);
}
/* Now we know what features to advertize. */
features_init(take(feature_set));
if (!pubkey_from_node_id(&daemon->mykey, &daemon->id))
status_failed(STATUS_FAIL_INTERNAL_ERROR,
"Invalid id for me %s",

5
connectd/peer_exchange_initmsg.c

@ -135,6 +135,7 @@ static struct io_plan *peer_write_postclose(struct io_conn *conn,
struct io_plan *peer_exchange_initmsg(struct io_conn *conn,
struct daemon *daemon,
const struct feature_set *fset,
const struct crypto_state *cs,
const struct node_id *id,
const struct wireaddr_internal *addr)
@ -181,8 +182,8 @@ struct io_plan *peer_exchange_initmsg(struct io_conn *conn,
* Finally, we agreed that bits below 13 could be put in both, but
* from now on they'll all go in initfeatures. */
peer->msg = towire_init(NULL,
get_offered_globalinitfeatures(tmpctx),
get_offered_initfeatures(tmpctx),
fset->bits[GLOBAL_INIT_FEATURE],
fset->bits[INIT_FEATURE],
tlvs);
status_peer_io(LOG_IO_OUT, &peer->id, peer->msg);
peer->msg = cryptomsg_encrypt_msg(peer, &peer->cs, take(peer->msg));

1
connectd/peer_exchange_initmsg.h

@ -12,6 +12,7 @@ struct wireaddr_internal;
/* If successful, calls peer_connected() */
struct io_plan *peer_exchange_initmsg(struct io_conn *conn,
struct daemon *daemon,
const struct feature_set *fset,
const struct crypto_state *cs,
const struct node_id *id,
const struct wireaddr_internal *addr);

3
connectd/test/run-initiator-success.c

@ -40,9 +40,6 @@ u8 *fromwire_tal_arrn(const tal_t *ctx UNNEEDED,
/* Generated stub for fromwire_u16 */
u16 fromwire_u16(const u8 **cursor UNNEEDED, size_t *max UNNEEDED)
{ fprintf(stderr, "fromwire_u16 called!\n"); abort(); }
/* Generated stub for notleak_ */
void *notleak_(const void *ptr UNNEEDED, bool plus_children UNNEEDED)
{ fprintf(stderr, "notleak_ called!\n"); abort(); }
/* Generated stub for towire_u16 */
void towire_u16(u8 **pptr UNNEEDED, u16 v UNNEEDED)
{ fprintf(stderr, "towire_u16 called!\n"); abort(); }

2
devtools/bolt11-cli.c

@ -93,7 +93,7 @@ int main(int argc, char *argv[])
errx(ERROR_USAGE, "Need argument\n%s",
opt_usage(argv[0], NULL));
b11 = bolt11_decode(ctx, argv[2], description, &fail);
b11 = bolt11_decode(ctx, argv[2], NULL, description, &fail);
if (!b11)
errx(ERROR_BAD_DECODE, "%s", fail);

3
gossipd/gossip_generation.c

@ -38,7 +38,8 @@ static u8 *create_node_announcement(const tal_t *ctx, struct daemon *daemon,
towire_wireaddr(&addresses, &daemon->announcable[i]);
announcement =
towire_node_announcement(ctx, sig, get_offered_nodefeatures(tmpctx),
towire_node_announcement(ctx, sig,
daemon->fset->bits[NODE_ANNOUNCE_FEATURE],
timestamp,
&daemon->id, daemon->rgb, daemon->alias,
addresses);

4
gossipd/gossipd.c

@ -831,11 +831,10 @@ static struct io_plan *gossip_init(struct io_conn *conn,
u32 *dev_gossip_time;
bool dev_fast_gossip, dev_fast_gossip_prune;
u32 timestamp;
struct feature_set *feature_set;
if (!fromwire_gossipctl_init(daemon, msg,
&chainparams,
&feature_set,
&daemon->fset,
&daemon->id,
daemon->rgb,
daemon->alias,
@ -846,7 +845,6 @@ static struct io_plan *gossip_init(struct io_conn *conn,
master_badmsg(WIRE_GOSSIPCTL_INIT, msg);
}
features_init(take(feature_set));
daemon->rstate = new_routing_state(daemon,
&daemon->id,
&daemon->peers,

3
gossipd/gossipd.h

@ -57,6 +57,9 @@ struct daemon {
/* What, if any, gossip we're seeker from peers. */
struct seeker *seeker;
/* Features lightningd told us to set. */
struct feature_set *fset;
};
/* This represents each peer we're gossiping with */

3
gossipd/test/run-extended-info.c

@ -78,9 +78,6 @@ void json_object_start(struct json_stream *ks UNNEEDED, const char *fieldname UN
/* Generated stub for master_badmsg */
void master_badmsg(u32 type_expected UNNEEDED, const u8 *msg)
{ fprintf(stderr, "master_badmsg called!\n"); abort(); }
/* Generated stub for notleak_ */
void *notleak_(const void *ptr UNNEEDED, bool plus_children UNNEEDED)
{ fprintf(stderr, "notleak_ called!\n"); abort(); }
/* Generated stub for peer_supplied_good_gossip */
void peer_supplied_good_gossip(struct peer *peer UNNEEDED, size_t amount UNNEEDED)
{ fprintf(stderr, "peer_supplied_good_gossip called!\n"); abort(); }

3
gossipd/test/run-next_block_range.c

@ -38,9 +38,6 @@ struct oneshot *new_reltimer_(struct timers *timers UNNEEDED,
struct timerel expire UNNEEDED,
void (*cb)(void *) UNNEEDED, void *arg UNNEEDED)
{ fprintf(stderr, "new_reltimer_ called!\n"); abort(); }
/* Generated stub for notleak_ */
void *notleak_(const void *ptr UNNEEDED, bool plus_children UNNEEDED)
{ fprintf(stderr, "notleak_ called!\n"); abort(); }
/* Generated stub for query_channel_range */
bool query_channel_range(struct daemon *daemon UNNEEDED,
struct peer *peer UNNEEDED,

6
lightningd/invoice.c

@ -1013,7 +1013,9 @@ static struct command_result *json_invoice(struct command *cmd,
info->b11->description_hash = NULL;
info->b11->payment_secret = tal_dup(info->b11, struct secret,
&payment_secret);
info->b11->features = get_offered_bolt11features(info->b11);
info->b11->features = tal_dup_talarr(info->b11, u8,
cmd->ld->feature_set
->bits[BOLT11_FEATURE]);
#if DEVELOPER
info->b11->routes = unpack_routes(info->b11, buffer, routes);
@ -1319,7 +1321,7 @@ static struct command_result *json_decodepay(struct command *cmd,
NULL))
return command_param_failed();
b11 = bolt11_decode(cmd, str, desc, &fail);
b11 = bolt11_decode(cmd, str, cmd->ld->feature_set, desc, &fail);
if (!b11) {
return command_fail(cmd, LIGHTNINGD, "Invalid bolt11: %s", fail);

36
lightningd/lightningd.c

@ -703,6 +703,39 @@ static void setup_sig_handlers(void)
}
}
/*~ We actually keep more than one set of features, used in different
* contexts. common/features.c knows how each standard feature is
* presented, so we have it generate the set for each one at a time, and
* combine them.
*
* This is inefficient, but the primitives are useful for adding single
* features later, or adding them when supplied by plugins. */
static struct feature_set *default_features(const tal_t *ctx)
{
struct feature_set *ret = NULL;
static const u32 features[] = {
OPTIONAL_FEATURE(OPT_DATA_LOSS_PROTECT),
OPTIONAL_FEATURE(OPT_UPFRONT_SHUTDOWN_SCRIPT),
OPTIONAL_FEATURE(OPT_GOSSIP_QUERIES),
OPTIONAL_FEATURE(OPT_VAR_ONION),
OPTIONAL_FEATURE(OPT_PAYMENT_SECRET),
OPTIONAL_FEATURE(OPT_BASIC_MPP),
OPTIONAL_FEATURE(OPT_GOSSIP_QUERIES_EX),
OPTIONAL_FEATURE(OPT_STATIC_REMOTEKEY),
};
for (size_t i = 0; i < ARRAY_SIZE(features); i++) {
struct feature_set *f
= feature_set_for_feature(NULL, features[i]);
if (!ret)
ret = tal_steal(ctx, f);
else
feature_set_or(ret, take(f));
}
return ret;
}
int main(int argc, char *argv[])
{
struct lightningd *ld;
@ -751,6 +784,9 @@ int main(int argc, char *argv[])
if (!ld->daemon_dir)
errx(1, "Could not find daemons");
/* Set up the feature bits for what we support */
ld->feature_set = default_features(ld);
/*~ Handle early options; this moves us into --lightning-dir.
* Plugins may add new options, which is why we are splitting
* between early args (including --plugin registration) and

2
lightningd/lightningd.h

@ -120,7 +120,7 @@ struct lightningd {
struct node_id id;
/* Feature set we offer. */
const struct feature_set *feature_set;
struct feature_set *feature_set;
/* My name is... my favorite color is... */
u8 *alias; /* At least 32 bytes (zero-filled) */

6
lightningd/opening_control.c

@ -220,7 +220,8 @@ wallet_commit_channel(struct lightningd *ld,
*/
/* i.e. We set it now for the channel permanently. */
option_static_remotekey
= feature_negotiated(uc->peer->features, OPT_STATIC_REMOTEKEY);
= feature_negotiated(ld->feature_set,
uc->peer->features, OPT_STATIC_REMOTEKEY);
channel = new_channel(uc->peer, uc->dbid,
NULL, /* No shachain yet */
@ -1009,7 +1010,8 @@ void peer_start_openingd(struct peer *peer,
feerate_min(peer->ld, NULL),
feerate_max(peer->ld, NULL),
peer->features,
feature_negotiated(peer->features,
feature_negotiated(peer->ld->feature_set,
peer->features,
OPT_STATIC_REMOTEKEY),
send_msg,
IFDEV(peer->ld->dev_force_tmp_channel_id, NULL),

25
lightningd/options.c

@ -692,7 +692,7 @@ static char *test_subdaemons_and_exit(struct lightningd *ld)
static char *list_features_and_exit(struct lightningd *ld)
{
const char **features = list_supported_features(ld);
const char **features = list_supported_features(tmpctx, ld->feature_set);
for (size_t i = 0; i < tal_count(features); i++)
printf("%s\n", features[i]);
exit(0);
@ -1004,34 +1004,11 @@ void setup_color_and_alias(struct lightningd *ld)
}
}
static struct feature_set *setup_default_features(void)
{
static const u32 default_features[] = {
OPTIONAL_FEATURE(OPT_DATA_LOSS_PROTECT),
OPTIONAL_FEATURE(OPT_UPFRONT_SHUTDOWN_SCRIPT),
OPTIONAL_FEATURE(OPT_GOSSIP_QUERIES),
OPTIONAL_FEATURE(OPT_VAR_ONION),
OPTIONAL_FEATURE(OPT_PAYMENT_SECRET),
OPTIONAL_FEATURE(OPT_BASIC_MPP),
OPTIONAL_FEATURE(OPT_GOSSIP_QUERIES_EX),
OPTIONAL_FEATURE(OPT_STATIC_REMOTEKEY),
};
u8 *f = tal_arr(NULL, u8, 0);
for (size_t i = 0; i < ARRAY_SIZE(default_features); i++)
set_feature_bit(&f, default_features[i]);
return features_core_init(take(f));
}
void handle_early_opts(struct lightningd *ld, int argc, char *argv[])
{
/* Make ccan/opt use tal for allocations */
setup_option_allocators();
/* Make sure options are populated. */
ld->feature_set = setup_default_features();
/*~ List features immediately, before doing anything interesting */
opt_register_early_noarg("--list-features-only",
list_features_and_exit,

2
lightningd/pay.c

@ -1406,7 +1406,7 @@ static struct command_result *json_listsendpays(struct command *cmd,
struct bolt11 *b11;
char *fail;
b11 = bolt11_decode(cmd, b11str, NULL, &fail);
b11 = bolt11_decode(cmd, b11str, cmd->ld->feature_set, NULL, &fail);
if (!b11) {
return command_fail(cmd, JSONRPC2_INVALID_PARAMS,
"Invalid bolt11: %s", fail);

2
lightningd/plugin.c

@ -916,7 +916,7 @@ bool plugin_parse_getmanifest_response(const char *buffer,
return true;
}
if (!features_additional(fset)) {
if (!feature_set_or(plugin->plugins->ld->feature_set, fset)) {
plugin_kill(plugin,
"Custom featurebits already present");
return true;

7
lightningd/test/run-find_my_abspath.c

@ -60,6 +60,13 @@ bool db_in_transaction(struct db *db UNNEEDED)
/* Generated stub for fatal */
void fatal(const char *fmt UNNEEDED, ...)
{ fprintf(stderr, "fatal called!\n"); abort(); }
/* Generated stub for feature_set_for_feature */
struct feature_set *feature_set_for_feature(const tal_t *ctx UNNEEDED, int feature UNNEEDED)
{ fprintf(stderr, "feature_set_for_feature called!\n"); abort(); }
/* Generated stub for feature_set_or */
bool feature_set_or(struct feature_set *a UNNEEDED,
const struct feature_set *b TAKES UNNEEDED)
{ fprintf(stderr, "feature_set_or called!\n"); abort(); }
/* Generated stub for free_htlcs */
void free_htlcs(struct lightningd *ld UNNEEDED, const struct channel *channel UNNEEDED)
{ fprintf(stderr, "free_htlcs called!\n"); abort(); }

4
lightningd/test/run-invoice-select-inchan.c

@ -23,6 +23,7 @@ void bitcoind_getutxout_(struct bitcoind *bitcoind UNNEEDED,
{ fprintf(stderr, "bitcoind_getutxout_ called!\n"); abort(); }
/* Generated stub for bolt11_decode */
struct bolt11 *bolt11_decode(const tal_t *ctx UNNEEDED, const char *str UNNEEDED,
const struct feature_set *fset UNNEEDED,
const char *description UNNEEDED, char **fail UNNEEDED)
{ fprintf(stderr, "bolt11_decode called!\n"); abort(); }
/* Generated stub for bolt11_encode_ */
@ -137,9 +138,6 @@ u32 get_feerate(const struct fee_states *fee_states UNNEEDED,
enum side funder UNNEEDED,
enum side side UNNEEDED)
{ fprintf(stderr, "get_feerate called!\n"); abort(); }
/* Generated stub for get_offered_bolt11features */
u8 *get_offered_bolt11features(const tal_t *ctx UNNEEDED)
{ fprintf(stderr, "get_offered_bolt11features called!\n"); abort(); }
/* Generated stub for htlc_is_trimmed */
bool htlc_is_trimmed(enum side htlc_owner UNNEEDED,
struct amount_msat htlc_amount UNNEEDED,

12
openingd/openingd.c

@ -113,6 +113,8 @@ struct state {
struct channel *channel;
bool option_static_remotekey;
struct feature_set *fset;
};
static u8 *dev_upfront_shutdown_script(const tal_t *ctx)
@ -563,7 +565,7 @@ static u8 *funder_channel_start(struct state *state, u8 channel_flags)
* `payment_basepoint`, or `delayed_payment_basepoint` are not
* valid secp256k1 pubkeys in compressed format.
*/
if (feature_negotiated(state->features,
if (feature_negotiated(state->fset, state->features,
OPT_UPFRONT_SHUTDOWN_SCRIPT)) {
if (!fromwire_accept_channel_option_upfront_shutdown_script(state,
msg, &id_in,
@ -644,6 +646,7 @@ static u8 *funder_channel_start(struct state *state, u8 channel_flags)
return towire_opening_funder_start_reply(state,
funding_output_script,
feature_negotiated(
state->fset,
state->features,
OPT_UPFRONT_SHUTDOWN_SCRIPT));
}
@ -904,7 +907,7 @@ static u8 *fundee_channel(struct state *state, const u8 *open_channel_msg)
* `payment_basepoint`, or `delayed_payment_basepoint` are not valid
* secp256k1 pubkeys in compressed format.
*/
if (feature_negotiated(state->features,
if (feature_negotiated(state->fset, state->features,
OPT_UPFRONT_SHUTDOWN_SCRIPT)) {
if (!fromwire_open_channel_option_upfront_shutdown_script(state,
open_channel_msg, &chain_hash,
@ -1481,7 +1484,6 @@ int main(int argc, char *argv[])
struct state *state = tal(NULL, struct state);
struct secret *none;
struct channel_id *force_tmp_channel_id;
struct feature_set *feature_set;
subdaemon_setup(argc, argv);
@ -1493,7 +1495,7 @@ int main(int argc, char *argv[])
msg = wire_sync_read(tmpctx, REQ_FD);
if (!fromwire_opening_init(state, msg,
&chainparams,
&feature_set,
&state->fset,
&state->localconf,
&state->max_to_self_delay,
&state->min_effective_htlc_capacity,
@ -1509,8 +1511,6 @@ int main(int argc, char *argv[])
&dev_fast_gossip))
master_badmsg(WIRE_OPENING_INIT, msg);
features_init(take(feature_set));
#if DEVELOPER
dev_force_tmp_channel_id = force_tmp_channel_id;
#endif

3
plugins/pay.c

@ -1283,7 +1283,8 @@ static struct command_result *json_pay(struct command *cmd,
NULL))
return command_param_failed();
b11 = bolt11_decode(cmd, b11str, NULL, &fail);
/* FIXME: We need to know our features! */
b11 = bolt11_decode(cmd, b11str, NULL, NULL, &fail);
if (!b11) {
return command_fail(cmd, JSONRPC2_INVALID_PARAMS,
"Invalid bolt11: %s", fail);

Loading…
Cancel
Save