From 7b8eae38e54ca87f4760263821762a78577480c6 Mon Sep 17 00:00:00 2001 From: "Johan T. Halseth" Date: Mon, 17 Feb 2020 12:47:26 +0100 Subject: [PATCH] peer: avoid chansync resend loop If a peer receives a channel reestablish message shortly after the channel has been closed, it will resend its own channel reestablish message. In the meantime the other peer could also have seen the channel being closed and will also resend its own message. This leads to a resend loop that never terminates. To avoid two peers getting into this situation, we now allow only one such resent message per conection. --- peer.go | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/peer.go b/peer.go index 4c8369f1..5aef5f59 100644 --- a/peer.go +++ b/peer.go @@ -210,6 +210,12 @@ type peer struct { // the connection handshake. remoteFeatures *lnwire.FeatureVector + // resentChanSyncMsg is a set that keeps track of which channels we + // have re-sent channel reestablishment messages for. This is done to + // avoid getting into loop where both peers will respond to the other + // peer's chansync message with its own over and over again. + resentChanSyncMsg map[lnwire.ChannelID]struct{} + // writePool is the task pool to that manages reuse of write buffers. // Write tasks are submitted to the pool in order to conserve the total // number of write buffers allocated at any one time, and decouple write @@ -266,6 +272,7 @@ func newPeer(conn net.Conn, connReq *connmgr.ConnReq, server *server, localCloseChanReqs: make(chan *htlcswitch.ChanClose), linkFailures: make(chan linkFailureReport), chanCloseMsgs: make(chan *closeMsg), + resentChanSyncMsg: make(map[lnwire.ChannelID]struct{}), chanActiveTimeout: chanActiveTimeout, @@ -2506,6 +2513,12 @@ func (p *peer) sendInitMsg() error { // resendChanSyncMsg will attempt to find a channel sync message for the closed // channel and resend it to our peer. func (p *peer) resendChanSyncMsg(cid lnwire.ChannelID) error { + // If we already re-sent the mssage for this channel, we won't do it + // again. + if _, ok := p.resentChanSyncMsg[cid]; ok { + return nil + } + // Check if we have any channel sync messages stored for this channel. c, err := p.server.chanDB.FetchClosedChannelForID(cid) if err != nil { @@ -2534,6 +2547,10 @@ func (p *peer) resendChanSyncMsg(cid lnwire.ChannelID) error { peerLog.Debugf("Re-sent channel sync message for channel %v to peer "+ "%v", cid, p) + // Note down that we sent the message, so we won't resend it again for + // this connection. + p.resentChanSyncMsg[cid] = struct{}{} + return nil }