channeldb/invoice: fail extra HTLC sets immeidately
This commit is contained in:
parent
70efaa5fe2
commit
8402e346f5
@ -494,6 +494,31 @@ func (i *Invoice) HTLCSet(setID *[32]byte, state HtlcState) map[CircuitKey]*Invo
|
|||||||
return htlcSet
|
return htlcSet
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// HTLCSetCompliment returns the set of all HTLCs not belonging to setID that
|
||||||
|
// are in the target state. Passing a nil setID will return no invoices, since
|
||||||
|
// all MPP HTLCs are part of the same HTLC set.
|
||||||
|
func (i *Invoice) HTLCSetCompliment(setID *[32]byte,
|
||||||
|
state HtlcState) map[CircuitKey]*InvoiceHTLC {
|
||||||
|
|
||||||
|
htlcSet := make(map[CircuitKey]*InvoiceHTLC)
|
||||||
|
for key, htlc := range i.Htlcs {
|
||||||
|
// Only add HTLCs that are in the requested HtlcState.
|
||||||
|
if htlc.State != state {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
// We are constructing the compliment, so filter anything that
|
||||||
|
// matches this set id.
|
||||||
|
if htlc.IsInHTLCSet(setID) {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
htlcSet[key] = htlc
|
||||||
|
}
|
||||||
|
|
||||||
|
return htlcSet
|
||||||
|
}
|
||||||
|
|
||||||
// HtlcState defines the states an htlc paying to an invoice can be in.
|
// HtlcState defines the states an htlc paying to an invoice can be in.
|
||||||
type HtlcState uint8
|
type HtlcState uint8
|
||||||
|
|
||||||
|
@ -1063,6 +1063,23 @@ func (i *InvoiceRegistry) notifyExitHopHtlcLocked(
|
|||||||
i.notifyHodlSubscribers(htlcSettleResolution)
|
i.notifyHodlSubscribers(htlcSettleResolution)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// If concurrent payments were attempted to this invoice before
|
||||||
|
// the current one was ultimately settled, cancel back any of
|
||||||
|
// the HTLCs immediately. As a result of the settle, the HTLCs
|
||||||
|
// in other HTLC sets are automatically converted to a canceled
|
||||||
|
// state when updating the invoice.
|
||||||
|
canceledHtlcSet := invoice.HTLCSetCompliment(
|
||||||
|
setID, channeldb.HtlcStateCanceled,
|
||||||
|
)
|
||||||
|
for key, htlc := range canceledHtlcSet {
|
||||||
|
htlcFailResolution := NewFailResolution(
|
||||||
|
key, int32(htlc.AcceptHeight),
|
||||||
|
ResultInvoiceAlreadySettled,
|
||||||
|
)
|
||||||
|
|
||||||
|
i.notifyHodlSubscribers(htlcFailResolution)
|
||||||
|
}
|
||||||
|
|
||||||
// If we accepted the htlc, subscribe to the hodl invoice and return
|
// If we accepted the htlc, subscribe to the hodl invoice and return
|
||||||
// an accept resolution with the htlc's accept time on it.
|
// an accept resolution with the htlc's accept time on it.
|
||||||
case *htlcAcceptResolution:
|
case *htlcAcceptResolution:
|
||||||
|
@ -61,6 +61,10 @@ const (
|
|||||||
// invoice that is already canceled.
|
// invoice that is already canceled.
|
||||||
ResultInvoiceAlreadyCanceled
|
ResultInvoiceAlreadyCanceled
|
||||||
|
|
||||||
|
// ResultInvoiceAlreadySettled is returned when trying to pay an invoice
|
||||||
|
// that is already settled.
|
||||||
|
ResultInvoiceAlreadySettled
|
||||||
|
|
||||||
// ResultAmountTooLow is returned when an invoice is underpaid.
|
// ResultAmountTooLow is returned when an invoice is underpaid.
|
||||||
ResultAmountTooLow
|
ResultAmountTooLow
|
||||||
|
|
||||||
@ -133,6 +137,9 @@ func (f FailResolutionResult) FailureString() string {
|
|||||||
case ResultInvoiceAlreadyCanceled:
|
case ResultInvoiceAlreadyCanceled:
|
||||||
return "invoice already canceled"
|
return "invoice already canceled"
|
||||||
|
|
||||||
|
case ResultInvoiceAlreadySettled:
|
||||||
|
return "invoice alread settled"
|
||||||
|
|
||||||
case ResultAmountTooLow:
|
case ResultAmountTooLow:
|
||||||
return "amount too low"
|
return "amount too low"
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user