mirror of
https://github.com/lightningnetwork/lnd.git
synced 2024-11-19 01:43:16 +01:00
284 lines
11 KiB
Go
284 lines
11 KiB
Go
package invoices
|
|
|
|
import (
|
|
"context"
|
|
"time"
|
|
|
|
"github.com/btcsuite/btcd/chaincfg/chainhash"
|
|
"github.com/lightningnetwork/lnd/channeldb/models"
|
|
"github.com/lightningnetwork/lnd/lntypes"
|
|
"github.com/lightningnetwork/lnd/lnwire"
|
|
"github.com/lightningnetwork/lnd/record"
|
|
)
|
|
|
|
// InvoiceDB is the database that stores the information about invoices.
|
|
type InvoiceDB interface {
|
|
// AddInvoice inserts the targeted invoice into the database.
|
|
// If the invoice has *any* payment hashes which already exists within
|
|
// the database, then the insertion will be aborted and rejected due to
|
|
// the strict policy banning any duplicate payment hashes.
|
|
//
|
|
// NOTE: A side effect of this function is that it sets AddIndex on
|
|
// newInvoice.
|
|
AddInvoice(ctx context.Context, invoice *Invoice,
|
|
paymentHash lntypes.Hash) (uint64, error)
|
|
|
|
// InvoicesAddedSince can be used by callers to seek into the event
|
|
// time series of all the invoices added in the database. The specified
|
|
// sinceAddIndex should be the highest add index that the caller knows
|
|
// of. This method will return all invoices with an add index greater
|
|
// than the specified sinceAddIndex.
|
|
//
|
|
// NOTE: The index starts from 1, as a result. We enforce that
|
|
// specifying a value below the starting index value is a noop.
|
|
InvoicesAddedSince(ctx context.Context, sinceAddIndex uint64) (
|
|
[]Invoice, error)
|
|
|
|
// LookupInvoice attempts to look up an invoice according to its 32 byte
|
|
// payment hash. If an invoice which can settle the HTLC identified by
|
|
// the passed payment hash isn't found, then an error is returned.
|
|
// Otherwise, the full invoice is returned.
|
|
// Before setting the incoming HTLC, the values SHOULD be checked to
|
|
// ensure the payer meets the agreed upon contractual terms of the
|
|
// payment.
|
|
LookupInvoice(ctx context.Context, ref InvoiceRef) (Invoice, error)
|
|
|
|
// FetchPendingInvoices returns all invoices that have not yet been
|
|
// settled or canceled.
|
|
FetchPendingInvoices(ctx context.Context) (map[lntypes.Hash]Invoice,
|
|
error)
|
|
|
|
// QueryInvoices allows a caller to query the invoice database for
|
|
// invoices within the specified add index range.
|
|
QueryInvoices(ctx context.Context, q InvoiceQuery) (InvoiceSlice, error)
|
|
|
|
// UpdateInvoice attempts to update an invoice corresponding to the
|
|
// passed payment hash. If an invoice matching the passed payment hash
|
|
// doesn't exist within the database, then the action will fail with a
|
|
// "not found" error.
|
|
//
|
|
// The update is performed inside the same database transaction that
|
|
// fetches the invoice and is therefore atomic. The fields to update
|
|
// are controlled by the supplied callback.
|
|
//
|
|
// TODO(positiveblue): abstract this functionality so it makes sense for
|
|
// other backends like sql.
|
|
UpdateInvoice(ctx context.Context, ref InvoiceRef, setIDHint *SetID,
|
|
callback InvoiceUpdateCallback) (*Invoice, error)
|
|
|
|
// InvoicesSettledSince can be used by callers to catch up any settled
|
|
// invoices they missed within the settled invoice time series. We'll
|
|
// return all known settled invoice that have a settle index higher than
|
|
// the passed sinceSettleIndex.
|
|
//
|
|
// NOTE: The index starts from 1, as a result. We enforce that
|
|
// specifying a value below the starting index value is a noop.
|
|
InvoicesSettledSince(ctx context.Context, sinceSettleIndex uint64) (
|
|
[]Invoice, error)
|
|
|
|
// DeleteInvoice attempts to delete the passed invoices from the
|
|
// database in one transaction. The passed delete references hold all
|
|
// keys required to delete the invoices without also needing to
|
|
// deserialize them.
|
|
DeleteInvoice(ctx context.Context,
|
|
invoicesToDelete []InvoiceDeleteRef) error
|
|
|
|
// DeleteCanceledInvoices removes all canceled invoices from the
|
|
// database.
|
|
DeleteCanceledInvoices(ctx context.Context) error
|
|
}
|
|
|
|
// Payload abstracts access to any additional fields provided in the final hop's
|
|
// TLV onion payload.
|
|
type Payload interface {
|
|
// MultiPath returns the record corresponding the option_mpp parsed from
|
|
// the onion payload.
|
|
MultiPath() *record.MPP
|
|
|
|
// AMPRecord returns the record corresponding to the option_amp record
|
|
// parsed from the onion payload.
|
|
AMPRecord() *record.AMP
|
|
|
|
// CustomRecords returns the custom tlv type records that were parsed
|
|
// from the payload.
|
|
CustomRecords() record.CustomSet
|
|
|
|
// Metadata returns the additional data that is sent along with the
|
|
// payment to the payee.
|
|
Metadata() []byte
|
|
|
|
// PathID returns the path ID encoded in the payload of a blinded
|
|
// payment.
|
|
PathID() *chainhash.Hash
|
|
|
|
// TotalAmtMsat returns the total amount sent to the final hop, as set
|
|
// by the payee.
|
|
TotalAmtMsat() lnwire.MilliSatoshi
|
|
}
|
|
|
|
// InvoiceQuery represents a query to the invoice database. The query allows a
|
|
// caller to retrieve all invoices starting from a particular add index and
|
|
// limit the number of results returned.
|
|
type InvoiceQuery struct {
|
|
// IndexOffset is the offset within the add indices to start at. This
|
|
// can be used to start the response at a particular invoice.
|
|
IndexOffset uint64
|
|
|
|
// NumMaxInvoices is the maximum number of invoices that should be
|
|
// starting from the add index.
|
|
NumMaxInvoices uint64
|
|
|
|
// PendingOnly, if set, returns unsettled invoices starting from the
|
|
// add index.
|
|
PendingOnly bool
|
|
|
|
// Reversed, if set, indicates that the invoices returned should start
|
|
// from the IndexOffset and go backwards.
|
|
Reversed bool
|
|
|
|
// CreationDateStart, expressed in Unix seconds, if set, filters out
|
|
// all invoices with a creation date greater than or equal to it.
|
|
CreationDateStart int64
|
|
|
|
// CreationDateEnd, if set, filters out all invoices with a creation
|
|
// date less than or equal to it.
|
|
CreationDateEnd int64
|
|
}
|
|
|
|
// InvoiceSlice is the response to a invoice query. It includes the original
|
|
// query, the set of invoices that match the query, and an integer which
|
|
// represents the offset index of the last item in the set of returned invoices.
|
|
// This integer allows callers to resume their query using this offset in the
|
|
// event that the query's response exceeds the maximum number of returnable
|
|
// invoices.
|
|
type InvoiceSlice struct {
|
|
InvoiceQuery
|
|
|
|
// Invoices is the set of invoices that matched the query above.
|
|
Invoices []Invoice
|
|
|
|
// FirstIndexOffset is the index of the first element in the set of
|
|
// returned Invoices above. Callers can use this to resume their query
|
|
// in the event that the slice has too many events to fit into a single
|
|
// response.
|
|
FirstIndexOffset uint64
|
|
|
|
// LastIndexOffset is the index of the last element in the set of
|
|
// returned Invoices above. Callers can use this to resume their query
|
|
// in the event that the slice has too many events to fit into a single
|
|
// response.
|
|
LastIndexOffset uint64
|
|
}
|
|
|
|
// CircuitKey is a tuple of channel ID and HTLC ID, used to uniquely identify
|
|
// HTLCs in a circuit.
|
|
type CircuitKey = models.CircuitKey
|
|
|
|
// InvoiceUpdater is an interface to abstract away the details of updating an
|
|
// invoice in the database. The methods of this interface are called during the
|
|
// in-memory update of an invoice when the database needs to be updated or the
|
|
// updated state needs to be marked as needing to be written to the database.
|
|
type InvoiceUpdater interface {
|
|
// AddHtlc adds a new htlc to the invoice.
|
|
AddHtlc(circuitKey CircuitKey, newHtlc *InvoiceHTLC) error
|
|
|
|
// ResolveHtlc marks an htlc as resolved with the given state.
|
|
ResolveHtlc(circuitKey CircuitKey, state HtlcState,
|
|
resolveTime time.Time) error
|
|
|
|
// AddAmpHtlcPreimage adds a preimage of an AMP htlc to the AMP invoice
|
|
// identified by the setID.
|
|
AddAmpHtlcPreimage(setID [32]byte, circuitKey CircuitKey,
|
|
preimage lntypes.Preimage) error
|
|
|
|
// UpdateInvoiceState updates the invoice state to the new state.
|
|
UpdateInvoiceState(newState ContractState,
|
|
preimage *lntypes.Preimage) error
|
|
|
|
// UpdateInvoiceAmtPaid updates the invoice amount paid to the new
|
|
// amount.
|
|
UpdateInvoiceAmtPaid(amtPaid lnwire.MilliSatoshi) error
|
|
|
|
// UpdateAmpState updates the state of the AMP invoice identified by
|
|
// the setID.
|
|
UpdateAmpState(setID [32]byte, newState InvoiceStateAMP,
|
|
circuitKey models.CircuitKey) error
|
|
|
|
// Finalize finalizes the update before it is written to the database.
|
|
Finalize(updateType UpdateType) error
|
|
}
|
|
|
|
// HtlcModifyRequest is the request that is passed to the client via callback
|
|
// during a HTLC interceptor session. The request contains the invoice that the
|
|
// given HTLC is attempting to settle.
|
|
type HtlcModifyRequest struct {
|
|
// WireCustomRecords are the custom records that were parsed from the
|
|
// HTLC wire message. These are the records of the current HTLC to be
|
|
// accepted/settled. All previously accepted/settled HTLCs for the same
|
|
// invoice are present in the Invoice field below.
|
|
WireCustomRecords lnwire.CustomRecords
|
|
|
|
// ExitHtlcCircuitKey is the circuit key that identifies the HTLC which
|
|
// is involved in the invoice settlement.
|
|
ExitHtlcCircuitKey CircuitKey
|
|
|
|
// ExitHtlcAmt is the amount of the HTLC which is involved in the
|
|
// invoice settlement.
|
|
ExitHtlcAmt lnwire.MilliSatoshi
|
|
|
|
// ExitHtlcExpiry is the absolute expiry height of the HTLC which is
|
|
// involved in the invoice settlement.
|
|
ExitHtlcExpiry uint32
|
|
|
|
// CurrentHeight is the current block height.
|
|
CurrentHeight uint32
|
|
|
|
// Invoice is the invoice that is being intercepted. The HTLCs within
|
|
// the invoice are only those previously accepted/settled for the same
|
|
// invoice.
|
|
Invoice Invoice
|
|
}
|
|
|
|
// HtlcModifyResponse is the response that the client should send back to the
|
|
// interceptor after processing the HTLC modify request.
|
|
type HtlcModifyResponse struct {
|
|
// AmountPaid is the amount that the client has decided the HTLC is
|
|
// actually worth. This might be different from the amount that the
|
|
// HTLC was originally sent with, in case additional value is carried
|
|
// along with it (which might be the case in custom channels).
|
|
AmountPaid lnwire.MilliSatoshi
|
|
|
|
// CancelSet is a flag the interceptor client can set to force a
|
|
// cancellation of all HTLCs associated with the invoice that are
|
|
// currently accepted. Setting this field will ignore the AmountPaid
|
|
// field.
|
|
CancelSet bool
|
|
}
|
|
|
|
// HtlcModifyCallback is a function that is called when an invoice is
|
|
// intercepted by the invoice interceptor.
|
|
type HtlcModifyCallback func(HtlcModifyRequest) (*HtlcModifyResponse, error)
|
|
|
|
// HtlcModifier is an interface that allows an intercept client to register
|
|
// itself as a modifier of HTLCs that are settling an invoice. The client can
|
|
// then modify the HTLCs based on the invoice and the HTLC that is settling it.
|
|
type HtlcModifier interface {
|
|
// RegisterInterceptor sets the client callback function that will be
|
|
// called when an invoice is intercepted. If a callback is already set,
|
|
// an error is returned. The returned function must be used to reset the
|
|
// callback to nil once the client is done or disconnects. The read-only
|
|
// channel closes when the server stops.
|
|
RegisterInterceptor(HtlcModifyCallback) (func(), <-chan struct{}, error)
|
|
}
|
|
|
|
// HtlcInterceptor is an interface that allows the invoice registry to let
|
|
// clients intercept invoices before they are settled.
|
|
type HtlcInterceptor interface {
|
|
// Intercept generates a new intercept session for the given invoice.
|
|
// The call blocks until the client has responded to the request or an
|
|
// error occurs. The response callback is only called if a session was
|
|
// created in the first place, which is only the case if a client is
|
|
// registered.
|
|
Intercept(HtlcModifyRequest, func(HtlcModifyResponse)) error
|
|
}
|