From 33c658ecfb394283fdb266c9a33deb1a0d7e9e91 Mon Sep 17 00:00:00 2001 From: Rusty Russell Date: Fri, 4 Oct 2019 10:44:00 +0930 Subject: [PATCH] gossipd: advertize all our features in node_announcement. This preempts the acceptance of https://github.com/lightningnetwork/lightning-rfc/pull/666 but it's clear that feature bits are going to be distinct, so this is safe to do anyway. See https://github.com/lightningnetwork/lightning-rfc/pull/680 Signed-off-by: Rusty Russell --- CHANGELOG.md | 1 + common/features.c | 12 ++++++++++++ common/features.h | 1 + gossipd/gossip_generation.c | 2 +- gossipd/gossipd.c | 3 ++- gossipd/gossipd.h | 4 ++-- lightningd/gossip_control.c | 2 +- tests/test_connection.py | 4 ++-- tests/test_gossip.py | 7 ++++++- 9 files changed, 28 insertions(+), 8 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index cdad04f84..13ba05acb 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -18,6 +18,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - Plugin: new notifications `sendpay_success` and `sendpay_failure`. - Protocol: we now offer `option_gossip_queries_ex` for finegrained gossip control. - Protocol: no longer ask for `initial_routing_sync` (only affects ancient peers). +- Protocol: nodes now announce features in `node_announcement` broadcasts. ### Changed diff --git a/common/features.c b/common/features.c index ff3ae89fc..2d2b023ad 100644 --- a/common/features.c +++ b/common/features.c @@ -54,6 +54,18 @@ u8 *get_offered_globalfeatures(const tal_t *ctx) our_globalfeatures, ARRAY_SIZE(our_globalfeatures)); } +/* We currently advertize everything in node_announcement, except + * initial_routing_sync which the spec says not to (and we don't set + * any more anyway). + * + * FIXME: Add bolt ref when finalized! + */ +u8 *get_offered_nodefeatures(const tal_t *ctx) +{ + return mkfeatures(ctx, + our_localfeatures, ARRAY_SIZE(our_localfeatures)); +} + u8 *get_offered_localfeatures(const tal_t *ctx) { return mkfeatures(ctx, diff --git a/common/features.h b/common/features.h index f4b677784..f6d23853b 100644 --- a/common/features.h +++ b/common/features.h @@ -10,6 +10,7 @@ bool features_supported(const u8 *globalfeatures, const u8 *localfeatures); /* For sending our features: tal_count() returns length. */ u8 *get_offered_globalfeatures(const tal_t *ctx); u8 *get_offered_localfeatures(const tal_t *ctx); +u8 *get_offered_nodefeatures(const tal_t *ctx); /* Is this feature bit requested? (Either compulsory or optional) */ bool feature_offered(const u8 *features, size_t f); diff --git a/gossipd/gossip_generation.c b/gossipd/gossip_generation.c index b698caae0..baf048825 100644 --- a/gossipd/gossip_generation.c +++ b/gossipd/gossip_generation.c @@ -35,7 +35,7 @@ static u8 *create_node_announcement(const tal_t *ctx, struct daemon *daemon, towire_wireaddr(&addresses, &daemon->announcable[i]); announcement = - towire_node_announcement(ctx, sig, daemon->globalfeatures, timestamp, + towire_node_announcement(ctx, sig, daemon->nodefeatures, timestamp, &daemon->id, daemon->rgb, daemon->alias, addresses); return announcement; diff --git a/gossipd/gossipd.c b/gossipd/gossipd.c index 9e52641d0..cd35c8bef 100644 --- a/gossipd/gossipd.c +++ b/gossipd/gossipd.c @@ -931,7 +931,8 @@ static struct io_plan *gossip_init(struct io_conn *conn, if (!fromwire_gossipctl_init(daemon, msg, &chainparams, - &daemon->id, &daemon->globalfeatures, + &daemon->id, + &daemon->nodefeatures, daemon->rgb, daemon->alias, &daemon->announcable, diff --git a/gossipd/gossipd.h b/gossipd/gossipd.h index f9704ae3b..9208201b6 100644 --- a/gossipd/gossipd.h +++ b/gossipd/gossipd.h @@ -43,8 +43,8 @@ struct daemon { /* Timers: we batch gossip, and also refresh announcements */ struct timers timers; - /* Global features to list in node_announcement. */ - u8 *globalfeatures; + /* Features to list in node_announcement. */ + u8 *nodefeatures; /* Alias (not NUL terminated) and favorite color for node_announcement */ u8 alias[32]; diff --git a/lightningd/gossip_control.c b/lightningd/gossip_control.c index d20c96445..b17649aa0 100644 --- a/lightningd/gossip_control.c +++ b/lightningd/gossip_control.c @@ -210,7 +210,7 @@ void gossip_init(struct lightningd *ld, int connectd_fd) tmpctx, chainparams, &ld->id, - get_offered_globalfeatures(tmpctx), + get_offered_nodefeatures(tmpctx), ld->rgb, ld->alias, ld->announcable, diff --git a/tests/test_connection.py b/tests/test_connection.py index 4ca2b60a6..8e4a81043 100644 --- a/tests/test_connection.py +++ b/tests/test_connection.py @@ -1403,8 +1403,8 @@ def test_peerinfo(node_factory, bitcoind): nodes2 = l2.rpc.listnodes(l2.info['id'])['nodes'] peer1 = l1.rpc.getpeer(l2.info['id']) peer2 = l2.rpc.getpeer(l1.info['id']) - assert only_one(nodes1)['globalfeatures'] == peer1['globalfeatures'] - assert only_one(nodes2)['globalfeatures'] == peer2['globalfeatures'] + assert only_one(nodes1)['globalfeatures'] == peer1['localfeatures'] + assert only_one(nodes2)['globalfeatures'] == peer2['localfeatures'] assert l1.rpc.getpeer(l2.info['id'])['localfeatures'] == lfeatures assert l2.rpc.getpeer(l1.info['id'])['localfeatures'] == lfeatures diff --git a/tests/test_gossip.py b/tests/test_gossip.py index d0fd1beeb..0ca0b1290 100644 --- a/tests/test_gossip.py +++ b/tests/test_gossip.py @@ -1012,6 +1012,11 @@ def test_node_reannounce(node_factory, bitcoind): wait_for(lambda: 'alias' in only_one(l2.rpc.listnodes(l1.info['id'])['nodes'])) assert only_one(l2.rpc.listnodes(l1.info['id'])['nodes'])['alias'].startswith('JUNIORBEAM') + lfeatures = '28a2' + + # Make sure it gets features correct. + assert only_one(l2.rpc.listnodes(l1.info['id'])['nodes'])['globalfeatures'] == lfeatures + l1.stop() l1.daemon.opts['alias'] = 'SENIORBEAM' # It won't update within 5 seconds, so sleep. @@ -1429,7 +1434,7 @@ def test_gossip_store_compact_on_load(node_factory, bitcoind): l2.restart() wait_for(lambda: l2.daemon.is_in_log(r'gossip_store_compact_offline: [5-8] deleted, 9 copied')) - wait_for(lambda: l2.daemon.is_in_log(r'gossip_store: Read 1/4/2/0 cannounce/cupdate/nannounce/cdelete from store \(0 deleted\) in 1446 bytes')) + wait_for(lambda: l2.daemon.is_in_log(r'gossip_store: Read 1/4/2/0 cannounce/cupdate/nannounce/cdelete from store \(0 deleted\) in 1450 bytes')) def test_gossip_announce_invalid_block(node_factory, bitcoind):