From 3554678e9c778c8893fc091a6566240a313998f4 Mon Sep 17 00:00:00 2001 From: Matt Corallo Date: Wed, 15 Feb 2023 01:13:57 +0000 Subject: [PATCH] Fix (and DRY) the conditionals before calling `peer_disconnected` If we have a peer that sends a non-`Init` first message, we'll call `peer_disconnected` without ever having called `peer_connected` (which has to wait until we have an `Init` message). This is a violation of our API guarantees, though should generally not be an issue. Because this bug was repeated in a few places, we also take this opportunity to DRY up the logic which checks the peer state before calling `peer_disconnected`. Found by the new `ChannelManager` assertions and the `full_stack_target` fuzzer. --- lightning/src/ln/peer_handler.rs | 79 +++++++++++++++++++------------- 1 file changed, 48 insertions(+), 31 deletions(-) diff --git a/lightning/src/ln/peer_handler.rs b/lightning/src/ln/peer_handler.rs index 3775c27e..010894aa 100644 --- a/lightning/src/ln/peer_handler.rs +++ b/lightning/src/ln/peer_handler.rs @@ -393,6 +393,12 @@ struct Peer { /// We cache a `NodeId` here to avoid serializing peers' keys every time we forward gossip /// messages in `PeerManager`. Use `Peer::set_their_node_id` to modify this field. their_node_id: Option<(PublicKey, NodeId)>, + /// The features provided in the peer's [`msgs::Init`] message. + /// + /// This is set only after we've processed the [`msgs::Init`] message and called relevant + /// `peer_connected` handler methods. Thus, this field is set *iff* we've finished our + /// handshake and can talk to this peer normally (though use [`Peer::handshake_complete`] to + /// check this. their_features: Option, their_net_address: Option, @@ -424,6 +430,13 @@ struct Peer { } impl Peer { + /// True after we've processed the [`msgs::Init`] message and called relevant `peer_connected` + /// handler methods. Thus, this implies we've finished our handshake and can talk to this peer + /// normally. + fn handshake_complete(&self) -> bool { + self.their_features.is_some() + } + /// Returns true if the channel announcements/updates for the given channel should be /// forwarded to this peer. /// If we are sending our routing table to this peer and we have not yet sent channel @@ -1877,24 +1890,21 @@ impl { let peer = peer_lock.lock().unwrap(); + if !peer.handshake_complete() { return; } + debug_assert!(peer.their_node_id.is_some()); if let Some((node_id, _)) = peer.their_node_id { log_trace!(self.logger, "Handling disconnection of peer {}, with {}future connection to the peer possible.", @@ -1937,14 +1965,13 @@ impl