• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

lightningnetwork / lnd / 9915780197

13 Jul 2024 12:30AM UTC coverage: 49.268% (-9.1%) from 58.413%
9915780197

push

github

web-flow
Merge pull request #8653 from ProofOfKeags/fn-prim

DynComms [0/n]: `fn` package additions

92837 of 188433 relevant lines covered (49.27%)

1.55 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

76.34
/invoices/invoices.go
1
package invoices
2

3
import (
4
        "errors"
5
        "fmt"
6
        "strings"
7
        "time"
8

9
        "github.com/lightningnetwork/lnd/feature"
10
        "github.com/lightningnetwork/lnd/lntypes"
11
        "github.com/lightningnetwork/lnd/lnwire"
12
        "github.com/lightningnetwork/lnd/record"
13
)
14

15
const (
16
        // MaxMemoSize is maximum size of the memo field within invoices stored
17
        // in the database.
18
        MaxMemoSize = 1024
19

20
        // MaxPaymentRequestSize is the max size of a payment request for
21
        // this invoice.
22
        // TODO(halseth): determine the max length payment request when field
23
        // lengths are final.
24
        MaxPaymentRequestSize = 4096
25
)
26

27
var (
28
        // unknownPreimage is an all-zeroes preimage that indicates that the
29
        // preimage for this invoice is not yet known.
30
        UnknownPreimage lntypes.Preimage
31

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

39
// RefModifier is a modification on top of a base invoice ref. It allows the
40
// caller to opt to skip out on HTLCs for a given payAddr, or only return the
41
// set of specified HTLCs for a given setID.
42
type RefModifier uint8
43

44
const (
45
        // DefaultModifier is the base modifier that doesn't change any
46
        // behavior.
47
        DefaultModifier RefModifier = iota
48

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

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

60
// InvoiceRef is a composite identifier for invoices. Invoices can be referenced
61
// by various combinations of payment hash and payment addr, in certain contexts
62
// only some of these are known. An InvoiceRef and its constructors thus
63
// encapsulate the valid combinations of query parameters that can be supplied
64
// to LookupInvoice and UpdateInvoice.
65
type InvoiceRef struct {
66
        // payHash is the payment hash of the target invoice. All invoices are
67
        // currently indexed by payment hash. This value will be used as a
68
        // fallback when no payment address is known.
69
        payHash *lntypes.Hash
70

71
        // payAddr is the payment addr of the target invoice. Newer invoices
72
        // (0.11 and up) are indexed by payment address in addition to payment
73
        // hash, but pre 0.8 invoices do not have one at all. When this value is
74
        // known it will be used as the primary identifier, falling back to
75
        // payHash if no value is known.
76
        payAddr *[32]byte
77

78
        // setID is the optional set id for an AMP payment. This can be used to
79
        // lookup or update the invoice knowing only this value. Queries by set
80
        // id are only used to facilitate user-facing requests, e.g. lookup,
81
        // settle or cancel an AMP invoice. The regular update flow from the
82
        // invoice registry will always query for the invoice by
83
        // payHash+payAddr.
84
        setID *[32]byte
85

86
        // refModifier allows an invoice ref to include or exclude specific
87
        // HTLC sets based on the payAddr or setId.
88
        refModifier RefModifier
89
}
90

91
// InvoiceRefByHash creates an InvoiceRef that queries for an invoice only by
92
// its payment hash.
93
func InvoiceRefByHash(payHash lntypes.Hash) InvoiceRef {
3✔
94
        return InvoiceRef{
3✔
95
                payHash: &payHash,
3✔
96
        }
3✔
97
}
3✔
98

99
// InvoiceRefByHashAndAddr creates an InvoiceRef that first queries for an
100
// invoice by the provided payment address, falling back to the payment hash if
101
// the payment address is unknown.
102
func InvoiceRefByHashAndAddr(payHash lntypes.Hash,
103
        payAddr [32]byte) InvoiceRef {
3✔
104

3✔
105
        return InvoiceRef{
3✔
106
                payHash: &payHash,
3✔
107
                payAddr: &payAddr,
3✔
108
        }
3✔
109
}
3✔
110

111
// InvoiceRefByAddr creates an InvoiceRef that queries the payment addr index
112
// for an invoice with the provided payment address.
113
func InvoiceRefByAddr(addr [32]byte) InvoiceRef {
3✔
114
        return InvoiceRef{
3✔
115
                payAddr: &addr,
3✔
116
        }
3✔
117
}
3✔
118

119
// InvoiceRefByAddrBlankHtlc creates an InvoiceRef that queries the payment addr
120
// index for an invoice with the provided payment address, but excludes any of
121
// the core HTLC information.
122
func InvoiceRefByAddrBlankHtlc(addr [32]byte) InvoiceRef {
3✔
123
        return InvoiceRef{
3✔
124
                payAddr:     &addr,
3✔
125
                refModifier: HtlcSetBlankModifier,
3✔
126
        }
3✔
127
}
3✔
128

129
// InvoiceRefBySetID creates an InvoiceRef that queries the set id index for an
130
// invoice with the provided setID. If the invoice is not found, the query will
131
// not fallback to payHash or payAddr.
132
func InvoiceRefBySetID(setID [32]byte) InvoiceRef {
3✔
133
        return InvoiceRef{
3✔
134
                setID: &setID,
3✔
135
        }
3✔
136
}
3✔
137

138
// InvoiceRefBySetIDFiltered is similar to the InvoiceRefBySetID identifier,
139
// but it specifies that the returned set of HTLCs should be filtered to only
140
// include HTLCs that are part of that set.
141
func InvoiceRefBySetIDFiltered(setID [32]byte) InvoiceRef {
3✔
142
        return InvoiceRef{
3✔
143
                setID:       &setID,
3✔
144
                refModifier: HtlcSetOnlyModifier,
3✔
145
        }
3✔
146
}
3✔
147

148
// PayHash returns the optional payment hash of the target invoice.
149
//
150
// NOTE: This value may be nil.
151
func (r InvoiceRef) PayHash() *lntypes.Hash {
3✔
152
        if r.payHash != nil {
6✔
153
                hash := *r.payHash
3✔
154
                return &hash
3✔
155
        }
3✔
156

157
        return nil
3✔
158
}
159

160
// PayAddr returns the optional payment address of the target invoice.
161
//
162
// NOTE: This value may be nil.
163
func (r InvoiceRef) PayAddr() *[32]byte {
3✔
164
        if r.payAddr != nil {
6✔
165
                addr := *r.payAddr
3✔
166
                return &addr
3✔
167
        }
3✔
168

169
        return nil
3✔
170
}
171

172
// SetID returns the optional set id of the target invoice.
173
//
174
// NOTE: This value may be nil.
175
func (r InvoiceRef) SetID() *[32]byte {
3✔
176
        if r.setID != nil {
6✔
177
                id := *r.setID
3✔
178
                return &id
3✔
179
        }
3✔
180

181
        return nil
3✔
182
}
183

184
// Modifier defines the set of available modifications to the base invoice ref
185
// look up that are available.
186
func (r InvoiceRef) Modifier() RefModifier {
3✔
187
        return r.refModifier
3✔
188
}
3✔
189

190
// String returns a human-readable representation of an InvoiceRef.
191
func (r InvoiceRef) String() string {
3✔
192
        var ids []string
3✔
193
        if r.payHash != nil {
6✔
194
                ids = append(ids, fmt.Sprintf("pay_hash=%v", *r.payHash))
3✔
195
        }
3✔
196
        if r.payAddr != nil {
6✔
197
                ids = append(ids, fmt.Sprintf("pay_addr=%x", *r.payAddr))
3✔
198
        }
3✔
199
        if r.setID != nil {
6✔
200
                ids = append(ids, fmt.Sprintf("set_id=%x", *r.setID))
3✔
201
        }
3✔
202

203
        return fmt.Sprintf("(%s)", strings.Join(ids, ", "))
3✔
204
}
205

206
// ContractState describes the state the invoice is in.
207
type ContractState uint8
208

209
const (
210
        // ContractOpen means the invoice has only been created.
211
        ContractOpen ContractState = 0
212

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

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

220
        // ContractAccepted means the HTLC has been accepted but not settled
221
        // yet.
222
        ContractAccepted ContractState = 3
223
)
224

225
// String returns a human readable identifier for the ContractState type.
226
func (c ContractState) String() string {
×
227
        switch c {
×
228
        case ContractOpen:
×
229
                return "Open"
×
230

231
        case ContractSettled:
×
232
                return "Settled"
×
233

234
        case ContractCanceled:
×
235
                return "Canceled"
×
236

237
        case ContractAccepted:
×
238
                return "Accepted"
×
239
        }
240

241
        return "Unknown"
×
242
}
243

244
// IsFinal returns a boolean indicating whether an invoice state is final.
245
func (c ContractState) IsFinal() bool {
3✔
246
        return c == ContractSettled || c == ContractCanceled
3✔
247
}
3✔
248

249
// ContractTerm is a companion struct to the Invoice struct. This struct houses
250
// the necessary conditions required before the invoice can be considered fully
251
// settled by the payee.
252
type ContractTerm struct {
253
        // FinalCltvDelta is the minimum required number of blocks before htlc
254
        // expiry when the invoice is accepted.
255
        FinalCltvDelta int32
256

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

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

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

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

273
        // Features is the feature vectors advertised on the payment request.
274
        Features *lnwire.FeatureVector
275
}
276

277
// String returns a human-readable description of the prominent contract terms.
278
func (c ContractTerm) String() string {
3✔
279
        return fmt.Sprintf("amt=%v, expiry=%v, final_cltv_delta=%v", c.Value,
3✔
280
                c.Expiry, c.FinalCltvDelta)
3✔
281
}
3✔
282

283
// SetID is the extra unique tuple item for AMP invoices. In addition to
284
// setting a payment address, each repeated payment to an AMP invoice will also
285
// contain a set ID as well.
286
type SetID [32]byte
287

288
// InvoiceStateAMP is a struct that associates the current state of an AMP
289
// invoice identified by its set ID along with the set of invoices identified
290
// by the circuit key. This allows callers to easily look up the latest state
291
// of an AMP "sub-invoice" and also look up the invoice HLTCs themselves in the
292
// greater HTLC map index.
293
type InvoiceStateAMP struct {
294
        // State is the state of this sub-AMP invoice.
295
        State HtlcState
296

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

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

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

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

316
// copy makes a deep copy of the underlying InvoiceStateAMP.
317
func (i *InvoiceStateAMP) copy() (InvoiceStateAMP, error) {
3✔
318
        result := *i
3✔
319

3✔
320
        // Make a copy of the InvoiceKeys map.
3✔
321
        result.InvoiceKeys = make(map[CircuitKey]struct{})
3✔
322
        for k := range i.InvoiceKeys {
6✔
323
                result.InvoiceKeys[k] = struct{}{}
3✔
324
        }
3✔
325

326
        // As a safety measure, copy SettleDate. time.Time is concurrency safe
327
        // except when using any of the (un)marshalling methods.
328
        settleDateBytes, err := i.SettleDate.MarshalBinary()
3✔
329
        if err != nil {
3✔
330
                return InvoiceStateAMP{}, err
×
331
        }
×
332

333
        err = result.SettleDate.UnmarshalBinary(settleDateBytes)
3✔
334
        if err != nil {
3✔
335
                return InvoiceStateAMP{}, err
×
336
        }
×
337

338
        return result, nil
3✔
339
}
340

341
// AMPInvoiceState represents a type that stores metadata related to the set of
342
// settled AMP "sub-invoices".
343
type AMPInvoiceState map[SetID]InvoiceStateAMP
344

345
// Invoice is a payment invoice generated by a payee in order to request
346
// payment for some good or service. The inclusion of invoices within Lightning
347
// creates a payment work flow for merchants very similar to that of the
348
// existing financial system within PayPal, etc.  Invoices are added to the
349
// database when a payment is requested, then can be settled manually once the
350
// payment is received at the upper layer. For record keeping purposes,
351
// invoices are never deleted from the database, instead a bit is toggled
352
// denoting the invoice has been fully settled. Within the database, all
353
// invoices must have a unique payment hash which is generated by taking the
354
// sha256 of the payment preimage.
355
type Invoice struct {
356
        // Memo is an optional memo to be stored along side an invoice.  The
357
        // memo may contain further details pertaining to the invoice itself,
358
        // or any other message which fits within the size constraints.
359
        Memo []byte
360

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

365
        // CreationDate is the exact time the invoice was created.
366
        CreationDate time.Time
367

368
        // SettleDate is the exact time the invoice was settled.
369
        SettleDate time.Time
370

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

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

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

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

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

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

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

419
        // HodlInvoice indicates whether the invoice should be held in the
420
        // Accepted state or be settled right away.
421
        HodlInvoice bool
422
}
423

424
// HTLCSet returns the set of HTLCs belonging to setID and in the provided
425
// state. Passing a nil setID will return all HTLCs in the provided state in the
426
// case of legacy or MPP, and no HTLCs in the case of AMP.  Otherwise, the
427
// returned set will be filtered by the populated setID which is used to
428
// retrieve AMP HTLC sets.
429
func (i *Invoice) HTLCSet(setID *[32]byte,
430
        state HtlcState) map[CircuitKey]*InvoiceHTLC {
3✔
431

3✔
432
        htlcSet := make(map[CircuitKey]*InvoiceHTLC)
3✔
433
        for key, htlc := range i.Htlcs {
6✔
434
                // Only add HTLCs that are in the requested HtlcState.
3✔
435
                if htlc.State != state {
3✔
436
                        continue
×
437
                }
438

439
                if !htlc.IsInHTLCSet(setID) {
3✔
440
                        continue
×
441
                }
442

443
                htlcSet[key] = htlc
3✔
444
        }
445

446
        return htlcSet
3✔
447
}
448

449
// HTLCSetCompliment returns the set of all HTLCs not belonging to setID that
450
// are in the target state. Passing a nil setID will return no invoices, since
451
// all MPP HTLCs are part of the same HTLC set.
452
func (i *Invoice) HTLCSetCompliment(setID *[32]byte,
453
        state HtlcState) map[CircuitKey]*InvoiceHTLC {
3✔
454

3✔
455
        htlcSet := make(map[CircuitKey]*InvoiceHTLC)
3✔
456
        for key, htlc := range i.Htlcs {
6✔
457
                // Only add HTLCs that are in the requested HtlcState.
3✔
458
                if htlc.State != state {
6✔
459
                        continue
3✔
460
                }
461

462
                // We are constructing the compliment, so filter anything that
463
                // matches this set id.
464
                if htlc.IsInHTLCSet(setID) {
×
465
                        continue
×
466
                }
467

468
                htlcSet[key] = htlc
×
469
        }
470

471
        return htlcSet
3✔
472
}
473

474
// IsKeysend returns true if the invoice is a Keysend invoice.
475
func (i *Invoice) IsKeysend() bool {
3✔
476
        // TODO(positiveblue): look for a more reliable way to tests if
3✔
477
        // an invoice is keysend.
3✔
478
        return len(i.PaymentRequest) == 0 && !i.IsAMP()
3✔
479
}
3✔
480

481
// IsAMP returns true if the invoice is an AMP invoice.
482
func (i *Invoice) IsAMP() bool {
3✔
483
        if i.Terms.Features == nil {
3✔
484
                return false
×
485
        }
×
486

487
        return i.Terms.Features.HasFeature(
3✔
488
                lnwire.AMPRequired,
3✔
489
        )
3✔
490
}
491

492
// HtlcState defines the states an htlc paying to an invoice can be in.
493
type HtlcState uint8
494

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

499
        // HtlcStateCanceled indicates the htlc is canceled back to the
500
        // sender.
501
        HtlcStateCanceled
502

503
        // HtlcStateSettled indicates the htlc is settled.
504
        HtlcStateSettled
505
)
506

507
// InvoiceHTLC contains details about an htlc paying to this invoice.
508
type InvoiceHTLC struct {
509
        // Amt is the amount that is carried by this htlc.
510
        Amt lnwire.MilliSatoshi
511

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

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

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

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

529
        // Expiry is the expiry height of this htlc.
530
        Expiry uint32
531

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

537
        // CustomRecords contains the custom key/value pairs that accompanied
538
        // the htlc.
539
        CustomRecords record.CustomSet
540

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

550
// Copy makes a deep copy of the target InvoiceHTLC.
551
func (h *InvoiceHTLC) Copy() *InvoiceHTLC {
3✔
552
        result := *h
3✔
553

3✔
554
        // Make a copy of the CustomSet map.
3✔
555
        result.CustomRecords = make(record.CustomSet)
3✔
556
        for k, v := range h.CustomRecords {
3✔
557
                result.CustomRecords[k] = v
×
558
        }
×
559

560
        result.AMP = h.AMP.Copy()
3✔
561

3✔
562
        return &result
3✔
563
}
564

565
// IsInHTLCSet returns true if this HTLC is part an HTLC set. If nil is passed,
566
// this method returns true if this is an MPP HTLC. Otherwise, it only returns
567
// true if the AMP HTLC's set id matches the populated setID.
568
func (h *InvoiceHTLC) IsInHTLCSet(setID *[32]byte) bool {
3✔
569
        wantAMPSet := setID != nil
3✔
570
        isAMPHtlc := h.AMP != nil
3✔
571

3✔
572
        // Non-AMP HTLCs cannot be part of AMP HTLC sets, and vice versa.
3✔
573
        if wantAMPSet != isAMPHtlc {
3✔
574
                return false
×
575
        }
×
576

577
        // Skip AMP HTLCs that have differing set ids.
578
        if isAMPHtlc && *setID != h.AMP.Record.SetID() {
3✔
579
                return false
×
580
        }
×
581

582
        return true
3✔
583
}
584

585
// InvoiceHtlcAMPData is a struct hodling the additional metadata stored for
586
// each received AMP HTLC. This includes the AMP onion record, in addition to
587
// the HTLC's payment hash and preimage.
588
type InvoiceHtlcAMPData struct {
589
        // AMP is a copy of the AMP record presented in the onion payload
590
        // containing the information necessary to correlate and settle a
591
        // spontaneous HTLC set. Newly accepted legacy keysend payments will
592
        // also have this field set as we automatically promote them into an AMP
593
        // payment for internal processing.
594
        Record record.AMP
595

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

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

612
// Copy returns a deep copy of the InvoiceHtlcAMPData.
613
func (d *InvoiceHtlcAMPData) Copy() *InvoiceHtlcAMPData {
3✔
614
        if d == nil {
6✔
615
                return nil
3✔
616
        }
3✔
617

618
        var preimage *lntypes.Preimage
3✔
619
        if d.Preimage != nil {
3✔
620
                pimg := *d.Preimage
×
621
                preimage = &pimg
×
622
        }
×
623

624
        return &InvoiceHtlcAMPData{
3✔
625
                Record:   d.Record,
3✔
626
                Hash:     d.Hash,
3✔
627
                Preimage: preimage,
3✔
628
        }
3✔
629
}
630

631
// HtlcAcceptDesc describes the details of a newly accepted htlc.
632
type HtlcAcceptDesc struct {
633
        // AcceptHeight is the block height at which this htlc was accepted.
634
        AcceptHeight int32
635

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

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

643
        // Expiry is the expiry height of this htlc.
644
        Expiry uint32
645

646
        // CustomRecords contains the custom key/value pairs that accompanied
647
        // the htlc.
648
        CustomRecords record.CustomSet
649

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

659
// UpdateType is an enum that describes the type of update that was applied to
660
// an invoice.
661
type UpdateType uint8
662

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

668
        // CancelHTLCsUpdate indicates that this update cancels one or more
669
        // HTLCs.
670
        CancelHTLCsUpdate
671

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

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

679
        // CancelInvoiceUpdate indicates that this update is trying to cancel
680
        // an invoice.
681
        CancelInvoiceUpdate
682
)
683

684
// String returns a human readable string for the UpdateType.
685
func (u UpdateType) String() string {
×
686
        switch u {
×
687
        case CancelHTLCsUpdate:
×
688
                return "CancelHTLCsUpdate"
×
689

690
        case AddHTLCsUpdate:
×
691
                return "AddHTLCsUpdate"
×
692

693
        case SettleHodlInvoiceUpdate:
×
694
                return "SettleHodlInvoiceUpdate"
×
695

696
        case CancelInvoiceUpdate:
×
697
                return "CancelInvoiceUpdate"
×
698

699
        default:
×
700
                return fmt.Sprintf("unknown invoice update type: %d", u)
×
701
        }
702
}
703

704
// InvoiceUpdateDesc describes the changes that should be applied to the
705
// invoice.
706
type InvoiceUpdateDesc struct {
707
        // State is the new state that this invoice should progress to. If nil,
708
        // the state is left unchanged.
709
        State *InvoiceStateUpdateDesc
710

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

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

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

723
        // UpdateType indicates what type of update is being applied.
724
        UpdateType UpdateType
725
}
726

727
// InvoiceStateUpdateDesc describes an invoice-level state transition.
728
type InvoiceStateUpdateDesc struct {
729
        // NewState is the new state that this invoice should progress to.
730
        NewState ContractState
731

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

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

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

746
// InvoiceUpdateCallback is a callback used in the db transaction to update the
747
// invoice.
748
type InvoiceUpdateCallback = func(invoice *Invoice) (*InvoiceUpdateDesc, error)
749

750
// ValidateInvoice assures the invoice passes the checks for all the relevant
751
// constraints.
752
func ValidateInvoice(i *Invoice, paymentHash lntypes.Hash) error {
3✔
753
        // Avoid conflicts with all-zeroes magic value in the database.
3✔
754
        if paymentHash == UnknownPreimage.Hash() {
3✔
755
                return fmt.Errorf("cannot use hash of all-zeroes preimage")
×
756
        }
×
757

758
        if len(i.Memo) > MaxMemoSize {
3✔
759
                return fmt.Errorf("max length a memo is %v, and invoice "+
×
760
                        "of length %v was provided", MaxMemoSize, len(i.Memo))
×
761
        }
×
762
        if len(i.PaymentRequest) > MaxPaymentRequestSize {
3✔
763
                return fmt.Errorf("max length of payment request is %v, "+
×
764
                        "length provided was %v", MaxPaymentRequestSize,
×
765
                        len(i.PaymentRequest))
×
766
        }
×
767
        if i.Terms.Features == nil {
3✔
768
                return errors.New("invoice must have a feature vector")
×
769
        }
×
770

771
        err := feature.ValidateDeps(i.Terms.Features)
3✔
772
        if err != nil {
3✔
773
                return err
×
774
        }
×
775

776
        if i.requiresPreimage() && i.Terms.PaymentPreimage == nil {
3✔
777
                return errors.New("this invoice must have a preimage")
×
778
        }
×
779

780
        if len(i.Htlcs) > 0 {
3✔
781
                return ErrInvoiceHasHtlcs
×
782
        }
×
783

784
        return nil
3✔
785
}
786

787
// requiresPreimage returns true if the invoice requires a preimage to be valid.
788
func (i *Invoice) requiresPreimage() bool {
3✔
789
        // AMP invoices and hodl invoices are allowed to have no preimage
3✔
790
        // specified.
3✔
791
        if i.HodlInvoice || i.IsAMP() {
6✔
792
                return false
3✔
793
        }
3✔
794

795
        return true
3✔
796
}
797

798
// IsPending returns true if the invoice is in ContractOpen state.
799
func (i *Invoice) IsPending() bool {
3✔
800
        return i.State == ContractOpen || i.State == ContractAccepted
3✔
801
}
3✔
802

803
// copySlice allocates a new slice and copies the source into it.
804
func copySlice(src []byte) []byte {
3✔
805
        dest := make([]byte, len(src))
3✔
806
        copy(dest, src)
3✔
807
        return dest
3✔
808
}
3✔
809

810
// CopyInvoice makes a deep copy of the supplied invoice.
811
func CopyInvoice(src *Invoice) (*Invoice, error) {
3✔
812
        dest := Invoice{
3✔
813
                Memo:           copySlice(src.Memo),
3✔
814
                PaymentRequest: copySlice(src.PaymentRequest),
3✔
815
                CreationDate:   src.CreationDate,
3✔
816
                SettleDate:     src.SettleDate,
3✔
817
                Terms:          src.Terms,
3✔
818
                AddIndex:       src.AddIndex,
3✔
819
                SettleIndex:    src.SettleIndex,
3✔
820
                State:          src.State,
3✔
821
                AmtPaid:        src.AmtPaid,
3✔
822
                Htlcs: make(
3✔
823
                        map[CircuitKey]*InvoiceHTLC, len(src.Htlcs),
3✔
824
                ),
3✔
825
                AMPState:    make(map[SetID]InvoiceStateAMP),
3✔
826
                HodlInvoice: src.HodlInvoice,
3✔
827
        }
3✔
828

3✔
829
        dest.Terms.Features = src.Terms.Features.Clone()
3✔
830

3✔
831
        if src.Terms.PaymentPreimage != nil {
6✔
832
                preimage := *src.Terms.PaymentPreimage
3✔
833
                dest.Terms.PaymentPreimage = &preimage
3✔
834
        }
3✔
835

836
        for k, v := range src.Htlcs {
6✔
837
                dest.Htlcs[k] = v.Copy()
3✔
838
        }
3✔
839

840
        // Lastly, copy the amp invoice state.
841
        for k, v := range src.AMPState {
6✔
842
                ampInvState, err := v.copy()
3✔
843
                if err != nil {
3✔
844
                        return nil, err
×
845
                }
×
846

847
                dest.AMPState[k] = ampInvState
3✔
848
        }
849

850
        return &dest, nil
3✔
851
}
852

853
// InvoiceDeleteRef holds a reference to an invoice to be deleted.
854
type InvoiceDeleteRef struct {
855
        // PayHash is the payment hash of the target invoice. All invoices are
856
        // currently indexed by payment hash.
857
        PayHash lntypes.Hash
858

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

864
        // AddIndex is the add index of the invoice.
865
        AddIndex uint64
866

867
        // SettleIndex is the settle index of the invoice.
868
        SettleIndex uint64
869
}
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2025 Coveralls, Inc