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

lightningnetwork / lnd / 11216766535

07 Oct 2024 01:37PM UTC coverage: 57.817% (-1.0%) from 58.817%
11216766535

Pull #9148

github

ProofOfKeags
lnwire: remove kickoff feerate from propose/commit
Pull Request #9148: DynComms [2/n]: lnwire: add authenticated wire messages for Dyn*

571 of 879 new or added lines in 16 files covered. (64.96%)

23253 existing lines in 251 files now uncovered.

99022 of 171268 relevant lines covered (57.82%)

38420.67 hits per line

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

94.25
/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 {
18✔
35
        return ErrMissingFeatureDep{dep: dep}
18✔
36
}
18✔
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.RouteBlindingOptional: {
83
                lnwire.TLVOnionPayloadOptional: {},
84
        },
85
        lnwire.Bolt11BlindedPathsOptional: {
86
                lnwire.RouteBlindingOptional: {},
87
        },
88
}
89

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

98
        return validateDeps(features, supported)
99
}
2,667✔
100

2,667✔
101
// validateDeps is a subroutine that recursively checks that the passed features
2,667✔
102
// have all of their associated dependencies in the supported map.
2,667✔
103
func validateDeps(features featureSet, supported supportedFeatures) error {
2,667✔
104
        for bit := range features {
2,667✔
105
                // Convert any required bits to optional.
106
                bit = mapToOptional(bit)
107

108
                // If the supported features doesn't contain the dependency, this
109
                // vector is invalid.
110
                checked, ok := supported[bit]
111
                if !ok {
112
                        return NewErrMissingFeatureDep(bit)
112✔
113
                }
112✔
114

112✔
115
                // Alternatively, if we know that this dependency is valid, we
112✔
116
                // can short circuit and continue verifying other bits.
112✔
117
                if checked {
112✔
118
                        continue
112✔
119
                }
112✔
120

112✔
121
                // Recursively validate dependencies, since this method ranges
112✔
122
                // over the subDeps. This method will return true even if
112✔
123
                // subDeps is nil.
112✔
124
                subDeps := deps[bit]
170✔
125
                if err := validateDeps(subDeps, supported); err != nil {
58✔
126
                        return err
58✔
127
                }
58✔
128

58✔
129
                // Once we've confirmed that this feature's dependencies, if
58✔
130
                // any, are sound, we record this so other paths taken through
58✔
131
                // `bit` return early when inspecting the supported map.
87✔
132
                supported[bit] = true
29✔
133
        }
29✔
134

135
        return nil
58✔
136
}
137

138
// initSupported sets all bits from the feature vector as supported but not
139
// checked. This signals that the validity of their dependencies has not been
140
// verified. All required bits are mapped to optional to simplify the DAG.
141
func initSupported(features featureSet) supportedFeatures {
54✔
142
        supported := make(supportedFeatures)
54✔
143
        for bit := range features {
54✔
144
                bit = mapToOptional(bit)
54✔
145
                supported[bit] = false
79✔
146
        }
25✔
147

25✔
148
        return supported
25✔
149
}
25✔
150

25✔
151
// mapToOptional returns the optional variant of a given feature bit pair. Our
25✔
152
// dependency graph is described using only optional feature bits, which
25✔
153
// reduces the number of constraints we need to express in the descriptor.
25✔
154
func mapToOptional(bit lnwire.FeatureBit) lnwire.FeatureBit {
155
        if bit.IsRequired() {
54✔
156
                bit ^= 0x01
157
        }
158
        return bit
159
}
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