Merge pull request #9303 from yyforyongyu/fix-circuit-closed
htlcswitch+routing: handle nil pointer dereference properly
This commit is contained in:
4 files changed
+41
-7
No files matched your search
@@ -1,6 +1,8 @@
|
|||||||
package htlcswitch
|
package htlcswitch
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"fmt"
|
||||||
|
|
||||||
"github.com/lightningnetwork/lnd/channeldb"
|
"github.com/lightningnetwork/lnd/channeldb"
|
||||||
"github.com/lightningnetwork/lnd/graph/db/models"
|
"github.com/lightningnetwork/lnd/graph/db/models"
|
||||||
"github.com/lightningnetwork/lnd/htlcswitch/hop"
|
"github.com/lightningnetwork/lnd/htlcswitch/hop"
|
||||||
@@ -136,3 +138,12 @@ func (p *htlcPacket) keystone() Keystone {
|
|||||||
OutKey: p.outKey(),
|
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)
|
||||||
|
}
|
||||||
+10
-1
@@ -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
|
// If the source of this packet has not been set, use the circuit map
|
||||||
// to lookup the origin.
|
// to lookup the origin.
|
||||||
circuit, err := s.closeCircuit(packet)
|
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 {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
@@ -3005,7 +3014,7 @@ func (s *Switch) handlePacketSettle(packet *htlcPacket) error {
|
|||||||
// and when `UpdateFulfillHTLC` is received. After which `RevokeAndAck`
|
// and when `UpdateFulfillHTLC` is received. After which `RevokeAndAck`
|
||||||
// is received, which invokes `processRemoteSettleFails` in its link.
|
// is received, which invokes `processRemoteSettleFails` in its link.
|
||||||
if circuit == nil {
|
if circuit == nil {
|
||||||
log.Debugf("Found nil circuit: packet=%v", spew.Sdump(packet))
|
log.Debugf("Circuit already closed for packet=%v", packet)
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+4
-1
@@ -1710,7 +1710,7 @@ func (lc *LightningChannel) restorePendingRemoteUpdates(
|
|||||||
localCommitmentHeight uint64,
|
localCommitmentHeight uint64,
|
||||||
pendingRemoteCommit *commitment) error {
|
pendingRemoteCommit *commitment) error {
|
||||||
|
|
||||||
lc.log.Debugf("Restoring %v dangling remote updates",
|
lc.log.Debugf("Restoring %v dangling remote updates pending our sig",
|
||||||
len(unsignedAckedUpdates))
|
len(unsignedAckedUpdates))
|
||||||
|
|
||||||
for _, logUpdate := range unsignedAckedUpdates {
|
for _, logUpdate := range unsignedAckedUpdates {
|
||||||
@@ -1829,6 +1829,9 @@ func (lc *LightningChannel) restorePendingLocalUpdates(
|
|||||||
pendingCommit := pendingRemoteCommitDiff.Commitment
|
pendingCommit := pendingRemoteCommitDiff.Commitment
|
||||||
pendingHeight := pendingCommit.CommitHeight
|
pendingHeight := pendingCommit.CommitHeight
|
||||||
|
|
||||||
|
lc.log.Debugf("Restoring pending remote commitment %v at commit "+
|
||||||
|
"height %v", pendingCommit.CommitTx.TxHash(), pendingHeight)
|
||||||
|
|
||||||
auxResult, err := fn.MapOptionZ(
|
auxResult, err := fn.MapOptionZ(
|
||||||
lc.leafStore,
|
lc.leafStore,
|
||||||
func(s AuxLeafStore) fn.Result[CommitDiffAuxResult] {
|
func(s AuxLeafStore) fn.Result[CommitDiffAuxResult] {
|
||||||
|
|||||||
@@ -189,10 +189,21 @@ func (p *paymentLifecycle) resumePayment(ctx context.Context) ([32]byte,
|
|||||||
p.resultCollector(&a)
|
p.resultCollector(&a)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Get the payment status.
|
||||||
|
status := payment.GetStatus()
|
||||||
|
|
||||||
// exitWithErr is a helper closure that logs and returns an error.
|
// exitWithErr is a helper closure that logs and returns an error.
|
||||||
exitWithErr := func(err error) ([32]byte, *route.Route, error) {
|
exitWithErr := func(err error) ([32]byte, *route.Route, error) {
|
||||||
log.Errorf("Payment %v with status=%v failed: %v",
|
// Log an error with the latest payment status.
|
||||||
p.identifier, payment.GetStatus(), err)
|
//
|
||||||
|
// NOTE: this `status` variable is reassigned in the loop
|
||||||
|
// below. We could also call `payment.GetStatus` here, but in a
|
||||||
|
// rare case when the critical log is triggered when using
|
||||||
|
// postgres as db backend, the `payment` could be nil, causing
|
||||||
|
// the payment fetching to return an error.
|
||||||
|
log.Errorf("Payment %v with status=%v failed: %v", p.identifier,
|
||||||
|
status, err)
|
||||||
|
|
||||||
return [32]byte{}, nil, err
|
return [32]byte{}, nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -213,10 +224,10 @@ lifecycle:
|
|||||||
ps := payment.GetState()
|
ps := payment.GetState()
|
||||||
remainingFees := p.calcFeeBudget(ps.FeesPaid)
|
remainingFees := p.calcFeeBudget(ps.FeesPaid)
|
||||||
|
|
||||||
|
status = payment.GetStatus()
|
||||||
log.Debugf("Payment %v: status=%v, active_shards=%v, "+
|
log.Debugf("Payment %v: status=%v, active_shards=%v, "+
|
||||||
"rem_value=%v, fee_limit=%v", p.identifier,
|
"rem_value=%v, fee_limit=%v", p.identifier, status,
|
||||||
payment.GetStatus(), ps.NumAttemptsInFlight,
|
ps.NumAttemptsInFlight, ps.RemainingAmt, remainingFees)
|
||||||
ps.RemainingAmt, remainingFees)
|
|
||||||
|
|
||||||
// We now proceed our lifecycle with the following tasks in
|
// We now proceed our lifecycle with the following tasks in
|
||||||
// order,
|
// order,
|
||||||
|
|||||||
Reference in new issue
Block a user