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

lightningnetwork / lnd / 12986279612

27 Jan 2025 09:51AM UTC coverage: 57.652% (-1.1%) from 58.788%
12986279612

Pull #9447

github

yyforyongyu
sweep: rename methods for clarity

We now rename "third party" to "unknown" as the inputs can be spent via
an older sweeping tx, a third party (anchor), or a remote party (pin).
In fee bumper we don't have the info to distinguish the above cases, and
leave them to be further handled by the sweeper as it has more context.
Pull Request #9447: sweep: start tracking input spending status in the fee bumper

83 of 87 new or added lines in 2 files covered. (95.4%)

19578 existing lines in 256 files now uncovered.

103448 of 179434 relevant lines covered (57.65%)

24884.58 hits per line

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

69.57
/zpay32/invoice.go
1
package zpay32
2

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

8
        "github.com/btcsuite/btcd/btcec/v2"
9
        "github.com/btcsuite/btcd/btcutil"
10
        "github.com/btcsuite/btcd/chaincfg"
11
        "github.com/lightningnetwork/lnd/fn/v2"
12
        "github.com/lightningnetwork/lnd/lnwire"
13
)
14

15
const (
16
        // mSatPerBtc is the number of millisatoshis in 1 BTC.
17
        mSatPerBtc = 100000000000
18

19
        // signatureBase32Len is the number of 5-bit groups needed to encode
20
        // the 512 bit signature + 8 bit recovery ID.
21
        signatureBase32Len = 104
22

23
        // timestampBase32Len is the number of 5-bit groups needed to encode
24
        // the 35-bit timestamp.
25
        timestampBase32Len = 7
26

27
        // hashBase32Len is the number of 5-bit groups needed to encode a
28
        // 256-bit hash. Note that the last group will be padded with zeroes.
29
        hashBase32Len = 52
30

31
        // pubKeyBase32Len is the number of 5-bit groups needed to encode a
32
        // 33-byte compressed pubkey. Note that the last group will be padded
33
        // with zeroes.
34
        pubKeyBase32Len = 53
35

36
        // hopHintLen is the number of bytes needed to encode the hop hint of a
37
        // single private route.
38
        hopHintLen = 51
39

40
        // The following byte values correspond to the supported field types.
41
        // The field name is the character representing that 5-bit value in the
42
        // bech32 string.
43

44
        // fieldTypeP is the field containing the payment hash.
45
        fieldTypeP = 1
46

47
        // fieldTypeD contains a short description of the payment.
48
        fieldTypeD = 13
49

50
        // fieldTypeM contains the payment metadata.
51
        fieldTypeM = 27
52

53
        // fieldTypeN contains the pubkey of the target node.
54
        fieldTypeN = 19
55

56
        // fieldTypeH contains the hash of a description of the payment.
57
        fieldTypeH = 23
58

59
        // fieldTypeX contains the expiry in seconds of the invoice.
60
        fieldTypeX = 6
61

62
        // fieldTypeF contains a fallback on-chain address.
63
        fieldTypeF = 9
64

65
        // fieldTypeR contains extra routing information.
66
        fieldTypeR = 3
67

68
        // fieldTypeC contains an optional requested final CLTV delta.
69
        fieldTypeC = 24
70

71
        // fieldType9 contains one or more bytes for signaling features
72
        // supported or required by the receiver.
73
        fieldType9 = 5
74

75
        // fieldTypeS contains a 32-byte payment address, which is a nonce
76
        // included in the final hop's payload to prevent intermediaries from
77
        // probing the recipient.
78
        fieldTypeS = 16
79

80
        // fieldTypeB contains blinded payment path information. This field may
81
        // be repeated to include multiple blinded payment paths in the invoice.
82
        fieldTypeB = 20
83

84
        // maxInvoiceLength is the maximum total length an invoice can have.
85
        // This is chosen to be the maximum number of bytes that can fit into a
86
        // single QR code: https://en.wikipedia.org/wiki/QR_code#Storage
87
        maxInvoiceLength = 7089
88

89
        // DefaultInvoiceExpiry is the default expiry duration from the creation
90
        // timestamp if expiry is set to zero.
91
        DefaultInvoiceExpiry = time.Hour
92
)
93

94
var (
95
        // ErrInvoiceTooLarge is returned when an invoice exceeds
96
        // maxInvoiceLength.
97
        ErrInvoiceTooLarge = errors.New("invoice is too large")
98

99
        // ErrInvalidFieldLength is returned when a tagged field was specified
100
        // with a length larger than the left over bytes of the data field.
101
        ErrInvalidFieldLength = errors.New("invalid field length")
102

103
        // ErrBrokenTaggedField is returned when the last tagged field is
104
        // incorrectly formatted and doesn't have enough bytes to be read.
105
        ErrBrokenTaggedField = errors.New("last tagged field is broken")
106
)
107

108
// MessageSigner is passed to the Encode method to provide a signature
109
// corresponding to the node's pubkey.
110
type MessageSigner struct {
111
        // SignCompact signs the hash of the passed msg with the node's privkey.
112
        // The returned signature should be 65 bytes, where the last 64 are the
113
        // compact signature, and the first one is a header byte. This is the
114
        // format returned by ecdsa.SignCompact.
115
        SignCompact func(msg []byte) ([]byte, error)
116
}
117

118
// Invoice represents a decoded invoice, or to-be-encoded invoice. Some of the
119
// fields are optional, and will only be non-nil if the invoice this was parsed
120
// from contains that field. When encoding, only the non-nil fields will be
121
// added to the encoded invoice.
122
type Invoice struct {
123
        // Net specifies what network this Lightning invoice is meant for.
124
        Net *chaincfg.Params
125

126
        // MilliSat specifies the amount of this invoice in millisatoshi.
127
        // Optional.
128
        MilliSat *lnwire.MilliSatoshi
129

130
        // Timestamp specifies the time this invoice was created.
131
        // Mandatory
132
        Timestamp time.Time
133

134
        // PaymentHash is the payment hash to be used for a payment to this
135
        // invoice.
136
        PaymentHash *[32]byte
137

138
        // PaymentAddr is the payment address to be used by payments to prevent
139
        // probing of the destination.
140
        PaymentAddr fn.Option[[32]byte]
141

142
        // Destination is the public key of the target node. This will always
143
        // be set after decoding, and can optionally be set before encoding to
144
        // include the pubkey as an 'n' field. If this is not set before
145
        // encoding then the destination pubkey won't be added as an 'n' field,
146
        // and the pubkey will be extracted from the signature during decoding.
147
        Destination *btcec.PublicKey
148

149
        // minFinalCLTVExpiry is the value that the creator of the invoice
150
        // expects to be used for the CLTV expiry of the HTLC extended to it in
151
        // the last hop.
152
        //
153
        // NOTE: This value is optional, and should be set to nil if the
154
        // invoice creator doesn't have a strong requirement on the CLTV expiry
155
        // of the final HTLC extended to it.
156
        //
157
        // This field is un-exported and can only be read by the
158
        // MinFinalCLTVExpiry() method. By forcing callers to read via this
159
        // method, we can easily enforce the default if not specified.
160
        //
161
        // NOTE: this field is ignored in the case that the invoice contains
162
        // blinded paths since then the final minimum cltv expiry delta is
163
        // expected to be included in the route's accumulated CLTV delta value.
164
        minFinalCLTVExpiry *uint64
165

166
        // Description is a short description of the purpose of this invoice.
167
        // Optional. Non-nil iff DescriptionHash is nil.
168
        Description *string
169

170
        // DescriptionHash is the SHA256 hash of a description of the purpose of
171
        // this invoice.
172
        // Optional. Non-nil iff Description is nil.
173
        DescriptionHash *[32]byte
174

175
        // expiry specifies the timespan this invoice will be valid.
176
        // Optional. If not set, a default expiry of 60 min will be implied.
177
        //
178
        // This field is unexported and can be read by the Expiry() method. This
179
        // method makes sure the default expiry time is returned in case the
180
        // field is not set.
181
        expiry *time.Duration
182

183
        // FallbackAddr is an on-chain address that can be used for payment in
184
        // case the Lightning payment fails.
185
        // Optional.
186
        FallbackAddr btcutil.Address
187

188
        // RouteHints represents one or more different route hints. Each route
189
        // hint can be individually used to reach the destination. These usually
190
        // represent private routes.
191
        //
192
        // NOTE: This is optional and should not be set at the same time as
193
        // BlindedPaymentPaths.
194
        RouteHints [][]HopHint
195

196
        // BlindedPaymentPaths is a set of blinded payment paths that can be
197
        // used to find the payment receiver.
198
        //
199
        // NOTE: This is optional and should not be set at the same time as
200
        // RouteHints.
201
        BlindedPaymentPaths []*BlindedPaymentPath
202

203
        // Features represents an optional field used to signal optional or
204
        // required support for features by the receiver.
205
        Features *lnwire.FeatureVector
206

207
        // Metadata is additional data that is sent along with the payment to
208
        // the payee.
209
        Metadata []byte
210
}
211

212
// Amount is a functional option that allows callers of NewInvoice to set the
213
// amount in millisatoshis that the Invoice should encode.
214
func Amount(milliSat lnwire.MilliSatoshi) func(*Invoice) {
98✔
215
        return func(i *Invoice) {
196✔
216
                i.MilliSat = &milliSat
98✔
217
        }
98✔
218
}
219

220
// Destination is a functional option that allows callers of NewInvoice to
221
// explicitly set the pubkey of the Invoice's destination node.
222
func Destination(destination *btcec.PublicKey) func(*Invoice) {
7✔
223
        return func(i *Invoice) {
14✔
224
                i.Destination = destination
7✔
225
        }
7✔
226
}
227

228
// Description is a functional option that allows callers of NewInvoice to set
229
// the payment description of the created Invoice.
230
//
231
// NOTE: Must be used if and only if DescriptionHash is not used.
232
func Description(description string) func(*Invoice) {
103✔
233
        return func(i *Invoice) {
206✔
234
                i.Description = &description
103✔
235
        }
103✔
236
}
237

238
// CLTVExpiry is an optional value which allows the receiver of the payment to
239
// specify the delta between the current height and the HTLC extended to the
240
// receiver.
241
func CLTVExpiry(delta uint64) func(*Invoice) {
4✔
242
        return func(i *Invoice) {
8✔
243
                i.minFinalCLTVExpiry = &delta
4✔
244
        }
4✔
245
}
246

247
// DescriptionHash is a functional option that allows callers of NewInvoice to
248
// set the payment description hash of the created Invoice.
249
//
250
// NOTE: Must be used if and only if Description is not used.
251
func DescriptionHash(descriptionHash [32]byte) func(*Invoice) {
2✔
252
        return func(i *Invoice) {
4✔
253
                i.DescriptionHash = &descriptionHash
2✔
254
        }
2✔
255
}
256

257
// Expiry is a functional option that allows callers of NewInvoice to set the
258
// expiry of the created Invoice. If not set, a default expiry of 60 min will
259
// be implied.
260
func Expiry(expiry time.Duration) func(*Invoice) {
91✔
261
        return func(i *Invoice) {
182✔
262
                i.expiry = &expiry
91✔
263
        }
91✔
264
}
265

266
// FallbackAddr is a functional option that allows callers of NewInvoice to set
267
// the Invoice's fallback on-chain address that can be used for payment in case
268
// the Lightning payment fails
269
func FallbackAddr(fallbackAddr btcutil.Address) func(*Invoice) {
1✔
270
        return func(i *Invoice) {
2✔
271
                i.FallbackAddr = fallbackAddr
1✔
272
        }
1✔
273
}
274

275
// RouteHint is a functional option that allows callers of NewInvoice to add
276
// one or more hop hints that represent a private route to the destination.
277
func RouteHint(routeHint []HopHint) func(*Invoice) {
1✔
278
        return func(i *Invoice) {
2✔
279
                i.RouteHints = append(i.RouteHints, routeHint)
1✔
280
        }
1✔
281
}
282

283
// WithBlindedPaymentPath is a functional option that allows a caller of
284
// NewInvoice to attach a blinded payment path to the invoice. The option can
285
// be used multiple times to attach multiple paths.
286
func WithBlindedPaymentPath(p *BlindedPaymentPath) func(*Invoice) {
2✔
287
        return func(i *Invoice) {
4✔
288
                i.BlindedPaymentPaths = append(i.BlindedPaymentPaths, p)
2✔
289
        }
2✔
290
}
291

292
// Features is a functional option that allows callers of NewInvoice to set the
293
// desired feature bits that are advertised on the invoice. If this option is
294
// not used, an empty feature vector will automatically be populated.
UNCOV
295
func Features(features *lnwire.FeatureVector) func(*Invoice) {
×
UNCOV
296
        return func(i *Invoice) {
×
UNCOV
297
                i.Features = features
×
UNCOV
298
        }
×
299
}
300

301
// PaymentAddr is a functional option that allows callers of NewInvoice to set
302
// the desired payment address that is advertised on the invoice.
303
func PaymentAddr(addr [32]byte) func(*Invoice) {
90✔
304
        return func(i *Invoice) {
180✔
305
                i.PaymentAddr = fn.Some(addr)
90✔
306
        }
90✔
307
}
308

309
// Metadata is a functional option that allows callers of NewInvoice to set
310
// the desired payment Metadata that is advertised on the invoice.
311
func Metadata(metadata []byte) func(*Invoice) {
×
312
        return func(i *Invoice) {
×
313
                i.Metadata = metadata
×
314
        }
×
315
}
316

317
// NewInvoice creates a new Invoice object. The last parameter is a set of
318
// variadic arguments for setting optional fields of the invoice.
319
//
320
// NOTE: Either Description  or DescriptionHash must be provided for the Invoice
321
// to be considered valid.
322
func NewInvoice(net *chaincfg.Params, paymentHash [32]byte,
323
        timestamp time.Time, options ...func(*Invoice)) (*Invoice, error) {
104✔
324

104✔
325
        invoice := &Invoice{
104✔
326
                Net:         net,
104✔
327
                PaymentHash: &paymentHash,
104✔
328
                Timestamp:   timestamp,
104✔
329
        }
104✔
330

104✔
331
        for _, option := range options {
503✔
332
                option(invoice)
399✔
333
        }
399✔
334

335
        // If no features were set, we'll populate an empty feature vector.
336
        if invoice.Features == nil {
208✔
337
                invoice.Features = lnwire.NewFeatureVector(
104✔
338
                        nil, lnwire.Features,
104✔
339
                )
104✔
340
        }
104✔
341

342
        if err := validateInvoice(invoice); err != nil {
105✔
343
                return nil, err
1✔
344
        }
1✔
345

346
        return invoice, nil
103✔
347
}
348

349
// Expiry returns the expiry time for this invoice. If expiry time is not set
350
// explicitly, the default 3600 second expiry will be returned.
UNCOV
351
func (invoice *Invoice) Expiry() time.Duration {
×
UNCOV
352
        if invoice.expiry != nil {
×
UNCOV
353
                return *invoice.expiry
×
UNCOV
354
        }
×
355

356
        // If no expiry is set for this invoice, default is 3600 seconds.
357
        return DefaultInvoiceExpiry
×
358
}
359

360
// MinFinalCLTVExpiry returns the minimum final CLTV expiry delta as specified
361
// by the creator of the invoice. This value specifies the delta between the
362
// current height and the expiry height of the HTLC extended in the last hop.
UNCOV
363
func (invoice *Invoice) MinFinalCLTVExpiry() uint64 {
×
UNCOV
364
        if invoice.minFinalCLTVExpiry != nil {
×
UNCOV
365
                return *invoice.minFinalCLTVExpiry
×
UNCOV
366
        }
×
367

UNCOV
368
        return DefaultAssumedFinalCLTVDelta
×
369
}
370

371
// validateInvoice does a sanity check of the provided Invoice, making sure it
372
// has all the necessary fields set for it to be considered valid by BOLT-0011.
373
func validateInvoice(invoice *Invoice) error {
509✔
374
        // The net must be set.
509✔
375
        if invoice.Net == nil {
509✔
376
                return fmt.Errorf("net params not set")
×
377
        }
×
378

379
        // The invoice must contain a payment hash.
380
        if invoice.PaymentHash == nil {
572✔
381
                return fmt.Errorf("no payment hash found")
63✔
382
        }
63✔
383

384
        if len(invoice.RouteHints) != 0 &&
446✔
385
                len(invoice.BlindedPaymentPaths) != 0 {
446✔
386

×
387
                return fmt.Errorf("cannot have both route hints and blinded " +
×
388
                        "payment paths")
×
389
        }
×
390

391
        // Either Description or DescriptionHash must be set, not both.
392
        if invoice.Description != nil && invoice.DescriptionHash != nil {
450✔
393
                return fmt.Errorf("both description and description hash set")
4✔
394
        }
4✔
395
        if invoice.Description == nil && invoice.DescriptionHash == nil {
446✔
396
                return fmt.Errorf("neither description nor description hash set")
4✔
397
        }
4✔
398

399
        // Check that we support the field lengths.
400
        if len(invoice.PaymentHash) != 32 {
438✔
401
                return fmt.Errorf("unsupported payment hash length: %d",
×
402
                        len(invoice.PaymentHash))
×
403
        }
×
404

405
        if invoice.DescriptionHash != nil && len(invoice.DescriptionHash) != 32 {
438✔
406
                return fmt.Errorf("unsupported description hash length: %d",
×
407
                        len(invoice.DescriptionHash))
×
408
        }
×
409

410
        if invoice.Destination != nil &&
438✔
411
                len(invoice.Destination.SerializeCompressed()) != 33 {
438✔
412
                return fmt.Errorf("unsupported pubkey length: %d",
×
413
                        len(invoice.Destination.SerializeCompressed()))
×
414
        }
×
415

416
        // Ensure that all invoices have feature vectors.
417
        if invoice.Features == nil {
438✔
418
                return fmt.Errorf("missing feature vector")
×
419
        }
×
420

421
        return nil
438✔
422
}
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