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

lightningnetwork / lnd / 13211764208

08 Feb 2025 03:08AM UTC coverage: 49.288% (-9.5%) from 58.815%
13211764208

Pull #9489

github

calvinrzachman
itest: verify switchrpc server enforces send then track

We prevent the rpc server from allowing onion dispatches for
attempt IDs which have already been tracked by rpc clients.

This helps protect the client from leaking a duplicate onion
attempt. NOTE: This is not the only method for solving this
issue! The issue could be addressed via careful client side
programming which accounts for the uncertainty and async
nature of dispatching onions to a remote process via RPC.
This would require some lnd ChannelRouter changes for how
we intend to use these RPCs though.
Pull Request #9489: multi: add BuildOnion, SendOnion, and TrackOnion RPCs

474 of 990 new or added lines in 11 files covered. (47.88%)

27321 existing lines in 435 files now uncovered.

101192 of 205306 relevant lines covered (49.29%)

1.54 hits per line

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

7.69
/channeldb/migration/lnwire21/features.go
1
package lnwire
2

3
import (
4
        "encoding/binary"
5
        "errors"
6
        "io"
7
)
8

9
var (
10
        // ErrFeaturePairExists signals an error in feature vector construction
11
        // where the opposing bit in a feature pair has already been set.
12
        ErrFeaturePairExists = errors.New("feature pair exists")
13
)
14

15
// FeatureBit represents a feature that can be enabled in either a local or
16
// global feature vector at a specific bit position. Feature bits follow the
17
// "it's OK to be odd" rule, where features at even bit positions must be known
18
// to a node receiving them from a peer while odd bits do not. In accordance,
19
// feature bits are usually assigned in pairs, first being assigned an odd bit
20
// position which may later be changed to the preceding even position once
21
// knowledge of the feature becomes required on the network.
22
type FeatureBit uint16
23

24
const (
25
        // DataLossProtectRequired is a feature bit that indicates that a peer
26
        // *requires* the other party know about the data-loss-protect optional
27
        // feature. If the remote peer does not know of such a feature, then
28
        // the sending peer SHOLUD disconnect them. The data-loss-protect
29
        // feature allows a peer that's lost partial data to recover their
30
        // settled funds of the latest commitment state.
31
        DataLossProtectRequired FeatureBit = 0
32

33
        // DataLossProtectOptional is an optional feature bit that indicates
34
        // that the sending peer knows of this new feature and can activate it
35
        // it. The data-loss-protect feature allows a peer that's lost partial
36
        // data to recover their settled funds of the latest commitment state.
37
        DataLossProtectOptional FeatureBit = 1
38

39
        // InitialRoutingSync is a local feature bit meaning that the receiving
40
        // node should send a complete dump of routing information when a new
41
        // connection is established.
42
        InitialRoutingSync FeatureBit = 3
43

44
        // UpfrontShutdownScriptRequired is a feature bit which indicates that a
45
        // peer *requires* that the remote peer accept an upfront shutdown script to
46
        // which payout is enforced on cooperative closes.
47
        UpfrontShutdownScriptRequired FeatureBit = 4
48

49
        // UpfrontShutdownScriptOptional is an optional feature bit which indicates
50
        // that the peer will accept an upfront shutdown script to which payout is
51
        // enforced on cooperative closes.
52
        UpfrontShutdownScriptOptional FeatureBit = 5
53

54
        // GossipQueriesRequired is a feature bit that indicates that the
55
        // receiving peer MUST know of the set of features that allows nodes to
56
        // more efficiently query the network view of peers on the network for
57
        // reconciliation purposes.
58
        GossipQueriesRequired FeatureBit = 6
59

60
        // GossipQueriesOptional is an optional feature bit that signals that
61
        // the setting peer knows of the set of features that allows more
62
        // efficient network view reconciliation.
63
        GossipQueriesOptional FeatureBit = 7
64

65
        // TLVOnionPayloadRequired is a feature bit that indicates a node is
66
        // able to decode the new TLV information included in the onion packet.
67
        TLVOnionPayloadRequired FeatureBit = 8
68

69
        // TLVOnionPayloadOptional is an optional feature bit that indicates a
70
        // node is able to decode the new TLV information included in the onion
71
        // packet.
72
        TLVOnionPayloadOptional FeatureBit = 9
73

74
        // StaticRemoteKeyRequired is a required feature bit that signals that
75
        // within one's commitment transaction, the key used for the remote
76
        // party's non-delay output should not be tweaked.
77
        StaticRemoteKeyRequired FeatureBit = 12
78

79
        // StaticRemoteKeyOptional is an optional feature bit that signals that
80
        // within one's commitment transaction, the key used for the remote
81
        // party's non-delay output should not be tweaked.
82
        StaticRemoteKeyOptional FeatureBit = 13
83

84
        // PaymentAddrRequired is a required feature bit that signals that a
85
        // node requires payment addresses, which are used to mitigate probing
86
        // attacks on the receiver of a payment.
87
        PaymentAddrRequired FeatureBit = 14
88

89
        // PaymentAddrOptional is an optional feature bit that signals that a
90
        // node supports payment addresses, which are used to mitigate probing
91
        // attacks on the receiver of a payment.
92
        PaymentAddrOptional FeatureBit = 15
93

94
        // MPPOptional is a required feature bit that signals that the receiver
95
        // of a payment requires settlement of an invoice with more than one
96
        // HTLC.
97
        MPPRequired FeatureBit = 16
98

99
        // MPPOptional is an optional feature bit that signals that the receiver
100
        // of a payment supports settlement of an invoice with more than one
101
        // HTLC.
102
        MPPOptional FeatureBit = 17
103

104
        // WumboChannelsRequired is a required feature bit that signals that a
105
        // node is willing to accept channels larger than 2^24 satoshis.
106
        WumboChannelsRequired FeatureBit = 18
107

108
        // WumboChannelsOptional is an optional feature bit that signals that a
109
        // node is willing to accept channels larger than 2^24 satoshis.
110
        WumboChannelsOptional FeatureBit = 19
111

112
        // AnchorsRequired is a required feature bit that signals that the node
113
        // requires channels to be made using commitments having anchor
114
        // outputs.
115
        AnchorsRequired FeatureBit = 20
116

117
        // AnchorsOptional is an optional feature bit that signals that the
118
        // node supports channels to be made using commitments having anchor
119
        // outputs.
120
        AnchorsOptional FeatureBit = 21
121

122
        // AnchorsZeroFeeHtlcTxRequired is a required feature bit that signals
123
        // that the node requires channels having zero-fee second-level HTLC
124
        // transactions, which also imply anchor commitments.
125
        AnchorsZeroFeeHtlcTxRequired FeatureBit = 22
126

127
        // AnchorsZeroFeeHtlcTxRequired is an optional feature bit that signals
128
        // that the node supports channels having zero-fee second-level HTLC
129
        // transactions, which also imply anchor commitments.
130
        AnchorsZeroFeeHtlcTxOptional FeatureBit = 23
131

132
        // maxAllowedSize is a maximum allowed size of feature vector.
133
        //
134
        // NOTE: Within the protocol, the maximum allowed message size is 65535
135
        // bytes for all messages. Accounting for the overhead within the feature
136
        // message to signal the type of message, that leaves us with 65533 bytes
137
        // for the init message itself.  Next, we reserve 4 bytes to encode the
138
        // lengths of both the local and global feature vectors, so 65529 bytes
139
        // for the local and global features. Knocking off one byte for the sake
140
        // of the calculation, that leads us to 32764 bytes for each feature
141
        // vector, or 131056 different features.
142
        maxAllowedSize = 32764
143
)
144

145
// IsRequired returns true if the feature bit is even, and false otherwise.
146
func (b FeatureBit) IsRequired() bool {
×
147
        return b&0x01 == 0x00
×
148
}
×
149

150
// Features is a mapping of known feature bits to a descriptive name. All known
151
// feature bits must be assigned a name in this mapping, and feature bit pairs
152
// must be assigned together for correct behavior.
153
var Features = map[FeatureBit]string{
154
        DataLossProtectRequired:       "data-loss-protect",
155
        DataLossProtectOptional:       "data-loss-protect",
156
        InitialRoutingSync:            "initial-routing-sync",
157
        UpfrontShutdownScriptRequired: "upfront-shutdown-script",
158
        UpfrontShutdownScriptOptional: "upfront-shutdown-script",
159
        GossipQueriesRequired:         "gossip-queries",
160
        GossipQueriesOptional:         "gossip-queries",
161
        TLVOnionPayloadRequired:       "tlv-onion",
162
        TLVOnionPayloadOptional:       "tlv-onion",
163
        StaticRemoteKeyOptional:       "static-remote-key",
164
        StaticRemoteKeyRequired:       "static-remote-key",
165
        PaymentAddrOptional:           "payment-addr",
166
        PaymentAddrRequired:           "payment-addr",
167
        MPPOptional:                   "multi-path-payments",
168
        MPPRequired:                   "multi-path-payments",
169
        AnchorsRequired:               "anchor-commitments",
170
        AnchorsOptional:               "anchor-commitments",
171
        AnchorsZeroFeeHtlcTxRequired:  "anchors-zero-fee-htlc-tx",
172
        AnchorsZeroFeeHtlcTxOptional:  "anchors-zero-fee-htlc-tx",
173
        WumboChannelsRequired:         "wumbo-channels",
174
        WumboChannelsOptional:         "wumbo-channels",
175
}
176

177
// RawFeatureVector represents a set of feature bits as defined in BOLT-09.  A
178
// RawFeatureVector itself just stores a set of bit flags but can be used to
179
// construct a FeatureVector which binds meaning to each bit. Feature vectors
180
// can be serialized and deserialized to/from a byte representation that is
181
// transmitted in Lightning network messages.
182
type RawFeatureVector struct {
183
        features map[FeatureBit]bool
184
}
185

186
// NewRawFeatureVector creates a feature vector with all of the feature bits
187
// given as arguments enabled.
188
func NewRawFeatureVector(bits ...FeatureBit) *RawFeatureVector {
3✔
189
        fv := &RawFeatureVector{features: make(map[FeatureBit]bool)}
3✔
190
        for _, bit := range bits {
3✔
191
                fv.Set(bit)
×
192
        }
×
193
        return fv
3✔
194
}
195

196
// Merges sets all feature bits in other on the receiver's feature vector.
197
func (fv *RawFeatureVector) Merge(other *RawFeatureVector) error {
×
198
        for bit := range other.features {
×
199
                err := fv.SafeSet(bit)
×
200
                if err != nil {
×
201
                        return err
×
202
                }
×
203
        }
204
        return nil
×
205
}
206

207
// Clone makes a copy of a feature vector.
208
func (fv *RawFeatureVector) Clone() *RawFeatureVector {
×
209
        newFeatures := NewRawFeatureVector()
×
210
        for bit := range fv.features {
×
211
                newFeatures.Set(bit)
×
212
        }
×
213
        return newFeatures
×
214
}
215

216
// IsSet returns whether a particular feature bit is enabled in the vector.
217
func (fv *RawFeatureVector) IsSet(feature FeatureBit) bool {
×
218
        return fv.features[feature]
×
219
}
×
220

221
// Set marks a feature as enabled in the vector.
222
func (fv *RawFeatureVector) Set(feature FeatureBit) {
×
223
        fv.features[feature] = true
×
224
}
×
225

226
// SafeSet sets the chosen feature bit in the feature vector, but returns an
227
// error if the opposing feature bit is already set. This ensures both that we
228
// are creating properly structured feature vectors, and in some cases, that
229
// peers are sending properly encoded ones, i.e. it can't be both optional and
230
// required.
231
func (fv *RawFeatureVector) SafeSet(feature FeatureBit) error {
×
232
        if _, ok := fv.features[feature^1]; ok {
×
233
                return ErrFeaturePairExists
×
234
        }
×
235

236
        fv.Set(feature)
×
237
        return nil
×
238
}
239

240
// Unset marks a feature as disabled in the vector.
241
func (fv *RawFeatureVector) Unset(feature FeatureBit) {
×
242
        delete(fv.features, feature)
×
243
}
×
244

245
// SerializeSize returns the number of bytes needed to represent feature vector
246
// in byte format.
UNCOV
247
func (fv *RawFeatureVector) SerializeSize() int {
×
UNCOV
248
        // We calculate byte-length via the largest bit index.
×
UNCOV
249
        return fv.serializeSize(8)
×
UNCOV
250
}
×
251

252
// SerializeSize32 returns the number of bytes needed to represent feature
253
// vector in base32 format.
254
func (fv *RawFeatureVector) SerializeSize32() int {
×
255
        // We calculate base32-length via the largest bit index.
×
256
        return fv.serializeSize(5)
×
257
}
×
258

259
// serializeSize returns the number of bytes required to encode the feature
260
// vector using at most width bits per encoded byte.
UNCOV
261
func (fv *RawFeatureVector) serializeSize(width int) int {
×
UNCOV
262
        // Find the largest feature bit index
×
UNCOV
263
        max := -1
×
UNCOV
264
        for feature := range fv.features {
×
265
                index := int(feature)
×
266
                if index > max {
×
267
                        max = index
×
268
                }
×
269
        }
UNCOV
270
        if max == -1 {
×
UNCOV
271
                return 0
×
UNCOV
272
        }
×
273

274
        return max/width + 1
×
275
}
276

277
// Encode writes the feature vector in byte representation. Every feature
278
// encoded as a bit, and the bit vector is serialized using the least number of
279
// bytes. Since the bit vector length is variable, the first two bytes of the
280
// serialization represent the length.
UNCOV
281
func (fv *RawFeatureVector) Encode(w io.Writer) error {
×
UNCOV
282
        // Write length of feature vector.
×
UNCOV
283
        var l [2]byte
×
UNCOV
284
        length := fv.SerializeSize()
×
UNCOV
285
        binary.BigEndian.PutUint16(l[:], uint16(length))
×
UNCOV
286
        if _, err := w.Write(l[:]); err != nil {
×
287
                return err
×
288
        }
×
289

UNCOV
290
        return fv.encode(w, length, 8)
×
291
}
292

293
// EncodeBase256 writes the feature vector in base256 representation. Every
294
// feature is encoded as a bit, and the bit vector is serialized using the least
295
// number of bytes.
UNCOV
296
func (fv *RawFeatureVector) EncodeBase256(w io.Writer) error {
×
UNCOV
297
        length := fv.SerializeSize()
×
UNCOV
298
        return fv.encode(w, length, 8)
×
UNCOV
299
}
×
300

301
// EncodeBase32 writes the feature vector in base32 representation. Every feature
302
// is encoded as a bit, and the bit vector is serialized using the least number of
303
// bytes.
304
func (fv *RawFeatureVector) EncodeBase32(w io.Writer) error {
×
305
        length := fv.SerializeSize32()
×
306
        return fv.encode(w, length, 5)
×
307
}
×
308

309
// encode writes the feature vector
UNCOV
310
func (fv *RawFeatureVector) encode(w io.Writer, length, width int) error {
×
UNCOV
311
        // Generate the data and write it.
×
UNCOV
312
        data := make([]byte, length)
×
UNCOV
313
        for feature := range fv.features {
×
314
                byteIndex := int(feature) / width
×
315
                bitIndex := int(feature) % width
×
316
                data[length-byteIndex-1] |= 1 << uint(bitIndex)
×
317
        }
×
318

UNCOV
319
        _, err := w.Write(data)
×
UNCOV
320
        return err
×
321
}
322

323
// Decode reads the feature vector from its byte representation. Every feature
324
// is encoded as a bit, and the bit vector is serialized using the least number
325
// of bytes. Since the bit vector length is variable, the first two bytes of the
326
// serialization represent the length.
UNCOV
327
func (fv *RawFeatureVector) Decode(r io.Reader) error {
×
UNCOV
328
        // Read the length of the feature vector.
×
UNCOV
329
        var l [2]byte
×
UNCOV
330
        if _, err := io.ReadFull(r, l[:]); err != nil {
×
331
                return err
×
332
        }
×
UNCOV
333
        length := binary.BigEndian.Uint16(l[:])
×
UNCOV
334

×
UNCOV
335
        return fv.decode(r, int(length), 8)
×
336
}
337

338
// DecodeBase256 reads the feature vector from its base256 representation. Every
339
// feature encoded as a bit, and the bit vector is serialized using the least
340
// number of bytes.
341
func (fv *RawFeatureVector) DecodeBase256(r io.Reader, length int) error {
×
342
        return fv.decode(r, length, 8)
×
343
}
×
344

345
// DecodeBase32 reads the feature vector from its base32 representation. Every
346
// feature encoded as a bit, and the bit vector is serialized using the least
347
// number of bytes.
348
func (fv *RawFeatureVector) DecodeBase32(r io.Reader, length int) error {
×
349
        return fv.decode(r, length, 5)
×
350
}
×
351

352
// decode reads a feature vector from the next length bytes of the io.Reader,
353
// assuming each byte has width feature bits encoded per byte.
UNCOV
354
func (fv *RawFeatureVector) decode(r io.Reader, length, width int) error {
×
UNCOV
355
        // Read the feature vector data.
×
UNCOV
356
        data := make([]byte, length)
×
UNCOV
357
        if _, err := io.ReadFull(r, data); err != nil {
×
358
                return err
×
359
        }
×
360

361
        // Set feature bits from parsed data.
UNCOV
362
        bitsNumber := len(data) * width
×
UNCOV
363
        for i := 0; i < bitsNumber; i++ {
×
364
                byteIndex := int(i / width)
×
365
                bitIndex := uint(i % width)
×
366
                if (data[length-byteIndex-1]>>bitIndex)&1 == 1 {
×
367
                        fv.Set(FeatureBit(i))
×
368
                }
×
369
        }
370

UNCOV
371
        return nil
×
372
}
373

374
// FeatureVector represents a set of enabled features. The set stores
375
// information on enabled flags and metadata about the feature names. A feature
376
// vector is serializable to a compact byte representation that is included in
377
// Lightning network messages.
378
type FeatureVector struct {
379
        *RawFeatureVector
380
        featureNames map[FeatureBit]string
381
}
382

383
// NewFeatureVector constructs a new FeatureVector from a raw feature vector
384
// and mapping of feature definitions. If the feature vector argument is nil, a
385
// new one will be constructed with no enabled features.
386
func NewFeatureVector(featureVector *RawFeatureVector,
387
        featureNames map[FeatureBit]string) *FeatureVector {
3✔
388

3✔
389
        if featureVector == nil {
6✔
390
                featureVector = NewRawFeatureVector()
3✔
391
        }
3✔
392
        return &FeatureVector{
3✔
393
                RawFeatureVector: featureVector,
3✔
394
                featureNames:     featureNames,
3✔
395
        }
3✔
396
}
397

398
// EmptyFeatureVector returns a feature vector with no bits set.
399
func EmptyFeatureVector() *FeatureVector {
×
400
        return NewFeatureVector(nil, Features)
×
401
}
×
402

403
// HasFeature returns whether a particular feature is included in the set. The
404
// feature can be seen as set either if the bit is set directly OR the queried
405
// bit has the same meaning as its corresponding even/odd bit, which is set
406
// instead. The second case is because feature bits are generally assigned in
407
// pairs where both the even and odd position represent the same feature.
408
func (fv *FeatureVector) HasFeature(feature FeatureBit) bool {
×
409
        return fv.IsSet(feature) ||
×
410
                (fv.isFeatureBitPair(feature) && fv.IsSet(feature^1))
×
411
}
×
412

413
// RequiresFeature returns true if the referenced feature vector *requires*
414
// that the given required bit be set. This method can be used with both
415
// optional and required feature bits as a parameter.
416
func (fv *FeatureVector) RequiresFeature(feature FeatureBit) bool {
×
417
        // If we weren't passed a required feature bit, then we'll flip the
×
418
        // lowest bit to query for the required version of the feature. This
×
419
        // lets callers pass in both the optional and required bits.
×
420
        if !feature.IsRequired() {
×
421
                feature ^= 1
×
422
        }
×
423

424
        return fv.IsSet(feature)
×
425
}
426

427
// UnknownRequiredFeatures returns a list of feature bits set in the vector
428
// that are unknown and in an even bit position. Feature bits with an even
429
// index must be known to a node receiving the feature vector in a message.
430
func (fv *FeatureVector) UnknownRequiredFeatures() []FeatureBit {
×
431
        var unknown []FeatureBit
×
432
        for feature := range fv.features {
×
433
                if feature%2 == 0 && !fv.IsKnown(feature) {
×
434
                        unknown = append(unknown, feature)
×
435
                }
×
436
        }
437
        return unknown
×
438
}
439

440
// Name returns a string identifier for the feature represented by this bit. If
441
// the bit does not represent a known feature, this returns a string indicating
442
// as such.
443
func (fv *FeatureVector) Name(bit FeatureBit) string {
×
444
        name, known := fv.featureNames[bit]
×
445
        if !known {
×
446
                return "unknown"
×
447
        }
×
448
        return name
×
449
}
450

451
// IsKnown returns whether this feature bit represents a known feature.
452
func (fv *FeatureVector) IsKnown(bit FeatureBit) bool {
×
453
        _, known := fv.featureNames[bit]
×
454
        return known
×
455
}
×
456

457
// isFeatureBitPair returns whether this feature bit and its corresponding
458
// even/odd bit both represent the same feature. This may often be the case as
459
// bits are generally assigned in pairs, first being assigned an odd bit
460
// position then being promoted to an even bit position once the network is
461
// ready.
462
func (fv *FeatureVector) isFeatureBitPair(bit FeatureBit) bool {
×
463
        name1, known1 := fv.featureNames[bit]
×
464
        name2, known2 := fv.featureNames[bit^1]
×
465
        return known1 && known2 && name1 == name2
×
466
}
×
467

468
// Features returns the set of raw features contained in the feature vector.
469
func (fv *FeatureVector) Features() map[FeatureBit]struct{} {
×
470
        fs := make(map[FeatureBit]struct{}, len(fv.RawFeatureVector.features))
×
471
        for b := range fv.RawFeatureVector.features {
×
472
                fs[b] = struct{}{}
×
473
        }
×
474
        return fs
×
475
}
476

477
// Clone copies a feature vector, carrying over its feature bits. The feature
478
// names are not copied.
479
func (fv *FeatureVector) Clone() *FeatureVector {
×
480
        features := fv.RawFeatureVector.Clone()
×
481
        return NewFeatureVector(features, fv.featureNames)
×
482
}
×
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