Skip to content

Commit 92e79ab

Browse files
committed
Stop enqueueing messages for disconnected peers
If a channel operation occurs while a peer is disconnected, we'll still have a `PeerState` for that peer. Historically, we haven't bothered to check if a peer is actually connected before we push new messages onto the `PeerState::pending_msg_events` field, leaving us sending messages into the void. This is generally not an issue as `ChannelManager::get_and_clear_pending_msg_events` should be called very regularly, removing these messages and then dropping them as `PeerManager` won't have anything to do with them. Still, there is a race condition here - if a peer manages to connect between the generation of one such message and when `get_and_clear_pending_msg_events` is called, we may enqueue a message to the peer which makes no sense and could lead to a spurious channel closure (especially in the case of an async `ChannelMonitorUpdate` completion or async signing operation, which often lead to normal channel message generation). Further, if a peer is slow to send their `channel_reestablish` message after connection this race could be substantially more likely, as such normal channel messages may be nonsense until we've completed the reestablish dance (i.e. the later reestablish dance may lead us to re-send the same messages again immediately). Here we remove most of the cases where we enqueue messages for disconnected peers. Note that we differentiate between two different checks for connected-ness - for cases where we're sending an `error` or gossip messages, we allow the messages to be enqueued if the peer is connected at all. For most other cases, we only allow messages to be enqueued if the peer is connected *and* the channel has completed its reestablish dance (if required, i.e. the channel is "connected").
1 parent 50391d3 commit 92e79ab

File tree

3 files changed

+180
-133
lines changed

3 files changed

+180
-133
lines changed

lightning/src/ln/channel.rs

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3883,6 +3883,12 @@ where
38833883
self.is_usable() && !self.channel_state.is_peer_disconnected()
38843884
}
38853885

3886+
/// Returns true if the peer for this channel is currently connected and we're not waiting on
3887+
/// `channel_reestablish` messages to re-init the channel.
3888+
pub fn is_connected(&self) -> bool {
3889+
!self.channel_state.is_peer_disconnected()
3890+
}
3891+
38863892
/// Returns false if our last broadcasted channel_update message has the "channel disabled" bit set
38873893
pub fn is_enabled(&self) -> bool {
38883894
self.is_usable()

0 commit comments

Comments
 (0)