mirror of
https://github.com/lightningnetwork/lnd.git
synced 2025-06-13 10:21:37 +02:00
invoices: fix deadlock in invoice registry
This commit is contained in:
parent
74c44da315
commit
c548a70e0d
@ -939,12 +939,18 @@ func (i *InvoiceRegistry) NotifyExitHopHtlc(rHash lntypes.Hash,
|
|||||||
|
|
||||||
// Execute locked notify exit hop logic.
|
// Execute locked notify exit hop logic.
|
||||||
i.Lock()
|
i.Lock()
|
||||||
resolution, err := i.notifyExitHopHtlcLocked(&ctx, hodlChan)
|
resolution, invoiceToExpire, err := i.notifyExitHopHtlcLocked(
|
||||||
|
&ctx, hodlChan,
|
||||||
|
)
|
||||||
i.Unlock()
|
i.Unlock()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if invoiceToExpire != nil {
|
||||||
|
i.expiryWatcher.AddInvoices(invoiceToExpire)
|
||||||
|
}
|
||||||
|
|
||||||
switch r := resolution.(type) {
|
switch r := resolution.(type) {
|
||||||
// The htlc is held. Start a timer outside the lock if the htlc should
|
// The htlc is held. Start a timer outside the lock if the htlc should
|
||||||
// be auto-released, because otherwise a deadlock may happen with the
|
// be auto-released, because otherwise a deadlock may happen with the
|
||||||
@ -975,10 +981,11 @@ func (i *InvoiceRegistry) NotifyExitHopHtlc(rHash lntypes.Hash,
|
|||||||
}
|
}
|
||||||
|
|
||||||
// notifyExitHopHtlcLocked is the internal implementation of NotifyExitHopHtlc
|
// notifyExitHopHtlcLocked is the internal implementation of NotifyExitHopHtlc
|
||||||
// that should be executed inside the registry lock.
|
// that should be executed inside the registry lock. The returned invoiceExpiry
|
||||||
|
// (if not nil) needs to be added to the expiry watcher outside of the lock.
|
||||||
func (i *InvoiceRegistry) notifyExitHopHtlcLocked(
|
func (i *InvoiceRegistry) notifyExitHopHtlcLocked(
|
||||||
ctx *invoiceUpdateCtx, hodlChan chan<- interface{}) (
|
ctx *invoiceUpdateCtx, hodlChan chan<- interface{}) (
|
||||||
HtlcResolution, error) {
|
HtlcResolution, invoiceExpiry, error) {
|
||||||
|
|
||||||
// We'll attempt to settle an invoice matching this rHash on disk (if
|
// We'll attempt to settle an invoice matching this rHash on disk (if
|
||||||
// one exists). The callback will update the invoice state and/or htlcs.
|
// one exists). The callback will update the invoice state and/or htlcs.
|
||||||
@ -1014,15 +1021,17 @@ func (i *InvoiceRegistry) notifyExitHopHtlcLocked(
|
|||||||
return NewFailResolution(
|
return NewFailResolution(
|
||||||
ctx.circuitKey, ctx.currentHeight,
|
ctx.circuitKey, ctx.currentHeight,
|
||||||
ResultInvoiceNotFound,
|
ResultInvoiceNotFound,
|
||||||
), nil
|
), nil, nil
|
||||||
|
|
||||||
case nil:
|
case nil:
|
||||||
|
|
||||||
default:
|
default:
|
||||||
ctx.log(err.Error())
|
ctx.log(err.Error())
|
||||||
return nil, err
|
return nil, nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var invoiceToExpire invoiceExpiry
|
||||||
|
|
||||||
switch res := resolution.(type) {
|
switch res := resolution.(type) {
|
||||||
case *HtlcFailResolution:
|
case *HtlcFailResolution:
|
||||||
// Inspect latest htlc state on the invoice. If it is found,
|
// Inspect latest htlc state on the invoice. If it is found,
|
||||||
@ -1116,7 +1125,7 @@ func (i *InvoiceRegistry) notifyExitHopHtlcLocked(
|
|||||||
case *htlcAcceptResolution:
|
case *htlcAcceptResolution:
|
||||||
invoiceHtlc, ok := invoice.Htlcs[ctx.circuitKey]
|
invoiceHtlc, ok := invoice.Htlcs[ctx.circuitKey]
|
||||||
if !ok {
|
if !ok {
|
||||||
return nil, fmt.Errorf("accepted htlc: %v not"+
|
return nil, nil, fmt.Errorf("accepted htlc: %v not"+
|
||||||
" present on invoice: %x", ctx.circuitKey,
|
" present on invoice: %x", ctx.circuitKey,
|
||||||
ctx.hash[:])
|
ctx.hash[:])
|
||||||
}
|
}
|
||||||
@ -1145,8 +1154,7 @@ func (i *InvoiceRegistry) notifyExitHopHtlcLocked(
|
|||||||
// possible that we MppTimeout the htlcs, and then our relevant
|
// possible that we MppTimeout the htlcs, and then our relevant
|
||||||
// expiry height could change.
|
// expiry height could change.
|
||||||
if res.outcome == resultAccepted {
|
if res.outcome == resultAccepted {
|
||||||
expiry := makeInvoiceExpiry(ctx.hash, invoice)
|
invoiceToExpire = makeInvoiceExpiry(ctx.hash, invoice)
|
||||||
i.expiryWatcher.AddInvoices(expiry)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
i.hodlSubscribe(hodlChan, ctx.circuitKey)
|
i.hodlSubscribe(hodlChan, ctx.circuitKey)
|
||||||
@ -1169,7 +1177,7 @@ func (i *InvoiceRegistry) notifyExitHopHtlcLocked(
|
|||||||
i.notifyClients(ctx.hash, invoice, setID)
|
i.notifyClients(ctx.hash, invoice, setID)
|
||||||
}
|
}
|
||||||
|
|
||||||
return resolution, nil
|
return resolution, invoiceToExpire, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// SettleHodlInvoice sets the preimage of a hodl invoice.
|
// SettleHodlInvoice sets the preimage of a hodl invoice.
|
||||||
|
Loading…
x
Reference in New Issue
Block a user