invoices

package
v0.17.4-beta.rc1 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Jan 30, 2024 License: MIT Imports: 28 Imported by: 0

Documentation

Index

Constants

View Source
const (
	// MaxMemoSize is maximum size of the memo field within invoices stored
	// in the database.
	MaxMemoSize = 1024

	// MaxPaymentRequestSize is the max size of a payment request for
	// this invoice.
	// TODO(halseth): determine the max length payment request when field
	// lengths are final.
	MaxPaymentRequestSize = 4096
)
View Source
const (
	// DefaultHtlcHoldDuration defines the default for how long mpp htlcs
	// are held while waiting for the other set members to arrive.
	DefaultHtlcHoldDuration = 120 * time.Second
)

Variables

View Source
var (
	// ErrInvoiceAlreadySettled is returned when the invoice is already
	// settled.
	ErrInvoiceAlreadySettled = errors.New("invoice already settled")

	// ErrInvoiceAlreadyCanceled is returned when the invoice is already
	// canceled.
	ErrInvoiceAlreadyCanceled = errors.New("invoice already canceled")

	// ErrInvoiceAlreadyAccepted is returned when the invoice is already
	// accepted.
	ErrInvoiceAlreadyAccepted = errors.New("invoice already accepted")

	// ErrInvoiceStillOpen is returned when the invoice is still open.
	ErrInvoiceStillOpen = errors.New("invoice still open")

	// ErrInvoiceCannotOpen is returned when an attempt is made to move an
	// invoice to the open state.
	ErrInvoiceCannotOpen = errors.New("cannot move invoice to open")

	// ErrInvoiceCannotAccept is returned when an attempt is made to accept
	// an invoice while the invoice is not in the open state.
	ErrInvoiceCannotAccept = errors.New("cannot accept invoice")

	// ErrInvoicePreimageMismatch is returned when the preimage doesn't
	// match the invoice hash.
	ErrInvoicePreimageMismatch = errors.New("preimage does not match")

	// ErrHTLCPreimageMissing is returned when trying to accept/settle an
	// AMP HTLC but the HTLC-level preimage has not been set.
	ErrHTLCPreimageMissing = errors.New("AMP htlc missing preimage")

	// ErrHTLCPreimageMismatch is returned when trying to accept/settle an
	// AMP HTLC but the HTLC-level preimage does not satisfying the
	// HTLC-level payment hash.
	ErrHTLCPreimageMismatch = errors.New("htlc preimage mismatch")

	// ErrHTLCAlreadySettled is returned when trying to settle an invoice
	// but HTLC already exists in the settled state.
	ErrHTLCAlreadySettled = errors.New("htlc already settled")

	// ErrInvoiceHasHtlcs is returned when attempting to insert an invoice
	// that already has HTLCs.
	ErrInvoiceHasHtlcs = errors.New("cannot add invoice with htlcs")

	// ErrEmptyHTLCSet is returned when attempting to accept or settle and
	// HTLC set that has no HTLCs.
	ErrEmptyHTLCSet = errors.New("cannot settle/accept empty HTLC set")

	// ErrUnexpectedInvoicePreimage is returned when an invoice-level
	// preimage is provided when trying to settle an invoice that shouldn't
	// have one, e.g. an AMP invoice.
	ErrUnexpectedInvoicePreimage = errors.New(
		"unexpected invoice preimage provided on settle",
	)

	// ErrHTLCPreimageAlreadyExists is returned when trying to set an
	// htlc-level preimage but one is already known.
	ErrHTLCPreimageAlreadyExists = errors.New(
		"htlc-level preimage already exists",
	)

	// ErrInvoiceNotFound is returned when a targeted invoice can't be
	// found.
	ErrInvoiceNotFound = errors.New("unable to locate invoice")

	// ErrNoInvoicesCreated is returned when we don't have invoices in
	// our database to return.
	ErrNoInvoicesCreated = errors.New("there are no existing invoices")

	// ErrDuplicateInvoice is returned when an invoice with the target
	// payment hash already exists.
	ErrDuplicateInvoice = errors.New(
		"invoice with payment hash already exists",
	)

	// ErrDuplicatePayAddr is returned when an invoice with the target
	// payment addr already exists.
	ErrDuplicatePayAddr = errors.New(
		"invoice with payemnt addr already exists",
	)

	// ErrInvRefEquivocation is returned when an InvoiceRef targets
	// multiple, distinct invoices.
	ErrInvRefEquivocation = errors.New("inv ref matches multiple invoices")

	// ErrNoPaymentsCreated is returned when bucket of payments hasn't been
	// created.
	ErrNoPaymentsCreated = errors.New("there are no existing payments")
)
View Source
var (
	// ErrInvoiceExpiryTooSoon is returned when an invoice is attempted to
	// be accepted or settled with not enough blocks remaining.
	ErrInvoiceExpiryTooSoon = errors.New("invoice expiry too soon")

	// ErrInvoiceAmountTooLow is returned  when an invoice is attempted to
	// be accepted or settled with an amount that is too low.
	ErrInvoiceAmountTooLow = errors.New(
		"paid amount less than invoice amount",
	)

	// ErrShuttingDown is returned when an operation failed because the
	// invoice registry is shutting down.
	ErrShuttingDown = errors.New("invoice registry shutting down")
)
View Source
var (
	// unknownPreimage is an all-zeroes preimage that indicates that the
	// preimage for this invoice is not yet known.
	UnknownPreimage lntypes.Preimage

	// BlankPayAddr is a sentinel payment address for legacy invoices.
	// Invoices with this payment address are special-cased in the insertion
	// logic to prevent being indexed in the payment address index,
	// otherwise they would cause collisions after the first insertion.
	BlankPayAddr [32]byte
)

Functions

func DisableLog

func DisableLog()

DisableLog disables all library log output. Logging output is disabled by default until UseLogger is called.

func UseLogger

func UseLogger(logger btclog.Logger)

UseLogger uses a specified Logger to output package logging info. This should be used in preference to SetLogWriter if the caller is also using btclog.

func ValidateInvoice

func ValidateInvoice(i *Invoice, paymentHash lntypes.Hash) error

ValidateInvoice assures the invoice passes the checks for all the relevant constraints.

Types

type AMPInvoiceState

type AMPInvoiceState map[SetID]InvoiceStateAMP

AMPInvoiceState represents a type that stores metadata related to the set of settled AMP "sub-invoices".

type CircuitKey

type CircuitKey = models.CircuitKey

CircuitKey is a tuple of channel ID and HTLC ID, used to uniquely identify HTLCs in a circuit.

type ContractState

type ContractState uint8

ContractState describes the state the invoice is in.

const (
	// ContractOpen means the invoice has only been created.
	ContractOpen ContractState = 0

	// ContractSettled means the htlc is settled and the invoice has been
	// paid.
	ContractSettled ContractState = 1

	// ContractCanceled means the invoice has been canceled.
	ContractCanceled ContractState = 2

	// ContractAccepted means the HTLC has been accepted but not settled
	// yet.
	ContractAccepted ContractState = 3
)

func (ContractState) IsFinal

func (c ContractState) IsFinal() bool

IsFinal returns a boolean indicating whether an invoice state is final.

func (ContractState) String

func (c ContractState) String() string

String returns a human readable identifier for the ContractState type.

type ContractTerm

type ContractTerm struct {
	// FinalCltvDelta is the minimum required number of blocks before htlc
	// expiry when the invoice is accepted.
	FinalCltvDelta int32

	// Expiry defines how long after creation this invoice should expire.
	Expiry time.Duration

	// PaymentPreimage is the preimage which is to be revealed in the
	// occasion that an HTLC paying to the hash of this preimage is
	// extended. Set to nil if the preimage isn't known yet.
	PaymentPreimage *lntypes.Preimage

	// Value is the expected amount of milli-satoshis to be paid to an HTLC
	// which can be satisfied by the above preimage.
	Value lnwire.MilliSatoshi

	// PaymentAddr is a randomly generated value include in the MPP record
	// by the sender to prevent probing of the receiver.
	PaymentAddr [32]byte

	// Features is the feature vectors advertised on the payment request.
	Features *lnwire.FeatureVector
}

ContractTerm is a companion struct to the Invoice struct. This struct houses the necessary conditions required before the invoice can be considered fully settled by the payee.

func (ContractTerm) String

func (c ContractTerm) String() string

String returns a human-readable description of the prominent contract terms.

type ErrDuplicateSetID

type ErrDuplicateSetID struct {
	SetID [32]byte
}

ErrDuplicateSetID is an error returned when attempting to adding an AMP HTLC to an invoice, but another invoice is already indexed by the same set id.

func (ErrDuplicateSetID) Error

func (e ErrDuplicateSetID) Error() string

Error returns a human-readable description of ErrDuplicateSetID.

type FailResolutionResult

type FailResolutionResult uint8

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.

const (

	// ResultReplayToCanceled is returned when we replay a canceled invoice.
	ResultReplayToCanceled FailResolutionResult

	// ResultInvoiceAlreadyCanceled is returned when trying to pay an
	// invoice that is already canceled.
	ResultInvoiceAlreadyCanceled

	// ResultInvoiceAlreadySettled is returned when trying to pay an invoice
	// that is already settled.
	ResultInvoiceAlreadySettled

	// 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

	// ResultHtlcInvoiceTypeMismatch is returned when an AMP HTLC targets a
	// non-AMP invoice and vice versa.
	ResultHtlcInvoiceTypeMismatch

	// ResultAmpError is returned when we receive invalid AMP parameters.
	ResultAmpError

	// ResultAmpReconstruction is returned when the derived child
	// hash/preimage pairs were invalid for at least one HTLC in the set.
	ResultAmpReconstruction
)

func (FailResolutionResult) FailureString

func (f FailResolutionResult) FailureString() string

FailureString returns a string representation of the result.

Note: it is part of the FailureDetail interface.

func (FailResolutionResult) IsSetFailure

func (f FailResolutionResult) IsSetFailure() bool

IsSetFailure returns true if this failure should result in the entire HTLC set being failed with the same result.

func (FailResolutionResult) String

func (f FailResolutionResult) String() string

String returns a string representation of the result.

type HTLCPreimages

type HTLCPreimages = map[CircuitKey]lntypes.Preimage

HTLCPreimages is a map of CircuitKey to preimage.

type HTLCSet

type HTLCSet = map[CircuitKey]*InvoiceHTLC

HTLCSet is a map of CircuitKey to InvoiceHTLC.

type HtlcAcceptDesc

type HtlcAcceptDesc struct {
	// AcceptHeight is the block height at which this htlc was accepted.
	AcceptHeight int32

	// Amt is the amount that is carried by this htlc.
	Amt lnwire.MilliSatoshi

	// MppTotalAmt is a field for mpp that indicates the expected total
	// amount.
	MppTotalAmt lnwire.MilliSatoshi

	// Expiry is the expiry height of this htlc.
	Expiry uint32

	// CustomRecords contains the custom key/value pairs that accompanied
	// the htlc.
	CustomRecords record.CustomSet

	// AMP encapsulates additional data relevant to AMP HTLCs. This includes
	// the AMP onion record, in addition to the HTLC's payment hash and
	// preimage since these are unique to each AMP HTLC, and not the invoice
	// as a whole.
	//
	// NOTE: This value will only be set for AMP HTLCs.
	AMP *InvoiceHtlcAMPData
}

HtlcAcceptDesc describes the details of a newly accepted htlc.

type HtlcFailResolution

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 FailResolutionResult
	// contains filtered or unexported fields
}

HtlcFailResolution is an implementation of the HtlcResolution interface which is returned when a htlc is failed.

func NewFailResolution

func NewFailResolution(key CircuitKey, acceptHeight int32,
	outcome FailResolutionResult) *HtlcFailResolution

NewFailResolution returns a htlc failure resolution.

func (*HtlcFailResolution) CircuitKey

func (f *HtlcFailResolution) CircuitKey() CircuitKey

CircuitKey returns the circuit key for the htlc that we have a resolution for.

Note: it is part of the HtlcResolution interface.

type HtlcResolution

type HtlcResolution interface {
	// CircuitKey returns the circuit key for the htlc that we have a
	// resolution for.
	CircuitKey() CircuitKey
}

HtlcResolution describes how an htlc should be resolved.

type HtlcSettleResolution

type HtlcSettleResolution struct {
	// Preimage is the htlc preimage. Its value is nil in case of a cancel.
	Preimage lntypes.Preimage

	// acceptHeight is the original height at which the htlc was accepted.
	AcceptHeight int32

	// Outcome indicates the outcome of the invoice registry update.
	Outcome SettleResolutionResult
	// contains filtered or unexported fields
}

HtlcSettleResolution is an implementation of the HtlcResolution interface which is returned when a htlc is settled.

func NewSettleResolution

func NewSettleResolution(preimage lntypes.Preimage, key CircuitKey,
	acceptHeight int32,
	outcome SettleResolutionResult) *HtlcSettleResolution

NewSettleResolution returns a htlc resolution which is associated with a settle.

func (*HtlcSettleResolution) CircuitKey

func (s *HtlcSettleResolution) CircuitKey() CircuitKey

CircuitKey returns the circuit key for the htlc that we have a resolution for.

Note: it is part of the HtlcResolution interface.

type HtlcState

type HtlcState uint8

HtlcState defines the states an htlc paying to an invoice can be in.

const (
	// HtlcStateAccepted indicates the htlc is locked-in, but not resolved.
	HtlcStateAccepted HtlcState = iota

	// HtlcStateCanceled indicates the htlc is canceled back to the
	// sender.
	HtlcStateCanceled

	// HtlcStateSettled indicates the htlc is settled.
	HtlcStateSettled
)

type InvScanFunc

type InvScanFunc func(lntypes.Hash, *Invoice) error

InvScanFunc is a helper type used to specify the type used in the ScanInvoices methods (part of the InvoiceDB interface).

type Invoice

type Invoice struct {
	// Memo is an optional memo to be stored along side an invoice.  The
	// memo may contain further details pertaining to the invoice itself,
	// or any other message which fits within the size constraints.
	Memo []byte

	// PaymentRequest is the encoded payment request for this invoice. For
	// spontaneous (keysend) payments, this field will be empty.
	PaymentRequest []byte

	// CreationDate is the exact time the invoice was created.
	CreationDate time.Time

	// SettleDate is the exact time the invoice was settled.
	SettleDate time.Time

	// Terms are the contractual payment terms of the invoice. Once all the
	// terms have been satisfied by the payer, then the invoice can be
	// considered fully fulfilled.
	//
	// TODO(roasbeef): later allow for multiple terms to fulfill the final
	// invoice: payment fragmentation, etc.
	Terms ContractTerm

	// AddIndex is an auto-incrementing integer that acts as a
	// monotonically increasing sequence number for all invoices created.
	// Clients can then use this field as a "checkpoint" of sorts when
	// implementing a streaming RPC to notify consumers of instances where
	// an invoice has been added before they re-connected.
	//
	// NOTE: This index starts at 1.
	AddIndex uint64

	// SettleIndex is an auto-incrementing integer that acts as a
	// monotonically increasing sequence number for all settled invoices.
	// Clients can then use this field as a "checkpoint" of sorts when
	// implementing a streaming RPC to notify consumers of instances where
	// an invoice has been settled before they re-connected.
	//
	// NOTE: This index starts at 1.
	SettleIndex uint64

	// State describes the state the invoice is in. This is the global
	// state of the invoice which may remain open even when a series of
	// sub-invoices for this invoice has been settled.
	State ContractState

	// AmtPaid is the final amount that we ultimately accepted for pay for
	// this invoice. We specify this value independently as it's possible
	// that the invoice originally didn't specify an amount, or the sender
	// overpaid.
	AmtPaid lnwire.MilliSatoshi

	// Htlcs records all htlcs that paid to this invoice. Some of these
	// htlcs may have been marked as canceled.
	Htlcs map[CircuitKey]*InvoiceHTLC

	// AMPState describes the state of any related sub-invoices AMP to this
	// greater invoice. A sub-invoice is defined by a set of HTLCs with the
	// same set ID that attempt to make one time or recurring payments to
	// this greater invoice. It's possible for a sub-invoice to be canceled
	// or settled, but the greater invoice still open.
	AMPState AMPInvoiceState

	// HodlInvoice indicates whether the invoice should be held in the
	// Accepted state or be settled right away.
	HodlInvoice bool
}

Invoice is a payment invoice generated by a payee in order to request payment for some good or service. The inclusion of invoices within Lightning creates a payment work flow for merchants very similar to that of the existing financial system within PayPal, etc. Invoices are added to the database when a payment is requested, then can be settled manually once the payment is received at the upper layer. For record keeping purposes, invoices are never deleted from the database, instead a bit is toggled denoting the invoice has been fully settled. Within the database, all invoices must have a unique payment hash which is generated by taking the sha256 of the payment preimage.

func CopyInvoice

func CopyInvoice(src *Invoice) (*Invoice, error)

CopyInvoice makes a deep copy of the supplied invoice.

func (*Invoice) HTLCSet

func (i *Invoice) HTLCSet(setID *[32]byte,
	state HtlcState) map[CircuitKey]*InvoiceHTLC

HTLCSet returns the set of HTLCs belonging to setID and in the provided state. Passing a nil setID will return all HTLCs in the provided state in the case of legacy or MPP, and no HTLCs in the case of AMP. Otherwise, the returned set will be filtered by the populated setID which is used to retrieve AMP HTLC sets.

func (*Invoice) HTLCSetCompliment

func (i *Invoice) HTLCSetCompliment(setID *[32]byte,
	state HtlcState) map[CircuitKey]*InvoiceHTLC

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 (*Invoice) IsAMP

func (i *Invoice) IsAMP() bool

IsAMP returns true if the invoice is an AMP invoice.

func (*Invoice) IsKeysend

func (i *Invoice) IsKeysend() bool

IsKeysend returns true if the invoice is a Keysend invoice.

func (*Invoice) IsPending

func (i *Invoice) IsPending() bool

IsPending returns true if the invoice is in ContractOpen state.

type InvoiceDB

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(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(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(ref InvoiceRef) (Invoice, error)

	// ScanInvoices scans through all invoices and calls the passed scanFunc
	// for each invoice with its respective payment hash. Additionally a
	// reset() closure is passed which is used to reset/initialize partial
	// results and also to signal if the kvdb.View transaction has been
	// retried.
	//
	// TODO(positiveblue): abstract this functionality so it makes sense for
	// other backends like sql.
	ScanInvoices(scanFunc InvScanFunc, reset func()) error

	// QueryInvoices allows a caller to query the invoice database for
	// invoices within the specified add index range.
	QueryInvoices(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(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(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
	// deserialze them.
	DeleteInvoice(invoicesToDelete []InvoiceDeleteRef) error
}

InvoiceDB is the database that stores the information about invoices.

type InvoiceDeleteRef

type InvoiceDeleteRef struct {
	// PayHash is the payment hash of the target invoice. All invoices are
	// currently indexed by payment hash.
	PayHash lntypes.Hash

	// PayAddr is the payment addr of the target invoice. Newer invoices
	// (0.11 and up) are indexed by payment address in addition to payment
	// hash, but pre 0.8 invoices do not have one at all.
	PayAddr *[32]byte

	// AddIndex is the add index of the invoice.
	AddIndex uint64

	// SettleIndex is the settle index of the invoice.
	SettleIndex uint64
}

InvoiceDeleteRef holds a reference to an invoice to be deleted.

type InvoiceExpiryWatcher

type InvoiceExpiryWatcher struct {
	sync.Mutex
	// contains filtered or unexported fields
}

InvoiceExpiryWatcher handles automatic invoice cancellation of expired invoices. Upon start InvoiceExpiryWatcher will retrieve all pending (not yet settled or canceled) invoices invoices to its watching queue. When a new invoice is added to the InvoiceRegistry, it'll be forwarded to the InvoiceExpiryWatcher and will end up in the watching queue as well. If any of the watched invoices expire, they'll be removed from the watching queue and will be cancelled through InvoiceRegistry.CancelInvoice().

func NewInvoiceExpiryWatcher

func NewInvoiceExpiryWatcher(clock clock.Clock,
	expiryDelta, startHeight uint32, startHash *chainhash.Hash,
	notifier chainntnfs.ChainNotifier) *InvoiceExpiryWatcher

NewInvoiceExpiryWatcher creates a new InvoiceExpiryWatcher instance.

func (*InvoiceExpiryWatcher) AddInvoices

func (ew *InvoiceExpiryWatcher) AddInvoices(invoices ...invoiceExpiry)

AddInvoices adds invoices to the InvoiceExpiryWatcher.

func (*InvoiceExpiryWatcher) Start

func (ew *InvoiceExpiryWatcher) Start(
	cancelInvoice func(lntypes.Hash, bool) error) error

Start starts the the subscription handler and the main loop. Start() will return with error if InvoiceExpiryWatcher is already started. Start() expects a cancellation function passed that will be use to cancel expired invoices by their payment hash.

func (*InvoiceExpiryWatcher) Stop

func (ew *InvoiceExpiryWatcher) Stop()

Stop quits the expiry handler loop and waits for InvoiceExpiryWatcher to fully stop.

type InvoiceHTLC

type InvoiceHTLC struct {
	// Amt is the amount that is carried by this htlc.
	Amt lnwire.MilliSatoshi

	// MppTotalAmt is a field for mpp that indicates the expected total
	// amount.
	MppTotalAmt lnwire.MilliSatoshi

	// AcceptHeight is the block height at which the invoice registry
	// decided to accept this htlc as a payment to the invoice. At this
	// height, the invoice cltv delay must have been met.
	AcceptHeight uint32

	// AcceptTime is the wall clock time at which the invoice registry
	// decided to accept the htlc.
	AcceptTime time.Time

	// ResolveTime is the wall clock time at which the invoice registry
	// decided to settle the htlc.
	ResolveTime time.Time

	// Expiry is the expiry height of this htlc.
	Expiry uint32

	// State indicates the state the invoice htlc is currently in. A
	// canceled htlc isn't just removed from the invoice htlcs map, because
	// we need AcceptHeight to properly cancel the htlc back.
	State HtlcState

	// CustomRecords contains the custom key/value pairs that accompanied
	// the htlc.
	CustomRecords record.CustomSet

	// AMP encapsulates additional data relevant to AMP HTLCs. This includes
	// the AMP onion record, in addition to the HTLC's payment hash and
	// preimage since these are unique to each AMP HTLC, and not the invoice
	// as a whole.
	//
	// NOTE: This value will only be set for AMP HTLCs.
	AMP *InvoiceHtlcAMPData
}

InvoiceHTLC contains details about an htlc paying to this invoice.

func (*InvoiceHTLC) Copy

func (h *InvoiceHTLC) Copy() *InvoiceHTLC

Copy makes a deep copy of the target InvoiceHTLC.

func (*InvoiceHTLC) IsInHTLCSet

func (h *InvoiceHTLC) IsInHTLCSet(setID *[32]byte) bool

IsInHTLCSet returns true if this HTLC is part an HTLC set. If nil is passed, this method returns true if this is an MPP HTLC. Otherwise, it only returns true if the AMP HTLC's set id matches the populated setID.

type InvoiceHtlcAMPData

type InvoiceHtlcAMPData struct {
	// AMP is a copy of the AMP record presented in the onion payload
	// containing the information necessary to correlate and settle a
	// spontaneous HTLC set. Newly accepted legacy keysend payments will
	// also have this field set as we automatically promote them into an AMP
	// payment for internal processing.
	Record record.AMP

	// Hash is an HTLC-level payment hash that is stored only for AMP
	// payments. This is done because an AMP HTLC will carry a different
	// payment hash from the invoice it might be satisfying, so we track the
	// payment hashes individually to able to compute whether or not the
	// reconstructed preimage correctly matches the HTLC's hash.
	Hash lntypes.Hash

	// Preimage is an HTLC-level preimage that satisfies the AMP HTLC's
	// Hash. The preimage will be derived either from secret share
	// reconstruction of the shares in the AMP payload.
	//
	// NOTE: Preimage will only be present once the HTLC is in
	// HtlcStateSettled.
	Preimage *lntypes.Preimage
}

InvoiceHtlcAMPData is a struct hodling the additional metadata stored for each received AMP HTLC. This includes the AMP onion record, in addition to the HTLC's payment hash and preimage.

func (*InvoiceHtlcAMPData) Copy

Copy returns a deep copy of the InvoiceHtlcAMPData.

type InvoiceQuery

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, if set, filters out all invoices with a creation
	// date greater than or euqal to it.
	CreationDateStart time.Time

	// CreationDateEnd, if set, filters out all invoices with a creation
	// date less than or euqal to it.
	CreationDateEnd time.Time
}

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 InvoiceRef

type InvoiceRef struct {
	// contains filtered or unexported fields
}

InvoiceRef is a composite identifier for invoices. Invoices can be referenced by various combinations of payment hash and payment addr, in certain contexts only some of these are known. An InvoiceRef and its constructors thus encapsulate the valid combinations of query parameters that can be supplied to LookupInvoice and UpdateInvoice.

func InvoiceRefByAddr

func InvoiceRefByAddr(addr [32]byte) InvoiceRef

InvoiceRefByAddr creates an InvoiceRef that queries the payment addr index for an invoice with the provided payment address.

func InvoiceRefByAddrBlankHtlc

func InvoiceRefByAddrBlankHtlc(addr [32]byte) InvoiceRef

InvoiceRefByAddrBlankHtlc creates an InvoiceRef that queries the payment addr index for an invoice with the provided payment address, but excludes any of the core HTLC information.

func InvoiceRefByHash

func InvoiceRefByHash(payHash lntypes.Hash) InvoiceRef

InvoiceRefByHash creates an InvoiceRef that queries for an invoice only by its payment hash.

func InvoiceRefByHashAndAddr

func InvoiceRefByHashAndAddr(payHash lntypes.Hash,
	payAddr [32]byte) InvoiceRef

InvoiceRefByHashAndAddr creates an InvoiceRef that first queries for an invoice by the provided payment address, falling back to the payment hash if the payment address is unknown.

func InvoiceRefBySetID

func InvoiceRefBySetID(setID [32]byte) InvoiceRef

InvoiceRefBySetID creates an InvoiceRef that queries the set id index for an invoice with the provided setID. If the invoice is not found, the query will not fallback to payHash or payAddr.

func InvoiceRefBySetIDFiltered

func InvoiceRefBySetIDFiltered(setID [32]byte) InvoiceRef

InvoiceRefBySetIDFiltered is similar to the InvoiceRefBySetID identifier, but it specifies that the returned set of HTLCs should be filtered to only include HTLCs that are part of that set.

func (InvoiceRef) Modifier

func (r InvoiceRef) Modifier() RefModifier

Modifier defines the set of available modifications to the base invoice ref look up that are available.

func (InvoiceRef) PayAddr

func (r InvoiceRef) PayAddr() *[32]byte

PayAddr returns the optional payment address of the target invoice.

NOTE: This value may be nil.

func (InvoiceRef) PayHash

func (r InvoiceRef) PayHash() *lntypes.Hash

PayHash returns the optional payment hash of the target invoice.

NOTE: This value may be nil.

func (InvoiceRef) SetID

func (r InvoiceRef) SetID() *[32]byte

SetID returns the optional set id of the target invoice.

NOTE: This value may be nil.

func (InvoiceRef) String

func (r InvoiceRef) String() string

String returns a human-readable representation of an InvoiceRef.

type InvoiceRegistry

type InvoiceRegistry struct {
	sync.RWMutex
	// contains filtered or unexported fields
}

InvoiceRegistry is a central registry of all the outstanding invoices created by the daemon. The registry is a thin wrapper around a map in order to ensure that all updates/reads are thread safe.

func NewRegistry

func NewRegistry(idb InvoiceDB, expiryWatcher *InvoiceExpiryWatcher,
	cfg *RegistryConfig) *InvoiceRegistry

NewRegistry creates a new invoice registry. The invoice registry wraps the persistent on-disk invoice storage with an additional in-memory layer. The in-memory layer is in place such that debug invoices can be added which are volatile yet available system wide within the daemon.

func (*InvoiceRegistry) AddInvoice

func (i *InvoiceRegistry) AddInvoice(invoice *Invoice,
	paymentHash lntypes.Hash) (uint64, error)

AddInvoice adds a regular invoice for the specified amount, identified by the passed preimage. Additionally, any memo or receipt data provided will also be stored on-disk. Once this invoice is added, subsystems within the daemon add/forward HTLCs are able to obtain the proper preimage required for redemption in the case that we're the final destination. We also return the addIndex of the newly created invoice which monotonically increases for each new invoice added. A side effect of this function is that it also sets AddIndex on the invoice argument.

func (*InvoiceRegistry) CancelInvoice

func (i *InvoiceRegistry) CancelInvoice(payHash lntypes.Hash) error

CancelInvoice attempts to cancel the invoice corresponding to the passed payment hash.

func (*InvoiceRegistry) HodlUnsubscribeAll

func (i *InvoiceRegistry) HodlUnsubscribeAll(subscriber chan<- interface{})

HodlUnsubscribeAll cancels the subscription.

func (*InvoiceRegistry) LookupInvoice

func (i *InvoiceRegistry) LookupInvoice(rHash lntypes.Hash) (Invoice, error)

LookupInvoice looks up an invoice by its payment hash (R-Hash), if found then we're able to pull the funds pending within an HTLC.

TODO(roasbeef): ignore if settled?

func (*InvoiceRegistry) LookupInvoiceByRef

func (i *InvoiceRegistry) LookupInvoiceByRef(ref InvoiceRef) (Invoice, error)

LookupInvoiceByRef looks up an invoice by the given reference, if found then we're able to pull the funds pending within an HTLC.

func (*InvoiceRegistry) NotifyExitHopHtlc

func (i *InvoiceRegistry) NotifyExitHopHtlc(rHash lntypes.Hash,
	amtPaid lnwire.MilliSatoshi, expiry uint32, currentHeight int32,
	circuitKey CircuitKey, hodlChan chan<- interface{},
	payload Payload) (HtlcResolution, error)

NotifyExitHopHtlc attempts to mark an invoice as settled. The return value describes how the htlc should be resolved.

When the preimage of the invoice is not yet known (hodl invoice), this function moves the invoice to the accepted state. When SettleHoldInvoice is called later, a resolution message will be send back to the caller via the provided hodlChan. Invoice registry sends on this channel what action needs to be taken on the htlc (settle or cancel). The caller needs to ensure that the channel is either buffered or received on from another goroutine to prevent deadlock.

In the case that the htlc is part of a larger set of htlcs that pay to the same invoice (multi-path payment), the htlc is held until the set is complete. If the set doesn't fully arrive in time, a timer will cancel the held htlc.

func (*InvoiceRegistry) SettleHodlInvoice

func (i *InvoiceRegistry) SettleHodlInvoice(preimage lntypes.Preimage) error

SettleHodlInvoice sets the preimage of a hodl invoice.

func (*InvoiceRegistry) Start

func (i *InvoiceRegistry) Start() error

Start starts the registry and all goroutines it needs to carry out its task.

func (*InvoiceRegistry) Stop

func (i *InvoiceRegistry) Stop() error

Stop signals the registry for a graceful shutdown.

func (*InvoiceRegistry) SubscribeNotifications

func (i *InvoiceRegistry) SubscribeNotifications(
	addIndex, settleIndex uint64) (*InvoiceSubscription, error)

SubscribeNotifications returns an InvoiceSubscription which allows the caller to receive async notifications when any invoices are settled or added. The invoiceIndex parameter is a streaming "checkpoint". We'll start by first sending out all new events with an invoice index _greater_ than this value. Afterwards, we'll send out real-time notifications.

func (*InvoiceRegistry) SubscribeSingleInvoice

func (i *InvoiceRegistry) SubscribeSingleInvoice(
	hash lntypes.Hash) (*SingleInvoiceSubscription, error)

SubscribeSingleInvoice returns an SingleInvoiceSubscription which allows the caller to receive async notifications for a specific invoice.

type InvoiceSlice

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
}

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 InvoiceStateAMP

type InvoiceStateAMP struct {
	// State is the state of this sub-AMP invoice.
	State HtlcState

	// SettleIndex indicates the location in the settle index that
	// references this instance of InvoiceStateAMP, but only if
	// this value is set (non-zero), and State is HtlcStateSettled.
	SettleIndex uint64

	// SettleDate is the date that the setID was settled.
	SettleDate time.Time

	// InvoiceKeys is the set of circuit keys that can be used to locate
	// the invoices for a given set ID.
	InvoiceKeys map[CircuitKey]struct{}

	// AmtPaid is the total amount that was paid in the AMP sub-invoice.
	// Fetching the full HTLC/invoice state allows one to extract the
	// custom records as well as the break down of the payment splits used
	// when paying.
	AmtPaid lnwire.MilliSatoshi
}

InvoiceStateAMP is a struct that associates the current state of an AMP invoice identified by its set ID along with the set of invoices identified by the circuit key. This allows callers to easily look up the latest state of an AMP "sub-invoice" and also look up the invoice HLTCs themselves in the greater HTLC map index.

type InvoiceStateUpdateDesc

type InvoiceStateUpdateDesc struct {
	// NewState is the new state that this invoice should progress to.
	NewState ContractState

	// Preimage must be set to the preimage when NewState is settled.
	Preimage *lntypes.Preimage

	// HTLCPreimages set the HTLC-level preimages stored for AMP HTLCs.
	// These are only learned when settling the invoice as a whole. Must be
	// set when settling an invoice with non-nil SetID.
	HTLCPreimages map[CircuitKey]lntypes.Preimage

	// SetID identifies a specific set of HTLCs destined for the same
	// invoice as part of a larger AMP payment. This value will be nil for
	// legacy or MPP payments.
	SetID *[32]byte
}

InvoiceStateUpdateDesc describes an invoice-level state transition.

type InvoiceSubscription

type InvoiceSubscription struct {

	// NewInvoices is a channel that we'll use to send all newly created
	// invoices with an invoice index greater than the specified
	// StartingInvoiceIndex field.
	NewInvoices chan *Invoice

	// SettledInvoices is a channel that we'll use to send all settled
	// invoices with an invoices index greater than the specified
	// StartingInvoiceIndex field.
	SettledInvoices chan *Invoice
	// contains filtered or unexported fields
}

InvoiceSubscription represents an intent to receive updates for newly added or settled invoices. For each newly added invoice, a copy of the invoice will be sent over the NewInvoices channel. Similarly, for each newly settled invoice, a copy of the invoice will be sent over the SettledInvoices channel.

func (*InvoiceSubscription) Cancel

func (i *InvoiceSubscription) Cancel()

Cancel unregisters the InvoiceSubscription, freeing any previously allocated resources.

type InvoiceUpdateCallback

type InvoiceUpdateCallback = func(invoice *Invoice) (*InvoiceUpdateDesc, error)

InvoiceUpdateCallback is a callback used in the db transaction to update the invoice.

type InvoiceUpdateDesc

type InvoiceUpdateDesc struct {
	// State is the new state that this invoice should progress to. If nil,
	// the state is left unchanged.
	State *InvoiceStateUpdateDesc

	// CancelHtlcs describes the htlcs that need to be canceled.
	CancelHtlcs map[CircuitKey]struct{}

	// AddHtlcs describes the newly accepted htlcs that need to be added to
	// the invoice.
	AddHtlcs map[CircuitKey]*HtlcAcceptDesc

	// SetID is an optional set ID for AMP invoices that allows operations
	// to be more efficient by ensuring we don't need to read out the
	// entire HTLC set each timee an HTLC is to be cancelled.
	SetID *SetID

	// UpdateType indicates what type of update is being applied.
	UpdateType UpdateType
}

InvoiceUpdateDesc describes the changes that should be applied to the invoice.

type MockInvoiceDB

type MockInvoiceDB struct {
	mock.Mock
}

func NewInvoicesDBMock

func NewInvoicesDBMock() *MockInvoiceDB

func (*MockInvoiceDB) AddInvoice

func (m *MockInvoiceDB) AddInvoice(invoice *Invoice,
	paymentHash lntypes.Hash) (uint64, error)

func (*MockInvoiceDB) DeleteInvoice

func (m *MockInvoiceDB) DeleteInvoice(invoices []InvoiceDeleteRef) error

func (*MockInvoiceDB) InvoicesAddedSince

func (m *MockInvoiceDB) InvoicesAddedSince(idx uint64) ([]Invoice, error)

func (*MockInvoiceDB) InvoicesSettledSince

func (m *MockInvoiceDB) InvoicesSettledSince(idx uint64) ([]Invoice, error)

func (*MockInvoiceDB) LookupInvoice

func (m *MockInvoiceDB) LookupInvoice(ref InvoiceRef) (Invoice, error)

func (*MockInvoiceDB) QueryInvoices

func (m *MockInvoiceDB) QueryInvoices(q InvoiceQuery) (InvoiceSlice, error)

func (*MockInvoiceDB) ScanInvoices

func (m *MockInvoiceDB) ScanInvoices(scanFunc InvScanFunc,
	reset func()) error

func (*MockInvoiceDB) UpdateInvoice

func (m *MockInvoiceDB) UpdateInvoice(ref InvoiceRef, setIDHint *SetID,
	callback InvoiceUpdateCallback) (*Invoice, error)

type 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
}

Payload abstracts access to any additional fields provided in the final hop's TLV onion payload.

type RefModifier

type RefModifier uint8

RefModifier is a modification on top of a base invoice ref. It allows the caller to opt to skip out on HTLCs for a given payAddr, or only return the set of specified HTLCs for a given setID.

const (
	// DefaultModifier is the base modifier that doesn't change any
	// behavior.
	DefaultModifier RefModifier = iota

	// HtlcSetOnlyModifier can only be used with a setID based invoice ref,
	// and specifies that only the set of HTLCs related to that setID are
	// to be returned.
	HtlcSetOnlyModifier

	// HtlcSetOnlyModifier can only be used with a payAddr based invoice
	// ref, and specifies that the returned invoice shouldn't include any
	// HTLCs at all.
	HtlcSetBlankModifier
)

type RegistryConfig

type RegistryConfig struct {
	// FinalCltvRejectDelta defines the number of blocks before the expiry
	// of the htlc where we no longer settle it as an exit hop and instead
	// cancel it back. Normally this value should be lower than the cltv
	// expiry of any invoice we create and the code effectuating this should
	// not be hit.
	FinalCltvRejectDelta int32

	// HtlcHoldDuration defines for how long mpp htlcs are held while
	// waiting for the other set members to arrive.
	HtlcHoldDuration time.Duration

	// Clock holds the clock implementation that is used to provide
	// Now() and TickAfter() and is useful to stub out the clock functions
	// during testing.
	Clock clock.Clock

	// AcceptKeySend indicates whether we want to accept spontaneous key
	// send payments.
	AcceptKeySend bool

	// AcceptAMP indicates whether we want to accept spontaneous AMP
	// payments.
	AcceptAMP bool

	// GcCanceledInvoicesOnStartup if set, we'll attempt to garbage collect
	// all canceled invoices upon start.
	GcCanceledInvoicesOnStartup bool

	// GcCanceledInvoicesOnTheFly if set, we'll garbage collect all newly
	// canceled invoices on the fly.
	GcCanceledInvoicesOnTheFly bool

	// KeysendHoldTime indicates for how long we want to accept and hold
	// spontaneous keysend payments.
	KeysendHoldTime time.Duration
}

RegistryConfig contains the configuration parameters for invoice registry.

type SetID

type SetID [32]byte

SetID is the extra unique tuple item for AMP invoices. In addition to setting a payment address, each repeated payment to an AMP invoice will also contain a set ID as well.

type SettleResolutionResult

type SettleResolutionResult uint8

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.

const (

	// ResultSettled is returned when we settle an invoice.
	ResultSettled SettleResolutionResult

	// 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
)

func (SettleResolutionResult) String

func (s SettleResolutionResult) String() string

String returns a string representation of the result.

type SingleInvoiceSubscription

type SingleInvoiceSubscription struct {

	// Updates is a channel that we'll use to send all invoice events for
	// the invoice that is subscribed to.
	Updates chan *Invoice
	// contains filtered or unexported fields
}

SingleInvoiceSubscription represents an intent to receive updates for a specific invoice.

func (*SingleInvoiceSubscription) Cancel

func (i *SingleInvoiceSubscription) Cancel()

Cancel unregisters the InvoiceSubscription, freeing any previously allocated resources.

func (*SingleInvoiceSubscription) PayHash

func (s *SingleInvoiceSubscription) PayHash() *lntypes.Hash

PayHash returns the optional payment hash of the target invoice.

TODO(positiveblue): This method is only supposed to be used in tests. It will be deleted as soon as invoiceregistery_test is in the same module.

type UpdateType

type UpdateType uint8

UpdateType is an enum that describes the type of update that was applied to an invoice.

const (
	// UnknownUpdate indicates that the UpdateType has not been set for a
	// given udpate. This kind of updates are not allowed.
	UnknownUpdate UpdateType = iota

	// CancelHTLCsUpdate indicates that this update cancels one or more
	// HTLCs.
	CancelHTLCsUpdate

	// AddHTLCsUpdate indicates that this update adds one or more HTLCs.
	AddHTLCsUpdate

	// SettleHodlInvoiceUpdate indicates that this update settles one or
	// more HTLCs from a hodl invoice.
	SettleHodlInvoiceUpdate

	// CancelInvoiceUpdate indicates that this update is trying to cancel
	// an invoice.
	CancelInvoiceUpdate
)

func (UpdateType) String

func (u UpdateType) String() string

String returns a human readable string for the UpdateType.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL