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

lightningnetwork / lnd / 12199391122

06 Dec 2024 01:10PM UTC coverage: 49.807% (-9.1%) from 58.933%
12199391122

push

github

web-flow
Merge pull request #9337 from Guayaba221/patch-1

chore: fix typo in ruby.md

100137 of 201051 relevant lines covered (49.81%)

2.07 hits per line

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

74.71
/feature/deps.go
1
package feature
2

3
import (
4
        "fmt"
5

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

9
type (
10
        // featureSet contains a set of feature bits.
11
        featureSet map[lnwire.FeatureBit]struct{}
12

13
        // supportedFeatures maps the feature bit from a feature vector to a
14
        // boolean indicating if this features dependencies have already been
15
        // verified. This allows us to short circuit verification if multiple
16
        // features have common dependencies, or map traversal starts verifying
17
        // from the bottom up.
18
        supportedFeatures map[lnwire.FeatureBit]bool
19

20
        // depDesc maps a features to its set of dependent features, which must
21
        // also be present for the vector to be valid. This can be used to
22
        // recursively check the dependency chain for features in a feature
23
        // vector.
24
        depDesc map[lnwire.FeatureBit]featureSet
25
)
26

27
// ErrMissingFeatureDep is an error signaling that a transitive dependency in a
28
// feature vector is not set properly.
29
type ErrMissingFeatureDep struct {
30
        dep lnwire.FeatureBit
31
}
32

33
// NewErrMissingFeatureDep creates a new ErrMissingFeatureDep error.
34
func NewErrMissingFeatureDep(dep lnwire.FeatureBit) ErrMissingFeatureDep {
×
35
        return ErrMissingFeatureDep{dep: dep}
×
36
}
×
37

38
// Error returns a human-readable description of the missing dep error.
39
func (e ErrMissingFeatureDep) Error() string {
×
40
        return fmt.Sprintf("missing feature dependency: %v", e.dep)
×
41
}
×
42

43
// deps is the default set of dependencies for assigned feature bits. If a
44
// feature is not present in the depDesc it is assumed to have no dependencies.
45
//
46
// NOTE: For proper functioning, only the optional variant of feature bits
47
// should be used in the following descriptor. In the future it may be necessary
48
// to distinguish the dependencies for optional and required bits, but for now
49
// the validation code maps required bits to optional ones since it simplifies
50
// the number of constraints.
51
var deps = depDesc{
52
        lnwire.PaymentAddrOptional: {
53
                lnwire.TLVOnionPayloadOptional: {},
54
        },
55
        lnwire.MPPOptional: {
56
                lnwire.PaymentAddrOptional: {},
57
        },
58
        lnwire.AnchorsOptional: {
59
                lnwire.StaticRemoteKeyOptional: {},
60
        },
61
        lnwire.AnchorsZeroFeeHtlcTxOptional: {
62
                lnwire.StaticRemoteKeyOptional: {},
63
        },
64
        lnwire.AMPOptional: {
65
                lnwire.PaymentAddrOptional: {},
66
        },
67
        lnwire.ExplicitChannelTypeOptional: {},
68
        lnwire.ScriptEnforcedLeaseOptional: {
69
                lnwire.ExplicitChannelTypeOptional:  {},
70
                lnwire.AnchorsZeroFeeHtlcTxOptional: {},
71
        },
72
        lnwire.KeysendOptional: {
73
                lnwire.TLVOnionPayloadOptional: {},
74
        },
75
        lnwire.ZeroConfOptional: {
76
                lnwire.ScidAliasOptional: {},
77
        },
78
        lnwire.SimpleTaprootChannelsOptionalStaging: {
79
                lnwire.AnchorsZeroFeeHtlcTxOptional: {},
80
                lnwire.ExplicitChannelTypeOptional:  {},
81
        },
82
        lnwire.SimpleTaprootOverlayChansOptional: {
83
                lnwire.SimpleTaprootChannelsOptionalStaging: {},
84
                lnwire.TLVOnionPayloadOptional:              {},
85
                lnwire.ScidAliasOptional:                    {},
86
        },
87
        lnwire.RouteBlindingOptional: {
88
                lnwire.TLVOnionPayloadOptional: {},
89
        },
90
        lnwire.Bolt11BlindedPathsOptional: {
91
                lnwire.RouteBlindingOptional: {},
92
        },
93
}
94

95
// ValidateDeps asserts that a feature vector sets all features and their
96
// transitive dependencies properly. It assumes that the dependencies between
97
// optional and required features are identical, e.g. if a feature is required
98
// but its dependency is optional, that is sufficient.
99
func ValidateDeps(fv *lnwire.FeatureVector) error {
4✔
100
        features := fv.Features()
4✔
101
        supported := initSupported(features)
4✔
102

4✔
103
        return validateDeps(features, supported)
4✔
104
}
4✔
105

106
// SetBit sets the given feature bit on the given feature bit vector along with
107
// any of its dependencies. If the bit is required, then all the dependencies
108
// are also set to required, otherwise, the optional dependency bits are set.
109
// Existing bits are only upgraded from optional to required but never
110
// downgraded from required to optional.
111
func SetBit(vector *lnwire.FeatureVector,
112
        bit lnwire.FeatureBit) *lnwire.FeatureVector {
4✔
113

4✔
114
        fv := vector.Clone()
4✔
115

4✔
116
        // Get the optional version of the bit since that is what the deps map
4✔
117
        // uses.
4✔
118
        optBit := mapToOptional(bit)
4✔
119

4✔
120
        // If the bit we are setting is optional, then we set it (in its
4✔
121
        // optional form) and also set all its dependents as optional if they
4✔
122
        // are not already set (they may already be set in a required form in
4✔
123
        // which case they should not be overridden).
4✔
124
        if !bit.IsRequired() {
4✔
125
                // Set the bit itself if it does not already exist. We use
×
126
                // SafeSet here so that if the bit already exists in the
×
127
                // required form, then this is not overwritten.
×
128
                _ = fv.SafeSet(bit)
×
129

×
130
                // Do the same for all the dependent bits.
×
131
                for depBit := range deps[optBit] {
×
132
                        fv = SetBit(fv, depBit)
×
133
                }
×
134

135
                return fv
×
136
        }
137

138
        // The bit is required. In this case, we do want to override any
139
        // existing optional bit for both the bit itself and for the dependent
140
        // bits.
141
        fv.Unset(optBit)
4✔
142
        fv.Set(bit)
4✔
143

4✔
144
        // Do the same for all the dependent bits.
4✔
145
        for depBit := range deps[optBit] {
8✔
146
                // The deps map only contains the optional versions of bits, so
4✔
147
                // there is no need to first map the bit to the optional
4✔
148
                // version.
4✔
149
                fv.Unset(depBit)
4✔
150

4✔
151
                // Set the required version of the bit instead.
4✔
152
                fv = SetBit(fv, mapToRequired(depBit))
4✔
153
        }
4✔
154

155
        return fv
4✔
156
}
157

158
// validateDeps is a subroutine that recursively checks that the passed features
159
// have all of their associated dependencies in the supported map.
160
func validateDeps(features featureSet, supported supportedFeatures) error {
4✔
161
        for bit := range features {
8✔
162
                // Convert any required bits to optional.
4✔
163
                bit = mapToOptional(bit)
4✔
164

4✔
165
                // If the supported features doesn't contain the dependency, this
4✔
166
                // vector is invalid.
4✔
167
                checked, ok := supported[bit]
4✔
168
                if !ok {
4✔
169
                        return NewErrMissingFeatureDep(bit)
×
170
                }
×
171

172
                // Alternatively, if we know that this dependency is valid, we
173
                // can short circuit and continue verifying other bits.
174
                if checked {
8✔
175
                        continue
4✔
176
                }
177

178
                // Recursively validate dependencies, since this method ranges
179
                // over the subDeps. This method will return true even if
180
                // subDeps is nil.
181
                subDeps := deps[bit]
4✔
182
                if err := validateDeps(subDeps, supported); err != nil {
4✔
183
                        return err
×
184
                }
×
185

186
                // Once we've confirmed that this feature's dependencies, if
187
                // any, are sound, we record this so other paths taken through
188
                // `bit` return early when inspecting the supported map.
189
                supported[bit] = true
4✔
190
        }
191

192
        return nil
4✔
193
}
194

195
// initSupported sets all bits from the feature vector as supported but not
196
// checked. This signals that the validity of their dependencies has not been
197
// verified. All required bits are mapped to optional to simplify the DAG.
198
func initSupported(features featureSet) supportedFeatures {
4✔
199
        supported := make(supportedFeatures)
4✔
200
        for bit := range features {
8✔
201
                bit = mapToOptional(bit)
4✔
202
                supported[bit] = false
4✔
203
        }
4✔
204

205
        return supported
4✔
206
}
207

208
// mapToOptional returns the optional variant of a given feature bit pair. Our
209
// dependency graph is described using only optional feature bits, which
210
// reduces the number of constraints we need to express in the descriptor.
211
func mapToOptional(bit lnwire.FeatureBit) lnwire.FeatureBit {
4✔
212
        if bit.IsRequired() {
8✔
213
                bit ^= 0x01
4✔
214
        }
4✔
215
        return bit
4✔
216
}
217

218
// mapToRequired returns the required variant of a given feature bit pair.
219
func mapToRequired(bit lnwire.FeatureBit) lnwire.FeatureBit {
4✔
220
        if bit.IsRequired() {
4✔
221
                return bit
×
222
        }
×
223
        bit ^= 0x01
4✔
224

4✔
225
        return bit
4✔
226
}
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