• 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

63.54
/feature/manager.go
1
package feature
2

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

7
        "github.com/lightningnetwork/lnd/lnwire"
8
)
9

10
var (
11
        // ErrUnknownSet is returned if a proposed feature vector contains a
12
        // set that is unknown to LND.
13
        ErrUnknownSet = errors.New("unknown feature bit set")
14

15
        // ErrFeatureConfigured is returned if an attempt is made to unset a
16
        // feature that was configured at startup.
17
        ErrFeatureConfigured = errors.New("can't unset configured feature")
18
)
19

20
// Config houses any runtime modifications to the default set descriptors. For
21
// our purposes, this typically means disabling certain features to test legacy
22
// protocol interoperability or functionality.
23
type Config struct {
24
        // NoTLVOnion unsets any optional or required TLVOnionPaylod bits from
25
        // all feature sets.
26
        NoTLVOnion bool
27

28
        // NoStaticRemoteKey unsets any optional or required StaticRemoteKey
29
        // bits from all feature sets.
30
        NoStaticRemoteKey bool
31

32
        // NoAnchors unsets any bits signaling support for anchor outputs.
33
        NoAnchors bool
34

35
        // NoWumbo unsets any bits signalling support for wumbo channels.
36
        NoWumbo bool
37

38
        // NoTaprootChans unsets any bits signaling support for taproot
39
        // channels.
40
        NoTaprootChans bool
41

42
        // NoScriptEnforcementLease unsets any bits signaling support for script
43
        // enforced leases.
44
        NoScriptEnforcementLease bool
45

46
        // NoKeysend unsets any bits signaling support for accepting keysend
47
        // payments.
48
        NoKeysend bool
49

50
        // NoOptionScidAlias unsets any bits signalling support for
51
        // option_scid_alias. This also implicitly disables zero-conf channels.
52
        NoOptionScidAlias bool
53

54
        // NoZeroConf unsets any bits signalling support for zero-conf
55
        // channels. This should be used instead of NoOptionScidAlias to still
56
        // keep option-scid-alias support.
57
        NoZeroConf bool
58

59
        // NoAnySegwit unsets any bits that signal support for using other
60
        // segwit witness versions for co-op closes.
61
        NoAnySegwit bool
62

63
        // NoRouteBlinding unsets route blinding feature bits.
64
        NoRouteBlinding bool
65

66
        // NoQuiescence unsets quiescence feature bits.
67
        NoQuiescence bool
68

69
        // NoTaprootOverlay unsets the taproot overlay channel feature bits.
70
        NoTaprootOverlay bool
71

72
        // NoExperimentalEndorsement unsets any bits that signal support for
73
        // forwarding experimental endorsement.
74
        NoExperimentalEndorsement bool
75

76
        // CustomFeatures is a set of custom features to advertise in each
77
        // set.
78
        CustomFeatures map[Set][]lnwire.FeatureBit
79
}
80

81
// Manager is responsible for generating feature vectors for different requested
82
// feature sets.
83
type Manager struct {
84
        // fsets is a static map of feature set to raw feature vectors. Requests
85
        // are fulfilled by cloning these internal feature vectors.
86
        fsets map[Set]*lnwire.RawFeatureVector
87

88
        // configFeatures is a set of custom features that were "hard set" in
89
        // lnd's config that cannot be updated at runtime (as is the case with
90
        // our "standard" features that are defined in LND).
91
        configFeatures map[Set]*lnwire.FeatureVector
92
}
93

94
// NewManager creates a new feature Manager, applying any custom modifications
95
// to its feature sets before returning.
UNCOV
96
func NewManager(cfg Config) (*Manager, error) {
×
UNCOV
97
        return newManager(cfg, defaultSetDesc)
×
UNCOV
98
}
×
99

100
// newManager creates a new feature Manager, applying any custom modifications
101
// to its feature sets before returning. This method accepts the setDesc as its
102
// own parameter so that it can be unit tested.
103
func newManager(cfg Config, desc setDesc) (*Manager, error) {
16✔
104
        // First build the default feature vector for all known sets.
16✔
105
        fsets := make(map[Set]*lnwire.RawFeatureVector)
16✔
106
        for bit, sets := range desc {
53✔
107
                for set := range sets {
95✔
108
                        // Fetch the feature vector for this set, allocating a
58✔
109
                        // new one if it doesn't exist.
58✔
110
                        fv, ok := fsets[set]
58✔
111
                        if !ok {
90✔
112
                                fv = lnwire.NewRawFeatureVector()
32✔
113
                        }
32✔
114

115
                        // Set the configured bit on the feature vector,
116
                        // ensuring that we don't set two feature bits for the
117
                        // same pair.
118
                        err := fv.SafeSet(bit)
58✔
119
                        if err != nil {
58✔
120
                                return nil, fmt.Errorf("unable to set "+
×
121
                                        "%v in %v: %v", bit, set, err)
×
122
                        }
×
123

124
                        // Write the updated feature vector under its set.
125
                        fsets[set] = fv
58✔
126
                }
127
        }
128

129
        // Now, remove any features as directed by the config.
130
        configFeatures := make(map[Set]*lnwire.FeatureVector)
16✔
131
        for set, raw := range fsets {
48✔
132
                if cfg.NoTLVOnion {
36✔
133
                        raw.Unset(lnwire.TLVOnionPayloadOptional)
4✔
134
                        raw.Unset(lnwire.TLVOnionPayloadRequired)
4✔
135
                        raw.Unset(lnwire.PaymentAddrOptional)
4✔
136
                        raw.Unset(lnwire.PaymentAddrRequired)
4✔
137
                        raw.Unset(lnwire.MPPOptional)
4✔
138
                        raw.Unset(lnwire.MPPRequired)
4✔
139
                        raw.Unset(lnwire.RouteBlindingOptional)
4✔
140
                        raw.Unset(lnwire.RouteBlindingRequired)
4✔
141
                        raw.Unset(lnwire.Bolt11BlindedPathsOptional)
4✔
142
                        raw.Unset(lnwire.Bolt11BlindedPathsRequired)
4✔
143
                        raw.Unset(lnwire.AMPOptional)
4✔
144
                        raw.Unset(lnwire.AMPRequired)
4✔
145
                        raw.Unset(lnwire.KeysendOptional)
4✔
146
                        raw.Unset(lnwire.KeysendRequired)
4✔
147
                }
4✔
148
                if cfg.NoStaticRemoteKey {
36✔
149
                        raw.Unset(lnwire.StaticRemoteKeyOptional)
4✔
150
                        raw.Unset(lnwire.StaticRemoteKeyRequired)
4✔
151
                }
4✔
152
                if cfg.NoAnchors {
34✔
153
                        raw.Unset(lnwire.AnchorsZeroFeeHtlcTxOptional)
2✔
154
                        raw.Unset(lnwire.AnchorsZeroFeeHtlcTxRequired)
2✔
155

2✔
156
                        // If anchors are disabled, then we also need to
2✔
157
                        // disable all other features that depend on it as
2✔
158
                        // well, as otherwise we may create an invalid feature
2✔
159
                        // bit set.
2✔
160
                        for bit, depFeatures := range deps {
28✔
161
                                for depFeature := range depFeatures {
58✔
162
                                        switch {
32✔
163
                                        case depFeature == lnwire.AnchorsZeroFeeHtlcTxRequired:
×
164
                                                fallthrough
×
165
                                        case depFeature == lnwire.AnchorsZeroFeeHtlcTxOptional:
4✔
166
                                                raw.Unset(bit)
4✔
167
                                        }
168
                                }
169
                        }
170
                }
171
                if cfg.NoWumbo {
32✔
UNCOV
172
                        raw.Unset(lnwire.WumboChannelsOptional)
×
UNCOV
173
                        raw.Unset(lnwire.WumboChannelsRequired)
×
UNCOV
174
                }
×
175
                if cfg.NoScriptEnforcementLease {
32✔
UNCOV
176
                        raw.Unset(lnwire.ScriptEnforcedLeaseOptional)
×
UNCOV
177
                        raw.Unset(lnwire.ScriptEnforcedLeaseRequired)
×
UNCOV
178
                }
×
179
                if cfg.NoKeysend {
32✔
180
                        raw.Unset(lnwire.KeysendOptional)
×
181
                        raw.Unset(lnwire.KeysendRequired)
×
182
                }
×
183
                if cfg.NoOptionScidAlias {
32✔
UNCOV
184
                        raw.Unset(lnwire.ScidAliasOptional)
×
UNCOV
185
                        raw.Unset(lnwire.ScidAliasRequired)
×
UNCOV
186
                }
×
187
                if cfg.NoZeroConf {
32✔
UNCOV
188
                        raw.Unset(lnwire.ZeroConfOptional)
×
UNCOV
189
                        raw.Unset(lnwire.ZeroConfRequired)
×
UNCOV
190
                }
×
191
                if cfg.NoAnySegwit {
32✔
UNCOV
192
                        raw.Unset(lnwire.ShutdownAnySegwitOptional)
×
UNCOV
193
                        raw.Unset(lnwire.ShutdownAnySegwitRequired)
×
UNCOV
194
                }
×
195
                if cfg.NoTaprootChans {
32✔
UNCOV
196
                        raw.Unset(lnwire.SimpleTaprootChannelsOptionalStaging)
×
UNCOV
197
                        raw.Unset(lnwire.SimpleTaprootChannelsRequiredStaging)
×
UNCOV
198
                }
×
199
                if cfg.NoRouteBlinding {
32✔
UNCOV
200
                        raw.Unset(lnwire.RouteBlindingOptional)
×
UNCOV
201
                        raw.Unset(lnwire.RouteBlindingRequired)
×
UNCOV
202
                        raw.Unset(lnwire.Bolt11BlindedPathsOptional)
×
UNCOV
203
                        raw.Unset(lnwire.Bolt11BlindedPathsRequired)
×
UNCOV
204
                }
×
205
                if cfg.NoQuiescence {
32✔
206
                        raw.Unset(lnwire.QuiescenceOptional)
×
207
                }
×
208
                if cfg.NoTaprootOverlay {
32✔
UNCOV
209
                        raw.Unset(lnwire.SimpleTaprootOverlayChansOptional)
×
UNCOV
210
                        raw.Unset(lnwire.SimpleTaprootOverlayChansRequired)
×
UNCOV
211
                }
×
212

213
                if cfg.NoExperimentalEndorsement {
32✔
UNCOV
214
                        raw.Unset(lnwire.ExperimentalEndorsementOptional)
×
UNCOV
215
                        raw.Unset(lnwire.ExperimentalEndorsementRequired)
×
UNCOV
216
                }
×
217

218
                for _, custom := range cfg.CustomFeatures[set] {
34✔
219
                        if custom > set.Maximum() {
2✔
220
                                return nil, fmt.Errorf("feature bit: %v "+
×
221
                                        "exceeds set: %v maximum: %v", custom,
×
222
                                        set, set.Maximum())
×
223
                        }
×
224

225
                        if raw.IsSet(custom) {
2✔
226
                                return nil, fmt.Errorf("feature bit: %v "+
×
227
                                        "already set", custom)
×
228
                        }
×
229

230
                        if err := raw.SafeSet(custom); err != nil {
2✔
231
                                return nil, fmt.Errorf("%w: could not set "+
×
232
                                        "feature: %d", err, custom)
×
233
                        }
×
234
                }
235

236
                // Track custom features separately so that we can check that
237
                // they aren't unset in subsequent updates. If there is no
238
                // entry for the set, the vector will just be empty.
239
                configFeatures[set] = lnwire.NewFeatureVector(
32✔
240
                        lnwire.NewRawFeatureVector(cfg.CustomFeatures[set]...),
32✔
241
                        lnwire.Features,
32✔
242
                )
32✔
243

32✔
244
                // Ensure that all of our feature sets properly set any
32✔
245
                // dependent features.
32✔
246
                fv := lnwire.NewFeatureVector(raw, lnwire.Features)
32✔
247
                err := ValidateDeps(fv)
32✔
248
                if err != nil {
32✔
249
                        return nil, fmt.Errorf("invalid feature set %v: %w",
×
250
                                set, err)
×
251
                }
×
252
        }
253

254
        return &Manager{
16✔
255
                fsets:          fsets,
16✔
256
                configFeatures: configFeatures,
16✔
257
        }, nil
16✔
258
}
259

260
// GetRaw returns a raw feature vector for the passed set. If no set is known,
261
// an empty raw feature vector is returned.
262
func (m *Manager) GetRaw(set Set) *lnwire.RawFeatureVector {
66✔
263
        if fv, ok := m.fsets[set]; ok {
110✔
264
                return fv.Clone()
44✔
265
        }
44✔
266

267
        return lnwire.NewRawFeatureVector()
22✔
268
}
269

270
// setRaw sets a new raw feature vector for the given set.
271
func (m *Manager) setRaw(set Set, raw *lnwire.RawFeatureVector) {
6✔
272
        m.fsets[set] = raw
6✔
273
}
6✔
274

275
// Get returns a feature vector for the passed set. If no set is known, an empty
276
// feature vector is returned.
277
func (m *Manager) Get(set Set) *lnwire.FeatureVector {
32✔
278
        raw := m.GetRaw(set)
32✔
279
        return lnwire.NewFeatureVector(raw, lnwire.Features)
32✔
280
}
32✔
281

282
// ListSets returns a list of the feature sets that our node supports.
UNCOV
283
func (m *Manager) ListSets() []Set {
×
UNCOV
284
        var sets []Set
×
UNCOV
285

×
UNCOV
286
        for set := range m.fsets {
×
UNCOV
287
                sets = append(sets, set)
×
UNCOV
288
        }
×
289

UNCOV
290
        return sets
×
291
}
292

293
// UpdateFeatureSets accepts a map of new feature vectors for each of the
294
// manager's known sets, validates that the update can be applied and modifies
295
// the feature manager's internal state. If a set is not included in the update
296
// map, it is left unchanged. The feature vectors provided are expected to
297
// include the current set of features, updated with desired bits added/removed.
298
func (m *Manager) UpdateFeatureSets(
299
        updates map[Set]*lnwire.RawFeatureVector) error {
7✔
300

7✔
301
        for set, newFeatures := range updates {
17✔
302
                if !set.valid() {
11✔
303
                        return fmt.Errorf("%w: set: %d", ErrUnknownSet, set)
1✔
304
                }
1✔
305

306
                if err := newFeatures.ValidatePairs(); err != nil {
11✔
307
                        return err
2✔
308
                }
2✔
309

310
                if err := m.Get(set).ValidateUpdate(
7✔
311
                        newFeatures, set.Maximum(),
7✔
312
                ); err != nil {
7✔
UNCOV
313
                        return err
×
UNCOV
314
                }
×
315

316
                // If any features were configured for this set, ensure that
317
                // they are still set in the new feature vector.
318
                if cfgFeat, haveCfgFeat := m.configFeatures[set]; haveCfgFeat {
12✔
319
                        for feature := range cfgFeat.Features() {
6✔
320
                                if !newFeatures.IsSet(feature) {
2✔
321
                                        return fmt.Errorf("%w: can't unset: "+
1✔
322
                                                "%d", ErrFeatureConfigured,
1✔
323
                                                feature)
1✔
324
                                }
1✔
325
                        }
326
                }
327

328
                fv := lnwire.NewFeatureVector(newFeatures, lnwire.Features)
6✔
329
                if err := ValidateDeps(fv); err != nil {
6✔
330
                        return err
×
331
                }
×
332
        }
333

334
        // Only update the current feature sets once every proposed set has
335
        // passed validation so that we don't partially update any sets then
336
        // fail out on a later set's validation.
337
        for set, features := range updates {
9✔
338
                m.setRaw(set, features.Clone())
6✔
339
        }
6✔
340

341
        return nil
3✔
342
}
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