From 162adfdf12d5e6907c18ffa6a5f9a6885d405590 Mon Sep 17 00:00:00 2001 From: Rusty Russell Date: Fri, 17 Aug 2018 13:44:39 +0930 Subject: [PATCH] listpeers: correctly display features on reconnect. peer features are only kept for connected peers (as they can change), but we didn't update them on reconnect. The main effect was that after a restart we displayed the features as empty, even after reconnect. Signed-off-by: Rusty Russell --- lightningd/peer_control.c | 20 ++++++++++++++++---- tests/test_connection.py | 12 +++++++++++- 2 files changed, 27 insertions(+), 5 deletions(-) diff --git a/lightningd/peer_control.c b/lightningd/peer_control.c index 8bc05aede..7ac334101 100644 --- a/lightningd/peer_control.c +++ b/lightningd/peer_control.c @@ -78,6 +78,18 @@ static void copy_to_parent_log(const char *prefix, log_(parent_log, level, "%s %s", prefix, str); } +static void peer_update_features(struct peer *peer, + const u8 *gfeatures TAKES, + const u8 *lfeatures TAKES) +{ + tal_free(peer->global_features); + tal_free(peer->local_features); + peer->global_features = tal_dup_arr(peer, u8, + gfeatures, tal_count(gfeatures), 0); + peer->local_features = tal_dup_arr(peer, u8, + lfeatures, tal_count(lfeatures), 0); +} + struct peer *new_peer(struct lightningd *ld, u64 dbid, const struct pubkey *id, const struct wireaddr_internal *addr, @@ -97,10 +109,8 @@ struct peer *new_peer(struct lightningd *ld, u64 dbid, peer->addr.itype = ADDR_INTERNAL_WIREADDR; peer->addr.u.wireaddr.type = ADDR_TYPE_PADDING; } - peer->global_features = tal_dup_arr(peer, u8, - gfeatures, tal_count(gfeatures), 0); - peer->local_features = tal_dup_arr(peer, u8, - lfeatures, tal_count(lfeatures), 0); + peer->global_features = peer->local_features = NULL; + peer_update_features(peer, gfeatures, lfeatures); list_head_init(&peer->channels); peer->direction = get_channel_direction(&peer->ld->id, &peer->id); @@ -447,6 +457,8 @@ void peer_connected(struct lightningd *ld, const u8 *msg, peer = peer_by_id(ld, &id); if (!peer) peer = new_peer(ld, 0, &id, &addr, gfeatures, lfeatures); + else + peer_update_features(peer, gfeatures, lfeatures); /* Can't be opening, since we wouldn't have sent peer_disconnected. */ assert(!peer->uncommitted_channel); diff --git a/tests/test_connection.py b/tests/test_connection.py index 301c29f51..787a87687 100644 --- a/tests/test_connection.py +++ b/tests/test_connection.py @@ -1002,7 +1002,7 @@ def test_forget_channel(node_factory): def test_peerinfo(node_factory, bitcoind): - l1, l2 = node_factory.line_graph(2, fundchannel=False) + l1, l2 = node_factory.line_graph(2, fundchannel=False, opts={'may_reconnect': True}) # Gossiping but no node announcement yet assert l1.rpc.getpeer(l2.info['id'])['connected'] assert len(l1.rpc.getpeer(l2.info['id'])['channels']) == 0 @@ -1024,6 +1024,16 @@ def test_peerinfo(node_factory, bitcoind): assert only_one(nodes1)['global_features'] == peer1['global_features'] assert only_one(nodes2)['global_features'] == peer2['global_features'] + assert l1.rpc.getpeer(l2.info['id'])['local_features'] == '8a' + assert l2.rpc.getpeer(l1.info['id'])['local_features'] == '8a' + + # If it reconnects after db load, it should know features. + l1.restart() + wait_for(lambda: l1.rpc.getpeer(l2.info['id'])['connected']) + wait_for(lambda: l2.rpc.getpeer(l1.info['id'])['connected']) + assert l1.rpc.getpeer(l2.info['id'])['local_features'] == '8a' + assert l2.rpc.getpeer(l1.info['id'])['local_features'] == '8a' + # Close the channel to forget the peer with pytest.raises(RpcError, match=r'Channel close negotiation not finished'): l1.rpc.close(chan, False, 0)