From 891b00d473468c93d9e0c20157466b9258a67f55 Mon Sep 17 00:00:00 2001 From: Keagan McClelland Date: Fri, 8 Dec 2023 15:10:30 -0800 Subject: [PATCH] htlcswitch: drop the connection when receiving an invalid add When the link is flushing in the incoming direction, it means adds are invalid. The best chance we have at dealing with this is to drop the connection. This should roll back the channel state to the last CommitSig. If the remote has already sent a CommitSig we haven't received yet, channel state will be re-synchronized with a ChannelReestablish message upon reconnection and the protocol state that caused us to flush the link will be rolled back. In the event that there was some non-deterministic behavior in the remote that caused them to violate the protocol, we have a decent shot at correcting it this way, since reconnecting will put us in the cleanest possible state to try again. --- htlcswitch/link.go | 33 +++++++++++++++++++++++++++++++++ 1 file changed, 33 insertions(+) diff --git a/htlcswitch/link.go b/htlcswitch/link.go index 76293fd7a..ebcd2031a 100644 --- a/htlcswitch/link.go +++ b/htlcswitch/link.go @@ -1786,6 +1786,39 @@ func (l *channelLink) handleUpstreamMsg(msg lnwire.Message) { switch msg := msg.(type) { case *lnwire.UpdateAddHTLC: + if l.IsFlushing(Incoming) { + // This is forbidden by the protocol specification. + // The best chance we have to deal with this is to drop + // the connection. This should roll back the channel + // state to the last CommitSig. If the remote has + // already sent a CommitSig we haven't received yet, + // channel state will be re-synchronized with a + // ChannelReestablish message upon reconnection and the + // protocol state that caused us to flush the link will + // be rolled back. In the event that there was some + // non-deterministic behavior in the remote that caused + // them to violate the protocol, we have a decent shot + // at correcting it this way, since reconnecting will + // put us in the cleanest possible state to try again. + // + // In addition to the above, it is possible for us to + // hit this case in situations where we improperly + // handle message ordering due to concurrency choices. + // An issue has been filed to address this here: + // https://github.com/lightningnetwork/lnd/issues/8393 + l.fail( + LinkFailureError{ + code: ErrInvalidUpdate, + FailureAction: LinkFailureDisconnect, + PermanentFailure: false, + Warning: true, + }, + "received add while link is flushing", + ) + + return + } + // We just received an add request from an upstream peer, so we // add it to our state machine, then add the HTLC to our // "settle" list in the event that we know the preimage.