diff --git a/invoices/invoiceregistry.go b/invoices/invoiceregistry.go index 7f62ae45..00885edb 100644 --- a/invoices/invoiceregistry.go +++ b/invoices/invoiceregistry.go @@ -565,7 +565,7 @@ func (i *InvoiceRegistry) startHtlcTimer(hash lntypes.Hash, // a resolution result which will be used to notify subscribed links and // resolvers of the details of the htlc cancellation. func (i *InvoiceRegistry) cancelSingleHtlc(hash lntypes.Hash, - key channeldb.CircuitKey, result ResolutionResult) error { + key channeldb.CircuitKey, result FailResolutionResult) error { i.Lock() defer i.Unlock() diff --git a/invoices/resolution.go b/invoices/resolution.go index 483a5777..e6f31330 100644 --- a/invoices/resolution.go +++ b/invoices/resolution.go @@ -23,13 +23,13 @@ type HtlcFailResolution struct { // AcceptHeight is the original height at which the htlc was accepted. AcceptHeight int32 - // outcome indicates the outcome of the invoice registry update. - Outcome ResolutionResult + // Outcome indicates the outcome of the invoice registry update. + Outcome FailResolutionResult } // NewFailResolution returns a htlc failure resolution. func NewFailResolution(key channeldb.CircuitKey, - acceptHeight int32, outcome ResolutionResult) *HtlcFailResolution { + acceptHeight int32, outcome FailResolutionResult) *HtlcFailResolution { return &HtlcFailResolution{ circuitKey: key, @@ -59,13 +59,14 @@ type HtlcSettleResolution struct { AcceptHeight int32 // Outcome indicates the outcome of the invoice registry update. - Outcome ResolutionResult + Outcome SettleResolutionResult } // NewSettleResolution returns a htlc resolution which is associated with a // settle. -func NewSettleResolution(preimage lntypes.Preimage, key channeldb.CircuitKey, - acceptHeight int32, outcome ResolutionResult) *HtlcSettleResolution { +func NewSettleResolution(preimage lntypes.Preimage, + key channeldb.CircuitKey, acceptHeight int32, + outcome SettleResolutionResult) *HtlcSettleResolution { return &HtlcSettleResolution{ Preimage: preimage, @@ -101,13 +102,13 @@ type htlcAcceptResolution struct { acceptTime time.Time // outcome indicates the outcome of the invoice registry update. - outcome ResolutionResult + outcome acceptResolutionResult } // newAcceptResolution returns a htlc resolution which is associated with a // htlc accept. func newAcceptResolution(key channeldb.CircuitKey, - outcome ResolutionResult) *htlcAcceptResolution { + outcome acceptResolutionResult) *htlcAcceptResolution { return &htlcAcceptResolution{ circuitKey: key, diff --git a/invoices/resolution_result.go b/invoices/resolution_result.go new file mode 100644 index 00000000..3952d11a --- /dev/null +++ b/invoices/resolution_result.go @@ -0,0 +1,200 @@ +package invoices + +// acceptResolutionResult provides metadata which about a htlc that was +// accepted by the registry. +type acceptResolutionResult uint8 + +const ( + resultInvalidAccept acceptResolutionResult = iota + + // resultReplayToAccepted is returned when we replay an accepted + // invoice. + resultReplayToAccepted + + // resultDuplicateToAccepted is returned when we accept a duplicate + // htlc. + resultDuplicateToAccepted + + // resultAccepted is returned when we accept a hodl invoice. + resultAccepted + + // resultPartialAccepted is returned when we have partially received + // payment. + resultPartialAccepted +) + +// String returns a string representation of the result. +func (a acceptResolutionResult) String() string { + switch a { + case resultInvalidAccept: + return "invalid accept result" + + case resultReplayToAccepted: + return "replayed htlc to accepted invoice" + + case resultDuplicateToAccepted: + return "accepting duplicate payment to accepted invoice" + + case resultAccepted: + return "accepted" + + case resultPartialAccepted: + return "partial payment accepted" + + default: + return "unknown accept resolution result" + } +} + +// FailResolutionResult provides metadata about a htlc that was failed by +// the registry. It can be used to take custom actions on resolution of the +// htlc. +type FailResolutionResult uint8 + +const ( + resultInvalidFailure FailResolutionResult = iota + + // ResultReplayToCanceled is returned when we replay a canceled invoice. + ResultReplayToCanceled + + // ResultInvoiceAlreadyCanceled is returned when trying to pay an + // invoice that is already canceled. + ResultInvoiceAlreadyCanceled + + // ResultAmountTooLow is returned when an invoice is underpaid. + ResultAmountTooLow + + // ResultExpiryTooSoon is returned when we do not accept an invoice + // payment because it expires too soon. + ResultExpiryTooSoon + + // ResultCanceled is returned when we cancel an invoice and its + // associated htlcs. + ResultCanceled + + // ResultInvoiceNotOpen is returned when a mpp invoice is not open. + ResultInvoiceNotOpen + + // ResultMppTimeout is returned when an invoice paid with multiple + // partial payments times out before it is fully paid. + ResultMppTimeout + + // ResultAddressMismatch is returned when the payment address for a mpp + // invoice does not match. + ResultAddressMismatch + + // ResultHtlcSetTotalMismatch is returned when the amount paid by a + // htlc does not match its set total. + ResultHtlcSetTotalMismatch + + // ResultHtlcSetTotalTooLow is returned when a mpp set total is too low + // for an invoice. + ResultHtlcSetTotalTooLow + + // ResultHtlcSetOverpayment is returned when a mpp set is overpaid. + ResultHtlcSetOverpayment + + // ResultInvoiceNotFound is returned when an attempt is made to pay an + // invoice that is unknown to us. + ResultInvoiceNotFound + + // ResultKeySendError is returned when we receive invalid keysend + // parameters. + ResultKeySendError + + // ResultMppInProgress is returned when we are busy receiving a mpp + // payment. + ResultMppInProgress +) + +// String returns a string representation of the result. +func (f FailResolutionResult) String() string { + switch f { + case resultInvalidFailure: + return "invalid failure result" + + case ResultReplayToCanceled: + return "replayed htlc to canceled invoice" + + case ResultInvoiceAlreadyCanceled: + return "invoice already canceled" + + case ResultAmountTooLow: + return "amount too low" + + case ResultExpiryTooSoon: + return "expiry too soon" + + case ResultCanceled: + return "canceled" + + case ResultInvoiceNotOpen: + return "invoice no longer open" + + case ResultMppTimeout: + return "mpp timeout" + + case ResultAddressMismatch: + return "payment address mismatch" + + case ResultHtlcSetTotalMismatch: + return "htlc total amt doesn't match set total" + + case ResultHtlcSetTotalTooLow: + return "set total too low for invoice" + + case ResultHtlcSetOverpayment: + return "mpp is overpaying set total" + + case ResultInvoiceNotFound: + return "invoice not found" + + case ResultKeySendError: + return "invalid keysend parameters" + + case ResultMppInProgress: + return "mpp reception in progress" + + default: + return "unknown failure resolution result" + } +} + +// SettleResolutionResult provides metadata which about a htlc that was failed +// by the registry. It can be used to take custom actions on resolution of the +// htlc. +type SettleResolutionResult uint8 + +const ( + resultInvalidSettle SettleResolutionResult = iota + + // ResultSettled is returned when we settle an invoice. + ResultSettled + + // ResultReplayToSettled is returned when we replay a settled invoice. + ResultReplayToSettled + + // ResultDuplicateToSettled is returned when we settle an invoice which + // has already been settled at least once. + ResultDuplicateToSettled +) + +// String returns a string representation of the result. +func (s SettleResolutionResult) String() string { + switch s { + case resultInvalidSettle: + return "invalid settle result" + + case ResultSettled: + return "settled" + + case ResultReplayToSettled: + return "replayed htlc to settled invoice" + + case ResultDuplicateToSettled: + return "accepting duplicate payment to settled invoice" + + default: + return "unknown settle resolution result" + } +} diff --git a/invoices/update.go b/invoices/update.go index c747521e..3226779c 100644 --- a/invoices/update.go +++ b/invoices/update.go @@ -9,164 +9,6 @@ import ( "github.com/lightningnetwork/lnd/record" ) -// ResolutionResult provides metadata which about an invoice update which can -// be used to take custom actions on resolution of the htlc. Only results which -// are actionable by the link are exported. -type ResolutionResult uint8 - -const ( - resultInvalid ResolutionResult = iota - - // ResultReplayToCanceled is returned when we replay a canceled invoice. - ResultReplayToCanceled - - // ResultReplayToAccepted is returned when we replay an accepted invoice. - ResultReplayToAccepted - - // ResultReplayToSettled is returned when we replay a settled invoice. - ResultReplayToSettled - - // ResultInvoiceAlreadyCanceled is returned when trying to pay an invoice - // that is already canceled. - ResultInvoiceAlreadyCanceled - - // ResultAmountTooLow is returned when an invoice is underpaid. - ResultAmountTooLow - - // ResultExpiryTooSoon is returned when we do not accept an invoice payment - // because it expires too soon. - ResultExpiryTooSoon - - // ResultDuplicateToAccepted is returned when we accept a duplicate htlc. - ResultDuplicateToAccepted - - // ResultDuplicateToSettled is returned when we settle an invoice which has - // already been settled at least once. - ResultDuplicateToSettled - - // ResultAccepted is returned when we accept a hodl invoice. - ResultAccepted - - // ResultSettled is returned when we settle an invoice. - ResultSettled - - // ResultCanceled is returned when we cancel an invoice and its associated - // htlcs. - ResultCanceled - - // ResultInvoiceNotOpen is returned when a mpp invoice is not open. - ResultInvoiceNotOpen - - // ResultPartialAccepted is returned when we have partially received - // payment. - ResultPartialAccepted - - // ResultMppInProgress is returned when we are busy receiving a mpp payment. - ResultMppInProgress - - // ResultMppTimeout is returned when an invoice paid with multiple partial - // payments times out before it is fully paid. - ResultMppTimeout - - // ResultAddressMismatch is returned when the payment address for a mpp - // invoice does not match. - ResultAddressMismatch - - // ResultHtlcSetTotalMismatch is returned when the amount paid by a htlc - // does not match its set total. - ResultHtlcSetTotalMismatch - - // ResultHtlcSetTotalTooLow is returned when a mpp set total is too low for - // an invoice. - ResultHtlcSetTotalTooLow - - // ResultHtlcSetOverpayment is returned when a mpp set is overpaid. - ResultHtlcSetOverpayment - - // ResultInvoiceNotFound is returned when an attempt is made to pay an - // invoice that is unknown to us. - ResultInvoiceNotFound - - // ResultKeySendError is returned when we receive invalid keysend - // parameters. - ResultKeySendError -) - -// String returns a human-readable representation of the invoice update result. -func (u ResolutionResult) String() string { - switch u { - - case resultInvalid: - return "invalid" - - case ResultReplayToCanceled: - return "replayed htlc to canceled invoice" - - case ResultReplayToAccepted: - return "replayed htlc to accepted invoice" - - case ResultReplayToSettled: - return "replayed htlc to settled invoice" - - case ResultInvoiceAlreadyCanceled: - return "invoice already canceled" - - case ResultAmountTooLow: - return "amount too low" - - case ResultExpiryTooSoon: - return "expiry too soon" - - case ResultDuplicateToAccepted: - return "accepting duplicate payment to accepted invoice" - - case ResultDuplicateToSettled: - return "accepting duplicate payment to settled invoice" - - case ResultAccepted: - return "accepted" - - case ResultSettled: - return "settled" - - case ResultCanceled: - return "canceled" - - case ResultInvoiceNotOpen: - return "invoice no longer open" - - case ResultPartialAccepted: - return "partial payment accepted" - - case ResultMppInProgress: - return "mpp reception in progress" - - case ResultMppTimeout: - return "mpp timeout" - - case ResultAddressMismatch: - return "payment address mismatch" - - case ResultHtlcSetTotalMismatch: - return "htlc total amt doesn't match set total" - - case ResultHtlcSetTotalTooLow: - return "set total too low for invoice" - - case ResultHtlcSetOverpayment: - return "mpp is overpaying set total" - - case ResultKeySendError: - return "invalid keysend parameters" - - case ResultInvoiceNotFound: - return "invoice not found" - - default: - return "unknown" - } -} - // invoiceUpdateCtx is an object that describes the context for the invoice // update to be carried out. type invoiceUpdateCtx struct { @@ -187,16 +29,17 @@ func (i *invoiceUpdateCtx) log(s string) { } // failRes is a helper function which creates a failure resolution with -// the information contained in the invoiceUpdateCtx and the outcome provided. -func (i invoiceUpdateCtx) failRes(outcome ResolutionResult) *HtlcFailResolution { +// the information contained in the invoiceUpdateCtx and the fail resolution +// result provided. +func (i invoiceUpdateCtx) failRes(outcome FailResolutionResult) *HtlcFailResolution { return NewFailResolution(i.circuitKey, i.currentHeight, outcome) } // settleRes is a helper function which creates a settle resolution with // the information contained in the invoiceUpdateCtx and the preimage and -// outcome provided. +// the settle resolution result provided. func (i invoiceUpdateCtx) settleRes(preimage lntypes.Preimage, - outcome ResolutionResult) *HtlcSettleResolution { + outcome SettleResolutionResult) *HtlcSettleResolution { return NewSettleResolution( preimage, i.circuitKey, i.currentHeight, outcome, @@ -204,8 +47,9 @@ func (i invoiceUpdateCtx) settleRes(preimage lntypes.Preimage, } // acceptRes is a helper function which creates an accept resolution with -// the information contained in the invoiceUpdateCtx and the outcome provided. -func (i invoiceUpdateCtx) acceptRes(outcome ResolutionResult) *htlcAcceptResolution { +// the information contained in the invoiceUpdateCtx and the accept resolution +// result provided. +func (i invoiceUpdateCtx) acceptRes(outcome acceptResolutionResult) *htlcAcceptResolution { return newAcceptResolution(i.circuitKey, outcome) } @@ -223,7 +67,7 @@ func updateInvoice(ctx *invoiceUpdateCtx, inv *channeldb.Invoice) ( return nil, ctx.failRes(ResultReplayToCanceled), nil case channeldb.HtlcStateAccepted: - return nil, ctx.acceptRes(ResultReplayToAccepted), nil + return nil, ctx.acceptRes(resultReplayToAccepted), nil case channeldb.HtlcStateSettled: return nil, ctx.settleRes( @@ -328,7 +172,7 @@ func updateMpp(ctx *invoiceUpdateCtx, // If the invoice cannot be settled yet, only record the htlc. setComplete := newSetTotal == ctx.mpp.TotalMsat() if !setComplete { - return &update, ctx.acceptRes(ResultPartialAccepted), nil + return &update, ctx.acceptRes(resultPartialAccepted), nil } // Check to see if we can settle or this is an hold invoice and @@ -338,7 +182,7 @@ func updateMpp(ctx *invoiceUpdateCtx, update.State = &channeldb.InvoiceStateUpdateDesc{ NewState: channeldb.ContractAccepted, } - return &update, ctx.acceptRes(ResultAccepted), nil + return &update, ctx.acceptRes(resultAccepted), nil } update.State = &channeldb.InvoiceStateUpdateDesc{ @@ -411,7 +255,7 @@ func updateLegacy(ctx *invoiceUpdateCtx, // We do accept or settle the HTLC. switch inv.State { case channeldb.ContractAccepted: - return &update, ctx.acceptRes(ResultDuplicateToAccepted), nil + return &update, ctx.acceptRes(resultDuplicateToAccepted), nil case channeldb.ContractSettled: return &update, ctx.settleRes( @@ -427,7 +271,7 @@ func updateLegacy(ctx *invoiceUpdateCtx, NewState: channeldb.ContractAccepted, } - return &update, ctx.acceptRes(ResultAccepted), nil + return &update, ctx.acceptRes(resultAccepted), nil } update.State = &channeldb.InvoiceStateUpdateDesc{