peer: handle close messages using link lifecycle hooks

This commit is contained in:
Keagan McClelland 2023-11-26 12:57:11 -08:00
parent 70292253d1
commit 442f1dd677

View file

@ -3602,6 +3602,8 @@ func (p *Brontide) StartTime() time.Time {
// message is received from the remote peer. We'll use this message to advance
// the chan closer state machine.
func (p *Brontide) handleCloseMsg(msg *closeMsg) {
link := p.fetchLinkFromKeyAndCid(msg.cid)
// We'll now fetch the matching closing state machine in order to continue,
// or finalize the channel closure process.
chanCloser, err := p.fetchActiveChanCloser(msg.cid)
@ -3641,6 +3643,15 @@ func (p *Brontide) handleCloseMsg(msg *closeMsg) {
// We'll either continue negotiation, or halt.
switch typed := msg.msg.(type) {
case *lnwire.Shutdown:
// Disable incoming adds immediately.
if link != nil {
err := link.DisableAdds(htlcswitch.Incoming)
if err != nil {
p.log.Warnf("incoming link adds already disabled: %v",
link.ChanID())
}
}
oShutdown, err := chanCloser.ReceiveShutdown(*typed)
if err != nil {
handleErr(err)
@ -3648,18 +3659,49 @@ func (p *Brontide) handleCloseMsg(msg *closeMsg) {
}
oShutdown.WhenSome(func(msg lnwire.Shutdown) {
p.queueMsg(&msg, nil)
// if the link is nil it means we can immediately queue
// the Shutdown message since we don't have to wait for
// commitment transaction synchronization
if link == nil {
p.queueMsg(typed, nil)
return
}
// When we have a Shutdown to send, we defer it til the
// next time we send a CommitSig to remain spec
// compliant.
link.OnCommitOnce(htlcswitch.Outgoing, func() {
err := link.DisableAdds(htlcswitch.Outgoing)
if err != nil {
p.log.Warn(err.Error())
}
p.queueMsg(&msg, nil)
})
})
oClosingSigned, err := chanCloser.BeginNegotiation()
if err != nil {
handleErr(err)
return
beginNegotiation := func() {
oClosingSigned, err := chanCloser.BeginNegotiation()
if err != nil {
handleErr(err)
return
}
oClosingSigned.WhenSome(func(msg lnwire.ClosingSigned) {
p.queueMsg(&msg, nil)
})
}
oClosingSigned.WhenSome(func(msg lnwire.ClosingSigned) {
p.queueMsg(&msg, nil)
})
if link == nil {
beginNegotiation()
} else {
// Now we register a flush hook to advance the
// ChanCloser and possibly send out a ClosingSigned
// when the link finishes draining.
link.OnFlushedOnce(func() {
// Remove link in goroutine to prevent deadlock.
go p.cfg.Switch.RemoveLink(msg.cid)
beginNegotiation()
})
}
case *lnwire.ClosingSigned:
oClosingSigned, err := chanCloser.ReceiveClosingSigned(*typed)