diff --git a/htlcswitch/link.go b/htlcswitch/link.go index 7163c8ac..2b28700e 100644 --- a/htlcswitch/link.go +++ b/htlcswitch/link.go @@ -157,15 +157,6 @@ type channelLink struct { started int32 shutdown int32 - // cancelReasons stores the reason why a particular HTLC was cancelled. - // The index of the HTLC within the log is mapped to the cancellation - // reason. This value is used to thread the proper error through to the - // htlcSwitch, or subsystem that initiated the HTLC. - // - // TODO(andrew.shvv) remove after payment descriptor start store - // htlc cancel reasons. - cancelReasons map[uint64]lnwire.OpaqueReason - // batchCounter is the number of updates which we received from remote // side, but not include in commitment transaction yet and plus the // current number of settles that have been sent, but not yet committed @@ -236,7 +227,6 @@ func NewChannelLink(cfg ChannelLinkConfig, channel *lnwallet.LightningChannel, linkControl: make(chan interface{}), // TODO(roasbeef): just do reserve here? availableBandwidth: uint64(channel.StateSnapshot().LocalBalance), - cancelReasons: make(map[uint64]lnwire.OpaqueReason), logCommitTimer: time.NewTimer(300 * time.Millisecond), overflowQueue: newPacketQueue(lnwallet.MaxHTLCNumber / 2), bestHeight: currentHeight, @@ -664,7 +654,7 @@ func (l *channelLink) handleDownStreamPkt(pkt *htlcPacket, isReProcess bool) { case *lnwire.UpdateFailHTLC: // An HTLC cancellation has been triggered somewhere upstream, // we'll remove then HTLC from our local state machine. - logIndex, err := l.channel.FailHTLC(pkt.payHash) + logIndex, err := l.channel.FailHTLC(pkt.payHash, htlc.Reason) if err != nil { log.Errorf("unable to cancel HTLC: %v", err) return @@ -749,20 +739,6 @@ func (l *channelLink) handleUpstreamMsg(msg lnwire.Message) { // repeated r-values case *lnwire.UpdateFailMalformedHTLC: - // If remote side have been unable to parse the onion blob we - // have sent to it, than we should transform the malformed HTLC - // message to the usual HTLC fail message. - idx := msg.ID - amt, err := l.channel.ReceiveFailHTLC(idx) - if err != nil { - l.fail("unable to handle upstream fail HTLC: %v", err) - return - } - - // Increment the available bandwidth as they've removed our - // HTLC. - atomic.AddUint64(&l.availableBandwidth, uint64(amt)) - // Convert the failure type encoded within the HTLC fail // message to the proper generic lnwire error code. var failure lnwire.FailureMessage @@ -795,11 +771,10 @@ func (l *channelLink) handleUpstreamMsg(msg lnwire.Message) { return } - l.cancelReasons[idx] = lnwire.OpaqueReason(b.Bytes()) - - case *lnwire.UpdateFailHTLC: - idx := msg.ID - amt, err := l.channel.ReceiveFailHTLC(idx) + // If remote side have been unable to parse the onion blob we + // have sent to it, than we should transform the malformed HTLC + // message to the usual HTLC fail message. + amt, err := l.channel.ReceiveFailHTLC(idx, b.Bytes()) if err != nil { l.fail("unable to handle upstream fail HTLC: %v", err) return @@ -809,7 +784,17 @@ func (l *channelLink) handleUpstreamMsg(msg lnwire.Message) { // HTLC. atomic.AddUint64(&l.availableBandwidth, uint64(amt)) - l.cancelReasons[idx] = msg.Reason + case *lnwire.UpdateFailHTLC: + idx := msg.ID + amt, err := l.channel.ReceiveFailHTLC(idx, msg.Reason[:]) + if err != nil { + l.fail("unable to handle upstream fail HTLC: %v", err) + return + } + + // Increment the available bandwidth as they've removed our + // HTLC. + atomic.AddUint64(&l.availableBandwidth, uint64(amt)) case *lnwire.CommitSig: // We just received a new updates to our local commitment chain, @@ -1105,10 +1090,8 @@ func (l *channelLink) processLockedInHtlcs( case lnwallet.Fail: // Fetch the reason the HTLC was cancelled so we can // continue to propagate it. - opaqueReason := l.cancelReasons[pd.ParentIndex] - failUpdate := &lnwire.UpdateFailHTLC{ - Reason: opaqueReason, + Reason: lnwire.OpaqueReason(pd.FailReason), ChanID: l.ChanID(), } failPacket := newFailPacket(l.ShortChanID(), failUpdate, @@ -1513,7 +1496,7 @@ func (l *channelLink) sendHTLCError(rHash [32]byte, failure lnwire.FailureMessag return } - index, err := l.channel.FailHTLC(rHash) + index, err := l.channel.FailHTLC(rHash, reason) if err != nil { log.Errorf("unable cancel htlc: %v", err) return diff --git a/lnwallet/channel.go b/lnwallet/channel.go index 0bf5dc8f..3e2c9f61 100644 --- a/lnwallet/channel.go +++ b/lnwallet/channel.go @@ -214,6 +214,11 @@ type PaymentDescriptor struct { // NOTE: Populated only on add payment descriptor entry types. OnionBlob []byte + // FailReason stores the reason why a particular payment was cancelled. + // + // NOTE: Populate only in fail payment descriptor entry types. + FailReason []byte + // [our|their|]PkScript are the raw public key scripts that encodes the // redemption rules for this particular HTLC. These fields will only be // populated iff the EntryType of this PaymentDescriptor is Add. @@ -1691,7 +1696,6 @@ func (lc *LightningChannel) restoreStateLogs() error { EntryType: Add, addCommitHeightRemote: pastHeight, addCommitHeightLocal: pastHeight, - OnionBlob: htlc.OnionBlob, ourPkScript: ourP2WSH, ourWitnessScript: ourWitnessScript, theirPkScript: theirP2WSH, @@ -3219,7 +3223,7 @@ func (lc *LightningChannel) ReceiveHTLCSettle(preimage [32]byte, htlcIndex uint6 // _incoming_ HTLC. // // TODO(roasbeef): add value as well? -func (lc *LightningChannel) FailHTLC(rHash [32]byte) (uint64, error) { +func (lc *LightningChannel) FailHTLC(rHash [32]byte, reason []byte) (uint64, error) { lc.Lock() defer lc.Unlock() @@ -3235,6 +3239,7 @@ func (lc *LightningChannel) FailHTLC(rHash [32]byte) (uint64, error) { ParentIndex: addEntry.HtlcIndex, LogIndex: lc.localUpdateLog.logIndex, EntryType: Fail, + FailReason: reason, } lc.localUpdateLog.appendUpdate(pd) @@ -3253,7 +3258,9 @@ func (lc *LightningChannel) FailHTLC(rHash [32]byte) (uint64, error) { // commitment update. This method should be called in response to the upstream // party cancelling an outgoing HTLC. The value of the failed HTLC is returned // along with an error indicating success. -func (lc *LightningChannel) ReceiveFailHTLC(htlcIndex uint64) (lnwire.MilliSatoshi, error) { +func (lc *LightningChannel) ReceiveFailHTLC(htlcIndex uint64, + reason []byte) (lnwire.MilliSatoshi, error) { + lc.Lock() defer lc.Unlock() @@ -3268,6 +3275,7 @@ func (lc *LightningChannel) ReceiveFailHTLC(htlcIndex uint64) (lnwire.MilliSatos ParentIndex: htlc.HtlcIndex, LogIndex: lc.remoteUpdateLog.logIndex, EntryType: Fail, + FailReason: reason, } lc.remoteUpdateLog.appendUpdate(pd) diff --git a/lnwallet/channel_test.go b/lnwallet/channel_test.go index a364629d..958c1362 100644 --- a/lnwallet/channel_test.go +++ b/lnwallet/channel_test.go @@ -1648,11 +1648,11 @@ func TestCancelHTLC(t *testing.T) { // Now, with the HTLC committed on both sides, trigger a cancellation // from Bob to Alice, removing the HTLC. - htlcCancelIndex, err := bobChannel.FailHTLC(paymentHash) + htlcCancelIndex, err := bobChannel.FailHTLC(paymentHash, []byte("failreason")) if err != nil { t.Fatalf("unable to cancel HTLC: %v", err) } - if _, err := aliceChannel.ReceiveFailHTLC(htlcCancelIndex); err != nil { + if _, err := aliceChannel.ReceiveFailHTLC(htlcCancelIndex, []byte("bad")); err != nil { t.Fatalf("unable to recv htlc cancel: %v", err) }