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

lightningnetwork / lnd / 12313002221

13 Dec 2024 09:25AM UTC coverage: 57.486% (+8.6%) from 48.92%
12313002221

push

github

web-flow
Merge pull request #9343 from ellemouton/contextGuard

fn: expand the ContextGuard and add tests

101902 of 177264 relevant lines covered (57.49%)

24909.26 hits per line

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

74.25
/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 {
2,136✔
94
        return InvoiceRef{
2,136✔
95
                payHash: &payHash,
2,136✔
96
        }
2,136✔
97
}
2,136✔
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 {
1,606✔
104

1,606✔
105
        return InvoiceRef{
1,606✔
106
                payHash: &payHash,
1,606✔
107
                payAddr: &payAddr,
1,606✔
108
        }
1,606✔
109
}
1,606✔
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 {
70✔
114
        return InvoiceRef{
70✔
115
                payAddr: &addr,
70✔
116
        }
70✔
117
}
70✔
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 {
22✔
133
        return InvoiceRef{
22✔
134
                setID: &setID,
22✔
135
        }
22✔
136
}
22✔
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 {
12✔
142
        return InvoiceRef{
12✔
143
                setID:       &setID,
12✔
144
                refModifier: HtlcSetOnlyModifier,
12✔
145
        }
12✔
146
}
12✔
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 {
7,227✔
152
        if r.payHash != nil {
14,255✔
153
                hash := *r.payHash
7,028✔
154
                return &hash
7,028✔
155
        }
7,028✔
156

157
        return nil
199✔
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 {
4,541✔
164
        if r.payAddr != nil {
7,358✔
165
                addr := *r.payAddr
2,817✔
166
                return &addr
2,817✔
167
        }
2,817✔
168

169
        return nil
1,724✔
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,643✔
176
        if r.setID != nil {
3,967✔
177
                id := *r.setID
324✔
178
                return &id
324✔
179
        }
324✔
180

181
        return nil
3,319✔
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 {
1,742✔
187
        return r.refModifier
1,742✔
188
}
1,742✔
189

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

203
        return fmt.Sprintf("(%s)", strings.Join(ids, ", "))
×
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 {
×
246
        return c == ContractSettled || c == ContractCanceled
×
247
}
×
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 {
×
279
        return fmt.Sprintf("amt=%v, expiry=%v, final_cltv_delta=%v", c.Value,
×
280
                c.Expiry, c.FinalCltvDelta)
×
281
}
×
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) {
76✔
318
        result := *i
76✔
319

76✔
320
        // Make a copy of the InvoiceKeys map.
76✔
321
        result.InvoiceKeys = make(map[CircuitKey]struct{})
76✔
322
        for k := range i.InvoiceKeys {
173✔
323
                result.InvoiceKeys[k] = struct{}{}
97✔
324
        }
97✔
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()
76✔
329
        if err != nil {
76✔
330
                return InvoiceStateAMP{}, err
×
331
        }
×
332

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

338
        return result, nil
76✔
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 {
2,252✔
431

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

439
                if !htlc.IsInHTLCSet(setID) {
2,589✔
440
                        continue
120✔
441
                }
442

443
                htlcSet[key] = htlc
2,349✔
444
        }
445

446
        return htlcSet
2,252✔
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 {
473✔
454

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

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

468
                htlcSet[key] = htlc
×
469
        }
470

471
        return htlcSet
473✔
472
}
473

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

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

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

492
// IsBlinded returns true if the invoice contains blinded paths.
493
func (i *Invoice) IsBlinded() bool {
×
494
        if i.Terms.Features == nil {
×
495
                return false
×
496
        }
×
497

498
        return i.Terms.Features.IsSet(lnwire.Bolt11BlindedPathsRequired)
×
499
}
500

501
// HtlcState defines the states an htlc paying to an invoice can be in.
502
type HtlcState uint8
503

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

508
        // HtlcStateCanceled indicates the htlc is canceled back to the
509
        // sender.
510
        HtlcStateCanceled
511

512
        // HtlcStateSettled indicates the htlc is settled.
513
        HtlcStateSettled
514
)
515

516
// InvoiceHTLC contains details about an htlc paying to this invoice.
517
type InvoiceHTLC struct {
518
        // Amt is the amount that is carried by this htlc.
519
        Amt lnwire.MilliSatoshi
520

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

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

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

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

538
        // Expiry is the expiry height of this htlc.
539
        Expiry uint32
540

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

546
        // CustomRecords contains the custom key/value pairs that accompanied
547
        // the htlc.
548
        CustomRecords record.CustomSet
549

550
        // WireCustomRecords contains the custom key/value pairs that were only
551
        // included in p2p wire message of the HTLC and not in the onion
552
        // payload.
553
        WireCustomRecords lnwire.CustomRecords
554

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

564
// Copy makes a deep copy of the target InvoiceHTLC.
565
func (h *InvoiceHTLC) Copy() *InvoiceHTLC {
599✔
566
        result := *h
599✔
567

599✔
568
        // Make a copy of the CustomSet map.
599✔
569
        result.CustomRecords = make(record.CustomSet)
599✔
570
        for k, v := range h.CustomRecords {
610✔
571
                result.CustomRecords[k] = v
11✔
572
        }
11✔
573

574
        result.WireCustomRecords = h.WireCustomRecords.Copy()
599✔
575
        result.AMP = h.AMP.Copy()
599✔
576

599✔
577
        return &result
599✔
578
}
579

580
// IsInHTLCSet returns true if this HTLC is part an HTLC set. If nil is passed,
581
// this method returns true if this is an MPP HTLC. Otherwise, it only returns
582
// true if the AMP HTLC's set id matches the populated setID.
583
func (h *InvoiceHTLC) IsInHTLCSet(setID *[32]byte) bool {
3,587✔
584
        wantAMPSet := setID != nil
3,587✔
585
        isAMPHtlc := h.AMP != nil
3,587✔
586

3,587✔
587
        // Non-AMP HTLCs cannot be part of AMP HTLC sets, and vice versa.
3,587✔
588
        if wantAMPSet != isAMPHtlc {
3,667✔
589
                return false
80✔
590
        }
80✔
591

592
        // Skip AMP HTLCs that have differing set ids.
593
        if isAMPHtlc && *setID != h.AMP.Record.SetID() {
3,549✔
594
                return false
42✔
595
        }
42✔
596

597
        return true
3,465✔
598
}
599

600
// InvoiceHtlcAMPData is a struct hodling the additional metadata stored for
601
// each received AMP HTLC. This includes the AMP onion record, in addition to
602
// the HTLC's payment hash and preimage.
603
type InvoiceHtlcAMPData struct {
604
        // AMP is a copy of the AMP record presented in the onion payload
605
        // containing the information necessary to correlate and settle a
606
        // spontaneous HTLC set. Newly accepted legacy keysend payments will
607
        // also have this field set as we automatically promote them into an AMP
608
        // payment for internal processing.
609
        Record record.AMP
610

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

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

627
// Copy returns a deep copy of the InvoiceHtlcAMPData.
628
func (d *InvoiceHtlcAMPData) Copy() *InvoiceHtlcAMPData {
656✔
629
        if d == nil {
1,168✔
630
                return nil
512✔
631
        }
512✔
632

633
        var preimage *lntypes.Preimage
144✔
634
        if d.Preimage != nil {
231✔
635
                pimg := *d.Preimage
87✔
636
                preimage = &pimg
87✔
637
        }
87✔
638

639
        return &InvoiceHtlcAMPData{
144✔
640
                Record:   d.Record,
144✔
641
                Hash:     d.Hash,
144✔
642
                Preimage: preimage,
144✔
643
        }
144✔
644
}
645

646
// HtlcAcceptDesc describes the details of a newly accepted htlc.
647
type HtlcAcceptDesc struct {
648
        // AcceptHeight is the block height at which this htlc was accepted.
649
        AcceptHeight int32
650

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

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

658
        // Expiry is the expiry height of this htlc.
659
        Expiry uint32
660

661
        // CustomRecords contains the custom key/value pairs that accompanied
662
        // the htlc.
663
        CustomRecords record.CustomSet
664

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

674
// UpdateType is an enum that describes the type of update that was applied to
675
// an invoice.
676
type UpdateType uint8
677

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

683
        // CancelHTLCsUpdate indicates that this update cancels one or more
684
        // HTLCs.
685
        CancelHTLCsUpdate
686

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

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

694
        // CancelInvoiceUpdate indicates that this update is trying to cancel
695
        // an invoice.
696
        CancelInvoiceUpdate
697
)
698

699
// String returns a human readable string for the UpdateType.
700
func (u UpdateType) String() string {
×
701
        switch u {
×
702
        case CancelHTLCsUpdate:
×
703
                return "CancelHTLCsUpdate"
×
704

705
        case AddHTLCsUpdate:
×
706
                return "AddHTLCsUpdate"
×
707

708
        case SettleHodlInvoiceUpdate:
×
709
                return "SettleHodlInvoiceUpdate"
×
710

711
        case CancelInvoiceUpdate:
×
712
                return "CancelInvoiceUpdate"
×
713

714
        default:
×
715
                return fmt.Sprintf("unknown invoice update type: %d", u)
×
716
        }
717
}
718

719
// InvoiceUpdateDesc describes the changes that should be applied to the
720
// invoice.
721
type InvoiceUpdateDesc struct {
722
        // State is the new state that this invoice should progress to. If nil,
723
        // the state is left unchanged.
724
        State *InvoiceStateUpdateDesc
725

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

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

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

738
        // UpdateType indicates what type of update is being applied.
739
        UpdateType UpdateType
740
}
741

742
// InvoiceStateUpdateDesc describes an invoice-level state transition.
743
type InvoiceStateUpdateDesc struct {
744
        // NewState is the new state that this invoice should progress to.
745
        NewState ContractState
746

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

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

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

761
// InvoiceUpdateCallback is a callback used in the db transaction to update the
762
// invoice.
763
type InvoiceUpdateCallback = func(invoice *Invoice) (*InvoiceUpdateDesc, error)
764

765
// ValidateInvoice assures the invoice passes the checks for all the relevant
766
// constraints.
767
func ValidateInvoice(i *Invoice, paymentHash lntypes.Hash) error {
1,212✔
768
        // Avoid conflicts with all-zeroes magic value in the database.
1,212✔
769
        if paymentHash == UnknownPreimage.Hash() {
1,212✔
770
                return fmt.Errorf("cannot use hash of all-zeroes preimage")
×
771
        }
×
772

773
        if len(i.Memo) > MaxMemoSize {
1,212✔
774
                return fmt.Errorf("max length a memo is %v, and invoice "+
×
775
                        "of length %v was provided", MaxMemoSize, len(i.Memo))
×
776
        }
×
777
        if len(i.PaymentRequest) > MaxPaymentRequestSize {
1,212✔
778
                return fmt.Errorf("max length of payment request is %v, "+
×
779
                        "length provided was %v", MaxPaymentRequestSize,
×
780
                        len(i.PaymentRequest))
×
781
        }
×
782
        if i.Terms.Features == nil {
1,212✔
783
                return errors.New("invoice must have a feature vector")
×
784
        }
×
785

786
        err := feature.ValidateDeps(i.Terms.Features)
1,212✔
787
        if err != nil {
1,215✔
788
                return err
3✔
789
        }
3✔
790

791
        if i.requiresPreimage() && i.Terms.PaymentPreimage == nil {
1,209✔
792
                return errors.New("this invoice must have a preimage")
×
793
        }
×
794

795
        if len(i.Htlcs) > 0 {
1,212✔
796
                return ErrInvoiceHasHtlcs
3✔
797
        }
3✔
798

799
        return nil
1,206✔
800
}
801

802
// requiresPreimage returns true if the invoice requires a preimage to be valid.
803
func (i *Invoice) requiresPreimage() bool {
1,209✔
804
        // AMP invoices and hodl invoices are allowed to have no preimage
1,209✔
805
        // specified.
1,209✔
806
        if i.HodlInvoice || i.IsAMP() {
1,336✔
807
                return false
127✔
808
        }
127✔
809

810
        return true
1,082✔
811
}
812

813
// IsPending returns true if the invoice is in ContractOpen state.
814
func (i *Invoice) IsPending() bool {
351✔
815
        return i.State == ContractOpen || i.State == ContractAccepted
351✔
816
}
351✔
817

818
// copySlice allocates a new slice and copies the source into it.
819
func copySlice(src []byte) []byte {
2,696✔
820
        dest := make([]byte, len(src))
2,696✔
821
        copy(dest, src)
2,696✔
822
        return dest
2,696✔
823
}
2,696✔
824

825
// CopyInvoice makes a deep copy of the supplied invoice.
826
func CopyInvoice(src *Invoice) (*Invoice, error) {
1,348✔
827
        dest := Invoice{
1,348✔
828
                Memo:           copySlice(src.Memo),
1,348✔
829
                PaymentRequest: copySlice(src.PaymentRequest),
1,348✔
830
                CreationDate:   src.CreationDate,
1,348✔
831
                SettleDate:     src.SettleDate,
1,348✔
832
                Terms:          src.Terms,
1,348✔
833
                AddIndex:       src.AddIndex,
1,348✔
834
                SettleIndex:    src.SettleIndex,
1,348✔
835
                State:          src.State,
1,348✔
836
                AmtPaid:        src.AmtPaid,
1,348✔
837
                Htlcs: make(
1,348✔
838
                        map[CircuitKey]*InvoiceHTLC, len(src.Htlcs),
1,348✔
839
                ),
1,348✔
840
                AMPState:    make(map[SetID]InvoiceStateAMP),
1,348✔
841
                HodlInvoice: src.HodlInvoice,
1,348✔
842
        }
1,348✔
843

1,348✔
844
        dest.Terms.Features = src.Terms.Features.Clone()
1,348✔
845

1,348✔
846
        if src.Terms.PaymentPreimage != nil {
2,522✔
847
                preimage := *src.Terms.PaymentPreimage
1,174✔
848
                dest.Terms.PaymentPreimage = &preimage
1,174✔
849
        }
1,174✔
850

851
        for k, v := range src.Htlcs {
1,928✔
852
                dest.Htlcs[k] = v.Copy()
580✔
853
        }
580✔
854

855
        // Lastly, copy the amp invoice state.
856
        for k, v := range src.AMPState {
1,424✔
857
                ampInvState, err := v.copy()
76✔
858
                if err != nil {
76✔
859
                        return nil, err
×
860
                }
×
861

862
                dest.AMPState[k] = ampInvState
76✔
863
        }
864

865
        return &dest, nil
1,348✔
866
}
867

868
// InvoiceDeleteRef holds a reference to an invoice to be deleted.
869
type InvoiceDeleteRef struct {
870
        // PayHash is the payment hash of the target invoice. All invoices are
871
        // currently indexed by payment hash.
872
        PayHash lntypes.Hash
873

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

879
        // AddIndex is the add index of the invoice.
880
        AddIndex uint64
881

882
        // SettleIndex is the settle index of the invoice.
883
        SettleIndex uint64
884
}
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