Skip to content

Commit

Permalink
htlcswitch: handle nil circuit properly when settling
Browse files Browse the repository at this point in the history
We have two sources which can call `handlePacketSettle`, either through
the link's `<-s.htlcPlex`, or the `<-s.resolutionMsgs`, which means the
`closeCircuit` could be call twice. Previously we already caught this
case inside `closeCircuit`, in that we would return a nil circuit upon
seeing `ErrUnknownCircuit`, indicating the circuit was removed. However,
we still need to account the case when the circuit is the process of
being closed, which is now fixed as we will ignore when seeing
`ErrCircuitClosing`.
  • Loading branch information
yyforyongyu committed Dec 16, 2024
1 parent bb9c680 commit 944f162
Show file tree
Hide file tree
Showing 2 changed files with 21 additions and 1 deletion.
11 changes: 11 additions & 0 deletions htlcswitch/packet.go
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
package htlcswitch

import (
"fmt"

"github.com/lightningnetwork/lnd/channeldb"
"github.com/lightningnetwork/lnd/graph/db/models"
"github.com/lightningnetwork/lnd/htlcswitch/hop"
Expand Down Expand Up @@ -136,3 +138,12 @@ func (p *htlcPacket) keystone() Keystone {
OutKey: p.outKey(),
}
}

// String returns a human-readable description of the packet.
func (p *htlcPacket) String() string {
return fmt.Sprintf("keystone=%v, sourceRef=%v, destRef=%v, "+
"incomingAmount=%v, amount=%v, localFailure=%v, hasSource=%v "+
"isResolution=%v", p.keystone(), p.sourceRef, p.destRef,
p.incomingAmount, p.amount, p.localFailure, p.hasSource,
p.isResolution)
}
11 changes: 10 additions & 1 deletion htlcswitch/switch.go
Original file line number Diff line number Diff line change
Expand Up @@ -2994,6 +2994,15 @@ func (s *Switch) handlePacketSettle(packet *htlcPacket) error {
// If the source of this packet has not been set, use the circuit map
// to lookup the origin.
circuit, err := s.closeCircuit(packet)

// If the circuit is in the process of closing, we will return a nil as
// there's another packet handling undergoing.
if errors.Is(err, ErrCircuitClosing) {
log.Debugf("Circuit is closing for packet=%v", packet)
return nil
}

// Exit early if there's another error.
if err != nil {
return err
}
Expand All @@ -3005,7 +3014,7 @@ func (s *Switch) handlePacketSettle(packet *htlcPacket) error {
// and when `UpdateFulfillHTLC` is received. After which `RevokeAndAck`
// is received, which invokes `processRemoteSettleFails` in its link.
if circuit == nil {
log.Debugf("Found nil circuit: packet=%v", spew.Sdump(packet))
log.Debugf("Circuit already closed for packet=%v", packet)
return nil
}

Expand Down

0 comments on commit 944f162

Please sign in to comment.