From 44c87ef1d74870323570517fd71193da0956f928 Mon Sep 17 00:00:00 2001 From: Keagan McClelland Date: Tue, 12 Dec 2023 13:11:05 -0800 Subject: [PATCH] htlcswitch: bounce packets when quiescent --- htlcswitch/link.go | 49 +++++++++++++++++++++++++++++++++++----------- 1 file changed, 38 insertions(+), 11 deletions(-) diff --git a/htlcswitch/link.go b/htlcswitch/link.go index 46f06c9ab..b56b0897f 100644 --- a/htlcswitch/link.go +++ b/htlcswitch/link.go @@ -643,20 +643,37 @@ func (l *channelLink) WaitForShutdown() { // actively accept requests to forward HTLC's. We're able to forward HTLC's if // we are eligible to update AND the channel isn't currently flushing the // outgoing half of the channel. +// +// NOTE: MUST NOT be called from the main event loop. func (l *channelLink) EligibleToForward() bool { - return l.EligibleToUpdate() && - !l.IsFlushing(Outgoing) + l.RLock() + defer l.RUnlock() + + return l.eligibleToForward() } -// EligibleToUpdate returns a bool indicating if the channel is able to update +// eligibleToForward returns a bool indicating if the channel is able to +// actively accept requests to forward HTLC's. We're able to forward HTLC's if +// we are eligible to update AND the channel isn't currently flushing the +// outgoing half of the channel. +// +// NOTE: MUST be called from the main event loop. +func (l *channelLink) eligibleToForward() bool { + return l.eligibleToUpdate() && !l.IsFlushing(Outgoing) +} + +// eligibleToUpdate returns a bool indicating if the channel is able to update // channel state. We're able to update channel state if we know the remote // party's next revocation point. Otherwise, we can't initiate new channel // state. We also require that the short channel ID not be the all-zero source // ID, meaning that the channel has had its ID finalized. -func (l *channelLink) EligibleToUpdate() bool { +// +// NOTE: MUST be called from the main event loop. +func (l *channelLink) eligibleToUpdate() bool { return l.channel.RemoteNextRevocation() != nil && - l.ShortChanID() != hop.Source && - l.isReestablished() + l.channel.ShortChanID() != hop.Source && + l.isReestablished() && + l.quiescer.CanSendUpdates() } // EnableAdds sets the ChannelUpdateHandler state to allow UpdateAddHtlc's in @@ -1599,13 +1616,14 @@ func (l *channelLink) handleDownstreamUpdateAdd(pkt *htlcPacket) error { return errors.New("not an UpdateAddHTLC packet") } - // If we are flushing the link in the outgoing direction we can't add - // new htlcs to the link and we need to bounce it - if l.IsFlushing(Outgoing) { + // If we are flushing the link in the outgoing direction or we have + // already sent Stfu, then we can't add new htlcs to the link and we + // need to bounce it. + if l.IsFlushing(Outgoing) || !l.quiescer.CanSendUpdates() { l.mailBox.FailAdd(pkt) return NewDetailedLinkError( - &lnwire.FailPermanentChannelFailure{}, + &lnwire.FailTemporaryChannelFailure{}, OutgoingFailureLinkNotEligible, ) } @@ -1708,6 +1726,15 @@ func (l *channelLink) handleDownstreamUpdateAdd(pkt *htlcPacket) error { // // TODO(roasbeef): add sync ntfn to ensure switch always has consistent view? func (l *channelLink) handleDownstreamPkt(pkt *htlcPacket) { + if pkt.htlc.MsgType().IsChannelUpdate() && + !l.quiescer.CanSendUpdates() { + + l.log.Warnf("unable to process channel update. "+ + "ChannelID=%v is quiescent.", l.ChanID) + + return + } + switch htlc := pkt.htlc.(type) { case *lnwire.UpdateAddHTLC: // Handle add message. The returned error can be ignored, @@ -3364,7 +3391,7 @@ func (l *channelLink) updateChannelFee(feePerKw chainfee.SatPerKWeight) error { // We skip sending the UpdateFee message if the channel is not // currently eligible to forward messages. - if !l.EligibleToUpdate() { + if !l.eligibleToUpdate() { l.log.Debugf("skipping fee update for inactive channel") return nil }