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

lightningnetwork / lnd / 12033440129

26 Nov 2024 03:03PM UTC coverage: 48.738% (-10.3%) from 58.999%
12033440129

Pull #9309

github

yyforyongyu
gomod: update `btcd` for shutdown fix
Pull Request #9309: chainntnfs: fix `TestHistoricalConfDetailsTxIndex`

97664 of 200385 relevant lines covered (48.74%)

0.52 hits per line

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

81.46
/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
        // NoTaprootOverlay unsets the taproot overlay channel feature bits.
67
        NoTaprootOverlay bool
68

69
        // NoExperimentalEndorsement unsets any bits that signal support for
70
        // forwarding experimental endorsement.
71
        NoExperimentalEndorsement bool
72

73
        // CustomFeatures is a set of custom features to advertise in each
74
        // set.
75
        CustomFeatures map[Set][]lnwire.FeatureBit
76
}
77

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

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

91
// NewManager creates a new feature Manager, applying any custom modifications
92
// to its feature sets before returning.
93
func NewManager(cfg Config) (*Manager, error) {
1✔
94
        return newManager(cfg, defaultSetDesc)
1✔
95
}
1✔
96

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

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

121
                        // Write the updated feature vector under its set.
122
                        fsets[set] = fv
1✔
123
                }
124
        }
125

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

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

207
                if cfg.NoExperimentalEndorsement {
2✔
208
                        raw.Unset(lnwire.ExperimentalEndorsementOptional)
1✔
209
                        raw.Unset(lnwire.ExperimentalEndorsementRequired)
1✔
210
                }
1✔
211

212
                for _, custom := range cfg.CustomFeatures[set] {
2✔
213
                        if custom > set.Maximum() {
1✔
214
                                return nil, fmt.Errorf("feature bit: %v "+
×
215
                                        "exceeds set: %v maximum: %v", custom,
×
216
                                        set, set.Maximum())
×
217
                        }
×
218

219
                        if raw.IsSet(custom) {
1✔
220
                                return nil, fmt.Errorf("feature bit: %v "+
×
221
                                        "already set", custom)
×
222
                        }
×
223

224
                        if err := raw.SafeSet(custom); err != nil {
1✔
225
                                return nil, fmt.Errorf("%w: could not set "+
×
226
                                        "feature: %d", err, custom)
×
227
                        }
×
228
                }
229

230
                // Track custom features separately so that we can check that
231
                // they aren't unset in subsequent updates. If there is no
232
                // entry for the set, the vector will just be empty.
233
                configFeatures[set] = lnwire.NewFeatureVector(
1✔
234
                        lnwire.NewRawFeatureVector(cfg.CustomFeatures[set]...),
1✔
235
                        lnwire.Features,
1✔
236
                )
1✔
237

1✔
238
                // Ensure that all of our feature sets properly set any
1✔
239
                // dependent features.
1✔
240
                fv := lnwire.NewFeatureVector(raw, lnwire.Features)
1✔
241
                err := ValidateDeps(fv)
1✔
242
                if err != nil {
1✔
243
                        return nil, fmt.Errorf("invalid feature set %v: %w",
×
244
                                set, err)
×
245
                }
×
246
        }
247

248
        return &Manager{
1✔
249
                fsets:          fsets,
1✔
250
                configFeatures: configFeatures,
1✔
251
        }, nil
1✔
252
}
253

254
// GetRaw returns a raw feature vector for the passed set. If no set is known,
255
// an empty raw feature vector is returned.
256
func (m *Manager) GetRaw(set Set) *lnwire.RawFeatureVector {
1✔
257
        if fv, ok := m.fsets[set]; ok {
2✔
258
                return fv.Clone()
1✔
259
        }
1✔
260

261
        return lnwire.NewRawFeatureVector()
×
262
}
263

264
// setRaw sets a new raw feature vector for the given set.
265
func (m *Manager) setRaw(set Set, raw *lnwire.RawFeatureVector) {
1✔
266
        m.fsets[set] = raw
1✔
267
}
1✔
268

269
// Get returns a feature vector for the passed set. If no set is known, an empty
270
// feature vector is returned.
271
func (m *Manager) Get(set Set) *lnwire.FeatureVector {
1✔
272
        raw := m.GetRaw(set)
1✔
273
        return lnwire.NewFeatureVector(raw, lnwire.Features)
1✔
274
}
1✔
275

276
// ListSets returns a list of the feature sets that our node supports.
277
func (m *Manager) ListSets() []Set {
1✔
278
        var sets []Set
1✔
279

1✔
280
        for set := range m.fsets {
2✔
281
                sets = append(sets, set)
1✔
282
        }
1✔
283

284
        return sets
1✔
285
}
286

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

1✔
295
        for set, newFeatures := range updates {
2✔
296
                if !set.valid() {
1✔
297
                        return fmt.Errorf("%w: set: %d", ErrUnknownSet, set)
×
298
                }
×
299

300
                if err := newFeatures.ValidatePairs(); err != nil {
1✔
301
                        return err
×
302
                }
×
303

304
                if err := m.Get(set).ValidateUpdate(
1✔
305
                        newFeatures, set.Maximum(),
1✔
306
                ); err != nil {
2✔
307
                        return err
1✔
308
                }
1✔
309

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

322
                fv := lnwire.NewFeatureVector(newFeatures, lnwire.Features)
1✔
323
                if err := ValidateDeps(fv); err != nil {
1✔
324
                        return err
×
325
                }
×
326
        }
327

328
        // Only update the current feature sets once every proposed set has
329
        // passed validation so that we don't partially update any sets then
330
        // fail out on a later set's validation.
331
        for set, features := range updates {
2✔
332
                m.setRaw(set, features.Clone())
1✔
333
        }
1✔
334

335
        return nil
1✔
336
}
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