diff --git a/htlcswitch/link.go b/htlcswitch/link.go index 27091e811..254b56f8c 100644 --- a/htlcswitch/link.go +++ b/htlcswitch/link.go @@ -1927,58 +1927,14 @@ func (l *channelLink) handleUpstreamMsg(ctx context.Context, } case *lnwire.UpdateFulfillHTLC: - pre := msg.PaymentPreimage - idx := msg.ID + err := l.processRemoteUpdateFulfillHTLC(msg) + if err != nil { + l.log.Errorf("failed to process remote fulfill: %v", + err) - // Before we pipeline the settle, we'll check the set of active - // htlc's to see if the related UpdateAddHTLC has been fully - // locked-in. - var lockedin bool - htlcs := l.channel.ActiveHtlcs() - for _, add := range htlcs { - // The HTLC will be outgoing and match idx. - if !add.Incoming && add.HtlcIndex == idx { - lockedin = true - break - } - } - - if !lockedin { - l.failf( - LinkFailureError{code: ErrInvalidUpdate}, - "unable to handle upstream settle", - ) return } - if err := l.channel.ReceiveHTLCSettle(pre, idx); err != nil { - l.failf( - LinkFailureError{ - code: ErrInvalidUpdate, - FailureAction: LinkFailureForceClose, - }, - "unable to handle upstream settle HTLC: %v", err, - ) - return - } - - settlePacket := &htlcPacket{ - outgoingChanID: l.ShortChanID(), - outgoingHTLCID: idx, - htlc: &lnwire.UpdateFulfillHTLC{ - PaymentPreimage: pre, - }, - } - - // Add the newly discovered preimage to our growing list of - // uncommitted preimage. These will be written to the witness - // cache just before accepting the next commitment signature - // from the remote peer. - l.uncommittedPreimages = append(l.uncommittedPreimages, pre) - - // Pipeline this settle, send it to the switch. - go l.forwardBatch(false, settlePacket) - case *lnwire.UpdateFailMalformedHTLC: // Convert the failure type encoded within the HTLC fail // message to the proper generic lnwire error code. @@ -4657,3 +4613,61 @@ func (l *channelLink) processRemoteUpdateAddHTLC( return nil } + +// processRemoteUpdateFulfillHTLC takes an `UpdateFulfillHTLC` msg sent from the +// remote and processes it. +func (l *channelLink) processRemoteUpdateFulfillHTLC( + msg *lnwire.UpdateFulfillHTLC) error { + + pre := msg.PaymentPreimage + idx := msg.ID + + // Before we pipeline the settle, we'll check the set of active htlc's + // to see if the related UpdateAddHTLC has been fully locked-in. + var lockedin bool + htlcs := l.channel.ActiveHtlcs() + for _, add := range htlcs { + // The HTLC will be outgoing and match idx. + if !add.Incoming && add.HtlcIndex == idx { + lockedin = true + break + } + } + + if !lockedin { + err := errors.New("unable to handle upstream settle") + l.failf(LinkFailureError{code: ErrInvalidUpdate}, err.Error()) + + return err + } + + if err := l.channel.ReceiveHTLCSettle(pre, idx); err != nil { + l.failf( + LinkFailureError{ + code: ErrInvalidUpdate, + FailureAction: LinkFailureForceClose, + }, + "unable to handle upstream settle HTLC: %v", err, + ) + + return err + } + + settlePacket := &htlcPacket{ + outgoingChanID: l.ShortChanID(), + outgoingHTLCID: idx, + htlc: &lnwire.UpdateFulfillHTLC{ + PaymentPreimage: pre, + }, + } + + // Add the newly discovered preimage to our growing list of uncommitted + // preimage. These will be written to the witness cache just before + // accepting the next commitment signature from the remote peer. + l.uncommittedPreimages = append(l.uncommittedPreimages, pre) + + // Pipeline this settle, send it to the switch. + go l.forwardBatch(false, settlePacket) + + return nil +}