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.