diff --git a/peer.go b/peer.go index f8a541c9..90ecec10 100644 --- a/peer.go +++ b/peer.go @@ -874,7 +874,33 @@ func newChanMsgStream(p *peer, cid lnwire.ChannelID) *msgStream { // active goroutine dedicated to this channel. if chanLink == nil { link, err := p.server.htlcSwitch.GetLink(cid) - if err != nil { + switch { + + // If we failed to find the link in question, + // and the message received was a channel sync + // message, then this might be a peer trying to + // resync closed channel. In this case we'll + // try to resend our last channel sync message, + // such that the peer can recover funds from + // the closed channel. + case err != nil && isChanSyncMsg: + peerLog.Debugf("Unable to find "+ + "link(%v) to handle channel "+ + "sync, attempting to resend "+ + "last ChanSync message", cid) + + err := p.resendChanSyncMsg(cid) + if err != nil { + // TODO(halseth): send error to + // peer? + peerLog.Errorf( + "resend failed: %v", + err, + ) + } + return + + case err != nil: peerLog.Errorf("recv'd update for "+ "unknown channel %v from %v: "+ "%v", cid, p, err) @@ -2144,6 +2170,35 @@ func (p *peer) sendInitMsg() error { return p.writeMessage(msg) } +// 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 { + // Check if we have any channel sync messages stored for this channel. + c, err := p.server.chanDB.FetchClosedChannelForID(cid) + if err != nil { + return fmt.Errorf("unable to fetch channel sync messages for "+ + "peer %v: %v", p, err) + } + + if c.LastChanSyncMsg == nil { + return fmt.Errorf("no chan sync message stored for channel %v", + cid) + } + + peerLog.Debugf("Re-sending channel sync message for channel %v to "+ + "peer %v", cid, p) + + if err := p.SendMessage(true, c.LastChanSyncMsg); err != nil { + return fmt.Errorf("Failed resending channel sync "+ + "message to peer %v: %v", p, err) + } + + peerLog.Debugf("Re-sent channel sync message for channel %v to peer "+ + "%v", cid, p) + + return nil +} + // SendMessage sends a variadic number of message to remote peer. The first // argument denotes if the method should block until the message has been sent // to the remote peer.