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

lightningnetwork / lnd / 13236757158

10 Feb 2025 08:39AM UTC coverage: 57.649% (-1.2%) from 58.815%
13236757158

Pull #9493

github

ziggie1984
lncli: for some cmds we don't replace the data of the response.

For some cmds it is not very practical to replace the json output
because we might pipe it into other commands. For example when
creating the route we want to pipe it into sendtoRoute.
Pull Request #9493: For some lncli cmds we should not replace the content with other data

0 of 9 new or added lines in 2 files covered. (0.0%)

19535 existing lines in 252 files now uncovered.

103517 of 179563 relevant lines covered (57.65%)

24878.49 hits per line

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

77.49
/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 {
22,197✔
94
        return InvoiceRef{
22,197✔
95
                payHash: &payHash,
22,197✔
96
        }
22,197✔
97
}
22,197✔
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,621✔
104

1,621✔
105
        return InvoiceRef{
1,621✔
106
                payHash: &payHash,
1,621✔
107
                payAddr: &payAddr,
1,621✔
108
        }
1,621✔
109
}
1,621✔
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 {
100✔
114
        return InvoiceRef{
100✔
115
                payAddr: &addr,
100✔
116
        }
100✔
117
}
100✔
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 {
37✔
133
        return InvoiceRef{
37✔
134
                setID: &setID,
37✔
135
        }
37✔
136
}
37✔
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 {
46,886✔
152
        if r.payHash != nil {
93,473✔
153
                hash := *r.payHash
46,587✔
154
                return &hash
46,587✔
155
        }
46,587✔
156

157
        return nil
299✔
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,136✔
164
        if r.payAddr != nil {
7,075✔
165
                addr := *r.payAddr
2,939✔
166
                return &addr
2,939✔
167
        }
2,939✔
168

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

181
        return nil
2,817✔
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 {
21,820✔
187
        return r.refModifier
21,820✔
188
}
21,820✔
189

190
// IsHashOnly returns true if the invoice ref only contains a payment hash.
191
func (r InvoiceRef) IsHashOnly() bool {
21,623✔
192
        return r.payHash != nil && r.payAddr == nil && r.setID == nil
21,623✔
193
}
21,623✔
194

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

UNCOV
208
        return fmt.Sprintf("(%s)", strings.Join(ids, ", "))
×
209
}
210

211
// ContractState describes the state the invoice is in.
212
type ContractState uint8
213

214
const (
215
        // ContractOpen means the invoice has only been created.
216
        ContractOpen ContractState = 0
217

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

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

225
        // ContractAccepted means the HTLC has been accepted but not settled
226
        // yet.
227
        ContractAccepted ContractState = 3
228
)
229

230
// String returns a human readable identifier for the ContractState type.
231
func (c ContractState) String() string {
3✔
232
        switch c {
3✔
233
        case ContractOpen:
3✔
234
                return "Open"
3✔
235

236
        case ContractSettled:
×
237
                return "Settled"
×
238

239
        case ContractCanceled:
×
240
                return "Canceled"
×
241

242
        case ContractAccepted:
×
243
                return "Accepted"
×
244
        }
245

246
        return "Unknown"
×
247
}
248

249
// IsFinal returns a boolean indicating whether an invoice state is final.
UNCOV
250
func (c ContractState) IsFinal() bool {
×
UNCOV
251
        return c == ContractSettled || c == ContractCanceled
×
UNCOV
252
}
×
253

254
// ContractTerm is a companion struct to the Invoice struct. This struct houses
255
// the necessary conditions required before the invoice can be considered fully
256
// settled by the payee.
257
type ContractTerm struct {
258
        // FinalCltvDelta is the minimum required number of blocks before htlc
259
        // expiry when the invoice is accepted.
260
        FinalCltvDelta int32
261

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

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

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

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

278
        // Features is the feature vectors advertised on the payment request.
279
        Features *lnwire.FeatureVector
280
}
281

282
// String returns a human-readable description of the prominent contract terms.
283
func (c ContractTerm) String() string {
3✔
284
        return fmt.Sprintf("amt=%v, expiry=%v, final_cltv_delta=%v", c.Value,
3✔
285
                c.Expiry, c.FinalCltvDelta)
3✔
286
}
3✔
287

288
// SetID is the extra unique tuple item for AMP invoices. In addition to
289
// setting a payment address, each repeated payment to an AMP invoice will also
290
// contain a set ID as well.
291
type SetID [32]byte
292

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

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

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

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

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

321
// copy makes a deep copy of the underlying InvoiceStateAMP.
322
func (i *InvoiceStateAMP) copy() (InvoiceStateAMP, error) {
111✔
323
        result := *i
111✔
324

111✔
325
        // Make a copy of the InvoiceKeys map.
111✔
326
        result.InvoiceKeys = make(map[CircuitKey]struct{})
111✔
327
        for k := range i.InvoiceKeys {
264✔
328
                result.InvoiceKeys[k] = struct{}{}
153✔
329
        }
153✔
330

331
        // As a safety measure, copy SettleDate. time.Time is concurrency safe
332
        // except when using any of the (un)marshalling methods.
333
        settleDateBytes, err := i.SettleDate.MarshalBinary()
111✔
334
        if err != nil {
111✔
335
                return InvoiceStateAMP{}, err
×
336
        }
×
337

338
        err = result.SettleDate.UnmarshalBinary(settleDateBytes)
111✔
339
        if err != nil {
111✔
340
                return InvoiceStateAMP{}, err
×
341
        }
×
342

343
        return result, nil
111✔
344
}
345

346
// AMPInvoiceState represents a type that stores metadata related to the set of
347
// settled AMP "sub-invoices".
348
type AMPInvoiceState map[SetID]InvoiceStateAMP
349

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

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

370
        // CreationDate is the exact time the invoice was created.
371
        CreationDate time.Time
372

373
        // SettleDate is the exact time the invoice was settled.
374
        SettleDate time.Time
375

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

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

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

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

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

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

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

424
        // HodlInvoice indicates whether the invoice should be held in the
425
        // Accepted state or be settled right away.
426
        HodlInvoice bool
427
}
428

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

2,294✔
437
        htlcSet := make(map[CircuitKey]*InvoiceHTLC)
2,294✔
438
        for key, htlc := range i.Htlcs {
4,909✔
439
                // Only add HTLCs that are in the requested HtlcState.
2,615✔
440
                if htlc.State != state {
2,730✔
441
                        continue
115✔
442
                }
443

444
                if !htlc.IsInHTLCSet(setID) {
2,623✔
445
                        continue
123✔
446
                }
447

448
                htlcSet[key] = htlc
2,377✔
449
        }
450

451
        return htlcSet
2,294✔
452
}
453

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

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

467
                // We are constructing the compliment, so filter anything that
468
                // matches this set id.
469
                if htlc.IsInHTLCSet(setID) {
6✔
470
                        continue
3✔
471
                }
472

473
                htlcSet[key] = htlc
×
474
        }
475

476
        return htlcSet
473✔
477
}
478

479
// IsKeysend returns true if the invoice is a Keysend invoice.
480
func (i *Invoice) IsKeysend() bool {
20,596✔
481
        // TODO(positiveblue): look for a more reliable way to tests if
20,596✔
482
        // an invoice is keysend.
20,596✔
483
        return len(i.PaymentRequest) == 0 && !i.IsAMP()
20,596✔
484
}
20,596✔
485

486
// IsAMP returns true if the invoice is an AMP invoice.
487
func (i *Invoice) IsAMP() bool {
130,204✔
488
        if i.Terms.Features == nil {
130,204✔
489
                return false
×
490
        }
×
491

492
        return i.Terms.Features.HasFeature(
130,204✔
493
                lnwire.AMPRequired,
130,204✔
494
        )
130,204✔
495
}
496

497
// IsBlinded returns true if the invoice contains blinded paths.
UNCOV
498
func (i *Invoice) IsBlinded() bool {
×
UNCOV
499
        if i.Terms.Features == nil {
×
500
                return false
×
501
        }
×
502

UNCOV
503
        return i.Terms.Features.IsSet(lnwire.Bolt11BlindedPathsRequired)
×
504
}
505

506
// HtlcState defines the states an htlc paying to an invoice can be in.
507
type HtlcState uint8
508

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

513
        // HtlcStateCanceled indicates the htlc is canceled back to the
514
        // sender.
515
        HtlcStateCanceled
516

517
        // HtlcStateSettled indicates the htlc is settled.
518
        HtlcStateSettled
519
)
520

521
// InvoiceHTLC contains details about an htlc paying to this invoice.
522
type InvoiceHTLC struct {
523
        // Amt is the amount that is carried by this htlc.
524
        Amt lnwire.MilliSatoshi
525

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

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

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

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

543
        // Expiry is the expiry height of this htlc.
544
        Expiry uint32
545

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

551
        // CustomRecords contains the custom key/value pairs that accompanied
552
        // the htlc.
553
        CustomRecords record.CustomSet
554

555
        // WireCustomRecords contains the custom key/value pairs that were only
556
        // included in p2p wire message of the HTLC and not in the onion
557
        // payload.
558
        WireCustomRecords lnwire.CustomRecords
559

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

569
// Copy makes a deep copy of the target InvoiceHTLC.
570
func (h *InvoiceHTLC) Copy() *InvoiceHTLC {
663✔
571
        result := *h
663✔
572

663✔
573
        // Make a copy of the CustomSet map.
663✔
574
        result.CustomRecords = make(record.CustomSet)
663✔
575
        for k, v := range h.CustomRecords {
674✔
576
                result.CustomRecords[k] = v
11✔
577
        }
11✔
578

579
        result.WireCustomRecords = h.WireCustomRecords.Copy()
663✔
580
        result.AMP = h.AMP.Copy()
663✔
581

663✔
582
        return &result
663✔
583
}
584

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

3,618✔
592
        // Non-AMP HTLCs cannot be part of AMP HTLC sets, and vice versa.
3,618✔
593
        if wantAMPSet != isAMPHtlc {
3,698✔
594
                return false
80✔
595
        }
80✔
596

597
        // Skip AMP HTLCs that have differing set ids.
598
        if isAMPHtlc && *setID != h.AMP.Record.SetID() {
3,583✔
599
                return false
45✔
600
        }
45✔
601

602
        return true
3,493✔
603
}
604

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

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

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

632
// Copy returns a deep copy of the InvoiceHtlcAMPData.
633
func (d *InvoiceHtlcAMPData) Copy() *InvoiceHtlcAMPData {
735✔
634
        if d == nil {
1,255✔
635
                return nil
520✔
636
        }
520✔
637

638
        var preimage *lntypes.Preimage
215✔
639
        if d.Preimage != nil {
303✔
640
                pimg := *d.Preimage
88✔
641
                preimage = &pimg
88✔
642
        }
88✔
643

644
        return &InvoiceHtlcAMPData{
215✔
645
                Record:   d.Record,
215✔
646
                Hash:     d.Hash,
215✔
647
                Preimage: preimage,
215✔
648
        }
215✔
649
}
650

651
// HtlcAcceptDesc describes the details of a newly accepted htlc.
652
type HtlcAcceptDesc struct {
653
        // AcceptHeight is the block height at which this htlc was accepted.
654
        AcceptHeight int32
655

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

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

663
        // Expiry is the expiry height of this htlc.
664
        Expiry uint32
665

666
        // CustomRecords contains the custom key/value pairs that accompanied
667
        // the htlc.
668
        CustomRecords record.CustomSet
669

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

679
// UpdateType is an enum that describes the type of update that was applied to
680
// an invoice.
681
type UpdateType uint8
682

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

688
        // CancelHTLCsUpdate indicates that this update cancels one or more
689
        // HTLCs.
690
        CancelHTLCsUpdate
691

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

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

699
        // CancelInvoiceUpdate indicates that this update is trying to cancel
700
        // an invoice.
701
        CancelInvoiceUpdate
702
)
703

704
// String returns a human readable string for the UpdateType.
705
func (u UpdateType) String() string {
×
706
        switch u {
×
707
        case CancelHTLCsUpdate:
×
708
                return "CancelHTLCsUpdate"
×
709

710
        case AddHTLCsUpdate:
×
711
                return "AddHTLCsUpdate"
×
712

713
        case SettleHodlInvoiceUpdate:
×
714
                return "SettleHodlInvoiceUpdate"
×
715

716
        case CancelInvoiceUpdate:
×
717
                return "CancelInvoiceUpdate"
×
718

719
        default:
×
720
                return fmt.Sprintf("unknown invoice update type: %d", u)
×
721
        }
722
}
723

724
// InvoiceUpdateDesc describes the changes that should be applied to the
725
// invoice.
726
type InvoiceUpdateDesc struct {
727
        // State is the new state that this invoice should progress to. If nil,
728
        // the state is left unchanged.
729
        State *InvoiceStateUpdateDesc
730

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

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

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

743
        // UpdateType indicates what type of update is being applied.
744
        UpdateType UpdateType
745
}
746

747
// InvoiceStateUpdateDesc describes an invoice-level state transition.
748
type InvoiceStateUpdateDesc struct {
749
        // NewState is the new state that this invoice should progress to.
750
        NewState ContractState
751

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

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

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

766
// InvoiceUpdateCallback is a callback used in the db transaction to update the
767
// invoice.
768
// TODO(ziggie): Add the option of additional return values to the callback
769
// for example the resolution which is currently assigned via an outer scope
770
// variable.
771
type InvoiceUpdateCallback = func(invoice *Invoice) (*InvoiceUpdateDesc, error)
772

773
// ValidateInvoice assures the invoice passes the checks for all the relevant
774
// constraints.
775
func ValidateInvoice(i *Invoice, paymentHash lntypes.Hash) error {
1,221✔
776
        // Avoid conflicts with all-zeroes magic value in the database.
1,221✔
777
        if paymentHash == UnknownPreimage.Hash() {
1,221✔
778
                return fmt.Errorf("cannot use hash of all-zeroes preimage")
×
779
        }
×
780

781
        if len(i.Memo) > MaxMemoSize {
1,221✔
782
                return fmt.Errorf("max length a memo is %v, and invoice "+
×
783
                        "of length %v was provided", MaxMemoSize, len(i.Memo))
×
784
        }
×
785
        if len(i.PaymentRequest) > MaxPaymentRequestSize {
1,221✔
786
                return fmt.Errorf("max length of payment request is %v, "+
×
787
                        "length provided was %v", MaxPaymentRequestSize,
×
788
                        len(i.PaymentRequest))
×
789
        }
×
790
        if i.Terms.Features == nil {
1,221✔
791
                return errors.New("invoice must have a feature vector")
×
792
        }
×
793

794
        err := feature.ValidateDeps(i.Terms.Features)
1,221✔
795
        if err != nil {
1,224✔
796
                return err
3✔
797
        }
3✔
798

799
        if i.requiresPreimage() && i.Terms.PaymentPreimage == nil {
1,218✔
800
                return errors.New("this invoice must have a preimage")
×
801
        }
×
802

803
        if len(i.Htlcs) > 0 {
1,221✔
804
                return ErrInvoiceHasHtlcs
3✔
805
        }
3✔
806

807
        return nil
1,215✔
808
}
809

810
// requiresPreimage returns true if the invoice requires a preimage to be valid.
811
func (i *Invoice) requiresPreimage() bool {
1,218✔
812
        // AMP invoices and hodl invoices are allowed to have no preimage
1,218✔
813
        // specified.
1,218✔
814
        if i.HodlInvoice || i.IsAMP() {
1,351✔
815
                return false
133✔
816
        }
133✔
817

818
        return true
1,085✔
819
}
820

821
// IsPending returns true if the invoice is in ContractOpen state.
822
func (i *Invoice) IsPending() bool {
351✔
823
        return i.State == ContractOpen || i.State == ContractAccepted
351✔
824
}
351✔
825

826
// copySlice allocates a new slice and copies the source into it.
827
func copySlice(src []byte) []byte {
2,794✔
828
        dest := make([]byte, len(src))
2,794✔
829
        copy(dest, src)
2,794✔
830
        return dest
2,794✔
831
}
2,794✔
832

833
// CopyInvoice makes a deep copy of the supplied invoice.
834
func CopyInvoice(src *Invoice) (*Invoice, error) {
1,397✔
835
        dest := Invoice{
1,397✔
836
                Memo:           copySlice(src.Memo),
1,397✔
837
                PaymentRequest: copySlice(src.PaymentRequest),
1,397✔
838
                CreationDate:   src.CreationDate,
1,397✔
839
                SettleDate:     src.SettleDate,
1,397✔
840
                Terms:          src.Terms,
1,397✔
841
                AddIndex:       src.AddIndex,
1,397✔
842
                SettleIndex:    src.SettleIndex,
1,397✔
843
                State:          src.State,
1,397✔
844
                AmtPaid:        src.AmtPaid,
1,397✔
845
                Htlcs: make(
1,397✔
846
                        map[CircuitKey]*InvoiceHTLC, len(src.Htlcs),
1,397✔
847
                ),
1,397✔
848
                AMPState:    make(map[SetID]InvoiceStateAMP),
1,397✔
849
                HodlInvoice: src.HodlInvoice,
1,397✔
850
        }
1,397✔
851

1,397✔
852
        dest.Terms.Features = src.Terms.Features.Clone()
1,397✔
853

1,397✔
854
        if src.Terms.PaymentPreimage != nil {
2,583✔
855
                preimage := *src.Terms.PaymentPreimage
1,186✔
856
                dest.Terms.PaymentPreimage = &preimage
1,186✔
857
        }
1,186✔
858

859
        for k, v := range src.Htlcs {
2,041✔
860
                dest.Htlcs[k] = v.Copy()
644✔
861
        }
644✔
862

863
        // Lastly, copy the amp invoice state.
864
        for k, v := range src.AMPState {
1,508✔
865
                ampInvState, err := v.copy()
111✔
866
                if err != nil {
111✔
867
                        return nil, err
×
868
                }
×
869

870
                dest.AMPState[k] = ampInvState
111✔
871
        }
872

873
        return &dest, nil
1,397✔
874
}
875

876
// InvoiceDeleteRef holds a reference to an invoice to be deleted.
877
type InvoiceDeleteRef struct {
878
        // PayHash is the payment hash of the target invoice. All invoices are
879
        // currently indexed by payment hash.
880
        PayHash lntypes.Hash
881

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

887
        // AddIndex is the add index of the invoice.
888
        AddIndex uint64
889

890
        // SettleIndex is the settle index of the invoice.
891
        SettleIndex uint64
892
}
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